aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar caryclark@google.com <caryclark@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2011-06-22 13:19:43 +0000
committerGravatar caryclark@google.com <caryclark@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2011-06-22 13:19:43 +0000
commit1eeaf0ba2381f84ffd889f56303cbe0d1886bb21 (patch)
tree99852310e8d9f0a3f7a9c94f3ff0afb0375b48e4 /src
parent3c898186c9082c535e589807752a0a9dc5d28aa0 (diff)
Add support for 8 bits/component glyphs, to
better match the fonts produced by CoreText on OS/X. M include/config/SkUserConfig.h M include/core/SkMask.h M include/core/SkScalerContext.h M src/core/SkBlitter_ARGB32.cpp M src/core/SkScalerContext.cpp M src/core/SkPaint.cpp M src/gpu/SkGrFontScaler.cpp M src/ports/SkFontHost_mac_coretext.cpp M src/ports/SkFontHost_mac.cpp M gpu/include/GrTypes.h M gpu/src/GrAtlas.cpp git-svn-id: http://skia.googlecode.com/svn/trunk@1672 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src')
-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
6 files changed, 104 insertions, 5 deletions
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);