void InlineFlowBox::adjustMaxAscentAndDescent(int& maxAscent, int& maxDescent, int maxPositionTop, int maxPositionBottom) { for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) { // The computed lineheight needs to be extended for the // positioned elements // see khtmltests/rendering/html_align.html if (curr->object()->isPositioned()) continue; // Positioned placeholders don't affect calculations. if (curr->yPos() == PositionTop || curr->yPos() == PositionBottom) { if (curr->yPos() == PositionTop) { if (maxAscent + maxDescent < curr->height()) maxDescent = curr->height() - maxAscent; } else { if (maxAscent + maxDescent < curr->height()) maxAscent = curr->height() - maxDescent; } if ( maxAscent + maxDescent >= kMax( maxPositionTop, maxPositionBottom ) ) break; } if (curr->isInlineFlowBox()) static_cast<InlineFlowBox*>(curr)->adjustMaxAscentAndDescent(maxAscent, maxDescent, maxPositionTop, maxPositionBottom); } }
void InlineFlowBox::computeLogicalBoxHeights(int& maxPositionTop, int& maxPositionBottom, int& maxAscent, int& maxDescent, bool strictMode) { if (isRootInlineBox()) { // Examine our root box. setHeight(object()->lineHeight(m_firstLine)); bool isTableCell = object()->isTableCell(); if (isTableCell) { RenderTableCell* tableCell = static_cast<RenderTableCell*>(object()); setBaseline(tableCell->RenderBlock::baselinePosition(m_firstLine)); } else setBaseline(object()->baselinePosition(m_firstLine)); if (hasTextChildren() || strictMode) { int ascent = baseline(); int descent = height() - ascent; if (maxAscent < ascent) maxAscent = ascent; if (maxDescent < descent) maxDescent = descent; } } for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) { if (curr->object()->isPositioned()) continue; // Positioned placeholders don't affect calculations. curr->setHeight(curr->object()->lineHeight(m_firstLine)); curr->setBaseline(curr->object()->baselinePosition(m_firstLine)); curr->setYPos(curr->object()->verticalPositionHint(m_firstLine)); if (curr->yPos() == PositionTop) { if (maxPositionTop < curr->height()) maxPositionTop = curr->height(); } else if (curr->yPos() == PositionBottom) { if (maxPositionBottom < curr->height()) maxPositionBottom = curr->height(); } else if (curr->hasTextChildren() || strictMode) { int ascent = curr->baseline() - curr->yPos(); int descent = curr->height() - ascent; if (maxAscent < ascent) maxAscent = ascent; if (maxDescent < descent) maxDescent = descent; } if (curr->isInlineFlowBox()) static_cast<InlineFlowBox*>(curr)->computeLogicalBoxHeights(maxPositionTop, maxPositionBottom, maxAscent, maxDescent, strictMode); } }
FloatRect RenderSVGText::relativeBBox(bool includeStroke) const { FloatRect repaintRect; for (InlineRunBox* runBox = firstLineBox(); runBox; runBox = runBox->nextLineBox()) { ASSERT(runBox->isInlineFlowBox()); InlineFlowBox* flowBox = static_cast<InlineFlowBox*>(runBox); for (InlineBox* box = flowBox->firstChild(); box; box = box->nextOnLine()) repaintRect.unite(FloatRect(box->xPos(), box->yPos(), box->width(), box->height())); } // SVG needs to include the strokeWidth(), not the textStrokeWidth(). if (includeStroke && style()->svgStyle()->hasStroke()) { float strokeWidth = SVGRenderStyle::cssPrimitiveToLength(this, style()->svgStyle()->strokeWidth(), 0.0f); #if ENABLE(SVG_FONTS) const Font& font = style()->font(); if (font.primaryFont()->isSVGFont()) { float scale = font.unitsPerEm() > 0 ? font.size() / font.unitsPerEm() : 0.0f; if (scale != 0.0f) strokeWidth /= scale; } #endif repaintRect.inflate(strokeWidth); } repaintRect.move(xPos(), yPos()); return repaintRect; }
FloatRect RenderSVGText::objectBoundingBox() const { FloatRect boundingBox; for (InlineFlowBox* flow = firstLineBox(); flow; flow = flow->nextLineBox()) { for (InlineBox* box = flow->firstChild(); box; box = box->nextOnLine()) boundingBox.unite(FloatRect(box->x(), box->y(), box->width(), box->height())); } boundingBox.move(x(), y()); return boundingBox; }
FloatRect RenderSVGText::objectBoundingBox() const { FloatRect boundingBox; for (InlineRunBox* runBox = firstLineBox(); runBox; runBox = runBox->nextLineBox()) { ASSERT(runBox->isInlineFlowBox()); InlineFlowBox* flowBox = static_cast<InlineFlowBox*>(runBox); for (InlineBox* box = flowBox->firstChild(); box; box = box->nextOnLine()) boundingBox.unite(FloatRect(box->x(), box->y(), box->width(), box->height())); } boundingBox.move(x(), y()); return boundingBox; }
void RenderSVGText::absoluteQuads(Vector<FloatQuad>& quads) { RenderSVGRoot* root = findSVGRootObject(parent()); if (!root) return; // Don't use objectBoundingBox here, as it's unites the selection rects. Makes it hard // to spot errors, if there are any using WebInspector. Individually feed them into 'rects'. for (InlineFlowBox* flow = firstLineBox(); flow; flow = flow->nextLineBox()) { for (InlineBox* box = flow->firstChild(); box; box = box->nextOnLine()) { FloatRect boxRect(box->x(), box->y(), box->width(), box->height()); // FIXME: crawling up the parent chain to map each quad is very inefficient // we should compute the absoluteTransform outside this loop first. quads.append(localToAbsoluteQuad(boxRect)); } } }
FloatRect RenderSVGText::relativeBBox(bool includeStroke) const { FloatRect repaintRect; for (InlineRunBox* runBox = firstLineBox(); runBox; runBox = runBox->nextLineBox()) { ASSERT(runBox->isInlineFlowBox()); InlineFlowBox* flowBox = static_cast<InlineFlowBox*>(runBox); for (InlineBox* box = flowBox->firstChild(); box; box = box->nextOnLine()) repaintRect.unite(FloatRect(box->xPos(), box->yPos(), box->width(), box->height())); } // SVG needs to include the strokeWidth(), not the textStrokeWidth(). if (includeStroke && style()->svgStyle()->hasStroke()) repaintRect.inflate(narrowPrecisionToFloat(KSVGPainterFactory::cssPrimitiveToLength(this, style()->svgStyle()->strokeWidth(), 0.0))); repaintRect.move(xPos(), yPos()); return repaintRect; }
void RenderSVGText::absoluteRects(Vector<IntRect>& rects, int, int) { RenderSVGRoot* root = findSVGRootObject(parent()); if (!root) return; // Don't use objectBoundingBox here, as it's unites the selection rects. Makes it hard // to spot errors, if there are any using WebInspector. Individually feed them into 'rects'. for (InlineRunBox* runBox = firstLineBox(); runBox; runBox = runBox->nextLineBox()) { ASSERT(runBox->isInlineFlowBox()); InlineFlowBox* flowBox = static_cast<InlineFlowBox*>(runBox); for (InlineBox* box = flowBox->firstChild(); box; box = box->nextOnLine()) { FloatRect boxRect(box->x(), box->y(), box->width(), box->height()); // FIXME: crawling up the parent chain to map each rect is very inefficient // we should compute the absoluteTransform outside this loop first. rects.append(enclosingIntRect(localToAbsoluteQuad(boxRect).boundingBox())); } } }
void RenderSVGText::absoluteRects(Vector<IntRect>& rects, int, int, bool) { RenderSVGRoot* root = findSVGRootObject(parent()); if (!root) return; int x, y; absolutePosition(x, y); AffineTransform htmlParentCtm = root->RenderContainer::absoluteTransform(); // Don't use relativeBBox here, as it's unites the selection rects. Makes it hard // to spot errors, if there are any using WebInspector. Individually feed them into 'rects'. for (InlineRunBox* runBox = firstLineBox(); runBox; runBox = runBox->nextLineBox()) { ASSERT(runBox->isInlineFlowBox()); InlineFlowBox* flowBox = static_cast<InlineFlowBox*>(runBox); for (InlineBox* box = flowBox->firstChild(); box; box = box->nextOnLine()) { FloatRect boxRect(box->xPos(), box->yPos(), box->width(), box->height()); boxRect.move(narrowPrecisionToFloat(x - htmlParentCtm.e()), narrowPrecisionToFloat(y - htmlParentCtm.f())); rects.append(enclosingIntRect(absoluteTransform().mapRect(boxRect))); } } }
void InlineFlowBox::placeBoxesVertically(int y, int maxHeight, int maxAscent, bool strictMode, int& topPosition, int& bottomPosition) { if (isRootInlineBox()) { setYPos(y + maxAscent - baseline());// Place our root box. // CSS2: 10.8.1 - line-height on the block level element specifies the *minimum* // height of the generated line box if (hasTextChildren() && maxHeight < object()->lineHeight(m_firstLine)) maxHeight = object()->lineHeight(m_firstLine); } for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) { if (curr->object()->isPositioned()) continue; // Positioned placeholders don't affect calculations. // Adjust boxes to use their real box y/height and not the logical height (as dictated by // line-height). if (curr->isInlineFlowBox()) static_cast<InlineFlowBox*>(curr)->placeBoxesVertically(y, maxHeight, maxAscent, strictMode, topPosition, bottomPosition); bool childAffectsTopBottomPos = true; if (curr->yPos() == PositionTop) curr->setYPos(y); else if (curr->yPos() == PositionBottom) curr->setYPos(y + maxHeight - curr->height()); else { if (!strictMode && !curr->hasTextDescendant()) childAffectsTopBottomPos = false; curr->setYPos(curr->yPos() + y + maxAscent - curr->baseline()); } int newY = curr->yPos(); int newHeight = curr->height(); int newBaseline = curr->baseline(); int overflowTop = 0; int overflowBottom = 0; if (curr->isInlineTextBox() || curr->isInlineFlowBox()) { const QFontMetrics &fm = curr->object()->fontMetrics( m_firstLine ); #ifdef APPLE_CHANGES newBaseline = fm.ascent(); newY += curr->baseline() - newBaseline; newHeight = newBaseline+fm.descent(); #else // only adjust if the leading delta is superior to the font's natural leading if ( kAbs(fm.ascent() - curr->baseline()) > fm.leading()/2 ) { int ascent = fm.ascent()+fm.leading()/2; newBaseline = ascent; newY += curr->baseline() - newBaseline; newHeight = fm.lineSpacing(); } #endif for (ShadowData* shadow = curr->object()->style()->textShadow(); shadow; shadow = shadow->next) { overflowTop = kMin(overflowTop, shadow->y - shadow->blur); overflowBottom = kMax(overflowBottom, shadow->y + shadow->blur); } if (curr->isInlineFlowBox()) { newHeight += curr->object()->borderTop() + curr->object()->paddingTop() + curr->object()->borderBottom() + curr->object()->paddingBottom(); newY -= curr->object()->borderTop() + curr->object()->paddingTop(); newBaseline += curr->object()->borderTop() + curr->object()->paddingTop(); } } else { newY += curr->object()->marginTop(); newHeight = curr->height() - (curr->object()->marginTop() + curr->object()->marginBottom()); overflowTop = curr->object()->overflowTop(); overflowBottom = curr->object()->overflowHeight() - newHeight; } curr->setYPos(newY); curr->setHeight(newHeight); curr->setBaseline(newBaseline); if (childAffectsTopBottomPos) { topPosition = kMin(topPosition, newY + overflowTop); bottomPosition = kMax(bottomPosition, newY + newHeight + overflowBottom); } } if (isRootInlineBox()) { const QFontMetrics &fm = object()->fontMetrics( m_firstLine ); #ifdef APPLE_CHANGES setHeight(fm.ascent()+fm.descent()); setYPos(yPos() + baseline() - fm.ascent()); setBaseline(fm.ascent()); #else if ( kAbs(fm.ascent() - baseline()) > fm.leading()/2 ) { int ascent = fm.ascent()+fm.leading()/2; setHeight(fm.lineSpacing()); setYPos(yPos() + baseline() - ascent); setBaseline(ascent); } #endif if (hasTextDescendant() || strictMode) { if (yPos() < topPosition) topPosition = yPos(); if (yPos() + height() > bottomPosition) bottomPosition = yPos() + height(); } } }