check-point for kLCD16_Format mask support
disabled for now in SkPaint.cpp (for further testing) git-svn-id: http://skia.googlecode.com/svn/trunk@917 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
parent
649a862186
commit
f88d6765a5
@ -47,6 +47,7 @@ struct SkMask {
|
|||||||
kHorizontalLCD_Format, //!< 4 bytes/pixel: a/r/g/b
|
kHorizontalLCD_Format, //!< 4 bytes/pixel: a/r/g/b
|
||||||
kVerticalLCD_Format, //!< 4 bytes/pixel: a/r/g/b
|
kVerticalLCD_Format, //!< 4 bytes/pixel: a/r/g/b
|
||||||
kARGB32_Format, //!< SkPMColor
|
kARGB32_Format, //!< SkPMColor
|
||||||
|
kLCD16_Format //!< 565 alpha for r/g/b
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
@ -96,6 +97,19 @@ struct SkMask {
|
|||||||
return fImage + x - fBounds.fLeft + (y - fBounds.fTop) * fRowBytes;
|
return fImage + x - fBounds.fLeft + (y - fBounds.fTop) * fRowBytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the address of the specified 16bit mask. In the debug build,
|
||||||
|
* this asserts that the mask's format is kLCD16_Format, and that (x,y)
|
||||||
|
* are contained in the mask's fBounds.
|
||||||
|
*/
|
||||||
|
uint16_t* getAddrLCD16(int x, int y) const {
|
||||||
|
SkASSERT(kLCD16_Format == fFormat);
|
||||||
|
SkASSERT(fBounds.contains(x, y));
|
||||||
|
SkASSERT(fImage != NULL);
|
||||||
|
uint16_t* row = (uint16_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
|
/** Return an address into the 32-bit plane of an LCD or VerticalLCD mask
|
||||||
for the given position.
|
for the given position.
|
||||||
*/
|
*/
|
||||||
@ -120,7 +134,7 @@ struct SkMask {
|
|||||||
|
|
||||||
static uint8_t* AllocImage(size_t bytes);
|
static uint8_t* AllocImage(size_t bytes);
|
||||||
static void FreeImage(void* image);
|
static void FreeImage(void* image);
|
||||||
|
|
||||||
enum CreateMode {
|
enum CreateMode {
|
||||||
kJustComputeBounds_CreateMode, //!< compute bounds and return
|
kJustComputeBounds_CreateMode, //!< compute bounds and return
|
||||||
kJustRenderImage_CreateMode, //!< render into preallocate mask
|
kJustRenderImage_CreateMode, //!< render into preallocate mask
|
||||||
|
@ -53,18 +53,27 @@ struct SkGlyph {
|
|||||||
fMaskFormat = MASK_FORMAT_UNKNOWN;
|
fMaskFormat = MASK_FORMAT_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned rowBytes() const {
|
/**
|
||||||
unsigned rb = fWidth;
|
* Compute the rowbytes for the specified width and mask-format.
|
||||||
if (SkMask::kBW_Format == fMaskFormat) {
|
*/
|
||||||
|
static unsigned ComputeRowBytes(unsigned width, SkMask::Format format) {
|
||||||
|
unsigned rb = width;
|
||||||
|
if (SkMask::kBW_Format == format) {
|
||||||
rb = (rb + 7) >> 3;
|
rb = (rb + 7) >> 3;
|
||||||
} else if (SkMask::kARGB32_Format == fMaskFormat) {
|
} else if (SkMask::kARGB32_Format == format) {
|
||||||
rb <<= 2;
|
rb <<= 2;
|
||||||
|
} else if (SkMask::kLCD16_Format == format) {
|
||||||
|
rb = SkAlign4(rb << 1);
|
||||||
} else {
|
} else {
|
||||||
rb = SkAlign4(rb);
|
rb = SkAlign4(rb);
|
||||||
}
|
}
|
||||||
return rb;
|
return rb;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned rowBytes() const {
|
||||||
|
return ComputeRowBytes(fWidth, (SkMask::Format)fMaskFormat);
|
||||||
|
}
|
||||||
|
|
||||||
bool isJustAdvance() const {
|
bool isJustAdvance() const {
|
||||||
return MASK_FORMAT_JUST_ADVANCE == fMaskFormat;
|
return MASK_FORMAT_JUST_ADVANCE == fMaskFormat;
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,12 @@
|
|||||||
#include "SkColorPriv.h"
|
#include "SkColorPriv.h"
|
||||||
#include "SkImageDecoder.h"
|
#include "SkImageDecoder.h"
|
||||||
|
|
||||||
|
static void setNamedTypeface(SkPaint* paint, const char name[]) {
|
||||||
|
SkTypeface* face = SkTypeface::CreateFromName(name, SkTypeface::kNormal);
|
||||||
|
paint->setTypeface(face);
|
||||||
|
SkSafeUnref(face);
|
||||||
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
static int newscale(U8CPU a, U8CPU b, int shift) {
|
static int newscale(U8CPU a, U8CPU b, int shift) {
|
||||||
unsigned prod = a * b + (1 << (shift - 1));
|
unsigned prod = a * b + (1 << (shift - 1));
|
||||||
@ -35,7 +41,7 @@ static void test_srcover565(SkCanvas* canvas) {
|
|||||||
bm1.setConfig(SkBitmap::kRGB_565_Config, width, 256); bm1.allocPixels(NULL);
|
bm1.setConfig(SkBitmap::kRGB_565_Config, width, 256); bm1.allocPixels(NULL);
|
||||||
bm2.setConfig(SkBitmap::kRGB_565_Config, width, 256); bm2.allocPixels(NULL);
|
bm2.setConfig(SkBitmap::kRGB_565_Config, width, 256); bm2.allocPixels(NULL);
|
||||||
bm3.setConfig(SkBitmap::kRGB_565_Config, width, 256); bm3.allocPixels(NULL);
|
bm3.setConfig(SkBitmap::kRGB_565_Config, width, 256); bm3.allocPixels(NULL);
|
||||||
|
|
||||||
int rgb = 0x18;
|
int rgb = 0x18;
|
||||||
int r = rgb >> 3;
|
int r = rgb >> 3;
|
||||||
int g = rgb >> 2;
|
int g = rgb >> 2;
|
||||||
@ -44,7 +50,7 @@ static void test_srcover565(SkCanvas* canvas) {
|
|||||||
SkPMColor pm = SkPreMultiplyARGB(alpha, rgb, rgb, rgb);
|
SkPMColor pm = SkPreMultiplyARGB(alpha, rgb, rgb, rgb);
|
||||||
uint16_t newdst = SkSrcOver32To16(pm, dst);
|
uint16_t newdst = SkSrcOver32To16(pm, dst);
|
||||||
sk_memset16(bm1.getAddr16(0, alpha), newdst, bm1.width());
|
sk_memset16(bm1.getAddr16(0, alpha), newdst, bm1.width());
|
||||||
|
|
||||||
int ia = 255 - alpha;
|
int ia = 255 - alpha;
|
||||||
int iscale = SkAlpha255To256(ia);
|
int iscale = SkAlpha255To256(ia);
|
||||||
int dr = (SkGetPackedR32(pm) + (r * iscale >> 5)) >> 3;
|
int dr = (SkGetPackedR32(pm) + (r * iscale >> 5)) >> 3;
|
||||||
@ -54,7 +60,7 @@ static void test_srcover565(SkCanvas* canvas) {
|
|||||||
|
|
||||||
int dr2 = (SkMulDiv255Round(alpha, rgb) + newscale(r, ia, 5)) >> 3;
|
int dr2 = (SkMulDiv255Round(alpha, rgb) + newscale(r, ia, 5)) >> 3;
|
||||||
int dg2 = (SkMulDiv255Round(alpha, rgb) + newscale(g, ia, 6)) >> 2;
|
int dg2 = (SkMulDiv255Round(alpha, rgb) + newscale(g, ia, 6)) >> 2;
|
||||||
|
|
||||||
sk_memset16(bm3.getAddr16(0, alpha), SkPackRGB16(dr2, dg2, dr2), bm3.width());
|
sk_memset16(bm3.getAddr16(0, alpha), SkPackRGB16(dr2, dg2, dr2), bm3.width());
|
||||||
|
|
||||||
// if (mr != dr || mg != dg)
|
// if (mr != dr || mg != dg)
|
||||||
@ -62,13 +68,13 @@ static void test_srcover565(SkCanvas* canvas) {
|
|||||||
// SkDebugf("[%d] macro [%d %d] inline [%d %d] new [%d %d]\n", alpha, mr, mg, dr, dg, dr2, dg2);
|
// SkDebugf("[%d] macro [%d %d] inline [%d %d] new [%d %d]\n", alpha, mr, mg, dr, dg, dr2, dg2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SkScalar dx = SkIntToScalar(width+4);
|
SkScalar dx = SkIntToScalar(width+4);
|
||||||
|
|
||||||
canvas->drawBitmap(bm1, 0, 0, NULL); canvas->translate(dx, 0);
|
canvas->drawBitmap(bm1, 0, 0, NULL); canvas->translate(dx, 0);
|
||||||
canvas->drawBitmap(bm2, 0, 0, NULL); canvas->translate(dx, 0);
|
canvas->drawBitmap(bm2, 0, 0, NULL); canvas->translate(dx, 0);
|
||||||
canvas->drawBitmap(bm3, 0, 0, NULL); canvas->translate(dx, 0);
|
canvas->drawBitmap(bm3, 0, 0, NULL); canvas->translate(dx, 0);
|
||||||
|
|
||||||
SkRect rect = { 0, 0, SkIntToScalar(bm1.width()), SkIntToScalar(bm1.height()) };
|
SkRect rect = { 0, 0, SkIntToScalar(bm1.width()), SkIntToScalar(bm1.height()) };
|
||||||
SkPaint p;
|
SkPaint p;
|
||||||
p.setARGB(0xFF, rgb, rgb, rgb);
|
p.setARGB(0xFF, rgb, rgb, rgb);
|
||||||
@ -76,7 +82,7 @@ static void test_srcover565(SkCanvas* canvas) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void make_bitmaps(int w, int h, SkBitmap* src, SkBitmap* dst) {
|
static void make_bitmaps(int w, int h, SkBitmap* src, SkBitmap* dst) {
|
||||||
src->setConfig(SkBitmap::kARGB_8888_Config, w, h);
|
src->setConfig(SkBitmap::kARGB_8888_Config, w, h);
|
||||||
src->allocPixels();
|
src->allocPixels();
|
||||||
src->eraseColor(0);
|
src->eraseColor(0);
|
||||||
@ -88,10 +94,10 @@ static void make_bitmaps(int w, int h, SkBitmap* src, SkBitmap* dst) {
|
|||||||
SkScalar hh = SkIntToScalar(h);
|
SkScalar hh = SkIntToScalar(h);
|
||||||
|
|
||||||
p.setAntiAlias(true);
|
p.setAntiAlias(true);
|
||||||
p.setColor(0xFFFFCC44);
|
p.setColor(0xFFFFCC44);
|
||||||
r.set(0, 0, ww*3/4, hh*3/4);
|
r.set(0, 0, ww*3/4, hh*3/4);
|
||||||
c.drawOval(r, p);
|
c.drawOval(r, p);
|
||||||
|
|
||||||
dst->setConfig(SkBitmap::kARGB_8888_Config, w, h);
|
dst->setConfig(SkBitmap::kARGB_8888_Config, w, h);
|
||||||
dst->allocPixels();
|
dst->allocPixels();
|
||||||
dst->eraseColor(0);
|
dst->eraseColor(0);
|
||||||
@ -112,26 +118,26 @@ class XfermodesView : public SkView {
|
|||||||
SkScalar x, SkScalar y) {
|
SkScalar x, SkScalar y) {
|
||||||
SkPaint p;
|
SkPaint p;
|
||||||
|
|
||||||
canvas->drawBitmap(fSrcB, x, y, &p);
|
canvas->drawBitmap(fSrcB, x, y, &p);
|
||||||
p.setAlpha(alpha);
|
p.setAlpha(alpha);
|
||||||
p.setXfermode(mode);
|
p.setXfermode(mode);
|
||||||
canvas->drawBitmap(fDstB, x, y, &p);
|
canvas->drawBitmap(fDstB, x, y, &p);
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
const static int W = 64;
|
const static int W = 64;
|
||||||
const static int H = 64;
|
const static int H = 64;
|
||||||
XfermodesView() {
|
XfermodesView() {
|
||||||
const int W = 64;
|
const int W = 64;
|
||||||
const int H = 64;
|
const int H = 64;
|
||||||
|
|
||||||
fBG.setConfig(SkBitmap::kARGB_4444_Config, 2, 2, 4);
|
fBG.setConfig(SkBitmap::kARGB_4444_Config, 2, 2, 4);
|
||||||
fBG.setPixels(gBG);
|
fBG.setPixels(gBG);
|
||||||
fBG.setIsOpaque(true);
|
fBG.setIsOpaque(true);
|
||||||
|
|
||||||
make_bitmaps(W, H, &fSrcB, &fDstB);
|
make_bitmaps(W, H, &fSrcB, &fDstB);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// overrides from SkEventSink
|
// overrides from SkEventSink
|
||||||
virtual bool onQuery(SkEvent* evt) {
|
virtual bool onQuery(SkEvent* evt) {
|
||||||
@ -145,12 +151,12 @@ protected:
|
|||||||
void drawBG(SkCanvas* canvas) {
|
void drawBG(SkCanvas* canvas) {
|
||||||
canvas->drawColor(SK_ColorWHITE);
|
canvas->drawColor(SK_ColorWHITE);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void onDraw(SkCanvas* canvas) {
|
virtual void onDraw(SkCanvas* canvas) {
|
||||||
canvas->translate(SkIntToScalar(10), SkIntToScalar(20));
|
canvas->translate(SkIntToScalar(10), SkIntToScalar(20));
|
||||||
|
|
||||||
this->drawBG(canvas);
|
this->drawBG(canvas);
|
||||||
|
|
||||||
const struct {
|
const struct {
|
||||||
SkXfermode::Mode fMode;
|
SkXfermode::Mode fMode;
|
||||||
const char* fLabel;
|
const char* fLabel;
|
||||||
@ -190,11 +196,14 @@ protected:
|
|||||||
SkMatrix m;
|
SkMatrix m;
|
||||||
m.setScale(SkIntToScalar(6), SkIntToScalar(6));
|
m.setScale(SkIntToScalar(6), SkIntToScalar(6));
|
||||||
s->setLocalMatrix(m);
|
s->setLocalMatrix(m);
|
||||||
|
|
||||||
SkPaint labelP;
|
SkPaint labelP;
|
||||||
labelP.setAntiAlias(true);
|
labelP.setAntiAlias(true);
|
||||||
|
labelP.setLCDRenderText(true);
|
||||||
labelP.setTextAlign(SkPaint::kCenter_Align);
|
labelP.setTextAlign(SkPaint::kCenter_Align);
|
||||||
|
setNamedTypeface(&labelP, "Menlo Regular");
|
||||||
|
// labelP.setTextSize(SkIntToScalar(11));
|
||||||
|
|
||||||
const int W = 5;
|
const int W = 5;
|
||||||
|
|
||||||
SkScalar x0 = 0;
|
SkScalar x0 = 0;
|
||||||
@ -210,7 +219,7 @@ protected:
|
|||||||
p.setStyle(SkPaint::kFill_Style);
|
p.setStyle(SkPaint::kFill_Style);
|
||||||
p.setShader(s);
|
p.setShader(s);
|
||||||
canvas->drawRect(r, p);
|
canvas->drawRect(r, p);
|
||||||
|
|
||||||
canvas->saveLayer(&r, NULL, SkCanvas::kARGB_ClipLayer_SaveFlag);
|
canvas->saveLayer(&r, NULL, SkCanvas::kARGB_ClipLayer_SaveFlag);
|
||||||
// canvas->save();
|
// canvas->save();
|
||||||
draw_mode(canvas, mode, twice ? 0x88 : 0xFF, r.fLeft, r.fTop);
|
draw_mode(canvas, mode, twice ? 0x88 : 0xFF, r.fLeft, r.fTop);
|
||||||
|
@ -38,6 +38,74 @@ extern uint32_t BlendLCDPixelWithBlack(const uint32_t alphaPixel, const uint32_t
|
|||||||
using namespace skia_blitter_support;
|
using namespace skia_blitter_support;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
static int upscale31To256(int value) {
|
||||||
|
SkASSERT((unsigned)value <= 31);
|
||||||
|
// 0..31 -> 0..255
|
||||||
|
value = (value << 3) | (value >> 2);
|
||||||
|
// 0..255 -> 0..256
|
||||||
|
value += (value >> 7);
|
||||||
|
SkASSERT((unsigned)value <= 256);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void blit_lcd16_opaque(SkPMColor dst[], const uint16_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++) {
|
||||||
|
uint16_t mask = src[i];
|
||||||
|
if (0 == mask) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We want all of these in 5bits, hence the shifts in case one of them
|
||||||
|
* (green) is 6bits.
|
||||||
|
*/
|
||||||
|
int maskR = SkGetPackedR16(mask) >> (SK_R16_BITS - 5);
|
||||||
|
int maskG = SkGetPackedG16(mask) >> (SK_G16_BITS - 5);
|
||||||
|
int maskB = SkGetPackedB16(mask) >> (SK_B16_BITS - 5);
|
||||||
|
|
||||||
|
// Now upscale them to 0..256, so we can use SkAlphaBlend
|
||||||
|
maskR = upscale31To256(maskR);
|
||||||
|
maskG = upscale31To256(maskG);
|
||||||
|
maskB = upscale31To256(maskB);
|
||||||
|
|
||||||
|
int maskA = SkMax32(SkMax32(maskR, maskG), maskB);
|
||||||
|
|
||||||
|
SkPMColor d = dst[i];
|
||||||
|
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;
|
||||||
|
int y = clip.fTop;
|
||||||
|
int width = clip.width();
|
||||||
|
int height = clip.height();
|
||||||
|
|
||||||
|
SkPMColor* dstRow = device.getAddr32(x, y);
|
||||||
|
const uint16_t* srcRow = mask.getAddrLCD16(x, y);
|
||||||
|
|
||||||
|
do {
|
||||||
|
blit_lcd16_opaque(dstRow, srcRow, srcColor, width);
|
||||||
|
dstRow = (SkPMColor*)((char*)dstRow + device.rowBytes());
|
||||||
|
srcRow = (const uint16_t*)((const char*)srcRow + mask.fRowBytes);
|
||||||
|
} while (--height != 0);
|
||||||
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
static void SkARGB32_Blit32(const SkBitmap& device, const SkMask& mask,
|
static void SkARGB32_Blit32(const SkBitmap& device, const SkMask& mask,
|
||||||
@ -189,6 +257,9 @@ void SkARGB32_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) {
|
|||||||
} else if (SkMask::kARGB32_Format == mask.fFormat) {
|
} else if (SkMask::kARGB32_Format == mask.fFormat) {
|
||||||
SkARGB32_Blit32(fDevice, mask, clip, fPMColor);
|
SkARGB32_Blit32(fDevice, mask, clip, fPMColor);
|
||||||
return;
|
return;
|
||||||
|
} else if (SkMask::kLCD16_Format == mask.fFormat) {
|
||||||
|
blitmask_lcd16(fDevice, mask, clip, fPMColor);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int x = clip.fLeft;
|
int x = clip.fLeft;
|
||||||
@ -210,6 +281,9 @@ void SkARGB32_Opaque_Blitter::blitMask(const SkMask& mask,
|
|||||||
} else if (SkMask::kARGB32_Format == mask.fFormat) {
|
} else if (SkMask::kARGB32_Format == mask.fFormat) {
|
||||||
SkARGB32_Blit32(fDevice, mask, clip, fPMColor);
|
SkARGB32_Blit32(fDevice, mask, clip, fPMColor);
|
||||||
return;
|
return;
|
||||||
|
} else if (SkMask::kLCD16_Format == mask.fFormat) {
|
||||||
|
blitmask_lcd16(fDevice, mask, clip, fPMColor);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int x = clip.fLeft;
|
int x = clip.fLeft;
|
||||||
@ -319,6 +393,8 @@ void SkARGB32_Black_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) {
|
|||||||
SkARGB32_BlitBW(fDevice, mask, clip, black);
|
SkARGB32_BlitBW(fDevice, mask, clip, black);
|
||||||
} else if (SkMask::kARGB32_Format == mask.fFormat) {
|
} else if (SkMask::kARGB32_Format == mask.fFormat) {
|
||||||
SkARGB32_Blit32(fDevice, mask, clip, fPMColor);
|
SkARGB32_Blit32(fDevice, mask, clip, fPMColor);
|
||||||
|
} else if (SkMask::kLCD16_Format == mask.fFormat) {
|
||||||
|
blitmask_lcd16(fDevice, mask, clip, fPMColor);
|
||||||
} else {
|
} else {
|
||||||
#if defined(SK_SUPPORT_LCDTEXT)
|
#if defined(SK_SUPPORT_LCDTEXT)
|
||||||
const bool lcdMode = mask.fFormat == SkMask::kHorizontalLCD_Format;
|
const bool lcdMode = mask.fFormat == SkMask::kHorizontalLCD_Format;
|
||||||
|
@ -1104,6 +1104,22 @@ static void add_flattenable(SkDescriptor* desc, uint32_t tag,
|
|||||||
buffer->flatten(desc->addEntry(tag, buffer->size(), NULL));
|
buffer->flatten(desc->addEntry(tag, buffer->size(), NULL));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool canSupportLCD16(const SkPaint& paint) {
|
||||||
|
#if 0
|
||||||
|
return !paint.getShader() &&
|
||||||
|
!paint.getXfermode() && // unless its srcover
|
||||||
|
!paint.getMaskFilter() &&
|
||||||
|
!paint.getRasterizer() &&
|
||||||
|
!paint.getColorFilter() &&
|
||||||
|
!paint.getPathEffect() &&
|
||||||
|
!paint.isFakeBoldText() &&
|
||||||
|
paint.getStyle() == SkPaint::kFill_Style;
|
||||||
|
#else
|
||||||
|
// disable for now, while we test more
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
static SkMask::Format computeMaskFormat(const SkPaint& paint) {
|
static SkMask::Format computeMaskFormat(const SkPaint& paint) {
|
||||||
uint32_t flags = paint.getFlags();
|
uint32_t flags = paint.getFlags();
|
||||||
|
|
||||||
@ -1111,6 +1127,12 @@ static SkMask::Format computeMaskFormat(const SkPaint& paint) {
|
|||||||
if (!(flags & SkPaint::kAntiAlias_Flag))
|
if (!(flags & SkPaint::kAntiAlias_Flag))
|
||||||
return SkMask::kBW_Format;
|
return SkMask::kBW_Format;
|
||||||
|
|
||||||
|
if (flags & SkPaint::kLCDRenderText_Flag) {
|
||||||
|
if (canSupportLCD16(paint)) {
|
||||||
|
return SkMask::kLCD16_Format;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(SK_SUPPORT_LCDTEXT)
|
#if defined(SK_SUPPORT_LCDTEXT)
|
||||||
if (flags & SkPaint::kLCDRenderText_Flag) {
|
if (flags & SkPaint::kLCDRenderText_Flag) {
|
||||||
return SkFontHost::GetSubpixelOrientation() == SkFontHost::kHorizontal_LCDOrientation ?
|
return SkFontHost::GetSubpixelOrientation() == SkFontHost::kHorizontal_LCDOrientation ?
|
||||||
|
@ -497,6 +497,7 @@ void SkScalerContext::getImage(const SkGlyph& origGlyph) {
|
|||||||
|
|
||||||
if (NULL == fMaskFilter &&
|
if (NULL == fMaskFilter &&
|
||||||
fRec.fMaskFormat != SkMask::kBW_Format &&
|
fRec.fMaskFormat != SkMask::kBW_Format &&
|
||||||
|
fRec.fMaskFormat != SkMask::kLCD16_Format &&
|
||||||
(fRec.fFlags & (kGammaForBlack_Flag | kGammaForWhite_Flag)) != 0)
|
(fRec.fFlags & (kGammaForBlack_Flag | kGammaForWhite_Flag)) != 0)
|
||||||
{
|
{
|
||||||
const uint8_t* table = (fRec.fFlags & kGammaForBlack_Flag) ? gBlackGammaTable : gWhiteGammaTable;
|
const uint8_t* table = (fRec.fFlags & kGammaForBlack_Flag) ? gBlackGammaTable : gWhiteGammaTable;
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
/*
|
/*
|
||||||
** Copyright 2006, The Android Open Source Project
|
** Copyright 2006, The Android Open Source Project
|
||||||
**
|
**
|
||||||
** Licensed under the Apache License, Version 2.0 (the "License");
|
** Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
** you may not use this file except in compliance with the License.
|
** you may not use this file except in compliance with the License.
|
||||||
** You may obtain a copy of the License at
|
** You may obtain a copy of the License at
|
||||||
**
|
**
|
||||||
** http://www.apache.org/licenses/LICENSE-2.0
|
** http://www.apache.org/licenses/LICENSE-2.0
|
||||||
**
|
**
|
||||||
** Unless required by applicable law or agreed to in writing, software
|
** Unless required by applicable law or agreed to in writing, software
|
||||||
** distributed under the License is distributed on an "AS IS" BASIS,
|
** distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
** See the License for the specific language governing permissions and
|
** See the License for the specific language governing permissions and
|
||||||
** limitations under the License.
|
** limitations under the License.
|
||||||
*/
|
*/
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@ -21,7 +21,7 @@
|
|||||||
#include "SkString.h"
|
#include "SkString.h"
|
||||||
#include "SkPaint.h"
|
#include "SkPaint.h"
|
||||||
#include "SkFloatingPoint.h"
|
#include "SkFloatingPoint.h"
|
||||||
|
#include "SkUtils.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -88,13 +88,13 @@ public:
|
|||||||
|
|
||||||
// Is a font ID valid?
|
// Is a font ID valid?
|
||||||
bool IsValid(SkFontID fontID);
|
bool IsValid(SkFontID fontID);
|
||||||
|
|
||||||
|
|
||||||
// Get a font
|
// Get a font
|
||||||
CTFontRef GetFont(SkFontID fontID);
|
CTFontRef GetFont(SkFontID fontID);
|
||||||
SkNativeFontInfo GetFontInfo(const SkString &theName, SkTypeface::Style theStyle);
|
SkNativeFontInfo GetFontInfo(const SkString &theName, SkTypeface::Style theStyle);
|
||||||
|
|
||||||
|
|
||||||
// Create a font
|
// Create a font
|
||||||
SkNativeFontInfo CreateFont(const SkString &theName, SkTypeface::Style theStyle);
|
SkNativeFontInfo CreateFont(const SkString &theName, SkTypeface::Style theStyle);
|
||||||
|
|
||||||
@ -132,7 +132,7 @@ SkNativeFontCache::SkNativeFontCache(void)
|
|||||||
fontInfo.style = SkTypeface::kNormal;
|
fontInfo.style = SkTypeface::kNormal;
|
||||||
fontInfo.fontID = kSkInvalidFontID;
|
fontInfo.fontID = kSkInvalidFontID;
|
||||||
fontInfo.fontRef = NULL;
|
fontInfo.fontRef = NULL;
|
||||||
|
|
||||||
mFonts.push_back(fontInfo);
|
mFonts.push_back(fontInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -190,7 +190,7 @@ SkNativeFontInfo SkNativeFontCache::GetFontInfo(const SkString &theName, SkTypef
|
|||||||
if (theIter->name == theName && theIter->style == theStyle)
|
if (theIter->name == theName && theIter->style == theStyle)
|
||||||
return(*theIter);
|
return(*theIter);
|
||||||
}
|
}
|
||||||
|
|
||||||
return(fontInfo);
|
return(fontInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -328,7 +328,8 @@ private:
|
|||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CGColorSpaceRef mColorSpace;
|
CGColorSpaceRef mColorSpaceGray;
|
||||||
|
CGColorSpaceRef mColorSpaceRGB;
|
||||||
CGAffineTransform mTransform;
|
CGAffineTransform mTransform;
|
||||||
|
|
||||||
CTFontRef mFont;
|
CTFontRef mFont;
|
||||||
@ -352,7 +353,11 @@ SkScalerContext_Mac::SkScalerContext_Mac(const SkDescriptor* desc)
|
|||||||
|
|
||||||
|
|
||||||
// Initialise ourselves
|
// Initialise ourselves
|
||||||
mColorSpace = CGColorSpaceCreateDeviceGray();
|
// mColorSpaceRGB = CGColorSpaceCreateDeviceRGB();
|
||||||
|
// mColorSpaceRGB = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
|
||||||
|
mColorSpaceRGB = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGBLinear);
|
||||||
|
mColorSpaceGray = CGColorSpaceCreateDeviceGray();
|
||||||
|
|
||||||
const float inv = 1.0f / FONT_CANONICAL_POINTSIZE;
|
const float inv = 1.0f / FONT_CANONICAL_POINTSIZE;
|
||||||
mTransform = CGAffineTransformMake(SkScalarToFloat(skMatrix[SkMatrix::kMScaleX]) * inv,
|
mTransform = CGAffineTransformMake(SkScalarToFloat(skMatrix[SkMatrix::kMScaleX]) * inv,
|
||||||
-SkScalarToFloat(skMatrix[SkMatrix::kMSkewY]) * inv,
|
-SkScalarToFloat(skMatrix[SkMatrix::kMSkewY]) * inv,
|
||||||
@ -369,7 +374,8 @@ SkScalerContext_Mac::~SkScalerContext_Mac(void)
|
|||||||
{
|
{
|
||||||
|
|
||||||
// Clean up
|
// Clean up
|
||||||
CFSafeRelease(mColorSpace);
|
CFSafeRelease(mColorSpaceGray);
|
||||||
|
CFSafeRelease(mColorSpaceRGB);
|
||||||
CFSafeRelease(mFont);
|
CFSafeRelease(mFont);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -437,8 +443,27 @@ void SkScalerContext_Mac::generateMetrics(SkGlyph* glyph)
|
|||||||
glyph->fLeft = sk_float_round2int(CGRectGetMinX(theBounds));
|
glyph->fLeft = sk_float_round2int(CGRectGetMinX(theBounds));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SkScalerContext_Mac::generateImage(const SkGlyph& glyph)
|
#include "SkColorPriv.h"
|
||||||
{ CGContextRef cgContext;
|
|
||||||
|
static inline uint16_t rgb_to_lcd16(uint32_t rgb) {
|
||||||
|
int r = (rgb >> 16) & 0xFF;
|
||||||
|
int g = (rgb >> 8) & 0xFF;
|
||||||
|
int b = (rgb >> 0) & 0xFF;
|
||||||
|
|
||||||
|
// invert, since we draw black-on-white, but we want the original
|
||||||
|
// src mask values.
|
||||||
|
r = 255 - r;
|
||||||
|
g = 255 - g;
|
||||||
|
b = 255 - b;
|
||||||
|
|
||||||
|
return SkPackRGB16(SkR32ToR16(r), SkG32ToG16(g), SkB32ToB16(b));
|
||||||
|
}
|
||||||
|
|
||||||
|
#define BITMAP_INFO_RGB (kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Host)
|
||||||
|
#define BITMAP_INFO_GRAY (kCGImageAlphaNone)
|
||||||
|
|
||||||
|
void SkScalerContext_Mac::generateImage(const SkGlyph& glyph) {
|
||||||
|
CGContextRef cgContext;
|
||||||
CGGlyph cgGlyph;
|
CGGlyph cgGlyph;
|
||||||
CGFontRef cgFont;
|
CGFontRef cgFont;
|
||||||
|
|
||||||
@ -447,17 +472,61 @@ void SkScalerContext_Mac::generateImage(const SkGlyph& glyph)
|
|||||||
|
|
||||||
cgGlyph = (CGGlyph) glyph.getGlyphID(fBaseGlyphCount);
|
cgGlyph = (CGGlyph) glyph.getGlyphID(fBaseGlyphCount);
|
||||||
cgFont = CTFontCopyGraphicsFont(mFont, NULL);
|
cgFont = CTFontCopyGraphicsFont(mFont, NULL);
|
||||||
cgContext = CGBitmapContextCreate( glyph.fImage, glyph.fWidth, glyph.fHeight, 8,
|
|
||||||
glyph.rowBytes(), mColorSpace, kCGImageAlphaNone);
|
SkAutoSMalloc<1024> storage;
|
||||||
|
|
||||||
|
CGColorSpaceRef colorspace = mColorSpaceGray;
|
||||||
|
uint32_t info = BITMAP_INFO_GRAY;
|
||||||
|
void* image = glyph.fImage;
|
||||||
|
size_t rowBytes = glyph.rowBytes();
|
||||||
|
float grayColor = 1; // white
|
||||||
|
|
||||||
|
/* For LCD16, we first create a temp offscreen cg-context in 32bit,
|
||||||
|
* erase to white, and then draw a black glyph into it. Then we can
|
||||||
|
* 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) {
|
||||||
|
colorspace = mColorSpaceRGB;
|
||||||
|
info = BITMAP_INFO_RGB;
|
||||||
|
// need tmp storage for 32bit RGB offscreen
|
||||||
|
rowBytes = glyph.fWidth << 2;
|
||||||
|
size_t size = glyph.fHeight * rowBytes;
|
||||||
|
image = storage.realloc(size);
|
||||||
|
// we draw black-on-white (and invert in rgb_to_lcd16)
|
||||||
|
sk_memset32((uint32_t*)image, 0xFFFFFFFF, size >> 2);
|
||||||
|
grayColor = 0; // black
|
||||||
|
}
|
||||||
|
|
||||||
|
cgContext = CGBitmapContextCreate(image, glyph.fWidth, glyph.fHeight, 8,
|
||||||
|
rowBytes, colorspace, info);
|
||||||
|
|
||||||
// Draw the glyph
|
// Draw the glyph
|
||||||
if (cgFont != NULL && cgContext != NULL) {
|
if (cgFont != NULL && cgContext != NULL) {
|
||||||
CGContextSetGrayFillColor( cgContext, 1.0, 1.0);
|
CGContextSetAllowsFontSubpixelQuantization(cgContext, true);
|
||||||
|
CGContextSetShouldSubpixelQuantizeFonts(cgContext, true);
|
||||||
|
|
||||||
|
CGContextSetGrayFillColor( cgContext, grayColor, 1.0);
|
||||||
CGContextSetTextDrawingMode(cgContext, kCGTextFill);
|
CGContextSetTextDrawingMode(cgContext, kCGTextFill);
|
||||||
CGContextSetFont( cgContext, cgFont);
|
CGContextSetFont( cgContext, cgFont);
|
||||||
CGContextSetFontSize( cgContext, FONT_CANONICAL_POINTSIZE);
|
CGContextSetFontSize( cgContext, FONT_CANONICAL_POINTSIZE);
|
||||||
CGContextSetTextMatrix( cgContext, mTransform);
|
CGContextSetTextMatrix( cgContext, mTransform);
|
||||||
CGContextShowGlyphsAtPoint( cgContext, -glyph.fLeft, glyph.fTop + glyph.fHeight, &cgGlyph, 1);
|
CGContextShowGlyphsAtPoint( cgContext, -glyph.fLeft, glyph.fTop + glyph.fHeight, &cgGlyph, 1);
|
||||||
|
|
||||||
|
if (SkMask::kLCD16_Format == glyph.fMaskFormat) {
|
||||||
|
// downsample from rgba to rgb565
|
||||||
|
int width = glyph.fWidth;
|
||||||
|
const uint32_t* src = (const uint32_t*)image;
|
||||||
|
uint16_t* dst = (uint16_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_lcd16(src[i]);
|
||||||
|
}
|
||||||
|
src = (const uint32_t*)((const char*)src + rowBytes);
|
||||||
|
dst = (uint16_t*)((char*)dst + dstRB);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clean up
|
// Clean up
|
||||||
@ -539,7 +608,7 @@ void SkScalerContext_Mac::CTPathElement(void *info, const CGPathElement *element
|
|||||||
case kCGPathElementCloseSubpath:
|
case kCGPathElementCloseSubpath:
|
||||||
skPath->close();
|
skPath->close();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
SkASSERT("Unknown path element!");
|
SkASSERT("Unknown path element!");
|
||||||
break;
|
break;
|
||||||
@ -783,7 +852,7 @@ size_t SkFontHost::GetTableSize(SkFontID fontID, SkFontTableTag tag)
|
|||||||
theSize = CFDataGetLength(cfData);
|
theSize = CFDataGetLength(cfData);
|
||||||
CFSafeRelease(cfData);
|
CFSafeRelease(cfData);
|
||||||
}
|
}
|
||||||
|
|
||||||
return(theSize);
|
return(theSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user