LCL-GTK3: Improve bitmap drawing etc. Issue #38567, patch from Anton Kavalenka.

git-svn-id: trunk@64802 -
This commit is contained in:
juha 2021-03-14 08:12:17 +00:00
parent 2b0050a648
commit 1d097a9a7d
4 changed files with 154 additions and 17 deletions

View File

@ -180,6 +180,8 @@ begin
Result:=inherited GetAcceleratorString(AVKey,AShiftState);
end;
{------------------------------------------------------------------------------
Function: RawImage_CreateBitmap
Params: ARawImage:
@ -196,6 +198,9 @@ var
NewData: PByte;
ImageFormat: cairo_format_t;
ARowStride: PtrUInt;
x,y:integer;
src,dst,pdst,psrc,SrcRowPtr,DstRowPtr:pbyte;
ridx,gidx,bidx,aidx:byte;
begin
Result := False;
ABitmap := 0;
@ -203,8 +208,57 @@ begin
if ARawImage.DataSize > 0 then
begin
NewData := GetMem(ARawImage.DataSize);
Move(ARawImage.Data^, NewData^, ARawImage.DataSize);
case Desc.LineEnd of
rileQWordBoundary:
begin
ARowStride := Desc.Width;
if Desc.Width and 1 <> 0 then Inc(ARowStride);
ARowStride := ARowStride shl 2;
end;
rileDQWordBoundary:
begin
ARowStride := Desc.Width shr 1;
if Desc.Width and 3 <> 0 then Inc(ARowStride);
ARowStride := ARowStride shl 3;
end;
else
ARowStride := Desc.Width shl 2;
end;
// check if the pixels are in order, pixbuf expects them in R-G-B-A
Desc.GetRGBIndices(Ridx, Gidx, Bidx, AIdx);
GetMem(NewData, ArawImage.DataSize);
//if (Ridx <> 0) or (Gidx <> 1) or (Bidx <> 2) or (AIdx <> 3) then
begin
// put components in right order
DstRowPtr := NewData;
SrcRowPtr := ArawImage.Data;
y := Desc.Height;
while y > 0 do
begin
Src := SrcRowPtr;
Dst := DstRowPtr;
x := Desc.Width;
while x > 0 do
begin
Dst[0] := Src[Ridx];
Dst[1] := Src[Gidx];
Dst[2] := Src[Bidx];
Dst[3] := $ff;//Src[Aidx] ;
Inc(Src, 4);
Inc(Dst, 4);
Dec(x);
end;
Inc(SrcRowPtr, ARowstride);
Inc(DstRowPtr, ARowstride);
Dec(y);
end;
end;
end
else
NewData := nil;
@ -218,21 +272,26 @@ begin
end;
ARowStride := GetBytesPerLine(Desc.Width, Desc.BitsPerPixel, rileDWordBoundary);
ABitmap := HBitmap(TGtk3Image.Create(NewData, Desc.Width, Desc.Height, ARowStride, ImageFormat,
not ASkipMask)); // Using ASkipMask for DataOwner param prevents a crash later.
{not ASkipMask}true)); // Using ASkipMask for DataOwner param prevents a crash later.
Result := ABitmap <> 0;
{ if ASkipMask then
FreeMem(NewData); }
if ASkipMask then Exit;
if (ARawImage.Mask <> nil) and (ARawImage.MaskSize > 0) then
begin
NewData := GetMem(ARawImage.MaskSize);
//FillChar(NewData^, ARawImage.MaskSize,$ff);
Move(ARawImage.Mask^, NewData^, ARawImage.MaskSize);
end
else
NewData := nil;
ARowStride := GetBytesPerLine(Desc.Width, Desc.BitsPerPixel, rileDWordBoundary);
AMask := HBitmap(TGtk3Image.Create(NewData, Desc.Width, Desc.Height, ARowStride, CAIRO_FORMAT_A1, True));
ARowStride := GetBytesPerLine(Desc.Width, {Desc.BitsPerPixel}8, rileDWordBoundary);
AMask := HBitmap(TGtk3Image.Create(NewData, Desc.Width, Desc.Height, ARowStride, CAIRO_FORMAT_A8, True));
end;
@ -747,7 +806,7 @@ begin
if InvertPixels then
WorkMask.invertPixels(QImageInvertRGB);
*)
if WorkMask.bits<>nil then
if (WorkMask.bits<>nil) and (ARawImage.Mask<>nil) then
Move(WorkMask.bits^, ARawImage.Mask^, ARawImage.MaskSize);
// if InvertPixels then
// WorkMask.invertPixels(QImageInvertRGB);

View File

@ -264,6 +264,7 @@ type
procedure fillRect(x, y, w, h: Integer; ABrush: HBRUSH); overload;
procedure fillRect(x, y, w, h: Integer); overload;
function RoundRect(X1, Y1, X2, Y2: Integer; RX, RY: Integer): Boolean;
function drawFrameControl(arect:TRect;uType,uState:cardinal):boolean;
function drawFocusRect(const aRect: TRect): boolean;
function getBpp: integer;
function getDepth: integer;
@ -714,11 +715,12 @@ begin
sz:=fHandle^.get_size;
if fHandle^.get_size_is_absolute then
begin
sz:=12;// sz div PANGO_SCALE;
sz:= sz div PANGO_SCALE;
end else
begin
{ in points }
sz:=round(96*sz/PANGO_SCALE/72);//round(2.03*sz/PANGO_SCALE);
//sz:=round(96*sz/PANGO_SCALE/72);//round(2.03*sz/PANGO_SCALE);
sz := MulDiv(sz, 96{Screen.PixelsPerInch}, 72 * PANGO_SCALE)
end;
fLogFont.lfHeight:=sz;//round(sz/PANGO_SCALE);
@ -2103,6 +2105,79 @@ begin
end;
end;
function TGtk3DeviceContext.drawFrameControl(arect:TRect;uType,uState:cardinal):boolean;
var
Context: PGtkStyleContext;
AValue: TGValue;
pw:PGtkWidget;
path:PGtkwIdgetPath;
pc:pgchar;
w:PgtkWidget;
begin
Result:=false;
{ if Parent <> nil then
Context := Parent^.get_style_context
else
begin
Context:=TGtkStyleContext.new();
Context^.add_class('button');
end;
if Context = nil then
begin
DebugLn('WARNING: TGtk3WidgetSet.DrawFrameControl on non widget context isn''t implemented.');
exit;
end; }
w:=nil;
if uType=DFC_BUTTON then
begin
w:=GetStyleWidget(lgsButton);
end else
if uType=DFC_MENU then
begin
w:=GetStyleWidget(lgsMenu);
end;
if not Assigned(w) then exit;
Context:=w^.get_style_context;
path:=w^.get_path;
gtk_style_context_set_path (context, path);
gtk_style_context_set_state (context,(* gtk_widget_path_iter_get_state (path, -1)*) -1);
{GTK_STATE_FLAG_NORMAL: TGtkStateFlags = 0;
GTK_STATE_FLAG_ACTIVE: TGtkStateFlags = 1;
GTK_STATE_FLAG_PRELIGHT: TGtkStateFlags = 2;
GTK_STATE_FLAG_SELECTED: TGtkStateFlags = 4;
GTK_STATE_FLAG_INSENSITIVE: TGtkStateFlags = 8;
GTK_STATE_FLAG_INCONSISTENT: TGtkStateFlags = 16;
GTK_STATE_FLAG_FOCUSED: TGtkStateFlags = 32;
GTK_STATE_FLAG_BACKDROP: TGtkStateFlags = 64;
GTK_STATE_FLAG_DIR_LTR: TGtkStateFlags = 128;
GTK_STATE_FLAG_DIR_RTL: TGtkStateFlags = 256;
}
gtk_style_context_set_state (context, GTK_STATE_FLAG_FOCUSED or GTK_STATE_FLAG_PRELIGHT);
pw:=w;
while Assigned(pw) do
begin
Context:=pw^.get_style_context;
path:=pw^.get_path;
with aRect do
begin
gtk_render_background(Context,pcr, Left, Top, Right - Left, Bottom - Top);
gtk_render_frame(Context,pcr, Left, Top, Right - Left, Bottom - Top);
end;
pw:=pw^.parent;
end;
Result := True;
end;
function TGtk3DeviceContext.drawFocusRect(const aRect: TRect): boolean;
var
Context: PGtkStyleContext;

View File

@ -2370,7 +2370,7 @@ begin
*)
end else
begin
ARgba := TColortoTGdkRGBA(AValue);
ARgba := TColortoTGdkRGBA(ColorToRGB(AValue));
{$info GTK3: set GdkRGBA.alpah to 1.0?}
{ColorToCairoRGB(ColorToRGB(AValue), R, G, B);
@ -6734,10 +6734,15 @@ begin
Result := PGtkWidget(check);
check^.set_use_underline(True);
{fWidgetRGBA[0].G:=0.8;
fWidgetRGBA[0].Alpha:=0.7;
check^.override_color(GTK_STATE_NORMAL,@Self.FWidgetRGBA[0]);}
fWidgetRGBA[0].Alpha:=1;
check^.override_color(GTK_STATE_FLAG_NORMAL,@Self.FWidgetRGBA[0]);}
(*fWidgetRGBA[0].G:=0.8;
fWidgetRGBA[0].B:=0.9;
fWidgetRGBA[0].Alpha:=0.9;
check^.override_color(GTK_STATE_FLAG_ACTIVE,@Self.FWidgetRGBA[0]); *)
// nil resets color to gtk default
FWidget^.override_background_color(GTK_STATE_FLAG_NORMAL, nil);
{ FWidget^.override_color(GTK_STATE_FLAG_NORMAL, nil);
FWidget^.override_background_color(GTK_STATE_FLAG_NORMAL, nil);}
end;
{ TGtk3RadioButton }

View File

@ -600,11 +600,9 @@ end;
function TGtk3WidgetSet.DrawFrameControl(DC: HDC; const aRect: TRect; uType,
uState: Cardinal): Boolean;
begin
{$IFDEF GTK3DEBUGNOTIMPLEMENTED}
DebugLn('WARNING: TGtk3WidgetSet.DrawFrameControl not implemented ...');
{$ENDIF}
Result := False;
// inherited DrawFrameControl(DC, aRect, uType, uState);
Result:=false;
if IsValidDC(DC) then
Result:=TGtk3DeviceContext(DC).drawFrameControl(aRect,uType,uState);
end;
function TGtk3WidgetSet.DrawFocusRect(DC: HDC; const aRect: TRect): boolean;