source: trunk/third/gtkhtml3/src/htmlprinter.c @ 21460

Revision 21460, 30.8 KB checked in by ghudson, 20 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r21459, which included commits to RCS files with non-trunk default branches.
Line 
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2/* This file is part of the GtkHTML library.
3
4   Copyright (C) 2000 Helix Code, Inc.
5   
6   This library is free software; you can redistribute it and/or
7   modify it under the terms of the GNU Library General Public
8   License as published by the Free Software Foundation; either
9   version 2 of the License, or (at your option) any later version.
10   
11   This library is distributed in the hope that it will be useful,
12   but WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14   Library General Public License for more details.
15   
16   You should have received a copy of the GNU Library General Public License
17   along with this library; see the file COPYING.LIB.  If not, write to
18   the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19   Boston, MA 02111-1307, USA.
20*/
21
22#include <config.h>
23#include "gtkhtml-compat.h"
24
25#include <string.h>
26#include <gnome.h>
27#include <ctype.h>
28#include <libgnomeprint/gnome-print.h>
29#include <libgnomeprint/gnome-print-paper.h>
30
31#include "htmlembedded.h"
32#include "htmlentity.h"
33#include "gtkhtml-embedded.h"
34#include "htmlfontmanager.h"
35#include "htmlprinter.h"
36#include "htmltext.h"
37
38/* #define PRINTER_DEBUG */
39
40
41static HTMLPainterClass *parent_class = NULL;
42
43
44/* The size of a pixel in the printed output, in points.  */
45#define PIXEL_SIZE .5
46
47static void
48insure_config (HTMLPrinter *p)
49{
50        if (!p->config)
51                p->config = p->master ? gnome_print_job_get_config (p->master) : gnome_print_config_default ();
52}
53
54static gdouble
55printer_get_page_height (HTMLPrinter *printer)
56{
57        gdouble width, height = 0.0;
58
59        insure_config (printer);
60        gnome_print_config_get_page_size (printer->config, &width, &height);
61
62        return height;
63}
64
65static gdouble
66printer_get_page_width (HTMLPrinter *printer)
67{
68        gdouble width = 0.0, height;
69
70        insure_config (printer);
71        gnome_print_config_get_page_size (printer->config, &width, &height);
72
73        return width;
74}
75
76/* .5" in PS units */
77#define TEMP_MARGIN 72*.5
78
79static gdouble
80get_lmargin (HTMLPrinter *printer)
81{
82        /*gdouble lmargin = 0.0;
83
84        insure_config (printer);
85        gnome_print_config_get_double (printer->config, GNOME_PRINT_KEY_PAGE_MARGIN_LEFT, &lmargin);
86
87        printf ("lmargin %f\n", lmargin);
88        return lmargin;*/
89
90        return TEMP_MARGIN;
91}
92
93static gdouble
94get_rmargin (HTMLPrinter *printer)
95{
96        /*gdouble rmargin = 0.0;
97
98        insure_config (printer);
99        gnome_print_config_get_double (printer->config, GNOME_PRINT_KEY_PAGE_MARGIN_RIGHT, &rmargin);
100
101        return rmargin;*/
102
103        return TEMP_MARGIN;
104}
105
106static gdouble
107get_tmargin (HTMLPrinter *printer)
108{
109        /* gdouble tmargin = 0.0;
110
111        insure_config (printer);
112        gnome_print_config_get_double (printer->config, GNOME_PRINT_KEY_PAGE_MARGIN_TOP, &tmargin);
113
114        return tmargin; */
115
116        return TEMP_MARGIN;
117}
118
119static gdouble
120get_bmargin (HTMLPrinter *printer)
121{
122        /* gdouble bmargin = 0.0;
123
124        insure_config (printer);
125        gnome_print_config_get_double (printer->config, GNOME_PRINT_KEY_PAGE_MARGIN_BOTTOM, &bmargin);
126
127        return bmargin; */
128
129        return TEMP_MARGIN;
130}
131
132gdouble
133html_printer_scale_to_gnome_print (HTMLPrinter *printer, gint x)
134{
135        return SCALE_ENGINE_TO_GNOME_PRINT (x);
136}
137
138void
139html_printer_coordinates_to_gnome_print (HTMLPrinter *printer,
140                                         gint engine_x, gint engine_y,
141                                         gdouble *print_x_return, gdouble *print_y_return)
142{
143        gdouble print_x, print_y;
144
145        print_x = SCALE_ENGINE_TO_GNOME_PRINT (engine_x);
146        print_y = SCALE_ENGINE_TO_GNOME_PRINT (engine_y);
147
148        print_x = print_x + get_lmargin (printer);
149        print_y = (printer_get_page_height (printer) - print_y) - get_tmargin (printer);
150
151        *print_x_return = print_x;
152        *print_y_return = print_y;
153}
154
155#if 0
156static void
157gnome_print_coordinates_to_engine (HTMLPrinter *printer,
158                                   gdouble print_x, gdouble print_y,
159                                   gint *engine_x_return, gint *engine_y_return)
160{
161        print_x -= get_lmargin (printer);
162        print_y -= get_bmargin (printer);
163
164        *engine_x_return = SCALE_ENGINE_TO_GNOME_PRINT (print_x);
165        *engine_y_return = SCALE_GNOME_PRINT_TO_ENGINE (get_page_height (printer) - print_y);
166}
167#endif
168
169
170/* GtkObject methods.  */
171
172static void
173finalize (GObject *object)
174{
175        HTMLPrinter *printer;
176
177        printer = HTML_PRINTER (object);
178
179        if (printer->config != NULL) {
180                /* FIXME g_object_unref (printer->config); */
181                printer->config = NULL;
182        }
183        if (printer->context != NULL) {
184                gnome_print_context_close (printer->context);
185                g_object_unref (printer->context);
186                printer->context = NULL;
187        }
188
189        (* G_OBJECT_CLASS (parent_class)->finalize) (object);
190}
191
192
193static void
194begin (HTMLPainter *painter,
195       int x1, int y1,
196       int x2, int y2)
197{
198        HTMLPrinter *printer;
199        GnomePrintContext *pc;
200        gdouble printer_x1, printer_y1;
201        gdouble printer_x2, printer_y2;
202#ifdef PRINTER_DEBUG
203        gdouble dash [2];
204#endif
205        printer = HTML_PRINTER (painter);
206        g_return_if_fail (printer);
207        pc      = printer->context;
208        g_return_if_fail (pc);
209
210        gnome_print_beginpage (pc, "page");
211        gnome_print_gsave (pc);
212
213        html_printer_coordinates_to_gnome_print (printer, x1, y1, &printer_x1, &printer_y1);
214        printer_x2 = printer_x1 + SCALE_ENGINE_TO_GNOME_PRINT (x2);
215        printer_y2 = printer_y1 - SCALE_ENGINE_TO_GNOME_PRINT (y2);
216
217        gnome_print_newpath (pc);
218
219        gnome_print_moveto (pc, printer_x1, printer_y1);
220        gnome_print_lineto (pc, printer_x1, printer_y2);
221        gnome_print_lineto (pc, printer_x2, printer_y2);
222        gnome_print_lineto (pc, printer_x2, printer_y1);
223        gnome_print_lineto (pc, printer_x1, printer_y1);
224        gnome_print_closepath (pc);
225
226#ifdef PRINTER_DEBUG
227        gnome_print_gsave (pc);
228        dash [0] = 10.0;
229        dash [1] = 10.0;
230        gnome_print_setrgbcolor (pc, .5, .5, .5);
231        gnome_print_setlinewidth (pc, .3);
232        gnome_print_setdash (pc, 2, dash, .0);
233        gnome_print_stroke (pc);
234        gnome_print_grestore (pc);
235#endif
236        gnome_print_clip (pc);
237}
238
239static void
240end (HTMLPainter *painter)
241{
242        HTMLPrinter *printer;
243
244        printer = HTML_PRINTER (painter);
245        g_return_if_fail (printer->context != NULL);
246
247        gnome_print_grestore (printer->context);
248        gnome_print_showpage (printer->context);
249}
250
251static void
252clear (HTMLPainter *painter)
253{
254}
255
256
257static void
258alloc_color (HTMLPainter *painter, GdkColor *color)
259{
260}
261
262static void
263free_color (HTMLPainter *painter, GdkColor *color)
264{
265}
266
267
268static void
269set_pen (HTMLPainter *painter,
270         const GdkColor *color)
271{
272        HTMLPrinter *printer;
273
274        printer = HTML_PRINTER (painter);
275        g_return_if_fail (printer->context != NULL);
276
277        gnome_print_setrgbcolor (printer->context,
278                                 color->red / 65535.0, color->green / 65535.0, color->blue / 65535.0);
279}
280
281static const GdkColor *
282get_black (const HTMLPainter *painter)
283{
284        static GdkColor black = { 0, 0, 0, 0 };
285
286        return &black;
287}
288
289static void
290prepare_rectangle (HTMLPainter *painter, gint _x, gint _y, gint w, gint h)
291{
292        HTMLPrinter *printer = HTML_PRINTER (painter);
293        GnomePrintContext *context = printer->context;
294        gdouble x;
295        gdouble y;
296        gdouble width;
297        gdouble height;
298
299        width = SCALE_ENGINE_TO_GNOME_PRINT (w);
300        height = SCALE_ENGINE_TO_GNOME_PRINT (h);
301
302        html_printer_coordinates_to_gnome_print (HTML_PRINTER (painter), _x, _y, &x, &y);
303
304        gnome_print_newpath (context);
305        gnome_print_moveto  (context, x, y);
306        gnome_print_lineto  (context, x + width, y);
307        gnome_print_lineto  (context, x + width, y - height);
308        gnome_print_lineto  (context, x, y - height);
309        gnome_print_lineto  (context, x, y);
310        gnome_print_closepath (context);
311}
312
313static void
314do_rectangle (HTMLPainter *painter, gint x, gint y, gint w, gint h, gint lw)
315{
316        HTMLPrinter *printer = HTML_PRINTER (painter);
317        GnomePrintContext *context = printer->context;
318
319        gnome_print_setlinewidth (context, SCALE_ENGINE_TO_GNOME_PRINT (lw) * PIXEL_SIZE);
320        prepare_rectangle (painter, x, y, w, h);
321        gnome_print_stroke (context);
322}
323
324static void
325set_clip_rectangle (HTMLPainter *painter,
326                    gint x, gint y,
327                    gint width, gint height)
328{
329        prepare_rectangle (painter, x, y, width, height);
330        gnome_print_clip (HTML_PRINTER (painter)->context);
331}
332
333/* HTMLPainter drawing functions.  */
334
335static void
336draw_line (HTMLPainter *painter,
337           gint x1, gint y1,
338           gint x2, gint y2)
339{
340        HTMLPrinter *printer;
341        double printer_x1, printer_y1;
342        double printer_x2, printer_y2;
343
344        printer = HTML_PRINTER (painter);
345        g_return_if_fail (printer->context != NULL);
346
347        html_printer_coordinates_to_gnome_print (printer, x1, y1, &printer_x1, &printer_y1);
348        html_printer_coordinates_to_gnome_print (printer, x2, y2, &printer_x2, &printer_y2);
349
350        gnome_print_setlinewidth (printer->context, PIXEL_SIZE);
351
352        gnome_print_newpath (printer->context);
353        gnome_print_moveto (printer->context, printer_x1, printer_y1);
354        gnome_print_lineto (printer->context, printer_x2, printer_y2);
355
356        gnome_print_stroke (printer->context);
357}
358
359static void
360draw_rect (HTMLPainter *painter,
361           gint x, gint y,
362           gint width, gint height)
363{
364        do_rectangle (painter, x, y, width, height, 1);
365}
366
367static void
368draw_panel (HTMLPainter *painter,
369            GdkColor *bg,
370            gint _x, gint _y,
371            gint w, gint h,
372            GtkHTMLEtchStyle inset,
373            gint bordersize)
374{
375        HTMLPrinter *printer = HTML_PRINTER (painter);
376        GnomePrintContext *pc = printer->context;
377        GdkColor *col1 = NULL, *col2 = NULL;
378        GdkColor dark, light;
379        gdouble x;
380        gdouble y;
381        gdouble width, bs;
382        gdouble height;
383
384        #define INC 0x8000
385        #define DARK(c)  dark.c = MAX (((gint) bg->c) - INC, 0)
386        #define LIGHT(c) light.c = MIN (((gint) bg->c) + INC, 0xffff)
387
388        DARK(red);
389        DARK(green);
390        DARK(blue);
391        LIGHT(red);
392        LIGHT(green);
393        LIGHT(blue);
394
395        switch (inset) {
396        case GTK_HTML_ETCH_NONE:
397                /* use the current pen color */
398                col1 = NULL;
399                col2 = NULL;
400                break;
401        case GTK_HTML_ETCH_OUT:
402                col1 = &light;
403                col2 = &dark;
404                break;
405        default:
406        case GTK_HTML_ETCH_IN:
407                col1 = &dark;
408                col2 = &light;
409                break;
410        }
411
412        width  = SCALE_ENGINE_TO_GNOME_PRINT (w);
413        height = SCALE_ENGINE_TO_GNOME_PRINT (h);
414        bs     = SCALE_ENGINE_TO_GNOME_PRINT (bordersize);
415
416        html_printer_coordinates_to_gnome_print (HTML_PRINTER (painter), _x, _y, &x, &y);
417
418        if (col2)
419                gnome_print_setrgbcolor (pc, col1->red / 65535.0, col1->green / 65535.0, col1->blue / 65535.0);
420
421        gnome_print_newpath (pc);
422        gnome_print_moveto  (pc, x, y);
423        gnome_print_lineto  (pc, x + width, y);
424        gnome_print_lineto  (pc, x + width - bs, y - bs);
425        gnome_print_lineto  (pc, x + bs, y - bs );
426        gnome_print_lineto  (pc, x + bs, y - height + bs);
427        gnome_print_lineto  (pc, x, y - height);
428        gnome_print_closepath (pc);
429        gnome_print_fill    (pc);
430
431        if (col1)
432                gnome_print_setrgbcolor (pc, col2->red / 65535.0, col2->green / 65535.0, col2->blue / 65535.0);
433
434        gnome_print_newpath (pc);
435        gnome_print_moveto  (pc, x, y - height);
436        gnome_print_lineto  (pc, x + width, y - height);
437        gnome_print_lineto  (pc, x + width, y);
438        gnome_print_lineto  (pc, x + width - bs, y - bs);
439        gnome_print_lineto  (pc, x + width - bs, y - height + bs);
440        gnome_print_lineto  (pc, x + bs, y - height + bs);
441        gnome_print_closepath (pc);
442        gnome_print_fill    (pc);
443}
444
445static void
446draw_background (HTMLPainter *painter,
447                 GdkColor *color,
448                 GdkPixbuf *pixbuf,
449                 gint ix, gint iy,
450                 gint pix_width, gint pix_height,
451                 gint tile_x, gint tile_y)
452{
453        GnomePrintContext *pc;
454        HTMLPrinter *printer;
455        gdouble x, y, width, height;
456
457        printer = HTML_PRINTER (painter);
458        g_return_if_fail (printer);
459        pc = printer->context;
460        g_return_if_fail (printer->context);
461
462        width = SCALE_ENGINE_TO_GNOME_PRINT  (pix_width);
463        height = SCALE_ENGINE_TO_GNOME_PRINT (pix_height);
464        html_printer_coordinates_to_gnome_print (printer, ix, iy, &x, &y);
465
466        if (color) {
467                gnome_print_setrgbcolor (pc, color->red / 65535.0, color->green / 65535.0, color->blue / 65535.0);
468
469                gnome_print_newpath (pc);
470                gnome_print_moveto (pc, x, y);
471                gnome_print_lineto (pc, x + width, y);
472                gnome_print_lineto (pc, x + width, y - height);
473                gnome_print_lineto (pc, x, y - height);
474                gnome_print_lineto (pc, x, y);
475                gnome_print_closepath (pc);
476
477                gnome_print_fill (pc);
478        }
479}
480
481static void
482print_pixbuf (GnomePrintContext *pc, GdkPixbuf *pixbuf)
483{
484        if (!pixbuf || (gdk_pixbuf_get_colorspace (pixbuf) != GDK_COLORSPACE_RGB))
485                return;
486       
487        if (gdk_pixbuf_get_has_alpha (pixbuf)) {
488                gnome_print_rgbaimage (pc,
489                                       gdk_pixbuf_get_pixels (pixbuf),
490                                       gdk_pixbuf_get_width (pixbuf),
491                                       gdk_pixbuf_get_height (pixbuf),
492                                       gdk_pixbuf_get_rowstride (pixbuf));
493        } else {
494                gnome_print_rgbimage (pc,
495                                      gdk_pixbuf_get_pixels (pixbuf),
496                                      gdk_pixbuf_get_width (pixbuf),
497                                      gdk_pixbuf_get_height (pixbuf),
498                                      gdk_pixbuf_get_rowstride (pixbuf));
499        }
500}
501
502static void
503draw_pixmap (HTMLPainter *painter, GdkPixbuf *pixbuf, gint x, gint y, gint scale_width, gint scale_height, const GdkColor *color)
504{
505        HTMLPrinter *printer;
506        gint width, height;
507        double print_x, print_y;
508        double print_scale_width, print_scale_height;
509
510        printer = HTML_PRINTER (painter);
511        g_return_if_fail (printer->context != NULL);
512
513        width = gdk_pixbuf_get_width (pixbuf);
514        height = gdk_pixbuf_get_height (pixbuf);
515
516        html_printer_coordinates_to_gnome_print (printer, x, y, &print_x, &print_y);
517
518        print_scale_width  = SCALE_ENGINE_TO_GNOME_PRINT (scale_width);
519        print_scale_height = SCALE_ENGINE_TO_GNOME_PRINT (scale_height);
520
521        gnome_print_gsave (printer->context);
522        gnome_print_translate (printer->context, print_x, print_y - print_scale_height);
523        gnome_print_scale (printer->context, print_scale_width, print_scale_height);
524        print_pixbuf (printer->context, pixbuf);
525        gnome_print_grestore (printer->context);
526}
527
528static void
529fill_rect (HTMLPainter *painter, gint x, gint y, gint width, gint height)
530{
531        HTMLPrinter *printer;
532        double printer_x, printer_y;
533        double printer_width, printer_height;
534
535        printer = HTML_PRINTER (painter);
536        g_return_if_fail (printer->context != NULL);
537
538        printer_width = SCALE_ENGINE_TO_GNOME_PRINT (width);
539        printer_height = SCALE_ENGINE_TO_GNOME_PRINT (height);
540
541        html_printer_coordinates_to_gnome_print (printer, x, y, &printer_x, &printer_y);
542
543        gnome_print_newpath (printer->context);
544        gnome_print_moveto (printer->context, printer_x, printer_y);
545        gnome_print_lineto (printer->context, printer_x + printer_width, printer_y);
546        gnome_print_lineto (printer->context, printer_x + printer_width, printer_y - printer_height);
547        gnome_print_lineto (printer->context, printer_x, printer_y - printer_height);
548        gnome_print_lineto (printer->context, printer_x, printer_y);
549        gnome_print_closepath (printer->context);
550
551        gnome_print_fill (printer->context);
552}
553
554static void
555process_attrs (HTMLPrinter *printer, GSList *attrs, GtkHTMLFontStyle *style, gboolean *bgcolor, gboolean *underline, gboolean *strikethrough, gboolean set_context)
556{
557        gboolean set_color = FALSE;
558
559        while (attrs) {
560                PangoAttribute *attr = attrs->data;
561
562                switch (attr->klass->type) {
563                case PANGO_ATTR_FOREGROUND: {
564                        PangoColor pc;
565     
566                        if (set_context) {
567                                pc = ((PangoAttrColor *) attr)->color;
568                                gnome_print_setrgbcolor (printer->context,
569                                                         pc.red / 65535.0, pc.green / 65535.0, pc.blue / 65535.0);
570                                set_color = TRUE;
571                        }
572                }
573                break;
574                case PANGO_ATTR_BACKGROUND:
575                        if (bgcolor)
576                                *bgcolor = TRUE;
577                case PANGO_ATTR_WEIGHT:
578                        if (style)
579                                *style |= GTK_HTML_FONT_STYLE_BOLD;
580                        break;
581                case PANGO_ATTR_STYLE:
582                        if (style)
583                                *style |= GTK_HTML_FONT_STYLE_ITALIC;
584                        break;
585                case PANGO_ATTR_UNDERLINE:
586                        if (underline)
587                                *underline = TRUE;
588                        break;
589                case PANGO_ATTR_STRIKETHROUGH:
590                        if (strikethrough)
591                                *strikethrough = TRUE;
592                        break;
593                case PANGO_ATTR_SIZE:
594                        if (style)
595                                *style |= ((HTMLPangoAttrFontSize *) attr)->style;
596                        break;
597                case PANGO_ATTR_FAMILY: {
598                        PangoAttrString *as = (PangoAttrString *) attr;
599
600                        if (!strcmp (as->value, "Monospace")
601                            || (HTML_PAINTER (printer)->font_manager.fixed.face && !strcmp (as->value, HTML_PAINTER (printer)->font_manager.fixed.face)))
602                                *style |= GTK_HTML_FONT_STYLE_FIXED;
603                }
604                break;
605                default:
606                        break;
607                }
608                attrs = attrs->next;
609        }
610
611        if (set_context && !set_color)
612                gnome_print_setrgbcolor (printer->context, 0.0, 0.0, 0.0);
613}
614
615static void
616show_sized_with_nbsps_replaced (GnomePrintContext *pc, const char *text, int bytes)
617{
618        const char *cur_text;
619        char *cur_replaced, *match, *replaced, *to_free = NULL;
620        int replaced_bytes;
621
622        if (bytes < 8192)
623                replaced = alloca (bytes);
624        else
625                to_free = replaced = g_malloc (bytes);
626
627        cur_text = text;
628        cur_replaced = replaced;
629        replaced_bytes = bytes;
630        while (cur_text < text + bytes) {
631                /* look for begining of 0xc2 0xa0 sequence - utf8 nbsp; */
632                match = memchr (cur_text, 0xc2, bytes - (cur_text - text));
633                if (match != NULL && match - text < bytes && IS_UTF8_NBSP ((guchar *)match)) {
634                        strncpy (cur_replaced, cur_text, match - cur_text);
635                        cur_replaced += match - cur_text;
636                        *cur_replaced = ' ';
637                        cur_replaced ++;
638                        cur_text = match + 2;
639                        replaced_bytes --;
640                } else {
641                        strncpy (cur_replaced, cur_text, bytes - (cur_text - text));
642                        break;
643                }
644        }
645
646        replaced [replaced_bytes] = 0;
647        gnome_print_show_sized (pc, replaced, replaced_bytes);
648
649        g_free (to_free);
650}
651
652static gint
653draw_text (HTMLPainter *painter, gint x, gint y, const gchar *text, gint len, HTMLTextPangoInfo *pi, PangoAttrList *attrs, GList *glyphs, gint start_byte_offset)
654{
655        GnomeFont *font;
656        HTMLPrinter *printer;
657        gdouble print_x, print_y;
658        double width, asc, dsc;
659        gboolean temp_pi = FALSE;
660
661        width = 0.0;
662
663        printer = HTML_PRINTER (painter);
664        g_return_val_if_fail (printer->context != NULL, 0);
665
666        if (!pi) {
667                pi = html_painter_text_itemize_and_prepare_glyphs (painter, html_painter_get_font (painter, painter->font_face, painter->font_style),
668                                                                   text, g_utf8_offset_to_pointer (text, len) - text, &glyphs, attrs);
669                start_byte_offset = 0;
670                temp_pi = TRUE;
671        }
672
673        font = html_painter_get_font (painter, painter->font_face, painter->font_style);
674        dsc = -gnome_font_get_descender (font);
675        asc = gnome_font_get_ascender (font);
676
677        if (pi && pi->n) {
678                GList *gl;
679                PangoGlyphString *str;
680                GtkHTMLFontStyle style;
681                guint char_offset = 0;
682                gint ii;
683                const gchar *c_text = text;
684                PangoAttrIterator *iter = NULL;
685
686                html_printer_coordinates_to_gnome_print (printer, x, y, &print_x, &print_y);
687                c_text = text;
688                for (gl = glyphs; gl && char_offset < len; gl = gl->next) {
689                        GnomeFont *c_font;
690                        GdkGC *bg_gc;
691                        gboolean underline, strikethrough, bgcolor;
692                        gint c_bytes, begin, end;
693                        double cw = 0.0;
694
695                        str = (PangoGlyphString *) gl->data;
696                        gl = gl->next;
697                        ii = GPOINTER_TO_INT (gl->data);
698                        bg_gc = NULL;
699                        c_font = font;
700                        style = GTK_HTML_FONT_STYLE_DEFAULT;
701                        c_bytes = g_utf8_offset_to_pointer (c_text, str->num_glyphs) - c_text;
702                        gnome_print_gsave (printer->context);
703                        bgcolor = underline = strikethrough = FALSE;
704
705                        if (attrs)
706                                iter = pango_attr_list_get_iterator (attrs);
707
708                        if (iter) {
709                                do {
710                                        pango_attr_iterator_range (iter, &begin, &end);
711                                        if (iter && MAX (begin, c_text - text) < MIN (end, (c_text - text) + c_bytes)) {
712                                                GSList *attr_list;
713                                                attr_list = pango_attr_iterator_get_attrs (iter);
714                                                process_attrs (printer, attr_list, &style, &bgcolor, &underline, &strikethrough, TRUE);
715                                                html_text_free_attrs (attr_list);
716                                        }
717                                } while (pango_attr_iterator_next (iter));
718                                pango_attr_iterator_destroy (iter);
719                        }
720                        process_attrs (printer, pi->entries [ii].item->analysis.extra_attrs, &style, &bgcolor, &underline, &strikethrough, TRUE);
721                        if (style != GTK_HTML_FONT_STYLE_DEFAULT)
722                                c_font = html_painter_get_font (HTML_PAINTER (printer), HTML_PAINTER (printer)->font_face, style);
723
724                        /* FIXME if (bgcolor) {
725                                PangoRectangle log_rect;
726
727                                pango_glyph_string_extents (str, pi->entries [ii].item->analysis.font, NULL, &log_rect);
728                                gdk_draw_rectangle (gdk_painter->pixmap, bg_gc, TRUE, x + width, y - PANGO_PIXELS (PANGO_ASCENT (log_rect)),
729                                                    PANGO_PIXELS (log_rect.width), PANGO_PIXELS (log_rect.height));
730                                gdk_gc_unref (bg_gc);
731                                } */
732
733                        gnome_print_newpath (printer->context);
734                        gnome_print_moveto (printer->context, print_x, print_y);
735                        gnome_print_setfont (printer->context, c_font);
736                        show_sized_with_nbsps_replaced (printer->context, c_text, c_bytes);
737
738                        cw = gnome_font_get_width_utf8_sized (c_font, c_text, c_bytes);
739                        if (strikethrough || underline) {
740                                gint ly;
741
742                                gnome_print_setlinewidth (printer->context, 1.0);
743                                gnome_print_setlinecap (printer->context, GDK_CAP_BUTT);
744
745                                if (underline) {
746                                        ly = print_y + gnome_font_get_underline_position (c_font);
747                                        gnome_print_newpath (printer->context);
748                                        gnome_print_moveto (printer->context, print_x, ly);
749                                        gnome_print_lineto (printer->context, print_x + cw, ly);
750                                        gnome_print_setlinewidth (printer->context, gnome_font_get_underline_thickness (c_font));
751                                        gnome_print_stroke (printer->context);
752                                }
753
754                                if (strikethrough) {
755                                        ly = print_y + gnome_font_get_ascender (c_font) / 2.0;
756                                        gnome_print_newpath (printer->context);
757                                        gnome_print_moveto (printer->context, print_x, ly);
758                                        gnome_print_lineto (printer->context, print_x + cw, ly);
759                                        gnome_print_setlinewidth (printer->context, gnome_font_get_underline_thickness (c_font));
760                                        gnome_print_stroke (printer->context);
761                                }
762                        }
763
764                        gnome_print_grestore (printer->context);
765
766                        width += cw;
767                        print_x += cw;
768                        c_text += c_bytes;
769                        char_offset += str->num_glyphs;
770                }
771        }
772
773        if (temp_pi) {
774                if (glyphs)
775                        html_painter_glyphs_destroy (glyphs);
776                if (pi)
777                        html_text_pango_info_destroy (pi);
778        }
779
780        return SCALE_GNOME_PRINT_TO_ENGINE (width);
781}
782
783static void
784draw_embedded (HTMLPainter *p, HTMLEmbedded *o, gint x, gint y)
785{
786        gdouble print_x, print_y;       
787        HTMLPrinter *printer = HTML_PRINTER(p);
788        GtkWidget *embedded_widget;
789
790        html_printer_coordinates_to_gnome_print (printer, x, y, &print_x, &print_y);
791        gnome_print_gsave(printer->context);
792
793        gnome_print_translate(printer->context,
794                              print_x, print_y - o->height * PIXEL_SIZE);
795 
796        embedded_widget = html_embedded_get_widget(o);
797        if (embedded_widget && GTK_IS_HTML_EMBEDDED (embedded_widget)) {
798                g_signal_emit_by_name(GTK_OBJECT (embedded_widget), 0,
799                                      "draw_print",
800                                      printer->context);
801        }
802
803        gnome_print_grestore(printer->context);
804}
805
806static void
807draw_shade_line (HTMLPainter *painter,
808                 gint x, gint y,
809                 gint width)
810{
811        HTMLPrinter *printer;
812
813        printer = HTML_PRINTER (painter);
814        g_return_if_fail (printer->context != NULL);
815
816        /* FIXME */
817}
818
819static void
820text_size (HTMLPainter *painter, const gchar *text, guint blen, HTMLTextPangoInfo *pi, PangoAttrList *attrs, GList *glyphs, gint start_byte_offset,
821           GnomeFont *font, GtkHTMLFontStyle style, gint *width, gint *asc, gint *dsc)
822{
823        HTMLPrinter *printer;
824        gboolean temp_pi = FALSE;
825        double real_width = 0.0;
826
827        printer = HTML_PRINTER (painter);
828        g_return_if_fail (printer->context != NULL);
829        g_return_if_fail (font != NULL);
830
831        if (asc)
832                *asc = SCALE_GNOME_PRINT_TO_ENGINE (gnome_font_get_ascender (font));
833        if (dsc)
834                *dsc = SCALE_GNOME_PRINT_TO_ENGINE (-gnome_font_get_descender (font));
835
836        if (!pi) {
837                pi = html_painter_text_itemize_and_prepare_glyphs (painter, html_painter_get_font (painter, painter->font_face, painter->font_style),
838                                                                   text, blen, &glyphs, attrs);
839                start_byte_offset = 0;
840                temp_pi = TRUE;
841        }
842
843        if (pi && pi->n) {
844                GList *gl;
845                guint char_offset = 0;
846                gint ii;
847                const gchar *c_text = text;
848                PangoGlyphString *str;
849                PangoAttrIterator *iter = NULL;
850
851                c_text = text;
852                for (gl = glyphs; gl && char_offset < blen; gl = gl->next) {
853                        GnomeFont *c_font;
854                        gint c_bytes, begin, end;
855
856                        str = (PangoGlyphString *) gl->data;
857                        gl = gl->next;
858                        ii = GPOINTER_TO_INT (gl->data);
859                        style = GTK_HTML_FONT_STYLE_DEFAULT;
860                        c_font = font;
861                        c_bytes = g_utf8_offset_to_pointer (c_text, str->num_glyphs) - c_text;
862
863                        if (attrs)
864                                iter = pango_attr_list_get_iterator (attrs);
865
866                        if (iter) {
867                                do {
868                                        pango_attr_iterator_range (iter, &begin, &end);
869                                        if (iter && MAX (begin, c_text - text) < MIN (end, (c_text - text) + c_bytes)) {
870                                                GSList *attr_list;
871                                                attr_list = pango_attr_iterator_get_attrs (iter);
872                                                process_attrs (printer, attr_list, &style, NULL, NULL, NULL, FALSE);
873                                                html_text_free_attrs (attr_list);
874                                        }
875                                } while (pango_attr_iterator_next (iter));
876                                pango_attr_iterator_destroy (iter);
877                        }
878
879                        process_attrs (printer, pi->entries [ii].item->analysis.extra_attrs, &style, NULL, NULL, NULL, FALSE);
880                        if (style != GTK_HTML_FONT_STYLE_DEFAULT)
881                                c_font = html_painter_get_font (HTML_PAINTER (printer), HTML_PAINTER (printer)->font_face, style);
882
883                        if (asc)
884                                *asc = MAX (*asc, SCALE_GNOME_PRINT_TO_ENGINE (gnome_font_get_ascender (c_font)));
885                        if (dsc)
886                                *dsc = MAX (*dsc, SCALE_GNOME_PRINT_TO_ENGINE (-gnome_font_get_descender (c_font)));
887
888                        if (width)
889                                real_width += gnome_font_get_width_utf8_sized (c_font, c_text, c_bytes);
890                        c_text += c_bytes;
891                        char_offset += str->num_glyphs;
892                }
893        }
894
895        if (temp_pi) {
896                if (glyphs)
897                        html_painter_glyphs_destroy (glyphs);
898                if (pi)
899                        html_text_pango_info_destroy (pi);
900        }
901
902        if (width)
903                *width = SCALE_GNOME_PRINT_TO_ENGINE (real_width);
904}
905
906static void
907calc_text_size_bytes (HTMLPainter *painter, const gchar *text, guint len, HTMLTextPangoInfo *pi, PangoAttrList *attrs, GList *glyphs, gint start_byte_offset,
908                      HTMLFont *font, GtkHTMLFontStyle style, gint *width, gint *asc, gint *dsc)
909{
910        text_size (painter, text, len, pi, attrs, glyphs, start_byte_offset, font->data, style, width, asc, dsc);
911}
912
913static void
914calc_text_size (HTMLPainter *painter, const gchar *text, guint len, HTMLTextPangoInfo *pi, PangoAttrList *attrs, GList *glyphs, gint start_byte_offset,
915                GtkHTMLFontStyle style, HTMLFontFace *face, gint *width, gint *asc, gint *dsc)
916{
917        HTMLPrinter *printer;
918
919        printer = HTML_PRINTER (painter);
920        g_return_if_fail (printer->context != NULL);
921
922        text_size (painter, text, g_utf8_offset_to_pointer (text, len) - text, pi, attrs, glyphs,
923                   start_byte_offset, html_painter_get_font (painter, face, style), style, width, asc, dsc);
924}
925
926
927static guint
928get_pixel_size (HTMLPainter *painter)
929{
930        HTMLPrinter *printer = HTML_PRINTER (painter);
931
932        return SCALE_GNOME_PRINT_TO_ENGINE (PIXEL_SIZE);
933}
934
935static inline gdouble
936get_font_size (HTMLPrinter *printer, gboolean points, gdouble size)
937{
938        return printer->scale * (points ? PANGO_PIXELS (size) / 10 : PANGO_PIXELS (size));
939}
940
941static HTMLFont *
942alloc_font (HTMLPainter *painter, gchar *face, gdouble size, gboolean points, GtkHTMLFontStyle style)
943{
944        HTMLPrinter *printer = HTML_PRINTER (painter);
945        GnomeFontWeight weight;
946        GnomeFont *font;
947        gboolean italic;
948
949        weight = (style & GTK_HTML_FONT_STYLE_BOLD) ? GNOME_FONT_BOLD : GNOME_FONT_BOOK;
950        italic = (style & GTK_HTML_FONT_STYLE_ITALIC) ? TRUE : FALSE;
951
952        font = gnome_font_find_closest_from_weight_slant (face ? face : (style & GTK_HTML_FONT_STYLE_FIXED ? "Monospace" : "Sans"),
953                                                          weight, italic, get_font_size (printer, points, size));
954
955        if (font == NULL && face == NULL) {
956                GList *family_list;
957
958                family_list = gnome_font_family_list ();
959                if (family_list && family_list->data) {
960                        font = gnome_font_find_closest_from_weight_slant (family_list->data, weight, italic, get_font_size (printer, points, size));
961                        gnome_font_family_list_free (family_list);
962                }
963        }
964
965        return font ? html_font_new (font,
966                                     SCALE_GNOME_PRINT_FONT_TO_ENGINE (gnome_font_get_width_utf8_sized (font, " ", 1)/HTML_PRINTER (printer)->scale),
967                                     SCALE_GNOME_PRINT_TO_ENGINE (gnome_font_get_ascender (font)),
968                                     SCALE_GNOME_PRINT_TO_ENGINE (-gnome_font_get_descender (font)),
969                                     SCALE_GNOME_PRINT_FONT_TO_ENGINE (gnome_font_get_width_utf8_sized (font, "\xc2\xa0", 2)/HTML_PRINTER (printer)->scale),
970                                     SCALE_GNOME_PRINT_FONT_TO_ENGINE (gnome_font_get_width_utf8_sized (font, "\t", 1)/HTML_PRINTER (printer)->scale),
971                                     SCALE_GNOME_PRINT_FONT_TO_ENGINE (gnome_font_get_width_utf8_sized (font, "e", 1)/HTML_PRINTER (printer)->scale),
972                                     SCALE_GNOME_PRINT_FONT_TO_ENGINE (gnome_font_get_width_utf8_sized (font, HTML_BLOCK_CITE, strlen (HTML_BLOCK_CITE))
973                                                                       /HTML_PRINTER (printer)->scale),
974                                     SCALE_GNOME_PRINT_FONT_TO_ENGINE (gnome_font_get_width_utf8_sized (font, HTML_BLOCK_INDENT, strlen (HTML_BLOCK_INDENT))
975                                                                       /HTML_PRINTER (printer)->scale))
976                : NULL;
977}
978
979static void
980ref_font (HTMLPainter *painter, HTMLFont *font)
981{
982        g_object_ref (font->data);
983}
984
985static void
986unref_font (HTMLPainter *painter, HTMLFont *font)
987{
988        g_object_unref (font->data);
989}
990
991static guint
992get_page_width (HTMLPainter *painter, HTMLEngine *e)
993{
994        return html_printer_get_page_width (HTML_PRINTER (painter));
995}
996
997static guint
998get_page_height (HTMLPainter *painter, HTMLEngine *e)
999{
1000        return html_printer_get_page_height (HTML_PRINTER (painter));
1001}
1002
1003static void
1004html_printer_init (GObject *object)
1005{
1006        HTMLPrinter *printer;
1007
1008        printer                = HTML_PRINTER (object);
1009        printer->context       = NULL;
1010        printer->config        = NULL;
1011        printer->scale         = 1.0;
1012}
1013
1014static void
1015html_printer_class_init (GObjectClass *object_class)
1016{
1017        HTMLPainterClass *painter_class;
1018
1019        painter_class = HTML_PAINTER_CLASS (object_class);
1020
1021        parent_class = g_type_class_ref (HTML_TYPE_PAINTER);
1022
1023        object_class->finalize = finalize;
1024
1025        painter_class->begin = begin;
1026        painter_class->end = end;
1027        painter_class->alloc_font = alloc_font;
1028        painter_class->ref_font   = ref_font;
1029        painter_class->unref_font = unref_font;
1030        painter_class->alloc_color = alloc_color;
1031        painter_class->free_color = free_color;
1032        painter_class->calc_text_size = calc_text_size;
1033        painter_class->calc_text_size_bytes = calc_text_size_bytes;
1034        painter_class->set_pen = set_pen;
1035        painter_class->get_black = get_black;
1036        painter_class->draw_line = draw_line;
1037        painter_class->draw_rect = draw_rect;
1038        painter_class->draw_panel = draw_panel;
1039        painter_class->draw_text = draw_text;
1040        painter_class->fill_rect = fill_rect;
1041        painter_class->draw_pixmap = draw_pixmap;
1042        painter_class->clear = clear;
1043        painter_class->draw_shade_line = draw_shade_line;
1044        painter_class->draw_background = draw_background;
1045        painter_class->get_pixel_size = get_pixel_size;
1046        painter_class->set_clip_rectangle = set_clip_rectangle;
1047        painter_class->draw_embedded = draw_embedded;
1048        painter_class->get_page_width = get_page_width;
1049        painter_class->get_page_height = get_page_height;
1050}
1051
1052GType
1053html_printer_get_type (void)
1054{
1055        static GType html_printer_type = 0;
1056
1057        if (html_printer_type == 0) {
1058                static const GTypeInfo html_printer_info = {
1059                        sizeof (HTMLPrinterClass),
1060                        NULL,
1061                        NULL,
1062                        (GClassInitFunc) html_printer_class_init,
1063                        NULL,
1064                        NULL,
1065                        sizeof (HTMLPrinter),
1066                        1,
1067                        (GInstanceInitFunc) html_printer_init,
1068                };
1069                html_printer_type = g_type_register_static (HTML_TYPE_PAINTER, "HTMLPrinter", &html_printer_info, 0);
1070        }
1071
1072        return html_printer_type;
1073}
1074
1075HTMLPainter *
1076html_printer_new (GtkWidget *widget, GnomePrintContext *context, GnomePrintJob *master)
1077{
1078        HTMLPrinter *new;
1079
1080        new = g_object_new (HTML_TYPE_PRINTER, NULL);
1081
1082        g_object_ref (context);
1083        html_painter_set_widget (HTML_PAINTER (new), widget);
1084        new->context = context;
1085        new->master = master;
1086
1087        return HTML_PAINTER (new);
1088}
1089
1090
1091guint
1092html_printer_get_page_width (HTMLPrinter *printer)
1093{
1094        double printer_width;
1095        guint engine_width;
1096
1097        g_return_val_if_fail (printer != NULL, 0);
1098        g_return_val_if_fail (HTML_IS_PRINTER (printer), 0);
1099
1100        printer_width = printer_get_page_width (printer) - get_lmargin (printer) - get_rmargin (printer);
1101        engine_width = SCALE_GNOME_PRINT_TO_ENGINE (printer_width);
1102
1103        return engine_width;
1104}
1105
1106guint
1107html_printer_get_page_height (HTMLPrinter *printer)
1108{
1109        double printer_height;
1110        guint engine_height;
1111
1112        g_return_val_if_fail (printer != NULL, 0);
1113        g_return_val_if_fail (HTML_IS_PRINTER (printer), 0);
1114
1115        printer_height = printer_get_page_height (printer) - get_tmargin (printer) - get_bmargin (printer);
1116        engine_height = SCALE_GNOME_PRINT_TO_ENGINE (printer_height);
1117
1118        return engine_height;
1119}
Note: See TracBrowser for help on using the repository browser.