@nativescript-community/ui-svg
Version:
Adds support for SVGs in your NativeScript apps.
178 lines • 7.95 kB
JavaScript
import { Length, Screen, Utils } from '@nativescript/core';
import { SVG as SVGBase, xfermodeFromString } from './canvas.common';
import { getSVG } from './index.android';
export { CanvasSVG } from './canvas.common';
let bgdImagePaint;
export class SVG extends SVGBase {
constructor() {
super(...arguments);
this.renderOptions = new com.caverock.androidsvg.RenderOptions();
this._preserveAspectRatio = com.caverock.androidsvg.PreserveAspectRatio.LETTERBOX;
}
getWidth(availableWidth, availableHeight) {
if (this.width) {
return super.getWidth(availableWidth, availableHeight);
}
const svg = this._svg;
if (!svg) {
return 0;
}
const viewRect = svg.getDocumentViewBox();
if (viewRect) {
const nativeWidth = viewRect.width();
const nativeHeight = viewRect.height();
const width = Math.min(nativeWidth, availableWidth);
const height = this.height ? this.getHeight(availableWidth, availableHeight) : Math.min(nativeHeight, availableHeight);
let paintedWidth = width;
let paintedHeight = height;
const nativeAspectRatio = nativeWidth / nativeHeight;
const boundedAspectRatio = width / height;
if (this._stretch === 'aspectFit') {
if (nativeAspectRatio >= boundedAspectRatio) {
// blank space on top and bottom
paintedHeight = paintedWidth / nativeAspectRatio;
}
else {
paintedWidth = paintedHeight * nativeAspectRatio;
}
return paintedWidth;
}
else if (this._stretch === 'aspectFill') {
if (nativeAspectRatio <= boundedAspectRatio) {
// blank space on top and bottom
paintedHeight = paintedWidth / nativeAspectRatio;
}
else {
paintedWidth = paintedHeight * nativeAspectRatio;
}
return paintedWidth;
}
return paintedWidth;
}
return svg.getDocumentWidth();
}
getHeight(availableWidth, availableHeight) {
if (this.height) {
return super.getHeight(availableWidth, availableHeight);
}
const svg = this._svg;
if (!svg) {
return 0;
}
const viewRect = svg.getDocumentViewBox();
if (viewRect) {
const nativeWidth = viewRect.width();
const nativeHeight = viewRect.height();
const height = Math.min(nativeHeight, availableHeight);
const width = this.width ? this.getWidth(availableWidth, availableHeight) : Math.min(nativeHeight, availableHeight);
let paintedWidth = width;
let paintedHeight = height;
const nativeAspectRatio = nativeWidth / nativeHeight;
const boundedAspectRatio = width / height;
if (this._stretch === 'aspectFit') {
if (nativeAspectRatio >= boundedAspectRatio) {
// blank space on top and bottom
paintedHeight = paintedWidth / nativeAspectRatio;
}
else {
paintedWidth = paintedHeight * nativeAspectRatio;
}
return paintedHeight;
}
else if (this._stretch === 'aspectFill') {
if (nativeAspectRatio <= boundedAspectRatio) {
// blank space on top and bottom
paintedHeight = paintedWidth / nativeAspectRatio;
}
else {
paintedWidth = paintedHeight * nativeAspectRatio;
}
return paintedHeight;
}
return paintedHeight;
}
return svg.getDocumentHeight();
}
drawOnCanvas(canvas, parent) {
const svg = this._svg;
if (svg) {
// const startTime = new Date().valueOf();
// const wasCached = !!this._cachedImage;
const availableWidth = Utils.layout.toDevicePixels(canvas.getWidth());
const availableHeight = Utils.layout.toDevicePixels(canvas.getHeight());
let options = this.renderOptions;
const width = this.getWidth(availableWidth, availableHeight);
const height = this.getHeight(availableWidth, availableHeight);
// const box = svg.getDocumentViewBox();
// const nativeWidth = box ? box.width() : width;
// const nativeHeight = box ? box.height() : height;
// const nativeAspectRatio = nativeWidth / nativeHeight;
// const boundedAspectRatio = width / height;
const paintedWidth = width;
const paintedHeight = height;
// does not seem like we need this. Handled by options?
// if (nativeAspectRatio >= boundedAspectRatio) {
// paintedHeight = paintedWidth / nativeAspectRatio;
// } else {
// paintedWidth = paintedHeight * nativeAspectRatio;
// }
const xOrigin = (width - paintedWidth) / 2.0;
const yOrigin = (height - paintedHeight) / 2.0;
options = options.preserveAspectRatio(this._preserveAspectRatio);
if (this.blendingMode || this.cache) {
let newBitmap = this._cachedImage;
const scale = Screen.mainScreen.scale;
if (!this.cache || !this._cachedImage) {
newBitmap = android.graphics.Bitmap.createBitmap(width * scale, height * scale, android.graphics.Bitmap.Config.ARGB_8888);
const bmcanvas = new android.graphics.Canvas(newBitmap);
bmcanvas.setDensity(Math.round(scale * 160));
svg.renderToCanvas(bmcanvas, options);
if (this.cache) {
this._cachedImage = newBitmap;
}
}
if (this.blendingMode) {
if (!bgdImagePaint) {
bgdImagePaint = new android.graphics.Paint();
}
bgdImagePaint.setXfermode(new android.graphics.PorterDuffXfermode(xfermodeFromString(this.blendingMode)));
}
canvas.drawBitmap(newBitmap, new android.graphics.Rect(0, 0, width * scale, height * scale), new android.graphics.Rect(xOrigin, yOrigin, width, height), bgdImagePaint);
}
else {
options.viewPort(-xOrigin + Utils.layout.toDeviceIndependentPixels(Length.toDevicePixels(this.left)), -yOrigin + Utils.layout.toDeviceIndependentPixels(Length.toDevicePixels(this.top)), width, height);
svg.renderToCanvas(canvas.getNative(), options);
}
// console.log('drawSvg', wasCached, Date.now() - startTime, 'ms');
}
}
set src(value) {
this._src = value;
this._svg = getSVG(value);
if (this._svg) {
this._svg.setDocumentWidth('100%');
this._svg.setDocumentHeight('100%');
}
}
get src() {
return this._src;
}
set stretch(value) {
this._stretch = value;
switch (value) {
case 'aspectFill':
this._preserveAspectRatio = com.caverock.androidsvg.PreserveAspectRatio.FULLSCREEN;
break;
case 'fill':
this._preserveAspectRatio = com.caverock.androidsvg.PreserveAspectRatio.STRETCH;
break;
case 'aspectFit':
this._preserveAspectRatio = com.caverock.androidsvg.PreserveAspectRatio.LETTERBOX;
break;
}
}
get stretch() {
return this._stretch;
}
}
//# sourceMappingURL=canvas.android.js.map