From cc68709d1484d51c777ce719a9f8345abb9889b2 Mon Sep 17 00:00:00 2001 From: dmitry Date: Wed, 31 Mar 2010 22:05:07 +0000 Subject: [PATCH] carbon: improved FloodFill implementation git-svn-id: trunk@24322 - --- lcl/interfaces/carbon/carbongdiobjects.pp | 86 ++++++++++++++--------- lcl/interfaces/carbon/carbonwinapi.inc | 8 ++- 2 files changed, 59 insertions(+), 35 deletions(-) diff --git a/lcl/interfaces/carbon/carbongdiobjects.pp b/lcl/interfaces/carbon/carbongdiobjects.pp index 5b63a0b8a4..7c3160e3ac 100644 --- a/lcl/interfaces/carbon/carbongdiobjects.pp +++ b/lcl/interfaces/carbon/carbongdiobjects.pp @@ -172,6 +172,9 @@ type procedure GetRGBA(AROP2: Integer; out AR, AG, AB, AA: Single); function CreateCGColor: CGColorRef; + property Red: Byte read FR write FR; + property Green: Byte read FG write FG; + property Blue: Byte read FB write FB; property Solid: Boolean read FA write FA; property ColorRef: TColorRef read GetColorRef; end; @@ -2434,7 +2437,15 @@ begin else Result:=PByteArray(@PByteArray(Bitmap.Data)^[ Bitmap.BytesPerRow*Line ]); end; -procedure GetRGBA24(Bitmap: TCarbonBitmap; X,Y: Integer; var r,g,b,a: Byte); +type + TColorPos = record + ri : Byte; + gi : Byte; + bi : Byte; + ai : Byte; + end; + +procedure GetRGBA24(Bitmap: TCarbonBitmap; X,Y: Integer; var r,g,b,a: Byte; const pos: TColorPos); var line : PByteArray; begin @@ -2443,24 +2454,24 @@ begin r:=0;g:=0;b:=0;a:=$FF; Exit; end; - r:=line^[x*3+0]; - g:=line^[x*3+1]; - b:=line^[x*3+2]; + r:=line^[x*3+pos.ri]; + g:=line^[x*3+pos.gi]; + b:=line^[x*3+pos.bi]; a:=255; end; -procedure SetRGBA24(Bitmap: TCarbonBitmap; X,Y: Integer; r,g,b,a: Byte); +procedure SetRGBA24(Bitmap: TCarbonBitmap; X,Y: Integer; r,g,b,a: Byte; const pos: TColorPos); var line : PByteArray; begin line:=GetScanLine(Bitmap, Y); if not Assigned(line) then Exit; - line^[x*3+0]:=r; - line^[x*3+1]:=g; - line^[x*3+2]:=b; + line^[x*3+pos.ri]:=r; + line^[x*3+pos.gi]:=g; + line^[x*3+pos.bi]:=b; end; -procedure GetRGBA32(Bitmap: TCarbonBitmap; X,Y: Integer; var r,g,b,a: Byte); +procedure GetRGBA32(Bitmap: TCarbonBitmap; X,Y: Integer; var r,g,b,a: Byte; const pos: TColorPos); var line : PByteArray; begin @@ -2469,26 +2480,27 @@ begin r:=0;g:=0;b:=0;a:=$FF; Exit; end; - r:=line^[x*4+0]; - g:=line^[x*4+1]; - b:=line^[x*4+2]; - a:=line^[x*4+3]; + r:=line^[x*4+pos.ri]; + g:=line^[x*4+pos.gi]; + b:=line^[x*4+pos.bi]; + a:=line^[x*4+pos.ai]; end; -procedure SetRGBA32(Bitmap: TCarbonBitmap; X,Y: Integer; r,g,b,a: Byte); +procedure SetRGBA32(Bitmap: TCarbonBitmap; X,Y: Integer; r,g,b,a: Byte; const pos: TColorPos); var line : PByteArray; begin line:=GetScanLine(Bitmap, Y); if not Assigned(line) then Exit; - line^[x*4+0]:=r; - line^[x*4+1]:=g; - line^[x*4+2]:=b; - line^[x*4+3]:=a; + line^[x*4+pos.ri]:=r; + line^[x*4+pos.gi]:=g; + line^[x*4+pos.bi]:=b; + line^[x*4+pos.ai]:=a; end; //todo: add support for non 24-32 bit images //todo: faster and better code! +//todo: support for iBorderColor (currently ignored both ABorderColor and isBorderColor settings) function FloodFillBitmap(const Bitmap: TCarbonBitmap; X,Y: Integer; ABorderColor, FillColor: TColor; isBorderColor: Boolean): Boolean; var sr, sg, sb, sa : Byte; @@ -2498,12 +2510,15 @@ var cnt : Integer; i,j : Integer; k : Integer; + clpos : TColorPos; +const + LEPos : TColorPos = (ri:1;gi:2;bi:3;ai:0); const dx : array [0..3] of Integer = (-1,1,0,0); dy : array [0..3] of Integer = (0,0,-1,1); var - GetRGBA: procedure (Bitmap: TCarbonBitmap; X,Y: Integer; var r,g,b,a: Byte); - SetRGBA: procedure (Bitmap: TCarbonBitmap; X,Y: Integer; r,g,b,a: Byte); + GetRGBA: procedure (Bitmap: TCarbonBitmap; X,Y: Integer; var r,g,b,a: Byte; const pos: TColorPos); + SetRGBA: procedure (Bitmap: TCarbonBitmap; X,Y: Integer; r,g,b,a: Byte; const pos: TColorPos); begin FillColor:=ColorToRGB(FillColor); r:=FillColor and $FF; @@ -2512,12 +2527,15 @@ begin a:=$FF; GetRGBA:=nil; SetRGBA:=nil; - if Bitmap.BitsPerComponent=8 then begin - //todo: Little endian, big endian - if Bitmap.FBitsPerPixel=32 then begin + clpos:=LEPos; //todo: Little endian, big endian or bitmap specific + if Bitmap.BitsPerComponent=8 then + begin + if Bitmap.FBitsPerPixel=32 then + begin GetRGBA:=@GetRGBA32; SetRGBA:=@SetRGBA32; - end else begin + end else + begin GetRGBA:=@GetRGBA24; SetRGBA:=@SetRGBA24; end; @@ -2526,25 +2544,29 @@ begin if not Result then Exit; try - GetRGBA(Bitmap, x,y, sr, sg, sb, sa); + GetRGBA(Bitmap, x,y, sr, sg, sb, sa, clpos); if (sr=r) and (sg=g) and (sb=b) then Exit; SetLength(data, Bitmap.Width*Bitmap.Height); cnt:=1; data[0].x:=x; data[0].y:=y; - SetRGBA(Bitmap, x,y, r, g, b, a); + SetRGBA(Bitmap, x,y, r, g, b, a, clPos); - while cnt>0 do begin + while cnt>0 do + begin x:=data[0].x; y:=data[0].y; - for k:=0 to 3 do begin + for k:=0 to 3 do + begin i:=x+dx[k]; j:=y+dy[k]; - for j:=Max(0, y-1) to Min(Bitmap.Height-1, y+1) do begin - GetRGBA(Bitmap, i,j, tr, tg, tb, ta); - if (tr=sr) and (tg=sg) and (tb=sb) then begin - SetRGBA(Bitmap, i,j, r, g, b, a); + for j:=Max(0, y-1) to Min(Bitmap.Height-1, y+1) do + begin + GetRGBA(Bitmap, i,j, tr, tg, tb, ta, clPos); + if (tr=sr) and (tg=sg) and (tb=sb) then + begin + SetRGBA(Bitmap, i,j, r, g, b, a, clPos); data[cnt].X:=i; data[cnt].Y:=j; inc(cnt); diff --git a/lcl/interfaces/carbon/carbonwinapi.inc b/lcl/interfaces/carbon/carbonwinapi.inc index 4b138579b2..ecf19e6a69 100644 --- a/lcl/interfaces/carbon/carbonwinapi.inc +++ b/lcl/interfaces/carbon/carbonwinapi.inc @@ -1009,9 +1009,11 @@ begin try Result:=TCarbonDeviceContext(DC) is TCarbonBitmapContext; if not Result then Exit; - TCarbonBrush(Brush).GetRGBA(R2_COPYPEN,r,g,b,a); - Result:=FloodFillBitmap( TCarbonBitmapContext(DC).Bitmap, - X, Y, 0, RGBToColor(round(r*255),round(g*255),round(b*255)), True); + with TCarbonBrush(Brush) do + begin + Result:=FloodFillBitmap( TCarbonBitmapContext(DC).Bitmap, + X, Y, 0, RGBToColor(Red,Green,Blue), True); + end; except Result:=False; end;