createSkeletons method

  1. @override
List<Skeleton> createSkeletons(
  1. Element element,
  2. Rect elementRect,
  3. Rect? parentRect
)
override

Implementation

@override
List<Skeleton> createSkeletons(
  Element element,
  Rect elementRect,
  Rect? parentRect,
) {
  final double leftPaddingElement = elementRect.left;
  final double topPaddingElement = elementRect.top;
  final List<Skeleton> textSkeletons = [];
  final TextSpan text = (element.renderObject as dynamic).text as TextSpan;
  double leftPosition = 0;
  double topPosition = 0;
  int lineCounter = 0;
  final Map<int, double> lineAscent = {};
  final Map<int, double> lineDescent = {};
  final Map<int, List<TextRect>> textRows = {};

  void createTextSkeleton(TextSpan iterateText, TextStyle? rootStyle) {
    final bool isIcon = iterateText.style?.fontFamily == "MaterialIcons";
    late final List<ui.LineMetrics>? lines;
    late final TextSpan theText;
    final int hashcode = iterateText.hashCode;
    final cacheData = lineMetricsCache[hashcode];
    if (cacheData != null) {
      lines = cacheData.lines;
      theText = cacheData.textSpan;
    } else {
      if (lineMetricsCache.length > 800) {
        for (int i = 0; i < 500; i++) lineMetricsCache.remove(lineMetricsCache);
      }
      theText = TextSpan(text: iterateText.text, style: iterateText.style);
      final textPainter = TextPainter(
        text: theText,
        textDirection: TextDirection.ltr,
        textAlign: TextAlign.right,
      );
      textPainter.layout();
      final paragraphBuilder = ui.ParagraphBuilder(ui.ParagraphStyle());
      theText.build(paragraphBuilder);
      final paragraph = paragraphBuilder.build();
      paragraph.layout(ui.ParagraphConstraints(
        width: element.size?.width ?? double.infinity,
      ));
      lines = paragraph.computeLineMetrics();
      lineMetricsCache[hashcode] = CachedTextInfo(lines, theText);
    }
    for (final line in lines) {
      int lastLine = 0;

      if (lastLine < line.lineNumber) {
        lineCounter++;
        lastLine++;
      } else if (elementRect.width < leftPosition + line.width) {
        lineCounter++;
      }
      lineDescent[lineCounter] ??= line.descent;
      lineDescent[lineCounter] = max(lineDescent[lineCounter]!, line.descent);
      lineAscent[lineCounter] ??= line.ascent.floorToDouble();
      lineAscent[lineCounter] = max(lineAscent[lineCounter]!, line.ascent.floorToDouble());
      if (line.width == 0 || line.height == 0) continue;
      if (textRows[lineCounter] == null) {
        leftPosition = 0;
        topPosition += lineDescent[lineCounter - 1] ?? 0;
        topPosition += lineAscent[lineCounter - 1] ?? 0;
        textRows[lineCounter] = [];
      }
      textRows[lineCounter]!.add(textRectFromLine(
        line,
        theText.style?.color ?? rootStyle?.color,
        leftPosition,
        topPosition,
        isIcon,
      ));
      leftPosition += line.width;
    }
  }

  void iterateTextSpan(TextSpan theText) {
    for (final child in theText.children ?? <InlineSpan>[]) {
      if (child is TextSpan) {
        if ((child.style?.color ?? theText.style?.color) != null && child.text != null) {
          createTextSkeleton(child, theText.style);
        }
        iterateTextSpan(child);
      }
    }
  }

  createTextSkeleton(text, null);
  iterateTextSpan(text);

  textRows.forEach((key, value) {
    for (final textRect in value) {
      if (lineAscent[key] == null) {
        continue;
      }
      if (textRect.color != null) {
        final Skeleton? skeleton = skeletonFromTextRect(
          textRect,
          leftPaddingElement,
          topPaddingElement,
          elementRect,
          lineAscent[key]!,
          elementRect,
        );
        if (skeleton != null) {
          textSkeletons.add(skeleton);
        }
      }
    }
  });

  return textSkeletons;
}