70
179
TCocoaFontStyle = set of (cfs_Bold, cfs_Italic, cfs_Underline, cfs_Strikeout);
72
181
TCocoaFont = class(TCocoaGDIObject)
75
Style : TCocoaFontStyle;
186
FStyle: TCocoaFontStyle;
187
FAntialiased: Boolean;
189
constructor CreateDefault(AGlobal: Boolean = False);
190
constructor Create(const ALogFont: TLogFont; AFontName: String; AGlobal: Boolean = False); reintroduce; overload;
191
constructor Create(const AFont: NSFont; AGlobal: Boolean = False); overload;
192
class function CocoaFontWeightToWin32FontWeight(const CocoaFontWeight: Integer): Integer; static;
193
property Antialiased: Boolean read FAntialiased;
194
property Font: NSFont read FFont;
195
property Name: String read FName;
196
property Size: Integer read FSize;
197
property Style: TCocoaFontStyle read FStyle;
81
TCocoaBitmap = class(TCocoaGDIObject);
202
TCocoaBitmap = class(TCocoaGDIObject)
205
FAlignment: TCocoaBitmapAlignment;
208
FBytesPerRow: Integer;
213
FType: TCocoaBitmapType;
215
FbitsPerSample: NSInteger; // How many bits in each color component
216
FsamplesPerPixel: NSInteger;// How many color components
218
FImagerep: NSBitmapImageRep;
219
function GetColorSpace: NSString;
221
constructor Create(ABitmap: TCocoaBitmap);
222
constructor Create(AWidth, AHeight, ADepth, ABitsPerPixel: Integer;
223
AAlignment: TCocoaBitmapAlignment; AType: TCocoaBitmapType;
224
AData: Pointer; ACopyData: Boolean = True);
225
destructor Destroy; override;
226
procedure SetInfo(AWidth, AHeight, ADepth, ABitsPerPixel: Integer;
227
AAlignment: TCocoaBitmapAlignment; AType: TCocoaBitmapType);
229
function CreateSubImage(const ARect: TRect): CGImageRef;
231
property BitmapType: TCocoaBitmapType read FType;
232
property BitsPerPixel: Byte read FBitsPerPixel;
233
property BitsPerSample: NSInteger read FBitsPerSample;
234
property BytesPerRow: Integer read FBytesPerRow;
235
property Image: NSImage read FImage;
236
property ImageRep: NSBitmapImageRep read FImageRep;
237
property ColorSpace: NSString read GetColorSpace;
238
property Data: Pointer read FData;
239
property DataSize: Integer read FDataSize;
240
property Depth: Byte read FDepth;
241
property Width: Integer read FWidth;
242
property Height: Integer read FHeight;
247
TCocoaCursor = class(TObject)
250
FBitmap: TCocoaBitmap;
253
constructor CreateStandard(const ACursor: NSCursor);
254
constructor CreateFromBitmap(const ABitmap: TCocoaBitmap; const hotSpot: NSPoint);
255
destructor Destroy; override;
256
function Install: TCocoaCursor;
257
property Cursor: NSCursor read FCursor;
258
property Standard: Boolean read FStandard;
262
// device context data for SaveDC/RestoreDC
265
CurrentFont: TCocoaFont;
266
CurrentBrush: TCocoaBrush;
267
CurrentPen: TCocoaPen;
268
CurrentRegion: TCocoaRegion;
272
BkBrush: TCocoaBrush;
280
TGlyphArray = array of NSGlyph;
83
282
{ TCocoaTextLayout }
85
TCocoaTextLayout = class(TObject)
284
TCocoaTextLayout = class
286
FBackgroundColor: TColor;
287
FForegroundColor: TColor;
288
FLayout: NSLayoutManager;
289
FTextStorage: NSTextStorage;
290
FTextContainer: NSTextContainer;
293
procedure SetBackgoundColor(AValue: TColor);
294
procedure SetForegoundColor(AValue: TColor);
295
procedure SetFont(AFont: TCocoaFont);
296
procedure UpdateFont;
297
procedure UpdateColor;
298
function GetTextRange: NSRange;
87
constructor Create; virtual;
88
procedure SetFont(AFont: TCocoaFont); virtual; abstract;
89
procedure SetText(UTF8Text: PChar; ByteSize: Integer); virtual; abstract;
90
function GetSize: TSize; virtual; abstract;
301
destructor Destroy; override;
302
procedure SetText(UTF8Text: PChar; ByteSize: Integer);
303
function GetSize: TSize;
304
function GetGlyphs: TGlyphArray;
305
procedure Draw(ctx: NSGraphicsContext; X, Y: Integer; FillBackground: Boolean; DX: PInteger);
92
procedure Draw(cg: CGContextRef; X, Y: Integer; DX: PInteger); virtual; abstract;
307
property Font: TCocoaFont read FFont write SetFont;
308
property BackgroundColor: TColor read FBackgroundColor write SetBackgoundColor;
309
property ForegroundColor: TColor read FForegroundColor write SetForegoundColor;
94
TCocoaTextLayoutClass = class of TCocoaTextLayout;
98
314
TCocoaContext = class(TObject)
100
fText : TCocoaTextLayout;
101
fBrush : TCocoaBrush;
104
fRegion : TCocoaRegion;
105
fBitmap : TCocoaBitmap;
316
FBkBrush: TCocoaBrush;
320
FText : TCocoaTextLayout;
321
FBrush : TCocoaBrush;
323
FRegion : TCocoaRegion;
324
FBitmap : TCocoaBitmap;
326
FClipRegion: TCocoaRegion;
327
FSavedDCList: TFPObjectList;
330
function GetFont: TCocoaFont;
331
function GetTextColor: TColor;
106
332
procedure SetBitmap(const AValue: TCocoaBitmap);
333
procedure SetBkColor(AValue: TColor);
334
procedure SetBkMode(AValue: Integer);
107
335
procedure SetBrush(const AValue: TCocoaBrush);
108
336
procedure SetFont(const AValue: TCocoaFont);
109
337
procedure SetPen(const AValue: TCocoaPen);
110
338
procedure SetRegion(const AValue: TCocoaRegion);
339
procedure SetROP2(AValue: Integer);
340
procedure SetTextColor(AValue: TColor);
342
function SaveDCData: TCocoaDCData; virtual;
343
procedure RestoreDCData(const AData: TCocoaDCData); virtual;
344
procedure SetCGFillping(Ctx: CGContextRef; Width, Height: Integer);
345
procedure RestoreCGFillping(Ctx: CGContextRef; Width, Height: Integer);
114
ctx : NSGraphicsContext;
347
ctx: NSGraphicsContext;
118
348
constructor Create;
119
349
destructor Destroy; override;
351
function SaveDC: Integer;
352
function RestoreDC(ASavedDC: Integer): Boolean;
120
354
function InitDraw(width, height: Integer): Boolean;
121
procedure MoveTo(x,y: Integer);
122
procedure LineTo(x,y: Integer);
357
procedure DrawBitmap(X, Y: Integer; ABitmap: TCocoaBitmap);
358
procedure DrawFocusRect(ARect: TRect);
359
procedure InvertRectangle(X1, Y1, X2, Y2: Integer);
360
procedure MoveTo(X, Y: Integer);
361
procedure LineTo(X, Y: Integer);
123
362
procedure Polygon(const Points: array of TPoint; NumPts: Integer; Winding: boolean);
124
363
procedure Polyline(const Points: array of TPoint; NumPts: Integer);
125
364
procedure Rectangle(X1, Y1, X2, Y2: Integer; FillRect: Boolean; UseBrush: TCocoaBrush);
126
365
procedure Ellipse(X1, Y1, X2, Y2: Integer);
127
procedure TextOut(X,Y: Integer; UTF8Chars: PChar; Count: Integer; CharsDelta: PInteger);
128
procedure SetOrigin(X,Y: Integer);
366
procedure TextOut(X, Y: Integer; Options: Longint; Rect: PRect; UTF8Chars: PChar; Count: Integer; CharsDelta: PInteger);
367
procedure Frame(const R: TRect);
368
procedure Frame3d(var ARect: TRect; const FrameWidth: integer; const Style: TBevelCut);
369
procedure FrameRect(const ARect: TRect; const ABrush: TCocoaBrush);
370
function DrawCGImage(X, Y, Width, Height: Integer; CGImage: CGImageRef): Boolean;
371
function StretchDraw(X, Y, Width, Height: Integer; SrcDC: TCocoaContext;
372
XSrc, YSrc, SrcWidth, SrcHeight: Integer; Msk: TCocoaBitmap; XMsk,
373
YMsk: Integer; Rop: DWORD): Boolean;
375
function GetTextExtentPoint(AStr: PChar; ACount: Integer; var Size: TSize): Boolean;
376
function GetTextMetrics(var TM: TTextMetric): Boolean;
377
procedure SetOrigin(X, Y: Integer);
129
378
procedure GetOrigin(var X,Y: Integer);
130
380
function CGContext: CGContextRef; virtual;
131
property Brush: TCocoaBrush read fBrush write SetBrush;
132
property Pen: TCocoaPen read fPen write SetPen;
133
property Font: TCocoaFont read fFont write SetFont;
134
property Region: TCocoaRegion read fRegion write SetRegion;
135
property Bitmap: TCocoaBitmap read fBitmap write SetBitmap;
381
procedure SetAntialiasing(AValue: Boolean);
383
function GetClipRect: TRect;
384
function SetClipRegion(AClipRegion: TCocoaRegion; Mode: TCocoaCombine): TCocoaRegionType;
385
function CopyClipRegion(ADstRegion: TCocoaRegion): TCocoaRegionType;
387
property Clipped: Boolean read FClipped;
388
property PenPos: TPoint read FPenPos write FPenPos;
389
property ROP2: Integer read FROP2 write SetROP2;
390
property Size: TSize read FSize;
392
property BkColor: TColor read FBkColor write SetBkColor;
393
property BkMode: Integer read FBkMode write SetBkMode;
394
property BkBrush: TCocoaBrush read FBkBrush;
396
property TextColor: TColor read GetTextColor write SetTextColor;
398
// selected GDI objects
399
property Brush: TCocoaBrush read FBrush write SetBrush;
400
property Pen: TCocoaPen read FPen write SetPen;
401
property Font: TCocoaFont read GetFont write SetFont;
402
property Region: TCocoaRegion read FRegion write SetRegion;
403
property Bitmap: TCocoaBitmap read FBitmap write SetBitmap;
139
TextLayoutClass : TCocoaTextLayoutClass = nil;
407
DefaultBrush: TCocoaBrush;
408
DefaultPen: TCocoaPen;
409
DefaultFont: TCocoaFont;
411
function CheckDC(dc: HDC): TCocoaContext;
412
function CheckDC(dc: HDC; Str: string): Boolean;
413
function CheckGDIOBJ(obj: HGDIOBJ): TCocoaGDIObject;
414
function CheckBitmap(ABitmap: HBITMAP; AStr: string): Boolean;
421
//todo: a better check!
423
function CheckDC(dc: HDC): TCocoaContext;
425
Result := TCocoaContext(dc);
428
function CheckDC(dc: HDC; Str: string): Boolean;
433
function CheckGDIOBJ(obj: HGDIOBJ): TCocoaGDIObject;
435
Result := TCocoaGDIObject(obj);
438
function CheckBitmap(ABitmap: HBITMAP; AStr: string): Boolean;
440
Result := ABitmap <> 0;
446
// The following dummy categories fix bugs in the Cocoa bindings available in FPC
447
// Remove them when the FPC binding parser is fixed.
449
// http://wiki.freepascal.org/FPC_PasCocoa/Differences#Sending_messages_to_id
450
// http://wiki.lazarus.freepascal.org/FPC_PasCocoa#Category_declaration
451
NSBitmapImageRepFix = objccategory external(NSBitmapImageRep)
452
function initWithBitmapDataPlanes_pixelsWide_pixelsHigh__colorSpaceName_bytesPerRow_bitsPerPixel(planes: PPByte; width: NSInteger; height: NSInteger; bps: NSInteger; spp: NSInteger; alpha: Boolean; isPlanar_: Boolean; colorSpaceName_: NSString; rBytes: NSInteger; pBits: NSInteger): id; message 'initWithBitmapDataPlanes:pixelsWide:pixelsHigh:bitsPerSample:samplesPerPixel:hasAlpha:isPlanar:colorSpaceName:bytesPerRow:bitsPerPixel:';
453
function initWithBitmapDataPlanes_pixelsWide_pixelsHigh__colorSpaceName_bitmapFormat_bytesPerRow_bitsPerPixel(planes: PPByte; width: NSInteger; height: NSInteger; bps: NSInteger; spp: NSInteger; alpha: Boolean; isPlanar_: Boolean; colorSpaceName_: NSString; bitmapFormat_: NSBitmapFormat; rBytes: NSInteger; pBits: NSInteger): id; message 'initWithBitmapDataPlanes:pixelsWide:pixelsHigh:bitsPerSample:samplesPerPixel:hasAlpha:isPlanar:colorSpaceName:bitmapFormat:bytesPerRow:bitsPerPixel:';
456
NSGraphicsContextFix = objccategory external(NSGraphicsContext)
457
procedure setImageInterpolation(interpolation: NSImageInterpolation); message 'setImageInterpolation:';
458
procedure setShouldAntialias(antialias: Boolean); message 'setShouldAntialias:';
463
constructor TCocoaFont.CreateDefault(AGlobal: Boolean = False);
465
Create(NSFont.systemFontOfSize(0));
468
constructor TCocoaFont.Create(const ALogFont: TLogFont; AFontName: String; AGlobal: Boolean);
471
Descriptor: NSFontDescriptor;
472
Attributes: NSDictionary;
473
Pool: NSAutoreleasePool;
474
Win32Weight, LoopCount: Integer;
475
CocoaWeight: NSInteger;
477
inherited Create(AGlobal);
479
Pool := NSAutoreleasePool.alloc.init;
482
if FName = 'default' then
484
FName := NSStringToString(NSFont.systemFontOfSize(0).familyName);
485
FSize := Round(NSFont.systemFontSize);
488
FSize := ALogFont.lfHeight;
490
// create font attributes
491
Win32Weight := ALogFont.lfWeight;
493
if ALogFont.lfItalic > 0 then
494
include(FStyle, cfs_Italic);
495
if Win32Weight > FW_NORMAL then
496
include(FStyle, cfs_Bold);
497
if ALogFont.lfUnderline > 0 then
498
include(FStyle, cfs_Underline);
499
if ALogFont.lfStrikeOut > 0 then
500
include(FStyle, cfs_StrikeOut);
502
Attributes := NSDictionary.dictionaryWithObjectsAndKeys(
503
NSStringUTF8(FName), NSFontFamilyAttribute,
504
NSNumber.numberWithFloat(ALogFont.lfHeight), NSFontSizeAttribute,
507
Descriptor := NSFontDescriptor.fontDescriptorWithFontAttributes(Attributes);
508
FFont := NSFont.fontWithDescriptor_textTransform(Descriptor, nil);
509
// we could use NSFontTraitsAttribute to request the desired font style (Bold/Italic)
510
// but in this case we may get NIL as result. This way is safer.
511
if cfs_Italic in Style then
512
FFont := NSFontManager.sharedFontManager.convertFont_toHaveTrait(FFont, NSItalicFontMask);
513
if cfs_Bold in Style then
514
FFont := NSFontManager.sharedFontManager.convertFont_toHaveTrait(FFont, NSBoldFontMask);
515
case ALogFont.lfPitchAndFamily and $F of
516
FIXED_PITCH, MONO_FONT:
517
FFont := NSFontManager.sharedFontManager.convertFont_toHaveTrait(FFont, NSFixedPitchFontMask);
519
FFont := NSFontManager.sharedFontManager.convertFont_toNotHaveTrait(FFont, NSFixedPitchFontMask);
521
if Win32Weight <> FW_DONTCARE then
523
// currently if we request the desired waight by Attributes we may get a nil font
524
// so we need to get font weight and to convert it to lighter/havier
527
// protection from endless loop
528
if LoopCount > 12 then
530
CocoaWeight := CocoaFontWeightToWin32FontWeight(NSFontManager.sharedFontManager.weightOfFont(FFont));
531
if CocoaWeight < Win32Weight then
532
FFont := NSFontManager.sharedFontManager.convertWeight_ofFont(True, FFont)
534
if CocoaWeight > Win32Weight then
535
FFont := NSFontManager.sharedFontManager.convertWeight_ofFont(False, FFont);
537
until CocoaWeight = Win32Weight;
540
FAntialiased := ALogFont.lfQuality <> NONANTIALIASED_QUALITY;
544
constructor TCocoaFont.Create(const AFont: NSFont; AGlobal: Boolean);
546
inherited Create(AGlobal);
548
FName := NSStringToString(FFont.familyName);
549
FSize := Round(FFont.pointSize);
551
FAntialiased := True;
554
class function TCocoaFont.CocoaFontWeightToWin32FontWeight(const CocoaFontWeight: Integer): Integer; static;
556
case CocoaFontWeight of
557
0, 1: Result := FW_THIN;
558
2: Result := FW_ULTRALIGHT;
559
3: Result := FW_EXTRALIGHT;
560
4: Result := FW_LIGHT;
561
5: Result := FW_NORMAL;
562
6: Result := FW_MEDIUM;
563
7, 8: Result := FW_SEMIBOLD;
564
9: Result := FW_BOLD;
565
10: Result := FW_EXTRABOLD;
571
{ TCocoaColorObject }
573
function TCocoaColorObject.GetColorRef: TColorRef;
575
Result := TColorRef(RGBToColor(FR, FG, FB));
578
constructor TCocoaColorObject.Create(const AColor: TColor; ASolid, AGlobal: Boolean);
580
inherited Create(AGlobal);
582
SetColor(AColor, ASolid);
585
procedure TCocoaColorObject.SetColor(const AColor: TColor; ASolid: Boolean);
587
RedGreenBlue(ColorToRGB(AColor), FR, FG, FB);
591
procedure TCocoaColorObject.GetRGBA(AROP2: Integer; out AR, AG, AB, AA: Single);
624
AR := (255 - FR) / 255;
625
AG := (255 - FG) / 255;
626
AB := (255 - FB) / 255;
639
function TCocoaColorObject.CreateNSColor: NSColor;
641
Result := NSColor.colorWithCalibratedRed_green_blue_alpha(FR / 255, FG / 255, FB / 255, Byte(FA));
644
{------------------------------------------------------------------------------
645
Method: TCocoaBitmap.Create
646
Params: AWidth - Bitmap width
647
AHeight - Bitmap height
648
ADepth - Significant bits per pixel
649
ABitsPerPixel - The number of allocated bits per pixel (can be larger than depth)
650
// AAlignment - Alignment of the data for each row
651
// ABytesPerRow - The number of bytes between rows
652
ACopyData - Copy supplied bitmap data (OPTIONAL)
654
Creates Cocoa bitmap with the specified characteristics
655
------------------------------------------------------------------------------}
656
constructor TCocoaBitmap.Create(AWidth, AHeight, ADepth, ABitsPerPixel: Integer;
657
AAlignment: TCocoaBitmapAlignment; AType: TCocoaBitmapType;
658
AData: Pointer; ACopyData: Boolean);
661
BitmapFormat: NSBitmapFormat;
663
inherited Create(False);
664
{$ifdef VerboseBitmaps}
665
DebugLn(Format('[TCocoaBitmap.Create] AWidth=%d AHeight=%d ADepth=%d ABitsPerPixel=%d'
666
+ ' AAlignment=%d AType=%d AData=? ACopyData=%d',
667
[AWidth, AHeight, ADepth, ABitsPerPixel, Integer(AAlignment), Integer(AType), Integer(ACopyData)]));
669
SetInfo(AWidth, AHeight, ADepth, ABitsPerPixel, AAlignment, AType);
671
// Copy the image data, if necessary
672
if (AData = nil) or ACopyData then
674
System.GetMem(FData, FDataSize);
677
System.Move(AData^, FData^, FDataSize) // copy data
679
FillDWord(FData^, FDataSize shr 2, 0); // clear bitmap
687
HasAlpha := AType in [cbtARGB, cbtRGBA, cbtBGRA];
688
BitmapFormat := NSAlphaNonpremultipliedBitmapFormat;
689
if AType = cbtARGB then
690
BitmapFormat := BitmapFormat or NSAlphaFirstBitmapFormat;
692
{$ifdef VerboseBitmaps}
693
DebugLn(Format('[TCocoaBitmap.Create] NSBitmapImageRep.alloc HasAlpha=%d',
694
[Integer(HasAlpha)]));
696
// Create the associated NSImageRep
697
FImagerep := NSBitmapImageRep(NSBitmapImageRep.alloc.initWithBitmapDataPlanes_pixelsWide_pixelsHigh__colorSpaceName_bitmapFormat_bytesPerRow_bitsPerPixel(
698
@FData, // planes, BitmapDataPlanes
699
FWidth, // width, pixelsWide
700
FHeight,// height, PixelsHigh
701
FbitsPerSample,// bitsPerSample, bps
702
FsamplesPerPixel, // samplesPerPixel, sps
703
HasAlpha, // hasAlpha
705
GetColorSpace, // colorSpaceName
706
BitmapFormat, // bitmapFormat
707
FBytesPerRow, // bytesPerRow
708
FBitsPerPixel //bitsPerPixel
711
// Create the associated NSImage
712
FImage := NSImage.alloc.initWithSize(NSMakeSize(AWidth, AHeight));
713
Image.addRepresentation(Imagerep);
716
destructor TCocoaBitmap.Destroy;
719
if FFreeData then System.FreeMem(FData);
724
procedure TCocoaBitmap.SetInfo(AWidth, AHeight, ADepth,
725
ABitsPerPixel: Integer; AAlignment: TCocoaBitmapAlignment;
726
AType: TCocoaBitmapType);
728
ALIGNBITS: array[TCocoaBitmapAlignment] of Integer = (0, 1, 3, 7, $F);
732
if AWidth < 1 then AWidth := 1;
733
if AHeight < 1 then AHeight := 1;
737
FBitsPerPixel := ABitsPerPixel;
739
FAlignment := AAlignment;
741
if (FType in [cbtMono, cbtGray]) and (FDepth=0) then
742
FDepth:=FBitsPerPixel;
744
FBytesPerRow := ((AWidth * ABitsPerPixel) + 7) shr 3;
745
M := FBytesPerRow and ALIGNBITS[AAlignment];
746
if M <> 0 then Inc(FBytesPerRow, ALIGNBITS[AAlignment] + 1 - M);
748
FDataSize := FBytesPerRow * FHeight;
751
case ABitsPerPixel of
752
// Strangely, this might appear
756
FsamplesPerPixel := 0;
762
FsamplesPerPixel := 1;
768
FsamplesPerPixel := 1;
774
FsamplesPerPixel := 4;
778
FbitsPerSample := ABitsPerPixel div 3;
779
FsamplesPerPixel := 3;
783
function TCocoaBitmap.CreateSubImage(const ARect: TRect): CGImageRef;
785
if ImageRep = nil then
788
Result := CGImageCreateWithImageInRect(ImageRep.CGImage, RectToCGRect(ARect));
791
function TCocoaBitmap.GetColorSpace: NSString;
793
if FType in [cbtMono, cbtGray] then
794
Result := NSCalibratedWhiteColorSpace
796
Result := NSCalibratedRGBColorSpace;
799
constructor TCocoaBitmap.Create(ABitmap: TCocoaBitmap);
801
Create(ABitmap.Width, ABitmap.Height, ABitmap.Depth, ABitmap.FBitsPerPixel,
802
ABitmap.FAlignment, ABitmap.FType, ABitmap.Data);
806
constructor TCocoaCursor.CreateStandard(const ACursor: NSCursor);
813
constructor TCocoaCursor.CreateFromBitmap(const ABitmap: TCocoaBitmap; const hotSpot: NSPoint);
816
FCursor := NSCursor.alloc.initWithImage_hotSpot(ABitmap.Image, hotSpot);
820
destructor TCocoaCursor.Destroy;
828
function TCocoaCursor.Install: TCocoaCursor;
831
// also request form cursors invalidation
832
CocoaWidgetSet.NSApp.keyWindow.resetCursorRects;
838
procedure TCocoaTextLayout.UpdateFont;
840
UnderlineStyle = NSUnderlineStyleSingle or NSUnderlinePatternSolid;
844
if Assigned(FFont) then
846
Range := GetTextRange;
848
FTextStorage.addAttribute_value_range(NSFontAttributeName, FFont.Font, Range);
849
// aply font attributes which are not in NSFont
850
if cfs_Underline in FFont.Style then
851
FTextStorage.addAttribute_value_range(NSUnderlineStyleAttributeName, NSNumber.numberWithInteger(UnderlineStyle), Range);
852
if cfs_Strikeout in FFont.Style then
853
FTextStorage.addAttribute_value_range(NSStrikethroughStyleAttributeName, NSNumber.numberWithInteger(UnderlineStyle), Range);
857
procedure TCocoaTextLayout.UpdateColor;
859
FTextStorage.addAttribute_value_range(NSForegroundColorAttributeName, ColorToNSColor(ForegroundColor), GetTextRange);
860
FTextStorage.addAttribute_value_range(NSBackgroundColorAttributeName, ColorToNSColor(BackgroundColor), GetTextRange);
863
function TCocoaTextLayout.GetTextRange: NSRange;
865
Result.location := 0;
866
Result.length := FTextStorage.length;
869
procedure TCocoaTextLayout.SetForegoundColor(AValue: TColor);
871
if FForegroundColor <> AValue then
873
FForegroundColor := AValue;
874
FTextStorage.beginEditing;
876
FTextStorage.endEditing;
880
procedure TCocoaTextLayout.SetBackgoundColor(AValue: TColor);
882
if FBackgroundColor <> AValue then
884
FBackgroundColor := AValue;
885
FTextStorage.beginEditing;
887
FTextStorage.endEditing;
891
constructor TCocoaTextLayout.Create;
895
FLayout := NSLayoutManager.alloc.init;
896
FTextContainer := NSTextContainer.alloc.init;
897
FTextContainer.setLineFragmentPadding(0);
898
FLayout.addTextContainer(FTextContainer);
899
FTextContainer.release;
901
FTextStorage := NSTextStorage.alloc.initWithString(S);
903
FTextStorage.addLayoutManager(FLayout);
905
FFont := DefaultFont;
908
FBackgroundColor := clWhite;
909
FForegroundColor := clBlack;
912
destructor TCocoaTextLayout.Destroy;
914
FTextStorage.release;
919
procedure TCocoaTextLayout.SetFont(AFont: TCocoaFont);
921
if FFont <> AFont then
924
FTextStorage.beginEditing;
926
FTextStorage.endEditing;
930
procedure TCocoaTextLayout.SetText(UTF8Text: PChar; ByteSize: Integer);
935
if ByteSize >= 0 then
936
System.SetString(NewText, UTF8Text, ByteSize)
938
NewText := StrPas(UTF8Text);
939
if FText <> NewText then
942
S := NSStringUTF8(NewText);
943
FTextStorage.beginEditing;
944
FTextStorage.replaceCharactersInRange_withString(GetTextRange, S);
947
FTextStorage.endEditing;
952
function TCocoaTextLayout.GetSize: TSize;
956
Range := FLayout.glyphRangeForTextContainer(FTextContainer);
957
with FLayout.boundingRectForGlyphRange_inTextContainer(Range, FTextContainer).size do
959
Result.cx := Round(width);
960
Result.cy := Round(height);
964
function TCocoaTextLayout.GetGlyphs: TGlyphArray;
968
Range := FLayout.glyphRangeForTextContainer(FTextContainer);
969
// required length + 1 space
970
SetLength(Result, Range.length + 1);
971
FLayout.getGlyphs_range(@Result[0], Range);
972
SetLength(Result, Range.length);
975
procedure TCocoaTextLayout.Draw(ctx: NSGraphicsContext; X, Y: Integer; FillBackground: Boolean; DX: PInteger);
979
Context: NSGraphicsContext;
980
Locations: array of NSPoint;
981
Indexes: array of NSUInteger;
982
I, Count: NSUInteger;
984
if not ctx.isFlipped then
985
Context := NSGraphicsContext.graphicsContextWithGraphicsPort_flipped(ctx.graphicsPort, True)
989
ctx.setCurrentContext(Context);
990
ctx.setShouldAntialias(FFont.Antialiased);
991
Range := FLayout.glyphRangeForTextContainer(FTextContainer);
996
Count := Range.length;
997
SetLength(Locations, Count);
998
SetLength(Indexes, Count);
999
Locations[0] := FLayout.locationForGlyphAtIndex(0);
1001
for I := 1 to Count - 1 do
1003
Locations[I] := Locations[I - 1];
1004
Locations[I].x := Locations[I].x + DX[I - 1];
1007
FLayout.setLocations_startingGlyphIndexes_count_forGlyphRange(@Locations[0], @Indexes[0], Count, Range);
1009
if FillBackground then
1010
FLayout.drawBackgroundForGlyphRange_atPoint(Range, Pt);
1011
FLayout.drawGlyphsForGlyphRange_atPoint(Range, Pt);
143
1014
{ TCocoaContext }
145
function TCocoaContext.CGContext:CGContextRef;
147
Result:=CGContextRef(ctx.graphicsPort);
1016
function TCocoaContext.CGContext: CGContextRef;
1018
Result := CGContextRef(ctx.graphicsPort);
1021
procedure TCocoaContext.SetAntialiasing(AValue: Boolean);
1024
ctx.setImageInterpolation(NSImageInterpolationNone)
1026
ctx.setImageInterpolation(NSImageInterpolationDefault);
1027
ctx.setShouldAntialias(AValue);
1030
function TCocoaContext.GetClipRect: TRect;
1032
Result := CGRectToRect(CGContextGetClipBoundingBox(CGContext));
1035
function TCocoaContext.SetClipRegion(AClipRegion: TCocoaRegion; Mode: TCocoaCombine): TCocoaRegionType;
1040
ctx.restoreGraphicsState;
1043
if not Assigned(AClipRegion) then
1047
ctx.saveGraphicsState;
1048
FClipRegion.CombineWith(AClipRegion, Mode);
1049
FClipRegion.Apply(Self);
1052
Result := FClipRegion.GetType;
1055
function TCocoaContext.CopyClipRegion(ADstRegion: TCocoaRegion): TCocoaRegionType;
1057
if Assigned(ADstRegion) and ADstRegion.CombineWith(FClipRegion, cc_Copy) then
1058
Result := ADstRegion.GetType
1060
Result := crt_Error;
150
1063
procedure TCocoaContext.SetBitmap(const AValue: TCocoaBitmap);
1065
if FBitmap <> AValue then
1072
function TCocoaContext.GetTextColor: TColor;
1074
Result := FText.ForegroundColor;
1077
function TCocoaContext.GetFont: TCocoaFont;
1079
Result := FText.Font;
1082
procedure TCocoaContext.SetBkColor(AValue: TColor);
1084
AValue := ColorToRGB(AValue);
1086
FBkBrush.SetColor(AValue, BkMode = OPAQUE);
1089
procedure TCocoaContext.SetBkMode(AValue: Integer);
1091
if FBkMode <> AValue then
1094
FBkBrush.SetColor(FBkColor, FBkMode = OPAQUE);
155
1098
procedure TCocoaContext.SetBrush(const AValue: TCocoaBrush);
158
if Assigned(fBrush) then fBrush.Apply(CGContext);
1100
if FBrush <> AValue then
1103
if Assigned(FBrush) then FBrush.Apply(Self);
161
1107
procedure TCocoaContext.SetFont(const AValue: TCocoaFont);
1109
FText.Font := AValue;
166
1112
procedure TCocoaContext.SetPen(const AValue: TCocoaPen);
169
if Assigned(fPen) then fPen.Apply(CGContext);
1114
if FPen <> AValue then
1117
if Assigned(FPen) then FPen.Apply(Self);
172
1121
procedure TCocoaContext.SetRegion(const AValue: TCocoaRegion);
1123
if FRegion <> AValue then
1126
if Assigned(FRegion) then FRegion.Apply(Self);
1130
procedure TCocoaContext.SetROP2(AValue: Integer);
1132
if FROP2 <> AValue then
1140
procedure TCocoaContext.SetTextColor(AValue: TColor);
1142
FText.ForegroundColor := TColor(ColorToRGB(AValue));
1145
function TCocoaContext.SaveDCData: TCocoaDCData;
1147
Result := TCocoaDCData.Create;
1149
Result.CurrentFont := Font;
1150
Result.CurrentBrush := FBrush;
1151
Result.CurrentPen := FPen;
1152
Result.CurrentRegion := FRegion;
1154
Result.BkColor := FBkColor;
1155
Result.BkMode := FBkMode;
1156
Result.BkBrush := FBkBrush;
1158
Result.TextColor := TextColor;
1160
Result.ROP2 := FROP2;
1161
Result.PenPos := FPenPos;
1164
procedure TCocoaContext.RestoreDCData(const AData: TCocoaDCData);
1166
if (Font <> AData.CurrentFont) then
1168
if Assigned(Font) then
1170
if Assigned(AData.CurrentFont) then
1171
AData.CurrentFont.AddRef;
1173
Font := AData.CurrentFont;
1175
if (FBrush <> AData.CurrentBrush) then
1177
if Assigned(FBrush) then
1179
if Assigned(AData.CurrentBrush) then
1180
AData.CurrentBrush.AddRef;
1182
FBrush := AData.CurrentBrush;
1184
if (FPen <> AData.CurrentPen) then
1186
if Assigned(FPen) then
1188
if Assigned(AData.CurrentPen) then
1189
AData.CurrentPen.AddRef;
1191
FPen := AData.CurrentPen;
1193
if (FRegion <> AData.CurrentRegion) then
1195
if Assigned(FRegion) then
1197
if Assigned(AData.CurrentRegion) then
1198
AData.CurrentRegion.AddRef;
1200
FRegion := AData.CurrentRegion;
1202
FBkColor := AData.BkColor;
1203
FBkMode := AData.BkMode;
1204
FBkBrush := AData.BkBrush;
1206
TextColor := AData.TextColor;
1208
FROP2 := AData.ROP2;
1209
FPenPos := AData.PenPos;
177
1212
constructor TCocoaContext.Create;
179
fText:=TextLayoutClass.Create;
1216
FBkBrush := TCocoaBrush.CreateDefault;
1218
FBrush := DefaultBrush;
1222
FRegion := TCocoaRegion.CreateDefault;
1224
FClipRegion := FRegion;
1225
FText := TCocoaTextLayout.Create;
182
1229
destructor TCocoaContext.Destroy;
1233
if Assigned(FBrush) then
1235
if Assigned(FPen) then
1237
if Assigned(FRegion) then
185
1242
inherited Destroy;
188
function TCocoaContext.InitDraw(width,height:Integer): Boolean;
1245
function TCocoaContext.SaveDC: Integer;
1248
ctx.restoreGraphicsState;
1252
if FSavedDCList = nil then
1253
FSavedDCList := TFPObjectList.Create(True);
1255
ctx.saveGraphicsState;
1256
Result := FSavedDCList.Add(SaveDCData) + 1;
1260
ctx.saveGraphicsState;
1261
FClipRegion.Apply(Self);
1265
function TCocoaContext.RestoreDC(ASavedDC: Integer): Boolean;
1268
ctx.restoreGraphicsState;
1271
if (FSavedDCList = nil) or (ASavedDC <= 0) or (ASavedDC > FSavedDCList.Count) then
1274
while FSavedDCList.Count > ASavedDC do
1276
ctx.restoreGraphicsState;
1277
FSavedDCList.Delete(FSavedDCList.Count - 1);
1280
ctx.restoreGraphicsState;
1281
RestoreDCData(TCocoaDCData(FSavedDCList[ASavedDC - 1]));
1282
FSavedDCList.Delete(ASavedDC - 1);
1285
if FSavedDCList.Count = 0 then FreeAndNil(FSavedDCList);
1290
FClipRegion.Shape := HIShapeCreateEmpty;
1295
function TCocoaContext.InitDraw(width, height:Integer): Boolean;
193
Result:=Assigned(cg);
1300
Result := Assigned(cg);
194
1301
if not Result then Exit;
196
ContextSize.cx:=width;
197
ContextSize.cy:=height;
199
1306
CGContextTranslateCTM(cg, 0, height);
200
1307
CGContextScaleCTM(cg, 1, -1);
205
procedure TCocoaContext.MoveTo(x,y:Integer);
211
procedure TCocoaContext.LineTo(x,y:Integer);
1312
procedure TCocoaContext.InvertRectangle(X1, Y1, X2, Y2: Integer);
1314
// save dest context
1315
ctx.saveGraphicsState;
1317
DefaultBrush.Apply(Self, False);
1318
CGContextSetBlendMode(CGContext, kCGBlendModeDifference);
1320
CGContextFillRect(CGContext, GetCGRectSorted(X1, Y1, X2, Y2));
1322
ctx.restoreGraphicsState;
1326
procedure TCocoaContext.MoveTo(X, Y: Integer);
1332
procedure TCocoaContext.LineTo(X, Y: Integer);
214
p : array [0..1] of CGPoint;
1335
p: array [0..1] of CGPoint;
215
1336
deltaX, deltaY, absDeltaX, absDeltaY: Integer;
216
1337
clipDeltaX, clipDeltaY: Float32;
220
1341
if not Assigned(cg) then Exit;
222
1343
deltaX := X - PenPos.x;
355
1479
CGContextDrawPath(CGContext, kCGPathFillStroke);
358
procedure TCocoaContext.TextOut(X,Y:Integer;UTF8Chars:PChar;Count:Integer;
359
CharsDelta:PInteger);
364
if not Assigned(cg) then Exit;
366
CGContextScaleCTM(cg, 1, -1);
367
CGContextTranslateCTM(cg, 0, -ContextSize.cy);
369
CGContextSetRGBFillColor(cg, TR, TG, TB, 1);
370
fText.SetText(UTF8Chars, Count);
371
fText.Draw(cg, X, ContextSize.cy-Y, CharsDelta);
373
if Assigned(fBrush) then fBrush.Apply(cg);
375
CGContextTranslateCTM(cg, 0, ContextSize.cy);
376
CGContextScaleCTM(cg, 1, -1);
379
procedure TCocoaContext.SetOrigin(X,Y:Integer);
384
if not Assigned(cg) then Exit;
385
if Assigned(cg) then CGContextTranslateCTM(cg, X, Y);
388
procedure TCocoaContext.GetOrigin(var X,Y: Integer);
391
t : CGAffineTransform;
394
if not Assigned(cg) then Exit;
395
t:=CGContextGetCTM(cg);
397
Y := ContextSize.cy - Round(t.ty);
1482
procedure TCocoaContext.TextOut(X, Y: Integer; Options: Longint; Rect: PRect; UTF8Chars: PChar; Count: Integer; CharsDelta: PInteger);
1484
BrushSolid, FillBg: Boolean;
1486
ctx.saveGraphicsState;
1488
if Assigned(Rect) then
1491
if (Options and ETO_OPAQUE) <> 0 then
1493
BrushSolid := BkBrush.Solid;
1494
BkBrush.Solid := True;
1496
Rectangle(Left, Top, Right, Bottom, True, BkBrush);
1497
BkBrush.Solid := BrushSolid;
1500
if (Options and ETO_CLIPPED) <> 0 then
1502
CGContextBeginPath(CGContext);
1503
CGContextAddRect(CGContext, RectToCGrect(Rect^));
1504
CGContextClip(CGContext);
1508
FillBg := BkMode = OPAQUE;
1510
FText.BackgroundColor := BkBrush.ColorRef;
1511
FText.SetText(UTF8Chars, Count);
1512
FText.Draw(ctx, X, Y, FillBg, CharsDelta);
1514
ctx.restoreGraphicsState;
1517
procedure TCocoaContext.Frame(const R: TRect);
1519
Rectangle(R.Left, R.Top, R.Right + 1, R.Bottom + 1, False, nil);
1522
procedure TCocoaContext.Frame3d(var ARect: TRect; const FrameWidth: integer; const Style: TBevelCut);
1525
DrawInfo: HIThemeGroupBoxDrawInfo;
1527
if Style = bvRaised then
1529
GetThemeMetric(kThemeMetricPrimaryGroupBoxContentInset, D);
1531
// draw frame as group box
1532
DrawInfo.version := 0;
1533
DrawInfo.state := kThemeStateActive;
1534
DrawInfo.kind := kHIThemeGroupBoxKindPrimary;
1536
for I := 1 to FrameWidth do
1538
HIThemeDrawGroupBox(RectToCGRect(ARect), DrawInfo, CGContext, kHIThemeOrientationNormal);
1539
InflateRect(ARect, -D, -D);
1544
procedure TCocoaContext.FrameRect(const ARect: TRect; const ABrush: TCocoaBrush);
1546
if ABrush <> Brush then
1548
if not ctx.currentContextDrawingToScreen then
1549
ctx.setCurrentContext(ctx);
1550
NSFrameRect(RectToNSRect(ARect));
1551
if ABrush <> Brush then
1555
procedure TCocoaContext.SetCGFillping(Ctx: CGContextRef; Width, Height: Integer);
1559
CGContextTranslateCTM(Ctx, -Width, 0);
1560
CGContextScaleCTM(Ctx, -1, 1);
1565
CGContextTranslateCTM(Ctx, 0, -Height);
1566
CGContextScaleCTM(Ctx, 1, -1);
1570
procedure TCocoaContext.RestoreCGFillping(Ctx: CGContextRef; Width, Height: Integer);
1574
CGContextTranslateCTM(Ctx, 0, Height);
1575
CGContextScaleCTM(Ctx, 1, -1);
1580
CGContextScaleCTM(Ctx, -1, 1);
1581
CGContextTranslateCTM(Ctx, Width, 0);
1585
function TCocoaContext.DrawCGImage(X, Y, Width, Height: Integer;
1586
CGImage: CGImageRef): Boolean;
1590
// save dest context
1591
ctx.saveGraphicsState;
1593
CGContextSetBlendMode(CGContext, kCGBlendModeNormal);
1595
SetCGFillping(CGContext, Width, Height);
1596
CGContextDrawImage(CGContext, GetCGRectSorted(X, Y, X + Width, Y + Height), CGImage);
1597
RestoreCGFillping(CGContext, Width, Height);
1599
ctx.restoreGraphicsState;
1605
function TCocoaContext.StretchDraw(X, Y, Width, Height: Integer;
1606
SrcDC: TCocoaContext; XSrc, YSrc, SrcWidth, SrcHeight: Integer;
1607
Msk: TCocoaBitmap; XMsk, YMsk: Integer; Rop: DWORD): Boolean;
1609
Image, MskImage: CGImageRef;
1610
SubImage, SubMask: Boolean;
1612
LayRect, DstRect: CGRect;
1614
LayerContext: CGContextRef;
1620
Bmp := SrcDC.Bitmap;
1621
if Assigned(Bmp) then
1622
Image := Bmp.ImageRep.CGImage
1626
if Image = nil then Exit;
1628
DstRect := CGRectMake(X, Y, Abs(Width), Abs(Height));
1630
SubMask := (Msk <> nil)
1631
and (Msk.Image <> nil)
1634
or (Msk.Width <> SrcWidth)
1635
or (Msk.Height <> SrcHeight));
1637
SubImage := ((Msk <> nil) and (Msk.Image <> nil))
1640
or (SrcWidth <> Bmp.Width)
1641
or (SrcHeight <> Bmp.Height);
1645
MskImage := Msk.CreateSubImage(Bounds(XMsk, YMsk, SrcWidth, SrcHeight))
1647
if Assigned(Msk) then
1648
MskImage := Msk.ImageRep.CGImage
1653
Image := Bmp.CreateSubImage(Bounds(XSrc, YSrc, SrcWidth, SrcHeight));
1656
UseLayer:=Assigned(MskImage)
1657
or (CGImageGetWidth(Image)<>SrcWidth)
1658
or (CGImageGetHeight(Image)<>SrcHeight);
1661
if not UseLayer then
1664
Result := DrawCGImage(X, Y, Width, Height, Image);
1668
// use temp layer to mask source image
1669
// todo find a way to mask "hard" when stretching, now some soft remains are visible
1670
LayRect := CGRectMake(0, 0, SrcWidth, SrcHeight);
1671
Layer := CGLayerCreateWithContext(SrcDC.CGContext, LayRect.size, nil);
1673
// the sub-image is out of edges
1674
if (CGImageGetWidth(Image)<>SrcWidth) or (CGImageGetHeight(Image)<>SrcHeight) then
1677
if XSrc<0 then origin.x:=SrcWidth-CGImageGetWidth(Image) else origin.x:=0;
1679
if YSrc<0 then origin.y:=0 else origin.y:=SrcHeight-CGImageGetHeight(Image);
1681
ImgRect.size.width:=CGImageGetWidth(Image);
1682
ImgRect.size.height:=CGImageGetHeight(Image);
1688
LayerContext := CGLayerGetContext(Layer);
1689
CGContextScaleCTM(LayerContext, 1, -1);
1690
CGContextTranslateCTM(LayerContext, 0, -SrcHeight);
1692
SetCGFillping(LayerContext, Width, Height);
1693
if Assigned(MskImage) then
1694
CGContextClipToMask(LayerContext, ImgRect, MskImage);
1695
CGContextDrawImage(LayerContext, ImgRect, Image);
1697
CGContextDrawLayerInRect(CGContext, DstRect, Layer);
1701
CGLayerRelease(Layer);
1706
if SubImage then CGImageRelease(Image);
1707
if SubMask then CGImageRelease(MskImage);
1711
{------------------------------------------------------------------------------
1712
Method: GetTextExtentPoint
1713
Params: Str - Text string
1714
Count - Number of characters in string
1715
Size - The record for the dimensions of the string
1716
Returns: If the function succeeds
1718
Computes the width and height of the specified string of text
1719
------------------------------------------------------------------------------}
1720
function TCocoaContext.GetTextExtentPoint(AStr: PChar; ACount: Integer; var Size: TSize): Boolean;
1722
FText.SetText(AStr, ACount);
1723
Size := FText.GetSize;
1727
{------------------------------------------------------------------------------
1728
Method: TCocoaContext.GetTextMetrics
1729
Params: TM - The Record for the text metrics
1730
Returns: If the function succeeds
1732
Fills the specified buffer with the metrics for the currently selected font
1733
------------------------------------------------------------------------------}
1734
function TCocoaContext.GetTextMetrics(var TM: TTextMetric): Boolean;
1736
Glyphs: TGlyphArray;
1737
Adjustments: array of NSSize;
1741
FillChar(TM, SizeOf(TM), 0);
1743
TM.tmAscent := Round(Font.Font.ascender);
1744
TM.tmDescent := -Round(Font.Font.descender);
1745
TM.tmHeight := TM.tmAscent + TM.tmDescent;
1747
TM.tmInternalLeading := Round(Font.Font.leading);
1748
TM.tmExternalLeading := 0;
1750
TM.tmMaxCharWidth := Round(Font.Font.maximumAdvancement.width);
1751
FText.SetText('WMTigq[_|^', 10);
1752
Glyphs := FText.GetGlyphs;
1753
if Length(Glyphs) > 0 then
1755
SetLength(Adjustments, Length(Glyphs));
1756
Font.Font.getAdvancements_forGlyphs_count(@Adjustments[0], @Glyphs[0], Length(Glyphs));
1758
for I := 0 to High(Adjustments) do
1759
A := A + Adjustments[I].width;
1760
TM.tmAveCharWidth := Round(A / Length(Adjustments));
1761
SetLength(Adjustments, 0);
1762
SetLength(Glyphs, 0);
1765
TM.tmAveCharWidth := TM.tmMaxCharWidth;
1768
TM.tmDigitizedAspectX := 0;
1769
TM.tmDigitizedAspectY := 0;
1770
TM.tmFirstChar := 'a';
1771
TM.tmLastChar := 'z';
1772
TM.tmDefaultChar := 'x';
1773
TM.tmBreakChar := '?';
1775
TM.tmWeight := Font.CocoaFontWeightToWin32FontWeight(NSFontManager.sharedFontManager.weightOfFont(Font.Font));
1777
if cfs_Italic in Font.Style then
1780
if cfs_Underline in Font.Style then
1781
TM.tmUnderlined := 1;
1783
if cfs_StrikeOut in Font.Style then
1784
TM.tmStruckOut := 1;
1786
TM.tmPitchAndFamily := TRUETYPE_FONTTYPE;
1787
if Font.Font.isFixedPitch then
1788
TM.tmPitchAndFamily := TM.tmPitchAndFamily or FIXED_PITCH;
1790
// we can take charset from Font.Charset also but leave it to default for now
1791
TM.tmCharSet := DEFAULT_CHARSET;
1796
procedure TCocoaContext.DrawBitmap(X, Y: Integer; ABitmap: TCocoaBitmap);
1798
NSGraphicsContext.saveGraphicsState();
1799
NSGraphicsContext.setCurrentContext(ctx);
1800
ABitmap.imagerep.drawAtPoint(NSMakePoint(X, Y));
1801
NSGraphicsContext.restoreGraphicsState();
1804
procedure TCocoaContext.DrawFocusRect(ARect: TRect);
1808
// LCL thinks that focus cannot be drawn outside focus rects, but carbon do that
1810
GetThemeMetric(kThemeMetricFocusRectOutset, AOutSet);
1811
InflateRect(ARect, -AOutSet, -AOutSet);
1812
HIThemeDrawFocusRect(RectToCGRect(ARect), True, CGContext, kHIThemeOrientationNormal);
1815
procedure TCocoaContext.SetOrigin(X, Y:Integer);
1820
if Assigned(cg) then
1821
CGContextTranslateCTM(cg, X, Y);
1824
procedure TCocoaContext.GetOrigin(var X, Y: Integer);
1827
t: CGAffineTransform;
1830
if Assigned(cg) then
1832
t := CGContextGetCTM(cg);
1834
Y := Size.cy - Round(t.ty);
666
procedure TCocoaPen.Apply(cg:CGContextRef);
668
if not Assigned(cg) then Exit;
669
CGContextSetRGBStrokeColor(cg, r, g, b, 1);
670
CGContextSetLineWidth(cg, Width);
674
constructor TCocoaPen.Create;
2110
procedure TCocoaPen.Apply(ADC: TCocoaContext; UseROP2: Boolean = True);
2112
function GetDashes(Source: TCocoaDashes): TCocoaDashes;
2117
for i := Low(Result) to High(Result) do
2118
Result[i] := Result[i] * FWidth;
2122
AR, AG, AB, AA: Single;
2124
ADashes: TCocoaDashes;
2126
if ADC = nil then Exit;
2127
if ADC.CGContext = nil then Exit;
2132
AROP2 := R2_COPYPEN;
2134
GetRGBA(AROP2, AR, AG, AB, AA);
2136
if AROP2 <> R2_NOT then
2137
CGContextSetBlendMode(ADC.CGContext, kCGBlendModeNormal)
2139
CGContextSetBlendMode(ADC.CGContext, kCGBlendModeDifference);
2141
CGContextSetRGBStrokeColor(ADC.CGContext, AR, AG, AB, AA);
2142
CGContextSetLineWidth(ADC.CGContext, FWidth);
2148
CGContextSetLineCap(ADC.CGContext, FEndCap);
2149
CGContextSetLineJoin(ADC.CGContext, FJoinStyle);
2156
ADashes := GetDashes(CocoaDashStyle);
2157
CGContextSetLineDash(ADC.CGContext, 0, @ADashes[0], Length(ADashes));
2161
ADashes := GetDashes(CocoaDotStyle);
2162
CGContextSetLineDash(ADC.CGContext, 0, @ADashes[0], Length(ADashes));
2166
ADashes := GetDashes(CocoaDashDotStyle);
2167
CGContextSetLineDash(ADC.CGContext, 0, @ADashes[0], Length(ADashes));
2171
ADashes := GetDashes(CocoaDashDotDotStyle);
2172
CGContextSetLineDash(ADC.CGContext, 0, @ADashes[0], Length(ADashes));
2175
CGContextSetLineDash(ADC.CGContext, 0, @Dashes[0], Length(Dashes));
2177
CGContextSetLineDash(ADC.CGContext, 0, nil, 0);
2181
constructor TCocoaPen.CreateDefault;
2183
inherited Create(clBlack, True, False);
2190
constructor TCocoaPen.Create(const ALogPen: TLogPen; const AGlobal: Boolean = False);
2192
case ALogPen.lopnStyle of
2193
PS_SOLID..PS_DASHDOTDOT,
2196
inherited Create(ColorToRGB(TColor(ALogPen.lopnColor)), True, AGlobal);
2197
FWidth := Max(1, ALogPen.lopnWidth.x);
2201
inherited Create(ColorToRGB(TColor(ALogPen.lopnColor)), False, AGlobal);
2206
FStyle := ALogPen.lopnStyle;
2209
constructor TCocoaPen.Create(dwPenStyle, dwWidth: DWord; const lplb: TLogBrush;
2210
dwStyleCount: DWord; lpStyle: PDWord);
2214
case dwPenStyle and PS_STYLE_MASK of
2215
PS_SOLID..PS_DASHDOTDOT,
2218
inherited Create(ColorToRGB(TColor(lplb.lbColor)), True, False);
2222
inherited Create(ColorToRGB(TColor(lplb.lbColor)), False, False);
2227
FIsGeometric := (dwPenStyle and PS_TYPE_MASK) = PS_GEOMETRIC;
2231
case dwPenStyle and PS_JOIN_MASK of
2232
PS_JOIN_ROUND: FJoinStyle := kCGLineJoinRound;
2233
PS_JOIN_BEVEL: FJoinStyle := kCGLineJoinBevel;
2234
PS_JOIN_MITER: FJoinStyle := kCGLineJoinMiter;
2237
case dwPenStyle and PS_ENDCAP_MASK of
2238
PS_ENDCAP_ROUND: FEndCap := kCGLineCapRound;
2239
PS_ENDCAP_SQUARE: FEndCap := kCGLineCapSquare;
2240
PS_ENDCAP_FLAT: FEndCap := kCGLineCapButt;
2242
FWidth := Max(1, dwWidth);
2247
if (dwPenStyle and PS_STYLE_MASK) = PS_USERSTYLE then
2249
SetLength(Dashes, dwStyleCount);
2250
for i := 0 to dwStyleCount - 1 do
2251
Dashes[i] := lpStyle[i];
2254
FStyle := dwPenStyle and PS_STYLE_MASK;
2257
constructor TCocoaPen.Create(const ABrush: TCocoaBrush; const AGlobal: Boolean);
2259
inherited Create(ABrush.ColorRef, True, AGlobal);
682
procedure TCocoaBrush.Apply(cg:CGContextRef);
684
CGContextSetRGBFillColor(cg, R,G,B, 1);
689
constructor TCocoaTextLayout.Create;
2268
procedure DrawBitmapPattern(info: UnivPtr; c: CGContextRef); MWPascal;
2270
ABrush: TCocoaBrush absolute info;
2273
AImage := ABrush.FImage;
2274
CGContextDrawImage(c, GetCGRect(0, 0, CGImageGetWidth(AImage), CGImageGetHeight(AImage)),
2278
procedure TCocoaBrush.SetHatchStyle(AHatch: PtrInt);
2280
HATCH_DATA: array[HS_HORIZONTAL..HS_DIAGCROSS] of array[0..7] of Byte =
2282
{ HS_HORIZONTAL } ($FF, $FF, $FF, $00, $FF, $FF, $FF, $FF),
2283
{ HS_VERTICAL } ($F7, $F7, $F7, $F7, $F7, $F7, $F7, $F7),
2284
{ HS_FDIAGONAL } ($7F, $BF, $DF, $EF, $F7, $FB, $FD, $FE),
2285
{ HS_BDIAGONAL } ($FE, $FD, $FB, $F7, $EF, $DF, $BF, $7F),
2286
{ HS_CROSS } ($F7, $F7, $F7, $00, $F7, $F7, $F7, $F7),
2287
{ HS_DIAGCROSS } ($7E, $BD, $DB, $E7, $E7, $DB, $BD, $7E)
2290
ACallBacks: CGPatternCallbacks;
2292
if AHatch in [HS_HORIZONTAL..HS_DIAGCROSS] then
2294
FillChar(ACallBacks, SizeOf(ACallBacks), 0);
2295
ACallBacks.drawPattern := @DrawBitmapPattern;
2296
FBitmap := TCocoaBitmap.Create(8, 8, 1, 1, cbaByte, cbtMask, @HATCH_DATA[AHatch]);
2297
FImage := FBitmap.ImageRep.CGImageForProposedRect_context_hints(nil, nil, nil);
2299
FCGPattern := CGPatternCreate(Self, GetCGRect(0, 0, 8, 8),
2300
CGAffineTransformIdentity, 8, 8, kCGPatternTilingConstantSpacing,
2301
Ord(FColored), ACallBacks);
2305
procedure TCocoaBrush.SetBitmap(ABitmap: TCocoaBitmap);
2307
AWidth, AHeight: Integer;
2308
ACallBacks: CGPatternCallbacks;
2310
AWidth := ABitmap.Width;
2311
AHeight := ABitmap.Height;
2312
FillChar(ACallBacks, SizeOf(ACallBacks), 0);
2313
ACallBacks.drawPattern := @DrawBitmapPattern;
2314
FBitmap := TCocoaBitmap.Create(ABitmap);
2315
FImage := FBitmap.imageRep.CGImageForProposedRect_context_hints(nil, nil, nil);
2317
FCGPattern := CGPatternCreate(Self, GetCGRect(0, 0, AWidth, AHeight),
2318
CGAffineTransformIdentity, AWidth, AHeight, kCGPatternTilingConstantSpacing,
2319
Ord(FColored), ACallBacks);
2322
procedure TCocoaBrush.SetImage(AImage: NSImage);
2324
AWidth, AHeight: Single;
2325
ACallBacks: CGPatternCallbacks;
2328
FillChar(ACallBacks, SizeOf(ACallBacks), 0);
2329
ACallBacks.drawPattern := @DrawBitmapPattern;
2330
FImage := CGImageCreateCopy(AImage.CGImageForProposedRect_context_hints(nil, nil, nil));
2334
Rect.size := CGSize(AImage.size);
2335
FCGPattern := CGPatternCreate(Self, Rect,
2336
CGAffineTransformIdentity, Rect.size.width, Rect.size.height, kCGPatternTilingConstantSpacing,
2337
Ord(FColored), ACallBacks);
2340
procedure TCocoaBrush.SetColor(AColor: NSColor);
2342
RGBColor, PatternColor: NSColor;
2349
RGBColor := AColor.colorUsingColorSpaceName(NSCalibratedRGBColorSpace);
2351
if Assigned(RGBColor) then
2352
SetColor(NSColorToRGB(RGBColor), True)
2355
PatternColor := AColor.colorUsingColorSpaceName(NSPatternColorSpace);
2356
if Assigned(PatternColor) then
2358
SetColor(NSColorToColorRef(PatternColor.patternImage.backgroundColor), False);
2359
SetImage(PatternColor.patternImage);
2366
constructor TCocoaBrush.CreateDefault(const AGlobal: Boolean = False);
2368
inherited Create(clWhite, True, AGlobal);
2375
constructor TCocoaBrush.Create(const ALogBrush: TLogBrush; const AGlobal: Boolean = False);
2381
case ALogBrush.lbStyle of
2383
inherited Create(ColorToRGB(TColor(ALogBrush.lbColor)), True, AGlobal);
2384
BS_HATCHED: // Hatched brush.
2386
inherited Create(ColorToRGB(TColor(ALogBrush.lbColor)), True, AGlobal);
2387
SetHatchStyle(ALogBrush.lbHatch);
2395
inherited Create(ColorToRGB(TColor(ALogBrush.lbColor)), False, AGlobal);
2396
SetBitmap(TCocoaBitmap(ALogBrush.lbHatch));
2399
inherited Create(ColorToRGB(TColor(ALogBrush.lbColor)), False, AGlobal);
2403
constructor TCocoaBrush.Create(const AColor: NSColor; const AGlobal: Boolean);
2405
RGBColor, PatternColor: NSColor;
2413
RGBColor := AColor.colorUsingColorSpaceName(NSCalibratedRGBColorSpace);
2414
if Assigned(RGBColor) then
2415
inherited Create(NSColorToRGB(RGBColor), True, AGlobal)
2418
PatternColor := AColor.colorUsingColorSpaceName(NSPatternColorSpace);
2419
if Assigned(PatternColor) then
2421
inherited Create(NSColorToColorRef(PatternColor.patternImage.backgroundColor), False, AGlobal);
2422
SetImage(PatternColor.patternImage);
2425
inherited Create(0, True, AGlobal);
2429
procedure TCocoaBrush.Clear;
2431
if FColor <> nil then
2437
if FCGPattern <> nil then
2439
CGPatternRelease(FCGPattern);
2443
FreeAndNil(FBitmap);
2445
if FImage <> nil then
2447
CGImageRelease(FImage);
2452
destructor TCocoaBrush.Destroy;
2458
procedure TCocoaBrush.Apply(ADC: TCocoaContext; UseROP2: Boolean = True);
2460
RGBA: array[0..3] of Single;
2462
APatternSpace: CGColorSpaceRef;
2463
BaseSpace: CGColorSpaceRef;
2465
if ADC = nil then Exit;
2470
AROP2 := R2_COPYPEN;
2472
GetRGBA(AROP2, RGBA[0], RGBA[1], RGBA[2], RGBA[3]);
2474
if AROP2 <> R2_NOT then
2475
CGContextSetBlendMode(ADC.CGContext, kCGBlendModeNormal)
2477
CGContextSetBlendMode(ADC.CGContext, kCGBlendModeDifference);
2479
if Assigned(FCGPattern) then
2481
if not FColored then
2482
BaseSpace := CGColorSpaceCreateDeviceRGB
2488
APatternSpace := CGColorSpaceCreatePattern(BaseSpace);
2489
CGContextSetFillColorSpace(ADC.CGContext, APatternSpace);
2490
CGColorSpaceRelease(APatternSpace);
2491
if Assigned(BaseSpace) then CGColorSpaceRelease(BaseSpace);
2492
CGContextSetFillPattern(ADC.CGcontext, FCGPattern, @RGBA[0]);
2495
CGContextSetRGBFillColor(ADC.CGContext, RGBA[0], RGBA[1], RGBA[2], RGBA[3]);
694
2498
{ TCocoaGDIObject }
2500
constructor TCocoaGDIObject.Create(AGlobal: Boolean);
696
2506
procedure TCocoaGDIObject.AddRef;
698
if RefCount>=0 then inc(RefCount);
2508
if FGlobal then Exit;
2509
if FRefCount >= 0 then inc(FRefCount);
701
2512
procedure TCocoaGDIObject.Release;
703
if RefCount>0 then Dec(RefCount)
704
else if RefCount=0 then Free;
2514
if FGlobal then Exit;
2515
if FRefCount > 0 then
2519
//DebugLn('TCocoaGDIObject.Release Error - ', dbgsName(self), ' RefCount = ', dbgs(FRefCount));
2524
DefaultBrush := TCocoaBrush.CreateDefault;
2525
DefaultPen := TCocoaPen.CreateDefault;
2526
DefaultFont := TCocoaFont.CreateDefault;