lcl: apply Mark patch

- CreateCompatibleBitmaps
  - separate MaskHandleNeeded of icon from BitmapHandleNeeded
  - simplify TRasterImage.BitmapHandleNeeded
from me:
  - fix TRawImageLineStarts.GetPosition

git-svn-id: trunk@16262 -
This commit is contained in:
paul 2008-08-27 02:47:30 +00:00
parent 09225df31f
commit d173c2f1ae
4 changed files with 117 additions and 274 deletions

View File

@ -12,7 +12,7 @@
* *
* This file is part of the Lazarus Component Library (LCL) *
* *
* See the file COPYING.modifiedLGPL.txt, included in this distribution, *
* See the file COPYING.modifiedLGPL.txt, included in this distribution, *
* for details about the copyright. *
* *
* This program is distributed in the hope that it will be useful, *
@ -1892,6 +1892,76 @@ begin
CB.Free;
end;
//TODO: publish ?? (as RawImage_CreateCompatibleBitmaps)
function CreateCompatibleBitmaps(const ARawImage: TRawImage; out ABitmap, AMask: HBitmap; ASkipMask: Boolean = False): Boolean;
var
Desc: TRawImageDescription absolute ARawimage.Description;
ImgHandle, ImgMaskHandle: HBitmap;
ImagePtr: PRawImage;
DevImage: TRawImage;
DevDesc: TRawImageDescription;
SrcImage, DstImage: TLazIntfImage;
QueryFlags: TRawImageQueryFlags;
W, H: Integer;
begin
ImgMaskHandle := 0;
W := Desc.Width;
if W < 1 then W := 1;
H := Desc.Height;
if H < 1 then H := 1;
if Desc.Depth = 1
then QueryFlags := [riqfMono]
else QueryFlags := [riqfRGB];
if Desc.AlphaPrec <> 0
then Include(QueryFlags, riqfAlpha);
if Desc.MaskBitsPerPixel <> 0
then Include(QueryFlags, riqfMask);
QueryDescription(DevDesc, QueryFlags, W, H);
if DevDesc.IsEqual(Desc)
then begin
// image is compatible, so use it
DstImage := nil;
ImagePtr := @ARawImage;
end
else begin
// create compatible copy
SrcImage := TLazIntfImage.Create(ARawImage, False);
DstImage := TLazIntfImage.Create(0, 0);
// create mask for alphachannel when device has no alpha support
if (DevDesc.AlphaPrec = 0) and (riqfAlpha in QueryFlags)
then begin
//add mask if not already queried
if not (riqfMask in QueryFlags)
then QueryDescription(DevDesc, [riqfMask, riqfUpdate]);
DstImage.DataDescription := DevDesc;
DstImage.CopyPixels(SrcImage, 0, 0, True, $8000);
end
else begin
DstImage.DataDescription := DevDesc;
DstImage.CopyPixels(SrcImage);
end;
SrcImage.Free;
DstImage.GetRawImage(DevImage);
ImagePtr := @DevImage;
end;
try
Result := RawImage_CreateBitmaps(ImagePtr^, ImgHandle, ImgMaskHandle, ASkipMask);
if not Result then Exit;
ABitmap := ImgHandle;
if not ASkipMask
then AMask := ImgMaskHandle;
finally
DstImage.Free;
end;
end;
procedure Register;
begin
RegisterClasses([TBitmap,TPixmap,TPortableNetworkGraphic,

View File

@ -1572,7 +1572,7 @@ var
BitOffset: Cardinal;
begin
if FLineOrder = riloBottomToTop then
y := FHeight - y;
y := FHeight - y - 1;
Result := Positions[y];
BitOffset := x * FBitsPerPixel + Result.Bit;
Result.Bit := BitOffset and 7;
@ -1622,210 +1622,6 @@ begin
end;
end;
{$ifdef OldRawImageProcs}
function RawImageMaskIsEmpty(RawImage: PRawImage; TestPixels: boolean): boolean;
begin
Result := not RawImage^.IsMasked(TestPixels);
end;
{$endif}
{$ifdef OldRawImageProcs}
function RawImageDescriptionAsString(Desc: PRawImageDescription): string;
begin
Result := Desc^.AsString;
end;
{$endif}
{$ifdef OldRawImageProcs}
procedure FreeRawImageData(RawImage: PRawImage);
begin
RawImage^.FreeData;
end;
{$endif}
{$ifdef OldRawImageProcs}
procedure ReleaseRawImageData(RawImage: PRawImage);
begin
RawImage^.ReleaseData;
end;
{$endif}
{-------------------------------------------------------------------------------
Beware: Data is used in ReallocMem
-------------------------------------------------------------------------------}
{$ifdef OldRawImageProcs}
procedure CreateRawImageData(Width, Height, BitsPerPixel: cardinal;
LineEnd: TRawImageLineEnd; var Data: Pointer; var DataSize: PtrUInt);
var
PixelCount: PtrUInt;
BitsPerLine: PtrUInt;
DataBits: QWord;
begin
// get current size
PixelCount:=Width*Height;
if PixelCount=0 then exit;
// calculate BitsPerLine
BitsPerLine:=GetBitsPerLine(Width,BitsPerPixel,LineEnd);
// create pixels
DataBits:=QWord(BitsPerLine)*Height;
DataSize:=cardinal((DataBits+7) shr 3);
ReAllocMem(Data,DataSize);
FillChar(Data^,DataSize,0);
end;
{$endif}
{$ifdef OldRawImageProcs}
procedure CreateRawImageDescFromMask(SrcRawImageDesc,
DestRawImageDesc: PRawImageDescription);
begin
// original code raises an exception, imo it is perfectly valid
// to create a black image (MWE)
if (SrcRawImageDesc^.MaskBitsPerPixel = 0) then
RaiseGDBException('CreateRawImageFromMask Alpha not separate');
DestRawImageDesc^ := SrcRawImageDesc^.GetDescriptionFromMask;
end;
{$endif}
{$ifdef OldRawImageProcs}
procedure GetRawImageXYPosition(RawImageDesc: PRawImageDescription;
LineStarts: PRawImagePosition; x, y: cardinal;
var Position: TRawImagePosition);
var
BitOffset: cardinal;
begin
if RawImageDesc^.LineOrder=riloBottomToTop then
y:=RawImageDesc^.Height-y;
Position:=LineStarts[y];
BitOffset:=RawImageDesc^.BitsPerPixel*cardinal(x)+Position.Bit;
Position.Bit:=(BitOffset and 7);
inc(Position.Byte,BitOffset shr 3);
end;
{$endif}
{$ifdef OldRawImageProcs}
procedure ExtractRawImageRect(SrcRawImage: PRawImage; const SrcRect: TRect;
DestRawImage: PRawImage);
begin
SrcRawImage^.ExtractRect(SrcRect, DestRawImage^);
end;
{$endif}
{$ifdef OldRawImageProcs}
procedure CreateRawImageLineStarts(Width, Height, BitsPerPixel: cardinal;
LineEnd: TRawImageLineEnd; var LineStarts: PRawImagePosition);
// LineStarts is recreated, so make sure it is nil or a valid mem
var
PixelCount: cardinal;
BitsPerLine: cardinal;
CurLine: cardinal;
BytesPerLine: cardinal;
ExtraBitsPerLine: cardinal;
CurBitOffset: cardinal;
begin
// get current size
PixelCount:=Width*Height;
if PixelCount=0 then exit;
// calculate BitsPerLine, BytesPerLine and ExtraBitsPerLine
BitsPerLine:=GetBitsPerLine(Width,BitsPerPixel,LineEnd);
BytesPerLine:=BitsPerLine shr 3;
ExtraBitsPerLine:=BitsPerLine and 7;
// create line start array
ReAllocMem(LineStarts,Height*SizeOf(TRawImagePosition));
LineStarts[0].Byte:=0;
LineStarts[0].Bit:=0;
for CurLine:=1 to Height-1 do begin
CurBitOffset:=LineStarts[CurLine-1].Bit+ExtraBitsPerLine;
LineStarts[CurLine].Byte:=LineStarts[CurLine-1].Byte+BytesPerLine
+(CurBitOffset shr 3);
LineStarts[CurLine].Bit:=CurBitOffset and 7;
end;
end;
{$endif}
{$ifdef OldRawImageProcs}
procedure ReadRawImageBits(TheData: PByte;
const Position: TRawImagePosition;
BitsPerPixel, Prec, Shift: cardinal; BitOrder: TRawImageBitOrder;
var Bits: word);
begin
RawImage_ReadBits(TheData, Position, BitsPerPixel, Prec, Shift, BitOrder, Bits);
end;
{$endif}
{$ifdef OldRawImageProcs}
procedure WriteRawImageBits(TheData: PByte;
const Position: TRawImagePosition;
BitsPerPixel, Prec, Shift: cardinal; BitOrder: TRawImageBitOrder; Bits: word);
begin
RawImage_WriteBits(TheData, Position, BitsPerPixel, Prec, Shift, BitOrder, Bits);
end;
{$endif}
{$ifdef OldRawImageProcs}
procedure ReAlignRawImageLines(var Data: Pointer; var Size: PtrUInt;
Width, Height, BitsPerPixel: cardinal;
var OldLineEnd: TRawImageLineEnd; NewLineEnd: TRawImageLineEnd);
var
OldBytesPerLine: PtrUInt;
OldSize: PtrUInt;
NewBytesPerLine: PtrUInt;
NewSize: PtrUInt;
y: Integer;
OldPos: Pointer;
NewPos: Pointer;
begin
if OldLineEnd=NewLineEnd then exit;
if (Width=0) or (Height=0) then exit;
OldBytesPerLine:=GetBytesPerLine(Width,BitsPerPixel,OldLineEnd);
OldSize:=OldBytesPerLine*PtrUInt(Height);
if OldSize<>Size then
RaiseGDBException('ReAlignRawImageLines OldSize<>Size');
NewBytesPerLine:=GetBytesPerLine(Width,BitsPerPixel,NewLineEnd);
NewSize:=NewBytesPerLine*PtrUInt(Height);
//DebugLn(['ReAlignRawImageLines OldBytesPerLine=',OldBytesPerLine,' NewBytesPerLine=',NewBytesPerLine]);
// enlarge before
if OldSize<NewSize then
ReAllocMem(Data,NewSize);
// move data
OldPos:=Data;
NewPos:=Data;
if OldBytesPerLine>NewBytesPerLine then begin
// compress
for y:=0 to Height-1 do begin
System.Move(OldPos^,NewPos^,NewBytesPerLine);
inc(OldPos,OldBytesPerLine);
inc(NewPos,NewBytesPerLine);
end;
end else begin
// expand
inc(OldPos,OldSize);
inc(NewPos,NewSize);
for y:=Height-1 downto 0 do begin
dec(OldPos,OldBytesPerLine);
dec(NewPos,NewBytesPerLine);
System.Move(OldPos^,NewPos^,OldBytesPerLine);
end;
end;
// shrink after
if OldSize>NewSize then
ReAllocMem(Data,NewSize);
Size:=NewSize;
OldLineEnd:=NewLineEnd;
end;
{$endif}
//------------------------------------------------------------------------------
procedure InternalInit;
var

View File

@ -534,9 +534,24 @@ begin
end;
procedure TCustomIcon.MaskHandleNeeded;
var
ImgHandle, dummy: HBITMAP;
begin
// Created by bitmaphandle
BitmapHandleNeeded;
//!!! BitmapHandleNeeded;
if FCurrent = -1 then Exit;
if MaskHandleAllocated then exit;
if not CreateCompatibleBitmaps(GetRawImagePtr^, Dummy, ImgHandle)
then begin
DebugLn('TCustomIcon.MaskHandleNeeded: Unable to create makshandle');
Exit;
end;
if BitmapHandleAllocated
then UpdateHandles(BitmapHandle, ImgHandle)
else UpdateHandles(0, ImgHandle);
end;
function TCustomIcon.PaletteAllocated: boolean;

View File

@ -170,9 +170,7 @@ procedure TRasterImage.BitmapHandleNeeded;
var
ImgHandle, ImgMaskHandle: HBitmap;
ImagePtr: PRawImage;
DevImage: TRawImage;
DevDesc: TRawImageDescription;
SrcImage, DstImage: TLazIntfImage;
QueryFlags: TRawImageQueryFlags;
W, H: Integer;
SkipMask: Boolean;
@ -180,77 +178,41 @@ begin
if BitmapHandleAllocated then exit;
ImagePtr := GetRawImagePtr;
if ImagePtr = nil then Exit;
ImgMaskHandle := 0;
// create a device compatible image
W := Width;
if W < 1 then W := 1;
H := Height;
if H < 1 then H := 1;
// we must skip mask creation if
// a) we already have mask
// b) mask needs to be created another way - using TransparentColor
SkipMask := MaskHandleAllocated
or (TransparentMode = tmFixed)
or (ImagePtr^.Description.MaskBitsPerPixel = 0);
if ImagePtr^.Description.Depth = 1
then QueryFlags := [riqfMono]
else QueryFlags := [riqfRGB];
if ImagePtr^.Description.AlphaPrec <> 0
then Include(QueryFlags, riqfAlpha);
if ImagePtr^.Description.MaskBitsPerPixel <> 0
then Include(QueryFlags, riqfMask);
QueryDescription(DevDesc, QueryFlags, W, H);
if DevDesc.IsEqual(ImagePtr^.Description)
if not CreateCompatibleBitmaps(ImagePtr^, ImgHandle, ImgMaskHandle, SkipMask)
then begin
// image is compatible, so use it
DstImage := nil;
end
else begin
// create compatible copy
SrcImage := TLazIntfImage.Create(ImagePtr^, False);
DstImage := TLazIntfImage.Create(0, 0);
// create mask for alphachannel when device has no alpha support
if (DevDesc.AlphaPrec = 0) and (riqfAlpha in QueryFlags)
then begin
//add mask if not already queried
if not (riqfMask in QueryFlags)
then QueryDescription(DevDesc, [riqfMask, riqfUpdate]);
DstImage.DataDescription := DevDesc;
DstImage.CopyPixels(SrcImage, 0, 0, True, $8000);
end
else begin
DstImage.DataDescription := DevDesc;
DstImage.CopyPixels(SrcImage);
end;
SrcImage.Free;
DstImage.GetRawImage(DevImage);
ImagePtr := @DevImage;
DebugLn('TRasterImage.BitmapHandleNeeded: Unable to create handles, using default');
// create a default handle
W := Width;
if W < 1 then W := 1;
H := Height;
if H < 1 then H := 1;
if ImagePtr^.Description.Depth = 1
then QueryFlags := [riqfMono]
else QueryFlags := [riqfRGB];
if ImagePtr^.Description.AlphaPrec <> 0
then Include(QueryFlags, riqfAlpha);
if ImagePtr^.Description.MaskBitsPerPixel <> 0
then Include(QueryFlags, riqfMask);
QueryDescription(DevDesc, QueryFlags, W, H);
ImgHandle := CreateDefaultBitmapHandle(DevDesc);
end;
try
// we must skip mask creation if
// a) we already have mask
// b) mask needs to be created another way - using TransparentColor
// c) we dont have mask in the description
SkipMask := MaskHandleAllocated or
(TransparentMode = tmFixed) or
(DevDesc.MaskBitsPerPixel = 0);
if not RawImage_CreateBitmaps(ImagePtr^, ImgHandle, ImgMaskHandle, SkipMask)
then begin
DebugLn('TRasterImage.BitmapHandleNeeded: Unable to create handles, using default');
// create a default handle
ImgHandle := CreateDefaultBitmapHandle(DevDesc);
end;
if SkipMask
then begin
// if we dont have new mask then either use old one or use none
if MaskHandleAllocated
then UpdateHandles(ImgHandle, MaskHandle)
else UpdateHandles(ImgHandle, 0);
end
else UpdateHandles(ImgHandle, ImgMaskHandle);
finally
DstImage.Free;
end;
// if we dont have new mask then either use old one or use none
if SkipMask and MaskHandleAllocated
then UpdateHandles(ImgHandle, MaskHandle)
else UpdateHandles(ImgHandle, ImgMaskHandle);
end;
function TRasterImage.CanShareImage(AClass: TSharedRasterImageClass): Boolean;