Cocoa: CocoaWinapi & TCocoaContext refactored

This commit is contained in:
rich2014 2023-10-13 21:06:42 +08:00
parent f49aedaf1f
commit 25f4ba3380
2 changed files with 124 additions and 107 deletions

View File

@ -397,6 +397,7 @@ type
procedure ApplyTransform(Trans: CGAffineTransform);
procedure ClearClipping;
procedure AttachedBitmap_SetModified(); virtual;
procedure DrawEdgeRect(const r: TRect; flags: Cardinal; LTColor, BRColor: TColor);
public
ctx: NSGraphicsContext;
isControlDC: Boolean; // control DCs should never be freed by ReleaseDC as the control will free it by itself
@ -429,8 +430,10 @@ type
procedure BackgroundFill(dirtyRect:NSRect);
procedure Ellipse(X1, Y1, X2, Y2: Integer);
procedure TextOut(X, Y: Integer; Options: Longint; Rect: PRect; UTF8Chars: PChar; Count: Integer; CharsDelta: PInteger);
procedure DrawEdge(var Rect: TRect; edge: Cardinal; grfFlags: Cardinal);
procedure Frame(const R: TRect);
procedure Frame3d(var ARect: TRect; const FrameWidth: integer; const Style: TBevelCut);
procedure Frame3dClassic(var ARect: TRect; const FrameWidth: integer; const Style: TBevelCut);
procedure Frame3dBox(var ARect: TRect; const FrameWidth: integer; const Style: TBevelCut);
procedure FrameRect(const ARect: TRect; const ABrush: TCocoaBrush);
procedure DrawBitmap(X, Y: Integer; ABitmap: TCocoaBitmap);
function DrawImageRep(dstRect: NSRect; const srcRect: NSRect; ImageRep: NSBitmapImageRep): Boolean;
@ -1992,13 +1995,115 @@ begin
AttachedBitmap_SetModified();
end;
procedure TCocoaContext.DrawEdgeRect(const r: TRect; flags: Cardinal;
LTColor, BRColor: TColor);
begin
Pen.SetColor(LTColor, true);
Pen.Apply(self);
if flags and BF_LEFT > 0 then
begin
MoveTo(r.Left, r.Bottom);
LineTo(r.Left, r.Top);
end;
if flags and BF_TOP > 0 then
begin
MoveTo(r.Left, r.Top);
LineTo(r.Right, r.Top);
end;
Pen.SetColor(BRColor, true);
Pen.Apply(self);
if flags and BF_RIGHT > 0 then
begin
MoveTo(r.Right, r.Top);
LineTo(r.Right, r.Bottom);
end;
if flags and BF_BOTTOM > 0 then
begin
MoveTo(r.Right, r.Bottom);
// there's a missing pixel. Seems like it's accumulating an offset
LineTo(r.Left-1, r.Bottom);
end;
end;
procedure TCocoaContext.DrawEdge(var Rect: TRect; edge: Cardinal;
grfFlags: Cardinal);
var
r: TRect;
keepPen : TCocoaPen;
edgePen : TCocoaPen;
keepBrush : TCocoaBrush;
edgeBrush : TCocoaBrush;
const
OutLT = cl3DLight; // the next to hilight
OutBR = cl3DDkShadow; // the darkest (almost black)
InnLT = cl3DHiLight; // the lightest (almost white)
InnBR = cl3DShadow; // darker than light, lighter than dark shadow
begin
keepPen := Pen;
keepBrush := Brush;
try
edgePen := TCocoaPen.Create($FFFFFF, psSolid, false, 1, pmCopy, pecRound, pjsRound);
edgeBrush := TCocoaBrush.Create(NSColor.whiteColor, false);
edgeBrush.Solid := false;
Pen := edgePen;
Brush := edgeBrush;
r := Rect;
if (edge and BDR_OUTER > 0) then
begin
if edge and BDR_RAISEDOUTER > 0 then
DrawEdgeRect(r, grfFlags, OutLT, OutBR)
else
DrawEdgeRect(r, grfFlags, InnBR, InnLT);
InflateRect(r, -1, -1);
end;
if (edge and BDR_INNER > 0) then
begin
if edge and BDR_RAISEDINNER > 0 then
DrawEdgeRect(r, grfFlags, InnLT, InnBR)
else
DrawEdgeRect(r, grfFlags, OutBR, OutLT);
end;
finally
Pen := keepPen;
Brush := keepBrush;
edgeBrush.Free;
edgePen.Free;
end;
end;
procedure TCocoaContext.Frame(const R: TRect);
begin
Rectangle(R.Left, R.Top, R.Right + 1, R.Bottom + 1, False, nil);
AttachedBitmap_SetModified();
end;
procedure TCocoaContext.Frame3d(var ARect: TRect; const FrameWidth: integer; const Style: TBevelCut);
procedure TCocoaContext.Frame3dClassic(var ARect: TRect; const FrameWidth: integer;
const Style: TBevelCut);
const
Edge: array[TBevelCut] of Integer =
(
{bvNone } 0,
{bvLowered} BDR_SUNKENOUTER,
{bvRaised } EDGE_RAISED,
{bvSpace } 0
);
var
I: Integer;
rect: TRect;
begin
rect:= ARect;
for I := 0 to FrameWidth - 1 do
begin
DrawEdge(rect, Edge[Style], BF_RECT or BF_ADJUST);
InflateRect(rect,-1,-1);
end;
end;
procedure TCocoaContext.Frame3dBox(var ARect: TRect; const FrameWidth: integer; const Style: TBevelCut);
var
dx,dy: integer;
ns : NSRect;

View File

@ -564,89 +564,17 @@ begin
end;
end;
procedure DrawEdgeRect(dst: TCocoaContext; const r: TRect; flags: Cardinal;
LTColor, BRColor: TColor);
begin
dst.Pen.SetColor(LTColor, true);
dst.Pen.Apply(dst);
if flags and BF_LEFT > 0 then
begin
dst.MoveTo(r.Left, r.Bottom);
dst.LineTo(r.Left, r.Top);
end;
if flags and BF_TOP > 0 then
begin
dst.MoveTo(r.Left, r.Top);
dst.LineTo(r.Right, r.Top);
end;
dst.Pen.SetColor(BRColor, true);
dst.Pen.Apply(dst);
if flags and BF_RIGHT > 0 then
begin
dst.MoveTo(r.Right, r.Top);
dst.LineTo(r.Right, r.Bottom);
end;
if flags and BF_BOTTOM > 0 then
begin
dst.MoveTo(r.Right, r.Bottom);
// there's a missing pixel. Seems like it's accumulating an offset
dst.LineTo(r.Left-1, r.Bottom);
end;
end;
function TCocoaWidgetSet.DrawEdge(DC: HDC; var Rect: TRect; edge: Cardinal;
grfFlags: Cardinal): Boolean;
var
ctx: TCocoaContext;
r: TRect;
keepPen : TCocoaPen;
edgePen : TCocoaPen;
keepBrush : TCocoaBrush;
edgeBrush : TCocoaBrush;
const
OutLT = cl3DLight; // the next to hilight
OutBR = cl3DDkShadow; // the darkest (almost black)
InnLT = cl3DHiLight; // the lightest (almost white)
InnBR = cl3DShadow; // darker than light, lighter than dark shadow
begin
Result := false;
ctx := CheckDC(DC);
Result := Assigned(ctx);
if not Result then Exit;
if not Assigned(ctx) then
Exit;
keepPen := ctx.Pen;
keepBrush := ctx.Brush;
try
edgePen := TCocoaPen.Create($FFFFFF, psSolid, false, 1, pmCopy, pecRound, pjsRound);
edgeBrush := TCocoaBrush.Create(NSColor.whiteColor, false);
edgeBrush.Solid := false;
ctx.Pen := edgePen;
ctx.Brush := edgeBrush;
r := Rect;
if (edge and BDR_OUTER > 0) then
begin
if edge and BDR_RAISEDOUTER > 0 then
DrawEdgeRect(ctx, r, grfFlags, OutLT, OutBR)
else
DrawEdgeRect(ctx, r, grfFlags, InnBR, InnLT);
InflateRect(r, -1, -1);
end;
if (edge and BDR_INNER > 0) then
begin
if edge and BDR_RAISEDINNER > 0 then
DrawEdgeRect(ctx, r, grfFlags, InnLT, InnBR)
else
DrawEdgeRect(ctx, r, grfFlags, OutBR, OutLT);
end;
finally
ctx.Pen := keepPen;
ctx.Brush := keepBrush;
edgeBrush.Free;
edgePen.Free;
end;
ctx.DrawEdge(Rect, edge, grfFlags);
Result := true;
end;
@ -955,47 +883,31 @@ end;
function TCocoaWidgetSet.Frame3d(DC: HDC; var ARect: TRect;
const FrameWidth: integer; const Style: TBevelCut): Boolean;
const
Edge: array[TBevelCut] of Integer =
(
{bvNone } 0,
{bvLowered} BDR_SUNKENOUTER,
{bvRaised } EDGE_RAISED,
{bvSpace } 0
);
var
I: Integer;
rect: TRect;
ctx: TCocoaContext;
control: TWinControl;
is3dStyle: Boolean;
is3dClassicStyle: Boolean;
begin
Result := false;
if FrameWidth <= 0 then
Exit;
ctx := CheckDC(DC);
if not Assigned(ctx) then
exit;
Exit;
control := ctx.control;
if Assigned(control) then
is3dStyle := csParentBackground in control.ControlStyle
is3dClassicStyle := csParentBackground in control.ControlStyle
else
is3dStyle := true;
is3dClassicStyle := true;
if is3dStyle then
begin
Result := FrameWidth > 0;
if not Result then exit;
rect:= ARect;
for I := 0 to FrameWidth - 1 do
begin
Result := Boolean(DrawEdge(DC, rect, Edge[Style], BF_RECT or BF_ADJUST));
InflateRect(rect,-1,-1);
end;
end
if is3dClassicStyle then
ctx.Frame3dClassic(ARect, FrameWidth, Style)
else
begin
if FrameWidth > 0 then
ctx.Frame3d(ARect, FrameWidth, Style);
end;
ctx.Frame3dBox(ARect, FrameWidth, Style);
Result := true;
end;
function TCocoaWidgetSet.FrameRect(DC: HDC; const ARect: TRect; hBr: HBRUSH): Integer;