1/* 2 * Copyright (C) 2012 Koji Ishii <kojiishi@gmail.com> 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 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. 12 * 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. 23 */ 24 25#include "config.h" 26#if ENABLE(OPENTYPE_VERTICAL) 27#include "OpenTypeVerticalData.h" 28 29#include "FloatRect.h" 30#include "GlyphPage.h" 31#include "OpenTypeTypes.h" 32#include "SharedBuffer.h" 33#include "SimpleFontData.h" 34#include <wtf/RefPtr.h> 35 36using namespace std; 37 38namespace WebCore { 39namespace OpenType { 40 41const uint32_t GSUBTag = OT_MAKE_TAG('G', 'S', 'U', 'B'); 42const uint32_t HheaTag = OT_MAKE_TAG('h', 'h', 'e', 'a'); 43const uint32_t HmtxTag = OT_MAKE_TAG('h', 'm', 't', 'x'); 44const uint32_t VheaTag = OT_MAKE_TAG('v', 'h', 'e', 'a'); 45const uint32_t VmtxTag = OT_MAKE_TAG('v', 'm', 't', 'x'); 46const uint32_t VORGTag = OT_MAKE_TAG('V', 'O', 'R', 'G'); 47 48const uint32_t DefaultScriptTag = OT_MAKE_TAG('D', 'F', 'L', 'T'); 49 50const uint32_t VertFeatureTag = OT_MAKE_TAG('v', 'e', 'r', 't'); 51 52#pragma pack(1) 53 54struct HheaTable { 55 OpenType::Fixed version; 56 OpenType::Int16 ascender; 57 OpenType::Int16 descender; 58 OpenType::Int16 lineGap; 59 OpenType::Int16 advanceWidthMax; 60 OpenType::Int16 minLeftSideBearing; 61 OpenType::Int16 minRightSideBearing; 62 OpenType::Int16 xMaxExtent; 63 OpenType::Int16 caretSlopeRise; 64 OpenType::Int16 caretSlopeRun; 65 OpenType::Int16 caretOffset; 66 OpenType::Int16 reserved[4]; 67 OpenType::Int16 metricDataFormat; 68 OpenType::UInt16 numberOfHMetrics; 69}; 70 71struct VheaTable { 72 OpenType::Fixed version; 73 OpenType::Int16 ascent; 74 OpenType::Int16 descent; 75 OpenType::Int16 lineGap; 76 OpenType::Int16 advanceHeightMax; 77 OpenType::Int16 minTopSideBearing; 78 OpenType::Int16 minBottomSideBearing; 79 OpenType::Int16 yMaxExtent; 80 OpenType::Int16 caretSlopeRise; 81 OpenType::Int16 caretSlopeRun; 82 OpenType::Int16 caretOffset; 83 OpenType::Int16 reserved[4]; 84 OpenType::Int16 metricDataFormat; 85 OpenType::UInt16 numOfLongVerMetrics; 86}; 87 88struct HmtxTable { 89 struct Entry { 90 OpenType::UInt16 advanceWidth; 91 OpenType::Int16 lsb; 92 } entries[1]; 93}; 94 95struct VmtxTable { 96 struct Entry { 97 OpenType::UInt16 advanceHeight; 98 OpenType::Int16 topSideBearing; 99 } entries[1]; 100}; 101 102struct VORGTable { 103 OpenType::UInt16 majorVersion; 104 OpenType::UInt16 minorVersion; 105 OpenType::Int16 defaultVertOriginY; 106 OpenType::UInt16 numVertOriginYMetrics; 107 struct VertOriginYMetrics { 108 OpenType::UInt16 glyphIndex; 109 OpenType::Int16 vertOriginY; 110 } vertOriginYMetrics[1]; 111 112 size_t requiredSize() const { return sizeof(*this) + sizeof(VertOriginYMetrics) * (numVertOriginYMetrics - 1); } 113}; 114 115struct SubstitutionSubTable : TableBase { 116 OpenType::UInt16 substFormat; 117 OpenType::Offset coverageOffset; 118 119 const CoverageTable* coverage(const SharedBuffer& buffer) const { return validateOffset<CoverageTable>(buffer, coverageOffset); } 120}; 121 122struct SingleSubstitution2SubTable : SubstitutionSubTable { 123 OpenType::UInt16 glyphCount; 124 OpenType::GlyphID substitute[1]; 125}; 126 127struct LookupTable : TableBase { 128 OpenType::UInt16 lookupType; 129 OpenType::UInt16 lookupFlag; 130 OpenType::UInt16 subTableCount; 131 OpenType::Offset subTableOffsets[1]; 132 // OpenType::UInt16 markFilteringSet; this field comes after variable length, so offset is determined dynamically. 133 134 bool getSubstitutions(HashMap<Glyph, Glyph>* map, const SharedBuffer& buffer) const 135 { 136 uint16_t countSubTable = subTableCount; 137 if (!isValidEnd(buffer, &subTableOffsets[countSubTable])) 138 return false; 139 if (lookupType != 1) // "Single Substitution Subtable" is all what we support 140 return false; 141 for (uint16_t i = 0; i < countSubTable; ++i) { 142 const SubstitutionSubTable* substitution = validateOffset<SubstitutionSubTable>(buffer, subTableOffsets[i]); 143 if (!substitution) 144 return false; 145 const CoverageTable* coverage = substitution->coverage(buffer); 146 if (!coverage) 147 return false; 148 if (substitution->substFormat != 2) // "Single Substitution Format 2" is all what we support 149 return false; 150 const SingleSubstitution2SubTable* singleSubstitution2 = validatePtr<SingleSubstitution2SubTable>(buffer, substitution); 151 if (!singleSubstitution2) 152 return false; 153 uint16_t countTo = singleSubstitution2->glyphCount; 154 if (!isValidEnd(buffer, &singleSubstitution2->substitute[countTo])) 155 return false; 156 switch (coverage->coverageFormat) { 157 case 1: { // Coverage Format 1 (e.g., MS Gothic) 158 const Coverage1Table* coverage1 = validatePtr<Coverage1Table>(buffer, coverage); 159 if (!coverage1) 160 return false; 161 uint16_t countFrom = coverage1->glyphCount; 162 if (!isValidEnd(buffer, &coverage1->glyphArray[countFrom]) || countTo != countFrom) 163 return false; 164 for (uint16_t i = 0; i < countTo; ++i) 165 map->set(coverage1->glyphArray[i], singleSubstitution2->substitute[i]); 166 break; 167 } 168 case 2: { // Coverage Format 2 (e.g., Adobe Kozuka Gothic) 169 const Coverage2Table* coverage2 = validatePtr<Coverage2Table>(buffer, coverage); 170 if (!coverage2) 171 return false; 172 uint16_t countRange = coverage2->rangeCount; 173 if (!isValidEnd(buffer, &coverage2->ranges[countRange])) 174 return false; 175 for (uint16_t i = 0, indexTo = 0; i < countRange; ++i) { 176 uint16_t from = coverage2->ranges[i].start; 177 uint16_t fromEnd = coverage2->ranges[i].end + 1; // OpenType "end" is inclusive 178 if (indexTo + (fromEnd - from) > countTo) 179 return false; 180 for (; from != fromEnd; ++from, ++indexTo) 181 map->set(from, singleSubstitution2->substitute[indexTo]); 182 } 183 break; 184 } 185 default: 186 return false; 187 } 188 } 189 return true; 190 } 191}; 192 193struct LookupList : TableBase { 194 OpenType::UInt16 lookupCount; 195 OpenType::Offset lookupOffsets[1]; 196 197 const LookupTable* lookup(uint16_t index, const SharedBuffer& buffer) const 198 { 199 uint16_t count = lookupCount; 200 if (index >= count || !isValidEnd(buffer, &lookupOffsets[count])) 201 return 0; 202 return validateOffset<LookupTable>(buffer, lookupOffsets[index]); 203 } 204}; 205 206struct FeatureTable : TableBase { 207 OpenType::Offset featureParams; 208 OpenType::UInt16 lookupCount; 209 OpenType::UInt16 lookupListIndex[1]; 210 211 bool getGlyphSubstitutions(const LookupList* lookups, HashMap<Glyph, Glyph>* map, const SharedBuffer& buffer) const 212 { 213 uint16_t count = lookupCount; 214 if (!isValidEnd(buffer, &lookupListIndex[count])) 215 return false; 216 for (uint16_t i = 0; i < count; ++i) { 217 const LookupTable* lookup = lookups->lookup(lookupListIndex[i], buffer); 218 if (!lookup || !lookup->getSubstitutions(map, buffer)) 219 return false; 220 } 221 return true; 222 } 223}; 224 225struct FeatureList : TableBase { 226 OpenType::UInt16 featureCount; 227 struct FeatureRecord { 228 OpenType::Tag featureTag; 229 OpenType::Offset featureOffset; 230 } features[1]; 231 232 const FeatureTable* feature(uint16_t index, OpenType::Tag tag, const SharedBuffer& buffer) const 233 { 234 uint16_t count = featureCount; 235 if (index >= count || !isValidEnd(buffer, &features[count])) 236 return 0; 237 if (features[index].featureTag == tag) 238 return validateOffset<FeatureTable>(buffer, features[index].featureOffset); 239 return 0; 240 } 241 242 const FeatureTable* findFeature(OpenType::Tag tag, const SharedBuffer& buffer) const 243 { 244 for (uint16_t i = 0; i < featureCount; ++i) { 245 if (isValidEnd(buffer, &features[i]) && features[i].featureTag == tag) 246 return validateOffset<FeatureTable>(buffer, features[i].featureOffset); 247 } 248 return 0; 249 } 250}; 251 252struct LangSysTable : TableBase { 253 OpenType::Offset lookupOrder; 254 OpenType::UInt16 reqFeatureIndex; 255 OpenType::UInt16 featureCount; 256 OpenType::UInt16 featureIndex[1]; 257 258 const FeatureTable* feature(OpenType::Tag featureTag, const FeatureList* features, const SharedBuffer& buffer) const 259 { 260 uint16_t count = featureCount; 261 if (!isValidEnd(buffer, &featureIndex[count])) 262 return 0; 263 for (uint16_t i = 0; i < count; ++i) { 264 const FeatureTable* featureTable = features->feature(featureIndex[i], featureTag, buffer); 265 if (featureTable) 266 return featureTable; 267 } 268 return 0; 269 } 270}; 271 272struct ScriptTable : TableBase { 273 OpenType::Offset defaultLangSysOffset; 274 OpenType::UInt16 langSysCount; 275 struct LangSysRecord { 276 OpenType::Tag langSysTag; 277 OpenType::Offset langSysOffset; 278 } langSysRecords[1]; 279 280 const LangSysTable* defaultLangSys(const SharedBuffer& buffer) const 281 { 282 uint16_t count = langSysCount; 283 if (!isValidEnd(buffer, &langSysRecords[count])) 284 return 0; 285 uint16_t offset = defaultLangSysOffset; 286 if (offset) 287 return validateOffset<LangSysTable>(buffer, offset); 288 if (count) 289 return validateOffset<LangSysTable>(buffer, langSysRecords[0].langSysOffset); 290 return 0; 291 } 292}; 293 294struct ScriptList : TableBase { 295 OpenType::UInt16 scriptCount; 296 struct ScriptRecord { 297 OpenType::Tag scriptTag; 298 OpenType::Offset scriptOffset; 299 } scripts[1]; 300 301 const ScriptTable* script(OpenType::Tag tag, const SharedBuffer& buffer) const 302 { 303 uint16_t count = scriptCount; 304 if (!isValidEnd(buffer, &scripts[count])) 305 return 0; 306 for (uint16_t i = 0; i < count; ++i) { 307 if (scripts[i].scriptTag == tag) 308 return validateOffset<ScriptTable>(buffer, scripts[i].scriptOffset); 309 } 310 return 0; 311 } 312 313 const ScriptTable* defaultScript(const SharedBuffer& buffer) const 314 { 315 uint16_t count = scriptCount; 316 if (!count || !isValidEnd(buffer, &scripts[count])) 317 return 0; 318 const ScriptTable* scriptOfDefaultTag = script(OpenType::DefaultScriptTag, buffer); 319 if (scriptOfDefaultTag) 320 return scriptOfDefaultTag; 321 return validateOffset<ScriptTable>(buffer, scripts[0].scriptOffset); 322 } 323 324 const LangSysTable* defaultLangSys(const SharedBuffer& buffer) const 325 { 326 const ScriptTable* scriptTable = defaultScript(buffer); 327 if (!scriptTable) 328 return 0; 329 return scriptTable->defaultLangSys(buffer); 330 } 331}; 332 333struct GSUBTable : TableBase { 334 OpenType::Fixed version; 335 OpenType::Offset scriptListOffset; 336 OpenType::Offset featureListOffset; 337 OpenType::Offset lookupListOffset; 338 339 const ScriptList* scriptList(const SharedBuffer& buffer) const { return validateOffset<ScriptList>(buffer, scriptListOffset); } 340 const FeatureList* featureList(const SharedBuffer& buffer) const { return validateOffset<FeatureList>(buffer, featureListOffset); } 341 const LookupList* lookupList(const SharedBuffer& buffer) const { return validateOffset<LookupList>(buffer, lookupListOffset); } 342 343 const LangSysTable* defaultLangSys(const SharedBuffer& buffer) const 344 { 345 const ScriptList* scripts = scriptList(buffer); 346 if (!scripts) 347 return 0; 348 return scripts->defaultLangSys(buffer); 349 } 350 351 const FeatureTable* feature(OpenType::Tag featureTag, const SharedBuffer& buffer) const 352 { 353 const LangSysTable* langSys = defaultLangSys(buffer); 354 const FeatureList* features = featureList(buffer); 355 if (!features) 356 return 0; 357 const FeatureTable* feature = 0; 358 if (langSys) 359 feature = langSys->feature(featureTag, features, buffer); 360 if (!feature) { 361 // If the font has no langSys table, or has no default script and the first script doesn't 362 // have the requested feature, then use the first matching feature directly. 363 feature = features->findFeature(featureTag, buffer); 364 } 365 return feature; 366 } 367 368 bool getVerticalGlyphSubstitutions(HashMap<Glyph, Glyph>* map, const SharedBuffer& buffer) const 369 { 370 const FeatureTable* verticalFeatureTable = feature(OpenType::VertFeatureTag, buffer); 371 if (!verticalFeatureTable) 372 return false; 373 const LookupList* lookups = lookupList(buffer); 374 return lookups && verticalFeatureTable->getGlyphSubstitutions(lookups, map, buffer); 375 } 376}; 377 378#pragma pack() 379 380} // namespace OpenType 381 382OpenTypeVerticalData::OpenTypeVerticalData(const FontPlatformData& platformData) 383 : m_defaultVertOriginY(0) 384{ 385 loadMetrics(platformData); 386 loadVerticalGlyphSubstitutions(platformData); 387} 388 389void OpenTypeVerticalData::loadMetrics(const FontPlatformData& platformData) 390{ 391 // Load hhea and hmtx to get x-component of vertical origins. 392 // If these tables are missing, it's not an OpenType font. 393 RefPtr<SharedBuffer> buffer = platformData.openTypeTable(OpenType::HheaTag); 394 const OpenType::HheaTable* hhea = OpenType::validateTable<OpenType::HheaTable>(buffer); 395 if (!hhea) 396 return; 397 uint16_t countHmtxEntries = hhea->numberOfHMetrics; 398 if (!countHmtxEntries) { 399 LOG_ERROR("Invalid numberOfHMetrics"); 400 return; 401 } 402 403 buffer = platformData.openTypeTable(OpenType::HmtxTag); 404 const OpenType::HmtxTable* hmtx = OpenType::validateTable<OpenType::HmtxTable>(buffer, countHmtxEntries); 405 if (!hmtx) { 406 LOG_ERROR("hhea exists but hmtx does not (or broken)"); 407 return; 408 } 409 m_advanceWidths.resize(countHmtxEntries); 410 for (uint16_t i = 0; i < countHmtxEntries; ++i) 411 m_advanceWidths[i] = hmtx->entries[i].advanceWidth; 412 413 // Load vhea first. This table is required for fonts that support vertical flow. 414 buffer = platformData.openTypeTable(OpenType::VheaTag); 415 const OpenType::VheaTable* vhea = OpenType::validateTable<OpenType::VheaTable>(buffer); 416 if (!vhea) 417 return; 418 uint16_t countVmtxEntries = vhea->numOfLongVerMetrics; 419 if (!countVmtxEntries) { 420 LOG_ERROR("Invalid numOfLongVerMetrics"); 421 return; 422 } 423 424 // Load VORG. This table is optional. 425 buffer = platformData.openTypeTable(OpenType::VORGTag); 426 const OpenType::VORGTable* vorg = OpenType::validateTable<OpenType::VORGTable>(buffer); 427 if (vorg && buffer->size() >= vorg->requiredSize()) { 428 m_defaultVertOriginY = vorg->defaultVertOriginY; 429 uint16_t countVertOriginYMetrics = vorg->numVertOriginYMetrics; 430 if (!countVertOriginYMetrics) { 431 // Add one entry so that hasVORG() becomes true 432 m_vertOriginY.set(0, m_defaultVertOriginY); 433 } else { 434 for (uint16_t i = 0; i < countVertOriginYMetrics; ++i) { 435 const OpenType::VORGTable::VertOriginYMetrics& metrics = vorg->vertOriginYMetrics[i]; 436 m_vertOriginY.set(metrics.glyphIndex, metrics.vertOriginY); 437 } 438 } 439 } 440 441 // Load vmtx then. This table is required for fonts that support vertical flow. 442 buffer = platformData.openTypeTable(OpenType::VmtxTag); 443 const OpenType::VmtxTable* vmtx = OpenType::validateTable<OpenType::VmtxTable>(buffer, countVmtxEntries); 444 if (!vmtx) { 445 LOG_ERROR("vhea exists but vmtx does not (or broken)"); 446 return; 447 } 448 m_advanceHeights.resize(countVmtxEntries); 449 for (uint16_t i = 0; i < countVmtxEntries; ++i) 450 m_advanceHeights[i] = vmtx->entries[i].advanceHeight; 451 452 // VORG is preferred way to calculate vertical origin than vmtx, 453 // so load topSideBearing from vmtx only if VORG is missing. 454 if (hasVORG()) 455 return; 456 457 size_t sizeExtra = buffer->size() - sizeof(OpenType::VmtxTable::Entry) * countVmtxEntries; 458 if (sizeExtra % sizeof(OpenType::Int16)) { 459 LOG_ERROR("vmtx has incorrect tsb count"); 460 return; 461 } 462 size_t countTopSideBearings = countVmtxEntries + sizeExtra / sizeof(OpenType::Int16); 463 m_topSideBearings.resize(countTopSideBearings); 464 size_t i; 465 for (i = 0; i < countVmtxEntries; ++i) 466 m_topSideBearings[i] = vmtx->entries[i].topSideBearing; 467 if (i < countTopSideBearings) { 468 const OpenType::Int16* pTopSideBearingsExtra = reinterpret_cast<const OpenType::Int16*>(&vmtx->entries[countVmtxEntries]); 469 for (; i < countTopSideBearings; ++i, ++pTopSideBearingsExtra) 470 m_topSideBearings[i] = *pTopSideBearingsExtra; 471 } 472} 473 474void OpenTypeVerticalData::loadVerticalGlyphSubstitutions(const FontPlatformData& platformData) 475{ 476 RefPtr<SharedBuffer> buffer = platformData.openTypeTable(OpenType::GSUBTag); 477 const OpenType::GSUBTable* gsub = OpenType::validateTable<OpenType::GSUBTable>(buffer); 478 if (gsub) 479 gsub->getVerticalGlyphSubstitutions(&m_verticalGlyphMap, *buffer.get()); 480} 481 482float OpenTypeVerticalData::advanceHeight(const SimpleFontData* font, Glyph glyph) const 483{ 484 size_t countHeights = m_advanceHeights.size(); 485 if (countHeights) { 486 uint16_t advanceFUnit = m_advanceHeights[glyph < countHeights ? glyph : countHeights - 1]; 487 float advance = advanceFUnit * font->sizePerUnit(); 488 return advance; 489 } 490 491 // No vertical info in the font file; use height as advance. 492 return font->fontMetrics().height(); 493} 494 495void OpenTypeVerticalData::getVerticalTranslationsForGlyphs(const SimpleFontData* font, const Glyph* glyphs, size_t count, float* outXYArray) const 496{ 497 size_t countWidths = m_advanceWidths.size(); 498 ASSERT(countWidths > 0); 499 const FontMetrics& metrics = font->fontMetrics(); 500 float sizePerUnit = font->sizePerUnit(); 501 float ascent = metrics.ascent(); 502 bool useVORG = hasVORG(); 503 size_t countTopSideBearings = m_topSideBearings.size(); 504 float defaultVertOriginY = std::numeric_limits<float>::quiet_NaN(); 505 for (float* end = &(outXYArray[count * 2]); outXYArray != end; ++glyphs, outXYArray += 2) { 506 Glyph glyph = *glyphs; 507 uint16_t widthFUnit = m_advanceWidths[glyph < countWidths ? glyph : countWidths - 1]; 508 float width = widthFUnit * sizePerUnit; 509 outXYArray[0] = -width / 2; 510 511 // For Y, try VORG first. 512 if (useVORG) { 513 int16_t vertOriginYFUnit = m_vertOriginY.get(glyph); 514 if (vertOriginYFUnit) { 515 outXYArray[1] = -vertOriginYFUnit * sizePerUnit; 516 continue; 517 } 518 if (std::isnan(defaultVertOriginY)) 519 defaultVertOriginY = -m_defaultVertOriginY * sizePerUnit; 520 outXYArray[1] = defaultVertOriginY; 521 continue; 522 } 523 524 // If no VORG, try vmtx next. 525 if (countTopSideBearings) { 526 int16_t topSideBearingFUnit = m_topSideBearings[glyph < countTopSideBearings ? glyph : countTopSideBearings - 1]; 527 float topSideBearing = topSideBearingFUnit * sizePerUnit; 528 FloatRect bounds = font->boundsForGlyph(glyph); 529 outXYArray[1] = bounds.y() - topSideBearing; 530 continue; 531 } 532 533 // No vertical info in the font file; use ascent as vertical origin. 534 outXYArray[1] = -ascent; 535 } 536} 537 538void OpenTypeVerticalData::substituteWithVerticalGlyphs(const SimpleFontData* font, GlyphPage* glyphPage, unsigned offset, unsigned length) const 539{ 540 const HashMap<Glyph, Glyph>& map = m_verticalGlyphMap; 541 if (map.isEmpty()) 542 return; 543 544 for (unsigned index = offset, end = offset + length; index < end; ++index) { 545 Glyph glyph = glyphPage->glyphAt(index); 546 if (glyph) { 547 ASSERT(glyphPage->glyphDataForIndex(index).fontData == font); 548 Glyph to = map.get(glyph); 549 if (to) 550 glyphPage->setGlyphDataForIndex(index, to, font); 551 } 552 } 553} 554 555} // namespace WebCore 556#endif // ENABLE(OPENTYPE_VERTICAL) 557