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

Side by Side Diff: Source/core/rendering/svg/SVGTextRunRenderingContext.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, 2008 Nikolas Zimmermann <zimmermann@kde.org>
3 * Copyright (C) Research In Motion Limited 2010-2011. All rights reserved.
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public License
16 * along with this library; see the file COPYING.LIB. If not, write to
17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19 */
20
21 #include "config.h"
22
23 #if ENABLE(SVG_FONTS)
24 #include "core/rendering/svg/SVGTextRunRenderingContext.h"
25
26 #include "core/rendering/RenderObject.h"
27 #include "core/svg/SVGFontData.h"
28 #include "core/svg/SVGFontElement.h"
29 #include "core/svg/SVGFontFaceElement.h"
30 #include "core/svg/SVGGlyphElement.h"
31 #include "platform/fonts/GlyphBuffer.h"
32 #include "platform/fonts/shaping/SimpleShaper.h"
33 #include "platform/graphics/GraphicsContext.h"
34
35 namespace blink {
36
37 static inline const SVGFontData* svgFontAndFontFaceElementForFontData(const Simp leFontData* fontData, SVGFontFaceElement*& fontFace, SVGFontElement*& font)
38 {
39 ASSERT(fontData);
40 ASSERT(fontData->isCustomFont());
41 ASSERT(fontData->isSVGFont());
42
43 RefPtr<CustomFontData> customFontData = fontData->customFontData();
44 const SVGFontData* svgFontData = toSVGFontData(customFontData);
45
46 // FIXME crbug.com/359380 : The current editing impl references the font aft er the svg font nodes are removed.
47 if (svgFontData->shouldSkipDrawing())
48 return 0;
49
50 fontFace = svgFontData->svgFontFaceElement();
51 ASSERT(fontFace);
52
53 font = fontFace->associatedFontElement();
54 return svgFontData;
55 }
56
57 static inline RenderObject* firstParentRendererForNonTextNode(RenderObject* rend erer)
58 {
59 ASSERT(renderer);
60 return renderer->isText() ? renderer->parent() : renderer;
61 }
62
63 static inline RenderObject* renderObjectFromRun(const TextRun& run)
64 {
65 if (TextRun::RenderingContext* renderingContext = run.renderingContext())
66 return static_cast<SVGTextRunRenderingContext*>(renderingContext)->rende rer();
67 return 0;
68 }
69
70 float SVGTextRunRenderingContext::floatWidthUsingSVGFont(const Font& font, const TextRun& run, int& charsConsumed, Glyph& glyphId) const
71 {
72 SimpleShaper it(&font, run);
73 GlyphBuffer glyphBuffer;
74 charsConsumed += it.advance(run.length(), &glyphBuffer);
75 glyphId = !glyphBuffer.isEmpty() ? glyphBuffer.glyphAt(0) : 0;
76 return it.runWidthSoFar();
77 }
78
79 void SVGTextRunRenderingContext::drawSVGGlyphs(GraphicsContext* context, const T extRun& run, const SimpleFontData* fontData, const GlyphBuffer& glyphBuffer, int from, int numGlyphs, const FloatPoint& point) const
80 {
81 SVGFontElement* fontElement = 0;
82 SVGFontFaceElement* fontFaceElement = 0;
83
84 const SVGFontData* svgFontData = svgFontAndFontFaceElementForFontData(fontDa ta, fontFaceElement, fontElement);
85 if (!fontElement || !fontFaceElement)
86 return;
87
88 // We can only paint SVGFonts if a context is available.
89 RenderObject* renderObject = renderObjectFromRun(run);
90 ASSERT(renderObject);
91
92 bool isVerticalText = false;
93 if (RenderObject* parentRenderObject = firstParentRendererForNonTextNode(ren derObject)) {
94 RenderStyle* parentRenderObjectStyle = parentRenderObject->style();
95 ASSERT(parentRenderObjectStyle);
96 isVerticalText = parentRenderObjectStyle->svgStyle().isVerticalWritingMo de();
97 }
98
99 float scale = scaleEmToUnits(fontData->platformData().size(), fontFaceElemen t->unitsPerEm());
100
101 FloatPoint glyphOrigin;
102 glyphOrigin.setX(svgFontData->horizontalOriginX() * scale);
103 glyphOrigin.setY(svgFontData->horizontalOriginY() * scale);
104
105 FloatPoint currentPoint = point;
106 for (int i = 0; i < numGlyphs; ++i) {
107 Glyph glyph = glyphBuffer.glyphAt(from + i);
108 if (!glyph)
109 continue;
110
111 float advance = glyphBuffer.advanceAt(from + i);
112 SVGGlyph svgGlyph = fontElement->svgGlyphForGlyph(glyph);
113 ASSERT(!svgGlyph.isPartOfLigature);
114 ASSERT(svgGlyph.tableEntry == glyph);
115
116 SVGGlyphElement::inheritUnspecifiedAttributes(svgGlyph, svgFontData);
117
118 // FIXME: Support arbitary SVG content as glyph (currently limited to <g lyph d="..."> situations).
119 if (svgGlyph.pathData.isEmpty()) {
120 if (isVerticalText)
121 currentPoint.move(0, advance);
122 else
123 currentPoint.move(advance, 0);
124 continue;
125 }
126
127 if (isVerticalText) {
128 glyphOrigin.setX(svgGlyph.verticalOriginX * scale);
129 glyphOrigin.setY(svgGlyph.verticalOriginY * scale);
130 }
131
132 AffineTransform glyphPathTransform;
133 glyphPathTransform.translate(currentPoint.x() + glyphOrigin.x(), current Point.y() + glyphOrigin.y());
134 glyphPathTransform.scale(scale, -scale);
135
136 Path glyphPath = svgGlyph.pathData;
137 glyphPath.transform(glyphPathTransform);
138
139 if (context->textDrawingMode() == TextModeStroke)
140 context->strokePath(glyphPath);
141 else
142 context->fillPath(glyphPath);
143
144 if (isVerticalText)
145 currentPoint.move(0, advance);
146 else
147 currentPoint.move(advance, 0);
148 }
149 }
150
151 GlyphData SVGTextRunRenderingContext::glyphDataForCharacter(const Font& font, co nst TextRun& run, SimpleShaper& iterator, UChar32 character, bool mirror, int cu rrentCharacter, unsigned& advanceLength)
152 {
153 const SimpleFontData* primaryFont = font.primaryFont();
154 ASSERT(primaryFont);
155
156 pair<GlyphData, GlyphPage*> pair = font.glyphDataAndPageForCharacter(charact er, mirror);
157 GlyphData glyphData = pair.first;
158
159 // Check if we have the missing glyph data, in which case we can just return .
160 GlyphData missingGlyphData = primaryFont->missingGlyphData();
161 if (glyphData.glyph == missingGlyphData.glyph && glyphData.fontData == missi ngGlyphData.fontData) {
162 ASSERT(glyphData.fontData);
163 return glyphData;
164 }
165
166 // Save data fromt he font fallback list because we may modify it later. Do this before the
167 // potential change to glyphData.fontData below.
168 FontFallbackList* fontList = font.fontList();
169 ASSERT(fontList);
170 FontFallbackList::GlyphPagesStateSaver glyphPagesSaver(*fontList);
171
172 // Characters enclosed by an <altGlyph> element, may not be registered in th e GlyphPage.
173 const SimpleFontData* originalFontData = glyphData.fontData;
174 if (originalFontData && !originalFontData->isSVGFont()) {
175 if (TextRun::RenderingContext* renderingContext = run.renderingContext() ) {
176 RenderObject* renderObject = static_cast<SVGTextRunRenderingContext* >(renderingContext)->renderer();
177 RenderObject* parentRenderObject = renderObject->isText() ? renderOb ject->parent() : renderObject;
178 ASSERT(parentRenderObject);
179 if (Element* parentRenderObjectElement = toElement(parentRenderObjec t->node())) {
180 if (isSVGAltGlyphElement(*parentRenderObjectElement))
181 glyphData.fontData = primaryFont;
182 }
183 }
184 }
185
186 const SimpleFontData* fontData = glyphData.fontData;
187 if (fontData) {
188 if (!fontData->isSVGFont())
189 return glyphData;
190
191 SVGFontElement* fontElement = 0;
192 SVGFontFaceElement* fontFaceElement = 0;
193
194 const SVGFontData* svgFontData = svgFontAndFontFaceElementForFontData(fo ntData, fontFaceElement, fontElement);
195 if (!fontElement || !fontFaceElement)
196 return glyphData;
197
198 // If we got here, we're dealing with a glyph defined in a SVG Font.
199 // The returned glyph by glyphDataAndPageForCharacter() is a glyph store d in the SVG Font glyph table.
200 // This doesn't necessarily mean the glyph is suitable for rendering/mea suring in this context, its
201 // arabic-form/orientation/... may not match, we have to apply SVG Glyph selection to discover that.
202 if (svgFontData->applySVGGlyphSelection(iterator, glyphData, mirror, cur rentCharacter, advanceLength))
203 return glyphData;
204 }
205
206 GlyphPage* page = pair.second;
207 ASSERT(page);
208
209 // No suitable glyph found that is compatible with the requirments (same lan guage, arabic-form, orientation etc.)
210 // Even though our GlyphPage contains an entry for eg. glyph "a", it's not c ompatible. So we have to temporarily
211 // remove the glyph data information from the GlyphPage, and retry the looku p, which handles font fallbacks correctly.
212 page->setGlyphDataForCharacter(character, 0, 0);
213
214 // Assure that the font fallback glyph selection worked, aka. the fallbackGl yphData font data is not the same as before.
215 GlyphData fallbackGlyphData = font.glyphDataForCharacter(character, mirror);
216 ASSERT(fallbackGlyphData.fontData != fontData);
217
218 // Restore original state of the SVG Font glyph table and the current font f allback list,
219 // to assure the next lookup of the same glyph won't immediately return the fallback glyph.
220 page->setGlyphDataForCharacter(character, glyphData.glyph, originalFontData) ;
221 ASSERT(fallbackGlyphData.fontData);
222 return fallbackGlyphData;
223 }
224
225 }
226
227 #endif
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698