void FirstLetterPseudoElement::attachFirstLetterTextLayoutObjects()
{
    LayoutObject* nextLayoutObject = FirstLetterPseudoElement::firstLetterTextLayoutObject(*this);
    ASSERT(nextLayoutObject);
    ASSERT(nextLayoutObject->isText());

    // The original string is going to be either a generated content string or a DOM node's
    // string. We want the original string before it got transformed in case first-letter has
    // no text-transform or a different text-transform applied to it.
    String oldText = toLayoutText(nextLayoutObject)->isTextFragment() ? toLayoutTextFragment(nextLayoutObject)->completeText() : toLayoutText(nextLayoutObject)->originalText();
    ASSERT(oldText.impl());

    ComputedStyle* pseudoStyle = styleForFirstLetter(nextLayoutObject->parent());
    layoutObject()->setStyle(pseudoStyle);

    // FIXME: This would already have been calculated in firstLetterLayoutObject. Can we pass the length through?
    unsigned length = FirstLetterPseudoElement::firstLetterLength(oldText);

    // Construct a text fragment for the text after the first letter.
    // This text fragment might be empty.
    LayoutTextFragment* remainingText =
        new LayoutTextFragment(nextLayoutObject->node() ? nextLayoutObject->node() : &nextLayoutObject->document(), oldText.impl(), length, oldText.length() - length);
    remainingText->setFirstLetterPseudoElement(this);
    remainingText->setIsRemainingTextLayoutObject(true);
    remainingText->setStyle(nextLayoutObject->mutableStyle());

    if (remainingText->node())
        remainingText->node()->setLayoutObject(remainingText);

    m_remainingTextLayoutObject = remainingText;

    LayoutObject* nextSibling = layoutObject()->nextSibling();
    layoutObject()->parent()->addChild(remainingText, nextSibling);

    // Construct text fragment for the first letter.
    LayoutTextFragment* letter = new LayoutTextFragment(&nextLayoutObject->document(), oldText.impl(), 0, length);
    letter->setFirstLetterPseudoElement(this);
    letter->setStyle(pseudoStyle);
    layoutObject()->addChild(letter);

    nextLayoutObject->destroy();
}
void PaintPropertyTreeBuilder::updateMainThreadScrollingReasons(
    const LayoutObject& object,
    PaintPropertyTreeBuilderContext& context) {
  if (context.current.scroll &&
      !object.document().settings()->threadedScrollingEnabled())
    context.current.scroll->addMainThreadScrollingReasons(
        MainThreadScrollingReason::kThreadedScrollingDisabled);

  if (object.isBackgroundAttachmentFixedObject()) {
    auto* scrollNode = context.current.scroll;
    while (
        scrollNode &&
        !scrollNode->hasMainThreadScrollingReasons(
            MainThreadScrollingReason::kHasBackgroundAttachmentFixedObjects)) {
      scrollNode->addMainThreadScrollingReasons(
          MainThreadScrollingReason::kHasBackgroundAttachmentFixedObjects);
      scrollNode = scrollNode->parent();
    }
  }
}
// static
TextPainter::Style TextPainter::textPaintingStyle(LayoutObject& layoutObject, const ComputedStyle& style, bool usesTextAsClip, bool isPrinting)
{
    TextPainter::Style textStyle;

    if (usesTextAsClip) {
        // When we use the text as a clip, we only care about the alpha, thus we make all the colors black.
        textStyle.currentColor = Color::black;
        textStyle.fillColor = Color::black;
        textStyle.strokeColor = Color::black;
        textStyle.emphasisMarkColor = Color::black;
        textStyle.strokeWidth = style.textStrokeWidth();
        textStyle.shadow = 0;
    } else {
        textStyle.currentColor = style.visitedDependentColor(CSSPropertyColor);
        textStyle.fillColor = layoutObject.resolveColor(style, CSSPropertyWebkitTextFillColor);
        textStyle.strokeColor = layoutObject.resolveColor(style, CSSPropertyWebkitTextStrokeColor);
        textStyle.emphasisMarkColor = layoutObject.resolveColor(style, CSSPropertyWebkitTextEmphasisColor);
        textStyle.strokeWidth = style.textStrokeWidth();
        textStyle.shadow = style.textShadow();

        // Adjust text color when printing with a white background.
        ASSERT(layoutObject.document().printing() == isPrinting);
        bool forceBackgroundToWhite = BoxPainter::shouldForceWhiteBackgroundForPrintEconomy(style, layoutObject.document());
        if (forceBackgroundToWhite) {
            textStyle.fillColor = textColorForWhiteBackground(textStyle.fillColor);
            textStyle.strokeColor = textColorForWhiteBackground(textStyle.strokeColor);
            textStyle.emphasisMarkColor = textColorForWhiteBackground(textStyle.emphasisMarkColor);
        }

        // Text shadows are disabled when printing. http://crbug.com/258321
        if (isPrinting)
            textStyle.shadow = 0;
    }

    return textStyle;
}
void writeResources(TextStream& ts, const LayoutObject& object, int indent)
{
    const ComputedStyle& style = object.styleRef();
    const SVGComputedStyle& svgStyle = style.svgStyle();

    // FIXME: We want to use SVGResourcesCache to determine which resources are present, instead of quering the resource <-> id cache.
    // For now leave the DRT output as is, but later on we should change this so cycles are properly ignored in the DRT output.
    LayoutObject& layoutObject = const_cast<LayoutObject&>(object);
    if (!svgStyle.maskerResource().isEmpty()) {
        if (LayoutSVGResourceMasker* masker = getLayoutSVGResourceById<LayoutSVGResourceMasker>(object.document(), svgStyle.maskerResource())) {
            writeIndent(ts, indent);
            ts << " ";
            writeNameAndQuotedValue(ts, "masker", svgStyle.maskerResource());
            ts << " ";
            writeStandardPrefix(ts, *masker, 0);
            ts << " " << masker->resourceBoundingBox(&layoutObject) << "\n";
        }
    }
    if (!svgStyle.clipperResource().isEmpty()) {
        if (LayoutSVGResourceClipper* clipper = getLayoutSVGResourceById<LayoutSVGResourceClipper>(object.document(), svgStyle.clipperResource())) {
            writeIndent(ts, indent);
            ts << " ";
            writeNameAndQuotedValue(ts, "clipPath", svgStyle.clipperResource());
            ts << " ";
            writeStandardPrefix(ts, *clipper, 0);
            ts << " " << clipper->resourceBoundingBox(&layoutObject) << "\n";
        }
    }
    if (!svgStyle.filterResource().isEmpty()) {
        if (LayoutSVGResourceFilter* filter = getLayoutSVGResourceById<LayoutSVGResourceFilter>(object.document(), svgStyle.filterResource())) {
            writeIndent(ts, indent);
            ts << " ";
            writeNameAndQuotedValue(ts, "filter", svgStyle.filterResource());
            ts << " ";
            writeStandardPrefix(ts, *filter, 0);
            ts << " " << filter->resourceBoundingBox(&layoutObject) << "\n";
        }
    }
}