GlyphData Font::glyphDataForCharacter(UChar32 character) const { auto* page = glyphPage(character / GlyphPage::size); if (!page) return GlyphData(); return page->glyphDataForCharacter(character); }
GlyphData FontCascadeFonts::glyphDataForCharacter(UChar32 c, const FontDescription& description, FontVariant variant) { ASSERT(isMainThread()); ASSERT(variant != AutoVariant); if (variant != NormalVariant) return glyphDataForVariant(c, description, variant, 0); const unsigned pageNumber = c / GlyphPage::size; RefPtr<GlyphPage>& cachedPage = pageNumber ? m_cachedPages.add(pageNumber, nullptr).iterator->value : m_cachedPageZero; if (!cachedPage) cachedPage = glyphPageFromFontRanges(pageNumber, realizeFallbackRangesAt(description, 0)); GlyphData glyphData = cachedPage ? cachedPage->glyphDataForCharacter(c) : GlyphData(); if (!glyphData.glyph) { if (!cachedPage) cachedPage = GlyphPage::createForMixedFonts(); else if (cachedPage->isImmutable()) cachedPage = GlyphPage::createCopyForMixedFonts(*cachedPage); glyphData = glyphDataForNormalVariant(c, description); cachedPage->setGlyphDataForCharacter(c, glyphData.glyph, glyphData.font); } return glyphData; }
GlyphData FontCascadeFonts::glyphDataForSystemFallback(UChar32 c, const FontDescription& description, FontVariant variant) { // System fallback is character-dependent. auto& primaryRanges = realizeFallbackRangesAt(description, 0); auto* originalFont = primaryRanges.fontForCharacter(c); if (!originalFont) originalFont = &primaryRanges.fontForFirstRange(); RefPtr<Font> systemFallbackFont = originalFont->systemFallbackFontForCharacter(c, description, m_isForPlatformFont); if (!systemFallbackFont) return GlyphData(); if (systemFallbackFont->platformData().orientation() == Vertical && !systemFallbackFont->hasVerticalGlyphs() && FontCascade::isCJKIdeographOrSymbol(c)) variant = BrokenIdeographVariant; GlyphData fallbackGlyphData; if (variant == NormalVariant) fallbackGlyphData = systemFallbackFont->glyphDataForCharacter(c); else fallbackGlyphData = systemFallbackFont->variantFont(description, variant)->glyphDataForCharacter(c); if (variant == NormalVariant && fallbackGlyphData.font) { if (!FontCascade::isCJKIdeographOrSymbol(c) && fallbackGlyphData.font->platformData().orientation() == Vertical && !fallbackGlyphData.font->isTextOrientationFallback()) fallbackGlyphData = glyphDataForNonCJKCharacterWithGlyphOrientation(c, description.nonCJKGlyphOrientation(), fallbackGlyphData); } // Keep the system fallback fonts we use alive. if (fallbackGlyphData.glyph) m_systemFallbackFontSet.add(systemFallbackFont.release()); return fallbackGlyphData; }
GlyphData FontCascadeFonts::glyphDataForVariant(UChar32 c, const FontDescription& description, FontVariant variant, unsigned fallbackIndex) { while (true) { auto& fontRanges = realizeFallbackRangesAt(description, fallbackIndex++); if (fontRanges.isNull()) break; auto* font = fontRanges.fontForCharacter(c); GlyphData data = font ? font->glyphDataForCharacter(c) : GlyphData(); if (data.font) { // The variantFont function should not normally return 0. // But if it does, we will just render the capital letter big. RefPtr<Font> variantFont = data.font->variantFont(description, variant); if (!variantFont) return data; return variantFont->glyphDataForCharacter(c); } } return glyphDataForSystemFallback(c, description, variant); }