aboutsummaryrefslogtreecommitdiff
path: root/src/deps/skia/include/c
diff options
context:
space:
mode:
authorGravatar Jarred Sumner <jarred@jarredsumner.com> 2022-04-03 16:34:10 -0700
committerGravatar Jarred Sumner <jarred@jarredsumner.com> 2022-04-03 16:34:10 -0700
commita87508008dfa1604baf2d4e39bf44704c00f261c (patch)
tree0be2ade96772037a02803b30e157c367d931e3d9 /src/deps/skia/include/c
parent4a19a3f07f1887903e5638a3be167f0c7b377ba3 (diff)
downloadbun-jarred/canvas.tar.gz
bun-jarred/canvas.tar.zst
bun-jarred/canvas.zip
Diffstat (limited to '')
-rw-r--r--src/deps/skia/include/c/BUILD.bazel91
-rw-r--r--src/deps/skia/include/c/sk_canvas.h159
-rw-r--r--src/deps/skia/include/c/sk_colorspace.h25
-rw-r--r--src/deps/skia/include/c/sk_data.h65
-rw-r--r--src/deps/skia/include/c/sk_image.h71
-rw-r--r--src/deps/skia/include/c/sk_imageinfo.h62
-rw-r--r--src/deps/skia/include/c/sk_maskfilter.h47
-rw-r--r--src/deps/skia/include/c/sk_matrix.h49
-rw-r--r--src/deps/skia/include/c/sk_paint.h145
-rw-r--r--src/deps/skia/include/c/sk_path.h102
-rw-r--r--src/deps/skia/include/c/sk_picture.h70
-rw-r--r--src/deps/skia/include/c/sk_shader.h143
-rw-r--r--src/deps/skia/include/c/sk_surface.h73
-rw-r--r--src/deps/skia/include/c/sk_types.h278
-rw-r--r--src/deps/skia/include/codec/BUILD.bazel47
-rw-r--r--src/deps/skia/include/codec/SkAndroidCodec.h263
-rw-r--r--src/deps/skia/include/codec/SkCodec.h992
-rw-r--r--src/deps/skia/include/codec/SkCodecAnimation.h61
-rw-r--r--src/deps/skia/include/codec/SkEncodedOrigin.h54
-rw-r--r--src/deps/skia/include/config/BUILD.bazel7
-rw-r--r--src/deps/skia/include/config/SkUserConfig.h89
-rw-r--r--src/deps/skia/include/core/BUILD.bazel951
-rw-r--r--src/deps/skia/include/core/SkAnnotation.h50
-rw-r--r--src/deps/skia/include/core/SkBBHFactory.h63
-rw-r--r--src/deps/skia/include/core/SkBitmap.h1212
-rw-r--r--src/deps/skia/include/core/SkBlendMode.h110
-rw-r--r--src/deps/skia/include/core/SkBlender.h33
-rw-r--r--src/deps/skia/include/core/SkBlurTypes.h22
-rw-r--r--src/deps/skia/include/core/SkCanvas.h2583
-rw-r--r--src/deps/skia/include/core/SkCanvasVirtualEnforcer.h61
-rw-r--r--src/deps/skia/include/core/SkClipOp.h19
-rw-r--r--src/deps/skia/include/core/SkColor.h438
-rw-r--r--src/deps/skia/include/core/SkColorFilter.h90
-rw-r--r--src/deps/skia/include/core/SkColorPriv.h152
-rw-r--r--src/deps/skia/include/core/SkColorSpace.h245
-rw-r--r--src/deps/skia/include/core/SkContourMeasure.h131
-rw-r--r--src/deps/skia/include/core/SkCoverageMode.h30
-rw-r--r--src/deps/skia/include/core/SkCubicMap.h45
-rw-r--r--src/deps/skia/include/core/SkCustomMesh.h202
-rw-r--r--src/deps/skia/include/core/SkData.h188
-rw-r--r--src/deps/skia/include/core/SkDataTable.h118
-rw-r--r--src/deps/skia/include/core/SkDeferredDisplayList.h110
-rw-r--r--src/deps/skia/include/core/SkDeferredDisplayListRecorder.h97
-rw-r--r--src/deps/skia/include/core/SkDocument.h91
-rw-r--r--src/deps/skia/include/core/SkDrawLooper.h135
-rw-r--r--src/deps/skia/include/core/SkDrawable.h160
-rw-r--r--src/deps/skia/include/core/SkEncodedImageFormat.h35
-rw-r--r--src/deps/skia/include/core/SkExecutor.h41
-rw-r--r--src/deps/skia/include/core/SkFlattenable.h113
-rw-r--r--src/deps/skia/include/core/SkFont.h534
-rw-r--r--src/deps/skia/include/core/SkFontArguments.h62
-rw-r--r--src/deps/skia/include/core/SkFontMetrics.h138
-rw-r--r--src/deps/skia/include/core/SkFontMgr.h157
-rw-r--r--src/deps/skia/include/core/SkFontParameters.h42
-rw-r--r--src/deps/skia/include/core/SkFontStyle.h81
-rw-r--r--src/deps/skia/include/core/SkFontTypes.h25
-rw-r--r--src/deps/skia/include/core/SkGraphics.h153
-rw-r--r--src/deps/skia/include/core/SkICC.h19
-rw-r--r--src/deps/skia/include/core/SkImage.h1302
-rw-r--r--src/deps/skia/include/core/SkImageEncoder.h72
-rw-r--r--src/deps/skia/include/core/SkImageFilter.h114
-rw-r--r--src/deps/skia/include/core/SkImageGenerator.h215
-rw-r--r--src/deps/skia/include/core/SkImageInfo.h721
-rw-r--r--src/deps/skia/include/core/SkM44.h426
-rw-r--r--src/deps/skia/include/core/SkMallocPixelRef.h42
-rw-r--r--src/deps/skia/include/core/SkMaskFilter.h50
-rw-r--r--src/deps/skia/include/core/SkMath.h54
-rw-r--r--src/deps/skia/include/core/SkMatrix.h1986
-rw-r--r--src/deps/skia/include/core/SkMilestone.h9
-rw-r--r--src/deps/skia/include/core/SkOverdrawCanvas.h68
-rw-r--r--src/deps/skia/include/core/SkPaint.h720
-rw-r--r--src/deps/skia/include/core/SkPath.h1891
-rw-r--r--src/deps/skia/include/core/SkPathBuilder.h268
-rw-r--r--src/deps/skia/include/core/SkPathEffect.h106
-rw-r--r--src/deps/skia/include/core/SkPathMeasure.h88
-rw-r--r--src/deps/skia/include/core/SkPathTypes.h59
-rw-r--r--src/deps/skia/include/core/SkPicture.h280
-rw-r--r--src/deps/skia/include/core/SkPictureRecorder.h115
-rw-r--r--src/deps/skia/include/core/SkPixelRef.h123
-rw-r--r--src/deps/skia/include/core/SkPixmap.h720
-rw-r--r--src/deps/skia/include/core/SkPngChunkReader.h45
-rw-r--r--src/deps/skia/include/core/SkPoint.h566
-rw-r--r--src/deps/skia/include/core/SkPoint3.h157
-rw-r--r--src/deps/skia/include/core/SkPromiseImageTexture.h46
-rw-r--r--src/deps/skia/include/core/SkRRect.h512
-rw-r--r--src/deps/skia/include/core/SkRSXform.h69
-rw-r--r--src/deps/skia/include/core/SkRasterHandleAllocator.h92
-rw-r--r--src/deps/skia/include/core/SkRect.h1378
-rw-r--r--src/deps/skia/include/core/SkRefCnt.h382
-rw-r--r--src/deps/skia/include/core/SkRegion.h672
-rw-r--r--src/deps/skia/include/core/SkSamplingOptions.h92
-rw-r--r--src/deps/skia/include/core/SkScalar.h194
-rw-r--r--src/deps/skia/include/core/SkSerialProcs.h73
-rw-r--r--src/deps/skia/include/core/SkShader.h148
-rw-r--r--src/deps/skia/include/core/SkSize.h90
-rw-r--r--src/deps/skia/include/core/SkSpan.h89
-rw-r--r--src/deps/skia/include/core/SkStream.h524
-rw-r--r--src/deps/skia/include/core/SkString.h302
-rw-r--r--src/deps/skia/include/core/SkStringView.h185
-rw-r--r--src/deps/skia/include/core/SkStrokeRec.h154
-rw-r--r--src/deps/skia/include/core/SkSurface.h1079
-rw-r--r--src/deps/skia/include/core/SkSurfaceCharacterization.h263
-rw-r--r--src/deps/skia/include/core/SkSurfaceProps.h92
-rw-r--r--src/deps/skia/include/core/SkSwizzle.h19
-rw-r--r--src/deps/skia/include/core/SkTextBlob.h503
-rw-r--r--src/deps/skia/include/core/SkTileMode.h41
-rw-r--r--src/deps/skia/include/core/SkTime.h63
-rw-r--r--src/deps/skia/include/core/SkTraceMemoryDump.h99
-rw-r--r--src/deps/skia/include/core/SkTypeface.h454
-rw-r--r--src/deps/skia/include/core/SkTypes.h621
-rw-r--r--src/deps/skia/include/core/SkUnPreMultiply.h56
-rw-r--r--src/deps/skia/include/core/SkVertices.h132
-rw-r--r--src/deps/skia/include/core/SkYUVAInfo.h304
-rw-r--r--src/deps/skia/include/core/SkYUVAPixmaps.h336
114 files changed, 30890 insertions, 0 deletions
diff --git a/src/deps/skia/include/c/BUILD.bazel b/src/deps/skia/include/c/BUILD.bazel
new file mode 100644
index 000000000..ffb4f7f6b
--- /dev/null
+++ b/src/deps/skia/include/c/BUILD.bazel
@@ -0,0 +1,91 @@
+load("//bazel:macros.bzl", "generated_cc_atom")
+
+generated_cc_atom(
+ name = "sk_canvas_hdr",
+ hdrs = ["sk_canvas.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [":sk_types_hdr"],
+)
+
+generated_cc_atom(
+ name = "sk_colorspace_hdr",
+ hdrs = ["sk_colorspace.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [":sk_types_hdr"],
+)
+
+generated_cc_atom(
+ name = "sk_data_hdr",
+ hdrs = ["sk_data.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [":sk_types_hdr"],
+)
+
+generated_cc_atom(
+ name = "sk_image_hdr",
+ hdrs = ["sk_image.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [":sk_types_hdr"],
+)
+
+generated_cc_atom(
+ name = "sk_imageinfo_hdr",
+ hdrs = ["sk_imageinfo.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [":sk_types_hdr"],
+)
+
+generated_cc_atom(
+ name = "sk_maskfilter_hdr",
+ hdrs = ["sk_maskfilter.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [":sk_types_hdr"],
+)
+
+generated_cc_atom(
+ name = "sk_matrix_hdr",
+ hdrs = ["sk_matrix.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [":sk_types_hdr"],
+)
+
+generated_cc_atom(
+ name = "sk_paint_hdr",
+ hdrs = ["sk_paint.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [":sk_types_hdr"],
+)
+
+generated_cc_atom(
+ name = "sk_path_hdr",
+ hdrs = ["sk_path.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [":sk_types_hdr"],
+)
+
+generated_cc_atom(
+ name = "sk_picture_hdr",
+ hdrs = ["sk_picture.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [":sk_types_hdr"],
+)
+
+generated_cc_atom(
+ name = "sk_shader_hdr",
+ hdrs = ["sk_shader.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [":sk_types_hdr"],
+)
+
+generated_cc_atom(
+ name = "sk_surface_hdr",
+ hdrs = ["sk_surface.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [":sk_types_hdr"],
+)
+
+generated_cc_atom(
+ name = "sk_types_hdr",
+ hdrs = ["sk_types.h"],
+ visibility = ["//:__subpackages__"],
+)
diff --git a/src/deps/skia/include/c/sk_canvas.h b/src/deps/skia/include/c/sk_canvas.h
new file mode 100644
index 000000000..751c07ba3
--- /dev/null
+++ b/src/deps/skia/include/c/sk_canvas.h
@@ -0,0 +1,159 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+// EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL
+// DO NOT USE -- FOR INTERNAL TESTING ONLY
+
+#ifndef sk_canvas_DEFINED
+#define sk_canvas_DEFINED
+
+#include "include/c/sk_types.h"
+
+SK_C_PLUS_PLUS_BEGIN_GUARD
+
+/**
+ Save the current matrix and clip on the canvas. When the
+ balancing call to sk_canvas_restore() is made, the previous matrix
+ and clip are restored.
+*/
+SK_API void sk_canvas_save(sk_canvas_t*);
+/**
+ This behaves the same as sk_canvas_save(), but in addition it
+ allocates an offscreen surface. All drawing calls are directed
+ there, and only when the balancing call to sk_canvas_restore() is
+ made is that offscreen transfered to the canvas (or the previous
+ layer).
+
+ @param sk_rect_t* (may be null) This rect, if non-null, is used as
+ a hint to limit the size of the offscreen, and
+ thus drawing may be clipped to it, though that
+ clipping is not guaranteed to happen. If exact
+ clipping is desired, use sk_canvas_clip_rect().
+ @param sk_paint_t* (may be null) The paint is copied, and is applied
+ to the offscreen when sk_canvas_restore() is
+ called.
+*/
+SK_API void sk_canvas_save_layer(sk_canvas_t*, const sk_rect_t*, const sk_paint_t*);
+/**
+ This call balances a previous call to sk_canvas_save() or
+ sk_canvas_save_layer(), and is used to remove all modifications to
+ the matrix and clip state since the last save call. It is an
+ error to call sk_canvas_restore() more times than save and
+ save_layer were called.
+*/
+SK_API void sk_canvas_restore(sk_canvas_t*);
+
+/**
+ Preconcat the current coordinate transformation matrix with the
+ specified translation.
+*/
+SK_API void sk_canvas_translate(sk_canvas_t*, float dx, float dy);
+/**
+ Preconcat the current coordinate transformation matrix with the
+ specified scale.
+*/
+SK_API void sk_canvas_scale(sk_canvas_t*, float sx, float sy);
+/**
+ Preconcat the current coordinate transformation matrix with the
+ specified rotation in degrees.
+*/
+SK_API void sk_canvas_rotate_degrees(sk_canvas_t*, float degrees);
+/**
+ Preconcat the current coordinate transformation matrix with the
+ specified rotation in radians.
+*/
+SK_API void sk_canvas_rotate_radians(sk_canvas_t*, float radians);
+/**
+ Preconcat the current coordinate transformation matrix with the
+ specified skew.
+*/
+SK_API void sk_canvas_skew(sk_canvas_t*, float sx, float sy);
+/**
+ Preconcat the current coordinate transformation matrix with the
+ specified matrix.
+*/
+SK_API void sk_canvas_concat(sk_canvas_t*, const sk_matrix_t*);
+
+/**
+ Modify the current clip with the specified rectangle. The new
+ current clip will be the intersection of the old clip and the
+ rectange.
+*/
+SK_API void sk_canvas_clip_rect(sk_canvas_t*, const sk_rect_t*);
+/**
+ Modify the current clip with the specified path. The new
+ current clip will be the intersection of the old clip and the
+ path.
+*/
+SK_API void sk_canvas_clip_path(sk_canvas_t*, const sk_path_t*);
+
+/**
+ Fill the entire canvas (restricted to the current clip) with the
+ specified paint.
+*/
+SK_API void sk_canvas_draw_paint(sk_canvas_t*, const sk_paint_t*);
+/**
+ Draw the specified rectangle using the specified paint. The
+ rectangle will be filled or stroked based on the style in the
+ paint.
+*/
+SK_API void sk_canvas_draw_rect(sk_canvas_t*, const sk_rect_t*, const sk_paint_t*);
+/**
+ * Draw the circle centered at (cx, cy) with radius rad using the specified paint.
+ * The circle will be filled or framed based on the style in the paint
+ */
+SK_API void sk_canvas_draw_circle(sk_canvas_t*, float cx, float cy, float rad, const sk_paint_t*);
+/**
+ Draw the specified oval using the specified paint. The oval will be
+ filled or framed based on the style in the paint
+*/
+SK_API void sk_canvas_draw_oval(sk_canvas_t*, const sk_rect_t*, const sk_paint_t*);
+/**
+ Draw the specified path using the specified paint. The path will be
+ filled or framed based on the style in the paint
+*/
+SK_API void sk_canvas_draw_path(sk_canvas_t*, const sk_path_t*, const sk_paint_t*);
+/**
+ Draw the specified image, with its top/left corner at (x,y), using
+ the specified paint, transformed by the current matrix.
+
+ @param sk_paint_t* (may be NULL) the paint used to draw the image.
+*/
+SK_API void sk_canvas_draw_image(sk_canvas_t*, const sk_image_t*, float x, float y,
+ const sk_sampling_options_t*, const sk_paint_t*);
+/**
+ Draw the specified image, scaling and translating so that it fills
+ the specified dst rect. If the src rect is non-null, only that
+ subset of the image is transformed and drawn.
+
+ @param sk_paint_t* (may be NULL) The paint used to draw the image.
+*/
+SK_API void sk_canvas_draw_image_rect(sk_canvas_t*, const sk_image_t*,
+ const sk_rect_t* src, const sk_rect_t* dst,
+ const sk_sampling_options_t*, const sk_paint_t*);
+
+/**
+ Draw the picture into this canvas (replay the pciture's drawing commands).
+
+ @param sk_matrix_t* If non-null, apply that matrix to the CTM when
+ drawing this picture. This is logically
+ equivalent to: save, concat, draw_picture,
+ restore.
+
+ @param sk_paint_t* If non-null, draw the picture into a temporary
+ buffer, and then apply the paint's alpha,
+ colorfilter, imagefilter, and xfermode to that
+ buffer as it is drawn to the canvas. This is
+ logically equivalent to save_layer(paint),
+ draw_picture, restore.
+*/
+SK_API void sk_canvas_draw_picture(sk_canvas_t*, const sk_picture_t*,
+ const sk_matrix_t*, const sk_paint_t*);
+
+SK_C_PLUS_PLUS_END_GUARD
+
+#endif
diff --git a/src/deps/skia/include/c/sk_colorspace.h b/src/deps/skia/include/c/sk_colorspace.h
new file mode 100644
index 000000000..31839840d
--- /dev/null
+++ b/src/deps/skia/include/c/sk_colorspace.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2018 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+// EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL
+// DO NOT USE -- FOR INTERNAL TESTING ONLY
+
+#ifndef sk_colorspace_DEFINED
+#define sk_colorspace_DEFINED
+
+#include "include/c/sk_types.h"
+
+SK_C_PLUS_PLUS_BEGIN_GUARD
+
+SK_API sk_colorspace_t* sk_colorspace_new_srgb();
+
+SK_API void sk_colorspace_ref(sk_colorspace_t*);
+SK_API void sk_colorspace_unref(sk_colorspace_t*);
+
+SK_C_PLUS_PLUS_END_GUARD
+
+#endif
diff --git a/src/deps/skia/include/c/sk_data.h b/src/deps/skia/include/c/sk_data.h
new file mode 100644
index 000000000..a330b92f2
--- /dev/null
+++ b/src/deps/skia/include/c/sk_data.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+// EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL
+// DO NOT USE -- FOR INTERNAL TESTING ONLY
+
+#ifndef sk_data_DEFINED
+#define sk_data_DEFINED
+
+#include "include/c/sk_types.h"
+
+SK_C_PLUS_PLUS_BEGIN_GUARD
+
+/**
+ Returns a new sk_data_t by copying the specified source data.
+ This call must be balanced with a call to sk_data_unref().
+*/
+SK_API sk_data_t* sk_data_new_with_copy(const void* src, size_t length);
+/**
+ Pass ownership of the given memory to a new sk_data_t, which will
+ call free() when the refernce count of the data goes to zero. For
+ example:
+ size_t length = 1024;
+ void* buffer = malloc(length);
+ memset(buffer, 'X', length);
+ sk_data_t* data = sk_data_new_from_malloc(buffer, length);
+ This call must be balanced with a call to sk_data_unref().
+*/
+SK_API sk_data_t* sk_data_new_from_malloc(const void* memory, size_t length);
+/**
+ Returns a new sk_data_t using a subset of the data in the
+ specified source sk_data_t. This call must be balanced with a
+ call to sk_data_unref().
+*/
+SK_API sk_data_t* sk_data_new_subset(const sk_data_t* src, size_t offset, size_t length);
+
+/**
+ Increment the reference count on the given sk_data_t. Must be
+ balanced by a call to sk_data_unref().
+*/
+SK_API void sk_data_ref(const sk_data_t*);
+/**
+ Decrement the reference count. If the reference count is 1 before
+ the decrement, then release both the memory holding the sk_data_t
+ and the memory it is managing. New sk_data_t are created with a
+ reference count of 1.
+*/
+SK_API void sk_data_unref(const sk_data_t*);
+
+/**
+ Returns the number of bytes stored.
+*/
+SK_API size_t sk_data_get_size(const sk_data_t*);
+/**
+ Returns the pointer to the data.
+ */
+SK_API const void* sk_data_get_data(const sk_data_t*);
+
+SK_C_PLUS_PLUS_END_GUARD
+
+#endif
diff --git a/src/deps/skia/include/c/sk_image.h b/src/deps/skia/include/c/sk_image.h
new file mode 100644
index 000000000..d8ddc145d
--- /dev/null
+++ b/src/deps/skia/include/c/sk_image.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+// EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL
+// DO NOT USE -- FOR INTERNAL TESTING ONLY
+
+#ifndef sk_image_DEFINED
+#define sk_image_DEFINED
+
+#include "include/c/sk_types.h"
+
+SK_C_PLUS_PLUS_BEGIN_GUARD
+
+/**
+ * Return a new image that has made a copy of the provided pixels, or NULL on failure.
+ * Balance with a call to sk_image_unref().
+ */
+SK_API sk_image_t* sk_image_new_raster_copy(const sk_imageinfo_t*, const void* pixels, size_t rowBytes);
+
+/**
+ * If the specified data can be interpreted as a compressed image (e.g. PNG or JPEG) then this
+ * returns an image. If the encoded data is not supported, returns NULL.
+ *
+ * On success, the encoded data may be processed immediately, or it may be ref()'d for later
+ * use.
+ */
+SK_API sk_image_t* sk_image_new_from_encoded(const sk_data_t* encoded);
+
+/**
+ * Encode the image's pixels and return the result as a new PNG in a
+ * sk_data_t, which the caller must manage: call sk_data_unref() when
+ * they are done.
+ *
+ * If the image type cannot be encoded, this will return NULL.
+ */
+SK_API sk_data_t* sk_image_encode(const sk_image_t*);
+
+/**
+ * Increment the reference count on the given sk_image_t. Must be
+ * balanced by a call to sk_image_unref().
+*/
+SK_API void sk_image_ref(const sk_image_t*);
+/**
+ * Decrement the reference count. If the reference count is 1 before
+ * the decrement, then release both the memory holding the sk_image_t
+ * and the memory it is managing. New sk_image_t are created with a
+ reference count of 1.
+*/
+SK_API void sk_image_unref(const sk_image_t*);
+
+/**
+ * Return the width of the sk_image_t/
+ */
+SK_API int sk_image_get_width(const sk_image_t*);
+/**
+ * Return the height of the sk_image_t/
+ */
+SK_API int sk_image_get_height(const sk_image_t*);
+
+/**
+ * Returns a non-zero value unique among all images.
+ */
+SK_API uint32_t sk_image_get_unique_id(const sk_image_t*);
+
+SK_C_PLUS_PLUS_END_GUARD
+
+#endif
diff --git a/src/deps/skia/include/c/sk_imageinfo.h b/src/deps/skia/include/c/sk_imageinfo.h
new file mode 100644
index 000000000..6c8e9fff2
--- /dev/null
+++ b/src/deps/skia/include/c/sk_imageinfo.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2018 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+// EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL
+// DO NOT USE -- FOR INTERNAL TESTING ONLY
+
+#ifndef sk_imageinfo_DEFINED
+#define sk_imageinfo_DEFINED
+
+#include "include/c/sk_types.h"
+
+SK_C_PLUS_PLUS_BEGIN_GUARD
+
+typedef enum {
+ UNKNOWN_SK_COLORTYPE,
+ RGBA_8888_SK_COLORTYPE,
+ BGRA_8888_SK_COLORTYPE,
+ ALPHA_8_SK_COLORTYPE,
+ GRAY_8_SK_COLORTYPE,
+ RGBA_F16_SK_COLORTYPE,
+ RGBA_F32_SK_COLORTYPE,
+} sk_colortype_t;
+
+typedef enum {
+ OPAQUE_SK_ALPHATYPE,
+ PREMUL_SK_ALPHATYPE,
+ UNPREMUL_SK_ALPHATYPE,
+} sk_alphatype_t;
+
+/**
+ * Allocate a new imageinfo object. If colorspace is not null, it's owner-count will be
+ * incremented automatically.
+ */
+SK_API sk_imageinfo_t* sk_imageinfo_new(int width, int height, sk_colortype_t ct, sk_alphatype_t at,
+ sk_colorspace_t* cs);
+
+/**
+ * Free the imageinfo object. If it contains a reference to a colorspace, its owner-count will
+ * be decremented automatically.
+ */
+SK_API void sk_imageinfo_delete(sk_imageinfo_t*);
+
+SK_API int32_t sk_imageinfo_get_width(const sk_imageinfo_t*);
+SK_API int32_t sk_imageinfo_get_height(const sk_imageinfo_t*);
+SK_API sk_colortype_t sk_imageinfo_get_colortype(const sk_imageinfo_t*);
+SK_API sk_alphatype_t sk_imageinfo_get_alphatype(const sk_imageinfo_t*);
+
+/**
+ * Return the colorspace object reference contained in the imageinfo, or null if there is none.
+ * Note: this does not modify the owner-count on the colorspace object. If the caller needs to
+ * use the colorspace beyond the lifetime of the imageinfo, it should manually call
+ * sk_colorspace_ref() (and then call unref() when it is done).
+ */
+SK_API sk_colorspace_t* sk_imageinfo_get_colorspace(const sk_imageinfo_t*);
+
+SK_C_PLUS_PLUS_END_GUARD
+
+#endif
diff --git a/src/deps/skia/include/c/sk_maskfilter.h b/src/deps/skia/include/c/sk_maskfilter.h
new file mode 100644
index 000000000..c8aa7ed44
--- /dev/null
+++ b/src/deps/skia/include/c/sk_maskfilter.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+// EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL
+// DO NOT USE -- FOR INTERNAL TESTING ONLY
+
+#ifndef sk_maskfilter_DEFINED
+#define sk_maskfilter_DEFINED
+
+#include "include/c/sk_types.h"
+
+typedef enum {
+ NORMAL_SK_BLUR_STYLE, //!< fuzzy inside and outside
+ SOLID_SK_BLUR_STYLE, //!< solid inside, fuzzy outside
+ OUTER_SK_BLUR_STYLE, //!< nothing inside, fuzzy outside
+ INNER_SK_BLUR_STYLE, //!< fuzzy inside, nothing outside
+} sk_blurstyle_t;
+
+SK_C_PLUS_PLUS_BEGIN_GUARD
+
+/**
+ Increment the reference count on the given sk_maskfilter_t. Must be
+ balanced by a call to sk_maskfilter_unref().
+*/
+SK_API void sk_maskfilter_ref(sk_maskfilter_t*);
+/**
+ Decrement the reference count. If the reference count is 1 before
+ the decrement, then release both the memory holding the
+ sk_maskfilter_t and any other associated resources. New
+ sk_maskfilter_t are created with a reference count of 1.
+*/
+SK_API void sk_maskfilter_unref(sk_maskfilter_t*);
+
+/**
+ Create a blur maskfilter.
+ @param sk_blurstyle_t The SkBlurStyle to use
+ @param sigma Standard deviation of the Gaussian blur to apply. Must be > 0.
+*/
+SK_API sk_maskfilter_t* sk_maskfilter_new_blur(sk_blurstyle_t, float sigma);
+
+SK_C_PLUS_PLUS_END_GUARD
+
+#endif
diff --git a/src/deps/skia/include/c/sk_matrix.h b/src/deps/skia/include/c/sk_matrix.h
new file mode 100644
index 000000000..244863c4f
--- /dev/null
+++ b/src/deps/skia/include/c/sk_matrix.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+// EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL
+// DO NOT USE -- FOR INTERNAL TESTING ONLY
+
+#ifndef sk_matrix_DEFINED
+#define sk_matrix_DEFINED
+
+#include "include/c/sk_types.h"
+
+SK_C_PLUS_PLUS_BEGIN_GUARD
+
+/** Set the matrix to identity */
+void sk_matrix_set_identity(sk_matrix_t*);
+
+/** Set the matrix to translate by (tx, ty). */
+void sk_matrix_set_translate(sk_matrix_t*, float tx, float ty);
+/**
+ Preconcats the matrix with the specified translation.
+ M' = M * T(dx, dy)
+*/
+void sk_matrix_pre_translate(sk_matrix_t*, float tx, float ty);
+/**
+ Postconcats the matrix with the specified translation.
+ M' = T(dx, dy) * M
+*/
+void sk_matrix_post_translate(sk_matrix_t*, float tx, float ty);
+
+/** Set the matrix to scale by sx and sy. */
+void sk_matrix_set_scale(sk_matrix_t*, float sx, float sy);
+/**
+ Preconcats the matrix with the specified scale.
+ M' = M * S(sx, sy)
+*/
+void sk_matrix_pre_scale(sk_matrix_t*, float sx, float sy);
+/**
+ Postconcats the matrix with the specified scale.
+ M' = S(sx, sy) * M
+*/
+void sk_matrix_post_scale(sk_matrix_t*, float sx, float sy);
+
+SK_C_PLUS_PLUS_END_GUARD
+
+#endif
diff --git a/src/deps/skia/include/c/sk_paint.h b/src/deps/skia/include/c/sk_paint.h
new file mode 100644
index 000000000..98ba4954c
--- /dev/null
+++ b/src/deps/skia/include/c/sk_paint.h
@@ -0,0 +1,145 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+// EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL
+// DO NOT USE -- FOR INTERNAL TESTING ONLY
+
+#ifndef sk_paint_DEFINED
+#define sk_paint_DEFINED
+
+#include "include/c/sk_types.h"
+
+SK_C_PLUS_PLUS_BEGIN_GUARD
+
+/**
+ Create a new paint with default settings:
+ antialias : false
+ stroke : false
+ stroke width : 0.0f (hairline)
+ stroke miter : 4.0f
+ stroke cap : BUTT_SK_STROKE_CAP
+ stroke join : MITER_SK_STROKE_JOIN
+ color : opaque black
+ shader : NULL
+ maskfilter : NULL
+ xfermode_mode : SRCOVER_SK_XFERMODE_MODE
+*/
+SK_API sk_paint_t* sk_paint_new(void);
+/**
+ Release the memory storing the sk_paint_t and unref() all
+ associated objects.
+*/
+SK_API void sk_paint_delete(sk_paint_t*);
+
+/**
+ Return true iff the paint has antialiasing enabled.
+*/
+SK_API bool sk_paint_is_antialias(const sk_paint_t*);
+/**
+ Set to true to enable antialiasing, false to disable it on this
+ sk_paint_t.
+*/
+SK_API void sk_paint_set_antialias(sk_paint_t*, bool);
+
+/**
+ Return the paint's curent drawing color.
+*/
+SK_API sk_color_t sk_paint_get_color(const sk_paint_t*);
+/**
+ Set the paint's curent drawing color.
+*/
+SK_API void sk_paint_set_color(sk_paint_t*, sk_color_t);
+
+/* stroke settings */
+
+/**
+ Return true iff stroking is enabled rather than filling on this
+ sk_paint_t.
+*/
+SK_API bool sk_paint_is_stroke(const sk_paint_t*);
+/**
+ Set to true to enable stroking rather than filling with this
+ sk_paint_t.
+*/
+SK_API void sk_paint_set_stroke(sk_paint_t*, bool);
+
+/**
+ Return the width for stroking. A value of 0 strokes in hairline mode.
+ */
+SK_API float sk_paint_get_stroke_width(const sk_paint_t*);
+/**
+ Set the width for stroking. A value of 0 strokes in hairline mode
+ (always draw 1-pixel wide, regardless of the matrix).
+ */
+SK_API void sk_paint_set_stroke_width(sk_paint_t*, float width);
+
+/**
+ Return the paint's stroke miter value. This is used to control the
+ behavior of miter joins when the joins angle is sharp.
+*/
+SK_API float sk_paint_get_stroke_miter(const sk_paint_t*);
+/**
+ Set the paint's stroke miter value. This is used to control the
+ behavior of miter joins when the joins angle is sharp. This value
+ must be >= 0.
+*/
+SK_API void sk_paint_set_stroke_miter(sk_paint_t*, float miter);
+
+typedef enum {
+ BUTT_SK_STROKE_CAP,
+ ROUND_SK_STROKE_CAP,
+ SQUARE_SK_STROKE_CAP
+} sk_stroke_cap_t;
+
+/**
+ Return the paint's stroke cap type, controlling how the start and
+ end of stroked lines and paths are treated.
+*/
+SK_API sk_stroke_cap_t sk_paint_get_stroke_cap(const sk_paint_t*);
+/**
+ Set the paint's stroke cap type, controlling how the start and
+ end of stroked lines and paths are treated.
+*/
+SK_API void sk_paint_set_stroke_cap(sk_paint_t*, sk_stroke_cap_t);
+
+typedef enum {
+ MITER_SK_STROKE_JOIN,
+ ROUND_SK_STROKE_JOIN,
+ BEVEL_SK_STROKE_JOIN
+} sk_stroke_join_t;
+
+/**
+ Return the paint's stroke join type, specifies the treatment that
+ is applied to corners in paths and rectangles
+ */
+SK_API sk_stroke_join_t sk_paint_get_stroke_join(const sk_paint_t*);
+/**
+ Set the paint's stroke join type, specifies the treatment that
+ is applied to corners in paths and rectangles
+ */
+SK_API void sk_paint_set_stroke_join(sk_paint_t*, sk_stroke_join_t);
+
+/**
+ * Set the paint's shader to the specified parameter. This will automatically call unref() on
+ * any previous value, and call ref() on the new value.
+ */
+SK_API void sk_paint_set_shader(sk_paint_t*, sk_shader_t*);
+
+/**
+ * Set the paint's maskfilter to the specified parameter. This will automatically call unref() on
+ * any previous value, and call ref() on the new value.
+ */
+SK_API void sk_paint_set_maskfilter(sk_paint_t*, sk_maskfilter_t*);
+
+/**
+ * Set the paint's xfermode to the specified parameter.
+ */
+SK_API void sk_paint_set_xfermode_mode(sk_paint_t*, sk_xfermode_mode_t);
+
+SK_C_PLUS_PLUS_END_GUARD
+
+#endif
diff --git a/src/deps/skia/include/c/sk_path.h b/src/deps/skia/include/c/sk_path.h
new file mode 100644
index 000000000..ed8cbb94f
--- /dev/null
+++ b/src/deps/skia/include/c/sk_path.h
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+// EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL
+// DO NOT USE -- FOR INTERNAL TESTING ONLY
+
+#ifndef sk_path_DEFINED
+#define sk_path_DEFINED
+
+#include "include/c/sk_types.h"
+
+SK_C_PLUS_PLUS_BEGIN_GUARD
+
+typedef enum {
+ CW_SK_PATH_DIRECTION,
+ CCW_SK_PATH_DIRECTION,
+} sk_path_direction_t;
+
+typedef struct sk_pathbuilder_t sk_pathbuilder_t;
+
+/** Create a new, empty path. */
+SK_API sk_pathbuilder_t* sk_pathbuilder_new(void);
+
+/** Release the memory used by a sk_pathbuilder_t. */
+SK_API void sk_pathbuilder_delete(sk_pathbuilder_t*);
+
+/** Set the beginning of the next contour to the point (x,y). */
+SK_API void sk_pathbuilder_move_to(sk_pathbuilder_t*, float x, float y);
+/**
+ Add a line from the last point to the specified point (x,y). If no
+ sk_pathbuilder_move_to() call has been made for this contour, the first
+ point is automatically set to (0,0).
+*/
+SK_API void sk_pathbuilder_line_to(sk_pathbuilder_t*, float x, float y);
+/**
+ Add a quadratic bezier from the last point, approaching control
+ point (x0,y0), and ending at (x1,y1). If no sk_pathbuilder_move_to() call
+ has been made for this contour, the first point is automatically
+ set to (0,0).
+*/
+SK_API void sk_pathbuilder_quad_to(sk_pathbuilder_t*, float x0, float y0, float x1, float y1);
+/**
+ Add a conic curve from the last point, approaching control point
+ (x0,y01), and ending at (x1,y1) with weight w. If no
+ sk_pathbuilder_move_to() call has been made for this contour, the first
+ point is automatically set to (0,0).
+*/
+SK_API void sk_pathbuilder_conic_to(sk_pathbuilder_t*, float x0, float y0, float x1, float y1, float w);
+/**
+ Add a cubic bezier from the last point, approaching control points
+ (x0,y0) and (x1,y1), and ending at (x2,y2). If no
+ sk_pathbuilder_move_to() call has been made for this contour, the first
+ point is automatically set to (0,0).
+*/
+SK_API void sk_pathbuilder_cubic_to(sk_pathbuilder_t*,
+ float x0, float y0,
+ float x1, float y1,
+ float x2, float y2);
+/**
+ Close the current contour. If the current point is not equal to the
+ first point of the contour, a line segment is automatically added.
+*/
+SK_API void sk_pathbuilder_close(sk_pathbuilder_t*);
+
+/**
+ Add a closed rectangle contour to the path.
+*/
+SK_API void sk_pathbuilder_add_rect(sk_pathbuilder_t*, const sk_rect_t*, sk_path_direction_t);
+/**
+ Add a closed oval contour to the path
+*/
+SK_API void sk_pathbuilder_add_oval(sk_pathbuilder_t*, const sk_rect_t*, sk_path_direction_t);
+
+/**** path *****/
+
+/**
+* Return a Path from the builder, resetting the builder to its original empty state.
+*/
+SK_API sk_path_t* sk_pathbuilder_detach_path(sk_pathbuilder_t*);
+
+/**
+ * Return a Path from the builder. The builder reamins in its current state.
+ */
+SK_API sk_path_t* sk_pathbuilder_snapshot_path(sk_pathbuilder_t*);
+
+/** Release the memory used by a sk_path_t. */
+SK_API void sk_path_delete(sk_path_t*);
+
+/**
+ * If the path is empty, return false and set the rect parameter to [0, 0, 0, 0].
+ * else return true and set the rect parameter to the bounds of the control-points
+ * of the path.
+ */
+SK_API bool sk_path_get_bounds(const sk_path_t*, sk_rect_t*);
+
+SK_C_PLUS_PLUS_END_GUARD
+
+#endif
diff --git a/src/deps/skia/include/c/sk_picture.h b/src/deps/skia/include/c/sk_picture.h
new file mode 100644
index 000000000..e56910407
--- /dev/null
+++ b/src/deps/skia/include/c/sk_picture.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+// EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL
+// DO NOT USE -- FOR INTERNAL TESTING ONLY
+
+#ifndef sk_picture_DEFINED
+#define sk_picture_DEFINED
+
+#include "include/c/sk_types.h"
+
+SK_C_PLUS_PLUS_BEGIN_GUARD
+
+/**
+ Create a new sk_picture_recorder_t. Its resources should be
+ released with a call to sk_picture_recorder_delete().
+*/
+SK_API sk_picture_recorder_t* sk_picture_recorder_new(void);
+/**
+ Release the memory and other resources used by this
+ sk_picture_recorder_t.
+*/
+SK_API void sk_picture_recorder_delete(sk_picture_recorder_t*);
+
+/**
+ Returns the canvas that records the drawing commands
+
+ @param sk_rect_t* the cull rect used when recording this
+ picture. Any drawing the falls outside of this
+ rect is undefined, and may be drawn or it may not.
+*/
+SK_API sk_canvas_t* sk_picture_recorder_begin_recording(sk_picture_recorder_t*, const sk_rect_t*);
+/**
+ Signal that the caller is done recording. This invalidates the
+ canvas returned by begin_recording. Ownership of the sk_picture_t
+ is passed to the caller, who must call sk_picture_unref() when
+ they are done using it. The returned picture is immutable.
+*/
+SK_API sk_picture_t* sk_picture_recorder_end_recording(sk_picture_recorder_t*);
+
+/**
+ Increment the reference count on the given sk_picture_t. Must be
+ balanced by a call to sk_picture_unref().
+*/
+SK_API void sk_picture_ref(sk_picture_t*);
+/**
+ Decrement the reference count. If the reference count is 1 before
+ the decrement, then release both the memory holding the
+ sk_picture_t and any resouces it may be managing. New
+ sk_picture_t are created with a reference count of 1.
+*/
+SK_API void sk_picture_unref(sk_picture_t*);
+
+/**
+ Returns a non-zero value unique among all pictures.
+ */
+SK_API uint32_t sk_picture_get_unique_id(sk_picture_t*);
+
+/**
+ Return the cull rect specified when this picture was recorded.
+*/
+SK_API sk_rect_t sk_picture_get_bounds(sk_picture_t*);
+
+SK_C_PLUS_PLUS_END_GUARD
+
+#endif
diff --git a/src/deps/skia/include/c/sk_shader.h b/src/deps/skia/include/c/sk_shader.h
new file mode 100644
index 000000000..023ccbaea
--- /dev/null
+++ b/src/deps/skia/include/c/sk_shader.h
@@ -0,0 +1,143 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+// EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL
+// DO NOT USE -- FOR INTERNAL TESTING ONLY
+
+#ifndef sk_shader_DEFINED
+#define sk_shader_DEFINED
+
+#include "include/c/sk_types.h"
+
+SK_C_PLUS_PLUS_BEGIN_GUARD
+
+SK_API void sk_shader_ref(sk_shader_t*);
+SK_API void sk_shader_unref(sk_shader_t*);
+
+typedef enum {
+ CLAMP_SK_SHADER_TILEMODE,
+ REPEAT_SK_SHADER_TILEMODE,
+ MIRROR_SK_SHADER_TILEMODE,
+} sk_shader_tilemode_t;
+
+/**
+ Returns a shader that generates a linear gradient between the two
+ specified points.
+
+ @param points The start and end points for the gradient.
+ @param colors The array[count] of colors, to be distributed between
+ the two points
+ @param colorPos May be NULL. array[count] of SkScalars, or NULL, of
+ the relative position of each corresponding color
+ in the colors array. If this is NULL, the the
+ colors are distributed evenly between the start
+ and end point. If this is not null, the values
+ must begin with 0, end with 1.0, and intermediate
+ values must be strictly increasing.
+ @param colorCount Must be >=2. The number of colors (and pos if not
+ NULL) entries.
+ @param mode The tiling mode
+*/
+SK_API sk_shader_t* sk_shader_new_linear_gradient(const sk_point_t points[2],
+ const sk_color_t colors[],
+ const float colorPos[],
+ int colorCount,
+ sk_shader_tilemode_t tileMode,
+ const sk_matrix_t* localMatrix);
+
+
+/**
+ Returns a shader that generates a radial gradient given the center
+ and radius.
+
+ @param center The center of the circle for this gradient
+ @param radius Must be positive. The radius of the circle for this
+ gradient
+ @param colors The array[count] of colors, to be distributed
+ between the center and edge of the circle
+ @param colorPos May be NULL. The array[count] of the relative
+ position of each corresponding color in the colors
+ array. If this is NULL, the the colors are
+ distributed evenly between the center and edge of
+ the circle. If this is not null, the values must
+ begin with 0, end with 1.0, and intermediate
+ values must be strictly increasing.
+ @param count Must be >= 2. The number of colors (and pos if not
+ NULL) entries
+ @param tileMode The tiling mode
+ @param localMatrix May be NULL
+*/
+SK_API sk_shader_t* sk_shader_new_radial_gradient(const sk_point_t* center,
+ float radius,
+ const sk_color_t colors[],
+ const float colorPos[],
+ int colorCount,
+ sk_shader_tilemode_t tileMode,
+ const sk_matrix_t* localMatrix);
+
+/**
+ Returns a shader that generates a sweep gradient given a center.
+
+ @param center The coordinates of the center of the sweep
+ @param colors The array[count] of colors, to be distributed around
+ the center.
+ @param colorPos May be NULL. The array[count] of the relative
+ position of each corresponding color in the colors
+ array. If this is NULL, the the colors are
+ distributed evenly between the center and edge of
+ the circle. If this is not null, the values must
+ begin with 0, end with 1.0, and intermediate
+ values must be strictly increasing.
+ @param colorCount Must be >= 2. The number of colors (and pos if
+ not NULL) entries
+ @param localMatrix May be NULL
+*/
+SK_API sk_shader_t* sk_shader_new_sweep_gradient(const sk_point_t* center,
+ const sk_color_t colors[],
+ const float colorPos[],
+ int colorCount,
+ const sk_matrix_t* localMatrix);
+
+/**
+ Returns a shader that generates a conical gradient given two circles, or
+ returns NULL if the inputs are invalid. The gradient interprets the
+ two circles according to the following HTML spec.
+ http://dev.w3.org/html5/2dcontext/#dom-context-2d-createradialgradient
+
+ Returns a shader that generates a sweep gradient given a center.
+
+ @param start, startRadius Defines the first circle.
+ @param end, endRadius Defines the first circle.
+ @param colors The array[count] of colors, to be distributed between
+ the two circles.
+ @param colorPos May be NULL. The array[count] of the relative
+ position of each corresponding color in the colors
+ array. If this is NULL, the the colors are
+ distributed evenly between the two circles. If
+ this is not null, the values must begin with 0,
+ end with 1.0, and intermediate values must be
+ strictly increasing.
+ @param colorCount Must be >= 2. The number of colors (and pos if
+ not NULL) entries
+ @param tileMode The tiling mode
+ @param localMatrix May be NULL
+
+*/
+SK_API sk_shader_t* sk_shader_new_two_point_conical_gradient(
+ const sk_point_t* start,
+ float startRadius,
+ const sk_point_t* end,
+ float endRadius,
+ const sk_color_t colors[],
+ const float colorPos[],
+ int colorCount,
+ sk_shader_tilemode_t tileMode,
+ const sk_matrix_t* localMatrix);
+
+SK_C_PLUS_PLUS_END_GUARD
+
+#endif
diff --git a/src/deps/skia/include/c/sk_surface.h b/src/deps/skia/include/c/sk_surface.h
new file mode 100644
index 000000000..88c8c87b3
--- /dev/null
+++ b/src/deps/skia/include/c/sk_surface.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+// EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL
+// DO NOT USE -- FOR INTERNAL TESTING ONLY
+
+#ifndef sk_surface_DEFINED
+#define sk_surface_DEFINED
+
+#include "include/c/sk_types.h"
+
+SK_C_PLUS_PLUS_BEGIN_GUARD
+
+/**
+ Return a new surface, with the memory for the pixels automatically
+ allocated. If the requested surface cannot be created, or the
+ request is not a supported configuration, NULL will be returned.
+
+ @param sk_imageinfo_t* Specify the width, height, color type, and
+ alpha type for the surface.
+
+ @param sk_surfaceprops_t* If not NULL, specify additional non-default
+ properties of the surface.
+*/
+SK_API sk_surface_t* sk_surface_new_raster(const sk_imageinfo_t*, const sk_surfaceprops_t*);
+
+/**
+ Create a new surface which will draw into the specified pixels
+ with the specified rowbytes. If the requested surface cannot be
+ created, or the request is not a supported configuration, NULL
+ will be returned.
+
+ @param sk_imageinfo_t* Specify the width, height, color type, and
+ alpha type for the surface.
+ @param void* pixels Specify the location in memory where the
+ destination pixels are. This memory must
+ outlast this surface.
+ @param size_t rowBytes Specify the difference, in bytes, between
+ each adjacent row. Should be at least
+ (width * sizeof(one pixel)).
+ @param sk_surfaceprops_t* If not NULL, specify additional non-default
+ properties of the surface.
+*/
+SK_API sk_surface_t* sk_surface_new_raster_direct(const sk_imageinfo_t*,
+ void* pixels, size_t rowBytes,
+ const sk_surfaceprops_t* props);
+
+/**
+ Decrement the reference count. If the reference count is 1 before
+ the decrement, then release both the memory holding the
+ sk_surface_t and any pixel memory it may be managing. New
+ sk_surface_t are created with a reference count of 1.
+*/
+SK_API void sk_surface_unref(sk_surface_t*);
+
+/**
+ * Return the canvas associated with this surface. Note: the canvas is owned by the surface,
+ * so the returned object is only valid while the owning surface is valid.
+ */
+SK_API sk_canvas_t* sk_surface_get_canvas(sk_surface_t*);
+
+/**
+ * Call sk_image_unref() when the returned image is no longer used.
+ */
+SK_API sk_image_t* sk_surface_new_image_snapshot(sk_surface_t*);
+
+SK_C_PLUS_PLUS_END_GUARD
+
+#endif
diff --git a/src/deps/skia/include/c/sk_types.h b/src/deps/skia/include/c/sk_types.h
new file mode 100644
index 000000000..5a484af42
--- /dev/null
+++ b/src/deps/skia/include/c/sk_types.h
@@ -0,0 +1,278 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+// EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL
+// DO NOT USE -- FOR INTERNAL TESTING ONLY
+
+#ifndef sk_types_DEFINED
+#define sk_types_DEFINED
+
+#include <stdint.h>
+#include <stddef.h>
+
+#ifdef __cplusplus
+ #define SK_C_PLUS_PLUS_BEGIN_GUARD extern "C" {
+ #define SK_C_PLUS_PLUS_END_GUARD }
+#else
+ #include <stdbool.h>
+ #define SK_C_PLUS_PLUS_BEGIN_GUARD
+ #define SK_C_PLUS_PLUS_END_GUARD
+#endif
+
+#if !defined(SK_API)
+ #if defined(SKIA_DLL)
+ #if defined(_MSC_VER)
+ #if SKIA_IMPLEMENTATION
+ #define SK_API __declspec(dllexport)
+ #else
+ #define SK_API __declspec(dllimport)
+ #endif
+ #else
+ #define SK_API __attribute__((visibility("default")))
+ #endif
+ #else
+ #define SK_API
+ #endif
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////
+
+SK_C_PLUS_PLUS_BEGIN_GUARD
+
+typedef uint32_t sk_color_t;
+
+/* This macro assumes all arguments are >=0 and <=255. */
+#define sk_color_set_argb(a, r, g, b) (((a) << 24) | ((r) << 16) | ((g) << 8) | (b))
+#define sk_color_get_a(c) (((c) >> 24) & 0xFF)
+#define sk_color_get_r(c) (((c) >> 16) & 0xFF)
+#define sk_color_get_g(c) (((c) >> 8) & 0xFF)
+#define sk_color_get_b(c) (((c) >> 0) & 0xFF)
+
+typedef enum {
+ INTERSECT_SK_CLIPTYPE,
+ DIFFERENCE_SK_CLIPTYPE,
+} sk_cliptype_t;
+
+typedef enum {
+ UNKNOWN_SK_PIXELGEOMETRY,
+ RGB_H_SK_PIXELGEOMETRY,
+ BGR_H_SK_PIXELGEOMETRY,
+ RGB_V_SK_PIXELGEOMETRY,
+ BGR_V_SK_PIXELGEOMETRY,
+} sk_pixelgeometry_t;
+
+typedef struct {
+ sk_pixelgeometry_t pixelGeometry;
+} sk_surfaceprops_t;
+
+typedef struct {
+ float x;
+ float y;
+} sk_point_t;
+
+typedef struct {
+ int32_t left;
+ int32_t top;
+ int32_t right;
+ int32_t bottom;
+} sk_irect_t;
+
+typedef struct {
+ float left;
+ float top;
+ float right;
+ float bottom;
+} sk_rect_t;
+
+/**
+ The sk_matrix_t struct holds a 3x3 perspective matrix for
+ transforming coordinates:
+
+ (X,Y) = T[M]((x,y))
+ X = (M[0] * x + M[1] * y + M[2]) / (M[6] * x + M[7] * y + M[8]);
+ Y = (M[3] * x + M[4] * y + M[5]) / (M[6] * x + M[7] * y + M[8]);
+
+ Therefore, the identity matrix is
+
+ sk_matrix_t identity = {{1, 0, 0,
+ 0, 1, 0,
+ 0, 0, 1}};
+
+ A matrix that scales by sx and sy is:
+
+ sk_matrix_t scale = {{sx, 0, 0,
+ 0, sy, 0,
+ 0, 0, 1}};
+
+ A matrix that translates by tx and ty is:
+
+ sk_matrix_t translate = {{1, 0, tx,
+ 0, 1, ty,
+ 0, 0, 1}};
+
+ A matrix that rotates around the origin by A radians:
+
+ sk_matrix_t rotate = {{cos(A), -sin(A), 0,
+ sin(A), cos(A), 0,
+ 0, 0, 1}};
+
+ Two matrixes can be concatinated by:
+
+ void concat_matrices(sk_matrix_t* dst,
+ const sk_matrix_t* matrixU,
+ const sk_matrix_t* matrixV) {
+ const float* u = matrixU->mat;
+ const float* v = matrixV->mat;
+ sk_matrix_t result = {{
+ u[0] * v[0] + u[1] * v[3] + u[2] * v[6],
+ u[0] * v[1] + u[1] * v[4] + u[2] * v[7],
+ u[0] * v[2] + u[1] * v[5] + u[2] * v[8],
+ u[3] * v[0] + u[4] * v[3] + u[5] * v[6],
+ u[3] * v[1] + u[4] * v[4] + u[5] * v[7],
+ u[3] * v[2] + u[4] * v[5] + u[5] * v[8],
+ u[6] * v[0] + u[7] * v[3] + u[8] * v[6],
+ u[6] * v[1] + u[7] * v[4] + u[8] * v[7],
+ u[6] * v[2] + u[7] * v[5] + u[8] * v[8]
+ }};
+ *dst = result;
+ }
+*/
+typedef struct {
+ float mat[9];
+} sk_matrix_t;
+
+/**
+ A sk_canvas_t encapsulates all of the state about drawing into a
+ destination This includes a reference to the destination itself,
+ and a stack of matrix/clip values.
+*/
+typedef struct sk_canvas_t sk_canvas_t;
+/**
+ A sk_data_ holds an immutable data buffer.
+*/
+typedef struct sk_data_t sk_data_t;
+/**
+ A sk_image_t is an abstraction for drawing a rectagle of pixels.
+ The content of the image is always immutable, though the actual
+ storage may change, if for example that image can be re-created via
+ encoded data or other means.
+*/
+typedef struct sk_image_t sk_image_t;
+
+/**
+ * Describes the color components. See ICC Profiles.
+ */
+typedef struct sk_colorspace_t sk_colorspace_t;
+
+/**
+ * Describes an image buffer : width, height, pixel type, colorspace, etc.
+ */
+typedef struct sk_imageinfo_t sk_imageinfo_t;
+
+/**
+ A sk_maskfilter_t is an object that perform transformations on an
+ alpha-channel mask before drawing it; it may be installed into a
+ sk_paint_t. Each time a primitive is drawn, it is first
+ scan-converted into a alpha mask, which os handed to the
+ maskfilter, which may create a new mask is to render into the
+ destination.
+ */
+typedef struct sk_maskfilter_t sk_maskfilter_t;
+/**
+ A sk_paint_t holds the style and color information about how to
+ draw geometries, text and bitmaps.
+*/
+typedef struct sk_paint_t sk_paint_t;
+/**
+ A sk_path_t encapsulates compound (multiple contour) geometric
+ paths consisting of straight line segments, quadratic curves, and
+ cubic curves.
+*/
+typedef struct sk_path_t sk_path_t;
+/**
+ A sk_picture_t holds recorded canvas drawing commands to be played
+ back at a later time.
+*/
+typedef struct sk_picture_t sk_picture_t;
+/**
+ A sk_picture_recorder_t holds a sk_canvas_t that records commands
+ to create a sk_picture_t.
+*/
+typedef struct sk_picture_recorder_t sk_picture_recorder_t;
+/**
+ A sk_shader_t specifies the source color(s) for what is being drawn. If a
+ paint has no shader, then the paint's color is used. If the paint
+ has a shader, then the shader's color(s) are use instead, but they
+ are modulated by the paint's alpha.
+*/
+typedef struct sk_shader_t sk_shader_t;
+/**
+ A sk_surface_t holds the destination for drawing to a canvas. For
+ raster drawing, the destination is an array of pixels in memory.
+ For GPU drawing, the destination is a texture or a framebuffer.
+*/
+typedef struct sk_surface_t sk_surface_t;
+
+typedef enum {
+ NEAREST_SK_FILTER_MODE,
+ LINEAR_SK_FILTER_MODE,
+} sk_filter_mode_t;
+
+typedef enum {
+ NONE_SK_MIPMAP_MODE,
+ NEAREST_SK_MIPMAP_MODE,
+ LINEAR_SK_MIPMAP_MODE,
+} sk_mipmap_mode_t;
+
+typedef struct {
+ float B, C;
+} sk_cubic_resampler_t;
+
+typedef struct {
+ bool useCubic;
+ sk_cubic_resampler_t cubic;
+ sk_filter_mode_t filter;
+ sk_mipmap_mode_t mipmap;
+} sk_sampling_options_t;
+
+typedef enum {
+ CLEAR_SK_XFERMODE_MODE,
+ SRC_SK_XFERMODE_MODE,
+ DST_SK_XFERMODE_MODE,
+ SRCOVER_SK_XFERMODE_MODE,
+ DSTOVER_SK_XFERMODE_MODE,
+ SRCIN_SK_XFERMODE_MODE,
+ DSTIN_SK_XFERMODE_MODE,
+ SRCOUT_SK_XFERMODE_MODE,
+ DSTOUT_SK_XFERMODE_MODE,
+ SRCATOP_SK_XFERMODE_MODE,
+ DSTATOP_SK_XFERMODE_MODE,
+ XOR_SK_XFERMODE_MODE,
+ PLUS_SK_XFERMODE_MODE,
+ MODULATE_SK_XFERMODE_MODE,
+ SCREEN_SK_XFERMODE_MODE,
+ OVERLAY_SK_XFERMODE_MODE,
+ DARKEN_SK_XFERMODE_MODE,
+ LIGHTEN_SK_XFERMODE_MODE,
+ COLORDODGE_SK_XFERMODE_MODE,
+ COLORBURN_SK_XFERMODE_MODE,
+ HARDLIGHT_SK_XFERMODE_MODE,
+ SOFTLIGHT_SK_XFERMODE_MODE,
+ DIFFERENCE_SK_XFERMODE_MODE,
+ EXCLUSION_SK_XFERMODE_MODE,
+ MULTIPLY_SK_XFERMODE_MODE,
+ HUE_SK_XFERMODE_MODE,
+ SATURATION_SK_XFERMODE_MODE,
+ COLOR_SK_XFERMODE_MODE,
+ LUMINOSITY_SK_XFERMODE_MODE,
+} sk_xfermode_mode_t;
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+SK_C_PLUS_PLUS_END_GUARD
+
+#endif
diff --git a/src/deps/skia/include/codec/BUILD.bazel b/src/deps/skia/include/codec/BUILD.bazel
new file mode 100644
index 000000000..27db9c460
--- /dev/null
+++ b/src/deps/skia/include/codec/BUILD.bazel
@@ -0,0 +1,47 @@
+load("//bazel:macros.bzl", "generated_cc_atom")
+
+generated_cc_atom(
+ name = "SkAndroidCodec_hdr",
+ hdrs = ["SkAndroidCodec.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [
+ ":SkCodec_hdr",
+ "//include/core:SkEncodedImageFormat_hdr",
+ "//include/core:SkStream_hdr",
+ "//include/core:SkTypes_hdr",
+ ],
+)
+
+generated_cc_atom(
+ name = "SkCodecAnimation_hdr",
+ hdrs = ["SkCodecAnimation.h"],
+ visibility = ["//:__subpackages__"],
+)
+
+generated_cc_atom(
+ name = "SkCodec_hdr",
+ hdrs = ["SkCodec.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [
+ ":SkCodecAnimation_hdr",
+ ":SkEncodedOrigin_hdr",
+ "//include/core:SkColor_hdr",
+ "//include/core:SkEncodedImageFormat_hdr",
+ "//include/core:SkImageInfo_hdr",
+ "//include/core:SkPixmap_hdr",
+ "//include/core:SkSize_hdr",
+ "//include/core:SkStream_hdr",
+ "//include/core:SkTypes_hdr",
+ "//include/core:SkYUVAPixmaps_hdr",
+ "//include/private:SkEncodedInfo_hdr",
+ "//include/private:SkNoncopyable_hdr",
+ "//include/private:SkTemplates_hdr",
+ ],
+)
+
+generated_cc_atom(
+ name = "SkEncodedOrigin_hdr",
+ hdrs = ["SkEncodedOrigin.h"],
+ visibility = ["//:__subpackages__"],
+ deps = ["//include/core:SkMatrix_hdr"],
+)
diff --git a/src/deps/skia/include/codec/SkAndroidCodec.h b/src/deps/skia/include/codec/SkAndroidCodec.h
new file mode 100644
index 000000000..11157429f
--- /dev/null
+++ b/src/deps/skia/include/codec/SkAndroidCodec.h
@@ -0,0 +1,263 @@
+/*
+ * Copyright 2015 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkAndroidCodec_DEFINED
+#define SkAndroidCodec_DEFINED
+
+#include "include/codec/SkCodec.h"
+#include "include/core/SkEncodedImageFormat.h"
+#include "include/core/SkStream.h"
+#include "include/core/SkTypes.h"
+
+/**
+ * Abstract interface defining image codec functionality that is necessary for
+ * Android.
+ */
+class SK_API SkAndroidCodec : SkNoncopyable {
+public:
+ /**
+ * Deprecated.
+ *
+ * Now that SkAndroidCodec supports multiframe images, there are multiple
+ * ways to handle compositing an oriented frame on top of an oriented frame
+ * with different tradeoffs. SkAndroidCodec now ignores the orientation and
+ * forces the client to handle it.
+ */
+ enum class ExifOrientationBehavior {
+ kIgnore,
+ kRespect,
+ };
+
+ /**
+ * Pass ownership of an SkCodec to a newly-created SkAndroidCodec.
+ */
+ static std::unique_ptr<SkAndroidCodec> MakeFromCodec(std::unique_ptr<SkCodec>);
+
+ /**
+ * If this stream represents an encoded image that we know how to decode,
+ * return an SkAndroidCodec that can decode it. Otherwise return NULL.
+ *
+ * The SkPngChunkReader handles unknown chunks in PNGs.
+ * See SkCodec.h for more details.
+ *
+ * If NULL is returned, the stream is deleted immediately. Otherwise, the
+ * SkCodec takes ownership of it, and will delete it when done with it.
+ */
+ static std::unique_ptr<SkAndroidCodec> MakeFromStream(std::unique_ptr<SkStream>,
+ SkPngChunkReader* = nullptr);
+
+ /**
+ * If this data represents an encoded image that we know how to decode,
+ * return an SkAndroidCodec that can decode it. Otherwise return NULL.
+ *
+ * The SkPngChunkReader handles unknown chunks in PNGs.
+ * See SkCodec.h for more details.
+ */
+ static std::unique_ptr<SkAndroidCodec> MakeFromData(sk_sp<SkData>, SkPngChunkReader* = nullptr);
+
+ virtual ~SkAndroidCodec();
+
+ // TODO: fInfo is now just a cache of SkCodec's SkImageInfo. No need to
+ // cache and return a reference here, once Android call-sites are updated.
+ const SkImageInfo& getInfo() const { return fInfo; }
+
+ /**
+ * Return the ICC profile of the encoded data.
+ */
+ const skcms_ICCProfile* getICCProfile() const {
+ return fCodec->getEncodedInfo().profile();
+ }
+
+ /**
+ * Format of the encoded data.
+ */
+ SkEncodedImageFormat getEncodedFormat() const { return fCodec->getEncodedFormat(); }
+
+ /**
+ * @param requestedColorType Color type requested by the client
+ *
+ * |requestedColorType| may be overriden. We will default to kF16
+ * for high precision images.
+ *
+ * In the general case, if it is possible to decode to
+ * |requestedColorType|, this returns |requestedColorType|.
+ * Otherwise, this returns a color type that is an appropriate
+ * match for the the encoded data.
+ */
+ SkColorType computeOutputColorType(SkColorType requestedColorType);
+
+ /**
+ * @param requestedUnpremul Indicates if the client requested
+ * unpremultiplied output
+ *
+ * Returns the appropriate alpha type to decode to. If the image
+ * has alpha, the value of requestedUnpremul will be honored.
+ */
+ SkAlphaType computeOutputAlphaType(bool requestedUnpremul);
+
+ /**
+ * @param outputColorType Color type that the client will decode to.
+ * @param prefColorSpace Preferred color space to decode to.
+ * This may not return |prefColorSpace| for a couple reasons.
+ * (1) Android Principles: 565 must be sRGB, F16 must be
+ * linear sRGB, transfer function must be parametric.
+ * (2) Codec Limitations: F16 requires a linear color space.
+ *
+ * Returns the appropriate color space to decode to.
+ */
+ sk_sp<SkColorSpace> computeOutputColorSpace(SkColorType outputColorType,
+ sk_sp<SkColorSpace> prefColorSpace = nullptr);
+
+ /**
+ * Compute the appropriate sample size to get to |size|.
+ *
+ * @param size As an input parameter, the desired output size of
+ * the decode. As an output parameter, the smallest sampled size
+ * larger than the input.
+ * @return the sample size to set AndroidOptions::fSampleSize to decode
+ * to the output |size|.
+ */
+ int computeSampleSize(SkISize* size) const;
+
+ /**
+ * Returns the dimensions of the scaled output image, for an input
+ * sampleSize.
+ *
+ * When the sample size divides evenly into the original dimensions, the
+ * scaled output dimensions will simply be equal to the original
+ * dimensions divided by the sample size.
+ *
+ * When the sample size does not divide even into the original
+ * dimensions, the codec may round up or down, depending on what is most
+ * efficient to decode.
+ *
+ * Finally, the codec will always recommend a non-zero output, so the output
+ * dimension will always be one if the sampleSize is greater than the
+ * original dimension.
+ */
+ SkISize getSampledDimensions(int sampleSize) const;
+
+ /**
+ * Return (via desiredSubset) a subset which can decoded from this codec,
+ * or false if the input subset is invalid.
+ *
+ * @param desiredSubset in/out parameter
+ * As input, a desired subset of the original bounds
+ * (as specified by getInfo).
+ * As output, if true is returned, desiredSubset may
+ * have been modified to a subset which is
+ * supported. Although a particular change may have
+ * been made to desiredSubset to create something
+ * supported, it is possible other changes could
+ * result in a valid subset. If false is returned,
+ * desiredSubset's value is undefined.
+ * @return true If the input desiredSubset is valid.
+ * desiredSubset may be modified to a subset
+ * supported by the codec.
+ * false If desiredSubset is invalid (NULL or not fully
+ * contained within the image).
+ */
+ bool getSupportedSubset(SkIRect* desiredSubset) const;
+ // TODO: Rename SkCodec::getValidSubset() to getSupportedSubset()
+
+ /**
+ * Returns the dimensions of the scaled, partial output image, for an
+ * input sampleSize and subset.
+ *
+ * @param sampleSize Factor to scale down by.
+ * @param subset Must be a valid subset of the original image
+ * dimensions and a subset supported by SkAndroidCodec.
+ * getSubset() can be used to obtain a subset supported
+ * by SkAndroidCodec.
+ * @return Size of the scaled partial image. Or zero size
+ * if either of the inputs is invalid.
+ */
+ SkISize getSampledSubsetDimensions(int sampleSize, const SkIRect& subset) const;
+
+ /**
+ * Additional options to pass to getAndroidPixels().
+ */
+ // FIXME: It's a bit redundant to name these AndroidOptions when this class is already
+ // called SkAndroidCodec. On the other hand, it's may be a bit confusing to call
+ // these Options when SkCodec has a slightly different set of Options. Maybe these
+ // should be DecodeOptions or SamplingOptions?
+ struct AndroidOptions : public SkCodec::Options {
+ AndroidOptions()
+ : SkCodec::Options()
+ , fSampleSize(1)
+ {}
+
+ /**
+ * The client may provide an integer downscale factor for the decode.
+ * The codec may implement this downscaling by sampling or another
+ * method if it is more efficient.
+ *
+ * The default is 1, representing no downscaling.
+ */
+ int fSampleSize;
+ };
+
+ /**
+ * Decode into the given pixels, a block of memory of size at
+ * least (info.fHeight - 1) * rowBytes + (info.fWidth *
+ * bytesPerPixel)
+ *
+ * Repeated calls to this function should give the same results,
+ * allowing the PixelRef to be immutable.
+ *
+ * @param info A description of the format (config, size)
+ * expected by the caller. This can simply be identical
+ * to the info returned by getInfo().
+ *
+ * This contract also allows the caller to specify
+ * different output-configs, which the implementation can
+ * decide to support or not.
+ *
+ * A size that does not match getInfo() implies a request
+ * to scale or subset. If the codec cannot perform this
+ * scaling or subsetting, it will return an error code.
+ *
+ * The AndroidOptions object is also used to specify any requested scaling or subsetting
+ * using options->fSampleSize and options->fSubset. If NULL, the defaults (as specified above
+ * for AndroidOptions) are used.
+ *
+ * @return Result kSuccess, or another value explaining the type of failure.
+ */
+ // FIXME: It's a bit redundant to name this getAndroidPixels() when this class is already
+ // called SkAndroidCodec. On the other hand, it's may be a bit confusing to call
+ // this getPixels() when it is a slightly different API than SkCodec's getPixels().
+ // Maybe this should be decode() or decodeSubset()?
+ SkCodec::Result getAndroidPixels(const SkImageInfo& info, void* pixels, size_t rowBytes,
+ const AndroidOptions* options);
+
+ /**
+ * Simplified version of getAndroidPixels() where we supply the default AndroidOptions as
+ * specified above for AndroidOptions. It will not perform any scaling or subsetting.
+ */
+ SkCodec::Result getAndroidPixels(const SkImageInfo& info, void* pixels, size_t rowBytes);
+
+ SkCodec::Result getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes) {
+ return this->getAndroidPixels(info, pixels, rowBytes);
+ }
+
+ SkCodec* codec() const { return fCodec.get(); }
+
+protected:
+ SkAndroidCodec(SkCodec*);
+
+ virtual SkISize onGetSampledDimensions(int sampleSize) const = 0;
+
+ virtual bool onGetSupportedSubset(SkIRect* desiredSubset) const = 0;
+
+ virtual SkCodec::Result onGetAndroidPixels(const SkImageInfo& info, void* pixels,
+ size_t rowBytes, const AndroidOptions& options) = 0;
+
+private:
+ const SkImageInfo fInfo;
+ std::unique_ptr<SkCodec> fCodec;
+};
+#endif // SkAndroidCodec_DEFINED
diff --git a/src/deps/skia/include/codec/SkCodec.h b/src/deps/skia/include/codec/SkCodec.h
new file mode 100644
index 000000000..e7c7c0eaa
--- /dev/null
+++ b/src/deps/skia/include/codec/SkCodec.h
@@ -0,0 +1,992 @@
+/*
+ * Copyright 2015 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkCodec_DEFINED
+#define SkCodec_DEFINED
+
+#include "include/codec/SkCodecAnimation.h"
+#include "include/codec/SkEncodedOrigin.h"
+#include "include/core/SkColor.h"
+#include "include/core/SkEncodedImageFormat.h"
+#include "include/core/SkImageInfo.h"
+#include "include/core/SkPixmap.h"
+#include "include/core/SkSize.h"
+#include "include/core/SkStream.h"
+#include "include/core/SkTypes.h"
+#include "include/core/SkYUVAPixmaps.h"
+#include "include/private/SkEncodedInfo.h"
+#include "include/private/SkNoncopyable.h"
+#include "include/private/SkTemplates.h"
+
+#include <vector>
+
+class SkAndroidCodec;
+class SkColorSpace;
+class SkData;
+class SkFrameHolder;
+class SkImage;
+class SkPngChunkReader;
+class SkSampler;
+
+namespace DM {
+class CodecSrc;
+class ColorCodecSrc;
+} // namespace DM
+
+/**
+ * Abstraction layer directly on top of an image codec.
+ */
+class SK_API SkCodec : SkNoncopyable {
+public:
+ /**
+ * Minimum number of bytes that must be buffered in SkStream input.
+ *
+ * An SkStream passed to NewFromStream must be able to use this many
+ * bytes to determine the image type. Then the same SkStream must be
+ * passed to the correct decoder to read from the beginning.
+ *
+ * This can be accomplished by implementing peek() to support peeking
+ * this many bytes, or by implementing rewind() to be able to rewind()
+ * after reading this many bytes.
+ */
+ static constexpr size_t MinBufferedBytesNeeded() { return 32; }
+
+ /**
+ * Error codes for various SkCodec methods.
+ */
+ enum Result {
+ /**
+ * General return value for success.
+ */
+ kSuccess,
+ /**
+ * The input is incomplete. A partial image was generated.
+ */
+ kIncompleteInput,
+ /**
+ * Like kIncompleteInput, except the input had an error.
+ *
+ * If returned from an incremental decode, decoding cannot continue,
+ * even with more data.
+ */
+ kErrorInInput,
+ /**
+ * The generator cannot convert to match the request, ignoring
+ * dimensions.
+ */
+ kInvalidConversion,
+ /**
+ * The generator cannot scale to requested size.
+ */
+ kInvalidScale,
+ /**
+ * Parameters (besides info) are invalid. e.g. NULL pixels, rowBytes
+ * too small, etc.
+ */
+ kInvalidParameters,
+ /**
+ * The input did not contain a valid image.
+ */
+ kInvalidInput,
+ /**
+ * Fulfilling this request requires rewinding the input, which is not
+ * supported for this input.
+ */
+ kCouldNotRewind,
+ /**
+ * An internal error, such as OOM.
+ */
+ kInternalError,
+ /**
+ * This method is not implemented by this codec.
+ * FIXME: Perhaps this should be kUnsupported?
+ */
+ kUnimplemented,
+ };
+
+ /**
+ * Readable string representing the error code.
+ */
+ static const char* ResultToString(Result);
+
+ /**
+ * For container formats that contain both still images and image sequences,
+ * instruct the decoder how the output should be selected. (Refer to comments
+ * for each value for more details.)
+ */
+ enum class SelectionPolicy {
+ /**
+ * If the container format contains both still images and image sequences,
+ * SkCodec should choose one of the still images. This is the default.
+ */
+ kPreferStillImage,
+ /**
+ * If the container format contains both still images and image sequences,
+ * SkCodec should choose one of the image sequences for animation.
+ */
+ kPreferAnimation,
+ };
+
+ /**
+ * If this stream represents an encoded image that we know how to decode,
+ * return an SkCodec that can decode it. Otherwise return NULL.
+ *
+ * As stated above, this call must be able to peek or read
+ * MinBufferedBytesNeeded to determine the correct format, and then start
+ * reading from the beginning. First it will attempt to peek, and it
+ * assumes that if less than MinBufferedBytesNeeded bytes (but more than
+ * zero) are returned, this is because the stream is shorter than this,
+ * so falling back to reading would not provide more data. If peek()
+ * returns zero bytes, this call will instead attempt to read(). This
+ * will require that the stream can be rewind()ed.
+ *
+ * If Result is not NULL, it will be set to either kSuccess if an SkCodec
+ * is returned or a reason for the failure if NULL is returned.
+ *
+ * If SkPngChunkReader is not NULL, take a ref and pass it to libpng if
+ * the image is a png.
+ *
+ * If the SkPngChunkReader is not NULL then:
+ * If the image is not a PNG, the SkPngChunkReader will be ignored.
+ * If the image is a PNG, the SkPngChunkReader will be reffed.
+ * If the PNG has unknown chunks, the SkPngChunkReader will be used
+ * to handle these chunks. SkPngChunkReader will be called to read
+ * any unknown chunk at any point during the creation of the codec
+ * or the decode. Note that if SkPngChunkReader fails to read a
+ * chunk, this could result in a failure to create the codec or a
+ * failure to decode the image.
+ * If the PNG does not contain unknown chunks, the SkPngChunkReader
+ * will not be used or modified.
+ *
+ * If NULL is returned, the stream is deleted immediately. Otherwise, the
+ * SkCodec takes ownership of it, and will delete it when done with it.
+ */
+ static std::unique_ptr<SkCodec> MakeFromStream(
+ std::unique_ptr<SkStream>, Result* = nullptr,
+ SkPngChunkReader* = nullptr,
+ SelectionPolicy selectionPolicy = SelectionPolicy::kPreferStillImage);
+
+ /**
+ * If this data represents an encoded image that we know how to decode,
+ * return an SkCodec that can decode it. Otherwise return NULL.
+ *
+ * If the SkPngChunkReader is not NULL then:
+ * If the image is not a PNG, the SkPngChunkReader will be ignored.
+ * If the image is a PNG, the SkPngChunkReader will be reffed.
+ * If the PNG has unknown chunks, the SkPngChunkReader will be used
+ * to handle these chunks. SkPngChunkReader will be called to read
+ * any unknown chunk at any point during the creation of the codec
+ * or the decode. Note that if SkPngChunkReader fails to read a
+ * chunk, this could result in a failure to create the codec or a
+ * failure to decode the image.
+ * If the PNG does not contain unknown chunks, the SkPngChunkReader
+ * will not be used or modified.
+ */
+ static std::unique_ptr<SkCodec> MakeFromData(sk_sp<SkData>, SkPngChunkReader* = nullptr);
+
+ virtual ~SkCodec();
+
+ /**
+ * Return a reasonable SkImageInfo to decode into.
+ *
+ * If the image has an ICC profile that does not map to an SkColorSpace,
+ * the returned SkImageInfo will use SRGB.
+ */
+ SkImageInfo getInfo() const { return fEncodedInfo.makeImageInfo(); }
+
+ SkISize dimensions() const { return {fEncodedInfo.width(), fEncodedInfo.height()}; }
+ SkIRect bounds() const {
+ return SkIRect::MakeWH(fEncodedInfo.width(), fEncodedInfo.height());
+ }
+
+ /**
+ * Return the ICC profile of the encoded data.
+ */
+ const skcms_ICCProfile* getICCProfile() const {
+ return this->getEncodedInfo().profile();
+ }
+
+ /**
+ * Returns the image orientation stored in the EXIF data.
+ * If there is no EXIF data, or if we cannot read the EXIF data, returns kTopLeft.
+ */
+ SkEncodedOrigin getOrigin() const { return fOrigin; }
+
+ /**
+ * Return a size that approximately supports the desired scale factor.
+ * The codec may not be able to scale efficiently to the exact scale
+ * factor requested, so return a size that approximates that scale.
+ * The returned value is the codec's suggestion for the closest valid
+ * scale that it can natively support
+ */
+ SkISize getScaledDimensions(float desiredScale) const {
+ // Negative and zero scales are errors.
+ SkASSERT(desiredScale > 0.0f);
+ if (desiredScale <= 0.0f) {
+ return SkISize::Make(0, 0);
+ }
+
+ // Upscaling is not supported. Return the original size if the client
+ // requests an upscale.
+ if (desiredScale >= 1.0f) {
+ return this->dimensions();
+ }
+ return this->onGetScaledDimensions(desiredScale);
+ }
+
+ /**
+ * Return (via desiredSubset) a subset which can decoded from this codec,
+ * or false if this codec cannot decode subsets or anything similar to
+ * desiredSubset.
+ *
+ * @param desiredSubset In/out parameter. As input, a desired subset of
+ * the original bounds (as specified by getInfo). If true is returned,
+ * desiredSubset may have been modified to a subset which is
+ * supported. Although a particular change may have been made to
+ * desiredSubset to create something supported, it is possible other
+ * changes could result in a valid subset.
+ * If false is returned, desiredSubset's value is undefined.
+ * @return true if this codec supports decoding desiredSubset (as
+ * returned, potentially modified)
+ */
+ bool getValidSubset(SkIRect* desiredSubset) const {
+ return this->onGetValidSubset(desiredSubset);
+ }
+
+ /**
+ * Format of the encoded data.
+ */
+ SkEncodedImageFormat getEncodedFormat() const { return this->onGetEncodedFormat(); }
+
+ /**
+ * Whether or not the memory passed to getPixels is zero initialized.
+ */
+ enum ZeroInitialized {
+ /**
+ * The memory passed to getPixels is zero initialized. The SkCodec
+ * may take advantage of this by skipping writing zeroes.
+ */
+ kYes_ZeroInitialized,
+ /**
+ * The memory passed to getPixels has not been initialized to zero,
+ * so the SkCodec must write all zeroes to memory.
+ *
+ * This is the default. It will be used if no Options struct is used.
+ */
+ kNo_ZeroInitialized,
+ };
+
+ /**
+ * Additional options to pass to getPixels.
+ */
+ struct Options {
+ Options()
+ : fZeroInitialized(kNo_ZeroInitialized)
+ , fSubset(nullptr)
+ , fFrameIndex(0)
+ , fPriorFrame(kNoFrame)
+ {}
+
+ ZeroInitialized fZeroInitialized;
+ /**
+ * If not NULL, represents a subset of the original image to decode.
+ * Must be within the bounds returned by getInfo().
+ * If the EncodedFormat is SkEncodedImageFormat::kWEBP (the only one which
+ * currently supports subsets), the top and left values must be even.
+ *
+ * In getPixels and incremental decode, we will attempt to decode the
+ * exact rectangular subset specified by fSubset.
+ *
+ * In a scanline decode, it does not make sense to specify a subset
+ * top or subset height, since the client already controls which rows
+ * to get and which rows to skip. During scanline decodes, we will
+ * require that the subset top be zero and the subset height be equal
+ * to the full height. We will, however, use the values of
+ * subset left and subset width to decode partial scanlines on calls
+ * to getScanlines().
+ */
+ const SkIRect* fSubset;
+
+ /**
+ * The frame to decode.
+ *
+ * Only meaningful for multi-frame images.
+ */
+ int fFrameIndex;
+
+ /**
+ * If not kNoFrame, the dst already contains the prior frame at this index.
+ *
+ * Only meaningful for multi-frame images.
+ *
+ * If fFrameIndex needs to be blended with a prior frame (as reported by
+ * getFrameInfo[fFrameIndex].fRequiredFrame), the client can set this to
+ * any non-kRestorePrevious frame in [fRequiredFrame, fFrameIndex) to
+ * indicate that that frame is already in the dst. Options.fZeroInitialized
+ * is ignored in this case.
+ *
+ * If set to kNoFrame, the codec will decode any necessary required frame(s) first.
+ */
+ int fPriorFrame;
+ };
+
+ /**
+ * Decode into the given pixels, a block of memory of size at
+ * least (info.fHeight - 1) * rowBytes + (info.fWidth *
+ * bytesPerPixel)
+ *
+ * Repeated calls to this function should give the same results,
+ * allowing the PixelRef to be immutable.
+ *
+ * @param info A description of the format (config, size)
+ * expected by the caller. This can simply be identical
+ * to the info returned by getInfo().
+ *
+ * This contract also allows the caller to specify
+ * different output-configs, which the implementation can
+ * decide to support or not.
+ *
+ * A size that does not match getInfo() implies a request
+ * to scale. If the generator cannot perform this scale,
+ * it will return kInvalidScale.
+ *
+ * If the info contains a non-null SkColorSpace, the codec
+ * will perform the appropriate color space transformation.
+ *
+ * If the caller passes in the SkColorSpace that maps to the
+ * ICC profile reported by getICCProfile(), the color space
+ * transformation is a no-op.
+ *
+ * If the caller passes a null SkColorSpace, no color space
+ * transformation will be done.
+ *
+ * If a scanline decode is in progress, scanline mode will end, requiring the client to call
+ * startScanlineDecode() in order to return to decoding scanlines.
+ *
+ * @return Result kSuccess, or another value explaining the type of failure.
+ */
+ Result getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, const Options*);
+
+ /**
+ * Simplified version of getPixels() that uses the default Options.
+ */
+ Result getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes) {
+ return this->getPixels(info, pixels, rowBytes, nullptr);
+ }
+
+ Result getPixels(const SkPixmap& pm, const Options* opts = nullptr) {
+ return this->getPixels(pm.info(), pm.writable_addr(), pm.rowBytes(), opts);
+ }
+
+ /**
+ * Return an image containing the pixels.
+ */
+ std::tuple<sk_sp<SkImage>, SkCodec::Result> getImage(const SkImageInfo& info,
+ const Options* opts = nullptr);
+ std::tuple<sk_sp<SkImage>, SkCodec::Result> getImage();
+
+ /**
+ * If decoding to YUV is supported, this returns true. Otherwise, this
+ * returns false and the caller will ignore output parameter yuvaPixmapInfo.
+ *
+ * @param supportedDataTypes Indicates the data type/planar config combinations that are
+ * supported by the caller. If the generator supports decoding to
+ * YUV(A), but not as a type in supportedDataTypes, this method
+ * returns false.
+ * @param yuvaPixmapInfo Output parameter that specifies the planar configuration, subsampling,
+ * orientation, chroma siting, plane color types, and row bytes.
+ */
+ bool queryYUVAInfo(const SkYUVAPixmapInfo::SupportedDataTypes& supportedDataTypes,
+ SkYUVAPixmapInfo* yuvaPixmapInfo) const;
+
+ /**
+ * Returns kSuccess, or another value explaining the type of failure.
+ * This always attempts to perform a full decode. To get the planar
+ * configuration without decoding use queryYUVAInfo().
+ *
+ * @param yuvaPixmaps Contains preallocated pixmaps configured according to a successful call
+ * to queryYUVAInfo().
+ */
+ Result getYUVAPlanes(const SkYUVAPixmaps& yuvaPixmaps);
+
+ /**
+ * Prepare for an incremental decode with the specified options.
+ *
+ * This may require a rewind.
+ *
+ * If kIncompleteInput is returned, may be called again after more data has
+ * been provided to the source SkStream.
+ *
+ * @param dstInfo Info of the destination. If the dimensions do not match
+ * those of getInfo, this implies a scale.
+ * @param dst Memory to write to. Needs to be large enough to hold the subset,
+ * if present, or the full image as described in dstInfo.
+ * @param options Contains decoding options, including if memory is zero
+ * initialized and whether to decode a subset.
+ * @return Enum representing success or reason for failure.
+ */
+ Result startIncrementalDecode(const SkImageInfo& dstInfo, void* dst, size_t rowBytes,
+ const Options*);
+
+ Result startIncrementalDecode(const SkImageInfo& dstInfo, void* dst, size_t rowBytes) {
+ return this->startIncrementalDecode(dstInfo, dst, rowBytes, nullptr);
+ }
+
+ /**
+ * Start/continue the incremental decode.
+ *
+ * Not valid to call before a call to startIncrementalDecode() returns
+ * kSuccess.
+ *
+ * If kIncompleteInput is returned, may be called again after more data has
+ * been provided to the source SkStream.
+ *
+ * Unlike getPixels and getScanlines, this does not do any filling. This is
+ * left up to the caller, since they may be skipping lines or continuing the
+ * decode later. In the latter case, they may choose to initialize all lines
+ * first, or only initialize the remaining lines after the first call.
+ *
+ * @param rowsDecoded Optional output variable returning the total number of
+ * lines initialized. Only meaningful if this method returns kIncompleteInput.
+ * Otherwise the implementation may not set it.
+ * Note that some implementations may have initialized this many rows, but
+ * not necessarily finished those rows (e.g. interlaced PNG). This may be
+ * useful for determining what rows the client needs to initialize.
+ * @return kSuccess if all lines requested in startIncrementalDecode have
+ * been completely decoded. kIncompleteInput otherwise.
+ */
+ Result incrementalDecode(int* rowsDecoded = nullptr) {
+ if (!fStartedIncrementalDecode) {
+ return kInvalidParameters;
+ }
+ return this->onIncrementalDecode(rowsDecoded);
+ }
+
+ /**
+ * The remaining functions revolve around decoding scanlines.
+ */
+
+ /**
+ * Prepare for a scanline decode with the specified options.
+ *
+ * After this call, this class will be ready to decode the first scanline.
+ *
+ * This must be called in order to call getScanlines or skipScanlines.
+ *
+ * This may require rewinding the stream.
+ *
+ * Not all SkCodecs support this.
+ *
+ * @param dstInfo Info of the destination. If the dimensions do not match
+ * those of getInfo, this implies a scale.
+ * @param options Contains decoding options, including if memory is zero
+ * initialized.
+ * @return Enum representing success or reason for failure.
+ */
+ Result startScanlineDecode(const SkImageInfo& dstInfo, const Options* options);
+
+ /**
+ * Simplified version of startScanlineDecode() that uses the default Options.
+ */
+ Result startScanlineDecode(const SkImageInfo& dstInfo) {
+ return this->startScanlineDecode(dstInfo, nullptr);
+ }
+
+ /**
+ * Write the next countLines scanlines into dst.
+ *
+ * Not valid to call before calling startScanlineDecode().
+ *
+ * @param dst Must be non-null, and large enough to hold countLines
+ * scanlines of size rowBytes.
+ * @param countLines Number of lines to write.
+ * @param rowBytes Number of bytes per row. Must be large enough to hold
+ * a scanline based on the SkImageInfo used to create this object.
+ * @return the number of lines successfully decoded. If this value is
+ * less than countLines, this will fill the remaining lines with a
+ * default value.
+ */
+ int getScanlines(void* dst, int countLines, size_t rowBytes);
+
+ /**
+ * Skip count scanlines.
+ *
+ * Not valid to call before calling startScanlineDecode().
+ *
+ * The default version just calls onGetScanlines and discards the dst.
+ * NOTE: If skipped lines are the only lines with alpha, this default
+ * will make reallyHasAlpha return true, when it could have returned
+ * false.
+ *
+ * @return true if the scanlines were successfully skipped
+ * false on failure, possible reasons for failure include:
+ * An incomplete input image stream.
+ * Calling this function before calling startScanlineDecode().
+ * If countLines is less than zero or so large that it moves
+ * the current scanline past the end of the image.
+ */
+ bool skipScanlines(int countLines);
+
+ /**
+ * The order in which rows are output from the scanline decoder is not the
+ * same for all variations of all image types. This explains the possible
+ * output row orderings.
+ */
+ enum SkScanlineOrder {
+ /*
+ * By far the most common, this indicates that the image can be decoded
+ * reliably using the scanline decoder, and that rows will be output in
+ * the logical order.
+ */
+ kTopDown_SkScanlineOrder,
+
+ /*
+ * This indicates that the scanline decoder reliably outputs rows, but
+ * they will be returned in reverse order. If the scanline format is
+ * kBottomUp, the nextScanline() API can be used to determine the actual
+ * y-coordinate of the next output row, but the client is not forced
+ * to take advantage of this, given that it's not too tough to keep
+ * track independently.
+ *
+ * For full image decodes, it is safe to get all of the scanlines at
+ * once, since the decoder will handle inverting the rows as it
+ * decodes.
+ *
+ * For subset decodes and sampling, it is simplest to get and skip
+ * scanlines one at a time, using the nextScanline() API. It is
+ * possible to ask for larger chunks at a time, but this should be used
+ * with caution. As with full image decodes, the decoder will handle
+ * inverting the requested rows, but rows will still be delivered
+ * starting from the bottom of the image.
+ *
+ * Upside down bmps are an example.
+ */
+ kBottomUp_SkScanlineOrder,
+ };
+
+ /**
+ * An enum representing the order in which scanlines will be returned by
+ * the scanline decoder.
+ *
+ * This is undefined before startScanlineDecode() is called.
+ */
+ SkScanlineOrder getScanlineOrder() const { return this->onGetScanlineOrder(); }
+
+ /**
+ * Returns the y-coordinate of the next row to be returned by the scanline
+ * decoder.
+ *
+ * This will equal fCurrScanline, except in the case of strangely
+ * encoded image types (bottom-up bmps).
+ *
+ * Results are undefined when not in scanline decoding mode.
+ */
+ int nextScanline() const { return this->outputScanline(fCurrScanline); }
+
+ /**
+ * Returns the output y-coordinate of the row that corresponds to an input
+ * y-coordinate. The input y-coordinate represents where the scanline
+ * is located in the encoded data.
+ *
+ * This will equal inputScanline, except in the case of strangely
+ * encoded image types (bottom-up bmps, interlaced gifs).
+ */
+ int outputScanline(int inputScanline) const;
+
+ /**
+ * Return the number of frames in the image.
+ *
+ * May require reading through the stream.
+ */
+ int getFrameCount() {
+ return this->onGetFrameCount();
+ }
+
+ // Sentinel value used when a frame index implies "no frame":
+ // - FrameInfo::fRequiredFrame set to this value means the frame
+ // is independent.
+ // - Options::fPriorFrame set to this value means no (relevant) prior frame
+ // is residing in dst's memory.
+ static constexpr int kNoFrame = -1;
+
+ // This transitional definition was added in August 2018, and will eventually be removed.
+#ifdef SK_LEGACY_SKCODEC_NONE_ENUM
+ static constexpr int kNone = kNoFrame;
+#endif
+
+ /**
+ * Information about individual frames in a multi-framed image.
+ */
+ struct FrameInfo {
+ /**
+ * The frame that this frame needs to be blended with, or
+ * kNoFrame if this frame is independent (so it can be
+ * drawn over an uninitialized buffer).
+ *
+ * Note that this is the *earliest* frame that can be used
+ * for blending. Any frame from [fRequiredFrame, i) can be
+ * used, unless its fDisposalMethod is kRestorePrevious.
+ */
+ int fRequiredFrame;
+
+ /**
+ * Number of milliseconds to show this frame.
+ */
+ int fDuration;
+
+ /**
+ * Whether the end marker for this frame is contained in the stream.
+ *
+ * Note: this does not guarantee that an attempt to decode will be complete.
+ * There could be an error in the stream.
+ */
+ bool fFullyReceived;
+
+ /**
+ * This is conservative; it will still return non-opaque if e.g. a
+ * color index-based frame has a color with alpha but does not use it.
+ */
+ SkAlphaType fAlphaType;
+
+ /**
+ * Whether the updated rectangle contains alpha.
+ *
+ * This is conservative; it will still be set to true if e.g. a color
+ * index-based frame has a color with alpha but does not use it. In
+ * addition, it may be set to true, even if the final frame, after
+ * blending, is opaque.
+ */
+ bool fHasAlphaWithinBounds;
+
+ /**
+ * How this frame should be modified before decoding the next one.
+ */
+ SkCodecAnimation::DisposalMethod fDisposalMethod;
+
+ /**
+ * How this frame should blend with the prior frame.
+ */
+ SkCodecAnimation::Blend fBlend;
+
+ /**
+ * The rectangle updated by this frame.
+ *
+ * It may be empty, if the frame does not change the image. It will
+ * always be contained by SkCodec::dimensions().
+ */
+ SkIRect fFrameRect;
+ };
+
+ /**
+ * Return info about a single frame.
+ *
+ * Does not read through the stream, so it should be called after
+ * getFrameCount() to parse any frames that have not already been parsed.
+ *
+ * Only supported by animated (multi-frame) codecs. Note that this is a
+ * property of the codec (the SkCodec subclass), not the image.
+ *
+ * To elaborate, some codecs support animation (e.g. GIF). Others do not
+ * (e.g. BMP). Animated codecs can still represent single frame images.
+ * Calling getFrameInfo(0, etc) will return true for a single frame GIF
+ * even if the overall image is not animated (in that the pixels on screen
+ * do not change over time). When incrementally decoding a GIF image, we
+ * might only know that there's a single frame *so far*.
+ *
+ * For non-animated SkCodec subclasses, it's sufficient but not necessary
+ * for this method to always return false.
+ */
+ bool getFrameInfo(int index, FrameInfo* info) const {
+ if (index < 0) {
+ return false;
+ }
+ return this->onGetFrameInfo(index, info);
+ }
+
+ /**
+ * Return info about all the frames in the image.
+ *
+ * May require reading through the stream to determine info about the
+ * frames (including the count).
+ *
+ * As such, future decoding calls may require a rewind.
+ *
+ * This may return an empty vector for non-animated codecs. See the
+ * getFrameInfo(int, FrameInfo*) comment.
+ */
+ std::vector<FrameInfo> getFrameInfo();
+
+ static constexpr int kRepetitionCountInfinite = -1;
+
+ /**
+ * Return the number of times to repeat, if this image is animated. This number does not
+ * include the first play through of each frame. For example, a repetition count of 4 means
+ * that each frame is played 5 times and then the animation stops.
+ *
+ * It can return kRepetitionCountInfinite, a negative number, meaning that the animation
+ * should loop forever.
+ *
+ * May require reading the stream to find the repetition count.
+ *
+ * As such, future decoding calls may require a rewind.
+ *
+ * For still (non-animated) image codecs, this will return 0.
+ */
+ int getRepetitionCount() {
+ return this->onGetRepetitionCount();
+ }
+
+ // Register a decoder at runtime by passing two function pointers:
+ // - peek() to return true if the span of bytes appears to be your encoded format;
+ // - make() to attempt to create an SkCodec from the given stream.
+ // Not thread safe.
+ static void Register(
+ bool (*peek)(const void*, size_t),
+ std::unique_ptr<SkCodec> (*make)(std::unique_ptr<SkStream>, SkCodec::Result*));
+
+protected:
+ const SkEncodedInfo& getEncodedInfo() const { return fEncodedInfo; }
+
+ using XformFormat = skcms_PixelFormat;
+
+ SkCodec(SkEncodedInfo&&,
+ XformFormat srcFormat,
+ std::unique_ptr<SkStream>,
+ SkEncodedOrigin = kTopLeft_SkEncodedOrigin);
+
+ virtual SkISize onGetScaledDimensions(float /*desiredScale*/) const {
+ // By default, scaling is not supported.
+ return this->dimensions();
+ }
+
+ // FIXME: What to do about subsets??
+ /**
+ * Subclasses should override if they support dimensions other than the
+ * srcInfo's.
+ */
+ virtual bool onDimensionsSupported(const SkISize&) {
+ return false;
+ }
+
+ virtual SkEncodedImageFormat onGetEncodedFormat() const = 0;
+
+ /**
+ * @param rowsDecoded When the encoded image stream is incomplete, this function
+ * will return kIncompleteInput and rowsDecoded will be set to
+ * the number of scanlines that were successfully decoded.
+ * This will allow getPixels() to fill the uninitialized memory.
+ */
+ virtual Result onGetPixels(const SkImageInfo& info,
+ void* pixels, size_t rowBytes, const Options&,
+ int* rowsDecoded) = 0;
+
+ virtual bool onQueryYUVAInfo(const SkYUVAPixmapInfo::SupportedDataTypes&,
+ SkYUVAPixmapInfo*) const { return false; }
+
+ virtual Result onGetYUVAPlanes(const SkYUVAPixmaps&) { return kUnimplemented; }
+
+ virtual bool onGetValidSubset(SkIRect* /*desiredSubset*/) const {
+ // By default, subsets are not supported.
+ return false;
+ }
+
+ /**
+ * If the stream was previously read, attempt to rewind.
+ *
+ * If the stream needed to be rewound, call onRewind.
+ * @returns true if the codec is at the right position and can be used.
+ * false if there was a failure to rewind.
+ *
+ * This is called by getPixels(), getYUV8Planes(), startIncrementalDecode() and
+ * startScanlineDecode(). Subclasses may call if they need to rewind at another time.
+ */
+ bool SK_WARN_UNUSED_RESULT rewindIfNeeded();
+
+ /**
+ * Called by rewindIfNeeded, if the stream needed to be rewound.
+ *
+ * Subclasses should do any set up needed after a rewind.
+ */
+ virtual bool onRewind() {
+ return true;
+ }
+
+ /**
+ * Get method for the input stream
+ */
+ SkStream* stream() {
+ return fStream.get();
+ }
+
+ /**
+ * The remaining functions revolve around decoding scanlines.
+ */
+
+ /**
+ * Most images types will be kTopDown and will not need to override this function.
+ */
+ virtual SkScanlineOrder onGetScanlineOrder() const { return kTopDown_SkScanlineOrder; }
+
+ const SkImageInfo& dstInfo() const { return fDstInfo; }
+
+ const Options& options() const { return fOptions; }
+
+ /**
+ * Returns the number of scanlines that have been decoded so far.
+ * This is unaffected by the SkScanlineOrder.
+ *
+ * Returns -1 if we have not started a scanline decode.
+ */
+ int currScanline() const { return fCurrScanline; }
+
+ virtual int onOutputScanline(int inputScanline) const;
+
+ /**
+ * Return whether we can convert to dst.
+ *
+ * Will be called for the appropriate frame, prior to initializing the colorXform.
+ */
+ virtual bool conversionSupported(const SkImageInfo& dst, bool srcIsOpaque,
+ bool needsColorXform);
+
+ // Some classes never need a colorXform e.g.
+ // - ICO uses its embedded codec's colorXform
+ // - WBMP is just Black/White
+ virtual bool usesColorXform() const { return true; }
+ void applyColorXform(void* dst, const void* src, int count) const;
+
+ bool colorXform() const { return fXformTime != kNo_XformTime; }
+ bool xformOnDecode() const { return fXformTime == kDecodeRow_XformTime; }
+
+ virtual int onGetFrameCount() {
+ return 1;
+ }
+
+ virtual bool onGetFrameInfo(int, FrameInfo*) const {
+ return false;
+ }
+
+ virtual int onGetRepetitionCount() {
+ return 0;
+ }
+
+private:
+ const SkEncodedInfo fEncodedInfo;
+ const XformFormat fSrcXformFormat;
+ std::unique_ptr<SkStream> fStream;
+ bool fNeedsRewind;
+ const SkEncodedOrigin fOrigin;
+
+ SkImageInfo fDstInfo;
+ Options fOptions;
+
+ enum XformTime {
+ kNo_XformTime,
+ kPalette_XformTime,
+ kDecodeRow_XformTime,
+ };
+ XformTime fXformTime;
+ XformFormat fDstXformFormat; // Based on fDstInfo.
+ skcms_ICCProfile fDstProfile;
+ skcms_AlphaFormat fDstXformAlphaFormat;
+
+ // Only meaningful during scanline decodes.
+ int fCurrScanline;
+
+ bool fStartedIncrementalDecode;
+
+ // Allows SkAndroidCodec to call handleFrameIndex (potentially decoding a prior frame and
+ // clearing to transparent) without SkCodec calling it, too.
+ bool fAndroidCodecHandlesFrameIndex;
+
+ bool initializeColorXform(const SkImageInfo& dstInfo, SkEncodedInfo::Alpha, bool srcIsOpaque);
+
+ /**
+ * Return whether these dimensions are supported as a scale.
+ *
+ * The codec may choose to cache the information about scale and subset.
+ * Either way, the same information will be passed to onGetPixels/onStart
+ * on success.
+ *
+ * This must return true for a size returned from getScaledDimensions.
+ */
+ bool dimensionsSupported(const SkISize& dim) {
+ return dim == this->dimensions() || this->onDimensionsSupported(dim);
+ }
+
+ /**
+ * For multi-framed images, return the object with information about the frames.
+ */
+ virtual const SkFrameHolder* getFrameHolder() const {
+ return nullptr;
+ }
+
+ /**
+ * Check for a valid Options.fFrameIndex, and decode prior frames if necessary.
+ *
+ * If androidCodec is not null, that means this SkCodec is owned by an SkAndroidCodec. In that
+ * case, the Options will be treated as an AndroidOptions, and SkAndroidCodec will be used to
+ * decode a prior frame, if a prior frame is needed. When such an owned SkCodec calls
+ * handleFrameIndex, it will immediately return kSuccess, since SkAndroidCodec already handled
+ * it.
+ */
+ Result handleFrameIndex(const SkImageInfo&, void* pixels, size_t rowBytes, const Options&,
+ SkAndroidCodec* androidCodec = nullptr);
+
+ // Methods for scanline decoding.
+ virtual Result onStartScanlineDecode(const SkImageInfo& /*dstInfo*/,
+ const Options& /*options*/) {
+ return kUnimplemented;
+ }
+
+ virtual Result onStartIncrementalDecode(const SkImageInfo& /*dstInfo*/, void*, size_t,
+ const Options&) {
+ return kUnimplemented;
+ }
+
+ virtual Result onIncrementalDecode(int*) {
+ return kUnimplemented;
+ }
+
+
+ virtual bool onSkipScanlines(int /*countLines*/) { return false; }
+
+ virtual int onGetScanlines(void* /*dst*/, int /*countLines*/, size_t /*rowBytes*/) { return 0; }
+
+ /**
+ * On an incomplete decode, getPixels() and getScanlines() will call this function
+ * to fill any uinitialized memory.
+ *
+ * @param dstInfo Contains the destination color type
+ * Contains the destination alpha type
+ * Contains the destination width
+ * The height stored in this info is unused
+ * @param dst Pointer to the start of destination pixel memory
+ * @param rowBytes Stride length in destination pixel memory
+ * @param zeroInit Indicates if memory is zero initialized
+ * @param linesRequested Number of lines that the client requested
+ * @param linesDecoded Number of lines that were successfully decoded
+ */
+ void fillIncompleteImage(const SkImageInfo& dstInfo, void* dst, size_t rowBytes,
+ ZeroInitialized zeroInit, int linesRequested, int linesDecoded);
+
+ /**
+ * Return an object which will allow forcing scanline decodes to sample in X.
+ *
+ * May create a sampler, if one is not currently being used. Otherwise, does
+ * not affect ownership.
+ *
+ * Only valid during scanline decoding or incremental decoding.
+ */
+ virtual SkSampler* getSampler(bool /*createIfNecessary*/) { return nullptr; }
+
+ friend class DM::CodecSrc; // for fillIncompleteImage
+ friend class SkSampledCodec;
+ friend class SkIcoCodec;
+ friend class SkAndroidCodec; // for fEncodedInfo
+};
+#endif // SkCodec_DEFINED
diff --git a/src/deps/skia/include/codec/SkCodecAnimation.h b/src/deps/skia/include/codec/SkCodecAnimation.h
new file mode 100644
index 000000000..c5883e2af
--- /dev/null
+++ b/src/deps/skia/include/codec/SkCodecAnimation.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkCodecAnimation_DEFINED
+#define SkCodecAnimation_DEFINED
+
+namespace SkCodecAnimation {
+ /**
+ * This specifies how the next frame is based on this frame.
+ *
+ * Names are based on the GIF 89a spec.
+ *
+ * The numbers correspond to values in a GIF.
+ */
+ enum class DisposalMethod {
+ /**
+ * The next frame should be drawn on top of this one.
+ *
+ * In a GIF, a value of 0 (not specified) is also treated as Keep.
+ */
+ kKeep = 1,
+
+ /**
+ * Similar to Keep, except the area inside this frame's rectangle
+ * should be cleared to the BackGround color (transparent) before
+ * drawing the next frame.
+ */
+ kRestoreBGColor = 2,
+
+ /**
+ * The next frame should be drawn on top of the previous frame - i.e.
+ * disregarding this one.
+ *
+ * In a GIF, a value of 4 is also treated as RestorePrevious.
+ */
+ kRestorePrevious = 3,
+ };
+
+ /**
+ * How to blend the current frame.
+ */
+ enum class Blend {
+ /**
+ * Blend with the prior frame as if using SkBlendMode::kSrcOver.
+ */
+ kSrcOver,
+
+ /**
+ * Blend with the prior frame as if using SkBlendMode::kSrc.
+ *
+ * This frame's pixels replace the destination pixels.
+ */
+ kSrc,
+ };
+
+} // namespace SkCodecAnimation
+#endif // SkCodecAnimation_DEFINED
diff --git a/src/deps/skia/include/codec/SkEncodedOrigin.h b/src/deps/skia/include/codec/SkEncodedOrigin.h
new file mode 100644
index 000000000..19d083672
--- /dev/null
+++ b/src/deps/skia/include/codec/SkEncodedOrigin.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkEncodedOrigin_DEFINED
+#define SkEncodedOrigin_DEFINED
+
+#include "include/core/SkMatrix.h"
+
+// These values match the orientation www.exif.org/Exif2-2.PDF.
+enum SkEncodedOrigin {
+ kTopLeft_SkEncodedOrigin = 1, // Default
+ kTopRight_SkEncodedOrigin = 2, // Reflected across y-axis
+ kBottomRight_SkEncodedOrigin = 3, // Rotated 180
+ kBottomLeft_SkEncodedOrigin = 4, // Reflected across x-axis
+ kLeftTop_SkEncodedOrigin = 5, // Reflected across x-axis, Rotated 90 CCW
+ kRightTop_SkEncodedOrigin = 6, // Rotated 90 CW
+ kRightBottom_SkEncodedOrigin = 7, // Reflected across x-axis, Rotated 90 CW
+ kLeftBottom_SkEncodedOrigin = 8, // Rotated 90 CCW
+ kDefault_SkEncodedOrigin = kTopLeft_SkEncodedOrigin,
+ kLast_SkEncodedOrigin = kLeftBottom_SkEncodedOrigin,
+};
+
+/**
+ * Given an encoded origin and the width and height of the source data, returns a matrix
+ * that transforms the source rectangle with upper left corner at [0, 0] and origin to a correctly
+ * oriented destination rectangle of [0, 0, w, h].
+ */
+static inline SkMatrix SkEncodedOriginToMatrix(SkEncodedOrigin origin, int w, int h) {
+ switch (origin) {
+ case kTopLeft_SkEncodedOrigin: return SkMatrix::I();
+ case kTopRight_SkEncodedOrigin: return SkMatrix::MakeAll(-1, 0, w, 0, 1, 0, 0, 0, 1);
+ case kBottomRight_SkEncodedOrigin: return SkMatrix::MakeAll(-1, 0, w, 0, -1, h, 0, 0, 1);
+ case kBottomLeft_SkEncodedOrigin: return SkMatrix::MakeAll( 1, 0, 0, 0, -1, h, 0, 0, 1);
+ case kLeftTop_SkEncodedOrigin: return SkMatrix::MakeAll( 0, 1, 0, 1, 0, 0, 0, 0, 1);
+ case kRightTop_SkEncodedOrigin: return SkMatrix::MakeAll( 0, -1, w, 1, 0, 0, 0, 0, 1);
+ case kRightBottom_SkEncodedOrigin: return SkMatrix::MakeAll( 0, -1, w, -1, 0, h, 0, 0, 1);
+ case kLeftBottom_SkEncodedOrigin: return SkMatrix::MakeAll( 0, 1, 0, -1, 0, h, 0, 0, 1);
+ }
+ SK_ABORT("Unexpected origin");
+}
+
+/**
+ * Return true if the encoded origin includes a 90 degree rotation, in which case the width
+ * and height of the source data are swapped relative to a correctly oriented destination.
+ */
+static inline bool SkEncodedOriginSwapsWidthHeight(SkEncodedOrigin origin) {
+ return origin >= kLeftTop_SkEncodedOrigin;
+}
+
+#endif // SkEncodedOrigin_DEFINED
diff --git a/src/deps/skia/include/config/BUILD.bazel b/src/deps/skia/include/config/BUILD.bazel
new file mode 100644
index 000000000..ad2d64d7b
--- /dev/null
+++ b/src/deps/skia/include/config/BUILD.bazel
@@ -0,0 +1,7 @@
+load("//bazel:macros.bzl", "generated_cc_atom")
+
+generated_cc_atom(
+ name = "SkUserConfig_hdr",
+ hdrs = ["SkUserConfig.h"],
+ visibility = ["//:__subpackages__"],
+)
diff --git a/src/deps/skia/include/config/SkUserConfig.h b/src/deps/skia/include/config/SkUserConfig.h
new file mode 100644
index 000000000..313d324e4
--- /dev/null
+++ b/src/deps/skia/include/config/SkUserConfig.h
@@ -0,0 +1,89 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkUserConfig_DEFINED
+#define SkUserConfig_DEFINED
+
+/* SkTypes.h, the root of the public header files, includes this file
+ SkUserConfig.h after first initializing certain Skia defines, letting
+ this file change or augment those flags.
+
+ Below are optional defines that add, subtract, or change default behavior
+ in Skia. Your port can locally edit this file to enable/disable flags as
+ you choose, or these can be delared on your command line (i.e. -Dfoo).
+
+ By default, this include file will always default to having all of the flags
+ commented out, so including it will have no effect.
+*/
+
+///////////////////////////////////////////////////////////////////////////////
+
+/* Skia has lots of debug-only code. Often this is just null checks or other
+ parameter checking, but sometimes it can be quite intrusive (e.g. check that
+ each 32bit pixel is in premultiplied form). This code can be very useful
+ during development, but will slow things down in a shipping product.
+
+ By default, these mutually exclusive flags are defined in SkTypes.h,
+ based on the presence or absence of NDEBUG, but that decision can be changed
+ here.
+ */
+//#define SK_DEBUG
+//#define SK_RELEASE
+
+/* To write debug messages to a console, skia will call SkDebugf(...) following
+ printf conventions (e.g. const char* format, ...). If you want to redirect
+ this to something other than printf, define yours here
+ */
+//#define SkDebugf(...) MyFunction(__VA_ARGS__)
+
+/*
+ * To specify a different default font cache limit, define this. If this is
+ * undefined, skia will use a built-in value.
+ */
+//#define SK_DEFAULT_FONT_CACHE_LIMIT (1024 * 1024)
+
+/*
+ * To specify the default size of the image cache, undefine this and set it to
+ * the desired value (in bytes). SkGraphics.h as a runtime API to set this
+ * value as well. If this is undefined, a built-in value will be used.
+ */
+//#define SK_DEFAULT_IMAGE_CACHE_LIMIT (1024 * 1024)
+
+/* Define this to set the upper limit for text to support LCD. Values that
+ are very large increase the cost in the font cache and draw slower, without
+ improving readability. If this is undefined, Skia will use its default
+ value (e.g. 48)
+ */
+//#define SK_MAX_SIZE_FOR_LCDTEXT 48
+
+/* Change the kN32_SkColorType ordering to BGRA to work in X windows.
+ */
+//#define SK_R32_SHIFT 16
+
+
+/* Determines whether to build code that supports the GPU backend. Some classes
+ that are not GPU-specific, such as SkShader subclasses, have optional code
+ that is used allows them to interact with the GPU backend. If you'd like to
+ omit this code set SK_SUPPORT_GPU to 0. This also allows you to omit the gpu
+ directories from your include search path when you're not building the GPU
+ backend. Defaults to 1 (build the GPU code).
+ */
+//#define SK_SUPPORT_GPU 1
+
+/* Skia makes use of histogram logging macros to trace the frequency of
+ * events. By default, Skia provides no-op versions of these macros.
+ * Skia consumers can provide their own definitions of these macros to
+ * integrate with their histogram collection backend.
+ */
+//#define SK_HISTOGRAM_BOOLEAN(name, sample)
+//#define SK_HISTOGRAM_ENUMERATION(name, sample, enum_size)
+//#define SK_HISTOGRAM_EXACT_LINEAR(name, sample, value_max)
+//#define SK_HISTOGRAM_MEMORY_KB(name, sample)
+
+#endif
diff --git a/src/deps/skia/include/core/BUILD.bazel b/src/deps/skia/include/core/BUILD.bazel
new file mode 100644
index 000000000..9b32d5a6e
--- /dev/null
+++ b/src/deps/skia/include/core/BUILD.bazel
@@ -0,0 +1,951 @@
+load("//bazel:macros.bzl", "generated_cc_atom")
+
+generated_cc_atom(
+ name = "SkAnnotation_hdr",
+ hdrs = ["SkAnnotation.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [":SkTypes_hdr"],
+)
+
+generated_cc_atom(
+ name = "SkBBHFactory_hdr",
+ hdrs = ["SkBBHFactory.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [
+ ":SkRect_hdr",
+ ":SkRefCnt_hdr",
+ ":SkTypes_hdr",
+ ],
+)
+
+generated_cc_atom(
+ name = "SkBitmap_hdr",
+ hdrs = ["SkBitmap.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [
+ ":SkColor_hdr",
+ ":SkImageInfo_hdr",
+ ":SkMatrix_hdr",
+ ":SkPixmap_hdr",
+ ":SkPoint_hdr",
+ ":SkRefCnt_hdr",
+ ":SkShader_hdr",
+ ":SkTileMode_hdr",
+ ],
+)
+
+generated_cc_atom(
+ name = "SkBlendMode_hdr",
+ hdrs = ["SkBlendMode.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [":SkTypes_hdr"],
+)
+
+generated_cc_atom(
+ name = "SkBlender_hdr",
+ hdrs = ["SkBlender.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [
+ ":SkBlendMode_hdr",
+ ":SkFlattenable_hdr",
+ ],
+)
+
+generated_cc_atom(
+ name = "SkBlurTypes_hdr",
+ hdrs = ["SkBlurTypes.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [":SkTypes_hdr"],
+)
+
+generated_cc_atom(
+ name = "SkCanvasVirtualEnforcer_hdr",
+ hdrs = ["SkCanvasVirtualEnforcer.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [":SkCanvas_hdr"],
+)
+
+generated_cc_atom(
+ name = "SkCanvas_hdr",
+ hdrs = ["SkCanvas.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [
+ ":SkBlendMode_hdr",
+ ":SkClipOp_hdr",
+ ":SkColor_hdr",
+ ":SkFontTypes_hdr",
+ ":SkImageInfo_hdr",
+ ":SkM44_hdr",
+ ":SkMatrix_hdr",
+ ":SkPaint_hdr",
+ ":SkPoint_hdr",
+ ":SkRasterHandleAllocator_hdr",
+ ":SkRect_hdr",
+ ":SkRefCnt_hdr",
+ ":SkSamplingOptions_hdr",
+ ":SkScalar_hdr",
+ ":SkSize_hdr",
+ ":SkString_hdr",
+ ":SkSurfaceProps_hdr",
+ ":SkTypes_hdr",
+ "//include/private:SkDeque_hdr",
+ "//include/private:SkMacros_hdr",
+ ],
+)
+
+generated_cc_atom(
+ name = "SkClipOp_hdr",
+ hdrs = ["SkClipOp.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [":SkTypes_hdr"],
+)
+
+generated_cc_atom(
+ name = "SkColorFilter_hdr",
+ hdrs = ["SkColorFilter.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [
+ ":SkBlendMode_hdr",
+ ":SkColor_hdr",
+ ":SkFlattenable_hdr",
+ ],
+)
+
+generated_cc_atom(
+ name = "SkColorPriv_hdr",
+ hdrs = ["SkColorPriv.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [
+ ":SkColor_hdr",
+ ":SkMath_hdr",
+ "//include/private:SkTPin_hdr",
+ "//include/private:SkTo_hdr",
+ ],
+)
+
+generated_cc_atom(
+ name = "SkColorSpace_hdr",
+ hdrs = ["SkColorSpace.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [
+ ":SkRefCnt_hdr",
+ "//include/private:SkFixed_hdr",
+ "//include/private:SkOnce_hdr",
+ "//include/third_party/skcms:skcms_hdr",
+ ],
+)
+
+generated_cc_atom(
+ name = "SkColor_hdr",
+ hdrs = ["SkColor.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [
+ ":SkImageInfo_hdr",
+ ":SkScalar_hdr",
+ ":SkTypes_hdr",
+ ],
+)
+
+generated_cc_atom(
+ name = "SkContourMeasure_hdr",
+ hdrs = ["SkContourMeasure.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [
+ ":SkPath_hdr",
+ ":SkRefCnt_hdr",
+ "//include/private:SkTDArray_hdr",
+ ],
+)
+
+generated_cc_atom(
+ name = "SkCoverageMode_hdr",
+ hdrs = ["SkCoverageMode.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [":SkTypes_hdr"],
+)
+
+generated_cc_atom(
+ name = "SkCubicMap_hdr",
+ hdrs = ["SkCubicMap.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [":SkPoint_hdr"],
+)
+
+generated_cc_atom(
+ name = "SkDataTable_hdr",
+ hdrs = ["SkDataTable.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [
+ ":SkData_hdr",
+ "//include/private:SkTDArray_hdr",
+ ],
+)
+
+generated_cc_atom(
+ name = "SkData_hdr",
+ hdrs = ["SkData.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [":SkRefCnt_hdr"],
+)
+
+generated_cc_atom(
+ name = "SkDeferredDisplayListRecorder_hdr",
+ hdrs = ["SkDeferredDisplayListRecorder.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [
+ ":SkDeferredDisplayList_hdr",
+ ":SkImageInfo_hdr",
+ ":SkImage_hdr",
+ ":SkRefCnt_hdr",
+ ":SkSurfaceCharacterization_hdr",
+ ":SkTypes_hdr",
+ ],
+)
+
+generated_cc_atom(
+ name = "SkDeferredDisplayList_hdr",
+ hdrs = ["SkDeferredDisplayList.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [
+ ":SkRefCnt_hdr",
+ ":SkSurfaceCharacterization_hdr",
+ ":SkTypes_hdr",
+ "//include/gpu:GrRecordingContext_hdr",
+ "//include/private:SkTArray_hdr",
+ ],
+)
+
+generated_cc_atom(
+ name = "SkDocument_hdr",
+ hdrs = ["SkDocument.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [
+ ":SkRefCnt_hdr",
+ ":SkScalar_hdr",
+ ],
+)
+
+generated_cc_atom(
+ name = "SkDrawLooper_hdr",
+ hdrs = ["SkDrawLooper.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [
+ ":SkBlurTypes_hdr",
+ ":SkColor_hdr",
+ ":SkFlattenable_hdr",
+ ":SkPoint_hdr",
+ ],
+)
+
+generated_cc_atom(
+ name = "SkDrawable_hdr",
+ hdrs = ["SkDrawable.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [
+ ":SkFlattenable_hdr",
+ ":SkImageInfo_hdr",
+ ":SkScalar_hdr",
+ ],
+)
+
+generated_cc_atom(
+ name = "SkEncodedImageFormat_hdr",
+ hdrs = ["SkEncodedImageFormat.h"],
+ visibility = ["//:__subpackages__"],
+)
+
+generated_cc_atom(
+ name = "SkExecutor_hdr",
+ hdrs = ["SkExecutor.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [":SkTypes_hdr"],
+)
+
+generated_cc_atom(
+ name = "SkFlattenable_hdr",
+ hdrs = ["SkFlattenable.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [":SkRefCnt_hdr"],
+)
+
+generated_cc_atom(
+ name = "SkFontArguments_hdr",
+ hdrs = ["SkFontArguments.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [
+ ":SkScalar_hdr",
+ ":SkTypes_hdr",
+ ],
+)
+
+generated_cc_atom(
+ name = "SkFontMetrics_hdr",
+ hdrs = ["SkFontMetrics.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [":SkScalar_hdr"],
+)
+
+generated_cc_atom(
+ name = "SkFontMgr_hdr",
+ hdrs = ["SkFontMgr.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [
+ ":SkFontArguments_hdr",
+ ":SkFontStyle_hdr",
+ ":SkRefCnt_hdr",
+ ":SkTypes_hdr",
+ ],
+)
+
+generated_cc_atom(
+ name = "SkFontParameters_hdr",
+ hdrs = ["SkFontParameters.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [
+ ":SkScalar_hdr",
+ ":SkTypes_hdr",
+ ],
+)
+
+generated_cc_atom(
+ name = "SkFontStyle_hdr",
+ hdrs = ["SkFontStyle.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [
+ ":SkTypes_hdr",
+ "//include/private:SkTPin_hdr",
+ ],
+)
+
+generated_cc_atom(
+ name = "SkFontTypes_hdr",
+ hdrs = ["SkFontTypes.h"],
+ visibility = ["//:__subpackages__"],
+)
+
+generated_cc_atom(
+ name = "SkFont_hdr",
+ hdrs = ["SkFont.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [
+ ":SkFontTypes_hdr",
+ ":SkScalar_hdr",
+ ":SkTypeface_hdr",
+ ],
+)
+
+generated_cc_atom(
+ name = "SkGraphics_hdr",
+ hdrs = ["SkGraphics.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [":SkRefCnt_hdr"],
+)
+
+generated_cc_atom(
+ name = "SkICC_hdr",
+ hdrs = ["SkICC.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [":SkData_hdr"],
+)
+
+generated_cc_atom(
+ name = "SkImageEncoder_hdr",
+ hdrs = ["SkImageEncoder.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [
+ ":SkBitmap_hdr",
+ ":SkData_hdr",
+ ":SkEncodedImageFormat_hdr",
+ ":SkPixmap_hdr",
+ ":SkStream_hdr",
+ ],
+)
+
+generated_cc_atom(
+ name = "SkImageFilter_hdr",
+ hdrs = ["SkImageFilter.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [
+ ":SkFlattenable_hdr",
+ ":SkMatrix_hdr",
+ ":SkRect_hdr",
+ ],
+)
+
+generated_cc_atom(
+ name = "SkImageGenerator_hdr",
+ hdrs = ["SkImageGenerator.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [
+ ":SkBitmap_hdr",
+ ":SkColor_hdr",
+ ":SkImageInfo_hdr",
+ ":SkImage_hdr",
+ ":SkYUVAPixmaps_hdr",
+ "//include/private:SkTOptional_hdr",
+ ],
+)
+
+generated_cc_atom(
+ name = "SkImageInfo_hdr",
+ hdrs = ["SkImageInfo.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [
+ ":SkColorSpace_hdr",
+ ":SkMath_hdr",
+ ":SkRect_hdr",
+ ":SkSize_hdr",
+ "//include/private:SkTFitsIn_hdr",
+ "//include/private:SkTo_hdr",
+ ],
+)
+
+generated_cc_atom(
+ name = "SkImage_hdr",
+ hdrs = ["SkImage.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [
+ ":SkImageEncoder_hdr",
+ ":SkImageInfo_hdr",
+ ":SkRefCnt_hdr",
+ ":SkSamplingOptions_hdr",
+ ":SkScalar_hdr",
+ ":SkShader_hdr",
+ ":SkTileMode_hdr",
+ "//include/gpu:GrTypes_hdr",
+ "//include/private:SkTOptional_hdr",
+ ],
+)
+
+generated_cc_atom(
+ name = "SkM44_hdr",
+ hdrs = ["SkM44.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [
+ ":SkMatrix_hdr",
+ ":SkRect_hdr",
+ ":SkScalar_hdr",
+ ],
+)
+
+generated_cc_atom(
+ name = "SkMallocPixelRef_hdr",
+ hdrs = ["SkMallocPixelRef.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [
+ ":SkPixelRef_hdr",
+ ":SkRefCnt_hdr",
+ ":SkTypes_hdr",
+ ],
+)
+
+generated_cc_atom(
+ name = "SkMaskFilter_hdr",
+ hdrs = ["SkMaskFilter.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [
+ ":SkBlurTypes_hdr",
+ ":SkCoverageMode_hdr",
+ ":SkFlattenable_hdr",
+ ":SkScalar_hdr",
+ ],
+)
+
+generated_cc_atom(
+ name = "SkMath_hdr",
+ hdrs = ["SkMath.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [":SkTypes_hdr"],
+)
+
+generated_cc_atom(
+ name = "SkMatrix_hdr",
+ hdrs = ["SkMatrix.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [
+ ":SkRect_hdr",
+ "//include/private:SkMacros_hdr",
+ "//include/private:SkTo_hdr",
+ ],
+)
+
+generated_cc_atom(
+ name = "SkMilestone_hdr",
+ hdrs = ["SkMilestone.h"],
+ visibility = ["//:__subpackages__"],
+)
+
+generated_cc_atom(
+ name = "SkOverdrawCanvas_hdr",
+ hdrs = ["SkOverdrawCanvas.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [
+ ":SkCanvasVirtualEnforcer_hdr",
+ "//include/utils:SkNWayCanvas_hdr",
+ ],
+)
+
+generated_cc_atom(
+ name = "SkPaint_hdr",
+ hdrs = ["SkPaint.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [
+ ":SkBlendMode_hdr",
+ ":SkColor_hdr",
+ ":SkRefCnt_hdr",
+ "//include/private:SkTOptional_hdr",
+ "//include/private:SkTo_hdr",
+ ],
+)
+
+generated_cc_atom(
+ name = "SkPathBuilder_hdr",
+ hdrs = ["SkPathBuilder.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [
+ ":SkMatrix_hdr",
+ ":SkPathTypes_hdr",
+ ":SkPath_hdr",
+ "//include/private:SkTDArray_hdr",
+ ],
+)
+
+generated_cc_atom(
+ name = "SkPathEffect_hdr",
+ hdrs = ["SkPathEffect.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [
+ ":SkFlattenable_hdr",
+ ":SkPath_hdr",
+ ":SkScalar_hdr",
+ ],
+)
+
+generated_cc_atom(
+ name = "SkPathMeasure_hdr",
+ hdrs = ["SkPathMeasure.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [
+ ":SkContourMeasure_hdr",
+ ":SkPath_hdr",
+ "//include/private:SkTDArray_hdr",
+ ],
+)
+
+generated_cc_atom(
+ name = "SkPathTypes_hdr",
+ hdrs = ["SkPathTypes.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [":SkTypes_hdr"],
+)
+
+generated_cc_atom(
+ name = "SkPath_hdr",
+ hdrs = ["SkPath.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [
+ ":SkMatrix_hdr",
+ ":SkPathTypes_hdr",
+ "//include/private:SkPathRef_hdr",
+ "//include/private:SkTo_hdr",
+ ],
+)
+
+generated_cc_atom(
+ name = "SkPictureRecorder_hdr",
+ hdrs = ["SkPictureRecorder.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [
+ ":SkBBHFactory_hdr",
+ ":SkPicture_hdr",
+ ":SkRefCnt_hdr",
+ ],
+)
+
+generated_cc_atom(
+ name = "SkPicture_hdr",
+ hdrs = ["SkPicture.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [
+ ":SkRect_hdr",
+ ":SkRefCnt_hdr",
+ ":SkSamplingOptions_hdr",
+ ":SkShader_hdr",
+ ":SkTileMode_hdr",
+ ":SkTypes_hdr",
+ ],
+)
+
+generated_cc_atom(
+ name = "SkPixelRef_hdr",
+ hdrs = ["SkPixelRef.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [
+ ":SkBitmap_hdr",
+ ":SkImageInfo_hdr",
+ ":SkPixmap_hdr",
+ ":SkRefCnt_hdr",
+ ":SkSize_hdr",
+ "//include/private:SkIDChangeListener_hdr",
+ "//include/private:SkMutex_hdr",
+ "//include/private:SkTDArray_hdr",
+ ],
+)
+
+generated_cc_atom(
+ name = "SkPixmap_hdr",
+ hdrs = ["SkPixmap.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [
+ ":SkColor_hdr",
+ ":SkImageInfo_hdr",
+ ":SkSamplingOptions_hdr",
+ ],
+)
+
+generated_cc_atom(
+ name = "SkPngChunkReader_hdr",
+ hdrs = ["SkPngChunkReader.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [
+ ":SkRefCnt_hdr",
+ ":SkTypes_hdr",
+ ],
+)
+
+generated_cc_atom(
+ name = "SkPoint3_hdr",
+ hdrs = ["SkPoint3.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [":SkPoint_hdr"],
+)
+
+generated_cc_atom(
+ name = "SkPoint_hdr",
+ hdrs = ["SkPoint.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [
+ ":SkMath_hdr",
+ ":SkScalar_hdr",
+ "//include/private:SkSafe32_hdr",
+ ],
+)
+
+generated_cc_atom(
+ name = "SkPromiseImageTexture_hdr",
+ hdrs = ["SkPromiseImageTexture.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [
+ ":SkRefCnt_hdr",
+ ":SkTypes_hdr",
+ "//include/gpu:GrBackendSurface_hdr",
+ ],
+)
+
+generated_cc_atom(
+ name = "SkRRect_hdr",
+ hdrs = ["SkRRect.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [
+ ":SkPoint_hdr",
+ ":SkRect_hdr",
+ ],
+)
+
+generated_cc_atom(
+ name = "SkRSXform_hdr",
+ hdrs = ["SkRSXform.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [
+ ":SkPoint_hdr",
+ ":SkSize_hdr",
+ ],
+)
+
+generated_cc_atom(
+ name = "SkRasterHandleAllocator_hdr",
+ hdrs = ["SkRasterHandleAllocator.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [":SkImageInfo_hdr"],
+)
+
+generated_cc_atom(
+ name = "SkRect_hdr",
+ hdrs = ["SkRect.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [
+ ":SkPoint_hdr",
+ ":SkSize_hdr",
+ "//include/private:SkSafe32_hdr",
+ "//include/private:SkTFitsIn_hdr",
+ ],
+)
+
+generated_cc_atom(
+ name = "SkRefCnt_hdr",
+ hdrs = ["SkRefCnt.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [":SkTypes_hdr"],
+)
+
+generated_cc_atom(
+ name = "SkRegion_hdr",
+ hdrs = ["SkRegion.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [":SkRect_hdr"],
+)
+
+generated_cc_atom(
+ name = "SkSamplingOptions_hdr",
+ hdrs = ["SkSamplingOptions.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [":SkTypes_hdr"],
+)
+
+generated_cc_atom(
+ name = "SkScalar_hdr",
+ hdrs = ["SkScalar.h"],
+ visibility = ["//:__subpackages__"],
+ deps = ["//include/private:SkFloatingPoint_hdr"],
+)
+
+generated_cc_atom(
+ name = "SkSerialProcs_hdr",
+ hdrs = ["SkSerialProcs.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [
+ ":SkImage_hdr",
+ ":SkPicture_hdr",
+ ":SkTypeface_hdr",
+ ],
+)
+
+generated_cc_atom(
+ name = "SkShader_hdr",
+ hdrs = ["SkShader.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [
+ ":SkBlendMode_hdr",
+ ":SkColor_hdr",
+ ":SkFlattenable_hdr",
+ ":SkImageInfo_hdr",
+ ":SkMatrix_hdr",
+ ":SkTileMode_hdr",
+ ],
+)
+
+generated_cc_atom(
+ name = "SkSize_hdr",
+ hdrs = ["SkSize.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [":SkScalar_hdr"],
+)
+
+generated_cc_atom(
+ name = "SkSpan_hdr",
+ hdrs = ["SkSpan.h"],
+ visibility = ["//:__subpackages__"],
+ deps = ["//include/private:SkTLogic_hdr"],
+)
+
+generated_cc_atom(
+ name = "SkStream_hdr",
+ hdrs = ["SkStream.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [
+ ":SkData_hdr",
+ ":SkRefCnt_hdr",
+ ":SkScalar_hdr",
+ "//include/private:SkTo_hdr",
+ ],
+)
+
+generated_cc_atom(
+ name = "SkStringView_hdr",
+ hdrs = ["SkStringView.h"],
+ visibility = ["//:__subpackages__"],
+)
+
+generated_cc_atom(
+ name = "SkString_hdr",
+ hdrs = ["SkString.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [
+ ":SkRefCnt_hdr",
+ ":SkScalar_hdr",
+ ":SkTypes_hdr",
+ "//include/private:SkMalloc_hdr",
+ "//include/private:SkTArray_hdr",
+ "//include/private:SkTo_hdr",
+ ],
+)
+
+generated_cc_atom(
+ name = "SkStrokeRec_hdr",
+ hdrs = ["SkStrokeRec.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [
+ ":SkPaint_hdr",
+ "//include/private:SkMacros_hdr",
+ ],
+)
+
+generated_cc_atom(
+ name = "SkSurfaceCharacterization_hdr",
+ hdrs = ["SkSurfaceCharacterization.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [
+ ":SkColorSpace_hdr",
+ ":SkImageInfo_hdr",
+ ":SkRefCnt_hdr",
+ ":SkSurfaceProps_hdr",
+ "//include/gpu:GrBackendSurface_hdr",
+ "//include/gpu:GrContextThreadSafeProxy_hdr",
+ "//include/gpu:GrTypes_hdr",
+ ],
+)
+
+generated_cc_atom(
+ name = "SkSurfaceProps_hdr",
+ hdrs = ["SkSurfaceProps.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [":SkTypes_hdr"],
+)
+
+generated_cc_atom(
+ name = "SkSurface_hdr",
+ hdrs = ["SkSurface.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [
+ ":SkImage_hdr",
+ ":SkPixmap_hdr",
+ ":SkRefCnt_hdr",
+ ":SkSurfaceProps_hdr",
+ "//include/gpu:GrTypes_hdr",
+ "//include/gpu/mtl:GrMtlTypes_hdr",
+ ],
+)
+
+generated_cc_atom(
+ name = "SkSwizzle_hdr",
+ hdrs = ["SkSwizzle.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [":SkTypes_hdr"],
+)
+
+generated_cc_atom(
+ name = "SkTextBlob_hdr",
+ hdrs = ["SkTextBlob.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [
+ ":SkFont_hdr",
+ ":SkPaint_hdr",
+ ":SkRefCnt_hdr",
+ ":SkString_hdr",
+ "//include/private:SkTemplates_hdr",
+ ],
+)
+
+generated_cc_atom(
+ name = "SkTileMode_hdr",
+ hdrs = ["SkTileMode.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [":SkTypes_hdr"],
+)
+
+generated_cc_atom(
+ name = "SkTime_hdr",
+ hdrs = ["SkTime.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [
+ ":SkTypes_hdr",
+ "//include/private:SkMacros_hdr",
+ ],
+)
+
+generated_cc_atom(
+ name = "SkTraceMemoryDump_hdr",
+ hdrs = ["SkTraceMemoryDump.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [":SkTypes_hdr"],
+)
+
+generated_cc_atom(
+ name = "SkTypeface_hdr",
+ hdrs = ["SkTypeface.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [
+ ":SkFontArguments_hdr",
+ ":SkFontParameters_hdr",
+ ":SkFontStyle_hdr",
+ ":SkFontTypes_hdr",
+ ":SkRect_hdr",
+ ":SkString_hdr",
+ "//include/private:SkOnce_hdr",
+ "//include/private:SkWeakRefCnt_hdr",
+ ],
+)
+
+generated_cc_atom(
+ name = "SkTypes_hdr",
+ hdrs = ["SkTypes.h"],
+ visibility = ["//:__subpackages__"],
+ deps = ["//include/config:SkUserConfig_hdr"],
+)
+
+generated_cc_atom(
+ name = "SkUnPreMultiply_hdr",
+ hdrs = ["SkUnPreMultiply.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [":SkColor_hdr"],
+)
+
+generated_cc_atom(
+ name = "SkVertices_hdr",
+ hdrs = ["SkVertices.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [
+ ":SkColor_hdr",
+ ":SkRect_hdr",
+ ":SkRefCnt_hdr",
+ ],
+)
+
+generated_cc_atom(
+ name = "SkYUVAInfo_hdr",
+ hdrs = ["SkYUVAInfo.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [
+ ":SkImageInfo_hdr",
+ ":SkSize_hdr",
+ "//include/codec:SkEncodedOrigin_hdr",
+ ],
+)
+
+generated_cc_atom(
+ name = "SkYUVAPixmaps_hdr",
+ hdrs = ["SkYUVAPixmaps.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [
+ ":SkData_hdr",
+ ":SkImageInfo_hdr",
+ ":SkPixmap_hdr",
+ ":SkYUVAInfo_hdr",
+ "//include/private:SkTo_hdr",
+ ],
+)
+
+generated_cc_atom(
+ name = "SkCustomMesh_hdr",
+ hdrs = ["SkCustomMesh.h"],
+ visibility = ["//:__subpackages__"],
+ deps = [
+ ":SkColorSpace_hdr",
+ ":SkImageInfo_hdr",
+ ":SkRect_hdr",
+ ":SkRefCnt_hdr",
+ ":SkSpan_hdr",
+ ":SkString_hdr",
+ ":SkTypes_hdr",
+ ],
+)
diff --git a/src/deps/skia/include/core/SkAnnotation.h b/src/deps/skia/include/core/SkAnnotation.h
new file mode 100644
index 000000000..9048bb6b6
--- /dev/null
+++ b/src/deps/skia/include/core/SkAnnotation.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkAnnotation_DEFINED
+#define SkAnnotation_DEFINED
+
+#include "include/core/SkTypes.h"
+
+class SkData;
+struct SkPoint;
+struct SkRect;
+class SkCanvas;
+
+/**
+ * Annotate the canvas by associating the specified URL with the
+ * specified rectangle (in local coordinates, just like drawRect).
+ *
+ * If the backend of this canvas does not support annotations, this call is
+ * safely ignored.
+ *
+ * The caller is responsible for managing its ownership of the SkData.
+ */
+SK_API void SkAnnotateRectWithURL(SkCanvas*, const SkRect&, SkData*);
+
+/**
+ * Annotate the canvas by associating a name with the specified point.
+ *
+ * If the backend of this canvas does not support annotations, this call is
+ * safely ignored.
+ *
+ * The caller is responsible for managing its ownership of the SkData.
+ */
+SK_API void SkAnnotateNamedDestination(SkCanvas*, const SkPoint&, SkData*);
+
+/**
+ * Annotate the canvas by making the specified rectangle link to a named
+ * destination.
+ *
+ * If the backend of this canvas does not support annotations, this call is
+ * safely ignored.
+ *
+ * The caller is responsible for managing its ownership of the SkData.
+ */
+SK_API void SkAnnotateLinkToDestination(SkCanvas*, const SkRect&, SkData*);
+
+#endif
diff --git a/src/deps/skia/include/core/SkBBHFactory.h b/src/deps/skia/include/core/SkBBHFactory.h
new file mode 100644
index 000000000..2507d0f15
--- /dev/null
+++ b/src/deps/skia/include/core/SkBBHFactory.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkBBHFactory_DEFINED
+#define SkBBHFactory_DEFINED
+
+#include "include/core/SkRect.h"
+#include "include/core/SkRefCnt.h"
+#include "include/core/SkTypes.h"
+#include <vector>
+
+class SkBBoxHierarchy : public SkRefCnt {
+public:
+ struct Metadata {
+ bool isDraw; // The corresponding SkRect bounds a draw command, not a pure state change.
+ };
+
+ /**
+ * Insert N bounding boxes into the hierarchy.
+ */
+ virtual void insert(const SkRect[], int N) = 0;
+ virtual void insert(const SkRect[], const Metadata[], int N);
+
+ /**
+ * Populate results with the indices of bounding boxes intersecting that query.
+ */
+ virtual void search(const SkRect& query, std::vector<int>* results) const = 0;
+
+ /**
+ * Return approximate size in memory of *this.
+ */
+ virtual size_t bytesUsed() const = 0;
+
+protected:
+ SkBBoxHierarchy() = default;
+ SkBBoxHierarchy(const SkBBoxHierarchy&) = delete;
+ SkBBoxHierarchy& operator=(const SkBBoxHierarchy&) = delete;
+};
+
+class SK_API SkBBHFactory {
+public:
+ /**
+ * Allocate a new SkBBoxHierarchy. Return NULL on failure.
+ */
+ virtual sk_sp<SkBBoxHierarchy> operator()() const = 0;
+ virtual ~SkBBHFactory() {}
+
+protected:
+ SkBBHFactory() = default;
+ SkBBHFactory(const SkBBHFactory&) = delete;
+ SkBBHFactory& operator=(const SkBBHFactory&) = delete;
+};
+
+class SK_API SkRTreeFactory : public SkBBHFactory {
+public:
+ sk_sp<SkBBoxHierarchy> operator()() const override;
+};
+
+#endif
diff --git a/src/deps/skia/include/core/SkBitmap.h b/src/deps/skia/include/core/SkBitmap.h
new file mode 100644
index 000000000..088280fbe
--- /dev/null
+++ b/src/deps/skia/include/core/SkBitmap.h
@@ -0,0 +1,1212 @@
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkBitmap_DEFINED
+#define SkBitmap_DEFINED
+
+#include "include/core/SkColor.h"
+#include "include/core/SkImageInfo.h"
+#include "include/core/SkMatrix.h"
+#include "include/core/SkPixmap.h"
+#include "include/core/SkPoint.h"
+#include "include/core/SkRefCnt.h"
+#include "include/core/SkShader.h"
+#include "include/core/SkTileMode.h"
+
+class SkBitmap;
+struct SkMask;
+class SkMipmap;
+struct SkIRect;
+struct SkRect;
+class SkPaint;
+class SkPixelRef;
+class SkShader;
+
+/** \class SkBitmap
+ SkBitmap describes a two-dimensional raster pixel array. SkBitmap is built on
+ SkImageInfo, containing integer width and height, SkColorType and SkAlphaType
+ describing the pixel format, and SkColorSpace describing the range of colors.
+ SkBitmap points to SkPixelRef, which describes the physical array of pixels.
+ SkImageInfo bounds may be located anywhere fully inside SkPixelRef bounds.
+
+ SkBitmap can be drawn using SkCanvas. SkBitmap can be a drawing destination for SkCanvas
+ draw member functions. SkBitmap flexibility as a pixel container limits some
+ optimizations available to the target platform.
+
+ If pixel array is primarily read-only, use SkImage for better performance.
+ If pixel array is primarily written to, use SkSurface for better performance.
+
+ Declaring SkBitmap const prevents altering SkImageInfo: the SkBitmap height, width,
+ and so on cannot change. It does not affect SkPixelRef: a caller may write its
+ pixels. Declaring SkBitmap const affects SkBitmap configuration, not its contents.
+
+ SkBitmap is not thread safe. Each thread must have its own copy of SkBitmap fields,
+ although threads may share the underlying pixel array.
+*/
+class SK_API SkBitmap {
+public:
+ class SK_API Allocator;
+
+ /** Creates an empty SkBitmap without pixels, with kUnknown_SkColorType,
+ kUnknown_SkAlphaType, and with a width and height of zero. SkPixelRef origin is
+ set to (0, 0).
+
+ Use setInfo() to associate SkColorType, SkAlphaType, width, and height
+ after SkBitmap has been created.
+
+ @return empty SkBitmap
+
+ example: https://fiddle.skia.org/c/@Bitmap_empty_constructor
+ */
+ SkBitmap();
+
+ /** Copies settings from src to returned SkBitmap. Shares pixels if src has pixels
+ allocated, so both bitmaps reference the same pixels.
+
+ @param src SkBitmap to copy SkImageInfo, and share SkPixelRef
+ @return copy of src
+
+ example: https://fiddle.skia.org/c/@Bitmap_copy_const_SkBitmap
+ */
+ SkBitmap(const SkBitmap& src);
+
+ /** Copies settings from src to returned SkBitmap. Moves ownership of src pixels to
+ SkBitmap.
+
+ @param src SkBitmap to copy SkImageInfo, and reassign SkPixelRef
+ @return copy of src
+
+ example: https://fiddle.skia.org/c/@Bitmap_move_SkBitmap
+ */
+ SkBitmap(SkBitmap&& src);
+
+ /** Decrements SkPixelRef reference count, if SkPixelRef is not nullptr.
+ */
+ ~SkBitmap();
+
+ /** Copies settings from src to returned SkBitmap. Shares pixels if src has pixels
+ allocated, so both bitmaps reference the same pixels.
+
+ @param src SkBitmap to copy SkImageInfo, and share SkPixelRef
+ @return copy of src
+
+ example: https://fiddle.skia.org/c/@Bitmap_copy_operator
+ */
+ SkBitmap& operator=(const SkBitmap& src);
+
+ /** Copies settings from src to returned SkBitmap. Moves ownership of src pixels to
+ SkBitmap.
+
+ @param src SkBitmap to copy SkImageInfo, and reassign SkPixelRef
+ @return copy of src
+
+ example: https://fiddle.skia.org/c/@Bitmap_move_operator
+ */
+ SkBitmap& operator=(SkBitmap&& src);
+
+ /** Swaps the fields of the two bitmaps.
+
+ @param other SkBitmap exchanged with original
+
+ example: https://fiddle.skia.org/c/@Bitmap_swap
+ */
+ void swap(SkBitmap& other);
+
+ /** Returns a constant reference to the SkPixmap holding the SkBitmap pixel
+ address, row bytes, and SkImageInfo.
+
+ @return reference to SkPixmap describing this SkBitmap
+ */
+ const SkPixmap& pixmap() const { return fPixmap; }
+
+ /** Returns width, height, SkAlphaType, SkColorType, and SkColorSpace.
+
+ @return reference to SkImageInfo
+ */
+ const SkImageInfo& info() const { return fPixmap.info(); }
+
+ /** Returns pixel count in each row. Should be equal or less than
+ rowBytes() / info().bytesPerPixel().
+
+ May be less than pixelRef().width(). Will not exceed pixelRef().width() less
+ pixelRefOrigin().fX.
+
+ @return pixel width in SkImageInfo
+ */
+ int width() const { return fPixmap.width(); }
+
+ /** Returns pixel row count.
+
+ Maybe be less than pixelRef().height(). Will not exceed pixelRef().height() less
+ pixelRefOrigin().fY.
+
+ @return pixel height in SkImageInfo
+ */
+ int height() const { return fPixmap.height(); }
+
+ SkColorType colorType() const { return fPixmap.colorType(); }
+
+ SkAlphaType alphaType() const { return fPixmap.alphaType(); }
+
+ /** Returns SkColorSpace, the range of colors, associated with SkImageInfo. The
+ reference count of SkColorSpace is unchanged. The returned SkColorSpace is
+ immutable.
+
+ @return SkColorSpace in SkImageInfo, or nullptr
+ */
+ SkColorSpace* colorSpace() const { return fPixmap.colorSpace(); }
+
+ /** Returns smart pointer to SkColorSpace, the range of colors, associated with
+ SkImageInfo. The smart pointer tracks the number of objects sharing this
+ SkColorSpace reference so the memory is released when the owners destruct.
+
+ The returned SkColorSpace is immutable.
+
+ @return SkColorSpace in SkImageInfo wrapped in a smart pointer
+ */
+ sk_sp<SkColorSpace> refColorSpace() const { return fPixmap.info().refColorSpace(); }
+
+ /** Returns number of bytes per pixel required by SkColorType.
+ Returns zero if colorType( is kUnknown_SkColorType.
+
+ @return bytes in pixel
+ */
+ int bytesPerPixel() const { return fPixmap.info().bytesPerPixel(); }
+
+ /** Returns number of pixels that fit on row. Should be greater than or equal to
+ width().
+
+ @return maximum pixels per row
+ */
+ int rowBytesAsPixels() const { return fPixmap.rowBytesAsPixels(); }
+
+ /** Returns bit shift converting row bytes to row pixels.
+ Returns zero for kUnknown_SkColorType.
+
+ @return one of: 0, 1, 2, 3; left shift to convert pixels to bytes
+ */
+ int shiftPerPixel() const { return fPixmap.shiftPerPixel(); }
+
+ /** Returns true if either width() or height() are zero.
+
+ Does not check if SkPixelRef is nullptr; call drawsNothing() to check width(),
+ height(), and SkPixelRef.
+
+ @return true if dimensions do not enclose area
+ */
+ bool empty() const { return fPixmap.info().isEmpty(); }
+
+ /** Returns true if SkPixelRef is nullptr.
+
+ Does not check if width() or height() are zero; call drawsNothing() to check
+ width(), height(), and SkPixelRef.
+
+ @return true if no SkPixelRef is associated
+ */
+ bool isNull() const { return nullptr == fPixelRef; }
+
+ /** Returns true if width() or height() are zero, or if SkPixelRef is nullptr.
+ If true, SkBitmap has no effect when drawn or drawn into.
+
+ @return true if drawing has no effect
+ */
+ bool drawsNothing() const {
+ return this->empty() || this->isNull();
+ }
+
+ /** Returns row bytes, the interval from one pixel row to the next. Row bytes
+ is at least as large as: width() * info().bytesPerPixel().
+
+ Returns zero if colorType() is kUnknown_SkColorType, or if row bytes supplied to
+ setInfo() is not large enough to hold a row of pixels.
+
+ @return byte length of pixel row
+ */
+ size_t rowBytes() const { return fPixmap.rowBytes(); }
+
+ /** Sets SkAlphaType, if alphaType is compatible with SkColorType.
+ Returns true unless alphaType is kUnknown_SkAlphaType and current SkAlphaType
+ is not kUnknown_SkAlphaType.
+
+ Returns true if SkColorType is kUnknown_SkColorType. alphaType is ignored, and
+ SkAlphaType remains kUnknown_SkAlphaType.
+
+ Returns true if SkColorType is kRGB_565_SkColorType or kGray_8_SkColorType.
+ alphaType is ignored, and SkAlphaType remains kOpaque_SkAlphaType.
+
+ If SkColorType is kARGB_4444_SkColorType, kRGBA_8888_SkColorType,
+ kBGRA_8888_SkColorType, or kRGBA_F16_SkColorType: returns true unless
+ alphaType is kUnknown_SkAlphaType and SkAlphaType is not kUnknown_SkAlphaType.
+ If SkAlphaType is kUnknown_SkAlphaType, alphaType is ignored.
+
+ If SkColorType is kAlpha_8_SkColorType, returns true unless
+ alphaType is kUnknown_SkAlphaType and SkAlphaType is not kUnknown_SkAlphaType.
+ If SkAlphaType is kUnknown_SkAlphaType, alphaType is ignored. If alphaType is
+ kUnpremul_SkAlphaType, it is treated as kPremul_SkAlphaType.
+
+ This changes SkAlphaType in SkPixelRef; all bitmaps sharing SkPixelRef
+ are affected.
+
+ @return true if SkAlphaType is set
+
+ example: https://fiddle.skia.org/c/@Bitmap_setAlphaType
+ */
+ bool setAlphaType(SkAlphaType alphaType);
+
+ /** Returns pixel address, the base address corresponding to the pixel origin.
+
+ @return pixel address
+ */
+ void* getPixels() const { return fPixmap.writable_addr(); }
+
+ /** Returns minimum memory required for pixel storage.
+ Does not include unused memory on last row when rowBytesAsPixels() exceeds width().
+ Returns SIZE_MAX if result does not fit in size_t.
+ Returns zero if height() or width() is 0.
+ Returns height() times rowBytes() if colorType() is kUnknown_SkColorType.
+
+ @return size in bytes of image buffer
+ */
+ size_t computeByteSize() const { return fPixmap.computeByteSize(); }
+
+ /** Returns true if pixels can not change.
+
+ Most immutable SkBitmap checks trigger an assert only on debug builds.
+
+ @return true if pixels are immutable
+
+ example: https://fiddle.skia.org/c/@Bitmap_isImmutable
+ */
+ bool isImmutable() const;
+
+ /** Sets internal flag to mark SkBitmap as immutable. Once set, pixels can not change.
+ Any other bitmap sharing the same SkPixelRef are also marked as immutable.
+ Once SkPixelRef is marked immutable, the setting cannot be cleared.
+
+ Writing to immutable SkBitmap pixels triggers an assert on debug builds.
+
+ example: https://fiddle.skia.org/c/@Bitmap_setImmutable
+ */
+ void setImmutable();
+
+ /** Returns true if SkAlphaType is set to hint that all pixels are opaque; their
+ alpha value is implicitly or explicitly 1.0. If true, and all pixels are
+ not opaque, Skia may draw incorrectly.
+
+ Does not check if SkColorType allows alpha, or if any pixel value has
+ transparency.
+
+ @return true if SkImageInfo SkAlphaType is kOpaque_SkAlphaType
+ */
+ bool isOpaque() const {
+ return SkAlphaTypeIsOpaque(this->alphaType());
+ }
+
+ /** Resets to its initial state; all fields are set to zero, as if SkBitmap had
+ been initialized by SkBitmap().
+
+ Sets width, height, row bytes to zero; pixel address to nullptr; SkColorType to
+ kUnknown_SkColorType; and SkAlphaType to kUnknown_SkAlphaType.
+
+ If SkPixelRef is allocated, its reference count is decreased by one, releasing
+ its memory if SkBitmap is the sole owner.
+
+ example: https://fiddle.skia.org/c/@Bitmap_reset
+ */
+ void reset();
+
+ /** Returns true if all pixels are opaque. SkColorType determines how pixels
+ are encoded, and whether pixel describes alpha. Returns true for SkColorType
+ without alpha in each pixel; for other SkColorType, returns true if all
+ pixels have alpha values equivalent to 1.0 or greater.
+
+ For SkColorType kRGB_565_SkColorType or kGray_8_SkColorType: always
+ returns true. For SkColorType kAlpha_8_SkColorType, kBGRA_8888_SkColorType,
+ kRGBA_8888_SkColorType: returns true if all pixel alpha values are 255.
+ For SkColorType kARGB_4444_SkColorType: returns true if all pixel alpha values are 15.
+ For kRGBA_F16_SkColorType: returns true if all pixel alpha values are 1.0 or
+ greater.
+
+ Returns false for kUnknown_SkColorType.
+
+ @param bm SkBitmap to check
+ @return true if all pixels have opaque values or SkColorType is opaque
+ */
+ static bool ComputeIsOpaque(const SkBitmap& bm) {
+ return bm.pixmap().computeIsOpaque();
+ }
+
+ /** Returns SkRect { 0, 0, width(), height() }.
+
+ @param bounds container for floating point rectangle
+
+ example: https://fiddle.skia.org/c/@Bitmap_getBounds
+ */
+ void getBounds(SkRect* bounds) const;
+
+ /** Returns SkIRect { 0, 0, width(), height() }.
+
+ @param bounds container for integral rectangle
+
+ example: https://fiddle.skia.org/c/@Bitmap_getBounds_2
+ */
+ void getBounds(SkIRect* bounds) const;
+
+ /** Returns SkIRect { 0, 0, width(), height() }.
+
+ @return integral rectangle from origin to width() and height()
+ */
+ SkIRect bounds() const { return fPixmap.info().bounds(); }
+
+ /** Returns SkISize { width(), height() }.
+
+ @return integral size of width() and height()
+ */
+ SkISize dimensions() const { return fPixmap.info().dimensions(); }
+
+ /** Returns the bounds of this bitmap, offset by its SkPixelRef origin.
+
+ @return bounds within SkPixelRef bounds
+ */
+ SkIRect getSubset() const {
+ SkIPoint origin = this->pixelRefOrigin();
+ return SkIRect::MakeXYWH(origin.x(), origin.y(), this->width(), this->height());
+ }
+
+ /** Sets width, height, SkAlphaType, SkColorType, SkColorSpace, and optional
+ rowBytes. Frees pixels, and returns true if successful.
+
+ imageInfo.alphaType() may be altered to a value permitted by imageInfo.colorSpace().
+ If imageInfo.colorType() is kUnknown_SkColorType, imageInfo.alphaType() is
+ set to kUnknown_SkAlphaType.
+ If imageInfo.colorType() is kAlpha_8_SkColorType and imageInfo.alphaType() is
+ kUnpremul_SkAlphaType, imageInfo.alphaType() is replaced by kPremul_SkAlphaType.
+ If imageInfo.colorType() is kRGB_565_SkColorType or kGray_8_SkColorType,
+ imageInfo.alphaType() is set to kOpaque_SkAlphaType.
+ If imageInfo.colorType() is kARGB_4444_SkColorType, kRGBA_8888_SkColorType,
+ kBGRA_8888_SkColorType, or kRGBA_F16_SkColorType: imageInfo.alphaType() remains
+ unchanged.
+
+ rowBytes must equal or exceed imageInfo.minRowBytes(). If imageInfo.colorSpace() is
+ kUnknown_SkColorType, rowBytes is ignored and treated as zero; for all other
+ SkColorSpace values, rowBytes of zero is treated as imageInfo.minRowBytes().
+
+ Calls reset() and returns false if:
+ - rowBytes exceeds 31 bits
+ - imageInfo.width() is negative
+ - imageInfo.height() is negative
+ - rowBytes is positive and less than imageInfo.width() times imageInfo.bytesPerPixel()
+
+ @param imageInfo contains width, height, SkAlphaType, SkColorType, SkColorSpace
+ @param rowBytes imageInfo.minRowBytes() or larger; or zero
+ @return true if SkImageInfo set successfully
+
+ example: https://fiddle.skia.org/c/@Bitmap_setInfo
+ */
+ bool setInfo(const SkImageInfo& imageInfo, size_t rowBytes = 0);
+
+ /** \enum SkBitmap::AllocFlags
+ AllocFlags is obsolete. We always zero pixel memory when allocated.
+ */
+ enum AllocFlags {
+ kZeroPixels_AllocFlag = 1 << 0, //!< zero pixel memory. No effect. This is the default.
+ };
+
+ /** Sets SkImageInfo to info following the rules in setInfo() and allocates pixel
+ memory. Memory is zeroed.
+
+ Returns false and calls reset() if SkImageInfo could not be set, or memory could
+ not be allocated, or memory could not optionally be zeroed.
+
+ On most platforms, allocating pixel memory may succeed even though there is
+ not sufficient memory to hold pixels; allocation does not take place
+ until the pixels are written to. The actual behavior depends on the platform
+ implementation of calloc().
+
+ @param info contains width, height, SkAlphaType, SkColorType, SkColorSpace
+ @param flags kZeroPixels_AllocFlag, or zero
+ @return true if pixels allocation is successful
+ */
+ bool SK_WARN_UNUSED_RESULT tryAllocPixelsFlags(const SkImageInfo& info, uint32_t flags);
+
+ /** Sets SkImageInfo to info following the rules in setInfo() and allocates pixel
+ memory. Memory is zeroed.
+
+ Aborts execution if SkImageInfo could not be set, or memory could
+ not be allocated, or memory could not optionally
+ be zeroed. Abort steps may be provided by the user at compile time by defining
+ SK_ABORT.
+
+ On most platforms, allocating pixel memory may succeed even though there is
+ not sufficient memory to hold pixels; allocation does not take place
+ until the pixels are written to. The actual behavior depends on the platform
+ implementation of calloc().
+
+ @param info contains width, height, SkAlphaType, SkColorType, SkColorSpace
+ @param flags kZeroPixels_AllocFlag, or zero
+
+ example: https://fiddle.skia.org/c/@Bitmap_allocPixelsFlags
+ */
+ void allocPixelsFlags(const SkImageInfo& info, uint32_t flags);
+
+ /** Sets SkImageInfo to info following the rules in setInfo() and allocates pixel
+ memory. rowBytes must equal or exceed info.width() times info.bytesPerPixel(),
+ or equal zero. Pass in zero for rowBytes to compute the minimum valid value.
+
+ Returns false and calls reset() if SkImageInfo could not be set, or memory could
+ not be allocated.
+
+ On most platforms, allocating pixel memory may succeed even though there is
+ not sufficient memory to hold pixels; allocation does not take place
+ until the pixels are written to. The actual behavior depends on the platform
+ implementation of malloc().
+
+ @param info contains width, height, SkAlphaType, SkColorType, SkColorSpace
+ @param rowBytes size of pixel row or larger; may be zero
+ @return true if pixel storage is allocated
+ */
+ bool SK_WARN_UNUSED_RESULT tryAllocPixels(const SkImageInfo& info, size_t rowBytes);
+
+ /** Sets SkImageInfo to info following the rules in setInfo() and allocates pixel
+ memory. rowBytes must equal or exceed info.width() times info.bytesPerPixel(),
+ or equal zero. Pass in zero for rowBytes to compute the minimum valid value.
+
+ Aborts execution if SkImageInfo could not be set, or memory could
+ not be allocated. Abort steps may be provided by
+ the user at compile time by defining SK_ABORT.
+
+ On most platforms, allocating pixel memory may succeed even though there is
+ not sufficient memory to hold pixels; allocation does not take place
+ until the pixels are written to. The actual behavior depends on the platform
+ implementation of malloc().
+
+ @param info contains width, height, SkAlphaType, SkColorType, SkColorSpace
+ @param rowBytes size of pixel row or larger; may be zero
+
+ example: https://fiddle.skia.org/c/@Bitmap_allocPixels
+ */
+ void allocPixels(const SkImageInfo& info, size_t rowBytes);
+
+ /** Sets SkImageInfo to info following the rules in setInfo() and allocates pixel
+ memory.
+
+ Returns false and calls reset() if SkImageInfo could not be set, or memory could
+ not be allocated.
+
+ On most platforms, allocating pixel memory may succeed even though there is
+ not sufficient memory to hold pixels; allocation does not take place
+ until the pixels are written to. The actual behavior depends on the platform
+ implementation of malloc().
+
+ @param info contains width, height, SkAlphaType, SkColorType, SkColorSpace
+ @return true if pixel storage is allocated
+ */
+ bool SK_WARN_UNUSED_RESULT tryAllocPixels(const SkImageInfo& info) {
+ return this->tryAllocPixels(info, info.minRowBytes());
+ }
+
+ /** Sets SkImageInfo to info following the rules in setInfo() and allocates pixel
+ memory.
+
+ Aborts execution if SkImageInfo could not be set, or memory could
+ not be allocated. Abort steps may be provided by
+ the user at compile time by defining SK_ABORT.
+
+ On most platforms, allocating pixel memory may succeed even though there is
+ not sufficient memory to hold pixels; allocation does not take place
+ until the pixels are written to. The actual behavior depends on the platform
+ implementation of malloc().
+
+ @param info contains width, height, SkAlphaType, SkColorType, SkColorSpace
+
+ example: https://fiddle.skia.org/c/@Bitmap_allocPixels_2
+ */
+ void allocPixels(const SkImageInfo& info);
+
+ /** Sets SkImageInfo to width, height, and native color type; and allocates
+ pixel memory. If isOpaque is true, sets SkImageInfo to kOpaque_SkAlphaType;
+ otherwise, sets to kPremul_SkAlphaType.
+
+ Calls reset() and returns false if width exceeds 29 bits or is negative,
+ or height is negative.
+
+ Returns false if allocation fails.
+
+ Use to create SkBitmap that matches SkPMColor, the native pixel arrangement on
+ the platform. SkBitmap drawn to output device skips converting its pixel format.
+
+ @param width pixel column count; must be zero or greater
+ @param height pixel row count; must be zero or greater
+ @param isOpaque true if pixels do not have transparency
+ @return true if pixel storage is allocated
+ */
+ bool SK_WARN_UNUSED_RESULT tryAllocN32Pixels(int width, int height, bool isOpaque = false);
+
+ /** Sets SkImageInfo to width, height, and the native color type; and allocates
+ pixel memory. If isOpaque is true, sets SkImageInfo to kOpaque_SkAlphaType;
+ otherwise, sets to kPremul_SkAlphaType.
+
+ Aborts if width exceeds 29 bits or is negative, or height is negative, or
+ allocation fails. Abort steps may be provided by the user at compile time by
+ defining SK_ABORT.
+
+ Use to create SkBitmap that matches SkPMColor, the native pixel arrangement on
+ the platform. SkBitmap drawn to output device skips converting its pixel format.
+
+ @param width pixel column count; must be zero or greater
+ @param height pixel row count; must be zero or greater
+ @param isOpaque true if pixels do not have transparency
+
+ example: https://fiddle.skia.org/c/@Bitmap_allocN32Pixels
+ */
+ void allocN32Pixels(int width, int height, bool isOpaque = false);
+
+ /** Sets SkImageInfo to info following the rules in setInfo(), and creates SkPixelRef
+ containing pixels and rowBytes. releaseProc, if not nullptr, is called
+ immediately on failure or when pixels are no longer referenced. context may be
+ nullptr.
+
+ If SkImageInfo could not be set, or rowBytes is less than info.minRowBytes():
+ calls releaseProc if present, calls reset(), and returns false.
+
+ Otherwise, if pixels equals nullptr: sets SkImageInfo, calls releaseProc if
+ present, returns true.
+
+ If SkImageInfo is set, pixels is not nullptr, and releaseProc is not nullptr:
+ when pixels are no longer referenced, calls releaseProc with pixels and context
+ as parameters.
+
+ @param info contains width, height, SkAlphaType, SkColorType, SkColorSpace
+ @param pixels address or pixel storage; may be nullptr
+ @param rowBytes size of pixel row or larger
+ @param releaseProc function called when pixels can be deleted; may be nullptr
+ @param context caller state passed to releaseProc; may be nullptr
+ @return true if SkImageInfo is set to info
+ */
+ bool installPixels(const SkImageInfo& info, void* pixels, size_t rowBytes,
+ void (*releaseProc)(void* addr, void* context), void* context);
+
+ /** Sets SkImageInfo to info following the rules in setInfo(), and creates SkPixelRef
+ containing pixels and rowBytes.
+
+ If SkImageInfo could not be set, or rowBytes is less than info.minRowBytes():
+ calls reset(), and returns false.
+
+ Otherwise, if pixels equals nullptr: sets SkImageInfo, returns true.
+
+ Caller must ensure that pixels are valid for the lifetime of SkBitmap and SkPixelRef.
+
+ @param info contains width, height, SkAlphaType, SkColorType, SkColorSpace
+ @param pixels address or pixel storage; may be nullptr
+ @param rowBytes size of pixel row or larger
+ @return true if SkImageInfo is set to info
+ */
+ bool installPixels(const SkImageInfo& info, void* pixels, size_t rowBytes) {
+ return this->installPixels(info, pixels, rowBytes, nullptr, nullptr);
+ }
+
+ /** Sets SkImageInfo to pixmap.info() following the rules in setInfo(), and creates
+ SkPixelRef containing pixmap.addr() and pixmap.rowBytes().
+
+ If SkImageInfo could not be set, or pixmap.rowBytes() is less than
+ SkImageInfo::minRowBytes(): calls reset(), and returns false.
+
+ Otherwise, if pixmap.addr() equals nullptr: sets SkImageInfo, returns true.
+
+ Caller must ensure that pixmap is valid for the lifetime of SkBitmap and SkPixelRef.
+
+ @param pixmap SkImageInfo, pixel address, and rowBytes()
+ @return true if SkImageInfo was set to pixmap.info()
+
+ example: https://fiddle.skia.org/c/@Bitmap_installPixels_3
+ */
+ bool installPixels(const SkPixmap& pixmap);
+
+ /** Deprecated.
+ */
+ bool installMaskPixels(const SkMask& mask);
+
+ /** Replaces SkPixelRef with pixels, preserving SkImageInfo and rowBytes().
+ Sets SkPixelRef origin to (0, 0).
+
+ If pixels is nullptr, or if info().colorType() equals kUnknown_SkColorType;
+ release reference to SkPixelRef, and set SkPixelRef to nullptr.
+
+ Caller is responsible for handling ownership pixel memory for the lifetime
+ of SkBitmap and SkPixelRef.
+
+ @param pixels address of pixel storage, managed by caller
+
+ example: https://fiddle.skia.org/c/@Bitmap_setPixels
+ */
+ void setPixels(void* pixels);
+
+ /** Allocates pixel memory with HeapAllocator, and replaces existing SkPixelRef.
+ The allocation size is determined by SkImageInfo width, height, and SkColorType.
+
+ Returns false if info().colorType() is kUnknown_SkColorType, or allocation fails.
+
+ @return true if the allocation succeeds
+ */
+ bool SK_WARN_UNUSED_RESULT tryAllocPixels() {
+ return this->tryAllocPixels((Allocator*)nullptr);
+ }
+
+ /** Allocates pixel memory with HeapAllocator, and replaces existing SkPixelRef.
+ The allocation size is determined by SkImageInfo width, height, and SkColorType.
+
+ Aborts if info().colorType() is kUnknown_SkColorType, or allocation fails.
+ Abort steps may be provided by the user at compile
+ time by defining SK_ABORT.
+
+ example: https://fiddle.skia.org/c/@Bitmap_allocPixels_3
+ */
+ void allocPixels();
+
+ /** Allocates pixel memory with allocator, and replaces existing SkPixelRef.
+ The allocation size is determined by SkImageInfo width, height, and SkColorType.
+ If allocator is nullptr, use HeapAllocator instead.
+
+ Returns false if Allocator::allocPixelRef return false.
+
+ @param allocator instance of SkBitmap::Allocator instantiation
+ @return true if custom allocator reports success
+ */
+ bool SK_WARN_UNUSED_RESULT tryAllocPixels(Allocator* allocator);
+
+ /** Allocates pixel memory with allocator, and replaces existing SkPixelRef.
+ The allocation size is determined by SkImageInfo width, height, and SkColorType.
+ If allocator is nullptr, use HeapAllocator instead.
+
+ Aborts if Allocator::allocPixelRef return false. Abort steps may be provided by
+ the user at compile time by defining SK_ABORT.
+
+ @param allocator instance of SkBitmap::Allocator instantiation
+
+ example: https://fiddle.skia.org/c/@Bitmap_allocPixels_4
+ */
+ void allocPixels(Allocator* allocator);
+
+ /** Returns SkPixelRef, which contains: pixel base address; its dimensions; and
+ rowBytes(), the interval from one row to the next. Does not change SkPixelRef
+ reference count. SkPixelRef may be shared by multiple bitmaps.
+ If SkPixelRef has not been set, returns nullptr.
+
+ @return SkPixelRef, or nullptr
+ */
+ SkPixelRef* pixelRef() const { return fPixelRef.get(); }
+
+ /** Returns origin of pixels within SkPixelRef. SkBitmap bounds is always contained
+ by SkPixelRef bounds, which may be the same size or larger. Multiple SkBitmap
+ can share the same SkPixelRef, where each SkBitmap has different bounds.
+
+ The returned origin added to SkBitmap dimensions equals or is smaller than the
+ SkPixelRef dimensions.
+
+ Returns (0, 0) if SkPixelRef is nullptr.
+
+ @return pixel origin within SkPixelRef
+
+ example: https://fiddle.skia.org/c/@Bitmap_pixelRefOrigin
+ */
+ SkIPoint pixelRefOrigin() const;
+
+ /** Replaces pixelRef and origin in SkBitmap. dx and dy specify the offset
+ within the SkPixelRef pixels for the top-left corner of the bitmap.
+
+ Asserts in debug builds if dx or dy are out of range. Pins dx and dy
+ to legal range in release builds.
+
+ The caller is responsible for ensuring that the pixels match the
+ SkColorType and SkAlphaType in SkImageInfo.
+
+ @param pixelRef SkPixelRef describing pixel address and rowBytes()
+ @param dx column offset in SkPixelRef for bitmap origin
+ @param dy row offset in SkPixelRef for bitmap origin
+
+ example: https://fiddle.skia.org/c/@Bitmap_setPixelRef
+ */
+ void setPixelRef(sk_sp<SkPixelRef> pixelRef, int dx, int dy);
+
+ /** Returns true if SkBitmap is can be drawn.
+
+ @return true if getPixels() is not nullptr
+ */
+ bool readyToDraw() const {
+ return this->getPixels() != nullptr;
+ }
+
+ /** Returns a unique value corresponding to the pixels in SkPixelRef.
+ Returns a different value after notifyPixelsChanged() has been called.
+ Returns zero if SkPixelRef is nullptr.
+
+ Determines if pixels have changed since last examined.
+
+ @return unique value for pixels in SkPixelRef
+
+ example: https://fiddle.skia.org/c/@Bitmap_getGenerationID
+ */
+ uint32_t getGenerationID() const;
+
+ /** Marks that pixels in SkPixelRef have changed. Subsequent calls to
+ getGenerationID() return a different value.
+
+ example: https://fiddle.skia.org/c/@Bitmap_notifyPixelsChanged
+ */
+ void notifyPixelsChanged() const;
+
+ /** Replaces pixel values with c, interpreted as being in the sRGB SkColorSpace.
+ All pixels contained by bounds() are affected. If the colorType() is
+ kGray_8_SkColorType or kRGB_565_SkColorType, then alpha is ignored; RGB is
+ treated as opaque. If colorType() is kAlpha_8_SkColorType, then RGB is ignored.
+
+ @param c unpremultiplied color
+
+ example: https://fiddle.skia.org/c/@Bitmap_eraseColor
+ */
+ void eraseColor(SkColor c) const;
+
+ /** Replaces pixel values with unpremultiplied color built from a, r, g, and b,
+ interpreted as being in the sRGB SkColorSpace. All pixels contained by
+ bounds() are affected. If the colorType() is kGray_8_SkColorType or
+ kRGB_565_SkColorType, then a is ignored; r, g, and b are treated as opaque.
+ If colorType() is kAlpha_8_SkColorType, then r, g, and b are ignored.
+
+ @param a amount of alpha, from fully transparent (0) to fully opaque (255)
+ @param r amount of red, from no red (0) to full red (255)
+ @param g amount of green, from no green (0) to full green (255)
+ @param b amount of blue, from no blue (0) to full blue (255)
+ */
+ void eraseARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) const {
+ this->eraseColor(SkColorSetARGB(a, r, g, b));
+ }
+
+ /** Replaces pixel values inside area with c. interpreted as being in the sRGB
+ SkColorSpace. If area does not intersect bounds(), call has no effect.
+
+ If the colorType() is kGray_8_SkColorType or kRGB_565_SkColorType, then alpha
+ is ignored; RGB is treated as opaque. If colorType() is kAlpha_8_SkColorType,
+ then RGB is ignored.
+
+ @param c unpremultiplied color
+ @param area rectangle to fill
+
+ example: https://fiddle.skia.org/c/@Bitmap_erase
+ */
+ void erase(SkColor c, const SkIRect& area) const;
+
+ /** Deprecated.
+ */
+ void eraseArea(const SkIRect& area, SkColor c) const {
+ this->erase(c, area);
+ }
+
+ /** Returns pixel at (x, y) as unpremultiplied color.
+ Returns black with alpha if SkColorType is kAlpha_8_SkColorType.
+
+ Input is not validated: out of bounds values of x or y trigger an assert() if
+ built with SK_DEBUG defined; and returns undefined values or may crash if
+ SK_RELEASE is defined. Fails if SkColorType is kUnknown_SkColorType or
+ pixel address is nullptr.
+
+ SkColorSpace in SkImageInfo is ignored. Some color precision may be lost in the
+ conversion to unpremultiplied color; original pixel data may have additional
+ precision.
+
+ @param x column index, zero or greater, and less than width()
+ @param y row index, zero or greater, and less than height()
+ @return pixel converted to unpremultiplied color
+ */
+ SkColor getColor(int x, int y) const {
+ return this->pixmap().getColor(x, y);
+ }
+
+ /** Look up the pixel at (x,y) and return its alpha component, normalized to [0..1].
+ This is roughly equivalent to SkGetColorA(getColor()), but can be more efficent
+ (and more precise if the pixels store more than 8 bits per component).
+
+ @param x column index, zero or greater, and less than width()
+ @param y row index, zero or greater, and less than height()
+ @return alpha converted to normalized float
+ */
+ float getAlphaf(int x, int y) const {
+ return this->pixmap().getAlphaf(x, y);
+ }
+
+ /** Returns pixel address at (x, y).
+
+ Input is not validated: out of bounds values of x or y, or kUnknown_SkColorType,
+ trigger an assert() if built with SK_DEBUG defined. Returns nullptr if
+ SkColorType is kUnknown_SkColorType, or SkPixelRef is nullptr.
+
+ Performs a lookup of pixel size; for better performance, call
+ one of: getAddr8(), getAddr16(), or getAddr32().
+
+ @param x column index, zero or greater, and less than width()
+ @param y row index, zero or greater, and less than height()
+ @return generic pointer to pixel
+
+ example: https://fiddle.skia.org/c/@Bitmap_getAddr
+ */
+ void* getAddr(int x, int y) const;
+
+ /** Returns address at (x, y).
+
+ Input is not validated. Triggers an assert() if built with SK_DEBUG defined and:
+ - SkPixelRef is nullptr
+ - bytesPerPixel() is not four
+ - x is negative, or not less than width()
+ - y is negative, or not less than height()
+
+ @param x column index, zero or greater, and less than width()
+ @param y row index, zero or greater, and less than height()
+ @return unsigned 32-bit pointer to pixel at (x, y)
+ */
+ inline uint32_t* getAddr32(int x, int y) const;
+
+ /** Returns address at (x, y).
+
+ Input is not validated. Triggers an assert() if built with SK_DEBUG defined and:
+ - SkPixelRef is nullptr
+ - bytesPerPixel() is not two
+ - x is negative, or not less than width()
+ - y is negative, or not less than height()
+
+ @param x column index, zero or greater, and less than width()
+ @param y row index, zero or greater, and less than height()
+ @return unsigned 16-bit pointer to pixel at (x, y)
+ */
+ inline uint16_t* getAddr16(int x, int y) const;
+
+ /** Returns address at (x, y).
+
+ Input is not validated. Triggers an assert() if built with SK_DEBUG defined and:
+ - SkPixelRef is nullptr
+ - bytesPerPixel() is not one
+ - x is negative, or not less than width()
+ - y is negative, or not less than height()
+
+ @param x column index, zero or greater, and less than width()
+ @param y row index, zero or greater, and less than height()
+ @return unsigned 8-bit pointer to pixel at (x, y)
+ */
+ inline uint8_t* getAddr8(int x, int y) const;
+
+ /** Shares SkPixelRef with dst. Pixels are not copied; SkBitmap and dst point
+ to the same pixels; dst bounds() are set to the intersection of subset
+ and the original bounds().
+
+ subset may be larger than bounds(). Any area outside of bounds() is ignored.
+
+ Any contents of dst are discarded.
+
+ Return false if:
+ - dst is nullptr
+ - SkPixelRef is nullptr
+ - subset does not intersect bounds()
+
+ @param dst SkBitmap set to subset
+ @param subset rectangle of pixels to reference
+ @return true if dst is replaced by subset
+
+ example: https://fiddle.skia.org/c/@Bitmap_extractSubset
+ */
+ bool extractSubset(SkBitmap* dst, const SkIRect& subset) const;
+
+ /** Copies a SkRect of pixels from SkBitmap to dstPixels. Copy starts at (srcX, srcY),
+ and does not exceed SkBitmap (width(), height()).
+
+ dstInfo specifies width, height, SkColorType, SkAlphaType, and SkColorSpace of
+ destination. dstRowBytes specifics the gap from one destination row to the next.
+ Returns true if pixels are copied. Returns false if:
+ - dstInfo has no address
+ - dstRowBytes is less than dstInfo.minRowBytes()
+ - SkPixelRef is nullptr
+
+ Pixels are copied only if pixel conversion is possible. If SkBitmap colorType() is
+ kGray_8_SkColorType, or kAlpha_8_SkColorType; dstInfo.colorType() must match.
+ If SkBitmap colorType() is kGray_8_SkColorType, dstInfo.colorSpace() must match.
+ If SkBitmap alphaType() is kOpaque_SkAlphaType, dstInfo.alphaType() must
+ match. If SkBitmap colorSpace() is nullptr, dstInfo.colorSpace() must match. Returns
+ false if pixel conversion is not possible.
+
+ srcX and srcY may be negative to copy only top or left of source. Returns
+ false if width() or height() is zero or negative.
+ Returns false if abs(srcX) >= Bitmap width(), or if abs(srcY) >= Bitmap height().
+
+ @param dstInfo destination width, height, SkColorType, SkAlphaType, SkColorSpace
+ @param dstPixels destination pixel storage
+ @param dstRowBytes destination row length
+ @param srcX column index whose absolute value is less than width()
+ @param srcY row index whose absolute value is less than height()
+ @return true if pixels are copied to dstPixels
+ */
+ bool readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
+ int srcX, int srcY) const;
+
+ /** Copies a SkRect of pixels from SkBitmap to dst. Copy starts at (srcX, srcY), and
+ does not exceed SkBitmap (width(), height()).
+
+ dst specifies width, height, SkColorType, SkAlphaType, SkColorSpace, pixel storage,
+ and row bytes of destination. dst.rowBytes() specifics the gap from one destination
+ row to the next. Returns true if pixels are copied. Returns false if:
+ - dst pixel storage equals nullptr
+ - dst.rowBytes is less than SkImageInfo::minRowBytes()
+ - SkPixelRef is nullptr
+
+ Pixels are copied only if pixel conversion is possible. If SkBitmap colorType() is
+ kGray_8_SkColorType, or kAlpha_8_SkColorType; dst SkColorType must match.
+ If SkBitmap colorType() is kGray_8_SkColorType, dst SkColorSpace must match.
+ If SkBitmap alphaType() is kOpaque_SkAlphaType, dst SkAlphaType must
+ match. If SkBitmap colorSpace() is nullptr, dst SkColorSpace must match. Returns
+ false if pixel conversion is not possible.
+
+ srcX and srcY may be negative to copy only top or left of source. Returns
+ false if width() or height() is zero or negative.
+ Returns false if abs(srcX) >= Bitmap width(), or if abs(srcY) >= Bitmap height().
+
+ @param dst destination SkPixmap: SkImageInfo, pixels, row bytes
+ @param srcX column index whose absolute value is less than width()
+ @param srcY row index whose absolute value is less than height()
+ @return true if pixels are copied to dst
+
+ example: https://fiddle.skia.org/c/@Bitmap_readPixels_2
+ */
+ bool readPixels(const SkPixmap& dst, int srcX, int srcY) const;
+
+ /** Copies a SkRect of pixels from SkBitmap to dst. Copy starts at (0, 0), and
+ does not exceed SkBitmap (width(), height()).
+
+ dst specifies width, height, SkColorType, SkAlphaType, SkColorSpace, pixel storage,
+ and row bytes of destination. dst.rowBytes() specifics the gap from one destination
+ row to the next. Returns true if pixels are copied. Returns false if:
+ - dst pixel storage equals nullptr
+ - dst.rowBytes is less than SkImageInfo::minRowBytes()
+ - SkPixelRef is nullptr
+
+ Pixels are copied only if pixel conversion is possible. If SkBitmap colorType() is
+ kGray_8_SkColorType, or kAlpha_8_SkColorType; dst SkColorType must match.
+ If SkBitmap colorType() is kGray_8_SkColorType, dst SkColorSpace must match.
+ If SkBitmap alphaType() is kOpaque_SkAlphaType, dst SkAlphaType must
+ match. If SkBitmap colorSpace() is nullptr, dst SkColorSpace must match. Returns
+ false if pixel conversion is not possible.
+
+ @param dst destination SkPixmap: SkImageInfo, pixels, row bytes
+ @return true if pixels are copied to dst
+ */
+ bool readPixels(const SkPixmap& dst) const {
+ return this->readPixels(dst, 0, 0);
+ }
+
+ /** Copies a SkRect of pixels from src. Copy starts at (dstX, dstY), and does not exceed
+ (src.width(), src.height()).
+
+ src specifies width, height, SkColorType, SkAlphaType, SkColorSpace, pixel storage,
+ and row bytes of source. src.rowBytes() specifics the gap from one source
+ row to the next. Returns true if pixels are copied. Returns false if:
+ - src pixel storage equals nullptr
+ - src.rowBytes is less than SkImageInfo::minRowBytes()
+ - SkPixelRef is nullptr
+
+ Pixels are copied only if pixel conversion is possible. If SkBitmap colorType() is
+ kGray_8_SkColorType, or kAlpha_8_SkColorType; src SkColorType must match.
+ If SkBitmap colorType() is kGray_8_SkColorType, src SkColorSpace must match.
+ If SkBitmap alphaType() is kOpaque_SkAlphaType, src SkAlphaType must
+ match. If SkBitmap colorSpace() is nullptr, src SkColorSpace must match. Returns
+ false if pixel conversion is not possible.
+
+ dstX and dstY may be negative to copy only top or left of source. Returns
+ false if width() or height() is zero or negative.
+ Returns false if abs(dstX) >= Bitmap width(), or if abs(dstY) >= Bitmap height().
+
+ @param src source SkPixmap: SkImageInfo, pixels, row bytes
+ @param dstX column index whose absolute value is less than width()
+ @param dstY row index whose absolute value is less than height()
+ @return true if src pixels are copied to SkBitmap
+
+ example: https://fiddle.skia.org/c/@Bitmap_writePixels
+ */
+ bool writePixels(const SkPixmap& src, int dstX, int dstY);
+
+ /** Copies a SkRect of pixels from src. Copy starts at (0, 0), and does not exceed
+ (src.width(), src.height()).
+
+ src specifies width, height, SkColorType, SkAlphaType, SkColorSpace, pixel storage,
+ and row bytes of source. src.rowBytes() specifics the gap from one source
+ row to the next. Returns true if pixels are copied. Returns false if:
+ - src pixel storage equals nullptr
+ - src.rowBytes is less than SkImageInfo::minRowBytes()
+ - SkPixelRef is nullptr
+
+ Pixels are copied only if pixel conversion is possible. If SkBitmap colorType() is
+ kGray_8_SkColorType, or kAlpha_8_SkColorType; src SkColorType must match.
+ If SkBitmap colorType() is kGray_8_SkColorType, src SkColorSpace must match.
+ If SkBitmap alphaType() is kOpaque_SkAlphaType, src SkAlphaType must
+ match. If SkBitmap colorSpace() is nullptr, src SkColorSpace must match. Returns
+ false if pixel conversion is not possible.
+
+ @param src source SkPixmap: SkImageInfo, pixels, row bytes
+ @return true if src pixels are copied to SkBitmap
+ */
+ bool writePixels(const SkPixmap& src) {
+ return this->writePixels(src, 0, 0);
+ }
+
+ /** Sets dst to alpha described by pixels. Returns false if dst cannot be written to
+ or dst pixels cannot be allocated.
+
+ Uses HeapAllocator to reserve memory for dst SkPixelRef.
+
+ @param dst holds SkPixelRef to fill with alpha layer
+ @return true if alpha layer was constructed in dst SkPixelRef
+ */
+ bool extractAlpha(SkBitmap* dst) const {
+ return this->extractAlpha(dst, nullptr, nullptr, nullptr);
+ }
+
+ /** Sets dst to alpha described by pixels. Returns false if dst cannot be written to
+ or dst pixels cannot be allocated.
+
+ If paint is not nullptr and contains SkMaskFilter, SkMaskFilter
+ generates mask alpha from SkBitmap. Uses HeapAllocator to reserve memory for dst
+ SkPixelRef. Sets offset to top-left position for dst for alignment with SkBitmap;
+ (0, 0) unless SkMaskFilter generates mask.
+
+ @param dst holds SkPixelRef to fill with alpha layer
+ @param paint holds optional SkMaskFilter; may be nullptr
+ @param offset top-left position for dst; may be nullptr
+ @return true if alpha layer was constructed in dst SkPixelRef
+ */
+ bool extractAlpha(SkBitmap* dst, const SkPaint* paint,
+ SkIPoint* offset) const {
+ return this->extractAlpha(dst, paint, nullptr, offset);
+ }
+
+ /** Sets dst to alpha described by pixels. Returns false if dst cannot be written to
+ or dst pixels cannot be allocated.
+
+ If paint is not nullptr and contains SkMaskFilter, SkMaskFilter
+ generates mask alpha from SkBitmap. allocator may reference a custom allocation
+ class or be set to nullptr to use HeapAllocator. Sets offset to top-left
+ position for dst for alignment with SkBitmap; (0, 0) unless SkMaskFilter generates
+ mask.
+
+ @param dst holds SkPixelRef to fill with alpha layer
+ @param paint holds optional SkMaskFilter; may be nullptr
+ @param allocator function to reserve memory for SkPixelRef; may be nullptr
+ @param offset top-left position for dst; may be nullptr
+ @return true if alpha layer was constructed in dst SkPixelRef
+ */
+ bool extractAlpha(SkBitmap* dst, const SkPaint* paint, Allocator* allocator,
+ SkIPoint* offset) const;
+
+ /** Copies SkBitmap pixel address, row bytes, and SkImageInfo to pixmap, if address
+ is available, and returns true. If pixel address is not available, return
+ false and leave pixmap unchanged.
+
+ pixmap contents become invalid on any future change to SkBitmap.
+
+ @param pixmap storage for pixel state if pixels are readable; otherwise, ignored
+ @return true if SkBitmap has direct access to pixels
+
+ example: https://fiddle.skia.org/c/@Bitmap_peekPixels
+ */
+ bool peekPixels(SkPixmap* pixmap) const;
+ sk_sp<SkShader> makeShader(SkTileMode tmx, SkTileMode tmy, const SkSamplingOptions&,
+ const SkMatrix* = nullptr) const;
+
+ sk_sp<SkShader> makeShader(SkTileMode tmx, SkTileMode tmy, const SkSamplingOptions& sampling,
+ const SkMatrix& localMatrix) const {
+ return this->makeShader(tmx, tmy, sampling, &localMatrix);
+ }
+
+ sk_sp<SkShader> makeShader(const SkSamplingOptions& sampling,
+ const SkMatrix* localMatrix = nullptr) const {
+ return this->makeShader(SkTileMode::kClamp, SkTileMode::kClamp, sampling, localMatrix);
+ }
+
+ sk_sp<SkShader> makeShader(const SkSamplingOptions& sampling,
+ const SkMatrix& localMatrix) const {
+ return this->makeShader(sampling, &localMatrix);
+ }
+
+ /**
+ * Returns a new image from the bitmap. If the bitmap is marked immutable, this will
+ * share the pixel buffer. If not, it will make a copy of the pixels for the image.
+ */
+ sk_sp<SkImage> asImage() const;
+
+ /** Asserts if internal values are illegal or inconsistent. Only available if
+ SK_DEBUG is defined at compile time.
+ */
+ SkDEBUGCODE(void validate() const;)
+
+ /** \class SkBitmap::Allocator
+ Abstract subclass of HeapAllocator.
+ */
+ class Allocator : public SkRefCnt {
+ public:
+
+ /** Allocates the pixel memory for the bitmap, given its dimensions and
+ SkColorType. Returns true on success, where success means either setPixels()
+ or setPixelRef() was called.
+
+ @param bitmap SkBitmap containing SkImageInfo as input, and SkPixelRef as output
+ @return true if SkPixelRef was allocated
+ */
+ virtual bool allocPixelRef(SkBitmap* bitmap) = 0;
+ private:
+ using INHERITED = SkRefCnt;
+ };
+
+ /** \class SkBitmap::HeapAllocator
+ Subclass of SkBitmap::Allocator that returns a SkPixelRef that allocates its pixel
+ memory from the heap. This is the default SkBitmap::Allocator invoked by
+ allocPixels().
+ */
+ class HeapAllocator : public Allocator {
+ public:
+
+ /** Allocates the pixel memory for the bitmap, given its dimensions and
+ SkColorType. Returns true on success, where success means either setPixels()
+ or setPixelRef() was called.
+
+ @param bitmap SkBitmap containing SkImageInfo as input, and SkPixelRef as output
+ @return true if pixels are allocated
+
+ example: https://fiddle.skia.org/c/@Bitmap_HeapAllocator_allocPixelRef
+ */
+ bool allocPixelRef(SkBitmap* bitmap) override;
+ };
+
+private:
+ sk_sp<SkPixelRef> fPixelRef;
+ SkPixmap fPixmap;
+ sk_sp<SkMipmap> fMips;
+
+ friend class SkImage_Raster;
+ friend class SkReadBuffer; // unflatten
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+inline uint32_t* SkBitmap::getAddr32(int x, int y) const {
+ SkASSERT(fPixmap.addr());
+ return fPixmap.writable_addr32(x, y);
+}
+
+inline uint16_t* SkBitmap::getAddr16(int x, int y) const {
+ SkASSERT(fPixmap.addr());
+ return fPixmap.writable_addr16(x, y);
+}
+
+inline uint8_t* SkBitmap::getAddr8(int x, int y) const {
+ SkASSERT(fPixmap.addr());
+ return fPixmap.writable_addr8(x, y);
+}
+
+#endif
diff --git a/src/deps/skia/include/core/SkBlendMode.h b/src/deps/skia/include/core/SkBlendMode.h
new file mode 100644
index 000000000..07640cf55
--- /dev/null
+++ b/src/deps/skia/include/core/SkBlendMode.h
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkBlendMode_DEFINED
+#define SkBlendMode_DEFINED
+
+#include "include/core/SkTypes.h"
+
+/**
+ * Blends are operators that take in two colors (source, destination) and return a new color.
+ * Many of these operate the same on all 4 components: red, green, blue, alpha. For these,
+ * we just document what happens to one component, rather than naming each one separately.
+ *
+ * Different SkColorTypes have different representations for color components:
+ * 8-bit: 0..255
+ * 6-bit: 0..63
+ * 5-bit: 0..31
+ * 4-bit: 0..15
+ * floats: 0...1
+ *
+ * The documentation is expressed as if the component values are always 0..1 (floats).
+ *
+ * For brevity, the documentation uses the following abbreviations
+ * s : source
+ * d : destination
+ * sa : source alpha
+ * da : destination alpha
+ *
+ * Results are abbreviated
+ * r : if all 4 components are computed in the same manner
+ * ra : result alpha component
+ * rc : result "color": red, green, blue components
+ */
+enum class SkBlendMode {
+ kClear, //!< r = 0
+ kSrc, //!< r = s
+ kDst, //!< r = d
+ kSrcOver, //!< r = s + (1-sa)*d
+ kDstOver, //!< r = d + (1-da)*s
+ kSrcIn, //!< r = s * da
+ kDstIn, //!< r = d * sa
+ kSrcOut, //!< r = s * (1-da)
+ kDstOut, //!< r = d * (1-sa)
+ kSrcATop, //!< r = s*da + d*(1-sa)
+ kDstATop, //!< r = d*sa + s*(1-da)
+ kXor, //!< r = s*(1-da) + d*(1-sa)
+ kPlus, //!< r = min(s + d, 1)
+ kModulate, //!< r = s*d
+ kScreen, //!< r = s + d - s*d
+
+ kOverlay, //!< multiply or screen, depending on destination
+ kDarken, //!< rc = s + d - max(s*da, d*sa), ra = kSrcOver
+ kLighten, //!< rc = s + d - min(s*da, d*sa), ra = kSrcOver
+ kColorDodge, //!< brighten destination to reflect source
+ kColorBurn, //!< darken destination to reflect source
+ kHardLight, //!< multiply or screen, depending on source
+ kSoftLight, //!< lighten or darken, depending on source
+ kDifference, //!< rc = s + d - 2*(min(s*da, d*sa)), ra = kSrcOver
+ kExclusion, //!< rc = s + d - two(s*d), ra = kSrcOver
+ kMultiply, //!< r = s*(1-da) + d*(1-sa) + s*d
+
+ kHue, //!< hue of source with saturation and luminosity of destination
+ kSaturation, //!< saturation of source with hue and luminosity of destination
+ kColor, //!< hue and saturation of source with luminosity of destination
+ kLuminosity, //!< luminosity of source with hue and saturation of destination
+
+ kLastCoeffMode = kScreen, //!< last porter duff blend mode
+ kLastSeparableMode = kMultiply, //!< last blend mode operating separately on components
+ kLastMode = kLuminosity, //!< last valid value
+};
+
+/**
+ * For Porter-Duff SkBlendModes (those <= kLastCoeffMode), these coefficients describe the blend
+ * equation used. Coefficient-based blend modes specify an equation:
+ * ('dstCoeff' * dst + 'srcCoeff' * src), where the coefficient values are constants, functions of
+ * the src or dst alpha, or functions of the src or dst color.
+ */
+enum class SkBlendModeCoeff {
+ kZero, /** 0 */
+ kOne, /** 1 */
+ kSC, /** src color */
+ kISC, /** inverse src color (i.e. 1 - sc) */
+ kDC, /** dst color */
+ kIDC, /** inverse dst color (i.e. 1 - dc) */
+ kSA, /** src alpha */
+ kISA, /** inverse src alpha (i.e. 1 - sa) */
+ kDA, /** dst alpha */
+ kIDA, /** inverse dst alpha (i.e. 1 - da) */
+
+ kCoeffCount
+};
+
+/**
+ * Returns true if 'mode' is a coefficient-based blend mode (<= kLastCoeffMode). If true is
+ * returned, the mode's src and dst coefficient functions are set in 'src' and 'dst'.
+ */
+SK_API bool SkBlendMode_AsCoeff(SkBlendMode mode, SkBlendModeCoeff* src, SkBlendModeCoeff* dst);
+
+
+/** Returns name of blendMode as null-terminated C string.
+
+ @return C string
+*/
+SK_API const char* SkBlendMode_Name(SkBlendMode blendMode);
+
+#endif
diff --git a/src/deps/skia/include/core/SkBlender.h b/src/deps/skia/include/core/SkBlender.h
new file mode 100644
index 000000000..7acba87f5
--- /dev/null
+++ b/src/deps/skia/include/core/SkBlender.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2021 Google LLC
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkBlender_DEFINED
+#define SkBlender_DEFINED
+
+#include "include/core/SkBlendMode.h"
+#include "include/core/SkFlattenable.h"
+
+/**
+ * SkBlender represents a custom blend function in the Skia pipeline. When an SkBlender is
+ * present in a paint, the SkBlendMode is ignored. A blender combines a source color (the
+ * result of our paint) and destination color (from the canvas) into a final color.
+ */
+class SK_API SkBlender : public SkFlattenable {
+public:
+ /**
+ * Create a blender that implements the specified BlendMode.
+ */
+ static sk_sp<SkBlender> Mode(SkBlendMode mode);
+
+private:
+ SkBlender() = default;
+ friend class SkBlenderBase;
+
+ using INHERITED = SkFlattenable;
+};
+
+#endif
diff --git a/src/deps/skia/include/core/SkBlurTypes.h b/src/deps/skia/include/core/SkBlurTypes.h
new file mode 100644
index 000000000..aec37b6e6
--- /dev/null
+++ b/src/deps/skia/include/core/SkBlurTypes.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkBlurTypes_DEFINED
+#define SkBlurTypes_DEFINED
+
+#include "include/core/SkTypes.h"
+
+enum SkBlurStyle : int {
+ kNormal_SkBlurStyle, //!< fuzzy inside and outside
+ kSolid_SkBlurStyle, //!< solid inside, fuzzy outside
+ kOuter_SkBlurStyle, //!< nothing inside, fuzzy outside
+ kInner_SkBlurStyle, //!< fuzzy inside, nothing outside
+
+ kLastEnum_SkBlurStyle = kInner_SkBlurStyle,
+};
+
+#endif
diff --git a/src/deps/skia/include/core/SkCanvas.h b/src/deps/skia/include/core/SkCanvas.h
new file mode 100644
index 000000000..a2867f9bb
--- /dev/null
+++ b/src/deps/skia/include/core/SkCanvas.h
@@ -0,0 +1,2583 @@
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkCanvas_DEFINED
+#define SkCanvas_DEFINED
+
+#include "include/core/SkBlendMode.h"
+#include "include/core/SkClipOp.h"
+#include "include/core/SkColor.h"
+#include "include/core/SkFontTypes.h"
+#include "include/core/SkImageInfo.h"
+#include "include/core/SkM44.h"
+#include "include/core/SkMatrix.h"
+#include "include/core/SkPaint.h"
+#include "include/core/SkPoint.h"
+#include "include/core/SkRasterHandleAllocator.h"
+#include "include/core/SkRect.h"
+#include "include/core/SkRefCnt.h"
+#include "include/core/SkSamplingOptions.h"
+#include "include/core/SkScalar.h"
+#include "include/core/SkSize.h"
+#include "include/core/SkString.h"
+#include "include/core/SkSurfaceProps.h"
+#include "include/core/SkTypes.h"
+#include "include/private/SkDeque.h"
+#include "include/private/SkMacros.h"
+
+#include <cstring>
+#include <memory>
+#include <vector>
+
+#ifndef SK_SUPPORT_LEGACY_GETTOTALMATRIX
+#define SK_SUPPORT_LEGACY_GETTOTALMATRIX
+#endif
+
+class AutoLayerForImageFilter;
+class GrBackendRenderTarget;
+class GrRecordingContext;
+class GrSlug;
+class SkBaseDevice;
+class SkBitmap;
+class SkData;
+class SkDrawable;
+struct SkDrawShadowRec;
+class SkFont;
+class SkGlyphRunBuilder;
+class SkGlyphRunList;
+class SkImage;
+class SkImageFilter;
+class SkPaintFilterCanvas;
+class SkPath;
+class SkPicture;
+class SkPixmap;
+class SkRegion;
+class SkRRect;
+struct SkRSXform;
+struct SkCustomMesh;
+class SkSpecialImage;
+class SkSurface;
+class SkSurface_Base;
+class SkTextBlob;
+class SkVertices;
+
+namespace skstd {
+ template<typename T> class optional;
+}
+
+/** \class SkCanvas
+ SkCanvas provides an interface for drawing, and how the drawing is clipped and transformed.
+ SkCanvas contains a stack of SkMatrix and clip values.
+
+ SkCanvas and SkPaint together provide the state to draw into SkSurface or SkBaseDevice.
+ Each SkCanvas draw call transforms the geometry of the object by the concatenation of all
+ SkMatrix values in the stack. The transformed geometry is clipped by the intersection
+ of all of clip values in the stack. The SkCanvas draw calls use SkPaint to supply drawing
+ state such as color, SkTypeface, text size, stroke width, SkShader and so on.
+
+ To draw to a pixel-based destination, create raster surface or GPU surface.
+ Request SkCanvas from SkSurface to obtain the interface to draw.
+ SkCanvas generated by raster surface draws to memory visible to the CPU.
+ SkCanvas generated by GPU surface uses Vulkan or OpenGL to draw to the GPU.
+
+ To draw to a document, obtain SkCanvas from SVG canvas, document PDF, or SkPictureRecorder.
+ SkDocument based SkCanvas and other SkCanvas subclasses reference SkBaseDevice describing the
+ destination.
+
+ SkCanvas can be constructed to draw to SkBitmap without first creating raster surface.
+ This approach may be deprecated in the future.
+*/
+class SK_API SkCanvas {
+public:
+
+ /** Allocates raster SkCanvas that will draw directly into pixels.
+
+ SkCanvas is returned if all parameters are valid.
+ Valid parameters include:
+ info dimensions are zero or positive;
+ info contains SkColorType and SkAlphaType supported by raster surface;
+ pixels is not nullptr;
+ rowBytes is zero or large enough to contain info width pixels of SkColorType.
+
+ Pass zero for rowBytes to compute rowBytes from info width and size of pixel.
+ If rowBytes is greater than zero, it must be equal to or greater than
+ info width times bytes required for SkColorType.
+
+ Pixel buffer size should be info height times computed rowBytes.
+ Pixels are not initialized.
+ To access pixels after drawing, call flush() or peekPixels().
+
+ @param info width, height, SkColorType, SkAlphaType, SkColorSpace, of raster surface;
+ width, or height, or both, may be zero
+ @param pixels pointer to destination pixels buffer
+ @param rowBytes interval from one SkSurface row to the next, or zero
+ @param props LCD striping orientation and setting for device independent fonts;
+ may be nullptr
+ @return SkCanvas if all parameters are valid; otherwise, nullptr
+ */
+ static std::unique_ptr<SkCanvas> MakeRasterDirect(const SkImageInfo& info, void* pixels,
+ size_t rowBytes,
+ const SkSurfaceProps* props = nullptr);
+
+ /** Allocates raster SkCanvas specified by inline image specification. Subsequent SkCanvas
+ calls draw into pixels.
+ SkColorType is set to kN32_SkColorType.
+ SkAlphaType is set to kPremul_SkAlphaType.
+ To access pixels after drawing, call flush() or peekPixels().
+
+ SkCanvas is returned if all parameters are valid.
+ Valid parameters include:
+ width and height are zero or positive;
+ pixels is not nullptr;
+ rowBytes is zero or large enough to contain width pixels of kN32_SkColorType.
+
+ Pass zero for rowBytes to compute rowBytes from width and size of pixel.
+ If rowBytes is greater than zero, it must be equal to or greater than
+ width times bytes required for SkColorType.
+
+ Pixel buffer size should be height times rowBytes.
+
+ @param width pixel column count on raster surface created; must be zero or greater
+ @param height pixel row count on raster surface created; must be zero or greater
+ @param pixels pointer to destination pixels buffer; buffer size should be height
+ times rowBytes
+ @param rowBytes interval from one SkSurface row to the next, or zero
+ @return SkCanvas if all parameters are valid; otherwise, nullptr
+ */
+ static std::unique_ptr<SkCanvas> MakeRasterDirectN32(int width, int height, SkPMColor* pixels,
+ size_t rowBytes) {
+ return MakeRasterDirect(SkImageInfo::MakeN32Premul(width, height), pixels, rowBytes);
+ }
+
+ /** Creates an empty SkCanvas with no backing device or pixels, with
+ a width and height of zero.
+
+ @return empty SkCanvas
+
+ example: https://fiddle.skia.org/c/@Canvas_empty_constructor
+ */
+ SkCanvas();
+
+ /** Creates SkCanvas of the specified dimensions without a SkSurface.
+ Used by subclasses with custom implementations for draw member functions.
+
+ If props equals nullptr, SkSurfaceProps are created with
+ SkSurfaceProps::InitType settings, which choose the pixel striping
+ direction and order. Since a platform may dynamically change its direction when
+ the device is rotated, and since a platform may have multiple monitors with
+ different characteristics, it is best not to rely on this legacy behavior.
+
+ @param width zero or greater
+ @param height zero or greater
+ @param props LCD striping orientation and setting for device independent fonts;
+ may be nullptr
+ @return SkCanvas placeholder with dimensions
+
+ example: https://fiddle.skia.org/c/@Canvas_int_int_const_SkSurfaceProps_star
+ */
+ SkCanvas(int width, int height, const SkSurfaceProps* props = nullptr);
+
+ /** Private. For internal use only.
+ */
+ explicit SkCanvas(sk_sp<SkBaseDevice> device);
+
+ /** Constructs a canvas that draws into bitmap.
+ Sets kUnknown_SkPixelGeometry in constructed SkSurface.
+
+ SkBitmap is copied so that subsequently editing bitmap will not affect
+ constructed SkCanvas.
+
+ May be deprecated in the future.
+
+ @param bitmap width, height, SkColorType, SkAlphaType, and pixel
+ storage of raster surface
+ @return SkCanvas that can be used to draw into bitmap
+
+ example: https://fiddle.skia.org/c/@Canvas_copy_const_SkBitmap
+ */
+ explicit SkCanvas(const SkBitmap& bitmap);
+
+#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
+ /** Private.
+ */
+ enum class ColorBehavior {
+ kLegacy, //!< placeholder
+ };
+
+ /** Private. For use by Android framework only.
+
+ @param bitmap specifies a bitmap for the canvas to draw into
+ @param behavior specializes this constructor; value is unused
+ @return SkCanvas that can be used to draw into bitmap
+ */
+ SkCanvas(const SkBitmap& bitmap, ColorBehavior behavior);
+#endif
+
+ /** Constructs a canvas that draws into bitmap.
+ Use props to match the device characteristics, like LCD striping.
+
+ bitmap is copied so that subsequently editing bitmap will not affect
+ constructed SkCanvas.
+
+ @param bitmap width, height, SkColorType, SkAlphaType,
+ and pixel storage of raster surface
+ @param props order and orientation of RGB striping; and whether to use
+ device independent fonts
+ @return SkCanvas that can be used to draw into bitmap
+
+ example: https://fiddle.skia.org/c/@Canvas_const_SkBitmap_const_SkSurfaceProps
+ */
+ SkCanvas(const SkBitmap& bitmap, const SkSurfaceProps& props);
+
+ /** Draws saved layers, if any.
+ Frees up resources used by SkCanvas.
+
+ example: https://fiddle.skia.org/c/@Canvas_destructor
+ */
+ virtual ~SkCanvas();
+
+ /** Returns SkImageInfo for SkCanvas. If SkCanvas is not associated with raster surface or
+ GPU surface, returned SkColorType is set to kUnknown_SkColorType.
+
+ @return dimensions and SkColorType of SkCanvas
+
+ example: https://fiddle.skia.org/c/@Canvas_imageInfo
+ */
+ SkImageInfo imageInfo() const;
+
+ /** Copies SkSurfaceProps, if SkCanvas is associated with raster surface or
+ GPU surface, and returns true. Otherwise, returns false and leave props unchanged.
+
+ @param props storage for writable SkSurfaceProps
+ @return true if SkSurfaceProps was copied
+
+ example: https://fiddle.skia.org/c/@Canvas_getProps
+ */
+ bool getProps(SkSurfaceProps* props) const;
+
+ /** Triggers the immediate execution of all pending draw operations.
+ If SkCanvas is associated with GPU surface, resolves all pending GPU operations.
+ If SkCanvas is associated with raster surface, has no effect; raster draw
+ operations are never deferred.
+
+ DEPRECATED: Replace usage with GrDirectContext::flush()
+ */
+ void flush();
+
+ /** Gets the size of the base or root layer in global canvas coordinates. The
+ origin of the base layer is always (0,0). The area available for drawing may be
+ smaller (due to clipping or saveLayer).
+
+ @return integral width and height of base layer
+
+ example: https://fiddle.skia.org/c/@Canvas_getBaseLayerSize
+ */
+ virtual SkISize getBaseLayerSize() const;
+
+ /** Creates SkSurface matching info and props, and associates it with SkCanvas.
+ Returns nullptr if no match found.
+
+ If props is nullptr, matches SkSurfaceProps in SkCanvas. If props is nullptr and SkCanvas
+ does not have SkSurfaceProps, creates SkSurface with default SkSurfaceProps.
+
+ @param info width, height, SkColorType, SkAlphaType, and SkColorSpace
+ @param props SkSurfaceProps to match; may be nullptr to match SkCanvas
+ @return SkSurface matching info and props, or nullptr if no match is available
+
+ example: https://fiddle.skia.org/c/@Canvas_makeSurface
+ */
+ sk_sp<SkSurface> makeSurface(const SkImageInfo& info, const SkSurfaceProps* props = nullptr);
+
+ /** Returns GPU context of the GPU surface associated with SkCanvas.
+
+ @return GPU context, if available; nullptr otherwise
+
+ example: https://fiddle.skia.org/c/@Canvas_recordingContext
+ */
+ virtual GrRecordingContext* recordingContext();
+
+ /** Sometimes a canvas is owned by a surface. If it is, getSurface() will return a bare
+ * pointer to that surface, else this will return nullptr.
+ */
+ SkSurface* getSurface() const;
+
+ /** Returns the pixel base address, SkImageInfo, rowBytes, and origin if the pixels
+ can be read directly. The returned address is only valid
+ while SkCanvas is in scope and unchanged. Any SkCanvas call or SkSurface call
+ may invalidate the returned address and other returned values.
+
+ If pixels are inaccessible, info, rowBytes, and origin are unchanged.
+
+ @param info storage for writable pixels' SkImageInfo; may be nullptr
+ @param rowBytes storage for writable pixels' row bytes; may be nullptr
+ @param origin storage for SkCanvas top layer origin, its top-left corner;
+ may be nullptr
+ @return address of pixels, or nullptr if inaccessible
+
+ example: https://fiddle.skia.org/c/@Canvas_accessTopLayerPixels_a
+ example: https://fiddle.skia.org/c/@Canvas_accessTopLayerPixels_b
+ */
+ void* accessTopLayerPixels(SkImageInfo* info, size_t* rowBytes, SkIPoint* origin = nullptr);
+
+ /** Returns custom context that tracks the SkMatrix and clip.
+
+ Use SkRasterHandleAllocator to blend Skia drawing with custom drawing, typically performed
+ by the host platform user interface. The custom context returned is generated by
+ SkRasterHandleAllocator::MakeCanvas, which creates a custom canvas with raster storage for
+ the drawing destination.
+
+ @return context of custom allocation
+
+ example: https://fiddle.skia.org/c/@Canvas_accessTopRasterHandle
+ */
+ SkRasterHandleAllocator::Handle accessTopRasterHandle() const;
+
+ /** Returns true if SkCanvas has direct access to its pixels.
+
+ Pixels are readable when SkBaseDevice is raster. Pixels are not readable when SkCanvas
+ is returned from GPU surface, returned by SkDocument::beginPage, returned by
+ SkPictureRecorder::beginRecording, or SkCanvas is the base of a utility class
+ like DebugCanvas.
+
+ pixmap is valid only while SkCanvas is in scope and unchanged. Any
+ SkCanvas or SkSurface call may invalidate the pixmap values.
+
+ @param pixmap storage for pixel state if pixels are readable; otherwise, ignored
+ @return true if SkCanvas has direct access to pixels
+
+ example: https://fiddle.skia.org/c/@Canvas_peekPixels
+ */
+ bool peekPixels(SkPixmap* pixmap);
+
+ /** Copies SkRect of pixels from SkCanvas into dstPixels. SkMatrix and clip are
+ ignored.
+
+ Source SkRect corners are (srcX, srcY) and (imageInfo().width(), imageInfo().height()).
+ Destination SkRect corners are (0, 0) and (dstInfo.width(), dstInfo.height()).
+ Copies each readable pixel intersecting both rectangles, without scaling,
+ converting to dstInfo.colorType() and dstInfo.alphaType() if required.
+
+ Pixels are readable when SkBaseDevice is raster, or backed by a GPU.
+ Pixels are not readable when SkCanvas is returned by SkDocument::beginPage,
+ returned by SkPictureRecorder::beginRecording, or SkCanvas is the base of a utility
+ class like DebugCanvas.
+
+ The destination pixel storage must be allocated by the caller.
+
+ Pixel values are converted only if SkColorType and SkAlphaType
+ do not match. Only pixels within both source and destination rectangles
+ are copied. dstPixels contents outside SkRect intersection are unchanged.
+
+ Pass negative values for srcX or srcY to offset pixels across or down destination.
+
+ Does not copy, and returns false if:
+ - Source and destination rectangles do not intersect.
+ - SkCanvas pixels could not be converted to dstInfo.colorType() or dstInfo.alphaType().
+ - SkCanvas pixels are not readable; for instance, SkCanvas is document-based.
+ - dstRowBytes is too small to contain one row of pixels.
+
+ @param dstInfo width, height, SkColorType, and SkAlphaType of dstPixels
+ @param dstPixels storage for pixels; dstInfo.height() times dstRowBytes, or larger
+ @param dstRowBytes size of one destination row; dstInfo.width() times pixel size, or larger
+ @param srcX offset into readable pixels on x-axis; may be negative
+ @param srcY offset into readable pixels on y-axis; may be negative
+ @return true if pixels were copied
+ */
+ bool readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
+ int srcX, int srcY);
+
+ /** Copies SkRect of pixels from SkCanvas into pixmap. SkMatrix and clip are
+ ignored.
+
+ Source SkRect corners are (srcX, srcY) and (imageInfo().width(), imageInfo().height()).
+ Destination SkRect corners are (0, 0) and (pixmap.width(), pixmap.height()).
+ Copies each readable pixel intersecting both rectangles, without scaling,
+ converting to pixmap.colorType() and pixmap.alphaType() if required.
+
+ Pixels are readable when SkBaseDevice is raster, or backed by a GPU.
+ Pixels are not readable when SkCanvas is returned by SkDocument::beginPage,
+ returned by SkPictureRecorder::beginRecording, or SkCanvas is the base of a utility
+ class like DebugCanvas.
+
+ Caller must allocate pixel storage in pixmap if needed.
+
+ Pixel values are converted only if SkColorType and SkAlphaType
+ do not match. Only pixels within both source and destination SkRect
+ are copied. pixmap pixels contents outside SkRect intersection are unchanged.
+
+ Pass negative values for srcX or srcY to offset pixels across or down pixmap.
+
+ Does not copy, and returns false if:
+ - Source and destination rectangles do not intersect.
+ - SkCanvas pixels could not be converted to pixmap.colorType() or pixmap.alphaType().
+ - SkCanvas pixels are not readable; for instance, SkCanvas is document-based.
+ - SkPixmap pixels could not be allocated.
+ - pixmap.rowBytes() is too small to contain one row of pixels.
+
+ @param pixmap storage for pixels copied from SkCanvas
+ @param srcX offset into readable pixels on x-axis; may be negative
+ @param srcY offset into readable pixels on y-axis; may be negative
+ @return true if pixels were copied
+
+ example: https://fiddle.skia.org/c/@Canvas_readPixels_2
+ */
+ bool readPixels(const SkPixmap& pixmap, int srcX, int srcY);
+
+ /** Copies SkRect of pixels from SkCanvas into bitmap. SkMatrix and clip are
+ ignored.
+
+ Source SkRect corners are (srcX, srcY) and (imageInfo().width(), imageInfo().height()).
+ Destination SkRect corners are (0, 0) and (bitmap.width(), bitmap.height()).
+ Copies each readable pixel intersecting both rectangles, without scaling,
+ converting to bitmap.colorType() and bitmap.alphaType() if required.
+
+ Pixels are readable when SkBaseDevice is raster, or backed by a GPU.
+ Pixels are not readable when SkCanvas is returned by SkDocument::beginPage,
+ returned by SkPictureRecorder::beginRecording, or SkCanvas is the base of a utility
+ class like DebugCanvas.
+
+ Caller must allocate pixel storage in bitmap if needed.
+
+ SkBitmap values are converted only if SkColorType and SkAlphaType
+ do not match. Only pixels within both source and destination rectangles
+ are copied. SkBitmap pixels outside SkRect intersection are unchanged.
+
+ Pass negative values for srcX or srcY to offset pixels across or down bitmap.
+
+ Does not copy, and returns false if:
+ - Source and destination rectangles do not intersect.
+ - SkCanvas pixels could not be converted to bitmap.colorType() or bitmap.alphaType().
+ - SkCanvas pixels are not readable; for instance, SkCanvas is document-based.
+ - bitmap pixels could not be allocated.
+ - bitmap.rowBytes() is too small to contain one row of pixels.
+
+ @param bitmap storage for pixels copied from SkCanvas
+ @param srcX offset into readable pixels on x-axis; may be negative
+ @param srcY offset into readable pixels on y-axis; may be negative
+ @return true if pixels were copied
+
+ example: https://fiddle.skia.org/c/@Canvas_readPixels_3
+ */
+ bool readPixels(const SkBitmap& bitmap, int srcX, int srcY);
+
+ /** Copies SkRect from pixels to SkCanvas. SkMatrix and clip are ignored.
+ Source SkRect corners are (0, 0) and (info.width(), info.height()).
+ Destination SkRect corners are (x, y) and
+ (imageInfo().width(), imageInfo().height()).
+
+ Copies each readable pixel intersecting both rectangles, without scaling,
+ converting to imageInfo().colorType() and imageInfo().alphaType() if required.
+
+ Pixels are writable when SkBaseDevice is raster, or backed by a GPU.
+ Pixels are not writable when SkCanvas is returned by SkDocument::beginPage,
+ returned by SkPictureRecorder::beginRecording, or SkCanvas is the base of a utility
+ class like DebugCanvas.
+
+ Pixel values are converted only if SkColorType and SkAlphaType
+ do not match. Only pixels within both source and destination rectangles
+ are copied. SkCanvas pixels outside SkRect intersection are unchanged.
+
+ Pass negative values for x or y to offset pixels to the left or
+ above SkCanvas pixels.
+
+ Does not copy, and returns false if:
+ - Source and destination rectangles do not intersect.
+ - pixels could not be converted to SkCanvas imageInfo().colorType() or
+ imageInfo().alphaType().
+ - SkCanvas pixels are not writable; for instance, SkCanvas is document-based.
+ - rowBytes is too small to contain one row of pixels.
+
+ @param info width, height, SkColorType, and SkAlphaType of pixels
+ @param pixels pixels to copy, of size info.height() times rowBytes, or larger
+ @param rowBytes size of one row of pixels; info.width() times pixel size, or larger
+ @param x offset into SkCanvas writable pixels on x-axis; may be negative
+ @param y offset into SkCanvas writable pixels on y-axis; may be negative
+ @return true if pixels were written to SkCanvas
+
+ example: https://fiddle.skia.org/c/@Canvas_writePixels
+ */
+ bool writePixels(const SkImageInfo& info, const void* pixels, size_t rowBytes, int x, int y);
+
+ /** Copies SkRect from pixels to SkCanvas. SkMatrix and clip are ignored.
+ Source SkRect corners are (0, 0) and (bitmap.width(), bitmap.height()).
+
+ Destination SkRect corners are (x, y) and
+ (imageInfo().width(), imageInfo().height()).
+
+ Copies each readable pixel intersecting both rectangles, without scaling,
+ converting to imageInfo().colorType() and imageInfo().alphaType() if required.
+
+ Pixels are writable when SkBaseDevice is raster, or backed by a GPU.
+ Pixels are not writable when SkCanvas is returned by SkDocument::beginPage,
+ returned by SkPictureRecorder::beginRecording, or SkCanvas is the base of a utility
+ class like DebugCanvas.
+
+ Pixel values are converted only if SkColorType and SkAlphaType
+ do not match. Only pixels within both source and destination rectangles
+ are copied. SkCanvas pixels outside SkRect intersection are unchanged.
+
+ Pass negative values for x or y to offset pixels to the left or
+ above SkCanvas pixels.
+
+ Does not copy, and returns false if:
+ - Source and destination rectangles do not intersect.
+ - bitmap does not have allocated pixels.
+ - bitmap pixels could not be converted to SkCanvas imageInfo().colorType() or
+ imageInfo().alphaType().
+ - SkCanvas pixels are not writable; for instance, SkCanvas is document based.
+ - bitmap pixels are inaccessible; for instance, bitmap wraps a texture.
+
+ @param bitmap contains pixels copied to SkCanvas
+ @param x offset into SkCanvas writable pixels on x-axis; may be negative
+ @param y offset into SkCanvas writable pixels on y-axis; may be negative
+ @return true if pixels were written to SkCanvas
+
+ example: https://fiddle.skia.org/c/@Canvas_writePixels_2
+ example: https://fiddle.skia.org/c/@State_Stack_a
+ example: https://fiddle.skia.org/c/@State_Stack_b
+ */
+ bool writePixels(const SkBitmap& bitmap, int x, int y);
+
+ /** Saves SkMatrix and clip.
+ Calling restore() discards changes to SkMatrix and clip,
+ restoring the SkMatrix and clip to their state when save() was called.
+
+ SkMatrix may be changed by translate(), scale(), rotate(), skew(), concat(), setMatrix(),
+ and resetMatrix(). Clip may be changed by clipRect(), clipRRect(), clipPath(), clipRegion().
+
+ Saved SkCanvas state is put on a stack; multiple calls to save() should be balance
+ by an equal number of calls to restore().
+
+ Call restoreToCount() with result to restore this and subsequent saves.
+
+ @return depth of saved stack
+
+ example: https://fiddle.skia.org/c/@Canvas_save
+ */
+ int save();
+
+ /** Saves SkMatrix and clip, and allocates a SkBitmap for subsequent drawing.
+ Calling restore() discards changes to SkMatrix and clip, and draws the SkBitmap.
+
+ SkMatrix may be changed by translate(), scale(), rotate(), skew(), concat(),
+ setMatrix(), and resetMatrix(). Clip may be changed by clipRect(), clipRRect(),
+ clipPath(), clipRegion().
+
+ SkRect bounds suggests but does not define the SkBitmap size. To clip drawing to
+ a specific rectangle, use clipRect().
+
+ Optional SkPaint paint applies alpha, SkColorFilter, SkImageFilter, and
+ SkBlendMode when restore() is called.
+
+ Call restoreToCount() with returned value to restore this and subsequent saves.
+
+ @param bounds hint to limit the size of the layer; may be nullptr
+ @param paint graphics state for layer; may be nullptr
+ @return depth of saved stack
+
+ example: https://fiddle.skia.org/c/@Canvas_saveLayer
+ example: https://fiddle.skia.org/c/@Canvas_saveLayer_4
+ */
+ int saveLayer(const SkRect* bounds, const SkPaint* paint);
+
+ /** Saves SkMatrix and clip, and allocates a SkBitmap for subsequent drawing.
+ Calling restore() discards changes to SkMatrix and clip, and draws the SkBitmap.
+
+ SkMatrix may be changed by translate(), scale(), rotate(), skew(), concat(),
+ setMatrix(), and resetMatrix(). Clip may be changed by clipRect(), clipRRect(),
+ clipPath(), clipRegion().
+
+ SkRect bounds suggests but does not define the layer size. To clip drawing to
+ a specific rectangle, use clipRect().
+
+ Optional SkPaint paint applies alpha, SkColorFilter, SkImageFilter, and
+ SkBlendMode when restore() is called.
+
+ Call restoreToCount() with returned value to restore this and subsequent saves.
+
+ @param bounds hint to limit the size of layer; may be nullptr
+ @param paint graphics state for layer; may be nullptr
+ @return depth of saved stack
+ */
+ int saveLayer(const SkRect& bounds, const SkPaint* paint) {
+ return this->saveLayer(&bounds, paint);
+ }
+
+ /** Saves SkMatrix and clip, and allocates SkBitmap for subsequent drawing.
+
+ Calling restore() discards changes to SkMatrix and clip,
+ and blends layer with alpha opacity onto prior layer.
+
+ SkMatrix may be changed by translate(), scale(), rotate(), skew(), concat(),
+ setMatrix(), and resetMatrix(). Clip may be changed by clipRect(), clipRRect(),
+ clipPath(), clipRegion().
+
+ SkRect bounds suggests but does not define layer size. To clip drawing to
+ a specific rectangle, use clipRect().
+
+ alpha of zero is fully transparent, 255 is fully opaque.
+
+ Call restoreToCount() with returned value to restore this and subsequent saves.
+
+ @param bounds hint to limit the size of layer; may be nullptr
+ @param alpha opacity of layer
+ @return depth of saved stack
+
+ example: https://fiddle.skia.org/c/@Canvas_saveLayerAlpha
+ */
+ int saveLayerAlpha(const SkRect* bounds, U8CPU alpha);
+
+ /** \enum SkCanvas::SaveLayerFlagsSet
+ SaveLayerFlags provides options that may be used in any combination in SaveLayerRec,
+ defining how layer allocated by saveLayer() operates. It may be set to zero,
+ kPreserveLCDText_SaveLayerFlag, kInitWithPrevious_SaveLayerFlag, or both flags.
+ */
+ enum SaveLayerFlagsSet {
+ kPreserveLCDText_SaveLayerFlag = 1 << 1,
+ kInitWithPrevious_SaveLayerFlag = 1 << 2, //!< initializes with previous contents
+ // instead of matching previous layer's colortype, use F16
+ kF16ColorType = 1 << 4,
+ };
+
+ typedef uint32_t SaveLayerFlags;
+
+ /** \struct SkCanvas::SaveLayerRec
+ SaveLayerRec contains the state used to create the layer.
+ */
+ struct SaveLayerRec {
+ /** Sets fBounds, fPaint, and fBackdrop to nullptr. Clears fSaveLayerFlags.
+
+ @return empty SaveLayerRec
+ */
+ SaveLayerRec() {}
+
+ /** Sets fBounds, fPaint, and fSaveLayerFlags; sets fBackdrop to nullptr.
+
+ @param bounds layer dimensions; may be nullptr
+ @param paint applied to layer when overlaying prior layer; may be nullptr
+ @param saveLayerFlags SaveLayerRec options to modify layer
+ @return SaveLayerRec with empty fBackdrop
+ */
+ SaveLayerRec(const SkRect* bounds, const SkPaint* paint, SaveLayerFlags saveLayerFlags = 0)
+ : SaveLayerRec(bounds, paint, nullptr, 1.f, saveLayerFlags) {}
+
+ /** Sets fBounds, fPaint, fBackdrop, and fSaveLayerFlags.
+
+ @param bounds layer dimensions; may be nullptr
+ @param paint applied to layer when overlaying prior layer;
+ may be nullptr
+ @param backdrop If not null, this causes the current layer to be filtered by
+ backdrop, and then drawn into the new layer
+ (respecting the current clip).
+ If null, the new layer is initialized with transparent-black.
+ @param saveLayerFlags SaveLayerRec options to modify layer
+ @return SaveLayerRec fully specified
+ */
+ SaveLayerRec(const SkRect* bounds, const SkPaint* paint, const SkImageFilter* backdrop,
+ SaveLayerFlags saveLayerFlags)
+ : SaveLayerRec(bounds, paint, backdrop, 1.f, saveLayerFlags) {}
+
+ /** hints at layer size limit */
+ const SkRect* fBounds = nullptr;
+
+ /** modifies overlay */
+ const SkPaint* fPaint = nullptr;
+
+ /**
+ * If not null, this triggers the same initialization behavior as setting
+ * kInitWithPrevious_SaveLayerFlag on fSaveLayerFlags: the current layer is copied into
+ * the new layer, rather than initializing the new layer with transparent-black.
+ * This is then filtered by fBackdrop (respecting the current clip).
+ */
+ const SkImageFilter* fBackdrop = nullptr;
+
+ /** preserves LCD text, creates with prior layer contents */
+ SaveLayerFlags fSaveLayerFlags = 0;
+
+ private:
+ friend class SkCanvas;
+ friend class SkCanvasPriv;
+
+ SaveLayerRec(const SkRect* bounds, const SkPaint* paint, const SkImageFilter* backdrop,
+ SkScalar backdropScale, SaveLayerFlags saveLayerFlags)
+ : fBounds(bounds)
+ , fPaint(paint)
+ , fBackdrop(backdrop)
+ , fSaveLayerFlags(saveLayerFlags)
+ , fExperimentalBackdropScale(backdropScale) {}
+
+ // Relative scale factor that the image content used to initialize the layer when the
+ // kInitFromPrevious flag or a backdrop filter is used.
+ SkScalar fExperimentalBackdropScale = 1.f;
+ };
+
+ /** Saves SkMatrix and clip, and allocates SkBitmap for subsequent drawing.
+
+ Calling restore() discards changes to SkMatrix and clip,
+ and blends SkBitmap with alpha opacity onto the prior layer.
+
+ SkMatrix may be changed by translate(), scale(), rotate(), skew(), concat(),
+ setMatrix(), and resetMatrix(). Clip may be changed by clipRect(), clipRRect(),
+ clipPath(), clipRegion().
+
+ SaveLayerRec contains the state used to create the layer.
+
+ Call restoreToCount() with returned value to restore this and subsequent saves.
+
+ @param layerRec layer state
+ @return depth of save state stack before this call was made.
+
+ example: https://fiddle.skia.org/c/@Canvas_saveLayer_3
+ */
+ int saveLayer(const SaveLayerRec& layerRec);
+
+ /** Removes changes to SkMatrix and clip since SkCanvas state was
+ last saved. The state is removed from the stack.
+
+ Does nothing if the stack is empty.
+
+ example: https://fiddle.skia.org/c/@AutoCanvasRestore_restore
+
+ example: https://fiddle.skia.org/c/@Canvas_restore
+ */
+ void restore();
+
+ /** Returns the number of saved states, each containing: SkMatrix and clip.
+ Equals the number of save() calls less the number of restore() calls plus one.
+ The save count of a new canvas is one.
+
+ @return depth of save state stack
+
+ example: https://fiddle.skia.org/c/@Canvas_getSaveCount
+ */
+ int getSaveCount() const;
+
+ /** Restores state to SkMatrix and clip values when save(), saveLayer(),
+ saveLayerPreserveLCDTextRequests(), or saveLayerAlpha() returned saveCount.
+
+ Does nothing if saveCount is greater than state stack count.
+ Restores state to initial values if saveCount is less than or equal to one.
+
+ @param saveCount depth of state stack to restore
+
+ example: https://fiddle.skia.org/c/@Canvas_restoreToCount
+ */
+ void restoreToCount(int saveCount);
+
+ /** Translates SkMatrix by dx along the x-axis and dy along the y-axis.
+
+ Mathematically, replaces SkMatrix with a translation matrix
+ premultiplied with SkMatrix.
+
+ This has the effect of moving the drawing by (dx, dy) before transforming
+ the result with SkMatrix.
+
+ @param dx distance to translate on x-axis
+ @param dy distance to translate on y-axis
+
+ example: https://fiddle.skia.org/c/@Canvas_translate
+ */
+ void translate(SkScalar dx, SkScalar dy);
+
+ /** Scales SkMatrix by sx on the x-axis and sy on the y-axis.
+
+ Mathematically, replaces SkMatrix with a scale matrix
+ premultiplied with SkMatrix.
+
+ This has the effect of scaling the drawing by (sx, sy) before transforming
+ the result with SkMatrix.
+
+ @param sx amount to scale on x-axis
+ @param sy amount to scale on y-axis
+
+ example: https://fiddle.skia.org/c/@Canvas_scale
+ */
+ void scale(SkScalar sx, SkScalar sy);
+
+ /** Rotates SkMatrix by degrees. Positive degrees rotates clockwise.
+
+ Mathematically, replaces SkMatrix with a rotation matrix
+ premultiplied with SkMatrix.
+
+ This has the effect of rotating the drawing by degrees before transforming
+ the result with SkMatrix.
+
+ @param degrees amount to rotate, in degrees
+
+ example: https://fiddle.skia.org/c/@Canvas_rotate
+ */
+ void rotate(SkScalar degrees);
+
+ /** Rotates SkMatrix by degrees about a point at (px, py). Positive degrees rotates
+ clockwise.
+
+ Mathematically, constructs a rotation matrix; premultiplies the rotation matrix by
+ a translation matrix; then replaces SkMatrix with the resulting matrix
+ premultiplied with SkMatrix.
+
+ This has the effect of rotating the drawing about a given point before
+ transforming the result with SkMatrix.
+
+ @param degrees amount to rotate, in degrees
+ @param px x-axis value of the point to rotate about
+ @param py y-axis value of the point to rotate about
+
+ example: https://fiddle.skia.org/c/@Canvas_rotate_2
+ */
+ void rotate(SkScalar degrees, SkScalar px, SkScalar py);
+
+ /** Skews SkMatrix by sx on the x-axis and sy on the y-axis. A positive value of sx
+ skews the drawing right as y-axis values increase; a positive value of sy skews
+ the drawing down as x-axis values increase.
+
+ Mathematically, replaces SkMatrix with a skew matrix premultiplied with SkMatrix.
+
+ This has the effect of skewing the drawing by (sx, sy) before transforming
+ the result with SkMatrix.
+
+ @param sx amount to skew on x-axis
+ @param sy amount to skew on y-axis
+
+ example: https://fiddle.skia.org/c/@Canvas_skew
+ */
+ void skew(SkScalar sx, SkScalar sy);
+
+ /** Replaces SkMatrix with matrix premultiplied with existing SkMatrix.
+
+ This has the effect of transforming the drawn geometry by matrix, before
+ transforming the result with existing SkMatrix.
+
+ @param matrix matrix to premultiply with existing SkMatrix
+
+ example: https://fiddle.skia.org/c/@Canvas_concat
+ */
+ void concat(const SkMatrix& matrix);
+ void concat(const SkM44&);
+
+ /** Replaces SkMatrix with matrix.
+ Unlike concat(), any prior matrix state is overwritten.
+
+ @param matrix matrix to copy, replacing existing SkMatrix
+
+ example: https://fiddle.skia.org/c/@Canvas_setMatrix
+ */
+ void setMatrix(const SkM44& matrix);
+
+ // DEPRECATED -- use SkM44 version
+ void setMatrix(const SkMatrix& matrix);
+
+ /** Sets SkMatrix to the identity matrix.
+ Any prior matrix state is overwritten.
+
+ example: https://fiddle.skia.org/c/@Canvas_resetMatrix
+ */
+ void resetMatrix();
+
+ /** Replaces clip with the intersection or difference of clip and rect,
+ with an aliased or anti-aliased clip edge. rect is transformed by SkMatrix
+ before it is combined with clip.
+
+ @param rect SkRect to combine with clip
+ @param op SkClipOp to apply to clip
+ @param doAntiAlias true if clip is to be anti-aliased
+
+ example: https://fiddle.skia.org/c/@Canvas_clipRect
+ */
+ void clipRect(const SkRect& rect, SkClipOp op, bool doAntiAlias);
+
+ /** Replaces clip with the intersection or difference of clip and rect.
+ Resulting clip is aliased; pixels are fully contained by the clip.
+ rect is transformed by SkMatrix before it is combined with clip.
+
+ @param rect SkRect to combine with clip
+ @param op SkClipOp to apply to clip
+ */
+ void clipRect(const SkRect& rect, SkClipOp op) {
+ this->clipRect(rect, op, false);
+ }
+
+ /** Replaces clip with the intersection of clip and rect.
+ Resulting clip is aliased; pixels are fully contained by the clip.
+ rect is transformed by SkMatrix
+ before it is combined with clip.
+
+ @param rect SkRect to combine with clip
+ @param doAntiAlias true if clip is to be anti-aliased
+ */
+ void clipRect(const SkRect& rect, bool doAntiAlias = false) {
+ this->clipRect(rect, SkClipOp::kIntersect, doAntiAlias);
+ }
+
+ void clipIRect(const SkIRect& irect, SkClipOp op = SkClipOp::kIntersect) {
+ this->clipRect(SkRect::Make(irect), op, false);
+ }
+
+ /** Sets the maximum clip rectangle, which can be set by clipRect(), clipRRect() and
+ clipPath() and intersect the current clip with the specified rect.
+ The maximum clip affects only future clipping operations; it is not retroactive.
+ The clip restriction is not recorded in pictures.
+
+ Pass an empty rect to disable maximum clip.
+ This private API is for use by Android framework only.
+
+ DEPRECATED: Replace usage with SkAndroidFrameworkUtils::replaceClip()
+
+ @param rect maximum allowed clip in device coordinates
+ */
+ void androidFramework_setDeviceClipRestriction(const SkIRect& rect);
+
+ /** Replaces clip with the intersection or difference of clip and rrect,
+ with an aliased or anti-aliased clip edge.
+ rrect is transformed by SkMatrix
+ before it is combined with clip.
+
+ @param rrect SkRRect to combine with clip
+ @param op SkClipOp to apply to clip
+ @param doAntiAlias true if clip is to be anti-aliased
+
+ example: https://fiddle.skia.org/c/@Canvas_clipRRect
+ */
+ void clipRRect(const SkRRect& rrect, SkClipOp op, bool doAntiAlias);
+
+ /** Replaces clip with the intersection or difference of clip and rrect.
+ Resulting clip is aliased; pixels are fully contained by the clip.
+ rrect is transformed by SkMatrix before it is combined with clip.
+
+ @param rrect SkRRect to combine with clip
+ @param op SkClipOp to apply to clip
+ */
+ void clipRRect(const SkRRect& rrect, SkClipOp op) {
+ this->clipRRect(rrect, op, false);
+ }
+
+ /** Replaces clip with the intersection of clip and rrect,
+ with an aliased or anti-aliased clip edge.
+ rrect is transformed by SkMatrix before it is combined with clip.
+
+ @param rrect SkRRect to combine with clip
+ @param doAntiAlias true if clip is to be anti-aliased
+ */
+ void clipRRect(const SkRRect& rrect, bool doAntiAlias = false) {
+ this->clipRRect(rrect, SkClipOp::kIntersect, doAntiAlias);
+ }
+
+ /** Replaces clip with the intersection or difference of clip and path,
+ with an aliased or anti-aliased clip edge. SkPath::FillType determines if path
+ describes the area inside or outside its contours; and if path contour overlaps
+ itself or another path contour, whether the overlaps form part of the area.
+ path is transformed by SkMatrix before it is combined with clip.
+
+ @param path SkPath to combine with clip
+ @param op SkClipOp to apply to clip
+ @param doAntiAlias true if clip is to be anti-aliased
+
+ example: https://fiddle.skia.org/c/@Canvas_clipPath
+ */
+ void clipPath(const SkPath& path, SkClipOp op, bool doAntiAlias);
+
+ /** Replaces clip with the intersection or difference of clip and path.
+ Resulting clip is aliased; pixels are fully contained by the clip.
+ SkPath::FillType determines if path
+ describes the area inside or outside its contours; and if path contour overlaps
+ itself or another path contour, whether the overlaps form part of the area.
+ path is transformed by SkMatrix
+ before it is combined with clip.
+
+ @param path SkPath to combine with clip
+ @param op SkClipOp to apply to clip
+ */
+ void clipPath(const SkPath& path, SkClipOp op) {
+ this->clipPath(path, op, false);
+ }
+
+ /** Replaces clip with the intersection of clip and path.
+ Resulting clip is aliased; pixels are fully contained by the clip.
+ SkPath::FillType determines if path
+ describes the area inside or outside its contours; and if path contour overlaps
+ itself or another path contour, whether the overlaps form part of the area.
+ path is transformed by SkMatrix before it is combined with clip.
+
+ @param path SkPath to combine with clip
+ @param doAntiAlias true if clip is to be anti-aliased
+ */
+ void clipPath(const SkPath& path, bool doAntiAlias = false) {
+ this->clipPath(path, SkClipOp::kIntersect, doAntiAlias);
+ }
+
+ void clipShader(sk_sp<SkShader>, SkClipOp = SkClipOp::kIntersect);
+
+ /** Replaces clip with the intersection or difference of clip and SkRegion deviceRgn.
+ Resulting clip is aliased; pixels are fully contained by the clip.
+ deviceRgn is unaffected by SkMatrix.
+
+ @param deviceRgn SkRegion to combine with clip
+ @param op SkClipOp to apply to clip
+
+ example: https://fiddle.skia.org/c/@Canvas_clipRegion
+ */
+ void clipRegion(const SkRegion& deviceRgn, SkClipOp op = SkClipOp::kIntersect);
+
+ /** Returns true if SkRect rect, transformed by SkMatrix, can be quickly determined to be
+ outside of clip. May return false even though rect is outside of clip.
+
+ Use to check if an area to be drawn is clipped out, to skip subsequent draw calls.
+
+ @param rect SkRect to compare with clip
+ @return true if rect, transformed by SkMatrix, does not intersect clip
+
+ example: https://fiddle.skia.org/c/@Canvas_quickReject
+ */
+ bool quickReject(const SkRect& rect) const;
+
+ /** Returns true if path, transformed by SkMatrix, can be quickly determined to be
+ outside of clip. May return false even though path is outside of clip.
+
+ Use to check if an area to be drawn is clipped out, to skip subsequent draw calls.
+
+ @param path SkPath to compare with clip
+ @return true if path, transformed by SkMatrix, does not intersect clip
+
+ example: https://fiddle.skia.org/c/@Canvas_quickReject_2
+ */
+ bool quickReject(const SkPath& path) const;
+
+ /** Returns bounds of clip, transformed by inverse of SkMatrix. If clip is empty,
+ return SkRect::MakeEmpty, where all SkRect sides equal zero.
+
+ SkRect returned is outset by one to account for partial pixel coverage if clip
+ is anti-aliased.
+
+ @return bounds of clip in local coordinates
+
+ example: https://fiddle.skia.org/c/@Canvas_getLocalClipBounds
+ */
+ SkRect getLocalClipBounds() const;
+
+ /** Returns bounds of clip, transformed by inverse of SkMatrix. If clip is empty,
+ return false, and set bounds to SkRect::MakeEmpty, where all SkRect sides equal zero.
+
+ bounds is outset by one to account for partial pixel coverage if clip
+ is anti-aliased.
+
+ @param bounds SkRect of clip in local coordinates
+ @return true if clip bounds is not empty
+ */
+ bool getLocalClipBounds(SkRect* bounds) const {
+ *bounds = this->getLocalClipBounds();
+ return !bounds->isEmpty();
+ }
+
+ /** Returns SkIRect bounds of clip, unaffected by SkMatrix. If clip is empty,
+ return SkRect::MakeEmpty, where all SkRect sides equal zero.
+
+ Unlike getLocalClipBounds(), returned SkIRect is not outset.
+
+ @return bounds of clip in SkBaseDevice coordinates
+
+ example: https://fiddle.skia.org/c/@Canvas_getDeviceClipBounds
+ */
+ SkIRect getDeviceClipBounds() const;
+
+ /** Returns SkIRect bounds of clip, unaffected by SkMatrix. If clip is empty,
+ return false, and set bounds to SkRect::MakeEmpty, where all SkRect sides equal zero.
+
+ Unlike getLocalClipBounds(), bounds is not outset.
+
+ @param bounds SkRect of clip in device coordinates
+ @return true if clip bounds is not empty
+ */
+ bool getDeviceClipBounds(SkIRect* bounds) const {
+ *bounds = this->getDeviceClipBounds();
+ return !bounds->isEmpty();
+ }
+
+ /** Fills clip with color color.
+ mode determines how ARGB is combined with destination.
+
+ @param color unpremultiplied ARGB
+ @param mode SkBlendMode used to combine source color and destination
+
+ example: https://fiddle.skia.org/c/@Canvas_drawColor
+ */
+ void drawColor(SkColor color, SkBlendMode mode = SkBlendMode::kSrcOver) {
+ this->drawColor(SkColor4f::FromColor(color), mode);
+ }
+
+ /** Fills clip with color color.
+ mode determines how ARGB is combined with destination.
+
+ @param color SkColor4f representing unpremultiplied color.
+ @param mode SkBlendMode used to combine source color and destination
+ */
+ void drawColor(const SkColor4f& color, SkBlendMode mode = SkBlendMode::kSrcOver);
+
+ /** Fills clip with color color using SkBlendMode::kSrc.
+ This has the effect of replacing all pixels contained by clip with color.
+
+ @param color unpremultiplied ARGB
+ */
+ void clear(SkColor color) {
+ this->clear(SkColor4f::FromColor(color));
+ }
+
+ /** Fills clip with color color using SkBlendMode::kSrc.
+ This has the effect of replacing all pixels contained by clip with color.
+
+ @param color SkColor4f representing unpremultiplied color.
+ */
+ void clear(const SkColor4f& color) {
+ this->drawColor(color, SkBlendMode::kSrc);
+ }
+
+ /** Makes SkCanvas contents undefined. Subsequent calls that read SkCanvas pixels,
+ such as drawing with SkBlendMode, return undefined results. discard() does
+ not change clip or SkMatrix.
+
+ discard() may do nothing, depending on the implementation of SkSurface or SkBaseDevice
+ that created SkCanvas.
+
+ discard() allows optimized performance on subsequent draws by removing
+ cached data associated with SkSurface or SkBaseDevice.
+ It is not necessary to call discard() once done with SkCanvas;
+ any cached data is deleted when owning SkSurface or SkBaseDevice is deleted.
+ */
+ void discard() { this->onDiscard(); }
+
+ /** Fills clip with SkPaint paint. SkPaint components, SkShader,
+ SkColorFilter, SkImageFilter, and SkBlendMode affect drawing;
+ SkMaskFilter and SkPathEffect in paint are ignored.
+
+ @param paint graphics state used to fill SkCanvas
+
+ example: https://fiddle.skia.org/c/@Canvas_drawPaint
+ */
+ void drawPaint(const SkPaint& paint);
+
+ /** \enum SkCanvas::PointMode
+ Selects if an array of points are drawn as discrete points, as lines, or as
+ an open polygon.
+ */
+ enum PointMode {
+ kPoints_PointMode, //!< draw each point separately
+ kLines_PointMode, //!< draw each pair of points as a line segment
+ kPolygon_PointMode, //!< draw the array of points as a open polygon
+ };
+
+ /** Draws pts using clip, SkMatrix and SkPaint paint.
+ count is the number of points; if count is less than one, has no effect.
+ mode may be one of: kPoints_PointMode, kLines_PointMode, or kPolygon_PointMode.
+
+ If mode is kPoints_PointMode, the shape of point drawn depends on paint
+ SkPaint::Cap. If paint is set to SkPaint::kRound_Cap, each point draws a
+ circle of diameter SkPaint stroke width. If paint is set to SkPaint::kSquare_Cap
+ or SkPaint::kButt_Cap, each point draws a square of width and height
+ SkPaint stroke width.
+
+ If mode is kLines_PointMode, each pair of points draws a line segment.
+ One line is drawn for every two points; each point is used once. If count is odd,
+ the final point is ignored.
+
+ If mode is kPolygon_PointMode, each adjacent pair of points draws a line segment.
+ count minus one lines are drawn; the first and last point are used once.
+
+ Each line segment respects paint SkPaint::Cap and SkPaint stroke width.
+ SkPaint::Style is ignored, as if were set to SkPaint::kStroke_Style.
+
+ Always draws each element one at a time; is not affected by
+ SkPaint::Join, and unlike drawPath(), does not create a mask from all points
+ and lines before drawing.
+
+ @param mode whether pts draws points or lines
+ @param count number of points in the array
+ @param pts array of points to draw
+ @param paint stroke, blend, color, and so on, used to draw
+
+ example: https://fiddle.skia.org/c/@Canvas_drawPoints
+ */
+ void drawPoints(PointMode mode, size_t count, const SkPoint pts[], const SkPaint& paint);
+
+ /** Draws point at (x, y) using clip, SkMatrix and SkPaint paint.
+
+ The shape of point drawn depends on paint SkPaint::Cap.
+ If paint is set to SkPaint::kRound_Cap, draw a circle of diameter
+ SkPaint stroke width. If paint is set to SkPaint::kSquare_Cap or SkPaint::kButt_Cap,
+ draw a square of width and height SkPaint stroke width.
+ SkPaint::Style is ignored, as if were set to SkPaint::kStroke_Style.
+
+ @param x left edge of circle or square
+ @param y top edge of circle or square
+ @param paint stroke, blend, color, and so on, used to draw
+
+ example: https://fiddle.skia.org/c/@Canvas_drawPoint
+ */
+ void drawPoint(SkScalar x, SkScalar y, const SkPaint& paint);
+
+ /** Draws point p using clip, SkMatrix and SkPaint paint.
+
+ The shape of point drawn depends on paint SkPaint::Cap.
+ If paint is set to SkPaint::kRound_Cap, draw a circle of diameter
+ SkPaint stroke width. If paint is set to SkPaint::kSquare_Cap or SkPaint::kButt_Cap,
+ draw a square of width and height SkPaint stroke width.
+ SkPaint::Style is ignored, as if were set to SkPaint::kStroke_Style.
+
+ @param p top-left edge of circle or square
+ @param paint stroke, blend, color, and so on, used to draw
+ */
+ void drawPoint(SkPoint p, const SkPaint& paint) {
+ this->drawPoint(p.x(), p.y(), paint);
+ }
+
+ /** Draws line segment from (x0, y0) to (x1, y1) using clip, SkMatrix, and SkPaint paint.
+ In paint: SkPaint stroke width describes the line thickness;
+ SkPaint::Cap draws the end rounded or square;
+ SkPaint::Style is ignored, as if were set to SkPaint::kStroke_Style.
+
+ @param x0 start of line segment on x-axis
+ @param y0 start of line segment on y-axis
+ @param x1 end of line segment on x-axis
+ @param y1 end of line segment on y-axis
+ @param paint stroke, blend, color, and so on, used to draw
+
+ example: https://fiddle.skia.org/c/@Canvas_drawLine
+ */
+ void drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1, const SkPaint& paint);
+
+ /** Draws line segment from p0 to p1 using clip, SkMatrix, and SkPaint paint.
+ In paint: SkPaint stroke width describes the line thickness;
+ SkPaint::Cap draws the end rounded or square;
+ SkPaint::Style is ignored, as if were set to SkPaint::kStroke_Style.
+
+ @param p0 start of line segment
+ @param p1 end of line segment
+ @param paint stroke, blend, color, and so on, used to draw
+ */
+ void drawLine(SkPoint p0, SkPoint p1, const SkPaint& paint) {
+ this->drawLine(p0.x(), p0.y(), p1.x(), p1.y(), paint);
+ }
+
+ /** Draws SkRect rect using clip, SkMatrix, and SkPaint paint.
+ In paint: SkPaint::Style determines if rectangle is stroked or filled;
+ if stroked, SkPaint stroke width describes the line thickness, and
+ SkPaint::Join draws the corners rounded or square.
+
+ @param rect rectangle to draw
+ @param paint stroke or fill, blend, color, and so on, used to draw
+
+ example: https://fiddle.skia.org/c/@Canvas_drawRect
+ */
+ void drawRect(const SkRect& rect, const SkPaint& paint);
+
+ /** Draws SkIRect rect using clip, SkMatrix, and SkPaint paint.
+ In paint: SkPaint::Style determines if rectangle is stroked or filled;
+ if stroked, SkPaint stroke width describes the line thickness, and
+ SkPaint::Join draws the corners rounded or square.
+
+ @param rect rectangle to draw
+ @param paint stroke or fill, blend, color, and so on, used to draw
+ */
+ void drawIRect(const SkIRect& rect, const SkPaint& paint) {
+ SkRect r;
+ r.set(rect); // promotes the ints to scalars
+ this->drawRect(r, paint);
+ }
+
+ /** Draws SkRegion region using clip, SkMatrix, and SkPaint paint.
+ In paint: SkPaint::Style determines if rectangle is stroked or filled;
+ if stroked, SkPaint stroke width describes the line thickness, and
+ SkPaint::Join draws the corners rounded or square.
+
+ @param region region to draw
+ @param paint SkPaint stroke or fill, blend, color, and so on, used to draw
+
+ example: https://fiddle.skia.org/c/@Canvas_drawRegion
+ */
+ void drawRegion(const SkRegion& region, const SkPaint& paint);
+
+ /** Draws oval oval using clip, SkMatrix, and SkPaint.
+ In paint: SkPaint::Style determines if oval is stroked or filled;
+ if stroked, SkPaint stroke width describes the line thickness.
+
+ @param oval SkRect bounds of oval
+ @param paint SkPaint stroke or fill, blend, color, and so on, used to draw
+
+ example: https://fiddle.skia.org/c/@Canvas_drawOval
+ */
+ void drawOval(const SkRect& oval, const SkPaint& paint);
+
+ /** Draws SkRRect rrect using clip, SkMatrix, and SkPaint paint.
+ In paint: SkPaint::Style determines if rrect is stroked or filled;
+ if stroked, SkPaint stroke width describes the line thickness.
+
+ rrect may represent a rectangle, circle, oval, uniformly rounded rectangle, or
+ may have any combination of positive non-square radii for the four corners.
+
+ @param rrect SkRRect with up to eight corner radii to draw
+ @param paint SkPaint stroke or fill, blend, color, and so on, used to draw
+
+ example: https://fiddle.skia.org/c/@Canvas_drawRRect
+ */
+ void drawRRect(const SkRRect& rrect, const SkPaint& paint);
+
+ /** Draws SkRRect outer and inner
+ using clip, SkMatrix, and SkPaint paint.
+ outer must contain inner or the drawing is undefined.
+ In paint: SkPaint::Style determines if SkRRect is stroked or filled;
+ if stroked, SkPaint stroke width describes the line thickness.
+ If stroked and SkRRect corner has zero length radii, SkPaint::Join can
+ draw corners rounded or square.
+
+ GPU-backed platforms optimize drawing when both outer and inner are
+ concave and outer contains inner. These platforms may not be able to draw
+ SkPath built with identical data as fast.
+
+ @param outer SkRRect outer bounds to draw
+ @param inner SkRRect inner bounds to draw
+ @param paint SkPaint stroke or fill, blend, color, and so on, used to draw
+
+ example: https://fiddle.skia.org/c/@Canvas_drawDRRect_a
+ example: https://fiddle.skia.org/c/@Canvas_drawDRRect_b
+ */
+ void drawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint& paint);
+
+ /** Draws circle at (cx, cy) with radius using clip, SkMatrix, and SkPaint paint.
+ If radius is zero or less, nothing is drawn.
+ In paint: SkPaint::Style determines if circle is stroked or filled;
+ if stroked, SkPaint stroke width describes the line thickness.
+
+ @param cx circle center on the x-axis
+ @param cy circle center on the y-axis
+ @param radius half the diameter of circle
+ @param paint SkPaint stroke or fill, blend, color, and so on, used to draw
+
+ example: https://fiddle.skia.org/c/@Canvas_drawCircle
+ */
+ void drawCircle(SkScalar cx, SkScalar cy, SkScalar radius, const SkPaint& paint);
+
+ /** Draws circle at center with radius using clip, SkMatrix, and SkPaint paint.
+ If radius is zero or less, nothing is drawn.
+ In paint: SkPaint::Style determines if circle is stroked or filled;
+ if stroked, SkPaint stroke width describes the line thickness.
+
+ @param center circle center
+ @param radius half the diameter of circle
+ @param paint SkPaint stroke or fill, blend, color, and so on, used to draw
+ */
+ void drawCircle(SkPoint center, SkScalar radius, const SkPaint& paint) {
+ this->drawCircle(center.x(), center.y(), radius, paint);
+ }
+
+ /** Draws arc using clip, SkMatrix, and SkPaint paint.
+
+ Arc is part of oval bounded by oval, sweeping from startAngle to startAngle plus
+ sweepAngle. startAngle and sweepAngle are in degrees.
+
+ startAngle of zero places start point at the right middle edge of oval.
+ A positive sweepAngle places arc end point clockwise from start point;
+ a negative sweepAngle places arc end point counterclockwise from start point.
+ sweepAngle may exceed 360 degrees, a full circle.
+ If useCenter is true, draw a wedge that includes lines from oval
+ center to arc end points. If useCenter is false, draw arc between end points.
+
+ If SkRect oval is empty or sweepAngle is zero, nothing is drawn.
+
+ @param oval SkRect bounds of oval containing arc to draw
+ @param startAngle angle in degrees where arc begins
+ @param sweepAngle sweep angle in degrees; positive is clockwise
+ @param useCenter if true, include the center of the oval
+ @param paint SkPaint stroke or fill, blend, color, and so on, used to draw
+ */
+ void drawArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle,
+ bool useCenter, const SkPaint& paint);
+
+ /** Draws SkRRect bounded by SkRect rect, with corner radii (rx, ry) using clip,
+ SkMatrix, and SkPaint paint.
+
+ In paint: SkPaint::Style determines if SkRRect is stroked or filled;
+ if stroked, SkPaint stroke width describes the line thickness.
+ If rx or ry are less than zero, they are treated as if they are zero.
+ If rx plus ry exceeds rect width or rect height, radii are scaled down to fit.
+ If rx and ry are zero, SkRRect is drawn as SkRect and if stroked is affected by
+ SkPaint::Join.
+
+ @param rect SkRect bounds of SkRRect to draw
+ @param rx axis length on x-axis of oval describing rounded corners
+ @param ry axis length on y-axis of oval describing rounded corners
+ @param paint stroke, blend, color, and so on, used to draw
+
+ example: https://fiddle.skia.org/c/@Canvas_drawRoundRect
+ */
+ void drawRoundRect(const SkRect& rect, SkScalar rx, SkScalar ry, const SkPaint& paint);
+
+ /** Draws SkPath path using clip, SkMatrix, and SkPaint paint.
+ SkPath contains an array of path contour, each of which may be open or closed.
+
+ In paint: SkPaint::Style determines if SkRRect is stroked or filled:
+ if filled, SkPath::FillType determines whether path contour describes inside or
+ outside of fill; if stroked, SkPaint stroke width describes the line thickness,
+ SkPaint::Cap describes line ends, and SkPaint::Join describes how
+ corners are drawn.
+
+ @param path SkPath to draw
+ @param paint stroke, blend, color, and so on, used to draw
+
+ example: https://fiddle.skia.org/c/@Canvas_drawPath
+ */
+ void drawPath(const SkPath& path, const SkPaint& paint);
+
+ void drawImage(const SkImage* image, SkScalar left, SkScalar top) {
+ this->drawImage(image, left, top, SkSamplingOptions(), nullptr);
+ }
+ void drawImage(const sk_sp<SkImage>& image, SkScalar left, SkScalar top) {
+ this->drawImage(image.get(), left, top, SkSamplingOptions(), nullptr);
+ }
+
+ /** \enum SkCanvas::SrcRectConstraint
+ SrcRectConstraint controls the behavior at the edge of source SkRect,
+ provided to drawImageRect() when there is any filtering. If kStrict is set,
+ then extra code is used to ensure it nevers samples outside of the src-rect.
+ */
+ enum SrcRectConstraint {
+ kStrict_SrcRectConstraint, //!< sample only inside bounds; slower
+ kFast_SrcRectConstraint, //!< sample outside bounds; faster
+ };
+
+ void drawImage(const SkImage*, SkScalar x, SkScalar y, const SkSamplingOptions&,
+ const SkPaint* = nullptr);
+ void drawImage(const sk_sp<SkImage>& image, SkScalar x, SkScalar y,
+ const SkSamplingOptions& sampling, const SkPaint* paint = nullptr) {
+ this->drawImage(image.get(), x, y, sampling, paint);
+ }
+ void drawImageRect(const SkImage*, const SkRect& src, const SkRect& dst,
+ const SkSamplingOptions&, const SkPaint*, SrcRectConstraint);
+ void drawImageRect(const SkImage*, const SkRect& dst, const SkSamplingOptions&,
+ const SkPaint* = nullptr);
+ void drawImageRect(const sk_sp<SkImage>& image, const SkRect& src, const SkRect& dst,
+ const SkSamplingOptions& sampling, const SkPaint* paint,
+ SrcRectConstraint constraint) {
+ this->drawImageRect(image.get(), src, dst, sampling, paint, constraint);
+ }
+ void drawImageRect(const sk_sp<SkImage>& image, const SkRect& dst,
+ const SkSamplingOptions& sampling, const SkPaint* paint = nullptr) {
+ this->drawImageRect(image.get(), dst, sampling, paint);
+ }
+
+ /** Draws SkImage image stretched proportionally to fit into SkRect dst.
+ SkIRect center divides the image into nine sections: four sides, four corners, and
+ the center. Corners are unmodified or scaled down proportionately if their sides
+ are larger than dst; center and four sides are scaled to fit remaining space, if any.
+
+ Additionally transform draw using clip, SkMatrix, and optional SkPaint paint.
+
+ If SkPaint paint is supplied, apply SkColorFilter, alpha, SkImageFilter, and
+ SkBlendMode. If image is kAlpha_8_SkColorType, apply SkShader.
+ If paint contains SkMaskFilter, generate mask from image bounds.
+ Any SkMaskFilter on paint is ignored as is paint anti-aliasing state.
+
+ If generated mask extends beyond image bounds, replicate image edge colors, just
+ as SkShader made from SkImage::makeShader with SkShader::kClamp_TileMode set
+ replicates the image edge color when it samples outside of its bounds.
+
+ @param image SkImage containing pixels, dimensions, and format
+ @param center SkIRect edge of image corners and sides
+ @param dst destination SkRect of image to draw to
+ @param filter what technique to use when sampling the image
+ @param paint SkPaint containing SkBlendMode, SkColorFilter, SkImageFilter,
+ and so on; or nullptr
+ */
+ void drawImageNine(const SkImage* image, const SkIRect& center, const SkRect& dst,
+ SkFilterMode filter, const SkPaint* paint = nullptr);
+
+ /** \struct SkCanvas::Lattice
+ SkCanvas::Lattice divides SkBitmap or SkImage into a rectangular grid.
+ Grid entries on even columns and even rows are fixed; these entries are
+ always drawn at their original size if the destination is large enough.
+ If the destination side is too small to hold the fixed entries, all fixed
+ entries are proportionately scaled down to fit.
+ The grid entries not on even columns and rows are scaled to fit the
+ remaining space, if any.
+ */
+ struct Lattice {
+
+ /** \enum SkCanvas::Lattice::RectType
+ Optional setting per rectangular grid entry to make it transparent,
+ or to fill the grid entry with a color.
+ */
+ enum RectType : uint8_t {
+ kDefault = 0, //!< draws SkBitmap into lattice rectangle
+ kTransparent, //!< skips lattice rectangle by making it transparent
+ kFixedColor, //!< draws one of fColors into lattice rectangle
+ };
+
+ const int* fXDivs; //!< x-axis values dividing bitmap
+ const int* fYDivs; //!< y-axis values dividing bitmap
+ const RectType* fRectTypes; //!< array of fill types
+ int fXCount; //!< number of x-coordinates
+ int fYCount; //!< number of y-coordinates
+ const SkIRect* fBounds; //!< source bounds to draw from
+ const SkColor* fColors; //!< array of colors
+ };
+
+ /** Draws SkImage image stretched proportionally to fit into SkRect dst.
+
+ SkCanvas::Lattice lattice divides image into a rectangular grid.
+ Each intersection of an even-numbered row and column is fixed;
+ fixed lattice elements never scale larger than their initial
+ size and shrink proportionately when all fixed elements exceed the bitmap
+ dimension. All other grid elements scale to fill the available space, if any.
+
+ Additionally transform draw using clip, SkMatrix, and optional SkPaint paint.
+
+ If SkPaint paint is supplied, apply SkColorFilter, alpha, SkImageFilter, and
+ SkBlendMode. If image is kAlpha_8_SkColorType, apply SkShader.
+ If paint contains SkMaskFilter, generate mask from image bounds.
+ Any SkMaskFilter on paint is ignored as is paint anti-aliasing state.
+
+ If generated mask extends beyond bitmap bounds, replicate bitmap edge colors,
+ just as SkShader made from SkShader::MakeBitmapShader with
+ SkShader::kClamp_TileMode set replicates the bitmap edge color when it samples
+ outside of its bounds.
+
+ @param image SkImage containing pixels, dimensions, and format
+ @param lattice division of bitmap into fixed and variable rectangles
+ @param dst destination SkRect of image to draw to
+ @param filter what technique to use when sampling the image
+ @param paint SkPaint containing SkBlendMode, SkColorFilter, SkImageFilter,
+ and so on; or nullptr
+ */
+ void drawImageLattice(const SkImage* image, const Lattice& lattice, const SkRect& dst,
+ SkFilterMode filter, const SkPaint* paint = nullptr);
+ void drawImageLattice(const SkImage* image, const Lattice& lattice, const SkRect& dst) {
+ this->drawImageLattice(image, lattice, dst, SkFilterMode::kNearest, nullptr);
+ }
+
+ /**
+ * Experimental. Controls anti-aliasing of each edge of images in an image-set.
+ */
+ enum QuadAAFlags : unsigned {
+ kLeft_QuadAAFlag = 0b0001,
+ kTop_QuadAAFlag = 0b0010,
+ kRight_QuadAAFlag = 0b0100,
+ kBottom_QuadAAFlag = 0b1000,
+
+ kNone_QuadAAFlags = 0b0000,
+ kAll_QuadAAFlags = 0b1111,
+ };
+
+ /** This is used by the experimental API below. */
+ struct SK_API ImageSetEntry {
+ ImageSetEntry(sk_sp<const SkImage> image, const SkRect& srcRect, const SkRect& dstRect,
+ int matrixIndex, float alpha, unsigned aaFlags, bool hasClip);
+
+ ImageSetEntry(sk_sp<const SkImage> image, const SkRect& srcRect, const SkRect& dstRect,
+ float alpha, unsigned aaFlags);
+
+ ImageSetEntry();
+ ~ImageSetEntry();
+ ImageSetEntry(const ImageSetEntry&);
+ ImageSetEntry& operator=(const ImageSetEntry&);
+
+ sk_sp<const SkImage> fImage;
+ SkRect fSrcRect;
+ SkRect fDstRect;
+ int fMatrixIndex = -1; // Index into the preViewMatrices arg, or < 0
+ float fAlpha = 1.f;
+ unsigned fAAFlags = kNone_QuadAAFlags; // QuadAAFlags
+ bool fHasClip = false; // True to use next 4 points in dstClip arg as quad
+ };
+
+ /**
+ * This is an experimental API for the SkiaRenderer Chromium project, and its API will surely
+ * evolve if it is not removed outright.
+ *
+ * This behaves very similarly to drawRect() combined with a clipPath() formed by clip
+ * quadrilateral. 'rect' and 'clip' are in the same coordinate space. If 'clip' is null, then it
+ * is as if the rectangle was not clipped (or, alternatively, clipped to itself). If not null,
+ * then it must provide 4 points.
+ *
+ * In addition to combining the draw and clipping into one operation, this function adds the
+ * additional capability of controlling each of the rectangle's edges anti-aliasing
+ * independently. The edges of the clip will respect the per-edge AA flags. It is required that
+ * 'clip' be contained inside 'rect'. In terms of mapping to edge labels, the 'clip' points
+ * should be ordered top-left, top-right, bottom-right, bottom-left so that the edge between [0]
+ * and [1] is "top", [1] and [2] is "right", [2] and [3] is "bottom", and [3] and [0] is "left".
+ * This ordering matches SkRect::toQuad().
+ *
+ * This API only draws solid color, filled rectangles so it does not accept a full SkPaint.
+ */
+ void experimental_DrawEdgeAAQuad(const SkRect& rect, const SkPoint clip[4], QuadAAFlags aaFlags,
+ const SkColor4f& color, SkBlendMode mode);
+ void experimental_DrawEdgeAAQuad(const SkRect& rect, const SkPoint clip[4], QuadAAFlags aaFlags,
+ SkColor color, SkBlendMode mode) {
+ this->experimental_DrawEdgeAAQuad(rect, clip, aaFlags, SkColor4f::FromColor(color), mode);
+ }
+
+ /**
+ * This is an bulk variant of experimental_DrawEdgeAAQuad() that renders 'cnt' textured quads.
+ * For each entry, 'fDstRect' is rendered with its clip (determined by entry's 'fHasClip' and
+ * the current index in 'dstClip'). The entry's fImage is applied to the destination rectangle
+ * by sampling from 'fSrcRect' sub-image. The corners of 'fSrcRect' map to the corners of
+ * 'fDstRect', just like in drawImageRect(), and they will be properly interpolated when
+ * applying a clip.
+ *
+ * Like experimental_DrawEdgeAAQuad(), each entry can specify edge AA flags that apply to both
+ * the destination rect and its clip.
+ *
+ * If provided, the 'dstClips' array must have length equal 4 * the number of entries with
+ * fHasClip true. If 'dstClips' is null, every entry must have 'fHasClip' set to false. The
+ * destination clip coordinates will be read consecutively with the image set entries, advancing
+ * by 4 points every time an entry with fHasClip is passed.
+ *
+ * This entry point supports per-entry manipulations to the canvas's current matrix. If an
+ * entry provides 'fMatrixIndex' >= 0, it will be drawn as if the canvas's CTM was
+ * canvas->getTotalMatrix() * preViewMatrices[fMatrixIndex]. If 'fMatrixIndex' is less than 0,
+ * the pre-view matrix transform is implicitly the identity, so it will be drawn using just the
+ * current canvas matrix. The pre-view matrix modifies the canvas's view matrix, it does not
+ * affect the local coordinates of each entry.
+ *
+ * An optional paint may be provided, which supports the same subset of features usable with
+ * drawImageRect (i.e. assumed to be filled and no path effects). When a paint is provided, the
+ * image set is drawn as if each image used the applied paint independently, so each is affected
+ * by the image, color, and/or mask filter.
+ */
+ void experimental_DrawEdgeAAImageSet(const ImageSetEntry imageSet[], int cnt,
+ const SkPoint dstClips[], const SkMatrix preViewMatrices[],
+ const SkSamplingOptions&, const SkPaint* paint = nullptr,
+ SrcRectConstraint constraint = kStrict_SrcRectConstraint);
+
+ /** Draws text, with origin at (x, y), using clip, SkMatrix, SkFont font,
+ and SkPaint paint.
+
+ When encoding is SkTextEncoding::kUTF8, SkTextEncoding::kUTF16, or
+ SkTextEncoding::kUTF32, this function uses the default
+ character-to-glyph mapping from the SkTypeface in font. It does not
+ perform typeface fallback for characters not found in the SkTypeface.
+ It does not perform kerning or other complex shaping; glyphs are
+ positioned based on their default advances.
+
+ Text meaning depends on SkTextEncoding.
+
+ Text size is affected by SkMatrix and SkFont text size. Default text
+ size is 12 point.
+
+ All elements of paint: SkPathEffect, SkMaskFilter, SkShader,
+ SkColorFilter, and SkImageFilter; apply to text. By
+ default, draws filled black glyphs.
+
+ @param text character code points or glyphs drawn
+ @param byteLength byte length of text array
+ @param encoding text encoding used in the text array
+ @param x start of text on x-axis
+ @param y start of text on y-axis
+ @param font typeface, text size and so, used to describe the text
+ @param paint blend, color, and so on, used to draw
+ */
+ void drawSimpleText(const void* text, size_t byteLength, SkTextEncoding encoding,
+ SkScalar x, SkScalar y, const SkFont& font, const SkPaint& paint);
+
+ /** Draws null terminated string, with origin at (x, y), using clip, SkMatrix,
+ SkFont font, and SkPaint paint.
+
+ This function uses the default character-to-glyph mapping from the
+ SkTypeface in font. It does not perform typeface fallback for
+ characters not found in the SkTypeface. It does not perform kerning;
+ glyphs are positioned based on their default advances.
+
+ String str is encoded as UTF-8.
+
+ Text size is affected by SkMatrix and font text size. Default text
+ size is 12 point.
+
+ All elements of paint: SkPathEffect, SkMaskFilter, SkShader,
+ SkColorFilter, and SkImageFilter; apply to text. By
+ default, draws filled black glyphs.
+
+ @param str character code points drawn,
+ ending with a char value of zero
+ @param x start of string on x-axis
+ @param y start of string on y-axis
+ @param font typeface, text size and so, used to describe the text
+ @param paint blend, color, and so on, used to draw
+ */
+ void drawString(const char str[], SkScalar x, SkScalar y, const SkFont& font,
+ const SkPaint& paint) {
+ this->drawSimpleText(str, strlen(str), SkTextEncoding::kUTF8, x, y, font, paint);
+ }
+
+ /** Draws SkString, with origin at (x, y), using clip, SkMatrix, SkFont font,
+ and SkPaint paint.
+
+ This function uses the default character-to-glyph mapping from the
+ SkTypeface in font. It does not perform typeface fallback for
+ characters not found in the SkTypeface. It does not perform kerning;
+ glyphs are positioned based on their default advances.
+
+ SkString str is encoded as UTF-8.
+
+ Text size is affected by SkMatrix and SkFont text size. Default text
+ size is 12 point.
+
+ All elements of paint: SkPathEffect, SkMaskFilter, SkShader,
+ SkColorFilter, and SkImageFilter; apply to text. By
+ default, draws filled black glyphs.
+
+ @param str character code points drawn,
+ ending with a char value of zero
+ @param x start of string on x-axis
+ @param y start of string on y-axis
+ @param font typeface, text size and so, used to describe the text
+ @param paint blend, color, and so on, used to draw
+ */
+ void drawString(const SkString& str, SkScalar x, SkScalar y, const SkFont& font,
+ const SkPaint& paint) {
+ this->drawSimpleText(str.c_str(), str.size(), SkTextEncoding::kUTF8, x, y, font, paint);
+ }
+
+ /** Draws count glyphs, at positions relative to origin styled with font and paint with
+ supporting utf8 and cluster information.
+
+ This function draw glyphs at the given positions relative to the given origin.
+ It does not perform typeface fallback for glyphs not found in the SkTypeface in font.
+
+ The drawing obeys the current transform matrix and clipping.
+
+ All elements of paint: SkPathEffect, SkMaskFilter, SkShader,
+ SkColorFilter, and SkImageFilter; apply to text. By
+ default, draws filled black glyphs.
+
+ @param count number of glyphs to draw
+ @param glyphs the array of glyphIDs to draw
+ @param positions where to draw each glyph relative to origin
+ @param clusters array of size count of cluster information
+ @param textByteCount size of the utf8text
+ @param utf8text utf8text supporting information for the glyphs
+ @param origin the origin of all the positions
+ @param font typeface, text size and so, used to describe the text
+ @param paint blend, color, and so on, used to draw
+ */
+ 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);
+
+ /** Draws count glyphs, at positions relative to origin styled with font and paint.
+
+ This function draw glyphs at the given positions relative to the given origin.
+ It does not perform typeface fallback for glyphs not found in the SkTypeface in font.
+
+ The drawing obeys the current transform matrix and clipping.
+
+ All elements of paint: SkPathEffect, SkMaskFilter, SkShader,
+ SkColorFilter, and SkImageFilter; apply to text. By
+ default, draws filled black glyphs.
+
+ @param count number of glyphs to draw
+ @param glyphs the array of glyphIDs to draw
+ @param positions where to draw each glyph relative to origin
+ @param origin the origin of all the positions
+ @param font typeface, text size and so, used to describe the text
+ @param paint blend, color, and so on, used to draw
+ */
+ void drawGlyphs(int count, const SkGlyphID glyphs[], const SkPoint positions[],
+ SkPoint origin, const SkFont& font, const SkPaint& paint);
+
+ /** Draws count glyphs, at positions relative to origin styled with font and paint.
+
+ This function draw glyphs using the given scaling and rotations. They are positioned
+ relative to the given origin. It does not perform typeface fallback for glyphs not found
+ in the SkTypeface in font.
+
+ The drawing obeys the current transform matrix and clipping.
+
+ All elements of paint: SkPathEffect, SkMaskFilter, SkShader,
+ SkColorFilter, and SkImageFilter; apply to text. By
+ default, draws filled black glyphs.
+
+ @param count number of glyphs to draw
+ @param glyphs the array of glyphIDs to draw
+ @param xforms where to draw and orient each glyph
+ @param origin the origin of all the positions
+ @param font typeface, text size and so, used to describe the text
+ @param paint blend, color, and so on, used to draw
+ */
+ void drawGlyphs(int count, const SkGlyphID glyphs[], const SkRSXform xforms[],
+ SkPoint origin, const SkFont& font, const SkPaint& paint);
+
+ /** Draws SkTextBlob blob at (x, y), using clip, SkMatrix, and SkPaint paint.
+
+ blob contains glyphs, their positions, and paint attributes specific to text:
+ SkTypeface, SkPaint text size, SkPaint text scale x,
+ SkPaint text skew x, SkPaint::Align, SkPaint::Hinting, anti-alias, SkPaint fake bold,
+ SkPaint font embedded bitmaps, SkPaint full hinting spacing, LCD text, SkPaint linear text,
+ and SkPaint subpixel text.
+
+ SkTextEncoding must be set to SkTextEncoding::kGlyphID.
+
+ Elements of paint: anti-alias, SkBlendMode, color including alpha,
+ SkColorFilter, SkPaint dither, SkMaskFilter, SkPathEffect, SkShader, and
+ SkPaint::Style; apply to blob. If SkPaint contains SkPaint::kStroke_Style:
+ SkPaint miter limit, SkPaint::Cap, SkPaint::Join, and SkPaint stroke width;
+ apply to SkPath created from blob.
+
+ @param blob glyphs, positions, and their paints' text size, typeface, and so on
+ @param x horizontal offset applied to blob
+ @param y vertical offset applied to blob
+ @param paint blend, color, stroking, and so on, used to draw
+
+ example: https://fiddle.skia.org/c/@Canvas_drawTextBlob
+ */
+ void drawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, const SkPaint& paint);
+
+ /** Draws SkTextBlob blob at (x, y), using clip, SkMatrix, and SkPaint paint.
+
+ blob contains glyphs, their positions, and paint attributes specific to text:
+ SkTypeface, SkPaint text size, SkPaint text scale x,
+ SkPaint text skew x, SkPaint::Align, SkPaint::Hinting, anti-alias, SkPaint fake bold,
+ SkPaint font embedded bitmaps, SkPaint full hinting spacing, LCD text, SkPaint linear text,
+ and SkPaint subpixel text.
+
+ SkTextEncoding must be set to SkTextEncoding::kGlyphID.
+
+ Elements of paint: SkPathEffect, SkMaskFilter, SkShader, SkColorFilter,
+ and SkImageFilter; apply to blob.
+
+ @param blob glyphs, positions, and their paints' text size, typeface, and so on
+ @param x horizontal offset applied to blob
+ @param y vertical offset applied to blob
+ @param paint blend, color, stroking, and so on, used to draw
+ */
+ void drawTextBlob(const sk_sp<SkTextBlob>& blob, SkScalar x, SkScalar y, const SkPaint& paint) {
+ this->drawTextBlob(blob.get(), x, y, paint);
+ }
+
+ /** Draws SkPicture picture, using clip and SkMatrix.
+ Clip and SkMatrix are unchanged by picture contents, as if
+ save() was called before and restore() was called after drawPicture().
+
+ SkPicture records a series of draw commands for later playback.
+
+ @param picture recorded drawing commands to play
+ */
+ void drawPicture(const SkPicture* picture) {
+ this->drawPicture(picture, nullptr, nullptr);
+ }
+
+ /** Draws SkPicture picture, using clip and SkMatrix.
+ Clip and SkMatrix are unchanged by picture contents, as if
+ save() was called before and restore() was called after drawPicture().
+
+ SkPicture records a series of draw commands for later playback.
+
+ @param picture recorded drawing commands to play
+ */
+ void drawPicture(const sk_sp<SkPicture>& picture) {
+ this->drawPicture(picture.get());
+ }
+
+ /** Draws SkPicture picture, using clip and SkMatrix; transforming picture with
+ SkMatrix matrix, if provided; and use SkPaint paint alpha, SkColorFilter,
+ SkImageFilter, and SkBlendMode, if provided.
+
+ If paint is non-null, then the picture is always drawn into a temporary layer before
+ actually landing on the canvas. Note that drawing into a layer can also change its
+ appearance if there are any non-associative blendModes inside any of the pictures elements.
+
+ @param picture recorded drawing commands to play
+ @param matrix SkMatrix to rotate, scale, translate, and so on; may be nullptr
+ @param paint SkPaint to apply transparency, filtering, and so on; may be nullptr
+
+ example: https://fiddle.skia.org/c/@Canvas_drawPicture_3
+ */
+ void drawPicture(const SkPicture* picture, const SkMatrix* matrix, const SkPaint* paint);
+
+ /** Draws SkPicture picture, using clip and SkMatrix; transforming picture with
+ SkMatrix matrix, if provided; and use SkPaint paint alpha, SkColorFilter,
+ SkImageFilter, and SkBlendMode, if provided.
+
+ If paint is non-null, then the picture is always drawn into a temporary layer before
+ actually landing on the canvas. Note that drawing into a layer can also change its
+ appearance if there are any non-associative blendModes inside any of the pictures elements.
+
+ @param picture recorded drawing commands to play
+ @param matrix SkMatrix to rotate, scale, translate, and so on; may be nullptr
+ @param paint SkPaint to apply transparency, filtering, and so on; may be nullptr
+ */
+ void drawPicture(const sk_sp<SkPicture>& picture, const SkMatrix* matrix,
+ const SkPaint* paint) {
+ this->drawPicture(picture.get(), matrix, paint);
+ }
+
+ /** Draws SkVertices vertices, a triangle mesh, using clip and SkMatrix.
+ If paint contains an SkShader and vertices does not contain texCoords, the shader
+ is mapped using the vertices' positions.
+
+ SkBlendMode is ignored if SkVertices does not have colors. Otherwise, it combines
+ - the SkShader if SkPaint contains SkShader
+ - or the opaque SkPaint color if SkPaint does not contain SkShader
+ as the src of the blend and the interpolated vertex colors as the dst.
+
+ SkMaskFilter, SkPathEffect, and antialiasing on SkPaint are ignored.
+
+ @param vertices triangle mesh to draw
+ @param mode combines vertices' colors with SkShader if present or SkPaint opaque color
+ if not. Ignored if the vertices do not contain color.
+ @param paint specifies the SkShader, used as SkVertices texture, and SkColorFilter.
+
+ example: https://fiddle.skia.org/c/@Canvas_drawVertices
+ */
+ void drawVertices(const SkVertices* vertices, SkBlendMode mode, const SkPaint& paint);
+
+ /** Draws SkVertices vertices, a triangle mesh, using clip and SkMatrix.
+ If paint contains an SkShader and vertices does not contain texCoords, the shader
+ is mapped using the vertices' positions.
+
+ SkBlendMode is ignored if SkVertices does not have colors. Otherwise, it combines
+ - the SkShader if SkPaint contains SkShader
+ - or the opaque SkPaint color if SkPaint does not contain SkShader
+ as the src of the blend and the interpolated vertex colors as the dst.
+
+ SkMaskFilter, SkPathEffect, and antialiasing on SkPaint are ignored.
+
+ @param vertices triangle mesh to draw
+ @param mode combines vertices' colors with SkShader if present or SkPaint opaque color
+ if not. Ignored if the vertices do not contain color.
+ @param paint specifies the SkShader, used as SkVertices texture, may be nullptr
+
+ example: https://fiddle.skia.org/c/@Canvas_drawVertices_2
+ */
+ void drawVertices(const sk_sp<SkVertices>& vertices, SkBlendMode mode, const SkPaint& paint);
+
+#if defined(SK_ENABLE_EXPERIMENTAL_CUSTOM_MESH) && defined(SK_ENABLE_SKSL)
+ /**
+ Experimental, under active development, and subject to change without notice.
+
+ Draws a mesh using a user-defined specification (see SkCustomMeshSpecification).
+
+ SkBlender is ignored if SkCustomMesh's specification does not output fragment shader color.
+ Otherwise, it combines
+ - the SkShader if SkPaint contains SkShader
+ - or the opaque SkPaint color if SkPaint does not contain SkShader
+ as the src of the blend and the mesh's fragment color as the dst.
+
+ SkMaskFilter, SkPathEffect, and antialiasing on SkPaint are ignored.
+
+ @param cm the custom mesh vertices and compatible specification.
+ @param blender combines vertices colors with SkShader if present or SkPaint opaque color
+ if not. Ignored if the custom mesh does not output color. Defaults to
+ SkBlendMode::kModulate if nullptr.
+ @param paint specifies the SkShader, used as SkVertices texture, may be nullptr
+ */
+ void drawCustomMesh(SkCustomMesh cm, sk_sp<SkBlender> blender, const SkPaint& paint);
+#endif
+
+ /** Draws a Coons patch: the interpolation of four cubics with shared corners,
+ associating a color, and optionally a texture SkPoint, with each corner.
+
+ SkPoint array cubics specifies four SkPath cubic starting at the top-left corner,
+ in clockwise order, sharing every fourth point. The last SkPath cubic ends at the
+ first point.
+
+ Color array color associates colors with corners in top-left, top-right,
+ bottom-right, bottom-left order.
+
+ If paint contains SkShader, SkPoint array texCoords maps SkShader as texture to
+ corners in top-left, top-right, bottom-right, bottom-left order. If texCoords is
+ nullptr, SkShader is mapped using positions (derived from cubics).
+
+ SkBlendMode is ignored if colors is null. Otherwise, it combines
+ - the SkShader if SkPaint contains SkShader
+ - or the opaque SkPaint color if SkPaint does not contain SkShader
+ as the src of the blend and the interpolated patch colors as the dst.
+
+ SkMaskFilter, SkPathEffect, and antialiasing on SkPaint are ignored.
+
+ @param cubics SkPath cubic array, sharing common points
+ @param colors color array, one for each corner
+ @param texCoords SkPoint array of texture coordinates, mapping SkShader to corners;
+ may be nullptr
+ @param mode combines patch's colors with SkShader if present or SkPaint opaque color
+ if not. Ignored if colors is null.
+ @param paint SkShader, SkColorFilter, SkBlendMode, used to draw
+ */
+ void drawPatch(const SkPoint cubics[12], const SkColor colors[4],
+ const SkPoint texCoords[4], SkBlendMode mode, const SkPaint& paint);
+
+ /** Draws a set of sprites from atlas, using clip, SkMatrix, and optional SkPaint paint.
+ paint uses anti-alias, alpha, SkColorFilter, SkImageFilter, and SkBlendMode
+ to draw, if present. For each entry in the array, SkRect tex locates sprite in
+ atlas, and SkRSXform xform transforms it into destination space.
+
+ SkMaskFilter and SkPathEffect on paint are ignored.
+
+ xform, tex, and colors if present, must contain count entries.
+ Optional colors are applied for each sprite using SkBlendMode mode, treating
+ sprite as source and colors as destination.
+ Optional cullRect is a conservative bounds of all transformed sprites.
+ If cullRect is outside of clip, canvas can skip drawing.
+
+ If atlas is nullptr, this draws nothing.
+
+ @param atlas SkImage containing sprites
+ @param xform SkRSXform mappings for sprites in atlas
+ @param tex SkRect locations of sprites in atlas
+ @param colors one per sprite, blended with sprite using SkBlendMode; may be nullptr
+ @param count number of sprites to draw
+ @param mode SkBlendMode combining colors and sprites
+ @param sampling SkSamplingOptions used when sampling from the atlas image
+ @param cullRect bounds of transformed sprites for efficient clipping; may be nullptr
+ @param paint SkColorFilter, SkImageFilter, SkBlendMode, and so on; may be nullptr
+ */
+ 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);
+
+ /** Draws SkDrawable drawable using clip and SkMatrix, concatenated with
+ optional matrix.
+
+ If SkCanvas has an asynchronous implementation, as is the case
+ when it is recording into SkPicture, then drawable will be referenced,
+ so that SkDrawable::draw() can be called when the operation is finalized. To force
+ immediate drawing, call SkDrawable::draw() instead.
+
+ @param drawable custom struct encapsulating drawing commands
+ @param matrix transformation applied to drawing; may be nullptr
+
+ example: https://fiddle.skia.org/c/@Canvas_drawDrawable
+ */
+ void drawDrawable(SkDrawable* drawable, const SkMatrix* matrix = nullptr);
+
+ /** Draws SkDrawable drawable using clip and SkMatrix, offset by (x, y).
+
+ If SkCanvas has an asynchronous implementation, as is the case
+ when it is recording into SkPicture, then drawable will be referenced,
+ so that SkDrawable::draw() can be called when the operation is finalized. To force
+ immediate drawing, call SkDrawable::draw() instead.
+
+ @param drawable custom struct encapsulating drawing commands
+ @param x offset into SkCanvas writable pixels on x-axis
+ @param y offset into SkCanvas writable pixels on y-axis
+
+ example: https://fiddle.skia.org/c/@Canvas_drawDrawable_2
+ */
+ void drawDrawable(SkDrawable* drawable, SkScalar x, SkScalar y);
+
+ /** Associates SkRect on SkCanvas with an annotation; a key-value pair, where the key is
+ a null-terminated UTF-8 string, and optional value is stored as SkData.
+
+ Only some canvas implementations, such as recording to SkPicture, or drawing to
+ document PDF, use annotations.
+
+ @param rect SkRect extent of canvas to annotate
+ @param key string used for lookup
+ @param value data holding value stored in annotation
+
+ example: https://fiddle.skia.org/c/@Canvas_drawAnnotation_2
+ */
+ void drawAnnotation(const SkRect& rect, const char key[], SkData* value);
+
+ /** Associates SkRect on SkCanvas when an annotation; a key-value pair, where the key is
+ a null-terminated UTF-8 string, and optional value is stored as SkData.
+
+ Only some canvas implementations, such as recording to SkPicture, or drawing to
+ document PDF, use annotations.
+
+ @param rect SkRect extent of canvas to annotate
+ @param key string used for lookup
+ @param value data holding value stored in annotation
+ */
+ void drawAnnotation(const SkRect& rect, const char key[], const sk_sp<SkData>& value) {
+ this->drawAnnotation(rect, key, value.get());
+ }
+
+ /** Returns true if clip is empty; that is, nothing will draw.
+
+ May do work when called; it should not be called
+ more often than needed. However, once called, subsequent calls perform no
+ work until clip changes.
+
+ @return true if clip is empty
+
+ example: https://fiddle.skia.org/c/@Canvas_isClipEmpty
+ */
+ virtual bool isClipEmpty() const;
+
+ /** Returns true if clip is SkRect and not empty.
+ Returns false if the clip is empty, or if it is not SkRect.
+
+ @return true if clip is SkRect and not empty
+
+ example: https://fiddle.skia.org/c/@Canvas_isClipRect
+ */
+ virtual bool isClipRect() const;
+
+ /** Returns the current transform from local coordinates to the 'device', which for most
+ * purposes means pixels.
+ *
+ * @return transformation from local coordinates to device / pixels.
+ */
+ SkM44 getLocalToDevice() const;
+
+ /**
+ * Throws away the 3rd row and column in the matrix, so be warned.
+ */
+ SkMatrix getLocalToDeviceAs3x3() const {
+ return this->getLocalToDevice().asM33();
+ }
+
+#ifdef SK_SUPPORT_LEGACY_GETTOTALMATRIX
+ /** DEPRECATED
+ * Legacy version of getLocalToDevice(), which strips away any Z information, and
+ * just returns a 3x3 version.
+ *
+ * @return 3x3 version of getLocalToDevice()
+ *
+ * example: https://fiddle.skia.org/c/@Canvas_getTotalMatrix
+ * example: https://fiddle.skia.org/c/@Clip
+ */
+ SkMatrix getTotalMatrix() const;
+#endif
+
+ ///////////////////////////////////////////////////////////////////////////
+
+#if defined(SK_BUILD_FOR_ANDROID_FRAMEWORK) && SK_SUPPORT_GPU
+ // These methods exist to support WebView in Android Framework.
+ SkIRect topLayerBounds() const;
+ GrBackendRenderTarget topLayerBackendRenderTarget() const;
+#endif
+
+ /**
+ * Returns the global clip as a region. If the clip contains AA, then only the bounds
+ * of the clip may be returned.
+ */
+ void temporary_internal_getRgnClip(SkRegion* region);
+
+ void private_draw_shadow_rec(const SkPath&, const SkDrawShadowRec&);
+
+
+protected:
+ // default impl defers to getDevice()->newSurface(info)
+ virtual sk_sp<SkSurface> onNewSurface(const SkImageInfo& info, const SkSurfaceProps& props);
+
+ // default impl defers to its device
+ virtual bool onPeekPixels(SkPixmap* pixmap);
+ virtual bool onAccessTopLayerPixels(SkPixmap* pixmap);
+ virtual SkImageInfo onImageInfo() const;
+ virtual bool onGetProps(SkSurfaceProps* props) const;
+ virtual void onFlush();
+
+ // Subclass save/restore notifiers.
+ // Overriders should call the corresponding INHERITED method up the inheritance chain.
+ // getSaveLayerStrategy()'s return value may suppress full layer allocation.
+ enum SaveLayerStrategy {
+ kFullLayer_SaveLayerStrategy,
+ kNoLayer_SaveLayerStrategy,
+ };
+
+ virtual void willSave() {}
+ // Overriders should call the corresponding INHERITED method up the inheritance chain.
+ virtual SaveLayerStrategy getSaveLayerStrategy(const SaveLayerRec& ) {
+ return kFullLayer_SaveLayerStrategy;
+ }
+
+ // returns true if we should actually perform the saveBehind, or false if we should just save.
+ virtual bool onDoSaveBehind(const SkRect*) { return true; }
+ virtual void willRestore() {}
+ virtual void didRestore() {}
+
+ virtual void didConcat44(const SkM44&) {}
+ virtual void didSetM44(const SkM44&) {}
+ virtual void didTranslate(SkScalar, SkScalar) {}
+ virtual void didScale(SkScalar, SkScalar) {}
+
+#ifndef SK_ENABLE_EXPERIMENTAL_CUSTOM_MESH
+ // Define this in protected so we can still access internally for testing.
+ void drawCustomMesh(SkCustomMesh cm, sk_sp<SkBlender> blender, const SkPaint& paint);
+#endif
+
+ // NOTE: If you are adding a new onDraw virtual to SkCanvas, PLEASE add an override to
+ // SkCanvasVirtualEnforcer (in SkCanvasVirtualEnforcer.h). This ensures that subclasses using
+ // that mechanism will be required to implement the new function.
+ virtual void onDrawPaint(const SkPaint& paint);
+ virtual void onDrawBehind(const SkPaint& paint);
+ virtual void onDrawRect(const SkRect& rect, const SkPaint& paint);
+ virtual void onDrawRRect(const SkRRect& rrect, const SkPaint& paint);
+ virtual void onDrawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint& paint);
+ virtual void onDrawOval(const SkRect& rect, const SkPaint& paint);
+ virtual void onDrawArc(const SkRect& rect, SkScalar startAngle, SkScalar sweepAngle,
+ bool useCenter, const SkPaint& paint);
+ virtual void onDrawPath(const SkPath& path, const SkPaint& paint);
+ virtual void onDrawRegion(const SkRegion& region, const SkPaint& paint);
+
+ virtual void onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
+ const SkPaint& paint);
+
+ virtual void onDrawGlyphRunList(const SkGlyphRunList& glyphRunList, const SkPaint& paint);
+
+ virtual void onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
+ const SkPoint texCoords[4], SkBlendMode mode, const SkPaint& paint);
+ virtual void onDrawPoints(PointMode mode, size_t count, const SkPoint pts[],
+ const SkPaint& paint);
+
+ virtual void onDrawImage2(const SkImage*, SkScalar dx, SkScalar dy, const SkSamplingOptions&,
+ const SkPaint*);
+ virtual void onDrawImageRect2(const SkImage*, const SkRect& src, const SkRect& dst,
+ const SkSamplingOptions&, const SkPaint*, SrcRectConstraint);
+ virtual void onDrawImageLattice2(const SkImage*, const Lattice&, const SkRect& dst,
+ SkFilterMode, const SkPaint*);
+ virtual void onDrawAtlas2(const SkImage*, const SkRSXform[], const SkRect src[],
+ const SkColor[], int count, SkBlendMode, const SkSamplingOptions&,
+ const SkRect* cull, const SkPaint*);
+ virtual void onDrawEdgeAAImageSet2(const ImageSetEntry imageSet[], int count,
+ const SkPoint dstClips[], const SkMatrix preViewMatrices[],
+ const SkSamplingOptions&, const SkPaint*,
+ SrcRectConstraint);
+
+ virtual void onDrawVerticesObject(const SkVertices* vertices, SkBlendMode mode,
+ const SkPaint& paint);
+#ifdef SK_ENABLE_SKSL
+ virtual void onDrawCustomMesh(SkCustomMesh, sk_sp<SkBlender>, const SkPaint&);
+#endif
+ virtual void onDrawAnnotation(const SkRect& rect, const char key[], SkData* value);
+ virtual void onDrawShadowRec(const SkPath&, const SkDrawShadowRec&);
+
+ virtual void onDrawDrawable(SkDrawable* drawable, const SkMatrix* matrix);
+ virtual void onDrawPicture(const SkPicture* picture, const SkMatrix* matrix,
+ const SkPaint* paint);
+
+ virtual void onDrawEdgeAAQuad(const SkRect& rect, const SkPoint clip[4], QuadAAFlags aaFlags,
+ const SkColor4f& color, SkBlendMode mode);
+
+ enum ClipEdgeStyle {
+ kHard_ClipEdgeStyle,
+ kSoft_ClipEdgeStyle
+ };
+
+ virtual void onClipRect(const SkRect& rect, SkClipOp op, ClipEdgeStyle edgeStyle);
+ virtual void onClipRRect(const SkRRect& rrect, SkClipOp op, ClipEdgeStyle edgeStyle);
+ virtual void onClipPath(const SkPath& path, SkClipOp op, ClipEdgeStyle edgeStyle);
+ virtual void onClipShader(sk_sp<SkShader>, SkClipOp);
+ virtual void onClipRegion(const SkRegion& deviceRgn, SkClipOp op);
+ virtual void onResetClip();
+
+ virtual void onDiscard();
+
+#if SK_SUPPORT_GPU
+ /** Experimental
+ */
+ virtual sk_sp<GrSlug> doConvertBlobToSlug(
+ const SkTextBlob& blob, SkPoint origin, const SkPaint& paint);
+
+ /** Experimental
+ */
+ virtual void doDrawSlug(GrSlug* slug);
+#endif
+
+private:
+
+ enum 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
+ };
+
+ // notify our surface (if we have one) that we are about to draw, so it
+ // can perform copy-on-write or invalidate any cached images
+ // returns false if the copy failed
+ bool SK_WARN_UNUSED_RESULT predrawNotify(bool willOverwritesEntireSurface = false);
+ bool SK_WARN_UNUSED_RESULT predrawNotify(const SkRect*, const SkPaint*, ShaderOverrideOpacity);
+
+ enum class CheckForOverwrite : bool {
+ kNo = false,
+ kYes = true
+ };
+ // call the appropriate predrawNotify and create a layer if needed.
+ skstd::optional<AutoLayerForImageFilter> aboutToDraw(
+ SkCanvas* canvas,
+ const SkPaint& paint,
+ const SkRect* rawBounds = nullptr,
+ CheckForOverwrite = CheckForOverwrite::kNo,
+ ShaderOverrideOpacity = kNone_ShaderOverrideOpacity);
+
+ // The bottom-most device in the stack, only changed by init(). Image properties and the final
+ // canvas pixels are determined by this device.
+ SkBaseDevice* baseDevice() const {
+ SkASSERT(fBaseDevice);
+ return fBaseDevice.get();
+ }
+
+ // The top-most device in the stack, will change within saveLayer()'s. All drawing and clipping
+ // operations should route to this device.
+ SkBaseDevice* topDevice() const;
+
+ // Canvases maintain a sparse stack of layers, where the top-most layer receives the drawing,
+ // clip, and matrix commands. There is a layer per call to saveLayer() using the
+ // kFullLayer_SaveLayerStrategy.
+ struct Layer {
+ sk_sp<SkBaseDevice> fDevice;
+ sk_sp<SkImageFilter> fImageFilter; // applied to layer *before* being drawn by paint
+ SkPaint fPaint;
+ bool fDiscard;
+
+ Layer(sk_sp<SkBaseDevice> device, sk_sp<SkImageFilter> imageFilter, const SkPaint& paint);
+ };
+
+ // Encapsulate state needed to restore from saveBehind()
+ struct BackImage {
+ sk_sp<SkSpecialImage> fImage;
+ SkIPoint fLoc;
+ };
+
+ class MCRec {
+ public:
+ // If not null, this MCRec corresponds with the saveLayer() record that made the layer.
+ // The base "layer" is not stored here, since it is stored inline in SkCanvas and has no
+ // restoration behavior.
+ std::unique_ptr<Layer> fLayer;
+
+ // This points to the device of the top-most layer (which may be lower in the stack), or
+ // to the canvas's fBaseDevice. The MCRec does not own the device.
+ SkBaseDevice* fDevice;
+
+ std::unique_ptr<BackImage> fBackImage;
+ SkM44 fMatrix;
+ int fDeferredSaveCount = 0;
+
+ MCRec(SkBaseDevice* device);
+ MCRec(const MCRec* prev);
+ ~MCRec();
+
+ void newLayer(sk_sp<SkBaseDevice> layerDevice,
+ sk_sp<SkImageFilter> filter,
+ const SkPaint& restorePaint);
+
+ void reset(SkBaseDevice* device);
+ };
+
+ SkDeque fMCStack;
+ // points to top of stack
+ MCRec* fMCRec;
+
+ // the first N recs that can fit here mean we won't call malloc
+ static constexpr int kMCRecSize = 96; // most recent measurement
+ static constexpr int kMCRecCount = 32; // common depth for save/restores
+
+ intptr_t fMCRecStorage[kMCRecSize * kMCRecCount / sizeof(intptr_t)];
+
+ // Installed via init()
+ sk_sp<SkBaseDevice> fBaseDevice;
+ const SkSurfaceProps fProps;
+
+ int fSaveCount; // value returned by getSaveCount()
+
+ std::unique_ptr<SkRasterHandleAllocator> fAllocator;
+
+ SkSurface_Base* fSurfaceBase;
+ SkSurface_Base* getSurfaceBase() const { return fSurfaceBase; }
+ void setSurfaceBase(SkSurface_Base* sb) {
+ fSurfaceBase = sb;
+ }
+ friend class SkSurface_Base;
+ friend class SkSurface_Gpu;
+
+ SkIRect fClipRestrictionRect = SkIRect::MakeEmpty();
+ int fClipRestrictionSaveCount = -1;
+
+ void doSave();
+ void checkForDeferredSave();
+ void internalSetMatrix(const SkM44&);
+
+ friend class SkAndroidFrameworkUtils;
+ friend class SkCanvasPriv; // needs to expose android functions for testing outside android
+ friend class AutoLayerForImageFilter;
+ friend class SkSurface_Raster; // needs getDevice()
+ friend class SkNoDrawCanvas; // needs resetForNextPicture()
+ friend class SkNWayCanvas;
+ friend class SkPictureRecord; // predrawNotify (why does it need it? <reed>)
+ friend class SkOverdrawCanvas;
+ friend class SkRasterHandleAllocator;
+protected:
+ // For use by SkNoDrawCanvas (via SkCanvasVirtualEnforcer, which can't be a friend)
+ SkCanvas(const SkIRect& bounds);
+private:
+ SkCanvas(const SkBitmap&, std::unique_ptr<SkRasterHandleAllocator>,
+ SkRasterHandleAllocator::Handle);
+
+ SkCanvas(SkCanvas&&) = delete;
+ SkCanvas(const SkCanvas&) = delete;
+ SkCanvas& operator=(SkCanvas&&) = delete;
+ SkCanvas& operator=(const SkCanvas&) = delete;
+
+#if SK_SUPPORT_GPU
+ friend class GrSlug;
+ /** Experimental
+ * Convert a SkTextBlob to a GrSlug using the current canvas state.
+ */
+ sk_sp<GrSlug> convertBlobToSlug(const SkTextBlob& blob, SkPoint origin, const SkPaint& paint);
+
+ /** Experimental
+ * Draw an GrSlug given the current canvas state.
+ */
+ void drawSlug(GrSlug* slug);
+#endif
+
+ /** Experimental
+ * Saves the specified subset of the current pixels in the current layer,
+ * and then clears those pixels to transparent black.
+ * Restores the pixels on restore() by drawing them in SkBlendMode::kDstOver.
+ *
+ * @param subset conservative bounds of the area to be saved / restored.
+ * @return depth of save state stack before this call was made.
+ */
+ int only_axis_aligned_saveBehind(const SkRect* subset);
+
+ /**
+ * Like drawPaint, but magically clipped to the most recent saveBehind buffer rectangle.
+ * If there is no active saveBehind, then this draws nothing.
+ */
+ void drawClippedToSaveBehind(const SkPaint&);
+
+ void resetForNextPicture(const SkIRect& bounds);
+
+ // needs gettotalclip()
+ friend class SkCanvasStateUtils;
+
+ void init(sk_sp<SkBaseDevice>);
+
+ // All base onDrawX() functions should call this and skip drawing if it returns true.
+ // If 'matrix' is non-null, it maps the paint's fast bounds before checking for quick rejection
+ bool internalQuickReject(const SkRect& bounds, const SkPaint& paint,
+ const SkMatrix* matrix = nullptr);
+
+ void internalDrawPaint(const SkPaint& paint);
+ void internalSaveLayer(const SaveLayerRec&, SaveLayerStrategy);
+ void internalSaveBehind(const SkRect*);
+
+ void internalConcat44(const SkM44&);
+
+ // shared by save() and saveLayer()
+ void internalSave();
+ void internalRestore();
+
+ enum class DeviceCompatibleWithFilter : bool {
+ // Check the src device's local-to-device matrix for compatibility with the filter, and if
+ // it is not compatible, introduce an intermediate image and transformation that allows the
+ // filter to be evaluated on the modified src content.
+ kUnknown = false,
+ // Assume that the src device's local-to-device matrix is compatible with the filter.
+ kYes = true
+ };
+ /**
+ * Filters the contents of 'src' and draws the result into 'dst'. The filter is evaluated
+ * relative to the current canvas matrix, and src is drawn to dst using their relative transform
+ * 'paint' is applied after the filter and must not have a mask or image filter of its own.
+ * A null 'filter' behaves as if the identity filter were used.
+ *
+ * 'scaleFactor' is an extra uniform scale transform applied to downscale the 'src' image
+ * before any filtering, or as part of the copy, and is then drawn with 1/scaleFactor to 'dst'.
+ * Must be 1.0 if 'compat' is kYes (i.e. any scale factor has already been baked into the
+ * relative transforms between the devices).
+ */
+ void internalDrawDeviceWithFilter(SkBaseDevice* src, SkBaseDevice* dst,
+ const SkImageFilter* filter, const SkPaint& paint,
+ DeviceCompatibleWithFilter compat,
+ SkScalar scaleFactor = 1.f);
+
+ /*
+ * Returns true if drawing the specified rect (or all if it is null) with the specified
+ * paint (or default if null) would overwrite the entire root device of the canvas
+ * (i.e. the canvas' surface if it had one).
+ */
+ bool wouldOverwriteEntireSurface(const SkRect*, const SkPaint*, ShaderOverrideOpacity) const;
+
+ /**
+ * Returns true if the paint's imagefilter can be invoked directly, without needed a layer.
+ */
+ bool canDrawBitmapAsSprite(SkScalar x, SkScalar y, int w, int h, const SkSamplingOptions&,
+ const SkPaint&);
+
+ /**
+ * Returns true if the clip (for any active layer) contains antialiasing.
+ * If the clip is empty, this will return false.
+ */
+ bool androidFramework_isClipAA() const;
+
+ /**
+ * Reset the clip to be wide-open (modulo any separately specified device clip restriction).
+ * This operate within the save/restore clip stack so it can be undone by restoring to an
+ * earlier save point.
+ */
+ void internal_private_resetClip();
+
+ virtual SkPaintFilterCanvas* internal_private_asPaintFilterCanvas() const { return nullptr; }
+
+ // Keep track of the device clip bounds in the canvas' global space to reject draws before
+ // invoking the top-level device.
+ SkRect fQuickRejectBounds;
+
+ // Compute the clip's bounds based on all clipped SkDevice's reported device bounds transformed
+ // into the canvas' global space.
+ SkRect computeDeviceClipBounds(bool outsetForAA=true) const;
+
+ class AutoUpdateQRBounds;
+ void validateClip() const;
+
+ std::unique_ptr<SkGlyphRunBuilder> fScratchGlyphRunBuilder;
+
+ using INHERITED = SkRefCnt;
+};
+
+/** \class SkAutoCanvasRestore
+ Stack helper class calls SkCanvas::restoreToCount when SkAutoCanvasRestore
+ goes out of scope. Use this to guarantee that the canvas is restored to a known
+ state.
+*/
+class SkAutoCanvasRestore {
+public:
+
+ /** Preserves SkCanvas::save() count. Optionally saves SkCanvas clip and SkCanvas matrix.
+
+ @param canvas SkCanvas to guard
+ @param doSave call SkCanvas::save()
+ @return utility to restore SkCanvas state on destructor
+ */
+ SkAutoCanvasRestore(SkCanvas* canvas, bool doSave) : fCanvas(canvas), fSaveCount(0) {
+ if (fCanvas) {
+ fSaveCount = canvas->getSaveCount();
+ if (doSave) {
+ canvas->save();
+ }
+ }
+ }
+
+ /** Restores SkCanvas to saved state. Destructor is called when container goes out of
+ scope.
+ */
+ ~SkAutoCanvasRestore() {
+ if (fCanvas) {
+ fCanvas->restoreToCount(fSaveCount);
+ }
+ }
+
+ /** Restores SkCanvas to saved state immediately. Subsequent calls and
+ ~SkAutoCanvasRestore() have no effect.
+ */
+ void restore() {
+ if (fCanvas) {
+ fCanvas->restoreToCount(fSaveCount);
+ fCanvas = nullptr;
+ }
+ }
+
+private:
+ SkCanvas* fCanvas;
+ int fSaveCount;
+
+ SkAutoCanvasRestore(SkAutoCanvasRestore&&) = delete;
+ SkAutoCanvasRestore(const SkAutoCanvasRestore&) = delete;
+ SkAutoCanvasRestore& operator=(SkAutoCanvasRestore&&) = delete;
+ SkAutoCanvasRestore& operator=(const SkAutoCanvasRestore&) = delete;
+};
+
+#endif
diff --git a/src/deps/skia/include/core/SkCanvasVirtualEnforcer.h b/src/deps/skia/include/core/SkCanvasVirtualEnforcer.h
new file mode 100644
index 000000000..5086b4337
--- /dev/null
+++ b/src/deps/skia/include/core/SkCanvasVirtualEnforcer.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2018 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkCanvasVirtualEnforcer_DEFINED
+#define SkCanvasVirtualEnforcer_DEFINED
+
+#include "include/core/SkCanvas.h"
+
+// If you would ordinarily want to inherit from Base (eg SkCanvas, SkNWayCanvas), instead
+// inherit from SkCanvasVirtualEnforcer<Base>, which will make the build fail if you forget
+// to override one of SkCanvas' key virtual hooks.
+template <typename Base>
+class SkCanvasVirtualEnforcer : public Base {
+public:
+ using Base::Base;
+
+protected:
+ void onDrawPaint(const SkPaint& paint) override = 0;
+ void onDrawBehind(const SkPaint&) override {} // make zero after android updates
+ void onDrawRect(const SkRect& rect, const SkPaint& paint) override = 0;
+ void onDrawRRect(const SkRRect& rrect, const SkPaint& paint) override = 0;
+ void onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
+ const SkPaint& paint) override = 0;
+ void onDrawOval(const SkRect& rect, const SkPaint& paint) override = 0;
+ void onDrawArc(const SkRect& rect, SkScalar startAngle, SkScalar sweepAngle, bool useCenter,
+ const SkPaint& paint) override = 0;
+ void onDrawPath(const SkPath& path, const SkPaint& paint) override = 0;
+ void onDrawRegion(const SkRegion& region, const SkPaint& paint) override = 0;
+
+ void onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
+ const SkPaint& paint) override = 0;
+
+ void onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
+ const SkPoint texCoords[4], SkBlendMode mode,
+ const SkPaint& paint) override = 0;
+ void onDrawPoints(SkCanvas::PointMode mode, size_t count, const SkPoint pts[],
+ const SkPaint& paint) override = 0;
+
+#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
+ // This is under active development for Chrome and not used in Android. Hold off on adding
+ // implementations in Android's SkCanvas subclasses until this stabilizes.
+ void onDrawEdgeAAQuad(const SkRect& rect, const SkPoint clip[4],
+ SkCanvas::QuadAAFlags aaFlags, const SkColor4f& color, SkBlendMode mode) override {}
+#else
+ void onDrawEdgeAAQuad(const SkRect& rect, const SkPoint clip[4],
+ SkCanvas::QuadAAFlags aaFlags, const SkColor4f& color, SkBlendMode mode) override = 0;
+#endif
+
+ void onDrawAnnotation(const SkRect& rect, const char key[], SkData* value) override = 0;
+ void onDrawShadowRec(const SkPath&, const SkDrawShadowRec&) override = 0;
+
+ void onDrawDrawable(SkDrawable* drawable, const SkMatrix* matrix) override = 0;
+ void onDrawPicture(const SkPicture* picture, const SkMatrix* matrix,
+ const SkPaint* paint) override = 0;
+};
+
+#endif
diff --git a/src/deps/skia/include/core/SkClipOp.h b/src/deps/skia/include/core/SkClipOp.h
new file mode 100644
index 000000000..3da6c6113
--- /dev/null
+++ b/src/deps/skia/include/core/SkClipOp.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkClipOp_DEFINED
+#define SkClipOp_DEFINED
+
+#include "include/core/SkTypes.h"
+
+enum class SkClipOp {
+ kDifference = 0,
+ kIntersect = 1,
+ kMax_EnumValue = kIntersect
+};
+
+#endif
diff --git a/src/deps/skia/include/core/SkColor.h b/src/deps/skia/include/core/SkColor.h
new file mode 100644
index 000000000..9cba771dd
--- /dev/null
+++ b/src/deps/skia/include/core/SkColor.h
@@ -0,0 +1,438 @@
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkColor_DEFINED
+#define SkColor_DEFINED
+
+#include "include/core/SkImageInfo.h"
+#include "include/core/SkScalar.h"
+#include "include/core/SkTypes.h"
+
+#include <array>
+
+/** \file SkColor.h
+
+ Types, consts, functions, and macros for colors.
+*/
+
+/** 8-bit type for an alpha value. 255 is 100% opaque, zero is 100% transparent.
+*/
+typedef uint8_t SkAlpha;
+
+/** 32-bit ARGB color value, unpremultiplied. Color components are always in
+ a known order. This is different from SkPMColor, which has its bytes in a configuration
+ dependent order, to match the format of kBGRA_8888_SkColorType bitmaps. SkColor
+ is the type used to specify colors in SkPaint and in gradients.
+
+ Color that is premultiplied has the same component values as color
+ that is unpremultiplied if alpha is 255, fully opaque, although may have the
+ component values in a different order.
+*/
+typedef uint32_t SkColor;
+
+/** Returns color value from 8-bit component values. Asserts if SK_DEBUG is defined
+ if a, r, g, or b exceed 255. Since color is unpremultiplied, a may be smaller
+ than the largest of r, g, and b.
+
+ @param a amount of alpha, from fully transparent (0) to fully opaque (255)
+ @param r amount of red, from no red (0) to full red (255)
+ @param g amount of green, from no green (0) to full green (255)
+ @param b amount of blue, from no blue (0) to full blue (255)
+ @return color and alpha, unpremultiplied
+*/
+static constexpr inline SkColor SkColorSetARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) {
+ return SkASSERT(a <= 255 && r <= 255 && g <= 255 && b <= 255),
+ (a << 24) | (r << 16) | (g << 8) | (b << 0);
+}
+
+/** Returns color value from 8-bit component values, with alpha set
+ fully opaque to 255.
+*/
+#define SkColorSetRGB(r, g, b) SkColorSetARGB(0xFF, r, g, b)
+
+/** Returns alpha byte from color value.
+*/
+#define SkColorGetA(color) (((color) >> 24) & 0xFF)
+
+/** Returns red component of color, from zero to 255.
+*/
+#define SkColorGetR(color) (((color) >> 16) & 0xFF)
+
+/** Returns green component of color, from zero to 255.
+*/
+#define SkColorGetG(color) (((color) >> 8) & 0xFF)
+
+/** Returns blue component of color, from zero to 255.
+*/
+#define SkColorGetB(color) (((color) >> 0) & 0xFF)
+
+/** Returns unpremultiplied color with red, blue, and green set from c; and alpha set
+ from a. Alpha component of c is ignored and is replaced by a in result.
+
+ @param c packed RGB, eight bits per component
+ @param a alpha: transparent at zero, fully opaque at 255
+ @return color with transparency
+*/
+static constexpr inline SkColor SK_WARN_UNUSED_RESULT SkColorSetA(SkColor c, U8CPU a) {
+ return (c & 0x00FFFFFF) | (a << 24);
+}
+
+/** Represents fully transparent SkAlpha value. SkAlpha ranges from zero,
+ fully transparent; to 255, fully opaque.
+*/
+constexpr SkAlpha SK_AlphaTRANSPARENT = 0x00;
+
+/** Represents fully opaque SkAlpha value. SkAlpha ranges from zero,
+ fully transparent; to 255, fully opaque.
+*/
+constexpr SkAlpha SK_AlphaOPAQUE = 0xFF;
+
+/** Represents fully transparent SkColor. May be used to initialize a destination
+ containing a mask or a non-rectangular image.
+*/
+constexpr SkColor SK_ColorTRANSPARENT = SkColorSetARGB(0x00, 0x00, 0x00, 0x00);
+
+/** Represents fully opaque black.
+*/
+constexpr SkColor SK_ColorBLACK = SkColorSetARGB(0xFF, 0x00, 0x00, 0x00);
+
+/** Represents fully opaque dark gray.
+ Note that SVG dark gray is equivalent to 0xFFA9A9A9.
+*/
+constexpr SkColor SK_ColorDKGRAY = SkColorSetARGB(0xFF, 0x44, 0x44, 0x44);
+
+/** Represents fully opaque gray.
+ Note that HTML gray is equivalent to 0xFF808080.
+*/
+constexpr SkColor SK_ColorGRAY = SkColorSetARGB(0xFF, 0x88, 0x88, 0x88);
+
+/** Represents fully opaque light gray. HTML silver is equivalent to 0xFFC0C0C0.
+ Note that SVG light gray is equivalent to 0xFFD3D3D3.
+*/
+constexpr SkColor SK_ColorLTGRAY = SkColorSetARGB(0xFF, 0xCC, 0xCC, 0xCC);
+
+/** Represents fully opaque white.
+*/
+constexpr SkColor SK_ColorWHITE = SkColorSetARGB(0xFF, 0xFF, 0xFF, 0xFF);
+
+/** Represents fully opaque red.
+*/
+constexpr SkColor SK_ColorRED = SkColorSetARGB(0xFF, 0xFF, 0x00, 0x00);
+
+/** Represents fully opaque green. HTML lime is equivalent.
+ Note that HTML green is equivalent to 0xFF008000.
+*/
+constexpr SkColor SK_ColorGREEN = SkColorSetARGB(0xFF, 0x00, 0xFF, 0x00);
+
+/** Represents fully opaque blue.
+*/
+constexpr SkColor SK_ColorBLUE = SkColorSetARGB(0xFF, 0x00, 0x00, 0xFF);
+
+/** Represents fully opaque yellow.
+*/
+constexpr SkColor SK_ColorYELLOW = SkColorSetARGB(0xFF, 0xFF, 0xFF, 0x00);
+
+/** Represents fully opaque cyan. HTML aqua is equivalent.
+*/
+constexpr SkColor SK_ColorCYAN = SkColorSetARGB(0xFF, 0x00, 0xFF, 0xFF);
+
+/** Represents fully opaque magenta. HTML fuchsia is equivalent.
+*/
+constexpr SkColor SK_ColorMAGENTA = SkColorSetARGB(0xFF, 0xFF, 0x00, 0xFF);
+
+/** Converts RGB to its HSV components.
+ hsv[0] contains hsv hue, a value from zero to less than 360.
+ hsv[1] contains hsv saturation, a value from zero to one.
+ hsv[2] contains hsv value, a value from zero to one.
+
+ @param red red component value from zero to 255
+ @param green green component value from zero to 255
+ @param blue blue component value from zero to 255
+ @param hsv three element array which holds the resulting HSV components
+*/
+SK_API void SkRGBToHSV(U8CPU red, U8CPU green, U8CPU blue, SkScalar hsv[3]);
+
+/** Converts ARGB to its HSV components. Alpha in ARGB is ignored.
+ hsv[0] contains hsv hue, and is assigned a value from zero to less than 360.
+ hsv[1] contains hsv saturation, a value from zero to one.
+ hsv[2] contains hsv value, a value from zero to one.
+
+ @param color ARGB color to convert
+ @param hsv three element array which holds the resulting HSV components
+*/
+static inline void SkColorToHSV(SkColor color, SkScalar hsv[3]) {
+ SkRGBToHSV(SkColorGetR(color), SkColorGetG(color), SkColorGetB(color), hsv);
+}
+
+/** Converts HSV components to an ARGB color. Alpha is passed through unchanged.
+ hsv[0] represents hsv hue, an angle from zero to less than 360.
+ hsv[1] represents hsv saturation, and varies from zero to one.
+ hsv[2] represents hsv value, and varies from zero to one.
+
+ Out of range hsv values are pinned.
+
+ @param alpha alpha component of the returned ARGB color
+ @param hsv three element array which holds the input HSV components
+ @return ARGB equivalent to HSV
+*/
+SK_API SkColor SkHSVToColor(U8CPU alpha, const SkScalar hsv[3]);
+
+/** Converts HSV components to an ARGB color. Alpha is set to 255.
+ hsv[0] represents hsv hue, an angle from zero to less than 360.
+ hsv[1] represents hsv saturation, and varies from zero to one.
+ hsv[2] represents hsv value, and varies from zero to one.
+
+ Out of range hsv values are pinned.
+
+ @param hsv three element array which holds the input HSV components
+ @return RGB equivalent to HSV
+*/
+static inline SkColor SkHSVToColor(const SkScalar hsv[3]) {
+ return SkHSVToColor(0xFF, hsv);
+}
+
+/** 32-bit ARGB color value, premultiplied. The byte order for this value is
+ configuration dependent, matching the format of kBGRA_8888_SkColorType bitmaps.
+ This is different from SkColor, which is unpremultiplied, and is always in the
+ same byte order.
+*/
+typedef uint32_t SkPMColor;
+
+/** Returns a SkPMColor value from unpremultiplied 8-bit component values.
+
+ @param a amount of alpha, from fully transparent (0) to fully opaque (255)
+ @param r amount of red, from no red (0) to full red (255)
+ @param g amount of green, from no green (0) to full green (255)
+ @param b amount of blue, from no blue (0) to full blue (255)
+ @return premultiplied color
+*/
+SK_API SkPMColor SkPreMultiplyARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b);
+
+/** Returns pmcolor closest to color c. Multiplies c RGB components by the c alpha,
+ and arranges the bytes to match the format of kN32_SkColorType.
+
+ @param c unpremultiplied ARGB color
+ @return premultiplied color
+*/
+SK_API SkPMColor SkPreMultiplyColor(SkColor c);
+
+/** \enum SkColorChannel
+ Describes different color channels one can manipulate
+*/
+enum class SkColorChannel {
+ kR, // the red channel
+ kG, // the green channel
+ kB, // the blue channel
+ kA, // the alpha channel
+
+ kLastEnum = kA,
+};
+
+/** Used to represent the channels available in a color type or texture format as a mask. */
+enum SkColorChannelFlag : uint32_t {
+ kRed_SkColorChannelFlag = 1 << static_cast<uint32_t>(SkColorChannel::kR),
+ kGreen_SkColorChannelFlag = 1 << static_cast<uint32_t>(SkColorChannel::kG),
+ kBlue_SkColorChannelFlag = 1 << static_cast<uint32_t>(SkColorChannel::kB),
+ kAlpha_SkColorChannelFlag = 1 << static_cast<uint32_t>(SkColorChannel::kA),
+ kGray_SkColorChannelFlag = 0x10,
+ // Convenience values
+ kGrayAlpha_SkColorChannelFlags = kGray_SkColorChannelFlag | kAlpha_SkColorChannelFlag,
+ kRG_SkColorChannelFlags = kRed_SkColorChannelFlag | kGreen_SkColorChannelFlag,
+ kRGB_SkColorChannelFlags = kRG_SkColorChannelFlags | kBlue_SkColorChannelFlag,
+ kRGBA_SkColorChannelFlags = kRGB_SkColorChannelFlags | kAlpha_SkColorChannelFlag,
+};
+static_assert(0 == (kGray_SkColorChannelFlag & kRGBA_SkColorChannelFlags), "bitfield conflict");
+
+/** \struct SkRGBA4f
+ RGBA color value, holding four floating point components. Color components are always in
+ a known order. kAT determines if the SkRGBA4f's R, G, and B components are premultiplied
+ by alpha or not.
+
+ Skia's public API always uses unpremultiplied colors, which can be stored as
+ SkRGBA4f<kUnpremul_SkAlphaType>. For convenience, this type can also be referred to
+ as SkColor4f.
+*/
+template <SkAlphaType kAT>
+struct SkRGBA4f {
+ float fR; //!< red component
+ float fG; //!< green component
+ float fB; //!< blue component
+ float fA; //!< alpha component
+
+ /** Compares SkRGBA4f with other, and returns true if all components are equal.
+
+ @param other SkRGBA4f to compare
+ @return true if SkRGBA4f equals other
+ */
+ bool operator==(const SkRGBA4f& other) const {
+ return fA == other.fA && fR == other.fR && fG == other.fG && fB == other.fB;
+ }
+
+ /** Compares SkRGBA4f with other, and returns true if not all components are equal.
+
+ @param other SkRGBA4f to compare
+ @return true if SkRGBA4f is not equal to other
+ */
+ bool operator!=(const SkRGBA4f& other) const {
+ return !(*this == other);
+ }
+
+ /** Returns SkRGBA4f multiplied by scale.
+
+ @param scale value to multiply by
+ @return SkRGBA4f as (fR * scale, fG * scale, fB * scale, fA * scale)
+ */
+ SkRGBA4f operator*(float scale) const {
+ return { fR * scale, fG * scale, fB * scale, fA * scale };
+ }
+
+ /** Returns SkRGBA4f multiplied component-wise by scale.
+
+ @param scale SkRGBA4f to multiply by
+ @return SkRGBA4f as (fR * scale.fR, fG * scale.fG, fB * scale.fB, fA * scale.fA)
+ */
+ SkRGBA4f operator*(const SkRGBA4f& scale) const {
+ return { fR * scale.fR, fG * scale.fG, fB * scale.fB, fA * scale.fA };
+ }
+
+ /** Returns a pointer to components of SkRGBA4f, for array access.
+
+ @return pointer to array [fR, fG, fB, fA]
+ */
+ const float* vec() const { return &fR; }
+
+ /** Returns a pointer to components of SkRGBA4f, for array access.
+
+ @return pointer to array [fR, fG, fB, fA]
+ */
+ float* vec() { return &fR; }
+
+ /** As a std::array<float, 4> */
+ std::array<float, 4> array() const { return {fR, fG, fB, fA}; }
+
+ /** Returns one component. Asserts if index is out of range and SK_DEBUG is defined.
+
+ @param index one of: 0 (fR), 1 (fG), 2 (fB), 3 (fA)
+ @return value corresponding to index
+ */
+ float operator[](int index) const {
+ SkASSERT(index >= 0 && index < 4);
+ return this->vec()[index];
+ }
+
+ /** Returns one component. Asserts if index is out of range and SK_DEBUG is defined.
+
+ @param index one of: 0 (fR), 1 (fG), 2 (fB), 3 (fA)
+ @return value corresponding to index
+ */
+ float& operator[](int index) {
+ SkASSERT(index >= 0 && index < 4);
+ return this->vec()[index];
+ }
+
+ /** Returns true if SkRGBA4f is an opaque color. Asserts if fA is out of range and
+ SK_DEBUG is defined.
+
+ @return true if SkRGBA4f is opaque
+ */
+ bool isOpaque() const {
+ SkASSERT(fA <= 1.0f && fA >= 0.0f);
+ return fA == 1.0f;
+ }
+
+ /** Returns true if all channels are in [0, 1]. */
+ bool fitsInBytes() const {
+ SkASSERT(fA >= 0.0f && fA <= 1.0f);
+ return fR >= 0.0f && fR <= 1.0f &&
+ fG >= 0.0f && fG <= 1.0f &&
+ fB >= 0.0f && fB <= 1.0f;
+ }
+
+ /** Returns closest SkRGBA4f to SkColor. Only allowed if SkRGBA4f is unpremultiplied.
+
+ @param color Color with Alpha, red, blue, and green components
+ @return SkColor as SkRGBA4f
+
+ example: https://fiddle.skia.org/c/@RGBA4f_FromColor
+ */
+ static SkRGBA4f FromColor(SkColor color); // impl. depends on kAT
+
+ /** Returns closest SkColor to SkRGBA4f. Only allowed if SkRGBA4f is unpremultiplied.
+
+ @return color as SkColor
+
+ example: https://fiddle.skia.org/c/@RGBA4f_toSkColor
+ */
+ SkColor toSkColor() const; // impl. depends on kAT
+
+ /** Returns closest SkRGBA4f to SkPMColor. Only allowed if SkRGBA4f is premultiplied.
+
+ @return SkPMColor as SkRGBA4f
+ */
+ static SkRGBA4f FromPMColor(SkPMColor); // impl. depends on kAT
+
+ /** Returns SkRGBA4f premultiplied by alpha. Asserts at compile time if SkRGBA4f is
+ already premultiplied.
+
+ @return premultiplied color
+ */
+ SkRGBA4f<kPremul_SkAlphaType> premul() const {
+ static_assert(kAT == kUnpremul_SkAlphaType, "");
+ return { fR * fA, fG * fA, fB * fA, fA };
+ }
+
+ /** Returns SkRGBA4f unpremultiplied by alpha. Asserts at compile time if SkRGBA4f is
+ already unpremultiplied.
+
+ @return unpremultiplied color
+ */
+ SkRGBA4f<kUnpremul_SkAlphaType> unpremul() const {
+ static_assert(kAT == kPremul_SkAlphaType, "");
+
+ if (fA == 0.0f) {
+ return { 0, 0, 0, 0 };
+ } else {
+ float invAlpha = 1 / fA;
+ return { fR * invAlpha, fG * invAlpha, fB * invAlpha, fA };
+ }
+ }
+
+ // This produces bytes in RGBA order (eg GrColor). Impl. is the same, regardless of kAT
+ uint32_t toBytes_RGBA() const;
+ static SkRGBA4f FromBytes_RGBA(uint32_t color);
+
+ SkRGBA4f makeOpaque() const {
+ return { fR, fG, fB, 1.0f };
+ }
+};
+
+/** \struct SkColor4f
+ RGBA color value, holding four floating point components. Color components are always in
+ a known order, and are unpremultiplied.
+
+ This is a specialization of SkRGBA4f. For details, @see SkRGBA4f.
+*/
+using SkColor4f = SkRGBA4f<kUnpremul_SkAlphaType>;
+
+template <> SK_API SkColor4f SkColor4f::FromColor(SkColor);
+template <> SK_API SkColor SkColor4f::toSkColor() const;
+
+namespace SkColors {
+constexpr SkColor4f kTransparent = {0, 0, 0, 0};
+constexpr SkColor4f kBlack = {0, 0, 0, 1};
+constexpr SkColor4f kDkGray = {0.25f, 0.25f, 0.25f, 1};
+constexpr SkColor4f kGray = {0.50f, 0.50f, 0.50f, 1};
+constexpr SkColor4f kLtGray = {0.75f, 0.75f, 0.75f, 1};
+constexpr SkColor4f kWhite = {1, 1, 1, 1};
+constexpr SkColor4f kRed = {1, 0, 0, 1};
+constexpr SkColor4f kGreen = {0, 1, 0, 1};
+constexpr SkColor4f kBlue = {0, 0, 1, 1};
+constexpr SkColor4f kYellow = {1, 1, 0, 1};
+constexpr SkColor4f kCyan = {0, 1, 1, 1};
+constexpr SkColor4f kMagenta = {1, 0, 1, 1};
+} // namespace SkColors
+#endif
diff --git a/src/deps/skia/include/core/SkColorFilter.h b/src/deps/skia/include/core/SkColorFilter.h
new file mode 100644
index 000000000..e949b24ac
--- /dev/null
+++ b/src/deps/skia/include/core/SkColorFilter.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkColorFilter_DEFINED
+#define SkColorFilter_DEFINED
+
+#include "include/core/SkBlendMode.h"
+#include "include/core/SkColor.h"
+#include "include/core/SkFlattenable.h"
+
+class SkColorMatrix;
+
+/**
+* ColorFilters are optional objects in the drawing pipeline. When present in
+* a paint, they are called with the "src" colors, and return new colors, which
+* are then passed onto the next stage (either ImageFilter or Xfermode).
+*
+* All subclasses are required to be reentrant-safe : it must be legal to share
+* the same instance between several threads.
+*/
+class SK_API SkColorFilter : public SkFlattenable {
+public:
+ /** If the filter can be represented by a source color plus Mode, this
+ * returns true, and sets (if not NULL) the color and mode appropriately.
+ * If not, this returns false and ignores the parameters.
+ */
+ bool asAColorMode(SkColor* color, SkBlendMode* mode) const;
+
+ /** If the filter can be represented by a 5x4 matrix, this
+ * returns true, and sets the matrix appropriately.
+ * If not, this returns false and ignores the parameter.
+ */
+ bool asAColorMatrix(float matrix[20]) const;
+
+ // Returns true if the filter is guaranteed to never change the alpha of a color it filters.
+ bool isAlphaUnchanged() const;
+
+ SkColor filterColor(SkColor) const;
+
+ /**
+ * Converts the src color (in src colorspace), into the dst colorspace,
+ * then applies this filter to it, returning the filtered color in the dst colorspace.
+ */
+ SkColor4f filterColor4f(const SkColor4f& srcColor, SkColorSpace* srcCS,
+ SkColorSpace* dstCS) const;
+
+ /** Construct a colorfilter whose effect is to first apply the inner filter and then apply
+ * this filter, applied to the output of the inner filter.
+ *
+ * result = this(inner(...))
+ */
+ sk_sp<SkColorFilter> makeComposed(sk_sp<SkColorFilter> inner) const;
+
+ static sk_sp<SkColorFilter> Deserialize(const void* data, size_t size,
+ const SkDeserialProcs* procs = nullptr);
+
+private:
+ SkColorFilter() = default;
+ friend class SkColorFilterBase;
+
+ using INHERITED = SkFlattenable;
+};
+
+class SK_API SkColorFilters {
+public:
+ static sk_sp<SkColorFilter> Compose(sk_sp<SkColorFilter> outer, sk_sp<SkColorFilter> inner) {
+ return outer ? outer->makeComposed(inner) : inner;
+ }
+ static sk_sp<SkColorFilter> Blend(SkColor c, SkBlendMode mode);
+ static sk_sp<SkColorFilter> Matrix(const SkColorMatrix&);
+ static sk_sp<SkColorFilter> Matrix(const float rowMajor[20]);
+
+ // A version of Matrix which operates in HSLA space instead of RGBA.
+ // I.e. HSLA-to-RGBA(Matrix(RGBA-to-HSLA(input))).
+ static sk_sp<SkColorFilter> HSLAMatrix(const SkColorMatrix&);
+ static sk_sp<SkColorFilter> HSLAMatrix(const float rowMajor[20]);
+
+ static sk_sp<SkColorFilter> LinearToSRGBGamma();
+ static sk_sp<SkColorFilter> SRGBToLinearGamma();
+ static sk_sp<SkColorFilter> Lerp(float t, sk_sp<SkColorFilter> dst, sk_sp<SkColorFilter> src);
+
+private:
+ SkColorFilters() = delete;
+};
+
+#endif
diff --git a/src/deps/skia/include/core/SkColorPriv.h b/src/deps/skia/include/core/SkColorPriv.h
new file mode 100644
index 000000000..29f64339b
--- /dev/null
+++ b/src/deps/skia/include/core/SkColorPriv.h
@@ -0,0 +1,152 @@
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkColorPriv_DEFINED
+#define SkColorPriv_DEFINED
+
+#include "include/core/SkColor.h"
+#include "include/core/SkMath.h"
+#include "include/private/SkTPin.h"
+#include "include/private/SkTo.h"
+
+/** Turn 0..255 into 0..256 by adding 1 at the half-way point. Used to turn a
+ byte into a scale value, so that we can say scale * value >> 8 instead of
+ alpha * value / 255.
+
+ In debugging, asserts that alpha is 0..255
+*/
+static inline unsigned SkAlpha255To256(U8CPU alpha) {
+ SkASSERT(SkToU8(alpha) == alpha);
+ // this one assues that blending on top of an opaque dst keeps it that way
+ // even though it is less accurate than a+(a>>7) for non-opaque dsts
+ return alpha + 1;
+}
+
+/** Multiplify value by 0..256, and shift the result down 8
+ (i.e. return (value * alpha256) >> 8)
+ */
+#define SkAlphaMul(value, alpha256) (((value) * (alpha256)) >> 8)
+
+static inline U8CPU SkUnitScalarClampToByte(SkScalar x) {
+ return static_cast<U8CPU>(SkTPin(x, 0.0f, 1.0f) * 255 + 0.5);
+}
+
+#define SK_A32_BITS 8
+#define SK_R32_BITS 8
+#define SK_G32_BITS 8
+#define SK_B32_BITS 8
+
+#define SK_A32_MASK ((1 << SK_A32_BITS) - 1)
+#define SK_R32_MASK ((1 << SK_R32_BITS) - 1)
+#define SK_G32_MASK ((1 << SK_G32_BITS) - 1)
+#define SK_B32_MASK ((1 << SK_B32_BITS) - 1)
+
+/*
+ * Skia's 32bit backend only supports 1 swizzle order at a time (compile-time).
+ * This is specified by SK_R32_SHIFT=0 or SK_R32_SHIFT=16.
+ *
+ * For easier compatibility with Skia's GPU backend, we further restrict these
+ * to either (in memory-byte-order) RGBA or BGRA. Note that this "order" does
+ * not directly correspond to the same shift-order, since we have to take endianess
+ * into account.
+ *
+ * Here we enforce this constraint.
+ */
+
+#define SK_RGBA_R32_SHIFT 0
+#define SK_RGBA_G32_SHIFT 8
+#define SK_RGBA_B32_SHIFT 16
+#define SK_RGBA_A32_SHIFT 24
+
+#define SK_BGRA_B32_SHIFT 0
+#define SK_BGRA_G32_SHIFT 8
+#define SK_BGRA_R32_SHIFT 16
+#define SK_BGRA_A32_SHIFT 24
+
+#if defined(SK_PMCOLOR_IS_RGBA) || defined(SK_PMCOLOR_IS_BGRA)
+ #error "Configure PMCOLOR by setting SK_R32_SHIFT."
+#endif
+
+// Deduce which SK_PMCOLOR_IS_ to define from the _SHIFT defines
+
+#if (SK_A32_SHIFT == SK_RGBA_A32_SHIFT && \
+ SK_R32_SHIFT == SK_RGBA_R32_SHIFT && \
+ SK_G32_SHIFT == SK_RGBA_G32_SHIFT && \
+ SK_B32_SHIFT == SK_RGBA_B32_SHIFT)
+ #define SK_PMCOLOR_IS_RGBA
+#elif (SK_A32_SHIFT == SK_BGRA_A32_SHIFT && \
+ SK_R32_SHIFT == SK_BGRA_R32_SHIFT && \
+ SK_G32_SHIFT == SK_BGRA_G32_SHIFT && \
+ SK_B32_SHIFT == SK_BGRA_B32_SHIFT)
+ #define SK_PMCOLOR_IS_BGRA
+#else
+ #error "need 32bit packing to be either RGBA or BGRA"
+#endif
+
+#define SkGetPackedA32(packed) ((uint32_t)((packed) << (24 - SK_A32_SHIFT)) >> 24)
+#define SkGetPackedR32(packed) ((uint32_t)((packed) << (24 - SK_R32_SHIFT)) >> 24)
+#define SkGetPackedG32(packed) ((uint32_t)((packed) << (24 - SK_G32_SHIFT)) >> 24)
+#define SkGetPackedB32(packed) ((uint32_t)((packed) << (24 - SK_B32_SHIFT)) >> 24)
+
+#define SkA32Assert(a) SkASSERT((unsigned)(a) <= SK_A32_MASK)
+#define SkR32Assert(r) SkASSERT((unsigned)(r) <= SK_R32_MASK)
+#define SkG32Assert(g) SkASSERT((unsigned)(g) <= SK_G32_MASK)
+#define SkB32Assert(b) SkASSERT((unsigned)(b) <= SK_B32_MASK)
+
+/**
+ * Pack the components into a SkPMColor, checking (in the debug version) that
+ * the components are 0..255, and are already premultiplied (i.e. alpha >= color)
+ */
+static inline SkPMColor SkPackARGB32(U8CPU a, U8CPU r, U8CPU g, U8CPU b) {
+ SkA32Assert(a);
+ SkASSERT(r <= a);
+ SkASSERT(g <= a);
+ SkASSERT(b <= a);
+
+ return (a << SK_A32_SHIFT) | (r << SK_R32_SHIFT) |
+ (g << SK_G32_SHIFT) | (b << SK_B32_SHIFT);
+}
+
+/**
+ * Same as SkPackARGB32, but this version guarantees to not check that the
+ * values are premultiplied in the debug version.
+ */
+static inline SkPMColor SkPackARGB32NoCheck(U8CPU a, U8CPU r, U8CPU g, U8CPU b) {
+ return (a << SK_A32_SHIFT) | (r << SK_R32_SHIFT) |
+ (g << SK_G32_SHIFT) | (b << SK_B32_SHIFT);
+}
+
+static inline
+SkPMColor SkPremultiplyARGBInline(U8CPU a, U8CPU r, U8CPU g, U8CPU b) {
+ SkA32Assert(a);
+ SkR32Assert(r);
+ SkG32Assert(g);
+ SkB32Assert(b);
+
+ if (a != 255) {
+ r = SkMulDiv255Round(r, a);
+ g = SkMulDiv255Round(g, a);
+ b = SkMulDiv255Round(b, a);
+ }
+ return SkPackARGB32(a, r, g, b);
+}
+
+// When Android is compiled optimizing for size, SkAlphaMulQ doesn't get
+// inlined; forcing inlining significantly improves performance.
+static SK_ALWAYS_INLINE uint32_t SkAlphaMulQ(uint32_t c, unsigned scale) {
+ uint32_t mask = 0xFF00FF;
+
+ uint32_t rb = ((c & mask) * scale) >> 8;
+ uint32_t ag = ((c >> 8) & mask) * scale;
+ return (rb & mask) | (ag & ~mask);
+}
+
+static inline SkPMColor SkPMSrcOver(SkPMColor src, SkPMColor dst) {
+ return src + SkAlphaMulQ(dst, SkAlpha255To256(255 - SkGetPackedA32(src)));
+}
+
+#endif
diff --git a/src/deps/skia/include/core/SkColorSpace.h b/src/deps/skia/include/core/SkColorSpace.h
new file mode 100644
index 000000000..9efd140e2
--- /dev/null
+++ b/src/deps/skia/include/core/SkColorSpace.h
@@ -0,0 +1,245 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkColorSpace_DEFINED
+#define SkColorSpace_DEFINED
+
+#include "include/core/SkRefCnt.h"
+#include "include/private/SkFixed.h"
+#include "include/private/SkOnce.h"
+#include "include/third_party/skcms/skcms.h"
+#include <memory>
+
+class SkData;
+
+/**
+ * Describes a color gamut with primaries and a white point.
+ */
+struct SK_API SkColorSpacePrimaries {
+ float fRX;
+ float fRY;
+ float fGX;
+ float fGY;
+ float fBX;
+ float fBY;
+ float fWX;
+ float fWY;
+
+ /**
+ * Convert primaries and a white point to a toXYZD50 matrix, the preferred color gamut
+ * representation of SkColorSpace.
+ */
+ bool toXYZD50(skcms_Matrix3x3* toXYZD50) const;
+};
+
+namespace SkNamedTransferFn {
+
+// Like SkNamedGamut::kSRGB, keeping this bitwise exactly the same as skcms makes things fastest.
+static constexpr skcms_TransferFunction kSRGB =
+ { 2.4f, (float)(1/1.055), (float)(0.055/1.055), (float)(1/12.92), 0.04045f, 0.0f, 0.0f };
+
+static constexpr skcms_TransferFunction k2Dot2 =
+ { 2.2f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f };
+
+static constexpr skcms_TransferFunction kLinear =
+ { 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f };
+
+static constexpr skcms_TransferFunction kRec2020 =
+ {2.22222f, 0.909672f, 0.0903276f, 0.222222f, 0.0812429f, 0, 0};
+
+static constexpr skcms_TransferFunction kPQ =
+ {-2.0f, -107/128.0f, 1.0f, 32/2523.0f, 2413/128.0f, -2392/128.0f, 8192/1305.0f };
+
+static constexpr skcms_TransferFunction kHLG =
+ {-3.0f, 2.0f, 2.0f, 1/0.17883277f, 0.28466892f, 0.55991073f, 0.0f };
+
+} // namespace SkNamedTransferFn
+
+namespace SkNamedGamut {
+
+static constexpr skcms_Matrix3x3 kSRGB = {{
+ // ICC fixed-point (16.16) representation, taken from skcms. Please keep them exactly in sync.
+ // 0.436065674f, 0.385147095f, 0.143066406f,
+ // 0.222488403f, 0.716873169f, 0.060607910f,
+ // 0.013916016f, 0.097076416f, 0.714096069f,
+ { SkFixedToFloat(0x6FA2), SkFixedToFloat(0x6299), SkFixedToFloat(0x24A0) },
+ { SkFixedToFloat(0x38F5), SkFixedToFloat(0xB785), SkFixedToFloat(0x0F84) },
+ { SkFixedToFloat(0x0390), SkFixedToFloat(0x18DA), SkFixedToFloat(0xB6CF) },
+}};
+
+static constexpr skcms_Matrix3x3 kAdobeRGB = {{
+ // ICC fixed-point (16.16) repesentation of:
+ // 0.60974, 0.20528, 0.14919,
+ // 0.31111, 0.62567, 0.06322,
+ // 0.01947, 0.06087, 0.74457,
+ { SkFixedToFloat(0x9c18), SkFixedToFloat(0x348d), SkFixedToFloat(0x2631) },
+ { SkFixedToFloat(0x4fa5), SkFixedToFloat(0xa02c), SkFixedToFloat(0x102f) },
+ { SkFixedToFloat(0x04fc), SkFixedToFloat(0x0f95), SkFixedToFloat(0xbe9c) },
+}};
+
+static constexpr skcms_Matrix3x3 kDisplayP3 = {{
+ { 0.515102f, 0.291965f, 0.157153f },
+ { 0.241182f, 0.692236f, 0.0665819f },
+ { -0.00104941f, 0.0418818f, 0.784378f },
+}};
+
+static constexpr skcms_Matrix3x3 kRec2020 = {{
+ { 0.673459f, 0.165661f, 0.125100f },
+ { 0.279033f, 0.675338f, 0.0456288f },
+ { -0.00193139f, 0.0299794f, 0.797162f },
+}};
+
+static constexpr skcms_Matrix3x3 kXYZ = {{
+ { 1.0f, 0.0f, 0.0f },
+ { 0.0f, 1.0f, 0.0f },
+ { 0.0f, 0.0f, 1.0f },
+}};
+
+} // namespace SkNamedGamut
+
+class SK_API SkColorSpace : public SkNVRefCnt<SkColorSpace> {
+public:
+ /**
+ * Create the sRGB color space.
+ */
+ static sk_sp<SkColorSpace> MakeSRGB();
+
+ /**
+ * Colorspace with the sRGB primaries, but a linear (1.0) gamma.
+ */
+ static sk_sp<SkColorSpace> MakeSRGBLinear();
+
+ /**
+ * Create an SkColorSpace from a transfer function and a row-major 3x3 transformation to XYZ.
+ */
+ static sk_sp<SkColorSpace> MakeRGB(const skcms_TransferFunction& transferFn,
+ const skcms_Matrix3x3& toXYZ);
+
+ /**
+ * Create an SkColorSpace from a parsed (skcms) ICC profile.
+ */
+ static sk_sp<SkColorSpace> Make(const skcms_ICCProfile&);
+
+ /**
+ * Convert this color space to an skcms ICC profile struct.
+ */
+ void toProfile(skcms_ICCProfile*) const;
+
+ /**
+ * Returns true if the color space gamma is near enough to be approximated as sRGB.
+ */
+ bool gammaCloseToSRGB() const;
+
+ /**
+ * Returns true if the color space gamma is linear.
+ */
+ bool gammaIsLinear() const;
+
+ /**
+ * Sets |fn| to the transfer function from this color space. Returns true if the transfer
+ * function can be represented as coefficients to the standard ICC 7-parameter equation.
+ * Returns false otherwise (eg, PQ, HLG).
+ */
+ bool isNumericalTransferFn(skcms_TransferFunction* fn) const;
+
+ /**
+ * Returns true and sets |toXYZD50| if the color gamut can be described as a matrix.
+ * Returns false otherwise.
+ */
+ bool toXYZD50(skcms_Matrix3x3* toXYZD50) const;
+
+ /**
+ * Returns a hash of the gamut transformation to XYZ D50. Allows for fast equality checking
+ * of gamuts, at the (very small) risk of collision.
+ */
+ uint32_t toXYZD50Hash() const { return fToXYZD50Hash; }
+
+ /**
+ * Returns a color space with the same gamut as this one, but with a linear gamma.
+ * For color spaces whose gamut can not be described in terms of XYZ D50, returns
+ * linear sRGB.
+ */
+ sk_sp<SkColorSpace> makeLinearGamma() const;
+
+ /**
+ * Returns a color space with the same gamut as this one, with with the sRGB transfer
+ * function. For color spaces whose gamut can not be described in terms of XYZ D50, returns
+ * sRGB.
+ */
+ sk_sp<SkColorSpace> makeSRGBGamma() const;
+
+ /**
+ * Returns a color space with the same transfer function as this one, but with the primary
+ * colors rotated. For any XYZ space, this produces a new color space that maps RGB to GBR
+ * (when applied to a source), and maps RGB to BRG (when applied to a destination). For other
+ * types of color spaces, returns nullptr.
+ *
+ * This is used for testing, to construct color spaces that have severe and testable behavior.
+ */
+ sk_sp<SkColorSpace> makeColorSpin() const;
+
+ /**
+ * Returns true if the color space is sRGB.
+ * Returns false otherwise.
+ *
+ * This allows a little bit of tolerance, given that we might see small numerical error
+ * in some cases: converting ICC fixed point to float, converting white point to D50,
+ * rounding decisions on transfer function and matrix.
+ *
+ * This does not consider a 2.2f exponential transfer function to be sRGB. While these
+ * functions are similar (and it is sometimes useful to consider them together), this
+ * function checks for logical equality.
+ */
+ bool isSRGB() const;
+
+ /**
+ * Returns nullptr on failure. Fails when we fallback to serializing ICC data and
+ * the data is too large to serialize.
+ */
+ sk_sp<SkData> serialize() const;
+
+ /**
+ * If |memory| is nullptr, returns the size required to serialize.
+ * Otherwise, serializes into |memory| and returns the size.
+ */
+ size_t writeToMemory(void* memory) const;
+
+ static sk_sp<SkColorSpace> Deserialize(const void* data, size_t length);
+
+ /**
+ * If both are null, we return true. If one is null and the other is not, we return false.
+ * If both are non-null, we do a deeper compare.
+ */
+ static bool Equals(const SkColorSpace*, const SkColorSpace*);
+
+ void transferFn(float gabcdef[7]) const; // DEPRECATED: Remove when webview usage is gone
+ void transferFn(skcms_TransferFunction* fn) const;
+ void invTransferFn(skcms_TransferFunction* fn) const;
+ void gamutTransformTo(const SkColorSpace* dst, skcms_Matrix3x3* src_to_dst) const;
+
+ uint32_t transferFnHash() const { return fTransferFnHash; }
+ uint64_t hash() const { return (uint64_t)fTransferFnHash << 32 | fToXYZD50Hash; }
+
+private:
+ friend class SkColorSpaceSingletonFactory;
+
+ SkColorSpace(const skcms_TransferFunction& transferFn, const skcms_Matrix3x3& toXYZ);
+
+ void computeLazyDstFields() const;
+
+ uint32_t fTransferFnHash;
+ uint32_t fToXYZD50Hash;
+
+ skcms_TransferFunction fTransferFn;
+ skcms_Matrix3x3 fToXYZD50;
+
+ mutable skcms_TransferFunction fInvTransferFn;
+ mutable skcms_Matrix3x3 fFromXYZD50;
+ mutable SkOnce fLazyDstFieldsOnce;
+};
+
+#endif
diff --git a/src/deps/skia/include/core/SkContourMeasure.h b/src/deps/skia/include/core/SkContourMeasure.h
new file mode 100644
index 000000000..08a50b110
--- /dev/null
+++ b/src/deps/skia/include/core/SkContourMeasure.h
@@ -0,0 +1,131 @@
+/*
+ * Copyright 2018 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkContourMeasure_DEFINED
+#define SkContourMeasure_DEFINED
+
+#include "include/core/SkPath.h"
+#include "include/core/SkRefCnt.h"
+#include "include/private/SkTDArray.h"
+
+struct SkConic;
+
+class SK_API SkContourMeasure : public SkRefCnt {
+public:
+ /** Return the length of the contour.
+ */
+ SkScalar length() const { return fLength; }
+
+ /** Pins distance to 0 <= distance <= length(), and then computes the corresponding
+ * position and tangent.
+ */
+ bool SK_WARN_UNUSED_RESULT getPosTan(SkScalar distance, SkPoint* position,
+ SkVector* tangent) const;
+
+ enum MatrixFlags {
+ kGetPosition_MatrixFlag = 0x01,
+ kGetTangent_MatrixFlag = 0x02,
+ kGetPosAndTan_MatrixFlag = kGetPosition_MatrixFlag | kGetTangent_MatrixFlag
+ };
+
+ /** Pins distance to 0 <= distance <= getLength(), and then computes
+ the corresponding matrix (by calling getPosTan).
+ Returns false if there is no path, or a zero-length path was specified, in which case
+ matrix is unchanged.
+ */
+ bool SK_WARN_UNUSED_RESULT getMatrix(SkScalar distance, SkMatrix* matrix,
+ MatrixFlags flags = kGetPosAndTan_MatrixFlag) const;
+
+ /** Given a start and stop distance, return in dst the intervening segment(s).
+ If the segment is zero-length, return false, else return true.
+ startD and stopD are pinned to legal values (0..getLength()). If startD > stopD
+ then return false (and leave dst untouched).
+ Begin the segment with a moveTo if startWithMoveTo is true
+ */
+ bool SK_WARN_UNUSED_RESULT getSegment(SkScalar startD, SkScalar stopD, SkPath* dst,
+ bool startWithMoveTo) const;
+
+ /** Return true if the contour is closed()
+ */
+ bool isClosed() const { return fIsClosed; }
+
+private:
+ struct Segment {
+ SkScalar fDistance; // total distance up to this point
+ unsigned fPtIndex; // index into the fPts array
+ unsigned fTValue : 30;
+ unsigned fType : 2; // actually the enum SkSegType
+ // See SkPathMeasurePriv.h
+
+ SkScalar getScalarT() const;
+
+ static const Segment* Next(const Segment* seg) {
+ unsigned ptIndex = seg->fPtIndex;
+ do {
+ ++seg;
+ } while (seg->fPtIndex == ptIndex);
+ return seg;
+ }
+
+ };
+
+ const SkTDArray<Segment> fSegments;
+ const SkTDArray<SkPoint> fPts; // Points used to define the segments
+
+ const SkScalar fLength;
+ const bool fIsClosed;
+
+ SkContourMeasure(SkTDArray<Segment>&& segs, SkTDArray<SkPoint>&& pts,
+ SkScalar length, bool isClosed);
+ ~SkContourMeasure() override {}
+
+ const Segment* distanceToSegment(SkScalar distance, SkScalar* t) const;
+
+ friend class SkContourMeasureIter;
+};
+
+class SK_API SkContourMeasureIter {
+public:
+ SkContourMeasureIter();
+ /**
+ * Initialize the Iter with a path.
+ * The parts of the path that are needed are copied, so the client is free to modify/delete
+ * the path after this call.
+ *
+ * resScale controls the precision of the measure. values > 1 increase the
+ * precision (and possibly slow down the computation).
+ */
+ SkContourMeasureIter(const SkPath& path, bool forceClosed, SkScalar resScale = 1);
+ ~SkContourMeasureIter();
+
+ /**
+ * Reset the Iter with a path.
+ * The parts of the path that are needed are copied, so the client is free to modify/delete
+ * the path after this call.
+ */
+ void reset(const SkPath& path, bool forceClosed, SkScalar resScale = 1);
+
+ /**
+ * Iterates through contours in path, returning a contour-measure object for each contour
+ * in the path. Returns null when it is done.
+ *
+ * This only returns non-zero length contours, where a contour is the segments between
+ * a kMove_Verb and either ...
+ * - the next kMove_Verb
+ * - kClose_Verb (1 or more)
+ * - kDone_Verb
+ * If it encounters a zero-length contour, it is skipped.
+ */
+ sk_sp<SkContourMeasure> next();
+
+private:
+ class Impl;
+
+ std::unique_ptr<Impl> fImpl;
+};
+
+#endif
diff --git a/src/deps/skia/include/core/SkCoverageMode.h b/src/deps/skia/include/core/SkCoverageMode.h
new file mode 100644
index 000000000..ea5b73d1a
--- /dev/null
+++ b/src/deps/skia/include/core/SkCoverageMode.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2018 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkCoverageMode_DEFINED
+#define SkCoverageMode_DEFINED
+
+#include "include/core/SkTypes.h"
+
+/**
+ * Describes geometric operations (ala SkRegion::Op) that can be applied to coverage bytes.
+ * These can be thought of as variants of porter-duff (SkBlendMode) modes, but only applied
+ * to the alpha channel.
+ *
+ * See SkMaskFilter for ways to use these when combining two different masks.
+ */
+enum class SkCoverageMode {
+ kUnion, // A ∪ B A+B-A*B
+ kIntersect, // A ∩ B A*B
+ kDifference, // A - B A*(1-B)
+ kReverseDifference, // B - A B*(1-A)
+ kXor, // A ⊕ B A+B-2*A*B
+
+ kLast = kXor,
+};
+
+#endif
diff --git a/src/deps/skia/include/core/SkCubicMap.h b/src/deps/skia/include/core/SkCubicMap.h
new file mode 100644
index 000000000..7389b92af
--- /dev/null
+++ b/src/deps/skia/include/core/SkCubicMap.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2018 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkCubicMap_DEFINED
+#define SkCubicMap_DEFINED
+
+#include "include/core/SkPoint.h"
+
+/**
+ * Fast evaluation of a cubic ease-in / ease-out curve. This is defined as a parametric cubic
+ * curve inside the unit square.
+ *
+ * pt[0] is implicitly { 0, 0 }
+ * pt[3] is implicitly { 1, 1 }
+ * pts[1,2].X are inside the unit [0..1]
+ */
+class SK_API SkCubicMap {
+public:
+ SkCubicMap(SkPoint p1, SkPoint p2);
+
+ static bool IsLinear(SkPoint p1, SkPoint p2) {
+ return SkScalarNearlyEqual(p1.fX, p1.fY) && SkScalarNearlyEqual(p2.fX, p2.fY);
+ }
+
+ float computeYFromX(float x) const;
+
+ SkPoint computeFromT(float t) const;
+
+private:
+ enum Type {
+ kLine_Type, // x == y
+ kCubeRoot_Type, // At^3 == x
+ kSolver_Type, // general monotonic cubic solver
+ };
+
+ SkPoint fCoeff[3];
+ Type fType;
+};
+
+#endif
+
diff --git a/src/deps/skia/include/core/SkCustomMesh.h b/src/deps/skia/include/core/SkCustomMesh.h
new file mode 100644
index 000000000..f9bddf338
--- /dev/null
+++ b/src/deps/skia/include/core/SkCustomMesh.h
@@ -0,0 +1,202 @@
+/*
+ * Copyright 2021 Google LLC
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkCustomMesh_DEFINED
+#define SkCustomMesh_DEFINED
+
+#include "include/core/SkTypes.h"
+
+#ifdef SK_ENABLE_SKSL
+#include "include/core/SkColorSpace.h"
+#include "include/core/SkImageInfo.h"
+#include "include/core/SkRect.h"
+#include "include/core/SkRefCnt.h"
+#include "include/core/SkSpan.h"
+#include "include/core/SkString.h"
+
+#include <vector>
+
+namespace SkSL { struct Program; }
+
+/**
+ * A specification for custom meshes. Specifies the vertex buffer attributes and stride, the
+ * vertex program that produces a user-defined set of varyings, a fragment program that ingests
+ * the interpolated varyings and produces local coordinates and optionally a color.
+ *
+ * The signature of the vertex program must be:
+ * float2 main(Attributes, out Varyings)
+ * where the return value is a local position that will be transformed by SkCanvas's matrix.
+ *
+ * The signature of the fragment program must be either:
+ * (float2|void) main(Varyings)
+ * or
+ * (float2|void) main(Varyings, out (half4|float4) color)
+ *
+ * where the return value is the local coordinates that will be used to access SkShader. If the
+ * return type is void then the interpolated position from vertex shader return is used as the local
+ * coordinate. If the color variant is used it will be blended with SkShader (or SkPaint color in
+ * absence of a shader) using the SkBlender provided to the SkCanvas draw call.
+ */
+class SkCustomMeshSpecification : public SkNVRefCnt<SkCustomMeshSpecification> {
+public:
+ /** These values are enforced when creating a specification. */
+ static constexpr size_t kMaxStride = 1024;
+ static constexpr size_t kMaxAttributes = 8;
+ static constexpr size_t kStrideAlignment = 4;
+ static constexpr size_t kOffsetAlignment = 4;
+ static constexpr size_t kMaxVaryings = 6;
+
+ struct Attribute {
+ enum class Type : uint32_t { // CPU representation Shader Type
+ kFloat, // float float
+ kFloat2, // two floats float2
+ kFloat3, // three floats float3
+ kFloat4, // four floats float4
+ kUByte4_unorm, // four bytes half4
+
+ kLast = kUByte4_unorm
+ };
+ Type type;
+ size_t offset;
+ SkString name;
+ };
+
+ struct Varying {
+ enum class Type : uint32_t {
+ kFloat, // "float"
+ kFloat2, // "float2"
+ kFloat3, // "float3"
+ kFloat4, // "float4"
+ kHalf, // "half"
+ kHalf2, // "half2"
+ kHalf3, // "half3"
+ kHalf4, // "half4"
+
+ kLast = kHalf4
+ };
+ Type type;
+ SkString name;
+ };
+
+ ~SkCustomMeshSpecification();
+
+ struct Result {
+ sk_sp<SkCustomMeshSpecification> specification;
+ SkString error;
+ };
+
+ /**
+ * If successful the return is a specification and an empty error string. Otherwise, it is a
+ * null specification a non-empty error string.
+ *
+ * @param attributes The vertex attributes that will be consumed by 'vs'. Attributes need
+ * not be tightly packed but attribute offsets must be aligned to
+ * kOffsetAlignment and offset + size may not be greater than
+ * 'vertexStride'. At least one attribute is required.
+ * @param vertexStride The offset between successive attribute values. This must be aligned to
+ * kStrideAlignment.
+ * @param varyings The varyings that will be written by 'vs' and read by 'fs'. This may
+ * be empty.
+ * @param vs The vertex shader code that computes a vertex position and the varyings
+ * from the attributes.
+ * @param fs The fragment code that computes a local coordinate and optionally a
+ * color from the varyings. The local coordinate is used to sample
+ * SkShader.
+ * @param cs The colorspace of the color produced by 'fs'. Ignored if 'fs's main()
+ * function does not have a color out param.
+ * @param at The alpha type of the color produced by 'fs'. Ignored if 'fs's main()
+ * function does not have a color out param. Cannot be kUnknown.
+ */
+ static Result Make(SkSpan<const Attribute> attributes,
+ size_t vertexStride,
+ SkSpan<const Varying> varyings,
+ const SkString& vs,
+ const SkString& fs,
+ sk_sp<SkColorSpace> cs = SkColorSpace::MakeSRGB(),
+ SkAlphaType at = kPremul_SkAlphaType);
+
+ SkSpan<const Attribute> attributes() const { return SkMakeSpan(fAttributes); }
+
+ size_t stride() const { return fStride; }
+
+private:
+ friend struct SkCustomMeshSpecificationPriv;
+
+ enum class ColorType {
+ kNone,
+ kHalf4,
+ kFloat4,
+ };
+
+ static Result MakeFromSourceWithStructs(SkSpan<const Attribute> attributes,
+ size_t stride,
+ SkSpan<const Varying> varyings,
+ const SkString& vs,
+ const SkString& fs,
+ sk_sp<SkColorSpace> cs,
+ SkAlphaType at);
+
+ SkCustomMeshSpecification(SkSpan<const Attribute>,
+ size_t,
+ SkSpan<const Varying>,
+ std::unique_ptr<SkSL::Program>,
+ std::unique_ptr<SkSL::Program>,
+ ColorType,
+ bool hasLocalCoords,
+ sk_sp<SkColorSpace>,
+ SkAlphaType);
+
+ SkCustomMeshSpecification(const SkCustomMeshSpecification&) = delete;
+ SkCustomMeshSpecification(SkCustomMeshSpecification&&) = delete;
+
+ SkCustomMeshSpecification& operator=(const SkCustomMeshSpecification&) = delete;
+ SkCustomMeshSpecification& operator=(SkCustomMeshSpecification&&) = delete;
+
+ const std::vector<Attribute> fAttributes;
+ const std::vector<Varying> fVaryings;
+ std::unique_ptr<SkSL::Program> fVS;
+ std::unique_ptr<SkSL::Program> fFS;
+ size_t fStride;
+ uint32_t fHash;
+ ColorType fColorType;
+ bool fHasLocalCoords;
+ sk_sp<SkColorSpace> fColorSpace;
+ SkAlphaType fAlphaType;
+};
+
+/**
+ * This is a placeholder object. We will want something that allows the client to incrementally
+ * update the mesh that can be synchronized with the GPU backend without requiring extra copies.
+ *
+ * A buffer of vertices, a topology, optionally indices, and a compatible SkCustomMeshSpecification.
+ * The data in 'vb' is expected to contain the attributes described in 'spec' for 'vcount' vertices.
+ * The size of the buffer must be at least spec->stride()*vcount (even if vertex attributes contains
+ * pad at the end of the stride). If 'bounds' does not contain all points output by 'spec''s vertex
+ * program when applied to the vertices in 'vb' a draw of the custom mesh produces undefined
+ * results.
+ *
+ * If indices is null then then 'icount' must be <= 0. 'vcount' vertices will be selected from 'vb'
+ * to create the topology indicated by 'mode'.
+ *
+ * If indices is not null then icount must be >= 3. 'vb' will be indexed by 'icount' successive
+ * values in 'indices' to create the topology indicated by 'mode'. The values in 'indices' must be
+ * less than 'vcount'
+ */
+struct SkCustomMesh {
+ enum class Mode { kTriangles, kTriangleStrip };
+ sk_sp<SkCustomMeshSpecification> spec;
+ Mode mode = Mode::kTriangles;
+ SkRect bounds = SkRect::MakeEmpty();
+ const void* vb = nullptr;
+ int vcount = 0;
+ const uint16_t* indices = nullptr;
+ int icount = 0;
+};
+
+#endif // SK_ENABLE_SKSL
+
+#endif
diff --git a/src/deps/skia/include/core/SkData.h b/src/deps/skia/include/core/SkData.h
new file mode 100644
index 000000000..2a4b40d5f
--- /dev/null
+++ b/src/deps/skia/include/core/SkData.h
@@ -0,0 +1,188 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkData_DEFINED
+#define SkData_DEFINED
+
+#include <stdio.h>
+
+#include "include/core/SkRefCnt.h"
+
+class SkStream;
+
+/**
+ * SkData holds an immutable data buffer. Not only is the data immutable,
+ * but the actual ptr that is returned (by data() or bytes()) is guaranteed
+ * to always be the same for the life of this instance.
+ */
+class SK_API SkData final : public SkNVRefCnt<SkData> {
+public:
+ /**
+ * Returns the number of bytes stored.
+ */
+ size_t size() const { return fSize; }
+
+ bool isEmpty() const { return 0 == fSize; }
+
+ /**
+ * Returns the ptr to the data.
+ */
+ const void* data() const { return fPtr; }
+
+ /**
+ * Like data(), returns a read-only ptr into the data, but in this case
+ * it is cast to uint8_t*, to make it easy to add an offset to it.
+ */
+ const uint8_t* bytes() const {
+ return reinterpret_cast<const uint8_t*>(fPtr);
+ }
+
+ /**
+ * USE WITH CAUTION.
+ * This call will assert that the refcnt is 1, as a precaution against modifying the
+ * contents when another client/thread has access to the data.
+ */
+ void* writable_data() {
+ if (fSize) {
+ // only assert we're unique if we're not empty
+ SkASSERT(this->unique());
+ }
+ return const_cast<void*>(fPtr);
+ }
+
+ /**
+ * Helper to copy a range of the data into a caller-provided buffer.
+ * Returns the actual number of bytes copied, after clamping offset and
+ * length to the size of the data. If buffer is NULL, it is ignored, and
+ * only the computed number of bytes is returned.
+ */
+ size_t copyRange(size_t offset, size_t length, void* buffer) const;
+
+ /**
+ * Returns true if these two objects have the same length and contents,
+ * effectively returning 0 == memcmp(...)
+ */
+ bool equals(const SkData* other) const;
+
+ /**
+ * Function that, if provided, will be called when the SkData goes out
+ * of scope, allowing for custom allocation/freeing of the data's contents.
+ */
+ typedef void (*ReleaseProc)(const void* ptr, void* context);
+
+ /**
+ * Create a new dataref by copying the specified data
+ */
+ static sk_sp<SkData> MakeWithCopy(const void* data, size_t length);
+
+
+ /**
+ * Create a new data with uninitialized contents. The caller should call writable_data()
+ * to write into the buffer, but this must be done before another ref() is made.
+ */
+ static sk_sp<SkData> MakeUninitialized(size_t length);
+
+ /**
+ * Create a new data with zero-initialized contents. The caller should call writable_data()
+ * to write into the buffer, but this must be done before another ref() is made.
+ */
+ static sk_sp<SkData> MakeZeroInitialized(size_t length);
+
+ /**
+ * Create a new dataref by copying the specified c-string
+ * (a null-terminated array of bytes). The returned SkData will have size()
+ * equal to strlen(cstr) + 1. If cstr is NULL, it will be treated the same
+ * as "".
+ */
+ static sk_sp<SkData> MakeWithCString(const char cstr[]);
+
+ /**
+ * Create a new dataref, taking the ptr as is, and using the
+ * releaseproc to free it. The proc may be NULL.
+ */
+ static sk_sp<SkData> MakeWithProc(const void* ptr, size_t length, ReleaseProc proc, void* ctx);
+
+ /**
+ * Call this when the data parameter is already const and will outlive the lifetime of the
+ * SkData. Suitable for with const globals.
+ */
+ static sk_sp<SkData> MakeWithoutCopy(const void* data, size_t length) {
+ return MakeWithProc(data, length, NoopReleaseProc, nullptr);
+ }
+
+ /**
+ * Create a new dataref from a pointer allocated by malloc. The Data object
+ * takes ownership of that allocation, and will handling calling sk_free.
+ */
+ static sk_sp<SkData> MakeFromMalloc(const void* data, size_t length);
+
+ /**
+ * Create a new dataref the file with the specified path.
+ * If the file cannot be opened, this returns NULL.
+ */
+ static sk_sp<SkData> MakeFromFileName(const char path[]);
+
+ /**
+ * Create a new dataref from a stdio FILE.
+ * This does not take ownership of the FILE, nor close it.
+ * The caller is free to close the FILE at its convenience.
+ * The FILE must be open for reading only.
+ * Returns NULL on failure.
+ */
+ static sk_sp<SkData> MakeFromFILE(FILE* f);
+
+ /**
+ * Create a new dataref from a file descriptor.
+ * This does not take ownership of the file descriptor, nor close it.
+ * The caller is free to close the file descriptor at its convenience.
+ * The file descriptor must be open for reading only.
+ * Returns NULL on failure.
+ */
+ static sk_sp<SkData> MakeFromFD(int fd);
+
+ /**
+ * Attempt to read size bytes into a SkData. If the read succeeds, return the data,
+ * else return NULL. Either way the stream's cursor may have been changed as a result
+ * of calling read().
+ */
+ static sk_sp<SkData> MakeFromStream(SkStream*, size_t size);
+
+ /**
+ * Create a new dataref using a subset of the data in the specified
+ * src dataref.
+ */
+ static sk_sp<SkData> MakeSubset(const SkData* src, size_t offset, size_t length);
+
+ /**
+ * Returns a new empty dataref (or a reference to a shared empty dataref).
+ * New or shared, the caller must see that unref() is eventually called.
+ */
+ static sk_sp<SkData> MakeEmpty();
+
+private:
+ friend class SkNVRefCnt<SkData>;
+ ReleaseProc fReleaseProc;
+ void* fReleaseProcContext;
+ const void* fPtr;
+ size_t fSize;
+
+ SkData(const void* ptr, size_t size, ReleaseProc, void* context);
+ explicit SkData(size_t size); // inplace new/delete
+ ~SkData();
+
+ // Ensure the unsized delete is called.
+ void operator delete(void* p);
+
+ // shared internal factory
+ static sk_sp<SkData> PrivateNewWithCopy(const void* srcOrNull, size_t length);
+
+ static void NoopReleaseProc(const void*, void*); // {}
+
+ using INHERITED = SkRefCnt;
+};
+
+#endif
diff --git a/src/deps/skia/include/core/SkDataTable.h b/src/deps/skia/include/core/SkDataTable.h
new file mode 100644
index 000000000..a6a510b7b
--- /dev/null
+++ b/src/deps/skia/include/core/SkDataTable.h
@@ -0,0 +1,118 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkDataTable_DEFINED
+#define SkDataTable_DEFINED
+
+#include "include/core/SkData.h"
+#include "include/private/SkTDArray.h"
+
+/**
+ * Like SkData, SkDataTable holds an immutable data buffer. The data buffer is
+ * organized into a table of entries, each with a length, so the entries are
+ * not required to all be the same size.
+ */
+class SK_API SkDataTable : public SkRefCnt {
+public:
+ /**
+ * Returns true if the table is empty (i.e. has no entries).
+ */
+ bool isEmpty() const { return 0 == fCount; }
+
+ /**
+ * Return the number of entries in the table. 0 for an empty table
+ */
+ int count() const { return fCount; }
+
+ /**
+ * Return the size of the index'th entry in the table. The caller must
+ * ensure that index is valid for this table.
+ */
+ size_t atSize(int index) const;
+
+ /**
+ * Return a pointer to the data of the index'th entry in the table.
+ * The caller must ensure that index is valid for this table.
+ *
+ * @param size If non-null, this returns the byte size of this entry. This
+ * will be the same value that atSize(index) would return.
+ */
+ const void* at(int index, size_t* size = nullptr) const;
+
+ template <typename T>
+ const T* atT(int index, size_t* size = nullptr) const {
+ return reinterpret_cast<const T*>(this->at(index, size));
+ }
+
+ /**
+ * Returns the index'th entry as a c-string, and assumes that the trailing
+ * null byte had been copied into the table as well.
+ */
+ const char* atStr(int index) const {
+ size_t size;
+ const char* str = this->atT<const char>(index, &size);
+ SkASSERT(strlen(str) + 1 == size);
+ return str;
+ }
+
+ typedef void (*FreeProc)(void* context);
+
+ static sk_sp<SkDataTable> MakeEmpty();
+
+ /**
+ * Return a new DataTable that contains a copy of the data stored in each
+ * "array".
+ *
+ * @param ptrs array of points to each element to be copied into the table.
+ * @param sizes array of byte-lengths for each entry in the corresponding
+ * ptrs[] array.
+ * @param count the number of array elements in ptrs[] and sizes[] to copy.
+ */
+ static sk_sp<SkDataTable> MakeCopyArrays(const void * const * ptrs,
+ const size_t sizes[], int count);
+
+ /**
+ * Return a new table that contains a copy of the data in array.
+ *
+ * @param array contiguous array of data for all elements to be copied.
+ * @param elemSize byte-length for a given element.
+ * @param count the number of entries to be copied out of array. The number
+ * of bytes that will be copied is count * elemSize.
+ */
+ static sk_sp<SkDataTable> MakeCopyArray(const void* array, size_t elemSize, int count);
+
+ static sk_sp<SkDataTable> MakeArrayProc(const void* array, size_t elemSize, int count,
+ FreeProc proc, void* context);
+
+private:
+ struct Dir {
+ const void* fPtr;
+ uintptr_t fSize;
+ };
+
+ int fCount;
+ size_t fElemSize;
+ union {
+ const Dir* fDir;
+ const char* fElems;
+ } fU;
+
+ FreeProc fFreeProc;
+ void* fFreeProcContext;
+
+ SkDataTable();
+ SkDataTable(const void* array, size_t elemSize, int count,
+ FreeProc, void* context);
+ SkDataTable(const Dir*, int count, FreeProc, void* context);
+ ~SkDataTable() override;
+
+ friend class SkDataTableBuilder; // access to Dir
+
+ using INHERITED = SkRefCnt;
+};
+
+#endif
diff --git a/src/deps/skia/include/core/SkDeferredDisplayList.h b/src/deps/skia/include/core/SkDeferredDisplayList.h
new file mode 100644
index 000000000..28e460fa8
--- /dev/null
+++ b/src/deps/skia/include/core/SkDeferredDisplayList.h
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkDeferredDisplayList_DEFINED
+#define SkDeferredDisplayList_DEFINED
+
+#include "include/core/SkRefCnt.h"
+#include "include/core/SkSurfaceCharacterization.h"
+#include "include/core/SkTypes.h"
+
+class SkDeferredDisplayListPriv;
+
+#if SK_SUPPORT_GPU
+#include "include/gpu/GrRecordingContext.h"
+#include "include/private/SkTArray.h"
+#include <map>
+class GrRenderTask;
+class GrRenderTargetProxy;
+#else
+using GrRenderTargetProxy = SkRefCnt;
+#endif
+
+/*
+ * This class contains pre-processed gpu operations that can be replayed into
+ * an SkSurface via SkSurface::draw(SkDeferredDisplayList*).
+ */
+class SkDeferredDisplayList : public SkNVRefCnt<SkDeferredDisplayList> {
+public:
+ SK_API ~SkDeferredDisplayList();
+
+ SK_API const SkSurfaceCharacterization& characterization() const {
+ return fCharacterization;
+ }
+
+#if SK_SUPPORT_GPU
+ /**
+ * Iterate through the programs required by the DDL.
+ */
+ class SK_API ProgramIterator {
+ public:
+ ProgramIterator(GrDirectContext*, SkDeferredDisplayList*);
+ ~ProgramIterator();
+
+ // This returns true if any work was done. Getting a cache hit does not count as work.
+ bool compile();
+ bool done() const;
+ void next();
+
+ private:
+ GrDirectContext* fDContext;
+ const SkTArray<GrRecordingContext::ProgramData>& fProgramData;
+ int fIndex;
+ };
+#endif
+
+ // Provides access to functions that aren't part of the public API.
+ SkDeferredDisplayListPriv priv();
+ const SkDeferredDisplayListPriv priv() const; // NOLINT(readability-const-return-type)
+
+private:
+ friend class GrDrawingManager; // for access to 'fRenderTasks', 'fLazyProxyData', 'fArenas'
+ friend class SkDeferredDisplayListRecorder; // for access to 'fLazyProxyData'
+ friend class SkDeferredDisplayListPriv;
+
+ // This object is the source from which the lazy proxy backing the DDL will pull its backing
+ // texture when the DDL is replayed. It has to be separately ref counted bc the lazy proxy
+ // can outlive the DDL.
+ class LazyProxyData : public SkRefCnt {
+#if SK_SUPPORT_GPU
+ public:
+ // Upon being replayed - this field will be filled in (by the DrawingManager) with the
+ // proxy backing the destination SkSurface. Note that, since there is no good place to
+ // clear it, it can become a dangling pointer. Additionally, since the renderTargetProxy
+ // doesn't get a ref here, the SkSurface that owns it must remain alive until the DDL
+ // is flushed.
+ // TODO: the drawing manager could ref the renderTargetProxy for the DDL and then add
+ // a renderingTask to unref it after the DDL's ops have been executed.
+ GrRenderTargetProxy* fReplayDest = nullptr;
+#endif
+ };
+
+ SK_API SkDeferredDisplayList(const SkSurfaceCharacterization& characterization,
+ sk_sp<GrRenderTargetProxy> fTargetProxy,
+ sk_sp<LazyProxyData>);
+
+#if SK_SUPPORT_GPU
+ const SkTArray<GrRecordingContext::ProgramData>& programData() const {
+ return fProgramData;
+ }
+#endif
+
+ const SkSurfaceCharacterization fCharacterization;
+
+#if SK_SUPPORT_GPU
+ // These are ordered such that the destructor cleans op tasks up first (which may refer back
+ // to the arena and memory pool in their destructors).
+ GrRecordingContext::OwnedArenas fArenas;
+ SkTArray<sk_sp<GrRenderTask>> fRenderTasks;
+
+ SkTArray<GrRecordingContext::ProgramData> fProgramData;
+ sk_sp<GrRenderTargetProxy> fTargetProxy;
+ sk_sp<LazyProxyData> fLazyProxyData;
+#endif
+};
+
+#endif
diff --git a/src/deps/skia/include/core/SkDeferredDisplayListRecorder.h b/src/deps/skia/include/core/SkDeferredDisplayListRecorder.h
new file mode 100644
index 000000000..30a4a73ee
--- /dev/null
+++ b/src/deps/skia/include/core/SkDeferredDisplayListRecorder.h
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkDeferredDisplayListRecorder_DEFINED
+#define SkDeferredDisplayListRecorder_DEFINED
+
+#include "include/core/SkDeferredDisplayList.h"
+#include "include/core/SkImage.h"
+#include "include/core/SkImageInfo.h"
+#include "include/core/SkRefCnt.h"
+#include "include/core/SkSurfaceCharacterization.h"
+#include "include/core/SkTypes.h"
+
+class GrBackendFormat;
+class GrBackendTexture;
+class GrRecordingContext;
+class GrYUVABackendTextureInfo;
+class SkCanvas;
+class SkSurface;
+
+/*
+ * This class is intended to be used as:
+ * Get an SkSurfaceCharacterization representing the intended gpu-backed destination SkSurface
+ * Create one of these (an SkDeferredDisplayListRecorder) on the stack
+ * Get the canvas and render into it
+ * Snap off and hold on to an SkDeferredDisplayList
+ * Once your app actually needs the pixels, call SkSurface::draw(SkDeferredDisplayList*)
+ *
+ * This class never accesses the GPU but performs all the cpu work it can. It
+ * is thread-safe (i.e., one can break a scene into tiles and perform their cpu-side
+ * work in parallel ahead of time).
+ */
+class SK_API SkDeferredDisplayListRecorder {
+public:
+ SkDeferredDisplayListRecorder(const SkSurfaceCharacterization&);
+ ~SkDeferredDisplayListRecorder();
+
+ const SkSurfaceCharacterization& characterization() const {
+ return fCharacterization;
+ }
+
+ // The backing canvas will become invalid (and this entry point will return
+ // null) once 'detach' is called.
+ // Note: ownership of the SkCanvas is not transferred via this call.
+ SkCanvas* getCanvas();
+
+ sk_sp<SkDeferredDisplayList> detach();
+
+#if SK_SUPPORT_GPU
+ using PromiseImageTextureContext = SkImage::PromiseImageTextureContext;
+ using PromiseImageTextureFulfillProc = SkImage::PromiseImageTextureFulfillProc;
+ using PromiseImageTextureReleaseProc = SkImage::PromiseImageTextureReleaseProc;
+
+#ifndef SK_MAKE_PROMISE_TEXTURE_DISABLE_LEGACY_API
+ /** Deprecated: Use SkImage::MakePromiseTexture instead. */
+ sk_sp<SkImage> makePromiseTexture(const GrBackendFormat& backendFormat,
+ int width,
+ int height,
+ GrMipmapped mipMapped,
+ GrSurfaceOrigin origin,
+ SkColorType colorType,
+ SkAlphaType alphaType,
+ sk_sp<SkColorSpace> colorSpace,
+ PromiseImageTextureFulfillProc textureFulfillProc,
+ PromiseImageTextureReleaseProc textureReleaseProc,
+ PromiseImageTextureContext textureContext);
+
+ /** Deprecated: Use SkImage::MakePromiseYUVATexture instead. */
+ sk_sp<SkImage> makeYUVAPromiseTexture(const GrYUVABackendTextureInfo& yuvaBackendTextureInfo,
+ sk_sp<SkColorSpace> imageColorSpace,
+ PromiseImageTextureFulfillProc textureFulfillProc,
+ PromiseImageTextureReleaseProc textureReleaseProc,
+ PromiseImageTextureContext textureContexts[]);
+#endif // SK_MAKE_PROMISE_TEXTURE_DISABLE_LEGACY_API
+#endif // SK_SUPPORT_GPU
+
+private:
+ SkDeferredDisplayListRecorder(const SkDeferredDisplayListRecorder&) = delete;
+ SkDeferredDisplayListRecorder& operator=(const SkDeferredDisplayListRecorder&) = delete;
+
+ bool init();
+
+ const SkSurfaceCharacterization fCharacterization;
+
+#if SK_SUPPORT_GPU
+ sk_sp<GrRecordingContext> fContext;
+ sk_sp<GrRenderTargetProxy> fTargetProxy;
+ sk_sp<SkDeferredDisplayList::LazyProxyData> fLazyProxyData;
+ sk_sp<SkSurface> fSurface;
+#endif
+};
+
+#endif
diff --git a/src/deps/skia/include/core/SkDocument.h b/src/deps/skia/include/core/SkDocument.h
new file mode 100644
index 000000000..eacfb2c04
--- /dev/null
+++ b/src/deps/skia/include/core/SkDocument.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkDocument_DEFINED
+#define SkDocument_DEFINED
+
+#include "include/core/SkRefCnt.h"
+#include "include/core/SkScalar.h"
+
+class SkCanvas;
+class SkWStream;
+struct SkRect;
+
+/** SK_ScalarDefaultDPI is 72 dots per inch. */
+static constexpr SkScalar SK_ScalarDefaultRasterDPI = 72.0f;
+
+/**
+ * High-level API for creating a document-based canvas. To use..
+ *
+ * 1. Create a document, specifying a stream to store the output.
+ * 2. For each "page" of content:
+ * a. canvas = doc->beginPage(...)
+ * b. draw_my_content(canvas);
+ * c. doc->endPage();
+ * 3. Close the document with doc->close().
+ */
+class SK_API SkDocument : public SkRefCnt {
+public:
+
+ /**
+ * Begin a new page for the document, returning the canvas that will draw
+ * into the page. The document owns this canvas, and it will go out of
+ * scope when endPage() or close() is called, or the document is deleted.
+ */
+ SkCanvas* beginPage(SkScalar width, SkScalar height, const SkRect* content = nullptr);
+
+ /**
+ * Call endPage() when the content for the current page has been drawn
+ * (into the canvas returned by beginPage()). After this call the canvas
+ * returned by beginPage() will be out-of-scope.
+ */
+ void endPage();
+
+ /**
+ * Call close() when all pages have been drawn. This will close the file
+ * or stream holding the document's contents. After close() the document
+ * can no longer add new pages. Deleting the document will automatically
+ * call close() if need be.
+ */
+ void close();
+
+ /**
+ * Call abort() to stop producing the document immediately.
+ * The stream output must be ignored, and should not be trusted.
+ */
+ void abort();
+
+protected:
+ SkDocument(SkWStream*);
+
+ // note: subclasses must call close() in their destructor, as the base class
+ // cannot do this for them.
+ ~SkDocument() override;
+
+ virtual SkCanvas* onBeginPage(SkScalar width, SkScalar height) = 0;
+ virtual void onEndPage() = 0;
+ virtual void onClose(SkWStream*) = 0;
+ virtual void onAbort() = 0;
+
+ // Allows subclasses to write to the stream as pages are written.
+ SkWStream* getStream() { return fStream; }
+
+ enum State {
+ kBetweenPages_State,
+ kInPage_State,
+ kClosed_State
+ };
+ State getState() const { return fState; }
+
+private:
+ SkWStream* fStream;
+ State fState;
+
+ using INHERITED = SkRefCnt;
+};
+
+#endif
diff --git a/src/deps/skia/include/core/SkDrawLooper.h b/src/deps/skia/include/core/SkDrawLooper.h
new file mode 100644
index 000000000..69d341c25
--- /dev/null
+++ b/src/deps/skia/include/core/SkDrawLooper.h
@@ -0,0 +1,135 @@
+
+/*
+ * Copyright 2011 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkDrawLooper_DEFINED
+#define SkDrawLooper_DEFINED
+
+#include "include/core/SkBlurTypes.h"
+#include "include/core/SkColor.h"
+#include "include/core/SkFlattenable.h"
+#include "include/core/SkPoint.h"
+#include <functional> // std::function
+
+#ifndef SK_SUPPORT_LEGACY_DRAWLOOPER
+#error "SkDrawLooper is unsupported"
+#endif
+
+class SkArenaAlloc;
+class SkCanvas;
+class SkMatrix;
+class SkPaint;
+struct SkRect;
+
+/** \class SkDrawLooper
+ DEPRECATED: No longer supported in Skia.
+*/
+class SK_API SkDrawLooper : public SkFlattenable {
+public:
+ /**
+ * Holds state during a draw. Users call next() until it returns false.
+ *
+ * Subclasses of SkDrawLooper should create a subclass of this object to
+ * hold state specific to their subclass.
+ */
+ class SK_API Context {
+ public:
+ Context() {}
+ virtual ~Context() {}
+
+ struct Info {
+ SkVector fTranslate;
+ bool fApplyPostCTM;
+
+ void applyToCTM(SkMatrix* ctm) const;
+ void applyToCanvas(SkCanvas*) const;
+ };
+
+ /**
+ * Called in a loop on objects returned by SkDrawLooper::createContext().
+ * Each time true is returned, the object is drawn (possibly with a modified
+ * canvas and/or paint). When false is finally returned, drawing for the object
+ * stops.
+ *
+ * On each call, the paint will be in its original state, but the
+ * canvas will be as it was following the previous call to next() or
+ * createContext().
+ *
+ * The implementation must ensure that, when next() finally returns
+ * false, the canvas has been restored to the state it was
+ * initially, before createContext() was first called.
+ */
+ virtual bool next(Info*, SkPaint*) = 0;
+
+ private:
+ Context(const Context&) = delete;
+ Context& operator=(const Context&) = delete;
+ };
+
+ /**
+ * Called right before something is being drawn. Returns a Context
+ * whose next() method should be called until it returns false.
+ */
+ virtual Context* makeContext(SkArenaAlloc*) const = 0;
+
+ /**
+ * The fast bounds functions are used to enable the paint to be culled early
+ * in the drawing pipeline. If a subclass can support this feature it must
+ * return true for the canComputeFastBounds() function. If that function
+ * returns false then computeFastBounds behavior is undefined otherwise it
+ * is expected to have the following behavior. Given the parent paint and
+ * the parent's bounding rect the subclass must fill in and return the
+ * storage rect, where the storage rect is with the union of the src rect
+ * and the looper's bounding rect.
+ */
+ bool canComputeFastBounds(const SkPaint& paint) const;
+ void computeFastBounds(const SkPaint& paint, const SkRect& src, SkRect* dst) const;
+
+ struct BlurShadowRec {
+ SkScalar fSigma;
+ SkVector fOffset;
+ SkColor fColor;
+ SkBlurStyle fStyle;
+ };
+ /**
+ * If this looper can be interpreted as having two layers, such that
+ * 1. The first layer (bottom most) just has a blur and translate
+ * 2. The second layer has no modifications to either paint or canvas
+ * 3. No other layers.
+ * then return true, and if not null, fill out the BlurShadowRec).
+ *
+ * If any of the above are not met, return false and ignore the BlurShadowRec parameter.
+ */
+ virtual bool asABlurShadow(BlurShadowRec*) const;
+
+ static SkFlattenable::Type GetFlattenableType() {
+ return kSkDrawLooper_Type;
+ }
+
+ SkFlattenable::Type getFlattenableType() const override {
+ return kSkDrawLooper_Type;
+ }
+
+ static sk_sp<SkDrawLooper> Deserialize(const void* data, size_t size,
+ const SkDeserialProcs* procs = nullptr) {
+ return sk_sp<SkDrawLooper>(static_cast<SkDrawLooper*>(
+ SkFlattenable::Deserialize(
+ kSkDrawLooper_Type, data, size, procs).release()));
+ }
+
+ void apply(SkCanvas* canvas, const SkPaint& paint,
+ std::function<void(SkCanvas*, const SkPaint&)>);
+
+protected:
+ SkDrawLooper() {}
+
+private:
+ using INHERITED = SkFlattenable;
+};
+
+#endif
diff --git a/src/deps/skia/include/core/SkDrawable.h b/src/deps/skia/include/core/SkDrawable.h
new file mode 100644
index 000000000..8d605f80d
--- /dev/null
+++ b/src/deps/skia/include/core/SkDrawable.h
@@ -0,0 +1,160 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkDrawable_DEFINED
+#define SkDrawable_DEFINED
+
+#include "include/core/SkFlattenable.h"
+#include "include/core/SkImageInfo.h"
+#include "include/core/SkScalar.h"
+
+class GrBackendDrawableInfo;
+class SkCanvas;
+class SkMatrix;
+class SkPicture;
+enum class GrBackendApi : unsigned;
+struct SkRect;
+
+/**
+ * Base-class for objects that draw into SkCanvas.
+ *
+ * The object has a generation ID, which is guaranteed to be unique across all drawables. To
+ * allow for clients of the drawable that may want to cache the results, the drawable must
+ * change its generation ID whenever its internal state changes such that it will draw differently.
+ */
+class SK_API SkDrawable : public SkFlattenable {
+public:
+ /**
+ * Draws into the specified content. The drawing sequence will be balanced upon return
+ * (i.e. the saveLevel() on the canvas will match what it was when draw() was called,
+ * and the current matrix and clip settings will not be changed.
+ */
+ void draw(SkCanvas*, const SkMatrix* = nullptr);
+ void draw(SkCanvas*, SkScalar x, SkScalar y);
+
+ /**
+ * When using the GPU backend it is possible for a drawable to execute using the underlying 3D
+ * API rather than the SkCanvas API. It does so by creating a GpuDrawHandler. The GPU backend
+ * is deferred so the handler will be given access to the 3D API at the correct point in the
+ * drawing stream as the GPU backend flushes. Since the drawable may mutate, each time it is
+ * drawn to a GPU-backed canvas a new handler is snapped, representing the drawable's state at
+ * the time of the snap.
+ *
+ * When the GPU backend flushes to the 3D API it will call the draw method on the
+ * GpuDrawHandler. At this time the drawable may add commands to the stream of GPU commands for
+ * the unerlying 3D API. The draw function takes a GrBackendDrawableInfo which contains
+ * information about the current state of 3D API which the caller must respect. See
+ * GrBackendDrawableInfo for more specific details on what information is sent and the
+ * requirements for different 3D APIs.
+ *
+ * Additionaly there may be a slight delay from when the drawable adds its commands to when
+ * those commands are actually submitted to the GPU. Thus the drawable or GpuDrawHandler is
+ * required to keep any resources that are used by its added commands alive and valid until
+ * those commands are submitted to the GPU. The GpuDrawHandler will be kept alive and then
+ * deleted once the commands are submitted to the GPU. The dtor of the GpuDrawHandler is the
+ * signal to the drawable that the commands have all been submitted. Different 3D APIs may have
+ * additional requirements for certain resources which require waiting for the GPU to finish
+ * all work on those resources before reusing or deleting them. In this case, the drawable can
+ * use the dtor call of the GpuDrawHandler to add a fence to the GPU to track when the GPU work
+ * has completed.
+ *
+ * Currently this is only supported for the GPU Vulkan backend.
+ */
+
+ class GpuDrawHandler {
+ public:
+ virtual ~GpuDrawHandler() {}
+
+ virtual void draw(const GrBackendDrawableInfo&) {}
+ };
+
+ /**
+ * Snaps off a GpuDrawHandler to represent the state of the SkDrawable at the time the snap is
+ * called. This is used for executing GPU backend specific draws intermixed with normal Skia GPU
+ * draws. The GPU API, which will be used for the draw, as well as the full matrix, device clip
+ * bounds and imageInfo of the target buffer are passed in as inputs.
+ */
+ std::unique_ptr<GpuDrawHandler> snapGpuDrawHandler(GrBackendApi backendApi,
+ const SkMatrix& matrix,
+ const SkIRect& clipBounds,
+ const SkImageInfo& bufferInfo) {
+ return this->onSnapGpuDrawHandler(backendApi, matrix, clipBounds, bufferInfo);
+ }
+
+ SkPicture* newPictureSnapshot();
+
+ /**
+ * Return a unique value for this instance. If two calls to this return the same value,
+ * it is presumed that calling the draw() method will render the same thing as well.
+ *
+ * Subclasses that change their state should call notifyDrawingChanged() to ensure that
+ * a new value will be returned the next time it is called.
+ */
+ uint32_t getGenerationID();
+
+ /**
+ * Return the (conservative) bounds of what the drawable will draw. If the drawable can
+ * change what it draws (e.g. animation or in response to some external change), then this
+ * must return a bounds that is always valid for all possible states.
+ */
+ SkRect getBounds();
+
+ /**
+ * Calling this invalidates the previous generation ID, and causes a new one to be computed
+ * the next time getGenerationID() is called. Typically this is called by the object itself,
+ * in response to its internal state changing.
+ */
+ void notifyDrawingChanged();
+
+ static SkFlattenable::Type GetFlattenableType() {
+ return kSkDrawable_Type;
+ }
+
+ SkFlattenable::Type getFlattenableType() const override {
+ return kSkDrawable_Type;
+ }
+
+ static sk_sp<SkDrawable> Deserialize(const void* data, size_t size,
+ const SkDeserialProcs* procs = nullptr) {
+ return sk_sp<SkDrawable>(static_cast<SkDrawable*>(
+ SkFlattenable::Deserialize(
+ kSkDrawable_Type, data, size, procs).release()));
+ }
+
+ Factory getFactory() const override { return nullptr; }
+ const char* getTypeName() const override { return nullptr; }
+
+protected:
+ SkDrawable();
+
+ virtual SkRect onGetBounds() = 0;
+ virtual void onDraw(SkCanvas*) = 0;
+
+ virtual std::unique_ptr<GpuDrawHandler> onSnapGpuDrawHandler(GrBackendApi, const SkMatrix&,
+ const SkIRect& /*clipBounds*/,
+ const SkImageInfo&) {
+ return nullptr;
+ }
+
+ // TODO: Delete this once Android gets updated to take the clipBounds version above.
+ virtual std::unique_ptr<GpuDrawHandler> onSnapGpuDrawHandler(GrBackendApi, const SkMatrix&) {
+ return nullptr;
+ }
+
+ /**
+ * Default implementation calls onDraw() with a canvas that records into a picture. Subclasses
+ * may override if they have a more efficient way to return a picture for the current state
+ * of their drawable. Note: this picture must draw the same as what would be drawn from
+ * onDraw().
+ */
+ virtual SkPicture* onNewPictureSnapshot();
+
+private:
+ int32_t fGenerationID;
+};
+
+#endif
diff --git a/src/deps/skia/include/core/SkEncodedImageFormat.h b/src/deps/skia/include/core/SkEncodedImageFormat.h
new file mode 100644
index 000000000..97add6dea
--- /dev/null
+++ b/src/deps/skia/include/core/SkEncodedImageFormat.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2015 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkEncodedImageFormat_DEFINED
+#define SkEncodedImageFormat_DEFINED
+
+#include <stdint.h>
+
+/**
+ * Enum describing format of encoded data.
+ */
+enum class SkEncodedImageFormat {
+#ifdef SK_BUILD_FOR_GOOGLE3
+ kUnknown,
+#endif
+ kBMP,
+ kGIF,
+ kICO,
+ kJPEG,
+ kPNG,
+ kWBMP,
+ kWEBP,
+ kPKM,
+ kKTX,
+ kASTC,
+ kDNG,
+ kHEIF,
+ kAVIF,
+};
+
+#endif // SkEncodedImageFormat_DEFINED
diff --git a/src/deps/skia/include/core/SkExecutor.h b/src/deps/skia/include/core/SkExecutor.h
new file mode 100644
index 000000000..88e2ca6e5
--- /dev/null
+++ b/src/deps/skia/include/core/SkExecutor.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkExecutor_DEFINED
+#define SkExecutor_DEFINED
+
+#include <functional>
+#include <memory>
+#include "include/core/SkTypes.h"
+
+class SK_API SkExecutor {
+public:
+ virtual ~SkExecutor();
+
+ // Create a thread pool SkExecutor with a fixed thread count, by default the number of cores.
+ static std::unique_ptr<SkExecutor> MakeFIFOThreadPool(int threads = 0,
+ bool allowBorrowing = true);
+ static std::unique_ptr<SkExecutor> MakeLIFOThreadPool(int threads = 0,
+ bool allowBorrowing = true);
+
+ // There is always a default SkExecutor available by calling SkExecutor::GetDefault().
+ static SkExecutor& GetDefault();
+ static void SetDefault(SkExecutor*); // Does not take ownership. Not thread safe.
+
+ // Add work to execute.
+ virtual void add(std::function<void(void)>) = 0;
+
+ // If it makes sense for this executor, use this thread to execute work for a little while.
+ virtual void borrow() {}
+
+protected:
+ SkExecutor() = default;
+ SkExecutor(const SkExecutor&) = delete;
+ SkExecutor& operator=(const SkExecutor&) = delete;
+};
+
+#endif//SkExecutor_DEFINED
diff --git a/src/deps/skia/include/core/SkFlattenable.h b/src/deps/skia/include/core/SkFlattenable.h
new file mode 100644
index 000000000..916ee174f
--- /dev/null
+++ b/src/deps/skia/include/core/SkFlattenable.h
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkFlattenable_DEFINED
+#define SkFlattenable_DEFINED
+
+#include "include/core/SkRefCnt.h"
+
+class SkData;
+class SkReadBuffer;
+class SkWriteBuffer;
+
+struct SkSerialProcs;
+struct SkDeserialProcs;
+
+/** \class SkFlattenable
+
+ SkFlattenable is the base class for objects that need to be flattened
+ into a data stream for either transport or as part of the key to the
+ font cache.
+ */
+class SK_API SkFlattenable : public SkRefCnt {
+public:
+ enum Type {
+ kSkColorFilter_Type,
+ kSkBlender_Type,
+ kSkDrawable_Type,
+ kSkDrawLooper_Type, // no longer used internally by Skia
+ kSkImageFilter_Type,
+ kSkMaskFilter_Type,
+ kSkPathEffect_Type,
+ kSkShader_Type,
+ };
+
+ typedef sk_sp<SkFlattenable> (*Factory)(SkReadBuffer&);
+
+ SkFlattenable() {}
+
+ /** Implement this to return a factory function pointer that can be called
+ to recreate your class given a buffer (previously written to by your
+ override of flatten().
+ */
+ virtual Factory getFactory() const = 0;
+
+ /**
+ * Returns the name of the object's class.
+ */
+ virtual const char* getTypeName() const = 0;
+
+ static Factory NameToFactory(const char name[]);
+ static const char* FactoryToName(Factory);
+
+ static void Register(const char name[], Factory);
+
+ /**
+ * Override this if your subclass needs to record data that it will need to recreate itself
+ * from its CreateProc (returned by getFactory()).
+ *
+ * DEPRECATED public : will move to protected ... use serialize() instead
+ */
+ virtual void flatten(SkWriteBuffer&) const {}
+
+ virtual Type getFlattenableType() const = 0;
+
+ //
+ // public ways to serialize / deserialize
+ //
+ sk_sp<SkData> serialize(const SkSerialProcs* = nullptr) const;
+ size_t serialize(void* memory, size_t memory_size,
+ const SkSerialProcs* = nullptr) const;
+ static sk_sp<SkFlattenable> Deserialize(Type, const void* data, size_t length,
+ const SkDeserialProcs* procs = nullptr);
+
+protected:
+ class PrivateInitializer {
+ public:
+ static void InitEffects();
+ static void InitImageFilters();
+ };
+
+private:
+ static void RegisterFlattenablesIfNeeded();
+ static void Finalize();
+
+ friend class SkGraphics;
+
+ using INHERITED = SkRefCnt;
+};
+
+#if defined(SK_DISABLE_EFFECT_DESERIALIZATION)
+ #define SK_REGISTER_FLATTENABLE(type) do{}while(false)
+
+ #define SK_FLATTENABLE_HOOKS(type) \
+ static sk_sp<SkFlattenable> CreateProc(SkReadBuffer&); \
+ friend class SkFlattenable::PrivateInitializer; \
+ Factory getFactory() const override { return nullptr; } \
+ const char* getTypeName() const override { return #type; }
+#else
+ #define SK_REGISTER_FLATTENABLE(type) \
+ SkFlattenable::Register(#type, type::CreateProc)
+
+ #define SK_FLATTENABLE_HOOKS(type) \
+ static sk_sp<SkFlattenable> CreateProc(SkReadBuffer&); \
+ friend class SkFlattenable::PrivateInitializer; \
+ Factory getFactory() const override { return type::CreateProc; } \
+ const char* getTypeName() const override { return #type; }
+#endif
+
+#endif
diff --git a/src/deps/skia/include/core/SkFont.h b/src/deps/skia/include/core/SkFont.h
new file mode 100644
index 000000000..947e4dd77
--- /dev/null
+++ b/src/deps/skia/include/core/SkFont.h
@@ -0,0 +1,534 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkFont_DEFINED
+#define SkFont_DEFINED
+
+#include "include/core/SkFontTypes.h"
+#include "include/core/SkScalar.h"
+#include "include/core/SkTypeface.h"
+
+#include <vector>
+
+class SkMatrix;
+class SkPaint;
+class SkPath;
+struct SkFontMetrics;
+
+/** \class SkFont
+ SkFont controls options applied when drawing and measuring text.
+*/
+class SK_API SkFont {
+public:
+ /** Whether edge pixels draw opaque or with partial transparency.
+ */
+ enum class Edging {
+ kAlias, //!< no transparent pixels on glyph edges
+ kAntiAlias, //!< may have transparent pixels on glyph edges
+ kSubpixelAntiAlias, //!< glyph positioned in pixel using transparency
+ };
+
+ /** Constructs SkFont with default values.
+
+ @return default initialized SkFont
+ */
+ SkFont();
+
+ /** Constructs SkFont with default values with SkTypeface and size in points.
+
+ @param typeface font and style used to draw and measure text
+ @param size typographic height of text
+ @return initialized SkFont
+ */
+ SkFont(sk_sp<SkTypeface> typeface, SkScalar size);
+
+ /** Constructs SkFont with default values with SkTypeface.
+
+ @param typeface font and style used to draw and measure text
+ @return initialized SkFont
+ */
+ explicit SkFont(sk_sp<SkTypeface> typeface);
+
+
+ /** Constructs SkFont with default values with SkTypeface and size in points,
+ horizontal scale, and horizontal skew. Horizontal scale emulates condensed
+ and expanded fonts. Horizontal skew emulates oblique fonts.
+
+ @param typeface font and style used to draw and measure text
+ @param size typographic height of text
+ @param scaleX text horizontal scale
+ @param skewX additional shear on x-axis relative to y-axis
+ @return initialized SkFont
+ */
+ SkFont(sk_sp<SkTypeface> typeface, SkScalar size, SkScalar scaleX, SkScalar skewX);
+
+
+ /** Compares SkFont and font, and returns true if they are equivalent.
+ May return false if SkTypeface has identical contents but different pointers.
+
+ @param font font to compare
+ @return true if SkFont pair are equivalent
+ */
+ bool operator==(const SkFont& font) const;
+
+ /** Compares SkFont and font, and returns true if they are not equivalent.
+ May return true if SkTypeface has identical contents but different pointers.
+
+ @param font font to compare
+ @return true if SkFont pair are not equivalent
+ */
+ bool operator!=(const SkFont& font) const { return !(*this == font); }
+
+ /** If true, instructs the font manager to always hint glyphs.
+ Returned value is only meaningful if platform uses FreeType as the font manager.
+
+ @return true if all glyphs are hinted
+ */
+ bool isForceAutoHinting() const { return SkToBool(fFlags & kForceAutoHinting_PrivFlag); }
+
+ /** Returns true if font engine may return glyphs from font bitmaps instead of from outlines.
+
+ @return true if glyphs may be font bitmaps
+ */
+ bool isEmbeddedBitmaps() const { return SkToBool(fFlags & kEmbeddedBitmaps_PrivFlag); }
+
+ /** Returns true if glyphs may be drawn at sub-pixel offsets.
+
+ @return true if glyphs may be drawn at sub-pixel offsets.
+ */
+ bool isSubpixel() const { return SkToBool(fFlags & kSubpixel_PrivFlag); }
+
+ /** Returns true if font and glyph metrics are requested to be linearly scalable.
+
+ @return true if font and glyph metrics are requested to be linearly scalable.
+ */
+ bool isLinearMetrics() const { return SkToBool(fFlags & kLinearMetrics_PrivFlag); }
+
+ /** Returns true if bold is approximated by increasing the stroke width when creating glyph
+ bitmaps from outlines.
+
+ @return bold is approximated through stroke width
+ */
+ bool isEmbolden() const { return SkToBool(fFlags & kEmbolden_PrivFlag); }
+
+ /** Returns true if baselines will be snapped to pixel positions when the current transformation
+ matrix is axis aligned.
+
+ @return baselines may be snapped to pixels
+ */
+ bool isBaselineSnap() const { return SkToBool(fFlags & kBaselineSnap_PrivFlag); }
+
+ /** Sets whether to always hint glyphs.
+ If forceAutoHinting is set, instructs the font manager to always hint glyphs.
+
+ Only affects platforms that use FreeType as the font manager.
+
+ @param forceAutoHinting setting to always hint glyphs
+ */
+ void setForceAutoHinting(bool forceAutoHinting);
+
+ /** Requests, but does not require, to use bitmaps in fonts instead of outlines.
+
+ @param embeddedBitmaps setting to use bitmaps in fonts
+ */
+ void setEmbeddedBitmaps(bool embeddedBitmaps);
+
+ /** Requests, but does not require, that glyphs respect sub-pixel positioning.
+
+ @param subpixel setting for sub-pixel positioning
+ */
+ void setSubpixel(bool subpixel);
+
+ /** Requests, but does not require, linearly scalable font and glyph metrics.
+
+ For outline fonts 'true' means font and glyph metrics should ignore hinting and rounding.
+ Note that some bitmap formats may not be able to scale linearly and will ignore this flag.
+
+ @param linearMetrics setting for linearly scalable font and glyph metrics.
+ */
+ void setLinearMetrics(bool linearMetrics);
+
+ /** Increases stroke width when creating glyph bitmaps to approximate a bold typeface.
+
+ @param embolden setting for bold approximation
+ */
+ void setEmbolden(bool embolden);
+
+ /** Requests that baselines be snapped to pixels when the current transformation matrix is axis
+ aligned.
+
+ @param baselineSnap setting for baseline snapping to pixels
+ */
+ void setBaselineSnap(bool baselineSnap);
+
+ /** Whether edge pixels draw opaque or with partial transparency.
+ */
+ Edging getEdging() const { return (Edging)fEdging; }
+
+ /** Requests, but does not require, that edge pixels draw opaque or with
+ partial transparency.
+ */
+ void setEdging(Edging edging);
+
+ /** Sets level of glyph outline adjustment.
+ Does not check for valid values of hintingLevel.
+ */
+ void setHinting(SkFontHinting hintingLevel);
+
+ /** Returns level of glyph outline adjustment.
+ */
+ SkFontHinting getHinting() const { return (SkFontHinting)fHinting; }
+
+ /** Returns a font with the same attributes of this font, but with the specified size.
+ Returns nullptr if size is less than zero, infinite, or NaN.
+
+ @param size typographic height of text
+ @return initialized SkFont
+ */
+ SkFont makeWithSize(SkScalar size) const;
+
+ /** Returns SkTypeface if set, or nullptr.
+ Does not alter SkTypeface SkRefCnt.
+
+ @return SkTypeface if previously set, nullptr otherwise
+ */
+ SkTypeface* getTypeface() const {return fTypeface.get(); }
+
+ /** Returns SkTypeface if set, or the default typeface.
+ Does not alter SkTypeface SkRefCnt.
+
+ @return SkTypeface if previously set or, a pointer to the default typeface if not
+ previously set.
+ */
+ SkTypeface* getTypefaceOrDefault() const;
+
+ /** Returns text size in points.
+
+ @return typographic height of text
+ */
+ SkScalar getSize() const { return fSize; }
+
+ /** Returns text scale on x-axis.
+ Default value is 1.
+
+ @return text horizontal scale
+ */
+ SkScalar getScaleX() const { return fScaleX; }
+
+ /** Returns text skew on x-axis.
+ Default value is zero.
+
+ @return additional shear on x-axis relative to y-axis
+ */
+ SkScalar getSkewX() const { return fSkewX; }
+
+ /** Increases SkTypeface SkRefCnt by one.
+
+ @return SkTypeface if previously set, nullptr otherwise
+ */
+ sk_sp<SkTypeface> refTypeface() const { return fTypeface; }
+
+ /** Increases SkTypeface SkRefCnt by one.
+
+ @return SkTypeface if previously set or, a pointer to the default typeface if not
+ previously set.
+ */
+ sk_sp<SkTypeface> refTypefaceOrDefault() const;
+
+ /** Sets SkTypeface to typeface, decreasing SkRefCnt of the previous SkTypeface.
+ Pass nullptr to clear SkTypeface and use the default typeface. Increments
+ tf SkRefCnt by one.
+
+ @param tf font and style used to draw text
+ */
+ void setTypeface(sk_sp<SkTypeface> tf) { fTypeface = tf; }
+
+ /** Sets text size in points.
+ Has no effect if textSize is not greater than or equal to zero.
+
+ @param textSize typographic height of text
+ */
+ void setSize(SkScalar textSize);
+
+ /** Sets text scale on x-axis.
+ Default value is 1.
+
+ @param scaleX text horizontal scale
+ */
+ void setScaleX(SkScalar scaleX);
+
+ /** Sets text skew on x-axis.
+ Default value is zero.
+
+ @param skewX additional shear on x-axis relative to y-axis
+ */
+ void setSkewX(SkScalar skewX);
+
+ /** Converts text into glyph indices.
+ Returns the number of glyph indices represented by text.
+ SkTextEncoding specifies how text represents characters or glyphs.
+ glyphs may be nullptr, to compute the glyph count.
+
+ Does not check text for valid character codes or valid glyph indices.
+
+ If byteLength equals zero, returns zero.
+ If byteLength includes a partial character, the partial character is ignored.
+
+ If encoding is SkTextEncoding::kUTF8 and text contains an invalid UTF-8 sequence,
+ zero is returned.
+
+ When encoding is SkTextEncoding::kUTF8, SkTextEncoding::kUTF16, or
+ SkTextEncoding::kUTF32; then each Unicode codepoint is mapped to a
+ single glyph. This function uses the default character-to-glyph
+ mapping from the SkTypeface and maps characters not found in the
+ SkTypeface to zero.
+
+ If maxGlyphCount is not sufficient to store all the glyphs, no glyphs are copied.
+ The total glyph count is returned for subsequent buffer reallocation.
+
+ @param text character storage encoded with SkTextEncoding
+ @param byteLength length of character storage in bytes
+ @param glyphs storage for glyph indices; may be nullptr
+ @param maxGlyphCount storage capacity
+ @return number of glyphs represented by text of length byteLength
+ */
+ int textToGlyphs(const void* text, size_t byteLength, SkTextEncoding encoding,
+ SkGlyphID glyphs[], int maxGlyphCount) const;
+
+ /** Returns glyph index for Unicode character.
+
+ If the character is not supported by the SkTypeface, returns 0.
+
+ @param uni Unicode character
+ @return glyph index
+ */
+ SkGlyphID unicharToGlyph(SkUnichar uni) const;
+
+ void unicharsToGlyphs(const SkUnichar uni[], int count, SkGlyphID glyphs[]) const;
+
+ /** Returns number of glyphs represented by text.
+
+ If encoding is SkTextEncoding::kUTF8, SkTextEncoding::kUTF16, or
+ SkTextEncoding::kUTF32; then each Unicode codepoint is mapped to a
+ single glyph.
+
+ @param text character storage encoded with SkTextEncoding
+ @param byteLength length of character storage in bytes
+ @return number of glyphs represented by text of length byteLength
+ */
+ int countText(const void* text, size_t byteLength, SkTextEncoding encoding) const {
+ return this->textToGlyphs(text, byteLength, encoding, nullptr, 0);
+ }
+
+ /** Returns the advance width of text.
+ The advance is the normal distance to move before drawing additional text.
+ Returns the bounding box of text if bounds is not nullptr.
+
+ @param text character storage encoded with SkTextEncoding
+ @param byteLength length of character storage in bytes
+ @param bounds returns bounding box relative to (0, 0) if not nullptr
+ @return number of glyphs represented by text of length byteLength
+ */
+ SkScalar measureText(const void* text, size_t byteLength, SkTextEncoding encoding,
+ SkRect* bounds = nullptr) const {
+ return this->measureText(text, byteLength, encoding, bounds, nullptr);
+ }
+
+ /** Returns the advance width of text.
+ The advance is the normal distance to move before drawing additional text.
+ Returns the bounding box of text if bounds is not nullptr. The paint
+ stroke settings, mask filter, or path effect may modify the bounds.
+
+ @param text character storage encoded with SkTextEncoding
+ @param byteLength length of character storage in bytes
+ @param bounds returns bounding box relative to (0, 0) if not nullptr
+ @param paint optional; may be nullptr
+ @return number of glyphs represented by text of length byteLength
+ */
+ SkScalar measureText(const void* text, size_t byteLength, SkTextEncoding encoding,
+ SkRect* bounds, const SkPaint* paint) const;
+
+ /** DEPRECATED
+ Retrieves the advance and bounds for each glyph in glyphs.
+ Both widths and bounds may be nullptr.
+ If widths is not nullptr, widths must be an array of count entries.
+ if bounds is not nullptr, bounds must be an array of count entries.
+
+ @param glyphs array of glyph indices to be measured
+ @param count number of glyphs
+ @param widths returns text advances for each glyph; may be nullptr
+ @param bounds returns bounds for each glyph relative to (0, 0); may be nullptr
+ */
+ void getWidths(const SkGlyphID glyphs[], int count, SkScalar widths[], SkRect bounds[]) const {
+ this->getWidthsBounds(glyphs, count, widths, bounds, nullptr);
+ }
+
+ // DEPRECATED
+ void getWidths(const SkGlyphID glyphs[], int count, SkScalar widths[], std::nullptr_t) const {
+ this->getWidths(glyphs, count, widths);
+ }
+
+ /** Retrieves the advance and bounds for each glyph in glyphs.
+ Both widths and bounds may be nullptr.
+ If widths is not nullptr, widths must be an array of count entries.
+ if bounds is not nullptr, bounds must be an array of count entries.
+
+ @param glyphs array of glyph indices to be measured
+ @param count number of glyphs
+ @param widths returns text advances for each glyph
+ */
+ void getWidths(const SkGlyphID glyphs[], int count, SkScalar widths[]) const {
+ this->getWidthsBounds(glyphs, count, widths, nullptr, nullptr);
+ }
+
+ /** Retrieves the advance and bounds for each glyph in glyphs.
+ Both widths and bounds may be nullptr.
+ If widths is not nullptr, widths must be an array of count entries.
+ if bounds is not nullptr, bounds must be an array of count entries.
+
+ @param glyphs array of glyph indices to be measured
+ @param count number of glyphs
+ @param widths returns text advances for each glyph; may be nullptr
+ @param bounds returns bounds for each glyph relative to (0, 0); may be nullptr
+ @param paint optional, specifies stroking, SkPathEffect and SkMaskFilter
+ */
+ void getWidthsBounds(const SkGlyphID glyphs[], int count, SkScalar widths[], SkRect bounds[],
+ const SkPaint* paint) const;
+
+
+ /** Retrieves the bounds for each glyph in glyphs.
+ bounds must be an array of count entries.
+ If paint is not nullptr, its stroking, SkPathEffect, and SkMaskFilter fields are respected.
+
+ @param glyphs array of glyph indices to be measured
+ @param count number of glyphs
+ @param bounds returns bounds for each glyph relative to (0, 0); may be nullptr
+ @param paint optional, specifies stroking, SkPathEffect, and SkMaskFilter
+ */
+ void getBounds(const SkGlyphID glyphs[], int count, SkRect bounds[],
+ const SkPaint* paint) const {
+ this->getWidthsBounds(glyphs, count, nullptr, bounds, paint);
+ }
+
+ /** Retrieves the positions for each glyph, beginning at the specified origin. The caller
+ must allocated at least count number of elements in the pos[] array.
+
+ @param glyphs array of glyph indices to be positioned
+ @param count number of glyphs
+ @param pos returns glyphs positions
+ @param origin location of the first glyph. Defaults to {0, 0}.
+ */
+ void getPos(const SkGlyphID glyphs[], int count, SkPoint pos[], SkPoint origin = {0, 0}) const;
+
+ /** Retrieves the x-positions for each glyph, beginning at the specified origin. The caller
+ must allocated at least count number of elements in the xpos[] array.
+
+ @param glyphs array of glyph indices to be positioned
+ @param count number of glyphs
+ @param xpos returns glyphs x-positions
+ @param origin x-position of the first glyph. Defaults to 0.
+ */
+ void getXPos(const SkGlyphID glyphs[], int count, SkScalar xpos[], SkScalar origin = 0) const;
+
+ /** Returns intervals [start, end] describing lines parallel to the advance that intersect
+ * with the glyphs.
+ *
+ * @param glyphs the glyphs to intersect
+ * @param count the number of glyphs and positions
+ * @param pos the position of each glyph
+ * @param top the top of the line intersecting
+ * @param bottom the bottom of the line intersecting
+ @return array of pairs of x values [start, end]. May be empty.
+ */
+ std::vector<SkScalar> getIntercepts(const SkGlyphID glyphs[], int count, const SkPoint pos[],
+ SkScalar top, SkScalar bottom,
+ const SkPaint* = nullptr) const;
+
+ /** Modifies path to be the outline of the glyph.
+ If the glyph has an outline, modifies path to be the glyph's outline and returns true.
+ The glyph outline may be empty. Degenerate contours in the glyph outline will be skipped.
+ If glyph is described by a bitmap, returns false and ignores path parameter.
+
+ @param glyphID index of glyph
+ @param path pointer to existing SkPath
+ @return true if glyphID is described by path
+ */
+ bool getPath(SkGlyphID glyphID, SkPath* path) const;
+
+ /** Returns path corresponding to glyph array.
+
+ @param glyphIDs array of glyph indices
+ @param count number of glyphs
+ @param glyphPathProc function returning one glyph description as path
+ @param ctx function context
+ */
+ void getPaths(const SkGlyphID glyphIDs[], int count,
+ void (*glyphPathProc)(const SkPath* pathOrNull, const SkMatrix& mx, void* ctx),
+ void* ctx) const;
+
+ /** Returns SkFontMetrics associated with SkTypeface.
+ The return value is the recommended spacing between lines: the sum of metrics
+ descent, ascent, and leading.
+ If metrics is not nullptr, SkFontMetrics is copied to metrics.
+ Results are scaled by text size but does not take into account
+ dimensions required by text scale, text skew, fake bold,
+ style stroke, and SkPathEffect.
+
+ @param metrics storage for SkFontMetrics; may be nullptr
+ @return recommended spacing between lines
+ */
+ SkScalar getMetrics(SkFontMetrics* metrics) const;
+
+ /** Returns the recommended spacing between lines: the sum of metrics
+ descent, ascent, and leading.
+ Result is scaled by text size but does not take into account
+ dimensions required by stroking and SkPathEffect.
+ Returns the same result as getMetrics().
+
+ @return recommended spacing between lines
+ */
+ SkScalar getSpacing() const { return this->getMetrics(nullptr); }
+
+ /** Dumps fields of the font to SkDebugf. May change its output over time, so clients should
+ * not rely on this for anything specific. Used to aid in debugging.
+ */
+ void dump() const;
+
+private:
+ enum PrivFlags {
+ kForceAutoHinting_PrivFlag = 1 << 0,
+ kEmbeddedBitmaps_PrivFlag = 1 << 1,
+ kSubpixel_PrivFlag = 1 << 2,
+ kLinearMetrics_PrivFlag = 1 << 3,
+ kEmbolden_PrivFlag = 1 << 4,
+ kBaselineSnap_PrivFlag = 1 << 5,
+ };
+
+ static constexpr unsigned kAllFlags = kForceAutoHinting_PrivFlag
+ | kEmbeddedBitmaps_PrivFlag
+ | kSubpixel_PrivFlag
+ | kLinearMetrics_PrivFlag
+ | kEmbolden_PrivFlag
+ | kBaselineSnap_PrivFlag;
+
+ sk_sp<SkTypeface> fTypeface;
+ SkScalar fSize;
+ SkScalar fScaleX;
+ SkScalar fSkewX;
+ uint8_t fFlags;
+ uint8_t fEdging;
+ uint8_t fHinting;
+
+ SkScalar setupForAsPaths(SkPaint*);
+ bool hasSomeAntiAliasing() const;
+
+ friend class SkFontPriv;
+ friend class SkGlyphRunListPainter;
+ friend class SkStrikeSpec;
+};
+
+#endif
diff --git a/src/deps/skia/include/core/SkFontArguments.h b/src/deps/skia/include/core/SkFontArguments.h
new file mode 100644
index 000000000..2aaaf55ca
--- /dev/null
+++ b/src/deps/skia/include/core/SkFontArguments.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkFontArguments_DEFINED
+#define SkFontArguments_DEFINED
+
+#include "include/core/SkScalar.h"
+#include "include/core/SkTypes.h"
+
+/** Represents a set of actual arguments for a font. */
+struct SkFontArguments {
+ struct VariationPosition {
+ struct Coordinate {
+ SkFourByteTag axis;
+ float value;
+ };
+ const Coordinate* coordinates;
+ int coordinateCount;
+ };
+
+ SkFontArguments() : fCollectionIndex(0), fVariationDesignPosition{nullptr, 0} {}
+
+ /** Specify the index of the desired font.
+ *
+ * Font formats like ttc, dfont, cff, cid, pfr, t42, t1, and fon may actually be indexed
+ * collections of fonts.
+ */
+ SkFontArguments& setCollectionIndex(int collectionIndex) {
+ fCollectionIndex = collectionIndex;
+ return *this;
+ }
+
+ /** Specify a position in the variation design space.
+ *
+ * Any axis not specified will use the default value.
+ * Any specified axis not actually present in the font will be ignored.
+ *
+ * @param position not copied. The value must remain valid for life of SkFontArguments.
+ */
+ SkFontArguments& setVariationDesignPosition(VariationPosition position) {
+ fVariationDesignPosition.coordinates = position.coordinates;
+ fVariationDesignPosition.coordinateCount = position.coordinateCount;
+ return *this;
+ }
+
+ int getCollectionIndex() const {
+ return fCollectionIndex;
+ }
+
+ VariationPosition getVariationDesignPosition() const {
+ return fVariationDesignPosition;
+ }
+private:
+ int fCollectionIndex;
+ VariationPosition fVariationDesignPosition;
+};
+
+#endif
diff --git a/src/deps/skia/include/core/SkFontMetrics.h b/src/deps/skia/include/core/SkFontMetrics.h
new file mode 100644
index 000000000..717a87f05
--- /dev/null
+++ b/src/deps/skia/include/core/SkFontMetrics.h
@@ -0,0 +1,138 @@
+/*
+ * Copyright 2018 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkFontMetrics_DEFINED
+#define SkFontMetrics_DEFINED
+
+#include "include/core/SkScalar.h"
+
+/** \class SkFontMetrics
+ The metrics of an SkFont.
+ The metric values are consistent with the Skia y-down coordinate system.
+ */
+struct SK_API SkFontMetrics {
+ bool operator==(const SkFontMetrics& that) {
+ return
+ this->fFlags == that.fFlags &&
+ this->fTop == that.fTop &&
+ this->fAscent == that.fAscent &&
+ this->fDescent == that.fDescent &&
+ this->fBottom == that.fBottom &&
+ this->fLeading == that.fLeading &&
+ this->fAvgCharWidth == that.fAvgCharWidth &&
+ this->fMaxCharWidth == that.fMaxCharWidth &&
+ this->fXMin == that.fXMin &&
+ this->fXMax == that.fXMax &&
+ this->fXHeight == that.fXHeight &&
+ this->fCapHeight == that.fCapHeight &&
+ this->fUnderlineThickness == that.fUnderlineThickness &&
+ this->fUnderlinePosition == that.fUnderlinePosition &&
+ this->fStrikeoutThickness == that.fStrikeoutThickness &&
+ this->fStrikeoutPosition == that.fStrikeoutPosition;
+ }
+
+ /** \enum FontMetricsFlags
+ FontMetricsFlags indicate when certain metrics are valid;
+ the underline or strikeout metrics may be valid and zero.
+ Fonts with embedded bitmaps may not have valid underline or strikeout metrics.
+ */
+ enum FontMetricsFlags {
+ kUnderlineThicknessIsValid_Flag = 1 << 0, //!< set if fUnderlineThickness is valid
+ kUnderlinePositionIsValid_Flag = 1 << 1, //!< set if fUnderlinePosition is valid
+ kStrikeoutThicknessIsValid_Flag = 1 << 2, //!< set if fStrikeoutThickness is valid
+ kStrikeoutPositionIsValid_Flag = 1 << 3, //!< set if fStrikeoutPosition is valid
+ kBoundsInvalid_Flag = 1 << 4, //!< set if fTop, fBottom, fXMin, fXMax invalid
+ };
+
+ uint32_t fFlags; //!< FontMetricsFlags indicating which metrics are valid
+ SkScalar fTop; //!< greatest extent above origin of any glyph bounding box, typically negative; deprecated with variable fonts
+ SkScalar fAscent; //!< distance to reserve above baseline, typically negative
+ SkScalar fDescent; //!< distance to reserve below baseline, typically positive
+ SkScalar fBottom; //!< greatest extent below origin of any glyph bounding box, typically positive; deprecated with variable fonts
+ SkScalar fLeading; //!< distance to add between lines, typically positive or zero
+ SkScalar fAvgCharWidth; //!< average character width, zero if unknown
+ SkScalar fMaxCharWidth; //!< maximum character width, zero if unknown
+ SkScalar fXMin; //!< greatest extent to left of origin of any glyph bounding box, typically negative; deprecated with variable fonts
+ SkScalar fXMax; //!< greatest extent to right of origin of any glyph bounding box, typically positive; deprecated with variable fonts
+ SkScalar fXHeight; //!< height of lower-case 'x', zero if unknown, typically negative
+ SkScalar fCapHeight; //!< height of an upper-case letter, zero if unknown, typically negative
+ SkScalar fUnderlineThickness; //!< underline thickness
+ SkScalar fUnderlinePosition; //!< distance from baseline to top of stroke, typically positive
+ SkScalar fStrikeoutThickness; //!< strikeout thickness
+ SkScalar fStrikeoutPosition; //!< distance from baseline to bottom of stroke, typically negative
+
+ /** Returns true if SkFontMetrics has a valid underline thickness, and sets
+ thickness to that value. If the underline thickness is not valid,
+ return false, and ignore thickness.
+
+ @param thickness storage for underline width
+ @return true if font specifies underline width
+ */
+ bool hasUnderlineThickness(SkScalar* thickness) const {
+ if (SkToBool(fFlags & kUnderlineThicknessIsValid_Flag)) {
+ *thickness = fUnderlineThickness;
+ return true;
+ }
+ return false;
+ }
+
+ /** Returns true if SkFontMetrics has a valid underline position, and sets
+ position to that value. If the underline position is not valid,
+ return false, and ignore position.
+
+ @param position storage for underline position
+ @return true if font specifies underline position
+ */
+ bool hasUnderlinePosition(SkScalar* position) const {
+ if (SkToBool(fFlags & kUnderlinePositionIsValid_Flag)) {
+ *position = fUnderlinePosition;
+ return true;
+ }
+ return false;
+ }
+
+ /** Returns true if SkFontMetrics has a valid strikeout thickness, and sets
+ thickness to that value. If the underline thickness is not valid,
+ return false, and ignore thickness.
+
+ @param thickness storage for strikeout width
+ @return true if font specifies strikeout width
+ */
+ bool hasStrikeoutThickness(SkScalar* thickness) const {
+ if (SkToBool(fFlags & kStrikeoutThicknessIsValid_Flag)) {
+ *thickness = fStrikeoutThickness;
+ return true;
+ }
+ return false;
+ }
+
+ /** Returns true if SkFontMetrics has a valid strikeout position, and sets
+ position to that value. If the underline position is not valid,
+ return false, and ignore position.
+
+ @param position storage for strikeout position
+ @return true if font specifies strikeout position
+ */
+ bool hasStrikeoutPosition(SkScalar* position) const {
+ if (SkToBool(fFlags & kStrikeoutPositionIsValid_Flag)) {
+ *position = fStrikeoutPosition;
+ return true;
+ }
+ return false;
+ }
+
+ /** Returns true if SkFontMetrics has a valid fTop, fBottom, fXMin, and fXMax.
+ If the bounds are not valid, return false.
+
+ @return true if font specifies maximum glyph bounds
+ */
+ bool hasBounds() const {
+ return !SkToBool(fFlags & kBoundsInvalid_Flag);
+ }
+};
+
+#endif
diff --git a/src/deps/skia/include/core/SkFontMgr.h b/src/deps/skia/include/core/SkFontMgr.h
new file mode 100644
index 000000000..611faa3aa
--- /dev/null
+++ b/src/deps/skia/include/core/SkFontMgr.h
@@ -0,0 +1,157 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkFontMgr_DEFINED
+#define SkFontMgr_DEFINED
+
+#include "include/core/SkFontArguments.h"
+#include "include/core/SkFontStyle.h"
+#include "include/core/SkRefCnt.h"
+#include "include/core/SkTypes.h"
+
+class SkData;
+class SkFontData;
+class SkStreamAsset;
+class SkString;
+class SkTypeface;
+
+class SK_API SkFontStyleSet : public SkRefCnt {
+public:
+ virtual int count() = 0;
+ virtual void getStyle(int index, SkFontStyle*, SkString* style) = 0;
+ virtual SkTypeface* createTypeface(int index) = 0;
+ virtual SkTypeface* matchStyle(const SkFontStyle& pattern) = 0;
+
+ static SkFontStyleSet* CreateEmpty();
+
+protected:
+ SkTypeface* matchStyleCSS3(const SkFontStyle& pattern);
+
+private:
+ using INHERITED = SkRefCnt;
+};
+
+class SK_API SkFontMgr : public SkRefCnt {
+public:
+ int countFamilies() const;
+ void getFamilyName(int index, SkString* familyName) const;
+ SkFontStyleSet* createStyleSet(int index) const;
+
+ /**
+ * The caller must call unref() on the returned object.
+ * Never returns NULL; will return an empty set if the name is not found.
+ *
+ * Passing nullptr as the parameter will return the default system family.
+ * Note that most systems don't have a default system family, so passing nullptr will often
+ * result in the empty set.
+ *
+ * It is possible that this will return a style set not accessible from
+ * createStyleSet(int) due to hidden or auto-activated fonts.
+ */
+ SkFontStyleSet* matchFamily(const char familyName[]) const;
+
+ /**
+ * Find the closest matching typeface to the specified familyName and style
+ * and return a ref to it. The caller must call unref() on the returned
+ * object. Will return nullptr if no 'good' match is found.
+ *
+ * Passing |nullptr| as the parameter for |familyName| will return the
+ * default system font.
+ *
+ * It is possible that this will return a style set not accessible from
+ * createStyleSet(int) or matchFamily(const char[]) due to hidden or
+ * auto-activated fonts.
+ */
+ SkTypeface* matchFamilyStyle(const char familyName[], const SkFontStyle&) const;
+
+ /**
+ * Use the system fallback to find a typeface for the given character.
+ * Note that bcp47 is a combination of ISO 639, 15924, and 3166-1 codes,
+ * so it is fine to just pass a ISO 639 here.
+ *
+ * Will return NULL if no family can be found for the character
+ * in the system fallback.
+ *
+ * Passing |nullptr| as the parameter for |familyName| will return the
+ * default system font.
+ *
+ * bcp47[0] is the least significant fallback, bcp47[bcp47Count-1] is the
+ * most significant. If no specified bcp47 codes match, any font with the
+ * requested character will be matched.
+ */
+ SkTypeface* matchFamilyStyleCharacter(const char familyName[], const SkFontStyle&,
+ const char* bcp47[], int bcp47Count,
+ SkUnichar character) const;
+
+ /**
+ * Create a typeface for the specified data and TTC index (pass 0 for none)
+ * or NULL if the data is not recognized. The caller must call unref() on
+ * the returned object if it is not null.
+ */
+ sk_sp<SkTypeface> makeFromData(sk_sp<SkData>, int ttcIndex = 0) const;
+
+ /**
+ * Create a typeface for the specified stream and TTC index
+ * (pass 0 for none) or NULL if the stream is not recognized. The caller
+ * must call unref() on the returned object if it is not null.
+ */
+ sk_sp<SkTypeface> makeFromStream(std::unique_ptr<SkStreamAsset>, int ttcIndex = 0) const;
+
+ /* Experimental, API subject to change. */
+ sk_sp<SkTypeface> makeFromStream(std::unique_ptr<SkStreamAsset>, const SkFontArguments&) const;
+
+ /**
+ * Create a typeface for the specified fileName and TTC index
+ * (pass 0 for none) or NULL if the file is not found, or its contents are
+ * not recognized. The caller must call unref() on the returned object
+ * if it is not null.
+ */
+ sk_sp<SkTypeface> makeFromFile(const char path[], int ttcIndex = 0) const;
+
+ sk_sp<SkTypeface> legacyMakeTypeface(const char familyName[], SkFontStyle style) const;
+
+ /** Return the default fontmgr. */
+ static sk_sp<SkFontMgr> RefDefault();
+
+protected:
+ virtual int onCountFamilies() const = 0;
+ virtual void onGetFamilyName(int index, SkString* familyName) const = 0;
+ virtual SkFontStyleSet* onCreateStyleSet(int index)const = 0;
+
+ /** May return NULL if the name is not found. */
+ virtual SkFontStyleSet* onMatchFamily(const char familyName[]) const = 0;
+
+ virtual SkTypeface* onMatchFamilyStyle(const char familyName[],
+ const SkFontStyle&) const = 0;
+ virtual SkTypeface* onMatchFamilyStyleCharacter(const char familyName[], const SkFontStyle&,
+ const char* bcp47[], int bcp47Count,
+ SkUnichar character) const = 0;
+
+ virtual sk_sp<SkTypeface> onMakeFromData(sk_sp<SkData>, int ttcIndex) const = 0;
+ virtual sk_sp<SkTypeface> onMakeFromStreamIndex(std::unique_ptr<SkStreamAsset>,
+ int ttcIndex) const = 0;
+ virtual sk_sp<SkTypeface> onMakeFromStreamArgs(std::unique_ptr<SkStreamAsset>,
+ const SkFontArguments&) const = 0;
+ virtual sk_sp<SkTypeface> onMakeFromFile(const char path[], int ttcIndex) const = 0;
+
+ virtual sk_sp<SkTypeface> onLegacyMakeTypeface(const char familyName[], SkFontStyle) const = 0;
+
+ // this method is never called -- will be removed
+ virtual SkTypeface* onMatchFaceStyle(const SkTypeface*,
+ const SkFontStyle&) const {
+ return nullptr;
+ }
+
+private:
+
+ /** Implemented by porting layer to return the default factory. */
+ static sk_sp<SkFontMgr> Factory();
+
+ using INHERITED = SkRefCnt;
+};
+
+#endif
diff --git a/src/deps/skia/include/core/SkFontParameters.h b/src/deps/skia/include/core/SkFontParameters.h
new file mode 100644
index 000000000..ae4f1d68b
--- /dev/null
+++ b/src/deps/skia/include/core/SkFontParameters.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2018 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkFontParameters_DEFINED
+#define SkFontParameters_DEFINED
+
+#include "include/core/SkScalar.h"
+#include "include/core/SkTypes.h"
+
+struct SkFontParameters {
+ struct Variation {
+ // Parameters in a variation font axis.
+ struct Axis {
+ constexpr Axis() : tag(0), min(0), def(0), max(0), flags(0) {}
+ constexpr Axis(SkFourByteTag tag, float min, float def, float max, bool hidden) :
+ tag(tag), min(min), def(def), max(max), flags(hidden ? HIDDEN : 0) {}
+
+ // Four character identifier of the font axis (weight, width, slant, italic...).
+ SkFourByteTag tag;
+ // Minimum value supported by this axis.
+ float min;
+ // Default value set by this axis.
+ float def;
+ // Maximum value supported by this axis. The maximum can equal the minimum.
+ float max;
+ // Return whether this axis is recommended to be remain hidden in user interfaces.
+ bool isHidden() const { return flags & HIDDEN; }
+ // Set this axis to be remain hidden in user interfaces.
+ void setHidden(bool hidden) { flags = hidden ? (flags | HIDDEN) : (flags & ~HIDDEN); }
+ private:
+ static constexpr uint16_t HIDDEN = 0x0001;
+ // Attributes for a font axis.
+ uint16_t flags;
+ };
+ };
+};
+
+#endif
diff --git a/src/deps/skia/include/core/SkFontStyle.h b/src/deps/skia/include/core/SkFontStyle.h
new file mode 100644
index 000000000..04893ef2f
--- /dev/null
+++ b/src/deps/skia/include/core/SkFontStyle.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkFontStyle_DEFINED
+#define SkFontStyle_DEFINED
+
+#include "include/core/SkTypes.h"
+#include "include/private/SkTPin.h"
+
+class SK_API SkFontStyle {
+public:
+ enum Weight {
+ kInvisible_Weight = 0,
+ kThin_Weight = 100,
+ kExtraLight_Weight = 200,
+ kLight_Weight = 300,
+ kNormal_Weight = 400,
+ kMedium_Weight = 500,
+ kSemiBold_Weight = 600,
+ kBold_Weight = 700,
+ kExtraBold_Weight = 800,
+ kBlack_Weight = 900,
+ kExtraBlack_Weight = 1000,
+ };
+
+ enum Width {
+ kUltraCondensed_Width = 1,
+ kExtraCondensed_Width = 2,
+ kCondensed_Width = 3,
+ kSemiCondensed_Width = 4,
+ kNormal_Width = 5,
+ kSemiExpanded_Width = 6,
+ kExpanded_Width = 7,
+ kExtraExpanded_Width = 8,
+ kUltraExpanded_Width = 9,
+ };
+
+ enum Slant {
+ kUpright_Slant,
+ kItalic_Slant,
+ kOblique_Slant,
+ };
+
+ constexpr SkFontStyle(int weight, int width, Slant slant) : fValue(
+ (SkTPin<int>(weight, kInvisible_Weight, kExtraBlack_Weight)) +
+ (SkTPin<int>(width, kUltraCondensed_Width, kUltraExpanded_Width) << 16) +
+ (SkTPin<int>(slant, kUpright_Slant, kOblique_Slant) << 24)
+ ) { }
+
+ constexpr SkFontStyle() : SkFontStyle{kNormal_Weight, kNormal_Width, kUpright_Slant} { }
+
+ bool operator==(const SkFontStyle& rhs) const {
+ return fValue == rhs.fValue;
+ }
+
+ int weight() const { return fValue & 0xFFFF; }
+ int width() const { return (fValue >> 16) & 0xFF; }
+ Slant slant() const { return (Slant)((fValue >> 24) & 0xFF); }
+
+ static constexpr SkFontStyle Normal() {
+ return SkFontStyle(kNormal_Weight, kNormal_Width, kUpright_Slant);
+ }
+ static constexpr SkFontStyle Bold() {
+ return SkFontStyle(kBold_Weight, kNormal_Width, kUpright_Slant);
+ }
+ static constexpr SkFontStyle Italic() {
+ return SkFontStyle(kNormal_Weight, kNormal_Width, kItalic_Slant );
+ }
+ static constexpr SkFontStyle BoldItalic() {
+ return SkFontStyle(kBold_Weight, kNormal_Width, kItalic_Slant );
+ }
+
+private:
+ int32_t fValue;
+};
+
+#endif
diff --git a/src/deps/skia/include/core/SkFontTypes.h b/src/deps/skia/include/core/SkFontTypes.h
new file mode 100644
index 000000000..76f5dde67
--- /dev/null
+++ b/src/deps/skia/include/core/SkFontTypes.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2018 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkFontTypes_DEFINED
+#define SkFontTypes_DEFINED
+
+enum class SkTextEncoding {
+ kUTF8, //!< uses bytes to represent UTF-8 or ASCII
+ kUTF16, //!< uses two byte words to represent most of Unicode
+ kUTF32, //!< uses four byte words to represent all of Unicode
+ kGlyphID, //!< uses two byte words to represent glyph indices
+};
+
+enum class SkFontHinting {
+ kNone, //!< glyph outlines unchanged
+ kSlight, //!< minimal modification to improve constrast
+ kNormal, //!< glyph outlines modified to improve constrast
+ kFull, //!< modifies glyph outlines for maximum constrast
+};
+
+#endif
diff --git a/src/deps/skia/include/core/SkGraphics.h b/src/deps/skia/include/core/SkGraphics.h
new file mode 100644
index 000000000..b68bb78ba
--- /dev/null
+++ b/src/deps/skia/include/core/SkGraphics.h
@@ -0,0 +1,153 @@
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkGraphics_DEFINED
+#define SkGraphics_DEFINED
+
+#include "include/core/SkRefCnt.h"
+
+class SkData;
+class SkImageGenerator;
+class SkTraceMemoryDump;
+
+class SK_API SkGraphics {
+public:
+ /**
+ * Call this at process initialization time if your environment does not
+ * permit static global initializers that execute code.
+ * Init() is thread-safe and idempotent.
+ */
+ static void Init();
+
+ /**
+ * Return the max number of bytes that should be used by the font cache.
+ * If the cache needs to allocate more, it will purge previous entries.
+ * This max can be changed by calling SetFontCacheLimit().
+ */
+ static size_t GetFontCacheLimit();
+
+ /**
+ * Specify the max number of bytes that should be used by the font cache.
+ * If the cache needs to allocate more, it will purge previous entries.
+ *
+ * This function returns the previous setting, as if GetFontCacheLimit()
+ * had be called before the new limit was set.
+ */
+ static size_t SetFontCacheLimit(size_t bytes);
+
+ /**
+ * Return the number of bytes currently used by the font cache.
+ */
+ static size_t GetFontCacheUsed();
+
+ /**
+ * Return the number of entries in the font cache.
+ * A cache "entry" is associated with each typeface + pointSize + matrix.
+ */
+ static int GetFontCacheCountUsed();
+
+ /**
+ * Return the current limit to the number of entries in the font cache.
+ * A cache "entry" is associated with each typeface + pointSize + matrix.
+ */
+ static int GetFontCacheCountLimit();
+
+ /**
+ * Set the limit to the number of entries in the font cache, and return
+ * the previous value. If this new value is lower than the previous,
+ * it will automatically try to purge entries to meet the new limit.
+ */
+ static int SetFontCacheCountLimit(int count);
+
+ /**
+ * For debugging purposes, this will attempt to purge the font cache. It
+ * does not change the limit, but will cause subsequent font measures and
+ * draws to be recreated, since they will no longer be in the cache.
+ */
+ static void PurgeFontCache();
+
+ /**
+ * This function returns the memory used for temporary images and other resources.
+ */
+ static size_t GetResourceCacheTotalBytesUsed();
+
+ /**
+ * These functions get/set the memory usage limit for the resource cache, used for temporary
+ * bitmaps and other resources. Entries are purged from the cache when the memory useage
+ * exceeds this limit.
+ */
+ static size_t GetResourceCacheTotalByteLimit();
+ static size_t SetResourceCacheTotalByteLimit(size_t newLimit);
+
+ /**
+ * For debugging purposes, this will attempt to purge the resource cache. It
+ * does not change the limit.
+ */
+ static void PurgeResourceCache();
+
+ /**
+ * When the cachable entry is very lage (e.g. a large scaled bitmap), adding it to the cache
+ * can cause most/all of the existing entries to be purged. To avoid the, the client can set
+ * a limit for a single allocation. If a cacheable entry would have been cached, but its size
+ * exceeds this limit, then we do not attempt to cache it at all.
+ *
+ * Zero is the default value, meaning we always attempt to cache entries.
+ */
+ static size_t GetResourceCacheSingleAllocationByteLimit();
+ static size_t SetResourceCacheSingleAllocationByteLimit(size_t newLimit);
+
+ /**
+ * Dumps memory usage of caches using the SkTraceMemoryDump interface. See SkTraceMemoryDump
+ * for usage of this method.
+ */
+ static void DumpMemoryStatistics(SkTraceMemoryDump* dump);
+
+ /**
+ * Free as much globally cached memory as possible. This will purge all private caches in Skia,
+ * including font and image caches.
+ *
+ * If there are caches associated with GPU context, those will not be affected by this call.
+ */
+ static void PurgeAllCaches();
+
+ /**
+ * Applications with command line options may pass optional state, such
+ * as cache sizes, here, for instance:
+ * font-cache-limit=12345678
+ *
+ * The flags format is name=value[;name=value...] with no spaces.
+ * This format is subject to change.
+ */
+ static void SetFlags(const char* flags);
+
+ typedef std::unique_ptr<SkImageGenerator>
+ (*ImageGeneratorFromEncodedDataFactory)(sk_sp<SkData>);
+
+ /**
+ * To instantiate images from encoded data, first looks at this runtime function-ptr. If it
+ * exists, it is called to create an SkImageGenerator from SkData. If there is no function-ptr
+ * or there is, but it returns NULL, then skia will call its internal default implementation.
+ *
+ * Returns the previous factory (which could be NULL).
+ */
+ static ImageGeneratorFromEncodedDataFactory
+ SetImageGeneratorFromEncodedDataFactory(ImageGeneratorFromEncodedDataFactory);
+
+ /**
+ * Call early in main() to allow Skia to use a JIT to accelerate CPU-bound operations.
+ */
+ static void AllowJIT();
+};
+
+class SkAutoGraphics {
+public:
+ SkAutoGraphics() {
+ SkGraphics::Init();
+ }
+};
+
+#endif
diff --git a/src/deps/skia/include/core/SkICC.h b/src/deps/skia/include/core/SkICC.h
new file mode 100644
index 000000000..cb84c1ffb
--- /dev/null
+++ b/src/deps/skia/include/core/SkICC.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkICC_DEFINED
+#define SkICC_DEFINED
+
+#include "include/core/SkData.h"
+
+struct skcms_Matrix3x3;
+struct skcms_TransferFunction;
+
+SK_API sk_sp<SkData> SkWriteICCProfile(const skcms_TransferFunction&,
+ const skcms_Matrix3x3& toXYZD50);
+
+#endif//SkICC_DEFINED
diff --git a/src/deps/skia/include/core/SkImage.h b/src/deps/skia/include/core/SkImage.h
new file mode 100644
index 000000000..bdcfff3fa
--- /dev/null
+++ b/src/deps/skia/include/core/SkImage.h
@@ -0,0 +1,1302 @@
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkImage_DEFINED
+#define SkImage_DEFINED
+
+#include "include/core/SkImageEncoder.h"
+#include "include/core/SkImageInfo.h"
+#include "include/core/SkRefCnt.h"
+#include "include/core/SkSamplingOptions.h"
+#include "include/core/SkScalar.h"
+#include "include/core/SkShader.h"
+#include "include/core/SkTileMode.h"
+#include "include/private/SkTOptional.h"
+#if SK_SUPPORT_GPU
+#include "include/gpu/GrTypes.h"
+#endif
+#include <functional> // std::function
+
+#if defined(SK_BUILD_FOR_ANDROID) && __ANDROID_API__ >= 26
+#include <android/hardware_buffer.h>
+#endif
+
+class SkData;
+class SkCanvas;
+class SkImage;
+class SkImageFilter;
+class SkImageGenerator;
+class SkMipmap;
+class SkPaint;
+class SkPicture;
+class SkPromiseImageTexture;
+class SkSurface;
+class SkYUVAPixmaps;
+class GrBackendFormat;
+class GrBackendTexture;
+class GrDirectContext;
+class GrRecordingContext;
+class GrContextThreadSafeProxy;
+class GrYUVABackendTextureInfo;
+class GrYUVABackendTextures;
+
+/** \class SkImage
+ SkImage describes a two dimensional array of pixels to draw. The pixels may be
+ decoded in a raster bitmap, encoded in a SkPicture or compressed data stream,
+ or located in GPU memory as a GPU texture.
+
+ SkImage cannot be modified after it is created. SkImage may allocate additional
+ storage as needed; for instance, an encoded SkImage may decode when drawn.
+
+ SkImage width and height are greater than zero. Creating an SkImage with zero width
+ or height returns SkImage equal to nullptr.
+
+ SkImage may be created from SkBitmap, SkPixmap, SkSurface, SkPicture, encoded streams,
+ GPU texture, YUV_ColorSpace data, or hardware buffer. Encoded streams supported
+ include BMP, GIF, HEIF, ICO, JPEG, PNG, WBMP, WebP. Supported encoding details
+ vary with platform.
+*/
+class SK_API SkImage : public SkRefCnt {
+public:
+
+ /** Caller data passed to RasterReleaseProc; may be nullptr.
+ */
+ typedef void* ReleaseContext;
+
+ /** Creates SkImage from SkPixmap and copy of pixels. Since pixels are copied, SkPixmap
+ pixels may be modified or deleted without affecting SkImage.
+
+ SkImage is returned if SkPixmap is valid. Valid SkPixmap parameters include:
+ dimensions are greater than zero;
+ each dimension fits in 29 bits;
+ SkColorType and SkAlphaType are valid, and SkColorType is not kUnknown_SkColorType;
+ row bytes are large enough to hold one row of pixels;
+ pixel address is not nullptr.
+
+ @param pixmap SkImageInfo, pixel address, and row bytes
+ @return copy of SkPixmap pixels, or nullptr
+
+ example: https://fiddle.skia.org/c/@Image_MakeRasterCopy
+ */
+ static sk_sp<SkImage> MakeRasterCopy(const SkPixmap& pixmap);
+
+ /** Creates SkImage from SkImageInfo, sharing pixels.
+
+ SkImage is returned if SkImageInfo is valid. Valid SkImageInfo parameters include:
+ dimensions are greater than zero;
+ each dimension fits in 29 bits;
+ SkColorType and SkAlphaType are valid, and SkColorType is not kUnknown_SkColorType;
+ rowBytes are large enough to hold one row of pixels;
+ pixels is not nullptr, and contains enough data for SkImage.
+
+ @param info contains width, height, SkAlphaType, SkColorType, SkColorSpace
+ @param pixels address or pixel storage
+ @param rowBytes size of pixel row or larger
+ @return SkImage sharing pixels, or nullptr
+ */
+ static sk_sp<SkImage> MakeRasterData(const SkImageInfo& info, sk_sp<SkData> pixels,
+ size_t rowBytes);
+
+ /** Function called when SkImage no longer shares pixels. ReleaseContext is
+ provided by caller when SkImage is created, and may be nullptr.
+ */
+ typedef void (*RasterReleaseProc)(const void* pixels, ReleaseContext);
+
+ /** Creates SkImage from pixmap, sharing SkPixmap pixels. Pixels must remain valid and
+ unchanged until rasterReleaseProc is called. rasterReleaseProc is passed
+ releaseContext when SkImage is deleted or no longer refers to pixmap pixels.
+
+ Pass nullptr for rasterReleaseProc to share SkPixmap without requiring a callback
+ when SkImage is released. Pass nullptr for releaseContext if rasterReleaseProc
+ does not require state.
+
+ SkImage is returned if pixmap is valid. Valid SkPixmap parameters include:
+ dimensions are greater than zero;
+ each dimension fits in 29 bits;
+ SkColorType and SkAlphaType are valid, and SkColorType is not kUnknown_SkColorType;
+ row bytes are large enough to hold one row of pixels;
+ pixel address is not nullptr.
+
+ @param pixmap SkImageInfo, pixel address, and row bytes
+ @param rasterReleaseProc function called when pixels can be released; or nullptr
+ @param releaseContext state passed to rasterReleaseProc; or nullptr
+ @return SkImage sharing pixmap
+ */
+ static sk_sp<SkImage> MakeFromRaster(const SkPixmap& pixmap,
+ RasterReleaseProc rasterReleaseProc,
+ ReleaseContext releaseContext);
+
+ /** Creates SkImage from bitmap, sharing or copying bitmap pixels. If the bitmap
+ is marked immutable, and its pixel memory is shareable, it may be shared
+ instead of copied.
+
+ SkImage is returned if bitmap is valid. Valid SkBitmap parameters include:
+ dimensions are greater than zero;
+ each dimension fits in 29 bits;
+ SkColorType and SkAlphaType are valid, and SkColorType is not kUnknown_SkColorType;
+ row bytes are large enough to hold one row of pixels;
+ pixel address is not nullptr.
+
+ @param bitmap SkImageInfo, row bytes, and pixels
+ @return created SkImage, or nullptr
+
+ example: https://fiddle.skia.org/c/@Image_MakeFromBitmap
+ */
+ static sk_sp<SkImage> MakeFromBitmap(const SkBitmap& bitmap);
+
+ /** Creates SkImage from data returned by imageGenerator. Generated data is owned by SkImage and
+ may not be shared or accessed.
+
+ SkImage is returned if generator data is valid. Valid data parameters vary by type of data
+ and platform.
+
+ imageGenerator may wrap SkPicture data, codec data, or custom data.
+
+ @param imageGenerator stock or custom routines to retrieve SkImage
+ @return created SkImage, or nullptr
+ */
+ static sk_sp<SkImage> MakeFromGenerator(std::unique_ptr<SkImageGenerator> imageGenerator);
+
+ /**
+ * Return an image backed by the encoded data, but attempt to defer decoding until the image
+ * is actually used/drawn. This deferral allows the system to cache the result, either on the
+ * CPU or on the GPU, depending on where the image is drawn. If memory is low, the cache may
+ * be purged, causing the next draw of the image to have to re-decode.
+ *
+ * If alphaType is nullopt, the image's alpha type will be chosen automatically based on the
+ * image format. Transparent images will default to kPremul_SkAlphaType. If alphaType contains
+ * kPremul_SkAlphaType or kUnpremul_SkAlphaType, that alpha type will be used. Forcing opaque
+ * (passing kOpaque_SkAlphaType) is not allowed, and will return nullptr.
+ *
+ * This is similar to DecodeTo[Raster,Texture], but this method will attempt to defer the
+ * actual decode, while the DecodeTo... method explicitly decode and allocate the backend
+ * when the call is made.
+ *
+ * If the encoded format is not supported, nullptr is returned.
+ *
+ * @param encoded the encoded data
+ * @return created SkImage, or nullptr
+
+ example: https://fiddle.skia.org/c/@Image_MakeFromEncoded
+ */
+ static sk_sp<SkImage> MakeFromEncoded(sk_sp<SkData> encoded,
+ skstd::optional<SkAlphaType> alphaType = skstd::nullopt);
+
+ /*
+ * Experimental:
+ * Skia | GL_COMPRESSED_* | MTLPixelFormat* | VK_FORMAT_*_BLOCK
+ * --------------------------------------------------------------------------------------
+ * kETC2_RGB8_UNORM | ETC1_RGB8 | ETC2_RGB8 (iOS-only) | ETC2_R8G8B8_UNORM
+ * | RGB8_ETC2 | |
+ * --------------------------------------------------------------------------------------
+ * kBC1_RGB8_UNORM | RGB_S3TC_DXT1_EXT | N/A | BC1_RGB_UNORM
+ * --------------------------------------------------------------------------------------
+ * kBC1_RGBA8_UNORM | RGBA_S3TC_DXT1_EXT | BC1_RGBA (macOS-only)| BC1_RGBA_UNORM
+ */
+ enum class CompressionType {
+ kNone,
+ kETC2_RGB8_UNORM, // the same as ETC1
+
+ kBC1_RGB8_UNORM,
+ kBC1_RGBA8_UNORM,
+ kLast = kBC1_RGBA8_UNORM,
+ };
+
+ static constexpr int kCompressionTypeCount = static_cast<int>(CompressionType::kLast) + 1;
+
+ static const CompressionType kETC1_CompressionType = CompressionType::kETC2_RGB8_UNORM;
+
+ /** Creates a CPU-backed SkImage from compressed data.
+
+ This method will decompress the compressed data and create an image wrapping
+ it. Any mipmap levels present in the compressed data are discarded.
+
+ @param data compressed data to store in SkImage
+ @param width width of full SkImage
+ @param height height of full SkImage
+ @param type type of compression used
+ @return created SkImage, or nullptr
+ */
+ static sk_sp<SkImage> MakeRasterFromCompressed(sk_sp<SkData> data,
+ int width, int height,
+ CompressionType type);
+
+ enum class BitDepth {
+ kU8, //!< uses 8-bit unsigned int per color component
+ kF16, //!< uses 16-bit float per color component
+ };
+
+ /** Creates SkImage from picture. Returned SkImage width and height are set by dimensions.
+ SkImage draws picture with matrix and paint, set to bitDepth and colorSpace.
+
+ If matrix is nullptr, draws with identity SkMatrix. If paint is nullptr, draws
+ with default SkPaint. colorSpace may be nullptr.
+
+ @param picture stream of drawing commands
+ @param dimensions width and height
+ @param matrix SkMatrix to rotate, scale, translate, and so on; may be nullptr
+ @param paint SkPaint to apply transparency, filtering, and so on; may be nullptr
+ @param bitDepth 8-bit integer or 16-bit float: per component
+ @param colorSpace range of colors; may be nullptr
+ @return created SkImage, or nullptr
+ */
+ static sk_sp<SkImage> MakeFromPicture(sk_sp<SkPicture> picture, const SkISize& dimensions,
+ const SkMatrix* matrix, const SkPaint* paint,
+ BitDepth bitDepth,
+ sk_sp<SkColorSpace> colorSpace);
+
+#if SK_SUPPORT_GPU
+ /** Creates a GPU-backed SkImage from compressed data.
+
+ This method will return an SkImage representing the compressed data.
+ If the GPU doesn't support the specified compression method, the data
+ will be decompressed and then wrapped in a GPU-backed image.
+
+ Note: one can query the supported compression formats via
+ GrRecordingContext::compressedBackendFormat.
+
+ @param context GPU context
+ @param data compressed data to store in SkImage
+ @param width width of full SkImage
+ @param height height of full SkImage
+ @param type type of compression used
+ @param mipMapped does 'data' contain data for all the mipmap levels?
+ @param isProtected do the contents of 'data' require DRM protection (on Vulkan)?
+ @return created SkImage, or nullptr
+ */
+ static sk_sp<SkImage> MakeTextureFromCompressed(GrDirectContext* direct,
+ sk_sp<SkData> data,
+ int width, int height,
+ CompressionType type,
+ GrMipmapped mipMapped = GrMipmapped::kNo,
+ GrProtected isProtected = GrProtected::kNo);
+
+ /** User function called when supplied texture may be deleted.
+ */
+ typedef void (*TextureReleaseProc)(ReleaseContext releaseContext);
+
+ /** Creates SkImage from GPU texture associated with context. GPU texture must stay
+ valid and unchanged until textureReleaseProc is called. textureReleaseProc is
+ passed releaseContext when SkImage is deleted or no longer refers to texture.
+
+ SkImage is returned if format of backendTexture is recognized and supported.
+ Recognized formats vary by GPU back-end.
+
+ @note When using a DDL recording context, textureReleaseProc will be called on the
+ GPU thread after the DDL is played back on the direct context.
+
+ @param context GPU context
+ @param backendTexture texture residing on GPU
+ @param colorSpace This describes the color space of this image's contents, as
+ seen after sampling. In general, if the format of the backend
+ texture is SRGB, some linear colorSpace should be supplied
+ (e.g., SkColorSpace::MakeSRGBLinear()). If the format of the
+ backend texture is linear, then the colorSpace should include
+ a description of the transfer function as
+ well (e.g., SkColorSpace::MakeSRGB()).
+ @param textureReleaseProc function called when texture can be released
+ @param releaseContext state passed to textureReleaseProc
+ @return created SkImage, or nullptr
+ */
+ static sk_sp<SkImage> MakeFromTexture(GrRecordingContext* context,
+ const GrBackendTexture& backendTexture,
+ GrSurfaceOrigin origin,
+ SkColorType colorType,
+ SkAlphaType alphaType,
+ sk_sp<SkColorSpace> colorSpace,
+ TextureReleaseProc textureReleaseProc = nullptr,
+ ReleaseContext releaseContext = nullptr);
+
+ /** Creates an SkImage from a GPU backend texture. The backend texture must stay
+ valid and unchanged until textureReleaseProc is called. The textureReleaseProc is
+ called when the SkImage is deleted or no longer refers to the texture and will be
+ passed the releaseContext.
+
+ An SkImage is returned if the format of backendTexture is recognized and supported.
+ Recognized formats vary by GPU back-end.
+
+ @note When using a DDL recording context, textureReleaseProc will be called on the
+ GPU thread after the DDL is played back on the direct context.
+
+ @param context the GPU context
+ @param backendTexture a texture already allocated by the GPU
+ @param alphaType This characterizes the nature of the alpha values in the
+ backend texture. For opaque compressed formats (e.g., ETC1)
+ this should usually be set to kOpaque_SkAlphaType.
+ @param colorSpace This describes the color space of this image's contents, as
+ seen after sampling. In general, if the format of the backend
+ texture is SRGB, some linear colorSpace should be supplied
+ (e.g., SkColorSpace::MakeSRGBLinear()). If the format of the
+ backend texture is linear, then the colorSpace should include
+ a description of the transfer function as
+ well (e.g., SkColorSpace::MakeSRGB()).
+ @param textureReleaseProc function called when the backend texture can be released
+ @param releaseContext state passed to textureReleaseProc
+ @return created SkImage, or nullptr
+ */
+ static sk_sp<SkImage> MakeFromCompressedTexture(GrRecordingContext* context,
+ const GrBackendTexture& backendTexture,
+ GrSurfaceOrigin origin,
+ SkAlphaType alphaType,
+ sk_sp<SkColorSpace> colorSpace,
+ TextureReleaseProc textureReleaseProc = nullptr,
+ ReleaseContext releaseContext = nullptr);
+
+ /** Creates SkImage from pixmap. SkImage is uploaded to GPU back-end using context.
+
+ Created SkImage is available to other GPU contexts, and is available across thread
+ boundaries. All contexts must be in the same GPU share group, or otherwise
+ share resources.
+
+ When SkImage is no longer referenced, context releases texture memory
+ asynchronously.
+
+ GrBackendTexture created from pixmap is uploaded to match SkSurface created with
+ dstColorSpace. SkColorSpace of SkImage is determined by pixmap.colorSpace().
+
+ SkImage is returned referring to GPU back-end if context is not nullptr,
+ format of data is recognized and supported, and if context supports moving
+ resources between contexts. Otherwise, pixmap pixel data is copied and SkImage
+ as returned in raster format if possible; nullptr may be returned.
+ Recognized GPU formats vary by platform and GPU back-end.
+
+ @param context GPU context
+ @param pixmap SkImageInfo, pixel address, and row bytes
+ @param buildMips create SkImage as mip map if true
+ @param dstColorSpace range of colors of matching SkSurface on GPU
+ @param limitToMaxTextureSize downscale image to GPU maximum texture size, if necessary
+ @return created SkImage, or nullptr
+ */
+ static sk_sp<SkImage> MakeCrossContextFromPixmap(GrDirectContext* context,
+ const SkPixmap& pixmap,
+ bool buildMips,
+ bool limitToMaxTextureSize = false);
+
+ /** Creates SkImage from backendTexture associated with context. backendTexture and
+ returned SkImage are managed internally, and are released when no longer needed.
+
+ SkImage is returned if format of backendTexture is recognized and supported.
+ Recognized formats vary by GPU back-end.
+
+ @param context GPU context
+ @param backendTexture texture residing on GPU
+ @param textureOrigin origin of backendTexture
+ @param colorType color type of the resulting image
+ @param alphaType alpha type of the resulting image
+ @param colorSpace range of colors; may be nullptr
+ @return created SkImage, or nullptr
+ */
+ static sk_sp<SkImage> MakeFromAdoptedTexture(GrRecordingContext* context,
+ const GrBackendTexture& backendTexture,
+ GrSurfaceOrigin textureOrigin,
+ SkColorType colorType,
+ SkAlphaType alphaType = kPremul_SkAlphaType,
+ sk_sp<SkColorSpace> colorSpace = nullptr);
+
+ /** Creates an SkImage from YUV[A] planar textures. This requires that the textures stay valid
+ for the lifetime of the image. The ReleaseContext can be used to know when it is safe to
+ either delete or overwrite the textures. If ReleaseProc is provided it is also called before
+ return on failure.
+
+ @param context GPU context
+ @param yuvaTextures A set of textures containing YUVA data and a description of the
+ data and transformation to RGBA.
+ @param imageColorSpace range of colors of the resulting image after conversion to RGB;
+ may be nullptr
+ @param textureReleaseProc called when the backend textures can be released
+ @param releaseContext state passed to textureReleaseProc
+ @return created SkImage, or nullptr
+ */
+ static sk_sp<SkImage> MakeFromYUVATextures(GrRecordingContext* context,
+ const GrYUVABackendTextures& yuvaTextures,
+ sk_sp<SkColorSpace> imageColorSpace = nullptr,
+ TextureReleaseProc textureReleaseProc = nullptr,
+ ReleaseContext releaseContext = nullptr);
+
+ /** Creates SkImage from SkYUVAPixmaps.
+
+ The image will remain planar with each plane converted to a texture using the passed
+ GrRecordingContext.
+
+ SkYUVAPixmaps has a SkYUVAInfo which specifies the transformation from YUV to RGB.
+ The SkColorSpace of the resulting RGB values is specified by imageColorSpace. This will
+ be the SkColorSpace reported by the image and when drawn the RGB values will be converted
+ from this space into the destination space (if the destination is tagged).
+
+ Currently, this is only supported using the GPU backend and will fail if context is nullptr.
+
+ SkYUVAPixmaps does not need to remain valid after this returns.
+
+ @param context GPU context
+ @param pixmaps The planes as pixmaps with supported SkYUVAInfo that
+ specifies conversion to RGB.
+ @param buildMips create internal YUVA textures as mip map if kYes. This is
+ silently ignored if the context does not support mip maps.
+ @param limitToMaxTextureSize downscale image to GPU maximum texture size, if necessary
+ @param imageColorSpace range of colors of the resulting image; may be nullptr
+ @return created SkImage, or nullptr
+ */
+ static sk_sp<SkImage> MakeFromYUVAPixmaps(GrRecordingContext* context,
+ const SkYUVAPixmaps& pixmaps,
+ GrMipMapped buildMips = GrMipmapped::kNo,
+ bool limitToMaxTextureSize = false,
+ sk_sp<SkColorSpace> imageColorSpace = nullptr);
+
+ using PromiseImageTextureContext = void*;
+ using PromiseImageTextureFulfillProc =
+ sk_sp<SkPromiseImageTexture> (*)(PromiseImageTextureContext);
+ using PromiseImageTextureReleaseProc = void (*)(PromiseImageTextureContext);
+
+ /** Create a new SkImage that is very similar to an SkImage created by MakeFromTexture. The
+ difference is that the caller need not have created the texture nor populated it with the
+ image pixel data. Moreover, the SkImage may be created on a thread as the creation of the
+ image does not require access to the backend API or GrDirectContext. Instead of passing a
+ GrBackendTexture the client supplies a description of the texture consisting of
+ GrBackendFormat, width, height, and GrMipmapped state. The resulting SkImage can be drawn
+ to a SkDeferredDisplayListRecorder or directly to a GPU-backed SkSurface.
+
+ When the actual texture is required to perform a backend API draw, textureFulfillProc will
+ be called to receive a GrBackendTexture. The properties of the GrBackendTexture must match
+ those set during the SkImage creation, and it must refer to a valid existing texture in the
+ backend API context/device, and be populated with the image pixel data. The texture cannot
+ be deleted until textureReleaseProc is called.
+
+ There is at most one call to each of textureFulfillProc and textureReleaseProc.
+ textureReleaseProc is always called even if image creation fails or if the
+ image is never fulfilled (e.g. it is never drawn or all draws are clipped out)
+
+ @param gpuContextProxy the thread-safe proxy of the gpu context. required.
+ @param backendFormat format of promised gpu texture
+ @param dimensions width & height of promised gpu texture
+ @param mipMapped mip mapped state of promised gpu texture
+ @param origin surface origin of promised gpu texture
+ @param colorType color type of promised gpu texture
+ @param alphaType alpha type of promised gpu texture
+ @param colorSpace range of colors; may be nullptr
+ @param textureFulfillProc function called to get actual gpu texture
+ @param textureReleaseProc function called when texture can be deleted
+ @param textureContext state passed to textureFulfillProc and textureReleaseProc
+ @return created SkImage, or nullptr
+ */
+ static sk_sp<SkImage> MakePromiseTexture(sk_sp<GrContextThreadSafeProxy> gpuContextProxy,
+ const GrBackendFormat& backendFormat,
+ SkISize dimensions,
+ GrMipmapped mipMapped,
+ GrSurfaceOrigin origin,
+ SkColorType colorType,
+ SkAlphaType alphaType,
+ sk_sp<SkColorSpace> colorSpace,
+ PromiseImageTextureFulfillProc textureFulfillProc,
+ PromiseImageTextureReleaseProc textureReleaseProc,
+ PromiseImageTextureContext textureContext);
+
+ /** This entry point operates like 'MakePromiseTexture' but it is used to construct a SkImage
+ from YUV[A] data. The source data may be planar (i.e. spread across multiple textures). In
+ the extreme Y, U, V, and A are all in different planes and thus the image is specified by
+ four textures. 'backendTextureInfo' describes the planar arrangement, texture formats,
+ conversion to RGB, and origin of the textures. Separate 'textureFulfillProc' and
+ 'textureReleaseProc' calls are made for each texture. Each texture has its own
+ PromiseImageTextureContext. If 'backendTextureInfo' is not valid then no release proc
+ calls are made. Otherwise, the calls will be made even on failure. 'textureContexts' has one
+ entry for each of the up to four textures, as indicated by 'backendTextureInfo'.
+
+ Currently the mip mapped property of 'backendTextureInfo' is ignored. However, in the
+ near future it will be required that if it is kYes then textureFulfillProc must return
+ a mip mapped texture for each plane in order to successfully draw the image.
+
+ @param gpuContextProxy the thread-safe proxy of the gpu context. required.
+ @param backendTextureInfo info about the promised yuva gpu texture
+ @param imageColorSpace range of colors; may be nullptr
+ @param textureFulfillProc function called to get actual gpu texture
+ @param textureReleaseProc function called when texture can be deleted
+ @param textureContexts state passed to textureFulfillProc and textureReleaseProc
+ @return created SkImage, or nullptr
+ */
+ static sk_sp<SkImage> MakePromiseYUVATexture(sk_sp<GrContextThreadSafeProxy> gpuContextProxy,
+ const GrYUVABackendTextureInfo& backendTextureInfo,
+ sk_sp<SkColorSpace> imageColorSpace,
+ PromiseImageTextureFulfillProc textureFulfillProc,
+ PromiseImageTextureReleaseProc textureReleaseProc,
+ PromiseImageTextureContext textureContexts[]);
+
+#endif // SK_SUPPORT_GPU
+
+#if defined(SK_BUILD_FOR_ANDROID) && __ANDROID_API__ >= 26
+ /** (See Skia bug 7447)
+ Creates SkImage from Android hardware buffer.
+ Returned SkImage takes a reference on the buffer.
+
+ Only available on Android, when __ANDROID_API__ is defined to be 26 or greater.
+
+ @param hardwareBuffer AHardwareBuffer Android hardware buffer
+ @param colorSpace range of colors; may be nullptr
+ @return created SkImage, or nullptr
+ */
+ static sk_sp<SkImage> MakeFromAHardwareBuffer(
+ AHardwareBuffer* hardwareBuffer,
+ SkAlphaType alphaType = kPremul_SkAlphaType,
+ sk_sp<SkColorSpace> colorSpace = nullptr,
+ GrSurfaceOrigin surfaceOrigin = kTopLeft_GrSurfaceOrigin);
+
+ /** Creates SkImage from Android hardware buffer and uploads the data from the SkPixmap to it.
+ Returned SkImage takes a reference on the buffer.
+
+ Only available on Android, when __ANDROID_API__ is defined to be 26 or greater.
+
+ @param context GPU context
+ @param pixmap SkPixmap that contains data to be uploaded to the AHardwareBuffer
+ @param hardwareBuffer AHardwareBuffer Android hardware buffer
+ @param surfaceOrigin surface origin for resulting image
+ @return created SkImage, or nullptr
+ */
+ static sk_sp<SkImage> MakeFromAHardwareBufferWithData(
+ GrDirectContext* context,
+ const SkPixmap& pixmap,
+ AHardwareBuffer* hardwareBuffer,
+ GrSurfaceOrigin surfaceOrigin = kTopLeft_GrSurfaceOrigin);
+#endif
+
+ /** Returns a SkImageInfo describing the width, height, color type, alpha type, and color space
+ of the SkImage.
+
+ @return image info of SkImage.
+ */
+ const SkImageInfo& imageInfo() const { return fInfo; }
+
+ /** Returns pixel count in each row.
+
+ @return pixel width in SkImage
+ */
+ int width() const { return fInfo.width(); }
+
+ /** Returns pixel row count.
+
+ @return pixel height in SkImage
+ */
+ int height() const { return fInfo.height(); }
+
+ /** Returns SkISize { width(), height() }.
+
+ @return integral size of width() and height()
+ */
+ SkISize dimensions() const { return SkISize::Make(fInfo.width(), fInfo.height()); }
+
+ /** Returns SkIRect { 0, 0, width(), height() }.
+
+ @return integral rectangle from origin to width() and height()
+ */
+ SkIRect bounds() const { return SkIRect::MakeWH(fInfo.width(), fInfo.height()); }
+
+ /** Returns value unique to image. SkImage contents cannot change after SkImage is
+ created. Any operation to create a new SkImage will receive generate a new
+ unique number.
+
+ @return unique identifier
+ */
+ uint32_t uniqueID() const { return fUniqueID; }
+
+ /** Returns SkAlphaType.
+
+ SkAlphaType returned was a parameter to an SkImage constructor,
+ or was parsed from encoded data.
+
+ @return SkAlphaType in SkImage
+
+ example: https://fiddle.skia.org/c/@Image_alphaType
+ */
+ SkAlphaType alphaType() const;
+
+ /** Returns SkColorType if known; otherwise, returns kUnknown_SkColorType.
+
+ @return SkColorType of SkImage
+
+ example: https://fiddle.skia.org/c/@Image_colorType
+ */
+ SkColorType colorType() const;
+
+ /** Returns SkColorSpace, the range of colors, associated with SkImage. The
+ reference count of SkColorSpace is unchanged. The returned SkColorSpace is
+ immutable.
+
+ SkColorSpace returned was passed to an SkImage constructor,
+ or was parsed from encoded data. SkColorSpace returned may be ignored when SkImage
+ is drawn, depending on the capabilities of the SkSurface receiving the drawing.
+
+ @return SkColorSpace in SkImage, or nullptr
+
+ example: https://fiddle.skia.org/c/@Image_colorSpace
+ */
+ SkColorSpace* colorSpace() const;
+
+ /** Returns a smart pointer to SkColorSpace, the range of colors, associated with
+ SkImage. The smart pointer tracks the number of objects sharing this
+ SkColorSpace reference so the memory is released when the owners destruct.
+
+ The returned SkColorSpace is immutable.
+
+ SkColorSpace returned was passed to an SkImage constructor,
+ or was parsed from encoded data. SkColorSpace returned may be ignored when SkImage
+ is drawn, depending on the capabilities of the SkSurface receiving the drawing.
+
+ @return SkColorSpace in SkImage, or nullptr, wrapped in a smart pointer
+
+ example: https://fiddle.skia.org/c/@Image_refColorSpace
+ */
+ sk_sp<SkColorSpace> refColorSpace() const;
+
+ /** Returns true if SkImage pixels represent transparency only. If true, each pixel
+ is packed in 8 bits as defined by kAlpha_8_SkColorType.
+
+ @return true if pixels represent a transparency mask
+
+ example: https://fiddle.skia.org/c/@Image_isAlphaOnly
+ */
+ bool isAlphaOnly() const;
+
+ /** Returns true if pixels ignore their alpha value and are treated as fully opaque.
+
+ @return true if SkAlphaType is kOpaque_SkAlphaType
+ */
+ bool isOpaque() const { return SkAlphaTypeIsOpaque(this->alphaType()); }
+
+ /**
+ * Make a shader with the specified tiling and mipmap sampling.
+ */
+ sk_sp<SkShader> makeShader(SkTileMode tmx, SkTileMode tmy, const SkSamplingOptions&,
+ const SkMatrix* localMatrix = nullptr) const;
+
+ sk_sp<SkShader> makeShader(SkTileMode tmx, SkTileMode tmy, const SkSamplingOptions& sampling,
+ const SkMatrix& lm) const {
+ return this->makeShader(tmx, tmy, sampling, &lm);
+ }
+ sk_sp<SkShader> makeShader(const SkSamplingOptions& sampling, const SkMatrix& lm) const {
+ return this->makeShader(SkTileMode::kClamp, SkTileMode::kClamp, sampling, &lm);
+ }
+ sk_sp<SkShader> makeShader(const SkSamplingOptions& sampling,
+ const SkMatrix* lm = nullptr) const {
+ return this->makeShader(SkTileMode::kClamp, SkTileMode::kClamp, sampling, lm);
+ }
+
+ /**
+ * makeRawShader functions like makeShader, but for images that contain non-color data.
+ * This includes images encoding things like normals, material properties (eg, roughness),
+ * heightmaps, or any other purely mathematical data that happens to be stored in an image.
+ * These types of images are useful with some programmable shaders (see: SkRuntimeEffect).
+ *
+ * Raw image shaders work like regular image shaders (including filtering and tiling), with
+ * a few major differences:
+ * - No color space transformation is ever applied (the color space of the image is ignored).
+ * - Images with an alpha type of kUnpremul are *not* automatically premultiplied.
+ * - Bicubic filtering is not supported. If SkSamplingOptions::useCubic is true, these
+ * factories will return nullptr.
+ */
+ sk_sp<SkShader> makeRawShader(SkTileMode tmx, SkTileMode tmy, const SkSamplingOptions&,
+ const SkMatrix* localMatrix = nullptr) const;
+
+ sk_sp<SkShader> makeRawShader(SkTileMode tmx, SkTileMode tmy, const SkSamplingOptions& sampling,
+ const SkMatrix& lm) const {
+ return this->makeRawShader(tmx, tmy, sampling, &lm);
+ }
+ sk_sp<SkShader> makeRawShader(const SkSamplingOptions& sampling, const SkMatrix& lm) const {
+ return this->makeRawShader(SkTileMode::kClamp, SkTileMode::kClamp, sampling, &lm);
+ }
+ sk_sp<SkShader> makeRawShader(const SkSamplingOptions& sampling,
+ const SkMatrix* lm = nullptr) const {
+ return this->makeRawShader(SkTileMode::kClamp, SkTileMode::kClamp, sampling, lm);
+ }
+
+ using CubicResampler = SkCubicResampler;
+
+ /** Copies SkImage pixel address, row bytes, and SkImageInfo to pixmap, if address
+ is available, and returns true. If pixel address is not available, return
+ false and leave pixmap unchanged.
+
+ @param pixmap storage for pixel state if pixels are readable; otherwise, ignored
+ @return true if SkImage has direct access to pixels
+
+ example: https://fiddle.skia.org/c/@Image_peekPixels
+ */
+ bool peekPixels(SkPixmap* pixmap) const;
+
+ /** Returns true the contents of SkImage was created on or uploaded to GPU memory,
+ and is available as a GPU texture.
+
+ @return true if SkImage is a GPU texture
+
+ example: https://fiddle.skia.org/c/@Image_isTextureBacked
+ */
+ bool isTextureBacked() const;
+
+ /** Returns an approximation of the amount of texture memory used by the image. Returns
+ zero if the image is not texture backed or if the texture has an external format.
+ */
+ size_t textureSize() const;
+
+ /** Returns true if SkImage can be drawn on either raster surface or GPU surface.
+ If context is nullptr, tests if SkImage draws on raster surface;
+ otherwise, tests if SkImage draws on GPU surface associated with context.
+
+ SkImage backed by GPU texture may become invalid if associated context is
+ invalid. lazy image may be invalid and may not draw to raster surface or
+ GPU surface or both.
+
+ @param context GPU context
+ @return true if SkImage can be drawn
+
+ example: https://fiddle.skia.org/c/@Image_isValid
+ */
+ bool isValid(GrRecordingContext* context) const;
+
+#if SK_SUPPORT_GPU
+ /** Flushes any pending uses of texture-backed images in the GPU backend. If the image is not
+ texture-backed (including promise texture images) or if the GrDirectContext does not
+ have the same context ID as the context backing the image then this is a no-op.
+
+ If the image was not used in any non-culled draws in the current queue of work for the
+ passed GrDirectContext then this is a no-op unless the GrFlushInfo contains semaphores or
+ a finish proc. Those are respected even when the image has not been used.
+
+ @param context the context on which to flush pending usages of the image.
+ @param info flush options
+ */
+ GrSemaphoresSubmitted flush(GrDirectContext* context, const GrFlushInfo& flushInfo) const;
+
+ void flush(GrDirectContext* context) const { this->flush(context, {}); }
+
+ /** Version of flush() that uses a default GrFlushInfo. Also submits the flushed work to the
+ GPU.
+ */
+ void flushAndSubmit(GrDirectContext*) const;
+
+ /** Retrieves the back-end texture. If SkImage has no back-end texture, an invalid
+ object is returned. Call GrBackendTexture::isValid to determine if the result
+ is valid.
+
+ If flushPendingGrContextIO is true, completes deferred I/O operations.
+
+ If origin in not nullptr, copies location of content drawn into SkImage.
+
+ @param flushPendingGrContextIO flag to flush outstanding requests
+ @return back-end API texture handle; invalid on failure
+ */
+ GrBackendTexture getBackendTexture(bool flushPendingGrContextIO,
+ GrSurfaceOrigin* origin = nullptr) const;
+#endif // SK_SUPPORT_GPU
+
+ /** \enum SkImage::CachingHint
+ CachingHint selects whether Skia may internally cache SkBitmap generated by
+ decoding SkImage, or by copying SkImage from GPU to CPU. The default behavior
+ allows caching SkBitmap.
+
+ Choose kDisallow_CachingHint if SkImage pixels are to be used only once, or
+ if SkImage pixels reside in a cache outside of Skia, or to reduce memory pressure.
+
+ Choosing kAllow_CachingHint does not ensure that pixels will be cached.
+ SkImage pixels may not be cached if memory requirements are too large or
+ pixels are not accessible.
+ */
+ enum CachingHint {
+ kAllow_CachingHint, //!< allows internally caching decoded and copied pixels
+ kDisallow_CachingHint, //!< disallows internally caching decoded and copied pixels
+ };
+
+ /** Copies SkRect of pixels from SkImage to dstPixels. Copy starts at offset (srcX, srcY),
+ and does not exceed SkImage (width(), height()).
+
+ dstInfo specifies width, height, SkColorType, SkAlphaType, and SkColorSpace of
+ destination. dstRowBytes specifies the gap from one destination row to the next.
+ Returns true if pixels are copied. Returns false if:
+ - dstInfo.addr() equals nullptr
+ - dstRowBytes is less than dstInfo.minRowBytes()
+ - SkPixelRef is nullptr
+
+ Pixels are copied only if pixel conversion is possible. If SkImage SkColorType is
+ kGray_8_SkColorType, or kAlpha_8_SkColorType; dstInfo.colorType() must match.
+ If SkImage SkColorType is kGray_8_SkColorType, dstInfo.colorSpace() must match.
+ If SkImage SkAlphaType is kOpaque_SkAlphaType, dstInfo.alphaType() must
+ match. If SkImage SkColorSpace is nullptr, dstInfo.colorSpace() must match. Returns
+ false if pixel conversion is not possible.
+
+ srcX and srcY may be negative to copy only top or left of source. Returns
+ false if width() or height() is zero or negative.
+ Returns false if abs(srcX) >= Image width(), or if abs(srcY) >= Image height().
+
+ If cachingHint is kAllow_CachingHint, pixels may be retained locally.
+ If cachingHint is kDisallow_CachingHint, pixels are not added to the local cache.
+
+ @param context the GrDirectContext in play, if it exists
+ @param dstInfo destination width, height, SkColorType, SkAlphaType, SkColorSpace
+ @param dstPixels destination pixel storage
+ @param dstRowBytes destination row length
+ @param srcX column index whose absolute value is less than width()
+ @param srcY row index whose absolute value is less than height()
+ @param cachingHint whether the pixels should be cached locally
+ @return true if pixels are copied to dstPixels
+ */
+ bool readPixels(GrDirectContext* context,
+ const SkImageInfo& dstInfo,
+ void* dstPixels,
+ size_t dstRowBytes,
+ int srcX, int srcY,
+ CachingHint cachingHint = kAllow_CachingHint) const;
+
+ /** Copies a SkRect of pixels from SkImage to dst. Copy starts at (srcX, srcY), and
+ does not exceed SkImage (width(), height()).
+
+ dst specifies width, height, SkColorType, SkAlphaType, SkColorSpace, pixel storage,
+ and row bytes of destination. dst.rowBytes() specifics the gap from one destination
+ row to the next. Returns true if pixels are copied. Returns false if:
+ - dst pixel storage equals nullptr
+ - dst.rowBytes is less than SkImageInfo::minRowBytes
+ - SkPixelRef is nullptr
+
+ Pixels are copied only if pixel conversion is possible. If SkImage SkColorType is
+ kGray_8_SkColorType, or kAlpha_8_SkColorType; dst.colorType() must match.
+ If SkImage SkColorType is kGray_8_SkColorType, dst.colorSpace() must match.
+ If SkImage SkAlphaType is kOpaque_SkAlphaType, dst.alphaType() must
+ match. If SkImage SkColorSpace is nullptr, dst.colorSpace() must match. Returns
+ false if pixel conversion is not possible.
+
+ srcX and srcY may be negative to copy only top or left of source. Returns
+ false if width() or height() is zero or negative.
+ Returns false if abs(srcX) >= Image width(), or if abs(srcY) >= Image height().
+
+ If cachingHint is kAllow_CachingHint, pixels may be retained locally.
+ If cachingHint is kDisallow_CachingHint, pixels are not added to the local cache.
+
+ @param context the GrDirectContext in play, if it exists
+ @param dst destination SkPixmap: SkImageInfo, pixels, row bytes
+ @param srcX column index whose absolute value is less than width()
+ @param srcY row index whose absolute value is less than height()
+ @param cachingHint whether the pixels should be cached locallyZ
+ @return true if pixels are copied to dst
+ */
+ bool readPixels(GrDirectContext* context,
+ const SkPixmap& dst,
+ int srcX,
+ int srcY,
+ CachingHint cachingHint = kAllow_CachingHint) const;
+
+#ifndef SK_IMAGE_READ_PIXELS_DISABLE_LEGACY_API
+ /** Deprecated. Use the variants that accept a GrDirectContext. */
+ bool readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
+ int srcX, int srcY, CachingHint cachingHint = kAllow_CachingHint) const;
+ bool readPixels(const SkPixmap& dst, int srcX, int srcY,
+ CachingHint cachingHint = kAllow_CachingHint) const;
+#endif
+
+ /** The result from asyncRescaleAndReadPixels() or asyncRescaleAndReadPixelsYUV420(). */
+ class AsyncReadResult {
+ public:
+ AsyncReadResult(const AsyncReadResult&) = delete;
+ AsyncReadResult(AsyncReadResult&&) = delete;
+ AsyncReadResult& operator=(const AsyncReadResult&) = delete;
+ AsyncReadResult& operator=(AsyncReadResult&&) = delete;
+
+ virtual ~AsyncReadResult() = default;
+ virtual int count() const = 0;
+ virtual const void* data(int i) const = 0;
+ virtual size_t rowBytes(int i) const = 0;
+
+ protected:
+ AsyncReadResult() = default;
+ };
+
+ /** Client-provided context that is passed to client-provided ReadPixelsContext. */
+ using ReadPixelsContext = void*;
+
+ /** Client-provided callback to asyncRescaleAndReadPixels() or
+ asyncRescaleAndReadPixelsYUV420() that is called when read result is ready or on failure.
+ */
+ using ReadPixelsCallback = void(ReadPixelsContext, std::unique_ptr<const AsyncReadResult>);
+
+ enum class RescaleGamma : bool { kSrc, kLinear };
+
+ enum class RescaleMode {
+ kNearest,
+ kRepeatedLinear,
+ kRepeatedCubic,
+ };
+
+ /** Makes image pixel data available to caller, possibly asynchronously. It can also rescale
+ the image pixels.
+
+ Currently asynchronous reads are only supported on the GPU backend and only when the
+ underlying 3D API supports transfer buffers and CPU/GPU synchronization primitives. In all
+ other cases this operates synchronously.
+
+ Data is read from the source sub-rectangle, is optionally converted to a linear gamma, is
+ rescaled to the size indicated by 'info', is then converted to the color space, color type,
+ and alpha type of 'info'. A 'srcRect' that is not contained by the bounds of the image
+ causes failure.
+
+ When the pixel data is ready the caller's ReadPixelsCallback is called with a
+ AsyncReadResult containing pixel data in the requested color type, alpha type, and color
+ space. The AsyncReadResult will have count() == 1. Upon failure the callback is called with
+ nullptr for AsyncReadResult. For a GPU image this flushes work but a submit must occur to
+ guarantee a finite time before the callback is called.
+
+ The data is valid for the lifetime of AsyncReadResult with the exception that if the SkImage
+ is GPU-backed the data is immediately invalidated if the context is abandoned or
+ destroyed.
+
+ @param info info of the requested pixels
+ @param srcRect subrectangle of image to read
+ @param rescaleGamma controls whether rescaling is done in the image's gamma or whether
+ the source data is transformed to a linear gamma before rescaling.
+ @param rescaleMode controls the technique (and cost) of the rescaling
+ @param callback function to call with result of the read
+ @param context passed to callback
+ */
+ void asyncRescaleAndReadPixels(const SkImageInfo& info,
+ const SkIRect& srcRect,
+ RescaleGamma rescaleGamma,
+ RescaleMode rescaleMode,
+ ReadPixelsCallback callback,
+ ReadPixelsContext context) const;
+
+ /**
+ Similar to asyncRescaleAndReadPixels but performs an additional conversion to YUV. The
+ RGB->YUV conversion is controlled by 'yuvColorSpace'. The YUV data is returned as three
+ planes ordered y, u, v. The u and v planes are half the width and height of the resized
+ rectangle. The y, u, and v values are single bytes. Currently this fails if 'dstSize'
+ width and height are not even. A 'srcRect' that is not contained by the bounds of the
+ image causes failure.
+
+ When the pixel data is ready the caller's ReadPixelsCallback is called with a
+ AsyncReadResult containing the planar data. The AsyncReadResult will have count() == 3.
+ Upon failure the callback is called with nullptr for AsyncReadResult. For a GPU image this
+ flushes work but a submit must occur to guarantee a finite time before the callback is
+ called.
+
+ The data is valid for the lifetime of AsyncReadResult with the exception that if the SkImage
+ is GPU-backed the data is immediately invalidated if the context is abandoned or
+ destroyed.
+
+ @param yuvColorSpace The transformation from RGB to YUV. Applied to the resized image
+ after it is converted to dstColorSpace.
+ @param dstColorSpace The color space to convert the resized image to, after rescaling.
+ @param srcRect The portion of the image to rescale and convert to YUV planes.
+ @param dstSize The size to rescale srcRect to
+ @param rescaleGamma controls whether rescaling is done in the image's gamma or whether
+ the source data is transformed to a linear gamma before rescaling.
+ @param rescaleMode controls the technique (and cost) of the rescaling
+ @param callback function to call with the planar read result
+ @param context passed to callback
+ */
+ void asyncRescaleAndReadPixelsYUV420(SkYUVColorSpace yuvColorSpace,
+ sk_sp<SkColorSpace> dstColorSpace,
+ const SkIRect& srcRect,
+ const SkISize& dstSize,
+ RescaleGamma rescaleGamma,
+ RescaleMode rescaleMode,
+ ReadPixelsCallback callback,
+ ReadPixelsContext context) const;
+
+ /** Copies SkImage to dst, scaling pixels to fit dst.width() and dst.height(), and
+ converting pixels to match dst.colorType() and dst.alphaType(). Returns true if
+ pixels are copied. Returns false if dst.addr() is nullptr, or dst.rowBytes() is
+ less than dst SkImageInfo::minRowBytes.
+
+ Pixels are copied only if pixel conversion is possible. If SkImage SkColorType is
+ kGray_8_SkColorType, or kAlpha_8_SkColorType; dst.colorType() must match.
+ If SkImage SkColorType is kGray_8_SkColorType, dst.colorSpace() must match.
+ If SkImage SkAlphaType is kOpaque_SkAlphaType, dst.alphaType() must
+ match. If SkImage SkColorSpace is nullptr, dst.colorSpace() must match. Returns
+ false if pixel conversion is not possible.
+
+ If cachingHint is kAllow_CachingHint, pixels may be retained locally.
+ If cachingHint is kDisallow_CachingHint, pixels are not added to the local cache.
+
+ @param dst destination SkPixmap: SkImageInfo, pixels, row bytes
+ @return true if pixels are scaled to fit dst
+ */
+ bool scalePixels(const SkPixmap& dst, const SkSamplingOptions&,
+ CachingHint cachingHint = kAllow_CachingHint) const;
+
+ /** Encodes SkImage pixels, returning result as SkData.
+
+ Returns nullptr if encoding fails, or if encodedImageFormat is not supported.
+
+ SkImage encoding in a format requires both building with one or more of:
+ SK_ENCODE_JPEG, SK_ENCODE_PNG, SK_ENCODE_WEBP; and platform support
+ for the encoded format.
+
+ If SK_BUILD_FOR_MAC or SK_BUILD_FOR_IOS is defined, encodedImageFormat can
+ additionally be one of: SkEncodedImageFormat::kICO, SkEncodedImageFormat::kBMP,
+ SkEncodedImageFormat::kGIF.
+
+ quality is a platform and format specific metric trading off size and encoding
+ error. When used, quality equaling 100 encodes with the least error. quality may
+ be ignored by the encoder.
+
+ @param encodedImageFormat one of: SkEncodedImageFormat::kJPEG, SkEncodedImageFormat::kPNG,
+ SkEncodedImageFormat::kWEBP
+ @param quality encoder specific metric with 100 equaling best
+ @return encoded SkImage, or nullptr
+
+ example: https://fiddle.skia.org/c/@Image_encodeToData
+ */
+ sk_sp<SkData> encodeToData(SkEncodedImageFormat encodedImageFormat, int quality) const;
+
+ /** Encodes SkImage pixels, returning result as SkData. Returns existing encoded data
+ if present; otherwise, SkImage is encoded with SkEncodedImageFormat::kPNG. Skia
+ must be built with SK_ENCODE_PNG to encode SkImage.
+
+ Returns nullptr if existing encoded data is missing or invalid, and
+ encoding fails.
+
+ @return encoded SkImage, or nullptr
+
+ example: https://fiddle.skia.org/c/@Image_encodeToData_2
+ */
+ sk_sp<SkData> encodeToData() const;
+
+ /** Returns encoded SkImage pixels as SkData, if SkImage was created from supported
+ encoded stream format. Platform support for formats vary and may require building
+ with one or more of: SK_ENCODE_JPEG, SK_ENCODE_PNG, SK_ENCODE_WEBP.
+
+ Returns nullptr if SkImage contents are not encoded.
+
+ @return encoded SkImage, or nullptr
+
+ example: https://fiddle.skia.org/c/@Image_refEncodedData
+ */
+ sk_sp<SkData> refEncodedData() const;
+
+ /** Returns subset of this image.
+
+ Returns nullptr if any of the following are true:
+ - Subset is empty
+ - Subset is not contained inside the image's bounds
+ - Pixels in the image could not be read or copied
+
+ If this image is texture-backed, the context parameter is required and must match the
+ context of the source image. If the context parameter is provided, and the image is
+ raster-backed, the subset will be converted to texture-backed.
+
+ @param subset bounds of returned SkImage
+ @param context the GrDirectContext in play, if it exists
+ @return the subsetted image, or nullptr
+
+ example: https://fiddle.skia.org/c/@Image_makeSubset
+ */
+ sk_sp<SkImage> makeSubset(const SkIRect& subset, GrDirectContext* direct = nullptr) const;
+
+ /**
+ * Returns true if the image has mipmap levels.
+ */
+ bool hasMipmaps() const;
+
+ /**
+ * Returns an image with the same "base" pixels as the this image, but with mipmap levels
+ * automatically generated and attached.
+ */
+ sk_sp<SkImage> withDefaultMipmaps() const;
+
+#if SK_SUPPORT_GPU
+ /** Returns SkImage backed by GPU texture associated with context. Returned SkImage is
+ compatible with SkSurface created with dstColorSpace. The returned SkImage respects
+ mipMapped setting; if mipMapped equals GrMipmapped::kYes, the backing texture
+ allocates mip map levels.
+
+ The mipMapped parameter is effectively treated as kNo if MIP maps are not supported by the
+ GPU.
+
+ Returns original SkImage if the image is already texture-backed, the context matches, and
+ mipMapped is compatible with the backing GPU texture. SkBudgeted is ignored in this case.
+
+ Returns nullptr if context is nullptr, or if SkImage was created with another
+ GrDirectContext.
+
+ @param GrDirectContext the GrDirectContext in play, if it exists
+ @param GrMipmapped whether created SkImage texture must allocate mip map levels
+ @param SkBudgeted whether to count a newly created texture for the returned image
+ counts against the context's budget.
+ @return created SkImage, or nullptr
+ */
+ sk_sp<SkImage> makeTextureImage(GrDirectContext*,
+ GrMipmapped = GrMipmapped::kNo,
+ SkBudgeted = SkBudgeted::kYes) const;
+#endif
+
+ /** Returns raster image or lazy image. Copies SkImage backed by GPU texture into
+ CPU memory if needed. Returns original SkImage if decoded in raster bitmap,
+ or if encoded in a stream.
+
+ Returns nullptr if backed by GPU texture and copy fails.
+
+ @return raster image, lazy image, or nullptr
+
+ example: https://fiddle.skia.org/c/@Image_makeNonTextureImage
+ */
+ sk_sp<SkImage> makeNonTextureImage() const;
+
+ /** Returns raster image. Copies SkImage backed by GPU texture into CPU memory,
+ or decodes SkImage from lazy image. Returns original SkImage if decoded in
+ raster bitmap.
+
+ Returns nullptr if copy, decode, or pixel read fails.
+
+ If cachingHint is kAllow_CachingHint, pixels may be retained locally.
+ If cachingHint is kDisallow_CachingHint, pixels are not added to the local cache.
+
+ @return raster image, or nullptr
+
+ example: https://fiddle.skia.org/c/@Image_makeRasterImage
+ */
+ sk_sp<SkImage> makeRasterImage(CachingHint cachingHint = kDisallow_CachingHint) const;
+
+ /** Creates filtered SkImage. filter processes original SkImage, potentially changing
+ color, position, and size. subset is the bounds of original SkImage processed
+ by filter. clipBounds is the expected bounds of the filtered SkImage. outSubset
+ is required storage for the actual bounds of the filtered SkImage. offset is
+ required storage for translation of returned SkImage.
+
+ Returns nullptr if SkImage could not be created or if the recording context provided doesn't
+ match the GPU context in which the image was created. If nullptr is returned, outSubset
+ and offset are undefined.
+
+ Useful for animation of SkImageFilter that varies size from frame to frame.
+ Returned SkImage is created larger than required by filter so that GPU texture
+ can be reused with different sized effects. outSubset describes the valid bounds
+ of GPU texture returned. offset translates the returned SkImage to keep subsequent
+ animation frames aligned with respect to each other.
+
+ @param context the GrRecordingContext in play - if it exists
+ @param filter how SkImage is sampled when transformed
+ @param subset bounds of SkImage processed by filter
+ @param clipBounds expected bounds of filtered SkImage
+ @param outSubset storage for returned SkImage bounds
+ @param offset storage for returned SkImage translation
+ @return filtered SkImage, or nullptr
+ */
+ sk_sp<SkImage> makeWithFilter(GrRecordingContext* context,
+ const SkImageFilter* filter, const SkIRect& subset,
+ const SkIRect& clipBounds, SkIRect* outSubset,
+ SkIPoint* offset) const;
+
+ /** Defines a callback function, taking one parameter of type GrBackendTexture with
+ no return value. Function is called when back-end texture is to be released.
+ */
+ typedef std::function<void(GrBackendTexture)> BackendTextureReleaseProc;
+
+#if SK_SUPPORT_GPU
+ /** Creates a GrBackendTexture from the provided SkImage. Returns true and
+ stores result in backendTexture and backendTextureReleaseProc if
+ texture is created; otherwise, returns false and leaves
+ backendTexture and backendTextureReleaseProc unmodified.
+
+ Call backendTextureReleaseProc after deleting backendTexture.
+ backendTextureReleaseProc cleans up auxiliary data related to returned
+ backendTexture. The caller must delete returned backendTexture after use.
+
+ If SkImage is both texture backed and singly referenced, image is returned in
+ backendTexture without conversion or making a copy. SkImage is singly referenced
+ if its was transferred solely using std::move().
+
+ If SkImage is not texture backed, returns texture with SkImage contents.
+
+ @param context GPU context
+ @param image SkImage used for texture
+ @param backendTexture storage for back-end texture
+ @param backendTextureReleaseProc storage for clean up function
+ @return true if back-end texture was created
+ */
+ static bool MakeBackendTextureFromSkImage(GrDirectContext* context,
+ sk_sp<SkImage> image,
+ GrBackendTexture* backendTexture,
+ BackendTextureReleaseProc* backendTextureReleaseProc);
+#endif
+ /** Deprecated.
+ */
+ enum LegacyBitmapMode {
+ kRO_LegacyBitmapMode, //!< returned bitmap is read-only and immutable
+ };
+
+ /** Deprecated.
+ Creates raster SkBitmap with same pixels as SkImage. If legacyBitmapMode is
+ kRO_LegacyBitmapMode, returned bitmap is read-only and immutable.
+ Returns true if SkBitmap is stored in bitmap. Returns false and resets bitmap if
+ SkBitmap write did not succeed.
+
+ @param bitmap storage for legacy SkBitmap
+ @param legacyBitmapMode bitmap is read-only and immutable
+ @return true if SkBitmap was created
+ */
+ bool asLegacyBitmap(SkBitmap* bitmap,
+ LegacyBitmapMode legacyBitmapMode = kRO_LegacyBitmapMode) const;
+
+ /** Returns true if SkImage is backed by an image-generator or other service that creates
+ and caches its pixels or texture on-demand.
+
+ @return true if SkImage is created as needed
+
+ example: https://fiddle.skia.org/c/@Image_isLazyGenerated_a
+ example: https://fiddle.skia.org/c/@Image_isLazyGenerated_b
+ */
+ bool isLazyGenerated() const;
+
+ /** Creates SkImage in target SkColorSpace.
+ Returns nullptr if SkImage could not be created.
+
+ Returns original SkImage if it is in target SkColorSpace.
+ Otherwise, converts pixels from SkImage SkColorSpace to target SkColorSpace.
+ If SkImage colorSpace() returns nullptr, SkImage SkColorSpace is assumed to be sRGB.
+
+ If this image is texture-backed, the context parameter is required and must match the
+ context of the source image.
+
+ @param target SkColorSpace describing color range of returned SkImage
+ @param direct The GrDirectContext in play, if it exists
+ @return created SkImage in target SkColorSpace
+
+ example: https://fiddle.skia.org/c/@Image_makeColorSpace
+ */
+ sk_sp<SkImage> makeColorSpace(sk_sp<SkColorSpace> target,
+ GrDirectContext* direct = nullptr) const;
+
+ /** Experimental.
+ Creates SkImage in target SkColorType and SkColorSpace.
+ Returns nullptr if SkImage could not be created.
+
+ Returns original SkImage if it is in target SkColorType and SkColorSpace.
+
+ If this image is texture-backed, the context parameter is required and must match the
+ context of the source image.
+
+ @param targetColorType SkColorType of returned SkImage
+ @param targetColorSpace SkColorSpace of returned SkImage
+ @param direct The GrDirectContext in play, if it exists
+ @return created SkImage in target SkColorType and SkColorSpace
+ */
+ sk_sp<SkImage> makeColorTypeAndColorSpace(SkColorType targetColorType,
+ sk_sp<SkColorSpace> targetColorSpace,
+ GrDirectContext* direct = nullptr) const;
+
+ /** Creates a new SkImage identical to this one, but with a different SkColorSpace.
+ This does not convert the underlying pixel data, so the resulting image will draw
+ differently.
+ */
+ sk_sp<SkImage> reinterpretColorSpace(sk_sp<SkColorSpace> newColorSpace) const;
+
+private:
+ SkImage(const SkImageInfo& info, uint32_t uniqueID);
+
+ friend class SkBitmap;
+ friend class SkImage_Base;
+ friend class SkMipmapBuilder;
+
+ SkImageInfo fInfo;
+ const uint32_t fUniqueID;
+
+ sk_sp<SkImage> withMipmaps(sk_sp<SkMipmap>) const;
+
+ using INHERITED = SkRefCnt;
+};
+
+#endif
diff --git a/src/deps/skia/include/core/SkImageEncoder.h b/src/deps/skia/include/core/SkImageEncoder.h
new file mode 100644
index 000000000..fd7bc8036
--- /dev/null
+++ b/src/deps/skia/include/core/SkImageEncoder.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkImageEncoder_DEFINED
+#define SkImageEncoder_DEFINED
+
+// TODO: update clients so we can remove this include, they should IWYU
+#include "include/core/SkBitmap.h"
+
+#include "include/core/SkData.h"
+#include "include/core/SkEncodedImageFormat.h"
+#include "include/core/SkPixmap.h"
+#include "include/core/SkStream.h"
+
+class SkBitmap;
+
+/**
+ * Encode SkPixmap in the given binary image format.
+ *
+ * @param dst results are written to this stream.
+ * @param src source pixels.
+ * @param format image format, not all formats are supported.
+ * @param quality range from 0-100, this is supported by jpeg and webp.
+ * higher values correspond to improved visual quality, but less compression.
+ *
+ * @return false iff input is bad or format is unsupported.
+ *
+ * Will always return false if Skia is compiled without image
+ * encoders.
+ *
+ * For SkEncodedImageFormat::kWEBP, if quality is 100, it will use lossless compression. Otherwise
+ * it will use lossy.
+ *
+ * For examples of encoding an image to a file or to a block of memory,
+ * see tools/ToolUtils.h.
+ */
+SK_API bool SkEncodeImage(SkWStream* dst, const SkPixmap& src,
+ SkEncodedImageFormat format, int quality);
+
+/**
+ * The following helper function wraps SkEncodeImage().
+ */
+SK_API bool SkEncodeImage(SkWStream* dst, const SkBitmap& src, SkEncodedImageFormat f, int q);
+
+/**
+ * Encode SkPixmap in the given binary image format.
+ *
+ * @param src source pixels.
+ * @param format image format, not all formats are supported.
+ * @param quality range from 0-100, this is supported by jpeg and webp.
+ * higher values correspond to improved visual quality, but less compression.
+ *
+ * @return encoded data or nullptr if input is bad or format is unsupported.
+ *
+ * Will always return nullptr if Skia is compiled without image
+ * encoders.
+ *
+ * For SkEncodedImageFormat::kWEBP, if quality is 100, it will use lossless compression. Otherwise
+ * it will use lossy.
+ */
+SK_API sk_sp<SkData> SkEncodePixmap(const SkPixmap& src, SkEncodedImageFormat format, int quality);
+
+/**
+ * Helper that extracts the pixmap from the bitmap, and then calls SkEncodePixmap()
+ */
+SK_API sk_sp<SkData> SkEncodeBitmap(const SkBitmap& src, SkEncodedImageFormat format, int quality);
+
+#endif // SkImageEncoder_DEFINED
diff --git a/src/deps/skia/include/core/SkImageFilter.h b/src/deps/skia/include/core/SkImageFilter.h
new file mode 100644
index 000000000..e2240916d
--- /dev/null
+++ b/src/deps/skia/include/core/SkImageFilter.h
@@ -0,0 +1,114 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkImageFilter_DEFINED
+#define SkImageFilter_DEFINED
+
+#include "include/core/SkFlattenable.h"
+#include "include/core/SkMatrix.h"
+#include "include/core/SkRect.h"
+
+class SkColorFilter;
+
+/**
+ * Base class for image filters. If one is installed in the paint, then all drawing occurs as
+ * usual, but it is as if the drawing happened into an offscreen (before the xfermode is applied).
+ * This offscreen bitmap will then be handed to the imagefilter, who in turn creates a new bitmap
+ * which is what will finally be drawn to the device (using the original xfermode).
+ *
+ * The local space of image filters matches the local space of the drawn geometry. For instance if
+ * there is rotation on the canvas, the blur will be computed along those rotated axes and not in
+ * the device space. In order to achieve this result, the actual drawing of the geometry may happen
+ * in an unrotated coordinate system so that the filtered image can be computed more easily, and
+ * then it will be post transformed to match what would have been produced if the geometry were
+ * drawn with the total canvas matrix to begin with.
+ */
+class SK_API SkImageFilter : public SkFlattenable {
+public:
+ enum MapDirection {
+ kForward_MapDirection,
+ kReverse_MapDirection,
+ };
+ /**
+ * Map a device-space rect recursively forward or backward through the filter DAG.
+ * kForward_MapDirection is used to determine which pixels of the destination canvas a source
+ * image rect would touch after filtering. kReverse_MapDirection is used to determine which rect
+ * of the source image would be required to fill the given rect (typically, clip bounds). Used
+ * for clipping and temp-buffer allocations, so the result need not be exact, but should never
+ * be smaller than the real answer. The default implementation recursively unions all input
+ * bounds, or returns the source rect if no inputs.
+ *
+ * In kReverse mode, 'inputRect' is the device-space bounds of the input pixels. In kForward
+ * mode it should always be null. If 'inputRect' is null in kReverse mode the resulting answer
+ * may be incorrect.
+ */
+ SkIRect filterBounds(const SkIRect& src, const SkMatrix& ctm,
+ MapDirection, const SkIRect* inputRect = nullptr) const;
+
+ /**
+ * Returns whether this image filter is a color filter and puts the color filter into the
+ * "filterPtr" parameter if it can. Does nothing otherwise.
+ * If this returns false, then the filterPtr is unchanged.
+ * If this returns true, then if filterPtr is not null, it must be set to a ref'd colorfitler
+ * (i.e. it may not be set to NULL).
+ */
+ bool isColorFilterNode(SkColorFilter** filterPtr) const;
+
+ // DEPRECATED : use isColorFilterNode() instead
+ bool asColorFilter(SkColorFilter** filterPtr) const {
+ return this->isColorFilterNode(filterPtr);
+ }
+
+ /**
+ * Returns true (and optionally returns a ref'd filter) if this imagefilter can be completely
+ * replaced by the returned colorfilter. i.e. the two effects will affect drawing in the same
+ * way.
+ */
+ bool asAColorFilter(SkColorFilter** filterPtr) const;
+
+ /**
+ * Returns the number of inputs this filter will accept (some inputs can be NULL).
+ */
+ int countInputs() const;
+
+ /**
+ * Returns the input filter at a given index, or NULL if no input is connected. The indices
+ * used are filter-specific.
+ */
+ const SkImageFilter* getInput(int i) const;
+
+ // Default impl returns union of all input bounds.
+ virtual SkRect computeFastBounds(const SkRect& bounds) const;
+
+ // Can this filter DAG compute the resulting bounds of an object-space rectangle?
+ bool canComputeFastBounds() const;
+
+ /**
+ * If this filter can be represented by another filter + a localMatrix, return that filter,
+ * else return null.
+ */
+ sk_sp<SkImageFilter> makeWithLocalMatrix(const SkMatrix& matrix) const;
+
+ static sk_sp<SkImageFilter> Deserialize(const void* data, size_t size,
+ const SkDeserialProcs* procs = nullptr) {
+ return sk_sp<SkImageFilter>(static_cast<SkImageFilter*>(
+ SkFlattenable::Deserialize(kSkImageFilter_Type, data, size, procs).release()));
+ }
+
+protected:
+
+ sk_sp<SkImageFilter> refMe() const {
+ return sk_ref_sp(const_cast<SkImageFilter*>(this));
+ }
+
+private:
+ friend class SkImageFilter_Base;
+
+ using INHERITED = SkFlattenable;
+};
+
+#endif
diff --git a/src/deps/skia/include/core/SkImageGenerator.h b/src/deps/skia/include/core/SkImageGenerator.h
new file mode 100644
index 000000000..abc781754
--- /dev/null
+++ b/src/deps/skia/include/core/SkImageGenerator.h
@@ -0,0 +1,215 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkImageGenerator_DEFINED
+#define SkImageGenerator_DEFINED
+
+#include "include/core/SkBitmap.h"
+#include "include/core/SkColor.h"
+#include "include/core/SkImage.h"
+#include "include/core/SkImageInfo.h"
+#include "include/core/SkYUVAPixmaps.h"
+#include "include/private/SkTOptional.h"
+
+class GrRecordingContext;
+class GrSurfaceProxyView;
+class GrSamplerState;
+class SkBitmap;
+class SkData;
+class SkMatrix;
+class SkPaint;
+class SkPicture;
+
+enum class GrImageTexGenPolicy : int;
+
+class SK_API SkImageGenerator {
+public:
+ /**
+ * The PixelRef which takes ownership of this SkImageGenerator
+ * will call the image generator's destructor.
+ */
+ virtual ~SkImageGenerator() { }
+
+ uint32_t uniqueID() const { return fUniqueID; }
+
+ /**
+ * Return a ref to the encoded (i.e. compressed) representation
+ * of this data.
+ *
+ * If non-NULL is returned, the caller is responsible for calling
+ * unref() on the data when it is finished.
+ */
+ sk_sp<SkData> refEncodedData() {
+ return this->onRefEncodedData();
+ }
+
+ /**
+ * Return the ImageInfo associated with this generator.
+ */
+ const SkImageInfo& getInfo() const { return fInfo; }
+
+ /**
+ * Can this generator be used to produce images that will be drawable to the specified context
+ * (or to CPU, if context is nullptr)?
+ */
+ bool isValid(GrRecordingContext* context) const {
+ return this->onIsValid(context);
+ }
+
+ /**
+ * Decode into the given pixels, a block of memory of size at
+ * least (info.fHeight - 1) * rowBytes + (info.fWidth *
+ * bytesPerPixel)
+ *
+ * Repeated calls to this function should give the same results,
+ * allowing the PixelRef to be immutable.
+ *
+ * @param info A description of the format
+ * expected by the caller. This can simply be identical
+ * to the info returned by getInfo().
+ *
+ * This contract also allows the caller to specify
+ * different output-configs, which the implementation can
+ * decide to support or not.
+ *
+ * A size that does not match getInfo() implies a request
+ * to scale. If the generator cannot perform this scale,
+ * it will return false.
+ *
+ * @return true on success.
+ */
+ bool getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes);
+
+ bool getPixels(const SkPixmap& pm) {
+ return this->getPixels(pm.info(), pm.writable_addr(), pm.rowBytes());
+ }
+
+ /**
+ * If decoding to YUV is supported, this returns true. Otherwise, this
+ * returns false and the caller will ignore output parameter yuvaPixmapInfo.
+ *
+ * @param supportedDataTypes Indicates the data type/planar config combinations that are
+ * supported by the caller. If the generator supports decoding to
+ * YUV(A), but not as a type in supportedDataTypes, this method
+ * returns false.
+ * @param yuvaPixmapInfo Output parameter that specifies the planar configuration, subsampling,
+ * orientation, chroma siting, plane color types, and row bytes.
+ */
+ bool queryYUVAInfo(const SkYUVAPixmapInfo::SupportedDataTypes& supportedDataTypes,
+ SkYUVAPixmapInfo* yuvaPixmapInfo) const;
+
+ /**
+ * Returns true on success and false on failure.
+ * This always attempts to perform a full decode. To get the planar
+ * configuration without decoding use queryYUVAInfo().
+ *
+ * @param yuvaPixmaps Contains preallocated pixmaps configured according to a successful call
+ * to queryYUVAInfo().
+ */
+ bool getYUVAPlanes(const SkYUVAPixmaps& yuvaPixmaps);
+
+#if SK_SUPPORT_GPU
+ /**
+ * If the generator can natively/efficiently return its pixels as a GPU image (backed by a
+ * texture) this will return that image. If not, this will return NULL.
+ *
+ * This routine also supports retrieving only a subset of the pixels. That subset is specified
+ * by the following rectangle:
+ *
+ * subset = SkIRect::MakeXYWH(origin.x(), origin.y(), info.width(), info.height())
+ *
+ * If subset is not contained inside the generator's bounds, this returns false.
+ *
+ * whole = SkIRect::MakeWH(getInfo().width(), getInfo().height())
+ * if (!whole.contains(subset)) {
+ * return false;
+ * }
+ *
+ * Regarding the GrRecordingContext parameter:
+ *
+ * It must be non-NULL. The generator should only succeed if:
+ * - its internal context is the same
+ * - it can somehow convert its texture into one that is valid for the provided context.
+ *
+ * If the willNeedMipMaps flag is true, the generator should try to create a TextureProxy that
+ * at least has the mip levels allocated and the base layer filled in. If this is not possible,
+ * the generator is allowed to return a non mipped proxy, but this will have some additional
+ * overhead in later allocating mips and copying of the base layer.
+ *
+ * GrImageTexGenPolicy determines whether or not a new texture must be created (and its budget
+ * status) or whether this may (but is not required to) return a pre-existing texture that is
+ * retained by the generator (kDraw).
+ */
+ GrSurfaceProxyView generateTexture(GrRecordingContext*, const SkImageInfo& info,
+ const SkIPoint& origin, GrMipmapped, GrImageTexGenPolicy);
+
+#endif
+
+ /**
+ * If the default image decoder system can interpret the specified (encoded) data, then
+ * this returns a new ImageGenerator for it. Otherwise this returns NULL. Either way
+ * the caller is still responsible for managing their ownership of the data.
+ * By default, images will be converted to premultiplied pixels. The alpha type can be
+ * overridden by specifying kPremul_SkAlphaType or kUnpremul_SkAlphaType. Specifying
+ * kOpaque_SkAlphaType is not supported, and will return NULL.
+ */
+ static std::unique_ptr<SkImageGenerator> MakeFromEncoded(
+ sk_sp<SkData>, skstd::optional<SkAlphaType> = skstd::nullopt);
+
+ /** Return a new image generator backed by the specified picture. If the size is empty or
+ * the picture is NULL, this returns NULL.
+ * The optional matrix and paint arguments are passed to drawPicture() at rasterization
+ * time.
+ */
+ static std::unique_ptr<SkImageGenerator> MakeFromPicture(const SkISize&, sk_sp<SkPicture>,
+ const SkMatrix*, const SkPaint*,
+ SkImage::BitDepth,
+ sk_sp<SkColorSpace>);
+
+protected:
+ static constexpr int kNeedNewImageUniqueID = 0;
+
+ SkImageGenerator(const SkImageInfo& info, uint32_t uniqueId = kNeedNewImageUniqueID);
+
+ virtual sk_sp<SkData> onRefEncodedData() { return nullptr; }
+ struct Options {};
+ virtual bool onGetPixels(const SkImageInfo&, void*, size_t, const Options&) { return false; }
+ virtual bool onIsValid(GrRecordingContext*) const { return true; }
+ virtual bool onQueryYUVAInfo(const SkYUVAPixmapInfo::SupportedDataTypes&,
+ SkYUVAPixmapInfo*) const { return false; }
+ virtual bool onGetYUVAPlanes(const SkYUVAPixmaps&) { return false; }
+#if SK_SUPPORT_GPU
+ // returns nullptr
+ virtual GrSurfaceProxyView onGenerateTexture(GrRecordingContext*, const SkImageInfo&,
+ const SkIPoint&, GrMipmapped, GrImageTexGenPolicy);
+
+ // Most internal SkImageGenerators produce textures and views that use kTopLeft_GrSurfaceOrigin.
+ // If the generator may produce textures with different origins (e.g.
+ // GrAHardwareBufferImageGenerator) it should override this function to return the correct
+ // origin.
+ virtual GrSurfaceOrigin origin() const { return kTopLeft_GrSurfaceOrigin; }
+#endif
+
+private:
+ const SkImageInfo fInfo;
+ const uint32_t fUniqueID;
+
+ friend class SkImage_Lazy;
+
+ // This is our default impl, which may be different on different platforms.
+ // It is called from NewFromEncoded() after it has checked for any runtime factory.
+ // The SkData will never be NULL, as that will have been checked by NewFromEncoded.
+ static std::unique_ptr<SkImageGenerator> MakeFromEncodedImpl(sk_sp<SkData>,
+ skstd::optional<SkAlphaType>);
+
+ SkImageGenerator(SkImageGenerator&&) = delete;
+ SkImageGenerator(const SkImageGenerator&) = delete;
+ SkImageGenerator& operator=(SkImageGenerator&&) = delete;
+ SkImageGenerator& operator=(const SkImageGenerator&) = delete;
+};
+
+#endif // SkImageGenerator_DEFINED
diff --git a/src/deps/skia/include/core/SkImageInfo.h b/src/deps/skia/include/core/SkImageInfo.h
new file mode 100644
index 000000000..99b65e875
--- /dev/null
+++ b/src/deps/skia/include/core/SkImageInfo.h
@@ -0,0 +1,721 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkImageInfo_DEFINED
+#define SkImageInfo_DEFINED
+
+#include "include/core/SkColorSpace.h"
+#include "include/core/SkMath.h"
+#include "include/core/SkRect.h"
+#include "include/core/SkSize.h"
+
+#include "include/private/SkTFitsIn.h"
+#include "include/private/SkTo.h"
+
+class SkReadBuffer;
+class SkWriteBuffer;
+
+/** \enum SkImageInfo::SkAlphaType
+ Describes how to interpret the alpha component of a pixel. A pixel may
+ be opaque, or alpha, describing multiple levels of transparency.
+
+ In simple blending, alpha weights the draw color and the destination
+ color to create a new color. If alpha describes a weight from zero to one:
+
+ new color = draw color * alpha + destination color * (1 - alpha)
+
+ In practice alpha is encoded in two or more bits, where 1.0 equals all bits set.
+
+ RGB may have alpha included in each component value; the stored
+ value is the original RGB multiplied by alpha. Premultiplied color
+ components improve performance.
+*/
+enum SkAlphaType : int {
+ kUnknown_SkAlphaType, //!< uninitialized
+ kOpaque_SkAlphaType, //!< pixel is opaque
+ kPremul_SkAlphaType, //!< pixel components are premultiplied by alpha
+ kUnpremul_SkAlphaType, //!< pixel components are independent of alpha
+ kLastEnum_SkAlphaType = kUnpremul_SkAlphaType, //!< last valid value
+};
+
+/** Returns true if SkAlphaType equals kOpaque_SkAlphaType.
+
+ kOpaque_SkAlphaType is a hint that the SkColorType is opaque, or that all
+ alpha values are set to their 1.0 equivalent. If SkAlphaType is
+ kOpaque_SkAlphaType, and SkColorType is not opaque, then the result of
+ drawing any pixel with a alpha value less than 1.0 is undefined.
+*/
+static inline bool SkAlphaTypeIsOpaque(SkAlphaType at) {
+ return kOpaque_SkAlphaType == at;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+/** \enum SkImageInfo::SkColorType
+ Describes how pixel bits encode color. A pixel may be an alpha mask, a grayscale, RGB, or ARGB.
+
+ kN32_SkColorType selects the native 32-bit ARGB format for the current configuration. This can
+ lead to inconsistent results across platforms, so use with caution.
+*/
+enum SkColorType : int {
+ kUnknown_SkColorType, //!< uninitialized
+ kAlpha_8_SkColorType, //!< pixel with alpha in 8-bit byte
+ kRGB_565_SkColorType, //!< pixel with 5 bits red, 6 bits green, 5 bits blue, in 16-bit word
+ kARGB_4444_SkColorType, //!< pixel with 4 bits for alpha, red, green, blue; in 16-bit word
+ kRGBA_8888_SkColorType, //!< pixel with 8 bits for red, green, blue, alpha; in 32-bit word
+ kRGB_888x_SkColorType, //!< pixel with 8 bits each for red, green, blue; in 32-bit word
+ kBGRA_8888_SkColorType, //!< pixel with 8 bits for blue, green, red, alpha; in 32-bit word
+ kRGBA_1010102_SkColorType, //!< 10 bits for red, green, blue; 2 bits for alpha; in 32-bit word
+ kBGRA_1010102_SkColorType, //!< 10 bits for blue, green, red; 2 bits for alpha; in 32-bit word
+ kRGB_101010x_SkColorType, //!< pixel with 10 bits each for red, green, blue; in 32-bit word
+ kBGR_101010x_SkColorType, //!< pixel with 10 bits each for blue, green, red; in 32-bit word
+ kGray_8_SkColorType, //!< pixel with grayscale level in 8-bit byte
+ kRGBA_F16Norm_SkColorType, //!< pixel with half floats in [0,1] for red, green, blue, alpha;
+ // in 64-bit word
+ kRGBA_F16_SkColorType, //!< pixel with half floats for red, green, blue, alpha;
+ // in 64-bit word
+ kRGBA_F32_SkColorType, //!< pixel using C float for red, green, blue, alpha; in 128-bit word
+
+ // The following 6 colortypes are just for reading from - not for rendering to
+ kR8G8_unorm_SkColorType, //!< pixel with a uint8_t for red and green
+
+ kA16_float_SkColorType, //!< pixel with a half float for alpha
+ kR16G16_float_SkColorType, //!< pixel with a half float for red and green
+
+ kA16_unorm_SkColorType, //!< pixel with a little endian uint16_t for alpha
+ kR16G16_unorm_SkColorType, //!< pixel with a little endian uint16_t for red and green
+ kR16G16B16A16_unorm_SkColorType, //!< pixel with a little endian uint16_t for red, green, blue
+ // and alpha
+
+ kSRGBA_8888_SkColorType,
+
+ kLastEnum_SkColorType = kSRGBA_8888_SkColorType, //!< last valid value
+
+#if SK_PMCOLOR_BYTE_ORDER(B,G,R,A)
+ kN32_SkColorType = kBGRA_8888_SkColorType,//!< native 32-bit BGRA encoding
+
+#elif SK_PMCOLOR_BYTE_ORDER(R,G,B,A)
+ kN32_SkColorType = kRGBA_8888_SkColorType,//!< native 32-bit RGBA encoding
+
+#else
+ #error "SK_*32_SHIFT values must correspond to BGRA or RGBA byte order"
+#endif
+};
+
+/** Returns the number of bytes required to store a pixel, including unused padding.
+ Returns zero if ct is kUnknown_SkColorType or invalid.
+
+ @return bytes per pixel
+*/
+SK_API int SkColorTypeBytesPerPixel(SkColorType ct);
+
+/** Returns true if SkColorType always decodes alpha to 1.0, making the pixel
+ fully opaque. If true, SkColorType does not reserve bits to encode alpha.
+
+ @return true if alpha is always set to 1.0
+*/
+SK_API bool SkColorTypeIsAlwaysOpaque(SkColorType ct);
+
+/** Returns true if canonical can be set to a valid SkAlphaType for colorType. If
+ there is more than one valid canonical SkAlphaType, set to alphaType, if valid.
+ If true is returned and canonical is not nullptr, store valid SkAlphaType.
+
+ Returns false only if alphaType is kUnknown_SkAlphaType, color type is not
+ kUnknown_SkColorType, and SkColorType is not always opaque. If false is returned,
+ canonical is ignored.
+
+ @param canonical storage for SkAlphaType
+ @return true if valid SkAlphaType can be associated with colorType
+*/
+SK_API bool SkColorTypeValidateAlphaType(SkColorType colorType, SkAlphaType alphaType,
+ SkAlphaType* canonical = nullptr);
+
+/** \enum SkImageInfo::SkYUVColorSpace
+ Describes color range of YUV pixels. The color mapping from YUV to RGB varies
+ depending on the source. YUV pixels may be generated by JPEG images, standard
+ video streams, or high definition video streams. Each has its own mapping from
+ YUV to RGB.
+
+ JPEG YUV values encode the full range of 0 to 255 for all three components.
+ Video YUV values often range from 16 to 235 for Y and from 16 to 240 for U and V (limited).
+ Details of encoding and conversion to RGB are described in YCbCr color space.
+
+ The identity colorspace exists to provide a utility mapping from Y to R, U to G and V to B.
+ It can be used to visualize the YUV planes or to explicitly post process the YUV channels.
+*/
+enum SkYUVColorSpace : int {
+ kJPEG_Full_SkYUVColorSpace, //!< describes full range
+ kRec601_Limited_SkYUVColorSpace, //!< describes SDTV range
+ kRec709_Full_SkYUVColorSpace, //!< describes HDTV range
+ kRec709_Limited_SkYUVColorSpace,
+ kBT2020_8bit_Full_SkYUVColorSpace, //!< describes UHDTV range, non-constant-luminance
+ kBT2020_8bit_Limited_SkYUVColorSpace,
+ kBT2020_10bit_Full_SkYUVColorSpace,
+ kBT2020_10bit_Limited_SkYUVColorSpace,
+ kBT2020_12bit_Full_SkYUVColorSpace,
+ kBT2020_12bit_Limited_SkYUVColorSpace,
+ kIdentity_SkYUVColorSpace, //!< maps Y->R, U->G, V->B
+
+ kLastEnum_SkYUVColorSpace = kIdentity_SkYUVColorSpace, //!< last valid value
+
+ // Legacy (deprecated) names:
+ kJPEG_SkYUVColorSpace = kJPEG_Full_SkYUVColorSpace,
+ kRec601_SkYUVColorSpace = kRec601_Limited_SkYUVColorSpace,
+ kRec709_SkYUVColorSpace = kRec709_Limited_SkYUVColorSpace,
+ kBT2020_SkYUVColorSpace = kBT2020_8bit_Limited_SkYUVColorSpace,
+};
+
+/** \struct SkColorInfo
+ Describes pixel and encoding. SkImageInfo can be created from SkColorInfo by
+ providing dimensions.
+
+ It encodes how pixel bits describe alpha, transparency; color components red, blue,
+ and green; and SkColorSpace, the range and linearity of colors.
+*/
+class SK_API SkColorInfo {
+public:
+ /** Creates an SkColorInfo with kUnknown_SkColorType, kUnknown_SkAlphaType,
+ and no SkColorSpace.
+
+ @return empty SkImageInfo
+ */
+ SkColorInfo() = default;
+
+ /** Creates SkColorInfo from SkColorType ct, SkAlphaType at, and optionally SkColorSpace cs.
+
+ If SkColorSpace cs is nullptr and SkColorInfo is part of drawing source: SkColorSpace
+ defaults to sRGB, mapping into SkSurface SkColorSpace.
+
+ Parameters are not validated to see if their values are legal, or that the
+ combination is supported.
+ @return created SkColorInfo
+ */
+ SkColorInfo(SkColorType ct, SkAlphaType at, sk_sp<SkColorSpace> cs)
+ : fColorSpace(std::move(cs)), fColorType(ct), fAlphaType(at) {}
+
+ SkColorInfo(const SkColorInfo&) = default;
+ SkColorInfo(SkColorInfo&&) = default;
+
+ SkColorInfo& operator=(const SkColorInfo&) = default;
+ SkColorInfo& operator=(SkColorInfo&&) = default;
+
+ SkColorSpace* colorSpace() const { return fColorSpace.get(); }
+ sk_sp<SkColorSpace> refColorSpace() const { return fColorSpace; }
+ SkColorType colorType() const { return fColorType; }
+ SkAlphaType alphaType() const { return fAlphaType; }
+
+ bool isOpaque() const {
+ return SkAlphaTypeIsOpaque(fAlphaType)
+ || SkColorTypeIsAlwaysOpaque(fColorType);
+ }
+
+ bool gammaCloseToSRGB() const { return fColorSpace && fColorSpace->gammaCloseToSRGB(); }
+
+ /** Does other represent the same color type, alpha type, and color space? */
+ bool operator==(const SkColorInfo& other) const {
+ return fColorType == other.fColorType && fAlphaType == other.fAlphaType &&
+ SkColorSpace::Equals(fColorSpace.get(), other.fColorSpace.get());
+ }
+
+ /** Does other represent a different color type, alpha type, or color space? */
+ bool operator!=(const SkColorInfo& other) const { return !(*this == other); }
+
+ /** Creates SkColorInfo with same SkColorType, SkColorSpace, with SkAlphaType set
+ to newAlphaType.
+
+ Created SkColorInfo contains newAlphaType even if it is incompatible with
+ SkColorType, in which case SkAlphaType in SkColorInfo is ignored.
+ */
+ SkColorInfo makeAlphaType(SkAlphaType newAlphaType) const {
+ return SkColorInfo(this->colorType(), newAlphaType, this->refColorSpace());
+ }
+
+ /** Creates new SkColorInfo with same SkAlphaType, SkColorSpace, with SkColorType
+ set to newColorType.
+ */
+ SkColorInfo makeColorType(SkColorType newColorType) const {
+ return SkColorInfo(newColorType, this->alphaType(), this->refColorSpace());
+ }
+
+ /** Creates SkColorInfo with same SkAlphaType, SkColorType, with SkColorSpace
+ set to cs. cs may be nullptr.
+ */
+ SkColorInfo makeColorSpace(sk_sp<SkColorSpace> cs) const {
+ return SkColorInfo(this->colorType(), this->alphaType(), std::move(cs));
+ }
+
+ /** Returns number of bytes per pixel required by SkColorType.
+ Returns zero if colorType() is kUnknown_SkColorType.
+
+ @return bytes in pixel
+
+ example: https://fiddle.skia.org/c/@ImageInfo_bytesPerPixel
+ */
+ int bytesPerPixel() const;
+
+ /** Returns bit shift converting row bytes to row pixels.
+ Returns zero for kUnknown_SkColorType.
+
+ @return one of: 0, 1, 2, 3, 4; left shift to convert pixels to bytes
+
+ example: https://fiddle.skia.org/c/@ImageInfo_shiftPerPixel
+ */
+ int shiftPerPixel() const;
+
+private:
+ sk_sp<SkColorSpace> fColorSpace;
+ SkColorType fColorType = kUnknown_SkColorType;
+ SkAlphaType fAlphaType = kUnknown_SkAlphaType;
+};
+
+/** \struct SkImageInfo
+ Describes pixel dimensions and encoding. SkBitmap, SkImage, PixMap, and SkSurface
+ can be created from SkImageInfo. SkImageInfo can be retrieved from SkBitmap and
+ SkPixmap, but not from SkImage and SkSurface. For example, SkImage and SkSurface
+ implementations may defer pixel depth, so may not completely specify SkImageInfo.
+
+ SkImageInfo contains dimensions, the pixel integral width and height. It encodes
+ how pixel bits describe alpha, transparency; color components red, blue,
+ and green; and SkColorSpace, the range and linearity of colors.
+*/
+struct SK_API SkImageInfo {
+public:
+
+ /** Creates an empty SkImageInfo with kUnknown_SkColorType, kUnknown_SkAlphaType,
+ a width and height of zero, and no SkColorSpace.
+
+ @return empty SkImageInfo
+ */
+ SkImageInfo() = default;
+
+ /** Creates SkImageInfo from integral dimensions width and height, SkColorType ct,
+ SkAlphaType at, and optionally SkColorSpace cs.
+
+ If SkColorSpace cs is nullptr and SkImageInfo is part of drawing source: SkColorSpace
+ defaults to sRGB, mapping into SkSurface SkColorSpace.
+
+ Parameters are not validated to see if their values are legal, or that the
+ combination is supported.
+
+ @param width pixel column count; must be zero or greater
+ @param height pixel row count; must be zero or greater
+ @param cs range of colors; may be nullptr
+ @return created SkImageInfo
+ */
+ static SkImageInfo Make(int width, int height, SkColorType ct, SkAlphaType at,
+ sk_sp<SkColorSpace> cs = nullptr) {
+ return SkImageInfo({width, height}, {ct, at, std::move(cs)});
+ }
+ static SkImageInfo Make(SkISize dimensions, SkColorType ct, SkAlphaType at,
+ sk_sp<SkColorSpace> cs = nullptr) {
+ return SkImageInfo(dimensions, {ct, at, std::move(cs)});
+ }
+
+ /** Creates SkImageInfo from integral dimensions and SkColorInfo colorInfo,
+
+ Parameters are not validated to see if their values are legal, or that the
+ combination is supported.
+
+ @param dimensions pixel column and row count; must be zeros or greater
+ @param SkColorInfo the pixel encoding consisting of SkColorType, SkAlphaType, and
+ SkColorSpace (which may be nullptr)
+ @return created SkImageInfo
+ */
+ static SkImageInfo Make(SkISize dimensions, const SkColorInfo& colorInfo) {
+ return SkImageInfo(dimensions, colorInfo);
+ }
+ static SkImageInfo Make(SkISize dimensions, SkColorInfo&& colorInfo) {
+ return SkImageInfo(dimensions, std::move(colorInfo));
+ }
+
+ /** Creates SkImageInfo from integral dimensions width and height, kN32_SkColorType,
+ SkAlphaType at, and optionally SkColorSpace cs. kN32_SkColorType will equal either
+ kBGRA_8888_SkColorType or kRGBA_8888_SkColorType, whichever is optimal.
+
+ If SkColorSpace cs is nullptr and SkImageInfo is part of drawing source: SkColorSpace
+ defaults to sRGB, mapping into SkSurface SkColorSpace.
+
+ Parameters are not validated to see if their values are legal, or that the
+ combination is supported.
+
+ @param width pixel column count; must be zero or greater
+ @param height pixel row count; must be zero or greater
+ @param cs range of colors; may be nullptr
+ @return created SkImageInfo
+ */
+ static SkImageInfo MakeN32(int width, int height, SkAlphaType at,
+ sk_sp<SkColorSpace> cs = nullptr) {
+ return Make({width, height}, kN32_SkColorType, at, std::move(cs));
+ }
+
+ /** Creates SkImageInfo from integral dimensions width and height, kN32_SkColorType,
+ SkAlphaType at, with sRGB SkColorSpace.
+
+ Parameters are not validated to see if their values are legal, or that the
+ combination is supported.
+
+ @param width pixel column count; must be zero or greater
+ @param height pixel row count; must be zero or greater
+ @return created SkImageInfo
+
+ example: https://fiddle.skia.org/c/@ImageInfo_MakeS32
+ */
+ static SkImageInfo MakeS32(int width, int height, SkAlphaType at);
+
+ /** Creates SkImageInfo from integral dimensions width and height, kN32_SkColorType,
+ kPremul_SkAlphaType, with optional SkColorSpace.
+
+ If SkColorSpace cs is nullptr and SkImageInfo is part of drawing source: SkColorSpace
+ defaults to sRGB, mapping into SkSurface SkColorSpace.
+
+ Parameters are not validated to see if their values are legal, or that the
+ combination is supported.
+
+ @param width pixel column count; must be zero or greater
+ @param height pixel row count; must be zero or greater
+ @param cs range of colors; may be nullptr
+ @return created SkImageInfo
+ */
+ static SkImageInfo MakeN32Premul(int width, int height, sk_sp<SkColorSpace> cs = nullptr) {
+ return Make({width, height}, kN32_SkColorType, kPremul_SkAlphaType, std::move(cs));
+ }
+
+ /** Creates SkImageInfo from integral dimensions width and height, kN32_SkColorType,
+ kPremul_SkAlphaType, with SkColorSpace set to nullptr.
+
+ If SkImageInfo is part of drawing source: SkColorSpace defaults to sRGB, mapping
+ into SkSurface SkColorSpace.
+
+ Parameters are not validated to see if their values are legal, or that the
+ combination is supported.
+
+ @param dimensions width and height, each must be zero or greater
+ @param cs range of colors; may be nullptr
+ @return created SkImageInfo
+ */
+ static SkImageInfo MakeN32Premul(SkISize dimensions, sk_sp<SkColorSpace> cs = nullptr) {
+ return Make(dimensions, kN32_SkColorType, kPremul_SkAlphaType, std::move(cs));
+ }
+
+ /** Creates SkImageInfo from integral dimensions width and height, kAlpha_8_SkColorType,
+ kPremul_SkAlphaType, with SkColorSpace set to nullptr.
+
+ @param width pixel column count; must be zero or greater
+ @param height pixel row count; must be zero or greater
+ @return created SkImageInfo
+ */
+ static SkImageInfo MakeA8(int width, int height) {
+ return Make({width, height}, kAlpha_8_SkColorType, kPremul_SkAlphaType, nullptr);
+ }
+ /** Creates SkImageInfo from integral dimensions, kAlpha_8_SkColorType,
+ kPremul_SkAlphaType, with SkColorSpace set to nullptr.
+
+ @param dimensions pixel row and column count; must be zero or greater
+ @return created SkImageInfo
+ */
+ static SkImageInfo MakeA8(SkISize dimensions) {
+ return Make(dimensions, kAlpha_8_SkColorType, kPremul_SkAlphaType, nullptr);
+ }
+
+ /** Creates SkImageInfo from integral dimensions width and height, kUnknown_SkColorType,
+ kUnknown_SkAlphaType, with SkColorSpace set to nullptr.
+
+ Returned SkImageInfo as part of source does not draw, and as part of destination
+ can not be drawn to.
+
+ @param width pixel column count; must be zero or greater
+ @param height pixel row count; must be zero or greater
+ @return created SkImageInfo
+ */
+ static SkImageInfo MakeUnknown(int width, int height) {
+ return Make({width, height}, kUnknown_SkColorType, kUnknown_SkAlphaType, nullptr);
+ }
+
+ /** Creates SkImageInfo from integral dimensions width and height set to zero,
+ kUnknown_SkColorType, kUnknown_SkAlphaType, with SkColorSpace set to nullptr.
+
+ Returned SkImageInfo as part of source does not draw, and as part of destination
+ can not be drawn to.
+
+ @return created SkImageInfo
+ */
+ static SkImageInfo MakeUnknown() {
+ return MakeUnknown(0, 0);
+ }
+
+ /** Returns pixel count in each row.
+
+ @return pixel width
+ */
+ int width() const { return fDimensions.width(); }
+
+ /** Returns pixel row count.
+
+ @return pixel height
+ */
+ int height() const { return fDimensions.height(); }
+
+ SkColorType colorType() const { return fColorInfo.colorType(); }
+
+ SkAlphaType alphaType() const { return fColorInfo.alphaType(); }
+
+ /** Returns SkColorSpace, the range of colors. The reference count of
+ SkColorSpace is unchanged. The returned SkColorSpace is immutable.
+
+ @return SkColorSpace, or nullptr
+ */
+ SkColorSpace* colorSpace() const { return fColorInfo.colorSpace(); }
+
+ /** Returns smart pointer to SkColorSpace, the range of colors. The smart pointer
+ tracks the number of objects sharing this SkColorSpace reference so the memory
+ is released when the owners destruct.
+
+ The returned SkColorSpace is immutable.
+
+ @return SkColorSpace wrapped in a smart pointer
+ */
+ sk_sp<SkColorSpace> refColorSpace() const { return fColorInfo.refColorSpace(); }
+
+ /** Returns if SkImageInfo describes an empty area of pixels by checking if either
+ width or height is zero or smaller.
+
+ @return true if either dimension is zero or smaller
+ */
+ bool isEmpty() const { return fDimensions.isEmpty(); }
+
+ /** Returns the dimensionless SkColorInfo that represents the same color type,
+ alpha type, and color space as this SkImageInfo.
+ */
+ const SkColorInfo& colorInfo() const { return fColorInfo; }
+
+ /** Returns true if SkAlphaType is set to hint that all pixels are opaque; their
+ alpha value is implicitly or explicitly 1.0. If true, and all pixels are
+ not opaque, Skia may draw incorrectly.
+
+ Does not check if SkColorType allows alpha, or if any pixel value has
+ transparency.
+
+ @return true if SkAlphaType is kOpaque_SkAlphaType
+ */
+ bool isOpaque() const { return fColorInfo.isOpaque(); }
+
+ /** Returns SkISize { width(), height() }.
+
+ @return integral size of width() and height()
+ */
+ SkISize dimensions() const { return fDimensions; }
+
+ /** Returns SkIRect { 0, 0, width(), height() }.
+
+ @return integral rectangle from origin to width() and height()
+ */
+ SkIRect bounds() const { return SkIRect::MakeSize(fDimensions); }
+
+ /** Returns true if associated SkColorSpace is not nullptr, and SkColorSpace gamma
+ is approximately the same as sRGB.
+ This includes the
+
+ @return true if SkColorSpace gamma is approximately the same as sRGB
+ */
+ bool gammaCloseToSRGB() const { return fColorInfo.gammaCloseToSRGB(); }
+
+ /** Creates SkImageInfo with the same SkColorType, SkColorSpace, and SkAlphaType,
+ with dimensions set to width and height.
+
+ @param newWidth pixel column count; must be zero or greater
+ @param newHeight pixel row count; must be zero or greater
+ @return created SkImageInfo
+ */
+ SkImageInfo makeWH(int newWidth, int newHeight) const {
+ return Make({newWidth, newHeight}, fColorInfo);
+ }
+
+ /** Creates SkImageInfo with the same SkColorType, SkColorSpace, and SkAlphaType,
+ with dimensions set to newDimensions.
+
+ @param newSize pixel column and row count; must be zero or greater
+ @return created SkImageInfo
+ */
+ SkImageInfo makeDimensions(SkISize newSize) const {
+ return Make(newSize, fColorInfo);
+ }
+
+ /** Creates SkImageInfo with same SkColorType, SkColorSpace, width, and height,
+ with SkAlphaType set to newAlphaType.
+
+ Created SkImageInfo contains newAlphaType even if it is incompatible with
+ SkColorType, in which case SkAlphaType in SkImageInfo is ignored.
+
+ @return created SkImageInfo
+ */
+ SkImageInfo makeAlphaType(SkAlphaType newAlphaType) const {
+ return Make(fDimensions, fColorInfo.makeAlphaType(newAlphaType));
+ }
+
+ /** Creates SkImageInfo with same SkAlphaType, SkColorSpace, width, and height,
+ with SkColorType set to newColorType.
+
+ @return created SkImageInfo
+ */
+ SkImageInfo makeColorType(SkColorType newColorType) const {
+ return Make(fDimensions, fColorInfo.makeColorType(newColorType));
+ }
+
+ /** Creates SkImageInfo with same SkAlphaType, SkColorType, width, and height,
+ with SkColorSpace set to cs.
+
+ @param cs range of colors; may be nullptr
+ @return created SkImageInfo
+ */
+ SkImageInfo makeColorSpace(sk_sp<SkColorSpace> cs) const {
+ return Make(fDimensions, fColorInfo.makeColorSpace(std::move(cs)));
+ }
+
+ /** Returns number of bytes per pixel required by SkColorType.
+ Returns zero if colorType( is kUnknown_SkColorType.
+
+ @return bytes in pixel
+ */
+ int bytesPerPixel() const { return fColorInfo.bytesPerPixel(); }
+
+ /** Returns bit shift converting row bytes to row pixels.
+ Returns zero for kUnknown_SkColorType.
+
+ @return one of: 0, 1, 2, 3; left shift to convert pixels to bytes
+ */
+ int shiftPerPixel() const { return fColorInfo.shiftPerPixel(); }
+
+ /** Returns minimum bytes per row, computed from pixel width() and SkColorType, which
+ specifies bytesPerPixel(). SkBitmap maximum value for row bytes must fit
+ in 31 bits.
+
+ @return width() times bytesPerPixel() as unsigned 64-bit integer
+ */
+ uint64_t minRowBytes64() const {
+ return (uint64_t)sk_64_mul(this->width(), this->bytesPerPixel());
+ }
+
+ /** Returns minimum bytes per row, computed from pixel width() and SkColorType, which
+ specifies bytesPerPixel(). SkBitmap maximum value for row bytes must fit
+ in 31 bits.
+
+ @return width() times bytesPerPixel() as size_t
+ */
+ size_t minRowBytes() const {
+ uint64_t minRowBytes = this->minRowBytes64();
+ if (!SkTFitsIn<int32_t>(minRowBytes)) {
+ return 0;
+ }
+ return (size_t)minRowBytes;
+ }
+
+ /** Returns byte offset of pixel from pixel base address.
+
+ Asserts in debug build if x or y is outside of bounds. Does not assert if
+ rowBytes is smaller than minRowBytes(), even though result may be incorrect.
+
+ @param x column index, zero or greater, and less than width()
+ @param y row index, zero or greater, and less than height()
+ @param rowBytes size of pixel row or larger
+ @return offset within pixel array
+
+ example: https://fiddle.skia.org/c/@ImageInfo_computeOffset
+ */
+ size_t computeOffset(int x, int y, size_t rowBytes) const;
+
+ /** Compares SkImageInfo with other, and returns true if width, height, SkColorType,
+ SkAlphaType, and SkColorSpace are equivalent.
+
+ @param other SkImageInfo to compare
+ @return true if SkImageInfo equals other
+ */
+ bool operator==(const SkImageInfo& other) const {
+ return fDimensions == other.fDimensions && fColorInfo == other.fColorInfo;
+ }
+
+ /** Compares SkImageInfo with other, and returns true if width, height, SkColorType,
+ SkAlphaType, and SkColorSpace are not equivalent.
+
+ @param other SkImageInfo to compare
+ @return true if SkImageInfo is not equal to other
+ */
+ bool operator!=(const SkImageInfo& other) const {
+ return !(*this == other);
+ }
+
+ /** Returns storage required by pixel array, given SkImageInfo dimensions, SkColorType,
+ and rowBytes. rowBytes is assumed to be at least as large as minRowBytes().
+
+ Returns zero if height is zero.
+ Returns SIZE_MAX if answer exceeds the range of size_t.
+
+ @param rowBytes size of pixel row or larger
+ @return memory required by pixel buffer
+
+ example: https://fiddle.skia.org/c/@ImageInfo_computeByteSize
+ */
+ size_t computeByteSize(size_t rowBytes) const;
+
+ /** Returns storage required by pixel array, given SkImageInfo dimensions, and
+ SkColorType. Uses minRowBytes() to compute bytes for pixel row.
+
+ Returns zero if height is zero.
+ Returns SIZE_MAX if answer exceeds the range of size_t.
+
+ @return least memory required by pixel buffer
+ */
+ size_t computeMinByteSize() const {
+ return this->computeByteSize(this->minRowBytes());
+ }
+
+ /** Returns true if byteSize equals SIZE_MAX. computeByteSize() and
+ computeMinByteSize() return SIZE_MAX if size_t can not hold buffer size.
+
+ @param byteSize result of computeByteSize() or computeMinByteSize()
+ @return true if computeByteSize() or computeMinByteSize() result exceeds size_t
+ */
+ static bool ByteSizeOverflowed(size_t byteSize) {
+ return SIZE_MAX == byteSize;
+ }
+
+ /** Returns true if rowBytes is valid for this SkImageInfo.
+
+ @param rowBytes size of pixel row including padding
+ @return true if rowBytes is large enough to contain pixel row and is properly
+ aligned
+ */
+ bool validRowBytes(size_t rowBytes) const {
+ if (rowBytes < this->minRowBytes64()) {
+ return false;
+ }
+ int shift = this->shiftPerPixel();
+ size_t alignedRowBytes = rowBytes >> shift << shift;
+ return alignedRowBytes == rowBytes;
+ }
+
+ /** Creates an empty SkImageInfo with kUnknown_SkColorType, kUnknown_SkAlphaType,
+ a width and height of zero, and no SkColorSpace.
+ */
+ void reset() { *this = {}; }
+
+ /** Asserts if internal values are illegal or inconsistent. Only available if
+ SK_DEBUG is defined at compile time.
+ */
+ SkDEBUGCODE(void validate() const;)
+
+private:
+ SkColorInfo fColorInfo;
+ SkISize fDimensions = {0, 0};
+
+ SkImageInfo(SkISize dimensions, const SkColorInfo& colorInfo)
+ : fColorInfo(colorInfo), fDimensions(dimensions) {}
+
+ SkImageInfo(SkISize dimensions, SkColorInfo&& colorInfo)
+ : fColorInfo(std::move(colorInfo)), fDimensions(dimensions) {}
+};
+
+#endif
diff --git a/src/deps/skia/include/core/SkM44.h b/src/deps/skia/include/core/SkM44.h
new file mode 100644
index 000000000..ae08b4400
--- /dev/null
+++ b/src/deps/skia/include/core/SkM44.h
@@ -0,0 +1,426 @@
+/*
+ * Copyright 2020 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkM44_DEFINED
+#define SkM44_DEFINED
+
+#include "include/core/SkMatrix.h"
+#include "include/core/SkRect.h"
+#include "include/core/SkScalar.h"
+
+struct SK_API SkV2 {
+ float x, y;
+
+ bool operator==(const SkV2 v) const { return x == v.x && y == v.y; }
+ bool operator!=(const SkV2 v) const { return !(*this == v); }
+
+ static SkScalar Dot(SkV2 a, SkV2 b) { return a.x * b.x + a.y * b.y; }
+ static SkScalar Cross(SkV2 a, SkV2 b) { return a.x * b.y - a.y * b.x; }
+ static SkV2 Normalize(SkV2 v) { return v * (1.0f / v.length()); }
+
+ SkV2 operator-() const { return {-x, -y}; }
+ SkV2 operator+(SkV2 v) const { return {x+v.x, y+v.y}; }
+ SkV2 operator-(SkV2 v) const { return {x-v.x, y-v.y}; }
+
+ SkV2 operator*(SkV2 v) const { return {x*v.x, y*v.y}; }
+ friend SkV2 operator*(SkV2 v, SkScalar s) { return {v.x*s, v.y*s}; }
+ friend SkV2 operator*(SkScalar s, SkV2 v) { return {v.x*s, v.y*s}; }
+ friend SkV2 operator/(SkV2 v, SkScalar s) { return {v.x/s, v.y/s}; }
+
+ void operator+=(SkV2 v) { *this = *this + v; }
+ void operator-=(SkV2 v) { *this = *this - v; }
+ void operator*=(SkV2 v) { *this = *this * v; }
+ void operator*=(SkScalar s) { *this = *this * s; }
+ void operator/=(SkScalar s) { *this = *this / s; }
+
+ SkScalar lengthSquared() const { return Dot(*this, *this); }
+ SkScalar length() const { return SkScalarSqrt(this->lengthSquared()); }
+
+ SkScalar dot(SkV2 v) const { return Dot(*this, v); }
+ SkScalar cross(SkV2 v) const { return Cross(*this, v); }
+ SkV2 normalize() const { return Normalize(*this); }
+
+ const float* ptr() const { return &x; }
+ float* ptr() { return &x; }
+};
+
+struct SK_API SkV3 {
+ float x, y, z;
+
+ bool operator==(const SkV3& v) const {
+ return x == v.x && y == v.y && z == v.z;
+ }
+ bool operator!=(const SkV3& v) const { return !(*this == v); }
+
+ static SkScalar Dot(const SkV3& a, const SkV3& b) { return a.x*b.x + a.y*b.y + a.z*b.z; }
+ static SkV3 Cross(const SkV3& a, const SkV3& b) {
+ return { a.y*b.z - a.z*b.y, a.z*b.x - a.x*b.z, a.x*b.y - a.y*b.x };
+ }
+ static SkV3 Normalize(const SkV3& v) { return v * (1.0f / v.length()); }
+
+ SkV3 operator-() const { return {-x, -y, -z}; }
+ SkV3 operator+(const SkV3& v) const { return { x + v.x, y + v.y, z + v.z }; }
+ SkV3 operator-(const SkV3& v) const { return { x - v.x, y - v.y, z - v.z }; }
+
+ SkV3 operator*(const SkV3& v) const {
+ return { x*v.x, y*v.y, z*v.z };
+ }
+ friend SkV3 operator*(const SkV3& v, SkScalar s) {
+ return { v.x*s, v.y*s, v.z*s };
+ }
+ friend SkV3 operator*(SkScalar s, const SkV3& v) { return v*s; }
+
+ void operator+=(SkV3 v) { *this = *this + v; }
+ void operator-=(SkV3 v) { *this = *this - v; }
+ void operator*=(SkV3 v) { *this = *this * v; }
+ void operator*=(SkScalar s) { *this = *this * s; }
+
+ SkScalar lengthSquared() const { return Dot(*this, *this); }
+ SkScalar length() const { return SkScalarSqrt(Dot(*this, *this)); }
+
+ SkScalar dot(const SkV3& v) const { return Dot(*this, v); }
+ SkV3 cross(const SkV3& v) const { return Cross(*this, v); }
+ SkV3 normalize() const { return Normalize(*this); }
+
+ const float* ptr() const { return &x; }
+ float* ptr() { return &x; }
+};
+
+struct SK_API SkV4 {
+ float x, y, z, w;
+
+ bool operator==(const SkV4& v) const {
+ return x == v.x && y == v.y && z == v.z && w == v.w;
+ }
+ bool operator!=(const SkV4& v) const { return !(*this == v); }
+
+ SkV4 operator-() const { return {-x, -y, -z, -w}; }
+ SkV4 operator+(const SkV4& v) const { return { x + v.x, y + v.y, z + v.z, w + v.w }; }
+ SkV4 operator-(const SkV4& v) const { return { x - v.x, y - v.y, z - v.z, w - v.w }; }
+
+ SkV4 operator*(const SkV4& v) const {
+ return { x*v.x, y*v.y, z*v.z, w*v.w };
+ }
+ friend SkV4 operator*(const SkV4& v, SkScalar s) {
+ return { v.x*s, v.y*s, v.z*s, v.w*s };
+ }
+ friend SkV4 operator*(SkScalar s, const SkV4& v) { return v*s; }
+
+ const float* ptr() const { return &x; }
+ float* ptr() { return &x; }
+
+ float operator[](int i) const {
+ SkASSERT(i >= 0 && i < 4);
+ return this->ptr()[i];
+ }
+ float& operator[](int i) {
+ SkASSERT(i >= 0 && i < 4);
+ return this->ptr()[i];
+ }
+};
+
+/**
+ * 4x4 matrix used by SkCanvas and other parts of Skia.
+ *
+ * Skia assumes a right-handed coordinate system:
+ * +X goes to the right
+ * +Y goes down
+ * +Z goes into the screen (away from the viewer)
+ */
+class SK_API SkM44 {
+public:
+ SkM44(const SkM44& src) = default;
+ SkM44& operator=(const SkM44& src) = default;
+
+ constexpr SkM44()
+ : fMat{1, 0, 0, 0,
+ 0, 1, 0, 0,
+ 0, 0, 1, 0,
+ 0, 0, 0, 1}
+ {}
+
+ SkM44(const SkM44& a, const SkM44& b) {
+ this->setConcat(a, b);
+ }
+
+ enum Uninitialized_Constructor {
+ kUninitialized_Constructor
+ };
+ SkM44(Uninitialized_Constructor) {}
+
+ enum NaN_Constructor {
+ kNaN_Constructor
+ };
+ constexpr SkM44(NaN_Constructor)
+ : fMat{SK_ScalarNaN, SK_ScalarNaN, SK_ScalarNaN, SK_ScalarNaN,
+ SK_ScalarNaN, SK_ScalarNaN, SK_ScalarNaN, SK_ScalarNaN,
+ SK_ScalarNaN, SK_ScalarNaN, SK_ScalarNaN, SK_ScalarNaN,
+ SK_ScalarNaN, SK_ScalarNaN, SK_ScalarNaN, SK_ScalarNaN}
+ {}
+
+ /**
+ * The constructor parameters are in row-major order.
+ */
+ constexpr SkM44(SkScalar m0, SkScalar m4, SkScalar m8, SkScalar m12,
+ SkScalar m1, SkScalar m5, SkScalar m9, SkScalar m13,
+ SkScalar m2, SkScalar m6, SkScalar m10, SkScalar m14,
+ SkScalar m3, SkScalar m7, SkScalar m11, SkScalar m15)
+ // fMat is column-major order in memory.
+ : fMat{m0, m1, m2, m3,
+ m4, m5, m6, m7,
+ m8, m9, m10, m11,
+ m12, m13, m14, m15}
+ {}
+
+ static SkM44 Rows(const SkV4& r0, const SkV4& r1, const SkV4& r2, const SkV4& r3) {
+ SkM44 m(kUninitialized_Constructor);
+ m.setRow(0, r0);
+ m.setRow(1, r1);
+ m.setRow(2, r2);
+ m.setRow(3, r3);
+ return m;
+ }
+ static SkM44 Cols(const SkV4& c0, const SkV4& c1, const SkV4& c2, const SkV4& c3) {
+ SkM44 m(kUninitialized_Constructor);
+ m.setCol(0, c0);
+ m.setCol(1, c1);
+ m.setCol(2, c2);
+ m.setCol(3, c3);
+ return m;
+ }
+
+ static SkM44 RowMajor(const SkScalar r[16]) {
+ return SkM44(r[ 0], r[ 1], r[ 2], r[ 3],
+ r[ 4], r[ 5], r[ 6], r[ 7],
+ r[ 8], r[ 9], r[10], r[11],
+ r[12], r[13], r[14], r[15]);
+ }
+ static SkM44 ColMajor(const SkScalar c[16]) {
+ return SkM44(c[0], c[4], c[ 8], c[12],
+ c[1], c[5], c[ 9], c[13],
+ c[2], c[6], c[10], c[14],
+ c[3], c[7], c[11], c[15]);
+ }
+
+ static SkM44 Translate(SkScalar x, SkScalar y, SkScalar z = 0) {
+ return SkM44(1, 0, 0, x,
+ 0, 1, 0, y,
+ 0, 0, 1, z,
+ 0, 0, 0, 1);
+ }
+
+ static SkM44 Scale(SkScalar x, SkScalar y, SkScalar z = 1) {
+ return SkM44(x, 0, 0, 0,
+ 0, y, 0, 0,
+ 0, 0, z, 0,
+ 0, 0, 0, 1);
+ }
+
+ static SkM44 Rotate(SkV3 axis, SkScalar radians) {
+ SkM44 m(kUninitialized_Constructor);
+ m.setRotate(axis, radians);
+ return m;
+ }
+
+ // Scales and translates 'src' to fill 'dst' exactly.
+ static SkM44 RectToRect(const SkRect& src, const SkRect& dst);
+
+ static SkM44 LookAt(const SkV3& eye, const SkV3& center, const SkV3& up);
+ static SkM44 Perspective(float near, float far, float angle);
+
+ bool operator==(const SkM44& other) const;
+ bool operator!=(const SkM44& other) const {
+ return !(other == *this);
+ }
+
+ void getColMajor(SkScalar v[]) const {
+ memcpy(v, fMat, sizeof(fMat));
+ }
+ void getRowMajor(SkScalar v[]) const;
+
+ SkScalar rc(int r, int c) const {
+ SkASSERT(r >= 0 && r <= 3);
+ SkASSERT(c >= 0 && c <= 3);
+ return fMat[c*4 + r];
+ }
+ void setRC(int r, int c, SkScalar value) {
+ SkASSERT(r >= 0 && r <= 3);
+ SkASSERT(c >= 0 && c <= 3);
+ fMat[c*4 + r] = value;
+ }
+
+ SkV4 row(int i) const {
+ SkASSERT(i >= 0 && i <= 3);
+ return {fMat[i + 0], fMat[i + 4], fMat[i + 8], fMat[i + 12]};
+ }
+ SkV4 col(int i) const {
+ SkASSERT(i >= 0 && i <= 3);
+ return {fMat[i*4 + 0], fMat[i*4 + 1], fMat[i*4 + 2], fMat[i*4 + 3]};
+ }
+
+ void setRow(int i, const SkV4& v) {
+ SkASSERT(i >= 0 && i <= 3);
+ fMat[i + 0] = v.x;
+ fMat[i + 4] = v.y;
+ fMat[i + 8] = v.z;
+ fMat[i + 12] = v.w;
+ }
+ void setCol(int i, const SkV4& v) {
+ SkASSERT(i >= 0 && i <= 3);
+ memcpy(&fMat[i*4], v.ptr(), sizeof(v));
+ }
+
+ SkM44& setIdentity() {
+ *this = { 1, 0, 0, 0,
+ 0, 1, 0, 0,
+ 0, 0, 1, 0,
+ 0, 0, 0, 1 };
+ return *this;
+ }
+
+ SkM44& setTranslate(SkScalar x, SkScalar y, SkScalar z = 0) {
+ *this = { 1, 0, 0, x,
+ 0, 1, 0, y,
+ 0, 0, 1, z,
+ 0, 0, 0, 1 };
+ return *this;
+ }
+
+ SkM44& setScale(SkScalar x, SkScalar y, SkScalar z = 1) {
+ *this = { x, 0, 0, 0,
+ 0, y, 0, 0,
+ 0, 0, z, 0,
+ 0, 0, 0, 1 };
+ return *this;
+ }
+
+ /**
+ * Set this matrix to rotate about the specified unit-length axis vector,
+ * by an angle specified by its sin() and cos().
+ *
+ * This does not attempt to verify that axis.length() == 1 or that the sin,cos values
+ * are correct.
+ */
+ SkM44& setRotateUnitSinCos(SkV3 axis, SkScalar sinAngle, SkScalar cosAngle);
+
+ /**
+ * Set this matrix to rotate about the specified unit-length axis vector,
+ * by an angle specified in radians.
+ *
+ * This does not attempt to verify that axis.length() == 1.
+ */
+ SkM44& setRotateUnit(SkV3 axis, SkScalar radians) {
+ return this->setRotateUnitSinCos(axis, SkScalarSin(radians), SkScalarCos(radians));
+ }
+
+ /**
+ * Set this matrix to rotate about the specified axis vector,
+ * by an angle specified in radians.
+ *
+ * Note: axis is not assumed to be unit-length, so it will be normalized internally.
+ * If axis is already unit-length, call setRotateAboutUnitRadians() instead.
+ */
+ SkM44& setRotate(SkV3 axis, SkScalar radians);
+
+ SkM44& setConcat(const SkM44& a, const SkM44& b);
+
+ friend SkM44 operator*(const SkM44& a, const SkM44& b) {
+ return SkM44(a, b);
+ }
+
+ SkM44& preConcat(const SkM44& m) {
+ return this->setConcat(*this, m);
+ }
+
+ SkM44& postConcat(const SkM44& m) {
+ return this->setConcat(m, *this);
+ }
+
+ /**
+ * A matrix is categorized as 'perspective' if the bottom row is not [0, 0, 0, 1].
+ * For most uses, a bottom row of [0, 0, 0, X] behaves like a non-perspective matrix, though
+ * it will be categorized as perspective. Calling normalizePerspective() will change the
+ * matrix such that, if its bottom row was [0, 0, 0, X], it will be changed to [0, 0, 0, 1]
+ * by scaling the rest of the matrix by 1/X.
+ *
+ * | A B C D | | A/X B/X C/X D/X |
+ * | E F G H | -> | E/X F/X G/X H/X | for X != 0
+ * | I J K L | | I/X J/X K/X L/X |
+ * | 0 0 0 X | | 0 0 0 1 |
+ */
+ void normalizePerspective();
+
+ /** Returns true if all elements of the matrix are finite. Returns false if any
+ element is infinity, or NaN.
+
+ @return true if matrix has only finite elements
+ */
+ bool isFinite() const { return SkScalarsAreFinite(fMat, 16); }
+
+ /** If this is invertible, return that in inverse and return true. If it is
+ * not invertible, return false and leave the inverse parameter unchanged.
+ */
+ bool SK_WARN_UNUSED_RESULT invert(SkM44* inverse) const;
+
+ SkM44 SK_WARN_UNUSED_RESULT transpose() const;
+
+ void dump() const;
+
+ ////////////
+
+ SkV4 map(float x, float y, float z, float w) const;
+ SkV4 operator*(const SkV4& v) const {
+ return this->map(v.x, v.y, v.z, v.w);
+ }
+ SkV3 operator*(SkV3 v) const {
+ auto v4 = this->map(v.x, v.y, v.z, 0);
+ return {v4.x, v4.y, v4.z};
+ }
+ ////////////////////// Converting to/from SkMatrix
+
+ /* When converting from SkM44 to SkMatrix, the third row and
+ * column is dropped. When converting from SkMatrix to SkM44
+ * the third row and column remain as identity:
+ * [ a b c ] [ a b 0 c ]
+ * [ d e f ] -> [ d e 0 f ]
+ * [ g h i ] [ 0 0 1 0 ]
+ * [ g h 0 i ]
+ */
+ SkMatrix asM33() const {
+ return SkMatrix::MakeAll(fMat[0], fMat[4], fMat[12],
+ fMat[1], fMat[5], fMat[13],
+ fMat[3], fMat[7], fMat[15]);
+ }
+
+ explicit SkM44(const SkMatrix& src)
+ : SkM44(src[SkMatrix::kMScaleX], src[SkMatrix::kMSkewX], 0, src[SkMatrix::kMTransX],
+ src[SkMatrix::kMSkewY], src[SkMatrix::kMScaleY], 0, src[SkMatrix::kMTransY],
+ 0, 0, 1, 0,
+ src[SkMatrix::kMPersp0], src[SkMatrix::kMPersp1], 0, src[SkMatrix::kMPersp2])
+ {}
+
+ SkM44& preTranslate(SkScalar x, SkScalar y, SkScalar z = 0);
+ SkM44& postTranslate(SkScalar x, SkScalar y, SkScalar z = 0);
+
+ SkM44& preScale(SkScalar x, SkScalar y);
+ SkM44& preScale(SkScalar x, SkScalar y, SkScalar z);
+ SkM44& preConcat(const SkMatrix&);
+
+private:
+ /* Stored in column-major.
+ * Indices
+ * 0 4 8 12 1 0 0 trans_x
+ * 1 5 9 13 e.g. 0 1 0 trans_y
+ * 2 6 10 14 0 0 1 trans_z
+ * 3 7 11 15 0 0 0 1
+ */
+ SkScalar fMat[16];
+
+ friend class SkMatrixPriv;
+};
+
+#endif
diff --git a/src/deps/skia/include/core/SkMallocPixelRef.h b/src/deps/skia/include/core/SkMallocPixelRef.h
new file mode 100644
index 000000000..cce54b50f
--- /dev/null
+++ b/src/deps/skia/include/core/SkMallocPixelRef.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2008 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkMallocPixelRef_DEFINED
+#define SkMallocPixelRef_DEFINED
+
+#include "include/core/SkPixelRef.h"
+#include "include/core/SkRefCnt.h"
+#include "include/core/SkTypes.h"
+class SkData;
+struct SkImageInfo;
+
+/** We explicitly use the same allocator for our pixels that SkMask does,
+ so that we can freely assign memory allocated by one class to the other.
+*/
+namespace SkMallocPixelRef {
+ /**
+ * Return a new SkMallocPixelRef, automatically allocating storage for the
+ * pixels. If rowBytes are 0, an optimal value will be chosen automatically.
+ * If rowBytes is > 0, then it will be respected, or NULL will be returned
+ * if rowBytes is invalid for the specified info.
+ *
+ * All pixel bytes are zeroed.
+ *
+ * Returns NULL on failure.
+ */
+ SK_API sk_sp<SkPixelRef> MakeAllocate(const SkImageInfo&, size_t rowBytes);
+
+ /**
+ * Return a new SkMallocPixelRef that will use the provided SkData and
+ * rowBytes as pixel storage. The SkData will be ref()ed and on
+ * destruction of the PixelRef, the SkData will be unref()ed.
+ *
+ * Returns NULL on failure.
+ */
+ SK_API sk_sp<SkPixelRef> MakeWithData(const SkImageInfo&, size_t rowBytes, sk_sp<SkData> data);
+} // namespace SkMallocPixelRef
+#endif
diff --git a/src/deps/skia/include/core/SkMaskFilter.h b/src/deps/skia/include/core/SkMaskFilter.h
new file mode 100644
index 000000000..3fde51b71
--- /dev/null
+++ b/src/deps/skia/include/core/SkMaskFilter.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkMaskFilter_DEFINED
+#define SkMaskFilter_DEFINED
+
+#include "include/core/SkBlurTypes.h"
+#include "include/core/SkCoverageMode.h"
+#include "include/core/SkFlattenable.h"
+#include "include/core/SkScalar.h"
+
+class SkMatrix;
+struct SkRect;
+
+/** \class SkMaskFilter
+
+ SkMaskFilter is the base class for object that perform transformations on
+ the mask before drawing it. An example subclass is Blur.
+*/
+class SK_API SkMaskFilter : public SkFlattenable {
+public:
+ /** Create a blur maskfilter.
+ * @param style The SkBlurStyle to use
+ * @param sigma Standard deviation of the Gaussian blur to apply. Must be > 0.
+ * @param respectCTM if true the blur's sigma is modified by the CTM.
+ * @return The new blur maskfilter
+ */
+ static sk_sp<SkMaskFilter> MakeBlur(SkBlurStyle style, SkScalar sigma,
+ bool respectCTM = true);
+
+ /**
+ * Returns the approximate bounds that would result from filtering the src rect.
+ * The actual result may be different, but it should be contained within the
+ * returned bounds.
+ */
+ SkRect approximateFilteredBounds(const SkRect& src) const;
+
+ static sk_sp<SkMaskFilter> Deserialize(const void* data, size_t size,
+ const SkDeserialProcs* procs = nullptr);
+
+private:
+ static void RegisterFlattenables();
+ friend class SkFlattenable;
+};
+
+#endif
diff --git a/src/deps/skia/include/core/SkMath.h b/src/deps/skia/include/core/SkMath.h
new file mode 100644
index 000000000..97352afab
--- /dev/null
+++ b/src/deps/skia/include/core/SkMath.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkMath_DEFINED
+#define SkMath_DEFINED
+
+#include "include/core/SkTypes.h"
+
+// 64bit -> 32bit utilities
+
+// Handy util that can be passed two ints, and will automatically promote to
+// 64bits before the multiply, so the caller doesn't have to remember to cast
+// e.g. (int64_t)a * b;
+static inline int64_t sk_64_mul(int64_t a, int64_t b) {
+ return a * b;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+/**
+ * Returns true if value is a power of 2. Does not explicitly check for
+ * value <= 0.
+ */
+template <typename T> constexpr inline bool SkIsPow2(T value) {
+ return (value & (value - 1)) == 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+/**
+ * Return a*b/((1 << shift) - 1), rounding any fractional bits.
+ * Only valid if a and b are unsigned and <= 32767 and shift is > 0 and <= 8
+ */
+static inline unsigned SkMul16ShiftRound(U16CPU a, U16CPU b, int shift) {
+ SkASSERT(a <= 32767);
+ SkASSERT(b <= 32767);
+ SkASSERT(shift > 0 && shift <= 8);
+ unsigned prod = a*b + (1 << (shift - 1));
+ return (prod + (prod >> shift)) >> shift;
+}
+
+/**
+ * Return a*b/255, rounding any fractional bits.
+ * Only valid if a and b are unsigned and <= 32767.
+ */
+static inline U8CPU SkMulDiv255Round(U16CPU a, U16CPU b) {
+ return SkMul16ShiftRound(a,b,8);
+}
+
+#endif
diff --git a/src/deps/skia/include/core/SkMatrix.h b/src/deps/skia/include/core/SkMatrix.h
new file mode 100644
index 000000000..03140760d
--- /dev/null
+++ b/src/deps/skia/include/core/SkMatrix.h
@@ -0,0 +1,1986 @@
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkMatrix_DEFINED
+#define SkMatrix_DEFINED
+
+#include "include/core/SkRect.h"
+#include "include/private/SkMacros.h"
+#include "include/private/SkTo.h"
+
+struct SkRSXform;
+struct SkPoint3;
+
+// Remove when clients are updated to live without this
+#define SK_SUPPORT_LEGACY_MATRIX_RECTTORECT
+
+/**
+ * When we transform points through a matrix containing perspective (the bottom row is something
+ * other than 0,0,1), the bruteforce math can produce confusing results (since we might divide
+ * by 0, or a negative w value). By default, methods that map rects and paths will apply
+ * perspective clipping, but this can be changed by specifying kYes to those methods.
+ */
+enum class SkApplyPerspectiveClip {
+ kNo, //!< Don't pre-clip the geometry before applying the (perspective) matrix
+ kYes, //!< Do pre-clip the geometry before applying the (perspective) matrix
+};
+
+/** \class SkMatrix
+ SkMatrix holds a 3x3 matrix for transforming coordinates. This allows mapping
+ SkPoint and vectors with translation, scaling, skewing, rotation, and
+ perspective.
+
+ SkMatrix elements are in row major order.
+ SkMatrix constexpr default constructs to identity.
+
+ SkMatrix includes a hidden variable that classifies the type of matrix to
+ improve performance. SkMatrix is not thread safe unless getType() is called first.
+
+ example: https://fiddle.skia.org/c/@Matrix_063
+*/
+SK_BEGIN_REQUIRE_DENSE
+class SK_API SkMatrix {
+public:
+
+ /** Creates an identity SkMatrix:
+
+ | 1 0 0 |
+ | 0 1 0 |
+ | 0 0 1 |
+ */
+ constexpr SkMatrix() : SkMatrix(1,0,0, 0,1,0, 0,0,1, kIdentity_Mask | kRectStaysRect_Mask) {}
+
+ /** Sets SkMatrix to scale by (sx, sy). Returned matrix is:
+
+ | sx 0 0 |
+ | 0 sy 0 |
+ | 0 0 1 |
+
+ @param sx horizontal scale factor
+ @param sy vertical scale factor
+ @return SkMatrix with scale
+ */
+ static SkMatrix SK_WARN_UNUSED_RESULT Scale(SkScalar sx, SkScalar sy) {
+ SkMatrix m;
+ m.setScale(sx, sy);
+ return m;
+ }
+
+ /** Sets SkMatrix to translate by (dx, dy). Returned matrix is:
+
+ | 1 0 dx |
+ | 0 1 dy |
+ | 0 0 1 |
+
+ @param dx horizontal translation
+ @param dy vertical translation
+ @return SkMatrix with translation
+ */
+ static SkMatrix SK_WARN_UNUSED_RESULT Translate(SkScalar dx, SkScalar dy) {
+ SkMatrix m;
+ m.setTranslate(dx, dy);
+ return m;
+ }
+ static SkMatrix SK_WARN_UNUSED_RESULT Translate(SkVector t) { return Translate(t.x(), t.y()); }
+ static SkMatrix SK_WARN_UNUSED_RESULT Translate(SkIVector t) { return Translate(t.x(), t.y()); }
+
+ /** Sets SkMatrix to rotate by |deg| about a pivot point at (0, 0).
+
+ @param deg rotation angle in degrees (positive rotates clockwise)
+ @return SkMatrix with rotation
+ */
+ static SkMatrix SK_WARN_UNUSED_RESULT RotateDeg(SkScalar deg) {
+ SkMatrix m;
+ m.setRotate(deg);
+ return m;
+ }
+ static SkMatrix SK_WARN_UNUSED_RESULT RotateDeg(SkScalar deg, SkPoint pt) {
+ SkMatrix m;
+ m.setRotate(deg, pt.x(), pt.y());
+ return m;
+ }
+ static SkMatrix SK_WARN_UNUSED_RESULT RotateRad(SkScalar rad) {
+ return RotateDeg(SkRadiansToDegrees(rad));
+ }
+
+ /** Sets SkMatrix to skew by (kx, ky) about pivot point (0, 0).
+
+ @param kx horizontal skew factor
+ @param ky vertical skew factor
+ @return SkMatrix with skew
+ */
+ static SkMatrix SK_WARN_UNUSED_RESULT Skew(SkScalar kx, SkScalar ky) {
+ SkMatrix m;
+ m.setSkew(kx, ky);
+ return m;
+ }
+
+ /** \enum SkMatrix::ScaleToFit
+ ScaleToFit describes how SkMatrix is constructed to map one SkRect to another.
+ ScaleToFit may allow SkMatrix to have unequal horizontal and vertical scaling,
+ or may restrict SkMatrix to square scaling. If restricted, ScaleToFit specifies
+ how SkMatrix maps to the side or center of the destination SkRect.
+ */
+ enum ScaleToFit {
+ kFill_ScaleToFit, //!< scales in x and y to fill destination SkRect
+ kStart_ScaleToFit, //!< scales and aligns to left and top
+ kCenter_ScaleToFit, //!< scales and aligns to center
+ kEnd_ScaleToFit, //!< scales and aligns to right and bottom
+ };
+
+ /** Returns SkMatrix set to scale and translate src to dst. ScaleToFit selects
+ whether mapping completely fills dst or preserves the aspect ratio, and how to
+ align src within dst. Returns the identity SkMatrix if src is empty. If dst is
+ empty, returns SkMatrix set to:
+
+ | 0 0 0 |
+ | 0 0 0 |
+ | 0 0 1 |
+
+ @param src SkRect to map from
+ @param dst SkRect to map to
+ @param mode How to handle the mapping
+ @return SkMatrix mapping src to dst
+ */
+ static SkMatrix SK_WARN_UNUSED_RESULT RectToRect(const SkRect& src, const SkRect& dst,
+ ScaleToFit mode = kFill_ScaleToFit) {
+ return MakeRectToRect(src, dst, mode);
+ }
+
+ /** Sets SkMatrix to:
+
+ | scaleX skewX transX |
+ | skewY scaleY transY |
+ | pers0 pers1 pers2 |
+
+ @param scaleX horizontal scale factor
+ @param skewX horizontal skew factor
+ @param transX horizontal translation
+ @param skewY vertical skew factor
+ @param scaleY vertical scale factor
+ @param transY vertical translation
+ @param pers0 input x-axis perspective factor
+ @param pers1 input y-axis perspective factor
+ @param pers2 perspective scale factor
+ @return SkMatrix constructed from parameters
+ */
+ static SkMatrix SK_WARN_UNUSED_RESULT MakeAll(SkScalar scaleX, SkScalar skewX, SkScalar transX,
+ SkScalar skewY, SkScalar scaleY, SkScalar transY,
+ SkScalar pers0, SkScalar pers1, SkScalar pers2) {
+ SkMatrix m;
+ m.setAll(scaleX, skewX, transX, skewY, scaleY, transY, pers0, pers1, pers2);
+ return m;
+ }
+
+ /** \enum SkMatrix::TypeMask
+ Enum of bit fields for mask returned by getType().
+ Used to identify the complexity of SkMatrix, to optimize performance.
+ */
+ enum TypeMask {
+ kIdentity_Mask = 0, //!< identity SkMatrix; all bits clear
+ kTranslate_Mask = 0x01, //!< translation SkMatrix
+ kScale_Mask = 0x02, //!< scale SkMatrix
+ kAffine_Mask = 0x04, //!< skew or rotate SkMatrix
+ kPerspective_Mask = 0x08, //!< perspective SkMatrix
+ };
+
+ /** Returns a bit field describing the transformations the matrix may
+ perform. The bit field is computed conservatively, so it may include
+ false positives. For example, when kPerspective_Mask is set, all
+ other bits are set.
+
+ @return kIdentity_Mask, or combinations of: kTranslate_Mask, kScale_Mask,
+ kAffine_Mask, kPerspective_Mask
+ */
+ TypeMask getType() const {
+ if (fTypeMask & kUnknown_Mask) {
+ fTypeMask = this->computeTypeMask();
+ }
+ // only return the public masks
+ return (TypeMask)(fTypeMask & 0xF);
+ }
+
+ /** Returns true if SkMatrix is identity. Identity matrix is:
+
+ | 1 0 0 |
+ | 0 1 0 |
+ | 0 0 1 |
+
+ @return true if SkMatrix has no effect
+ */
+ bool isIdentity() const {
+ return this->getType() == 0;
+ }
+
+ /** Returns true if SkMatrix at most scales and translates. SkMatrix may be identity,
+ contain only scale elements, only translate elements, or both. SkMatrix form is:
+
+ | scale-x 0 translate-x |
+ | 0 scale-y translate-y |
+ | 0 0 1 |
+
+ @return true if SkMatrix is identity; or scales, translates, or both
+ */
+ bool isScaleTranslate() const {
+ return !(this->getType() & ~(kScale_Mask | kTranslate_Mask));
+ }
+
+ /** Returns true if SkMatrix is identity, or translates. SkMatrix form is:
+
+ | 1 0 translate-x |
+ | 0 1 translate-y |
+ | 0 0 1 |
+
+ @return true if SkMatrix is identity, or translates
+ */
+ bool isTranslate() const { return !(this->getType() & ~(kTranslate_Mask)); }
+
+ /** Returns true SkMatrix maps SkRect to another SkRect. If true, SkMatrix is identity,
+ or scales, or rotates a multiple of 90 degrees, or mirrors on axes. In all
+ cases, SkMatrix may also have translation. SkMatrix form is either:
+
+ | scale-x 0 translate-x |
+ | 0 scale-y translate-y |
+ | 0 0 1 |
+
+ or
+
+ | 0 rotate-x translate-x |
+ | rotate-y 0 translate-y |
+ | 0 0 1 |
+
+ for non-zero values of scale-x, scale-y, rotate-x, and rotate-y.
+
+ Also called preservesAxisAlignment(); use the one that provides better inline
+ documentation.
+
+ @return true if SkMatrix maps one SkRect into another
+ */
+ bool rectStaysRect() const {
+ if (fTypeMask & kUnknown_Mask) {
+ fTypeMask = this->computeTypeMask();
+ }
+ return (fTypeMask & kRectStaysRect_Mask) != 0;
+ }
+
+ /** Returns true SkMatrix maps SkRect to another SkRect. If true, SkMatrix is identity,
+ or scales, or rotates a multiple of 90 degrees, or mirrors on axes. In all
+ cases, SkMatrix may also have translation. SkMatrix form is either:
+
+ | scale-x 0 translate-x |
+ | 0 scale-y translate-y |
+ | 0 0 1 |
+
+ or
+
+ | 0 rotate-x translate-x |
+ | rotate-y 0 translate-y |
+ | 0 0 1 |
+
+ for non-zero values of scale-x, scale-y, rotate-x, and rotate-y.
+
+ Also called rectStaysRect(); use the one that provides better inline
+ documentation.
+
+ @return true if SkMatrix maps one SkRect into another
+ */
+ bool preservesAxisAlignment() const { return this->rectStaysRect(); }
+
+ /** Returns true if the matrix contains perspective elements. SkMatrix form is:
+
+ | -- -- -- |
+ | -- -- -- |
+ | perspective-x perspective-y perspective-scale |
+
+ where perspective-x or perspective-y is non-zero, or perspective-scale is
+ not one. All other elements may have any value.
+
+ @return true if SkMatrix is in most general form
+ */
+ bool hasPerspective() const {
+ return SkToBool(this->getPerspectiveTypeMaskOnly() &
+ kPerspective_Mask);
+ }
+
+ /** Returns true if SkMatrix contains only translation, rotation, reflection, and
+ uniform scale.
+ Returns false if SkMatrix contains different scales, skewing, perspective, or
+ degenerate forms that collapse to a line or point.
+
+ Describes that the SkMatrix makes rendering with and without the matrix are
+ visually alike; a transformed circle remains a circle. Mathematically, this is
+ referred to as similarity of a Euclidean space, or a similarity transformation.
+
+ Preserves right angles, keeping the arms of the angle equal lengths.
+
+ @param tol to be deprecated
+ @return true if SkMatrix only rotates, uniformly scales, translates
+
+ example: https://fiddle.skia.org/c/@Matrix_isSimilarity
+ */
+ bool isSimilarity(SkScalar tol = SK_ScalarNearlyZero) const;
+
+ /** Returns true if SkMatrix contains only translation, rotation, reflection, and
+ scale. Scale may differ along rotated axes.
+ Returns false if SkMatrix skewing, perspective, or degenerate forms that collapse
+ to a line or point.
+
+ Preserves right angles, but not requiring that the arms of the angle
+ retain equal lengths.
+
+ @param tol to be deprecated
+ @return true if SkMatrix only rotates, scales, translates
+
+ example: https://fiddle.skia.org/c/@Matrix_preservesRightAngles
+ */
+ bool preservesRightAngles(SkScalar tol = SK_ScalarNearlyZero) const;
+
+ /** SkMatrix organizes its values in row-major order. These members correspond to
+ each value in SkMatrix.
+ */
+ static constexpr int kMScaleX = 0; //!< horizontal scale factor
+ static constexpr int kMSkewX = 1; //!< horizontal skew factor
+ static constexpr int kMTransX = 2; //!< horizontal translation
+ static constexpr int kMSkewY = 3; //!< vertical skew factor
+ static constexpr int kMScaleY = 4; //!< vertical scale factor
+ static constexpr int kMTransY = 5; //!< vertical translation
+ static constexpr int kMPersp0 = 6; //!< input x perspective factor
+ static constexpr int kMPersp1 = 7; //!< input y perspective factor
+ static constexpr int kMPersp2 = 8; //!< perspective bias
+
+ /** Affine arrays are in column-major order to match the matrix used by
+ PDF and XPS.
+ */
+ static constexpr int kAScaleX = 0; //!< horizontal scale factor
+ static constexpr int kASkewY = 1; //!< vertical skew factor
+ static constexpr int kASkewX = 2; //!< horizontal skew factor
+ static constexpr int kAScaleY = 3; //!< vertical scale factor
+ static constexpr int kATransX = 4; //!< horizontal translation
+ static constexpr int kATransY = 5; //!< vertical translation
+
+ /** Returns one matrix value. Asserts if index is out of range and SK_DEBUG is
+ defined.
+
+ @param index one of: kMScaleX, kMSkewX, kMTransX, kMSkewY, kMScaleY, kMTransY,
+ kMPersp0, kMPersp1, kMPersp2
+ @return value corresponding to index
+ */
+ SkScalar operator[](int index) const {
+ SkASSERT((unsigned)index < 9);
+ return fMat[index];
+ }
+
+ /** Returns one matrix value. Asserts if index is out of range and SK_DEBUG is
+ defined.
+
+ @param index one of: kMScaleX, kMSkewX, kMTransX, kMSkewY, kMScaleY, kMTransY,
+ kMPersp0, kMPersp1, kMPersp2
+ @return value corresponding to index
+ */
+ SkScalar get(int index) const {
+ SkASSERT((unsigned)index < 9);
+ return fMat[index];
+ }
+
+ /** Returns one matrix value from a particular row/column. Asserts if index is out
+ of range and SK_DEBUG is defined.
+
+ @param r matrix row to fetch
+ @param c matrix column to fetch
+ @return value at the given matrix position
+ */
+ SkScalar rc(int r, int c) const {
+ SkASSERT(r >= 0 && r <= 2);
+ SkASSERT(c >= 0 && c <= 2);
+ return fMat[r*3 + c];
+ }
+
+ /** Returns scale factor multiplied by x-axis input, contributing to x-axis output.
+ With mapPoints(), scales SkPoint along the x-axis.
+
+ @return horizontal scale factor
+ */
+ SkScalar getScaleX() const { return fMat[kMScaleX]; }
+
+ /** Returns scale factor multiplied by y-axis input, contributing to y-axis output.
+ With mapPoints(), scales SkPoint along the y-axis.
+
+ @return vertical scale factor
+ */
+ SkScalar getScaleY() const { return fMat[kMScaleY]; }
+
+ /** Returns scale factor multiplied by x-axis input, contributing to y-axis output.
+ With mapPoints(), skews SkPoint along the y-axis.
+ Skewing both axes can rotate SkPoint.
+
+ @return vertical skew factor
+ */
+ SkScalar getSkewY() const { return fMat[kMSkewY]; }
+
+ /** Returns scale factor multiplied by y-axis input, contributing to x-axis output.
+ With mapPoints(), skews SkPoint along the x-axis.
+ Skewing both axes can rotate SkPoint.
+
+ @return horizontal scale factor
+ */
+ SkScalar getSkewX() const { return fMat[kMSkewX]; }
+
+ /** Returns translation contributing to x-axis output.
+ With mapPoints(), moves SkPoint along the x-axis.
+
+ @return horizontal translation factor
+ */
+ SkScalar getTranslateX() const { return fMat[kMTransX]; }
+
+ /** Returns translation contributing to y-axis output.
+ With mapPoints(), moves SkPoint along the y-axis.
+
+ @return vertical translation factor
+ */
+ SkScalar getTranslateY() const { return fMat[kMTransY]; }
+
+ /** Returns factor scaling input x-axis relative to input y-axis.
+
+ @return input x-axis perspective factor
+ */
+ SkScalar getPerspX() const { return fMat[kMPersp0]; }
+
+ /** Returns factor scaling input y-axis relative to input x-axis.
+
+ @return input y-axis perspective factor
+ */
+ SkScalar getPerspY() const { return fMat[kMPersp1]; }
+
+ /** Returns writable SkMatrix value. Asserts if index is out of range and SK_DEBUG is
+ defined. Clears internal cache anticipating that caller will change SkMatrix value.
+
+ Next call to read SkMatrix state may recompute cache; subsequent writes to SkMatrix
+ value must be followed by dirtyMatrixTypeCache().
+
+ @param index one of: kMScaleX, kMSkewX, kMTransX, kMSkewY, kMScaleY, kMTransY,
+ kMPersp0, kMPersp1, kMPersp2
+ @return writable value corresponding to index
+ */
+ SkScalar& operator[](int index) {
+ SkASSERT((unsigned)index < 9);
+ this->setTypeMask(kUnknown_Mask);
+ return fMat[index];
+ }
+
+ /** Sets SkMatrix value. Asserts if index is out of range and SK_DEBUG is
+ defined. Safer than operator[]; internal cache is always maintained.
+
+ @param index one of: kMScaleX, kMSkewX, kMTransX, kMSkewY, kMScaleY, kMTransY,
+ kMPersp0, kMPersp1, kMPersp2
+ @param value scalar to store in SkMatrix
+ */
+ SkMatrix& set(int index, SkScalar value) {
+ SkASSERT((unsigned)index < 9);
+ fMat[index] = value;
+ this->setTypeMask(kUnknown_Mask);
+ return *this;
+ }
+
+ /** Sets horizontal scale factor.
+
+ @param v horizontal scale factor to store
+ */
+ SkMatrix& setScaleX(SkScalar v) { return this->set(kMScaleX, v); }
+
+ /** Sets vertical scale factor.
+
+ @param v vertical scale factor to store
+ */
+ SkMatrix& setScaleY(SkScalar v) { return this->set(kMScaleY, v); }
+
+ /** Sets vertical skew factor.
+
+ @param v vertical skew factor to store
+ */
+ SkMatrix& setSkewY(SkScalar v) { return this->set(kMSkewY, v); }
+
+ /** Sets horizontal skew factor.
+
+ @param v horizontal skew factor to store
+ */
+ SkMatrix& setSkewX(SkScalar v) { return this->set(kMSkewX, v); }
+
+ /** Sets horizontal translation.
+
+ @param v horizontal translation to store
+ */
+ SkMatrix& setTranslateX(SkScalar v) { return this->set(kMTransX, v); }
+
+ /** Sets vertical translation.
+
+ @param v vertical translation to store
+ */
+ SkMatrix& setTranslateY(SkScalar v) { return this->set(kMTransY, v); }
+
+ /** Sets input x-axis perspective factor, which causes mapXY() to vary input x-axis values
+ inversely proportional to input y-axis values.
+
+ @param v perspective factor
+ */
+ SkMatrix& setPerspX(SkScalar v) { return this->set(kMPersp0, v); }
+
+ /** Sets input y-axis perspective factor, which causes mapXY() to vary input y-axis values
+ inversely proportional to input x-axis values.
+
+ @param v perspective factor
+ */
+ SkMatrix& setPerspY(SkScalar v) { return this->set(kMPersp1, v); }
+
+ /** Sets all values from parameters. Sets matrix to:
+
+ | scaleX skewX transX |
+ | skewY scaleY transY |
+ | persp0 persp1 persp2 |
+
+ @param scaleX horizontal scale factor to store
+ @param skewX horizontal skew factor to store
+ @param transX horizontal translation to store
+ @param skewY vertical skew factor to store
+ @param scaleY vertical scale factor to store
+ @param transY vertical translation to store
+ @param persp0 input x-axis values perspective factor to store
+ @param persp1 input y-axis values perspective factor to store
+ @param persp2 perspective scale factor to store
+ */
+ SkMatrix& setAll(SkScalar scaleX, SkScalar skewX, SkScalar transX,
+ SkScalar skewY, SkScalar scaleY, SkScalar transY,
+ SkScalar persp0, SkScalar persp1, SkScalar persp2) {
+ fMat[kMScaleX] = scaleX;
+ fMat[kMSkewX] = skewX;
+ fMat[kMTransX] = transX;
+ fMat[kMSkewY] = skewY;
+ fMat[kMScaleY] = scaleY;
+ fMat[kMTransY] = transY;
+ fMat[kMPersp0] = persp0;
+ fMat[kMPersp1] = persp1;
+ fMat[kMPersp2] = persp2;
+ this->setTypeMask(kUnknown_Mask);
+ return *this;
+ }
+
+ /** Copies nine scalar values contained by SkMatrix into buffer, in member value
+ ascending order: kMScaleX, kMSkewX, kMTransX, kMSkewY, kMScaleY, kMTransY,
+ kMPersp0, kMPersp1, kMPersp2.
+
+ @param buffer storage for nine scalar values
+ */
+ void get9(SkScalar buffer[9]) const {
+ memcpy(buffer, fMat, 9 * sizeof(SkScalar));
+ }
+
+ /** Sets SkMatrix to nine scalar values in buffer, in member value ascending order:
+ kMScaleX, kMSkewX, kMTransX, kMSkewY, kMScaleY, kMTransY, kMPersp0, kMPersp1,
+ kMPersp2.
+
+ Sets matrix to:
+
+ | buffer[0] buffer[1] buffer[2] |
+ | buffer[3] buffer[4] buffer[5] |
+ | buffer[6] buffer[7] buffer[8] |
+
+ In the future, set9 followed by get9 may not return the same values. Since SkMatrix
+ maps non-homogeneous coordinates, scaling all nine values produces an equivalent
+ transformation, possibly improving precision.
+
+ @param buffer nine scalar values
+ */
+ SkMatrix& set9(const SkScalar buffer[9]);
+
+ /** Sets SkMatrix to identity; which has no effect on mapped SkPoint. Sets SkMatrix to:
+
+ | 1 0 0 |
+ | 0 1 0 |
+ | 0 0 1 |
+
+ Also called setIdentity(); use the one that provides better inline
+ documentation.
+ */
+ SkMatrix& reset();
+
+ /** Sets SkMatrix to identity; which has no effect on mapped SkPoint. Sets SkMatrix to:
+
+ | 1 0 0 |
+ | 0 1 0 |
+ | 0 0 1 |
+
+ Also called reset(); use the one that provides better inline
+ documentation.
+ */
+ SkMatrix& setIdentity() { return this->reset(); }
+
+ /** Sets SkMatrix to translate by (dx, dy).
+
+ @param dx horizontal translation
+ @param dy vertical translation
+ */
+ SkMatrix& setTranslate(SkScalar dx, SkScalar dy);
+
+ /** Sets SkMatrix to translate by (v.fX, v.fY).
+
+ @param v vector containing horizontal and vertical translation
+ */
+ SkMatrix& setTranslate(const SkVector& v) { return this->setTranslate(v.fX, v.fY); }
+
+ /** Sets SkMatrix to scale by sx and sy, about a pivot point at (px, py).
+ The pivot point is unchanged when mapped with SkMatrix.
+
+ @param sx horizontal scale factor
+ @param sy vertical scale factor
+ @param px pivot on x-axis
+ @param py pivot on y-axis
+ */
+ SkMatrix& setScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py);
+
+ /** Sets SkMatrix to scale by sx and sy about at pivot point at (0, 0).
+
+ @param sx horizontal scale factor
+ @param sy vertical scale factor
+ */
+ SkMatrix& setScale(SkScalar sx, SkScalar sy);
+
+ /** Sets SkMatrix to rotate by degrees about a pivot point at (px, py).
+ The pivot point is unchanged when mapped with SkMatrix.
+
+ Positive degrees rotates clockwise.
+
+ @param degrees angle of axes relative to upright axes
+ @param px pivot on x-axis
+ @param py pivot on y-axis
+ */
+ SkMatrix& setRotate(SkScalar degrees, SkScalar px, SkScalar py);
+
+ /** Sets SkMatrix to rotate by degrees about a pivot point at (0, 0).
+ Positive degrees rotates clockwise.
+
+ @param degrees angle of axes relative to upright axes
+ */
+ SkMatrix& setRotate(SkScalar degrees);
+
+ /** Sets SkMatrix to rotate by sinValue and cosValue, about a pivot point at (px, py).
+ The pivot point is unchanged when mapped with SkMatrix.
+
+ Vector (sinValue, cosValue) describes the angle of rotation relative to (0, 1).
+ Vector length specifies scale.
+
+ @param sinValue rotation vector x-axis component
+ @param cosValue rotation vector y-axis component
+ @param px pivot on x-axis
+ @param py pivot on y-axis
+ */
+ SkMatrix& setSinCos(SkScalar sinValue, SkScalar cosValue,
+ SkScalar px, SkScalar py);
+
+ /** Sets SkMatrix to rotate by sinValue and cosValue, about a pivot point at (0, 0).
+
+ Vector (sinValue, cosValue) describes the angle of rotation relative to (0, 1).
+ Vector length specifies scale.
+
+ @param sinValue rotation vector x-axis component
+ @param cosValue rotation vector y-axis component
+ */
+ SkMatrix& setSinCos(SkScalar sinValue, SkScalar cosValue);
+
+ /** Sets SkMatrix to rotate, scale, and translate using a compressed matrix form.
+
+ Vector (rsxForm.fSSin, rsxForm.fSCos) describes the angle of rotation relative
+ to (0, 1). Vector length specifies scale. Mapped point is rotated and scaled
+ by vector, then translated by (rsxForm.fTx, rsxForm.fTy).
+
+ @param rsxForm compressed SkRSXform matrix
+ @return reference to SkMatrix
+
+ example: https://fiddle.skia.org/c/@Matrix_setRSXform
+ */
+ SkMatrix& setRSXform(const SkRSXform& rsxForm);
+
+ /** Sets SkMatrix to skew by kx and ky, about a pivot point at (px, py).
+ The pivot point is unchanged when mapped with SkMatrix.
+
+ @param kx horizontal skew factor
+ @param ky vertical skew factor
+ @param px pivot on x-axis
+ @param py pivot on y-axis
+ */
+ SkMatrix& setSkew(SkScalar kx, SkScalar ky, SkScalar px, SkScalar py);
+
+ /** Sets SkMatrix to skew by kx and ky, about a pivot point at (0, 0).
+
+ @param kx horizontal skew factor
+ @param ky vertical skew factor
+ */
+ SkMatrix& setSkew(SkScalar kx, SkScalar ky);
+
+ /** Sets SkMatrix to SkMatrix a multiplied by SkMatrix b. Either a or b may be this.
+
+ Given:
+
+ | A B C | | J K L |
+ a = | D E F |, b = | M N O |
+ | G H I | | P Q R |
+
+ sets SkMatrix to:
+
+ | A B C | | J K L | | AJ+BM+CP AK+BN+CQ AL+BO+CR |
+ a * b = | D E F | * | M N O | = | DJ+EM+FP DK+EN+FQ DL+EO+FR |
+ | G H I | | P Q R | | GJ+HM+IP GK+HN+IQ GL+HO+IR |
+
+ @param a SkMatrix on left side of multiply expression
+ @param b SkMatrix on right side of multiply expression
+ */
+ SkMatrix& setConcat(const SkMatrix& a, const SkMatrix& b);
+
+ /** Sets SkMatrix to SkMatrix multiplied by SkMatrix constructed from translation (dx, dy).
+ This can be thought of as moving the point to be mapped before applying SkMatrix.
+
+ Given:
+
+ | A B C | | 1 0 dx |
+ Matrix = | D E F |, T(dx, dy) = | 0 1 dy |
+ | G H I | | 0 0 1 |
+
+ sets SkMatrix to:
+
+ | A B C | | 1 0 dx | | A B A*dx+B*dy+C |
+ Matrix * T(dx, dy) = | D E F | | 0 1 dy | = | D E D*dx+E*dy+F |
+ | G H I | | 0 0 1 | | G H G*dx+H*dy+I |
+
+ @param dx x-axis translation before applying SkMatrix
+ @param dy y-axis translation before applying SkMatrix
+ */
+ SkMatrix& preTranslate(SkScalar dx, SkScalar dy);
+
+ /** Sets SkMatrix to SkMatrix multiplied by SkMatrix constructed from scaling by (sx, sy)
+ about pivot point (px, py).
+ This can be thought of as scaling about a pivot point before applying SkMatrix.
+
+ Given:
+
+ | A B C | | sx 0 dx |
+ Matrix = | D E F |, S(sx, sy, px, py) = | 0 sy dy |
+ | G H I | | 0 0 1 |
+
+ where
+
+ dx = px - sx * px
+ dy = py - sy * py
+
+ sets SkMatrix to:
+
+ | A B C | | sx 0 dx | | A*sx B*sy A*dx+B*dy+C |
+ Matrix * S(sx, sy, px, py) = | D E F | | 0 sy dy | = | D*sx E*sy D*dx+E*dy+F |
+ | G H I | | 0 0 1 | | G*sx H*sy G*dx+H*dy+I |
+
+ @param sx horizontal scale factor
+ @param sy vertical scale factor
+ @param px pivot on x-axis
+ @param py pivot on y-axis
+ */
+ SkMatrix& preScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py);
+
+ /** Sets SkMatrix to SkMatrix multiplied by SkMatrix constructed from scaling by (sx, sy)
+ about pivot point (0, 0).
+ This can be thought of as scaling about the origin before applying SkMatrix.
+
+ Given:
+
+ | A B C | | sx 0 0 |
+ Matrix = | D E F |, S(sx, sy) = | 0 sy 0 |
+ | G H I | | 0 0 1 |
+
+ sets SkMatrix to:
+
+ | A B C | | sx 0 0 | | A*sx B*sy C |
+ Matrix * S(sx, sy) = | D E F | | 0 sy 0 | = | D*sx E*sy F |
+ | G H I | | 0 0 1 | | G*sx H*sy I |
+
+ @param sx horizontal scale factor
+ @param sy vertical scale factor
+ */
+ SkMatrix& preScale(SkScalar sx, SkScalar sy);
+
+ /** Sets SkMatrix to SkMatrix multiplied by SkMatrix constructed from rotating by degrees
+ about pivot point (px, py).
+ This can be thought of as rotating about a pivot point before applying SkMatrix.
+
+ Positive degrees rotates clockwise.
+
+ Given:
+
+ | A B C | | c -s dx |
+ Matrix = | D E F |, R(degrees, px, py) = | s c dy |
+ | G H I | | 0 0 1 |
+
+ where
+
+ c = cos(degrees)
+ s = sin(degrees)
+ dx = s * py + (1 - c) * px
+ dy = -s * px + (1 - c) * py
+
+ sets SkMatrix to:
+
+ | A B C | | c -s dx | | Ac+Bs -As+Bc A*dx+B*dy+C |
+ Matrix * R(degrees, px, py) = | D E F | | s c dy | = | Dc+Es -Ds+Ec D*dx+E*dy+F |
+ | G H I | | 0 0 1 | | Gc+Hs -Gs+Hc G*dx+H*dy+I |
+
+ @param degrees angle of axes relative to upright axes
+ @param px pivot on x-axis
+ @param py pivot on y-axis
+ */
+ SkMatrix& preRotate(SkScalar degrees, SkScalar px, SkScalar py);
+
+ /** Sets SkMatrix to SkMatrix multiplied by SkMatrix constructed from rotating by degrees
+ about pivot point (0, 0).
+ This can be thought of as rotating about the origin before applying SkMatrix.
+
+ Positive degrees rotates clockwise.
+
+ Given:
+
+ | A B C | | c -s 0 |
+ Matrix = | D E F |, R(degrees, px, py) = | s c 0 |
+ | G H I | | 0 0 1 |
+
+ where
+
+ c = cos(degrees)
+ s = sin(degrees)
+
+ sets SkMatrix to:
+
+ | A B C | | c -s 0 | | Ac+Bs -As+Bc C |
+ Matrix * R(degrees, px, py) = | D E F | | s c 0 | = | Dc+Es -Ds+Ec F |
+ | G H I | | 0 0 1 | | Gc+Hs -Gs+Hc I |
+
+ @param degrees angle of axes relative to upright axes
+ */
+ SkMatrix& preRotate(SkScalar degrees);
+
+ /** Sets SkMatrix to SkMatrix multiplied by SkMatrix constructed from skewing by (kx, ky)
+ about pivot point (px, py).
+ This can be thought of as skewing about a pivot point before applying SkMatrix.
+
+ Given:
+
+ | A B C | | 1 kx dx |
+ Matrix = | D E F |, K(kx, ky, px, py) = | ky 1 dy |
+ | G H I | | 0 0 1 |
+
+ where
+
+ dx = -kx * py
+ dy = -ky * px
+
+ sets SkMatrix to:
+
+ | A B C | | 1 kx dx | | A+B*ky A*kx+B A*dx+B*dy+C |
+ Matrix * K(kx, ky, px, py) = | D E F | | ky 1 dy | = | D+E*ky D*kx+E D*dx+E*dy+F |
+ | G H I | | 0 0 1 | | G+H*ky G*kx+H G*dx+H*dy+I |
+
+ @param kx horizontal skew factor
+ @param ky vertical skew factor
+ @param px pivot on x-axis
+ @param py pivot on y-axis
+ */
+ SkMatrix& preSkew(SkScalar kx, SkScalar ky, SkScalar px, SkScalar py);
+
+ /** Sets SkMatrix to SkMatrix multiplied by SkMatrix constructed from skewing by (kx, ky)
+ about pivot point (0, 0).
+ This can be thought of as skewing about the origin before applying SkMatrix.
+
+ Given:
+
+ | A B C | | 1 kx 0 |
+ Matrix = | D E F |, K(kx, ky) = | ky 1 0 |
+ | G H I | | 0 0 1 |
+
+ sets SkMatrix to:
+
+ | A B C | | 1 kx 0 | | A+B*ky A*kx+B C |
+ Matrix * K(kx, ky) = | D E F | | ky 1 0 | = | D+E*ky D*kx+E F |
+ | G H I | | 0 0 1 | | G+H*ky G*kx+H I |
+
+ @param kx horizontal skew factor
+ @param ky vertical skew factor
+ */
+ SkMatrix& preSkew(SkScalar kx, SkScalar ky);
+
+ /** Sets SkMatrix to SkMatrix multiplied by SkMatrix other.
+ This can be thought of mapping by other before applying SkMatrix.
+
+ Given:
+
+ | A B C | | J K L |
+ Matrix = | D E F |, other = | M N O |
+ | G H I | | P Q R |
+
+ sets SkMatrix to:
+
+ | A B C | | J K L | | AJ+BM+CP AK+BN+CQ AL+BO+CR |
+ Matrix * other = | D E F | * | M N O | = | DJ+EM+FP DK+EN+FQ DL+EO+FR |
+ | G H I | | P Q R | | GJ+HM+IP GK+HN+IQ GL+HO+IR |
+
+ @param other SkMatrix on right side of multiply expression
+ */
+ SkMatrix& preConcat(const SkMatrix& other);
+
+ /** Sets SkMatrix to SkMatrix constructed from translation (dx, dy) multiplied by SkMatrix.
+ This can be thought of as moving the point to be mapped after applying SkMatrix.
+
+ Given:
+
+ | J K L | | 1 0 dx |
+ Matrix = | M N O |, T(dx, dy) = | 0 1 dy |
+ | P Q R | | 0 0 1 |
+
+ sets SkMatrix to:
+
+ | 1 0 dx | | J K L | | J+dx*P K+dx*Q L+dx*R |
+ T(dx, dy) * Matrix = | 0 1 dy | | M N O | = | M+dy*P N+dy*Q O+dy*R |
+ | 0 0 1 | | P Q R | | P Q R |
+
+ @param dx x-axis translation after applying SkMatrix
+ @param dy y-axis translation after applying SkMatrix
+ */
+ SkMatrix& postTranslate(SkScalar dx, SkScalar dy);
+
+ /** Sets SkMatrix to SkMatrix constructed from scaling by (sx, sy) about pivot point
+ (px, py), multiplied by SkMatrix.
+ This can be thought of as scaling about a pivot point after applying SkMatrix.
+
+ Given:
+
+ | J K L | | sx 0 dx |
+ Matrix = | M N O |, S(sx, sy, px, py) = | 0 sy dy |
+ | P Q R | | 0 0 1 |
+
+ where
+
+ dx = px - sx * px
+ dy = py - sy * py
+
+ sets SkMatrix to:
+
+ | sx 0 dx | | J K L | | sx*J+dx*P sx*K+dx*Q sx*L+dx+R |
+ S(sx, sy, px, py) * Matrix = | 0 sy dy | | M N O | = | sy*M+dy*P sy*N+dy*Q sy*O+dy*R |
+ | 0 0 1 | | P Q R | | P Q R |
+
+ @param sx horizontal scale factor
+ @param sy vertical scale factor
+ @param px pivot on x-axis
+ @param py pivot on y-axis
+ */
+ SkMatrix& postScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py);
+
+ /** Sets SkMatrix to SkMatrix constructed from scaling by (sx, sy) about pivot point
+ (0, 0), multiplied by SkMatrix.
+ This can be thought of as scaling about the origin after applying SkMatrix.
+
+ Given:
+
+ | J K L | | sx 0 0 |
+ Matrix = | M N O |, S(sx, sy) = | 0 sy 0 |
+ | P Q R | | 0 0 1 |
+
+ sets SkMatrix to:
+
+ | sx 0 0 | | J K L | | sx*J sx*K sx*L |
+ S(sx, sy) * Matrix = | 0 sy 0 | | M N O | = | sy*M sy*N sy*O |
+ | 0 0 1 | | P Q R | | P Q R |
+
+ @param sx horizontal scale factor
+ @param sy vertical scale factor
+ */
+ SkMatrix& postScale(SkScalar sx, SkScalar sy);
+
+ /** Sets SkMatrix to SkMatrix constructed from rotating by degrees about pivot point
+ (px, py), multiplied by SkMatrix.
+ This can be thought of as rotating about a pivot point after applying SkMatrix.
+
+ Positive degrees rotates clockwise.
+
+ Given:
+
+ | J K L | | c -s dx |
+ Matrix = | M N O |, R(degrees, px, py) = | s c dy |
+ | P Q R | | 0 0 1 |
+
+ where
+
+ c = cos(degrees)
+ s = sin(degrees)
+ dx = s * py + (1 - c) * px
+ dy = -s * px + (1 - c) * py
+
+ sets SkMatrix to:
+
+ |c -s dx| |J K L| |cJ-sM+dx*P cK-sN+dx*Q cL-sO+dx+R|
+ R(degrees, px, py) * Matrix = |s c dy| |M N O| = |sJ+cM+dy*P sK+cN+dy*Q sL+cO+dy*R|
+ |0 0 1| |P Q R| | P Q R|
+
+ @param degrees angle of axes relative to upright axes
+ @param px pivot on x-axis
+ @param py pivot on y-axis
+ */
+ SkMatrix& postRotate(SkScalar degrees, SkScalar px, SkScalar py);
+
+ /** Sets SkMatrix to SkMatrix constructed from rotating by degrees about pivot point
+ (0, 0), multiplied by SkMatrix.
+ This can be thought of as rotating about the origin after applying SkMatrix.
+
+ Positive degrees rotates clockwise.
+
+ Given:
+
+ | J K L | | c -s 0 |
+ Matrix = | M N O |, R(degrees, px, py) = | s c 0 |
+ | P Q R | | 0 0 1 |
+
+ where
+
+ c = cos(degrees)
+ s = sin(degrees)
+
+ sets SkMatrix to:
+
+ | c -s dx | | J K L | | cJ-sM cK-sN cL-sO |
+ R(degrees, px, py) * Matrix = | s c dy | | M N O | = | sJ+cM sK+cN sL+cO |
+ | 0 0 1 | | P Q R | | P Q R |
+
+ @param degrees angle of axes relative to upright axes
+ */
+ SkMatrix& postRotate(SkScalar degrees);
+
+ /** Sets SkMatrix to SkMatrix constructed from skewing by (kx, ky) about pivot point
+ (px, py), multiplied by SkMatrix.
+ This can be thought of as skewing about a pivot point after applying SkMatrix.
+
+ Given:
+
+ | J K L | | 1 kx dx |
+ Matrix = | M N O |, K(kx, ky, px, py) = | ky 1 dy |
+ | P Q R | | 0 0 1 |
+
+ where
+
+ dx = -kx * py
+ dy = -ky * px
+
+ sets SkMatrix to:
+
+ | 1 kx dx| |J K L| |J+kx*M+dx*P K+kx*N+dx*Q L+kx*O+dx+R|
+ K(kx, ky, px, py) * Matrix = |ky 1 dy| |M N O| = |ky*J+M+dy*P ky*K+N+dy*Q ky*L+O+dy*R|
+ | 0 0 1| |P Q R| | P Q R|
+
+ @param kx horizontal skew factor
+ @param ky vertical skew factor
+ @param px pivot on x-axis
+ @param py pivot on y-axis
+ */
+ SkMatrix& postSkew(SkScalar kx, SkScalar ky, SkScalar px, SkScalar py);
+
+ /** Sets SkMatrix to SkMatrix constructed from skewing by (kx, ky) about pivot point
+ (0, 0), multiplied by SkMatrix.
+ This can be thought of as skewing about the origin after applying SkMatrix.
+
+ Given:
+
+ | J K L | | 1 kx 0 |
+ Matrix = | M N O |, K(kx, ky) = | ky 1 0 |
+ | P Q R | | 0 0 1 |
+
+ sets SkMatrix to:
+
+ | 1 kx 0 | | J K L | | J+kx*M K+kx*N L+kx*O |
+ K(kx, ky) * Matrix = | ky 1 0 | | M N O | = | ky*J+M ky*K+N ky*L+O |
+ | 0 0 1 | | P Q R | | P Q R |
+
+ @param kx horizontal skew factor
+ @param ky vertical skew factor
+ */
+ SkMatrix& postSkew(SkScalar kx, SkScalar ky);
+
+ /** Sets SkMatrix to SkMatrix other multiplied by SkMatrix.
+ This can be thought of mapping by other after applying SkMatrix.
+
+ Given:
+
+ | J K L | | A B C |
+ Matrix = | M N O |, other = | D E F |
+ | P Q R | | G H I |
+
+ sets SkMatrix to:
+
+ | A B C | | J K L | | AJ+BM+CP AK+BN+CQ AL+BO+CR |
+ other * Matrix = | D E F | * | M N O | = | DJ+EM+FP DK+EN+FQ DL+EO+FR |
+ | G H I | | P Q R | | GJ+HM+IP GK+HN+IQ GL+HO+IR |
+
+ @param other SkMatrix on left side of multiply expression
+ */
+ SkMatrix& postConcat(const SkMatrix& other);
+
+#ifndef SK_SUPPORT_LEGACY_MATRIX_RECTTORECT
+private:
+#endif
+ /** Sets SkMatrix to scale and translate src SkRect to dst SkRect. stf selects whether
+ mapping completely fills dst or preserves the aspect ratio, and how to align
+ src within dst. Returns false if src is empty, and sets SkMatrix to identity.
+ Returns true if dst is empty, and sets SkMatrix to:
+
+ | 0 0 0 |
+ | 0 0 0 |
+ | 0 0 1 |
+
+ @param src SkRect to map from
+ @param dst SkRect to map to
+ @return true if SkMatrix can represent SkRect mapping
+
+ example: https://fiddle.skia.org/c/@Matrix_setRectToRect
+ */
+ bool setRectToRect(const SkRect& src, const SkRect& dst, ScaleToFit stf);
+
+ /** Returns SkMatrix set to scale and translate src SkRect to dst SkRect. stf selects
+ whether mapping completely fills dst or preserves the aspect ratio, and how to
+ align src within dst. Returns the identity SkMatrix if src is empty. If dst is
+ empty, returns SkMatrix set to:
+
+ | 0 0 0 |
+ | 0 0 0 |
+ | 0 0 1 |
+
+ @param src SkRect to map from
+ @param dst SkRect to map to
+ @return SkMatrix mapping src to dst
+ */
+ static SkMatrix MakeRectToRect(const SkRect& src, const SkRect& dst, ScaleToFit stf) {
+ SkMatrix m;
+ m.setRectToRect(src, dst, stf);
+ return m;
+ }
+#ifndef SK_SUPPORT_LEGACY_MATRIX_RECTTORECT
+public:
+#endif
+
+ /** Sets SkMatrix to map src to dst. count must be zero or greater, and four or less.
+
+ If count is zero, sets SkMatrix to identity and returns true.
+ If count is one, sets SkMatrix to translate and returns true.
+ If count is two or more, sets SkMatrix to map SkPoint if possible; returns false
+ if SkMatrix cannot be constructed. If count is four, SkMatrix may include
+ perspective.
+
+ @param src SkPoint to map from
+ @param dst SkPoint to map to
+ @param count number of SkPoint in src and dst
+ @return true if SkMatrix was constructed successfully
+
+ example: https://fiddle.skia.org/c/@Matrix_setPolyToPoly
+ */
+ bool setPolyToPoly(const SkPoint src[], const SkPoint dst[], int count);
+
+ /** Sets inverse to reciprocal matrix, returning true if SkMatrix can be inverted.
+ Geometrically, if SkMatrix maps from source to destination, inverse SkMatrix
+ maps from destination to source. If SkMatrix can not be inverted, inverse is
+ unchanged.
+
+ @param inverse storage for inverted SkMatrix; may be nullptr
+ @return true if SkMatrix can be inverted
+ */
+ bool SK_WARN_UNUSED_RESULT invert(SkMatrix* inverse) const {
+ // Allow the trivial case to be inlined.
+ if (this->isIdentity()) {
+ if (inverse) {
+ inverse->reset();
+ }
+ return true;
+ }
+ return this->invertNonIdentity(inverse);
+ }
+
+ /** Fills affine with identity values in column major order.
+ Sets affine to:
+
+ | 1 0 0 |
+ | 0 1 0 |
+
+ Affine 3 by 2 matrices in column major order are used by OpenGL and XPS.
+
+ @param affine storage for 3 by 2 affine matrix
+
+ example: https://fiddle.skia.org/c/@Matrix_SetAffineIdentity
+ */
+ static void SetAffineIdentity(SkScalar affine[6]);
+
+ /** Fills affine in column major order. Sets affine to:
+
+ | scale-x skew-x translate-x |
+ | skew-y scale-y translate-y |
+
+ If SkMatrix contains perspective, returns false and leaves affine unchanged.
+
+ @param affine storage for 3 by 2 affine matrix; may be nullptr
+ @return true if SkMatrix does not contain perspective
+ */
+ bool SK_WARN_UNUSED_RESULT asAffine(SkScalar affine[6]) const;
+
+ /** Sets SkMatrix to affine values, passed in column major order. Given affine,
+ column, then row, as:
+
+ | scale-x skew-x translate-x |
+ | skew-y scale-y translate-y |
+
+ SkMatrix is set, row, then column, to:
+
+ | scale-x skew-x translate-x |
+ | skew-y scale-y translate-y |
+ | 0 0 1 |
+
+ @param affine 3 by 2 affine matrix
+ */
+ SkMatrix& setAffine(const SkScalar affine[6]);
+
+ /**
+ * A matrix is categorized as 'perspective' if the bottom row is not [0, 0, 1].
+ * However, for most uses (e.g. mapPoints) a bottom row of [0, 0, X] behaves like a
+ * non-perspective matrix, though it will be categorized as perspective. Calling
+ * normalizePerspective() will change the matrix such that, if its bottom row was [0, 0, X],
+ * it will be changed to [0, 0, 1] by scaling the rest of the matrix by 1/X.
+ *
+ * | A B C | | A/X B/X C/X |
+ * | D E F | -> | D/X E/X F/X | for X != 0
+ * | 0 0 X | | 0 0 1 |
+ */
+ void normalizePerspective() {
+ if (fMat[8] != 1) {
+ this->doNormalizePerspective();
+ }
+ }
+
+ /** Maps src SkPoint array of length count to dst SkPoint array of equal or greater
+ length. SkPoint are mapped by multiplying each SkPoint by SkMatrix. Given:
+
+ | A B C | | x |
+ Matrix = | D E F |, pt = | y |
+ | G H I | | 1 |
+
+ where
+
+ for (i = 0; i < count; ++i) {
+ x = src[i].fX
+ y = src[i].fY
+ }
+
+ each dst SkPoint is computed as:
+
+ |A B C| |x| Ax+By+C Dx+Ey+F
+ Matrix * pt = |D E F| |y| = |Ax+By+C Dx+Ey+F Gx+Hy+I| = ------- , -------
+ |G H I| |1| Gx+Hy+I Gx+Hy+I
+
+ src and dst may point to the same storage.
+
+ @param dst storage for mapped SkPoint
+ @param src SkPoint to transform
+ @param count number of SkPoint to transform
+
+ example: https://fiddle.skia.org/c/@Matrix_mapPoints
+ */
+ void mapPoints(SkPoint dst[], const SkPoint src[], int count) const;
+
+ /** Maps pts SkPoint array of length count in place. SkPoint are mapped by multiplying
+ each SkPoint by SkMatrix. Given:
+
+ | A B C | | x |
+ Matrix = | D E F |, pt = | y |
+ | G H I | | 1 |
+
+ where
+
+ for (i = 0; i < count; ++i) {
+ x = pts[i].fX
+ y = pts[i].fY
+ }
+
+ each resulting pts SkPoint is computed as:
+
+ |A B C| |x| Ax+By+C Dx+Ey+F
+ Matrix * pt = |D E F| |y| = |Ax+By+C Dx+Ey+F Gx+Hy+I| = ------- , -------
+ |G H I| |1| Gx+Hy+I Gx+Hy+I
+
+ @param pts storage for mapped SkPoint
+ @param count number of SkPoint to transform
+ */
+ void mapPoints(SkPoint pts[], int count) const {
+ this->mapPoints(pts, pts, count);
+ }
+
+ /** Maps src SkPoint3 array of length count to dst SkPoint3 array, which must of length count or
+ greater. SkPoint3 array is mapped by multiplying each SkPoint3 by SkMatrix. Given:
+
+ | A B C | | x |
+ Matrix = | D E F |, src = | y |
+ | G H I | | z |
+
+ each resulting dst SkPoint is computed as:
+
+ |A B C| |x|
+ Matrix * src = |D E F| |y| = |Ax+By+Cz Dx+Ey+Fz Gx+Hy+Iz|
+ |G H I| |z|
+
+ @param dst storage for mapped SkPoint3 array
+ @param src SkPoint3 array to transform
+ @param count items in SkPoint3 array to transform
+
+ example: https://fiddle.skia.org/c/@Matrix_mapHomogeneousPoints
+ */
+ void mapHomogeneousPoints(SkPoint3 dst[], const SkPoint3 src[], int count) const;
+
+ /**
+ * Returns homogeneous points, starting with 2D src points (with implied w = 1).
+ */
+ void mapHomogeneousPoints(SkPoint3 dst[], const SkPoint src[], int count) const;
+
+ /** Returns SkPoint pt multiplied by SkMatrix. Given:
+
+ | A B C | | x |
+ Matrix = | D E F |, pt = | y |
+ | G H I | | 1 |
+
+ result is computed as:
+
+ |A B C| |x| Ax+By+C Dx+Ey+F
+ Matrix * pt = |D E F| |y| = |Ax+By+C Dx+Ey+F Gx+Hy+I| = ------- , -------
+ |G H I| |1| Gx+Hy+I Gx+Hy+I
+
+ @param p SkPoint to map
+ @return mapped SkPoint
+ */
+ SkPoint mapPoint(SkPoint pt) const {
+ SkPoint result;
+ this->mapXY(pt.x(), pt.y(), &result);
+ return result;
+ }
+
+ /** Maps SkPoint (x, y) to result. SkPoint is mapped by multiplying by SkMatrix. Given:
+
+ | A B C | | x |
+ Matrix = | D E F |, pt = | y |
+ | G H I | | 1 |
+
+ result is computed as:
+
+ |A B C| |x| Ax+By+C Dx+Ey+F
+ Matrix * pt = |D E F| |y| = |Ax+By+C Dx+Ey+F Gx+Hy+I| = ------- , -------
+ |G H I| |1| Gx+Hy+I Gx+Hy+I
+
+ @param x x-axis value of SkPoint to map
+ @param y y-axis value of SkPoint to map
+ @param result storage for mapped SkPoint
+
+ example: https://fiddle.skia.org/c/@Matrix_mapXY
+ */
+ void mapXY(SkScalar x, SkScalar y, SkPoint* result) const;
+
+ /** Returns SkPoint (x, y) multiplied by SkMatrix. Given:
+
+ | A B C | | x |
+ Matrix = | D E F |, pt = | y |
+ | G H I | | 1 |
+
+ result is computed as:
+
+ |A B C| |x| Ax+By+C Dx+Ey+F
+ Matrix * pt = |D E F| |y| = |Ax+By+C Dx+Ey+F Gx+Hy+I| = ------- , -------
+ |G H I| |1| Gx+Hy+I Gx+Hy+I
+
+ @param x x-axis value of SkPoint to map
+ @param y y-axis value of SkPoint to map
+ @return mapped SkPoint
+ */
+ SkPoint mapXY(SkScalar x, SkScalar y) const {
+ SkPoint result;
+ this->mapXY(x,y, &result);
+ return result;
+ }
+
+
+ /** Returns (0, 0) multiplied by SkMatrix. Given:
+
+ | A B C | | 0 |
+ Matrix = | D E F |, pt = | 0 |
+ | G H I | | 1 |
+
+ result is computed as:
+
+ |A B C| |0| C F
+ Matrix * pt = |D E F| |0| = |C F I| = - , -
+ |G H I| |1| I I
+
+ @return mapped (0, 0)
+ */
+ SkPoint mapOrigin() const {
+ SkScalar x = this->getTranslateX(),
+ y = this->getTranslateY();
+ if (this->hasPerspective()) {
+ SkScalar w = fMat[kMPersp2];
+ if (w) { w = 1 / w; }
+ x *= w;
+ y *= w;
+ }
+ return {x, y};
+ }
+
+ /** Maps src vector array of length count to vector SkPoint array of equal or greater
+ length. Vectors are mapped by multiplying each vector by SkMatrix, treating
+ SkMatrix translation as zero. Given:
+
+ | A B 0 | | x |
+ Matrix = | D E 0 |, src = | y |
+ | G H I | | 1 |
+
+ where
+
+ for (i = 0; i < count; ++i) {
+ x = src[i].fX
+ y = src[i].fY
+ }
+
+ each dst vector is computed as:
+
+ |A B 0| |x| Ax+By Dx+Ey
+ Matrix * src = |D E 0| |y| = |Ax+By Dx+Ey Gx+Hy+I| = ------- , -------
+ |G H I| |1| Gx+Hy+I Gx+Hy+I
+
+ src and dst may point to the same storage.
+
+ @param dst storage for mapped vectors
+ @param src vectors to transform
+ @param count number of vectors to transform
+
+ example: https://fiddle.skia.org/c/@Matrix_mapVectors
+ */
+ void mapVectors(SkVector dst[], const SkVector src[], int count) const;
+
+ /** Maps vecs vector array of length count in place, multiplying each vector by
+ SkMatrix, treating SkMatrix translation as zero. Given:
+
+ | A B 0 | | x |
+ Matrix = | D E 0 |, vec = | y |
+ | G H I | | 1 |
+
+ where
+
+ for (i = 0; i < count; ++i) {
+ x = vecs[i].fX
+ y = vecs[i].fY
+ }
+
+ each result vector is computed as:
+
+ |A B 0| |x| Ax+By Dx+Ey
+ Matrix * vec = |D E 0| |y| = |Ax+By Dx+Ey Gx+Hy+I| = ------- , -------
+ |G H I| |1| Gx+Hy+I Gx+Hy+I
+
+ @param vecs vectors to transform, and storage for mapped vectors
+ @param count number of vectors to transform
+ */
+ void mapVectors(SkVector vecs[], int count) const {
+ this->mapVectors(vecs, vecs, count);
+ }
+
+ /** Maps vector (dx, dy) to result. Vector is mapped by multiplying by SkMatrix,
+ treating SkMatrix translation as zero. Given:
+
+ | A B 0 | | dx |
+ Matrix = | D E 0 |, vec = | dy |
+ | G H I | | 1 |
+
+ each result vector is computed as:
+
+ |A B 0| |dx| A*dx+B*dy D*dx+E*dy
+ Matrix * vec = |D E 0| |dy| = |A*dx+B*dy D*dx+E*dy G*dx+H*dy+I| = ----------- , -----------
+ |G H I| | 1| G*dx+H*dy+I G*dx+*dHy+I
+
+ @param dx x-axis value of vector to map
+ @param dy y-axis value of vector to map
+ @param result storage for mapped vector
+ */
+ void mapVector(SkScalar dx, SkScalar dy, SkVector* result) const {
+ SkVector vec = { dx, dy };
+ this->mapVectors(result, &vec, 1);
+ }
+
+ /** Returns vector (dx, dy) multiplied by SkMatrix, treating SkMatrix translation as zero.
+ Given:
+
+ | A B 0 | | dx |
+ Matrix = | D E 0 |, vec = | dy |
+ | G H I | | 1 |
+
+ each result vector is computed as:
+
+ |A B 0| |dx| A*dx+B*dy D*dx+E*dy
+ Matrix * vec = |D E 0| |dy| = |A*dx+B*dy D*dx+E*dy G*dx+H*dy+I| = ----------- , -----------
+ |G H I| | 1| G*dx+H*dy+I G*dx+*dHy+I
+
+ @param dx x-axis value of vector to map
+ @param dy y-axis value of vector to map
+ @return mapped vector
+ */
+ SkVector mapVector(SkScalar dx, SkScalar dy) const {
+ SkVector vec = { dx, dy };
+ this->mapVectors(&vec, &vec, 1);
+ return vec;
+ }
+
+ /** Sets dst to bounds of src corners mapped by SkMatrix.
+ Returns true if mapped corners are dst corners.
+
+ Returned value is the same as calling rectStaysRect().
+
+ @param dst storage for bounds of mapped SkPoint
+ @param src SkRect to map
+ @param pc whether to apply perspective clipping
+ @return true if dst is equivalent to mapped src
+
+ example: https://fiddle.skia.org/c/@Matrix_mapRect
+ */
+ bool mapRect(SkRect* dst, const SkRect& src,
+ SkApplyPerspectiveClip pc = SkApplyPerspectiveClip::kYes) const;
+
+ /** Sets rect to bounds of rect corners mapped by SkMatrix.
+ Returns true if mapped corners are computed rect corners.
+
+ Returned value is the same as calling rectStaysRect().
+
+ @param rect rectangle to map, and storage for bounds of mapped corners
+ @param pc whether to apply perspective clipping
+ @return true if result is equivalent to mapped rect
+ */
+ bool mapRect(SkRect* rect, SkApplyPerspectiveClip pc = SkApplyPerspectiveClip::kYes) const {
+ return this->mapRect(rect, *rect, pc);
+ }
+
+ /** Returns bounds of src corners mapped by SkMatrix.
+
+ @param src rectangle to map
+ @return mapped bounds
+ */
+ SkRect mapRect(const SkRect& src,
+ SkApplyPerspectiveClip pc = SkApplyPerspectiveClip::kYes) const {
+ SkRect dst;
+ (void)this->mapRect(&dst, src, pc);
+ return dst;
+ }
+
+ /** Maps four corners of rect to dst. SkPoint are mapped by multiplying each
+ rect corner by SkMatrix. rect corner is processed in this order:
+ (rect.fLeft, rect.fTop), (rect.fRight, rect.fTop), (rect.fRight, rect.fBottom),
+ (rect.fLeft, rect.fBottom).
+
+ rect may be empty: rect.fLeft may be greater than or equal to rect.fRight;
+ rect.fTop may be greater than or equal to rect.fBottom.
+
+ Given:
+
+ | A B C | | x |
+ Matrix = | D E F |, pt = | y |
+ | G H I | | 1 |
+
+ where pt is initialized from each of (rect.fLeft, rect.fTop),
+ (rect.fRight, rect.fTop), (rect.fRight, rect.fBottom), (rect.fLeft, rect.fBottom),
+ each dst SkPoint is computed as:
+
+ |A B C| |x| Ax+By+C Dx+Ey+F
+ Matrix * pt = |D E F| |y| = |Ax+By+C Dx+Ey+F Gx+Hy+I| = ------- , -------
+ |G H I| |1| Gx+Hy+I Gx+Hy+I
+
+ @param dst storage for mapped corner SkPoint
+ @param rect SkRect to map
+
+ Note: this does not perform perspective clipping (as that might result in more than
+ 4 points, so results are suspect if the matrix contains perspective.
+ */
+ void mapRectToQuad(SkPoint dst[4], const SkRect& rect) const {
+ // This could potentially be faster if we only transformed each x and y of the rect once.
+ rect.toQuad(dst);
+ this->mapPoints(dst, 4);
+ }
+
+ /** Sets dst to bounds of src corners mapped by SkMatrix. If matrix contains
+ elements other than scale or translate: asserts if SK_DEBUG is defined;
+ otherwise, results are undefined.
+
+ @param dst storage for bounds of mapped SkPoint
+ @param src SkRect to map
+
+ example: https://fiddle.skia.org/c/@Matrix_mapRectScaleTranslate
+ */
+ void mapRectScaleTranslate(SkRect* dst, const SkRect& src) const;
+
+ /** Returns geometric mean radius of ellipse formed by constructing circle of
+ size radius, and mapping constructed circle with SkMatrix. The result squared is
+ equal to the major axis length times the minor axis length.
+ Result is not meaningful if SkMatrix contains perspective elements.
+
+ @param radius circle size to map
+ @return average mapped radius
+
+ example: https://fiddle.skia.org/c/@Matrix_mapRadius
+ */
+ SkScalar mapRadius(SkScalar radius) const;
+
+ /** Compares a and b; returns true if a and b are numerically equal. Returns true
+ even if sign of zero values are different. Returns false if either SkMatrix
+ contains NaN, even if the other SkMatrix also contains NaN.
+
+ @param a SkMatrix to compare
+ @param b SkMatrix to compare
+ @return true if SkMatrix a and SkMatrix b are numerically equal
+ */
+ friend SK_API bool operator==(const SkMatrix& a, const SkMatrix& b);
+
+ /** Compares a and b; returns true if a and b are not numerically equal. Returns false
+ even if sign of zero values are different. Returns true if either SkMatrix
+ contains NaN, even if the other SkMatrix also contains NaN.
+
+ @param a SkMatrix to compare
+ @param b SkMatrix to compare
+ @return true if SkMatrix a and SkMatrix b are numerically not equal
+ */
+ friend SK_API bool operator!=(const SkMatrix& a, const SkMatrix& b) {
+ return !(a == b);
+ }
+
+ /** Writes text representation of SkMatrix to standard output. Floating point values
+ are written with limited precision; it may not be possible to reconstruct
+ original SkMatrix from output.
+
+ example: https://fiddle.skia.org/c/@Matrix_dump
+ */
+ void dump() const;
+
+ /** Returns the minimum scaling factor of SkMatrix by decomposing the scaling and
+ skewing elements.
+ Returns -1 if scale factor overflows or SkMatrix contains perspective.
+
+ @return minimum scale factor
+
+ example: https://fiddle.skia.org/c/@Matrix_getMinScale
+ */
+ SkScalar getMinScale() const;
+
+ /** Returns the maximum scaling factor of SkMatrix by decomposing the scaling and
+ skewing elements.
+ Returns -1 if scale factor overflows or SkMatrix contains perspective.
+
+ @return maximum scale factor
+
+ example: https://fiddle.skia.org/c/@Matrix_getMaxScale
+ */
+ SkScalar getMaxScale() const;
+
+ /** Sets scaleFactors[0] to the minimum scaling factor, and scaleFactors[1] to the
+ maximum scaling factor. Scaling factors are computed by decomposing
+ the SkMatrix scaling and skewing elements.
+
+ Returns true if scaleFactors are found; otherwise, returns false and sets
+ scaleFactors to undefined values.
+
+ @param scaleFactors storage for minimum and maximum scale factors
+ @return true if scale factors were computed correctly
+ */
+ bool SK_WARN_UNUSED_RESULT getMinMaxScales(SkScalar scaleFactors[2]) const;
+
+ /** Decomposes SkMatrix into scale components and whatever remains. Returns false if
+ SkMatrix could not be decomposed.
+
+ Sets scale to portion of SkMatrix that scale axes. Sets remaining to SkMatrix
+ with scaling factored out. remaining may be passed as nullptr
+ to determine if SkMatrix can be decomposed without computing remainder.
+
+ Returns true if scale components are found. scale and remaining are
+ unchanged if SkMatrix contains perspective; scale factors are not finite, or
+ are nearly zero.
+
+ On success: Matrix = Remaining * scale.
+
+ @param scale axes scaling factors; may be nullptr
+ @param remaining SkMatrix without scaling; may be nullptr
+ @return true if scale can be computed
+
+ example: https://fiddle.skia.org/c/@Matrix_decomposeScale
+ */
+ bool decomposeScale(SkSize* scale, SkMatrix* remaining = nullptr) const;
+
+ /** Returns reference to const identity SkMatrix. Returned SkMatrix is set to:
+
+ | 1 0 0 |
+ | 0 1 0 |
+ | 0 0 1 |
+
+ @return const identity SkMatrix
+
+ example: https://fiddle.skia.org/c/@Matrix_I
+ */
+ static const SkMatrix& I();
+
+ /** Returns reference to a const SkMatrix with invalid values. Returned SkMatrix is set
+ to:
+
+ | SK_ScalarMax SK_ScalarMax SK_ScalarMax |
+ | SK_ScalarMax SK_ScalarMax SK_ScalarMax |
+ | SK_ScalarMax SK_ScalarMax SK_ScalarMax |
+
+ @return const invalid SkMatrix
+
+ example: https://fiddle.skia.org/c/@Matrix_InvalidMatrix
+ */
+ static const SkMatrix& InvalidMatrix();
+
+ /** Returns SkMatrix a multiplied by SkMatrix b.
+
+ Given:
+
+ | A B C | | J K L |
+ a = | D E F |, b = | M N O |
+ | G H I | | P Q R |
+
+ sets SkMatrix to:
+
+ | A B C | | J K L | | AJ+BM+CP AK+BN+CQ AL+BO+CR |
+ a * b = | D E F | * | M N O | = | DJ+EM+FP DK+EN+FQ DL+EO+FR |
+ | G H I | | P Q R | | GJ+HM+IP GK+HN+IQ GL+HO+IR |
+
+ @param a SkMatrix on left side of multiply expression
+ @param b SkMatrix on right side of multiply expression
+ @return SkMatrix computed from a times b
+ */
+ static SkMatrix Concat(const SkMatrix& a, const SkMatrix& b) {
+ SkMatrix result;
+ result.setConcat(a, b);
+ return result;
+ }
+
+ friend SkMatrix operator*(const SkMatrix& a, const SkMatrix& b) {
+ return Concat(a, b);
+ }
+
+ /** Sets internal cache to unknown state. Use to force update after repeated
+ modifications to SkMatrix element reference returned by operator[](int index).
+ */
+ void dirtyMatrixTypeCache() {
+ this->setTypeMask(kUnknown_Mask);
+ }
+
+ /** Initializes SkMatrix with scale and translate elements.
+
+ | sx 0 tx |
+ | 0 sy ty |
+ | 0 0 1 |
+
+ @param sx horizontal scale factor to store
+ @param sy vertical scale factor to store
+ @param tx horizontal translation to store
+ @param ty vertical translation to store
+ */
+ void setScaleTranslate(SkScalar sx, SkScalar sy, SkScalar tx, SkScalar ty) {
+ fMat[kMScaleX] = sx;
+ fMat[kMSkewX] = 0;
+ fMat[kMTransX] = tx;
+
+ fMat[kMSkewY] = 0;
+ fMat[kMScaleY] = sy;
+ fMat[kMTransY] = ty;
+
+ fMat[kMPersp0] = 0;
+ fMat[kMPersp1] = 0;
+ fMat[kMPersp2] = 1;
+
+ int mask = 0;
+ if (sx != 1 || sy != 1) {
+ mask |= kScale_Mask;
+ }
+ if (tx != 0.0f || ty != 0.0f) {
+ mask |= kTranslate_Mask;
+ }
+ this->setTypeMask(mask | kRectStaysRect_Mask);
+ }
+
+ /** Returns true if all elements of the matrix are finite. Returns false if any
+ element is infinity, or NaN.
+
+ @return true if matrix has only finite elements
+ */
+ bool isFinite() const { return SkScalarsAreFinite(fMat, 9); }
+
+private:
+ /** Set if the matrix will map a rectangle to another rectangle. This
+ can be true if the matrix is scale-only, or rotates a multiple of
+ 90 degrees.
+
+ This bit will be set on identity matrices
+ */
+ static constexpr int kRectStaysRect_Mask = 0x10;
+
+ /** Set if the perspective bit is valid even though the rest of
+ the matrix is Unknown.
+ */
+ static constexpr int kOnlyPerspectiveValid_Mask = 0x40;
+
+ static constexpr int kUnknown_Mask = 0x80;
+
+ static constexpr int kORableMasks = kTranslate_Mask |
+ kScale_Mask |
+ kAffine_Mask |
+ kPerspective_Mask;
+
+ static constexpr int kAllMasks = kTranslate_Mask |
+ kScale_Mask |
+ kAffine_Mask |
+ kPerspective_Mask |
+ kRectStaysRect_Mask;
+
+ SkScalar fMat[9];
+ mutable int32_t fTypeMask;
+
+ constexpr SkMatrix(SkScalar sx, SkScalar kx, SkScalar tx,
+ SkScalar ky, SkScalar sy, SkScalar ty,
+ SkScalar p0, SkScalar p1, SkScalar p2, int typeMask)
+ : fMat{sx, kx, tx,
+ ky, sy, ty,
+ p0, p1, p2}
+ , fTypeMask(typeMask) {}
+
+ static void ComputeInv(SkScalar dst[9], const SkScalar src[9], double invDet, bool isPersp);
+
+ uint8_t computeTypeMask() const;
+ uint8_t computePerspectiveTypeMask() const;
+
+ void setTypeMask(int mask) {
+ // allow kUnknown or a valid mask
+ SkASSERT(kUnknown_Mask == mask || (mask & kAllMasks) == mask ||
+ ((kUnknown_Mask | kOnlyPerspectiveValid_Mask) & mask)
+ == (kUnknown_Mask | kOnlyPerspectiveValid_Mask));
+ fTypeMask = mask;
+ }
+
+ void orTypeMask(int mask) {
+ SkASSERT((mask & kORableMasks) == mask);
+ fTypeMask |= mask;
+ }
+
+ void clearTypeMask(int mask) {
+ // only allow a valid mask
+ SkASSERT((mask & kAllMasks) == mask);
+ fTypeMask &= ~mask;
+ }
+
+ TypeMask getPerspectiveTypeMaskOnly() const {
+ if ((fTypeMask & kUnknown_Mask) &&
+ !(fTypeMask & kOnlyPerspectiveValid_Mask)) {
+ fTypeMask = this->computePerspectiveTypeMask();
+ }
+ return (TypeMask)(fTypeMask & 0xF);
+ }
+
+ /** Returns true if we already know that the matrix is identity;
+ false otherwise.
+ */
+ bool isTriviallyIdentity() const {
+ if (fTypeMask & kUnknown_Mask) {
+ return false;
+ }
+ return ((fTypeMask & 0xF) == 0);
+ }
+
+ inline void updateTranslateMask() {
+ if ((fMat[kMTransX] != 0) | (fMat[kMTransY] != 0)) {
+ fTypeMask |= kTranslate_Mask;
+ } else {
+ fTypeMask &= ~kTranslate_Mask;
+ }
+ }
+
+ typedef void (*MapXYProc)(const SkMatrix& mat, SkScalar x, SkScalar y,
+ SkPoint* result);
+
+ static MapXYProc GetMapXYProc(TypeMask mask) {
+ SkASSERT((mask & ~kAllMasks) == 0);
+ return gMapXYProcs[mask & kAllMasks];
+ }
+
+ MapXYProc getMapXYProc() const {
+ return GetMapXYProc(this->getType());
+ }
+
+ typedef void (*MapPtsProc)(const SkMatrix& mat, SkPoint dst[],
+ const SkPoint src[], int count);
+
+ static MapPtsProc GetMapPtsProc(TypeMask mask) {
+ SkASSERT((mask & ~kAllMasks) == 0);
+ return gMapPtsProcs[mask & kAllMasks];
+ }
+
+ MapPtsProc getMapPtsProc() const {
+ return GetMapPtsProc(this->getType());
+ }
+
+ bool SK_WARN_UNUSED_RESULT invertNonIdentity(SkMatrix* inverse) const;
+
+ static bool Poly2Proc(const SkPoint[], SkMatrix*);
+ static bool Poly3Proc(const SkPoint[], SkMatrix*);
+ static bool Poly4Proc(const SkPoint[], SkMatrix*);
+
+ static void Identity_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*);
+ static void Trans_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*);
+ static void Scale_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*);
+ static void ScaleTrans_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*);
+ static void Rot_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*);
+ static void RotTrans_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*);
+ static void Persp_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*);
+
+ static const MapXYProc gMapXYProcs[];
+
+ static void Identity_pts(const SkMatrix&, SkPoint[], const SkPoint[], int);
+ static void Trans_pts(const SkMatrix&, SkPoint dst[], const SkPoint[], int);
+ static void Scale_pts(const SkMatrix&, SkPoint dst[], const SkPoint[], int);
+ static void ScaleTrans_pts(const SkMatrix&, SkPoint dst[], const SkPoint[],
+ int count);
+ static void Persp_pts(const SkMatrix&, SkPoint dst[], const SkPoint[], int);
+
+ static void Affine_vpts(const SkMatrix&, SkPoint dst[], const SkPoint[], int);
+
+ static const MapPtsProc gMapPtsProcs[];
+
+ // return the number of bytes written, whether or not buffer is null
+ size_t writeToMemory(void* buffer) const;
+ /**
+ * Reads data from the buffer parameter
+ *
+ * @param buffer Memory to read from
+ * @param length Amount of memory available in the buffer
+ * @return number of bytes read (must be a multiple of 4) or
+ * 0 if there was not enough memory available
+ */
+ size_t readFromMemory(const void* buffer, size_t length);
+
+ // legacy method -- still needed? why not just postScale(1/divx, ...)?
+ bool postIDiv(int divx, int divy);
+ void doNormalizePerspective();
+
+ friend class SkPerspIter;
+ friend class SkMatrixPriv;
+ friend class SerializationTest;
+};
+SK_END_REQUIRE_DENSE
+
+#endif
diff --git a/src/deps/skia/include/core/SkMilestone.h b/src/deps/skia/include/core/SkMilestone.h
new file mode 100644
index 000000000..8f036e3f3
--- /dev/null
+++ b/src/deps/skia/include/core/SkMilestone.h
@@ -0,0 +1,9 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#ifndef SK_MILESTONE
+#define SK_MILESTONE 99
+#endif
diff --git a/src/deps/skia/include/core/SkOverdrawCanvas.h b/src/deps/skia/include/core/SkOverdrawCanvas.h
new file mode 100644
index 000000000..1be26c6fa
--- /dev/null
+++ b/src/deps/skia/include/core/SkOverdrawCanvas.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkOverdrawCanvas_DEFINED
+#define SkOverdrawCanvas_DEFINED
+
+#include "include/core/SkCanvasVirtualEnforcer.h"
+#include "include/utils/SkNWayCanvas.h"
+
+/**
+ * Captures all drawing commands. Rather than draw the actual content, this device
+ * increments the alpha channel of each pixel every time it would have been touched
+ * by a draw call. This is useful for detecting overdraw.
+ */
+class SK_API SkOverdrawCanvas : public SkCanvasVirtualEnforcer<SkNWayCanvas> {
+public:
+ /* Does not take ownership of canvas */
+ SkOverdrawCanvas(SkCanvas*);
+
+ void onDrawTextBlob(const SkTextBlob*, SkScalar, SkScalar, const SkPaint&) override;
+ void onDrawGlyphRunList(const SkGlyphRunList& glyphRunList, const SkPaint& paint) override;
+ void onDrawPatch(const SkPoint[12], const SkColor[4], const SkPoint[4], SkBlendMode,
+ const SkPaint&) override;
+ void onDrawPaint(const SkPaint&) override;
+ void onDrawBehind(const SkPaint& paint) override;
+ void onDrawRect(const SkRect&, const SkPaint&) override;
+ void onDrawRegion(const SkRegion&, const SkPaint&) override;
+ void onDrawOval(const SkRect&, const SkPaint&) override;
+ void onDrawArc(const SkRect&, SkScalar, SkScalar, bool, const SkPaint&) override;
+ void onDrawDRRect(const SkRRect&, const SkRRect&, const SkPaint&) override;
+ void onDrawRRect(const SkRRect&, const SkPaint&) override;
+ void onDrawPoints(PointMode, size_t, const SkPoint[], const SkPaint&) override;
+ void onDrawVerticesObject(const SkVertices*, SkBlendMode, const SkPaint&) override;
+ void onDrawPath(const SkPath&, const SkPaint&) override;
+
+ void onDrawImage2(const SkImage*, SkScalar, SkScalar, const SkSamplingOptions&,
+ const SkPaint*) override;
+ void onDrawImageRect2(const SkImage*, const SkRect&, const SkRect&, const SkSamplingOptions&,
+ const SkPaint*, SrcRectConstraint) override;
+ void onDrawImageLattice2(const SkImage*, const Lattice&, const SkRect&, SkFilterMode,
+ const SkPaint*) override;
+ void onDrawAtlas2(const SkImage*, const SkRSXform[], const SkRect[], const SkColor[], int,
+ SkBlendMode, const SkSamplingOptions&, const SkRect*, const SkPaint*) override;
+
+ void onDrawDrawable(SkDrawable*, const SkMatrix*) override;
+ void onDrawPicture(const SkPicture*, const SkMatrix*, const SkPaint*) override;
+
+ void onDrawAnnotation(const SkRect&, const char key[], SkData* value) override;
+ void onDrawShadowRec(const SkPath&, const SkDrawShadowRec&) override;
+
+ void onDrawEdgeAAQuad(const SkRect&, const SkPoint[4], SkCanvas::QuadAAFlags, const SkColor4f&,
+ SkBlendMode) override;
+ void onDrawEdgeAAImageSet2(const ImageSetEntry[], int count, const SkPoint[], const SkMatrix[],
+ const SkSamplingOptions&,const SkPaint*, SrcRectConstraint) override;
+
+private:
+ inline SkPaint overdrawPaint(const SkPaint& paint);
+
+ SkPaint fPaint;
+
+ using INHERITED = SkCanvasVirtualEnforcer<SkNWayCanvas>;
+};
+
+#endif
diff --git a/src/deps/skia/include/core/SkPaint.h b/src/deps/skia/include/core/SkPaint.h
new file mode 100644
index 000000000..e3cc0391d
--- /dev/null
+++ b/src/deps/skia/include/core/SkPaint.h
@@ -0,0 +1,720 @@
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkPaint_DEFINED
+#define SkPaint_DEFINED
+
+#include "include/core/SkBlendMode.h"
+#include "include/core/SkColor.h"
+#include "include/core/SkRefCnt.h"
+#include "include/private/SkTOptional.h"
+#include "include/private/SkTo.h"
+
+class SkBlender;
+class SkColorFilter;
+class SkColorSpace;
+struct SkRect;
+class SkImageFilter;
+class SkMaskFilter;
+class SkMatrix;
+class SkPath;
+class SkPathEffect;
+class SkShader;
+
+/** \class SkPaint
+ SkPaint controls options applied when drawing. SkPaint collects all
+ options outside of the SkCanvas clip and SkCanvas matrix.
+
+ Various options apply to strokes and fills, and images.
+
+ SkPaint collects effects and filters that describe single-pass and multiple-pass
+ algorithms that alter the drawing geometry, color, and transparency. For instance,
+ SkPaint does not directly implement dashing or blur, but contains the objects that do so.
+*/
+class SK_API SkPaint {
+public:
+
+ /** Constructs SkPaint with default values.
+
+ @return default initialized SkPaint
+
+ example: https://fiddle.skia.org/c/@Paint_empty_constructor
+ */
+ SkPaint();
+
+ /** Constructs SkPaint with default values and the given color.
+
+ Sets alpha and RGB used when stroking and filling. The color is four floating
+ point values, unpremultiplied. The color values are interpreted as being in
+ the colorSpace. If colorSpace is nullptr, then color is assumed to be in the
+ sRGB color space.
+
+ @param color unpremultiplied RGBA
+ @param colorSpace SkColorSpace describing the encoding of color
+ @return SkPaint with the given color
+ */
+ explicit SkPaint(const SkColor4f& color, SkColorSpace* colorSpace = nullptr);
+
+ /** Makes a shallow copy of SkPaint. SkPathEffect, SkShader,
+ SkMaskFilter, SkColorFilter, and SkImageFilter are shared
+ between the original paint and the copy. Objects containing SkRefCnt increment
+ their references by one.
+
+ The referenced objects SkPathEffect, SkShader, SkMaskFilter, SkColorFilter,
+ and SkImageFilter cannot be modified after they are created.
+ This prevents objects with SkRefCnt from being modified once SkPaint refers to them.
+
+ @param paint original to copy
+ @return shallow copy of paint
+
+ example: https://fiddle.skia.org/c/@Paint_copy_const_SkPaint
+ */
+ SkPaint(const SkPaint& paint);
+
+ /** Implements a move constructor to avoid increasing the reference counts
+ of objects referenced by the paint.
+
+ After the call, paint is undefined, and can be safely destructed.
+
+ @param paint original to move
+ @return content of paint
+
+ example: https://fiddle.skia.org/c/@Paint_move_SkPaint
+ */
+ SkPaint(SkPaint&& paint);
+
+ /** Decreases SkPaint SkRefCnt of owned objects: SkPathEffect, SkShader,
+ SkMaskFilter, SkColorFilter, and SkImageFilter. If the
+ objects containing SkRefCnt go to zero, they are deleted.
+ */
+ ~SkPaint();
+
+ /** Makes a shallow copy of SkPaint. SkPathEffect, SkShader,
+ SkMaskFilter, SkColorFilter, and SkImageFilter are shared
+ between the original paint and the copy. Objects containing SkRefCnt in the
+ prior destination are decreased by one, and the referenced objects are deleted if the
+ resulting count is zero. Objects containing SkRefCnt in the parameter paint
+ are increased by one. paint is unmodified.
+
+ @param paint original to copy
+ @return content of paint
+
+ example: https://fiddle.skia.org/c/@Paint_copy_operator
+ */
+ SkPaint& operator=(const SkPaint& paint);
+
+ /** Moves the paint to avoid increasing the reference counts
+ of objects referenced by the paint parameter. Objects containing SkRefCnt in the
+ prior destination are decreased by one; those objects are deleted if the resulting count
+ is zero.
+
+ After the call, paint is undefined, and can be safely destructed.
+
+ @param paint original to move
+ @return content of paint
+
+ example: https://fiddle.skia.org/c/@Paint_move_operator
+ */
+ SkPaint& operator=(SkPaint&& paint);
+
+ /** Compares a and b, and returns true if a and b are equivalent. May return false
+ if SkPathEffect, SkShader, SkMaskFilter, SkColorFilter,
+ or SkImageFilter have identical contents but different pointers.
+
+ @param a SkPaint to compare
+ @param b SkPaint to compare
+ @return true if SkPaint pair are equivalent
+ */
+ SK_API friend bool operator==(const SkPaint& a, const SkPaint& b);
+
+ /** Compares a and b, and returns true if a and b are not equivalent. May return true
+ if SkPathEffect, SkShader, SkMaskFilter, SkColorFilter,
+ or SkImageFilter have identical contents but different pointers.
+
+ @param a SkPaint to compare
+ @param b SkPaint to compare
+ @return true if SkPaint pair are not equivalent
+ */
+ friend bool operator!=(const SkPaint& a, const SkPaint& b) {
+ return !(a == b);
+ }
+
+ /** Sets all SkPaint contents to their initial values. This is equivalent to replacing
+ SkPaint with the result of SkPaint().
+
+ example: https://fiddle.skia.org/c/@Paint_reset
+ */
+ void reset();
+
+ /** Returns true if pixels on the active edges of SkPath may be drawn with partial transparency.
+ @return antialiasing state
+ */
+ bool isAntiAlias() const {
+ return SkToBool(fBitfields.fAntiAlias);
+ }
+
+ /** Requests, but does not require, that edge pixels draw opaque or with
+ partial transparency.
+ @param aa setting for antialiasing
+ */
+ void setAntiAlias(bool aa) { fBitfields.fAntiAlias = static_cast<unsigned>(aa); }
+
+ /** Returns true if color error may be distributed to smooth color transition.
+ @return dithering state
+ */
+ bool isDither() const {
+ return SkToBool(fBitfields.fDither);
+ }
+
+ /** Requests, but does not require, to distribute color error.
+ @param dither setting for ditering
+ */
+ void setDither(bool dither) { fBitfields.fDither = static_cast<unsigned>(dither); }
+
+ /** \enum SkPaint::Style
+ Set Style to fill, stroke, or both fill and stroke geometry.
+ The stroke and fill
+ share all paint attributes; for instance, they are drawn with the same color.
+
+ Use kStrokeAndFill_Style to avoid hitting the same pixels twice with a stroke draw and
+ a fill draw.
+ */
+ enum Style : uint8_t {
+ kFill_Style, //!< set to fill geometry
+ kStroke_Style, //!< set to stroke geometry
+ kStrokeAndFill_Style, //!< sets to stroke and fill geometry
+ };
+
+ /** May be used to verify that SkPaint::Style is a legal value.
+ */
+ static constexpr int kStyleCount = kStrokeAndFill_Style + 1;
+
+ /** Returns whether the geometry is filled, stroked, or filled and stroked.
+ */
+ Style getStyle() const { return (Style)fBitfields.fStyle; }
+
+ /** Sets whether the geometry is filled, stroked, or filled and stroked.
+ Has no effect if style is not a legal SkPaint::Style value.
+
+ example: https://fiddle.skia.org/c/@Paint_setStyle
+ example: https://fiddle.skia.org/c/@Stroke_Width
+ */
+ void setStyle(Style style);
+
+ /**
+ * Set paint's style to kStroke if true, or kFill if false.
+ */
+ void setStroke(bool);
+
+ /** Retrieves alpha and RGB, unpremultiplied, packed into 32 bits.
+ Use helpers SkColorGetA(), SkColorGetR(), SkColorGetG(), and SkColorGetB() to extract
+ a color component.
+
+ @return unpremultiplied ARGB
+ */
+ SkColor getColor() const { return fColor4f.toSkColor(); }
+
+ /** Retrieves alpha and RGB, unpremultiplied, as four floating point values. RGB are
+ extended sRGB values (sRGB gamut, and encoded with the sRGB transfer function).
+
+ @return unpremultiplied RGBA
+ */
+ SkColor4f getColor4f() const { return fColor4f; }
+
+ /** Sets alpha and RGB used when stroking and filling. The color is a 32-bit value,
+ unpremultiplied, packing 8-bit components for alpha, red, blue, and green.
+
+ @param color unpremultiplied ARGB
+
+ example: https://fiddle.skia.org/c/@Paint_setColor
+ */
+ void setColor(SkColor color);
+
+ /** Sets alpha and RGB used when stroking and filling. The color is four floating
+ point values, unpremultiplied. The color values are interpreted as being in
+ the colorSpace. If colorSpace is nullptr, then color is assumed to be in the
+ sRGB color space.
+
+ @param color unpremultiplied RGBA
+ @param colorSpace SkColorSpace describing the encoding of color
+ */
+ void setColor(const SkColor4f& color, SkColorSpace* colorSpace = nullptr);
+
+ void setColor4f(const SkColor4f& color, SkColorSpace* colorSpace = nullptr) {
+ this->setColor(color, colorSpace);
+ }
+
+ /** Retrieves alpha from the color used when stroking and filling.
+
+ @return alpha ranging from zero, fully transparent, to 255, fully opaque
+ */
+ float getAlphaf() const { return fColor4f.fA; }
+
+ // Helper that scales the alpha by 255.
+ uint8_t getAlpha() const { return sk_float_round2int(this->getAlphaf() * 255); }
+
+ /** Replaces alpha, leaving RGB
+ unchanged. An out of range value triggers an assert in the debug
+ build. a is a value from 0.0 to 1.0.
+ a set to zero makes color fully transparent; a set to 1.0 makes color
+ fully opaque.
+
+ @param a alpha component of color
+ */
+ void setAlphaf(float a);
+
+ // Helper that accepts an int between 0 and 255, and divides it by 255.0
+ void setAlpha(U8CPU a) {
+ this->setAlphaf(a * (1.0f / 255));
+ }
+
+ /** Sets color used when drawing solid fills. The color components range from 0 to 255.
+ The color is unpremultiplied; alpha sets the transparency independent of RGB.
+
+ @param a amount of alpha, from fully transparent (0) to fully opaque (255)
+ @param r amount of red, from no red (0) to full red (255)
+ @param g amount of green, from no green (0) to full green (255)
+ @param b amount of blue, from no blue (0) to full blue (255)
+
+ example: https://fiddle.skia.org/c/@Paint_setARGB
+ */
+ void setARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b);
+
+ /** Returns the thickness of the pen used by SkPaint to
+ outline the shape.
+
+ @return zero for hairline, greater than zero for pen thickness
+ */
+ SkScalar getStrokeWidth() const { return fWidth; }
+
+ /** Sets the thickness of the pen used by the paint to outline the shape.
+ A stroke-width of zero is treated as "hairline" width. Hairlines are always exactly one
+ pixel wide in device space (their thickness does not change as the canvas is scaled).
+ Negative stroke-widths are invalid; setting a negative width will have no effect.
+
+ @param width zero thickness for hairline; greater than zero for pen thickness
+
+ example: https://fiddle.skia.org/c/@Miter_Limit
+ example: https://fiddle.skia.org/c/@Paint_setStrokeWidth
+ */
+ void setStrokeWidth(SkScalar width);
+
+ /** Returns the limit at which a sharp corner is drawn beveled.
+
+ @return zero and greater miter limit
+ */
+ SkScalar getStrokeMiter() const { return fMiterLimit; }
+
+ /** Sets the limit at which a sharp corner is drawn beveled.
+ Valid values are zero and greater.
+ Has no effect if miter is less than zero.
+
+ @param miter zero and greater miter limit
+
+ example: https://fiddle.skia.org/c/@Paint_setStrokeMiter
+ */
+ void setStrokeMiter(SkScalar miter);
+
+ /** \enum SkPaint::Cap
+ Cap draws at the beginning and end of an open path contour.
+ */
+ enum Cap {
+ kButt_Cap, //!< no stroke extension
+ kRound_Cap, //!< adds circle
+ kSquare_Cap, //!< adds square
+ kLast_Cap = kSquare_Cap, //!< largest Cap value
+ kDefault_Cap = kButt_Cap, //!< equivalent to kButt_Cap
+ };
+
+ /** May be used to verify that SkPaint::Cap is a legal value.
+ */
+ static constexpr int kCapCount = kLast_Cap + 1;
+
+ /** \enum SkPaint::Join
+ Join specifies how corners are drawn when a shape is stroked. Join
+ affects the four corners of a stroked rectangle, and the connected segments in a
+ stroked path.
+
+ Choose miter join to draw sharp corners. Choose round join to draw a circle with a
+ radius equal to the stroke width on top of the corner. Choose bevel join to minimally
+ connect the thick strokes.
+
+ The fill path constructed to describe the stroked path respects the join setting but may
+ not contain the actual join. For instance, a fill path constructed with round joins does
+ not necessarily include circles at each connected segment.
+ */
+ enum Join : uint8_t {
+ kMiter_Join, //!< extends to miter limit
+ kRound_Join, //!< adds circle
+ kBevel_Join, //!< connects outside edges
+ kLast_Join = kBevel_Join, //!< equivalent to the largest value for Join
+ kDefault_Join = kMiter_Join, //!< equivalent to kMiter_Join
+ };
+
+ /** May be used to verify that SkPaint::Join is a legal value.
+ */
+ static constexpr int kJoinCount = kLast_Join + 1;
+
+ /** Returns the geometry drawn at the beginning and end of strokes.
+ */
+ Cap getStrokeCap() const { return (Cap)fBitfields.fCapType; }
+
+ /** Sets the geometry drawn at the beginning and end of strokes.
+
+ example: https://fiddle.skia.org/c/@Paint_setStrokeCap_a
+ example: https://fiddle.skia.org/c/@Paint_setStrokeCap_b
+ */
+ void setStrokeCap(Cap cap);
+
+ /** Returns the geometry drawn at the corners of strokes.
+ */
+ Join getStrokeJoin() const { return (Join)fBitfields.fJoinType; }
+
+ /** Sets the geometry drawn at the corners of strokes.
+
+ example: https://fiddle.skia.org/c/@Paint_setStrokeJoin
+ */
+ void setStrokeJoin(Join join);
+
+ /** Returns the filled equivalent of the stroked path.
+
+ @param src SkPath read to create a filled version
+ @param dst resulting SkPath; may be the same as src, but may not be nullptr
+ @param cullRect optional limit passed to SkPathEffect
+ @param resScale if > 1, increase precision, else if (0 < resScale < 1) reduce precision
+ to favor speed and size
+ @return true if the path represents style fill, or false if it represents hairline
+ */
+ bool getFillPath(const SkPath& src, SkPath* dst, const SkRect* cullRect,
+ SkScalar resScale = 1) const;
+
+ bool getFillPath(const SkPath& src, SkPath* dst, const SkRect* cullRect,
+ const SkMatrix& ctm) const;
+
+ /** Returns the filled equivalent of the stroked path.
+
+ Replaces dst with the src path modified by SkPathEffect and style stroke.
+ SkPathEffect, if any, is not culled. stroke width is created with default precision.
+
+ @param src SkPath read to create a filled version
+ @param dst resulting SkPath dst may be the same as src, but may not be nullptr
+ @return true if the path represents style fill, or false if it represents hairline
+ */
+ bool getFillPath(const SkPath& src, SkPath* dst) const {
+ return this->getFillPath(src, dst, nullptr, 1);
+ }
+
+ /** Returns optional colors used when filling a path, such as a gradient.
+
+ Does not alter SkShader SkRefCnt.
+
+ @return SkShader if previously set, nullptr otherwise
+ */
+ SkShader* getShader() const { return fShader.get(); }
+
+ /** Returns optional colors used when filling a path, such as a gradient.
+
+ Increases SkShader SkRefCnt by one.
+
+ @return SkShader if previously set, nullptr otherwise
+
+ example: https://fiddle.skia.org/c/@Paint_refShader
+ */
+ sk_sp<SkShader> refShader() const;
+
+ /** Sets optional colors used when filling a path, such as a gradient.
+
+ Sets SkShader to shader, decreasing SkRefCnt of the previous SkShader.
+ Increments shader SkRefCnt by one.
+
+ @param shader how geometry is filled with color; if nullptr, color is used instead
+
+ example: https://fiddle.skia.org/c/@Color_Filter_Methods
+ example: https://fiddle.skia.org/c/@Paint_setShader
+ */
+ void setShader(sk_sp<SkShader> shader);
+
+ /** Returns SkColorFilter if set, or nullptr.
+ Does not alter SkColorFilter SkRefCnt.
+
+ @return SkColorFilter if previously set, nullptr otherwise
+ */
+ SkColorFilter* getColorFilter() const { return fColorFilter.get(); }
+
+ /** Returns SkColorFilter if set, or nullptr.
+ Increases SkColorFilter SkRefCnt by one.
+
+ @return SkColorFilter if set, or nullptr
+
+ example: https://fiddle.skia.org/c/@Paint_refColorFilter
+ */
+ sk_sp<SkColorFilter> refColorFilter() const;
+
+ /** Sets SkColorFilter to filter, decreasing SkRefCnt of the previous
+ SkColorFilter. Pass nullptr to clear SkColorFilter.
+
+ Increments filter SkRefCnt by one.
+
+ @param colorFilter SkColorFilter to apply to subsequent draw
+
+ example: https://fiddle.skia.org/c/@Blend_Mode_Methods
+ example: https://fiddle.skia.org/c/@Paint_setColorFilter
+ */
+ void setColorFilter(sk_sp<SkColorFilter> colorFilter);
+
+ /** If the current blender can be represented as a SkBlendMode enum, this returns that
+ * enum in the optional's value(). If it cannot, then the returned optional does not
+ * contain a value.
+ */
+ skstd::optional<SkBlendMode> asBlendMode() const;
+
+ /**
+ * Queries the blender, and if it can be represented as a SkBlendMode, return that mode,
+ * else return the defaultMode provided.
+ */
+ SkBlendMode getBlendMode_or(SkBlendMode defaultMode) const;
+
+ /** Returns true iff the current blender claims to be equivalent to SkBlendMode::kSrcOver.
+ *
+ * Also returns true of the current blender is nullptr.
+ */
+ bool isSrcOver() const;
+
+ /** Helper method for calling setBlender().
+ *
+ * This sets a blender that implements the specified blendmode enum.
+ */
+ void setBlendMode(SkBlendMode mode);
+
+ /** Returns the user-supplied blend function, if one has been set.
+ * Does not alter SkBlender's SkRefCnt.
+ *
+ * A nullptr blender signifies the default SrcOver behavior.
+ *
+ * @return the SkBlender assigned to this paint, otherwise nullptr
+ */
+ SkBlender* getBlender() const { return fBlender.get(); }
+
+ /** Returns the user-supplied blend function, if one has been set.
+ * Increments the SkBlender's SkRefCnt by one.
+ *
+ * A nullptr blender signifies the default SrcOver behavior.
+ *
+ * @return the SkBlender assigned to this paint, otherwise nullptr
+ */
+ sk_sp<SkBlender> refBlender() const;
+
+ /** Sets the current blender, increasing its refcnt, and if a blender is already
+ * present, decreasing that object's refcnt.
+ *
+ * A nullptr blender signifies the default SrcOver behavior.
+ *
+ * For convenience, you can call setBlendMode() if the blend effect can be expressed
+ * as one of those values.
+ */
+ void setBlender(sk_sp<SkBlender> blender);
+
+ /** Returns SkPathEffect if set, or nullptr.
+ Does not alter SkPathEffect SkRefCnt.
+
+ @return SkPathEffect if previously set, nullptr otherwise
+ */
+ SkPathEffect* getPathEffect() const { return fPathEffect.get(); }
+
+ /** Returns SkPathEffect if set, or nullptr.
+ Increases SkPathEffect SkRefCnt by one.
+
+ @return SkPathEffect if previously set, nullptr otherwise
+
+ example: https://fiddle.skia.org/c/@Paint_refPathEffect
+ */
+ sk_sp<SkPathEffect> refPathEffect() const;
+
+ /** Sets SkPathEffect to pathEffect, decreasing SkRefCnt of the previous
+ SkPathEffect. Pass nullptr to leave the path geometry unaltered.
+
+ Increments pathEffect SkRefCnt by one.
+
+ @param pathEffect replace SkPath with a modification when drawn
+
+ example: https://fiddle.skia.org/c/@Mask_Filter_Methods
+ example: https://fiddle.skia.org/c/@Paint_setPathEffect
+ */
+ void setPathEffect(sk_sp<SkPathEffect> pathEffect);
+
+ /** Returns SkMaskFilter if set, or nullptr.
+ Does not alter SkMaskFilter SkRefCnt.
+
+ @return SkMaskFilter if previously set, nullptr otherwise
+ */
+ SkMaskFilter* getMaskFilter() const { return fMaskFilter.get(); }
+
+ /** Returns SkMaskFilter if set, or nullptr.
+
+ Increases SkMaskFilter SkRefCnt by one.
+
+ @return SkMaskFilter if previously set, nullptr otherwise
+
+ example: https://fiddle.skia.org/c/@Paint_refMaskFilter
+ */
+ sk_sp<SkMaskFilter> refMaskFilter() const;
+
+ /** Sets SkMaskFilter to maskFilter, decreasing SkRefCnt of the previous
+ SkMaskFilter. Pass nullptr to clear SkMaskFilter and leave SkMaskFilter effect on
+ mask alpha unaltered.
+
+ Increments maskFilter SkRefCnt by one.
+
+ @param maskFilter modifies clipping mask generated from drawn geometry
+
+ example: https://fiddle.skia.org/c/@Paint_setMaskFilter
+ example: https://fiddle.skia.org/c/@Typeface_Methods
+ */
+ void setMaskFilter(sk_sp<SkMaskFilter> maskFilter);
+
+ /** Returns SkImageFilter if set, or nullptr.
+ Does not alter SkImageFilter SkRefCnt.
+
+ @return SkImageFilter if previously set, nullptr otherwise
+ */
+ SkImageFilter* getImageFilter() const { return fImageFilter.get(); }
+
+ /** Returns SkImageFilter if set, or nullptr.
+ Increases SkImageFilter SkRefCnt by one.
+
+ @return SkImageFilter if previously set, nullptr otherwise
+
+ example: https://fiddle.skia.org/c/@Paint_refImageFilter
+ */
+ sk_sp<SkImageFilter> refImageFilter() const;
+
+ /** Sets SkImageFilter to imageFilter, decreasing SkRefCnt of the previous
+ SkImageFilter. Pass nullptr to clear SkImageFilter, and remove SkImageFilter effect
+ on drawing.
+
+ Increments imageFilter SkRefCnt by one.
+
+ @param imageFilter how SkImage is sampled when transformed
+
+ example: https://fiddle.skia.org/c/@Paint_setImageFilter
+ */
+ void setImageFilter(sk_sp<SkImageFilter> imageFilter);
+
+ /** Returns true if SkPaint prevents all drawing;
+ otherwise, the SkPaint may or may not allow drawing.
+
+ Returns true if, for example, SkBlendMode combined with alpha computes a
+ new alpha of zero.
+
+ @return true if SkPaint prevents all drawing
+
+ example: https://fiddle.skia.org/c/@Paint_nothingToDraw
+ */
+ bool nothingToDraw() const;
+
+ /** (to be made private)
+ Returns true if SkPaint does not include elements requiring extensive computation
+ to compute SkBaseDevice bounds of drawn geometry. For instance, SkPaint with SkPathEffect
+ always returns false.
+
+ @return true if SkPaint allows for fast computation of bounds
+ */
+ bool canComputeFastBounds() const;
+
+ /** (to be made private)
+ Only call this if canComputeFastBounds() returned true. This takes a
+ raw rectangle (the raw bounds of a shape), and adjusts it for stylistic
+ effects in the paint (e.g. stroking). If needed, it uses the storage
+ parameter. It returns the adjusted bounds that can then be used
+ for SkCanvas::quickReject tests.
+
+ The returned SkRect will either be orig or storage, thus the caller
+ should not rely on storage being set to the result, but should always
+ use the returned value. It is legal for orig and storage to be the same
+ SkRect.
+ For example:
+ if (!path.isInverseFillType() && paint.canComputeFastBounds()) {
+ SkRect storage;
+ if (canvas->quickReject(paint.computeFastBounds(path.getBounds(), &storage))) {
+ return; // do not draw the path
+ }
+ }
+ // draw the path
+
+ @param orig geometry modified by SkPaint when drawn
+ @param storage computed bounds of geometry; may not be nullptr
+ @return fast computed bounds
+ */
+ const SkRect& computeFastBounds(const SkRect& orig, SkRect* storage) const {
+ // Things like stroking, etc... will do math on the bounds rect, assuming that it's sorted.
+ SkASSERT(orig.isSorted());
+ SkPaint::Style style = this->getStyle();
+ // ultra fast-case: filling with no effects that affect geometry
+ if (kFill_Style == style) {
+ uintptr_t effects = 0;
+ effects |= reinterpret_cast<uintptr_t>(this->getMaskFilter());
+ effects |= reinterpret_cast<uintptr_t>(this->getPathEffect());
+ effects |= reinterpret_cast<uintptr_t>(this->getImageFilter());
+ if (!effects) {
+ return orig;
+ }
+ }
+
+ return this->doComputeFastBounds(orig, storage, style);
+ }
+
+ /** (to be made private)
+
+ @param orig geometry modified by SkPaint when drawn
+ @param storage computed bounds of geometry
+ @return fast computed bounds
+ */
+ const SkRect& computeFastStrokeBounds(const SkRect& orig,
+ SkRect* storage) const {
+ return this->doComputeFastBounds(orig, storage, kStroke_Style);
+ }
+
+ /** (to be made private)
+ Computes the bounds, overriding the SkPaint SkPaint::Style. This can be used to
+ account for additional width required by stroking orig, without
+ altering SkPaint::Style set to fill.
+
+ @param orig geometry modified by SkPaint when drawn
+ @param storage computed bounds of geometry
+ @param style overrides SkPaint::Style
+ @return fast computed bounds
+ */
+ const SkRect& doComputeFastBounds(const SkRect& orig, SkRect* storage,
+ Style style) const;
+
+private:
+ sk_sp<SkPathEffect> fPathEffect;
+ sk_sp<SkShader> fShader;
+ sk_sp<SkMaskFilter> fMaskFilter;
+ sk_sp<SkColorFilter> fColorFilter;
+ sk_sp<SkImageFilter> fImageFilter;
+ sk_sp<SkBlender> fBlender;
+
+ SkColor4f fColor4f;
+ SkScalar fWidth;
+ SkScalar fMiterLimit;
+ union {
+ struct {
+ unsigned fAntiAlias : 1;
+ unsigned fDither : 1;
+ unsigned fCapType : 2;
+ unsigned fJoinType : 2;
+ unsigned fStyle : 2;
+ unsigned fPadding : 24; // 24 == 32 -1-1-2-2-2
+ } fBitfields;
+ uint32_t fBitfieldsUInt;
+ };
+
+ friend class SkPaintPriv;
+};
+
+#endif
diff --git a/src/deps/skia/include/core/SkPath.h b/src/deps/skia/include/core/SkPath.h
new file mode 100644
index 000000000..178e4d22f
--- /dev/null
+++ b/src/deps/skia/include/core/SkPath.h
@@ -0,0 +1,1891 @@
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkPath_DEFINED
+#define SkPath_DEFINED
+
+#include "include/core/SkMatrix.h"
+#include "include/core/SkPathTypes.h"
+#include "include/private/SkPathRef.h"
+#include "include/private/SkTo.h"
+
+#include <initializer_list>
+
+class SkAutoPathBoundsUpdate;
+class SkData;
+class SkRRect;
+class SkWStream;
+
+// WIP -- define this locally, and fix call-sites to use SkPathBuilder (skbug.com/9000)
+//#define SK_HIDE_PATH_EDIT_METHODS
+
+/** \class SkPath
+ SkPath contain geometry. SkPath may be empty, or contain one or more verbs that
+ outline a figure. SkPath always starts with a move verb to a Cartesian coordinate,
+ and may be followed by additional verbs that add lines or curves.
+ Adding a close verb makes the geometry into a continuous loop, a closed contour.
+ SkPath may contain any number of contours, each beginning with a move verb.
+
+ SkPath contours may contain only a move verb, or may also contain lines,
+ quadratic beziers, conics, and cubic beziers. SkPath contours may be open or
+ closed.
+
+ When used to draw a filled area, SkPath describes whether the fill is inside or
+ outside the geometry. SkPath also describes the winding rule used to fill
+ overlapping contours.
+
+ Internally, SkPath lazily computes metrics likes bounds and convexity. Call
+ SkPath::updateBoundsCache to make SkPath thread safe.
+*/
+class SK_API SkPath {
+public:
+ /**
+ * Create a new path with the specified segments.
+ *
+ * The points and weights arrays are read in order, based on the sequence of verbs.
+ *
+ * Move 1 point
+ * Line 1 point
+ * Quad 2 points
+ * Conic 2 points and 1 weight
+ * Cubic 3 points
+ * Close 0 points
+ *
+ * If an illegal sequence of verbs is encountered, or the specified number of points
+ * or weights is not sufficient given the verbs, an empty Path is returned.
+ *
+ * A legal sequence of verbs consists of any number of Contours. A contour always begins
+ * with a Move verb, followed by 0 or more segments: Line, Quad, Conic, Cubic, followed
+ * by an optional Close.
+ */
+ static SkPath Make(const SkPoint[], int pointCount,
+ const uint8_t[], int verbCount,
+ const SkScalar[], int conicWeightCount,
+ SkPathFillType, bool isVolatile = false);
+
+ static SkPath Rect(const SkRect&, SkPathDirection = SkPathDirection::kCW,
+ unsigned startIndex = 0);
+ static SkPath Oval(const SkRect&, SkPathDirection = SkPathDirection::kCW);
+ static SkPath Oval(const SkRect&, SkPathDirection, unsigned startIndex);
+ static SkPath Circle(SkScalar center_x, SkScalar center_y, SkScalar radius,
+ SkPathDirection dir = SkPathDirection::kCW);
+ static SkPath RRect(const SkRRect&, SkPathDirection dir = SkPathDirection::kCW);
+ static SkPath RRect(const SkRRect&, SkPathDirection, unsigned startIndex);
+ static SkPath RRect(const SkRect& bounds, SkScalar rx, SkScalar ry,
+ SkPathDirection dir = SkPathDirection::kCW);
+
+ static SkPath Polygon(const SkPoint pts[], int count, bool isClosed,
+ SkPathFillType = SkPathFillType::kWinding,
+ bool isVolatile = false);
+
+ static SkPath Polygon(const std::initializer_list<SkPoint>& list, bool isClosed,
+ SkPathFillType fillType = SkPathFillType::kWinding,
+ bool isVolatile = false) {
+ return Polygon(list.begin(), SkToInt(list.size()), isClosed, fillType, isVolatile);
+ }
+
+ static SkPath Line(const SkPoint a, const SkPoint b) {
+ return Polygon({a, b}, false);
+ }
+
+ /** Constructs an empty SkPath. By default, SkPath has no verbs, no SkPoint, and no weights.
+ FillType is set to kWinding.
+
+ @return empty SkPath
+
+ example: https://fiddle.skia.org/c/@Path_empty_constructor
+ */
+ SkPath();
+
+ /** Constructs a copy of an existing path.
+ Copy constructor makes two paths identical by value. Internally, path and
+ the returned result share pointer values. The underlying verb array, SkPoint array
+ and weights are copied when modified.
+
+ Creating a SkPath copy is very efficient and never allocates memory.
+ SkPath are always copied by value from the interface; the underlying shared
+ pointers are not exposed.
+
+ @param path SkPath to copy by value
+ @return copy of SkPath
+
+ example: https://fiddle.skia.org/c/@Path_copy_const_SkPath
+ */
+ SkPath(const SkPath& path);
+
+ /** Releases ownership of any shared data and deletes data if SkPath is sole owner.
+
+ example: https://fiddle.skia.org/c/@Path_destructor
+ */
+ ~SkPath();
+
+ /** Constructs a copy of an existing path.
+ SkPath assignment makes two paths identical by value. Internally, assignment
+ shares pointer values. The underlying verb array, SkPoint array and weights
+ are copied when modified.
+
+ Copying SkPath by assignment is very efficient and never allocates memory.
+ SkPath are always copied by value from the interface; the underlying shared
+ pointers are not exposed.
+
+ @param path verb array, SkPoint array, weights, and SkPath::FillType to copy
+ @return SkPath copied by value
+
+ example: https://fiddle.skia.org/c/@Path_copy_operator
+ */
+ SkPath& operator=(const SkPath& path);
+
+ /** Compares a and b; returns true if SkPath::FillType, verb array, SkPoint array, and weights
+ are equivalent.
+
+ @param a SkPath to compare
+ @param b SkPath to compare
+ @return true if SkPath pair are equivalent
+ */
+ friend SK_API bool operator==(const SkPath& a, const SkPath& b);
+
+ /** Compares a and b; returns true if SkPath::FillType, verb array, SkPoint array, and weights
+ are not equivalent.
+
+ @param a SkPath to compare
+ @param b SkPath to compare
+ @return true if SkPath pair are not equivalent
+ */
+ friend bool operator!=(const SkPath& a, const SkPath& b) {
+ return !(a == b);
+ }
+
+ /** Returns true if SkPath contain equal verbs and equal weights.
+ If SkPath contain one or more conics, the weights must match.
+
+ conicTo() may add different verbs depending on conic weight, so it is not
+ trivial to interpolate a pair of SkPath containing conics with different
+ conic weight values.
+
+ @param compare SkPath to compare
+ @return true if SkPath verb array and weights are equivalent
+
+ example: https://fiddle.skia.org/c/@Path_isInterpolatable
+ */
+ bool isInterpolatable(const SkPath& compare) const;
+
+ /** Interpolates between SkPath with SkPoint array of equal size.
+ Copy verb array and weights to out, and set out SkPoint array to a weighted
+ average of this SkPoint array and ending SkPoint array, using the formula:
+ (Path Point * weight) + ending Point * (1 - weight).
+
+ weight is most useful when between zero (ending SkPoint array) and
+ one (this Point_Array); will work with values outside of this
+ range.
+
+ interpolate() returns false and leaves out unchanged if SkPoint array is not
+ the same size as ending SkPoint array. Call isInterpolatable() to check SkPath
+ compatibility prior to calling interpolate().
+
+ @param ending SkPoint array averaged with this SkPoint array
+ @param weight contribution of this SkPoint array, and
+ one minus contribution of ending SkPoint array
+ @param out SkPath replaced by interpolated averages
+ @return true if SkPath contain same number of SkPoint
+
+ example: https://fiddle.skia.org/c/@Path_interpolate
+ */
+ bool interpolate(const SkPath& ending, SkScalar weight, SkPath* out) const;
+
+ /** Returns SkPathFillType, the rule used to fill SkPath.
+
+ @return current SkPathFillType setting
+ */
+ SkPathFillType getFillType() const { return (SkPathFillType)fFillType; }
+
+ /** Sets FillType, the rule used to fill SkPath. While there is no check
+ that ft is legal, values outside of FillType are not supported.
+ */
+ void setFillType(SkPathFillType ft) {
+ fFillType = SkToU8(ft);
+ }
+
+ /** Returns if FillType describes area outside SkPath geometry. The inverse fill area
+ extends indefinitely.
+
+ @return true if FillType is kInverseWinding or kInverseEvenOdd
+ */
+ bool isInverseFillType() const { return SkPathFillType_IsInverse(this->getFillType()); }
+
+ /** Replaces FillType with its inverse. The inverse of FillType describes the area
+ unmodified by the original FillType.
+ */
+ void toggleInverseFillType() {
+ fFillType ^= 2;
+ }
+
+ /** Returns true if the path is convex. If necessary, it will first compute the convexity.
+ */
+ bool isConvex() const {
+ return SkPathConvexity::kConvex == this->getConvexity();
+ }
+
+ /** Returns true if this path is recognized as an oval or circle.
+
+ bounds receives bounds of oval.
+
+ bounds is unmodified if oval is not found.
+
+ @param bounds storage for bounding SkRect of oval; may be nullptr
+ @return true if SkPath is recognized as an oval or circle
+
+ example: https://fiddle.skia.org/c/@Path_isOval
+ */
+ bool isOval(SkRect* bounds) const;
+
+ /** Returns true if path is representable as SkRRect.
+ Returns false if path is representable as oval, circle, or SkRect.
+
+ rrect receives bounds of SkRRect.
+
+ rrect is unmodified if SkRRect is not found.
+
+ @param rrect storage for bounding SkRect of SkRRect; may be nullptr
+ @return true if SkPath contains only SkRRect
+
+ example: https://fiddle.skia.org/c/@Path_isRRect
+ */
+ bool isRRect(SkRRect* rrect) const;
+
+ /** Sets SkPath to its initial state.
+ Removes verb array, SkPoint array, and weights, and sets FillType to kWinding.
+ Internal storage associated with SkPath is released.
+
+ @return reference to SkPath
+
+ example: https://fiddle.skia.org/c/@Path_reset
+ */
+ SkPath& reset();
+
+ /** Sets SkPath to its initial state, preserving internal storage.
+ Removes verb array, SkPoint array, and weights, and sets FillType to kWinding.
+ Internal storage associated with SkPath is retained.
+
+ Use rewind() instead of reset() if SkPath storage will be reused and performance
+ is critical.
+
+ @return reference to SkPath
+
+ example: https://fiddle.skia.org/c/@Path_rewind
+ */
+ SkPath& rewind();
+
+ /** Returns if SkPath is empty.
+ Empty SkPath may have FillType but has no SkPoint, SkPath::Verb, or conic weight.
+ SkPath() constructs empty SkPath; reset() and rewind() make SkPath empty.
+
+ @return true if the path contains no SkPath::Verb array
+ */
+ bool isEmpty() const {
+ SkDEBUGCODE(this->validate();)
+ return 0 == fPathRef->countVerbs();
+ }
+
+ /** Returns if contour is closed.
+ Contour is closed if SkPath SkPath::Verb array was last modified by close(). When stroked,
+ closed contour draws SkPaint::Join instead of SkPaint::Cap at first and last SkPoint.
+
+ @return true if the last contour ends with a kClose_Verb
+
+ example: https://fiddle.skia.org/c/@Path_isLastContourClosed
+ */
+ bool isLastContourClosed() const;
+
+ /** Returns true for finite SkPoint array values between negative SK_ScalarMax and
+ positive SK_ScalarMax. Returns false for any SkPoint array value of
+ SK_ScalarInfinity, SK_ScalarNegativeInfinity, or SK_ScalarNaN.
+
+ @return true if all SkPoint values are finite
+ */
+ bool isFinite() const {
+ SkDEBUGCODE(this->validate();)
+ return fPathRef->isFinite();
+ }
+
+ /** Returns true if the path is volatile; it will not be altered or discarded
+ by the caller after it is drawn. SkPath by default have volatile set false, allowing
+ SkSurface to attach a cache of data which speeds repeated drawing. If true, SkSurface
+ may not speed repeated drawing.
+
+ @return true if caller will alter SkPath after drawing
+ */
+ bool isVolatile() const {
+ return SkToBool(fIsVolatile);
+ }
+
+ /** Specifies whether SkPath is volatile; whether it will be altered or discarded
+ by the caller after it is drawn. SkPath by default have volatile set false, allowing
+ SkBaseDevice to attach a cache of data which speeds repeated drawing.
+
+ Mark temporary paths, discarded or modified after use, as volatile
+ to inform SkBaseDevice that the path need not be cached.
+
+ Mark animating SkPath volatile to improve performance.
+ Mark unchanging SkPath non-volatile to improve repeated rendering.
+
+ raster surface SkPath draws are affected by volatile for some shadows.
+ GPU surface SkPath draws are affected by volatile for some shadows and concave geometries.
+
+ @param isVolatile true if caller will alter SkPath after drawing
+ @return reference to SkPath
+ */
+ SkPath& setIsVolatile(bool isVolatile) {
+ fIsVolatile = isVolatile;
+ return *this;
+ }
+
+ /** Tests if line between SkPoint pair is degenerate.
+ Line with no length or that moves a very short distance is degenerate; it is
+ treated as a point.
+
+ exact changes the equality test. If true, returns true only if p1 equals p2.
+ If false, returns true if p1 equals or nearly equals p2.
+
+ @param p1 line start point
+ @param p2 line end point
+ @param exact if false, allow nearly equals
+ @return true if line is degenerate; its length is effectively zero
+
+ example: https://fiddle.skia.org/c/@Path_IsLineDegenerate
+ */
+ static bool IsLineDegenerate(const SkPoint& p1, const SkPoint& p2, bool exact);
+
+ /** Tests if quad is degenerate.
+ Quad with no length or that moves a very short distance is degenerate; it is
+ treated as a point.
+
+ @param p1 quad start point
+ @param p2 quad control point
+ @param p3 quad end point
+ @param exact if true, returns true only if p1, p2, and p3 are equal;
+ if false, returns true if p1, p2, and p3 are equal or nearly equal
+ @return true if quad is degenerate; its length is effectively zero
+ */
+ static bool IsQuadDegenerate(const SkPoint& p1, const SkPoint& p2,
+ const SkPoint& p3, bool exact);
+
+ /** Tests if cubic is degenerate.
+ Cubic with no length or that moves a very short distance is degenerate; it is
+ treated as a point.
+
+ @param p1 cubic start point
+ @param p2 cubic control point 1
+ @param p3 cubic control point 2
+ @param p4 cubic end point
+ @param exact if true, returns true only if p1, p2, p3, and p4 are equal;
+ if false, returns true if p1, p2, p3, and p4 are equal or nearly equal
+ @return true if cubic is degenerate; its length is effectively zero
+ */
+ static bool IsCubicDegenerate(const SkPoint& p1, const SkPoint& p2,
+ const SkPoint& p3, const SkPoint& p4, bool exact);
+
+ /** Returns true if SkPath contains only one line;
+ SkPath::Verb array has two entries: kMove_Verb, kLine_Verb.
+ If SkPath contains one line and line is not nullptr, line is set to
+ line start point and line end point.
+ Returns false if SkPath is not one line; line is unaltered.
+
+ @param line storage for line. May be nullptr
+ @return true if SkPath contains exactly one line
+
+ example: https://fiddle.skia.org/c/@Path_isLine
+ */
+ bool isLine(SkPoint line[2]) const;
+
+ /** Returns the number of points in SkPath.
+ SkPoint count is initially zero.
+
+ @return SkPath SkPoint array length
+
+ example: https://fiddle.skia.org/c/@Path_countPoints
+ */
+ int countPoints() const;
+
+ /** Returns SkPoint at index in SkPoint array. Valid range for index is
+ 0 to countPoints() - 1.
+ Returns (0, 0) if index is out of range.
+
+ @param index SkPoint array element selector
+ @return SkPoint array value or (0, 0)
+
+ example: https://fiddle.skia.org/c/@Path_getPoint
+ */
+ SkPoint getPoint(int index) const;
+
+ /** Returns number of points in SkPath. Up to max points are copied.
+ points may be nullptr; then, max must be zero.
+ If max is greater than number of points, excess points storage is unaltered.
+
+ @param points storage for SkPath SkPoint array. May be nullptr
+ @param max maximum to copy; must be greater than or equal to zero
+ @return SkPath SkPoint array length
+
+ example: https://fiddle.skia.org/c/@Path_getPoints
+ */
+ int getPoints(SkPoint points[], int max) const;
+
+ /** Returns the number of verbs: kMove_Verb, kLine_Verb, kQuad_Verb, kConic_Verb,
+ kCubic_Verb, and kClose_Verb; added to SkPath.
+
+ @return length of verb array
+
+ example: https://fiddle.skia.org/c/@Path_countVerbs
+ */
+ int countVerbs() const;
+
+ /** Returns the number of verbs in the path. Up to max verbs are copied. The
+ verbs are copied as one byte per verb.
+
+ @param verbs storage for verbs, may be nullptr
+ @param max maximum number to copy into verbs
+ @return the actual number of verbs in the path
+
+ example: https://fiddle.skia.org/c/@Path_getVerbs
+ */
+ int getVerbs(uint8_t verbs[], int max) const;
+
+ /** Returns the approximate byte size of the SkPath in memory.
+
+ @return approximate size
+ */
+ size_t approximateBytesUsed() const;
+
+ /** Exchanges the verb array, SkPoint array, weights, and SkPath::FillType with other.
+ Cached state is also exchanged. swap() internally exchanges pointers, so
+ it is lightweight and does not allocate memory.
+
+ swap() usage has largely been replaced by operator=(const SkPath& path).
+ SkPath do not copy their content on assignment until they are written to,
+ making assignment as efficient as swap().
+
+ @param other SkPath exchanged by value
+
+ example: https://fiddle.skia.org/c/@Path_swap
+ */
+ void swap(SkPath& other);
+
+ /** Returns minimum and maximum axes values of SkPoint array.
+ Returns (0, 0, 0, 0) if SkPath contains no points. Returned bounds width and height may
+ be larger or smaller than area affected when SkPath is drawn.
+
+ SkRect returned includes all SkPoint added to SkPath, including SkPoint associated with
+ kMove_Verb that define empty contours.
+
+ @return bounds of all SkPoint in SkPoint array
+ */
+ const SkRect& getBounds() const {
+ return fPathRef->getBounds();
+ }
+
+ /** Updates internal bounds so that subsequent calls to getBounds() are instantaneous.
+ Unaltered copies of SkPath may also access cached bounds through getBounds().
+
+ For now, identical to calling getBounds() and ignoring the returned value.
+
+ Call to prepare SkPath subsequently drawn from multiple threads,
+ to avoid a race condition where each draw separately computes the bounds.
+ */
+ void updateBoundsCache() const {
+ // for now, just calling getBounds() is sufficient
+ this->getBounds();
+ }
+
+ /** Returns minimum and maximum axes values of the lines and curves in SkPath.
+ Returns (0, 0, 0, 0) if SkPath contains no points.
+ Returned bounds width and height may be larger or smaller than area affected
+ when SkPath is drawn.
+
+ Includes SkPoint associated with kMove_Verb that define empty
+ contours.
+
+ Behaves identically to getBounds() when SkPath contains
+ only lines. If SkPath contains curves, computed bounds includes
+ the maximum extent of the quad, conic, or cubic; is slower than getBounds();
+ and unlike getBounds(), does not cache the result.
+
+ @return tight bounds of curves in SkPath
+
+ example: https://fiddle.skia.org/c/@Path_computeTightBounds
+ */
+ SkRect computeTightBounds() const;
+
+ /** Returns true if rect is contained by SkPath.
+ May return false when rect is contained by SkPath.
+
+ For now, only returns true if SkPath has one contour and is convex.
+ rect may share points and edges with SkPath and be contained.
+ Returns true if rect is empty, that is, it has zero width or height; and
+ the SkPoint or line described by rect is contained by SkPath.
+
+ @param rect SkRect, line, or SkPoint checked for containment
+ @return true if rect is contained
+
+ example: https://fiddle.skia.org/c/@Path_conservativelyContainsRect
+ */
+ bool conservativelyContainsRect(const SkRect& rect) const;
+
+ /** Grows SkPath verb array and SkPoint array to contain extraPtCount additional SkPoint.
+ May improve performance and use less memory by
+ reducing the number and size of allocations when creating SkPath.
+
+ @param extraPtCount number of additional SkPoint to allocate
+
+ example: https://fiddle.skia.org/c/@Path_incReserve
+ */
+ void incReserve(int extraPtCount);
+
+#ifdef SK_HIDE_PATH_EDIT_METHODS
+private:
+#endif
+
+ /** Adds beginning of contour at SkPoint (x, y).
+
+ @param x x-axis value of contour start
+ @param y y-axis value of contour start
+ @return reference to SkPath
+
+ example: https://fiddle.skia.org/c/@Path_moveTo
+ */
+ SkPath& moveTo(SkScalar x, SkScalar y);
+
+ /** Adds beginning of contour at SkPoint p.
+
+ @param p contour start
+ @return reference to SkPath
+ */
+ SkPath& moveTo(const SkPoint& p) {
+ return this->moveTo(p.fX, p.fY);
+ }
+
+ /** Adds beginning of contour relative to last point.
+ If SkPath is empty, starts contour at (dx, dy).
+ Otherwise, start contour at last point offset by (dx, dy).
+ Function name stands for "relative move to".
+
+ @param dx offset from last point to contour start on x-axis
+ @param dy offset from last point to contour start on y-axis
+ @return reference to SkPath
+
+ example: https://fiddle.skia.org/c/@Path_rMoveTo
+ */
+ SkPath& rMoveTo(SkScalar dx, SkScalar dy);
+
+ /** Adds line from last point to (x, y). If SkPath is empty, or last SkPath::Verb is
+ kClose_Verb, last point is set to (0, 0) before adding line.
+
+ lineTo() appends kMove_Verb to verb array and (0, 0) to SkPoint array, if needed.
+ lineTo() then appends kLine_Verb to verb array and (x, y) to SkPoint array.
+
+ @param x end of added line on x-axis
+ @param y end of added line on y-axis
+ @return reference to SkPath
+
+ example: https://fiddle.skia.org/c/@Path_lineTo
+ */
+ SkPath& lineTo(SkScalar x, SkScalar y);
+
+ /** Adds line from last point to SkPoint p. If SkPath is empty, or last SkPath::Verb is
+ kClose_Verb, last point is set to (0, 0) before adding line.
+
+ lineTo() first appends kMove_Verb to verb array and (0, 0) to SkPoint array, if needed.
+ lineTo() then appends kLine_Verb to verb array and SkPoint p to SkPoint array.
+
+ @param p end SkPoint of added line
+ @return reference to SkPath
+ */
+ SkPath& lineTo(const SkPoint& p) {
+ return this->lineTo(p.fX, p.fY);
+ }
+
+ /** Adds line from last point to vector (dx, dy). If SkPath is empty, or last SkPath::Verb is
+ kClose_Verb, last point is set to (0, 0) before adding line.
+
+ Appends kMove_Verb to verb array and (0, 0) to SkPoint array, if needed;
+ then appends kLine_Verb to verb array and line end to SkPoint array.
+ Line end is last point plus vector (dx, dy).
+ Function name stands for "relative line to".
+
+ @param dx offset from last point to line end on x-axis
+ @param dy offset from last point to line end on y-axis
+ @return reference to SkPath
+
+ example: https://fiddle.skia.org/c/@Path_rLineTo
+ example: https://fiddle.skia.org/c/@Quad_a
+ example: https://fiddle.skia.org/c/@Quad_b
+ */
+ SkPath& rLineTo(SkScalar dx, SkScalar dy);
+
+ /** Adds quad from last point towards (x1, y1), to (x2, y2).
+ If SkPath is empty, or last SkPath::Verb is kClose_Verb, last point is set to (0, 0)
+ before adding quad.
+
+ Appends kMove_Verb to verb array and (0, 0) to SkPoint array, if needed;
+ then appends kQuad_Verb to verb array; and (x1, y1), (x2, y2)
+ to SkPoint array.
+
+ @param x1 control SkPoint of quad on x-axis
+ @param y1 control SkPoint of quad on y-axis
+ @param x2 end SkPoint of quad on x-axis
+ @param y2 end SkPoint of quad on y-axis
+ @return reference to SkPath
+
+ example: https://fiddle.skia.org/c/@Path_quadTo
+ */
+ SkPath& quadTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2);
+
+ /** Adds quad from last point towards SkPoint p1, to SkPoint p2.
+ If SkPath is empty, or last SkPath::Verb is kClose_Verb, last point is set to (0, 0)
+ before adding quad.
+
+ Appends kMove_Verb to verb array and (0, 0) to SkPoint array, if needed;
+ then appends kQuad_Verb to verb array; and SkPoint p1, p2
+ to SkPoint array.
+
+ @param p1 control SkPoint of added quad
+ @param p2 end SkPoint of added quad
+ @return reference to SkPath
+ */
+ SkPath& quadTo(const SkPoint& p1, const SkPoint& p2) {
+ return this->quadTo(p1.fX, p1.fY, p2.fX, p2.fY);
+ }
+
+ /** Adds quad from last point towards vector (dx1, dy1), to vector (dx2, dy2).
+ If SkPath is empty, or last SkPath::Verb
+ is kClose_Verb, last point is set to (0, 0) before adding quad.
+
+ Appends kMove_Verb to verb array and (0, 0) to SkPoint array,
+ if needed; then appends kQuad_Verb to verb array; and appends quad
+ control and quad end to SkPoint array.
+ Quad control is last point plus vector (dx1, dy1).
+ Quad end is last point plus vector (dx2, dy2).
+ Function name stands for "relative quad to".
+
+ @param dx1 offset from last point to quad control on x-axis
+ @param dy1 offset from last point to quad control on y-axis
+ @param dx2 offset from last point to quad end on x-axis
+ @param dy2 offset from last point to quad end on y-axis
+ @return reference to SkPath
+
+ example: https://fiddle.skia.org/c/@Conic_Weight_a
+ example: https://fiddle.skia.org/c/@Conic_Weight_b
+ example: https://fiddle.skia.org/c/@Conic_Weight_c
+ example: https://fiddle.skia.org/c/@Path_rQuadTo
+ */
+ SkPath& rQuadTo(SkScalar dx1, SkScalar dy1, SkScalar dx2, SkScalar dy2);
+
+ /** Adds conic from last point towards (x1, y1), to (x2, y2), weighted by w.
+ If SkPath is empty, or last SkPath::Verb is kClose_Verb, last point is set to (0, 0)
+ before adding conic.
+
+ Appends kMove_Verb to verb array and (0, 0) to SkPoint array, if needed.
+
+ If w is finite and not one, appends kConic_Verb to verb array;
+ and (x1, y1), (x2, y2) to SkPoint array; and w to conic weights.
+
+ If w is one, appends kQuad_Verb to verb array, and
+ (x1, y1), (x2, y2) to SkPoint array.
+
+ If w is not finite, appends kLine_Verb twice to verb array, and
+ (x1, y1), (x2, y2) to SkPoint array.
+
+ @param x1 control SkPoint of conic on x-axis
+ @param y1 control SkPoint of conic on y-axis
+ @param x2 end SkPoint of conic on x-axis
+ @param y2 end SkPoint of conic on y-axis
+ @param w weight of added conic
+ @return reference to SkPath
+ */
+ SkPath& conicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
+ SkScalar w);
+
+ /** Adds conic from last point towards SkPoint p1, to SkPoint p2, weighted by w.
+ If SkPath is empty, or last SkPath::Verb is kClose_Verb, last point is set to (0, 0)
+ before adding conic.
+
+ Appends kMove_Verb to verb array and (0, 0) to SkPoint array, if needed.
+
+ If w is finite and not one, appends kConic_Verb to verb array;
+ and SkPoint p1, p2 to SkPoint array; and w to conic weights.
+
+ If w is one, appends kQuad_Verb to verb array, and SkPoint p1, p2
+ to SkPoint array.
+
+ If w is not finite, appends kLine_Verb twice to verb array, and
+ SkPoint p1, p2 to SkPoint array.
+
+ @param p1 control SkPoint of added conic
+ @param p2 end SkPoint of added conic
+ @param w weight of added conic
+ @return reference to SkPath
+ */
+ SkPath& conicTo(const SkPoint& p1, const SkPoint& p2, SkScalar w) {
+ return this->conicTo(p1.fX, p1.fY, p2.fX, p2.fY, w);
+ }
+
+ /** Adds conic from last point towards vector (dx1, dy1), to vector (dx2, dy2),
+ weighted by w. If SkPath is empty, or last SkPath::Verb
+ is kClose_Verb, last point is set to (0, 0) before adding conic.
+
+ Appends kMove_Verb to verb array and (0, 0) to SkPoint array,
+ if needed.
+
+ If w is finite and not one, next appends kConic_Verb to verb array,
+ and w is recorded as conic weight; otherwise, if w is one, appends
+ kQuad_Verb to verb array; or if w is not finite, appends kLine_Verb
+ twice to verb array.
+
+ In all cases appends SkPoint control and end to SkPoint array.
+ control is last point plus vector (dx1, dy1).
+ end is last point plus vector (dx2, dy2).
+
+ Function name stands for "relative conic to".
+
+ @param dx1 offset from last point to conic control on x-axis
+ @param dy1 offset from last point to conic control on y-axis
+ @param dx2 offset from last point to conic end on x-axis
+ @param dy2 offset from last point to conic end on y-axis
+ @param w weight of added conic
+ @return reference to SkPath
+ */
+ SkPath& rConicTo(SkScalar dx1, SkScalar dy1, SkScalar dx2, SkScalar dy2,
+ SkScalar w);
+
+ /** Adds cubic from last point towards (x1, y1), then towards (x2, y2), ending at
+ (x3, y3). If SkPath is empty, or last SkPath::Verb is kClose_Verb, last point is set to
+ (0, 0) before adding cubic.
+
+ Appends kMove_Verb to verb array and (0, 0) to SkPoint array, if needed;
+ then appends kCubic_Verb to verb array; and (x1, y1), (x2, y2), (x3, y3)
+ to SkPoint array.
+
+ @param x1 first control SkPoint of cubic on x-axis
+ @param y1 first control SkPoint of cubic on y-axis
+ @param x2 second control SkPoint of cubic on x-axis
+ @param y2 second control SkPoint of cubic on y-axis
+ @param x3 end SkPoint of cubic on x-axis
+ @param y3 end SkPoint of cubic on y-axis
+ @return reference to SkPath
+ */
+ SkPath& cubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
+ SkScalar x3, SkScalar y3);
+
+ /** Adds cubic from last point towards SkPoint p1, then towards SkPoint p2, ending at
+ SkPoint p3. If SkPath is empty, or last SkPath::Verb is kClose_Verb, last point is set to
+ (0, 0) before adding cubic.
+
+ Appends kMove_Verb to verb array and (0, 0) to SkPoint array, if needed;
+ then appends kCubic_Verb to verb array; and SkPoint p1, p2, p3
+ to SkPoint array.
+
+ @param p1 first control SkPoint of cubic
+ @param p2 second control SkPoint of cubic
+ @param p3 end SkPoint of cubic
+ @return reference to SkPath
+ */
+ SkPath& cubicTo(const SkPoint& p1, const SkPoint& p2, const SkPoint& p3) {
+ return this->cubicTo(p1.fX, p1.fY, p2.fX, p2.fY, p3.fX, p3.fY);
+ }
+
+ /** Adds cubic from last point towards vector (dx1, dy1), then towards
+ vector (dx2, dy2), to vector (dx3, dy3).
+ If SkPath is empty, or last SkPath::Verb
+ is kClose_Verb, last point is set to (0, 0) before adding cubic.
+
+ Appends kMove_Verb to verb array and (0, 0) to SkPoint array,
+ if needed; then appends kCubic_Verb to verb array; and appends cubic
+ control and cubic end to SkPoint array.
+ Cubic control is last point plus vector (dx1, dy1).
+ Cubic end is last point plus vector (dx2, dy2).
+ Function name stands for "relative cubic to".
+
+ @param dx1 offset from last point to first cubic control on x-axis
+ @param dy1 offset from last point to first cubic control on y-axis
+ @param dx2 offset from last point to second cubic control on x-axis
+ @param dy2 offset from last point to second cubic control on y-axis
+ @param dx3 offset from last point to cubic end on x-axis
+ @param dy3 offset from last point to cubic end on y-axis
+ @return reference to SkPath
+ */
+ SkPath& rCubicTo(SkScalar dx1, SkScalar dy1, SkScalar dx2, SkScalar dy2,
+ SkScalar dx3, SkScalar dy3);
+
+ /** Appends arc to SkPath. Arc added is part of ellipse
+ bounded by oval, from startAngle through sweepAngle. Both startAngle and
+ sweepAngle are measured in degrees, where zero degrees is aligned with the
+ positive x-axis, and positive sweeps extends arc clockwise.
+
+ arcTo() adds line connecting SkPath last SkPoint to initial arc SkPoint if forceMoveTo
+ is false and SkPath is not empty. Otherwise, added contour begins with first point
+ of arc. Angles greater than -360 and less than 360 are treated modulo 360.
+
+ @param oval bounds of ellipse containing arc
+ @param startAngle starting angle of arc in degrees
+ @param sweepAngle sweep, in degrees. Positive is clockwise; treated modulo 360
+ @param forceMoveTo true to start a new contour with arc
+ @return reference to SkPath
+
+ example: https://fiddle.skia.org/c/@Path_arcTo
+ */
+ SkPath& arcTo(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle, bool forceMoveTo);
+
+ /** Appends arc to SkPath, after appending line if needed. Arc is implemented by conic
+ weighted to describe part of circle. Arc is contained by tangent from
+ last SkPath point to (x1, y1), and tangent from (x1, y1) to (x2, y2). Arc
+ is part of circle sized to radius, positioned so it touches both tangent lines.
+
+ If last Path Point does not start Arc, arcTo appends connecting Line to Path.
+ The length of Vector from (x1, y1) to (x2, y2) does not affect Arc.
+
+ Arc sweep is always less than 180 degrees. If radius is zero, or if
+ tangents are nearly parallel, arcTo appends Line from last Path Point to (x1, y1).
+
+ arcTo appends at most one Line and one conic.
+ arcTo implements the functionality of PostScript arct and HTML Canvas arcTo.
+
+ @param x1 x-axis value common to pair of tangents
+ @param y1 y-axis value common to pair of tangents
+ @param x2 x-axis value end of second tangent
+ @param y2 y-axis value end of second tangent
+ @param radius distance from arc to circle center
+ @return reference to SkPath
+
+ example: https://fiddle.skia.org/c/@Path_arcTo_2_a
+ example: https://fiddle.skia.org/c/@Path_arcTo_2_b
+ example: https://fiddle.skia.org/c/@Path_arcTo_2_c
+ */
+ SkPath& arcTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, SkScalar radius);
+
+ /** Appends arc to SkPath, after appending line if needed. Arc is implemented by conic
+ weighted to describe part of circle. Arc is contained by tangent from
+ last SkPath point to p1, and tangent from p1 to p2. Arc
+ is part of circle sized to radius, positioned so it touches both tangent lines.
+
+ If last SkPath SkPoint does not start arc, arcTo() appends connecting line to SkPath.
+ The length of vector from p1 to p2 does not affect arc.
+
+ Arc sweep is always less than 180 degrees. If radius is zero, or if
+ tangents are nearly parallel, arcTo() appends line from last SkPath SkPoint to p1.
+
+ arcTo() appends at most one line and one conic.
+ arcTo() implements the functionality of PostScript arct and HTML Canvas arcTo.
+
+ @param p1 SkPoint common to pair of tangents
+ @param p2 end of second tangent
+ @param radius distance from arc to circle center
+ @return reference to SkPath
+ */
+ SkPath& arcTo(const SkPoint p1, const SkPoint p2, SkScalar radius) {
+ return this->arcTo(p1.fX, p1.fY, p2.fX, p2.fY, radius);
+ }
+
+ /** \enum SkPath::ArcSize
+ Four oval parts with radii (rx, ry) start at last SkPath SkPoint and ends at (x, y).
+ ArcSize and Direction select one of the four oval parts.
+ */
+ enum ArcSize {
+ kSmall_ArcSize, //!< smaller of arc pair
+ kLarge_ArcSize, //!< larger of arc pair
+ };
+
+ /** Appends arc to SkPath. Arc is implemented by one or more conics weighted to
+ describe part of oval with radii (rx, ry) rotated by xAxisRotate degrees. Arc
+ curves from last SkPath SkPoint to (x, y), choosing one of four possible routes:
+ clockwise or counterclockwise, and smaller or larger.
+
+ Arc sweep is always less than 360 degrees. arcTo() appends line to (x, y) if
+ either radii are zero, or if last SkPath SkPoint equals (x, y). arcTo() scales radii
+ (rx, ry) to fit last SkPath SkPoint and (x, y) if both are greater than zero but
+ too small.
+
+ arcTo() appends up to four conic curves.
+ arcTo() implements the functionality of SVG arc, although SVG sweep-flag value
+ is opposite the integer value of sweep; SVG sweep-flag uses 1 for clockwise,
+ while kCW_Direction cast to int is zero.
+
+ @param rx radius on x-axis before x-axis rotation
+ @param ry radius on y-axis before x-axis rotation
+ @param xAxisRotate x-axis rotation in degrees; positive values are clockwise
+ @param largeArc chooses smaller or larger arc
+ @param sweep chooses clockwise or counterclockwise arc
+ @param x end of arc
+ @param y end of arc
+ @return reference to SkPath
+ */
+ SkPath& arcTo(SkScalar rx, SkScalar ry, SkScalar xAxisRotate, ArcSize largeArc,
+ SkPathDirection sweep, SkScalar x, SkScalar y);
+
+ /** Appends arc to SkPath. Arc is implemented by one or more conic weighted to describe
+ part of oval with radii (r.fX, r.fY) rotated by xAxisRotate degrees. Arc curves
+ from last SkPath SkPoint to (xy.fX, xy.fY), choosing one of four possible routes:
+ clockwise or counterclockwise,
+ and smaller or larger.
+
+ Arc sweep is always less than 360 degrees. arcTo() appends line to xy if either
+ radii are zero, or if last SkPath SkPoint equals (xy.fX, xy.fY). arcTo() scales radii r to
+ fit last SkPath SkPoint and xy if both are greater than zero but too small to describe
+ an arc.
+
+ arcTo() appends up to four conic curves.
+ arcTo() implements the functionality of SVG arc, although SVG sweep-flag value is
+ opposite the integer value of sweep; SVG sweep-flag uses 1 for clockwise, while
+ kCW_Direction cast to int is zero.
+
+ @param r radii on axes before x-axis rotation
+ @param xAxisRotate x-axis rotation in degrees; positive values are clockwise
+ @param largeArc chooses smaller or larger arc
+ @param sweep chooses clockwise or counterclockwise arc
+ @param xy end of arc
+ @return reference to SkPath
+ */
+ SkPath& arcTo(const SkPoint r, SkScalar xAxisRotate, ArcSize largeArc, SkPathDirection sweep,
+ const SkPoint xy) {
+ return this->arcTo(r.fX, r.fY, xAxisRotate, largeArc, sweep, xy.fX, xy.fY);
+ }
+
+ /** Appends arc to SkPath, relative to last SkPath SkPoint. Arc is implemented by one or
+ more conic, weighted to describe part of oval with radii (rx, ry) rotated by
+ xAxisRotate degrees. Arc curves from last SkPath SkPoint to relative end SkPoint:
+ (dx, dy), choosing one of four possible routes: clockwise or
+ counterclockwise, and smaller or larger. If SkPath is empty, the start arc SkPoint
+ is (0, 0).
+
+ Arc sweep is always less than 360 degrees. arcTo() appends line to end SkPoint
+ if either radii are zero, or if last SkPath SkPoint equals end SkPoint.
+ arcTo() scales radii (rx, ry) to fit last SkPath SkPoint and end SkPoint if both are
+ greater than zero but too small to describe an arc.
+
+ arcTo() appends up to four conic curves.
+ arcTo() implements the functionality of svg arc, although SVG "sweep-flag" value is
+ opposite the integer value of sweep; SVG "sweep-flag" uses 1 for clockwise, while
+ kCW_Direction cast to int is zero.
+
+ @param rx radius before x-axis rotation
+ @param ry radius before x-axis rotation
+ @param xAxisRotate x-axis rotation in degrees; positive values are clockwise
+ @param largeArc chooses smaller or larger arc
+ @param sweep chooses clockwise or counterclockwise arc
+ @param dx x-axis offset end of arc from last SkPath SkPoint
+ @param dy y-axis offset end of arc from last SkPath SkPoint
+ @return reference to SkPath
+ */
+ SkPath& rArcTo(SkScalar rx, SkScalar ry, SkScalar xAxisRotate, ArcSize largeArc,
+ SkPathDirection sweep, SkScalar dx, SkScalar dy);
+
+ /** Appends kClose_Verb to SkPath. A closed contour connects the first and last SkPoint
+ with line, forming a continuous loop. Open and closed contour draw the same
+ with SkPaint::kFill_Style. With SkPaint::kStroke_Style, open contour draws
+ SkPaint::Cap at contour start and end; closed contour draws
+ SkPaint::Join at contour start and end.
+
+ close() has no effect if SkPath is empty or last SkPath SkPath::Verb is kClose_Verb.
+
+ @return reference to SkPath
+
+ example: https://fiddle.skia.org/c/@Path_close
+ */
+ SkPath& close();
+
+#ifdef SK_HIDE_PATH_EDIT_METHODS
+public:
+#endif
+
+ /** Approximates conic with quad array. Conic is constructed from start SkPoint p0,
+ control SkPoint p1, end SkPoint p2, and weight w.
+ Quad array is stored in pts; this storage is supplied by caller.
+ Maximum quad count is 2 to the pow2.
+ Every third point in array shares last SkPoint of previous quad and first SkPoint of
+ next quad. Maximum pts storage size is given by:
+ (1 + 2 * (1 << pow2)) * sizeof(SkPoint).
+
+ Returns quad count used the approximation, which may be smaller
+ than the number requested.
+
+ conic weight determines the amount of influence conic control point has on the curve.
+ w less than one represents an elliptical section. w greater than one represents
+ a hyperbolic section. w equal to one represents a parabolic section.
+
+ Two quad curves are sufficient to approximate an elliptical conic with a sweep
+ of up to 90 degrees; in this case, set pow2 to one.
+
+ @param p0 conic start SkPoint
+ @param p1 conic control SkPoint
+ @param p2 conic end SkPoint
+ @param w conic weight
+ @param pts storage for quad array
+ @param pow2 quad count, as power of two, normally 0 to 5 (1 to 32 quad curves)
+ @return number of quad curves written to pts
+ */
+ static int ConvertConicToQuads(const SkPoint& p0, const SkPoint& p1, const SkPoint& p2,
+ SkScalar w, SkPoint pts[], int pow2);
+
+ /** Returns true if SkPath is equivalent to SkRect when filled.
+ If false: rect, isClosed, and direction are unchanged.
+ If true: rect, isClosed, and direction are written to if not nullptr.
+
+ rect may be smaller than the SkPath bounds. SkPath bounds may include kMove_Verb points
+ that do not alter the area drawn by the returned rect.
+
+ @param rect storage for bounds of SkRect; may be nullptr
+ @param isClosed storage set to true if SkPath is closed; may be nullptr
+ @param direction storage set to SkRect direction; may be nullptr
+ @return true if SkPath contains SkRect
+
+ example: https://fiddle.skia.org/c/@Path_isRect
+ */
+ bool isRect(SkRect* rect, bool* isClosed = nullptr, SkPathDirection* direction = nullptr) const;
+
+#ifdef SK_HIDE_PATH_EDIT_METHODS
+private:
+#endif
+
+ /** Adds a new contour to the path, defined by the rect, and wound in the
+ specified direction. The verbs added to the path will be:
+
+ kMove, kLine, kLine, kLine, kClose
+
+ start specifies which corner to begin the contour:
+ 0: upper-left corner
+ 1: upper-right corner
+ 2: lower-right corner
+ 3: lower-left corner
+
+ This start point also acts as the implied beginning of the subsequent,
+ contour, if it does not have an explicit moveTo(). e.g.
+
+ path.addRect(...)
+ // if we don't say moveTo() here, we will use the rect's start point
+ path.lineTo(...)
+
+ @param rect SkRect to add as a closed contour
+ @param dir SkPath::Direction to orient the new contour
+ @param start initial corner of SkRect to add
+ @return reference to SkPath
+
+ example: https://fiddle.skia.org/c/@Path_addRect_2
+ */
+ SkPath& addRect(const SkRect& rect, SkPathDirection dir, unsigned start);
+
+ SkPath& addRect(const SkRect& rect, SkPathDirection dir = SkPathDirection::kCW) {
+ return this->addRect(rect, dir, 0);
+ }
+
+ SkPath& addRect(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom,
+ SkPathDirection dir = SkPathDirection::kCW) {
+ return this->addRect({left, top, right, bottom}, dir, 0);
+ }
+
+ /** Adds oval to path, appending kMove_Verb, four kConic_Verb, and kClose_Verb.
+ Oval is upright ellipse bounded by SkRect oval with radii equal to half oval width
+ and half oval height. Oval begins at (oval.fRight, oval.centerY()) and continues
+ clockwise if dir is kCW_Direction, counterclockwise if dir is kCCW_Direction.
+
+ @param oval bounds of ellipse added
+ @param dir SkPath::Direction to wind ellipse
+ @return reference to SkPath
+
+ example: https://fiddle.skia.org/c/@Path_addOval
+ */
+ SkPath& addOval(const SkRect& oval, SkPathDirection dir = SkPathDirection::kCW);
+
+ /** Adds oval to SkPath, appending kMove_Verb, four kConic_Verb, and kClose_Verb.
+ Oval is upright ellipse bounded by SkRect oval with radii equal to half oval width
+ and half oval height. Oval begins at start and continues
+ clockwise if dir is kCW_Direction, counterclockwise if dir is kCCW_Direction.
+
+ @param oval bounds of ellipse added
+ @param dir SkPath::Direction to wind ellipse
+ @param start index of initial point of ellipse
+ @return reference to SkPath
+
+ example: https://fiddle.skia.org/c/@Path_addOval_2
+ */
+ SkPath& addOval(const SkRect& oval, SkPathDirection dir, unsigned start);
+
+ /** Adds circle centered at (x, y) of size radius to SkPath, appending kMove_Verb,
+ four kConic_Verb, and kClose_Verb. Circle begins at: (x + radius, y), continuing
+ clockwise if dir is kCW_Direction, and counterclockwise if dir is kCCW_Direction.
+
+ Has no effect if radius is zero or negative.
+
+ @param x center of circle
+ @param y center of circle
+ @param radius distance from center to edge
+ @param dir SkPath::Direction to wind circle
+ @return reference to SkPath
+ */
+ SkPath& addCircle(SkScalar x, SkScalar y, SkScalar radius,
+ SkPathDirection dir = SkPathDirection::kCW);
+
+ /** Appends arc to SkPath, as the start of new contour. Arc added is part of ellipse
+ bounded by oval, from startAngle through sweepAngle. Both startAngle and
+ sweepAngle are measured in degrees, where zero degrees is aligned with the
+ positive x-axis, and positive sweeps extends arc clockwise.
+
+ If sweepAngle <= -360, or sweepAngle >= 360; and startAngle modulo 90 is nearly
+ zero, append oval instead of arc. Otherwise, sweepAngle values are treated
+ modulo 360, and arc may or may not draw depending on numeric rounding.
+
+ @param oval bounds of ellipse containing arc
+ @param startAngle starting angle of arc in degrees
+ @param sweepAngle sweep, in degrees. Positive is clockwise; treated modulo 360
+ @return reference to SkPath
+
+ example: https://fiddle.skia.org/c/@Path_addArc
+ */
+ SkPath& addArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle);
+
+ /** Appends SkRRect to SkPath, creating a new closed contour. SkRRect has bounds
+ equal to rect; each corner is 90 degrees of an ellipse with radii (rx, ry). If
+ dir is kCW_Direction, SkRRect starts at top-left of the lower-left corner and
+ winds clockwise. If dir is kCCW_Direction, SkRRect starts at the bottom-left
+ of the upper-left corner and winds counterclockwise.
+
+ If either rx or ry is too large, rx and ry are scaled uniformly until the
+ corners fit. If rx or ry is less than or equal to zero, addRoundRect() appends
+ SkRect rect to SkPath.
+
+ After appending, SkPath may be empty, or may contain: SkRect, oval, or SkRRect.
+
+ @param rect bounds of SkRRect
+ @param rx x-axis radius of rounded corners on the SkRRect
+ @param ry y-axis radius of rounded corners on the SkRRect
+ @param dir SkPath::Direction to wind SkRRect
+ @return reference to SkPath
+ */
+ SkPath& addRoundRect(const SkRect& rect, SkScalar rx, SkScalar ry,
+ SkPathDirection dir = SkPathDirection::kCW);
+
+ /** Appends SkRRect to SkPath, creating a new closed contour. SkRRect has bounds
+ equal to rect; each corner is 90 degrees of an ellipse with radii from the
+ array.
+
+ @param rect bounds of SkRRect
+ @param radii array of 8 SkScalar values, a radius pair for each corner
+ @param dir SkPath::Direction to wind SkRRect
+ @return reference to SkPath
+ */
+ SkPath& addRoundRect(const SkRect& rect, const SkScalar radii[],
+ SkPathDirection dir = SkPathDirection::kCW);
+
+ /** Adds rrect to SkPath, creating a new closed contour. If
+ dir is kCW_Direction, rrect starts at top-left of the lower-left corner and
+ winds clockwise. If dir is kCCW_Direction, rrect starts at the bottom-left
+ of the upper-left corner and winds counterclockwise.
+
+ After appending, SkPath may be empty, or may contain: SkRect, oval, or SkRRect.
+
+ @param rrect bounds and radii of rounded rectangle
+ @param dir SkPath::Direction to wind SkRRect
+ @return reference to SkPath
+
+ example: https://fiddle.skia.org/c/@Path_addRRect
+ */
+ SkPath& addRRect(const SkRRect& rrect, SkPathDirection dir = SkPathDirection::kCW);
+
+ /** Adds rrect to SkPath, creating a new closed contour. If dir is kCW_Direction, rrect
+ winds clockwise; if dir is kCCW_Direction, rrect winds counterclockwise.
+ start determines the first point of rrect to add.
+
+ @param rrect bounds and radii of rounded rectangle
+ @param dir SkPath::Direction to wind SkRRect
+ @param start index of initial point of SkRRect
+ @return reference to SkPath
+
+ example: https://fiddle.skia.org/c/@Path_addRRect_2
+ */
+ SkPath& addRRect(const SkRRect& rrect, SkPathDirection dir, unsigned start);
+
+ /** Adds contour created from line array, adding (count - 1) line segments.
+ Contour added starts at pts[0], then adds a line for every additional SkPoint
+ in pts array. If close is true, appends kClose_Verb to SkPath, connecting
+ pts[count - 1] and pts[0].
+
+ If count is zero, append kMove_Verb to path.
+ Has no effect if count is less than one.
+
+ @param pts array of line sharing end and start SkPoint
+ @param count length of SkPoint array
+ @param close true to add line connecting contour end and start
+ @return reference to SkPath
+
+ example: https://fiddle.skia.org/c/@Path_addPoly
+ */
+ SkPath& addPoly(const SkPoint pts[], int count, bool close);
+
+ /** Adds contour created from list. Contour added starts at list[0], then adds a line
+ for every additional SkPoint in list. If close is true, appends kClose_Verb to SkPath,
+ connecting last and first SkPoint in list.
+
+ If list is empty, append kMove_Verb to path.
+
+ @param list array of SkPoint
+ @param close true to add line connecting contour end and start
+ @return reference to SkPath
+ */
+ SkPath& addPoly(const std::initializer_list<SkPoint>& list, bool close) {
+ return this->addPoly(list.begin(), SkToInt(list.size()), close);
+ }
+
+#ifdef SK_HIDE_PATH_EDIT_METHODS
+public:
+#endif
+
+ /** \enum SkPath::AddPathMode
+ AddPathMode chooses how addPath() appends. Adding one SkPath to another can extend
+ the last contour or start a new contour.
+ */
+ enum AddPathMode {
+ kAppend_AddPathMode, //!< appended to destination unaltered
+ kExtend_AddPathMode, //!< add line if prior contour is not closed
+ };
+
+ /** Appends src to SkPath, offset by (dx, dy).
+
+ If mode is kAppend_AddPathMode, src verb array, SkPoint array, and conic weights are
+ added unaltered. If mode is kExtend_AddPathMode, add line before appending
+ verbs, SkPoint, and conic weights.
+
+ @param src SkPath verbs, SkPoint, and conic weights to add
+ @param dx offset added to src SkPoint array x-axis coordinates
+ @param dy offset added to src SkPoint array y-axis coordinates
+ @param mode kAppend_AddPathMode or kExtend_AddPathMode
+ @return reference to SkPath
+ */
+ SkPath& addPath(const SkPath& src, SkScalar dx, SkScalar dy,
+ AddPathMode mode = kAppend_AddPathMode);
+
+ /** Appends src to SkPath.
+
+ If mode is kAppend_AddPathMode, src verb array, SkPoint array, and conic weights are
+ added unaltered. If mode is kExtend_AddPathMode, add line before appending
+ verbs, SkPoint, and conic weights.
+
+ @param src SkPath verbs, SkPoint, and conic weights to add
+ @param mode kAppend_AddPathMode or kExtend_AddPathMode
+ @return reference to SkPath
+ */
+ SkPath& addPath(const SkPath& src, AddPathMode mode = kAppend_AddPathMode) {
+ SkMatrix m;
+ m.reset();
+ return this->addPath(src, m, mode);
+ }
+
+ /** Appends src to SkPath, transformed by matrix. Transformed curves may have different
+ verbs, SkPoint, and conic weights.
+
+ If mode is kAppend_AddPathMode, src verb array, SkPoint array, and conic weights are
+ added unaltered. If mode is kExtend_AddPathMode, add line before appending
+ verbs, SkPoint, and conic weights.
+
+ @param src SkPath verbs, SkPoint, and conic weights to add
+ @param matrix transform applied to src
+ @param mode kAppend_AddPathMode or kExtend_AddPathMode
+ @return reference to SkPath
+ */
+ SkPath& addPath(const SkPath& src, const SkMatrix& matrix,
+ AddPathMode mode = kAppend_AddPathMode);
+
+ /** Appends src to SkPath, from back to front.
+ Reversed src always appends a new contour to SkPath.
+
+ @param src SkPath verbs, SkPoint, and conic weights to add
+ @return reference to SkPath
+
+ example: https://fiddle.skia.org/c/@Path_reverseAddPath
+ */
+ SkPath& reverseAddPath(const SkPath& src);
+
+ /** Offsets SkPoint array by (dx, dy). Offset SkPath replaces dst.
+ If dst is nullptr, SkPath is replaced by offset data.
+
+ @param dx offset added to SkPoint array x-axis coordinates
+ @param dy offset added to SkPoint array y-axis coordinates
+ @param dst overwritten, translated copy of SkPath; may be nullptr
+
+ example: https://fiddle.skia.org/c/@Path_offset
+ */
+ void offset(SkScalar dx, SkScalar dy, SkPath* dst) const;
+
+ /** Offsets SkPoint array by (dx, dy). SkPath is replaced by offset data.
+
+ @param dx offset added to SkPoint array x-axis coordinates
+ @param dy offset added to SkPoint array y-axis coordinates
+ */
+ void offset(SkScalar dx, SkScalar dy) {
+ this->offset(dx, dy, this);
+ }
+
+ /** Transforms verb array, SkPoint array, and weight by matrix.
+ transform may change verbs and increase their number.
+ Transformed SkPath replaces dst; if dst is nullptr, original data
+ is replaced.
+
+ @param matrix SkMatrix to apply to SkPath
+ @param dst overwritten, transformed copy of SkPath; may be nullptr
+ @param pc whether to apply perspective clipping
+
+ example: https://fiddle.skia.org/c/@Path_transform
+ */
+ void transform(const SkMatrix& matrix, SkPath* dst,
+ SkApplyPerspectiveClip pc = SkApplyPerspectiveClip::kYes) const;
+
+ /** Transforms verb array, SkPoint array, and weight by matrix.
+ transform may change verbs and increase their number.
+ SkPath is replaced by transformed data.
+
+ @param matrix SkMatrix to apply to SkPath
+ @param pc whether to apply perspective clipping
+ */
+ void transform(const SkMatrix& matrix,
+ SkApplyPerspectiveClip pc = SkApplyPerspectiveClip::kYes) {
+ this->transform(matrix, this, pc);
+ }
+
+ SkPath makeTransform(const SkMatrix& m,
+ SkApplyPerspectiveClip pc = SkApplyPerspectiveClip::kYes) const {
+ SkPath dst;
+ this->transform(m, &dst, pc);
+ return dst;
+ }
+
+ SkPath makeScale(SkScalar sx, SkScalar sy) {
+ return this->makeTransform(SkMatrix::Scale(sx, sy), SkApplyPerspectiveClip::kNo);
+ }
+
+ /** Returns last point on SkPath in lastPt. Returns false if SkPoint array is empty,
+ storing (0, 0) if lastPt is not nullptr.
+
+ @param lastPt storage for final SkPoint in SkPoint array; may be nullptr
+ @return true if SkPoint array contains one or more SkPoint
+
+ example: https://fiddle.skia.org/c/@Path_getLastPt
+ */
+ bool getLastPt(SkPoint* lastPt) const;
+
+ /** Sets last point to (x, y). If SkPoint array is empty, append kMove_Verb to
+ verb array and append (x, y) to SkPoint array.
+
+ @param x set x-axis value of last point
+ @param y set y-axis value of last point
+
+ example: https://fiddle.skia.org/c/@Path_setLastPt
+ */
+ void setLastPt(SkScalar x, SkScalar y);
+
+ /** Sets the last point on the path. If SkPoint array is empty, append kMove_Verb to
+ verb array and append p to SkPoint array.
+
+ @param p set value of last point
+ */
+ void setLastPt(const SkPoint& p) {
+ this->setLastPt(p.fX, p.fY);
+ }
+
+ /** \enum SkPath::SegmentMask
+ SegmentMask constants correspond to each drawing Verb type in SkPath; for
+ instance, if SkPath only contains lines, only the kLine_SegmentMask bit is set.
+ */
+ enum SegmentMask {
+ kLine_SegmentMask = kLine_SkPathSegmentMask,
+ kQuad_SegmentMask = kQuad_SkPathSegmentMask,
+ kConic_SegmentMask = kConic_SkPathSegmentMask,
+ kCubic_SegmentMask = kCubic_SkPathSegmentMask,
+ };
+
+ /** Returns a mask, where each set bit corresponds to a SegmentMask constant
+ if SkPath contains one or more verbs of that type.
+ Returns zero if SkPath contains no lines, or curves: quads, conics, or cubics.
+
+ getSegmentMasks() returns a cached result; it is very fast.
+
+ @return SegmentMask bits or zero
+ */
+ uint32_t getSegmentMasks() const { return fPathRef->getSegmentMasks(); }
+
+ /** \enum SkPath::Verb
+ Verb instructs SkPath how to interpret one or more SkPoint and optional conic weight;
+ manage contour, and terminate SkPath.
+ */
+ enum Verb {
+ kMove_Verb = static_cast<int>(SkPathVerb::kMove),
+ kLine_Verb = static_cast<int>(SkPathVerb::kLine),
+ kQuad_Verb = static_cast<int>(SkPathVerb::kQuad),
+ kConic_Verb = static_cast<int>(SkPathVerb::kConic),
+ kCubic_Verb = static_cast<int>(SkPathVerb::kCubic),
+ kClose_Verb = static_cast<int>(SkPathVerb::kClose),
+ kDone_Verb = kClose_Verb + 1
+ };
+
+ /** \class SkPath::Iter
+ Iterates through verb array, and associated SkPoint array and conic weight.
+ Provides options to treat open contours as closed, and to ignore
+ degenerate data.
+ */
+ class SK_API Iter {
+ public:
+
+ /** Initializes SkPath::Iter with an empty SkPath. next() on SkPath::Iter returns
+ kDone_Verb.
+ Call setPath to initialize SkPath::Iter at a later time.
+
+ @return SkPath::Iter of empty SkPath
+
+ example: https://fiddle.skia.org/c/@Path_Iter_Iter
+ */
+ Iter();
+
+ /** Sets SkPath::Iter to return elements of verb array, SkPoint array, and conic weight in
+ path. If forceClose is true, SkPath::Iter will add kLine_Verb and kClose_Verb after each
+ open contour. path is not altered.
+
+ @param path SkPath to iterate
+ @param forceClose true if open contours generate kClose_Verb
+ @return SkPath::Iter of path
+
+ example: https://fiddle.skia.org/c/@Path_Iter_const_SkPath
+ */
+ Iter(const SkPath& path, bool forceClose);
+
+ /** Sets SkPath::Iter to return elements of verb array, SkPoint array, and conic weight in
+ path. If forceClose is true, SkPath::Iter will add kLine_Verb and kClose_Verb after each
+ open contour. path is not altered.
+
+ @param path SkPath to iterate
+ @param forceClose true if open contours generate kClose_Verb
+
+ example: https://fiddle.skia.org/c/@Path_Iter_setPath
+ */
+ void setPath(const SkPath& path, bool forceClose);
+
+ /** Returns next SkPath::Verb in verb array, and advances SkPath::Iter.
+ When verb array is exhausted, returns kDone_Verb.
+
+ Zero to four SkPoint are stored in pts, depending on the returned SkPath::Verb.
+
+ @param pts storage for SkPoint data describing returned SkPath::Verb
+ @return next SkPath::Verb from verb array
+
+ example: https://fiddle.skia.org/c/@Path_RawIter_next
+ */
+ Verb next(SkPoint pts[4]);
+
+ /** Returns conic weight if next() returned kConic_Verb.
+
+ If next() has not been called, or next() did not return kConic_Verb,
+ result is undefined.
+
+ @return conic weight for conic SkPoint returned by next()
+ */
+ SkScalar conicWeight() const { return *fConicWeights; }
+
+ /** Returns true if last kLine_Verb returned by next() was generated
+ by kClose_Verb. When true, the end point returned by next() is
+ also the start point of contour.
+
+ If next() has not been called, or next() did not return kLine_Verb,
+ result is undefined.
+
+ @return true if last kLine_Verb was generated by kClose_Verb
+ */
+ bool isCloseLine() const { return SkToBool(fCloseLine); }
+
+ /** Returns true if subsequent calls to next() return kClose_Verb before returning
+ kMove_Verb. if true, contour SkPath::Iter is processing may end with kClose_Verb, or
+ SkPath::Iter may have been initialized with force close set to true.
+
+ @return true if contour is closed
+
+ example: https://fiddle.skia.org/c/@Path_Iter_isClosedContour
+ */
+ bool isClosedContour() const;
+
+ private:
+ const SkPoint* fPts;
+ const uint8_t* fVerbs;
+ const uint8_t* fVerbStop;
+ const SkScalar* fConicWeights;
+ SkPoint fMoveTo;
+ SkPoint fLastPt;
+ bool fForceClose;
+ bool fNeedClose;
+ bool fCloseLine;
+
+ Verb autoClose(SkPoint pts[2]);
+ };
+
+private:
+ /** \class SkPath::RangeIter
+ Iterates through a raw range of path verbs, points, and conics. All values are returned
+ unaltered.
+
+ NOTE: This class will be moved into SkPathPriv once RangeIter is removed.
+ */
+ class RangeIter {
+ public:
+ RangeIter() = default;
+ RangeIter(const uint8_t* verbs, const SkPoint* points, const SkScalar* weights)
+ : fVerb(verbs), fPoints(points), fWeights(weights) {
+ SkDEBUGCODE(fInitialPoints = fPoints;)
+ }
+ bool operator!=(const RangeIter& that) const {
+ return fVerb != that.fVerb;
+ }
+ bool operator==(const RangeIter& that) const {
+ return fVerb == that.fVerb;
+ }
+ RangeIter& operator++() {
+ auto verb = static_cast<SkPathVerb>(*fVerb++);
+ fPoints += pts_advance_after_verb(verb);
+ if (verb == SkPathVerb::kConic) {
+ ++fWeights;
+ }
+ return *this;
+ }
+ RangeIter operator++(int) {
+ RangeIter copy = *this;
+ this->operator++();
+ return copy;
+ }
+ SkPathVerb peekVerb() const {
+ return static_cast<SkPathVerb>(*fVerb);
+ }
+ std::tuple<SkPathVerb, const SkPoint*, const SkScalar*> operator*() const {
+ SkPathVerb verb = this->peekVerb();
+ // We provide the starting point for beziers by peeking backwards from the current
+ // point, which works fine as long as there is always a kMove before any geometry.
+ // (SkPath::injectMoveToIfNeeded should have guaranteed this to be the case.)
+ int backset = pts_backset_for_verb(verb);
+ SkASSERT(fPoints + backset >= fInitialPoints);
+ return {verb, fPoints + backset, fWeights};
+ }
+ private:
+ constexpr static int pts_advance_after_verb(SkPathVerb verb) {
+ switch (verb) {
+ case SkPathVerb::kMove: return 1;
+ case SkPathVerb::kLine: return 1;
+ case SkPathVerb::kQuad: return 2;
+ case SkPathVerb::kConic: return 2;
+ case SkPathVerb::kCubic: return 3;
+ case SkPathVerb::kClose: return 0;
+ }
+ SkUNREACHABLE;
+ }
+ constexpr static int pts_backset_for_verb(SkPathVerb verb) {
+ switch (verb) {
+ case SkPathVerb::kMove: return 0;
+ case SkPathVerb::kLine: return -1;
+ case SkPathVerb::kQuad: return -1;
+ case SkPathVerb::kConic: return -1;
+ case SkPathVerb::kCubic: return -1;
+ case SkPathVerb::kClose: return -1;
+ }
+ SkUNREACHABLE;
+ }
+ const uint8_t* fVerb = nullptr;
+ const SkPoint* fPoints = nullptr;
+ const SkScalar* fWeights = nullptr;
+ SkDEBUGCODE(const SkPoint* fInitialPoints = nullptr;)
+ };
+public:
+
+ /** \class SkPath::RawIter
+ Use Iter instead. This class will soon be removed and RangeIter will be made private.
+ */
+ class SK_API RawIter {
+ public:
+
+ /** Initializes RawIter with an empty SkPath. next() on RawIter returns kDone_Verb.
+ Call setPath to initialize SkPath::Iter at a later time.
+
+ @return RawIter of empty SkPath
+ */
+ RawIter() {}
+
+ /** Sets RawIter to return elements of verb array, SkPoint array, and conic weight in path.
+
+ @param path SkPath to iterate
+ @return RawIter of path
+ */
+ RawIter(const SkPath& path) {
+ setPath(path);
+ }
+
+ /** Sets SkPath::Iter to return elements of verb array, SkPoint array, and conic weight in
+ path.
+
+ @param path SkPath to iterate
+ */
+ void setPath(const SkPath&);
+
+ /** Returns next SkPath::Verb in verb array, and advances RawIter.
+ When verb array is exhausted, returns kDone_Verb.
+ Zero to four SkPoint are stored in pts, depending on the returned SkPath::Verb.
+
+ @param pts storage for SkPoint data describing returned SkPath::Verb
+ @return next SkPath::Verb from verb array
+ */
+ Verb next(SkPoint[4]);
+
+ /** Returns next SkPath::Verb, but does not advance RawIter.
+
+ @return next SkPath::Verb from verb array
+ */
+ Verb peek() const {
+ return (fIter != fEnd) ? static_cast<Verb>(std::get<0>(*fIter)) : kDone_Verb;
+ }
+
+ /** Returns conic weight if next() returned kConic_Verb.
+
+ If next() has not been called, or next() did not return kConic_Verb,
+ result is undefined.
+
+ @return conic weight for conic SkPoint returned by next()
+ */
+ SkScalar conicWeight() const {
+ return fConicWeight;
+ }
+
+ private:
+ RangeIter fIter;
+ RangeIter fEnd;
+ SkScalar fConicWeight = 0;
+ friend class SkPath;
+
+ };
+
+ /** Returns true if the point (x, y) is contained by SkPath, taking into
+ account FillType.
+
+ @param x x-axis value of containment test
+ @param y y-axis value of containment test
+ @return true if SkPoint is in SkPath
+
+ example: https://fiddle.skia.org/c/@Path_contains
+ */
+ bool contains(SkScalar x, SkScalar y) const;
+
+ /** Writes text representation of SkPath to stream. If stream is nullptr, writes to
+ standard output. Set dumpAsHex true to generate exact binary representations
+ of floating point numbers used in SkPoint array and conic weights.
+
+ @param stream writable SkWStream receiving SkPath text representation; may be nullptr
+ @param dumpAsHex true if SkScalar values are written as hexadecimal
+
+ example: https://fiddle.skia.org/c/@Path_dump
+ */
+ void dump(SkWStream* stream, bool dumpAsHex) const;
+
+ void dump() const { this->dump(nullptr, false); }
+ void dumpHex() const { this->dump(nullptr, true); }
+
+ // Like dump(), but outputs for the SkPath::Make() factory
+ void dumpArrays(SkWStream* stream, bool dumpAsHex) const;
+ void dumpArrays() const { this->dumpArrays(nullptr, false); }
+
+ /** Writes SkPath to buffer, returning the number of bytes written.
+ Pass nullptr to obtain the storage size.
+
+ Writes SkPath::FillType, verb array, SkPoint array, conic weight, and
+ additionally writes computed information like SkPath::Convexity and bounds.
+
+ Use only be used in concert with readFromMemory();
+ the format used for SkPath in memory is not guaranteed.
+
+ @param buffer storage for SkPath; may be nullptr
+ @return size of storage required for SkPath; always a multiple of 4
+
+ example: https://fiddle.skia.org/c/@Path_writeToMemory
+ */
+ size_t writeToMemory(void* buffer) const;
+
+ /** Writes SkPath to buffer, returning the buffer written to, wrapped in SkData.
+
+ serialize() writes SkPath::FillType, verb array, SkPoint array, conic weight, and
+ additionally writes computed information like SkPath::Convexity and bounds.
+
+ serialize() should only be used in concert with readFromMemory().
+ The format used for SkPath in memory is not guaranteed.
+
+ @return SkPath data wrapped in SkData buffer
+
+ example: https://fiddle.skia.org/c/@Path_serialize
+ */
+ sk_sp<SkData> serialize() const;
+
+ /** Initializes SkPath from buffer of size length. Returns zero if the buffer is
+ data is inconsistent, or the length is too small.
+
+ Reads SkPath::FillType, verb array, SkPoint array, conic weight, and
+ additionally reads computed information like SkPath::Convexity and bounds.
+
+ Used only in concert with writeToMemory();
+ the format used for SkPath in memory is not guaranteed.
+
+ @param buffer storage for SkPath
+ @param length buffer size in bytes; must be multiple of 4
+ @return number of bytes read, or zero on failure
+
+ example: https://fiddle.skia.org/c/@Path_readFromMemory
+ */
+ size_t readFromMemory(const void* buffer, size_t length);
+
+ /** (See Skia bug 1762.)
+ Returns a non-zero, globally unique value. A different value is returned
+ if verb array, SkPoint array, or conic weight changes.
+
+ Setting SkPath::FillType does not change generation identifier.
+
+ Each time the path is modified, a different generation identifier will be returned.
+ SkPath::FillType does affect generation identifier on Android framework.
+
+ @return non-zero, globally unique value
+
+ example: https://fiddle.skia.org/c/@Path_getGenerationID
+ */
+ uint32_t getGenerationID() const;
+
+ /** Returns if SkPath data is consistent. Corrupt SkPath data is detected if
+ internal values are out of range or internal storage does not match
+ array dimensions.
+
+ @return true if SkPath data is consistent
+ */
+ bool isValid() const { return this->isValidImpl() && fPathRef->isValid(); }
+
+private:
+ SkPath(sk_sp<SkPathRef>, SkPathFillType, bool isVolatile, SkPathConvexity,
+ SkPathFirstDirection firstDirection);
+
+ sk_sp<SkPathRef> fPathRef;
+ int fLastMoveToIndex;
+ mutable std::atomic<uint8_t> fConvexity; // SkPathConvexity
+ mutable std::atomic<uint8_t> fFirstDirection; // SkPathFirstDirection
+ uint8_t fFillType : 2;
+ uint8_t fIsVolatile : 1;
+
+ /** Resets all fields other than fPathRef to their initial 'empty' values.
+ * Assumes the caller has already emptied fPathRef.
+ * On Android increments fGenerationID without reseting it.
+ */
+ void resetFields();
+
+ /** Sets all fields other than fPathRef to the values in 'that'.
+ * Assumes the caller has already set fPathRef.
+ * Doesn't change fGenerationID or fSourcePath on Android.
+ */
+ void copyFields(const SkPath& that);
+
+ size_t writeToMemoryAsRRect(void* buffer) const;
+ size_t readAsRRect(const void*, size_t);
+ size_t readFromMemory_EQ4Or5(const void*, size_t);
+
+ friend class Iter;
+ friend class SkPathPriv;
+ friend class SkPathStroker;
+
+ /* Append, in reverse order, the first contour of path, ignoring path's
+ last point. If no moveTo() call has been made for this contour, the
+ first point is automatically set to (0,0).
+ */
+ SkPath& reversePathTo(const SkPath&);
+
+ // called before we add points for lineTo, quadTo, cubicTo, checking to see
+ // if we need to inject a leading moveTo first
+ //
+ // SkPath path; path.lineTo(...); <--- need a leading moveTo(0, 0)
+ // SkPath path; ... path.close(); path.lineTo(...) <-- need a moveTo(previous moveTo)
+ //
+ inline void injectMoveToIfNeeded();
+
+ inline bool hasOnlyMoveTos() const;
+
+ SkPathConvexity computeConvexity() const;
+
+ /** Asserts if SkPath data is inconsistent.
+ Debugging check intended for internal use only.
+ */
+ SkDEBUGCODE(void validate() const { SkASSERT(this->isValidImpl()); } )
+ bool isValidImpl() const;
+ SkDEBUGCODE(void validateRef() const { fPathRef->validate(); } )
+
+ // called by stroker to see if all points (in the last contour) are equal and worthy of a cap
+ bool isZeroLengthSincePoint(int startPtIndex) const;
+
+ /** Returns if the path can return a bound at no cost (true) or will have to
+ perform some computation (false).
+ */
+ bool hasComputedBounds() const {
+ SkDEBUGCODE(this->validate();)
+ return fPathRef->hasComputedBounds();
+ }
+
+
+ // 'rect' needs to be sorted
+ void setBounds(const SkRect& rect) {
+ SkPathRef::Editor ed(&fPathRef);
+
+ ed.setBounds(rect);
+ }
+
+ void setPt(int index, SkScalar x, SkScalar y);
+
+ SkPath& dirtyAfterEdit();
+
+ // Bottlenecks for working with fConvexity and fFirstDirection.
+ // Notice the setters are const... these are mutable atomic fields.
+ void setConvexity(SkPathConvexity) const;
+
+ void setFirstDirection(SkPathFirstDirection) const;
+ SkPathFirstDirection getFirstDirection() const;
+
+ /** Returns the comvexity type, computing if needed. Never returns kUnknown.
+ @return path's convexity type (convex or concave)
+ */
+ SkPathConvexity getConvexity() const;
+
+ SkPathConvexity getConvexityOrUnknown() const {
+ return (SkPathConvexity)fConvexity.load(std::memory_order_relaxed);
+ }
+
+ // Compares the cached value with a freshly computed one (computeConvexity())
+ bool isConvexityAccurate() const;
+
+ /** Stores a convexity type for this path. This is what will be returned if
+ * getConvexityOrUnknown() is called. If you pass kUnknown, then if getContexityType()
+ * is called, the real convexity will be computed.
+ *
+ * example: https://fiddle.skia.org/c/@Path_setConvexity
+ */
+ void setConvexity(SkPathConvexity convexity);
+
+ /** Shrinks SkPath verb array and SkPoint array storage to discard unused capacity.
+ * May reduce the heap overhead for SkPath known to be fully constructed.
+ *
+ * NOTE: This may relocate the underlying buffers, and thus any Iterators referencing
+ * this path should be discarded after calling shrinkToFit().
+ */
+ void shrinkToFit();
+
+ friend class SkAutoPathBoundsUpdate;
+ friend class SkAutoDisableOvalCheck;
+ friend class SkAutoDisableDirectionCheck;
+ friend class SkPathBuilder;
+ friend class SkPathEdgeIter;
+ friend class SkPathWriter;
+ friend class SkOpBuilder;
+ friend class SkBench_AddPathTest; // perf test reversePathTo
+ friend class PathTest_Private; // unit test reversePathTo
+ friend class ForceIsRRect_Private; // unit test isRRect
+ friend class FuzzPath; // for legacy access to validateRef
+};
+
+#endif
diff --git a/src/deps/skia/include/core/SkPathBuilder.h b/src/deps/skia/include/core/SkPathBuilder.h
new file mode 100644
index 000000000..ec10de87e
--- /dev/null
+++ b/src/deps/skia/include/core/SkPathBuilder.h
@@ -0,0 +1,268 @@
+/*
+ * Copyright 2015 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkPathBuilder_DEFINED
+#define SkPathBuilder_DEFINED
+
+#include "include/core/SkMatrix.h"
+#include "include/core/SkPath.h"
+#include "include/core/SkPathTypes.h"
+#include "include/private/SkTDArray.h"
+
+class SK_API SkPathBuilder {
+public:
+ SkPathBuilder();
+ SkPathBuilder(SkPathFillType);
+ SkPathBuilder(const SkPath&);
+ SkPathBuilder(const SkPathBuilder&) = default;
+ ~SkPathBuilder();
+
+ SkPathBuilder& operator=(const SkPath&);
+ SkPathBuilder& operator=(const SkPathBuilder&) = default;
+
+ SkPathFillType fillType() const { return fFillType; }
+ SkRect computeBounds() const;
+
+ SkPath snapshot() const; // the builder is unchanged after returning this path
+ SkPath detach(); // the builder is reset to empty after returning this path
+
+ SkPathBuilder& setFillType(SkPathFillType ft) { fFillType = ft; return *this; }
+ SkPathBuilder& setIsVolatile(bool isVolatile) { fIsVolatile = isVolatile; return *this; }
+
+ SkPathBuilder& reset();
+
+ SkPathBuilder& moveTo(SkPoint pt);
+ SkPathBuilder& moveTo(SkScalar x, SkScalar y) { return this->moveTo(SkPoint::Make(x, y)); }
+
+ SkPathBuilder& lineTo(SkPoint pt);
+ SkPathBuilder& lineTo(SkScalar x, SkScalar y) { return this->lineTo(SkPoint::Make(x, y)); }
+
+ SkPathBuilder& quadTo(SkPoint pt1, SkPoint pt2);
+ SkPathBuilder& quadTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2) {
+ return this->quadTo(SkPoint::Make(x1, y1), SkPoint::Make(x2, y2));
+ }
+ SkPathBuilder& quadTo(const SkPoint pts[2]) { return this->quadTo(pts[0], pts[1]); }
+
+ SkPathBuilder& conicTo(SkPoint pt1, SkPoint pt2, SkScalar w);
+ SkPathBuilder& conicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, SkScalar w) {
+ return this->conicTo(SkPoint::Make(x1, y1), SkPoint::Make(x2, y2), w);
+ }
+ SkPathBuilder& conicTo(const SkPoint pts[2], SkScalar w) {
+ return this->conicTo(pts[0], pts[1], w);
+ }
+
+ SkPathBuilder& cubicTo(SkPoint pt1, SkPoint pt2, SkPoint pt3);
+ SkPathBuilder& cubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, SkScalar x3, SkScalar y3) {
+ return this->cubicTo(SkPoint::Make(x1, y1), SkPoint::Make(x2, y2), SkPoint::Make(x3, y3));
+ }
+ SkPathBuilder& cubicTo(const SkPoint pts[3]) {
+ return this->cubicTo(pts[0], pts[1], pts[2]);
+ }
+
+ SkPathBuilder& close();
+
+ // Append a series of lineTo(...)
+ SkPathBuilder& polylineTo(const SkPoint pts[], int count);
+ SkPathBuilder& polylineTo(const std::initializer_list<SkPoint>& list) {
+ return this->polylineTo(list.begin(), SkToInt(list.size()));
+ }
+
+ // Relative versions of segments, relative to the previous position.
+
+ SkPathBuilder& rLineTo(SkPoint pt);
+ SkPathBuilder& rLineTo(SkScalar x, SkScalar y) { return this->rLineTo({x, y}); }
+ SkPathBuilder& rQuadTo(SkPoint pt1, SkPoint pt2);
+ SkPathBuilder& rQuadTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2) {
+ return this->rQuadTo({x1, y1}, {x2, y2});
+ }
+ SkPathBuilder& rConicTo(SkPoint p1, SkPoint p2, SkScalar w);
+ SkPathBuilder& rConicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, SkScalar w) {
+ return this->rConicTo({x1, y1}, {x2, y2}, w);
+ }
+ SkPathBuilder& rCubicTo(SkPoint pt1, SkPoint pt2, SkPoint pt3);
+ SkPathBuilder& rCubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, SkScalar x3, SkScalar y3) {
+ return this->rCubicTo({x1, y1}, {x2, y2}, {x3, y3});
+ }
+
+ // Arcs
+
+ /** Appends arc to the builder. Arc added is part of ellipse
+ bounded by oval, from startAngle through sweepAngle. Both startAngle and
+ sweepAngle are measured in degrees, where zero degrees is aligned with the
+ positive x-axis, and positive sweeps extends arc clockwise.
+
+ arcTo() adds line connecting the builder's last point to initial arc point if forceMoveTo
+ is false and the builder is not empty. Otherwise, added contour begins with first point
+ of arc. Angles greater than -360 and less than 360 are treated modulo 360.
+
+ @param oval bounds of ellipse containing arc
+ @param startAngleDeg starting angle of arc in degrees
+ @param sweepAngleDeg sweep, in degrees. Positive is clockwise; treated modulo 360
+ @param forceMoveTo true to start a new contour with arc
+ @return reference to the builder
+ */
+ SkPathBuilder& arcTo(const SkRect& oval, SkScalar startAngleDeg, SkScalar sweepAngleDeg,
+ bool forceMoveTo);
+
+ /** Appends arc to SkPath, after appending line if needed. Arc is implemented by conic
+ weighted to describe part of circle. Arc is contained by tangent from
+ last SkPath point to p1, and tangent from p1 to p2. Arc
+ is part of circle sized to radius, positioned so it touches both tangent lines.
+
+ If last SkPath SkPoint does not start arc, arcTo() appends connecting line to SkPath.
+ The length of vector from p1 to p2 does not affect arc.
+
+ Arc sweep is always less than 180 degrees. If radius is zero, or if
+ tangents are nearly parallel, arcTo() appends line from last SkPath SkPoint to p1.
+
+ arcTo() appends at most one line and one conic.
+ arcTo() implements the functionality of PostScript arct and HTML Canvas arcTo.
+
+ @param p1 SkPoint common to pair of tangents
+ @param p2 end of second tangent
+ @param radius distance from arc to circle center
+ @return reference to SkPath
+ */
+ SkPathBuilder& arcTo(SkPoint p1, SkPoint p2, SkScalar radius);
+
+ enum ArcSize {
+ kSmall_ArcSize, //!< smaller of arc pair
+ kLarge_ArcSize, //!< larger of arc pair
+ };
+
+ /** Appends arc to SkPath. Arc is implemented by one or more conic weighted to describe
+ part of oval with radii (r.fX, r.fY) rotated by xAxisRotate degrees. Arc curves
+ from last SkPath SkPoint to (xy.fX, xy.fY), choosing one of four possible routes:
+ clockwise or counterclockwise,
+ and smaller or larger.
+
+ Arc sweep is always less than 360 degrees. arcTo() appends line to xy if either
+ radii are zero, or if last SkPath SkPoint equals (xy.fX, xy.fY). arcTo() scales radii r to
+ fit last SkPath SkPoint and xy if both are greater than zero but too small to describe
+ an arc.
+
+ arcTo() appends up to four conic curves.
+ arcTo() implements the functionality of SVG arc, although SVG sweep-flag value is
+ opposite the integer value of sweep; SVG sweep-flag uses 1 for clockwise, while
+ kCW_Direction cast to int is zero.
+
+ @param r radii on axes before x-axis rotation
+ @param xAxisRotate x-axis rotation in degrees; positive values are clockwise
+ @param largeArc chooses smaller or larger arc
+ @param sweep chooses clockwise or counterclockwise arc
+ @param xy end of arc
+ @return reference to SkPath
+ */
+ SkPathBuilder& arcTo(SkPoint r, SkScalar xAxisRotate, ArcSize largeArc, SkPathDirection sweep,
+ SkPoint xy);
+
+ /** Appends arc to the builder, as the start of new contour. Arc added is part of ellipse
+ bounded by oval, from startAngle through sweepAngle. Both startAngle and
+ sweepAngle are measured in degrees, where zero degrees is aligned with the
+ positive x-axis, and positive sweeps extends arc clockwise.
+
+ If sweepAngle <= -360, or sweepAngle >= 360; and startAngle modulo 90 is nearly
+ zero, append oval instead of arc. Otherwise, sweepAngle values are treated
+ modulo 360, and arc may or may not draw depending on numeric rounding.
+
+ @param oval bounds of ellipse containing arc
+ @param startAngleDeg starting angle of arc in degrees
+ @param sweepAngleDeg sweep, in degrees. Positive is clockwise; treated modulo 360
+ @return reference to this builder
+ */
+ SkPathBuilder& addArc(const SkRect& oval, SkScalar startAngleDeg, SkScalar sweepAngleDeg);
+
+ // Add a new contour
+
+ SkPathBuilder& addRect(const SkRect&, SkPathDirection, unsigned startIndex);
+ SkPathBuilder& addOval(const SkRect&, SkPathDirection, unsigned startIndex);
+ SkPathBuilder& addRRect(const SkRRect&, SkPathDirection, unsigned startIndex);
+
+ SkPathBuilder& addRect(const SkRect& rect, SkPathDirection dir = SkPathDirection::kCW) {
+ return this->addRect(rect, dir, 0);
+ }
+ SkPathBuilder& addOval(const SkRect& rect, SkPathDirection dir = SkPathDirection::kCW) {
+ // legacy start index: 1
+ return this->addOval(rect, dir, 1);
+ }
+ SkPathBuilder& addRRect(const SkRRect& rrect, SkPathDirection dir = SkPathDirection::kCW) {
+ // legacy start indices: 6 (CW) and 7 (CCW)
+ return this->addRRect(rrect, dir, dir == SkPathDirection::kCW ? 6 : 7);
+ }
+
+ SkPathBuilder& addCircle(SkScalar center_x, SkScalar center_y, SkScalar radius,
+ SkPathDirection dir = SkPathDirection::kCW);
+
+ SkPathBuilder& addPolygon(const SkPoint pts[], int count, bool isClosed);
+ SkPathBuilder& addPolygon(const std::initializer_list<SkPoint>& list, bool isClosed) {
+ return this->addPolygon(list.begin(), SkToInt(list.size()), isClosed);
+ }
+
+ SkPathBuilder& addPath(const SkPath&);
+
+ // Performance hint, to reserve extra storage for subsequent calls to lineTo, quadTo, etc.
+
+ void incReserve(int extraPtCount, int extraVerbCount);
+ void incReserve(int extraPtCount) {
+ this->incReserve(extraPtCount, extraPtCount);
+ }
+
+ SkPathBuilder& offset(SkScalar dx, SkScalar dy);
+
+ SkPathBuilder& toggleInverseFillType() {
+ fFillType = (SkPathFillType)((unsigned)fFillType ^ 2);
+ return *this;
+ }
+
+private:
+ SkTDArray<SkPoint> fPts;
+ SkTDArray<uint8_t> fVerbs;
+ SkTDArray<SkScalar> fConicWeights;
+
+ SkPathFillType fFillType;
+ bool fIsVolatile;
+
+ unsigned fSegmentMask;
+ SkPoint fLastMovePoint;
+ int fLastMoveIndex; // only needed until SkPath is immutable
+ bool fNeedsMoveVerb;
+
+ enum IsA {
+ kIsA_JustMoves, // we only have 0 or more moves
+ kIsA_MoreThanMoves, // we have verbs other than just move
+ kIsA_Oval, // we are 0 or more moves followed by an oval
+ kIsA_RRect, // we are 0 or more moves followed by a rrect
+ };
+ IsA fIsA = kIsA_JustMoves;
+ int fIsAStart = -1; // tracks direction iff fIsA is not unknown
+ bool fIsACCW = false; // tracks direction iff fIsA is not unknown
+
+ // for testing
+ SkPathConvexity fOverrideConvexity = SkPathConvexity::kUnknown;
+
+ int countVerbs() const { return fVerbs.count(); }
+
+ // called right before we add a (non-move) verb
+ void ensureMove() {
+ fIsA = kIsA_MoreThanMoves;
+ if (fNeedsMoveVerb) {
+ this->moveTo(fLastMovePoint);
+ }
+ }
+
+ SkPath make(sk_sp<SkPathRef>) const;
+
+ SkPathBuilder& privateReverseAddPath(const SkPath&);
+
+ // For testing
+ void privateSetConvexity(SkPathConvexity c) { fOverrideConvexity = c; }
+
+ friend class SkPathPriv;
+};
+
+#endif
+
diff --git a/src/deps/skia/include/core/SkPathEffect.h b/src/deps/skia/include/core/SkPathEffect.h
new file mode 100644
index 000000000..abb370c52
--- /dev/null
+++ b/src/deps/skia/include/core/SkPathEffect.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkPathEffect_DEFINED
+#define SkPathEffect_DEFINED
+
+#include "include/core/SkFlattenable.h"
+#include "include/core/SkScalar.h"
+// not needed, but some of our clients need it (they don't IWYU)
+#include "include/core/SkPath.h"
+
+class SkPath;
+struct SkRect;
+class SkStrokeRec;
+
+/** \class SkPathEffect
+
+ SkPathEffect is the base class for objects in the SkPaint that affect
+ the geometry of a drawing primitive before it is transformed by the
+ canvas' matrix and drawn.
+
+ Dashing is implemented as a subclass of SkPathEffect.
+*/
+class SK_API SkPathEffect : public SkFlattenable {
+public:
+ /**
+ * Returns a patheffect that apples each effect (first and second) to the original path,
+ * and returns a path with the sum of these.
+ *
+ * result = first(path) + second(path)
+ *
+ */
+ static sk_sp<SkPathEffect> MakeSum(sk_sp<SkPathEffect> first, sk_sp<SkPathEffect> second);
+
+ /**
+ * Returns a patheffect that applies the inner effect to the path, and then applies the
+ * outer effect to the result of the inner's.
+ *
+ * result = outer(inner(path))
+ */
+ static sk_sp<SkPathEffect> MakeCompose(sk_sp<SkPathEffect> outer, sk_sp<SkPathEffect> inner);
+
+ static SkFlattenable::Type GetFlattenableType() {
+ return kSkPathEffect_Type;
+ }
+
+ // move to base?
+
+ enum DashType {
+ kNone_DashType, //!< ignores the info parameter
+ kDash_DashType, //!< fills in all of the info parameter
+ };
+
+ struct DashInfo {
+ DashInfo() : fIntervals(nullptr), fCount(0), fPhase(0) {}
+ DashInfo(SkScalar* intervals, int32_t count, SkScalar phase)
+ : fIntervals(intervals), fCount(count), fPhase(phase) {}
+
+ SkScalar* fIntervals; //!< Length of on/off intervals for dashed lines
+ // Even values represent ons, and odds offs
+ int32_t fCount; //!< Number of intervals in the dash. Should be even number
+ SkScalar fPhase; //!< Offset into the dashed interval pattern
+ // mod the sum of all intervals
+ };
+
+ DashType asADash(DashInfo* info) const;
+
+ /**
+ * Given a src path (input) and a stroke-rec (input and output), apply
+ * this effect to the src path, returning the new path in dst, and return
+ * true. If this effect cannot be applied, return false and ignore dst
+ * and stroke-rec.
+ *
+ * The stroke-rec specifies the initial request for stroking (if any).
+ * The effect can treat this as input only, or it can choose to change
+ * the rec as well. For example, the effect can decide to change the
+ * stroke's width or join, or the effect can change the rec from stroke
+ * to fill (or fill to stroke) in addition to returning a new (dst) path.
+ *
+ * If this method returns true, the caller will apply (as needed) the
+ * resulting stroke-rec to dst and then draw.
+ */
+ bool filterPath(SkPath* dst, const SkPath& src, SkStrokeRec*, const SkRect* cullR) const;
+
+ /** Version of filterPath that can be called when the CTM is known. */
+ bool filterPath(SkPath* dst, const SkPath& src, SkStrokeRec*, const SkRect* cullR,
+ const SkMatrix& ctm) const;
+
+ /** True if this path effect requires a valid CTM */
+ bool needsCTM() const;
+
+ static sk_sp<SkPathEffect> Deserialize(const void* data, size_t size,
+ const SkDeserialProcs* procs = nullptr);
+
+private:
+ SkPathEffect() = default;
+ friend class SkPathEffectBase;
+
+ using INHERITED = SkFlattenable;
+};
+
+#endif
diff --git a/src/deps/skia/include/core/SkPathMeasure.h b/src/deps/skia/include/core/SkPathMeasure.h
new file mode 100644
index 000000000..2335c7c23
--- /dev/null
+++ b/src/deps/skia/include/core/SkPathMeasure.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkPathMeasure_DEFINED
+#define SkPathMeasure_DEFINED
+
+#include "include/core/SkContourMeasure.h"
+#include "include/core/SkPath.h"
+#include "include/private/SkTDArray.h"
+
+class SK_API SkPathMeasure {
+public:
+ SkPathMeasure();
+ /** Initialize the pathmeasure with the specified path. The parts of the path that are needed
+ * are copied, so the client is free to modify/delete the path after this call.
+ *
+ * resScale controls the precision of the measure. values > 1 increase the
+ * precision (and possibly slow down the computation).
+ */
+ SkPathMeasure(const SkPath& path, bool forceClosed, SkScalar resScale = 1);
+ ~SkPathMeasure();
+
+ /** Reset the pathmeasure with the specified path. The parts of the path that are needed
+ * are copied, so the client is free to modify/delete the path after this call..
+ */
+ void setPath(const SkPath*, bool forceClosed);
+
+ /** Return the total length of the current contour, or 0 if no path
+ is associated (e.g. resetPath(null))
+ */
+ SkScalar getLength();
+
+ /** Pins distance to 0 <= distance <= getLength(), and then computes
+ the corresponding position and tangent.
+ Returns false if there is no path, or a zero-length path was specified, in which case
+ position and tangent are unchanged.
+ */
+ bool SK_WARN_UNUSED_RESULT getPosTan(SkScalar distance, SkPoint* position,
+ SkVector* tangent);
+
+ enum MatrixFlags {
+ kGetPosition_MatrixFlag = 0x01,
+ kGetTangent_MatrixFlag = 0x02,
+ kGetPosAndTan_MatrixFlag = kGetPosition_MatrixFlag | kGetTangent_MatrixFlag
+ };
+
+ /** Pins distance to 0 <= distance <= getLength(), and then computes
+ the corresponding matrix (by calling getPosTan).
+ Returns false if there is no path, or a zero-length path was specified, in which case
+ matrix is unchanged.
+ */
+ bool SK_WARN_UNUSED_RESULT getMatrix(SkScalar distance, SkMatrix* matrix,
+ MatrixFlags flags = kGetPosAndTan_MatrixFlag);
+
+ /** Given a start and stop distance, return in dst the intervening segment(s).
+ If the segment is zero-length, return false, else return true.
+ startD and stopD are pinned to legal values (0..getLength()). If startD > stopD
+ then return false (and leave dst untouched).
+ Begin the segment with a moveTo if startWithMoveTo is true
+ */
+ bool getSegment(SkScalar startD, SkScalar stopD, SkPath* dst, bool startWithMoveTo);
+
+ /** Return true if the current contour is closed()
+ */
+ bool isClosed();
+
+ /** Move to the next contour in the path. Return true if one exists, or false if
+ we're done with the path.
+ */
+ bool nextContour();
+
+#ifdef SK_DEBUG
+ void dump();
+#endif
+
+private:
+ SkContourMeasureIter fIter;
+ sk_sp<SkContourMeasure> fContour;
+
+ SkPathMeasure(const SkPathMeasure&) = delete;
+ SkPathMeasure& operator=(const SkPathMeasure&) = delete;
+};
+
+#endif
diff --git a/src/deps/skia/include/core/SkPathTypes.h b/src/deps/skia/include/core/SkPathTypes.h
new file mode 100644
index 000000000..f589ea46c
--- /dev/null
+++ b/src/deps/skia/include/core/SkPathTypes.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2019 Google LLC.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkPathTypes_DEFINED
+#define SkPathTypes_DEFINED
+
+#include "include/core/SkTypes.h"
+
+enum class SkPathFillType {
+ /** Specifies that "inside" is computed by a non-zero sum of signed edge crossings */
+ kWinding,
+ /** Specifies that "inside" is computed by an odd number of edge crossings */
+ kEvenOdd,
+ /** Same as Winding, but draws outside of the path, rather than inside */
+ kInverseWinding,
+ /** Same as EvenOdd, but draws outside of the path, rather than inside */
+ kInverseEvenOdd
+};
+
+static inline bool SkPathFillType_IsEvenOdd(SkPathFillType ft) {
+ return (static_cast<int>(ft) & 1) != 0;
+}
+
+static inline bool SkPathFillType_IsInverse(SkPathFillType ft) {
+ return (static_cast<int>(ft) & 2) != 0;
+}
+
+static inline SkPathFillType SkPathFillType_ConvertToNonInverse(SkPathFillType ft) {
+ return static_cast<SkPathFillType>(static_cast<int>(ft) & 1);
+}
+
+enum class SkPathDirection {
+ /** clockwise direction for adding closed contours */
+ kCW,
+ /** counter-clockwise direction for adding closed contours */
+ kCCW,
+};
+
+enum SkPathSegmentMask {
+ kLine_SkPathSegmentMask = 1 << 0,
+ kQuad_SkPathSegmentMask = 1 << 1,
+ kConic_SkPathSegmentMask = 1 << 2,
+ kCubic_SkPathSegmentMask = 1 << 3,
+};
+
+enum class SkPathVerb {
+ kMove, //!< SkPath::RawIter returns 1 point
+ kLine, //!< SkPath::RawIter returns 2 points
+ kQuad, //!< SkPath::RawIter returns 3 points
+ kConic, //!< SkPath::RawIter returns 3 points + 1 weight
+ kCubic, //!< SkPath::RawIter returns 4 points
+ kClose //!< SkPath::RawIter returns 0 points
+};
+
+#endif
diff --git a/src/deps/skia/include/core/SkPicture.h b/src/deps/skia/include/core/SkPicture.h
new file mode 100644
index 000000000..d05f13fc2
--- /dev/null
+++ b/src/deps/skia/include/core/SkPicture.h
@@ -0,0 +1,280 @@
+/*
+ * Copyright 2007 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkPicture_DEFINED
+#define SkPicture_DEFINED
+
+#include "include/core/SkRect.h"
+#include "include/core/SkRefCnt.h"
+#include "include/core/SkSamplingOptions.h"
+#include "include/core/SkShader.h"
+#include "include/core/SkTileMode.h"
+#include "include/core/SkTypes.h"
+
+class SkCanvas;
+class SkData;
+struct SkDeserialProcs;
+class SkImage;
+class SkMatrix;
+struct SkSerialProcs;
+class SkStream;
+class SkWStream;
+
+/** \class SkPicture
+ SkPicture records drawing commands made to SkCanvas. The command stream may be
+ played in whole or in part at a later time.
+
+ SkPicture is an abstract class. SkPicture may be generated by SkPictureRecorder
+ or SkDrawable, or from SkPicture previously saved to SkData or SkStream.
+
+ SkPicture may contain any SkCanvas drawing command, as well as one or more
+ SkCanvas matrix or SkCanvas clip. SkPicture has a cull SkRect, which is used as
+ a bounding box hint. To limit SkPicture bounds, use SkCanvas clip when
+ recording or drawing SkPicture.
+*/
+class SK_API SkPicture : public SkRefCnt {
+public:
+ ~SkPicture() override;
+
+ /** Recreates SkPicture that was serialized into a stream. Returns constructed SkPicture
+ if successful; otherwise, returns nullptr. Fails if data does not permit
+ constructing valid SkPicture.
+
+ procs->fPictureProc permits supplying a custom function to decode SkPicture.
+ If procs->fPictureProc is nullptr, default decoding is used. procs->fPictureCtx
+ may be used to provide user context to procs->fPictureProc; procs->fPictureProc
+ is called with a pointer to data, data byte length, and user context.
+
+ @param stream container for serial data
+ @param procs custom serial data decoders; may be nullptr
+ @return SkPicture constructed from stream data
+ */
+ static sk_sp<SkPicture> MakeFromStream(SkStream* stream,
+ const SkDeserialProcs* procs = nullptr);
+
+ /** Recreates SkPicture that was serialized into data. Returns constructed SkPicture
+ if successful; otherwise, returns nullptr. Fails if data does not permit
+ constructing valid SkPicture.
+
+ procs->fPictureProc permits supplying a custom function to decode SkPicture.
+ If procs->fPictureProc is nullptr, default decoding is used. procs->fPictureCtx
+ may be used to provide user context to procs->fPictureProc; procs->fPictureProc
+ is called with a pointer to data, data byte length, and user context.
+
+ @param data container for serial data
+ @param procs custom serial data decoders; may be nullptr
+ @return SkPicture constructed from data
+ */
+ static sk_sp<SkPicture> MakeFromData(const SkData* data,
+ const SkDeserialProcs* procs = nullptr);
+
+ /**
+
+ @param data pointer to serial data
+ @param size size of data
+ @param procs custom serial data decoders; may be nullptr
+ @return SkPicture constructed from data
+ */
+ static sk_sp<SkPicture> MakeFromData(const void* data, size_t size,
+ const SkDeserialProcs* procs = nullptr);
+
+ /** \class SkPicture::AbortCallback
+ AbortCallback is an abstract class. An implementation of AbortCallback may
+ passed as a parameter to SkPicture::playback, to stop it before all drawing
+ commands have been processed.
+
+ If AbortCallback::abort returns true, SkPicture::playback is interrupted.
+ */
+ class SK_API AbortCallback {
+ public:
+ /** Has no effect.
+ */
+ virtual ~AbortCallback() = default;
+
+ /** Stops SkPicture playback when some condition is met. A subclass of
+ AbortCallback provides an override for abort() that can stop SkPicture::playback.
+
+ The part of SkPicture drawn when aborted is undefined. SkPicture instantiations are
+ free to stop drawing at different points during playback.
+
+ If the abort happens inside one or more calls to SkCanvas::save(), stack
+ of SkCanvas matrix and SkCanvas clip values is restored to its state before
+ SkPicture::playback was called.
+
+ @return true to stop playback
+
+ example: https://fiddle.skia.org/c/@Picture_AbortCallback_abort
+ */
+ virtual bool abort() = 0;
+
+ protected:
+ AbortCallback() = default;
+ AbortCallback(const AbortCallback&) = delete;
+ AbortCallback& operator=(const AbortCallback&) = delete;
+ };
+
+ /** Replays the drawing commands on the specified canvas. In the case that the
+ commands are recorded, each command in the SkPicture is sent separately to canvas.
+
+ To add a single command to draw SkPicture to recording canvas, call
+ SkCanvas::drawPicture instead.
+
+ @param canvas receiver of drawing commands
+ @param callback allows interruption of playback
+
+ example: https://fiddle.skia.org/c/@Picture_playback
+ */
+ virtual void playback(SkCanvas* canvas, AbortCallback* callback = nullptr) const = 0;
+
+ /** Returns cull SkRect for this picture, passed in when SkPicture was created.
+ Returned SkRect does not specify clipping SkRect for SkPicture; cull is hint
+ of SkPicture bounds.
+
+ SkPicture is free to discard recorded drawing commands that fall outside
+ cull.
+
+ @return bounds passed when SkPicture was created
+
+ example: https://fiddle.skia.org/c/@Picture_cullRect
+ */
+ virtual SkRect cullRect() const = 0;
+
+ /** Returns a non-zero value unique among SkPicture in Skia process.
+
+ @return identifier for SkPicture
+ */
+ uint32_t uniqueID() const { return fUniqueID; }
+
+ /** Returns storage containing SkData describing SkPicture, using optional custom
+ encoders.
+
+ procs->fPictureProc permits supplying a custom function to encode SkPicture.
+ If procs->fPictureProc is nullptr, default encoding is used. procs->fPictureCtx
+ may be used to provide user context to procs->fPictureProc; procs->fPictureProc
+ is called with a pointer to SkPicture and user context.
+
+ @param procs custom serial data encoders; may be nullptr
+ @return storage containing serialized SkPicture
+
+ example: https://fiddle.skia.org/c/@Picture_serialize
+ */
+ sk_sp<SkData> serialize(const SkSerialProcs* procs = nullptr) const;
+
+ /** Writes picture to stream, using optional custom encoders.
+
+ procs->fPictureProc permits supplying a custom function to encode SkPicture.
+ If procs->fPictureProc is nullptr, default encoding is used. procs->fPictureCtx
+ may be used to provide user context to procs->fPictureProc; procs->fPictureProc
+ is called with a pointer to SkPicture and user context.
+
+ @param stream writable serial data stream
+ @param procs custom serial data encoders; may be nullptr
+
+ example: https://fiddle.skia.org/c/@Picture_serialize_2
+ */
+ void serialize(SkWStream* stream, const SkSerialProcs* procs = nullptr) const;
+
+ /** Returns a placeholder SkPicture. Result does not draw, and contains only
+ cull SkRect, a hint of its bounds. Result is immutable; it cannot be changed
+ later. Result identifier is unique.
+
+ Returned placeholder can be intercepted during playback to insert other
+ commands into SkCanvas draw stream.
+
+ @param cull placeholder dimensions
+ @return placeholder with unique identifier
+
+ example: https://fiddle.skia.org/c/@Picture_MakePlaceholder
+ */
+ static sk_sp<SkPicture> MakePlaceholder(SkRect cull);
+
+ /** Returns the approximate number of operations in SkPicture. Returned value
+ may be greater or less than the number of SkCanvas calls
+ recorded: some calls may be recorded as more than one operation, other
+ calls may be optimized away.
+
+ @param nested if true, include the op-counts of nested pictures as well, else
+ just return count the ops in the top-level picture.
+ @return approximate operation count
+
+ example: https://fiddle.skia.org/c/@Picture_approximateOpCount
+ */
+ virtual int approximateOpCount(bool nested = false) const = 0;
+
+ /** Returns the approximate byte size of SkPicture. Does not include large objects
+ referenced by SkPicture.
+
+ @return approximate size
+
+ example: https://fiddle.skia.org/c/@Picture_approximateBytesUsed
+ */
+ virtual size_t approximateBytesUsed() const = 0;
+
+ /** Return a new shader that will draw with this picture.
+ *
+ * @param tmx The tiling mode to use when sampling in the x-direction.
+ * @param tmy The tiling mode to use when sampling in the y-direction.
+ * @param mode How to filter the tiles
+ * @param localMatrix Optional matrix used when sampling
+ * @param tile The tile rectangle in picture coordinates: this represents the subset
+ * (or superset) of the picture used when building a tile. It is not
+ * affected by localMatrix and does not imply scaling (only translation
+ * and cropping). If null, the tile rect is considered equal to the picture
+ * bounds.
+ * @return Returns a new shader object. Note: this function never returns null.
+ */
+ sk_sp<SkShader> makeShader(SkTileMode tmx, SkTileMode tmy, SkFilterMode mode,
+ const SkMatrix* localMatrix, const SkRect* tileRect) const;
+
+ sk_sp<SkShader> makeShader(SkTileMode tmx, SkTileMode tmy, SkFilterMode mode) const {
+ return this->makeShader(tmx, tmy, mode, nullptr, nullptr);
+ }
+
+private:
+ // Allowed subclasses.
+ SkPicture();
+ friend class SkBigPicture;
+ friend class SkEmptyPicture;
+ friend class SkPicturePriv;
+ template <typename> friend class SkMiniPicture;
+
+ void serialize(SkWStream*, const SkSerialProcs*, class SkRefCntSet* typefaces,
+ bool textBlobsOnly=false) const;
+ static sk_sp<SkPicture> MakeFromStream(SkStream*, const SkDeserialProcs*,
+ class SkTypefacePlayback*);
+ friend class SkPictureData;
+
+ /** Return true if the SkStream/Buffer represents a serialized picture, and
+ fills out SkPictInfo. After this function returns, the data source is not
+ rewound so it will have to be manually reset before passing to
+ MakeFromStream or MakeFromBuffer. Note, MakeFromStream and
+ MakeFromBuffer perform this check internally so these entry points are
+ intended for stand alone tools.
+ If false is returned, SkPictInfo is unmodified.
+ */
+ static bool StreamIsSKP(SkStream*, struct SkPictInfo*);
+ static bool BufferIsSKP(class SkReadBuffer*, struct SkPictInfo*);
+ friend bool SkPicture_StreamIsSKP(SkStream*, struct SkPictInfo*);
+
+ // Returns NULL if this is not an SkBigPicture.
+ virtual const class SkBigPicture* asSkBigPicture() const { return nullptr; }
+
+ friend struct SkPathCounter;
+
+ static bool IsValidPictInfo(const struct SkPictInfo& info);
+ static sk_sp<SkPicture> Forwardport(const struct SkPictInfo&,
+ const class SkPictureData*,
+ class SkReadBuffer* buffer);
+
+ struct SkPictInfo createHeader() const;
+ class SkPictureData* backport() const;
+
+ uint32_t fUniqueID;
+ mutable std::atomic<bool> fAddedToCache{false};
+};
+
+#endif
diff --git a/src/deps/skia/include/core/SkPictureRecorder.h b/src/deps/skia/include/core/SkPictureRecorder.h
new file mode 100644
index 000000000..9bc5d1aa1
--- /dev/null
+++ b/src/deps/skia/include/core/SkPictureRecorder.h
@@ -0,0 +1,115 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkPictureRecorder_DEFINED
+#define SkPictureRecorder_DEFINED
+
+#include "include/core/SkBBHFactory.h"
+#include "include/core/SkPicture.h"
+#include "include/core/SkRefCnt.h"
+
+#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
+namespace android {
+ class Picture;
+};
+#endif
+
+class SkCanvas;
+class SkDrawable;
+class SkMiniRecorder;
+class SkPictureRecord;
+class SkRecord;
+class SkRecorder;
+
+class SK_API SkPictureRecorder {
+public:
+ SkPictureRecorder();
+ ~SkPictureRecorder();
+
+ enum FinishFlags {
+ };
+
+ /** Returns the canvas that records the drawing commands.
+ @param bounds the cull rect used when recording this picture. Any drawing the falls outside
+ of this rect is undefined, and may be drawn or it may not.
+ @param bbh optional acceleration structure
+ @param recordFlags optional flags that control recording.
+ @return the canvas.
+ */
+ SkCanvas* beginRecording(const SkRect& bounds, sk_sp<SkBBoxHierarchy> bbh);
+
+ SkCanvas* beginRecording(const SkRect& bounds, SkBBHFactory* bbhFactory = nullptr);
+
+ SkCanvas* beginRecording(SkScalar width, SkScalar height,
+ SkBBHFactory* bbhFactory = nullptr) {
+ return this->beginRecording(SkRect::MakeWH(width, height), bbhFactory);
+ }
+
+ /** Returns the recording canvas if one is active, or NULL if recording is
+ not active. This does not alter the refcnt on the canvas (if present).
+ */
+ SkCanvas* getRecordingCanvas();
+
+ /**
+ * Signal that the caller is done recording. This invalidates the canvas returned by
+ * beginRecording/getRecordingCanvas. Ownership of the object is passed to the caller, who
+ * must call unref() when they are done using it.
+ *
+ * The returned picture is immutable. If during recording drawables were added to the canvas,
+ * these will have been "drawn" into a recording canvas, so that this resulting picture will
+ * reflect their current state, but will not contain a live reference to the drawables
+ * themselves.
+ */
+ sk_sp<SkPicture> finishRecordingAsPicture();
+
+ /**
+ * Signal that the caller is done recording, and update the cull rect to use for bounding
+ * box hierarchy (BBH) generation. The behavior is the same as calling
+ * finishRecordingAsPicture(), except that this method updates the cull rect initially passed
+ * into beginRecording.
+ * @param cullRect the new culling rectangle to use as the overall bound for BBH generation
+ * and subsequent culling operations.
+ * @return the picture containing the recorded content.
+ */
+ sk_sp<SkPicture> finishRecordingAsPictureWithCull(const SkRect& cullRect);
+
+ /**
+ * Signal that the caller is done recording. This invalidates the canvas returned by
+ * beginRecording/getRecordingCanvas. Ownership of the object is passed to the caller, who
+ * must call unref() when they are done using it.
+ *
+ * Unlike finishRecordingAsPicture(), which returns an immutable picture, the returned drawable
+ * may contain live references to other drawables (if they were added to the recording canvas)
+ * and therefore this drawable will reflect the current state of those nested drawables anytime
+ * it is drawn or a new picture is snapped from it (by calling drawable->newPictureSnapshot()).
+ */
+ sk_sp<SkDrawable> finishRecordingAsDrawable();
+
+private:
+ void reset();
+
+ /** Replay the current (partially recorded) operation stream into
+ canvas. This call doesn't close the current recording.
+ */
+#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
+ friend class android::Picture;
+#endif
+ friend class SkPictureRecorderReplayTester; // for unit testing
+ void partialReplay(SkCanvas* canvas) const;
+
+ bool fActivelyRecording;
+ SkRect fCullRect;
+ sk_sp<SkBBoxHierarchy> fBBH;
+ std::unique_ptr<SkRecorder> fRecorder;
+ sk_sp<SkRecord> fRecord;
+ std::unique_ptr<SkMiniRecorder> fMiniRecorder;
+
+ SkPictureRecorder(SkPictureRecorder&&) = delete;
+ SkPictureRecorder& operator=(SkPictureRecorder&&) = delete;
+};
+
+#endif
diff --git a/src/deps/skia/include/core/SkPixelRef.h b/src/deps/skia/include/core/SkPixelRef.h
new file mode 100644
index 000000000..0a55ac339
--- /dev/null
+++ b/src/deps/skia/include/core/SkPixelRef.h
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2008 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkPixelRef_DEFINED
+#define SkPixelRef_DEFINED
+
+#include "include/core/SkBitmap.h"
+#include "include/core/SkImageInfo.h"
+#include "include/core/SkPixmap.h"
+#include "include/core/SkRefCnt.h"
+#include "include/core/SkSize.h"
+#include "include/private/SkIDChangeListener.h"
+#include "include/private/SkMutex.h"
+#include "include/private/SkTDArray.h"
+
+#include <atomic>
+
+struct SkIRect;
+
+class GrTexture;
+class SkDiscardableMemory;
+
+/** \class SkPixelRef
+
+ This class is the smart container for pixel memory, and is used with SkBitmap.
+ This class can be shared/accessed between multiple threads.
+*/
+class SK_API SkPixelRef : public SkRefCnt {
+public:
+ SkPixelRef(int width, int height, void* addr, size_t rowBytes);
+ ~SkPixelRef() override;
+
+ SkISize dimensions() const { return {fWidth, fHeight}; }
+ int width() const { return fWidth; }
+ int height() const { return fHeight; }
+ void* pixels() const { return fPixels; }
+ size_t rowBytes() const { return fRowBytes; }
+
+ /** Returns a non-zero, unique value corresponding to the pixels in this
+ pixelref. Each time the pixels are changed (and notifyPixelsChanged is
+ called), a different generation ID will be returned.
+ */
+ uint32_t getGenerationID() const;
+
+ /**
+ * Call this if you have changed the contents of the pixels. This will in-
+ * turn cause a different generation ID value to be returned from
+ * getGenerationID().
+ */
+ void notifyPixelsChanged();
+
+ /** Returns true if this pixelref is marked as immutable, meaning that the
+ contents of its pixels will not change for the lifetime of the pixelref.
+ */
+ bool isImmutable() const { return fMutability != kMutable; }
+
+ /** Marks this pixelref is immutable, meaning that the contents of its
+ pixels will not change for the lifetime of the pixelref. This state can
+ be set on a pixelref, but it cannot be cleared once it is set.
+ */
+ void setImmutable();
+
+ // Register a listener that may be called the next time our generation ID changes.
+ //
+ // We'll only call the listener if we're confident that we are the only SkPixelRef with this
+ // generation ID. If our generation ID changes and we decide not to call the listener, we'll
+ // never call it: you must add a new listener for each generation ID change. We also won't call
+ // the listener when we're certain no one knows what our generation ID is.
+ //
+ // This can be used to invalidate caches keyed by SkPixelRef generation ID.
+ // Takes ownership of listener. Threadsafe.
+ void addGenIDChangeListener(sk_sp<SkIDChangeListener> listener);
+
+ // Call when this pixelref is part of the key to a resourcecache entry. This allows the cache
+ // to know automatically those entries can be purged when this pixelref is changed or deleted.
+ void notifyAddedToCache() {
+ fAddedToCache.store(true);
+ }
+
+ virtual SkDiscardableMemory* diagnostic_only_getDiscardable() const { return nullptr; }
+
+protected:
+ void android_only_reset(int width, int height, size_t rowBytes);
+
+private:
+ int fWidth;
+ int fHeight;
+ void* fPixels;
+ size_t fRowBytes;
+
+ // Bottom bit indicates the Gen ID is unique.
+ bool genIDIsUnique() const { return SkToBool(fTaggedGenID.load() & 1); }
+ mutable std::atomic<uint32_t> fTaggedGenID;
+
+ SkIDChangeListener::List fGenIDChangeListeners;
+
+ // Set true by caches when they cache content that's derived from the current pixels.
+ std::atomic<bool> fAddedToCache;
+
+ enum Mutability {
+ kMutable, // PixelRefs begin mutable.
+ kTemporarilyImmutable, // Considered immutable, but can revert to mutable.
+ kImmutable, // Once set to this state, it never leaves.
+ } fMutability : 8; // easily fits inside a byte
+
+ void needsNewGenID();
+ void callGenIDChangeListeners();
+
+ void setTemporarilyImmutable();
+ void restoreMutability();
+ friend class SkSurface_Raster; // For the two methods above.
+
+ void setImmutableWithID(uint32_t genID);
+ friend void SkBitmapCache_setImmutableWithID(SkPixelRef*, uint32_t);
+
+ using INHERITED = SkRefCnt;
+};
+
+#endif
diff --git a/src/deps/skia/include/core/SkPixmap.h b/src/deps/skia/include/core/SkPixmap.h
new file mode 100644
index 000000000..ba1268a20
--- /dev/null
+++ b/src/deps/skia/include/core/SkPixmap.h
@@ -0,0 +1,720 @@
+/*
+ * Copyright 2015 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkPixmap_DEFINED
+#define SkPixmap_DEFINED
+
+#include "include/core/SkColor.h"
+#include "include/core/SkImageInfo.h"
+#include "include/core/SkSamplingOptions.h"
+
+class SkData;
+struct SkMask;
+
+/** \class SkPixmap
+ SkPixmap provides a utility to pair SkImageInfo with pixels and row bytes.
+ SkPixmap is a low level class which provides convenience functions to access
+ raster destinations. SkCanvas can not draw SkPixmap, nor does SkPixmap provide
+ a direct drawing destination.
+
+ Use SkBitmap to draw pixels referenced by SkPixmap; use SkSurface to draw into
+ pixels referenced by SkPixmap.
+
+ SkPixmap does not try to manage the lifetime of the pixel memory. Use SkPixelRef
+ to manage pixel memory; SkPixelRef is safe across threads.
+*/
+class SK_API SkPixmap {
+public:
+
+ /** Creates an empty SkPixmap without pixels, with kUnknown_SkColorType, with
+ kUnknown_SkAlphaType, and with a width and height of zero. Use
+ reset() to associate pixels, SkColorType, SkAlphaType, width, and height
+ after SkPixmap has been created.
+
+ @return empty SkPixmap
+ */
+ SkPixmap()
+ : fPixels(nullptr), fRowBytes(0), fInfo(SkImageInfo::MakeUnknown(0, 0))
+ {}
+
+ /** Creates SkPixmap from info width, height, SkAlphaType, and SkColorType.
+ addr points to pixels, or nullptr. rowBytes should be info.width() times
+ info.bytesPerPixel(), or larger.
+
+ No parameter checking is performed; it is up to the caller to ensure that
+ addr and rowBytes agree with info.
+
+ The memory lifetime of pixels is managed by the caller. When SkPixmap goes
+ out of scope, addr is unaffected.
+
+ SkPixmap may be later modified by reset() to change its size, pixel type, or
+ storage.
+
+ @param info width, height, SkAlphaType, SkColorType of SkImageInfo
+ @param addr pointer to pixels allocated by caller; may be nullptr
+ @param rowBytes size of one row of addr; width times pixel size, or larger
+ @return initialized SkPixmap
+ */
+ SkPixmap(const SkImageInfo& info, const void* addr, size_t rowBytes)
+ : fPixels(addr), fRowBytes(rowBytes), fInfo(info)
+ {}
+
+ /** Sets width, height, row bytes to zero; pixel address to nullptr; SkColorType to
+ kUnknown_SkColorType; and SkAlphaType to kUnknown_SkAlphaType.
+
+ The prior pixels are unaffected; it is up to the caller to release pixels
+ memory if desired.
+
+ example: https://fiddle.skia.org/c/@Pixmap_reset
+ */
+ void reset();
+
+ /** Sets width, height, SkAlphaType, and SkColorType from info.
+ Sets pixel address from addr, which may be nullptr.
+ Sets row bytes from rowBytes, which should be info.width() times
+ info.bytesPerPixel(), or larger.
+
+ Does not check addr. Asserts if built with SK_DEBUG defined and if rowBytes is
+ too small to hold one row of pixels.
+
+ The memory lifetime pixels are managed by the caller. When SkPixmap goes
+ out of scope, addr is unaffected.
+
+ @param info width, height, SkAlphaType, SkColorType of SkImageInfo
+ @param addr pointer to pixels allocated by caller; may be nullptr
+ @param rowBytes size of one row of addr; width times pixel size, or larger
+
+ example: https://fiddle.skia.org/c/@Pixmap_reset_2
+ */
+ void reset(const SkImageInfo& info, const void* addr, size_t rowBytes);
+
+ /** Changes SkColorSpace in SkImageInfo; preserves width, height, SkAlphaType, and
+ SkColorType in SkImage, and leaves pixel address and row bytes unchanged.
+ SkColorSpace reference count is incremented.
+
+ @param colorSpace SkColorSpace moved to SkImageInfo
+
+ example: https://fiddle.skia.org/c/@Pixmap_setColorSpace
+ */
+ void setColorSpace(sk_sp<SkColorSpace> colorSpace);
+
+ /** Deprecated.
+ */
+ bool SK_WARN_UNUSED_RESULT reset(const SkMask& mask);
+
+ /** Sets subset width, height, pixel address to intersection of SkPixmap with area,
+ if intersection is not empty; and return true. Otherwise, leave subset unchanged
+ and return false.
+
+ Failing to read the return value generates a compile time warning.
+
+ @param subset storage for width, height, pixel address of intersection
+ @param area bounds to intersect with SkPixmap
+ @return true if intersection of SkPixmap and area is not empty
+ */
+ bool SK_WARN_UNUSED_RESULT extractSubset(SkPixmap* subset, const SkIRect& area) const;
+
+ /** Returns width, height, SkAlphaType, SkColorType, and SkColorSpace.
+
+ @return reference to SkImageInfo
+ */
+ const SkImageInfo& info() const { return fInfo; }
+
+ /** Returns row bytes, the interval from one pixel row to the next. Row bytes
+ is at least as large as: width() * info().bytesPerPixel().
+
+ Returns zero if colorType() is kUnknown_SkColorType.
+ It is up to the SkBitmap creator to ensure that row bytes is a useful value.
+
+ @return byte length of pixel row
+ */
+ size_t rowBytes() const { return fRowBytes; }
+
+ /** Returns pixel address, the base address corresponding to the pixel origin.
+
+ It is up to the SkPixmap creator to ensure that pixel address is a useful value.
+
+ @return pixel address
+ */
+ const void* addr() const { return fPixels; }
+
+ /** Returns pixel count in each pixel row. Should be equal or less than:
+ rowBytes() / info().bytesPerPixel().
+
+ @return pixel width in SkImageInfo
+ */
+ int width() const { return fInfo.width(); }
+
+ /** Returns pixel row count.
+
+ @return pixel height in SkImageInfo
+ */
+ int height() const { return fInfo.height(); }
+
+ /**
+ * Return the dimensions of the pixmap (from its ImageInfo)
+ */
+ SkISize dimensions() const { return fInfo.dimensions(); }
+
+ SkColorType colorType() const { return fInfo.colorType(); }
+
+ SkAlphaType alphaType() const { return fInfo.alphaType(); }
+
+ /** Returns SkColorSpace, the range of colors, associated with SkImageInfo. The
+ reference count of SkColorSpace is unchanged. The returned SkColorSpace is
+ immutable.
+
+ @return SkColorSpace in SkImageInfo, or nullptr
+ */
+ SkColorSpace* colorSpace() const { return fInfo.colorSpace(); }
+
+ /** Returns smart pointer to SkColorSpace, the range of colors, associated with
+ SkImageInfo. The smart pointer tracks the number of objects sharing this
+ SkColorSpace reference so the memory is released when the owners destruct.
+
+ The returned SkColorSpace is immutable.
+
+ @return SkColorSpace in SkImageInfo wrapped in a smart pointer
+ */
+ sk_sp<SkColorSpace> refColorSpace() const { return fInfo.refColorSpace(); }
+
+ /** Returns true if SkAlphaType is kOpaque_SkAlphaType.
+ Does not check if SkColorType allows alpha, or if any pixel value has
+ transparency.
+
+ @return true if SkImageInfo has opaque SkAlphaType
+ */
+ bool isOpaque() const { return fInfo.isOpaque(); }
+
+ /** Returns SkIRect { 0, 0, width(), height() }.
+
+ @return integral rectangle from origin to width() and height()
+ */
+ SkIRect bounds() const { return SkIRect::MakeWH(this->width(), this->height()); }
+
+ /** Returns number of pixels that fit on row. Should be greater than or equal to
+ width().
+
+ @return maximum pixels per row
+ */
+ int rowBytesAsPixels() const { return int(fRowBytes >> this->shiftPerPixel()); }
+
+ /** Returns bit shift converting row bytes to row pixels.
+ Returns zero for kUnknown_SkColorType.
+
+ @return one of: 0, 1, 2, 3; left shift to convert pixels to bytes
+ */
+ int shiftPerPixel() const { return fInfo.shiftPerPixel(); }
+
+ /** Returns minimum memory required for pixel storage.
+ Does not include unused memory on last row when rowBytesAsPixels() exceeds width().
+ Returns SIZE_MAX if result does not fit in size_t.
+ Returns zero if height() or width() is 0.
+ Returns height() times rowBytes() if colorType() is kUnknown_SkColorType.
+
+ @return size in bytes of image buffer
+ */
+ size_t computeByteSize() const { return fInfo.computeByteSize(fRowBytes); }
+
+ /** Returns true if all pixels are opaque. SkColorType determines how pixels
+ are encoded, and whether pixel describes alpha. Returns true for SkColorType
+ without alpha in each pixel; for other SkColorType, returns true if all
+ pixels have alpha values equivalent to 1.0 or greater.
+
+ For SkColorType kRGB_565_SkColorType or kGray_8_SkColorType: always
+ returns true. For SkColorType kAlpha_8_SkColorType, kBGRA_8888_SkColorType,
+ kRGBA_8888_SkColorType: returns true if all pixel alpha values are 255.
+ For SkColorType kARGB_4444_SkColorType: returns true if all pixel alpha values are 15.
+ For kRGBA_F16_SkColorType: returns true if all pixel alpha values are 1.0 or
+ greater.
+
+ Returns false for kUnknown_SkColorType.
+
+ @return true if all pixels have opaque values or SkColorType is opaque
+
+ example: https://fiddle.skia.org/c/@Pixmap_computeIsOpaque
+ */
+ bool computeIsOpaque() const;
+
+ /** Returns pixel at (x, y) as unpremultiplied color.
+ Returns black with alpha if SkColorType is kAlpha_8_SkColorType.
+
+ Input is not validated: out of bounds values of x or y trigger an assert() if
+ built with SK_DEBUG defined; and returns undefined values or may crash if
+ SK_RELEASE is defined. Fails if SkColorType is kUnknown_SkColorType or
+ pixel address is nullptr.
+
+ SkColorSpace in SkImageInfo is ignored. Some color precision may be lost in the
+ conversion to unpremultiplied color; original pixel data may have additional
+ precision.
+
+ @param x column index, zero or greater, and less than width()
+ @param y row index, zero or greater, and less than height()
+ @return pixel converted to unpremultiplied color
+
+ example: https://fiddle.skia.org/c/@Pixmap_getColor
+ */
+ SkColor getColor(int x, int y) const;
+
+ /** Look up the pixel at (x,y) and return its alpha component, normalized to [0..1].
+ This is roughly equivalent to SkGetColorA(getColor()), but can be more efficent
+ (and more precise if the pixels store more than 8 bits per component).
+
+ @param x column index, zero or greater, and less than width()
+ @param y row index, zero or greater, and less than height()
+ @return alpha converted to normalized float
+ */
+ float getAlphaf(int x, int y) const;
+
+ /** Returns readable pixel address at (x, y). Returns nullptr if SkPixelRef is nullptr.
+
+ Input is not validated: out of bounds values of x or y trigger an assert() if
+ built with SK_DEBUG defined. Returns nullptr if SkColorType is kUnknown_SkColorType.
+
+ Performs a lookup of pixel size; for better performance, call
+ one of: addr8, addr16, addr32, addr64, or addrF16().
+
+ @param x column index, zero or greater, and less than width()
+ @param y row index, zero or greater, and less than height()
+ @return readable generic pointer to pixel
+ */
+ const void* addr(int x, int y) const {
+ return (const char*)fPixels + fInfo.computeOffset(x, y, fRowBytes);
+ }
+
+ /** Returns readable base pixel address. Result is addressable as unsigned 8-bit bytes.
+ Will trigger an assert() if SkColorType is not kAlpha_8_SkColorType or
+ kGray_8_SkColorType, and is built with SK_DEBUG defined.
+
+ One byte corresponds to one pixel.
+
+ @return readable unsigned 8-bit pointer to pixels
+ */
+ const uint8_t* addr8() const {
+ SkASSERT(1 == fInfo.bytesPerPixel());
+ return reinterpret_cast<const uint8_t*>(fPixels);
+ }
+
+ /** Returns readable base pixel address. Result is addressable as unsigned 16-bit words.
+ Will trigger an assert() if SkColorType is not kRGB_565_SkColorType or
+ kARGB_4444_SkColorType, and is built with SK_DEBUG defined.
+
+ One word corresponds to one pixel.
+
+ @return readable unsigned 16-bit pointer to pixels
+ */
+ const uint16_t* addr16() const {
+ SkASSERT(2 == fInfo.bytesPerPixel());
+ return reinterpret_cast<const uint16_t*>(fPixels);
+ }
+
+ /** Returns readable base pixel address. Result is addressable as unsigned 32-bit words.
+ Will trigger an assert() if SkColorType is not kRGBA_8888_SkColorType or
+ kBGRA_8888_SkColorType, and is built with SK_DEBUG defined.
+
+ One word corresponds to one pixel.
+
+ @return readable unsigned 32-bit pointer to pixels
+ */
+ const uint32_t* addr32() const {
+ SkASSERT(4 == fInfo.bytesPerPixel());
+ return reinterpret_cast<const uint32_t*>(fPixels);
+ }
+
+ /** Returns readable base pixel address. Result is addressable as unsigned 64-bit words.
+ Will trigger an assert() if SkColorType is not kRGBA_F16_SkColorType and is built
+ with SK_DEBUG defined.
+
+ One word corresponds to one pixel.
+
+ @return readable unsigned 64-bit pointer to pixels
+ */
+ const uint64_t* addr64() const {
+ SkASSERT(8 == fInfo.bytesPerPixel());
+ return reinterpret_cast<const uint64_t*>(fPixels);
+ }
+
+ /** Returns readable base pixel address. Result is addressable as unsigned 16-bit words.
+ Will trigger an assert() if SkColorType is not kRGBA_F16_SkColorType and is built
+ with SK_DEBUG defined.
+
+ Each word represents one color component encoded as a half float.
+ Four words correspond to one pixel.
+
+ @return readable unsigned 16-bit pointer to first component of pixels
+ */
+ const uint16_t* addrF16() const {
+ SkASSERT(8 == fInfo.bytesPerPixel());
+ SkASSERT(kRGBA_F16_SkColorType == fInfo.colorType() ||
+ kRGBA_F16Norm_SkColorType == fInfo.colorType());
+ return reinterpret_cast<const uint16_t*>(fPixels);
+ }
+
+ /** Returns readable pixel address at (x, y).
+
+ Input is not validated: out of bounds values of x or y trigger an assert() if
+ built with SK_DEBUG defined.
+
+ Will trigger an assert() if SkColorType is not kAlpha_8_SkColorType or
+ kGray_8_SkColorType, and is built with SK_DEBUG defined.
+
+ @param x column index, zero or greater, and less than width()
+ @param y row index, zero or greater, and less than height()
+ @return readable unsigned 8-bit pointer to pixel at (x, y)
+ */
+ const uint8_t* addr8(int x, int y) const {
+ SkASSERT((unsigned)x < (unsigned)fInfo.width());
+ SkASSERT((unsigned)y < (unsigned)fInfo.height());
+ return (const uint8_t*)((const char*)this->addr8() + (size_t)y * fRowBytes + (x << 0));
+ }
+
+ /** Returns readable pixel address at (x, y).
+
+ Input is not validated: out of bounds values of x or y trigger an assert() if
+ built with SK_DEBUG defined.
+
+ Will trigger an assert() if SkColorType is not kRGB_565_SkColorType or
+ kARGB_4444_SkColorType, and is built with SK_DEBUG defined.
+
+ @param x column index, zero or greater, and less than width()
+ @param y row index, zero or greater, and less than height()
+ @return readable unsigned 16-bit pointer to pixel at (x, y)
+ */
+ const uint16_t* addr16(int x, int y) const {
+ SkASSERT((unsigned)x < (unsigned)fInfo.width());
+ SkASSERT((unsigned)y < (unsigned)fInfo.height());
+ return (const uint16_t*)((const char*)this->addr16() + (size_t)y * fRowBytes + (x << 1));
+ }
+
+ /** Returns readable pixel address at (x, y).
+
+ Input is not validated: out of bounds values of x or y trigger an assert() if
+ built with SK_DEBUG defined.
+
+ Will trigger an assert() if SkColorType is not kRGBA_8888_SkColorType or
+ kBGRA_8888_SkColorType, and is built with SK_DEBUG defined.
+
+ @param x column index, zero or greater, and less than width()
+ @param y row index, zero or greater, and less than height()
+ @return readable unsigned 32-bit pointer to pixel at (x, y)
+ */
+ const uint32_t* addr32(int x, int y) const {
+ SkASSERT((unsigned)x < (unsigned)fInfo.width());
+ SkASSERT((unsigned)y < (unsigned)fInfo.height());
+ return (const uint32_t*)((const char*)this->addr32() + (size_t)y * fRowBytes + (x << 2));
+ }
+
+ /** Returns readable pixel address at (x, y).
+
+ Input is not validated: out of bounds values of x or y trigger an assert() if
+ built with SK_DEBUG defined.
+
+ Will trigger an assert() if SkColorType is not kRGBA_F16_SkColorType and is built
+ with SK_DEBUG defined.
+
+ @param x column index, zero or greater, and less than width()
+ @param y row index, zero or greater, and less than height()
+ @return readable unsigned 64-bit pointer to pixel at (x, y)
+ */
+ const uint64_t* addr64(int x, int y) const {
+ SkASSERT((unsigned)x < (unsigned)fInfo.width());
+ SkASSERT((unsigned)y < (unsigned)fInfo.height());
+ return (const uint64_t*)((const char*)this->addr64() + (size_t)y * fRowBytes + (x << 3));
+ }
+
+ /** Returns readable pixel address at (x, y).
+
+ Input is not validated: out of bounds values of x or y trigger an assert() if
+ built with SK_DEBUG defined.
+
+ Will trigger an assert() if SkColorType is not kRGBA_F16_SkColorType and is built
+ with SK_DEBUG defined.
+
+ Each unsigned 16-bit word represents one color component encoded as a half float.
+ Four words correspond to one pixel.
+
+ @param x column index, zero or greater, and less than width()
+ @param y row index, zero or greater, and less than height()
+ @return readable unsigned 16-bit pointer to pixel component at (x, y)
+ */
+ const uint16_t* addrF16(int x, int y) const {
+ SkASSERT(kRGBA_F16_SkColorType == fInfo.colorType() ||
+ kRGBA_F16Norm_SkColorType == fInfo.colorType());
+ return reinterpret_cast<const uint16_t*>(this->addr64(x, y));
+ }
+
+ /** Returns writable base pixel address.
+
+ @return writable generic base pointer to pixels
+ */
+ void* writable_addr() const { return const_cast<void*>(fPixels); }
+
+ /** Returns writable pixel address at (x, y).
+
+ Input is not validated: out of bounds values of x or y trigger an assert() if
+ built with SK_DEBUG defined. Returns zero if SkColorType is kUnknown_SkColorType.
+
+ @param x column index, zero or greater, and less than width()
+ @param y row index, zero or greater, and less than height()
+ @return writable generic pointer to pixel
+ */
+ void* writable_addr(int x, int y) const {
+ return const_cast<void*>(this->addr(x, y));
+ }
+
+ /** Returns writable pixel address at (x, y). Result is addressable as unsigned
+ 8-bit bytes. Will trigger an assert() if SkColorType is not kAlpha_8_SkColorType
+ or kGray_8_SkColorType, and is built with SK_DEBUG defined.
+
+ One byte corresponds to one pixel.
+
+ @param x column index, zero or greater, and less than width()
+ @param y row index, zero or greater, and less than height()
+ @return writable unsigned 8-bit pointer to pixels
+ */
+ uint8_t* writable_addr8(int x, int y) const {
+ return const_cast<uint8_t*>(this->addr8(x, y));
+ }
+
+ /** Returns writable_addr pixel address at (x, y). Result is addressable as unsigned
+ 16-bit words. Will trigger an assert() if SkColorType is not kRGB_565_SkColorType
+ or kARGB_4444_SkColorType, and is built with SK_DEBUG defined.
+
+ One word corresponds to one pixel.
+
+ @param x column index, zero or greater, and less than width()
+ @param y row index, zero or greater, and less than height()
+ @return writable unsigned 16-bit pointer to pixel
+ */
+ uint16_t* writable_addr16(int x, int y) const {
+ return const_cast<uint16_t*>(this->addr16(x, y));
+ }
+
+ /** Returns writable pixel address at (x, y). Result is addressable as unsigned
+ 32-bit words. Will trigger an assert() if SkColorType is not
+ kRGBA_8888_SkColorType or kBGRA_8888_SkColorType, and is built with SK_DEBUG
+ defined.
+
+ One word corresponds to one pixel.
+
+ @param x column index, zero or greater, and less than width()
+ @param y row index, zero or greater, and less than height()
+ @return writable unsigned 32-bit pointer to pixel
+ */
+ uint32_t* writable_addr32(int x, int y) const {
+ return const_cast<uint32_t*>(this->addr32(x, y));
+ }
+
+ /** Returns writable pixel address at (x, y). Result is addressable as unsigned
+ 64-bit words. Will trigger an assert() if SkColorType is not
+ kRGBA_F16_SkColorType and is built with SK_DEBUG defined.
+
+ One word corresponds to one pixel.
+
+ @param x column index, zero or greater, and less than width()
+ @param y row index, zero or greater, and less than height()
+ @return writable unsigned 64-bit pointer to pixel
+ */
+ uint64_t* writable_addr64(int x, int y) const {
+ return const_cast<uint64_t*>(this->addr64(x, y));
+ }
+
+ /** Returns writable pixel address at (x, y). Result is addressable as unsigned
+ 16-bit words. Will trigger an assert() if SkColorType is not
+ kRGBA_F16_SkColorType and is built with SK_DEBUG defined.
+
+ Each word represents one color component encoded as a half float.
+ Four words correspond to one pixel.
+
+ @param x column index, zero or greater, and less than width()
+ @param y row index, zero or greater, and less than height()
+ @return writable unsigned 16-bit pointer to first component of pixel
+ */
+ uint16_t* writable_addrF16(int x, int y) const {
+ return reinterpret_cast<uint16_t*>(writable_addr64(x, y));
+ }
+
+ /** Copies a SkRect of pixels to dstPixels. Copy starts at (0, 0), and does not
+ exceed SkPixmap (width(), height()).
+
+ dstInfo specifies width, height, SkColorType, SkAlphaType, and
+ SkColorSpace of destination. dstRowBytes specifics the gap from one destination
+ row to the next. Returns true if pixels are copied. Returns false if
+ dstInfo address equals nullptr, or dstRowBytes is less than dstInfo.minRowBytes().
+
+ Pixels are copied only if pixel conversion is possible. If SkPixmap colorType() is
+ kGray_8_SkColorType, or kAlpha_8_SkColorType; dstInfo.colorType() must match.
+ If SkPixmap colorType() is kGray_8_SkColorType, dstInfo.colorSpace() must match.
+ If SkPixmap alphaType() is kOpaque_SkAlphaType, dstInfo.alphaType() must
+ match. If SkPixmap colorSpace() is nullptr, dstInfo.colorSpace() must match. Returns
+ false if pixel conversion is not possible.
+
+ Returns false if SkPixmap width() or height() is zero or negative.
+
+ @param dstInfo destination width, height, SkColorType, SkAlphaType, SkColorSpace
+ @param dstPixels destination pixel storage
+ @param dstRowBytes destination row length
+ @return true if pixels are copied to dstPixels
+ */
+ bool readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes) const {
+ return this->readPixels(dstInfo, dstPixels, dstRowBytes, 0, 0);
+ }
+
+ /** Copies a SkRect of pixels to dstPixels. Copy starts at (srcX, srcY), and does not
+ exceed SkPixmap (width(), height()).
+
+ dstInfo specifies width, height, SkColorType, SkAlphaType, and
+ SkColorSpace of destination. dstRowBytes specifics the gap from one destination
+ row to the next. Returns true if pixels are copied. Returns false if
+ dstInfo address equals nullptr, or dstRowBytes is less than dstInfo.minRowBytes().
+
+ Pixels are copied only if pixel conversion is possible. If SkPixmap colorType() is
+ kGray_8_SkColorType, or kAlpha_8_SkColorType; dstInfo.colorType() must match.
+ If SkPixmap colorType() is kGray_8_SkColorType, dstInfo.colorSpace() must match.
+ If SkPixmap alphaType() is kOpaque_SkAlphaType, dstInfo.alphaType() must
+ match. If SkPixmap colorSpace() is nullptr, dstInfo.colorSpace() must match. Returns
+ false if pixel conversion is not possible.
+
+ srcX and srcY may be negative to copy only top or left of source. Returns
+ false if SkPixmap width() or height() is zero or negative. Returns false if:
+ abs(srcX) >= Pixmap width(), or if abs(srcY) >= Pixmap height().
+
+ @param dstInfo destination width, height, SkColorType, SkAlphaType, SkColorSpace
+ @param dstPixels destination pixel storage
+ @param dstRowBytes destination row length
+ @param srcX column index whose absolute value is less than width()
+ @param srcY row index whose absolute value is less than height()
+ @return true if pixels are copied to dstPixels
+ */
+ bool readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes, int srcX,
+ int srcY) const;
+
+ /** Copies a SkRect of pixels to dst. Copy starts at (srcX, srcY), and does not
+ exceed SkPixmap (width(), height()). dst specifies width, height, SkColorType,
+ SkAlphaType, and SkColorSpace of destination. Returns true if pixels are copied.
+ Returns false if dst address equals nullptr, or dst.rowBytes() is less than
+ dst SkImageInfo::minRowBytes.
+
+ Pixels are copied only if pixel conversion is possible. If SkPixmap colorType() is
+ kGray_8_SkColorType, or kAlpha_8_SkColorType; dst.info().colorType must match.
+ If SkPixmap colorType() is kGray_8_SkColorType, dst.info().colorSpace must match.
+ If SkPixmap alphaType() is kOpaque_SkAlphaType, dst.info().alphaType must
+ match. If SkPixmap colorSpace() is nullptr, dst.info().colorSpace must match. Returns
+ false if pixel conversion is not possible.
+
+ srcX and srcY may be negative to copy only top or left of source. Returns
+ false SkPixmap width() or height() is zero or negative. Returns false if:
+ abs(srcX) >= Pixmap width(), or if abs(srcY) >= Pixmap height().
+
+ @param dst SkImageInfo and pixel address to write to
+ @param srcX column index whose absolute value is less than width()
+ @param srcY row index whose absolute value is less than height()
+ @return true if pixels are copied to dst
+ */
+ bool readPixels(const SkPixmap& dst, int srcX, int srcY) const {
+ return this->readPixels(dst.info(), dst.writable_addr(), dst.rowBytes(), srcX, srcY);
+ }
+
+ /** Copies pixels inside bounds() to dst. dst specifies width, height, SkColorType,
+ SkAlphaType, and SkColorSpace of destination. Returns true if pixels are copied.
+ Returns false if dst address equals nullptr, or dst.rowBytes() is less than
+ dst SkImageInfo::minRowBytes.
+
+ Pixels are copied only if pixel conversion is possible. If SkPixmap colorType() is
+ kGray_8_SkColorType, or kAlpha_8_SkColorType; dst SkColorType must match.
+ If SkPixmap colorType() is kGray_8_SkColorType, dst SkColorSpace must match.
+ If SkPixmap alphaType() is kOpaque_SkAlphaType, dst SkAlphaType must
+ match. If SkPixmap colorSpace() is nullptr, dst SkColorSpace must match. Returns
+ false if pixel conversion is not possible.
+
+ Returns false if SkPixmap width() or height() is zero or negative.
+
+ @param dst SkImageInfo and pixel address to write to
+ @return true if pixels are copied to dst
+ */
+ bool readPixels(const SkPixmap& dst) const {
+ return this->readPixels(dst.info(), dst.writable_addr(), dst.rowBytes(), 0, 0);
+ }
+
+ /** Copies SkBitmap to dst, scaling pixels to fit dst.width() and dst.height(), and
+ converting pixels to match dst.colorType() and dst.alphaType(). Returns true if
+ pixels are copied. Returns false if dst address is nullptr, or dst.rowBytes() is
+ less than dst SkImageInfo::minRowBytes.
+
+ Pixels are copied only if pixel conversion is possible. If SkPixmap colorType() is
+ kGray_8_SkColorType, or kAlpha_8_SkColorType; dst SkColorType must match.
+ If SkPixmap colorType() is kGray_8_SkColorType, dst SkColorSpace must match.
+ If SkPixmap alphaType() is kOpaque_SkAlphaType, dst SkAlphaType must
+ match. If SkPixmap colorSpace() is nullptr, dst SkColorSpace must match. Returns
+ false if pixel conversion is not possible.
+
+ Returns false if SkBitmap width() or height() is zero or negative.
+
+ @param dst SkImageInfo and pixel address to write to
+ @return true if pixels are scaled to fit dst
+
+ example: https://fiddle.skia.org/c/@Pixmap_scalePixels
+ */
+ bool scalePixels(const SkPixmap& dst, const SkSamplingOptions&) const;
+
+ /** Writes color to pixels bounded by subset; returns true on success.
+ Returns false if colorType() is kUnknown_SkColorType, or if subset does
+ not intersect bounds().
+
+ @param color sRGB unpremultiplied color to write
+ @param subset bounding integer SkRect of written pixels
+ @return true if pixels are changed
+
+ example: https://fiddle.skia.org/c/@Pixmap_erase
+ */
+ bool erase(SkColor color, const SkIRect& subset) const;
+
+ /** Writes color to pixels inside bounds(); returns true on success.
+ Returns false if colorType() is kUnknown_SkColorType, or if bounds()
+ is empty.
+
+ @param color sRGB unpremultiplied color to write
+ @return true if pixels are changed
+ */
+ bool erase(SkColor color) const { return this->erase(color, this->bounds()); }
+
+ /** Writes color to pixels bounded by subset; returns true on success.
+ if subset is nullptr, writes colors pixels inside bounds(). Returns false if
+ colorType() is kUnknown_SkColorType, if subset is not nullptr and does
+ not intersect bounds(), or if subset is nullptr and bounds() is empty.
+
+ @param color sRGB unpremultiplied color to write
+ @param subset bounding integer SkRect of pixels to write; may be nullptr
+ @return true if pixels are changed
+
+ example: https://fiddle.skia.org/c/@Pixmap_erase_3
+ */
+ bool erase(const SkColor4f& color, const SkIRect* subset = nullptr) const {
+ return this->erase(color, nullptr, subset);
+ }
+
+ /** Writes color to pixels bounded by subset; returns true on success.
+ if subset is nullptr, writes colors pixels inside bounds(). Returns false if
+ colorType() is kUnknown_SkColorType, if subset is not nullptr and does
+ not intersect bounds(), or if subset is nullptr and bounds() is empty.
+
+ @param color unpremultiplied color to write
+ @param cs SkColorSpace of color
+ @param subset bounding integer SkRect of pixels to write; may be nullptr
+ @return true if pixels are changed
+ */
+ bool erase(const SkColor4f& color, SkColorSpace* cs, const SkIRect* subset = nullptr) const;
+
+private:
+ const void* fPixels;
+ size_t fRowBytes;
+ SkImageInfo fInfo;
+
+ friend class SkPixmapPriv;
+};
+
+#endif
diff --git a/src/deps/skia/include/core/SkPngChunkReader.h b/src/deps/skia/include/core/SkPngChunkReader.h
new file mode 100644
index 000000000..0ee8a9ecc
--- /dev/null
+++ b/src/deps/skia/include/core/SkPngChunkReader.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2015 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkPngChunkReader_DEFINED
+#define SkPngChunkReader_DEFINED
+
+#include "include/core/SkRefCnt.h"
+#include "include/core/SkTypes.h"
+
+/**
+ * SkPngChunkReader
+ *
+ * Base class for optional callbacks to retrieve meta/chunk data out of a PNG
+ * encoded image as it is being decoded.
+ * Used by SkCodec.
+ */
+class SkPngChunkReader : public SkRefCnt {
+public:
+ /**
+ * This will be called by the decoder when it sees an unknown chunk.
+ *
+ * Use by SkCodec:
+ * Depending on the location of the unknown chunks, this callback may be
+ * called by
+ * - the factory (NewFromStream/NewFromData)
+ * - getPixels
+ * - startScanlineDecode
+ * - the first call to getScanlines/skipScanlines
+ * The callback may be called from a different thread (e.g. if the SkCodec
+ * is passed to another thread), and it may be called multiple times, if
+ * the SkCodec is used multiple times.
+ *
+ * @param tag Name for this type of chunk.
+ * @param data Data to be interpreted by the subclass.
+ * @param length Number of bytes of data in the chunk.
+ * @return true to continue decoding, or false to indicate an error, which
+ * will cause the decoder to not return the image.
+ */
+ virtual bool readChunk(const char tag[], const void* data, size_t length) = 0;
+};
+#endif // SkPngChunkReader_DEFINED
diff --git a/src/deps/skia/include/core/SkPoint.h b/src/deps/skia/include/core/SkPoint.h
new file mode 100644
index 000000000..92cb0b7f0
--- /dev/null
+++ b/src/deps/skia/include/core/SkPoint.h
@@ -0,0 +1,566 @@
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkPoint_DEFINED
+#define SkPoint_DEFINED
+
+#include "include/core/SkMath.h"
+#include "include/core/SkScalar.h"
+#include "include/private/SkSafe32.h"
+
+struct SkIPoint;
+
+/** SkIVector provides an alternative name for SkIPoint. SkIVector and SkIPoint
+ can be used interchangeably for all purposes.
+*/
+typedef SkIPoint SkIVector;
+
+/** \struct SkIPoint
+ SkIPoint holds two 32-bit integer coordinates.
+*/
+struct SkIPoint {
+ int32_t fX; //!< x-axis value
+ int32_t fY; //!< y-axis value
+
+ /** Sets fX to x, fY to y.
+
+ @param x integer x-axis value of constructed SkIPoint
+ @param y integer y-axis value of constructed SkIPoint
+ @return SkIPoint (x, y)
+ */
+ static constexpr SkIPoint Make(int32_t x, int32_t y) {
+ return {x, y};
+ }
+
+ /** Returns x-axis value of SkIPoint.
+
+ @return fX
+ */
+ constexpr int32_t x() const { return fX; }
+
+ /** Returns y-axis value of SkIPoint.
+
+ @return fY
+ */
+ constexpr int32_t y() const { return fY; }
+
+ /** Returns true if fX and fY are both zero.
+
+ @return true if fX is zero and fY is zero
+ */
+ bool isZero() const { return (fX | fY) == 0; }
+
+ /** Sets fX to x and fY to y.
+
+ @param x new value for fX
+ @param y new value for fY
+ */
+ void set(int32_t x, int32_t y) {
+ fX = x;
+ fY = y;
+ }
+
+ /** Returns SkIPoint changing the signs of fX and fY.
+
+ @return SkIPoint as (-fX, -fY)
+ */
+ SkIPoint operator-() const {
+ return {-fX, -fY};
+ }
+
+ /** Offsets SkIPoint by ivector v. Sets SkIPoint to (fX + v.fX, fY + v.fY).
+
+ @param v ivector to add
+ */
+ void operator+=(const SkIVector& v) {
+ fX = Sk32_sat_add(fX, v.fX);
+ fY = Sk32_sat_add(fY, v.fY);
+ }
+
+ /** Subtracts ivector v from SkIPoint. Sets SkIPoint to: (fX - v.fX, fY - v.fY).
+
+ @param v ivector to subtract
+ */
+ void operator-=(const SkIVector& v) {
+ fX = Sk32_sat_sub(fX, v.fX);
+ fY = Sk32_sat_sub(fY, v.fY);
+ }
+
+ /** Returns true if SkIPoint is equivalent to SkIPoint constructed from (x, y).
+
+ @param x value compared with fX
+ @param y value compared with fY
+ @return true if SkIPoint equals (x, y)
+ */
+ bool equals(int32_t x, int32_t y) const {
+ return fX == x && fY == y;
+ }
+
+ /** Returns true if a is equivalent to b.
+
+ @param a SkIPoint to compare
+ @param b SkIPoint to compare
+ @return true if a.fX == b.fX and a.fY == b.fY
+ */
+ friend bool operator==(const SkIPoint& a, const SkIPoint& b) {
+ return a.fX == b.fX && a.fY == b.fY;
+ }
+
+ /** Returns true if a is not equivalent to b.
+
+ @param a SkIPoint to compare
+ @param b SkIPoint to compare
+ @return true if a.fX != b.fX or a.fY != b.fY
+ */
+ friend bool operator!=(const SkIPoint& a, const SkIPoint& b) {
+ return a.fX != b.fX || a.fY != b.fY;
+ }
+
+ /** Returns ivector from b to a; computed as (a.fX - b.fX, a.fY - b.fY).
+
+ Can also be used to subtract ivector from ivector, returning ivector.
+
+ @param a SkIPoint or ivector to subtract from
+ @param b ivector to subtract
+ @return ivector from b to a
+ */
+ friend SkIVector operator-(const SkIPoint& a, const SkIPoint& b) {
+ return { Sk32_sat_sub(a.fX, b.fX), Sk32_sat_sub(a.fY, b.fY) };
+ }
+
+ /** Returns SkIPoint resulting from SkIPoint a offset by ivector b, computed as:
+ (a.fX + b.fX, a.fY + b.fY).
+
+ Can also be used to offset SkIPoint b by ivector a, returning SkIPoint.
+ Can also be used to add ivector to ivector, returning ivector.
+
+ @param a SkIPoint or ivector to add to
+ @param b SkIPoint or ivector to add
+ @return SkIPoint equal to a offset by b
+ */
+ friend SkIPoint operator+(const SkIPoint& a, const SkIVector& b) {
+ return { Sk32_sat_add(a.fX, b.fX), Sk32_sat_add(a.fY, b.fY) };
+ }
+};
+
+struct SkPoint;
+
+/** SkVector provides an alternative name for SkPoint. SkVector and SkPoint can
+ be used interchangeably for all purposes.
+*/
+typedef SkPoint SkVector;
+
+/** \struct SkPoint
+ SkPoint holds two 32-bit floating point coordinates.
+*/
+struct SK_API SkPoint {
+ SkScalar fX; //!< x-axis value
+ SkScalar fY; //!< y-axis value
+
+ /** Sets fX to x, fY to y. Used both to set SkPoint and vector.
+
+ @param x SkScalar x-axis value of constructed SkPoint or vector
+ @param y SkScalar y-axis value of constructed SkPoint or vector
+ @return SkPoint (x, y)
+ */
+ static constexpr SkPoint Make(SkScalar x, SkScalar y) {
+ return {x, y};
+ }
+
+ /** Returns x-axis value of SkPoint or vector.
+
+ @return fX
+ */
+ constexpr SkScalar x() const { return fX; }
+
+ /** Returns y-axis value of SkPoint or vector.
+
+ @return fY
+ */
+ constexpr SkScalar y() const { return fY; }
+
+ /** Returns true if fX and fY are both zero.
+
+ @return true if fX is zero and fY is zero
+ */
+ bool isZero() const { return (0 == fX) & (0 == fY); }
+
+ /** Sets fX to x and fY to y.
+
+ @param x new value for fX
+ @param y new value for fY
+ */
+ void set(SkScalar x, SkScalar y) {
+ fX = x;
+ fY = y;
+ }
+
+ /** Sets fX to x and fY to y, promoting integers to SkScalar values.
+
+ Assigning a large integer value directly to fX or fY may cause a compiler
+ error, triggered by narrowing conversion of int to SkScalar. This safely
+ casts x and y to avoid the error.
+
+ @param x new value for fX
+ @param y new value for fY
+ */
+ void iset(int32_t x, int32_t y) {
+ fX = SkIntToScalar(x);
+ fY = SkIntToScalar(y);
+ }
+
+ /** Sets fX to p.fX and fY to p.fY, promoting integers to SkScalar values.
+
+ Assigning an SkIPoint containing a large integer value directly to fX or fY may
+ cause a compiler error, triggered by narrowing conversion of int to SkScalar.
+ This safely casts p.fX and p.fY to avoid the error.
+
+ @param p SkIPoint members promoted to SkScalar
+ */
+ void iset(const SkIPoint& p) {
+ fX = SkIntToScalar(p.fX);
+ fY = SkIntToScalar(p.fY);
+ }
+
+ /** Sets fX to absolute value of pt.fX; and fY to absolute value of pt.fY.
+
+ @param pt members providing magnitude for fX and fY
+ */
+ void setAbs(const SkPoint& pt) {
+ fX = SkScalarAbs(pt.fX);
+ fY = SkScalarAbs(pt.fY);
+ }
+
+ /** Adds offset to each SkPoint in points array with count entries.
+
+ @param points SkPoint array
+ @param count entries in array
+ @param offset vector added to points
+ */
+ static void Offset(SkPoint points[], int count, const SkVector& offset) {
+ Offset(points, count, offset.fX, offset.fY);
+ }
+
+ /** Adds offset (dx, dy) to each SkPoint in points array of length count.
+
+ @param points SkPoint array
+ @param count entries in array
+ @param dx added to fX in points
+ @param dy added to fY in points
+ */
+ static void Offset(SkPoint points[], int count, SkScalar dx, SkScalar dy) {
+ for (int i = 0; i < count; ++i) {
+ points[i].offset(dx, dy);
+ }
+ }
+
+ /** Adds offset (dx, dy) to SkPoint.
+
+ @param dx added to fX
+ @param dy added to fY
+ */
+ void offset(SkScalar dx, SkScalar dy) {
+ fX += dx;
+ fY += dy;
+ }
+
+ /** Returns the Euclidean distance from origin, computed as:
+
+ sqrt(fX * fX + fY * fY)
+
+ .
+
+ @return straight-line distance to origin
+ */
+ SkScalar length() const { return SkPoint::Length(fX, fY); }
+
+ /** Returns the Euclidean distance from origin, computed as:
+
+ sqrt(fX * fX + fY * fY)
+
+ .
+
+ @return straight-line distance to origin
+ */
+ SkScalar distanceToOrigin() const { return this->length(); }
+
+ /** Scales (fX, fY) so that length() returns one, while preserving ratio of fX to fY,
+ if possible. If prior length is nearly zero, sets vector to (0, 0) and returns
+ false; otherwise returns true.
+
+ @return true if former length is not zero or nearly zero
+
+ example: https://fiddle.skia.org/c/@Point_normalize_2
+ */
+ bool normalize();
+
+ /** Sets vector to (x, y) scaled so length() returns one, and so that
+ (fX, fY) is proportional to (x, y). If (x, y) length is nearly zero,
+ sets vector to (0, 0) and returns false; otherwise returns true.
+
+ @param x proportional value for fX
+ @param y proportional value for fY
+ @return true if (x, y) length is not zero or nearly zero
+
+ example: https://fiddle.skia.org/c/@Point_setNormalize
+ */
+ bool setNormalize(SkScalar x, SkScalar y);
+
+ /** Scales vector so that distanceToOrigin() returns length, if possible. If former
+ length is nearly zero, sets vector to (0, 0) and return false; otherwise returns
+ true.
+
+ @param length straight-line distance to origin
+ @return true if former length is not zero or nearly zero
+
+ example: https://fiddle.skia.org/c/@Point_setLength
+ */
+ bool setLength(SkScalar length);
+
+ /** Sets vector to (x, y) scaled to length, if possible. If former
+ length is nearly zero, sets vector to (0, 0) and return false; otherwise returns
+ true.
+
+ @param x proportional value for fX
+ @param y proportional value for fY
+ @param length straight-line distance to origin
+ @return true if (x, y) length is not zero or nearly zero
+
+ example: https://fiddle.skia.org/c/@Point_setLength_2
+ */
+ bool setLength(SkScalar x, SkScalar y, SkScalar length);
+
+ /** Sets dst to SkPoint times scale. dst may be SkPoint to modify SkPoint in place.
+
+ @param scale factor to multiply SkPoint by
+ @param dst storage for scaled SkPoint
+
+ example: https://fiddle.skia.org/c/@Point_scale
+ */
+ void scale(SkScalar scale, SkPoint* dst) const;
+
+ /** Scales SkPoint in place by scale.
+
+ @param value factor to multiply SkPoint by
+ */
+ void scale(SkScalar value) { this->scale(value, this); }
+
+ /** Changes the sign of fX and fY.
+ */
+ void negate() {
+ fX = -fX;
+ fY = -fY;
+ }
+
+ /** Returns SkPoint changing the signs of fX and fY.
+
+ @return SkPoint as (-fX, -fY)
+ */
+ SkPoint operator-() const {
+ return {-fX, -fY};
+ }
+
+ /** Adds vector v to SkPoint. Sets SkPoint to: (fX + v.fX, fY + v.fY).
+
+ @param v vector to add
+ */
+ void operator+=(const SkVector& v) {
+ fX += v.fX;
+ fY += v.fY;
+ }
+
+ /** Subtracts vector v from SkPoint. Sets SkPoint to: (fX - v.fX, fY - v.fY).
+
+ @param v vector to subtract
+ */
+ void operator-=(const SkVector& v) {
+ fX -= v.fX;
+ fY -= v.fY;
+ }
+
+ /** Returns SkPoint multiplied by scale.
+
+ @param scale scalar to multiply by
+ @return SkPoint as (fX * scale, fY * scale)
+ */
+ SkPoint operator*(SkScalar scale) const {
+ return {fX * scale, fY * scale};
+ }
+
+ /** Multiplies SkPoint by scale. Sets SkPoint to: (fX * scale, fY * scale).
+
+ @param scale scalar to multiply by
+ @return reference to SkPoint
+ */
+ SkPoint& operator*=(SkScalar scale) {
+ fX *= scale;
+ fY *= scale;
+ return *this;
+ }
+
+ /** Returns true if both fX and fY are measurable values.
+
+ @return true for values other than infinities and NaN
+ */
+ bool isFinite() const {
+ SkScalar accum = 0;
+ accum *= fX;
+ accum *= fY;
+
+ // accum is either NaN or it is finite (zero).
+ SkASSERT(0 == accum || SkScalarIsNaN(accum));
+
+ // value==value will be true iff value is not NaN
+ // TODO: is it faster to say !accum or accum==accum?
+ return !SkScalarIsNaN(accum);
+ }
+
+ /** Returns true if SkPoint is equivalent to SkPoint constructed from (x, y).
+
+ @param x value compared with fX
+ @param y value compared with fY
+ @return true if SkPoint equals (x, y)
+ */
+ bool equals(SkScalar x, SkScalar y) const {
+ return fX == x && fY == y;
+ }
+
+ /** Returns true if a is equivalent to b.
+
+ @param a SkPoint to compare
+ @param b SkPoint to compare
+ @return true if a.fX == b.fX and a.fY == b.fY
+ */
+ friend bool operator==(const SkPoint& a, const SkPoint& b) {
+ return a.fX == b.fX && a.fY == b.fY;
+ }
+
+ /** Returns true if a is not equivalent to b.
+
+ @param a SkPoint to compare
+ @param b SkPoint to compare
+ @return true if a.fX != b.fX or a.fY != b.fY
+ */
+ friend bool operator!=(const SkPoint& a, const SkPoint& b) {
+ return a.fX != b.fX || a.fY != b.fY;
+ }
+
+ /** Returns vector from b to a, computed as (a.fX - b.fX, a.fY - b.fY).
+
+ Can also be used to subtract vector from SkPoint, returning SkPoint.
+ Can also be used to subtract vector from vector, returning vector.
+
+ @param a SkPoint to subtract from
+ @param b SkPoint to subtract
+ @return vector from b to a
+ */
+ friend SkVector operator-(const SkPoint& a, const SkPoint& b) {
+ return {a.fX - b.fX, a.fY - b.fY};
+ }
+
+ /** Returns SkPoint resulting from SkPoint a offset by vector b, computed as:
+ (a.fX + b.fX, a.fY + b.fY).
+
+ Can also be used to offset SkPoint b by vector a, returning SkPoint.
+ Can also be used to add vector to vector, returning vector.
+
+ @param a SkPoint or vector to add to
+ @param b SkPoint or vector to add
+ @return SkPoint equal to a offset by b
+ */
+ friend SkPoint operator+(const SkPoint& a, const SkVector& b) {
+ return {a.fX + b.fX, a.fY + b.fY};
+ }
+
+ /** Returns the Euclidean distance from origin, computed as:
+
+ sqrt(x * x + y * y)
+
+ .
+
+ @param x component of length
+ @param y component of length
+ @return straight-line distance to origin
+
+ example: https://fiddle.skia.org/c/@Point_Length
+ */
+ static SkScalar Length(SkScalar x, SkScalar y);
+
+ /** Scales (vec->fX, vec->fY) so that length() returns one, while preserving ratio of vec->fX
+ to vec->fY, if possible. If original length is nearly zero, sets vec to (0, 0) and returns
+ zero; otherwise, returns length of vec before vec is scaled.
+
+ Returned prior length may be SK_ScalarInfinity if it can not be represented by SkScalar.
+
+ Note that normalize() is faster if prior length is not required.
+
+ @param vec normalized to unit length
+ @return original vec length
+
+ example: https://fiddle.skia.org/c/@Point_Normalize
+ */
+ static SkScalar Normalize(SkVector* vec);
+
+ /** Returns the Euclidean distance between a and b.
+
+ @param a line end point
+ @param b line end point
+ @return straight-line distance from a to b
+ */
+ static SkScalar Distance(const SkPoint& a, const SkPoint& b) {
+ return Length(a.fX - b.fX, a.fY - b.fY);
+ }
+
+ /** Returns the dot product of vector a and vector b.
+
+ @param a left side of dot product
+ @param b right side of dot product
+ @return product of input magnitudes and cosine of the angle between them
+ */
+ static SkScalar DotProduct(const SkVector& a, const SkVector& b) {
+ return a.fX * b.fX + a.fY * b.fY;
+ }
+
+ /** Returns the cross product of vector a and vector b.
+
+ a and b form three-dimensional vectors with z-axis value equal to zero. The
+ cross product is a three-dimensional vector with x-axis and y-axis values equal
+ to zero. The cross product z-axis component is returned.
+
+ @param a left side of cross product
+ @param b right side of cross product
+ @return area spanned by vectors signed by angle direction
+ */
+ static SkScalar CrossProduct(const SkVector& a, const SkVector& b) {
+ return a.fX * b.fY - a.fY * b.fX;
+ }
+
+ /** Returns the cross product of vector and vec.
+
+ Vector and vec form three-dimensional vectors with z-axis value equal to zero.
+ The cross product is a three-dimensional vector with x-axis and y-axis values
+ equal to zero. The cross product z-axis component is returned.
+
+ @param vec right side of cross product
+ @return area spanned by vectors signed by angle direction
+ */
+ SkScalar cross(const SkVector& vec) const {
+ return CrossProduct(*this, vec);
+ }
+
+ /** Returns the dot product of vector and vector vec.
+
+ @param vec right side of dot product
+ @return product of input magnitudes and cosine of the angle between them
+ */
+ SkScalar dot(const SkVector& vec) const {
+ return DotProduct(*this, vec);
+ }
+
+};
+
+#endif
diff --git a/src/deps/skia/include/core/SkPoint3.h b/src/deps/skia/include/core/SkPoint3.h
new file mode 100644
index 000000000..e372f8279
--- /dev/null
+++ b/src/deps/skia/include/core/SkPoint3.h
@@ -0,0 +1,157 @@
+/*
+ * Copyright 2015 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkPoint3_DEFINED
+#define SkPoint3_DEFINED
+
+#include "include/core/SkPoint.h"
+
+struct SK_API SkPoint3 {
+ SkScalar fX, fY, fZ;
+
+ static SkPoint3 Make(SkScalar x, SkScalar y, SkScalar z) {
+ SkPoint3 pt;
+ pt.set(x, y, z);
+ return pt;
+ }
+
+ SkScalar x() const { return fX; }
+ SkScalar y() const { return fY; }
+ SkScalar z() const { return fZ; }
+
+ void set(SkScalar x, SkScalar y, SkScalar z) { fX = x; fY = y; fZ = z; }
+
+ friend bool operator==(const SkPoint3& a, const SkPoint3& b) {
+ return a.fX == b.fX && a.fY == b.fY && a.fZ == b.fZ;
+ }
+
+ friend bool operator!=(const SkPoint3& a, const SkPoint3& b) {
+ return !(a == b);
+ }
+
+ /** Returns the Euclidian distance from (0,0,0) to (x,y,z)
+ */
+ static SkScalar Length(SkScalar x, SkScalar y, SkScalar z);
+
+ /** Return the Euclidian distance from (0,0,0) to the point
+ */
+ SkScalar length() const { return SkPoint3::Length(fX, fY, fZ); }
+
+ /** Set the point (vector) to be unit-length in the same direction as it
+ already points. If the point has a degenerate length (i.e., nearly 0)
+ then set it to (0,0,0) and return false; otherwise return true.
+ */
+ bool normalize();
+
+ /** Return a new point whose X, Y and Z coordinates are scaled.
+ */
+ SkPoint3 makeScale(SkScalar scale) const {
+ SkPoint3 p;
+ p.set(scale * fX, scale * fY, scale * fZ);
+ return p;
+ }
+
+ /** Scale the point's coordinates by scale.
+ */
+ void scale(SkScalar value) {
+ fX *= value;
+ fY *= value;
+ fZ *= value;
+ }
+
+ /** Return a new point whose X, Y and Z coordinates are the negative of the
+ original point's
+ */
+ SkPoint3 operator-() const {
+ SkPoint3 neg;
+ neg.fX = -fX;
+ neg.fY = -fY;
+ neg.fZ = -fZ;
+ return neg;
+ }
+
+ /** Returns a new point whose coordinates are the difference between
+ a and b (i.e., a - b)
+ */
+ friend SkPoint3 operator-(const SkPoint3& a, const SkPoint3& b) {
+ return { a.fX - b.fX, a.fY - b.fY, a.fZ - b.fZ };
+ }
+
+ /** Returns a new point whose coordinates are the sum of a and b (a + b)
+ */
+ friend SkPoint3 operator+(const SkPoint3& a, const SkPoint3& b) {
+ return { a.fX + b.fX, a.fY + b.fY, a.fZ + b.fZ };
+ }
+
+ /** Add v's coordinates to the point's
+ */
+ void operator+=(const SkPoint3& v) {
+ fX += v.fX;
+ fY += v.fY;
+ fZ += v.fZ;
+ }
+
+ /** Subtract v's coordinates from the point's
+ */
+ void operator-=(const SkPoint3& v) {
+ fX -= v.fX;
+ fY -= v.fY;
+ fZ -= v.fZ;
+ }
+
+ friend SkPoint3 operator*(SkScalar t, SkPoint3 p) {
+ return { t * p.fX, t * p.fY, t * p.fZ };
+ }
+
+ /** Returns true if fX, fY, and fZ are measurable values.
+
+ @return true for values other than infinities and NaN
+ */
+ bool isFinite() const {
+ SkScalar accum = 0;
+ accum *= fX;
+ accum *= fY;
+ accum *= fZ;
+
+ // accum is either NaN or it is finite (zero).
+ SkASSERT(0 == accum || SkScalarIsNaN(accum));
+
+ // value==value will be true iff value is not NaN
+ // TODO: is it faster to say !accum or accum==accum?
+ return !SkScalarIsNaN(accum);
+ }
+
+ /** Returns the dot product of a and b, treating them as 3D vectors
+ */
+ static SkScalar DotProduct(const SkPoint3& a, const SkPoint3& b) {
+ return a.fX * b.fX + a.fY * b.fY + a.fZ * b.fZ;
+ }
+
+ SkScalar dot(const SkPoint3& vec) const {
+ return DotProduct(*this, vec);
+ }
+
+ /** Returns the cross product of a and b, treating them as 3D vectors
+ */
+ static SkPoint3 CrossProduct(const SkPoint3& a, const SkPoint3& b) {
+ SkPoint3 result;
+ result.fX = a.fY*b.fZ - a.fZ*b.fY;
+ result.fY = a.fZ*b.fX - a.fX*b.fZ;
+ result.fZ = a.fX*b.fY - a.fY*b.fX;
+
+ return result;
+ }
+
+ SkPoint3 cross(const SkPoint3& vec) const {
+ return CrossProduct(*this, vec);
+ }
+};
+
+typedef SkPoint3 SkVector3;
+typedef SkPoint3 SkColor3f;
+
+#endif
diff --git a/src/deps/skia/include/core/SkPromiseImageTexture.h b/src/deps/skia/include/core/SkPromiseImageTexture.h
new file mode 100644
index 000000000..05434c094
--- /dev/null
+++ b/src/deps/skia/include/core/SkPromiseImageTexture.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkPromiseImageTexture_DEFINED
+#define SkPromiseImageTexture_DEFINED
+
+#include "include/core/SkTypes.h"
+
+#if SK_SUPPORT_GPU
+#include "include/core/SkRefCnt.h"
+#include "include/gpu/GrBackendSurface.h"
+/**
+ * This type is used to fulfill textures for PromiseImages. Once an instance is returned from a
+ * PromiseImageTextureFulfillProc the GrBackendTexture it wraps must remain valid until the
+ * corresponding PromiseImageTextureReleaseProc is called.
+ */
+class SK_API SkPromiseImageTexture : public SkNVRefCnt<SkPromiseImageTexture> {
+public:
+ SkPromiseImageTexture() = delete;
+ SkPromiseImageTexture(const SkPromiseImageTexture&) = delete;
+ SkPromiseImageTexture(SkPromiseImageTexture&&) = delete;
+ ~SkPromiseImageTexture();
+ SkPromiseImageTexture& operator=(const SkPromiseImageTexture&) = delete;
+ SkPromiseImageTexture& operator=(SkPromiseImageTexture&&) = delete;
+
+ static sk_sp<SkPromiseImageTexture> Make(const GrBackendTexture& backendTexture) {
+ if (!backendTexture.isValid()) {
+ return nullptr;
+ }
+ return sk_sp<SkPromiseImageTexture>(new SkPromiseImageTexture(backendTexture));
+ }
+
+ GrBackendTexture backendTexture() const { return fBackendTexture; }
+
+private:
+ explicit SkPromiseImageTexture(const GrBackendTexture& backendTexture);
+
+ GrBackendTexture fBackendTexture;
+};
+#endif // SK_SUPPORT_GPU
+
+#endif // SkPromiseImageTexture_DEFINED
diff --git a/src/deps/skia/include/core/SkRRect.h b/src/deps/skia/include/core/SkRRect.h
new file mode 100644
index 000000000..099385168
--- /dev/null
+++ b/src/deps/skia/include/core/SkRRect.h
@@ -0,0 +1,512 @@
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkRRect_DEFINED
+#define SkRRect_DEFINED
+
+#include "include/core/SkPoint.h"
+#include "include/core/SkRect.h"
+
+class SkPath;
+class SkMatrix;
+class SkString;
+
+/** \class SkRRect
+ SkRRect describes a rounded rectangle with a bounds and a pair of radii for each corner.
+ The bounds and radii can be set so that SkRRect describes: a rectangle with sharp corners;
+ a circle; an oval; or a rectangle with one or more rounded corners.
+
+ SkRRect allows implementing CSS properties that describe rounded corners.
+ SkRRect may have up to eight different radii, one for each axis on each of its four
+ corners.
+
+ SkRRect may modify the provided parameters when initializing bounds and radii.
+ If either axis radii is zero or less: radii are stored as zero; corner is square.
+ If corner curves overlap, radii are proportionally reduced to fit within bounds.
+*/
+class SK_API SkRRect {
+public:
+
+ /** Initializes bounds at (0, 0), the origin, with zero width and height.
+ Initializes corner radii to (0, 0), and sets type of kEmpty_Type.
+
+ @return empty SkRRect
+ */
+ SkRRect() = default;
+
+ /** Initializes to copy of rrect bounds and corner radii.
+
+ @param rrect bounds and corner to copy
+ @return copy of rrect
+ */
+ SkRRect(const SkRRect& rrect) = default;
+
+ /** Copies rrect bounds and corner radii.
+
+ @param rrect bounds and corner to copy
+ @return copy of rrect
+ */
+ SkRRect& operator=(const SkRRect& rrect) = default;
+
+ /** \enum SkRRect::Type
+ Type describes possible specializations of SkRRect. Each Type is
+ exclusive; a SkRRect may only have one type.
+
+ Type members become progressively less restrictive; larger values of
+ Type have more degrees of freedom than smaller values.
+ */
+ enum Type {
+ kEmpty_Type, //!< zero width or height
+ kRect_Type, //!< non-zero width and height, and zeroed radii
+ kOval_Type, //!< non-zero width and height filled with radii
+ kSimple_Type, //!< non-zero width and height with equal radii
+ kNinePatch_Type, //!< non-zero width and height with axis-aligned radii
+ kComplex_Type, //!< non-zero width and height with arbitrary radii
+ kLastType = kComplex_Type, //!< largest Type value
+ };
+
+ Type getType() const {
+ SkASSERT(this->isValid());
+ return static_cast<Type>(fType);
+ }
+
+ Type type() const { return this->getType(); }
+
+ inline bool isEmpty() const { return kEmpty_Type == this->getType(); }
+ inline bool isRect() const { return kRect_Type == this->getType(); }
+ inline bool isOval() const { return kOval_Type == this->getType(); }
+ inline bool isSimple() const { return kSimple_Type == this->getType(); }
+ inline bool isNinePatch() const { return kNinePatch_Type == this->getType(); }
+ inline bool isComplex() const { return kComplex_Type == this->getType(); }
+
+ /** Returns span on the x-axis. This does not check if result fits in 32-bit float;
+ result may be infinity.
+
+ @return rect().fRight minus rect().fLeft
+ */
+ SkScalar width() const { return fRect.width(); }
+
+ /** Returns span on the y-axis. This does not check if result fits in 32-bit float;
+ result may be infinity.
+
+ @return rect().fBottom minus rect().fTop
+ */
+ SkScalar height() const { return fRect.height(); }
+
+ /** Returns top-left corner radii. If type() returns kEmpty_Type, kRect_Type,
+ kOval_Type, or kSimple_Type, returns a value representative of all corner radii.
+ If type() returns kNinePatch_Type or kComplex_Type, at least one of the
+ remaining three corners has a different value.
+
+ @return corner radii for simple types
+ */
+ SkVector getSimpleRadii() const {
+ return fRadii[0];
+ }
+
+ /** Sets bounds to zero width and height at (0, 0), the origin. Sets
+ corner radii to zero and sets type to kEmpty_Type.
+ */
+ void setEmpty() { *this = SkRRect(); }
+
+ /** Sets bounds to sorted rect, and sets corner radii to zero.
+ If set bounds has width and height, and sets type to kRect_Type;
+ otherwise, sets type to kEmpty_Type.
+
+ @param rect bounds to set
+ */
+ void setRect(const SkRect& rect) {
+ if (!this->initializeRect(rect)) {
+ return;
+ }
+
+ memset(fRadii, 0, sizeof(fRadii));
+ fType = kRect_Type;
+
+ SkASSERT(this->isValid());
+ }
+
+ /** Initializes bounds at (0, 0), the origin, with zero width and height.
+ Initializes corner radii to (0, 0), and sets type of kEmpty_Type.
+
+ @return empty SkRRect
+ */
+ static SkRRect MakeEmpty() { return SkRRect(); }
+
+ /** Initializes to copy of r bounds and zeroes corner radii.
+
+ @param r bounds to copy
+ @return copy of r
+ */
+ static SkRRect MakeRect(const SkRect& r) {
+ SkRRect rr;
+ rr.setRect(r);
+ return rr;
+ }
+
+ /** Sets bounds to oval, x-axis radii to half oval.width(), and all y-axis radii
+ to half oval.height(). If oval bounds is empty, sets to kEmpty_Type.
+ Otherwise, sets to kOval_Type.
+
+ @param oval bounds of oval
+ @return oval
+ */
+ static SkRRect MakeOval(const SkRect& oval) {
+ SkRRect rr;
+ rr.setOval(oval);
+ return rr;
+ }
+
+ /** Sets to rounded rectangle with the same radii for all four corners.
+ If rect is empty, sets to kEmpty_Type.
+ Otherwise, if xRad and yRad are zero, sets to kRect_Type.
+ Otherwise, if xRad is at least half rect.width() and yRad is at least half
+ rect.height(), sets to kOval_Type.
+ Otherwise, sets to kSimple_Type.
+
+ @param rect bounds of rounded rectangle
+ @param xRad x-axis radius of corners
+ @param yRad y-axis radius of corners
+ @return rounded rectangle
+ */
+ static SkRRect MakeRectXY(const SkRect& rect, SkScalar xRad, SkScalar yRad) {
+ SkRRect rr;
+ rr.setRectXY(rect, xRad, yRad);
+ return rr;
+ }
+
+ /** Sets bounds to oval, x-axis radii to half oval.width(), and all y-axis radii
+ to half oval.height(). If oval bounds is empty, sets to kEmpty_Type.
+ Otherwise, sets to kOval_Type.
+
+ @param oval bounds of oval
+ */
+ void setOval(const SkRect& oval);
+
+ /** Sets to rounded rectangle with the same radii for all four corners.
+ If rect is empty, sets to kEmpty_Type.
+ Otherwise, if xRad or yRad is zero, sets to kRect_Type.
+ Otherwise, if xRad is at least half rect.width() and yRad is at least half
+ rect.height(), sets to kOval_Type.
+ Otherwise, sets to kSimple_Type.
+
+ @param rect bounds of rounded rectangle
+ @param xRad x-axis radius of corners
+ @param yRad y-axis radius of corners
+
+ example: https://fiddle.skia.org/c/@RRect_setRectXY
+ */
+ void setRectXY(const SkRect& rect, SkScalar xRad, SkScalar yRad);
+
+ /** Sets bounds to rect. Sets radii to (leftRad, topRad), (rightRad, topRad),
+ (rightRad, bottomRad), (leftRad, bottomRad).
+
+ If rect is empty, sets to kEmpty_Type.
+ Otherwise, if leftRad and rightRad are zero, sets to kRect_Type.
+ Otherwise, if topRad and bottomRad are zero, sets to kRect_Type.
+ Otherwise, if leftRad and rightRad are equal and at least half rect.width(), and
+ topRad and bottomRad are equal at least half rect.height(), sets to kOval_Type.
+ Otherwise, if leftRad and rightRad are equal, and topRad and bottomRad are equal,
+ sets to kSimple_Type. Otherwise, sets to kNinePatch_Type.
+
+ Nine patch refers to the nine parts defined by the radii: one center rectangle,
+ four edge patches, and four corner patches.
+
+ @param rect bounds of rounded rectangle
+ @param leftRad left-top and left-bottom x-axis radius
+ @param topRad left-top and right-top y-axis radius
+ @param rightRad right-top and right-bottom x-axis radius
+ @param bottomRad left-bottom and right-bottom y-axis radius
+ */
+ void setNinePatch(const SkRect& rect, SkScalar leftRad, SkScalar topRad,
+ SkScalar rightRad, SkScalar bottomRad);
+
+ /** Sets bounds to rect. Sets radii array for individual control of all for corners.
+
+ If rect is empty, sets to kEmpty_Type.
+ Otherwise, if one of each corner radii are zero, sets to kRect_Type.
+ Otherwise, if all x-axis radii are equal and at least half rect.width(), and
+ all y-axis radii are equal at least half rect.height(), sets to kOval_Type.
+ Otherwise, if all x-axis radii are equal, and all y-axis radii are equal,
+ sets to kSimple_Type. Otherwise, sets to kNinePatch_Type.
+
+ @param rect bounds of rounded rectangle
+ @param radii corner x-axis and y-axis radii
+
+ example: https://fiddle.skia.org/c/@RRect_setRectRadii
+ */
+ void setRectRadii(const SkRect& rect, const SkVector radii[4]);
+
+ /** \enum SkRRect::Corner
+ The radii are stored: top-left, top-right, bottom-right, bottom-left.
+ */
+ enum Corner {
+ kUpperLeft_Corner, //!< index of top-left corner radii
+ kUpperRight_Corner, //!< index of top-right corner radii
+ kLowerRight_Corner, //!< index of bottom-right corner radii
+ kLowerLeft_Corner, //!< index of bottom-left corner radii
+ };
+
+ /** Returns bounds. Bounds may have zero width or zero height. Bounds right is
+ greater than or equal to left; bounds bottom is greater than or equal to top.
+ Result is identical to getBounds().
+
+ @return bounding box
+ */
+ const SkRect& rect() const { return fRect; }
+
+ /** Returns scalar pair for radius of curve on x-axis and y-axis for one corner.
+ Both radii may be zero. If not zero, both are positive and finite.
+
+ @return x-axis and y-axis radii for one corner
+ */
+ SkVector radii(Corner corner) const { return fRadii[corner]; }
+
+ /** Returns bounds. Bounds may have zero width or zero height. Bounds right is
+ greater than or equal to left; bounds bottom is greater than or equal to top.
+ Result is identical to rect().
+
+ @return bounding box
+ */
+ const SkRect& getBounds() const { return fRect; }
+
+ /** Returns true if bounds and radii in a are equal to bounds and radii in b.
+
+ a and b are not equal if either contain NaN. a and b are equal if members
+ contain zeroes with different signs.
+
+ @param a SkRect bounds and radii to compare
+ @param b SkRect bounds and radii to compare
+ @return true if members are equal
+ */
+ friend bool operator==(const SkRRect& a, const SkRRect& b) {
+ return a.fRect == b.fRect && SkScalarsEqual(&a.fRadii[0].fX, &b.fRadii[0].fX, 8);
+ }
+
+ /** Returns true if bounds and radii in a are not equal to bounds and radii in b.
+
+ a and b are not equal if either contain NaN. a and b are equal if members
+ contain zeroes with different signs.
+
+ @param a SkRect bounds and radii to compare
+ @param b SkRect bounds and radii to compare
+ @return true if members are not equal
+ */
+ friend bool operator!=(const SkRRect& a, const SkRRect& b) {
+ return a.fRect != b.fRect || !SkScalarsEqual(&a.fRadii[0].fX, &b.fRadii[0].fX, 8);
+ }
+
+ /** Copies SkRRect to dst, then insets dst bounds by dx and dy, and adjusts dst
+ radii by dx and dy. dx and dy may be positive, negative, or zero. dst may be
+ SkRRect.
+
+ If either corner radius is zero, the corner has no curvature and is unchanged.
+ Otherwise, if adjusted radius becomes negative, pins radius to zero.
+ If dx exceeds half dst bounds width, dst bounds left and right are set to
+ bounds x-axis center. If dy exceeds half dst bounds height, dst bounds top and
+ bottom are set to bounds y-axis center.
+
+ If dx or dy cause the bounds to become infinite, dst bounds is zeroed.
+
+ @param dx added to rect().fLeft, and subtracted from rect().fRight
+ @param dy added to rect().fTop, and subtracted from rect().fBottom
+ @param dst insets bounds and radii
+
+ example: https://fiddle.skia.org/c/@RRect_inset
+ */
+ void inset(SkScalar dx, SkScalar dy, SkRRect* dst) const;
+
+ /** Insets bounds by dx and dy, and adjusts radii by dx and dy. dx and dy may be
+ positive, negative, or zero.
+
+ If either corner radius is zero, the corner has no curvature and is unchanged.
+ Otherwise, if adjusted radius becomes negative, pins radius to zero.
+ If dx exceeds half bounds width, bounds left and right are set to
+ bounds x-axis center. If dy exceeds half bounds height, bounds top and
+ bottom are set to bounds y-axis center.
+
+ If dx or dy cause the bounds to become infinite, bounds is zeroed.
+
+ @param dx added to rect().fLeft, and subtracted from rect().fRight
+ @param dy added to rect().fTop, and subtracted from rect().fBottom
+ */
+ void inset(SkScalar dx, SkScalar dy) {
+ this->inset(dx, dy, this);
+ }
+
+ /** Outsets dst bounds by dx and dy, and adjusts radii by dx and dy. dx and dy may be
+ positive, negative, or zero.
+
+ If either corner radius is zero, the corner has no curvature and is unchanged.
+ Otherwise, if adjusted radius becomes negative, pins radius to zero.
+ If dx exceeds half dst bounds width, dst bounds left and right are set to
+ bounds x-axis center. If dy exceeds half dst bounds height, dst bounds top and
+ bottom are set to bounds y-axis center.
+
+ If dx or dy cause the bounds to become infinite, dst bounds is zeroed.
+
+ @param dx subtracted from rect().fLeft, and added to rect().fRight
+ @param dy subtracted from rect().fTop, and added to rect().fBottom
+ @param dst outset bounds and radii
+ */
+ void outset(SkScalar dx, SkScalar dy, SkRRect* dst) const {
+ this->inset(-dx, -dy, dst);
+ }
+
+ /** Outsets bounds by dx and dy, and adjusts radii by dx and dy. dx and dy may be
+ positive, negative, or zero.
+
+ If either corner radius is zero, the corner has no curvature and is unchanged.
+ Otherwise, if adjusted radius becomes negative, pins radius to zero.
+ If dx exceeds half bounds width, bounds left and right are set to
+ bounds x-axis center. If dy exceeds half bounds height, bounds top and
+ bottom are set to bounds y-axis center.
+
+ If dx or dy cause the bounds to become infinite, bounds is zeroed.
+
+ @param dx subtracted from rect().fLeft, and added to rect().fRight
+ @param dy subtracted from rect().fTop, and added to rect().fBottom
+ */
+ void outset(SkScalar dx, SkScalar dy) {
+ this->inset(-dx, -dy, this);
+ }
+
+ /** Translates SkRRect by (dx, dy).
+
+ @param dx offset added to rect().fLeft and rect().fRight
+ @param dy offset added to rect().fTop and rect().fBottom
+ */
+ void offset(SkScalar dx, SkScalar dy) {
+ fRect.offset(dx, dy);
+ }
+
+ /** Returns SkRRect translated by (dx, dy).
+
+ @param dx offset added to rect().fLeft and rect().fRight
+ @param dy offset added to rect().fTop and rect().fBottom
+ @return SkRRect bounds offset by (dx, dy), with unchanged corner radii
+ */
+ SkRRect SK_WARN_UNUSED_RESULT makeOffset(SkScalar dx, SkScalar dy) const {
+ return SkRRect(fRect.makeOffset(dx, dy), fRadii, fType);
+ }
+
+ /** Returns true if rect is inside the bounds and corner radii, and if
+ SkRRect and rect are not empty.
+
+ @param rect area tested for containment
+ @return true if SkRRect contains rect
+
+ example: https://fiddle.skia.org/c/@RRect_contains
+ */
+ bool contains(const SkRect& rect) const;
+
+ /** Returns true if bounds and radii values are finite and describe a SkRRect
+ SkRRect::Type that matches getType(). All SkRRect methods construct valid types,
+ even if the input values are not valid. Invalid SkRRect data can only
+ be generated by corrupting memory.
+
+ @return true if bounds and radii match type()
+
+ example: https://fiddle.skia.org/c/@RRect_isValid
+ */
+ bool isValid() const;
+
+ static constexpr size_t kSizeInMemory = 12 * sizeof(SkScalar);
+
+ /** Writes SkRRect to buffer. Writes kSizeInMemory bytes, and returns
+ kSizeInMemory, the number of bytes written.
+
+ @param buffer storage for SkRRect
+ @return bytes written, kSizeInMemory
+
+ example: https://fiddle.skia.org/c/@RRect_writeToMemory
+ */
+ size_t writeToMemory(void* buffer) const;
+
+ /** Reads SkRRect from buffer, reading kSizeInMemory bytes.
+ Returns kSizeInMemory, bytes read if length is at least kSizeInMemory.
+ Otherwise, returns zero.
+
+ @param buffer memory to read from
+ @param length size of buffer
+ @return bytes read, or 0 if length is less than kSizeInMemory
+
+ example: https://fiddle.skia.org/c/@RRect_readFromMemory
+ */
+ size_t readFromMemory(const void* buffer, size_t length);
+
+ /** Transforms by SkRRect by matrix, storing result in dst.
+ Returns true if SkRRect transformed can be represented by another SkRRect.
+ Returns false if matrix contains transformations that are not axis aligned.
+
+ Asserts in debug builds if SkRRect equals dst.
+
+ @param matrix SkMatrix specifying the transform
+ @param dst SkRRect to store the result
+ @return true if transformation succeeded.
+
+ example: https://fiddle.skia.org/c/@RRect_transform
+ */
+ bool transform(const SkMatrix& matrix, SkRRect* dst) const;
+
+ /** Writes text representation of SkRRect to standard output.
+ Set asHex true to generate exact binary representations
+ of floating point numbers.
+
+ @param asHex true if SkScalar values are written as hexadecimal
+
+ example: https://fiddle.skia.org/c/@RRect_dump
+ */
+ void dump(bool asHex) const;
+ SkString dumpToString(bool asHex) const;
+
+ /** Writes text representation of SkRRect to standard output. The representation
+ may be directly compiled as C++ code. Floating point values are written
+ with limited precision; it may not be possible to reconstruct original
+ SkRRect from output.
+ */
+ void dump() const { this->dump(false); }
+
+ /** Writes text representation of SkRRect to standard output. The representation
+ may be directly compiled as C++ code. Floating point values are written
+ in hexadecimal to preserve their exact bit pattern. The output reconstructs the
+ original SkRRect.
+ */
+ void dumpHex() const { this->dump(true); }
+
+private:
+ static bool AreRectAndRadiiValid(const SkRect&, const SkVector[4]);
+
+ SkRRect(const SkRect& rect, const SkVector radii[4], int32_t type)
+ : fRect(rect)
+ , fRadii{radii[0], radii[1], radii[2], radii[3]}
+ , fType(type) {}
+
+ /**
+ * Initializes fRect. If the passed in rect is not finite or empty the rrect will be fully
+ * initialized and false is returned. Otherwise, just fRect is initialized and true is returned.
+ */
+ bool initializeRect(const SkRect&);
+
+ void computeType();
+ bool checkCornerContainment(SkScalar x, SkScalar y) const;
+ // Returns true if the radii had to be scaled to fit rect
+ bool scaleRadii();
+
+ SkRect fRect = SkRect::MakeEmpty();
+ // Radii order is UL, UR, LR, LL. Use Corner enum to index into fRadii[]
+ SkVector fRadii[4] = {{0, 0}, {0, 0}, {0,0}, {0,0}};
+ // use an explicitly sized type so we're sure the class is dense (no uninitialized bytes)
+ int32_t fType = kEmpty_Type;
+ // TODO: add padding so we can use memcpy for flattening and not copy uninitialized data
+
+ // to access fRadii directly
+ friend class SkPath;
+ friend class SkRRectPriv;
+};
+
+#endif
diff --git a/src/deps/skia/include/core/SkRSXform.h b/src/deps/skia/include/core/SkRSXform.h
new file mode 100644
index 000000000..91653311d
--- /dev/null
+++ b/src/deps/skia/include/core/SkRSXform.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2015 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkRSXform_DEFINED
+#define SkRSXform_DEFINED
+
+#include "include/core/SkPoint.h"
+#include "include/core/SkSize.h"
+
+/**
+ * A compressed form of a rotation+scale matrix.
+ *
+ * [ fSCos -fSSin fTx ]
+ * [ fSSin fSCos fTy ]
+ * [ 0 0 1 ]
+ */
+struct SkRSXform {
+ static SkRSXform Make(SkScalar scos, SkScalar ssin, SkScalar tx, SkScalar ty) {
+ SkRSXform xform = { scos, ssin, tx, ty };
+ return xform;
+ }
+
+ /*
+ * Initialize a new xform based on the scale, rotation (in radians), final tx,ty location
+ * and anchor-point ax,ay within the src quad.
+ *
+ * Note: the anchor point is not normalized (e.g. 0...1) but is in pixels of the src image.
+ */
+ static SkRSXform MakeFromRadians(SkScalar scale, SkScalar radians, SkScalar tx, SkScalar ty,
+ SkScalar ax, SkScalar ay) {
+ const SkScalar s = SkScalarSin(radians) * scale;
+ const SkScalar c = SkScalarCos(radians) * scale;
+ return Make(c, s, tx + -c * ax + s * ay, ty + -s * ax - c * ay);
+ }
+
+ SkScalar fSCos;
+ SkScalar fSSin;
+ SkScalar fTx;
+ SkScalar fTy;
+
+ bool rectStaysRect() const {
+ return 0 == fSCos || 0 == fSSin;
+ }
+
+ void setIdentity() {
+ fSCos = 1;
+ fSSin = fTx = fTy = 0;
+ }
+
+ void set(SkScalar scos, SkScalar ssin, SkScalar tx, SkScalar ty) {
+ fSCos = scos;
+ fSSin = ssin;
+ fTx = tx;
+ fTy = ty;
+ }
+
+ void toQuad(SkScalar width, SkScalar height, SkPoint quad[4]) const;
+ void toQuad(const SkSize& size, SkPoint quad[4]) const {
+ this->toQuad(size.width(), size.height(), quad);
+ }
+ void toTriStrip(SkScalar width, SkScalar height, SkPoint strip[4]) const;
+};
+
+#endif
+
diff --git a/src/deps/skia/include/core/SkRasterHandleAllocator.h b/src/deps/skia/include/core/SkRasterHandleAllocator.h
new file mode 100644
index 000000000..ad7c379ee
--- /dev/null
+++ b/src/deps/skia/include/core/SkRasterHandleAllocator.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkRasterHandleAllocator_DEFINED
+#define SkRasterHandleAllocator_DEFINED
+
+#include "include/core/SkImageInfo.h"
+
+class SkBitmap;
+class SkCanvas;
+class SkMatrix;
+
+/**
+ * If a client wants to control the allocation of raster layers in a canvas, it should subclass
+ * SkRasterHandleAllocator. This allocator performs two tasks:
+ * 1. controls how the memory for the pixels is allocated
+ * 2. associates a "handle" to a private object that can track the matrix/clip of the SkCanvas
+ *
+ * This example allocates a canvas, and defers to the allocator to create the base layer.
+ *
+ * std::unique_ptr<SkCanvas> canvas = SkRasterHandleAllocator::MakeCanvas(
+ * SkImageInfo::Make(...),
+ * std::make_unique<MySubclassRasterHandleAllocator>(...),
+ * nullptr);
+ *
+ * If you have already allocated the base layer (and its handle, release-proc etc.) then you
+ * can pass those in using the last parameter to MakeCanvas().
+ *
+ * Regardless of how the base layer is allocated, each time canvas->saveLayer() is called,
+ * your allocator's allocHandle() will be called.
+ */
+class SK_API SkRasterHandleAllocator {
+public:
+ virtual ~SkRasterHandleAllocator() = default;
+
+ // The value that is returned to clients of the canvas that has this allocator installed.
+ typedef void* Handle;
+
+ struct Rec {
+ // When the allocation goes out of scope, this proc is called to free everything associated
+ // with it: the pixels, the "handle", etc. This is passed the pixel address and fReleaseCtx.
+ void (*fReleaseProc)(void* pixels, void* ctx);
+ void* fReleaseCtx; // context passed to fReleaseProc
+ void* fPixels; // pixels for this allocation
+ size_t fRowBytes; // rowbytes for these pixels
+ Handle fHandle; // public handle returned by SkCanvas::accessTopRasterHandle()
+ };
+
+ /**
+ * Given a requested info, allocate the corresponding pixels/rowbytes, and whatever handle
+ * is desired to give clients access to those pixels. The rec also contains a proc and context
+ * which will be called when this allocation goes out of scope.
+ *
+ * e.g.
+ * when canvas->saveLayer() is called, the allocator will be called to allocate the pixels
+ * for the layer. When canvas->restore() is called, the fReleaseProc will be called.
+ */
+ virtual bool allocHandle(const SkImageInfo&, Rec*) = 0;
+
+ /**
+ * Clients access the handle for a given layer by calling SkCanvas::accessTopRasterHandle().
+ * To allow the handle to reflect the current matrix/clip in the canvs, updateHandle() is
+ * is called. The subclass is responsible to update the handle as it sees fit.
+ */
+ virtual void updateHandle(Handle, const SkMatrix&, const SkIRect&) = 0;
+
+ /**
+ * This creates a canvas which will use the allocator to manage pixel allocations, including
+ * all calls to saveLayer().
+ *
+ * If rec is non-null, then it will be used as the base-layer of pixels/handle.
+ * If rec is null, then the allocator will be called for the base-layer as well.
+ */
+ static std::unique_ptr<SkCanvas> MakeCanvas(std::unique_ptr<SkRasterHandleAllocator>,
+ const SkImageInfo&, const Rec* rec = nullptr);
+
+protected:
+ SkRasterHandleAllocator() = default;
+ SkRasterHandleAllocator(const SkRasterHandleAllocator&) = delete;
+ SkRasterHandleAllocator& operator=(const SkRasterHandleAllocator&) = delete;
+
+private:
+ friend class SkBitmapDevice;
+
+ Handle allocBitmap(const SkImageInfo&, SkBitmap*);
+};
+
+#endif
diff --git a/src/deps/skia/include/core/SkRect.h b/src/deps/skia/include/core/SkRect.h
new file mode 100644
index 000000000..99efe70bc
--- /dev/null
+++ b/src/deps/skia/include/core/SkRect.h
@@ -0,0 +1,1378 @@
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkRect_DEFINED
+#define SkRect_DEFINED
+
+#include "include/core/SkPoint.h"
+#include "include/core/SkSize.h"
+#include "include/private/SkSafe32.h"
+#include "include/private/SkTFitsIn.h"
+
+#include <algorithm>
+#include <utility>
+
+struct SkRect;
+
+/** \struct SkIRect
+ SkIRect holds four 32-bit integer coordinates describing the upper and
+ lower bounds of a rectangle. SkIRect may be created from outer bounds or
+ from position, width, and height. SkIRect describes an area; if its right
+ is less than or equal to its left, or if its bottom is less than or equal to
+ its top, it is considered empty.
+*/
+struct SK_API SkIRect {
+ int32_t fLeft; //!< smaller x-axis bounds
+ int32_t fTop; //!< smaller y-axis bounds
+ int32_t fRight; //!< larger x-axis bounds
+ int32_t fBottom; //!< larger y-axis bounds
+
+ /** Returns constructed SkIRect set to (0, 0, 0, 0).
+ Many other rectangles are empty; if left is equal to or greater than right,
+ or if top is equal to or greater than bottom. Setting all members to zero
+ is a convenience, but does not designate a special empty rectangle.
+
+ @return bounds (0, 0, 0, 0)
+ */
+ static constexpr SkIRect SK_WARN_UNUSED_RESULT MakeEmpty() {
+ return SkIRect{0, 0, 0, 0};
+ }
+
+ /** Returns constructed SkIRect set to (0, 0, w, h). Does not validate input; w or h
+ may be negative.
+
+ @param w width of constructed SkIRect
+ @param h height of constructed SkIRect
+ @return bounds (0, 0, w, h)
+ */
+ static constexpr SkIRect SK_WARN_UNUSED_RESULT MakeWH(int32_t w, int32_t h) {
+ return SkIRect{0, 0, w, h};
+ }
+
+ /** Returns constructed SkIRect set to (0, 0, size.width(), size.height()).
+ Does not validate input; size.width() or size.height() may be negative.
+
+ @param size values for SkIRect width and height
+ @return bounds (0, 0, size.width(), size.height())
+ */
+ static constexpr SkIRect SK_WARN_UNUSED_RESULT MakeSize(const SkISize& size) {
+ return SkIRect{0, 0, size.fWidth, size.fHeight};
+ }
+
+ /** Returns constructed SkIRect set to (pt.x(), pt.y(), pt.x() + size.width(),
+ pt.y() + size.height()). Does not validate input; size.width() or size.height() may be
+ negative.
+
+ @param pt values for SkIRect fLeft and fTop
+ @param size values for SkIRect width and height
+ @return bounds at pt with width and height of size
+ */
+ static constexpr SkIRect SK_WARN_UNUSED_RESULT MakePtSize(SkIPoint pt, SkISize size) {
+ return MakeXYWH(pt.x(), pt.y(), size.width(), size.height());
+ }
+
+ /** Returns constructed SkIRect set to (l, t, r, b). Does not sort input; SkIRect may
+ result in fLeft greater than fRight, or fTop greater than fBottom.
+
+ @param l integer stored in fLeft
+ @param t integer stored in fTop
+ @param r integer stored in fRight
+ @param b integer stored in fBottom
+ @return bounds (l, t, r, b)
+ */
+ static constexpr SkIRect SK_WARN_UNUSED_RESULT MakeLTRB(int32_t l, int32_t t,
+ int32_t r, int32_t b) {
+ return SkIRect{l, t, r, b};
+ }
+
+ /** Returns constructed SkIRect set to: (x, y, x + w, y + h).
+ Does not validate input; w or h may be negative.
+
+ @param x stored in fLeft
+ @param y stored in fTop
+ @param w added to x and stored in fRight
+ @param h added to y and stored in fBottom
+ @return bounds at (x, y) with width w and height h
+ */
+ static constexpr SkIRect SK_WARN_UNUSED_RESULT MakeXYWH(int32_t x, int32_t y,
+ int32_t w, int32_t h) {
+ return { x, y, Sk32_sat_add(x, w), Sk32_sat_add(y, h) };
+ }
+
+ /** Returns left edge of SkIRect, if sorted.
+ Call sort() to reverse fLeft and fRight if needed.
+
+ @return fLeft
+ */
+ constexpr int32_t left() const { return fLeft; }
+
+ /** Returns top edge of SkIRect, if sorted. Call isEmpty() to see if SkIRect may be invalid,
+ and sort() to reverse fTop and fBottom if needed.
+
+ @return fTop
+ */
+ constexpr int32_t top() const { return fTop; }
+
+ /** Returns right edge of SkIRect, if sorted.
+ Call sort() to reverse fLeft and fRight if needed.
+
+ @return fRight
+ */
+ constexpr int32_t right() const { return fRight; }
+
+ /** Returns bottom edge of SkIRect, if sorted. Call isEmpty() to see if SkIRect may be invalid,
+ and sort() to reverse fTop and fBottom if needed.
+
+ @return fBottom
+ */
+ constexpr int32_t bottom() const { return fBottom; }
+
+ /** Returns left edge of SkIRect, if sorted. Call isEmpty() to see if SkIRect may be invalid,
+ and sort() to reverse fLeft and fRight if needed.
+
+ @return fLeft
+ */
+ constexpr int32_t x() const { return fLeft; }
+
+ /** Returns top edge of SkIRect, if sorted. Call isEmpty() to see if SkIRect may be invalid,
+ and sort() to reverse fTop and fBottom if needed.
+
+ @return fTop
+ */
+ constexpr int32_t y() const { return fTop; }
+
+ // Experimental
+ constexpr SkIPoint topLeft() const { return {fLeft, fTop}; }
+
+ /** Returns span on the x-axis. This does not check if SkIRect is sorted, or if
+ result fits in 32-bit signed integer; result may be negative.
+
+ @return fRight minus fLeft
+ */
+ constexpr int32_t width() const { return Sk32_can_overflow_sub(fRight, fLeft); }
+
+ /** Returns span on the y-axis. This does not check if SkIRect is sorted, or if
+ result fits in 32-bit signed integer; result may be negative.
+
+ @return fBottom minus fTop
+ */
+ constexpr int32_t height() const { return Sk32_can_overflow_sub(fBottom, fTop); }
+
+ /** Returns spans on the x-axis and y-axis. This does not check if SkIRect is sorted,
+ or if result fits in 32-bit signed integer; result may be negative.
+
+ @return SkISize (width, height)
+ */
+ constexpr SkISize size() const { return SkISize::Make(this->width(), this->height()); }
+
+ /** Returns span on the x-axis. This does not check if SkIRect is sorted, so the
+ result may be negative. This is safer than calling width() since width() might
+ overflow in its calculation.
+
+ @return fRight minus fLeft cast to int64_t
+ */
+ constexpr int64_t width64() const { return (int64_t)fRight - (int64_t)fLeft; }
+
+ /** Returns span on the y-axis. This does not check if SkIRect is sorted, so the
+ result may be negative. This is safer than calling height() since height() might
+ overflow in its calculation.
+
+ @return fBottom minus fTop cast to int64_t
+ */
+ constexpr int64_t height64() const { return (int64_t)fBottom - (int64_t)fTop; }
+
+ /** Returns true if fLeft is equal to or greater than fRight, or if fTop is equal
+ to or greater than fBottom. Call sort() to reverse rectangles with negative
+ width64() or height64().
+
+ @return true if width64() or height64() are zero or negative
+ */
+ bool isEmpty64() const { return fRight <= fLeft || fBottom <= fTop; }
+
+ /** Returns true if width() or height() are zero or negative.
+
+ @return true if width() or height() are zero or negative
+ */
+ bool isEmpty() const {
+ int64_t w = this->width64();
+ int64_t h = this->height64();
+ if (w <= 0 || h <= 0) {
+ return true;
+ }
+ // Return true if either exceeds int32_t
+ return !SkTFitsIn<int32_t>(w | h);
+ }
+
+ /** Returns true if all members in a: fLeft, fTop, fRight, and fBottom; are
+ identical to corresponding members in b.
+
+ @param a SkIRect to compare
+ @param b SkIRect to compare
+ @return true if members are equal
+ */
+ friend bool operator==(const SkIRect& a, const SkIRect& b) {
+ return !memcmp(&a, &b, sizeof(a));
+ }
+
+ /** Returns true if any member in a: fLeft, fTop, fRight, and fBottom; is not
+ identical to the corresponding member in b.
+
+ @param a SkIRect to compare
+ @param b SkIRect to compare
+ @return true if members are not equal
+ */
+ friend bool operator!=(const SkIRect& a, const SkIRect& b) {
+ return !(a == b);
+ }
+
+ /** Sets SkIRect to (0, 0, 0, 0).
+
+ Many other rectangles are empty; if left is equal to or greater than right,
+ or if top is equal to or greater than bottom. Setting all members to zero
+ is a convenience, but does not designate a special empty rectangle.
+ */
+ void setEmpty() { memset(this, 0, sizeof(*this)); }
+
+ /** Sets SkIRect to (left, top, right, bottom).
+ left and right are not sorted; left is not necessarily less than right.
+ top and bottom are not sorted; top is not necessarily less than bottom.
+
+ @param left stored in fLeft
+ @param top stored in fTop
+ @param right stored in fRight
+ @param bottom stored in fBottom
+ */
+ void setLTRB(int32_t left, int32_t top, int32_t right, int32_t bottom) {
+ fLeft = left;
+ fTop = top;
+ fRight = right;
+ fBottom = bottom;
+ }
+
+ /** Sets SkIRect to: (x, y, x + width, y + height).
+ Does not validate input; width or height may be negative.
+
+ @param x stored in fLeft
+ @param y stored in fTop
+ @param width added to x and stored in fRight
+ @param height added to y and stored in fBottom
+ */
+ void setXYWH(int32_t x, int32_t y, int32_t width, int32_t height) {
+ fLeft = x;
+ fTop = y;
+ fRight = Sk32_sat_add(x, width);
+ fBottom = Sk32_sat_add(y, height);
+ }
+
+ void setWH(int32_t width, int32_t height) {
+ fLeft = 0;
+ fTop = 0;
+ fRight = width;
+ fBottom = height;
+ }
+
+ void setSize(SkISize size) {
+ fLeft = 0;
+ fTop = 0;
+ fRight = size.width();
+ fBottom = size.height();
+ }
+
+ /** Returns SkIRect offset by (dx, dy).
+
+ If dx is negative, SkIRect returned is moved to the left.
+ If dx is positive, SkIRect returned is moved to the right.
+ If dy is negative, SkIRect returned is moved upward.
+ If dy is positive, SkIRect returned is moved downward.
+
+ @param dx offset added to fLeft and fRight
+ @param dy offset added to fTop and fBottom
+ @return SkIRect offset by dx and dy, with original width and height
+ */
+ constexpr SkIRect makeOffset(int32_t dx, int32_t dy) const {
+ return {
+ Sk32_sat_add(fLeft, dx), Sk32_sat_add(fTop, dy),
+ Sk32_sat_add(fRight, dx), Sk32_sat_add(fBottom, dy),
+ };
+ }
+
+ /** Returns SkIRect offset by (offset.x(), offset.y()).
+
+ If offset.x() is negative, SkIRect returned is moved to the left.
+ If offset.x() is positive, SkIRect returned is moved to the right.
+ If offset.y() is negative, SkIRect returned is moved upward.
+ If offset.y() is positive, SkIRect returned is moved downward.
+
+ @param offset translation vector
+ @return SkIRect translated by offset, with original width and height
+ */
+ constexpr SkIRect makeOffset(SkIVector offset) const {
+ return this->makeOffset(offset.x(), offset.y());
+ }
+
+ /** Returns SkIRect, inset by (dx, dy).
+
+ If dx is negative, SkIRect returned is wider.
+ If dx is positive, SkIRect returned is narrower.
+ If dy is negative, SkIRect returned is taller.
+ If dy is positive, SkIRect returned is shorter.
+
+ @param dx offset added to fLeft and subtracted from fRight
+ @param dy offset added to fTop and subtracted from fBottom
+ @return SkIRect inset symmetrically left and right, top and bottom
+ */
+ SkIRect makeInset(int32_t dx, int32_t dy) const {
+ return {
+ Sk32_sat_add(fLeft, dx), Sk32_sat_add(fTop, dy),
+ Sk32_sat_sub(fRight, dx), Sk32_sat_sub(fBottom, dy),
+ };
+ }
+
+ /** Returns SkIRect, outset by (dx, dy).
+
+ If dx is negative, SkIRect returned is narrower.
+ If dx is positive, SkIRect returned is wider.
+ If dy is negative, SkIRect returned is shorter.
+ If dy is positive, SkIRect returned is taller.
+
+ @param dx offset subtracted to fLeft and added from fRight
+ @param dy offset subtracted to fTop and added from fBottom
+ @return SkIRect outset symmetrically left and right, top and bottom
+ */
+ SkIRect makeOutset(int32_t dx, int32_t dy) const {
+ return {
+ Sk32_sat_sub(fLeft, dx), Sk32_sat_sub(fTop, dy),
+ Sk32_sat_add(fRight, dx), Sk32_sat_add(fBottom, dy),
+ };
+ }
+
+ /** Offsets SkIRect by adding dx to fLeft, fRight; and by adding dy to fTop, fBottom.
+
+ If dx is negative, moves SkIRect returned to the left.
+ If dx is positive, moves SkIRect returned to the right.
+ If dy is negative, moves SkIRect returned upward.
+ If dy is positive, moves SkIRect returned downward.
+
+ @param dx offset added to fLeft and fRight
+ @param dy offset added to fTop and fBottom
+ */
+ void offset(int32_t dx, int32_t dy) {
+ fLeft = Sk32_sat_add(fLeft, dx);
+ fTop = Sk32_sat_add(fTop, dy);
+ fRight = Sk32_sat_add(fRight, dx);
+ fBottom = Sk32_sat_add(fBottom, dy);
+ }
+
+ /** Offsets SkIRect by adding delta.fX to fLeft, fRight; and by adding delta.fY to
+ fTop, fBottom.
+
+ If delta.fX is negative, moves SkIRect returned to the left.
+ If delta.fX is positive, moves SkIRect returned to the right.
+ If delta.fY is negative, moves SkIRect returned upward.
+ If delta.fY is positive, moves SkIRect returned downward.
+
+ @param delta offset added to SkIRect
+ */
+ void offset(const SkIPoint& delta) {
+ this->offset(delta.fX, delta.fY);
+ }
+
+ /** Offsets SkIRect so that fLeft equals newX, and fTop equals newY. width and height
+ are unchanged.
+
+ @param newX stored in fLeft, preserving width()
+ @param newY stored in fTop, preserving height()
+ */
+ void offsetTo(int32_t newX, int32_t newY) {
+ fRight = Sk64_pin_to_s32((int64_t)fRight + newX - fLeft);
+ fBottom = Sk64_pin_to_s32((int64_t)fBottom + newY - fTop);
+ fLeft = newX;
+ fTop = newY;
+ }
+
+ /** Insets SkIRect by (dx,dy).
+
+ If dx is positive, makes SkIRect narrower.
+ If dx is negative, makes SkIRect wider.
+ If dy is positive, makes SkIRect shorter.
+ If dy is negative, makes SkIRect taller.
+
+ @param dx offset added to fLeft and subtracted from fRight
+ @param dy offset added to fTop and subtracted from fBottom
+ */
+ void inset(int32_t dx, int32_t dy) {
+ fLeft = Sk32_sat_add(fLeft, dx);
+ fTop = Sk32_sat_add(fTop, dy);
+ fRight = Sk32_sat_sub(fRight, dx);
+ fBottom = Sk32_sat_sub(fBottom, dy);
+ }
+
+ /** Outsets SkIRect by (dx, dy).
+
+ If dx is positive, makes SkIRect wider.
+ If dx is negative, makes SkIRect narrower.
+ If dy is positive, makes SkIRect taller.
+ If dy is negative, makes SkIRect shorter.
+
+ @param dx subtracted to fLeft and added from fRight
+ @param dy subtracted to fTop and added from fBottom
+ */
+ void outset(int32_t dx, int32_t dy) { this->inset(-dx, -dy); }
+
+ /** Adjusts SkIRect by adding dL to fLeft, dT to fTop, dR to fRight, and dB to fBottom.
+
+ If dL is positive, narrows SkIRect on the left. If negative, widens it on the left.
+ If dT is positive, shrinks SkIRect on the top. If negative, lengthens it on the top.
+ If dR is positive, narrows SkIRect on the right. If negative, widens it on the right.
+ If dB is positive, shrinks SkIRect on the bottom. If negative, lengthens it on the bottom.
+
+ The resulting SkIRect is not checked for validity. Thus, if the resulting SkIRect left is
+ greater than right, the SkIRect will be considered empty. Call sort() after this call
+ if that is not the desired behavior.
+
+ @param dL offset added to fLeft
+ @param dT offset added to fTop
+ @param dR offset added to fRight
+ @param dB offset added to fBottom
+ */
+ void adjust(int32_t dL, int32_t dT, int32_t dR, int32_t dB) {
+ fLeft = Sk32_sat_add(fLeft, dL);
+ fTop = Sk32_sat_add(fTop, dT);
+ fRight = Sk32_sat_add(fRight, dR);
+ fBottom = Sk32_sat_add(fBottom, dB);
+ }
+
+ /** Returns true if: fLeft <= x < fRight && fTop <= y < fBottom.
+ Returns false if SkIRect is empty.
+
+ Considers input to describe constructed SkIRect: (x, y, x + 1, y + 1) and
+ returns true if constructed area is completely enclosed by SkIRect area.
+
+ @param x test SkIPoint x-coordinate
+ @param y test SkIPoint y-coordinate
+ @return true if (x, y) is inside SkIRect
+ */
+ bool contains(int32_t x, int32_t y) const {
+ return x >= fLeft && x < fRight && y >= fTop && y < fBottom;
+ }
+
+ /** Returns true if SkIRect contains r.
+ Returns false if SkIRect is empty or r is empty.
+
+ SkIRect contains r when SkIRect area completely includes r area.
+
+ @param r SkIRect contained
+ @return true if all sides of SkIRect are outside r
+ */
+ bool contains(const SkIRect& r) const {
+ return !r.isEmpty() && !this->isEmpty() && // check for empties
+ fLeft <= r.fLeft && fTop <= r.fTop &&
+ fRight >= r.fRight && fBottom >= r.fBottom;
+ }
+
+ /** Returns true if SkIRect contains r.
+ Returns false if SkIRect is empty or r is empty.
+
+ SkIRect contains r when SkIRect area completely includes r area.
+
+ @param r SkRect contained
+ @return true if all sides of SkIRect are outside r
+ */
+ inline bool contains(const SkRect& r) const;
+
+ /** Returns true if SkIRect contains construction.
+ Asserts if SkIRect is empty or construction is empty, and if SK_DEBUG is defined.
+
+ Return is undefined if SkIRect is empty or construction is empty.
+
+ @param r SkIRect contained
+ @return true if all sides of SkIRect are outside r
+ */
+ bool containsNoEmptyCheck(const SkIRect& r) const {
+ SkASSERT(fLeft < fRight && fTop < fBottom);
+ SkASSERT(r.fLeft < r.fRight && r.fTop < r.fBottom);
+ return fLeft <= r.fLeft && fTop <= r.fTop && fRight >= r.fRight && fBottom >= r.fBottom;
+ }
+
+ /** Returns true if SkIRect intersects r, and sets SkIRect to intersection.
+ Returns false if SkIRect does not intersect r, and leaves SkIRect unchanged.
+
+ Returns false if either r or SkIRect is empty, leaving SkIRect unchanged.
+
+ @param r limit of result
+ @return true if r and SkIRect have area in common
+ */
+ bool intersect(const SkIRect& r) {
+ return this->intersect(*this, r);
+ }
+
+ /** Returns true if a intersects b, and sets SkIRect to intersection.
+ Returns false if a does not intersect b, and leaves SkIRect unchanged.
+
+ Returns false if either a or b is empty, leaving SkIRect unchanged.
+
+ @param a SkIRect to intersect
+ @param b SkIRect to intersect
+ @return true if a and b have area in common
+ */
+ bool SK_WARN_UNUSED_RESULT intersect(const SkIRect& a, const SkIRect& b);
+
+ /** Returns true if a intersects b.
+ Returns false if either a or b is empty, or do not intersect.
+
+ @param a SkIRect to intersect
+ @param b SkIRect to intersect
+ @return true if a and b have area in common
+ */
+ static bool Intersects(const SkIRect& a, const SkIRect& b) {
+ return SkIRect{}.intersect(a, b);
+ }
+
+ /** Sets SkIRect to the union of itself and r.
+
+ Has no effect if r is empty. Otherwise, if SkIRect is empty, sets SkIRect to r.
+
+ @param r expansion SkIRect
+
+ example: https://fiddle.skia.org/c/@IRect_join_2
+ */
+ void join(const SkIRect& r);
+
+ /** Swaps fLeft and fRight if fLeft is greater than fRight; and swaps
+ fTop and fBottom if fTop is greater than fBottom. Result may be empty,
+ and width() and height() will be zero or positive.
+ */
+ void sort() {
+ using std::swap;
+ if (fLeft > fRight) {
+ swap(fLeft, fRight);
+ }
+ if (fTop > fBottom) {
+ swap(fTop, fBottom);
+ }
+ }
+
+ /** Returns SkIRect with fLeft and fRight swapped if fLeft is greater than fRight; and
+ with fTop and fBottom swapped if fTop is greater than fBottom. Result may be empty;
+ and width() and height() will be zero or positive.
+
+ @return sorted SkIRect
+ */
+ SkIRect makeSorted() const {
+ return MakeLTRB(std::min(fLeft, fRight), std::min(fTop, fBottom),
+ std::max(fLeft, fRight), std::max(fTop, fBottom));
+ }
+};
+
+/** \struct SkRect
+ SkRect holds four SkScalar coordinates describing the upper and
+ lower bounds of a rectangle. SkRect may be created from outer bounds or
+ from position, width, and height. SkRect describes an area; if its right
+ is less than or equal to its left, or if its bottom is less than or equal to
+ its top, it is considered empty.
+*/
+struct SK_API SkRect {
+ SkScalar fLeft; //!< smaller x-axis bounds
+ SkScalar fTop; //!< smaller y-axis bounds
+ SkScalar fRight; //!< larger x-axis bounds
+ SkScalar fBottom; //!< larger y-axis bounds
+
+ /** Returns constructed SkRect set to (0, 0, 0, 0).
+ Many other rectangles are empty; if left is equal to or greater than right,
+ or if top is equal to or greater than bottom. Setting all members to zero
+ is a convenience, but does not designate a special empty rectangle.
+
+ @return bounds (0, 0, 0, 0)
+ */
+ static constexpr SkRect SK_WARN_UNUSED_RESULT MakeEmpty() {
+ return SkRect{0, 0, 0, 0};
+ }
+
+ /** Returns constructed SkRect set to SkScalar values (0, 0, w, h). Does not
+ validate input; w or h may be negative.
+
+ Passing integer values may generate a compiler warning since SkRect cannot
+ represent 32-bit integers exactly. Use SkIRect for an exact integer rectangle.
+
+ @param w SkScalar width of constructed SkRect
+ @param h SkScalar height of constructed SkRect
+ @return bounds (0, 0, w, h)
+ */
+ static constexpr SkRect SK_WARN_UNUSED_RESULT MakeWH(SkScalar w, SkScalar h) {
+ return SkRect{0, 0, w, h};
+ }
+
+ /** Returns constructed SkRect set to integer values (0, 0, w, h). Does not validate
+ input; w or h may be negative.
+
+ Use to avoid a compiler warning that input may lose precision when stored.
+ Use SkIRect for an exact integer rectangle.
+
+ @param w integer width of constructed SkRect
+ @param h integer height of constructed SkRect
+ @return bounds (0, 0, w, h)
+ */
+ static SkRect SK_WARN_UNUSED_RESULT MakeIWH(int w, int h) {
+ return {0, 0, SkIntToScalar(w), SkIntToScalar(h)};
+ }
+
+ /** Returns constructed SkRect set to (0, 0, size.width(), size.height()). Does not
+ validate input; size.width() or size.height() may be negative.
+
+ @param size SkScalar values for SkRect width and height
+ @return bounds (0, 0, size.width(), size.height())
+ */
+ static constexpr SkRect SK_WARN_UNUSED_RESULT MakeSize(const SkSize& size) {
+ return SkRect{0, 0, size.fWidth, size.fHeight};
+ }
+
+ /** Returns constructed SkRect set to (l, t, r, b). Does not sort input; SkRect may
+ result in fLeft greater than fRight, or fTop greater than fBottom.
+
+ @param l SkScalar stored in fLeft
+ @param t SkScalar stored in fTop
+ @param r SkScalar stored in fRight
+ @param b SkScalar stored in fBottom
+ @return bounds (l, t, r, b)
+ */
+ static constexpr SkRect SK_WARN_UNUSED_RESULT MakeLTRB(SkScalar l, SkScalar t, SkScalar r,
+ SkScalar b) {
+ return SkRect {l, t, r, b};
+ }
+
+ /** Returns constructed SkRect set to (x, y, x + w, y + h).
+ Does not validate input; w or h may be negative.
+
+ @param x stored in fLeft
+ @param y stored in fTop
+ @param w added to x and stored in fRight
+ @param h added to y and stored in fBottom
+ @return bounds at (x, y) with width w and height h
+ */
+ static constexpr SkRect SK_WARN_UNUSED_RESULT MakeXYWH(SkScalar x, SkScalar y, SkScalar w,
+ SkScalar h) {
+ return SkRect {x, y, x + w, y + h};
+ }
+
+ /** Returns constructed SkIRect set to (0, 0, size.width(), size.height()).
+ Does not validate input; size.width() or size.height() may be negative.
+
+ @param size integer values for SkRect width and height
+ @return bounds (0, 0, size.width(), size.height())
+ */
+ static SkRect Make(const SkISize& size) {
+ return MakeIWH(size.width(), size.height());
+ }
+
+ /** Returns constructed SkIRect set to irect, promoting integers to scalar.
+ Does not validate input; fLeft may be greater than fRight, fTop may be greater
+ than fBottom.
+
+ @param irect integer unsorted bounds
+ @return irect members converted to SkScalar
+ */
+ static SkRect SK_WARN_UNUSED_RESULT Make(const SkIRect& irect) {
+ return {
+ SkIntToScalar(irect.fLeft), SkIntToScalar(irect.fTop),
+ SkIntToScalar(irect.fRight), SkIntToScalar(irect.fBottom)
+ };
+ }
+
+ /** Returns true if fLeft is equal to or greater than fRight, or if fTop is equal
+ to or greater than fBottom. Call sort() to reverse rectangles with negative
+ width() or height().
+
+ @return true if width() or height() are zero or negative
+ */
+ bool isEmpty() const {
+ // We write it as the NOT of a non-empty rect, so we will return true if any values
+ // are NaN.
+ return !(fLeft < fRight && fTop < fBottom);
+ }
+
+ /** Returns true if fLeft is equal to or less than fRight, or if fTop is equal
+ to or less than fBottom. Call sort() to reverse rectangles with negative
+ width() or height().
+
+ @return true if width() or height() are zero or positive
+ */
+ bool isSorted() const { return fLeft <= fRight && fTop <= fBottom; }
+
+ /** Returns true if all values in the rectangle are finite: SK_ScalarMin or larger,
+ and SK_ScalarMax or smaller.
+
+ @return true if no member is infinite or NaN
+ */
+ bool isFinite() const {
+ float accum = 0;
+ accum *= fLeft;
+ accum *= fTop;
+ accum *= fRight;
+ accum *= fBottom;
+
+ // accum is either NaN or it is finite (zero).
+ SkASSERT(0 == accum || SkScalarIsNaN(accum));
+
+ // value==value will be true iff value is not NaN
+ // TODO: is it faster to say !accum or accum==accum?
+ return !SkScalarIsNaN(accum);
+ }
+
+ /** Returns left edge of SkRect, if sorted. Call isSorted() to see if SkRect is valid.
+ Call sort() to reverse fLeft and fRight if needed.
+
+ @return fLeft
+ */
+ constexpr SkScalar x() const { return fLeft; }
+
+ /** Returns top edge of SkRect, if sorted. Call isEmpty() to see if SkRect may be invalid,
+ and sort() to reverse fTop and fBottom if needed.
+
+ @return fTop
+ */
+ constexpr SkScalar y() const { return fTop; }
+
+ /** Returns left edge of SkRect, if sorted. Call isSorted() to see if SkRect is valid.
+ Call sort() to reverse fLeft and fRight if needed.
+
+ @return fLeft
+ */
+ constexpr SkScalar left() const { return fLeft; }
+
+ /** Returns top edge of SkRect, if sorted. Call isEmpty() to see if SkRect may be invalid,
+ and sort() to reverse fTop and fBottom if needed.
+
+ @return fTop
+ */
+ constexpr SkScalar top() const { return fTop; }
+
+ /** Returns right edge of SkRect, if sorted. Call isSorted() to see if SkRect is valid.
+ Call sort() to reverse fLeft and fRight if needed.
+
+ @return fRight
+ */
+ constexpr SkScalar right() const { return fRight; }
+
+ /** Returns bottom edge of SkRect, if sorted. Call isEmpty() to see if SkRect may be invalid,
+ and sort() to reverse fTop and fBottom if needed.
+
+ @return fBottom
+ */
+ constexpr SkScalar bottom() const { return fBottom; }
+
+ /** Returns span on the x-axis. This does not check if SkRect is sorted, or if
+ result fits in 32-bit float; result may be negative or infinity.
+
+ @return fRight minus fLeft
+ */
+ constexpr SkScalar width() const { return fRight - fLeft; }
+
+ /** Returns span on the y-axis. This does not check if SkRect is sorted, or if
+ result fits in 32-bit float; result may be negative or infinity.
+
+ @return fBottom minus fTop
+ */
+ constexpr SkScalar height() const { return fBottom - fTop; }
+
+ /** Returns average of left edge and right edge. Result does not change if SkRect
+ is sorted. Result may overflow to infinity if SkRect is far from the origin.
+
+ @return midpoint on x-axis
+ */
+ SkScalar centerX() const {
+ // don't use SkScalarHalf(fLeft + fBottom) as that might overflow before the 0.5
+ return SkScalarHalf(fLeft) + SkScalarHalf(fRight);
+ }
+
+ /** Returns average of top edge and bottom edge. Result does not change if SkRect
+ is sorted.
+
+ @return midpoint on y-axis
+ */
+ SkScalar centerY() const {
+ // don't use SkScalarHalf(fTop + fBottom) as that might overflow before the 0.5
+ return SkScalarHalf(fTop) + SkScalarHalf(fBottom);
+ }
+
+ /** Returns true if all members in a: fLeft, fTop, fRight, and fBottom; are
+ equal to the corresponding members in b.
+
+ a and b are not equal if either contain NaN. a and b are equal if members
+ contain zeroes with different signs.
+
+ @param a SkRect to compare
+ @param b SkRect to compare
+ @return true if members are equal
+ */
+ friend bool operator==(const SkRect& a, const SkRect& b) {
+ return SkScalarsEqual((const SkScalar*)&a, (const SkScalar*)&b, 4);
+ }
+
+ /** Returns true if any in a: fLeft, fTop, fRight, and fBottom; does not
+ equal the corresponding members in b.
+
+ a and b are not equal if either contain NaN. a and b are equal if members
+ contain zeroes with different signs.
+
+ @param a SkRect to compare
+ @param b SkRect to compare
+ @return true if members are not equal
+ */
+ friend bool operator!=(const SkRect& a, const SkRect& b) {
+ return !SkScalarsEqual((const SkScalar*)&a, (const SkScalar*)&b, 4);
+ }
+
+ /** Returns four points in quad that enclose SkRect ordered as: top-left, top-right,
+ bottom-right, bottom-left.
+
+ TODO: Consider adding parameter to control whether quad is clockwise or counterclockwise.
+
+ @param quad storage for corners of SkRect
+
+ example: https://fiddle.skia.org/c/@Rect_toQuad
+ */
+ void toQuad(SkPoint quad[4]) const;
+
+ /** Sets SkRect to (0, 0, 0, 0).
+
+ Many other rectangles are empty; if left is equal to or greater than right,
+ or if top is equal to or greater than bottom. Setting all members to zero
+ is a convenience, but does not designate a special empty rectangle.
+ */
+ void setEmpty() { *this = MakeEmpty(); }
+
+ /** Sets SkRect to src, promoting src members from integer to scalar.
+ Very large values in src may lose precision.
+
+ @param src integer SkRect
+ */
+ void set(const SkIRect& src) {
+ fLeft = SkIntToScalar(src.fLeft);
+ fTop = SkIntToScalar(src.fTop);
+ fRight = SkIntToScalar(src.fRight);
+ fBottom = SkIntToScalar(src.fBottom);
+ }
+
+ /** Sets SkRect to (left, top, right, bottom).
+ left and right are not sorted; left is not necessarily less than right.
+ top and bottom are not sorted; top is not necessarily less than bottom.
+
+ @param left stored in fLeft
+ @param top stored in fTop
+ @param right stored in fRight
+ @param bottom stored in fBottom
+ */
+ void setLTRB(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom) {
+ fLeft = left;
+ fTop = top;
+ fRight = right;
+ fBottom = bottom;
+ }
+
+ /** Sets to bounds of SkPoint array with count entries. If count is zero or smaller,
+ or if SkPoint array contains an infinity or NaN, sets to (0, 0, 0, 0).
+
+ Result is either empty or sorted: fLeft is less than or equal to fRight, and
+ fTop is less than or equal to fBottom.
+
+ @param pts SkPoint array
+ @param count entries in array
+ */
+ void setBounds(const SkPoint pts[], int count) {
+ (void)this->setBoundsCheck(pts, count);
+ }
+
+ /** Sets to bounds of SkPoint array with count entries. Returns false if count is
+ zero or smaller, or if SkPoint array contains an infinity or NaN; in these cases
+ sets SkRect to (0, 0, 0, 0).
+
+ Result is either empty or sorted: fLeft is less than or equal to fRight, and
+ fTop is less than or equal to fBottom.
+
+ @param pts SkPoint array
+ @param count entries in array
+ @return true if all SkPoint values are finite
+
+ example: https://fiddle.skia.org/c/@Rect_setBoundsCheck
+ */
+ bool setBoundsCheck(const SkPoint pts[], int count);
+
+ /** Sets to bounds of SkPoint pts array with count entries. If any SkPoint in pts
+ contains infinity or NaN, all SkRect dimensions are set to NaN.
+
+ @param pts SkPoint array
+ @param count entries in array
+
+ example: https://fiddle.skia.org/c/@Rect_setBoundsNoCheck
+ */
+ void setBoundsNoCheck(const SkPoint pts[], int count);
+
+ /** Sets bounds to the smallest SkRect enclosing SkPoint p0 and p1. The result is
+ sorted and may be empty. Does not check to see if values are finite.
+
+ @param p0 corner to include
+ @param p1 corner to include
+ */
+ void set(const SkPoint& p0, const SkPoint& p1) {
+ fLeft = std::min(p0.fX, p1.fX);
+ fRight = std::max(p0.fX, p1.fX);
+ fTop = std::min(p0.fY, p1.fY);
+ fBottom = std::max(p0.fY, p1.fY);
+ }
+
+ /** Sets SkRect to (x, y, x + width, y + height).
+ Does not validate input; width or height may be negative.
+
+ @param x stored in fLeft
+ @param y stored in fTop
+ @param width added to x and stored in fRight
+ @param height added to y and stored in fBottom
+ */
+ void setXYWH(SkScalar x, SkScalar y, SkScalar width, SkScalar height) {
+ fLeft = x;
+ fTop = y;
+ fRight = x + width;
+ fBottom = y + height;
+ }
+
+ /** Sets SkRect to (0, 0, width, height). Does not validate input;
+ width or height may be negative.
+
+ @param width stored in fRight
+ @param height stored in fBottom
+ */
+ void setWH(SkScalar width, SkScalar height) {
+ fLeft = 0;
+ fTop = 0;
+ fRight = width;
+ fBottom = height;
+ }
+ void setIWH(int32_t width, int32_t height) {
+ this->setWH(SkIntToScalar(width), SkIntToScalar(height));
+ }
+
+ /** Returns SkRect offset by (dx, dy).
+
+ If dx is negative, SkRect returned is moved to the left.
+ If dx is positive, SkRect returned is moved to the right.
+ If dy is negative, SkRect returned is moved upward.
+ If dy is positive, SkRect returned is moved downward.
+
+ @param dx added to fLeft and fRight
+ @param dy added to fTop and fBottom
+ @return SkRect offset on axes, with original width and height
+ */
+ constexpr SkRect makeOffset(SkScalar dx, SkScalar dy) const {
+ return MakeLTRB(fLeft + dx, fTop + dy, fRight + dx, fBottom + dy);
+ }
+
+ /** Returns SkRect offset by v.
+
+ @param v added to rect
+ @return SkRect offset on axes, with original width and height
+ */
+ constexpr SkRect makeOffset(SkVector v) const { return this->makeOffset(v.x(), v.y()); }
+
+ /** Returns SkRect, inset by (dx, dy).
+
+ If dx is negative, SkRect returned is wider.
+ If dx is positive, SkRect returned is narrower.
+ If dy is negative, SkRect returned is taller.
+ If dy is positive, SkRect returned is shorter.
+
+ @param dx added to fLeft and subtracted from fRight
+ @param dy added to fTop and subtracted from fBottom
+ @return SkRect inset symmetrically left and right, top and bottom
+ */
+ SkRect makeInset(SkScalar dx, SkScalar dy) const {
+ return MakeLTRB(fLeft + dx, fTop + dy, fRight - dx, fBottom - dy);
+ }
+
+ /** Returns SkRect, outset by (dx, dy).
+
+ If dx is negative, SkRect returned is narrower.
+ If dx is positive, SkRect returned is wider.
+ If dy is negative, SkRect returned is shorter.
+ If dy is positive, SkRect returned is taller.
+
+ @param dx subtracted to fLeft and added from fRight
+ @param dy subtracted to fTop and added from fBottom
+ @return SkRect outset symmetrically left and right, top and bottom
+ */
+ SkRect makeOutset(SkScalar dx, SkScalar dy) const {
+ return MakeLTRB(fLeft - dx, fTop - dy, fRight + dx, fBottom + dy);
+ }
+
+ /** Offsets SkRect by adding dx to fLeft, fRight; and by adding dy to fTop, fBottom.
+
+ If dx is negative, moves SkRect to the left.
+ If dx is positive, moves SkRect to the right.
+ If dy is negative, moves SkRect upward.
+ If dy is positive, moves SkRect downward.
+
+ @param dx offset added to fLeft and fRight
+ @param dy offset added to fTop and fBottom
+ */
+ void offset(SkScalar dx, SkScalar dy) {
+ fLeft += dx;
+ fTop += dy;
+ fRight += dx;
+ fBottom += dy;
+ }
+
+ /** Offsets SkRect by adding delta.fX to fLeft, fRight; and by adding delta.fY to
+ fTop, fBottom.
+
+ If delta.fX is negative, moves SkRect to the left.
+ If delta.fX is positive, moves SkRect to the right.
+ If delta.fY is negative, moves SkRect upward.
+ If delta.fY is positive, moves SkRect downward.
+
+ @param delta added to SkRect
+ */
+ void offset(const SkPoint& delta) {
+ this->offset(delta.fX, delta.fY);
+ }
+
+ /** Offsets SkRect so that fLeft equals newX, and fTop equals newY. width and height
+ are unchanged.
+
+ @param newX stored in fLeft, preserving width()
+ @param newY stored in fTop, preserving height()
+ */
+ void offsetTo(SkScalar newX, SkScalar newY) {
+ fRight += newX - fLeft;
+ fBottom += newY - fTop;
+ fLeft = newX;
+ fTop = newY;
+ }
+
+ /** Insets SkRect by (dx, dy).
+
+ If dx is positive, makes SkRect narrower.
+ If dx is negative, makes SkRect wider.
+ If dy is positive, makes SkRect shorter.
+ If dy is negative, makes SkRect taller.
+
+ @param dx added to fLeft and subtracted from fRight
+ @param dy added to fTop and subtracted from fBottom
+ */
+ void inset(SkScalar dx, SkScalar dy) {
+ fLeft += dx;
+ fTop += dy;
+ fRight -= dx;
+ fBottom -= dy;
+ }
+
+ /** Outsets SkRect by (dx, dy).
+
+ If dx is positive, makes SkRect wider.
+ If dx is negative, makes SkRect narrower.
+ If dy is positive, makes SkRect taller.
+ If dy is negative, makes SkRect shorter.
+
+ @param dx subtracted to fLeft and added from fRight
+ @param dy subtracted to fTop and added from fBottom
+ */
+ void outset(SkScalar dx, SkScalar dy) { this->inset(-dx, -dy); }
+
+ /** Returns true if SkRect intersects r, and sets SkRect to intersection.
+ Returns false if SkRect does not intersect r, and leaves SkRect unchanged.
+
+ Returns false if either r or SkRect is empty, leaving SkRect unchanged.
+
+ @param r limit of result
+ @return true if r and SkRect have area in common
+
+ example: https://fiddle.skia.org/c/@Rect_intersect
+ */
+ bool intersect(const SkRect& r);
+
+ /** Returns true if a intersects b, and sets SkRect to intersection.
+ Returns false if a does not intersect b, and leaves SkRect unchanged.
+
+ Returns false if either a or b is empty, leaving SkRect unchanged.
+
+ @param a SkRect to intersect
+ @param b SkRect to intersect
+ @return true if a and b have area in common
+ */
+ bool SK_WARN_UNUSED_RESULT intersect(const SkRect& a, const SkRect& b);
+
+
+private:
+ static bool Intersects(SkScalar al, SkScalar at, SkScalar ar, SkScalar ab,
+ SkScalar bl, SkScalar bt, SkScalar br, SkScalar bb) {
+ SkScalar L = std::max(al, bl);
+ SkScalar R = std::min(ar, br);
+ SkScalar T = std::max(at, bt);
+ SkScalar B = std::min(ab, bb);
+ return L < R && T < B;
+ }
+
+public:
+
+ /** Returns true if SkRect intersects r.
+ Returns false if either r or SkRect is empty, or do not intersect.
+
+ @param r SkRect to intersect
+ @return true if r and SkRect have area in common
+ */
+ bool intersects(const SkRect& r) const {
+ return Intersects(fLeft, fTop, fRight, fBottom,
+ r.fLeft, r.fTop, r.fRight, r.fBottom);
+ }
+
+ /** Returns true if a intersects b.
+ Returns false if either a or b is empty, or do not intersect.
+
+ @param a SkRect to intersect
+ @param b SkRect to intersect
+ @return true if a and b have area in common
+ */
+ static bool Intersects(const SkRect& a, const SkRect& b) {
+ return Intersects(a.fLeft, a.fTop, a.fRight, a.fBottom,
+ b.fLeft, b.fTop, b.fRight, b.fBottom);
+ }
+
+ /** Sets SkRect to the union of itself and r.
+
+ Has no effect if r is empty. Otherwise, if SkRect is empty, sets
+ SkRect to r.
+
+ @param r expansion SkRect
+
+ example: https://fiddle.skia.org/c/@Rect_join_2
+ */
+ void join(const SkRect& r);
+
+ /** Sets SkRect to the union of itself and r.
+
+ Asserts if r is empty and SK_DEBUG is defined.
+ If SkRect is empty, sets SkRect to r.
+
+ May produce incorrect results if r is empty.
+
+ @param r expansion SkRect
+ */
+ void joinNonEmptyArg(const SkRect& r) {
+ SkASSERT(!r.isEmpty());
+ // if we are empty, just assign
+ if (fLeft >= fRight || fTop >= fBottom) {
+ *this = r;
+ } else {
+ this->joinPossiblyEmptyRect(r);
+ }
+ }
+
+ /** Sets SkRect to the union of itself and the construction.
+
+ May produce incorrect results if SkRect or r is empty.
+
+ @param r expansion SkRect
+ */
+ void joinPossiblyEmptyRect(const SkRect& r) {
+ fLeft = std::min(fLeft, r.left());
+ fTop = std::min(fTop, r.top());
+ fRight = std::max(fRight, r.right());
+ fBottom = std::max(fBottom, r.bottom());
+ }
+
+ /** Returns true if: fLeft <= x < fRight && fTop <= y < fBottom.
+ Returns false if SkRect is empty.
+
+ @param x test SkPoint x-coordinate
+ @param y test SkPoint y-coordinate
+ @return true if (x, y) is inside SkRect
+ */
+ bool contains(SkScalar x, SkScalar y) const {
+ return x >= fLeft && x < fRight && y >= fTop && y < fBottom;
+ }
+
+ /** Returns true if SkRect contains r.
+ Returns false if SkRect is empty or r is empty.
+
+ SkRect contains r when SkRect area completely includes r area.
+
+ @param r SkRect contained
+ @return true if all sides of SkRect are outside r
+ */
+ bool contains(const SkRect& r) const {
+ // todo: can we eliminate the this->isEmpty check?
+ return !r.isEmpty() && !this->isEmpty() &&
+ fLeft <= r.fLeft && fTop <= r.fTop &&
+ fRight >= r.fRight && fBottom >= r.fBottom;
+ }
+
+ /** Returns true if SkRect contains r.
+ Returns false if SkRect is empty or r is empty.
+
+ SkRect contains r when SkRect area completely includes r area.
+
+ @param r SkIRect contained
+ @return true if all sides of SkRect are outside r
+ */
+ bool contains(const SkIRect& r) const {
+ // todo: can we eliminate the this->isEmpty check?
+ return !r.isEmpty() && !this->isEmpty() &&
+ fLeft <= SkIntToScalar(r.fLeft) && fTop <= SkIntToScalar(r.fTop) &&
+ fRight >= SkIntToScalar(r.fRight) && fBottom >= SkIntToScalar(r.fBottom);
+ }
+
+ /** Sets SkIRect by adding 0.5 and discarding the fractional portion of SkRect
+ members, using (SkScalarRoundToInt(fLeft), SkScalarRoundToInt(fTop),
+ SkScalarRoundToInt(fRight), SkScalarRoundToInt(fBottom)).
+
+ @param dst storage for SkIRect
+ */
+ void round(SkIRect* dst) const {
+ SkASSERT(dst);
+ dst->setLTRB(SkScalarRoundToInt(fLeft), SkScalarRoundToInt(fTop),
+ SkScalarRoundToInt(fRight), SkScalarRoundToInt(fBottom));
+ }
+
+ /** Sets SkIRect by discarding the fractional portion of fLeft and fTop; and rounding
+ up fRight and fBottom, using
+ (SkScalarFloorToInt(fLeft), SkScalarFloorToInt(fTop),
+ SkScalarCeilToInt(fRight), SkScalarCeilToInt(fBottom)).
+
+ @param dst storage for SkIRect
+ */
+ void roundOut(SkIRect* dst) const {
+ SkASSERT(dst);
+ dst->setLTRB(SkScalarFloorToInt(fLeft), SkScalarFloorToInt(fTop),
+ SkScalarCeilToInt(fRight), SkScalarCeilToInt(fBottom));
+ }
+
+ /** Sets SkRect by discarding the fractional portion of fLeft and fTop; and rounding
+ up fRight and fBottom, using
+ (SkScalarFloorToInt(fLeft), SkScalarFloorToInt(fTop),
+ SkScalarCeilToInt(fRight), SkScalarCeilToInt(fBottom)).
+
+ @param dst storage for SkRect
+ */
+ void roundOut(SkRect* dst) const {
+ dst->setLTRB(SkScalarFloorToScalar(fLeft), SkScalarFloorToScalar(fTop),
+ SkScalarCeilToScalar(fRight), SkScalarCeilToScalar(fBottom));
+ }
+
+ /** Sets SkRect by rounding up fLeft and fTop; and discarding the fractional portion
+ of fRight and fBottom, using
+ (SkScalarCeilToInt(fLeft), SkScalarCeilToInt(fTop),
+ SkScalarFloorToInt(fRight), SkScalarFloorToInt(fBottom)).
+
+ @param dst storage for SkIRect
+ */
+ void roundIn(SkIRect* dst) const {
+ SkASSERT(dst);
+ dst->setLTRB(SkScalarCeilToInt(fLeft), SkScalarCeilToInt(fTop),
+ SkScalarFloorToInt(fRight), SkScalarFloorToInt(fBottom));
+ }
+
+ /** Returns SkIRect by adding 0.5 and discarding the fractional portion of SkRect
+ members, using (SkScalarRoundToInt(fLeft), SkScalarRoundToInt(fTop),
+ SkScalarRoundToInt(fRight), SkScalarRoundToInt(fBottom)).
+
+ @return rounded SkIRect
+ */
+ SkIRect round() const {
+ SkIRect ir;
+ this->round(&ir);
+ return ir;
+ }
+
+ /** Sets SkIRect by discarding the fractional portion of fLeft and fTop; and rounding
+ up fRight and fBottom, using
+ (SkScalarFloorToInt(fLeft), SkScalarFloorToInt(fTop),
+ SkScalarCeilToInt(fRight), SkScalarCeilToInt(fBottom)).
+
+ @return rounded SkIRect
+ */
+ SkIRect roundOut() const {
+ SkIRect ir;
+ this->roundOut(&ir);
+ return ir;
+ }
+ /** Sets SkIRect by rounding up fLeft and fTop; and discarding the fractional portion
+ of fRight and fBottom, using
+ (SkScalarCeilToInt(fLeft), SkScalarCeilToInt(fTop),
+ SkScalarFloorToInt(fRight), SkScalarFloorToInt(fBottom)).
+
+ @return rounded SkIRect
+ */
+ SkIRect roundIn() const {
+ SkIRect ir;
+ this->roundIn(&ir);
+ return ir;
+ }
+
+ /** Swaps fLeft and fRight if fLeft is greater than fRight; and swaps
+ fTop and fBottom if fTop is greater than fBottom. Result may be empty;
+ and width() and height() will be zero or positive.
+ */
+ void sort() {
+ using std::swap;
+ if (fLeft > fRight) {
+ swap(fLeft, fRight);
+ }
+
+ if (fTop > fBottom) {
+ swap(fTop, fBottom);
+ }
+ }
+
+ /** Returns SkRect with fLeft and fRight swapped if fLeft is greater than fRight; and
+ with fTop and fBottom swapped if fTop is greater than fBottom. Result may be empty;
+ and width() and height() will be zero or positive.
+
+ @return sorted SkRect
+ */
+ SkRect makeSorted() const {
+ return MakeLTRB(std::min(fLeft, fRight), std::min(fTop, fBottom),
+ std::max(fLeft, fRight), std::max(fTop, fBottom));
+ }
+
+ /** Returns pointer to first scalar in SkRect, to treat it as an array with four
+ entries.
+
+ @return pointer to fLeft
+ */
+ const SkScalar* asScalars() const { return &fLeft; }
+
+ /** Writes text representation of SkRect to standard output. Set asHex to true to
+ generate exact binary representations of floating point numbers.
+
+ @param asHex true if SkScalar values are written as hexadecimal
+
+ example: https://fiddle.skia.org/c/@Rect_dump
+ */
+ void dump(bool asHex) const;
+
+ /** Writes text representation of SkRect to standard output. The representation may be
+ directly compiled as C++ code. Floating point values are written
+ with limited precision; it may not be possible to reconstruct original SkRect
+ from output.
+ */
+ void dump() const { this->dump(false); }
+
+ /** Writes text representation of SkRect to standard output. The representation may be
+ directly compiled as C++ code. Floating point values are written
+ in hexadecimal to preserve their exact bit pattern. The output reconstructs the
+ original SkRect.
+
+ Use instead of dump() when submitting
+ */
+ void dumpHex() const { this->dump(true); }
+};
+
+inline bool SkIRect::contains(const SkRect& r) const {
+ return !r.isEmpty() && !this->isEmpty() && // check for empties
+ (SkScalar)fLeft <= r.fLeft && (SkScalar)fTop <= r.fTop &&
+ (SkScalar)fRight >= r.fRight && (SkScalar)fBottom >= r.fBottom;
+}
+
+#endif
diff --git a/src/deps/skia/include/core/SkRefCnt.h b/src/deps/skia/include/core/SkRefCnt.h
new file mode 100644
index 000000000..bcb75d769
--- /dev/null
+++ b/src/deps/skia/include/core/SkRefCnt.h
@@ -0,0 +1,382 @@
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkRefCnt_DEFINED
+#define SkRefCnt_DEFINED
+
+#include "include/core/SkTypes.h"
+
+#include <atomic> // std::atomic, std::memory_order_*
+#include <cstddef> // std::nullptr_t
+#include <iosfwd> // std::basic_ostream
+#include <memory> // TODO: unused
+#include <type_traits> // std::enable_if, std::is_convertible
+#include <utility> // std::forward, std::swap
+
+/** \class SkRefCntBase
+
+ SkRefCntBase is the base class for objects that may be shared by multiple
+ objects. When an existing owner wants to share a reference, it calls ref().
+ When an owner wants to release its reference, it calls unref(). When the
+ shared object's reference count goes to zero as the result of an unref()
+ call, its (virtual) destructor is called. It is an error for the
+ destructor to be called explicitly (or via the object going out of scope on
+ the stack or calling delete) if getRefCnt() > 1.
+*/
+class SK_API SkRefCntBase {
+public:
+ /** Default construct, initializing the reference count to 1.
+ */
+ SkRefCntBase() : fRefCnt(1) {}
+
+ /** Destruct, asserting that the reference count is 1.
+ */
+ virtual ~SkRefCntBase() {
+ #ifdef SK_DEBUG
+ SkASSERTF(this->getRefCnt() == 1, "fRefCnt was %d", this->getRefCnt());
+ // illegal value, to catch us if we reuse after delete
+ fRefCnt.store(0, std::memory_order_relaxed);
+ #endif
+ }
+
+ /** May return true if the caller is the only owner.
+ * Ensures that all previous owner's actions are complete.
+ */
+ bool unique() const {
+ if (1 == fRefCnt.load(std::memory_order_acquire)) {
+ // The acquire barrier is only really needed if we return true. It
+ // prevents code conditioned on the result of unique() from running
+ // until previous owners are all totally done calling unref().
+ return true;
+ }
+ return false;
+ }
+
+ /** Increment the reference count. Must be balanced by a call to unref().
+ */
+ void ref() const {
+ SkASSERT(this->getRefCnt() > 0);
+ // No barrier required.
+ (void)fRefCnt.fetch_add(+1, std::memory_order_relaxed);
+ }
+
+ /** Decrement the reference count. If the reference count is 1 before the
+ decrement, then delete the object. Note that if this is the case, then
+ the object needs to have been allocated via new, and not on the stack.
+ */
+ void unref() const {
+ SkASSERT(this->getRefCnt() > 0);
+ // A release here acts in place of all releases we "should" have been doing in ref().
+ if (1 == fRefCnt.fetch_add(-1, std::memory_order_acq_rel)) {
+ // Like unique(), the acquire is only needed on success, to make sure
+ // code in internal_dispose() doesn't happen before the decrement.
+ this->internal_dispose();
+ }
+ }
+
+private:
+
+#ifdef SK_DEBUG
+ /** Return the reference count. Use only for debugging. */
+ int32_t getRefCnt() const {
+ return fRefCnt.load(std::memory_order_relaxed);
+ }
+#endif
+
+ /**
+ * Called when the ref count goes to 0.
+ */
+ virtual void internal_dispose() const {
+ #ifdef SK_DEBUG
+ SkASSERT(0 == this->getRefCnt());
+ fRefCnt.store(1, std::memory_order_relaxed);
+ #endif
+ delete this;
+ }
+
+ // The following friends are those which override internal_dispose()
+ // and conditionally call SkRefCnt::internal_dispose().
+ friend class SkWeakRefCnt;
+
+ mutable std::atomic<int32_t> fRefCnt;
+
+ SkRefCntBase(SkRefCntBase&&) = delete;
+ SkRefCntBase(const SkRefCntBase&) = delete;
+ SkRefCntBase& operator=(SkRefCntBase&&) = delete;
+ SkRefCntBase& operator=(const SkRefCntBase&) = delete;
+};
+
+#ifdef SK_REF_CNT_MIXIN_INCLUDE
+// It is the responsibility of the following include to define the type SkRefCnt.
+// This SkRefCnt should normally derive from SkRefCntBase.
+#include SK_REF_CNT_MIXIN_INCLUDE
+#else
+class SK_API SkRefCnt : public SkRefCntBase {
+ // "#include SK_REF_CNT_MIXIN_INCLUDE" doesn't work with this build system.
+ #if defined(SK_BUILD_FOR_GOOGLE3)
+ public:
+ void deref() const { this->unref(); }
+ #endif
+};
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+
+/** Call obj->ref() and return obj. The obj must not be nullptr.
+ */
+template <typename T> static inline T* SkRef(T* obj) {
+ SkASSERT(obj);
+ obj->ref();
+ return obj;
+}
+
+/** Check if the argument is non-null, and if so, call obj->ref() and return obj.
+ */
+template <typename T> static inline T* SkSafeRef(T* obj) {
+ if (obj) {
+ obj->ref();
+ }
+ return obj;
+}
+
+/** Check if the argument is non-null, and if so, call obj->unref()
+ */
+template <typename T> static inline void SkSafeUnref(T* obj) {
+ if (obj) {
+ obj->unref();
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+// This is a variant of SkRefCnt that's Not Virtual, so weighs 4 bytes instead of 8 or 16.
+// There's only benefit to using this if the deriving class does not otherwise need a vtable.
+template <typename Derived>
+class SkNVRefCnt {
+public:
+ SkNVRefCnt() : fRefCnt(1) {}
+ ~SkNVRefCnt() {
+ #ifdef SK_DEBUG
+ int rc = fRefCnt.load(std::memory_order_relaxed);
+ SkASSERTF(rc == 1, "NVRefCnt was %d", rc);
+ #endif
+ }
+
+ // Implementation is pretty much the same as SkRefCntBase. All required barriers are the same:
+ // - unique() needs acquire when it returns true, and no barrier if it returns false;
+ // - ref() doesn't need any barrier;
+ // - unref() needs a release barrier, and an acquire if it's going to call delete.
+
+ bool unique() const { return 1 == fRefCnt.load(std::memory_order_acquire); }
+ void ref() const { (void)fRefCnt.fetch_add(+1, std::memory_order_relaxed); }
+ void unref() const {
+ if (1 == fRefCnt.fetch_add(-1, std::memory_order_acq_rel)) {
+ // restore the 1 for our destructor's assert
+ SkDEBUGCODE(fRefCnt.store(1, std::memory_order_relaxed));
+ delete (const Derived*)this;
+ }
+ }
+ void deref() const { this->unref(); }
+
+ // This must be used with caution. It is only valid to call this when 'threadIsolatedTestCnt'
+ // refs are known to be isolated to the current thread. That is, it is known that there are at
+ // least 'threadIsolatedTestCnt' refs for which no other thread may make a balancing unref()
+ // call. Assuming the contract is followed, if this returns false then no other thread has
+ // ownership of this. If it returns true then another thread *may* have ownership.
+ bool refCntGreaterThan(int32_t threadIsolatedTestCnt) const {
+ int cnt = fRefCnt.load(std::memory_order_acquire);
+ // If this fails then the above contract has been violated.
+ SkASSERT(cnt >= threadIsolatedTestCnt);
+ return cnt > threadIsolatedTestCnt;
+ }
+
+private:
+ mutable std::atomic<int32_t> fRefCnt;
+
+ SkNVRefCnt(SkNVRefCnt&&) = delete;
+ SkNVRefCnt(const SkNVRefCnt&) = delete;
+ SkNVRefCnt& operator=(SkNVRefCnt&&) = delete;
+ SkNVRefCnt& operator=(const SkNVRefCnt&) = delete;
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * Shared pointer class to wrap classes that support a ref()/unref() interface.
+ *
+ * This can be used for classes inheriting from SkRefCnt, but it also works for other
+ * classes that match the interface, but have different internal choices: e.g. the hosted class
+ * may have its ref/unref be thread-safe, but that is not assumed/imposed by sk_sp.
+ */
+template <typename T> class sk_sp {
+public:
+ using element_type = T;
+
+ constexpr sk_sp() : fPtr(nullptr) {}
+ constexpr sk_sp(std::nullptr_t) : fPtr(nullptr) {}
+
+ /**
+ * Shares the underlying object by calling ref(), so that both the argument and the newly
+ * created sk_sp both have a reference to it.
+ */
+ sk_sp(const sk_sp<T>& that) : fPtr(SkSafeRef(that.get())) {}
+ template <typename U,
+ typename = typename std::enable_if<std::is_convertible<U*, T*>::value>::type>
+ sk_sp(const sk_sp<U>& that) : fPtr(SkSafeRef(that.get())) {}
+
+ /**
+ * Move the underlying object from the argument to the newly created sk_sp. Afterwards only
+ * the new sk_sp will have a reference to the object, and the argument will point to null.
+ * No call to ref() or unref() will be made.
+ */
+ sk_sp(sk_sp<T>&& that) : fPtr(that.release()) {}
+ template <typename U,
+ typename = typename std::enable_if<std::is_convertible<U*, T*>::value>::type>
+ sk_sp(sk_sp<U>&& that) : fPtr(that.release()) {}
+
+ /**
+ * Adopt the bare pointer into the newly created sk_sp.
+ * No call to ref() or unref() will be made.
+ */
+ explicit sk_sp(T* obj) : fPtr(obj) {}
+
+ /**
+ * Calls unref() on the underlying object pointer.
+ */
+ ~sk_sp() {
+ SkSafeUnref(fPtr);
+ SkDEBUGCODE(fPtr = nullptr);
+ }
+
+ sk_sp<T>& operator=(std::nullptr_t) { this->reset(); return *this; }
+
+ /**
+ * Shares the underlying object referenced by the argument by calling ref() on it. If this
+ * sk_sp previously had a reference to an object (i.e. not null) it will call unref() on that
+ * object.
+ */
+ sk_sp<T>& operator=(const sk_sp<T>& that) {
+ if (this != &that) {
+ this->reset(SkSafeRef(that.get()));
+ }
+ return *this;
+ }
+ template <typename U,
+ typename = typename std::enable_if<std::is_convertible<U*, T*>::value>::type>
+ sk_sp<T>& operator=(const sk_sp<U>& that) {
+ this->reset(SkSafeRef(that.get()));
+ return *this;
+ }
+
+ /**
+ * Move the underlying object from the argument to the sk_sp. If the sk_sp previously held
+ * a reference to another object, unref() will be called on that object. No call to ref()
+ * will be made.
+ */
+ sk_sp<T>& operator=(sk_sp<T>&& that) {
+ this->reset(that.release());
+ return *this;
+ }
+ template <typename U,
+ typename = typename std::enable_if<std::is_convertible<U*, T*>::value>::type>
+ sk_sp<T>& operator=(sk_sp<U>&& that) {
+ this->reset(that.release());
+ return *this;
+ }
+
+ T& operator*() const {
+ SkASSERT(this->get() != nullptr);
+ return *this->get();
+ }
+
+ explicit operator bool() const { return this->get() != nullptr; }
+
+ T* get() const { return fPtr; }
+ T* operator->() const { return fPtr; }
+
+ /**
+ * Adopt the new bare pointer, and call unref() on any previously held object (if not null).
+ * No call to ref() will be made.
+ */
+ void reset(T* ptr = nullptr) {
+ // Calling fPtr->unref() may call this->~() or this->reset(T*).
+ // http://wg21.cmeerw.net/lwg/issue998
+ // http://wg21.cmeerw.net/lwg/issue2262
+ T* oldPtr = fPtr;
+ fPtr = ptr;
+ SkSafeUnref(oldPtr);
+ }
+
+ /**
+ * Return the bare pointer, and set the internal object pointer to nullptr.
+ * The caller must assume ownership of the object, and manage its reference count directly.
+ * No call to unref() will be made.
+ */
+ T* SK_WARN_UNUSED_RESULT release() {
+ T* ptr = fPtr;
+ fPtr = nullptr;
+ return ptr;
+ }
+
+ void swap(sk_sp<T>& that) /*noexcept*/ {
+ using std::swap;
+ swap(fPtr, that.fPtr);
+ }
+
+private:
+ T* fPtr;
+};
+
+template <typename T> inline void swap(sk_sp<T>& a, sk_sp<T>& b) /*noexcept*/ {
+ a.swap(b);
+}
+
+template <typename T, typename U> inline bool operator==(const sk_sp<T>& a, const sk_sp<U>& b) {
+ return a.get() == b.get();
+}
+template <typename T> inline bool operator==(const sk_sp<T>& a, std::nullptr_t) /*noexcept*/ {
+ return !a;
+}
+template <typename T> inline bool operator==(std::nullptr_t, const sk_sp<T>& b) /*noexcept*/ {
+ return !b;
+}
+
+template <typename T, typename U> inline bool operator!=(const sk_sp<T>& a, const sk_sp<U>& b) {
+ return a.get() != b.get();
+}
+template <typename T> inline bool operator!=(const sk_sp<T>& a, std::nullptr_t) /*noexcept*/ {
+ return static_cast<bool>(a);
+}
+template <typename T> inline bool operator!=(std::nullptr_t, const sk_sp<T>& b) /*noexcept*/ {
+ return static_cast<bool>(b);
+}
+
+template <typename C, typename CT, typename T>
+auto operator<<(std::basic_ostream<C, CT>& os, const sk_sp<T>& sp) -> decltype(os << sp.get()) {
+ return os << sp.get();
+}
+
+template <typename T, typename... Args>
+sk_sp<T> sk_make_sp(Args&&... args) {
+ return sk_sp<T>(new T(std::forward<Args>(args)...));
+}
+
+/*
+ * Returns a sk_sp wrapping the provided ptr AND calls ref on it (if not null).
+ *
+ * This is different than the semantics of the constructor for sk_sp, which just wraps the ptr,
+ * effectively "adopting" it.
+ */
+template <typename T> sk_sp<T> sk_ref_sp(T* obj) {
+ return sk_sp<T>(SkSafeRef(obj));
+}
+
+template <typename T> sk_sp<T> sk_ref_sp(const T* obj) {
+ return sk_sp<T>(const_cast<T*>(SkSafeRef(obj)));
+}
+
+#endif
diff --git a/src/deps/skia/include/core/SkRegion.h b/src/deps/skia/include/core/SkRegion.h
new file mode 100644
index 000000000..ab326d98f
--- /dev/null
+++ b/src/deps/skia/include/core/SkRegion.h
@@ -0,0 +1,672 @@
+/*
+ * Copyright 2005 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkRegion_DEFINED
+#define SkRegion_DEFINED
+
+#include "include/core/SkRect.h"
+
+class SkPath;
+class SkRgnBuilder;
+
+/** \class SkRegion
+ SkRegion describes the set of pixels used to clip SkCanvas. SkRegion is compact,
+ efficiently storing a single integer rectangle, or a run length encoded array
+ of rectangles. SkRegion may reduce the current SkCanvas clip, or may be drawn as
+ one or more integer rectangles. SkRegion iterator returns the scan lines or
+ rectangles contained by it, optionally intersecting a bounding rectangle.
+*/
+class SK_API SkRegion {
+ typedef int32_t RunType;
+public:
+
+ /** Constructs an empty SkRegion. SkRegion is set to empty bounds
+ at (0, 0) with zero width and height.
+
+ @return empty SkRegion
+
+ example: https://fiddle.skia.org/c/@Region_empty_constructor
+ */
+ SkRegion();
+
+ /** Constructs a copy of an existing region.
+ Copy constructor makes two regions identical by value. Internally, region and
+ the returned result share pointer values. The underlying SkRect array is
+ copied when modified.
+
+ Creating a SkRegion copy is very efficient and never allocates memory.
+ SkRegion are always copied by value from the interface; the underlying shared
+ pointers are not exposed.
+
+ @param region SkRegion to copy by value
+ @return copy of SkRegion
+
+ example: https://fiddle.skia.org/c/@Region_copy_const_SkRegion
+ */
+ SkRegion(const SkRegion& region);
+
+ /** Constructs a rectangular SkRegion matching the bounds of rect.
+
+ @param rect bounds of constructed SkRegion
+ @return rectangular SkRegion
+
+ example: https://fiddle.skia.org/c/@Region_copy_const_SkIRect
+ */
+ explicit SkRegion(const SkIRect& rect);
+
+ /** Releases ownership of any shared data and deletes data if SkRegion is sole owner.
+
+ example: https://fiddle.skia.org/c/@Region_destructor
+ */
+ ~SkRegion();
+
+ /** Constructs a copy of an existing region.
+ Makes two regions identical by value. Internally, region and
+ the returned result share pointer values. The underlying SkRect array is
+ copied when modified.
+
+ Creating a SkRegion copy is very efficient and never allocates memory.
+ SkRegion are always copied by value from the interface; the underlying shared
+ pointers are not exposed.
+
+ @param region SkRegion to copy by value
+ @return SkRegion to copy by value
+
+ example: https://fiddle.skia.org/c/@Region_copy_operator
+ */
+ SkRegion& operator=(const SkRegion& region);
+
+ /** Compares SkRegion and other; returns true if they enclose exactly
+ the same area.
+
+ @param other SkRegion to compare
+ @return true if SkRegion pair are equivalent
+
+ example: https://fiddle.skia.org/c/@Region_equal1_operator
+ */
+ bool operator==(const SkRegion& other) const;
+
+ /** Compares SkRegion and other; returns true if they do not enclose the same area.
+
+ @param other SkRegion to compare
+ @return true if SkRegion pair are not equivalent
+ */
+ bool operator!=(const SkRegion& other) const {
+ return !(*this == other);
+ }
+
+ /** Sets SkRegion to src, and returns true if src bounds is not empty.
+ This makes SkRegion and src identical by value. Internally,
+ SkRegion and src share pointer values. The underlying SkRect array is
+ copied when modified.
+
+ Creating a SkRegion copy is very efficient and never allocates memory.
+ SkRegion are always copied by value from the interface; the underlying shared
+ pointers are not exposed.
+
+ @param src SkRegion to copy
+ @return copy of src
+ */
+ bool set(const SkRegion& src) {
+ *this = src;
+ return !this->isEmpty();
+ }
+
+ /** Exchanges SkIRect array of SkRegion and other. swap() internally exchanges pointers,
+ so it is lightweight and does not allocate memory.
+
+ swap() usage has largely been replaced by operator=(const SkRegion& region).
+ SkPath do not copy their content on assignment until they are written to,
+ making assignment as efficient as swap().
+
+ @param other operator=(const SkRegion& region) set
+
+ example: https://fiddle.skia.org/c/@Region_swap
+ */
+ void swap(SkRegion& other);
+
+ /** Returns true if SkRegion is empty.
+ Empty SkRegion has bounds width or height less than or equal to zero.
+ SkRegion() constructs empty SkRegion; setEmpty()
+ and setRect() with dimensionless data make SkRegion empty.
+
+ @return true if bounds has no width or height
+ */
+ bool isEmpty() const { return fRunHead == emptyRunHeadPtr(); }
+
+ /** Returns true if SkRegion is one SkIRect with positive dimensions.
+
+ @return true if SkRegion contains one SkIRect
+ */
+ bool isRect() const { return fRunHead == kRectRunHeadPtr; }
+
+ /** Returns true if SkRegion is described by more than one rectangle.
+
+ @return true if SkRegion contains more than one SkIRect
+ */
+ bool isComplex() const { return !this->isEmpty() && !this->isRect(); }
+
+ /** Returns minimum and maximum axes values of SkIRect array.
+ Returns (0, 0, 0, 0) if SkRegion is empty.
+
+ @return combined bounds of all SkIRect elements
+ */
+ const SkIRect& getBounds() const { return fBounds; }
+
+ /** Returns a value that increases with the number of
+ elements in SkRegion. Returns zero if SkRegion is empty.
+ Returns one if SkRegion equals SkIRect; otherwise, returns
+ value greater than one indicating that SkRegion is complex.
+
+ Call to compare SkRegion for relative complexity.
+
+ @return relative complexity
+
+ example: https://fiddle.skia.org/c/@Region_computeRegionComplexity
+ */
+ int computeRegionComplexity() const;
+
+ /** Appends outline of SkRegion to path.
+ Returns true if SkRegion is not empty; otherwise, returns false, and leaves path
+ unmodified.
+
+ @param path SkPath to append to
+ @return true if path changed
+
+ example: https://fiddle.skia.org/c/@Region_getBoundaryPath
+ */
+ bool getBoundaryPath(SkPath* path) const;
+
+ /** Constructs an empty SkRegion. SkRegion is set to empty bounds
+ at (0, 0) with zero width and height. Always returns false.
+
+ @return false
+
+ example: https://fiddle.skia.org/c/@Region_setEmpty
+ */
+ bool setEmpty();
+
+ /** Constructs a rectangular SkRegion matching the bounds of rect.
+ If rect is empty, constructs empty and returns false.
+
+ @param rect bounds of constructed SkRegion
+ @return true if rect is not empty
+
+ example: https://fiddle.skia.org/c/@Region_setRect
+ */
+ bool setRect(const SkIRect& rect);
+
+ /** Constructs SkRegion as the union of SkIRect in rects array. If count is
+ zero, constructs empty SkRegion. Returns false if constructed SkRegion is empty.
+
+ May be faster than repeated calls to op().
+
+ @param rects array of SkIRect
+ @param count array size
+ @return true if constructed SkRegion is not empty
+
+ example: https://fiddle.skia.org/c/@Region_setRects
+ */
+ bool setRects(const SkIRect rects[], int count);
+
+ /** Constructs a copy of an existing region.
+ Makes two regions identical by value. Internally, region and
+ the returned result share pointer values. The underlying SkRect array is
+ copied when modified.
+
+ Creating a SkRegion copy is very efficient and never allocates memory.
+ SkRegion are always copied by value from the interface; the underlying shared
+ pointers are not exposed.
+
+ @param region SkRegion to copy by value
+ @return SkRegion to copy by value
+
+ example: https://fiddle.skia.org/c/@Region_setRegion
+ */
+ bool setRegion(const SkRegion& region);
+
+ /** Constructs SkRegion to match outline of path within clip.
+ Returns false if constructed SkRegion is empty.
+
+ Constructed SkRegion draws the same pixels as path through clip when
+ anti-aliasing is disabled.
+
+ @param path SkPath providing outline
+ @param clip SkRegion containing path
+ @return true if constructed SkRegion is not empty
+
+ example: https://fiddle.skia.org/c/@Region_setPath
+ */
+ bool setPath(const SkPath& path, const SkRegion& clip);
+
+ /** Returns true if SkRegion intersects rect.
+ Returns false if either rect or SkRegion is empty, or do not intersect.
+
+ @param rect SkIRect to intersect
+ @return true if rect and SkRegion have area in common
+
+ example: https://fiddle.skia.org/c/@Region_intersects
+ */
+ bool intersects(const SkIRect& rect) const;
+
+ /** Returns true if SkRegion intersects other.
+ Returns false if either other or SkRegion is empty, or do not intersect.
+
+ @param other SkRegion to intersect
+ @return true if other and SkRegion have area in common
+
+ example: https://fiddle.skia.org/c/@Region_intersects_2
+ */
+ bool intersects(const SkRegion& other) const;
+
+ /** Returns true if SkIPoint (x, y) is inside SkRegion.
+ Returns false if SkRegion is empty.
+
+ @param x test SkIPoint x-coordinate
+ @param y test SkIPoint y-coordinate
+ @return true if (x, y) is inside SkRegion
+
+ example: https://fiddle.skia.org/c/@Region_contains
+ */
+ bool contains(int32_t x, int32_t y) const;
+
+ /** Returns true if other is completely inside SkRegion.
+ Returns false if SkRegion or other is empty.
+
+ @param other SkIRect to contain
+ @return true if other is inside SkRegion
+
+ example: https://fiddle.skia.org/c/@Region_contains_2
+ */
+ bool contains(const SkIRect& other) const;
+
+ /** Returns true if other is completely inside SkRegion.
+ Returns false if SkRegion or other is empty.
+
+ @param other SkRegion to contain
+ @return true if other is inside SkRegion
+
+ example: https://fiddle.skia.org/c/@Region_contains_3
+ */
+ bool contains(const SkRegion& other) const;
+
+ /** Returns true if SkRegion is a single rectangle and contains r.
+ May return false even though SkRegion contains r.
+
+ @param r SkIRect to contain
+ @return true quickly if r points are equal or inside
+ */
+ bool quickContains(const SkIRect& r) const {
+ SkASSERT(this->isEmpty() == fBounds.isEmpty()); // valid region
+
+ return r.fLeft < r.fRight && r.fTop < r.fBottom &&
+ fRunHead == kRectRunHeadPtr && // this->isRect()
+ /* fBounds.contains(left, top, right, bottom); */
+ fBounds.fLeft <= r.fLeft && fBounds.fTop <= r.fTop &&
+ fBounds.fRight >= r.fRight && fBounds.fBottom >= r.fBottom;
+ }
+
+ /** Returns true if SkRegion does not intersect rect.
+ Returns true if rect is empty or SkRegion is empty.
+ May return false even though SkRegion does not intersect rect.
+
+ @param rect SkIRect to intersect
+ @return true if rect does not intersect
+ */
+ bool quickReject(const SkIRect& rect) const {
+ return this->isEmpty() || rect.isEmpty() ||
+ !SkIRect::Intersects(fBounds, rect);
+ }
+
+ /** Returns true if SkRegion does not intersect rgn.
+ Returns true if rgn is empty or SkRegion is empty.
+ May return false even though SkRegion does not intersect rgn.
+
+ @param rgn SkRegion to intersect
+ @return true if rgn does not intersect
+ */
+ bool quickReject(const SkRegion& rgn) const {
+ return this->isEmpty() || rgn.isEmpty() ||
+ !SkIRect::Intersects(fBounds, rgn.fBounds);
+ }
+
+ /** Offsets SkRegion by ivector (dx, dy). Has no effect if SkRegion is empty.
+
+ @param dx x-axis offset
+ @param dy y-axis offset
+ */
+ void translate(int dx, int dy) { this->translate(dx, dy, this); }
+
+ /** Offsets SkRegion by ivector (dx, dy), writing result to dst. SkRegion may be passed
+ as dst parameter, translating SkRegion in place. Has no effect if dst is nullptr.
+ If SkRegion is empty, sets dst to empty.
+
+ @param dx x-axis offset
+ @param dy y-axis offset
+ @param dst translated result
+
+ example: https://fiddle.skia.org/c/@Region_translate_2
+ */
+ void translate(int dx, int dy, SkRegion* dst) const;
+
+ /** \enum SkRegion::Op
+ The logical operations that can be performed when combining two SkRegion.
+ */
+ enum Op {
+ kDifference_Op, //!< target minus operand
+ kIntersect_Op, //!< target intersected with operand
+ kUnion_Op, //!< target unioned with operand
+ kXOR_Op, //!< target exclusive or with operand
+ kReverseDifference_Op, //!< operand minus target
+ kReplace_Op, //!< replace target with operand
+ kLastOp = kReplace_Op, //!< last operator
+ };
+
+ static const int kOpCnt = kLastOp + 1;
+
+ /** Replaces SkRegion with the result of SkRegion op rect.
+ Returns true if replaced SkRegion is not empty.
+
+ @param rect SkIRect operand
+ @return false if result is empty
+ */
+ bool op(const SkIRect& rect, Op op) {
+ if (this->isRect() && kIntersect_Op == op) {
+ if (!fBounds.intersect(rect)) {
+ return this->setEmpty();
+ }
+ return true;
+ }
+ return this->op(*this, rect, op);
+ }
+
+ /** Replaces SkRegion with the result of SkRegion op rgn.
+ Returns true if replaced SkRegion is not empty.
+
+ @param rgn SkRegion operand
+ @return false if result is empty
+ */
+ bool op(const SkRegion& rgn, Op op) { return this->op(*this, rgn, op); }
+
+ /** Replaces SkRegion with the result of rect op rgn.
+ Returns true if replaced SkRegion is not empty.
+
+ @param rect SkIRect operand
+ @param rgn SkRegion operand
+ @return false if result is empty
+
+ example: https://fiddle.skia.org/c/@Region_op_4
+ */
+ bool op(const SkIRect& rect, const SkRegion& rgn, Op op);
+
+ /** Replaces SkRegion with the result of rgn op rect.
+ Returns true if replaced SkRegion is not empty.
+
+ @param rgn SkRegion operand
+ @param rect SkIRect operand
+ @return false if result is empty
+
+ example: https://fiddle.skia.org/c/@Region_op_5
+ */
+ bool op(const SkRegion& rgn, const SkIRect& rect, Op op);
+
+ /** Replaces SkRegion with the result of rgna op rgnb.
+ Returns true if replaced SkRegion is not empty.
+
+ @param rgna SkRegion operand
+ @param rgnb SkRegion operand
+ @return false if result is empty
+
+ example: https://fiddle.skia.org/c/@Region_op_6
+ */
+ bool op(const SkRegion& rgna, const SkRegion& rgnb, Op op);
+
+#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
+ /** Private. Android framework only.
+
+ @return string representation of SkRegion
+ */
+ char* toString();
+#endif
+
+ /** \class SkRegion::Iterator
+ Returns sequence of rectangles, sorted along y-axis, then x-axis, that make
+ up SkRegion.
+ */
+ class SK_API Iterator {
+ public:
+
+ /** Initializes SkRegion::Iterator with an empty SkRegion. done() on SkRegion::Iterator
+ returns true.
+ Call reset() to initialized SkRegion::Iterator at a later time.
+
+ @return empty SkRegion iterator
+ */
+ Iterator() : fRgn(nullptr), fDone(true) {}
+
+ /** Sets SkRegion::Iterator to return elements of SkIRect array in region.
+
+ @param region SkRegion to iterate
+ @return SkRegion iterator
+
+ example: https://fiddle.skia.org/c/@Region_Iterator_copy_const_SkRegion
+ */
+ Iterator(const SkRegion& region);
+
+ /** SkPoint SkRegion::Iterator to start of SkRegion.
+ Returns true if SkRegion was set; otherwise, returns false.
+
+ @return true if SkRegion was set
+
+ example: https://fiddle.skia.org/c/@Region_Iterator_rewind
+ */
+ bool rewind();
+
+ /** Resets iterator, using the new SkRegion.
+
+ @param region SkRegion to iterate
+
+ example: https://fiddle.skia.org/c/@Region_Iterator_reset
+ */
+ void reset(const SkRegion& region);
+
+ /** Returns true if SkRegion::Iterator is pointing to final SkIRect in SkRegion.
+
+ @return true if data parsing is complete
+ */
+ bool done() const { return fDone; }
+
+ /** Advances SkRegion::Iterator to next SkIRect in SkRegion if it is not done.
+
+ example: https://fiddle.skia.org/c/@Region_Iterator_next
+ */
+ void next();
+
+ /** Returns SkIRect element in SkRegion. Does not return predictable results if SkRegion
+ is empty.
+
+ @return part of SkRegion as SkIRect
+ */
+ const SkIRect& rect() const { return fRect; }
+
+ /** Returns SkRegion if set; otherwise, returns nullptr.
+
+ @return iterated SkRegion
+ */
+ const SkRegion* rgn() const { return fRgn; }
+
+ private:
+ const SkRegion* fRgn;
+ const SkRegion::RunType* fRuns;
+ SkIRect fRect = {0, 0, 0, 0};
+ bool fDone;
+ };
+
+ /** \class SkRegion::Cliperator
+ Returns the sequence of rectangles, sorted along y-axis, then x-axis, that make
+ up SkRegion intersected with the specified clip rectangle.
+ */
+ class SK_API Cliperator {
+ public:
+
+ /** Sets SkRegion::Cliperator to return elements of SkIRect array in SkRegion within clip.
+
+ @param region SkRegion to iterate
+ @param clip bounds of iteration
+ @return SkRegion iterator
+
+ example: https://fiddle.skia.org/c/@Region_Cliperator_const_SkRegion_const_SkIRect
+ */
+ Cliperator(const SkRegion& region, const SkIRect& clip);
+
+ /** Returns true if SkRegion::Cliperator is pointing to final SkIRect in SkRegion.
+
+ @return true if data parsing is complete
+ */
+ bool done() { return fDone; }
+
+ /** Advances iterator to next SkIRect in SkRegion contained by clip.
+
+ example: https://fiddle.skia.org/c/@Region_Cliperator_next
+ */
+ void next();
+
+ /** Returns SkIRect element in SkRegion, intersected with clip passed to
+ SkRegion::Cliperator constructor. Does not return predictable results if SkRegion
+ is empty.
+
+ @return part of SkRegion inside clip as SkIRect
+ */
+ const SkIRect& rect() const { return fRect; }
+
+ private:
+ Iterator fIter;
+ SkIRect fClip;
+ SkIRect fRect = {0, 0, 0, 0};
+ bool fDone;
+ };
+
+ /** \class SkRegion::Spanerator
+ Returns the line segment ends within SkRegion that intersect a horizontal line.
+ */
+ class Spanerator {
+ public:
+
+ /** Sets SkRegion::Spanerator to return line segments in SkRegion on scan line.
+
+ @param region SkRegion to iterate
+ @param y horizontal line to intersect
+ @param left bounds of iteration
+ @param right bounds of iteration
+ @return SkRegion iterator
+
+ example: https://fiddle.skia.org/c/@Region_Spanerator_const_SkRegion_int_int_int
+ */
+ Spanerator(const SkRegion& region, int y, int left, int right);
+
+ /** Advances iterator to next span intersecting SkRegion within line segment provided
+ in constructor. Returns true if interval was found.
+
+ @param left pointer to span start; may be nullptr
+ @param right pointer to span end; may be nullptr
+ @return true if interval was found
+
+ example: https://fiddle.skia.org/c/@Region_Spanerator_next
+ */
+ bool next(int* left, int* right);
+
+ private:
+ const SkRegion::RunType* fRuns;
+ int fLeft, fRight;
+ bool fDone;
+ };
+
+ /** Writes SkRegion to buffer, and returns number of bytes written.
+ If buffer is nullptr, returns number number of bytes that would be written.
+
+ @param buffer storage for binary data
+ @return size of SkRegion
+
+ example: https://fiddle.skia.org/c/@Region_writeToMemory
+ */
+ size_t writeToMemory(void* buffer) const;
+
+ /** Constructs SkRegion from buffer of size length. Returns bytes read.
+ Returned value will be multiple of four or zero if length was too small.
+
+ @param buffer storage for binary data
+ @param length size of buffer
+ @return bytes read
+
+ example: https://fiddle.skia.org/c/@Region_readFromMemory
+ */
+ size_t readFromMemory(const void* buffer, size_t length);
+
+private:
+ static constexpr int kOpCount = kReplace_Op + 1;
+
+ // T
+ // [B N L R S]
+ // S
+ static constexpr int kRectRegionRuns = 7;
+
+ struct RunHead;
+
+ static RunHead* emptyRunHeadPtr() { return (SkRegion::RunHead*) -1; }
+ static constexpr RunHead* kRectRunHeadPtr = nullptr;
+
+ // allocate space for count runs
+ void allocateRuns(int count);
+ void allocateRuns(int count, int ySpanCount, int intervalCount);
+ void allocateRuns(const RunHead& src);
+
+ SkDEBUGCODE(void dump() const;)
+
+ SkIRect fBounds;
+ RunHead* fRunHead;
+
+ void freeRuns();
+
+ /**
+ * Return the runs from this region, consing up fake runs if the region
+ * is empty or a rect. In those 2 cases, we use tmpStorage to hold the
+ * run data.
+ */
+ const RunType* getRuns(RunType tmpStorage[], int* intervals) const;
+
+ // This is called with runs[] that do not yet have their interval-count
+ // field set on each scanline. That is computed as part of this call
+ // (inside ComputeRunBounds).
+ bool setRuns(RunType runs[], int count);
+
+ int count_runtype_values(int* itop, int* ibot) const;
+
+ bool isValid() const;
+
+ static void BuildRectRuns(const SkIRect& bounds,
+ RunType runs[kRectRegionRuns]);
+
+ // If the runs define a simple rect, return true and set bounds to that
+ // rect. If not, return false and ignore bounds.
+ static bool RunsAreARect(const SkRegion::RunType runs[], int count,
+ SkIRect* bounds);
+
+ /**
+ * If the last arg is null, just return if the result is non-empty,
+ * else store the result in the last arg.
+ */
+ static bool Oper(const SkRegion&, const SkRegion&, SkRegion::Op, SkRegion*);
+
+ friend struct RunHead;
+ friend class Iterator;
+ friend class Spanerator;
+ friend class SkRegionPriv;
+ friend class SkRgnBuilder;
+ friend class SkFlatRegion;
+};
+
+#endif
diff --git a/src/deps/skia/include/core/SkSamplingOptions.h b/src/deps/skia/include/core/SkSamplingOptions.h
new file mode 100644
index 000000000..468cf5bef
--- /dev/null
+++ b/src/deps/skia/include/core/SkSamplingOptions.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2020 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkImageSampling_DEFINED
+#define SkImageSampling_DEFINED
+
+#include "include/core/SkTypes.h"
+#include <new>
+
+enum class SkFilterMode {
+ kNearest, // single sample point (nearest neighbor)
+ kLinear, // interporate between 2x2 sample points (bilinear interpolation)
+
+ kLast = kLinear,
+};
+
+enum class SkMipmapMode {
+ kNone, // ignore mipmap levels, sample from the "base"
+ kNearest, // sample from the nearest level
+ kLinear, // interpolate between the two nearest levels
+
+ kLast = kLinear,
+};
+
+/*
+ * Specify B and C (each between 0...1) to create a shader that applies the corresponding
+ * cubic reconstruction filter to the image.
+ *
+ * Example values:
+ * B = 1/3, C = 1/3 "Mitchell" filter
+ * B = 0, C = 1/2 "Catmull-Rom" filter
+ *
+ * See "Reconstruction Filters in Computer Graphics"
+ * Don P. Mitchell
+ * Arun N. Netravali
+ * 1988
+ * https://www.cs.utexas.edu/~fussell/courses/cs384g-fall2013/lectures/mitchell/Mitchell.pdf
+ *
+ * Desmos worksheet https://www.desmos.com/calculator/aghdpicrvr
+ * Nice overview https://entropymine.com/imageworsener/bicubic/
+ */
+struct SkCubicResampler {
+ float B, C;
+
+ // Historic default for kHigh_SkFilterQuality
+ static constexpr SkCubicResampler Mitchell() { return {1/3.0f, 1/3.0f}; }
+ static constexpr SkCubicResampler CatmullRom() { return {0.0f, 1/2.0f}; }
+};
+
+struct SK_API SkSamplingOptions {
+ const bool useCubic = false;
+ const SkCubicResampler cubic = {0, 0};
+ const SkFilterMode filter = SkFilterMode::kNearest;
+ const SkMipmapMode mipmap = SkMipmapMode::kNone;
+
+ SkSamplingOptions() = default;
+ SkSamplingOptions(const SkSamplingOptions&) = default;
+ SkSamplingOptions& operator=(const SkSamplingOptions& that) {
+ this->~SkSamplingOptions(); // A pedantic no-op.
+ new (this) SkSamplingOptions(that);
+ return *this;
+ }
+
+ SkSamplingOptions(SkFilterMode fm, SkMipmapMode mm)
+ : useCubic(false)
+ , filter(fm)
+ , mipmap(mm) {}
+
+ explicit SkSamplingOptions(SkFilterMode fm)
+ : useCubic(false)
+ , filter(fm)
+ , mipmap(SkMipmapMode::kNone) {}
+
+ explicit SkSamplingOptions(const SkCubicResampler& c)
+ : useCubic(true)
+ , cubic(c) {}
+
+ bool operator==(const SkSamplingOptions& other) const {
+ return useCubic == other.useCubic
+ && cubic.B == other.cubic.B
+ && cubic.C == other.cubic.C
+ && filter == other.filter
+ && mipmap == other.mipmap;
+ }
+ bool operator!=(const SkSamplingOptions& other) const { return !(*this == other); }
+};
+
+#endif
diff --git a/src/deps/skia/include/core/SkScalar.h b/src/deps/skia/include/core/SkScalar.h
new file mode 100644
index 000000000..07d4ec73d
--- /dev/null
+++ b/src/deps/skia/include/core/SkScalar.h
@@ -0,0 +1,194 @@
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkScalar_DEFINED
+#define SkScalar_DEFINED
+
+#include "include/private/SkFloatingPoint.h"
+
+#undef SK_SCALAR_IS_FLOAT
+#define SK_SCALAR_IS_FLOAT 1
+
+typedef float SkScalar;
+
+#define SK_Scalar1 1.0f
+#define SK_ScalarHalf 0.5f
+#define SK_ScalarSqrt2 SK_FloatSqrt2
+#define SK_ScalarPI SK_FloatPI
+#define SK_ScalarTanPIOver8 0.414213562f
+#define SK_ScalarRoot2Over2 0.707106781f
+#define SK_ScalarMax 3.402823466e+38f
+#define SK_ScalarInfinity SK_FloatInfinity
+#define SK_ScalarNegativeInfinity SK_FloatNegativeInfinity
+#define SK_ScalarNaN SK_FloatNaN
+
+#define SkScalarFloorToScalar(x) sk_float_floor(x)
+#define SkScalarCeilToScalar(x) sk_float_ceil(x)
+#define SkScalarRoundToScalar(x) sk_float_floor((x) + 0.5f)
+#define SkScalarTruncToScalar(x) sk_float_trunc(x)
+
+#define SkScalarFloorToInt(x) sk_float_floor2int(x)
+#define SkScalarCeilToInt(x) sk_float_ceil2int(x)
+#define SkScalarRoundToInt(x) sk_float_round2int(x)
+
+#define SkScalarAbs(x) sk_float_abs(x)
+#define SkScalarCopySign(x, y) sk_float_copysign(x, y)
+#define SkScalarMod(x, y) sk_float_mod(x,y)
+#define SkScalarSqrt(x) sk_float_sqrt(x)
+#define SkScalarPow(b, e) sk_float_pow(b, e)
+
+#define SkScalarSin(radians) (float)sk_float_sin(radians)
+#define SkScalarCos(radians) (float)sk_float_cos(radians)
+#define SkScalarTan(radians) (float)sk_float_tan(radians)
+#define SkScalarASin(val) (float)sk_float_asin(val)
+#define SkScalarACos(val) (float)sk_float_acos(val)
+#define SkScalarATan2(y, x) (float)sk_float_atan2(y,x)
+#define SkScalarExp(x) (float)sk_float_exp(x)
+#define SkScalarLog(x) (float)sk_float_log(x)
+#define SkScalarLog2(x) (float)sk_float_log2(x)
+
+//////////////////////////////////////////////////////////////////////////////////////////////////
+
+#define SkIntToScalar(x) static_cast<SkScalar>(x)
+#define SkIntToFloat(x) static_cast<float>(x)
+#define SkScalarTruncToInt(x) sk_float_saturate2int(x)
+
+#define SkScalarToFloat(x) static_cast<float>(x)
+#define SkFloatToScalar(x) static_cast<SkScalar>(x)
+#define SkScalarToDouble(x) static_cast<double>(x)
+#define SkDoubleToScalar(x) sk_double_to_float(x)
+
+#define SK_ScalarMin (-SK_ScalarMax)
+
+static inline bool SkScalarIsNaN(SkScalar x) { return x != x; }
+
+/** Returns true if x is not NaN and not infinite
+ */
+static inline bool SkScalarIsFinite(SkScalar x) { return sk_float_isfinite(x); }
+
+static inline bool SkScalarsAreFinite(SkScalar a, SkScalar b) {
+ return sk_floats_are_finite(a, b);
+}
+
+static inline bool SkScalarsAreFinite(const SkScalar array[], int count) {
+ return sk_floats_are_finite(array, count);
+}
+
+/**
+ * Variant of SkScalarRoundToInt, that performs the rounding step (adding 0.5) explicitly using
+ * double, to avoid possibly losing the low bit(s) of the answer before calling floor().
+ *
+ * This routine will likely be slower than SkScalarRoundToInt(), and should only be used when the
+ * extra precision is known to be valuable.
+ *
+ * In particular, this catches the following case:
+ * SkScalar x = 0.49999997;
+ * int ix = SkScalarRoundToInt(x);
+ * SkASSERT(0 == ix); // <--- fails
+ * ix = SkDScalarRoundToInt(x);
+ * SkASSERT(0 == ix); // <--- succeeds
+ */
+static inline int SkDScalarRoundToInt(SkScalar x) {
+ double xx = x;
+ xx += 0.5;
+ return (int)floor(xx);
+}
+
+/** Returns the fractional part of the scalar. */
+static inline SkScalar SkScalarFraction(SkScalar x) {
+ return x - SkScalarTruncToScalar(x);
+}
+
+static inline SkScalar SkScalarSquare(SkScalar x) { return x * x; }
+
+#define SkScalarInvert(x) sk_ieee_float_divide_TODO_IS_DIVIDE_BY_ZERO_SAFE_HERE(SK_Scalar1, (x))
+#define SkScalarAve(a, b) (((a) + (b)) * SK_ScalarHalf)
+#define SkScalarHalf(a) ((a) * SK_ScalarHalf)
+
+#define SkDegreesToRadians(degrees) ((degrees) * (SK_ScalarPI / 180))
+#define SkRadiansToDegrees(radians) ((radians) * (180 / SK_ScalarPI))
+
+static inline bool SkScalarIsInt(SkScalar x) {
+ return x == SkScalarFloorToScalar(x);
+}
+
+/**
+ * Returns -1 || 0 || 1 depending on the sign of value:
+ * -1 if x < 0
+ * 0 if x == 0
+ * 1 if x > 0
+ */
+static inline int SkScalarSignAsInt(SkScalar x) {
+ return x < 0 ? -1 : (x > 0);
+}
+
+// Scalar result version of above
+static inline SkScalar SkScalarSignAsScalar(SkScalar x) {
+ return x < 0 ? -SK_Scalar1 : ((x > 0) ? SK_Scalar1 : 0);
+}
+
+#define SK_ScalarNearlyZero (SK_Scalar1 / (1 << 12))
+
+static inline bool SkScalarNearlyZero(SkScalar x,
+ SkScalar tolerance = SK_ScalarNearlyZero) {
+ SkASSERT(tolerance >= 0);
+ return SkScalarAbs(x) <= tolerance;
+}
+
+static inline bool SkScalarNearlyEqual(SkScalar x, SkScalar y,
+ SkScalar tolerance = SK_ScalarNearlyZero) {
+ SkASSERT(tolerance >= 0);
+ return SkScalarAbs(x-y) <= tolerance;
+}
+
+static inline float SkScalarSinSnapToZero(SkScalar radians) {
+ float v = SkScalarSin(radians);
+ return SkScalarNearlyZero(v) ? 0.0f : v;
+}
+
+static inline float SkScalarCosSnapToZero(SkScalar radians) {
+ float v = SkScalarCos(radians);
+ return SkScalarNearlyZero(v) ? 0.0f : v;
+}
+
+/** Linearly interpolate between A and B, based on t.
+ If t is 0, return A
+ If t is 1, return B
+ else interpolate.
+ t must be [0..SK_Scalar1]
+*/
+static inline SkScalar SkScalarInterp(SkScalar A, SkScalar B, SkScalar t) {
+ SkASSERT(t >= 0 && t <= SK_Scalar1);
+ return A + (B - A) * t;
+}
+
+/** Interpolate along the function described by (keys[length], values[length])
+ for the passed searchKey. SearchKeys outside the range keys[0]-keys[Length]
+ clamp to the min or max value. This function assumes the number of pairs
+ (length) will be small and a linear search is used.
+
+ Repeated keys are allowed for discontinuous functions (so long as keys is
+ monotonically increasing). If key is the value of a repeated scalar in
+ keys the first one will be used.
+*/
+SkScalar SkScalarInterpFunc(SkScalar searchKey, const SkScalar keys[],
+ const SkScalar values[], int length);
+
+/*
+ * Helper to compare an array of scalars.
+ */
+static inline bool SkScalarsEqual(const SkScalar a[], const SkScalar b[], int n) {
+ SkASSERT(n >= 0);
+ for (int i = 0; i < n; ++i) {
+ if (a[i] != b[i]) {
+ return false;
+ }
+ }
+ return true;
+}
+
+#endif
diff --git a/src/deps/skia/include/core/SkSerialProcs.h b/src/deps/skia/include/core/SkSerialProcs.h
new file mode 100644
index 000000000..87e10d847
--- /dev/null
+++ b/src/deps/skia/include/core/SkSerialProcs.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkSerialProcs_DEFINED
+#define SkSerialProcs_DEFINED
+
+#include "include/core/SkImage.h"
+#include "include/core/SkPicture.h"
+#include "include/core/SkTypeface.h"
+
+/**
+ * A serial-proc is asked to serialize the specified object (e.g. picture or image).
+ * If a data object is returned, it will be used (even if it is zero-length).
+ * If null is returned, then Skia will take its default action.
+ *
+ * The default action for pictures is to use Skia's internal format.
+ * The default action for images is to encode either in its native format or PNG.
+ * The default action for typefaces is to use Skia's internal format.
+ */
+
+typedef sk_sp<SkData> (*SkSerialPictureProc)(SkPicture*, void* ctx);
+typedef sk_sp<SkData> (*SkSerialImageProc)(SkImage*, void* ctx);
+typedef sk_sp<SkData> (*SkSerialTypefaceProc)(SkTypeface*, void* ctx);
+
+/**
+ * Called with the encoded form of a picture (previously written with a custom
+ * SkSerialPictureProc proc). Return a picture object, or nullptr indicating failure.
+ */
+typedef sk_sp<SkPicture> (*SkDeserialPictureProc)(const void* data, size_t length, void* ctx);
+
+/**
+ * Called with the encoded from of an image. The proc can return an image object, or if it
+ * returns nullptr, then Skia will take its default action to try to create an image from the data.
+ *
+ * Note that unlike SkDeserialPictureProc and SkDeserialTypefaceProc, return nullptr from this
+ * does not indicate failure, but is a signal for Skia to take its default action.
+ */
+typedef sk_sp<SkImage> (*SkDeserialImageProc)(const void* data, size_t length, void* ctx);
+
+/**
+ * Called with the encoded form of a typeface (previously written with a custom
+ * SkSerialTypefaceProc proc). Return a typeface object, or nullptr indicating failure.
+ */
+typedef sk_sp<SkTypeface> (*SkDeserialTypefaceProc)(const void* data, size_t length, void* ctx);
+
+struct SK_API SkSerialProcs {
+ SkSerialPictureProc fPictureProc = nullptr;
+ void* fPictureCtx = nullptr;
+
+ SkSerialImageProc fImageProc = nullptr;
+ void* fImageCtx = nullptr;
+
+ SkSerialTypefaceProc fTypefaceProc = nullptr;
+ void* fTypefaceCtx = nullptr;
+};
+
+struct SK_API SkDeserialProcs {
+ SkDeserialPictureProc fPictureProc = nullptr;
+ void* fPictureCtx = nullptr;
+
+ SkDeserialImageProc fImageProc = nullptr;
+ void* fImageCtx = nullptr;
+
+ SkDeserialTypefaceProc fTypefaceProc = nullptr;
+ void* fTypefaceCtx = nullptr;
+};
+
+#endif
+
diff --git a/src/deps/skia/include/core/SkShader.h b/src/deps/skia/include/core/SkShader.h
new file mode 100644
index 000000000..fba17f8ad
--- /dev/null
+++ b/src/deps/skia/include/core/SkShader.h
@@ -0,0 +1,148 @@
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkShader_DEFINED
+#define SkShader_DEFINED
+
+#include "include/core/SkBlendMode.h"
+#include "include/core/SkColor.h"
+#include "include/core/SkFlattenable.h"
+#include "include/core/SkImageInfo.h"
+#include "include/core/SkMatrix.h"
+#include "include/core/SkTileMode.h"
+
+class SkArenaAlloc;
+class SkBitmap;
+class SkBlender;
+class SkColorFilter;
+class SkColorSpace;
+class SkImage;
+class SkPath;
+class SkPicture;
+class SkRasterPipeline;
+class GrFragmentProcessor;
+
+/** \class SkShader
+ *
+ * Shaders specify the source color(s) for what is being drawn. If a paint
+ * has no shader, then the paint's color is used. If the paint has a
+ * shader, then the shader's color(s) are use instead, but they are
+ * modulated by the paint's alpha. This makes it easy to create a shader
+ * once (e.g. bitmap tiling or gradient) and then change its transparency
+ * w/o having to modify the original shader... only the paint's alpha needs
+ * to be modified.
+ */
+class SK_API SkShader : public SkFlattenable {
+public:
+ /**
+ * Returns true if the shader is guaranteed to produce only opaque
+ * colors, subject to the SkPaint using the shader to apply an opaque
+ * alpha value. Subclasses should override this to allow some
+ * optimizations.
+ */
+ virtual bool isOpaque() const { return false; }
+
+ /**
+ * Iff this shader is backed by a single SkImage, return its ptr (the caller must ref this
+ * if they want to keep it longer than the lifetime of the shader). If not, return nullptr.
+ */
+ SkImage* isAImage(SkMatrix* localMatrix, SkTileMode xy[2]) const;
+
+ bool isAImage() const {
+ return this->isAImage(nullptr, (SkTileMode*)nullptr) != nullptr;
+ }
+
+ /**
+ * If the shader subclass can be represented as a gradient, asAGradient
+ * returns the matching GradientType enum (or kNone_GradientType if it
+ * cannot). Also, if info is not null, asAGradient populates info with
+ * the relevant (see below) parameters for the gradient. fColorCount
+ * is both an input and output parameter. On input, it indicates how
+ * many entries in fColors and fColorOffsets can be used, if they are
+ * non-NULL. After asAGradient has run, fColorCount indicates how
+ * many color-offset pairs there are in the gradient. If there is
+ * insufficient space to store all of the color-offset pairs, fColors
+ * and fColorOffsets will not be altered. fColorOffsets specifies
+ * where on the range of 0 to 1 to transition to the given color.
+ * The meaning of fPoint and fRadius is dependant on the type of gradient.
+ *
+ * None:
+ * info is ignored.
+ * Color:
+ * fColorOffsets[0] is meaningless.
+ * Linear:
+ * fPoint[0] and fPoint[1] are the end-points of the gradient
+ * Radial:
+ * fPoint[0] and fRadius[0] are the center and radius
+ * Conical:
+ * fPoint[0] and fRadius[0] are the center and radius of the 1st circle
+ * fPoint[1] and fRadius[1] are the center and radius of the 2nd circle
+ * Sweep:
+ * fPoint[0] is the center of the sweep.
+ */
+
+ enum GradientType {
+ kNone_GradientType,
+ kColor_GradientType,
+ kLinear_GradientType,
+ kRadial_GradientType,
+ kSweep_GradientType,
+ kConical_GradientType,
+ kLast_GradientType = kConical_GradientType,
+ };
+
+ struct GradientInfo {
+ int fColorCount; //!< In-out parameter, specifies passed size
+ // of fColors/fColorOffsets on input, and
+ // actual number of colors/offsets on
+ // output.
+ SkColor* fColors; //!< The colors in the gradient.
+ SkScalar* fColorOffsets; //!< The unit offset for color transitions.
+ SkPoint fPoint[2]; //!< Type specific, see above.
+ SkScalar fRadius[2]; //!< Type specific, see above.
+ SkTileMode fTileMode;
+ uint32_t fGradientFlags; //!< see SkGradientShader::Flags
+ };
+
+ // DEPRECATED. skbug.com/8941
+ virtual GradientType asAGradient(GradientInfo* info) const;
+
+ //////////////////////////////////////////////////////////////////////////
+ // Methods to create combinations or variants of shaders
+
+ /**
+ * Return a shader that will apply the specified localMatrix to this shader.
+ * The specified matrix will be applied before any matrix associated with this shader.
+ */
+ sk_sp<SkShader> makeWithLocalMatrix(const SkMatrix&) const;
+
+ /**
+ * Create a new shader that produces the same colors as invoking this shader and then applying
+ * the colorfilter.
+ */
+ sk_sp<SkShader> makeWithColorFilter(sk_sp<SkColorFilter>) const;
+
+private:
+ SkShader() = default;
+ friend class SkShaderBase;
+
+ using INHERITED = SkFlattenable;
+};
+
+class SK_API SkShaders {
+public:
+ static sk_sp<SkShader> Empty();
+ static sk_sp<SkShader> Color(SkColor);
+ static sk_sp<SkShader> Color(const SkColor4f&, sk_sp<SkColorSpace>);
+ static sk_sp<SkShader> Blend(SkBlendMode mode, sk_sp<SkShader> dst, sk_sp<SkShader> src);
+ static sk_sp<SkShader> Blend(sk_sp<SkBlender>, sk_sp<SkShader> dst, sk_sp<SkShader> src);
+
+private:
+ SkShaders() = delete;
+};
+
+#endif
diff --git a/src/deps/skia/include/core/SkSize.h b/src/deps/skia/include/core/SkSize.h
new file mode 100644
index 000000000..79d673775
--- /dev/null
+++ b/src/deps/skia/include/core/SkSize.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkSize_DEFINED
+#define SkSize_DEFINED
+
+#include "include/core/SkScalar.h"
+
+struct SkISize {
+ int32_t fWidth;
+ int32_t fHeight;
+
+ static constexpr SkISize Make(int32_t w, int32_t h) { return {w, h}; }
+
+ static constexpr SkISize MakeEmpty() { return {0, 0}; }
+
+ void set(int32_t w, int32_t h) { *this = SkISize{w, h}; }
+
+ /** Returns true iff fWidth == 0 && fHeight == 0
+ */
+ bool isZero() const { return 0 == fWidth && 0 == fHeight; }
+
+ /** Returns true if either width or height are <= 0 */
+ bool isEmpty() const { return fWidth <= 0 || fHeight <= 0; }
+
+ /** Set the width and height to 0 */
+ void setEmpty() { fWidth = fHeight = 0; }
+
+ constexpr int32_t width() const { return fWidth; }
+ constexpr int32_t height() const { return fHeight; }
+
+ constexpr int64_t area() const { return fWidth * fHeight; }
+
+ bool equals(int32_t w, int32_t h) const { return fWidth == w && fHeight == h; }
+};
+
+static inline bool operator==(const SkISize& a, const SkISize& b) {
+ return a.fWidth == b.fWidth && a.fHeight == b.fHeight;
+}
+
+static inline bool operator!=(const SkISize& a, const SkISize& b) { return !(a == b); }
+
+///////////////////////////////////////////////////////////////////////////////
+
+struct SkSize {
+ SkScalar fWidth;
+ SkScalar fHeight;
+
+ static SkSize Make(SkScalar w, SkScalar h) { return {w, h}; }
+
+ static SkSize Make(const SkISize& src) {
+ return {SkIntToScalar(src.width()), SkIntToScalar(src.height())};
+ }
+
+ static SkSize MakeEmpty() { return {0, 0}; }
+
+ void set(SkScalar w, SkScalar h) { *this = SkSize{w, h}; }
+
+ /** Returns true iff fWidth == 0 && fHeight == 0
+ */
+ bool isZero() const { return 0 == fWidth && 0 == fHeight; }
+
+ /** Returns true if either width or height are <= 0 */
+ bool isEmpty() const { return fWidth <= 0 || fHeight <= 0; }
+
+ /** Set the width and height to 0 */
+ void setEmpty() { *this = SkSize{0, 0}; }
+
+ SkScalar width() const { return fWidth; }
+ SkScalar height() const { return fHeight; }
+
+ bool equals(SkScalar w, SkScalar h) const { return fWidth == w && fHeight == h; }
+
+ SkISize toRound() const { return {SkScalarRoundToInt(fWidth), SkScalarRoundToInt(fHeight)}; }
+
+ SkISize toCeil() const { return {SkScalarCeilToInt(fWidth), SkScalarCeilToInt(fHeight)}; }
+
+ SkISize toFloor() const { return {SkScalarFloorToInt(fWidth), SkScalarFloorToInt(fHeight)}; }
+};
+
+static inline bool operator==(const SkSize& a, const SkSize& b) {
+ return a.fWidth == b.fWidth && a.fHeight == b.fHeight;
+}
+
+static inline bool operator!=(const SkSize& a, const SkSize& b) { return !(a == b); }
+#endif
diff --git a/src/deps/skia/include/core/SkSpan.h b/src/deps/skia/include/core/SkSpan.h
new file mode 100644
index 000000000..b09ec867a
--- /dev/null
+++ b/src/deps/skia/include/core/SkSpan.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2018 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkSpan_DEFINED
+#define SkSpan_DEFINED
+
+#include <cstddef>
+#include <iterator>
+#include <type_traits>
+#include <utility>
+#include "include/private/SkTLogic.h"
+
+/**
+ * An SkSpan is a view of a contiguous collection of elements of type T. It can be directly
+ * constructed from a pointer and size. SkMakeSpan can be used to construct one from an array,
+ * or a container (like std::vector).
+ *
+ * With C++17, we could add template deduction guides that eliminate the need for SkMakeSpan:
+ * https://skia-review.googlesource.com/c/skia/+/320264
+ */
+template <typename T>
+class SkSpan {
+public:
+ constexpr SkSpan() : fPtr{nullptr}, fSize{0} {}
+ constexpr SkSpan(T* ptr, size_t size) : fPtr{ptr}, fSize{size} {
+ SkASSERT(size < kMaxSize);
+ }
+ template <typename U, typename = typename std::enable_if<std::is_same<const U, T>::value>::type>
+ constexpr SkSpan(const SkSpan<U>& that) : fPtr(that.data()), fSize{that.size()} {}
+ constexpr SkSpan(const SkSpan& o) = default;
+
+ constexpr SkSpan& operator=(const SkSpan& that) {
+ fPtr = that.fPtr;
+ fSize = that.fSize;
+ return *this;
+ }
+ constexpr T& operator [] (size_t i) const {
+ SkASSERT(i < this->size());
+ return fPtr[i];
+ }
+ constexpr T& front() const { return fPtr[0]; }
+ constexpr T& back() const { return fPtr[fSize - 1]; }
+ constexpr T* begin() const { return fPtr; }
+ constexpr T* end() const { return fPtr + fSize; }
+ constexpr auto rbegin() const { return std::make_reverse_iterator(this->end()); }
+ constexpr auto rend() const { return std::make_reverse_iterator(this->begin()); }
+ constexpr T* data() const { return this->begin(); }
+ constexpr size_t size() const { return fSize; }
+ constexpr bool empty() const { return fSize == 0; }
+ constexpr size_t size_bytes() const { return fSize * sizeof(T); }
+ constexpr SkSpan<T> first(size_t prefixLen) const {
+ SkASSERT(prefixLen <= this->size());
+ return SkSpan{fPtr, prefixLen};
+ }
+ constexpr SkSpan<T> last(size_t postfixLen) const {
+ SkASSERT(postfixLen <= this->size());
+ return SkSpan{fPtr + (this->size() - postfixLen), postfixLen};
+ }
+ constexpr SkSpan<T> subspan(size_t offset, size_t count) const {
+ SkASSERT(offset <= this->size());
+ SkASSERT(count <= this->size() - offset);
+ return SkSpan{fPtr + offset, count};
+ }
+
+private:
+ static constexpr size_t kMaxSize = std::numeric_limits<size_t>::max() / sizeof(T);
+ T* fPtr;
+ size_t fSize;
+};
+
+template <typename T, typename S> inline constexpr SkSpan<T> SkMakeSpan(T* p, S s) {
+ return SkSpan<T>{p, SkTo<size_t>(s)};
+}
+
+template <size_t N, typename T> inline constexpr SkSpan<T> SkMakeSpan(T (&a)[N]) {
+ return SkSpan<T>{a, N};
+}
+
+template <typename Container>
+inline auto SkMakeSpan(Container& c)
+ -> SkSpan<typename std::remove_reference<decltype(*(c.data()))>::type> {
+ return {c.data(), c.size()};
+}
+
+#endif // SkSpan_DEFINED
diff --git a/src/deps/skia/include/core/SkStream.h b/src/deps/skia/include/core/SkStream.h
new file mode 100644
index 000000000..32dfff25b
--- /dev/null
+++ b/src/deps/skia/include/core/SkStream.h
@@ -0,0 +1,524 @@
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkStream_DEFINED
+#define SkStream_DEFINED
+
+#include "include/core/SkData.h"
+#include "include/core/SkRefCnt.h"
+#include "include/core/SkScalar.h"
+#include "include/private/SkTo.h"
+
+#include <memory.h>
+
+class SkStream;
+class SkStreamRewindable;
+class SkStreamSeekable;
+class SkStreamAsset;
+class SkStreamMemory;
+
+/**
+ * SkStream -- abstraction for a source of bytes. Subclasses can be backed by
+ * memory, or a file, or something else.
+ *
+ * NOTE:
+ *
+ * Classic "streams" APIs are sort of async, in that on a request for N
+ * bytes, they may return fewer than N bytes on a given call, in which case
+ * the caller can "try again" to get more bytes, eventually (modulo an error)
+ * receiving their total N bytes.
+ *
+ * Skia streams behave differently. They are effectively synchronous, and will
+ * always return all N bytes of the request if possible. If they return fewer
+ * (the read() call returns the number of bytes read) then that means there is
+ * no more data (at EOF or hit an error). The caller should *not* call again
+ * in hopes of fulfilling more of the request.
+ */
+class SK_API SkStream {
+public:
+ virtual ~SkStream() {}
+ SkStream() {}
+
+ /**
+ * Attempts to open the specified file as a stream, returns nullptr on failure.
+ */
+ static std::unique_ptr<SkStreamAsset> MakeFromFile(const char path[]);
+
+ /** Reads or skips size number of bytes.
+ * If buffer == NULL, skip size bytes, return how many were skipped.
+ * If buffer != NULL, copy size bytes into buffer, return how many were copied.
+ * @param buffer when NULL skip size bytes, otherwise copy size bytes into buffer
+ * @param size the number of bytes to skip or copy
+ * @return the number of bytes actually read.
+ */
+ virtual size_t read(void* buffer, size_t size) = 0;
+
+ /** Skip size number of bytes.
+ * @return the actual number bytes that could be skipped.
+ */
+ size_t skip(size_t size) {
+ return this->read(nullptr, size);
+ }
+
+ /**
+ * Attempt to peek at size bytes.
+ * If this stream supports peeking, copy min(size, peekable bytes) into
+ * buffer, and return the number of bytes copied.
+ * If the stream does not support peeking, or cannot peek any bytes,
+ * return 0 and leave buffer unchanged.
+ * The stream is guaranteed to be in the same visible state after this
+ * call, regardless of success or failure.
+ * @param buffer Must not be NULL, and must be at least size bytes. Destination
+ * to copy bytes.
+ * @param size Number of bytes to copy.
+ * @return The number of bytes peeked/copied.
+ */
+ virtual size_t peek(void* /*buffer*/, size_t /*size*/) const { return 0; }
+
+ /** Returns true when all the bytes in the stream have been read.
+ * This may return true early (when there are no more bytes to be read)
+ * or late (after the first unsuccessful read).
+ */
+ virtual bool isAtEnd() const = 0;
+
+ bool SK_WARN_UNUSED_RESULT readS8(int8_t*);
+ bool SK_WARN_UNUSED_RESULT readS16(int16_t*);
+ bool SK_WARN_UNUSED_RESULT readS32(int32_t*);
+
+ bool SK_WARN_UNUSED_RESULT readU8(uint8_t* i) { return this->readS8((int8_t*)i); }
+ bool SK_WARN_UNUSED_RESULT readU16(uint16_t* i) { return this->readS16((int16_t*)i); }
+ bool SK_WARN_UNUSED_RESULT readU32(uint32_t* i) { return this->readS32((int32_t*)i); }
+
+ bool SK_WARN_UNUSED_RESULT readBool(bool* b) {
+ uint8_t i;
+ if (!this->readU8(&i)) { return false; }
+ *b = (i != 0);
+ return true;
+ }
+ bool SK_WARN_UNUSED_RESULT readScalar(SkScalar*);
+ bool SK_WARN_UNUSED_RESULT readPackedUInt(size_t*);
+
+//SkStreamRewindable
+ /** Rewinds to the beginning of the stream. Returns true if the stream is known
+ * to be at the beginning after this call returns.
+ */
+ virtual bool rewind() { return false; }
+
+ /** Duplicates this stream. If this cannot be done, returns NULL.
+ * The returned stream will be positioned at the beginning of its data.
+ */
+ std::unique_ptr<SkStream> duplicate() const {
+ return std::unique_ptr<SkStream>(this->onDuplicate());
+ }
+ /** Duplicates this stream. If this cannot be done, returns NULL.
+ * The returned stream will be positioned the same as this stream.
+ */
+ std::unique_ptr<SkStream> fork() const {
+ return std::unique_ptr<SkStream>(this->onFork());
+ }
+
+//SkStreamSeekable
+ /** Returns true if this stream can report it's current position. */
+ virtual bool hasPosition() const { return false; }
+ /** Returns the current position in the stream. If this cannot be done, returns 0. */
+ virtual size_t getPosition() const { return 0; }
+
+ /** Seeks to an absolute position in the stream. If this cannot be done, returns false.
+ * If an attempt is made to seek past the end of the stream, the position will be set
+ * to the end of the stream.
+ */
+ virtual bool seek(size_t /*position*/) { return false; }
+
+ /** Seeks to an relative offset in the stream. If this cannot be done, returns false.
+ * If an attempt is made to move to a position outside the stream, the position will be set
+ * to the closest point within the stream (beginning or end).
+ */
+ virtual bool move(long /*offset*/) { return false; }
+
+//SkStreamAsset
+ /** Returns true if this stream can report it's total length. */
+ virtual bool hasLength() const { return false; }
+ /** Returns the total length of the stream. If this cannot be done, returns 0. */
+ virtual size_t getLength() const { return 0; }
+
+//SkStreamMemory
+ /** Returns the starting address for the data. If this cannot be done, returns NULL. */
+ //TODO: replace with virtual const SkData* getData()
+ virtual const void* getMemoryBase() { return nullptr; }
+
+private:
+ virtual SkStream* onDuplicate() const { return nullptr; }
+ virtual SkStream* onFork() const { return nullptr; }
+
+ SkStream(SkStream&&) = delete;
+ SkStream(const SkStream&) = delete;
+ SkStream& operator=(SkStream&&) = delete;
+ SkStream& operator=(const SkStream&) = delete;
+};
+
+/** SkStreamRewindable is a SkStream for which rewind and duplicate are required. */
+class SK_API SkStreamRewindable : public SkStream {
+public:
+ bool rewind() override = 0;
+ std::unique_ptr<SkStreamRewindable> duplicate() const {
+ return std::unique_ptr<SkStreamRewindable>(this->onDuplicate());
+ }
+private:
+ SkStreamRewindable* onDuplicate() const override = 0;
+};
+
+/** SkStreamSeekable is a SkStreamRewindable for which position, seek, move, and fork are required. */
+class SK_API SkStreamSeekable : public SkStreamRewindable {
+public:
+ std::unique_ptr<SkStreamSeekable> duplicate() const {
+ return std::unique_ptr<SkStreamSeekable>(this->onDuplicate());
+ }
+
+ bool hasPosition() const override { return true; }
+ size_t getPosition() const override = 0;
+ bool seek(size_t position) override = 0;
+ bool move(long offset) override = 0;
+
+ std::unique_ptr<SkStreamSeekable> fork() const {
+ return std::unique_ptr<SkStreamSeekable>(this->onFork());
+ }
+private:
+ SkStreamSeekable* onDuplicate() const override = 0;
+ SkStreamSeekable* onFork() const override = 0;
+};
+
+/** SkStreamAsset is a SkStreamSeekable for which getLength is required. */
+class SK_API SkStreamAsset : public SkStreamSeekable {
+public:
+ bool hasLength() const override { return true; }
+ size_t getLength() const override = 0;
+
+ std::unique_ptr<SkStreamAsset> duplicate() const {
+ return std::unique_ptr<SkStreamAsset>(this->onDuplicate());
+ }
+ std::unique_ptr<SkStreamAsset> fork() const {
+ return std::unique_ptr<SkStreamAsset>(this->onFork());
+ }
+private:
+ SkStreamAsset* onDuplicate() const override = 0;
+ SkStreamAsset* onFork() const override = 0;
+};
+
+/** SkStreamMemory is a SkStreamAsset for which getMemoryBase is required. */
+class SK_API SkStreamMemory : public SkStreamAsset {
+public:
+ const void* getMemoryBase() override = 0;
+
+ std::unique_ptr<SkStreamMemory> duplicate() const {
+ return std::unique_ptr<SkStreamMemory>(this->onDuplicate());
+ }
+ std::unique_ptr<SkStreamMemory> fork() const {
+ return std::unique_ptr<SkStreamMemory>(this->onFork());
+ }
+private:
+ SkStreamMemory* onDuplicate() const override = 0;
+ SkStreamMemory* onFork() const override = 0;
+};
+
+class SK_API SkWStream {
+public:
+ virtual ~SkWStream();
+ SkWStream() {}
+
+ /** Called to write bytes to a SkWStream. Returns true on success
+ @param buffer the address of at least size bytes to be written to the stream
+ @param size The number of bytes in buffer to write to the stream
+ @return true on success
+ */
+ virtual bool write(const void* buffer, size_t size) = 0;
+ virtual void flush();
+
+ virtual size_t bytesWritten() const = 0;
+
+ // helpers
+
+ bool write8(U8CPU value) {
+ uint8_t v = SkToU8(value);
+ return this->write(&v, 1);
+ }
+ bool write16(U16CPU value) {
+ uint16_t v = SkToU16(value);
+ return this->write(&v, 2);
+ }
+ bool write32(uint32_t v) {
+ return this->write(&v, 4);
+ }
+
+ bool writeText(const char text[]) {
+ SkASSERT(text);
+ return this->write(text, strlen(text));
+ }
+
+ bool newline() { return this->write("\n", strlen("\n")); }
+
+ bool writeDecAsText(int32_t);
+ bool writeBigDecAsText(int64_t, int minDigits = 0);
+ bool writeHexAsText(uint32_t, int minDigits = 0);
+ bool writeScalarAsText(SkScalar);
+
+ bool writeBool(bool v) { return this->write8(v); }
+ bool writeScalar(SkScalar);
+ bool writePackedUInt(size_t);
+
+ bool writeStream(SkStream* input, size_t length);
+
+ /**
+ * This returns the number of bytes in the stream required to store
+ * 'value'.
+ */
+ static int SizeOfPackedUInt(size_t value);
+
+private:
+ SkWStream(const SkWStream&) = delete;
+ SkWStream& operator=(const SkWStream&) = delete;
+};
+
+class SK_API SkNullWStream : public SkWStream {
+public:
+ SkNullWStream() : fBytesWritten(0) {}
+
+ bool write(const void* , size_t n) override { fBytesWritten += n; return true; }
+ void flush() override {}
+ size_t bytesWritten() const override { return fBytesWritten; }
+
+private:
+ size_t fBytesWritten;
+};
+
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <stdio.h>
+
+/** A stream that wraps a C FILE* file stream. */
+class SK_API SkFILEStream : public SkStreamAsset {
+public:
+ /** Initialize the stream by calling sk_fopen on the specified path.
+ * This internal stream will be closed in the destructor.
+ */
+ explicit SkFILEStream(const char path[] = nullptr);
+
+ /** Initialize the stream with an existing C FILE stream.
+ * The current position of the C FILE stream will be considered the
+ * beginning of the SkFILEStream and the current seek end of the FILE will be the end.
+ * The C FILE stream will be closed in the destructor.
+ */
+ explicit SkFILEStream(FILE* file);
+
+ /** Initialize the stream with an existing C FILE stream.
+ * The current position of the C FILE stream will be considered the
+ * beginning of the SkFILEStream and size bytes later will be the end.
+ * The C FILE stream will be closed in the destructor.
+ */
+ explicit SkFILEStream(FILE* file, size_t size);
+
+ ~SkFILEStream() override;
+
+ static std::unique_ptr<SkFILEStream> Make(const char path[]) {
+ std::unique_ptr<SkFILEStream> stream(new SkFILEStream(path));
+ return stream->isValid() ? std::move(stream) : nullptr;
+ }
+
+ /** Returns true if the current path could be opened. */
+ bool isValid() const { return fFILE != nullptr; }
+
+ /** Close this SkFILEStream. */
+ void close();
+
+ size_t read(void* buffer, size_t size) override;
+ bool isAtEnd() const override;
+
+ bool rewind() override;
+ std::unique_ptr<SkStreamAsset> duplicate() const {
+ return std::unique_ptr<SkStreamAsset>(this->onDuplicate());
+ }
+
+ size_t getPosition() const override;
+ bool seek(size_t position) override;
+ bool move(long offset) override;
+
+ std::unique_ptr<SkStreamAsset> fork() const {
+ return std::unique_ptr<SkStreamAsset>(this->onFork());
+ }
+
+ size_t getLength() const override;
+
+private:
+ explicit SkFILEStream(FILE*, size_t size, size_t start);
+ explicit SkFILEStream(std::shared_ptr<FILE>, size_t end, size_t start);
+ explicit SkFILEStream(std::shared_ptr<FILE>, size_t end, size_t start, size_t current);
+
+ SkStreamAsset* onDuplicate() const override;
+ SkStreamAsset* onFork() const override;
+
+ std::shared_ptr<FILE> fFILE;
+ // My own council will I keep on sizes and offsets.
+ // These are seek positions in the underling FILE, not offsets into the stream.
+ size_t fEnd;
+ size_t fStart;
+ size_t fCurrent;
+
+ using INHERITED = SkStreamAsset;
+};
+
+class SK_API SkMemoryStream : public SkStreamMemory {
+public:
+ SkMemoryStream();
+
+ /** We allocate (and free) the memory. Write to it via getMemoryBase() */
+ SkMemoryStream(size_t length);
+
+ /** If copyData is true, the stream makes a private copy of the data. */
+ SkMemoryStream(const void* data, size_t length, bool copyData = false);
+
+ /** Creates the stream to read from the specified data */
+ SkMemoryStream(sk_sp<SkData> data);
+
+ /** Returns a stream with a copy of the input data. */
+ static std::unique_ptr<SkMemoryStream> MakeCopy(const void* data, size_t length);
+
+ /** Returns a stream with a bare pointer reference to the input data. */
+ static std::unique_ptr<SkMemoryStream> MakeDirect(const void* data, size_t length);
+
+ /** Returns a stream with a shared reference to the input data. */
+ static std::unique_ptr<SkMemoryStream> Make(sk_sp<SkData> data);
+
+ /** Resets the stream to the specified data and length,
+ just like the constructor.
+ if copyData is true, the stream makes a private copy of the data
+ */
+ virtual void setMemory(const void* data, size_t length,
+ bool copyData = false);
+ /** Replace any memory buffer with the specified buffer. The caller
+ must have allocated data with sk_malloc or sk_realloc, since it
+ will be freed with sk_free.
+ */
+ void setMemoryOwned(const void* data, size_t length);
+
+ sk_sp<SkData> asData() const { return fData; }
+ void setData(sk_sp<SkData> data);
+
+ void skipToAlign4();
+ const void* getAtPos();
+
+ size_t read(void* buffer, size_t size) override;
+ bool isAtEnd() const override;
+
+ size_t peek(void* buffer, size_t size) const override;
+
+ bool rewind() override;
+
+ std::unique_ptr<SkMemoryStream> duplicate() const {
+ return std::unique_ptr<SkMemoryStream>(this->onDuplicate());
+ }
+
+ size_t getPosition() const override;
+ bool seek(size_t position) override;
+ bool move(long offset) override;
+
+ std::unique_ptr<SkMemoryStream> fork() const {
+ return std::unique_ptr<SkMemoryStream>(this->onFork());
+ }
+
+ size_t getLength() const override;
+
+ const void* getMemoryBase() override;
+
+private:
+ SkMemoryStream* onDuplicate() const override;
+ SkMemoryStream* onFork() const override;
+
+ sk_sp<SkData> fData;
+ size_t fOffset;
+
+ using INHERITED = SkStreamMemory;
+};
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+
+class SK_API SkFILEWStream : public SkWStream {
+public:
+ SkFILEWStream(const char path[]);
+ ~SkFILEWStream() override;
+
+ /** Returns true if the current path could be opened.
+ */
+ bool isValid() const { return fFILE != nullptr; }
+
+ bool write(const void* buffer, size_t size) override;
+ void flush() override;
+ void fsync();
+ size_t bytesWritten() const override;
+
+private:
+ FILE* fFILE;
+
+ using INHERITED = SkWStream;
+};
+
+class SK_API SkDynamicMemoryWStream : public SkWStream {
+public:
+ SkDynamicMemoryWStream() = default;
+ SkDynamicMemoryWStream(SkDynamicMemoryWStream&&);
+ SkDynamicMemoryWStream& operator=(SkDynamicMemoryWStream&&);
+ ~SkDynamicMemoryWStream() override;
+
+ bool write(const void* buffer, size_t size) override;
+ size_t bytesWritten() const override;
+
+ bool read(void* buffer, size_t offset, size_t size);
+
+ /** More efficient version of read(dst, 0, bytesWritten()). */
+ void copyTo(void* dst) const;
+ bool writeToStream(SkWStream* dst) const;
+
+ /** Equivalent to copyTo() followed by reset(), but may save memory use. */
+ void copyToAndReset(void* dst);
+
+ /** Equivalent to writeToStream() followed by reset(), but may save memory use. */
+ bool writeToAndReset(SkWStream* dst);
+
+ /** Equivalent to writeToStream() followed by reset(), but may save memory use.
+ When the dst is also a SkDynamicMemoryWStream, the implementation is constant time. */
+ bool writeToAndReset(SkDynamicMemoryWStream* dst);
+
+ /** Prepend this stream to dst, resetting this. */
+ void prependToAndReset(SkDynamicMemoryWStream* dst);
+
+ /** Return the contents as SkData, and then reset the stream. */
+ sk_sp<SkData> detachAsData();
+
+ /** Reset, returning a reader stream with the current content. */
+ std::unique_ptr<SkStreamAsset> detachAsStream();
+
+ /** Reset the stream to its original, empty, state. */
+ void reset();
+ void padToAlign4();
+private:
+ struct Block;
+ Block* fHead = nullptr;
+ Block* fTail = nullptr;
+ size_t fBytesWrittenBeforeTail = 0;
+
+#ifdef SK_DEBUG
+ void validate() const;
+#else
+ void validate() const {}
+#endif
+
+ // For access to the Block type.
+ friend class SkBlockMemoryStream;
+ friend class SkBlockMemoryRefCnt;
+
+ using INHERITED = SkWStream;
+};
+
+#endif
diff --git a/src/deps/skia/include/core/SkString.h b/src/deps/skia/include/core/SkString.h
new file mode 100644
index 000000000..5576e7422
--- /dev/null
+++ b/src/deps/skia/include/core/SkString.h
@@ -0,0 +1,302 @@
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkString_DEFINED
+#define SkString_DEFINED
+
+#include "include/core/SkRefCnt.h"
+#include "include/core/SkScalar.h"
+#include "include/core/SkTypes.h"
+#include "include/private/SkMalloc.h"
+#include "include/private/SkTArray.h"
+#include "include/private/SkTo.h"
+
+#include <stdarg.h>
+#include <string.h>
+#include <atomic>
+#include <string>
+
+namespace skstd {
+ class string_view;
+}
+
+/* Some helper functions for C strings */
+static inline bool SkStrStartsWith(const char string[], const char prefixStr[]) {
+ SkASSERT(string);
+ SkASSERT(prefixStr);
+ return !strncmp(string, prefixStr, strlen(prefixStr));
+}
+static inline bool SkStrStartsWith(const char string[], const char prefixChar) {
+ SkASSERT(string);
+ return (prefixChar == *string);
+}
+
+bool SkStrEndsWith(const char string[], const char suffixStr[]);
+bool SkStrEndsWith(const char string[], const char suffixChar);
+
+int SkStrStartsWithOneOf(const char string[], const char prefixes[]);
+
+static inline int SkStrFind(const char string[], const char substring[]) {
+ const char *first = strstr(string, substring);
+ if (nullptr == first) return -1;
+ return SkToInt(first - &string[0]);
+}
+
+static inline int SkStrFindLastOf(const char string[], const char subchar) {
+ const char* last = strrchr(string, subchar);
+ if (nullptr == last) return -1;
+ return SkToInt(last - &string[0]);
+}
+
+static inline bool SkStrContains(const char string[], const char substring[]) {
+ SkASSERT(string);
+ SkASSERT(substring);
+ return (-1 != SkStrFind(string, substring));
+}
+static inline bool SkStrContains(const char string[], const char subchar) {
+ SkASSERT(string);
+ char tmp[2];
+ tmp[0] = subchar;
+ tmp[1] = '\0';
+ return (-1 != SkStrFind(string, tmp));
+}
+
+/*
+ * The SkStrAppend... methods will write into the provided buffer, assuming it is large enough.
+ * Each method has an associated const (e.g. kSkStrAppendU32_MaxSize) which will be the largest
+ * value needed for that method's buffer.
+ *
+ * char storage[kSkStrAppendU32_MaxSize];
+ * SkStrAppendU32(storage, value);
+ *
+ * Note : none of the SkStrAppend... methods write a terminating 0 to their buffers. Instead,
+ * the methods return the ptr to the end of the written part of the buffer. This can be used
+ * to compute the length, and/or know where to write a 0 if that is desired.
+ *
+ * char storage[kSkStrAppendU32_MaxSize + 1];
+ * char* stop = SkStrAppendU32(storage, value);
+ * size_t len = stop - storage;
+ * *stop = 0; // valid, since storage was 1 byte larger than the max.
+ */
+
+static constexpr int kSkStrAppendU32_MaxSize = 10;
+char* SkStrAppendU32(char buffer[], uint32_t);
+static constexpr int kSkStrAppendU64_MaxSize = 20;
+char* SkStrAppendU64(char buffer[], uint64_t, int minDigits);
+
+static constexpr int kSkStrAppendS32_MaxSize = kSkStrAppendU32_MaxSize + 1;
+char* SkStrAppendS32(char buffer[], int32_t);
+static constexpr int kSkStrAppendS64_MaxSize = kSkStrAppendU64_MaxSize + 1;
+char* SkStrAppendS64(char buffer[], int64_t, int minDigits);
+
+/**
+ * Floats have at most 8 significant digits, so we limit our %g to that.
+ * However, the total string could be 15 characters: -1.2345678e-005
+ *
+ * In theory we should only expect up to 2 digits for the exponent, but on
+ * some platforms we have seen 3 (as in the example above).
+ */
+static constexpr int kSkStrAppendScalar_MaxSize = 15;
+
+/**
+ * Write the scalar in decimal format into buffer, and return a pointer to
+ * the next char after the last one written. Note: a terminating 0 is not
+ * written into buffer, which must be at least kSkStrAppendScalar_MaxSize.
+ * Thus if the caller wants to add a 0 at the end, buffer must be at least
+ * kSkStrAppendScalar_MaxSize + 1 bytes large.
+ */
+char* SkStrAppendScalar(char buffer[], SkScalar);
+
+/** \class SkString
+
+ Light weight class for managing strings. Uses reference
+ counting to make string assignments and copies very fast
+ with no extra RAM cost. Assumes UTF8 encoding.
+*/
+class SK_API SkString {
+public:
+ SkString();
+ explicit SkString(size_t len);
+ explicit SkString(const char text[]);
+ SkString(const char text[], size_t len);
+ SkString(const SkString&);
+ SkString(SkString&&);
+ explicit SkString(const std::string&);
+ explicit SkString(skstd::string_view);
+ ~SkString();
+
+ bool isEmpty() const { return 0 == fRec->fLength; }
+ size_t size() const { return (size_t) fRec->fLength; }
+ const char* c_str() const { return fRec->data(); }
+ char operator[](size_t n) const { return this->c_str()[n]; }
+
+ bool equals(const SkString&) const;
+ bool equals(const char text[]) const;
+ bool equals(const char text[], size_t len) const;
+
+ bool startsWith(const char prefixStr[]) const {
+ return SkStrStartsWith(fRec->data(), prefixStr);
+ }
+ bool startsWith(const char prefixChar) const {
+ return SkStrStartsWith(fRec->data(), prefixChar);
+ }
+ bool endsWith(const char suffixStr[]) const {
+ return SkStrEndsWith(fRec->data(), suffixStr);
+ }
+ bool endsWith(const char suffixChar) const {
+ return SkStrEndsWith(fRec->data(), suffixChar);
+ }
+ bool contains(const char substring[]) const {
+ return SkStrContains(fRec->data(), substring);
+ }
+ bool contains(const char subchar) const {
+ return SkStrContains(fRec->data(), subchar);
+ }
+ int find(const char substring[]) const {
+ return SkStrFind(fRec->data(), substring);
+ }
+ int findLastOf(const char subchar) const {
+ return SkStrFindLastOf(fRec->data(), subchar);
+ }
+
+ friend bool operator==(const SkString& a, const SkString& b) {
+ return a.equals(b);
+ }
+ friend bool operator!=(const SkString& a, const SkString& b) {
+ return !a.equals(b);
+ }
+
+ // these methods edit the string
+
+ SkString& operator=(const SkString&);
+ SkString& operator=(SkString&&);
+ SkString& operator=(const char text[]);
+
+ char* writable_str();
+ char& operator[](size_t n) { return this->writable_str()[n]; }
+
+ void reset();
+ /** String contents are preserved on resize. (For destructive resize, `set(nullptr, length)`.)
+ * `resize` automatically reserves an extra byte at the end of the buffer for a null terminator.
+ */
+ void resize(size_t len);
+ void set(const SkString& src) { *this = src; }
+ void set(const char text[]);
+ void set(const char text[], size_t len);
+
+ void insert(size_t offset, const SkString& src) { this->insert(offset, src.c_str(), src.size()); }
+ void insert(size_t offset, const char text[]);
+ void insert(size_t offset, const char text[], size_t len);
+ void insertUnichar(size_t offset, SkUnichar);
+ void insertS32(size_t offset, int32_t value);
+ void insertS64(size_t offset, int64_t value, int minDigits = 0);
+ void insertU32(size_t offset, uint32_t value);
+ void insertU64(size_t offset, uint64_t value, int minDigits = 0);
+ void insertHex(size_t offset, uint32_t value, int minDigits = 0);
+ void insertScalar(size_t offset, SkScalar);
+
+ void append(const SkString& str) { this->insert((size_t)-1, str); }
+ void append(const char text[]) { this->insert((size_t)-1, text); }
+ void append(const char text[], size_t len) { this->insert((size_t)-1, text, len); }
+ void appendUnichar(SkUnichar uni) { this->insertUnichar((size_t)-1, uni); }
+ void appendS32(int32_t value) { this->insertS32((size_t)-1, value); }
+ void appendS64(int64_t value, int minDigits = 0) { this->insertS64((size_t)-1, value, minDigits); }
+ void appendU32(uint32_t value) { this->insertU32((size_t)-1, value); }
+ void appendU64(uint64_t value, int minDigits = 0) { this->insertU64((size_t)-1, value, minDigits); }
+ void appendHex(uint32_t value, int minDigits = 0) { this->insertHex((size_t)-1, value, minDigits); }
+ void appendScalar(SkScalar value) { this->insertScalar((size_t)-1, value); }
+
+ void prepend(const SkString& str) { this->insert(0, str); }
+ void prepend(const char text[]) { this->insert(0, text); }
+ void prepend(const char text[], size_t len) { this->insert(0, text, len); }
+ void prependUnichar(SkUnichar uni) { this->insertUnichar(0, uni); }
+ void prependS32(int32_t value) { this->insertS32(0, value); }
+ void prependS64(int32_t value, int minDigits = 0) { this->insertS64(0, value, minDigits); }
+ void prependHex(uint32_t value, int minDigits = 0) { this->insertHex(0, value, minDigits); }
+ void prependScalar(SkScalar value) { this->insertScalar((size_t)-1, value); }
+
+ void printf(const char format[], ...) SK_PRINTF_LIKE(2, 3);
+ void printVAList(const char format[], va_list);
+ void appendf(const char format[], ...) SK_PRINTF_LIKE(2, 3);
+ void appendVAList(const char format[], va_list);
+ void prependf(const char format[], ...) SK_PRINTF_LIKE(2, 3);
+ void prependVAList(const char format[], va_list);
+
+ void remove(size_t offset, size_t length);
+
+ SkString& operator+=(const SkString& s) { this->append(s); return *this; }
+ SkString& operator+=(const char text[]) { this->append(text); return *this; }
+ SkString& operator+=(const char c) { this->append(&c, 1); return *this; }
+
+ /**
+ * Swap contents between this and other. This function is guaranteed
+ * to never fail or throw.
+ */
+ void swap(SkString& other);
+
+private:
+ struct Rec {
+ public:
+ constexpr Rec(uint32_t len, int32_t refCnt) : fLength(len), fRefCnt(refCnt) {}
+ static sk_sp<Rec> Make(const char text[], size_t len);
+ char* data() { return fBeginningOfData; }
+ const char* data() const { return fBeginningOfData; }
+ void ref() const;
+ void unref() const;
+ bool unique() const;
+#ifdef SK_DEBUG
+ int32_t getRefCnt() const;
+#endif
+ uint32_t fLength; // logically size_t, but we want it to stay 32 bits
+
+ private:
+ mutable std::atomic<int32_t> fRefCnt;
+ char fBeginningOfData[1] = {'\0'};
+
+ // Ensure the unsized delete is called.
+ void operator delete(void* p) { ::operator delete(p); }
+ };
+ sk_sp<Rec> fRec;
+
+#ifdef SK_DEBUG
+ const SkString& validate() const;
+#else
+ const SkString& validate() const { return *this; }
+#endif
+
+ static const Rec gEmptyRec;
+};
+
+/// Creates a new string and writes into it using a printf()-style format.
+SkString SkStringPrintf(const char* format, ...) SK_PRINTF_LIKE(1, 2);
+/// This makes it easier to write a caller as a VAR_ARGS function where the format string is
+/// optional.
+static inline SkString SkStringPrintf() { return SkString(); }
+
+static inline void swap(SkString& a, SkString& b) {
+ a.swap(b);
+}
+
+enum SkStrSplitMode {
+ // Strictly return all results. If the input is ",," and the separator is ',' this will return
+ // an array of three empty strings.
+ kStrict_SkStrSplitMode,
+
+ // Only nonempty results will be added to the results. Multiple separators will be
+ // coalesced. Separators at the beginning and end of the input will be ignored. If the input is
+ // ",," and the separator is ',', this will return an empty vector.
+ kCoalesce_SkStrSplitMode
+};
+
+// Split str on any characters in delimiters into out. (Think, strtok with a sane API.)
+void SkStrSplit(const char* str, const char* delimiters, SkStrSplitMode splitMode,
+ SkTArray<SkString>* out);
+inline void SkStrSplit(const char* str, const char* delimiters, SkTArray<SkString>* out) {
+ SkStrSplit(str, delimiters, kCoalesce_SkStrSplitMode, out);
+}
+
+#endif
diff --git a/src/deps/skia/include/core/SkStringView.h b/src/deps/skia/include/core/SkStringView.h
new file mode 100644
index 000000000..184e681d2
--- /dev/null
+++ b/src/deps/skia/include/core/SkStringView.h
@@ -0,0 +1,185 @@
+/*
+ * Copyright 2021 Google LLC.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkStringView_DEFINED
+#define SkStringView_DEFINED
+
+#include <algorithm>
+#include <cstring>
+#include <string>
+
+namespace skstd {
+
+class string_view {
+public:
+ using value_type = char;
+ using traits_type = std::char_traits<value_type>;
+ using const_pointer = const value_type*;
+ using const_reference = const value_type&;
+ using iterator = const_pointer;
+ using const_iterator = iterator;
+ using size_type = size_t;
+ static constexpr size_type npos = size_type(-1);
+
+ constexpr string_view()
+ : fData(nullptr)
+ , fLength(0) {}
+
+ constexpr string_view(const string_view&) = default;
+
+ constexpr string_view(const_pointer data, size_type length)
+ : fData(data)
+ , fLength(length) {}
+
+ string_view(const_pointer data)
+ : string_view(data, strlen(data)) {}
+
+ string_view(const std::string& str)
+ : string_view(str.data(), str.length()) {}
+
+ constexpr string_view& operator=(const string_view&) = default;
+
+ constexpr iterator begin() const {
+ return fData;
+ }
+
+ constexpr iterator end() const {
+ return fData + fLength;
+ }
+
+ constexpr const_reference operator[](size_type idx) const {
+ return fData[idx];
+ }
+
+ constexpr const_reference front() const {
+ return fData[0];
+ }
+
+ constexpr const_reference back() const {
+ return fData[fLength - 1];
+ }
+
+ constexpr const_pointer data() const {
+ return fData;
+ }
+
+ constexpr size_type size() const {
+ return fLength;
+ }
+
+ constexpr size_type length() const {
+ return fLength;
+ }
+
+ constexpr bool empty() const {
+ return fLength == 0;
+ }
+
+ constexpr bool starts_with(string_view s) const {
+ if (s.length() > fLength) {
+ return false;
+ }
+ return s.length() == 0 || !memcmp(fData, s.fData, s.length());
+ }
+
+ constexpr bool starts_with(value_type c) const {
+ return !this->empty() && this->front() == c;
+ }
+
+ constexpr bool ends_with(string_view s) const {
+ if (s.length() > fLength) {
+ return false;
+ }
+ return s.length() == 0 || !memcmp(this->end() - s.length(), s.fData, s.length());
+ }
+
+ constexpr bool ends_with(value_type c) const {
+ return !this->empty() && this->back() == c;
+ }
+
+ size_type find(string_view needle, size_type pos = 0) const {
+ if (needle.length() == 0) {
+ return 0;
+ }
+ if (this->length() < needle.length()) {
+ return npos;
+ }
+ const char* match = nullptr;
+ const char* start = this->data() + pos;
+ const char* end = start + this->length() - needle.length() + 1;
+ while ((match = (const char*)(memchr(start, needle[0], (size_t)(end - start))))) {
+ if (!memcmp(match, needle.data(), needle.length())) {
+ return (size_type)(match - this->data());
+ } else {
+ start = match + 1;
+ }
+ }
+ return npos;
+ }
+
+ bool contains(string_view needle) const {
+ return this->find(needle) != npos;
+ }
+
+ constexpr string_view substr(size_type pos = 0, size_type count = npos) const {
+ if (pos > fLength) {
+ return {};
+ }
+ return string_view{fData + pos, std::min(count, fLength - pos)};
+ }
+
+ constexpr void swap(string_view& other) {
+ const_pointer tempData = fData;
+ fData = other.fData;
+ other.fData = tempData;
+
+ size_type tempLength = fLength;
+ fLength = other.fLength;
+ other.fLength = tempLength;
+ }
+
+ constexpr void remove_prefix(size_type n) {
+ fData += n;
+ fLength -= n;
+ }
+
+ constexpr void remove_suffix(size_type n) {
+ fLength -= n;
+ }
+
+private:
+ const_pointer fData;
+ size_type fLength;
+};
+
+bool operator==(string_view left, string_view right);
+
+bool operator!=(string_view left, string_view right);
+
+bool operator<(string_view left, string_view right);
+
+bool operator<=(string_view left, string_view right);
+
+bool operator>(string_view left, string_view right);
+
+bool operator>=(string_view left, string_view right);
+
+} // namespace skstd
+
+namespace std {
+ template<> struct hash<skstd::string_view> {
+ size_t operator()(const skstd::string_view& s) const {
+ size_t result = 0;
+ for (auto iter = s.begin(); iter != s.end(); ++iter) {
+ result = result * 101 + (size_t) *iter;
+ }
+ return result;
+ }
+ };
+} // namespace std
+
+#endif
diff --git a/src/deps/skia/include/core/SkStrokeRec.h b/src/deps/skia/include/core/SkStrokeRec.h
new file mode 100644
index 000000000..b4796fcbf
--- /dev/null
+++ b/src/deps/skia/include/core/SkStrokeRec.h
@@ -0,0 +1,154 @@
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkStrokeRec_DEFINED
+#define SkStrokeRec_DEFINED
+
+#include "include/core/SkPaint.h"
+#include "include/private/SkMacros.h"
+
+class SkPath;
+
+SK_BEGIN_REQUIRE_DENSE
+class SK_API SkStrokeRec {
+public:
+ enum InitStyle {
+ kHairline_InitStyle,
+ kFill_InitStyle
+ };
+ SkStrokeRec(InitStyle style);
+ SkStrokeRec(const SkPaint&, SkPaint::Style, SkScalar resScale = 1);
+ explicit SkStrokeRec(const SkPaint&, SkScalar resScale = 1);
+
+ enum Style {
+ kHairline_Style,
+ kFill_Style,
+ kStroke_Style,
+ kStrokeAndFill_Style
+ };
+
+ static constexpr int kStyleCount = kStrokeAndFill_Style + 1;
+
+ Style getStyle() const;
+ SkScalar getWidth() const { return fWidth; }
+ SkScalar getMiter() const { return fMiterLimit; }
+ SkPaint::Cap getCap() const { return (SkPaint::Cap)fCap; }
+ SkPaint::Join getJoin() const { return (SkPaint::Join)fJoin; }
+
+ bool isHairlineStyle() const {
+ return kHairline_Style == this->getStyle();
+ }
+
+ bool isFillStyle() const {
+ return kFill_Style == this->getStyle();
+ }
+
+ void setFillStyle();
+ void setHairlineStyle();
+ /**
+ * Specify the strokewidth, and optionally if you want stroke + fill.
+ * Note, if width==0, then this request is taken to mean:
+ * strokeAndFill==true -> new style will be Fill
+ * strokeAndFill==false -> new style will be Hairline
+ */
+ void setStrokeStyle(SkScalar width, bool strokeAndFill = false);
+
+ void setStrokeParams(SkPaint::Cap cap, SkPaint::Join join, SkScalar miterLimit) {
+ fCap = cap;
+ fJoin = join;
+ fMiterLimit = miterLimit;
+ }
+
+ SkScalar getResScale() const {
+ return fResScale;
+ }
+
+ void setResScale(SkScalar rs) {
+ SkASSERT(rs > 0 && SkScalarIsFinite(rs));
+ fResScale = rs;
+ }
+
+ /**
+ * Returns true if this specifes any thick stroking, i.e. applyToPath()
+ * will return true.
+ */
+ bool needToApply() const {
+ Style style = this->getStyle();
+ return (kStroke_Style == style) || (kStrokeAndFill_Style == style);
+ }
+
+ /**
+ * Apply these stroke parameters to the src path, returning the result
+ * in dst.
+ *
+ * If there was no change (i.e. style == hairline or fill) this returns
+ * false and dst is unchanged. Otherwise returns true and the result is
+ * stored in dst.
+ *
+ * src and dst may be the same path.
+ */
+ bool applyToPath(SkPath* dst, const SkPath& src) const;
+
+ /**
+ * Apply these stroke parameters to a paint.
+ */
+ void applyToPaint(SkPaint* paint) const;
+
+ /**
+ * Gives a conservative value for the outset that should applied to a
+ * geometries bounds to account for any inflation due to applying this
+ * strokeRec to the geometry.
+ */
+ SkScalar getInflationRadius() const;
+
+ /**
+ * Equivalent to:
+ * SkStrokeRec rec(paint, style);
+ * rec.getInflationRadius();
+ * This does not account for other effects on the paint (i.e. path
+ * effect).
+ */
+ static SkScalar GetInflationRadius(const SkPaint&, SkPaint::Style);
+
+ static SkScalar GetInflationRadius(SkPaint::Join, SkScalar miterLimit, SkPaint::Cap,
+ SkScalar strokeWidth);
+
+ /**
+ * Compare if two SkStrokeRecs have an equal effect on a path.
+ * Equal SkStrokeRecs produce equal paths. Equality of produced
+ * paths does not take the ResScale parameter into account.
+ */
+ bool hasEqualEffect(const SkStrokeRec& other) const {
+ if (!this->needToApply()) {
+ return this->getStyle() == other.getStyle();
+ }
+ return fWidth == other.fWidth &&
+ (fJoin != SkPaint::kMiter_Join || fMiterLimit == other.fMiterLimit) &&
+ fCap == other.fCap &&
+ fJoin == other.fJoin &&
+ fStrokeAndFill == other.fStrokeAndFill;
+ }
+
+private:
+ void init(const SkPaint&, SkPaint::Style, SkScalar resScale);
+
+ SkScalar fResScale;
+ SkScalar fWidth;
+ SkScalar fMiterLimit;
+ // The following three members are packed together into a single u32.
+ // This is to avoid unnecessary padding and ensure binary equality for
+ // hashing (because the padded areas might contain garbage values).
+ //
+ // fCap and fJoin are larger than needed to avoid having to initialize
+ // any pad values
+ uint32_t fCap : 16; // SkPaint::Cap
+ uint32_t fJoin : 15; // SkPaint::Join
+ uint32_t fStrokeAndFill : 1; // bool
+};
+SK_END_REQUIRE_DENSE
+
+#endif
diff --git a/src/deps/skia/include/core/SkSurface.h b/src/deps/skia/include/core/SkSurface.h
new file mode 100644
index 000000000..3718aaaab
--- /dev/null
+++ b/src/deps/skia/include/core/SkSurface.h
@@ -0,0 +1,1079 @@
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkSurface_DEFINED
+#define SkSurface_DEFINED
+
+#include "include/core/SkImage.h"
+#include "include/core/SkPixmap.h"
+#include "include/core/SkRefCnt.h"
+#include "include/core/SkSurfaceProps.h"
+
+#if SK_SUPPORT_GPU
+#include "include/gpu/GrTypes.h"
+#endif
+
+#if defined(SK_BUILD_FOR_ANDROID) && __ANDROID_API__ >= 26
+#include <android/hardware_buffer.h>
+#endif
+
+#ifdef SK_METAL
+#include "include/gpu/mtl/GrMtlTypes.h"
+#endif
+
+class SkCanvas;
+class SkDeferredDisplayList;
+class SkPaint;
+class SkSurfaceCharacterization;
+class GrBackendRenderTarget;
+class GrBackendSemaphore;
+class GrBackendSurfaceMutableState;
+class GrBackendTexture;
+class GrDirectContext;
+class GrRecordingContext;
+class GrRenderTarget;
+enum GrSurfaceOrigin: int;
+
+/** \class SkSurface
+ SkSurface is responsible for managing the pixels that a canvas draws into. The pixels can be
+ allocated either in CPU memory (a raster surface) or on the GPU (a GrRenderTarget surface).
+ SkSurface takes care of allocating a SkCanvas that will draw into the surface. Call
+ surface->getCanvas() to use that canvas (but don't delete it, it is owned by the surface).
+ SkSurface always has non-zero dimensions. If there is a request for a new surface, and either
+ of the requested dimensions are zero, then nullptr will be returned.
+*/
+class SK_API SkSurface : public SkRefCnt {
+public:
+
+ /** Allocates raster SkSurface. SkCanvas returned by SkSurface draws directly into pixels.
+
+ SkSurface is returned if all parameters are valid.
+ Valid parameters include:
+ info dimensions are greater than zero;
+ info contains SkColorType and SkAlphaType supported by raster surface;
+ pixels is not nullptr;
+ rowBytes is large enough to contain info width pixels of SkColorType.
+
+ Pixel buffer size should be info height times computed rowBytes.
+ Pixels are not initialized.
+ To access pixels after drawing, peekPixels() or readPixels().
+
+ @param imageInfo width, height, SkColorType, SkAlphaType, SkColorSpace,
+ of raster surface; width and height must be greater than zero
+ @param pixels pointer to destination pixels buffer
+ @param rowBytes interval from one SkSurface row to the next
+ @param surfaceProps LCD striping orientation and setting for device independent fonts;
+ may be nullptr
+ @return SkSurface if all parameters are valid; otherwise, nullptr
+ */
+ static sk_sp<SkSurface> MakeRasterDirect(const SkImageInfo& imageInfo, void* pixels,
+ size_t rowBytes,
+ const SkSurfaceProps* surfaceProps = nullptr);
+
+ static sk_sp<SkSurface> MakeRasterDirect(const SkPixmap& pm,
+ const SkSurfaceProps* props = nullptr) {
+ return MakeRasterDirect(pm.info(), pm.writable_addr(), pm.rowBytes(), props);
+ }
+
+ /** Allocates raster SkSurface. SkCanvas returned by SkSurface draws directly into pixels.
+ releaseProc is called with pixels and context when SkSurface is deleted.
+
+ SkSurface is returned if all parameters are valid.
+ Valid parameters include:
+ info dimensions are greater than zero;
+ info contains SkColorType and SkAlphaType supported by raster surface;
+ pixels is not nullptr;
+ rowBytes is large enough to contain info width pixels of SkColorType.
+
+ Pixel buffer size should be info height times computed rowBytes.
+ Pixels are not initialized.
+ To access pixels after drawing, call flush() or peekPixels().
+
+ @param imageInfo width, height, SkColorType, SkAlphaType, SkColorSpace,
+ of raster surface; width and height must be greater than zero
+ @param pixels pointer to destination pixels buffer
+ @param rowBytes interval from one SkSurface row to the next
+ @param releaseProc called when SkSurface is deleted; may be nullptr
+ @param context passed to releaseProc; may be nullptr
+ @param surfaceProps LCD striping orientation and setting for device independent fonts;
+ may be nullptr
+ @return SkSurface if all parameters are valid; otherwise, nullptr
+ */
+ static sk_sp<SkSurface> MakeRasterDirectReleaseProc(const SkImageInfo& imageInfo, void* pixels,
+ size_t rowBytes,
+ void (*releaseProc)(void* pixels, void* context),
+ void* context, const SkSurfaceProps* surfaceProps = nullptr);
+
+ /** Allocates raster SkSurface. SkCanvas returned by SkSurface draws directly into pixels.
+ Allocates and zeroes pixel memory. Pixel memory size is imageInfo.height() times
+ rowBytes, or times imageInfo.minRowBytes() if rowBytes is zero.
+ Pixel memory is deleted when SkSurface is deleted.
+
+ SkSurface is returned if all parameters are valid.
+ Valid parameters include:
+ info dimensions are greater than zero;
+ info contains SkColorType and SkAlphaType supported by raster surface;
+ rowBytes is large enough to contain info width pixels of SkColorType, or is zero.
+
+ If rowBytes is zero, a suitable value will be chosen internally.
+
+ @param imageInfo width, height, SkColorType, SkAlphaType, SkColorSpace,
+ of raster surface; width and height must be greater than zero
+ @param rowBytes interval from one SkSurface row to the next; may be zero
+ @param surfaceProps LCD striping orientation and setting for device independent fonts;
+ may be nullptr
+ @return SkSurface if all parameters are valid; otherwise, nullptr
+ */
+ static sk_sp<SkSurface> MakeRaster(const SkImageInfo& imageInfo, size_t rowBytes,
+ const SkSurfaceProps* surfaceProps);
+
+ /** Allocates raster SkSurface. SkCanvas returned by SkSurface draws directly into pixels.
+ Allocates and zeroes pixel memory. Pixel memory size is imageInfo.height() times
+ imageInfo.minRowBytes().
+ Pixel memory is deleted when SkSurface is deleted.
+
+ SkSurface is returned if all parameters are valid.
+ Valid parameters include:
+ info dimensions are greater than zero;
+ info contains SkColorType and SkAlphaType supported by raster surface.
+
+ @param imageInfo width, height, SkColorType, SkAlphaType, SkColorSpace,
+ of raster surface; width and height must be greater than zero
+ @param props LCD striping orientation and setting for device independent fonts;
+ may be nullptr
+ @return SkSurface if all parameters are valid; otherwise, nullptr
+ */
+ static sk_sp<SkSurface> MakeRaster(const SkImageInfo& imageInfo,
+ const SkSurfaceProps* props = nullptr) {
+ return MakeRaster(imageInfo, 0, props);
+ }
+
+ /** Allocates raster SkSurface. SkCanvas returned by SkSurface draws directly into pixels.
+ Allocates and zeroes pixel memory. Pixel memory size is height times width times
+ four. Pixel memory is deleted when SkSurface is deleted.
+
+ Internally, sets SkImageInfo to width, height, native color type, and
+ kPremul_SkAlphaType.
+
+ SkSurface is returned if width and height are greater than zero.
+
+ Use to create SkSurface that matches SkPMColor, the native pixel arrangement on
+ the platform. SkSurface drawn to output device skips converting its pixel format.
+
+ @param width pixel column count; must be greater than zero
+ @param height pixel row count; must be greater than zero
+ @param surfaceProps LCD striping orientation and setting for device independent
+ fonts; may be nullptr
+ @return SkSurface if all parameters are valid; otherwise, nullptr
+ */
+ static sk_sp<SkSurface> MakeRasterN32Premul(int width, int height,
+ const SkSurfaceProps* surfaceProps = nullptr);
+
+ /** Caller data passed to RenderTarget/TextureReleaseProc; may be nullptr. */
+ typedef void* ReleaseContext;
+
+ /** User function called when supplied render target may be deleted. */
+ typedef void (*RenderTargetReleaseProc)(ReleaseContext releaseContext);
+
+ /** User function called when supplied texture may be deleted. */
+ typedef void (*TextureReleaseProc)(ReleaseContext releaseContext);
+
+ /** Wraps a GPU-backed texture into SkSurface. Caller must ensure the texture is
+ valid for the lifetime of returned SkSurface. If sampleCnt greater than zero,
+ creates an intermediate MSAA SkSurface which is used for drawing backendTexture.
+
+ SkSurface is returned if all parameters are valid. backendTexture is valid if
+ its pixel configuration agrees with colorSpace and context; for instance, if
+ backendTexture has an sRGB configuration, then context must support sRGB,
+ and colorSpace must be present. Further, backendTexture width and height must
+ not exceed context capabilities, and the context must be able to support
+ back-end textures.
+
+ Upon success textureReleaseProc is called when it is safe to delete the texture in the
+ backend API (accounting only for use of the texture by this surface). If SkSurface creation
+ fails textureReleaseProc is called before this function returns.
+
+ If SK_SUPPORT_GPU is defined as zero, has no effect and returns nullptr.
+
+ @param context GPU context
+ @param backendTexture texture residing on GPU
+ @param sampleCnt samples per pixel, or 0 to disable full scene anti-aliasing
+ @param colorSpace range of colors; may be nullptr
+ @param surfaceProps LCD striping orientation and setting for device independent
+ fonts; may be nullptr
+ @param textureReleaseProc function called when texture can be released
+ @param releaseContext state passed to textureReleaseProc
+ @return SkSurface if all parameters are valid; otherwise, nullptr
+ */
+ static sk_sp<SkSurface> MakeFromBackendTexture(GrRecordingContext* context,
+ const GrBackendTexture& backendTexture,
+ GrSurfaceOrigin origin, int sampleCnt,
+ SkColorType colorType,
+ sk_sp<SkColorSpace> colorSpace,
+ const SkSurfaceProps* surfaceProps,
+ TextureReleaseProc textureReleaseProc = nullptr,
+ ReleaseContext releaseContext = nullptr);
+
+ /** Wraps a GPU-backed buffer into SkSurface. Caller must ensure backendRenderTarget
+ is valid for the lifetime of returned SkSurface.
+
+ SkSurface is returned if all parameters are valid. backendRenderTarget is valid if
+ its pixel configuration agrees with colorSpace and context; for instance, if
+ backendRenderTarget has an sRGB configuration, then context must support sRGB,
+ and colorSpace must be present. Further, backendRenderTarget width and height must
+ not exceed context capabilities, and the context must be able to support
+ back-end render targets.
+
+ Upon success releaseProc is called when it is safe to delete the render target in the
+ backend API (accounting only for use of the render target by this surface). If SkSurface
+ creation fails releaseProc is called before this function returns.
+
+ If SK_SUPPORT_GPU is defined as zero, has no effect and returns nullptr.
+
+ @param context GPU context
+ @param backendRenderTarget GPU intermediate memory buffer
+ @param colorSpace range of colors
+ @param surfaceProps LCD striping orientation and setting for device independent
+ fonts; may be nullptr
+ @param releaseProc function called when backendRenderTarget can be released
+ @param releaseContext state passed to releaseProc
+ @return SkSurface if all parameters are valid; otherwise, nullptr
+ */
+ static sk_sp<SkSurface> MakeFromBackendRenderTarget(GrRecordingContext* context,
+ const GrBackendRenderTarget& backendRenderTarget,
+ GrSurfaceOrigin origin,
+ SkColorType colorType,
+ sk_sp<SkColorSpace> colorSpace,
+ const SkSurfaceProps* surfaceProps,
+ RenderTargetReleaseProc releaseProc = nullptr,
+ ReleaseContext releaseContext = nullptr);
+
+ /** Returns SkSurface on GPU indicated by context. Allocates memory for
+ pixels, based on the width, height, and SkColorType in SkImageInfo. budgeted
+ selects whether allocation for pixels is tracked by context. imageInfo
+ describes the pixel format in SkColorType, and transparency in
+ SkAlphaType, and color matching in SkColorSpace.
+
+ sampleCount requests the number of samples per pixel.
+ Pass zero to disable multi-sample anti-aliasing. The request is rounded
+ up to the next supported count, or rounded down if it is larger than the
+ maximum supported count.
+
+ surfaceOrigin pins either the top-left or the bottom-left corner to the origin.
+
+ shouldCreateWithMips hints that SkImage returned by makeImageSnapshot() is mip map.
+
+ If SK_SUPPORT_GPU is defined as zero, has no effect and returns nullptr.
+
+ @param context GPU context
+ @param imageInfo width, height, SkColorType, SkAlphaType, SkColorSpace;
+ width, or height, or both, may be zero
+ @param sampleCount samples per pixel, or 0 to disable full scene anti-aliasing
+ @param surfaceProps LCD striping orientation and setting for device independent
+ fonts; may be nullptr
+ @param shouldCreateWithMips hint that SkSurface will host mip map images
+ @return SkSurface if all parameters are valid; otherwise, nullptr
+ */
+ static sk_sp<SkSurface> MakeRenderTarget(GrRecordingContext* context, SkBudgeted budgeted,
+ const SkImageInfo& imageInfo,
+ int sampleCount, GrSurfaceOrigin surfaceOrigin,
+ const SkSurfaceProps* surfaceProps,
+ bool shouldCreateWithMips = false);
+
+ /** Returns SkSurface on GPU indicated by context. Allocates memory for
+ pixels, based on the width, height, and SkColorType in SkImageInfo. budgeted
+ selects whether allocation for pixels is tracked by context. imageInfo
+ describes the pixel format in SkColorType, and transparency in
+ SkAlphaType, and color matching in SkColorSpace.
+
+ sampleCount requests the number of samples per pixel.
+ Pass zero to disable multi-sample anti-aliasing. The request is rounded
+ up to the next supported count, or rounded down if it is larger than the
+ maximum supported count.
+
+ SkSurface bottom-left corner is pinned to the origin.
+
+ @param context GPU context
+ @param imageInfo width, height, SkColorType, SkAlphaType, SkColorSpace,
+ of raster surface; width, or height, or both, may be zero
+ @param sampleCount samples per pixel, or 0 to disable multi-sample anti-aliasing
+ @param surfaceProps LCD striping orientation and setting for device independent
+ fonts; may be nullptr
+ @return SkSurface if all parameters are valid; otherwise, nullptr
+ */
+ static sk_sp<SkSurface> MakeRenderTarget(GrRecordingContext* context, SkBudgeted budgeted,
+ const SkImageInfo& imageInfo, int sampleCount,
+ const SkSurfaceProps* surfaceProps) {
+#if SK_SUPPORT_GPU
+ return MakeRenderTarget(context, budgeted, imageInfo, sampleCount,
+ kBottomLeft_GrSurfaceOrigin, surfaceProps);
+#else
+ // TODO(kjlubick, scroggo) Remove this once Android is updated.
+ return nullptr;
+#endif
+ }
+
+ /** Returns SkSurface on GPU indicated by context. Allocates memory for
+ pixels, based on the width, height, and SkColorType in SkImageInfo. budgeted
+ selects whether allocation for pixels is tracked by context. imageInfo
+ describes the pixel format in SkColorType, and transparency in
+ SkAlphaType, and color matching in SkColorSpace.
+
+ SkSurface bottom-left corner is pinned to the origin.
+
+ @param context GPU context
+ @param imageInfo width, height, SkColorType, SkAlphaType, SkColorSpace,
+ of raster surface; width, or height, or both, may be zero
+ @return SkSurface if all parameters are valid; otherwise, nullptr
+ */
+ static sk_sp<SkSurface> MakeRenderTarget(GrRecordingContext* context, SkBudgeted budgeted,
+ const SkImageInfo& imageInfo) {
+#if SK_SUPPORT_GPU
+ if (!imageInfo.width() || !imageInfo.height()) {
+ return nullptr;
+ }
+ return MakeRenderTarget(context, budgeted, imageInfo, 0, kBottomLeft_GrSurfaceOrigin,
+ nullptr);
+#else
+ // TODO(kjlubick, scroggo) Remove this once Android is updated.
+ return nullptr;
+#endif
+ }
+
+ /** Returns SkSurface on GPU indicated by context that is compatible with the provided
+ characterization. budgeted selects whether allocation for pixels is tracked by context.
+
+ @param context GPU context
+ @param characterization description of the desired SkSurface
+ @return SkSurface if all parameters are valid; otherwise, nullptr
+ */
+ static sk_sp<SkSurface> MakeRenderTarget(GrRecordingContext* context,
+ const SkSurfaceCharacterization& characterization,
+ SkBudgeted budgeted);
+
+
+#if defined(SK_BUILD_FOR_ANDROID) && __ANDROID_API__ >= 26
+ /** Private.
+ Creates SkSurface from Android hardware buffer.
+ Returned SkSurface takes a reference on the buffer. The ref on the buffer will be released
+ when the SkSurface is destroyed and there is no pending work on the GPU involving the
+ buffer.
+
+ Only available on Android, when __ANDROID_API__ is defined to be 26 or greater.
+
+ Currently this is only supported for buffers that can be textured as well as rendered to.
+ In other words that must have both AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT and
+ AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE usage bits.
+
+ @param context GPU context
+ @param hardwareBuffer AHardwareBuffer Android hardware buffer
+ @param colorSpace range of colors; may be nullptr
+ @param surfaceProps LCD striping orientation and setting for device independent
+ fonts; may be nullptr
+ @param fromWindow Whether or not the AHardwareBuffer is part of an Android Window.
+ Currently only used with Vulkan backend.
+ @return created SkSurface, or nullptr
+ */
+ static sk_sp<SkSurface> MakeFromAHardwareBuffer(GrDirectContext* context,
+ AHardwareBuffer* hardwareBuffer,
+ GrSurfaceOrigin origin,
+ sk_sp<SkColorSpace> colorSpace,
+ const SkSurfaceProps* surfaceProps
+#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
+ , bool fromWindow = false
+#endif // SK_BUILD_FOR_ANDROID_FRAMEWORK
+ );
+#endif
+
+#ifdef SK_METAL
+ /** Creates SkSurface from CAMetalLayer.
+ Returned SkSurface takes a reference on the CAMetalLayer. The ref on the layer will be
+ released when the SkSurface is destroyed.
+
+ Only available when Metal API is enabled.
+
+ Will grab the current drawable from the layer and use its texture as a backendRT to
+ create a renderable surface.
+
+ @param context GPU context
+ @param layer GrMTLHandle (expected to be a CAMetalLayer*)
+ @param sampleCnt samples per pixel, or 0 to disable full scene anti-aliasing
+ @param colorSpace range of colors; may be nullptr
+ @param surfaceProps LCD striping orientation and setting for device independent
+ fonts; may be nullptr
+ @param drawable Pointer to drawable to be filled in when this surface is
+ instantiated; may not be nullptr
+ @return created SkSurface, or nullptr
+ */
+ static sk_sp<SkSurface> MakeFromCAMetalLayer(GrRecordingContext* context,
+ GrMTLHandle layer,
+ GrSurfaceOrigin origin,
+ int sampleCnt,
+ SkColorType colorType,
+ sk_sp<SkColorSpace> colorSpace,
+ const SkSurfaceProps* surfaceProps,
+ GrMTLHandle* drawable)
+ SK_API_AVAILABLE_CA_METAL_LAYER;
+
+ /** Creates SkSurface from MTKView.
+ Returned SkSurface takes a reference on the MTKView. The ref on the layer will be
+ released when the SkSurface is destroyed.
+
+ Only available when Metal API is enabled.
+
+ Will grab the current drawable from the layer and use its texture as a backendRT to
+ create a renderable surface.
+
+ @param context GPU context
+ @param layer GrMTLHandle (expected to be a MTKView*)
+ @param sampleCnt samples per pixel, or 0 to disable full scene anti-aliasing
+ @param colorSpace range of colors; may be nullptr
+ @param surfaceProps LCD striping orientation and setting for device independent
+ fonts; may be nullptr
+ @return created SkSurface, or nullptr
+ */
+ static sk_sp<SkSurface> MakeFromMTKView(GrRecordingContext* context,
+ GrMTLHandle mtkView,
+ GrSurfaceOrigin origin,
+ int sampleCnt,
+ SkColorType colorType,
+ sk_sp<SkColorSpace> colorSpace,
+ const SkSurfaceProps* surfaceProps)
+ SK_API_AVAILABLE(macos(10.11), ios(9.0));
+#endif
+
+ /** Is this surface compatible with the provided characterization?
+
+ This method can be used to determine if an existing SkSurface is a viable destination
+ for an SkDeferredDisplayList.
+
+ @param characterization The characterization for which a compatibility check is desired
+ @return true if this surface is compatible with the characterization;
+ false otherwise
+ */
+ bool isCompatible(const SkSurfaceCharacterization& characterization) const;
+
+ /** Returns SkSurface without backing pixels. Drawing to SkCanvas returned from SkSurface
+ has no effect. Calling makeImageSnapshot() on returned SkSurface returns nullptr.
+
+ @param width one or greater
+ @param height one or greater
+ @return SkSurface if width and height are positive; otherwise, nullptr
+
+ example: https://fiddle.skia.org/c/@Surface_MakeNull
+ */
+ static sk_sp<SkSurface> MakeNull(int width, int height);
+
+ /** Returns pixel count in each row; may be zero or greater.
+
+ @return number of pixel columns
+ */
+ int width() const { return fWidth; }
+
+ /** Returns pixel row count; may be zero or greater.
+
+ @return number of pixel rows
+ */
+ int height() const { return fHeight; }
+
+ /** Returns an ImageInfo describing the surface.
+ */
+ SkImageInfo imageInfo();
+
+ /** Returns unique value identifying the content of SkSurface. Returned value changes
+ each time the content changes. Content is changed by drawing, or by calling
+ notifyContentWillChange().
+
+ @return unique content identifier
+
+ example: https://fiddle.skia.org/c/@Surface_notifyContentWillChange
+ */
+ uint32_t generationID();
+
+ /** \enum SkSurface::ContentChangeMode
+ ContentChangeMode members are parameters to notifyContentWillChange().
+ */
+ enum ContentChangeMode {
+ kDiscard_ContentChangeMode, //!< discards surface on change
+ kRetain_ContentChangeMode, //!< preserves surface on change
+ };
+
+ /** Notifies that SkSurface contents will be changed by code outside of Skia.
+ Subsequent calls to generationID() return a different value.
+
+ TODO: Can kRetain_ContentChangeMode be deprecated?
+
+ example: https://fiddle.skia.org/c/@Surface_notifyContentWillChange
+ */
+ void notifyContentWillChange(ContentChangeMode mode);
+
+ /** Returns the recording context being used by the SkSurface.
+
+ @return the recording context, if available; nullptr otherwise
+ */
+ GrRecordingContext* recordingContext();
+
+#if SK_SUPPORT_GPU
+ enum BackendHandleAccess {
+ kFlushRead_BackendHandleAccess, //!< back-end object is readable
+ kFlushWrite_BackendHandleAccess, //!< back-end object is writable
+ kDiscardWrite_BackendHandleAccess, //!< back-end object must be overwritten
+ };
+
+ /** Deprecated.
+ */
+ static const BackendHandleAccess kFlushRead_TextureHandleAccess =
+ kFlushRead_BackendHandleAccess;
+
+ /** Deprecated.
+ */
+ static const BackendHandleAccess kFlushWrite_TextureHandleAccess =
+ kFlushWrite_BackendHandleAccess;
+
+ /** Deprecated.
+ */
+ static const BackendHandleAccess kDiscardWrite_TextureHandleAccess =
+ kDiscardWrite_BackendHandleAccess;
+
+ /** Retrieves the back-end texture. If SkSurface has no back-end texture, an invalid
+ object is returned. Call GrBackendTexture::isValid to determine if the result
+ is valid.
+
+ The returned GrBackendTexture should be discarded if the SkSurface is drawn to or deleted.
+
+ @return GPU texture reference; invalid on failure
+ */
+ GrBackendTexture getBackendTexture(BackendHandleAccess backendHandleAccess);
+
+ /** Retrieves the back-end render target. If SkSurface has no back-end render target, an invalid
+ object is returned. Call GrBackendRenderTarget::isValid to determine if the result
+ is valid.
+
+ The returned GrBackendRenderTarget should be discarded if the SkSurface is drawn to
+ or deleted.
+
+ @return GPU render target reference; invalid on failure
+ */
+ GrBackendRenderTarget getBackendRenderTarget(BackendHandleAccess backendHandleAccess);
+
+ /** If the surface was made via MakeFromBackendTexture then it's backing texture may be
+ substituted with a different texture. The contents of the previous backing texture are
+ copied into the new texture. SkCanvas state is preserved. The original sample count is
+ used. The GrBackendFormat and dimensions of replacement texture must match that of
+ the original.
+
+ Upon success textureReleaseProc is called when it is safe to delete the texture in the
+ backend API (accounting only for use of the texture by this surface). If SkSurface creation
+ fails textureReleaseProc is called before this function returns.
+
+ @param backendTexture the new backing texture for the surface
+ @param mode Retain or discard current Content
+ @param textureReleaseProc function called when texture can be released
+ @param releaseContext state passed to textureReleaseProc
+ */
+ bool replaceBackendTexture(const GrBackendTexture& backendTexture,
+ GrSurfaceOrigin origin,
+ ContentChangeMode mode = kRetain_ContentChangeMode,
+ TextureReleaseProc textureReleaseProc = nullptr,
+ ReleaseContext releaseContext = nullptr);
+#endif
+
+ /** Returns SkCanvas that draws into SkSurface. Subsequent calls return the same SkCanvas.
+ SkCanvas returned is managed and owned by SkSurface, and is deleted when SkSurface
+ is deleted.
+
+ @return drawing SkCanvas for SkSurface
+
+ example: https://fiddle.skia.org/c/@Surface_getCanvas
+ */
+ SkCanvas* getCanvas();
+
+ /** Returns a compatible SkSurface, or nullptr. Returned SkSurface contains
+ the same raster, GPU, or null properties as the original. Returned SkSurface
+ does not share the same pixels.
+
+ Returns nullptr if imageInfo width or height are zero, or if imageInfo
+ is incompatible with SkSurface.
+
+ @param imageInfo width, height, SkColorType, SkAlphaType, SkColorSpace,
+ of SkSurface; width and height must be greater than zero
+ @return compatible SkSurface or nullptr
+
+ example: https://fiddle.skia.org/c/@Surface_makeSurface
+ */
+ sk_sp<SkSurface> makeSurface(const SkImageInfo& imageInfo);
+
+ /** Calls makeSurface(ImageInfo) with the same ImageInfo as this surface, but with the
+ * specified width and height.
+ */
+ sk_sp<SkSurface> makeSurface(int width, int height);
+
+ /** Returns SkImage capturing SkSurface contents. Subsequent drawing to SkSurface contents
+ are not captured. SkImage allocation is accounted for if SkSurface was created with
+ SkBudgeted::kYes.
+
+ @return SkImage initialized with SkSurface contents
+
+ example: https://fiddle.skia.org/c/@Surface_makeImageSnapshot
+ */
+ sk_sp<SkImage> makeImageSnapshot();
+
+ /**
+ * Like the no-parameter version, this returns an image of the current surface contents.
+ * This variant takes a rectangle specifying the subset of the surface that is of interest.
+ * These bounds will be sanitized before being used.
+ * - If bounds extends beyond the surface, it will be trimmed to just the intersection of
+ * it and the surface.
+ * - If bounds does not intersect the surface, then this returns nullptr.
+ * - If bounds == the surface, then this is the same as calling the no-parameter variant.
+
+ example: https://fiddle.skia.org/c/@Surface_makeImageSnapshot_2
+ */
+ sk_sp<SkImage> makeImageSnapshot(const SkIRect& bounds);
+
+ /** Draws SkSurface contents to canvas, with its top-left corner at (x, y).
+
+ If SkPaint paint is not nullptr, apply SkColorFilter, alpha, SkImageFilter, and SkBlendMode.
+
+ @param canvas SkCanvas drawn into
+ @param x horizontal offset in SkCanvas
+ @param y vertical offset in SkCanvas
+ @param sampling what technique to use when sampling the surface pixels
+ @param paint SkPaint containing SkBlendMode, SkColorFilter, SkImageFilter,
+ and so on; or nullptr
+
+ example: https://fiddle.skia.org/c/@Surface_draw
+ */
+ void draw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkSamplingOptions& sampling,
+ const SkPaint* paint);
+
+ void draw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint = nullptr) {
+ this->draw(canvas, x, y, SkSamplingOptions(), paint);
+ }
+
+ /** Copies SkSurface pixel address, row bytes, and SkImageInfo to SkPixmap, if address
+ is available, and returns true. If pixel address is not available, return
+ false and leave SkPixmap unchanged.
+
+ pixmap contents become invalid on any future change to SkSurface.
+
+ @param pixmap storage for pixel state if pixels are readable; otherwise, ignored
+ @return true if SkSurface has direct access to pixels
+
+ example: https://fiddle.skia.org/c/@Surface_peekPixels
+ */
+ bool peekPixels(SkPixmap* pixmap);
+
+ /** Copies SkRect of pixels to dst.
+
+ Source SkRect corners are (srcX, srcY) and SkSurface (width(), height()).
+ Destination SkRect corners are (0, 0) and (dst.width(), dst.height()).
+ Copies each readable pixel intersecting both rectangles, without scaling,
+ converting to dst.colorType() and dst.alphaType() if required.
+
+ Pixels are readable when SkSurface is raster, or backed by a GPU.
+
+ The destination pixel storage must be allocated by the caller.
+
+ Pixel values are converted only if SkColorType and SkAlphaType
+ do not match. Only pixels within both source and destination rectangles
+ are copied. dst contents outside SkRect intersection are unchanged.
+
+ Pass negative values for srcX or srcY to offset pixels across or down destination.
+
+ Does not copy, and returns false if:
+ - Source and destination rectangles do not intersect.
+ - SkPixmap pixels could not be allocated.
+ - dst.rowBytes() is too small to contain one row of pixels.
+
+ @param dst storage for pixels copied from SkSurface
+ @param srcX offset into readable pixels on x-axis; may be negative
+ @param srcY offset into readable pixels on y-axis; may be negative
+ @return true if pixels were copied
+
+ example: https://fiddle.skia.org/c/@Surface_readPixels
+ */
+ bool readPixels(const SkPixmap& dst, int srcX, int srcY);
+
+ /** Copies SkRect of pixels from SkCanvas into dstPixels.
+
+ Source SkRect corners are (srcX, srcY) and SkSurface (width(), height()).
+ Destination SkRect corners are (0, 0) and (dstInfo.width(), dstInfo.height()).
+ Copies each readable pixel intersecting both rectangles, without scaling,
+ converting to dstInfo.colorType() and dstInfo.alphaType() if required.
+
+ Pixels are readable when SkSurface is raster, or backed by a GPU.
+
+ The destination pixel storage must be allocated by the caller.
+
+ Pixel values are converted only if SkColorType and SkAlphaType
+ do not match. Only pixels within both source and destination rectangles
+ are copied. dstPixels contents outside SkRect intersection are unchanged.
+
+ Pass negative values for srcX or srcY to offset pixels across or down destination.
+
+ Does not copy, and returns false if:
+ - Source and destination rectangles do not intersect.
+ - SkSurface pixels could not be converted to dstInfo.colorType() or dstInfo.alphaType().
+ - dstRowBytes is too small to contain one row of pixels.
+
+ @param dstInfo width, height, SkColorType, and SkAlphaType of dstPixels
+ @param dstPixels storage for pixels; dstInfo.height() times dstRowBytes, or larger
+ @param dstRowBytes size of one destination row; dstInfo.width() times pixel size, or larger
+ @param srcX offset into readable pixels on x-axis; may be negative
+ @param srcY offset into readable pixels on y-axis; may be negative
+ @return true if pixels were copied
+ */
+ bool readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
+ int srcX, int srcY);
+
+ /** Copies SkRect of pixels from SkSurface into bitmap.
+
+ Source SkRect corners are (srcX, srcY) and SkSurface (width(), height()).
+ Destination SkRect corners are (0, 0) and (bitmap.width(), bitmap.height()).
+ Copies each readable pixel intersecting both rectangles, without scaling,
+ converting to bitmap.colorType() and bitmap.alphaType() if required.
+
+ Pixels are readable when SkSurface is raster, or backed by a GPU.
+
+ The destination pixel storage must be allocated by the caller.
+
+ Pixel values are converted only if SkColorType and SkAlphaType
+ do not match. Only pixels within both source and destination rectangles
+ are copied. dst contents outside SkRect intersection are unchanged.
+
+ Pass negative values for srcX or srcY to offset pixels across or down destination.
+
+ Does not copy, and returns false if:
+ - Source and destination rectangles do not intersect.
+ - SkSurface pixels could not be converted to dst.colorType() or dst.alphaType().
+ - dst pixels could not be allocated.
+ - dst.rowBytes() is too small to contain one row of pixels.
+
+ @param dst storage for pixels copied from SkSurface
+ @param srcX offset into readable pixels on x-axis; may be negative
+ @param srcY offset into readable pixels on y-axis; may be negative
+ @return true if pixels were copied
+
+ example: https://fiddle.skia.org/c/@Surface_readPixels_3
+ */
+ bool readPixels(const SkBitmap& dst, int srcX, int srcY);
+
+ using AsyncReadResult = SkImage::AsyncReadResult;
+
+ /** Client-provided context that is passed to client-provided ReadPixelsContext. */
+ using ReadPixelsContext = void*;
+
+ /** Client-provided callback to asyncRescaleAndReadPixels() or
+ asyncRescaleAndReadPixelsYUV420() that is called when read result is ready or on failure.
+ */
+ using ReadPixelsCallback = void(ReadPixelsContext, std::unique_ptr<const AsyncReadResult>);
+
+ /** Controls the gamma that rescaling occurs in for asyncRescaleAndReadPixels() and
+ asyncRescaleAndReadPixelsYUV420().
+ */
+ using RescaleGamma = SkImage::RescaleGamma;
+ using RescaleMode = SkImage::RescaleMode;
+
+ /** Makes surface pixel data available to caller, possibly asynchronously. It can also rescale
+ the surface pixels.
+
+ Currently asynchronous reads are only supported on the GPU backend and only when the
+ underlying 3D API supports transfer buffers and CPU/GPU synchronization primitives. In all
+ other cases this operates synchronously.
+
+ Data is read from the source sub-rectangle, is optionally converted to a linear gamma, is
+ rescaled to the size indicated by 'info', is then converted to the color space, color type,
+ and alpha type of 'info'. A 'srcRect' that is not contained by the bounds of the surface
+ causes failure.
+
+ When the pixel data is ready the caller's ReadPixelsCallback is called with a
+ AsyncReadResult containing pixel data in the requested color type, alpha type, and color
+ space. The AsyncReadResult will have count() == 1. Upon failure the callback is called
+ with nullptr for AsyncReadResult. For a GPU surface this flushes work but a submit must
+ occur to guarantee a finite time before the callback is called.
+
+ The data is valid for the lifetime of AsyncReadResult with the exception that if the
+ SkSurface is GPU-backed the data is immediately invalidated if the context is abandoned
+ or destroyed.
+
+ @param info info of the requested pixels
+ @param srcRect subrectangle of surface to read
+ @param rescaleGamma controls whether rescaling is done in the surface's gamma or whether
+ the source data is transformed to a linear gamma before rescaling.
+ @param rescaleMode controls the technique of the rescaling
+ @param callback function to call with result of the read
+ @param context passed to callback
+ */
+ void asyncRescaleAndReadPixels(const SkImageInfo& info,
+ const SkIRect& srcRect,
+ RescaleGamma rescaleGamma,
+ RescaleMode rescaleMode,
+ ReadPixelsCallback callback,
+ ReadPixelsContext context);
+
+ /**
+ Similar to asyncRescaleAndReadPixels but performs an additional conversion to YUV. The
+ RGB->YUV conversion is controlled by 'yuvColorSpace'. The YUV data is returned as three
+ planes ordered y, u, v. The u and v planes are half the width and height of the resized
+ rectangle. The y, u, and v values are single bytes. Currently this fails if 'dstSize'
+ width and height are not even. A 'srcRect' that is not contained by the bounds of the
+ surface causes failure.
+
+ When the pixel data is ready the caller's ReadPixelsCallback is called with a
+ AsyncReadResult containing the planar data. The AsyncReadResult will have count() == 3.
+ Upon failure the callback is called with nullptr for AsyncReadResult. For a GPU surface this
+ flushes work but a submit must occur to guarantee a finite time before the callback is
+ called.
+
+ The data is valid for the lifetime of AsyncReadResult with the exception that if the
+ SkSurface is GPU-backed the data is immediately invalidated if the context is abandoned
+ or destroyed.
+
+ @param yuvColorSpace The transformation from RGB to YUV. Applied to the resized image
+ after it is converted to dstColorSpace.
+ @param dstColorSpace The color space to convert the resized image to, after rescaling.
+ @param srcRect The portion of the surface to rescale and convert to YUV planes.
+ @param dstSize The size to rescale srcRect to
+ @param rescaleGamma controls whether rescaling is done in the surface's gamma or whether
+ the source data is transformed to a linear gamma before rescaling.
+ @param rescaleMode controls the sampling technique of the rescaling
+ @param callback function to call with the planar read result
+ @param context passed to callback
+ */
+ void asyncRescaleAndReadPixelsYUV420(SkYUVColorSpace yuvColorSpace,
+ sk_sp<SkColorSpace> dstColorSpace,
+ const SkIRect& srcRect,
+ const SkISize& dstSize,
+ RescaleGamma rescaleGamma,
+ RescaleMode rescaleMode,
+ ReadPixelsCallback callback,
+ ReadPixelsContext context);
+
+ /** Copies SkRect of pixels from the src SkPixmap to the SkSurface.
+
+ Source SkRect corners are (0, 0) and (src.width(), src.height()).
+ Destination SkRect corners are (dstX, dstY) and
+ (dstX + Surface width(), dstY + Surface height()).
+
+ Copies each readable pixel intersecting both rectangles, without scaling,
+ converting to SkSurface colorType() and SkSurface alphaType() if required.
+
+ @param src storage for pixels to copy to SkSurface
+ @param dstX x-axis position relative to SkSurface to begin copy; may be negative
+ @param dstY y-axis position relative to SkSurface to begin copy; may be negative
+
+ example: https://fiddle.skia.org/c/@Surface_writePixels
+ */
+ void writePixels(const SkPixmap& src, int dstX, int dstY);
+
+ /** Copies SkRect of pixels from the src SkBitmap to the SkSurface.
+
+ Source SkRect corners are (0, 0) and (src.width(), src.height()).
+ Destination SkRect corners are (dstX, dstY) and
+ (dstX + Surface width(), dstY + Surface height()).
+
+ Copies each readable pixel intersecting both rectangles, without scaling,
+ converting to SkSurface colorType() and SkSurface alphaType() if required.
+
+ @param src storage for pixels to copy to SkSurface
+ @param dstX x-axis position relative to SkSurface to begin copy; may be negative
+ @param dstY y-axis position relative to SkSurface to begin copy; may be negative
+
+ example: https://fiddle.skia.org/c/@Surface_writePixels_2
+ */
+ void writePixels(const SkBitmap& src, int dstX, int dstY);
+
+ /** Returns SkSurfaceProps for surface.
+
+ @return LCD striping orientation and setting for device independent fonts
+ */
+ const SkSurfaceProps& props() const { return fProps; }
+
+ /** Call to ensure all reads/writes of the surface have been issued to the underlying 3D API.
+ Skia will correctly order its own draws and pixel operations. This must to be used to ensure
+ correct ordering when the surface backing store is accessed outside Skia (e.g. direct use of
+ the 3D API or a windowing system). GrDirectContext has additional flush and submit methods
+ that apply to all surfaces and images created from a GrDirectContext. This is equivalent to
+ calling SkSurface::flush with a default GrFlushInfo followed by
+ GrDirectContext::submit(syncCpu).
+ */
+ void flushAndSubmit(bool syncCpu = false);
+
+ enum class BackendSurfaceAccess {
+ kNoAccess, //!< back-end object will not be used by client
+ kPresent, //!< back-end surface will be used for presenting to screen
+ };
+
+#if SK_SUPPORT_GPU
+ /** Issues pending SkSurface commands to the GPU-backed API objects and resolves any SkSurface
+ MSAA. A call to GrDirectContext::submit is always required to ensure work is actually sent
+ to the gpu. Some specific API details:
+ GL: Commands are actually sent to the driver, but glFlush is never called. Thus some
+ sync objects from the flush will not be valid until a submission occurs.
+
+ Vulkan/Metal/D3D/Dawn: Commands are recorded to the backend APIs corresponding command
+ buffer or encoder objects. However, these objects are not sent to the gpu until a
+ submission occurs.
+
+ The work that is submitted to the GPU will be dependent on the BackendSurfaceAccess that is
+ passed in.
+
+ If BackendSurfaceAccess::kNoAccess is passed in all commands will be issued to the GPU.
+
+ If BackendSurfaceAccess::kPresent is passed in and the backend API is not Vulkan, it is
+ treated the same as kNoAccess. If the backend API is Vulkan, the VkImage that backs the
+ SkSurface will be transferred back to its original queue. If the SkSurface was created by
+ wrapping a VkImage, the queue will be set to the queue which was originally passed in on
+ the GrVkImageInfo. Additionally, if the original queue was not external or foreign the
+ layout of the VkImage will be set to VK_IMAGE_LAYOUT_PRESENT_SRC_KHR.
+
+ The GrFlushInfo describes additional options to flush. Please see documentation at
+ GrFlushInfo for more info.
+
+ If the return is GrSemaphoresSubmitted::kYes, only initialized GrBackendSemaphores will be
+ submitted to the gpu during the next submit call (it is possible Skia failed to create a
+ subset of the semaphores). The client should not wait on these semaphores until after submit
+ has been called, but must keep them alive until then. If a submit flag was passed in with
+ the flush these valid semaphores can we waited on immediately. If this call returns
+ GrSemaphoresSubmitted::kNo, the GPU backend will not submit any semaphores to be signaled on
+ the GPU. Thus the client should not have the GPU wait on any of the semaphores passed in
+ with the GrFlushInfo. Regardless of whether semaphores were submitted to the GPU or not, the
+ client is still responsible for deleting any initialized semaphores.
+ Regardless of semaphore submission the context will still be flushed. It should be
+ emphasized that a return value of GrSemaphoresSubmitted::kNo does not mean the flush did not
+ happen. It simply means there were no semaphores submitted to the GPU. A caller should only
+ take this as a failure if they passed in semaphores to be submitted.
+
+ Pending surface commands are flushed regardless of the return result.
+
+ @param access type of access the call will do on the backend object after flush
+ @param info flush options
+ */
+ GrSemaphoresSubmitted flush(BackendSurfaceAccess access, const GrFlushInfo& info);
+
+ /** Issues pending SkSurface commands to the GPU-backed API objects and resolves any SkSurface
+ MSAA. A call to GrDirectContext::submit is always required to ensure work is actually sent
+ to the gpu. Some specific API details:
+ GL: Commands are actually sent to the driver, but glFlush is never called. Thus some
+ sync objects from the flush will not be valid until a submission occurs.
+
+ Vulkan/Metal/D3D/Dawn: Commands are recorded to the backend APIs corresponding command
+ buffer or encoder objects. However, these objects are not sent to the gpu until a
+ submission occurs.
+
+ The GrFlushInfo describes additional options to flush. Please see documentation at
+ GrFlushInfo for more info.
+
+ If a GrBackendSurfaceMutableState is passed in, at the end of the flush we will transition
+ the surface to be in the state requested by the GrBackendSurfaceMutableState. If the surface
+ (or SkImage or GrBackendSurface wrapping the same backend object) is used again after this
+ flush the state may be changed and no longer match what is requested here. This is often
+ used if the surface will be used for presenting or external use and the client wants backend
+ object to be prepped for that use. A finishedProc or semaphore on the GrFlushInfo will also
+ include the work for any requested state change.
+
+ If the backend API is Vulkan, the caller can set the GrBackendSurfaceMutableState's
+ VkImageLayout to VK_IMAGE_LAYOUT_UNDEFINED or queueFamilyIndex to VK_QUEUE_FAMILY_IGNORED to
+ tell Skia to not change those respective states.
+
+ If the return is GrSemaphoresSubmitted::kYes, only initialized GrBackendSemaphores will be
+ submitted to the gpu during the next submit call (it is possible Skia failed to create a
+ subset of the semaphores). The client should not wait on these semaphores until after submit
+ has been called, but must keep them alive until then. If a submit flag was passed in with
+ the flush these valid semaphores can we waited on immediately. If this call returns
+ GrSemaphoresSubmitted::kNo, the GPU backend will not submit any semaphores to be signaled on
+ the GPU. Thus the client should not have the GPU wait on any of the semaphores passed in
+ with the GrFlushInfo. Regardless of whether semaphores were submitted to the GPU or not, the
+ client is still responsible for deleting any initialized semaphores.
+ Regardleess of semaphore submission the context will still be flushed. It should be
+ emphasized that a return value of GrSemaphoresSubmitted::kNo does not mean the flush did not
+ happen. It simply means there were no semaphores submitted to the GPU. A caller should only
+ take this as a failure if they passed in semaphores to be submitted.
+
+ Pending surface commands are flushed regardless of the return result.
+
+ @param info flush options
+ @param access optional state change request after flush
+ */
+ GrSemaphoresSubmitted flush(const GrFlushInfo& info,
+ const GrBackendSurfaceMutableState* newState = nullptr);
+#endif // SK_SUPPORT_GPU
+
+ void flush();
+
+ /** Inserts a list of GPU semaphores that the current GPU-backed API must wait on before
+ executing any more commands on the GPU for this surface. If this call returns false, then
+ the GPU back-end will not wait on any passed in semaphores, and the client will still own
+ the semaphores, regardless of the value of deleteSemaphoresAfterWait.
+
+ If deleteSemaphoresAfterWait is false then Skia will not delete the semaphores. In this case
+ it is the client's responsibility to not destroy or attempt to reuse the semaphores until it
+ knows that Skia has finished waiting on them. This can be done by using finishedProcs
+ on flush calls.
+
+ @param numSemaphores size of waitSemaphores array
+ @param waitSemaphores array of semaphore containers
+ @paramm deleteSemaphoresAfterWait who owns and should delete the semaphores
+ @return true if GPU is waiting on semaphores
+ */
+ bool wait(int numSemaphores, const GrBackendSemaphore* waitSemaphores,
+ bool deleteSemaphoresAfterWait = true);
+
+ /** Initializes SkSurfaceCharacterization that can be used to perform GPU back-end
+ processing in a separate thread. Typically this is used to divide drawing
+ into multiple tiles. SkDeferredDisplayListRecorder records the drawing commands
+ for each tile.
+
+ Return true if SkSurface supports characterization. raster surface returns false.
+
+ @param characterization properties for parallel drawing
+ @return true if supported
+
+ example: https://fiddle.skia.org/c/@Surface_characterize
+ */
+ bool characterize(SkSurfaceCharacterization* characterization) const;
+
+ /** Draws the deferred display list created via a SkDeferredDisplayListRecorder.
+ If the deferred display list is not compatible with this SkSurface, the draw is skipped
+ and false is return.
+
+ The xOffset and yOffset parameters are experimental and, if not both zero, will cause
+ the draw to be ignored.
+ When implemented, if xOffset or yOffset are non-zero, the DDL will be drawn offset by that
+ amount into the surface.
+
+ @param deferredDisplayList drawing commands
+ @param xOffset x-offset at which to draw the DDL
+ @param yOffset y-offset at which to draw the DDL
+ @return false if deferredDisplayList is not compatible
+
+ example: https://fiddle.skia.org/c/@Surface_draw_2
+ */
+ bool draw(sk_sp<const SkDeferredDisplayList> deferredDisplayList,
+ int xOffset = 0,
+ int yOffset = 0);
+
+protected:
+ SkSurface(int width, int height, const SkSurfaceProps* surfaceProps);
+ SkSurface(const SkImageInfo& imageInfo, const SkSurfaceProps* surfaceProps);
+
+ // called by subclass if their contents have changed
+ void dirtyGenerationID() {
+ fGenerationID = 0;
+ }
+
+private:
+ const SkSurfaceProps fProps;
+ const int fWidth;
+ const int fHeight;
+ uint32_t fGenerationID;
+
+ using INHERITED = SkRefCnt;
+};
+
+#endif
diff --git a/src/deps/skia/include/core/SkSurfaceCharacterization.h b/src/deps/skia/include/core/SkSurfaceCharacterization.h
new file mode 100644
index 000000000..91b10e87b
--- /dev/null
+++ b/src/deps/skia/include/core/SkSurfaceCharacterization.h
@@ -0,0 +1,263 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkSurfaceCharacterization_DEFINED
+#define SkSurfaceCharacterization_DEFINED
+
+
+#include "include/core/SkColorSpace.h"
+#include "include/core/SkImageInfo.h"
+#include "include/core/SkRefCnt.h"
+#include "include/core/SkSurfaceProps.h"
+
+class SkColorSpace;
+
+
+#if SK_SUPPORT_GPU
+#include "include/gpu/GrBackendSurface.h"
+#include "include/gpu/GrContextThreadSafeProxy.h"
+#include "include/gpu/GrTypes.h"
+
+/** \class SkSurfaceCharacterization
+ A surface characterization contains all the information Ganesh requires to makes its internal
+ rendering decisions. When passed into a SkDeferredDisplayListRecorder it will copy the
+ data and pass it on to the SkDeferredDisplayList if/when it is created. Note that both of
+ those objects (the Recorder and the DisplayList) will take a ref on the
+ GrContextThreadSafeProxy and SkColorSpace objects.
+*/
+class SK_API SkSurfaceCharacterization {
+public:
+ enum class Textureable : bool { kNo = false, kYes = true };
+ enum class MipMapped : bool { kNo = false, kYes = true };
+ enum class UsesGLFBO0 : bool { kNo = false, kYes = true };
+ // This flag indicates that the backing VkImage for this Vulkan surface will have the
+ // VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT set. This bit allows skia to handle advanced blends
+ // more optimally in a shader by being able to directly read the dst values.
+ enum class VkRTSupportsInputAttachment : bool { kNo = false, kYes = true };
+ // This flag indicates if the surface is wrapping a raw Vulkan secondary command buffer.
+ enum class VulkanSecondaryCBCompatible : bool { kNo = false, kYes = true };
+
+ SkSurfaceCharacterization()
+ : fCacheMaxResourceBytes(0)
+ , fOrigin(kBottomLeft_GrSurfaceOrigin)
+ , fSampleCnt(0)
+ , fIsTextureable(Textureable::kYes)
+ , fIsMipMapped(MipMapped::kYes)
+ , fUsesGLFBO0(UsesGLFBO0::kNo)
+ , fVulkanSecondaryCBCompatible(VulkanSecondaryCBCompatible::kNo)
+ , fIsProtected(GrProtected::kNo)
+ , fSurfaceProps(0, kUnknown_SkPixelGeometry) {
+ }
+
+ SkSurfaceCharacterization(SkSurfaceCharacterization&&) = default;
+ SkSurfaceCharacterization& operator=(SkSurfaceCharacterization&&) = default;
+
+ SkSurfaceCharacterization(const SkSurfaceCharacterization&) = default;
+ SkSurfaceCharacterization& operator=(const SkSurfaceCharacterization& other) = default;
+ bool operator==(const SkSurfaceCharacterization& other) const;
+ bool operator!=(const SkSurfaceCharacterization& other) const {
+ return !(*this == other);
+ }
+
+ /*
+ * Return a new surface characterization with the only difference being a different width
+ * and height
+ */
+ SkSurfaceCharacterization createResized(int width, int height) const;
+
+ /*
+ * Return a new surface characterization with only a replaced color space
+ */
+ SkSurfaceCharacterization createColorSpace(sk_sp<SkColorSpace>) const;
+
+ /*
+ * Return a new surface characterization with the backend format replaced. A colorType
+ * must also be supplied to indicate the interpretation of the new format.
+ */
+ SkSurfaceCharacterization createBackendFormat(SkColorType colorType,
+ const GrBackendFormat& backendFormat) const;
+
+ /*
+ * Return a new surface characterization with just a different use of FBO0 (in GL)
+ */
+ SkSurfaceCharacterization createFBO0(bool usesGLFBO0) const;
+
+ GrContextThreadSafeProxy* contextInfo() const { return fContextInfo.get(); }
+ sk_sp<GrContextThreadSafeProxy> refContextInfo() const { return fContextInfo; }
+ size_t cacheMaxResourceBytes() const { return fCacheMaxResourceBytes; }
+
+ bool isValid() const { return kUnknown_SkColorType != fImageInfo.colorType(); }
+
+ const SkImageInfo& imageInfo() const { return fImageInfo; }
+ const GrBackendFormat& backendFormat() const { return fBackendFormat; }
+ GrSurfaceOrigin origin() const { return fOrigin; }
+ SkISize dimensions() const { return fImageInfo.dimensions(); }
+ int width() const { return fImageInfo.width(); }
+ int height() const { return fImageInfo.height(); }
+ SkColorType colorType() const { return fImageInfo.colorType(); }
+ int sampleCount() const { return fSampleCnt; }
+ bool isTextureable() const { return Textureable::kYes == fIsTextureable; }
+ bool isMipMapped() const { return MipMapped::kYes == fIsMipMapped; }
+ bool usesGLFBO0() const { return UsesGLFBO0::kYes == fUsesGLFBO0; }
+ bool vkRTSupportsInputAttachment() const {
+ return VkRTSupportsInputAttachment::kYes == fVkRTSupportsInputAttachment;
+ }
+ bool vulkanSecondaryCBCompatible() const {
+ return VulkanSecondaryCBCompatible::kYes == fVulkanSecondaryCBCompatible;
+ }
+ GrProtected isProtected() const { return fIsProtected; }
+ SkColorSpace* colorSpace() const { return fImageInfo.colorSpace(); }
+ sk_sp<SkColorSpace> refColorSpace() const { return fImageInfo.refColorSpace(); }
+ const SkSurfaceProps& surfaceProps()const { return fSurfaceProps; }
+
+ // Is the provided backend texture compatible with this surface characterization?
+ bool isCompatible(const GrBackendTexture&) const;
+
+private:
+ friend class SkSurface_Gpu; // for 'set' & 'config'
+ friend class GrVkSecondaryCBDrawContext; // for 'set' & 'config'
+ friend class GrContextThreadSafeProxy; // for private ctor
+ friend class SkDeferredDisplayListRecorder; // for 'config'
+ friend class SkSurface; // for 'config'
+
+ SkDEBUGCODE(void validate() const;)
+
+ SkSurfaceCharacterization(sk_sp<GrContextThreadSafeProxy> contextInfo,
+ size_t cacheMaxResourceBytes,
+ const SkImageInfo& ii,
+ const GrBackendFormat& backendFormat,
+ GrSurfaceOrigin origin,
+ int sampleCnt,
+ Textureable isTextureable,
+ MipMapped isMipMapped,
+ UsesGLFBO0 usesGLFBO0,
+ VkRTSupportsInputAttachment vkRTSupportsInputAttachment,
+ VulkanSecondaryCBCompatible vulkanSecondaryCBCompatible,
+ GrProtected isProtected,
+ const SkSurfaceProps& surfaceProps)
+ : fContextInfo(std::move(contextInfo))
+ , fCacheMaxResourceBytes(cacheMaxResourceBytes)
+ , fImageInfo(ii)
+ , fBackendFormat(backendFormat)
+ , fOrigin(origin)
+ , fSampleCnt(sampleCnt)
+ , fIsTextureable(isTextureable)
+ , fIsMipMapped(isMipMapped)
+ , fUsesGLFBO0(usesGLFBO0)
+ , fVkRTSupportsInputAttachment(vkRTSupportsInputAttachment)
+ , fVulkanSecondaryCBCompatible(vulkanSecondaryCBCompatible)
+ , fIsProtected(isProtected)
+ , fSurfaceProps(surfaceProps) {
+ if (fSurfaceProps.flags() & SkSurfaceProps::kDynamicMSAA_Flag) {
+ // Dynamic MSAA is not currently supported with DDL.
+ *this = {};
+ }
+ SkDEBUGCODE(this->validate());
+ }
+
+ void set(sk_sp<GrContextThreadSafeProxy> contextInfo,
+ size_t cacheMaxResourceBytes,
+ const SkImageInfo& ii,
+ const GrBackendFormat& backendFormat,
+ GrSurfaceOrigin origin,
+ int sampleCnt,
+ Textureable isTextureable,
+ MipMapped isMipMapped,
+ UsesGLFBO0 usesGLFBO0,
+ VkRTSupportsInputAttachment vkRTSupportsInputAttachment,
+ VulkanSecondaryCBCompatible vulkanSecondaryCBCompatible,
+ GrProtected isProtected,
+ const SkSurfaceProps& surfaceProps) {
+ if (surfaceProps.flags() & SkSurfaceProps::kDynamicMSAA_Flag) {
+ // Dynamic MSAA is not currently supported with DDL.
+ *this = {};
+ } else {
+ fContextInfo = contextInfo;
+ fCacheMaxResourceBytes = cacheMaxResourceBytes;
+
+ fImageInfo = ii;
+ fBackendFormat = backendFormat;
+ fOrigin = origin;
+ fSampleCnt = sampleCnt;
+ fIsTextureable = isTextureable;
+ fIsMipMapped = isMipMapped;
+ fUsesGLFBO0 = usesGLFBO0;
+ fVkRTSupportsInputAttachment = vkRTSupportsInputAttachment;
+ fVulkanSecondaryCBCompatible = vulkanSecondaryCBCompatible;
+ fIsProtected = isProtected;
+ fSurfaceProps = surfaceProps;
+ }
+ SkDEBUGCODE(this->validate());
+ }
+
+ sk_sp<GrContextThreadSafeProxy> fContextInfo;
+ size_t fCacheMaxResourceBytes;
+
+ SkImageInfo fImageInfo;
+ GrBackendFormat fBackendFormat;
+ GrSurfaceOrigin fOrigin;
+ int fSampleCnt;
+ Textureable fIsTextureable;
+ MipMapped fIsMipMapped;
+ UsesGLFBO0 fUsesGLFBO0;
+ VkRTSupportsInputAttachment fVkRTSupportsInputAttachment;
+ VulkanSecondaryCBCompatible fVulkanSecondaryCBCompatible;
+ GrProtected fIsProtected;
+ SkSurfaceProps fSurfaceProps;
+};
+
+#else// !SK_SUPPORT_GPU
+class GrBackendFormat;
+
+class SK_API SkSurfaceCharacterization {
+public:
+ SkSurfaceCharacterization() : fSurfaceProps(0, kUnknown_SkPixelGeometry) { }
+
+ SkSurfaceCharacterization createResized(int width, int height) const {
+ return *this;
+ }
+
+ SkSurfaceCharacterization createColorSpace(sk_sp<SkColorSpace>) const {
+ return *this;
+ }
+
+ SkSurfaceCharacterization createBackendFormat(SkColorType, const GrBackendFormat&) const {
+ return *this;
+ }
+
+ SkSurfaceCharacterization createFBO0(bool usesGLFBO0) const {
+ return *this;
+ }
+
+ bool operator==(const SkSurfaceCharacterization& other) const { return false; }
+ bool operator!=(const SkSurfaceCharacterization& other) const {
+ return !(*this == other);
+ }
+
+ size_t cacheMaxResourceBytes() const { return 0; }
+
+ bool isValid() const { return false; }
+
+ int width() const { return 0; }
+ int height() const { return 0; }
+ int stencilCount() const { return 0; }
+ bool isTextureable() const { return false; }
+ bool isMipMapped() const { return false; }
+ bool usesGLFBO0() const { return false; }
+ bool vkRTSupportsAttachmentInput() const { return false; }
+ bool vulkanSecondaryCBCompatible() const { return false; }
+ SkColorSpace* colorSpace() const { return nullptr; }
+ sk_sp<SkColorSpace> refColorSpace() const { return nullptr; }
+ const SkSurfaceProps& surfaceProps()const { return fSurfaceProps; }
+
+private:
+ SkSurfaceProps fSurfaceProps;
+};
+
+#endif
+
+#endif
diff --git a/src/deps/skia/include/core/SkSurfaceProps.h b/src/deps/skia/include/core/SkSurfaceProps.h
new file mode 100644
index 000000000..7b07554e5
--- /dev/null
+++ b/src/deps/skia/include/core/SkSurfaceProps.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkSurfaceProps_DEFINED
+#define SkSurfaceProps_DEFINED
+
+#include "include/core/SkTypes.h"
+
+/**
+ * Description of how the LCD strips are arranged for each pixel. If this is unknown, or the
+ * pixels are meant to be "portable" and/or transformed before showing (e.g. rotated, scaled)
+ * then use kUnknown_SkPixelGeometry.
+ */
+enum SkPixelGeometry {
+ kUnknown_SkPixelGeometry,
+ kRGB_H_SkPixelGeometry,
+ kBGR_H_SkPixelGeometry,
+ kRGB_V_SkPixelGeometry,
+ kBGR_V_SkPixelGeometry,
+};
+
+// Returns true iff geo is a known geometry and is RGB.
+static inline bool SkPixelGeometryIsRGB(SkPixelGeometry geo) {
+ return kRGB_H_SkPixelGeometry == geo || kRGB_V_SkPixelGeometry == geo;
+}
+
+// Returns true iff geo is a known geometry and is BGR.
+static inline bool SkPixelGeometryIsBGR(SkPixelGeometry geo) {
+ return kBGR_H_SkPixelGeometry == geo || kBGR_V_SkPixelGeometry == geo;
+}
+
+// Returns true iff geo is a known geometry and is horizontal.
+static inline bool SkPixelGeometryIsH(SkPixelGeometry geo) {
+ return kRGB_H_SkPixelGeometry == geo || kBGR_H_SkPixelGeometry == geo;
+}
+
+// Returns true iff geo is a known geometry and is vertical.
+static inline bool SkPixelGeometryIsV(SkPixelGeometry geo) {
+ return kRGB_V_SkPixelGeometry == geo || kBGR_V_SkPixelGeometry == geo;
+}
+
+/**
+ * Describes properties and constraints of a given SkSurface. The rendering engine can parse these
+ * during drawing, and can sometimes optimize its performance (e.g. disabling an expensive
+ * feature).
+ */
+class SK_API SkSurfaceProps {
+public:
+ enum Flags {
+ kUseDeviceIndependentFonts_Flag = 1 << 0,
+ // Use internal MSAA to render to non-MSAA GPU surfaces.
+ kDynamicMSAA_Flag = 1 << 1
+ };
+ /** Deprecated alias used by Chromium. Will be removed. */
+ static const Flags kUseDistanceFieldFonts_Flag = kUseDeviceIndependentFonts_Flag;
+
+ /** No flags, unknown pixel geometry. */
+ SkSurfaceProps();
+ SkSurfaceProps(uint32_t flags, SkPixelGeometry);
+
+ SkSurfaceProps(const SkSurfaceProps&);
+ SkSurfaceProps& operator=(const SkSurfaceProps&);
+
+ SkSurfaceProps cloneWithPixelGeometry(SkPixelGeometry newPixelGeometry) const {
+ return SkSurfaceProps(fFlags, newPixelGeometry);
+ }
+
+ uint32_t flags() const { return fFlags; }
+ SkPixelGeometry pixelGeometry() const { return fPixelGeometry; }
+
+ bool isUseDeviceIndependentFonts() const {
+ return SkToBool(fFlags & kUseDeviceIndependentFonts_Flag);
+ }
+
+ bool operator==(const SkSurfaceProps& that) const {
+ return fFlags == that.fFlags && fPixelGeometry == that.fPixelGeometry;
+ }
+
+ bool operator!=(const SkSurfaceProps& that) const {
+ return !(*this == that);
+ }
+
+private:
+ uint32_t fFlags;
+ SkPixelGeometry fPixelGeometry;
+};
+
+#endif
diff --git a/src/deps/skia/include/core/SkSwizzle.h b/src/deps/skia/include/core/SkSwizzle.h
new file mode 100644
index 000000000..61e93b2da
--- /dev/null
+++ b/src/deps/skia/include/core/SkSwizzle.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkSwizzle_DEFINED
+#define SkSwizzle_DEFINED
+
+#include "include/core/SkTypes.h"
+
+/**
+ Swizzles byte order of |count| 32-bit pixels, swapping R and B.
+ (RGBA <-> BGRA)
+*/
+SK_API void SkSwapRB(uint32_t* dest, const uint32_t* src, int count);
+
+#endif
diff --git a/src/deps/skia/include/core/SkTextBlob.h b/src/deps/skia/include/core/SkTextBlob.h
new file mode 100644
index 000000000..d6cda3b27
--- /dev/null
+++ b/src/deps/skia/include/core/SkTextBlob.h
@@ -0,0 +1,503 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkTextBlob_DEFINED
+#define SkTextBlob_DEFINED
+
+#include "include/core/SkFont.h"
+#include "include/core/SkPaint.h"
+#include "include/core/SkRefCnt.h"
+#include "include/core/SkString.h"
+#include "include/private/SkTemplates.h"
+
+#include <atomic>
+
+struct SkRSXform;
+struct SkSerialProcs;
+struct SkDeserialProcs;
+
+/** \class SkTextBlob
+ SkTextBlob combines multiple text runs into an immutable container. Each text
+ run consists of glyphs, SkPaint, and position. Only parts of SkPaint related to
+ fonts and text rendering are used by run.
+*/
+class SK_API SkTextBlob final : public SkNVRefCnt<SkTextBlob> {
+private:
+ class RunRecord;
+
+public:
+
+ /** Returns conservative bounding box. Uses SkPaint associated with each glyph to
+ determine glyph bounds, and unions all bounds. Returned bounds may be
+ larger than the bounds of all glyphs in runs.
+
+ @return conservative bounding box
+ */
+ const SkRect& bounds() const { return fBounds; }
+
+ /** Returns a non-zero value unique among all text blobs.
+
+ @return identifier for SkTextBlob
+ */
+ uint32_t uniqueID() const { return fUniqueID; }
+
+ /** Returns the number of intervals that intersect bounds.
+ bounds describes a pair of lines parallel to the text advance.
+ The return count is zero or a multiple of two, and is at most twice the number of glyphs in
+ the the blob.
+
+ Pass nullptr for intervals to determine the size of the interval array.
+
+ Runs within the blob that contain SkRSXform are ignored when computing intercepts.
+
+ @param bounds lower and upper line parallel to the advance
+ @param intervals returned intersections; may be nullptr
+ @param paint specifies stroking, SkPathEffect that affects the result; may be nullptr
+ @return number of intersections; may be zero
+ */
+ int getIntercepts(const SkScalar bounds[2], SkScalar intervals[],
+ const SkPaint* paint = nullptr) const;
+
+ /** Creates SkTextBlob with a single run.
+
+ font contains attributes used to define the run text.
+
+ When encoding is SkTextEncoding::kUTF8, SkTextEncoding::kUTF16, or
+ SkTextEncoding::kUTF32, this function uses the default
+ character-to-glyph mapping from the SkTypeface in font. It does not
+ perform typeface fallback for characters not found in the SkTypeface.
+ It does not perform kerning or other complex shaping; glyphs are
+ positioned based on their default advances.
+
+ @param text character code points or glyphs drawn
+ @param byteLength byte length of text array
+ @param font text size, typeface, text scale, and so on, used to draw
+ @param encoding text encoding used in the text array
+ @return SkTextBlob constructed from one run
+ */
+ static sk_sp<SkTextBlob> MakeFromText(const void* text, size_t byteLength, const SkFont& font,
+ SkTextEncoding encoding = SkTextEncoding::kUTF8);
+
+ /** Creates SkTextBlob with a single run. string meaning depends on SkTextEncoding;
+ by default, string is encoded as UTF-8.
+
+ font contains attributes used to define the run text.
+
+ When encoding is SkTextEncoding::kUTF8, SkTextEncoding::kUTF16, or
+ SkTextEncoding::kUTF32, this function uses the default
+ character-to-glyph mapping from the SkTypeface in font. It does not
+ perform typeface fallback for characters not found in the SkTypeface.
+ It does not perform kerning or other complex shaping; glyphs are
+ positioned based on their default advances.
+
+ @param string character code points or glyphs drawn
+ @param font text size, typeface, text scale, and so on, used to draw
+ @param encoding text encoding used in the text array
+ @return SkTextBlob constructed from one run
+ */
+ static sk_sp<SkTextBlob> MakeFromString(const char* string, const SkFont& font,
+ SkTextEncoding encoding = SkTextEncoding::kUTF8) {
+ if (!string) {
+ return nullptr;
+ }
+ return MakeFromText(string, strlen(string), font, encoding);
+ }
+
+ /** Returns a textblob built from a single run of text with x-positions and a single y value.
+ This is equivalent to using SkTextBlobBuilder and calling allocRunPosH().
+ Returns nullptr if byteLength is zero.
+
+ @param text character code points or glyphs drawn (based on encoding)
+ @param byteLength byte length of text array
+ @param xpos array of x-positions, must contain values for all of the character points.
+ @param constY shared y-position for each character point, to be paired with each xpos.
+ @param font SkFont used for this run
+ @param encoding specifies the encoding of the text array.
+ @return new textblob or nullptr
+ */
+ static sk_sp<SkTextBlob> MakeFromPosTextH(const void* text, size_t byteLength,
+ const SkScalar xpos[], SkScalar constY, const SkFont& font,
+ SkTextEncoding encoding = SkTextEncoding::kUTF8);
+
+ /** Returns a textblob built from a single run of text with positions.
+ This is equivalent to using SkTextBlobBuilder and calling allocRunPos().
+ Returns nullptr if byteLength is zero.
+
+ @param text character code points or glyphs drawn (based on encoding)
+ @param byteLength byte length of text array
+ @param pos array of positions, must contain values for all of the character points.
+ @param font SkFont used for this run
+ @param encoding specifies the encoding of the text array.
+ @return new textblob or nullptr
+ */
+ static sk_sp<SkTextBlob> MakeFromPosText(const void* text, size_t byteLength,
+ const SkPoint pos[], const SkFont& font,
+ SkTextEncoding encoding = SkTextEncoding::kUTF8);
+
+ static sk_sp<SkTextBlob> MakeFromRSXform(const void* text, size_t byteLength,
+ const SkRSXform xform[], const SkFont& font,
+ SkTextEncoding encoding = SkTextEncoding::kUTF8);
+
+ /** Writes data to allow later reconstruction of SkTextBlob. memory points to storage
+ to receive the encoded data, and memory_size describes the size of storage.
+ Returns bytes used if provided storage is large enough to hold all data;
+ otherwise, returns zero.
+
+ procs.fTypefaceProc permits supplying a custom function to encode SkTypeface.
+ If procs.fTypefaceProc is nullptr, default encoding is used. procs.fTypefaceCtx
+ may be used to provide user context to procs.fTypefaceProc; procs.fTypefaceProc
+ is called with a pointer to SkTypeface and user context.
+
+ @param procs custom serial data encoders; may be nullptr
+ @param memory storage for data
+ @param memory_size size of storage
+ @return bytes written, or zero if required storage is larger than memory_size
+
+ example: https://fiddle.skia.org/c/@TextBlob_serialize
+ */
+ size_t serialize(const SkSerialProcs& procs, void* memory, size_t memory_size) const;
+
+ /** Returns storage containing SkData describing SkTextBlob, using optional custom
+ encoders.
+
+ procs.fTypefaceProc permits supplying a custom function to encode SkTypeface.
+ If procs.fTypefaceProc is nullptr, default encoding is used. procs.fTypefaceCtx
+ may be used to provide user context to procs.fTypefaceProc; procs.fTypefaceProc
+ is called with a pointer to SkTypeface and user context.
+
+ @param procs custom serial data encoders; may be nullptr
+ @return storage containing serialized SkTextBlob
+
+ example: https://fiddle.skia.org/c/@TextBlob_serialize_2
+ */
+ sk_sp<SkData> serialize(const SkSerialProcs& procs) const;
+
+ /** Recreates SkTextBlob that was serialized into data. Returns constructed SkTextBlob
+ if successful; otherwise, returns nullptr. Fails if size is smaller than
+ required data length, or if data does not permit constructing valid SkTextBlob.
+
+ procs.fTypefaceProc permits supplying a custom function to decode SkTypeface.
+ If procs.fTypefaceProc is nullptr, default decoding is used. procs.fTypefaceCtx
+ may be used to provide user context to procs.fTypefaceProc; procs.fTypefaceProc
+ is called with a pointer to SkTypeface data, data byte length, and user context.
+
+ @param data pointer for serial data
+ @param size size of data
+ @param procs custom serial data decoders; may be nullptr
+ @return SkTextBlob constructed from data in memory
+ */
+ static sk_sp<SkTextBlob> Deserialize(const void* data, size_t size,
+ const SkDeserialProcs& procs);
+
+ class SK_API Iter {
+ public:
+ struct Run {
+ SkTypeface* fTypeface;
+ int fGlyphCount;
+ const uint16_t* fGlyphIndices;
+#ifdef SK_UNTIL_CRBUG_1187654_IS_FIXED
+ const uint32_t* fClusterIndex_forTest;
+ int fUtf8Size_forTest;
+ const char* fUtf8_forTest;
+#endif
+ };
+
+ Iter(const SkTextBlob&);
+
+ /**
+ * Returns true for each "run" inside the textblob, setting the Run fields (if not null).
+ * If this returns false, there are no more runs, and the Run parameter will be ignored.
+ */
+ bool next(Run*);
+
+ // Experimental, DO NO USE, will change/go-away
+ struct ExperimentalRun {
+ SkFont font;
+ int count;
+ const uint16_t* glyphs;
+ const SkPoint* positions;
+ };
+ bool experimentalNext(ExperimentalRun*);
+
+ private:
+ const RunRecord* fRunRecord;
+ };
+
+private:
+ friend class SkNVRefCnt<SkTextBlob>;
+
+ enum GlyphPositioning : uint8_t;
+
+ explicit SkTextBlob(const SkRect& bounds);
+
+ ~SkTextBlob();
+
+ // Memory for objects of this class is created with sk_malloc rather than operator new and must
+ // be freed with sk_free.
+ void operator delete(void* p);
+ void* operator new(size_t);
+ void* operator new(size_t, void* p);
+
+ static unsigned ScalarsPerGlyph(GlyphPositioning pos);
+
+ // Call when this blob is part of the key to a cache entry. This allows the cache
+ // to know automatically those entries can be purged when this SkTextBlob is deleted.
+ void notifyAddedToCache(uint32_t cacheID) const {
+ fCacheID.store(cacheID);
+ }
+
+ friend class SkGlyphRunList;
+ friend class GrTextBlobCache;
+ friend class SkTextBlobBuilder;
+ friend class SkTextBlobPriv;
+ friend class SkTextBlobRunIterator;
+
+ const SkRect fBounds;
+ const uint32_t fUniqueID;
+ mutable std::atomic<uint32_t> fCacheID;
+
+ SkDEBUGCODE(size_t fStorageSize;)
+
+ // The actual payload resides in externally-managed storage, following the object.
+ // (see the .cpp for more details)
+
+ using INHERITED = SkRefCnt;
+};
+
+/** \class SkTextBlobBuilder
+ Helper class for constructing SkTextBlob.
+*/
+class SK_API SkTextBlobBuilder {
+public:
+
+ /** Constructs empty SkTextBlobBuilder. By default, SkTextBlobBuilder has no runs.
+
+ @return empty SkTextBlobBuilder
+
+ example: https://fiddle.skia.org/c/@TextBlobBuilder_empty_constructor
+ */
+ SkTextBlobBuilder();
+
+ /** Deletes data allocated internally by SkTextBlobBuilder.
+ */
+ ~SkTextBlobBuilder();
+
+ /** Returns SkTextBlob built from runs of glyphs added by builder. Returned
+ SkTextBlob is immutable; it may be copied, but its contents may not be altered.
+ Returns nullptr if no runs of glyphs were added by builder.
+
+ Resets SkTextBlobBuilder to its initial empty state, allowing it to be
+ reused to build a new set of runs.
+
+ @return SkTextBlob or nullptr
+
+ example: https://fiddle.skia.org/c/@TextBlobBuilder_make
+ */
+ sk_sp<SkTextBlob> make();
+
+ /** \struct SkTextBlobBuilder::RunBuffer
+ RunBuffer supplies storage for glyphs and positions within a run.
+
+ A run is a sequence of glyphs sharing font metrics and positioning.
+ Each run may position its glyphs in one of three ways:
+ by specifying where the first glyph is drawn, and allowing font metrics to
+ determine the advance to subsequent glyphs; by specifying a baseline, and
+ the position on that baseline for each glyph in run; or by providing SkPoint
+ array, one per glyph.
+ */
+ struct RunBuffer {
+ SkGlyphID* glyphs; //!< storage for glyph indexes in run
+ SkScalar* pos; //!< storage for glyph positions in run
+ char* utf8text; //!< storage for text UTF-8 code units in run
+ uint32_t* clusters; //!< storage for glyph clusters (index of UTF-8 code unit)
+
+ // Helpers, since the "pos" field can be different types (always some number of floats).
+ SkPoint* points() const { return reinterpret_cast<SkPoint*>(pos); }
+ SkRSXform* xforms() const { return reinterpret_cast<SkRSXform*>(pos); }
+ };
+
+ /** Returns run with storage for glyphs. Caller must write count glyphs to
+ RunBuffer::glyphs before next call to SkTextBlobBuilder.
+
+ RunBuffer::pos, RunBuffer::utf8text, and RunBuffer::clusters should be ignored.
+
+ Glyphs share metrics in font.
+
+ Glyphs are positioned on a baseline at (x, y), using font metrics to
+ determine their relative placement.
+
+ bounds defines an optional bounding box, used to suppress drawing when SkTextBlob
+ bounds does not intersect SkSurface bounds. If bounds is nullptr, SkTextBlob bounds
+ is computed from (x, y) and RunBuffer::glyphs metrics.
+
+ @param font SkFont used for this run
+ @param count number of glyphs
+ @param x horizontal offset within the blob
+ @param y vertical offset within the blob
+ @param bounds optional run bounding box
+ @return writable glyph buffer
+ */
+ const RunBuffer& allocRun(const SkFont& font, int count, SkScalar x, SkScalar y,
+ const SkRect* bounds = nullptr);
+
+ /** Returns run with storage for glyphs and positions along baseline. Caller must
+ write count glyphs to RunBuffer::glyphs and count scalars to RunBuffer::pos
+ before next call to SkTextBlobBuilder.
+
+ RunBuffer::utf8text and RunBuffer::clusters should be ignored.
+
+ Glyphs share metrics in font.
+
+ Glyphs are positioned on a baseline at y, using x-axis positions written by
+ caller to RunBuffer::pos.
+
+ bounds defines an optional bounding box, used to suppress drawing when SkTextBlob
+ bounds does not intersect SkSurface bounds. If bounds is nullptr, SkTextBlob bounds
+ is computed from y, RunBuffer::pos, and RunBuffer::glyphs metrics.
+
+ @param font SkFont used for this run
+ @param count number of glyphs
+ @param y vertical offset within the blob
+ @param bounds optional run bounding box
+ @return writable glyph buffer and x-axis position buffer
+ */
+ const RunBuffer& allocRunPosH(const SkFont& font, int count, SkScalar y,
+ const SkRect* bounds = nullptr);
+
+ /** Returns run with storage for glyphs and SkPoint positions. Caller must
+ write count glyphs to RunBuffer::glyphs and count SkPoint to RunBuffer::pos
+ before next call to SkTextBlobBuilder.
+
+ RunBuffer::utf8text and RunBuffer::clusters should be ignored.
+
+ Glyphs share metrics in font.
+
+ Glyphs are positioned using SkPoint written by caller to RunBuffer::pos, using
+ two scalar values for each SkPoint.
+
+ bounds defines an optional bounding box, used to suppress drawing when SkTextBlob
+ bounds does not intersect SkSurface bounds. If bounds is nullptr, SkTextBlob bounds
+ is computed from RunBuffer::pos, and RunBuffer::glyphs metrics.
+
+ @param font SkFont used for this run
+ @param count number of glyphs
+ @param bounds optional run bounding box
+ @return writable glyph buffer and SkPoint buffer
+ */
+ const RunBuffer& allocRunPos(const SkFont& font, int count,
+ const SkRect* bounds = nullptr);
+
+ // RunBuffer.pos points to SkRSXform array
+ const RunBuffer& allocRunRSXform(const SkFont& font, int count);
+
+ /** Returns run with storage for glyphs, text, and clusters. Caller must
+ write count glyphs to RunBuffer::glyphs, textByteCount UTF-8 code units
+ into RunBuffer::utf8text, and count monotonic indexes into utf8text
+ into RunBuffer::clusters before next call to SkTextBlobBuilder.
+
+ RunBuffer::pos should be ignored.
+
+ Glyphs share metrics in font.
+
+ Glyphs are positioned on a baseline at (x, y), using font metrics to
+ determine their relative placement.
+
+ bounds defines an optional bounding box, used to suppress drawing when SkTextBlob
+ bounds does not intersect SkSurface bounds. If bounds is nullptr, SkTextBlob bounds
+ is computed from (x, y) and RunBuffer::glyphs metrics.
+
+ @param font SkFont used for this run
+ @param count number of glyphs
+ @param x horizontal offset within the blob
+ @param y vertical offset within the blob
+ @param textByteCount number of UTF-8 code units
+ @param bounds optional run bounding box
+ @return writable glyph buffer, text buffer, and cluster buffer
+ */
+ const RunBuffer& allocRunText(const SkFont& font, int count, SkScalar x, SkScalar y,
+ int textByteCount, const SkRect* bounds = nullptr);
+
+ /** Returns run with storage for glyphs, positions along baseline, text,
+ and clusters. Caller must write count glyphs to RunBuffer::glyphs,
+ count scalars to RunBuffer::pos, textByteCount UTF-8 code units into
+ RunBuffer::utf8text, and count monotonic indexes into utf8text into
+ RunBuffer::clusters before next call to SkTextBlobBuilder.
+
+ Glyphs share metrics in font.
+
+ Glyphs are positioned on a baseline at y, using x-axis positions written by
+ caller to RunBuffer::pos.
+
+ bounds defines an optional bounding box, used to suppress drawing when SkTextBlob
+ bounds does not intersect SkSurface bounds. If bounds is nullptr, SkTextBlob bounds
+ is computed from y, RunBuffer::pos, and RunBuffer::glyphs metrics.
+
+ @param font SkFont used for this run
+ @param count number of glyphs
+ @param y vertical offset within the blob
+ @param textByteCount number of UTF-8 code units
+ @param bounds optional run bounding box
+ @return writable glyph buffer, x-axis position buffer, text buffer, and cluster buffer
+ */
+ const RunBuffer& allocRunTextPosH(const SkFont& font, int count, SkScalar y, int textByteCount,
+ const SkRect* bounds = nullptr);
+
+ /** Returns run with storage for glyphs, SkPoint positions, text, and
+ clusters. Caller must write count glyphs to RunBuffer::glyphs, count
+ SkPoint to RunBuffer::pos, textByteCount UTF-8 code units into
+ RunBuffer::utf8text, and count monotonic indexes into utf8text into
+ RunBuffer::clusters before next call to SkTextBlobBuilder.
+
+ Glyphs share metrics in font.
+
+ Glyphs are positioned using SkPoint written by caller to RunBuffer::pos, using
+ two scalar values for each SkPoint.
+
+ bounds defines an optional bounding box, used to suppress drawing when SkTextBlob
+ bounds does not intersect SkSurface bounds. If bounds is nullptr, SkTextBlob bounds
+ is computed from RunBuffer::pos, and RunBuffer::glyphs metrics.
+
+ @param font SkFont used for this run
+ @param count number of glyphs
+ @param textByteCount number of UTF-8 code units
+ @param bounds optional run bounding box
+ @return writable glyph buffer, SkPoint buffer, text buffer, and cluster buffer
+ */
+ const RunBuffer& allocRunTextPos(const SkFont& font, int count, int textByteCount,
+ const SkRect* bounds = nullptr);
+
+ // RunBuffer.pos points to SkRSXform array
+ const RunBuffer& allocRunTextRSXform(const SkFont& font, int count, int textByteCount,
+ const SkRect* bounds = nullptr);
+
+private:
+ void reserve(size_t size);
+ void allocInternal(const SkFont& font, SkTextBlob::GlyphPositioning positioning,
+ int count, int textBytes, SkPoint offset, const SkRect* bounds);
+ bool mergeRun(const SkFont& font, SkTextBlob::GlyphPositioning positioning,
+ uint32_t count, SkPoint offset);
+ void updateDeferredBounds();
+
+ static SkRect ConservativeRunBounds(const SkTextBlob::RunRecord&);
+ static SkRect TightRunBounds(const SkTextBlob::RunRecord&);
+
+ friend class SkTextBlobPriv;
+ friend class SkTextBlobBuilderPriv;
+
+ SkAutoTMalloc<uint8_t> fStorage;
+ size_t fStorageSize;
+ size_t fStorageUsed;
+
+ SkRect fBounds;
+ int fRunCount;
+ bool fDeferredBounds;
+ size_t fLastRun; // index into fStorage
+
+ RunBuffer fCurrentRunBuffer;
+};
+
+#endif // SkTextBlob_DEFINED
diff --git a/src/deps/skia/include/core/SkTileMode.h b/src/deps/skia/include/core/SkTileMode.h
new file mode 100644
index 000000000..8a9d02095
--- /dev/null
+++ b/src/deps/skia/include/core/SkTileMode.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2019 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkTileModes_DEFINED
+#define SkTileModes_DEFINED
+
+#include "include/core/SkTypes.h"
+
+enum class SkTileMode {
+ /**
+ * Replicate the edge color if the shader draws outside of its
+ * original bounds.
+ */
+ kClamp,
+
+ /**
+ * Repeat the shader's image horizontally and vertically.
+ */
+ kRepeat,
+
+ /**
+ * Repeat the shader's image horizontally and vertically, alternating
+ * mirror images so that adjacent images always seam.
+ */
+ kMirror,
+
+ /**
+ * Only draw within the original domain, return transparent-black everywhere else.
+ */
+ kDecal,
+
+ kLastTileMode = kDecal,
+};
+
+static constexpr int kSkTileModeCount = static_cast<int>(SkTileMode::kLastTileMode) + 1;
+
+#endif
diff --git a/src/deps/skia/include/core/SkTime.h b/src/deps/skia/include/core/SkTime.h
new file mode 100644
index 000000000..3da2c8c77
--- /dev/null
+++ b/src/deps/skia/include/core/SkTime.h
@@ -0,0 +1,63 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkTime_DEFINED
+#define SkTime_DEFINED
+
+#include "include/core/SkTypes.h"
+#include "include/private/SkMacros.h"
+
+#include <cinttypes>
+
+class SkString;
+
+/** \class SkTime
+ Platform-implemented utilities to return time of day, and millisecond counter.
+*/
+class SK_API SkTime {
+public:
+ struct DateTime {
+ int16_t fTimeZoneMinutes; // The number of minutes that GetDateTime()
+ // is ahead of or behind UTC.
+ uint16_t fYear; //!< e.g. 2005
+ uint8_t fMonth; //!< 1..12
+ uint8_t fDayOfWeek; //!< 0..6, 0==Sunday
+ uint8_t fDay; //!< 1..31
+ uint8_t fHour; //!< 0..23
+ uint8_t fMinute; //!< 0..59
+ uint8_t fSecond; //!< 0..59
+
+ void toISO8601(SkString* dst) const;
+ };
+ static void GetDateTime(DateTime*);
+
+ static double GetSecs() { return GetNSecs() * 1e-9; }
+ static double GetMSecs() { return GetNSecs() * 1e-6; }
+ static double GetNSecs();
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+class SkAutoTime {
+public:
+ // The label is not deep-copied, so its address must remain valid for the
+ // lifetime of this object
+ SkAutoTime(const char* label = nullptr)
+ : fLabel(label)
+ , fNow(SkTime::GetMSecs()) {}
+ ~SkAutoTime() {
+ uint64_t dur = static_cast<uint64_t>(SkTime::GetMSecs() - fNow);
+ SkDebugf("%s %" PRIu64 "\n", fLabel ? fLabel : "", dur);
+ }
+private:
+ const char* fLabel;
+ double fNow;
+};
+
+#endif
diff --git a/src/deps/skia/include/core/SkTraceMemoryDump.h b/src/deps/skia/include/core/SkTraceMemoryDump.h
new file mode 100644
index 000000000..7837bfbd8
--- /dev/null
+++ b/src/deps/skia/include/core/SkTraceMemoryDump.h
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2015 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkTraceMemoryDump_DEFINED
+#define SkTraceMemoryDump_DEFINED
+
+#include "include/core/SkTypes.h"
+
+class SkDiscardableMemory;
+
+/**
+ * Interface for memory tracing.
+ * This interface is meant to be passed as argument to the memory dump methods of Skia objects.
+ * The implementation of this interface is provided by the embedder.
+ */
+class SK_API SkTraceMemoryDump {
+public:
+ /**
+ * Enum to specify the level of the requested details for the dump from the Skia objects.
+ */
+ enum LevelOfDetail {
+ // Dump only the minimal details to get the total memory usage (Usually just the totals).
+ kLight_LevelOfDetail,
+
+ // Dump the detailed breakdown of the objects in the caches.
+ kObjectsBreakdowns_LevelOfDetail
+ };
+
+ /**
+ * Appends a new memory dump (i.e. a row) to the trace memory infrastructure.
+ * If dumpName does not exist yet, a new one is created. Otherwise, a new column is appended to
+ * the previously created dump.
+ * Arguments:
+ * dumpName: an absolute, slash-separated, name for the item being dumped
+ * e.g., "skia/CacheX/EntryY".
+ * valueName: a string indicating the name of the column.
+ * e.g., "size", "active_size", "number_of_objects".
+ * This string is supposed to be long lived and is NOT copied.
+ * units: a string indicating the units for the value.
+ * e.g., "bytes", "objects".
+ * This string is supposed to be long lived and is NOT copied.
+ * value: the actual value being dumped.
+ */
+ virtual void dumpNumericValue(const char* dumpName,
+ const char* valueName,
+ const char* units,
+ uint64_t value) = 0;
+
+ virtual void dumpStringValue(const char* /*dumpName*/,
+ const char* /*valueName*/,
+ const char* /*value*/) { }
+
+ /**
+ * Sets the memory backing for an existing dump.
+ * backingType and backingObjectId are used by the embedder to associate the memory dumped via
+ * dumpNumericValue with the corresponding dump that backs the memory.
+ */
+ virtual void setMemoryBacking(const char* dumpName,
+ const char* backingType,
+ const char* backingObjectId) = 0;
+
+ /**
+ * Specialization for memory backed by discardable memory.
+ */
+ virtual void setDiscardableMemoryBacking(
+ const char* dumpName,
+ const SkDiscardableMemory& discardableMemoryObject) = 0;
+
+ /**
+ * Returns the type of details requested in the dump. The granularity of the dump is supposed to
+ * match the LevelOfDetail argument. The level of detail must not affect the total size
+ * reported, but only granularity of the child entries.
+ */
+ virtual LevelOfDetail getRequestedDetails() const = 0;
+
+ /**
+ * Returns true if we should dump wrapped objects. Wrapped objects come from outside Skia, and
+ * may be independently tracked there.
+ */
+ virtual bool shouldDumpWrappedObjects() const { return true; }
+
+ /**
+ * If shouldDumpWrappedObjects() returns true then this function will be called to populate
+ * the output with information on whether the item being dumped is a wrapped object.
+ */
+ virtual void dumpWrappedState(const char* /*dumpName*/, bool /*isWrappedObject*/) {}
+
+protected:
+ virtual ~SkTraceMemoryDump() = default;
+ SkTraceMemoryDump() = default;
+ SkTraceMemoryDump(const SkTraceMemoryDump&) = delete;
+ SkTraceMemoryDump& operator=(const SkTraceMemoryDump&) = delete;
+};
+
+#endif
diff --git a/src/deps/skia/include/core/SkTypeface.h b/src/deps/skia/include/core/SkTypeface.h
new file mode 100644
index 000000000..ad49a544b
--- /dev/null
+++ b/src/deps/skia/include/core/SkTypeface.h
@@ -0,0 +1,454 @@
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkTypeface_DEFINED
+#define SkTypeface_DEFINED
+
+#include "include/core/SkFontArguments.h"
+#include "include/core/SkFontParameters.h"
+#include "include/core/SkFontStyle.h"
+#include "include/core/SkFontTypes.h"
+#include "include/core/SkRect.h"
+#include "include/core/SkString.h"
+#include "include/private/SkOnce.h"
+#include "include/private/SkWeakRefCnt.h"
+
+class SkData;
+class SkDescriptor;
+class SkFontData;
+class SkFontDescriptor;
+class SkScalerContext;
+class SkStream;
+class SkStreamAsset;
+class SkWStream;
+struct SkAdvancedTypefaceMetrics;
+struct SkScalerContextEffects;
+struct SkScalerContextRec;
+
+typedef uint32_t SkFontID;
+/** Machine endian. */
+typedef uint32_t SkFontTableTag;
+
+/** \class SkTypeface
+
+ The SkTypeface class specifies the typeface and intrinsic style of a font.
+ This is used in the paint, along with optionally algorithmic settings like
+ textSize, textSkewX, textScaleX, kFakeBoldText_Mask, to specify
+ how text appears when drawn (and measured).
+
+ Typeface objects are immutable, and so they can be shared between threads.
+*/
+class SK_API SkTypeface : public SkWeakRefCnt {
+public:
+ /** Returns the typeface's intrinsic style attributes. */
+ SkFontStyle fontStyle() const {
+ return fStyle;
+ }
+
+ /** Returns true if style() has the kBold bit set. */
+ bool isBold() const { return fStyle.weight() >= SkFontStyle::kSemiBold_Weight; }
+
+ /** Returns true if style() has the kItalic bit set. */
+ bool isItalic() const { return fStyle.slant() != SkFontStyle::kUpright_Slant; }
+
+ /** Returns true if the typeface claims to be fixed-pitch.
+ * This is a style bit, advance widths may vary even if this returns true.
+ */
+ bool isFixedPitch() const { return fIsFixedPitch; }
+
+ /** Copy into 'coordinates' (allocated by the caller) the design variation coordinates.
+ *
+ * @param coordinates the buffer into which to write the design variation coordinates.
+ * @param coordinateCount the number of entries available through 'coordinates'.
+ *
+ * @return The number of axes, or -1 if there is an error.
+ * If 'coordinates != nullptr' and 'coordinateCount >= numAxes' then 'coordinates' will be
+ * filled with the variation coordinates describing the position of this typeface in design
+ * variation space. It is possible the number of axes can be retrieved but actual position
+ * cannot.
+ */
+ int getVariationDesignPosition(SkFontArguments::VariationPosition::Coordinate coordinates[],
+ int coordinateCount) const;
+
+ /** Copy into 'parameters' (allocated by the caller) the design variation parameters.
+ *
+ * @param parameters the buffer into which to write the design variation parameters.
+ * @param coordinateCount the number of entries available through 'parameters'.
+ *
+ * @return The number of axes, or -1 if there is an error.
+ * If 'parameters != nullptr' and 'parameterCount >= numAxes' then 'parameters' will be
+ * filled with the variation parameters describing the position of this typeface in design
+ * variation space. It is possible the number of axes can be retrieved but actual parameters
+ * cannot.
+ */
+ int getVariationDesignParameters(SkFontParameters::Variation::Axis parameters[],
+ int parameterCount) const;
+
+ /** Return a 32bit value for this typeface, unique for the underlying font
+ data. Will never return 0.
+ */
+ SkFontID uniqueID() const { return fUniqueID; }
+
+ /** Return the uniqueID for the specified typeface. If the face is null,
+ resolve it to the default font and return its uniqueID. Will never
+ return 0.
+ */
+ static SkFontID UniqueID(const SkTypeface* face);
+
+ /** Returns true if the two typefaces reference the same underlying font,
+ handling either being null (treating null as the default font)
+ */
+ static bool Equal(const SkTypeface* facea, const SkTypeface* faceb);
+
+ /** Returns the default normal typeface, which is never nullptr. */
+ static sk_sp<SkTypeface> MakeDefault();
+
+ /** Creates a new reference to the typeface that most closely matches the
+ requested familyName and fontStyle. This method allows extended font
+ face specifiers as in the SkFontStyle type. Will never return null.
+
+ @param familyName May be NULL. The name of the font family.
+ @param fontStyle The style of the typeface.
+ @return reference to the closest-matching typeface. Call must call
+ unref() when they are done.
+ */
+ static sk_sp<SkTypeface> MakeFromName(const char familyName[], SkFontStyle fontStyle);
+
+ /** Return a new typeface given a file. If the file does not exist, or is
+ not a valid font file, returns nullptr.
+ */
+ static sk_sp<SkTypeface> MakeFromFile(const char path[], int index = 0);
+
+ /** Return a new typeface given a stream. If the stream is
+ not a valid font file, returns nullptr. Ownership of the stream is
+ transferred, so the caller must not reference it again.
+ */
+ static sk_sp<SkTypeface> MakeFromStream(std::unique_ptr<SkStreamAsset> stream, int index = 0);
+
+ /** Return a new typeface given a SkData. If the data is null, or is not a valid font file,
+ * returns nullptr.
+ */
+ static sk_sp<SkTypeface> MakeFromData(sk_sp<SkData>, int index = 0);
+
+ /** Return a new typeface based on this typeface but parameterized as specified in the
+ SkFontArguments. If the SkFontArguments does not supply an argument for a parameter
+ in the font then the value from this typeface will be used as the value for that
+ argument. If the cloned typeface would be exaclty the same as this typeface then
+ this typeface may be ref'ed and returned. May return nullptr on failure.
+ */
+ sk_sp<SkTypeface> makeClone(const SkFontArguments&) const;
+
+ /**
+ * A typeface can serialize just a descriptor (names, etc.), or it can also include the
+ * actual font data (which can be large). This enum controls how serialize() decides what
+ * to serialize.
+ */
+ enum class SerializeBehavior {
+ kDoIncludeData,
+ kDontIncludeData,
+ kIncludeDataIfLocal,
+ };
+
+ /** Write a unique signature to a stream, sufficient to reconstruct a
+ typeface referencing the same font when Deserialize is called.
+ */
+ void serialize(SkWStream*, SerializeBehavior = SerializeBehavior::kIncludeDataIfLocal) const;
+
+ /**
+ * Same as serialize(SkWStream*, ...) but returns the serialized data in SkData, instead of
+ * writing it to a stream.
+ */
+ sk_sp<SkData> serialize(SerializeBehavior = SerializeBehavior::kIncludeDataIfLocal) const;
+
+ /** Given the data previously written by serialize(), return a new instance
+ of a typeface referring to the same font. If that font is not available,
+ return nullptr.
+ Does not affect ownership of SkStream.
+ */
+ static sk_sp<SkTypeface> MakeDeserialize(SkStream*);
+
+ /**
+ * Given an array of UTF32 character codes, return their corresponding glyph IDs.
+ *
+ * @param chars pointer to the array of UTF32 chars
+ * @param number of chars and glyphs
+ * @param glyphs returns the corresponding glyph IDs for each character.
+ */
+ void unicharsToGlyphs(const SkUnichar uni[], int count, SkGlyphID glyphs[]) const;
+
+ int textToGlyphs(const void* text, size_t byteLength, SkTextEncoding encoding,
+ SkGlyphID glyphs[], int maxGlyphCount) const;
+
+ /**
+ * Return the glyphID that corresponds to the specified unicode code-point
+ * (in UTF32 encoding). If the unichar is not supported, returns 0.
+ *
+ * This is a short-cut for calling unicharsToGlyphs().
+ */
+ SkGlyphID unicharToGlyph(SkUnichar unichar) const;
+
+ /**
+ * Return the number of glyphs in the typeface.
+ */
+ int countGlyphs() const;
+
+ // Table getters -- may fail if the underlying font format is not organized
+ // as 4-byte tables.
+
+ /** Return the number of tables in the font. */
+ int countTables() const;
+
+ /** Copy into tags[] (allocated by the caller) the list of table tags in
+ * the font, and return the number. This will be the same as CountTables()
+ * or 0 if an error occured. If tags == NULL, this only returns the count
+ * (the same as calling countTables()).
+ */
+ int getTableTags(SkFontTableTag tags[]) const;
+
+ /** Given a table tag, return the size of its contents, or 0 if not present
+ */
+ size_t getTableSize(SkFontTableTag) const;
+
+ /** Copy the contents of a table into data (allocated by the caller). Note
+ * that the contents of the table will be in their native endian order
+ * (which for most truetype tables is big endian). If the table tag is
+ * not found, or there is an error copying the data, then 0 is returned.
+ * If this happens, it is possible that some or all of the memory pointed
+ * to by data may have been written to, even though an error has occured.
+ *
+ * @param tag The table tag whose contents are to be copied
+ * @param offset The offset in bytes into the table's contents where the
+ * copy should start from.
+ * @param length The number of bytes, starting at offset, of table data
+ * to copy.
+ * @param data storage address where the table contents are copied to
+ * @return the number of bytes actually copied into data. If offset+length
+ * exceeds the table's size, then only the bytes up to the table's
+ * size are actually copied, and this is the value returned. If
+ * offset > the table's size, or tag is not a valid table,
+ * then 0 is returned.
+ */
+ size_t getTableData(SkFontTableTag tag, size_t offset, size_t length,
+ void* data) const;
+
+ /**
+ * Return an immutable copy of the requested font table, or nullptr if that table was
+ * not found. This can sometimes be faster than calling getTableData() twice: once to find
+ * the length, and then again to copy the data.
+ *
+ * @param tag The table tag whose contents are to be copied
+ * @return an immutable copy of the table's data, or nullptr.
+ */
+ sk_sp<SkData> copyTableData(SkFontTableTag tag) const;
+
+ /**
+ * Return the units-per-em value for this typeface, or zero if there is an
+ * error.
+ */
+ int getUnitsPerEm() const;
+
+ /**
+ * Given a run of glyphs, return the associated horizontal adjustments.
+ * Adjustments are in "design units", which are integers relative to the
+ * typeface's units per em (see getUnitsPerEm).
+ *
+ * Some typefaces are known to never support kerning. Calling this method
+ * with all zeros (e.g. getKerningPairAdustments(NULL, 0, NULL)) returns
+ * a boolean indicating if the typeface might support kerning. If it
+ * returns false, then it will always return false (no kerning) for all
+ * possible glyph runs. If it returns true, then it *may* return true for
+ * somne glyph runs.
+ *
+ * If count is non-zero, then the glyphs parameter must point to at least
+ * [count] valid glyph IDs, and the adjustments parameter must be
+ * sized to at least [count - 1] entries. If the method returns true, then
+ * [count-1] entries in the adjustments array will be set. If the method
+ * returns false, then no kerning should be applied, and the adjustments
+ * array will be in an undefined state (possibly some values may have been
+ * written, but none of them should be interpreted as valid values).
+ */
+ bool getKerningPairAdjustments(const SkGlyphID glyphs[], int count,
+ int32_t adjustments[]) const;
+
+ struct LocalizedString {
+ SkString fString;
+ SkString fLanguage;
+ };
+ class LocalizedStrings {
+ public:
+ LocalizedStrings() = default;
+ virtual ~LocalizedStrings() { }
+ virtual bool next(LocalizedString* localizedString) = 0;
+ void unref() { delete this; }
+
+ private:
+ LocalizedStrings(const LocalizedStrings&) = delete;
+ LocalizedStrings& operator=(const LocalizedStrings&) = delete;
+ };
+ /**
+ * Returns an iterator which will attempt to enumerate all of the
+ * family names specified by the font.
+ * It is the caller's responsibility to unref() the returned pointer.
+ */
+ LocalizedStrings* createFamilyNameIterator() const;
+
+ /**
+ * Return the family name for this typeface. It will always be returned
+ * encoded as UTF8, but the language of the name is whatever the host
+ * platform chooses.
+ */
+ void getFamilyName(SkString* name) const;
+
+ /**
+ * Return the PostScript name for this typeface.
+ * Value may change based on variation parameters.
+ * Returns false if no PostScript name is available.
+ */
+ bool getPostScriptName(SkString* name) const;
+
+ /**
+ * Return a stream for the contents of the font data, or NULL on failure.
+ * If ttcIndex is not null, it is set to the TrueTypeCollection index
+ * of this typeface within the stream, or 0 if the stream is not a
+ * collection.
+ * The caller is responsible for deleting the stream.
+ */
+ std::unique_ptr<SkStreamAsset> openStream(int* ttcIndex) const;
+
+ /**
+ * Return a scalercontext for the given descriptor. It may return a
+ * stub scalercontext that will not crash, but will draw nothing.
+ */
+ std::unique_ptr<SkScalerContext> createScalerContext(const SkScalerContextEffects&,
+ const SkDescriptor*) const;
+
+ /**
+ * Return a rectangle (scaled to 1-pt) that represents the union of the bounds of all
+ * of the glyphs, but each one positioned at (0,). This may be conservatively large, and
+ * will not take into account any hinting or other size-specific adjustments.
+ */
+ SkRect getBounds() const;
+
+ // PRIVATE / EXPERIMENTAL -- do not call
+ void filterRec(SkScalerContextRec* rec) const {
+ this->onFilterRec(rec);
+ }
+ // PRIVATE / EXPERIMENTAL -- do not call
+ void getFontDescriptor(SkFontDescriptor* desc, bool* isLocal) const {
+ this->onGetFontDescriptor(desc, isLocal);
+ }
+ // PRIVATE / EXPERIMENTAL -- do not call
+ void* internal_private_getCTFontRef() const {
+ return this->onGetCTFontRef();
+ }
+
+protected:
+ explicit SkTypeface(const SkFontStyle& style, bool isFixedPitch = false);
+ ~SkTypeface() override;
+
+ virtual sk_sp<SkTypeface> onMakeClone(const SkFontArguments&) const = 0;
+
+ /** Sets the fixedPitch bit. If used, must be called in the constructor. */
+ void setIsFixedPitch(bool isFixedPitch) { fIsFixedPitch = isFixedPitch; }
+ /** Sets the font style. If used, must be called in the constructor. */
+ void setFontStyle(SkFontStyle style) { fStyle = style; }
+
+ // Must return a valid scaler context. It can not return nullptr.
+ virtual std::unique_ptr<SkScalerContext> onCreateScalerContext(const SkScalerContextEffects&,
+ const SkDescriptor*) const = 0;
+ virtual void onFilterRec(SkScalerContextRec*) const = 0;
+ friend class SkScalerContext; // onFilterRec
+
+ // Subclasses *must* override this method to work with the PDF backend.
+ virtual std::unique_ptr<SkAdvancedTypefaceMetrics> onGetAdvancedMetrics() const = 0;
+ // For type1 postscript fonts only, set the glyph names for each glyph.
+ // destination array is non-null, and points to an array of size this->countGlyphs().
+ // Backends that do not suport type1 fonts should not override.
+ virtual void getPostScriptGlyphNames(SkString*) const = 0;
+
+ // The mapping from glyph to Unicode; array indices are glyph ids.
+ // For each glyph, give the default Unicode value, if it exists.
+ // dstArray is non-null, and points to an array of size this->countGlyphs().
+ virtual void getGlyphToUnicodeMap(SkUnichar* dstArray) const = 0;
+
+ virtual std::unique_ptr<SkStreamAsset> onOpenStream(int* ttcIndex) const = 0;
+
+ virtual bool onGlyphMaskNeedsCurrentColor() const = 0;
+
+ virtual int onGetVariationDesignPosition(
+ SkFontArguments::VariationPosition::Coordinate coordinates[],
+ int coordinateCount) const = 0;
+
+ virtual int onGetVariationDesignParameters(
+ SkFontParameters::Variation::Axis parameters[], int parameterCount) const = 0;
+
+ virtual void onGetFontDescriptor(SkFontDescriptor*, bool* isLocal) const = 0;
+
+ virtual void onCharsToGlyphs(const SkUnichar* chars, int count, SkGlyphID glyphs[]) const = 0;
+ virtual int onCountGlyphs() const = 0;
+
+ virtual int onGetUPEM() const = 0;
+ virtual bool onGetKerningPairAdjustments(const SkGlyphID glyphs[], int count,
+ int32_t adjustments[]) const;
+
+ /** Returns the family name of the typeface as known by its font manager.
+ * This name may or may not be produced by the family name iterator.
+ */
+ virtual void onGetFamilyName(SkString* familyName) const = 0;
+ virtual bool onGetPostScriptName(SkString*) const = 0;
+
+ /** Returns an iterator over the family names in the font. */
+ virtual LocalizedStrings* onCreateFamilyNameIterator() const = 0;
+
+ virtual int onGetTableTags(SkFontTableTag tags[]) const = 0;
+ virtual size_t onGetTableData(SkFontTableTag, size_t offset,
+ size_t length, void* data) const = 0;
+ virtual sk_sp<SkData> onCopyTableData(SkFontTableTag) const;
+
+ virtual bool onComputeBounds(SkRect*) const;
+
+ virtual void* onGetCTFontRef() const { return nullptr; }
+
+private:
+ /** Returns true if the typeface's glyph masks may refer to the foreground
+ * paint foreground color. This is needed to determine caching requirements. Usually true for
+ * typefaces that contain a COLR table.
+ */
+ bool glyphMaskNeedsCurrentColor() const;
+ friend class SkStrikeServerImpl; // glyphMaskNeedsCurrentColor
+
+ /** Retrieve detailed typeface metrics. Used by the PDF backend. */
+ std::unique_ptr<SkAdvancedTypefaceMetrics> getAdvancedMetrics() const;
+ friend class SkRandomTypeface; // getAdvancedMetrics
+ friend class SkPDFFont; // getAdvancedMetrics
+
+ /** Style specifies the intrinsic style attributes of a given typeface */
+ enum Style {
+ kNormal = 0,
+ kBold = 0x01,
+ kItalic = 0x02,
+
+ // helpers
+ kBoldItalic = 0x03
+ };
+ static SkFontStyle FromOldStyle(Style oldStyle);
+ static SkTypeface* GetDefaultTypeface(Style style = SkTypeface::kNormal);
+
+ friend class SkFontPriv; // GetDefaultTypeface
+ friend class SkPaintPriv; // GetDefaultTypeface
+ friend class SkFont; // getGlyphToUnicodeMap
+
+private:
+ SkFontID fUniqueID;
+ SkFontStyle fStyle;
+ mutable SkRect fBounds;
+ mutable SkOnce fBoundsOnce;
+ bool fIsFixedPitch;
+
+ using INHERITED = SkWeakRefCnt;
+};
+#endif
diff --git a/src/deps/skia/include/core/SkTypes.h b/src/deps/skia/include/core/SkTypes.h
new file mode 100644
index 000000000..1d94990d6
--- /dev/null
+++ b/src/deps/skia/include/core/SkTypes.h
@@ -0,0 +1,621 @@
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkTypes_DEFINED
+#define SkTypes_DEFINED
+
+/** \file SkTypes.h
+*/
+
+// Pre-SkUserConfig.h setup.
+
+// Allows embedders that want to disable macros that take arguments to just
+// define that symbol to be one of these
+#define SK_NOTHING_ARG1(arg1)
+#define SK_NOTHING_ARG2(arg1, arg2)
+#define SK_NOTHING_ARG3(arg1, arg2, arg3)
+
+#if !defined(SK_BUILD_FOR_ANDROID) && !defined(SK_BUILD_FOR_IOS) && !defined(SK_BUILD_FOR_WIN) && \
+ !defined(SK_BUILD_FOR_UNIX) && !defined(SK_BUILD_FOR_MAC)
+
+ #ifdef __APPLE__
+ #include <TargetConditionals.h>
+ #endif
+
+ #if defined(_WIN32) || defined(__SYMBIAN32__)
+ #define SK_BUILD_FOR_WIN
+ #elif defined(ANDROID) || defined(__ANDROID__)
+ #define SK_BUILD_FOR_ANDROID
+ #elif defined(linux) || defined(__linux) || defined(__FreeBSD__) || \
+ defined(__OpenBSD__) || defined(__sun) || defined(__NetBSD__) || \
+ defined(__DragonFly__) || defined(__Fuchsia__) || \
+ defined(__GLIBC__) || defined(__GNU__) || defined(__unix__)
+ #define SK_BUILD_FOR_UNIX
+ #elif TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR
+ #define SK_BUILD_FOR_IOS
+ #else
+ #define SK_BUILD_FOR_MAC
+ #endif
+
+#endif
+
+#if defined(SK_BUILD_FOR_WIN) && !defined(__clang__)
+ #if !defined(SK_RESTRICT)
+ #define SK_RESTRICT __restrict
+ #endif
+ #if !defined(SK_WARN_UNUSED_RESULT)
+ #define SK_WARN_UNUSED_RESULT
+ #endif
+#endif
+
+#if !defined(SK_RESTRICT)
+ #define SK_RESTRICT __restrict__
+#endif
+
+#if !defined(SK_WARN_UNUSED_RESULT)
+ #define SK_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
+#endif
+
+#if !defined(SK_CPU_BENDIAN) && !defined(SK_CPU_LENDIAN)
+ #if defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
+ #define SK_CPU_BENDIAN
+ #elif defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
+ #define SK_CPU_LENDIAN
+ #elif defined(__sparc) || defined(__sparc__) || \
+ defined(_POWER) || defined(__powerpc__) || \
+ defined(__ppc__) || defined(__hppa) || \
+ defined(__PPC__) || defined(__PPC64__) || \
+ defined(_MIPSEB) || defined(__ARMEB__) || \
+ defined(__s390__) || \
+ (defined(__sh__) && defined(__BIG_ENDIAN__)) || \
+ (defined(__ia64) && defined(__BIG_ENDIAN__))
+ #define SK_CPU_BENDIAN
+ #else
+ #define SK_CPU_LENDIAN
+ #endif
+#endif
+
+#if defined(__i386) || defined(_M_IX86) || defined(__x86_64__) || defined(_M_X64)
+ #define SK_CPU_X86 1
+#endif
+
+/**
+ * SK_CPU_SSE_LEVEL
+ *
+ * If defined, SK_CPU_SSE_LEVEL should be set to the highest supported level.
+ * On non-intel CPU this should be undefined.
+ */
+#define SK_CPU_SSE_LEVEL_SSE1 10
+#define SK_CPU_SSE_LEVEL_SSE2 20
+#define SK_CPU_SSE_LEVEL_SSE3 30
+#define SK_CPU_SSE_LEVEL_SSSE3 31
+#define SK_CPU_SSE_LEVEL_SSE41 41
+#define SK_CPU_SSE_LEVEL_SSE42 42
+#define SK_CPU_SSE_LEVEL_AVX 51
+#define SK_CPU_SSE_LEVEL_AVX2 52
+#define SK_CPU_SSE_LEVEL_SKX 60
+
+// Are we in GCC/Clang?
+#ifndef SK_CPU_SSE_LEVEL
+ // These checks must be done in descending order to ensure we set the highest
+ // available SSE level.
+ #if defined(__AVX512F__) && defined(__AVX512DQ__) && defined(__AVX512CD__) && \
+ defined(__AVX512BW__) && defined(__AVX512VL__)
+ #define SK_CPU_SSE_LEVEL SK_CPU_SSE_LEVEL_SKX
+ #elif defined(__AVX2__)
+ #define SK_CPU_SSE_LEVEL SK_CPU_SSE_LEVEL_AVX2
+ #elif defined(__AVX__)
+ #define SK_CPU_SSE_LEVEL SK_CPU_SSE_LEVEL_AVX
+ #elif defined(__SSE4_2__)
+ #define SK_CPU_SSE_LEVEL SK_CPU_SSE_LEVEL_SSE42
+ #elif defined(__SSE4_1__)
+ #define SK_CPU_SSE_LEVEL SK_CPU_SSE_LEVEL_SSE41
+ #elif defined(__SSSE3__)
+ #define SK_CPU_SSE_LEVEL SK_CPU_SSE_LEVEL_SSSE3
+ #elif defined(__SSE3__)
+ #define SK_CPU_SSE_LEVEL SK_CPU_SSE_LEVEL_SSE3
+ #elif defined(__SSE2__)
+ #define SK_CPU_SSE_LEVEL SK_CPU_SSE_LEVEL_SSE2
+ #endif
+#endif
+
+// Are we in VisualStudio?
+#ifndef SK_CPU_SSE_LEVEL
+ // These checks must be done in descending order to ensure we set the highest
+ // available SSE level. 64-bit intel guarantees at least SSE2 support.
+ #if defined(__AVX512F__) && defined(__AVX512DQ__) && defined(__AVX512CD__) && \
+ defined(__AVX512BW__) && defined(__AVX512VL__)
+ #define SK_CPU_SSE_LEVEL SK_CPU_SSE_LEVEL_SKX
+ #elif defined(__AVX2__)
+ #define SK_CPU_SSE_LEVEL SK_CPU_SSE_LEVEL_AVX2
+ #elif defined(__AVX__)
+ #define SK_CPU_SSE_LEVEL SK_CPU_SSE_LEVEL_AVX
+ #elif defined(_M_X64) || defined(_M_AMD64)
+ #define SK_CPU_SSE_LEVEL SK_CPU_SSE_LEVEL_SSE2
+ #elif defined(_M_IX86_FP)
+ #if _M_IX86_FP >= 2
+ #define SK_CPU_SSE_LEVEL SK_CPU_SSE_LEVEL_SSE2
+ #elif _M_IX86_FP == 1
+ #define SK_CPU_SSE_LEVEL SK_CPU_SSE_LEVEL_SSE1
+ #endif
+ #endif
+#endif
+
+// ARM defines
+#if defined(__arm__) && (!defined(__APPLE__) || !TARGET_IPHONE_SIMULATOR)
+ #define SK_CPU_ARM32
+#elif defined(__aarch64__)
+ #define SK_CPU_ARM64
+#endif
+
+// All 64-bit ARM chips have NEON. Many 32-bit ARM chips do too.
+#if !defined(SK_ARM_HAS_NEON) && defined(__ARM_NEON)
+ #define SK_ARM_HAS_NEON
+#endif
+
+#if defined(__ARM_FEATURE_CRC32)
+ #define SK_ARM_HAS_CRC32
+#endif
+
+
+// DLL/.so exports.
+#if !defined(SKIA_IMPLEMENTATION)
+ #define SKIA_IMPLEMENTATION 0
+#endif
+#if !defined(SK_API)
+ #if defined(SKIA_DLL)
+ #if defined(_MSC_VER)
+ #if SKIA_IMPLEMENTATION
+ #define SK_API __declspec(dllexport)
+ #else
+ #define SK_API __declspec(dllimport)
+ #endif
+ #else
+ #define SK_API __attribute__((visibility("default")))
+ #endif
+ #else
+ #define SK_API
+ #endif
+#endif
+
+// SK_SPI is functionally identical to SK_API, but used within src to clarify that it's less stable
+#if !defined(SK_SPI)
+ #define SK_SPI SK_API
+#endif
+
+// IWYU pragma: begin_exports
+#if defined (SK_USER_CONFIG_HEADER)
+ #include SK_USER_CONFIG_HEADER
+#else
+ #include "include/config/SkUserConfig.h"
+#endif
+#include <stddef.h>
+#include <stdint.h>
+// IWYU pragma: end_exports
+
+// Post SkUserConfig.h checks and such.
+#if !defined(SK_DEBUG) && !defined(SK_RELEASE)
+ #ifdef NDEBUG
+ #define SK_RELEASE
+ #else
+ #define SK_DEBUG
+ #endif
+#endif
+
+#if defined(SK_DEBUG) && defined(SK_RELEASE)
+# error "cannot define both SK_DEBUG and SK_RELEASE"
+#elif !defined(SK_DEBUG) && !defined(SK_RELEASE)
+# error "must define either SK_DEBUG or SK_RELEASE"
+#endif
+
+#if defined(SK_CPU_LENDIAN) && defined(SK_CPU_BENDIAN)
+# error "cannot define both SK_CPU_LENDIAN and SK_CPU_BENDIAN"
+#elif !defined(SK_CPU_LENDIAN) && !defined(SK_CPU_BENDIAN)
+# error "must define either SK_CPU_LENDIAN or SK_CPU_BENDIAN"
+#endif
+
+#if defined(SK_CPU_BENDIAN) && !defined(I_ACKNOWLEDGE_SKIA_DOES_NOT_SUPPORT_BIG_ENDIAN)
+ #error "The Skia team is not endian-savvy enough to support big-endian CPUs."
+ #error "If you still want to use Skia,"
+ #error "please define I_ACKNOWLEDGE_SKIA_DOES_NOT_SUPPORT_BIG_ENDIAN."
+#endif
+
+#if !defined(SK_ATTRIBUTE)
+# if defined(__clang__) || defined(__GNUC__)
+# define SK_ATTRIBUTE(attr) __attribute__((attr))
+# else
+# define SK_ATTRIBUTE(attr)
+# endif
+#endif
+
+#if !defined(SK_SUPPORT_GPU)
+# define SK_SUPPORT_GPU 1
+#endif
+
+#if SK_SUPPORT_GPU || SK_GRAPHITE_ENABLED
+# if !defined(SK_ENABLE_SKSL)
+# define SK_ENABLE_SKSL
+# endif
+#else
+# undef SK_GL
+# undef SK_VULKAN
+# undef SK_METAL
+# undef SK_DAWN
+# undef SK_DIRECT3D
+#endif
+
+#if !defined(SkUNREACHABLE)
+# if defined(_MSC_VER) && !defined(__clang__)
+# include <intrin.h>
+# define FAST_FAIL_INVALID_ARG 5
+// See https://developercommunity.visualstudio.com/content/problem/1128631/code-flow-doesnt-see-noreturn-with-extern-c.html
+// for why this is wrapped. Hopefully removable after msvc++ 19.27 is no longer supported.
+[[noreturn]] static inline void sk_fast_fail() { __fastfail(FAST_FAIL_INVALID_ARG); }
+# define SkUNREACHABLE sk_fast_fail()
+# else
+# define SkUNREACHABLE __builtin_trap()
+# endif
+#endif
+
+#if defined(SK_BUILD_FOR_GOOGLE3)
+ void SkDebugfForDumpStackTrace(const char* data, void* unused);
+ void DumpStackTrace(int skip_count, void w(const char*, void*), void* arg);
+# define SK_DUMP_GOOGLE3_STACK() DumpStackTrace(0, SkDebugfForDumpStackTrace, nullptr)
+#else
+# define SK_DUMP_GOOGLE3_STACK()
+#endif
+
+#ifndef SK_ABORT
+# ifdef SK_BUILD_FOR_WIN
+ // This style lets Visual Studio follow errors back to the source file.
+# define SK_DUMP_LINE_FORMAT "%s(%d)"
+# else
+# define SK_DUMP_LINE_FORMAT "%s:%d"
+# endif
+# define SK_ABORT(message, ...) \
+ do { \
+ SkDebugf(SK_DUMP_LINE_FORMAT ": fatal error: \"" message "\"\n", \
+ __FILE__, __LINE__, ##__VA_ARGS__); \
+ SK_DUMP_GOOGLE3_STACK(); \
+ sk_abort_no_print(); \
+ } while (false)
+#endif
+
+// If SK_R32_SHIFT is set, we'll use that to choose RGBA or BGRA.
+// If not, we'll default to RGBA everywhere except BGRA on Windows.
+#if defined(SK_R32_SHIFT)
+ static_assert(SK_R32_SHIFT == 0 || SK_R32_SHIFT == 16, "");
+#elif defined(SK_BUILD_FOR_WIN)
+ #define SK_R32_SHIFT 16
+#else
+ #define SK_R32_SHIFT 0
+#endif
+
+#if defined(SK_B32_SHIFT)
+ static_assert(SK_B32_SHIFT == (16-SK_R32_SHIFT), "");
+#else
+ #define SK_B32_SHIFT (16-SK_R32_SHIFT)
+#endif
+
+#define SK_G32_SHIFT 8
+#define SK_A32_SHIFT 24
+
+
+/**
+ * SK_PMCOLOR_BYTE_ORDER can be used to query the byte order of SkPMColor at compile time.
+ */
+#ifdef SK_CPU_BENDIAN
+# define SK_PMCOLOR_BYTE_ORDER(C0, C1, C2, C3) \
+ (SK_ ## C3 ## 32_SHIFT == 0 && \
+ SK_ ## C2 ## 32_SHIFT == 8 && \
+ SK_ ## C1 ## 32_SHIFT == 16 && \
+ SK_ ## C0 ## 32_SHIFT == 24)
+#else
+# define SK_PMCOLOR_BYTE_ORDER(C0, C1, C2, C3) \
+ (SK_ ## C0 ## 32_SHIFT == 0 && \
+ SK_ ## C1 ## 32_SHIFT == 8 && \
+ SK_ ## C2 ## 32_SHIFT == 16 && \
+ SK_ ## C3 ## 32_SHIFT == 24)
+#endif
+
+#if defined SK_DEBUG && defined SK_BUILD_FOR_WIN
+ #ifdef free
+ #undef free
+ #endif
+ #include <crtdbg.h>
+ #undef free
+#endif
+
+#if !defined(SK_UNUSED)
+# if !defined(__clang__) && defined(_MSC_VER)
+# define SK_UNUSED __pragma(warning(suppress:4189))
+# else
+# define SK_UNUSED SK_ATTRIBUTE(unused)
+# endif
+#endif
+
+#if !defined(SK_MAYBE_UNUSED)
+# if defined(__clang__) || defined(__GNUC__)
+# define SK_MAYBE_UNUSED [[maybe_unused]]
+# else
+# define SK_MAYBE_UNUSED
+# endif
+#endif
+
+/**
+ * If your judgment is better than the compiler's (i.e. you've profiled it),
+ * you can use SK_ALWAYS_INLINE to force inlining. E.g.
+ * inline void someMethod() { ... } // may not be inlined
+ * SK_ALWAYS_INLINE void someMethod() { ... } // should always be inlined
+ */
+#if !defined(SK_ALWAYS_INLINE)
+# if defined(SK_BUILD_FOR_WIN)
+# define SK_ALWAYS_INLINE __forceinline
+# else
+# define SK_ALWAYS_INLINE SK_ATTRIBUTE(always_inline) inline
+# endif
+#endif
+
+/**
+ * If your judgment is better than the compiler's (i.e. you've profiled it),
+ * you can use SK_NEVER_INLINE to prevent inlining.
+ */
+#if !defined(SK_NEVER_INLINE)
+# if defined(SK_BUILD_FOR_WIN)
+# define SK_NEVER_INLINE __declspec(noinline)
+# else
+# define SK_NEVER_INLINE SK_ATTRIBUTE(noinline)
+# endif
+#endif
+
+#ifndef SK_PRINTF_LIKE
+# if defined(__clang__) || defined(__GNUC__)
+# define SK_PRINTF_LIKE(A, B) __attribute__((format(printf, (A), (B))))
+# else
+# define SK_PRINTF_LIKE(A, B)
+# endif
+#endif
+
+#ifndef SK_ALLOW_STATIC_GLOBAL_INITIALIZERS
+ #define SK_ALLOW_STATIC_GLOBAL_INITIALIZERS 0
+#endif
+
+#if !defined(SK_GAMMA_EXPONENT)
+ #define SK_GAMMA_EXPONENT (0.0f) // SRGB
+#endif
+
+#ifndef GR_TEST_UTILS
+# define GR_TEST_UTILS 0
+#endif
+
+#ifndef SK_GPU_V1
+# define SK_GPU_V1 1
+#endif
+
+#if defined(SK_HISTOGRAM_ENUMERATION) || \
+ defined(SK_HISTOGRAM_BOOLEAN) || \
+ defined(SK_HISTOGRAM_EXACT_LINEAR) || \
+ defined(SK_HISTOGRAM_MEMORY_KB)
+# define SK_HISTOGRAMS_ENABLED 1
+#else
+# define SK_HISTOGRAMS_ENABLED 0
+#endif
+
+#ifndef SK_HISTOGRAM_BOOLEAN
+# define SK_HISTOGRAM_BOOLEAN(name, sample)
+#endif
+
+#ifndef SK_HISTOGRAM_ENUMERATION
+# define SK_HISTOGRAM_ENUMERATION(name, sample, enum_size)
+#endif
+
+#ifndef SK_HISTOGRAM_EXACT_LINEAR
+# define SK_HISTOGRAM_EXACT_LINEAR(name, sample, value_max)
+#endif
+
+#ifndef SK_HISTOGRAM_MEMORY_KB
+# define SK_HISTOGRAM_MEMORY_KB(name, sample)
+#endif
+
+#define SK_HISTOGRAM_PERCENTAGE(name, percent_as_int) \
+ SK_HISTOGRAM_EXACT_LINEAR(name, percent_as_int, 101)
+
+#ifndef SK_DISABLE_LEGACY_SHADERCONTEXT
+#define SK_ENABLE_LEGACY_SHADERCONTEXT
+#endif
+
+#ifdef SK_ENABLE_API_AVAILABLE
+#define SK_API_AVAILABLE API_AVAILABLE
+#else
+#define SK_API_AVAILABLE(...)
+#endif
+
+#if defined(SK_BUILD_FOR_LIBFUZZER) || defined(SK_BUILD_FOR_AFL_FUZZ)
+ #define SK_BUILD_FOR_FUZZER
+#endif
+
+/** Called internally if we hit an unrecoverable error.
+ The platform implementation must not return, but should either throw
+ an exception or otherwise exit.
+*/
+[[noreturn]] SK_API extern void sk_abort_no_print(void);
+
+#ifndef SkDebugf
+ SK_API void SkDebugf(const char format[], ...) SK_PRINTF_LIKE(1, 2);
+#endif
+
+// SkASSERT, SkASSERTF and SkASSERT_RELEASE can be used as stand alone assertion expressions, e.g.
+// uint32_t foo(int x) {
+// SkASSERT(x > 4);
+// return x - 4;
+// }
+// and are also written to be compatible with constexpr functions:
+// constexpr uint32_t foo(int x) {
+// return SkASSERT(x > 4),
+// x - 4;
+// }
+#define SkASSERT_RELEASE(cond) \
+ static_cast<void>( (cond) ? (void)0 : []{ SK_ABORT("assert(%s)", #cond); }() )
+
+#ifdef SK_DEBUG
+ #define SkASSERT(cond) SkASSERT_RELEASE(cond)
+ #define SkASSERTF(cond, fmt, ...) static_cast<void>( (cond) ? (void)0 : [&]{ \
+ SkDebugf(fmt"\n", ##__VA_ARGS__); \
+ SK_ABORT("assert(%s)", #cond); \
+ }() )
+ #define SkDEBUGFAIL(message) SK_ABORT("%s", message)
+ #define SkDEBUGFAILF(fmt, ...) SK_ABORT(fmt, ##__VA_ARGS__)
+ #define SkDEBUGCODE(...) __VA_ARGS__
+ #define SkDEBUGF(...) SkDebugf(__VA_ARGS__)
+ #define SkAssertResult(cond) SkASSERT(cond)
+#else
+ #define SkASSERT(cond) static_cast<void>(0)
+ #define SkASSERTF(cond, fmt, ...) static_cast<void>(0)
+ #define SkDEBUGFAIL(message)
+ #define SkDEBUGFAILF(fmt, ...)
+ #define SkDEBUGCODE(...)
+ #define SkDEBUGF(...)
+
+ // unlike SkASSERT, this macro executes its condition in the non-debug build.
+ // The if is present so that this can be used with functions marked SK_WARN_UNUSED_RESULT.
+ #define SkAssertResult(cond) if (cond) {} do {} while(false)
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+
+/** Fast type for unsigned 8 bits. Use for parameter passing and local
+ variables, not for storage
+*/
+typedef unsigned U8CPU;
+
+/** Fast type for unsigned 16 bits. Use for parameter passing and local
+ variables, not for storage
+*/
+typedef unsigned U16CPU;
+
+/** @return false or true based on the condition
+*/
+template <typename T> static constexpr bool SkToBool(const T& x) {
+ return 0 != x; // NOLINT(modernize-use-nullptr)
+}
+
+static constexpr int16_t SK_MaxS16 = INT16_MAX;
+static constexpr int16_t SK_MinS16 = -SK_MaxS16;
+
+static constexpr int32_t SK_MaxS32 = INT32_MAX;
+static constexpr int32_t SK_MinS32 = -SK_MaxS32;
+static constexpr int32_t SK_NaN32 = INT32_MIN;
+
+static constexpr int64_t SK_MaxS64 = INT64_MAX;
+static constexpr int64_t SK_MinS64 = -SK_MaxS64;
+
+static inline constexpr int32_t SkLeftShift(int32_t value, int32_t shift) {
+ return (int32_t) ((uint32_t) value << shift);
+}
+
+static inline constexpr int64_t SkLeftShift(int64_t value, int32_t shift) {
+ return (int64_t) ((uint64_t) value << shift);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+/** @return the number of entries in an array (not a pointer)
+*/
+template <typename T, size_t N> char (&SkArrayCountHelper(T (&array)[N]))[N];
+#define SK_ARRAY_COUNT(array) (sizeof(SkArrayCountHelper(array)))
+
+////////////////////////////////////////////////////////////////////////////////
+
+template <typename T> static constexpr T SkAlign2(T x) { return (x + 1) >> 1 << 1; }
+template <typename T> static constexpr T SkAlign4(T x) { return (x + 3) >> 2 << 2; }
+template <typename T> static constexpr T SkAlign8(T x) { return (x + 7) >> 3 << 3; }
+
+template <typename T> static constexpr bool SkIsAlign2(T x) { return 0 == (x & 1); }
+template <typename T> static constexpr bool SkIsAlign4(T x) { return 0 == (x & 3); }
+template <typename T> static constexpr bool SkIsAlign8(T x) { return 0 == (x & 7); }
+
+template <typename T> static constexpr T SkAlignPtr(T x) {
+ return sizeof(void*) == 8 ? SkAlign8(x) : SkAlign4(x);
+}
+template <typename T> static constexpr bool SkIsAlignPtr(T x) {
+ return sizeof(void*) == 8 ? SkIsAlign8(x) : SkIsAlign4(x);
+}
+
+/**
+ * align up to a power of 2
+ */
+static inline constexpr size_t SkAlignTo(size_t x, size_t alignment) {
+ // The same as alignment && SkIsPow2(value), w/o a dependency cycle.
+ SkASSERT(alignment && (alignment & (alignment - 1)) == 0);
+ return (x + alignment - 1) & ~(alignment - 1);
+}
+
+typedef uint32_t SkFourByteTag;
+static inline constexpr SkFourByteTag SkSetFourByteTag(char a, char b, char c, char d) {
+ return (((uint32_t)a << 24) | ((uint32_t)b << 16) | ((uint32_t)c << 8) | (uint32_t)d);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+/** 32 bit integer to hold a unicode value
+*/
+typedef int32_t SkUnichar;
+
+/** 16 bit unsigned integer to hold a glyph index
+*/
+typedef uint16_t SkGlyphID;
+
+/** 32 bit value to hold a millisecond duration
+ Note that SK_MSecMax is about 25 days.
+*/
+typedef uint32_t SkMSec;
+
+/** Maximum representable milliseconds; 24d 20h 31m 23.647s.
+*/
+static constexpr SkMSec SK_MSecMax = INT32_MAX;
+
+/** The generation IDs in Skia reserve 0 has an invalid marker.
+*/
+static constexpr uint32_t SK_InvalidGenID = 0;
+
+/** The unique IDs in Skia reserve 0 has an invalid marker.
+*/
+static constexpr uint32_t SK_InvalidUniqueID = 0;
+
+static inline int32_t SkAbs32(int32_t value) {
+ SkASSERT(value != SK_NaN32); // The most negative int32_t can't be negated.
+ if (value < 0) {
+ value = -value;
+ }
+ return value;
+}
+
+template <typename T> static inline T SkTAbs(T value) {
+ if (value < 0) {
+ value = -value;
+ }
+ return value;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+/** Indicates whether an allocation should count against a cache budget.
+*/
+enum class SkBudgeted : bool {
+ kNo = false,
+ kYes = true
+};
+
+/** Indicates whether a backing store needs to be an exact match or can be
+ larger than is strictly necessary
+*/
+enum class SkBackingFit {
+ kApprox,
+ kExact
+};
+
+#endif
diff --git a/src/deps/skia/include/core/SkUnPreMultiply.h b/src/deps/skia/include/core/SkUnPreMultiply.h
new file mode 100644
index 000000000..b492619d0
--- /dev/null
+++ b/src/deps/skia/include/core/SkUnPreMultiply.h
@@ -0,0 +1,56 @@
+
+/*
+ * Copyright 2008 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+
+
+
+#ifndef SkUnPreMultiply_DEFINED
+#define SkUnPreMultiply_DEFINED
+
+#include "include/core/SkColor.h"
+
+class SK_API SkUnPreMultiply {
+public:
+ typedef uint32_t Scale;
+
+ // index this table with alpha [0..255]
+ static const Scale* GetScaleTable() {
+ return gTable;
+ }
+
+ static Scale GetScale(U8CPU alpha) {
+ SkASSERT(alpha <= 255);
+ return gTable[alpha];
+ }
+
+ /** Usage:
+
+ const Scale* table = SkUnPreMultiply::GetScaleTable();
+
+ for (...) {
+ unsigned a = ...
+ SkUnPreMultiply::Scale scale = table[a];
+
+ red = SkUnPreMultiply::ApplyScale(scale, red);
+ ...
+ // now red is unpremultiplied
+ }
+ */
+ static U8CPU ApplyScale(Scale scale, U8CPU component) {
+ SkASSERT(component <= 255);
+ return (scale * component + (1 << 23)) >> 24;
+ }
+
+ static SkColor PMColorToColor(SkPMColor c);
+
+private:
+ static const uint32_t gTable[256];
+};
+
+#endif
diff --git a/src/deps/skia/include/core/SkVertices.h b/src/deps/skia/include/core/SkVertices.h
new file mode 100644
index 000000000..fc53e9d01
--- /dev/null
+++ b/src/deps/skia/include/core/SkVertices.h
@@ -0,0 +1,132 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkVertices_DEFINED
+#define SkVertices_DEFINED
+
+#include "include/core/SkColor.h"
+#include "include/core/SkRect.h"
+#include "include/core/SkRefCnt.h"
+
+class SkData;
+struct SkPoint;
+class SkVerticesPriv;
+
+/**
+ * An immutable set of vertex data that can be used with SkCanvas::drawVertices.
+ */
+class SK_API SkVertices : public SkNVRefCnt<SkVertices> {
+ struct Desc;
+ struct Sizes;
+public:
+ enum VertexMode {
+ kTriangles_VertexMode,
+ kTriangleStrip_VertexMode,
+ kTriangleFan_VertexMode,
+
+ kLast_VertexMode = kTriangleFan_VertexMode,
+ };
+
+ /**
+ * Create a vertices by copying the specified arrays. texs, colors may be nullptr,
+ * and indices is ignored if indexCount == 0.
+ */
+ static sk_sp<SkVertices> MakeCopy(VertexMode mode, int vertexCount,
+ const SkPoint positions[],
+ const SkPoint texs[],
+ const SkColor colors[],
+ int indexCount,
+ const uint16_t indices[]);
+
+ static sk_sp<SkVertices> MakeCopy(VertexMode mode, int vertexCount,
+ const SkPoint positions[],
+ const SkPoint texs[],
+ const SkColor colors[]) {
+ return MakeCopy(mode,
+ vertexCount,
+ positions,
+ texs,
+ colors,
+ 0,
+ nullptr);
+ }
+
+ enum BuilderFlags {
+ kHasTexCoords_BuilderFlag = 1 << 0,
+ kHasColors_BuilderFlag = 1 << 1,
+ };
+ class Builder {
+ public:
+ Builder(VertexMode mode, int vertexCount, int indexCount, uint32_t flags);
+
+ bool isValid() const { return fVertices != nullptr; }
+
+ SkPoint* positions();
+ uint16_t* indices(); // returns null if there are no indices
+
+ // If we have custom attributes, these will always be null
+ SkPoint* texCoords(); // returns null if there are no texCoords
+ SkColor* colors(); // returns null if there are no colors
+
+ // Detach the built vertices object. After the first call, this will always return null.
+ sk_sp<SkVertices> detach();
+
+ private:
+ Builder(const Desc&);
+
+ void init(const Desc&);
+
+ // holds a partially complete object. only completed in detach()
+ sk_sp<SkVertices> fVertices;
+ // Extra storage for intermediate vertices in the case where the client specifies indexed
+ // triangle fans. These get converted to indexed triangles when the Builder is finalized.
+ std::unique_ptr<uint8_t[]> fIntermediateFanIndices;
+
+ friend class SkVertices;
+ friend class SkVerticesPriv;
+ };
+
+ uint32_t uniqueID() const { return fUniqueID; }
+ const SkRect& bounds() const { return fBounds; }
+
+ // returns approximate byte size of the vertices object
+ size_t approximateSize() const;
+
+ // Provides access to functions that aren't part of the public API.
+ SkVerticesPriv priv();
+ const SkVerticesPriv priv() const; // NOLINT(readability-const-return-type)
+
+private:
+ SkVertices() {}
+
+ friend class SkVerticesPriv;
+
+ // these are needed since we've manually sized our allocation (see Builder::init)
+ friend class SkNVRefCnt<SkVertices>;
+ void operator delete(void* p);
+
+ Sizes getSizes() const;
+
+ // we store this first, to pair with the refcnt in our base-class, so we don't have an
+ // unnecessary pad between it and the (possibly 8-byte aligned) ptrs.
+ uint32_t fUniqueID;
+
+ // these point inside our allocation, so none of these can be "freed"
+ SkPoint* fPositions; // [vertexCount]
+ uint16_t* fIndices; // [indexCount] or null
+ SkPoint* fTexs; // [vertexCount] or null
+ SkColor* fColors; // [vertexCount] or null
+
+ SkRect fBounds; // computed to be the union of the fPositions[]
+ int fVertexCount;
+ int fIndexCount;
+
+ VertexMode fMode;
+ // below here is where the actual array data is stored.
+};
+
+#endif
diff --git a/src/deps/skia/include/core/SkYUVAInfo.h b/src/deps/skia/include/core/SkYUVAInfo.h
new file mode 100644
index 000000000..a3cf210f3
--- /dev/null
+++ b/src/deps/skia/include/core/SkYUVAInfo.h
@@ -0,0 +1,304 @@
+/*
+ * Copyright 2020 Google LLC
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkYUVAInfo_DEFINED
+#define SkYUVAInfo_DEFINED
+
+#include "include/codec/SkEncodedOrigin.h"
+#include "include/core/SkImageInfo.h"
+#include "include/core/SkSize.h"
+
+#include <array>
+#include <tuple>
+
+/**
+ * Specifies the structure of planes for a YUV image with optional alpha. The actual planar data
+ * is not part of this structure and depending on usage is in external textures or pixmaps.
+ */
+class SK_API SkYUVAInfo {
+public:
+ enum YUVAChannels { kY, kU, kV, kA, kLast = kA };
+ static constexpr int kYUVAChannelCount = static_cast<int>(YUVAChannels::kLast + 1);
+
+ struct YUVALocation; // For internal use.
+ using YUVALocations = std::array<YUVALocation, kYUVAChannelCount>;
+
+ /**
+ * Specifies how YUV (and optionally A) are divided among planes. Planes are separated by
+ * underscores in the enum value names. Within each plane the pixmap/texture channels are
+ * mapped to the YUVA channels in the order specified, e.g. for kY_UV Y is in channel 0 of plane
+ * 0, U is in channel 0 of plane 1, and V is in channel 1 of plane 1. Channel ordering
+ * within a pixmap/texture given the channels it contains:
+ * A: 0:A
+ * Luminance/Gray: 0:Gray
+ * Luminance/Gray + Alpha: 0:Gray, 1:A
+ * RG 0:R, 1:G
+ * RGB 0:R, 1:G, 2:B
+ * RGBA 0:R, 1:G, 2:B, 3:A
+ */
+ enum class PlaneConfig {
+ kUnknown,
+
+ kY_U_V, ///< Plane 0: Y, Plane 1: U, Plane 2: V
+ kY_V_U, ///< Plane 0: Y, Plane 1: V, Plane 2: U
+ kY_UV, ///< Plane 0: Y, Plane 1: UV
+ kY_VU, ///< Plane 0: Y, Plane 1: VU
+ kYUV, ///< Plane 0: YUV
+ kUYV, ///< Plane 0: UYV
+
+ kY_U_V_A, ///< Plane 0: Y, Plane 1: U, Plane 2: V, Plane 3: A
+ kY_V_U_A, ///< Plane 0: Y, Plane 1: V, Plane 2: U, Plane 3: A
+ kY_UV_A, ///< Plane 0: Y, Plane 1: UV, Plane 2: A
+ kY_VU_A, ///< Plane 0: Y, Plane 1: VU, Plane 2: A
+ kYUVA, ///< Plane 0: YUVA
+ kUYVA, ///< Plane 0: UYVA
+
+ kLast = kUYVA
+ };
+
+ /**
+ * UV subsampling is also specified in the enum value names using J:a:b notation (e.g. 4:2:0 is
+ * 1/2 horizontal and 1/2 vertical resolution for U and V). If alpha is present it is not sub-
+ * sampled. Note that Subsampling values other than k444 are only valid with PlaneConfig values
+ * that have U and V in different planes than Y (and A, if present).
+ */
+ enum class Subsampling {
+ kUnknown,
+
+ k444, ///< No subsampling. UV values for each Y.
+ k422, ///< 1 set of UV values for each 2x1 block of Y values.
+ k420, ///< 1 set of UV values for each 2x2 block of Y values.
+ k440, ///< 1 set of UV values for each 1x2 block of Y values.
+ k411, ///< 1 set of UV values for each 4x1 block of Y values.
+ k410, ///< 1 set of UV values for each 4x2 block of Y values.
+
+ kLast = k410
+ };
+
+ /**
+ * Describes how subsampled chroma values are sited relative to luma values.
+ *
+ * Currently only centered siting is supported but will expand to support additional sitings.
+ */
+ enum class Siting {
+ /**
+ * Subsampled chroma value is sited at the center of the block of corresponding luma values.
+ */
+ kCentered,
+ };
+
+ static constexpr int kMaxPlanes = 4;
+
+ /** ratio of Y/A values to U/V values in x and y. */
+ static std::tuple<int, int> SubsamplingFactors(Subsampling);
+
+ /**
+ * SubsamplingFactors(Subsampling) if planedIdx refers to a U/V plane and otherwise {1, 1} if
+ * inputs are valid. Invalid inputs consist of incompatible PlaneConfig/Subsampling/planeIdx
+ * combinations. {0, 0} is returned for invalid inputs.
+ */
+ static std::tuple<int, int> PlaneSubsamplingFactors(PlaneConfig, Subsampling, int planeIdx);
+
+ /**
+ * Given image dimensions, a planer configuration, subsampling, and origin, determine the
+ * expected size of each plane. Returns the number of expected planes. planeDimensions[0]
+ * through planeDimensions[<ret>] are written. The input image dimensions are as displayed
+ * (after the planes have been transformed to the intended display orientation). The plane
+ * dimensions are output as the planes are stored in memory (may be rotated from image
+ * dimensions).
+ */
+ static int PlaneDimensions(SkISize imageDimensions,
+ PlaneConfig,
+ Subsampling,
+ SkEncodedOrigin,
+ SkISize planeDimensions[kMaxPlanes]);
+
+ /** Number of planes for a given PlaneConfig. */
+ static constexpr int NumPlanes(PlaneConfig);
+
+ /**
+ * Number of Y, U, V, A channels in the ith plane for a given PlaneConfig (or 0 if i is
+ * invalid).
+ */
+ static constexpr int NumChannelsInPlane(PlaneConfig, int i);
+
+ /**
+ * Given a PlaneConfig and a set of channel flags for each plane, convert to YUVALocations
+ * representation. Fails if channel flags aren't valid for the PlaneConfig (i.e. don't have
+ * enough channels in a plane) by returning an invalid set of locations (plane indices are -1).
+ */
+ static YUVALocations GetYUVALocations(PlaneConfig, const uint32_t* planeChannelFlags);
+
+ /** Does the PlaneConfig have alpha values? */
+ static bool HasAlpha(PlaneConfig);
+
+ SkYUVAInfo() = default;
+ SkYUVAInfo(const SkYUVAInfo&) = default;
+
+ /**
+ * 'dimensions' should specify the size of the full resolution image (after planes have been
+ * oriented to how the image is displayed as indicated by 'origin').
+ */
+ SkYUVAInfo(SkISize dimensions,
+ PlaneConfig,
+ Subsampling,
+ SkYUVColorSpace,
+ SkEncodedOrigin origin = kTopLeft_SkEncodedOrigin,
+ Siting sitingX = Siting::kCentered,
+ Siting sitingY = Siting::kCentered);
+
+ SkYUVAInfo& operator=(const SkYUVAInfo& that) = default;
+
+ PlaneConfig planeConfig() const { return fPlaneConfig; }
+ Subsampling subsampling() const { return fSubsampling; }
+
+ std::tuple<int, int> planeSubsamplingFactors(int planeIdx) const {
+ return PlaneSubsamplingFactors(fPlaneConfig, fSubsampling, planeIdx);
+ }
+
+ /**
+ * Dimensions of the full resolution image (after planes have been oriented to how the image
+ * is displayed as indicated by fOrigin).
+ */
+ SkISize dimensions() const { return fDimensions; }
+ int width() const { return fDimensions.width(); }
+ int height() const { return fDimensions.height(); }
+
+ SkYUVColorSpace yuvColorSpace() const { return fYUVColorSpace; }
+ Siting sitingX() const { return fSitingX; }
+ Siting sitingY() const { return fSitingY; }
+
+ SkEncodedOrigin origin() const { return fOrigin; }
+
+ SkMatrix originMatrix() const {
+ return SkEncodedOriginToMatrix(fOrigin, this->width(), this->height());
+ }
+
+ bool hasAlpha() const { return HasAlpha(fPlaneConfig); }
+
+ /**
+ * Returns the number of planes and initializes planeDimensions[0]..planeDimensions[<ret>] to
+ * the expected dimensions for each plane. Dimensions are as stored in memory, before
+ * transformation to image display space as indicated by origin().
+ */
+ int planeDimensions(SkISize planeDimensions[kMaxPlanes]) const {
+ return PlaneDimensions(fDimensions, fPlaneConfig, fSubsampling, fOrigin, planeDimensions);
+ }
+
+ /**
+ * Given a per-plane row bytes, determine size to allocate for all planes. Optionally retrieves
+ * the per-plane byte sizes in planeSizes if not null. If total size overflows will return
+ * SIZE_MAX and set all planeSizes to SIZE_MAX.
+ */
+ size_t computeTotalBytes(const size_t rowBytes[kMaxPlanes],
+ size_t planeSizes[kMaxPlanes] = nullptr) const;
+
+ int numPlanes() const { return NumPlanes(fPlaneConfig); }
+
+ int numChannelsInPlane(int i) const { return NumChannelsInPlane(fPlaneConfig, i); }
+
+ /**
+ * Given a set of channel flags for each plane, converts this->planeConfig() to YUVALocations
+ * representation. Fails if the channel flags aren't valid for the PlaneConfig (i.e. don't have
+ * enough channels in a plane) by returning default initialized locations (all plane indices are
+ * -1).
+ */
+ YUVALocations toYUVALocations(const uint32_t* channelFlags) const;
+
+ /**
+ * Makes a SkYUVAInfo that is identical to this one but with the passed Subsampling. If the
+ * passed Subsampling is not k444 and this info's PlaneConfig is not compatible with chroma
+ * subsampling (because Y is in the same plane as UV) then the result will be an invalid
+ * SkYUVAInfo.
+ */
+ SkYUVAInfo makeSubsampling(SkYUVAInfo::Subsampling) const;
+
+ /**
+ * Makes a SkYUVAInfo that is identical to this one but with the passed dimensions. If the
+ * passed dimensions is empty then the result will be an invalid SkYUVAInfo.
+ */
+ SkYUVAInfo makeDimensions(SkISize) const;
+
+ bool operator==(const SkYUVAInfo& that) const;
+ bool operator!=(const SkYUVAInfo& that) const { return !(*this == that); }
+
+ bool isValid() const { return fPlaneConfig != PlaneConfig::kUnknown; }
+
+private:
+ SkISize fDimensions = {0, 0};
+
+ PlaneConfig fPlaneConfig = PlaneConfig::kUnknown;
+ Subsampling fSubsampling = Subsampling::kUnknown;
+
+ SkYUVColorSpace fYUVColorSpace = SkYUVColorSpace::kIdentity_SkYUVColorSpace;
+
+ /**
+ * YUVA data often comes from formats like JPEG that support EXIF orientation.
+ * Code that operates on the raw YUV data often needs to know that orientation.
+ */
+ SkEncodedOrigin fOrigin = kTopLeft_SkEncodedOrigin;
+
+ Siting fSitingX = Siting::kCentered;
+ Siting fSitingY = Siting::kCentered;
+};
+
+constexpr int SkYUVAInfo::NumPlanes(PlaneConfig planeConfig) {
+ switch (planeConfig) {
+ case PlaneConfig::kUnknown: return 0;
+ case PlaneConfig::kY_U_V: return 3;
+ case PlaneConfig::kY_V_U: return 3;
+ case PlaneConfig::kY_UV: return 2;
+ case PlaneConfig::kY_VU: return 2;
+ case PlaneConfig::kYUV: return 1;
+ case PlaneConfig::kUYV: return 1;
+ case PlaneConfig::kY_U_V_A: return 4;
+ case PlaneConfig::kY_V_U_A: return 4;
+ case PlaneConfig::kY_UV_A: return 3;
+ case PlaneConfig::kY_VU_A: return 3;
+ case PlaneConfig::kYUVA: return 1;
+ case PlaneConfig::kUYVA: return 1;
+ }
+ SkUNREACHABLE;
+}
+
+constexpr int SkYUVAInfo::NumChannelsInPlane(PlaneConfig config, int i) {
+ switch (config) {
+ case PlaneConfig::kUnknown:
+ return 0;
+
+ case SkYUVAInfo::PlaneConfig::kY_U_V:
+ case SkYUVAInfo::PlaneConfig::kY_V_U:
+ return i >= 0 && i < 3 ? 1 : 0;
+ case SkYUVAInfo::PlaneConfig::kY_UV:
+ case SkYUVAInfo::PlaneConfig::kY_VU:
+ switch (i) {
+ case 0: return 1;
+ case 1: return 2;
+ default: return 0;
+ }
+ case SkYUVAInfo::PlaneConfig::kYUV:
+ case SkYUVAInfo::PlaneConfig::kUYV:
+ return i == 0 ? 3 : 0;
+ case SkYUVAInfo::PlaneConfig::kY_U_V_A:
+ case SkYUVAInfo::PlaneConfig::kY_V_U_A:
+ return i >= 0 && i < 4 ? 1 : 0;
+ case SkYUVAInfo::PlaneConfig::kY_UV_A:
+ case SkYUVAInfo::PlaneConfig::kY_VU_A:
+ switch (i) {
+ case 0: return 1;
+ case 1: return 2;
+ case 2: return 1;
+ default: return 0;
+ }
+ case SkYUVAInfo::PlaneConfig::kYUVA:
+ case SkYUVAInfo::PlaneConfig::kUYVA:
+ return i == 0 ? 4 : 0;
+ }
+ return 0;
+}
+
+#endif
diff --git a/src/deps/skia/include/core/SkYUVAPixmaps.h b/src/deps/skia/include/core/SkYUVAPixmaps.h
new file mode 100644
index 000000000..de04ab14d
--- /dev/null
+++ b/src/deps/skia/include/core/SkYUVAPixmaps.h
@@ -0,0 +1,336 @@
+/*
+ * Copyright 2020 Google LLC
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkYUVAPixmaps_DEFINED
+#define SkYUVAPixmaps_DEFINED
+
+#include "include/core/SkData.h"
+#include "include/core/SkImageInfo.h"
+#include "include/core/SkPixmap.h"
+#include "include/core/SkYUVAInfo.h"
+#include "include/private/SkTo.h"
+
+#include <array>
+#include <bitset>
+
+class GrImageContext;
+
+/**
+ * SkYUVAInfo combined with per-plane SkColorTypes and row bytes. Fully specifies the SkPixmaps
+ * for a YUVA image without the actual pixel memory and data.
+ */
+class SK_API SkYUVAPixmapInfo {
+public:
+ static constexpr auto kMaxPlanes = SkYUVAInfo::kMaxPlanes;
+
+ using PlaneConfig = SkYUVAInfo::PlaneConfig;
+ using Subsampling = SkYUVAInfo::Subsampling;
+
+ /**
+ * Data type for Y, U, V, and possibly A channels independent of how values are packed into
+ * planes.
+ **/
+ enum class DataType {
+ kUnorm8, ///< 8 bit unsigned normalized
+ kUnorm16, ///< 16 bit unsigned normalized
+ kFloat16, ///< 16 bit (half) floating point
+ kUnorm10_Unorm2, ///< 10 bit unorm for Y, U, and V. 2 bit unorm for alpha (if present).
+
+ kLast = kUnorm10_Unorm2
+ };
+ static constexpr int kDataTypeCnt = static_cast<int>(DataType::kLast) + 1;
+
+ class SK_API SupportedDataTypes {
+ public:
+ /** Defaults to nothing supported. */
+ constexpr SupportedDataTypes() = default;
+
+ /** Init based on texture formats supported by the context. */
+ SupportedDataTypes(const GrImageContext&);
+
+ /** All legal combinations of PlaneConfig and DataType are supported. */
+ static constexpr SupportedDataTypes All();
+
+ /**
+ * Checks whether there is a supported combination of color types for planes structured
+ * as indicated by PlaneConfig with channel data types as indicated by DataType.
+ */
+ constexpr bool supported(PlaneConfig, DataType) const;
+
+ /**
+ * Update to add support for pixmaps with numChannel channels where each channel is
+ * represented as DataType.
+ */
+ void enableDataType(DataType, int numChannels);
+
+ private:
+ // The bit for DataType dt with n channels is at index kDataTypeCnt*(n-1) + dt.
+ std::bitset<kDataTypeCnt*4> fDataTypeSupport = {};
+ };
+
+ /**
+ * Gets the default SkColorType to use with numChannels channels, each represented as DataType.
+ * Returns kUnknown_SkColorType if no such color type.
+ */
+ static constexpr SkColorType DefaultColorTypeForDataType(DataType dataType, int numChannels);
+
+ /**
+ * If the SkColorType is supported for YUVA pixmaps this will return the number of YUVA channels
+ * that can be stored in a plane of this color type and what the DataType is of those channels.
+ * If the SkColorType is not supported as a YUVA plane the number of channels is reported as 0
+ * and the DataType returned should be ignored.
+ */
+ static std::tuple<int, DataType> NumChannelsAndDataType(SkColorType);
+
+ /** Default SkYUVAPixmapInfo is invalid. */
+ SkYUVAPixmapInfo() = default;
+
+ /**
+ * Initializes the SkYUVAPixmapInfo from a SkYUVAInfo with per-plane color types and row bytes.
+ * This will be invalid if the colorTypes aren't compatible with the SkYUVAInfo or if a
+ * rowBytes entry is not valid for the plane dimensions and color type. Color type and
+ * row byte values beyond the number of planes in SkYUVAInfo are ignored. All SkColorTypes
+ * must have the same DataType or this will be invalid.
+ *
+ * If rowBytes is nullptr then bpp*width is assumed for each plane.
+ */
+ SkYUVAPixmapInfo(const SkYUVAInfo&,
+ const SkColorType[kMaxPlanes],
+ const size_t rowBytes[kMaxPlanes]);
+ /**
+ * Like above but uses DefaultColorTypeForDataType to determine each plane's SkColorType. If
+ * rowBytes is nullptr then bpp*width is assumed for each plane.
+ */
+ SkYUVAPixmapInfo(const SkYUVAInfo&, DataType, const size_t rowBytes[kMaxPlanes]);
+
+ SkYUVAPixmapInfo(const SkYUVAPixmapInfo&) = default;
+
+ SkYUVAPixmapInfo& operator=(const SkYUVAPixmapInfo&) = default;
+
+ bool operator==(const SkYUVAPixmapInfo&) const;
+ bool operator!=(const SkYUVAPixmapInfo& that) const { return !(*this == that); }
+
+ const SkYUVAInfo& yuvaInfo() const { return fYUVAInfo; }
+
+ SkYUVColorSpace yuvColorSpace() const { return fYUVAInfo.yuvColorSpace(); }
+
+ /** The number of SkPixmap planes, 0 if this SkYUVAPixmapInfo is invalid. */
+ int numPlanes() const { return fYUVAInfo.numPlanes(); }
+
+ /** The per-YUV[A] channel data type. */
+ DataType dataType() const { return fDataType; }
+
+ /**
+ * Row bytes for the ith plane. Returns zero if i >= numPlanes() or this SkYUVAPixmapInfo is
+ * invalid.
+ */
+ size_t rowBytes(int i) const { return fRowBytes[static_cast<size_t>(i)]; }
+
+ /** Image info for the ith plane, or default SkImageInfo if i >= numPlanes() */
+ const SkImageInfo& planeInfo(int i) const { return fPlaneInfos[static_cast<size_t>(i)]; }
+
+ /**
+ * Determine size to allocate for all planes. Optionally retrieves the per-plane sizes in
+ * planeSizes if not null. If total size overflows will return SIZE_MAX and set all planeSizes
+ * to SIZE_MAX. Returns 0 and fills planesSizes with 0 if this SkYUVAPixmapInfo is not valid.
+ */
+ size_t computeTotalBytes(size_t planeSizes[kMaxPlanes] = nullptr) const;
+
+ /**
+ * Takes an allocation that is assumed to be at least computeTotalBytes() in size and configures
+ * the first numPlanes() entries in pixmaps array to point into that memory. The remaining
+ * entries of pixmaps are default initialized. Fails if this SkYUVAPixmapInfo not valid.
+ */
+ bool initPixmapsFromSingleAllocation(void* memory, SkPixmap pixmaps[kMaxPlanes]) const;
+
+ /**
+ * Returns true if this has been configured with a non-empty dimensioned SkYUVAInfo with
+ * compatible color types and row bytes.
+ */
+ bool isValid() const { return fYUVAInfo.isValid(); }
+
+ /** Is this valid and does it use color types allowed by the passed SupportedDataTypes? */
+ bool isSupported(const SupportedDataTypes&) const;
+
+private:
+ SkYUVAInfo fYUVAInfo;
+ std::array<SkImageInfo, kMaxPlanes> fPlaneInfos = {};
+ std::array<size_t, kMaxPlanes> fRowBytes = {};
+ DataType fDataType = DataType::kUnorm8;
+ static_assert(kUnknown_SkColorType == 0, "default init isn't kUnknown");
+};
+
+/**
+ * Helper to store SkPixmap planes as described by a SkYUVAPixmapInfo. Can be responsible for
+ * allocating/freeing memory for pixmaps or use external memory.
+ */
+class SK_API SkYUVAPixmaps {
+public:
+ using DataType = SkYUVAPixmapInfo::DataType;
+ static constexpr auto kMaxPlanes = SkYUVAPixmapInfo::kMaxPlanes;
+
+ static SkColorType RecommendedRGBAColorType(DataType);
+
+ /** Allocate space for pixmaps' pixels in the SkYUVAPixmaps. */
+ static SkYUVAPixmaps Allocate(const SkYUVAPixmapInfo& yuvaPixmapInfo);
+
+ /**
+ * Use storage in SkData as backing store for pixmaps' pixels. SkData is retained by the
+ * SkYUVAPixmaps.
+ */
+ static SkYUVAPixmaps FromData(const SkYUVAPixmapInfo&, sk_sp<SkData>);
+
+ /**
+ * Makes a deep copy of the src SkYUVAPixmaps. The returned SkYUVAPixmaps owns its planes'
+ * backing stores.
+ */
+ static SkYUVAPixmaps MakeCopy(const SkYUVAPixmaps& src);
+
+ /**
+ * Use passed in memory as backing store for pixmaps' pixels. Caller must ensure memory remains
+ * allocated while pixmaps are in use. There must be at least
+ * SkYUVAPixmapInfo::computeTotalBytes() allocated starting at memory.
+ */
+ static SkYUVAPixmaps FromExternalMemory(const SkYUVAPixmapInfo&, void* memory);
+
+ /**
+ * Wraps existing SkPixmaps. The SkYUVAPixmaps will have no ownership of the SkPixmaps' pixel
+ * memory so the caller must ensure it remains valid. Will return an invalid SkYUVAPixmaps if
+ * the SkYUVAInfo isn't compatible with the SkPixmap array (number of planes, plane dimensions,
+ * sufficient color channels in planes, ...).
+ */
+ static SkYUVAPixmaps FromExternalPixmaps(const SkYUVAInfo&, const SkPixmap[kMaxPlanes]);
+
+ /** Default SkYUVAPixmaps is invalid. */
+ SkYUVAPixmaps() = default;
+ ~SkYUVAPixmaps() = default;
+
+ SkYUVAPixmaps(SkYUVAPixmaps&& that) = default;
+ SkYUVAPixmaps& operator=(SkYUVAPixmaps&& that) = default;
+ SkYUVAPixmaps(const SkYUVAPixmaps&) = default;
+ SkYUVAPixmaps& operator=(const SkYUVAPixmaps& that) = default;
+
+ /** Does have initialized pixmaps compatible with its SkYUVAInfo. */
+ bool isValid() const { return !fYUVAInfo.dimensions().isEmpty(); }
+
+ const SkYUVAInfo& yuvaInfo() const { return fYUVAInfo; }
+
+ DataType dataType() const { return fDataType; }
+
+ SkYUVAPixmapInfo pixmapsInfo() const;
+
+ /** Number of pixmap planes or 0 if this SkYUVAPixmaps is invalid. */
+ int numPlanes() const { return this->isValid() ? fYUVAInfo.numPlanes() : 0; }
+
+ /**
+ * Access the SkPixmap planes. They are default initialized if this is not a valid
+ * SkYUVAPixmaps.
+ */
+ const std::array<SkPixmap, kMaxPlanes>& planes() const { return fPlanes; }
+
+ /**
+ * Get the ith SkPixmap plane. SkPixmap will be default initialized if i >= numPlanes or this
+ * SkYUVAPixmaps is invalid.
+ */
+ const SkPixmap& plane(int i) const { return fPlanes[SkToSizeT(i)]; }
+
+ /**
+ * Computes a YUVALocations representation of the planar layout. The result is guaranteed to be
+ * valid if this->isValid().
+ */
+ SkYUVAInfo::YUVALocations toYUVALocations() const;
+
+ /** Does this SkPixmaps own the backing store of the planes? */
+ bool ownsStorage() const { return SkToBool(fData); }
+
+private:
+ SkYUVAPixmaps(const SkYUVAPixmapInfo&, sk_sp<SkData>);
+ SkYUVAPixmaps(const SkYUVAInfo&, DataType, const SkPixmap[kMaxPlanes]);
+
+ std::array<SkPixmap, kMaxPlanes> fPlanes = {};
+ sk_sp<SkData> fData;
+ SkYUVAInfo fYUVAInfo;
+ DataType fDataType;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+constexpr SkYUVAPixmapInfo::SupportedDataTypes SkYUVAPixmapInfo::SupportedDataTypes::All() {
+ using ULL = unsigned long long; // bitset cons. takes this.
+ ULL bits = 0;
+ for (ULL c = 1; c <= 4; ++c) {
+ for (ULL dt = 0; dt <= ULL(kDataTypeCnt); ++dt) {
+ if (DefaultColorTypeForDataType(static_cast<DataType>(dt),
+ static_cast<int>(c)) != kUnknown_SkColorType) {
+ bits |= ULL(1) << (dt + static_cast<ULL>(kDataTypeCnt)*(c - 1));
+ }
+ }
+ }
+ SupportedDataTypes combinations;
+ combinations.fDataTypeSupport = bits;
+ return combinations;
+}
+
+constexpr bool SkYUVAPixmapInfo::SupportedDataTypes::supported(PlaneConfig config,
+ DataType type) const {
+ int n = SkYUVAInfo::NumPlanes(config);
+ for (int i = 0; i < n; ++i) {
+ auto c = static_cast<size_t>(SkYUVAInfo::NumChannelsInPlane(config, i));
+ SkASSERT(c >= 1 && c <= 4);
+ if (!fDataTypeSupport[static_cast<size_t>(type) +
+ (c - 1)*static_cast<size_t>(kDataTypeCnt)]) {
+ return false;
+ }
+ }
+ return true;
+}
+
+constexpr SkColorType SkYUVAPixmapInfo::DefaultColorTypeForDataType(DataType dataType,
+ int numChannels) {
+ switch (numChannels) {
+ case 1:
+ switch (dataType) {
+ case DataType::kUnorm8: return kGray_8_SkColorType;
+ case DataType::kUnorm16: return kA16_unorm_SkColorType;
+ case DataType::kFloat16: return kA16_float_SkColorType;
+ case DataType::kUnorm10_Unorm2: return kUnknown_SkColorType;
+ }
+ break;
+ case 2:
+ switch (dataType) {
+ case DataType::kUnorm8: return kR8G8_unorm_SkColorType;
+ case DataType::kUnorm16: return kR16G16_unorm_SkColorType;
+ case DataType::kFloat16: return kR16G16_float_SkColorType;
+ case DataType::kUnorm10_Unorm2: return kUnknown_SkColorType;
+ }
+ break;
+ case 3:
+ // None of these are tightly packed. The intended use case is for interleaved YUVA
+ // planes where we're forcing opaqueness by ignoring the alpha values.
+ // There are "x" rather than "A" variants for Unorm8 and Unorm10_Unorm2 but we don't
+ // choose them because 1) there is no inherent advantage and 2) there is better support
+ // in the GPU backend for the "A" versions.
+ switch (dataType) {
+ case DataType::kUnorm8: return kRGBA_8888_SkColorType;
+ case DataType::kUnorm16: return kR16G16B16A16_unorm_SkColorType;
+ case DataType::kFloat16: return kRGBA_F16_SkColorType;
+ case DataType::kUnorm10_Unorm2: return kRGBA_1010102_SkColorType;
+ }
+ break;
+ case 4:
+ switch (dataType) {
+ case DataType::kUnorm8: return kRGBA_8888_SkColorType;
+ case DataType::kUnorm16: return kR16G16B16A16_unorm_SkColorType;
+ case DataType::kFloat16: return kRGBA_F16_SkColorType;
+ case DataType::kUnorm10_Unorm2: return kRGBA_1010102_SkColorType;
+ }
+ break;
+ }
+ return kUnknown_SkColorType;
+}
+
+#endif