From 2fde30f4295fd34201e8edc10c517e509e32ace9 Mon Sep 17 00:00:00 2001 From: MoyuScript Date: Thu, 3 Aug 2017 20:57:55 +0800 Subject: [PATCH] Implement HTMLCanvasElement rendering --- src/CanvasRenderer.js | 4 ++-- src/ImageLoader.js | 18 +++++++++++++----- src/NodeContainer.js | 17 ++++++++++++++--- src/parsing/background.js | 4 ++-- 4 files changed, 31 insertions(+), 12 deletions(-) diff --git a/src/CanvasRenderer.js b/src/CanvasRenderer.js index 3f61318..1b6d890 100644 --- a/src/CanvasRenderer.js +++ b/src/CanvasRenderer.js @@ -12,7 +12,7 @@ import BezierCurve from './BezierCurve'; import type NodeContainer from './NodeContainer'; import type TextContainer from './TextContainer'; -import type {ImageStore} from './ImageLoader'; +import type {ImageStore, ImageElement} from './ImageLoader'; import type StackingContext from './StackingContext'; import { @@ -192,7 +192,7 @@ export default class CanvasRenderer { } } - resizeImage(image: HTMLImageElement, size: Size) { + resizeImage(image: ImageElement, size: Size) { if (image.width === size.width && image.height === size.height) { return image; } diff --git a/src/ImageLoader.js b/src/ImageLoader.js index 2d844e2..e4c4e9c 100644 --- a/src/ImageLoader.js +++ b/src/ImageLoader.js @@ -1,11 +1,11 @@ /* @flow */ 'use strict'; -import type NodeContainer from './NodeContainer'; import type Options from './index'; import type Logger from './Logger'; -type ImageCache = {[string]: Promise}; +export type ImageElement = Image | HTMLCanvasElement; +type ImageCache = {[string]: Promise}; export default class ImageLoader { origin: string; @@ -13,12 +13,14 @@ export default class ImageLoader { _link: HTMLAnchorElement; cache: ImageCache; logger: Logger; + _index: number; constructor(options: Options, logger: Logger) { this.options = options; this.origin = this.getOrigin(window.location.href); this.cache = {}; this.logger = logger; + this._index = 0; } loadImage(src: string): ?string { @@ -33,6 +35,12 @@ export default class ImageLoader { } } + loadCanvas(node: HTMLCanvasElement): string { + const key = String(this._index++); + this.cache[key] = Promise.resolve(node); + return key; + } + isInlineImage(src: string): boolean { return /data:image\/.*;base64,/i.test(src); } @@ -86,14 +94,14 @@ export default class ImageLoader { export class ImageStore { _keys: Array; - _images: Array; + _images: Array; - constructor(keys: Array, images: Array) { + constructor(keys: Array, images: Array) { this._keys = keys; this._images = images; } - get(key: string): ?HTMLImageElement { + get(key: string): ?ImageElement { const index = this._keys.indexOf(key); return index === -1 ? null : this._images[index]; } diff --git a/src/NodeContainer.js b/src/NodeContainer.js index 62984d6..a38edfd 100644 --- a/src/NodeContainer.js +++ b/src/NodeContainer.js @@ -102,9 +102,7 @@ export default class NodeContainer { node.style.transform = 'matrix(1,0,0,1,0,0)'; } - this.image = - // $FlowFixMe - node.tagName === 'IMG' ? imageLoader.loadImage(node.currentSrc || node.src) : null; + this.image = getImage(node, imageLoader); this.bounds = parseBounds(node); this.curvedBounds = parseBoundCurves( this.bounds, @@ -172,3 +170,16 @@ export default class NodeContainer { ); } } + +const getImage = (node: HTMLElement, imageLoader: ImageLoader): ?string => { + switch (node.tagName) { + case 'IMG': + // $FlowFixMe + return imageLoader.loadImage(node.currentSrc || node.src); + case 'CANVAS': + // $FlowFixMe + return imageLoader.loadCanvas(node); + } + + return null; +}; diff --git a/src/parsing/background.js b/src/parsing/background.js index 64b964f..4a70a03 100644 --- a/src/parsing/background.js +++ b/src/parsing/background.js @@ -2,7 +2,7 @@ 'use strict'; import type {Bounds, BoundCurves, Path} from '../Bounds'; -import type ImageLoader from '../ImageLoader'; +import type ImageLoader, {ImageElement} from '../ImageLoader'; import Color from '../Color'; import Length from '../Length'; @@ -82,7 +82,7 @@ class BackgroundSize { export const calculateBackgroundSize = ( backgroundImage: BackgroundImage, - image: HTMLImageElement, + image: ImageElement, bounds: Bounds ): Size => { let width = 0;