aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--gpu/include/GrTypes.h8
-rw-r--r--gpu/src/GrAtlas.cpp2
-rw-r--r--include/config/SkUserConfig.h11
-rw-r--r--include/core/SkMask.h16
-rw-r--r--include/core/SkScalerContext.h4
-rw-r--r--src/core/SkBlitter_ARGB32.cpp62
-rw-r--r--src/core/SkPaint.cpp8
-rw-r--r--src/core/SkScalerContext.cpp1
-rw-r--r--src/gpu/SkGrFontScaler.cpp2
-rwxr-xr-xsrc/ports/SkFontHost_mac.cpp2
-rw-r--r--src/ports/SkFontHost_mac_coretext.cpp34
11 files changed, 140 insertions, 10 deletions
diff --git a/gpu/include/GrTypes.h b/gpu/include/GrTypes.h
index 76e01b00a7..2bf4b09055 100644
--- a/gpu/include/GrTypes.h
+++ b/gpu/include/GrTypes.h
@@ -247,10 +247,12 @@ enum GrBlendCoeff {
* Important that these are 0-based.
*/
enum GrMaskFormat {
- kA8_GrMaskFormat, //!< 1-byte per pixel
- kA565_GrMaskFormat //!< 2-bytes per pixel
+ kA8_GrMaskFormat, //!< 1-byte per pixel
+ kA565_GrMaskFormat, //!< 2-bytes per pixel
+ kA888_GrMaskFormat, //!< 4-bytes per pixel
+
+ kCount_GrMaskFormats //!< used to allocate arrays sized for mask formats
};
-#define kCount_GrMaskFormats 2
/**
* Return the number of bytes-per-pixel for the specified mask format.
diff --git a/gpu/src/GrAtlas.cpp b/gpu/src/GrAtlas.cpp
index e577beb629..480a3073f9 100644
--- a/gpu/src/GrAtlas.cpp
+++ b/gpu/src/GrAtlas.cpp
@@ -148,6 +148,8 @@ static GrPixelConfig maskformat2pixelconfig(GrMaskFormat format) {
return kAlpha_8_GrPixelConfig;
case kA565_GrMaskFormat:
return kRGB_565_GrPixelConfig;
+ case kA888_GrMaskFormat:
+ return kRGBA_8888_GrPixelConfig;
default:
GrAssert(!"unknown maskformat");
}
diff --git a/include/config/SkUserConfig.h b/include/config/SkUserConfig.h
index c56d8cfa78..80ecdb6433 100644
--- a/include/config/SkUserConfig.h
+++ b/include/config/SkUserConfig.h
@@ -117,6 +117,17 @@
*/
//#define SK_SUPPORT_LCDTEXT
+/* Define this to pack glyphs using 8 bits per component instead of 5-6-5.
+ This will double the size of the font cache, but will produce fonts with
+ gray levels closer to the designer's intent.
+*/
+//#define SK_SUPPORT_888_TEXT
+
+/* If defined, use CoreText instead of ATSUI on OS X.
+*/
+//#define SK_USE_MAC_CORE_TEXT
+
+
/* If zlib is available and you want to support the flate compression
algorithm (used in PDF generation), define SK_ZLIB_INCLUDE to be the
include path.
diff --git a/include/core/SkMask.h b/include/core/SkMask.h
index f437622388..ac495fcda3 100644
--- a/include/core/SkMask.h
+++ b/include/core/SkMask.h
@@ -47,7 +47,8 @@ struct SkMask {
kHorizontalLCD_Format, //!< 4 bytes/pixel: a/r/g/b
kVerticalLCD_Format, //!< 4 bytes/pixel: a/r/g/b
kARGB32_Format, //!< SkPMColor
- kLCD16_Format //!< 565 alpha for r/g/b
+ kLCD16_Format, //!< 565 alpha for r/g/b
+ kLCD32_Format //!< 888 alpha for r/g/b
};
enum {
@@ -110,6 +111,19 @@ struct SkMask {
return row + (x - fBounds.fLeft);
}
+ /**
+ * Return the address of the specified 32bit mask. In the debug build,
+ * this asserts that the mask's format is kLCD32_Format, and that (x,y)
+ * are contained in the mask's fBounds.
+ */
+ uint32_t* getAddrLCD32(int x, int y) const {
+ SkASSERT(kLCD32_Format == fFormat);
+ SkASSERT(fBounds.contains(x, y));
+ SkASSERT(fImage != NULL);
+ uint32_t* row = (uint32_t*)(fImage + (y - fBounds.fTop) * fRowBytes);
+ return row + (x - fBounds.fLeft);
+ }
+
/** Return an address into the 32-bit plane of an LCD or VerticalLCD mask
for the given position.
*/
diff --git a/include/core/SkScalerContext.h b/include/core/SkScalerContext.h
index cbbbdf0357..d7b5eece12 100644
--- a/include/core/SkScalerContext.h
+++ b/include/core/SkScalerContext.h
@@ -60,7 +60,9 @@ struct SkGlyph {
unsigned rb = width;
if (SkMask::kBW_Format == format) {
rb = (rb + 7) >> 3;
- } else if (SkMask::kARGB32_Format == format) {
+ } else if (SkMask::kARGB32_Format == format ||
+ SkMask::kLCD32_Format == format)
+ {
rb <<= 2;
} else if (SkMask::kLCD16_Format == format) {
rb = SkAlign4(rb << 1);
diff --git a/src/core/SkBlitter_ARGB32.cpp b/src/core/SkBlitter_ARGB32.cpp
index dec355a1e4..1901937080 100644
--- a/src/core/SkBlitter_ARGB32.cpp
+++ b/src/core/SkBlitter_ARGB32.cpp
@@ -92,6 +92,43 @@ static void blit_lcd16_opaque(SkPMColor dst[], const uint16_t src[],
}
}
+static void blit_lcd32_opaque(SkPMColor dst[], const uint32_t src[],
+ SkPMColor color, int width) {
+ int srcR = SkGetPackedR32(color);
+ int srcG = SkGetPackedG32(color);
+ int srcB = SkGetPackedB32(color);
+
+ for (int i = 0; i < width; i++) {
+ uint32_t mask = src[i];
+ if (0 == mask) {
+ continue;
+ }
+
+ SkPMColor d = dst[i];
+
+ int maskR = SkGetPackedR32(mask);
+ int maskG = SkGetPackedG32(mask);
+ int maskB = SkGetPackedB32(mask);
+
+ // Now upscale them to 0..256, so we can use SkAlphaBlend
+ maskR = SkAlpha255To256(maskR);
+ maskG = SkAlpha255To256(maskG);
+ maskB = SkAlpha255To256(maskB);
+
+ int maskA = SkMax32(SkMax32(maskR, maskG), maskB);
+
+ int dstA = SkGetPackedA32(d);
+ int dstR = SkGetPackedR32(d);
+ int dstG = SkGetPackedG32(d);
+ int dstB = SkGetPackedB32(d);
+
+ dst[i] = SkPackARGB32(SkAlphaBlend(0xFF, dstA, maskA),
+ SkAlphaBlend(srcR, dstR, maskR),
+ SkAlphaBlend(srcG, dstG, maskG),
+ SkAlphaBlend(srcB, dstB, maskB));
+ }
+}
+
static void blitmask_lcd16(const SkBitmap& device, const SkMask& mask,
const SkIRect& clip, SkPMColor srcColor) {
int x = clip.fLeft;
@@ -109,6 +146,23 @@ static void blitmask_lcd16(const SkBitmap& device, const SkMask& mask,
} while (--height != 0);
}
+static void blitmask_lcd32(const SkBitmap& device, const SkMask& mask,
+ const SkIRect& clip, SkPMColor srcColor) {
+ int x = clip.fLeft;
+ int y = clip.fTop;
+ int width = clip.width();
+ int height = clip.height();
+
+ SkPMColor* dstRow = device.getAddr32(x, y);
+ const uint32_t* srcRow = mask.getAddrLCD32(x, y);
+
+ do {
+ blit_lcd32_opaque(dstRow, srcRow, srcColor, width);
+ dstRow = (SkPMColor*)((char*)dstRow + device.rowBytes());
+ srcRow = (const uint32_t*)((const char*)srcRow + mask.fRowBytes);
+ } while (--height != 0);
+}
+
//////////////////////////////////////////////////////////////////////////////////////
static void SkARGB32_Blit32(const SkBitmap& device, const SkMask& mask,
@@ -263,6 +317,9 @@ void SkARGB32_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) {
} else if (SkMask::kLCD16_Format == mask.fFormat) {
blitmask_lcd16(fDevice, mask, clip, fPMColor);
return;
+ } else if (SkMask::kLCD32_Format == mask.fFormat) {
+ blitmask_lcd32(fDevice, mask, clip, fPMColor);
+ return;
}
int x = clip.fLeft;
@@ -287,6 +344,9 @@ void SkARGB32_Opaque_Blitter::blitMask(const SkMask& mask,
} else if (SkMask::kLCD16_Format == mask.fFormat) {
blitmask_lcd16(fDevice, mask, clip, fPMColor);
return;
+ } else if (SkMask::kLCD32_Format == mask.fFormat) {
+ blitmask_lcd32(fDevice, mask, clip, fPMColor);
+ return;
}
int x = clip.fLeft;
@@ -395,6 +455,8 @@ void SkARGB32_Black_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) {
SkARGB32_Blit32(fDevice, mask, clip, fPMColor);
} else if (SkMask::kLCD16_Format == mask.fFormat) {
blitmask_lcd16(fDevice, mask, clip, fPMColor);
+ } else if (SkMask::kLCD32_Format == mask.fFormat) {
+ blitmask_lcd32(fDevice, mask, clip, fPMColor);
} else {
#if defined(SK_SUPPORT_LCDTEXT)
const bool lcdMode = mask.fFormat == SkMask::kHorizontalLCD_Format;
diff --git a/src/core/SkPaint.cpp b/src/core/SkPaint.cpp
index f9abe3f420..0608320f40 100644
--- a/src/core/SkPaint.cpp
+++ b/src/core/SkPaint.cpp
@@ -1198,7 +1198,11 @@ static SkMask::Format computeMaskFormat(const SkPaint& paint) {
}
#else
if (flags & SkPaint::kLCDRenderText_Flag) {
+#if !defined(SK_SUPPORT_888_TEXT)
return SkMask::kLCD16_Format;
+#else
+ return SkMask::kLCD32_Format;
+#endif
}
#endif
@@ -1294,7 +1298,9 @@ void SkScalerContext::MakeRec(const SkPaint& paint,
rec->fMaskFormat = SkToU8(computeMaskFormat(paint));
- if (SkMask::kLCD16_Format == rec->fMaskFormat) {
+ if (SkMask::kLCD16_Format == rec->fMaskFormat ||
+ SkMask::kLCD32_Format == rec->fMaskFormat)
+ {
SkFontHost::LCDOrder order = SkFontHost::GetSubpixelOrder();
SkFontHost::LCDOrientation orient = SkFontHost::GetSubpixelOrientation();
if (SkFontHost::kNONE_LCDOrder == order) {
diff --git a/src/core/SkScalerContext.cpp b/src/core/SkScalerContext.cpp
index 05439f1f55..2109531c0b 100644
--- a/src/core/SkScalerContext.cpp
+++ b/src/core/SkScalerContext.cpp
@@ -497,6 +497,7 @@ void SkScalerContext::getImage(const SkGlyph& origGlyph) {
if (NULL == fMaskFilter &&
fRec.fMaskFormat != SkMask::kBW_Format &&
fRec.fMaskFormat != SkMask::kLCD16_Format &&
+ fRec.fMaskFormat != SkMask::kLCD32_Format &&
(fRec.fFlags & (kGammaForBlack_Flag | kGammaForWhite_Flag)) != 0)
{
const uint8_t* table = (fRec.fFlags & kGammaForBlack_Flag) ? gBlackGammaTable : gWhiteGammaTable;
diff --git a/src/gpu/SkGrFontScaler.cpp b/src/gpu/SkGrFontScaler.cpp
index eb260fb826..e82b8a0451 100644
--- a/src/gpu/SkGrFontScaler.cpp
+++ b/src/gpu/SkGrFontScaler.cpp
@@ -92,6 +92,8 @@ GrMaskFormat SkGrFontScaler::getMaskFormat() {
return kA8_GrMaskFormat;
case SkMask::kLCD16_Format:
return kA565_GrMaskFormat;
+ case SkMask::kLCD32_Format:
+ return kA888_GrMaskFormat;
default:
GrAssert(!"unsupported SkMask::Format");
return kA8_GrMaskFormat;
diff --git a/src/ports/SkFontHost_mac.cpp b/src/ports/SkFontHost_mac.cpp
index 6adaf329b0..100eea52be 100755
--- a/src/ports/SkFontHost_mac.cpp
+++ b/src/ports/SkFontHost_mac.cpp
@@ -30,7 +30,7 @@
** builds unless SK_USE_CORETEXT is defined.
*/
#ifndef SK_USE_CORETEXT
- #if TARGET_RT_64_BIT
+ #if TARGET_RT_64_BIT || defined(SK_USE_MAC_CORE_TEXT)
#define SK_USE_CORETEXT 1
#else
#define SK_USE_CORETEXT 0
diff --git a/src/ports/SkFontHost_mac_coretext.cpp b/src/ports/SkFontHost_mac_coretext.cpp
index 30a2d67381..fd8e2845a9 100644
--- a/src/ports/SkFontHost_mac_coretext.cpp
+++ b/src/ports/SkFontHost_mac_coretext.cpp
@@ -447,6 +447,16 @@ static inline uint16_t rgb_to_lcd16(uint32_t rgb) {
return SkPackRGB16(r32_to_16(r), g32_to_16(g), b32_to_16(b));
}
+static inline uint32_t rgb_to_lcd32(uint32_t rgb) {
+ // invert, since we draw black-on-white, but we want the original
+ // src mask values.
+ rgb = ~rgb;
+ int r = (rgb >> 16) & 0xFF;
+ int g = (rgb >> 8) & 0xFF;
+ int b = (rgb >> 0) & 0xFF;
+ return SkPackARGB32(0xFF, r, g, b);
+}
+
#define BITMAP_INFO_RGB (kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Host)
#define BITMAP_INFO_GRAY (kCGImageAlphaNone)
@@ -475,7 +485,9 @@ void SkScalerContext_Mac::generateImage(const SkGlyph& glyph) {
* extract the r,g,b values, invert-them, and now we have the original
* src mask components, which we pack into our 16bit mask.
*/
- if (SkMask::kLCD16_Format == glyph.fMaskFormat) {
+ if (SkMask::kLCD16_Format == glyph.fMaskFormat ||
+ SkMask::kLCD32_Format == glyph.fMaskFormat)
+ {
colorspace = mColorSpaceRGB;
info = BITMAP_INFO_RGB;
// need tmp storage for 32bit RGB offscreen
@@ -523,6 +535,18 @@ void SkScalerContext_Mac::generateImage(const SkGlyph& glyph) {
src = (const uint32_t*)((const char*)src + rowBytes);
dst = (uint16_t*)((char*)dst + dstRB);
}
+ } else if (SkMask::kLCD32_Format == glyph.fMaskFormat) {
+ int width = glyph.fWidth;
+ const uint32_t* src = (const uint32_t*)image;
+ uint32_t* dst = (uint32_t*)glyph.fImage;
+ size_t dstRB = glyph.rowBytes();
+ for (int y = 0; y < glyph.fHeight; y++) {
+ for (int i = 0; i < width; i++) {
+ dst[i] = rgb_to_lcd32(src[i]);
+ }
+ src = (const uint32_t*)((const char*)src + rowBytes);
+ dst = (uint32_t*)((char*)dst + dstRB);
+ }
} else if (SkMask::kBW_Format == glyph.fMaskFormat) {
// downsample from A8 to A1
const uint8_t* src = (const uint8_t*)image;
@@ -698,11 +722,15 @@ SkAdvancedTypefaceMetrics* SkFontHost::GetAdvancedTypefaceMetrics(
CTFontRef ctFont = GetFontRefFromFontID(fontID);
SkAdvancedTypefaceMetrics* info = new SkAdvancedTypefaceMetrics;
CFStringRef fontName = CTFontCopyPostScriptName(ctFont);
- int length = CFStringGetMaximumSizeForEncoding(CFStringGetLength(fontName),
- kCFStringEncodingUTF8);
+ // Reserve enough room for the worst-case string,
+ // plus 1 byte for the trailing null.
+ int length = CFStringGetMaximumSizeForEncoding(CFStringGetLength(
+ fontName), kCFStringEncodingUTF8) + 1;
info->fFontName.resize(length);
CFStringGetCString(fontName, info->fFontName.writable_str(), length,
kCFStringEncodingUTF8);
+ // Resize to the actual UTF-8 length used, stripping the null character.
+ info->fFontName.resize(strlen(info->fFontName.c_str()));
info->fMultiMaster = false;
CFIndex glyphCount = CTFontGetGlyphCount(ctFont);
info->fLastGlyphID = SkToU16(glyphCount - 1);