FontPlatformData::FontPlatformData(FcPattern* pattern, const FontDescription& fontDescription)
    : m_pattern(pattern)
    , m_fallbacks(0)
    , m_size(fontDescription.computedPixelSize())
    , m_syntheticBold(false)
    , m_syntheticOblique(false)
    , m_fixedWidth(false)
    , m_scaledFont(0)
    , m_orientation(fontDescription.orientation())
{
    RefPtr<cairo_font_face_t> fontFace = adoptRef(cairo_ft_font_face_create_for_pattern(m_pattern.get()));
    initializeWithFontFace(fontFace.get(), fontDescription);

    int spacing;
    if (FcPatternGetInteger(pattern, FC_SPACING, 0, &spacing) == FcResultMatch && spacing == FC_MONO)
        m_fixedWidth = true;

    if (fontDescription.weight() >= FontWeightBold) {
        // The FC_EMBOLDEN property instructs us to fake the boldness of the font.
        FcBool fontConfigEmbolden = FcFalse;
        if (FcPatternGetBool(pattern, FC_EMBOLDEN, 0, &fontConfigEmbolden) == FcResultMatch)
            m_syntheticBold = fontConfigEmbolden;

        // Fallback fonts may not have FC_EMBOLDEN activated even though it's necessary.
        int weight = 0;
        if (!m_syntheticBold && FcPatternGetInteger(pattern, FC_WEIGHT, 0, &weight) == FcResultMatch)
            m_syntheticBold = m_syntheticBold || weight < FC_WEIGHT_DEMIBOLD;
    }
}
Example #2
0
PassRefPtr<FontData> CSSSegmentedFontFace::getFontData(const FontDescription& fontDescription)
{
    if (!isValid())
        return 0;

    FontTraitsMask desiredTraitsMask = fontDescription.traitsMask();
    unsigned hashKey = ((fontDescription.computedPixelSize() + 1) << (FontTraitsMaskWidth + FontWidthVariantWidth + 1))
        | ((fontDescription.orientation() == Vertical ? 1 : 0) << (FontTraitsMaskWidth + FontWidthVariantWidth))
        | fontDescription.widthVariant() << FontTraitsMaskWidth
        | desiredTraitsMask;

    RefPtr<SegmentedFontData>& fontData = m_fontDataTable.add(hashKey, 0).iterator->value;
    if (fontData && fontData->numRanges())
        return fontData; // No release, we have a reference to an object in the cache which should retain the ref count it has.

    if (!fontData)
        fontData = SegmentedFontData::create();

    unsigned size = m_fontFaces.size();
    for (unsigned i = 0; i < size; i++) {
        if (!m_fontFaces[i]->isValid())
            continue;
        FontTraitsMask traitsMask = m_fontFaces[i]->traitsMask();
        bool syntheticBold = !(traitsMask & (FontWeight600Mask | FontWeight700Mask | FontWeight800Mask | FontWeight900Mask)) && (desiredTraitsMask & (FontWeight600Mask | FontWeight700Mask | FontWeight800Mask | FontWeight900Mask));
        bool syntheticItalic = !(traitsMask & FontStyleItalicMask) && (desiredTraitsMask & FontStyleItalicMask);
        if (RefPtr<SimpleFontData> faceFontData = m_fontFaces[i]->getFontData(fontDescription, syntheticBold, syntheticItalic)) {
            ASSERT(!faceFontData->isSegmented());
            appendFontDataWithInvalidUnicodeRangeIfLoading(fontData.get(), faceFontData.release(), m_fontFaces[i]->ranges());
        }
    }
    if (fontData->numRanges())
        return fontData; // No release, we have a reference to an object in the cache which should retain the ref count it has.

    return 0;
}
PassRefPtr<SimpleFontData> BinaryDataFontFaceSource::createFontData(const FontDescription& fontDescription)
{
    return SimpleFontData::create(
        m_customPlatformData->fontPlatformData(fontDescription.effectiveFontSize(),
            fontDescription.isSyntheticBold(), fontDescription.isSyntheticItalic(),
            fontDescription.orientation()), CustomFontData::create());
}
Example #4
0
FontRanges CSSSegmentedFontFace::fontRanges(const FontDescription& fontDescription)
{
    if (!isValid())
        return FontRanges();

    FontTraitsMask desiredTraitsMask = fontDescription.traitsMask();
    unsigned hashKey = ((fontDescription.computedPixelSize() + 1) << (FontTraitsMaskWidth + FontWidthVariantWidth + 1))
        | ((fontDescription.orientation() == Vertical ? 1 : 0) << (FontTraitsMaskWidth + FontWidthVariantWidth))
        | fontDescription.widthVariant() << FontTraitsMaskWidth
        | desiredTraitsMask;

    auto addResult = m_descriptionToRangesMap.add(hashKey, FontRanges());
    auto& fontRanges = addResult.iterator->value;

    if (addResult.isNewEntry) {
        for (auto& face : m_fontFaces) {
            if (!face->isValid())
                continue;
            FontTraitsMask traitsMask = face->traitsMask();
            bool syntheticBold = !(traitsMask & (FontWeight600Mask | FontWeight700Mask | FontWeight800Mask | FontWeight900Mask)) && (desiredTraitsMask & (FontWeight600Mask | FontWeight700Mask | FontWeight800Mask | FontWeight900Mask));
            bool syntheticItalic = !(traitsMask & FontStyleItalicMask) && (desiredTraitsMask & FontStyleItalicMask);
            if (RefPtr<Font> faceFont = face->font(fontDescription, syntheticBold, syntheticItalic))
                appendFontWithInvalidUnicodeRangeIfLoading(fontRanges, faceFont.releaseNonNull(), face->ranges());
        }
    }
    return fontRanges;
}
FontPlatformData FontCustomPlatformData::fontPlatformData(const FontDescription& fontDescription, bool bold, bool italic, const FontFeatureSettings& fontFaceFeatures, const FontVariantSettings& fontFaceVariantSettings)
{
    int size = fontDescription.computedPixelSize();
    FontOrientation orientation = fontDescription.orientation();
    FontWidthVariant widthVariant = fontDescription.widthVariant();
    RetainPtr<CTFontRef> font = adoptCF(CTFontCreateWithFontDescriptor(m_fontDescriptor.get(), size, nullptr));
    font = preparePlatformFont(font.get(), fontDescription.textRenderingMode(), &fontFaceFeatures, &fontFaceVariantSettings, fontDescription.featureSettings(), fontDescription.variantSettings());
    return FontPlatformData(font.get(), size, bold, italic, orientation, widthVariant, fontDescription.textRenderingMode());
}
PassRefPtr<SimpleFontData> SimpleFontData::platformCreateScaledFontData(const FontDescription& fontDescription, float scaleFactor) const
{
    ASSERT(m_platformData.scaledFont());
    return SimpleFontData::create(FontPlatformData(cairo_scaled_font_get_font_face(m_platformData.scaledFont()),
        scaleFactor * fontDescription.computedSize(),
        m_platformData.syntheticBold(),
        m_platformData.syntheticOblique(),
        fontDescription.orientation()),
        isCustomFont(), false);
}
FontPlatformData FontCustomPlatformData::fontPlatformData(const FontDescription& fontDescription, bool bold, bool italic)
{
    int size = fontDescription.computedPixelSize();
    FontOrientation orientation = fontDescription.orientation();
    FontWidthVariant widthVariant = fontDescription.widthVariant();
#if CORETEXT_WEB_FONTS
    RetainPtr<CTFontRef> font = adoptCF(CTFontCreateWithFontDescriptor(m_fontDescriptor.get(), size, nullptr));
    font = preparePlatformFont(font.get(), fontDescription.textRenderingMode(), fontDescription.featureSettings());
    return FontPlatformData(font.get(), size, bold, italic, orientation, widthVariant, fontDescription.textRenderingMode());
#else
    return FontPlatformData(m_cgFont.get(), size, bold, italic, orientation, widthVariant, fontDescription.textRenderingMode());
#endif
}
Example #8
0
PassRefPtr<SimpleFontData> RemoteFontFaceSource::createFontData(const FontDescription& fontDescription)
{
    if (!isLoaded())
        return createLoadingFallbackFontData(fontDescription);

    if (!m_font->ensureCustomFontData() || m_period == FailurePeriod)
        return nullptr;

    m_histograms.recordFallbackTime(m_font.get());

    return SimpleFontData::create(
        m_font->platformDataFromCustomData(fontDescription.effectiveFontSize(),
            fontDescription.isSyntheticBold(), fontDescription.isSyntheticItalic(),
            fontDescription.orientation()), CustomFontData::create());
}
Example #9
0
PassRefPtr<SimpleFontData> RemoteFontFaceSource::createFontData(const FontDescription& fontDescription)
{
    if (!isLoaded())
        return createLoadingFallbackFontData(fontDescription);

    // Create new FontPlatformData from our CGFontRef, point size and ATSFontRef.
    if (!m_font->ensureCustomFontData())
        return nullptr;

    m_histograms.recordFallbackTime(m_font.get());

    return SimpleFontData::create(
        m_font->platformDataFromCustomData(fontDescription.effectiveFontSize(),
            fontDescription.isSyntheticBold(), fontDescription.isSyntheticItalic(),
            fontDescription.orientation(), fontDescription.widthVariant()), CustomFontData::create());
}
RefPtr<Font> CSSFontFaceSource::font(const FontDescription& fontDescription, bool syntheticBold, bool syntheticItalic, CSSFontSelector* fontSelector, const FontFeatureSettings& fontFaceFeatures, const FontVariantSettings& fontFaceVariantSettings)
{
    // If the font hasn't loaded or an error occurred, then we've got nothing.
    if (!isValid())
        return nullptr;

    if (!m_font
#if ENABLE(SVG_FONTS)
            && !m_svgFontFaceElement
#endif
    ) {
        // We're local. Just return a Font from the normal cache.
        // We don't want to check alternate font family names here, so pass true as the checkingAlternateName parameter.
        return FontCache::singleton().fontForFamily(fontDescription, m_string, true);
    }

    unsigned hashKey = (fontDescription.computedPixelSize() + 1) << 5 | fontDescription.widthVariant() << 3
                       | (fontDescription.orientation() == Vertical ? 4 : 0) | (syntheticBold ? 2 : 0) | (syntheticItalic ? 1 : 0);

    RefPtr<Font> font = m_fontTable.add(hashKey, nullptr).iterator->value;
    if (font)
        return font.release();

    if (isLoaded()) {
        if (m_font) {
            bool hasExternalSVGFont = false;
#if ENABLE(SVG_FONTS)
            hasExternalSVGFont = m_hasExternalSVGFont;
#endif
            if (!m_font->ensureCustomFontData(hasExternalSVGFont, m_string))
                return nullptr;

            font = m_font->createFont(fontDescription, m_string, syntheticBold, syntheticItalic, hasExternalSVGFont, fontFaceFeatures, fontFaceVariantSettings);
        } else {
#if ENABLE(SVG_FONTS)
            // In-Document SVG Fonts
            if (m_svgFontFaceElement) {
#if ENABLE(SVG_OTF_CONVERTER)
                if (!m_svgFontFaceElement->parentNode() || !is<SVGFontElement>(m_svgFontFaceElement->parentNode()))
                    return nullptr;
                SVGFontElement& fontElement = downcast<SVGFontElement>(*m_svgFontFaceElement->parentNode());
                // FIXME: Re-run this when script modifies the element or any of its descendents
                // FIXME: We might have already converted this font. Make existing conversions discoverable.
                Vector<char> otfFont = convertSVGToOTFFont(fontElement);
                m_generatedOTFBuffer = SharedBuffer::adoptVector(otfFont);
                if (!m_generatedOTFBuffer)
                    return nullptr;
                auto customPlatformData = createFontCustomPlatformData(*m_generatedOTFBuffer);
                if (!customPlatformData)
                    return nullptr;
                font = Font::create(customPlatformData->fontPlatformData(fontDescription, syntheticBold, syntheticItalic, fontFaceFeatures, fontFaceVariantSettings), true, false);
#else
                font = Font::create(std::make_unique<SVGFontData>(m_svgFontFaceElement.get()), fontDescription.computedPixelSize(), syntheticBold, syntheticItalic);
#endif
            }
#endif
        }
    } else {
        // Kick off the load. Do it soon rather than now, because we may be in the middle of layout,
        // and the loader may invoke arbitrary delegate or event handler code.
        fontSelector->beginLoadingFontSoon(m_font.get());

        Ref<Font> placeholderFont = FontCache::singleton().lastResortFallbackFont(fontDescription);
        Ref<Font> placeholderFontCopyInLoadingState = Font::create(placeholderFont->platformData(), true, true);
        return WTFMove(placeholderFontCopyInLoadingState);
    }

    return font.release();
}
PassRefPtr<SimpleFontData> CSSFontFaceSource::getFontData(const FontDescription& fontDescription, bool syntheticBold, bool syntheticItalic, CSSFontSelector* fontSelector)
{
    // If the font hasn't loaded or an error occurred, then we've got nothing.
    if (!isValid())
        return 0;

    if (!m_font
#if ENABLE(SVG_FONTS)
            && !m_svgFontFaceElement
#endif
    ) {
        // We're local. Just return a SimpleFontData from the normal cache.
        // We don't want to check alternate font family names here, so pass true as the checkingAlternateName parameter.
        return fontCache()->getCachedFontData(fontDescription, m_string, true);
    }

    // See if we have a mapping in our FontData cache.
    unsigned hashKey = (fontDescription.computedPixelSize() + 1) << 5 | fontDescription.widthVariant() << 3
                       | (fontDescription.orientation() == Vertical ? 4 : 0) | (syntheticBold ? 2 : 0) | (syntheticItalic ? 1 : 0);

    RefPtr<SimpleFontData>& fontData = m_fontDataTable.add(hashKey, 0).iterator->value;
    if (fontData)
        return fontData; // No release, because fontData is a reference to a RefPtr that is held in the m_fontDataTable.

    // If we are still loading, then we let the system pick a font.
    if (isLoaded()) {
        if (m_font) {
#if ENABLE(SVG_FONTS)
            if (m_hasExternalSVGFont) {
                // For SVG fonts parse the external SVG document, and extract the <font> element.
                if (!m_font->ensureSVGFontData())
                    return 0;

                if (!m_externalSVGFontElement) {
                    String fragmentIdentifier;
                    size_t start = m_string.find('#');
                    if (start != notFound)
                        fragmentIdentifier = m_string.string().substring(start + 1);
                    m_externalSVGFontElement = m_font->getSVGFontById(fragmentIdentifier);
                }

                if (!m_externalSVGFontElement)
                    return 0;

                if (auto fontFaceElement = Traversal<SVGFontFaceElement>::firstChild(m_externalSVGFontElement.get())) {
                    if (!m_svgFontFaceElement) {
                        // We're created using a CSS @font-face rule, that means we're not associated with a SVGFontFaceElement.
                        // Use the imported <font-face> tag as referencing font-face element for these cases.
                        m_svgFontFaceElement = fontFaceElement;
                    }

                    fontData = SimpleFontData::create(SVGFontData::create(fontFaceElement), fontDescription.computedPixelSize(), syntheticBold, syntheticItalic);
                }
            } else
#endif
            {
                // Create new FontPlatformData from our CGFontRef, point size and ATSFontRef.
                if (!m_font->ensureCustomFontData())
                    return 0;

                fontData = SimpleFontData::create(m_font->platformDataFromCustomData(fontDescription.computedPixelSize(), syntheticBold, syntheticItalic,
                    fontDescription.orientation(), fontDescription.widthVariant(), fontDescription.renderingMode()), true, false);
            }
        } else {
#if ENABLE(SVG_FONTS)
            // In-Document SVG Fonts
            if (m_svgFontFaceElement)
                fontData = SimpleFontData::create(SVGFontData::create(m_svgFontFaceElement.get()), fontDescription.computedPixelSize(), syntheticBold, syntheticItalic);
#endif
        }
    } else {
        // Kick off the load. Do it soon rather than now, because we may be in the middle of layout,
        // and the loader may invoke arbitrary delegate or event handler code.
        fontSelector->beginLoadingFontSoon(m_font.get());

        // This temporary font is not retained and should not be returned.
        FontCachePurgePreventer fontCachePurgePreventer;
        SimpleFontData* temporaryFont = fontCache()->getNonRetainedLastResortFallbackFont(fontDescription);
        fontData = SimpleFontData::create(temporaryFont->platformData(), true, true);
    }

    return fontData; // No release, because fontData is a reference to a RefPtr that is held in the m_fontDataTable.
}
Example #12
0
PassRefPtr<SimpleFontData> CSSFontFaceSource::getFontData(const FontDescription& fontDescription)
{
    // If the font hasn't loaded or an error occurred, then we've got nothing.
    if (!isValid())
        return 0;

    if (isLocal()) {
        // We're local. Just return a SimpleFontData from the normal cache.
        // We don't want to check alternate font family names here, so pass true as the checkingAlternateName parameter.
        RefPtr<SimpleFontData> fontData = FontCache::fontCache()->getFontData(fontDescription, m_string, true);
        m_histograms.recordLocalFont(fontData);
        return fontData;
    }

    // See if we have a mapping in our FontData cache.
    AtomicString emptyFontFamily = "";
    FontCacheKey key = fontDescription.cacheKey(emptyFontFamily);

    RefPtr<SimpleFontData>& fontData = m_fontDataTable.add(key.hash(), 0).iterator->value;
    if (fontData)
        return fontData; // No release, because fontData is a reference to a RefPtr that is held in the m_fontDataTable.

    // If we are still loading, then we let the system pick a font.
    if (isLoaded()) {
        if (m_font) {
#if ENABLE(SVG_FONTS)
            if (m_hasExternalSVGFont) {
                // For SVG fonts parse the external SVG document, and extract the <font> element.
                if (!m_font->ensureSVGFontData())
                    return 0;

                if (!m_externalSVGFontElement) {
                    String fragmentIdentifier;
                    size_t start = m_string.find('#');
                    if (start != kNotFound)
                        fragmentIdentifier = m_string.string().substring(start + 1);
                    m_externalSVGFontElement = m_font->getSVGFontById(fragmentIdentifier);
                }

                if (!m_externalSVGFontElement)
                    return 0;

                SVGFontFaceElement* fontFaceElement = 0;

                // Select first <font-face> child
                for (Node* fontChild = m_externalSVGFontElement->firstChild(); fontChild; fontChild = fontChild->nextSibling()) {
                    if (fontChild->hasTagName(SVGNames::font_faceTag)) {
                        fontFaceElement = toSVGFontFaceElement(fontChild);
                        break;
                    }
                }

                if (fontFaceElement) {
                    if (!m_svgFontFaceElement) {
                        // We're created using a CSS @font-face rule, that means we're not associated with a SVGFontFaceElement.
                        // Use the imported <font-face> tag as referencing font-face element for these cases.
                        m_svgFontFaceElement = fontFaceElement;
                    }

                    fontData = SimpleFontData::create(
                        SVGFontData::create(fontFaceElement),
                        fontDescription.effectiveFontSize(),
                        fontDescription.isSyntheticBold(),
                        fontDescription.isSyntheticItalic());
                }
            } else
#endif
            {
                // Create new FontPlatformData from our CGFontRef, point size and ATSFontRef.
                if (!m_font->ensureCustomFontData())
                    return 0;

                fontData = SimpleFontData::create(
                    m_font->platformDataFromCustomData(fontDescription.effectiveFontSize(),
                        fontDescription.isSyntheticBold(), fontDescription.isSyntheticItalic(),
                        fontDescription.orientation(), fontDescription.widthVariant()), CustomFontData::create(false));
            }
        } else {
#if ENABLE(SVG_FONTS)
            // In-Document SVG Fonts
            if (m_svgFontFaceElement) {
                fontData = SimpleFontData::create(
                    SVGFontData::create(m_svgFontFaceElement.get()),
                    fontDescription.effectiveFontSize(),
                    fontDescription.isSyntheticBold(),
                    fontDescription.isSyntheticItalic());
            }
#endif
        }
    } else {
        // This temporary font is not retained and should not be returned.
        FontCachePurgePreventer fontCachePurgePreventer;
        SimpleFontData* temporaryFont = FontCache::fontCache()->getNonRetainedLastResortFallbackFont(fontDescription);
        if (!temporaryFont) {
            ASSERT_NOT_REACHED();
            return 0;
        }
        RefPtr<CSSCustomFontData> cssFontData = CSSCustomFontData::create(true);
        cssFontData->setCSSFontFaceSource(this);
        fontData = SimpleFontData::create(temporaryFont->platformData(), cssFontData);
    }

    return fontData; // No release, because fontData is a reference to a RefPtr that is held in the m_fontDataTable.
}
Example #13
0
std::unique_ptr<FontPlatformData> FontCache::createFontPlatformData(
    const FontDescription& fontDescription,
    const FontFaceCreationParams& creationParams,
    float fontSize) {
  ASSERT(creationParams.creationType() == CreateFontByFamily);

  CString name;
  sk_sp<SkTypeface> tf = createTypeface(fontDescription, creationParams, name);
  // Windows will always give us a valid pointer here, even if the face name
  // is non-existent. We have to double-check and see if the family name was
  // really used.
  if (!tf || !typefacesMatchesFamily(tf.get(), creationParams.family())) {
    AtomicString adjustedName;
    FontWeight variantWeight;
    FontStretch variantStretch;

    if (typefacesHasWeightSuffix(creationParams.family(), adjustedName,
                                 variantWeight)) {
      FontFaceCreationParams adjustedParams(adjustedName);
      FontDescription adjustedFontDescription = fontDescription;
      adjustedFontDescription.setWeight(variantWeight);
      tf = createTypeface(adjustedFontDescription, adjustedParams, name);
      if (!tf || !typefacesMatchesFamily(tf.get(), adjustedName))
        return nullptr;

    } else if (typefacesHasStretchSuffix(creationParams.family(), adjustedName,
                                         variantStretch)) {
      FontFaceCreationParams adjustedParams(adjustedName);
      FontDescription adjustedFontDescription = fontDescription;
      adjustedFontDescription.setStretch(variantStretch);
      tf = createTypeface(adjustedFontDescription, adjustedParams, name);
      if (!tf || !typefacesMatchesFamily(tf.get(), adjustedName))
        return nullptr;

    } else {
      return nullptr;
    }
  }

  std::unique_ptr<FontPlatformData> result =
      WTF::wrapUnique(new FontPlatformData(
          tf, name.data(), fontSize,
          (fontDescription.weight() >= FontWeight600 && !tf->isBold()) ||
              fontDescription.isSyntheticBold(),
          ((fontDescription.style() == FontStyleItalic ||
            fontDescription.style() == FontStyleOblique) &&
           !tf->isItalic()) ||
              fontDescription.isSyntheticItalic(),
          fontDescription.orientation()));

  struct FamilyMinSize {
    const wchar_t* family;
    unsigned minSize;
  };
  const static FamilyMinSize minAntiAliasSizeForFont[] = {
      {L"simsun", 11},
      {L"dotum", 12},
      {L"gulim", 12},
      {L"pmingliu", 11},
      {L"pmingliu-extb", 11}};
  size_t numFonts = WTF_ARRAY_LENGTH(minAntiAliasSizeForFont);
  for (size_t i = 0; i < numFonts; i++) {
    FamilyMinSize entry = minAntiAliasSizeForFont[i];
    if (typefacesMatchesFamily(tf.get(), entry.family)) {
      result->setMinSizeForAntiAlias(entry.minSize);
      break;
    }
  }

  // List of fonts that look bad with subpixel text rendering at smaller font
  // sizes. This includes all fonts in the Microsoft Core fonts for the Web
  // collection.
  const static wchar_t* noSubpixelForSmallSizeFont[] = {
      L"andale mono", L"arial",           L"comic sans",   L"courier new",
      L"dotum",       L"georgia",         L"impact",       L"lucida console",
      L"tahoma",      L"times new roman", L"trebuchet ms", L"verdana",
      L"webdings"};
  const static float minSizeForSubpixelForFont = 16.0f;
  numFonts = WTF_ARRAY_LENGTH(noSubpixelForSmallSizeFont);
  for (size_t i = 0; i < numFonts; i++) {
    const wchar_t* family = noSubpixelForSmallSizeFont[i];
    if (typefacesMatchesFamily(tf.get(), family)) {
      result->setMinSizeForSubpixel(minSizeForSubpixelForFont);
      break;
    }
  }

  return result;
}
FontPlatformData::FontPlatformData(const FontDescription& in_desc, const AtomicString& in_family)
    : m_orientation(in_desc.orientation())
    , m_size(in_desc.computedSize())
{
    m_font = _createWKCFont(in_desc, in_family.string().utf8().data());
}