Skip to content

Commit 77ee40a

Browse files
committed
Use ragg in R bitmap fallback if available
1 parent 6ce307b commit 77ee40a

File tree

5 files changed

+25
-14
lines changed

5 files changed

+25
-14
lines changed

_extensions/live/resources/live-runtime.js

Lines changed: 8 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/reference/cell-options.qmd

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ The following code cell options can be used in `webr` or `pyodide` blocks, or se
1313
|--------|---------|-------------|
1414
| `autorun` | `false` | Evaluate initial code block contents automatically? |
1515
| `caption` | None | Heading text for code editor block. |
16+
| `canvas` | `true` | Use HTML canvas graphics? |
1617
| `completion` | `true` | Show code completion and suggestions in editor? |
1718
| `echo` | `false` | Show source code in output display? |
1819
| `edit` | `true` | Show the code editor? If `false`, a read-only code block is shown. |

live-runtime/src/editor.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ export type OJSEditorElement = HTMLElement & { value?: EditorValue };
2020

2121
type ExerciseOptions = EvaluateOptions & {
2222
autorun: boolean;
23+
canvas: boolean;
2324
caption: string;
2425
completion: boolean;
2526
id: string,
@@ -108,6 +109,7 @@ abstract class ExerciseEditor {
108109
// Default editor options
109110
this.options = Object.assign({
110111
autorun: false,
112+
canvas: true,
111113
completion: true,
112114
runbutton: true,
113115
startover: true,

live-runtime/src/evaluate-webr.ts

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,7 @@ export class WebREvaluator implements ExerciseEvaluator {
383383
const imageDiv = document.createElement("img");
384384
outputDiv.className = "cell-output-display cell-output-pyodide";
385385
imageDiv.src = `data:${mime};base64, ${data}`;
386+
imageDiv.style.maxWidth = "100%";
386387
outputDiv.appendChild(imageDiv);
387388
container.appendChild(outputDiv);
388389
}
@@ -426,28 +427,31 @@ export class WebREvaluator implements ExerciseEvaluator {
426427

427428
// Plot image
428429
if (classes.includes('recordedplot')) {
429-
let width = await this.webR.evalRNumber('72 * getOption("webr.fig.width")');
430+
let width = await this.webR.evalRNumber('getOption("webr.fig.width")');
430431
if ("fig-width" in this.options) {
431-
width = 72 * Number(this.options["fig-width"]);
432+
width = Number(this.options["fig-width"]);
432433
}
433-
let height = await this.webR.evalRNumber('72 * getOption("webr.fig.height")');
434+
let height = await this.webR.evalRNumber('getOption("webr.fig.height")');
434435
if ("fig-height" in this.options) {
435-
height = 72 * Number(this.options["fig-height"]);
436+
height = Number(this.options["fig-height"]);
436437
}
437438

438-
if (typeof OffscreenCanvas !== "undefined") {
439+
if (typeof OffscreenCanvas !== "undefined" && this.options.canvas) {
439440
const capturePlot = await shelter.captureR("replayPlot(plot)", {
440-
captureGraphics: { width, height },
441+
captureGraphics: { width: 72 * width, height: 72 * height },
441442
env: { plot: result[i] },
442443
});
443444
appendImage(capturePlot.images[0]);
444445
} else {
445446
// Fallback to cairo graphics
446447
const data = await shelter.evalR(`
447448
tmp_dir <- tempdir()
448-
on.exit(unlink(tmp_dir, recursive = TRUE))
449449
filename <- paste0(tmp_dir, ".webr-plot.png")
450-
png(file = filename, width = width, height = height)
450+
if (requireNamespace("ragg", quietly = TRUE)) {
451+
ragg::agg_png(file = filename, width = width, height = height, units = "in", res = 300)
452+
} else {
453+
png(file = filename, width = width, height = height, units = "in", res = 300)
454+
}
451455
replayPlot(plot)
452456
dev.off()
453457
filesize <- file.info(filename)[["size"]]
@@ -507,7 +511,7 @@ export class WebREvaluator implements ExerciseEvaluator {
507511
const height = await this.webR.evalRNumber('72 * getOption("webr.fig.height")');
508512
let images: (ImageBitmap | HTMLImageElement)[] = [];
509513

510-
const hasOffscreenCanvas = typeof OffscreenCanvas !== "undefined";
514+
const hasOffscreenCanvas = this.options.canvas && typeof OffscreenCanvas !== "undefined";
511515
if (!hasOffscreenCanvas) {
512516
// Fallback to cairo graphics
513517
this.webR.evalRVoid(`

live-runtime/src/evaluate.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ export type EvaluateValue = {
99
export type OJSEvaluateElement = HTMLElement & { value?: EvaluateValue };
1010

1111
export type EvaluateOptions = {
12+
canvas: boolean;
1213
define?: string[];
1314
echo: boolean;
1415
envir: string;

0 commit comments

Comments
 (0)