xref: /aosp_15_r20/external/skia/modules/canvaskit/htmlcanvas/htmlcanvas.js (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1*c8dee2aaSAndroid Build Coastguard WorkerCanvasKit.MakeCanvas = function(width, height) {
2*c8dee2aaSAndroid Build Coastguard Worker  var surf = CanvasKit.MakeSurface(width, height);
3*c8dee2aaSAndroid Build Coastguard Worker  if (surf) {
4*c8dee2aaSAndroid Build Coastguard Worker    return new HTMLCanvas(surf);
5*c8dee2aaSAndroid Build Coastguard Worker  }
6*c8dee2aaSAndroid Build Coastguard Worker  return null;
7*c8dee2aaSAndroid Build Coastguard Worker};
8*c8dee2aaSAndroid Build Coastguard Worker
9*c8dee2aaSAndroid Build Coastguard Workerfunction HTMLCanvas(skSurface) {
10*c8dee2aaSAndroid Build Coastguard Worker  this._surface = skSurface;
11*c8dee2aaSAndroid Build Coastguard Worker  this._context = new CanvasRenderingContext2D(skSurface.getCanvas());
12*c8dee2aaSAndroid Build Coastguard Worker  this._toCleanup = [];
13*c8dee2aaSAndroid Build Coastguard Worker
14*c8dee2aaSAndroid Build Coastguard Worker  // Data is either an ArrayBuffer, a TypedArray, or a Node Buffer
15*c8dee2aaSAndroid Build Coastguard Worker  this.decodeImage = function(data) {
16*c8dee2aaSAndroid Build Coastguard Worker    var img = CanvasKit.MakeImageFromEncoded(data);
17*c8dee2aaSAndroid Build Coastguard Worker    if (!img) {
18*c8dee2aaSAndroid Build Coastguard Worker      throw 'Invalid input';
19*c8dee2aaSAndroid Build Coastguard Worker    }
20*c8dee2aaSAndroid Build Coastguard Worker    this._toCleanup.push(img);
21*c8dee2aaSAndroid Build Coastguard Worker    return new HTMLImage(img);
22*c8dee2aaSAndroid Build Coastguard Worker  };
23*c8dee2aaSAndroid Build Coastguard Worker
24*c8dee2aaSAndroid Build Coastguard Worker  this.loadFont = function(buffer, descriptors) {
25*c8dee2aaSAndroid Build Coastguard Worker    var newFont = CanvasKit.Typeface.MakeTypefaceFromData(buffer);
26*c8dee2aaSAndroid Build Coastguard Worker    if (!newFont) {
27*c8dee2aaSAndroid Build Coastguard Worker      Debug('font could not be processed', descriptors);
28*c8dee2aaSAndroid Build Coastguard Worker      return null;
29*c8dee2aaSAndroid Build Coastguard Worker    }
30*c8dee2aaSAndroid Build Coastguard Worker    this._toCleanup.push(newFont);
31*c8dee2aaSAndroid Build Coastguard Worker    addToFontCache(newFont, descriptors);
32*c8dee2aaSAndroid Build Coastguard Worker  };
33*c8dee2aaSAndroid Build Coastguard Worker
34*c8dee2aaSAndroid Build Coastguard Worker  this.makePath2D = function(path) {
35*c8dee2aaSAndroid Build Coastguard Worker    var p2d = new Path2D(path);
36*c8dee2aaSAndroid Build Coastguard Worker    this._toCleanup.push(p2d._getPath());
37*c8dee2aaSAndroid Build Coastguard Worker    return p2d;
38*c8dee2aaSAndroid Build Coastguard Worker  };
39*c8dee2aaSAndroid Build Coastguard Worker
40*c8dee2aaSAndroid Build Coastguard Worker  // A normal <canvas> requires that clients call getContext
41*c8dee2aaSAndroid Build Coastguard Worker  this.getContext = function(type) {
42*c8dee2aaSAndroid Build Coastguard Worker    if (type === '2d') {
43*c8dee2aaSAndroid Build Coastguard Worker      return this._context;
44*c8dee2aaSAndroid Build Coastguard Worker    }
45*c8dee2aaSAndroid Build Coastguard Worker    return null;
46*c8dee2aaSAndroid Build Coastguard Worker  };
47*c8dee2aaSAndroid Build Coastguard Worker
48*c8dee2aaSAndroid Build Coastguard Worker  this.toDataURL = function(codec, quality) {
49*c8dee2aaSAndroid Build Coastguard Worker    // TODO(kjlubick): maybe support other codecs (webp?)
50*c8dee2aaSAndroid Build Coastguard Worker    // For now, just to png and jpeg
51*c8dee2aaSAndroid Build Coastguard Worker    this._surface.flush();
52*c8dee2aaSAndroid Build Coastguard Worker
53*c8dee2aaSAndroid Build Coastguard Worker    var img = this._surface.makeImageSnapshot();
54*c8dee2aaSAndroid Build Coastguard Worker    if (!img) {
55*c8dee2aaSAndroid Build Coastguard Worker      Debug('no snapshot');
56*c8dee2aaSAndroid Build Coastguard Worker      return;
57*c8dee2aaSAndroid Build Coastguard Worker    }
58*c8dee2aaSAndroid Build Coastguard Worker    codec = codec || 'image/png';
59*c8dee2aaSAndroid Build Coastguard Worker    var format = CanvasKit.ImageFormat.PNG;
60*c8dee2aaSAndroid Build Coastguard Worker    if (codec === 'image/jpeg') {
61*c8dee2aaSAndroid Build Coastguard Worker      format = CanvasKit.ImageFormat.JPEG;
62*c8dee2aaSAndroid Build Coastguard Worker    }
63*c8dee2aaSAndroid Build Coastguard Worker    quality = quality || 0.92;
64*c8dee2aaSAndroid Build Coastguard Worker    var imgBytes = img.encodeToBytes(format, quality);
65*c8dee2aaSAndroid Build Coastguard Worker    if (!imgBytes) {
66*c8dee2aaSAndroid Build Coastguard Worker      Debug('encoding failure');
67*c8dee2aaSAndroid Build Coastguard Worker      return
68*c8dee2aaSAndroid Build Coastguard Worker    }
69*c8dee2aaSAndroid Build Coastguard Worker    img.delete();
70*c8dee2aaSAndroid Build Coastguard Worker    return 'data:' + codec + ';base64,' + toBase64String(imgBytes);
71*c8dee2aaSAndroid Build Coastguard Worker  };
72*c8dee2aaSAndroid Build Coastguard Worker
73*c8dee2aaSAndroid Build Coastguard Worker  this.dispose = function() {
74*c8dee2aaSAndroid Build Coastguard Worker    this._context._dispose();
75*c8dee2aaSAndroid Build Coastguard Worker    this._toCleanup.forEach(function(i) {
76*c8dee2aaSAndroid Build Coastguard Worker      i.delete();
77*c8dee2aaSAndroid Build Coastguard Worker    });
78*c8dee2aaSAndroid Build Coastguard Worker    this._surface.dispose();
79*c8dee2aaSAndroid Build Coastguard Worker  }
80*c8dee2aaSAndroid Build Coastguard Worker}
81