Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Address review comments.
  • Loading branch information
anntzer committed May 6, 2018
commit aca804f865fb08df66df0c8d97787d113013d75f
13 changes: 9 additions & 4 deletions doc/api/backend_cairo_api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,12 @@
:mod:`matplotlib.backends.backend_cairo`
========================================

.. automodule:: matplotlib.backends.backend_cairo
:members:
:undoc-members:
:show-inheritance:
.. Building the docs requires either adding pycairo/cairocffi as docs build
dependency, or bumping the minimal numpy version to one that supports
MagicMocks (which does define `__index__`) as indices (recent numpys do, but
1.7.1 doesn't).

.. .. automodule:: matplotlib.backends.backend_cairo
.. :members:
.. :undoc-members:
.. :show-inheritance:
31 changes: 14 additions & 17 deletions lib/matplotlib/backends/backend_cairo.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,15 +94,6 @@ def buffer_info(self):
_CAIRO_PATH_TYPE_SIZES[cairo.PATH_CLOSE_PATH] = 1


def _convert_path(ctx, path, transform, clip=None):
return _convert_paths(ctx, [path], [transform], clip)


def _convert_paths(ctx, paths, transforms, clip=None):
return (_convert_paths_fast if HAS_CAIRO_CFFI else _convert_paths_slow)(
ctx, paths, transforms, clip)


def _convert_paths_slow(ctx, paths, transforms, clip=None):
for path, transform in zip(paths, transforms):
for points, code in path.iter_segments(transform, clip=clip):
Expand All @@ -123,7 +114,7 @@ def _convert_paths_slow(ctx, paths, transforms, clip=None):

def _convert_paths_fast(ctx, paths, transforms, clip=None):
# We directly convert to the internal representation used by cairo, for
# which ABI compatibility is guaranteed. The layout is for each item is
# which ABI compatibility is guaranteed. The layout for each item is
# --CODE(4)-- -LENGTH(4)- ---------PAD(8)---------
# ----------X(8)---------- ----------Y(8)----------
# with the size in bytes in parentheses, and (X, Y) repeated as many times
Expand Down Expand Up @@ -154,10 +145,10 @@ def _convert_paths_fast(ctx, paths, transforms, clip=None):
# Fill the buffer.
buf = np.empty(cairo_num_data * 16, np.uint8)
as_int = np.frombuffer(buf.data, np.int32)
as_float = np.frombuffer(buf.data, np.float64)
mask = np.ones_like(as_float, bool)
as_int[::4][cairo_type_positions] = codes
as_int[1::4][cairo_type_positions] = cairo_type_sizes
as_float = np.frombuffer(buf.data, np.float64)
mask = np.ones_like(as_float, bool)
mask[::2][cairo_type_positions] = mask[1::2][cairo_type_positions] = False
as_float[mask] = vertices.ravel()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could be re-arranged slightly to keep the int and float bits together.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure what you meant?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, you start with a buffer, make an int version, then a float version, then a mask (which is for float). But then go back to filling the int version, modifying the mask (which is float stuff again), then fill the float version. So I mean more like:

    buf = np.empty(cairo_num_data * 16, np.uint8)
    as_int = np.frombuffer(buf.data, np.int32)
    as_int[::4][cairo_type_positions] = codes
    as_int[1::4][cairo_type_positions] = cairo_type_sizes
    as_float = np.frombuffer(buf.data, np.float64)
    mask = np.ones_like(as_float, bool)
    mask[::2][cairo_type_positions] = mask[1::2][cairo_type_positions] = False
    as_float[mask] = vertices.ravel() 


Expand All @@ -169,6 +160,13 @@ def _convert_paths_fast(ctx, paths, transforms, clip=None):
cairo.cairo.cairo_append_path(ctx._pointer, ptr)


_convert_paths = _convert_paths_fast if HAS_CAIRO_CFFI else _convert_paths_slow


def _convert_path(ctx, path, transform, clip=None):
return _convert_paths(ctx, [path], [transform], clip)


class RendererCairo(RendererBase):
fontweights = {
100 : cairo.FONT_WEIGHT_NORMAL,
Expand Down Expand Up @@ -247,8 +245,7 @@ def draw_markers(self, gc, marker_path, marker_trans, path, transform,

ctx.new_path()
# Create the path for the marker; it needs to be flipped here already!
_convert_path(
ctx, marker_path, marker_trans + Affine2D().scale(1, -1))
_convert_path(ctx, marker_path, marker_trans + Affine2D().scale(1, -1))
marker_path = ctx.copy_path_flat()

# Figure out whether the path has a fill
Expand Down Expand Up @@ -312,7 +309,7 @@ def _draw_paths():
for k, v in gc_vars.items():
try:
getattr(gc, "set" + k)(v)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No underscore is needed?

Copy link
Contributor Author

@anntzer anntzer Feb 3, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually no, I'm just copying the __dict__ of the original gc, and (kind of an implementation detail...) GraphicsContextBase stores "property" foo (accessed by get/set_foo) in ._foo). Not very elegant I admit.

except (AttributeError, TypeError):
except (AttributeError, TypeError) as e:
pass
gc.ctx.new_path()
paths, transforms = zip(*grouped_draw)
Expand All @@ -326,8 +323,8 @@ def _draw_paths():
offsetTrans, facecolors, edgecolors, linewidths, linestyles,
antialiaseds, urls, offset_position):
path, transform = path_id
transform = (Affine2D(transform.get_matrix()).translate(xo, yo)
+ Affine2D().scale(1, -1).translate(0, self.height))
transform = (Affine2D(transform.get_matrix())
.translate(xo, yo - self.height).scale(1, -1))
# rgb_fc could be a ndarray, for which equality is elementwise.
new_key = vars(gc0), tuple(rgb_fc) if rgb_fc is not None else None
if new_key == reuse_key:
Expand Down