r6363 joty - in /trunk/netsurf: desktop/save_pdf/font_haru.c desktop/save_pdf/font_haru.h desktop/save_pdf/pdf_plotters.c desktop/save_pdf/pdf_plotters.h gtk/gtk_scaffolding.c

netsurf at semichrome.net netsurf at semichrome.net
Thu Feb 5 02:31:19 GMT 2009


Author: joty
Date: Wed Feb  4 20:31:19 2009
New Revision: 6363

URL: http://source.netsurf-browser.org?rev=6363&view=rev
Log:
- desktop/save_pdf/pdf_plotters.c:
  - Have a set of libharu gstate update related wrapper routines which minimizes the gstate updates in the PDF file 
resulting in smaller PDF file size.
  - Colour values were wrongly scaled (was dividing by 256 instead of by 255).
  - pdf_plot_polygon(): last (closing) lineto wasn't needed, a fill operation will do that automatically.
  - pdf_scale/pdf_set_scale(): moved to desktop/save_pdf/font_haru.c as pdf_text_scale/haru_nsfont_set_scale().
- desktop/save_pdf/pdf_plotters.c(pdf_set_scale): moved to desktop/save_pdf/font_haru.h as haru_nsfont_set_scale().
- desktop/save_pdf/font_haru.c:
  - moved pdf_scale variable from pdf_plotters.c to here.
  - haru_nsfont_set_scale(): was pdf_set_scale from pdf_plotters.c
  - haru_nsfont_apply_style(): always calculate font size and pass it on to caller when requested.
- desktop/save_pdf/font_haru.h:
  - haru_nsfont_set_scale(): declare.
  - haru_nsfont_apply_style(): add font size parameter
- gtk/gtk_scaffolding.c(MENUHANDLER(export_pdf)): call haru_nsfont_set_scale() instead of pdf_set_scale().

Modified:
    trunk/netsurf/desktop/save_pdf/font_haru.c
    trunk/netsurf/desktop/save_pdf/font_haru.h
    trunk/netsurf/desktop/save_pdf/pdf_plotters.c
    trunk/netsurf/desktop/save_pdf/pdf_plotters.h
    trunk/netsurf/gtk/gtk_scaffolding.c

Modified: trunk/netsurf/desktop/save_pdf/font_haru.c
URL: http://source.netsurf-browser.org/trunk/netsurf/desktop/save_pdf/font_haru.c?rev=6363&r1=6362&r2=6363&view=diff
==============================================================================
--- trunk/netsurf/desktop/save_pdf/font_haru.c (original)
+++ trunk/netsurf/desktop/save_pdf/font_haru.c Wed Feb  4 20:31:19 2009
@@ -1,5 +1,6 @@
 /*
  * Copyright 2008 Adam Blokus <adamblokus at gmail.com>
+ * Copyright 2009 John Tytgat <joty at netsurf-browser.org>
  *
  * This file is part of NetSurf, http://www.netsurf-browser.org/
  *
@@ -32,8 +33,11 @@
 #include <float.h> 
 #include <math.h>
 #include <string.h> 
+
 #include "hpdf.h"  
 #include "css/css.h"
+
+#include "desktop/options.h"
 #include "desktop/save_pdf/font_haru.h"
 #include "render/font.h"
 #include "utils/log.h"
@@ -54,6 +58,7 @@
 		const char *string, size_t length,
 	 	int x, size_t *char_offset, int *actual_x);
 	 	
+static float pdf_text_scale = DEFAULT_EXPORT_SCALE;
 
 const struct font_functions haru_nsfont = {
 	haru_nsfont_width,
@@ -122,22 +127,21 @@
 	HPDF_Page page;
 	char *string_nt;
 	HPDF_REAL width_real;
-	
+
 	*width = 0;
-	
-	if (length == 0) {
+
+	if (length == 0)
 		return true;
-	}
-	
+
 	if (!haru_nsfont_init(&pdf, &page, string, &string_nt, length))
 		return false;
-	
-	if (!haru_nsfont_apply_style(style, pdf, page, NULL)) {
+
+	if (!haru_nsfont_apply_style(style, pdf, page, NULL, NULL)) {
 		free(string_nt);
 		HPDF_Free(pdf);
 		return false;
 	}
-	
+
 	width_real = HPDF_Page_TextWidth(page, string_nt);
 	*width = width_real;
 
@@ -146,8 +150,7 @@
 #endif
 	free(string_nt);
 	HPDF_Free(pdf);
-	
-		
+
 	return true;
 }
 
@@ -179,7 +182,7 @@
 		return false;
 	
 	if (HPDF_Page_SetWidth(page, x) != HPDF_OK
-			|| !haru_nsfont_apply_style(style, pdf, page, NULL)) {
+			|| !haru_nsfont_apply_style(style, pdf, page, NULL, NULL)) {
 		free(string_nt);
 		HPDF_Free(pdf);
 		return false;
@@ -239,7 +242,7 @@
 		return false;
 	
 	if (HPDF_Page_SetWidth(page, x) != HPDF_OK
-		    || !haru_nsfont_apply_style(style, pdf, page, NULL)) {
+		    || !haru_nsfont_apply_style(style, pdf, page, NULL, NULL)) {
 		free(string_nt);
 		HPDF_Free(pdf);
 		return false;
@@ -270,12 +273,18 @@
  *			CSS_FONT_SIZE_LENGTH
  * \param  doc		document owning the page
  * \param  page		the page to apply the style to
- * \param  font		if this is not NULL it is updated to the font from the
- *			style and nothing with the page is done
+ * \param  font		if this is non NULL it is updated to the font based
+ *			on given CSS style style
+ * \param  font_size	if this is non NULL it is updated to the font size
+ *			based on given CSS style
  * \return true on success, false on error and error reported
+ *
+ * When both font and font_size are NULL, the HPDF_Page is updated for given
+ * CSS style, otherwise it is left to the called to do this.
  */
 bool haru_nsfont_apply_style(const struct css_style *style,
-		HPDF_Doc doc, HPDF_Page page, HPDF_Font *font)
+		HPDF_Doc doc, HPDF_Page page,
+		HPDF_Font *font, HPDF_REAL *font_size)
 {
 	HPDF_Font pdf_font;
 	HPDF_REAL size;
@@ -287,7 +296,6 @@
 	roman = false;
 	bold = false;
 	styled = false;
-	
 	
 	/*TODO: style handling, we are mapping the
 		styles on the basic 14 fonts only
@@ -311,7 +319,7 @@
 			break;
 	}
 	
-	if (style->font_weight == CSS_FONT_WEIGHT_BOLD){
+	if (style->font_weight == CSS_FONT_WEIGHT_BOLD) {
 		strcat(font_name, "-Bold");
 		bold = true;
 	}
@@ -339,34 +347,42 @@
 	LOG(("Setting font: %s", font_name));
 #endif		
 	
-	/*the functions was invoked only to get the proper font*/
-	if (font != NULL) {
-		pdf_font = HPDF_GetFont(doc, font_name, "StandardEncoding");
-		if (pdf_font == NULL)
-			return false;
+	if (style->font_size.value.length.unit  == CSS_UNIT_PX)
+		size = style->font_size.value.length.value;
+	else
+		size = css_len2pt(&style->font_size.value.length, style);
+
+	if (font != NULL)
+		size *= pdf_text_scale;
+
+	if (size <= 0)
+		return true;
+
+	if (size > HPDF_MAX_FONTSIZE)
+		size = HPDF_MAX_FONTSIZE;
+
+	if (font_size)
+		*font_size = size;
+
+	pdf_font = HPDF_GetFont(doc, font_name, "StandardEncoding");
+	if (pdf_font == NULL)
+		return false;
+	if (font != NULL)
 		*font = pdf_font;
-	}
-	/*the function was invoked to set the page parameters*/
-	else {
-		if (style->font_size.value.length.unit  == CSS_UNIT_PX)
-			size = style->font_size.value.length.value;
-		else
-			size = css_len2pt(&style->font_size.value.length, style);
-	
-		if (size <= 0)
-			return false;
-		
-		if (size > HPDF_MAX_FONTSIZE)
-			size = HPDF_MAX_FONTSIZE;
-		
-		pdf_font = HPDF_GetFont(doc, font_name, "StandardEncoding");
-		if (pdf_font == NULL)
-			return false;
+
+	if (font == NULL || font_size == NULL)
 		HPDF_Page_SetFontAndSize(page, pdf_font, size);
-	}	
 	
 	return true;
 }
 
+/**
+ * Sync the text scale with the scale for the whole content
+ */
+void haru_nsfont_set_scale(float s)
+{
+	pdf_text_scale = s;
+}
+
 #endif /* WITH_PDF_EXPORT */
 

Modified: trunk/netsurf/desktop/save_pdf/font_haru.h
URL: http://source.netsurf-browser.org/trunk/netsurf/desktop/save_pdf/font_haru.h?rev=6363&r1=6362&r2=6363&view=diff
==============================================================================
--- trunk/netsurf/desktop/save_pdf/font_haru.h (original)
+++ trunk/netsurf/desktop/save_pdf/font_haru.h Wed Feb  4 20:31:19 2009
@@ -1,5 +1,6 @@
 /*
  * Copyright 2008 Adam Blokus <adamblokus at gmail.com>
+ * Copyright 2009 John Tytgat <joty at netsurf-browser.org>
  *
  * This file is part of NetSurf, http://www.netsurf-browser.org/
  *
@@ -28,8 +29,10 @@
  
 bool haru_nsfont_apply_style(const struct css_style *style,
 			      	HPDF_Doc doc, HPDF_Page page,
-	  			HPDF_Font *font);
- 
+	  			HPDF_Font *font, HPDF_REAL *font_size);
+
+void haru_nsfont_set_scale(float s);
+
 extern const struct font_functions haru_nsfont;
 
 #endif

Modified: trunk/netsurf/desktop/save_pdf/pdf_plotters.c
URL: http://source.netsurf-browser.org/trunk/netsurf/desktop/save_pdf/pdf_plotters.c?rev=6363&r1=6362&r2=6363&view=diff
==============================================================================
--- trunk/netsurf/desktop/save_pdf/pdf_plotters.c (original)
+++ trunk/netsurf/desktop/save_pdf/pdf_plotters.c Wed Feb  4 20:31:19 2009
@@ -40,11 +40,8 @@
 
 #include "font_haru.h"
 
-#define R(x) ((  (x) & 0x0000ff     )/256.0)
-#define G(x) ((( (x) & 0x00ff00)>>8 )/256.0)
-#define B(x) ((( (x) & 0xff0000)>>16)/256.0)
-
-/*#define PDF_DEBUG*/
+/* #define PDF_DEBUG */
+/* #define PDF_DEBUG_DUMPGRID */
 
 static bool pdf_plot_clg(colour c);
 static bool pdf_plot_rectangle(int x0, int y0, int width, int height,
@@ -68,34 +65,61 @@
 static bool pdf_plot_path(const float *p, unsigned int n, colour fill, float width,
 		colour c, const float transform[6]);
 
-static void pdf_set_solid(void);
-static void pdf_set_dashed(void);
-static void pdf_set_dotted(void);
-
 static HPDF_Image pdf_extract_image(struct bitmap *bitmap, struct content *content);
-static void apply_clip_and_mode(bool selectTextMode);
-
 
 static void error_handler(HPDF_STATUS error_no, HPDF_STATUS detail_no,
 		void *user_data);
 
-#ifdef PDF_DEBUG
+#ifdef PDF_DEBUG_DUMPGRID
 static void pdf_plot_grid(int x_dist,int y_dist,unsigned int colour);
 #endif
 
-/*PDF Plotter - current doc,page and font*/
-static HPDF_Doc pdf_doc;
-static HPDF_Page pdf_page;
-static HPDF_Font pdf_font;
+typedef enum {
+	DashPattern_eNone,
+	DashPattern_eDash,
+	DashPattern_eDotted
+} DashPattern_e;
+
+/* Wrapper routines to minimize gstate updates in the produced PDF file.  */
+static void pdfw_gs_init(void);
+static void pdfw_gs_save(HPDF_Page page);
+static void pdfw_gs_restore(HPDF_Page page);
+static void pdfw_gs_fillcolour(HPDF_Page page, colour col);
+static void pdfw_gs_strokecolour(HPDF_Page page, colour col);
+static void pdfw_gs_linewidth(HPDF_Page page, float lineWidth);
+static void pdfw_gs_font(HPDF_Page page, HPDF_Font font, HPDF_REAL font_size);
+static void pdfw_gs_dash(HPDF_Page page, DashPattern_e dash);
+
+/** 
+ * Our PDF gstate mirror which we use to minimize gstate updates
+ * in the PDF file.
+ */
+typedef struct {
+	colour fillColour; /**< Current fill colour.  */
+	colour strokeColour; /**< Current stroke colour.  */
+	float lineWidth; /**< Current line width.  */
+	HPDF_Font font; /**< Current font.  */
+	HPDF_REAL font_size; /**< Current font size.  */
+	DashPattern_e dash; /**< Current dash state.  */
+} PDFW_GState;
+
+static void apply_clip_and_mode(bool selectTextMode, colour fillCol,
+	colour strokeCol, float lineWidth, DashPattern_e dash);
+
+#define PDFW_MAX_GSTATES 4
+static PDFW_GState pdfw_gs[PDFW_MAX_GSTATES];
+static unsigned int pdfw_gs_level;
+
+static HPDF_Doc pdf_doc; /**< Current PDF document.  */
+static HPDF_Page pdf_page; /**< Current page.  */
 
 /*PDF Page size*/
 static HPDF_REAL page_height, page_width;
 
-/*Remeber if pdf_plot_clip was invoked for current page*/
-static bool page_clipped;
+static bool in_text_mode; /**< true if we're currently in text mode or not.  */
+static bool clip_update_needed; /**< true if pdf_plot_clip was invoked for
+	current page and not yet synced with PDF output.  */
 static int last_clip_x0, last_clip_y0, last_clip_x1, last_clip_y1;
-
-static bool in_text_mode;
 
 static const struct print_settings *settings;
 
@@ -125,7 +149,6 @@
 	pdf_end
 };
 
-static float pdf_scale = DEFAULT_EXPORT_SCALE;
 static char *owner_pass;
 static char *user_pass;
 
@@ -140,22 +163,14 @@
 #ifdef PDF_DEBUG
 	LOG(("."));
 #endif
-	apply_clip_and_mode(false);
-
-	HPDF_Page_SetLineWidth(pdf_page, line_width);
-
-	if (dotted)
-		pdf_set_dotted();
-	else if (dashed)
-		pdf_set_dashed();
-
-	HPDF_Page_SetRGBStroke(pdf_page, R(c), G(c), B(c));
+
+	apply_clip_and_mode(false, TRANSPARENT, c, line_width,
+			(dotted) ? DashPattern_eDotted :
+			((dashed) ? DashPattern_eDash : DashPattern_eNone));
+
 	HPDF_Page_Rectangle(pdf_page, x0, page_height - y0, width, -height);
 	HPDF_Page_Stroke(pdf_page);
 
-	if (dotted || dashed)
-		pdf_set_solid();
-
 	return true;
 }
 
@@ -166,24 +181,14 @@
 	LOG(("."));
 #endif
 
-	apply_clip_and_mode(false);
-
-	HPDF_Page_SetLineWidth(pdf_page, width);
-
-	if (dotted)
-		pdf_set_dotted();
-	else if (dashed)
-		pdf_set_dashed();
-
-	HPDF_Page_SetRGBStroke(pdf_page, R(c), G(c), B(c));
-	HPDF_Page_SetLineWidth(pdf_page, width);
+	apply_clip_and_mode(false, TRANSPARENT, c, width,
+			(dotted) ? DashPattern_eDotted :
+			((dashed) ? DashPattern_eDash : DashPattern_eNone));
+
 	HPDF_Page_MoveTo(pdf_page, x0, page_height - y0);
 	HPDF_Page_LineTo(pdf_page, x1, page_height - y1);
 	HPDF_Page_Stroke(pdf_page);
 
-	if (dotted || dashed)
-		pdf_set_solid();
-
 	return true;
 }
 
@@ -198,11 +203,9 @@
 	if (n == 0)
 		return true;
 
-	apply_clip_and_mode(false);
-
-	HPDF_Page_SetRGBFill(pdf_page, R(fill), G(fill), B(fill));
+	apply_clip_and_mode(false, fill, TRANSPARENT, 0., DashPattern_eNone);
+
 	HPDF_Page_MoveTo(pdf_page, p[0], page_height - p[1]);
-
 	for (i = 1 ; i<n ; i++) {
 		HPDF_Page_LineTo(pdf_page, p[i*2], page_height - p[i*2+1]);
 #ifdef PDF_DEBUG
@@ -217,7 +220,6 @@
 	LOG(("%d %d %d %d %f", pminx, pminy, pmaxx, pmaxy, page_height - pminy));
 #endif
 
-	HPDF_Page_LineTo(pdf_page, p[0], page_height - p[1]);
 	HPDF_Page_Fill(pdf_page);
 
 	return true;
@@ -228,6 +230,8 @@
 #ifdef PDF_DEBUG
 	LOG(("%d %d %d %d %f %X", x0, y0, x1, y1, page_height - y0, c));
 #endif
+
+	apply_clip_and_mode(false, c, TRANSPARENT, 0., DashPattern_eNone);
 
 	/*Normalize boundaries of the area - to prevent overflows.
 	  It is needed only in a few functions, where integers are subtracted.
@@ -239,10 +243,7 @@
 	x1 = min(max(x1, 0), page_width);
 	y1 = min(max(y1, 0), page_height);
 
-	apply_clip_and_mode(false);
-
-	HPDF_Page_SetRGBFill(pdf_page, R(c), G(c), B(c));
-	HPDF_Page_Rectangle(pdf_page, x0, page_height - y1, x1 - x0, y1 - y0);
+	HPDF_Page_Rectangle(pdf_page, x0, page_height, x1 - x0, y0 - y1);
 	HPDF_Page_Fill(pdf_page);
 
 	return true;
@@ -263,7 +264,7 @@
 	last_clip_x1 = min(max(clip_x1, 0), page_width);
 	last_clip_y1 = min(max(clip_y1, 0), page_height);
 
-	page_clipped = true;
+	clip_update_needed = true;
 
 	return true;
 }
@@ -275,42 +276,25 @@
 	LOG((". %d %d %.*s", x, y, (int)length, text));
 #endif
 	char *word;
+	HPDF_Font pdf_font;
 	HPDF_REAL size;
-	float text_bottom_position, descent;
 
 	if (length == 0)
 		return true;
 
-	apply_clip_and_mode(true);
-
-	if (style->font_size.value.length.unit  == CSS_UNIT_PX)
-		size = style->font_size.value.length.value;
-	else
-		size = css_len2pt(&style->font_size.value.length, style);
-
-	size *= pdf_scale;
-
-	if (size <= 0)
-		return true;
-
-	if (size > HPDF_MAX_FONTSIZE)
-		size = HPDF_MAX_FONTSIZE;
-
-	haru_nsfont_apply_style(style, pdf_doc, pdf_page, &pdf_font);
-
-	descent = size * (HPDF_Font_GetDescent(pdf_font) / 1000.0);
-	text_bottom_position = page_height - y + descent;
-
-	word = (char*) malloc( sizeof(char) * (length+1) );
+	apply_clip_and_mode(true, c, TRANSPARENT, 0., DashPattern_eNone);
+
+	haru_nsfont_apply_style(style, pdf_doc, pdf_page, &pdf_font, &size);
+	pdfw_gs_font(pdf_page, pdf_font, size);
+
+	/* FIXME: UTF-8 to current font encoding needs to done.  Or the font
+	 * encoding needs to be UTF-8 or other Unicode encoding.  */
+	word = (char *)malloc( sizeof(char) * (length+1) );
 	if (word == NULL)
 		return false;
-
 	memcpy(word, text, length);
 	word[length] = '\0';
 
-	HPDF_Page_SetRGBFill(pdf_page, R(c), G(c), B(c));
-
-	HPDF_Page_SetFontAndSize (pdf_page, pdf_font, size);
 	HPDF_Page_TextOut (pdf_page, x, page_height - y, word);
 
 	free(word);
@@ -323,12 +307,11 @@
 #ifdef PDF_DEBUG
 	LOG(("."));
 #endif
-	apply_clip_and_mode(false);
-
-	if (filled)
-		HPDF_Page_SetRGBFill(pdf_page, R(c), G(c), B(c));
-	else
-		HPDF_Page_SetRGBStroke(pdf_page, R(c), G(c), B(c));
+
+	/* FIXME: line width 1 is ok ? */
+	apply_clip_and_mode(false,
+			filled ? c : TRANSPARENT, filled ? TRANSPARENT : c,
+			1., DashPattern_eNone);
 
 	HPDF_Page_Circle(pdf_page, x, page_height - y, radius);
 
@@ -346,16 +329,15 @@
 	LOG(("%d %d %d %d %d %X", x, y, radius, angle1, angle2, c));
 #endif
 
-	/*Normalize angles*/
+	/* FIXME: line width 1 is ok ? */
+	apply_clip_and_mode(false, TRANSPARENT, c, 1., DashPattern_eNone);
+
+	/* Normalize angles */
 	angle1 %= 360;
 	angle2 %= 360;
 	if (angle1 > angle2)
 		angle1 -= 360;
 
-	apply_clip_and_mode(false);
-
-	HPDF_Page_SetRGBStroke(pdf_page, R(c), G(c), B(c));
-
 	HPDF_Page_Arc(pdf_page, x, page_height - y, radius, angle1, angle2);
 
 	HPDF_Page_Stroke(pdf_page);
@@ -374,7 +356,7 @@
  	if (width == 0 || height == 0)
  		return true;
 
-	apply_clip_and_mode(false);
+	apply_clip_and_mode(false, TRANSPARENT, TRANSPARENT, 0., DashPattern_eNone);
 
 	image = pdf_extract_image(bitmap, content);
 
@@ -404,7 +386,7 @@
  	if (width == 0 || height == 0)
  		return true;
 
-	apply_clip_and_mode(false);
+	apply_clip_and_mode(false, TRANSPARENT, TRANSPARENT, 0., DashPattern_eNone);
 
 	image = pdf_extract_image(bitmap, content);
 	if (!image)
@@ -508,18 +490,55 @@
 }
 
 /**
- * Change the mode and clip only if it's necessary
- */
-static void apply_clip_and_mode(bool selectTextMode)
-{
-	if (in_text_mode && (!selectTextMode || page_clipped)) {
+ * Enter/leave text mode and update PDF gstate for its clip, fill & stroke
+ * colour, line width and dash pattern parameters.
+ * \param selectTextMode true if text mode needs to be entered if required;
+ * false otherwise.
+ * \param fillCol Desired fill colour, use TRANSPARENT if no update is
+ * required.
+ * \param strokeCol Desired stroke colour, use TRANSPARENT if no update is
+ * required.
+ * \param lineWidth Desired line width. Only taken into account when strokeCol
+ * is different from TRANSPARENT.
+ * \param dash Desired dash pattern. Only taken into account when strokeCol
+ * is different from TRANSPARENT.
+ */
+static void apply_clip_and_mode(bool selectTextMode, colour fillCol,
+		colour strokeCol, float lineWidth, DashPattern_e dash)
+{
+	/* Leave text mode when
+	 *  1) we're not setting text anymore
+	 *  2) or we need to update the current clippath
+	 *  3) or we need to update any fill/stroke colour, linewidth or dash.
+	 * Note: the test on stroke parameters (stroke colour, line width and
+	 * dash) is commented out as if these need updating we want to be
+	 * outside the text mode anyway (i.e. selectTextMode is false).
+	 */
+	if (in_text_mode && (!selectTextMode || clip_update_needed
+		|| (fillCol != TRANSPARENT
+			&& fillCol != pdfw_gs[pdfw_gs_level].fillColour)
+		/* || (strokeCol != TRANSPARENT
+			&& (strokeCol != pdfw_gs[pdfw_gs_level].strokeColour
+				|| lineWidth != pdfw_gs[pdfw_gs_level].lineWidth
+				|| dash != pdfw_gs[pdfw_gs_level].dash)) */)) {
 		HPDF_Page_EndText(pdf_page);
 		in_text_mode = false;
 	}
 
-	if (page_clipped) {
-		HPDF_Page_GRestore(pdf_page);
-		HPDF_Page_GSave(pdf_page);
+	if (clip_update_needed)
+		pdfw_gs_restore(pdf_page);
+
+	/* Update fill/stroke colour, linewidth and dash when needed.  */
+	if (fillCol != TRANSPARENT)
+		pdfw_gs_fillcolour(pdf_page, fillCol);
+	if (strokeCol != TRANSPARENT) {
+		pdfw_gs_strokecolour(pdf_page, strokeCol);
+		pdfw_gs_linewidth(pdf_page, lineWidth);
+		pdfw_gs_dash(pdf_page, dash);
+	}
+
+	if (clip_update_needed) {
+		pdfw_gs_save(pdf_page);
 
 		HPDF_Page_Rectangle(pdf_page, last_clip_x0,
 				page_height - last_clip_y1,
@@ -528,14 +547,12 @@
 		HPDF_Page_Clip(pdf_page);
 		HPDF_Page_EndPath(pdf_page);
 
-		page_clipped = false;
-	}
-
-	if (selectTextMode) {
-		if (!in_text_mode) {
-			HPDF_Page_BeginText(pdf_page);
-			in_text_mode = true;
-		}
+		clip_update_needed = false;
+	}
+
+	if (selectTextMode && !in_text_mode) {
+		HPDF_Page_BeginText(pdf_page);
+		in_text_mode = true;
 	}
 }
 
@@ -553,12 +570,13 @@
 bool pdf_plot_path(const float *p, unsigned int n, colour fill, float width,
 		colour c, const float transform[6])
 {
-#ifdef PDF_DEBUG
-	LOG(("."));
-#endif
 	unsigned int i;
 	bool empty_path;
 
+#ifdef PDF_DEBUG
+	LOG(("."));
+#endif
+
 	if (n == 0)
 		return true;
 
@@ -568,14 +586,7 @@
 	if (p[0] != PLOTTER_PATH_MOVE)
 		return false;
 
-	apply_clip_and_mode(false);
-
-	if (fill != TRANSPARENT)
-		HPDF_Page_SetRGBFill(pdf_page, R(fill), G(fill), B(fill));
-	if (c != TRANSPARENT) {
-		HPDF_Page_SetLineWidth(pdf_page, width);
-		HPDF_Page_SetRGBStroke(pdf_page, R(c), G(c), B(c));
-	}
+	apply_clip_and_mode(false, fill, c, width, DashPattern_eNone);
 
 	empty_path = true;
 	for (i = 0 ; i < n ; ) {
@@ -627,23 +638,6 @@
 	return true;
 }
 
-void pdf_set_solid()
-{
-	HPDF_Page_SetDash(pdf_page, NULL, 0, 0);
-}
-
-void pdf_set_dashed()
-{
-	const HPDF_UINT16 dash_ptn[] = {3};
-	HPDF_Page_SetDash(pdf_page, dash_ptn, 1, 1);
-}
-
-void pdf_set_dotted()
-{
-	const HPDF_UINT16 dash_ptn[] = {1};
-	HPDF_Page_SetDash(pdf_page, dash_ptn, 1, 1);
-}
-
 /**
  * Begin pdf plotting - initialize a new document
  * \param path Output file path
@@ -652,6 +646,8 @@
  */
 bool pdf_begin(struct print_settings *print_settings)
 {
+	pdfw_gs_init();
+
 	if (pdf_doc != NULL)
 		HPDF_Free(pdf_doc);
 	pdf_doc = HPDF_New(error_handler, NULL);
@@ -674,7 +670,6 @@
 #endif
 	HPDF_SetInfoAttr(pdf_doc, HPDF_INFO_CREATOR, user_agent_string());
 
-	pdf_font = NULL;
 	pdf_page = NULL;
 
 #ifdef PDF_DEBUG
@@ -689,13 +684,14 @@
 #ifdef PDF_DEBUG
 	LOG(("pdf_next_page begins"));
 #endif
+	clip_update_needed = false;
 	if (pdf_page != NULL) {
-		page_clipped = false;
-		apply_clip_and_mode(false);
-		HPDF_Page_GRestore(pdf_page);
-	}
-
-#ifdef PDF_DEBUG
+		apply_clip_and_mode(false, TRANSPARENT, TRANSPARENT, 0.,
+				DashPattern_eNone);
+		pdfw_gs_restore(pdf_page);
+	}
+
+#ifdef PDF_DEBUG_DUMPGRID
 	if (pdf_page != NULL) {
 		pdf_plot_grid(10, 10, 0xCCCCCC);
 		pdf_plot_grid(100, 100, 0xCCCCFF);
@@ -708,10 +704,9 @@
 	HPDF_Page_SetWidth (pdf_page, settings->page_width);
 	HPDF_Page_SetHeight(pdf_page, settings->page_height);
 
-	HPDF_Page_Concat(pdf_page,1,0,0,1,settings->margins[MARGINLEFT],0);
-
-	page_clipped = false;
-	HPDF_Page_GSave(pdf_page);
+	HPDF_Page_Concat(pdf_page, 1, 0, 0, 1, settings->margins[MARGINLEFT], 0);
+
+	pdfw_gs_save(pdf_page);
 
 #ifdef PDF_DEBUG
 	LOG(("%f %f", page_width, page_height));
@@ -726,13 +721,14 @@
 #ifdef PDF_DEBUG
 	LOG(("pdf_end begins"));
 #endif
+	clip_update_needed = false;
 	if (pdf_page != NULL) {
-		page_clipped = false;
-		apply_clip_and_mode(false);
-		HPDF_Page_GRestore(pdf_page);
-	}
-
-#ifdef PDF_DEBUG
+		apply_clip_and_mode(false, TRANSPARENT, TRANSPARENT, 0.,
+				DashPattern_eNone);
+		pdfw_gs_restore(pdf_page);
+	}
+
+#ifdef PDF_DEBUG_DUMPGRID
 	if (pdf_page != NULL) {
 		pdf_plot_grid(10, 10, 0xCCCCCC);
 		pdf_plot_grid(100, 100, 0xCCCCFF);
@@ -797,7 +793,7 @@
  * This function plots a grid - used for debug purposes to check if all
  * elements' final coordinates are correct.
 */
-#ifdef PDF_DEBUG
+#ifdef PDF_DEBUG_DUMPGRID
 void pdf_plot_grid(int x_dist, int y_dist, unsigned int colour)
 {
 	for (int i = x_dist ; i < page_width ; i += x_dist)
@@ -805,16 +801,148 @@
 
 	for (int i = y_dist ; i < page_height ; i += x_dist)
 		pdf_plot_line(0, i, page_width, i, 1, colour, false, false);
-
-}
-#endif
-
-/**
- * Sync the text scale with the scale for the whole content
- */
-void pdf_set_scale(float s)
-{
-	pdf_scale = s;
+}
+#endif
+
+/**
+ * Initialize the gstate wrapper code.
+ */
+void pdfw_gs_init()
+{
+	pdfw_gs_level = 0;
+	pdfw_gs[0].fillColour = 0x00000000; /* Default PDF fill colour is black.  */
+	pdfw_gs[0].strokeColour = 0x00000000; /* Default PDF stroke colour is black.  */
+	pdfw_gs[0].lineWidth = 1.0; /* Default PDF line width is 1.  */
+	pdfw_gs[0].font = NULL;
+	pdfw_gs[0].font_size = 0.;
+	pdfw_gs[0].dash = DashPattern_eNone; /* Default dash state is a solid line.  */
+}
+
+/**
+ * Increase gstate level.
+ * \param page	PDF page where the update needs to happen.
+ */
+void pdfw_gs_save(HPDF_Page page)
+{
+	if (pdfw_gs_level == PDFW_MAX_GSTATES)
+		abort();
+	pdfw_gs[pdfw_gs_level + 1] = pdfw_gs[pdfw_gs_level];
+	++pdfw_gs_level;
+	HPDF_Page_GSave(page);
+}
+
+/**
+ * Decrease gstate level and restore the gstate to its value at last save
+ * operation.
+ * \param page	PDF page where the update needs to happen.
+ */
+void pdfw_gs_restore(HPDF_Page page)
+{
+	if (pdfw_gs_level == 0)
+		abort();
+	--pdfw_gs_level;
+	HPDF_Page_GRestore(page);
+}
+
+#define RBYTE(x) (((x) & 0x0000FF) >>  0)
+#define GBYTE(x) (((x) & 0x00FF00) >>  8)
+#define BBYTE(x) (((x) & 0xFF0000) >> 16)
+#define R(x) (RBYTE(x) / 255.)
+#define G(x) (GBYTE(x) / 255.)
+#define B(x) (BBYTE(x) / 255.)
+
+/**
+ * Checks if given fill colour is already set in PDF gstate and if not,
+ * update the gstate accordingly.
+ * \param page	PDF page where the update needs to happen.
+ * \param col	Wanted fill colour.
+ */
+void pdfw_gs_fillcolour(HPDF_Page page, colour col)
+{
+	if (col == pdfw_gs[pdfw_gs_level].fillColour)
+		return;
+	pdfw_gs[pdfw_gs_level].fillColour = col;
+	if (RBYTE(col) == GBYTE(col) && GBYTE(col) == BBYTE(col))
+		HPDF_Page_SetGrayFill(pdf_page, R(col));
+	else
+		HPDF_Page_SetRGBFill(pdf_page, R(col), G(col), B(col));
+}
+
+/**
+ * Checks if given stroke colour is already set in PDF gstate and if not,
+ * update the gstate accordingly.
+ * \param page	PDF page where the update needs to happen.
+ * \param col	Wanted stroke colour.
+ */
+void pdfw_gs_strokecolour(HPDF_Page page, colour col)
+{
+	if (col == pdfw_gs[pdfw_gs_level].strokeColour)
+		return;
+	pdfw_gs[pdfw_gs_level].strokeColour = col;
+	if (RBYTE(col) == GBYTE(col) && GBYTE(col) == BBYTE(col))
+		HPDF_Page_SetGrayStroke(pdf_page, R(col));
+	else
+		HPDF_Page_SetRGBStroke(pdf_page, R(col), G(col), B(col));
+}
+
+/**
+ * Checks if given line width is already set in PDF gstate and if not, update
+ * the gstate accordingly.
+ * \param page		PDF page where the update needs to happen.
+ * \param lineWidth	Wanted line width.
+ */
+void pdfw_gs_linewidth(HPDF_Page page, float lineWidth)
+{
+	if (lineWidth == pdfw_gs[pdfw_gs_level].lineWidth)
+		return;
+	pdfw_gs[pdfw_gs_level].lineWidth = lineWidth;
+	HPDF_Page_SetLineWidth(page, lineWidth);
+}
+
+/**
+ * Checks if given font and font size is already set in PDF gstate and if not,
+ * update the gstate accordingly.
+ * \param page		PDF page where the update needs to happen.
+ * \param font		Wanted PDF font.
+ * \param font_size	Wanted PDF font size.
+ */
+void pdfw_gs_font(HPDF_Page page, HPDF_Font font, HPDF_REAL font_size)
+{
+	if (font == pdfw_gs[pdfw_gs_level].font
+		&& font_size == pdfw_gs[pdfw_gs_level].font_size)
+		return;
+	pdfw_gs[pdfw_gs_level].font = font;
+	pdfw_gs[pdfw_gs_level].font_size = font_size;
+	HPDF_Page_SetFontAndSize(page, font, font_size);
+}
+
+/**
+ * Checks if given dash pattern is already set in PDF gstate and if not,
+ * update the gstate accordingly.
+ * \param page	PDF page where the update needs to happen.
+ * \param dash	Wanted dash pattern.
+ */
+void pdfw_gs_dash(HPDF_Page page, DashPattern_e dash)
+{
+	if (dash == pdfw_gs[pdfw_gs_level].dash)
+		return;
+	pdfw_gs[pdfw_gs_level].dash = dash;
+	switch (dash) {
+		case DashPattern_eNone: {
+			HPDF_Page_SetDash(page, NULL, 0, 0);
+			break;
+		}
+		case DashPattern_eDash: {
+			const HPDF_UINT16 dash_ptn[] = {3};
+			HPDF_Page_SetDash(page, dash_ptn, 1, 1);
+			break;
+		}
+		case DashPattern_eDotted: {
+			const HPDF_UINT16 dash_ptn[] = {1};
+			HPDF_Page_SetDash(page, dash_ptn, 1, 1);
+			break;
+		}
+	}
 }
 
 #endif /* WITH_PDF_EXPORT */

Modified: trunk/netsurf/desktop/save_pdf/pdf_plotters.h
URL: http://source.netsurf-browser.org/trunk/netsurf/desktop/save_pdf/pdf_plotters.h?rev=6363&r1=6362&r2=6363&view=diff
==============================================================================
--- trunk/netsurf/desktop/save_pdf/pdf_plotters.h (original)
+++ trunk/netsurf/desktop/save_pdf/pdf_plotters.h Wed Feb  4 20:31:19 2009
@@ -36,8 +36,6 @@
 /**Close pdf document and save changes to file*/
 void pdf_end(void);
 
-void pdf_set_scale(float s);
-
 void save_pdf(const char *path);
 
 #endif /*NETSURF_PDF_PLOTTERS_H*/

Modified: trunk/netsurf/gtk/gtk_scaffolding.c
URL: http://source.netsurf-browser.org/trunk/netsurf/gtk/gtk_scaffolding.c?rev=6363&r1=6362&r2=6363&view=diff
==============================================================================
--- trunk/netsurf/gtk/gtk_scaffolding.c (original)
+++ trunk/netsurf/gtk/gtk_scaffolding.c Wed Feb  4 20:31:19 2009
@@ -573,7 +573,7 @@
 	settings = print_make_settings(OPTIONS, NULL);
 	/*this way the scale used by PDF functions is synchronized with that
 	used by the all-purpose print interface*/
-	pdf_set_scale((float)option_export_scale / 100);
+	haru_nsfont_set_scale((float)option_export_scale / 100);
 
 	save_dialog = gtk_file_chooser_dialog_new("Export to PDF", gw->window,
 		GTK_FILE_CHOOSER_ACTION_SAVE,




More information about the netsurf-commits mailing list