summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorTavmjong Bah <tavmjong@free.fr>2017-11-30 10:33:32 +0000
committerTavmjong Bah <tavmjong@free.fr>2017-11-30 10:33:32 +0000
commit21530cc5cfd6af290cc70be53dedad8c26d71ab9 (patch)
treecc87380cb6d9945e781b0ff58fb86aa1e94e80fc /src
parentAdapt control shapes for hi DPI displays. (diff)
downloadinkscape-21530cc5cfd6af290cc70be53dedad8c26d71ab9.tar.gz
inkscape-21530cc5cfd6af290cc70be53dedad8c26d71ab9.zip
Store device-scale and propogate value where necessary.
Avoids reliance on cairo_surface_get_device_scale. Also necessary for filters.
Diffstat (limited to 'src')
-rw-r--r--src/display/cairo-utils.cpp22
-rw-r--r--src/display/sodipodi-ctrl.cpp16
-rw-r--r--src/display/sp-canvas.cpp47
-rw-r--r--src/display/sp-canvas.h3
4 files changed, 54 insertions, 34 deletions
diff --git a/src/display/cairo-utils.cpp b/src/display/cairo-utils.cpp
index 8045007e7..aeda3f379 100644
--- a/src/display/cairo-utils.cpp
+++ b/src/display/cairo-utils.cpp
@@ -842,8 +842,19 @@ ink_cairo_surface_create_identical(cairo_surface_t *s)
cairo_surface_t *
ink_cairo_surface_create_same_size(cairo_surface_t *s, cairo_content_t c)
{
- cairo_surface_t *ns = cairo_surface_create_similar(s, c,
- ink_cairo_surface_get_width(s), ink_cairo_surface_get_height(s));
+ // ink_cairo_surface_get_width()/height() returns value in pixels
+ // cairo_surface_create_similar() uses device units
+ double x_scale = 0;
+ double y_scale = 0;
+ cairo_surface_get_device_scale( s, &x_scale, &y_scale );
+
+ assert (x_scale > 0);
+ assert (y_scale > 0);
+
+ cairo_surface_t *ns =
+ cairo_surface_create_similar(s, c,
+ ink_cairo_surface_get_width(s)/x_scale,
+ ink_cairo_surface_get_height(s)/y_scale);
return ns;
}
@@ -908,6 +919,9 @@ ink_cairo_surface_blit(cairo_surface_t *src, cairo_surface_t *dest)
}
}
+/**
+ * Return width in pixels.
+ */
int
ink_cairo_surface_get_width(cairo_surface_t *surface)
{
@@ -916,6 +930,10 @@ ink_cairo_surface_get_width(cairo_surface_t *surface)
assert(cairo_surface_get_type(surface) == CAIRO_SURFACE_TYPE_IMAGE);
return cairo_image_surface_get_width(surface);
}
+
+/**
+ * Return height in pixels.
+ */
int
ink_cairo_surface_get_height(cairo_surface_t *surface)
{
diff --git a/src/display/sodipodi-ctrl.cpp b/src/display/sodipodi-ctrl.cpp
index fdb079446..0c346eccf 100644
--- a/src/display/sodipodi-ctrl.cpp
+++ b/src/display/sodipodi-ctrl.cpp
@@ -583,20 +583,14 @@ sp_ctrl_render (SPCanvasItem *item, SPCanvasBuf *buf)
if (!ctrl->defined) return;
if ((!ctrl->filled) && (!ctrl->stroked)) return;
- // Find device scale of source surface.
- double x_scale = 0;
- double y_scale = 0;
- cairo_surface_get_device_scale(cairo_get_target(buf->ct), &x_scale, &y_scale);
- int device_scale = x_scale;
-
// the control-image is rendered into ctrl->cache
if (!ctrl->build) {
- sp_ctrl_build_cache (ctrl, device_scale);
+ sp_ctrl_build_cache (ctrl, buf->device_scale);
}
// Must match width/height sp_ctrl_build_cache.
- int w = (ctrl->width * 2 + 1) * device_scale;
- int h = (ctrl->height * 2 + 1) * device_scale;
+ int w = (ctrl->width * 2 + 1) * buf->device_scale;
+ int h = (ctrl->height * 2 + 1) * buf->device_scale;
// The code below works even when the target is not an image surface
if (ctrl->mode == SP_CTRL_MODE_XOR) {
@@ -605,7 +599,7 @@ sp_ctrl_render (SPCanvasItem *item, SPCanvasBuf *buf)
// Size in device pixels. Does not set device scale.
cairo_surface_t *work = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, w, h);
- cairo_surface_set_device_scale(work, device_scale, device_scale);
+ cairo_surface_set_device_scale(work, buf->device_scale, buf->device_scale);
cairo_t *cr = cairo_create(work);
cairo_translate(cr, -ctrl->box.left(), -ctrl->box.top());
@@ -644,7 +638,7 @@ sp_ctrl_render (SPCanvasItem *item, SPCanvasBuf *buf)
cairo_save(buf->ct);
cairo_set_source_surface(buf->ct, work,
ctrl->box.left() - buf->rect.left(), ctrl->box.top() - buf->rect.top());
- cairo_rectangle(buf->ct, ctrl->box.left() - buf->rect.left(), ctrl->box.top() - buf->rect.top(), w/device_scale, h/device_scale);
+ cairo_rectangle(buf->ct, ctrl->box.left() - buf->rect.left(), ctrl->box.top() - buf->rect.top(), w/buf->device_scale, h/buf->device_scale);
cairo_clip(buf->ct);
cairo_set_operator(buf->ct, CAIRO_OPERATOR_SOURCE);
cairo_paint(buf->ct);
diff --git a/src/display/sp-canvas.cpp b/src/display/sp-canvas.cpp
index 9fdc61a5e..20ad27bf5 100644
--- a/src/display/sp-canvas.cpp
+++ b/src/display/sp-canvas.cpp
@@ -1129,7 +1129,7 @@ void SPCanvas::handle_size_allocate(GtkWidget *widget, GtkAllocation *allocation
gtk_widget_get_allocation(widget, &old_allocation);
// For HiDPI monitors.
- int device_scale = gtk_widget_get_scale_factor( widget );
+ canvas->_device_scale = gtk_widget_get_scale_factor( widget );
Geom::IntRect new_area = Geom::IntRect::from_xywh(canvas->_x0, canvas->_y0,
allocation->width, allocation->height);
@@ -1143,8 +1143,8 @@ void SPCanvas::handle_size_allocate(GtkWidget *widget, GtkAllocation *allocation
new_backing_store =
cairo_surface_create_similar_image(canvas->_surface_for_similar,
CAIRO_FORMAT_ARGB32,
- allocation->width * device_scale,
- allocation->height * device_scale);
+ allocation->width * canvas->_device_scale,
+ allocation->height * canvas->_device_scale);
}
#endif
if (new_backing_store == NULL) {
@@ -1152,12 +1152,12 @@ void SPCanvas::handle_size_allocate(GtkWidget *widget, GtkAllocation *allocation
// Size in device pixels. Does not set device scale.
new_backing_store =
cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
- allocation->width * device_scale,
- allocation->height * device_scale);
+ allocation->width * canvas->_device_scale,
+ allocation->height * canvas->_device_scale);
}
// Set device scale
- cairo_surface_set_device_scale(new_backing_store, device_scale, device_scale);
+ cairo_surface_set_device_scale(new_backing_store, canvas->_device_scale, canvas->_device_scale);
if (canvas->_backing_store) {
cairo_t *cr = cairo_create(new_backing_store);
@@ -1546,6 +1546,7 @@ void SPCanvas::paintSingleBuffer(Geom::IntRect const &paint_rect, Geom::IntRect
buf.buf_rowstride = 0;
buf.rect = paint_rect;
buf.canvas_rect = canvas_rect;
+ buf.device_scale = _device_scale;
buf.is_empty = true;
// Make sure the following code does not go outside of _backing_store's data
@@ -1562,21 +1563,24 @@ void SPCanvas::paintSingleBuffer(Geom::IntRect const &paint_rect, Geom::IntRect
unsigned char *data = cairo_image_surface_get_data(_backing_store);
int stride = cairo_image_surface_get_stride(_backing_store);
+ // Check we are using correct device scale
double x_scale = 0;
double y_scale = 0;
cairo_surface_get_device_scale(_backing_store, &x_scale, &y_scale);
- if (x_scale != y_scale) {
- std::cerr << "SPCanvas::paintSingleBuffer(): non-uniform device scale!" << std::endl;
- }
+ assert (_device_scale == (int)x_scale);
+ assert (_device_scale == (int)y_scale);
// Move to the right row
data += stride * (paint_rect.top() - _y0) * (int)y_scale;
// Move to the right pixel inside of that row
data += 4 * (paint_rect.left() - _x0) * (int)x_scale;
- cairo_surface_t *imgs = cairo_image_surface_create_for_data(data, CAIRO_FORMAT_ARGB32,
- paint_rect.width() * x_scale, paint_rect.height() * y_scale, stride);
+ cairo_surface_t *imgs =
+ cairo_image_surface_create_for_data(data, CAIRO_FORMAT_ARGB32,
+ paint_rect.width() * _device_scale,
+ paint_rect.height() * _device_scale,
+ stride);
+ cairo_surface_set_device_scale(imgs, _device_scale, _device_scale);
- cairo_surface_set_device_scale(imgs, x_scale, y_scale);
buf.ct = cairo_create(imgs);
cairo_save(buf.ct);
@@ -1829,12 +1833,12 @@ gboolean SPCanvas::handle_draw(GtkWidget *widget, cairo_t *cr) {
canvas->_surface_for_similar =
cairo_surface_create_similar(cairo_get_target(cr), CAIRO_CONTENT_COLOR_ALPHA, 1, 1);
+ // Check we are using correct device scale
double x_scale = 0;
double y_scale = 0;
cairo_surface_get_device_scale(canvas->_backing_store, &x_scale, &y_scale);
- if (x_scale != y_scale) {
- std::cerr << "SPCanvas::handle_draw(): non-uniform device scale!" << std::endl;
- }
+ assert (canvas->_device_scale == (int)x_scale);
+ assert (canvas->_device_scale == (int)y_scale);
// Reallocate backing store so that cairo can use shared memory
// Function does NOT copy device scale! Width and height are in device pixels.
@@ -1843,7 +1847,7 @@ gboolean SPCanvas::handle_draw(GtkWidget *widget, cairo_t *cr) {
cairo_image_surface_get_width(canvas->_backing_store),
cairo_image_surface_get_height(canvas->_backing_store));
- cairo_surface_set_device_scale(new_backing_store, x_scale, y_scale);
+ cairo_surface_set_device_scale(new_backing_store, canvas->_device_scale, canvas->_device_scale);
// Copy the old backing store contents
cairo_t *cr = cairo_create(new_backing_store);
@@ -2029,6 +2033,7 @@ void SPCanvas::scrollTo( Geom::Point const &c, unsigned int clear, bool is_scrol
// For HiDPI monitors
int device_scale = gtk_widget_get_scale_factor(GTK_WIDGET(this));
+ assert( device_scale == _device_scale);
double cx = c[Geom::X];
double cy = c[Geom::Y];
@@ -2055,19 +2060,19 @@ void SPCanvas::scrollTo( Geom::Point const &c, unsigned int clear, bool is_scrol
new_backing_store =
cairo_surface_create_similar_image(_surface_for_similar,
CAIRO_FORMAT_ARGB32,
- allocation.width * device_scale,
- allocation.height * device_scale);
+ allocation.width * _device_scale,
+ allocation.height * _device_scale);
#endif
if (new_backing_store == NULL)
// Size in device pixels. Does not set device scale.
new_backing_store =
cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
- allocation.width * device_scale,
- allocation.height * device_scale);
+ allocation.width * _device_scale,
+ allocation.height * _device_scale);
// Set device scale
- cairo_surface_set_device_scale(new_backing_store, device_scale, device_scale);
+ cairo_surface_set_device_scale(new_backing_store, _device_scale, _device_scale);
cairo_t *cr = cairo_create(new_backing_store);
cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
diff --git a/src/display/sp-canvas.h b/src/display/sp-canvas.h
index 92a50da11..d30e0a485 100644
--- a/src/display/sp-canvas.h
+++ b/src/display/sp-canvas.h
@@ -55,6 +55,7 @@ struct SPCanvasBuf {
unsigned char *buf;
int buf_rowstride;
+ int device_scale; // For high DPI monitors.
bool is_empty;
};
@@ -177,6 +178,8 @@ public:
int _x0; ///< World coordinate of the leftmost pixels of window
int _y0; ///< World coordinate of the topmost pixels of window
+ int _device_scale; ///< Scale for high DPI montiors
+
/// Image surface storing the contents of the widget
cairo_surface_t *_backing_store;
#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 12, 0)