* made the rasterimage rawimage public

git-svn-id: trunk@15850 -
This commit is contained in:
marc 2008-07-23 18:59:53 +00:00
parent 2b8097dfd9
commit 7b10f5086e
3 changed files with 72 additions and 34 deletions

View File

@ -1108,11 +1108,6 @@ type
Handle is interface dependent. Handle is interface dependent.
To access the raw data, see TLazIntfImage in IntfGraphics.pas } To access the raw data, see TLazIntfImage in IntfGraphics.pas }
TBitmapInternalStateFlag = (
bmisCreatingCanvas
);
TBitmapInternalState = set of TBitmapInternalStateFlag;
{ TRasterImage } { TRasterImage }
TRasterImage = class(TGraphic) TRasterImage = class(TGraphic)
@ -1120,7 +1115,10 @@ type
FCanvas: TCanvas; FCanvas: TCanvas;
FTransparentColor: TColor; FTransparentColor: TColor;
FTransparentMode: TTransparentMode; FTransparentMode: TTransparentMode;
FInternalState: TBitmapInternalState; FUpdateCount: Integer;
FUpdateCanvasOnly: Boolean;
procedure CanvasChanging(Sender: TObject);
procedure CreateCanvas; procedure CreateCanvas;
procedure CreateMask(AColor: TColor = clDefault); procedure CreateMask(AColor: TColor = clDefault);
procedure FreeCanvasContext; procedure FreeCanvasContext;
@ -1130,7 +1128,6 @@ type
FSharedImage: TSharedRasterImage; FSharedImage: TSharedRasterImage;
function CanShareImage(AClass: TSharedRasterImageClass): Boolean; virtual; function CanShareImage(AClass: TSharedRasterImageClass): Boolean; virtual;
procedure Changed(Sender: TObject); override; procedure Changed(Sender: TObject); override;
procedure Changing(Sender: TObject); virtual;
function CreateDefaultBitmapHandle(const ADesc: TRawImageDescription): HBITMAP; virtual; abstract; function CreateDefaultBitmapHandle(const ADesc: TRawImageDescription): HBITMAP; virtual; abstract;
procedure Draw(DestCanvas: TCanvas; const DestRect: TRect); override; procedure Draw(DestCanvas: TCanvas; const DestRect: TRect); override;
function GetEmpty: Boolean; override; function GetEmpty: Boolean; override;
@ -1155,11 +1152,11 @@ type
procedure SetBitmapHandle(AValue: HBITMAP); procedure SetBitmapHandle(AValue: HBITMAP);
procedure SetMaskHandle(AValue: HBITMAP); procedure SetMaskHandle(AValue: HBITMAP);
procedure UnshareImage(CopyContent: boolean); virtual; abstract; procedure UnshareImage(CopyContent: boolean); virtual; abstract;
function UpdateHandles(ABitmap, AMask: HBITMAP): Boolean; virtual; abstract; // called when handles are created from rawimage (true whan handle changed) function UpdateHandles(ABitmap, AMask: HBITMAP): Boolean; virtual; abstract; // called when handles are created from rawimage (true when handle changed)
procedure SaveStreamNeeded; procedure SaveStreamNeeded;
procedure FreeSaveStream; procedure FreeSaveStream;
procedure ReadData(Stream: TStream); override; procedure ReadData(Stream: TStream); override;
procedure ReadStream(AStream: TMemoryStream; ASize: Longint); virtual; abstract; // loads imagedata into rawimage, this method shouldn't call changed. procedure ReadStream(AStream: TMemoryStream; ASize: Longint); virtual; abstract; // loads imagedata into rawimage, this method shouldn't call changed().
procedure SetSize(AWidth, AHeight: integer); virtual; abstract; procedure SetSize(AWidth, AHeight: integer); virtual; abstract;
procedure SetHandle(AValue: THandle); virtual; procedure SetHandle(AValue: THandle); virtual;
procedure SetHeight(AHeight: Integer); override; procedure SetHeight(AHeight: Integer); override;
@ -1173,6 +1170,8 @@ type
destructor Destroy; override; destructor Destroy; override;
procedure Assign(Source: TPersistent); override; procedure Assign(Source: TPersistent); override;
procedure Clear; override; procedure Clear; override;
procedure BeginUpdate(ACanvasOnly: Boolean = False);
procedure EndUpdate;
procedure FreeImage; procedure FreeImage;
function BitmapHandleAllocated: boolean; virtual; abstract; function BitmapHandleAllocated: boolean; virtual; abstract;
function MaskHandleAllocated: boolean; virtual; abstract; function MaskHandleAllocated: boolean; virtual; abstract;
@ -1198,6 +1197,7 @@ type
property BitmapHandle: HBITMAP read GetBitmapHandle write SetBitmapHandle; property BitmapHandle: HBITMAP read GetBitmapHandle write SetBitmapHandle;
property MaskHandle: HBITMAP read GetMaskHandle write SetMaskHandle; property MaskHandle: HBITMAP read GetMaskHandle write SetMaskHandle;
property PixelFormat: TPixelFormat read GetPixelFormat write SetPixelFormat default pfDevice; property PixelFormat: TPixelFormat read GetPixelFormat write SetPixelFormat default pfDevice;
property RawImagePtr: PRawImage read GetRawImage; // be carefull with this, modify only within a begin/endupdate
// property ScanLine[Row: Integer]: Pointer; -> Use TLazIntfImage for such things // property ScanLine[Row: Integer]: Pointer; -> Use TLazIntfImage for such things
property TransparentColor: TColor read FTransparentColor property TransparentColor: TColor read FTransparentColor
write SetTransparentColor default clDefault; write SetTransparentColor default clDefault;

View File

@ -27,6 +27,8 @@
constructor TBitmapCanvas.Create(AImage: TRasterImage); constructor TBitmapCanvas.Create(AImage: TRasterImage);
begin begin
inherited Create; inherited Create;
// set FImage after inherited create to make sure that the inherited Create
// won't trigger a call to FImage
FImage := AImage; FImage := AImage;
end; end;

View File

@ -47,25 +47,27 @@ begin
FSharedImage := SrcImage.FSharedImage; FSharedImage := SrcImage.FSharedImage;
FSharedImage.Reference; FSharedImage.Reference;
// We only can share images of the same type. // We only can share images of the same type and when neither we or source is updating
// Since we "share" it first, the unshare code will create a copy // Since we "share" it first, the unshare code will create a copy
if not CanShareImage(SrcImage.GetSharedImageClass) if (FUpdateCount > 0)
or (SrcImage.FUpdateCount > 0)
or not CanShareImage(SrcImage.GetSharedImageClass)
then begin then begin
UnshareImage(True); UnshareImage(True);
FreeSaveStream; FreeSaveStream;
end; end;
end; end;
Changed(Self); if FUpdateCount = 0
then Changed(Self);
Exit; Exit;
end; end;
if Source is TFPCustomImage if Source is TFPCustomImage
then begin then begin
// MWE: no need for a changeall, the sethandles will handle this // todo: base on rawimage
// ChangingAll(Self);
IntfImage := TLazIntfImage.Create(0,0); IntfImage := TLazIntfImage.Create(0,0);
try try
if BitmapHandleAllocated if BitmapHandleAllocated
@ -77,7 +79,8 @@ begin
finally finally
IntfImage.Free; IntfImage.Free;
end; end;
Changed(Self); if FUpdateCount = 0
then Changed(Self);
Exit; Exit;
end; end;
@ -86,13 +89,31 @@ begin
inherited Assign(Source); inherited Assign(Source);
end; end;
procedure TRasterImage.BeginUpdate(ACanvasOnly: Boolean);
begin
if FUpdateCount = 0
then begin
UnshareImage(True);
FUpdateCanvasOnly := ACanvasOnly;
end
else begin
// if we are updating all, then requesting a canvas only won't change it
// if we are updating canvas only, then requesting all is an error
if FUpdateCanvasOnly and not ACanvasOnly
then raise EInvalidGraphicOperation.Create('cannot begin update all when canvas only update in progress');
end;
Inc(FUpdateCount);
end;
procedure TRasterImage.Clear; procedure TRasterImage.Clear;
begin begin
if not Empty then if not Empty then
begin begin
FreeSaveStream; FreeSaveStream;
SetSize(0, 0); SetSize(0, 0);
Changed(Self); if FUpdateCount = 0
then Changed(Self);
end; end;
end; end;
@ -203,6 +224,20 @@ begin
DestCanvas.Changed; DestCanvas.Changed;
end; end;
procedure TRasterImage.EndUpdate;
begin
if FUpdatecount = 0
then raise EInvalidGraphicOperation.Create('Endupdate while no update in progress');
Dec(FUpdatecount);
if FUpdatecount > 0 then Exit;
if not FUpdateCanvasOnly
then FreeCanvasContext;
FreeSaveStream;
Changed(Self);
end;
constructor TRasterImage.Create; constructor TRasterImage.Create;
begin begin
inherited Create; inherited Create;
@ -236,16 +271,10 @@ end;
procedure TRasterImage.CreateCanvas; procedure TRasterImage.CreateCanvas;
begin begin
if FCanvas <> nil then Exit; if FCanvas <> nil then Exit;
if bmisCreatingCanvas in FInternalState then Exit;
Include(FInternalState, bmisCreatingCanvas); FCanvas := TBitmapCanvas.Create(Self);
try FCanvas.OnChanging := @CanvasChanging;
FCanvas := TBitmapCanvas.Create(Self); FCanvas.OnChange := @Changed;
FCanvas.OnChanging := @Changing;
FCanvas.OnChange := @Changed;
finally
Exclude(FInternalState,bmisCreatingCanvas);
end;
end; end;
procedure TRasterImage.FreeImage; procedure TRasterImage.FreeImage;
@ -319,6 +348,8 @@ end;
procedure TRasterImage.Changed(Sender: TObject); procedure TRasterImage.Changed(Sender: TObject);
begin begin
if FUpdateCount > 0 then Exit;
//FMaskBitsValid := False; //FMaskBitsValid := False;
if Sender = FCanvas if Sender = FCanvas
then FreeSaveStream; then FreeSaveStream;
@ -326,15 +357,14 @@ begin
inherited Changed(Sender); inherited Changed(Sender);
end; end;
procedure TRasterImage.Changing(Sender: TObject); procedure TRasterImage.CanvasChanging(Sender: TObject);
begin begin
// called before the bitmap is modified if FUpdateCount > 0 then Exit;
// called before the canvas is modified
// -> make sure the handle is unshared (otherwise the modifications will also // -> make sure the handle is unshared (otherwise the modifications will also
// modify all copies) // modify all copies)
// -> When canvas changing: Savestream will be freed when changed (so it can // -> Savestream will be freed when changed (so it can be loaded by canvas)
// be loaded by canvas)
if Sender <> FCanvas
then FreeSaveStream;
UnshareImage(True); UnshareImage(True);
end; end;
@ -380,7 +410,8 @@ begin
// if something went wrong, free the workstream // if something went wrong, free the workstream
WorkStream.Free; WorkStream.Free;
end; end;
Changed(Self); if FUpdateCount = 0
then Changed(Self);
end; end;
procedure TRasterImage.GetSupportedSourceMimeTypes(List: TStrings); procedure TRasterImage.GetSupportedSourceMimeTypes(List: TStrings);
@ -509,7 +540,8 @@ begin
FreeCanvasContext; FreeCanvasContext;
UnshareImage(False); UnshareImage(False);
FSharedImage.FHandle := AValue; FSharedImage.FHandle := AValue;
Changed(Self); if FUpdateCount = 0
then Changed(Self);
end; end;
procedure TRasterImage.SetMaskHandle(AValue: HBITMAP); procedure TRasterImage.SetMaskHandle(AValue: HBITMAP);
@ -546,6 +578,10 @@ procedure TRasterImage.SaveStreamNeeded;
var var
WorkStream: TMemoryStream; WorkStream: TMemoryStream;
begin begin
if FUpdateCount > 0
then raise EInvalidGraphicOperation.Create('Cannot save image wile update in progress');
if FSharedImage.SaveStream <> nil then Exit; if FSharedImage.SaveStream <> nil then Exit;
WorkStream := TMemoryStream.Create; WorkStream := TMemoryStream.Create;