2 * Copyright (C) 2012 Koji Ishii <kojiishi@gmail.com>
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
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 ANY
17 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
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 ON
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
22 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 #if ENABLE(OPENTYPE_VERTICAL)
27 #include "platform/fonts/opentype/OpenTypeVerticalData.h"
29 #include "platform/SharedBuffer.h"
30 #include "platform/fonts/SimpleFontData.h"
31 #include "platform/fonts/GlyphPage.h"
32 #include "platform/fonts/opentype/OpenTypeTypes.h"
33 #include "platform/geometry/FloatRect.h"
34 #include "wtf/RefPtr.h"
39 const uint32_t GSUBTag = OT_MAKE_TAG('G', 'S', 'U', 'B');
40 const uint32_t HheaTag = OT_MAKE_TAG('h', 'h', 'e', 'a');
41 const uint32_t HmtxTag = OT_MAKE_TAG('h', 'm', 't', 'x');
42 const uint32_t VheaTag = OT_MAKE_TAG('v', 'h', 'e', 'a');
43 const uint32_t VmtxTag = OT_MAKE_TAG('v', 'm', 't', 'x');
44 const uint32_t VORGTag = OT_MAKE_TAG('V', 'O', 'R', 'G');
46 const uint32_t DefaultScriptTag = OT_MAKE_TAG('D', 'F', 'L', 'T');
48 const uint32_t VertFeatureTag = OT_MAKE_TAG('v', 'e', 'r', 't');
53 OpenType::Fixed version;
54 OpenType::Int16 ascender;
55 OpenType::Int16 descender;
56 OpenType::Int16 lineGap;
57 OpenType::Int16 advanceWidthMax;
58 OpenType::Int16 minLeftSideBearing;
59 OpenType::Int16 minRightSideBearing;
60 OpenType::Int16 xMaxExtent;
61 OpenType::Int16 caretSlopeRise;
62 OpenType::Int16 caretSlopeRun;
63 OpenType::Int16 caretOffset;
64 OpenType::Int16 reserved[4];
65 OpenType::Int16 metricDataFormat;
66 OpenType::UInt16 numberOfHMetrics;
70 OpenType::Fixed version;
71 OpenType::Int16 ascent;
72 OpenType::Int16 descent;
73 OpenType::Int16 lineGap;
74 OpenType::Int16 advanceHeightMax;
75 OpenType::Int16 minTopSideBearing;
76 OpenType::Int16 minBottomSideBearing;
77 OpenType::Int16 yMaxExtent;
78 OpenType::Int16 caretSlopeRise;
79 OpenType::Int16 caretSlopeRun;
80 OpenType::Int16 caretOffset;
81 OpenType::Int16 reserved[4];
82 OpenType::Int16 metricDataFormat;
83 OpenType::UInt16 numOfLongVerMetrics;
88 OpenType::UInt16 advanceWidth;
95 OpenType::UInt16 advanceHeight;
96 OpenType::Int16 topSideBearing;
101 OpenType::UInt16 majorVersion;
102 OpenType::UInt16 minorVersion;
103 OpenType::Int16 defaultVertOriginY;
104 OpenType::UInt16 numVertOriginYMetrics;
105 struct VertOriginYMetrics {
106 OpenType::UInt16 glyphIndex;
107 OpenType::Int16 vertOriginY;
108 } vertOriginYMetrics[1];
110 size_t requiredSize() const { return sizeof(*this) + sizeof(VertOriginYMetrics) * (numVertOriginYMetrics - 1); }
113 struct CoverageTable : TableBase {
114 OpenType::UInt16 coverageFormat;
117 struct Coverage1Table : CoverageTable {
118 OpenType::UInt16 glyphCount;
119 OpenType::GlyphID glyphArray[1];
122 struct Coverage2Table : CoverageTable {
123 OpenType::UInt16 rangeCount;
125 OpenType::GlyphID start;
126 OpenType::GlyphID end;
127 OpenType::UInt16 startCoverageIndex;
131 struct SubstitutionSubTable : TableBase {
132 OpenType::UInt16 substFormat;
133 OpenType::Offset coverageOffset;
135 const CoverageTable* coverage(const SharedBuffer& buffer) const { return validateOffset<CoverageTable>(buffer, coverageOffset); }
138 struct SingleSubstitution2SubTable : SubstitutionSubTable {
139 OpenType::UInt16 glyphCount;
140 OpenType::GlyphID substitute[1];
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.
150 bool getSubstitutions(HashMap<Glyph, Glyph>* map, const SharedBuffer& buffer) const
152 uint16_t countSubTable = subTableCount;
153 if (!isValidEnd(buffer, &subTableOffsets[countSubTable]))
155 if (lookupType != 1) // "Single Substitution Subtable" is all what we support
157 for (uint16_t i = 0; i < countSubTable; ++i) {
158 const SubstitutionSubTable* substitution = validateOffset<SubstitutionSubTable>(buffer, subTableOffsets[i]);
161 const CoverageTable* coverage = substitution->coverage(buffer);
164 if (substitution->substFormat != 2) // "Single Substitution Format 2" is all what we support
166 const SingleSubstitution2SubTable* singleSubstitution2 = validatePtr<SingleSubstitution2SubTable>(buffer, substitution);
167 if (!singleSubstitution2)
169 uint16_t countTo = singleSubstitution2->glyphCount;
170 if (!isValidEnd(buffer, &singleSubstitution2->substitute[countTo]))
172 switch (coverage->coverageFormat) {
173 case 1: { // Coverage Format 1 (e.g., MS Gothic)
174 const Coverage1Table* coverage1 = validatePtr<Coverage1Table>(buffer, coverage);
177 uint16_t countFrom = coverage1->glyphCount;
178 if (!isValidEnd(buffer, &coverage1->glyphArray[countFrom]) || countTo != countFrom)
180 for (uint16_t i = 0; i < countTo; ++i)
181 map->set(coverage1->glyphArray[i], singleSubstitution2->substitute[i]);
184 case 2: { // Coverage Format 2 (e.g., Adobe Kozuka Gothic)
185 const Coverage2Table* coverage2 = validatePtr<Coverage2Table>(buffer, coverage);
188 uint16_t countRange = coverage2->rangeCount;
189 if (!isValidEnd(buffer, &coverage2->ranges[countRange]))
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)
196 for (; from != fromEnd; ++from, ++indexTo)
197 map->set(from, singleSubstitution2->substitute[indexTo]);
209 struct LookupList : TableBase {
210 OpenType::UInt16 lookupCount;
211 OpenType::Offset lookupOffsets[1];
213 const LookupTable* lookup(uint16_t index, const SharedBuffer& buffer) const
215 uint16_t count = lookupCount;
216 if (index >= count || !isValidEnd(buffer, &lookupOffsets[count]))
218 return validateOffset<LookupTable>(buffer, lookupOffsets[index]);
222 struct FeatureTable : TableBase {
223 OpenType::Offset featureParams;
224 OpenType::UInt16 lookupCount;
225 OpenType::UInt16 lookupListIndex[1];
227 bool getGlyphSubstitutions(const LookupList* lookups, HashMap<Glyph, Glyph>* map, const SharedBuffer& buffer) const
229 uint16_t count = lookupCount;
230 if (!isValidEnd(buffer, &lookupListIndex[count]))
232 for (uint16_t i = 0; i < count; ++i) {
233 const LookupTable* lookup = lookups->lookup(lookupListIndex[i], buffer);
234 if (!lookup || !lookup->getSubstitutions(map, buffer))
241 struct FeatureList : TableBase {
242 OpenType::UInt16 featureCount;
243 struct FeatureRecord {
244 OpenType::Tag featureTag;
245 OpenType::Offset featureOffset;
248 const FeatureTable* feature(uint16_t index, OpenType::Tag tag, const SharedBuffer& buffer) const
250 uint16_t count = featureCount;
251 if (index >= count || !isValidEnd(buffer, &features[count]))
253 if (features[index].featureTag == tag)
254 return validateOffset<FeatureTable>(buffer, features[index].featureOffset);
258 const FeatureTable* findFeature(OpenType::Tag tag, const SharedBuffer& buffer) const
260 for (uint16_t i = 0; i < featureCount; ++i) {
261 if (isValidEnd(buffer, &features[i]) && features[i].featureTag == tag)
262 return validateOffset<FeatureTable>(buffer, features[i].featureOffset);
268 struct LangSysTable : TableBase {
269 OpenType::Offset lookupOrder;
270 OpenType::UInt16 reqFeatureIndex;
271 OpenType::UInt16 featureCount;
272 OpenType::UInt16 featureIndex[1];
274 const FeatureTable* feature(OpenType::Tag featureTag, const FeatureList* features, const SharedBuffer& buffer) const
276 uint16_t count = featureCount;
277 if (!isValidEnd(buffer, &featureIndex[count]))
279 for (uint16_t i = 0; i < count; ++i) {
280 const FeatureTable* featureTable = features->feature(featureIndex[i], featureTag, buffer);
288 struct ScriptTable : TableBase {
289 OpenType::Offset defaultLangSysOffset;
290 OpenType::UInt16 langSysCount;
291 struct LangSysRecord {
292 OpenType::Tag langSysTag;
293 OpenType::Offset langSysOffset;
296 const LangSysTable* defaultLangSys(const SharedBuffer& buffer) const
298 uint16_t count = langSysCount;
299 if (!isValidEnd(buffer, &langSysRecords[count]))
301 uint16_t offset = defaultLangSysOffset;
303 return validateOffset<LangSysTable>(buffer, offset);
305 return validateOffset<LangSysTable>(buffer, langSysRecords[0].langSysOffset);
310 struct ScriptList : TableBase {
311 OpenType::UInt16 scriptCount;
312 struct ScriptRecord {
313 OpenType::Tag scriptTag;
314 OpenType::Offset scriptOffset;
317 const ScriptTable* script(OpenType::Tag tag, const SharedBuffer& buffer) const
319 uint16_t count = scriptCount;
320 if (!isValidEnd(buffer, &scripts[count]))
322 for (uint16_t i = 0; i < count; ++i) {
323 if (scripts[i].scriptTag == tag)
324 return validateOffset<ScriptTable>(buffer, scripts[i].scriptOffset);
329 const ScriptTable* defaultScript(const SharedBuffer& buffer) const
331 uint16_t count = scriptCount;
332 if (!count || !isValidEnd(buffer, &scripts[count]))
334 const ScriptTable* scriptOfDefaultTag = script(OpenType::DefaultScriptTag, buffer);
335 if (scriptOfDefaultTag)
336 return scriptOfDefaultTag;
337 return validateOffset<ScriptTable>(buffer, scripts[0].scriptOffset);
340 const LangSysTable* defaultLangSys(const SharedBuffer& buffer) const
342 const ScriptTable* scriptTable = defaultScript(buffer);
345 return scriptTable->defaultLangSys(buffer);
349 struct GSUBTable : TableBase {
350 OpenType::Fixed version;
351 OpenType::Offset scriptListOffset;
352 OpenType::Offset featureListOffset;
353 OpenType::Offset lookupListOffset;
355 const ScriptList* scriptList(const SharedBuffer& buffer) const { return validateOffset<ScriptList>(buffer, scriptListOffset); }
356 const FeatureList* featureList(const SharedBuffer& buffer) const { return validateOffset<FeatureList>(buffer, featureListOffset); }
357 const LookupList* lookupList(const SharedBuffer& buffer) const { return validateOffset<LookupList>(buffer, lookupListOffset); }
359 const LangSysTable* defaultLangSys(const SharedBuffer& buffer) const
361 const ScriptList* scripts = scriptList(buffer);
364 return scripts->defaultLangSys(buffer);
367 const FeatureTable* feature(OpenType::Tag featureTag, const SharedBuffer& buffer) const
369 const LangSysTable* langSys = defaultLangSys(buffer);
370 const FeatureList* features = featureList(buffer);
373 const FeatureTable* feature = 0;
375 feature = langSys->feature(featureTag, features, buffer);
377 // If the font has no langSys table, or has no default script and the first script doesn't
378 // have the requested feature, then use the first matching feature directly.
379 feature = features->findFeature(featureTag, buffer);
384 bool getVerticalGlyphSubstitutions(HashMap<Glyph, Glyph>* map, const SharedBuffer& buffer) const
386 const FeatureTable* verticalFeatureTable = feature(OpenType::VertFeatureTag, buffer);
387 if (!verticalFeatureTable)
389 const LookupList* lookups = lookupList(buffer);
390 return lookups && verticalFeatureTable->getGlyphSubstitutions(lookups, map, buffer);
396 } // namespace OpenType
398 OpenTypeVerticalData::OpenTypeVerticalData(const FontPlatformData& platformData)
399 : m_defaultVertOriginY(0)
401 loadMetrics(platformData);
402 loadVerticalGlyphSubstitutions(platformData);
405 void OpenTypeVerticalData::loadMetrics(const FontPlatformData& platformData)
407 // Load hhea and hmtx to get x-component of vertical origins.
408 // If these tables are missing, it's not an OpenType font.
409 RefPtr<SharedBuffer> buffer = platformData.openTypeTable(OpenType::HheaTag);
410 const OpenType::HheaTable* hhea = OpenType::validateTable<OpenType::HheaTable>(buffer);
413 uint16_t countHmtxEntries = hhea->numberOfHMetrics;
414 if (!countHmtxEntries) {
415 WTF_LOG_ERROR("Invalid numberOfHMetrics");
419 buffer = platformData.openTypeTable(OpenType::HmtxTag);
420 const OpenType::HmtxTable* hmtx = OpenType::validateTable<OpenType::HmtxTable>(buffer, countHmtxEntries);
422 WTF_LOG_ERROR("hhea exists but hmtx does not (or broken)");
425 m_advanceWidths.resize(countHmtxEntries);
426 for (uint16_t i = 0; i < countHmtxEntries; ++i)
427 m_advanceWidths[i] = hmtx->entries[i].advanceWidth;
429 // Load vhea first. This table is required for fonts that support vertical flow.
430 buffer = platformData.openTypeTable(OpenType::VheaTag);
431 const OpenType::VheaTable* vhea = OpenType::validateTable<OpenType::VheaTable>(buffer);
434 uint16_t countVmtxEntries = vhea->numOfLongVerMetrics;
435 if (!countVmtxEntries) {
436 WTF_LOG_ERROR("Invalid numOfLongVerMetrics");
440 // Load VORG. This table is optional.
441 buffer = platformData.openTypeTable(OpenType::VORGTag);
442 const OpenType::VORGTable* vorg = OpenType::validateTable<OpenType::VORGTable>(buffer);
443 if (vorg && buffer->size() >= vorg->requiredSize()) {
444 m_defaultVertOriginY = vorg->defaultVertOriginY;
445 uint16_t countVertOriginYMetrics = vorg->numVertOriginYMetrics;
446 if (!countVertOriginYMetrics) {
447 // Add one entry so that hasVORG() becomes true
448 m_vertOriginY.set(0, m_defaultVertOriginY);
450 for (uint16_t i = 0; i < countVertOriginYMetrics; ++i) {
451 const OpenType::VORGTable::VertOriginYMetrics& metrics = vorg->vertOriginYMetrics[i];
452 m_vertOriginY.set(metrics.glyphIndex, metrics.vertOriginY);
457 // Load vmtx then. This table is required for fonts that support vertical flow.
458 buffer = platformData.openTypeTable(OpenType::VmtxTag);
459 const OpenType::VmtxTable* vmtx = OpenType::validateTable<OpenType::VmtxTable>(buffer, countVmtxEntries);
461 WTF_LOG_ERROR("vhea exists but vmtx does not (or broken)");
464 m_advanceHeights.resize(countVmtxEntries);
465 for (uint16_t i = 0; i < countVmtxEntries; ++i)
466 m_advanceHeights[i] = vmtx->entries[i].advanceHeight;
468 // VORG is preferred way to calculate vertical origin than vmtx,
469 // so load topSideBearing from vmtx only if VORG is missing.
473 size_t sizeExtra = buffer->size() - sizeof(OpenType::VmtxTable::Entry) * countVmtxEntries;
474 if (sizeExtra % sizeof(OpenType::Int16)) {
475 WTF_LOG_ERROR("vmtx has incorrect tsb count");
478 size_t countTopSideBearings = countVmtxEntries + sizeExtra / sizeof(OpenType::Int16);
479 m_topSideBearings.resize(countTopSideBearings);
481 for (i = 0; i < countVmtxEntries; ++i)
482 m_topSideBearings[i] = vmtx->entries[i].topSideBearing;
483 if (i < countTopSideBearings) {
484 const OpenType::Int16* pTopSideBearingsExtra = reinterpret_cast<const OpenType::Int16*>(&vmtx->entries[countVmtxEntries]);
485 for (; i < countTopSideBearings; ++i, ++pTopSideBearingsExtra)
486 m_topSideBearings[i] = *pTopSideBearingsExtra;
490 void OpenTypeVerticalData::loadVerticalGlyphSubstitutions(const FontPlatformData& platformData)
492 RefPtr<SharedBuffer> buffer = platformData.openTypeTable(OpenType::GSUBTag);
493 const OpenType::GSUBTable* gsub = OpenType::validateTable<OpenType::GSUBTable>(buffer);
495 gsub->getVerticalGlyphSubstitutions(&m_verticalGlyphMap, *buffer.get());
498 float OpenTypeVerticalData::advanceHeight(const SimpleFontData* font, Glyph glyph) const
500 size_t countHeights = m_advanceHeights.size();
502 uint16_t advanceFUnit = m_advanceHeights[glyph < countHeights ? glyph : countHeights - 1];
503 float advance = advanceFUnit * font->sizePerUnit();
507 // No vertical info in the font file; use height as advance.
508 return font->fontMetrics().height();
511 void OpenTypeVerticalData::getVerticalTranslationsForGlyphs(const SimpleFontData* font, const Glyph* glyphs, size_t count, float* outXYArray) const
513 size_t countWidths = m_advanceWidths.size();
514 ASSERT(countWidths > 0);
515 const FontMetrics& metrics = font->fontMetrics();
516 float sizePerUnit = font->sizePerUnit();
517 float ascent = metrics.ascent();
518 bool useVORG = hasVORG();
519 size_t countTopSideBearings = m_topSideBearings.size();
520 float defaultVertOriginY = std::numeric_limits<float>::quiet_NaN();
521 for (float* end = &(outXYArray[count * 2]); outXYArray != end; ++glyphs, outXYArray += 2) {
522 Glyph glyph = *glyphs;
523 uint16_t widthFUnit = m_advanceWidths[glyph < countWidths ? glyph : countWidths - 1];
524 float width = widthFUnit * sizePerUnit;
525 outXYArray[0] = -width / 2;
527 // For Y, try VORG first.
529 int16_t vertOriginYFUnit = m_vertOriginY.get(glyph);
530 if (vertOriginYFUnit) {
531 outXYArray[1] = -vertOriginYFUnit * sizePerUnit;
534 if (std::isnan(defaultVertOriginY))
535 defaultVertOriginY = -m_defaultVertOriginY * sizePerUnit;
536 outXYArray[1] = defaultVertOriginY;
540 // If no VORG, try vmtx next.
541 if (countTopSideBearings) {
542 int16_t topSideBearingFUnit = m_topSideBearings[glyph < countTopSideBearings ? glyph : countTopSideBearings - 1];
543 float topSideBearing = topSideBearingFUnit * sizePerUnit;
544 FloatRect bounds = font->boundsForGlyph(glyph);
545 outXYArray[1] = bounds.y() - topSideBearing;
549 // No vertical info in the font file; use ascent as vertical origin.
550 outXYArray[1] = -ascent;
554 void OpenTypeVerticalData::substituteWithVerticalGlyphs(const SimpleFontData* font, GlyphPage* glyphPage, unsigned offset, unsigned length) const
556 const HashMap<Glyph, Glyph>& map = m_verticalGlyphMap;
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);
565 glyphPage->setGlyphDataForIndex(index, to, font);
571 #endif // ENABLE(OPENTYPE_VERTICAL)