FastReport_FMX_2.8.12/Source/FMX.frxCanvas.Mac.pas
2024-07-06 22:41:12 +02:00

167 lines
5.2 KiB
ObjectPascal

{******************************************}
{ }
{ FastReport FMX v2.8 }
{ Canvas for printing bitmap }
{ when using MetalAPI }
{ }
{ Copyright (c) 2021 }
{ Fast Reports Inc. }
{ }
{******************************************}
unit FMX.frxCanvas.Mac;
{$H+}
interface
uses
System.Types, System.Math.Vectors, System.UIConsts, System.Classes, System.SysUtils, System.Math, System.UITypes,
System.Character, System.Generics.Collections, Macapi.CocoaTypes, Macapi.CoreGraphics, Macapi.CoreFoundation,
Macapi.ImageIO, Macapi.CoreText, Macapi.Helpers, FMX.Types, FMX.Platform, FMX.Printer, FMX.Printer.Mac, FMX.Consts,
FMX.Forms, FMX.TextLayout, FMX.Surfaces, FMX.Graphics, FMX.Canvas.Mac;
type
TfrxCanvasQuartz = class(TCanvasQuartz)
protected
procedure DoDrawBitmap(const ABitmap: TBitmap; const SrcRect, DstRect: TRectF;
const AOpacity: Single; const HighSpeed: Boolean = False); override;
public
constructor CreateFromPrinter(const APrinter: TAbstractPrinter); override;
end;
implementation
uses
Macapi.PrintCore;
var
GlobalColorSpace: CGColorSpaceRef;
function ColorSpace: CGColorSpaceRef;
begin
if GlobalColorSpace = nil then
GlobalColorSpace := CGColorSpaceCreateDeviceRGB;
Result := GlobalColorSpace;
end;
constructor TfrxCanvasQuartz.CreateFromPrinter(
const APrinter: TAbstractPrinter);
begin
inherited;
end;
{ TfrxCanvasQuartz }
procedure TfrxCanvasQuartz.DoDrawBitmap(const ABitmap: TBitmap;
const SrcRect, DstRect: TRectF; const AOpacity: Single;
const HighSpeed: Boolean);
var
B: TObject;
pData, LContext: Pointer;
NewDestRect, SubRect: CGRect;
ImageRef, SubImageRef: CGImageRef;
Surf: TBitmapSurface;
begin
if (Context = nil) or (ABitmap = nil) then Exit;
if ABitmap.HandleAllocated then
begin
B := TObject(ABitmap.Handle);
if (B is TQuartzBitmap) then
inherited DoDrawBitmap(ABitmap, SrcRect, DstRect, AOpacity, HighSpeed)
else
begin
Surf := TBitmapSurface.Create;
try
Surf.Assign(ABitmap);
if Surf.PixelFormat = TPixelFormat.RGBA then
LContext := CGBitmapContextCreate(Surf.Bits, Surf.Width, Surf.Height,
8, Surf.Pitch, ColorSpace, kCGImageAlphaPremultipliedLast)
else
begin
LContext := CGBitmapContextCreate(nil, Surf.Width, Surf.Height, 8,
Surf.Pitch, ColorSpace, kCGImageAlphaPremultipliedLast);
pData := CGBitmapContextGetData(LContext);
ChangePixelFormat(Surf.Bits, pData, Surf.Width * Surf.Height,
Surf.PixelFormat, TPixelFormat.RGBA);
end;
if LContext <> nil then
begin
ImageRef := CGBitmapContextCreateImage(LContext);
if ImageRef <> nil then
try
NewDestRect := CGRectFromRect(DstRect);
if (SrcRect.Left = 0) and (SrcRect.Top = 0) and
(SrcRect.Right = ABitmap.Width) and
(SrcRect.Bottom = ABitmap.Height) then
begin
CGContextSaveGState(Context);
CGContextSetAlpha(Context, AOpacity);
if HighSpeed then
CGContextSetInterpolationQuality(Context,
kCGInterpolationNone)
else
CGContextSetInterpolationQuality(Context,
kCGInterpolationDefault);
NewDestRect.origin.y := -DstRect.Bottom;
CGContextScaleCTM(Context, 1, -1);
CGContextSetAllowsAntialiasing(Context, False);
CGContextDrawImage(Context, NewDestRect, ImageRef);
CGContextSetAllowsAntialiasing(Context, True);
CGContextRestoreGState(Context);
end
else
begin
SubRect := CGRectFromRect(SrcRect);
SubImageRef := CGImageCreateWithImageInRect(ImageRef, SubRect);
if SubImageRef <> nil then
begin
CGContextSaveGState(Context);
CGContextSetAlpha(Context, AOpacity);
if HighSpeed then
CGContextSetInterpolationQuality(Context,
kCGInterpolationNone)
else
CGContextSetInterpolationQuality(Context,
kCGInterpolationDefault);
NewDestRect.origin.y := -DstRect.Bottom;
CGContextScaleCTM(Context, 1, -1);
CGContextDrawImage(Context, NewDestRect, SubImageRef);
CGImageRelease(SubImageRef);
CGContextRestoreGState(Context);
end;
end;
finally
if ImageRef <> nil then
CGImageRelease(ImageRef);
if LContext <> nil then
CGContextRelease(LContext);
end;
end;
finally
Surf.Free;
end;
end;
end;
end;
initialization
TTextLayoutManager.RegisterTextLayout(TTextLayoutCT, TfrxCanvasQuartz);
finalization
end.