Przeglądaj źródła

* Some helper methods

Michaël Van Canneyt 1 rok temu
rodzic
commit
d4360a3184
2 zmienionych plików z 160 dodań i 8 usunięć
  1. 155 7
      src/base/fresnel.textlayouter.pas
  2. 5 1
      tests/base/tctextlayout.pas

+ 155 - 7
src/base/fresnel.textlayouter.pas

@@ -76,7 +76,7 @@ Type
   end;
   TTextPoint = {$IFDEF FPC_DOTTEDUNITS}System.{$ENDIF}Types.TPointF;
 
-  TFontAttribute = (faBold,faItalic,faStrikeThrough);
+  TFontAttribute = (faBold,faItalic,faUnderline,faStrikeOut);
   TFontAttributes = set of TFontAttribute;
 
   { TTextFont }
@@ -148,7 +148,7 @@ Type
     // Font size in points.
     Procedure SetFont(const aFontName : String; aSize : SmallInt; Attrs : TFontAttributes); virtual; abstract;
     Procedure SetFont(const aFont: TTextFont);
-    Function MeasureText(aText : String) : TTextMeasures; virtual; abstract;
+    Function MeasureText(aText : TTextString) : TTextMeasures; virtual; abstract;
     Function WhitespaceWidth : TTextUnits;
     Property Layouter : TTextLayouter Read FLayouter;
 
@@ -167,7 +167,7 @@ Type
   Public
     Constructor Create(aLayouter : TTextLayouter); override;
     Procedure SetFont(const aFontName : String; aSize : SmallInt; aAttrs : TFontAttributes); override;
-    Function MeasureText(aText : String) : TTextMeasures; override;
+    Function MeasureText(aText : TTextString) : TTextMeasures; override;
     Property CharHeight : TTextUnits Read FHeight Write FHeight;
     Property CharWidth : TTextUnits Read FWidth Write FWidth;
     Property Size : SmallInt Read FSize;
@@ -255,7 +255,7 @@ Type
     function GetRange(aIndex : integer): TTextRange;
     procedure SetRange(aIndex : integer; AValue: TTextRange);
   Public
-    Function AddRange(aOffset,aCharlength : SizeInt; aFont : TTextFont) : TTextRange;
+    Function AddRange(aOffset,aCharlength : SizeInt; aFont : TTextFont = Nil) : TTextRange;
     Property Ranges[aIndex : integer] : TTextRange Read GetRange Write SetRange; default;
   end;
 
@@ -369,6 +369,14 @@ Type
     Property TextBlockCount : Integer Read GetBlockCount;
     function Execute : integer; virtual;
     function Execute(const aText : String) : Integer;
+    Function GetTotalWidth : TTextUnits;
+    Function GetTotalHeight : TTextUnits;
+    Function GetMinLeft : TTextUnits;
+    Function GetMaxRight : TTextUnits;
+    Function GetMinTop : TTextUnits;
+    Function GetMaxBottom : TTextUnits;
+    Function GetTotalSize : TSizeF;
+    Function GetBoundsRect : TRectF;
     // Color of font
     Property FPColor : TFPColor Read GetColor Write SetColor;
   Published
@@ -599,7 +607,8 @@ begin
   Result:=add as TTextRange;
   Result.CharOffset:=aOffset;
   Result.CharLength:=aCharlength;
-  Result.Font:=aFont;
+  if assigned(aFont) then
+    Result.Font:=aFont;
 end;
 
 { TTextLayoutBounds }
@@ -804,7 +813,7 @@ begin
   FAttrs:=aAttrs;
 end;
 
-function TFixedSizeTextMeasurer.MeasureText(aText: String): TTextMeasures;
+function TFixedSizeTextMeasurer.MeasureText(aText: TTextString): TTextMeasures;
 
 var
   Scale: TTextUnits;
@@ -1444,6 +1453,145 @@ begin
   Result:=Execute;
 end;
 
+function TTextLayouter.GetTotalWidth: TTextUnits;
+
+var
+  X,Xmin,xMax : TTextUnits;
+  B : TTextBlock;
+  i : Integer;
+
+begin
+  if TextBlockCount=0 then
+    exit(0.0);
+  xMin:=Bounds.Width;
+  xMax:=0;
+  For I:=0 to TextBlockCount-1 do
+    begin
+    B:=TextBlocks[i];
+    X:=B.LayoutPos.X;
+    if X<xMin then
+      xMin:=X;
+    if X+B.Width>xMax then
+      xMax:=X+B.Width;
+    end;
+  Result:=xMax-xMin;
+end;
+
+function TTextLayouter.GetTotalHeight: TTextUnits;
+
+var
+  Y,Ymin,YMax : TTextUnits;
+  B : TTextBlock;
+  i : Integer;
+
+begin
+  if TextBlockCount=0 then
+    exit(0.0);
+  yMin:=Bounds.Height;
+  yMax:=0;
+  For I:=0 to TextBlockCount-1 do
+    begin
+    B:=TextBlocks[i];
+    y:=B.LayoutPos.y;
+    if Y<YMin then
+      yMin:=Y;
+    if Y+B.Height>yMax then
+      yMax:=Y+B.Height;
+    end;
+  Result:=yMax-yMin;
+end;
+
+function TTextLayouter.GetMinLeft: TTextUnits;
+var
+  X,Xmin : TTextUnits;
+  B : TTextBlock;
+  i : Integer;
+
+begin
+  if TextBlockCount=0 then
+    exit(0.0);
+  xMin:=Bounds.Width;
+  For I:=0 to TextBlockCount-1 do
+    begin
+    B:=TextBlocks[i];
+    X:=B.LayoutPos.X;
+    if X<xMin then
+      xMin:=X;
+    end;
+  Result:=xMin;
+end;
+
+function TTextLayouter.GetMaxRight: TTextUnits;
+var
+  X,xMax : TTextUnits;
+  B : TTextBlock;
+  i : Integer;
+
+begin
+  if TextBlockCount=0 then
+    exit(0.0);
+  xMax:=0;
+  For I:=0 to TextBlockCount-1 do
+    begin
+    B:=TextBlocks[i];
+    X:=B.LayoutPos.X;
+    if X+B.Width>xMax then
+      xMax:=X+B.Width;
+    end;
+  Result:=xMax;
+end;
+
+function TTextLayouter.GetMinTop: TTextUnits;
+
+var
+  Y,Ymin : TTextUnits;
+  B : TTextBlock;
+  i : Integer;
+
+begin
+  if TextBlockCount=0 then
+    exit(0.0);
+  yMin:=Bounds.Height;
+  For I:=0 to TextBlockCount-1 do
+    begin
+    B:=TextBlocks[i];
+    y:=B.LayoutPos.y;
+    if Y<YMin then
+      yMin:=Y;
+    end;
+  Result:=yMin;
+end;
+
+function TTextLayouter.GetMaxBottom: TTextUnits;
+var
+  Y,YMax : TTextUnits;
+  B : TTextBlock;
+  i : Integer;
+
+begin
+  if TextBlockCount=0 then
+    exit(0.0);
+  yMax:=0;
+  For I:=0 to TextBlockCount-1 do
+    begin
+    B:=TextBlocks[i];
+    y:=B.LayoutPos.y;
+    if Y+B.Height>yMax then
+      yMax:=Y+B.Height;
+    end;
+  Result:=yMax;
+end;
+
+function TTextLayouter.GetTotalSize: TSizeF;
+begin
+  Result:=TSizeF.Create(GetTotalWidth,GetTotalHeight);
+end;
+
+function TTextLayouter.GetBoundsRect: TRectF;
+begin
+  Result:=TRectF.Create(GetMinLeft,GetMinTop,GetMaxRight,GetMaxBottom);
+end;
+
 procedure TTextLayouter.ApplyStretchMode(const ADesiredHeight: TTextUnits);
 
 begin
@@ -1561,7 +1709,7 @@ begin
     TWordOverflow.woEllipsis:
       begin
       {$IF SIZEOF(CHAR)=2}
-      P:=FindLastFittingCharPos(B,cEllipsis);
+      P:=FindLastFittingCharPos(B,cEllipsis,Width);
       Suff:=cEllipsis;
       {$ELSE}
       P:=FindLastFittingCharPos(B,UTF8Encode(cEllipsis),Width);

+ 5 - 1
tests/base/tctextlayout.pas

@@ -470,6 +470,8 @@ begin
   Layouter.Bounds.Height:=cHeight*1.1;
   AssertEquals('block count',1,Layouter.Execute);
   AssertBlock('Block',0,Layouter.Text,0,0,MyWidth,MyHeight);
+  AssertEquals('TotalWidth',MyWidth,Layouter.GetTotalWidth);
+  AssertEquals('TotalHeight',MyHeight,Layouter.GetTotalHeight);
 end;
 
 procedure TTestTextLayouter.TestSimpleMultiLineText;
@@ -495,7 +497,9 @@ begin
   // Second block
   MyWidth:=Length(cLine2)*cWidth;
   AssertBlock('Block',1,cLine2,0,cHeight+cLineSpacing,MyWidth,MyHeight,True);
-
+  // Second block is larger
+  AssertEquals('TotalWidth',MyWidth,Layouter.GetTotalWidth);
+  AssertEquals('TotalHeight',MyHeight*2+cLineSpacing,Layouter.GetTotalHeight);
 end;
 
 procedure TTestTextLayouter.TestSimpleMultiLineTextCRLF;