From e063a2a59d698dd96123b68a44b09f0623f80cab Mon Sep 17 00:00:00 2001 From: John Tytgat Date: Thu, 14 Aug 2008 20:32:10 +0000 Subject: Second merge of Adam Blokus' GSoC work from his branch 'branches/adamblokus/netsurf'. Merged revisions 4195-4211,4216,4219-4220,4222-4234,4236-4250,4252-4262,4264-4266,4268-4326,4329-4335,4338-4342,4344-4411,4413-4420,4422-4436,4438-4491,4494-4506,4508-4514,4516,4518-4552,4554,4556-4564,4567-4568,4570-4574,4576-4686,4689-4692,4694,4698-4709,4715-4723,4725-4755,4757-4769,4771-4919,4921-4996,4998-5110,5112-5117 via svnmerge from svn://svn.netsurf-browser.org/branches/adamblokus/netsurf ........ r4736 | adamblokus | 2008-07-26 13:46:54 +0200 (Sat, 26 Jul 2008) | 2 lines Sorting out some problems with svn. ........ r4737 | adamblokus | 2008-07-26 13:54:36 +0200 (Sat, 26 Jul 2008) | 4 lines Added export tab to the options dialog. Added the possibility of changing some print options. ........ r4897 | adamblokus | 2008-08-04 17:59:05 +0200 (Mon, 04 Aug 2008) | 5 lines Added checking of horizontal clipping. Added better table loosening. Changed some minor bugs. Applied changes in the Export options tab according to the review from tlsa. ........ r4905 | adamblokus | 2008-08-05 01:53:34 +0200 (Tue, 05 Aug 2008) | 2 lines Fixed bug which made it impossible to export pdf's. ........ r4919 | adamblokus | 2008-08-05 16:39:33 +0200 (Tue, 05 Aug 2008) | 2 lines Fixed some memory leaks which caused Netsurf to break. ........ r4927 | adamblokus | 2008-08-06 02:26:30 +0200 (Wed, 06 Aug 2008) | 4 lines Fixed bug with filenames which crashed Netsurf. Turned anti aliasing off for printing. Fixed some scaling issues. ........ r4928 | adamblokus | 2008-08-06 17:52:44 +0200 (Wed, 06 Aug 2008) | 5 lines Added new export/print options: - suppressing images - turning off backgrounds - toggled loosening ........ r4950 | adamblokus | 2008-08-07 21:15:21 +0200 (Thu, 07 Aug 2008) | 5 lines Added new options to PDF export: - document compression - document encryption Added PDF password dialog ........ r4954 | adamblokus | 2008-08-07 22:11:31 +0200 (Thu, 07 Aug 2008) | 2 lines Added saving print settings. ........ r4956 | adamblokus | 2008-08-07 22:44:48 +0200 (Thu, 07 Aug 2008) | 2 lines Fixes to PDF encryption ........ r4970 | adamblokus | 2008-08-09 15:26:24 +0200 (Sat, 09 Aug 2008) | 3 lines Fixed bug in plotting tiled bitmaps. Fixed bug with too long text decorations. ........ r4977 | adamblokus | 2008-08-09 19:18:56 +0200 (Sat, 09 Aug 2008) | 2 lines Fixed JPG embedding bug. ........ r4988 | adamblokus | 2008-08-10 16:59:51 +0200 (Sun, 10 Aug 2008) | 3 lines Added clip checking to pdf plotters. No more "blank" clips. Made PDF compression a default setting. ........ r4995 | adamblokus | 2008-08-10 20:03:00 +0200 (Sun, 10 Aug 2008) | 2 lines Fixed Haru crash on font-size==0. ........ r4996 | adamblokus | 2008-08-10 21:04:43 +0200 (Sun, 10 Aug 2008) | 2 lines Added changing text mode only if necessary. ........ r5045 | adamblokus | 2008-08-11 21:26:26 +0200 (Mon, 11 Aug 2008) | 3 lines Removing gtk stuff from core code. Little fix in options. ........ r5048 | adamblokus | 2008-08-11 21:57:45 +0200 (Mon, 11 Aug 2008) | 2 lines Better font size checking in PDF export. ........ r5050 | adamblokus | 2008-08-11 22:19:56 +0200 (Mon, 11 Aug 2008) | 2 lines Fixed riscos text scale bug. ........ r5073 | adamblokus | 2008-08-12 17:40:57 +0200 (Tue, 12 Aug 2008) | 2 lines Added missing tooltips ........ r5092 | adamblokus | 2008-08-13 17:09:25 +0200 (Wed, 13 Aug 2008) | 2 lines Moved /pdf folder to desktop/save_pdf ........ r5110 | adamblokus | 2008-08-13 22:44:50 +0200 (Wed, 13 Aug 2008) | 2 lines Added comments. ........ r5113 | adamblokus | 2008-08-13 23:07:35 +0200 (Wed, 13 Aug 2008) | 2 lines Cosmetic changes ........ r5116 | adamblokus | 2008-08-14 16:10:18 +0200 (Thu, 14 Aug 2008) | 2 lines Fixed bug with BOX_INLINE_END in tree duplication. ........ r5117 | joty | 2008-08-14 21:47:46 +0200 (Thu, 14 Aug 2008) | 1 line Improvement for r5116: use local vars when possible; rename global last to box_duplicate_last; check on box_duplicate_main_tree failure. ........ svn path=/trunk/netsurf/; revision=5118 --- desktop/save_pdf/TODO | 19 + desktop/save_pdf/font_haru.c | 372 ++++++++++++++++++ desktop/save_pdf/font_haru.h | 36 ++ desktop/save_pdf/pdf_plotters.c | 831 ++++++++++++++++++++++++++++++++++++++++ desktop/save_pdf/pdf_plotters.h | 44 +++ 5 files changed, 1302 insertions(+) create mode 100644 desktop/save_pdf/TODO create mode 100644 desktop/save_pdf/font_haru.c create mode 100644 desktop/save_pdf/font_haru.h create mode 100644 desktop/save_pdf/pdf_plotters.c create mode 100644 desktop/save_pdf/pdf_plotters.h (limited to 'desktop/save_pdf') diff --git a/desktop/save_pdf/TODO b/desktop/save_pdf/TODO new file mode 100644 index 000000000..1b3a896b9 --- /dev/null +++ b/desktop/save_pdf/TODO @@ -0,0 +1,19 @@ +- finish all graphic primitives +- allow adding raw bitmaps +- make image-aware (embed the image in its native/original type if possible) + +- adjust content width to page width +- divide output into multiple pages (not just the first one) +- rearrange file structure + +- separate print-plotting as much as possible from window redrawing +- add text-scaling (if not yet using the original font - make the default one + have the same width) +- add a save file.. dialogue +- add utf support to Haru ( doable? ) +- wait for browser to end fetching? +- analyze and deal with performance issues(huge file hangs some pdf viewers, + for example kpdf when viewing plotted http://www.onet.pl) +- deal with to wide pages - when window layouting adds a horizontal scrollbar, + we should treat it otherwise - either print horizontal or scale or, + better, find a new layout. \ No newline at end of file diff --git a/desktop/save_pdf/font_haru.c b/desktop/save_pdf/font_haru.c new file mode 100644 index 000000000..2e5f90adb --- /dev/null +++ b/desktop/save_pdf/font_haru.c @@ -0,0 +1,372 @@ +/* + * Copyright 2008 Adam Blokus + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + /** \file + * Font handling in Haru pdf documents (implementation). + * + * The functions were written to implement the same interface as the Pango ones + * so that the usage of the latter wouldn't have to be modified. + */ + +#include "utils/config.h" +#ifdef WITH_PDF_EXPORT + +/*#define FONT_HARU_DEBUG */ + +#include +#include +#include +#include +#include "hpdf.h" +#include "css/css.h" +#include "desktop/save_pdf/font_haru.h" +#include "render/font.h" +#include "utils/log.h" + + +static bool haru_nsfont_init(HPDF_Doc *pdf, HPDF_Page *page, + const char *string, char **string_nt, int length); + +static bool haru_nsfont_width(const struct css_style *style, + const char *string, size_t length, + int *width); + +static bool haru_nsfont_position_in_string(const struct css_style *style, + const char *string, size_t length, + int x, size_t *char_offset, int *actual_x); + +static bool haru_nsfont_split(const struct css_style *style, + const char *string, size_t length, + int x, size_t *char_offset, int *actual_x); + + +const struct font_functions haru_nsfont = { + haru_nsfont_width, + haru_nsfont_position_in_string, + haru_nsfont_split +}; + +/** + * Haru error handler + * for debugging purposes - it immediately exits the program on the first error, + * as it would otherwise flood the user with all resulting complications, + * covering the most important error source. + */ +static void error_handler(HPDF_STATUS error_no, HPDF_STATUS detail_no, + void *user_data) +{ + LOG(("ERROR: in font_haru \n\terror_no=%x\n\tdetail_no=%d\n", + (HPDF_UINT)error_no, (HPDF_UINT)detail_no)); +#ifdef FONT_HARU_DEBUG + exit(1); +#endif +} + +static bool haru_nsfont_init(HPDF_Doc *pdf, HPDF_Page *page, + const char *string, char **string_nt, int length) +{ + + *pdf = HPDF_New(error_handler, NULL); + + if (*pdf == NULL) + return false; + + *page = HPDF_AddPage(*pdf); + + if (*page == NULL) { + HPDF_Free(*pdf); + return false; + } + + *string_nt = malloc((length + 1) * sizeof(char)); + if (*string_nt == NULL) { + HPDF_Free(*pdf); + return false; + } + + memcpy(*string_nt, string, length); + (*string_nt)[length] = '\0'; + return true; +} + +/** + * Measure the width of a string. + * + * \param style css_style for this text, with style->font_size.size == + * CSS_FONT_SIZE_LENGTH + * \param string string to measure (no UTF-8 currently) + * \param length length of string + * \param width updated to width of string[0..length] + * \return true on success, false on error and error reported + */ +bool haru_nsfont_width(const struct css_style *style, + const char *string, size_t length, + int *width) +{ + HPDF_Doc pdf; + HPDF_Page page; + char *string_nt; + HPDF_REAL width_real; + + *width = 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)) { + free(string_nt); + HPDF_Free(pdf); + return false; + } + + width_real = HPDF_Page_TextWidth(page, string_nt); + *width = width_real; + +#ifdef FONT_HARU_DEBUG + LOG(("Measuring string: %s ; Calculated width: %f %i",string_nt, width_real, *width)); +#endif + free(string_nt); + HPDF_Free(pdf); + + + return true; +} + + +/** + * Find the position in a string where an x coordinate falls. + * + * \param style css_style for this text, with style->font_size.size == + * CSS_FONT_SIZE_LENGTH + * \param string string to measure (no UTF-8 currently) + * \param length length of string + * \param x x coordinate to search for + * \param char_offset updated to offset in string of actual_x, [0..length] + * \param actual_x updated to x coordinate of character closest to x + * \return true on success, false on error and error reported + */ + +bool haru_nsfont_position_in_string(const struct css_style *style, + const char *string, size_t length, + int x, size_t *char_offset, int *actual_x) +{ + HPDF_Doc pdf; + HPDF_Page page; + char *string_nt; + HPDF_UINT offset; + HPDF_REAL real_width; + + if (!haru_nsfont_init(&pdf, &page, string, &string_nt, length)) + return false; + + if (HPDF_Page_SetWidth(page, x) != HPDF_OK + || !haru_nsfont_apply_style(style, pdf, page, NULL)) { + free(string_nt); + HPDF_Free(pdf); + return false; + } + + + offset = HPDF_Page_MeasureText(page, string_nt, x, + HPDF_FALSE, &real_width); + + + if (real_width < x) + *char_offset = offset; + else { + assert(fabs(real_width - x) < FLT_EPSILON); + assert(offset > 0); + *char_offset = offset - 1; + } + + /*TODO: this is only the right edge of the character*/ + *actual_x = real_width; + +#ifdef FONT_HARU_DEBUG + LOG(("Position in string: %s at x: %i; Calculated position: %i", + string_nt, x, *char_offset)); +#endif + free(string_nt); + HPDF_Free(pdf); + + return true; +} + +/** + * Find where to split a string to make it fit a width. + * + * \param style css_style for this text, with style->font_size.size == + * CSS_FONT_SIZE_LENGTH + * \param string string to measure (no UTF-8 currently) + * \param length length of string + * \param x width available + * \param char_offset updated to offset in string of actual_x, [0..length] + * \param actual_x updated to x coordinate of character closest to x + * \return true on success, false on error and error reported + */ + +bool haru_nsfont_split(const struct css_style *style, + const char *string, size_t length, + int x, size_t *char_offset, int *actual_x) +{ + HPDF_Doc pdf; + HPDF_Page page; + char *string_nt; + HPDF_REAL real_width; + HPDF_UINT offset; + + + if (!haru_nsfont_init(&pdf, &page, string, &string_nt, length)) + return false; + + if (HPDF_Page_SetWidth(page, x) != HPDF_OK + || !haru_nsfont_apply_style(style, pdf, page, NULL)) { + free(string_nt); + HPDF_Free(pdf); + return false; + } + + offset = HPDF_Page_MeasureText(page, string_nt, x, + HPDF_TRUE, &real_width); + +#ifdef FONT_HARU_DEBUG + LOG(("Splitting string: %s for width: %i ; Calculated position: %i Calculated real_width: %f", + string_nt, x, *char_offset, real_width)); +#endif + *char_offset = offset - 1; + + /*TODO: this is only the right edge of the character*/ + *actual_x = real_width; + + free(string_nt); + HPDF_Free(pdf); + + return true; +} + +/** + * Apply css_style to a Haru HPDF_Page + * + * \param style css_style for this page, with style->font_size.size == + * 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 + * \return true on success, false on error and error reported + */ +bool haru_nsfont_apply_style(const struct css_style *style, + HPDF_Doc doc, HPDF_Page page, HPDF_Font *font) +{ + HPDF_Font pdf_font; + HPDF_REAL size; + char font_name[50]; + bool roman; + bool bold; + bool styled; + + roman = false; + bold = false; + styled = false; + + + /*TODO: style handling, we are mapping the + styles on the basic 14 fonts only + */ + switch (style->font_family) { + case CSS_FONT_FAMILY_SERIF: + strcpy(font_name, "Times"); + roman = true; + break; + case CSS_FONT_FAMILY_MONOSPACE: + strcpy(font_name, "Courier"); + break; + case CSS_FONT_FAMILY_SANS_SERIF: + strcpy(font_name, "Helvetica"); + break; + case CSS_FONT_FAMILY_CURSIVE: + case CSS_FONT_FAMILY_FANTASY: + default: + strcpy(font_name, "Times"); + roman=true; + break; + } + + if (style->font_weight == CSS_FONT_WEIGHT_BOLD){ + strcat(font_name, "-Bold"); + bold = true; + } + + switch (style->font_style) { + case CSS_FONT_STYLE_ITALIC: + case CSS_FONT_STYLE_OBLIQUE: + if (!bold) + strcat(font_name,"-"); + if (roman) + strcat(font_name,"Italic"); + else + strcat(font_name,"Oblique"); + + styled = true; + break; + default: + break; + } + + if (roman && !styled && !bold) + strcat(font_name, "-Roman"); + +#ifdef FONT_HARU_DEBUG + 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; + *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; + HPDF_Page_SetFontAndSize(page, pdf_font, size); + } + + return true; +} + +#endif /* WITH_PDF_EXPORT */ + diff --git a/desktop/save_pdf/font_haru.h b/desktop/save_pdf/font_haru.h new file mode 100644 index 000000000..eca9855e6 --- /dev/null +++ b/desktop/save_pdf/font_haru.h @@ -0,0 +1,36 @@ +/* + * Copyright 2008 Adam Blokus + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + /** \file + * Font handling in Haru pdf documents (interface). + */ + +#ifndef _NETSURF_RENDER_FONT_HARU_H_ +#define _NETSURF_RENDER_FONT_HARU_H_ + +#include "render/font.h" +#include "hpdf.h" + +bool haru_nsfont_apply_style(const struct css_style *style, + HPDF_Doc doc, HPDF_Page page, + HPDF_Font *font); + +extern const struct font_functions haru_nsfont; +extern float pdf_scale; + +#endif diff --git a/desktop/save_pdf/pdf_plotters.c b/desktop/save_pdf/pdf_plotters.c new file mode 100644 index 000000000..10ddc10bf --- /dev/null +++ b/desktop/save_pdf/pdf_plotters.c @@ -0,0 +1,831 @@ +/* + * Copyright 2008 Adam Blokus + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + /** \file + * Target independent PDF plotting using Haru Free PDF Library. + */ + +#include "utils/config.h" +#ifdef WITH_PDF_EXPORT + +#include +#include +#include "hpdf.h" + +#include "desktop/options.h" +#include "desktop/plotters.h" +#include "desktop/print.h" +#include "desktop/printer.h" +#include "desktop/save_pdf/pdf_plotters.h" +#include "utils/log.h" +#include "utils/utils.h" +#include "image/bitmap.h" + +#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*/ + +static bool pdf_plot_clg(colour c); +static bool pdf_plot_rectangle(int x0, int y0, int width, int height, + int line_width, colour c, bool dotted, bool dashed); +static bool pdf_plot_line(int x0, int y0, int x1, int y1, int width, + colour c, bool dotted, bool dashed); +static bool pdf_plot_polygon(int *p, unsigned int n, colour fill); +static bool pdf_plot_fill(int x0, int y0, int x1, int y1, colour c); +static bool pdf_plot_clip(int clip_x0, int clip_y0, + int clip_x1, int clip_y1); +static bool pdf_plot_text(int x, int y, const struct css_style *style, + const char *text, size_t length, colour bg, colour c); +static bool pdf_plot_disc(int x, int y, int radius, colour c, bool filled); +static bool pdf_plot_arc(int x, int y, int radius, int angle1, int angle2, + colour c); +static bool pdf_plot_bitmap(int x, int y, int width, int height, + struct bitmap *bitmap, colour bg, struct content *content); +static bool pdf_plot_bitmap_tile(int x, int y, int width, int height, + struct bitmap *bitmap, colour bg, + bool repeat_x, bool repeat_y, struct content *content); +static bool pdf_plot_path(float *p, unsigned int n, colour fill, float width, + colour c, float *transform); + +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(void); + + +static void error_handler(HPDF_STATUS error_no, HPDF_STATUS detail_no, + void *user_data); + +#ifdef PDF_DEBUG +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; + +/*PDF Page size*/ +static HPDF_REAL page_height, page_width; + +/*Remeber if pdf_plot_clip was invoked for current page*/ +static bool page_clipped; +int last_clip_x0, last_clip_y0, last_clip_x1, last_clip_y1; + +bool in_text_mode, text_mode_request; + +static struct print_settings* settings; + +static const struct plotter_table pdf_plotters = { + pdf_plot_clg, + pdf_plot_rectangle, + pdf_plot_line, + pdf_plot_polygon, + pdf_plot_fill, + pdf_plot_clip, + pdf_plot_text, + pdf_plot_disc, + pdf_plot_arc, + pdf_plot_bitmap, + pdf_plot_bitmap_tile, + NULL, + NULL, + NULL, + pdf_plot_path, + false +}; + +struct printer pdf_printer= { + &pdf_plotters, + pdf_begin, + pdf_next_page, + pdf_end +}; + +float pdf_scale; +static char *owner_pass; +static char *user_pass; + +bool pdf_plot_clg(colour c) +{ + return true; +} + +bool pdf_plot_rectangle(int x0, int y0, int width, int height, + int line_width, colour c, bool dotted, bool dashed) +{ +#ifdef PDF_DEBUG + LOG((".")); +#endif + apply_clip_and_mode(); + + 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)); + HPDF_Page_Rectangle(pdf_page, x0, page_height - y0 + height, width, height); + HPDF_Page_Stroke(pdf_page); + + if (dotted||dashed) + pdf_set_solid(); + + return true; +} + +bool pdf_plot_line(int x0, int y0, int x1, int y1, int width, + colour c, bool dotted, bool dashed) +{ +#ifdef PDF_DEBUG + LOG((".")); +#endif + + apply_clip_and_mode(); + + 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); + 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; +} + +bool pdf_plot_polygon(int *p, unsigned int n, colour fill) +{ + int i; +#ifdef PDF_DEBUG + int pmaxx = p[0], pmaxy = p[1]; + int pminx = p[0], pminy = p[1]; + LOG((".")); +#endif + if (n == 0) + return true; + + apply_clip_and_mode(); + + HPDF_Page_SetRGBFill(pdf_page, R(fill), G(fill), B(fill)); + HPDF_Page_MoveTo(pdf_page, p[0], page_height - p[1]); + + for (i = 1 ; ifont_size.value.length.unit == CSS_UNIT_PX) + size = style->font_size.value.length.value; + else + size = css_len2pt(&style->font_size.value.length, style); + + /*this can be removed when export options get added for riscos*/ +#ifdef riscos + size *= DEFAULT_EXPORT_SCALE; +#else + size *= pdf_scale; +#endif + + 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) ); + 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); + + return true; +} + +bool pdf_plot_disc(int x, int y, int radius, colour c, bool filled) +{ +#ifdef PDF_DEBUG + LOG((".")); +#endif + apply_clip_and_mode(); + + 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)); + + HPDF_Page_Circle(pdf_page, x, page_height-y, radius); + + if (filled) + HPDF_Page_Fill(pdf_page); + else + HPDF_Page_Stroke(pdf_page); + + return true; +} + +bool pdf_plot_arc(int x, int y, int radius, int angle1, int angle2, colour c) +{ +#ifdef PDF_DEBUG + LOG(("%d %d %d %d %d %X", x, y, radius, angle1, angle2, c)); +#endif + + /*Normalize angles*/ + angle1 %= 360; + angle2 %= 360; + if (angle1 > angle2) + angle1 -= 360; + + apply_clip_and_mode(); + + 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); + return true; +} + +bool pdf_plot_bitmap(int x, int y, int width, int height, + struct bitmap *bitmap, colour bg, struct content *content) +{ + HPDF_Image image; + +#ifdef PDF_DEBUG + LOG(("%d %d %d %d %X %X %X", x, y, width, height, + bitmap, bg, content)); +#endif + if (width == 0 || height == 0) + return true; + + apply_clip_and_mode(); + + image = pdf_extract_image(bitmap, content); + + if (!image) + return false; + + HPDF_Page_DrawImage(pdf_page, image, + x, page_height-y-height, + width, height); + return true; + + +} + +bool pdf_plot_bitmap_tile(int x, int y, int width, int height, + struct bitmap *bitmap, colour bg, + bool repeat_x, bool repeat_y, struct content *content) +{ + HPDF_Image image; + +#ifdef PDF_DEBUG + LOG(("%d %d %d %d %X %X %X", x, y, width, height, + bitmap, bg, content)); +#endif + if (width == 0 || height == 0) + return true; + + apply_clip_and_mode(); + + image = pdf_extract_image(bitmap, content); + + if (image) { + /*The position of the next tile*/ + HPDF_REAL current_x, current_y ; + HPDF_REAL max_width, max_height; + + max_width = (repeat_x ? page_width : width); + max_height = (repeat_y ? page_height: height); + + + for (current_y=0; current_y < max_height; current_y += height) + for (current_x=0; current_x < max_width; current_x += width) + HPDF_Page_DrawImage(pdf_page, image, + current_x + x, + page_height-current_y - y - height, + width, height); + + return true; + } + else + return false; + + return true; +} + +HPDF_Image pdf_extract_image(struct bitmap *bitmap, struct content *content) +{ + HPDF_Image image = NULL,smask; + char *img_buffer, *rgb_buffer, *alpha_buffer; + int img_width, img_height, img_rowstride; + int i, j; + + if (content) { + /*Not sure if I don't have to check if downloading has been + finished. + Other way - lock pdf plotting while fetching a website + */ + switch(content->type){ + /*Handle "embeddable" types of images*/ + case CONTENT_JPEG: + image = HPDF_LoadJpegImageFromMem(pdf_doc, + content->source_data, + content->source_size); + break; + + /*Disabled until HARU PNG support will be more stable. + + case CONTENT_PNG: + image = HPDF_LoadPngImageFromMem(pdf_doc, + content->source_data, + content->total_size); + break;*/ + default: + break; + } + } + + if (!image) { + /*Handle pixmaps*/ + img_buffer = bitmap_get_buffer(bitmap); + img_width = bitmap_get_width(bitmap); + img_height = bitmap_get_height(bitmap); + img_rowstride = bitmap_get_rowstride(bitmap); + + rgb_buffer = (char*)malloc(3 * img_width * img_height); + if (rgb_buffer == NULL) { + LOG(("Not enough memory to create RGB buffer")); + return NULL; + } + + alpha_buffer = (char*)malloc(img_width * img_height); + if (alpha_buffer == NULL) { + LOG(("Not enough memory to create alpha buffer")); + free(rgb_buffer); + return NULL; + } + + + for (i = 0; ipage_width - settings->margins[MARGINLEFT] - + settings->margins[MARGINRIGHT]; + + page_height = settings->page_height - settings->margins[MARGINTOP]; + + + if (option_enable_PDF_compression) + HPDF_SetCompressionMode(pdf_doc, HPDF_COMP_ALL); /*Compression on*/ + + pdf_font = HPDF_GetFont (pdf_doc, "Times-Roman", "StandardEncoding"); + + pdf_page = NULL; + +#ifdef PDF_DEBUG + LOG(("pdf_begin finishes")); +#endif + return true; +} + + +bool pdf_next_page(void) +{ +#ifdef PDF_DEBUG + if (pdf_page != NULL) { + HPDF_Page_GRestore(pdf_page); + if (page_clipped) + HPDF_Page_GRestore(pdf_page); + pdf_plot_grid(10, 10, 0xCCCCCC); + pdf_plot_grid(100, 100, 0xCCCCFF); + } +#endif + pdf_page = HPDF_AddPage(pdf_doc); + if (pdf_page == NULL) + return false; + + 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); + + text_mode_request = false; + in_text_mode = false; + +#ifdef PDF_DEBUG + LOG(("%f %f", page_width, page_height)); +#endif + + return true; +} + + +void pdf_end(void) +{ + char *path; +#ifdef PDF_DEBUG + LOG(("pdf_end begins")); + if (pdf_page != NULL) { + HPDF_Page_GRestore(pdf_page); + if (page_clipped) + HPDF_Page_GRestore(pdf_page); + pdf_plot_grid(10, 10, 0xCCCCCC); + pdf_plot_grid(100, 100, 0xCCCCFF); + } +#endif + + if (settings->output != NULL) + path = strdup(settings->output); + else + path = NULL; + + /*Encryption on*/ + if (option_enable_PDF_password) + PDF_Password(&owner_pass, &user_pass, path); + else + save_pdf(path); +#ifdef PDF_DEBUG + LOG(("pdf_end finishes")); +#endif +} +/** saves the pdf optionally encrypting it before*/ +void save_pdf(char *path) +{ + bool success = false; + + if (option_enable_PDF_password && owner_pass != NULL ) { + HPDF_SetPassword(pdf_doc, owner_pass, user_pass); + HPDF_SetEncryptionMode(pdf_doc, HPDF_ENCRYPT_R3, 16); + free(owner_pass); + free(user_pass); + } + + if (path != NULL) { + if (HPDF_SaveToFile(pdf_doc, path) != HPDF_OK) + remove(path); + else + success = true; + + free(path); + } + + if (!success) + warn_user("Unable to save PDF file.", 0); + + HPDF_Free(pdf_doc); +} + + +/** + * Haru error handler + * for debugging purposes - it immediately exits the program on the first error, + * as it would otherwise flood the user with all resulting complications, + * covering the most important error source. +*/ +static void error_handler(HPDF_STATUS error_no, HPDF_STATUS detail_no, + void *user_data) +{ + LOG(("ERROR:\n\terror_no=%x\n\tdetail_no=%d\n", (HPDF_UINT)error_no, + (HPDF_UINT)detail_no)); +#ifdef PDF_DEBUG + exit(1); +#endif +} + +/** + * This function plots a grid - used for debug purposes to check if all + * elements' final coordinates are correct. +*/ +#ifdef PDF_DEBUG +void pdf_plot_grid(int x_dist, int y_dist, unsigned int colour) +{ + int i; + + for (int i = x_dist ; i < page_width ; i += x_dist) + pdf_plot_line(i, 0, i, page_height, 1, colour, false, false); + + for (int i = y_dist ; i < page_height ; i += x_dist) + pdf_plot_line(0, i, page_width, i, 1, colour, false, false); + +} +#endif + +/**used to synch the text scale with the scale for the whole content*/ +void pdf_set_scale(float s) +{ + pdf_scale = s; +} + +#endif /* WITH_PDF_EXPORT */ + diff --git a/desktop/save_pdf/pdf_plotters.h b/desktop/save_pdf/pdf_plotters.h new file mode 100644 index 000000000..ba815c552 --- /dev/null +++ b/desktop/save_pdf/pdf_plotters.h @@ -0,0 +1,44 @@ +/* + * Copyright 2008 Adam Blokus + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** \file + PDF Plotting +*/ + +#ifndef NETSURF_PDF_PLOTTERS_H +#define NETSURF_PDF_PLOTTERS_H + +#include "desktop/print.h" +struct plotter_table; + +extern struct printer pdf_printer; + +/**Start plotting a pdf file*/ +bool pdf_begin(struct print_settings* settings); + +/**Finish the current page and start a new one*/ +bool pdf_next_page(void); + +/**Close pdf document and save changes to file*/ +void pdf_end(void); + +void pdf_set_scale(float s); + +void save_pdf(char *path); + +#endif /*NETSURF_PDF_PLOTTERS_H*/ -- cgit v1.2.3