bool SVGFontData::applySVGGlyphSelection(WidthIterator& iterator, GlyphData& glyphData, bool mirror, int currentCharacter, unsigned& advanceLength, String& normalizedSpacesStringCache) const { const TextRun& run = iterator.run(); Vector<SVGGlyph::ArabicForm>& arabicForms = iterator.arabicForms(); ASSERT(run.charactersLength() >= static_cast<unsigned>(currentCharacter)); SVGFontFaceElement* svgFontFaceElement = this->svgFontFaceElement(); ASSERT(svgFontFaceElement); SVGFontElement* associatedFontElement = svgFontFaceElement->associatedFontElement(); ASSERT(associatedFontElement); RenderObject* renderObject = nullptr; if (TextRun::RenderingContext* renderingContext = run.renderingContext()) renderObject = &static_cast<SVGTextRunRenderingContext*>(renderingContext)->renderer(); String language; bool isVerticalText = false; Vector<String> altGlyphNames; if (renderObject) { RenderElement& parentRenderer = is<RenderElement>(*renderObject) ? downcast<RenderElement>(*renderObject) : *renderObject->parent(); isVerticalText = parentRenderer.style().svgStyle().isVerticalWritingMode(); if (Element* parentRendererElement = parentRenderer.element()) { language = parentRendererElement->getAttribute(XMLNames::langAttr); if (is<SVGAltGlyphElement>(*parentRendererElement)) { SVGAltGlyphElement& altGlyph = downcast<SVGAltGlyphElement>(*parentRendererElement); if (!altGlyph.hasValidGlyphElements(altGlyphNames)) altGlyphNames.clear(); } } } Vector<SVGGlyph> glyphs; size_t altGlyphNamesSize = altGlyphNames.size(); if (altGlyphNamesSize) { for (size_t index = 0; index < altGlyphNamesSize; ++index) associatedFontElement->collectGlyphsForGlyphName(altGlyphNames[index], glyphs); // Assign the unicodeStringLength now that its known. size_t glyphsSize = glyphs.size(); for (size_t i = 0; i < glyphsSize; ++i) glyphs[i].unicodeStringLength = run.length(); // Do not check alt glyphs for compatibility. Just return the first one. // Later code will fail if we do not do this and the glyph is incompatible. if (glyphsSize) { SVGGlyph& svgGlyph = glyphs[0]; iterator.setLastGlyphName(svgGlyph.glyphName); glyphData.glyph = svgGlyph.tableEntry; advanceLength = svgGlyph.unicodeStringLength; return true; } } else { // Associate text with arabic forms, if needed. computeNormalizedSpaces(run, mirror, normalizedSpacesStringCache); auto remainingTextInRun = normalizedSpacesStringCache.substring(currentCharacter); if (!currentCharacter && arabicForms.isEmpty()) arabicForms = charactersWithArabicForm(remainingTextInRun, mirror); associatedFontElement->collectGlyphsForString(remainingTextInRun, glyphs); } size_t glyphsSize = glyphs.size(); for (size_t i = 0; i < glyphsSize; ++i) { SVGGlyph& svgGlyph = glyphs[i]; if (svgGlyph.isPartOfLigature) continue; if (!isCompatibleGlyph(svgGlyph, isVerticalText, language, arabicForms, currentCharacter, currentCharacter + svgGlyph.unicodeStringLength)) continue; iterator.setLastGlyphName(svgGlyph.glyphName); glyphData.glyph = svgGlyph.tableEntry; advanceLength = svgGlyph.unicodeStringLength; return true; } iterator.setLastGlyphName(String()); return false; }
bool SVGFontData::applySVGGlyphSelection(WidthIterator& iterator, GlyphData& glyphData, bool mirror, int currentCharacter, unsigned& advanceLength) const { const TextRun& run = iterator.run(); Vector<SVGGlyph::ArabicForm>& arabicForms = iterator.arabicForms(); ASSERT(int(run.charactersLength()) >= currentCharacter); // Associate text with arabic forms, if needed. String remainingTextInRun(run.data16(currentCharacter), run.charactersLength() - currentCharacter); remainingTextInRun = Font::normalizeSpaces(remainingTextInRun.characters(), remainingTextInRun.length()); if (mirror) remainingTextInRun = createStringWithMirroredCharacters(remainingTextInRun.characters(), remainingTextInRun.length()); if (!currentCharacter && arabicForms.isEmpty()) arabicForms = charactersWithArabicForm(remainingTextInRun, mirror); SVGFontFaceElement* svgFontFaceElement = this->svgFontFaceElement(); ASSERT(svgFontFaceElement); SVGFontElement* associatedFontElement = svgFontFaceElement->associatedFontElement(); ASSERT(associatedFontElement); RenderObject* renderObject = 0; if (TextRun::RenderingContext* renderingContext = run.renderingContext()) renderObject = static_cast<SVGTextRunRenderingContext*>(renderingContext)->renderer(); String language; bool isVerticalText = false; Vector<String> altGlyphNames; if (renderObject) { RenderObject* parentRenderObject = renderObject->isText() ? renderObject->parent() : renderObject; ASSERT(parentRenderObject); isVerticalText = parentRenderObject->style()->svgStyle()->isVerticalWritingMode(); if (Element* parentRenderObjectElement = toElement(parentRenderObject->node())) { language = parentRenderObjectElement->getAttribute(XMLNames::langAttr); if (parentRenderObjectElement->hasTagName(SVGNames::altGlyphTag)) { SVGAltGlyphElement* altGlyph = static_cast<SVGAltGlyphElement*>(parentRenderObjectElement); if (!altGlyph->hasValidGlyphElements(altGlyphNames)) altGlyphNames.clear(); } } } Vector<SVGGlyph> glyphs; size_t altGlyphNamesSize = altGlyphNames.size(); if (altGlyphNamesSize) { for (size_t index = 0; index < altGlyphNamesSize; ++index) associatedFontElement->collectGlyphsForGlyphName(altGlyphNames[index], glyphs); // Assign the unicodeStringLength now that its known. size_t glyphsSize = glyphs.size(); for (size_t i = 0; i < glyphsSize; ++i) glyphs[i].unicodeStringLength = run.length(); } else associatedFontElement->collectGlyphsForString(remainingTextInRun, glyphs); size_t glyphsSize = glyphs.size(); for (size_t i = 0; i < glyphsSize; ++i) { SVGGlyph& svgGlyph = glyphs[i]; if (svgGlyph.isPartOfLigature) continue; if (!isCompatibleGlyph(svgGlyph, isVerticalText, language, arabicForms, currentCharacter, currentCharacter + svgGlyph.unicodeStringLength)) continue; iterator.setLastGlyphName(svgGlyph.glyphName); glyphData.glyph = svgGlyph.tableEntry; advanceLength = svgGlyph.unicodeStringLength; return true; } iterator.setLastGlyphName(String()); return false; }