aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--include/core/SkPaint.h8
-rw-r--r--src/core/SkPaint.cpp213
2 files changed, 143 insertions, 78 deletions
diff --git a/include/core/SkPaint.h b/include/core/SkPaint.h
index 5f02662d71..bb5eff4d91 100644
--- a/include/core/SkPaint.h
+++ b/include/core/SkPaint.h
@@ -20,6 +20,7 @@
class SkAnnotation;
class SkAutoGlyphCache;
class SkColorFilter;
+class SkData;
class SkDescriptor;
struct SkDeviceProperties;
class SkReadBuffer;
@@ -1080,6 +1081,13 @@ private:
SkScalar measure_text(SkGlyphCache*, const char* text, size_t length,
int* count, SkRect* bounds) const;
+ /*
+ * Allocs an SkDescriptor on the heap and return it to the caller as a refcnted
+ * SkData. Caller is responsible for managing the lifetime of this object.
+ */
+ const SkData* getScalerContextDescriptor(const SkDeviceProperties* deviceProperties,
+ const SkMatrix*, bool ignoreGamma) const;
+
SkGlyphCache* detachCache(const SkDeviceProperties* deviceProperties, const SkMatrix*,
bool ignoreGamma) const;
diff --git a/src/core/SkPaint.cpp b/src/core/SkPaint.cpp
index b93236f0d1..6ddbe027a1 100644
--- a/src/core/SkPaint.cpp
+++ b/src/core/SkPaint.cpp
@@ -1589,121 +1589,178 @@ void SkScalerContext::PostMakeRec(const SkPaint&, SkScalerContext::Rec* rec) {
#define TEST_DESC
#endif
-/*
- * ignoreGamma tells us that the caller just wants metrics that are unaffected
- * by gamma correction, so we set the rec to ignore preblend: i.e. gamma = 1,
- * contrast = 0, luminanceColor = transparent black.
- */
-void SkPaint::descriptorProc(const SkDeviceProperties* deviceProperties,
- const SkMatrix* deviceMatrix,
- void (*proc)(SkTypeface*, const SkDescriptor*, void*),
- void* context, bool ignoreGamma) const {
- SkScalerContext::Rec rec;
+static void write_out_descriptor(SkDescriptor* desc, const SkScalerContext::Rec& rec,
+ const SkPathEffect* pe, SkWriteBuffer* peBuffer,
+ const SkMaskFilter* mf, SkWriteBuffer* mfBuffer,
+ const SkRasterizer* ra, SkWriteBuffer* raBuffer,
+ size_t descSize) {
+ desc->init();
+ desc->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
- SkScalerContext::MakeRec(*this, deviceProperties, deviceMatrix, &rec);
- if (ignoreGamma) {
- rec.ignorePreBlend();
+ if (pe) {
+ add_flattenable(desc, kPathEffect_SkDescriptorTag, peBuffer);
+ }
+ if (mf) {
+ add_flattenable(desc, kMaskFilter_SkDescriptorTag, mfBuffer);
+ }
+ if (ra) {
+ add_flattenable(desc, kRasterizer_SkDescriptorTag, raBuffer);
}
- size_t descSize = sizeof(rec);
- int entryCount = 1;
- SkPathEffect* pe = this->getPathEffect();
- SkMaskFilter* mf = this->getMaskFilter();
- SkRasterizer* ra = this->getRasterizer();
+ desc->computeChecksum();
+}
+
+static size_t fill_out_rec(const SkPaint& paint, SkScalerContext::Rec* rec,
+ const SkDeviceProperties* deviceProperties,
+ const SkMatrix* deviceMatrix, bool ignoreGamma,
+ const SkPathEffect* pe, SkWriteBuffer* peBuffer,
+ const SkMaskFilter* mf, SkWriteBuffer* mfBuffer,
+ const SkRasterizer* ra, SkWriteBuffer* raBuffer) {
+ SkScalerContext::MakeRec(paint, deviceProperties, deviceMatrix, rec);
+ if (ignoreGamma) {
+ rec->ignorePreBlend();
+ }
- SkWriteBuffer peBuffer, mfBuffer, raBuffer;
+ int entryCount = 1;
+ size_t descSize = sizeof(*rec);
if (pe) {
- peBuffer.writeFlattenable(pe);
- descSize += peBuffer.bytesWritten();
+ peBuffer->writeFlattenable(pe);
+ descSize += peBuffer->bytesWritten();
entryCount += 1;
- rec.fMaskFormat = SkMask::kA8_Format; // force antialiasing when we do the scan conversion
+ rec->fMaskFormat = SkMask::kA8_Format; // force antialiasing when we do the scan conversion
// seems like we could support kLCD as well at this point...
}
if (mf) {
- mfBuffer.writeFlattenable(mf);
- descSize += mfBuffer.bytesWritten();
+ mfBuffer->writeFlattenable(mf);
+ descSize += mfBuffer->bytesWritten();
entryCount += 1;
- rec.fMaskFormat = SkMask::kA8_Format; // force antialiasing with maskfilters
+ rec->fMaskFormat = SkMask::kA8_Format; // force antialiasing with maskfilters
/* Pre-blend is not currently applied to filtered text.
The primary filter is blur, for which contrast makes no sense,
and for which the destination guess error is more visible.
Also, all existing users of blur have calibrated for linear. */
- rec.ignorePreBlend();
+ rec->ignorePreBlend();
}
if (ra) {
- raBuffer.writeFlattenable(ra);
- descSize += raBuffer.bytesWritten();
+ raBuffer->writeFlattenable(ra);
+ descSize += raBuffer->bytesWritten();
entryCount += 1;
- rec.fMaskFormat = SkMask::kA8_Format; // force antialiasing when we do the scan conversion
+ rec->fMaskFormat = SkMask::kA8_Format; // force antialiasing when we do the scan conversion
}
///////////////////////////////////////////////////////////////////////////
// Now that we're done tweaking the rec, call the PostMakeRec cleanup
- SkScalerContext::PostMakeRec(*this, &rec);
+ SkScalerContext::PostMakeRec(paint, rec);
descSize += SkDescriptor::ComputeOverhead(entryCount);
+ return descSize;
+}
- SkAutoDescriptor ad(descSize);
- SkDescriptor* desc = ad.getDesc();
-
- desc->init();
- desc->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
+#ifdef TEST_DESC
+static void test_desc(const SkScalerContext::Rec& rec,
+ const SkPathEffect* pe, SkWriteBuffer* peBuffer,
+ const SkMaskFilter* mf, SkWriteBuffer* mfBuffer,
+ const SkRasterizer* ra, SkWriteBuffer* raBuffer,
+ const SkDescriptor* desc, size_t descSize) {
+ // Check that we completely write the bytes in desc (our key), and that
+ // there are no uninitialized bytes. If there were, then we would get
+ // false-misses (or worse, false-hits) in our fontcache.
+ //
+ // We do this buy filling 2 others, one with 0s and the other with 1s
+ // and create those, and then check that all 3 are identical.
+ SkAutoDescriptor ad1(descSize);
+ SkAutoDescriptor ad2(descSize);
+ SkDescriptor* desc1 = ad1.getDesc();
+ SkDescriptor* desc2 = ad2.getDesc();
+
+ memset(desc1, 0x00, descSize);
+ memset(desc2, 0xFF, descSize);
+
+ desc1->init();
+ desc2->init();
+ desc1->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
+ desc2->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
if (pe) {
- add_flattenable(desc, kPathEffect_SkDescriptorTag, &peBuffer);
+ add_flattenable(desc1, kPathEffect_SkDescriptorTag, peBuffer);
+ add_flattenable(desc2, kPathEffect_SkDescriptorTag, peBuffer);
}
if (mf) {
- add_flattenable(desc, kMaskFilter_SkDescriptorTag, &mfBuffer);
+ add_flattenable(desc1, kMaskFilter_SkDescriptorTag, mfBuffer);
+ add_flattenable(desc2, kMaskFilter_SkDescriptorTag, mfBuffer);
}
if (ra) {
- add_flattenable(desc, kRasterizer_SkDescriptorTag, &raBuffer);
+ add_flattenable(desc1, kRasterizer_SkDescriptorTag, raBuffer);
+ add_flattenable(desc2, kRasterizer_SkDescriptorTag, raBuffer);
}
+ SkASSERT(descSize == desc1->getLength());
+ SkASSERT(descSize == desc2->getLength());
+ desc1->computeChecksum();
+ desc2->computeChecksum();
+ SkASSERT(!memcmp(desc, desc1, descSize));
+ SkASSERT(!memcmp(desc, desc2, descSize));
+}
+#endif
+
+/* see the note on ignoreGamma on descriptorProc */
+const SkData* SkPaint::getScalerContextDescriptor(const SkDeviceProperties* deviceProperties,
+ const SkMatrix* deviceMatrix,
+ bool ignoreGamma) const {
+ SkScalerContext::Rec rec;
+
+ SkPathEffect* pe = this->getPathEffect();
+ SkMaskFilter* mf = this->getMaskFilter();
+ SkRasterizer* ra = this->getRasterizer();
+
+ SkWriteBuffer peBuffer, mfBuffer, raBuffer;
+ size_t descSize = fill_out_rec(*this, &rec, deviceProperties, deviceMatrix, ignoreGamma,
+ pe, &peBuffer, mf, &mfBuffer, ra, &raBuffer);
+
+ SkASSERT(SkAlign4(descSize) == descSize);
+ SkData* data = SkData::NewUninitialized(descSize);
+ SkDescriptor* desc = reinterpret_cast<SkDescriptor*>(data->writable_data());
+
+ write_out_descriptor(desc, rec, pe, &peBuffer, mf, &mfBuffer, ra, &raBuffer, descSize);
+
SkASSERT(descSize == desc->getLength());
- desc->computeChecksum();
#ifdef TEST_DESC
- {
- // Check that we completely write the bytes in desc (our key), and that
- // there are no uninitialized bytes. If there were, then we would get
- // false-misses (or worse, false-hits) in our fontcache.
- //
- // We do this buy filling 2 others, one with 0s and the other with 1s
- // and create those, and then check that all 3 are identical.
- SkAutoDescriptor ad1(descSize);
- SkAutoDescriptor ad2(descSize);
- SkDescriptor* desc1 = ad1.getDesc();
- SkDescriptor* desc2 = ad2.getDesc();
-
- memset(desc1, 0x00, descSize);
- memset(desc2, 0xFF, descSize);
-
- desc1->init();
- desc2->init();
- desc1->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
- desc2->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
-
- if (pe) {
- add_flattenable(desc1, kPathEffect_SkDescriptorTag, &peBuffer);
- add_flattenable(desc2, kPathEffect_SkDescriptorTag, &peBuffer);
- }
- if (mf) {
- add_flattenable(desc1, kMaskFilter_SkDescriptorTag, &mfBuffer);
- add_flattenable(desc2, kMaskFilter_SkDescriptorTag, &mfBuffer);
- }
- if (ra) {
- add_flattenable(desc1, kRasterizer_SkDescriptorTag, &raBuffer);
- add_flattenable(desc2, kRasterizer_SkDescriptorTag, &raBuffer);
- }
+ test_desc(rec, pe, &peBuffer, mf, &mfBuffer, ra, &raBuffer, desc, descSize);
+#endif
- SkASSERT(descSize == desc1->getLength());
- SkASSERT(descSize == desc2->getLength());
- desc1->computeChecksum();
- desc2->computeChecksum();
- SkASSERT(!memcmp(desc, desc1, descSize));
- SkASSERT(!memcmp(desc, desc2, descSize));
- }
+ return data;
+}
+
+/*
+ * ignoreGamma tells us that the caller just wants metrics that are unaffected
+ * by gamma correction, so we set the rec to ignore preblend: i.e. gamma = 1,
+ * contrast = 0, luminanceColor = transparent black.
+ */
+void SkPaint::descriptorProc(const SkDeviceProperties* deviceProperties,
+ const SkMatrix* deviceMatrix,
+ void (*proc)(SkTypeface*, const SkDescriptor*, void*),
+ void* context, bool ignoreGamma) const {
+ SkScalerContext::Rec rec;
+
+ SkPathEffect* pe = this->getPathEffect();
+ SkMaskFilter* mf = this->getMaskFilter();
+ SkRasterizer* ra = this->getRasterizer();
+
+ SkWriteBuffer peBuffer, mfBuffer, raBuffer;
+ size_t descSize = fill_out_rec(*this, &rec, deviceProperties, deviceMatrix, ignoreGamma,
+ pe, &peBuffer, mf, &mfBuffer, ra, &raBuffer);
+
+ SkAutoDescriptor ad(descSize);
+ SkDescriptor* desc = ad.getDesc();
+
+ write_out_descriptor(desc, rec, pe, &peBuffer, mf, &mfBuffer, ra, &raBuffer, descSize);
+
+ SkASSERT(descSize == desc->getLength());
+
+#ifdef TEST_DESC
+ test_desc(rec, pe, &peBuffer, mf, &mfBuffer, ra, &raBuffer, desc, descSize);
#endif
proc(fTypeface, desc, context);