From 2a88723a40e594fed66956decddfb35e5513ee08 Mon Sep 17 00:00:00 2001 From: Michael Natterer Date: Fri, 19 Jun 2009 17:08:34 +0200 Subject: [PATCH] Bug 573256 - Text tool appearance doesn't account for DPI * app/text/gimptextlayout-render.c: remove private function which creates the transform matrix. * app/text/gimptextlayout.[ch]: add it here as public API. Also add function which transform and untransform PangoRectangles, points and distances using the transform matrix. * app/tools/gimptexttool.c: convert coordinates using above new transform functions when drawing selection and cursor, and when processing mouse events. --- app/text/gimptextlayout-render.c | 28 +---- app/text/gimptextlayout.c | 177 +++++++++++++++++++++++++++++++ app/text/gimptextlayout.h | 49 ++++++--- app/tools/gimptexttool.c | 40 +++++-- 4 files changed, 244 insertions(+), 50 deletions(-) diff --git a/app/text/gimptextlayout-render.c b/app/text/gimptextlayout-render.c index 8a9cf2809b..aa7241de4f 100644 --- a/app/text/gimptextlayout-render.c +++ b/app/text/gimptextlayout-render.c @@ -32,10 +32,6 @@ #include "gimptextlayout-render.h" -static void gimp_text_layout_render_trafo (GimpTextLayout *layout, - cairo_matrix_t *trafo); - - void gimp_text_layout_render (GimpTextLayout *layout, cairo_t *cr, @@ -79,7 +75,7 @@ gimp_text_layout_render (GimpTextLayout *layout, cairo_translate (cr, x, y); - gimp_text_layout_render_trafo (layout, &trafo); + gimp_text_layout_get_transform (layout, &trafo); cairo_transform (cr, &trafo); if (path) @@ -87,25 +83,3 @@ gimp_text_layout_render (GimpTextLayout *layout, else pango_cairo_show_layout (cr, pango_layout); } - - -static void -gimp_text_layout_render_trafo (GimpTextLayout *layout, - cairo_matrix_t *trafo) -{ - GimpText *text = gimp_text_layout_get_text (layout); - gdouble xres; - gdouble yres; - gdouble norm; - - gimp_text_layout_get_resolution (layout, &xres, &yres); - - norm = 1.0 / yres * xres; - - trafo->xx = text->transformation.coeff[0][0] * norm; - trafo->xy = text->transformation.coeff[0][1] * 1.0; - trafo->yx = text->transformation.coeff[1][0] * norm; - trafo->yy = text->transformation.coeff[1][1] * 1.0; - trafo->x0 = 0; - trafo->y0 = 0; -} diff --git a/app/text/gimptextlayout.c b/app/text/gimptextlayout.c index 24c96f958d..e0e7a2ee51 100644 --- a/app/text/gimptextlayout.c +++ b/app/text/gimptextlayout.c @@ -289,6 +289,183 @@ gimp_text_layout_get_pango_layout (GimpTextLayout *layout) return layout->layout; } +void +gimp_text_layout_get_transform (GimpTextLayout *layout, + cairo_matrix_t *matrix) +{ + GimpText *text; + gdouble xres; + gdouble yres; + gdouble norm; + + g_return_if_fail (GIMP_IS_TEXT_LAYOUT (layout)); + g_return_if_fail (matrix != NULL); + + text = gimp_text_layout_get_text (layout); + + gimp_text_layout_get_resolution (layout, &xres, &yres); + + norm = 1.0 / yres * xres; + + matrix->xx = text->transformation.coeff[0][0] * norm; + matrix->xy = text->transformation.coeff[0][1] * 1.0; + matrix->yx = text->transformation.coeff[1][0] * norm; + matrix->yy = text->transformation.coeff[1][1] * 1.0; + matrix->x0 = 0; + matrix->y0 = 0; +} + +void +gimp_text_layout_transform_rect (GimpTextLayout *layout, + PangoRectangle *rect) +{ + cairo_matrix_t matrix; + gdouble x, y; + gdouble width, height; + + g_return_if_fail (GIMP_IS_TEXT_LAYOUT (layout)); + g_return_if_fail (rect != NULL); + + x = rect->x; + y = rect->y; + width = rect->width; + height = rect->height; + + gimp_text_layout_get_transform (layout, &matrix); + + cairo_matrix_transform_point (&matrix, &x, &y); + cairo_matrix_transform_distance (&matrix, &width, &height); + + rect->x = ROUND (x); + rect->y = ROUND (y); + rect->width = ROUND (width); + rect->height = ROUND (height); +} + +void +gimp_text_layout_transform_point (GimpTextLayout *layout, + gdouble *x, + gdouble *y) +{ + cairo_matrix_t matrix; + gdouble _x = 0.0; + gdouble _y = 0.0; + + g_return_if_fail (GIMP_IS_TEXT_LAYOUT (layout)); + + if (x) _x = *x; + if (y) _y = *y; + + gimp_text_layout_get_transform (layout, &matrix); + + cairo_matrix_transform_point (&matrix, &_x, &_y); + + if (x) *x = _x; + if (y) *y = _y; +} + +void +gimp_text_layout_transform_distance (GimpTextLayout *layout, + gdouble *x, + gdouble *y) +{ + cairo_matrix_t matrix; + gdouble _x = 0.0; + gdouble _y = 0.0; + + g_return_if_fail (GIMP_IS_TEXT_LAYOUT (layout)); + + if (x) _x = *x; + if (y) _y = *y; + + gimp_text_layout_get_transform (layout, &matrix); + + cairo_matrix_transform_distance (&matrix, &_x, &_y); + + if (x) *x = _x; + if (y) *y = _y; +} + +void +gimp_text_layout_untransform_rect (GimpTextLayout *layout, + PangoRectangle *rect) +{ + cairo_matrix_t matrix; + gdouble x, y; + gdouble width, height; + + g_return_if_fail (GIMP_IS_TEXT_LAYOUT (layout)); + g_return_if_fail (rect != NULL); + + x = rect->x; + y = rect->y; + width = rect->width; + height = rect->height; + + gimp_text_layout_get_transform (layout, &matrix); + + if (cairo_matrix_invert (&matrix) == CAIRO_STATUS_SUCCESS) + { + cairo_matrix_transform_point (&matrix, &x, &y); + cairo_matrix_transform_distance (&matrix, &width, &height); + + rect->x = ROUND (x); + rect->y = ROUND (y); + rect->width = ROUND (width); + rect->height = ROUND (height); + } +} + +void +gimp_text_layout_untransform_point (GimpTextLayout *layout, + gdouble *x, + gdouble *y) +{ + cairo_matrix_t matrix; + gdouble _x = 0.0; + gdouble _y = 0.0; + + g_return_if_fail (GIMP_IS_TEXT_LAYOUT (layout)); + + if (x) _x = *x; + if (y) _y = *y; + + gimp_text_layout_get_transform (layout, &matrix); + + if (cairo_matrix_invert (&matrix) == CAIRO_STATUS_SUCCESS) + { + cairo_matrix_transform_point (&matrix, &_x, &_y); + + if (x) *x = _x; + if (y) *y = _y; + } +} + +void +gimp_text_layout_untransform_distance (GimpTextLayout *layout, + gdouble *x, + gdouble *y) +{ + cairo_matrix_t matrix; + gdouble _x = 0.0; + gdouble _y = 0.0; + + g_return_if_fail (GIMP_IS_TEXT_LAYOUT (layout)); + + if (x) _x = *x; + if (y) _y = *y; + + gimp_text_layout_get_transform (layout, &matrix); + + if (cairo_matrix_invert (&matrix) == CAIRO_STATUS_SUCCESS) + { + cairo_matrix_transform_distance (&matrix, &_x, &_y); + + if (x) *x = _x; + if (y) *y = _y; + } +} + static void gimp_text_layout_position (GimpTextLayout *layout) { diff --git a/app/text/gimptextlayout.h b/app/text/gimptextlayout.h index c27a063da1..c562ca86ac 100644 --- a/app/text/gimptextlayout.h +++ b/app/text/gimptextlayout.h @@ -35,22 +35,43 @@ struct _GimpTextLayoutClass }; -GType gimp_text_layout_get_type (void) G_GNUC_CONST; +GType gimp_text_layout_get_type (void) G_GNUC_CONST; -GimpTextLayout * gimp_text_layout_new (GimpText *text, - GimpImage *image); -gboolean gimp_text_layout_get_size (GimpTextLayout *layout, - gint *width, - gint *heigth); -void gimp_text_layout_get_offsets (GimpTextLayout *layout, - gint *x, - gint *y); -void gimp_text_layout_get_resolution (GimpTextLayout *layout, - gdouble *xres, - gdouble *yres); +GimpTextLayout * gimp_text_layout_new (GimpText *text, + GimpImage *image); +gboolean gimp_text_layout_get_size (GimpTextLayout *layout, + gint *width, + gint *heigth); +void gimp_text_layout_get_offsets (GimpTextLayout *layout, + gint *x, + gint *y); +void gimp_text_layout_get_resolution (GimpTextLayout *layout, + gdouble *xres, + gdouble *yres); -GimpText * gimp_text_layout_get_text (GimpTextLayout *layout); -PangoLayout * gimp_text_layout_get_pango_layout (GimpTextLayout *layout); +GimpText * gimp_text_layout_get_text (GimpTextLayout *layout); +PangoLayout * gimp_text_layout_get_pango_layout (GimpTextLayout *layout); + +void gimp_text_layout_get_transform (GimpTextLayout *layout, + cairo_matrix_t *matrix); + +void gimp_text_layout_transform_rect (GimpTextLayout *layout, + PangoRectangle *rect); +void gimp_text_layout_transform_point (GimpTextLayout *layout, + gdouble *x, + gdouble *y); +void gimp_text_layout_transform_distance (GimpTextLayout *layout, + gdouble *x, + gdouble *y); + +void gimp_text_layout_untransform_rect (GimpTextLayout *layout, + PangoRectangle *rect); +void gimp_text_layout_untransform_point (GimpTextLayout *layout, + gdouble *x, + gdouble *y); +void gimp_text_layout_untransform_distance (GimpTextLayout *layout, + gdouble *x, + gdouble *y); #endif /* __GIMP_TEXT_LAYOUT_H__ */ diff --git a/app/tools/gimptexttool.c b/app/tools/gimptexttool.c index 1cbd68ff1e..614ec75c82 100644 --- a/app/tools/gimptexttool.c +++ b/app/tools/gimptexttool.c @@ -1069,6 +1069,7 @@ gimp_text_tool_draw (GimpDrawTool *draw_tool) layout = gimp_text_layout_get_pango_layout (text_tool->layout); pango_layout_get_pixel_extents (layout, &ink_extents, &logical_extents); + gimp_text_layout_transform_rect (text_tool->layout, &logical_extents); if (ink_extents.x < 0) logical_off_x = -ink_extents.x; @@ -1103,6 +1104,7 @@ gimp_text_tool_draw (GimpDrawTool *draw_tool) g_free (string); pango_layout_index_to_pos (layout, cursorx, &crect); + gimp_text_layout_transform_rect (text_tool->layout, &crect); crect.x = PANGO_PIXELS (crect.x) + logical_off_x; crect.y = PANGO_PIXELS (crect.y) + logical_off_y; @@ -1157,14 +1159,21 @@ gimp_text_tool_draw_preedit (GimpDrawTool *draw_tool, do { - gint firstline, lastline; - gint first_x, last_x; + gint firstline, lastline; + gint first_x, last_x; + gdouble first_tmp, last_tmp; pango_layout_index_to_line_x (layout, min, 0, &firstline, &first_x); - pango_layout_index_to_line_x (layout, max, 0, &lastline, &last_x); + pango_layout_index_to_line_x (layout, max, 0, &lastline, &last_x); - first_x = PANGO_PIXELS (first_x) + logical_off_x; - last_x = PANGO_PIXELS (last_x) + logical_off_x; + first_tmp = first_x; + last_tmp = last_x; + + gimp_text_layout_transform_distance (text_tool->layout, &first_tmp, NULL); + gimp_text_layout_transform_distance (text_tool->layout, &last_tmp, NULL); + + first_x = PANGO_PIXELS (first_tmp) + logical_off_x; + last_x = PANGO_PIXELS (last_tmp) + logical_off_x; if (i >= firstline && i <= lastline) { @@ -1173,6 +1182,8 @@ gimp_text_tool_draw_preedit (GimpDrawTool *draw_tool, pango_layout_iter_get_line_extents (line_iter, NULL, &crect); pango_extents_to_pixels (&crect, NULL); + gimp_text_layout_transform_rect (text_tool->layout, &crect); + crect.x += logical_off_x; crect.y += logical_off_y; @@ -1256,14 +1267,21 @@ gimp_text_tool_draw_selection (GimpDrawTool *draw_tool, */ do { - gint firstline, lastline; - gint first_x, last_x; + gint firstline, lastline; + gint first_x, last_x; + gdouble first_tmp, last_tmp; pango_layout_index_to_line_x (layout, min, 0, &firstline, &first_x); pango_layout_index_to_line_x (layout, max, 0, &lastline, &last_x); - first_x = PANGO_PIXELS (first_x) + logical_off_x; - last_x = PANGO_PIXELS (last_x) + logical_off_x; + first_tmp = first_x; + last_tmp = last_x; + + gimp_text_layout_transform_distance (text_tool->layout, &first_tmp, NULL); + gimp_text_layout_transform_distance (text_tool->layout, &last_tmp, NULL); + + first_x = PANGO_PIXELS (first_tmp) + logical_off_x; + last_x = PANGO_PIXELS (last_tmp) + logical_off_x; if (i >= firstline && i <= lastline) { @@ -1272,6 +1290,8 @@ gimp_text_tool_draw_selection (GimpDrawTool *draw_tool, pango_layout_iter_get_line_extents (line_iter, NULL, &crect); pango_extents_to_pixels (&crect, NULL); + gimp_text_layout_transform_rect (text_tool->layout, &crect); + crect.x += logical_off_x; crect.y += logical_off_y; @@ -2238,6 +2258,8 @@ gimp_text_tool_xy_to_offset (GimpTextTool *text_tool, gint offset; gint trailing; + gimp_text_layout_untransform_point (text_tool->layout, &x, &y); + /* adjust to offset of logical rect */ layout = gimp_text_layout_get_pango_layout (text_tool->layout); pango_layout_get_pixel_extents (layout, &ink_extents, NULL);