TxTextSpriteBlock constructor

TxTextSpriteBlock({
  1. required int msgCode,
  2. required int width,
  3. required int fontSize,
  4. required int displayRows,
  5. String? fontFamily,
  6. TextAlign textAlign = ui.TextAlign.left,
  7. TextDirection textDirection = ui.TextDirection.ltr,
  8. required String text,
})

Represents an (optionally) multi-line block of text of a specified width and number of visible rows at a specified lineHeight If the supplied text string is longer, only the last displayRows will be shown rendered and sent to Frame. If the supplied text string has fewer than or equal to displayRows, only the number of actual rows will be rendered and sent to Frame If any given line of text is shorter than width, the text Sprite will be set to the actual width required. When sending TxTextSpriteBlock to Frame, the sendMessage() will send the header with block dimensions and line-by-line offsets and the user then sends each line[] as a TxSprite message with the same msgCode as the Block, and the frame app will use the offsets to place each line. By sending each line separately we can display them as they arrive, as well as reducing overall memory requirement (each concat() call is smaller)

Implementation

TxTextSpriteBlock(
    {required super.msgCode,
    required int width,
    required int fontSize,
    required int displayRows,
    String? fontFamily,
    ui.TextAlign textAlign = ui.TextAlign.left,
    ui.TextDirection textDirection = ui.TextDirection.ltr,
    required String text})
    : _msgCode = msgCode,
      _width = width,
      _fontSize = fontSize {
  final paragraphBuilder = ui.ParagraphBuilder(ui.ParagraphStyle(
    textAlign: textAlign,
    textDirection: textDirection,
    fontFamily: fontFamily, // gets platform default if null
    fontSize: _fontSize.toDouble(), // Adjust font size as needed
  ));

  // trim whitespace around text - in particular, a trailing newline char leads to a final line of text with zero
  // width, which results in a sprite that can't be drawn and caused problems frameside
  // TODO would a double line break have the same issue?
  paragraphBuilder.addText(text.trim());
  final paragraph = paragraphBuilder.build();

  final pictureRecorder = ui.PictureRecorder();
  final canvas = ui.Canvas(pictureRecorder);

  paragraph.layout(ui.ParagraphConstraints(width: width.toDouble()));

  canvas.drawParagraph(paragraph, ui.Offset.zero);
  _picture = pictureRecorder.endRecording();

  // work out height using metrics after paragraph.layout() call
  _lineMetrics = paragraph.computeLineMetrics();

  // take the last `displayRows` lines only
  _displayLineMetrics = _lineMetrics.length - displayRows <= 0 ?
    _lineMetrics :
    _lineMetrics.sublist(_lineMetrics.length - displayRows);

  _totalHeight = (_displayLineMetrics.fold<double>(0, (prev, lm) {
    return prev + lm.height;
  })).toInt();
}