Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(44)

Side by Side Diff: Source/core/svg/SVGFontFaceElement.cpp

Issue 656913006: Remove SVG fonts (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Update tests for landing Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 /*
2 * Copyright (C) 2007 Eric Seidel <eric@webkit.org>
3 * Copyright (C) 2007, 2008 Nikolas Zimmermann <zimmermann@kde.org>
4 * Copyright (C) 2008 Apple Inc. All rights reserved.
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
15 *
16 * You should have received a copy of the GNU Library General Public License
17 * along with this library; see the file COPYING.LIB. If not, write to
18 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
20 */
21
22 #include "config.h"
23
24 #if ENABLE(SVG_FONTS)
25 #include "core/svg/SVGFontFaceElement.h"
26
27 #include "core/CSSPropertyNames.h"
28 #include "core/CSSValueKeywords.h"
29 #include "core/css/CSSFontFaceSrcValue.h"
30 #include "core/css/CSSFontSelector.h"
31 #include "core/css/CSSStyleSheet.h"
32 #include "core/css/CSSValueList.h"
33 #include "core/css/StylePropertySet.h"
34 #include "core/css/StyleRule.h"
35 #include "core/css/parser/CSSParser.h"
36 #include "core/dom/Attribute.h"
37 #include "core/dom/Document.h"
38 #include "core/dom/StyleEngine.h"
39 #include "core/svg/SVGDocumentExtensions.h"
40 #include "core/svg/SVGFontElement.h"
41 #include "core/svg/SVGFontFaceSrcElement.h"
42 #include "core/svg/SVGGlyphElement.h"
43 #include "platform/fonts/Font.h"
44 #include <math.h>
45
46 namespace blink {
47
48 using namespace SVGNames;
49
50 inline SVGFontFaceElement::SVGFontFaceElement(Document& document)
51 : SVGElement(font_faceTag, document)
52 , m_fontFaceRule(StyleRuleFontFace::create())
53 , m_fontElement(nullptr)
54 , m_weakFactory(this)
55 {
56 RefPtrWillBeRawPtr<MutableStylePropertySet> styleDeclaration = MutableStyleP ropertySet::create(HTMLStandardMode);
57 m_fontFaceRule->setProperties(styleDeclaration.release());
58 }
59
60 DEFINE_NODE_FACTORY(SVGFontFaceElement)
61
62 static CSSPropertyID cssPropertyIdForFontFaceAttributeName(const QualifiedName& attrName)
63 {
64 if (!attrName.namespaceURI().isNull())
65 return CSSPropertyInvalid;
66
67 static HashMap<StringImpl*, CSSPropertyID>* propertyNameToIdMap = 0;
68 if (!propertyNameToIdMap) {
69 propertyNameToIdMap = new HashMap<StringImpl*, CSSPropertyID>;
70 // This is a list of all @font-face CSS properties which are exposed as SVG XML attributes
71 // Those commented out are not yet supported by WebCore's style system
72 const QualifiedName* const attrNames[] = {
73 // &accent_heightAttr,
74 // &alphabeticAttr,
75 // &ascentAttr,
76 // &bboxAttr,
77 // &cap_heightAttr,
78 // &descentAttr,
79 &font_familyAttr,
80 &font_sizeAttr,
81 &font_stretchAttr,
82 &font_styleAttr,
83 &font_variantAttr,
84 &font_weightAttr,
85 // &hangingAttr,
86 // &ideographicAttr,
87 // &mathematicalAttr,
88 // &overline_positionAttr,
89 // &overline_thicknessAttr,
90 // &panose_1Attr,
91 // &slopeAttr,
92 // &stemhAttr,
93 // &stemvAttr,
94 // &strikethrough_positionAttr,
95 // &strikethrough_thicknessAttr,
96 // &underline_positionAttr,
97 // &underline_thicknessAttr,
98 // &unicode_rangeAttr,
99 // &units_per_emAttr,
100 // &v_alphabeticAttr,
101 // &v_hangingAttr,
102 // &v_ideographicAttr,
103 // &v_mathematicalAttr,
104 // &widthsAttr,
105 // &x_heightAttr,
106 };
107 for (size_t i = 0; i < WTF_ARRAY_LENGTH(attrNames); i++) {
108 CSSPropertyID propertyId = cssPropertyID(attrNames[i]->localName());
109 ASSERT(propertyId > 0);
110 propertyNameToIdMap->set(attrNames[i]->localName().impl(), propertyI d);
111 }
112 }
113
114 return propertyNameToIdMap->get(attrName.localName().impl());
115 }
116
117 void SVGFontFaceElement::parseAttribute(const QualifiedName& name, const AtomicS tring& value)
118 {
119 CSSPropertyID propId = cssPropertyIdForFontFaceAttributeName(name);
120 if (propId > 0) {
121 m_fontFaceRule->mutableProperties().setProperty(propId, value, false);
122 rebuildFontFace();
123 return;
124 }
125
126 SVGElement::parseAttribute(name, value);
127 }
128
129 unsigned SVGFontFaceElement::unitsPerEm() const
130 {
131 const AtomicString& value = fastGetAttribute(units_per_emAttr);
132 if (value.isEmpty())
133 return gDefaultUnitsPerEm;
134
135 return static_cast<unsigned>(ceilf(value.toFloat()));
136 }
137
138 int SVGFontFaceElement::xHeight() const
139 {
140 return static_cast<int>(ceilf(fastGetAttribute(x_heightAttr).toFloat()));
141 }
142
143 float SVGFontFaceElement::horizontalOriginX() const
144 {
145 if (!m_fontElement)
146 return 0.0f;
147
148 // Spec: The X-coordinate in the font coordinate system of the origin of a g lyph to be used when
149 // drawing horizontally oriented text. (Note that the origin applies to all glyphs in the font.)
150 // If the attribute is not specified, the effect is as if a value of "0" wer e specified.
151 return m_fontElement->fastGetAttribute(horiz_origin_xAttr).toFloat();
152 }
153
154 float SVGFontFaceElement::horizontalOriginY() const
155 {
156 if (!m_fontElement)
157 return 0.0f;
158
159 // Spec: The Y-coordinate in the font coordinate system of the origin of a g lyph to be used when
160 // drawing horizontally oriented text. (Note that the origin applies to all glyphs in the font.)
161 // If the attribute is not specified, the effect is as if a value of "0" wer e specified.
162 return m_fontElement->fastGetAttribute(horiz_origin_yAttr).toFloat();
163 }
164
165 float SVGFontFaceElement::horizontalAdvanceX() const
166 {
167 if (!m_fontElement)
168 return 0.0f;
169
170 // Spec: The default horizontal advance after rendering a glyph in horizonta l orientation. Glyph
171 // widths are required to be non-negative, even if the glyph is typically re ndered right-to-left,
172 // as in Hebrew and Arabic scripts.
173 return m_fontElement->fastGetAttribute(horiz_adv_xAttr).toFloat();
174 }
175
176 float SVGFontFaceElement::verticalOriginX() const
177 {
178 if (!m_fontElement)
179 return 0.0f;
180
181 // Spec: The default X-coordinate in the font coordinate system of the origi n of a glyph to be used when
182 // drawing vertically oriented text. If the attribute is not specified, the effect is as if the attribute
183 // were set to half of the effective value of attribute horiz-adv-x.
184 const AtomicString& value = m_fontElement->fastGetAttribute(vert_origin_xAtt r);
185 if (value.isEmpty())
186 return horizontalAdvanceX() / 2.0f;
187
188 return value.toFloat();
189 }
190
191 float SVGFontFaceElement::verticalOriginY() const
192 {
193 if (!m_fontElement)
194 return 0.0f;
195
196 // Spec: The default Y-coordinate in the font coordinate system of the origi n of a glyph to be used when
197 // drawing vertically oriented text. If the attribute is not specified, the effect is as if the attribute
198 // were set to the position specified by the font's ascent attribute.
199 const AtomicString& value = m_fontElement->fastGetAttribute(vert_origin_yAtt r);
200 if (value.isEmpty())
201 return ascent();
202
203 return value.toFloat();
204 }
205
206 float SVGFontFaceElement::verticalAdvanceY() const
207 {
208 if (!m_fontElement)
209 return 0.0f;
210
211 // Spec: The default vertical advance after rendering a glyph in vertical or ientation. If the attribute is
212 // not specified, the effect is as if a value equivalent of one em were spec ified (see units-per-em).
213 const AtomicString& value = m_fontElement->fastGetAttribute(vert_adv_yAttr);
214 if (value.isEmpty())
215 return 1.0f;
216
217 return value.toFloat();
218 }
219
220 int SVGFontFaceElement::ascent() const
221 {
222 // Spec: Same syntax and semantics as the 'ascent' descriptor within an @fon t-face rule. The maximum
223 // unaccented height of the font within the font coordinate system. If the a ttribute is not specified,
224 // the effect is as if the attribute were set to the difference between the units-per-em value and the
225 // vert-origin-y value for the corresponding font.
226 const AtomicString& ascentValue = fastGetAttribute(ascentAttr);
227 if (!ascentValue.isEmpty())
228 return static_cast<int>(ceilf(ascentValue.toFloat()));
229
230 if (m_fontElement) {
231 const AtomicString& vertOriginY = m_fontElement->fastGetAttribute(vert_o rigin_yAttr);
232 if (!vertOriginY.isEmpty())
233 return static_cast<int>(unitsPerEm()) - static_cast<int>(ceilf(vertO riginY.toFloat()));
234 }
235
236 // Match Batiks default value
237 return static_cast<int>(ceilf(unitsPerEm() * 0.8f));
238 }
239
240 int SVGFontFaceElement::descent() const
241 {
242 // Spec: Same syntax and semantics as the 'descent' descriptor within an @fo nt-face rule. The maximum
243 // unaccented depth of the font within the font coordinate system. If the at tribute is not specified,
244 // the effect is as if the attribute were set to the vert-origin-y value for the corresponding font.
245 const AtomicString& descentValue = fastGetAttribute(descentAttr);
246 if (!descentValue.isEmpty()) {
247 // 14 different W3C SVG 1.1 testcases use a negative descent value,
248 // where a positive was meant to be used Including:
249 // animate-elem-24-t.svg, fonts-elem-01-t.svg, fonts-elem-02-t.svg (and 11 others)
250 int descent = static_cast<int>(ceilf(descentValue.toFloat()));
251 return descent < 0 ? -descent : descent;
252 }
253
254 if (m_fontElement) {
255 const AtomicString& vertOriginY = m_fontElement->fastGetAttribute(vert_o rigin_yAttr);
256 if (!vertOriginY.isEmpty())
257 return static_cast<int>(ceilf(vertOriginY.toFloat()));
258 }
259
260 // Match Batiks default value
261 return static_cast<int>(ceilf(unitsPerEm() * 0.2f));
262 }
263
264 String SVGFontFaceElement::fontFamily() const
265 {
266 return m_fontFaceRule->properties().getPropertyValue(CSSPropertyFontFamily);
267 }
268
269 SVGFontElement* SVGFontFaceElement::associatedFontElement() const
270 {
271 ASSERT(parentNode() == m_fontElement);
272 ASSERT(!parentNode() || isSVGFontElement(*parentNode()));
273 return m_fontElement;
274 }
275
276 void SVGFontFaceElement::rebuildFontFace()
277 {
278 if (!inDocument()) {
279 ASSERT(!m_fontElement);
280 return;
281 }
282
283 bool describesParentFont = isSVGFontElement(*parentNode());
284 RefPtrWillBeRawPtr<CSSValueList> list = nullptr;
285
286 if (describesParentFont) {
287 m_fontElement = toSVGFontElement(parentNode());
288
289 list = CSSValueList::createCommaSeparated();
290 list->append(CSSFontFaceSrcValue::createLocal(fontFamily()));
291 } else {
292 m_fontElement = nullptr;
293 // we currently ignore all but the last src element, alternatively we co uld concat them
294 if (SVGFontFaceSrcElement* element = Traversal<SVGFontFaceSrcElement>::l astChild(*this))
295 list = element->srcValue();
296 }
297
298 if (!list || !list->length())
299 return;
300
301 // Parse in-memory CSS rules
302 m_fontFaceRule->mutableProperties().addParsedProperty(CSSProperty(CSSPropert ySrc, list));
303
304 if (describesParentFont) {
305 // Traverse parsed CSS values and associate CSSFontFaceSrcValue elements with ourselves.
306 RefPtrWillBeRawPtr<CSSValue> src = m_fontFaceRule->properties().getPrope rtyCSSValue(CSSPropertySrc);
307 CSSValueList* srcList = toCSSValueList(src.get());
308
309 unsigned srcLength = srcList ? srcList->length() : 0;
310 for (unsigned i = 0; i < srcLength; i++) {
311 if (CSSFontFaceSrcValue* item = toCSSFontFaceSrcValue(srcList->item( i)))
312 item->setSVGFontFaceElement(this);
313 }
314 }
315
316 document().styleResolverChanged();
317 }
318
319 Node::InsertionNotificationRequest SVGFontFaceElement::insertedInto(ContainerNod e* rootParent)
320 {
321 SVGElement::insertedInto(rootParent);
322 if (!rootParent->inDocument()) {
323 ASSERT(!m_fontElement);
324 return InsertionDone;
325 }
326 document().accessSVGExtensions().registerSVGFontFaceElement(this);
327
328 rebuildFontFace();
329 return InsertionDone;
330 }
331
332 void SVGFontFaceElement::removedFrom(ContainerNode* rootParent)
333 {
334 SVGElement::removedFrom(rootParent);
335
336 if (rootParent->inDocument()) {
337 m_fontElement = nullptr;
338 document().accessSVGExtensions().unregisterSVGFontFaceElement(this);
339
340 // FIXME: HTMLTemplateElement's document or imported document can be ac tive?
341 // If so, we also need to check whether fontSelector() is nullptr or not .
342 // Otherwise, we will use just document().isActive() here.
343 if (document().isActive() && document().styleEngine()->fontSelector()) {
344 document().styleEngine()->fontSelector()->fontFaceCache()->remove(m_ fontFaceRule.get());
345 document().accessSVGExtensions().registerPendingSVGFontFaceElementsF orRemoval(this);
346 }
347 m_fontFaceRule->mutableProperties().clear();
348 document().styleResolverChanged();
349 } else
350 ASSERT(!m_fontElement);
351 }
352
353 void SVGFontFaceElement::childrenChanged(const ChildrenChange& change)
354 {
355 SVGElement::childrenChanged(change);
356 rebuildFontFace();
357 }
358
359 void SVGFontFaceElement::trace(Visitor* visitor)
360 {
361 visitor->trace(m_fontFaceRule);
362 visitor->trace(m_fontElement);
363 SVGElement::trace(visitor);
364 }
365
366 } // namespace blink
367
368 #endif // ENABLE(SVG_FONTS)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698