diff options
Diffstat (limited to 'src/core/SkScalerContext.cpp')
-rw-r--r-- | src/core/SkScalerContext.cpp | 66 |
1 files changed, 61 insertions, 5 deletions
diff --git a/src/core/SkScalerContext.cpp b/src/core/SkScalerContext.cpp index 7d66c2a5e6..57a3b3548d 100644 --- a/src/core/SkScalerContext.cpp +++ b/src/core/SkScalerContext.cpp @@ -16,6 +16,7 @@ */ #include "SkScalerContext.h" +#include "SkColorPriv.h" #include "SkDescriptor.h" #include "SkDraw.h" #include "SkFontHost.h" @@ -45,11 +46,18 @@ void SkGlyph::toMask(SkMask* mask) const { } size_t SkGlyph::computeImageSize() const { - size_t size = this->rowBytes() * fHeight; - if (fMaskFormat == SkMask::k3D_Format) { - size *= 3; + const size_t size = this->rowBytes() * fHeight; + + switch (fMaskFormat) { + case SkMask::kHorizontalLCD_Format: + return SkAlign4(size) + sizeof(uint32_t) * ((fWidth + 2) * fHeight); + case SkMask::kVerticalLCD_Format: + return SkAlign4(size) + sizeof(uint32_t) * (fWidth * (fHeight + 2)); + case SkMask::k3D_Format: + return 3 * size; + default: + return size; } - return size; } void SkGlyph::zeroMetrics() { @@ -63,6 +71,48 @@ void SkGlyph::zeroMetrics() { fLsbDelta = 0; } +void SkGlyph::expandA8ToLCD() const { + SkASSERT(fMaskFormat == SkMask::kHorizontalLCD_Format || + fMaskFormat == SkMask::kVerticalLCD_Format); + +#if defined(SK_BUILD_SUBPIXEL) + uint8_t* input = reinterpret_cast<uint8_t*>(fImage); + uint32_t* output = reinterpret_cast<uint32_t*>(input + SkAlign4(rowBytes() * fHeight)); + + if (fMaskFormat == SkMask::kHorizontalLCD_Format) { + for (unsigned y = 0; y < fHeight; ++y) { + const uint8_t* inputRow = input; + *output++ = 0; // make the extra column on the left clear + for (unsigned x = 0; x < fWidth; ++x) { + const uint8_t alpha = *inputRow++; + *output++ = SkPackARGB32(alpha, alpha, alpha, alpha); + } + *output++ = 0; + + input += rowBytes(); + } + } else { + const unsigned outputRowBytes = sizeof(uint32_t) * fWidth; + memset(output, 0, outputRowBytes); + output += fWidth; + + for (unsigned y = 0; y < fHeight; ++y) { + const uint8_t* inputRow = input; + for (unsigned x = 0; x < fWidth; ++x) { + const uint8_t alpha = *inputRow++; + *output++ = SkPackARGB32(alpha, alpha, alpha, alpha); + } + + input += rowBytes(); + } + + memset(output, 0, outputRowBytes); + output += fWidth; + } +#else +#endif +} + /////////////////////////////////////////////////////////////////////////////// #ifdef SK_DEBUG @@ -329,6 +379,9 @@ void SkScalerContext::getImage(const SkGlyph& origGlyph) { this->internalGetPath(*glyph, &fillPath, &devPath, &fillToDevMatrix); + const bool lcdMode = fRec.fMaskFormat == SkMask::kHorizontalLCD_Format || + fRec.fMaskFormat == SkMask::kVerticalLCD_Format; + if (fRasterizer) { SkMask mask; @@ -349,7 +402,7 @@ void SkScalerContext::getImage(const SkGlyph& origGlyph) { SkPaint paint; SkDraw draw; - if (SkMask::kA8_Format == fRec.fMaskFormat) { + if (SkMask::kA8_Format == fRec.fMaskFormat || lcdMode) { config = SkBitmap::kA8_Config; paint.setAntiAlias(true); } else { @@ -372,6 +425,9 @@ void SkScalerContext::getImage(const SkGlyph& origGlyph) { draw.fBounder = NULL; draw.drawPath(devPath, paint); } + + if (lcdMode) + glyph->expandA8ToLCD(); } else { this->getGlyphContext(*glyph)->generateImage(*glyph); } |