mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-04-09 21:48:19 +02:00
Cocoa: Advances the bitmap code
git-svn-id: trunk@31449 -
This commit is contained in:
parent
ddcae0f6ae
commit
1a26b03f11
@ -14,6 +14,14 @@ uses
|
||||
Classes, Types;
|
||||
|
||||
type
|
||||
TCocoaBitmapAlignment = (
|
||||
cbaByte, // each line starts at byte boundary.
|
||||
cbaWord, // each line starts at word (16bit) boundary
|
||||
cbaDWord, // each line starts at double word (32bit) boundary
|
||||
cbaQWord, // each line starts at quad word (64bit) boundary
|
||||
cbaDQWord // each line starts at double quad word (128bit) boundary
|
||||
);
|
||||
|
||||
TCocoaBitmapType = (
|
||||
cbtMono, // mask or mono bitmap
|
||||
cbtGray, // grayscale bitmap
|
||||
@ -24,6 +32,10 @@ type
|
||||
cbtBGRA // color bitmap with alpha channel 8-8-8-8 B-G-R-A (windows compatible)
|
||||
);
|
||||
|
||||
const
|
||||
cbtMask = cbtMono;
|
||||
|
||||
type
|
||||
{ TCocoaGDIObject }
|
||||
|
||||
TCocoaGDIObject = class(TObject)
|
||||
@ -91,14 +103,40 @@ type
|
||||
|
||||
TCocoaBitmap = class(TCocoaGDIObject)
|
||||
private
|
||||
FData: Pointer;
|
||||
FAlignment: TCocoaBitmapAlignment;
|
||||
FFreeData: Boolean;
|
||||
FDataSize: Integer;
|
||||
FBytesPerRow: Integer;
|
||||
FDepth: Byte;
|
||||
FBitsPerPixel: Byte;
|
||||
FWidth: Integer;
|
||||
FHeight: Integer;
|
||||
FType: TCocoaBitmapType;
|
||||
// Cocoa information
|
||||
FbitsPerSample: NSInteger; // How many bits in each color component
|
||||
FsamplesPerPixel: NSInteger;// How many color components
|
||||
public
|
||||
image: NSImage;
|
||||
imagerep: NSBitmapImageRep;
|
||||
constructor Create(AWidth, AHeight, ADepth, ABitsPerPixel: Integer;
|
||||
AAlignment: TCocoaBitmapAlignment; AType: TCocoaBitmapType;
|
||||
AData: Pointer; ACopyData: Boolean = True);
|
||||
destructor Destroy; override;
|
||||
procedure SetInfo(AWidth, AHeight, ADepth, ABitsPerPixel: Integer;
|
||||
AAlignment: TCocoaBitmapAlignment; AType: TCocoaBitmapType);
|
||||
public
|
||||
// property BitsPerComponent: Integer read GetBitsPerComponent;
|
||||
property BitmapType: TCocoaBitmapType read FType;
|
||||
// property BytesPerRow: Integer read FBytesPerRow;
|
||||
// property CGImage: CGImageRef read FCGImage write SetCGImage;
|
||||
// property ColorSpace: CGColorSpaceRef read GetColorSpace;
|
||||
property Data: Pointer read FData;
|
||||
property DataSize: Integer read FDataSize;
|
||||
property Depth: Byte read FDepth;
|
||||
// property Info: CGBitmapInfo read GetInfo;
|
||||
property Width: Integer read FWidth;
|
||||
property Height: Integer read FHeight;
|
||||
end;
|
||||
|
||||
{ TCocoaTextLayout }
|
||||
@ -161,8 +199,29 @@ type
|
||||
var
|
||||
TextLayoutClass : TCocoaTextLayoutClass = nil;
|
||||
|
||||
function CheckDC(dc: HDC): TCocoaContext;
|
||||
function CheckGDIOBJ(obj: HGDIOBJ): TCocoaGDIObject;
|
||||
function CheckBitmap(ABitmap: HBITMAP; AStr: string): Boolean;
|
||||
|
||||
implementation
|
||||
|
||||
//todo: a better check!
|
||||
|
||||
function CheckDC(dc: HDC): TCocoaContext;
|
||||
begin
|
||||
Result:=TCocoaContext(dc);
|
||||
end;
|
||||
|
||||
function CheckGDIOBJ(obj: HGDIOBJ): TCocoaGDIObject;
|
||||
begin
|
||||
Result:=TCocoaGDIObject(obj);
|
||||
end;
|
||||
|
||||
function CheckBitmap(ABitmap: HBITMAP; AStr: string): Boolean;
|
||||
begin
|
||||
Result := ABitmap <> 0;
|
||||
end;
|
||||
|
||||
{ TCocoaBitmap }
|
||||
|
||||
type
|
||||
@ -186,52 +245,43 @@ type
|
||||
// ABytesPerRow - The number of bytes between rows
|
||||
ACopyData - Copy supplied bitmap data (OPTIONAL)
|
||||
|
||||
Creates Carbon bitmap with the specified characteristics
|
||||
Creates Cocoa bitmap with the specified characteristics
|
||||
------------------------------------------------------------------------------}
|
||||
constructor TCocoaBitmap.Create(AWidth, AHeight, ADepth,
|
||||
ABitsPerPixel: Integer; AData: Pointer; ACopyData: Boolean);
|
||||
var
|
||||
bitsPerSample: NSInteger; // How many bits in each color component
|
||||
samplesPerPixel: NSInteger;// How many color components
|
||||
constructor TCocoaBitmap.Create(AWidth, AHeight, ADepth, ABitsPerPixel: Integer;
|
||||
AAlignment: TCocoaBitmapAlignment; AType: TCocoaBitmapType;
|
||||
AData: Pointer; ACopyData: Boolean);
|
||||
begin
|
||||
case ABitsPerPixel of
|
||||
// Mono
|
||||
1:
|
||||
begin
|
||||
bitsPerSample := 1;
|
||||
samplesPerPixel := 1;
|
||||
end;
|
||||
// Gray scale
|
||||
8:
|
||||
begin
|
||||
bitsPerSample := 8;
|
||||
samplesPerPixel := 1;
|
||||
end;
|
||||
// ARGB
|
||||
32:
|
||||
begin
|
||||
bitsPerSample := 8;
|
||||
samplesPerPixel := 4;
|
||||
end;
|
||||
SetInfo(AWidth, AHeight, ADepth, ABitsPerPixel, AAlignment, AType);
|
||||
|
||||
// Copy the image data, if necessary
|
||||
if (AData = nil) or ACopyData then
|
||||
begin
|
||||
System.GetMem(FData, FDataSize);
|
||||
FFreeData := True;
|
||||
if AData <> nil then
|
||||
System.Move(AData^, FData^, FDataSize) // copy data
|
||||
else
|
||||
FillDWord(FData^, FDataSize shr 2, 0); // clear bitmap
|
||||
end
|
||||
else
|
||||
// Other RGB
|
||||
bitsPerSample := bitsPerSample div 3;
|
||||
samplesPerPixel := 3;
|
||||
begin
|
||||
FData := AData;
|
||||
FFreeData := False;
|
||||
end;
|
||||
|
||||
// Create the associated NSImageRep
|
||||
imagerep := NSBitmapImageRep(NSBitmapImageRep.alloc.initWithBitmapDataPlanes_pixelsWide_pixelsHigh__colorSpaceName_bitmapFormat_bytesPerRow_bitsPerPixel(
|
||||
@AData, // planes, BitmapDataPlanes
|
||||
AWidth, // width, pixelsWide
|
||||
AHeight,// height, PixelsHigh
|
||||
bitsPerSample,// bitsPerSample, bps
|
||||
samplesPerPixel, // samplesPerPixel, sps
|
||||
@FData, // planes, BitmapDataPlanes
|
||||
FWidth, // width, pixelsWide
|
||||
FHeight,// height, PixelsHigh
|
||||
FbitsPerSample,// bitsPerSample, bps
|
||||
FsamplesPerPixel, // samplesPerPixel, sps
|
||||
False, // hasAlpha
|
||||
False, // isPlanar
|
||||
NSCalibratedRGBColorSpace, // colorSpaceName
|
||||
0, // bitmapFormat
|
||||
0, // bytesPerRow
|
||||
ABitsPerPixel //bitsPerPixel
|
||||
FBitsPerPixel //bitsPerPixel
|
||||
));
|
||||
|
||||
// Create the associated NSImage
|
||||
@ -239,6 +289,73 @@ begin
|
||||
image.addRepresentation(imagerep);
|
||||
end;
|
||||
|
||||
destructor TCocoaBitmap.Destroy;
|
||||
begin
|
||||
//CGImageRelease(FCGImage);
|
||||
if FFreeData then System.FreeMem(FData);
|
||||
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
procedure TCocoaBitmap.SetInfo(AWidth, AHeight, ADepth,
|
||||
ABitsPerPixel: Integer; AAlignment: TCocoaBitmapAlignment;
|
||||
AType: TCocoaBitmapType);
|
||||
const
|
||||
ALIGNBITS: array[TCocoaBitmapAlignment] of Integer = (0, 1, 3, 7, $F);
|
||||
var
|
||||
M: Integer;
|
||||
begin
|
||||
if AWidth < 1 then AWidth := 1;
|
||||
if AHeight < 1 then AHeight := 1;
|
||||
FWidth := AWidth;
|
||||
FHeight := AHeight;
|
||||
FDepth := ADepth;
|
||||
FBitsPerPixel := ABitsPerPixel;
|
||||
FType := AType;
|
||||
FAlignment := AAlignment;
|
||||
|
||||
if (FType in [cbtMono, cbtGray]) and (FDepth=0) then
|
||||
FDepth:=FBitsPerPixel;
|
||||
|
||||
FBytesPerRow := ((AWidth * ABitsPerPixel) + 7) shr 3;
|
||||
M := FBytesPerRow and ALIGNBITS[AAlignment];
|
||||
if M <> 0 then Inc(FBytesPerRow, ALIGNBITS[AAlignment] + 1 - M);
|
||||
|
||||
FDataSize := FBytesPerRow * FHeight;
|
||||
|
||||
// Cocoa information
|
||||
case ABitsPerPixel of
|
||||
// Strangely, this might appear
|
||||
0:
|
||||
begin
|
||||
FbitsPerSample := 0;
|
||||
FsamplesPerPixel := 0;
|
||||
end;
|
||||
// Mono
|
||||
1:
|
||||
begin
|
||||
FbitsPerSample := 1;
|
||||
FsamplesPerPixel := 1;
|
||||
end;
|
||||
// Gray scale
|
||||
8:
|
||||
begin
|
||||
FbitsPerSample := 8;
|
||||
FsamplesPerPixel := 1;
|
||||
end;
|
||||
// ARGB
|
||||
32:
|
||||
begin
|
||||
FbitsPerSample := 8;
|
||||
FsamplesPerPixel := 4;
|
||||
end;
|
||||
else
|
||||
// Other RGB
|
||||
FbitsPerSample := ABitsPerPixel div 3;
|
||||
FsamplesPerPixel := 3;
|
||||
end;
|
||||
end;
|
||||
|
||||
{ TCocoaContext }
|
||||
|
||||
function TCocoaContext.CGContext:CGContextRef;
|
||||
|
@ -363,8 +363,8 @@ end; {TCarbonWidgetSet.PromptUser}*)
|
||||
|
||||
------------------------------------------------------------------------------}
|
||||
function TCocoaWidgetSet.RawImage_CreateBitmaps(const ARawImage: TRawImage; out ABitmap, AMask: HBitmap; ASkipMask: Boolean): Boolean;
|
||||
{const
|
||||
ALIGNMAP: array[TRawImageLineEnd] of TCarbonBitmapAlignment = (cbaByte, cbaByte, cbaWord, cbaDWord, cbaQWord, cbaDQWord);}
|
||||
const
|
||||
ALIGNMAP: array[TRawImageLineEnd] of TCocoaBitmapAlignment = (cbaByte, cbaByte, cbaWord, cbaDWord, cbaQWord, cbaDQWord);
|
||||
var
|
||||
ADesc: TRawImageDescription absolute ARawImage.Description;
|
||||
bmpType: TCocoaBitmapType;
|
||||
@ -374,11 +374,11 @@ begin
|
||||
debugln(['TCarbonWidgetSet.RawImage_CreateBitmaps TODO Depth=',ADesc.Depth,' alphaprec=',ADesc.AlphaPrec,' byteorder=',ord(ADesc.ByteOrder),' alpha=',ADesc.AlphaShift,' red=',ADesc.RedShift,' green=',adesc.GreenShift,' blue=',adesc.BlueShift]);
|
||||
exit;
|
||||
end;
|
||||
ABitmap := HBITMAP(TCocoaBitmap.Create(ADesc.Width, ADesc.Height, ADesc.Depth, ADesc.BitsPerPixel, {ALIGNMAP[ADesc.LineEnd], bmpType,} ARawImage.Data));
|
||||
ABitmap := HBITMAP(TCocoaBitmap.Create(ADesc.Width, ADesc.Height, ADesc.Depth, ADesc.BitsPerPixel, ALIGNMAP[ADesc.LineEnd], bmpType, ARawImage.Data));
|
||||
|
||||
if ASkipMask or (ADesc.MaskBitsPerPixel = 0)
|
||||
then AMask := 0
|
||||
else AMask := HBITMAP(TCocoaBitmap.Create(ADesc.Width, ADesc.Height, 1, ADesc.MaskBitsPerPixel, {ALIGNMAP[ADesc.MaskLineEnd], cbtMask,} ARawImage.Mask));
|
||||
else AMask := HBITMAP(TCocoaBitmap.Create(ADesc.Width, ADesc.Height, 1, ADesc.MaskBitsPerPixel, ALIGNMAP[ADesc.MaskLineEnd], cbtMask, ARawImage.Mask));
|
||||
|
||||
Result := True;
|
||||
end;
|
||||
@ -423,7 +423,7 @@ begin
|
||||
end;
|
||||
|
||||
Result := True;
|
||||
end;
|
||||
end;*)
|
||||
|
||||
{------------------------------------------------------------------------------
|
||||
Function: RawImage_FromBitmap
|
||||
@ -435,14 +435,14 @@ end;
|
||||
|
||||
Creates a raw image from the specified bitmap
|
||||
------------------------------------------------------------------------------}
|
||||
function TCarbonWidgetSet.RawImage_FromBitmap(out ARawImage: TRawImage; ABitmap, AMask: HBITMAP; ARect: PRect = nil): Boolean;
|
||||
function TCocoaWidgetSet.RawImage_FromBitmap(out ARawImage: TRawImage; ABitmap, AMask: HBITMAP; ARect: PRect = nil): Boolean;
|
||||
begin
|
||||
if CheckBitmap(ABitmap, 'RawImage_FromBitmap')
|
||||
and ((AMask = 0) or CheckBitmap(AMask, 'RawImage_FromBitmap (mask)'))
|
||||
then Result := RawImage_FromCarbonBitmap(ARawImage, TCarbonBitmap(ABitmap), TCarbonBitmap(AMask), ARect)
|
||||
then Result := RawImage_FromCocoaBitmap(ARawImage, TCocoaBitmap(ABitmap), TCocoaBitmap(AMask), ARect)
|
||||
else Result := False;
|
||||
end;
|
||||
|
||||
(*
|
||||
{------------------------------------------------------------------------------
|
||||
Function: RawImage_FromDevice
|
||||
Params: ARawImage: Image to create
|
||||
|
@ -52,9 +52,9 @@ function PromptUser(const DialogCaption : string;
|
||||
|
||||
function RawImage_CreateBitmaps(const ARawImage: TRawImage; out ABitmap, AMask: HBitmap; ASkipMask: Boolean = False): Boolean; override;
|
||||
{function RawImage_DescriptionFromBitmap(ABitmap: HBITMAP; out ADesc: TRawImageDescription): Boolean; override;
|
||||
function RawImage_DescriptionFromDevice(ADC: HDC; out ADesc: TRawImageDescription): Boolean; override;
|
||||
function RawImage_DescriptionFromDevice(ADC: HDC; out ADesc: TRawImageDescription): Boolean; override;}
|
||||
function RawImage_FromBitmap(out ARawImage: TRawImage; ABitmap, AMask: HBITMAP; ARect: PRect = nil): Boolean; override;
|
||||
function RawImage_FromDevice(out ARawImage: TRawImage; ADC: HDC; const ARect: TRect): Boolean; override;
|
||||
{function RawImage_FromDevice(out ARawImage: TRawImage; ADC: HDC; const ARect: TRect): Boolean; override;
|
||||
// override only when queried formats are different from screen description
|
||||
//function RawImage_QueryDescription(AFlags: TRawImageQueryFlags; var ADesc: TRawImageDescription): Boolean; override;
|
||||
|
||||
|
@ -22,18 +22,6 @@
|
||||
*****************************************************************************
|
||||
}
|
||||
|
||||
//todo: a better check!
|
||||
|
||||
function CheckDC(dc: HDC): TCocoaContext;
|
||||
begin
|
||||
Result:=TCocoaContext(dc);
|
||||
end;
|
||||
|
||||
function CheckGDIOBJ(obj: HGDIOBJ): TCocoaGDIObject;
|
||||
begin
|
||||
Result:=TCocoaGDIObject(obj);
|
||||
end;
|
||||
|
||||
{ TCocoaWidgetSet }
|
||||
|
||||
{------------------------------------------------------------------------------
|
||||
@ -450,7 +438,7 @@ begin
|
||||
FillChar(ARawImage, SizeOf(ARawImage), 0);
|
||||
RawImage_DescriptionFromCocoaBitmap(ARawImage.Description, ABitmap);
|
||||
|
||||
{ ARawImage.DataSize := ABitmap.DataSize;
|
||||
ARawImage.DataSize := ABitmap.DataSize;
|
||||
ReAllocMem(ARawImage.Data, ARawImage.DataSize);
|
||||
if ARawImage.DataSize > 0 then
|
||||
System.Move(ABitmap.Data^, ARawImage.Data^, ARawImage.DataSize);
|
||||
@ -472,7 +460,7 @@ begin
|
||||
ARawImage.MaskSize := AMask.DataSize;
|
||||
ReAllocMem(ARawImage.Mask, ARawImage.MaskSize);
|
||||
if ARawImage.MaskSize > 0 then
|
||||
System.Move(AMask.Data^, ARawImage.Mask^, ARawImage.MaskSize);}
|
||||
System.Move(AMask.Data^, ARawImage.Mask^, ARawImage.MaskSize);
|
||||
end;
|
||||
|
||||
function TCocoaWidgetSet.RawImage_DescriptionToBitmapType(
|
||||
|
@ -60,6 +60,9 @@ begin
|
||||
statusitem := bar.statusItemWithLength(NSSquareStatusItemLength);
|
||||
// statusitem.bar := bar;
|
||||
//statusicon.callback:=TLCLCommonCallback.Create(box, AWinControl);
|
||||
|
||||
{ Shows the icon }
|
||||
|
||||
statusitem.retain();
|
||||
if (ATrayIcon.icon <> nil) and (ATrayIcon.icon.Handle <> 0) then
|
||||
begin
|
||||
@ -75,7 +78,6 @@ begin
|
||||
APrivateTrayIcon.item := nil;
|
||||
end;}
|
||||
|
||||
{ Shows the icon }
|
||||
|
||||
{ if APrivateTrayIcon.item <> nil then Exit(True);
|
||||
|
||||
|
@ -371,12 +371,30 @@ end;
|
||||
------------------------------------------------------------------------------}
|
||||
function TCocoaWidgetSet.CreateBitmap(Width, Height: Integer;
|
||||
Planes, BitCount: Longint; BitmapBits: Pointer): HBITMAP;
|
||||
var
|
||||
bmpType: TCocoaBitmapType;
|
||||
begin
|
||||
{$IFDEF VerboseWinAPI}
|
||||
DebugLn('TCocoaWidgetSet.CreateBitmap');
|
||||
{$ENDIF}
|
||||
|
||||
Result := HBITMAP(TCocoaBitmap.Create(Width, Height, BitCount, BitCount, BitmapBits));
|
||||
// WORKAROUND: force context supported depths
|
||||
if BitmapBits = nil then
|
||||
begin
|
||||
if BitCount = 24 then BitCount := 32;
|
||||
// if BitCount = 1 then BitCount := 8;
|
||||
end;
|
||||
|
||||
case BitCount of
|
||||
1: bmpType := cbtMono;
|
||||
8: bmpType := cbtGray;
|
||||
32: bmpType := cbtARGB;
|
||||
else
|
||||
bmpType := cbtRGB;
|
||||
end;
|
||||
|
||||
// winapi Bitmaps are on a word boundary
|
||||
Result := HBITMAP(TCocoaBitmap.Create(Width, Height, BitCount, BitCount, cbaWord, bmpType, BitmapBits));
|
||||
end;
|
||||
|
||||
function TCocoaWidgetSet.CreateRectRgn(X1, Y1, X2, Y2: Integer): HRGN;
|
||||
@ -428,7 +446,7 @@ begin
|
||||
DebugLn('TCocoaWidgetSet.CreateCompatibleBitmap');
|
||||
{$ENDIF}
|
||||
|
||||
Result := HBITMAP(TCocoaBitmap.Create(Width, Height, 32, 32, nil));
|
||||
Result := HBITMAP(TCocoaBitmap.Create(Width, Height, 32, 32, cbaDQWord, cbtARGB, nil));
|
||||
end;
|
||||
|
||||
{------------------------------- SYNC OBJECTS ---------------------------------}
|
||||
|
Loading…
Reference in New Issue
Block a user