74#if defined(SK_RESOLVE_FILTERS_BEFORE_RESTORE)
78#define RETURN_ON_NULL(ptr) do { if (nullptr == (ptr)) return; } while (0)
79#define RETURN_ON_FALSE(pred) do { if (!(pred)) return; } while (0)
83static_assert(std::max(3,4) == 4);
102 auto overrideOpacity = (
flags & PredrawFlags::kOpaqueShaderOverride) ?
104 (
flags & PredrawFlags::kNonOpaqueShaderOverride) ?
113 const SkDevice* root = this->rootDevice();
114 const SkDevice* top = this->topDevice();
118 if (!root->isClipWideOpen()) {
141 if (
paint->getMaskFilter() ||
paint->getPathEffect() ||
paint->getImageFilter()) {
150bool SkCanvas::predrawNotify(
bool willOverwritesEntireSurface) {
152 if (!fSurfaceBase->aboutToDraw(willOverwritesEntireSurface
154 :
SkSurface::kRetain_ContentChangeMode)) {
169 if (fSurfaceBase->outstandingImageSnapshot()) {
170 if (this->wouldOverwriteEntireSurface(rect,
paint,
flags)) {
174 if (!fSurfaceBase->aboutToDraw(mode)) {
184 FilterSpan imageFilters,
188 , fImageFilters(imageFilters.
data(), imageFilters.
size())
190 , fIsCoverage(isCoverage)
199 :fImage(img), fLoc(loc) {}
200SkCanvas::BackImage::BackImage(
const BackImage&) =
default;
201SkCanvas::BackImage::BackImage(BackImage&&) =
default;
202SkCanvas::BackImage& SkCanvas::BackImage::operator=(
const BackImage&) =
default;
203SkCanvas::BackImage::~BackImage() =
default;
209SkCanvas::MCRec::MCRec(
const MCRec*
prev) : fDevice(
prev->fDevice), fMatrix(
prev->fMatrix) {
213SkCanvas::MCRec::~MCRec() {}
218 bool layerIsCoverage) {
221 std::make_unique<Layer>(std::move(layerDevice), filters, restorePaint, layerIsCoverage);
222 fDevice = fLayer->fDevice.get();
238 fCanvas->validateClip();
241 fCanvas->fQuickRejectBounds = fCanvas->computeDeviceClipBounds();
243 fCanvas->validateClip();
257std::optional<AutoLayerForImageFilter> SkCanvas::aboutToDraw(
261 if (
flags & PredrawFlags::kCheckForOverwrite) {
262 if (!this->predrawNotify(rawBounds, &
paint,
flags)) {
266 if (!this->predrawNotify()) {
272 const bool skipMaskFilterLayer = (
flags & PredrawFlags::kSkipMaskFilterAutoLayer) ||
274 return std::optional<AutoLayerForImageFilter>(
275 std::in_place,
this,
paint, rawBounds, skipMaskFilterLayer);
278std::optional<AutoLayerForImageFilter> SkCanvas::aboutToDraw(
280 const SkRect* rawBounds) {
281 return this->aboutToDraw(
paint, rawBounds, PredrawFlags::kNone);
286void SkCanvas::resetForNextPicture(
const SkIRect& bounds) {
294 fRootDevice = sk_make_sp<SkNoPixelsDevice>(bounds,
299 fMCRec->reset(fRootDevice.
get());
300 fQuickRejectBounds = this->computeDeviceClipBounds();
307 static_assert(
sizeof(MCRec) <= kMCRecSize);
322 fSurfaceBase =
nullptr;
323 fRootDevice = std::move(
device);
324 fScratchGlyphRunBuilder = std::make_unique<sktext::GlyphRunBuilder>();
325 fQuickRejectBounds = this->computeDeviceClipBounds();
333 : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
335 this->init(sk_make_sp<SkNoPixelsDevice>(
340 : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) {
342 this->init(sk_make_sp<SkNoPixelsDevice>(r, fProps));
346 : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
347 , fProps(
device->surfaceProps()) {
348 this->init(std::move(
device));
355 MCRec* rec = (MCRec*)iter.
next();
360 rec->fLayer->fDiscard =
true;
366 this->internalRestore();
377SkDevice* SkCanvas::topDevice()
const {
379 return fMCRec->fDevice;
387 return this->
readPixels({ dstInfo, dstP, rowBytes},
x,
y);
397 if (
bitmap.peekPixels(&pm)) {
410 if (!srcRect.
intersect({0, 0, device->width(), device->height()})) {
415 const bool completeOverwrite = srcRect.
size() ==
device->imageInfo().dimensions();
416 if (!this->predrawNotify(completeOverwrite)) {
424 return device->writePixels({srcInfo, pixels, rowBytes},
x,
y);
429void SkCanvas::checkForDeferredSave() {
430 if (fMCRec->fDeferredSaveCount > 0) {
440 const MCRec* rec = (
const MCRec*)iter.
next();
444 count += 1 + rec->fDeferredSaveCount;
453 fMCRec->fDeferredSaveCount += 1;
457void SkCanvas::doSave() {
460 SkASSERT(fMCRec->fDeferredSaveCount > 0);
461 fMCRec->fDeferredSaveCount -= 1;
462 this->internalSave();
466 if (fMCRec->fDeferredSaveCount > 0) {
469 fMCRec->fDeferredSaveCount -= 1;
472 if (fMCStack.
count() > 1) {
476 this->internalRestore();
489 for (
int i = 0; i < n; ++i) {
494void SkCanvas::internalSave() {
495 fMCRec =
new (fMCStack.
push_back()) MCRec(fMCRec);
513 this->internalSaveLayer(rec, strategy);
518int SkCanvas::only_axis_aligned_saveBehind(
const SkRect* bounds) {
526 this->internalSave();
528 this->internalSaveBehind(bounds);
543 if (!contentBounds) {
571static std::optional<std::pair<skif::Mapping, skif::LayerSpace<SkIRect>>>
577#if defined(SK_RESOLVE_FILTERS_BEFORE_RESTORE)
578 bool mustCoverDst =
true,
583 !localToDst.
invert(&dstToLocal)) {
589#if defined(SK_RESOLVE_FILTERS_BEFORE_RESTORE)
593 contentBounds.reset();
603 capability = std::min(capability,
as_IFB(filter)->getCTMCapability());
611 if (scaleFactor != 1.0f &&
621 static const int kMinDimThreshold = 2048;
623 SkIRect(targetOutput).height64())),
631 if (!baseLayerBounds.intersect(knownBounds)) {
637 if (!filters.
empty()) {
639 return filters[i] ? as_IFB(filters[i])
640 ->getInputBounds(mapping, targetOutput, contentBounds)
645 if (layerBounds.width() > maxLayerDim || layerBounds.height() > maxLayerDim) {
650 idealMapping, targetOutput, contentBounds);
651 maxLayerDim = std::max(std::max(idealLayerBounds.width(),
652 idealLayerBounds.height()),
658 if (baseLayerBounds.isEmpty()) {
661 layerBounds = baseLayerBounds;
664 if (layerBounds.width() > maxLayerDim || layerBounds.height() > maxLayerDim) {
667 std::min(layerBounds.height(), maxLayerDim)));
674 layerBounds = newLayerBounds;
678 return std::make_pair(mapping, layerBounds);
689 return kN32_SkColorType;
695#if !defined(SK_RESOLVE_FILTERS_BEFORE_RESTORE)
703 if (
paint.getAlphaf() < 1.f) {
708 if (
paint.getColorFilter()) {
714void SkCanvas::internalDrawDeviceWithFilter(
SkDevice* src,
718 DeviceCompatibleWithFilter compat,
721 bool srcIsCoverageLayer) {
746 if (compat == DeviceCompatibleWithFilter::kYes) {
758 dst->getRelativeTransform(*src),
766 filters,
dst->localToDevice(), outputBounds, {},
SkTPin(scaleFactor, 0.f, 1.f));
767 if (!mappingAndBounds) {
771 std::tie(mapping, requiredInput) = *mappingAndBounds;
773 if (!requiredInput.isEmpty()) {
778 if (!localToSrc.
invert(&srcToLocal)) {
791 auto backend =
dst->createImageFilteringBackend(src ?
src->surfaceProps() :
dst->surfaceProps(),
798 filterColorSpace.
get(),
802 if (src && !requiredInput.isEmpty()) {
804 if (!srcToLayer.inverseMapRect(requiredInput, &srcSubset)) {
809 ctx.markNewSurface();
814 if (
SkMatrix(srcToLayer).isScaleTranslate()) {
818 auto requiredSubset = srcToLayer.mapRect(availSrc);
819 if (requiredSubset.width() == availSrc.width() &&
820 requiredSubset.height() == availSrc.height()) {
825 SkASSERT(compat == DeviceCompatibleWithFilter::kUnknown);
827 SkISize(requiredSubset.size())),
828 requiredSubset.topLeft()};
829 ctx.markNewSurface();
833 if (compat == DeviceCompatibleWithFilter::kYes) {
834#if defined(SK_DONT_PAD_LAYER_IMAGES)
847 }
else if (!requiredInput.isEmpty()) {
856 source =
source.applyCrop(ctx.withNewDesiredOutput(srcSubset),
865 ctx = ctx.withNewDesiredOutput(mapping.
deviceToLayer(outputBounds))
875 if (srcIsCoverageLayer) {
876 SkASSERT(
dst->useDrawCoverageMaskForMaskFilters());
879 auto [coverageMask, origin] =
result.imageAndOffset(ctx);
882 deviceMatrixWithOffset.
preTranslate(origin.x(), origin.y());
883 dst->drawCoverageMask(
884 coverageMask.get(), deviceMatrixWithOffset,
result.sampling(),
paint);
897static bool can_layer_be_drawn_as_sprite(
const SkMatrix& matrix,
const SkISize& size) {
901 paint.setAntiAlias(
true);
906void SkCanvas::internalDrawDeviceWithFilter(
SkDevice* src,
910 DeviceCompatibleWithFilter compat,
913 bool srcIsCoverageLayer) {
914 const SkImageFilter* filter = filters.empty() ? nullptr : filters.front().get();
917 (void) srcIsCoverageLayer;
928 SkMatrix localToSrc = (
src->globalToDevice() * fMCRec->fMatrix).asM33();
929 SkISize srcDims =
src->imageInfo().dimensions();
932 bool needsIntermediateImage =
false;
937 if (compat == DeviceCompatibleWithFilter::kYes) {
946 dst->getRelativeTransform(*src),
955 {},
true,
SkTPin(scaleFactor, 0.f, 1.f));
956 if (!mappingAndBounds) {
960 std::tie(mapping, requiredInput) = *mappingAndBounds;
961 if (!requiredInput.isEmpty()) {
965 if (!localToSrc.
invert(&srcToIntermediate)) {
969 if (can_layer_be_drawn_as_sprite(srcToIntermediate, srcDims)) {
975 requiredInput.offset(-srcOrigin);
979 needsIntermediateImage =
true;
985 if (!needsIntermediateImage) {
988 if (srcSubset.intersect(requiredInput)) {
989 filterInput =
src->snapSpecial(
SkIRect(srcSubset));
998 SkASSERT(compat == DeviceCompatibleWithFilter::kUnknown);
1016 filterInput =
src->snapSpecialScaled(srcSubset,
1017 {requiredSubset.width(), requiredSubset.height()});
1033 requiredInput.height(),
1040 if (!intermediateDevice) {
1043 intermediateDevice->setOrigin(
SkM44(srcToIntermediate),
1044 requiredInput.left(), requiredInput.top());
1054 intermediateDevice->drawPaint(imageFill);
1055 filterInput = intermediateDevice->snapSpecial();
1062 if (filterInput || requiredInput.isEmpty()) {
1063 const bool useNN = can_layer_be_drawn_as_sprite(mapping.
layerToDevice(),
1064 dst->devClipBounds().size());
1067 dst->drawFilteredImage(mapping, filterInput.
get(), filterColorType, filter,
1093 if (
paint->getAlphaf() < 1.f) {
1100 paint->setAlphaf(1.f);
1114static bool must_cover_prior_device(
const SkImageFilter* backdrop,
1115 const SkPaint& restorePaint) {
1117 if (backdrop || (cf &&
as_CFB(cf)->affectsTransparentBlack())) {
1124 if (
auto blendMode = restorePaint.
asBlendMode()) {
1145void SkCanvas::internalSaveLayer(
const SaveLayerRec& rec,
1146 SaveLayerStrategy strategy,
1147 bool coverageOnly) {
1151 this->internalSave();
1171#if defined(SK_RESOLVE_FILTERS_BEFORE_RESTORE)
1173 rec.fPaint ? rec.fPaint->getImageFilter() : nullptr, &restorePaint));
1180 SkDevice* priorDevice = this->topDevice();
1183 std::optional<skif::ParameterSpace<SkRect>> contentBounds;
1192 must_cover_prior_device(rec.fBackdrop, restorePaint));
1205 bool filtersPriorDevice = rec.fBackdrop;
1206#if !defined(SK_LEGACY_INITWITHPREV_LAYER_SIZING)
1212 (!filters.empty() || cf || blender || restorePaint.
getAlphaf() < 1.f));
1220 const bool drawDeviceMustFillClip = filters.empty() &&
1223 const bool trivialRestore = !filtersPriorDevice && !drawDeviceMustFillClip;
1226 SkDevice* priorDevice = this->topDevice();
1231 std::optional<skif::ParameterSpace<SkRect>> contentBounds;
1233 if (rec.fBounds && trivialRestore) {
1238 filters, priorDevice->
localToDevice(), outputBounds, contentBounds);
1241 auto abortLayer = [
this]() {
1245 AutoUpdateQRBounds aqr(
this);
1249 if (!mappingAndBounds) {
1254 std::tie(newLayerMapping, layerBounds) = *mappingAndBounds;
1256 if (layerBounds.isEmpty()) {
1264#if defined(SK_RESOLVE_FILTERS_BEFORE_RESTORE)
1265 const SkImageFilter* filter = filters.empty() ? nullptr : filters.front().get();
1267 std::optional<skif::DeviceSpace<SkIRect>>
output =
1272 const bool useNN = can_layer_be_drawn_as_sprite(
1284 if (rec.fColorSpace) {
1287 this->internalDrawDeviceWithFilter(
nullptr, priorDevice, filters, restorePaint,
1288 DeviceCompatibleWithFilter::kUnknown,
1298#if !defined(SK_RESOLVE_FILTERS_BEFORE_RESTORE) && !defined(SK_DONT_PAD_LAYER_IMAGES)
1303 if (!filters.empty()) {
1325 layerBounds.height(),
1328 rec.fColorSpace ?
sk_ref_sp(rec.fColorSpace)
1329 : priorDevice->
imageInfo().refColorSpace());
1336 newDevice = priorDevice->
createDevice(createInfo, rec.fPaint);
1345 newDevice = sk_make_sp<SkNoPixelsDevice>(
SkIRect::MakeWH(layerBounds.width(),
1346 layerBounds.height()),
1347 fProps, this->imageInfo().refColorSpace());
1348 initBackdrop =
false;
1351#if !defined(SK_RESOLVE_FILTERS_BEFORE_RESTORE) && !defined(SK_DONT_PAD_LAYER_IMAGES)
1354 if (!filters.empty()) {
1355 newDevice->clipRect(
SkRect::Make(newDevice->devClipBounds().makeInset(1, 1)),
1364 newDevice->setDeviceCoordinateSystem(
1374#if defined(SK_RESOLVE_FILTERS_BEFORE_RESTORE)
1375 const SkImageFilter* backdropFilter = optimize_layer_filter(rec.fBackdrop, &backdropPaint);
1384 bool scaleBackdrop = rec.fExperimentalBackdropScale != 1.0f;
1385 auto compat = (!filters.empty() || backdropFilter || scaleBackdrop)
1386 ? DeviceCompatibleWithFilter::kUnknown : DeviceCompatibleWithFilter::
kYes;
1388 this->internalDrawDeviceWithFilter(priorDevice,
1393 newDevice->imageInfo().colorInfo(),
1394 rec.fExperimentalBackdropScale);
1397 fMCRec->newLayer(std::move(newDevice), filters, restorePaint, coverageOnly);
1398 fQuickRejectBounds = this->computeDeviceClipBounds();
1402 if (alpha >= 1.0f) {
1403 return this->
saveLayer(bounds,
nullptr);
1407 return this->
saveLayer(bounds, &tmpPaint);
1411void SkCanvas::internalSaveBehind(
const SkRect* localBounds) {
1419 device->localToDevice().mapRect(&tmp, *localBounds);
1424 devBounds =
device->devClipBounds();
1434 auto backImage =
device->snapSpecial(devBounds,
true);
1440 this->checkForDeferredSave();
1442 fMCRec->fBackImage =
1443 std::make_unique<BackImage>(BackImage{std::move(backImage), devBounds.
topLeft()});
1447 this->drawClippedToSaveBehind(
paint);
1450void SkCanvas::internalRestore() {
1454 std::unique_ptr<Layer> layer = std::move(fMCRec->fLayer);
1455 std::unique_ptr<BackImage> backImage = std::move(fMCRec->fBackImage);
1460 fMCRec = (MCRec*) fMCStack.
back();
1473 this->topDevice()->
drawSpecial(backImage->fImage.get(),
1481 if (layer && !layer->fDevice->isNoPixelsDevice() && !layer->fDiscard) {
1482 layer->fDevice->setImmutable();
1486 if (this->predrawNotify()) {
1487 SkDevice* dstDev = this->topDevice();
1488 if (!layer->fImageFilters.empty()) {
1489 this->internalDrawDeviceWithFilter(layer->fDevice.get(),
1491 layer->fImageFilters,
1493 DeviceCompatibleWithFilter::kYes,
1494 layer->fDevice->imageInfo().colorInfo(),
1496 layer->fIsCoverage);
1503 dstDev->
drawDevice(layer->fDevice.get(), sampling, layer->fPaint);
1509 if (this->
getSaveCount() < fClipRestrictionSaveCount) {
1511 fClipRestrictionSaveCount = -1;
1515 fQuickRejectBounds = this->computeDeviceClipBounds();
1516 this->validateClip();
1520 if (
nullptr == props) {
1587 if (this->topDevice()->isPixelAlignedToGlobal()) {
1588 *origin = this->topDevice()->
getOrigin();
1604 this->checkForDeferredSave();
1605 fMCRec->fMatrix.preTranslate(dx, dy);
1614 if (sx != 1 || sy != 1) {
1615 this->checkForDeferredSave();
1616 fMCRec->fMatrix.preScale(sx, sy);
1626 m.setRotate(degrees);
1632 m.setRotate(degrees, px, py);
1643 if (matrix.isIdentity()) {
1649void SkCanvas::internalConcat44(
const SkM44& m) {
1650 this->checkForDeferredSave();
1652 fMCRec->fMatrix.preConcat(m);
1658 this->internalConcat44(m);
1663void SkCanvas::internalSetMatrix(
const SkM44& m) {
1664 fMCRec->fMatrix = m;
1674 this->checkForDeferredSave();
1675 this->internalSetMatrix(m);
1686 if (!rect.isFinite()) {
1689 this->checkForDeferredSave();
1699 this->topDevice()->
clipRect(rect, op, isAA);
1725 SkASSERT(this->topDevice() == this->rootDevice());
1727 SkASSERT(fClipRestrictionSaveCount < 0 && fClipRestrictionRect.
isEmpty());
1729 if (fClipRestrictionSaveCount < 0 && !rect.isEmpty()) {
1730 fClipRestrictionRect = rect;
1735 this->checkForDeferredSave();
1743void SkCanvas::internal_private_resetClip() {
1744 this->checkForDeferredSave();
1750 if (fClipRestrictionSaveCount >= 0 && this->topDevice() == this->rootDevice()) {
1754 if (!deviceRestriction.
intersect(fClipRestrictionRect)) {
1760 this->topDevice()->
replaceClip(deviceRestriction);
1764 this->checkForDeferredSave();
1777 this->topDevice()->
clipRRect(rrect, op, isAA);
1781 this->checkForDeferredSave();
1784 if (!path.isInverseFillType() && fMCRec->fMatrix.asM33().rectStaysRect()) {
1786 if (path.isRect(&r)) {
1791 if (path.isOval(&r)) {
1796 if (path.isRRect(&rrect)) {
1809 this->topDevice()->
clipPath(path, op, isAA);
1814 if (sh->isOpaque()) {
1823 this->checkForDeferredSave();
1835 this->checkForDeferredSave();
1844void SkCanvas::validateClip()
const {
1846 SkRect tmp = this->computeDeviceClipBounds();
1850 SkASSERT(tmp == fQuickRejectBounds);
1855bool SkCanvas::androidFramework_isClipAA()
const {
1863 device->android_utils_clipAsRgn(rgn);
1865 if (origin.
x() | origin.
y()) {
1884 this->validateClip();
1897 if (!bounds.isFinite() ||
paint.nothingToDraw()) {
1901 if (
paint.canComputeFastBounds()) {
1918 if (!fMCRec->fMatrix.asM33().invert(&inverse)) {
1924 const int margin = 1;
1932 return this->computeDeviceClipBounds(
false).
roundOut();
1935SkRect SkCanvas::computeDeviceClipBounds(
bool outsetForAA)
const {
1936 const SkDevice* dev = this->topDevice();
1945 devClipBounds.
outset(1.f, 1.f);
1947 return devClipBounds;
1954 return fMCRec->fMatrix.asM33();
1958 return fMCRec->fMatrix;
1966 return this->topDevice()->
recorder();
2004void SkCanvas::drawClippedToSaveBehind(
const SkPaint&
paint) {
2051#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
2114 if (dst.isEmpty()) {
2119 Lattice latticePlusBounds = lattice;
2120 if (!latticePlusBounds.
fBounds) {
2122 latticePlusBounds.
fBounds = &bounds;
2163 if (!this->predrawNotify()) {
2184#if !defined(SK_RESOLVE_FILTERS_BEFORE_RESTORE)
2187 if (
paint &&
paint->getImageFilter() && cnt == 1) {
2188 const auto& entry = imageSet[0];
2192 (preViewMatrices[entry.fMatrixIndex].isScaleTranslate() &&
2193 preViewMatrices[entry.fMatrixIndex].getScaleX() > 0.f &&
2194 preViewMatrices[entry.fMatrixIndex].getScaleY() > 0.f);
2195 if (!entry.fHasClip && canMapDstRect) {
2196 SkRect dst = entry.fDstRect;
2197 if (entry.fMatrixIndex >= 0) {
2198 preViewMatrices[entry.fMatrixIndex].mapRect(&dst);
2200 this->
drawImageRect(entry.fImage.get(), entry.fSrcRect, dst,
2201 sampling,
paint, constraint);
2221 this->internalDrawPaint(
paint);
2224void SkCanvas::internalDrawPaint(
const SkPaint&
paint) {
2227 if (
paint.nothingToDraw() || this->isClipEmpty()) {
2231 auto layer = this->aboutToDraw(
paint,
nullptr, PredrawFlags::kCheckForOverwrite);
2233 this->topDevice()->
drawPaint(layer->paint());
2239 if ((
long)
count <= 0 ||
paint.nothingToDraw()) {
2247 bounds.set(pts[0], pts[1]);
2255 if (this->internalQuickReject(bounds, strokePaint)) {
2259 auto layer = this->aboutToDraw(strokePaint, &bounds);
2266 if (
paint.getPathEffect()) {
2286 return blurMaskFilter;
2289std::optional<AutoLayerForImageFilter> SkCanvas::attemptBlurredRRectDraw(
2291 SkASSERT(!(
flags & PredrawFlags::kSkipMaskFilterAutoLayer));
2294 if (!this->topDevice()->useDrawCoverageMaskForMaskFilters()) {
2296 return this->aboutToDraw(
paint, &bounds,
flags);
2303 return this->aboutToDraw(
paint, &bounds,
flags);
2307 if (!blurMaskFilter) {
2309 return this->aboutToDraw(
paint, &bounds,
flags);
2312 auto layer = this->aboutToDraw(
paint, &bounds,
flags | PredrawFlags::kSkipMaskFilterAutoLayer);
2315 return std::nullopt;
2319 if (this->topDevice()->drawBlurredRRect(rrect, layer->paint(), deviceSigma)) {
2321 return std::nullopt;
2326 layer->addMaskFilterLayer(&bounds);
2332 if (this->internalQuickReject(r,
paint)) {
2337 std::optional<AutoLayerForImageFilter> layer = this->attemptBlurredRRectDraw(
2341 this->topDevice()->
drawRect(r, layer->paint());
2347 if (this->internalQuickReject(bounds,
paint)) {
2351 auto layer = this->aboutToDraw(
paint, &bounds);
2353 this->topDevice()->
drawRegion(region, layer->paint());
2366 const MCRec* rec = (
const MCRec*)iter.
prev();
2370 if (rec->fBackImage) {
2375 rec->fBackImage->fImage->width(),
2376 rec->fBackImage->fImage->height());
2393 auto layer = this->aboutToDraw(
paint);
2395 this->topDevice()->
drawPaint(layer->paint());
2403 if (this->internalQuickReject(oval,
paint)) {
2408 std::optional<AutoLayerForImageFilter> layer =
2412 this->topDevice()->
drawOval(oval, layer->paint());
2417 SkScalar sweepAngle,
bool useCenter,
2420 if (this->internalQuickReject(oval,
paint)) {
2424 auto layer = this->aboutToDraw(
paint, &oval);
2426 this->topDevice()->
drawArc(oval, startAngle, sweepAngle, useCenter, layer->paint());
2438 }
else if (rrect.
isOval()) {
2444 if (this->internalQuickReject(bounds,
paint)) {
2449 std::optional<AutoLayerForImageFilter> layer =
2450 this->attemptBlurredRRectDraw(rrect,
paint, PredrawFlags::kNone);
2453 this->topDevice()->
drawRRect(rrect, layer->paint());
2459 if (this->internalQuickReject(bounds,
paint)) {
2463 auto layer = this->aboutToDraw(
paint, &bounds);
2465 this->topDevice()->
drawDRRect(outer, inner, layer->paint());
2470 if (!path.isFinite()) {
2474 const SkRect& pathBounds = path.getBounds();
2475 if (!path.isInverseFillType() && this->internalQuickReject(pathBounds,
paint)) {
2478 if (path.isInverseFillType() && pathBounds.
width() <= 0 && pathBounds.
height() <= 0) {
2479 this->internalDrawPaint(
paint);
2483 auto layer = this->aboutToDraw(
paint, path.isInverseFillType() ?
nullptr : &pathBounds);
2485 this->topDevice()->
drawPath(path, layer->paint());
2492#if defined(SK_RESOLVE_FILTERS_BEFORE_RESTORE)
2493 if (!
paint.getImageFilter()) {
2504 if (
paint.getAlphaf() < 1.f ||
paint.getColorFilter() ||
paint.getMaskFilter()) {
2518 return ir.
contains(fQuickRejectBounds);
2539 paint.setMaskFilter(
nullptr);
2540 paint.setPathEffect(
nullptr);
2547#if defined(SK_RESOLVE_FILTERS_BEFORE_RESTORE)
2551 if (this->internalQuickReject(dst, realPaint)) {
2576 if (!layerToDevice.
invert(&deviceToLayer)) {
2582 if (this->predrawNotify()) {
2585 const auto filterColorType =
2587 device->drawFilteredImage(mapping, special.
get(), filterColorType, filter.
get(),
2588 sampling,realPaint);
2594 if (this->topDevice()->shouldDrawAsTiledImageRect()) {
2595 if (this->topDevice()->drawAsTiledImageRect(
2601 auto layer = this->aboutToDraw(realPaint, &dst);
2632 if (this->internalQuickReject(dst, realPaint)) {
2636 if (this->topDevice()->shouldDrawAsTiledImageRect()) {
2637 if (this->topDevice()->drawAsTiledImageRect(
2638 this,
image, &src, dst, realSampling, realPaint, constraint)) {
2642#if !defined(SK_RESOLVE_FILTERS_BEFORE_RESTORE)
2665 if (!mappingAndBounds) {
2668 if (!this->predrawNotify()) {
2678 auto [mapping, srcBounds] = *mappingAndBounds;
2684 device->imageInfo().colorSpace(),
2695 ctx = ctx.withNewDesiredOutput(mapping.
deviceToLayer(outputBounds))
2699 stats.reportStats();
2707 if (realPaint.
getMaskFilter() && this->topDevice()->useDrawCoverageMaskForMaskFilters()) {
2715 this->
drawRect(drawDst, realPaint);
2720 auto layer = this->aboutToDraw(realPaint, &dst,
2721 PredrawFlags::kCheckForOverwrite |
2723 : PredrawFlags::kNonOpaqueShaderOverride));
2734 if (this->internalQuickReject(dst, realPaint)) {
2738 auto layer = this->aboutToDraw(realPaint, &dst);
2748#if defined(SK_RESOLVE_FILTERS_BEFORE_RESTORE)
2779 auto glyphRunList = fScratchGlyphRunBuilder->blobToGlyphRunList(*blob, {
x,
y});
2785 if (this->internalQuickReject(bounds,
paint)) {
2793 auto layer = this->aboutToDraw(
paint, &bounds, PredrawFlags::kSkipMaskFilterAutoLayer);
2802 auto glyphRunList = fScratchGlyphRunBuilder->blobToGlyphRunList(blob, origin);
2809 if (bounds.isEmpty() || !bounds.isFinite() ||
paint.nothingToDraw()) {
2813 auto layer = this->aboutToDraw(
paint, &bounds, PredrawFlags::kSkipMaskFilterAutoLayer);
2829 if (this->internalQuickReject(bounds,
paint)) {
2833 auto layer = this->aboutToDraw(
paint, &bounds, PredrawFlags::kSkipMaskFilterAutoLayer);
2835 this->topDevice()->
drawSlug(
this, slug, layer->paint());
2846 fScratchGlyphRunBuilder->textToGlyphRunList(
2848 if (!glyphRunList.
empty()) {
2855 const uint32_t* clusters,
int textByteCount,
const char* utf8text,
2857 if (
count <= 0) {
return; }
2863 SkSpan(utf8text, textByteCount),
2869 glyphRun,
paint, origin);
2875 if (
count <= 0) {
return; }
2887 glyphRun,
paint, origin);
2893 if (
count <= 0) {
return; }
2895 auto [positions, rotateScales] =
2896 fScratchGlyphRunBuilder->convertRSXForm(
SkSpan(xforms,
count));
2907 glyphRun,
paint, origin);
2920 int totalGlyphCount = 0;
2924 while (i.
next(&r)) {
2938 if (this->internalQuickReject(bounds, simplePaint)) {
2942 auto layer = this->aboutToDraw(simplePaint, &bounds);
2950 auto layer = this->aboutToDraw(simplePaint,
nullptr);
2952 this->topDevice()->
drawMesh(mesh, std::move(blender),
paint);
2960 if (
nullptr == cubics) {
2977 if (this->internalQuickReject(bounds, simplePaint)) {
2981 auto layer = this->aboutToDraw(simplePaint, &bounds);
2989#ifndef SK_BUILD_FOR_ANDROID_FRAMEWORK
3002#ifndef SK_BUILD_FOR_ANDROID_FRAMEWORK
3006 if (matrix && matrix->isIdentity()) {
3015 if (this->predrawNotify()) {
3028 if (cull && this->internalQuickReject(*cull, realPaint)) {
3035 auto layer = this->aboutToDraw(realPaint);
3045 if (this->predrawNotify()) {
3055 paint.setBlendMode(mode);
3056 if (this->internalQuickReject(r,
paint)) {
3060 if (this->predrawNotify()) {
3082 bool setBoundsValid =
count == 1 || needsAutoLayer;
3084 if (imageSet[0].fMatrixIndex >= 0) {
3086 preViewMatrices[imageSet[0].
fMatrixIndex].mapRect(&setBounds);
3088 if (needsAutoLayer) {
3089 for (
int i = 1; i <
count; ++i) {
3091 if (imageSet[i].fMatrixIndex >= 0) {
3092 preViewMatrices[imageSet[i].
fMatrixIndex].mapRect(&entryBounds);
3099 if (setBoundsValid && this->internalQuickReject(setBounds, realPaint)) {
3103 auto layer = this->aboutToDraw(realPaint, setBoundsValid ? &setBounds :
nullptr);
3106 realSampling, layer->paint(), constraint);
3118 paint.setBlendMode(mode);
3140 r.
setLTRB(cx - radius, cy - radius, cx + radius, cy + radius);
3146 if (rx > 0 && ry > 0) {
3156 SkScalar sweepAngle,
bool useCenter,
3159 if (oval.
isEmpty() || !sweepAngle) {
3166#ifdef SK_DISABLE_SKPICTURE
3178 if (matrix && matrix->isIdentity()) {
3208 const SkRect& dstRect,
int matrixIndex,
float alpha,
3209 unsigned aaFlags,
bool hasClip)
3213 , fMatrixIndex(matrixIndex)
3216 , fHasClip(hasClip) {}
3219 const SkRect& dstRect,
float alpha,
unsigned aaFlags)
3224 , fAAFlags(aaFlags) {}
3235 if (!
bitmap.installPixels(
info, pixels, rowBytes)) {
3240 std::make_unique<SkCanvas>(
bitmap, *props) :
3241 std::make_unique<SkCanvas>(
bitmap);
3269 const SkDevice* dev = this->topDevice();
3273 if (!
clip.intersect({0, 0, dev->width(), dev->height()})) {
3297std::unique_ptr<SkCanvas>
3311 hndl = alloc->allocBitmap(
info, &bm);
3313 return hndl ? std::unique_ptr<SkCanvas>(
new SkCanvas(bm, std::move(alloc), hndl, props))
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
constexpr int kMaxGlyphCount
static float prev(float f)
@ kPremul_SkAlphaType
pixel components are premultiplied by alpha
SK_API bool SkBlendMode_AsCoeff(SkBlendMode mode, SkBlendModeCoeff *src, SkBlendModeCoeff *dst)
@ kDstOver
r = d + (1-da)*s
SkBlenderBase * as_BB(SkBlender *blend)
@ kNormal_SkBlurStyle
fuzzy inside and outside
constexpr int kMaxPictureOpsToUnrollInsteadOfRef
#define RETURN_ON_NULL(ptr)
static SkPaint clean_paint_for_drawImage(const SkPaint *paint)
static bool install(SkBitmap *bm, const SkImageInfo &info, const SkRasterHandleAllocator::Rec &rec)
static SkPaint clean_paint_for_drawVertices(SkPaint paint)
static SkSamplingOptions clean_sampling_for_constraint(const SkSamplingOptions &sampling, SkCanvas::SrcRectConstraint constraint)
static SkPaint clean_paint_for_lattice(const SkPaint *paint)
static std::optional< std::pair< skif::Mapping, skif::LayerSpace< SkIRect > > > get_layer_mapping_and_bounds(SkCanvas::FilterSpan filters, const SkMatrix &localToDst, const skif::DeviceSpace< SkIRect > &targetOutput, std::optional< skif::ParameterSpace< SkRect > > contentBounds={}, SkScalar scaleFactor=1.0f)
static skif::FilterResult apply_alpha_and_colorfilter(const skif::Context &ctx, const skif::FilterResult &image, const SkPaint &paint)
static SkColorType image_filter_color_type(const SkColorInfo &dstInfo)
static bool fillable(const SkRect &r)
static skif::ParameterSpace< SkPoint > compute_decomposition_center(const SkMatrix &dstToLocal, std::optional< skif::ParameterSpace< SkRect > > contentBounds, const skif::DeviceSpace< SkIRect > &targetOutput)
static const SkBlurMaskFilterImpl * can_attempt_blurred_rrect_draw(const SkPaint &paint)
#define RETURN_ON_FALSE(pred)
static SkColorFilterBase * as_CFB(SkColorFilter *filter)
@ kBGRA_8888_SkColorType
pixel with 8 bits for blue, green, red, alpha; in 32-bit word
@ kRGBA_F16_SkColorType
pixel with half floats for red, green, blue, alpha;
@ kAlpha_8_SkColorType
pixel with alpha in 8-bit byte
@ kRGBA_8888_SkColorType
pixel with 8 bits for red, green, blue, alpha; in 32-bit word
#define SK_MAKE_BITMASK_OPS(E)
static bool SkIsFinite(T x, Pack... values)
static SkImageFilter_Base * as_IFB(SkImageFilter *filter)
SkRect SkModifyPaintAndDstForDrawImageRect(const SkImage *image, const SkSamplingOptions &, SkRect src, SkRect dst, bool strictSrcSubset, SkPaint *paint)
static void sk_msan_assert_initialized(const void *begin, const void *end)
SkMaskFilterBase * as_MFB(SkMaskFilter *mf)
bool SkTreatAsSprite(const SkMatrix &mat, const SkISize &size, const SkSamplingOptions &sampling, bool isAntiAlias)
@ kYes
Do pre-clip the geometry before applying the (perspective) matrix.
static SkPath clip(const SkPath &path, const SkHalfPlane &plane)
sk_sp< T > sk_ref_sp(T *obj)
static constexpr int32_t Sk64_pin_to_s32(int64_t x)
#define SkScalarRoundToInt(x)
static SkSurfaceProps SkSurfacePropsCopyOrDefault(const SkSurfaceProps *props)
bool SkSurfaceValidateRasterInfo(const SkImageInfo &, size_t rb=kIgnoreRowBytesValue)
constexpr size_t kIgnoreRowBytesValue
@ kUnknown_SkPixelGeometry
static constexpr const T & SkTPin(const T &x, const T &lo, const T &hi)
void sk_ignore_unused_variable(const T &)
constexpr int SkToInt(S x)
static constexpr bool SkToBool(const T &x)
static SkScalar center(float pos0, float pos1)
Type::kYUV Type::kRGBA() int(0.7 *637)
bool installPixels(const SkImageInfo &info, void *pixels, size_t rowBytes, void(*releaseProc)(void *addr, void *context), void *context)
bool peekPixels(SkPixmap *pixmap) const
bool affectsTransparentBlack() const
static sk_sp< SkBlender > Mode(SkBlendMode mode)
SkBlurStyle blurStyle() const
SkScalar computeXformedSigma(const SkMatrix &ctm) const
static bool ImageToColorFilter(SkPaint *)
AutoUpdateQRBounds(SkCanvas *canvas)
virtual void onDrawDrawable(SkDrawable *drawable, const SkMatrix *matrix)
virtual void onDrawImage2(const SkImage *, SkScalar dx, SkScalar dy, const SkSamplingOptions &, const SkPaint *)
int saveLayer(const SkRect *bounds, const SkPaint *paint)
bool getProps(SkSurfaceProps *props) const
virtual void onDrawDRRect(const SkRRect &outer, const SkRRect &inner, const SkPaint &paint)
SkRasterHandleAllocator::Handle accessTopRasterHandle() const
SkSpan< sk_sp< SkImageFilter > > FilterSpan
void drawRect(const SkRect &rect, const SkPaint &paint)
SkSurface * getSurface() const
void drawOval(const SkRect &oval, const SkPaint &paint)
void clipRect(const SkRect &rect, SkClipOp op, bool doAntiAlias)
virtual void onDrawPath(const SkPath &path, const SkPaint &paint)
bool peekPixels(SkPixmap *pixmap)
void drawPoints(PointMode mode, size_t count, const SkPoint pts[], const SkPaint &paint)
virtual void onDrawAtlas2(const SkImage *, const SkRSXform[], const SkRect src[], const SkColor[], int count, SkBlendMode, const SkSamplingOptions &, const SkRect *cull, const SkPaint *)
virtual bool isClipEmpty() const
SkSurfaceProps getTopProps() const
void drawPatch(const SkPoint cubics[12], const SkColor colors[4], const SkPoint texCoords[4], SkBlendMode mode, const SkPaint &paint)
void drawPoint(SkScalar x, SkScalar y, const SkPaint &paint)
virtual bool onPeekPixels(SkPixmap *pixmap)
void drawSimpleText(const void *text, size_t byteLength, SkTextEncoding encoding, SkScalar x, SkScalar y, const SkFont &font, const SkPaint &paint)
void translate(SkScalar dx, SkScalar dy)
sk_sp< SkSurface > makeSurface(const SkImageInfo &info, const SkSurfaceProps *props=nullptr)
virtual SkImageInfo onImageInfo() const
virtual void onDrawImageLattice2(const SkImage *, const Lattice &, const SkRect &dst, SkFilterMode, const SkPaint *)
void drawImageNine(const SkImage *image, const SkIRect ¢er, const SkRect &dst, SkFilterMode filter, const SkPaint *paint=nullptr)
void drawColor(SkColor color, SkBlendMode mode=SkBlendMode::kSrcOver)
virtual void onDrawPicture(const SkPicture *picture, const SkMatrix *matrix, const SkPaint *paint)
void androidFramework_setDeviceClipRestriction(const SkIRect &rect)
virtual void onDrawAnnotation(const SkRect &rect, const char key[], SkData *value)
virtual void onDrawPaint(const SkPaint &paint)
virtual void onDrawBehind(const SkPaint &paint)
bool writePixels(const SkImageInfo &info, const void *pixels, size_t rowBytes, int x, int y)
SkRect getLocalClipBounds() const
virtual GrRecordingContext * recordingContext() const
virtual void onClipShader(sk_sp< SkShader >, SkClipOp)
virtual sk_sp< sktext::gpu::Slug > onConvertGlyphRunListToSlug(const sktext::GlyphRunList &glyphRunList, const SkPaint &paint)
virtual void didScale(SkScalar, SkScalar)
virtual void didSetM44(const SkM44 &)
virtual bool isClipRect() const
virtual void didRestore()
virtual void onDrawTextBlob(const SkTextBlob *blob, SkScalar x, SkScalar y, const SkPaint &paint)
virtual skgpu::graphite::Recorder * recorder() const
void drawPaint(const SkPaint &paint)
void drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1, const SkPaint &paint)
void private_draw_shadow_rec(const SkPath &, const SkDrawShadowRec &)
void drawDrawable(SkDrawable *drawable, const SkMatrix *matrix=nullptr)
virtual void onDrawRect(const SkRect &rect, const SkPaint &paint)
virtual void onDrawEdgeAAImageSet2(const ImageSetEntry imageSet[], int count, const SkPoint dstClips[], const SkMatrix preViewMatrices[], const SkSamplingOptions &, const SkPaint *, SrcRectConstraint)
void drawAnnotation(const SkRect &rect, const char key[], SkData *value)
virtual SkISize getBaseLayerSize() const
virtual void onDrawRegion(const SkRegion ®ion, const SkPaint &paint)
virtual bool onAccessTopLayerPixels(SkPixmap *pixmap)
virtual void onDrawShadowRec(const SkPath &, const SkDrawShadowRec &)
static constexpr int kMaxFiltersPerLayer
virtual SaveLayerStrategy getSaveLayerStrategy(const SaveLayerRec &)
virtual void onClipRect(const SkRect &rect, SkClipOp op, ClipEdgeStyle edgeStyle)
friend class SkNoDrawCanvas
virtual void onResetClip()
virtual void onDrawMesh(const SkMesh &, sk_sp< SkBlender >, const SkPaint &)
@ kStrict_SrcRectConstraint
sample only inside bounds; slower
@ kFast_SrcRectConstraint
sample outside bounds; faster
void drawGlyphs(int count, const SkGlyphID glyphs[], const SkPoint positions[], const uint32_t clusters[], int textByteCount, const char utf8text[], SkPoint origin, const SkFont &font, const SkPaint &paint)
SkM44 getLocalToDevice() const
void clipRegion(const SkRegion &deviceRgn, SkClipOp op=SkClipOp::kIntersect)
void experimental_DrawEdgeAAQuad(const SkRect &rect, const SkPoint clip[4], QuadAAFlags aaFlags, const SkColor4f &color, SkBlendMode mode)
@ kFullLayer_SaveLayerStrategy
@ kNoLayer_SaveLayerStrategy
void drawMesh(const SkMesh &mesh, sk_sp< SkBlender > blender, const SkPaint &paint)
virtual void onDrawSlug(const sktext::gpu::Slug *slug, const SkPaint &paint)
void drawIRect(const SkIRect &rect, const SkPaint &paint)
virtual void willRestore()
void experimental_DrawEdgeAAImageSet(const ImageSetEntry imageSet[], int cnt, const SkPoint dstClips[], const SkMatrix preViewMatrices[], const SkSamplingOptions &, const SkPaint *paint=nullptr, SrcRectConstraint constraint=kStrict_SrcRectConstraint)
void rotate(SkScalar degrees)
virtual void onDrawPatch(const SkPoint cubics[12], const SkColor colors[4], const SkPoint texCoords[4], SkBlendMode mode, const SkPaint &paint)
void restoreToCount(int saveCount)
virtual void didTranslate(SkScalar, SkScalar)
void drawRRect(const SkRRect &rrect, const SkPaint &paint)
SkMatrix getTotalMatrix() const
virtual void onDrawVerticesObject(const SkVertices *vertices, SkBlendMode mode, const SkPaint &paint)
void drawRoundRect(const SkRect &rect, SkScalar rx, SkScalar ry, const SkPaint &paint)
void drawArc(const SkRect &oval, SkScalar startAngle, SkScalar sweepAngle, bool useCenter, const SkPaint &paint)
void drawImageLattice(const SkImage *image, const Lattice &lattice, const SkRect &dst, SkFilterMode filter, const SkPaint *paint=nullptr)
void clipPath(const SkPath &path, SkClipOp op, bool doAntiAlias)
SkIRect getDeviceClipBounds() const
@ kPreserveLCDText_SaveLayerFlag
@ kInitWithPrevious_SaveLayerFlag
initializes with previous contents
virtual void onDrawOval(const SkRect &rect, const SkPaint &paint)
void drawRegion(const SkRegion ®ion, const SkPaint &paint)
virtual void didConcat44(const SkM44 &)
virtual bool onGetProps(SkSurfaceProps *props, bool top) const
void drawImageRect(const SkImage *, const SkRect &src, const SkRect &dst, const SkSamplingOptions &, const SkPaint *, SrcRectConstraint)
void drawPath(const SkPath &path, const SkPaint &paint)
void drawAtlas(const SkImage *atlas, const SkRSXform xform[], const SkRect tex[], const SkColor colors[], int count, SkBlendMode mode, const SkSamplingOptions &sampling, const SkRect *cullRect, const SkPaint *paint)
void setMatrix(const SkM44 &matrix)
virtual void onClipRRect(const SkRRect &rrect, SkClipOp op, ClipEdgeStyle edgeStyle)
void temporary_internal_getRgnClip(SkRegion *region)
virtual void onClipPath(const SkPath &path, SkClipOp op, ClipEdgeStyle edgeStyle)
void drawDRRect(const SkRRect &outer, const SkRRect &inner, const SkPaint &paint)
void scale(SkScalar sx, SkScalar sy)
void concat(const SkMatrix &matrix)
virtual bool onDoSaveBehind(const SkRect *)
virtual void onDrawGlyphRunList(const sktext::GlyphRunList &glyphRunList, const SkPaint &paint)
SkSurfaceProps getBaseProps() const
void drawPicture(const SkPicture *picture)
virtual void onDrawImageRect2(const SkImage *, const SkRect &src, const SkRect &dst, const SkSamplingOptions &, const SkPaint *, SrcRectConstraint)
void clipShader(sk_sp< SkShader >, SkClipOp=SkClipOp::kIntersect)
static std::unique_ptr< SkCanvas > MakeRasterDirect(const SkImageInfo &info, void *pixels, size_t rowBytes, const SkSurfaceProps *props=nullptr)
void drawVertices(const SkVertices *vertices, SkBlendMode mode, const SkPaint &paint)
virtual sk_sp< SkSurface > onNewSurface(const SkImageInfo &info, const SkSurfaceProps &props)
SkImageInfo imageInfo() const
void * accessTopLayerPixels(SkImageInfo *info, size_t *rowBytes, SkIPoint *origin=nullptr)
@ kLines_PointMode
draw each pair of points as a line segment
@ kPoints_PointMode
draw each point separately
bool readPixels(const SkImageInfo &dstInfo, void *dstPixels, size_t dstRowBytes, int srcX, int srcY)
virtual void onDrawEdgeAAQuad(const SkRect &rect, const SkPoint clip[4], QuadAAFlags aaFlags, const SkColor4f &color, SkBlendMode mode)
virtual void onDrawPoints(PointMode mode, size_t count, const SkPoint pts[], const SkPaint &paint)
void skew(SkScalar sx, SkScalar sy)
void drawTextBlob(const SkTextBlob *blob, SkScalar x, SkScalar y, const SkPaint &paint)
void drawImage(const SkImage *image, SkScalar left, SkScalar top)
bool quickReject(const SkRect &rect) const
virtual void onDrawRRect(const SkRRect &rrect, const SkPaint &paint)
virtual void onClipRegion(const SkRegion &deviceRgn, SkClipOp op)
void clipRRect(const SkRRect &rrect, SkClipOp op, bool doAntiAlias)
int saveLayerAlphaf(const SkRect *bounds, float alpha)
void drawCircle(SkScalar cx, SkScalar cy, SkScalar radius, const SkPaint &paint)
virtual void onDrawArc(const SkRect &rect, SkScalar startAngle, SkScalar sweepAngle, bool useCenter, const SkPaint &paint)
bool affectsTransparentBlack() const
static sk_sp< SkColorFilter > Compose(const sk_sp< SkColorFilter > &outer, sk_sp< SkColorFilter > inner)
static sk_sp< SkColorFilter > Blend(const SkColor4f &c, sk_sp< SkColorSpace >, SkBlendMode mode)
int bytesPerPixel() const
SkColorInfo makeColorSpace(sk_sp< SkColorSpace > cs) const
sk_sp< SkColorSpace > refColorSpace() const
SkColorType colorType() const
const void * back() const
void drawFilteredImage(const skif::Mapping &mapping, SkSpecialImage *src, SkColorType ct, const SkImageFilter *, const SkSamplingOptions &, const SkPaint &)
const SkImageInfo & imageInfo() const
virtual sk_sp< SkDevice > createDevice(const CreateInfo &, const SkPaint *)
virtual void drawVertices(const SkVertices *, sk_sp< SkBlender >, const SkPaint &, bool skipColorXform=false)=0
virtual void drawRRect(const SkRRect &rr, const SkPaint &paint)=0
virtual void drawEdgeAAQuad(const SkRect &rect, const SkPoint clip[4], SkCanvas::QuadAAFlags aaFlags, const SkColor4f &color, SkBlendMode mode)
virtual void drawPoints(SkCanvas::PointMode mode, size_t count, const SkPoint[], const SkPaint &paint)=0
virtual void drawRegion(const SkRegion &r, const SkPaint &paint)
SkIPoint getOrigin() const
virtual void drawAtlas(const SkRSXform[], const SkRect[], const SkColor[], int count, sk_sp< SkBlender >, const SkPaint &)
virtual void clipPath(const SkPath &path, SkClipOp op, bool aa)=0
bool readPixels(const SkPixmap &dst, int x, int y)
virtual bool isClipEmpty() const =0
void clipShader(sk_sp< SkShader > sh, SkClipOp op)
virtual void drawShadow(const SkPath &, const SkDrawShadowRec &)
virtual bool isClipRect() const =0
virtual void clipRegion(const SkRegion ®ion, SkClipOp op)=0
void drawGlyphRunList(SkCanvas *, const sktext::GlyphRunList &glyphRunList, const SkPaint &paint)
virtual void drawEdgeAAImageSet(const SkCanvas::ImageSetEntry[], int count, const SkPoint dstClips[], const SkMatrix preViewMatrices[], const SkSamplingOptions &, const SkPaint &, SkCanvas::SrcRectConstraint)
const SkM44 & globalToDevice() const
virtual void drawDRRect(const SkRRect &outer, const SkRRect &inner, const SkPaint &)
virtual void * getRasterHandle() const
virtual void popClipStack()=0
virtual void pushClipStack()=0
bool accessPixels(SkPixmap *pmap)
const SkMatrix & localToDevice() const
virtual void drawSlug(SkCanvas *, const sktext::gpu::Slug *slug, const SkPaint &paint)
virtual GrRecordingContext * recordingContext() const
virtual void drawSpecial(SkSpecialImage *, const SkMatrix &localToDevice, const SkSamplingOptions &, const SkPaint &, SkCanvas::SrcRectConstraint constraint=SkCanvas::kStrict_SrcRectConstraint)
virtual void drawDevice(SkDevice *, const SkSamplingOptions &, const SkPaint &)
virtual void clipRRect(const SkRRect &rrect, SkClipOp op, bool aa)=0
virtual SkIRect devClipBounds() const =0
const SkSurfaceProps & surfaceProps() const
virtual void clipRect(const SkRect &rect, SkClipOp op, bool aa)=0
const SkM44 & deviceToGlobal() const
virtual void drawDrawable(SkCanvas *, SkDrawable *, const SkMatrix *)
virtual skgpu::graphite::Recorder * recorder() const
void setGlobalCTM(const SkM44 &ctm)
virtual sk_sp< sktext::gpu::Slug > convertGlyphRunListToSlug(const sktext::GlyphRunList &glyphRunList, const SkPaint &paint)
bool peekPixels(SkPixmap *)
virtual sk_sp< SkSurface > makeSurface(const SkImageInfo &, const SkSurfaceProps &)
virtual void drawPaint(const SkPaint &paint)=0
virtual void drawMesh(const SkMesh &mesh, sk_sp< SkBlender >, const SkPaint &)=0
virtual bool isClipAntiAliased() const =0
virtual bool useDrawCoverageMaskForMaskFilters() const
virtual void drawPatch(const SkPoint cubics[12], const SkColor colors[4], const SkPoint texCoords[4], sk_sp< SkBlender >, const SkPaint &paint)
virtual void drawRect(const SkRect &r, const SkPaint &paint)=0
virtual void drawImageRect(const SkImage *, const SkRect *src, const SkRect &dst, const SkSamplingOptions &, const SkPaint &, SkCanvas::SrcRectConstraint)=0
virtual void drawAnnotation(const SkRect &, const char[], SkData *)
virtual void drawPath(const SkPath &path, const SkPaint &paint, bool pathIsMutable=false)=0
virtual void drawArc(const SkRect &oval, SkScalar startAngle, SkScalar sweepAngle, bool useCenter, const SkPaint &paint)
virtual void drawOval(const SkRect &oval, const SkPaint &paint)=0
virtual bool isNoPixelsDevice() const
virtual void replaceClip(const SkIRect &rect)=0
virtual void drawImageLattice(const SkImage *, const SkCanvas::Lattice &, const SkRect &dst, SkFilterMode, const SkPaint &)
std::optional< skif::DeviceSpace< SkIRect > > getOutputBounds(const skif::Mapping &mapping, const skif::ParameterSpace< SkRect > &contentBounds) const
skif::LayerSpace< SkIRect > getInputBounds(const skif::Mapping &mapping, const skif::DeviceSpace< SkIRect > &desiredOutput, std::optional< skif::ParameterSpace< SkRect > > knownContentBounds) const
skif::FilterResult filterImage(const skif::Context &context) const
bool isColorFilterNode(SkColorFilter **filterPtr) const
const SkImageFilter * getInput(int i) const
sk_sp< SkShader > makeShader(SkTileMode tmx, SkTileMode tmy, const SkSamplingOptions &, const SkMatrix *localMatrix=nullptr) const
static bool Valid(int imageWidth, int imageHeight, const SkCanvas::Lattice &lattice)
virtual Type type() const =0
static SkRect MapRect(const SkM44 &m, const SkRect &r)
static bool InverseMapRect(const SkMatrix &mx, SkRect *dst, const SkRect &src)
static SkMatrix Scale(SkScalar sx, SkScalar sy)
SkMatrix & postConcat(const SkMatrix &other)
static SkMatrix Translate(SkScalar dx, SkScalar dy)
SkScalar getTranslateY() const
@ kFill_ScaleToFit
scales in x and y to fill destination SkRect
void mapPoints(SkPoint dst[], const SkPoint src[], int count) const
static SkMatrix Concat(const SkMatrix &a, const SkMatrix &b)
bool invert(SkMatrix *inverse) const
void mapXY(SkScalar x, SkScalar y, SkPoint *result) const
static const SkMatrix & I()
SkMatrix & preTranslate(SkScalar dx, SkScalar dy)
void mapRectScaleTranslate(SkRect *dst, const SkRect &src) const
static SkMatrix MakeRectToRect(const SkRect &src, const SkRect &dst, ScaleToFit stf)
bool isScaleTranslate() const
bool mapRect(SkRect *dst, const SkRect &src, SkApplyPerspectiveClip pc=SkApplyPerspectiveClip::kYes) const
SkScalar getTranslateX() const
bool onDoSaveBehind(const SkRect *) override
SaveLayerStrategy getSaveLayerStrategy(const SaveLayerRec &rec) override
bool resetForNextPicture(const SkIRect &bounds)
static bool Overwrites(const SkPaint *paint, ShaderOverrideOpacity)
@ kNone_ShaderOverrideOpacity
there is no overriding shader (bitmap or image)
@ kOpaque_ShaderOverrideOpacity
the overriding shader is opaque
@ kNotOpaque_ShaderOverrideOpacity
the overriding shader may not be opaque
void setStyle(Style style)
void setAntiAlias(bool aa)
sk_sp< SkImageFilter > refImageFilter() const
void setImageFilter(sk_sp< SkImageFilter > imageFilter)
const SkRect & computeFastBounds(const SkRect &orig, SkRect *storage) const
SkColorFilter * getColorFilter() const
@ kStroke_Style
set to stroke geometry
@ kFill_Style
set to fill geometry
@ kStrokeAndFill_Style
sets to stroke and fill geometry
void setMaskFilter(sk_sp< SkMaskFilter > maskFilter)
bool nothingToDraw() const
SkMaskFilter * getMaskFilter() const
void setShader(sk_sp< SkShader > shader)
void setPathEffect(sk_sp< SkPathEffect > pathEffect)
SkBlender * getBlender() const
SkImageFilter * getImageFilter() const
std::optional< SkBlendMode > asBlendMode() const
const SkRect & getBounds() const
virtual SkRect cullRect() const =0
virtual void playback(SkCanvas *canvas, AbortCallback *callback=nullptr) const =0
virtual int approximateOpCount(bool nested=false) const =0
const SkImageInfo & info() const
void * writable_addr() const
const void * addr() const
static SkRRect MakeOval(const SkRect &oval)
static SkRRect MakeRect(const SkRect &r)
void setOval(const SkRect &oval)
void setRectXY(const SkRect &rect, SkScalar xRad, SkScalar yRad)
const SkRect & getBounds() const
static std::unique_ptr< SkCanvas > MakeCanvas(std::unique_ptr< SkRasterHandleAllocator >, const SkImageInfo &, const Rec *rec=nullptr, const SkSurfaceProps *props=nullptr)
virtual bool allocHandle(const SkImageInfo &, Rec *)=0
void translate(int dx, int dy)
@ kIntersect_Op
target intersected with operand
@ kDifference_Op
target minus operand
const SkIRect & getBounds() const
constexpr bool empty() const
constexpr size_t size() const
SkPixelGeometry pixelGeometry() const
@ kDiscard_ContentChangeMode
discards surface on change
@ kRetain_ContentChangeMode
preserves surface on change
const SkRect & bounds() const
SkVertices::VertexMode mode() const
bool hasTexCoords() const
const SkRect & bounds() const
@ kTriangleFan_VertexMode
void draw(const Context &ctx, SkDevice *target, const SkBlender *blender) const
static FilterResult MakeFromImage(const Context &ctx, sk_sp< SkImage > image, SkRect srcRect, ParameterSpace< SkRect > dstRect, const SkSamplingOptions &sampling)
void applyOrigin(const LayerSpace< SkIPoint > &origin)
const SkMatrix & deviceToLayer() const
const SkMatrix & layerToDevice() const
bool decomposeCTM(const SkMatrix &ctm, const SkImageFilter *filter, const skif::ParameterSpace< SkPoint > &representativePt)
const SkMatrix & layerMatrix() const
LayerSpace< T > paramToLayer(const ParameterSpace< T > ¶mGeometry) const
bool adjustLayerSpace(const SkMatrix &layer)
auto empty() const -> decltype(fGlyphRuns.empty())
SkRect sourceBoundsWithOrigin() const
virtual SkRect sourceBoundsWithOrigin() const =0
FlutterSemanticsFlag flags
unsigned useCenter Optional< SkMatrix > matrix
Optional< SkRect > bounds
SkSamplingOptions sampling
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot data
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 mode
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
font
Font Metadata and Metrics.
SkIRect RoundOut(SkRect r)
sk_sp< SkImageFilter > fFilter
FilterToSpan(const SkImageFilter *filter)
ImageSetEntry & operator=(const ImageSetEntry &)
int fYCount
number of y-coordinates
const SkIRect * fBounds
source bounds to draw from
const int * fYDivs
y-axis values dividing bitmap
int fXCount
number of x-coordinates
const RectType * fRectTypes
array of fill types
const SkColor * fColors
array of colors
const int * fXDivs
x-axis values dividing bitmap
constexpr int32_t y() const
constexpr int32_t x() const
SkIRect makeOutset(int32_t dx, int32_t dy) const
bool intersect(const SkIRect &r)
static bool Intersects(const SkIRect &a, const SkIRect &b)
constexpr SkISize size() const
static constexpr SkIRect MakeSize(const SkISize &size)
static constexpr SkIRect MakeEmpty()
static constexpr SkIRect MakeWH(int32_t w, int32_t h)
constexpr SkIPoint topLeft() const
static constexpr SkIRect MakeXYWH(int32_t x, int32_t y, int32_t w, int32_t h)
void outset(int32_t dx, int32_t dy)
bool contains(int32_t x, int32_t y) const
static constexpr SkISize Make(int32_t w, int32_t h)
const SkColorInfo & colorInfo() const
sk_sp< SkColorSpace > refColorSpace() const
SkISize dimensions() const
static SkImageInfo Make(int width, int height, SkColorType ct, SkAlphaType at)
void set(float x, float y)
constexpr float y() const
constexpr float x() const
void(* fReleaseProc)(void *pixels, void *ctx)
SkRect makeSorted() const
static SkRect Make(const SkISize &size)
static constexpr SkRect MakeEmpty()
constexpr SkRect makeOffset(float dx, float dy) const
void joinPossiblyEmptyRect(const SkRect &r)
bool intersect(const SkRect &r)
static SkRect MakeIWH(int w, int h)
void outset(float dx, float dy)
static constexpr SkRect MakeXYWH(float x, float y, float w, float h)
bool intersects(const SkRect &r) const
bool contains(SkScalar x, SkScalar y) const
void roundOut(SkIRect *dst) const
void round(SkIRect *dst) const
constexpr float height() const
void setLTRB(float left, float top, float right, float bottom)
constexpr float width() const
static constexpr SkRect MakeWH(float w, float h)
const SkFilterMode filter
const SkMipmapMode mipmap
#define TRACE_EVENT0(category_group, name)