diff options
-rw-r--r-- | gpu/include/GrTypes.h | 8 | ||||
-rw-r--r-- | gpu/src/GrAtlas.cpp | 2 | ||||
-rw-r--r-- | include/config/SkUserConfig.h | 11 | ||||
-rw-r--r-- | include/core/SkMask.h | 16 | ||||
-rw-r--r-- | include/core/SkScalerContext.h | 4 | ||||
-rw-r--r-- | src/core/SkBlitter_ARGB32.cpp | 62 | ||||
-rw-r--r-- | src/core/SkPaint.cpp | 8 | ||||
-rw-r--r-- | src/core/SkScalerContext.cpp | 1 | ||||
-rw-r--r-- | src/gpu/SkGrFontScaler.cpp | 2 | ||||
-rwxr-xr-x | src/ports/SkFontHost_mac.cpp | 2 | ||||
-rw-r--r-- | src/ports/SkFontHost_mac_coretext.cpp | 34 |
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); |