aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar reed@android.com <reed@android.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2009-02-11 15:07:19 +0000
committerGravatar reed@android.com <reed@android.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2009-02-11 15:07:19 +0000
commit62900b4c64401bc80ae85f6f5c87309a273cae10 (patch)
treec36e459951deccd587a7c75d44f1d01653fad8f2 /src
parentd9c0f0b57affec7a472879c5919acac6637d926a (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.cpp51
-rw-r--r--src/images/SkImageDecoder.cpp59
-rw-r--r--src/ports/SkFontHost_FreeType.cpp38
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;
}
///////////////////////////////////////////////////////////////////////////////