From 610245564b2e44da2690c95821e572b0a629823d Mon Sep 17 00:00:00 2001 From: juha Date: Wed, 8 Apr 2020 15:16:12 +0000 Subject: [PATCH] LCL-GTK3: OOP approach in SelectObject, hatched brushes implemented etc. Issue #36744, patch from Anton Kavalenka. git-svn-id: trunk@62917 - --- lcl/interfaces/gtk3/gtk3object.inc | 6 +- lcl/interfaces/gtk3/gtk3objects.pas | 227 +++++++++++++++++++++++---- lcl/interfaces/gtk3/gtk3winapi.inc | 32 +--- lcl/interfaces/gtk3/gtk3wsimglist.pp | 4 + 4 files changed, 207 insertions(+), 62 deletions(-) diff --git a/lcl/interfaces/gtk3/gtk3object.inc b/lcl/interfaces/gtk3/gtk3object.inc index 9dcf2468f7..a79d515a3d 100644 --- a/lcl/interfaces/gtk3/gtk3object.inc +++ b/lcl/interfaces/gtk3/gtk3object.inc @@ -95,11 +95,13 @@ begin 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 @@ end; 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; diff --git a/lcl/interfaces/gtk3/gtk3objects.pas b/lcl/interfaces/gtk3/gtk3objects.pas index 92eec70b17..debfa114cf 100644 --- a/lcl/interfaces/gtk3/gtk3objects.pas +++ b/lcl/interfaces/gtk3/gtk3objects.pas @@ -50,8 +50,10 @@ type 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 @@ type 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 @@ type 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 @@ type FStyle: TFPPenStyle; FWidth: Integer; FColor: TColor; - FContext: TGtk3DeviceContext; FIsExtPen: Boolean; procedure SetColor(AValue: TColor); procedure setCosmetic(b: Boolean); @@ -113,6 +116,7 @@ type 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 @@ type 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 @@ type 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 @@ var 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,6 +323,83 @@ var * 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 @@ -388,6 +451,12 @@ begin 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 @@ begin 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 @@ begin 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 @@ begin 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 @@ begin 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 @@ end; 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; diff --git a/lcl/interfaces/gtk3/gtk3winapi.inc b/lcl/interfaces/gtk3/gtk3winapi.inc index efd97ab509..86bbe55752 100644 --- a/lcl/interfaces/gtk3/gtk3winapi.inc +++ b/lcl/interfaces/gtk3/gtk3winapi.inc @@ -3436,37 +3436,7 @@ begin 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; diff --git a/lcl/interfaces/gtk3/gtk3wsimglist.pp b/lcl/interfaces/gtk3/gtk3wsimglist.pp index 3848f23121..f5ba949080 100644 --- a/lcl/interfaces/gtk3/gtk3wsimglist.pp +++ b/lcl/interfaces/gtk3/gtk3wsimglist.pp @@ -60,6 +60,7 @@ type implementation +uses gtk3objects,lazgdkpixbuf2; { TGtk3WSCustomImageListResolution } @@ -94,6 +95,9 @@ class procedure TGtk3WSCustomImageListResolution.Draw(AList: TCustomImageListRes 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;