Clean up SkScalerContext descriptor creation

Allow a descriptor creation using just a rec and effects.
This is the most complex part of the change.

Cleanup SkScalerContextFlags to be a real thing.
This has spread everywhere.

BUG=skia:7515

Change-Id: I67189c9aeb51f1777a1c60145216524d440cb890
Reviewed-on: https://skia-review.googlesource.com/98320
Commit-Queue: Herb Derby <herb@google.com>
Commit-Queue: Mike Reed <reed@google.com>
Reviewed-by: Mike Reed <reed@google.com>
This commit is contained in:
Herb Derby 2018-01-22 14:39:27 -05:00 committed by Skia Commit-Bot
parent 0331d37af9
commit d8327a8c8b
13 changed files with 307 additions and 298 deletions

View File

@ -36,6 +36,7 @@ class SkSurfaceProps;
class SkTextBlob;
class SkTypeface;
/** \class SkPaint
SkPaint controls options applied when drawing and measuring. SkPaint collects all
options outside of the SkCanvas clip and SkCanvas matrix.
@ -1679,25 +1680,12 @@ private:
SkScalar measure_text(SkGlyphCache*, const char* text, size_t length,
int* count, SkRect* bounds) const;
enum ScalerContextFlags : uint32_t {
kNone_ScalerContextFlags = 0,
kFakeGamma_ScalerContextFlag = 1 << 0,
kBoostContrast_ScalerContextFlag = 1 << 1,
kFakeGammaAndBoostContrast_ScalerContextFlags =
kFakeGamma_ScalerContextFlag | kBoostContrast_ScalerContextFlag,
};
/*
* 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.
*/
void getScalerContextDescriptor(SkScalerContextEffects*, SkAutoDescriptor*,
const SkSurfaceProps& surfaceProps,
const SkSurfaceProps* surfaceProps,
uint32_t scalerContextFlags, const SkMatrix*) const;
SkGlyphCache* detachCache(const SkSurfaceProps* surfaceProps, uint32_t scalerContextFlags,
SkGlyphCache* detachCache(const SkSurfaceProps* surfaceProps,
uint32_t scalerContextFlags,
const SkMatrix*) const;
void descriptorProc(const SkSurfaceProps* surfaceProps, uint32_t scalerContextFlags,

View File

@ -26,6 +26,7 @@
#include "SkRasterClip.h"
#include "SkRectPriv.h"
#include "SkRRect.h"
#include "SkScalerContext.h"
#include "SkScan.h"
#include "SkShader.h"
#include "SkString.h"
@ -1495,10 +1496,10 @@ private:
////////////////////////////////////////////////////////////////////////////////////////////////////
uint32_t SkDraw::scalerContextFlags() const {
uint32_t flags = SkPaint::kBoostContrast_ScalerContextFlag;
SkScalerContextFlags SkDraw::scalerContextFlags() const {
SkScalerContextFlags flags = SkScalerContextFlags::kBoostContrast;
if (!fDst.colorSpace()) {
flags |= SkPaint::kFakeGamma_ScalerContextFlag;
flags = kFakeGammaAndBoostContrast;
}
return flags;
}

View File

@ -16,6 +16,7 @@
#include "SkPixmap.h"
#include "SkStrokeRec.h"
#include "SkVertices.h"
#include "SkScalerContext.h"
class SkBitmap;
class SkClipStack;
@ -143,7 +144,7 @@ private:
computeConservativeLocalClipBounds(SkRect* bounds) const;
/** Returns the current setting for using fake gamma and contrast. */
uint32_t SK_WARN_UNUSED_RESULT scalerContextFlags() const;
SkScalerContextFlags SK_WARN_UNUSED_RESULT scalerContextFlags() const;
public:
SkPixmap fDst;

View File

@ -263,12 +263,12 @@ public:
const SkSurfaceProps* surfaceProps,
const SkMatrix* matrix)
: INHERITED(paint.detachCache(surfaceProps,
SkPaint::kFakeGammaAndBoostContrast_ScalerContextFlags,
SkScalerContextFlags::kFakeGammaAndBoostContrast,
matrix))
{}
SkAutoGlyphCache(const SkPaint& paint,
const SkSurfaceProps* surfaceProps,
uint32_t scalerContextFlags,
SkScalerContextFlags scalerContextFlags,
const SkMatrix* matrix)
: INHERITED(paint.detachCache(surfaceProps, scalerContextFlags, matrix))
{}
@ -281,7 +281,7 @@ public:
SkAutoGlyphCacheNoGamma(const SkPaint& paint,
const SkSurfaceProps* surfaceProps,
const SkMatrix* matrix)
: SkAutoGlyphCache(paint, surfaceProps, SkPaint::kNone_ScalerContextFlags, matrix)
: SkAutoGlyphCache(paint, surfaceProps, SkScalerContextFlags::kNone, matrix)
{}
};
#define SkAutoGlyphCache(...) SK_REQUIRE_LOCAL_VAR(SkAutoGlyphCache)

View File

@ -62,7 +62,7 @@ void SkOverdrawCanvas::onDrawText(const void* text, size_t byteLength, SkScalar
ProcessOneGlyphBounds processBounds(this);
SkSurfaceProps props(0, kUnknown_SkPixelGeometry);
this->getProps(&props);
SkAutoGlyphCache cache(paint, &props, 0, &this->getTotalMatrix());
SkAutoGlyphCache cache(paint, &props, SkScalerContextFlags::kNone, &this->getTotalMatrix());
SkFindAndPlaceGlyph::ProcessText(paint.getTextEncoding(), (const char*) text, byteLength,
SkPoint::Make(x, y), SkMatrix(), paint.getTextAlign(),
cache.get(), processBounds);
@ -74,7 +74,7 @@ void SkOverdrawCanvas::drawPosTextCommon(const void* text, size_t byteLength, co
ProcessOneGlyphBounds processBounds(this);
SkSurfaceProps props(0, kUnknown_SkPixelGeometry);
this->getProps(&props);
SkAutoGlyphCache cache(paint, &props, 0, &this->getTotalMatrix());
SkAutoGlyphCache cache(paint, &props, SkScalerContextFlags::kNone, &this->getTotalMatrix());
SkFindAndPlaceGlyph::ProcessPosText(paint.getTextEncoding(), (const char*) text, byteLength,
SkPoint::Make(0, 0), SkMatrix(), (const SkScalar*) pos, 2,
paint.getTextAlign(), cache.get(), processBounds);

View File

@ -936,7 +936,8 @@ SkScalar SkPaint::getFontMetrics(FontMetrics* metrics, SkScalar zoom) const {
metrics = &storage;
}
paint.descriptorProc(nullptr, kNone_ScalerContextFlags, zoomPtr, FontMetricsDescProc, metrics);
paint.descriptorProc(nullptr, SkScalerContextFlags::kNone, zoomPtr,
FontMetricsDescProc, metrics);
if (scale) {
SkPaintPriv::ScaleFontMetrics(metrics, scale);
@ -1216,11 +1217,6 @@ SkRect SkPaint::getFontBounds() const {
return bounds;
}
static void add_flattenable(SkDescriptor* desc, uint32_t tag,
SkBinaryWriteBuffer* buffer) {
buffer->writeToMemory(desc->addEntry(tag, buffer->bytesWritten(), nullptr));
}
static SkMask::Format compute_mask_format(const SkPaint& paint) {
uint32_t flags = paint.getFlags();
@ -1303,10 +1299,12 @@ static SkScalar sk_relax(SkScalar x) {
return n / 1024.0f;
}
void SkScalerContext::MakeRec(const SkPaint& paint,
const SkSurfaceProps* surfaceProps,
const SkMatrix* deviceMatrix,
SkScalerContextRec* rec) {
void SkScalerContext::MakeRecAndEffects(const SkPaint& paint,
const SkSurfaceProps* surfaceProps,
const SkMatrix* deviceMatrix,
SkScalerContextFlags scalerContextFlags,
SkScalerContextRec* rec,
SkScalerContextEffects* effects) {
SkASSERT(deviceMatrix == nullptr || !deviceMatrix->hasPerspective());
SkTypeface* typeface = paint.getTypeface();
@ -1440,35 +1438,80 @@ void SkScalerContext::MakeRec(const SkPaint& paint,
rec->setLuminanceColor(paint.computeLuminanceColor());
//For now always set the paint gamma equal to the device gamma.
//The math in SkMaskGamma can handle them being different,
//but it requires superluminous masks when
//Ex : deviceGamma(x) < paintGamma(x) and x is sufficiently large.
// For now always set the paint gamma equal to the device gamma.
// The math in SkMaskGamma can handle them being different,
// but it requires superluminous masks when
// Ex : deviceGamma(x) < paintGamma(x) and x is sufficiently large.
rec->setDeviceGamma(SK_GAMMA_EXPONENT);
rec->setPaintGamma(SK_GAMMA_EXPONENT);
#ifdef SK_GAMMA_CONTRAST
rec->setContrast(SK_GAMMA_CONTRAST);
#else
/**
* A value of 0.5 for SK_GAMMA_CONTRAST appears to be a good compromise.
* With lower values small text appears washed out (though correctly so).
* With higher values lcd fringing is worse and the smoothing effect of
* partial coverage is diminished.
*/
// A value of 0.5 for SK_GAMMA_CONTRAST appears to be a good compromise.
// With lower values small text appears washed out (though correctly so).
// With higher values lcd fringing is worse and the smoothing effect of
// partial coverage is diminished.
rec->setContrast(0.5f);
#endif
rec->fReservedAlign = 0;
/* Allow the fonthost to modify our rec before we use it as a key into the
cache. This way if we're asking for something that they will ignore,
they can modify our rec up front, so we don't create duplicate cache
entries.
*/
// Allow the fonthost to modify our rec before we use it as a key into the
// cache. This way if we're asking for something that they will ignore,
// they can modify our rec up front, so we don't create duplicate cache
// entries.
typeface->onFilterRec(rec);
// be sure to call PostMakeRec(rec) before you actually use it!
if (!SkToBool(scalerContextFlags & SkScalerContextFlags::kFakeGamma)) {
rec->ignoreGamma();
}
if (!SkToBool(scalerContextFlags & SkScalerContextFlags::kBoostContrast)) {
rec->setContrast(0);
}
new (effects) SkScalerContextEffects{paint};
if (effects->fPathEffect) {
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 (effects->fMaskFilter) {
// force antialiasing with maskfilters
rec->fMaskFormat = SkMask::kA8_Format;
// 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();
}
// If we're asking for A8, we force the colorlum to be gray, since that
// limits the number of unique entries, and the scaler will only look at
// the lum of one of them.
switch (rec->fMaskFormat) {
case SkMask::kLCD16_Format: {
// filter down the luminance color to a finite number of bits
SkColor color = rec->getLuminanceColor();
rec->setLuminanceColor(SkMaskGamma::CanonicalColor(color));
break;
}
case SkMask::kA8_Format: {
// filter down the luminance to a single component, since A8 can't
// use per-component information
SkColor color = rec->getLuminanceColor();
U8CPU lum = SkComputeLuminance(SkColorGetR(color),
SkColorGetG(color),
SkColorGetB(color));
// reduce to our finite number of bits
color = SkColorSetRGB(lum, lum, lum);
rec->setLuminanceColor(SkMaskGamma::CanonicalColor(color));
break;
}
case SkMask::kBW_Format:
// No need to differentiate gamma or apply contrast if we're BW
rec->ignorePreBlend();
break;
}
}
/**
@ -1505,216 +1548,36 @@ static const SkMaskGamma& cachedMaskGamma(SkScalar contrast, SkScalar paintGamma
return *gMaskGamma;
}
/**
* We ensure that the rec is self-consistent and efficient (where possible)
*/
void SkScalerContext::PostMakeRec(const SkPaint&, SkScalerContextRec* rec) {
/**
* If we're asking for A8, we force the colorlum to be gray, since that
* limits the number of unique entries, and the scaler will only look at
* the lum of one of them.
*/
switch (rec->fMaskFormat) {
case SkMask::kLCD16_Format: {
// filter down the luminance color to a finite number of bits
SkColor color = rec->getLuminanceColor();
rec->setLuminanceColor(SkMaskGamma::CanonicalColor(color));
break;
}
case SkMask::kA8_Format: {
// filter down the luminance to a single component, since A8 can't
// use per-component information
SkColor color = rec->getLuminanceColor();
U8CPU lum = SkComputeLuminance(SkColorGetR(color),
SkColorGetG(color),
SkColorGetB(color));
// reduce to our finite number of bits
color = SkColorSetRGB(lum, lum, lum);
rec->setLuminanceColor(SkMaskGamma::CanonicalColor(color));
break;
}
case SkMask::kBW_Format:
// No need to differentiate gamma or apply contrast if we're BW
rec->ignorePreBlend();
break;
}
}
#define MIN_SIZE_FOR_EFFECT_BUFFER 1024
#ifdef SK_DEBUG
#define TEST_DESC
#endif
static void write_out_descriptor(SkDescriptor* desc, const SkScalerContextRec& rec,
const SkPathEffect* pe, SkBinaryWriteBuffer* peBuffer,
const SkMaskFilter* mf, SkBinaryWriteBuffer* mfBuffer,
size_t descSize) {
desc->init();
desc->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
if (pe) {
add_flattenable(desc, kPathEffect_SkDescriptorTag, peBuffer);
}
if (mf) {
add_flattenable(desc, kMaskFilter_SkDescriptorTag, mfBuffer);
}
desc->computeChecksum();
}
static size_t fill_out_rec(const SkPaint& paint, SkScalerContextRec* rec,
const SkSurfaceProps* surfaceProps,
bool fakeGamma, bool boostContrast,
const SkMatrix* deviceMatrix,
const SkPathEffect* pe, SkBinaryWriteBuffer* peBuffer,
const SkMaskFilter* mf, SkBinaryWriteBuffer* mfBuffer) {
SkScalerContext::MakeRec(paint, surfaceProps, deviceMatrix, rec);
if (!fakeGamma) {
rec->ignoreGamma();
}
if (!boostContrast) {
rec->setContrast(0);
}
int entryCount = 1;
size_t descSize = sizeof(*rec);
if (pe) {
pe->flatten(*peBuffer);
descSize += peBuffer->bytesWritten();
entryCount += 1;
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) {
mf->flatten(*mfBuffer);
descSize += mfBuffer->bytesWritten();
entryCount += 1;
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();
}
///////////////////////////////////////////////////////////////////////////
// Now that we're done tweaking the rec, call the PostMakeRec cleanup
SkScalerContext::PostMakeRec(paint, rec);
descSize += SkDescriptor::ComputeOverhead(entryCount);
return descSize;
}
#ifdef TEST_DESC
static void test_desc(const SkScalerContextRec& rec,
const SkPathEffect* pe, SkBinaryWriteBuffer* peBuffer,
const SkMaskFilter* mf, SkBinaryWriteBuffer* mfBuffer,
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(desc1, kPathEffect_SkDescriptorTag, peBuffer);
add_flattenable(desc2, kPathEffect_SkDescriptorTag, peBuffer);
}
if (mf) {
add_flattenable(desc1, kMaskFilter_SkDescriptorTag, mfBuffer);
add_flattenable(desc2, kMaskFilter_SkDescriptorTag, mfBuffer);
}
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 */
void SkPaint::getScalerContextDescriptor(SkScalerContextEffects* effects,
SkAutoDescriptor* ad,
const SkSurfaceProps& surfaceProps,
const SkSurfaceProps* surfaceProps,
uint32_t scalerContextFlags,
const SkMatrix* deviceMatrix) const {
SkScalerContextRec rec;
SkPathEffect* pe = this->getPathEffect();
SkMaskFilter* mf = this->getMaskFilter();
SkBinaryWriteBuffer peBuffer, mfBuffer;
size_t descSize = fill_out_rec(*this, &rec, &surfaceProps,
SkToBool(scalerContextFlags & kFakeGamma_ScalerContextFlag),
SkToBool(scalerContextFlags & kBoostContrast_ScalerContextFlag),
deviceMatrix, pe, &peBuffer, mf, &mfBuffer);
ad->reset(descSize);
SkDescriptor* desc = ad->getDesc();
write_out_descriptor(desc, rec, pe, &peBuffer, mf, &mfBuffer, descSize);
SkASSERT(descSize == desc->getLength());
#ifdef TEST_DESC
test_desc(rec, pe, &peBuffer, mf, &mfBuffer, desc, descSize);
#endif
effects->fPathEffect = pe;
effects->fMaskFilter = mf;
SkScalerContext::MakeRecAndEffects(
*this, surfaceProps, deviceMatrix, (SkScalerContextFlags)scalerContextFlags, &rec, effects);
auto alloc = [ad](size_t size) {
ad->reset(size);
return ad->getDesc();
};
SkScalerContext::CreateDescriptorGivenRecAndEffects(rec, *effects, alloc);
}
/*
* 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 SkSurfaceProps* surfaceProps,
uint32_t scalerContextFlags,
const SkMatrix* deviceMatrix,
void (*proc)(SkTypeface*, const SkScalerContextEffects&,
const SkDescriptor*, void*),
void* context) const {
SkScalerContextRec rec;
SkAutoDescriptor ad;
SkScalerContextEffects effects;
SkPathEffect* pe = this->getPathEffect();
SkMaskFilter* mf = this->getMaskFilter();
this->getScalerContextDescriptor(&effects, &ad, surfaceProps, scalerContextFlags,
deviceMatrix);
SkBinaryWriteBuffer peBuffer, mfBuffer, raBuffer;
size_t descSize = fill_out_rec(*this, &rec, surfaceProps,
SkToBool(scalerContextFlags & kFakeGamma_ScalerContextFlag),
SkToBool(scalerContextFlags & kBoostContrast_ScalerContextFlag),
deviceMatrix, pe, &peBuffer, mf, &mfBuffer);
SkAutoDescriptor ad(descSize);
SkDescriptor* desc = ad.getDesc();
write_out_descriptor(desc, rec, pe, &peBuffer, mf, &mfBuffer, descSize);
SkASSERT(descSize == desc->getLength());
#ifdef TEST_DESC
test_desc(rec, pe, &peBuffer, mf, &mfBuffer, desc, descSize);
#endif
proc(fTypeface.get(), { pe, mf }, desc, context);
auto desc = ad.getDesc();
proc(fTypeface.get(), effects, desc, context);
}
SkGlyphCache* SkPaint::detachCache(const SkSurfaceProps* surfaceProps,
@ -1725,6 +1588,7 @@ SkGlyphCache* SkPaint::detachCache(const SkSurfaceProps* surfaceProps,
return cache;
}
/**
* Expands fDeviceGamma, fPaintGamma, fContrast, and fLumBits into a mask pre-blend.
*/
@ -1768,6 +1632,106 @@ bool SkScalerContext::GetGammaLUTData(SkScalar contrast, SkScalar paintGamma, Sk
return true;
}
size_t SkScalerContext::CalculateSizeAndFlatten(
const SkScalerContextRec& rec,
const SkScalerContextEffects& effects,
SkBinaryWriteBuffer* pathEffectBuffer,
SkBinaryWriteBuffer* maskFilterBuffer) {
size_t descSize = sizeof(rec);
int entryCount = 1;
if (effects.fPathEffect) {
effects.fPathEffect->flatten(*pathEffectBuffer);
descSize += pathEffectBuffer->bytesWritten();
entryCount += 1;
}
if (effects.fMaskFilter) {
effects.fMaskFilter->flatten(*maskFilterBuffer);
descSize += maskFilterBuffer->bytesWritten();
entryCount += 1;
}
descSize += SkDescriptor::ComputeOverhead(entryCount);
return descSize;
}
#ifdef SK_DEBUG
#define TEST_DESC
#endif
#ifdef TEST_DESC
static void test_desc(const SkScalerContextRec& rec,
const SkScalerContextEffects& effects,
SkBinaryWriteBuffer* peBuffer,
SkBinaryWriteBuffer* mfBuffer,
const SkDescriptor* 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(desc->getLength());
SkAutoDescriptor ad2(desc->getLength());
SkDescriptor* desc1 = ad1.getDesc();
SkDescriptor* desc2 = ad2.getDesc();
memset(desc1, 0x00, desc->getLength());
memset(desc2, 0xFF, desc->getLength());
desc1->init();
desc2->init();
desc1->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
desc2->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
auto add_flattenable = [](SkDescriptor* desc, uint32_t tag,
SkBinaryWriteBuffer* buffer) {
buffer->writeToMemory(desc->addEntry(tag, buffer->bytesWritten(), nullptr));
};
if (effects.fPathEffect) {
add_flattenable(desc1, kPathEffect_SkDescriptorTag, peBuffer);
add_flattenable(desc2, kPathEffect_SkDescriptorTag, peBuffer);
}
if (effects.fMaskFilter) {
add_flattenable(desc1, kMaskFilter_SkDescriptorTag, mfBuffer);
add_flattenable(desc2, kMaskFilter_SkDescriptorTag, mfBuffer);
}
SkASSERT(desc->getLength() == desc1->getLength());
SkASSERT(desc->getLength() == desc2->getLength());
desc1->computeChecksum();
desc2->computeChecksum();
SkASSERT(!memcmp(desc, desc1, desc->getLength()));
SkASSERT(!memcmp(desc, desc2, desc->getLength()));
}
#endif
void SkScalerContext::GenerateDescriptor(const SkScalerContextRec& rec,
const SkScalerContextEffects& effects,
SkBinaryWriteBuffer* pathEffectBuffer,
SkBinaryWriteBuffer* maskFilterBuffer,
SkDescriptor* desc) {
desc->init();
desc->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
auto add = [&desc](uint32_t tag, SkBinaryWriteBuffer* buffer) {
buffer->writeToMemory(desc->addEntry(tag, buffer->bytesWritten(), nullptr));
};
if (effects.fPathEffect) {
add(kPathEffect_SkDescriptorTag, pathEffectBuffer);
}
if (effects.fMaskFilter) {
add(kMaskFilter_SkDescriptorTag, maskFilterBuffer);
}
desc->computeChecksum();
#ifdef TEST_DESC
test_desc(rec, effects, pathEffectBuffer, maskFilterBuffer, desc);
#endif
}
///////////////////////////////////////////////////////////////////////////////
#include "SkStream.h"
@ -2207,8 +2171,7 @@ SkTextBaseIter::SkTextBaseIter(const char text[], size_t length,
}
// SRGBTODO: Is this correct?
fCache = fPaint.detachCache(nullptr, SkPaint::kFakeGammaAndBoostContrast_ScalerContextFlags,
nullptr);
fCache = fPaint.detachCache(nullptr, SkScalerContextFlags::kFakeGammaAndBoostContrast, nullptr);
SkPaint::Style style = SkPaint::kFill_Style;
sk_sp<SkPathEffect> pe;

View File

@ -10,19 +10,31 @@
#include "SkGlyph.h"
#include "SkMask.h"
#include "SkMaskFilter.h"
#include "SkMaskGamma.h"
#include "SkMatrix.h"
#include "SkPaint.h"
#include "SkTypeface.h"
#include "SkWriteBuffer.h"
class SkDescriptor;
class SkMaskFilter;
class SkPathEffect;
enum SkScalerContextFlags : uint32_t {
kNone = 0,
kFakeGamma = 1 << 0,
kBoostContrast = 1 << 1,
kFakeGammaAndBoostContrast = kFakeGamma | kBoostContrast,
};
struct SkScalerContextEffects {
SkScalerContextEffects() : fPathEffect(nullptr), fMaskFilter(nullptr) {}
SkScalerContextEffects(SkPathEffect* pe, SkMaskFilter* mf)
: fPathEffect(pe), fMaskFilter(mf) {}
explicit SkScalerContextEffects(const SkPaint& paint)
: fPathEffect(paint.getPathEffect())
, fMaskFilter(paint.getMaskFilter()) {}
SkPathEffect* fPathEffect;
SkMaskFilter* fMaskFilter;
@ -34,6 +46,7 @@ enum SkAxisAlignment {
kY_SkAxisAlignment
};
/*
* To allow this to be forward-declared, it must be its own typename, rather
* than a nested struct inside SkScalerContext (where it started).
@ -101,7 +114,7 @@ struct SkScalerContextRec {
// Warning: when adding members note that the size of this structure
// must be a multiple of 4. SkDescriptor requires that its arguments be
// multiples of four and this structure is put in an SkDescriptor in
// SkPaint::MakeRec.
// SkPaint::MakeRecAndEffects.
void getMatrixFrom2x2(SkMatrix*) const;
void getLocalMatrix(SkMatrix*) const;
@ -260,9 +273,18 @@ public:
static bool GetGammaLUTData(SkScalar contrast, SkScalar paintGamma, SkScalar deviceGamma,
uint8_t* data);
static void MakeRec(const SkPaint&, const SkSurfaceProps* surfaceProps,
const SkMatrix*, SkScalerContextRec* rec);
static inline void PostMakeRec(const SkPaint&, SkScalerContextRec*);
static void MakeRecAndEffects(const SkPaint& paint,
const SkSurfaceProps* surfaceProps,
const SkMatrix* deviceMatrix,
SkScalerContextFlags scalerContextFlags,
SkScalerContextRec* rec,
SkScalerContextEffects* effects);
template <typename A>
static auto CreateDescriptorGivenRecAndEffects(
const SkScalerContextRec &rec,
const SkScalerContextEffects &effects,
A alloc) -> decltype(alloc((size_t)0));
static SkMaskGamma::PreBlend GetMaskPreBlend(const SkScalerContextRec& rec);
@ -331,6 +353,16 @@ protected:
void forceOffGenerateImageFromPath() { fGenerateImageFromPath = false; }
private:
static size_t CalculateSizeAndFlatten(const SkScalerContextRec& rec,
const SkScalerContextEffects& effects,
SkBinaryWriteBuffer* pathEffectBuffer,
SkBinaryWriteBuffer* maskFilterBuffer);
static void GenerateDescriptor(const SkScalerContextRec& rec,
const SkScalerContextEffects& effects,
SkBinaryWriteBuffer* pathEffectBuffer,
SkBinaryWriteBuffer* maskFilterBuffer,
SkDescriptor* desc);
friend class SkRandomScalerContext; // For debug purposes
// never null
@ -357,6 +389,22 @@ private:
const SkMaskGamma::PreBlend fPreBlendForFilter;
};
template <typename A>
inline auto SkScalerContext::CreateDescriptorGivenRecAndEffects(
const SkScalerContextRec &rec,
const SkScalerContextEffects &effects,
A alloc) -> decltype(alloc((size_t)0)) {
SkBinaryWriteBuffer peBuffer, mfBuffer;
auto desc = alloc(CalculateSizeAndFlatten(rec, effects, &peBuffer, &mfBuffer));
GenerateDescriptor(rec, effects, &peBuffer, &mfBuffer, &(*desc));
return desc;
}
#define kRec_SkDescriptorTag SkSetFourByteTag('s', 'r', 'e', 'c')
#define kPathEffect_SkDescriptorTag SkSetFourByteTag('p', 't', 'h', 'e')
#define kMaskFilter_SkDescriptorTag SkSetFourByteTag('m', 's', 'k', 'f')

View File

@ -84,7 +84,7 @@ protected:
}
};
}
} // namespace
SkFontStyle SkTypeface::FromOldStyle(Style oldStyle) {
return SkFontStyle((oldStyle & SkTypeface::kBold) ? SkFontStyle::kBold_Weight
@ -340,7 +340,9 @@ bool SkTypeface::onComputeBounds(SkRect* bounds) const {
paint.setLinearText(true);
SkScalerContextRec rec;
SkScalerContext::MakeRec(paint, nullptr, nullptr, &rec);
SkScalerContextEffects effects;
SkScalerContext::MakeRecAndEffects(
paint, nullptr, nullptr, SkScalerContextFlags::kNone, &rec, &effects);
SkAutoDescriptor ad(sizeof(rec) + SkDescriptor::ComputeOverhead(1));
SkDescriptor* desc = ad.getDesc();

View File

@ -49,7 +49,7 @@ sk_sp<GrAtlasTextBlob> GrAtlasTextBlob::Make(GrMemoryPool* pool, int glyphCount,
SkGlyphCache* GrAtlasTextBlob::setupCache(int runIndex,
const SkSurfaceProps& props,
uint32_t scalerContextFlags,
SkScalerContextFlags scalerContextFlags,
const SkPaint& skPaint,
const SkMatrix* viewMatrix) {
GrAtlasTextBlob::Run* run = &fRuns[runIndex];
@ -58,7 +58,7 @@ SkGlyphCache* GrAtlasTextBlob::setupCache(int runIndex,
SkAutoDescriptor* desc = run->fOverrideDescriptor.get() ? run->fOverrideDescriptor.get() :
&run->fDescriptor;
SkScalerContextEffects effects;
skPaint.getScalerContextDescriptor(&effects, desc, props, scalerContextFlags, viewMatrix);
skPaint.getScalerContextDescriptor(&effects, desc, &props, scalerContextFlags, viewMatrix);
run->fTypeface.reset(SkSafeRef(skPaint.getTypeface()));
run->fPathEffect = sk_ref_sp(effects.fPathEffect);
run->fMaskFilter = sk_ref_sp(effects.fMaskFilter);

View File

@ -163,7 +163,7 @@ public:
SkGlyphCache* setupCache(int runIndex,
const SkSurfaceProps& props,
uint32_t scalerContextFlags,
SkScalerContextFlags scalerContextFlags,
const SkPaint& skPaint,
const SkMatrix* viewMatrix);

View File

@ -78,13 +78,14 @@ SkColor GrAtlasTextContext::ComputeCanonicalColor(const SkPaint& paint, bool lcd
return canonicalColor;
}
uint32_t GrAtlasTextContext::ComputeScalerContextFlags(const GrColorSpaceInfo& colorSpaceInfo) {
SkScalerContextFlags GrAtlasTextContext::ComputeScalerContextFlags(
const GrColorSpaceInfo& colorSpaceInfo) {
// If we're doing gamma-correct rendering, then we can disable the gamma hacks.
// Otherwise, leave them on. In either case, we still want the contrast boost:
if (colorSpaceInfo.isGammaCorrect()) {
return SkPaint::kBoostContrast_ScalerContextFlag;
return SkScalerContextFlags::kBoostContrast;
} else {
return SkPaint::kFakeGammaAndBoostContrast_ScalerContextFlags;
return SkScalerContextFlags::kFakeGammaAndBoostContrast;
}
}
@ -120,7 +121,7 @@ void GrAtlasTextContext::drawTextBlob(GrContext* context, GrTextUtils::Target* t
bool canCache = !(skPaint.getPathEffect() ||
(mf && !mf->asABlur(&blurRec)) ||
drawFilter);
uint32_t scalerContextFlags = ComputeScalerContextFlags(target->colorSpaceInfo());
SkScalerContextFlags scalerContextFlags = ComputeScalerContextFlags(target->colorSpaceInfo());
auto atlasGlyphCache = context->contextPriv().getAtlasGlyphCache();
GrTextBlobCache* textBlobCache = context->contextPriv().getTextBlobCache();
@ -192,7 +193,7 @@ void GrAtlasTextContext::regenerateTextBlob(GrAtlasTextBlob* cacheBlob,
GrAtlasGlyphCache* fontCache,
const GrShaderCaps& shaderCaps,
const GrTextUtils::Paint& paint,
uint32_t scalerContextFlags,
SkScalerContextFlags scalerContextFlags,
const SkMatrix& viewMatrix,
const SkSurfaceProps& props, const SkTextBlob* blob,
SkScalar x, SkScalar y,
@ -262,7 +263,7 @@ GrAtlasTextContext::makeDrawTextBlob(GrTextBlobCache* blobCache,
GrAtlasGlyphCache* fontCache,
const GrShaderCaps& shaderCaps,
const GrTextUtils::Paint& paint,
uint32_t scalerContextFlags,
SkScalerContextFlags scalerContextFlags,
const SkMatrix& viewMatrix,
const SkSurfaceProps& props,
const char text[], size_t byteLength,
@ -289,7 +290,7 @@ GrAtlasTextContext::makeDrawPosTextBlob(GrTextBlobCache* blobCache,
GrAtlasGlyphCache* fontCache,
const GrShaderCaps& shaderCaps,
const GrTextUtils::Paint& paint,
uint32_t scalerContextFlags,
SkScalerContextFlags scalerContextFlags,
const SkMatrix& viewMatrix,
const SkSurfaceProps& props,
const char text[], size_t byteLength,
@ -380,7 +381,8 @@ void GrAtlasTextContext::drawPosText(GrContext* context, GrTextUtils::Target* ta
void GrAtlasTextContext::DrawBmpText(GrAtlasTextBlob* blob, int runIndex,
GrAtlasGlyphCache* fontCache, const SkSurfaceProps& props,
const GrTextUtils::Paint& paint, uint32_t scalerContextFlags,
const GrTextUtils::Paint& paint,
SkScalerContextFlags scalerContextFlags,
const SkMatrix& viewMatrix, const char text[],
size_t byteLength, SkScalar x, SkScalar y) {
SkASSERT(byteLength == 0 || text != nullptr);
@ -413,7 +415,8 @@ void GrAtlasTextContext::DrawBmpText(GrAtlasTextBlob* blob, int runIndex,
void GrAtlasTextContext::DrawBmpPosText(GrAtlasTextBlob* blob, int runIndex,
GrAtlasGlyphCache* fontCache, const SkSurfaceProps& props,
const GrTextUtils::Paint& paint,
uint32_t scalerContextFlags, const SkMatrix& viewMatrix,
SkScalerContextFlags scalerContextFlags,
const SkMatrix& viewMatrix,
const char text[], size_t byteLength, const SkScalar pos[],
int scalarsPerPosition, const SkPoint& offset,
SkScalar textRatio) {
@ -580,7 +583,8 @@ void GrAtlasTextContext::initDistanceFieldPaint(GrAtlasTextBlob* blob,
void GrAtlasTextContext::drawDFText(GrAtlasTextBlob* blob, int runIndex,
GrAtlasGlyphCache* fontCache, const SkSurfaceProps& props,
const GrTextUtils::Paint& paint, uint32_t scalerContextFlags,
const GrTextUtils::Paint& paint,
SkScalerContextFlags scalerContextFlags,
const SkMatrix& viewMatrix, const char text[],
size_t byteLength, SkScalar x, SkScalar y) const {
SkASSERT(byteLength == 0 || text != nullptr);
@ -597,7 +601,7 @@ void GrAtlasTextContext::drawDFText(GrAtlasTextBlob* blob, int runIndex,
SkScalerContextEffects effects;
// We apply the fake-gamma by altering the distance in the shader, so we ignore the
// passed-in scaler context flags. (It's only used when we fall-back to bitmap text).
skPaint.getScalerContextDescriptor(&effects, &desc, props, SkPaint::kNone_ScalerContextFlags,
skPaint.getScalerContextDescriptor(&effects, &desc, &props, SkScalerContextFlags::kNone,
nullptr);
SkGlyphCache* origPaintCache =
SkGlyphCache::DetachCache(skPaint.getTypeface(), effects, desc.getDesc());
@ -654,7 +658,8 @@ void GrAtlasTextContext::drawDFText(GrAtlasTextBlob* blob, int runIndex,
void GrAtlasTextContext::drawDFPosText(GrAtlasTextBlob* blob, int runIndex,
GrAtlasGlyphCache* fontCache, const SkSurfaceProps& props,
const GrTextUtils::Paint& paint, uint32_t scalerContextFlags,
const GrTextUtils::Paint& paint,
SkScalerContextFlags scalerContextFlags,
const SkMatrix& viewMatrix, const char text[],
size_t byteLength, const SkScalar pos[],
int scalarsPerPosition, const SkPoint& offset) const {
@ -691,7 +696,7 @@ void GrAtlasTextContext::drawDFPosText(GrAtlasTextBlob* blob, int runIndex,
// We apply the fake-gamma by altering the distance in the shader, so we ignore the
// passed-in scaler context flags. (It's only used when we fall-back to bitmap text).
SkGlyphCache* cache =
blob->setupCache(runIndex, props, SkPaint::kNone_ScalerContextFlags, dfPaint, nullptr);
blob->setupCache(runIndex, props, SkScalerContextFlags::kNone, dfPaint, nullptr);
SkPaint::GlyphCacheProc glyphCacheProc =
SkPaint::GetGlyphCacheProc(dfPaint.getTextEncoding(), dfPaint.isDevKernText(), true);

View File

@ -62,50 +62,50 @@ private:
GrAtlasTextContext(const Options& options);
// sets up the descriptor on the blob and returns a detached cache. Client must attach
inline static SkColor ComputeCanonicalColor(const SkPaint&, bool lcd);
static SkColor ComputeCanonicalColor(const SkPaint&, bool lcd);
// Determines if we need to use fake gamma (and contrast boost):
inline static uint32_t ComputeScalerContextFlags(const GrColorSpaceInfo&);
static SkScalerContextFlags ComputeScalerContextFlags(const GrColorSpaceInfo&);
void regenerateTextBlob(GrAtlasTextBlob* bmp,
GrAtlasGlyphCache*,
const GrShaderCaps&,
const GrTextUtils::Paint&,
uint32_t scalerContextFlags,
SkScalerContextFlags scalerContextFlags,
const SkMatrix& viewMatrix,
const SkSurfaceProps&,
const SkTextBlob* blob, SkScalar x, SkScalar y,
SkDrawFilter* drawFilter) const;
inline static bool HasLCD(const SkTextBlob*);
static bool HasLCD(const SkTextBlob*);
inline sk_sp<GrAtlasTextBlob> makeDrawTextBlob(GrTextBlobCache*, GrAtlasGlyphCache*,
const GrShaderCaps&,
const GrTextUtils::Paint&,
uint32_t scalerContextFlags,
const SkMatrix& viewMatrix,
const SkSurfaceProps&,
const char text[], size_t byteLength,
SkScalar x, SkScalar y) const;
sk_sp<GrAtlasTextBlob> makeDrawTextBlob(GrTextBlobCache*, GrAtlasGlyphCache*,
const GrShaderCaps&,
const GrTextUtils::Paint&,
SkScalerContextFlags scalerContextFlags,
const SkMatrix& viewMatrix,
const SkSurfaceProps&,
const char text[], size_t byteLength,
SkScalar x, SkScalar y) const;
inline sk_sp<GrAtlasTextBlob> makeDrawPosTextBlob(GrTextBlobCache*, GrAtlasGlyphCache*,
const GrShaderCaps&,
const GrTextUtils::Paint&,
uint32_t scalerContextFlags,
const SkMatrix& viewMatrix,
const SkSurfaceProps&,
const char text[], size_t byteLength,
const SkScalar pos[],
int scalarsPerPosition,
const SkPoint& offset) const;
sk_sp<GrAtlasTextBlob> makeDrawPosTextBlob(GrTextBlobCache*, GrAtlasGlyphCache*,
const GrShaderCaps&,
const GrTextUtils::Paint&,
SkScalerContextFlags scalerContextFlags,
const SkMatrix& viewMatrix,
const SkSurfaceProps&,
const char text[], size_t byteLength,
const SkScalar pos[],
int scalarsPerPosition,
const SkPoint& offset) const;
// Functions for appending BMP text to GrAtlasTextBlob
static void DrawBmpText(GrAtlasTextBlob*, int runIndex, GrAtlasGlyphCache*,
const SkSurfaceProps&, const GrTextUtils::Paint& paint,
uint32_t scalerContextFlags, const SkMatrix& viewMatrix,
SkScalerContextFlags scalerContextFlags, const SkMatrix& viewMatrix,
const char text[], size_t byteLength, SkScalar x, SkScalar y);
static void DrawBmpPosText(GrAtlasTextBlob*, int runIndex, GrAtlasGlyphCache*,
const SkSurfaceProps&, const GrTextUtils::Paint& paint,
uint32_t scalerContextFlags, const SkMatrix& viewMatrix,
SkScalerContextFlags scalerContextFlags, const SkMatrix& viewMatrix,
const char text[], size_t byteLength, const SkScalar pos[],
int scalarsPerPosition, const SkPoint& offset,
SkScalar textRatio);
@ -115,13 +115,14 @@ private:
const SkSurfaceProps& props, const GrShaderCaps& caps) const;
void drawDFText(GrAtlasTextBlob* blob, int runIndex, GrAtlasGlyphCache*, const SkSurfaceProps&,
const GrTextUtils::Paint& paint, uint32_t scalerContextFlags,
const GrTextUtils::Paint& paint, SkScalerContextFlags scalerContextFlags,
const SkMatrix& viewMatrix, const char text[], size_t byteLength, SkScalar x,
SkScalar y) const;
void drawDFPosText(GrAtlasTextBlob* blob, int runIndex, GrAtlasGlyphCache*,
const SkSurfaceProps&, const GrTextUtils::Paint& paint,
uint32_t scalerContextFlags, const SkMatrix& viewMatrix, const char text[],
SkScalerContextFlags scalerContextFlags,
const SkMatrix& viewMatrix, const char text[],
size_t byteLength, const SkScalar pos[], int scalarsPerPosition,
const SkPoint& offset) const;
@ -147,8 +148,8 @@ private:
bool fDistanceFieldVerticesAlwaysHaveW;
#if GR_TEST_UTILS
static const uint32_t kTextBlobOpScalerContextFlags =
SkPaint::kFakeGammaAndBoostContrast_ScalerContextFlags;
static const SkScalerContextFlags kTextBlobOpScalerContextFlags =
SkScalerContextFlags::kFakeGammaAndBoostContrast;
GR_DRAW_OP_TEST_FRIEND(GrAtlasTextOp);
#endif
};

View File

@ -605,7 +605,7 @@ void GrStencilAndCoverTextContext::TextRun::draw(GrContext* ctx,
SkGlyphCache* GrStencilAndCoverTextContext::TextRun::getGlyphCache() const {
if (!fDetachedGlyphCache) {
fDetachedGlyphCache = fFont.detachCache(nullptr, SkPaint::kNone_ScalerContextFlags,
fDetachedGlyphCache = fFont.detachCache(nullptr, SkScalerContextFlags::kNone,
nullptr);
}
return fDetachedGlyphCache;