diff options
author | Steve Block <steveblock@google.com> | 2011-05-06 11:45:16 +0100 |
---|---|---|
committer | Steve Block <steveblock@google.com> | 2011-05-12 13:44:10 +0100 |
commit | cad810f21b803229eb11403f9209855525a25d57 (patch) | |
tree | 29a6fd0279be608e0fe9ffe9841f722f0f4e4269 /Source/WebCore/rendering/svg/SVGTextLayoutEngineBaseline.cpp | |
parent | 121b0cf4517156d0ac5111caf9830c51b69bae8f (diff) | |
download | external_webkit-cad810f21b803229eb11403f9209855525a25d57.zip external_webkit-cad810f21b803229eb11403f9209855525a25d57.tar.gz external_webkit-cad810f21b803229eb11403f9209855525a25d57.tar.bz2 |
Merge WebKit at r75315: Initial merge by git.
Change-Id: I570314b346ce101c935ed22a626b48c2af266b84
Diffstat (limited to 'Source/WebCore/rendering/svg/SVGTextLayoutEngineBaseline.cpp')
-rw-r--r-- | Source/WebCore/rendering/svg/SVGTextLayoutEngineBaseline.cpp | 234 |
1 files changed, 234 insertions, 0 deletions
diff --git a/Source/WebCore/rendering/svg/SVGTextLayoutEngineBaseline.cpp b/Source/WebCore/rendering/svg/SVGTextLayoutEngineBaseline.cpp new file mode 100644 index 0000000..7060ac6 --- /dev/null +++ b/Source/WebCore/rendering/svg/SVGTextLayoutEngineBaseline.cpp @@ -0,0 +1,234 @@ +/* + * Copyright (C) Research In Motion Limited 2010. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "config.h" + +#if ENABLE(SVG) +#include "SVGTextLayoutEngineBaseline.h" + +#include "Font.h" +#include "RenderObject.h" +#include "SVGRenderStyle.h" +#include "SVGTextMetrics.h" +#include "UnicodeRange.h" + +namespace WebCore { + +SVGTextLayoutEngineBaseline::SVGTextLayoutEngineBaseline(const Font& font) + : m_font(font) +{ +} + +float SVGTextLayoutEngineBaseline::calculateBaselineShift(const SVGRenderStyle* style, SVGElement* lengthContext) const +{ + if (style->baselineShift() == BS_LENGTH) { + SVGLength baselineShiftValueLength = style->baselineShiftValue(); + if (baselineShiftValueLength.unitType() == LengthTypePercentage) + return baselineShiftValueLength.valueAsPercentage() * m_font.pixelSize(); + + return baselineShiftValueLength.value(lengthContext); + } + + switch (style->baselineShift()) { + case BS_BASELINE: + return 0; + case BS_SUB: + return -m_font.height() / 2; + case BS_SUPER: + return m_font.height() / 2; + default: + ASSERT_NOT_REACHED(); + return 0; + } +} + +EAlignmentBaseline SVGTextLayoutEngineBaseline::dominantBaselineToAlignmentBaseline(bool isVerticalText, const RenderObject* textRenderer) const +{ + ASSERT(textRenderer); + ASSERT(textRenderer->style()); + ASSERT(textRenderer->parent()); + ASSERT(textRenderer->parent()->style()); + + const SVGRenderStyle* style = textRenderer->style()->svgStyle(); + ASSERT(style); + + EDominantBaseline baseline = style->dominantBaseline(); + if (baseline == DB_AUTO) { + if (isVerticalText) + baseline = DB_CENTRAL; + else + baseline = DB_ALPHABETIC; + } + + switch (baseline) { + case DB_USE_SCRIPT: + // FIXME: The dominant-baseline and the baseline-table components are set by determining the predominant script of the character data content. + return AB_ALPHABETIC; + case DB_NO_CHANGE: + return dominantBaselineToAlignmentBaseline(isVerticalText, textRenderer->parent()); + case DB_RESET_SIZE: + return dominantBaselineToAlignmentBaseline(isVerticalText, textRenderer->parent()); + case DB_IDEOGRAPHIC: + return AB_IDEOGRAPHIC; + case DB_ALPHABETIC: + return AB_ALPHABETIC; + case DB_HANGING: + return AB_HANGING; + case DB_MATHEMATICAL: + return AB_MATHEMATICAL; + case DB_CENTRAL: + return AB_CENTRAL; + case DB_MIDDLE: + return AB_MIDDLE; + case DB_TEXT_AFTER_EDGE: + return AB_TEXT_AFTER_EDGE; + case DB_TEXT_BEFORE_EDGE: + return AB_TEXT_BEFORE_EDGE; + default: + ASSERT_NOT_REACHED(); + return AB_AUTO; + } +} + +float SVGTextLayoutEngineBaseline::calculateAlignmentBaselineShift(bool isVerticalText, const RenderObject* textRenderer) const +{ + ASSERT(textRenderer); + ASSERT(textRenderer->style()); + ASSERT(textRenderer->style()->svgStyle()); + ASSERT(textRenderer->parent()); + + const RenderObject* textRendererParent = textRenderer->parent(); + ASSERT(textRendererParent); + + EAlignmentBaseline baseline = textRenderer->style()->svgStyle()->alignmentBaseline(); + if (baseline == AB_AUTO) { + baseline = dominantBaselineToAlignmentBaseline(isVerticalText, textRendererParent); + ASSERT(baseline != AB_AUTO); + } + + // Note: http://wiki.apache.org/xmlgraphics-fop/LineLayout/AlignmentHandling + switch (baseline) { + case AB_BASELINE: + return dominantBaselineToAlignmentBaseline(isVerticalText, textRendererParent); + case AB_BEFORE_EDGE: + case AB_TEXT_BEFORE_EDGE: + return m_font.ascent(); + case AB_MIDDLE: + return m_font.xHeight() / 2; + case AB_CENTRAL: + return (m_font.ascent() - m_font.descent()) / 2; + case AB_AFTER_EDGE: + case AB_TEXT_AFTER_EDGE: + case AB_IDEOGRAPHIC: + return m_font.descent(); + case AB_ALPHABETIC: + return 0; + case AB_HANGING: + return m_font.ascent() * 8 / 10.f; + case AB_MATHEMATICAL: + return m_font.ascent() / 2; + default: + ASSERT_NOT_REACHED(); + return 0; + } +} + +float SVGTextLayoutEngineBaseline::calculateGlyphOrientationAngle(bool isVerticalText, const SVGRenderStyle* style, const UChar& character) const +{ + ASSERT(style); + + switch (isVerticalText ? style->glyphOrientationVertical() : style->glyphOrientationHorizontal()) { + case GO_AUTO: + { + // Spec: Fullwidth ideographic and fullwidth Latin text will be set with a glyph-orientation of 0-degrees. + // Text which is not fullwidth will be set with a glyph-orientation of 90-degrees. + unsigned int unicodeRange = findCharUnicodeRange(character); + if (unicodeRange == cRangeSetLatin || unicodeRange == cRangeArabic) + return 90; + + return 0; + } + case GO_90DEG: + return 90; + case GO_180DEG: + return 180; + case GO_270DEG: + return 270; + case GO_0DEG: + default: + return 0; + } +} + +static inline bool glyphOrientationIsMultiplyOf180Degrees(float orientationAngle) +{ + return !fabsf(fmodf(orientationAngle, 180)); +} + +float SVGTextLayoutEngineBaseline::calculateGlyphAdvanceAndOrientation(bool isVerticalText, SVGTextMetrics& metrics, float angle, float& xOrientationShift, float& yOrientationShift) const +{ + bool orientationIsMultiplyOf180Degrees = glyphOrientationIsMultiplyOf180Degrees(angle); + + // The function is based on spec requirements: + // + // Spec: If the 'glyph-orientation-horizontal' results in an orientation angle that is not a multiple of + // of 180 degrees, then the current text position is incremented according to the vertical metrics of the glyph. + // + // Spec: If if the 'glyph-orientation-vertical' results in an orientation angle that is not a multiple of + // 180 degrees, then the current text position is incremented according to the horizontal metrics of the glyph. + + // Vertical orientation handling. + if (isVerticalText) { + float ascentMinusDescent = m_font.ascent() - m_font.descent(); + if (!angle) { + xOrientationShift = (ascentMinusDescent - metrics.width()) / 2; + yOrientationShift = m_font.ascent(); + } else if (angle == 180) + xOrientationShift = (ascentMinusDescent + metrics.width()) / 2; + else if (angle == 270) { + yOrientationShift = metrics.width(); + xOrientationShift = ascentMinusDescent; + } + + // Vertical advance calculation. + if (angle && !orientationIsMultiplyOf180Degrees) + return metrics.width(); + + return metrics.height(); + } + + // Horizontal orientation handling. + if (angle == 90) + yOrientationShift = -metrics.width(); + else if (angle == 180) { + xOrientationShift = metrics.width(); + yOrientationShift = -m_font.ascent(); + } else if (angle == 270) + xOrientationShift = metrics.width(); + + // Horizontal advance calculation. + if (angle && !orientationIsMultiplyOf180Degrees) + return metrics.height(); + + return metrics.width(); +} + +} + +#endif // ENABLE(SVG) |