mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-09-26 16:49:14 +02:00
gtk1, gtk2: Add CreateIconIndirect implementation which returns pixbuf. Move CreateCursor code there and remove its declaration.
git-svn-id: trunk@15457 -
This commit is contained in:
parent
66ca0835ec
commit
db26dddf06
@ -1139,16 +1139,14 @@ begin
|
||||
EndGDKErrorTrap;
|
||||
end;
|
||||
|
||||
function ScalePixmapAndMask(AScaleGC: PGDKGC; AScaleMethod: TGdkInterpType;
|
||||
ASrc: PGdkPixmap; ASrcX, ASrcY, ASrcWidth, ASrcHeight: integer;
|
||||
ASrcColorMap: PGdkColormap; ASrcMask: PGdkBitmap;
|
||||
ADstWidth, ADstHeight: Integer; out ADst, ADstMask: PGdkPixmap) : Boolean;
|
||||
function CreatePixbufFromImageAndMask(ASrc: PGdkPixmap; ASrcX, ASrcY, ASrcWidth,
|
||||
ASrcHeight: integer; ASrcColorMap: PGdkColormap; ASrcMask: PGdkBitmap): PGdkPixbuf;
|
||||
|
||||
procedure Warn(const AText: String);
|
||||
begin
|
||||
DebugLn('[WARNING] ScalePixmapAndMask: ' + AText);
|
||||
end;
|
||||
|
||||
|
||||
procedure ApplyMask(APixels, AMask: pguchar);
|
||||
type
|
||||
TPixbufPixel = record
|
||||
@ -1169,10 +1167,10 @@ function ScalePixmapAndMask(AScaleGC: PGDKGC; AScaleMethod: TGdkInterpType;
|
||||
end;
|
||||
|
||||
var
|
||||
ScaleSrc, ScaleDst, ScaleMsk: PGdkPixbuf;
|
||||
Msk: PGdkPixbuf;
|
||||
FullSrcWidth, FullSrcHeight: integer;
|
||||
begin
|
||||
Result := False;
|
||||
Result := nil;
|
||||
if ASrc = nil then Exit;
|
||||
|
||||
gdk_window_get_size(PGDKWindow(ASrc), @FullSrcWidth, @FullSrcHeight);
|
||||
@ -1186,27 +1184,48 @@ begin
|
||||
end;
|
||||
|
||||
// Creating PixBuf from pixmap
|
||||
ScaleSrc := CreatePixbufFromDrawable(ASrc, ASrcColorMap, ASrcMask <> nil, ASrcX, ASrcY, 0, 0, ASrcWidth, ASrcHeight);
|
||||
if ScaleSrc = nil
|
||||
Result := CreatePixbufFromDrawable(ASrc, ASrcColorMap, ASrcMask <> nil, ASrcX, ASrcY, 0, 0, ASrcWidth, ASrcHeight);
|
||||
if Result = nil
|
||||
then begin
|
||||
Warn('ScaleSrc=nil');
|
||||
Warn('Result=nil');
|
||||
Exit;
|
||||
end;
|
||||
|
||||
// Apply mask if present
|
||||
if ASrcMask <> nil
|
||||
then begin
|
||||
if gdk_pixbuf_get_rowstride(ScaleSrc) <> ASrcWidth shl 2
|
||||
if gdk_pixbuf_get_rowstride(Result) <> ASrcWidth shl 2
|
||||
then begin
|
||||
Warn('rowstride <> 4*width');
|
||||
gdk_pixbuf_unref(ScaleSrc);
|
||||
gdk_pixbuf_unref(Result);
|
||||
Result := nil;
|
||||
Exit;
|
||||
end;
|
||||
|
||||
ScaleMsk := CreatePixbufFromDrawable(ASrcMask, nil, True, ASrcX, ASrcY, 0, 0, ASrcWidth, ASrcHeight);
|
||||
ApplyMask(gdk_pixbuf_get_pixels(ScaleSrc), gdk_pixbuf_get_pixels(ScaleMsk));
|
||||
gdk_pixbuf_unref(ScaleMsk);
|
||||
|
||||
Msk := CreatePixbufFromDrawable(ASrcMask, nil, True, ASrcX, ASrcY, 0, 0, ASrcWidth, ASrcHeight);
|
||||
ApplyMask(gdk_pixbuf_get_pixels(Result), gdk_pixbuf_get_pixels(Msk));
|
||||
gdk_pixbuf_unref(Msk);
|
||||
end;
|
||||
end;
|
||||
|
||||
function ScalePixmapAndMask(AScaleGC: PGDKGC; AScaleMethod: TGdkInterpType;
|
||||
ASrc: PGdkPixmap; ASrcX, ASrcY, ASrcWidth, ASrcHeight: integer;
|
||||
ASrcColorMap: PGdkColormap; ASrcMask: PGdkBitmap;
|
||||
ADstWidth, ADstHeight: Integer; out ADst, ADstMask: PGdkPixmap) : Boolean;
|
||||
|
||||
procedure Warn(const AText: String);
|
||||
begin
|
||||
DebugLn('[WARNING] ScalePixmapAndMask: ' + AText);
|
||||
end;
|
||||
|
||||
var
|
||||
ScaleSrc, ScaleDst: PGdkPixbuf;
|
||||
begin
|
||||
Result := False;
|
||||
|
||||
// Creating PixBuf from pixmap
|
||||
ScaleSrc := CreatePixbufFromImageAndMask(ASrc, ASrcX, ASrcY, ASrcWidth, ASrcHeight,
|
||||
ASrcColorMap, ASrcMask);
|
||||
|
||||
// Scaling PixBuf
|
||||
ScaleDst := gdk_pixbuf_scale_simple(ScaleSrc, ADstWidth, ADstHeight, AScaleMethod);
|
||||
|
@ -630,6 +630,8 @@ procedure MergeClipping(DestinationDC: TGtkDeviceContext; DestinationGC: PGDKGC;
|
||||
X,Y,Width,Height: integer; ClipMergeMask: PGdkBitmap;
|
||||
ClipMergeMaskX, ClipMergeMaskY: integer;
|
||||
var NewClipMask: PGdkBitmap);
|
||||
function CreatePixbufFromImageAndMask(ASrc: PGdkPixmap; ASrcX, ASrcY, ASrcWidth,
|
||||
ASrcHeight: integer; ASrcColorMap: PGdkColormap; ASrcMask: PGdkBitmap): PGdkPixbuf;
|
||||
function ScalePixmapAndMask(AScaleGC: PGDKGC; AScaleMethod: TGdkInterpType;
|
||||
ASrc: PGdkPixmap; ASrcX, ASrcY, ASrcWidth, ASrcHeight: integer;
|
||||
ASrcColorMap: PGdkColormap; ASrcMask: PGdkBitmap;
|
||||
|
@ -1226,136 +1226,19 @@ begin
|
||||
Assert(False,Format('trace: [TGtkWidgetSet.CreateCompatibleDC] DC: 0x%x --> 0x%x', [Integer(DC), Integer(Result)]));
|
||||
end;
|
||||
|
||||
|
||||
function TGtkWidgetSet.CreateCursor(ACursorInfo: PIconInfo): hCursor;
|
||||
|
||||
procedure GetColorMask(AImage, AMask: PGDKPixmap; AImgBits, AMskBits: PByte; AWidth, AHeight: integer);
|
||||
var
|
||||
i, j: integer;
|
||||
colormap: PGDKColormap;
|
||||
Image, MaskImage: PGDKImage;
|
||||
GDKColor: TGDKColor;
|
||||
Pixel, MaskPixel: LongWord;
|
||||
offset: byte;
|
||||
|
||||
procedure SetColorAndMask(c: TGDKColor; MaskPixel: LongWord);
|
||||
var
|
||||
c_bit, m_bit: byte;
|
||||
begin
|
||||
// c_bit := Ord(0.222 * c.red + 0.707 * c.green + 0.071 * c.blue >= $8000);
|
||||
// do some int math
|
||||
c_bit := Ord(cardinal(222) * c.red
|
||||
+ cardinal(707) * c.green
|
||||
+ cardinal(071) * c.blue
|
||||
>= $8000 * 1000);
|
||||
m_bit := ord(MaskPixel = 1);
|
||||
|
||||
AImgBits^ := AImgBits^ or (c_bit shl offset);
|
||||
AMskBits^ := AMskBits^ or (m_bit shl offset);
|
||||
|
||||
inc(offset);
|
||||
if offset > 7 then
|
||||
begin
|
||||
inc(AImgBits);
|
||||
inc(AMskBits);
|
||||
offset := 0;
|
||||
end;
|
||||
end;
|
||||
|
||||
begin
|
||||
// most of this code was taken from TGtkWidgetSet.DCGetPixel
|
||||
|
||||
Image := gdk_drawable_get_image(AImage, 0, 0, AWidth, AHeight);
|
||||
MaskImage := gdk_drawable_get_image(AMask, 0, 0, AWidth, AHeight);
|
||||
|
||||
{$ifdef Gtk1}
|
||||
// previously gdk_image_get_colormap(image) was used, implementation
|
||||
// was casting GdkImage to GdkWindow which is not valid and cause AVs
|
||||
if gdk_window_get_type(PGdkWindow(AImage))= GDK_WINDOW_PIXMAP then
|
||||
colormap := nil // pixmaps are created with null colormap, get system one instead
|
||||
else
|
||||
colormap := gdk_window_get_colormap(PGdkWindow(AImage));
|
||||
{$else}
|
||||
colormap := gdk_image_get_colormap(image);
|
||||
{$endif}
|
||||
|
||||
if colormap = nil then
|
||||
colormap := gdk_colormap_get_system;
|
||||
|
||||
offset := 0;
|
||||
|
||||
for j := 0 to AHeight - 1 do
|
||||
for i := 0 to AWidth - 1 do
|
||||
begin
|
||||
Pixel := gdk_image_get_pixel(Image, i, j);
|
||||
MaskPixel := gdk_image_get_pixel(MaskImage, i, j);
|
||||
FillChar(GDKColor,SizeOf(GDKColor), 0);
|
||||
// does not work with TBitmap.Canvas
|
||||
gdk_colormap_query_color(colormap, Pixel, @GDKColor);
|
||||
SetColorAndMask(GDKColor, MaskPixel);
|
||||
end;
|
||||
gdk_image_unref(Image);
|
||||
gdk_image_unref(MaskImage);
|
||||
end;
|
||||
|
||||
var
|
||||
FG, BG: TGDKColor;
|
||||
Img, Msk: PGdkPixmap;
|
||||
srcbitmap, mskbitmap: PGdkPixmap;
|
||||
W, H, bitlen: integer;
|
||||
ImgBits, MskBits: array of byte;
|
||||
begin
|
||||
Result := 0;
|
||||
if not IsValidGDIObject(ACursorInfo^.hbmColor) then Exit;
|
||||
|
||||
{$IFDEF VerboseGtkToDos}{$note TODO: add support for mono cursors}{$ENDIF}
|
||||
Img := PGDIObject(ACursorInfo^.hbmColor)^.GDIBitmapObject;
|
||||
if (PGDIObject(ACursorInfo^.hbmColor)^.GDIBitmapType = gbPixmap) and
|
||||
(PGDIObject(ACursorInfo^.hbmColor)^.GDIPixmapObject.Mask <> nil) then
|
||||
Msk := PGDIObject(ACursorInfo^.hbmColor)^.GDIPixmapObject.Mask
|
||||
else
|
||||
Msk := PGDIObject(ACursorInfo^.hbmMask)^.GDIBitmapObject;
|
||||
|
||||
gdk_drawable_get_size(Img, @W, @H);
|
||||
|
||||
bitlen := (W * H) shr 3;
|
||||
SetLength(ImgBits, bitlen);
|
||||
SetLength(MskBits, bitlen);
|
||||
FillChar(ImgBits[0], bitlen, 0);
|
||||
FillChar(MskBits[0], bitlen, 0);
|
||||
|
||||
GetColorMask(Img, Msk, @ImgBits[0], @MskBits[0], W, H);
|
||||
|
||||
srcbitmap := gdk_bitmap_create_from_data(nil, @ImgBits[0], W, H);
|
||||
mskbitmap := gdk_bitmap_create_from_data(nil, @MskBits[0], W, H);
|
||||
|
||||
|
||||
// white
|
||||
fg.red := $FFFF;
|
||||
fg.green := $FFFF;
|
||||
fg.blue := $FFFF;
|
||||
fg.pixel := 0;
|
||||
|
||||
// black
|
||||
bg.red := 0;
|
||||
bg.green := 0;
|
||||
bg.blue := 0;
|
||||
bg.pixel := 0;
|
||||
|
||||
Result := HCursor(PtrUInt(gdk_cursor_new_from_pixmap(srcbitmap, mskbitmap,
|
||||
@fg, @bg, ACursorInfo^.xHotspot, ACursorInfo^.yHotspot)));
|
||||
|
||||
gdk_pixmap_unref(srcbitmap);
|
||||
gdk_pixmap_unref(mskbitmap);
|
||||
if Msk <> nil then
|
||||
gdk_pixmap_unref(msk);
|
||||
end;
|
||||
|
||||
function TGtkWidgetSet.DestroyCursor(Handle: hCursor): Boolean;
|
||||
begin
|
||||
if Handle <> 0 then
|
||||
Result := Handle <> 0;
|
||||
if Result then
|
||||
gdk_cursor_destroy(PGdkCursor(Handle));
|
||||
Result:=true;
|
||||
end;
|
||||
|
||||
function TGTKWidgetSet.DestroyIcon(Handle: HICON): Boolean;
|
||||
begin
|
||||
// todo: handle cursors here, but how to check whether it is a cursor or an icon?
|
||||
Result := Handle <> 0;
|
||||
if Result then
|
||||
gdk_pixbuf_unref(PGdkPixbuf(Handle));
|
||||
end;
|
||||
|
||||
{------------------------------------------------------------------------------
|
||||
@ -1908,6 +1791,135 @@ begin
|
||||
end;
|
||||
{$EndIf}
|
||||
|
||||
function TGTKWidgetSet.CreateIconIndirect(IconInfo: PIconInfo): HICON;
|
||||
procedure GetColorMask(AImage, AMask: PGDKPixmap; AImgBits, AMskBits: PByte; AWidth, AHeight: integer);
|
||||
var
|
||||
i, j: integer;
|
||||
colormap: PGDKColormap;
|
||||
Image, MaskImage: PGDKImage;
|
||||
GDKColor: TGDKColor;
|
||||
Pixel, MaskPixel: LongWord;
|
||||
offset: byte;
|
||||
|
||||
procedure SetColorAndMask(c: TGDKColor; MaskPixel: LongWord);
|
||||
var
|
||||
c_bit, m_bit: byte;
|
||||
begin
|
||||
// c_bit := Ord(0.222 * c.red + 0.707 * c.green + 0.071 * c.blue >= $8000);
|
||||
// do some int math
|
||||
c_bit := Ord(cardinal(222) * c.red
|
||||
+ cardinal(707) * c.green
|
||||
+ cardinal(071) * c.blue
|
||||
>= $8000 * 1000);
|
||||
m_bit := ord(MaskPixel = 1);
|
||||
|
||||
AImgBits^ := AImgBits^ or (c_bit shl offset);
|
||||
AMskBits^ := AMskBits^ or (m_bit shl offset);
|
||||
|
||||
inc(offset);
|
||||
if offset > 7 then
|
||||
begin
|
||||
inc(AImgBits);
|
||||
inc(AMskBits);
|
||||
offset := 0;
|
||||
end;
|
||||
end;
|
||||
|
||||
begin
|
||||
// most of this code was taken from TGtkWidgetSet.DCGetPixel
|
||||
|
||||
Image := gdk_drawable_get_image(AImage, 0, 0, AWidth, AHeight);
|
||||
MaskImage := gdk_drawable_get_image(AMask, 0, 0, AWidth, AHeight);
|
||||
|
||||
{$ifdef Gtk1}
|
||||
// previously gdk_image_get_colormap(image) was used, implementation
|
||||
// was casting GdkImage to GdkWindow which is not valid and cause AVs
|
||||
if gdk_window_get_type(PGdkWindow(AImage))= GDK_WINDOW_PIXMAP then
|
||||
colormap := nil // pixmaps are created with null colormap, get system one instead
|
||||
else
|
||||
colormap := gdk_window_get_colormap(PGdkWindow(AImage));
|
||||
{$else}
|
||||
colormap := gdk_image_get_colormap(image);
|
||||
{$endif}
|
||||
|
||||
if colormap = nil then
|
||||
colormap := gdk_colormap_get_system;
|
||||
|
||||
offset := 0;
|
||||
|
||||
for j := 0 to AHeight - 1 do
|
||||
for i := 0 to AWidth - 1 do
|
||||
begin
|
||||
Pixel := gdk_image_get_pixel(Image, i, j);
|
||||
MaskPixel := gdk_image_get_pixel(MaskImage, i, j);
|
||||
FillChar(GDKColor,SizeOf(GDKColor), 0);
|
||||
// does not work with TBitmap.Canvas
|
||||
gdk_colormap_query_color(colormap, Pixel, @GDKColor);
|
||||
SetColorAndMask(GDKColor, MaskPixel);
|
||||
end;
|
||||
gdk_image_unref(Image);
|
||||
gdk_image_unref(MaskImage);
|
||||
end;
|
||||
|
||||
var
|
||||
FG, BG: TGDKColor;
|
||||
Img, Msk: PGdkPixmap;
|
||||
srcbitmap, mskbitmap: PGdkBitmap;
|
||||
W, H, bitlen: integer;
|
||||
ImgBits, MskBits: array of byte;
|
||||
APixbuf: PGdkPixbuf;
|
||||
begin
|
||||
Result := 0;
|
||||
if not IsValidGDIObject(IconInfo^.hbmColor) then Exit;
|
||||
|
||||
{$IFDEF VerboseGtkToDos}{$note TODO: add support for mono cursors}{$ENDIF}
|
||||
Img := PGDIObject(IconInfo^.hbmColor)^.GDIBitmapObject;
|
||||
if (PGDIObject(IconInfo^.hbmColor)^.GDIBitmapType = gbPixmap) and
|
||||
(PGDIObject(IconInfo^.hbmColor)^.GDIPixmapObject.Mask <> nil) then
|
||||
Msk := PGDIObject(IconInfo^.hbmColor)^.GDIPixmapObject.Mask
|
||||
else
|
||||
Msk := PGDIObject(IconInfo^.hbmMask)^.GDIBitmapObject;
|
||||
|
||||
gdk_drawable_get_size(Img, @W, @H);
|
||||
|
||||
if IconInfo^.fIcon then
|
||||
begin
|
||||
// Creating PixBuf from pixmap and mask
|
||||
Result := HICON(PtrUInt(CreatePixbufFromImageAndMask(Img, 0, 0, W, H, nil, Msk)));
|
||||
end
|
||||
else
|
||||
begin
|
||||
bitlen := (W * H) shr 3;
|
||||
SetLength(ImgBits, bitlen);
|
||||
SetLength(MskBits, bitlen);
|
||||
FillChar(ImgBits[0], bitlen, 0);
|
||||
FillChar(MskBits[0], bitlen, 0);
|
||||
|
||||
GetColorMask(Img, Msk, @ImgBits[0], @MskBits[0], W, H);
|
||||
|
||||
srcbitmap := gdk_bitmap_create_from_data(nil, @ImgBits[0], W, H);
|
||||
mskbitmap := gdk_bitmap_create_from_data(nil, @MskBits[0], W, H);
|
||||
|
||||
// white
|
||||
fg.red := $FFFF;
|
||||
fg.green := $FFFF;
|
||||
fg.blue := $FFFF;
|
||||
fg.pixel := 0;
|
||||
|
||||
// black
|
||||
bg.red := 0;
|
||||
bg.green := 0;
|
||||
bg.blue := 0;
|
||||
bg.pixel := 0;
|
||||
|
||||
Result := HCURSOR(PtrUInt(gdk_cursor_new_from_pixmap(srcbitmap, mskbitmap,
|
||||
@fg, @bg, IconInfo^.xHotspot, IconInfo^.yHotspot)));
|
||||
|
||||
gdk_pixmap_unref(srcbitmap);
|
||||
gdk_pixmap_unref(mskbitmap);
|
||||
end;
|
||||
end;
|
||||
|
||||
{------------------------------------------------------------------------------
|
||||
Function: CreatePalette
|
||||
Params: LogPalette
|
||||
|
@ -52,9 +52,9 @@ function CreateBrushIndirect(const LogBrush: TLogBrush): HBRUSH; override;
|
||||
function CreateCaret(Handle : HWND; Bitmap : hBitmap; width, Height : Integer) : Boolean; override;
|
||||
function CreateCompatibleBitmap(DC: HDC; Width, Height: Integer): HBITMAP; override;
|
||||
function CreateCompatibleDC(DC: HDC): HDC; override;
|
||||
function CreateCursor(ACursorInfo: PIconInfo): hCursor; override;
|
||||
function CreateFontIndirect(const LogFont: TLogFont): HFONT; override;
|
||||
function CreateFontIndirectEx(const LogFont: TLogFont; const LongFontName: string): HFONT; override;
|
||||
function CreateIconIndirect(IconInfo: PIconInfo): HICON; override;
|
||||
function CreatePalette(const LogPalette: TLogPalette): HPALETTE; override;
|
||||
function CreatePenIndirect(const LogPen: TLogPen): HPEN; override;
|
||||
function CreatePolygonRgn(Points: PPoint; NumPts: Integer; FillMode: integer): HRGN; Override;
|
||||
@ -64,7 +64,8 @@ procedure DeleteCriticalSection(var CritSection: TCriticalSection); override;
|
||||
function DeleteDC(hDC: HDC): Boolean; override;
|
||||
function DeleteObject(GDIObject: HGDIOBJ): Boolean; override;
|
||||
function DestroyCaret(Handle : HWND): Boolean; override;
|
||||
function DestroyCursor(Handle: hCursor): Boolean; override;
|
||||
function DestroyCursor(Handle: HCURSOR): Boolean; override;
|
||||
function DestroyIcon(Handle: HICON): Boolean; override;
|
||||
function DrawFrameControl(DC: HDC; const Rect : TRect; uType, uState : Cardinal) : Boolean; override;
|
||||
function DrawFocusRect(DC: HDC; const Rect: TRect): boolean; override;
|
||||
function DrawEdge(DC: HDC; var ARect: TRect; Edge: Cardinal; grfFlags: Cardinal): Boolean; override;
|
||||
|
@ -67,78 +67,6 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
function TGtk2WidgetSet.CreateCursor(ACursorInfo: PIconInfo): hCursor;
|
||||
var
|
||||
pixmap: PGdkPixmap;
|
||||
bitmap: PGdkBitmap;
|
||||
Width, Height: integer;
|
||||
MaxWidth, MaxHeight: guint;
|
||||
pixbuf, masked_pixbuf: PGdkPixbuf;
|
||||
|
||||
{$ifdef Windows}
|
||||
Old80807CW: Word;
|
||||
|
||||
procedure SetCW; inline;
|
||||
begin
|
||||
Old80807CW := Get8087CW;
|
||||
Set8087CW($133F);
|
||||
end;
|
||||
|
||||
procedure ResetCW; inline;
|
||||
begin
|
||||
Set8087CW(Old80807CW);
|
||||
end;
|
||||
{$endif}
|
||||
|
||||
begin
|
||||
Result := 0;
|
||||
if not IsValidGDIObject(ACursorInfo^.hbmColor) then Exit;
|
||||
|
||||
pixmap := PGDIObject(ACursorInfo^.hbmColor)^.GDIPixmapObject.Image;
|
||||
bitmap := PGDIObject(ACursorInfo^.hbmColor)^.GDIPixmapObject.Mask;
|
||||
|
||||
gdk_drawable_get_size(pixmap, @Width, @Height);
|
||||
gdk_display_get_maximal_cursor_size(gdk_display_get_default,
|
||||
@MaxWidth, @MaxHeight);
|
||||
|
||||
if (Width > integer(MaxWidth)) or (Height > integer(MaxHeight)) then
|
||||
exit;
|
||||
|
||||
{
|
||||
MaxWidth := gdk_display_get_default_cursor_size(gdk_display_get_default);
|
||||
if (Width > MaxWidth) or (Height > MaxWidth) then
|
||||
DebugLn(['CreateCursor cursor size:',Width,'x',Height,' > default size:', MaxWidth]);
|
||||
}
|
||||
|
||||
// create alpha pixbuf
|
||||
pixbuf := gdk_pixbuf_new(GDK_COLORSPACE_RGB, True, 8, Width, Height);
|
||||
|
||||
// fill pixbuf from pixmap
|
||||
gdk_pixbuf_get_from_drawable(pixbuf, pixmap, nil, 0, 0, 0, 0, -1, -1);
|
||||
|
||||
masked_pixbuf := GdkPixbufAddBitmapMask(pixbuf, bitmap, 0);
|
||||
if masked_pixbuf <> nil then
|
||||
begin
|
||||
// masked_pixuf is a new pixbuf created from pixbuf with applying mask
|
||||
gdk_pixbuf_unref(pixbuf);
|
||||
pixbuf := masked_pixbuf;
|
||||
end;
|
||||
|
||||
// create cursor from pixbuf
|
||||
try
|
||||
{$IFDEF Windows}
|
||||
// we'll get 'division by zero' error in CMCheckColorsInGamut in other case
|
||||
SetCW;
|
||||
{$ENDIF}
|
||||
Result := HCursor(PtrUInt(gdk_cursor_new_from_pixbuf(gdk_display_get_default, pixbuf,
|
||||
ACursorInfo^.xHotSpot, ACursorInfo^.yHotSpot)));
|
||||
finally
|
||||
{$IFDEF Windows}
|
||||
ResetCW;
|
||||
{$ENDIF}
|
||||
end;
|
||||
end;
|
||||
|
||||
function TGtk2WidgetSet.CreateFontIndirectEx(const LogFont: TLogFont;
|
||||
const LongFontName: string): HFONT;
|
||||
{off $DEFINE VerboseFonts}
|
||||
@ -320,6 +248,90 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
function TGtk2WidgetSet.CreateIconIndirect(IconInfo: PIconInfo): HICON;
|
||||
var
|
||||
pixmap: PGdkPixmap;
|
||||
bitmap: PGdkBitmap;
|
||||
Width, Height: integer;
|
||||
MaxWidth, MaxHeight: guint;
|
||||
pixbuf, masked_pixbuf: PGdkPixbuf;
|
||||
{$ifdef Windows}
|
||||
Old80807CW: Word;
|
||||
|
||||
procedure SetCW; inline;
|
||||
begin
|
||||
Old80807CW := Get8087CW;
|
||||
Set8087CW($133F);
|
||||
end;
|
||||
|
||||
procedure ResetCW; inline;
|
||||
begin
|
||||
Set8087CW(Old80807CW);
|
||||
end;
|
||||
{$endif}
|
||||
begin
|
||||
Result := 0;
|
||||
if not IsValidGDIObject(IconInfo^.hbmColor) then Exit;
|
||||
|
||||
pixmap := PGDIObject(IconInfo^.hbmColor)^.GDIPixmapObject.Image;
|
||||
bitmap := PGDIObject(IconInfo^.hbmColor)^.GDIPixmapObject.Mask;
|
||||
|
||||
gdk_drawable_get_size(pixmap, @Width, @Height);
|
||||
gdk_display_get_maximal_cursor_size(gdk_display_get_default,
|
||||
@MaxWidth, @MaxHeight);
|
||||
|
||||
if (Width > integer(MaxWidth)) or (Height > integer(MaxHeight)) then
|
||||
exit;
|
||||
|
||||
// create alpha pixbuf
|
||||
pixbuf := gdk_pixbuf_new(GDK_COLORSPACE_RGB, True, 8, Width, Height);
|
||||
|
||||
// fill pixbuf from pixmap
|
||||
gdk_pixbuf_get_from_drawable(pixbuf, pixmap, nil, 0, 0, 0, 0, -1, -1);
|
||||
|
||||
masked_pixbuf := GdkPixbufAddBitmapMask(pixbuf, bitmap, 0);
|
||||
if masked_pixbuf <> nil then
|
||||
begin
|
||||
// masked_pixuf is a new pixbuf created from pixbuf with applying mask
|
||||
gdk_pixbuf_unref(pixbuf);
|
||||
pixbuf := masked_pixbuf;
|
||||
end;
|
||||
|
||||
if IconInfo^.fIcon then
|
||||
Result := HICON(PtrUInt(pixbuf))
|
||||
else
|
||||
begin
|
||||
// create cursor from pixbuf
|
||||
try
|
||||
{$IFDEF Windows}
|
||||
// we'll get 'division by zero' error in CMCheckColorsInGamut in other case
|
||||
SetCW;
|
||||
{$ENDIF}
|
||||
Result := HCURSOR(PtrUInt(gdk_cursor_new_from_pixbuf(gdk_display_get_default, pixbuf,
|
||||
IconInfo^.xHotSpot, IconInfo^.yHotSpot)));
|
||||
finally
|
||||
{$IFDEF Windows}
|
||||
ResetCW;
|
||||
{$ENDIF}
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TGtk2WidgetSet.DestroyIcon(Handle: HICON): Boolean;
|
||||
begin
|
||||
Result := (Handle <> 0) and
|
||||
(
|
||||
GDK_IS_PIXBUF(Pointer(Handle)) or
|
||||
// todo: replace with GDK_IS_CURSOR when fpc will have it
|
||||
G_TYPE_CHECK_INSTANCE_TYPE(Pointer(Handle),GDK_TYPE_CURSOR)
|
||||
);
|
||||
if Result then
|
||||
if GDK_IS_PIXBUF(Pointer(Handle)) then
|
||||
gdk_pixbuf_unref(PGdkPixbuf(Handle))
|
||||
else
|
||||
gdk_cursor_unref(PGdkCursor(Handle));
|
||||
end;
|
||||
|
||||
|
||||
{------------------------------------------------------------------------------
|
||||
Function: EndPaint
|
||||
|
@ -35,8 +35,9 @@
|
||||
|
||||
function BeginPaint(Handle: hWnd; Var PS : TPaintStruct) : hdc; override;
|
||||
|
||||
function CreateCursor(ACursorInfo: PIconInfo): hCursor; override;
|
||||
function CreateFontIndirectEx(const LogFont: TLogFont; const LongFontName: string): HFONT; override;
|
||||
function CreateIconIndirect(IconInfo: PIconInfo): HICON; override;
|
||||
function DestroyIcon(Handle: HICON): Boolean; override;
|
||||
|
||||
function EndPaint(Handle : hwnd; var PS : TPaintStruct): Integer; override;
|
||||
function ExtTextOut(DC: HDC; X, Y: Integer; Options: Longint; Rect: PRect; Str: PChar; Count: Longint; Dx: PInteger): Boolean; override;
|
||||
|
Loading…
Reference in New Issue
Block a user