mirror of
https://github.com/netsurf-browser/netsurf
synced 2024-12-28 06:49:41 +03:00
6807b4208a
NetSurf includes are now done with ""s and other system includes with <>s as C intended. The scandeps tool has been updated to only look for ""ed includes, and to verify that the files exist in the tree before adding them to the dependency lines. The depend rule has therefore been augmented to make sure the autogenerated files are built before it is run. This is untested under self-hosted RISC OS builds. All else tested and works. svn path=/trunk/netsurf/; revision=3307
912 lines
24 KiB
C
912 lines
24 KiB
C
/*
|
|
* This file is part of NetSurf, http://netsurf-browser.org/
|
|
* Licensed under the GNU General Public License,
|
|
* http://www.opensource.org/licenses/gpl-license
|
|
* Copyright 2004 John M Bell <jmb202@ecs.soton.ac.uk>
|
|
* Copyright 2006 James Bursa <bursa@users.sourceforge.net>
|
|
*/
|
|
|
|
#include <assert.h>
|
|
#include <string.h>
|
|
#include "oslib/font.h"
|
|
#include "oslib/hourglass.h"
|
|
#include "oslib/osfile.h"
|
|
#include "oslib/osfind.h"
|
|
#include "oslib/pdriver.h"
|
|
#include "oslib/wimp.h"
|
|
#include "rufl.h"
|
|
#include "utils/config.h"
|
|
#include "content/content.h"
|
|
#include "desktop/plotters.h"
|
|
#include "render/box.h"
|
|
#include "render/font.h"
|
|
#include "render/html.h"
|
|
#include "render/layout.h"
|
|
#include "riscos/dialog.h"
|
|
#include "riscos/menus.h"
|
|
#include "riscos/print.h"
|
|
#include "riscos/wimp.h"
|
|
#include "riscos/wimp_event.h"
|
|
#include "utils/log.h"
|
|
#include "utils/messages.h"
|
|
#include "utils/utils.h"
|
|
|
|
|
|
#define ICON_PRINT_TO_BOTTOM 1
|
|
#define ICON_PRINT_SHEETS 2
|
|
#define ICON_PRINT_SHEETS_VALUE 3
|
|
#define ICON_PRINT_SHEETS_DOWN 4
|
|
#define ICON_PRINT_SHEETS_UP 5
|
|
#define ICON_PRINT_SHEETS_TEXT 6
|
|
#define ICON_PRINT_FG_IMAGES 7
|
|
#define ICON_PRINT_BG_IMAGES 8
|
|
#define ICON_PRINT_IN_BACKGROUND 9
|
|
#define ICON_PRINT_UPRIGHT 10
|
|
#define ICON_PRINT_SIDEWAYS 11
|
|
#define ICON_PRINT_COPIES 12
|
|
#define ICON_PRINT_COPIES_DOWN 13
|
|
#define ICON_PRINT_COPIES_UP 14
|
|
#define ICON_PRINT_CANCEL 15
|
|
#define ICON_PRINT_PRINT 16
|
|
#define ICON_PRINT_TEXT_BLACK 20
|
|
|
|
|
|
/** \todo landscape format pages
|
|
* \todo be somewhat more intelligent and try not to crop pages
|
|
* half way up a line of text
|
|
* \todo make use of print stylesheets
|
|
*/
|
|
|
|
struct gui_window *print_current_window = 0;
|
|
bool print_text_black = false;
|
|
bool print_active = false;
|
|
|
|
#ifdef WITH_PRINT
|
|
|
|
/* 1 millipoint == 1/400 OS unit == 1/800 browser units */
|
|
|
|
static int print_prev_message = 0;
|
|
static bool print_in_background = false;
|
|
static float print_scale = 1.0;
|
|
static int print_num_copies = 1;
|
|
static bool print_bg_images = false;
|
|
static int print_max_sheets = -1;
|
|
/** List of fonts in current print. */
|
|
static char **print_fonts_list = 0;
|
|
/** Number of entries in print_fonts_list. */
|
|
static unsigned int print_fonts_count;
|
|
/** Error in print_fonts_plot_text() or print_fonts_callback(). */
|
|
static const char *print_fonts_error;
|
|
|
|
|
|
static bool ro_gui_print_click(wimp_pointer *pointer);
|
|
static bool ro_gui_print_apply(wimp_w w);
|
|
static void print_update_sheets_shaded_state(bool on);
|
|
static void print_send_printsave(struct content *c);
|
|
static bool print_send_printtypeknown(wimp_message *m);
|
|
static bool print_document(struct gui_window *g, const char *filename);
|
|
static const char *print_declare_fonts(struct content *content);
|
|
static bool print_fonts_plot_clg(colour c);
|
|
static bool print_fonts_plot_rectangle(int x0, int y0, int width, int height,
|
|
int line_width, colour c, bool dotted, bool dashed);
|
|
static bool print_fonts_plot_line(int x0, int y0, int x1, int y1, int width,
|
|
colour c, bool dotted, bool dashed);
|
|
static bool print_fonts_plot_polygon(int *p, unsigned int n, colour fill);
|
|
static bool print_fonts_plot_fill(int x0, int y0, int x1, int y1, colour c);
|
|
static bool print_fonts_plot_clip(int clip_x0, int clip_y0,
|
|
int clip_x1, int clip_y1);
|
|
static bool print_fonts_plot_text(int x, int y, struct css_style *style,
|
|
const char *text, size_t length, colour bg, colour c);
|
|
static bool print_fonts_plot_disc(int x, int y, int radius, colour c,
|
|
bool filled);
|
|
static bool print_fonts_plot_arc(int x, int y, int radius, int angle1, int angle2,
|
|
colour c);
|
|
static bool print_fonts_plot_bitmap(int x, int y, int width, int height,
|
|
struct bitmap *bitmap, colour bg);
|
|
static bool print_fonts_plot_bitmap_tile(int x, int y, int width, int height,
|
|
struct bitmap *bitmap, colour bg,
|
|
bool repeat_x, bool repeat_y);
|
|
static bool print_fonts_plot_group_start(const char *name);
|
|
static bool print_fonts_plot_group_end(void);
|
|
static void print_fonts_callback(void *context,
|
|
const char *font_name, unsigned int font_size,
|
|
const char *s8, unsigned short *s16, unsigned int n,
|
|
int x, int y);
|
|
|
|
|
|
/** Plotter for print_declare_fonts(). All the functions do nothing except for
|
|
* print_fonts_plot_text, which records the fonts used. */
|
|
static const struct plotter_table print_fonts_plotters = {
|
|
print_fonts_plot_clg,
|
|
print_fonts_plot_rectangle,
|
|
print_fonts_plot_line,
|
|
print_fonts_plot_polygon,
|
|
print_fonts_plot_fill,
|
|
print_fonts_plot_clip,
|
|
print_fonts_plot_text,
|
|
print_fonts_plot_disc,
|
|
print_fonts_plot_arc,
|
|
print_fonts_plot_bitmap,
|
|
print_fonts_plot_bitmap_tile,
|
|
print_fonts_plot_group_start,
|
|
print_fonts_plot_group_end,
|
|
NULL
|
|
};
|
|
|
|
|
|
/**
|
|
* Initialise the print dialog.
|
|
*/
|
|
|
|
void ro_gui_print_init(void)
|
|
{
|
|
wimp_i radio_print_type[] = {ICON_PRINT_TO_BOTTOM, ICON_PRINT_SHEETS,
|
|
-1};
|
|
wimp_i radio_print_orientation[] = {ICON_PRINT_UPRIGHT,
|
|
ICON_PRINT_SIDEWAYS, -1};
|
|
|
|
dialog_print = ro_gui_dialog_create("print");
|
|
ro_gui_wimp_event_register_radio(dialog_print, radio_print_type);
|
|
ro_gui_wimp_event_register_radio(dialog_print, radio_print_orientation);
|
|
ro_gui_wimp_event_register_checkbox(dialog_print, ICON_PRINT_FG_IMAGES);
|
|
ro_gui_wimp_event_register_checkbox(dialog_print, ICON_PRINT_BG_IMAGES);
|
|
ro_gui_wimp_event_register_checkbox(dialog_print,
|
|
ICON_PRINT_IN_BACKGROUND);
|
|
ro_gui_wimp_event_register_checkbox(dialog_print,
|
|
ICON_PRINT_TEXT_BLACK);
|
|
ro_gui_wimp_event_register_text_field(dialog_print,
|
|
ICON_PRINT_SHEETS_TEXT);
|
|
ro_gui_wimp_event_register_numeric_field(dialog_print,
|
|
ICON_PRINT_COPIES, ICON_PRINT_COPIES_UP,
|
|
ICON_PRINT_COPIES_DOWN, 1, 99, 1, 0);
|
|
ro_gui_wimp_event_register_numeric_field(dialog_print,
|
|
ICON_PRINT_SHEETS_VALUE, ICON_PRINT_SHEETS_UP,
|
|
ICON_PRINT_SHEETS_DOWN, 1, 99, 1, 0);
|
|
ro_gui_wimp_event_register_cancel(dialog_print, ICON_PRINT_CANCEL);
|
|
ro_gui_wimp_event_register_mouse_click(dialog_print,
|
|
ro_gui_print_click);
|
|
ro_gui_wimp_event_register_ok(dialog_print, ICON_PRINT_PRINT,
|
|
ro_gui_print_apply);
|
|
ro_gui_wimp_event_set_help_prefix(dialog_print, "HelpPrint");
|
|
}
|
|
|
|
|
|
/**
|
|
* Prepares all aspects of the print dialog prior to opening.
|
|
*
|
|
* \param g parent window
|
|
*/
|
|
|
|
void ro_gui_print_prepare(struct gui_window *g)
|
|
{
|
|
char *desc;
|
|
bool printers_exists = true;
|
|
os_error *error;
|
|
|
|
assert(g);
|
|
|
|
print_current_window = g;
|
|
print_prev_message = 0;
|
|
|
|
/* Read Printer Driver name */
|
|
error = xpdriver_info(0, 0, 0, 0, &desc, 0, 0, 0);
|
|
if (error) {
|
|
LOG(("xpdriver_info: 0x%x: %s", error->errnum, error->errmess));
|
|
printers_exists = false;
|
|
}
|
|
|
|
print_bg_images = g->option.background_images;
|
|
|
|
ro_gui_set_icon_selected_state(dialog_print, ICON_PRINT_TO_BOTTOM,
|
|
true);
|
|
|
|
ro_gui_set_icon_selected_state(dialog_print, ICON_PRINT_SHEETS, false);
|
|
ro_gui_set_icon_integer(dialog_print, ICON_PRINT_SHEETS_VALUE, 1);
|
|
print_update_sheets_shaded_state(true);
|
|
|
|
ro_gui_set_icon_selected_state(dialog_print, ICON_PRINT_FG_IMAGES,
|
|
true);
|
|
ro_gui_set_icon_shaded_state(dialog_print, ICON_PRINT_FG_IMAGES, true);
|
|
|
|
ro_gui_set_icon_selected_state(dialog_print, ICON_PRINT_BG_IMAGES,
|
|
print_bg_images);
|
|
|
|
ro_gui_set_icon_selected_state(dialog_print, ICON_PRINT_IN_BACKGROUND,
|
|
false);
|
|
|
|
ro_gui_set_icon_selected_state(dialog_print, ICON_PRINT_UPRIGHT, true);
|
|
ro_gui_set_icon_selected_state(dialog_print, ICON_PRINT_SIDEWAYS,
|
|
false);
|
|
|
|
ro_gui_set_icon_selected_state(dialog_print, ICON_PRINT_TEXT_BLACK,
|
|
false);
|
|
|
|
ro_gui_set_icon_integer(dialog_print, ICON_PRINT_COPIES, 1);
|
|
|
|
ro_gui_set_icon_shaded_state(dialog_print, ICON_PRINT_PRINT,
|
|
!printers_exists);
|
|
if (printers_exists)
|
|
ro_gui_set_window_title(dialog_print, desc);
|
|
|
|
ro_gui_wimp_event_memorise(dialog_print);
|
|
}
|
|
|
|
|
|
/**
|
|
* Handle mouse clicks in print dialog
|
|
*
|
|
* \param pointer wimp_pointer block
|
|
*/
|
|
|
|
bool ro_gui_print_click(wimp_pointer *pointer)
|
|
{
|
|
if (pointer->buttons == wimp_CLICK_MENU)
|
|
return true;
|
|
|
|
switch (pointer->i) {
|
|
case ICON_PRINT_TO_BOTTOM:
|
|
case ICON_PRINT_SHEETS:
|
|
print_update_sheets_shaded_state(pointer->i !=
|
|
ICON_PRINT_SHEETS);
|
|
break;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
/**
|
|
* Handle click on the Print button in the print dialog.
|
|
*/
|
|
|
|
bool ro_gui_print_apply(wimp_w w)
|
|
{
|
|
int copies = atoi(ro_gui_get_icon_string(dialog_print,
|
|
ICON_PRINT_COPIES));
|
|
int sheets = atoi(ro_gui_get_icon_string(dialog_print,
|
|
ICON_PRINT_SHEETS_VALUE));
|
|
|
|
print_in_background = ro_gui_get_icon_selected_state(dialog_print,
|
|
ICON_PRINT_IN_BACKGROUND);
|
|
print_text_black = ro_gui_get_icon_selected_state(dialog_print,
|
|
ICON_PRINT_TEXT_BLACK);
|
|
print_num_copies = copies;
|
|
if (ro_gui_get_icon_selected_state(dialog_print, ICON_PRINT_SHEETS))
|
|
print_max_sheets = sheets;
|
|
else
|
|
print_max_sheets = -1;
|
|
print_current_window->option.background_images =
|
|
ro_gui_get_icon_selected_state(dialog_print,
|
|
ICON_PRINT_BG_IMAGES);
|
|
|
|
print_send_printsave(print_current_window->bw->current_content);
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
/**
|
|
* Set shaded state of sheets
|
|
*
|
|
* \param on whether to turn shading on or off
|
|
*/
|
|
|
|
void print_update_sheets_shaded_state(bool on)
|
|
{
|
|
ro_gui_set_icon_shaded_state(dialog_print, ICON_PRINT_SHEETS_VALUE, on);
|
|
ro_gui_set_icon_shaded_state(dialog_print, ICON_PRINT_SHEETS_DOWN, on);
|
|
ro_gui_set_icon_shaded_state(dialog_print, ICON_PRINT_SHEETS_UP, on);
|
|
ro_gui_set_icon_shaded_state(dialog_print, ICON_PRINT_SHEETS_TEXT, on);
|
|
ro_gui_set_caret_first(dialog_print);
|
|
}
|
|
|
|
|
|
/**
|
|
* Send a message_PRINT_SAVE
|
|
*
|
|
* \param c content to print
|
|
*/
|
|
|
|
void print_send_printsave(struct content *c)
|
|
{
|
|
wimp_full_message_data_xfer m;
|
|
os_error *e;
|
|
int len;
|
|
|
|
len = strlen(c->title) + 1;
|
|
if (212 < len)
|
|
len = 212;
|
|
|
|
m.size = ((44+len+3) & ~3);
|
|
m.your_ref = 0;
|
|
m.action = message_PRINT_SAVE;
|
|
m.w = (wimp_w)0;
|
|
m.i = m.pos.x = m.pos.y = 0;
|
|
m.est_size = 1024; /* arbitrary value - it really doesn't matter */
|
|
m.file_type = ro_content_filetype(c);
|
|
strncpy(m.file_name, c->title, 211);
|
|
m.file_name[211] = 0;
|
|
e = xwimp_send_message(wimp_USER_MESSAGE_RECORDED,
|
|
(wimp_message *)&m, 0);
|
|
if (e) {
|
|
LOG(("xwimp_send_message: 0x%x: %s",
|
|
e->errnum, e->errmess));
|
|
warn_user("WimpError", e->errmess);
|
|
print_cleanup();
|
|
}
|
|
print_prev_message = m.my_ref;
|
|
}
|
|
|
|
|
|
/**
|
|
* Send a message_PRINT_TYPE_KNOWN
|
|
*
|
|
* \param m message to reply to
|
|
* \return true on success, false otherwise
|
|
*/
|
|
|
|
bool print_send_printtypeknown(wimp_message *m)
|
|
{
|
|
os_error *e;
|
|
|
|
m->size = 20;
|
|
m->your_ref = m->my_ref;
|
|
m->action = message_PRINT_TYPE_KNOWN;
|
|
e = xwimp_send_message(wimp_USER_MESSAGE, m, m->sender);
|
|
if (e) {
|
|
LOG(("xwimp_send_message: 0x%x: %s",
|
|
e->errnum, e->errmess));
|
|
warn_user("WimpError", e->errmess);
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
/**
|
|
* Handle a bounced message_PRINT_SAVE
|
|
*
|
|
* \param m the bounced message
|
|
*/
|
|
|
|
void print_save_bounce(wimp_message *m)
|
|
{
|
|
if (m->my_ref == 0 || m->my_ref != print_prev_message)
|
|
return;
|
|
|
|
/* try to print anyway (we're graphics printing) */
|
|
if (print_current_window) {
|
|
print_document(print_current_window, "printer:");
|
|
}
|
|
print_cleanup();
|
|
}
|
|
|
|
|
|
/**
|
|
* Handle message_PRINT_ERROR
|
|
*
|
|
* \param m the message containing the error
|
|
*/
|
|
|
|
void print_error(wimp_message *m)
|
|
{
|
|
pdriver_message_print_error *p = (pdriver_message_print_error*)&m->data;
|
|
if (m->your_ref == 0 || m->your_ref != print_prev_message)
|
|
return;
|
|
|
|
if (m->size == 20)
|
|
warn_user("PrintErrorRO2", 0);
|
|
else
|
|
warn_user("PrintError", p->errmess);
|
|
|
|
print_cleanup();
|
|
}
|
|
|
|
|
|
/**
|
|
* Handle message_PRINT_TYPE_ODD
|
|
*
|
|
* \param m the message to handle
|
|
*/
|
|
|
|
void print_type_odd(wimp_message *m)
|
|
{
|
|
if ((m->your_ref == 0 || m->your_ref == print_prev_message) &&
|
|
!print_in_background) {
|
|
/* reply to a previous message (ie printsave) */
|
|
if (print_current_window && print_send_printtypeknown(m)) {
|
|
print_document(print_current_window, "printer:");
|
|
}
|
|
print_cleanup();
|
|
}
|
|
else {
|
|
/* broadcast message */
|
|
/* no need to do anything */
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/**
|
|
* Handle message_DATASAVE_ACK for the printing protocol.
|
|
*
|
|
* \param m the message to handle
|
|
* \return true if message successfully handled, false otherwise
|
|
*
|
|
* We cheat here and, instead of giving Printers what it asked for (a copy of
|
|
* the file so it can poke us later via a broadcast of PrintTypeOdd), we give
|
|
* it a file that it can print itself without having to bother us further. For
|
|
* PostScript printers (type 0) we give it a PostScript file. Otherwise, we give
|
|
* it a PrintOut file.
|
|
*
|
|
* This method has a couple of advantages:
|
|
* - we can reuse this code for background printing (we simply ignore the
|
|
* PrintTypeOdd reply)
|
|
* - there's no need to ensure all components of a page queued to be printed
|
|
* still exist when it reaches the top of the queue. (which reduces complexity
|
|
* a fair bit)
|
|
*/
|
|
|
|
bool print_ack(wimp_message *m)
|
|
{
|
|
pdriver_info_type info_type;
|
|
pdriver_type type;
|
|
os_error *error;
|
|
|
|
if (m->your_ref == 0 || m->your_ref != print_prev_message ||
|
|
!print_current_window)
|
|
return false;
|
|
|
|
/* read printer driver type */
|
|
error = xpdriver_info(&info_type, 0, 0, 0, 0, 0, 0, 0);
|
|
if (error) {
|
|
LOG(("xpdriver_info: 0x%x: %s",
|
|
error->errnum, error->errmess));
|
|
warn_user("PrintError", error->errmess);
|
|
print_cleanup();
|
|
return true;
|
|
}
|
|
type = info_type >> 16;
|
|
|
|
/* print to file */
|
|
if (!print_document(print_current_window,
|
|
m->data.data_xfer.file_name)) {
|
|
print_cleanup();
|
|
return true;
|
|
}
|
|
|
|
/* send dataload */
|
|
m->your_ref = m->my_ref;
|
|
m->action = message_DATA_LOAD;
|
|
|
|
if (type == pdriver_TYPE_PS)
|
|
m->data.data_xfer.file_type = osfile_TYPE_POSTSCRIPT;
|
|
else
|
|
m->data.data_xfer.file_type = osfile_TYPE_PRINTOUT;
|
|
|
|
error = xwimp_send_message(wimp_USER_MESSAGE_RECORDED, m, m->sender);
|
|
if (error) {
|
|
LOG(("xwimp_send_message: 0x%x: %s",
|
|
error->errnum, error->errmess));
|
|
warn_user("WimpError", error->errmess);
|
|
/* and delete temporary file */
|
|
xosfile_delete(m->data.data_xfer.file_name,
|
|
0, 0, 0, 0, 0);
|
|
}
|
|
print_prev_message = m->my_ref;
|
|
|
|
print_cleanup();
|
|
return true;
|
|
}
|
|
|
|
|
|
/**
|
|
* Handle a bounced dataload message
|
|
*
|
|
* \param m the message to handle
|
|
*/
|
|
|
|
void print_dataload_bounce(wimp_message *m)
|
|
{
|
|
if (m->your_ref == 0 || m->your_ref != print_prev_message)
|
|
return;
|
|
|
|
xosfile_delete(m->data.data_xfer.file_name, 0, 0, 0, 0, 0);
|
|
print_cleanup();
|
|
}
|
|
|
|
|
|
/**
|
|
* Cleanup after printing
|
|
*/
|
|
|
|
void print_cleanup(void)
|
|
{
|
|
if (print_current_window)
|
|
print_current_window->option.background_images =
|
|
print_bg_images;
|
|
print_current_window = 0;
|
|
print_text_black = false;
|
|
print_prev_message = 0;
|
|
print_max_sheets = -1;
|
|
ro_gui_menu_closed(true);
|
|
ro_gui_dialog_close(dialog_print);
|
|
}
|
|
|
|
|
|
/**
|
|
* Print a document.
|
|
*
|
|
* \param g gui_window containing the document to print
|
|
* \param filename name of file to print to
|
|
* \return true on success, false on error and error reported
|
|
*/
|
|
|
|
bool print_document(struct gui_window *g, const char *filename)
|
|
{
|
|
int left, right, top, bottom, width, height;
|
|
int saved_width, saved_height;
|
|
int yscroll = 0, sheets = print_max_sheets;
|
|
struct content *c = g->bw->current_content;
|
|
const char *error_message;
|
|
pdriver_features features;
|
|
os_fw fhandle, old_job = 0;
|
|
os_error *error;
|
|
|
|
/* no point printing a blank page */
|
|
if (!c) {
|
|
warn_user("PrintError", "nothing to print");
|
|
return false;
|
|
}
|
|
|
|
/* read printer driver features */
|
|
error = xpdriver_info(0, 0, 0, &features, 0, 0, 0, 0);
|
|
if (error) {
|
|
LOG(("xpdriver_info: 0x%x: %s",
|
|
error->errnum, error->errmess));
|
|
warn_user("PrintError", error->errmess);
|
|
return false;
|
|
}
|
|
|
|
/* read page size */
|
|
error = xpdriver_page_size(0, 0, &left, &bottom, &right, &top);
|
|
if (error) {
|
|
LOG(("xpdriver_page_size: 0x%x: %s",
|
|
error->errnum, error->errmess));
|
|
warn_user("PrintError", error->errmess);
|
|
return false;
|
|
}
|
|
|
|
width = (right - left) / 800;
|
|
height = (top - bottom) / 800;
|
|
|
|
/* layout the document to the correct width */
|
|
saved_width = c->width;
|
|
saved_height = c->height;
|
|
if (c->type == CONTENT_HTML)
|
|
layout_document(c, width, height);
|
|
|
|
/* open printer file */
|
|
error = xosfind_openoutw(osfind_NO_PATH | osfind_ERROR_IF_DIR |
|
|
osfind_ERROR_IF_ABSENT, filename, 0, &fhandle);
|
|
if (error) {
|
|
LOG(("xosfind_openoutw: 0x%x: %s",
|
|
error->errnum, error->errmess));
|
|
warn_user("PrintError", error->errmess);
|
|
return false;
|
|
}
|
|
|
|
/* select print job */
|
|
error = xpdriver_select_jobw(fhandle, "NetSurf", &old_job);
|
|
if (error) {
|
|
LOG(("xpdriver_select_jobw: 0x%x: %s",
|
|
error->errnum, error->errmess));
|
|
warn_user("PrintError", error->errmess);
|
|
xosfind_closew(fhandle);
|
|
return false;
|
|
}
|
|
|
|
rufl_invalidate_cache();
|
|
|
|
/* declare fonts, if necessary */
|
|
if (features & pdriver_FEATURE_DECLARE_FONT) {
|
|
if ((error_message = print_declare_fonts(c)))
|
|
goto error;
|
|
}
|
|
|
|
plot = ro_plotters;
|
|
ro_plot_set_scale(print_scale);
|
|
ro_gui_current_redraw_gui = g;
|
|
current_redraw_browser = NULL; /* we don't want to print the
|
|
selection */
|
|
|
|
/* print is now active */
|
|
print_active = true;
|
|
|
|
do {
|
|
int clip_x0, clip_y0, clip_x1, clip_y1;
|
|
os_box b = {left / 400 - 2, bottom / 400 - 2,
|
|
right / 400 + 2, top / 400 + 2};
|
|
os_hom_trfm t = { { {65536, 0}, {0, 65536} } };
|
|
os_coord p = {left, bottom};
|
|
osbool more;
|
|
|
|
xhourglass_percentage((int) (yscroll * 100 / c->height));
|
|
|
|
/* give page rectangle */
|
|
error = xpdriver_give_rectangle(0, &b, &t, &p, os_COLOUR_WHITE);
|
|
if (error) {
|
|
LOG(("xpdriver_give_rectangle: 0x%x: %s",
|
|
error->errnum, error->errmess));
|
|
error_message = error->errmess;
|
|
goto error;
|
|
}
|
|
|
|
LOG(("given rectangle: [(%d, %d), (%d, %d)]",
|
|
b.x0, b.y0, b.x1, b.y1));
|
|
|
|
/* and redraw the document */
|
|
error = xpdriver_draw_page(print_num_copies, &b, 0, 0,
|
|
&more, 0);
|
|
if (error) {
|
|
LOG(("xpdriver_draw_page: 0x%x: %s",
|
|
error->errnum, error->errmess));
|
|
error_message = error->errmess;
|
|
goto error;
|
|
}
|
|
|
|
ro_plot_origin_x = left / 400;
|
|
ro_plot_origin_y = top / 400 + yscroll * 2;
|
|
|
|
while (more) {
|
|
LOG(("redrawing area: [(%d, %d), (%d, %d)]",
|
|
b.x0, b.y0, b.x1, b.y1));
|
|
clip_x0 = (b.x0 - ro_plot_origin_x) / 2;
|
|
clip_y0 = (ro_plot_origin_y - b.y1) / 2;
|
|
clip_x1 = (b.x1 - ro_plot_origin_x) / 2;
|
|
clip_y1 = (ro_plot_origin_y - b.y0) / 2;
|
|
if (!content_redraw(c, 0, 0,
|
|
c->width, c->height,
|
|
clip_x0, clip_y0, clip_x1, clip_y1,
|
|
print_scale,
|
|
0xFFFFFF)) {
|
|
error_message = "redraw error";
|
|
goto error;
|
|
}
|
|
|
|
error = xpdriver_get_rectangle(&b, &more, 0);
|
|
if (error) {
|
|
LOG(("xpdriver_get_rectangle: 0x%x: %s",
|
|
error->errnum, error->errmess));
|
|
error_message = error->errmess;
|
|
goto error;
|
|
}
|
|
}
|
|
|
|
yscroll += height;
|
|
} while (yscroll <= c->height && --sheets != 0);
|
|
|
|
/* make print inactive */
|
|
print_active = false;
|
|
ro_gui_current_redraw_gui = 0;
|
|
|
|
/* clean up */
|
|
error = xpdriver_end_jobw(fhandle);
|
|
if (error) {
|
|
LOG(("xpdriver_end_jobw: 0x%x: %s",
|
|
error->errnum, error->errmess));
|
|
error_message = error->errmess;
|
|
goto error;
|
|
}
|
|
|
|
error = xosfind_closew(fhandle);
|
|
if (error) {
|
|
LOG(("xosfind_closew: 0x%x: %s",
|
|
error->errnum, error->errmess));
|
|
warn_user("PrintError", error->errmess);
|
|
return false;
|
|
}
|
|
|
|
if (old_job) {
|
|
error = xpdriver_select_jobw(old_job, 0, 0);
|
|
if (error) {
|
|
LOG(("xpdriver_select_jobw: 0x%x: %s",
|
|
error->errnum, error->errmess));
|
|
warn_user("PrintError", error->errmess);
|
|
/* the printing succeeded anyway */
|
|
return true;
|
|
}
|
|
}
|
|
|
|
rufl_invalidate_cache();
|
|
|
|
/* restore document layout */
|
|
if (c->type == CONTENT_HTML)
|
|
layout_document(c, saved_width, saved_height);
|
|
|
|
return true;
|
|
|
|
error:
|
|
xpdriver_abort_job(fhandle);
|
|
xosfind_closew(fhandle);
|
|
if (old_job)
|
|
xpdriver_select_jobw(old_job, 0, 0);
|
|
print_active = false;
|
|
ro_gui_current_redraw_gui = 0;
|
|
|
|
warn_user("PrintError", error_message);
|
|
|
|
rufl_invalidate_cache();
|
|
|
|
/* restore document layout */
|
|
if (c->type == CONTENT_HTML)
|
|
layout_document(c, saved_width, saved_height);
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
/**
|
|
* Declare fonts to the printer driver.
|
|
*
|
|
* \param c content being printed
|
|
* \return 0 on success, error message on error
|
|
*/
|
|
|
|
const char *print_declare_fonts(struct content *content)
|
|
{
|
|
unsigned int i;
|
|
const char *error_message = 0;
|
|
os_error *error;
|
|
|
|
free(print_fonts_list);
|
|
print_fonts_list = 0;
|
|
print_fonts_count = 0;
|
|
print_fonts_error = 0;
|
|
|
|
plot = print_fonts_plotters;
|
|
if (!content_redraw(content, 0, 0, content->width, content->height,
|
|
INT_MIN, INT_MIN, INT_MAX, INT_MAX, 1, 0xffffff)) {
|
|
if (print_fonts_error)
|
|
return print_fonts_error;
|
|
return "Declaring fonts failed.";
|
|
}
|
|
|
|
for (i = 0; i != print_fonts_count; ++i) {
|
|
LOG(("%u %s", i, print_fonts_list[i]));
|
|
error = xpdriver_declare_font(0, print_fonts_list[i],
|
|
pdriver_KERNED);
|
|
if (error) {
|
|
LOG(("xpdriver_declare_font: 0x%x: %s",
|
|
error->errnum, error->errmess));
|
|
error_message = error->errmess;
|
|
goto end;
|
|
}
|
|
}
|
|
error = xpdriver_declare_font(0, 0, 0);
|
|
if (error) {
|
|
LOG(("xpdriver_declare_font: 0x%x: %s",
|
|
error->errnum, error->errmess));
|
|
error_message = error->errmess;
|
|
goto end;
|
|
}
|
|
|
|
end:
|
|
for (i = 0; i != print_fonts_count; i++)
|
|
free(print_fonts_list[i]);
|
|
free(print_fonts_list);
|
|
print_fonts_list = 0;
|
|
|
|
return error_message;
|
|
}
|
|
|
|
|
|
bool print_fonts_plot_clg(colour c) { return true; }
|
|
bool print_fonts_plot_rectangle(int x0, int y0, int width, int height,
|
|
int line_width, colour c, bool dotted, bool dashed)
|
|
{ return true; }
|
|
bool print_fonts_plot_line(int x0, int y0, int x1, int y1, int width,
|
|
colour c, bool dotted, bool dashed) { return true; }
|
|
bool print_fonts_plot_polygon(int *p, unsigned int n, colour fill)
|
|
{ return true; }
|
|
bool print_fonts_plot_fill(int x0, int y0, int x1, int y1, colour c)
|
|
{ return true; }
|
|
bool print_fonts_plot_clip(int clip_x0, int clip_y0,
|
|
int clip_x1, int clip_y1) { return true; }
|
|
bool print_fonts_plot_disc(int x, int y, int radius, colour colour, bool filled)
|
|
{ return true; }
|
|
bool print_fonts_plot_arc(int x, int y, int radius, int angle1, int angle2,
|
|
colour c)
|
|
{ return true; }
|
|
bool print_fonts_plot_bitmap(int x, int y, int width, int height,
|
|
struct bitmap *bitmap, colour bg) { return true; }
|
|
bool print_fonts_plot_bitmap_tile(int x, int y, int width, int height,
|
|
struct bitmap *bitmap, colour bg,
|
|
bool repeat_x, bool repeat_y) { return true; }
|
|
bool print_fonts_plot_group_start(const char *name) { return true; }
|
|
bool print_fonts_plot_group_end(void) { return true; }
|
|
|
|
|
|
/**
|
|
* Plotter for text plotting during font listing.
|
|
*/
|
|
|
|
bool print_fonts_plot_text(int x, int y, struct css_style *style,
|
|
const char *text, size_t length, colour bg, colour c)
|
|
{
|
|
const char *font_family;
|
|
unsigned int font_size;
|
|
rufl_style font_style;
|
|
rufl_code code;
|
|
|
|
nsfont_read_style(style, &font_family, &font_size, &font_style);
|
|
|
|
code = rufl_paint_callback(font_family, font_style, font_size,
|
|
text, length, 0, 0, print_fonts_callback, 0);
|
|
if (code != rufl_OK) {
|
|
if (code == rufl_FONT_MANAGER_ERROR) {
|
|
LOG(("rufl_paint_callback: rufl_FONT_MANAGER_ERROR: "
|
|
"0x%x: %s",
|
|
rufl_fm_error->errnum,
|
|
rufl_fm_error->errmess));
|
|
print_fonts_error = rufl_fm_error->errmess;
|
|
} else {
|
|
LOG(("rufl_paint_callback: 0x%x", code));
|
|
}
|
|
return false;
|
|
}
|
|
if (print_fonts_error)
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
/**
|
|
* Callback for print_fonts_plot_text().
|
|
*
|
|
* The font name is added to print_fonts_list.
|
|
*/
|
|
|
|
void print_fonts_callback(void *context,
|
|
const char *font_name, unsigned int font_size,
|
|
const char *s8, unsigned short *s16, unsigned int n,
|
|
int x, int y)
|
|
{
|
|
unsigned int i;
|
|
char **fonts_list;
|
|
|
|
(void) context; /* unused */
|
|
(void) font_size; /* unused */
|
|
(void) x; /* unused */
|
|
(void) y; /* unused */
|
|
|
|
assert(s8 || s16);
|
|
|
|
/* check if the font name is new */
|
|
for (i = 0; i != print_fonts_count &&
|
|
strcmp(print_fonts_list[i], font_name) != 0; i++)
|
|
;
|
|
if (i != print_fonts_count)
|
|
return;
|
|
|
|
/* add to list of fonts */
|
|
fonts_list = realloc(print_fonts_list,
|
|
sizeof print_fonts_list[0] *
|
|
(print_fonts_count + 1));
|
|
if (!fonts_list) {
|
|
print_fonts_error = messages_get("NoMemory");
|
|
return;
|
|
}
|
|
fonts_list[print_fonts_count] = strdup(font_name);
|
|
if (!fonts_list[print_fonts_count]) {
|
|
print_fonts_error = messages_get("NoMemory");
|
|
return;
|
|
}
|
|
print_fonts_list = fonts_list;
|
|
print_fonts_count++;
|
|
}
|
|
|
|
|
|
#endif
|