text method

void text(
  1. String text, {
  2. PrintTextStyle? style,
})

Implementation

void text(String text, {PrintTextStyle? style}) async {
  img.BitmapFont textFont = font;
  PrintAlign align = PrintAlign.left;
  bool arabic = isArabic(text);
  if (arabic) {
    textFont = arabic24;
    // Step 1: Shape the Arabic characters into their presentation forms.
    // The output of ShapeArabic.shape is in logical order (LTR sequence of glyphs).
    text = ShapeArabic.shape(text);
  }

  if (style != null) {
    textFont = _getFont(
      style,
      isArabic: arabic,
    ); // Make sure _getFont returns a font that handles RTL if you use it
    align = style.align;
  }

  // final fontZipFile2 = await rootBundle.load('assets/noto_serif_24.zip').then((byteData) => byteData.buffer.asUint8List());
  // textFont = img.BitmapFont.fromZip(fontZipFile2);

  int maxWidth = paperSize.width - margin.width;

  String currentLine = '';
  List<String> words = text
      .split(' ')
      .where((e) => e.isNotEmpty)
      .toList(); // This assumes space as word delimiter
  for (int i = words.length - 1; i >= 0; i--) {
    // Iterate words in reverse logical order for RTL line breaking
    String word = words[i];
    String testLine = currentLine.isEmpty
        ? word
        : '$word $currentLine'; // Build line from right
    if (textFont.getMetrics(testLine).width <= maxWidth) {
      currentLine = testLine;
    } else {
      break; // Line is full
    }
  }

  // After determining 'currentLine' in logical order (reading from right to left visually)
  // It's crucial that `drawString` correctly handles this logical order for RTL display.

  // Draw the current line
  int xPosition = margin.left;
  if (align == PrintAlign.center) {
    xPosition =
        ((paperSize.width - textFont.getMetrics(currentLine).width) / 2)
            .round();
  } else if (align == PrintAlign.right) {
    // For RTL text aligned right, the text starts at (paperSize.width - text width - margin.right).
    // The current align.right logic for xPosition is correct if getMetrics gives logical width.
    xPosition =
        (paperSize.width -
                textFont.getMetrics(currentLine).width -
                margin.width)
            .round();
  }

  _ensureHeight(runningHeight + textFont.lineHeight + 10);
  drawString(
    utilImage,
    currentLine, // Pass the shaped text in its logical order
    font: textFont,
    x: xPosition,
    y: runningHeight,
    color: textColor,
  );
  runningHeight += textFont.lineHeight + 10;

  // Recursively call the function with the remaining text
  // This part needs to be careful with indexing if you adapted line breaking for RTL.
  // Simplest is to rejoin the words not used and pass them to the recursive call.
  List<String> remainingWords = [];
  int currentLineWordCount = currentLine.split(' ').length;
  for (int i = 0; i < words.length - currentLineWordCount; i++) {
    remainingWords.add(words[i]); // Words that were not put into currentLine
  }
  String remainingText = remainingWords.join(' ');

  if (remainingText.isNotEmpty) {
    // Note: 'this.text' implies a method named 'text' in the same class.
    // If 'this.text' means the original 'void text(String text, ...)'
    // then it will re-shape the text, which is redundant.
    // Ensure the recursive call doesn't re-shape already shaped text.
    // You might need a `textArabicShaped(String shapedText, ...)` for recursion.
    // For now, assuming you want to re-shape, which is inefficient but functionally ok if `text`
    // doesn't call shape again.
    this.text(remainingText, style: style);
  }
}