Skip to content

Commit

Permalink
Add a draw_shape_at_points method to the canvas (celiagg#79)
Browse files Browse the repository at this point in the history
  • Loading branch information
jwiggins authored Feb 25, 2021
1 parent 5048a74 commit 622ea38
Show file tree
Hide file tree
Showing 5 changed files with 122 additions and 0 deletions.
6 changes: 6 additions & 0 deletions celiagg/_ndarray_canvas.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,12 @@ cdef extern from "ndarray_canvas.h":
const _transform.trans_affine& transform,
_paint.Paint& linePaint, _paint.Paint& fillPaint,
const _graphics_state.GraphicsState& gs)
void draw_shape_at_points(_vertex_source.VertexSource& shape,
const double* points,
const size_t point_count,
const _transform.trans_affine& transform,
_paint.Paint& linePaint, _paint.Paint& fillPaint,
const _graphics_state.GraphicsState& gs)
void draw_text(const char* text, _font.Font& font,
const _transform.trans_affine& transform,
_paint.Paint& linePaint, _paint.Paint& fillPaint,
Expand Down
12 changes: 12 additions & 0 deletions celiagg/ndarray_canvas.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,12 @@ class ndarray_canvas_base
const agg::trans_affine& transform,
Paint& linePaint, Paint& fillPaint,
const GraphicsState& gs) = 0;
virtual void draw_shape_at_points(VertexSource& shape,
const double* points,
const size_t point_count,
const agg::trans_affine& transform,
Paint& linePaint, Paint& fillPaint,
const GraphicsState& gs) = 0;
virtual void draw_text(const char* text, Font& font,
const agg::trans_affine& transform,
Paint& linePaint, Paint& fillPaint,
Expand Down Expand Up @@ -108,6 +114,12 @@ class ndarray_canvas : public ndarray_canvas_base
const agg::trans_affine& transform,
Paint& linePaint, Paint& fillPaint,
const GraphicsState& gs);
void draw_shape_at_points(VertexSource& shape,
const double* points,
const size_t point_count,
const agg::trans_affine& transform,
Paint& linePaint, Paint& fillPaint,
const GraphicsState& gs);
void draw_text(const char* text, Font& font,
const agg::trans_affine& transform,
Paint& linePaint, Paint& fillPaint,
Expand Down
37 changes: 37 additions & 0 deletions celiagg/ndarray_canvas.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,43 @@ void ndarray_canvas<pixfmt_t>::draw_shape(VertexSource& shape,
}
}

template<typename pixfmt_t>
void ndarray_canvas<pixfmt_t>::draw_shape_at_points(VertexSource& shape,
const double* points, const size_t point_count,
const agg::trans_affine& transform, Paint& linePaint, Paint& fillPaint,
const GraphicsState& gs)
{
agg::simple_polygon_vertex_source _points(points, point_count, false, false);
agg::trans_affine pt_trans;
unsigned cmd;

_set_clipping(gs.clip_box());
linePaint.master_alpha(gs.master_alpha());
fillPaint.master_alpha(gs.master_alpha());

if (gs.stencil() == NULL)
{
for (;;)
{
cmd = _points.vertex(&pt_trans.tx, &pt_trans.ty);
if (cmd == agg::path_cmd_end_poly) break;

_draw_shape_internal(shape, pt_trans * transform, linePaint, fillPaint, gs, m_renderer);
}
}
else
{
_WITH_MASKED_RENDERER(gs, renderer)
for (;;)
{
cmd = _points.vertex(&pt_trans.tx, &pt_trans.ty);
if (cmd == agg::path_cmd_end_poly) break;

_draw_shape_internal(shape, pt_trans * transform, linePaint, fillPaint, gs, renderer);
}
}
}

template<typename pixfmt_t>
void ndarray_canvas<pixfmt_t>::draw_text(const char* text,
Font& font, const agg::trans_affine& transform,
Expand Down
51 changes: 51 additions & 0 deletions celiagg/ndarray_canvas.pxi
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,57 @@ cdef class CanvasBase:
dereference(fill_paint._this),
dereference(gs._this))

def draw_shape_at_points(self, shape, points, transform, state, stroke=None, fill=None):
"""draw_shape_at_points(shape, points, transform, state, stroke=SolidColor(0, 0, 0), fill=SolidColor(0, 0, 0))
Draw a shape at multiple points on the canvas.
.. note::
Use ``GraphicsState.drawing_mode`` to enable/disable stroke or fill
drawing.
:param shape: A ``VertexSource`` object
:param points: A sequence of (x, y) pairs where the ``shape`` should be drawn.
:param transform: A ``Transform`` object
:param state: A ``GraphicsState`` object
:param stroke: The ``Paint`` to use for outlines. Defaults to black.
:param fill: The ``Paint`` to use for fills. Defaults to black.
"""
if not isinstance(shape, VertexSource):
raise TypeError("shape must be a VertexSource (Path, BSpline, etc)")
if not isinstance(transform, Transform):
raise TypeError("transform must be a Transform instance")
if not isinstance(state, GraphicsState):
raise TypeError("state must be a GraphicsState instance")
if stroke is not None and not isinstance(stroke, Paint):
raise TypeError("stroke must be a Paint instance")
if fill is not None and not isinstance(fill, Paint):
raise TypeError("fill must be a Paint instance")

cdef:
VertexSource shp = <VertexSource>shape
double[:,::1] _points = numpy.asarray(points, dtype=numpy.float64,
order='c')
GraphicsState gs = <GraphicsState>state
Transform trans = <Transform>transform
PixelFormat fmt = self.pixel_format
Paint stroke_paint
Paint fill_paint

if _points.shape[1] != 2:
msg = 'Points argument must be an iterable of (x, y) pairs.'
raise ValueError(msg)

self._check_stencil(gs)
stroke_paint = self._get_native_paint(stroke, fmt)
fill_paint = self._get_native_paint(fill, fmt)

self._this.draw_shape_at_points(dereference(shp._this),
&_points[0][0], _points.shape[0],
dereference(trans._this),
dereference(stroke_paint._this),
dereference(fill_paint._this),
dereference(gs._this))

def draw_text(self, text, font, transform, state, stroke=None, fill=None):
"""draw_text(text, font, transform, state, stroke=SolidColor(0, 0, 0), fill=SolidColor(0, 0, 0))
Draw a line of text on the canvas.
Expand Down
16 changes: 16 additions & 0 deletions celiagg/tests/test_drawing.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,3 +132,19 @@ def test_ellipse(self):
path, self.transform, self.state, stroke=self.paint
)
assert_equal(expected, self.canvas.array)

def test_draw_shape_at_points(self):
path = agg.Path()
path.ellipse(0, 0, 0.5, 0.5)
points = [(0.0, 0.0), (0.0, 5.0), (5.0, 0.0), (5.0, 5.0), (2.5, 2.5)]
expected = [
[1, 0, 0, 0, 1],
[0, 0, 0, 0, 0],
[0, 0, 1, 0, 0],
[0, 0, 0, 0, 0],
[1, 0, 0, 0, 1],
]
self.canvas.draw_shape_at_points(
path, points, self.transform, self.state, stroke=self.paint
)
assert_equal(expected, self.canvas.array)

0 comments on commit 622ea38

Please sign in to comment.