Skip to content

Commit 3838fe3

Browse files
herbderbySkia Commit-Bot
authored andcommitted
Use SkDrawableGlyphBuffer for bitmap rendering
Change-Id: I0e7c995123c55b63b2d4c9ddee033d7098cdc358 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/247416 Reviewed-by: Ben Wagner <bungeman@google.com> Commit-Queue: Herb Derby <herb@google.com>
1 parent caf025e commit 3838fe3

File tree

9 files changed

+125
-124
lines changed

9 files changed

+125
-124
lines changed

src/core/SkDraw.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,11 +84,11 @@ class SkDraw : public SkGlyphRunListPainter::BitmapDevicePainter {
8484
this->drawPath(src, paint, nullptr, false, !isHairline, customBlitter);
8585
}
8686

87-
void paintPaths(SkSpan<const SkPathPos> pathsAndPositions,
87+
void paintPaths(SkDrawableGlyphBuffer* drawables,
8888
SkScalar scale,
8989
const SkPaint& paint) const override;
9090

91-
void paintMasks(SkSpan<const SkMask> masks, const SkPaint& paint) const override;
91+
void paintMasks(SkDrawableGlyphBuffer* drawables, const SkPaint& paint) const override;
9292

9393
static bool ComputeMaskBounds(const SkRect& devPathBounds, const SkIRect* clipBounds,
9494
const SkMaskFilter* filter, const SkMatrix* filterMatrix,

src/core/SkDraw_text.cpp

Lines changed: 64 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "src/core/SkScalerContext.h"
1313
#include "src/core/SkStrike.h"
1414
#include "src/core/SkUtils.h"
15+
#include <climits>
1516

1617
// disable warning : local variable used without having been initialized
1718
#if defined _WIN32
@@ -21,7 +22,18 @@
2122

2223
////////////////////////////////////////////////////////////////////////////////////////////////////
2324

24-
void SkDraw::paintMasks(SkSpan<const SkMask> masks, const SkPaint& paint) const {
25+
static bool check_glyph_position(SkPoint position) {
26+
// Prevent glyphs from being drawn outside of or straddling the edge of device space.
27+
// Comparisons written a little weirdly so that NaN coordinates are treated safely.
28+
auto gt = [](float a, int b) { return !(a <= (float)b); };
29+
auto lt = [](float a, int b) { return !(a >= (float)b); };
30+
return !(gt(position.fX, INT_MAX - (INT16_MAX + SkTo<int>(UINT16_MAX))) ||
31+
lt(position.fX, INT_MIN - (INT16_MIN + 0 /*UINT16_MIN*/)) ||
32+
gt(position.fY, INT_MAX - (INT16_MAX + SkTo<int>(UINT16_MAX))) ||
33+
lt(position.fY, INT_MIN - (INT16_MIN + 0 /*UINT16_MIN*/)));
34+
}
35+
36+
void SkDraw::paintMasks(SkDrawableGlyphBuffer* drawables, const SkPaint& paint) const {
2537

2638
// The size used for a typical blitter.
2739
SkSTArenaAlloc<3308> alloc;
@@ -38,62 +50,74 @@ void SkDraw::paintMasks(SkSpan<const SkMask> masks, const SkPaint& paint) const
3850
bool useRegion = fRC->isBW() && !fRC->isRect();
3951

4052
if (useRegion) {
41-
for (const SkMask& mask : masks) {
42-
SkRegion::Cliperator clipper(fRC->bwRgn(), mask.fBounds);
53+
for (auto t : drawables->drawable()) {
54+
SkGlyphVariant glyph; SkPoint pos;
55+
std::tie(glyph, pos) = t;
56+
if (check_glyph_position(pos)) {
57+
SkMask mask = glyph.glyph()->mask(pos);
58+
59+
SkRegion::Cliperator clipper(fRC->bwRgn(), mask.fBounds);
60+
61+
if (!clipper.done()) {
62+
if (SkMask::kARGB32_Format == mask.fFormat) {
63+
SkBitmap bm;
64+
bm.installPixels(SkImageInfo::MakeN32Premul(mask.fBounds.size()),
65+
mask.fImage,
66+
mask.fRowBytes);
67+
this->drawSprite(bm, mask.fBounds.x(), mask.fBounds.y(), paint);
68+
} else {
69+
const SkIRect& cr = clipper.rect();
70+
do {
71+
blitter->blitMask(mask, cr);
72+
clipper.next();
73+
} while (!clipper.done());
74+
}
75+
}
76+
}
77+
}
78+
} else {
79+
SkIRect clipBounds = fRC->isBW() ? fRC->bwRgn().getBounds()
80+
: fRC->aaRgn().getBounds();
81+
for (auto t : drawables->drawable()) {
82+
SkGlyphVariant glyph; SkPoint pos;
83+
std::tie(glyph, pos) = t;
84+
if (check_glyph_position(pos)) {
85+
SkMask mask = glyph.glyph()->mask(pos);
86+
SkIRect storage;
87+
const SkIRect* bounds = &mask.fBounds;
88+
89+
// this extra test is worth it, assuming that most of the time it succeeds
90+
// since we can avoid writing to storage
91+
if (!clipBounds.containsNoEmptyCheck(mask.fBounds)) {
92+
if (!storage.intersect(mask.fBounds, clipBounds)) {
93+
continue;
94+
}
95+
bounds = &storage;
96+
}
4397

44-
if (!clipper.done()) {
4598
if (SkMask::kARGB32_Format == mask.fFormat) {
4699
SkBitmap bm;
47100
bm.installPixels(SkImageInfo::MakeN32Premul(mask.fBounds.size()),
48101
mask.fImage,
49102
mask.fRowBytes);
50103
this->drawSprite(bm, mask.fBounds.x(), mask.fBounds.y(), paint);
51104
} else {
52-
const SkIRect& cr = clipper.rect();
53-
do {
54-
blitter->blitMask(mask, cr);
55-
clipper.next();
56-
} while (!clipper.done());
105+
blitter->blitMask(mask, *bounds);
57106
}
58107
}
59108
}
60-
} else {
61-
SkIRect clipBounds = fRC->isBW() ? fRC->bwRgn().getBounds()
62-
: fRC->aaRgn().getBounds();
63-
for (const SkMask& mask : masks) {
64-
SkIRect storage;
65-
const SkIRect* bounds = &mask.fBounds;
66-
67-
// this extra test is worth it, assuming that most of the time it succeeds
68-
// since we can avoid writing to storage
69-
if (!clipBounds.containsNoEmptyCheck(mask.fBounds)) {
70-
if (!storage.intersect(mask.fBounds, clipBounds)) {
71-
continue;
72-
}
73-
bounds = &storage;
74-
}
75-
76-
if (SkMask::kARGB32_Format == mask.fFormat) {
77-
SkBitmap bm;
78-
bm.installPixels(SkImageInfo::MakeN32Premul(mask.fBounds.size()),
79-
mask.fImage,
80-
mask.fRowBytes);
81-
this->drawSprite(bm, mask.fBounds.x(), mask.fBounds.y(), paint);
82-
} else {
83-
blitter->blitMask(mask, *bounds);
84-
}
85-
}
86109
}
87110
}
88111

89-
void SkDraw::paintPaths(SkSpan<const SkPathPos> pathsAndPositions,
112+
void SkDraw::paintPaths(SkDrawableGlyphBuffer* drawables,
90113
SkScalar scale,
91114
const SkPaint& paint) const {
92-
for (const auto& pathAndPos : pathsAndPositions) {
115+
for (auto t : drawables->drawable()) {
116+
SkGlyphVariant path; SkPoint pos;
117+
std::tie(path, pos) = t;
93118
SkMatrix m;
94-
SkPoint position = pathAndPos.position;
95-
m.setScaleTranslate(scale, scale, position.x(), position.y());
96-
this->drawPath(*pathAndPos.path, paint, &m, false);
119+
m.setScaleTranslate(scale, scale, pos.x(), pos.y());
120+
this->drawPath(*path.path(), paint, &m, false);
97121
}
98122
}
99123

src/core/SkGlyphBuffer.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
#include "src/core/SkStrikeForGPU.h"
1111

1212
void SkDrawableGlyphBuffer::ensureSize(size_t size) {
13-
SkASSERT(fPhase == kReset);
1413
if (size > fMaxSize) {
1514
fMultiBuffer.reset(size);
1615
fPositions.reset(size);
@@ -19,13 +18,12 @@ void SkDrawableGlyphBuffer::ensureSize(size_t size) {
1918

2019
fInputSize = 0;
2120
fDrawableSize = 0;
22-
SkDEBUGCODE(fPhase = kPackedID);
2321
}
2422

2523
void SkDrawableGlyphBuffer::startSource(
2624
const SkZip<const SkGlyphID, const SkPoint>& source, SkPoint origin) {
27-
SkASSERT(fPhase == kPackedID);
2825
fInputSize = source.size();
26+
fDrawableSize = 0;
2927

3028
// Map all the positions.
3129
auto positions = source.get<1>();
@@ -44,8 +42,8 @@ void SkDrawableGlyphBuffer::startDevice(
4442
const SkZip<const SkGlyphID, const SkPoint>& source,
4543
SkPoint origin, const SkMatrix& viewMatrix,
4644
const SkGlyphPositionRoundingSpec& roundingSpec) {
47-
SkASSERT(fPhase == kPackedID);
4845
fInputSize = source.size();
46+
fDrawableSize = 0;
4947

5048
// Map the positions including subpixel position.
5149
auto positions = source.get<1>();

src/core/SkGlyphBuffer.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,6 @@ class SkDrawableGlyphBuffer {
133133
#ifdef SK_DEBUG
134134
enum {
135135
kReset,
136-
kPackedID,
137136
kInput,
138137
kProcess,
139138
kDraw

src/core/SkGlyphRunPainter.cpp

Lines changed: 9 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -76,17 +76,6 @@ SkGlyphRunListPainter::SkGlyphRunListPainter(const GrRenderTargetContext& rtc)
7676

7777
#endif
7878

79-
static bool check_glyph_position(SkPoint position) {
80-
// Prevent glyphs from being drawn outside of or straddling the edge of device space.
81-
// Comparisons written a little weirdly so that NaN coordinates are treated safely.
82-
auto gt = [](float a, int b) { return !(a <= (float)b); };
83-
auto lt = [](float a, int b) { return !(a >= (float)b); };
84-
return !(gt(position.fX, INT_MAX - (INT16_MAX + SkTo<int>(UINT16_MAX))) ||
85-
lt(position.fX, INT_MIN - (INT16_MIN + 0 /*UINT16_MIN*/)) ||
86-
gt(position.fY, INT_MAX - (INT16_MAX + SkTo<int>(UINT16_MAX))) ||
87-
lt(position.fY, INT_MIN - (INT16_MIN + 0 /*UINT16_MIN*/)));
88-
}
89-
9079
SkSpan<const SkPackedGlyphID> SkGlyphRunListPainter::DeviceSpacePackedGlyphIDs(
9180
const SkGlyphPositionRoundingSpec& roundingSpec,
9281
const SkMatrix& viewMatrix,
@@ -148,7 +137,6 @@ void SkGlyphRunListPainter::drawForBitmapDevice(
148137
SkPoint origin = glyphRunList.origin();
149138
for (auto& glyphRun : glyphRunList) {
150139
const SkFont& runFont = glyphRun.font();
151-
auto runSize = glyphRun.runSize();
152140

153141
if (SkStrikeSpec::ShouldDrawAsPath(runPaint, runFont, deviceMatrix)) {
154142

@@ -157,71 +145,24 @@ void SkGlyphRunListPainter::drawForBitmapDevice(
157145

158146
auto strike = strikeSpec.findOrCreateExclusiveStrike();
159147

160-
// Used for the side effect for creating the right positions.
161-
SourceSpacePackedGlyphIDs(
162-
origin,
163-
runSize,
164-
glyphRun.glyphsIDs().data(),
165-
glyphRun.positions().data(),
166-
fPositions,
167-
fPackedGlyphIDs);
168-
169-
SkBulkGlyphMetricsAndPaths glyphPaths{strikeSpec};
170-
auto glyphs = glyphPaths.glyphs(glyphRun.glyphsIDs());
171-
172-
SkTDArray<SkPathPos> pathsAndPositions;
173-
pathsAndPositions.setReserve(runSize);
174-
for (size_t i = 0; i < runSize; i++) {
175-
const SkGlyph& glyph = *glyphs[i];
176-
SkPoint position = fPositions[i];
177-
if (check_glyph_position(position) && !glyph.isEmpty() && glyph.path() != nullptr) {
178-
pathsAndPositions.push_back(SkPathPos{glyph.path(), position});
179-
}
180-
}
148+
fDrawable.startSource(glyphRun.source(), origin);
149+
strike->prepareForDrawingPathsCPU(&fDrawable);
181150

182151
// The paint we draw paths with must have the same anti-aliasing state as the runFont
183152
// allowing the paths to have the same edging as the glyph masks.
184153
SkPaint pathPaint = runPaint;
185154
pathPaint.setAntiAlias(runFont.hasSomeAntiAliasing());
186155

187-
bitmapDevice->paintPaths(
188-
SkSpan<const SkPathPos>{pathsAndPositions.begin(), pathsAndPositions.size()},
189-
strikeSpec.strikeToSourceRatio(), pathPaint);
156+
bitmapDevice->paintPaths(&fDrawable, strikeSpec.strikeToSourceRatio(), pathPaint);
190157
} else {
191158
SkStrikeSpec strikeSpec = SkStrikeSpec::MakeMask(
192159
runFont, runPaint, props, fScalerContextFlags, deviceMatrix);
193160

194161
auto strike = strikeSpec.findOrCreateExclusiveStrike();
195162

196-
auto packedGlyphIDs = DeviceSpacePackedGlyphIDs(
197-
strike->roundingSpec(),
198-
deviceMatrix,
199-
origin,
200-
runSize,
201-
glyphRun.glyphsIDs().data(),
202-
glyphRun.positions().data(),
203-
fPositions,
204-
fPackedGlyphIDs);
205-
206-
SkBulkGlyphMetricsAndImages glyphImages{strikeSpec};
207-
SkSpan<const SkGlyph*> glyphs = glyphImages.glyphs(packedGlyphIDs);
208-
209-
SkTDArray<SkMask> masks;
210-
masks.setReserve(runSize);
211-
212-
SkPoint* posCursor = fPositions.get();
213-
for (const SkGlyph* glyph : glyphs) {
214-
SkPoint position = *posCursor++;
215-
// The glyph could have dimensions (!isEmpty()), but still may have no bits if
216-
// the width is too wide. So check that there really is an image.
217-
if (check_glyph_position(position)
218-
&& !glyph->isEmpty()
219-
&& glyph->image() != nullptr) {
220-
masks.push_back(glyph->mask(position));
221-
}
222-
}
223-
224-
bitmapDevice->paintMasks(SkSpan<const SkMask>{masks.begin(), masks.size()}, runPaint);
163+
fDrawable.startDevice(glyphRun.source(), origin, deviceMatrix, strike->roundingSpec());
164+
strike->prepareForDrawingMasksCPU(&fDrawable);
165+
bitmapDevice->paintMasks(&fDrawable, runPaint);
225166
}
226167
}
227168
}
@@ -930,9 +871,9 @@ std::unique_ptr<GrDrawOp> GrTextContext::createOp_TestingOnly(GrRecordingContext
930871
#endif // GR_TEST_UTILS
931872
#endif // SK_SUPPORT_GPU
932873

933-
SkGlyphRunListPainter::ScopedBuffers::ScopedBuffers(SkGlyphRunListPainter* painter, int size)
874+
SkGlyphRunListPainter::ScopedBuffers::ScopedBuffers(SkGlyphRunListPainter* painter, size_t size)
934875
: fPainter{painter} {
935-
SkASSERT(size >= 0);
876+
fPainter->fDrawable.ensureSize(size);
936877
if (fPainter->fMaxRunSize < size) {
937878
fPainter->fMaxRunSize = size;
938879

@@ -943,6 +884,7 @@ SkGlyphRunListPainter::ScopedBuffers::ScopedBuffers(SkGlyphRunListPainter* paint
943884
}
944885

945886
SkGlyphRunListPainter::ScopedBuffers::~ScopedBuffers() {
887+
fPainter->fDrawable.reset();
946888
fPainter->fPaths.clear();
947889
fPainter->fARGBGlyphsIDs.clear();
948890
fPainter->fARGBPositions.clear();

src/core/SkGlyphRunPainter.h

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
#include "include/core/SkSurfaceProps.h"
1212
#include "src/core/SkDistanceFieldGen.h"
13+
#include "src/core/SkGlyphBuffer.h"
1314
#include "src/core/SkGlyphRun.h"
1415
#include "src/core/SkScalerContext.h"
1516
#include "src/core/SkTextBlobPriv.h"
@@ -66,11 +67,10 @@ class SkGlyphRunListPainter {
6667
public:
6768
virtual ~BitmapDevicePainter() = default;
6869

69-
virtual void paintPaths(SkSpan<const SkPathPos> pathsAndPositions,
70-
SkScalar scale,
71-
const SkPaint& paint) const = 0;
70+
virtual void paintPaths(
71+
SkDrawableGlyphBuffer* drawables, SkScalar scale, const SkPaint& paint) const = 0;
7272

73-
virtual void paintMasks(SkSpan<const SkMask> masks, const SkPaint& paint) const = 0;
73+
virtual void paintMasks(SkDrawableGlyphBuffer* drawables, const SkPaint& paint) const = 0;
7474
};
7575

7676
void drawForBitmapDevice(
@@ -93,7 +93,7 @@ class SkGlyphRunListPainter {
9393
SkScalerContextFlags flags, SkStrikeForGPUCacheInterface* strikeCache);
9494

9595
struct ScopedBuffers {
96-
ScopedBuffers(SkGlyphRunListPainter* painter, int size);
96+
ScopedBuffers(SkGlyphRunListPainter* painter, size_t size);
9797
~ScopedBuffers();
9898
SkGlyphRunListPainter* fPainter;
9999
};
@@ -143,7 +143,9 @@ class SkGlyphRunListPainter {
143143

144144
SkStrikeForGPUCacheInterface* const fStrikeCache;
145145

146-
int fMaxRunSize{0};
146+
SkDrawableGlyphBuffer fDrawable;
147+
148+
size_t fMaxRunSize{0};
147149
SkAutoTMalloc<SkPoint> fPositions;
148150
SkAutoTMalloc<SkPackedGlyphID> fPackedGlyphIDs;
149151
SkAutoTMalloc<SkGlyphPos> fGlyphPos;

src/core/SkOverdrawCanvas.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,11 +50,13 @@ class TextDevice : public SkNoPixelsDevice, public SkGlyphRunListPainter::Bitmap
5050
fOverdrawCanvas{overdrawCanvas},
5151
fPainter{props, kN32_SkColorType, nullptr, SkStrikeCache::GlobalStrikeCache()} {}
5252

53-
void paintPaths(SkSpan<const SkPathPos> pathsAndPositions, SkScalar scale,
54-
const SkPaint& paint) const override {}
53+
void paintPaths(SkDrawableGlyphBuffer*, SkScalar scale, const SkPaint& paint) const override {}
5554

56-
void paintMasks(SkSpan<const SkMask> masks, const SkPaint& paint) const override {
57-
for (auto& mask : masks) {
55+
void paintMasks(SkDrawableGlyphBuffer* drawables, const SkPaint& paint) const override {
56+
for (auto t : drawables->drawable()) {
57+
SkGlyphVariant glyph; SkPoint pos;
58+
std::tie(glyph, pos) = t;
59+
SkMask mask = glyph.glyph()->mask(pos);
5860
fOverdrawCanvas->drawRect(SkRect::Make(mask.fBounds), SkPaint());
5961
}
6062
}

0 commit comments

Comments
 (0)