gtk2 intf: the GC of device contexts are now created only when needed

git-svn-id: trunk@11106 -
This commit is contained in:
mattias 2007-05-08 16:24:44 +00:00
parent cc70f5376b
commit 6a41acd5f4
6 changed files with 506 additions and 636 deletions

View File

@ -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}

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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;