mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-06 14:54:56 +01:00
basically operational switch to canvas drawing coordinates, although text and waves don't work, and redraw areas are too small
This commit is contained in:
parent
a0c5de281a
commit
77f5f4c4bf
14 changed files with 160 additions and 149 deletions
|
|
@ -65,7 +65,10 @@ Arc::render (Rect const & /*area*/, Cairo::RefPtr<Cairo::Context> context) const
|
||||||
if (_radius <= 0.0 || _arc_degrees <= 0.0) {
|
if (_radius <= 0.0 || _arc_degrees <= 0.0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
context->arc (_center.x, _center.y, _radius, _start_degrees * (M_PI/180.0), _arc_degrees * (M_PI/180.0));
|
|
||||||
|
Duple c = item_to_window (Duple (_center.x, _center.y));
|
||||||
|
|
||||||
|
context->arc (c.x, c.y, _radius, _start_degrees * (M_PI/180.0), _arc_degrees * (M_PI/180.0));
|
||||||
setup_fill_context (context);
|
setup_fill_context (context);
|
||||||
context->fill_preserve ();
|
context->fill_preserve ();
|
||||||
setup_outline_context (context);
|
setup_outline_context (context);
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,6 @@ using namespace ArdourCanvas;
|
||||||
/** Construct a new Canvas */
|
/** Construct a new Canvas */
|
||||||
Canvas::Canvas ()
|
Canvas::Canvas ()
|
||||||
: _root (this)
|
: _root (this)
|
||||||
, _log_renders (true)
|
|
||||||
, _scroll_offset_x (0)
|
, _scroll_offset_x (0)
|
||||||
, _scroll_offset_y (0)
|
, _scroll_offset_y (0)
|
||||||
{
|
{
|
||||||
|
|
@ -68,64 +67,21 @@ Canvas::render (Rect const & area, Cairo::RefPtr<Cairo::Context> const & context
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// checkpoint ("render", "-> render");
|
|
||||||
render_count = 0;
|
render_count = 0;
|
||||||
|
|
||||||
context->save ();
|
|
||||||
|
|
||||||
#ifdef CANVAS_DEBUG
|
|
||||||
if (getenv ("ARDOUR_REDRAW_CANVAS")) {
|
|
||||||
/* light up the canvas to show redraws */
|
|
||||||
context->set_source_rgba (random()%255 / 255.0,
|
|
||||||
random()%255 / 255.0,
|
|
||||||
random()%255 / 255.0,
|
|
||||||
0.3);
|
|
||||||
context->rectangle (area.x0, area.y0, area.width(), area.height());
|
|
||||||
context->fill ();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* clip to the requested area */
|
|
||||||
context->rectangle (area.x0, area.y0, area.width(), area.height());
|
|
||||||
context->clip ();
|
|
||||||
|
|
||||||
boost::optional<Rect> root_bbox = _root.bounding_box();
|
boost::optional<Rect> root_bbox = _root.bounding_box();
|
||||||
if (!root_bbox) {
|
if (!root_bbox) {
|
||||||
/* the root has no bounding box, so there's nothing to render */
|
/* the root has no bounding box, so there's nothing to render */
|
||||||
// checkpoint ("render", "no root bbox");
|
|
||||||
context->restore ();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::optional<Rect> draw = root_bbox.get().intersection (area);
|
boost::optional<Rect> draw = root_bbox->intersection (area);
|
||||||
if (draw) {
|
if (draw) {
|
||||||
/* there's a common area between the root and the requested
|
/* there's a common area between the root and the requested
|
||||||
area, so render it.
|
area, so render it.
|
||||||
*/
|
*/
|
||||||
// checkpoint ("render", "... root");
|
|
||||||
context->stroke ();
|
|
||||||
|
|
||||||
_root.render (*draw, context);
|
_root.render (*draw, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_log_renders) {
|
|
||||||
_renders.push_back (area);
|
|
||||||
}
|
|
||||||
|
|
||||||
context->restore ();
|
|
||||||
|
|
||||||
#ifdef CANVAS_DEBUG
|
|
||||||
if (getenv ("ARDOUR_HARLEQUIN_CANVAS")) {
|
|
||||||
/* light up the canvas to show redraws */
|
|
||||||
context->set_source_rgba (random()%255 / 255.0,
|
|
||||||
random()%255 / 255.0,
|
|
||||||
random()%255 / 255.0,
|
|
||||||
0.4);
|
|
||||||
context->rectangle (area.x0, area.y0, area.width(), area.height());
|
|
||||||
context->fill ();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
// checkpoint ("render", "<- render");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ostream&
|
ostream&
|
||||||
|
|
@ -502,29 +458,9 @@ GtkCanvas::item_going_away (Item* item, boost::optional<Rect> bounding_box)
|
||||||
bool
|
bool
|
||||||
GtkCanvas::on_expose_event (GdkEventExpose* ev)
|
GtkCanvas::on_expose_event (GdkEventExpose* ev)
|
||||||
{
|
{
|
||||||
|
|
||||||
Cairo::RefPtr<Cairo::Context> c = get_window()->create_cairo_context ();
|
Cairo::RefPtr<Cairo::Context> c = get_window()->create_cairo_context ();
|
||||||
|
|
||||||
/* WINDOW CANVAS
|
|
||||||
* 0,0 _scroll_offset_x, _scroll_offset_y
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* render using canvas coordinates */
|
render (Rect (ev->area.x, ev->area.y, ev->area.x + ev->area.width, ev->area.y + ev->area.height), c);
|
||||||
|
|
||||||
Rect canvas_area (ev->area.x, ev->area.y, ev->area.x + ev->area.width, ev->area.y + ev->area.height);
|
|
||||||
canvas_area = canvas_area.translate (Duple (_scroll_offset_x, _scroll_offset_y));
|
|
||||||
|
|
||||||
/* things are going to render to the cairo surface with canvas
|
|
||||||
* coordinates:
|
|
||||||
*
|
|
||||||
* an item at window/cairo 0,0 will have canvas_coords _scroll_offset_x,_scroll_offset_y
|
|
||||||
*
|
|
||||||
* let them render at their natural coordinates by using cairo_translate()
|
|
||||||
*/
|
|
||||||
|
|
||||||
c->translate (-_scroll_offset_x, -_scroll_offset_y);
|
|
||||||
|
|
||||||
render (canvas_area, c);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -79,14 +79,6 @@ public:
|
||||||
|
|
||||||
virtual Cairo::RefPtr<Cairo::Context> context () = 0;
|
virtual Cairo::RefPtr<Cairo::Context> context () = 0;
|
||||||
|
|
||||||
std::list<Rect> const & renders () const {
|
|
||||||
return _renders;
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_log_renders (bool log) {
|
|
||||||
_log_renders = log;
|
|
||||||
}
|
|
||||||
|
|
||||||
Rect canvas_to_window (Rect const&) const;
|
Rect canvas_to_window (Rect const&) const;
|
||||||
Rect window_to_canvas (Rect const&) const;
|
Rect window_to_canvas (Rect const&) const;
|
||||||
Duple canvas_to_window (Duple const&) const;
|
Duple canvas_to_window (Duple const&) const;
|
||||||
|
|
@ -117,9 +109,6 @@ protected:
|
||||||
/** our root group */
|
/** our root group */
|
||||||
RootGroup _root;
|
RootGroup _root;
|
||||||
|
|
||||||
mutable std::list<Rect> _renders;
|
|
||||||
bool _log_renders;
|
|
||||||
|
|
||||||
Coord _scroll_offset_x;
|
Coord _scroll_offset_x;
|
||||||
Coord _scroll_offset_y;
|
Coord _scroll_offset_y;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,15 @@ public:
|
||||||
virtual ~Item ();
|
virtual ~Item ();
|
||||||
|
|
||||||
/** Render this item to a Cairo context.
|
/** Render this item to a Cairo context.
|
||||||
* @param area Area to draw in this item's coordinates.
|
* @param area Area to draw, in **window** coordinates
|
||||||
|
*
|
||||||
|
* Items must convert their own coordinates into window coordinates
|
||||||
|
* because Cairo is limited to a fixed point coordinate space that
|
||||||
|
* does not extend as far as the Ardour timeline. All rendering must
|
||||||
|
* be done using coordinates that do not exceed the (rough) limits
|
||||||
|
* of the canvas' window, to avoid odd errors within Cairo as it
|
||||||
|
* converts doubles into its fixed point format and then tesselates
|
||||||
|
* the results.
|
||||||
*/
|
*/
|
||||||
virtual void render (Rect const & area, Cairo::RefPtr<Cairo::Context>) const = 0;
|
virtual void render (Rect const & area, Cairo::RefPtr<Cairo::Context>) const = 0;
|
||||||
|
|
||||||
|
|
@ -105,8 +113,13 @@ public:
|
||||||
Duple canvas_to_item (Duple const &) const;
|
Duple canvas_to_item (Duple const &) const;
|
||||||
void item_to_canvas (Coord &, Coord &) const;
|
void item_to_canvas (Coord &, Coord &) const;
|
||||||
Rect item_to_canvas (Rect const &) const;
|
Rect item_to_canvas (Rect const &) const;
|
||||||
|
Rect canvas_to_item (Rect const &) const;
|
||||||
Duple item_to_canvas (Duple const &) const;
|
Duple item_to_canvas (Duple const &) const;
|
||||||
|
|
||||||
|
Duple item_to_window (Duple const&) const;
|
||||||
|
Duple window_to_item (Duple const&) const;
|
||||||
|
Rect item_to_window (Rect const&) const;
|
||||||
|
|
||||||
void raise_to_top ();
|
void raise_to_top ();
|
||||||
void raise (int);
|
void raise (int);
|
||||||
void lower_to_bottom ();
|
void lower_to_bottom ();
|
||||||
|
|
|
||||||
|
|
@ -78,8 +78,8 @@ Group::render (Rect const & area, Cairo::RefPtr<Cairo::Context> context) const
|
||||||
|
|
||||||
#ifdef CANVAS_DEBUG
|
#ifdef CANVAS_DEBUG
|
||||||
if (DEBUG_ENABLED(PBD::DEBUG::CanvasRender)) {
|
if (DEBUG_ENABLED(PBD::DEBUG::CanvasRender)) {
|
||||||
cerr << string_compose ("%1GROUP %2 render %3 items out of %4\n",
|
cerr << string_compose ("%1GROUP %2 render %5 %3 items out of %4\n",
|
||||||
_canvas->render_indent(), (name.empty() ? string ("[unnamed]") : name), items.size(), _items.size());
|
_canvas->render_indent(), (name.empty() ? string ("[unnamed]") : name), items.size(), _items.size(), area);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -105,25 +105,18 @@ Group::render (Rect const & area, Cairo::RefPtr<Cairo::Context> context) const
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* convert the render area to our child's coordinates */
|
Rect item = (*i)->item_to_window (item_bbox.get());
|
||||||
Rect const item_area = (*i)->parent_to_item (area);
|
boost::optional<Rect> draw = item.intersection (area);
|
||||||
|
|
||||||
/* intersect the child's render area with the child's bounding box */
|
if (draw) {
|
||||||
boost::optional<Rect> r = item_bbox.get().intersection (item_area);
|
|
||||||
|
|
||||||
if (r) {
|
|
||||||
/* render the intersection */
|
|
||||||
context->save ();
|
|
||||||
context->translate ((*i)->position().x, (*i)->position().y);
|
|
||||||
#ifdef CANVAS_DEBUG
|
#ifdef CANVAS_DEBUG
|
||||||
if (DEBUG_ENABLED(PBD::DEBUG::CanvasRender)) {
|
if (DEBUG_ENABLED(PBD::DEBUG::CanvasRender)) {
|
||||||
cerr << string_compose ("%1render %2 %3\n", _canvas->render_indent(), (*i)->whatami(),
|
cerr << string_compose ("%1render %2 %3\n", _canvas->render_indent(), (*i)->whatami(),
|
||||||
(*i)->name);
|
(*i)->name);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
(*i)->render (r.get(), context);
|
(*i)->render (draw.get(), context);
|
||||||
++render_count;
|
++render_count;
|
||||||
context->restore ();
|
|
||||||
} else {
|
} else {
|
||||||
#ifdef CANVAS_DEBUG
|
#ifdef CANVAS_DEBUG
|
||||||
if (DEBUG_ENABLED(PBD::DEBUG::CanvasRender)) {
|
if (DEBUG_ENABLED(PBD::DEBUG::CanvasRender)) {
|
||||||
|
|
|
||||||
|
|
@ -43,10 +43,13 @@ Image::render (Rect const& area, Cairo::RefPtr<Cairo::Context> context) const
|
||||||
_pending->stride);
|
_pending->stride);
|
||||||
_current = _pending;
|
_current = _pending;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Rect self = item_to_window (Rect (0, 0, _width, _height));
|
||||||
|
boost::optional<Rect> draw = self.intersection (area);
|
||||||
|
|
||||||
if (_surface) {
|
if (_surface && draw) {
|
||||||
context->set_source (_surface, 0, 0);
|
context->set_source (_surface, 0, 0);
|
||||||
context->rectangle (area.x0, area.y0, area.width(), area.height());
|
context->rectangle (draw->x0, draw->y0, draw->width(), draw->height());
|
||||||
context->fill ();
|
context->fill ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -127,6 +127,20 @@ Item::canvas_to_item (ArdourCanvas::Duple const & d) const
|
||||||
return d.translate (offset);
|
return d.translate (offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ArdourCanvas::Rect
|
||||||
|
Item::canvas_to_item (ArdourCanvas::Rect const & d) const
|
||||||
|
{
|
||||||
|
Item const * i = this;
|
||||||
|
Duple offset;
|
||||||
|
|
||||||
|
while (i) {
|
||||||
|
offset = offset.translate (-(i->position()));
|
||||||
|
i = i->parent();
|
||||||
|
}
|
||||||
|
|
||||||
|
return d.translate (offset);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Item::item_to_canvas (Coord& x, Coord& y) const
|
Item::item_to_canvas (Coord& x, Coord& y) const
|
||||||
{
|
{
|
||||||
|
|
@ -145,6 +159,24 @@ Item::canvas_to_item (Coord& x, Coord& y) const
|
||||||
y = d.y;
|
y = d.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Duple
|
||||||
|
Item::item_to_window (ArdourCanvas::Duple const & d) const
|
||||||
|
{
|
||||||
|
return _canvas->canvas_to_window (item_to_canvas (d));
|
||||||
|
}
|
||||||
|
|
||||||
|
Duple
|
||||||
|
Item::window_to_item (ArdourCanvas::Duple const & d) const
|
||||||
|
{
|
||||||
|
return _canvas->window_to_canvas (canvas_to_item (d));
|
||||||
|
}
|
||||||
|
|
||||||
|
Rect
|
||||||
|
Item::item_to_window (ArdourCanvas::Rect const & r) const
|
||||||
|
{
|
||||||
|
return _canvas->canvas_to_window (item_to_canvas (r));
|
||||||
|
}
|
||||||
|
|
||||||
/** Set the position of this item in the parent's coordinates */
|
/** Set the position of this item in the parent's coordinates */
|
||||||
void
|
void
|
||||||
Item::set_position (Duple p)
|
Item::set_position (Duple p)
|
||||||
|
|
|
||||||
|
|
@ -56,8 +56,10 @@ void
|
||||||
Line::render (Rect const & /*area*/, Cairo::RefPtr<Cairo::Context> context) const
|
Line::render (Rect const & /*area*/, Cairo::RefPtr<Cairo::Context> context) const
|
||||||
{
|
{
|
||||||
setup_outline_context (context);
|
setup_outline_context (context);
|
||||||
context->move_to (_points[0].x, _points[0].y);
|
Duple p0 = item_to_window (Duple (_points[0].x, _points[0].y));
|
||||||
context->line_to (_points[1].x, _points[1].y);
|
Duple p1 = item_to_window (Duple (_points[1].x, _points[1].y));
|
||||||
|
context->move_to (p0.x, p0.y);
|
||||||
|
context->line_to (p1.x, p1.y);
|
||||||
context->stroke ();
|
context->stroke ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -73,8 +73,10 @@ LineSet::render (Rect const & area, Cairo::RefPtr<Cairo::Context> context) const
|
||||||
} else if (i->y > area.y0) {
|
} else if (i->y > area.y0) {
|
||||||
set_source_rgba (context, i->color);
|
set_source_rgba (context, i->color);
|
||||||
context->set_line_width (i->width);
|
context->set_line_width (i->width);
|
||||||
context->move_to (area.x0, i->y);
|
Duple p0 = item_to_window (Duple (area.x0, i->y));
|
||||||
context->line_to (area.x1, i->y);
|
Duple p1 = item_to_window (Duple (area.x1, i->y));
|
||||||
|
context->move_to (p0.x, p0.y);
|
||||||
|
context->line_to (p1.x, p1.y);
|
||||||
context->stroke ();
|
context->stroke ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -70,9 +70,11 @@ PolyItem::render_path (Rect const & /*area*/, Cairo::RefPtr<Cairo::Context> cont
|
||||||
bool done_first = false;
|
bool done_first = false;
|
||||||
for (Points::const_iterator i = _points.begin(); i != _points.end(); ++i) {
|
for (Points::const_iterator i = _points.begin(); i != _points.end(); ++i) {
|
||||||
if (done_first) {
|
if (done_first) {
|
||||||
context->line_to (i->x, i->y);
|
Duple c = item_to_window (Duple (i->x, i->y));
|
||||||
|
context->line_to (c.x, c.y);
|
||||||
} else {
|
} else {
|
||||||
context->move_to (i->x, i->y);
|
Duple c = item_to_window (Duple (i->x, i->y));
|
||||||
|
context->move_to (c.x, c.y);
|
||||||
done_first = true;
|
done_first = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -95,15 +97,18 @@ PolyItem::render_curve (Rect const & area, Cairo::RefPtr<Cairo::Context> context
|
||||||
|
|
||||||
if (done_first) {
|
if (done_first) {
|
||||||
|
|
||||||
context->curve_to (cp1->x, cp1->y,
|
Duple c1 = item_to_window (Duple (cp1->x, cp1->y));
|
||||||
cp2->x, cp2->y,
|
Duple c2 = item_to_window (Duple (cp2->x, cp2->y));
|
||||||
i->x, i->y);
|
Duple c3 = item_to_window (Duple (i->x, i->y));
|
||||||
|
|
||||||
|
context->curve_to (c1.x, c1.y, c2.x, c2.y, c3.x, c3.y);
|
||||||
|
|
||||||
cp1++;
|
cp1++;
|
||||||
cp2++;
|
cp2++;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
Duple c = item_to_window (Duple (i->x, i->y));
|
||||||
context->move_to (i->x, i->y);
|
context->move_to (i->x, i->y);
|
||||||
done_first = true;
|
done_first = true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,9 @@ Polygon::render (Rect const & area, Cairo::RefPtr<Cairo::Context> context) const
|
||||||
render_path (area, context);
|
render_path (area, context);
|
||||||
|
|
||||||
if (!_points.empty ()) {
|
if (!_points.empty ()) {
|
||||||
context->move_to (_points.front().x, _points.front().y);
|
/* close path */
|
||||||
|
Duple p = item_to_window (Duple (_points.front().x, _points.front().y));
|
||||||
|
context->move_to (p.x, p.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
context->stroke_preserve ();
|
context->stroke_preserve ();
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,7 @@ Rectangle::Rectangle (Group* parent, Rect const & rect)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Rectangle::render (Rect const & /*area*/, Cairo::RefPtr<Cairo::Context> context) const
|
Rectangle::render (Rect const & area, Cairo::RefPtr<Cairo::Context> context) const
|
||||||
{
|
{
|
||||||
/* Cairo goes a little (!) wrong when asked to fill/stroke rectangles that
|
/* Cairo goes a little (!) wrong when asked to fill/stroke rectangles that
|
||||||
* extend way beyond the surface boundaries. To avoid this issue,
|
* extend way beyond the surface boundaries. To avoid this issue,
|
||||||
|
|
@ -58,17 +58,13 @@ Rectangle::render (Rect const & /*area*/, Cairo::RefPtr<Cairo::Context> context)
|
||||||
* canvas, converting to item-space coordinates, of course.
|
* canvas, converting to item-space coordinates, of course.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Rect plot = _rect;
|
Rect self = item_to_window (_rect);
|
||||||
Rect visible = _canvas->visible_area();
|
boost::optional<Rect> draw = self.intersection (area);
|
||||||
Duple visible_end = canvas_to_item (Duple (visible.x1, visible.y1));
|
|
||||||
|
|
||||||
plot.x1 = min (plot.x1, visible_end.x);
|
if (_fill && draw) {
|
||||||
plot.y1 = min (plot.y1, visible_end.y);
|
|
||||||
|
|
||||||
if (_fill) {
|
|
||||||
setup_fill_context (context);
|
setup_fill_context (context);
|
||||||
cerr << "Fill rect: " << plot << endl;
|
|
||||||
context->rectangle (plot.x0, plot.y0, plot.width(), plot.height());
|
context->rectangle (draw->x0, draw->y0, draw->width(), draw->height());
|
||||||
|
|
||||||
if (!_outline) {
|
if (!_outline) {
|
||||||
context->fill ();
|
context->fill ();
|
||||||
|
|
@ -100,30 +96,30 @@ Rectangle::render (Rect const & /*area*/, Cairo::RefPtr<Cairo::Context> context)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (!_fill) {
|
if (!_fill) {
|
||||||
context->rectangle (plot.x0, plot.y0, plot.width(), plot.height());
|
context->rectangle (draw->x0, draw->y0, draw->width(), draw->height());
|
||||||
context->stroke ();
|
context->stroke ();
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
if (_outline_what & LEFT) {
|
if (_outline_what & LEFT) {
|
||||||
context->move_to (plot.x0, plot.y0);
|
context->move_to (draw->x0, draw->y0);
|
||||||
context->line_to (plot.x0, plot.y1);
|
context->line_to (draw->x0, draw->y1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_outline_what & BOTTOM) {
|
if (_outline_what & BOTTOM) {
|
||||||
context->move_to (plot.x0, plot.y1);
|
context->move_to (draw->x0, draw->y1);
|
||||||
context->line_to (plot.x1, plot.y1);
|
context->line_to (draw->x1, draw->y1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_outline_what & RIGHT) {
|
if (_outline_what & RIGHT) {
|
||||||
context->move_to (plot.x1, plot.y0);
|
context->move_to (draw->x1, draw->y0);
|
||||||
context->line_to (plot.x1, plot.y1);
|
context->line_to (draw->x1, draw->y1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_outline_what & TOP) {
|
if (_outline_what & TOP) {
|
||||||
context->move_to (plot.x0, plot.y0);
|
context->move_to (draw->x0, draw->y0);
|
||||||
context->line_to (plot.x1, plot.y0);
|
context->line_to (draw->x1, draw->y0);
|
||||||
}
|
}
|
||||||
|
|
||||||
context->stroke ();
|
context->stroke ();
|
||||||
|
|
|
||||||
|
|
@ -96,6 +96,8 @@ Text::redraw (Cairo::RefPtr<Cairo::Context> context) const
|
||||||
* ::render
|
* ::render
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
cerr << "rendered \"" << layout->get_text() << "\" into image\n";
|
||||||
|
|
||||||
_need_redraw = false;
|
_need_redraw = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -136,7 +138,7 @@ Text::compute_bounding_box () const
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Text::render (Rect const & /*area*/, Cairo::RefPtr<Cairo::Context> context) const
|
Text::render (Rect const & area, Cairo::RefPtr<Cairo::Context> context) const
|
||||||
{
|
{
|
||||||
if (_text.empty()) {
|
if (_text.empty()) {
|
||||||
return;
|
return;
|
||||||
|
|
@ -146,8 +148,12 @@ Text::render (Rect const & /*area*/, Cairo::RefPtr<Cairo::Context> context) cons
|
||||||
redraw (context);
|
redraw (context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Rect self = item_to_window (Rect (0, 0, min (_clamped_width, _width), _height));
|
||||||
|
cerr << "Draw \"" << _text << "\" @ " << self.x0 << ", " << self.y0 << ' ' << self.width() << " x " << self.height() << endl;
|
||||||
|
context->rectangle (self.x0, self.y0, self.width(), self.height());
|
||||||
context->set_source (_image, 0, 0);
|
context->set_source (_image, 0, 0);
|
||||||
context->rectangle (0, 0, min (_clamped_width, _width), _height);
|
//context->set_source_rgb (0.3, 0.4, 0.02);
|
||||||
context->fill ();
|
context->fill ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -133,13 +133,13 @@ WaveView::set_samples_per_pixel (double samples_per_pixel)
|
||||||
static inline double
|
static inline double
|
||||||
to_src_sample_offset (frameoffset_t src_sample_start, double pixel_offset, double spp)
|
to_src_sample_offset (frameoffset_t src_sample_start, double pixel_offset, double spp)
|
||||||
{
|
{
|
||||||
return src_sample_start + (pixel_offset * spp);
|
return llrintf (src_sample_start + (pixel_offset * spp));
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline double
|
static inline double
|
||||||
to_pixel_offset (frameoffset_t src_sample_start, double sample_offset, double spp)
|
to_pixel_offset (frameoffset_t src_sample_start, double sample_offset, double spp)
|
||||||
{
|
{
|
||||||
return (sample_offset - src_sample_start) / spp;
|
return llrintf ((sample_offset - src_sample_start) / spp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -151,32 +151,43 @@ WaveView::render (Rect const & area, Cairo::RefPtr<Cairo::Context> context) cons
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* These are all pixel (integer) coordinates from the left hand edge of
|
Rect self = item_to_window (Rect (0.0, 0.0, _region->length() / _samples_per_pixel, _height));
|
||||||
* the waveview.
|
boost::optional<Rect> draw = self.intersection (area);
|
||||||
*/
|
|
||||||
|
context->rectangle (self.x0, self.y0, self.width(), self.height());
|
||||||
double start = area.x0;
|
context->set_source_rgb (1.0, 0.0, 0.0);
|
||||||
double const end = area.x1;
|
context->stroke ();
|
||||||
double const rend = _region->length() / _samples_per_pixel;
|
|
||||||
|
if (!draw) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* pixel coordinates */
|
||||||
|
|
||||||
|
double start = draw->x0;
|
||||||
|
double const end = draw->x1;
|
||||||
|
|
||||||
list<CacheEntry*>::iterator cache = _cache.begin ();
|
list<CacheEntry*>::iterator cache = _cache.begin ();
|
||||||
#if 0
|
|
||||||
cerr << name << " cache contains " << _cache.size() << endl;
|
cerr << name << " draw " << area << "self = " << self << "\n\twill use " << draw.get() << endl;
|
||||||
|
#if 1
|
||||||
|
cerr << " Cache contains " << _cache.size() << endl;
|
||||||
while (cache != _cache.end()) {
|
while (cache != _cache.end()) {
|
||||||
cerr << "\tsamples " << (*cache)->start() << " .. " << (*cache)->end()
|
cerr << "\tsample span " << (*cache)->start() << " .. " << (*cache)->end()
|
||||||
<< " pixels "
|
<< " pixel span "
|
||||||
<< to_pixel_offset (_region_start, (*cache)->start(), _samples_per_pixel)
|
<< to_pixel_offset (_region_start, (*cache)->start(), _samples_per_pixel)
|
||||||
<< " .. "
|
<< " .. "
|
||||||
<< to_pixel_offset (_region_start, (*cache)->end(), _samples_per_pixel)
|
<< to_pixel_offset (_region_start, (*cache)->end(), _samples_per_pixel)
|
||||||
<< endl;
|
<< endl;
|
||||||
++cache;
|
++cache;
|
||||||
}
|
}
|
||||||
|
|
||||||
cache = _cache.begin();
|
cache = _cache.begin();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
while ((end - start) > 1.0) {
|
while ((end - start) > 1.0) {
|
||||||
|
|
||||||
|
cerr << "***** RANGE = " << start << " .. " << end << " = " << end - start << endl;
|
||||||
|
|
||||||
frameoffset_t start_sample_offset = to_src_sample_offset (_region_start, start, _samples_per_pixel);
|
frameoffset_t start_sample_offset = to_src_sample_offset (_region_start, start, _samples_per_pixel);
|
||||||
|
|
||||||
/* Step through cache entries that end at or before our current position */
|
/* Step through cache entries that end at or before our current position */
|
||||||
|
|
@ -197,6 +208,8 @@ WaveView::render (Rect const & area, Cairo::RefPtr<Cairo::Context> context) cons
|
||||||
|
|
||||||
if (cache == _cache.end ()) {
|
if (cache == _cache.end ()) {
|
||||||
|
|
||||||
|
cerr << "Nothing in cache spans\n";
|
||||||
|
|
||||||
/* Case 1: we have run out of cache entries, so make a new one for
|
/* Case 1: we have run out of cache entries, so make a new one for
|
||||||
the whole required area and put it in the list.
|
the whole required area and put it in the list.
|
||||||
|
|
||||||
|
|
@ -209,7 +222,12 @@ WaveView::render (Rect const & area, Cairo::RefPtr<Cairo::Context> context) cons
|
||||||
the region actually is, so clamp with that too.
|
the region actually is, so clamp with that too.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
double const rend = _region->length() / _samples_per_pixel;
|
||||||
double const endpoint = min (rend, max (end, start + _canvas->visible_area().width()));
|
double const endpoint = min (rend, max (end, start + _canvas->visible_area().width()));
|
||||||
|
|
||||||
|
cerr << "New cache entry for " << start_sample_offset << " .. " << to_src_sample_offset (_region_start, endpoint, _samples_per_pixel)
|
||||||
|
<< endl;
|
||||||
|
|
||||||
CacheEntry* c = new CacheEntry (this,
|
CacheEntry* c = new CacheEntry (this,
|
||||||
start_sample_offset,
|
start_sample_offset,
|
||||||
to_src_sample_offset (_region_start, endpoint, _samples_per_pixel),
|
to_src_sample_offset (_region_start, endpoint, _samples_per_pixel),
|
||||||
|
|
@ -228,20 +246,24 @@ WaveView::render (Rect const & area, Cairo::RefPtr<Cairo::Context> context) cons
|
||||||
* or the end of the render area, whichever comes first.
|
* or the end of the render area, whichever comes first.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
double end_pixel = min (rend, end);
|
double end_pixel;
|
||||||
double end_sample_offset = to_src_sample_offset (_region_start, end_pixel, _samples_per_pixel);
|
double end_sample_offset;
|
||||||
int npeaks;
|
int npeaks;
|
||||||
|
|
||||||
if (end_sample_offset < (*cache)->start()) {
|
if (end_sample_offset < (*cache)->start()) {
|
||||||
npeaks = end_pixel - start;
|
double const rend = _region->length() / _samples_per_pixel;
|
||||||
assert (npeaks > 0);
|
end_sample_offset = to_src_sample_offset (_region_start, end_pixel, _samples_per_pixel);
|
||||||
|
end_pixel = min (rend, end);
|
||||||
} else {
|
} else {
|
||||||
end_sample_offset = (*cache)->start();
|
end_sample_offset = (*cache)->start();
|
||||||
end_pixel = to_pixel_offset (_region_start, end_sample_offset, _samples_per_pixel);
|
end_pixel = to_pixel_offset (_region_start, end_sample_offset, _samples_per_pixel);
|
||||||
npeaks = end_pixel - npeaks;
|
|
||||||
assert (npeaks > 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
npeaks = end_pixel - start;
|
||||||
|
assert (npeaks > 0);
|
||||||
|
|
||||||
|
cerr << "New fill-in cache entry for " << start_sample_offset << " .. " << end_sample_offset << endl;
|
||||||
|
|
||||||
CacheEntry* c = new CacheEntry (this,
|
CacheEntry* c = new CacheEntry (this,
|
||||||
start_sample_offset,
|
start_sample_offset,
|
||||||
end_sample_offset,
|
end_sample_offset,
|
||||||
|
|
@ -257,14 +279,18 @@ WaveView::render (Rect const & area, Cairo::RefPtr<Cairo::Context> context) cons
|
||||||
we have left, so render it.
|
we have left, so render it.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
cerr << "found suitable cache entry\n";
|
||||||
|
|
||||||
image = *cache;
|
image = *cache;
|
||||||
++cache;
|
++cache;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
double this_end = min (end, to_pixel_offset (_region_start, image->end (), _samples_per_pixel));
|
double this_end = min (end, to_pixel_offset (_region_start, image->end (), _samples_per_pixel));
|
||||||
double const image_origin = to_pixel_offset (_region_start, image->start(), _samples_per_pixel);
|
double const image_origin = to_pixel_offset (_region_start, image->start(), _samples_per_pixel);
|
||||||
#if 0
|
#if 1
|
||||||
cerr << "\t\tDraw image between "
|
cerr << "\t\tDraw image between "
|
||||||
<< start
|
<< start
|
||||||
<< " .. "
|
<< " .. "
|
||||||
|
|
@ -280,8 +306,11 @@ WaveView::render (Rect const & area, Cairo::RefPtr<Cairo::Context> context) cons
|
||||||
<< endl;
|
<< endl;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
context->rectangle (start, area.y0, this_end - start, area.height());
|
cerr << "Fill rect " << draw->x0 << ", " << self.y0 << ' ' << draw->width() << " x " << draw->height() << endl;
|
||||||
context->set_source (image->image(), image_origin, 0);
|
|
||||||
|
context->rectangle (start, draw->y0, this_end - start, _height);
|
||||||
|
// context->set_source (image->image(), image_origin, self.y0 - draw->y0);
|
||||||
|
context->set_source_rgb (0.0, 0.0, 1.0);
|
||||||
context->fill ();
|
context->fill ();
|
||||||
|
|
||||||
start = this_end;
|
start = this_end;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue