Changeset 239156 in webkit


Ignore:
Timestamp:
Dec 13, 2018 1:17:31 AM (5 years ago)
Author:
Carlos Garcia Campos
Message:

[FreeType] Add initial implementation of variation fonts
https://bugs.webkit.org/show_bug.cgi?id=192151

Reviewed by Michael Catanzaro.

.:

Enable variation fonts in GTK+ port when required dependencies are available.

  • Source/cmake/OptionsGTK.cmake:

Source/WebCore:

  • css/CSSFontFaceSource.cpp:

(WebCore::CSSFontFaceSource::font): Remove platform ifdefs.

  • loader/cache/CachedFont.cpp:

(WebCore::CachedFont::platformDataFromCustomData): Ditto.

  • platform/graphics/FontPlatformData.h:

(WebCore::FontPlatformData::isFixedWidth const):

  • platform/graphics/cairo/FontCustomPlatformData.h: Use RefPtr for cairo_font_face_t.
  • platform/graphics/freetype/FontCacheFreeType.cpp:

(WebCore::getFontPropertiesFromPattern): Helper function to get several font properties from the fontconfig
pattern.
(WebCore::FontCache::systemFallbackForCharacters): Use getFontPropertiesFromPattern().
(WebCore::FontCache::createFontPlatformData): Pass FC_VARIABLE to the pattern and call buildVariationSettings()
before creating the FontPlatformData to set FC_FONT_VARIATIONS on the pattern.
(WebCore::defaultVariationValues): Parse font variations table.
(WebCore::buildVariationSettings): Build a font variations string from the settings that can be passed to cairo.

  • platform/graphics/freetype/FontCacheFreeType.h: Added.
  • platform/graphics/freetype/FontCustomPlatformDataFreeType.cpp:

(WebCore::FontCustomPlatformData::FontCustomPlatformData): Use RefPtr and make freeTypeFaceKey global.
(WebCore::FontCustomPlatformData::~FontCustomPlatformData): Remove explicit destroy.
(WebCore::defaultFontconfigOptions): Moved here from FontCacheFreeType.
(WebCore::FontCustomPlatformData::fontPlatformData): Call buildVariationSettings() before creating the
FontPlatformData to set FC_FONT_VARIATIONS on the pattern.
(WebCore::FontCustomPlatformData::supportsFormat): Add variation formats.

  • platform/graphics/freetype/FontPlatformDataFreeType.cpp:

(WebCore::setCairoFontOptionsFromFontConfigPattern): Call cairo_font_options_set_variations() with the
FC_FONT_VARIATIONS value from the pattern.
(WebCore::FontPlatformData::FontPlatformData): Use a single constructor that always receives a valid fontconfig
pattern.
(WebCore::FontPlatformData::fcPattern const): Return the fontconfig pattern.
(WebCore::FontPlatformData::platformIsEqual const): Update the condition now that m_pattern can't be nullptr.
(WebCore::FontPlatformData::buildScaledFont): Use m_pattern unconditionally.

  • platform/graphics/freetype/SimpleFontDataFreeType.cpp:

(WebCore::Font::platformCreateScaledFont const): Update it to use the new FontPlatformData constructor.

  • platform/graphics/harfbuzz/HarfBuzzFaceCairo.cpp:

(WebCore::HarfBuzzFace::createFont): Pass variations to HarfBuzz.

  • platform/graphics/win/FontCustomPlatformData.cpp:

(WebCore::FontCustomPlatformData::fontPlatformData):

  • platform/graphics/win/FontCustomPlatformData.h:

Tools:

Add cairo patch to avoid crashes.

  • gtk/jhbuild.modules:
  • gtk/patches/cairo-ft-Use-FT_Done_MM_Var-instead-of-free-when-available.patch: Added.

LayoutTests:

Unskip variation fonts tests that are now passing in GTK+ port.

  • platform/gtk/TestExpectations:
Location:
trunk
Files:
2 added
19 edited

Legend:

Unmodified
Added
Removed
  • trunk/ChangeLog

    r239123 r239156  
     12018-12-12  Carlos Garcia Campos  <cgarcia@igalia.com>
     2
     3        [FreeType] Add initial implementation of variation fonts
     4        https://bugs.webkit.org/show_bug.cgi?id=192151
     5
     6        Reviewed by Michael Catanzaro.
     7
     8        Enable variation fonts in GTK+ port when required dependencies are available.
     9
     10        * Source/cmake/OptionsGTK.cmake:
     11
    1122018-12-12  Michael Catanzaro  <mcatanzaro@igalia.com>
    213
  • trunk/LayoutTests/ChangeLog

    r239150 r239156  
     12018-12-12  Carlos Garcia Campos  <cgarcia@igalia.com>
     2
     3        [FreeType] Add initial implementation of variation fonts
     4        https://bugs.webkit.org/show_bug.cgi?id=192151
     5
     6        Reviewed by Michael Catanzaro.
     7
     8        Unskip variation fonts tests that are now passing in GTK+ port.
     9
     10        * platform/gtk/TestExpectations:
     11
    1122018-12-12  Simon Fraser  <simon.fraser@apple.com>
    213
  • trunk/LayoutTests/platform/gtk/TestExpectations

    r239122 r239156  
    10471047webkit.org/b/161962 fast/forms/implicit-submission.html [ Failure ]
    10481048
    1049 # Font variations build flag is turned off
    1050 webkit.org/b/162815 fast/text/variations/ [ Skip ]
    1051 webkit.org/b/162815 animations/font-variations/ [ Skip ]
    1052 webkit.org/b/162815 legacy-animation-engine/animations/font-variations/ [ Skip ]
    1053 
    10541049webkit.org/b/169531 fast/text/font-selection-font-face-parse.html [ Skip ]
    10551050
     
    36433638webkit.org/b/192435 fast/css-custom-paint/leaks.html [ Failure ]
    36443639
     3640webkit.org/b/162815 fast/text/variations/font-face-clamp.html [ ImageOnlyFailure ]
     3641webkit.org/b/162815 fast/text/variations/font-selection-properties.html [ ImageOnlyFailure ]
     3642webkit.org/b/162815 fast/text/variations/skia-postscript-name.html [ ImageOnlyFailure ]
     3643
    36453644#////////////////////////////////////////////////////////////////////////////////////////
    36463645# End of non-crashing, non-flaky tests failing
  • trunk/Source/WebCore/ChangeLog

    r239151 r239156  
     12018-12-12  Carlos Garcia Campos  <cgarcia@igalia.com>
     2
     3        [FreeType] Add initial implementation of variation fonts
     4        https://bugs.webkit.org/show_bug.cgi?id=192151
     5
     6        Reviewed by Michael Catanzaro.
     7
     8        * css/CSSFontFaceSource.cpp:
     9        (WebCore::CSSFontFaceSource::font): Remove platform ifdefs.
     10        * loader/cache/CachedFont.cpp:
     11        (WebCore::CachedFont::platformDataFromCustomData): Ditto.
     12        * platform/graphics/FontPlatformData.h:
     13        (WebCore::FontPlatformData::isFixedWidth const):
     14        * platform/graphics/cairo/FontCustomPlatformData.h: Use RefPtr for cairo_font_face_t.
     15        * platform/graphics/freetype/FontCacheFreeType.cpp:
     16        (WebCore::getFontPropertiesFromPattern): Helper function to get several font properties from the fontconfig
     17        pattern.
     18        (WebCore::FontCache::systemFallbackForCharacters): Use getFontPropertiesFromPattern().
     19        (WebCore::FontCache::createFontPlatformData): Pass FC_VARIABLE to the pattern and call buildVariationSettings()
     20        before creating the FontPlatformData to set FC_FONT_VARIATIONS on the pattern.
     21        (WebCore::defaultVariationValues): Parse font variations table.
     22        (WebCore::buildVariationSettings): Build a font variations string from the settings that can be passed to cairo.
     23        * platform/graphics/freetype/FontCacheFreeType.h: Added.
     24        * platform/graphics/freetype/FontCustomPlatformDataFreeType.cpp:
     25        (WebCore::FontCustomPlatformData::FontCustomPlatformData): Use RefPtr and make freeTypeFaceKey global.
     26        (WebCore::FontCustomPlatformData::~FontCustomPlatformData): Remove explicit destroy.
     27        (WebCore::defaultFontconfigOptions): Moved here from FontCacheFreeType.
     28        (WebCore::FontCustomPlatformData::fontPlatformData): Call buildVariationSettings() before creating the
     29        FontPlatformData to set FC_FONT_VARIATIONS on the pattern.
     30        (WebCore::FontCustomPlatformData::supportsFormat): Add variation formats.
     31        * platform/graphics/freetype/FontPlatformDataFreeType.cpp:
     32        (WebCore::setCairoFontOptionsFromFontConfigPattern): Call cairo_font_options_set_variations() with the
     33        FC_FONT_VARIATIONS value from the pattern.
     34        (WebCore::FontPlatformData::FontPlatformData): Use a single constructor that always receives a valid fontconfig
     35        pattern.
     36        (WebCore::FontPlatformData::fcPattern const): Return the fontconfig pattern.
     37        (WebCore::FontPlatformData::platformIsEqual const): Update the condition now that m_pattern can't be nullptr.
     38        (WebCore::FontPlatformData::buildScaledFont): Use m_pattern unconditionally.
     39        * platform/graphics/freetype/SimpleFontDataFreeType.cpp:
     40        (WebCore::Font::platformCreateScaledFont const): Update it to use the new FontPlatformData constructor.
     41        * platform/graphics/harfbuzz/HarfBuzzFaceCairo.cpp:
     42        (WebCore::HarfBuzzFace::createFont): Pass variations to HarfBuzz.
     43        * platform/graphics/win/FontCustomPlatformData.cpp:
     44        (WebCore::FontCustomPlatformData::fontPlatformData):
     45        * platform/graphics/win/FontCustomPlatformData.h:
     46
    1472018-12-12  Fujii Hironori  <Hironori.Fujii@sony.com>
    248
  • trunk/Source/WebCore/css/CSSFontFaceSource.cpp

    r239122 r239156  
    233233    if (!m_inDocumentCustomPlatformData)
    234234        return nullptr;
    235 #if PLATFORM(COCOA)
    236235    return Font::create(m_inDocumentCustomPlatformData->fontPlatformData(fontDescription, syntheticBold, syntheticItalic, fontFaceFeatures, fontFaceVariantSettings, fontFaceCapabilities), Font::Origin::Remote);
    237 #else
    238     return Font::create(m_inDocumentCustomPlatformData->fontPlatformData(fontDescription, syntheticBold, syntheticItalic), Font::Origin::Remote);
    239 #endif
    240236#endif
    241237
  • trunk/Source/WebCore/loader/cache/CachedFont.cpp

    r239122 r239156  
    142142FontPlatformData CachedFont::platformDataFromCustomData(FontCustomPlatformData& fontCustomPlatformData, const FontDescription& fontDescription, bool bold, bool italic, const FontFeatureSettings& fontFaceFeatures, const FontVariantSettings& fontFaceVariantSettings, FontSelectionSpecifiedCapabilities fontFaceCapabilities)
    143143{
    144 #if PLATFORM(COCOA)
    145144    return fontCustomPlatformData.fontPlatformData(fontDescription, bold, italic, fontFaceFeatures, fontFaceVariantSettings, fontFaceCapabilities);
    146 #else
    147     UNUSED_PARAM(fontFaceFeatures);
    148     UNUSED_PARAM(fontFaceVariantSettings);
    149     UNUSED_PARAM(fontFaceCapabilities);
    150     return fontCustomPlatformData.fontPlatformData(fontDescription, bold, italic);
    151 #endif
    152145}
    153146
  • trunk/Source/WebCore/platform/graphics/FontPlatformData.h

    r239122 r239156  
    113113
    114114#if USE(FREETYPE)
    115     FontPlatformData(FcPattern*, const FontDescription&);
    116     FontPlatformData(cairo_font_face_t*, const FontDescription&, bool syntheticBold, bool syntheticOblique);
     115    FontPlatformData(cairo_font_face_t*, FcPattern*, float size, bool fixedWidth, bool syntheticBold, bool syntheticOblique, FontOrientation);
    117116    FontPlatformData(const FontPlatformData&);
    118117    FontPlatformData(FontPlatformData&&) = default;
     
    172171    HarfBuzzFace& harfBuzzFace() const;
    173172    bool hasCompatibleCharmap() const;
     173    FcPattern* fcPattern() const;
     174    bool isFixedWidth() const { return m_fixedWidth; }
    174175#endif
    175176
  • trunk/Source/WebCore/platform/graphics/cairo/FontCustomPlatformData.h

    r239122 r239156  
    2020 */
    2121
    22 #ifndef FontCustomPlatformData_h
    23 #define FontCustomPlatformData_h
     22#pragma once
    2423
    2524#if USE(CAIRO)
    2625
     26#include "RefPtrCairo.h"
    2727#include <wtf/Forward.h>
    2828#include <wtf/Noncopyable.h>
    2929
    3030typedef struct FT_FaceRec_*  FT_Face;
    31 typedef struct _cairo_font_face cairo_font_face_t;
    3231
    3332namespace WebCore {
     
    3635class FontPlatformData;
    3736class SharedBuffer;
     37struct FontSelectionSpecifiedCapabilities;
     38struct FontVariantSettings;
     39
     40template <typename T> class FontTaggedSettings;
     41typedef FontTaggedSettings<int> FontFeatureSettings;
    3842
    3943struct FontCustomPlatformData {
     
    4145public:
    4246    FontCustomPlatformData(FT_Face, SharedBuffer&);
    43     ~FontCustomPlatformData();
    44     FontPlatformData fontPlatformData(const FontDescription&, bool bold, bool italic);
     47    ~FontCustomPlatformData() = default;
     48    FontPlatformData fontPlatformData(const FontDescription&, bool bold, bool italic, const FontFeatureSettings&, const FontVariantSettings&, FontSelectionSpecifiedCapabilities);
    4549    static bool supportsFormat(const String&);
    4650
    4751private:
    48     cairo_font_face_t* m_fontFace;
     52    RefPtr<cairo_font_face_t> m_fontFace;
    4953};
    5054
     
    5458
    5559#endif // USE(CAIRO)
    56 
    57 #endif // FontCustomPlatformData_h
  • trunk/Source/WebCore/platform/graphics/freetype/FontCacheFreeType.cpp

    r239122 r239156  
    2323#include "FontCache.h"
    2424
     25#include "CairoUniquePtr.h"
    2526#include "CairoUtilities.h"
    2627#include "FcUniquePtr.h"
     28#include "FloatConversion.h"
    2729#include "Font.h"
     30#include "FontDescription.h"
     31#include "FontCacheFreeType.h"
    2832#include "RefPtrCairo.h"
    2933#include "RefPtrFontconfig.h"
     
    3741#if PLATFORM(GTK)
    3842#include "GtkUtilities.h"
     43#endif
     44
     45#if ENABLE(VARIATION_FONTS)
     46#include FT_MULTIPLE_MASTERS_H
    3947#endif
    4048
     
    8088}
    8189
     90static void getFontPropertiesFromPattern(FcPattern* pattern, const FontDescription& fontDescription, bool& fixedWidth, bool& syntheticBold, bool& syntheticOblique)
     91{
     92    fixedWidth = false;
     93    int spacing;
     94    if (FcPatternGetInteger(pattern, FC_SPACING, 0, &spacing) == FcResultMatch && spacing == FC_MONO)
     95        fixedWidth = true;
     96
     97    syntheticBold = false;
     98    bool descriptionAllowsSyntheticBold = fontDescription.fontSynthesis() & FontSynthesisWeight;
     99    if (descriptionAllowsSyntheticBold && isFontWeightBold(fontDescription.weight())) {
     100        // The FC_EMBOLDEN property instructs us to fake the boldness of the font.
     101        FcBool fontConfigEmbolden = FcFalse;
     102        if (FcPatternGetBool(pattern, FC_EMBOLDEN, 0, &fontConfigEmbolden) == FcResultMatch)
     103            syntheticBold = fontConfigEmbolden;
     104
     105        // Fallback fonts may not have FC_EMBOLDEN activated even though it's necessary.
     106        int weight = 0;
     107        if (!syntheticBold && FcPatternGetInteger(pattern, FC_WEIGHT, 0, &weight) == FcResultMatch)
     108            syntheticBold = syntheticBold || weight < FC_WEIGHT_DEMIBOLD;
     109    }
     110
     111    // We requested an italic font, but Fontconfig gave us one that was neither oblique nor italic.
     112    syntheticOblique = false;
     113    int actualFontSlant;
     114    bool descriptionAllowsSyntheticOblique = fontDescription.fontSynthesis() & FontSynthesisStyle;
     115    if (descriptionAllowsSyntheticOblique && fontDescription.italic()
     116        && FcPatternGetInteger(pattern, FC_SLANT, 0, &actualFontSlant) == FcResultMatch) {
     117        syntheticOblique = actualFontSlant == FC_SLANT_ROMAN;
     118    }
     119}
     120
    82121RefPtr<Font> FontCache::systemFallbackForCharacters(const FontDescription& description, const Font*, bool, const UChar* characters, unsigned length)
    83122{
     
    107146        return nullptr;
    108147
    109     FontPlatformData alternateFontData(resultPattern.get(), description);
     148    bool fixedWidth, syntheticBold, syntheticOblique;
     149    getFontPropertiesFromPattern(resultPattern.get(), description, fixedWidth, syntheticBold, syntheticOblique);
     150
     151    RefPtr<cairo_font_face_t> fontFace = adoptRef(cairo_ft_font_face_create_for_pattern(resultPattern.get()));
     152    FontPlatformData alternateFontData(fontFace.get(), resultPattern.get(), description.computedPixelSize(), fixedWidth, syntheticBold, syntheticOblique, description.orientation());
    110153    return fontForPlatformData(alternateFontData);
    111154}
     
    333376    // Never choose unscalable fonts, as they pixelate when displayed at different sizes.
    334377    FcPatternAddBool(pattern.get(), FC_SCALABLE, FcTrue);
     378#if ENABLE(VARIATION_FONTS)
     379    FcPatternAddBool(pattern.get(), FC_VARIABLE, FcDontCare);
     380#endif
    335381    String familyNameString(getFamilyNameStringFromFamily(family));
    336382    if (!FcPatternAddString(pattern.get(), FC_FAMILY, reinterpret_cast<const FcChar8*>(familyNameString.utf8().data())))
     
    383429        return nullptr;
    384430
     431    bool fixedWidth, syntheticBold, syntheticOblique;
     432    getFontPropertiesFromPattern(pattern.get(), fontDescription, fixedWidth, syntheticBold, syntheticOblique);
     433
     434    RefPtr<cairo_font_face_t> fontFace = adoptRef(cairo_ft_font_face_create_for_pattern(resultPattern.get()));
     435#if ENABLE(VARIATION_FONTS)
     436    // Cairo doesn't have API to get the FT_Face of an unscaled font, so we need to
     437    // create a temporary scaled font to get the FT_Face.
     438    CairoUniquePtr<cairo_font_options_t> options(cairo_font_options_copy(getDefaultCairoFontOptions()));
     439    cairo_matrix_t matrix;
     440    cairo_matrix_init_identity(&matrix);
     441    RefPtr<cairo_scaled_font_t> scaledFont = adoptRef(cairo_scaled_font_create(fontFace.get(), &matrix, &matrix, options.get()));
     442    CairoFtFaceLocker cairoFtFaceLocker(scaledFont.get());
     443    if (FT_Face freeTypeFace = cairoFtFaceLocker.ftFace()) {
     444        auto variants = buildVariationSettings(freeTypeFace, fontDescription);
     445        if (!variants.isEmpty())
     446            FcPatternAddString(resultPattern.get(), FC_FONT_VARIATIONS, reinterpret_cast<const FcChar8*>(variants.utf8().data()));
     447    }
     448#endif
     449    auto platformData = std::make_unique<FontPlatformData>(fontFace.get(), resultPattern.get(), fontDescription.computedPixelSize(), fixedWidth, syntheticBold, syntheticOblique, fontDescription.orientation());
    385450    // Verify that this font has an encoding compatible with Fontconfig. Fontconfig currently
    386451    // supports three encodings in FcFreeTypeCharIndex: Unicode, Symbol and AppleRoman.
    387452    // If this font doesn't have one of these three encodings, don't select it.
    388     auto platformData = std::make_unique<FontPlatformData>(resultPattern.get(), fontDescription);
    389453    if (!platformData->hasCompatibleCharmap())
    390454        return nullptr;
     
    398462}
    399463
    400 }
     464#if ENABLE(VARIATION_FONTS)
     465struct VariationDefaults {
     466    float defaultValue;
     467    float minimumValue;
     468    float maximumValue;
     469};
     470
     471typedef HashMap<FontTag, VariationDefaults, FourCharacterTagHash, FourCharacterTagHashTraits> VariationDefaultsMap;
     472typedef HashMap<FontTag, float, FourCharacterTagHash, FourCharacterTagHashTraits> VariationsMap;
     473
     474static VariationDefaultsMap defaultVariationValues(FT_Face face)
     475{
     476    VariationDefaultsMap result;
     477    FT_MM_Var* ftMMVar;
     478    if (FT_Get_MM_Var(face, &ftMMVar))
     479        return result;
     480
     481    for (unsigned i = 0; i < ftMMVar->num_axis; ++i) {
     482        auto tag = ftMMVar->axis[i].tag;
     483        auto b1 = 0xFF & (tag >> 24);
     484        auto b2 = 0xFF & (tag >> 16);
     485        auto b3 = 0xFF & (tag >> 8);
     486        auto b4 = 0xFF & (tag >> 0);
     487        FontTag resultKey = {{ static_cast<char>(b1), static_cast<char>(b2), static_cast<char>(b3), static_cast<char>(b4) }};
     488        VariationDefaults resultValues = { narrowPrecisionToFloat(ftMMVar->axis[i].def / 65536.), narrowPrecisionToFloat(ftMMVar->axis[i].minimum / 65536.), narrowPrecisionToFloat(ftMMVar->axis[i].maximum / 65536.) };
     489        result.set(resultKey, resultValues);
     490    }
     491    FT_Done_MM_Var(face->glyph->library, ftMMVar);
     492    return result;
     493}
     494
     495String buildVariationSettings(FT_Face face, const FontDescription& fontDescription)
     496{
     497    auto defaultValues = defaultVariationValues(face);
     498    const auto& variations = fontDescription.variationSettings();
     499
     500    VariationsMap variationsToBeApplied;
     501    auto applyVariation = [&](const FontTag& tag, float value) {
     502        auto iterator = defaultValues.find(tag);
     503        if (iterator == defaultValues.end())
     504            return;
     505        float valueToApply = clampTo(value, iterator->value.minimumValue, iterator->value.maximumValue);
     506        variationsToBeApplied.set(tag, valueToApply);
     507    };
     508
     509    for (auto& variation : variations)
     510        applyVariation(variation.tag(), variation.value());
     511
     512    StringBuilder builder;
     513    for (auto& variation : variationsToBeApplied) {
     514        if (!builder.isEmpty())
     515            builder.append(',');
     516        builder.append(variation.key[0]);
     517        builder.append(variation.key[1]);
     518        builder.append(variation.key[2]);
     519        builder.append(variation.key[3]);
     520        builder.append('=');
     521        builder.appendNumber(variation.value);
     522    }
     523    return builder.toString();
     524}
     525#endif // ENABLE(VARIATION_FONTS)
     526
     527}
  • trunk/Source/WebCore/platform/graphics/freetype/FontCustomPlatformDataFreeType.cpp

    r239122 r239156  
    2323#include "FontCustomPlatformData.h"
    2424
     25#include "CairoUtilities.h"
     26#include "FontCacheFreeType.h"
     27#include "FontDescription.h"
    2528#include "FontPlatformData.h"
    2629#include "SharedBuffer.h"
     
    3740}
    3841
     42static cairo_user_data_key_t freeTypeFaceKey;
     43
    3944FontCustomPlatformData::FontCustomPlatformData(FT_Face freeTypeFace, SharedBuffer& buffer)
    40     : m_fontFace(cairo_ft_font_face_create_for_ft_face(freeTypeFace, FT_LOAD_DEFAULT))
     45    : m_fontFace(adoptRef(cairo_ft_font_face_create_for_ft_face(freeTypeFace, FT_LOAD_DEFAULT)))
    4146{
    4247    buffer.ref(); // This is balanced by the buffer->deref() in releaseCustomFontData.
    4348    static cairo_user_data_key_t bufferKey;
    44     cairo_font_face_set_user_data(m_fontFace, &bufferKey, &buffer,
     49    cairo_font_face_set_user_data(m_fontFace.get(), &bufferKey, &buffer,
    4550         static_cast<cairo_destroy_func_t>(releaseCustomFontData));
    4651
    4752    // Cairo doesn't do FreeType reference counting, so we need to ensure that when
    4853    // this cairo_font_face_t is destroyed, it cleans up the FreeType face as well.
    49     static cairo_user_data_key_t freeTypeFaceKey;
    50     cairo_font_face_set_user_data(m_fontFace, &freeTypeFaceKey, freeTypeFace,
     54    cairo_font_face_set_user_data(m_fontFace.get(), &freeTypeFaceKey, freeTypeFace,
    5155        reinterpret_cast<cairo_destroy_func_t>(reinterpret_cast<void(*)(void)>(FT_Done_Face)));
    5256}
    5357
    54 FontCustomPlatformData::~FontCustomPlatformData()
     58static FcPattern* defaultFontconfigOptions()
    5559{
    56     cairo_font_face_destroy(m_fontFace);
     60    // Get some generic default settings from fontconfig for web fonts. Strategy
     61    // from Behdad Esfahbod in https://code.google.com/p/chromium/issues/detail?id=173207#c35
     62    // For web fonts, the hint style is overridden in FontCustomPlatformData::FontCustomPlatformData
     63    // so Fontconfig will not affect the hint style, but it may disable hinting completely.
     64    static FcPattern* pattern = nullptr;
     65    static std::once_flag flag;
     66    std::call_once(flag, [](FcPattern*) {
     67        pattern = FcPatternCreate();
     68        FcConfigSubstitute(nullptr, pattern, FcMatchPattern);
     69        cairo_ft_font_options_substitute(getDefaultCairoFontOptions(), pattern);
     70        FcDefaultSubstitute(pattern);
     71        FcPatternDel(pattern, FC_FAMILY);
     72        FcConfigSubstitute(nullptr, pattern, FcMatchFont);
     73    }, pattern);
     74    return pattern;
    5775}
    5876
    59 FontPlatformData FontCustomPlatformData::fontPlatformData(const FontDescription& description, bool bold, bool italic)
     77FontPlatformData FontCustomPlatformData::fontPlatformData(const FontDescription& description, bool bold, bool italic, const FontFeatureSettings&, const FontVariantSettings&, FontSelectionSpecifiedCapabilities)
    6078{
    61     return FontPlatformData(m_fontFace, description, bold, italic);
     79    auto* freeTypeFace = static_cast<FT_Face>(cairo_font_face_get_user_data(m_fontFace.get(), &freeTypeFaceKey));
     80    ASSERT(freeTypeFace);
     81    RefPtr<FcPattern> pattern = defaultFontconfigOptions();
     82#if ENABLE(VARIATION_FONTS)
     83    auto variants = buildVariationSettings(freeTypeFace, description);
     84    if (!variants.isEmpty()) {
     85        pattern = adoptRef(FcPatternDuplicate(pattern.get()));
     86        FcPatternAddString(pattern.get(), FC_FONT_VARIATIONS, reinterpret_cast<const FcChar8*>(variants.utf8().data()));
     87    }
     88#endif
     89    return FontPlatformData(m_fontFace.get(), pattern.get(), description.computedPixelSize(), freeTypeFace->face_flags & FT_FACE_FLAG_FIXED_WIDTH, bold, italic, description.orientation());
    6290}
    6391
     
    111139#if USE(WOFF2)
    112140        || equalLettersIgnoringASCIICase(format, "woff2")
     141#if ENABLE(VARIATION_FONTS)
     142        || equalLettersIgnoringASCIICase(format, "woff2-variations")
     143#endif
     144#endif
     145#if ENABLE(VARIATION_FONTS)
     146        || equalLettersIgnoringASCIICase(format, "woff-variations")
     147        || equalLettersIgnoringASCIICase(format, "truetype-variations")
     148        || equalLettersIgnoringASCIICase(format, "opentype-variations")
    113149#endif
    114150        || equalLettersIgnoringASCIICase(format, "woff");
  • trunk/Source/WebCore/platform/graphics/freetype/FontPlatformDataFreeType.cpp

    r239122 r239156  
    2929#include "CairoUtilities.h"
    3030#include "FontCache.h"
    31 #include "FontDescription.h"
    3231#include "SharedBuffer.h"
    3332#include <cairo-ft.h>
     
    101100    if (FcPatternGetBool(pattern, FC_HINTING, 0, &booleanResult) == FcResultMatch && !booleanResult)
    102101        cairo_font_options_set_hint_style(options, CAIRO_HINT_STYLE_NONE);
    103 }
    104 
    105 static FcPattern* getDefaultFontconfigOptions()
    106 {
    107     // Get some generic default settings from fontconfig for web fonts. Strategy
    108     // from Behdad Esfahbod in https://code.google.com/p/chromium/issues/detail?id=173207#c35
    109     // For web fonts, the hint style is overridden in FontCustomPlatformData::FontCustomPlatformData
    110     // so Fontconfig will not affect the hint style, but it may disable hinting completely.
    111     static FcPattern* pattern = nullptr;
    112     static std::once_flag flag;
    113     std::call_once(flag, [](FcPattern*) {
    114         pattern = FcPatternCreate();
    115         FcConfigSubstitute(nullptr, pattern, FcMatchPattern);
    116         cairo_ft_font_options_substitute(getDefaultCairoFontOptions(), pattern);
    117         FcDefaultSubstitute(pattern);
    118         FcPatternDel(pattern, FC_FAMILY);
    119         FcConfigSubstitute(nullptr, pattern, FcMatchFont);
    120     }, pattern);
    121     return pattern;
    122 }
    123 
    124 FontPlatformData::FontPlatformData(FcPattern* pattern, const FontDescription& fontDescription)
    125     : m_pattern(pattern)
    126     , m_size(fontDescription.computedPixelSize())
    127     , m_orientation(fontDescription.orientation())
    128 {
    129     ASSERT(m_pattern);
    130     RefPtr<cairo_font_face_t> fontFace = adoptRef(cairo_ft_font_face_create_for_pattern(m_pattern.get()));
    131 
    132     int spacing;
    133     if (FcPatternGetInteger(pattern, FC_SPACING, 0, &spacing) == FcResultMatch && spacing == FC_MONO)
    134         m_fixedWidth = true;
    135 
    136     bool descriptionAllowsSyntheticBold = fontDescription.fontSynthesis() & FontSynthesisWeight;
    137     if (descriptionAllowsSyntheticBold && isFontWeightBold(fontDescription.weight())) {
    138         // The FC_EMBOLDEN property instructs us to fake the boldness of the font.
    139         FcBool fontConfigEmbolden = FcFalse;
    140         if (FcPatternGetBool(pattern, FC_EMBOLDEN, 0, &fontConfigEmbolden) == FcResultMatch)
    141             m_syntheticBold = fontConfigEmbolden;
    142 
    143         // Fallback fonts may not have FC_EMBOLDEN activated even though it's necessary.
    144         int weight = 0;
    145         if (!m_syntheticBold && FcPatternGetInteger(pattern, FC_WEIGHT, 0, &weight) == FcResultMatch)
    146             m_syntheticBold = m_syntheticBold || weight < FC_WEIGHT_DEMIBOLD;
    147     }
    148 
    149     // We requested an italic font, but Fontconfig gave us one that was neither oblique nor italic.
    150     int actualFontSlant;
    151     bool descriptionAllowsSyntheticOblique = fontDescription.fontSynthesis() & FontSynthesisStyle;
    152     if (descriptionAllowsSyntheticOblique && fontDescription.italic()
    153         && FcPatternGetInteger(pattern, FC_SLANT, 0, &actualFontSlant) == FcResultMatch) {
    154         m_syntheticOblique = actualFontSlant == FC_SLANT_ROMAN;
    155     }
    156 
    157     buildScaledFont(fontFace.get());
    158 }
    159 
    160 FontPlatformData::FontPlatformData(cairo_font_face_t* fontFace, const FontDescription& description, bool bold, bool italic)
    161     : m_size(description.computedPixelSize())
    162     , m_orientation(description.orientation())
    163     , m_syntheticBold(bold)
    164     , m_syntheticOblique(italic)
    165 {
     102
     103#if ENABLE(VARIATION_FONTS)
     104    FcChar8* variations;
     105    if (FcPatternGetString(pattern, FC_FONT_VARIATIONS, 0, &variations) == FcResultMatch) {
     106        cairo_font_options_set_variations(options, reinterpret_cast<char*>(variations));
     107    }
     108#endif
     109}
     110
     111FontPlatformData::FontPlatformData(cairo_font_face_t* fontFace, FcPattern* pattern, float size, bool fixedWidth, bool syntheticBold, bool syntheticOblique, FontOrientation orientation)
     112    : FontPlatformData(size, syntheticBold, syntheticOblique, orientation)
     113{
     114    m_pattern = pattern;
     115    m_fixedWidth = fixedWidth;
     116
    166117    buildScaledFont(fontFace);
    167 
    168     CairoFtFaceLocker cairoFtFaceLocker(m_scaledFont.get());
    169     if (FT_Face fontConfigFace = cairoFtFaceLocker.ftFace())
    170         m_fixedWidth = fontConfigFace->face_flags & FT_FACE_FLAG_FIXED_WIDTH;
    171118}
    172119
     
    245192}
    246193
     194FcPattern* FontPlatformData::fcPattern() const
     195{
     196    return m_pattern.get();
     197}
     198
    247199bool FontPlatformData::isFixedPitch() const
    248200{
     
    275227void FontPlatformData::buildScaledFont(cairo_font_face_t* fontFace)
    276228{
     229    ASSERT(m_pattern);
    277230    CairoUniquePtr<cairo_font_options_t> options(cairo_font_options_copy(getDefaultCairoFontOptions()));
    278     FcPattern* optionsPattern = m_pattern ? m_pattern.get() : getDefaultFontconfigOptions();
    279     setCairoFontOptionsFromFontConfigPattern(options.get(), optionsPattern);
     231    setCairoFontOptionsFromFontConfigPattern(options.get(), m_pattern.get());
    280232
    281233    cairo_matrix_t ctm;
     
    289241
    290242    // These matrices may be stacked in the pattern, so it's our job to get them all and multiply them.
    291     for (int i = 0; FcPatternGetMatrix(optionsPattern, FC_MATRIX, i, &tempFontConfigMatrix) == FcResultMatch; i++)
     243    for (int i = 0; FcPatternGetMatrix(m_pattern.get(), FC_MATRIX, i, &tempFontConfigMatrix) == FcResultMatch; i++)
    292244        FcMatrixMultiply(&fontConfigMatrix, &fontConfigMatrix, tempFontConfigMatrix);
    293245
  • trunk/Source/WebCore/platform/graphics/freetype/SimpleFontDataFreeType.cpp

    r239122 r239156  
    144144{
    145145    ASSERT(m_platformData.scaledFont());
    146     FontDescription scaledFontDescription = fontDescription;
    147     scaledFontDescription.setComputedSize(scaleFactor * fontDescription.computedSize());
    148146    return Font::create(FontPlatformData(cairo_scaled_font_get_font_face(m_platformData.scaledFont()),
    149         scaledFontDescription,
     147        m_platformData.fcPattern(),
     148        scaleFactor * fontDescription.computedSize(),
     149        m_platformData.isFixedWidth(),
    150150        m_platformData.syntheticBold(),
    151         m_platformData.syntheticOblique()),
     151        m_platformData.syntheticOblique(),
     152        fontDescription.orientation()),
    152153        origin(), Interstitial::No);
    153154}
  • trunk/Source/WebCore/platform/graphics/harfbuzz/HarfBuzzFaceCairo.cpp

    r239122 r239156  
    4848#include <wtf/text/StringView.h>
    4949
     50#if ENABLE(VARIATION_FONTS)
     51#include FT_MULTIPLE_MASTERS_H
     52#endif
     53
    5054namespace WebCore {
    5155
     
    214218    int scale = floatToHarfBuzzPosition(size);
    215219    hb_font_set_scale(font, scale, scale);
     220
     221#if ENABLE(VARIATION_FONTS)
     222    {
     223        CairoFtFaceLocker cairoFtFaceLocker(m_platformData.scaledFont());
     224        if (FT_Face face = cairoFtFaceLocker.ftFace()) {
     225            FT_MM_Var* ftMMVar;
     226            if (!FT_Get_MM_Var(face, &ftMMVar)) {
     227                Vector<FT_Fixed, 4> coords;
     228                coords.resize(ftMMVar->num_axis);
     229                if (!FT_Get_Var_Design_Coordinates(face, coords.size(), coords.data())) {
     230                    Vector<hb_variation_t, 4> variations(coords.size());
     231                    for (FT_UInt i = 0; i < ftMMVar->num_axis; ++i) {
     232                        variations[i].tag = ftMMVar->axis[i].tag;
     233                        variations[i].value = coords[i] / 65536.0;
     234                    }
     235                    hb_font_set_variations(font, variations.data(), variations.size());
     236                }
     237                FT_Done_MM_Var(face->glyph->library, ftMMVar);
     238            }
     239        }
     240    }
     241#endif
     242
    216243    hb_font_make_immutable(font);
    217244    return font;
  • trunk/Source/WebCore/platform/graphics/win/FontCustomPlatformData.cpp

    r239122 r239156  
    4747}
    4848
    49 FontPlatformData FontCustomPlatformData::fontPlatformData(const FontDescription& fontDescription, bool bold, bool italic)
     49FontPlatformData FontCustomPlatformData::fontPlatformData(const FontDescription& fontDescription, bool bold, bool italic, const FontFeatureSettings&, const FontVariantSettings&, FontSelectionSpecifiedCapabilities)
    5050{
    5151    int size = fontDescription.computedPixelSize();
  • trunk/Source/WebCore/platform/graphics/win/FontCustomPlatformData.h

    r239122 r239156  
    3535class FontPlatformData;
    3636class SharedBuffer;
     37struct FontSelectionSpecifiedCapabilities;
     38struct FontVariantSettings;
     39
     40template <typename T> class FontTaggedSettings;
     41typedef FontTaggedSettings<int> FontFeatureSettings;
    3742
    3843struct FontCustomPlatformData {
     
    4752    ~FontCustomPlatformData();
    4853
    49     FontPlatformData fontPlatformData(const FontDescription&, bool bold, bool italic);
     54    FontPlatformData fontPlatformData(const FontDescription&, bool bold, bool italic, const FontFeatureSettings&, const FontVariantSettings&, FontSelectionSpecifiedCapabilities);
    5055
    5156    static bool supportsFormat(const String&);
  • trunk/Source/WebCore/platform/graphics/win/FontCustomPlatformDataCairo.cpp

    r239122 r239156  
    4141}
    4242
    43 FontPlatformData FontCustomPlatformData::fontPlatformData(const FontDescription& fontDescription, bool bold, bool italic)
     43FontPlatformData FontCustomPlatformData::fontPlatformData(const FontDescription& fontDescription, bool bold, bool italic, const FontFeatureSettings&, const FontVariantSettings&, FontSelectionSpecifiedCapabilities)
    4444{
    4545    int size = fontDescription.computedPixelSize();
  • trunk/Source/cmake/OptionsGTK.cmake

    r239122 r239156  
    126126endif ()
    127127
     128# Enable variation fonts when cairo >= 1.16, fontconfig >= 2.13.0, freetype >= 2.9.0 and harfbuzz >= 1.4.2.
     129if ("${PC_CAIRO_VERSION}" VERSION_GREATER_EQUAL "1.16.0"
     130    AND "${PC_FONTCONFIG_VERSION}" VERSION_GREATER_EQUAL "2.13.0"
     131    AND "${FREETYPE_VERSION_STRING}" VERSION_GREATER_EQUAL "2.9.0"
     132    AND "${PC_HARFBUZZ_VERSION}" VERSION_GREATER_EQUAL "1.4.2")
     133    WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_VARIATION_FONTS PRIVATE ON)
     134endif ()
     135
    128136# Public options shared with other WebKit ports. Do not add any options here
    129137# without approval from a GTK+ reviewer. There must be strong reason to support
  • trunk/Tools/ChangeLog

    r239151 r239156  
     12018-12-12  Carlos Garcia Campos  <cgarcia@igalia.com>
     2
     3        [FreeType] Add initial implementation of variation fonts
     4        https://bugs.webkit.org/show_bug.cgi?id=192151
     5
     6        Reviewed by Michael Catanzaro.
     7
     8        Add cairo patch to avoid crashes.
     9
     10        * gtk/jhbuild.modules:
     11        * gtk/patches/cairo-ft-Use-FT_Done_MM_Var-instead-of-free-when-available.patch: Added.
     12
    1132018-12-12  Fujii Hironori  <Hironori.Fujii@sony.com>
    214
  • trunk/Tools/gtk/jhbuild.modules

    r239122 r239156  
    108108    <branch module="releases/cairo-1.16.0.tar.xz" version="1.16.0"
    109109            repo="cairographics.org"
    110             hash="sha1:00e81842ae5e81bb0343108884eb5205be0eac14"/>
     110            hash="sha1:00e81842ae5e81bb0343108884eb5205be0eac14">
     111      <!-- See https://gitlab.freedesktop.org/cairo/cairo/merge_requests/5 -->
     112      <patch file="cairo-ft-Use-FT_Done_MM_Var-instead-of-free-when-available.patch" strip="1"/>
     113    </branch>
    111114  </autotools>
    112115
Note: See TracChangeset for help on using the changeset viewer.