Skip to content

Commit

Permalink
Browser Updates (#8)
Browse files Browse the repository at this point in the history
* Create framework for compatability API

* Add missing file

* Simplify type conversion

* Remove uneeded file
  • Loading branch information
siefkenj authored Dec 13, 2024
1 parent 62e7612 commit 632f814
Show file tree
Hide file tree
Showing 6 changed files with 50 additions and 38 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ mj_sre
dev
wasm
*~
.vscode
.vscode
.tsbuildinfo
37 changes: 5 additions & 32 deletions prefig/core/label_tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -204,41 +204,14 @@ def translate(self, text, typeform):


class PyodideTextMeasurements(AbstractTextMeasurements):
def __init__(self):
self.js_loaded = False
global js
try:
import js
log.info("js imported")
self.js_loaded = True
except:
from .compat import ErrorOnAccess
js = ErrorOnAccess("js")

js_code = '''
function js_measure_text(text) {
const canvas = document.createElement("canvas");
ctx = canvas.getContext("2d");
ctx.font = "14px sans";
const tm = ctx.measureText(text);
return [tm.width, tm.actualBoundingBoxAscent,tm.actualBoundingBoxDescent];
}
'''
try:
js.eval(js_code)
log.info("js_code evaluated")
except:
log.error("js_code evaluated")

def measure_text(self, text, font_data):
import json
text = json.dumps(text)
log.info('Called measure text')
try:
text_dims = js.eval(f"js_measure_text({text})").to_py()
log.info(f"text_dims found: {text_dims}")
log.error(f"type = {type(text_dims)}")
import prefigBrowserApi
# `prefigBrowserApi` will return a JsProxy. We want a native python object,
# so we convert it to a list.
metrics = prefigBrowserApi.measure_text(text, font_data).to_py()
return metrics
except Exception as e:
log.error(str(e))
log.error("text_dims not found")
return text_dims
4 changes: 2 additions & 2 deletions website/packages/playground/src/state/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ let compiler = new PreFigureCompiler();
(window as any).comp = compiler;

const worker = Comlink.wrap<typeof api>(new Worker());
console.log(worker, Worker);
//// Create a worker-based instance of the compiler
(window as any).compWorker = worker.compiler;
// The types seem to be wrong. We are not awaiting a promise here. Instead we have a proxy object
Expand Down Expand Up @@ -40,6 +39,7 @@ export const playgroundModel: PlaygroundModel = {
<circle center="(-2,3.5)" radius="2" fill="blue" thickness="5"/>
<ellipse center="(2,3)" axes="(1,2)" stroke="red"
rotate="pi/6" degrees="no"/>
<label anchor="(3,1)">foo</label>
</coordinates>
</diagram>`,
compiledSource: "",
Expand Down Expand Up @@ -90,7 +90,7 @@ export const playgroundModel: PlaygroundModel = {
try {
actions.setErrorState("");
const compiled = await compiler.compile(mode, source);
console.log("Got compiled results", compiled);
// console.log("Got compiled results", compiled);
actions.setCompiledSource(compiled.svg);
} catch (e) {
console.error(e);
Expand Down
33 changes: 33 additions & 0 deletions website/packages/playground/src/worker/compat-api.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/**
* This is the API used by PreFigure when running in the browser. It implements the necessary
* functions for Prefigure's abstract classes.
*/
export class PrefigBrowserApi {
offscreenCanvas: OffscreenCanvas | null = null;
ctx: OffscreenCanvasRenderingContext2D | null = null;
measure_text(text: string, _font_data?: unknown) {
if (!this.offscreenCanvas) {
this.offscreenCanvas = new OffscreenCanvas(200, 200);
}
if (!this.ctx) {
this.ctx = this.offscreenCanvas.getContext("2d");
if (!this.ctx) {
throw new Error("Failed to create canvas context");
}
}
// XXX replace this with proper data from `font_data`
this.ctx.font = "14px sans";

const tm = this.ctx.measureText(text);
console.log("Measured text", text, tm);
return [
tm.width,
tm.actualBoundingBoxAscent,
tm.actualBoundingBoxDescent,
];
}
}

export const prefigBrowserApi = new PrefigBrowserApi();

(globalThis as any).prefigBrowserApi = prefigBrowserApi;
10 changes: 8 additions & 2 deletions website/packages/playground/src/worker/compiler.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { PyodideInterface, loadPyodide } from "pyodide";
import { prefigBrowserApi } from "./compat-api";

type Options = Parameters<typeof loadPyodide>[0];

Expand Down Expand Up @@ -37,13 +38,18 @@ export class PreFigureCompiler {
this.pyodide =
(await this._pyodide) || (await loadPyodide(options));

// Set up our global compatibility API so it can be imported from Python with `import prefigBrowserApi`
this.pyodide.registerJsModule(
"prefigBrowserApi",
prefigBrowserApi,
);

// We want to make sure to load the prefig package from the same location that we are loading all
// the other packages from. This is accessing the internal `._api` from pyodide and might break in the
// future.
const PREFIG_PATH =
((this.pyodide as any)._api.config.indexURL as string) +
"prefig-0.2.11-py3-none-any.whl";
console.log({ PREFIG_PATH });

// Load all the dependencies
await this.pyodide.loadPackage([
Expand Down Expand Up @@ -80,12 +86,12 @@ export class PreFigureCompiler {
source: string,
): Promise<{ svg: string; annotations: unknown }> {
this._checkInit();

const result = await this.pyodide.runPython(`
import prefig
prefig.engine.build_from_string("${mode}", ${JSON.stringify(source)})
`);
const [svg, annotations] = result;
return { svg, annotations };
}

}
1 change: 0 additions & 1 deletion website/packages/playground/tsconfig.app.tsbuildinfo

This file was deleted.

0 comments on commit 632f814

Please sign in to comment.