support lcd16 in text atlas (sans shader support)
git-svn-id: http://skia.googlecode.com/svn/trunk@939 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/gpu/include/GrAtlas.h b/gpu/include/GrAtlas.h
index 9526e0b..9fd2cab 100644
--- a/gpu/include/GrAtlas.h
+++ b/gpu/include/GrAtlas.h
@@ -28,10 +28,11 @@
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 @@
GrRectanizer* fRects;
GrAtlasMgr* fAtlasMgr;
GrIPoint16 fPlot;
+ GrMaskFormat fMaskFormat;
friend class GrAtlasMgr;
};
@@ -68,7 +70,7 @@
~GrAtlasMgr();
GrAtlas* addToAtlas(GrAtlas*, int width, int height, const void*,
- GrIPoint16*);
+ GrMaskFormat, GrIPoint16*);
GrTexture* getTexture() const { return fTexture; }
diff --git a/gpu/include/GrFontScaler.h b/gpu/include/GrFontScaler.h
index 6baa56f..77730d7 100644
--- a/gpu/include/GrFontScaler.h
+++ b/gpu/include/GrFontScaler.h
@@ -33,6 +33,7 @@
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;
diff --git a/gpu/include/GrTextStrike.h b/gpu/include/GrTextStrike.h
index abafa57..610222c 100644
--- a/gpu/include/GrTextStrike.h
+++ b/gpu/include/GrTextStrike.h
@@ -35,11 +35,13 @@
*/
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 @@
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);
@@ -110,7 +114,7 @@
GrGpu* fGpu;
GrAtlasMgr* fAtlasMgr;
-
+
GrTextStrike* generateStrike(GrFontScaler*, const Key&);
inline void detachStrikeFromList(GrTextStrike*);
};
diff --git a/gpu/include/GrTypes.h b/gpu/include/GrTypes.h
index f407e2f..3c137f8 100644
--- a/gpu/include/GrTypes.h
+++ b/gpu/include/GrTypes.h
@@ -189,6 +189,22 @@
};
/**
+ * 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.
*/
enum GrSetOp {
diff --git a/gpu/src/GrAtlas.cpp b/gpu/src/GrAtlas.cpp
index b55a029..ea32719 100644
--- a/gpu/src/GrAtlas.cpp
+++ b/gpu/src/GrAtlas.cpp
@@ -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 @@
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 @@
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 @@
}
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 @@
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;
}
@@ -145,11 +171,11 @@
if (NULL == fTexture) {
GrGpu::TextureDesc desc = {
- GrGpu::kDynamicUpdate_TextureFlag,
+ GrGpu::kDynamicUpdate_TextureFlag,
GrGpu::kNone_AALevel,
- GR_ATLAS_TEXTURE_WIDTH,
+ 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* 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;
diff --git a/gpu/src/GrTextStrike.cpp b/gpu/src/GrTextStrike.cpp
index c2d81d5..6cdb61c 100644
--- a/gpu/src/GrTextStrike.cpp
+++ b/gpu/src/GrTextStrike.cpp
@@ -41,7 +41,8 @@
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 @@
*/
GrTextStrike::GrTextStrike(GrFontCache* cache, const GrKey* key,
+ GrMaskFormat format,
GrAtlasMgr* atlasMgr) : fPool(64) {
fFontScalerKey = key;
fFontScalerKey->ref();
@@ -139,6 +141,8 @@
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;
@@ -180,17 +184,20 @@
}
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;
diff --git a/include/core/SkScalerContext.h b/include/core/SkScalerContext.h
index 584b86b..55dfcef 100644
--- a/include/core/SkScalerContext.h
+++ b/include/core/SkScalerContext.h
@@ -222,6 +222,10 @@
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;
diff --git a/include/gpu/SkGr.h b/include/gpu/SkGr.h
index 6f5ebfe..7221213 100644
--- a/include/gpu/SkGr.h
+++ b/include/gpu/SkGr.h
@@ -231,7 +231,7 @@
SkGrRegionIterator() {}
SkGrRegionIterator(const SkRegion& region) { this->reset(region); }
- void reset(const SkRegion& region) {
+ void reset(const SkRegion& region) {
fRegion = ®ion;
fIter.reset(region);
}
@@ -275,6 +275,7 @@
// 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);
diff --git a/src/core/SkGlyphCache.h b/src/core/SkGlyphCache.h
index d6b4fd6..92e3795 100644
--- a/src/core/SkGlyphCache.h
+++ b/src/core/SkGlyphCache.h
@@ -2,16 +2,16 @@
**
** Copyright 2006, 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
+** 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
+** 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
+** 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.
*/
@@ -47,17 +47,17 @@
*/
const SkGlyph& getUnicharAdvance(SkUnichar);
const SkGlyph& getGlyphIDAdvance(uint16_t);
-
+
/** Returns a glyph with all fields valid except fImage and fPath, which
may be null. If they are null, call findImage or findPath for those.
If they are not null, then they are valid.
-
+
This call is potentially slower than the matching ...Advance call. If
you only need the fAdvance/fDevKern fields, call those instead.
*/
const SkGlyph& getUnicharMetrics(SkUnichar);
const SkGlyph& getGlyphIDMetrics(uint16_t);
-
+
/** These are variants that take the device position of the glyph. Call
these only if you are drawing in subpixel mode. Passing 0, 0 is
effectively the same as calling the variants w/o the extra params, tho
@@ -65,13 +65,13 @@
*/
const SkGlyph& getUnicharMetrics(SkUnichar, SkFixed x, SkFixed y);
const SkGlyph& getGlyphIDMetrics(uint16_t, SkFixed x, SkFixed y);
-
+
/** Return the glyphID for the specified Unichar. If the char has already
been seen, use the existing cache entry. If not, ask the scalercontext
to compute it for us.
*/
uint16_t unicharToGlyph(SkUnichar);
-
+
/** Map the glyph to its Unicode equivalent. Unmappable glyphs map to
a character code of zero.
*/
@@ -98,6 +98,10 @@
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
@@ -106,7 +110,7 @@
this glyphcache in any way, since it may be in the process of being
deleted.
*/
-
+
//! If the proc is found, return true and set *dataPtr to its data
bool getAuxProcData(void (*auxProc)(void*), void** dataPtr) const;
//! Add a proc/data pair to the glyphcache. proc should be non-null
@@ -120,7 +124,7 @@
deadlock.
*/
static void VisitAllCaches(bool (*proc)(SkGlyphCache*, void*), void* ctx);
-
+
/** Find a matching cache entry, and call proc() with it. If none is found
create a new one. If the proc() returns true, detach the cache and
return it, otherwise leave it and return NULL.
@@ -128,7 +132,7 @@
static SkGlyphCache* VisitCache(const SkDescriptor* desc,
bool (*proc)(const SkGlyphCache*, void*),
void* context);
-
+
/** Given a strike that was returned by either VisitCache() or DetachCache()
add it back into the global cache list (after which the caller should
not reference it anymore.
@@ -184,11 +188,11 @@
private:
const SkGlyphCache* fCache;
};
-
+
private:
SkGlyphCache(const SkDescriptor*);
~SkGlyphCache();
-
+
enum MetricsType {
kJustAdvance_MetricsType,
kFull_MetricsType
@@ -208,7 +212,7 @@
}
fPrev = fNext = NULL;
}
-
+
void attachToHead(SkGlyphCache** head) {
SkASSERT(NULL == fPrev && NULL == fNext);
if (*head) {
@@ -232,7 +236,7 @@
SkTDArray<SkGlyph*> fGlyphArray;
SkChunkAlloc fGlyphAlloc;
SkChunkAlloc fImageAlloc;
-
+
int fMetricsCount, fAdvanceCount;
struct CharGlyphRec {
@@ -241,7 +245,7 @@
};
// no reason to use the same kHashCount as fGlyphHash, but we do for now
CharGlyphRec fCharToGlyphHash[kHashCount];
-
+
enum {
// shift so that the top bits fall into kHashBits region
kShiftForHashIndex = SkGlyph::kSubShift +
@@ -252,7 +256,7 @@
static inline unsigned ID2HashIndex(uint32_t id) {
return (id ^ (id >> kShiftForHashIndex)) & kHashMask;
}
-
+
// used to track (approx) how much ram is tied-up in this cache
size_t fMemoryUsed;
@@ -302,7 +306,7 @@
}
private:
SkGlyphCache* fCache;
-
+
static bool DetachProc(const SkGlyphCache*, void*);
};
diff --git a/src/gpu/SkGrFontScaler.cpp b/src/gpu/SkGrFontScaler.cpp
index 3d57aa8..16e44b9 100644
--- a/src/gpu/SkGrFontScaler.cpp
+++ b/src/gpu/SkGrFontScaler.cpp
@@ -83,6 +83,19 @@
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 @@
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;
}