Flutter Engine
The Flutter Engine
Classes | Public Member Functions | List of all members
SkGlyphRunListPainterCPU Class Reference

#include <SkGlyphRunPainter.h>

Classes

class  BitmapDevicePainter
 

Public Member Functions

 SkGlyphRunListPainterCPU (const SkSurfaceProps &props, SkColorType colorType, SkColorSpace *cs)
 
void drawForBitmapDevice (SkCanvas *canvas, const BitmapDevicePainter *bitmapDevice, const sktext::GlyphRunList &glyphRunList, const SkPaint &paint, const SkMatrix &drawMatrix)
 

Detailed Description

Definition at line 29 of file SkGlyphRunPainter.h.

Constructor & Destructor Documentation

◆ SkGlyphRunListPainterCPU()

SkGlyphRunListPainterCPU::SkGlyphRunListPainterCPU ( const SkSurfaceProps props,
SkColorType  colorType,
SkColorSpace cs 
)

Definition at line 166 of file SkGlyphRunPainter.cpp.

169 : fDeviceProps{props}
170 , fBitmapFallbackProps{props.cloneWithPixelGeometry(kUnknown_SkPixelGeometry)}
171 , fColorType{colorType}
172 , fScalerContextFlags{compute_scaler_context_flags(cs)} {}
static SkColorType colorType(AImageDecoder *decoder, const AImageDecoderHeaderInfo *headerInfo)
@ kUnknown_SkPixelGeometry
SkSurfaceProps cloneWithPixelGeometry(SkPixelGeometry newPixelGeometry) const

Member Function Documentation

◆ drawForBitmapDevice()

void SkGlyphRunListPainterCPU::drawForBitmapDevice ( SkCanvas canvas,
const BitmapDevicePainter bitmapDevice,
const sktext::GlyphRunList glyphRunList,
const SkPaint paint,
const SkMatrix drawMatrix 
)

Definition at line 174 of file SkGlyphRunPainter.cpp.

178 {
179 STArray<64, const SkGlyph*> acceptedPackedGlyphIDs;
180 STArray<64, SkPoint> acceptedPositions;
181 STArray<64, SkGlyphID> rejectedGlyphIDs;
182 STArray<64, SkPoint> rejectedPositions;
183 const int maxGlyphRunSize = glyphRunList.maxGlyphRunSize();
184 acceptedPackedGlyphIDs.resize(maxGlyphRunSize);
185 acceptedPositions.resize(maxGlyphRunSize);
186 const auto acceptedBuffer = SkMakeZip(acceptedPackedGlyphIDs, acceptedPositions);
187 rejectedGlyphIDs.resize(maxGlyphRunSize);
188 rejectedPositions.resize(maxGlyphRunSize);
189 const auto rejectedBuffer = SkMakeZip(rejectedGlyphIDs, rejectedPositions);
190
191 // The bitmap blitters can only draw lcd text to a N32 bitmap in srcOver. Otherwise,
192 // convert the lcd text into A8 text. The props communicate this to the scaler.
193 auto& props = (kN32_SkColorType == fColorType && paint.isSrcOver())
194 ? fDeviceProps
195 : fBitmapFallbackProps;
196
197 SkPoint drawOrigin = glyphRunList.origin();
198 SkMatrix positionMatrix{drawMatrix};
199 positionMatrix.preTranslate(drawOrigin.x(), drawOrigin.y());
200 for (auto& glyphRun : glyphRunList) {
201 const SkFont& runFont = glyphRun.font();
202
204
205 if (SkStrikeSpec::ShouldDrawAsPath(paint, runFont, positionMatrix)) {
206 auto [strikeSpec, strikeToSourceScale] =
207 SkStrikeSpec::MakePath(runFont, paint, props, fScalerContextFlags);
208
209 auto strike = strikeSpec.findOrCreateStrike();
210
211 {
212 auto [accepted, rejected] = prepare_for_path_drawing(strike.get(),
213 source,
214 acceptedBuffer,
215 rejectedBuffer);
216
217 source = rejected;
218 // The paint we draw paths with must have the same anti-aliasing state as the
219 // runFont allowing the paths to have the same edging as the glyph masks.
220 SkPaint pathPaint = paint;
221 pathPaint.setAntiAlias(runFont.hasSomeAntiAliasing());
222
223 const bool stroking = pathPaint.getStyle() != SkPaint::kFill_Style;
224 const bool hairline = pathPaint.getStrokeWidth() == 0;
225 const bool needsExactCTM = pathPaint.getShader() ||
226 pathPaint.getPathEffect() ||
227 pathPaint.getMaskFilter() ||
228 (stroking && !hairline);
229
230 if (!needsExactCTM) {
231 for (auto [glyph, pos] : accepted) {
232 const SkPath* path = glyph->path();
233 SkMatrix m;
234 SkPoint translate = drawOrigin + pos;
235 m.setScaleTranslate(strikeToSourceScale, strikeToSourceScale,
236 translate.x(), translate.y());
237 SkAutoCanvasRestore acr(canvas, true);
238 canvas->concat(m);
239 canvas->drawPath(*path, pathPaint);
240 }
241 } else {
242 for (auto [glyph, pos] : accepted) {
243 const SkPath* path = glyph->path();
244 SkMatrix m;
245 SkPoint translate = drawOrigin + pos;
246 m.setScaleTranslate(strikeToSourceScale, strikeToSourceScale,
247 translate.x(), translate.y());
248
249 SkPath deviceOutline;
250 path->transform(m, &deviceOutline);
251 deviceOutline.setIsVolatile(true);
252 canvas->drawPath(deviceOutline, pathPaint);
253 }
254 }
255 }
256
257 if (!source.empty()) {
258 auto [accepted, rejected] = prepare_for_drawable_drawing(strike.get(),
259 source,
260 acceptedBuffer,
261 rejectedBuffer);
262 source = rejected;
263
264 for (auto [glyph, pos] : accepted) {
265 SkDrawable* drawable = glyph->drawable();
266 SkMatrix m;
267 SkPoint translate = drawOrigin + pos;
268 m.setScaleTranslate(strikeToSourceScale, strikeToSourceScale,
269 translate.x(), translate.y());
270 SkAutoCanvasRestore acr(canvas, false);
271 SkRect drawableBounds = drawable->getBounds();
272 m.mapRect(&drawableBounds);
273 canvas->saveLayer(&drawableBounds, &paint);
274 drawable->draw(canvas, &m);
275 }
276 }
277 }
278 if (!source.empty() && !positionMatrix.hasPerspective()) {
280 runFont, paint, props, fScalerContextFlags, positionMatrix);
281
282 auto strike = strikeSpec.findOrCreateStrike();
283
284 auto [accepted, rejected] = prepare_for_direct_mask_drawing(strike.get(),
285 positionMatrix,
286 source,
287 acceptedBuffer,
288 rejectedBuffer);
289 source = rejected;
290 bitmapDevice->paintMasks(accepted, paint);
291 }
292 if (!source.empty()) {
293 std::vector<SkPoint> sourcePositions;
294
295 // Create a strike is source space to calculate scale information.
296 SkStrikeSpec scaleStrikeSpec = SkStrikeSpec::MakeMask(
297 runFont, paint, props, fScalerContextFlags, SkMatrix::I());
298 SkBulkGlyphMetrics metrics{scaleStrikeSpec};
299
300 auto glyphIDs = source.get<0>();
301 auto positions = source.get<1>();
302 SkSpan<const SkGlyph*> glyphs = metrics.glyphs(glyphIDs);
303 SkScalar maxScale = SK_ScalarMin;
304
305 // Calculate the scale that makes the longest edge 1:1 with its side in the cache.
306 for (auto [glyph, pos] : SkMakeZip(glyphs, positions)) {
307 if (glyph->isEmpty()) {
308 continue;
309 }
310 SkPoint corners[4];
311 SkPoint srcPos = pos + drawOrigin;
312 // Store off the positions in device space to position the glyphs during drawing.
313 sourcePositions.push_back(srcPos);
314 SkRect rect = glyph->rect();
315 rect.makeOffset(srcPos);
316 positionMatrix.mapRectToQuad(corners, rect);
317 // left top -> right top
318 SkScalar scale = (corners[1] - corners[0]).length() / rect.width();
319 maxScale = std::max(maxScale, scale);
320 // right top -> right bottom
321 scale = (corners[2] - corners[1]).length() / rect.height();
322 maxScale = std::max(maxScale, scale);
323 // right bottom -> left bottom
324 scale = (corners[3] - corners[2]).length() / rect.width();
325 maxScale = std::max(maxScale, scale);
326 // left bottom -> left top
327 scale = (corners[0] - corners[3]).length() / rect.height();
328 maxScale = std::max(maxScale, scale);
329 }
330
331 if (maxScale <= 0) {
332 continue; // to the next run.
333 }
334
335 if (maxScale * runFont.getSize() > 256) {
336 maxScale = 256.0f / runFont.getSize();
337 }
338
339 SkMatrix cacheScale = SkMatrix::Scale(maxScale, maxScale);
341 runFont, paint, props, fScalerContextFlags, cacheScale);
342
343 auto strike = strikeSpec.findOrCreateStrike();
344
345 auto [accepted, rejected] = prepare_for_direct_mask_drawing(strike.get(),
346 positionMatrix,
347 source,
348 acceptedBuffer,
349 rejectedBuffer);
350 const SkScalar invMaxScale = 1.0f/maxScale;
351 for (auto [glyph, srcPos] : SkMakeZip(accepted.get<0>(), sourcePositions)) {
352 SkMask mask = glyph->mask();
353 // TODO: is this needed will A8 and BW just work?
354 if (mask.fFormat != SkMask::kARGB32_Format) {
355 continue;
356 }
357 SkBitmap bm;
359 const_cast<uint8_t*>(mask.fImage),
360 mask.fRowBytes);
361 bm.setImmutable();
362
363 // Since the glyph in the cache is scaled by maxScale, its top left vector is too
364 // long. Reduce it to find proper positions on the device.
365 SkPoint realPos =
366 srcPos + SkPoint::Make(mask.fBounds.left(), mask.fBounds.top())*invMaxScale;
367
368 // Calculate the preConcat matrix for drawBitmap to get the rectangle from the
369 // glyph cache (which is multiplied by maxScale) to land in the right place.
370 SkMatrix translate = SkMatrix::Translate(realPos);
371 translate.preScale(invMaxScale, invMaxScale);
372
373 // Draw the bitmap using the rect from the scaled cache, and not the source
374 // rectangle for the glyph.
375 bitmapDevice->drawBitmap(bm, translate, nullptr, SkFilterMode::kLinear, paint);
376 }
377 }
378
379 // TODO: have the mask stage above reject the glyphs that are too big, and handle the
380 // rejects in a more sophisticated stage.
381 }
382}
uint16_t glyphs[5]
Definition: FontMgrTest.cpp:46
SkPoint pos
#define SK_ScalarMin
Definition: SkScalar.h:25
constexpr auto SkMakeZip(Ts &&... ts)
Definition: SkZip.h:212
void setImmutable()
Definition: SkBitmap.cpp:400
bool installPixels(const SkImageInfo &info, void *pixels, size_t rowBytes, void(*releaseProc)(void *addr, void *context), void *context)
Definition: SkBitmap.cpp:323
bool empty() const
Definition: SkBitmap.h:210
int saveLayer(const SkRect *bounds, const SkPaint *paint)
Definition: SkCanvas.cpp:496
void drawPath(const SkPath &path, const SkPaint &paint)
Definition: SkCanvas.cpp:1747
void concat(const SkMatrix &matrix)
Definition: SkCanvas.cpp:1318
SkRect getBounds()
Definition: SkDrawable.cpp:71
void draw(SkCanvas *, const SkMatrix *=nullptr)
Definition: SkDrawable.cpp:43
Definition: SkFont.h:35
SkScalar getSize() const
Definition: SkFont.h:217
static SkMatrix Scale(SkScalar sx, SkScalar sy)
Definition: SkMatrix.h:75
static SkMatrix Translate(SkScalar dx, SkScalar dy)
Definition: SkMatrix.h:91
static const SkMatrix & I()
Definition: SkMatrix.cpp:1544
SkMatrix & preTranslate(SkScalar dx, SkScalar dy)
Definition: SkMatrix.cpp:263
SkMatrix & preScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py)
Definition: SkMatrix.cpp:315
Style getStyle() const
Definition: SkPaint.h:204
SkPathEffect * getPathEffect() const
Definition: SkPaint.h:506
void setAntiAlias(bool aa)
Definition: SkPaint.h:170
@ kFill_Style
set to fill geometry
Definition: SkPaint.h:193
SkMaskFilter * getMaskFilter() const
Definition: SkPaint.h:534
SkScalar getStrokeWidth() const
Definition: SkPaint.h:300
SkShader * getShader() const
Definition: SkPaint.h:397
Definition: SkPath.h:59
SkPath & setIsVolatile(bool isVolatile)
Definition: SkPath.h:370
static SkStrikeSpec MakeMask(const SkFont &font, const SkPaint &paint, const SkSurfaceProps &surfaceProps, SkScalerContextFlags scalerContextFlags, const SkMatrix &deviceMatrix)
static bool ShouldDrawAsPath(const SkPaint &paint, const SkFont &font, const SkMatrix &matrix)
sk_sp< SkStrike > findOrCreateStrike() const
static std::tuple< SkStrikeSpec, SkScalar > MakePath(const SkFont &font, const SkPaint &paint, const SkSurfaceProps &surfaceProps, SkScalerContextFlags scalerContextFlags)
Definition: SkZip.h:25
void resize(size_t count)
Definition: SkTArray.h:423
size_t maxGlyphRunSize() const
Definition: GlyphRun.h:97
SkPoint origin() const
Definition: GlyphRun.h:114
const Paint & paint
Definition: color_source.cc:38
SkBitmap source
Definition: examples.cpp:28
float SkScalar
Definition: extension.cpp:12
static float max(float r, float g, float b)
Definition: hsl.cpp:49
size_t length
sk_sp< SkBlender > blender SkRect rect
Definition: SkRecords.h:350
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir path
Definition: switches.h:57
std::tuple< SkZip< const SkGlyphID, const SkPoint >, SkZip< SkGlyphID, SkPoint > > prepare_for_drawable_drawing(StrikeForGPU *strike, SkZip< const SkGlyphID, const SkPoint > source, SkZip< SkGlyphID, SkPoint > acceptedBuffer, SkZip< SkGlyphID, SkPoint > rejectedBuffer)
std::tuple< SkZip< const SkGlyphID, const SkPoint >, SkZip< SkGlyphID, SkPoint > > prepare_for_path_drawing(StrikeForGPU *strike, SkZip< const SkGlyphID, const SkPoint > source, SkZip< SkGlyphID, SkPoint > acceptedBuffer, SkZip< SkGlyphID, SkPoint > rejectedBuffer)
std::tuple< SkZip< const SkPackedGlyphID, const SkPoint, const SkMask::Format >, SkZip< SkGlyphID, SkPoint >, SkRect > prepare_for_direct_mask_drawing(StrikeForGPU *strike, const SkMatrix &positionMatrix, SkZip< const SkGlyphID, const SkPoint > source, SkZip< SkPackedGlyphID, SkPoint, SkMask::Format > acceptedBuffer, SkZip< SkGlyphID, SkPoint > rejectedBuffer)
const Scalar scale
constexpr int32_t top() const
Definition: SkRect.h:120
constexpr SkISize size() const
Definition: SkRect.h:172
constexpr int32_t left() const
Definition: SkRect.h:113
static SkImageInfo MakeN32Premul(int width, int height)
Definition: SkMask.h:25
const uint32_t fRowBytes
Definition: SkMask.h:43
@ kARGB32_Format
SkPMColor.
Definition: SkMask.h:30
uint8_t const *const fImage
Definition: SkMask.h:41
const SkIRect fBounds
Definition: SkMask.h:42
const Format fFormat
Definition: SkMask.h:44
static constexpr SkPoint Make(float x, float y)
Definition: SkPoint_impl.h:173
constexpr float y() const
Definition: SkPoint_impl.h:187
constexpr float x() const
Definition: SkPoint_impl.h:181

The documentation for this class was generated from the following files: