From 77989dc1e0847684d42042c3ec45533a3e9dabe2 Mon Sep 17 00:00:00 2001 From: paul Date: Wed, 6 Feb 2008 06:13:00 +0000 Subject: [PATCH] gtk2: draw text with rotation - rearrange extras - introduced TGtk2DeviceContext.DrawTextWithColor (mostly from 0009665 with modifications) - use DrawTextWithColor in TextOut and ExtTextOut git-svn-id: trunk@13987 - --- lcl/interfaces/gtk/gtkwinapi.inc | 3 +- lcl/interfaces/gtk2/gtk2def.pp | 5 +- lcl/interfaces/gtk2/gtk2devicecontext.inc | 54 +++++++++++ lcl/interfaces/gtk2/gtk2extrah.inc | 104 ++++++++++++++-------- lcl/interfaces/gtk2/gtk2lclintf.inc | 2 +- lcl/interfaces/gtk2/gtk2winapi.inc | 79 +++++++--------- 6 files changed, 157 insertions(+), 90 deletions(-) diff --git a/lcl/interfaces/gtk/gtkwinapi.inc b/lcl/interfaces/gtk/gtkwinapi.inc index cf0f3eca62..c48197800d 100644 --- a/lcl/interfaces/gtk/gtkwinapi.inc +++ b/lcl/interfaces/gtk/gtkwinapi.inc @@ -1367,7 +1367,7 @@ end; ------------------------------------------------------------------------------} function TGtkWidgetSet.CreateFontIndirect(const LogFont: TLogFont): HFONT; begin - Result:=CreateFontIndirectEx(LogFont,''); + Result := CreateFontIndirectEx(LogFont,''); end; {------------------------------------------------------------------------------ @@ -3148,7 +3148,6 @@ begin if not IsValidDC(DC) then Exit(0); if Count < -1 then Exit(0); - // Don't try to use StrLen(Str) in cases count >= 0 // In those cases str is NOT required to have a null terminator ! diff --git a/lcl/interfaces/gtk2/gtk2def.pp b/lcl/interfaces/gtk2/gtk2def.pp index 6dec0f7fbd..2e89501811 100644 --- a/lcl/interfaces/gtk2/gtk2def.pp +++ b/lcl/interfaces/gtk2/gtk2def.pp @@ -32,9 +32,7 @@ interface uses glib2, gdk2pixbuf, pango, gdk2, gtk2, -// Classes, SysUtils, LCLIntf, LCLProc, LCLType, DynHashArray, -// GraphType, GtkExtra, - GtkDef; + GtkExtra, GtkDef; type @@ -46,6 +44,7 @@ type protected function GetFunction: TGdkFunction; override; public + procedure DrawTextWithColors(AText: PChar; ALength: LongInt; X, Y: Integer; FGColor, BGColor: PGdkColor); end; implementation diff --git a/lcl/interfaces/gtk2/gtk2devicecontext.inc b/lcl/interfaces/gtk2/gtk2devicecontext.inc index ff2e9712e3..a1d5b30844 100644 --- a/lcl/interfaces/gtk2/gtk2devicecontext.inc +++ b/lcl/interfaces/gtk2/gtk2devicecontext.inc @@ -31,4 +31,58 @@ begin Result := GCValues._function; end; +procedure TGtk2DeviceContext.DrawTextWithColors(AText: PChar; ALength: LongInt; X, Y: Integer; FGColor, BGColor: PGdkColor); +var + WidgetCont: PPangoContext; + newmatrix: TPangoMatrix; + oldmatrix: PPangoMatrix; + renderer: PPangoRenderer; + AFont: PGdiObject; + + procedure SetColors(AFGColor, ABGColor: PGdkColor); inline; + begin + gdk_pango_renderer_set_override_color(renderer, PANGO_RENDER_PART_FOREGROUND, AFGColor); + gdk_pango_renderer_set_override_color(renderer, PANGO_RENDER_PART_UNDERLINE, AFGColor); + gdk_pango_renderer_set_override_color(renderer, PANGO_RENDER_PART_STRIKETHROUGH, AFGColor); + gdk_pango_renderer_set_override_color(renderer, PANGO_RENDER_PART_BACKGROUND, ABGColor); + end; + +begin + AFont := GetFont; + pango_layout_set_text(AFont^.GDIFontObject, AText, ALength); + + if AFont^.LogFont.lfEscapement <> 0 then + begin + renderer := gdk_pango_renderer_get_default(gdk_screen_get_default()); + gdk_pango_renderer_set_drawable(renderer, drawable); + gdk_pango_renderer_set_gc(renderer, GC); + SetColors(FGColor, BGColor); + + WidgetCont := pango_layout_get_context(AFont^.GDIFontObject); + oldmatrix := pango_context_get_matrix(WidgetCont); + newmatrix.xx := 1.0; + newmatrix.xy := 0.0; + newmatrix.yx := 0.0; + newmatrix.yy := 1.0; + newmatrix.x0 := 0.0; + newmatrix.y0 := 0.0; + pango_matrix_translate(@newmatrix, X, Y); + pango_matrix_rotate(@newmatrix, AFont^.LogFont.lfEscapement div 10); + + pango_context_set_matrix(WidgetCont, @newmatrix); + pango_layout_context_changed(AFont^.GDIFontObject); + pango_renderer_draw_layout(renderer, AFont^.GDIFontObject, X, Y); + + //now reset + pango_context_set_matrix(WidgetCont, oldmatrix); + pango_layout_context_changed(AFont^.GDIFontObject); + + SetColors(nil, nil); + gdk_pango_renderer_set_drawable(renderer, nil); + gdk_pango_renderer_set_gc(renderer, nil); + end + else + gdk_draw_layout_with_colors(drawable, GC, X, Y, AFont^.GDIFontObject, FGColor, BGColor); +end; + diff --git a/lcl/interfaces/gtk2/gtk2extrah.inc b/lcl/interfaces/gtk2/gtk2extrah.inc index 5c578a8d7c..70aa943148 100644 --- a/lcl/interfaces/gtk2/gtk2extrah.inc +++ b/lcl/interfaces/gtk2/gtk2extrah.inc @@ -52,8 +52,63 @@ function gdk_x11_image_get_ximage(image:PGdkImage):PXImage;cdecl;external gdklib procedure laz_gdk_gc_set_dashes(gc:PGdkGC; dash_offset:gint; dashlist:Pgint8; n:gint); cdecl; external gdkdll name 'gdk_gc_set_dashes'; +// - - - - - - - - - pango extras - - - - - - - - - type PPPangoAttrList = ^PPangoAttrList; +// pango 1.6 + PPangoMatrix = ^TPangoMatrix; + TPangoMatrix = record + xx: double; + xy: double; + yx: double; + yy: double; + x0: double; + y0: double; + end; + +// pango 1.8 + TPangoRenderer = pointer; + PPangoRenderer = ^TPangoRenderer; + TPangoRenderPart = ( + PANGO_RENDER_PART_FOREGROUND, + PANGO_RENDER_PART_BACKGROUND, + PANGO_RENDER_PART_UNDERLINE, + PANGO_RENDER_PART_STRIKETHROUGH + ); + +// pango 1.16 + PPangoGravity = ^TPangoGravity; + TPangoGravity = ( + PANGO_GRAVITY_SOUTH, + PANGO_GRAVITY_EAST, + PANGO_GRAVITY_NORTH, + PANGO_GRAVITY_WEST, + PANGO_GRAVITY_AUTO + ); + +function pango_context_get_gravity(Context: PPangoContext): TPangoGravity; cdecl; external pangolib; +procedure pango_context_set_base_gravity(Context: PPangoContext; gravity: TPangoGravity); cdecl; external pangolib; + +function pango_context_get_matrix(Context: PPangoContext): PPangoMatrix; cdecl; external pangolib; +procedure pango_context_set_matrix(context: PPangoContext; const matrix: PPangoMatrix); cdecl; external pangolib; +procedure pango_matrix_translate(matrix: PPangoMatrix; tx, ty: double); cdecl; external pangolib; +procedure pango_matrix_rotate(matrix: PPangoMatrix; degrees: double); cdecl; external pangolib; + +function pango_font_description_get_gravity(desc: PPangoFontDescription): TPangoGravity; cdecl; external pangolib; +procedure pango_font_description_set_gravity(desc: PPangoFontDescription; gravity: TPangoGravity); cdecl; external pangolib; + +function pango_attr_gravity_new(gravity: TPangoGravity): PPangoAttribute; cdecl; external pangolib; + +procedure pango_renderer_draw_layout(renderer: PPangoRenderer; layout: PPangoLayout; x, y: Integer); cdecl; external pangolib; + +function pango_version_check(required_major, required_minor, required_micro: integer): PChar; cdecl; external pangolib; + +{$if defined(VER2_0) or defined(VER2_2_0)} +function pango_layout_get_font_description(layout:PPangoLayout):PPangoFontDescription; cdecl; external pangolib; +{$ifend} + +// - - - - - - - - - gtk extras - - - - - - - - - + procedure gtk_im_context_get_preedit_string_laz(context:PGtkIMContext; str:PPgchar; attrs:PPPangoAttrList; cursor_pos:Pgint); cdecl; external gtklib name 'gtk_im_context_get_preedit_string'; function gdk_event_new(_type: TGdkEventType): PGdkEvent; cdecl; external gdklib; @@ -68,7 +123,11 @@ procedure gtk_event_box_set_above_child(event_box: PGtkEventBox; visible_window: // gtk 2.6 function gtk_cell_view_get_displayed_row(cell_view: Pointer): PGtkTreePath; cdecl; external gtklib name 'gtk_cell_view_get_displayed_row'; +// - - - - - - - - - gdk extras - - - - - - - - - +type + PGdkPangoRenderer = pointer; + // gdk 2.2 procedure gdk_display_get_pointer(display : PGdkDisplay; screen :PGdkScreen; x :Pgint; y : Pgint; mask : PGdkModifierType); cdecl; external gdklib; function gdk_display_get_default:PGdkDisplay; cdecl; external gdklib; @@ -83,6 +142,12 @@ function gdk_cursor_new_from_pixbuf(display: PGdkDisplay; pixbuf: PGdkPixbuf; x, function gdk_display_get_default_cursor_size(display: PGdkDisplay): guint; cdecl; external gdklib; procedure gdk_display_get_maximal_cursor_size(display: PGdkDisplay; w, h: pguint); cdecl; external gdklib; +// gdk 2.6 +function gdk_pango_renderer_get_default(screen: PGdkScreen): PPangoRenderer; cdecl; external gdklib; +procedure gdk_pango_renderer_set_drawable(gdk_renderer: PGdkPangoRenderer; drawable: PGdkDrawable); cdecl; external gdklib; +procedure gdk_pango_renderer_set_gc(gdk_renderer: PGdkPangoRenderer; gc: PGdkGC); cdecl; external gdklib; +procedure gdk_pango_renderer_set_override_color(gdk_renderer: PGdkPangoRenderer; part: TPangoRenderPart; color: PGdkColor); cdecl; external gdklib; + {$ifdef GTK_2_8} // gdk 2.8 procedure gdk_display_warp_pointer(display: PGdkDisplay; screen: PGdkScreen; x, y: gint); cdecl; external gdklib; @@ -95,42 +160,3 @@ function gdk_screen_is_composited(screen: PGdkScreen): gboolean; cdecl; external function gdk_display_supports_cursor_alpha(display: PGdkDisplay): gBoolean; cdecl; external gdklib; function gdk_display_supports_cursor_color(display: PGdkDisplay): gBoolean; cdecl; external gdklib; } - -// pango 1.6 -type - PPangoMatrix = ^TPangoMatrix; - TPangoMatrix = record - xx: double; - xy: double; - yx: double; - yy: double; - x0: double; - y0: double; - end; - -// pango 1.16 - PPangoGravity = ^TPangoGravity; - TPangoGravity = ( - PANGO_GRAVITY_SOUTH, - PANGO_GRAVITY_EAST, - PANGO_GRAVITY_NORTH, - PANGO_GRAVITY_WEST, - PANGO_GRAVITY_AUTO - ); - -function pango_context_get_gravity(Context: PPangoContext): TPangoGravity; cdecl; external pangolib; -procedure pango_context_set_base_gravity(Context: PPangoContext; gravity: TPangoGravity); cdecl; external pangolib; - -function pango_context_get_matrix(Context: PPangoContext): PPangoMatrix; cdecl; external pangolib; -procedure pango_context_set_matrix(context: PPangoContext; const matrix: PPangoMatrix); cdecl; external pangolib; - -function pango_font_description_get_gravity(desc: PPangoFontDescription): TPangoGravity; cdecl; external pangolib; -procedure pango_font_description_set_gravity(desc: PPangoFontDescription; gravity: TPangoGravity); cdecl; external pangolib; - -function pango_attr_gravity_new(gravity: TPangoGravity): PPangoAttribute; cdecl; external pangolib; - -function pango_version_check(required_major, required_minor, required_micro: integer): PChar; cdecl; external pangolib; - -{$if defined(VER2_0) or defined(VER2_2_0)} -function pango_layout_get_font_description(layout:PPangoLayout):PPangoFontDescription; cdecl; external pangolib; -{$ifend} diff --git a/lcl/interfaces/gtk2/gtk2lclintf.inc b/lcl/interfaces/gtk2/gtk2lclintf.inc index e63847e3bf..7931927ab5 100644 --- a/lcl/interfaces/gtk2/gtk2lclintf.inc +++ b/lcl/interfaces/gtk2/gtk2lclintf.inc @@ -41,7 +41,7 @@ function TGtk2WidgetSet.TextUTF8Out(DC: HDC; X, Y: Integer; Str: PChar; Count: Longint): Boolean; begin // all fonts are UTF-8 under gtk2 => no mapping needed - Result:=TextOut(DC,X,Y,Str,Count); + Result := TextOut(DC, X, Y, Str, Count); end; function TGtk2WidgetSet.ComboBoxDropDown(Handle: HWND; DropDown: boolean): boolean; diff --git a/lcl/interfaces/gtk2/gtk2winapi.inc b/lcl/interfaces/gtk2/gtk2winapi.inc index ecf892491b..a56b49b11a 100644 --- a/lcl/interfaces/gtk2/gtk2winapi.inc +++ b/lcl/interfaces/gtk2/gtk2winapi.inc @@ -339,7 +339,7 @@ end; function TGtk2WidgetSet.ExtTextOut(DC: HDC; X, Y: Integer; Options: Longint; Rect: PRect; Str: PChar; Count: Longint; Dx: PInteger): Boolean; var - DevCtx: TGtkDeviceContext absolute DC; + DevCtx: TGtk2DeviceContext absolute DC; LineStart, LineEnd, StrEnd: PChar; Width, Height: Integer; @@ -347,7 +347,6 @@ var TxtPt: TPoint; DCOrigin: TPoint; Foreground: PGDKColor; - UseFont: PPangoLayout; CurDx: PInteger; CurStr: PChar; @@ -356,27 +355,21 @@ var CurScreenX: LongInt; CharLen: LongInt; begin - if (Dx<>nil) - then begin - CurScreenX:=X; - while CurCount>0 do begin - 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, - UseFont, Foreground, nil); - //gdk_draw_rectangle(DevCtx.Drawable,DevCtx.GC,1,CurScreenX,Y,3,3); - inc(CurScreenX,CurDx^); + if (Dx <> nil) then + begin + CurScreenX := X; + while CurCount > 0 do + begin + CharLen := UTF8CharacterLength(CurStr); + DevCtx.DrawTextWithColors(CurStr, CharLen, CurScreenX, Y, Foreground, nil); + inc(CurScreenX, CurDx^); inc(CurDx); - inc(CurStr,CharLen); - dec(CurCount,CharLen); + inc(CurStr, CharLen); + dec(CurCount, CharLen); end; end - else begin - pango_layout_set_text(UseFont, Str, Count); - gdk_draw_layout_with_colors(DevCtx.drawable, DevCtx.GC, X, Y, UseFont, - Foreground, nil); - end; + else + DevCtx.DrawTextWithColors(Str, Count, X, Y, Foreground, nil); end; begin @@ -395,11 +388,9 @@ begin exit; end; - UseFont:=GetGtkFont(DevCtx); - // to reduce flickering calculate first and then paint - DCOrigin:=DevCtx.Offset; + DCOrigin := DevCtx.Offset; if (Options and ETO_CLIPPED) <> 0 then begin @@ -434,26 +425,28 @@ begin CurDx:=Dx; CurStr:=Str; LineStart:=Str; - if LineLen < 0 then begin + if LineLen < 0 then + begin LineLen:=Count; if Count> 0 then DoTextOut(TxtPt.X, TxtPt.Y, LineStart, LineLen); end else - Begin //write multiple lines - StrEnd:=Str+Count; - while LineStart < StrEnd do begin - LineEnd:=LineStart+LineLen; + begin //write multiple lines + StrEnd := Str + Count; + while LineStart < StrEnd do + begin + LineEnd := LineStart + LineLen; if LineLen>0 then DoTextOut(TxtPt.X, TxtPt.Y, LineStart, LineLen); - inc(TxtPt.Y,LineHeight); - LineStart:=LineEnd+1; // skip #13 + inc(TxtPt.Y, LineHeight); + LineStart := LineEnd + 1; // skip #13 if (LineStart LineEnd^) then inc(LineStart); // skip #10 - Count:=StrEnd-LineStart; - LineLen:=FindLineLen(LineStart,Count); - if LineLen<0 then - LineLen:=Count; + Count := StrEnd - LineStart; + LineLen := FindLineLen(LineStart, Count); + if LineLen < 0 then + LineLen := Count; end; end; @@ -562,32 +555,28 @@ end; function TGtk2WidgetSet.TextOut(DC: HDC; X,Y : Integer; Str : Pchar; Count: Integer) : Boolean; var - DevCtx: TGtkDeviceContext absolute DC; + DevCtx: TGtk2DeviceContext absolute DC; DCOrigin: TPoint; yOffset: integer; - UseFont: PPangoLayout; begin Result := IsValidDC(DC); if not Result then Exit; if Count <= 0 then Exit; - UseFont := GetGtkFont(DevCtx); UpdateDCTextMetric(DevCtx); DCOrigin := DevCtx.Offset; with DevCtx.DCTextMetric.TextMetric do - yOffset:= tmHeight-tmDescent-tmAscent; - if yOffset<0 then yOffset:=0; + yOffset := tmHeight-tmDescent-tmAscent; + if yOffset < 0 then + yOffset := 0; DevCtx.SelectedColors := dcscCustom; EnsureGCColor(DC, dccCurrentTextColor, True, False); - pango_layout_set_text(UseFont, Str, Count); - 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(DevCtx.drawable, DevCtx.GC, - X+DCOrigin.X, Y+DCOrigin.Y+yOffset, UseFont, nil, nil); + DevCtx.DrawTextWithColors(Str, Count, + X + DCOrigin.X, Y + DCOrigin.Y + yOffset, + nil, nil); end; function TGtk2WidgetSet.UpdateWindow(Handle: HWND): Boolean;