Search code examples
delphifiremonkey

How to draw on a canvas a multi-line text with some words in bold/colored?


How to draw on a canvas, inside a defined Rect, a MULTILINE text with some words in bold/colored? on firemonkey ...

this is not the same question as How to draw text with different font formatting to a canvas in delphi at once? because me i want to draw a multiline text on firemonkey ! a text that break to fit inside a Rect. something like canvas.FillText but with a way to set some word in bold/colored


Solution

  • ok, so finally they was no easy way to achieve this. normally the most easy way (and an acceptable answer) will be to use TTextLayout. TTextlayout is quite performant and support formatting. problem is that it's lack of some other think, like for exemple colored emoticons on android

    so i end up by writing my own function that break the text. this function is too big to be post here but you can saw it https://svn.code.sf.net/p/alcinoe/code/ unit alFmxCommon

    function  ALDrawMultiLineText(const aText: String; // support only theses EXACT html tag :
                                                       //   <b>...</b>
                                                       //   <i>...</i>
                                                       //   <font color="#xxxxxx">...</font>
                                                       //   <span id="xxx">...</span>
                                                       // other < > must be encoded with &lt; and &gt;
                                  var aRect: TRectF; // in => the constraint boundaries in real pixel. out => the calculated rect that contain the html in real pixel
                                  var aTextBreaked: boolean; // true is the text was "breaked" in several lines
                                  var aAscent: single; // out => the Ascent of the last element (in real pixel)
                                  var aDescent: Single; // out => the Descent of the last element (in real pixel)
                                  var aFirstPos: TpointF; // out => the point of the start of the text
                                  var aLastPos: TpointF; // out => the point of the end of the text
                                  var aElements: TalTextElements; // out => the list of rect describing all span elements
                                  var aEllipsisRect: TRectF; // out => the rect of the Ellipsis (if present)
                                  const aOptions: TALDrawMultiLineTextOptions): {$IFDEF _USE_TEXTURE}TTexture{$ELSE}Tbitmap{$ENDIF};
    

    it's absolutely not trivial to break the text in several line and add also formatting to this text and this for all plateform