Use SkGlyphRunListIterator in gpu
Instead of using the text blob through the stack start using the glyph run list. This CL is similar to a portion of https://skia-review.googlesource.com/c/skia/+/137224 which was reverted. Change-Id: I1f0619bd2d13523f9af1a68ab27fb26abd086add Reviewed-on: https://skia-review.googlesource.com/141543 Commit-Queue: Herb Derby <herb@google.com> Reviewed-by: Jim Van Verth <jvanverth@google.com>
This commit is contained in:
parent
297c3c8e85
commit
cddab25218
@ -45,7 +45,7 @@ SkGlyphRun::SkGlyphRun(SkPaint&& runPaint,
|
||||
SkSpan<const uint32_t> clusters)
|
||||
: fUniqueGlyphIDIndices{denseIndices}
|
||||
, fPositions{positions}
|
||||
, fTemporaryShuntGlyphIDs{glyphIDs}
|
||||
, fGlyphIDs{glyphIDs}
|
||||
, fUniqueGlyphIDs{uniqueGlyphIDs}
|
||||
, fText{text}
|
||||
, fClusters{clusters}
|
||||
@ -66,10 +66,10 @@ void SkGlyphRun::eachGlyphToGlyphRun(SkGlyphRun::PerGlyph perGlyph) {
|
||||
SkSpan<const uint32_t>{}
|
||||
};
|
||||
|
||||
auto runSize = fTemporaryShuntGlyphIDs.size();
|
||||
auto runSize = fGlyphIDs.size();
|
||||
auto runPaint = run.mutablePaint();
|
||||
for (size_t i = 0; i < runSize; i++) {
|
||||
glyphID = fTemporaryShuntGlyphIDs[i];
|
||||
glyphID = fGlyphIDs[i];
|
||||
point = fPositions[i];
|
||||
perGlyph(&run, runPaint);
|
||||
}
|
||||
@ -80,21 +80,21 @@ void SkGlyphRun::temporaryShuntToDrawPosText(SkBaseDevice* device, SkPoint origi
|
||||
|
||||
auto pos = (const SkScalar*) this->positions().data();
|
||||
|
||||
if (!fTemporaryShuntGlyphIDs.empty()) {
|
||||
if (!fGlyphIDs.empty()) {
|
||||
device->drawPosText(
|
||||
fTemporaryShuntGlyphIDs.data(), fTemporaryShuntGlyphIDs.size() * sizeof(SkGlyphID),
|
||||
fGlyphIDs.data(), fGlyphIDs.size() * sizeof(SkGlyphID),
|
||||
pos, 2, origin, fRunPaint);
|
||||
}
|
||||
}
|
||||
|
||||
void SkGlyphRun::temporaryShuntToCallback(TemporaryShuntCallback callback) {
|
||||
auto bytes = (const char *)fTemporaryShuntGlyphIDs.data();
|
||||
auto bytes = (const char *)fGlyphIDs.data();
|
||||
auto pos = (const SkScalar*) this->positions().data();
|
||||
callback(fTemporaryShuntGlyphIDs.size(), bytes, pos);
|
||||
callback(fGlyphIDs.size(), bytes, pos);
|
||||
}
|
||||
|
||||
void SkGlyphRun::filloutGlyphsAndPositions(SkGlyphID* glyphIDs, SkPoint* positions) {
|
||||
memcpy(glyphIDs, fTemporaryShuntGlyphIDs.data(), fTemporaryShuntGlyphIDs.size_bytes());
|
||||
memcpy(glyphIDs, fGlyphIDs.data(), fGlyphIDs.size_bytes());
|
||||
memcpy(positions, fPositions.data(), fPositions.size_bytes());
|
||||
}
|
||||
|
||||
@ -111,7 +111,7 @@ SkGlyphRunList::SkGlyphRunList(
|
||||
, fGlyphRuns{glyphRunList} { }
|
||||
|
||||
SkGlyphRunList::SkGlyphRunList(SkGlyphRun* glyphRun)
|
||||
: fOriginalPaint{nullptr}
|
||||
: fOriginalPaint{&glyphRun->paint()}
|
||||
, fOriginalTextBlob{nullptr}
|
||||
, fOrigin{SkPoint::Make(0, 0)}
|
||||
, fGlyphRuns{SkSpan<SkGlyphRun>{glyphRun, 1}} {}
|
||||
|
@ -16,6 +16,8 @@
|
||||
#include "SkMask.h"
|
||||
#include "SkPath.h"
|
||||
#include "SkPoint.h"
|
||||
#include "SkTemplates.h"
|
||||
#include "SkTextBlob.h"
|
||||
#include "SkTypes.h"
|
||||
|
||||
class SkBaseDevice;
|
||||
@ -67,10 +69,13 @@ public:
|
||||
void temporaryShuntToCallback(TemporaryShuntCallback callback);
|
||||
void filloutGlyphsAndPositions(SkGlyphID* glyphIDs, SkPoint* positions);
|
||||
|
||||
size_t runSize() const { return fTemporaryShuntGlyphIDs.size(); }
|
||||
size_t runSize() const { return fGlyphIDs.size(); }
|
||||
SkSpan<const SkPoint> positions() const { return fPositions; }
|
||||
SkSpan<const SkGlyphID> shuntGlyphsIDs() const { return fGlyphIDs; }
|
||||
const SkPaint& paint() const { return fRunPaint; }
|
||||
SkPaint* mutablePaint() { return &fRunPaint; }
|
||||
SkSpan<const uint32_t> clusters() const { return fClusters; }
|
||||
SkSpan<const char> text() const { return fText; }
|
||||
|
||||
private:
|
||||
//
|
||||
@ -78,8 +83,8 @@ private:
|
||||
//
|
||||
const SkSpan<const SkPoint> fPositions;
|
||||
// This is temporary while converting from the old per glyph code to the bulk code.
|
||||
const SkSpan<const SkGlyphID> fTemporaryShuntGlyphIDs;
|
||||
// The unique glyphs from fTemporaryShuntGlyphIDs.
|
||||
const SkSpan<const SkGlyphID> fGlyphIDs;
|
||||
// The unique glyphs from fGlyphIDs.
|
||||
const SkSpan<const SkGlyphID> fUniqueGlyphIDs;
|
||||
// Original text from SkTextBlob if present. Will be empty of not present.
|
||||
const SkSpan<const char> fText;
|
||||
@ -139,6 +144,30 @@ public:
|
||||
|
||||
};
|
||||
|
||||
class SkGlyphRunListIterator {
|
||||
public:
|
||||
explicit SkGlyphRunListIterator(SkGlyphRunList* list) : fList{*list} {}
|
||||
|
||||
bool done() const { return fIndex == fList.size(); }
|
||||
void next() { fIndex += 1;}
|
||||
uint32_t glyphCount() const { return fList[fIndex].runSize(); }
|
||||
const uint16_t* glyphs() const { return fList[fIndex].shuntGlyphsIDs().data(); }
|
||||
const SkScalar* pos() const { return (const SkScalar*)fList[fIndex].positions().data(); }
|
||||
const SkPoint& offset() const { return fZero; }
|
||||
void applyFontToPaint(SkPaint* paint) const { *paint = fList[fIndex].paint(); }
|
||||
SkTextBlob::GlyphPositioning positioning() const { return SkTextBlob::kFull_Positioning; }
|
||||
const uint32_t* clusters() const { return fList[fIndex].clusters().data(); }
|
||||
uint32_t textSize() const { return fList[fIndex].text().size(); }
|
||||
const char* text() const { return fList[fIndex].text().data(); }
|
||||
|
||||
bool isLCD() const { return fList[fIndex].paint().isLCDRenderText(); }
|
||||
|
||||
private:
|
||||
static constexpr SkPoint fZero{0, 0};
|
||||
size_t fIndex{0};
|
||||
SkGlyphRunList& fList;
|
||||
};
|
||||
|
||||
class SkGlyphIDSet {
|
||||
public:
|
||||
SkSpan<const SkGlyphID> uniquifyGlyphIDs(
|
||||
|
@ -239,17 +239,17 @@ void GrRenderTargetContext::drawPosText(const GrClip& clip, const SkPaint& paint
|
||||
clipBounds);
|
||||
}
|
||||
|
||||
void GrRenderTargetContext::drawTextBlob(const GrClip& clip, const SkPaint& paint,
|
||||
const SkMatrix& viewMatrix, const SkTextBlob* blob,
|
||||
SkScalar x, SkScalar y, const SkIRect& clipBounds) {
|
||||
void GrRenderTargetContext::drawGlyphRunList(
|
||||
const GrClip& clip, const SkMatrix& viewMatrix,
|
||||
SkGlyphRunList* blob, const SkIRect& clipBounds) {
|
||||
ASSERT_SINGLE_OWNER
|
||||
RETURN_IF_ABANDONED
|
||||
SkDEBUGCODE(this->validate();)
|
||||
GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawTextBlob", fContext);
|
||||
GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawGlyphRunList", fContext);
|
||||
|
||||
GrTextContext* atlasTextContext = this->drawingManager()->getTextContext();
|
||||
atlasTextContext->drawTextBlob(fContext, fTextTarget.get(), clip, paint, viewMatrix,
|
||||
fSurfaceProps, blob, x, y, clipBounds);
|
||||
atlasTextContext->drawGlyphRunList(fContext, fTextTarget.get(), clip, viewMatrix,
|
||||
fSurfaceProps, blob, clipBounds);
|
||||
}
|
||||
|
||||
void GrRenderTargetContext::discard() {
|
||||
|
@ -37,6 +37,7 @@ class GrStyle;
|
||||
class GrTextureProxy;
|
||||
struct GrUserStencilSettings;
|
||||
struct SkDrawShadowRec;
|
||||
class SkGlyphRunList;
|
||||
struct SkIPoint;
|
||||
struct SkIRect;
|
||||
class SkLatticeIter;
|
||||
@ -67,9 +68,9 @@ public:
|
||||
const char text[], size_t byteLength, const SkScalar pos[],
|
||||
int scalarsPerPosition, const SkPoint& offset,
|
||||
const SkIRect& clipBounds);
|
||||
virtual void drawTextBlob(const GrClip&, const SkPaint&,
|
||||
const SkMatrix& viewMatrix, const SkTextBlob*,
|
||||
SkScalar x, SkScalar y, const SkIRect& clipBounds);
|
||||
virtual void drawGlyphRunList(const GrClip&,
|
||||
const SkMatrix& viewMatrix, SkGlyphRunList*,
|
||||
const SkIRect& clipBounds);
|
||||
|
||||
/**
|
||||
* Provides a perfomance hint that the render target's contents are allowed
|
||||
|
@ -1637,30 +1637,13 @@ void SkGpuDevice::drawPosText(const void* text, size_t byteLength,
|
||||
this->devClipBounds());
|
||||
}
|
||||
|
||||
void SkGpuDevice::drawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
|
||||
const SkPaint& paint) {
|
||||
ASSERT_SINGLE_OWNER
|
||||
GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "drawTextBlob", fContext.get());
|
||||
SkDEBUGCODE(this->validate();)
|
||||
|
||||
fRenderTargetContext->drawTextBlob(this->clip(), paint, this->ctm(), blob, x, y,
|
||||
this->devClipBounds());
|
||||
}
|
||||
|
||||
void SkGpuDevice::drawGlyphRunList(SkGlyphRunList* glyphRunList) {
|
||||
ASSERT_SINGLE_OWNER
|
||||
GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "drawGlyphRunList", fContext.get());
|
||||
SkDEBUGCODE(this->validate();)
|
||||
|
||||
auto blob = glyphRunList->blob();
|
||||
|
||||
if (blob == nullptr) {
|
||||
glyphRunList->temporaryShuntToDrawPosText(this, SkPoint::Make(0, 0));
|
||||
} else {
|
||||
auto origin = glyphRunList->origin();
|
||||
auto paint = glyphRunList->paint();
|
||||
this->drawTextBlob(blob, origin.x(), origin.y(), paint);
|
||||
}
|
||||
fRenderTargetContext->drawGlyphRunList(
|
||||
this->clip(), this->ctm(), glyphRunList, this->devClipBounds());
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -89,7 +89,6 @@ public:
|
||||
const SkPaint& paint) override;
|
||||
void drawPosText(const void* text, size_t len, const SkScalar pos[],
|
||||
int scalarsPerPos, const SkPoint& offset, const SkPaint&) override;
|
||||
void drawTextBlob(const SkTextBlob*, SkScalar x, SkScalar y, const SkPaint& paint) override;
|
||||
void drawGlyphRunList(SkGlyphRunList* glyphRunList) override;
|
||||
void drawVertices(const SkVertices*, const SkMatrix bones[], int boneCount, SkBlendMode,
|
||||
const SkPaint&) override;
|
||||
|
@ -56,6 +56,21 @@ public:
|
||||
return cacheBlob;
|
||||
}
|
||||
|
||||
sk_sp<GrTextBlob> makeBlob(SkGlyphRunList* glyphRunList) {
|
||||
return GrTextBlob::Make(glyphRunList->totalGlyphCount(), glyphRunList->size());
|
||||
}
|
||||
|
||||
sk_sp<GrTextBlob> makeCachedBlob(SkGlyphRunList* glyphRunList,
|
||||
const GrTextBlob::Key& key,
|
||||
const SkMaskFilterBase::BlurRec& blurRec,
|
||||
const SkPaint& paint) {
|
||||
sk_sp<GrTextBlob> cacheBlob(makeBlob(glyphRunList));
|
||||
cacheBlob->setupKey(key, blurRec, paint);
|
||||
this->add(cacheBlob);
|
||||
glyphRunList->temporaryShuntBlobNotifyAddedToCache(fUniqueID);
|
||||
return cacheBlob;
|
||||
}
|
||||
|
||||
sk_sp<GrTextBlob> find(const GrTextBlob::Key& key) const {
|
||||
const auto* idEntry = fBlobIDCache.find(key.fUniqueID);
|
||||
return idEntry ? idEntry->find(key) : nullptr;
|
||||
|
@ -84,56 +84,48 @@ SkScalerContextFlags GrTextContext::ComputeScalerContextFlags(
|
||||
}
|
||||
}
|
||||
|
||||
// TODO if this function ever shows up in profiling, then we can compute this value when the
|
||||
// textblob is being built and cache it. However, for the time being textblobs mostly only have 1
|
||||
// run so this is not a big deal to compute here.
|
||||
bool GrTextContext::HasLCD(const SkTextBlob* blob) {
|
||||
SkTextBlobRunIterator it(blob);
|
||||
for (; !it.done(); it.next()) {
|
||||
if (it.isLCD()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
void GrTextContext::drawGlyphRunList(
|
||||
GrContext* context, GrTextUtils::Target* target, const GrClip& clip,
|
||||
const SkMatrix& viewMatrix, const SkSurfaceProps& props, SkGlyphRunList* glyphRunList,
|
||||
const SkIRect& clipBounds) {
|
||||
SkPoint origin = glyphRunList->origin();
|
||||
|
||||
// Get the first paint to use as the key paint.
|
||||
const SkPaint& skPaint = glyphRunList->paint();
|
||||
|
||||
void GrTextContext::drawTextBlob(GrContext* context, GrTextUtils::Target* target,
|
||||
const GrClip& clip, const SkPaint& skPaint,
|
||||
const SkMatrix& viewMatrix, const SkSurfaceProps& props,
|
||||
const SkTextBlob* blob, SkScalar x, SkScalar y,
|
||||
const SkIRect& clipBounds) {
|
||||
// If we have been abandoned, then don't draw
|
||||
if (context->abandoned()) {
|
||||
return;
|
||||
}
|
||||
|
||||
sk_sp<GrTextBlob> cacheBlob;
|
||||
SkMaskFilterBase::BlurRec blurRec;
|
||||
GrTextBlob::Key key;
|
||||
// It might be worth caching these things, but its not clear at this time
|
||||
// TODO for animated mask filters, this will fill up our cache. We need a safeguard here
|
||||
const SkMaskFilter* mf = skPaint.getMaskFilter();
|
||||
bool canCache = !(skPaint.getPathEffect() || (mf && !as_MFB(mf)->asABlur(&blurRec)));
|
||||
bool canCache = glyphRunList->canCache() && !(skPaint.getPathEffect() ||
|
||||
(mf && !as_MFB(mf)->asABlur(&blurRec)));
|
||||
SkScalerContextFlags scalerContextFlags = ComputeScalerContextFlags(target->colorSpaceInfo());
|
||||
|
||||
auto glyphCache = context->contextPriv().getGlyphCache();
|
||||
GrTextBlobCache* textBlobCache = context->contextPriv().getTextBlobCache();
|
||||
|
||||
sk_sp<GrTextBlob> cacheBlob;
|
||||
GrTextBlob::Key key;
|
||||
if (canCache) {
|
||||
bool hasLCD = HasLCD(blob);
|
||||
bool hasLCD = glyphRunList->anyRunsLCD();
|
||||
|
||||
// We canonicalize all non-lcd draws to use kUnknown_SkPixelGeometry
|
||||
SkPixelGeometry pixelGeometry = hasLCD ? props.pixelGeometry() :
|
||||
kUnknown_SkPixelGeometry;
|
||||
kUnknown_SkPixelGeometry;
|
||||
|
||||
// TODO we want to figure out a way to be able to use the canonical color on LCD text,
|
||||
// see the note on ComputeCanonicalColor above. We pick a dummy value for LCD text to
|
||||
// ensure we always match the same key
|
||||
GrColor canonicalColor = hasLCD ? SK_ColorTRANSPARENT :
|
||||
ComputeCanonicalColor(skPaint, hasLCD);
|
||||
ComputeCanonicalColor(skPaint, hasLCD);
|
||||
|
||||
key.fPixelGeometry = pixelGeometry;
|
||||
key.fUniqueID = blob->uniqueID();
|
||||
key.fUniqueID = glyphRunList->uniqueID();
|
||||
key.fStyle = skPaint.getStyle();
|
||||
key.fHasBlur = SkToBool(mf);
|
||||
key.fCanonicalColor = canonicalColor;
|
||||
@ -143,139 +135,77 @@ void GrTextContext::drawTextBlob(GrContext* context, GrTextUtils::Target* target
|
||||
|
||||
GrTextUtils::Paint paint(&skPaint, &target->colorSpaceInfo());
|
||||
if (cacheBlob) {
|
||||
if (cacheBlob->mustRegenerate(paint, blurRec, viewMatrix, x, y)) {
|
||||
if (cacheBlob->mustRegenerate(paint, blurRec, viewMatrix, origin.x(), origin.y())) {
|
||||
// We have to remake the blob because changes may invalidate our masks.
|
||||
// TODO we could probably get away reuse most of the time if the pointer is unique,
|
||||
// but we'd have to clear the subrun information
|
||||
textBlobCache->remove(cacheBlob.get());
|
||||
cacheBlob = textBlobCache->makeCachedBlob(blob, key, blurRec, skPaint);
|
||||
this->regenerateTextBlob(cacheBlob.get(), glyphCache,
|
||||
cacheBlob = textBlobCache->makeCachedBlob(glyphRunList, key, blurRec, skPaint);
|
||||
this->regenerateGlyphRunList(cacheBlob.get(), glyphCache,
|
||||
*context->contextPriv().caps()->shaderCaps(), paint,
|
||||
scalerContextFlags, viewMatrix, props, blob, x, y);
|
||||
scalerContextFlags, viewMatrix, props, glyphRunList);
|
||||
} else {
|
||||
textBlobCache->makeMRU(cacheBlob.get());
|
||||
|
||||
if (CACHE_SANITY_CHECK) {
|
||||
int glyphCount = 0;
|
||||
int runCount = 0;
|
||||
GrTextBlobCache::BlobGlyphCount(&glyphCount, &runCount, blob);
|
||||
int glyphCount = glyphRunList->totalGlyphCount();
|
||||
int runCount = glyphRunList->runCount();
|
||||
sk_sp<GrTextBlob> sanityBlob(textBlobCache->makeBlob(glyphCount, runCount));
|
||||
sanityBlob->setupKey(key, blurRec, skPaint);
|
||||
this->regenerateTextBlob(
|
||||
this->regenerateGlyphRunList(
|
||||
sanityBlob.get(), glyphCache, *context->contextPriv().caps()->shaderCaps(),
|
||||
paint, scalerContextFlags, viewMatrix, props, blob, x, y);
|
||||
paint, scalerContextFlags, viewMatrix, props, glyphRunList);
|
||||
GrTextBlob::AssertEqual(*sanityBlob, *cacheBlob);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (canCache) {
|
||||
cacheBlob = textBlobCache->makeCachedBlob(blob, key, blurRec, skPaint);
|
||||
cacheBlob = textBlobCache->makeCachedBlob(glyphRunList, key, blurRec, skPaint);
|
||||
} else {
|
||||
cacheBlob = textBlobCache->makeBlob(blob);
|
||||
cacheBlob = textBlobCache->makeBlob(glyphRunList);
|
||||
}
|
||||
this->regenerateTextBlob(cacheBlob.get(), glyphCache,
|
||||
this->regenerateGlyphRunList(cacheBlob.get(), glyphCache,
|
||||
*context->contextPriv().caps()->shaderCaps(), paint,
|
||||
scalerContextFlags, viewMatrix, props, blob, x, y);
|
||||
scalerContextFlags, viewMatrix, props, glyphRunList);
|
||||
}
|
||||
|
||||
cacheBlob->flush(target, props, fDistanceAdjustTable.get(), paint,
|
||||
clip, viewMatrix, clipBounds, x, y);
|
||||
clip, viewMatrix, clipBounds, origin.x(), origin.y());
|
||||
}
|
||||
|
||||
void GrTextContext::regenerateTextBlob(GrTextBlob* cacheBlob,
|
||||
void GrTextContext::regenerateGlyphRunList(GrTextBlob* cacheBlob,
|
||||
GrGlyphCache* glyphCache,
|
||||
const GrShaderCaps& shaderCaps,
|
||||
const GrTextUtils::Paint& paint,
|
||||
SkScalerContextFlags scalerContextFlags,
|
||||
const SkMatrix& viewMatrix,
|
||||
const SkSurfaceProps& props, const SkTextBlob* blob,
|
||||
SkScalar x, SkScalar y) const {
|
||||
cacheBlob->initReusableBlob(paint.luminanceColor(), viewMatrix, x, y);
|
||||
const SkSurfaceProps& props,
|
||||
SkGlyphRunList* glyphRunList) const {
|
||||
SkPoint origin = glyphRunList->origin();
|
||||
cacheBlob->initReusableBlob(paint.luminanceColor(), viewMatrix, origin.x(), origin.y());
|
||||
|
||||
// Regenerate textblob
|
||||
SkTextBlobRunIterator it(blob);
|
||||
SkGlyphRunListIterator it(glyphRunList);
|
||||
GrTextUtils::RunPaint runPaint(&paint);
|
||||
for (int run = 0; !it.done(); it.next(), run++) {
|
||||
int glyphCount = it.glyphCount();
|
||||
size_t textLen = glyphCount * sizeof(uint16_t);
|
||||
const SkPoint& offset = it.offset();
|
||||
cacheBlob->push_back_run(run);
|
||||
if (!runPaint.modifyForRun([it](SkPaint* p) { it.applyFontToPaint(p); })) {
|
||||
continue;
|
||||
}
|
||||
cacheBlob->setRunPaintFlags(run, runPaint.skPaint().getFlags());
|
||||
|
||||
SkASSERT(it.positioning() == SkTextBlob::kFull_Positioning);
|
||||
if (CanDrawAsDistanceFields(runPaint, viewMatrix, props,
|
||||
shaderCaps.supportsDistanceFieldText(), fOptions)) {
|
||||
switch (it.positioning()) {
|
||||
case SkTextBlob::kDefault_Positioning: {
|
||||
auto origin = SkPoint::Make(x + offset.x(), y + offset.y());
|
||||
SkGlyphRunBuilder builder;
|
||||
builder.drawText(runPaint.skPaint(),
|
||||
(const char*) it.glyphs(), textLen, origin);
|
||||
|
||||
auto glyphRunList = builder.useGlyphRunList();
|
||||
if (!glyphRunList->empty()) {
|
||||
auto glyphRun = (*glyphRunList)[0];
|
||||
glyphRun.temporaryShuntToCallback(
|
||||
[&](size_t runSize, const char* glyphIDs, const SkScalar* pos) {
|
||||
this->drawDFPosText(
|
||||
cacheBlob, run, glyphCache, props, runPaint,
|
||||
scalerContextFlags, viewMatrix, glyphIDs, 2 * runSize,
|
||||
pos, 2, SkPoint::Make(0, 0));
|
||||
});
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case SkTextBlob::kHorizontal_Positioning: {
|
||||
SkPoint dfOffset = SkPoint::Make(x, y + offset.y());
|
||||
this->drawDFPosText(cacheBlob, run, glyphCache, props, runPaint,
|
||||
scalerContextFlags, viewMatrix, (const char*)it.glyphs(),
|
||||
textLen, it.pos(), 1, dfOffset);
|
||||
break;
|
||||
}
|
||||
case SkTextBlob::kFull_Positioning: {
|
||||
SkPoint dfOffset = SkPoint::Make(x, y);
|
||||
this->drawDFPosText(cacheBlob, run, glyphCache, props, runPaint,
|
||||
scalerContextFlags, viewMatrix, (const char*)it.glyphs(),
|
||||
textLen, it.pos(), 2, dfOffset);
|
||||
break;
|
||||
}
|
||||
}
|
||||
this->drawDFPosText(cacheBlob, run, glyphCache, props, runPaint,
|
||||
scalerContextFlags, viewMatrix, (const char*)it.glyphs(),
|
||||
textLen, it.pos(), 2, origin);
|
||||
} else {
|
||||
switch (it.positioning()) {
|
||||
case SkTextBlob::kDefault_Positioning: {
|
||||
auto origin = SkPoint::Make(x + offset.x(), y + offset.y());
|
||||
SkGlyphRunBuilder builder;
|
||||
builder.drawText(runPaint.skPaint(),
|
||||
(const char*) it.glyphs(), textLen, origin);
|
||||
|
||||
auto glyphRunList = builder.useGlyphRunList();
|
||||
if (!glyphRunList->empty()) {
|
||||
auto glyphRun = (*glyphRunList)[0];
|
||||
|
||||
glyphRun.temporaryShuntToCallback(
|
||||
[&](size_t runSize, const char* glyphIDs, const SkScalar* pos) {
|
||||
this->DrawBmpPosText(
|
||||
cacheBlob, run, glyphCache, props, runPaint,
|
||||
scalerContextFlags, viewMatrix, glyphIDs, 2 * runSize,
|
||||
pos, 2, SkPoint::Make(0, 0));
|
||||
});
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SkTextBlob::kHorizontal_Positioning:
|
||||
DrawBmpPosText(cacheBlob, run, glyphCache, props, runPaint, scalerContextFlags,
|
||||
viewMatrix, (const char*)it.glyphs(), textLen, it.pos(), 1,
|
||||
SkPoint::Make(x, y + offset.y()));
|
||||
break;
|
||||
case SkTextBlob::kFull_Positioning:
|
||||
DrawBmpPosText(cacheBlob, run, glyphCache, props, runPaint, scalerContextFlags,
|
||||
viewMatrix, (const char*)it.glyphs(), textLen, it.pos(), 2,
|
||||
SkPoint::Make(x, y));
|
||||
break;
|
||||
}
|
||||
DrawBmpPosText(cacheBlob, run, glyphCache, props, runPaint, scalerContextFlags,
|
||||
viewMatrix, (const char*)it.glyphs(), textLen, it.pos(), 2,
|
||||
origin);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -335,7 +265,6 @@ void GrTextContext::drawPosText(GrContext* context, GrTextUtils::Target* target,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void GrTextContext::DrawBmpPosText(GrTextBlob* blob, int runIndex,
|
||||
GrGlyphCache* glyphCache, const SkSurfaceProps& props,
|
||||
const GrTextUtils::Paint& paint,
|
||||
@ -798,8 +727,7 @@ std::unique_ptr<GrDrawOp> GrTextContext::createOp_TestingOnly(GrContext* context
|
||||
context->contextPriv().getTextBlobCache(), glyphCache,
|
||||
*context->contextPriv().caps()->shaderCaps(), utilsPaint,
|
||||
GrTextContext::kTextBlobOpScalerContextFlags, viewMatrix, surfaceProps,
|
||||
text,
|
||||
textLen, pos, 2, origin);
|
||||
text, textLen, pos, 2, origin);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -48,9 +48,9 @@ public:
|
||||
const SkMatrix& viewMatrix, const SkSurfaceProps&, const char text[],
|
||||
size_t byteLength, const SkScalar pos[], int scalarsPerPosition,
|
||||
const SkPoint& offset, const SkIRect& regionClipBounds);
|
||||
void drawTextBlob(GrContext*, GrTextUtils::Target*, const GrClip&, const SkPaint&,
|
||||
const SkMatrix& viewMatrix, const SkSurfaceProps&, const SkTextBlob*,
|
||||
SkScalar x, SkScalar y, const SkIRect& clipBounds);
|
||||
void drawGlyphRunList(GrContext*, GrTextUtils::Target*, const GrClip&,
|
||||
const SkMatrix& viewMatrix, const SkSurfaceProps&, SkGlyphRunList*,
|
||||
const SkIRect& clipBounds);
|
||||
|
||||
std::unique_ptr<GrDrawOp> createOp_TestingOnly(GrContext*,
|
||||
GrTextContext*,
|
||||
@ -115,16 +115,15 @@ private:
|
||||
static SkColor ComputeCanonicalColor(const SkPaint&, bool lcd);
|
||||
// Determines if we need to use fake gamma (and contrast boost):
|
||||
static SkScalerContextFlags ComputeScalerContextFlags(const GrColorSpaceInfo&);
|
||||
void regenerateTextBlob(GrTextBlob* bmp,
|
||||
|
||||
void regenerateGlyphRunList(GrTextBlob* bmp,
|
||||
GrGlyphCache*,
|
||||
const GrShaderCaps&,
|
||||
const GrTextUtils::Paint&,
|
||||
SkScalerContextFlags scalerContextFlags,
|
||||
const SkMatrix& viewMatrix,
|
||||
const SkSurfaceProps&,
|
||||
const SkTextBlob* blob, SkScalar x, SkScalar y) const;
|
||||
|
||||
static bool HasLCD(const SkTextBlob*);
|
||||
SkGlyphRunList* glyphRunList) const;
|
||||
|
||||
sk_sp<GrTextBlob> makeDrawPosTextBlob(GrTextBlobCache*, GrGlyphCache*,
|
||||
const GrShaderCaps&,
|
||||
|
Loading…
Reference in New Issue
Block a user