| 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 |