Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / svg / SVGFontData.cpp
1 /*
2  * Copyright (C) 2008 Nikolas Zimmermann <zimmermann@kde.org>
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
22 #if ENABLE(SVG_FONTS)
23 #include "core/svg/SVGFontData.h"
24
25 #include "SVGNames.h"
26 #include "XMLNames.h"
27 #include "core/rendering/RenderObject.h"
28 #include "core/rendering/svg/SVGTextRunRenderingContext.h"
29 #include "core/svg/SVGAltGlyphElement.h"
30 #include "core/svg/SVGFontElement.h"
31 #include "core/svg/SVGFontFaceElement.h"
32 #include "core/svg/SVGGlyphElement.h"
33 #include "platform/fonts/Character.h"
34 #include "platform/fonts/SVGGlyph.h"
35 #include "platform/fonts/SimpleFontData.h"
36 #include "platform/fonts/WidthIterator.h"
37 #include "platform/text/TextRun.h"
38 #include "wtf/text/StringBuilder.h"
39 #include "wtf/unicode/CharacterNames.h"
40 #include "wtf/unicode/Unicode.h"
41
42 using namespace WTF;
43 using namespace Unicode;
44
45 namespace WebCore {
46
47 SVGFontData::SVGFontData(SVGFontFaceElement* fontFaceElement)
48     : CustomFontData(false)
49     , m_svgFontFaceElement(fontFaceElement)
50     , m_horizontalOriginX(fontFaceElement->horizontalOriginX())
51     , m_horizontalOriginY(fontFaceElement->horizontalOriginY())
52     , m_horizontalAdvanceX(fontFaceElement->horizontalAdvanceX())
53     , m_verticalOriginX(fontFaceElement->verticalOriginX())
54     , m_verticalOriginY(fontFaceElement->verticalOriginY())
55     , m_verticalAdvanceY(fontFaceElement->verticalAdvanceY())
56 {
57     ASSERT_ARG(fontFaceElement, fontFaceElement);
58 }
59
60 void SVGFontData::initializeFontData(SimpleFontData* fontData, float fontSize)
61 {
62     ASSERT(fontData);
63
64     SVGFontFaceElement* svgFontFaceElement = this->svgFontFaceElement();
65     ASSERT(svgFontFaceElement);
66
67     SVGFontElement* svgFontElement = svgFontFaceElement->associatedFontElement();
68     ASSERT(svgFontElement);
69     GlyphData missingGlyphData;
70     missingGlyphData.fontData = fontData;
71     missingGlyphData.glyph = svgFontElement->missingGlyph();
72     fontData->setMissingGlyphData(missingGlyphData);
73
74     fontData->setZeroWidthSpaceGlyph(0);
75     fontData->determinePitch();
76
77     unsigned unitsPerEm = svgFontFaceElement->unitsPerEm();
78     float scale = scaleEmToUnits(fontSize, unitsPerEm);
79     float xHeight = svgFontFaceElement->xHeight() * scale;
80     float ascent = svgFontFaceElement->ascent() * scale;
81     float descent = svgFontFaceElement->descent() * scale;
82     float lineGap = 0.1f * fontSize;
83
84     GlyphPage* glyphPageZero = GlyphPageTreeNode::getRootChild(fontData, 0)->page();
85
86     if (!xHeight && glyphPageZero) {
87         // Fallback if x_heightAttr is not specified for the font element.
88         Glyph letterXGlyph = glyphPageZero->glyphForCharacter('x');
89         xHeight = letterXGlyph ? fontData->widthForGlyph(letterXGlyph) : 2 * ascent / 3;
90     }
91
92     FontMetrics& fontMetrics = fontData->fontMetrics();
93     fontMetrics.setUnitsPerEm(unitsPerEm);
94     fontMetrics.setAscent(ascent);
95     fontMetrics.setDescent(descent);
96     fontMetrics.setLineGap(lineGap);
97     fontMetrics.setLineSpacing(roundf(ascent) + roundf(descent) + roundf(lineGap));
98     fontMetrics.setXHeight(xHeight);
99
100     if (!glyphPageZero) {
101         fontData->setSpaceGlyph(0);
102         fontData->setSpaceWidth(0);
103         fontData->setAvgCharWidth(0);
104         fontData->setMaxCharWidth(ascent);
105         return;
106     }
107
108     // Calculate space width.
109     Glyph spaceGlyph = glyphPageZero->glyphForCharacter(' ');
110     fontData->setSpaceGlyph(spaceGlyph);
111     fontData->setSpaceWidth(fontData->widthForGlyph(spaceGlyph));
112
113     // Estimate average character width.
114     Glyph numeralZeroGlyph = glyphPageZero->glyphForCharacter('0');
115     fontData->setAvgCharWidth(numeralZeroGlyph ? fontData->widthForGlyph(numeralZeroGlyph) : fontData->spaceWidth());
116
117     // Estimate maximum character width.
118     Glyph letterWGlyph = glyphPageZero->glyphForCharacter('W');
119     fontData->setMaxCharWidth(letterWGlyph ? fontData->widthForGlyph(letterWGlyph) : ascent);
120 }
121
122 float SVGFontData::widthForSVGGlyph(Glyph glyph, float fontSize) const
123 {
124     SVGFontFaceElement* svgFontFaceElement = this->svgFontFaceElement();
125     ASSERT(svgFontFaceElement);
126
127     SVGFontElement* associatedFontElement = svgFontFaceElement->associatedFontElement();
128     ASSERT(associatedFontElement);
129
130     SVGGlyph svgGlyph = associatedFontElement->svgGlyphForGlyph(glyph);
131     SVGGlyphElement::inheritUnspecifiedAttributes(svgGlyph, this);
132     return svgGlyph.horizontalAdvanceX * scaleEmToUnits(fontSize, svgFontFaceElement->unitsPerEm());
133 }
134
135 bool SVGFontData::applySVGGlyphSelection(WidthIterator& iterator, GlyphData& glyphData, bool mirror, int currentCharacter, unsigned& advanceLength) const
136 {
137     const TextRun& run = iterator.run();
138     Vector<SVGGlyph::ArabicForm>& arabicForms = iterator.arabicForms();
139     ASSERT(int(run.charactersLength()) >= currentCharacter);
140
141     // Associate text with arabic forms, if needed.
142     String remainingTextInRun;
143
144     if (run.is8Bit()) {
145         remainingTextInRun = String(run.data8(currentCharacter), run.charactersLength() - currentCharacter);
146         remainingTextInRun = Character::normalizeSpaces(remainingTextInRun.characters8(), remainingTextInRun.length());
147     } else {
148         remainingTextInRun = String(run.data16(currentCharacter), run.charactersLength() - currentCharacter);
149         remainingTextInRun = Character::normalizeSpaces(remainingTextInRun.characters16(), remainingTextInRun.length());
150     }
151
152     if (mirror)
153         remainingTextInRun = createStringWithMirroredCharacters(remainingTextInRun);
154     if (!currentCharacter && arabicForms.isEmpty())
155         arabicForms = charactersWithArabicForm(remainingTextInRun, mirror);
156
157     SVGFontFaceElement* svgFontFaceElement = this->svgFontFaceElement();
158     ASSERT(svgFontFaceElement);
159
160     SVGFontElement* associatedFontElement = svgFontFaceElement->associatedFontElement();
161     ASSERT(associatedFontElement);
162
163     RenderObject* renderObject = 0;
164     if (TextRun::RenderingContext* renderingContext = run.renderingContext())
165         renderObject = static_cast<SVGTextRunRenderingContext*>(renderingContext)->renderer();
166
167     String language;
168     bool isVerticalText = false;
169     Vector<AtomicString> altGlyphNames;
170
171     if (renderObject) {
172         RenderObject* parentRenderObject = renderObject->isText() ? renderObject->parent() : renderObject;
173         ASSERT(parentRenderObject);
174
175         isVerticalText = parentRenderObject->style()->svgStyle()->isVerticalWritingMode();
176         if (Element* parentRenderObjectElement = toElement(parentRenderObject->node())) {
177             language = parentRenderObjectElement->getAttribute(XMLNames::langAttr);
178
179             if (parentRenderObjectElement->hasTagName(SVGNames::altGlyphTag)) {
180                 if (!toSVGAltGlyphElement(parentRenderObjectElement)->hasValidGlyphElements(altGlyphNames))
181                     altGlyphNames.clear();
182             }
183         }
184     }
185
186     Vector<SVGGlyph> glyphs;
187     size_t altGlyphNamesSize = altGlyphNames.size();
188     if (altGlyphNamesSize) {
189         for (size_t index = 0; index < altGlyphNamesSize; ++index)
190             associatedFontElement->collectGlyphsForGlyphName(altGlyphNames[index], glyphs);
191
192         // Assign the unicodeStringLength now that its known.
193         size_t glyphsSize = glyphs.size();
194         for (size_t i = 0; i < glyphsSize; ++i)
195             glyphs[i].unicodeStringLength = run.length();
196
197         // Do not check alt glyphs for compatibility. Just return the first one.
198         // Later code will fail if we do not do this and the glyph is incompatible.
199         if (glyphsSize) {
200             SVGGlyph& svgGlyph = glyphs[0];
201             iterator.setLastGlyphName(svgGlyph.glyphName);
202             glyphData.glyph = svgGlyph.tableEntry;
203             advanceLength = svgGlyph.unicodeStringLength;
204             return true;
205         }
206     } else
207         associatedFontElement->collectGlyphsForString(remainingTextInRun, glyphs);
208
209     size_t glyphsSize = glyphs.size();
210     for (size_t i = 0; i < glyphsSize; ++i) {
211         SVGGlyph& svgGlyph = glyphs[i];
212         if (svgGlyph.isPartOfLigature)
213             continue;
214         if (!isCompatibleGlyph(svgGlyph, isVerticalText, language, arabicForms, currentCharacter, currentCharacter + svgGlyph.unicodeStringLength))
215             continue;
216         iterator.setLastGlyphName(svgGlyph.glyphName);
217         glyphData.glyph = svgGlyph.tableEntry;
218         advanceLength = svgGlyph.unicodeStringLength;
219         return true;
220     }
221
222     iterator.setLastGlyphName(String());
223     return false;
224 }
225
226 bool SVGFontData::fillSVGGlyphPage(GlyphPage* pageToFill, unsigned offset, unsigned length, UChar* buffer, unsigned bufferLength, const SimpleFontData* fontData) const
227 {
228     ASSERT(fontData->isCustomFont());
229     ASSERT(fontData->isSVGFont());
230
231     SVGFontFaceElement* fontFaceElement = this->svgFontFaceElement();
232     ASSERT(fontFaceElement);
233
234     SVGFontElement* fontElement = fontFaceElement->associatedFontElement();
235     ASSERT(fontElement);
236
237     if (bufferLength == length)
238         return fillBMPGlyphs(fontElement, pageToFill, offset, length, buffer, fontData);
239
240     ASSERT(bufferLength == 2 * length);
241     return fillNonBMPGlyphs(fontElement, pageToFill, offset, length, buffer, fontData);
242 }
243
244 bool SVGFontData::fillBMPGlyphs(SVGFontElement* fontElement, GlyphPage* pageToFill, unsigned offset, unsigned length, UChar* buffer, const SimpleFontData* fontData) const
245 {
246     bool haveGlyphs = false;
247     Vector<SVGGlyph> glyphs;
248     for (unsigned i = 0; i < length; ++i) {
249         String lookupString(buffer + i, 1);
250         fontElement->collectGlyphsForString(lookupString, glyphs);
251         if (glyphs.isEmpty()) {
252             pageToFill->setGlyphDataForIndex(offset + i, 0, 0);
253             continue;
254         }
255
256         // Associate entry in glyph page with first valid SVGGlyph.
257         // If there are multiple valid ones, just take the first one. WidthIterator will take
258         // care of matching to the correct glyph, if multiple ones are available, as that's
259         // only possible within the context of a string (eg. arabic form matching).
260         haveGlyphs = true;
261         pageToFill->setGlyphDataForIndex(offset + i, glyphs.first().tableEntry, fontData);
262         glyphs.clear();
263     }
264
265     return haveGlyphs;
266 }
267
268 bool SVGFontData::fillNonBMPGlyphs(SVGFontElement* fontElement, GlyphPage* pageToFill, unsigned offset, unsigned length, UChar* buffer, const SimpleFontData* fontData) const
269 {
270     bool haveGlyphs = false;
271     Vector<SVGGlyph> glyphs;
272     for (unsigned i = 0; i < length; ++i) {
273         // Each character here consists of a surrogate pair
274         String lookupString(buffer + i * 2, 2);
275         fontElement->collectGlyphsForString(lookupString, glyphs);
276         if (glyphs.isEmpty()) {
277             pageToFill->setGlyphDataForIndex(offset + i, 0, 0);
278             continue;
279         }
280
281         // Associate entry in glyph page with first valid SVGGlyph.
282         // If there are multiple valid ones, just take the first one. WidthIterator will take
283         // care of matching to the correct glyph, if multiple ones are available, as that's
284         // only possible within the context of a string (eg. arabic form matching).
285         haveGlyphs = true;
286         pageToFill->setGlyphDataForIndex(offset + i, glyphs.first().tableEntry, fontData);
287         glyphs.clear();
288     }
289
290     return haveGlyphs;
291 }
292
293 String SVGFontData::createStringWithMirroredCharacters(const String& string) const
294 {
295     if (string.isEmpty())
296         return emptyString();
297
298     unsigned length = string.length();
299
300     StringBuilder mirroredCharacters;
301     mirroredCharacters.reserveCapacity(length);
302
303     if (string.is8Bit()) {
304         const LChar* characters = string.characters8();
305         for (unsigned i = 0; i < length; ++i)
306             mirroredCharacters.append(mirroredChar(characters[i]));
307     } else {
308         const UChar* characters = string.characters16();
309         unsigned i = 0;
310         while (i < length) {
311             UChar32 character;
312             U16_NEXT(characters, i, length, character);
313             mirroredCharacters.append(mirroredChar(character));
314         }
315     }
316
317     return mirroredCharacters.toString();
318 }
319
320 } // namespace WebCore
321
322 #endif