Skip to content

Commit

Permalink
feat: render svg directly in 2d and 3d context
Browse files Browse the repository at this point in the history
  • Loading branch information
triniwiz committed Apr 5, 2024
1 parent 156ada3 commit 38cc5bd
Show file tree
Hide file tree
Showing 242 changed files with 16,007 additions and 6,705 deletions.
5 changes: 3 additions & 2 deletions apps/demo/src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@ Helpers.initialize();
require('@nativescript/canvas-polyfill');
*/
const TextDecoderO = TextDecoder;
// require('@nativescript/canvas-polyfill');
require('@nativescript/canvas-polyfill');
import { Svg } from '@nativescript/canvas-svg';
// import { Canvas } from '@nativescript/canvas';
declare const jp, GDPerformanceMonitor, android, java, UIColor;
let monitor;
import { Application, path as filePath, knownFolders, Utils, path as nsPath, ImageSource, Trace } from '@nativescript/core';
import { Application, path as filePath, knownFolders, Utils, path as nsPath, ImageSource, Trace, Screen } from '@nativescript/core';

Application.on('discardedError', (args) => {
console.log('discardedError', args.error, args);
Expand Down
2 changes: 1 addition & 1 deletion apps/demo/src/plugin-demos/canvas-svg.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
</ActionBar>
</Page.actionBar>
<GridLayout columns="*,*" rows="*,*" loaded="{{ viewLoaded }}">
<ui:Svg id="1" width="100%" height="100%" src="{{src1}}" loaded="{{svgViewLoaded}}"/>
<!-- <ui:Svg id="1" width="100%" height="100%" src="{{src1}}" loaded="{{svgViewLoaded}}"/> -->
<!--<ui:Svg id="2" col="1" width="100%" height="100%" src="{{src2}}" loaded="{{svgViewLoaded}}"/>
<ui:Svg id="3" row="1" width="100%" height="100%" src="{{src3}}" loaded="{{svgViewLoaded}}"/>
<ui:Svg id="4" row="1" col="1" width="100%" height="100%" src="{{src4}}" loaded="{{svgViewLoaded}}"/>-->
Expand Down
2 changes: 1 addition & 1 deletion packages/canvas-babylon/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@nativescript/canvas-babylon",
"version": "2.0.0-beta.19",
"version": "2.0.0-beta.21",
"description": "",
"main": "index",
"typings": "index.d.ts",
Expand Down
2 changes: 1 addition & 1 deletion packages/canvas-media/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@nativescript/canvas-media",
"version": "2.0.0-beta.19",
"version": "2.0.0-beta.21",
"description": "Canvas media",
"main": "index",
"typings": "index.d.ts",
Expand Down
2 changes: 1 addition & 1 deletion packages/canvas-phaser-ce/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@nativescript/canvas-phaser-ce",
"version": "2.0.0-beta.19",
"version": "2.0.0-beta.21",
"description": "Tools for using Phaser-ce to build native 2D games in NativeScript 👾",
"main": "index",
"typings": "index.d.ts",
Expand Down
2 changes: 1 addition & 1 deletion packages/canvas-phaser/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@nativescript/canvas-phaser",
"version": "2.0.0-beta.19",
"version": "2.0.0-beta.21",
"description": "Build awesome 2D games with Phaser.js and NativeScript",
"main": "index",
"typings": "index.d.ts",
Expand Down
3 changes: 2 additions & 1 deletion packages/canvas-pixi/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ class NSCPIXIApplication extends Pixii.Application {
const height = props.height || clientHeight;

super({
resolution: global.isAndroid ? window.devicePixelRatio : 1,
...props,
context,
view,
Expand All @@ -37,7 +38,7 @@ if (!(PIXI.Application instanceof NSCPIXIApplication)) {
PIXI.Assets.setPreferences({ preferWorkers: false });
PIXI = {
...PIXI,
Application: NSCPIXIApplication as never
Application: NSCPIXIApplication as never,
};
}

Expand Down
2 changes: 1 addition & 1 deletion packages/canvas-pixi/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@nativescript/canvas-pixi",
"version": "2.0.0-beta.19",
"version": "2.0.0-beta.21",
"description": "Plugin for using pixi.js in NativeScript",
"main": "index",
"typings": "index.d.ts",
Expand Down
202 changes: 182 additions & 20 deletions packages/canvas-polyfill/DOM/Document.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,109 @@ import { HTMLCanvasElement } from './HTMLCanvasElement';
import { HTMLDivElement } from './HTMLDivElement';
import { Text } from './Text';
import { Canvas } from '@nativescript/canvas';
import { Frame, StackLayout } from '@nativescript/core';
import { ContentView, Frame, StackLayout, eachDescendant } from '@nativescript/core';
import { Node } from './Node';
import { Element } from './Element';
import { Element, parseChildren } from './Element';
import { SVGSVGElement } from './svg/SVGSVGElement';
import { SVGElement } from './svg/SVGElement';
import { HTMLUnknownElement } from './HTMLUnknownElement';
import { HTMLCollection } from './HTMLCollection';

function getElementsByClassName(v, clsName) {
var retVal = [];
if (!v) {
return retVal;
}

if (v.classList.contains(clsName)) {
retVal.push(v);
}

const classNameCallback = function (child) {
if (child.classList.contains(clsName)) {
retVal.push(child);
}

// Android patch for ListView
if (child._realizedItems && child._realizedItems.size !== child._childrenCount) {
for (var key in child._realizedItems) {
if (child._realizedItems.hasOwnProperty(key)) {
classNameCallback(child._realizedItems[key]);
}
}
}

return true;
};

eachDescendant(v, classNameCallback);

// Android patch for ListView
if (v._realizedItems && v._realizedItems.size !== v._childrenCount) {
for (var key in v._realizedItems) {
if (v._realizedItems.hasOwnProperty(key)) {
classNameCallback(v._realizedItems[key]);
}
}
}

return retVal;
}

function getElementsByTagName(v, tagName) {
// TagName is case-Insensitive
var tagNameLC = tagName.toLowerCase();

var retVal = [],
allTags = false;
if (!v) {
return retVal;
}

if (tagName === '*') {
allTags = true;
}

if ((v.typeName && v.typeName.toLowerCase() === tagNameLC) || allTags) {
retVal.push(v);
}

const tagNameCallback = function (child) {
if ((child.typeName && child.typeName.toLowerCase() === tagNameLC) || allTags) {
retVal.push(child);
}

// Android patch for ListView
if (child._realizedItems && child._realizedItems.size !== child._childrenCount) {
for (var key in child._realizedItems) {
if (child._realizedItems.hasOwnProperty(key)) {
tagNameCallback(child._realizedItems[key]);
}
}
}

return true;
};

eachDescendant(v, tagNameCallback);

// Android patch for ListView
if (v._realizedItems && v._realizedItems.size !== v._childrenCount) {
for (var key in v._realizedItems) {
if (v._realizedItems.hasOwnProperty(key)) {
tagNameCallback(v._realizedItems[key]);
}
}
}

return retVal;
}

export class Document extends Node {
readonly body: Element;
private _documentElement: Element;
private readyState: string;
readonly head: Element;
readonly body: Element = null;
_documentElement: Element;
readonly readyState: string;
readonly head: Element = null;
__instance: Document;
get defaultView() {
return global.window;
Expand All @@ -25,11 +116,24 @@ export class Document extends Node {
constructor() {
super('#document');
this.body = new Element('BODY');
this.documentElement = new Element('HTML');
this._documentElement = new Element('HTML');
this.readyState = 'complete';
this.head = new Element('HEAD');
}

get children() {
const children = new HTMLCollection();
children.push(this._documentElement);
if (this.body) {
children.push(this.head);
children.push(this.body);
}
if (this.__instance) {
parseChildren(this.__instance, children);
}
return children;
}

_createElement(namespaceURI: string | null, tagName: string, options?: {}) {
if (namespaceURI === 'http://www.w3.org/2000/svg') {
switch ((tagName || '').toLowerCase()) {
Expand Down Expand Up @@ -59,6 +163,10 @@ export class Document extends Node {
return new SVGRadialGradientElement();
case 'linearGradient':
return new SVGLinearGradientElement();
case 'use':
return new SVGUseElement();
case 'stop':
return new SVGStopElement();
default:
return new SVGElement(tagName ?? `${tagName}`);
}
Expand All @@ -81,29 +189,54 @@ export class Document extends Node {
}

createElement(tagName: string, options?: {}) {
return this._createElement(null, tagName, options);
const element = this._createElement(null, tagName, options) as Element;
if (element) {
if (!element.nativeElement) {
// set dummy nativeElement
element.nativeElement = new ContentView();
element.nativeElement.__domElement = new DOMParser().parseFromString(`<${element.nodeName}/>`, 'text/html').documentElement as never;
}

element._ownerDocument = this as never;
}
return element;
}

createElementNS(namespaceURI: string | null, qualifiedName?: string, options?: {}) {
const element = this._createElement(namespaceURI, qualifiedName, options) as any;
element.namespaceURI = namespaceURI;
if (qualifiedName?.toLowerCase?.() !== 'canvas') {
element.toDataURL = () => ({});
const element = this._createElement(namespaceURI, qualifiedName, options) as Element;
element._namespaceURI = namespaceURI;
if (element) {
if (!element.nativeElement) {
// set dummy nativeElement
element.nativeElement = new ContentView();
element.nativeElement.__domElement = new DOMParser().parseFromString(`<${element.nodeName}/>`, 'image/svg+xml').documentElement as never;
}

element._ownerDocument = this as never;
}
return element;
}

createTextNode(data) {
return new Text(data);
const text = new Text(data);
text._ownerDocument = this as never;
return text;
}

getElementById(id: string) {
if (this.__instance) {
return this.__instance.getElementById(id);
}
console.log('getElementsByTagName', id);
const topmost = Frame.topmost();
if (topmost) {
const nativeElement = topmost.getViewById(id);
let nativeElement;
if (topmost.currentPage && topmost.currentPage.modal) {
nativeElement = topmost.getViewById(id);
} else {
nativeElement = topmost.currentPage.modal.getViewById(id);
}

if (nativeElement) {
if (nativeElement instanceof Canvas) {
const canvas = new HTMLCanvasElement();
Expand All @@ -126,30 +259,59 @@ export class Document extends Node {
if (this.__instance) {
return this.__instance.getElementsByTagName(tagname);
}
console.log('getElementsByTagName', tagname);
const topmost = Frame.topmost();
if (topmost) {
let view;
if (topmost.currentPage && topmost.currentPage.modal) {
view = topmost;
} else {
view = topmost.currentPage.modal;
}
const elements = getElementsByTagName(view, tagname);

return elements;
}
return [];
}

get documentElement() {
if (this._documentElement) {
return this._documentElement;
}
getElementsByClassName(className: string) {
if (this.__instance) {
return this.__instance?.documentElement;
return this.__instance.getElementsByClassName(className);
}
return null;
console.log('getElementsByClassName', className);
const topmost = Frame.topmost();
if (topmost) {
let view;
if (topmost.currentPage && topmost.currentPage.modal) {
view = topmost;
} else {
view = topmost.currentPage.modal;
}
const elements = getElementsByClassName(view, className);

return elements;
}
return [];
}

get documentElement() {
return this._documentElement;
}

//@ts-ignore
set documentElement(value) {}

querySelectorAll(selector) {
console.log('querySelectorAll', selector);
if (this.__instance) {
return this.__instance.querySelectorAll?.(selector) ?? [];
}
return [];
}

querySelector(selector) {
console.log('querySelector', selector);
const ret = this.__instance?.querySelectorAll?.(selector);
// let element = ret?.[0] ?? null;
// if (ret === undefined) {
Expand Down
Loading

0 comments on commit 38cc5bd

Please sign in to comment.