Import Cobalt 25.master.0.1033734
diff --git a/third_party/skia/demos.skia.org/demos/image_sampling/index.html b/third_party/skia/demos.skia.org/demos/image_sampling/index.html
new file mode 100644
index 0000000..6626630
--- /dev/null
+++ b/third_party/skia/demos.skia.org/demos/image_sampling/index.html
@@ -0,0 +1,143 @@
+<!DOCTYPE html>
+<title>Custom Image Upscaling</title>
+<meta charset="utf-8" />
+<meta http-equiv="X-UA-Compatible" content="IE=edge">
+<meta name="viewport" content="width=device-width, initial-scale=1.0">
+<script type="text/javascript" src="https://unpkg.com/canvaskit-wasm@0.25.0/bin/full/canvaskit.js"></script>
+
+<style>
+ figcaption {
+ max-width: 800px;
+ }
+</style>
+
+<body>
+ <h1>Custom Image Upscaling</h1>
+
+ <div class="slidecontainer">
+ <input type="range" min="0" max="1" value="0" step="0.01" class="slider" id="sharpen"
+ title="sharpen coefficient: 0 means nearest neighbor.">
+ <input type="range" min="0" max="1" value="0.3" step="0.01" class="slider" id="cubic_B"
+ title="cubic B">
+ <input type="range" min="0" max="1" value="0.3" step="0.01" class="slider" id="cubic_C"
+ title="cubic C">
+ </div>
+
+ <figure>
+ <canvas id=draw width=820 height=820></canvas>
+ <figcaption>
+ This demo shows off a custom image upscaling algorithm written in SkSL. The algorithm
+ can be between nearest neighbor and linear interpolation, depending if the value of the
+ sharpen (i.e. the first) slider is 0 or 1, respectively. The upper left quadrant shows
+ the results of a 100x zoom in on a 4 pixel by 4 pixel image of random colors with this
+ algorithm. The lower left is the same algorithm with a smoothing curve applied.
+ <br>
+ For comparison, the upper right shows a stock linear interpolation and the lower right
+ shows a cubic interpolation with the B and C values controlled by the two remaining
+ sliders.
+ </figcaption>
+ </figure>
+
+</body>
+
+<script type="text/javascript" charset="utf-8">
+ const ckLoaded = CanvasKitInit({ locateFile: (file) => 'https://unpkg.com/canvaskit-wasm@0.25.0/bin/full/' + file });
+
+ ckLoaded.then((CanvasKit) => {
+ if (!CanvasKit.RuntimeEffect) {
+ throw 'Need RuntimeEffect';
+ }
+ const surface = CanvasKit.MakeCanvasSurface('draw');
+ if (!surface) {
+ throw 'Could not make surface';
+ }
+
+ const prog = `
+ uniform shader image;
+ uniform float sharp; // 1/m 0 --> NN, 1 --> Linear
+ uniform float do_smooth; // bool
+
+ float2 smooth(float2 t) {
+ return t * t * (3.0 - 2.0 * t);
+ }
+
+ float2 sharpen(float2 w) {
+ return saturate(sharp * (w - 0.5) + 0.5);
+ }
+
+ half4 main(float2 p) {
+ half4 pa = image.eval(float2(p.x-0.5, p.y-0.5));
+ half4 pb = image.eval(float2(p.x+0.5, p.y-0.5));
+ half4 pc = image.eval(float2(p.x-0.5, p.y+0.5));
+ half4 pd = image.eval(float2(p.x+0.5, p.y+0.5));
+ float2 w = sharpen(fract(p + 0.5));
+ if (do_smooth > 0) {
+ w = smooth(w);
+ }
+ return mix(mix(pa, pb, w.x), mix(pc, pd, w.x), w.y);
+ }
+ `;
+ const effect = CanvasKit.RuntimeEffect.Make(prog);
+
+ const paint = new CanvasKit.Paint();
+ // image is a 4x4 image of 16 random colors. This very small image will be upscaled
+ // through various techniques.
+ const image = function() {
+ const surf = CanvasKit.MakeSurface(4, 4);
+ const c = surf.getCanvas();
+ for (let y = 0; y < 4; y++) {
+ for (let x = 0; x < 4; x++) {
+ paint.setColor([Math.random(), Math.random(), Math.random(), 1]);
+ c.drawRect(CanvasKit.LTRBRect(x, y, x+1, y+1), paint);
+ }
+ }
+ return surf.makeImageSnapshot();
+ }();
+
+ const imageShader = image.makeShaderOptions(CanvasKit.TileMode.Clamp,
+ CanvasKit.TileMode.Clamp,
+ CanvasKit.FilterMode.Nearest,
+ CanvasKit.MipmapMode.None);
+
+ sharpen.oninput = () => { surface.requestAnimationFrame(drawFrame); };
+ cubic_B.oninput = () => { surface.requestAnimationFrame(drawFrame); };
+ cubic_C.oninput = () => { surface.requestAnimationFrame(drawFrame); };
+
+ const drawFrame = function(canvas) {
+ const v = sharpen.valueAsNumber;
+ const m = 1/Math.max(v, 0.00001);
+ const B = cubic_B.valueAsNumber;
+ const C = cubic_C.valueAsNumber;
+
+ canvas.save();
+ // Upscale all drawing by 100x; This is big enough to make the differences in technique
+ // more obvious.
+ const scale = 100;
+ canvas.scale(scale, scale);
+
+ // Upper left, draw image using an algorithm (written in SkSL) between nearest neighbor and
+ // linear interpolation with no smoothing.
+ paint.setShader(effect.makeShaderWithChildren([m, 0], [imageShader], null));
+ canvas.drawRect(CanvasKit.LTRBRect(0, 0, 4, 4), paint);
+
+ // Lower left, draw image using an algorithm (written in SkSL) between nearest neighbor and
+ // linear interpolation with smoothing enabled.
+ canvas.save();
+ canvas.translate(0, 4.1);
+ paint.setShader(effect.makeShaderWithChildren([m, 1], [imageShader], null));
+ canvas.drawRect(CanvasKit.LTRBRect(0, 0, 4, 4), paint);
+ canvas.restore();
+
+ // Upper right, draw image with built-in linear interpolation.
+ canvas.drawImageOptions(image, 4.1, 0, CanvasKit.FilterMode.Linear, CanvasKit.MipmapMode.None, null);
+
+ // Lower right, draw image with configurable cubic interpolation.
+ canvas.drawImageCubic(image, 4.1, 4.1, B, C, null);
+
+ canvas.restore();
+ };
+
+ surface.requestAnimationFrame(drawFrame);
+ });
+
+</script>