1/*
2 * Copyright (C) Research In Motion Limited 2010. All rights reserved.
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public License
15 * along with this library; see the file COPYING.LIB.  If not, write to
16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18 */
19
20#include "config.h"
21#include "SVGTextLayoutEngineSpacing.h"
22
23#include "Font.h"
24#include "SVGLengthContext.h"
25#include "SVGRenderStyle.h"
26
27#if ENABLE(SVG_FONTS)
28#include "SVGFontData.h"
29#include "SVGFontElement.h"
30#include "SVGFontFaceElement.h"
31#endif
32
33namespace WebCore {
34
35SVGTextLayoutEngineSpacing::SVGTextLayoutEngineSpacing(const Font& font)
36    : m_font(font)
37    , m_lastCharacter(0)
38{
39}
40
41float SVGTextLayoutEngineSpacing::calculateSVGKerning(bool isVerticalText, const SVGTextMetrics::Glyph& currentGlyph)
42{
43#if ENABLE(SVG_FONTS)
44    const SimpleFontData* fontData = m_font.primaryFont();
45    if (!fontData->isSVGFont()) {
46        m_lastGlyph.isValid = false;
47        return 0;
48    }
49
50    ASSERT(fontData->isCustomFont());
51    ASSERT(fontData->isSVGFont());
52
53    const SVGFontData* svgFontData = static_cast<const SVGFontData*>(fontData->fontData());
54    SVGFontFaceElement* svgFontFace = svgFontData->svgFontFaceElement();
55    ASSERT(svgFontFace);
56
57    SVGFontElement* svgFont = svgFontFace->associatedFontElement();
58    if (!svgFont) {
59        m_lastGlyph.isValid = false;
60        return 0;
61    }
62
63    float kerning = 0;
64    if (m_lastGlyph.isValid) {
65        if (isVerticalText)
66            kerning = svgFont->verticalKerningForPairOfStringsAndGlyphs(m_lastGlyph.unicodeString, m_lastGlyph.name, currentGlyph.unicodeString, currentGlyph.name);
67        else
68            kerning = svgFont->horizontalKerningForPairOfStringsAndGlyphs(m_lastGlyph.unicodeString, m_lastGlyph.name, currentGlyph.unicodeString, currentGlyph.name);
69    }
70
71    m_lastGlyph = currentGlyph;
72    m_lastGlyph.isValid = true;
73    kerning *= m_font.size() / m_font.fontMetrics().unitsPerEm();
74    return kerning;
75#else
76    UNUSED_PARAM(isVerticalText);
77    UNUSED_PARAM(currentGlyph);
78    return false;
79#endif
80}
81
82float SVGTextLayoutEngineSpacing::calculateCSSKerningAndSpacing(const SVGRenderStyle* style, SVGElement* contextElement, const UChar* currentCharacter)
83{
84    float kerning = 0;
85    SVGLength kerningLength = style->kerning();
86    if (kerningLength.unitType() == LengthTypePercentage)
87        kerning = kerningLength.valueAsPercentage() * m_font.pixelSize();
88    else {
89        SVGLengthContext lengthContext(contextElement);
90        kerning = kerningLength.value(lengthContext);
91    }
92
93    const UChar* lastCharacter = m_lastCharacter;
94    m_lastCharacter = currentCharacter;
95
96    if (!kerning && !m_font.letterSpacing() && !m_font.wordSpacing())
97        return 0;
98
99    float spacing = m_font.letterSpacing() + kerning;
100    if (currentCharacter && lastCharacter && m_font.wordSpacing()) {
101        if (Font::treatAsSpace(*currentCharacter) && !Font::treatAsSpace(*lastCharacter))
102            spacing += m_font.wordSpacing();
103    }
104
105    return spacing;
106}
107
108}
109