mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-06-01 15:52:32 +02:00
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:
parent
2767f20b23
commit
f1c6358aeb
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -459,6 +459,7 @@ var
|
||||
|
||||
function LCLCharToMacEvent(const AUTF8Char: AnsiString): Boolean;
|
||||
begin
|
||||
Result := False;
|
||||
if AUTF8Char = '' then
|
||||
Exit;
|
||||
// TODO
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user