diff options
Diffstat (limited to 'src/paps.c')
-rw-r--r-- | src/paps.c | 186 |
1 files changed, 156 insertions, 30 deletions
@@ -18,6 +18,8 @@ * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. * + * + * This is so broken, I feel like crying... :-( */ @@ -30,7 +32,6 @@ #include <string.h> #include <time.h> #include <locale.h> -#include <wchar.h> #define BUFSIZE 1024 #define DEFAULT_FONT_FAMILY "Monospace" @@ -84,9 +85,13 @@ typedef struct { gboolean do_separation_line; gboolean do_draw_contour; gboolean do_wordwrap; + gboolean do_use_markup; + gboolean do_stretch_chars; PangoDirection pango_dir; gchar *filename; gchar *header_font_desc; + gint lpi; + gint cpi; } page_layout_t; typedef struct { @@ -141,8 +146,6 @@ static void start_page (FILE *OUT, static void draw_line_to_page (FILE *OUT, int column_idx, int column_pos, - gdouble scale_x, - gdouble scale_y, page_layout_t *page_layout, PangoLayoutLine *line); static int draw_page_header_line_to_page(FILE *OUT, @@ -165,7 +168,6 @@ double last_pos_y = -1; double last_pos_x = -1; paps_t *paps; paper_type_t paper_type = PAPER_TYPE_A4; -gdouble lpi = 0.0L, cpi = 0.0L; #define CASE(s) if (strcmp(S_, s) == 0) @@ -205,11 +207,12 @@ _paps_arg_lpi_cb(const gchar *option_name, { gboolean retval = TRUE; gchar *p = NULL; + page_layout_t *page_layout = (page_layout_t*)data; if (value && *value) { errno = 0; - lpi = g_strtod(value, &p); + page_layout->lpi = g_strtod(value, &p); if ((p && *p) || errno == ERANGE) { fprintf(stderr, "given LPI value was invalid.\n"); @@ -232,11 +235,12 @@ _paps_arg_cpi_cb(const gchar *option_name, { gboolean retval = TRUE; gchar *p = NULL; - + page_layout_t *page_layout = (page_layout_t*)data; + if (value && *value) { errno = 0; - cpi = g_strtod(value, &p); + page_layout->cpi = g_strtod(value, &p); if ((p && *p) || errno == ERANGE) { fprintf(stderr, "given CPI value was invalid.\n"); @@ -275,13 +279,18 @@ get_language(void) int main(int argc, char *argv[]) { gboolean do_landscape = FALSE, do_rtl = FALSE, do_justify = FALSE, do_draw_header = FALSE; - gboolean do_wordwrap = TRUE; + gboolean do_stretch_chars = FALSE; + gboolean do_use_markup = FALSE; + gboolean do_wordwrap = TRUE; // What should be default? int num_columns = 1; int top_margin = 36, bottom_margin = 36, right_margin = 36, left_margin = 36; gchar *font = MAKE_FONT_NAME (DEFAULT_FONT_FAMILY, DEFAULT_FONT_SIZE), *encoding = NULL; + page_layout_t page_layout; GOptionContext *ctxt = g_option_context_new("[text file]"); GOptionEntry entries[] = { {"landscape", 0, 0, G_OPTION_ARG_NONE, &do_landscape, "Landscape output. (Default: portrait)", NULL}, + {"stretch-chars", 0, 0, G_OPTION_ARG_NONE, &do_stretch_chars, "Whether to stretch characters in y-direction to fill lines. (Default: no)", NULL}, + {"markup", 0, 0, G_OPTION_ARG_NONE, &do_use_markup, "Should the text be considered pango markup? (Default: no)", NULL}, {"columns", 0, 0, G_OPTION_ARG_INT, &num_columns, "Number of columns output. (Default: 1)", "NUM"}, {"font", 0, 0, G_OPTION_ARG_STRING, &font, "Set the font description. (Default: Monospace 12)", "DESC"}, {"rtl", 0, 0, G_OPTION_ARG_NONE, &do_rtl, "Do rtl layout.", NULL}, @@ -298,10 +307,10 @@ int main(int argc, char *argv[]) {"lpi", 0, 0, G_OPTION_ARG_CALLBACK, _paps_arg_lpi_cb, "Set the amount of lines per inch.", "REAL"}, {"cpi", 0, 0, G_OPTION_ARG_CALLBACK, _paps_arg_cpi_cb, "Set the amount of characters per inch.", "REAL"}, {NULL} + }; GError *error = NULL; FILE *IN, *OUT = NULL; - page_layout_t page_layout; GList *paragraphs; GList *pango_lines; PangoContext *pango_context; @@ -323,11 +332,20 @@ int main(int argc, char *argv[]) int header_sep = 20; int max_width = 0, w; GIConv cvh = NULL; + GOptionGroup *options; /* Prerequisite when using glib. */ g_type_init(); - + + /* Init page_layout_t parameters set by the option parsing */ + page_layout.cpi = page_layout.lpi = 0; + + options = g_option_group_new("main","","",&page_layout, NULL); + g_option_group_add_entries(options, entries); + g_option_context_set_main_group(ctxt, options); +#if 0 g_option_context_add_main_entries(ctxt, entries, NULL); +#endif /* Parse command line */ if (!g_option_context_parse(ctxt, &argc, &argv, &error)) @@ -430,6 +448,8 @@ int main(int argc, char *argv[]) page_layout.do_separation_line = TRUE; page_layout.do_landscape = do_landscape; page_layout.do_justify = do_justify; + page_layout.do_stretch_chars = do_stretch_chars; + page_layout.do_use_markup = do_use_markup; page_layout.do_tumble = do_tumble; page_layout.do_duplex = do_duplex; page_layout.pango_dir = pango_dir; @@ -437,8 +457,9 @@ int main(int argc, char *argv[]) page_layout.header_font_desc = header_font_desc; /* calculate x-coordinate scale */ - if (cpi > 0.0L) + if (page_layout.cpi > 0.0L) { + double scale; fontmap = pango_ft2_font_map_new (); fontset = pango_font_map_load_fontset (fontmap, pango_context, font_description, get_language ()); metrics = pango_fontset_get_metrics (fontset); @@ -446,11 +467,24 @@ int main(int argc, char *argv[]) w = pango_font_metrics_get_approximate_digit_width (metrics); if (w > max_width) max_width = w; - page_layout.scale_x = 1 / cpi * 72.0 * PANGO_SCALE / max_width; + page_layout.scale_x = 1 / page_layout.cpi * 72.0 * PANGO_SCALE / max_width; pango_font_metrics_unref (metrics); g_object_unref (G_OBJECT (fontmap)); + + // Now figure out how to scale the font to get that size + scale = 1 / page_layout.cpi * 72.0 * PANGO_SCALE / max_width; + + fprintf(stderr, "scale = %f\n", scale); + + // update the font size to that width + pango_font_description_set_size (font_description, (int)(atoi(DEFAULT_FONT_SIZE) * PANGO_SCALE * scale)); + pango_context_set_font_description (pango_context, font_description); + } + page_layout.scale_x = page_layout.scale_y = 1.0; + + if (encoding != NULL) { cvh = g_iconv_open ("UTF-8", encoding); @@ -471,7 +505,7 @@ int main(int argc, char *argv[]) page_layout.column_width * page_layout.pt_to_pixel, text); pango_lines = split_paragraphs_into_lines(&page_layout, paragraphs); - + if (OUT == NULL) OUT = stdout; @@ -550,7 +584,11 @@ read_file (FILE *file, return text; } -/* Take a UTF8 string and break it into paragraphs on \n characters +#if 0 +/* Take a UTF8 string and break it into paragraphs on \n characters. + * + * Sorry. I couldn't figure out what this version was supposed to do + * */ static GList * split_text_into_paragraphs (PangoContext *pango_context, @@ -587,14 +625,14 @@ split_text_into_paragraphs (PangoContext *pango_context, gchar *newtext; size_t i, len, wwidth = 0, n; - wtext = (wchar_t *)g_utf8_to_ucs4 (para->text, para->length, NULL, NULL, NULL); + wtext = g_utf8_to_ucs4 (para->text, para->length, NULL, NULL, NULL); if (wtext == NULL) { fprintf (stderr, "Failed to convert UTF-8 to UCS-4.\n"); return NULL; } - len = wcswidth (wtext); + len = g_utf8_strlen (para->text, para->length); /* the amount of characters to be able to put on the line against CPI */ n = page_layout->column_width / 72.0 * cpi; if (len > n) @@ -657,6 +695,94 @@ split_text_into_paragraphs (PangoContext *pango_context, return g_list_reverse (result); } +#endif + +/* Take a UTF8 string and break it into paragraphs on \n characters + */ +static GList * +split_text_into_paragraphs (PangoContext *pango_context, + page_layout_t *page_layout, + int paint_width, /* In pixels */ + char *text) +{ + char *p = text; + char *next; + gunichar wc; + GList *result = NULL; + char *last_para = text; + + /* If we are using markup we treat the entire text as a single paragraph. + * I tested it and found that this is much slower than the split and + * assign method used below. Otherwise we might as well use this single + * chunk method always. + */ + if (page_layout->do_use_markup) + { + Paragraph *para = g_new (Paragraph, 1); + para->text = text; + para->length = strlen(text); + para->layout = pango_layout_new (pango_context); + // pango_layout_set_font_description (para->layout, font_description); + pango_layout_set_markup (para->layout, para->text, para->length); + pango_layout_set_justify (para->layout, page_layout->do_justify); + pango_layout_set_alignment (para->layout, + page_layout->pango_dir == PANGO_DIRECTION_LTR + ? PANGO_ALIGN_LEFT : PANGO_ALIGN_RIGHT); + pango_layout_set_wrap (para->layout, PANGO_WRAP_WORD_CHAR); + + pango_layout_set_width (para->layout, paint_width * PANGO_SCALE); + para->height = 0; + + result = g_list_prepend (result, para); + } + else + { + + while (p != NULL && *p) + { + wc = g_utf8_get_char (p); + next = g_utf8_next_char (p); + if (wc == (gunichar)-1) + { + fprintf (stderr, "%s: Invalid character in input\n", g_get_prgname ()); + wc = 0; + } + if (!*p || !wc || wc == '\n' || wc == '\f') + { + Paragraph *para = g_new (Paragraph, 1); + para->text = last_para; + para->length = p - last_para; + para->layout = pango_layout_new (pango_context); + // pango_layout_set_font_description (para->layout, font_description); + pango_layout_set_text (para->layout, para->text, para->length); + pango_layout_set_justify (para->layout, page_layout->do_justify); + pango_layout_set_alignment (para->layout, + page_layout->pango_dir == PANGO_DIRECTION_LTR + ? PANGO_ALIGN_LEFT : PANGO_ALIGN_RIGHT); + pango_layout_set_wrap (para->layout, PANGO_WRAP_WORD_CHAR); + + pango_layout_set_width (para->layout, paint_width * PANGO_SCALE); + para->height = 0; + + last_para = next; + + if (wc == '\f') + para->formfeed = 1; + else + para->formfeed = 0; + + result = g_list_prepend (result, para); + } + if (!wc) /* incomplete character at end */ + break; + p = next; + } + } + + return g_list_reverse (result); +} + + /* Split a list of paragraphs into a list of lines. */ @@ -700,8 +826,9 @@ split_paragraphs_into_lines(page_layout_t *page_layout, par_list = par_list->next; } - if (lpi > 0.0L) - page_layout->scale_y = 1 / lpi * 72.0 * page_layout->pt_to_pixel * PANGO_SCALE / max_height; + + if (page_layout->do_stretch_chars && page_layout->lpi > 0.0L) + page_layout->scale_y = 1.0 / page_layout->lpi * 72.0 * page_layout->pt_to_pixel * PANGO_SCALE / max_height; return g_list_reverse(line_list); @@ -758,14 +885,13 @@ output_pages(FILE *OUT, draw_line_to_page(OUT, column_idx, column_y_pos+line_link->logical_rect.height, - page_layout->scale_x, page_layout->scale_y, page_layout, line); - if (lpi > 0.0L) - column_y_pos += (1 / lpi * 72.0 * page_layout->pt_to_pixel * PANGO_SCALE); + if (page_layout->lpi > 0.0L) + column_y_pos += (int)(1.0 / page_layout->lpi * 72.0 * page_layout->pt_to_pixel * PANGO_SCALE); else - column_y_pos += line_link->logical_rect.height; + column_y_pos += line_link->logical_rect.height; pango_lines = pango_lines->next; prev_line_link = line_link; @@ -796,7 +922,7 @@ void print_postscript_header(FILE *OUT, fprintf(OUT, "%%!PS-Adobe-3.0\n" "%%%%Title: %s\n" - "%%%%Creator: paps version 0.6.3 by Dov Grobgeld\n" + "%%%%Creator: paps version 0.6.7 by Dov Grobgeld\n" "%%%%Pages: (atend)\n" "%%%%BoundingBox: 0 0 %d %d\n" "%%%%BeginProlog\n" @@ -918,6 +1044,8 @@ void print_postscript_header(FILE *OUT, " papsdict begin\n" " gsave\n" " do_landscape {turnpage} if \n" + " %% ps2pdf gets wrong orientation without this!\n" + " /Helvetica findfont setfont 100 100 moveto ( ) show\n" " firstcolumn\n" " end\n" "} def\n" @@ -957,7 +1085,7 @@ void eject_column(FILE *OUT, if (column_idx == 1) total_gutter = 1.0 * page_layout->gutter_width /2; else - total_gutter = (column_idx + 1.5) * page_layout->gutter_width; + total_gutter = (column_idx - 0.5) * page_layout->gutter_width; x_pos = page_layout->left_margin + page_layout->column_width * column_idx @@ -992,8 +1120,6 @@ void draw_line_to_page(FILE *OUT, int column_idx, int column_pos, - gdouble scale_x, - gdouble scale_y, page_layout_t *page_layout, PangoLayoutLine *line) { @@ -1026,9 +1152,9 @@ draw_line_to_page(FILE *OUT, x_pos += page_layout->column_width - logical_rect.width / (page_layout->pt_to_pixel * PANGO_SCALE); } + paps_set_scale(paps, page_layout->scale_x, page_layout->scale_y); ps_layout = paps_layout_line_to_postscript_strdup(paps, x_pos, y_pos, - scale_x, scale_y, line); g_string_append(ps_pages_string, @@ -1088,9 +1214,9 @@ draw_page_header_line_to_page(FILE *OUT, y_pos = page_layout->page_height - page_layout->top_margin - height; page_layout->header_height = height; } + paps_set_scale(paps, page_layout->scale_x, page_layout->scale_y); ps_layout = paps_layout_line_to_postscript_strdup(paps, x_pos, y_pos, - page_layout->scale_x, page_layout->scale_y, line); g_string_append(ps_pages_string, ps_layout); @@ -1102,9 +1228,9 @@ draw_page_header_line_to_page(FILE *OUT, &ink_rect, &logical_rect); x_pos = (page_layout->page_width - (logical_rect.width / PANGO_SCALE * page_layout->pixel_to_pt)) / 2; + paps_set_scale(paps, page_layout->scale_x, page_layout->scale_y); ps_layout = paps_layout_line_to_postscript_strdup(paps, x_pos, y_pos, - page_layout->scale_x, page_layout->scale_y, line); g_string_append(ps_pages_string, ps_layout); @@ -1116,9 +1242,9 @@ draw_page_header_line_to_page(FILE *OUT, &ink_rect, &logical_rect); x_pos = page_layout->page_width - page_layout->right_margin - (logical_rect.width / PANGO_SCALE * page_layout->pixel_to_pt); + paps_set_scale(paps, page_layout->scale_x, page_layout->scale_y); ps_layout = paps_layout_line_to_postscript_strdup(paps, x_pos, y_pos, - page_layout->scale_x, page_layout->scale_y, line); g_string_append(ps_pages_string, ps_layout); |