support lcd16 in text atlas (sans shader support)

git-svn-id: http://skia.googlecode.com/svn/trunk@939 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
reed@google.com 2011-03-15 15:40:16 +00:00
parent b7e9aee1ac
commit 98539c607b
10 changed files with 128 additions and 49 deletions

View File

@ -28,10 +28,11 @@ class GrAtlasMgr;
class GrAtlas {
public:
GrAtlas(GrAtlasMgr*, int plotX, int plotY);
GrAtlas(GrAtlasMgr*, int plotX, int plotY, GrMaskFormat);
int getPlotX() const { return fPlot.fX; }
int getPlotY() const { return fPlot.fY; }
GrMaskFormat getMaskFormat() const { return fMaskFormat; }
GrTexture* texture() const { return fTexture; }
@ -56,6 +57,7 @@ private:
GrRectanizer* fRects;
GrAtlasMgr* fAtlasMgr;
GrIPoint16 fPlot;
GrMaskFormat fMaskFormat;
friend class GrAtlasMgr;
};
@ -68,7 +70,7 @@ public:
~GrAtlasMgr();
GrAtlas* addToAtlas(GrAtlas*, int width, int height, const void*,
GrIPoint16*);
GrMaskFormat, GrIPoint16*);
GrTexture* getTexture() const { return fTexture; }

View File

@ -33,6 +33,7 @@ class GrPath;
class GrFontScaler : public GrRefCnt {
public:
virtual const GrKey* getKey() = 0;
virtual GrMaskFormat getMaskFormat() = 0;
virtual bool getPackedGlyphBounds(GrGlyph::PackedID, GrIRect* bounds) = 0;
virtual bool getPackedGlyphImage(GrGlyph::PackedID, int width, int height,
int rowBytes, void* image) = 0;

View File

@ -35,11 +35,13 @@ class GrFontPurgeListener;
*/
class GrTextStrike {
public:
GrTextStrike(GrFontCache*, const GrKey* fontScalerKey, GrAtlasMgr*);
GrTextStrike(GrFontCache*, const GrKey* fontScalerKey, GrMaskFormat,
GrAtlasMgr*);
~GrTextStrike();
const GrKey* getFontScalerKey() const { return fFontScalerKey; }
GrFontCache* getFontCache() const { return fFontCache; }
GrMaskFormat getMaskFormat() const { return fMaskFormat; }
inline GrGlyph* getGlyph(GrGlyph::PackedID, GrFontScaler*);
bool getGlyphAtlas(GrGlyph*, GrFontScaler*);
@ -66,6 +68,8 @@ private:
GrAtlasMgr* fAtlasMgr;
GrAtlas* fAtlas; // linklist
GrMaskFormat fMaskFormat;
GrGlyph* generateGlyph(GrGlyph::PackedID packed, GrFontScaler* scaler);
// returns true if after the purge, the strike is empty
bool purgeAtlasAtY(GrAtlas* atlas, int yCoord);

View File

@ -188,6 +188,22 @@ enum GrBlendCoeff {
kIDA_BlendCoeff, //<! one minus dst alpha
};
/**
* Formats for masks, used by the font cache
*/
enum GrMaskFormat {
kA8_GrMaskFormat, //!< 1-byte per pixel
kA565_GrMaskFormat //!< 2-bytes per pixel
};
/**
* Return the number of bytes-per-pixel for the specified mask format.
*/
static inline int GrMaskFormatBytesPerPixel(GrMaskFormat format) {
GrAssert((unsigned)format <= 1);
return (int)format + 1;
}
/**
* Set Operations used to construct clips.
*/

View File

@ -51,7 +51,7 @@
static int gCounter;
#endif
GrAtlas::GrAtlas(GrAtlasMgr* mgr, int plotX, int plotY) {
GrAtlas::GrAtlas(GrAtlasMgr* mgr, int plotX, int plotY, GrMaskFormat format) {
fAtlasMgr = mgr; // just a pointer, not an owner
fNext = NULL;
fTexture = mgr->getTexture(); // we're not an owner, just a pointer
@ -60,6 +60,8 @@ GrAtlas::GrAtlas(GrAtlasMgr* mgr, int plotX, int plotY) {
fRects = GrRectanizer::Factory(GR_ATLAS_WIDTH - BORDER,
GR_ATLAS_HEIGHT - BORDER);
fMaskFormat = format;
#if GR_DEBUG
GrPrintf(" GrAtlas %p [%d %d] %d\n", this, plotX, plotY, gCounter);
gCounter += 1;
@ -82,6 +84,13 @@ static void adjustForPlot(GrIPoint16* loc, const GrIPoint16& plot) {
loc->fY += plot.fY * GR_ATLAS_HEIGHT;
}
static uint8_t* zerofill(uint8_t* ptr, int count) {
while (--count >= 0) {
*ptr++ = 0;
}
return ptr;
}
bool GrAtlas::addSubImage(int width, int height, const void* image,
GrIPoint16* loc) {
if (!fRects->addRect(width + BORDER, height + BORDER, loc)) {
@ -89,23 +98,26 @@ bool GrAtlas::addSubImage(int width, int height, const void* image,
}
GrAutoSMalloc<1024> storage;
int srcW = width + 2*BORDER;
int srcH = height + 2*BORDER;
int dstW = width + 2*BORDER;
int dstH = height + 2*BORDER;
if (BORDER) {
uint8_t* ptr = (uint8_t*)storage.realloc(srcW * srcH);
Gr_bzero(ptr, srcW); // zero top row
ptr += srcW;
const int bpp = GrMaskFormatBytesPerPixel(fMaskFormat);
const size_t dstRB = dstW * bpp;
uint8_t* dst = (uint8_t*)storage.realloc(dstH * dstRB);
Gr_bzero(dst, dstRB); // zero top row
dst += dstRB;
for (int y = 0; y < height; y++) {
*ptr++ = 0; // zero left edge
memcpy(ptr, image, width); ptr += width;
*ptr++ = 0; // zero right edge
image = (const void*)((const char*)image + width);
dst = zerofill(dst, bpp); // zero left edge
memcpy(dst, image, width * bpp);
dst += width * bpp;
dst = zerofill(dst, bpp); // zero right edge
image = (const void*)((const char*)image + width * bpp);
}
Gr_bzero(ptr, srcW); // zero bottom row
Gr_bzero(dst, dstRB); // zero bottom row
image = storage.get();
}
adjustForPlot(loc, fPlot);
fTexture->uploadTextureData(loc->fX, loc->fY, srcW, srcH, image);
fTexture->uploadTextureData(loc->fX, loc->fY, dstW, dstH, image);
// now tell the caller to skip the top/left BORDER
loc->fX += BORDER;
@ -128,9 +140,23 @@ GrAtlasMgr::~GrAtlasMgr() {
fGpu->unref();
}
static GrTexture::PixelConfig maskformat2pixelconfig(GrMaskFormat format) {
switch (format) {
case kA8_GrMaskFormat:
return GrTexture::kAlpha_8_PixelConfig;
case kA565_GrMaskFormat:
return GrTexture::kRGB_565_PixelConfig;
default:
GrAssert(!"unknown maskformat");
}
return GrTexture::kUnknown_PixelConfig;
}
GrAtlas* GrAtlasMgr::addToAtlas(GrAtlas* atlas,
int width, int height, const void* image,
GrMaskFormat format,
GrIPoint16* loc) {
GrAssert(NULL == atlas || atlas->getMaskFormat() == format);
if (atlas && atlas->addSubImage(width, height, image, loc)) {
return atlas;
}
@ -149,7 +175,7 @@ GrAtlas* GrAtlasMgr::addToAtlas(GrAtlas* atlas,
GrGpu::kNone_AALevel,
GR_ATLAS_TEXTURE_WIDTH,
GR_ATLAS_TEXTURE_HEIGHT,
GrTexture::kAlpha_8_PixelConfig
maskformat2pixelconfig(format)
};
fTexture = fGpu->createTexture(desc, NULL, 0);
if (NULL == fTexture) {
@ -157,7 +183,7 @@ GrAtlas* GrAtlasMgr::addToAtlas(GrAtlas* atlas,
}
}
GrAtlas* newAtlas = new GrAtlas(this, plot.fX, plot.fY);
GrAtlas* newAtlas = new GrAtlas(this, plot.fX, plot.fY, format);
if (!newAtlas->addSubImage(width, height, image, loc)) {
delete newAtlas;
return NULL;

View File

@ -41,7 +41,8 @@ GrTextStrike* GrFontCache::generateStrike(GrFontScaler* scaler,
if (NULL == fAtlasMgr) {
fAtlasMgr = new GrAtlasMgr(fGpu);
}
GrTextStrike* strike = new GrTextStrike(this, scaler->getKey(), fAtlasMgr);
GrTextStrike* strike = new GrTextStrike(this, scaler->getKey(),
scaler->getMaskFormat(), fAtlasMgr);
fCache.insert(key, strike);
if (fHead) {
@ -131,6 +132,7 @@ void GrFontCache::validate() const {
*/
GrTextStrike::GrTextStrike(GrFontCache* cache, const GrKey* key,
GrMaskFormat format,
GrAtlasMgr* atlasMgr) : fPool(64) {
fFontScalerKey = key;
fFontScalerKey->ref();
@ -139,6 +141,8 @@ GrTextStrike::GrTextStrike(GrFontCache* cache, const GrKey* key,
fAtlasMgr = atlasMgr; // no need to ref, it won't go away before we do
fAtlas = NULL;
fMaskFormat = format;
#if GR_DEBUG
GrPrintf(" GrTextStrike %p %d\n", this, gCounter);
gCounter += 1;
@ -181,16 +185,19 @@ bool GrTextStrike::getGlyphAtlas(GrGlyph* glyph, GrFontScaler* scaler) {
GrAutoRef ar(scaler);
size_t size = glyph->fBounds.area();
int bytesPerPixel = GrMaskFormatBytesPerPixel(fMaskFormat);
size_t size = glyph->fBounds.area() * bytesPerPixel;
GrAutoSMalloc<1024> storage(size);
if (!scaler->getPackedGlyphImage(glyph->fPackedID, glyph->width(),
glyph->height(), glyph->width(),
glyph->height(),
glyph->width() * bytesPerPixel,
storage.get())) {
return false;
}
GrAtlas* atlas = fAtlasMgr->addToAtlas(fAtlas, glyph->width(),
glyph->height(), storage.get(),
fMaskFormat,
&glyph->fAtlasLocation);
if (NULL == atlas) {
return false;

View File

@ -222,6 +222,10 @@ public:
SkScalerContext(const SkDescriptor* desc);
virtual ~SkScalerContext();
SkMask::Format getMaskFormat() const {
return (SkMask::Format)fRec.fMaskFormat;
}
// remember our glyph offset/base
void setBaseGlyphCount(unsigned baseGlyphCount) {
fBaseGlyphCount = baseGlyphCount;

View File

@ -275,6 +275,7 @@ public:
// overrides
virtual const GrKey* getKey();
virtual GrMaskFormat getMaskFormat();
virtual bool getPackedGlyphBounds(GrGlyph::PackedID, GrIRect* bounds);
virtual bool getPackedGlyphImage(GrGlyph::PackedID, int width, int height,
int rowBytes, void* image);

View File

@ -98,6 +98,10 @@ public:
const SkDescriptor& getDescriptor() const { return *fDesc; }
SkMask::Format getMaskFormat() const {
return fScalerContext->getMaskFormat();
}
/* AuxProc/Data allow a client to associate data with this cache entry.
Multiple clients can use this, as their data is keyed with a function
pointer. In addition to serving as a key, the function pointer is called

View File

@ -83,6 +83,19 @@ SkGrFontScaler::~SkGrFontScaler() {
GrSafeUnref(fKey);
}
GrMaskFormat SkGrFontScaler::getMaskFormat() {
SkMask::Format format = fStrike->getMaskFormat();
switch (format) {
case SkMask::kA8_Format:
return kA8_GrMaskFormat;
case SkMask::kLCD16_Format:
return kA565_GrMaskFormat;
default:
GrAssert(!"unsupported SkMask::Format");
return kA8_GrMaskFormat;
}
}
const GrKey* SkGrFontScaler::getKey() {
if (NULL == fKey) {
fKey = new SkGrDescKey(fStrike->getDescriptor());
@ -117,8 +130,9 @@ bool SkGrFontScaler::getPackedGlyphImage(GrGlyph::PackedID packed,
if (srcRB == dstRB) {
memcpy(dst, src, dstRB * height);
} else {
const int bbp = GrMaskFormatBytesPerPixel(this->getMaskFormat());
for (int y = 0; y < height; y++) {
memcpy(dst, src, width);
memcpy(dst, src, width * bbp);
src = (const char*)src + srcRB;
dst = (char*)dst + dstRB;
}