const SimpleFontData* Font::fontDataForCombiningCharacterSequence(const UChar* characters, size_t length, FontDataVariant variant) const { UChar32 baseCharacter; size_t baseCharacterLength = 0; U16_NEXT(characters, baseCharacterLength, length, baseCharacter); GlyphData baseCharacterGlyphData = glyphDataForCharacter(baseCharacter, false, variant); if (!baseCharacterGlyphData.glyph) return 0; if (length == baseCharacterLength) return baseCharacterGlyphData.fontData; bool triedBaseCharacterFontData = false; unsigned i = 0; for (const FontData* fontData = fontDataAt(0); fontData; fontData = fontDataAt(++i)) { const SimpleFontData* simpleFontData = fontData->fontDataForCharacter(baseCharacter); if (variant == NormalVariant) { if (simpleFontData->platformData().orientation() == Vertical) { if (isCJKIdeographOrSymbol(baseCharacter) && !simpleFontData->hasVerticalGlyphs()) { variant = BrokenIdeographVariant; simpleFontData = simpleFontData->brokenIdeographFontData().get(); } else if (m_fontDescription.nonCJKGlyphOrientation() == NonCJKGlyphOrientationVerticalRight) { SimpleFontData* verticalRightFontData = simpleFontData->verticalRightOrientationFontData().get(); Glyph verticalRightGlyph = verticalRightFontData->glyphForCharacter(baseCharacter); if (verticalRightGlyph == baseCharacterGlyphData.glyph) simpleFontData = verticalRightFontData; } else { SimpleFontData* uprightFontData = simpleFontData->uprightOrientationFontData().get(); Glyph uprightGlyph = uprightFontData->glyphForCharacter(baseCharacter); if (uprightGlyph != baseCharacterGlyphData.glyph) simpleFontData = uprightFontData; } } } else { if (const SimpleFontData* variantFontData = simpleFontData->variantFontData(m_fontDescription, variant).get()) simpleFontData = variantFontData; } if (simpleFontData == baseCharacterGlyphData.fontData) triedBaseCharacterFontData = true; if (simpleFontData->canRenderCombiningCharacterSequence(characters, length)) return simpleFontData; } if (!triedBaseCharacterFontData && baseCharacterGlyphData.fontData && baseCharacterGlyphData.fontData->canRenderCombiningCharacterSequence(characters, length)) return baseCharacterGlyphData.fontData; return SimpleFontData::systemFallback(); }
static bool canUseForText(const CharacterType* text, unsigned length, const SimpleFontData& fontData) { // FIXME: <textarea maxlength=0> generates empty text node. if (!length) return false; for (unsigned i = 0; i < length; ++i) { UChar character = text[i]; if (character == ' ') continue; // These would be easy to support. if (character == noBreakSpace) return false; if (character == softHyphen) return false; UCharDirection direction = u_charDirection(character); if (direction == U_RIGHT_TO_LEFT || direction == U_RIGHT_TO_LEFT_ARABIC || direction == U_RIGHT_TO_LEFT_EMBEDDING || direction == U_RIGHT_TO_LEFT_OVERRIDE || direction == U_LEFT_TO_RIGHT_EMBEDDING || direction == U_LEFT_TO_RIGHT_OVERRIDE || direction == U_POP_DIRECTIONAL_FORMAT || direction == U_BOUNDARY_NEUTRAL) return false; if (!fontData.glyphForCharacter(character)) return false; } return true; }