diff options
author | Steve Block <steveblock@google.com> | 2011-05-18 13:36:51 +0100 |
---|---|---|
committer | Steve Block <steveblock@google.com> | 2011-05-24 15:38:28 +0100 |
commit | 2fc2651226baac27029e38c9d6ef883fa32084db (patch) | |
tree | e396d4bf89dcce6ed02071be66212495b1df1dec /Source/WebCore/rendering/svg/SVGInlineTextBox.cpp | |
parent | b3725cedeb43722b3b175aaeff70552e562d2c94 (diff) | |
download | external_webkit-2fc2651226baac27029e38c9d6ef883fa32084db.zip external_webkit-2fc2651226baac27029e38c9d6ef883fa32084db.tar.gz external_webkit-2fc2651226baac27029e38c9d6ef883fa32084db.tar.bz2 |
Merge WebKit at r78450: Initial merge by git.
Change-Id: I6d3e5f1f868ec266a0aafdef66182ddc3f265dc1
Diffstat (limited to 'Source/WebCore/rendering/svg/SVGInlineTextBox.cpp')
-rw-r--r-- | Source/WebCore/rendering/svg/SVGInlineTextBox.cpp | 136 |
1 files changed, 104 insertions, 32 deletions
diff --git a/Source/WebCore/rendering/svg/SVGInlineTextBox.cpp b/Source/WebCore/rendering/svg/SVGInlineTextBox.cpp index 2879f20..52976f2 100644 --- a/Source/WebCore/rendering/svg/SVGInlineTextBox.cpp +++ b/Source/WebCore/rendering/svg/SVGInlineTextBox.cpp @@ -30,6 +30,7 @@ #include "RenderSVGInlineText.h" #include "RenderSVGResource.h" #include "RenderSVGResourceSolidColor.h" +#include "SVGImageBufferTools.h" #include "SVGRootInlineBox.h" #include "TextRun.h" @@ -56,9 +57,12 @@ int SVGInlineTextBox::offsetForPosition(int, bool) const int SVGInlineTextBox::offsetForPositionInFragment(const SVGTextFragment& fragment, float position, bool includePartialGlyphs) const { - RenderText* textRenderer = this->textRenderer(); + RenderSVGInlineText* textRenderer = toRenderSVGInlineText(this->textRenderer()); ASSERT(textRenderer); + float scalingFactor = textRenderer->scalingFactor(); + ASSERT(scalingFactor); + RenderStyle* style = textRenderer->style(); ASSERT(style); @@ -69,7 +73,7 @@ int SVGInlineTextBox::offsetForPositionInFragment(const SVGTextFragment& fragmen if (!fragment.transform.isIdentity()) textRun.setHorizontalGlyphStretch(narrowPrecisionToFloat(fragment.transform.xScale())); - return fragment.positionListOffset - start() + style->font().offsetForPosition(textRun, position, includePartialGlyphs); + return fragment.positionListOffset - start() + textRenderer->scaledFont().offsetForPosition(textRun, position * scalingFactor, includePartialGlyphs); } int SVGInlineTextBox::positionForOffset(int) const @@ -82,10 +86,28 @@ int SVGInlineTextBox::positionForOffset(int) const FloatRect SVGInlineTextBox::selectionRectForTextFragment(const SVGTextFragment& fragment, int startPosition, int endPosition, RenderStyle* style) { ASSERT(startPosition < endPosition); + ASSERT(style); + + RenderSVGInlineText* textRenderer = toRenderSVGInlineText(this->textRenderer()); + ASSERT(textRenderer); + + float scalingFactor = textRenderer->scalingFactor(); + ASSERT(scalingFactor); - const Font& font = style->font(); - FloatPoint textOrigin(fragment.x, fragment.y - font.ascent()); - return font.selectionRectForText(constructTextRun(style, fragment), textOrigin, fragment.height, startPosition, endPosition); + const Font& scaledFont = textRenderer->scaledFont(); + const FontMetrics& scaledFontMetrics = scaledFont.fontMetrics(); + FloatPoint textOrigin(fragment.x, fragment.y); + if (scalingFactor != 1) + textOrigin.scale(scalingFactor, scalingFactor); + + textOrigin.move(0, -scaledFontMetrics.floatAscent()); + + FloatRect selectionRect = scaledFont.selectionRectForText(constructTextRun(style, fragment), textOrigin, fragment.height * scalingFactor, startPosition, endPosition); + if (scalingFactor == 1) + return selectionRect; + + selectionRect.scale(1 / scalingFactor); + return selectionRect; } IntRect SVGInlineTextBox::selectionRect(int, int, int startPosition, int endPosition) @@ -125,6 +147,13 @@ IntRect SVGInlineTextBox::selectionRect(int, int, int startPosition, int endPosi return enclosingIntRect(selectionRect); } +static inline bool textShouldBePainted(RenderSVGInlineText* textRenderer) +{ + // Font::pixelSize(), returns FontDescription::computedPixelSize(), which returns "int(x + 0.5)". + // If the absolute font size on screen is below x=0.5, don't render anything. + return textRenderer->scaledFont().pixelSize(); +} + void SVGInlineTextBox::paintSelectionBackground(PaintInfo& paintInfo) { ASSERT(paintInfo.shouldPaintWithinRoot(renderer())); @@ -148,6 +177,11 @@ void SVGInlineTextBox::paintSelectionBackground(PaintInfo& paintInfo) if (!backgroundColor.isValid() || !backgroundColor.alpha()) return; + RenderSVGInlineText* textRenderer = toRenderSVGInlineText(this->textRenderer()); + ASSERT(textRenderer); + if (!textShouldBePainted(textRenderer)) + return; + RenderStyle* style = parentRenderer->style(); ASSERT(style); @@ -222,6 +256,11 @@ void SVGInlineTextBox::paint(PaintInfo& paintInfo, int, int) if (!hasSelection && paintSelectedTextOnly) return; + RenderSVGInlineText* textRenderer = toRenderSVGInlineText(this->textRenderer()); + ASSERT(textRenderer); + if (!textShouldBePainted(textRenderer)) + return; + RenderStyle* style = parentRenderer->style(); ASSERT(style); @@ -286,8 +325,9 @@ void SVGInlineTextBox::paint(PaintInfo& paintInfo, int, int) ASSERT(!m_paintingResource); } -bool SVGInlineTextBox::acquirePaintingResource(GraphicsContext*& context, RenderObject* renderer, RenderStyle* style) +bool SVGInlineTextBox::acquirePaintingResource(GraphicsContext*& context, float scalingFactor, RenderObject* renderer, RenderStyle* style) { + ASSERT(scalingFactor); ASSERT(renderer); ASSERT(style); ASSERT(m_paintingResourceMode != ApplyToDefaultMode); @@ -315,6 +355,9 @@ bool SVGInlineTextBox::acquirePaintingResource(GraphicsContext*& context, Render } } + if (scalingFactor != 1 && m_paintingResourceMode & ApplyToStrokeMode) + context->setStrokeThickness(context->strokeThickness() * scalingFactor); + return true; } @@ -329,9 +372,9 @@ void SVGInlineTextBox::releasePaintingResource(GraphicsContext*& context, const m_paintingResource = 0; } -bool SVGInlineTextBox::prepareGraphicsContextForTextPainting(GraphicsContext*& context, TextRun& textRun, RenderStyle* style) +bool SVGInlineTextBox::prepareGraphicsContextForTextPainting(GraphicsContext*& context, float scalingFactor, TextRun& textRun, RenderStyle* style) { - bool acquiredResource = acquirePaintingResource(context, parent()->renderer(), style); + bool acquiredResource = acquirePaintingResource(context, scalingFactor, parent()->renderer(), style); #if ENABLE(SVG_FONTS) // SVG Fonts need access to the painting resource used to draw the current text chunk. @@ -364,14 +407,12 @@ TextRun SVGInlineTextBox::constructTextRun(RenderStyle* style, const SVGTextFrag , false /* allowTabs */ , 0 /* xPos, only relevant with allowTabs=true */ , 0 /* padding, only relevant for justified text, not relevant for SVG */ + , TextRun::AllowTrailingExpansion , direction() == RTL , m_dirOverride || style->visuallyOrdered() /* directionalOverride */); #if ENABLE(SVG_FONTS) - RenderObject* parentRenderer = parent()->renderer(); - ASSERT(parentRenderer); - - run.setReferencingRenderObject(parentRenderer); + run.setReferencingRenderObject(text); #endif // Disable any word/character rounding. @@ -409,16 +450,16 @@ bool SVGInlineTextBox::mapStartEndPositionsIntoFragmentCoordinates(const SVGText return true; } -static inline float positionOffsetForDecoration(ETextDecoration decoration, const Font& font, float thickness) +static inline float positionOffsetForDecoration(ETextDecoration decoration, const FontMetrics& fontMetrics, float thickness) { // FIXME: For SVG Fonts we need to use the attributes defined in the <font-face> if specified. // Compatible with Batik/Opera. if (decoration == UNDERLINE) - return font.ascent() + thickness * 1.5f; + return fontMetrics.floatAscent() + thickness * 1.5f; if (decoration == OVERLINE) return thickness; if (decoration == LINE_THROUGH) - return font.ascent() * 5.0f / 8.0f; + return fontMetrics.floatAscent() * 5 / 8.0f; ASSERT_NOT_REACHED(); return 0.0f; @@ -486,22 +527,34 @@ void SVGInlineTextBox::paintDecorationWithStyle(GraphicsContext* context, ETextD RenderStyle* decorationStyle = decorationRenderer->style(); ASSERT(decorationStyle); - const Font& font = decorationStyle->font(); + float scalingFactor = 1; + Font scaledFont; + RenderSVGInlineText::computeNewScaledFontForStyle(decorationRenderer, decorationStyle, scalingFactor, scaledFont); + ASSERT(scalingFactor); // The initial y value refers to overline position. - float thickness = thicknessForDecoration(decoration, font); + float thickness = thicknessForDecoration(decoration, scaledFont); if (fragment.width <= 0 && thickness <= 0) return; - float y = fragment.y - font.ascent() + positionOffsetForDecoration(decoration, font, thickness); - - Path path; - path.addRect(FloatRect(fragment.x, y, fragment.width, thickness)); + FloatPoint decorationOrigin(fragment.x, fragment.y); + float width = fragment.width; + const FontMetrics& scaledFontMetrics = scaledFont.fontMetrics(); context->save(); + if (scalingFactor != 1) { + width *= scalingFactor; + decorationOrigin.scale(scalingFactor, scalingFactor); + context->scale(FloatSize(1 / scalingFactor, 1 / scalingFactor)); + } - if (acquirePaintingResource(context, decorationRenderer, decorationStyle)) + decorationOrigin.move(0, -scaledFontMetrics.floatAscent() + positionOffsetForDecoration(decoration, scaledFontMetrics, thickness)); + + Path path; + path.addRect(FloatRect(decorationOrigin, FloatSize(width, thickness))); + + if (acquirePaintingResource(context, scalingFactor, decorationRenderer, decorationStyle)) releasePaintingResource(context, &path); context->restore(); @@ -509,21 +562,41 @@ void SVGInlineTextBox::paintDecorationWithStyle(GraphicsContext* context, ETextD void SVGInlineTextBox::paintTextWithShadows(GraphicsContext* context, RenderStyle* style, TextRun& textRun, const SVGTextFragment& fragment, int startPosition, int endPosition) { - const Font& font = style->font(); + RenderSVGInlineText* textRenderer = toRenderSVGInlineText(this->textRenderer()); + ASSERT(textRenderer); + + float scalingFactor = textRenderer->scalingFactor(); + ASSERT(scalingFactor); + + const Font& scaledFont = textRenderer->scaledFont(); const ShadowData* shadow = style->textShadow(); FloatPoint textOrigin(fragment.x, fragment.y); - FloatRect shadowRect(FloatPoint(textOrigin.x(), textOrigin.y() - font.ascent()), FloatSize(fragment.width, fragment.height)); + FloatSize textSize(fragment.width, fragment.height); + + if (scalingFactor != 1) { + textOrigin.scale(scalingFactor, scalingFactor); + textSize.scale(scalingFactor); + } + + FloatRect shadowRect(FloatPoint(textOrigin.x(), textOrigin.y() - scaledFont.fontMetrics().floatAscent()), textSize); do { - if (!prepareGraphicsContextForTextPainting(context, textRun, style)) + if (!prepareGraphicsContextForTextPainting(context, scalingFactor, textRun, style)) break; FloatSize extraOffset; if (shadow) extraOffset = applyShadowToGraphicsContext(context, shadow, shadowRect, false /* stroked */, true /* opaque */, true /* horizontal */); - font.drawText(context, textRun, textOrigin + extraOffset, startPosition, endPosition); + if (scalingFactor != 1) + context->scale(FloatSize(1 / scalingFactor, 1 / scalingFactor)); + + scaledFont.drawText(context, textRun, textOrigin + extraOffset, startPosition, endPosition); + + if (scalingFactor != 1) + context->scale(FloatSize(scalingFactor, scalingFactor)); + restoreGraphicsContextAfterTextPainting(context, textRun); if (!shadow) @@ -580,19 +653,18 @@ IntRect SVGInlineTextBox::calculateBoundaries() const { FloatRect textRect; - RenderText* textRenderer = this->textRenderer(); + RenderSVGInlineText* textRenderer = toRenderSVGInlineText(this->textRenderer()); ASSERT(textRenderer); - RenderStyle* style = textRenderer->style(); - ASSERT(style); + float scalingFactor = textRenderer->scalingFactor(); + ASSERT(scalingFactor); - int baseline = baselinePosition(AlphabeticBaseline); - int heightDifference = baseline - style->font().ascent(); + float baseline = textRenderer->scaledFont().fontMetrics().floatAscent() / scalingFactor; unsigned textFragmentsSize = m_textFragments.size(); for (unsigned i = 0; i < textFragmentsSize; ++i) { const SVGTextFragment& fragment = m_textFragments.at(i); - FloatRect fragmentRect(fragment.x, fragment.y - baseline, fragment.width, fragment.height + heightDifference); + FloatRect fragmentRect(fragment.x, fragment.y - baseline, fragment.width, fragment.height); if (!fragment.transform.isIdentity()) fragmentRect = fragment.transform.mapRect(fragmentRect); |