TextDirection determinePlaintextDirectionality(LineLayoutItem root, LineLayoutItem current, unsigned pos) { LineLayoutItem firstLayoutObject = firstLayoutObjectForDirectionalityDetermination(root, current); InlineIterator iter(LineLayoutItem(root), firstLayoutObject, firstLayoutObject == current ? pos : 0); InlineBidiResolver observer; observer.setStatus(BidiStatus(root.style()->direction(), isOverride(root.style()->unicodeBidi()))); observer.setPositionIgnoringNestedIsolates(iter); return observer.determineParagraphDirectionality(); }
// static TextPainter::Style TextPainter::textPaintingStyle(LineLayoutItem lineLayoutItem, const ComputedStyle& style, const PaintInfo& paintInfo) { TextPainter::Style textStyle; bool isPrinting = paintInfo.isPrinting(); if (paintInfo.phase == PaintPhaseTextClip) { // 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 = lineLayoutItem.resolveColor(style, CSSPropertyWebkitTextFillColor); textStyle.strokeColor = lineLayoutItem.resolveColor(style, CSSPropertyWebkitTextStrokeColor); textStyle.emphasisMarkColor = lineLayoutItem.resolveColor(style, CSSPropertyWebkitTextEmphasisColor); textStyle.strokeWidth = style.textStrokeWidth(); textStyle.shadow = style.textShadow(); // Adjust text color when printing with a white background. ASSERT(lineLayoutItem.document().printing() == isPrinting); bool forceBackgroundToWhite = BoxPainter::shouldForceWhiteBackgroundForPrintEconomy( style, lineLayoutItem.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 LineBreaker::skipLeadingWhitespace(InlineBidiResolver& resolver, LineInfo& lineInfo, LineWidth& width) { while (!resolver.position().atEnd() && !requiresLineBox(resolver.position(), lineInfo, LeadingWhitespace)) { LineLayoutItem lineLayoutItem = resolver.position().getLineLayoutItem(); if (lineLayoutItem.isOutOfFlowPositioned()) { setStaticPositions(m_block, LineLayoutBox(lineLayoutItem), width.indentText()); if (lineLayoutItem.style()->isOriginalDisplayInlineType()) { resolver.runs().addRun(createRun(0, 1, LineLayoutItem(lineLayoutItem), resolver)); lineInfo.incrementRunsFromLeadingWhitespace(); } } else if (lineLayoutItem.isFloating()) { m_block.insertFloatingObject(LineLayoutBox(lineLayoutItem)); m_block.positionNewFloats(&width); } resolver.position().increment(&resolver); } resolver.commitExplicitEmbedding(resolver.runs()); }
static inline void setupResolverToResumeInIsolate(InlineBidiResolver& resolver, LineLayoutItem root, LineLayoutItem startObject) { if (root != startObject) { LineLayoutItem parent = startObject.parent(); setupResolverToResumeInIsolate(resolver, root, parent); notifyObserverEnteredObject(&resolver, LineLayoutItem(startObject)); } }
int CharacterNumberAtPositionData::characterNumberWithin(const LayoutObject* queryRoot) const { // http://www.w3.org/TR/SVG/single-page.html#text-__svg__SVGTextContentElement__getCharNumAtPosition // "If no such character exists, a value of -1 is returned." if (!hitLayoutItem) return -1; ASSERT(queryRoot); int characterNumber = offsetInTextNode; // Accumulate the lengths of all the text nodes preceding the target layout // object within the queried root, to get the complete character number. for (LineLayoutItem layoutItem = hitLayoutItem.previousInPreOrder(queryRoot); layoutItem; layoutItem = layoutItem.previousInPreOrder(queryRoot)) { if (!layoutItem.isSVGInlineText()) continue; characterNumber += LineLayoutSVGInlineText(layoutItem).resolvedTextLength(); } return characterNumber; }
void LineBoxList::dirtyLinesFromChangedChild(LineLayoutItem container, LineLayoutItem child) { if (!container.parent() || (container.isLayoutBlock() && (container.selfNeedsLayout() || !container.isLayoutBlockFlow()))) return; LineLayoutInline inlineContainer = container.isLayoutInline() ? LineLayoutInline(container) : LineLayoutInline(); InlineBox* firstBox = inlineContainer ? inlineContainer.firstLineBoxIncludingCulling() : firstLineBox(); // If we have no first line box, then just bail early. if (!firstBox) { // For an empty inline, go ahead and propagate the check up to our parent, unless the parent // is already dirty. if (container.isInline() && !container.ancestorLineBoxDirty()) { container.parent().dirtyLinesFromChangedChild(container); container.setAncestorLineBoxDirty(); // Mark the container to avoid dirtying the same lines again across multiple destroy() calls of the same subtree. } return; } // Try to figure out which line box we belong in. First try to find a previous // line box by examining our siblings. If we didn't find a line box, then use our // parent's first line box. RootInlineBox* box = nullptr; LineLayoutItem curr = nullptr; for (curr = child.previousSibling(); curr; curr = curr.previousSibling()) { if (curr.isFloatingOrOutOfFlowPositioned()) continue; if (curr.isAtomicInlineLevel()) { InlineBox* wrapper = toLayoutBox(curr)->inlineBoxWrapper(); if (wrapper) box = &wrapper->root(); } else if (curr.isText()) { InlineTextBox* textBox = toLayoutText(curr)->lastTextBox(); if (textBox) box = &textBox->root(); } else if (curr.isLayoutInline()) { InlineBox* lastSiblingBox = toLayoutInline(curr)->lastLineBoxIncludingCulling(); if (lastSiblingBox) box = &lastSiblingBox->root(); } if (box) break; } if (!box) { if (inlineContainer && !inlineContainer.alwaysCreateLineBoxes()) { // https://bugs.webkit.org/show_bug.cgi?id=60778 // We may have just removed a <br> with no line box that was our first child. In this case // we won't find a previous sibling, but firstBox can be pointing to a following sibling. // This isn't good enough, since we won't locate the root line box that encloses the removed // <br>. We have to just over-invalidate a bit and go up to our parent. if (!inlineContainer.ancestorLineBoxDirty()) { inlineContainer.parent().dirtyLinesFromChangedChild(inlineContainer); inlineContainer.setAncestorLineBoxDirty(); // Mark the container to avoid dirtying the same lines again across multiple destroy() calls of the same subtree. } return; } box = &firstBox->root(); } // If we found a line box, then dirty it. if (box) { box->markDirty(); // dirty the adjacent lines that might be affected // NOTE: we dirty the previous line because RootInlineBox objects cache // the address of the first object on the next line after a BR, which we may be // invalidating here. For more info, see how LayoutBlock::layoutInlineChildren // calls setLineBreakInfo with the result of findNextLineBreak. findNextLineBreak, // despite the name, actually returns the first LayoutObject after the BR. // <rdar://problem/3849947> "Typing after pasting line does not appear until after window resize." if (RootInlineBox* prevRootBox = box->prevRootBox()) prevRootBox->markDirty(); // If |child| or any of its immediately previous siblings with culled lineboxes is the object after a line-break in |box| or the linebox after it // then that means |child| actually sits on the linebox after |box| (or is its line-break object) and so we need to dirty it as well. if (RootInlineBox* nextRootBox = box->nextRootBox()) nextRootBox->markDirty(); } }