diff --git a/lcl/interfaces/gtk3/gtk3objects.pas b/lcl/interfaces/gtk3/gtk3objects.pas index b46a3e775c..72d1d82506 100644 --- a/lcl/interfaces/gtk3/gtk3objects.pas +++ b/lcl/interfaces/gtk3/gtk3objects.pas @@ -215,10 +215,12 @@ type FBkMode: Integer; FCanvasScaleFactor: double; function GetOffset: TPoint; + function GetRasterOp: integer; procedure setBrush(AValue: TGtk3Brush); procedure SetFont(AValue: TGtk3Font); procedure SetOffset(AValue: TPoint); procedure setPen(AValue: TGtk3Pen); + procedure SetRasterOp(AValue: integer); procedure SetvImage(AValue: TGtk3Image); function SX(const x: double): Double; function SY(const y: double): Double; @@ -291,6 +293,7 @@ type property CanvasScaleFactor: double read FCanvasScaleFactor write SetCanvasScaleFactor; property Offset: TPoint read GetOffset write SetOffset; property OwnsSurface: Boolean read FOwnsSurface; + property RasterOp: integer read GetRasterOp write SetRasterOp; //automatically maps cairo_operator_t to winapi ROP. property vBrush: TGtk3Brush read FBrush write setBrush; property vClipRect: TRect read FvClipRect write FvClipRect; property vFont: TGtk3Font read FFont write SetFont; @@ -464,6 +467,172 @@ begin B := ((AColor shr 16) and $FF) / 255; end; +{Map winapi ROP to Tcairo_operator_t} +function MapRasterOpToCairo(AValue: Integer): Tcairo_operator_t; +begin + case AValue of + BLACKNESS, + R2_BLACK: + Result := CAIRO_OPERATOR_CLEAR; + + SRCCOPY, + R2_COPYPEN: + Result := CAIRO_OPERATOR_SOURCE; + + MERGEPAINT, + R2_MASKNOTPEN: + Result := CAIRO_OPERATOR_OUT; + + SRCAND, + R2_MASKPEN: + Result := CAIRO_OPERATOR_IN; + + SRCERASE, + R2_MASKPENNOT: + Result := CAIRO_OPERATOR_OUT; + + R2_MERGENOTPEN: + Result := CAIRO_OPERATOR_OVER; + + SRCPAINT, + R2_MERGEPEN: + Result := CAIRO_OPERATOR_OVER; + + R2_MERGEPENNOT: + Result := CAIRO_OPERATOR_OVER; + + R2_NOP: + Result := CAIRO_OPERATOR_DEST; + + R2_NOT: + Result := CAIRO_OPERATOR_OUT; + + NOTSRCCOPY, + R2_NOTCOPYPEN: + Result := CAIRO_OPERATOR_SOURCE; + + PATPAINT, + R2_NOTMASKPEN: + Result := CAIRO_OPERATOR_XOR; + + NOTSRCERASE, + R2_NOTMERGEPEN: + Result := CAIRO_OPERATOR_CLEAR; + + DSTINVERT, + R2_NOTXORPEN: + Result := CAIRO_OPERATOR_DIFFERENCE; + + WHITENESS, + R2_WHITE: + Result := CAIRO_OPERATOR_SCREEN; + + SRCINVERT, + R2_XORPEN: + Result := CAIRO_OPERATOR_XOR; + + else + Result := CAIRO_OPERATOR_OVER; + end; +end; + +{Map cairo_operator_t to winapi ROP} +function MapCairoRasterOpToRasterOp(AValue: Tcairo_operator_t): Integer; +begin + case AValue of + CAIRO_OPERATOR_CLEAR: + Result := R2_BLACK; + + CAIRO_OPERATOR_SOURCE: + Result := R2_COPYPEN; + + CAIRO_OPERATOR_OVER: + Result := R2_MERGEPEN; + + CAIRO_OPERATOR_IN: + Result := R2_MASKPEN; + + CAIRO_OPERATOR_OUT: + Result := R2_MASKPENNOT; + + CAIRO_OPERATOR_ATOP: + Result := R2_MERGEPEN; + + CAIRO_OPERATOR_DEST: + Result := R2_NOP; + + CAIRO_OPERATOR_DEST_OVER: + Result := R2_MERGEPEN; + + CAIRO_OPERATOR_DEST_IN: + Result := R2_MASKPEN; + + CAIRO_OPERATOR_DEST_OUT: + Result := R2_MASKPENNOT; + + CAIRO_OPERATOR_DEST_ATOP: + Result := R2_MERGEPEN; + + CAIRO_OPERATOR_XOR: + Result := R2_XORPEN; + + CAIRO_OPERATOR_ADD: + Result := R2_MERGEPEN; // Similar to add-blend effect + + CAIRO_OPERATOR_SATURATE: + Result := R2_MERGEPEN; + + CAIRO_OPERATOR_MULTIPLY: + Result := R2_MASKPEN; + + CAIRO_OPERATOR_SCREEN: + Result := R2_WHITE; + + CAIRO_OPERATOR_OVERLAY: + Result := R2_MERGEPEN; + + CAIRO_OPERATOR_DARKEN: + Result := R2_MASKPEN; + + CAIRO_OPERATOR_LIGHTEN: + Result := R2_MERGEPEN; + + CAIRO_OPERATOR_COLOR_DODGE: + Result := R2_MERGEPEN; + + CAIRO_OPERATOR_COLOR_BURN: + Result := R2_MASKPEN; + + CAIRO_OPERATOR_HARD_LIGHT: + Result := R2_MERGEPEN; + + CAIRO_OPERATOR_SOFT_LIGHT: + Result := R2_MERGEPEN; + + CAIRO_OPERATOR_DIFFERENCE: + Result := R2_NOTXORPEN; + + CAIRO_OPERATOR_EXCLUSION: + Result := R2_XORPEN; + + CAIRO_OPERATOR_HSL_HUE: + Result := R2_MERGEPEN; + + CAIRO_OPERATOR_HSL_SATURATION: + Result := R2_MERGEPEN; + + CAIRO_OPERATOR_HSL_COLOR: + Result := R2_MERGEPEN; + + CAIRO_OPERATOR_HSL_LUMINOSITY: + Result := R2_MERGEPEN; + + else + Result := R2_NOP; // Default fallback + end; +end; + + { TGtk3Cursor } constructor TGtk3Cursor.Create(ACur:integer); @@ -1295,6 +1464,11 @@ begin Result := Point(Round(dx), Round(dy)); end; +function TGtk3DeviceContext.GetRasterOp: integer; +begin + Result := MapCairoRasterOpToRasterOp(cairo_get_operator(pcr)); +end; + procedure TGtk3DeviceContext.setBrush(AValue: TGtk3Brush); begin if Assigned(FBrush) then @@ -1325,6 +1499,11 @@ begin FPen := AValue; end; +procedure TGtk3DeviceContext.SetRasterOp(AValue: integer); +begin + cairo_set_operator(pcr, MapRasterOpToCairo(AValue)); +end; + procedure TGtk3DeviceContext.SetvImage(AValue: TGtk3Image); begin if Assigned(FvImage) then diff --git a/lcl/interfaces/gtk3/gtk3winapi.inc b/lcl/interfaces/gtk3/gtk3winapi.inc index c35328e29c..536021bef1 100644 --- a/lcl/interfaces/gtk3/gtk3winapi.inc +++ b/lcl/interfaces/gtk3/gtk3winapi.inc @@ -2410,11 +2410,13 @@ begin end; function TGtk3WidgetSet.GetROP2(DC: HDC): Integer; +var + GtkDC: TGtk3DeviceContext absolute DC; begin - {$IFDEF GTK3DEBUGNOTIMPLEMENTED} - DebugLn('WARNING: TGtk3WidgetSet.GetROP2 not implemented ...'); - {$ENDIF} - Result := inherited GetROP2(DC); + Result := R2_COPYPEN; + if not IsValidDC(DC) then + exit; + Result := GtkDC.RasterOp; end; function TGtk3WidgetSet.GetScrollBarSize(Handle: HWND; BarKind: Integer @@ -3692,11 +3694,14 @@ begin end; function TGtk3WidgetSet.SetROP2(DC: HDC; Mode: Integer): Integer; +var + GtkDC: TGtk3DeviceContext absolute DC; begin - {$IFDEF GTK3DEBUGNOTIMPLEMENTED} - DebugLn('WARNING: TGtk3WidgetSet.SetROP2 not implemented ...'); - {$ENDIF} - Result:=inherited SetROP2(DC, Mode); + Result := R2_COPYPEN; + if not IsValidDC(DC) then + exit; + Result := GtkDC.RasterOp; + GtkDC.RasterOp := Mode; end; function TGtk3WidgetSet.SetScrollInfo(Handle: HWND; SBStyle: Integer;