lcl-cocoa: Fixes TBitBtn.Glyph, the image data was being freed together with the glyph TBitmap

git-svn-id: trunk@46620 -
This commit is contained in:
sekelsenmat 2014-10-20 06:01:39 +00:00
parent 2767f20b23
commit f1c6358aeb
7 changed files with 64 additions and 14 deletions

View File

@ -203,6 +203,7 @@ type
TCocoaBitmap = class(TCocoaGDIObject)
strict private
FData: Pointer;
FOriginalData: PByte; // Exists and is set in case the data needed pre-multiplication
FAlignment: TCocoaBitmapAlignment;
FFreeData: Boolean;
FDataSize: Integer;
@ -218,7 +219,6 @@ type
FImage: NSImage;
FImagerep: NSBitmapImageRep;
function GetColorSpace: NSString;
procedure PreMultiplyAlpha();
function DebugShowData(): string;
public
constructor Create(ABitmap: TCocoaBitmap);
@ -232,6 +232,8 @@ type
function CreateSubImage(const ARect: TRect): CGImageRef;
function CreateMaskImage(const ARect: TRect): CGImageRef;
procedure PreMultiplyAlpha();
function GetNonPreMultipliedData(): PByte;
public
property BitmapType: TCocoaBitmapType read FType;
property BitsPerPixel: Byte read FBitsPerPixel;
@ -749,8 +751,10 @@ begin
HasAlpha := AType in [cbtARGB, cbtRGBA];
// Non premultiplied bitmaps can't be used for bitmap context
// So we need to pre-multiply ourselves
PreMultiplyAlpha();
// So we need to pre-multiply ourselves, but only if we were allowed
// to copy the data, otherwise we might corrupt the original
if ACopyData then
PreMultiplyAlpha();
BitmapFormat := 0;
if AType in [cbtARGB, cbtRGB] then
BitmapFormat := BitmapFormat or NSAlphaFirstBitmapFormat;
@ -789,6 +793,8 @@ destructor TCocoaBitmap.Destroy;
begin
image.release;
if FFreeData then System.FreeMem(FData);
if FOriginalData <> nil then
System.FreeMem(FOriginalData);
inherited Destroy;
end;
@ -890,6 +896,7 @@ begin
Result := NSCalibratedRGBColorSpace;
end;
// Cocoa cannot create a context unless the image has alpha pre-multiplied
procedure TCocoaBitmap.PreMultiplyAlpha;
var
lByteData: PByte;
@ -897,6 +904,16 @@ var
lAlpha, lRed, lGreen, lBlue: Byte;
begin
if not (FType in [cbtARGB, cbtRGBA]) then Exit;
if FData = nil then Exit;
// Keep the original data in a copy, otherwise we cant get access to it
// because pre-multiplying destroys the original value if we had alpha=0
if FOriginalData <> nil then
System.FreeMem(FOriginalData);
System.GetMem(FOriginalData, FDataSize);
System.Move(FData^, FOriginalData^, FDataSize); // copy data
// Pre-Multiply
lByteData := PByte(FData);
i := 0;
while i < FDataSize -1 do
@ -928,10 +945,22 @@ begin
end;
end;
// The Alpha pre-multiplication will prevent us from obtaining the original image
// raw data for the function RawImage_FromCocoaBitmap,
// so we need to store it
function TCocoaBitmap.GetNonPreMultipliedData(): PByte;
begin
if FOriginalData <> nil then
Result := FOriginalData
else
Result := PByte(FData);
end;
function TCocoaBitmap.DebugShowData: string;
var
i: Integer;
begin
Result := '';
for i := 0 to FDataSize -1 do
begin
Result := Result + IntToHex(PByte(FData)[i], 2);
@ -1823,7 +1852,7 @@ var
begin
if Style = bvRaised then
begin
GetHiThemeMetric(kThemeMetricPrimaryGroupBoxContentInset, D);
D := GetHiThemeMetric(kThemeMetricPrimaryGroupBoxContentInset);
// draw frame as group box
DrawInfo.version := 0;

View File

@ -585,19 +585,22 @@ begin
end;
{------------------------------------------------------------------------------
Method: TCarbonWidgetSet.RawImage_FromCarbonBitmap
Method: TCocoaWidgetSet.RawImage_FromCocoaBitmap
Creates a rawimage description for a carbonbitmap
Creates a rawimage description for a cocoabitmap
------------------------------------------------------------------------------}
function TCocoaWidgetSet.RawImage_FromCocoaBitmap(out ARawImage: TRawImage; ABitmap, AMask: TCocoaBitmap; ARect: PRect = nil): Boolean;
var
lBitmapData: PByte;
begin
FillChar(ARawImage, SizeOf(ARawImage), 0);
RawImage_DescriptionFromCocoaBitmap(ARawImage.Description, ABitmap);
ARawImage.DataSize := ABitmap.DataSize;
ReAllocMem(ARawImage.Data, ARawImage.DataSize);
lBitmapData := ABitmap.GetNonPreMultipliedData();
if ARawImage.DataSize > 0 then
System.Move(ABitmap.Data^, ARawImage.Data^, ARawImage.DataSize);
System.Move(lBitmapData^, ARawImage.Data^, ARawImage.DataSize);
Result := True;

View File

@ -29,7 +29,7 @@ uses
// Libs
MacOSAll, CocoaAll, CocoaUtils, CocoaGDIObjects,
// LCL
LMessages, LCLMessageGlue, ExtCtrls,
LMessages, LCLMessageGlue, ExtCtrls, Graphics,
LCLType, LCLProc, Controls, ComCtrls;
type
@ -216,6 +216,8 @@ type
procedure frameDidChange(sender: NSNotification); message 'frameDidChange:';
public
callback: IButtonCallback;
Glyph: TBitmap;
procedure dealloc; override;
function initWithFrame(frameRect: NSRect): id; override;
function acceptsFirstResponder: Boolean; override;
function becomeFirstResponder: Boolean; override;
@ -236,7 +238,6 @@ type
procedure mouseMoved(event: NSEvent); override;
procedure resetCursorRects; override;
function lclIsHandle: Boolean; override;
end;
TCocoaFieldEditor = objcclass;
@ -1425,6 +1426,14 @@ begin
callback.frameDidChange;
end;
procedure TCocoaButton.dealloc;
begin
if Assigned(Glyph) then
FreeAndNil(Glyph);
inherited dealloc;
end;
function TCocoaButton.initWithFrame(frameRect: NSRect): id;
begin
Result := inherited initWithFrame(frameRect);
@ -1581,6 +1590,7 @@ end;
function TCocoaTextField.RealResignFirstResponder: Boolean;
begin
callback.ResignFirstResponder;
Result := True;
end;
// Do not propagate this event to the LCL,
@ -1709,6 +1719,7 @@ end;
function TCocoaSecureTextField.RealResignFirstResponder: Boolean;
begin
callback.ResignFirstResponder;
Result := True;
end;
function TCocoaSecureTextField.resignFirstResponder: Boolean;
@ -2504,7 +2515,7 @@ end;
function TCocoaTabControl.tabView_shouldSelectTabViewItem(tabView: NSTabView;
tabViewItem: NSTabViewItem): Boolean;
begin
Result := True;
end;
procedure TCocoaTabControl.tabView_willSelectTabViewItem(tabView: NSTabView;

View File

@ -1710,7 +1710,8 @@ end;
function TCocoaWidgetSet.SetCapture(AHandle: HWND): HWND;
begin
FCaptureControl:= AHandle;
Result := FCaptureControl;
FCaptureControl := AHandle;
end;
function TCocoaWidgetSet.SetCaretPos(X, Y: Integer): Boolean;
@ -1750,6 +1751,7 @@ end;
function TCocoaWidgetSet.ReleaseCapture : Boolean;
begin
FCaptureControl:=0;
Result := True;
end;
function TCocoaWidgetSet.ReleaseDC(hWnd: HWND; DC: HDC): Integer;

View File

@ -111,7 +111,9 @@ begin
lButtonHandle := TCocoaButton(ABitBtn.Handle);
lButtonHandle.setImage(Img);
lButtonHandle.setImagePosition(LCLGlyphPosToCocoa(ABitBtn.Layout));
AGlyph.Free;
if Assigned(lButtonHandle.Glyph) then
FreeAndNil(lButtonHandle.Glyph);
lButtonHandle.Glyph := AGlyph;
end;
end;

View File

@ -459,6 +459,7 @@ var
function LCLCharToMacEvent(const AUTF8Char: AnsiString): Boolean;
begin
Result := False;
if AUTF8Char = '' then
Exit;
// TODO

View File

@ -590,8 +590,10 @@ end;
class function TCocoaWSCustomForm.GetClientBounds(const AWinControl: TWinControl; var ARect: TRect): Boolean;
begin
if AWinControl.HandleAllocated then
ARect := NSObject(AWinControl.Handle).lclClientFrame;
Result := False;
if not AWinControl.HandleAllocated then Exit;
ARect := NSObject(AWinControl.Handle).lclClientFrame;
Result := True;
end;
class function TCocoaWSCustomForm.GetClientRect(const AWinControl: TWinControl; var ARect: TRect): Boolean;