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;
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;

View File

@ -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

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_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;

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 }
{------------------------------------------------------------------------------
@ -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(

View File

@ -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);

View File

@ -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 ---------------------------------}