From eb11482eeed79e393c00ffb34bf199f00db04f1e Mon Sep 17 00:00:00 2001 From: paul Date: Thu, 8 Nov 2007 02:32:57 +0000 Subject: [PATCH] State image drawing: - implement TRawImage.PerformEffect - use TRawImage.PerformEffect for State drawing of win32 imagelist (except disabled drawing in manifested exe - in this case os method used) - implement state drawing of default imagelist git-svn-id: trunk@12776 - --- lcl/graphtype.pp | 77 ++++++++++++++ lcl/imglist.pp | 10 +- lcl/include/imglist.inc | 25 +++-- lcl/interfaces/win32/win32wsimglist.pp | 134 +++++++++---------------- lcl/widgetset/wsimglist.pp | 55 +++++++--- 5 files changed, 185 insertions(+), 116 deletions(-) diff --git a/lcl/graphtype.pp b/lcl/graphtype.pp index a05be26d45..ee13dd1899 100644 --- a/lcl/graphtype.pp +++ b/lcl/graphtype.pp @@ -42,6 +42,13 @@ type fsBorder // fill this color (it fills only conneted pixels of this color) ); TGraphicsBevelCut = (bvNone, bvLowered, bvRaised, bvSpace); + TGraphicsDrawEffect = + ( + gdeNormal, // no effect + gdeDisabled, // grayed image + gdeHighlighted, // a bit highlighted image + gdeShadowed // a bit shadowed image + ); //------------------------------------------------------------------------------ // raw image data @@ -173,6 +180,7 @@ type procedure ReleaseData; procedure ExtractRect(const ARect: TRect; out ADst: TRawImage); + procedure PerformEffect(const ADrawEffect: TGraphicsDrawEffect; CreateNewData: Boolean = True); function ReadBits(const APosition: TRawImagePosition; APrec, AShift: Byte): Word; procedure ReadChannels(const APosition: TRawImagePosition; out ARed, AGreen, ABlue, AAlpha: Word); procedure ReadMask(const APosition: TRawImagePosition; out AMask: Boolean); @@ -1403,6 +1411,75 @@ begin Description.MaskLineEnd, ADst.Mask, ADst.MaskSize); end; +procedure TRawImage.PerformEffect(const ADrawEffect: TGraphicsDrawEffect; + CreateNewData: Boolean); +const + GlowShadow = 48; + ColorMultiplier = (256 - GlowShadow) / 256; +var + AData: PRGBAQuad; + P: Pointer; + i, j: integer; +begin + if CreateNewData then + begin + GetMem(AData, DataSize); + Move(Data^, AData^, DataSize); + P := AData; + end + else + begin + P := Data; + AData := P; + end; + case ADrawEffect of + gdeNormal: ; + gdeDisabled: + begin + for i := 0 to Description.Height - 1 do + for j := 0 to Description.Width - 1 do + begin + with AData^ do + begin + Red := (Red + Green + Blue) div 3; + Green := Red; + Blue := Red; + end; + inc(AData); + end; + end; + gdeHighlighted: + begin + for i := 0 to Description.Height - 1 do + for j := 0 to Description.Width - 1 do + begin + with AData^ do + begin + Red := Round(GlowShadow + Red * ColorMultiplier); + Green := Round(GlowShadow + Green * ColorMultiplier); + Blue := Round(GlowShadow + Blue * ColorMultiplier); + end; + inc(AData); + end; + end; + gdeShadowed: + begin + for i := 0 to Description.Height - 1 do + for j := 0 to Description.Width - 1 do + begin + with AData^ do + begin + Red := Round(Red * ColorMultiplier); + Green := Round(Green * ColorMultiplier); + Blue := Round(Blue * ColorMultiplier); + end; + inc(AData); + end; + end; + end; + Data := P; +end; + { TRawImageLineStarts } function TRawImageLineStarts.GetPosition(x, y: cardinal): TRawImagePosition; diff --git a/lcl/imglist.pp b/lcl/imglist.pp index 60a5a50d20..c128f8ea8a 100644 --- a/lcl/imglist.pp +++ b/lcl/imglist.pp @@ -110,13 +110,6 @@ type TDrawingStyle = (dsFocus, dsSelected, dsNormal, dsTransparent); TImageType = (itImage, itMask); - TImageListDrawEffect = - ( - ideNormal, // no effect - ideDisabled, // grayed image - ideHighlighted, // a bit highlighted image - ideShadowed // a bit shadowed image - ); TCustomImageList = class(TLCLHandleComponent) private @@ -201,9 +194,10 @@ type procedure Delete(AIndex: Integer); destructor Destroy; override; procedure Draw(ACanvas: TCanvas; AX, AY, AIndex: Integer; AEnabled: Boolean = True); overload; - procedure Draw(ACanvas: TCanvas; AX, AY, AIndex: Integer; ADrawEffect: TImageListDrawEffect); overload; + procedure Draw(ACanvas: TCanvas; AX, AY, AIndex: Integer; ADrawEffect: TGraphicsDrawEffect); overload; procedure FillDescription(out ADesc: TRawImageDescription); procedure GetBitmap(Index: Integer; Image: TBitmap); + procedure GetRawImage(Index: Integer; out Image: TRawImage); {$ifdef IMGLIST_KEEP_EXTRA} procedure GetInternalImage(Index: integer; var Image, Mask: TBitmap; var ImageRect: TRect); diff --git a/lcl/include/imglist.inc b/lcl/include/imglist.inc index 16e3ececfd..4bc4a8b31b 100644 --- a/lcl/include/imglist.inc +++ b/lcl/include/imglist.inc @@ -46,7 +46,6 @@ begin ); end; - { TCustomImageList } {------------------------------------------------------------------------------ @@ -547,17 +546,17 @@ end; procedure TCustomImageList.Draw(ACanvas: TCanvas; AX, AY, AIndex: Integer; AEnabled: Boolean); const - EffectMap: array[Boolean] of TImageListDrawEffect = + EffectMap: array[Boolean] of TGraphicsDrawEffect = ( - ideDisabled, - ideNormal + gdeDisabled, + gdeNormal ); begin Draw(ACanvas, AX, AY, AIndex, EffectMap[AEnabled]); end; procedure TCustomImageList.Draw(ACanvas: TCanvas; AX, AY, AIndex: Integer; - ADrawEffect: TImageListDrawEffect); + ADrawEffect: TGraphicsDrawEffect); {$ifdef IMGLIST_OLDSTYLE} var aBitmap: TBitmap; @@ -642,11 +641,7 @@ begin {$ifdef IMGLIST_OLDSTYLE} Image.Assign(TBitMap(FImageList.Items[Index])); {$else} - CheckIndex(Index); - RawImg.Init; - FillDescription(RawImg.Description); - RawImg.DataSize := FWidth * FHeight * SizeOF(FData[0]); - RawImg.Data := @FData[Index * FWidth * FHeight]; + GetRawImage(Index, RawImg); if not RawImage_CreateBitmaps(RawImg, ImgHandle, MskHandle, True) then begin @@ -665,6 +660,16 @@ begin {$endif} end; +procedure TCustomImageList.GetRawImage(Index: Integer; out Image: TRawImage); +begin + if (FCount = 0) then Exit; + CheckIndex(Index); + Image.Init; + FillDescription(Image.Description); + Image.DataSize := FWidth * FHeight * SizeOF(FData[0]); + Image.Data := @FData[Index * FWidth * FHeight]; +end; + {------------------------------------------------------------------------------ procedure TCustomImageList.GetInternalImage(Index: integer; var Image, Mask: TBitmap); diff --git a/lcl/interfaces/win32/win32wsimglist.pp b/lcl/interfaces/win32/win32wsimglist.pp index 6bd1e23e2c..761f47dfda 100644 --- a/lcl/interfaces/win32/win32wsimglist.pp +++ b/lcl/interfaces/win32/win32wsimglist.pp @@ -53,7 +53,7 @@ type class procedure Delete(AList: TCustomImageList; AIndex: Integer); override; class procedure DestroyHandle(AComponent: TComponent); override; class procedure Draw(AList: TCustomImageList; AIndex: Integer; ACanvas: TCanvas; - ABounds: TRect; ABkColor, ABlendColor: TColor; ADrawEffect: TImageListDrawEffect; AStyle: TDrawingStyle; AImageType: TImageType); override; + ABounds: TRect; ABkColor, ABlendColor: TColor; ADrawEffect: TGraphicsDrawEffect; AStyle: TDrawingStyle; AImageType: TImageType); override; class procedure Insert(AList: TCustomImageList; AIndex: Integer; AData: PRGBAQuad); override; class procedure Move(AList: TCustomImageList; ACurIndex, ANewIndex: Integer); override; class procedure Replace(AList: TCustomImageList; AIndex: Integer; AData: PRGBAQuad); override; @@ -77,8 +77,6 @@ const { itImage } ILD_NORMAL, { itMask } ILD_MASK ); -var - GreyColorMap: array[0..255] of Cardinal; function ColorToImagelistColor(AColor: TColor): DWord; begin @@ -266,90 +264,65 @@ begin end; class procedure TWin32WSCustomImageList.Draw(AList: TCustomImageList; AIndex: Integer; - ACanvas: TCanvas; ABounds: TRect; ABkColor, ABlendColor: TColor; ADrawEffect: TImageListDrawEffect; AStyle: TDrawingStyle; AImageType: TImageType); + ACanvas: TCanvas; ABounds: TRect; ABkColor, ABlendColor: TColor; ADrawEffect: TGraphicsDrawEffect; AStyle: TDrawingStyle; AImageType: TImageType); var - hdcGrey, hdcBW: HDC; - hbmOld1, hbmGrey, hbmOld2, hbmBW: HBitmap; - - InfoGrey: record - Header: TBitmapInfoHeader; - Colors: array[0..255] of Cardinal; - end; - - BitsGrey: PChar; DrawParams: TImageListDrawParams; + RawImg: TRawImage; + ListImg, DeviceImg: TLazIntfImage; + ImgHandle, MskHandle: HBitmap; + ABitmap: TBitmap; begin if not WSCheckHandleAllocated(AList, 'Draw') then Exit; - if ADrawEffect <> ideDisabled then + if ADrawEffect = gdeNormal then begin - ImageList_DrawEx(HImageList(AList.Handle), AIndex, ACanvas.Handle, ABounds.Left, - ABounds.Top, ABounds.Right, ABounds.Bottom, ColorToImagelistColor(ABkColor), - ColorToImagelistColor(ABlendColor), DRAWINGSTYLEMAP[AStyle] or IMAGETPYEMAP[AImageType]) + ImageList_DrawEx(HImageList(AList.Handle), AIndex, ACanvas.Handle, ABounds.Left, + ABounds.Top, ABounds.Right, ABounds.Bottom, ColorToImagelistColor(ABkColor), + ColorToImagelistColor(ABlendColor), DRAWINGSTYLEMAP[AStyle] or IMAGETPYEMAP[AImageType]); + end + else + if (ADrawEffect = gdeDisabled) and (Win32WidgetSet.CommonControlsVersion >= ComCtlVersionIE6) then + begin + // if it is manifested exe then use winXP algoriphm of gray painting + FillChar(DrawParams, SizeOf(DrawParams), 0); + DrawParams.cbSize := SizeOf(DrawParams); + DrawParams.himlL := HImageList(AList.Handle); + DrawParams.i := AIndex; + DrawParams.hdcDst := ACanvas.Handle; + DrawParams.x := ABounds.Left; + DrawParams.y := ABounds.Top; + DrawParams.cx := ABounds.Right; + DrawParams.cy := ABounds.Bottom; + DrawParams.rgbBk := ColorToImagelistColor(ABkColor); + DrawParams.rgbFg := ColorToImagelistColor(ABlendColor); + DrawParams.fStyle := DRAWINGSTYLEMAP[AStyle] or IMAGETPYEMAP[AImageType]; + DrawParams.fState := ILS_SATURATE; // draw greyed + ImageList_DrawIndirect(@DrawParams); end else begin - // at moment only Disabled state is implemented - if (Win32WidgetSet.CommonControlsVersion >= ComCtlVersionIE6) then - begin - FillChar(DrawParams, SizeOf(DrawParams), 0); - DrawParams.cbSize := SizeOf(DrawParams); - DrawParams.himlL := HImageList(AList.Handle); - DrawParams.i := AIndex; - DrawParams.hdcDst := ACanvas.Handle; - DrawParams.x := ABounds.Left; - DrawParams.y := ABounds.Top; - DrawParams.cx := ABounds.Right; - DrawParams.cy := ABounds.Bottom; - DrawParams.rgbBk := ColorToImagelistColor(ABkColor); - DrawParams.rgbFg := ColorToImagelistColor(ABlendColor); - DrawParams.fStyle := DRAWINGSTYLEMAP[AStyle] or IMAGETPYEMAP[AImageType]; - DrawParams.fState := ILS_SATURATE; // draw greyed - ImageList_DrawIndirect(@DrawParams); - end else - begin - hdcGrey := CreateCompatibleDC(ACanvas.Handle); - hdcBW := CreateCompatibleDC(ACanvas.Handle); - - // create grey bitmap - FillChar(InfoGrey, sizeof(InfoGrey), 0); - InfoGrey.Header.biSize := sizeof(InfoGrey.Header); - InfoGrey.Header.biWidth := AList.Width; - InfoGrey.Header.biHeight := AList.Height; - InfoGrey.Header.biPlanes := 1; - InfoGrey.Header.biBitCount := 8; - InfoGrey.Header.biCompression := BI_RGB; - // fill color table - System.Move(GreyColorMap, InfoGrey.Colors, 256 * SizeOf(Cardinal)); - hbmGrey := CreateDIBSection(hdcGrey, Windows.PBitmapInfo(@InfoGrey)^, DIB_RGB_COLORS, BitsGrey, 0, 0); - - hbmBW := CreateBitmap(AList.Width, AList.Height, 1, 0, nil); - - hbmOld1 := SelectObject(hdcGrey, hbmGrey); - hbmOld2 := SelectObject(hdcBW, hbmBW); - - // draw to greyDC - ImageList_DrawEx(HImageList(AList.Handle), AIndex, hdcGrey, 0, - 0, ABounds.Right, ABounds.Bottom, ColorToImagelistColor(ABkColor), - ColorToImagelistColor(ABlendColor), ILD_NORMAL); - // draw to bwDC - ImageList_DrawEx(HImageList(AList.Handle), AIndex, hdcBW, 0, - 0, ABounds.Right, ABounds.Bottom, clBlack, - clWhite, ILD_MASK); - - // draw grey - BitBlt(ACanvas.Handle, ABounds.Left, ABounds.Top, ABounds.Right, - ABounds.Bottom, hdcGrey, 0, 0, SRCCOPY); - // mask - BitBlt(ACanvas.Handle, ABounds.Left, ABounds.Top, ABounds.Right, - ABounds.Bottom, hdcBW, 0, 0, SRCINVERT); - - DeleteObject(SelectObject(hdcBW, hbmOld2)); - DeleteDC(hdcBW); - DeleteObject(SelectObject(hdcGrey, hbmOld1)); - DeleteDC(hdcGrey); + // use RawImage_PerformEffect to perform drawing effect + AList.GetRawImage(AIndex, RawImg); + RawImg.PerformEffect(ADrawEffect, True); + + ABitmap := TBitmap.Create; + if not Widgetset.RawImage_CreateBitmaps(RawImg, ImgHandle, MskHandle, True) + then begin + // bummer, the widgetset doesn't support our 32bit format, try device + ListImg := TLazIntfImage.Create(RawImg, False); + DeviceImg := TLazIntfImage.Create(0, 0); + DeviceImg.DataDescription := GetDescriptionFromDevice(0, AList.Width, AList.Height); + DeviceImg.CopyPixels(ListImg); + DeviceImg.GetRawImage(RawImg); + Widgetset.RawImage_CreateBitmaps(RawImg, ImgHandle, MskHandle); + DeviceImg.Free; + ListImg.Free; end; + ABitmap.SetHandles(ImgHandle, MskHandle); + ACanvas.Draw(ABounds.Left, ABounds.Top, ABitmap); + ABitmap.Free; + FreeMem(RawImg.Data); end; end; @@ -413,16 +386,7 @@ begin then AddData(ImageList, 1, AIndex, AList.Width, AList.Height, AData); end; -procedure InitGreyColormap; -var - i: Cardinal; -begin - for i := 0 to 255 do - GreyColorMap[i] := $FF000000 or (i shl 16) or (i shl 8) or i; -end; - initialization - InitGreyColormap; //////////////////////////////////////////////////// // I M P O R T A N T //////////////////////////////////////////////////// diff --git a/lcl/widgetset/wsimglist.pp b/lcl/widgetset/wsimglist.pp index 0ee1eb3910..336dd2a8a0 100644 --- a/lcl/widgetset/wsimglist.pp +++ b/lcl/widgetset/wsimglist.pp @@ -40,7 +40,7 @@ interface // the uses clause of the XXXintf.pp //////////////////////////////////////////////////// uses - Classes, Contnrs, GraphType, Graphics, ImgList, LCLType, LCLIntf, + Classes, Contnrs, GraphType, Graphics, IntfGraphics, ImgList, LCLType, LCLIntf, WSLCLClasses, WSProc; type @@ -54,7 +54,7 @@ type class procedure Delete(AList: TCustomImageList; AIndex: Integer); virtual; class procedure DestroyHandle(AComponent: TComponent); override; class procedure Draw(AList: TCustomImageList; AIndex: Integer; ACanvas: TCanvas; - ABounds: TRect; ABkColor, ABlendColor: TColor; ADrawEffect: TImageListDrawEffect; AStyle: TDrawingStyle; AImageType: TImageType); virtual; + ABounds: TRect; ABkColor, ABlendColor: TColor; ADrawEffect: TGraphicsDrawEffect; AStyle: TDrawingStyle; AImageType: TImageType); virtual; class procedure Insert(AList: TCustomImageList; AIndex: Integer; AData: PRGBAQuad); virtual; @@ -74,27 +74,56 @@ type private FWidth: Integer; FHeight: Integer; + FList: TCustomImageList; public - constructor Create(AWidth, AHeight: Integer); reintroduce; - procedure Draw(AIndex: Integer; ACanvas: TCanvas; ABounds: TRect; ADrawEffect: TImageListDrawEffect; AStyle: TDrawingStyle); + constructor Create(AList: TCustomImageList); reintroduce; + procedure Draw(AIndex: Integer; ACanvas: TCanvas; ABounds: TRect; ADrawEffect: TGraphicsDrawEffect; AStyle: TDrawingStyle); end; { TDefaultImageListImplementor } -constructor TDefaultImageListImplementor.Create(AWidth, AHeight: Integer); +constructor TDefaultImageListImplementor.Create(AList: TCustomImageList); begin inherited Create(True); - FWidth := AWidth; - FHeight := AHeight; + FList := AList; end; procedure TDefaultImageListImplementor.Draw(AIndex: Integer; ACanvas: TCanvas; - ABounds: TRect; ADrawEffect: TImageListDrawEffect; AStyle: TDrawingStyle); + ABounds: TRect; ADrawEffect: TGraphicsDrawEffect; AStyle: TDrawingStyle); var - Bitmap: TBitmap; + ABitmap: TBitmap; + RawImg: TRawImage; + ListImg, DeviceImg: TLazIntfImage; + ImgHandle, MskHandle: HBitmap; begin - Bitmap := TBitmap(Items[AIndex]); - ACanvas.Draw(ABounds.Left, ABounds.Top, Bitmap); + if ADrawEffect = gdeNormal then + begin + ABitmap := TBitmap(Items[AIndex]); + ACanvas.Draw(ABounds.Left, ABounds.Top, ABitmap); + end + else + begin + FList.GetRawImage(AIndex, RawImg); + RawImg.PerformEffect(ADrawEffect, True); + + ABitmap := TBitmap.Create; + if not RawImage_CreateBitmaps(RawImg, ImgHandle, MskHandle, True) + then begin + // bummer, the widgetset doesn't support our 32bit format, try device + ListImg := TLazIntfImage.Create(RawImg, False); + DeviceImg := TLazIntfImage.Create(0, 0); + DeviceImg.DataDescription := GetDescriptionFromDevice(0, FList.Width, FList.Height); + DeviceImg.CopyPixels(ListImg); + DeviceImg.GetRawImage(RawImg); + RawImage_CreateBitmaps(RawImg, ImgHandle, MskHandle); + DeviceImg.Free; + ListImg.Free; + end; + ABitmap.SetHandles(ImgHandle, MskHandle); + ACanvas.Draw(ABounds.Left, ABounds.Top, ABitmap); + ABitmap.Free; + FreeMem(RawImg.Data); + end; end; function InternalCreateBitmap(AList: TCustomImageList; AWidth, AHeight: Integer; AData: PRGBAQuad): TBitmap; @@ -129,7 +158,7 @@ var ABitmap: TBitmap; i: integer; begin - Result := TLCLIntfHandle(TDefaultImageListImplementor.Create(AWidth, AHeight)); + Result := TLCLIntfHandle(TDefaultImageListImplementor.Create(AList)); if AData <> nil then begin @@ -158,7 +187,7 @@ begin end; class procedure TWSCustomImageList.Draw(AList: TCustomImageList; AIndex: Integer; - ACanvas: TCanvas; ABounds: TRect; ABkColor, ABlendColor: TColor; ADrawEffect: TImageListDrawEffect; AStyle: TDrawingStyle; AImageType: TImageType); + ACanvas: TCanvas; ABounds: TRect; ABkColor, ABlendColor: TColor; ADrawEffect: TGraphicsDrawEffect; AStyle: TDrawingStyle; AImageType: TImageType); begin if not WSCheckHandleAllocated(AList, 'Draw') then Exit;