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