74static bool pdf_plot_rectangle(
int x0,
int y0,
int x1,
int y1,
const plot_style_t *style);
75static bool pdf_plot_line(
int x0,
int y0,
int x1,
int y1,
const plot_style_t *pstyle);
76static bool pdf_plot_polygon(
const int *p,
unsigned int n,
const plot_style_t *style);
77static bool pdf_plot_clip(
const struct rect *
clip);
78static bool pdf_plot_text(
int x,
int y,
const char *
text,
size_t length,
80static bool pdf_plot_disc(
int x,
int y,
int radius,
const plot_style_t *style);
81static bool pdf_plot_arc(
int x,
int y,
int radius,
int angle1,
int angle2,
83static bool pdf_plot_bitmap_tile(
int x,
int y,
int width,
int height,
86static bool pdf_plot_path(
const float *p,
unsigned int n,
colour fill,
float width,
87 colour c,
const float transform[6]);
89static HPDF_Image pdf_extract_image(
struct bitmap *
bitmap);
91static void error_handler(HPDF_STATUS error_no, HPDF_STATUS detail_no,
94#ifdef PDF_DEBUG_DUMPGRID
95static void pdf_plot_grid(
int x_dist,
int y_dist,
unsigned int colour);
105static void pdfw_gs_init(
void);
106static void pdfw_gs_save(HPDF_Page page);
107static void pdfw_gs_restore(HPDF_Page page);
108static void pdfw_gs_fillcolour(HPDF_Page page,
colour col);
109static void pdfw_gs_strokecolour(HPDF_Page page,
colour col);
110static void pdfw_gs_linewidth(HPDF_Page page,
float lineWidth);
111static void pdfw_gs_font(HPDF_Page page, HPDF_Font font, HPDF_REAL font_size);
112static void pdfw_gs_dash(HPDF_Page page, DashPattern_e dash);
127static void apply_clip_and_mode(
bool selectTextMode,
colour fillCol,
128 colour strokeCol,
float lineWidth, DashPattern_e dash);
130#define PDFW_MAX_GSTATES 4
131static PDFW_GState pdfw_gs[PDFW_MAX_GSTATES];
132static unsigned int pdfw_gs_level;
134static HPDF_Doc pdf_doc;
135static HPDF_Page pdf_page;
138static HPDF_REAL page_height, page_width;
140static bool in_text_mode;
141static bool clip_update_needed;
143static int last_clip_x0, last_clip_y0, last_clip_x1, last_clip_y1;
149 .line = pdf_plot_line,
150 .polygon = pdf_plot_polygon,
151 .clip = pdf_plot_clip,
152 .text = pdf_plot_text,
153 .disc = pdf_plot_disc,
155 .bitmap = pdf_plot_bitmap_tile,
156 .path = pdf_plot_path,
157 .option_knockout =
false,
167static char *owner_pass;
168static char *user_pass;
170bool pdf_plot_rectangle(
int x0,
int y0,
int x1,
int y1,
const plot_style_t *pstyle)
174 NSLOG(netsurf, INFO,
"%d %d %d %d %f %X", x0, y0, x1, y1,
188 x0 =
min(
max(x0, 0), page_width);
189 y0 =
min(
max(y0, 0), page_height);
190 x1 =
min(
max(x1, 0), page_width);
191 y1 =
min(
max(y1, 0), page_height);
193 HPDF_Page_Rectangle(pdf_page, x0, page_height - y1, x1 - x0, y1 - y0);
194 HPDF_Page_Fill(pdf_page);
202 dash = DashPattern_eDotted;
206 dash = DashPattern_eDash;
210 dash = DashPattern_eNone;
215 apply_clip_and_mode(
false,
221 HPDF_Page_Rectangle(pdf_page, x0, page_height - y0, x1 - x0, -(y1 - y0));
222 HPDF_Page_Stroke(pdf_page);
228bool pdf_plot_line(
int x0,
int y0,
int x1,
int y1,
const plot_style_t *pstyle)
234 dash = DashPattern_eDotted;
238 dash = DashPattern_eDash;
242 dash = DashPattern_eNone;
247 apply_clip_and_mode(
false,
253 HPDF_Page_MoveTo(pdf_page, x0, page_height - y0);
254 HPDF_Page_LineTo(pdf_page, x1, page_height - y1);
255 HPDF_Page_Stroke(pdf_page);
260bool pdf_plot_polygon(
const int *p,
unsigned int n,
const plot_style_t *style)
264 int pmaxx = p[0], pmaxy = p[1];
265 int pminx = p[0], pminy = p[1];
266 NSLOG(netsurf, INFO,
".");
273 HPDF_Page_MoveTo(pdf_page, p[0], page_height - p[1]);
274 for (i = 1 ; i<n ; i++) {
275 HPDF_Page_LineTo(pdf_page, p[i*2], page_height - p[i*2+1]);
277 pmaxx =
max(pmaxx, p[i*2]);
278 pmaxy =
max(pmaxy, p[i*2+1]);
279 pminx =
min(pminx, p[i*2]);
280 pminy =
min(pminy, p[i*2+1]);
285 NSLOG(netsurf, INFO,
"%d %d %d %d %f", pminx, pminy, pmaxx, pmaxy,
286 page_height - pminy);
289 HPDF_Page_Fill(pdf_page);
296bool pdf_plot_clip(
const struct rect *
clip)
306 last_clip_x0 =
min(
max(
clip->x0, 0), page_width);
307 last_clip_y0 =
min(
max(
clip->y0, 0), page_height);
308 last_clip_x1 =
min(
max(
clip->x1, 0), page_width);
309 last_clip_y1 =
min(
max(
clip->y1, 0), page_height);
311 clip_update_needed =
true;
316bool pdf_plot_text(
int x,
int y,
const char *
text,
size_t length,
320 NSLOG(netsurf, INFO,
". %d %d %.*s", x, y, (
int)length,
text);
333 pdfw_gs_font(pdf_page, pdf_font, size);
337 word = (
char *)malloc(
sizeof(
char) * (length+1) );
340 memcpy(word,
text, length);
343 HPDF_Page_TextOut (pdf_page, x, page_height - y, word);
350bool pdf_plot_disc(
int x,
int y,
int radius,
const plot_style_t *style)
353 NSLOG(netsurf, INFO,
".");
356 apply_clip_and_mode(
false,
359 1., DashPattern_eNone);
361 HPDF_Page_Circle(pdf_page, x, page_height - y, radius);
363 HPDF_Page_Fill(pdf_page);
368 apply_clip_and_mode(
false,
371 1., DashPattern_eNone);
373 HPDF_Page_Circle(pdf_page, x, page_height - y, radius);
375 HPDF_Page_Stroke(pdf_page);
381bool pdf_plot_arc(
int x,
int y,
int radius,
int angle1,
int angle2,
const plot_style_t *style)
384 NSLOG(netsurf, INFO,
"%d %d %d %d %d %X", x, y, radius, angle1,
397 HPDF_Page_Arc(pdf_page, x, page_height - y, radius, angle1, angle2);
399 HPDF_Page_Stroke(pdf_page);
404bool pdf_plot_bitmap_tile(
int x,
int y,
int width,
int height,
409 HPDF_REAL current_x, current_y ;
410 HPDF_REAL max_width, max_height;
421 image = pdf_extract_image(
bitmap);
429 for (current_y = 0; current_y < max_height; current_y +=
height)
430 for (current_x = 0; current_x < max_width; current_x +=
width)
431 HPDF_Page_DrawImage(pdf_page, image,
433 page_height - current_y - y -
height,
441 HPDF_Image image = NULL;
447 const char *source_data;
448 unsigned long source_size;
459 image = HPDF_LoadJpegImageFromMem(pdf_doc,
460 (
const HPDF_BYTE *) source_data,
478 unsigned char *img_buffer, *rgb_buffer, *alpha_buffer;
479 int img_width, img_height, img_rowstride;
488 rgb_buffer = (
unsigned char *)malloc(3 * img_width * img_height);
489 alpha_buffer = (
unsigned char *)malloc(img_width * img_height);
490 if (rgb_buffer == NULL || alpha_buffer == NULL) {
492 "Not enough memory to create RGB buffer");
498 for (i = 0; i < img_height; i++)
499 for (j = 0; j < img_width; j++) {
500 rgb_buffer[((i * img_width) + j) * 3] =
501 img_buffer[(i * img_rowstride) + (j * 4)];
503 rgb_buffer[(((i * img_width) + j) * 3) + 1] =
504 img_buffer[(i * img_rowstride) + (j * 4) + 1];
506 rgb_buffer[(((i * img_width) + j) * 3) + 2] =
507 img_buffer[(i * img_rowstride) + (j * 4) + 2];
509 alpha_buffer[(i * img_width)+j] =
510 img_buffer[(i * img_rowstride) + (j * 4) + 3];
513 smask = HPDF_LoadRawImageFromMem(pdf_doc, alpha_buffer,
514 img_width, img_height,
515 HPDF_CS_DEVICE_GRAY, 8);
517 image = HPDF_LoadRawImageFromMem(pdf_doc, rgb_buffer,
518 img_width, img_height,
519 HPDF_CS_DEVICE_RGB, 8);
521 if (HPDF_Image_AddSMask(image, smask) != HPDF_OK)
545static void apply_clip_and_mode(
bool selectTextMode,
colour fillCol,
546 colour strokeCol,
float lineWidth, DashPattern_e dash)
556 if (in_text_mode && (!selectTextMode || clip_update_needed
558 && fillCol != pdfw_gs[pdfw_gs_level].fillColour)
563 HPDF_Page_EndText(pdf_page);
564 in_text_mode =
false;
567 if (clip_update_needed)
568 pdfw_gs_restore(pdf_page);
572 pdfw_gs_fillcolour(pdf_page, fillCol);
574 pdfw_gs_strokecolour(pdf_page, strokeCol);
575 pdfw_gs_linewidth(pdf_page, lineWidth);
576 pdfw_gs_dash(pdf_page, dash);
579 if (clip_update_needed) {
580 pdfw_gs_save(pdf_page);
582 HPDF_Page_Rectangle(pdf_page, last_clip_x0,
583 page_height - last_clip_y1,
584 last_clip_x1 - last_clip_x0,
585 last_clip_y1 - last_clip_y0);
586 HPDF_Page_Clip(pdf_page);
587 HPDF_Page_EndPath(pdf_page);
589 clip_update_needed =
false;
592 if (selectTextMode && !in_text_mode) {
593 HPDF_Page_BeginText(pdf_page);
598static inline float transform_x(
const float transform[6],
float x,
float y)
600 return transform[0] * x + transform[2] * y + transform[4];
603static inline float transform_y(
const float transform[6],
float x,
float y)
606 - (transform[1] * x + transform[3] * y + transform[5]);
609bool pdf_plot_path(
const float *p,
unsigned int n,
colour fill,
float width,
610 colour c,
const float transform[6])
616 NSLOG(netsurf, INFO,
".");
628 apply_clip_and_mode(
false, fill, c,
width, DashPattern_eNone);
631 for (i = 0 ; i < n ; ) {
633 HPDF_Page_MoveTo(pdf_page,
634 transform_x(transform, p[i+1], p[i+2]),
635 transform_y(transform, p[i+1], p[i+2]));
639 HPDF_Page_ClosePath(pdf_page);
642 HPDF_Page_LineTo(pdf_page,
643 transform_x(transform, p[i+1], p[i+2]),
644 transform_y(transform, p[i+1], p[i+2]));
648 HPDF_Page_CurveTo(pdf_page,
649 transform_x(transform, p[i+1], p[i+2]),
650 transform_y(transform, p[i+1], p[i+2]),
651 transform_x(transform, p[i+3], p[i+4]),
652 transform_y(transform, p[i+3], p[i+4]),
653 transform_x(transform, p[i+5], p[i+6]),
654 transform_y(transform, p[i+5], p[i+6]));
658 NSLOG(netsurf, INFO,
"bad path command %f", p[i]);
664 HPDF_Page_EndPath(pdf_page);
670 HPDF_Page_FillStroke(pdf_page);
672 HPDF_Page_Fill(pdf_page);
675 HPDF_Page_Stroke(pdf_page);
692 pdf_doc = HPDF_New(error_handler, NULL);
694 NSLOG(netsurf, INFO,
"Error creating pdf_doc");
709 if (option_enable_PDF_compression)
710 HPDF_SetCompressionMode(pdf_doc, HPDF_COMP_ALL);
717 NSLOG(netsurf, INFO,
"pdf_begin finishes");
726 NSLOG(netsurf, INFO,
"pdf_next_page begins");
728 clip_update_needed =
false;
729 if (pdf_page != NULL) {
732 pdfw_gs_restore(pdf_page);
735#ifdef PDF_DEBUG_DUMPGRID
736 if (pdf_page != NULL) {
737 pdf_plot_grid(10, 10, 0xCCCCCC);
738 pdf_plot_grid(100, 100, 0xCCCCFF);
741 pdf_page = HPDF_AddPage(pdf_doc);
742 if (pdf_page == NULL)
748 HPDF_Page_Concat(pdf_page, 1, 0, 0, 1,
751 pdfw_gs_save(pdf_page);
754 NSLOG(netsurf, INFO,
"%f %f", page_width, page_height);
764 NSLOG(netsurf, INFO,
"pdf_end begins");
766 clip_update_needed =
false;
767 if (pdf_page != NULL) {
770 pdfw_gs_restore(pdf_page);
773#ifdef PDF_DEBUG_DUMPGRID
774 if (pdf_page != NULL) {
775 pdf_plot_grid(10, 10, 0xCCCCCC);
776 pdf_plot_grid(100, 100, 0xCCCCFF);
783 if (option_enable_PDF_password)
789 NSLOG(netsurf, INFO,
"pdf_end finishes");
798 if (option_enable_PDF_password && owner_pass != NULL ) {
799 HPDF_SetPassword(pdf_doc, owner_pass, user_pass);
800 HPDF_SetEncryptionMode(pdf_doc, HPDF_ENCRYPT_R3, 16);
806 if (HPDF_SaveToFile(pdf_doc,
path) != HPDF_OK) {
825static void error_handler(HPDF_STATUS error_no, HPDF_STATUS detail_no,
828 NSLOG(netsurf, INFO,
"ERROR:\n\terror_no=%x\n\tdetail_no=%d\n",
829 (HPDF_UINT)error_no, (HPDF_UINT)detail_no);
839#ifdef PDF_DEBUG_DUMPGRID
840void pdf_plot_grid(
int x_dist,
int y_dist,
unsigned int colour)
842 for (
int i = x_dist ; i < page_width ; i += x_dist)
843 pdf_plot_line(i, 0, i, page_height, 1,
colour,
false,
false);
845 for (
int i = y_dist ; i < page_height ; i += x_dist)
846 pdf_plot_line(0, i, page_width, i, 1,
colour,
false,
false);
856 pdfw_gs[0].fillColour = 0x00000000;
857 pdfw_gs[0].strokeColour = 0x00000000;
858 pdfw_gs[0].lineWidth = 1.0;
859 pdfw_gs[0].font = NULL;
860 pdfw_gs[0].font_size = 0.;
861 pdfw_gs[0].dash = DashPattern_eNone;
868void pdfw_gs_save(HPDF_Page page)
870 if (pdfw_gs_level == PDFW_MAX_GSTATES)
872 pdfw_gs[pdfw_gs_level + 1] = pdfw_gs[pdfw_gs_level];
874 HPDF_Page_GSave(page);
882void pdfw_gs_restore(HPDF_Page page)
884 if (pdfw_gs_level == 0)
887 HPDF_Page_GRestore(page);
890#define RBYTE(x) (((x) & 0x0000FF) >> 0)
891#define GBYTE(x) (((x) & 0x00FF00) >> 8)
892#define BBYTE(x) (((x) & 0xFF0000) >> 16)
893#define R(x) (RBYTE(x) / 255.)
894#define G(x) (GBYTE(x) / 255.)
895#define B(x) (BBYTE(x) / 255.)
903void pdfw_gs_fillcolour(HPDF_Page page,
colour col)
905 if (col == pdfw_gs[pdfw_gs_level].fillColour)
907 pdfw_gs[pdfw_gs_level].fillColour = col;
908 if (RBYTE(col) == GBYTE(col) && GBYTE(col) == BBYTE(col))
909 HPDF_Page_SetGrayFill(pdf_page, R(col));
911 HPDF_Page_SetRGBFill(pdf_page, R(col), G(col), B(col));
920void pdfw_gs_strokecolour(HPDF_Page page,
colour col)
922 if (col == pdfw_gs[pdfw_gs_level].strokeColour)
924 pdfw_gs[pdfw_gs_level].strokeColour = col;
925 if (RBYTE(col) == GBYTE(col) && GBYTE(col) == BBYTE(col))
926 HPDF_Page_SetGrayStroke(pdf_page, R(col));
928 HPDF_Page_SetRGBStroke(pdf_page, R(col), G(col), B(col));
937void pdfw_gs_linewidth(HPDF_Page page,
float lineWidth)
939 if (lineWidth == pdfw_gs[pdfw_gs_level].lineWidth)
941 pdfw_gs[pdfw_gs_level].lineWidth = lineWidth;
942 HPDF_Page_SetLineWidth(page, lineWidth);
952void pdfw_gs_font(HPDF_Page page, HPDF_Font font, HPDF_REAL font_size)
954 if (font == pdfw_gs[pdfw_gs_level].font
955 && font_size == pdfw_gs[pdfw_gs_level].font_size)
957 pdfw_gs[pdfw_gs_level].font = font;
958 pdfw_gs[pdfw_gs_level].font_size = font_size;
959 HPDF_Page_SetFontAndSize(page, font, font_size);
968void pdfw_gs_dash(HPDF_Page page, DashPattern_e dash)
970 if (dash == pdfw_gs[pdfw_gs_level].dash)
972 pdfw_gs[pdfw_gs_level].dash = dash;
974 case DashPattern_eNone: {
975 HPDF_Page_SetDash(page, NULL, 0, 0);
978 case DashPattern_eDash: {
979 const HPDF_UINT16 dash_ptn[] = {3};
980 HPDF_Page_SetDash(page, dash_ptn, 1, 1);
983 case DashPattern_eDotted: {
984 const HPDF_UINT16 dash_ptn[] = {1};
985 HPDF_Page_SetDash(page, dash_ptn, 1, 1);
static size_t bitmap_get_rowstride(void *vbitmap)
Find the width of a pixel row in bytes.
Conception: Generalized output-in-pages.
nserror save_pdf(const char *path)
bool pdf_begin(struct print_settings *settings)
Start plotting a pdf file.
bool pdf_next_page(void)
Finish the current page and start a new one.
const struct printer pdf_printer
void pdf_end(void)
Close pdf document and save changes to file.
nserror
Enumeration of error codes.
@ NSERROR_SAVE_FAILED
Failed to save data.
@ NSERROR_NOT_IMPLEMENTED
Functionality is not implemented.
Font handling in Haru pdf documents (interface).
bool haru_nsfont_apply_style(const plot_font_style_t *fstyle, HPDF_Doc doc, HPDF_Page page, HPDF_Font *font, HPDF_REAL *font_size)
int bitmap_get_width(void *bitmap)
get width of a bitmap.
int bitmap_get_height(void *bitmap)
get height of a bitmap.
static unsigned char * bitmap_get_buffer(void *bitmap)
Return a pointer to the pixel data in a bitmap.
static struct print_settings * settings
struct netsurf_table * guit
The global interface table.
High-level resource cache interface.
Generic bitmap handling interface.
const uint8_t * content_get_source_data(struct hlcache_handle *h, size_t *size)
Retrieve source of content.
content_type content_get_type(struct hlcache_handle *h)
Retrieve computed type of content.
Target independent plotting interface.
unsigned long bitmap_flags_t
#define NSLOG(catname, level, logmsg, args...)
#define plot_style_int_to_fixed(v)
@ PLOT_OP_TYPE_NONE
No operation.
@ PLOT_OP_TYPE_DASH
Dashed plot.
@ PLOT_OP_TYPE_DOT
Dotted plot.
#define NS_TRANSPARENT
Transparent colour value.
Interface to utility string handling.
RISC OS wimp toolkit bitmap.
Content which corresponds to a single URL.
void(* pdf_password)(char **owner_pass, char **user_pass, char *path)
Prompt the user for a password for a PDF.
struct gui_misc_table * misc
Browser table.
colour foreground
Colour of text.
Plot style for stroke/fill plotters.
colour fill_colour
Colour of fill.
plot_style_fixed stroke_width
Width of stroke, in pixels.
plot_operation_type_t fill_type
Fill plot type.
colour stroke_colour
Colour of stroke.
plot_operation_type_t stroke_type
Stroke plot type.
Plotter operations table.
nserror(* rectangle)(const struct redraw_context *ctx, const plot_style_t *pstyle, const struct rect *rectangle)
Plots a rectangle.
Settings for a print - filled in by print_make_settings or 'manually' by the caller.
uint32_t colour
Colour type: XBGR.
const char * user_agent_string(void)
Retrieve the core user agent for this release.
Option reading and saving interface.
Interface to a number of general purpose functionality.
static nserror path(const struct redraw_context *ctx, const plot_style_t *pstyle, const float *p, unsigned int n, const float transform[6])
Plots a path.
static nserror text(const struct redraw_context *ctx, const struct plot_font_style *fstyle, int x, int y, const char *text, size_t length)
Text plotting.
static nserror clip(const struct redraw_context *ctx, const struct rect *clip)
Sets a clip rectangle for subsequent plot operations.