43 if (!
buffer.isValid() || pictureData->
size() == 0) {
56 return sk_make_sp<SkPictureBackedGlyphDrawable>(std::move(
picture));
60 if (drawable ==
nullptr) {
61 buffer.writeByteArray(
nullptr, 0);
71 if (!SkTFitsIn<uint32_t>(
data->size()) ||
data->size() == 0) {
72 buffer.writeByteArray(
nullptr, 0);
82SkRect SkPictureBackedGlyphDrawable::onGetBounds() {
86size_t SkPictureBackedGlyphDrawable::onApproximateBytesUsed() {
90void SkPictureBackedGlyphDrawable::onDraw(
SkCanvas* canvas) {
99 const uint32_t dimensions =
buffer.readUInt();
100 const uint32_t leftTop =
buffer.readUInt();
108 glyph.fAdvanceX = advance.
x();
109 glyph.fAdvanceY = advance.
y();
110 glyph.fWidth = dimensions >> 16;
111 glyph.fHeight = dimensions & 0xffffu;
112 glyph.fLeft = leftTop >> 16;
113 glyph.fTop = leftTop & 0xffffu;
114 glyph.fMaskFormat =
format;
115 SkDEBUGCODE(glyph.fAdvancesBoundsFormatAndInitialPathDone =
true;)
147 return (
bits + 7) >> 3;
156 return alignof(uint8_t);
158 return alignof(uint32_t);
160 return alignof(uint16_t);
190 this->allocImage(alloc);
200 this->allocImage(alloc);
210 SkASSERT(fImage ==
nullptr || from.fImage ==
nullptr);
213 if (fImage ==
nullptr) {
214 fAdvanceX = from.fAdvanceX;
215 fAdvanceY = from.fAdvanceY;
216 fWidth = from.fWidth;
217 fHeight = from.fHeight;
220 fScalerContextBits = from.fScalerContextBits;
221 fMaskFormat = from.fMaskFormat;
224 if (from.fImage !=
nullptr && this->setImage(alloc, from.
image())) {
228 SkDEBUGCODE(fAdvancesBoundsFormatAndInitialPathDone = from.fAdvancesBoundsFormatAndInitialPathDone;)
256 fPathData = alloc->
make<SkGlyph::PathData>();
257 if (
path !=
nullptr) {
258 fPathData->fPath = *
path;
259 fPathData->fPath.updateBoundsCache();
260 fPathData->fPath.getGenerationID();
261 fPathData->fHasPath =
true;
262 fPathData->fHairline = hairline;
268 scalerContext->
getPath(*
this, alloc);
270 return this->
path() !=
nullptr;
278 this->installPath(alloc,
path, hairline);
279 return this->
path() !=
nullptr;
287 if (fPathData->fHasPath) {
288 return &fPathData->fPath;
296 return fPathData->fHairline;
302 fDrawableData = alloc->
make<SkGlyph::DrawableData>();
304 fDrawableData->fDrawable = std::move(
drawable);
305 fDrawableData->fDrawable->getGenerationID();
306 fDrawableData->fHasDrawable =
true;
313 this->installDrawable(alloc, std::move(
drawable));
321 this->installDrawable(alloc, std::move(
drawable));
330 if (fDrawableData->fHasDrawable) {
331 return fDrawableData->fDrawable.get();
337 buffer.writeUInt(fID.value());
338 buffer.writePoint({fAdvanceX, fAdvanceY});
339 buffer.writeUInt(fWidth << 16 | fHeight);
343 const uint32_t
left =
static_cast<uint16_t
>(fLeft);
344 const uint32_t
top =
static_cast<uint16_t
>(fTop);
346 buffer.writeUInt(SkTo<uint32_t>(fMaskFormat));
366 size_t memoryIncrease = 0;
371 this->installImage(imageData);
375 return memoryIncrease;
381 const bool hasPath = this->
path() !=
nullptr;
392 size_t memoryIncrease = 0;
393 const bool hasPath =
buffer.readBool();
408 this->
setPath(alloc,
nullptr,
false);
411 return memoryIncrease;
456 if (0 <= t && t < 1) {
457 expandGap(pts[0].fX + t * (pts[1].fX - pts[0].fX));
471 float intersectionStorage[3];
475 for(
double intersection : intersections) {
476 expandGap(intersection);
481 auto addPts = [&expandGap, &pts, topOffset, bottomOffset](
int ptCount) {
482 for (
int i = 0;
i < ptCount; ++
i) {
483 if (topOffset < pts[
i].fY && pts[
i].fY < bottomOffset) {
484 expandGap(pts[
i].fX);
497 auto [lineTop, lineBottom] = std::minmax({pts[0].
fY, pts[1].
fY});
500 if (topOffset <= lineBottom && lineTop <= bottomOffset) {
502 addLine(bottomOffset);
508 auto [quadTop, quadBottom] = std::minmax({pts[0].
fY, pts[1].
fY, pts[2].
fY});
511 if (topOffset <= quadBottom && quadTop <= bottomOffset) {
513 addQuad(bottomOffset);
519 SkDEBUGFAIL(
"There should be no conic primitives in glyph outlines.");
523 auto [cubicTop, cubicBottom] =
524 std::minmax({pts[0].
fY, pts[1].
fY, pts[2].
fY, pts[3].
fY});
527 if (topOffset <= cubicBottom && cubicTop <= bottomOffset) {
529 addCubic(bottomOffset);
538 SkDEBUGFAIL(
"Unknown path verb generating glyph underline.");
550 auto offsetResults = [
scale, xPos](
551 const SkGlyph::Intercept* intercept,
SkScalar* array,
int*
count) {
554 for (
int index = 0; index < 2; index++) {
555 *array++ = intercept->fInterval[index] *
scale + xPos;
561 const SkGlyph::Intercept*
match =
563 if (fPathData ==
nullptr) {
566 const SkGlyph::Intercept* intercept = fPathData->fIntercept;
567 while (intercept !=
nullptr) {
568 if (
bounds[0] == intercept->fBounds[0] &&
bounds[1] == intercept->fBounds[1]) {
571 intercept = intercept->fNext;
576 if (
match !=
nullptr) {
577 if (
match->fInterval[0] <
match->fInterval[1]) {
583 SkGlyph::Intercept* intercept = alloc->
make<SkGlyph::Intercept>();
584 intercept->fNext = fPathData->fIntercept;
585 intercept->fBounds[0] =
bounds[0];
586 intercept->fBounds[1] =
bounds[1];
589 fPathData->fIntercept = intercept;
596 std::tie(intercept->fInterval[0], intercept->fInterval[1])
599 if (intercept->fInterval[0] >= intercept->fInterval[1]) {
604 offsetResults(intercept, array,
count);
608uint32_t init_actions(
const SkGlyph& glyph) {
609 constexpr uint32_t kAllUnset = 0;
610 constexpr uint32_t
kDrop = SkTo<uint32_t>(GlyphAction::kDrop);
611 constexpr uint32_t kAllDrop =
618 return glyph.
isEmpty() ? kAllDrop : kAllUnset;
624 : fPackedID{
SkTo<uint64_t>(glyph.getPackedID().
value())}
625 , fIndex{
SkTo<uint64_t>(index)}
626 , fIsEmpty(glyph.isEmpty())
627 , fFormat(glyph.maskFormat())
628 , fActions{init_actions(glyph)}
629 , fLeft{
SkTo<int16_t>(glyph.
left())}
630 , fTop{
SkTo<int16_t>(glyph.top())}
638 if (this->
actionFor(actionType) == GlyphAction::kUnset) {
640 switch (actionType) {
643 action = GlyphAction::kAccept;
650 action = GlyphAction::kAccept;
656 action = GlyphAction::kAccept;
662 this->
maskFormat() == SkMask::Format::kSDF_Format) {
663 action = GlyphAction::kAccept;
669 action = GlyphAction::kAccept;
675 action = GlyphAction::kAccept;
680 this->setAction(actionType,
action);
689SkVector SkGlyphPositionRoundingSpec::HalfAxisSampleFreq(
694 switch (axisAlignment) {
708SkIPoint SkGlyphPositionRoundingSpec::IgnorePositionMask(
714SkIPoint SkGlyphPositionRoundingSpec::IgnorePositionFieldMask(
bool isSubpixel,
716 SkIPoint ignoreMask = IgnorePositionMask(isSubpixel, axisAlignment);
724 : halfAxisSampleFreq{HalfAxisSampleFreq(isSubpixel, axisAlignment)}
725 , ignorePositionMask{IgnorePositionMask(isSubpixel, axisAlignment)}
726 , ignorePositionFieldMask {IgnorePositionFieldMask(isSubpixel, axisAlignment)} {}
#define SkDEBUGFAIL(message)
#define SK_ABORT(message,...)
static constexpr float sk_ieee_float_divide(float numer, float denom)
static size_t format_alignment(SkMask::Format format)
static size_t format_rowbytes(int width, SkMask::Format format)
static size_t bits_to_bytes(size_t bits)
static std::tuple< SkScalar, SkScalar > calculate_path_gap(SkScalar topOffset, SkScalar bottomOffset, const SkPath &path)
static bool left(const SkPoint &p0, const SkPoint &p1)
static bool right(const SkPoint &p0, const SkPoint &p1)
static bool SkScalarIsInt(SkScalar x)
#define SkScalarFloorToInt(x)
SkSpan(Container &&) -> SkSpan< std::remove_pointer_t< decltype(std::data(std::declval< Container >()))> >
void * makeBytesAlignedTo(size_t size, size_t align)
auto make(Ctor &&ctor) -> decltype(ctor(nullptr))
static SkSpan< const float > IntersectWithHorizontalLine(SkSpan< const SkPoint > controlPoints, float yIntercept, float intersectionStorage[3])
static SkSpan< const float > IntersectWithHorizontalLine(SkSpan< const SkPoint > controlPoints, float yIntercept, float intersectionStorage[2])
void drawPicture(const SkPicture *picture)
size_t approximateBytesUsed()
sk_sp< SkPicture > makePictureSnapshot()
SkMask::Format maskFormat() const
static bool FitsInAtlas(const SkGlyph &glyph)
static constexpr uint16_t kSkSideTooBigForAtlas
bool fitsInAtlasInterpolated() const
void setActionFor(skglyph::ActionType, SkGlyph *, sktext::StrikeForGPU *)
bool fitsInAtlasDirect() const
skglyph::GlyphAction actionFor(skglyph::ActionType actionType) const
bool setPathHasBeenCalled() const
size_t addPathFromBuffer(SkReadBuffer &, SkArenaAlloc *)
bool imageTooLarge() const
size_t formatAlignment() const
void ensureIntercepts(const SkScalar bounds[2], SkScalar scale, SkScalar xPos, SkScalar *array, int *count, SkArenaAlloc *alloc)
void flattenMetrics(SkWriteBuffer &) const
bool setDrawableHasBeenCalled() const
bool setImageHasBeenCalled() const
size_t setMetricsAndImage(SkArenaAlloc *alloc, const SkGlyph &from)
const SkPath * path() const
SkMask::Format maskFormat() const
SkGlyph & operator=(const SkGlyph &)
bool setDrawable(SkArenaAlloc *alloc, SkScalerContext *scalerContext)
bool setPath(SkArenaAlloc *alloc, SkScalerContext *scalerContext)
bool pathIsHairline() const
void flattenPath(SkWriteBuffer &) const
size_t rowBytesUsingFormat(SkMask::Format format) const
bool setImage(SkArenaAlloc *alloc, SkScalerContext *scalerContext)
void flattenDrawable(SkWriteBuffer &) const
size_t addImageFromBuffer(SkReadBuffer &, SkArenaAlloc *)
size_t addDrawableFromBuffer(SkReadBuffer &, SkArenaAlloc *)
void flattenImage(SkWriteBuffer &) const
SkDrawable * drawable() const
const void * image() const
static std::optional< SkGlyph > MakeFromBuffer(SkReadBuffer &)
Verb next(SkPoint pts[4])
size_t approximateBytesUsed() const
const SkRect & getBounds() const
SkPictureBackedGlyphDrawable(sk_sp< SkPicture > self)
static sk_sp< SkPictureBackedGlyphDrawable > MakeFromBuffer(SkReadBuffer &buffer)
static void FlattenDrawable(SkWriteBuffer &buffer, SkDrawable *drawable)
sk_sp< SkData > serialize(const SkSerialProcs *procs=nullptr) const
virtual SkRect cullRect() const =0
static sk_sp< SkPicture > MakeFromData(const SkData *data, const SkDeserialProcs *procs=nullptr)
virtual size_t approximateBytesUsed() const =0
bool readByteArray(void *value, size_t size)
void getPath(SkGlyph &, SkArenaAlloc *)
sk_sp< SkDrawable > getDrawable(SkGlyph &)
void getImage(const SkGlyph &)
virtual void writeBool(bool value)=0
virtual void writeByteArray(const void *data, size_t size)=0
virtual void writePath(const SkPath &path)=0
virtual bool prepareForPath(SkGlyph *)=0
virtual bool prepareForDrawable(SkGlyph *)=0
virtual bool prepareForImage(SkGlyph *)=0
uint32_t uint32_t * format
static float max(float r, float g, float b)
static float min(float r, float g, float b)
Optional< SkRect > bounds
sk_sp< const SkImage > image
sk_sp< const SkPicture > picture
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
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 to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace buffer
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
SkGlyphPositionRoundingSpec(bool isSubpixel, SkAxisAlignment axisAlignment)
constexpr int32_t y() const
static constexpr SkIPoint Make(int32_t x, int32_t y)
constexpr int32_t x() const
static constexpr SkIRect MakeXYWH(int32_t x, int32_t y, int32_t w, int32_t h)
@ k3D_Format
3 8bit per pixl planes: alpha, mul, add
@ kA8_Format
8bits per pixel mask (e.g. antialiasing)
@ kLCD16_Format
565 alpha for r/g/b
@ kARGB32_Format
SkPMColor.
@ kSDF_Format
8bits representing signed distance field
@ kBW_Format
1bit per pixel mask (e.g. monochrome)
static bool IsValidFormat(uint8_t format)
static const constexpr SkScalar kSubpixelRound
static const constexpr SkIPoint kXYFieldMask
constexpr float y() const
constexpr float x() const
SkScalar fBottom
larger y-axis bounds
SkScalar fTop
smaller y-axis bounds
std::shared_ptr< const fml::Mapping > data