+2015-05-06 Martin Robinson <mrobinson@igalia.com>
+
+ [FreeType] Vertical CJK glyphs should not be rendered with synthetic oblique
+ https://bugs.webkit.org/show_bug.cgi?id=144612
+
+ Reviewed by Darin Adler.
+
+ No new tests. This causes fast/text/international/synthesized-italic-vertical.html to pass.
+
+ * platform/graphics/Font.cpp:
+ (WebCore::Font::nonSyntheticItalicFont): Compile this method for Cairo as well.
+ * platform/graphics/FontCascadeFonts.cpp:
+ (WebCore::FontCascadeFonts::glyphDataForSystemFallback): When searching for the system fallback,
+ ensure that we do not use synthetic oblique when rendering vertical CJK glyphs.
+ (WebCore::FontCascadeFonts::glyphDataForNormalVariant): Extend the CJK fix to Cairo ports.
+ * platform/graphics/FontPlatformData.h:
+ (WebCore::FontPlatformData::setSyntheticOblique): Added this helper method, because
+ Freetype/Cairo ports needs to be able to recreate the scaled font matrix when the
+ synthetic oblique settings changes.
+ * platform/graphics/freetype/FontPlatformData.h: Rename initializeWithFontFace to buildScaledFont.
+ Remove the now unused m_horizontalOrientationMatrix member.
+ (WebCore::FontPlatformData::setSyntheticOblique): Added the helper here as well.
+ * platform/graphics/freetype/FontPlatformDataFreeType.cpp:
+ (WebCore::FontPlatformData::FontPlatformData): Calculate whether or not to use synthetic oblique here,
+ before buildScaledFont is called. Call buildScaledFont instead of initializeWithFontFace.
+ (WebCore::FontPlatformData::operator=):
+ (WebCore::FontPlatformData::buildScaledFont): Renamed from initializeWithFontFace, does
+ the same thing, except calculate whether or not to use synthetic oblique. Instead just
+ reads the value.
+ (WebCore::FontPlatformData::setOrientation): Instead of adjusting the font matrix, recreate
+ the entire font.
+ (WebCore::FontPlatformData::setSyntheticOblique): Added.
+ (WebCore::rotateCairoMatrixForVerticalOrientation): Deleted.
+ (WebCore::FontPlatformData::initializeWithFontFace): Deleted.
+
2015-05-06 Alex Christensen <achristensen@webkit.org>
[Content Extensions] Test splitting NFAs by max NFA size.
return false;
}
-#if PLATFORM(COCOA)
+#if PLATFORM(COCOA) || USE(CAIRO)
static GlyphData glyphDataForCJKCharacterWithoutSyntheticItalic(UChar32 character, GlyphData& data)
{
GlyphData nonItalicData = data.font->nonSyntheticItalicFont()->glyphDataForCharacter(character);
else
fallbackGlyphData = systemFallbackFont->variantFont(description, variant)->glyphDataForCharacter(c);
- if (variant == NormalVariant && fallbackGlyphData.font) {
- if (!FontCascade::isCJKIdeographOrSymbol(c) && fallbackGlyphData.font->platformData().orientation() == Vertical && !fallbackGlyphData.font->isTextOrientationFallback())
+ if (fallbackGlyphData.font && fallbackGlyphData.font->platformData().orientation() == Vertical && !fallbackGlyphData.font->isTextOrientationFallback()) {
+ if (variant == NormalVariant && !FontCascade::isCJKIdeographOrSymbol(c))
fallbackGlyphData = glyphDataForNonCJKCharacterWithGlyphOrientation(c, description.nonCJKGlyphOrientation(), fallbackGlyphData);
+#if PLATFORM(COCOA) || USE(CAIRO)
+ if (fallbackGlyphData.font->platformData().syntheticOblique() && FontCascade::isCJKIdeographOrSymbol(c))
+ fallbackGlyphData = glyphDataForCJKCharacterWithoutSyntheticItalic(c, fallbackGlyphData);
+#endif
}
// Keep the system fallback fonts we use alive.
// to make sure you get a square (even for broken glyphs like symbols used for punctuation).
return glyphDataForVariant(c, description, BrokenIdeographVariant, fallbackIndex);
}
-#if PLATFORM(COCOA)
+#if PLATFORM(COCOA) || USE(CAIRO)
if (data.font->platformData().syntheticOblique())
return glyphDataForCJKCharacterWithoutSyntheticItalic(c, data);
#endif
return pattern;
}
-static void rotateCairoMatrixForVerticalOrientation(cairo_matrix_t* matrix)
-{
- // The resulting transformation matrix for vertical glyphs (V) is a
- // combination of rotation (R) and translation (T) applied on the
- // horizontal matrix (H). V = H . R . T, where R rotates by -90 degrees
- // and T translates by font size towards y axis.
- cairo_matrix_rotate(matrix, -piOverTwoDouble);
- cairo_matrix_translate(matrix, 0.0, 1.0);
-}
-
FontPlatformData::FontPlatformData(FcPattern* pattern, const FontDescription& fontDescription)
: m_pattern(pattern)
, m_fallbacks(nullptr)
, m_scaledFont(nullptr)
, m_orientation(fontDescription.orientation())
{
+ ASSERT(m_pattern);
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)
if (!m_syntheticBold && FcPatternGetInteger(pattern, FC_WEIGHT, 0, &weight) == FcResultMatch)
m_syntheticBold = m_syntheticBold || weight < FC_WEIGHT_DEMIBOLD;
}
+
+ // We requested an italic font, but Fontconfig gave us one that was neither oblique nor italic.
+ int actualFontSlant;
+ bool descriptionAllowsSyntheticOblique = fontDescription.fontSynthesis() & FontSynthesisStyle;
+ if (descriptionAllowsSyntheticOblique && fontDescription.italic()
+ && FcPatternGetInteger(pattern, FC_SLANT, 0, &actualFontSlant) == FcResultMatch) {
+ m_syntheticOblique = actualFontSlant == FC_SLANT_ROMAN;
+ }
+
+ buildScaledFont(fontFace.get());
}
FontPlatformData::FontPlatformData(float size, bool bold, bool italic)
, m_scaledFont(nullptr)
, m_orientation(orientation)
{
- initializeWithFontFace(fontFace);
+ buildScaledFont(fontFace);
FT_Face fontConfigFace = cairo_ft_scaled_font_lock_face(m_scaledFont);
if (fontConfigFace) {
m_fixedWidth = other.m_fixedWidth;
m_pattern = other.m_pattern;
m_orientation = other.m_orientation;
- m_horizontalOrientationMatrix = other.m_horizontalOrientationMatrix;
if (m_fallbacks) {
FcFontSetDestroy(m_fallbacks);
// We need to reinitialize the instance, because the difference in size
// necessitates a new scaled font instance.
m_size = size;
- initializeWithFontFace(cairo_scaled_font_get_font_face(m_scaledFont));
+ buildScaledFont(cairo_scaled_font_get_font_face(m_scaledFont));
}
FontPlatformData::~FontPlatformData()
}
#endif
-void FontPlatformData::initializeWithFontFace(cairo_font_face_t* fontFace, const FontDescription& fontDescription)
+void FontPlatformData::buildScaledFont(cairo_font_face_t* fontFace)
{
cairo_font_options_t* options = getDefaultCairoFontOptions();
FcPattern* optionsPattern = m_pattern ? m_pattern.get() : getDefaultFontconfigOptions();
cairo_matrix_t ctm;
cairo_matrix_init_identity(&ctm);
- // Scaling a font with width zero size leads to a failed cairo_scaled_font_t instantiations.
- // Instead we scale we scale the font to a very tiny size and just abort rendering later on.
- float realSize = m_size ? m_size : 1;
-
// FontConfig may return a list of transformation matrices with the pattern, for instance,
// for fonts that are oblique. We use that to initialize the cairo font matrix.
cairo_matrix_t fontMatrix;
cairo_matrix_init(&fontMatrix, fontConfigMatrix.xx, -fontConfigMatrix.yx,
-fontConfigMatrix.xy, fontConfigMatrix.yy, 0, 0);
- // We requested an italic font, but Fontconfig gave us one that was neither oblique nor italic.
- int actualFontSlant;
- bool descriptionAllowsSyntheticOblique = fontDescription.fontSynthesis() & FontSynthesisStyle;
- if (descriptionAllowsSyntheticOblique && fontDescription.italic()
- && FcPatternGetInteger(optionsPattern, FC_SLANT, 0, &actualFontSlant) == FcResultMatch) {
- m_syntheticOblique = actualFontSlant == FC_SLANT_ROMAN;
- }
-
- // The matrix from FontConfig does not include the scale.
+ // The matrix from FontConfig does not include the scale. Scaling a font with width zero size leads
+ // to a failed cairo_scaled_font_t instantiations. Instead we scale we scale the font to a very tiny
+ // size and just abort rendering later on.
+ float realSize = m_size ? m_size : 1;
cairo_matrix_scale(&fontMatrix, realSize, realSize);
if (syntheticOblique()) {
cairo_matrix_multiply(&fontMatrix, m_orientation == Vertical ? &verticalSkew : &skew, &fontMatrix);
}
- m_horizontalOrientationMatrix = fontMatrix;
- if (m_orientation == Vertical)
- rotateCairoMatrixForVerticalOrientation(&fontMatrix);
+ if (m_orientation == Vertical) {
+ // The resulting transformation matrix for vertical glyphs (V) is a
+ // combination of rotation (R) and translation (T) applied on the
+ // horizontal matrix (H). V = H . R . T, where R rotates by -90 degrees
+ // and T translates by font size towards y axis.
+ cairo_matrix_rotate(&fontMatrix, -piOverTwoDouble);
+ cairo_matrix_translate(&fontMatrix, 0.0, 1.0);
+ }
+
+ if (m_scaledFont && m_scaledFont != hashTableDeletedFontValue())
+ cairo_scaled_font_destroy(m_scaledFont);
m_scaledFont = cairo_scaled_font_create(fontFace, &fontMatrix, &ctm, options);
cairo_font_options_destroy(options);
void FontPlatformData::setOrientation(FontOrientation orientation)
{
- ASSERT(m_scaledFont);
-
if (!m_scaledFont || (m_orientation == orientation))
return;
- cairo_matrix_t transformationMatrix;
- cairo_matrix_init_identity(&transformationMatrix);
-
- cairo_matrix_t fontMatrix;
- cairo_scaled_font_get_font_matrix(m_scaledFont, &fontMatrix);
-
- cairo_font_options_t* options = getDefaultCairoFontOptions();
+ ASSERT(m_scaledFont);
+ m_orientation = orientation;
+ buildScaledFont(cairo_scaled_font_get_font_face(m_scaledFont));
+}
- // In case of vertical orientation, rotate the transformation matrix.
- // Otherwise restore the horizontal orientation matrix.
- if (orientation == Vertical)
- rotateCairoMatrixForVerticalOrientation(&fontMatrix);
- else
- fontMatrix = m_horizontalOrientationMatrix;
+void FontPlatformData::setSyntheticOblique(bool newSyntheticObliqueValue)
+{
+ if (newSyntheticObliqueValue == syntheticOblique())
+ return;
- cairo_font_face_t* fontFace = cairo_scaled_font_get_font_face(m_scaledFont);
- cairo_scaled_font_destroy(m_scaledFont);
- m_scaledFont = cairo_scaled_font_create(fontFace, &fontMatrix, &transformationMatrix, options);
- cairo_font_options_destroy(options);
- m_orientation = orientation;
+ ASSERT(m_scaledFont);
+ m_syntheticOblique = newSyntheticObliqueValue;
+ buildScaledFont(cairo_scaled_font_get_font_face(m_scaledFont));
}
}