This source file includes following definitions.
- calculateBaselineShift
- dominantBaselineToAlignmentBaseline
- calculateAlignmentBaselineShift
- calculateGlyphOrientationAngle
- glyphOrientationIsMultiplyOf180Degrees
- calculateGlyphAdvanceAndOrientation
#include "config.h"
#include "core/rendering/svg/SVGTextLayoutEngineBaseline.h"
#include "core/rendering/RenderObject.h"
#include "core/rendering/style/SVGRenderStyle.h"
#include "core/rendering/svg/SVGTextMetrics.h"
#include "core/svg/SVGLengthContext.h"
#include "platform/fonts/Font.h"
#include "platform/text/UnicodeRange.h"
namespace WebCore {
SVGTextLayoutEngineBaseline::SVGTextLayoutEngineBaseline(const Font& font)
: m_font(font)
{
}
float SVGTextLayoutEngineBaseline::calculateBaselineShift(const SVGRenderStyle* style, SVGElement* contextElement) const
{
if (style->baselineShift() == BS_LENGTH) {
RefPtr<SVGLength> baselineShiftValueLength = style->baselineShiftValue();
if (baselineShiftValueLength->unitType() == LengthTypePercentage)
return baselineShiftValueLength->valueAsPercentage() * m_font.fontDescription().computedPixelSize();
SVGLengthContext lengthContext(contextElement);
return baselineShiftValueLength->value(lengthContext);
}
switch (style->baselineShift()) {
case BS_BASELINE:
return 0;
case BS_SUB:
return -m_font.fontMetrics().floatHeight() / 2;
case BS_SUPER:
return m_font.fontMetrics().floatHeight() / 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:
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);
}
const FontMetrics& fontMetrics = m_font.fontMetrics();
switch (baseline) {
case AB_BASELINE:
return dominantBaselineToAlignmentBaseline(isVerticalText, textRendererParent);
case AB_BEFORE_EDGE:
case AB_TEXT_BEFORE_EDGE:
return fontMetrics.floatAscent();
case AB_MIDDLE:
return fontMetrics.xHeight() / 2;
case AB_CENTRAL:
return (fontMetrics.floatAscent() - fontMetrics.floatDescent()) / 2;
case AB_AFTER_EDGE:
case AB_TEXT_AFTER_EDGE:
case AB_IDEOGRAPHIC:
return fontMetrics.floatDescent();
case AB_ALPHABETIC:
return 0;
case AB_HANGING:
return fontMetrics.floatAscent() * 8 / 10.f;
case AB_MATHEMATICAL:
return fontMetrics.floatAscent() / 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: {
unsigned 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);
const FontMetrics& fontMetrics = m_font.fontMetrics();
if (isVerticalText) {
float ascentMinusDescent = fontMetrics.floatAscent() - fontMetrics.floatDescent();
if (!angle) {
xOrientationShift = (ascentMinusDescent - metrics.width()) / 2;
yOrientationShift = fontMetrics.floatAscent();
} else if (angle == 180)
xOrientationShift = (ascentMinusDescent + metrics.width()) / 2;
else if (angle == 270) {
yOrientationShift = metrics.width();
xOrientationShift = ascentMinusDescent;
}
if (angle && !orientationIsMultiplyOf180Degrees)
return metrics.width();
return metrics.height();
}
if (angle == 90)
yOrientationShift = -metrics.width();
else if (angle == 180) {
xOrientationShift = metrics.width();
yOrientationShift = -fontMetrics.floatAscent();
} else if (angle == 270)
xOrientationShift = metrics.width();
if (angle && !orientationIsMultiplyOf180Degrees)
return metrics.height();
return metrics.width();
}
}