예제 #1
0
GlyphData FontCascadeFonts::glyphDataForNormalVariant(UChar32 c, const FontDescription& description)
{
    const unsigned pageNumber = c / GlyphPage::size;

    for (unsigned fallbackIndex = 0; true; ++fallbackIndex) {
        auto& fontRanges = realizeFallbackRangesAt(description, fallbackIndex);
        if (fontRanges.isNull())
            break;
        auto* font = fontRanges.fontForCharacter(c);
        auto* page = font ? font->glyphPage(pageNumber) : nullptr;
        if (!page)
            continue;
        GlyphData data = page->glyphDataForCharacter(c);
        if (data.font) {
            if (data.font->platformData().orientation() == Vertical && !data.font->isTextOrientationFallback()) {
                if (!FontCascade::isCJKIdeographOrSymbol(c))
                    return glyphDataForNonCJKCharacterWithGlyphOrientation(c, description.nonCJKGlyphOrientation(), data);

                if (!data.font->hasVerticalGlyphs()) {
                    // Use the broken ideograph font data. The broken ideograph font will use the horizontal width of glyphs
                    // to make sure you get a square (even for broken glyphs like symbols used for punctuation).
                    return glyphDataForVariant(c, description, BrokenIdeographVariant, fallbackIndex);
                }
#if PLATFORM(COCOA)
                if (data.font->platformData().syntheticOblique())
                    return glyphDataForCJKCharacterWithoutSyntheticItalic(c, data);
#endif
            }

            return data;
        }
    }

    return glyphDataForSystemFallback(c, description, NormalVariant);
}
예제 #2
0
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;
}
예제 #3
0
GlyphData FontCascadeFonts::glyphDataForCharacter(UChar32 c, const FontCascadeDescription& description, FontVariant variant)
{
    ASSERT(isMainThread());
    ASSERT(variant != AutoVariant);

    if (variant != NormalVariant)
        return glyphDataForVariant(c, description, variant, 0);

    const unsigned pageNumber = c / GlyphPage::size;

    auto& cacheEntry = pageNumber ? m_cachedPages.add(pageNumber, GlyphPageCacheEntry()).iterator->value : m_cachedPageZero;

    // Initialize cache with a full page of glyph mappings from a single font.
    if (cacheEntry.isNull())
        cacheEntry.setSingleFontPage(glyphPageFromFontRanges(pageNumber, realizeFallbackRangesAt(description, 0)));

    GlyphData glyphData = cacheEntry.glyphDataForCharacter(c);
    if (!glyphData.glyph) {
        // No glyph, resolve per-character.
        glyphData = glyphDataForNormalVariant(c, description);
        // Cache the results.
        cacheEntry.setGlyphDataForCharacter(c, glyphData);
    }

    return glyphData;
}