15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/*
25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) Research In Motion Limited 2010. All rights reserved.
35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * This library is free software; you can redistribute it and/or
55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modify it under the terms of the GNU Library General Public
65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * License as published by the Free Software Foundation; either
75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * version 2 of the License, or (at your option) any later version.
85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * This library is distributed in the hope that it will be useful,
105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * but WITHOUT ANY WARRANTY; without even the implied warranty of
115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Library General Public License for more details.
135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * You should have received a copy of the GNU Library General Public License
155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * along with this library; see the file COPYING.LIB.  If not, write to
165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Boston, MA 02110-1301, USA.
185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "config.h"
215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/svg/SVGTextLayoutEngineBaseline.h"
2353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
2453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/RenderObject.h"
2553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/style/SVGRenderStyle.h"
2653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/svg/SVGTextMetrics.h"
2753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/svg/SVGLengthContext.h"
28a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "platform/fonts/Font.h"
291e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include "platform/text/UnicodeRange.h"
305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)namespace WebCore {
325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)SVGTextLayoutEngineBaseline::SVGTextLayoutEngineBaseline(const Font& font)
345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    : m_font(font)
355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)float SVGTextLayoutEngineBaseline::calculateBaselineShift(const SVGRenderStyle* style, SVGElement* contextElement) const
395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (style->baselineShift() == BS_LENGTH) {
4109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        RefPtr<SVGLength> baselineShiftValueLength = style->baselineShiftValue();
4209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        if (baselineShiftValueLength->unitType() == LengthTypePercentage)
4309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            return baselineShiftValueLength->valueAsPercentage() * m_font.fontDescription().computedPixelSize();
445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        SVGLengthContext lengthContext(contextElement);
4609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        return baselineShiftValueLength->value(lengthContext);
475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    switch (style->baselineShift()) {
505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case BS_BASELINE:
515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return 0;
525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case BS_SUB:
535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return -m_font.fontMetrics().floatHeight() / 2;
545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case BS_SUPER:
555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return m_font.fontMetrics().floatHeight() / 2;
565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    default:
575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ASSERT_NOT_REACHED();
585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return 0;
595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)EAlignmentBaseline SVGTextLayoutEngineBaseline::dominantBaselineToAlignmentBaseline(bool isVerticalText, const RenderObject* textRenderer) const
635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(textRenderer);
655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(textRenderer->style());
665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(textRenderer->parent());
675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(textRenderer->parent()->style());
685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    const SVGRenderStyle* style = textRenderer->style()->svgStyle();
705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(style);
715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    EDominantBaseline baseline = style->dominantBaseline();
735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (baseline == DB_AUTO) {
745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (isVerticalText)
755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            baseline = DB_CENTRAL;
765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        else
775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            baseline = DB_ALPHABETIC;
785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    switch (baseline) {
815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case DB_USE_SCRIPT:
825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // FIXME: The dominant-baseline and the baseline-table components are set by determining the predominant script of the character data content.
835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return AB_ALPHABETIC;
845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case DB_NO_CHANGE:
855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return dominantBaselineToAlignmentBaseline(isVerticalText, textRenderer->parent());
865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case DB_RESET_SIZE:
875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return dominantBaselineToAlignmentBaseline(isVerticalText, textRenderer->parent());
885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case DB_IDEOGRAPHIC:
895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return AB_IDEOGRAPHIC;
905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case DB_ALPHABETIC:
915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return AB_ALPHABETIC;
925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case DB_HANGING:
935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return AB_HANGING;
945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case DB_MATHEMATICAL:
955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return AB_MATHEMATICAL;
965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case DB_CENTRAL:
975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return AB_CENTRAL;
985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case DB_MIDDLE:
995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return AB_MIDDLE;
1005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case DB_TEXT_AFTER_EDGE:
1015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return AB_TEXT_AFTER_EDGE;
1025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case DB_TEXT_BEFORE_EDGE:
1035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return AB_TEXT_BEFORE_EDGE;
1045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    default:
1055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ASSERT_NOT_REACHED();
1065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return AB_AUTO;
1075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)float SVGTextLayoutEngineBaseline::calculateAlignmentBaselineShift(bool isVerticalText, const RenderObject* textRenderer) const
1115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(textRenderer);
1135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(textRenderer->style());
1145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(textRenderer->style()->svgStyle());
1155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(textRenderer->parent());
1165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    const RenderObject* textRendererParent = textRenderer->parent();
1185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(textRendererParent);
1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    EAlignmentBaseline baseline = textRenderer->style()->svgStyle()->alignmentBaseline();
1215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (baseline == AB_AUTO) {
1225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        baseline = dominantBaselineToAlignmentBaseline(isVerticalText, textRendererParent);
1235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ASSERT(baseline != AB_AUTO);
1245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    const FontMetrics& fontMetrics = m_font.fontMetrics();
1275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Note: http://wiki.apache.org/xmlgraphics-fop/LineLayout/AlignmentHandling
1295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    switch (baseline) {
1305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case AB_BASELINE:
1315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return dominantBaselineToAlignmentBaseline(isVerticalText, textRendererParent);
1325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case AB_BEFORE_EDGE:
1335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case AB_TEXT_BEFORE_EDGE:
1345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return fontMetrics.floatAscent();
1355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case AB_MIDDLE:
1365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return fontMetrics.xHeight() / 2;
1375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case AB_CENTRAL:
1385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return (fontMetrics.floatAscent() - fontMetrics.floatDescent()) / 2;
1395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case AB_AFTER_EDGE:
1405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case AB_TEXT_AFTER_EDGE:
1415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case AB_IDEOGRAPHIC:
1425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return fontMetrics.floatDescent();
1435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case AB_ALPHABETIC:
1445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return 0;
1455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case AB_HANGING:
1465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return fontMetrics.floatAscent() * 8 / 10.f;
1475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case AB_MATHEMATICAL:
1485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return fontMetrics.floatAscent() / 2;
1495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    default:
1505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ASSERT_NOT_REACHED();
1515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return 0;
1525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)float SVGTextLayoutEngineBaseline::calculateGlyphOrientationAngle(bool isVerticalText, const SVGRenderStyle* style, const UChar& character) const
1565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(style);
1585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    switch (isVerticalText ? style->glyphOrientationVertical() : style->glyphOrientationHorizontal()) {
1605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case GO_AUTO: {
1615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Spec: Fullwidth ideographic and fullwidth Latin text will be set with a glyph-orientation of 0-degrees.
1625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Text which is not fullwidth will be set with a glyph-orientation of 90-degrees.
16307a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        unsigned unicodeRange = findCharUnicodeRange(character);
1645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (unicodeRange == cRangeSetLatin || unicodeRange == cRangeArabic)
1655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return 90;
1665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return 0;
1685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case GO_90DEG:
1705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return 90;
1715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case GO_180DEG:
1725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return 180;
1735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case GO_270DEG:
1745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return 270;
1755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case GO_0DEG:
1765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    default:
1775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return 0;
1785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static inline bool glyphOrientationIsMultiplyOf180Degrees(float orientationAngle)
1825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return !fabsf(fmodf(orientationAngle, 180));
1845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)float SVGTextLayoutEngineBaseline::calculateGlyphAdvanceAndOrientation(bool isVerticalText, SVGTextMetrics& metrics, float angle, float& xOrientationShift, float& yOrientationShift) const
1875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool orientationIsMultiplyOf180Degrees = glyphOrientationIsMultiplyOf180Degrees(angle);
1895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // The function is based on spec requirements:
1915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    //
1925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Spec: If the 'glyph-orientation-horizontal' results in an orientation angle that is not a multiple of
1935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // of 180 degrees, then the current text position is incremented according to the vertical metrics of the glyph.
1945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    //
1955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Spec: If if the 'glyph-orientation-vertical' results in an orientation angle that is not a multiple of
1965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // 180 degrees, then the current text position is incremented according to the horizontal metrics of the glyph.
1975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    const FontMetrics& fontMetrics = m_font.fontMetrics();
1995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Vertical orientation handling.
2015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (isVerticalText) {
2025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        float ascentMinusDescent = fontMetrics.floatAscent() - fontMetrics.floatDescent();
2035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!angle) {
2045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            xOrientationShift = (ascentMinusDescent - metrics.width()) / 2;
2055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            yOrientationShift = fontMetrics.floatAscent();
2065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        } else if (angle == 180)
2075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            xOrientationShift = (ascentMinusDescent + metrics.width()) / 2;
2085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        else if (angle == 270) {
2095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            yOrientationShift = metrics.width();
2105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            xOrientationShift = ascentMinusDescent;
2115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
2125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Vertical advance calculation.
2145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (angle && !orientationIsMultiplyOf180Degrees)
2155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return metrics.width();
2165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return metrics.height();
2185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Horizontal orientation handling.
2215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (angle == 90)
2225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        yOrientationShift = -metrics.width();
2235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else if (angle == 180) {
2245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        xOrientationShift = metrics.width();
2255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        yOrientationShift = -fontMetrics.floatAscent();
2265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    } else if (angle == 270)
2275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        xOrientationShift = metrics.width();
2285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Horizontal advance calculation.
2305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (angle && !orientationIsMultiplyOf180Degrees)
2315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return metrics.height();
2325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return metrics.width();
2345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
237