mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-14 09:19:22 +02:00
Cocoa: Rework pattern drawing to avoid calling DrawBitmapPattern and TCocoaBrush.drawPattern after items have been released.
This commit is contained in:
parent
99ee7e1d29
commit
c30426ffb3
@ -123,6 +123,14 @@ type
|
|||||||
|
|
||||||
{ TCocoaBrush }
|
{ TCocoaBrush }
|
||||||
|
|
||||||
|
TCocoaPatternInfo = record
|
||||||
|
image: CGImageRef;
|
||||||
|
bgColor: TColorRef;
|
||||||
|
fgColor: TColorRef;
|
||||||
|
colorMode: TCocoaPatternColorMode;
|
||||||
|
end;
|
||||||
|
PCocoaPatternInfo = ^TCocoaPatternInfo;
|
||||||
|
|
||||||
TCocoaBrush = class(TCocoaColorObject)
|
TCocoaBrush = class(TCocoaColorObject)
|
||||||
strict private
|
strict private
|
||||||
FCGPattern: CGPatternRef;
|
FCGPattern: CGPatternRef;
|
||||||
@ -132,10 +140,9 @@ type
|
|||||||
FFgColor: TColorRef;
|
FFgColor: TColorRef;
|
||||||
private
|
private
|
||||||
FImage: CGImageRef;
|
FImage: CGImageRef;
|
||||||
procedure DrawPattern(c: CGContextRef);
|
|
||||||
strict protected
|
strict protected
|
||||||
procedure Clear;
|
procedure Clear;
|
||||||
|
procedure CreateCGPattern(ARect: CGRect; IsColored: ShortInt);
|
||||||
procedure SetHatchStyle(AHatch: PtrInt);
|
procedure SetHatchStyle(AHatch: PtrInt);
|
||||||
procedure SetBitmap(ABitmap: TCocoaBitmap);
|
procedure SetBitmap(ABitmap: TCocoaBitmap);
|
||||||
procedure SetImage(AImage: NSImage);
|
procedure SetImage(AImage: NSImage);
|
||||||
@ -2973,9 +2980,53 @@ end;
|
|||||||
|
|
||||||
procedure DrawBitmapPattern(info: UnivPtr; c: CGContextRef); MWPascal;
|
procedure DrawBitmapPattern(info: UnivPtr; c: CGContextRef); MWPascal;
|
||||||
var
|
var
|
||||||
ABrush: TCocoaBrush absolute info;
|
R: CGRect;
|
||||||
|
sR, sG, sB: single;
|
||||||
|
APatternInfoPtr: PCocoaPatternInfo;
|
||||||
begin
|
begin
|
||||||
ABrush.DrawPattern(c);
|
APatternInfoPtr := PCocoaPatternInfo(Info);
|
||||||
|
R:= CGRectMake(0, 0, CGImageGetWidth(APatternInfoPtr^.image),
|
||||||
|
CGImageGetHeight(APatternInfoPtr^.image));
|
||||||
|
if APatternInfoPtr^.colorMode = cpmContextColor then
|
||||||
|
begin
|
||||||
|
ColorToRGBFloat(APatternInfoPtr^.bgColor, sR, sG, sB);
|
||||||
|
CGContextSetRGBFillColor(c, sR, sG, sB, 1);
|
||||||
|
CGContextFillRect(c, R);
|
||||||
|
ColorToRGBFloat(APatternInfoPtr^.fgColor, sR, sG, sB);
|
||||||
|
CGContextSetRGBFillColor(c, sR, sG, sB, 1);
|
||||||
|
end;
|
||||||
|
CGContextDrawImage(c, R, APatternInfoPtr^.image);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure PatternReleaseInfo(info: UnivPtr ); MWPascal;
|
||||||
|
begin
|
||||||
|
CGImageRelease(PCocoaPatternInfo(info)^.image);
|
||||||
|
Freemem(info);
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TCocoaBrush }
|
||||||
|
|
||||||
|
procedure TCocoaBrush.CreateCGPattern(ARect: CGRect; IsColored: ShortInt);
|
||||||
|
var
|
||||||
|
APatternInfoPtr: PCocoaPatternInfo;
|
||||||
|
Callbacks: CGPatternCallbacks;
|
||||||
|
begin
|
||||||
|
if FCGPattern <> nil then CGPatternRelease(FCGPattern);
|
||||||
|
|
||||||
|
APatternInfoPtr := GetMem(sizeof(TCocoapatternInfo));
|
||||||
|
APatternInfoPtr^.image := FImage;
|
||||||
|
CGImageRetain(APatternInfoPtr^.image);
|
||||||
|
APatternInfoPtr^.bgColor := RGBToColorFloat(Red/255, Green/255, Blue/255);
|
||||||
|
APatternInfoPtr^.fgColor := FFgColor;
|
||||||
|
APatternInfoPtr^.colorMode := FPatternColorMode;
|
||||||
|
|
||||||
|
FillChar(CallBacks, SizeOf(CallBacks), 0);
|
||||||
|
Callbacks.drawPattern := @DrawBitmapPattern;
|
||||||
|
Callbacks.releaseInfo := @PatternReleaseInfo;
|
||||||
|
|
||||||
|
FCGPattern := CGPatternCreate(APatternInfoPtr, ARect, CGAffineTransformIdentity,
|
||||||
|
ARect.size.width, ARect.size.height, kCGPatternTilingConstantSpacing,
|
||||||
|
IsColored, Callbacks);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TCocoaBrush.SetHatchStyle(AHatch: PtrInt);
|
procedure TCocoaBrush.SetHatchStyle(AHatch: PtrInt);
|
||||||
@ -2990,13 +3041,10 @@ const
|
|||||||
{ HS_DIAGCROSS } ($7E, $BD, $DB, $E7, $E7, $DB, $BD, $7E)
|
{ HS_DIAGCROSS } ($7E, $BD, $DB, $E7, $E7, $DB, $BD, $7E)
|
||||||
);
|
);
|
||||||
var
|
var
|
||||||
ACallBacks: CGPatternCallbacks;
|
|
||||||
CGDataProvider: CGDataProviderRef;
|
CGDataProvider: CGDataProviderRef;
|
||||||
begin
|
begin
|
||||||
if AHatch in [HS_HORIZONTAL..HS_DIAGCROSS] then
|
if AHatch in [HS_HORIZONTAL..HS_DIAGCROSS] then
|
||||||
begin
|
begin
|
||||||
FillChar(ACallBacks, SizeOf(ACallBacks), 0);
|
|
||||||
ACallBacks.drawPattern := @DrawBitmapPattern;
|
|
||||||
if (FBitmap <> nil) then FBitmap.Release;
|
if (FBitmap <> nil) then FBitmap.Release;
|
||||||
FBitmap := TCocoaBitmap.Create(8, 8, 1, 1, cbaByte, cbtMask, @HATCH_DATA[AHatch]);
|
FBitmap := TCocoaBitmap.Create(8, 8, 1, 1, cbaByte, cbtMask, @HATCH_DATA[AHatch]);
|
||||||
if FImage <> nil then CGImageRelease(FImage);
|
if FImage <> nil then CGImageRelease(FImage);
|
||||||
@ -3004,23 +3052,17 @@ begin
|
|||||||
FImage := CGImageMaskCreate(8, 8, 1, 1, 1, CGDataProvider, nil, 0);
|
FImage := CGImageMaskCreate(8, 8, 1, 1, 1, CGDataProvider, nil, 0);
|
||||||
CGDataProviderRelease(CGDataProvider);
|
CGDataProviderRelease(CGDataProvider);
|
||||||
FPatternColorMode := cpmBrushColor;
|
FPatternColorMode := cpmBrushColor;
|
||||||
if FCGPattern <> nil then CGPatternRelease(FCGPattern);
|
CreateCGPattern(GetCGRect(0 , 0, 8, 8), 0);
|
||||||
FCGPattern := CGPatternCreate(Self, GetCGRect(0, 0, 8, 8),
|
|
||||||
CGAffineTransformIdentity, 8.0, 8.0, kCGPatternTilingConstantSpacing,
|
|
||||||
0, ACallBacks);
|
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TCocoaBrush.SetBitmap(ABitmap: TCocoaBitmap);
|
procedure TCocoaBrush.SetBitmap(ABitmap: TCocoaBitmap);
|
||||||
var
|
var
|
||||||
AWidth, AHeight: Integer;
|
AWidth, AHeight: Integer;
|
||||||
ACallBacks: CGPatternCallbacks;
|
|
||||||
CGDataProvider: CGDataProviderRef;
|
CGDataProvider: CGDataProviderRef;
|
||||||
begin
|
begin
|
||||||
AWidth := ABitmap.Width;
|
AWidth := ABitmap.Width;
|
||||||
AHeight := ABitmap.Height;
|
AHeight := ABitmap.Height;
|
||||||
FillChar(ACallBacks, SizeOf(ACallBacks), 0);
|
|
||||||
ACallBacks.drawPattern := @DrawBitmapPattern;
|
|
||||||
if (FBitmap <> nil) then FBitmap.Release;
|
if (FBitmap <> nil) then FBitmap.Release;
|
||||||
FBitmap := TCocoaBitmap.Create(ABitmap);
|
FBitmap := TCocoaBitmap.Create(ABitmap);
|
||||||
if FImage <> nil then CGImageRelease(FImage);
|
if FImage <> nil then CGImageRelease(FImage);
|
||||||
@ -3039,29 +3081,20 @@ begin
|
|||||||
FImage := CGImageCreateCopy(MacOSAll.CGImageRef( FBitmap.imageRep.CGImageForProposedRect_context_hints(nil, nil, nil)));
|
FImage := CGImageCreateCopy(MacOSAll.CGImageRef( FBitmap.imageRep.CGImageForProposedRect_context_hints(nil, nil, nil)));
|
||||||
FPatternColorMode := cpmBitmap;
|
FPatternColorMode := cpmBitmap;
|
||||||
end;
|
end;
|
||||||
if FCGPattern <> nil then CGPatternRelease(FCGPattern);
|
CreateCGPattern(GetCGRect(0, 0, AWidth, AHeight), Ord(FPatternColorMode = cpmBitmap));
|
||||||
FCGPattern := CGPatternCreate(Self, GetCGRect(0, 0, AWidth, AHeight),
|
|
||||||
CGAffineTransformIdentity, CGFloat(AWidth), CGFloat(AHeight), kCGPatternTilingConstantSpacing,
|
|
||||||
Ord(FPatternColorMode = cpmBitmap), ACallBacks);
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TCocoaBrush.SetImage(AImage: NSImage);
|
procedure TCocoaBrush.SetImage(AImage: NSImage);
|
||||||
var
|
var
|
||||||
ACallBacks: CGPatternCallbacks;
|
|
||||||
Rect: CGRect;
|
Rect: CGRect;
|
||||||
begin
|
begin
|
||||||
FillChar(ACallBacks, SizeOf(ACallBacks), 0);
|
|
||||||
ACallBacks.drawPattern := @DrawBitmapPattern;
|
|
||||||
if FImage <> nil then CGImageRelease(FImage);
|
if FImage <> nil then CGImageRelease(FImage);
|
||||||
FImage := CGImageCreateCopy(MacOSAll.CGImageRef( AImage.CGImageForProposedRect_context_hints(nil, nil, nil)));
|
FImage := CGImageCreateCopy(MacOSAll.CGImageRef( AImage.CGImageForProposedRect_context_hints(nil, nil, nil)));
|
||||||
FPatternColorMode := cpmBitmap;
|
FPatternColorMode := cpmBitmap;
|
||||||
Rect.origin.x := 0;
|
Rect.origin.x := 0;
|
||||||
Rect.origin.y := 0;
|
Rect.origin.y := 0;
|
||||||
Rect.size := CGSize(AImage.size);
|
Rect.size := CGSize(AImage.size);
|
||||||
if FCGPattern <> nil then CGPatternRelease(FCGPattern);
|
CreateCGPattern(Rect, 1);
|
||||||
FCGPattern := CGPatternCreate(Self, Rect,
|
|
||||||
CGAffineTransformIdentity, Rect.size.width, Rect.size.height, kCGPatternTilingConstantSpacing,
|
|
||||||
1, ACallBacks);
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TCocoaBrush.SetColor(AColor: NSColor);
|
procedure TCocoaBrush.SetColor(AColor: NSColor);
|
||||||
@ -3169,22 +3202,6 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TCocoaBrush.DrawPattern(c: CGContextRef);
|
|
||||||
var
|
|
||||||
R: CGRect;
|
|
||||||
sR, sG, sB: single;
|
|
||||||
begin
|
|
||||||
R:=CGRectMake(0, 0, CGImageGetWidth(FImage), CGImageGetHeight(FImage));
|
|
||||||
if FPatternColorMode = cpmContextColor then
|
|
||||||
begin
|
|
||||||
CGContextSetRGBFillColor(c, Red/255, Green/255, Blue/255, 1);
|
|
||||||
CGContextFillRect(c, R);
|
|
||||||
ColorToRGBFloat(FFgColor, sR, sG, sB);
|
|
||||||
CGContextSetRGBFillColor(c, sR, sG, sB, 1);
|
|
||||||
end;
|
|
||||||
CGContextDrawImage(c, R, FImage);
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure TCocoaBrush.Clear;
|
procedure TCocoaBrush.Clear;
|
||||||
begin
|
begin
|
||||||
if FColor <> nil then
|
if FColor <> nil then
|
||||||
|
Loading…
Reference in New Issue
Block a user