View Issue Details

IDProjectCategoryView StatusLast Update
0036744LazarusPatchpublic2020-04-17 22:02
ReporterAnton Kavalenka Assigned ToJuha Manninen  
PrioritynormalSeverityminorReproducibilityalways
Status closedResolutionfixed 
Product Version2.1 (SVN) 
Summary0036744: gtk3: First approach in implementing pattern brush
DescriptionApply the patch.
Currently only one test pattern is implemented.

Attn:
@CudaText man
@Juha Manninen

Run the test from https://bugs.freepascal.org/file_download.php?file_id=32485&type=bug
Steps To ReproduceRun the test from https://bugs.freepascal.org/file_download.php?file_id=32485&type=bug
TagsNo tags attached.
Fixed in Revisionr62687, r62917
LazTarget-
WidgetsetGTK 3
Attached Files

Relationships

related to 0036374 resolvedJuha Manninen gtk3: Canvas artifacts, swapped R/B colors 
related to 0036826 new GTK3 AutoSize TCheckListBox 

Activities

Anton Kavalenka

2020-02-29 13:53

reporter  

gtk3objects.diff (4,816 bytes)   
Index: lcl/interfaces/gtk3/gtk3objects.pas
===================================================================
--- lcl/interfaces/gtk3/gtk3objects.pas	(revision 62686)
+++ lcl/interfaces/gtk3/gtk3objects.pas	(working copy)
@@ -82,12 +82,16 @@
     FContext: TGtk3DeviceContext;
     FStyle: LongWord;
     procedure SetColor(AValue: TColor);
+    procedure SetStyle(AStyle:longword);
   public
+    brush_pattern:pcairo_pattern_t;
     LogBrush: TLogBrush;
     constructor Create; override;
+    destructor Destroy;override;
+    procedure UpdatePattern;
     property Color: TColor read FColor write SetColor;
     property Context: TGtk3DeviceContext read FContext write FContext;
-    property Style: LongWord read FStyle write FStyle;
+    property Style: LongWord read FStyle write SetStyle;
   end;
 
   { TGtk3Pen }
@@ -295,6 +299,45 @@
   FDefaultContext: TGtk3DeviceContext = nil;
   FScreenContext: TGtk3DeviceContext = nil;
 
+  function create_stipple(stipple_data:pbyte;width,height:integer):pcairo_pattern_t;forward;
+
+  const COLOR_A_PRE = $3093BA52;
+  const COLOR_B_PRE = $30FFFFFF;
+  (*function PREMULTIPLY(argb:dword);inline                                                                          \
+  	((argb & 0xFF << 24) |                                                                         \
+  	 ((((argb & 0xFF << 16) >> 16) * ((argb & 0xFF << 24) >> 24) / 0xFF) << 16) |                  \
+  	 ((((argb & 0xFF << 8) >> 8) * ((argb & 0xFF << 24) >> 24) / 0xFF) << 8) |                     \
+  	 ((((argb & 0xFF << 0) >> 0) * ((argb & 0xFF << 24) >> 24) / 0xFF) << 0))
+  #define COLOR_A_PRE PREMULTIPLY (COLOR_A)
+  #define COLOR_B_PRE PREMULTIPLY (COLOR_B)
+  *)
+  const
+       stipple_data:array[0..8 * 8-1] of dword = (
+  	    COLOR_A_PRE, COLOR_A_PRE, COLOR_A_PRE, COLOR_B_PRE, COLOR_B_PRE, COLOR_B_PRE, COLOR_B_PRE,
+  	    COLOR_A_PRE, COLOR_A_PRE, COLOR_A_PRE, COLOR_B_PRE, COLOR_B_PRE, COLOR_B_PRE, COLOR_B_PRE,
+  	    COLOR_A_PRE, COLOR_A_PRE, COLOR_A_PRE, COLOR_B_PRE, COLOR_B_PRE, COLOR_B_PRE, COLOR_B_PRE,
+  	    COLOR_A_PRE, COLOR_A_PRE, COLOR_A_PRE, COLOR_B_PRE, COLOR_B_PRE, COLOR_B_PRE, COLOR_B_PRE,
+  	    COLOR_A_PRE, COLOR_A_PRE, COLOR_A_PRE, COLOR_A_PRE,
+
+  	    COLOR_B_PRE, COLOR_B_PRE, COLOR_B_PRE, COLOR_A_PRE, COLOR_A_PRE, COLOR_A_PRE, COLOR_A_PRE,
+  	    COLOR_B_PRE, COLOR_B_PRE, COLOR_B_PRE, COLOR_A_PRE, COLOR_A_PRE, COLOR_A_PRE, COLOR_A_PRE,
+  	    COLOR_B_PRE, COLOR_B_PRE, COLOR_B_PRE, COLOR_A_PRE, COLOR_A_PRE, COLOR_A_PRE, COLOR_A_PRE,
+  	    COLOR_B_PRE, COLOR_B_PRE, COLOR_B_PRE, COLOR_A_PRE, COLOR_A_PRE, COLOR_A_PRE, COLOR_A_PRE,
+  	    COLOR_B_PRE, COLOR_B_PRE, COLOR_B_PRE, COLOR_B_PRE);
+
+  	(* the stipple patten should look like that
+  	 *	    1 1 1 0  0 0 0 1
+  	 *	    1 1 0 0  0 0 1 1
+  	 *	    1 0 0 0  0 1 1 1
+  	 *	    0 0 0 0  1 1 1 1
+  	 *
+  	 *	    0 0 0 1  1 1 1 0
+  	 *	    0 0 1 1  1 1 0 0
+  	 *	    0 1 1 1  1 0 0 0
+  	 *	    1 1 1 1  0 0 0 0
+  	 *)
+
+
 function Gtk3DefaultContext: TGtk3DeviceContext;
 begin
   if FDefaultContext = nil then
@@ -852,6 +895,13 @@
     cairo_set_source_rgb(FContext.Widget, ARed, AGreen, ABlue);
 end;
 
+procedure TGtk3Brush.SetStyle(AStyle: longword);
+begin
+  if AStyle=fStyle then exit;
+  fStyle:=AStyle;
+  Self.UpdatePattern;
+end;
+
 constructor TGtk3Brush.Create;
 begin
   inherited Create;
@@ -862,6 +912,36 @@
   FillChar(LogBrush, SizeOf(TLogBrush), #0);
 end;
 
+destructor TGtk3Brush.Destroy;
+begin
+  if Assigned(brush_pattern) then
+    cairo_pattern_destroy(brush_pattern);
+  inherited Destroy;
+end;
+
+procedure TGtk3Brush.UpdatePattern;
+begin
+  if Assigned(Self.brush_pattern) then
+     cairo_pattern_destroy(brush_pattern);
+  self.brush_pattern:=create_stipple(@stipple_data,8,8); // this stipple_data is 8x8
+end;
+
+function create_stipple(stipple_data:pbyte;width,height:integer):pcairo_pattern_t;
+var
+  surface:pcairo_surface_t;
+	pattern:pcairo_pattern_t;
+  stride:integer;
+begin
+	stride := cairo_format_stride_for_width (CAIRO_FORMAT_ARGB32, width);
+	surface := cairo_image_surface_create_for_data (stipple_data, CAIRO_FORMAT_ARGB32, width, height,
+	                                               stride);
+	pattern := cairo_pattern_create_for_surface (surface);
+	cairo_surface_destroy (surface);
+	cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT);
+
+	result:= pattern;
+end;
+
 { TGtk3DeviceContext }
 
 function TGtk3DeviceContext.GetOffset: TPoint;
@@ -937,6 +1017,12 @@
     //cairo_set_source_surface(Widget, CairoSurface, 0 , 0);
   end else
     SetSourceColor(FCurrentBrush.Color);
+
+  if Self.FCurrentBrush.Style<>0 then
+  begin
+    if Assigned(Self.FCurrentBrush.brush_pattern) then
+    cairo_set_source(Widget,Self.FCurrentBrush.brush_pattern);
+  end;
 end;
 
 procedure TGtk3DeviceContext.ApplyFont;
gtk3objects.diff (4,816 bytes)   

CudaText man

2020-02-29 15:48

reporter   ~0121280

tested. now with that demo, I see that outer rectangle has green border, and inner triangle has red border - nice, but where is custom brush filling of rect/triangle?

   Brush.Style:=TBrushStyle(5);

Anton Kavalenka

2020-02-29 16:06

reporter   ~0121281

The test project has no LCL in dependencies - just force LCL rebuild

Juha Manninen

2020-02-29 22:14

developer   ~0121284

I applied the patch in r62687. At least it does not break anything.
I saw only white background and a red line forming a triangle. No other colors. Without the patch I saw black background.

CudaText man

2020-03-01 08:45

reporter   ~0121289

Backgnd must not be white nor black. it must be filled with diagonal colored lines (because of constants in demo).

CudaText man

2020-03-01 08:48

reporter   ~0121290

I see white filled figures (with colored red/green borders). I have here LCL in proj dependencies.

Anton Kavalenka

2020-03-01 09:31

reporter   ~0121291

Last edited: 2020-03-01 09:46

View 2 revisions

I'm under Debian GNU/Linux 10.2
In attachment - all my GTK3 diff from trunk. I think these changes irrelevant to brush style.

Or maybe BGRA <-> RGBA mess is the reason.

my_gtk3.diff (3,677 bytes)   
Index: lcl/interfaces/gtk3/gtk3int.pas
===================================================================
--- lcl/interfaces/gtk3/gtk3int.pas	(revision 62688)
+++ lcl/interfaces/gtk3/gtk3int.pas	(working copy)
@@ -191,9 +191,9 @@
   Desc.BluePrec := 8;
 
   Desc.AlphaShift := 24;
-  Desc.RedShift := 16;
+  Desc.RedShift := 0;
   Desc.GreenShift := 8;
-//  Desc.BlueShift := 0;
+  Desc.BlueShift := 16;
 
   // Qt wants dword-aligned data
   Desc.MaskLineEnd := rileDWordBoundary;
Index: lcl/interfaces/gtk3/gtk3lclintf.inc
===================================================================
--- lcl/interfaces/gtk3/gtk3lclintf.inc	(revision 62688)
+++ lcl/interfaces/gtk3/gtk3lclintf.inc	(working copy)
@@ -319,9 +319,9 @@
         ADesc.BluePrec := 8;
 
         ADesc.AlphaShift := 24;
-        ADesc.RedShift := 16;
+        ADesc.RedShift := 0;
         ADesc.GreenShift := 8;
-        ADesc.BlueShift := 0;
+        ADesc.BlueShift := 16;
       end;
   end;
   (*
Index: lcl/interfaces/gtk3/gtk3object.inc
===================================================================
--- lcl/interfaces/gtk3/gtk3object.inc	(revision 62688)
+++ lcl/interfaces/gtk3/gtk3object.inc	(working copy)
@@ -95,11 +95,13 @@
   g_type_init;
   gtk_init(@argc, @argv);
   AGtkThread := g_thread_self();
+  if not IsLibrary then
+  begin
   AId := 'org.lcl.thread_' + dbgHex(PtrUInt(AGtkThread));
   FGtk3Application := TGtkApplication.new(PgChar(AId), G_APPLICATION_NON_UNIQUE);
   // FGtk3Application^.set_application_id(PgChar(AId));
   FGtk3Application^.register(nil, nil);
-
+  end;
   GTK3WidgetSet := Self;
 end;
 
Index: lcl/interfaces/gtk3/gtk3winapi.inc
===================================================================
--- lcl/interfaces/gtk3/gtk3winapi.inc	(revision 62688)
+++ lcl/interfaces/gtk3/gtk3winapi.inc	(working copy)
@@ -4044,7 +4044,7 @@
   ATargetRect := Rect(X, Y, Width + X, Height + Y);
   ASrcRect := Rect(XSrc, YSrc, SrcWidth + XSrc, SrcHeight + YSrc);
 
-  if (DestContext.OwnsSurface) then
+  if (SrcContext.CurrentImage<>nil) and DestContext.OwnsSurface  then {image to image copy}
     DestContext.drawImage1(@ATargetRect, PgdkPixbuf(SrcContext.CurrentImage.Handle) , @ASrcRect, nil, nil)
   else
     DestContext.drawSurface(@ATargetRect,SrcContext.CairoSurface , @ASrcRect, nil, nil);
Index: lcl/interfaces/gtk3/gtk3wsbuttons.pp
===================================================================
--- lcl/interfaces/gtk3/gtk3wsbuttons.pp	(revision 62688)
+++ lcl/interfaces/gtk3/gtk3wsbuttons.pp	(working copy)
@@ -137,7 +137,7 @@
       resolution.GetRawImage(ABitBtn.ImageIndex,raw);
       { convice the bitmap it has actually another format }
       AGlyph.BeginUpdate();
-      raw.Description.Init_BPP32_R8G8B8A8_BIO_TTB(resolution.Width,resolution.Height);
+     // raw.Description.Init_BPP32_R8G8B8A8_BIO_TTB(resolution.Width,resolution.Height);
       AGlyph.LoadFromRawImage(raw,false);
       AGlyph.EndUpdate();
     end else
Index: lcl/interfaces/gtk3/gtk3wsimglist.pp
===================================================================
--- lcl/interfaces/gtk3/gtk3wsimglist.pp	(revision 62688)
+++ lcl/interfaces/gtk3/gtk3wsimglist.pp	(working copy)
@@ -60,6 +60,7 @@
 
 
 implementation
+uses gtk3objects,lazgdkpixbuf2;
 
 { TGtk3WSCustomImageListResolution }
 
@@ -94,6 +95,9 @@
 begin
   inherited Draw(AList, AIndex, ACanvas, ABounds, ABkColor, ABlendColor,
     ADrawEffect, AStyle, AImageType);
+{  TGtk3DeviceContext(ACanvas.Handle).drawImglistRes(AList,
+  AIndex,ABounds,ABkColor,
+  ABlendColor,ADrawEffect,AStyle, AImageType);}
 end;
 
 class procedure TGtk3WSCustomImageListResolution.Insert(AList: TCustomImageListResolution;
my_gtk3.diff (3,677 bytes)   

Juha Manninen

2020-03-01 09:52

developer   ~0121292

Last edited: 2020-03-01 10:00

View 2 revisions

I attach a screenshot to prove my case. I have Manjaro Linux + KDE. With QT5 bindings I also see the stripes in the pic correctly.
Yes, the project has LCL dependency.

> In attachment - all my GTK3 diff from trunk. I think these changes irrelevant to brush style.
Git with its local branches is nice when you have changes for many features at the same time. Recommended.

GTK3_CanvasBrush.png (8,979 bytes)   
GTK3_CanvasBrush.png (8,979 bytes)   

Anton Kavalenka

2020-03-02 12:19

reporter   ~0121312

Last edited: 2020-03-02 12:26

View 2 revisions

I was able to repeat your white background.

changing pattern colors to
  const COLOR_A_PRE = $20003300; // slightly green
  const COLOR_B_PRE = $00FFFFFF;

make pattern brush appear

Anton Kavalenka

2020-03-02 12:26

reporter  

CudaText man

2020-03-02 21:27

reporter   ~0121319

1. code is formatted awful. spaces / indents. keep the style of gtk3 code.
2. why using "Self." where it's no need?

Anton Kavalenka

2020-03-03 06:29

reporter   ~0121332

Last edited: 2020-03-03 06:39

View 3 revisions

@CudaText man
1. Patch is already applied in r62687 and IS in proper code style.
create_stipple is ported from GTK3 C++ example.
The second patch my_gtk2.diff has no relation with the problem and is just my exercise trying to fix another problems and guess whats wrong with white background.
This patch should be dropped out.
2. Self. is convenient with code-completion.

In any way it is "first approach" and both the stipple_data and create_stipple() has to be reworked.

Btw my exercise with RGBA clearly shows that basic LCL code is broken. Because the mechanism which stores shared bitmap handles can not account bitmaps in non-default (RGBA) format. Default for LCL is windows-one - BGRA

Anton Kavalenka

2020-04-08 16:55

reporter   ~0122034

GTK3 hatched brush is working. Attached patch proposes

* OOP approach in SelectObject implementation
* Hatched brushes implemented
* Surprisingly in some conditions GTK3 code can run in DLL, as on widgetset initialization no application registration performed.
* Fixes for 0036826 included
gtk3updates.diff (18,507 bytes)   
Index: gtk3object.inc
===================================================================
--- gtk3object.inc	(revision 62896)
+++ gtk3object.inc	(working copy)
@@ -95,11 +95,13 @@
   g_type_init;
   gtk_init(@argc, @argv);
   AGtkThread := g_thread_self();
+  if not IsLibrary then
+  begin
   AId := 'org.lcl.thread_' + dbgHex(PtrUInt(AGtkThread));
   FGtk3Application := TGtkApplication.new(PgChar(AId), G_APPLICATION_NON_UNIQUE);
   // FGtk3Application^.set_application_id(PgChar(AId));
   FGtk3Application^.register(nil, nil);
-
+  end;
   GTK3WidgetSet := Self;
 end;
 
@@ -727,7 +729,7 @@
 
 function TGtk3WidgetSet.IsValidGDIObject(const AGdiObject: HGDIOBJ): Boolean;
 begin
-  Result := AGdiObject <> 0;
+  Result := (AGdiObject <> 0) and (TObject(AGdiObject) is TGtk3ContextObject);
 end;
 
 function TGtk3WidgetSet.IsValidHandle(const AHandle: HWND): Boolean;
Index: gtk3objects.pas
===================================================================
--- gtk3objects.pas	(revision 62896)
+++ gtk3objects.pas	(working copy)
@@ -50,8 +50,10 @@
   TGtk3ContextObject = class(TGtk3Object)
   private
     FShared: Boolean;
+    fContext:TGtk3DeviceContext;
   public
     constructor Create; override;
+    function Select(ACtx:TGtk3DeviceContext):TGtk3ContextObject;virtual;
     property Shared: Boolean read FShared write FShared;
   end;
 
@@ -66,6 +68,7 @@
   public
     constructor Create(ACairo: Pcairo_t; AWidget: PGtkWidget = nil);
     constructor Create(ALogFont: TLogFont; const ALongFontName: String);
+    function Select(ACtx:TGtk3DeviceContext):TGtk3ContextObject;override;
     destructor Destroy; override;
     procedure UpdateLogFont;
     property FontName: String read FFontName write FFontName;
@@ -79,14 +82,15 @@
   TGtk3Brush = class(TGtk3ContextObject)
   private
     FColor: TColor;
-    FContext: TGtk3DeviceContext;
     FStyle: LongWord;
     procedure SetColor(AValue: TColor);
     procedure SetStyle(AStyle:longword);
   public
     brush_pattern:pcairo_pattern_t;
+    pat_buf:pdword;
     LogBrush: TLogBrush;
     constructor Create; override;
+    function Select(ACtx:TGtk3DeviceContext):TGtk3ContextObject;override;
     destructor Destroy;override;
     procedure UpdatePattern;
     property Color: TColor read FColor write SetColor;
@@ -105,7 +109,6 @@
     FStyle: TFPPenStyle;
     FWidth: Integer;
     FColor: TColor;
-    FContext: TGtk3DeviceContext;
     FIsExtPen: Boolean;
     procedure SetColor(AValue: TColor);
     procedure setCosmetic(b: Boolean);
@@ -113,6 +116,7 @@
   public
     LogPen: TLogPen;
     constructor Create; override;
+    function Select(ACtx:TGtk3DeviceContext):TGtk3ContextObject;override;
     property Color: TColor read FColor write SetColor;
     property Context: TGtk3DeviceContext read FContext write FContext;
 
@@ -134,6 +138,7 @@
     property Handle: Pcairo_region_t read FHandle write FHandle;
     constructor Create(CreateHandle: Boolean); virtual; overload;
     constructor Create(CreateHandle: Boolean; X1,Y1,X2,Y2: Integer); virtual; overload;
+    function Select(ACtx:TGtk3DeviceContext):TGtk3ContextObject;override;
     destructor Destroy; override;
     function GetExtents: TRect;
     function ContainsRect(ARect: TRect): Boolean;
@@ -153,6 +158,7 @@
     constructor Create(vHandle: PGdkPixbuf); overload;
     constructor Create(AData: PByte; width: Integer; height: Integer; format: cairo_format_t; const ADataOwner: Boolean = False); overload;
     constructor Create(AData: PByte; width: Integer; height: Integer; bytesPerLine: Integer; format: cairo_format_t; const ADataOwner: Boolean = False); overload;
+    function Select(ACtx:TGtk3DeviceContext):TGtk3ContextObject;override;
     destructor Destroy; override;
     procedure CopyFrom(AImage: PGdkPixbuf; x, y, w, h: integer);
     function height: Integer;
@@ -301,30 +307,10 @@
 
   function create_stipple(stipple_data:pbyte;width,height:integer):pcairo_pattern_t;forward;
 
-  const COLOR_A_PRE = $3093BA52;
-  const COLOR_B_PRE = $30FFFFFF;
-  (*function PREMULTIPLY(argb:dword);inline                                                                          \
-        ((argb & 0xFF << 24) |                                                                         \
-         ((((argb & 0xFF << 16) >> 16) * ((argb & 0xFF << 24) >> 24) / 0xFF) << 16) |                  \
-         ((((argb & 0xFF << 8) >> 8) * ((argb & 0xFF << 24) >> 24) / 0xFF) << 8) |                     \
-         ((((argb & 0xFF << 0) >> 0) * ((argb & 0xFF << 24) >> 24) / 0xFF) << 0))
-  #define COLOR_A_PRE PREMULTIPLY (COLOR_A)
-  #define COLOR_B_PRE PREMULTIPLY (COLOR_B)
-  *)
+  const clr_A = $FF008000;//$3093BA52;
+  const clr_B = $FFFFFFFF;//$30FFFFFF;
+
   const
-       stipple_data: array[0..8 * 8-1] of dword = (
-            COLOR_A_PRE, COLOR_A_PRE, COLOR_A_PRE, COLOR_B_PRE, COLOR_B_PRE, COLOR_B_PRE, COLOR_B_PRE,
-            COLOR_A_PRE, COLOR_A_PRE, COLOR_A_PRE, COLOR_B_PRE, COLOR_B_PRE, COLOR_B_PRE, COLOR_B_PRE,
-            COLOR_A_PRE, COLOR_A_PRE, COLOR_A_PRE, COLOR_B_PRE, COLOR_B_PRE, COLOR_B_PRE, COLOR_B_PRE,
-            COLOR_A_PRE, COLOR_A_PRE, COLOR_A_PRE, COLOR_B_PRE, COLOR_B_PRE, COLOR_B_PRE, COLOR_B_PRE,
-            COLOR_A_PRE, COLOR_A_PRE, COLOR_A_PRE, COLOR_A_PRE,
-
-            COLOR_B_PRE, COLOR_B_PRE, COLOR_B_PRE, COLOR_A_PRE, COLOR_A_PRE, COLOR_A_PRE, COLOR_A_PRE,
-            COLOR_B_PRE, COLOR_B_PRE, COLOR_B_PRE, COLOR_A_PRE, COLOR_A_PRE, COLOR_A_PRE, COLOR_A_PRE,
-            COLOR_B_PRE, COLOR_B_PRE, COLOR_B_PRE, COLOR_A_PRE, COLOR_A_PRE, COLOR_A_PRE, COLOR_A_PRE,
-            COLOR_B_PRE, COLOR_B_PRE, COLOR_B_PRE, COLOR_A_PRE, COLOR_A_PRE, COLOR_A_PRE, COLOR_A_PRE,
-            COLOR_B_PRE, COLOR_B_PRE, COLOR_B_PRE, COLOR_B_PRE);
-
         (* the stipple patten should look like that
          *	    1 1 1 0  0 0 0 1
          *	    1 1 0 0  0 0 1 1
@@ -337,7 +323,84 @@
          *	    1 1 1 1  0 0 0 0
          *)
 
+       stipple_bdiag: array[0..8 * 8-1] of dword = (
+            clr_A, clr_A, clr_A, clr_B, clr_B, clr_B, clr_B, clr_A,
+            clr_A, clr_A, clr_B, clr_B, clr_B, clr_B, clr_A, clr_A,
+            clr_A, clr_B, clr_B, clr_B, clr_B, clr_A, clr_A, clr_A,
+            clr_B, clr_B, clr_B, clr_B, clr_A, clr_A, clr_A, clr_A,
+            //-----------------------------------------------------
+            clr_B, clr_B, clr_B, clr_A, clr_A, clr_A, clr_A, clr_B,
+            clr_B, clr_B, clr_A, clr_A, clr_A, clr_A, clr_B, clr_B,
+            clr_B, clr_A, clr_A, clr_A, clr_A, clr_B, clr_B, clr_B,
+            clr_A, clr_A, clr_A, clr_A, clr_B, clr_B, clr_B, clr_B);
 
+        stipple_fdiag: array[0..8 * 8-1] of dword = (
+            clr_A, clr_A, clr_A, clr_A, clr_B, clr_B, clr_B, clr_B,
+            clr_B, clr_A, clr_A, clr_A, clr_A, clr_B, clr_B, clr_B,
+            clr_B, clr_B, clr_A, clr_A, clr_A, clr_A, clr_B, clr_B,
+            clr_B, clr_B, clr_B, clr_A, clr_A, clr_A, clr_A, clr_B,
+            //-----------------------------------------------------
+            clr_B, clr_B, clr_B, clr_B, clr_A, clr_A, clr_A, clr_A,
+            clr_A, clr_B, clr_B, clr_B, clr_B, clr_A, clr_A, clr_A,
+            clr_A, clr_A, clr_B, clr_B, clr_B, clr_B, clr_A, clr_A,
+            clr_A, clr_A, clr_A, clr_B, clr_B, clr_B, clr_B, clr_A);
+
+
+
+       //bsHorizontal
+       stipple_horz: array[0..15] of dword = (
+          clr_B, clr_B, clr_B, clr_B,
+          clr_B, clr_B, clr_B, clr_B,
+          clr_B, clr_B, clr_B, clr_B,
+          clr_A, clr_A, clr_A, clr_A
+       );
+
+       stipple_vert: array[0..15] of dword = (
+          clr_A, clr_B, clr_B, clr_B,
+          clr_A, clr_B, clr_B, clr_B,
+          clr_A, clr_B, clr_B, clr_B,
+          clr_A, clr_B, clr_B, clr_B
+       );
+
+      (* , bsVertical, bsFDiagonal,
+                   bsBDiagonal, bsCross, bsDiagCross, bsImage, bsPattern);*)
+
+
+       stipple_cross0: array[0..8] of dword = (
+          clr_B, clr_A, clr_B,
+          clr_A, clr_A, clr_A,
+          clr_B, clr_A, clr_B
+       );
+
+       stipple_cross1: array[0..63] of dword = (
+          clr_B, clr_B, clr_B, clr_A, clr_A, clr_B, clr_B, clr_B,
+          clr_B, clr_B, clr_B, clr_A, clr_A, clr_B, clr_B, clr_B,
+          clr_B, clr_B, clr_B, clr_A, clr_A, clr_B, clr_B, clr_B,
+          clr_A, clr_A, clr_A, clr_A, clr_A, clr_A, clr_A, clr_A,
+          clr_A, clr_A, clr_A, clr_A, clr_A, clr_A, clr_A, clr_A,
+          clr_B, clr_B, clr_B, clr_A, clr_A, clr_B, clr_B, clr_B,
+          clr_B, clr_B, clr_B, clr_A, clr_A, clr_B, clr_B, clr_B,
+          clr_B, clr_B, clr_B, clr_A, clr_A, clr_B, clr_B, clr_B
+       );
+
+       stipple_dcross0: array[0..8] of dword = (
+          clr_A, clr_B, clr_A,
+          clr_B, clr_A, clr_B,
+          clr_A, clr_B, clr_A
+       );
+
+       stipple_dcross: array[0..63] of dword = (
+          clr_A, clr_B, clr_B, clr_B, clr_B, clr_B, clr_B, clr_A,
+          clr_A, clr_A, clr_B, clr_B, clr_B, clr_B, clr_A, clr_A,
+          clr_B, clr_A, clr_A, clr_B, clr_B, clr_A, clr_A, clr_B,
+          clr_B, clr_B, clr_A, clr_A, clr_A, clr_A, clr_B, clr_B,
+          //----------------------------------------------------
+          clr_B, clr_B, clr_B, clr_A, clr_A, clr_B, clr_B, clr_B,
+          clr_B, clr_B, clr_A, clr_A, clr_A, clr_A, clr_B, clr_B,
+          clr_B, clr_A, clr_A, clr_B, clr_B, clr_A, clr_A, clr_B,
+          clr_A, clr_A, clr_B, clr_B, clr_B, clr_B, clr_A, clr_A
+       );
+
 function Gtk3DefaultContext: TGtk3DeviceContext;
 begin
   if FDefaultContext = nil then
@@ -388,6 +451,12 @@
   FShared := False;
 end;
 
+function TGtk3ContextObject.Select(ACtx:TGtk3DeviceContext): TGtk3ContextObject;
+begin
+  DbgS('Default context object selected, please implement');
+  Result:=nil;
+end;
+
 { TGtk3Region }
 
 constructor TGtk3Region.Create(CreateHandle: Boolean);
@@ -409,6 +478,14 @@
   FHandle := cairo_region_create_rectangle(@ARect);
 end;
 
+function TGtk3Region.Select(ACtx: TGtk3DeviceContext): TGtk3ContextObject;
+begin
+  fContext:=ACtx;
+  if not Assigned(fContext) then exit(nil);
+  fContext.setClipRegion(Self);
+  Result:=Self;
+end;
+
 destructor TGtk3Region.Destroy;
 begin
   if Assigned(FHandle) then
@@ -592,6 +669,14 @@
   g_object_unref(AContext);
 end;
 
+function TGtk3Font.Select(ACtx:TGtk3DeviceContext): TGtk3ContextObject;
+begin
+  fContext:=ACtx;
+  if not Assigned(fContext) then exit(nil);
+  Result := fContext.CurrentFont;
+  fContext.CurrentFont:= Self;
+end;
+
 destructor TGtk3Font.Destroy;
 begin
   if Assigned(FLayout) then
@@ -759,6 +844,14 @@
   end;
 end;
 
+function TGtk3Image.Select(ACtx: TGtk3DeviceContext): TGtk3ContextObject;
+begin
+  fContext:=ACtx;
+  if not Assigned(ACtx) then exit(nil);
+  Result := fContext.CurrentImage;
+  fContext.SetImage(Self);
+end;
+
 destructor TGtk3Image.Destroy;
 begin
   if FHandle <> nil then
@@ -864,6 +957,14 @@
   FPenMode := pmCopy; // default pen mode
 end;
 
+function TGtk3Pen.Select(ACtx:TGtk3DeviceContext): TGtk3ContextObject;
+begin
+  fContext:=ACtx;
+  if not Assigned(fContext) then exit(nil);
+  Result := FContext.CurrentPen;
+  fContext.CurrentPen := Self;
+end;
+
 procedure TGtk3Pen.setCosmetic(b: Boolean);
 begin
   FCosmetic := B;
@@ -905,27 +1006,95 @@
 constructor TGtk3Brush.Create;
 begin
   inherited Create;
-  {$note IMPORTANT TODO: use cairo_pattern_t for brush }
-  // cairo_pattern_create_for_surface();
-  FContext := nil;
   FColor := clNone;
   FillChar(LogBrush, SizeOf(TLogBrush), #0);
 end;
 
+function TGtk3Brush.Select(ACtx:TGtk3DeviceContext): TGtk3ContextObject;
+begin
+  fContext:=ACtx;
+  if not Assigned(fContext) then exit(nil);
+  Result := fContext.CurrentBrush;
+  Self.UpdatePattern;
+  fContext.CurrentBrush := Self;
+end;
+
 destructor TGtk3Brush.Destroy;
 begin
   if Assigned(brush_pattern) then
     cairo_pattern_destroy(brush_pattern);
+  if Assigned(pat_buf) then
+  freeandnil(pat_buf);
   inherited Destroy;
 end;
 
 procedure TGtk3Brush.UpdatePattern;
+var
+  w,h,i,j:integer;
+  clr:dword;
+  rgb:array[0..3] of byte absolute clr;
+  pat_sample,psrc,pdst:pdword;
 begin
+  if Self.LogBrush.lbStyle<>BS_HATCHED then exit;
+
   if Assigned(Self.brush_pattern) then
+  begin
      cairo_pattern_destroy(brush_pattern);
-  self.brush_pattern:=create_stipple(@stipple_data,8,8); // this stipple_data is 8x8
+     freeandnil(pat_buf);
+  end;
+  case TBrushStyle(Self.LogBrush.lbHatch+ord(bsHorizontal)) of
+  bsHorizontal:
+    begin
+      w:=4; h:=4;
+      pat_sample:=@stipple_horz;
+    end;
+  bsVertical:
+    begin
+      w:=4; h:=4;
+      pat_sample:=@stipple_vert;
+    end;
+  bsFDiagonal:
+    begin
+      w:=8; h:=8;
+      pat_sample:=@stipple_fdiag;
+    end;
+  bsBDiagonal:
+    begin
+      w:=8; h:=8;
+      pat_sample:=@stipple_bdiag;
+    end;
+  bsCross:
+    begin
+      w:=8; h:=8;
+      pat_sample:=@stipple_cross1;
+    end;
+  bsDiagCross:
+    begin
+      w:=8; h:=8;
+      pat_sample:=@stipple_dcross;
+    end;
+  else
+    exit
+  end;
+  psrc:=pat_sample;
+  getmem(pat_buf,w*h*sizeof(dword));
+  pdst:=pat_buf;
+  clr:=ColorToRgb(Self.Color);
+  for i:=0 to h-1 do
+  for j:=0 to w-1 do
+  begin
+    case psrc^ of
+    clr_A: pdst^:=$ff000000 or (rgb[0] shl 16) or (rgb[1] shl 8) or (rgb[2]);
+    clr_B: pdst^:=$ffffffff;
+    end;
+    inc(psrc); inc(pdst);
+  end;
+  {GTK3 states the buffer must exist, until image that uses the buffer - destroyed}
+  brush_pattern:=create_stipple(PByte(pat_buf),w,w);
 end;
 
+
+
 function create_stipple(stipple_data:pbyte;width,height:integer):pcairo_pattern_t;
 var
   surface:pcairo_surface_t;
Index: gtk3widgets.pas
===================================================================
--- gtk3widgets.pas	(revision 62896)
+++ gtk3widgets.pas	(working copy)
@@ -1458,7 +1458,7 @@
 
   Msg.SizeType := Msg.SizeType or Size_SourceIsInterface;
 
-  if ACtl is TGtk3Window then
+  if {ACtl is TGtk3Window} ACtl.WidgetType*[wtWindow,wtDialog]<>[] then
   begin
     Msg.Width := Word(NewSize.cx);
     Msg.Height := Word(NewSize.cy);
@@ -1771,7 +1771,6 @@
 var
   Msg: TLMPaint;
   AStruct: TPaintStruct;
-  P: TPoint;
   AClipRect: TGdkRectangle;
   localClip:TRect;
 begin
@@ -1810,39 +1809,6 @@
   Msg.PaintStruct^.rcPaint := PaintData.ClipRect^;
   Msg.PaintStruct^.hdc := FContext;
 
-  // P := Point(0, 0);
-
-  P := Self.getClientOffset;
-  if wtCustomControl in WidgetType then
-  begin
-    // ofsetting
-    P := Point(0, 0);
-    //TGtk3DeviceContext(Msg.DC).TranslateCairoToDevice;
-    //P.X := Round(TGtk3CustomControl(Self).getHorizontalScrollbar^.get_adjustment^.get_value);
-    //P.Y := Round(TGtk3CustomControl(Self).getVerticalScrollbar^.get_adjustment^.get_value);
-  end else
-  if wtScrollingWinControl in WidgetType then
-  begin
-    P := Point(0, 0);
-    //DebugLn('GtkEventPaint Scrollable ScrollX=',dbgs(TGtk3ScrollableWin(Self).ScrollX),
-    //  ' scrollY=',dbgs(TGtk3ScrollableWin(Self).ScrollY),' P=',dbgs(P));
-    //Inc(P.X, TGtk3ScrollableWin(Self).ScrollX);
-    //Inc(P.Y, TGtk3ScrollableWin(Self).ScrollY);
-    // cairo_surface_get_device_offset(cairo_get_target(AContext), @dx, @dy);
-    // TGtk3DeviceContext(Msg.DC).TranslateCairoToDevice;
-  end else
-  if wtGroupBox in WidgetType then
-  begin
-    // why is gtk3 so crazy about parent/child relation ?!?
-    // in this case child PGtkFixed has same top (+top caption) as parent TGtkFrame ... crap
-    // debugln('groupbox paint offset ',dbgs(p));
-    TGtk3DeviceContext(Msg.DC).TranslateCairoToDevice;
-    P := Point(0, 0);
-  end;
-
-  {$NOTE Currently TGtk3DeviceContext(Msg.DC).Translate(P) is creating incorrect offsets inside TPages for TLabel and maybe others}
-  TGtk3DeviceContext(Msg.DC).Translate(P);
-
   try
     try
       // DebugLn('**** Sending paint event to ',dbgsName(LCLObject),' clipRect=',dbgs(PaintData.ClipRect^),' P=',dbgs(P));
@@ -6586,7 +6552,7 @@
     else
     begin
       for i := 0 to Parent.ControlCount - 1 do
-        if Parent.Controls[i] is TRadioButton and
+        if (Parent.Controls[i] is TRadioButton) and
            TWinControl(Parent.Controls[i]).HandleAllocated then
         begin
           rb := TRadioButton(Parent.Controls[i]);
Index: gtk3winapi.inc
===================================================================
--- gtk3winapi.inc	(revision 62896)
+++ gtk3winapi.inc	(working copy)
@@ -3436,37 +3436,7 @@
     exit;
   if IsValidGDIObject(GDIObj) then
   begin
-    if TObject(GDIObj) is TGtk3Pen then
-    begin
-      // DebugLn('TGtk3WidgetSet.SelectObject PEN ');
-      Result := HGDIOBJ(TGtk3DeviceContext(DC).CurrentPen);
-      TGtk3DeviceContext(DC).CurrentPen:= TGtk3Pen(GDIObj);
-    end else
-    if TObject(GDIObj) is TGtk3Brush then
-    begin
-      Result := HGDIOBJ(TGtk3DeviceContext(DC).CurrentBrush);
-      // DebugLn('TGtk3WidgetSet.SelectObject BRUSH ',dbgHex(Result),'  ',TimeToStr(Now()));
-      TGtk3DeviceContext(DC).CurrentBrush:= TGtk3Brush(GDIObj);
-    end else
-    if TObject(GDIObj) is TGtk3Font then
-    begin
-      Result := HGDIOBJ(TGtk3DeviceContext(DC).CurrentFont);
-      TGtk3DeviceContext(DC).CurrentFont:= TGtk3Font(GDIObj);
-      // DebugLn('TGtk3WidgetSet.SelectObject Font ');
-    end else
-    if TObject(GDIObj) is TGtk3Region then
-    begin
-      Debugln('WARNING: TGtk3WidgetSet.SelectObject missing result for TGtk3Region.');
-      Result := 0;
-      SelectClipRGN(DC, GdiObj);
-    end else
-    if TObject(GDIObj) is TGtk3Image then
-    begin
-      // Debugln('WARNING: TGtk3WidgetSet.SelectObject missing result for TGtk3Image.');
-      Result := HGDIOBJ(TGtk3DeviceContext(DC).CurrentImage);
-      // TGtk3DeviceContext(DC).SetCurrentImage(TGtk3Image(GdiObj));
-      TGtk3DeviceContext(DC).SetImage(TGtk3Image(GdiObj));
-    end;
+    Result:=HGDIOBJ(TGtk3ContextObject(GDIOBJ).Select(TGtk3DeviceContext(DC)));
   end;
 end;
 
Index: gtk3wsimglist.pp
===================================================================
--- gtk3wsimglist.pp	(revision 62896)
+++ gtk3wsimglist.pp	(working copy)
@@ -60,6 +60,7 @@
 
 
 implementation
+uses gtk3objects,lazgdkpixbuf2;
 
 { TGtk3WSCustomImageListResolution }
 
@@ -94,6 +95,9 @@
 begin
   inherited Draw(AList, AIndex, ACanvas, ABounds, ABkColor, ABlendColor,
     ADrawEffect, AStyle, AImageType);
+{  TGtk3DeviceContext(ACanvas.Handle).drawImglistRes(AList,
+  AIndex,ABounds,ABkColor,
+  ABlendColor,ADrawEffect,AStyle, AImageType);}
 end;
 
 class procedure TGtk3WSCustomImageListResolution.Insert(AList: TCustomImageListResolution;
gtk3updates.diff (18,507 bytes)   

Juha Manninen

2020-04-08 17:23

developer   ~0122037

I applied the patch in r62917. Thanks.
I plan to resolve this issue soon after the commit got some testing.

Juha Manninen

2020-04-17 21:20

developer   ~0122215

Resolving.

Issue History

Date Modified Username Field Change
2020-02-29 13:53 Anton Kavalenka New Issue
2020-02-29 13:53 Anton Kavalenka File Added: gtk3objects.diff
2020-02-29 15:48 CudaText man Note Added: 0121280
2020-02-29 16:06 Anton Kavalenka File Added: Здымак экрана, 2020-02-29 18-05-31.png
2020-02-29 16:06 Anton Kavalenka Note Added: 0121281
2020-02-29 22:11 Juha Manninen Assigned To => Juha Manninen
2020-02-29 22:11 Juha Manninen Status new => assigned
2020-02-29 22:14 Juha Manninen Note Added: 0121284
2020-03-01 08:45 CudaText man Note Added: 0121289
2020-03-01 08:48 CudaText man Note Added: 0121290
2020-03-01 09:31 Anton Kavalenka File Added: my_gtk3.diff
2020-03-01 09:31 Anton Kavalenka Note Added: 0121291
2020-03-01 09:46 Anton Kavalenka Note Edited: 0121291 View Revisions
2020-03-01 09:52 Juha Manninen File Added: GTK3_CanvasBrush.png
2020-03-01 09:52 Juha Manninen Note Added: 0121292
2020-03-01 10:00 Juha Manninen Note Edited: 0121292 View Revisions
2020-03-02 12:19 Anton Kavalenka Note Added: 0121312
2020-03-02 12:26 Anton Kavalenka Note Edited: 0121312 View Revisions
2020-03-02 12:26 Anton Kavalenka File Added: Здымак экрана, 2020-03-02 14-26-19.png
2020-03-02 21:27 CudaText man Note Added: 0121319
2020-03-03 06:29 Anton Kavalenka Note Added: 0121332
2020-03-03 06:33 Anton Kavalenka Note Edited: 0121332 View Revisions
2020-03-03 06:39 Anton Kavalenka Note Edited: 0121332 View Revisions
2020-04-01 06:49 Juha Manninen Relationship added related to 0036374
2020-04-08 16:55 Anton Kavalenka File Added: gtk3updates.diff
2020-04-08 16:55 Anton Kavalenka Note Added: 0122034
2020-04-08 17:06 Juha Manninen Relationship added related to 0036826
2020-04-08 17:23 Juha Manninen Description Updated View Revisions
2020-04-08 17:23 Juha Manninen Fixed in Revision => r62687, r62917
2020-04-08 17:23 Juha Manninen LazTarget => -
2020-04-08 17:23 Juha Manninen Widgetset GTK 3 => GTK 3
2020-04-08 17:23 Juha Manninen Note Added: 0122037
2020-04-17 21:20 Juha Manninen Status assigned => resolved
2020-04-17 21:20 Juha Manninen Resolution open => fixed
2020-04-17 21:20 Juha Manninen Widgetset GTK 3 => GTK 3
2020-04-17 21:20 Juha Manninen Note Added: 0122215
2020-04-17 22:02 Anton Kavalenka Status resolved => closed