remove obsolete text codepaths
git-svn-id: http://skia.googlecode.com/svn/trunk@1725 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
parent
67908f2fae
commit
effc5016f0
@ -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',
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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:
|
||||
|
@ -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
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user