Le 02/11/2012 15:49, Roger Booth a écrit :
> On 11/02/2012 06:59 AM, Colomban Wendling wrote:
>> Le 02/11/2012 01:12, Roger Booth a écrit :
>>> I found a new problem just now. I changed the font size from 10 to 12.
>>> Text that is tab-aligned on the screen, and tab-aligned in Print Preview
>>> when the font size is 10 is no longer tab-aligned in Print Preview when
>>> the font size is 12.
>> I'm unable to reproduce this, could you provide a small sample showing
>> the issue?  Though this sounds like a Scintilla issue, I doubt anything
>> we can do could change that.
> Attached is an example. I see a problem in Print Preview when I change
> to either font size 12 or font size 8.

OK, gotcha (after a looong and boring dig into Scintilla code, beuah).
Actually Scintilla doesn't setup its Pango layouts for the actual target
Cairo surface but always for the widget's one, so some of the
measurements were done using a layout setup for the screen, thus the
sizing problem with the cairo_scale()s.  Attached patch should (and does
here) fix the issue
(0004-Scintilla-properly-update-the-Pango-contexts-for-the.patch).

Additionally it made me see that the scaling was inaccurate because
Scintilla don't use the default Pango scale but the scale for the screen
(which is correct), which changes depending on the screen's DPI.

I attach all patches.  They are based upon the printing-with-scintilla
branch but should apply cleanly on master.

Regards,
Colomban
>From 55b8c7af3fbaffe1acb32eb398ff96e1825ca695 Mon Sep 17 00:00:00 2001
From: Colomban Wendling <b...@herbesfolles.org>
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 5229267..8e91adb 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);
-- 
1.7.10.4

>From 9f32fdd1a4c54ba035c2f655bea6096c3b74fbe9 Mon Sep 17 00:00:00 2001
From: Colomban Wendling <b...@herbesfolles.org>
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 8e91adb..9ba85f1 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);
 	}
 
-- 
1.7.10.4

>From 4423de1a7223bc85ea89d706e699d2344d8dd36a Mon Sep 17 00:00:00 2001
From: Colomban Wendling <b...@herbesfolles.org>
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 9ba85f1..e95f485 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)
-- 
1.7.10.4

>From 2986246da3b986d654e0e10063b31aafb6b9f037 Mon Sep 17 00:00:00 2001
From: Colomban Wendling <b...@herbesfolles.org>
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.
---
 scintilla/gtk/PlatGTK.cxx |    4 ++++
 1 file changed, 4 insertions(+)

diff --git a/scintilla/gtk/PlatGTK.cxx b/scintilla/gtk/PlatGTK.cxx
index d98c235..8b91f33 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<cairo_t *>(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);
-- 
1.7.10.4

_______________________________________________
Devel mailing list
Devel@lists.geany.org
https://lists.geany.org/cgi-bin/mailman/listinfo/devel

Reply via email to