diff options
| author | Tavmjong Bah <tavmjong@free.fr> | 2017-11-30 10:33:32 +0000 |
|---|---|---|
| committer | Tavmjong Bah <tavmjong@free.fr> | 2017-11-30 10:33:32 +0000 |
| commit | 21530cc5cfd6af290cc70be53dedad8c26d71ab9 (patch) | |
| tree | cc87380cb6d9945e781b0ff58fb86aa1e94e80fc /src | |
| parent | Adapt control shapes for hi DPI displays. (diff) | |
| download | inkscape-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.cpp | 22 | ||||
| -rw-r--r-- | src/display/sodipodi-ctrl.cpp | 16 | ||||
| -rw-r--r-- | src/display/sp-canvas.cpp | 47 | ||||
| -rw-r--r-- | src/display/sp-canvas.h | 3 |
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) |
