Flutter Engine
The Flutter Engine
Classes | Macros | Typedefs | Functions
SkCanvas.cpp File Reference
#include "include/core/SkCanvas.h"
#include "include/core/SkAlphaType.h"
#include "include/core/SkBitmap.h"
#include "include/core/SkBlendMode.h"
#include "include/core/SkBlender.h"
#include "include/core/SkBlurTypes.h"
#include "include/core/SkColorFilter.h"
#include "include/core/SkColorSpace.h"
#include "include/core/SkColorType.h"
#include "include/core/SkImage.h"
#include "include/core/SkImageFilter.h"
#include "include/core/SkMaskFilter.h"
#include "include/core/SkPath.h"
#include "include/core/SkPathEffect.h"
#include "include/core/SkPicture.h"
#include "include/core/SkPixmap.h"
#include "include/core/SkRRect.h"
#include "include/core/SkRSXform.h"
#include "include/core/SkRasterHandleAllocator.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkRegion.h"
#include "include/core/SkShader.h"
#include "include/core/SkStrokeRec.h"
#include "include/core/SkSurface.h"
#include "include/core/SkTextBlob.h"
#include "include/core/SkTileMode.h"
#include "include/core/SkTypes.h"
#include "include/core/SkVertices.h"
#include "include/private/base/SkDebug.h"
#include "include/private/base/SkFloatingPoint.h"
#include "include/private/base/SkSafe32.h"
#include "include/private/base/SkTPin.h"
#include "include/private/base/SkTemplates.h"
#include "include/private/base/SkTo.h"
#include "include/private/chromium/Slug.h"
#include "include/utils/SkNoDrawCanvas.h"
#include "src/base/SkEnumBitMask.h"
#include "src/base/SkMSAN.h"
#include "src/core/SkBlenderBase.h"
#include "src/core/SkBlurMaskFilterImpl.h"
#include "src/core/SkCanvasPriv.h"
#include "src/core/SkDevice.h"
#include "src/core/SkImageFilterTypes.h"
#include "src/core/SkImageFilter_Base.h"
#include "src/core/SkImagePriv.h"
#include "src/core/SkLatticeIter.h"
#include "src/core/SkMaskFilterBase.h"
#include "src/core/SkMatrixPriv.h"
#include "src/core/SkPaintPriv.h"
#include "src/core/SkSpecialImage.h"
#include "src/core/SkSurfacePriv.h"
#include "src/core/SkTraceEvent.h"
#include "src/core/SkVerticesPriv.h"
#include "src/effects/colorfilters/SkColorFilterBase.h"
#include "src/image/SkSurface_Base.h"
#include "src/text/GlyphRun.h"
#include "src/utils/SkPatchUtils.h"
#include <algorithm>
#include <memory>
#include <new>
#include <optional>
#include <tuple>
#include <utility>

Go to the source code of this file.

Classes

class  SkCanvas::AutoUpdateQRBounds
 
struct  FilterToSpan
 

Macros

#define RETURN_ON_NULL(ptr)   do { if (nullptr == (ptr)) return; } while (0)
 
#define RETURN_ON_FALSE(pred)   do { if (!(pred)) return; } while (0)
 

Typedefs

using Slug = sktext::gpu::Slug
 

Functions

static skif::ParameterSpace< SkPointcompute_decomposition_center (const SkMatrix &dstToLocal, std::optional< skif::ParameterSpace< SkRect > > contentBounds, const skif::DeviceSpace< SkIRect > &targetOutput)
 
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 SkColorType image_filter_color_type (const SkColorInfo &dstInfo)
 
static skif::FilterResult apply_alpha_and_colorfilter (const skif::Context &ctx, const skif::FilterResult &image, const SkPaint &paint)
 
static bool fillable (const SkRect &r)
 
static SkPaint clean_paint_for_lattice (const SkPaint *paint)
 
static const SkBlurMaskFilterImplcan_attempt_blurred_rrect_draw (const SkPaint &paint)
 
static SkPaint clean_paint_for_drawImage (const SkPaint *paint)
 
static SkPaint clean_paint_for_drawVertices (SkPaint paint)
 
static SkSamplingOptions clean_sampling_for_constraint (const SkSamplingOptions &sampling, SkCanvas::SrcRectConstraint constraint)
 
static bool install (SkBitmap *bm, const SkImageInfo &info, const SkRasterHandleAllocator::Rec &rec)
 

Macro Definition Documentation

◆ RETURN_ON_FALSE

#define RETURN_ON_FALSE (   pred)    do { if (!(pred)) return; } while (0)

Definition at line 75 of file SkCanvas.cpp.

◆ RETURN_ON_NULL

#define RETURN_ON_NULL (   ptr)    do { if (nullptr == (ptr)) return; } while (0)

Definition at line 74 of file SkCanvas.cpp.

Typedef Documentation

◆ Slug

Definition at line 81 of file SkCanvas.cpp.

Function Documentation

◆ apply_alpha_and_colorfilter()

static skif::FilterResult apply_alpha_and_colorfilter ( const skif::Context ctx,
const skif::FilterResult image,
const SkPaint paint 
)
static

Definition at line 681 of file SkCanvas.cpp.

683 {
684 // The only effects that apply to layers (other than the SkImageFilter that made this image in
685 // the first place) are transparency and color filters.
687 if (paint.getAlphaf() < 1.f) {
688 result = result.applyColorFilter(ctx, SkColorFilters::Blend(paint.getColor4f(),
689 /*colorSpace=*/nullptr,
691 }
692 if (paint.getColorFilter()) {
693 result = result.applyColorFilter(ctx, paint.refColorFilter());
694 }
695 return result;
696}
@ kDstIn
r = d * sa
static sk_sp< SkColorFilter > Blend(const SkColor4f &c, sk_sp< SkColorSpace >, SkBlendMode mode)
const Paint & paint
Definition: color_source.cc:38
GAsyncResult * result
sk_sp< const SkImage > image
Definition: SkRecords.h:269

◆ can_attempt_blurred_rrect_draw()

static const SkBlurMaskFilterImpl * can_attempt_blurred_rrect_draw ( const SkPaint paint)
static

Definition at line 1939 of file SkCanvas.cpp.

1939 {
1940 if (paint.getPathEffect()) {
1941 return nullptr;
1942 }
1943
1944 // TODO: Once stroke-and-fill goes away, we can check the paint's style directly.
1945 if (SkStrokeRec(paint).getStyle() != SkStrokeRec::kFill_Style) {
1946 return nullptr;
1947 }
1948
1949 const SkMaskFilterBase* maskFilter = as_MFB(paint.getMaskFilter());
1950 if (!maskFilter || maskFilter->type() != SkMaskFilterBase::Type::kBlur) {
1951 return nullptr;
1952 }
1953
1954 const SkBlurMaskFilterImpl* blurMaskFilter =
1955 static_cast<const SkBlurMaskFilterImpl*>(maskFilter);
1956 if (blurMaskFilter->blurStyle() != kNormal_SkBlurStyle) {
1957 return nullptr;
1958 }
1959
1960 return blurMaskFilter;
1961}
@ kNormal_SkBlurStyle
fuzzy inside and outside
Definition: SkBlurTypes.h:12
SkMaskFilterBase * as_MFB(SkMaskFilter *mf)
SkBlurStyle blurStyle() const
virtual Type type() const =0

◆ clean_paint_for_drawImage()

static SkPaint clean_paint_for_drawImage ( const SkPaint paint)
static

Definition at line 2165 of file SkCanvas.cpp.

2165 {
2166 SkPaint cleaned;
2167 if (paint) {
2168 cleaned = *paint;
2170 cleaned.setPathEffect(nullptr);
2171 }
2172 return cleaned;
2173}
void setStyle(Style style)
Definition: SkPaint.cpp:105
@ kFill_Style
set to fill geometry
Definition: SkPaint.h:193
void setPathEffect(sk_sp< SkPathEffect > pathEffect)

◆ clean_paint_for_drawVertices()

static SkPaint clean_paint_for_drawVertices ( SkPaint  paint)
static

Definition at line 2177 of file SkCanvas.cpp.

2177 {
2178 paint.setStyle(SkPaint::kFill_Style);
2179 paint.setMaskFilter(nullptr);
2180 paint.setPathEffect(nullptr);
2181 return paint;
2182}

◆ clean_paint_for_lattice()

static SkPaint clean_paint_for_lattice ( const SkPaint paint)
static

Definition at line 1759 of file SkCanvas.cpp.

1759 {
1760 SkPaint cleaned;
1761 if (paint) {
1762 cleaned = *paint;
1763 cleaned.setMaskFilter(nullptr);
1764 cleaned.setAntiAlias(false);
1765 }
1766 return cleaned;
1767}
void setAntiAlias(bool aa)
Definition: SkPaint.h:170
void setMaskFilter(sk_sp< SkMaskFilter > maskFilter)

◆ clean_sampling_for_constraint()

static SkSamplingOptions clean_sampling_for_constraint ( const SkSamplingOptions sampling,
SkCanvas::SrcRectConstraint  constraint 
)
static

Definition at line 2190 of file SkCanvas.cpp.

2192 {
2193 if (constraint == SkCanvas::kStrict_SrcRectConstraint) {
2196 }
2197 if (sampling.isAniso()) {
2199 }
2200 }
2201 return sampling;
2202}
@ kStrict_SrcRectConstraint
sample only inside bounds; slower
Definition: SkCanvas.h:1542
SkSamplingOptions sampling
Definition: SkRecords.h:337
SkSamplingOptions(SkFilterMode::kLinear))
const SkFilterMode filter
const SkMipmapMode mipmap

◆ compute_decomposition_center()

static skif::ParameterSpace< SkPoint > compute_decomposition_center ( const SkMatrix dstToLocal,
std::optional< skif::ParameterSpace< SkRect > >  contentBounds,
const skif::DeviceSpace< SkIRect > &  targetOutput 
)
static

Definition at line 532 of file SkCanvas.cpp.

535 {
536 // Will use the inverse and center of the device bounds if the content bounds aren't provided.
537 SkRect rect = contentBounds ? SkRect(*contentBounds) : SkRect::Make(SkIRect(targetOutput));
538 SkPoint center = {rect.centerX(), rect.centerY()};
539 if (!contentBounds) {
540 // Theoretically, the inverse transform could put center's homogeneous coord behind W = 0,
541 // but that case is handled automatically in Mapping::decomposeCTM later.
542 dstToLocal.mapPoints(&center, 1);
543 }
544
546}
static SkScalar center(float pos0, float pos1)
void mapPoints(SkPoint dst[], const SkPoint src[], int count) const
Definition: SkMatrix.cpp:770
SK_API sk_sp< SkDocument > Make(SkWStream *dst, const SkSerialProcs *=nullptr, std::function< void(const SkPicture *)> onEndPage=nullptr)
sk_sp< SkBlender > blender SkRect rect
Definition: SkRecords.h:350
Definition: SkRect.h:32

◆ fillable()

static bool fillable ( const SkRect r)
static

Definition at line 1753 of file SkCanvas.cpp.

1753 {
1754 SkScalar w = r.width();
1755 SkScalar h = r.height();
1756 return SkIsFinite(w, h) && w > 0 && h > 0;
1757}
static bool SkIsFinite(T x, Pack... values)
float SkScalar
Definition: extension.cpp:12
SkScalar w
SkScalar h
constexpr float height() const
Definition: SkRect.h:769
constexpr float width() const
Definition: SkRect.h:762

◆ get_layer_mapping_and_bounds()

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

Definition at line 568 of file SkCanvas.cpp.

572 {},
573 SkScalar scaleFactor = 1.0f) {
574 SkMatrix dstToLocal;
575 if (!localToDst.isFinite() ||
576 !localToDst.invert(&dstToLocal)) {
577 return {};
578 }
579
581 compute_decomposition_center(dstToLocal, contentBounds, targetOutput);
582
583 // Determine initial mapping and a reasonable maximum dimension to prevent layer-to-device
584 // transforms with perspective and skew from triggering excessive buffer allocations.
585 skif::Mapping mapping;
587 for (const sk_sp<SkImageFilter>& filter : filters) {
588 if (filter) {
589 capability = std::min(capability, as_IFB(filter)->getCTMCapability());
590 }
591 }
592 if (!mapping.decomposeCTM(localToDst, capability, center)) {
593 return {};
594 }
595 // Push scale factor into layer matrix and device matrix (net no change, but the layer will have
596 // its resolution adjusted in comparison to the final device).
597 if (scaleFactor != 1.0f &&
598 !mapping.adjustLayerSpace(SkMatrix::Scale(scaleFactor, scaleFactor))) {
599 return {};
600 }
601
602 // Perspective and skew could exceed this since mapping.deviceToLayer(targetOutput) is
603 // theoretically unbounded under those conditions. Under a 45 degree rotation, a layer needs to
604 // be 2X larger per side of the prior device in order to fully cover it. We use the max of that
605 // and 2048 for a reasonable upper limit (this allows small layers under extreme transforms to
606 // use more relative resolution than a larger layer).
607 static const int kMinDimThreshold = 2048;
608 int maxLayerDim = std::max(Sk64_pin_to_s32(2 * std::max(SkIRect(targetOutput).width64(),
609 SkIRect(targetOutput).height64())),
610 kMinDimThreshold);
611
612 auto baseLayerBounds = mapping.deviceToLayer(targetOutput);
613 if (contentBounds) {
614 // For better or for worse, user bounds currently act as a hard clip on the layer's
615 // extent (i.e., they implement the CSS filter-effects 'filter region' feature).
616 skif::LayerSpace<SkIRect> knownBounds = mapping.paramToLayer(*contentBounds).roundOut();
617 if (!baseLayerBounds.intersect(knownBounds)) {
618 baseLayerBounds = skif::LayerSpace<SkIRect>::Empty();
619 }
620 }
621
622 skif::LayerSpace<SkIRect> layerBounds;
623 if (!filters.empty()) {
624 layerBounds = skif::LayerSpace<SkIRect>::Union(filters.size(), [&](int i) {
625 return filters[i] ? as_IFB(filters[i])
626 ->getInputBounds(mapping, targetOutput, contentBounds)
627 : baseLayerBounds;
628 });
629 // When a filter is involved, the layer size may be larger than the default maxLayerDim due
630 // to required inputs for filters (e.g. a displacement map with a large radius).
631 if (layerBounds.width() > maxLayerDim || layerBounds.height() > maxLayerDim) {
632 skif::Mapping idealMapping{mapping.layerMatrix()};
633 for (const sk_sp<SkImageFilter>& filter : filters) {
634 if (filter) {
635 auto idealLayerBounds = as_IFB(filter)->getInputBounds(
636 idealMapping, targetOutput, contentBounds);
637 maxLayerDim = std::max(std::max(idealLayerBounds.width(),
638 idealLayerBounds.height()),
639 maxLayerDim);
640 }
641 }
642 }
643 } else {
644 if (baseLayerBounds.isEmpty()) {
645 return {};
646 }
647 layerBounds = baseLayerBounds;
648 }
649
650 if (layerBounds.width() > maxLayerDim || layerBounds.height() > maxLayerDim) {
651 skif::LayerSpace<SkIRect> newLayerBounds(
652 SkIRect::MakeWH(std::min(layerBounds.width(), maxLayerDim),
653 std::min(layerBounds.height(), maxLayerDim)));
655 SkRect::Make(SkIRect(newLayerBounds)),
657 if (!mapping.adjustLayerSpace(adjust)) {
658 return {};
659 } else {
660 layerBounds = newLayerBounds;
661 }
662 }
663
664 return std::make_pair(mapping, layerBounds);
665}
static void Union(SkRegion *rgn, const SkIRect &rect)
Definition: RegionTest.cpp:27
static skif::ParameterSpace< SkPoint > compute_decomposition_center(const SkMatrix &dstToLocal, std::optional< skif::ParameterSpace< SkRect > > contentBounds, const skif::DeviceSpace< SkIRect > &targetOutput)
Definition: SkCanvas.cpp:532
static SkImageFilter_Base * as_IFB(SkImageFilter *filter)
static constexpr int32_t Sk64_pin_to_s32(int64_t x)
Definition: SkSafe32.h:16
skif::LayerSpace< SkIRect > getInputBounds(const skif::Mapping &mapping, const skif::DeviceSpace< SkIRect > &desiredOutput, std::optional< skif::ParameterSpace< SkRect > > knownContentBounds) const
static SkMatrix Scale(SkScalar sx, SkScalar sy)
Definition: SkMatrix.h:75
@ kFill_ScaleToFit
scales in x and y to fill destination SkRect
Definition: SkMatrix.h:137
bool invert(SkMatrix *inverse) const
Definition: SkMatrix.h:1206
static SkMatrix MakeRectToRect(const SkRect &src, const SkRect &dst, ScaleToFit stf)
Definition: SkMatrix.h:1172
bool isFinite() const
Definition: SkMatrix.h:1834
const SkMatrix & deviceToLayer() const
bool decomposeCTM(const SkMatrix &ctm, const SkImageFilter *filter, const skif::ParameterSpace< SkPoint > &representativePt)
const SkMatrix & layerMatrix() const
LayerSpace< T > paramToLayer(const ParameterSpace< T > &paramGeometry) const
bool adjustLayerSpace(const SkMatrix &layer)
static float max(float r, float g, float b)
Definition: hsl.cpp:49
static float min(float r, float g, float b)
Definition: hsl.cpp:48
SK_API sk_sp< SkShader > Empty()
static constexpr SkIRect MakeWH(int32_t w, int32_t h)
Definition: SkRect.h:56
static SkRect Make(const SkISize &size)
Definition: SkRect.h:669

◆ image_filter_color_type()

static SkColorType image_filter_color_type ( const SkColorInfo dstInfo)
static

Definition at line 670 of file SkCanvas.cpp.

670 {
671 if (dstInfo.bytesPerPixel() <= 4 &&
672 dstInfo.colorType() != kRGBA_8888_SkColorType &&
673 dstInfo.colorType() != kBGRA_8888_SkColorType) {
674 // "Upgrade" A8, G8, 565, 4444, 1010102, 101010x, and 888x to 8888
675 return kN32_SkColorType;
676 } else {
677 return dstInfo.colorType();
678 }
679}
@ kBGRA_8888_SkColorType
pixel with 8 bits for blue, green, red, alpha; in 32-bit word
Definition: SkColorType.h:26
@ kRGBA_8888_SkColorType
pixel with 8 bits for red, green, blue, alpha; in 32-bit word
Definition: SkColorType.h:24
int bytesPerPixel() const
Definition: SkImageInfo.cpp:88
SkColorType colorType() const
Definition: SkImageInfo.h:140

◆ install()

static bool install ( SkBitmap bm,
const SkImageInfo info,
const SkRasterHandleAllocator::Rec rec 
)
static

Definition at line 2856 of file SkCanvas.cpp.

2857 {
2858 return bm->installPixels(info, rec.fPixels, rec.fRowBytes, rec.fReleaseProc, rec.fReleaseCtx);
2859}
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
Definition: DM.cpp:213
bool installPixels(const SkImageInfo &info, void *pixels, size_t rowBytes, void(*releaseProc)(void *addr, void *context), void *context)
Definition: SkBitmap.cpp:323
void(* fReleaseProc)(void *pixels, void *ctx)