remove obsolete text codepaths

git-svn-id: http://skia.googlecode.com/svn/trunk@1725 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
reed@google.com 2011-06-27 16:44:46 +00:00
parent 67908f2fae
commit effc5016f0
13 changed files with 51 additions and 569 deletions

View File

@ -260,10 +260,8 @@
'sources': [
'../include/core/SkMMapStream.h',
'../src/core/SkMMapStream.cpp',
'../src/core/SkBlitter_ARGB32_Subpixel.cpp',
'../src/ports/SkThread_pthread.cpp',
'../src/ports/SkTime_Unix.cpp',
'../src/ports/SkFontHost_FreeType_Subpixel.cpp',
'../src/ports/SkFontHost_FreeType.cpp',
'../src/ports/SkFontHost_gamma_none.cpp',
'../src/ports/SkFontHost_linux.cpp',

View File

@ -112,14 +112,10 @@
*/
//#define SkDebugf(...) MyFunction(__VA_ARGS__)
/* To enable additional blitters (and fontscaler code) to support separate
alpha channels for R G B channels, define SK_SUPPORT_LCDTEXT
*/
//#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.
/**
* Used only for lcdtext, define this to pack glyphs using 8 bits per component
* instead of 5-6-5. This can increase fidelity with the native font scaler,
* but doubles the RAM used by the font cache.
*/
//#define SK_SUPPORT_888_TEXT

View File

@ -28,31 +28,13 @@ struct SkMask {
kBW_Format, //!< 1bit per pixel mask (e.g. monochrome)
kA8_Format, //!< 8bits per pixel mask (e.g. antialiasing)
k3D_Format, //!< 3 8bit per pixl planes: alpha, mul, add
/* The LCD formats look like this in memory:
First, there's an A8 plane which contains the average alpha value for
each pixel. Because of this, the LCD formats can be passed directly
to functions which expect an A8 and everything will just work.
After that in memory, there's a bitmap of 32-bit values which have
been RGB order corrected for the current screen (based on the
settings in SkFontHost at the time of renderering). The alpha value
for each pixel is the maximum of the three alpha values.
kHorizontalLCD_Format has an extra column of pixels on the left and right
edges. kVerticalLCD_Format has an extra row at the top and bottom.
*/
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
kLCD32_Format //!< 888 alpha for r/g/b
};
enum {
kCountMaskFormats = kVerticalLCD_Format + 1
kCountMaskFormats = kLCD32_Format + 1
};
uint8_t* fImage;
@ -124,29 +106,6 @@ struct SkMask {
return row + (x - fBounds.fLeft);
}
/** Return an address into the 32-bit plane of an LCD or VerticalLCD mask
for the given position.
*/
const uint32_t* getAddrLCD(int x, int y) const {
SkASSERT(fFormat == kHorizontalLCD_Format || fFormat == kVerticalLCD_Format);
SkASSERT(fImage != NULL);
return reinterpret_cast<const uint32_t*>(fImage + SkAlign4(fRowBytes * fBounds.height())) +
x - fBounds.fLeft + (y - fBounds.fTop) * rowWordsLCD();
}
/** Return the number of 32-bit words in a row of the 32-bit plane of an
LCD or VerticalLCD mask.
*/
unsigned rowWordsLCD() const {
SkASSERT(fFormat == kHorizontalLCD_Format || fFormat == kVerticalLCD_Format);
if (fFormat == kHorizontalLCD_Format) {
return fBounds.width() + 2;
} else {
return fBounds.width();
}
}
static uint8_t* AllocImage(size_t bytes);
static void FreeImage(void* image);
@ -155,10 +114,6 @@ struct SkMask {
kJustRenderImage_CreateMode, //!< render into preallocate mask
kComputeBoundsAndRenderImage_CreateMode //!< compute bounds, alloc image and render into it
};
static bool FormatIsLCD(Format fm) {
return kHorizontalLCD_Format == fm || kVerticalLCD_Format == fm;
}
};
#endif

View File

@ -159,11 +159,6 @@ struct SkGlyph {
}
void toMask(SkMask* mask) const;
/** Given a glyph which is has a mask format of LCD or VerticalLCD, take
the A8 plane in fImage and produce a valid LCD plane from it.
*/
void expandA8ToLCD() const;
};
class SkScalerContext {
@ -181,7 +176,8 @@ public:
kEmbolden_Flag = 0x80,
kSubpixelPositioning_Flag = 0x100,
kAutohinting_Flag = 0x200,
// these should only ever be set if fMaskFormat is LCD
// these should only ever be set if fMaskFormat is LCD16 or LCD32
kLCD_Vertical_Flag = 0x400, // else Horizontal
kLCD_BGROrder_Flag = 0x800, // else RGB order
};
@ -219,10 +215,6 @@ public:
SkMask::Format getFormat() const {
return static_cast<SkMask::Format>(fMaskFormat);
}
bool isLCD() const {
return SkMask::FormatIsLCD(this->getFormat());
}
};
SkScalerContext(const SkDescriptor* desc);

View File

@ -21,23 +21,6 @@
#include "SkUtils.h"
#include "SkXfermode.h"
#if defined(SK_SUPPORT_LCDTEXT)
namespace skia_blitter_support {
// subpixel helper functions from SkBlitter_ARGB32_Subpixel.cpp
uint32_t* adjustForSubpixelClip(const SkMask& mask,
const SkIRect& clip, const SkBitmap& device,
int* widthAdjustment, int* heightAdjustment,
const uint32_t** alpha32);
extern uint32_t BlendLCDPixelWithColor(const uint32_t alphaPixel, const uint32_t originalPixel,
const uint32_t sourcePixel);
extern uint32_t BlendLCDPixelWithOpaqueColor(const uint32_t alphaPixel, const uint32_t originalPixel,
const uint32_t sourcePixel);
extern uint32_t BlendLCDPixelWithBlack(const uint32_t alphaPixel, const uint32_t originalPixel);
}
using namespace skia_blitter_support;
#endif
///////////////////////////////////////////////////////////////////////////////
static inline int upscale31To32(int value) {
@ -354,38 +337,6 @@ void SkARGB32_Opaque_Blitter::blitMask(const SkMask& mask,
int width = clip.width();
int height = clip.height();
#if defined(SK_SUPPORT_LCDTEXT)
const bool lcdMode = mask.fFormat == SkMask::kHorizontalLCD_Format;
const bool verticalLCDMode = mask.fFormat == SkMask::kVerticalLCD_Format;
// In LCD mode the masks have either an extra couple of rows or columns on the edges.
if (lcdMode || verticalLCDMode) {
int widthAdjustment, heightAdjustment;
const uint32_t* alpha32;
uint32_t* device = adjustForSubpixelClip(mask, clip, fDevice, &widthAdjustment, &heightAdjustment, &alpha32);
width += widthAdjustment;
height += heightAdjustment;
unsigned devRB = fDevice.rowBytes() - (width << 2);
unsigned alphaExtraRowWords = mask.rowWordsLCD() - width;
SkPMColor srcColor = fPMColor;
do {
unsigned w = width;
do {
const uint32_t alphaPixel = *alpha32++;
const uint32_t originalPixel = *device;
*device++ = BlendLCDPixelWithOpaqueColor(alphaPixel, originalPixel, srcColor);
} while (--w != 0);
device = (uint32_t*)((char*)device + devRB);
alpha32 += alphaExtraRowWords;
} while (--height != 0);
return;
}
#endif
fBlitMaskProc(fDevice.getAddr32(x, y), fDevice.rowBytes(),
SkBitmap::kARGB_8888_Config,
mask.getAddr(x, y), mask.fRowBytes, fColor, width, height);
@ -458,45 +409,12 @@ void SkARGB32_Black_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) {
} 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;
const bool verticalLCDMode = mask.fFormat == SkMask::kVerticalLCD_Format;
#endif
// In LCD mode the masks have either an extra couple of rows or columns on the edges.
unsigned width = clip.width();
unsigned height = clip.height();
unsigned width = clip.width();
unsigned height = clip.height();
SkASSERT((int)height > 0);
SkASSERT((int)width > 0);
#if defined(SK_SUPPORT_LCDTEXT)
if (lcdMode || verticalLCDMode) {
int widthAdjustment, heightAdjustment;
const uint32_t* alpha32;
uint32_t* device = adjustForSubpixelClip(mask, clip, fDevice, &widthAdjustment, &heightAdjustment, &alpha32);
width += widthAdjustment;
height += heightAdjustment;
unsigned deviceRB = fDevice.rowBytes() - (width << 2);
unsigned alphaExtraRowWords = mask.rowWordsLCD() - width;
do {
unsigned w = width;
do {
const uint32_t alphaPixel = *alpha32++;
const uint32_t originalPixel = *device;
*device++ = BlendLCDPixelWithBlack(alphaPixel, originalPixel);
} while (--w != 0);
device = (uint32_t*)((char*)device + deviceRB);
alpha32 += alphaExtraRowWords;
} while (--height != 0);
return;
}
#endif
uint32_t* device = fDevice.getAddr32(clip.fLeft, clip.fTop);
unsigned maskRB = mask.fRowBytes - width;
unsigned deviceRB = fDevice.rowBytes() - (width << 2);

View File

@ -1,144 +0,0 @@
/* libs/graphics/sgl/SkBlitter_ARGB32_Subpixel.cpp
**
** Copyright 2009, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
/* LCD blend functions:
These functions take an alpha pixel of the following form:
red, green, blue -> an alpha value for the given colour component.
alpha -> the max of the red, green and blue alpha values.
These alpha pixels result from subpixel renderering. The R/G/B values have
already been corrected for RGB/BGR element ordering.
The alpha pixel is blended with an original pixel and a source colour,
resulting in a new pixel value.
*/
#include "SkBitmap.h"
#include "SkColorPriv.h"
#include "SkMask.h"
#include "SkRect.h"
namespace skia_blitter_support {
/** Given a clip region which describes the desired location of a glyph and a
bitmap to which an LCD glyph is to be blitted, return a pointer to the
SkBitmap's pixels and output width and height adjusts for the glyph as well
as a pointer into the glyph.
Recall that LCD glyphs have extra rows (vertical mode) or columns
(horizontal mode) at the edges as a result of low-pass filtering. If we
wanted to put a glyph on the hard-left edge of bitmap, we would have to know
to start one pixel into the glyph, as well as to only add 1 to the recorded
glyph width etc. This function encapsulates that behaviour.
@param mask The glyph to be blitted.
@param clip The clip region describing the desired location of the glyph.
@param device The SkBitmap target for the blit.
@param widthAdjustment (output) a number to add to the glyph's nominal width.
@param heightAdjustment (output) a number to add to the glyph's nominal width.
@param alpha32 (output) a pointer into the 32-bit subpixel alpha data for the glyph
*/
uint32_t* adjustForSubpixelClip(const SkMask& mask,
const SkIRect& clip, const SkBitmap& device,
int* widthAdjustment, int* heightAdjustment,
const uint32_t** alpha32) {
const bool lcdMode = mask.fFormat == SkMask::kHorizontalLCD_Format;
const bool verticalLCDMode = mask.fFormat == SkMask::kVerticalLCD_Format;
const int leftOffset = clip.fLeft > 0 ? lcdMode : 0;
const int topOffset = clip.fTop > 0 ? verticalLCDMode : 0;
const int rightOffset = lcdMode && clip.fRight < device.width();
const int bottomOffset = verticalLCDMode && clip.fBottom < device.height();
uint32_t* device32 = device.getAddr32(clip.fLeft - leftOffset, clip.fTop - topOffset);
*alpha32 = mask.getAddrLCD(clip.fLeft + (lcdMode && !leftOffset),
clip.fTop + (verticalLCDMode && !topOffset));
*widthAdjustment = leftOffset + rightOffset;
*heightAdjustment = topOffset + bottomOffset;
return device32;
}
uint32_t BlendLCDPixelWithColor(const uint32_t alphaPixel, const uint32_t originalPixel,
const uint32_t sourcePixel) {
unsigned alphaRed = SkAlpha255To256(SkGetPackedR32(alphaPixel));
unsigned alphaGreen = SkAlpha255To256(SkGetPackedG32(alphaPixel));
unsigned alphaBlue = SkAlpha255To256(SkGetPackedB32(alphaPixel));
unsigned sourceRed = SkGetPackedR32(sourcePixel);
unsigned sourceGreen = SkGetPackedG32(sourcePixel);
unsigned sourceBlue = SkGetPackedB32(sourcePixel);
unsigned sourceAlpha = SkAlpha255To256(SkGetPackedA32(sourcePixel));
alphaRed = (alphaRed * sourceAlpha) >> 8;
alphaGreen = (alphaGreen * sourceAlpha) >> 8;
alphaBlue = (alphaBlue * sourceAlpha) >> 8;
unsigned alphaAlpha = SkMax32(SkMax32(alphaRed, alphaBlue), alphaGreen);
unsigned originalRed = SkGetPackedR32(originalPixel);
unsigned originalGreen = SkGetPackedG32(originalPixel);
unsigned originalBlue = SkGetPackedB32(originalPixel);
unsigned originalAlpha = SkGetPackedA32(originalPixel);
return SkPackARGB32(SkMin32(255u, alphaAlpha + originalAlpha),
((sourceRed * alphaRed) >> 8) + ((originalRed * (256 - alphaRed)) >> 8),
((sourceGreen * alphaGreen) >> 8) + ((originalGreen * (256 - alphaGreen)) >> 8),
((sourceBlue * alphaBlue) >> 8) + ((originalBlue * (256 - alphaBlue)) >> 8));
}
uint32_t BlendLCDPixelWithOpaqueColor(const uint32_t alphaPixel, const uint32_t originalPixel,
const uint32_t sourcePixel) {
unsigned alphaRed = SkAlpha255To256(SkGetPackedR32(alphaPixel));
unsigned alphaGreen = SkAlpha255To256(SkGetPackedG32(alphaPixel));
unsigned alphaBlue = SkAlpha255To256(SkGetPackedB32(alphaPixel));
unsigned alphaAlpha = SkGetPackedA32(alphaPixel);
unsigned sourceRed = SkGetPackedR32(sourcePixel);
unsigned sourceGreen = SkGetPackedG32(sourcePixel);
unsigned sourceBlue = SkGetPackedB32(sourcePixel);
unsigned originalRed = SkGetPackedR32(originalPixel);
unsigned originalGreen = SkGetPackedG32(originalPixel);
unsigned originalBlue = SkGetPackedB32(originalPixel);
unsigned originalAlpha = SkGetPackedA32(originalPixel);
return SkPackARGB32(SkMin32(255u, alphaAlpha + originalAlpha),
((sourceRed * alphaRed) >> 8) + ((originalRed * (256 - alphaRed)) >> 8),
((sourceGreen * alphaGreen) >> 8) + ((originalGreen * (256 - alphaGreen)) >> 8),
((sourceBlue * alphaBlue) >> 8) + ((originalBlue * (256 - alphaBlue)) >> 8));
}
uint32_t BlendLCDPixelWithBlack(const uint32_t alphaPixel, const uint32_t originalPixel) {
unsigned alphaRed = SkAlpha255To256(SkGetPackedR32(alphaPixel));
unsigned alphaGreen = SkAlpha255To256(SkGetPackedG32(alphaPixel));
unsigned alphaBlue = SkAlpha255To256(SkGetPackedB32(alphaPixel));
unsigned alphaAlpha = SkGetPackedA32(alphaPixel);
unsigned originalRed = SkGetPackedR32(originalPixel);
unsigned originalGreen = SkGetPackedG32(originalPixel);
unsigned originalBlue = SkGetPackedB32(originalPixel);
unsigned originalAlpha = SkGetPackedA32(originalPixel);
return SkPackARGB32(SkMin32(255u, alphaAlpha + originalAlpha),
(originalRed * (256 - alphaRed)) >> 8,
(originalGreen * (256 - alphaGreen)) >> 8,
(originalBlue * (256 - alphaBlue)) >> 8);
}
} // namespace skia_blitter_support

View File

@ -1191,12 +1191,6 @@ static SkMask::Format computeMaskFormat(const SkPaint& paint) {
return SkMask::kBW_Format;
}
#if defined(SK_SUPPORT_LCDTEXT)
if (flags & SkPaint::kLCDRenderText_Flag) {
return SkFontHost::GetSubpixelOrientation() == SkFontHost::kHorizontal_LCDOrientation ?
SkMask::kHorizontalLCD_Format : SkMask::kVerticalLCD_Format;
}
#else
if (flags & SkPaint::kLCDRenderText_Flag) {
#if !defined(SK_SUPPORT_888_TEXT)
return SkMask::kLCD16_Format;
@ -1204,7 +1198,6 @@ static SkMask::Format computeMaskFormat(const SkPaint& paint) {
return SkMask::kLCD32_Format;
#endif
}
#endif
return SkMask::kA8_Format;
}

View File

@ -45,10 +45,6 @@ size_t SkGlyph::computeImageSize() const {
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:
@ -67,48 +63,6 @@ void SkGlyph::zeroMetrics() {
fLsbDelta = 0;
}
void SkGlyph::expandA8ToLCD() const {
SkASSERT(fMaskFormat == SkMask::kHorizontalLCD_Format ||
fMaskFormat == SkMask::kVerticalLCD_Format);
#if defined(SK_SUPPORT_LCDTEXT)
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
@ -403,9 +357,6 @@ 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;
@ -426,7 +377,7 @@ void SkScalerContext::getImage(const SkGlyph& origGlyph) {
SkPaint paint;
SkDraw draw;
if (SkMask::kA8_Format == fRec.fMaskFormat || lcdMode) {
if (SkMask::kA8_Format == fRec.fMaskFormat) {
config = SkBitmap::kA8_Config;
paint.setAntiAlias(true);
} else {
@ -449,10 +400,6 @@ void SkScalerContext::getImage(const SkGlyph& origGlyph) {
draw.fBounder = NULL;
draw.drawPath(devPath, paint);
}
if (lcdMode) {
glyph->expandA8ToLCD();
}
} else {
this->getGlyphContext(*glyph)->generateImage(*glyph);
}

View File

@ -80,6 +80,16 @@ using namespace skia_advanced_typeface_metrics_utils;
#define SK_FREETYPE_LCD_LERP 96
#endif
static bool isLCD(const SkScalerContext::Rec& rec) {
switch (rec.fMaskFormat) {
case SkMask::kLCD16_Format:
case SkMask::kLCD32_Format:
return true;
default:
return false;
}
}
//////////////////////////////////////////////////////////////////////////
struct SkFaceRec;
@ -588,14 +598,14 @@ void SkFontHost::FilterRec(SkScalerContext::Rec* rec) {
FT_Done_FreeType(gFTLibrary);
}
if (!gLCDSupport && (rec->isLCD() || SkMask::kLCD16_Format == rec->fMaskFormat)) {
if (!gLCDSupport && isLCD(*rec)) {
// If the runtime Freetype library doesn't support LCD mode, we disable
// it here.
rec->fMaskFormat = SkMask::kA8_Format;
}
SkPaint::Hinting h = rec->getHinting();
if (SkPaint::kFull_Hinting == h && !rec->isLCD()) {
if (SkPaint::kFull_Hinting == h && !isLCD(*rec)) {
// collapse full->normal hinting if we're not doing LCD
h = SkPaint::kNormal_Hinting;
} else if ((rec->fFlags & SkScalerContext::kSubpixelPositioning_Flag) &&
@ -689,8 +699,9 @@ SkScalerContext_FreeType::SkScalerContext_FreeType(const SkDescriptor* desc)
if (SkMask::kBW_Format == fRec.fMaskFormat) {
// See http://code.google.com/p/chromium/issues/detail?id=43252#c24
loadFlags = FT_LOAD_TARGET_MONO;
if (fRec.getHinting() == SkPaint::kNo_Hinting)
if (fRec.getHinting() == SkPaint::kNo_Hinting) {
loadFlags = FT_LOAD_NO_HINTING;
}
} else {
switch (fRec.getHinting()) {
case SkPaint::kNo_Hinting:
@ -711,11 +722,12 @@ SkScalerContext_FreeType::SkScalerContext_FreeType(const SkDescriptor* desc)
break;
}
loadFlags = FT_LOAD_TARGET_NORMAL;
if (SkMask::kHorizontalLCD_Format == fRec.fMaskFormat ||
SkMask::kLCD16_Format == fRec.fMaskFormat) {
loadFlags = FT_LOAD_TARGET_LCD;
} else if (SkMask::kVerticalLCD_Format == fRec.fMaskFormat) {
loadFlags = FT_LOAD_TARGET_LCD_V;
if (isLCD(fRec)) {
if (fRec.fFlags & SkScalerContext::kLCD_Vertical_Flag) {
loadFlags = FT_LOAD_TARGET_LCD_V;
} else {
loadFlags = FT_LOAD_TARGET_LCD;
}
}
break;
default:
@ -724,8 +736,9 @@ SkScalerContext_FreeType::SkScalerContext_FreeType(const SkDescriptor* desc)
}
}
if ((fRec.fFlags & SkScalerContext::kEmbeddedBitmapText_Flag) == 0)
if ((fRec.fFlags & SkScalerContext::kEmbeddedBitmapText_Flag) == 0) {
loadFlags |= FT_LOAD_NO_BITMAP;
}
// Always using FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH to get correct
// advances, as fontconfig and cairo do.
@ -847,10 +860,6 @@ SkUnichar SkScalerContext_FreeType::generateGlyphToChar(uint16_t glyph) {
static FT_Pixel_Mode compute_pixel_mode(SkMask::Format format) {
switch (format) {
case SkMask::kHorizontalLCD_Format:
case SkMask::kVerticalLCD_Format:
SkASSERT(!"An LCD format should never be passed here");
return FT_PIXEL_MODE_GRAY;
case SkMask::kBW_Format:
return FT_PIXEL_MODE_MONO;
case SkMask::kA8_Format:
@ -978,16 +987,6 @@ void SkScalerContext_FreeType::generateMetrics(SkGlyph* glyph) {
#endif
}
#if defined(SK_SUPPORT_LCDTEXT)
namespace skia_freetype_support {
// extern functions from SkFontHost_FreeType_Subpixel
extern void CopyFreetypeBitmapToLCDMask(const SkGlyph& dest, const FT_Bitmap& source);
extern void CopyFreetypeBitmapToVerticalLCDMask(const SkGlyph& dest, const FT_Bitmap& source);
}
using namespace skia_freetype_support;
#endif
static int lerp(int start, int end) {
SkASSERT((unsigned)SK_FREETYPE_LCD_LERP <= 256);
return start + ((end - start) * (SK_FREETYPE_LCD_LERP) >> 8);
@ -1015,7 +1014,8 @@ static int bittst(const uint8_t data[], int bitOffset) {
return lowBit & 1;
}
static void copyFT2LCD16(const SkGlyph& glyph, const FT_Bitmap& bitmap) {
static void copyFT2LCD16(const SkGlyph& glyph, const FT_Bitmap& bitmap,
int lcdIsBGR) {
SkASSERT(glyph.fHeight == bitmap.rows);
uint16_t* dst = reinterpret_cast<uint16_t*>(glyph.fImage);
const size_t dstRB = glyph.rowBytes();
@ -1046,9 +1046,16 @@ static void copyFT2LCD16(const SkGlyph& glyph, const FT_Bitmap& bitmap) {
src += 3;
for (int y = 0; y < glyph.fHeight; y++) {
const uint8_t* triple = src;
for (int x = 0; x < width; x++) {
dst[x] = packTriple(triple[0], triple[1], triple[2]);
triple += 3;
if (lcdIsBGR) {
for (int x = 0; x < width; x++) {
dst[x] = packTriple(triple[2], triple[1], triple[0]);
triple += 3;
}
} else {
for (int x = 0; x < width; x++) {
dst[x] = packTriple(triple[0], triple[1], triple[2]);
triple += 3;
}
}
src += bitmap.pitch;
dst = (uint16_t*)((char*)dst + dstRB);
@ -1075,9 +1082,6 @@ void SkScalerContext_FreeType::generateImage(const SkGlyph& glyph) {
return;
}
const bool lcdRenderMode = fRec.fMaskFormat == SkMask::kHorizontalLCD_Format ||
fRec.fMaskFormat == SkMask::kVerticalLCD_Format;
switch ( fFace->glyph->format ) {
case FT_GLYPH_FORMAT_OUTLINE: {
FT_Outline* outline = &fFace->glyph->outline;
@ -1107,26 +1111,10 @@ void SkScalerContext_FreeType::generateImage(const SkGlyph& glyph) {
FT_Outline_Translate(outline, dx - ((bbox.xMin + dx) & ~63),
dy - ((bbox.yMin + dy) & ~63));
#if defined(SK_SUPPORT_LCDTEXT)
if (lcdRenderMode) {
// FT_Outline_Get_Bitmap cannot render LCD glyphs. In this case
// we have to call FT_Render_Glyph and memcpy the image out.
const bool isVertical = fRec.fMaskFormat == SkMask::kVerticalLCD_Format;
FT_Render_Mode mode = isVertical ? FT_RENDER_MODE_LCD_V : FT_RENDER_MODE_LCD;
FT_Render_Glyph(fFace->glyph, mode);
if (isVertical)
CopyFreetypeBitmapToVerticalLCDMask(glyph, fFace->glyph->bitmap);
else
CopyFreetypeBitmapToLCDMask(glyph, fFace->glyph->bitmap);
break;
}
#endif
if (SkMask::kLCD16_Format == glyph.fMaskFormat) {
FT_Render_Glyph(fFace->glyph, FT_RENDER_MODE_LCD);
copyFT2LCD16(glyph, fFace->glyph->bitmap);
copyFT2LCD16(glyph, fFace->glyph->bitmap,
fRec.fFlags & SkScalerContext::kLCD_BGROrder_Flag);
} else {
target.width = glyph.fWidth;
target.rows = glyph.fHeight;
@ -1169,9 +1157,7 @@ void SkScalerContext_FreeType::generateImage(const SkGlyph& glyph) {
dst += dstRowBytes;
}
} else if (fFace->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_MONO &&
(glyph.fMaskFormat == SkMask::kA8_Format ||
glyph.fMaskFormat == SkMask::kHorizontalLCD_Format ||
glyph.fMaskFormat == SkMask::kVerticalLCD_Format)) {
glyph.fMaskFormat == SkMask::kA8_Format) {
for (int y = 0; y < fFace->glyph->bitmap.rows; ++y) {
uint8_t byte = 0;
int bits = 0;
@ -1193,14 +1179,11 @@ void SkScalerContext_FreeType::generateImage(const SkGlyph& glyph) {
dst += glyph.rowBytes();
}
} else if (SkMask::kLCD16_Format == glyph.fMaskFormat) {
copyFT2LCD16(glyph, fFace->glyph->bitmap);
copyFT2LCD16(glyph, fFace->glyph->bitmap,
fRec.fFlags & SkScalerContext::kLCD_BGROrder_Flag);
} else {
SkASSERT(!"unknown glyph bitmap transform needed");
}
if (lcdRenderMode)
glyph.expandA8ToLCD();
} break;
default:

View File

@ -1,143 +0,0 @@
/* libs/graphics/ports/SkFontHost_FreeType_Subpixel.cpp
**
** Copyright 2009, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
/* This file contains functions for converting Freetype's subpixel output
formats into the format used by SkMask for subpixel masks. See the comments
in SkMask.h for details on the format.
*/
#include "SkColorPriv.h"
#include "SkFontHost.h"
#include "SkMask.h"
#include "SkScalerContext.h"
#include <ft2build.h>
#include FT_FREETYPE_H
#if 0
// Also include the files by name for build tools which require this.
#include <freetype/freetype.h>
#endif
namespace skia_freetype_support {
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.
// ----- <--- a single pixel in the output
// source .oOo.. |.oO|o..
// .OOO.. -----
// .oOo.. --> .OO O..
// .oO o..
uint8_t* output = reinterpret_cast<uint8_t*>(dest.fImage);
const unsigned outputPitch = SkAlign4((source.width / 3) - 2);
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) {
const uint8_t averageAlpha = (static_cast<unsigned>(inputRow[0]) + inputRow[1] + inputRow[2] + 1) / 3;
*outputRow++ = averageAlpha;
inputRow += 3;
}
input += source.pitch;
output += outputPitch;
}
// Align the 32-bit plane on a word boundary
uint32_t* output32 = (uint32_t*) SkAlign4((uintptr_t) output);
// Now we build the 32-bit alpha mask and RGB order correct.
const int isBGR = SkFontHost::GetSubpixelOrder() == SkFontHost::kBGR_LCDOrder;
input = source.buffer;
for (int y = 0; y < source.rows; ++y) {
const uint8_t* inputRow = input;
for (int x = 0; x < source.width; x += 3) {
const uint8_t alphaRed = isBGR ? inputRow[2] : inputRow[0];
const uint8_t alphaGreen = inputRow[1];
const uint8_t alphaBlue = isBGR ? inputRow[0] : inputRow[2];
const uint8_t maxAlpha = SkMax32(alphaRed, SkMax32(alphaGreen, alphaBlue));
*output32++ = SkPackARGB32(maxAlpha, alphaRed, alphaGreen, alphaBlue);
inputRow += 3;
}
input += source.pitch;
}
}
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.
// source .oOo.. |.|oOo..
// .OOO.. --> |.|OOO..
// .oOo.. |.|oOo..
// ^
// |-------- A single pixel in the output
uint8_t* output = reinterpret_cast<uint8_t*>(dest.fImage);
const unsigned outputPitch = dest.rowBytes();
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) {
const uint8_t* inputRow = input;
uint8_t* outputRow = output;
for (int x = 0; x < source.width; ++x) {
const uint8_t averageAlpha = (static_cast<unsigned>(*inputRow) + inputRow[source.pitch] + inputRow[source.pitch * 2] + 1) / 3;
*outputRow++ = averageAlpha;
inputRow++;
}
input += source.pitch * 3;
output += outputPitch;
}
// Align the 32-bit plane on a word boundary
uint32_t* output32 = (uint32_t*) SkAlign4((uintptr_t) output);
// Now we build the 32-bit alpha mask and RGB order correct.
const int isBGR = SkFontHost::GetSubpixelOrder() == SkFontHost::kBGR_LCDOrder;
input = source.buffer;
for (int y = 0; y < source.rows; y += 3) {
const uint8_t* inputRow = input;
for (int x = 0; x < source.width; ++x) {
const uint8_t alphaRed = isBGR ? inputRow[source.pitch * 2] : inputRow[0];
const uint8_t alphaGreen = inputRow[source.pitch];
const uint8_t alphaBlue = isBGR ? inputRow[0] : inputRow[2 * source.pitch];
const uint8_t maxAlpha = SkMax32(alphaRed, SkMax32(alphaGreen, alphaBlue));
*output32++ = SkPackARGB32(maxAlpha, alphaRed, alphaGreen, alphaBlue);
inputRow++;
}
input += source.pitch * 3;
}
}
} // namespace skia_freetype_support

View File

@ -118,7 +118,8 @@ void SkFontHost::FilterRec(SkScalerContext::Rec* rec) {
rec->setHinting(h);
// we don't support LCD text
if (SkMask::FormatIsLCD((SkMask::Format)rec->fMaskFormat)) {
if (SkMask::kLCD16_Format == rec->fMaskFormat ||
SkMask::kLCD32_Format == rec->fMaskFormat) {
rec->fMaskFormat = SkMask::kA8_Format;
}
}

View File

@ -947,11 +947,6 @@ void SkFontHost::FilterRec(SkScalerContext::Rec* rec) {
h = SkPaint::kNormal_Hinting;
}
rec->setHinting(h);
// we don't support LCD text
if (SkMask::FormatIsLCD((SkMask::Format)rec->fMaskFormat)) {
rec->fMaskFormat = SkMask::kA8_Format;
}
}
///////////////////////////////////////////////////////////////////////////

View File

@ -969,15 +969,6 @@ SkTypeface* SkFontHost::CreateTypefaceFromFile(const char path[]) {
void SkFontHost::FilterRec(SkScalerContext::Rec* rec) {
// We don't control the hinting nor ClearType settings here
rec->setHinting(SkPaint::kNormal_Hinting);
// we do support LCD16
if (SkMask::kLCD16_Format == rec->fMaskFormat) {
return;
}
if (SkMask::FormatIsLCD((SkMask::Format)rec->fMaskFormat)) {
rec->fMaskFormat = SkMask::kA8_Format;
}
}
#endif // WIN32