xref: /aosp_15_r20/external/skia/modules/canvaskit/htmlcanvas/pattern.js (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1*c8dee2aaSAndroid Build Coastguard Workerfunction CanvasPattern(image, repetition) {
2*c8dee2aaSAndroid Build Coastguard Worker  this._shader = null;
3*c8dee2aaSAndroid Build Coastguard Worker  // image should be an Image returned from HTMLCanvas.decodeImage()
4*c8dee2aaSAndroid Build Coastguard Worker  if (image instanceof HTMLImage) {
5*c8dee2aaSAndroid Build Coastguard Worker    image = image.getSkImage();
6*c8dee2aaSAndroid Build Coastguard Worker  }
7*c8dee2aaSAndroid Build Coastguard Worker  this._image = image;
8*c8dee2aaSAndroid Build Coastguard Worker  this._transform = CanvasKit.Matrix.identity();
9*c8dee2aaSAndroid Build Coastguard Worker
10*c8dee2aaSAndroid Build Coastguard Worker  if (repetition === '') {
11*c8dee2aaSAndroid Build Coastguard Worker    repetition = 'repeat';
12*c8dee2aaSAndroid Build Coastguard Worker  }
13*c8dee2aaSAndroid Build Coastguard Worker  switch(repetition) {
14*c8dee2aaSAndroid Build Coastguard Worker    case 'repeat-x':
15*c8dee2aaSAndroid Build Coastguard Worker      this._tileX = CanvasKit.TileMode.Repeat;
16*c8dee2aaSAndroid Build Coastguard Worker      // Skia's 'clamp' mode repeats the last row/column
17*c8dee2aaSAndroid Build Coastguard Worker      // which looks very very strange.
18*c8dee2aaSAndroid Build Coastguard Worker      // Decal mode does just transparent copying, which
19*c8dee2aaSAndroid Build Coastguard Worker      // is exactly what the spec wants.
20*c8dee2aaSAndroid Build Coastguard Worker      this._tileY = CanvasKit.TileMode.Decal;
21*c8dee2aaSAndroid Build Coastguard Worker      break;
22*c8dee2aaSAndroid Build Coastguard Worker    case 'repeat-y':
23*c8dee2aaSAndroid Build Coastguard Worker      this._tileX = CanvasKit.TileMode.Decal;
24*c8dee2aaSAndroid Build Coastguard Worker      this._tileY = CanvasKit.TileMode.Repeat;
25*c8dee2aaSAndroid Build Coastguard Worker      break;
26*c8dee2aaSAndroid Build Coastguard Worker    case 'repeat':
27*c8dee2aaSAndroid Build Coastguard Worker      this._tileX = CanvasKit.TileMode.Repeat;
28*c8dee2aaSAndroid Build Coastguard Worker      this._tileY = CanvasKit.TileMode.Repeat;
29*c8dee2aaSAndroid Build Coastguard Worker      break;
30*c8dee2aaSAndroid Build Coastguard Worker    case 'no-repeat':
31*c8dee2aaSAndroid Build Coastguard Worker      this._tileX = CanvasKit.TileMode.Decal;
32*c8dee2aaSAndroid Build Coastguard Worker      this._tileY = CanvasKit.TileMode.Decal;
33*c8dee2aaSAndroid Build Coastguard Worker      break;
34*c8dee2aaSAndroid Build Coastguard Worker    default:
35*c8dee2aaSAndroid Build Coastguard Worker      throw 'invalid repetition mode ' + repetition;
36*c8dee2aaSAndroid Build Coastguard Worker  }
37*c8dee2aaSAndroid Build Coastguard Worker
38*c8dee2aaSAndroid Build Coastguard Worker  // Takes a DOMMatrix like object. e.g. the identity would be:
39*c8dee2aaSAndroid Build Coastguard Worker  // {a:1, b: 0, c: 0, d: 1, e: 0, f: 0}
40*c8dee2aaSAndroid Build Coastguard Worker  // @param {DOMMatrix} m
41*c8dee2aaSAndroid Build Coastguard Worker  this.setTransform = function(m) {
42*c8dee2aaSAndroid Build Coastguard Worker    var t = [m.a, m.c, m.e,
43*c8dee2aaSAndroid Build Coastguard Worker             m.b, m.d, m.f,
44*c8dee2aaSAndroid Build Coastguard Worker               0,   0,   1];
45*c8dee2aaSAndroid Build Coastguard Worker    if (allAreFinite(t)) {
46*c8dee2aaSAndroid Build Coastguard Worker      this._transform = t;
47*c8dee2aaSAndroid Build Coastguard Worker    }
48*c8dee2aaSAndroid Build Coastguard Worker  };
49*c8dee2aaSAndroid Build Coastguard Worker
50*c8dee2aaSAndroid Build Coastguard Worker  this._copy = function() {
51*c8dee2aaSAndroid Build Coastguard Worker    var cp = new CanvasPattern();
52*c8dee2aaSAndroid Build Coastguard Worker    cp._tileX = this._tileX;
53*c8dee2aaSAndroid Build Coastguard Worker    cp._tileY = this._tileY;
54*c8dee2aaSAndroid Build Coastguard Worker    return cp;
55*c8dee2aaSAndroid Build Coastguard Worker  };
56*c8dee2aaSAndroid Build Coastguard Worker
57*c8dee2aaSAndroid Build Coastguard Worker  this._dispose = function() {
58*c8dee2aaSAndroid Build Coastguard Worker    if (this._shader) {
59*c8dee2aaSAndroid Build Coastguard Worker      this._shader.delete();
60*c8dee2aaSAndroid Build Coastguard Worker      this._shader = null;
61*c8dee2aaSAndroid Build Coastguard Worker    }
62*c8dee2aaSAndroid Build Coastguard Worker  };
63*c8dee2aaSAndroid Build Coastguard Worker
64*c8dee2aaSAndroid Build Coastguard Worker  this._getShader = function(currentTransform) {
65*c8dee2aaSAndroid Build Coastguard Worker    // Ignore currentTransform since it will be applied later
66*c8dee2aaSAndroid Build Coastguard Worker    this._dispose();
67*c8dee2aaSAndroid Build Coastguard Worker    // A shader with cubic sampling options is high quality.
68*c8dee2aaSAndroid Build Coastguard Worker    this._shader = this._image.makeShaderCubic(this._tileX, this._tileY, 1/3, 1/3, this._transform);
69*c8dee2aaSAndroid Build Coastguard Worker    return this._shader;
70*c8dee2aaSAndroid Build Coastguard Worker  }
71*c8dee2aaSAndroid Build Coastguard Worker
72*c8dee2aaSAndroid Build Coastguard Worker}
73