mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-09-07 09:40:21 +02:00
gtk2 intf: the GC of device contexts are now created only when needed
git-svn-id: trunk@11106 -
This commit is contained in:
parent
cc70f5376b
commit
6a41acd5f4
@ -185,14 +185,19 @@ type
|
||||
dcscFont
|
||||
);
|
||||
|
||||
{ TDeviceContext }
|
||||
|
||||
TDeviceContext = class
|
||||
public
|
||||
WithChildWindows: boolean;// this DC covers sub gdkwindows
|
||||
|
||||
// device handles
|
||||
DCWidget: PGtkWidget; // the owner
|
||||
GC: pgdkGC;
|
||||
Drawable: PGDKDrawable;
|
||||
OriginalDrawable: PGDKDrawable; // only set if dcfDoubleBuffer in DCFlags
|
||||
|
||||
GC: pgdkGC;
|
||||
GCValues: TGdkGCValues;
|
||||
|
||||
// origins
|
||||
Origin: TPoint;
|
||||
SpecialOrigin: boolean;
|
||||
@ -217,7 +222,9 @@ type
|
||||
SelectedColors: TDevContextSelectedColorsType;
|
||||
SavedContext: TDeviceContext; // linked list of saved DCs
|
||||
DCFlags: TDeviceContextsFlags;
|
||||
|
||||
procedure Clear;
|
||||
function GetGC: pgdkGC;
|
||||
end;
|
||||
|
||||
|
||||
@ -388,6 +395,11 @@ procedure InternalDisposePGDIObject(GDIObject: PGdiObject);
|
||||
function NewDeviceContext: TDeviceContext;
|
||||
procedure DisposeDeviceContext(DeviceContext: TDeviceContext);
|
||||
|
||||
type
|
||||
TCreateGCForDC = procedure(DC: TDeviceContext) of object;
|
||||
var
|
||||
CreateGCForDC: TCreateGCForDC = nil;
|
||||
|
||||
{$IFDEF DebugLCLComponents}
|
||||
var
|
||||
DebugGtkWidgets: TDebugLCLItems = nil;
|
||||
@ -397,7 +409,6 @@ var
|
||||
|
||||
procedure GtkDefDone;
|
||||
|
||||
|
||||
implementation
|
||||
|
||||
|
||||
@ -587,9 +598,10 @@ end;
|
||||
procedure TDeviceContext.Clear;
|
||||
begin
|
||||
DCWidget:=nil;
|
||||
GC:=nil;
|
||||
Drawable:=nil;
|
||||
|
||||
GC:=nil;
|
||||
FillChar(GCValues, SizeOf(GCValues), #0);
|
||||
|
||||
Origin.X:=0;
|
||||
Origin.Y:=0;
|
||||
SpecialOrigin:=false;
|
||||
@ -610,6 +622,13 @@ begin
|
||||
DCFlags:=[];
|
||||
end;
|
||||
|
||||
function TDeviceContext.GetGC: pgdkGC;
|
||||
begin
|
||||
if GC=nil then
|
||||
CreateGCForDC(Self);
|
||||
Result:=GC;
|
||||
end;
|
||||
|
||||
procedure GtkDefInit;
|
||||
begin
|
||||
{$IFDEF DebugLCLComponents}
|
||||
|
@ -243,6 +243,7 @@ type
|
||||
procedure RemoveCallbacks(Widget: PGtkWidget); virtual;
|
||||
function ROP2ModeToGdkFunction(Mode: Integer): TGdkFunction;
|
||||
function gdkFunctionToROP2Mode(aFunction: TGdkFunction): Integer;
|
||||
procedure OnCreateGCForDC(DC: TDeviceContext);
|
||||
|
||||
// for gtk specific components:
|
||||
procedure SetLabelCaption(const ALabel: PGtkLabel; const ACaption: String;
|
||||
|
@ -175,6 +175,7 @@ begin
|
||||
// DCs, GDIObjects
|
||||
FDeviceContexts := TDynHashArray.Create(-1);
|
||||
FDeviceContexts.Options:=FDeviceContexts.Options+[dhaoCacheContains];
|
||||
CreateGCForDC:=@OnCreateGCForDC;
|
||||
FGDIObjects := TDynHashArray.Create(-1);
|
||||
FGDIObjects.Options:=FGDIObjects.Options+[dhaoCacheContains];
|
||||
|
||||
@ -3078,7 +3079,7 @@ var
|
||||
SelectGDKBrushProps(DC);
|
||||
|
||||
If not CurrentBrush^.IsNullBrush then begin
|
||||
gdk_draw_rectangle(TempPixmap, GC, 1, 0, 0, Width, Height);
|
||||
gdk_draw_rectangle(TempPixmap, GetGC, 1, 0, 0, Width, Height);
|
||||
end;
|
||||
// Restore current brush
|
||||
SelectedColors := dcscCustom;
|
||||
@ -3117,7 +3118,7 @@ var
|
||||
{$IFDEF VerboseStretchCopyArea}
|
||||
DebugLn('SrcDevBitmapToDrawable Simple copy');
|
||||
{$ENDIF}
|
||||
gdk_window_copy_area(DestDevContext.Drawable, DestDevContext.GC, X, Y,
|
||||
gdk_window_copy_area(DestDevContext.Drawable, DestDevContext.GetGC, X, Y,
|
||||
SrcPixmap, XSrc, YSrc, Width, Height);
|
||||
|
||||
exit;
|
||||
@ -3129,7 +3130,7 @@ var
|
||||
|
||||
// perform raster operation and scaling into Scale and fGC
|
||||
DestDevContext.SelectedColors := dcscCustom;
|
||||
If not ScaleAndROP(DestDevContext.GC, SrcDevContext.Drawable, SrcPixmap,
|
||||
If not ScaleAndROP(DestDevContext.GetGC, SrcDevContext.Drawable, SrcPixmap,
|
||||
MaskPixmap)
|
||||
then begin
|
||||
DebugLn('WARNING: SrcDevBitmapToDrawable: ScaleAndROP failed');
|
||||
@ -3168,20 +3169,20 @@ var
|
||||
{$ENDIF}
|
||||
|
||||
// set clipping mask for transparency
|
||||
MergeClipping(DestDevContext, DestDevContext.GC, X,Y,Width,Height,
|
||||
MergeClipping(DestDevContext, DestDevContext.GetGC, X,Y,Width,Height,
|
||||
MaskPixmap,XMask,YMask,
|
||||
NewClipMask);
|
||||
|
||||
// draw image
|
||||
{$IFDEF DebugGDK}BeginGDKErrorTrap;{$ENDIF}
|
||||
gdk_window_copy_area(DestDevContext.Drawable, DestDevContext.GC, X, Y,
|
||||
gdk_window_copy_area(DestDevContext.Drawable, DestDevContext.GetGC, X, Y,
|
||||
SrcPixmap, XSrc, YSrc, SrcWidth, SrcHeight);
|
||||
{$IFDEF DebugGDK}EndGDKErrorTrap;{$ENDIF}
|
||||
// unset clipping mask for transparency
|
||||
ResetClipping(DestDevContext.GC);
|
||||
ResetClipping(DestDevContext.GetGC);
|
||||
|
||||
// restore raster operation to SRCCOPY
|
||||
GDK_GC_Set_Function(DestDevContext.GC, GDK_Copy);
|
||||
GDK_GC_Set_Function(DestDevContext.GetGC, GDK_Copy);
|
||||
|
||||
Result:=True;
|
||||
end;
|
||||
@ -6130,9 +6131,9 @@ begin
|
||||
|
||||
aDC.SelectedColors := dcscCustom;
|
||||
GDKColor:=AllocGDKColor(AColor);
|
||||
gdk_gc_set_foreground(aDC.GC, @GDKColor);
|
||||
gdk_gc_set_foreground(aDC.GetGC, @GDKColor);
|
||||
{$IFDEF DebugGDK}BeginGDKErrorTrap;{$ENDIF}
|
||||
gdk_draw_point(aDC.Drawable, aDC.GC, X, Y);
|
||||
gdk_draw_point(aDC.Drawable, aDC.GetGC, X, Y);
|
||||
{$IFDEF DebugGDK}EndGDKErrorTrap;{$ENDIF}
|
||||
end;
|
||||
|
||||
@ -6141,7 +6142,6 @@ var
|
||||
fWindow :pGdkWindow;
|
||||
widget : PgtkWIdget;
|
||||
PixMap : pgdkPixMap;
|
||||
//gc : PGDKGc;
|
||||
Child: PGtkWidget;
|
||||
begin
|
||||
Assert(False, 'Trace:In AutoRedraw in GTKObject');
|
||||
@ -6151,7 +6151,6 @@ begin
|
||||
pixmap := gtk_Object_get_data(pgtkobject(Child),'Pixmap');
|
||||
if PixMap = nil then Exit;
|
||||
fWindow := GetControlWindow(widget);
|
||||
//gc := gdk_gc_new(PgdkWindow(fWindow));
|
||||
|
||||
if fWindow<>nil then begin
|
||||
{$IFDEF DebugGDK}BeginGDKErrorTrap;{$ENDIF}
|
||||
@ -6306,8 +6305,8 @@ begin
|
||||
|
||||
If GDIBrushFill <> GDK_Solid then
|
||||
If GDIBrushPixmap <> nil then begin
|
||||
gdk_gc_set_fill(GC, GDIBrushFill);
|
||||
gdk_gc_set_Stipple(GC,GDIBrushPixmap);
|
||||
gdk_gc_set_fill(GetGC, GDIBrushFill);
|
||||
gdk_gc_set_Stipple(GetGC,GDIBrushPixmap);
|
||||
end
|
||||
end;
|
||||
TDeviceContext(DC).SelectedColors:=dcscBrush;
|
||||
@ -6344,7 +6343,7 @@ procedure TGtkWidgetSet.SelectGDKPenProps(DC: HDC);
|
||||
procedure SetDashes(const Dashes: array of gint8);
|
||||
begin
|
||||
{$IFDEF DebugGDK}BeginGDKErrorTrap;{$ENDIF}
|
||||
laz_gdk_gc_set_dashes(TDeviceContext(DC).GC,0,Pgint8(@Dashes[Low(Dashes)]),
|
||||
laz_gdk_gc_set_dashes(TDeviceContext(DC).GetGC,0,Pgint8(@Dashes[Low(Dashes)]),
|
||||
High(Dashes)-Low(Dashes)+1);
|
||||
{$IFDEF DebugGDK}EndGDKErrorTrap;{$ENDIF}
|
||||
end;
|
||||
@ -6360,7 +6359,7 @@ begin
|
||||
|
||||
if (not (dcfPenSelected in TDeviceContext(DC).DCFlags)) then begin
|
||||
Exclude(TDeviceContext(DC).DCFlags,dcfPenInvalid);
|
||||
if TDeviceContext(DC).GC<>nil then begin
|
||||
if TDeviceContext(DC).GetGC<>nil then begin
|
||||
with TDeviceContext(DC), CurrentPen^ do
|
||||
begin
|
||||
IsNullPen := GDIPenStyle = PS_NULL;
|
||||
@ -6447,11 +6446,11 @@ var
|
||||
aDC: TDeviceContext;
|
||||
ClientWidget: PGtkWidget;
|
||||
FontGdiObject: PGdiObject;
|
||||
GCValues: TGdkGCValues;
|
||||
begin
|
||||
aDC := nil;
|
||||
|
||||
aDC := NewDC;
|
||||
aDC.WithChildWindows := WithChildWindows;
|
||||
aDC.DCWidget := TheWidget;
|
||||
|
||||
FontGdiObject := nil;
|
||||
@ -6460,7 +6459,6 @@ begin
|
||||
if TheWidget = nil
|
||||
then begin
|
||||
// screen: ToDo: multiple desktops
|
||||
FillChar(GCValues, SizeOf(GCValues), #0);
|
||||
end
|
||||
else begin
|
||||
// create a new devicecontext for this window
|
||||
@ -6479,29 +6477,19 @@ begin
|
||||
ClientWidget:=TheWidget;
|
||||
aDC.SpecialOrigin:=GtkWidgetIsA(ClientWidget,GTK_LAYOUT_GET_TYPE);
|
||||
aDC.Drawable := TheWindow;
|
||||
// create GC
|
||||
if WithChildWindows then begin
|
||||
//DebugLn('TGtkWidgetSet.CreateDCForWidget A WithChildWindows');
|
||||
FillChar(GCValues, SizeOf(GCValues), #0);
|
||||
GCValues.subwindow_mode := GDK_INCLUDE_INFERIORS;
|
||||
aDC.GC := gdk_gc_new_with_values(aDC.Drawable,
|
||||
@GCValues,GDK_GC_FUNCTION or GDK_GC_SUBWINDOW);
|
||||
end else begin
|
||||
aDC.GC := gdk_gc_new(aDC.Drawable);
|
||||
end;
|
||||
gdk_gc_set_function(aDC.GC, GDK_COPY);
|
||||
|
||||
gdk_gc_get_values(aDC.GC, @GCValues);
|
||||
{$IFDEF Gtk1}
|
||||
aDC.GetGC;
|
||||
{$ENDIF}
|
||||
end;
|
||||
|
||||
if aDC <> nil
|
||||
then begin
|
||||
{$Ifdef GTK1}
|
||||
// ToDo: create font on demand
|
||||
if GCValues.Font <> nil
|
||||
if aDC.GCValues.Font <> nil
|
||||
then begin
|
||||
FontGdiObject:=NewGDIObject(gdiFont);
|
||||
FontGdiObject^.GDIFontObject := GCValues.Font;
|
||||
FontGdiObject^.GDIFontObject := aDC.GCValues.Font;
|
||||
FontCache.Reference(FontGdiObject^.GDIFontObject);
|
||||
end
|
||||
else FontGdiObject := CreateDefaultFont;
|
||||
@ -6524,7 +6512,7 @@ begin
|
||||
end;
|
||||
|
||||
Result := HDC(aDC);
|
||||
Assert(False, Format('trace:< [TGtkWidgetSet.GetDC] Got 0x%x', [Result]));
|
||||
Assert(False, Format('trace:< [TGtkWidgetSet.CreateDCForWidget] Got 0x%x', [Result]));
|
||||
end;
|
||||
|
||||
{------------------------------------------------------------------------------
|
||||
@ -6542,6 +6530,7 @@ var
|
||||
DevContext: TDeviceContext;
|
||||
CaretWasVisible: Boolean;
|
||||
MainWidget: PGtkWidget;
|
||||
GC: PGdkGC;
|
||||
//LCLObject: TObject;
|
||||
//x, y: integer;
|
||||
begin
|
||||
@ -6595,14 +6584,16 @@ begin
|
||||
Include(DevContext.DCFlags,dcfDoubleBuffer);
|
||||
|
||||
if BufferCreated then begin
|
||||
// create GC
|
||||
GC:=DevContext.GetGC;
|
||||
// copy old context to buffer
|
||||
gdk_gc_set_clip_region(DevContext.GC, nil);
|
||||
gdk_gc_set_clip_rectangle(DevContext.GC, nil);
|
||||
gdk_gc_set_clip_region(GC, nil);
|
||||
gdk_gc_set_clip_rectangle(GC, nil);
|
||||
|
||||
// hide caret
|
||||
HideCaretOfWidgetGroup(Widget,MainWidget,CaretWasVisible);
|
||||
// copy
|
||||
gdk_window_copy_area(DoubleBuffer, DevContext.GC,0,0,
|
||||
gdk_window_copy_area(DoubleBuffer, GC,0,0,
|
||||
Widget^.Window,0,0,Width,Height);
|
||||
|
||||
{LCLObject:=GetParentLCLObject(Widget);
|
||||
@ -7418,6 +7409,39 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TGTKWidgetSet.OnCreateGCForDC(DC: TDeviceContext);
|
||||
var
|
||||
CurWidget: PGtkWidget;
|
||||
CurWindow: PGdkWindow;
|
||||
begin
|
||||
if DC.GC=nil then begin
|
||||
// create GC
|
||||
if DC.Drawable<>nil then begin
|
||||
if DC.WithChildWindows then begin
|
||||
FillChar(DC.GCValues, SizeOf(DC.GCValues), #0);
|
||||
DC.GCValues.subwindow_mode := GDK_INCLUDE_INFERIORS;
|
||||
DC.GC:=gdk_gc_new_with_values(DC.Drawable,
|
||||
@DC.GCValues,GDK_GC_FUNCTION or GDK_GC_SUBWINDOW);
|
||||
end else begin
|
||||
DC.GC:=gdk_gc_new(DC.Drawable);
|
||||
end;
|
||||
end else begin
|
||||
// create default GC
|
||||
{$IFDEF Gtk1}
|
||||
CurWidget:=GetStyleWidget(lgsWindow);
|
||||
CurWindow:=CurWidget^.window;
|
||||
DC.GC:=gdk_gc_new(CurWindow);
|
||||
{$ELSE}
|
||||
DC.GC:=gdk_gc_new(gdk_screen_get_root_window(gdk_screen_get_default));
|
||||
{$ENDIF}
|
||||
end;
|
||||
if DC.GC<>nil then begin
|
||||
gdk_gc_set_function(DC.GC, GDK_COPY);
|
||||
gdk_gc_get_values(DC.GC, @DC.GCValues);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TGtkWidgetSet.ForceLineBreaks(DC : hDC; Src: PChar; MaxWidthInPixels : Longint;
|
||||
ProcessAmpersands : Boolean) : PChar;
|
||||
var
|
||||
|
@ -1421,8 +1421,6 @@ end;
|
||||
Creates a copy DC from the given DC
|
||||
------------------------------------------------------------------------------}
|
||||
function CopyDCData(DestinationDC, SourceDC: TDeviceContext): Boolean;
|
||||
var
|
||||
GCValues: TGDKGCValues;
|
||||
begin
|
||||
// Assert(False, Format('Trace:> [CopyDCData] DestDC:0x%x, SourceDC:0x%x', [Integer(DestinationDC), Integer(SourceDC)]));
|
||||
Result := (DestinationDC <> nil) and (SourceDC <> nil);
|
||||
@ -1433,6 +1431,7 @@ begin
|
||||
DCWidget := SourceDC.DCWidget;
|
||||
Drawable := SourceDC.Drawable;
|
||||
if GC<>nil then begin
|
||||
// free old GC
|
||||
BeginGDKErrorTrap;
|
||||
gdk_gc_unref(GC);
|
||||
EndGDKErrorTrap;
|
||||
@ -1515,13 +1514,13 @@ begin
|
||||
{$IFDEF DebugGDK}
|
||||
BeginGDKErrorTrap;
|
||||
{$ENDIF}
|
||||
gdk_gc_set_clip_region(gc, nil);
|
||||
gdk_gc_set_clip_rectangle (gc, nil);
|
||||
gdk_gc_set_clip_region(GetGC, nil);
|
||||
gdk_gc_set_clip_rectangle (GetGC, nil);
|
||||
If (ClipRegion <> 0) then begin
|
||||
Region:=PGDIObject(ClipRegion);
|
||||
RGNType := RegionType(Region^.GDIRegionObject);
|
||||
If (RGNType <> ERROR) and (RGNType <> NULLREGION) then begin
|
||||
gdk_gc_set_clip_region(gc, PGDIObject(ClipRegion)^.GDIRegionObject);
|
||||
gdk_gc_set_clip_region(GetGC, PGDIObject(ClipRegion)^.GDIRegionObject);
|
||||
end;
|
||||
end;
|
||||
{$IFDEF DebugGDK}
|
||||
@ -1685,7 +1684,7 @@ var
|
||||
end;
|
||||
|
||||
begin
|
||||
GC:=TDeviceContext(DC).GC;
|
||||
GC:=TDeviceContext(DC).GetGC;
|
||||
GDIColor:=nil;
|
||||
with TDeviceContext(DC) do
|
||||
begin
|
||||
@ -7330,7 +7329,7 @@ begin
|
||||
GetStyleWithName(WName);
|
||||
// return widget
|
||||
l:=IndexOfStyleWithName(WName);
|
||||
If l>=0 then
|
||||
if l>=0 then
|
||||
Result := PStyleObject(Styles.Objects[l])^.Widget;
|
||||
end;
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -337,7 +337,7 @@ var
|
||||
CharLen:=UTF8CharacterLength(CurStr);
|
||||
//gdk_draw_glyphs(DevCtx.drawable,DevCtx.gc );
|
||||
pango_layout_set_text(UseFont, CurStr, CharLen);
|
||||
gdk_draw_layout_with_colors(DevCtx.drawable, DevCtx.gc, CurScreenX, Y,
|
||||
gdk_draw_layout_with_colors(DevCtx.drawable, DevCtx.GC, CurScreenX, Y,
|
||||
UseFont, Foreground, nil);
|
||||
//gdk_draw_rectangle(DevCtx.Drawable,DevCtx.GC,1,CurScreenX,Y,3,3);
|
||||
inc(CurScreenX,CurDx^);
|
||||
@ -347,7 +347,7 @@ var
|
||||
end;
|
||||
end else begin
|
||||
pango_layout_set_text(UseFont, Str, Count);
|
||||
gdk_draw_layout_with_colors(DevCtx.drawable, DevCtx.gc, X, Y, UseFont,
|
||||
gdk_draw_layout_with_colors(DevCtx.drawable, DevCtx.GC, X, Y, UseFont,
|
||||
Foreground, nil);
|
||||
end;
|
||||
end;
|
||||
@ -359,12 +359,7 @@ begin
|
||||
if Result
|
||||
then with TDeviceContext(DC) do
|
||||
begin
|
||||
if GC = nil
|
||||
then begin
|
||||
DebugLn('WARNING: [TGtk2WidgetSet.ExtTextOut] Uninitialized GC');
|
||||
Result := False;
|
||||
exit;
|
||||
end;
|
||||
GetGC; // create GC
|
||||
if ((Options and (ETO_OPAQUE+ETO_CLIPPED)) <> 0)
|
||||
and (Rect=nil) then begin
|
||||
DebugLn('WARNING: [TGtk2WidgetSet.ExtTextOut] Rect=nil');
|
||||
@ -521,11 +516,6 @@ begin
|
||||
if Result and (Count>0)
|
||||
then with TDeviceContext(DC) do
|
||||
begin
|
||||
if GC = nil
|
||||
then begin
|
||||
DebugLn('WARNING: [TGtk2WidgetSet.TextOut] Uninitialized GC');
|
||||
exit(false);
|
||||
end;
|
||||
if (CurrentFont = nil) or (CurrentFont^.GDIFontObject = nil)
|
||||
then begin
|
||||
UseFont := GetDefaultGtkFont(false);
|
||||
@ -552,7 +542,7 @@ begin
|
||||
EnsureGCColor(DC, dccCurrentTextColor, True, False);
|
||||
|
||||
//DebugLn(['TGtk2WidgetSet.TextOut Str="',copy(Str,1,Count),'" X=',X+DCOrigin.X,',',Y+DCOrigin.Y+yOffset]);
|
||||
gdk_draw_layout_with_colors(drawable, GC,
|
||||
gdk_draw_layout_with_colors(drawable, GetGC,
|
||||
X+DCOrigin.X, Y+DCOrigin.Y+yOffset, UseFont, nil, nil);
|
||||
|
||||
Result := True;
|
||||
|
Loading…
Reference in New Issue
Block a user