View Issue Details

IDProjectCategoryView StatusLast Update
0036292LazarusWidgetsetpublic2019-11-12 23:29
ReporterCudaText manAssigned ToJuha Manninen 
PrioritynormalSeverityminorReproducibilityalways
Status resolvedResolutionfixed 
PlatformUbuntu 19 x64OSOS Version
Product Version2.1 (SVN)Product Build 
Target VersionFixed in Version 
Summary0036292: gtk3: Problem with label autosize with Japanese text
DescriptionThere is the same issue but for qt4 or qt5 (I cannot find it today). it was fixed.
Run the demo, japanese text is clipped by height, see screenshot.

I tried to find the problem but seems it is call to
function TGtk3WidgetSet.GetTextExtentPoint(DC: HDC; Str: PChar; Count: Integer;
  var Size: TSize): Boolean;
...
  TGtk3DeviceContext(DC).CurrentFont.Layout^.set_text(Str, Count);
  TGtk3DeviceContext(DC).CurrentFont.Layout^.get_pixel_size(@Size.Cx, @Size.CY);
...

it cannot be fixed?
TagsNo tags attached.
Fixed in Revisionr62232
LazTarget-
WidgetsetGTK 3
Attached Files
  • tst-jp-label.zip (3,114 bytes)
  • j.diff (652 bytes)
    Index: lcl/interfaces/gtk3/gtk3winapi.inc
    ===================================================================
    --- lcl/interfaces/gtk3/gtk3winapi.inc	(revision 62230)
    +++ lcl/interfaces/gtk3/gtk3winapi.inc	(working copy)
    @@ -722,7 +722,10 @@
           TextExtentPoint(PChar(AStr), length(AStr), AP{%H-});
           theRect.Bottom := theRect.Top + TM.tmHeight;
           if (Flags and DT_CALCRECT)<>0 then
    -        theRect.Right := theRect.Left +  AP.cX
    +      begin
    +        theRect.Right := theRect.Left +  AP.cX;
    +        theRect.Bottom := theRect.Top + AP.cY;
    +      end
           else
           begin
             theRect.Right := theRect.Left + Min(MaxWidth, AP.cX);
    
    j.diff (652 bytes)
  • tst-jp-label-multiline.zip (3,186 bytes)
  • j2.diff (3,020 bytes)
    Index: lcl/interfaces/gtk3/gtk3winapi.inc
    ===================================================================
    --- lcl/interfaces/gtk3/gtk3winapi.inc	(revision 62230)
    +++ lcl/interfaces/gtk3/gtk3winapi.inc	(working copy)
    @@ -630,6 +630,8 @@
       l: LongInt;
       Pt: TPoint;
       SavedRect: TRect; // if font orientation <> 0
    +  LineHeight: Integer;
    +  Size: TSize;
     
       function LeftOffset: Longint;
       begin
    @@ -674,17 +676,13 @@
       procedure DoCalcRect;
       var
         AP: TSize;
    -    J, MaxWidth,
    -    LineWidth: Integer;
    -    PR1, PR2: TPangoRectangle;
    -    Alignment: Integer;
    -    ADevOffset: TPoint;
    +    J, MaxWidth, DefHeight,
    +    LineWidth, LineHeight: Integer;
       begin
    -
    -
         theRect := Rect;
     
         MaxWidth := theRect.Right - theRect.Left;
    +    DefHeight := theRect.Bottom - theRect.Top;
     
         (*
         if Flags and DT_CENTER  <> 0then
    @@ -722,7 +720,10 @@
           TextExtentPoint(PChar(AStr), length(AStr), AP{%H-});
           theRect.Bottom := theRect.Top + TM.tmHeight;
           if (Flags and DT_CALCRECT)<>0 then
    -        theRect.Right := theRect.Left +  AP.cX
    +      begin
    +        theRect.Right := theRect.Left +  AP.cX;
    +        theRect.Bottom := theRect.Top + AP.cY;
    +      end
           else
           begin
             theRect.Right := theRect.Left + Min(MaxWidth, AP.cX);
    @@ -745,6 +746,7 @@
             // do not break at word boundaries
             TextExtentPoint(PChar(AStr), length(AStr), AP);
             MaxWidth := AP.cX;
    +        DefHeight := AP.cY;
           end;
     
           Gtk3WordWrap(DC, PChar(AStr), MaxWidth, Lines, NumLines);
    @@ -752,6 +754,7 @@
           if (Flags and DT_CALCRECT)<>0 then
           begin
             LineWidth := 0;
    +        LineHeight := 0;
             if (Lines <> nil) then
             begin
               for J := 0 to NumLines - 1 do
    @@ -758,14 +761,18 @@
               begin
                 TextExtentPoint(Lines[J], StrLen(Lines[J]), AP);
                 LineWidth := Max(LineWidth, AP.cX);
    +            Inc(LineHeight, AP.cY);
               end;
             end;
             LineWidth := Min(MaxWidth, LineWidth);
           end else
    +      begin
             LineWidth := MaxWidth;
    +        LineHeight := DefHeight;
    +      end;
     
           theRect.Right := theRect.Left + LineWidth;
    -      theRect.Bottom := theRect.Top + NumLines*TM.tmHeight;
    +      theRect.Bottom := theRect.Top + LineHeight;
           if NumLines>1 then
             Inc(theRect.Bottom, (NumLines-1)*TM.tmDescent);// space between lines
     
    @@ -1022,12 +1029,17 @@
           and (tm.tmHeight > (theRect.Bottom - theRect.Top))
           then Break;
     
    -      if Lines[i] <> nil then begin
    +      if Lines[i] <> nil then
    +      begin
             l:=StrLen(Lines[i]);
             DrawLine(Lines[i], l, theRect.Top);
             dec(pIndex,l+length(LineEnding));
    -      end;
    -      Inc(theRect.Top, TM.tmDescent + TM.tmHeight);// space between lines
    +        GetTextExtentPoint(DC, Lines[i], l, Size);
    +        LineHeight := Size.cY;
    +      end
    +      else
    +        LineHeight := TM.tmHeight;
    +      Inc(theRect.Top, LineHeight + TM.tmDescent); // space between lines
         end;
     
       finally
    
    j2.diff (3,020 bytes)
  • j3.diff (3,031 bytes)
    Index: lcl/interfaces/gtk3/gtk3winapi.inc
    ===================================================================
    --- lcl/interfaces/gtk3/gtk3winapi.inc	(revision 62230)
    +++ lcl/interfaces/gtk3/gtk3winapi.inc	(working copy)
    @@ -630,6 +630,8 @@
       l: LongInt;
       Pt: TPoint;
       SavedRect: TRect; // if font orientation <> 0
    +  LineHeight: Integer;
    +  Size: TSize;
     
       function LeftOffset: Longint;
       begin
    @@ -674,17 +676,13 @@
       procedure DoCalcRect;
       var
         AP: TSize;
    -    J, MaxWidth,
    -    LineWidth: Integer;
    -    PR1, PR2: TPangoRectangle;
    -    Alignment: Integer;
    -    ADevOffset: TPoint;
    +    J, MaxWidth, DefHeight,
    +    LineWidth, LineHeight: Integer;
       begin
    -
    -
         theRect := Rect;
     
         MaxWidth := theRect.Right - theRect.Left;
    +    DefHeight := theRect.Bottom - theRect.Top;
     
         (*
         if Flags and DT_CENTER  <> 0then
    @@ -722,7 +720,10 @@
           TextExtentPoint(PChar(AStr), length(AStr), AP{%H-});
           theRect.Bottom := theRect.Top + TM.tmHeight;
           if (Flags and DT_CALCRECT)<>0 then
    -        theRect.Right := theRect.Left +  AP.cX
    +      begin
    +        theRect.Right := theRect.Left +  AP.cX;
    +        theRect.Bottom := theRect.Top + AP.cY;
    +      end
           else
           begin
             theRect.Right := theRect.Left + Min(MaxWidth, AP.cX);
    @@ -745,6 +746,7 @@
             // do not break at word boundaries
             TextExtentPoint(PChar(AStr), length(AStr), AP);
             MaxWidth := AP.cX;
    +        DefHeight := AP.cY;
           end;
     
           Gtk3WordWrap(DC, PChar(AStr), MaxWidth, Lines, NumLines);
    @@ -752,6 +754,7 @@
           if (Flags and DT_CALCRECT)<>0 then
           begin
             LineWidth := 0;
    +        LineHeight := 0;
             if (Lines <> nil) then
             begin
               for J := 0 to NumLines - 1 do
    @@ -758,14 +761,18 @@
               begin
                 TextExtentPoint(Lines[J], StrLen(Lines[J]), AP);
                 LineWidth := Max(LineWidth, AP.cX);
    +            Inc(LineHeight, AP.cY);
               end;
             end;
             LineWidth := Min(MaxWidth, LineWidth);
           end else
    +      begin
             LineWidth := MaxWidth;
    +        LineHeight := NumLines*TM.tmHeight;
    +      end;
     
           theRect.Right := theRect.Left + LineWidth;
    -      theRect.Bottom := theRect.Top + NumLines*TM.tmHeight;
    +      theRect.Bottom := theRect.Top + LineHeight;
           if NumLines>1 then
             Inc(theRect.Bottom, (NumLines-1)*TM.tmDescent);// space between lines
     
    @@ -1022,12 +1029,17 @@
           and (tm.tmHeight > (theRect.Bottom - theRect.Top))
           then Break;
     
    -      if Lines[i] <> nil then begin
    +      if Lines[i] <> nil then
    +      begin
             l:=StrLen(Lines[i]);
             DrawLine(Lines[i], l, theRect.Top);
             dec(pIndex,l+length(LineEnding));
    -      end;
    -      Inc(theRect.Top, TM.tmDescent + TM.tmHeight);// space between lines
    +        GetTextExtentPoint(DC, Lines[i], l, Size);
    +        LineHeight := Size.cY;
    +      end
    +      else
    +        LineHeight := TM.tmHeight;
    +      Inc(theRect.Top, LineHeight + TM.tmDescent); // space between lines
         end;
     
       finally
    
    j3.diff (3,031 bytes)

Relationships

related to 0036293 resolvedJuha Manninen gtk2: Incorrect rendering of multiline label with Japanese text 

Activities

CudaText man

2019-11-11 11:19

reporter  

tst-jp-label.zip (3,114 bytes)

CudaText man

2019-11-11 11:46

reporter   ~0119221

fixed it.

j.diff (652 bytes)
Index: lcl/interfaces/gtk3/gtk3winapi.inc
===================================================================
--- lcl/interfaces/gtk3/gtk3winapi.inc	(revision 62230)
+++ lcl/interfaces/gtk3/gtk3winapi.inc	(working copy)
@@ -722,7 +722,10 @@
       TextExtentPoint(PChar(AStr), length(AStr), AP{%H-});
       theRect.Bottom := theRect.Top + TM.tmHeight;
       if (Flags and DT_CALCRECT)<>0 then
-        theRect.Right := theRect.Left +  AP.cX
+      begin
+        theRect.Right := theRect.Left +  AP.cX;
+        theRect.Bottom := theRect.Top + AP.cY;
+      end
       else
       begin
         theRect.Right := theRect.Left + Min(MaxWidth, AP.cX);
j.diff (652 bytes)

Anton Kavalenka

2019-11-11 12:26

reporter   ~0119223

GetTextExtentPoint() works properly with correction +/-1 pixel clipping

CudaText man

2019-11-11 12:33

reporter   ~0119224

i found new issue-- MULTILINE Japanese label paints bad, ie Japanese wrapped parts paint with incorrect height.
i fixed it, j2.diff replaces j.diff.
Adding new demo with multiline label and screenshot after fix.

tst-jp-label-multiline.zip (3,186 bytes)
j2.diff (3,020 bytes)
Index: lcl/interfaces/gtk3/gtk3winapi.inc
===================================================================
--- lcl/interfaces/gtk3/gtk3winapi.inc	(revision 62230)
+++ lcl/interfaces/gtk3/gtk3winapi.inc	(working copy)
@@ -630,6 +630,8 @@
   l: LongInt;
   Pt: TPoint;
   SavedRect: TRect; // if font orientation <> 0
+  LineHeight: Integer;
+  Size: TSize;
 
   function LeftOffset: Longint;
   begin
@@ -674,17 +676,13 @@
   procedure DoCalcRect;
   var
     AP: TSize;
-    J, MaxWidth,
-    LineWidth: Integer;
-    PR1, PR2: TPangoRectangle;
-    Alignment: Integer;
-    ADevOffset: TPoint;
+    J, MaxWidth, DefHeight,
+    LineWidth, LineHeight: Integer;
   begin
-
-
     theRect := Rect;
 
     MaxWidth := theRect.Right - theRect.Left;
+    DefHeight := theRect.Bottom - theRect.Top;
 
     (*
     if Flags and DT_CENTER  <> 0then
@@ -722,7 +720,10 @@
       TextExtentPoint(PChar(AStr), length(AStr), AP{%H-});
       theRect.Bottom := theRect.Top + TM.tmHeight;
       if (Flags and DT_CALCRECT)<>0 then
-        theRect.Right := theRect.Left +  AP.cX
+      begin
+        theRect.Right := theRect.Left +  AP.cX;
+        theRect.Bottom := theRect.Top + AP.cY;
+      end
       else
       begin
         theRect.Right := theRect.Left + Min(MaxWidth, AP.cX);
@@ -745,6 +746,7 @@
         // do not break at word boundaries
         TextExtentPoint(PChar(AStr), length(AStr), AP);
         MaxWidth := AP.cX;
+        DefHeight := AP.cY;
       end;
 
       Gtk3WordWrap(DC, PChar(AStr), MaxWidth, Lines, NumLines);
@@ -752,6 +754,7 @@
       if (Flags and DT_CALCRECT)<>0 then
       begin
         LineWidth := 0;
+        LineHeight := 0;
         if (Lines <> nil) then
         begin
           for J := 0 to NumLines - 1 do
@@ -758,14 +761,18 @@
           begin
             TextExtentPoint(Lines[J], StrLen(Lines[J]), AP);
             LineWidth := Max(LineWidth, AP.cX);
+            Inc(LineHeight, AP.cY);
           end;
         end;
         LineWidth := Min(MaxWidth, LineWidth);
       end else
+      begin
         LineWidth := MaxWidth;
+        LineHeight := DefHeight;
+      end;
 
       theRect.Right := theRect.Left + LineWidth;
-      theRect.Bottom := theRect.Top + NumLines*TM.tmHeight;
+      theRect.Bottom := theRect.Top + LineHeight;
       if NumLines>1 then
         Inc(theRect.Bottom, (NumLines-1)*TM.tmDescent);// space between lines
 
@@ -1022,12 +1029,17 @@
       and (tm.tmHeight > (theRect.Bottom - theRect.Top))
       then Break;
 
-      if Lines[i] <> nil then begin
+      if Lines[i] <> nil then
+      begin
         l:=StrLen(Lines[i]);
         DrawLine(Lines[i], l, theRect.Top);
         dec(pIndex,l+length(LineEnding));
-      end;
-      Inc(theRect.Top, TM.tmDescent + TM.tmHeight);// space between lines
+        GetTextExtentPoint(DC, Lines[i], l, Size);
+        LineHeight := Size.cY;
+      end
+      else
+        LineHeight := TM.tmHeight;
+      Inc(theRect.Top, LineHeight + TM.tmDescent); // space between lines
     end;
 
   finally
j2.diff (3,020 bytes)

CudaText man

2019-11-11 12:50

reporter  

j3.diff (3,031 bytes)
Index: lcl/interfaces/gtk3/gtk3winapi.inc
===================================================================
--- lcl/interfaces/gtk3/gtk3winapi.inc	(revision 62230)
+++ lcl/interfaces/gtk3/gtk3winapi.inc	(working copy)
@@ -630,6 +630,8 @@
   l: LongInt;
   Pt: TPoint;
   SavedRect: TRect; // if font orientation <> 0
+  LineHeight: Integer;
+  Size: TSize;
 
   function LeftOffset: Longint;
   begin
@@ -674,17 +676,13 @@
   procedure DoCalcRect;
   var
     AP: TSize;
-    J, MaxWidth,
-    LineWidth: Integer;
-    PR1, PR2: TPangoRectangle;
-    Alignment: Integer;
-    ADevOffset: TPoint;
+    J, MaxWidth, DefHeight,
+    LineWidth, LineHeight: Integer;
   begin
-
-
     theRect := Rect;
 
     MaxWidth := theRect.Right - theRect.Left;
+    DefHeight := theRect.Bottom - theRect.Top;
 
     (*
     if Flags and DT_CENTER  <> 0then
@@ -722,7 +720,10 @@
       TextExtentPoint(PChar(AStr), length(AStr), AP{%H-});
       theRect.Bottom := theRect.Top + TM.tmHeight;
       if (Flags and DT_CALCRECT)<>0 then
-        theRect.Right := theRect.Left +  AP.cX
+      begin
+        theRect.Right := theRect.Left +  AP.cX;
+        theRect.Bottom := theRect.Top + AP.cY;
+      end
       else
       begin
         theRect.Right := theRect.Left + Min(MaxWidth, AP.cX);
@@ -745,6 +746,7 @@
         // do not break at word boundaries
         TextExtentPoint(PChar(AStr), length(AStr), AP);
         MaxWidth := AP.cX;
+        DefHeight := AP.cY;
       end;
 
       Gtk3WordWrap(DC, PChar(AStr), MaxWidth, Lines, NumLines);
@@ -752,6 +754,7 @@
       if (Flags and DT_CALCRECT)<>0 then
       begin
         LineWidth := 0;
+        LineHeight := 0;
         if (Lines <> nil) then
         begin
           for J := 0 to NumLines - 1 do
@@ -758,14 +761,18 @@
           begin
             TextExtentPoint(Lines[J], StrLen(Lines[J]), AP);
             LineWidth := Max(LineWidth, AP.cX);
+            Inc(LineHeight, AP.cY);
           end;
         end;
         LineWidth := Min(MaxWidth, LineWidth);
       end else
+      begin
         LineWidth := MaxWidth;
+        LineHeight := NumLines*TM.tmHeight;
+      end;
 
       theRect.Right := theRect.Left + LineWidth;
-      theRect.Bottom := theRect.Top + NumLines*TM.tmHeight;
+      theRect.Bottom := theRect.Top + LineHeight;
       if NumLines>1 then
         Inc(theRect.Bottom, (NumLines-1)*TM.tmDescent);// space between lines
 
@@ -1022,12 +1029,17 @@
       and (tm.tmHeight > (theRect.Bottom - theRect.Top))
       then Break;
 
-      if Lines[i] <> nil then begin
+      if Lines[i] <> nil then
+      begin
         l:=StrLen(Lines[i]);
         DrawLine(Lines[i], l, theRect.Top);
         dec(pIndex,l+length(LineEnding));
-      end;
-      Inc(theRect.Top, TM.tmDescent + TM.tmHeight);// space between lines
+        GetTextExtentPoint(DC, Lines[i], l, Size);
+        LineHeight := Size.cY;
+      end
+      else
+        LineHeight := TM.tmHeight;
+      Inc(theRect.Top, LineHeight + TM.tmDescent); // space between lines
     end;
 
   finally
j3.diff (3,031 bytes)

Zeljan Rikalo

2019-11-11 13:39

developer   ~0119226

So, which diff is correct ? j3.diff ?

CudaText man

2019-11-11 14:43

reporter   ~0119227

j3.diff is only needed.

Anton Kavalenka

2019-11-11 15:56

reporter   ~0119229

@Alexey Tor.
multiline should be handled by r62226

CudaText man

2019-11-11 20:50

reporter   ~0119231

@Anton
my fix is needed anyway. see the 2 screenshots from the same issue- it was fixed the same way for gtk2-- 0036293 .

Juha Manninen

2019-11-12 23:29

developer   ~0119244

Applied, thanks.

Issue History

Date Modified Username Field Change
2019-11-11 11:19 CudaText man New Issue
2019-11-11 11:19 CudaText man File Added: tst-jp-label.zip
2019-11-11 11:19 CudaText man File Added: Screenshot from 2019-11-11 13-11-35.png
2019-11-11 11:46 CudaText man File Added: j.diff
2019-11-11 11:46 CudaText man Note Added: 0119221
2019-11-11 12:26 Anton Kavalenka File Added: Здымак экрана, 2019-11-11 14-23-57.png
2019-11-11 12:26 Anton Kavalenka Note Added: 0119223
2019-11-11 12:33 CudaText man File Added: tst-jp-label-multiline.zip
2019-11-11 12:33 CudaText man File Added: j2.diff
2019-11-11 12:33 CudaText man File Added: Screenshot from 2019-11-11 14-23-07.png
2019-11-11 12:33 CudaText man Note Added: 0119224
2019-11-11 12:50 CudaText man File Added: j3.diff
2019-11-11 13:39 Zeljan Rikalo Note Added: 0119226
2019-11-11 14:43 CudaText man Note Added: 0119227
2019-11-11 15:56 Anton Kavalenka Note Added: 0119229
2019-11-11 20:50 CudaText man Note Added: 0119231
2019-11-12 23:14 Juha Manninen Relationship added related to 0036293
2019-11-12 23:21 Juha Manninen Assigned To => Juha Manninen
2019-11-12 23:21 Juha Manninen Status new => assigned
2019-11-12 23:29 Juha Manninen Status assigned => resolved
2019-11-12 23:29 Juha Manninen Resolution open => fixed
2019-11-12 23:29 Juha Manninen Fixed in Revision => r62232
2019-11-12 23:29 Juha Manninen LazTarget => -
2019-11-12 23:29 Juha Manninen Widgetset GTK 3 => GTK 3
2019-11-12 23:29 Juha Manninen Note Added: 0119244