From ceeaa97cbf02d92be39d65e326f4238117830b62 Mon Sep 17 00:00:00 2001 From: Helmut Pozimski Date: Mon, 18 Sep 2017 19:29:26 +0200 Subject: [PATCH] thunderbird: add patch to fix font rendering issue with freetype 2.8.1 After the recent freetype upgrade, font rendering in thunderbird 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 and also applies to the Skia version bundled with thunderbird. --- .../thunderbird/patches/freetype-skia.patch | 147 ++++++++++++++++++ srcpkgs/thunderbird/template | 2 +- 2 files changed, 148 insertions(+), 1 deletion(-) create mode 100644 srcpkgs/thunderbird/patches/freetype-skia.patch diff --git a/srcpkgs/thunderbird/patches/freetype-skia.patch b/srcpkgs/thunderbird/patches/freetype-skia.patch new file mode 100644 index 00000000000..2f573bf79a7 --- /dev/null +++ b/srcpkgs/thunderbird/patches/freetype-skia.patch @@ -0,0 +1,147 @@ +# HG changeset patch +# User Lee Salzman +# 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 +--- mozilla/gfx/skia/skia/src/ports/SkFontHost_FreeType_common.cpp ++++ mozilla/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(face->glyph->bitmap, mask, doBGR, ++ copyFT2LCD16(ftGlyph.bitmap, mask, doBGR, + fPreBlend.fR, fPreBlend.fG, fPreBlend.fB); + } else { +- copyFT2LCD16(face->glyph->bitmap, mask, doBGR, ++ copyFT2LCD16(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(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(face->glyph->bitmap.pixel_mode); + SkMask::Format maskFormat = static_cast(glyph.fMaskFormat); + diff --git a/srcpkgs/thunderbird/template b/srcpkgs/thunderbird/template index 05996af5b53..9b9c6cd4b9f 100644 --- a/srcpkgs/thunderbird/template +++ b/srcpkgs/thunderbird/template @@ -1,7 +1,7 @@ # Template build file for 'thunderbird'. pkgname=thunderbird version=52.3.0 -revision=1 +revision=2 short_desc="Standalone Mail/News reader" maintainer="Enno Boland " homepage="http://www.mozilla.org/thunderbird/"