Cocoa: Advances the bitmap code

git-svn-id: trunk@31449 -
This commit is contained in:
sekelsenmat 2011-06-29 07:04:24 +00:00
parent ddcae0f6ae
commit 1a26b03f11
6 changed files with 186 additions and 61 deletions

View File

@ -14,6 +14,14 @@ uses
Classes, Types; Classes, Types;
type 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 = ( TCocoaBitmapType = (
cbtMono, // mask or mono bitmap cbtMono, // mask or mono bitmap
cbtGray, // grayscale 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) cbtBGRA // color bitmap with alpha channel 8-8-8-8 B-G-R-A (windows compatible)
); );
const
cbtMask = cbtMono;
type
{ TCocoaGDIObject } { TCocoaGDIObject }
TCocoaGDIObject = class(TObject) TCocoaGDIObject = class(TObject)
@ -91,14 +103,40 @@ type
TCocoaBitmap = class(TCocoaGDIObject) TCocoaBitmap = class(TCocoaGDIObject)
private private
FData: Pointer;
FAlignment: TCocoaBitmapAlignment;
FFreeData: Boolean;
FDataSize: Integer;
FBytesPerRow: Integer;
FDepth: Byte;
FBitsPerPixel: Byte;
FWidth: Integer;
FHeight: Integer;
FType: TCocoaBitmapType; FType: TCocoaBitmapType;
// Cocoa information
FbitsPerSample: NSInteger; // How many bits in each color component
FsamplesPerPixel: NSInteger;// How many color components
public public
image: NSImage; image: NSImage;
imagerep: NSBitmapImageRep; imagerep: NSBitmapImageRep;
constructor Create(AWidth, AHeight, ADepth, ABitsPerPixel: Integer; constructor Create(AWidth, AHeight, ADepth, ABitsPerPixel: Integer;
AAlignment: TCocoaBitmapAlignment; AType: TCocoaBitmapType;
AData: Pointer; ACopyData: Boolean = True); AData: Pointer; ACopyData: Boolean = True);
destructor Destroy; override;
procedure SetInfo(AWidth, AHeight, ADepth, ABitsPerPixel: Integer;
AAlignment: TCocoaBitmapAlignment; AType: TCocoaBitmapType);
public public
// property BitsPerComponent: Integer read GetBitsPerComponent;
property BitmapType: TCocoaBitmapType read FType; 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; end;
{ TCocoaTextLayout } { TCocoaTextLayout }
@ -161,8 +199,29 @@ type
var var
TextLayoutClass : TCocoaTextLayoutClass = nil; TextLayoutClass : TCocoaTextLayoutClass = nil;
function CheckDC(dc: HDC): TCocoaContext;
function CheckGDIOBJ(obj: HGDIOBJ): TCocoaGDIObject;
function CheckBitmap(ABitmap: HBITMAP; AStr: string): Boolean;
implementation 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 } { TCocoaBitmap }
type type
@ -186,52 +245,43 @@ type
// ABytesPerRow - The number of bytes between rows // ABytesPerRow - The number of bytes between rows
ACopyData - Copy supplied bitmap data (OPTIONAL) 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, constructor TCocoaBitmap.Create(AWidth, AHeight, ADepth, ABitsPerPixel: Integer;
ABitsPerPixel: Integer; AData: Pointer; ACopyData: Boolean); AAlignment: TCocoaBitmapAlignment; AType: TCocoaBitmapType;
var AData: Pointer; ACopyData: Boolean);
bitsPerSample: NSInteger; // How many bits in each color component
samplesPerPixel: NSInteger;// How many color components
begin begin
case ABitsPerPixel of SetInfo(AWidth, AHeight, ADepth, ABitsPerPixel, AAlignment, AType);
// Mono
1: // Copy the image data, if necessary
begin if (AData = nil) or ACopyData then
bitsPerSample := 1; begin
samplesPerPixel := 1; System.GetMem(FData, FDataSize);
end; FFreeData := True;
// Gray scale if AData <> nil then
8: System.Move(AData^, FData^, FDataSize) // copy data
begin else
bitsPerSample := 8; FillDWord(FData^, FDataSize shr 2, 0); // clear bitmap
samplesPerPixel := 1; end
end;
// ARGB
32:
begin
bitsPerSample := 8;
samplesPerPixel := 4;
end;
else else
// Other RGB begin
bitsPerSample := bitsPerSample div 3; FData := AData;
samplesPerPixel := 3; FFreeData := False;
end; end;
// Create the associated NSImageRep // Create the associated NSImageRep
imagerep := NSBitmapImageRep(NSBitmapImageRep.alloc.initWithBitmapDataPlanes_pixelsWide_pixelsHigh__colorSpaceName_bitmapFormat_bytesPerRow_bitsPerPixel( imagerep := NSBitmapImageRep(NSBitmapImageRep.alloc.initWithBitmapDataPlanes_pixelsWide_pixelsHigh__colorSpaceName_bitmapFormat_bytesPerRow_bitsPerPixel(
@AData, // planes, BitmapDataPlanes @FData, // planes, BitmapDataPlanes
AWidth, // width, pixelsWide FWidth, // width, pixelsWide
AHeight,// height, PixelsHigh FHeight,// height, PixelsHigh
bitsPerSample,// bitsPerSample, bps FbitsPerSample,// bitsPerSample, bps
samplesPerPixel, // samplesPerPixel, sps FsamplesPerPixel, // samplesPerPixel, sps
False, // hasAlpha False, // hasAlpha
False, // isPlanar False, // isPlanar
NSCalibratedRGBColorSpace, // colorSpaceName NSCalibratedRGBColorSpace, // colorSpaceName
0, // bitmapFormat 0, // bitmapFormat
0, // bytesPerRow 0, // bytesPerRow
ABitsPerPixel //bitsPerPixel FBitsPerPixel //bitsPerPixel
)); ));
// Create the associated NSImage // Create the associated NSImage
@ -239,6 +289,73 @@ begin
image.addRepresentation(imagerep); image.addRepresentation(imagerep);
end; 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 } { TCocoaContext }
function TCocoaContext.CGContext:CGContextRef; function TCocoaContext.CGContext:CGContextRef;

View File

@ -363,8 +363,8 @@ end; {TCarbonWidgetSet.PromptUser}*)
------------------------------------------------------------------------------} ------------------------------------------------------------------------------}
function TCocoaWidgetSet.RawImage_CreateBitmaps(const ARawImage: TRawImage; out ABitmap, AMask: HBitmap; ASkipMask: Boolean): Boolean; function TCocoaWidgetSet.RawImage_CreateBitmaps(const ARawImage: TRawImage; out ABitmap, AMask: HBitmap; ASkipMask: Boolean): Boolean;
{const const
ALIGNMAP: array[TRawImageLineEnd] of TCarbonBitmapAlignment = (cbaByte, cbaByte, cbaWord, cbaDWord, cbaQWord, cbaDQWord);} ALIGNMAP: array[TRawImageLineEnd] of TCocoaBitmapAlignment = (cbaByte, cbaByte, cbaWord, cbaDWord, cbaQWord, cbaDQWord);
var var
ADesc: TRawImageDescription absolute ARawImage.Description; ADesc: TRawImageDescription absolute ARawImage.Description;
bmpType: TCocoaBitmapType; 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]); 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; exit;
end; 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) if ASkipMask or (ADesc.MaskBitsPerPixel = 0)
then AMask := 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; Result := True;
end; end;
@ -423,7 +423,7 @@ begin
end; end;
Result := True; Result := True;
end; end;*)
{------------------------------------------------------------------------------ {------------------------------------------------------------------------------
Function: RawImage_FromBitmap Function: RawImage_FromBitmap
@ -435,14 +435,14 @@ end;
Creates a raw image from the specified bitmap 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 begin
if CheckBitmap(ABitmap, 'RawImage_FromBitmap') if CheckBitmap(ABitmap, 'RawImage_FromBitmap')
and ((AMask = 0) or CheckBitmap(AMask, 'RawImage_FromBitmap (mask)')) 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; else Result := False;
end; end;
(*
{------------------------------------------------------------------------------ {------------------------------------------------------------------------------
Function: RawImage_FromDevice Function: RawImage_FromDevice
Params: ARawImage: Image to create Params: ARawImage: Image to create

View File

@ -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_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_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_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 // override only when queried formats are different from screen description
//function RawImage_QueryDescription(AFlags: TRawImageQueryFlags; var ADesc: TRawImageDescription): Boolean; override; //function RawImage_QueryDescription(AFlags: TRawImageQueryFlags; var ADesc: TRawImageDescription): Boolean; override;

View File

@ -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 } { TCocoaWidgetSet }
{------------------------------------------------------------------------------ {------------------------------------------------------------------------------
@ -450,7 +438,7 @@ begin
FillChar(ARawImage, SizeOf(ARawImage), 0); FillChar(ARawImage, SizeOf(ARawImage), 0);
RawImage_DescriptionFromCocoaBitmap(ARawImage.Description, ABitmap); RawImage_DescriptionFromCocoaBitmap(ARawImage.Description, ABitmap);
{ ARawImage.DataSize := ABitmap.DataSize; ARawImage.DataSize := ABitmap.DataSize;
ReAllocMem(ARawImage.Data, ARawImage.DataSize); ReAllocMem(ARawImage.Data, ARawImage.DataSize);
if ARawImage.DataSize > 0 then if ARawImage.DataSize > 0 then
System.Move(ABitmap.Data^, ARawImage.Data^, ARawImage.DataSize); System.Move(ABitmap.Data^, ARawImage.Data^, ARawImage.DataSize);
@ -472,7 +460,7 @@ begin
ARawImage.MaskSize := AMask.DataSize; ARawImage.MaskSize := AMask.DataSize;
ReAllocMem(ARawImage.Mask, ARawImage.MaskSize); ReAllocMem(ARawImage.Mask, ARawImage.MaskSize);
if ARawImage.MaskSize > 0 then if ARawImage.MaskSize > 0 then
System.Move(AMask.Data^, ARawImage.Mask^, ARawImage.MaskSize);} System.Move(AMask.Data^, ARawImage.Mask^, ARawImage.MaskSize);
end; end;
function TCocoaWidgetSet.RawImage_DescriptionToBitmapType( function TCocoaWidgetSet.RawImage_DescriptionToBitmapType(

View File

@ -60,6 +60,9 @@ begin
statusitem := bar.statusItemWithLength(NSSquareStatusItemLength); statusitem := bar.statusItemWithLength(NSSquareStatusItemLength);
// statusitem.bar := bar; // statusitem.bar := bar;
//statusicon.callback:=TLCLCommonCallback.Create(box, AWinControl); //statusicon.callback:=TLCLCommonCallback.Create(box, AWinControl);
{ Shows the icon }
statusitem.retain(); statusitem.retain();
if (ATrayIcon.icon <> nil) and (ATrayIcon.icon.Handle <> 0) then if (ATrayIcon.icon <> nil) and (ATrayIcon.icon.Handle <> 0) then
begin begin
@ -75,7 +78,6 @@ begin
APrivateTrayIcon.item := nil; APrivateTrayIcon.item := nil;
end;} end;}
{ Shows the icon }
{ if APrivateTrayIcon.item <> nil then Exit(True); { if APrivateTrayIcon.item <> nil then Exit(True);

View File

@ -371,12 +371,30 @@ end;
------------------------------------------------------------------------------} ------------------------------------------------------------------------------}
function TCocoaWidgetSet.CreateBitmap(Width, Height: Integer; function TCocoaWidgetSet.CreateBitmap(Width, Height: Integer;
Planes, BitCount: Longint; BitmapBits: Pointer): HBITMAP; Planes, BitCount: Longint; BitmapBits: Pointer): HBITMAP;
var
bmpType: TCocoaBitmapType;
begin begin
{$IFDEF VerboseWinAPI} {$IFDEF VerboseWinAPI}
DebugLn('TCocoaWidgetSet.CreateBitmap'); DebugLn('TCocoaWidgetSet.CreateBitmap');
{$ENDIF} {$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; end;
function TCocoaWidgetSet.CreateRectRgn(X1, Y1, X2, Y2: Integer): HRGN; function TCocoaWidgetSet.CreateRectRgn(X1, Y1, X2, Y2: Integer): HRGN;
@ -428,7 +446,7 @@ begin
DebugLn('TCocoaWidgetSet.CreateCompatibleBitmap'); DebugLn('TCocoaWidgetSet.CreateCompatibleBitmap');
{$ENDIF} {$ENDIF}
Result := HBITMAP(TCocoaBitmap.Create(Width, Height, 32, 32, nil)); Result := HBITMAP(TCocoaBitmap.Create(Width, Height, 32, 32, cbaDQWord, cbtARGB, nil));
end; end;
{------------------------------- SYNC OBJECTS ---------------------------------} {------------------------------- SYNC OBJECTS ---------------------------------}