fix clamping of line and rect coordinates to avoid issues with cairo when drawing way outside a surface's dimensions; move various coordinate methods down to Canvas, because they don't require GTK information; make visible_area() a Canvas virtual method so that we don't have to cast to call it
This commit is contained in:
parent
96eee9e7a1
commit
d1a05240ef
|
@ -107,31 +107,37 @@ Editor::initialize_canvas ()
|
|||
|
||||
meter_bar_group = new ArdourCanvas::Group (_time_bars_canvas->root ());
|
||||
meter_bar = new ArdourCanvas::Rectangle (meter_bar_group, ArdourCanvas::Rect (0.0, 0.0, ArdourCanvas::COORD_MAX, timebar_height - 1));
|
||||
CANVAS_DEBUG_NAME (meter_bar, "meter Bar");
|
||||
meter_bar->set_outline_width (1);
|
||||
meter_bar->set_outline_what (0x8);
|
||||
|
||||
tempo_bar_group = new ArdourCanvas::Group (_time_bars_canvas->root ());
|
||||
tempo_bar = new ArdourCanvas::Rectangle (tempo_bar_group, ArdourCanvas::Rect (0.0, 0.0, ArdourCanvas::COORD_MAX, timebar_height - 1));
|
||||
CANVAS_DEBUG_NAME (tempo_bar, "Tempo Bar");
|
||||
tempo_bar->set_outline_width (1);
|
||||
tempo_bar->set_outline_what (0x8);
|
||||
|
||||
range_marker_bar_group = new ArdourCanvas::Group (_time_bars_canvas->root ());
|
||||
range_marker_bar = new ArdourCanvas::Rectangle (range_marker_bar_group, ArdourCanvas::Rect (0.0, 0.0, ArdourCanvas::COORD_MAX, timebar_height - 1));
|
||||
CANVAS_DEBUG_NAME (range_marker_bar, "Range Marker Bar");
|
||||
range_marker_bar->set_outline_width (1);
|
||||
range_marker_bar->set_outline_what (0x8);
|
||||
|
||||
transport_marker_bar_group = new ArdourCanvas::Group (_time_bars_canvas->root ());
|
||||
transport_marker_bar = new ArdourCanvas::Rectangle (transport_marker_bar_group, ArdourCanvas::Rect (0.0, 0.0, ArdourCanvas::COORD_MAX, timebar_height - 1));
|
||||
CANVAS_DEBUG_NAME (transport_marker_bar, "transport Marker Bar");
|
||||
transport_marker_bar->set_outline_width (1);
|
||||
transport_marker_bar->set_outline_what (0x8);
|
||||
|
||||
marker_bar_group = new ArdourCanvas::Group (_time_bars_canvas->root ());
|
||||
marker_bar = new ArdourCanvas::Rectangle (marker_bar_group, ArdourCanvas::Rect (0.0, 0.0, ArdourCanvas::COORD_MAX, timebar_height - 1));
|
||||
CANVAS_DEBUG_NAME (marker_bar, "Marker Bar");
|
||||
marker_bar->set_outline_width (1);
|
||||
marker_bar->set_outline_what (0x8);
|
||||
|
||||
cd_marker_bar_group = new ArdourCanvas::Group (_time_bars_canvas->root ());
|
||||
cd_marker_bar = new ArdourCanvas::Rectangle (cd_marker_bar_group, ArdourCanvas::Rect (0.0, 0.0, ArdourCanvas::COORD_MAX, timebar_height - 1));
|
||||
CANVAS_DEBUG_NAME (cd_marker_bar, "CD Marker Bar");
|
||||
cd_marker_bar->set_outline_width (1);
|
||||
cd_marker_bar->set_outline_what (0x8);
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include <cmath>
|
||||
|
||||
#include "canvas/canvas.h"
|
||||
#include "canvas/debug.h"
|
||||
|
||||
#include "utils.h"
|
||||
#include "editor_cursors.h"
|
||||
|
@ -36,6 +37,9 @@ EditorCursor::EditorCursor (Editor& ed, bool (Editor::*callbck)(GdkEvent*,Ardour
|
|||
, _track_canvas_item (_editor._track_canvas->root ())
|
||||
, _length (1.0)
|
||||
{
|
||||
CANVAS_DEBUG_NAME ((&_time_bars_canvas_item), "timebars editor cursor");
|
||||
CANVAS_DEBUG_NAME ((&_track_canvas_item), "track canvas editor cursor");
|
||||
|
||||
_time_bars_canvas_item.set_outline_width (1);
|
||||
_track_canvas_item.set_outline_width (1);
|
||||
|
||||
|
|
|
@ -1444,7 +1444,7 @@ Editor::update_punch_range_view (bool visibility)
|
|||
Location* tpl;
|
||||
|
||||
if ((_session->config.get_punch_in() || _session->config.get_punch_out()) && ((tpl = transport_punch_location()) != 0)) {
|
||||
ArdourCanvas::Rect const v = _track_canvas_viewport->visible_area ();
|
||||
ArdourCanvas::Rect const v = _track_canvas->visible_area ();
|
||||
if (_session->config.get_punch_in()) {
|
||||
transport_punch_range_rect->set_x0 (sample_to_pixel (tpl->start()));
|
||||
transport_punch_range_rect->set_x1 (_session->config.get_punch_out() ? sample_to_pixel (tpl->end()) : sample_to_pixel (JACK_MAX_FRAMES));
|
||||
|
|
|
@ -1343,7 +1343,7 @@ Editor::button_press_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemTyp
|
|||
pointer_window = canvas_window->get_pointer (x, y, mask);
|
||||
|
||||
if (pointer_window == _track_canvas->get_window()) {
|
||||
_track_canvas_viewport->window_to_canvas (x, y, wx, wy);
|
||||
_track_canvas->window_to_canvas (x, y, wx, wy);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2942,5 +2942,5 @@ Editor::get_pointer_position (double& x, double& y) const
|
|||
{
|
||||
int px, py;
|
||||
_track_canvas->get_pointer (px, py);
|
||||
_track_canvas_viewport->window_to_canvas (px, py, x, y);
|
||||
_track_canvas->window_to_canvas (px, py, x, y);
|
||||
}
|
||||
|
|
|
@ -1335,8 +1335,8 @@ Editor::clamp_samples_per_pixel (double& fpp) const
|
|||
{
|
||||
bool clamped = false;
|
||||
|
||||
if (fpp < 2.0) {
|
||||
fpp = 2.0;
|
||||
if (fpp < 1.0) {
|
||||
fpp = 1.0;
|
||||
clamped = true;
|
||||
}
|
||||
|
||||
|
|
|
@ -191,7 +191,7 @@ Editor::draw_measures (ARDOUR::TempoMap::BBTPointList::const_iterator& begin,
|
|||
}
|
||||
|
||||
if (tempo_lines == 0) {
|
||||
tempo_lines = new TempoLines (*_track_canvas_viewport, time_line_group, physical_screen_height(get_window()));
|
||||
tempo_lines = new TempoLines (*_track_canvas, time_line_group, physical_screen_height(get_window()));
|
||||
}
|
||||
|
||||
tempo_lines->draw (begin, end, samples_per_pixel);
|
||||
|
|
|
@ -27,8 +27,8 @@ using namespace std;
|
|||
|
||||
#define MAX_CACHED_LINES 128
|
||||
|
||||
TempoLines::TempoLines (ArdourCanvas::GtkCanvasViewport& canvas_viewport, ArdourCanvas::Group* group, double screen_height)
|
||||
: _canvas_viewport (canvas_viewport)
|
||||
TempoLines::TempoLines (ArdourCanvas::Canvas& canvas, ArdourCanvas::Group* group, double screen_height)
|
||||
: _canvas (canvas)
|
||||
, _group(group)
|
||||
, _clean_left(DBL_MAX)
|
||||
, _clean_right(0.0)
|
||||
|
@ -88,7 +88,7 @@ TempoLines::draw (const ARDOUR::TempoMap::BBTPointList::const_iterator& begin,
|
|||
|
||||
const size_t needed = distance (begin, end);
|
||||
|
||||
ArdourCanvas::Rect const visible = _canvas_viewport.visible_area ();
|
||||
ArdourCanvas::Rect const visible = _canvas.visible_area ();
|
||||
|
||||
/* get the first bar spacing */
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ typedef boost::fast_pool_allocator<
|
|||
|
||||
class TempoLines {
|
||||
public:
|
||||
TempoLines(ArdourCanvas::GtkCanvasViewport& canvas, ArdourCanvas::Group* group, double screen_height);
|
||||
TempoLines(ArdourCanvas::Canvas& canvas, ArdourCanvas::Group* group, double screen_height);
|
||||
|
||||
void tempo_map_changed();
|
||||
|
||||
|
@ -48,7 +48,7 @@ private:
|
|||
typedef std::map<double, ArdourCanvas::Line*, std::less<double>, MapAllocator> Lines;
|
||||
Lines _lines;
|
||||
|
||||
ArdourCanvas::GtkCanvasViewport& _canvas_viewport;
|
||||
ArdourCanvas::Canvas& _canvas;
|
||||
ArdourCanvas::Group* _group;
|
||||
double _clean_left;
|
||||
double _clean_right;
|
||||
|
|
|
@ -780,9 +780,6 @@ TimeAxisView::set_samples_per_pixel (double fpp)
|
|||
for (Children::iterator i = children.begin(); i != children.end(); ++i) {
|
||||
(*i)->set_samples_per_pixel (fpp);
|
||||
}
|
||||
|
||||
AnalysisFeatureList::const_iterator i;
|
||||
list<ArdourCanvas::Line*>::iterator l;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -849,7 +849,6 @@ TimeAxisViewItem::set_samples_per_pixel (double fpp)
|
|||
void
|
||||
TimeAxisViewItem::reset_width_dependent_items (double pixel_width)
|
||||
{
|
||||
|
||||
if (pixel_width < 2.0) {
|
||||
|
||||
if (show_vestigial) {
|
||||
|
|
|
@ -198,6 +198,30 @@ Canvas::item_changed (Item* item, boost::optional<Rect> pre_change_bounding_box)
|
|||
}
|
||||
}
|
||||
|
||||
Duple
|
||||
Canvas::window_to_canvas (Duple const & d) const
|
||||
{
|
||||
return d.translate (Duple (_scroll_offset_x, _scroll_offset_y));
|
||||
}
|
||||
|
||||
Duple
|
||||
Canvas::canvas_to_window (Duple const & d) const
|
||||
{
|
||||
return d.translate (Duple (-_scroll_offset_x, -_scroll_offset_y));
|
||||
}
|
||||
|
||||
Rect
|
||||
Canvas::window_to_canvas (Rect const & r) const
|
||||
{
|
||||
return r.translate (Duple (_scroll_offset_x, _scroll_offset_y));
|
||||
}
|
||||
|
||||
Rect
|
||||
Canvas::canvas_to_window (Rect const & r) const
|
||||
{
|
||||
return r.translate (Duple (-_scroll_offset_x, -_scroll_offset_y));
|
||||
}
|
||||
|
||||
/** Called when an item has moved.
|
||||
* @param item Item that has moved.
|
||||
* @param pre_change_parent_bounding_box The bounding box of the item before
|
||||
|
@ -553,6 +577,15 @@ GtkCanvas::ungrab ()
|
|||
_grabbed_item = 0;
|
||||
}
|
||||
|
||||
/** @return The visible area of the canvas, in canvas coordinates */
|
||||
Rect
|
||||
GtkCanvas::visible_area () const
|
||||
{
|
||||
Distance const xo = _scroll_offset_x;
|
||||
Distance const yo = _scroll_offset_y;
|
||||
return Rect (xo, yo, xo + get_allocation().get_width (), yo + get_allocation().get_height ());
|
||||
}
|
||||
|
||||
/** Create a GtkCanvaSViewport.
|
||||
* @param hadj Adjustment to use for horizontal scrolling.
|
||||
* @param vadj Adjustment to use for vertica scrolling.
|
||||
|
@ -575,30 +608,6 @@ GtkCanvasViewport::scrolled ()
|
|||
queue_draw ();
|
||||
}
|
||||
|
||||
Duple
|
||||
GtkCanvas::window_to_canvas (Duple const & d) const
|
||||
{
|
||||
return d.translate (Duple (_scroll_offset_x, _scroll_offset_y));
|
||||
}
|
||||
|
||||
Duple
|
||||
GtkCanvas::canvas_to_window (Duple const & d) const
|
||||
{
|
||||
return d.translate (Duple (-_scroll_offset_x, -_scroll_offset_y));
|
||||
}
|
||||
|
||||
Rect
|
||||
GtkCanvas::window_to_canvas (Rect const & r) const
|
||||
{
|
||||
return r.translate (Duple (_scroll_offset_x, _scroll_offset_y));
|
||||
}
|
||||
|
||||
Rect
|
||||
GtkCanvas::canvas_to_window (Rect const & r) const
|
||||
{
|
||||
return r.translate (Duple (-_scroll_offset_x, -_scroll_offset_y));
|
||||
}
|
||||
|
||||
/** Handler for when GTK asks us what minimum size we want.
|
||||
* @param req Requsition to fill in.
|
||||
*/
|
||||
|
@ -612,26 +621,3 @@ GtkCanvasViewport::on_size_request (Gtk::Requisition* req)
|
|||
req->height = 16;
|
||||
}
|
||||
|
||||
/** Convert window coordinates to canvas coordinates by taking into account
|
||||
* where we are scrolled to.
|
||||
* @param wx Window x.
|
||||
* @param wy Window y.
|
||||
* @param cx Filled in with canvas x.
|
||||
* @param cy Filled in with canvas y.
|
||||
*/
|
||||
void
|
||||
GtkCanvasViewport::window_to_canvas (int wx, int wy, Coord& cx, Coord& cy) const
|
||||
{
|
||||
Duple d = _canvas.window_to_canvas (Duple (wx, wy));
|
||||
cx = d.x;
|
||||
cy = d.y;
|
||||
}
|
||||
|
||||
/** @return The visible area of the canvas, in canvas coordinates */
|
||||
Rect
|
||||
GtkCanvasViewport::visible_area () const
|
||||
{
|
||||
Distance const xo = hadjustment.get_value ();
|
||||
Distance const yo = vadjustment.get_value ();
|
||||
return Rect (xo, yo, xo + get_allocation().get_width (), yo + get_allocation().get_height ());
|
||||
}
|
||||
|
|
|
@ -87,7 +87,25 @@ public:
|
|||
_log_renders = log;
|
||||
}
|
||||
|
||||
Rect canvas_to_window (Rect const&) const;
|
||||
Rect window_to_canvas (Rect const&) const;
|
||||
Duple canvas_to_window (Duple const&) const;
|
||||
Duple window_to_canvas (Duple const&) const;
|
||||
|
||||
void canvas_to_window (Coord cx, Coord cy, Coord& wx, Coord& wy) {
|
||||
Duple d = canvas_to_window (Duple (cx, cy));
|
||||
wx = d.x;
|
||||
wy = d.y;
|
||||
}
|
||||
|
||||
void window_to_canvas (Coord wx, Coord wy, Coord& cx, Coord& cy) {
|
||||
Duple d = window_to_canvas (Duple (wx, wy));
|
||||
cx = d.x;
|
||||
cy = d.y;
|
||||
}
|
||||
|
||||
void scroll_to (Coord x, Coord y);
|
||||
virtual Rect visible_area () const = 0;
|
||||
|
||||
std::string indent() const;
|
||||
std::string render_indent() const;
|
||||
|
@ -119,11 +137,7 @@ public:
|
|||
|
||||
Cairo::RefPtr<Cairo::Context> context ();
|
||||
|
||||
Rect canvas_to_window (Rect const&) const;
|
||||
Rect window_to_canvas (Rect const&) const;
|
||||
|
||||
Duple canvas_to_window (Duple const&) const;
|
||||
Duple window_to_canvas (Duple const&) const;
|
||||
Rect visible_area () const;
|
||||
|
||||
protected:
|
||||
bool on_expose_event (GdkEventExpose *);
|
||||
|
@ -162,9 +176,6 @@ public:
|
|||
return &_canvas;
|
||||
}
|
||||
|
||||
void window_to_canvas (int, int, Coord &, Coord &) const;
|
||||
Rect visible_area () const;
|
||||
|
||||
protected:
|
||||
void on_size_request (Gtk::Requisition *);
|
||||
|
||||
|
|
|
@ -56,6 +56,7 @@ struct Duple
|
|||
|
||||
extern Duple operator- (Duple const &);
|
||||
extern Duple operator+ (Duple const &, Duple const &);
|
||||
extern bool operator== (Duple const &, Duple const &);
|
||||
extern Duple operator- (Duple const &, Duple const &);
|
||||
extern Duple operator/ (Duple const &, double);
|
||||
extern std::ostream & operator<< (std::ostream &, Duple const &);
|
||||
|
|
|
@ -370,7 +370,7 @@ Item::dump (ostream& o) const
|
|||
{
|
||||
boost::optional<ArdourCanvas::Rect> bb = bounding_box();
|
||||
|
||||
o << _canvas->indent() << whatami() << ' ' << this;
|
||||
o << _canvas->indent() << whatami() << ' ' << this << " Visible ? " << _visible;
|
||||
o << " @ " << position();
|
||||
|
||||
#ifdef CANVAS_DEBUG
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "canvas/types.h"
|
||||
#include "canvas/debug.h"
|
||||
#include "canvas/utils.h"
|
||||
#include "canvas/canvas.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace ArdourCanvas;
|
||||
|
@ -55,14 +56,8 @@ void
|
|||
Line::render (Rect const & /*area*/, Cairo::RefPtr<Cairo::Context> context) const
|
||||
{
|
||||
setup_outline_context (context);
|
||||
|
||||
Duple plot[2] = {
|
||||
Duple (min (_points[0].x, CAIRO_MAX), min (_points[0].y, CAIRO_MAX)),
|
||||
Duple (min (_points[1].x, CAIRO_MAX), min (_points[1].y, CAIRO_MAX))
|
||||
};
|
||||
|
||||
context->move_to (plot[0].x, plot[0].y);
|
||||
context->line_to (plot[1].x, plot[1].y);
|
||||
context->move_to (_points[0].x, _points[0].y);
|
||||
context->line_to (_points[1].x, _points[1].y);
|
||||
context->stroke ();
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
#include <cairomm/context.h>
|
||||
#include "pbd/stacktrace.h"
|
||||
#include "pbd/compose.h"
|
||||
|
||||
#include "canvas/canvas.h"
|
||||
#include "canvas/rectangle.h"
|
||||
#include "canvas/debug.h"
|
||||
#include "canvas/utils.h"
|
||||
|
@ -50,10 +52,18 @@ Rectangle::Rectangle (Group* parent, Rect const & rect)
|
|||
void
|
||||
Rectangle::render (Rect const & /*area*/, Cairo::RefPtr<Cairo::Context> context) const
|
||||
{
|
||||
Rect plot = _rect;
|
||||
/* Cairo goes a little (!) wrong when asked to fill/stroke rectangles that
|
||||
* extend way beyond the surface boundaries. To avoid this issue,
|
||||
* clamp what we are drawing using the absolute end of the visible
|
||||
* canvas, converting to item-space coordinates, of course.
|
||||
*/
|
||||
|
||||
plot.x1 = min (plot.x1, CAIRO_MAX);
|
||||
plot.y1 = min (plot.y1, CAIRO_MAX);
|
||||
Rect plot = _rect;
|
||||
Rect visible = _canvas->visible_area();
|
||||
Duple visible_end = canvas_to_item (Duple (visible.x1, visible.y1));
|
||||
|
||||
plot.x1 = min (plot.x1, visible_end.x);
|
||||
plot.y1 = min (plot.y1, visible_end.y);
|
||||
|
||||
if (_fill) {
|
||||
setup_fill_context (context);
|
||||
|
|
|
@ -25,9 +25,7 @@
|
|||
using namespace std;
|
||||
using namespace ArdourCanvas;
|
||||
|
||||
Coord const ArdourCanvas::COORD_MAX = DBL_MAX;
|
||||
/* XXX: empirically arrived at */
|
||||
Coord const ArdourCanvas::CAIRO_MAX = 65536;
|
||||
Coord const ArdourCanvas::COORD_MAX = 1.7e307;
|
||||
|
||||
static inline Coord
|
||||
safe_add (Coord a, Coord b)
|
||||
|
@ -132,6 +130,12 @@ ArdourCanvas::operator+ (Duple const & a, Duple const & b)
|
|||
return Duple (safe_add (a.x, b.x), safe_add (a.y, b.y));
|
||||
}
|
||||
|
||||
bool
|
||||
ArdourCanvas::operator== (Duple const & a, Duple const & b)
|
||||
{
|
||||
return a.x == b.x && a.y == b.y;
|
||||
}
|
||||
|
||||
Duple
|
||||
ArdourCanvas::operator- (Duple const & a, Duple const & b)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue
Block a user