|
7 | 7 | """ |
8 | 8 |
|
9 | 9 | import gzip |
| 10 | +import math |
10 | 11 |
|
11 | 12 | import numpy as np |
12 | 13 |
|
@@ -402,8 +403,47 @@ def set_linewidth(self, w): |
402 | 403 | self.ctx.set_line_width(self.renderer.points_to_pixels(w)) |
403 | 404 |
|
404 | 405 |
|
| 406 | +class _CairoRegion: |
| 407 | + def __init__(self, slices, data): |
| 408 | + self._slices = slices |
| 409 | + self._data = data |
| 410 | + |
| 411 | + |
405 | 412 | class FigureCanvasCairo(FigureCanvasBase): |
406 | 413 |
|
| 414 | + def copy_from_bbox(self, bbox): |
| 415 | + surface = self._renderer.gc.ctx.get_target() |
| 416 | + if not isinstance(surface, cairo.ImageSurface): |
| 417 | + raise RuntimeError( |
| 418 | + "copy_from_bbox only works when rendering to an ImageSurface") |
| 419 | + sw = surface.get_width() |
| 420 | + sh = surface.get_height() |
| 421 | + x0 = math.ceil(bbox.x0) |
| 422 | + x1 = math.floor(bbox.x1) |
| 423 | + y0 = math.ceil(sh - bbox.y1) |
| 424 | + y1 = math.floor(sh - bbox.y0) |
| 425 | + if not (0 <= x0 and x1 <= sw and bbox.x0 <= bbox.x1 |
| 426 | + and 0 <= y0 and y1 <= sh and bbox.y0 <= bbox.y1): |
| 427 | + raise ValueError("Invalid bbox") |
| 428 | + sls = slice(y0, y0 + max(y1 - y0, 0)), slice(x0, x0 + max(x1 - x0, 0)) |
| 429 | + data = (np.frombuffer(surface.get_data(), np.uint32) |
| 430 | + .reshape((sh, sw))[sls].copy()) |
| 431 | + return _CairoRegion(sls, data) |
| 432 | + |
| 433 | + def restore_region(self, region): |
| 434 | + surface = self._renderer.gc.ctx.get_target() |
| 435 | + if not isinstance(surface, cairo.ImageSurface): |
| 436 | + raise RuntimeError( |
| 437 | + "restore_region only works when rendering to an ImageSurface") |
| 438 | + surface.flush() |
| 439 | + sw = surface.get_width() |
| 440 | + sh = surface.get_height() |
| 441 | + sly, slx = region._slices |
| 442 | + (np.frombuffer(surface.get_data(), np.uint32) |
| 443 | + .reshape((sh, sw))[sly, slx]) = region._data |
| 444 | + surface.mark_dirty_rectangle( |
| 445 | + slx.start, sly.start, slx.stop - slx.start, sly.stop - sly.start) |
| 446 | + |
407 | 447 | def print_png(self, fobj, *args, **kwargs): |
408 | 448 | self._get_printed_image_surface().write_to_png(fobj) |
409 | 449 |
|
|
0 commit comments