diff --git a/.gitignore b/.gitignore index 60d2e8d..64bf263 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ +.DS_Store dist/ node_modules/ -example/ -.vscode/ +.vscode .history/ -.expo/ \ No newline at end of file +.expo/ +.idea \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index cc35c4d..0000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "prettier.singleQuote": true, - "prettier.trailingComma": "always", - "javascript.validate.enable": false, - "prettier.eslintIntegration": true, - "[javascriptreact]": { - "editor.formatOnSave": true - } -} diff --git a/example/App.js b/example/App.js index 282ac04..6d06000 100644 --- a/example/App.js +++ b/example/App.js @@ -129,6 +129,31 @@ export default class App extends Component { context.drawImage(image, 0, 0, 100, 100); }); } +/** + * For example used google font + */ + handleCustomFont(canvas) { + const image = new CanvasImage(canvas); + const ctx = canvas.getContext('2d'); + + canvas.width = 100; + canvas.height = 100; + + ctx.save(); + ctx.strokeStyle = 'black'; + ctx.strokeRect(0, 0, canvas.width, canvas.height); + ctx.restore(); + + canvas + .addFont({ + name: 'Miss Fajardose', + link: 'https://fonts.gstatic.com/l/font?kit=_Xmz-GY4rjmCbQfc-aPRaa4pqV340p7EZl5bwkcU4V55dc7XaVkOCo1Q-D-x1hYOZdAwD85gO8PnV3aw17Bcb_EJ-4NA_8H607rOs33MkhY8f7wbUWAdDQ2n1QB3eW3jcHe0AN51VVnuPiTMOVWKPaSDGFmHIHXVFubF6rRfNxY45LnE1RQ5DyQMd9Ji48bXLyygkZ3MoMVyaLdVNg8nVZJ-nR_Yf3UVbtEIyw&skey=f0bf0703ab573473&v=v7', + }) + .then((res) => { + ctx.font = 'bold 20px Miss Fajardose'; + ctx.fillText('Hello Font', 5, 52); + }); + } render() { return ( @@ -156,6 +181,9 @@ export default class App extends Component { + + + ); diff --git a/example/images/custom-font.png b/example/images/custom-font.png new file mode 100644 index 0000000..553a024 Binary files /dev/null and b/example/images/custom-font.png differ diff --git a/readme.md b/readme.md index 95bdc5f..2506d8f 100644 --- a/readme.md +++ b/readme.md @@ -53,6 +53,46 @@ Returns a canvas rendering context. Currently only supports 2d context. Returns a `Promise` that resolves to DataURL. +### Canvas#addFont(font) + +`font` is an object that described bellow +```JS +const font = { + name: 'Miss Fajardose', // required + link: 'https://fonts.gstatic.com/s/missfajardose/v8/E21-_dn5gvrawDdPFVl-N0Ajb_qoUverqJnp.woff2', // required + options: { // optional + style: 'normal', + weight: 500, + } +}; + +canvas + .addFont(font) + .then(() => { + console.log('Font has been added'); + }); + + +``` +Returns a `Promise` after loading font + + +#### Canvas#initFonts(fonts) + +`fonts` are an array of objects that described above +```JS +const fonts = [font1, font2, ...]; + +canvas + .initFonts(fonts) + .then(() => { + console.log('Fonts h'); + }); + +``` +Returns a `Promise` after loading all fonts + + #### CanvasRenderingContext2D Standard CanvasRenderingContext2D. [MDN](https://developer.mozilla.org/en/docs/Web/API/CanvasRenderingContext2D). Only difference is `await` should be used to retrieve values from methods. diff --git a/src/Canvas.js b/src/Canvas.js index 3499224..d83fdc4 100644 --- a/src/Canvas.js +++ b/src/Canvas.js @@ -27,7 +27,7 @@ const stylesheet = StyleSheet.create({ @webviewTarget('canvas') @webviewProperties({width: 300, height: 150}) -@webviewMethods(['toDataURL']) +@webviewMethods(['toDataURL', 'initFonts', 'addFont']) export default class Canvas extends Component { state = { @@ -66,8 +66,11 @@ export default class Canvas extends Component { case '2d': { return this.context2D; } + + default: { + return null; + } } - return null; }; postMessage = async message => { diff --git a/src/webview.js b/src/webview.js index e5c86ce..8cfb3b7 100644 --- a/src/webview.js +++ b/src/webview.js @@ -33,6 +33,9 @@ const flattenObject = object => { class AutoScaledCanvas { constructor(element) { this.element = element; + + this.FontFace = window.FontFace; + this.fontFaceSet = document.fonts; } toDataURL(...args) { @@ -68,6 +71,27 @@ class AutoScaledCanvas { this.autoScale(); return value; } + + initFonts(fonts = []) { + return Promise + .all(fonts.map(font => this.addFont(font))); + } + + addFont(font) { + const { + name, + link, + options: { + style = 'normal', + weight = 500, + } = {}, + } = font; + return new Promise(resolve => { + const fontFace = this.FontFace(name, `url(${link})`, {style, weight}); + this.fontFaceSet.onloadingdone = resolve; + this.fontFaceSet.add(fontFace); + }); + } } const toMessage = result => { @@ -112,18 +136,16 @@ const toMessage = result => { * `webview-binders.js`. * */ -const toArgs = result => { - const args = []; - for (const key in result) { - if (result[key] !== undefined && key !== '@@WEBVIEW_TARGET') { - if (typedArrays[result[key].constructor.name] !== undefined) { - result[key] = Array.from(result[key]); - } - args.push(result[key]); +const toArgs = result => Object + .entries(result) + .filter(([key, value]) => !(value === undefined || key === '@@WEBVIEW_TARGET')) + .map(([, value]) => { + if (typedArrays[value.constructor.name] !== undefined) { + return Array.from(value); } - } - return args; -}; + + return value; + }); /** * Creates objects from args. If any argument have the object