@@ -36,15 +36,16 @@ Possible drawing events:
3636###
3737
3838class DrawingLayer extends Layer
39- # (-> { model: ModelObj, quality: QualityObj, font: FontObj }) -> Unit
39+ # (-> { model: ModelObj, quality: QualityObj, font: FontObj }, (Unit) -> Unit ) -> Unit
4040 # see "./layer.coffee" for type info
41- constructor : (@_getDepInfo ) ->
41+ constructor : (@_getDepInfo , @_repaintCallback = -> ) ->
4242 super ()
4343 @_latestDepInfo = {
4444 model : undefined ,
4545 quality : undefined ,
4646 font : undefined
4747 }
48+ @_dirty = false
4849 @_canvas = document .createElement (' canvas' )
4950 @_ctx = @_canvas .getContext (' 2d' )
5051 return
@@ -56,33 +57,38 @@ class DrawingLayer extends Layer
5657 return
5758
5859 repaint : ->
59- if not mergeInfo (@_latestDepInfo , @ _getDepInfo ()) then return false
60-
61- { model : { model , worldShape }, quality : { quality } } = @_latestDepInfo
62- { worldWidth , worldHeight , patchsize } = worldShape
63- newWidth = worldWidth * patchsize * quality
64- newHeight = worldHeight * patchsize * quality
65- if @_canvas .width isnt newWidth or @_canvas .height isnt newHeight
66- # Save drawing content before resize (setting canvas dimensions always clears the canvas)
67- prevCanvas = document .createElement (' canvas' )
68- prevCanvas .width = @_canvas .width
69- prevCanvas .height = @_canvas .height
70- prevCanvas .getContext (' 2d' ).drawImage (@_canvas , 0 , 0 )
71- @_canvas .width = newWidth
72- @_canvas .height = newHeight
73- if prevCanvas .width > 0 and prevCanvas .height > 0
74- @_ctx .drawImage (prevCanvas, 0 , 0 , newWidth, newHeight)
75- for event in model .drawingEvents
76- switch event .type
77- when ' clear-drawing' then @ _clearDrawing ()
78- when ' line' then @ _drawLine (event)
79- when ' stamp-image'
80- switch event .agentType
81- when ' turtle' then @ _drawTurtleStamp (event .stamp )
82- when ' link' then @ _drawLinkStamp (event .stamp )
83- when ' import-drawing' then @ _importDrawing (event .imageBase64 )
84- # For those who still remember, `model.drawingEvents` is now reset by the ViewController after
85- # every layer has finished repainting.
60+ depsChanged = mergeInfo (@_latestDepInfo , @ _getDepInfo ())
61+ wasDrawnAsync = @_dirty
62+ @_dirty = false
63+ if not depsChanged and not wasDrawnAsync then return false
64+
65+ if depsChanged
66+ { model : { model , worldShape }, quality : { quality } } = @_latestDepInfo
67+ { worldWidth , worldHeight , patchsize } = worldShape
68+ newWidth = worldWidth * patchsize * quality
69+ newHeight = worldHeight * patchsize * quality
70+ if @_canvas .width isnt newWidth or @_canvas .height isnt newHeight
71+ # Save drawing content before resize (setting canvas dimensions always clears the canvas)
72+ prevCanvas = document .createElement (' canvas' )
73+ prevCanvas .width = @_canvas .width
74+ prevCanvas .height = @_canvas .height
75+ prevCanvas .getContext (' 2d' ).drawImage (@_canvas , 0 , 0 )
76+ @_canvas .width = newWidth
77+ @_canvas .height = newHeight
78+ if prevCanvas .width > 0 and prevCanvas .height > 0
79+ @_ctx .drawImage (prevCanvas, 0 , 0 , newWidth, newHeight)
80+ for event in model .drawingEvents
81+ switch event .type
82+ when ' clear-drawing' then @ _clearDrawing ()
83+ when ' line' then @ _drawLine (event)
84+ when ' stamp-image'
85+ switch event .agentType
86+ when ' turtle' then @ _drawTurtleStamp (event .stamp )
87+ when ' link' then @ _drawLinkStamp (event .stamp )
88+ when ' import-drawing' then @ _importDrawing (event .imageBase64 )
89+ # For those who still remember, `model.drawingEvents` is now reset by the ViewController after
90+ # every layer has finished repainting.
91+
8692 true
8793
8894 _clearDrawing : ->
@@ -148,7 +154,17 @@ class DrawingLayer extends Layer
148154 return
149155
150156 _importDrawing : (base64 ) ->
151- _clearDrawing ()
157+ @ _clearDrawing ()
158+ src =
159+ if base64 .startsWith (' data:' )
160+ base64
161+ else
162+ # Raw base64 from workspace resources; detect type by magic bytes
163+ mimeType =
164+ if base64 .startsWith (' R0lG' ) then ' image/gif'
165+ else if base64 .startsWith (' /9j/' ) then ' image/jpeg'
166+ else ' image/png'
167+ " data:#{ mimeType} ;base64,#{ base64} "
152168 image = new Image ()
153169 image .onload = () =>
154170 canvasRatio = @_canvas .width / @_canvas .height
@@ -163,7 +179,9 @@ class DrawingLayer extends Layer
163179 height = (canvasRatio / imageRatio) * @_canvas .height
164180
165181 @_ctx .drawImage (image, (@_canvas .width - width) / 2 , (@_canvas .height - height) / 2 , width, height)
166- image .src = base64
182+ @_dirty = true
183+ @ _repaintCallback ()
184+ image .src = src
167185 return
168186
169187 # x and y coordinates are given in CSS pixels not accounting for quality.
0 commit comments