1/* 2 * Copyright (C) 2006, 2013 Apple Inc. All rights reserved. 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 * 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. Neither the name of Apple Inc. ("Apple") nor the names of 14 * its contributors may be used to endorse or promote products derived 15 * from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29#include "config.h" 30#include "FontGlyphs.h" 31 32#include "Font.h" 33#include "FontCache.h" 34#include "SegmentedFontData.h" 35 36namespace WebCore { 37 38 39FontGlyphs::FontGlyphs(PassRefPtr<FontSelector> fontSelector) 40 : m_pageZero(0) 41 , m_cachedPrimarySimpleFontData(0) 42 , m_fontSelector(fontSelector) 43 , m_fontSelectorVersion(m_fontSelector ? m_fontSelector->version() : 0) 44 , m_familyIndex(0) 45 , m_generation(fontCache().generation()) 46 , m_pitch(UnknownPitch) 47 , m_loadingCustomFonts(false) 48 , m_isForPlatformFont(false) 49{ 50} 51 52FontGlyphs::FontGlyphs(const FontPlatformData& platformData) 53 : m_pageZero(0) 54 , m_cachedPrimarySimpleFontData(0) 55 , m_fontSelector(0) 56 , m_fontSelectorVersion(0) 57 , m_familyIndex(cAllFamiliesScanned) 58 , m_generation(fontCache().generation()) 59 , m_pitch(UnknownPitch) 60 , m_loadingCustomFonts(false) 61 , m_isForPlatformFont(true) 62{ 63 RefPtr<FontData> fontData = fontCache().getCachedFontData(&platformData); 64 m_realizedFontData.append(fontData.release()); 65} 66 67void FontGlyphs::releaseFontData() 68{ 69 unsigned numFonts = m_realizedFontData.size(); 70 for (unsigned i = 0; i < numFonts; ++i) { 71 if (m_realizedFontData[i]->isCustomFont()) 72 continue; 73 ASSERT(!m_realizedFontData[i]->isSegmented()); 74 fontCache().releaseFontData(static_cast<const SimpleFontData*>(m_realizedFontData[i].get())); 75 } 76} 77 78void FontGlyphs::determinePitch(const FontDescription& description) const 79{ 80 const FontData* fontData = primaryFontData(description); 81 if (!fontData->isSegmented()) 82 m_pitch = static_cast<const SimpleFontData*>(fontData)->pitch(); 83 else { 84 const SegmentedFontData* segmentedFontData = static_cast<const SegmentedFontData*>(fontData); 85 unsigned numRanges = segmentedFontData->numRanges(); 86 if (numRanges == 1) 87 m_pitch = segmentedFontData->rangeAt(0).fontData()->pitch(); 88 else 89 m_pitch = VariablePitch; 90 } 91} 92 93const FontData* FontGlyphs::realizeFontDataAt(const FontDescription& description, unsigned realizedFontIndex) const 94{ 95 if (realizedFontIndex < m_realizedFontData.size()) 96 return m_realizedFontData[realizedFontIndex].get(); // This fallback font is already in our list. 97 98 // Make sure we're not passing in some crazy value here. 99 ASSERT(realizedFontIndex == m_realizedFontData.size()); 100 101 if (m_familyIndex <= cAllFamiliesScanned) { 102 if (!m_fontSelector) 103 return 0; 104 105 size_t index = cAllFamiliesScanned - m_familyIndex; 106 if (index == m_fontSelector->fallbackFontDataCount()) 107 return 0; 108 109 m_familyIndex--; 110 RefPtr<FontData> fallback = m_fontSelector->getFallbackFontData(description, index); 111 if (fallback) 112 m_realizedFontData.append(fallback); 113 return fallback.get(); 114 } 115 116 // Ask the font cache for the font data. 117 // We are obtaining this font for the first time. We keep track of the families we've looked at before 118 // in |m_familyIndex|, so that we never scan the same spot in the list twice. getFontData will adjust our 119 // |m_familyIndex| as it scans for the right font to make. 120 ASSERT(fontCache().generation() == m_generation); 121 RefPtr<FontData> result = fontCache().getFontData(description, m_familyIndex, m_fontSelector.get()); 122 if (result) { 123 m_realizedFontData.append(result); 124 if (result->isLoading()) 125 m_loadingCustomFonts = true; 126 } 127 return result.get(); 128} 129 130static inline bool isInRange(UChar32 character, UChar32 lowerBound, UChar32 upperBound) 131{ 132 return character >= lowerBound && character <= upperBound; 133} 134 135static bool shouldIgnoreRotation(UChar32 character) 136{ 137 if (character == 0x000A7 || character == 0x000A9 || character == 0x000AE) 138 return true; 139 140 if (character == 0x000B6 || character == 0x000BC || character == 0x000BD || character == 0x000BE) 141 return true; 142 143 if (isInRange(character, 0x002E5, 0x002EB)) 144 return true; 145 146 if (isInRange(character, 0x01100, 0x011FF) || isInRange(character, 0x01401, 0x0167F) || isInRange(character, 0x01800, 0x018FF)) 147 return true; 148 149 if (character == 0x02016 || character == 0x02018 || character == 0x02019 || character == 0x02020 || character == 0x02021 150 || character == 0x2030 || character == 0x02031) 151 return true; 152 153 if (isInRange(character, 0x0203B, 0x0203D) || character == 0x02042 || character == 0x02044 || character == 0x02047 154 || character == 0x02048 || character == 0x02049 || character == 0x2051) 155 return true; 156 157 if (isInRange(character, 0x02065, 0x02069) || isInRange(character, 0x020DD, 0x020E0) 158 || isInRange(character, 0x020E2, 0x020E4) || isInRange(character, 0x02100, 0x02117) 159 || isInRange(character, 0x02119, 0x02131) || isInRange(character, 0x02133, 0x0213F)) 160 return true; 161 162 if (isInRange(character, 0x02145, 0x0214A) || character == 0x0214C || character == 0x0214D 163 || isInRange(character, 0x0214F, 0x0218F)) 164 return true; 165 166 if (isInRange(character, 0x02300, 0x02307) || isInRange(character, 0x0230C, 0x0231F) 167 || isInRange(character, 0x02322, 0x0232B) || isInRange(character, 0x0237D, 0x0239A) 168 || isInRange(character, 0x023B4, 0x023B6) || isInRange(character, 0x023BA, 0x023CF) 169 || isInRange(character, 0x023D1, 0x023DB) || isInRange(character, 0x023E2, 0x024FF)) 170 return true; 171 172 if (isInRange(character, 0x025A0, 0x02619) || isInRange(character, 0x02620, 0x02767) 173 || isInRange(character, 0x02776, 0x02793) || isInRange(character, 0x02B12, 0x02B2F) 174 || isInRange(character, 0x02B4D, 0x02BFF) || isInRange(character, 0x02E80, 0x03007)) 175 return true; 176 177 if (character == 0x03012 || character == 0x03013 || isInRange(character, 0x03020, 0x0302F) 178 || isInRange(character, 0x03031, 0x0309F) || isInRange(character, 0x030A1, 0x030FB) 179 || isInRange(character, 0x030FD, 0x0A4CF)) 180 return true; 181 182 if (isInRange(character, 0x0A840, 0x0A87F) || isInRange(character, 0x0A960, 0x0A97F) 183 || isInRange(character, 0x0AC00, 0x0D7FF) || isInRange(character, 0x0E000, 0x0FAFF)) 184 return true; 185 186 if (isInRange(character, 0x0FE10, 0x0FE1F) || isInRange(character, 0x0FE30, 0x0FE48) 187 || isInRange(character, 0x0FE50, 0x0FE57) || isInRange(character, 0x0FE5F, 0x0FE62) 188 || isInRange(character, 0x0FE67, 0x0FE6F)) 189 return true; 190 191 if (isInRange(character, 0x0FF01, 0x0FF07) || isInRange(character, 0x0FF0A, 0x0FF0C) 192 || isInRange(character, 0x0FF0E, 0x0FF19) || character == 0x0FF1B || isInRange(character, 0x0FF1F, 0x0FF3A)) 193 return true; 194 195 if (character == 0x0FF3C || character == 0x0FF3E) 196 return true; 197 198 if (isInRange(character, 0x0FF40, 0x0FF5A) || isInRange(character, 0x0FFE0, 0x0FFE2) 199 || isInRange(character, 0x0FFE4, 0x0FFE7) || isInRange(character, 0x0FFF0, 0x0FFF8) 200 || character == 0x0FFFD) 201 return true; 202 203 if (isInRange(character, 0x13000, 0x1342F) || isInRange(character, 0x1B000, 0x1B0FF) 204 || isInRange(character, 0x1D000, 0x1D1FF) || isInRange(character, 0x1D300, 0x1D37F) 205 || isInRange(character, 0x1F000, 0x1F64F) || isInRange(character, 0x1F680, 0x1F77F)) 206 return true; 207 208 if (isInRange(character, 0x20000, 0x2FFFD) || isInRange(character, 0x30000, 0x3FFFD)) 209 return true; 210 211 return false; 212} 213 214static inline std::pair<GlyphData, GlyphPage*> glyphDataAndPageForCJKCharacterWithoutSyntheticItalic(UChar32 character, GlyphData& data, GlyphPage* page, unsigned pageNumber) 215{ 216 RefPtr<SimpleFontData> nonItalicFontData = data.fontData->nonSyntheticItalicFontData(); 217 GlyphPageTreeNode* nonItalicNode = GlyphPageTreeNode::getRootChild(nonItalicFontData.get(), pageNumber); 218 GlyphPage* nonItalicPage = nonItalicNode->page(); 219 if (nonItalicPage) { 220 GlyphData nonItalicData = nonItalicPage->glyphDataForCharacter(character); 221 if (nonItalicData.fontData) 222 return std::make_pair(nonItalicData, nonItalicPage); 223 } 224 return std::make_pair(data, page); 225} 226 227static inline std::pair<GlyphData, GlyphPage*> glyphDataAndPageForNonCJKCharacterWithGlyphOrientation(UChar32 character, NonCJKGlyphOrientation orientation, GlyphData& data, GlyphPage* page, unsigned pageNumber) 228{ 229 if (orientation == NonCJKGlyphOrientationUpright || shouldIgnoreRotation(character)) { 230 RefPtr<SimpleFontData> uprightFontData = data.fontData->uprightOrientationFontData(); 231 GlyphPageTreeNode* uprightNode = GlyphPageTreeNode::getRootChild(uprightFontData.get(), pageNumber); 232 GlyphPage* uprightPage = uprightNode->page(); 233 if (uprightPage) { 234 GlyphData uprightData = uprightPage->glyphDataForCharacter(character); 235 // If the glyphs are the same, then we know we can just use the horizontal glyph rotated vertically to be upright. 236 if (data.glyph == uprightData.glyph) 237 return std::make_pair(data, page); 238 // The glyphs are distinct, meaning that the font has a vertical-right glyph baked into it. We can't use that 239 // glyph, so we fall back to the upright data and use the horizontal glyph. 240 if (uprightData.fontData) 241 return std::make_pair(uprightData, uprightPage); 242 } 243 } else if (orientation == NonCJKGlyphOrientationVerticalRight) { 244 RefPtr<SimpleFontData> verticalRightFontData = data.fontData->verticalRightOrientationFontData(); 245 GlyphPageTreeNode* verticalRightNode = GlyphPageTreeNode::getRootChild(verticalRightFontData.get(), pageNumber); 246 GlyphPage* verticalRightPage = verticalRightNode->page(); 247 if (verticalRightPage) { 248 GlyphData verticalRightData = verticalRightPage->glyphDataForCharacter(character); 249 // If the glyphs are distinct, we will make the assumption that the font has a vertical-right glyph baked 250 // into it. 251 if (data.glyph != verticalRightData.glyph) 252 return std::make_pair(data, page); 253 // The glyphs are identical, meaning that we should just use the horizontal glyph. 254 if (verticalRightData.fontData) 255 return std::make_pair(verticalRightData, verticalRightPage); 256 } 257 } 258 return std::make_pair(data, page); 259} 260 261std::pair<GlyphData, GlyphPage*> FontGlyphs::glyphDataAndPageForCharacter(const FontDescription& description, UChar32 c, bool mirror, FontDataVariant variant) const 262{ 263 ASSERT(isMainThread()); 264 265 if (variant == AutoVariant) { 266 if (description.smallCaps() && !primarySimpleFontData(description)->isSVGFont()) { 267 UChar32 upperC = u_toupper(c); 268 if (upperC != c) { 269 c = upperC; 270 variant = SmallCapsVariant; 271 } else 272 variant = NormalVariant; 273 } else 274 variant = NormalVariant; 275 } 276 277 if (mirror) 278 c = u_charMirror(c); 279 280 unsigned pageNumber = (c / GlyphPage::size); 281 282 GlyphPageTreeNode* node = pageNumber ? m_pages.get(pageNumber) : m_pageZero; 283 if (!node) { 284 node = GlyphPageTreeNode::getRootChild(realizeFontDataAt(description, 0), pageNumber); 285 if (pageNumber) 286 m_pages.set(pageNumber, node); 287 else 288 m_pageZero = node; 289 } 290 291 GlyphPage* page = 0; 292 if (variant == NormalVariant) { 293 // Fastest loop, for the common case (normal variant). 294 while (true) { 295 page = node->page(); 296 if (page) { 297 GlyphData data = page->glyphDataForCharacter(c); 298 if (data.fontData && (data.fontData->platformData().orientation() == Horizontal || data.fontData->isTextOrientationFallback())) 299 return std::make_pair(data, page); 300 301 if (data.fontData) { 302 if (Font::isCJKIdeographOrSymbol(c)) { 303 if (!data.fontData->hasVerticalGlyphs()) { 304 // Use the broken ideograph font data. The broken ideograph font will use the horizontal width of glyphs 305 // to make sure you get a square (even for broken glyphs like symbols used for punctuation). 306 variant = BrokenIdeographVariant; 307 break; 308 } 309#if PLATFORM(COCOA) 310 else if (data.fontData->platformData().syntheticOblique()) 311 return glyphDataAndPageForCJKCharacterWithoutSyntheticItalic(c, data, page, pageNumber); 312#endif 313 } else 314 return glyphDataAndPageForNonCJKCharacterWithGlyphOrientation(c, description.nonCJKGlyphOrientation(), data, page, pageNumber); 315 316 return std::make_pair(data, page); 317 } 318 319 if (node->isSystemFallback()) 320 break; 321 } 322 323 node = node->getChild(realizeFontDataAt(description, node->level()), pageNumber); 324 if (pageNumber) 325 m_pages.set(pageNumber, node); 326 else 327 m_pageZero = node; 328 } 329 } 330 if (variant != NormalVariant) { 331 while (true) { 332 page = node->page(); 333 if (page) { 334 GlyphData data = page->glyphDataForCharacter(c); 335 if (data.fontData) { 336 // The variantFontData function should not normally return 0. 337 // But if it does, we will just render the capital letter big. 338 RefPtr<SimpleFontData> variantFontData = data.fontData->variantFontData(description, variant); 339 if (!variantFontData) 340 return std::make_pair(data, page); 341 342 GlyphPageTreeNode* variantNode = GlyphPageTreeNode::getRootChild(variantFontData.get(), pageNumber); 343 GlyphPage* variantPage = variantNode->page(); 344 if (variantPage) { 345 GlyphData data = variantPage->glyphDataForCharacter(c); 346 if (data.fontData) 347 return std::make_pair(data, variantPage); 348 } 349 350 // Do not attempt system fallback off the variantFontData. This is the very unlikely case that 351 // a font has the lowercase character but the small caps font does not have its uppercase version. 352 return std::make_pair(variantFontData->missingGlyphData(), page); 353 } 354 355 if (node->isSystemFallback()) 356 break; 357 } 358 359 node = node->getChild(realizeFontDataAt(description, node->level()), pageNumber); 360 if (pageNumber) 361 m_pages.set(pageNumber, node); 362 else 363 m_pageZero = node; 364 } 365 } 366 367 ASSERT(page); 368 ASSERT(node->isSystemFallback()); 369 370 // System fallback is character-dependent. When we get here, we 371 // know that the character in question isn't in the system fallback 372 // font's glyph page. Try to lazily create it here. 373 UChar codeUnits[2]; 374 int codeUnitsLength; 375 if (c <= 0xFFFF) { 376 codeUnits[0] = Font::normalizeSpaces(c); 377 codeUnitsLength = 1; 378 } else { 379 codeUnits[0] = U16_LEAD(c); 380 codeUnits[1] = U16_TRAIL(c); 381 codeUnitsLength = 2; 382 } 383 const SimpleFontData* originalFontData = primaryFontData(description)->fontDataForCharacter(c); 384 RefPtr<SimpleFontData> characterFontData = fontCache().systemFallbackForCharacters(description, originalFontData, m_isForPlatformFont, codeUnits, codeUnitsLength); 385 if (characterFontData) { 386 if (characterFontData->platformData().orientation() == Vertical && !characterFontData->hasVerticalGlyphs() && Font::isCJKIdeographOrSymbol(c)) 387 variant = BrokenIdeographVariant; 388 if (variant != NormalVariant) 389 characterFontData = characterFontData->variantFontData(description, variant); 390 } 391 if (characterFontData) { 392 // Got the fallback glyph and font. 393 GlyphPage* fallbackPage = GlyphPageTreeNode::getRootChild(characterFontData.get(), pageNumber)->page(); 394 GlyphData data = fallbackPage && fallbackPage->fontDataForCharacter(c) ? fallbackPage->glyphDataForCharacter(c) : characterFontData->missingGlyphData(); 395 // Cache it so we don't have to do system fallback again next time. 396 if (variant == NormalVariant) { 397#if OS(WINCE) 398 // missingGlyphData returns a null character, which is not suitable for GDI to display. 399 // Also, sometimes we cannot map a font for the character on WINCE, but GDI can still 400 // display the character, probably because the font package is not installed correctly. 401 // So we just always set the glyph to be same as the character, and let GDI solve it. 402 page->setGlyphDataForCharacter(c, c, characterFontData.get()); 403 characterFontData->setMaxGlyphPageTreeLevel(std::max(characterFontData->maxGlyphPageTreeLevel(), node->level())); 404 return std::make_pair(page->glyphDataForCharacter(c), page); 405#else 406 page->setGlyphDataForCharacter(c, data.glyph, data.fontData); 407 data.fontData->setMaxGlyphPageTreeLevel(std::max(data.fontData->maxGlyphPageTreeLevel(), node->level())); 408 if (!Font::isCJKIdeographOrSymbol(c) && data.fontData->platformData().orientation() != Horizontal && !data.fontData->isTextOrientationFallback()) 409 return glyphDataAndPageForNonCJKCharacterWithGlyphOrientation(c, description.nonCJKGlyphOrientation(), data, fallbackPage, pageNumber); 410#endif 411 } 412 return std::make_pair(data, page); 413 } 414 415 // Even system fallback can fail; use the missing glyph in that case. 416 // FIXME: It would be nicer to use the missing glyph from the last resort font instead. 417 GlyphData data = primarySimpleFontData(description)->missingGlyphData(); 418 if (variant == NormalVariant) { 419#if OS(WINCE) 420 // See comment about WINCE GDI handling near setGlyphDataForCharacter above. 421 page->setGlyphDataForCharacter(c, c, data.fontData); 422 data.fontData->setMaxGlyphPageTreeLevel(std::max(data.fontData->maxGlyphPageTreeLevel(), node->level())); 423 return std::make_pair(page->glyphDataForCharacter(c), page); 424#else 425 page->setGlyphDataForCharacter(c, data.glyph, data.fontData); 426 data.fontData->setMaxGlyphPageTreeLevel(std::max(data.fontData->maxGlyphPageTreeLevel(), node->level())); 427#endif 428 } 429 return std::make_pair(data, page); 430} 431 432 433} 434