167 lines
5.2 KiB
ObjectPascal
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.
|