@@ -44,10 +44,25 @@ def _restore_foreground_window_at_end():
4444 _c_internal_utils .Win32_SetForegroundWindow (foreground )
4545
4646
47- def blit (photoimage , aggimage , offsets , bbox = None ):
47+ _blit_args = {}
48+ _blit_tcl_name = None
49+
50+
51+ def _blit (argsid ):
52+ """
53+ Thin wrapper to pass arguments to blit via tkapp.call
54+ """
55+ args = _blit_args .pop (argsid )
56+ _tkagg .blit (* args )
57+
58+
59+ def blit (tk_instance , photoimage , aggimage , offsets , bbox = None ):
4860 """
4961 Blit *aggimage* to *photoimage*.
5062
63+ A *tk_instance* such as a canvas is required execute the blit.
64+ Tcl events must be dispatched to trigger a blit from a non-Tcl thread.
65+
5166 *offsets* is a tuple describing how to fill the ``offset`` field of the
5267 ``Tk_PhotoImageBlock`` struct: it should be (0, 1, 2, 3) for RGBA8888 data,
5368 (2, 1, 0, 3) for little-endian ARBG32 (i.e. GBRA8888) data and (1, 2, 3, 0)
@@ -68,8 +83,22 @@ def blit(photoimage, aggimage, offsets, bbox=None):
6883 else :
6984 photoimage .blank ()
7085 bboxptr = (0 , width , 0 , height )
71- _tkagg .blit (
86+
87+ args = (
7288 photoimage .tk .interpaddr (), str (photoimage ), dataptr , offsets , bboxptr )
89+ argsid = str (id )
90+ _blit_args [argsid ] = args
91+
92+ global _blit_tcl_name
93+ # tkapp.call coerces all arguments to strings
94+ try :
95+ tk_instance .tk .call (_blit_tcl_name , argsid )
96+ except tk .TclError :
97+ # need to register with the tk root or constantly re-register
98+ # each time tk_instance is destroyed
99+ root = tk_instance ._root ()
100+ _blit_tcl_name = root .register (_blit )
101+ tk_instance .tk .call (_blit_tcl_name , argsid )
73102
74103
75104class TimerTk (TimerBase ):
@@ -123,9 +152,6 @@ def __init__(self, figure, master=None, resize_callback=None):
123152 width = w , height = h , borderwidth = 0 , highlightthickness = 0 )
124153 self ._tkphoto = tk .PhotoImage (
125154 master = self ._tkcanvas , width = w , height = h )
126- self ._findphoto_name = self ._tkcanvas .register (self ._findphoto )
127- self ._photoputblock_name = self ._tkcanvas .register (self ._photoputblock )
128- self ._tkpointers = None
129155 self ._tkcanvas .create_image (w // 2 , h // 2 , image = self ._tkphoto )
130156 self ._resize_callback = resize_callback
131157 self ._tkcanvas .bind ("<Configure>" , self .resize )
@@ -181,41 +207,6 @@ def resize(self, event):
181207 int (width / 2 ), int (height / 2 ), image = self ._tkphoto )
182208 self .resize_event ()
183209
184- def _findphoto (self ):
185- return _tkagg .findphoto (self ._tkphoto .tk .interpaddr (), str (self ._tkphoto ))
186-
187- def _photoputblock (self ):
188- photoptr , dataptr , bboxptr = self ._tkpointers
189- _tkagg .photoputblock (photoptr , dataptr , (0 , 1 , 2 , 3 ), bboxptr )
190-
191- def blit (self , bbox = None ):
192- """
193- Blit *aggimage* to *photoimage*.
194-
195- *offsets* is a tuple describing how to fill the ``offset`` field of the
196- ``Tk_PhotoImageBlock`` struct: it should be (0, 1, 2, 3) for RGBA8888 data,
197- (2, 1, 0, 3) for little-endian ARBG32 (i.e. GBRA8888) data and (1, 2, 3, 0)
198- for big-endian ARGB32 (i.e. ARGB8888) data.
199-
200- If *bbox* is passed, it defines the region that gets blitted.
201- """
202- data = np .asarray (self .renderer ._renderer )
203- height , width = data .shape [:2 ]
204- dataptr = (height , width , data .ctypes .data )
205- if bbox is not None :
206- (x1 , y1 ), (x2 , y2 ) = bbox .__array__ ()
207- x1 = max (math .floor (x1 ), 0 )
208- x2 = min (math .ceil (x2 ), width )
209- y1 = max (math .floor (y1 ), 0 )
210- y2 = min (math .ceil (y2 ), height )
211- bboxptr = (x1 , x2 , y1 , y2 )
212- else :
213- self ._tkphoto .blank ()
214- bboxptr = (0 , width , 0 , height )
215- photoptr = self ._master .tk .call (self ._findphoto_name )
216- self ._tkpointers = photoptr , dataptr , bboxptr
217- self ._master .tk .call (self ._photoputblock_name )
218-
219210 def draw_idle (self ):
220211 # docstring inherited
221212 if not self ._idle :
0 commit comments