Remove runIndex as a concept for GrTextBlob
Change-Id: I8ac756a088c1dddf475bf96f9a4a84ec2cb500be Reviewed-on: https://skia-review.googlesource.com/c/169763 Commit-Queue: Herb Derby <herb@google.com> Reviewed-by: Mike Klein <mtklein@google.com>
This commit is contained in:
parent
5cd242b4fc
commit
2bb343c5e8
@ -317,29 +317,6 @@ void SkGlyphRunListPainter::processARGBFallback(
|
||||
}
|
||||
}
|
||||
|
||||
static SkRect rect_to_draw(
|
||||
const SkGlyph& glyph, SkPoint origin, SkScalar textScale, bool isDFT) {
|
||||
|
||||
SkScalar dx = SkIntToScalar(glyph.fLeft);
|
||||
SkScalar dy = SkIntToScalar(glyph.fTop);
|
||||
SkScalar width = SkIntToScalar(glyph.fWidth);
|
||||
SkScalar height = SkIntToScalar(glyph.fHeight);
|
||||
|
||||
if (isDFT) {
|
||||
dx += SK_DistanceFieldInset;
|
||||
dy += SK_DistanceFieldInset;
|
||||
width -= 2 * SK_DistanceFieldInset;
|
||||
height -= 2 * SK_DistanceFieldInset;
|
||||
}
|
||||
|
||||
dx *= textScale;
|
||||
dy *= textScale;
|
||||
width *= textScale;
|
||||
height *= textScale;
|
||||
|
||||
return SkRect::MakeXYWH(origin.x() + dx, origin.y() + dy, width, height);
|
||||
}
|
||||
|
||||
// Beware! The following code will end up holding two glyph caches at the same time, but they
|
||||
// will not be the same cache (which would cause two separate caches to be created).
|
||||
template <typename PerPathT>
|
||||
@ -395,15 +372,7 @@ void SkGlyphRunListPainter::drawGlyphRunAsBMPWithPathFallback(
|
||||
if (SkScalarsAreFinite(mappedPt.x(), mappedPt.y())) {
|
||||
const SkGlyph& glyph = cache->getGlyphMetrics(glyphID, mappedPt);
|
||||
if (SkGlyphCacheCommon::GlyphTooBigForAtlas(glyph)) {
|
||||
SkScalar sx = SkScalarFloorToScalar(mappedPt.fX),
|
||||
sy = SkScalarFloorToScalar(mappedPt.fY);
|
||||
|
||||
SkRect glyphRect =
|
||||
rect_to_draw(glyph, {sx, sy}, SK_Scalar1, false);
|
||||
|
||||
if (!glyphRect.isEmpty()) {
|
||||
perPath(glyph, mappedPt);
|
||||
}
|
||||
perPath(glyph, mappedPt);
|
||||
} else {
|
||||
perGlyph(glyph, mappedPt);
|
||||
}
|
||||
@ -552,34 +521,6 @@ void GrTextContext::drawGlyphRunList(
|
||||
clip, viewMatrix, origin.x(), origin.y());
|
||||
}
|
||||
|
||||
static void append_glyph(GrTextBlob* blob, int runIndex,
|
||||
const sk_sp<GrTextStrike>& strike,
|
||||
const SkGlyph& skGlyph, GrGlyph::MaskStyle maskStyle,
|
||||
SkScalar sx, SkScalar sy,
|
||||
const SkPMColor4f& color, SkGlyphCache* skGlyphCache,
|
||||
SkScalar textRatio, bool needsTransform) {
|
||||
GrGlyph::PackedID id = GrGlyph::Pack(skGlyph.getGlyphID(),
|
||||
skGlyph.getSubXFixed(),
|
||||
skGlyph.getSubYFixed(),
|
||||
maskStyle);
|
||||
GrGlyph* glyph = strike->getGlyph(skGlyph, id, skGlyphCache);
|
||||
if (!glyph) {
|
||||
return;
|
||||
}
|
||||
|
||||
SkASSERT(skGlyph.fWidth == glyph->width());
|
||||
SkASSERT(skGlyph.fHeight == glyph->height());
|
||||
|
||||
bool isDFT = maskStyle == GrGlyph::kDistance_MaskStyle;
|
||||
|
||||
SkRect glyphRect = rect_to_draw(skGlyph, {sx, sy}, textRatio, isDFT);
|
||||
|
||||
if (!glyphRect.isEmpty()) {
|
||||
blob->appendGlyph(runIndex, glyphRect, color, strike, glyph, !needsTransform);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void GrTextBlob::generateFromGlyphRunList(GrGlyphCache* glyphCache,
|
||||
const GrShaderCaps& shaderCaps,
|
||||
const GrTextContext::Options& options,
|
||||
@ -595,26 +536,25 @@ void GrTextBlob::generateFromGlyphRunList(GrGlyphCache* glyphCache,
|
||||
SkSpan<const SkPoint> positions, SkScalar textScale,
|
||||
const SkMatrix& glyphCacheMatrix,
|
||||
SkGlyphRunListPainter::NeedsTransform needsTransform) const {
|
||||
fBlob->initOverride(fRunIndex);
|
||||
fRun->initOverride();
|
||||
fBlob->setHasBitmap();
|
||||
fBlob->setSubRunHasW(fRunIndex, glyphCacheMatrix.hasPerspective());
|
||||
fRun->setSubRunHasW(glyphCacheMatrix.hasPerspective());
|
||||
SkExclusiveStrikePtr fallbackCache =
|
||||
fBlob->setupCache(fRunIndex,
|
||||
fallbackPaint, fProps, fScalerContextFlags, glyphCacheMatrix);
|
||||
fRun->setupCache(fallbackPaint, fProps, fScalerContextFlags, glyphCacheMatrix);
|
||||
sk_sp<GrTextStrike> strike = fGlyphCache->getStrike(fallbackCache.get());
|
||||
const SkPoint* glyphPos = positions.data();
|
||||
for (auto glyphID : glyphIDs) {
|
||||
const SkGlyph& glyph = fallbackCache->getGlyphIDMetrics(glyphID);
|
||||
append_glyph(fBlob, fRunIndex, strike, glyph,
|
||||
GrGlyph::kCoverage_MaskStyle,
|
||||
glyphPos->fX, glyphPos->fY, fFilteredColor,
|
||||
fallbackCache.get(), textScale, needsTransform);
|
||||
fRun->appendGlyph(fBlob, strike, glyph,
|
||||
GrGlyph::kCoverage_MaskStyle,
|
||||
*glyphPos, fFilteredColor,
|
||||
fallbackCache.get(), textScale, needsTransform);
|
||||
glyphPos++;
|
||||
}
|
||||
}
|
||||
|
||||
GrTextBlob* const fBlob;
|
||||
const int fRunIndex;
|
||||
GrTextBlob::Run* fRun;
|
||||
const SkSurfaceProps& fProps;
|
||||
const SkScalerContextFlags fScalerContextFlags;
|
||||
GrGlyphCache* const fGlyphCache;
|
||||
@ -625,12 +565,11 @@ void GrTextBlob::generateFromGlyphRunList(GrGlyphCache* glyphCache,
|
||||
this->initReusableBlob(
|
||||
glyphRunList.paint().computeLuminanceColor(), viewMatrix, origin.x(), origin.y());
|
||||
|
||||
int runIndex = 0;
|
||||
for (const auto& glyphRun : glyphRunList) {
|
||||
const SkPaint& runPaint = glyphRun.paint();
|
||||
this->pushBackRun(runIndex);
|
||||
Run* run = this->pushBackRun();
|
||||
|
||||
this->setRunPaintFlags(runIndex, runPaint.getFlags());
|
||||
run->setRunPaintFlags(runPaint.getFlags());
|
||||
|
||||
if (GrTextContext::CanDrawAsDistanceFields(runPaint, viewMatrix, props,
|
||||
shaderCaps.supportsDistanceFieldText(), options)) {
|
||||
@ -644,42 +583,36 @@ void GrTextBlob::generateFromGlyphRunList(GrGlyphCache* glyphCache,
|
||||
GrTextContext::InitDistanceFieldPaint(this, &distanceFieldPaint, viewMatrix,
|
||||
options, &textRatio, &flags);
|
||||
this->setHasDistanceField();
|
||||
this->setSubRunHasDistanceFields(runIndex, runPaint.isLCDRenderText(),
|
||||
runPaint.isAntiAlias(), hasWCoord);
|
||||
run->setSubRunHasDistanceFields(runPaint.isLCDRenderText(),
|
||||
runPaint.isAntiAlias(), hasWCoord);
|
||||
|
||||
{
|
||||
auto cache = this->setupCache(
|
||||
runIndex, distanceFieldPaint, props, flags, SkMatrix::I());
|
||||
auto cache = run->setupCache(distanceFieldPaint, props, flags, SkMatrix::I());
|
||||
|
||||
sk_sp<GrTextStrike> currStrike = glyphCache->getStrike(cache.get());
|
||||
|
||||
auto perSDF =
|
||||
[this, runIndex, &currStrike, filteredColor, cache{cache.get()}, textRatio]
|
||||
[this, run, &currStrike, filteredColor, cache{cache.get()}, textRatio]
|
||||
(const SkGlyph& glyph, SkPoint position) {
|
||||
if (!glyph.isEmpty()) {
|
||||
SkScalar sx = position.fX,
|
||||
sy = position.fY;
|
||||
append_glyph(this, runIndex, currStrike,
|
||||
glyph, GrGlyph::kDistance_MaskStyle, sx, sy,
|
||||
run->appendGlyph(this, currStrike,
|
||||
glyph, GrGlyph::kDistance_MaskStyle, position,
|
||||
filteredColor,
|
||||
cache, textRatio, true);
|
||||
}
|
||||
};
|
||||
|
||||
auto perPath =
|
||||
[this, runIndex, textRatio, cache{cache.get()}]
|
||||
[run, textRatio, cache{cache.get()}]
|
||||
(const SkGlyph& glyph, SkPoint position) {
|
||||
if (!glyph.isEmpty()) {
|
||||
if (const SkPath* glyphPath = cache->findPath(glyph)) {
|
||||
SkScalar sx = position.fX,
|
||||
sy = position.fY;
|
||||
this->appendPathGlyph(
|
||||
runIndex, *glyphPath, sx, sy, textRatio, false);
|
||||
run->appendPathGlyph(*glyphPath, position, textRatio, false);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
ARGBFallbackHelper argbFallback{this, runIndex, props, scalerContextFlags,
|
||||
ARGBFallbackHelper argbFallback{this, run, props, scalerContextFlags,
|
||||
glyphCache, filteredColor};
|
||||
|
||||
glyphPainter->drawGlyphRunAsSDFWithARGBFallback(
|
||||
@ -701,18 +634,17 @@ void GrTextBlob::generateFromGlyphRunList(GrGlyphCache* glyphCache,
|
||||
pathPaint, props, scalerContextFlags, SkMatrix::I());
|
||||
|
||||
// Given a glyph that is not ARGB, draw it.
|
||||
auto perPath = [textScale, runIndex, this, &pathCache]
|
||||
auto perPath = [textScale, run, &pathCache]
|
||||
(const SkGlyph& glyph, SkPoint position) {
|
||||
if (!glyph.isEmpty()) {
|
||||
const SkPath* path = pathCache->findPath(glyph);
|
||||
if (path != nullptr) {
|
||||
this->appendPathGlyph(
|
||||
runIndex, *path, position.fX, position.fY, textScale, false);
|
||||
run->appendPathGlyph(*path, position, textScale, false);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
ARGBFallbackHelper argbFallback{this, runIndex, props, scalerContextFlags,
|
||||
ARGBFallbackHelper argbFallback{this, run, props, scalerContextFlags,
|
||||
glyphCache, filteredColor};
|
||||
|
||||
glyphPainter->drawGlyphRunAsPathWithARGBFallback(
|
||||
@ -722,35 +654,33 @@ void GrTextBlob::generateFromGlyphRunList(GrGlyphCache* glyphCache,
|
||||
// Ensure the blob is set for bitmaptext
|
||||
this->setHasBitmap();
|
||||
|
||||
auto cache = this->setupCache(
|
||||
runIndex, runPaint, props, scalerContextFlags, viewMatrix);
|
||||
auto cache = run->setupCache(runPaint, props, scalerContextFlags, viewMatrix);
|
||||
|
||||
sk_sp<GrTextStrike> currStrike = glyphCache->getStrike(cache.get());
|
||||
|
||||
auto perGlyph =
|
||||
[this, runIndex, &currStrike, filteredColor, cache{cache.get()}]
|
||||
[this, run, &currStrike, filteredColor, cache{cache.get()}]
|
||||
(const SkGlyph& glyph, SkPoint mappedPt) {
|
||||
if (!glyph.isEmpty()) {
|
||||
const void* glyphImage = cache->findImage(glyph);
|
||||
if (glyphImage != nullptr) {
|
||||
SkScalar sx = SkScalarFloorToScalar(mappedPt.fX),
|
||||
sy = SkScalarFloorToScalar(mappedPt.fY);
|
||||
append_glyph(this, runIndex, currStrike,
|
||||
glyph, GrGlyph::kCoverage_MaskStyle, sx, sy,
|
||||
filteredColor, cache, SK_Scalar1, false);
|
||||
SkPoint pt{SkScalarFloorToScalar(mappedPt.fX),
|
||||
SkScalarFloorToScalar(mappedPt.fY)};
|
||||
run->appendGlyph(this, currStrike,
|
||||
glyph, GrGlyph::kCoverage_MaskStyle, pt,
|
||||
filteredColor, cache, SK_Scalar1, false);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
auto perPath =
|
||||
[this, runIndex, cache{cache.get()}]
|
||||
[run, cache{cache.get()}]
|
||||
(const SkGlyph& glyph, SkPoint position) {
|
||||
const SkPath* glyphPath = cache->findPath(glyph);
|
||||
if (glyphPath != nullptr) {
|
||||
SkScalar sx = SkScalarFloorToScalar(position.fX),
|
||||
sy = SkScalarFloorToScalar(position.fY);
|
||||
this->appendPathGlyph(
|
||||
runIndex, *glyphPath, sx, sy, SK_Scalar1, true);
|
||||
SkPoint pt{SkScalarFloorToScalar(position.fX),
|
||||
SkScalarFloorToScalar(position.fY)};
|
||||
run->appendPathGlyph(*glyphPath, pt, SK_Scalar1, true);
|
||||
}
|
||||
};
|
||||
|
||||
@ -758,7 +688,6 @@ void GrTextBlob::generateFromGlyphRunList(GrGlyphCache* glyphCache,
|
||||
cache.get(), glyphRun, origin, viewMatrix,
|
||||
std::move(perGlyph), std::move(perPath));
|
||||
}
|
||||
runIndex += 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -40,7 +40,6 @@ public:
|
||||
static bool GlyphTooBigForAtlas(const SkGlyph& glyph);
|
||||
};
|
||||
|
||||
|
||||
class SkGlyphRunListPainter {
|
||||
public:
|
||||
// Constructor for SkBitmpapDevice.
|
||||
|
@ -126,7 +126,7 @@ SkString GrAtlasTextOp::dumpInfo() const {
|
||||
fGeoData[i].fColor.toBytes_RGBA(),
|
||||
fGeoData[i].fX,
|
||||
fGeoData[i].fY,
|
||||
fGeoData[i].fBlob->runCount());
|
||||
fGeoData[i].fBlob->runCountLimit());
|
||||
}
|
||||
|
||||
str += fProcessors.dumpProcessors();
|
||||
|
@ -54,96 +54,133 @@ sk_sp<GrTextBlob> GrTextBlob::Make(int glyphCount, int runCount) {
|
||||
for (int i = 0; i < runCount; i++) {
|
||||
new (&cacheBlob->fRuns[i]) GrTextBlob::Run;
|
||||
}
|
||||
cacheBlob->fRunCount = runCount;
|
||||
cacheBlob->fRunCountLimit = runCount;
|
||||
return cacheBlob;
|
||||
}
|
||||
|
||||
SkExclusiveStrikePtr GrTextBlob::setupCache(int runIndex,
|
||||
const SkPaint& skPaint,
|
||||
const SkSurfaceProps& props,
|
||||
SkScalerContextFlags scalerContextFlags,
|
||||
const SkMatrix& viewMatrix) {
|
||||
GrTextBlob::Run* run = &fRuns[runIndex];
|
||||
SkExclusiveStrikePtr GrTextBlob::Run::setupCache(const SkPaint& skPaint,
|
||||
const SkSurfaceProps& props,
|
||||
SkScalerContextFlags scalerContextFlags,
|
||||
const SkMatrix& viewMatrix) {
|
||||
|
||||
// if we have an override descriptor for the run, then we should use that
|
||||
SkAutoDescriptor* desc = run->fOverrideDescriptor.get() ? run->fOverrideDescriptor.get() :
|
||||
&run->fDescriptor;
|
||||
SkAutoDescriptor* desc = fOverrideDescriptor.get() ? fOverrideDescriptor.get() : &fDescriptor;
|
||||
SkScalerContextEffects effects;
|
||||
SkScalerContext::CreateDescriptorAndEffectsUsingPaint(
|
||||
skPaint, props, scalerContextFlags, viewMatrix, desc, &effects);
|
||||
run->fTypeface = SkPaintPriv::RefTypefaceOrDefault(skPaint);
|
||||
run->fPathEffect = sk_ref_sp(effects.fPathEffect);
|
||||
run->fMaskFilter = sk_ref_sp(effects.fMaskFilter);
|
||||
return SkStrikeCache::FindOrCreateStrikeExclusive(*desc->getDesc(), effects, *run->fTypeface);
|
||||
fTypeface = SkPaintPriv::RefTypefaceOrDefault(skPaint);
|
||||
fPathEffect = sk_ref_sp(effects.fPathEffect);
|
||||
fMaskFilter = sk_ref_sp(effects.fMaskFilter);
|
||||
return SkStrikeCache::FindOrCreateStrikeExclusive(*desc->getDesc(), effects, *fTypeface);
|
||||
}
|
||||
|
||||
void GrTextBlob::appendGlyph(int runIndex,
|
||||
const SkRect& positions,
|
||||
const SkPMColor4f& color4f,
|
||||
const sk_sp<GrTextStrike>& strike,
|
||||
GrGlyph* glyph, bool preTransformed) {
|
||||
// TODO4F: Preserve float colors
|
||||
GrColor color = color4f.toBytes_RGBA();
|
||||
static SkRect rect_to_draw(
|
||||
const SkGlyph& glyph, SkPoint origin, SkScalar textScale, bool isDFT) {
|
||||
|
||||
Run& run = fRuns[runIndex];
|
||||
GrMaskFormat format = glyph->fMaskFormat;
|
||||
SkScalar dx = SkIntToScalar(glyph.fLeft);
|
||||
SkScalar dy = SkIntToScalar(glyph.fTop);
|
||||
SkScalar width = SkIntToScalar(glyph.fWidth);
|
||||
SkScalar height = SkIntToScalar(glyph.fHeight);
|
||||
|
||||
Run::SubRunInfo* subRun = &run.fSubRunInfo.back();
|
||||
if (run.fInitialized && subRun->maskFormat() != format) {
|
||||
subRun = &run.push_back();
|
||||
subRun->setStrike(strike);
|
||||
} else if (!run.fInitialized) {
|
||||
subRun->setStrike(strike);
|
||||
if (isDFT) {
|
||||
dx += SK_DistanceFieldInset;
|
||||
dy += SK_DistanceFieldInset;
|
||||
width -= 2 * SK_DistanceFieldInset;
|
||||
height -= 2 * SK_DistanceFieldInset;
|
||||
}
|
||||
|
||||
run.fInitialized = true;
|
||||
dx *= textScale;
|
||||
dy *= textScale;
|
||||
width *= textScale;
|
||||
height *= textScale;
|
||||
|
||||
bool hasW = subRun->hasWCoord();
|
||||
// glyphs drawn in perspective must always have a w coord.
|
||||
SkASSERT(hasW || !fInitialViewMatrix.hasPerspective());
|
||||
|
||||
size_t vertexStride = GetVertexStride(format, hasW);
|
||||
|
||||
subRun->setMaskFormat(format);
|
||||
|
||||
subRun->joinGlyphBounds(positions);
|
||||
subRun->setColor(color);
|
||||
|
||||
intptr_t vertex = reinterpret_cast<intptr_t>(this->fVertices + subRun->vertexEndIndex());
|
||||
|
||||
// We always write the third position component used by SDFs. If it is unused it gets
|
||||
// overwritten. Similarly, we always write the color and the blob will later overwrite it
|
||||
// with texture coords if it is unused.
|
||||
size_t colorOffset = hasW ? sizeof(SkPoint3) : sizeof(SkPoint);
|
||||
// V0
|
||||
*reinterpret_cast<SkPoint3*>(vertex) = {positions.fLeft, positions.fTop, 1.f};
|
||||
*reinterpret_cast<GrColor*>(vertex + colorOffset) = color;
|
||||
vertex += vertexStride;
|
||||
|
||||
// V1
|
||||
*reinterpret_cast<SkPoint3*>(vertex) = {positions.fLeft, positions.fBottom, 1.f};
|
||||
*reinterpret_cast<GrColor*>(vertex + colorOffset) = color;
|
||||
vertex += vertexStride;
|
||||
|
||||
// V2
|
||||
*reinterpret_cast<SkPoint3*>(vertex) = {positions.fRight, positions.fTop, 1.f};
|
||||
*reinterpret_cast<GrColor*>(vertex + colorOffset) = color;
|
||||
vertex += vertexStride;
|
||||
|
||||
// V3
|
||||
*reinterpret_cast<SkPoint3*>(vertex) = {positions.fRight, positions.fBottom, 1.f};
|
||||
*reinterpret_cast<GrColor*>(vertex + colorOffset) = color;
|
||||
|
||||
subRun->appendVertices(vertexStride);
|
||||
fGlyphs[subRun->glyphEndIndex()] = glyph;
|
||||
subRun->glyphAppended();
|
||||
subRun->setNeedsTransform(!preTransformed);
|
||||
return SkRect::MakeXYWH(origin.x() + dx, origin.y() + dy, width, height);
|
||||
}
|
||||
|
||||
void GrTextBlob::appendPathGlyph(int runIndex, const SkPath& path, SkScalar x, SkScalar y,
|
||||
void GrTextBlob::Run::appendGlyph(GrTextBlob* blob,
|
||||
const sk_sp<GrTextStrike>& strike,
|
||||
const SkGlyph& skGlyph, GrGlyph::MaskStyle maskStyle,
|
||||
SkPoint origin,
|
||||
const SkPMColor4f& color4f, SkGlyphCache* skGlyphCache,
|
||||
SkScalar textRatio, bool needsTransform) {
|
||||
|
||||
GrGlyph::PackedID id = GrGlyph::Pack(skGlyph.getGlyphID(),
|
||||
skGlyph.getSubXFixed(),
|
||||
skGlyph.getSubYFixed(),
|
||||
maskStyle);
|
||||
GrGlyph* glyph = strike->getGlyph(skGlyph, id, skGlyphCache);
|
||||
if (!glyph) {
|
||||
return;
|
||||
}
|
||||
|
||||
SkASSERT(skGlyph.fWidth == glyph->width());
|
||||
SkASSERT(skGlyph.fHeight == glyph->height());
|
||||
|
||||
bool isDFT = maskStyle == GrGlyph::kDistance_MaskStyle;
|
||||
|
||||
SkRect glyphRect = rect_to_draw(skGlyph, origin, textRatio, isDFT);
|
||||
if (!glyphRect.isEmpty()) {
|
||||
// TODO4F: Preserve float colors
|
||||
GrColor color = color4f.toBytes_RGBA();
|
||||
|
||||
GrMaskFormat format = glyph->fMaskFormat;
|
||||
|
||||
Run::SubRunInfo* subRun = &fSubRunInfo.back();
|
||||
if (fInitialized && subRun->maskFormat() != format) {
|
||||
subRun = &pushBackSubRun();
|
||||
subRun->setStrike(strike);
|
||||
} else if (!fInitialized) {
|
||||
subRun->setStrike(strike);
|
||||
}
|
||||
|
||||
fInitialized = true;
|
||||
|
||||
bool hasW = subRun->hasWCoord();
|
||||
// glyphs drawn in perspective must always have a w coord.
|
||||
SkASSERT(hasW || !blob->fInitialViewMatrix.hasPerspective());
|
||||
|
||||
size_t vertexStride = GetVertexStride(format, hasW);
|
||||
|
||||
subRun->setMaskFormat(format);
|
||||
|
||||
subRun->joinGlyphBounds(glyphRect);
|
||||
subRun->setColor(color);
|
||||
|
||||
intptr_t vertex = reinterpret_cast<intptr_t>(blob->fVertices + subRun->vertexEndIndex());
|
||||
|
||||
// We always write the third position component used by SDFs. If it is unused it gets
|
||||
// overwritten. Similarly, we always write the color and the blob will later overwrite it
|
||||
// with texture coords if it is unused.
|
||||
size_t colorOffset = hasW ? sizeof(SkPoint3) : sizeof(SkPoint);
|
||||
// V0
|
||||
*reinterpret_cast<SkPoint3*>(vertex) = {glyphRect.fLeft, glyphRect.fTop, 1.f};
|
||||
*reinterpret_cast<GrColor*>(vertex + colorOffset) = color;
|
||||
vertex += vertexStride;
|
||||
|
||||
// V1
|
||||
*reinterpret_cast<SkPoint3*>(vertex) = {glyphRect.fLeft, glyphRect.fBottom, 1.f};
|
||||
*reinterpret_cast<GrColor*>(vertex + colorOffset) = color;
|
||||
vertex += vertexStride;
|
||||
|
||||
// V2
|
||||
*reinterpret_cast<SkPoint3*>(vertex) = {glyphRect.fRight, glyphRect.fTop, 1.f};
|
||||
*reinterpret_cast<GrColor*>(vertex + colorOffset) = color;
|
||||
vertex += vertexStride;
|
||||
|
||||
// V3
|
||||
*reinterpret_cast<SkPoint3*>(vertex) = {glyphRect.fRight, glyphRect.fBottom, 1.f};
|
||||
*reinterpret_cast<GrColor*>(vertex + colorOffset) = color;
|
||||
|
||||
subRun->appendVertices(vertexStride);
|
||||
blob->fGlyphs[subRun->glyphEndIndex()] = glyph;
|
||||
subRun->glyphAppended();
|
||||
subRun->setNeedsTransform(needsTransform);
|
||||
}
|
||||
}
|
||||
|
||||
void GrTextBlob::Run::appendPathGlyph(const SkPath& path, SkPoint position,
|
||||
SkScalar scale, bool preTransformed) {
|
||||
Run& run = fRuns[runIndex];
|
||||
run.fPathGlyphs.push_back(GrTextBlob::Run::PathGlyph(path, x, y, scale, preTransformed));
|
||||
fPathGlyphs.push_back(PathGlyph(path, position.x(), position.y(), scale, preTransformed));
|
||||
}
|
||||
|
||||
bool GrTextBlob::mustRegenerate(const SkPaint& paint, bool anyRunHasSubpixelPosition,
|
||||
@ -294,7 +331,7 @@ void GrTextBlob::flush(GrTextTarget* target, const SkSurfaceProps& props,
|
||||
|
||||
// GrTextBlob::makeOp only takes uint16_t values for run and subRun indices.
|
||||
// Encountering something larger than this is highly unlikely, so we'll just not draw it.
|
||||
int lastRun = SkTMin(fRunCount, (1 << 16)) - 1;
|
||||
int lastRun = SkTMin(fRunCountLimit, (1 << 16)) - 1;
|
||||
// For each run in the GrTextBlob we're going to churn through all the glyphs.
|
||||
// Each run is broken into a path part and a Mask / DFT / ARGB part.
|
||||
for (int runIndex = 0; runIndex <= lastRun; runIndex++) {
|
||||
@ -465,8 +502,8 @@ void GrTextBlob::AssertEqual(const GrTextBlob& l, const GrTextBlob& r) {
|
||||
SkASSERT_RELEASE(l.fMinMaxScale == r.fMinMaxScale);
|
||||
SkASSERT_RELEASE(l.fTextType == r.fTextType);
|
||||
|
||||
SkASSERT_RELEASE(l.fRunCount == r.fRunCount);
|
||||
for (int i = 0; i < l.fRunCount; i++) {
|
||||
SkASSERT_RELEASE(l.fRunCountLimit == r.fRunCountLimit);
|
||||
for (int i = 0; i < l.fRunCountLimit; i++) {
|
||||
const Run& lRun = l.fRuns[i];
|
||||
const Run& rRun = r.fRuns[i];
|
||||
|
||||
|
@ -132,36 +132,18 @@ public:
|
||||
void setHasDistanceField() { fTextType |= kHasDistanceField_TextType; }
|
||||
void setHasBitmap() { fTextType |= kHasBitmap_TextType; }
|
||||
|
||||
int runCount() const { return fRunCount; }
|
||||
int runCountLimit() const { return fRunCountLimit; }
|
||||
|
||||
void pushBackRun(int currRun) {
|
||||
SkASSERT(currRun < fRunCount);
|
||||
if (currRun > 0) {
|
||||
Run::SubRunInfo& newRun = fRuns[currRun].fSubRunInfo.back();
|
||||
Run::SubRunInfo& lastRun = fRuns[currRun - 1].fSubRunInfo.back();
|
||||
Run* pushBackRun() {
|
||||
SkASSERT(fRunCount < fRunCountLimit);
|
||||
if (fRunCount > 0) {
|
||||
Run::SubRunInfo& newRun = fRuns[fRunCount].fSubRunInfo.back();
|
||||
Run::SubRunInfo& lastRun = fRuns[fRunCount - 1].fSubRunInfo.back();
|
||||
newRun.setAsSuccessor(lastRun);
|
||||
}
|
||||
}
|
||||
|
||||
// sets the last subrun of runIndex to use distance field text
|
||||
void setSubRunHasDistanceFields(int runIndex, bool hasLCD, bool isAntiAlias, bool hasWCoord) {
|
||||
Run& run = fRuns[runIndex];
|
||||
Run::SubRunInfo& subRun = run.fSubRunInfo.back();
|
||||
subRun.setUseLCDText(hasLCD);
|
||||
subRun.setAntiAliased(isAntiAlias);
|
||||
subRun.setDrawAsDistanceFields();
|
||||
subRun.setHasWCoord(hasWCoord);
|
||||
}
|
||||
|
||||
// sets the last subrun of runIndex to use w values
|
||||
void setSubRunHasW(int runIndex, bool hasWCoord) {
|
||||
Run& run = fRuns[runIndex];
|
||||
Run::SubRunInfo& subRun = run.fSubRunInfo.back();
|
||||
subRun.setHasWCoord(hasWCoord);
|
||||
}
|
||||
|
||||
void setRunPaintFlags(int runIndex, uint16_t paintFlags) {
|
||||
fRuns[runIndex].fPaintFlags = paintFlags & Run::kPaintFlagsMask;
|
||||
fRunCount++;
|
||||
return &fRuns[fRunCount - 1];
|
||||
}
|
||||
|
||||
void setMinAndMaxScale(SkScalar scaledMax, SkScalar scaledMin) {
|
||||
@ -170,33 +152,6 @@ public:
|
||||
fMinMaxScale = SkMinScalar(scaledMin, fMinMaxScale);
|
||||
}
|
||||
|
||||
// inits the override descriptor on the current run. All following subruns must use this
|
||||
// descriptor
|
||||
void initOverride(int runIndex) {
|
||||
Run& run = fRuns[runIndex];
|
||||
// Push back a new subrun to fill and set the override descriptor
|
||||
run.push_back();
|
||||
run.fOverrideDescriptor.reset(new SkAutoDescriptor);
|
||||
}
|
||||
|
||||
SkExclusiveStrikePtr setupCache(int runIndex,
|
||||
const SkPaint& skPaint,
|
||||
const SkSurfaceProps& props,
|
||||
SkScalerContextFlags scalerContextFlags,
|
||||
const SkMatrix& viewMatrix);
|
||||
|
||||
// Appends a glyph to the blob. If the glyph is too large, the glyph will be appended
|
||||
// as a path.
|
||||
void appendGlyph(int runIndex,
|
||||
const SkRect& positions,
|
||||
const SkPMColor4f& color,
|
||||
const sk_sp<GrTextStrike>& strike,
|
||||
GrGlyph* glyph, bool preTransformed);
|
||||
|
||||
// Appends a glyph to the blob as a path only.
|
||||
void appendPathGlyph(int runIndex, const SkPath& path,
|
||||
SkScalar x, SkScalar y, SkScalar scale, bool preTransformed);
|
||||
|
||||
static size_t GetVertexStride(GrMaskFormat maskFormat, bool hasWCoord) {
|
||||
switch (maskFormat) {
|
||||
case kA8_GrMaskFormat:
|
||||
@ -280,7 +235,7 @@ public:
|
||||
size_t size() const { return fSize; }
|
||||
|
||||
~GrTextBlob() {
|
||||
for (int i = 0; i < fRunCount; i++) {
|
||||
for (int i = 0; i < fRunCountLimit; i++) {
|
||||
fRuns[i].~Run();
|
||||
}
|
||||
}
|
||||
@ -313,7 +268,7 @@ private:
|
||||
fInitialY = y;
|
||||
|
||||
// make sure all initial subruns have the correct VM and X/Y applied
|
||||
for (int i = 0; i < fRunCount; i++) {
|
||||
for (int i = 0; i < fRunCountLimit; i++) {
|
||||
fRuns[i].fSubRunInfo[0].init(fInitialViewMatrix, x, y);
|
||||
}
|
||||
}
|
||||
@ -474,7 +429,52 @@ private:
|
||||
uint32_t fFlags;
|
||||
}; // SubRunInfo
|
||||
|
||||
SubRunInfo& push_back() {
|
||||
// sets the last subrun of runIndex to use w values
|
||||
void setSubRunHasW(bool hasWCoord) {
|
||||
Run::SubRunInfo& subRun = this->fSubRunInfo.back();
|
||||
subRun.setHasWCoord(hasWCoord);
|
||||
}
|
||||
|
||||
// inits the override descriptor on the current run. All following subruns must use this
|
||||
// descriptor
|
||||
void initOverride() {
|
||||
// Push back a new subrun to fill and set the override descriptor
|
||||
this->pushBackSubRun();
|
||||
fOverrideDescriptor.reset(new SkAutoDescriptor);
|
||||
}
|
||||
|
||||
// Appends a glyph to the blob as a path only.
|
||||
void appendPathGlyph(
|
||||
const SkPath& path, SkPoint position, SkScalar scale, bool preTransformed);
|
||||
|
||||
// Appends a glyph to the blob. If the glyph is too large, the glyph will be appended
|
||||
// as a path.
|
||||
void appendGlyph(GrTextBlob* blob,
|
||||
const sk_sp<GrTextStrike>& strike,
|
||||
const SkGlyph& skGlyph, GrGlyph::MaskStyle maskStyle,
|
||||
SkPoint origin,
|
||||
const SkPMColor4f& color, SkGlyphCache* skGlyphCache,
|
||||
SkScalar textRatio, bool needsTransform);
|
||||
|
||||
SkExclusiveStrikePtr setupCache(const SkPaint& skPaint,
|
||||
const SkSurfaceProps& props,
|
||||
SkScalerContextFlags scalerContextFlags,
|
||||
const SkMatrix& viewMatrix);
|
||||
|
||||
void setRunPaintFlags(uint16_t paintFlags) {
|
||||
fPaintFlags = paintFlags & Run::kPaintFlagsMask;
|
||||
}
|
||||
|
||||
// sets the last subrun of runIndex to use distance field text
|
||||
void setSubRunHasDistanceFields(bool hasLCD, bool isAntiAlias, bool hasWCoord) {
|
||||
Run::SubRunInfo& subRun = fSubRunInfo.back();
|
||||
subRun.setUseLCDText(hasLCD);
|
||||
subRun.setAntiAliased(isAntiAlias);
|
||||
subRun.setDrawAsDistanceFields();
|
||||
subRun.setHasWCoord(hasWCoord);
|
||||
}
|
||||
|
||||
SubRunInfo& pushBackSubRun() {
|
||||
// Forward glyph / vertex information to seed the new sub run
|
||||
SubRunInfo& newSubRun = fSubRunInfo.push_back();
|
||||
const SubRunInfo& prevSubRun = fSubRunInfo.fromBack(1);
|
||||
@ -559,7 +559,8 @@ private:
|
||||
// maximum minimum scale, and minimum maximum scale, we can support before we need to regen
|
||||
SkScalar fMaxMinScale;
|
||||
SkScalar fMinMaxScale;
|
||||
int fRunCount;
|
||||
int fRunCount{0};
|
||||
int fRunCountLimit;
|
||||
uint8_t fTextType;
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user