@@ -64,10 +64,8 @@ globalThis.qwebrComputeEngine = async function(
64
64
// 1. We setup a canvas device to write to by making a namespace call into the {webr} package
65
65
// 2. We use values inside of the options array to set the figure size.
66
66
// 3. We capture the output stream information (STDOUT and STERR)
67
- // 4. While parsing the results, we disable image creation.
68
-
69
- // Create a canvas variable for graphics
70
- let canvas = undefined ;
67
+ // 4. We disable the current device's image creation.
68
+ // 5. Piece-wise parse the results into the different output areas
71
69
72
70
// Create a pager variable for help/file contents
73
71
let pager = [ ] ;
@@ -92,9 +90,14 @@ globalThis.qwebrComputeEngine = async function(
92
90
await mainWebR . init ( ) ;
93
91
94
92
// Setup a webR canvas by making a namespace call into the {webr} package
95
- await mainWebR . evalRVoid ( `webr::canvas(width=${ fig_width } , height=${ fig_height } )` ) ;
96
-
97
- const result = await mainWebRCodeShelter . captureR ( codeToRun , {
93
+ // Evaluate the R code
94
+ // Remove the active canvas silently
95
+ const result = await mainWebRCodeShelter . captureR (
96
+ `webr::canvas(width=${ fig_width } , height=${ fig_height } , capture = TRUE)
97
+ .webr_cvs_id <- dev.cur()
98
+ ${ codeToRun }
99
+ invisible(dev.off(.webr_cvs_id))
100
+ ` , {
98
101
withAutoprint : true ,
99
102
captureStreams : true ,
100
103
captureConditions : false //,
@@ -105,9 +108,6 @@ globalThis.qwebrComputeEngine = async function(
105
108
106
109
// Start attempting to parse the result data
107
110
processResultOutput:try {
108
-
109
- // Stop creating images
110
- await mainWebR . evalRVoid ( "dev.off()" ) ;
111
111
112
112
// Avoid running through output processing
113
113
if ( options . results === "hide" || options . output === "false" ) {
@@ -130,34 +130,11 @@ globalThis.qwebrComputeEngine = async function(
130
130
131
131
132
132
// Clean the state
133
- // We're now able to process both graphics and pager events.
133
+ // We're now able to process pager events.
134
134
// As a result, we cannot maintain a true 1-to-1 output order
135
135
// without individually feeding each line
136
136
const msgs = await mainWebR . flush ( ) ;
137
137
138
- // Output each image event stored
139
- msgs . forEach ( ( msg ) => {
140
- // Determine if old canvas can be used or a new canvas is required.
141
- if ( msg . type === 'canvas' ) {
142
- // Add image to the current canvas
143
- if ( msg . data . event === 'canvasImage' ) {
144
- canvas . getContext ( '2d' ) . drawImage ( msg . data . image , 0 , 0 ) ;
145
- } else if ( msg . data . event === 'canvasNewPage' ) {
146
-
147
- // Generate a new canvas element
148
- canvas = document . createElement ( "canvas" ) ;
149
- canvas . setAttribute ( "width" , 2 * fig_width ) ;
150
- canvas . setAttribute ( "height" , 2 * fig_height ) ;
151
- canvas . style . width = options [ "out-width" ] ? options [ "out-width" ] : `${ fig_width } px` ;
152
- if ( options [ "out-height" ] ) {
153
- canvas . style . height = options [ "out-height" ] ;
154
- }
155
- canvas . style . display = "block" ;
156
- canvas . style . margin = "auto" ;
157
- }
158
- }
159
- } ) ;
160
-
161
138
// Use `map` to process the filtered "pager" events asynchronously
162
139
const pager = await Promise . all (
163
140
msgs . filter ( msg => msg . type === 'pager' ) . map (
@@ -185,13 +162,37 @@ globalThis.qwebrComputeEngine = async function(
185
162
186
163
elements . outputCodeDiv . appendChild ( pre ) ;
187
164
188
- // Place the graphics on the canvas
189
- if ( canvas ) {
165
+ // Determine if we have graphs to display
166
+ if ( result . images . length > 0 ) {
190
167
// Create figure element
191
168
const figureElement = document . createElement ( 'figure' ) ;
192
169
193
- // Append canvas to figure
194
- figureElement . appendChild ( canvas ) ;
170
+ // Place each rendered graphic onto a canvas element
171
+ result . images . forEach ( ( img ) => {
172
+ // Construct canvas for object
173
+ const canvas = document . createElement ( "canvas" ) ;
174
+
175
+ // Set canvas size to image
176
+ canvas . width = img . width ;
177
+ canvas . height = img . height ;
178
+
179
+ // Apply output truncations
180
+ canvas . style . width = options [ "out-width" ] ? options [ "out-width" ] : `${ fig_width } px` ;
181
+ if ( options [ "out-height" ] ) {
182
+ canvas . style . height = options [ "out-height" ] ;
183
+ }
184
+
185
+ // Apply styling
186
+ canvas . style . display = "block" ;
187
+ canvas . style . margin = "auto" ;
188
+
189
+ // Draw image onto Canvas
190
+ const ctx = canvas . getContext ( "2d" ) ;
191
+ ctx . drawImage ( img , 0 , 0 , img . width , img . height ) ;
192
+
193
+ // Append canvas to figure output area
194
+ figureElement . appendChild ( canvas ) ;
195
+ } ) ;
195
196
196
197
if ( options [ 'fig-cap' ] ) {
197
198
// Create figcaption element
0 commit comments