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:
parent
b7e9aee1ac
commit
98539c607b
@ -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; }
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
*/
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user