Fix font rendering issues with freetype 2.8.1 for firefox and firefox-esr (#7723)
* firefox: add patch to fix font rendering issue with freetype 2.8.1 After the recent freetype upgrade, font rendering in firefox was messed up because of issues with the bundled Skia library as documented in https://bugzilla.mozilla.org/show_bug.cgi?id=1393467 . This commit adds the patch from https://bugzilla.mozilla.org/attachment.cgi?id=8902859 . * firefox-esr: add patch to fix font rendering issue with freetype 2.8.1 After the recent freetype upgrade, font rendering in firefox-esr was messed up because of issues with the bundled Skia library as documented in https://bugzilla.mozilla.org/show_bug.cgi?id=1393467 . This commit adds the patch from https://bugzilla.mozilla.org/attachment.cgi?id=8904705 which is a backported version of the Skia fix for Firefox 52 ESR.
This commit is contained in:
parent
1b67fa41e9
commit
8ca8ebae43
4 changed files with 313 additions and 2 deletions
148
srcpkgs/firefox-esr/patches/skia-freetype.patch
Normal file
148
srcpkgs/firefox-esr/patches/skia-freetype.patch
Normal file
|
@ -0,0 +1,148 @@
|
|||
# HG changeset patch
|
||||
# User Lee Salzman <lsalzman@mozilla.com>
|
||||
# Date 1504640559 14400
|
||||
# Tue Sep 05 15:42:39 2017 -0400
|
||||
# Node ID 923246286b9858fb103e100f886c03714b97b5ec
|
||||
# Parent 3fff2b174212af40a7b7ba75a047db431f81c780
|
||||
clip FreeType glyph bitmap to mask in Skia (52 ESR)
|
||||
|
||||
diff --git a/gfx/skia/skia/src/ports/SkFontHost_FreeType_common.cpp b/gfx/skia/skia/src/ports/SkFontHost_FreeType_common.cpp
|
||||
--- gfx/skia/skia/src/ports/SkFontHost_FreeType_common.cpp
|
||||
+++ gfx/skia/skia/src/ports/SkFontHost_FreeType_common.cpp
|
||||
@@ -350,58 +350,118 @@ void SkScalerContext_FreeType_Base::gene
|
||||
const SkMatrix& bitmapTransform)
|
||||
{
|
||||
const bool doBGR = SkToBool(fRec.fFlags & SkScalerContext::kLCD_BGROrder_Flag);
|
||||
const bool doVert = SkToBool(fRec.fFlags & SkScalerContext::kLCD_Vertical_Flag);
|
||||
|
||||
switch ( face->glyph->format ) {
|
||||
case FT_GLYPH_FORMAT_OUTLINE: {
|
||||
FT_Outline* outline = &face->glyph->outline;
|
||||
- FT_BBox bbox;
|
||||
- FT_Bitmap target;
|
||||
|
||||
int dx = 0, dy = 0;
|
||||
if (fRec.fFlags & SkScalerContext::kSubpixelPositioning_Flag) {
|
||||
dx = SkFixedToFDot6(glyph.getSubXFixed());
|
||||
dy = SkFixedToFDot6(glyph.getSubYFixed());
|
||||
// negate dy since freetype-y-goes-up and skia-y-goes-down
|
||||
dy = -dy;
|
||||
}
|
||||
- FT_Outline_Get_CBox(outline, &bbox);
|
||||
- /*
|
||||
- what we really want to do for subpixel is
|
||||
- offset(dx, dy)
|
||||
- compute_bounds
|
||||
- offset(bbox & !63)
|
||||
- but that is two calls to offset, so we do the following, which
|
||||
- achieves the same thing with only one offset call.
|
||||
- */
|
||||
- FT_Outline_Translate(outline, dx - ((bbox.xMin + dx) & ~63),
|
||||
- dy - ((bbox.yMin + dy) & ~63));
|
||||
+ memset(glyph.fImage, 0, glyph.rowBytes() * glyph.fHeight);
|
||||
|
||||
if (SkMask::kLCD16_Format == glyph.fMaskFormat) {
|
||||
- FT_Render_Glyph(face->glyph, doVert ? FT_RENDER_MODE_LCD_V : FT_RENDER_MODE_LCD);
|
||||
+ FT_Outline_Translate(outline, dx, dy);
|
||||
+ FT_Error err = FT_Render_Glyph(face->glyph, doVert ? FT_RENDER_MODE_LCD_V : FT_RENDER_MODE_LCD);
|
||||
+ if (err) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
SkMask mask;
|
||||
glyph.toMask(&mask);
|
||||
+
|
||||
+ FT_GlyphSlotRec& ftGlyph = *face->glyph;
|
||||
+
|
||||
+ if (!SkIRect::Intersects(mask.fBounds,
|
||||
+ SkIRect::MakeXYWH( ftGlyph.bitmap_left,
|
||||
+ -ftGlyph.bitmap_top,
|
||||
+ ftGlyph.bitmap.width,
|
||||
+ ftGlyph.bitmap.rows)))
|
||||
+ {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ // If the FT_Bitmap extent is larger, discard bits of the bitmap outside the mask.
|
||||
+ // If the SkMask extent is larger, shrink mask to fit bitmap (clearing discarded).
|
||||
+ unsigned char* origBuffer = ftGlyph.bitmap.buffer;
|
||||
+ // First align the top left (origin).
|
||||
+ if (-ftGlyph.bitmap_top < mask.fBounds.fTop) {
|
||||
+ int32_t topDiff = mask.fBounds.fTop - (-ftGlyph.bitmap_top);
|
||||
+ ftGlyph.bitmap.buffer += ftGlyph.bitmap.pitch * topDiff;
|
||||
+ ftGlyph.bitmap.rows -= topDiff;
|
||||
+ ftGlyph.bitmap_top = -mask.fBounds.fTop;
|
||||
+ }
|
||||
+ if (ftGlyph.bitmap_left < mask.fBounds.fLeft) {
|
||||
+ int32_t leftDiff = mask.fBounds.fLeft - ftGlyph.bitmap_left;
|
||||
+ ftGlyph.bitmap.buffer += leftDiff;
|
||||
+ ftGlyph.bitmap.width -= leftDiff;
|
||||
+ ftGlyph.bitmap_left = mask.fBounds.fLeft;
|
||||
+ }
|
||||
+ if (mask.fBounds.fTop < -ftGlyph.bitmap_top) {
|
||||
+ mask.fImage += mask.fRowBytes * (-ftGlyph.bitmap_top - mask.fBounds.fTop);
|
||||
+ mask.fBounds.fTop = -ftGlyph.bitmap_top;
|
||||
+ }
|
||||
+ if (mask.fBounds.fLeft < ftGlyph.bitmap_left) {
|
||||
+ mask.fImage += sizeof(uint16_t) * (ftGlyph.bitmap_left - mask.fBounds.fLeft);
|
||||
+ mask.fBounds.fLeft = ftGlyph.bitmap_left;
|
||||
+ }
|
||||
+ // Origins aligned, clean up the width and height.
|
||||
+ int ftVertScale = (doVert ? 3 : 1);
|
||||
+ int ftHoriScale = (doVert ? 1 : 3);
|
||||
+ if (mask.fBounds.height() * ftVertScale < SkToInt(ftGlyph.bitmap.rows)) {
|
||||
+ ftGlyph.bitmap.rows = mask.fBounds.height() * ftVertScale;
|
||||
+ }
|
||||
+ if (mask.fBounds.width() * ftHoriScale < SkToInt(ftGlyph.bitmap.width)) {
|
||||
+ ftGlyph.bitmap.width = mask.fBounds.width() * ftHoriScale;
|
||||
+ }
|
||||
+ if (SkToInt(ftGlyph.bitmap.rows) < mask.fBounds.height() * ftVertScale) {
|
||||
+ mask.fBounds.fBottom = mask.fBounds.fTop + ftGlyph.bitmap.rows / ftVertScale;
|
||||
+ }
|
||||
+ if (SkToInt(ftGlyph.bitmap.width) < mask.fBounds.width() * ftHoriScale) {
|
||||
+ mask.fBounds.fRight = mask.fBounds.fLeft + ftGlyph.bitmap.width / ftHoriScale;
|
||||
+ }
|
||||
+
|
||||
if (fPreBlend.isApplicable()) {
|
||||
- copyFT2LCD16<true>(face->glyph->bitmap, mask, doBGR,
|
||||
+ copyFT2LCD16<true>(ftGlyph.bitmap, mask, doBGR,
|
||||
fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
|
||||
} else {
|
||||
- copyFT2LCD16<false>(face->glyph->bitmap, mask, doBGR,
|
||||
+ copyFT2LCD16<false>(ftGlyph.bitmap, mask, doBGR,
|
||||
fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
|
||||
}
|
||||
+ // Restore the buffer pointer so FreeType can properly free it.
|
||||
+ ftGlyph.bitmap.buffer = origBuffer;
|
||||
} else {
|
||||
+ FT_BBox bbox;
|
||||
+ FT_Bitmap target;
|
||||
+ FT_Outline_Get_CBox(outline, &bbox);
|
||||
+ /*
|
||||
+ what we really want to do for subpixel is
|
||||
+ offset(dx, dy)
|
||||
+ compute_bounds
|
||||
+ offset(bbox & !63)
|
||||
+ but that is two calls to offset, so we do the following, which
|
||||
+ achieves the same thing with only one offset call.
|
||||
+ */
|
||||
+ FT_Outline_Translate(outline, dx - ((bbox.xMin + dx) & ~63),
|
||||
+ dy - ((bbox.yMin + dy) & ~63));
|
||||
+
|
||||
target.width = glyph.fWidth;
|
||||
target.rows = glyph.fHeight;
|
||||
target.pitch = glyph.rowBytes();
|
||||
target.buffer = reinterpret_cast<uint8_t*>(glyph.fImage);
|
||||
target.pixel_mode = compute_pixel_mode( (SkMask::Format)fRec.fMaskFormat);
|
||||
target.num_grays = 256;
|
||||
|
||||
- memset(glyph.fImage, 0, glyph.rowBytes() * glyph.fHeight);
|
||||
FT_Outline_Get_Bitmap(face->glyph->library, outline, &target);
|
||||
}
|
||||
} break;
|
||||
|
||||
case FT_GLYPH_FORMAT_BITMAP: {
|
||||
FT_Pixel_Mode pixel_mode = static_cast<FT_Pixel_Mode>(face->glyph->bitmap.pixel_mode);
|
||||
SkMask::Format maskFormat = static_cast<SkMask::Format>(glyph.fMaskFormat);
|
||||
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
# Template build file for 'firefox-esr'.
|
||||
pkgname=firefox-esr
|
||||
version=52.3.0
|
||||
revision=1
|
||||
revision=2
|
||||
wrksrc="firefox-${version}esr"
|
||||
short_desc="Mozilla Firefox web browser - Extended Support Release (ESR)"
|
||||
maintainer="Eivind Uggedal <eivind@uggedal.com>"
|
||||
|
|
163
srcpkgs/firefox/patches/skia-freetype.patch
Normal file
163
srcpkgs/firefox/patches/skia-freetype.patch
Normal file
|
@ -0,0 +1,163 @@
|
|||
# HG changeset patch
|
||||
# User Lee Salzman <lsalzman@mozilla.com>
|
||||
# Date 1504120456 14400
|
||||
# Wed Aug 30 15:14:16 2017 -0400
|
||||
# Node ID 708d52f954b6d7ca2497fcb5b5084c6483300e89
|
||||
# Parent 33224536ce20d942576cd4b9ffb350d6dce397bc
|
||||
clip FreeType glyph bitmap to mask in Skia
|
||||
|
||||
MozReview-Commit-ID: 9NqLj9SkHFo
|
||||
|
||||
diff --git a/gfx/skia/skia/src/ports/SkFontHost_FreeType_common.cpp b/gfx/skia/skia/src/ports/SkFontHost_FreeType_common.cpp
|
||||
--- gfx/skia/skia/src/ports/SkFontHost_FreeType_common.cpp
|
||||
+++ gfx/skia/skia/src/ports/SkFontHost_FreeType_common.cpp
|
||||
@@ -390,65 +390,131 @@ void SkScalerContext_FreeType_Base::gene
|
||||
const SkMatrix& bitmapTransform)
|
||||
{
|
||||
const bool doBGR = SkToBool(fRec.fFlags & SkScalerContext::kLCD_BGROrder_Flag);
|
||||
const bool doVert = SkToBool(fRec.fFlags & SkScalerContext::kLCD_Vertical_Flag);
|
||||
|
||||
switch ( face->glyph->format ) {
|
||||
case FT_GLYPH_FORMAT_OUTLINE: {
|
||||
FT_Outline* outline = &face->glyph->outline;
|
||||
- FT_BBox bbox;
|
||||
- FT_Bitmap target;
|
||||
|
||||
int dx = 0, dy = 0;
|
||||
if (fRec.fFlags & SkScalerContext::kSubpixelPositioning_Flag) {
|
||||
dx = SkFixedToFDot6(glyph.getSubXFixed());
|
||||
dy = SkFixedToFDot6(glyph.getSubYFixed());
|
||||
// negate dy since freetype-y-goes-up and skia-y-goes-down
|
||||
dy = -dy;
|
||||
}
|
||||
- FT_Outline_Get_CBox(outline, &bbox);
|
||||
- /*
|
||||
- what we really want to do for subpixel is
|
||||
- offset(dx, dy)
|
||||
- compute_bounds
|
||||
- offset(bbox & !63)
|
||||
- but that is two calls to offset, so we do the following, which
|
||||
- achieves the same thing with only one offset call.
|
||||
- */
|
||||
- FT_Outline_Translate(outline, dx - ((bbox.xMin + dx) & ~63),
|
||||
- dy - ((bbox.yMin + dy) & ~63));
|
||||
+
|
||||
+ memset(glyph.fImage, 0, glyph.rowBytes() * glyph.fHeight);
|
||||
|
||||
if (SkMask::kLCD16_Format == glyph.fMaskFormat) {
|
||||
+ FT_Outline_Translate(outline, dx, dy);
|
||||
FT_Error err = FT_Render_Glyph(face->glyph, doVert ? FT_RENDER_MODE_LCD_V :
|
||||
FT_RENDER_MODE_LCD);
|
||||
if (err) {
|
||||
SK_TRACEFTR(err, "Could not render glyph.");
|
||||
- sk_bzero(glyph.fImage, glyph.computeImageSize());
|
||||
return;
|
||||
}
|
||||
+
|
||||
SkMask mask;
|
||||
glyph.toMask(&mask);
|
||||
+#ifdef SK_SHOW_TEXT_BLIT_COVERAGE
|
||||
+ memset(mask.fImage, 0x80, mask.fBounds.height() * mask.fRowBytes);
|
||||
+#endif
|
||||
+ FT_GlyphSlotRec& ftGlyph = *face->glyph;
|
||||
+
|
||||
+ if (!SkIRect::Intersects(mask.fBounds,
|
||||
+ SkIRect::MakeXYWH( ftGlyph.bitmap_left,
|
||||
+ -ftGlyph.bitmap_top,
|
||||
+ ftGlyph.bitmap.width,
|
||||
+ ftGlyph.bitmap.rows)))
|
||||
+ {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ // If the FT_Bitmap extent is larger, discard bits of the bitmap outside the mask.
|
||||
+ // If the SkMask extent is larger, shrink mask to fit bitmap (clearing discarded).
|
||||
+ unsigned char* origBuffer = ftGlyph.bitmap.buffer;
|
||||
+ // First align the top left (origin).
|
||||
+ if (-ftGlyph.bitmap_top < mask.fBounds.fTop) {
|
||||
+ int32_t topDiff = mask.fBounds.fTop - (-ftGlyph.bitmap_top);
|
||||
+ ftGlyph.bitmap.buffer += ftGlyph.bitmap.pitch * topDiff;
|
||||
+ ftGlyph.bitmap.rows -= topDiff;
|
||||
+ ftGlyph.bitmap_top = -mask.fBounds.fTop;
|
||||
+ }
|
||||
+ if (ftGlyph.bitmap_left < mask.fBounds.fLeft) {
|
||||
+ int32_t leftDiff = mask.fBounds.fLeft - ftGlyph.bitmap_left;
|
||||
+ ftGlyph.bitmap.buffer += leftDiff;
|
||||
+ ftGlyph.bitmap.width -= leftDiff;
|
||||
+ ftGlyph.bitmap_left = mask.fBounds.fLeft;
|
||||
+ }
|
||||
+ if (mask.fBounds.fTop < -ftGlyph.bitmap_top) {
|
||||
+ mask.fImage += mask.fRowBytes * (-ftGlyph.bitmap_top - mask.fBounds.fTop);
|
||||
+ mask.fBounds.fTop = -ftGlyph.bitmap_top;
|
||||
+ }
|
||||
+ if (mask.fBounds.fLeft < ftGlyph.bitmap_left) {
|
||||
+ mask.fImage += sizeof(uint16_t) * (ftGlyph.bitmap_left - mask.fBounds.fLeft);
|
||||
+ mask.fBounds.fLeft = ftGlyph.bitmap_left;
|
||||
+ }
|
||||
+ // Origins aligned, clean up the width and height.
|
||||
+ int ftVertScale = (doVert ? 3 : 1);
|
||||
+ int ftHoriScale = (doVert ? 1 : 3);
|
||||
+ if (mask.fBounds.height() * ftVertScale < SkToInt(ftGlyph.bitmap.rows)) {
|
||||
+ ftGlyph.bitmap.rows = mask.fBounds.height() * ftVertScale;
|
||||
+ }
|
||||
+ if (mask.fBounds.width() * ftHoriScale < SkToInt(ftGlyph.bitmap.width)) {
|
||||
+ ftGlyph.bitmap.width = mask.fBounds.width() * ftHoriScale;
|
||||
+ }
|
||||
+ if (SkToInt(ftGlyph.bitmap.rows) < mask.fBounds.height() * ftVertScale) {
|
||||
+ mask.fBounds.fBottom = mask.fBounds.fTop + ftGlyph.bitmap.rows / ftVertScale;
|
||||
+ }
|
||||
+ if (SkToInt(ftGlyph.bitmap.width) < mask.fBounds.width() * ftHoriScale) {
|
||||
+ mask.fBounds.fRight = mask.fBounds.fLeft + ftGlyph.bitmap.width / ftHoriScale;
|
||||
+ }
|
||||
if (fPreBlend.isApplicable()) {
|
||||
- copyFT2LCD16<true>(face->glyph->bitmap, mask, doBGR,
|
||||
+ copyFT2LCD16<true>(ftGlyph.bitmap, mask, doBGR,
|
||||
fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
|
||||
} else {
|
||||
- copyFT2LCD16<false>(face->glyph->bitmap, mask, doBGR,
|
||||
+ copyFT2LCD16<false>(ftGlyph.bitmap, mask, doBGR,
|
||||
fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
|
||||
}
|
||||
+ // Restore the buffer pointer so FreeType can properly free it.
|
||||
+ ftGlyph.bitmap.buffer = origBuffer;
|
||||
} else {
|
||||
+ FT_BBox bbox;
|
||||
+ FT_Bitmap target;
|
||||
+ FT_Outline_Get_CBox(outline, &bbox);
|
||||
+ /*
|
||||
+ what we really want to do for subpixel is
|
||||
+ offset(dx, dy)
|
||||
+ compute_bounds
|
||||
+ offset(bbox & !63)
|
||||
+ but that is two calls to offset, so we do the following, which
|
||||
+ achieves the same thing with only one offset call.
|
||||
+ */
|
||||
+ FT_Outline_Translate(outline, dx - ((bbox.xMin + dx) & ~63),
|
||||
+ dy - ((bbox.yMin + dy) & ~63));
|
||||
+
|
||||
target.width = glyph.fWidth;
|
||||
target.rows = glyph.fHeight;
|
||||
target.pitch = glyph.rowBytes();
|
||||
target.buffer = reinterpret_cast<uint8_t*>(glyph.fImage);
|
||||
target.pixel_mode = compute_pixel_mode( (SkMask::Format)fRec.fMaskFormat);
|
||||
target.num_grays = 256;
|
||||
|
||||
- memset(glyph.fImage, 0, glyph.rowBytes() * glyph.fHeight);
|
||||
FT_Outline_Get_Bitmap(face->glyph->library, outline, &target);
|
||||
+#ifdef SK_SHOW_TEXT_BLIT_COVERAGE
|
||||
+ for (int y = 0; y < glyph.fHeight; ++y) {
|
||||
+ for (int x = 0; x < glyph.fWidth; ++x) {
|
||||
+ uint8_t& a = ((uint8_t*)glyph.fImage)[(glyph.rowBytes() * y) + x];
|
||||
+ a = SkTMax<uint8_t>(a, 0x20);
|
||||
+ }
|
||||
+ }
|
||||
+#endif
|
||||
}
|
||||
} break;
|
||||
|
||||
case FT_GLYPH_FORMAT_BITMAP: {
|
||||
FT_Pixel_Mode pixel_mode = static_cast<FT_Pixel_Mode>(face->glyph->bitmap.pixel_mode);
|
||||
SkMask::Format maskFormat = static_cast<SkMask::Format>(glyph.fMaskFormat);
|
||||
|
||||
// Assume that the other formats do not exist.
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
# Template build file for 'firefox'.
|
||||
pkgname=firefox
|
||||
version=55.0.3
|
||||
revision=1
|
||||
revision=2
|
||||
short_desc="Mozilla Firefox web browser"
|
||||
maintainer="Juan RP <xtraeme@voidlinux.eu>"
|
||||
homepage="https://www.mozilla.org/firefox/"
|
||||
|
|
Loading…
Reference in a new issue