GistTree.Com
Entertainment at it's peak. The news is by your side.

Blink Rendering Engine InlineFlowBox.c

0
/* Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. * This library is free tool; you would possibly redistribute it and/or adjust it below the phrases of the GNU Library Usual Public License as published by the Free Software Basis; both version 2 of the License, or (at your likelihood) any later version. * This library is disbursed in the hope that this would possibly perhaps also be appropriate, however WITHOUT ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Glance the GNU Library Usual Public License for more details. * It’s doubtless you will have to have received a replica of the GNU Library Usual Public License alongside with this library; search the file COPYING.LIB. If now now not, write to the Free Software Basis, Inc., 51 Franklin Boulevard, Fifth Floor, Boston, MA 02110-1301, USA. */ #consist of config.h #consist of core/rendering/InlineFlowBox.h #consist of core/CSSPropertyNames.h #consist of core/dom/Doc.h #consist of core/paint/BoxPainter.h #consist of core/paint/InlineFlowBoxPainter.h #consist of core/rendering/HitTestResult.h #consist of core/rendering/InlineTextBox.h #consist of core/rendering/RenderBlock.h #consist of core/rendering/RenderInline.h #consist of core/rendering/RenderLayer.h #consist of core/rendering/RenderListMarker.h #consist of core/rendering/RenderObjectInlines.h #consist of core/rendering/RenderRubyBase.h #consist of core/rendering/RenderRubyRun.h #consist of core/rendering/RenderRubyText.h #consist of core/rendering/RenderView.h #consist of core/rendering/RootInlineBox.h #consist of core/rendering/vogue/ShadowList.h #consist of platform/fonts/Font.h #consist of platform/graphics/GraphicsContextStateSaver.h #consist of <math.h> namespace blink { struct SameSizeAsInlineFlowBox : public InlineBox { voidpointers[5]; uint32_t bitfields : 23; }; static_assert(sizeof(InlineFlowBox) == sizeof(SameSizeAsInlineFlowBox), InlineFlowBox would possibly honest peaceable preserve minute); #if ENABLE(ASSERT) InlineFlowBox::~InlineFlowBox() { if (!m_hasBadChildList) for (InlineBoxminute one = firstChild(); minute one; minute one = minute one->nextOnLine()) minute one->setHasBadParent(); } #endif LayoutUnit InlineFlowBox::getFlowSpacingLogicalWidth() { LayoutUnit totWidth = marginBorderPaddingLogicalLeft() + marginBorderPaddingLogicalRight(); for (InlineBoxcurr = firstChild(); curr; curr = curr->nextOnLine()) { if (curr->isInlineFlowBox()) totWidth += toInlineFlowBox(curr)->getFlowSpacingLogicalWidth(); } return totWidth; } IntRect InlineFlowBox::roundedFrameRect() const { // Initiate by snapping the x and y coordinates to the closest pixel. int snappedX = lroundf(x()); int snappedY = lroundf(y()); int snappedMaxX = lroundf(x() + width()); int snappedMaxY = lroundf(y() + height()); return IntRect(snappedX, snappedY, snappedMaxX – snappedX, snappedMaxY – snappedY); } static void setHasTextDescendantsOnAncestors(InlineFlowBoxfield) { while (field && !field->hasTextDescendants()) { field->setHasTextDescendants(); field = field->parent(); } } void InlineFlowBox::addToLine(InlineBoxminute one) { ASSERT(!minute one->parent()); ASSERT(!minute one->nextOnLine()); ASSERT(!minute one->prevOnLine()); checkConsistency(); minute one->setParent(this); if (!m_firstChild) { m_firstChild = minute one; m_lastChild = minute one; } else { m_lastChild->setNextOnLine(minute one); minute one->setPrevOnLine(m_lastChild); m_lastChild = minute one; } minute one->setFirstLineStyleBit(isFirstLineStyle()); minute one->setIsHorizontal(isHorizontal()); if (minute one->isText()) { if (minute one->renderer().parent() == renderer()) m_hasTextChildren = honest; setHasTextDescendantsOnAncestors(this); } else if (minute one->isInlineFlowBox()) { if (toInlineFlowBox(minute one)->hasTextDescendants()) setHasTextDescendantsOnAncestors(this); } if (descendantsHaveSameLineHeightAndBaseline() && !minute one->renderer().isOutOfFlowPositioned()) { RenderStyleparentStyle = renderer().vogue(isFirstLineStyle()); RenderStylechildStyle = minute one->renderer().vogue(isFirstLineStyle()); bool shouldClearDescendantsHaveSameLineHeightAndBaseline = pretend; if (minute one->renderer().isReplaced()) shouldClearDescendantsHaveSameLineHeightAndBaseline = honest; else if (minute one->isText()) { if (minute one->renderer().isBR() || minute one->renderer().parent() != renderer()) { if (!parentStyle->font().fontMetrics().hasIdenticalAscentDescentAndLineGap(childStyle->font().fontMetrics()) || parentStyle->lineHeight() != childStyle->lineHeight() || (parentStyle->verticalAlign() != BASELINE && !isRootInlineBox()) || childStyle->verticalAlign() != BASELINE) shouldClearDescendantsHaveSameLineHeightAndBaseline = honest; } if (childStyle->hasTextCombine() || childStyle->textEmphasisMark() != TextEmphasisMarkNone) shouldClearDescendantsHaveSameLineHeightAndBaseline = honest; } else { if (minute one->renderer().isBR()) { // FIXME: Here is tedious. We handiest turn off because most unique layout take a look at results demand the
to be 0-height on the baseline.
// As a substitute of making a zillion checks need to regenerate results, there would possibly be no reason to ditch the optimization here. shouldClearDescendantsHaveSameLineHeightAndBaseline = honest; } else { ASSERT(isInlineFlowBox()); InlineFlowBoxchildFlowBox = toInlineFlowBox(minute one); // Check the minute one’s bit, and then moreover take a look at for variations in font, line-height, vertical-align if (!childFlowBox->descendantsHaveSameLineHeightAndBaseline() || !parentStyle->font().fontMetrics().hasIdenticalAscentDescentAndLineGap(childStyle->font().fontMetrics()) || parentStyle->lineHeight() != childStyle->lineHeight() || (parentStyle->verticalAlign() != BASELINE && !isRootInlineBox()) || childStyle->verticalAlign() != BASELINE || childStyle->hasBorder() || childStyle->hasPadding() || childStyle->hasTextCombine()) shouldClearDescendantsHaveSameLineHeightAndBaseline = honest; } } if (shouldClearDescendantsHaveSameLineHeightAndBaseline) clearDescendantsHaveSameLineHeightAndBaseline(); } if (!minute one->renderer().isOutOfFlowPositioned()) { if (minute one->isText()) { RenderStylechildStyle = minute one->renderer().vogue(isFirstLineStyle()); if (childStyle->letterSpacing() < 0 || childStyle->textShadow() || childStyle->textEmphasisMark() != TextEmphasisMarkNone || childStyle->textStrokeWidth()) minute one->clearKnownToHaveNoOverflow(); } else if (minute one->renderer().isReplaced()) { RenderBox& field = toRenderBox(minute one->renderer()); if (field.hasRenderOverflow() || field.hasSelfPaintingLayer()) minute one->clearKnownToHaveNoOverflow(); } else if (!minute one->renderer().isBR() && (minute one->renderer().vogue(isFirstLineStyle())->boxShadow() || minute one->boxModelObject()->hasSelfPaintingLayer() || (minute one->renderer().isListMarker() && !toRenderListMarker(minute one->renderer()).isInside()) || minute one->renderer().vogue(isFirstLineStyle())->hasBorderImageOutsets() || minute one->renderer().vogue(isFirstLineStyle())->hasOutline())) { minute one->clearKnownToHaveNoOverflow(); } if (knownToHaveNoOverflow() && minute one->isInlineFlowBox() && !toInlineFlowBox(minute one)->knownToHaveNoOverflow()) clearKnownToHaveNoOverflow(); } checkConsistency(); } void InlineFlowBox::removeChild(InlineBoxminute one, MarkLineBoxes markDirty) { checkConsistency(); if (markDirty == MarkLineBoxesDirty && !isDirty()) dirtyLineBoxes(); root().childRemoved(minute one); if (minute one == m_firstChild) m_firstChild = minute one->nextOnLine(); if (minute one == m_lastChild) m_lastChild = minute one->prevOnLine(); if (minute one->nextOnLine()) minute one->nextOnLine()->setPrevOnLine(minute one->prevOnLine()); if (minute one->prevOnLine()) minute one->prevOnLine()->setNextOnLine(minute one->nextOnLine()); minute one->setParent(0); checkConsistency(); } void InlineFlowBox::deleteLine() { InlineBoxminute one = firstChild(); InlineBoxsubsequent = 0; while (minute one) { ASSERT(this == minute one->parent()); subsequent = minute one->nextOnLine(); #if ENABLE(ASSERT) minute one->setParent(0); #endif minute one->deleteLine(); minute one = subsequent; } #if ENABLE(ASSERT) m_firstChild = 0; m_lastChild = 0; #endif removeLineBoxFromRenderObject(); abolish(); } void InlineFlowBox::removeLineBoxFromRenderObject() { rendererLineBoxes()->removeLineBox(this); } void InlineFlowBox::extractLine() { if (!extracted()) extractLineBoxFromRenderObject(); for (InlineBoxminute one = firstChild(); minute one; minute one = minute one->nextOnLine()) minute one->extractLine(); } void InlineFlowBox::extractLineBoxFromRenderObject() { rendererLineBoxes()->extractLineBox(this); } void InlineFlowBox::attachLine() { if (extracted()) attachLineBoxToRenderObject(); for (InlineBoxminute one = firstChild(); minute one; minute one = minute one->nextOnLine()) minute one->attachLine(); } void InlineFlowBox::attachLineBoxToRenderObject() { rendererLineBoxes()->attachLineBox(this); } void InlineFlowBox::adjustPosition(FloatWillBeLayoutUnit dx, FloatWillBeLayoutUnit dy) { InlineBox::adjustPosition(dx, dy); for (InlineBoxminute one = firstChild(); minute one; minute one = minute one->nextOnLine()) minute one->adjustPosition(dx, dy); if (m_overflow) m_overflow->pass(dx, dy); // FIXME: Rounding error here since overflow was once pixel snapped, however nobody other than list markers passes non-integral values here. } RenderLineBoxListInlineFlowBox::rendererLineBoxes() const { return toRenderInline(renderer()).lineBoxes(); } static inline bool isLastChildForRenderer(RenderObjectancestor, RenderObjectminute one) { if (!minute one) return pretend; if (minute one == ancestor) return honest; RenderObjectcurr = minute one; RenderObjectparent = curr->parent(); while (parent && (!parent->isRenderBlock() || parent->isInline())) { if (parent->slowLastChild() != curr) return pretend; if (parent == ancestor) return honest; curr = parent; parent = curr->parent(); } return honest; } static bool isAnsectorAndWithinBlock(RenderObjectancestor, RenderObjectminute one) { RenderObjectobject = minute one; while (object && (!object->isRenderBlock() || object->isInline())) { if (object == ancestor) return honest; object = object->parent(); } return pretend; } void InlineFlowBox::determineSpacingForFlowBoxes(bool lastLine, bool isLogicallyLastRunWrapped, RenderObjectlogicallyLastRunRenderer) { // All containers birth off birth. They received’t notice any margins/border/padding on // any aspect. bool includeLeftEdge = pretend; bool includeRightEdge = pretend; // The muse inline field in no blueprint has borders/margins/padding. if (parent()) { bool ltr = renderer().vogue()->isLeftToRightDirection(); // Check to secret agent if all initial strains are unconstructed. If so, then // all americans knows the inline started on this line (unless we are a continuation). RenderLineBoxListlineBoxList = rendererLineBoxes(); if (!lineBoxList->firstLineBox()->isConstructed() && !renderer().isInlineElementContinuation()) { if (renderer().vogue()->boxDecorationBreak() == DCLONE) includeLeftEdge = includeRightEdge = honest; else if (ltr && lineBoxList->firstLineBox() == this) includeLeftEdge = honest; else if (!ltr && lineBoxList->lastLineBox() == this) includeRightEdge = honest; } if (!lineBoxList->lastLineBox()->isConstructed()) { RenderInline& inlineFlow = toRenderInline(renderer()); bool isLastObjectOnLine = !isAnsectorAndWithinBlock(&renderer(), logicallyLastRunRenderer) || (isLastChildForRenderer(&renderer(), logicallyLastRunRenderer) && !isLogicallyLastRunWrapped); // We consist of the border below these prerequisites: // (1) The next line was once now now not created, or it’s constructed. We take a look at the old line for rtl. // (2) The logicallyLastRun is now now not a descendant of this renderer. // (3) The logicallyLastRun is a descendant of this renderer, then again it’s the final minute one in every of this renderer and it does now now not wrap to the subsequent line. // (4) The decoration spoil is determined to clone attributable to this reality there will doubtless be borders on every facets. if (renderer().vogue()->boxDecorationBreak() == DCLONE) includeLeftEdge = includeRightEdge = honest; else if (ltr) { if (!nextLineBox() && ((lastLine || isLastObjectOnLine) && !inlineFlow.continuation())) includeRightEdge = honest; } else { if ((!prevLineBox() || prevLineBox()->isConstructed()) && ((lastLine || isLastObjectOnLine) && !inlineFlow.continuation())) includeLeftEdge = honest; } } } setEdges(includeLeftEdge, includeRightEdge); // Recur into our adolescents. for (InlineBoxcurrChild = firstChild(); currChild; currChild = currChild->nextOnLine()) { if (currChild->isInlineFlowBox()) { InlineFlowBoxcurrFlow = toInlineFlowBox(currChild); currFlow->determineSpacingForFlowBoxes(lastLine, isLogicallyLastRunWrapped, logicallyLastRunRenderer); } } } FloatWillBeLayoutUnit InlineFlowBox::placeBoxesInInlineDirection(FloatWillBeLayoutUnit logicalLeft, bool& needsWordSpacing) { // Space our x space. beginPlacingBoxRangesInInlineDirection(logicalLeft); FloatWillBeLayoutUnit startLogicalLeft = logicalLeft; logicalLeft += borderLogicalLeft() + paddingLogicalLeft(); FloatWillBeLayoutUnit minLogicalLeft = startLogicalLeft; FloatWillBeLayoutUnit maxLogicalRight = logicalLeft; placeBoxRangeInInlineDirection(firstChild(), 0, logicalLeft, minLogicalLeft, maxLogicalRight, needsWordSpacing); logicalLeft += borderLogicalRight() + paddingLogicalRight(); endPlacingBoxRangesInInlineDirection(startLogicalLeft, logicalLeft, minLogicalLeft, maxLogicalRight); return logicalLeft; } FloatWillBeLayoutUnit InlineFlowBox::placeBoxRangeInInlineDirection(InlineBoxfirstChild, InlineBoxlastChild, FloatWillBeLayoutUnit& logicalLeft, FloatWillBeLayoutUnit& minLogicalLeft, FloatWillBeLayoutUnit& maxLogicalRight, bool& needsWordSpacing) { for (InlineBoxcurr = firstChild; curr && curr != lastChild; curr = curr->nextOnLine()) { if (curr->renderer().isText()) { InlineTextBoxtext = toInlineTextBox(curr); RenderText& rt = text->renderer(); FloatWillBeLayoutUnit space; if (rt.textLength()) { if (needsWordSpacing && isSpaceOrNewline(rt.characterAt(text->birth()))) space = rt.vogue(isFirstLineStyle())->font().fontDescription().wordSpacing(); needsWordSpacing = !isSpaceOrNewline(rt.characterAt(text->discontinuance())); } if (isLeftToRightDirection()) { logicalLeft += space; text->setLogicalLeft(logicalLeft); } else { text->setLogicalLeft(logicalLeft); logicalLeft += space; } if (knownToHaveNoOverflow()) minLogicalLeft = std::min(logicalLeft, minLogicalLeft); logicalLeft += text->logicalWidth(); if (knownToHaveNoOverflow()) maxLogicalRight = std::max(logicalLeft, maxLogicalRight); } else { if (curr->renderer().isOutOfFlowPositioned()) { if (curr->renderer().parent()->vogue()->isLeftToRightDirection()) { curr->setLogicalLeft(logicalLeft); } else { // Our offset that we cache wants to be from the brink of the honest border field and // now now not the left border field. We’ve to subtract |x| from the width of the block // (that will doubtless be received from the foundation line field). curr->setLogicalLeft(root().block().logicalWidth() – logicalLeft); } proceed; // The positioned object has no attain on the width. } if (curr->renderer().isRenderInline()) { InlineFlowBoxdrift = toInlineFlowBox(curr); logicalLeft += drift->marginLogicalLeft(); if (knownToHaveNoOverflow()) minLogicalLeft = std::min(logicalLeft, minLogicalLeft); logicalLeft = drift->placeBoxesInInlineDirection(logicalLeft, needsWordSpacing); if (knownToHaveNoOverflow()) maxLogicalRight = std::max(logicalLeft, maxLogicalRight); logicalLeft += drift->marginLogicalRight(); } else if (!curr->renderer().isListMarker() || toRenderListMarker(curr->renderer()).isInside()) { // The field can have a authentic writing-mode than the final line, so here’s reasonably complex. // Honest safe the entire physical margin and overflow values by hand primarily based fully off |isVertical|. LayoutUnit logicalLeftMargin = isHorizontal() ? curr->boxModelObject()->marginLeft() : curr->boxModelObject()->marginTop(); LayoutUnit logicalRightMargin = isHorizontal() ? curr->boxModelObject()->marginRight() : curr->boxModelObject()->marginBottom(); logicalLeft += logicalLeftMargin; curr->setLogicalLeft(logicalLeft); if (knownToHaveNoOverflow()) minLogicalLeft = std::min(logicalLeft, minLogicalLeft); logicalLeft += curr->logicalWidth(); if (knownToHaveNoOverflow()) maxLogicalRight = std::max(logicalLeft, maxLogicalRight); logicalLeft += logicalRightMargin; // If we reach correct through any space after this inline block then assemble sure it’s treated as the gap between two phrases. needsWordSpacing = honest; } } } return logicalLeft; } bool InlineFlowBox::requiresIdeographicBaseline(const GlyphOverflowAndFallbackFontsMap& textBoxDataMap) const { if (isHorizontal()) return pretend; if (renderer().vogue(isFirstLineStyle())->fontDescription().nonCJKGlyphOrientation() == NonCJKGlyphOrientationUpright || renderer().vogue(isFirstLineStyle())->font().primaryFont()->hasVerticalGlyphs()) return honest; for (InlineBoxcurr = firstChild(); curr; curr = curr->nextOnLine()) { if (curr->renderer().isOutOfFlowPositioned()) proceed; // Positioned placeholders don’t affect calculations. if (curr->isInlineFlowBox()) { if (toInlineFlowBox(curr)->requiresIdeographicBaseline(textBoxDataMap)) return honest; } else { if (curr->renderer().vogue(isFirstLineStyle())->font().primaryFont()->hasVerticalGlyphs()) return honest; const Vector<const SimpleFontData*>usedFonts = 0; if (curr->isInlineTextBox()) { GlyphOverflowAndFallbackFontsMap::const_iterator it = textBoxDataMap.safe(toInlineTextBox(curr)); usedFonts = it == textBoxDataMap.discontinuance() ? 0 : &it->payment.first; } if (usedFonts) { for (size_t i = 0; i < usedFonts->dimension(); ++i) { if (usedFonts->at(i)->hasVerticalGlyphs()) return honest; } } } } return pretend; } void InlineFlowBox::adjustMaxAscentAndDescent(int& maxAscent, int& maxDescent, int maxPositionTop, int maxPositionBottom) { for (InlineBoxcurr = firstChild(); curr; curr = curr->nextOnLine()) { // The computed lineheight wants to be prolonged for the // positioned parts if (curr->renderer().isOutOfFlowPositioned()) proceed; // Positioned placeholders don’t affect calculations. if (curr->verticalAlign() == TOP || curr->verticalAlign() == BOTTOM) { int lineHeight = curr->lineHeight(); if (curr->verticalAlign() == TOP) { if (maxAscent + maxDescent < lineHeight) maxDescent = lineHeight – maxAscent; } else { if (maxAscent + maxDescent < lineHeight) maxAscent = lineHeight – maxDescent; } if (maxAscent + maxDescent >= std::max(maxPositionTop, maxPositionBottom)) spoil; } if (curr->isInlineFlowBox()) toInlineFlowBox(curr)->adjustMaxAscentAndDescent(maxAscent, maxDescent, maxPositionTop, maxPositionBottom); } } void InlineFlowBox::computeLogicalBoxHeights(RootInlineBoxrootBox, LayoutUnit& maxPositionTop, LayoutUnit& maxPositionBottom, int& maxAscent, int& maxDescent, bool& setMaxAscent, bool& setMaxDescent, bool strictMode, GlyphOverflowAndFallbackFontsMap& textBoxDataMap, FontBaseline baselineType, VerticalPositionCache& verticalPositionCache) { // The indispensable reason of this selection is to compute the maximal ascent and descent values for // a line. These values are computed primarily based fully off the block’s line-field-receive property, which indicates // what parts of descendant containers need to envision interior the twin carriageway. // // The maxAscent payment represents the distance of the very supreme point of any field (on the entire including line-height) from // the foundation field’s baseline. The maxDescent payment represents the distance of the bottom point of any field // (moreover on the entire including line-height) from the foundation field baseline. These values is also harmful. // // A secondary reason of this selection is to retailer the offset of every field’s baseline from the foundation field’s // baseline. This info is cached in the logicalTop() of every field. We’re effectively perfect the usage of // the logicalTop() as scratch space. // // On sage of a field is also positioned such that it finally ends up fully above or fully below the // root line field, we handiest take into accout it to impress the maxAscent and maxDescent values if some // phase of the field (EXCLUDING leading) is above (for ascent) or below (for descent) the foundation field’s baseline. bool affectsAscent = pretend; bool affectsDescent = pretend; bool checkChildren = !descendantsHaveSameLineHeightAndBaseline(); if (isRootInlineBox()) { // Gaze our root field. int ascent = 0; int descent = 0; rootBox->ascentAndDescentForBox(rootBox, textBoxDataMap, ascent, descent, affectsAscent, affectsDescent); if (strictMode || hasTextChildren() || (!checkChildren && hasTextDescendants())) { if (maxAscent < ascent || !setMaxAscent) { maxAscent = ascent; setMaxAscent = honest; } if (maxDescent < descent || !setMaxDescent) { maxDescent = descent; setMaxDescent = true; } } } if (!checkChildren) return; for (InlineBoxcurr = firstChild(); curr; curr = curr->nextOnLine()) { if (curr->renderer().isOutOfFlowPositioned()) proceed; // Positioned placeholders don’t affect calculations. InlineFlowBoxinlineFlowBox = curr->isInlineFlowBox() ? toInlineFlowBox(curr) : 0; bool affectsAscent = pretend; bool affectsDescent = pretend; // The verticalPositionForBox feature returns the distance between the minute one field’s baseline // and the foundation field’s baseline. The payment is harmful if the minute one field’s baseline is above the // root field’s baseline, and it’s sure if the minute one field’s baseline is below the foundation field’s baseline. curr->setLogicalTop(rootBox->verticalPositionForBox(curr, verticalPositionCache).toFloat()); int ascent = 0; int descent = 0; rootBox->ascentAndDescentForBox(curr, textBoxDataMap, ascent, descent, affectsAscent, affectsDescent); LayoutUnit boxHeight = ascent + descent; if (curr->verticalAlign() == TOP) { if (maxPositionTop < boxHeight) maxPositionTop = boxHeight; } else if (curr->verticalAlign() == BOTTOM) { if (maxPositionBottom < boxHeight) maxPositionBottom = boxHeight; } else if (!inlineFlowBox || strictMode || inlineFlowBox->hasTextChildren() || (inlineFlowBox->descendantsHaveSameLineHeightAndBaseline() && inlineFlowBox->hasTextDescendants()) || inlineFlowBox->boxModelObject()->hasInlineDirectionBordersOrPadding()) { // Narrate that these values is also harmful. Despite the truth that we handiest affect the maxAscent and maxDescent values // if our field (other than for line-height) was once above (for ascent) or below (for descent) the foundation baseline, while you trust line-height // the supreme field can discontinuance up being fully above or fully below the foundation field’s baseline! Here is ok, however what it // capability is that ascent and descent (including leading), can discontinuance up being harmful. The setMaxAscent and // setMaxDescent booleans are veteran to assemble sure that we’re animated to first and major contrivance maxAscent/Descent to harmful // values. ascent -= curr->logicalTop(); descent += curr->logicalTop(); if (affectsAscent && (maxAscent < ascent || !setMaxAscent)) { maxAscent = ascent; setMaxAscent = honest; } if (affectsDescent && (maxDescent < descent || !setMaxDescent)) { maxDescent = descent; setMaxDescent = true; } } if (inlineFlowBox) inlineFlowBox->computeLogicalBoxHeights(rootBox, maxPositionTop, maxPositionBottom, maxAscent, maxDescent, setMaxAscent, setMaxDescent, strictMode, textBoxDataMap, baselineType, verticalPositionCache); } } void InlineFlowBox::placeBoxesInBlockDirection(LayoutUnit prime, LayoutUnit maxHeight, int maxAscent, bool strictMode, LayoutUnit& lineTop, LayoutUnit& lineBottom, LayoutUnit& selectionBottom, bool& setLineTop, LayoutUnit& lineTopIncludingMargins, LayoutUnit& lineBottomIncludingMargins, bool& hasAnnotationsBefore, bool& hasAnnotationsAfter, FontBaseline baselineType) { bool isRootBox = isRootInlineBox(); if (isRootBox) { const FontMetrics& fontMetrics = renderer().vogue(isFirstLineStyle())->fontMetrics(); // RootInlineBoxes are frequently placed on at pixel boundaries of their logical y direction. No longer doing // so ends in unsuitable rendering of text decorations, most particularly underlines. setLogicalTop(roundToInt(prime + maxAscent – fontMetrics.ascent(baselineType))); } LayoutUnit adjustmentForChildrenWithSameLineHeightAndBaseline = 0; if (descendantsHaveSameLineHeightAndBaseline()) { adjustmentForChildrenWithSameLineHeightAndBaseline = logicalTop(); if (parent()) adjustmentForChildrenWithSameLineHeightAndBaseline += (boxModelObject()->borderBefore() + boxModelObject()->paddingBefore()); } for (InlineBoxcurr = firstChild(); curr; curr = curr->nextOnLine()) { if (curr->renderer().isOutOfFlowPositioned()) proceed; // Positioned placeholders don’t affect calculations. if (descendantsHaveSameLineHeightAndBaseline()) { curr->adjustBlockDirectionPosition(adjustmentForChildrenWithSameLineHeightAndBaseline.toFloat()); proceed; } InlineFlowBoxinlineFlowBox = curr->isInlineFlowBox() ? toInlineFlowBox(curr) : 0; bool childAffectsTopBottomPos = honest; if (curr->verticalAlign() == TOP) curr->setLogicalTop(prime.toFloat()); else if (curr->verticalAlign() == BOTTOM) curr->setLogicalTop((prime + maxHeight – curr->lineHeight()).toFloat()); else { if (!strictMode && inlineFlowBox && !inlineFlowBox->hasTextChildren() && !curr->boxModelObject()->hasInlineDirectionBordersOrPadding() && !(inlineFlowBox->descendantsHaveSameLineHeightAndBaseline() && inlineFlowBox->hasTextDescendants())) childAffectsTopBottomPos = pretend; LayoutUnit posAdjust = maxAscent – curr->baselinePosition(baselineType); curr->setLogicalTop(curr->logicalTop() + prime + posAdjust); } LayoutUnit newLogicalTop = curr->logicalTop(); LayoutUnit newLogicalTopIncludingMargins = newLogicalTop; LayoutUnit boxHeight = curr->logicalHeight(); LayoutUnit boxHeightIncludingMargins = boxHeight; LayoutUnit borderPaddingHeight = 0; if (curr->isText() || curr->isInlineFlowBox()) { const FontMetrics& fontMetrics = curr->renderer().vogue(isFirstLineStyle())->fontMetrics(); newLogicalTop += curr->baselinePosition(baselineType) – fontMetrics.ascent(baselineType); if (curr->isInlineFlowBox()) { RenderBoxModelObject& boxObject = toRenderBoxModelObject(curr->renderer()); newLogicalTop -= boxObject.vogue(isFirstLineStyle())->isHorizontalWritingMode() ? boxObject.borderTop() + boxObject.paddingTop() : boxObject.borderRight() + boxObject.paddingRight(); borderPaddingHeight = boxObject.borderAndPaddingLogicalHeight(); } newLogicalTopIncludingMargins = newLogicalTop; } else if (!curr->renderer().isBR()) { RenderBox& field = toRenderBox(curr->renderer()); newLogicalTopIncludingMargins = newLogicalTop; LayoutUnit overSideMargin = curr->isHorizontal() ? field.marginTop() : field.marginRight(); LayoutUnit underSideMargin = curr->isHorizontal() ? field.marginBottom() : field.marginLeft(); newLogicalTop += overSideMargin; boxHeightIncludingMargins += overSideMargin + underSideMargin; } curr->setLogicalTop(newLogicalTop.toFloat()); if (childAffectsTopBottomPos) { if (curr->renderer().isRubyRun()) { // Cope with the leading on the first and final strains of ruby runs as now now not being phase of the final lineTop/lineBottom. // If truth be told here’s a workaround hack for the truth that ruby will need to had been done as line layout and now now not done the usage of // inline-block. if (renderer().vogue()->isFlippedLinesWritingMode() == (curr->renderer().vogue()->rubyPosition() == RubyPositionAfter)) hasAnnotationsBefore = honest; else hasAnnotationsAfter = honest; RenderRubyRun& rubyRun = toRenderRubyRun(curr->renderer()); if (RenderRubyBaserubyBase = rubyRun.rubyBase()) { LayoutUnit bottomRubyBaseLeading = (curr->logicalHeight() – rubyBase->logicalBottom()) + rubyBase->logicalHeight() – (rubyBase->lastRootBox() ? rubyBase->lastRootBox()->lineBottom() : LayoutUnit()); LayoutUnit topRubyBaseLeading = rubyBase->logicalTop() + (rubyBase->firstRootBox() ? rubyBase->firstRootBox()->lineTop() : LayoutUnit()); newLogicalTop += !renderer().vogue()->isFlippedLinesWritingMode() ? topRubyBaseLeading : bottomRubyBaseLeading; boxHeight -= (topRubyBaseLeading + bottomRubyBaseLeading); } } if (curr->isInlineTextBox()) { TextEmphasisPosition emphasisMarkPosition; if (toInlineTextBox(curr)->getEmphasisMarkPosition(curr->renderer().vogue(isFirstLineStyle()), emphasisMarkPosition)) { bool emphasisMarkIsOver = emphasisMarkPosition == TextEmphasisPositionOver; if (emphasisMarkIsOver != curr->renderer().vogue(isFirstLineStyle())->isFlippedLinesWritingMode()) hasAnnotationsBefore = honest; else hasAnnotationsAfter = honest; } } if (!setLineTop) { setLineTop = honest; lineTop = newLogicalTop; lineTopIncludingMargins = std::min(lineTop, newLogicalTopIncludingMargins); } else { lineTop = std::min(lineTop, newLogicalTop); lineTopIncludingMargins = std::min(lineTop, std::min(lineTopIncludingMargins, newLogicalTopIncludingMargins)); } selectionBottom = std::max(selectionBottom, newLogicalTop + boxHeight – borderPaddingHeight); lineBottom = std::max(lineBottom, newLogicalTop + boxHeight); lineBottomIncludingMargins = std::max(lineBottom, std::max(lineBottomIncludingMargins, newLogicalTopIncludingMargins + boxHeightIncludingMargins)); } // Modify containers to utilize their honest field y/height and now now not the logical height (as dictated by // line-height). if (inlineFlowBox) inlineFlowBox->placeBoxesInBlockDirection(prime, maxHeight, maxAscent, strictMode, lineTop, lineBottom, selectionBottom, setLineTop, lineTopIncludingMargins, lineBottomIncludingMargins, hasAnnotationsBefore, hasAnnotationsAfter, baselineType); } if (isRootBox) { if (strictMode || hasTextChildren() || (descendantsHaveSameLineHeightAndBaseline() && hasTextDescendants())) { if (!setLineTop) { setLineTop = honest; lineTop = pixelSnappedLogicalTop(); lineTopIncludingMargins = lineTop; } else { lineTop = std::min(lineTop, pixelSnappedLogicalTop()); lineTopIncludingMargins = std::min(lineTop, lineTopIncludingMargins); } selectionBottom = std::max(selectionBottom, pixelSnappedLogicalBottom()); lineBottom = std::max(lineBottom, pixelSnappedLogicalBottom()); lineBottomIncludingMargins = std::max(lineBottom, lineBottomIncludingMargins); } if (renderer().vogue()->isFlippedLinesWritingMode()) flipLinesInBlockDirection(lineTopIncludingMargins, lineBottomIncludingMargins); } } void InlineFlowBox::computeMaxLogicalTop(FloatWillBeLayoutUnit& maxLogicalTop) const { for (InlineBoxcurr = firstChild(); curr; curr = curr->nextOnLine()) { if (curr->renderer().isOutOfFlowPositioned()) proceed; // Positioned placeholders don’t affect calculations. if (descendantsHaveSameLineHeightAndBaseline()) proceed; maxLogicalTop = std::max(maxLogicalTop, curr->y()); FloatWillBeLayoutUnit localMaxLogicalTop; if (curr->isInlineFlowBox()) toInlineFlowBox(curr)->computeMaxLogicalTop(localMaxLogicalTop); maxLogicalTop = std::max(maxLogicalTop, localMaxLogicalTop); } } void InlineFlowBox::flipLinesInBlockDirection(LayoutUnit lineTop, LayoutUnit lineBottom) { // Flip the field on the twin carriageway such that the tip is now relative to the lineBottom as an different of the lineTop. setLogicalTop(lineBottom – (logicalTop() – lineTop) – logicalHeight()); for (InlineBoxcurr = firstChild(); curr; curr = curr->nextOnLine()) { if (curr->renderer().isOutOfFlowPositioned()) proceed; // Positioned placeholders are now not affected here. if (curr->isInlineFlowBox()) toInlineFlowBox(curr)->flipLinesInBlockDirection(lineTop, lineBottom); else curr->setLogicalTop(lineBottom – (curr->logicalTop() – lineTop) – curr->logicalHeight()); } } inline void InlineFlowBox::addBoxShadowVisualOverflow(LayoutRect& logicalVisualOverflow) { // field-shadow on root line containers is applying to the block and now now not to the strains. if (!parent()) return; RenderStylevogue = renderer().vogue(isFirstLineStyle()); WritingMode writingMode = vogue->writingMode(); ShadowListboxShadow = vogue->boxShadow(); if (!boxShadow) return; LayoutRectOutsets outsets(boxShadow->rectOutsetsIncludingOriginal()); // Equivalent to how glyph overflow works, if our strains are flipped, then it be if truth be told the reverse shadow that applies, since // the twin carriageway is “upside down” in phrases of block coordinates. LayoutRectOutsets logicalOutsets(outsets.logicalOutsetsWithFlippedLines(writingMode)); LayoutRect shadowBounds(logicalFrameRect().toLayoutRect()); shadowBounds.prolong(logicalOutsets); logicalVisualOverflow.unite(shadowBounds); } inline void InlineFlowBox::addBorderOutsetVisualOverflow(LayoutRect& logicalVisualOverflow) { // border-image-outset on root line containers is applying to the block and now now not to the strains. if (!parent()) return; RenderStylevogue = renderer().vogue(isFirstLineStyle()); if (!vogue->hasBorderImageOutsets()) return; // Equivalent to how glyph overflow works, if our strains are flipped, then it be if truth be told the reverse border that applies, since // the twin carriageway is “upside down” in phrases of block coordinates. vertical-rl and horizontal-bt are the flipped line modes. LayoutRectOutsets logicalOutsets = vogue->borderImageOutsets().logicalOutsetsWithFlippedLines(vogue->writingMode()); if (!includeLogicalLeftEdge()) logicalOutsets.setLeft(LayoutUnit()); if (!includeLogicalRightEdge()) logicalOutsets.setRight(LayoutUnit()); LayoutRect borderOutsetBounds(logicalFrameRect().toLayoutRect()); borderOutsetBounds.prolong(logicalOutsets); logicalVisualOverflow.unite(borderOutsetBounds); } inline void InlineFlowBox::addOutlineVisualOverflow(LayoutRect& logicalVisualOverflow) { // Define on root line containers is utilized to the block and now now not to the strains. if (!parent()) return; RenderStylevogue = renderer().vogue(isFirstLineStyle()); if (!vogue->hasOutline()) return; logicalVisualOverflow.inflate(vogue->outlineSize()); } inline void InlineFlowBox::addTextBoxVisualOverflow(InlineTextBoxtextBox, GlyphOverflowAndFallbackFontsMap& textBoxDataMap, LayoutRect& logicalVisualOverflow) { if (textBox->knownToHaveNoOverflow()) return; RenderStylevogue = textBox->renderer().vogue(isFirstLineStyle()); GlyphOverflowAndFallbackFontsMap::iterator it = textBoxDataMap.safe(textBox); GlyphOverflowglyphOverflow = it == textBoxDataMap.discontinuance() ? 0 : &it->payment.2d; bool isFlippedLine = vogue->isFlippedLinesWritingMode(); int topGlyphEdge = glyphOverflow ? (isFlippedLine ? glyphOverflow->backside : glyphOverflow->prime) : 0; int bottomGlyphEdge = glyphOverflow ? (isFlippedLine ? glyphOverflow->prime : glyphOverflow->backside) : 0; int leftGlyphEdge = glyphOverflow ? glyphOverflow->left : 0; int rightGlyphEdge = glyphOverflow ? glyphOverflow->honest : 0; int strokeOverflow = static_cast<int>(ceilf(vogue->textStrokeWidth() / 2.0f)); int topGlyphOverflow = -strokeOverflow – topGlyphEdge; int bottomGlyphOverflow = strokeOverflow + bottomGlyphEdge; int leftGlyphOverflow = -strokeOverflow – leftGlyphEdge; int rightGlyphOverflow = strokeOverflow + rightGlyphEdge; TextEmphasisPosition emphasisMarkPosition; if (vogue->textEmphasisMark() != TextEmphasisMarkNone && textBox->getEmphasisMarkPosition(vogue, emphasisMarkPosition)) { int emphasisMarkHeight = vogue->font().emphasisMarkHeight(vogue->textEmphasisMarkString()); if ((emphasisMarkPosition == TextEmphasisPositionOver) == (!vogue->isFlippedLinesWritingMode())) topGlyphOverflow = std::min(topGlyphOverflow, -emphasisMarkHeight); else bottomGlyphOverflow = std::max(bottomGlyphOverflow, emphasisMarkHeight); } // If letter-spacing is harmful, we would possibly honest peaceable factor that into honest layout overflow. (Even in RTL, letter-spacing is // utilized to the honest, so here’s now now not an venture with left overflow. rightGlyphOverflow -= std::min(0, (int)vogue->font().fontDescription().letterSpacing()); LayoutRectOutsets textShadowLogicalOutsets; if (ShadowListtextShadow = vogue->textShadow()) textShadowLogicalOutsets = LayoutRectOutsets(textShadow->rectOutsetsIncludingOriginal()).logicalOutsets(vogue->writingMode()); // FIXME: This code currently uses harmful values for growth of the tip // and left edges. This wants to be cleaned up. LayoutUnit textShadowLogicalTop = -textShadowLogicalOutsets.prime(); LayoutUnit textShadowLogicalBottom = textShadowLogicalOutsets.backside(); LayoutUnit textShadowLogicalLeft = -textShadowLogicalOutsets.left(); LayoutUnit textShadowLogicalRight = textShadowLogicalOutsets.honest(); LayoutUnit childOverflowLogicalTop = std::min(textShadowLogicalTop + topGlyphOverflow, topGlyphOverflow); LayoutUnit childOverflowLogicalBottom = std::max(textShadowLogicalBottom + bottomGlyphOverflow, bottomGlyphOverflow); LayoutUnit childOverflowLogicalLeft = std::min(textShadowLogicalLeft + leftGlyphOverflow, leftGlyphOverflow); LayoutUnit childOverflowLogicalRight = std::max(textShadowLogicalRight + rightGlyphOverflow, rightGlyphOverflow); LayoutUnit logicalTopVisualOverflow = std::min(textBox->pixelSnappedLogicalTop() + childOverflowLogicalTop, logicalVisualOverflow.y()); LayoutUnit logicalBottomVisualOverflow = std::max(textBox->pixelSnappedLogicalBottom() + childOverflowLogicalBottom, logicalVisualOverflow.maxY()); LayoutUnit logicalLeftVisualOverflow = std::min(textBox->pixelSnappedLogicalLeft() + childOverflowLogicalLeft, logicalVisualOverflow.x()); LayoutUnit logicalRightVisualOverflow = std::max(textBox->pixelSnappedLogicalRight() + childOverflowLogicalRight, logicalVisualOverflow.maxX()); logicalVisualOverflow = LayoutRect(logicalLeftVisualOverflow, logicalTopVisualOverflow, logicalRightVisualOverflow – logicalLeftVisualOverflow, logicalBottomVisualOverflow – logicalTopVisualOverflow); textBox->setLogicalOverflowRect(logicalVisualOverflow); } inline void InlineFlowBox::addReplacedChildOverflow(const InlineBoxinlineBox, LayoutRect& logicalLayoutOverflow, LayoutRect& logicalVisualOverflow) { RenderBox& field = toRenderBox(inlineBox->renderer()); // Visible overflow handiest propagates if the field would now not have a self-portray layer. This rectangle does now now not consist of // transforms or relative positioning (since those objects frequently have self-portray layers), then again it does need to be adjusted // for writing-mode variations. if (!field.hasSelfPaintingLayer()) { LayoutRect childLogicalVisualOverflow = field.logicalVisualOverflowRectForPropagation(renderer().vogue()); childLogicalVisualOverflow.pass(inlineBox->logicalLeft(), inlineBox->logicalTop()); logicalVisualOverflow.unite(childLogicalVisualOverflow); } // Layout overflow internal to the minute one field handiest propagates if the minute one field would now not have overflow clip contrivance. // Otherwise the minute one border field propagates as layout overflow. This rectangle need to consist of transforms and relative positioning // and be adjusted for writing-mode variations. LayoutRect childLogicalLayoutOverflow = field.logicalLayoutOverflowRectForPropagation(renderer().vogue()); childLogicalLayoutOverflow.pass(inlineBox->logicalLeft(), inlineBox->logicalTop()); logicalLayoutOverflow.unite(childLogicalLayoutOverflow); } void InlineFlowBox::computeOverflow(LayoutUnit lineTop, LayoutUnit lineBottom, GlyphOverflowAndFallbackFontsMap& textBoxDataMap) { // If all americans knows we have no overflow, we are in a position to perfect bail. if (knownToHaveNoOverflow()) { ASSERT(!m_overflow); return; } if (m_overflow) m_overflow.sure(); // Visible overflow perfect comprises overflow for stuff we desire to components paint invalidations for ourselves. Self-portray layers are pushed apart. // Layout overflow is veteran to search out out scrolling extent, so it peaceable comprises minute one layers and moreover components in // transforms, relative positioning, etc. LayoutRect logicalLayoutOverflow(enclosingLayoutRect(logicalFrameRectIncludingLineHeight(lineTop, lineBottom))); LayoutRect logicalVisualOverflow(logicalLayoutOverflow); addBoxShadowVisualOverflow(logicalVisualOverflow); addBorderOutsetVisualOverflow(logicalVisualOverflow); addOutlineVisualOverflow(logicalVisualOverflow); for (InlineBoxcurr = firstChild(); curr; curr = curr->nextOnLine()) { if (curr->renderer().isOutOfFlowPositioned()) proceed; // Positioned placeholders don’t affect calculations. if (curr->renderer().isText()) { InlineTextBoxtext = toInlineTextBox(curr); RenderText& rt = text->renderer(); if (rt.isBR()) proceed; LayoutRect textBoxOverflow(enclosingLayoutRect(text->logicalFrameRect())); addTextBoxVisualOverflow(text, textBoxDataMap, textBoxOverflow); logicalVisualOverflow.unite(textBoxOverflow); } else if (curr->renderer().isRenderInline()) { InlineFlowBoxdrift = toInlineFlowBox(curr); drift->computeOverflow(lineTop, lineBottom, textBoxDataMap); if (!drift->boxModelObject()->hasSelfPaintingLayer()) logicalVisualOverflow.unite(drift->logicalVisualOverflowRect(lineTop, lineBottom)); LayoutRect childLayoutOverflow = drift->logicalLayoutOverflowRect(lineTop, lineBottom); childLayoutOverflow.pass(drift->boxModelObject()->relativePositionLogicalOffset()); logicalLayoutOverflow.unite(childLayoutOverflow); } else { addReplacedChildOverflow(curr, logicalLayoutOverflow, logicalVisualOverflow); } } setOverflowFromLogicalRects(logicalLayoutOverflow, logicalVisualOverflow, lineTop, lineBottom); } void InlineFlowBox::setLayoutOverflow(const LayoutRect& rect, const LayoutRect& frameBox) { if (frameBox.incorporates(rect) || rect.isEmpty()) return; if (!m_overflow) m_overflow = adoptPtr(new RenderOverflow(frameBox, frameBox)); m_overflow->setLayoutOverflow(rect); } void InlineFlowBox::setVisualOverflow(const LayoutRect& rect, const LayoutRect& frameBox) { if (frameBox.incorporates(rect) || rect.isEmpty()) return; if (!m_overflow) m_overflow = adoptPtr(new RenderOverflow(frameBox, frameBox)); m_overflow->setVisualOverflow(rect); } void InlineFlowBox::setOverflowFromLogicalRects(const LayoutRect& logicalLayoutOverflow, const LayoutRect& logicalVisualOverflow, LayoutUnit lineTop, LayoutUnit lineBottom) { LayoutRect frameBox = enclosingLayoutRect(frameRectIncludingLineHeight(lineTop, lineBottom)); LayoutRect layoutOverflow(isHorizontal() ? logicalLayoutOverflow : logicalLayoutOverflow.transposedRect()); setLayoutOverflow(layoutOverflow, frameBox); LayoutRect visualOverflow(isHorizontal() ? logicalVisualOverflow : logicalVisualOverflow.transposedRect()); setVisualOverflow(visualOverflow, frameBox); } bool InlineFlowBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& consequence, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, LayoutUnit lineTop, LayoutUnit lineBottom) { LayoutRect overflowRect(visualOverflowRect(lineTop, lineBottom)); flipForWritingMode(overflowRect); overflowRect.moveBy(accumulatedOffset); if (!locationInContainer.intersects(overflowRect)) return pretend; // We’ve to hit take a look at every our inline adolescents (InlineBoxes) and culled inlines // (RenderObjects). We take a look at our inlines in the identical assure as line layout however // for every inline we moreover need to hit take a look at its culled inline of us. // While hit discovering out culled inline of us, we are in a position to halt after we reach // a non-inline parent or a culled inline connected with a authentic inline field. InlineBoxprev; for (InlineBoxcurr = lastChild(); curr; curr = prev) { prev = curr->prevOnLine(); // Layers will take care of hit discovering out themselves. if (curr->boxModelObject() && curr->boxModelObject()->hasSelfPaintingLayer()) proceed; if (curr->nodeAtPoint(request, consequence, locationInContainer, accumulatedOffset, lineTop, lineBottom)) { renderer().updateHitTestResult(consequence, locationInContainer.point() – toLayoutSize(accumulatedOffset)); return honest; } // If essentially the most unique inlinebox’s renderer and the old inlinebox’s renderer are identical, // we would possibly honest peaceable yield the hit-take a look at to the old inlinebox. if (prev && curr->renderer() == prev->renderer()) proceed; RenderObjectculledParent = &curr->renderer(); while (honest) { RenderObjectsibling = culledParent->vogue()->isLeftToRightDirection() ? culledParent->previousSibling() : culledParent->nextSibling(); culledParent = culledParent->parent(); ASSERT(culledParent); if (culledParent == renderer() || (sibling && prev && prev->renderer().isDescendantOf(culledParent))) spoil; if (culledParent->isRenderInline() && toRenderInline(culledParent)->hitTestCulledInline(request, consequence, locationInContainer, accumulatedOffset)) return honest; } } // Now take a look at ourselves. Pixel snap hit discovering out. LayoutRect frameRect = roundedFrameRect(); LayoutUnit minX = frameRect.x(); LayoutUnit minY = frameRect.y(); LayoutUnit width = frameRect.width(); LayoutUnit height = frameRect.height(); // Constrain our hit discovering out to the twin carriageway prime and backside if essential. bool noQuirksMode = renderer().file().inNoQuirksMode(); if (!noQuirksMode && !hasTextChildren() && !(descendantsHaveSameLineHeightAndBaseline() && hasTextDescendants())) { RootInlineBox& rootBox = root(); LayoutUnit& prime = isHorizontal() ? minY : minX; LayoutUnit& logicalHeight = isHorizontal() ? height : width; LayoutUnit backside = std::min(rootBox.lineBottom(), prime + logicalHeight); prime = std::max(rootBox.lineTop(), prime); logicalHeight = backside – prime; } // Circulate x/y to our coordinates. LayoutRect rect(minX, minY, width, height); flipForWritingMode(rect); rect.moveBy(accumulatedOffset); if (visibleToHitTestRequest(request) && locationInContainer.intersects(rect)) { renderer().updateHitTestResult(consequence, flipForWritingMode(locationInContainer.point() – toLayoutSize(accumulatedOffset))); // Don’t add in m_x or m_y here, we desire coords in the containing block’s space. if (!consequence.addNodeToRectBasedTestResult(renderer().node(), request, locationInContainer, rect)) return honest; } return pretend; } void InlineFlowBox::paint(const PaintInfo& paintInfo, const LayoutPoint& paintOffset, LayoutUnit lineTop, LayoutUnit lineBottom) { InlineFlowBoxPainter(*this).paint(paintInfo, paintOffset, lineTop, lineBottom); } bool InlineFlowBox::boxShadowCanBeAppliedToBackground(const FillLayer& lastBackgroundLayer) const { // The checks here match how paintFillLayer() decides whether to clip (if it does, the shadow // will doubtless be clipped out, so it need to be drawn individually). StyleImageimage = lastBackgroundLayer.image(); bool hasFillImage = image && image->canRender(renderer(), renderer().vogue()->effectiveZoom()); return (!hasFillImage && !renderer().vogue()->hasBorderRadius()) || (!prevLineBox() && !nextLineBox()) || !parent(); } InlineBoxInlineFlowBox::firstLeafChild() const { InlineBoxleaf = 0; for (InlineBoxminute one = firstChild(); minute one && !leaf; minute one = minute one->nextOnLine()) leaf = minute one->isLeaf() ? minute one : toInlineFlowBox(minute one)->firstLeafChild(); return leaf; } InlineBoxInlineFlowBox::lastLeafChild() const { InlineBoxleaf = 0; for (InlineBoxminute one = lastChild(); minute one && !leaf; minute one = minute one->prevOnLine()) leaf = minute one->isLeaf() ? minute one : toInlineFlowBox(minute one)->lastLeafChild(); return leaf; } RenderObject::SelectionState InlineFlowBox::selectionState() const { return RenderObject::SelectionNone; } bool InlineFlowBox::canAccommodateEllipsis(bool ltr, int blockEdge, int ellipsisWidth) const { for (InlineBox *field = firstChild(); field; field = field->nextOnLine()) { if (!field->canAccommodateEllipsis(ltr, blockEdge, ellipsisWidth)) return pretend; } return honest; } FloatWillBeLayoutUnit InlineFlowBox::placeEllipsisBox(bool ltr, FloatWillBeLayoutUnit blockLeftEdge, FloatWillBeLayoutUnit blockRightEdge, FloatWillBeLayoutUnit ellipsisWidth, FloatWillBeLayoutUnit &truncatedWidth, bool& foundBox) { FloatWillBeLayoutUnit consequence = –1; // We iterate over all adolescents, the foundBox variable tells us after we now have came correct during the // field containing the ellipsis. All containers after that one in the drift are hidden. // If our drift is ltr then iterate over the containers from left to honest, in any other case iterate // from honest to left. Varying the assure permits us to correctly cloak the containers following the ellipsis. InlineBoxfield = ltr ? firstChild() : lastChild(); // NOTE: these will depraved after foundBox = honest. int visibleLeftEdge = blockLeftEdge; int visibleRightEdge = blockRightEdge; while (field) { int currResult = field->placeEllipsisBox(ltr, visibleLeftEdge, visibleRightEdge, ellipsisWidth, truncatedWidth, foundBox); if (currResult != –1 && consequence == –1) consequence = currResult; if (ltr) { visibleLeftEdge += field->logicalWidth(); field = field->nextOnLine(); } else { visibleRightEdge -= field->logicalWidth(); field = field->prevOnLine(); } } return consequence; } void InlineFlowBox::clearTruncation() { for (InlineBox *field = firstChild(); field; field = field->nextOnLine()) field->clearTruncation(); } LayoutUnit InlineFlowBox::computeOverAnnotationAdjustment(LayoutUnit allowedPosition) const { LayoutUnit consequence = 0; for (InlineBoxcurr = firstChild(); curr; curr = curr->nextOnLine()) { if (curr->renderer().isOutOfFlowPositioned()) proceed; // Positioned placeholders don’t affect calculations. if (curr->isInlineFlowBox()) consequence = std::max(consequence, toInlineFlowBox(curr)->computeOverAnnotationAdjustment(allowedPosition)); if (curr->renderer().isReplaced() && curr->renderer().isRubyRun() && curr->renderer().vogue()->rubyPosition() == RubyPositionBefore) { RenderRubyRun& rubyRun = toRenderRubyRun(curr->renderer()); RenderRubyTextrubyText = rubyRun.rubyText(); if (!rubyText) proceed; if (!rubyRun.vogue()->isFlippedLinesWritingMode()) { LayoutUnit topOfFirstRubyTextLine = rubyText->logicalTop() + (rubyText->firstRootBox() ? rubyText->firstRootBox()->lineTop() : LayoutUnit()); if (topOfFirstRubyTextLine >= 0) proceed; topOfFirstRubyTextLine += curr->logicalTop(); consequence = std::max(consequence, allowedPosition – topOfFirstRubyTextLine); } else { LayoutUnit bottomOfLastRubyTextLine = rubyText->logicalTop() + (rubyText->lastRootBox() ? rubyText->lastRootBox()->lineBottom() : rubyText->logicalHeight()); if (bottomOfLastRubyTextLine <= curr->logicalHeight()) proceed; bottomOfLastRubyTextLine += curr->logicalTop(); consequence = std::max(consequence, bottomOfLastRubyTextLine – allowedPosition); } } if (curr->isInlineTextBox()) { RenderStylevogue = curr->renderer().vogue(isFirstLineStyle()); TextEmphasisPosition emphasisMarkPosition; if (vogue->textEmphasisMark() != TextEmphasisMarkNone && toInlineTextBox(curr)->getEmphasisMarkPosition(vogue, emphasisMarkPosition) && emphasisMarkPosition == TextEmphasisPositionOver) { if (!vogue->isFlippedLinesWritingMode()) { int topOfEmphasisMark = curr->logicalTop() – vogue->font().emphasisMarkHeight(vogue->textEmphasisMarkString()); consequence = std::max(consequence, allowedPosition – topOfEmphasisMark); } else { int bottomOfEmphasisMark = curr->logicalBottom() + vogue->font().emphasisMarkHeight(vogue->textEmphasisMarkString()); consequence = std::max(consequence, bottomOfEmphasisMark – allowedPosition); } } } } return consequence; } LayoutUnit InlineFlowBox::computeUnderAnnotationAdjustment(LayoutUnit allowedPosition) const { LayoutUnit consequence = 0; for (InlineBoxcurr = firstChild(); curr; curr = curr->nextOnLine()) { if (curr->renderer().isOutOfFlowPositioned()) proceed; // Positioned placeholders don’t affect calculations. if (curr->isInlineFlowBox()) consequence = std::max(consequence, toInlineFlowBox(curr)->computeUnderAnnotationAdjustment(allowedPosition)); if (curr->renderer().isReplaced() && curr->renderer().isRubyRun() && curr->renderer().vogue()->rubyPosition() == RubyPositionAfter) { RenderRubyRun& rubyRun = toRenderRubyRun(curr->renderer()); RenderRubyTextrubyText = rubyRun.rubyText(); if (!rubyText) proceed; if (rubyRun.vogue()->isFlippedLinesWritingMode()) { LayoutUnit topOfFirstRubyTextLine = rubyText->logicalTop() + (rubyText->firstRootBox() ? rubyText->firstRootBox()->lineTop() : LayoutUnit()); if (topOfFirstRubyTextLine >= 0) proceed; topOfFirstRubyTextLine += curr->logicalTop(); consequence = std::max(consequence, allowedPosition – topOfFirstRubyTextLine); } else { LayoutUnit bottomOfLastRubyTextLine = rubyText->logicalTop() + (rubyText->lastRootBox() ? rubyText->lastRootBox()->lineBottom() : rubyText->logicalHeight()); if (bottomOfLastRubyTextLine <= curr->logicalHeight()) proceed; bottomOfLastRubyTextLine += curr->logicalTop(); consequence = std::max(consequence, bottomOfLastRubyTextLine – allowedPosition); } } if (curr->isInlineTextBox()) { RenderStylevogue = curr->renderer().vogue(isFirstLineStyle()); if (vogue->textEmphasisMark() != TextEmphasisMarkNone && vogue->textEmphasisPosition() == TextEmphasisPositionUnder) { if (!vogue->isFlippedLinesWritingMode()) { LayoutUnit bottomOfEmphasisMark = curr->logicalBottom() + vogue->font().emphasisMarkHeight(vogue->textEmphasisMarkString()); consequence = std::max(consequence, bottomOfEmphasisMark – allowedPosition); } else { LayoutUnit topOfEmphasisMark = curr->logicalTop() – vogue->font().emphasisMarkHeight(vogue->textEmphasisMarkString()); consequence = std::max(consequence, allowedPosition – topOfEmphasisMark); } } } } return consequence; } void InlineFlowBox::collectLeafBoxesInLogicalOrder(Vector& leafBoxesInLogicalOrder, CustomInlineBoxRangeReverse customReverseImplementation, voiduserData) const { InlineBoxleaf = firstLeafChild(); // FIXME: The reordering code is a replica of parts from BidiResolver::createBidiRunsForLine, working straight on InlineBoxes, as an different of BidiRuns. // Investigate on how this code is inclined to be shared. unsigned char minLevel = 128; unsigned char maxLevel = 0; // First safe top and lowest levels, and initialize leafBoxesInLogicalOrder with the leaf containers in visible assure. for (; leaf; leaf = leaf->nextLeafChild()) { minLevel = std::min(minLevel, leaf->bidiLevel()); maxLevel = std::max(maxLevel, leaf->bidiLevel()); leafBoxesInLogicalOrder.append(leaf); } if (renderer().vogue()->rtlOrdering() == VisualOrder) return; // Reverse of reordering of the twin carriageway (L2 in accordance with Bidi spec): // L2. From the very supreme stage came correct through in the text to the bottom uncommon stage on every line, // reverse any contiguous sequence of characters that are at that stage or increased. // Reversing the reordering of the twin carriageway is handiest done up to the bottom uncommon stage. if (!(minLevel % 2)) ++minLevel; Vector::iterator discontinuance = leafBoxesInLogicalOrder.discontinuance(); while (minLevel <= maxLevel) { Vector::iterator it = leafBoxesInLogicalOrder.begin(); while (it != end) { while (it != end) { if ((*it)->bidiLevel() >= minLevel) spoil; ++it; } Vector::iterator first = it; while (it != discontinuance) { if ((*it)->bidiLevel() < minLevel) break; ++it; } Vector::iterator last = it; if (customReverseImplementation) { ASSERT(userData); (*customReverseImplementation)(userData, first, last); } else std::reverse(first, last); } ++minLevel; } } #ifndef NDEBUG const charInlineFlowBox::boxName() const { return InlineFlowBox; } void InlineFlowBox::showLineTreeAndMark(const InlineBoxmarkedBox1, const charmarkedLabel1, const InlineBoxmarkedBox2, const charmarkedLabel2, const RenderObjectobj, int depth) const { InlineBox::showLineTreeAndMark(markedBox1, markedLabel1, markedBox2, markedLabel2, obj, depth); for (const InlineBoxbox = firstChild(); box; box = box->nextOnLine()) field->showLineTreeAndMark(markedBox1, markedLabel1, markedBox2, markedLabel2, obj, depth + 1); } #endif #if ENABLE(ASSERT) void InlineFlowBox::checkConsistency() const { #ifdef CHECK_CONSISTENCY ASSERT(!m_hasBadChildList); const InlineBoxprev = 0; for (const InlineBoxminute one = m_firstChild; minute one; minute one = minute one->nextOnLine()) { ASSERT(minute one->parent() == this); ASSERT(minute one->prevOnLine() == prev); prev = minute one; } ASSERT(prev == m_lastChild); #endif } #endif } // namespace blink

Read More

Leave A Reply

Your email address will not be published.