#include "config.h"
#include "CachedSVGFont.h"
#if ENABLE(SVG_FONTS)
#include "FontDescription.h"
#include "FontPlatformData.h"
#include "NoEventDispatchAssertion.h"
#include "SVGDocument.h"
#include "SVGFontElement.h"
#include "SVGFontFaceElement.h"
#include "SharedBuffer.h"
#include "TextResourceDecoder.h"
#include "TypedElementDescendantIterator.h"
#include "SVGToOTFFontConversion.h"
#if USE(DIRECT2D)
#include <dwrite.h>
#endif
namespace WebCore {
CachedSVGFont::CachedSVGFont(CachedResourceRequest&& request, SessionID sessionID)
: CachedFont(WTFMove(request), sessionID, SVGFontResource)
, m_externalSVGFontElement(nullptr)
{
}
RefPtr<Font> CachedSVGFont::createFont(const FontDescription& fontDescription, const AtomicString& remoteURI, bool syntheticBold, bool syntheticItalic, const FontFeatureSettings& fontFaceFeatures, const FontVariantSettings& fontFaceVariantSettings)
{
if (firstFontFace(remoteURI))
return CachedFont::createFont(fontDescription, remoteURI, syntheticBold, syntheticItalic, fontFaceFeatures, fontFaceVariantSettings);
return nullptr;
}
FontPlatformData CachedSVGFont::platformDataFromCustomData(const FontDescription& fontDescription, bool bold, bool italic, const FontFeatureSettings& fontFaceFeatures, const FontVariantSettings& fontFaceVariantSettings)
{
if (m_externalSVGDocument)
return FontPlatformData(fontDescription.computedPixelSize(), bold, italic);
return CachedFont::platformDataFromCustomData(fontDescription, bold, italic, fontFaceFeatures, fontFaceVariantSettings);
}
bool CachedSVGFont::ensureCustomFontData(const AtomicString& remoteURI)
{
if (!m_externalSVGDocument && !errorOccurred() && !isLoading() && m_data) {
bool sawError = false;
{
m_externalSVGDocument = SVGDocument::create(nullptr, URL());
auto decoder = TextResourceDecoder::create("application/xml");
NoEventDispatchAssertion::EventAllowedScope allowedScope(*m_externalSVGDocument);
m_externalSVGDocument->setContent(decoder->decodeAndFlush(m_data->data(), m_data->size()));
sawError = decoder->sawError();
}
if (sawError)
m_externalSVGDocument = nullptr;
if (m_externalSVGDocument)
maybeInitializeExternalSVGFontElement(remoteURI);
if (!m_externalSVGFontElement)
return false;
if (auto convertedFont = convertSVGToOTFFont(*m_externalSVGFontElement))
m_convertedFont = SharedBuffer::adoptVector(convertedFont.value());
else {
m_externalSVGDocument = nullptr;
m_externalSVGFontElement = nullptr;
return false;
}
}
return m_externalSVGDocument && CachedFont::ensureCustomFontData(m_convertedFont.get());
}
SVGFontElement* CachedSVGFont::getSVGFontById(const String& fontName) const
{
ASSERT(m_externalSVGDocument);
auto elements = descendantsOfType<SVGFontElement>(*m_externalSVGDocument);
if (fontName.isEmpty())
return elements.first();
for (auto& element : elements) {
if (element.getIdAttribute() == fontName)
return &element;
}
return nullptr;
}
SVGFontElement* CachedSVGFont::maybeInitializeExternalSVGFontElement(const AtomicString& remoteURI)
{
if (m_externalSVGFontElement)
return m_externalSVGFontElement;
String fragmentIdentifier;
size_t start = remoteURI.find('#');
if (start != notFound)
fragmentIdentifier = remoteURI.string().substring(start + 1);
m_externalSVGFontElement = getSVGFontById(fragmentIdentifier);
return m_externalSVGFontElement;
}
SVGFontFaceElement* CachedSVGFont::firstFontFace(const AtomicString& remoteURI)
{
if (!maybeInitializeExternalSVGFontElement(remoteURI))
return nullptr;
if (auto* firstFontFace = childrenOfType<SVGFontFaceElement>(*m_externalSVGFontElement).first())
return firstFontFace;
return nullptr;
}
}
#endif