aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/ports
diff options
context:
space:
mode:
authorGravatar agl@chromium.org <agl@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>2009-07-28 00:02:42 +0000
committerGravatar agl@chromium.org <agl@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>2009-07-28 00:02:42 +0000
commitac3011c6d4a885af4f37e22ce94451a778239b0d (patch)
tree308f1a2696e435624db0d8d71ccd2f35db6fab83 /src/ports
parente2ca20740b1b3c9e71c085017b64fc9d2f553d93 (diff)
Support subpixel text when FreeType is built without such support.
On Fedora, at least, FreeType is built without subpixel support. It tries to simulate subpixel mode by replicating the gray-values three times. However, it fails to simulate the actions of the low-pass filter and so doesn't add border around the glyphs. This patch adds a compile-time constant, which is the number of bytes of filter border. If this value is zero (because FreeType is simulating subpixel support), then we add a transparent border ourselves when transforming from FreeType rendered glyphs to masks. http://codereview.appspot.com/96171 git-svn-id: http://skia.googlecode.com/svn/trunk@291 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src/ports')
-rw-r--r--src/ports/SkFontHost_FreeType_Subpixel.cpp35
1 files changed, 28 insertions, 7 deletions
diff --git a/src/ports/SkFontHost_FreeType_Subpixel.cpp b/src/ports/SkFontHost_FreeType_Subpixel.cpp
index bc01585ee8..82bb5542cc 100644
--- a/src/ports/SkFontHost_FreeType_Subpixel.cpp
+++ b/src/ports/SkFontHost_FreeType_Subpixel.cpp
@@ -27,6 +27,7 @@
#include <ft2build.h>
#include FT_FREETYPE_H
+#include FT_CONFIG_OPTIONS_H
#if 0
// Also include the files by name for build tools which require this.
@@ -35,10 +36,16 @@
namespace skia_freetype_support {
+#if defined(FT_CONFIG_OPTION_SUBPIXEL_RENDERING)
+static const int kFilterBorderWidth = 3;
+#else
+static const int kFilterBorderWidth = 0;
+#endif
+
void CopyFreetypeBitmapToLCDMask(const SkGlyph& dest, const FT_Bitmap& source)
{
// |source| has three alpha values per pixel and has an extra column at the
- // left and right edges.
+ // left and right edges (if FT_CONFIG_OPTION_SUBPIXEL_RENDERING).
// ----- <--- a single pixel in the output
// source .oOo.. |.oO|o..
@@ -47,15 +54,15 @@ void CopyFreetypeBitmapToLCDMask(const SkGlyph& dest, const FT_Bitmap& source)
// .oO o..
uint8_t* output = reinterpret_cast<uint8_t*>(dest.fImage);
- const unsigned outputPitch = SkAlign4((source.width / 3) - 2);
+ const unsigned outputPitch = SkAlign4((source.width - 2 * kFilterBorderWidth) / 3);
const uint8_t* input = source.buffer;
// First we calculate the A8 mask.
for (int y = 0; y < source.rows; ++y) {
const uint8_t* inputRow = input;
uint8_t* outputRow = output;
- inputRow += 3; // skip the extra column on the left
- for (int x = 3; x < source.width - 3; x += 3) {
+ inputRow += kFilterBorderWidth; // skip the extra column on the left
+ for (int x = kFilterBorderWidth; x < source.width - kFilterBorderWidth; x += 3) {
const uint8_t averageAlpha = (static_cast<unsigned>(inputRow[0]) + inputRow[1] + inputRow[2] + 1) / 3;
*outputRow++ = averageAlpha;
inputRow += 3;
@@ -74,6 +81,8 @@ void CopyFreetypeBitmapToLCDMask(const SkGlyph& dest, const FT_Bitmap& source)
for (int y = 0; y < source.rows; ++y) {
const uint8_t* inputRow = input;
+ if (!kFilterBorderWidth)
+ *output32++ = SkPackARGB32(0, 0, 0, 0);
for (int x = 0; x < source.width; x += 3) {
const uint8_t alphaRed = isBGR ? inputRow[2] : inputRow[0];
const uint8_t alphaGreen = inputRow[1];
@@ -83,6 +92,8 @@ void CopyFreetypeBitmapToLCDMask(const SkGlyph& dest, const FT_Bitmap& source)
inputRow += 3;
}
+ if (!kFilterBorderWidth)
+ *output32++ = SkPackARGB32(0, 0, 0, 0);
input += source.pitch;
}
@@ -91,7 +102,7 @@ void CopyFreetypeBitmapToLCDMask(const SkGlyph& dest, const FT_Bitmap& source)
void CopyFreetypeBitmapToVerticalLCDMask(const SkGlyph& dest, const FT_Bitmap& source)
{
// |source| has three times as many rows as normal, and an extra triple on the
- // top and bottom.
+ // top and bottom (if FT_CONFIG_OPTION_SUBPIXEL_RENDERING).
// source .oOo.. |.|oOo..
// .OOO.. --> |.|OOO..
@@ -104,8 +115,8 @@ void CopyFreetypeBitmapToVerticalLCDMask(const SkGlyph& dest, const FT_Bitmap& s
const uint8_t* input = source.buffer;
// First we calculate the A8 mask.
- input += 3 * source.pitch; // skip the extra at the beginning
- for (int y = 3; y < source.rows - 3; y += 3) {
+ input += kFilterBorderWidth * source.pitch; // skip the extra at the beginning
+ for (int y = kFilterBorderWidth; y < source.rows - kFilterBorderWidth; y += 3) {
const uint8_t* inputRow = input;
uint8_t* outputRow = output;
for (int x = 0; x < source.width; ++x) {
@@ -125,6 +136,11 @@ void CopyFreetypeBitmapToVerticalLCDMask(const SkGlyph& dest, const FT_Bitmap& s
const int isBGR = SkFontHost::GetSubpixelOrder() == SkFontHost::kBGR_LCDOrder;
input = source.buffer;
+ if (!kFilterBorderWidth) {
+ for (int x = 0; x < source.width; ++x)
+ *output32++ = SkPackARGB32(0, 0, 0, 0);
+ }
+
for (int y = 0; y < source.rows; y += 3) {
const uint8_t* inputRow = input;
for (int x = 0; x < source.width; ++x) {
@@ -138,6 +154,11 @@ void CopyFreetypeBitmapToVerticalLCDMask(const SkGlyph& dest, const FT_Bitmap& s
input += source.pitch * 3;
}
+
+ if (!kFilterBorderWidth) {
+ for (int x = 0; x < source.width; ++x)
+ *output32++ = SkPackARGB32(0, 0, 0, 0);
+ }
}
} // namespace skia_freetype_support