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

Revision 18136, 10.4 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) 1999, 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 <gtk/gtksignal.h>
24#include "htmlengine-edit-cursor.h"
25#include "htmlcolor.h"
26#include "htmldrawqueue.h"
27#include "htmlengine.h"
28#include "htmlgdkpainter.h"
29#include "htmlimage.h"
30#include "htmlpainter.h"
31#include "htmlobject.h"
32#include "htmltextslave.h"
33#include "htmlsettings.h"
34#include "gtkhtml.h"
35
36
37/* HTMLDrawQueueClearElement handling.  */
38
39static HTMLDrawQueueClearElement *
40clear_element_new (gint            x,
41                   gint            y,
42                   guint           width,
43                   guint           height,
44                   const GdkColor *background_color)
45{
46        HTMLDrawQueueClearElement *new;
47
48        new = g_new (HTMLDrawQueueClearElement, 1);
49
50        new->x = x;
51        new->y = y;
52        new->width = width;
53        new->height = height;
54
55        /* GDK color API non const-correct.  */
56        new->background_color = gdk_color_copy ((GdkColor *) background_color);
57
58        new->background_image = NULL;
59        new->background_image_x_offset = 0;
60        new->background_image_y_offset = 0;
61
62        return new;
63}
64
65static HTMLDrawQueueClearElement *
66clear_element_new_with_background (gint       x,
67                                   gint       y,
68                                   guint      width,
69                                   guint      height,
70                                   GdkPixbuf *background_image,
71                                   guint      background_image_x_offset,
72                                   guint      background_image_y_offset)
73{
74        HTMLDrawQueueClearElement *new;
75
76        new = g_new (HTMLDrawQueueClearElement, 1);
77
78        new->x = x;
79        new->y = y;
80        new->width = width;
81        new->height = height;
82
83        new->background_image = gdk_pixbuf_ref (background_image);
84
85        new->background_image_x_offset = background_image_x_offset;
86        new->background_image_y_offset = background_image_y_offset;
87
88        new->background_color = NULL;
89
90        return new;
91}
92
93static void
94clear_element_destroy (HTMLDrawQueueClearElement *elem)
95{
96        g_return_if_fail (elem != NULL);
97
98        if (elem->background_color != NULL)
99                gdk_color_free (elem->background_color);
100
101        if (elem->background_image != NULL)
102                gdk_pixbuf_unref (elem->background_image);
103
104        g_free (elem);
105}
106
107
108HTMLDrawQueue *
109html_draw_queue_new (HTMLEngine *engine)
110{
111        HTMLDrawQueue *new;
112
113        g_return_val_if_fail (engine != NULL, NULL);
114
115        new = g_new (HTMLDrawQueue, 1);
116
117        new->engine = engine;
118
119        new->elems = NULL;
120        new->last = NULL;
121
122        new->clear_elems = NULL;
123        new->clear_last = NULL;
124
125        return new;
126}
127
128void
129html_draw_queue_destroy (HTMLDrawQueue *queue)
130{
131        GList *p;
132
133        g_return_if_fail (queue != NULL);
134
135        for (p = queue->elems; p != NULL; p = p->next) {
136                HTMLObject *obj;
137
138                obj = p->data;
139                obj->redraw_pending = FALSE;
140        }
141
142        g_list_free (queue->elems);
143
144        g_free (queue);
145}
146
147void
148html_draw_queue_add (HTMLDrawQueue *queue, HTMLObject *object)
149{
150        g_return_if_fail (queue != NULL);
151        g_return_if_fail (object != NULL);
152
153        if (object->redraw_pending)
154                return;
155
156        object->redraw_pending = TRUE;
157
158        queue->last = g_list_append (queue->last, object);
159        if (queue->elems == NULL && queue->clear_elems == NULL)
160                gtk_signal_emit_by_name (GTK_OBJECT (queue->engine), "draw_pending");
161
162        if (queue->elems == NULL)
163                queue->elems = queue->last;
164        else
165                queue->last = queue->last->next;
166}
167
168
169static void
170add_clear (HTMLDrawQueue *queue,
171           HTMLDrawQueueClearElement *elem)
172{
173        queue->clear_last = g_list_append (queue->clear_last, elem);
174        if (queue->elems == NULL && queue->clear_elems == NULL)
175                gtk_signal_emit_by_name (GTK_OBJECT (queue->engine), "draw_pending");
176
177        if (queue->clear_elems == NULL)
178                queue->clear_elems = queue->clear_last;
179        else
180                queue->clear_last = queue->clear_last->next;
181}
182
183void
184html_draw_queue_add_clear (HTMLDrawQueue *queue,
185                           gint x,
186                           gint y,
187                           guint width,
188                           guint height,
189                           const GdkColor *background_color)
190{
191        HTMLDrawQueueClearElement *new;
192
193        g_return_if_fail (queue != NULL);
194        g_return_if_fail (background_color != NULL);
195
196        new = clear_element_new (x, y, width, height, background_color);
197        add_clear (queue, new);
198}
199
200void
201html_draw_queue_add_clear_with_background  (HTMLDrawQueue *queue,
202                                            gint x,
203                                            gint y,
204                                            guint width,
205                                            guint height,
206                                            GdkPixbuf *background_image,
207                                            guint background_image_x_offset,
208                                            guint background_image_y_offset)
209{
210        HTMLDrawQueueClearElement *new;
211
212        g_return_if_fail (queue != NULL);
213        g_return_if_fail (background_image != NULL);
214
215        new = clear_element_new_with_background (x, y, width, height, background_image,
216                                                 background_image_x_offset, background_image_y_offset);
217        add_clear (queue, new);
218}
219
220static void
221draw_link_focus (HTMLObject *o, HTMLEngine *e, gint x, gint y)
222{
223        HTMLGdkPainter *p = HTML_GDK_PAINTER (e->painter);
224        GdkColor *c = &html_colorset_get_color (e->settings->color_set, HTMLTextColor)->color;
225        GdkGCValues values;
226        gchar dash [2];
227
228        /* printf ("draw_link_focus\n"); */
229
230        gdk_gc_set_foreground (p->gc, c);
231        gdk_gc_get_values (p->gc, &values);
232
233        dash [0] = 1;
234        dash [1] = 1;
235        gdk_gc_set_line_attributes (p->gc, 1, GDK_LINE_ON_OFF_DASH, values.cap_style, values.join_style);
236        gdk_gc_set_dashes (p->gc, 2, dash, 2);
237        gdk_draw_line (p->pixmap, p->gc, x, y, x + o->width, y);
238        gdk_draw_line (p->pixmap, p->gc, x, y, x, y + o->ascent + 1);
239        gdk_draw_line (p->pixmap, p->gc, x + o->width - 1, y, x + o->width - 1, y + o->ascent + 1);
240        gdk_gc_set_line_attributes (p->gc, 1, values.line_style, values.cap_style, values.join_style);
241}
242
243static void
244draw_image_focus (HTMLObject *o, HTMLEngine *e, gint x, gint y)
245{
246        HTMLGdkPainter *p = HTML_GDK_PAINTER (e->painter);
247        GdkColor *c = &html_colorset_get_color (e->settings->color_set, HTMLTextColor)->color;
248        GdkGCValues values;
249        gchar dash [2];
250
251        /* printf ("draw_image_focus\n"); */
252
253        gdk_gc_set_foreground (p->gc, c);
254        gdk_gc_get_values (p->gc, &values);
255
256        dash [0] = 1;
257        dash [1] = 1;
258        gdk_gc_set_line_attributes (p->gc, 1, GDK_LINE_ON_OFF_DASH, values.cap_style, values.join_style);
259        gdk_gc_set_dashes (p->gc, 2, dash, 2);
260        gdk_draw_rectangle (p->pixmap, p->gc, 0, x, y, o->width - 1, o->ascent + o->descent - 1);
261        gdk_gc_set_line_attributes (p->gc, 1, values.line_style, values.cap_style, values.join_style);
262}
263
264static void
265draw_obj (HTMLDrawQueue *queue,
266          HTMLObject *obj)
267{
268        HTMLEngine *e;
269        gint x1, y1, x2, y2;
270        gint tx, ty;
271
272        if (obj->width == 0 || obj->ascent + obj->descent == 0)
273                return;
274
275        e = queue->engine;
276
277        html_object_engine_translation (obj, e, &tx, &ty);
278        if (!html_object_engine_intersection (obj, e, tx, ty, &x1, &y1, &x2, &y2))
279                return;
280
281        html_painter_begin (e->painter, x1, y1, x2, y2);
282
283        /* FIXME we are duplicating code from HTMLEngine here.
284           Instead, there should be a function in HTMLEngine to paint
285           stuff.  */
286
287        /* Draw the actual object.  */
288
289        if (html_object_is_transparent (obj)) {
290                html_engine_draw_background (e, x1, y1, x2, y2);
291                html_object_draw_background (obj, e->painter,
292                                             obj->x, obj->y - obj->ascent,
293                                             obj->width, obj->ascent + obj->descent,
294                                             tx, ty);
295        }
296
297        /* printf ("draw_obj %p\n", obj); */
298        html_object_draw (obj,
299                          e->painter,
300                          obj->x, obj->y - obj->ascent,
301                          obj->width, obj->ascent + obj->descent,
302                          tx, ty);
303
304#if 0
305        {
306                GdkColor c;
307
308                c.pixel = rand ();
309                html_painter_set_pen (e->painter, &c);
310                html_painter_draw_line (e->painter, x1, y1, x2 - 1, y2 - 1);
311                html_painter_draw_line (e->painter, x2 - 1, y1, x1, y2 - 1);
312        }
313#endif
314
315
316        if (HTML_IS_GDK_PAINTER (queue->engine->painter)) {
317                if (HTML_IS_TEXT_SLAVE (obj) && queue->engine->focus_object == HTML_OBJECT (HTML_TEXT_SLAVE (obj)->owner))
318                        draw_link_focus (obj, queue->engine, obj->x + tx - x1, obj->y - obj->ascent + ty - y1);
319                else if (queue->engine->focus_object == obj && HTML_IS_IMAGE (obj))
320                        draw_image_focus (obj, queue->engine, obj->x + tx - x1, obj->y - obj->ascent + ty - y1);
321        }
322
323        /* Done.  */
324        html_painter_end (e->painter);
325
326        if (e->editable)
327                html_engine_draw_cursor_in_area (e, x1, y1, x2 - x1, y2 - y1);
328}
329
330static void
331clear (HTMLDrawQueue *queue,
332       HTMLDrawQueueClearElement *elem)
333{
334        HTMLEngine *e;
335        gint x1, y1, x2, y2;
336
337        e = queue->engine;
338
339        x1 = elem->x + e->leftBorder - e->x_offset;
340        y1 = elem->y + e->topBorder - e->y_offset;
341
342        x2 = x1 + elem->width;
343        y2 = y1 + elem->height;
344
345        html_painter_begin (e->painter, x1, y1, x2, y2);
346
347        if (elem->background_color != NULL) {
348                html_engine_draw_background (e, x1, y1, x2, y2);
349        }
350
351#if 0
352        html_painter_set_pen (e->painter, html_colorset_get_color_allocated (e->painter, HTMLTextColor));
353        html_painter_draw_line (e->painter, x1, y1, x2 - 1, y2 - 1);
354        html_painter_draw_line (e->painter, x2 - 1, y1, x1, y2 - 1);
355#endif
356
357        html_painter_end (e->painter);
358
359        if (e->editable)
360                html_engine_draw_cursor_in_area (e, x1, y1, x2 - x1, y2 - y1);
361}
362
363void
364html_draw_queue_clear (HTMLDrawQueue *queue)
365{
366        GList *p;
367
368        for (p = queue->elems; p != NULL; p = p->next) {
369                HTMLObject *obj = HTML_OBJECT (p->data);
370                       
371                obj->redraw_pending = FALSE;
372                if (obj->free_pending) {
373                        g_free (obj);
374                        p->data = (gpointer)0xdeadbeef;
375                }
376        }
377
378        g_list_free (queue->clear_elems);
379        g_list_free (queue->elems);
380
381        queue->clear_elems = NULL;
382        queue->clear_last = NULL;
383        queue->elems = NULL;
384        queue->last = NULL;
385}
386
387void
388html_draw_queue_flush (HTMLDrawQueue *queue)
389{
390        GList *p;
391        GdkVisual *vis;
392
393        /* check to make sure we have something to draw on */
394
395        vis = queue->engine->window ? gdk_window_get_visual (queue->engine->window): NULL;
396
397        /* Draw clear areas.  */
398
399        for (p = queue->clear_elems; p != NULL; p = p->next) {
400                HTMLDrawQueueClearElement *clear_elem;
401
402                clear_elem = p->data;
403                if (vis)
404                        clear (queue, clear_elem);
405                clear_element_destroy (clear_elem);
406        }
407
408
409        /* Draw objects.  */
410
411        if (vis) {
412                for (p = queue->elems; p != NULL; p = p->next) {
413                        HTMLObject *obj = HTML_OBJECT (p->data);
414                       
415                        if (obj->redraw_pending && !obj->free_pending) {
416                                draw_obj (queue, obj);
417                                obj->redraw_pending = FALSE;
418                        }
419                }
420        }
421        html_draw_queue_clear (queue);
422}
423
424
425
426
427
428
429
430
431
Note: See TracBrowser for help on using the repository browser.