|
3 | 3 |
|
4 | 4 | import six
|
5 | 5 |
|
6 |
| -import numpy as np |
| 6 | +import sys |
7 | 7 | import warnings
|
8 | 8 |
|
| 9 | +import numpy as np |
| 10 | + |
9 | 11 | from . import backend_agg, backend_gtk3
|
10 | 12 | from .backend_cairo import cairo, HAS_CAIRO_CFFI
|
11 | 13 | from .backend_gtk3 import _BackendGTK3
|
@@ -48,20 +50,29 @@ def on_draw_event(self, widget, ctx):
|
48 | 50 | incref=True)
|
49 | 51 |
|
50 | 52 | for bbox in bbox_queue:
|
51 |
| - area = self.copy_from_bbox(bbox) |
52 |
| - buf = np.fromstring(area.to_string_argb(), dtype='uint8') |
53 |
| - |
54 | 53 | x = int(bbox.x0)
|
55 | 54 | y = h - int(bbox.y1)
|
56 | 55 | width = int(bbox.x1) - int(bbox.x0)
|
57 | 56 | height = int(bbox.y1) - int(bbox.y0)
|
58 | 57 |
|
59 |
| - if HAS_CAIRO_CFFI: |
60 |
| - image = cairo.ImageSurface.create_for_data( |
61 |
| - buf.data, cairo.FORMAT_ARGB32, width, height) |
| 58 | + buf = (np.fromstring(self.copy_from_bbox(bbox).to_string_argb(), |
| 59 | + dtype='uint8') |
| 60 | + .reshape((width, height, 4))) |
| 61 | + # cairo wants premultiplied alpha. Only bother doing the |
| 62 | + # conversion when the alpha channel is not fully opaque, as the |
| 63 | + # cost is not negligible. (The unsafe cast is needed to do the |
| 64 | + # multiplication in-place in an integer buffer.) |
| 65 | + if sys.byteorder == "little": |
| 66 | + rgb24 = buf[..., :-1] |
| 67 | + alpha8 = buf[..., -1:] |
62 | 68 | else:
|
63 |
| - image = cairo.ImageSurface.create_for_data( |
64 |
| - buf, cairo.FORMAT_ARGB32, width, height) |
| 69 | + alpha8 = buf[..., :1] |
| 70 | + rgb24 = buf[..., 1:] |
| 71 | + if alpha8.min() != 0xff: |
| 72 | + np.multiply(rgb24, alpha8 / 0xff, out=rgb24, casting="unsafe") |
| 73 | + |
| 74 | + image = cairo.ImageSurface.create_for_data( |
| 75 | + buf.ravel().data, cairo.FORMAT_ARGB32, width, height) |
65 | 76 | ctx.set_source_surface(image, x, y)
|
66 | 77 | ctx.paint()
|
67 | 78 |
|
|
0 commit comments