diff options
author | reed@android.com <reed@android.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2009-02-11 15:07:19 +0000 |
---|---|---|
committer | reed@android.com <reed@android.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2009-02-11 15:07:19 +0000 |
commit | 62900b4c64401bc80ae85f6f5c87309a273cae10 (patch) | |
tree | c36e459951deccd587a7c75d44f1d01653fad8f2 /src | |
parent | d9c0f0b57affec7a472879c5919acac6637d926a (diff) |
handle failure when creating a scalercontext
git-svn-id: http://skia.googlecode.com/svn/trunk@90 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src')
-rw-r--r-- | src/core/SkScalerContext.cpp | 51 | ||||
-rw-r--r-- | src/images/SkImageDecoder.cpp | 59 | ||||
-rw-r--r-- | src/ports/SkFontHost_FreeType.cpp | 38 |
3 files changed, 118 insertions, 30 deletions
diff --git a/src/core/SkScalerContext.cpp b/src/core/SkScalerContext.cpp index f63e729389..bbcc1308c1 100644 --- a/src/core/SkScalerContext.cpp +++ b/src/core/SkScalerContext.cpp @@ -52,6 +52,19 @@ size_t SkGlyph::computeImageSize() const { return size; } +void SkGlyph::zeroMetrics() { + fAdvanceX = 0; + fAdvanceY = 0; + fWidth = 0; + fHeight = 0; + fTop = 0; + fLeft = 0; + fRsbDelta = 0; + fLsbDelta = 0; +} + +/////////////////////////////////////////////////////////////////////////////// + #ifdef SK_DEBUG #define DUMP_RECx #endif @@ -521,10 +534,46 @@ void SkScalerContext::Rec::getSingleMatrix(SkMatrix* m) const } } +/////////////////////////////////////////////////////////////////////////////// + #include "SkFontHost.h" +class SkScalerContext_Empty : public SkScalerContext { +public: + SkScalerContext_Empty(const SkDescriptor* desc) : SkScalerContext(desc) {} + +protected: + virtual unsigned generateGlyphCount() const { + return 0; + } + virtual uint16_t generateCharToGlyph(SkUnichar uni) { + return 0; + } + virtual void generateAdvance(SkGlyph* glyph) { + glyph->zeroMetrics(); + } + virtual void generateMetrics(SkGlyph* glyph) { + glyph->zeroMetrics(); + } + virtual void generateImage(const SkGlyph& glyph) {} + virtual void generatePath(const SkGlyph& glyph, SkPath* path) {} + virtual void generateFontMetrics(SkPaint::FontMetrics* mx, + SkPaint::FontMetrics* my) { + if (mx) { + bzero(mx, sizeof(*mx)); + } + if (my) { + bzero(my, sizeof(*my)); + } + } +}; + SkScalerContext* SkScalerContext::Create(const SkDescriptor* desc) { - return SkFontHost::CreateScalerContext(desc); + SkScalerContext* c = SkFontHost::CreateScalerContext(desc); + if (NULL == c) { + c = SkNEW_ARGS(SkScalerContext_Empty, (desc)); + } + return c; } diff --git a/src/images/SkImageDecoder.cpp b/src/images/SkImageDecoder.cpp index 2d477ef4aa..f0fff1b9b3 100644 --- a/src/images/SkImageDecoder.cpp +++ b/src/images/SkImageDecoder.cpp @@ -91,25 +91,62 @@ bool SkImageDecoder::allocPixelRef(SkBitmap* bitmap, /////////////////////////////////////////////////////////////////////////////// +/* Technically, this should be 342, since that is the cutoff point between + an index and 32bit bitmap (they take equal ram), but since 32bit is almost + always faster, I bump up the value a bit. +*/ +#define MIN_SIZE_FOR_INDEX (512) + +/* Return the "optimal" config for this bitmap. In this case, we just look to + promote index bitmaps to full-color, since those are a little faster to + draw (fewer memory lookups). + + Seems like we could expose this to the caller through some exising or new + proxy object, allowing them to decide (after sniffing some aspect of the + original bitmap) what config they really want. + */ +static SkBitmap::Config optimal_config(const SkBitmap& bm, + SkBitmap::Config pref) { + if (bm.config() != pref) { + if (bm.config() == SkBitmap::kIndex8_Config) { + Sk64 size64 = bm.getSize64(); + if (size64.is32()) { + int32_t size = size64.get32(); + if (size < MIN_SIZE_FOR_INDEX) { + return SkBitmap::kARGB_8888_Config; + } + } + } + } + return bm.config(); +} + bool SkImageDecoder::decode(SkStream* stream, SkBitmap* bm, SkBitmap::Config pref, Mode mode) { + // pass a temporary bitmap, so that if we return false, we are assured of + // leaving the caller's bitmap untouched. SkBitmap tmp; // we reset this to false before calling onDecode fShouldCancelDecode = false; - // pass a temporary bitmap, so that if we return false, we are assured of - // leaving the caller's bitmap untouched. - if (this->onDecode(stream, &tmp, pref, mode)) { - /* We operate on a tmp bitmap until we know we succeed. This way - we're sure we don't change the caller's bitmap and then later - return false. Returning false must mean that their parameter - is unchanged. - */ - bm->swap(tmp); - return true; + if (!this->onDecode(stream, &tmp, pref, mode)) { + return false; } - return false; + + SkBitmap::Config c = optimal_config(tmp, pref); + if (c != tmp.config()) { + if (mode == kDecodeBounds_Mode) { + tmp.setConfig(c, tmp.width(), tmp.height()); + } else { + SkBitmap tmp2; + if (tmp.copyTo(&tmp2, c, this->getAllocator())) { + tmp.swap(tmp2); + } + } + } + bm->swap(tmp); + return true; } /////////////////////////////////////////////////////////////////////////////// diff --git a/src/ports/SkFontHost_FreeType.cpp b/src/ports/SkFontHost_FreeType.cpp index 5adeb13604..742a861ee4 100644 --- a/src/ports/SkFontHost_FreeType.cpp +++ b/src/ports/SkFontHost_FreeType.cpp @@ -63,6 +63,10 @@ class SkScalerContext_FreeType : public SkScalerContext { public: SkScalerContext_FreeType(const SkDescriptor* desc); virtual ~SkScalerContext_FreeType(); + + bool success() const { + return fFaceRec != NULL && fFTSize != NULL; + } protected: virtual unsigned generateGlyphCount() const; @@ -146,6 +150,7 @@ SkFaceRec::SkFaceRec(SkStream* strm, uint32_t fontID) fFTStream.close = sk_stream_close; } +// Will return 0 on failure static SkFaceRec* ref_ft_face(uint32_t fontID) { SkFaceRec* rec = gFaceRecHead; while (rec) { @@ -160,7 +165,6 @@ static SkFaceRec* ref_ft_face(uint32_t fontID) { SkStream* strm = SkFontHost::OpenStream(fontID); if (NULL == strm) { SkDEBUGF(("SkFontHost::OpenStream failed opening %x\n", fontID)); - sk_throw(); return 0; } @@ -187,7 +191,6 @@ static SkFaceRec* ref_ft_face(uint32_t fontID) { if (err) { // bad filename, try the default font fprintf(stderr, "ERROR: unable to open font '%x'\n", fontID); SkDELETE(rec); - sk_throw(); return 0; } else { SkASSERT(rec->fFace); @@ -225,7 +228,7 @@ static void unref_ft_face(FT_Face face) { /////////////////////////////////////////////////////////////////////////// SkScalerContext_FreeType::SkScalerContext_FreeType(const SkDescriptor* desc) - : SkScalerContext(desc), fFTSize(NULL) { + : SkScalerContext(desc) { SkAutoMutexAcquire ac(gFTMutex); FT_Error err; @@ -238,8 +241,13 @@ SkScalerContext_FreeType::SkScalerContext_FreeType(const SkDescriptor* desc) ++gFTCount; // load the font file + fFTSize = NULL; + fFace = NULL; fFaceRec = ref_ft_face(fRec.fFontID); - fFace = fFaceRec ? fFaceRec->fFace : NULL; + if (NULL == fFaceRec) { + return; + } + fFace = fFaceRec->fFace; // compute our factors from the record @@ -417,17 +425,6 @@ static FT_Pixel_Mode compute_pixel_mode(SkMask::Format format) { } } -static void set_glyph_metrics_on_error(SkGlyph* glyph) { - glyph->fRsbDelta = 0; - glyph->fLsbDelta = 0; - glyph->fWidth = 0; - glyph->fHeight = 0; - glyph->fTop = 0; - glyph->fLeft = 0; - glyph->fAdvanceX = 0; - glyph->fAdvanceY = 0; -} - void SkScalerContext_FreeType::generateAdvance(SkGlyph* glyph) { #ifdef FT_ADVANCES_H /* unhinted and light hinted text have linearly scaled advances @@ -437,7 +434,7 @@ void SkScalerContext_FreeType::generateAdvance(SkGlyph* glyph) { SkAutoMutexAcquire ac(gFTMutex); if (this->setupSize()) { - set_glyph_metrics_on_error(glyph); + glyph->zeroMetrics(); return; } @@ -478,7 +475,7 @@ void SkScalerContext_FreeType::generateMetrics(SkGlyph* glyph) { SkDEBUGF(("SkScalerContext_FreeType::generateMetrics(%x): FT_Load_Glyph(glyph:%d flags:%d) returned 0x%x\n", fFaceRec->fFontID, glyph->getGlyphID(fBaseGlyphCount), fLoadGlyphFlags, err)); ERROR: - set_glyph_metrics_on_error(glyph); + glyph->zeroMetrics(); return; } @@ -769,7 +766,12 @@ void SkScalerContext_FreeType::generateFontMetrics(SkPaint::FontMetrics* mx, //////////////////////////////////////////////////////////////////////// SkScalerContext* SkFontHost::CreateScalerContext(const SkDescriptor* desc) { - return SkNEW_ARGS(SkScalerContext_FreeType, (desc)); + SkScalerContext_FreeType* c = SkNEW_ARGS(SkScalerContext_FreeType, (desc)); + if (!c->success()) { + SkDELETE(c); + c = NULL; + } + return c; } /////////////////////////////////////////////////////////////////////////////// |