OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2012 Koji Ishii <kojiishi@gmail.com> | 2 * Copyright (C) 2012 Koji Ishii <kojiishi@gmail.com> |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
6 * are met: | 6 * are met: |
7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
11 * documentation and/or other materials provided with the distribution. | 11 * documentation and/or other materials provided with the distribution. |
12 * | 12 * |
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND AN
Y | 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND AN
Y |
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | 15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
16 * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR AN
Y | 16 * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR AN
Y |
17 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | 17 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
18 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | 18 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
19 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND O
N | 19 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND O
N |
20 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 20 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | 21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
22 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 22 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
23 */ | 23 */ |
24 | 24 |
25 #include "config.h" | 25 #include "config.h" |
26 #if ENABLE(OPENTYPE_VERTICAL) | |
27 #include "platform/fonts/opentype/OpenTypeVerticalData.h" | 26 #include "platform/fonts/opentype/OpenTypeVerticalData.h" |
28 | 27 |
29 #include "platform/SharedBuffer.h" | 28 #include "platform/SharedBuffer.h" |
30 #include "platform/fonts/SimpleFontData.h" | 29 #include "platform/fonts/SimpleFontData.h" |
31 #include "platform/fonts/GlyphPage.h" | 30 #include "platform/fonts/GlyphPage.h" |
32 #include "platform/fonts/opentype/OpenTypeTypes.h" | 31 #include "platform/fonts/opentype/OpenTypeTypes.h" |
33 #include "platform/geometry/FloatRect.h" | 32 #include "platform/geometry/FloatRect.h" |
34 #include "wtf/RefPtr.h" | 33 #include "wtf/RefPtr.h" |
35 | 34 |
36 namespace blink { | 35 namespace blink { |
37 namespace OpenType { | 36 namespace OpenType { |
38 | 37 |
39 const uint32_t GSUBTag = OT_MAKE_TAG('G', 'S', 'U', 'B'); | |
40 const uint32_t HheaTag = OT_MAKE_TAG('h', 'h', 'e', 'a'); | 38 const uint32_t HheaTag = OT_MAKE_TAG('h', 'h', 'e', 'a'); |
41 const uint32_t HmtxTag = OT_MAKE_TAG('h', 'm', 't', 'x'); | 39 const uint32_t HmtxTag = OT_MAKE_TAG('h', 'm', 't', 'x'); |
42 const uint32_t VheaTag = OT_MAKE_TAG('v', 'h', 'e', 'a'); | 40 const uint32_t VheaTag = OT_MAKE_TAG('v', 'h', 'e', 'a'); |
43 const uint32_t VmtxTag = OT_MAKE_TAG('v', 'm', 't', 'x'); | 41 const uint32_t VmtxTag = OT_MAKE_TAG('v', 'm', 't', 'x'); |
44 const uint32_t VORGTag = OT_MAKE_TAG('V', 'O', 'R', 'G'); | 42 const uint32_t VORGTag = OT_MAKE_TAG('V', 'O', 'R', 'G'); |
45 | 43 |
46 const uint32_t DefaultScriptTag = OT_MAKE_TAG('D', 'F', 'L', 'T'); | |
47 | |
48 const uint32_t VertFeatureTag = OT_MAKE_TAG('v', 'e', 'r', 't'); | |
49 | |
50 #pragma pack(1) | 44 #pragma pack(1) |
51 | 45 |
52 struct HheaTable { | 46 struct HheaTable { |
53 OpenType::Fixed version; | 47 OpenType::Fixed version; |
54 OpenType::Int16 ascender; | 48 OpenType::Int16 ascender; |
55 OpenType::Int16 descender; | 49 OpenType::Int16 descender; |
56 OpenType::Int16 lineGap; | 50 OpenType::Int16 lineGap; |
57 OpenType::Int16 advanceWidthMax; | 51 OpenType::Int16 advanceWidthMax; |
58 OpenType::Int16 minLeftSideBearing; | 52 OpenType::Int16 minLeftSideBearing; |
59 OpenType::Int16 minRightSideBearing; | 53 OpenType::Int16 minRightSideBearing; |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
103 OpenType::Int16 defaultVertOriginY; | 97 OpenType::Int16 defaultVertOriginY; |
104 OpenType::UInt16 numVertOriginYMetrics; | 98 OpenType::UInt16 numVertOriginYMetrics; |
105 struct VertOriginYMetrics { | 99 struct VertOriginYMetrics { |
106 OpenType::UInt16 glyphIndex; | 100 OpenType::UInt16 glyphIndex; |
107 OpenType::Int16 vertOriginY; | 101 OpenType::Int16 vertOriginY; |
108 } vertOriginYMetrics[1]; | 102 } vertOriginYMetrics[1]; |
109 | 103 |
110 size_t requiredSize() const { return sizeof(*this) + sizeof(VertOriginYMetri
cs) * (numVertOriginYMetrics - 1); } | 104 size_t requiredSize() const { return sizeof(*this) + sizeof(VertOriginYMetri
cs) * (numVertOriginYMetrics - 1); } |
111 }; | 105 }; |
112 | 106 |
113 struct CoverageTable : TableBase { | |
114 OpenType::UInt16 coverageFormat; | |
115 }; | |
116 | |
117 struct Coverage1Table : CoverageTable { | |
118 OpenType::UInt16 glyphCount; | |
119 OpenType::GlyphID glyphArray[1]; | |
120 }; | |
121 | |
122 struct Coverage2Table : CoverageTable { | |
123 OpenType::UInt16 rangeCount; | |
124 struct RangeRecord { | |
125 OpenType::GlyphID start; | |
126 OpenType::GlyphID end; | |
127 OpenType::UInt16 startCoverageIndex; | |
128 } ranges[1]; | |
129 }; | |
130 | |
131 struct SubstitutionSubTable : TableBase { | |
132 OpenType::UInt16 substFormat; | |
133 OpenType::Offset coverageOffset; | |
134 | |
135 const CoverageTable* coverage(const SharedBuffer& buffer) const { return val
idateOffset<CoverageTable>(buffer, coverageOffset); } | |
136 }; | |
137 | |
138 struct SingleSubstitution2SubTable : SubstitutionSubTable { | |
139 OpenType::UInt16 glyphCount; | |
140 OpenType::GlyphID substitute[1]; | |
141 }; | |
142 | |
143 struct LookupTable : TableBase { | |
144 OpenType::UInt16 lookupType; | |
145 OpenType::UInt16 lookupFlag; | |
146 OpenType::UInt16 subTableCount; | |
147 OpenType::Offset subTableOffsets[1]; | |
148 // OpenType::UInt16 markFilteringSet; this field comes after variable length
, so offset is determined dynamically. | |
149 | |
150 bool getSubstitutions(HashMap<Glyph, Glyph>* map, const SharedBuffer& buffer
) const | |
151 { | |
152 uint16_t countSubTable = subTableCount; | |
153 if (!isValidEnd(buffer, &subTableOffsets[countSubTable])) | |
154 return false; | |
155 if (lookupType != 1) // "Single Substitution Subtable" is all what we su
pport | |
156 return false; | |
157 for (uint16_t i = 0; i < countSubTable; ++i) { | |
158 const SubstitutionSubTable* substitution = validateOffset<Substituti
onSubTable>(buffer, subTableOffsets[i]); | |
159 if (!substitution) | |
160 return false; | |
161 const CoverageTable* coverage = substitution->coverage(buffer); | |
162 if (!coverage) | |
163 return false; | |
164 if (substitution->substFormat != 2) // "Single Substitution Format 2
" is all what we support | |
165 return false; | |
166 const SingleSubstitution2SubTable* singleSubstitution2 = validatePtr
<SingleSubstitution2SubTable>(buffer, substitution); | |
167 if (!singleSubstitution2) | |
168 return false; | |
169 uint16_t countTo = singleSubstitution2->glyphCount; | |
170 if (!isValidEnd(buffer, &singleSubstitution2->substitute[countTo])) | |
171 return false; | |
172 switch (coverage->coverageFormat) { | |
173 case 1: { // Coverage Format 1 (e.g., MS Gothic) | |
174 const Coverage1Table* coverage1 = validatePtr<Coverage1Table>(bu
ffer, coverage); | |
175 if (!coverage1) | |
176 return false; | |
177 uint16_t countFrom = coverage1->glyphCount; | |
178 if (!isValidEnd(buffer, &coverage1->glyphArray[countFrom]) || co
untTo != countFrom) | |
179 return false; | |
180 for (uint16_t i = 0; i < countTo; ++i) | |
181 map->set(coverage1->glyphArray[i], singleSubstitution2->subs
titute[i]); | |
182 break; | |
183 } | |
184 case 2: { // Coverage Format 2 (e.g., Adobe Kozuka Gothic) | |
185 const Coverage2Table* coverage2 = validatePtr<Coverage2Table>(bu
ffer, coverage); | |
186 if (!coverage2) | |
187 return false; | |
188 uint16_t countRange = coverage2->rangeCount; | |
189 if (!isValidEnd(buffer, &coverage2->ranges[countRange])) | |
190 return false; | |
191 for (uint16_t i = 0, indexTo = 0; i < countRange; ++i) { | |
192 uint16_t from = coverage2->ranges[i].start; | |
193 uint16_t fromEnd = coverage2->ranges[i].end + 1; // OpenType
"end" is inclusive | |
194 if (indexTo + (fromEnd - from) > countTo) | |
195 return false; | |
196 for (; from != fromEnd; ++from, ++indexTo) | |
197 map->set(from, singleSubstitution2->substitute[indexTo])
; | |
198 } | |
199 break; | |
200 } | |
201 default: | |
202 return false; | |
203 } | |
204 } | |
205 return true; | |
206 } | |
207 }; | |
208 | |
209 struct LookupList : TableBase { | |
210 OpenType::UInt16 lookupCount; | |
211 OpenType::Offset lookupOffsets[1]; | |
212 | |
213 const LookupTable* lookup(uint16_t index, const SharedBuffer& buffer) const | |
214 { | |
215 uint16_t count = lookupCount; | |
216 if (index >= count || !isValidEnd(buffer, &lookupOffsets[count])) | |
217 return 0; | |
218 return validateOffset<LookupTable>(buffer, lookupOffsets[index]); | |
219 } | |
220 }; | |
221 | |
222 struct FeatureTable : TableBase { | |
223 OpenType::Offset featureParams; | |
224 OpenType::UInt16 lookupCount; | |
225 OpenType::UInt16 lookupListIndex[1]; | |
226 | |
227 bool getGlyphSubstitutions(const LookupList* lookups, HashMap<Glyph, Glyph>*
map, const SharedBuffer& buffer) const | |
228 { | |
229 uint16_t count = lookupCount; | |
230 if (!isValidEnd(buffer, &lookupListIndex[count])) | |
231 return false; | |
232 for (uint16_t i = 0; i < count; ++i) { | |
233 const LookupTable* lookup = lookups->lookup(lookupListIndex[i], buff
er); | |
234 if (!lookup || !lookup->getSubstitutions(map, buffer)) | |
235 return false; | |
236 } | |
237 return true; | |
238 } | |
239 }; | |
240 | |
241 struct FeatureList : TableBase { | |
242 OpenType::UInt16 featureCount; | |
243 struct FeatureRecord { | |
244 OpenType::Tag featureTag; | |
245 OpenType::Offset featureOffset; | |
246 } features[1]; | |
247 | |
248 const FeatureTable* feature(uint16_t index, OpenType::Tag tag, const SharedB
uffer& buffer) const | |
249 { | |
250 uint16_t count = featureCount; | |
251 if (index >= count || !isValidEnd(buffer, &features[count])) | |
252 return 0; | |
253 if (features[index].featureTag == tag) | |
254 return validateOffset<FeatureTable>(buffer, features[index].featureO
ffset); | |
255 return 0; | |
256 } | |
257 | |
258 const FeatureTable* findFeature(OpenType::Tag tag, const SharedBuffer& buffe
r) const | |
259 { | |
260 for (uint16_t i = 0; i < featureCount; ++i) { | |
261 if (isValidEnd(buffer, &features[i]) && features[i].featureTag == ta
g) | |
262 return validateOffset<FeatureTable>(buffer, features[i].featureO
ffset); | |
263 } | |
264 return 0; | |
265 } | |
266 }; | |
267 | |
268 struct LangSysTable : TableBase { | |
269 OpenType::Offset lookupOrder; | |
270 OpenType::UInt16 reqFeatureIndex; | |
271 OpenType::UInt16 featureCount; | |
272 OpenType::UInt16 featureIndex[1]; | |
273 | |
274 const FeatureTable* feature(OpenType::Tag featureTag, const FeatureList* fea
tures, const SharedBuffer& buffer) const | |
275 { | |
276 uint16_t count = featureCount; | |
277 if (!isValidEnd(buffer, &featureIndex[count])) | |
278 return 0; | |
279 for (uint16_t i = 0; i < count; ++i) { | |
280 const FeatureTable* featureTable = features->feature(featureIndex[i]
, featureTag, buffer); | |
281 if (featureTable) | |
282 return featureTable; | |
283 } | |
284 return 0; | |
285 } | |
286 }; | |
287 | |
288 struct ScriptTable : TableBase { | |
289 OpenType::Offset defaultLangSysOffset; | |
290 OpenType::UInt16 langSysCount; | |
291 struct LangSysRecord { | |
292 OpenType::Tag langSysTag; | |
293 OpenType::Offset langSysOffset; | |
294 } langSysRecords[1]; | |
295 | |
296 const LangSysTable* defaultLangSys(const SharedBuffer& buffer) const | |
297 { | |
298 uint16_t count = langSysCount; | |
299 if (!isValidEnd(buffer, &langSysRecords[count])) | |
300 return 0; | |
301 uint16_t offset = defaultLangSysOffset; | |
302 if (offset) | |
303 return validateOffset<LangSysTable>(buffer, offset); | |
304 if (count) | |
305 return validateOffset<LangSysTable>(buffer, langSysRecords[0].langSy
sOffset); | |
306 return 0; | |
307 } | |
308 }; | |
309 | |
310 struct ScriptList : TableBase { | |
311 OpenType::UInt16 scriptCount; | |
312 struct ScriptRecord { | |
313 OpenType::Tag scriptTag; | |
314 OpenType::Offset scriptOffset; | |
315 } scripts[1]; | |
316 | |
317 const ScriptTable* script(OpenType::Tag tag, const SharedBuffer& buffer) con
st | |
318 { | |
319 uint16_t count = scriptCount; | |
320 if (!isValidEnd(buffer, &scripts[count])) | |
321 return 0; | |
322 for (uint16_t i = 0; i < count; ++i) { | |
323 if (scripts[i].scriptTag == tag) | |
324 return validateOffset<ScriptTable>(buffer, scripts[i].scriptOffs
et); | |
325 } | |
326 return 0; | |
327 } | |
328 | |
329 const ScriptTable* defaultScript(const SharedBuffer& buffer) const | |
330 { | |
331 uint16_t count = scriptCount; | |
332 if (!count || !isValidEnd(buffer, &scripts[count])) | |
333 return 0; | |
334 const ScriptTable* scriptOfDefaultTag = script(OpenType::DefaultScriptTa
g, buffer); | |
335 if (scriptOfDefaultTag) | |
336 return scriptOfDefaultTag; | |
337 return validateOffset<ScriptTable>(buffer, scripts[0].scriptOffset); | |
338 } | |
339 | |
340 const LangSysTable* defaultLangSys(const SharedBuffer& buffer) const | |
341 { | |
342 const ScriptTable* scriptTable = defaultScript(buffer); | |
343 if (!scriptTable) | |
344 return 0; | |
345 return scriptTable->defaultLangSys(buffer); | |
346 } | |
347 }; | |
348 | |
349 struct GSUBTable : TableBase { | |
350 OpenType::Fixed version; | |
351 OpenType::Offset scriptListOffset; | |
352 OpenType::Offset featureListOffset; | |
353 OpenType::Offset lookupListOffset; | |
354 | |
355 const ScriptList* scriptList(const SharedBuffer& buffer) const { return vali
dateOffset<ScriptList>(buffer, scriptListOffset); } | |
356 const FeatureList* featureList(const SharedBuffer& buffer) const { return va
lidateOffset<FeatureList>(buffer, featureListOffset); } | |
357 const LookupList* lookupList(const SharedBuffer& buffer) const { return vali
dateOffset<LookupList>(buffer, lookupListOffset); } | |
358 | |
359 const LangSysTable* defaultLangSys(const SharedBuffer& buffer) const | |
360 { | |
361 const ScriptList* scripts = scriptList(buffer); | |
362 if (!scripts) | |
363 return 0; | |
364 return scripts->defaultLangSys(buffer); | |
365 } | |
366 | |
367 const FeatureTable* feature(OpenType::Tag featureTag, const SharedBuffer& bu
ffer) const | |
368 { | |
369 const LangSysTable* langSys = defaultLangSys(buffer); | |
370 const FeatureList* features = featureList(buffer); | |
371 if (!features) | |
372 return 0; | |
373 const FeatureTable* feature = 0; | |
374 if (langSys) | |
375 feature = langSys->feature(featureTag, features, buffer); | |
376 if (!feature) { | |
377 // If the font has no langSys table, or has no default script and th
e first script doesn't | |
378 // have the requested feature, then use the first matching feature d
irectly. | |
379 feature = features->findFeature(featureTag, buffer); | |
380 } | |
381 return feature; | |
382 } | |
383 | |
384 bool getVerticalGlyphSubstitutions(HashMap<Glyph, Glyph>* map, const SharedB
uffer& buffer) const | |
385 { | |
386 const FeatureTable* verticalFeatureTable = feature(OpenType::VertFeature
Tag, buffer); | |
387 if (!verticalFeatureTable) | |
388 return false; | |
389 const LookupList* lookups = lookupList(buffer); | |
390 return lookups && verticalFeatureTable->getGlyphSubstitutions(lookups, m
ap, buffer); | |
391 } | |
392 }; | |
393 | |
394 #pragma pack() | 107 #pragma pack() |
395 | 108 |
396 } // namespace OpenType | 109 } // namespace OpenType |
397 | 110 |
398 OpenTypeVerticalData::OpenTypeVerticalData(const FontPlatformData& platformData) | 111 OpenTypeVerticalData::OpenTypeVerticalData(const FontPlatformData& platformData) |
399 : m_defaultVertOriginY(0) | 112 : m_defaultVertOriginY(0) |
400 { | 113 { |
401 loadMetrics(platformData); | 114 loadMetrics(platformData); |
402 loadVerticalGlyphSubstitutions(platformData); | |
403 } | 115 } |
404 | 116 |
405 void OpenTypeVerticalData::loadMetrics(const FontPlatformData& platformData) | 117 void OpenTypeVerticalData::loadMetrics(const FontPlatformData& platformData) |
406 { | 118 { |
407 // Load hhea and hmtx to get x-component of vertical origins. | 119 // Load hhea and hmtx to get x-component of vertical origins. |
408 // If these tables are missing, it's not an OpenType font. | 120 // If these tables are missing, it's not an OpenType font. |
409 RefPtr<SharedBuffer> buffer = platformData.openTypeTable(OpenType::HheaTag); | 121 RefPtr<SharedBuffer> buffer = platformData.openTypeTable(OpenType::HheaTag); |
410 const OpenType::HheaTable* hhea = OpenType::validateTable<OpenType::HheaTabl
e>(buffer); | 122 const OpenType::HheaTable* hhea = OpenType::validateTable<OpenType::HheaTabl
e>(buffer); |
411 if (!hhea) | 123 if (!hhea) |
412 return; | 124 return; |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
480 size_t i; | 192 size_t i; |
481 for (i = 0; i < countVmtxEntries; ++i) | 193 for (i = 0; i < countVmtxEntries; ++i) |
482 m_topSideBearings[i] = vmtx->entries[i].topSideBearing; | 194 m_topSideBearings[i] = vmtx->entries[i].topSideBearing; |
483 if (i < countTopSideBearings) { | 195 if (i < countTopSideBearings) { |
484 const OpenType::Int16* pTopSideBearingsExtra = reinterpret_cast<const Op
enType::Int16*>(&vmtx->entries[countVmtxEntries]); | 196 const OpenType::Int16* pTopSideBearingsExtra = reinterpret_cast<const Op
enType::Int16*>(&vmtx->entries[countVmtxEntries]); |
485 for (; i < countTopSideBearings; ++i, ++pTopSideBearingsExtra) | 197 for (; i < countTopSideBearings; ++i, ++pTopSideBearingsExtra) |
486 m_topSideBearings[i] = *pTopSideBearingsExtra; | 198 m_topSideBearings[i] = *pTopSideBearingsExtra; |
487 } | 199 } |
488 } | 200 } |
489 | 201 |
490 void OpenTypeVerticalData::loadVerticalGlyphSubstitutions(const FontPlatformData
& platformData) | |
491 { | |
492 RefPtr<SharedBuffer> buffer = platformData.openTypeTable(OpenType::GSUBTag); | |
493 const OpenType::GSUBTable* gsub = OpenType::validateTable<OpenType::GSUBTabl
e>(buffer); | |
494 if (gsub) | |
495 gsub->getVerticalGlyphSubstitutions(&m_verticalGlyphMap, *buffer.get()); | |
496 } | |
497 | |
498 float OpenTypeVerticalData::advanceHeight(const SimpleFontData* font, Glyph glyp
h) const | 202 float OpenTypeVerticalData::advanceHeight(const SimpleFontData* font, Glyph glyp
h) const |
499 { | 203 { |
500 size_t countHeights = m_advanceHeights.size(); | 204 size_t countHeights = m_advanceHeights.size(); |
501 if (countHeights) { | 205 if (countHeights) { |
502 uint16_t advanceFUnit = m_advanceHeights[glyph < countHeights ? glyph :
countHeights - 1]; | 206 uint16_t advanceFUnit = m_advanceHeights[glyph < countHeights ? glyph :
countHeights - 1]; |
503 float advance = advanceFUnit * font->sizePerUnit(); | 207 float advance = advanceFUnit * font->sizePerUnit(); |
504 return advance; | 208 return advance; |
505 } | 209 } |
506 | 210 |
507 // No vertical info in the font file; use height as advance. | 211 // No vertical info in the font file; use height as advance. |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
544 FloatRect bounds = font->boundsForGlyph(glyph); | 248 FloatRect bounds = font->boundsForGlyph(glyph); |
545 outXYArray[1] = bounds.y() - topSideBearing; | 249 outXYArray[1] = bounds.y() - topSideBearing; |
546 continue; | 250 continue; |
547 } | 251 } |
548 | 252 |
549 // No vertical info in the font file; use ascent as vertical origin. | 253 // No vertical info in the font file; use ascent as vertical origin. |
550 outXYArray[1] = -ascent; | 254 outXYArray[1] = -ascent; |
551 } | 255 } |
552 } | 256 } |
553 | 257 |
554 void OpenTypeVerticalData::substituteWithVerticalGlyphs(const SimpleFontData* fo
nt, GlyphPage* glyphPage, unsigned offset, unsigned length) const | |
555 { | |
556 const HashMap<Glyph, Glyph>& map = m_verticalGlyphMap; | |
557 if (map.isEmpty()) | |
558 return; | |
559 | |
560 for (unsigned index = offset, end = offset + length; index < end; ++index) { | |
561 GlyphData glyphData = glyphPage->glyphDataForIndex(index); | |
562 if (glyphData.glyph && glyphData.fontData == font) { | |
563 Glyph to = map.get(glyphData.glyph); | |
564 if (to) | |
565 glyphPage->setGlyphDataForIndex(index, to, font); | |
566 } | |
567 } | |
568 } | |
569 | |
570 } // namespace blink | 258 } // namespace blink |
571 #endif // ENABLE(OPENTYPE_VERTICAL) | |
OLD | NEW |