mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-07 01:06:02 +02:00
cocoa: improve text out drawing, implemented ref-counting for gdi objects
git-svn-id: trunk@27255 -
This commit is contained in:
parent
4475bded43
commit
ea83850a40
@ -15,7 +15,12 @@ uses
|
||||
type
|
||||
{ TCocoaGDIObject }
|
||||
|
||||
TCocoaGDIObject = class(TObject);
|
||||
TCocoaGDIObject = class(TObject)
|
||||
public
|
||||
RefCount: Integer;
|
||||
procedure AddRef;
|
||||
procedure Release;
|
||||
end;
|
||||
|
||||
TCocoaRegionType = (crt_Empty, crt_Rectangle, crt_Complex);
|
||||
TCocoaCombine = (cc_And, cc_Xor, cc_Or, cc_Diff, cc_Copy);
|
||||
@ -85,7 +90,7 @@ type
|
||||
procedure SetText(UTF8Text: PChar; ByteSize: Integer); virtual; abstract;
|
||||
function GetSize: TSize; virtual; abstract;
|
||||
|
||||
procedure Draw(cg: CGContextRef; X, Y: Integer; DX: PInteger; DXCount: Integer); virtual; abstract;
|
||||
procedure Draw(cg: CGContextRef; X, Y: Integer; DX: PInteger); virtual; abstract;
|
||||
end;
|
||||
TCocoaTextLayoutClass = class of TCocoaTextLayout;
|
||||
|
||||
@ -360,7 +365,7 @@ begin
|
||||
CGContextTranslateCTM(cg, 0, -ContextSize.cy);
|
||||
|
||||
fText.SetText(UTF8Chars, Count);
|
||||
fText.Draw(cg, X, ContextSize.cy-Y, CharsDelta, Count);
|
||||
fText.Draw(cg, X, ContextSize.cy-Y, CharsDelta);
|
||||
|
||||
CGContextTranslateCTM(cg, 0, ContextSize.cy);
|
||||
CGContextScaleCTM(cg, 1, -1);
|
||||
@ -536,7 +541,6 @@ end;
|
||||
------------------------------------------------------------------------------}
|
||||
procedure TCocoaRegion.Apply(cg: CGContextRef);
|
||||
begin
|
||||
exit;
|
||||
if not Assigned(cg) then Exit;
|
||||
if HIShapeIsEmpty(FShape) or (HIShapeReplacePathInCGContext(FShape, cg)<>noErr) then
|
||||
Exit;
|
||||
@ -661,4 +665,17 @@ begin
|
||||
inherited Create;
|
||||
end;
|
||||
|
||||
{ TCocoaGDIObject }
|
||||
|
||||
procedure TCocoaGDIObject.AddRef;
|
||||
begin
|
||||
if RefCount>=0 then inc(RefCount);
|
||||
end;
|
||||
|
||||
procedure TCocoaGDIObject.Release;
|
||||
begin
|
||||
if RefCount>0 then Dec(RefCount)
|
||||
else if RefCount=0 then Free;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
@ -1,4 +1,5 @@
|
||||
unit CocoaTextLayout;
|
||||
//todo: Implement TCoreTextLayout using CoreText API for newer OSes
|
||||
|
||||
interface
|
||||
|
||||
@ -14,10 +15,12 @@ type
|
||||
// legacy layout used for Mac OS X 10.4
|
||||
TASTUITextLayout = class(TCocoaTextLayout)
|
||||
private
|
||||
fBuffer : WideString;
|
||||
fUTF8 : String;
|
||||
FLayout : ATSUTextLayout;
|
||||
FStyle : ATSUStyle;
|
||||
fBuffer : WideString;
|
||||
fUTF8 : String;
|
||||
FDX : PIntegerArray;
|
||||
|
||||
FLayout : ATSUTextLayout;
|
||||
FStyle : ATSUStyle;
|
||||
|
||||
FTextBefore : ATSUTextMeasurement;
|
||||
FTextAfter : ATSUTextMeasurement;
|
||||
@ -26,18 +29,18 @@ type
|
||||
|
||||
FValidSize : Boolean;
|
||||
procedure RecountSize;
|
||||
procedure DoJustify(iLineRef: ATSULineRef; var Handled: Boolean);
|
||||
public
|
||||
constructor Create; override;
|
||||
destructor Destroy; override;
|
||||
procedure SetFont(AFont: TCocoaFont); override;
|
||||
procedure SetText(UTF8Text: PChar; ByteSize: Integer); override;
|
||||
function GetSize: TSize; override;
|
||||
procedure Draw(cg: CGContextRef; X, Y: Integer; DX: PInteger; DXCount: Integer); override;
|
||||
procedure Draw(cg: CGContextRef; X, Y: Integer; DX: PInteger); override;
|
||||
end;
|
||||
|
||||
{ TCoreTextLayout }
|
||||
|
||||
//todo: use CoreText for newer OSes
|
||||
//TCoreTextLayout = class(TCocoaTextLayout);
|
||||
|
||||
implementation
|
||||
@ -183,13 +186,66 @@ begin
|
||||
Result.cy := FixToInt(FDescent + FAscent);
|
||||
end;
|
||||
|
||||
procedure TASTUITextLayout.Draw(cg:CGContextRef;X,Y:Integer;DX:PInteger;DXCount: Integer);
|
||||
var
|
||||
MX, MY : Integer;
|
||||
ATSUDirectUPP : ATSUDirectLayoutOperationOverrideUPP = nil; //NewATSUDirectLayoutOperationOverrideUPP(@ATSUCallback)
|
||||
|
||||
function ATSUCallback(iCurrentOperation: ATSULayoutOperationSelector; iLineRef: ATSULineRef; iRefCon: UInt32; iOperationCallbackParameterPtr: UnivPtr;
|
||||
var oCallbackStatus: ATSULayoutOperationCallbackStatus ): OSStatus; {$ifdef DARWIN}mwpascal;{$endif}
|
||||
var
|
||||
Buffer : TASTUITextLayout;
|
||||
Handled : Boolean;
|
||||
begin
|
||||
Result := noErr;
|
||||
Buffer := TASTUITextLayout(iRefCon);
|
||||
oCallbackStatus:=kATSULayoutOperationCallbackStatusHandled;
|
||||
|
||||
if Assigned(Buffer) then
|
||||
Buffer.DoJustify(iLineRef, Handled);
|
||||
end;
|
||||
|
||||
procedure TASTUITextLayout.DoJustify(iLineRef: ATSULineRef; var Handled: Boolean);
|
||||
type
|
||||
ATSLayoutRecord1 = packed record
|
||||
glyphID: ATSGlyphRef;
|
||||
flags: ATSGlyphInfoFlags;
|
||||
originalOffset: ByteCount;
|
||||
realPos: Fixed;
|
||||
end;
|
||||
|
||||
type
|
||||
TATSLayoutRecordArray = array [Word] of ATSLayoutRecord1;
|
||||
PATSLayoutRecordArray = ^TATSLayoutRecordArray;
|
||||
var
|
||||
i, ofs : Integer;
|
||||
Layouts : PATSLayoutRecordArray;
|
||||
LayCount : ItemCount;
|
||||
begin
|
||||
if not Assigned(FDX) then Exit;
|
||||
Laycount:=0;
|
||||
ATSUDirectGetLayoutDataArrayPtrFromLineRef( iLineRef,
|
||||
kATSUDirectDataLayoutRecordATSLayoutRecordVersion1, true, @Layouts, Laycount);
|
||||
if Assigned(Layouts) and (Laycount>0) then
|
||||
begin
|
||||
ofs:=0;
|
||||
for i:=0 to LayCount-1 do
|
||||
begin
|
||||
Layouts^[i].realPos:=Long2Fix(ofs);
|
||||
inc(ofs, FDX^[i]);
|
||||
end;
|
||||
end;
|
||||
ATSUDirectReleaseLayoutDataArrayPtr(iLineRef, kATSUDirectDataLayoutRecordATSLayoutRecordCurrent, @Layouts );
|
||||
Handled:=True;
|
||||
end;
|
||||
|
||||
|
||||
procedure TASTUITextLayout.Draw(cg:CGContextRef;X,Y:Integer;DX:PInteger);
|
||||
var
|
||||
MX, MY : Integer;
|
||||
|
||||
Tag : ATSUAttributeTag;
|
||||
DataSize : ByteCount;
|
||||
PValue : ATSUAttributeValuePtr;
|
||||
Size : ByteCount;
|
||||
Value : ATSUAttributeValuePtr;
|
||||
OverSpec : ATSULayoutOperationOverrideSpecifier;
|
||||
begin
|
||||
if not Assigned(cg) then Exit;
|
||||
if not FValidSize then RecountSize;
|
||||
@ -197,22 +253,43 @@ begin
|
||||
MX:=0;
|
||||
MY:=0;
|
||||
Tag := kATSUCGContextTag;
|
||||
DataSize := sizeOf(CGContextRef);
|
||||
PValue := @cg;
|
||||
ATSUSetLayoutControls(FLayout, 1, @Tag, @DataSize, @PValue);
|
||||
Size := sizeOf(CGContextRef);
|
||||
Value := @cg;
|
||||
ATSUSetLayoutControls(FLayout, 1, @Tag, @Size, @Value);
|
||||
|
||||
Tag := kATSULayoutOperationOverrideTag;
|
||||
Size := sizeof (ATSULayoutOperationOverrideSpecifier);
|
||||
Value := @OverSpec;
|
||||
FillChar(OverSpec, sizeof(OverSpec), 0);
|
||||
if Assigned(Dx) then begin
|
||||
FDX := PIntegerArray(Dx);
|
||||
OverSpec.operationSelector := kATSULayoutOperationPostLayoutAdjustment;
|
||||
if not Assigned(ATSUDirectUPP) then ATSUDirectUPP:=NewATSUDirectLayoutOperationOverrideUPP(@ATSUCallback);
|
||||
OverSpec.overrideUPP := ATSUDirectUPP;
|
||||
end else
|
||||
FDX:=nil;
|
||||
ATSUSetLayoutControls (FLayout, 1, @Tag, @Size, @Value);
|
||||
|
||||
ATSUDrawText(FLayout, kATSUFromTextBeginning, kATSUToTextEnd,
|
||||
IntToFix(X)- FTextBefore + MX, IntToFix(Y) - FAscent + MY);
|
||||
end;
|
||||
|
||||
|
||||
procedure InitTextLayout;
|
||||
begin
|
||||
if not Assigned(TextLayoutClass) then
|
||||
if not Assigned(TextLayoutClass) then begin
|
||||
TextLayoutClass:=TASTUITextLayout;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure ReleaseTextLayout;
|
||||
begin
|
||||
if Assigned(ATSUDirectUPP) then DisposeATSUDirectLayoutOperationOverrideUPP(ATSUDirectUPP);
|
||||
end;
|
||||
|
||||
initialization
|
||||
InitTextLayout;
|
||||
|
||||
finalization
|
||||
ReleaseTextLayout;
|
||||
|
||||
end.
|
||||
|
@ -246,6 +246,15 @@ end;
|
||||
|
||||
{------------------------------- DEVICE CONTEXT -------------------------------}
|
||||
|
||||
function TCocoaWidgetSet.DeleteObject(GDIObject: HGDIOBJ): Boolean;
|
||||
var
|
||||
gdi: TCocoaGDIObject;
|
||||
begin
|
||||
Result:=True;
|
||||
gdi:=CheckGDIOBJ(GdiObject);
|
||||
if Assigned(gdi) then gdi.Release;
|
||||
end;
|
||||
|
||||
function TCocoaWidgetSet.SelectObject(ADC: HDC; GDIObj: HGDIOBJ): HGDIOBJ;
|
||||
var
|
||||
dc: TCocoaContext;
|
||||
@ -285,6 +294,9 @@ begin
|
||||
//TCarbonBitmapContext(ADC).Bitmap := TCarbonBitmap(GDIObj);
|
||||
end;
|
||||
|
||||
if Result<>0 then TCocoaGDIObject(Result).Release;
|
||||
if Assigned(gdi) then gdi.AddRef;
|
||||
|
||||
{$IFDEF VerboseWinAPI}
|
||||
DebugLn('TCocoaWidgetSet.SelectObject Result: ' + DbgS(Result));
|
||||
{$ENDIF}
|
||||
@ -316,7 +328,27 @@ begin
|
||||
{$ENDIF}
|
||||
end;
|
||||
|
||||
{------------------------------------ TEXT ------------------------------------}
|
||||
{------------------------------- FONT AND TEXT --------------------------------}
|
||||
|
||||
function TCocoaWidgetSet.CreateFontIndirect(const LogFont: TLogFont): HFONT;
|
||||
begin
|
||||
Result:=CreateFontIndirectEx(LogFont, LogFont.lfFaceName);
|
||||
end;
|
||||
|
||||
function TCocoaWidgetSet.CreateFontIndirectEx(const LogFont: TLogFont; const LongFontName: string): HFONT;
|
||||
var
|
||||
cf : TCocoaFont;
|
||||
begin
|
||||
cf:=TCocoaFont.Create;
|
||||
cf.Size:=LogFont.lfHeight;
|
||||
cf.Name:=LongFontName;
|
||||
if LogFont.lfWeight>FW_NORMAL then Include(cf.Style, cfs_Bold);
|
||||
if LogFont.lfItalic>0 then Include(cf.Style, cfs_Italic);
|
||||
if LogFont.lfUnderline>0 then Include(cf.Style, cfs_Underline);
|
||||
if LogFont.lfStrikeOut>0 then Include(cf.Style, cfs_Strikeout);
|
||||
cf.Antialiased:=logFont.lfQuality>=ANTIALIASED_QUALITY;
|
||||
Result:=HFONT(cf);
|
||||
end;
|
||||
|
||||
function TCocoaWidgetSet.ExtTextOut(DC: HDC; X, Y: Integer; Options: Longint; Rect: PRect; Str: PChar; Count: Longint; Dx: PInteger): Boolean;
|
||||
var
|
||||
@ -334,5 +366,4 @@ begin
|
||||
Result:=ExtTextOut(DC, X, Y, 0, nil, Str, Count, nil);
|
||||
end;
|
||||
|
||||
|
||||
//##apiwiz##eps## // Do not remove, no wizard declaration after this line
|
||||
|
@ -54,18 +54,18 @@ function CreateBrushIndirect(const LogBrush: TLogBrush): HBRUSH; override;
|
||||
function CreateCaret(Handle : HWND; Bitmap : hBitmap; Width, Height : Integer) : Boolean; override;
|
||||
function CreateCompatibleBitmap(DC: HDC; Width, Height: Integer): HBITMAP; override;
|
||||
function CreateCompatibleDC(DC: HDC): HDC; override;
|
||||
function CreateEllipticRgn(p1, p2, p3, p4: Integer): HRGN; override;
|
||||
function CreateEllipticRgn(p1, p2, p3, p4: Integer): HRGN; override;}
|
||||
function CreateFontIndirect(const LogFont: TLogFont): HFONT; override;
|
||||
function CreateFontIndirectEx(const LogFont: TLogFont; const LongFontName: string): HFONT; override;
|
||||
function CreateIconIndirect(IconInfo: PIconInfo): HICON; override;}
|
||||
{function CreateIconIndirect(IconInfo: PIconInfo): HICON; override;}
|
||||
function CreatePenIndirect(const LogPen: TLogPen): HPEN; override;
|
||||
function CreatePolygonRgn(Points: PPoint; NumPts: Integer; FillMode: integer): HRGN; override;
|
||||
function CreateRectRgn(X1, Y1, X2, Y2: Integer): HRGN; override;
|
||||
{
|
||||
procedure DeleteCriticalSection(var CritSection: TCriticalSection); override;
|
||||
function DeleteDC(hDC: HDC): Boolean; override;
|
||||
function DeleteDC(hDC: HDC): Boolean; override;}
|
||||
function DeleteObject(GDIObject: HGDIOBJ): Boolean; override;
|
||||
function DestroyCaret(Handle : HWND): Boolean; override;
|
||||
{function DestroyCaret(Handle : HWND): Boolean; override;
|
||||
function DestroyIcon(Handle: HICON): Boolean; override;
|
||||
function DPtoLP(DC: HDC; var Points; Count: Integer): BOOL; override;
|
||||
function DrawFocusRect(DC: HDC; const Rect: TRect): boolean; override;
|
||||
|
Loading…
Reference in New Issue
Block a user