source: trunk/third/gtkhtml/src/htmlgdkpainter.c @ 18136

Revision 18136, 36.5 KB checked in by ghudson, 22 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r18135, 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 <stdlib.h>
27#include <ctype.h>
28
29#include <glib.h>
30#include <gdk/gdkx.h>
31#include <gtk/gtksignal.h>
32
33#include <libgnome/gnome-defs.h>
34#include <libgnome/gnome-i18n.h>
35#include <libart_lgpl/art_rect.h>
36#include <gal/unicode/gunicode.h>
37#include <gal/widgets/e-font.h>
38
39#include "htmlentity.h"
40#include "htmlgdkpainter.h"
41#include "htmlcolor.h"
42#include "htmlcolorset.h"
43#include "htmlembedded.h"
44#include "htmlengine.h"
45#include "gtkhtml-embedded.h"
46
47static HTMLPainterClass *parent_class = NULL;
48
49static EFontStyle e_style (GtkHTMLFontStyle style);
50
51/* GtkObject methods.  */
52
53static void
54finalize (GtkObject *object)
55{
56        HTMLGdkPainter *painter;
57
58        painter = HTML_GDK_PAINTER (object);
59
60        if (painter->gc != NULL)
61                gdk_gc_destroy (painter->gc);
62
63        if (painter->pixmap != NULL)
64                gdk_pixmap_unref (painter->pixmap);
65
66        (* GTK_OBJECT_CLASS (parent_class)->finalize) (object);
67}
68
69static gchar *
70get_font_attr (gchar *font_name, gint pos)
71{
72        gchar *s, *end, *rv = NULL;
73        gint n;
74
75        /* Search paramether */
76        for (s=font_name, n=pos; n; n--,s++)
77                s = strchr (s,'-');
78
79        if (s && *s != 0) {
80                end = strchr (s, '-');
81                if (end)
82                        rv = g_strndup (s, end - s);
83        }
84
85        return rv;
86}
87
88static gint
89get_size (gchar *font_name, gboolean points)
90{
91    gchar *s, *end;
92    gint n;
93
94    /* Search paramether */
95    for (s=font_name, n=points ? 8 : 7; n; n--,s++)
96            s = strchr (s,'-');
97
98    if (s && *s != 0) {
99            end = strchr (s, '-');
100            if (end) {
101                    *end = 0;
102                    n = atoi (s);
103                    *end = '-';
104                    return n;
105            } else
106                    return 0;
107    } else
108            return 0;
109}
110
111static gchar *
112font_name_substitute_attr (const gchar *name, gint nth, gchar *val)
113{
114        const gchar *s;
115        gchar *s1, *s2, *rv;
116
117        if (!name)
118                return NULL;
119
120        for (s = name; nth; nth--) {
121                s = strchr (s, '-');
122                if (!s)
123                        return NULL;
124                s ++;
125        }
126        s2 = strchr (s, '-');
127        if (!s2)
128                return NULL;
129        s1 = g_strndup (name, s - name);
130
131        rv = g_strconcat (s1, val, s2, NULL);
132        g_free (s1);
133
134        return rv;
135}
136
137static GHashTable *cache_x_list_fonts_results = NULL;
138typedef struct _HTMLGdkPainterFontList
139{
140        gchar **list;
141        gint n;
142} HTMLGdkPainterFontList;
143
144static gint
145html_str_case_equal (gconstpointer v, gconstpointer v2)
146{
147        return strcasecmp ((const gchar*) v, (const gchar*)v2) == 0;
148}
149
150static guint
151html_str_case_hash (gconstpointer key)
152{
153  const char *p = key;
154  guint h = tolower (*p);
155 
156  if (h)
157    for (p += 1; *p != '\0'; p++)
158      h = (h << 5) - h + tolower (*p);
159 
160  return h;
161}
162
163static gchar **
164lookup_fonts (gchar *face, gint *n)
165{
166        HTMLGdkPainterFontList *fl;
167
168        if (!cache_x_list_fonts_results)
169                cache_x_list_fonts_results = g_hash_table_new (html_str_case_hash, html_str_case_equal);
170
171        fl = (HTMLGdkPainterFontList *) g_hash_table_lookup (cache_x_list_fonts_results, face);
172        if (!fl) {
173                GTimer *timer;
174                gdouble elapsed;
175
176                fl = g_new (HTMLGdkPainterFontList, 1);
177
178                timer = g_timer_new ();
179                g_timer_start (timer);
180                fl->list = XListFonts (GDK_DISPLAY (), face, 0x7fff, &fl->n);
181                elapsed = g_timer_elapsed (timer, NULL);
182                g_timer_destroy (timer);
183
184                if (!fl->list)
185                        fl->n = 0;
186                printf ("(%1.4fs) [list] %s --> %d\n", elapsed, face, fl->n);
187                /* printf ("inserting %d results for %s\n", fl->n, face); */
188                /* {
189                        gint i;
190                        for (i = 0; i < fl->n; i ++)
191                                printf ("\t%s\n", fl->list [i]);
192                                } */
193                g_hash_table_insert (cache_x_list_fonts_results, g_strdup (face), fl);
194        } /* else
195             printf ("%d results found in cache (%s)\n", fl->n, face); */
196
197        *n = fl->n;
198
199        return fl->list;
200}
201
202static gchar **
203filter_fonts_with_style (gchar **list, gint *n, gchar *weight, gchar *slant)
204{
205        if (*n) {
206                GSList *cur, *tmp_list = NULL;
207                gchar **filtered, *fw, *fs;
208                gint i, nf;
209
210                nf = 0;
211                for (i = 0; i < *n; i ++) {
212                        fw = get_font_attr (list [i], 3);
213                        fs = get_font_attr (list [i], 4);
214                        if (fw && fs) {
215                                if (!strcasecmp (fw, weight) && !strcasecmp (fs, slant)) {
216                                        tmp_list = g_slist_prepend (tmp_list, list [i]);
217                                        nf ++;
218                                }
219                        }
220                        g_free (fw);
221                        g_free (fs);
222                }
223
224                filtered = g_new (gchar *, nf);
225                for (i = 0, cur = tmp_list; cur; i++, cur = cur->next)
226                        filtered [i] = (gchar *) cur->data;
227                g_slist_free (tmp_list);
228                *n = nf;
229
230                /* printf ("found %d fonts (%s,%s)\n", *n, weight, slant); */
231
232                return filtered;
233        }
234
235        return list;
236}
237
238static gchar *
239find_font_with_similar_size (gchar **list, gint n, gint size, gboolean points, gboolean smaller)
240{
241        if (n) {
242                gint i, small, large, as, small_idx, large_idx;
243
244                small = large = small_idx = large_idx = 0;
245                for (i = 0; i < n; i++) {
246                        as = get_size (list [i], points);
247
248                        if (as > size && (as < large || !large)) {
249                                large = as;
250                                large_idx = i;
251                        } else if (as < size && (as > small || !small)) {
252                                small = as;
253                                small_idx = i;
254                        }
255                }
256
257                if (!small && !large)
258                        return NULL;
259                if (!small && large)
260                        return list [large_idx];
261                if (small && !large)
262                        return list [small_idx];
263                return list [smaller ? small_idx : large_idx];
264        }
265
266        return NULL;
267}
268
269static gpointer
270load_font_with_name (gchar *name)
271{
272        GdkFont *gdk_font;
273        gboolean need_fontset = FALSE;
274        gpointer font;
275        GTimer *timer;
276        gdouble elapsed;
277
278        if (strchr (name, ','))
279                need_fontset = TRUE;
280
281        timer = g_timer_new ();
282        g_timer_start (timer);
283        gdk_font = need_fontset ? gdk_fontset_load (name) : gdk_font_load (name);
284        elapsed = g_timer_elapsed (timer, NULL);
285        g_timer_destroy (timer);
286        printf ("(%1.4fs) [load] %s --> %p\n", elapsed, name, gdk_font);
287
288        if (gdk_font) {
289                font = e_font_from_gdk_font_gtkhtml (gdk_font);
290                gdk_font_unref (gdk_font);
291        } else
292                font = NULL;
293
294        return font;
295}
296
297static gchar *
298e_font_lookup_face (gchar *face, gint size, gboolean points, gchar *weight, gchar *slant,
299                    gboolean known_size, gboolean smaller)
300{
301        gchar *f1, *f2, *f3, *f4, **list, **filtered = NULL;
302        gchar *font_name = NULL;
303        gint n;
304
305        /* clear weight, slant and size */
306        f1 = font_name_substitute_attr (face, 7, "*");
307        f2 = font_name_substitute_attr (f1, 8, "*");
308        g_free (f1);
309        f3 = font_name_substitute_attr (f2, 3, "*");
310        g_free (f2);
311        f4 = font_name_substitute_attr (f3, 4, "*");
312        g_free (f3);
313
314        if (!f4) {
315                g_warning ("Don't know how to use face: %s", face ? face : "NULL");
316                return NULL;
317        }
318
319        list = lookup_fonts (f4, &n);
320        g_free (f4);
321
322        if (n == 0)
323                return NULL;
324
325        filtered = filter_fonts_with_style (list, &n, weight, slant);
326        if (n) {
327                gchar *name;
328                if (known_size) {
329
330
331                        name = find_font_with_similar_size (filtered, n, size, points, smaller);
332                       
333                        if (name)
334                                font_name = g_strdup (name);
335                } else {
336                        gchar *s;
337
338                        f1 = font_name_substitute_attr (face, 3, weight);
339                        f2 = font_name_substitute_attr (f1,   4, slant);
340                        if (!f2) {
341                                g_warning ("Don't know how to use face: %s", face ? face : "NULL");
342                                return NULL;
343                        }
344                        s    = g_strdup_printf ("%d", size);
345                        name = font_name_substitute_attr (f2, points ? 8 : 7, s);
346                        if (!name) {
347                                g_warning ("Don't know how to use face: %s", face ? face : "NULL");
348                                return NULL;
349                        }
350                        g_free (f1);
351                        g_free (f2);
352                        g_free (s);
353
354                        font_name = name;
355                }
356
357        }
358        if (filtered != list)
359                g_free (filtered);
360
361        return font_name;
362}
363
364static gpointer
365e_font_from_face (gchar *face, gint size, gboolean points, gchar *weight, gchar *slant,
366                  gboolean known_size, gboolean smaller)
367{
368        gchar *better_name;
369        gchar **fontnames;
370        GString *newface;
371        gint i;
372        gpointer font = NULL;
373        gboolean found = FALSE;
374
375        newface = g_string_new ("");
376        fontnames = g_strsplit (face, ",", 50);
377        for (i = 0; fontnames && fontnames[i] != NULL; i++) {
378                char *name = g_strstrip (fontnames[i]);
379
380                better_name = e_font_lookup_face (name, size, points, weight, slant, known_size, smaller);
381               
382                if (i)
383                        g_string_append (newface, ",");
384               
385                if (better_name) {
386                        g_string_append (newface, better_name);
387                        g_free (better_name);
388                        found = TRUE;
389                } else {
390                        g_string_append (newface, name);
391                }
392        }
393        g_strfreev (fontnames);
394       
395        if (found)
396                font = load_font_with_name (newface->str);
397        g_string_free (newface, TRUE);
398       
399        return font;
400}
401
402static GdkFont *
403get_fallback_gdk_font (void)
404{
405        static GdkFont *fallback_font = NULL;
406
407        if (!fallback_font) {
408                GtkWidget *tmp_window = gtk_window_new (GTK_WINDOW_POPUP);
409                gtk_widget_ensure_style (tmp_window);
410                fallback_font = gdk_font_ref (tmp_window->style->font);
411                gtk_widget_destroy (tmp_window);
412        }
413
414        return fallback_font;
415}
416
417static gpointer
418alloc_e_font_try (gchar *face, gdouble size, gboolean points, GtkHTMLFontStyle style,
419                  gchar *medium, gchar *bold, gchar *roman, gchar *italic, gboolean known_size)
420{
421        EFont *font;
422
423        /* printf ("alloc font %s %f\n", face, size); */
424
425        if (face) {
426                font = e_font_from_face (face, MAX (1, size), points,
427                                         style & GTK_HTML_FONT_STYLE_BOLD ? bold : medium,
428                                         style & GTK_HTML_FONT_STYLE_ITALIC ? italic : roman,
429                                         known_size, (style & GTK_HTML_FONT_STYLE_SIZE_MASK) > GTK_HTML_FONT_STYLE_SIZE_3);
430        } else {
431                font = e_font_from_gdk_font (get_fallback_gdk_font ());
432        }
433
434        return font;
435}
436
437static EFont *
438try_font_possible_names (gchar *face, gdouble size, gboolean points,
439                         GtkHTMLFontStyle style, gboolean known)
440{
441        EFont *font;
442
443        font = alloc_e_font_try (face, size, points, style, "medium", "bold", "r", "i", known);
444        if (!font && style & GTK_HTML_FONT_STYLE_ITALIC)
445                font = alloc_e_font_try (face, size, points, style, "medium", "bold", "r", "o", known);
446        if (!font)
447                font = alloc_e_font_try (face, size, points, style, "book",   "demi", "r", "i", known);
448        if (!font && style & GTK_HTML_FONT_STYLE_ITALIC)
449                font = alloc_e_font_try (face, size, points, style, "book",   "demi", "r", "o", known);
450        if (!font)
451                font = alloc_e_font_try (face, size, points, style, "light",   "demibold", "r", "i", known);
452        if (!font && style & GTK_HTML_FONT_STYLE_ITALIC)
453                font = alloc_e_font_try (face, size, points, style, "light",   "demibold", "r", "o", known);
454
455        return font;
456}
457
458static HTMLFont *
459alloc_e_font_do (gchar *face, gdouble size, gboolean points, GtkHTMLFontStyle style)
460{
461        EFont *font;
462
463        font = try_font_possible_names (face, size, points, style, FALSE);
464        if (!font)
465                font = try_font_possible_names (face, size, points, style, TRUE);
466
467        return font ? html_font_new (font,
468                                     e_font_utf8_text_width (font, e_style (style), " ", 1),
469                                     e_font_utf8_text_width (font, e_style (style), "\xc2\xa0", 2),
470                                     e_font_utf8_text_width (font, e_style (style), "\t", 1))
471
472                : NULL;
473}
474
475static HTMLFont *
476alloc_e_font (gchar *face, gdouble size, gboolean points, GtkHTMLFontStyle style)
477{
478        HTMLFont *font;
479
480        font = alloc_e_font_do (face, size, points, style);
481        if (!font && style & GTK_HTML_FONT_STYLE_BOLD)
482                font = alloc_e_font_do (face, size, points, style & (~GTK_HTML_FONT_STYLE_BOLD));
483        if (!font && style & GTK_HTML_FONT_STYLE_ITALIC)
484                font = alloc_e_font_do (face, size, points, style & (~GTK_HTML_FONT_STYLE_ITALIC));
485        if (!font && style & GTK_HTML_FONT_STYLE_ITALIC && style & GTK_HTML_FONT_STYLE_BOLD)
486                font = alloc_e_font_do (face, size, points,
487                                        style & ((~GTK_HTML_FONT_STYLE_ITALIC) & (~GTK_HTML_FONT_STYLE_BOLD)));
488
489        return font;
490}
491
492static void
493ref_font (HTMLFont *font)
494{
495        e_font_ref ((EFont *) font->data);
496}
497
498static void
499unref_font (HTMLFont *font)
500{
501        e_font_unref ((EFont *) font->data);
502}
503
504
505static void
506alloc_color (HTMLPainter *painter,
507             GdkColor *color)
508{
509        HTMLGdkPainter *gdk_painter;
510        GdkColormap *colormap;
511
512        gdk_painter = HTML_GDK_PAINTER (painter);
513        g_return_if_fail (gdk_painter->window != NULL);
514
515        colormap = gdk_window_get_colormap (gdk_painter->window);
516
517        gdk_colormap_alloc_color (colormap, color, FALSE, TRUE);
518}
519
520static void
521free_color (HTMLPainter *painter,
522            GdkColor *color)
523{
524        HTMLGdkPainter *gdk_painter;
525        GdkColormap *colormap;
526
527        gdk_painter = HTML_GDK_PAINTER (painter);
528
529        g_return_if_fail (gdk_painter->window != NULL);
530        g_return_if_fail (gdk_painter->gc != NULL);
531
532        colormap = gdk_window_get_colormap (gdk_painter->window);
533        gdk_colormap_free_colors (colormap, color, 1);
534}
535
536
537static void
538begin (HTMLPainter *painter, int x1, int y1, int x2, int y2)
539{
540        HTMLGdkPainter *gdk_painter;
541        GdkVisual *visual;
542
543        /* printf ("painter begin %d,%d %d,%d\n", x1, y1, x2, y2); */
544
545        gdk_painter = HTML_GDK_PAINTER (painter);
546        g_return_if_fail (gdk_painter->window != NULL);
547        visual = gdk_window_get_visual (gdk_painter->window);
548        g_return_if_fail (visual != NULL);
549
550        if (gdk_painter->double_buffer){
551                const int width = x2 - x1 + 1;
552                const int height = y2 - y1 + 1;
553
554                g_assert (gdk_painter->pixmap == NULL);
555               
556                gdk_painter->pixmap = gdk_pixmap_new (gdk_painter->pixmap, width, height, visual->depth);
557                gdk_painter->x1 = x1;
558                gdk_painter->y1 = y1;
559                gdk_painter->x2 = x2;
560                gdk_painter->y2 = y2;
561
562                if (gdk_painter->set_background){
563                        gdk_gc_set_background (gdk_painter->gc, &gdk_painter->background);
564                        gdk_painter->set_background = FALSE;
565                }
566
567                gdk_gc_set_foreground (gdk_painter->gc, &gdk_painter->background);
568                gdk_draw_rectangle (gdk_painter->pixmap, gdk_painter->gc,
569                                    TRUE, 0, 0, width, height);
570        } else {
571                gdk_painter->pixmap = gdk_painter->window;
572                gdk_painter->x1 = 0;
573                gdk_painter->y1 = 0;
574                gdk_painter->x2 = 0;
575                gdk_painter->y2 = 0;
576        }
577}
578
579static void
580end (HTMLPainter *painter)
581{
582        HTMLGdkPainter *gdk_painter;
583
584        /* printf ("painter end\n"); */
585
586        gdk_painter = HTML_GDK_PAINTER (painter);
587       
588        if (! gdk_painter->double_buffer)
589                return;
590
591        gdk_draw_pixmap (gdk_painter->window, gdk_painter->gc,
592                         gdk_painter->pixmap,
593                         0, 0,
594                         gdk_painter->x1, gdk_painter->y1,
595                         gdk_painter->x2 - gdk_painter->x1,
596                         gdk_painter->y2 - gdk_painter->y1);
597
598        gdk_pixmap_unref (gdk_painter->pixmap);
599        gdk_painter->pixmap = NULL;
600}
601
602static HTMLFontManagerId
603get_font_manager_id ()
604{
605        return HTML_FONT_MANAGER_ID_GDK;
606}
607
608static void
609clear (HTMLPainter *painter)
610{
611        HTMLGdkPainter *gdk_painter;
612
613        gdk_painter = HTML_GDK_PAINTER (painter);
614
615        if (! gdk_painter->double_buffer){
616                gdk_window_clear (gdk_painter->window);
617        } else {
618                if (gdk_painter->pixmap != NULL)
619                        gdk_window_clear (gdk_painter->pixmap);
620                else
621                        gdk_painter->do_clear = TRUE;
622        }
623}
624
625
626static void
627set_clip_rectangle (HTMLPainter *painter,
628                    gint x, gint y,
629                    gint width, gint height)
630{
631        HTMLGdkPainter *gdk_painter;
632        GdkRectangle rect;
633
634        gdk_painter = HTML_GDK_PAINTER (painter);
635
636        if (width == 0 || height == 0) {
637                gdk_gc_set_clip_rectangle (gdk_painter->gc, NULL);
638                return;
639        }
640
641        rect.x = x;
642        rect.y = y;
643        rect.width = width;
644        rect.height = height;
645       
646        gdk_gc_set_clip_rectangle (gdk_painter->gc, &rect);
647}
648
649static void
650set_background_color (HTMLPainter *painter,
651                      const GdkColor *color)
652{
653        g_warning ("HTMLGdkPainter::set_background_color() needs to be implemented.");
654}
655
656static void
657set_pen (HTMLPainter *painter,
658         const GdkColor *color)
659{
660        HTMLGdkPainter *gdk_painter;
661
662        gdk_painter = HTML_GDK_PAINTER (painter);
663
664        /* GdkColor API not const-safe!  */
665        gdk_gc_set_foreground (gdk_painter->gc, (GdkColor *) color);
666}
667
668static const GdkColor *
669get_black (const HTMLPainter *painter)
670{
671        HTMLGdkPainter *gdk_painter;
672
673        gdk_painter = HTML_GDK_PAINTER (painter);
674        return &gdk_painter->black;
675}
676
677
678/* HTMLPainter drawing functions.  */
679
680static void
681draw_line (HTMLPainter *painter,
682           gint x1, gint y1,
683           gint x2, gint y2)
684{
685        HTMLGdkPainter *gdk_painter;
686
687        gdk_painter = HTML_GDK_PAINTER (painter);
688
689        x1 -= gdk_painter->x1;
690        y1 -= gdk_painter->y1;
691        x2 -= gdk_painter->x1;
692        y2 -= gdk_painter->y1;
693
694        gdk_draw_line (gdk_painter->pixmap, gdk_painter->gc, x1, y1, x2, y2);
695}
696
697static void
698draw_ellipse (HTMLPainter *painter,
699              gint x, gint y,
700              gint width, gint height)
701{
702        HTMLGdkPainter *gdk_painter;
703
704        gdk_painter = HTML_GDK_PAINTER (painter);
705
706        gdk_draw_arc (gdk_painter->pixmap, gdk_painter->gc, TRUE,
707                      x - gdk_painter->x1, y - gdk_painter->y1,
708                      width, height,
709                      0, 360 * 64);
710}
711
712static void
713draw_rect (HTMLPainter *painter,
714           gint x, gint y,
715           gint width, gint height)
716{
717        HTMLGdkPainter *gdk_painter;
718
719        gdk_painter = HTML_GDK_PAINTER (painter);
720
721        gdk_draw_rectangle (gdk_painter->pixmap, gdk_painter->gc, FALSE,
722                            x - gdk_painter->x1, y - gdk_painter->y1,
723                            width, height);
724}
725
726static void
727draw_panel (HTMLPainter *painter,
728            GdkColor *bg,
729            gint x, gint y,
730            gint width, gint height,
731            GtkHTMLEtchStyle inset,
732            gint bordersize)
733{
734        HTMLGdkPainter *gdk_painter;
735        GdkColor *col1 = NULL, *col2 = NULL;
736        GdkColor dark, light;
737
738        #define INC 0x8000
739        #define DARK(c)  dark.c = MAX (((gint) bg->c) - INC, 0)
740        #define LIGHT(c) light.c = MIN (((gint) bg->c) + INC, 0xffff)
741
742        DARK(red);
743        DARK(green);
744        DARK(blue);
745        LIGHT(red);
746        LIGHT(green);
747        LIGHT(blue);
748
749        alloc_color (painter, &dark);
750        alloc_color (painter, &light);
751
752        gdk_painter = HTML_GDK_PAINTER (painter);
753
754        switch (inset) {
755        case GTK_HTML_ETCH_NONE:
756                /* use the current pen color */
757                col1 = NULL;
758                col2 = NULL;
759                break;
760        case GTK_HTML_ETCH_OUT:
761                col1 = &light;
762                col2 = &dark;
763                break;
764        default:
765        case GTK_HTML_ETCH_IN:
766                col1 = &dark;
767                col2 = &light;
768                break;
769        }
770       
771        x -= gdk_painter->x1;
772        y -= gdk_painter->y1;
773       
774        while (bordersize > 0) {
775                if (col2) {
776                        gdk_gc_set_foreground (gdk_painter->gc, col2);
777                }
778
779                gdk_draw_line (gdk_painter->pixmap, gdk_painter->gc,
780                               x + width - 1, y, x + width - 1, y + height - 1);
781                gdk_draw_line (gdk_painter->pixmap, gdk_painter->gc,
782                               x + 1, y + height - 1, x + width - 1, y + height - 1);
783                if (col1) {
784                        gdk_gc_set_foreground (gdk_painter->gc, col1);
785                }
786
787                gdk_draw_line (gdk_painter->pixmap, gdk_painter->gc,
788                               x, y, x + width - 2, y);
789                gdk_draw_line (gdk_painter->pixmap, gdk_painter->gc,
790                               x, y, x, y + height - 1);
791                bordersize--;
792                x++;
793                y++;
794                width-=2;
795                height-=2;
796        }
797
798        free_color (painter, &dark);
799        free_color (painter, &light);
800}
801
802static void
803draw_background (HTMLPainter *painter,
804                 GdkColor *color,
805                 GdkPixbuf *pixbuf,
806                 gint x, gint y,
807                 gint width, gint height,
808                 gint tile_x, gint tile_y)
809{
810        HTMLGdkPainter *gdk_painter;
811        gint pw;
812        gint ph;
813        gint tile_width, tile_height;
814        gint w, h;
815        ArtIRect expose, paint, clip;
816
817        gdk_painter = HTML_GDK_PAINTER (painter);
818
819        expose.x0 = x;
820        expose.y0 = y;
821        expose.x1 = x + width;
822        expose.y1 = y + height;
823
824        clip.x0 = gdk_painter->x1;
825        clip.x1 = gdk_painter->x2;
826        clip.y0 = gdk_painter->y1;
827        clip.y1 = gdk_painter->y2;
828        clip.x0 = gdk_painter->x1;
829
830        art_irect_intersect (&paint, &clip, &expose);
831        if (art_irect_empty (&paint))
832            return;
833
834        width = paint.x1 - paint.x0;
835        height = paint.y1 - paint.y0;   
836       
837        tile_x += paint.x0 - x;
838        tile_y += paint.y0 - y;
839       
840        x = paint.x0;
841        y = paint.y0;
842
843        if (!color && !pixbuf)
844                return;
845
846        if (color && !pixbuf) {
847                gdk_gc_set_foreground (gdk_painter->gc, color);
848                gdk_draw_rectangle (gdk_painter->pixmap, gdk_painter->gc,
849                                    TRUE, x - gdk_painter->x1, y - gdk_painter->y1,
850                                    width, height);     
851               
852        }
853
854        if (!pixbuf)
855                return;
856
857        pw = gdk_pixbuf_get_width (pixbuf);
858        ph = gdk_pixbuf_get_height (pixbuf);
859
860        /* optimize out some special cases */
861        if (pw == 1 && ph == 1) {
862                GdkColor pixcol;
863                guchar *p;
864
865                p = gdk_pixbuf_get_pixels (pixbuf);
866               
867                if (!(gdk_pixbuf_get_has_alpha (pixbuf) && (p[3] < 0x80))) {
868                        pixcol.red = p[0] * 0xff;
869                        pixcol.green = p[1] * 0xff;
870                        pixcol.blue = p[2] * 0xff;
871                       
872                        html_painter_alloc_color (painter, &pixcol);
873                        color = &pixcol;
874                }
875
876                if (color) {
877                        gdk_gc_set_foreground (gdk_painter->gc, color);
878                        gdk_draw_rectangle (gdk_painter->pixmap, gdk_painter->gc,
879                                            TRUE, x - gdk_painter->x1, y - gdk_painter->y1,
880                                            width, height);
881                }       
882               
883                return;
884        }
885
886        tile_width = (tile_x % pw) + width;
887        tile_height = (tile_y % ph) + height;
888
889        /* do tiling */
890        if (tile_width > pw || tile_height > ph) {
891                GdkPixmap *pixmap = NULL;
892                gint cw, ch, cx, cy;
893                gint dw, dh;
894                GdkGC *gc;
895                GdkBitmap *bitmap = NULL;
896               
897                dw = MIN (pw, tile_width);
898                dh = MIN (ph, tile_height);
899
900                gc = gdk_gc_new (gdk_painter->window);
901
902                if (color || !gdk_pixbuf_get_has_alpha (pixbuf)) {
903                        pixmap = gdk_pixmap_new (gdk_painter->window, dw, dh, -1);             
904                       
905                        if (color) {
906                                gdk_gc_set_foreground (gc, color);
907                                gdk_draw_rectangle (pixmap, gc,
908                                                    TRUE, 0, 0,
909                                                    dw, dh);
910                        }       
911
912                        gdk_pixbuf_render_to_drawable_alpha (pixbuf, pixmap,
913                                                     0, 0,
914                                                     0, 0,
915                                                     dw, dh,
916                                                     GDK_PIXBUF_ALPHA_BILEVEL,
917                                                     128,
918                                                     GDK_RGB_DITHER_NORMAL,
919                                                     x, y);
920                       
921                        gdk_gc_set_tile (gc, pixmap);
922                        gdk_gc_set_fill (gc, GDK_TILED);
923                        gdk_gc_set_ts_origin (gc,
924                                              x - (tile_x % pw) - gdk_painter->x1, 
925                                              y - (tile_y % ph) - gdk_painter->y1);
926
927                        gdk_draw_rectangle (gdk_painter->pixmap, gc, TRUE,
928                                            x - gdk_painter->x1, y - gdk_painter->y1,
929                                            width, height);
930                       
931                        gdk_pixmap_unref (pixmap);                     
932                        gdk_gc_unref (gc);                     
933                } else {
934                        int incr_x = 0;
935                        int incr_y = 0;
936
937                        /* Right now we only support GDK_PIXBUF_ALPHA_BILEVEL, so we
938                         * unconditionally create the clipping mask.
939                         */
940                        bitmap = gdk_pixmap_new (NULL, dw, dh, 1);
941                       
942                        gdk_pixbuf_render_threshold_alpha (pixbuf, bitmap,
943                                                           0, 0,
944                                                           0, 0,
945                                                           dw, dh,
946                                                           128);
947                       
948                        gdk_gc_set_clip_mask (gc, bitmap);
949                       
950                        pixmap = gdk_pixmap_new (gdk_painter->window, dw, dh, -1);             
951                        gdk_pixbuf_render_to_drawable (pixbuf, pixmap, gc,
952                                                       0, 0,
953                                                       0, 0,
954                                                       dw, dh,
955                                                       GDK_RGB_DITHER_NORMAL,
956                                                       x, y);
957                       
958                        cy = y;
959                        ch = height;
960                        h = tile_y % ph;
961                        while (ch > 0) {
962                                incr_y = dh - h;
963
964                                cx = x;
965                                cw = width;
966                                w = tile_x % pw;
967                                while (cw > 0) {
968                                        incr_x = dw - w;
969
970                                        gdk_gc_set_clip_origin (gc,
971                                                                cx - w - gdk_painter->x1,
972                                                                cy - h - gdk_painter->y1);
973                                       
974                                       
975                                        gdk_draw_pixmap (gdk_painter->pixmap, gc, pixmap,
976                                                         w, h, cx - gdk_painter->x1, cy - gdk_painter->y1,
977                                                         (cw >= incr_x) ? incr_x : cw,
978                                                         (ch >= incr_y) ? incr_y : ch);
979                                        cw -= incr_x;
980                                        cx += incr_x;
981                                        w = 0;
982                                }
983                                ch -= incr_y;
984                                cy += incr_y;
985                                h = 0;
986                        }
987                        gdk_pixmap_unref (pixmap);                     
988                        gdk_bitmap_unref (bitmap);
989                        gdk_gc_unref (gc);
990                }
991        } else {
992                if (color && gdk_pixbuf_get_has_alpha (pixbuf)) {
993                        gdk_gc_set_foreground (gdk_painter->gc, color);
994                        gdk_draw_rectangle (gdk_painter->pixmap, gdk_painter->gc, TRUE,
995                                            x - gdk_painter->x1, y - gdk_painter->y1,
996                                            width, height);     
997                }
998               
999                gdk_pixbuf_render_to_drawable_alpha (pixbuf, gdk_painter->pixmap,
1000                                                     tile_x % pw, tile_y % ph,
1001                                                     x - gdk_painter->x1, y - gdk_painter->y1,
1002                                                     width, height,
1003                                                     GDK_PIXBUF_ALPHA_BILEVEL,
1004                                                     128,
1005                                                     GDK_RGB_DITHER_NORMAL,
1006                                                     x, y);
1007        }
1008}
1009
1010static GdkPixbuf *
1011create_temporary_pixbuf (GdkPixbuf *src,
1012                         gint clip_width, gint clip_height)
1013{
1014        GdkPixbuf *pixbuf;
1015        gboolean has_alpha;
1016        guint bits_per_sample;
1017
1018        has_alpha = gdk_pixbuf_get_has_alpha (src);
1019        bits_per_sample = gdk_pixbuf_get_bits_per_sample (src);
1020
1021        pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, has_alpha, bits_per_sample, clip_width, clip_height);
1022
1023        return pixbuf;
1024}
1025
1026static void
1027draw_pixmap (HTMLPainter *painter,
1028             GdkPixbuf *pixbuf,
1029             gint x, gint y,
1030             gint scale_width, gint scale_height,
1031             const GdkColor *color)
1032{
1033        ArtIRect clip, image, paint;
1034        HTMLGdkPainter *gdk_painter;
1035        GdkPixbuf *tmp_pixbuf;
1036        guint n_channels;
1037        gint orig_width;
1038        gint orig_height;
1039        gint paint_width;
1040        gint paint_height;
1041        gint bilinear;
1042
1043        gdk_painter = HTML_GDK_PAINTER (painter);
1044
1045        orig_width = gdk_pixbuf_get_width (pixbuf);
1046        orig_height = gdk_pixbuf_get_height (pixbuf);
1047
1048        if (scale_width < 0)
1049                scale_width = orig_width;
1050        if (scale_height < 0)
1051                scale_height = orig_height;
1052
1053        image.x0 = x;
1054        image.y0 = y;
1055        image.x1 = x + scale_width;
1056        image.y1 = y + scale_height;
1057
1058        clip.x0 = gdk_painter->x1;
1059        clip.x1 = gdk_painter->x2;
1060        clip.y0 = gdk_painter->y1;
1061        clip.y1 = gdk_painter->y2;
1062
1063        art_irect_intersect (&paint, &clip, &image);
1064        if (art_irect_empty (&paint))
1065            return;
1066
1067        paint_width = paint.x1 - paint.x0;
1068        paint_height = paint.y1 - paint.y0;
1069
1070
1071        if (scale_width == orig_width && scale_height == orig_height && color == NULL && (!gdk_painter->alpha)) {
1072                gdk_pixbuf_render_to_drawable_alpha (pixbuf, gdk_painter->pixmap,
1073                                                     paint.x0 - image.x0,
1074                                                     paint.y0 - image.y0,
1075                                                     paint.x0 - clip.x0,
1076                                                     paint.y0 - clip.y0,
1077                                                     paint_width,
1078                                                     paint_height,
1079                                                     GDK_PIXBUF_ALPHA_BILEVEL,
1080                                                     128,
1081                                                     GDK_RGB_DITHER_NORMAL,
1082                                                     x, y);
1083                return;
1084        }
1085
1086        if (gdk_pixbuf_get_has_alpha (pixbuf) && gdk_painter->alpha) {
1087            tmp_pixbuf = gdk_pixbuf_get_from_drawable(NULL,
1088                                                      gdk_painter->pixmap,
1089                                                      gdk_window_get_colormap (gdk_painter->window),
1090                                                      paint.x0 - clip.x0,
1091                                                      paint.y0 - clip.y0,
1092                                                      0, 0, paint_width, paint_height);
1093        } else {
1094                tmp_pixbuf = create_temporary_pixbuf (pixbuf,
1095                                                      paint_width,
1096                                                      paint_height);
1097        }
1098
1099        if (tmp_pixbuf == NULL)
1100                return;
1101
1102        /*
1103         * FIXME this is a hack to work around a gdk-pixbuf bug
1104         * it could be removed when
1105         * http://bugzilla.ximian.com/show_bug.cgi?id=12968
1106         * is fixed.
1107         */
1108        bilinear = !((scale_width == 1) && (scale_height == 1));
1109
1110        gdk_pixbuf_composite (pixbuf, tmp_pixbuf,
1111                              0,
1112                              0,
1113                              paint_width, paint_height,
1114                              (double)-(paint.x0 - image.x0),
1115                              (double)-(paint.y0 - image.y0),
1116                              (gdouble) scale_width/ (gdouble) orig_width,
1117                              (gdouble) scale_height/ (gdouble) orig_height,
1118                              bilinear ? GDK_INTERP_BILINEAR : GDK_INTERP_NEAREST,
1119                              255);
1120
1121        if (color != NULL) {
1122                guchar *p, *q;
1123                guint i, j;
1124
1125                n_channels = gdk_pixbuf_get_n_channels (tmp_pixbuf);
1126                p = q = gdk_pixbuf_get_pixels (tmp_pixbuf);
1127                for (i = 0; i < paint_height; i++) {
1128                        p = q;
1129
1130                        for (j = 0; j < paint_width; j++) {
1131                                gint r, g, b, a;
1132
1133                                if (n_channels > 3)
1134                                        a = p[3];
1135                                else
1136                                        a = 0xff;
1137
1138                                r = (a * p[0] + color->red) >> 9;
1139                                g = (a * p[1] + color->green) >> 9;
1140                                b = (a * p[2] + color->blue) >> 9;
1141
1142                                p[0] = r;
1143                                p[1] = g;
1144                                p[2] = b;
1145
1146                                if (n_channels > 3)
1147                                        p[3] = 0xff;
1148
1149                                p += n_channels;
1150                        }
1151
1152                        q += gdk_pixbuf_get_rowstride (tmp_pixbuf);
1153                }
1154        }
1155
1156        gdk_pixbuf_render_to_drawable_alpha (tmp_pixbuf, gdk_painter->pixmap,
1157                                             0,
1158                                             0,
1159                                             paint.x0 - clip.x0,
1160                                             paint.y0 - clip.y0,
1161                                             paint_width,
1162                                             paint_height,
1163                                             GDK_PIXBUF_ALPHA_BILEVEL,
1164                                             128,
1165                                             GDK_RGB_DITHER_NORMAL,
1166                                             x, y);
1167        gdk_pixbuf_unref (tmp_pixbuf);
1168}
1169
1170static void
1171fill_rect (HTMLPainter *painter,
1172           gint x, gint y,
1173           gint width, gint height)
1174{
1175        HTMLGdkPainter *gdk_painter;
1176
1177        gdk_painter = HTML_GDK_PAINTER (painter);
1178
1179        gdk_draw_rectangle (gdk_painter->pixmap, gdk_painter->gc,
1180                            TRUE, x - gdk_painter->x1, y - gdk_painter->y1,
1181                            width, height);
1182}
1183
1184static EFontStyle
1185e_style (GtkHTMLFontStyle style)
1186{
1187        EFontStyle rv = E_FONT_PLAIN;
1188
1189        if (style & GTK_HTML_FONT_STYLE_BOLD)   rv |= E_FONT_BOLD;
1190        if (style & GTK_HTML_FONT_STYLE_ITALIC) rv |= E_FONT_ITALIC;
1191
1192        return rv;
1193}
1194
1195static gint
1196draw_spell_error (HTMLPainter *painter, gint x, gint y, const gchar *text, gint len)
1197{
1198        HTMLGdkPainter *gdk_painter;
1199        EFont *e_font;
1200        GdkGCValues values;
1201        guint width;
1202        gchar dash [2];
1203
1204        gdk_painter = HTML_GDK_PAINTER (painter);
1205
1206        x -= gdk_painter->x1;
1207        y -= gdk_painter->y1;
1208
1209        e_font  = html_painter_get_font  (painter, painter->font_face, painter->font_style);
1210        width   = e_font_utf8_text_width (e_font, e_style (painter->font_style), text,
1211                                          g_utf8_offset_to_pointer (text, len) - text);
1212
1213        gdk_gc_get_values (gdk_painter->gc, &values);
1214        gdk_gc_set_fill (gdk_painter->gc, GDK_OPAQUE_STIPPLED);
1215        dash [0] = 2;
1216        dash [1] = 2;
1217        gdk_gc_set_line_attributes (gdk_painter->gc, 1, GDK_LINE_ON_OFF_DASH, values.cap_style, values.join_style);
1218        gdk_gc_set_dashes (gdk_painter->gc, 2, dash, 2);
1219        gdk_draw_line (gdk_painter->pixmap, gdk_painter->gc, x, y, x + width, y);
1220        gdk_gc_set_dashes (gdk_painter->gc, 0, dash, 2);
1221        gdk_draw_line (gdk_painter->pixmap, gdk_painter->gc, x, y + 1, x + width, y + 1);
1222        gdk_gc_set_line_attributes (gdk_painter->gc, values.line_width,
1223                                    values.line_style, values.cap_style, values.join_style);
1224
1225        return width;
1226}
1227
1228static void
1229draw_embedded (HTMLPainter * p, HTMLEmbedded *o, gint x, gint y)
1230{
1231        HTMLGdkPainter *gdk_painter = HTML_GDK_PAINTER(p);
1232        GtkWidget *embedded_widget;
1233
1234        embedded_widget = html_embedded_get_widget (o);
1235        if (embedded_widget && GTK_IS_HTML_EMBEDDED (embedded_widget)) {
1236                gtk_signal_emit_by_name (GTK_OBJECT (embedded_widget),
1237                                         "draw_gdk",
1238                                         gdk_painter->pixmap,
1239                                         gdk_painter->gc,
1240                                         x, y);
1241        }
1242}
1243
1244static void
1245draw_text (HTMLPainter *painter,
1246           gint x, gint y,
1247           const gchar *text,
1248           gint len)
1249{
1250        HTMLGdkPainter *gdk_painter;
1251        EFont *e_font;
1252
1253        gdk_painter = HTML_GDK_PAINTER (painter);
1254
1255        if (len == -1)
1256                len = g_utf8_strlen (text, -1);
1257
1258        x -= gdk_painter->x1;
1259        y -= gdk_painter->y1;
1260
1261        e_font = html_painter_get_font (painter,
1262                                        painter->font_face,
1263                                        painter->font_style);
1264
1265        e_font_draw_utf8_text (gdk_painter->pixmap,
1266                               e_font,
1267                               e_style (painter->font_style),
1268                               gdk_painter->gc,
1269                               x, y,
1270                               text,
1271                               g_utf8_offset_to_pointer (text, len) - text);
1272
1273        if (painter->font_style & (GTK_HTML_FONT_STYLE_UNDERLINE
1274                                   | GTK_HTML_FONT_STYLE_STRIKEOUT)) {
1275                guint width;
1276
1277                width = e_font_utf8_text_width (e_font,
1278                                                e_style (painter->font_style),
1279                                                text,
1280                                                g_utf8_offset_to_pointer (text, len) - text);
1281
1282                if (painter->font_style & GTK_HTML_FONT_STYLE_UNDERLINE)
1283                        gdk_draw_line (gdk_painter->pixmap, gdk_painter->gc,
1284                                       x, y + 1,
1285                                       x + width, y + 1);
1286
1287                if (painter->font_style & GTK_HTML_FONT_STYLE_STRIKEOUT)
1288                        gdk_draw_line (gdk_painter->pixmap, gdk_painter->gc,
1289                                       x, y - e_font_ascent (e_font) / 2,
1290                                       x + width, y - e_font_ascent (e_font) / 2);
1291        }
1292}
1293
1294static void
1295draw_shade_line (HTMLPainter *painter,
1296                 gint x, gint y,
1297                 gint width)
1298{
1299        HTMLGdkPainter *gdk_painter;
1300
1301        gdk_painter = HTML_GDK_PAINTER (painter);
1302       
1303        x -= gdk_painter->x1;
1304        y -= gdk_painter->y1;
1305       
1306        gdk_gc_set_foreground (gdk_painter->gc, &gdk_painter->dark);
1307        gdk_draw_line (gdk_painter->pixmap, gdk_painter->gc, x, y, x+width, y);
1308        gdk_gc_set_foreground (gdk_painter->gc, &gdk_painter->light);
1309        gdk_draw_line (gdk_painter->pixmap, gdk_painter->gc, x, y + 1, x + width, y + 1);
1310}
1311
1312static guint
1313calc_ascent (HTMLPainter *painter, GtkHTMLFontStyle style, HTMLFontFace *face)
1314{
1315        HTMLGdkPainter *gdk_painter;
1316        EFont *e_font;
1317
1318        gdk_painter = HTML_GDK_PAINTER (painter);
1319
1320        e_font = html_painter_get_font (painter, face, style);
1321        if (e_font == NULL)
1322                return 0;
1323
1324        return e_font_ascent (e_font);
1325}
1326
1327static guint
1328calc_descent (HTMLPainter *painter, GtkHTMLFontStyle style, HTMLFontFace *face)
1329{
1330        HTMLGdkPainter *gdk_painter;
1331        EFont *e_font;
1332
1333        gdk_painter = HTML_GDK_PAINTER (painter);
1334
1335        e_font = html_painter_get_font (painter, face, style);
1336        if (e_font == NULL)
1337                return 0;
1338
1339        return e_font_descent (e_font);
1340}
1341
1342static guint
1343calc_text_width (HTMLPainter *painter,
1344                 const gchar *text,
1345                 guint len,
1346                 GtkHTMLFontStyle style,
1347                 HTMLFontFace *face)
1348{
1349        HTMLGdkPainter *gdk_painter;
1350        HTMLFont *font;
1351        EFont *e_font;
1352        gint width;
1353
1354        gdk_painter = HTML_GDK_PAINTER (painter);
1355        font = html_painter_get_html_font (painter, face, style);
1356        e_font = font->data;
1357
1358        width = e_font_utf8_text_width (e_font, e_style (style), text, g_utf8_offset_to_pointer (text, len) - text);
1359
1360        /* printf ("calc_text_width text: %s len: %d\n", text, len);
1361        { gint i; printf ("["); for (i=0;i<g_utf8_offset_to_pointer (text, len)-text; i++)
1362        printf ("%c", text [i]); printf ("] ");}
1363        printf ("%d (%p)\n", width, e_font); */
1364        return width;
1365}
1366
1367static guint
1368calc_text_width_bytes (HTMLPainter *painter, const gchar *text,
1369                       guint bytes_len, HTMLFont *font, GtkHTMLFontStyle style)
1370{
1371        return e_font_utf8_text_width (font->data, e_style (style), text, bytes_len);
1372}
1373
1374static guint
1375get_pixel_size (HTMLPainter *painter)
1376{
1377        return 1;
1378}
1379
1380static guint
1381get_page_width (HTMLPainter *painter, HTMLEngine *e)
1382{
1383        return html_engine_get_view_width (e) + e->leftBorder + e->rightBorder;
1384}
1385
1386static guint
1387get_page_height (HTMLPainter *painter, HTMLEngine *e)
1388{
1389        return html_engine_get_view_height (e) + e->topBorder + e->bottomBorder;
1390}
1391
1392static void
1393init_color (GdkColor *color, gushort red, gushort green, gushort blue)
1394{
1395        color->pixel = 0;
1396        color->red = red;
1397        color->green = green;
1398        color->blue = blue;
1399}
1400
1401static void
1402init (GtkObject *object)
1403{
1404        HTMLGdkPainter *gdk_painter;
1405
1406        gdk_painter = HTML_GDK_PAINTER (object);
1407
1408        gdk_painter->window = NULL;
1409
1410        gdk_painter->alpha = TRUE;
1411        gdk_painter->gc = NULL;
1412
1413        gdk_painter->double_buffer = TRUE;
1414        gdk_painter->pixmap = NULL;
1415        gdk_painter->x1 = gdk_painter->y1 = 0;
1416        gdk_painter->x2 = gdk_painter->y2 = 0;
1417        gdk_painter->set_background = FALSE;
1418        gdk_painter->do_clear = FALSE;
1419
1420        init_color (& gdk_painter->background, 0xffff, 0xffff, 0xffff);
1421        init_color (& gdk_painter->dark, 0, 0, 0);
1422        init_color (& gdk_painter->light, 0, 0, 0);
1423}
1424
1425static void
1426class_init (GtkObjectClass *object_class)
1427{
1428        HTMLPainterClass *painter_class;
1429
1430        painter_class = HTML_PAINTER_CLASS (object_class);
1431
1432        object_class->finalize = finalize;
1433
1434        painter_class->begin = begin;
1435        painter_class->end = end;
1436        painter_class->alloc_font = alloc_e_font;
1437        painter_class->ref_font   = ref_font;
1438        painter_class->unref_font = unref_font;
1439        painter_class->alloc_color = alloc_color;
1440        painter_class->free_color = free_color;
1441        painter_class->calc_ascent = calc_ascent;
1442        painter_class->calc_descent = calc_descent;
1443        painter_class->calc_text_width = calc_text_width;
1444        painter_class->calc_text_width_bytes = calc_text_width_bytes;
1445        painter_class->set_pen = set_pen;
1446        painter_class->get_black = get_black;
1447        painter_class->draw_line = draw_line;
1448        painter_class->draw_rect = draw_rect;
1449        painter_class->draw_text = draw_text;
1450        painter_class->draw_spell_error = draw_spell_error;
1451        painter_class->fill_rect = fill_rect;
1452        painter_class->draw_pixmap = draw_pixmap;
1453        painter_class->draw_ellipse = draw_ellipse;
1454        painter_class->clear = clear;
1455        painter_class->set_background_color = set_background_color;
1456        painter_class->draw_shade_line = draw_shade_line;
1457        painter_class->draw_panel = draw_panel;
1458        painter_class->set_clip_rectangle = set_clip_rectangle;
1459        painter_class->draw_background = draw_background;
1460        painter_class->get_pixel_size = get_pixel_size;
1461        painter_class->draw_embedded = draw_embedded;
1462        painter_class->get_page_width = get_page_width;
1463        painter_class->get_page_height = get_page_height;
1464        painter_class->get_font_manager_id = get_font_manager_id;
1465
1466        parent_class = gtk_type_class (html_painter_get_type ());
1467}
1468
1469GtkType
1470html_gdk_painter_get_type (void)
1471{
1472        static GtkType type = 0;
1473
1474        if (type == 0) {
1475                static const GtkTypeInfo info = {
1476                        "HTMLGdkPainter",
1477                        sizeof (HTMLGdkPainter),
1478                        sizeof (HTMLGdkPainterClass),
1479                        (GtkClassInitFunc) class_init,
1480                        (GtkObjectInitFunc) init,
1481                        /* reserved_1 */ NULL,
1482                        /* reserved_2 */ NULL,
1483                        (GtkClassInitFunc) NULL,
1484                };
1485
1486                type = gtk_type_unique (HTML_TYPE_PAINTER, &info);
1487        }
1488
1489        return type;
1490}
1491
1492
1493HTMLPainter *
1494html_gdk_painter_new (gboolean double_buffer)
1495{
1496        HTMLGdkPainter *new;
1497
1498        new = gtk_type_new (html_gdk_painter_get_type ());
1499
1500        new->double_buffer = double_buffer;
1501
1502        return HTML_PAINTER (new);
1503}
1504
1505void
1506html_gdk_painter_realize (HTMLGdkPainter *gdk_painter,
1507                          GdkWindow *window)
1508{
1509        GdkColormap *colormap;
1510
1511        g_return_if_fail (gdk_painter != NULL);
1512        g_return_if_fail (window != NULL);
1513       
1514        gdk_painter->gc = gdk_gc_new (window);
1515        gdk_painter->window = window;
1516
1517        colormap = gdk_window_get_colormap (window);
1518
1519        gdk_painter->light.red = 0xffff;
1520        gdk_painter->light.green = 0xffff;
1521        gdk_painter->light.blue = 0xffff;
1522        gdk_colormap_alloc_color (colormap, &gdk_painter->light, TRUE, TRUE);
1523
1524        gdk_painter->dark.red = 0x7fff;
1525        gdk_painter->dark.green = 0x7fff;
1526        gdk_painter->dark.blue = 0x7fff;
1527        gdk_colormap_alloc_color (colormap, &gdk_painter->dark, TRUE, TRUE);
1528
1529        gdk_painter->black.red = 0x0000;
1530        gdk_painter->black.green = 0x0000;
1531        gdk_painter->black.blue = 0x0000;
1532        gdk_colormap_alloc_color (colormap, &gdk_painter->black, TRUE, TRUE);
1533}
1534
1535void
1536html_gdk_painter_unrealize (HTMLGdkPainter *painter)
1537{
1538        g_return_if_fail (painter != NULL);
1539        g_return_if_fail (HTML_IS_GDK_PAINTER (painter));
1540
1541        if (html_gdk_painter_realized (painter)) {
1542                gdk_gc_unref (painter->gc);
1543                painter->gc = NULL;
1544
1545                painter->window = NULL;
1546        }
1547}
1548
1549gboolean
1550html_gdk_painter_realized (HTMLGdkPainter *painter)
1551{
1552        g_return_val_if_fail (painter != NULL, FALSE);
1553        g_return_val_if_fail (HTML_IS_GDK_PAINTER (painter), FALSE);
1554
1555        if (painter->window == NULL)
1556                return FALSE;
1557        else
1558                return TRUE;
1559}
Note: See TracBrowser for help on using the repository browser.