Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PIL Image Kiva Backend #969

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
1 change: 1 addition & 0 deletions enable/gcbench/bench.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
"blend2d": "enable.null.blend2d",
"cairo": "enable.null.cairo",
"celiagg": "enable.null.celiagg",
"pil_image": "enable.null.pil_image",
"qpainter": "enable.null.qpainter",
"quartz": "enable.null.quartz",
},
Expand Down
26 changes: 26 additions & 0 deletions enable/null/pil_image.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# (C) Copyright 2005-2022 Enthought, Inc., Austin, TX
# All rights reserved.
#
# This software is provided without warranty under the terms of the BSD
# license included in LICENSE.txt and may be redistributed only under
# the conditions described in the aforementioned license. The license
# is also available online at http://www.enthought.com/licenses/BSD.txt
#
# Thanks for using Enthought open source!
from kiva.pil_image import CompiledPath, GraphicsContext # noqa


class NativeScrollBar(object):
pass


class Window(object):
pass


def font_metrics_provider():
from kiva.api import Font

gc = GraphicsContext((1, 1))
gc.set_font(Font())
return gc
78 changes: 78 additions & 0 deletions enable/qt4/pil_image.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# (C) Copyright 2005-2022 Enthought, Inc., Austin, TX
# All rights reserved.
#
# This software is provided without warranty under the terms of the BSD
# license included in LICENSE.txt and may be redistributed only under
# the conditions described in the aforementioned license. The license
# is also available online at http://www.enthought.com/licenses/BSD.txt
#
# Thanks for using Enthought open source!

import numpy as np
from kiva.pil_image import CompiledPath, GraphicsContext # noqa
from pyface.qt import QtCore, QtGui
from traits.api import Array

from .base_window import BaseWindow
from .scrollbar import NativeScrollBar # noqa


class Window(BaseWindow):
# Keep a buffer around for converting RGBA -> BGRA
_shuffle_buffer = Array(shape=(None, None, 4), dtype=np.uint8)

def _create_gc(self, size, pix_format="rgba32"):
gc = GraphicsContext(
(size[0] + 1, size[1] + 1),
pix_format=pix_format,
base_pixel_scale=self.base_pixel_scale,
)
gc.translate_ctm(0.5, 0.5)

self._shuffle_buffer = np.empty(
(size[1] + 1, size[0] + 1, 4), dtype=np.uint8
)

return gc

def _window_paint(self, event):
if self.control is None:
return

# Convert to Qt's pixel format
self._shuffle_copy()

# self._gc is an image context
w = self._gc.width()
h = self._gc.height()
image = QtGui.QImage(
self._shuffle_buffer, w, h, QtGui.QImage.Format_RGB32
)
rect = QtCore.QRectF(
0, 0, w / self._gc.base_scale, h / self._gc.base_scale
)
painter = QtGui.QPainter(self.control)
painter.drawImage(rect, image)

def _shuffle_copy(self):
""" Convert from RGBA -> BGRA.
Supported source formats are: rgb24, rgba32, & bgra32

Qt's Format_RGB32 is actually BGR. So, Yeah...
"""
src = np.array(self._gc.image)
dst = self._shuffle_buffer

indices = (2, 1, 0)
dst[..., 0] = src[..., indices[0]]
dst[..., 1] = src[..., indices[1]]
dst[..., 2] = src[..., indices[2]]
dst[..., 3] = src[..., 3]


def font_metrics_provider():
from kiva.api import Font

gc = GraphicsContext((1, 1))
gc.set_font(Font())
return gc
50 changes: 50 additions & 0 deletions enable/wx/pil_image.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# (C) Copyright 2005-2022 Enthought, Inc., Austin, TX
# All rights reserved.
#
# This software is provided without warranty under the terms of the BSD
# license included in LICENSE.txt and may be redistributed only under
# the conditions described in the aforementioned license. The license
# is also available online at http://www.enthought.com/licenses/BSD.txt
#
# Thanks for using Enthought open source!

import numpy as np
import wx

from kiva.pil_image import CompiledPath, GraphicsContext # noqa

from .base_window import BaseWindow
from .scrollbar import NativeScrollBar


class Window(BaseWindow):
def _create_gc(self, size, pix_format="bgra32"):
gc = GraphicsContext(
(size[0] + 1, size[1] + 1),
base_pixel_scale=self.base_pixel_scale,
)
gc.translate_ctm(0.5, 0.5)
return gc

def _window_paint(self, event):
if self.control is None:
event.Skip()
return

control = self.control
wdc = control._dc = wx.PaintDC(control)

bmp = wx.Bitmap.FromBufferRGBA(
self._gc.width(), self._gc.height(), self._gc.image.tobytes()
)
wdc.DrawBitmap(bmp, 0, 0)

control._dc = None


def font_metrics_provider():
from kiva.api import Font

gc = GraphicsContext((1, 1))
gc.set_font(Font())
return gc
3 changes: 2 additions & 1 deletion kiva/basecore2d.py
Original file line number Diff line number Diff line change
Expand Up @@ -1218,7 +1218,8 @@ def device_transform_device_ctm(self, func, args):
elif func == CONCAT_CTM:
self.device_ctm = affine.concat(self.device_ctm, args[0])
elif func == LOAD_CTM:
self.device_ctm = args[0].copy()
self.device_prepare_device_ctm()
self.device_ctm = affine.concat(self.device_ctm, args[0])

def device_draw_rect(self, x, y, sx, sy, mode):
""" Default implementation of drawing a rect.
Expand Down
Loading