From 55b8c7af3fbaffe1acb32eb398ff96e1825ca695 Mon Sep 17 00:00:00 2001 From: Colomban Wendling Date: Thu, 1 Nov 2012 16:38:49 +0100 Subject: [PATCH 1/4] Printing: fix text resolution Scintilla doesn't respect the context resolution, so we need to scale its draws ourselves. --- src/printing.c | 38 +++++++++++++++++++++++++++++++++++--- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/src/printing.c b/src/printing.c index 5229267f..8e91adbf 100644 --- a/src/printing.c +++ b/src/printing.c @@ -59,6 +59,7 @@ typedef struct * takes more than a second) */ time_t print_time; PangoLayout *layout; /* commonly used layout object */ + gdouble sci_scale; struct Sci_RangeToFormat fr; GArray *pages; @@ -325,6 +326,15 @@ static void setup_range(DocInfo *dinfo, GtkPrintContext *ctx) if (printing_prefs.print_page_numbers) dinfo->fr.rc.bottom -= dinfo->line_height * 1; /* footer height */ + dinfo->fr.rcPage.left /= dinfo->sci_scale; + dinfo->fr.rcPage.top /= dinfo->sci_scale; + dinfo->fr.rcPage.right /= dinfo->sci_scale; + dinfo->fr.rcPage.bottom /= dinfo->sci_scale; + dinfo->fr.rc.left /= dinfo->sci_scale; + dinfo->fr.rc.top /= dinfo->sci_scale; + dinfo->fr.rc.right /= dinfo->sci_scale; + dinfo->fr.rc.bottom /= dinfo->sci_scale; + dinfo->fr.chrg.cpMin = 0; dinfo->fr.chrg.cpMax = sci_get_length(dinfo->sci); } @@ -333,6 +343,7 @@ static void setup_range(DocInfo *dinfo, GtkPrintContext *ctx) static void begin_print(GtkPrintOperation *operation, GtkPrintContext *context, gpointer user_data) { DocInfo *dinfo = user_data; + PangoContext *pango_ctx, *widget_pango_ctx; PangoFontDescription *desc; if (dinfo == NULL) @@ -351,9 +362,17 @@ static void begin_print(GtkPrintOperation *operation, GtkPrintContext *context, scintilla_send_message(dinfo->sci, SCI_SETVIEWWS, SCWS_INVISIBLE, 0); scintilla_send_message(dinfo->sci, SCI_SETVIEWEOL, FALSE, 0); scintilla_send_message(dinfo->sci, SCI_SETEDGEMODE, EDGE_NONE, 0); - scintilla_send_message(dinfo->sci, SCI_SETPRINTMAGNIFICATION, (uptr_t) -2, 0); /* WTF? */ scintilla_send_message(dinfo->sci, SCI_SETPRINTCOLOURMODE, SC_PRINT_COLOURONWHITE, 0); + /* Scintilla doesn't respect the context resolution, so we'll scale ourselves. + * Actually Scintilla simply doesn't know about the resolution since it creates its own + * Pango context out of the Cairo target, and the resolution is in the GtkPrintOperation's + * Pango context */ + pango_ctx = gtk_print_context_create_pango_context(context); + widget_pango_ctx = gtk_widget_get_pango_context(GTK_WIDGET(dinfo->sci)); + dinfo->sci_scale = pango_cairo_context_get_resolution(pango_ctx) / pango_cairo_context_get_resolution(widget_pango_ctx); + g_object_unref(pango_ctx); + dinfo->pages = g_array_new(FALSE, FALSE, sizeof(gint)); dinfo->print_time = time(NULL); @@ -370,6 +389,19 @@ static void begin_print(GtkPrintOperation *operation, GtkPrintContext *context, } +static gint format_range(DocInfo *dinfo, gboolean draw) +{ + gint pos; + + cairo_save(dinfo->fr.hdc); + cairo_scale(dinfo->fr.hdc, dinfo->sci_scale, dinfo->sci_scale); + pos = (gint) scintilla_send_message(dinfo->sci, SCI_FORMATRANGE, draw, (sptr_t) &dinfo->fr); + cairo_restore(dinfo->fr.hdc); + + return pos; +} + + static gboolean paginate(GtkPrintOperation *operation, GtkPrintContext *context, gpointer user_data) { DocInfo *dinfo = user_data; @@ -383,7 +415,7 @@ static gboolean paginate(GtkPrintOperation *operation, GtkPrintContext *context, gtk_progress_bar_set_text(GTK_PROGRESS_BAR(main_widgets.progressbar), _("Paginating")); g_array_append_val(dinfo->pages, dinfo->fr.chrg.cpMin); - dinfo->fr.chrg.cpMin = (gint) scintilla_send_message(dinfo->sci, SCI_FORMATRANGE, FALSE, (sptr_t) &dinfo->fr); + dinfo->fr.chrg.cpMin = format_range(dinfo, FALSE); gtk_print_operation_set_n_pages(operation, dinfo->pages->len); @@ -423,7 +455,7 @@ static void draw_page(GtkPrintOperation *operation, GtkPrintContext *context, else /* it's the last page, print 'til the end */ dinfo->fr.chrg.cpMax = sci_get_length(dinfo->sci); - scintilla_send_message(dinfo->sci, SCI_FORMATRANGE, TRUE, (sptr_t) &dinfo->fr); + format_range(dinfo, TRUE); /* reset color */ cairo_set_source_rgb(cr, 0, 0, 0); From 9f32fdd1a4c54ba035c2f655bea6096c3b74fbe9 Mon Sep 17 00:00:00 2001 From: Colomban Wendling Date: Thu, 1 Nov 2012 16:41:47 +0100 Subject: [PATCH 2/4] Printing: draw the vertical separator line more accurately Use the dimensions and offsets used by Scintilla to position our separator line, since its position depends on where Scintilla drawn. Closes #3580268. --- src/printing.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/printing.c b/src/printing.c index 8e91adbf..9ba85f16 100644 --- a/src/printing.c +++ b/src/printing.c @@ -462,18 +462,17 @@ static void draw_page(GtkPrintOperation *operation, GtkPrintContext *context, if (printing_prefs.print_line_numbers) { /* print a thin line between the line number margin and the data */ - gint y1 = 0, y2 = height; + gdouble y1 = dinfo->fr.rc.top * dinfo->sci_scale; + gdouble y2 = dinfo->fr.rc.bottom * dinfo->sci_scale; + gdouble x = dinfo->fr.rc.left * dinfo->sci_scale + dinfo->margin_width; if (printing_prefs.print_page_header) - y1 += (dinfo->line_height * 3) - 2; /* "- 2": to connect the line number line to - * the page header frame */ - - if (printing_prefs.print_page_numbers) - y2 -= (dinfo->line_height * 2) - 2; + y1 -= 2 - 0.3; /* to connect the line number line to the page header frame, + * 2 is the border, and 0.3 the line width */ cairo_set_line_width(cr, 0.3); - cairo_move_to(cr, dinfo->margin_width, y1); - cairo_line_to(cr, dinfo->margin_width, y2); + cairo_move_to(cr, x, y1); + cairo_line_to(cr, x, y2); cairo_stroke(cr); } From 4423de1a7223bc85ea89d706e699d2344d8dd36a Mon Sep 17 00:00:00 2001 From: Colomban Wendling Date: Fri, 2 Nov 2012 15:22:37 +0100 Subject: [PATCH 3/4] Printing: fix improper margins when printing to a physical device We were improperly adding the printing device margins to the area where we print, leading to wider margins on physical outputs than on PDF or preview outputs (which have no hard margins), as well as wasting space and not respecting user's settings. Closes #3580269. --- src/printing.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/src/printing.c b/src/printing.c index 9ba85f16..e95f4854 100644 --- a/src/printing.c +++ b/src/printing.c @@ -309,18 +309,7 @@ static void setup_range(DocInfo *dinfo, GtkPrintContext *ctx) dinfo->fr.rc.top = dinfo->fr.rcPage.top; dinfo->fr.rc.right = dinfo->fr.rcPage.right; dinfo->fr.rc.bottom = dinfo->fr.rcPage.bottom; -#if GTK_CHECK_VERSION(2, 20, 0) - { - gdouble m_top, m_left, m_right, m_bottom; - if (gtk_print_context_get_hard_margins(ctx, &m_top, &m_bottom, &m_left, &m_right)) - { - dinfo->fr.rc.left += m_left; - dinfo->fr.rc.top += m_top; - dinfo->fr.rc.right -= m_right; - dinfo->fr.rc.bottom -= m_bottom; - } - } -#endif + if (printing_prefs.print_page_header) dinfo->fr.rc.top += dinfo->line_height * 3; /* header height */ if (printing_prefs.print_page_numbers) From 1bad1551d7ab0827c3a4d9c08783424003123122 Mon Sep 17 00:00:00 2001 From: Colomban Wendling Date: Fri, 2 Nov 2012 21:54:51 +0100 Subject: [PATCH 4/4] Scintilla: properly update the Pango contexts for the target surface This fixes drawing on a surface that has different settings (like scaling) than the display surface, by performing the measurements on a layout properly set up for the target surface. In practice, this fixes e.g. printing on a scaled surface. (Applied to Scintilla HG as 74c71632dd1afa726b0f1608d13413e0864da9b0) --- scintilla/gtk/PlatGTK.cxx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/scintilla/gtk/PlatGTK.cxx b/scintilla/gtk/PlatGTK.cxx index d98c2353..8b91f335 100644 --- a/scintilla/gtk/PlatGTK.cxx +++ b/scintilla/gtk/PlatGTK.cxx @@ -541,6 +541,8 @@ void SurfaceImpl::Init(SurfaceID sid, WindowID wid) { PLATFORM_ASSERT(wid); context = cairo_reference(reinterpret_cast(sid)); pcontext = gtk_widget_create_pango_context(PWidget(wid)); + // update the Pango context in case sid isn't the widget's surface + pango_cairo_update_context(context, pcontext); layout = pango_layout_new(pcontext); cairo_set_line_width(context, 1); createdGC = true; @@ -554,6 +556,8 @@ void SurfaceImpl::InitPixMap(int width, int height, Surface *surface_, WindowID PLATFORM_ASSERT(wid); context = cairo_reference(surfImpl->context); pcontext = gtk_widget_create_pango_context(PWidget(wid)); + // update the Pango context in case surface_ isn't the widget's surface + pango_cairo_update_context(context, pcontext); PLATFORM_ASSERT(pcontext); layout = pango_layout_new(pcontext); PLATFORM_ASSERT(layout);