source: trunk/third/gtkhtml3/src/htmlfontmanager.c @ 21116

Revision 21116, 10.5 KB checked in by ghudson, 20 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r21115, 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 <string.h>
24#include <pango/pango.h>
25
26#include "gtkhtmlfontstyle.h"
27#include "htmlfontmanager.h"
28#include "htmlpainter.h"
29#include "htmlengine.h"
30
31static void
32html_font_set_init (HTMLFontSet *set, gchar *face)
33{
34        memset (set, 0, GTK_HTML_FONT_STYLE_MAX_FONT * sizeof (HTMLFont *));
35        set->ref_count = 1;
36        set->face = g_strdup (face);
37}
38
39static HTMLFontSet *
40html_font_set_new (gchar *face)
41{
42        HTMLFontSet *set;
43
44        set = g_new (HTMLFontSet, 1);
45        html_font_set_init (set, face);
46
47        return set;
48}
49
50static gboolean
51html_font_set_face (HTMLFontSet *set, gchar *face)
52{
53        if (!set->face || strcmp (set->face, face)) {
54                if (set->face)
55                        g_free (set->face);
56                set->face = g_strdup (face);
57                return TRUE;
58        }
59        return FALSE;
60}
61
62static void
63html_font_set_release (HTMLFontSet *set, HTMLPainter *painter)
64{
65        gint i;
66
67        for (i=0; i<GTK_HTML_FONT_STYLE_MAX_FONT; i++) {
68                if (set->font [i])
69                        html_font_unref (set->font [i], painter);
70                set->font [i] = NULL;
71        }
72}
73
74static void
75html_font_set_unref (HTMLFontSet *set, HTMLPainter *painter)
76{
77        set->ref_count --;
78        if (!set->ref_count) {
79                html_font_set_release (set, painter);
80                if (set->face)
81                        g_free (set->face);
82
83                g_free (set);
84        }
85}
86
87void
88html_font_manager_init (HTMLFontManager *manager, HTMLPainter *painter)
89{
90        manager->font_sets     = g_hash_table_new (g_str_hash, g_str_equal);
91        manager->var_size      = 12*PANGO_SCALE;
92        manager->var_points    = FALSE;
93        manager->fix_size      = 12*PANGO_SCALE;
94        manager->fix_points    = FALSE;
95        manager->magnification = 1.0;
96        manager->painter       = painter;
97
98        html_font_set_init (&manager->variable, NULL);
99        html_font_set_init (&manager->fixed, NULL);
100}
101
102void
103html_font_manager_set_magnification (HTMLFontManager *manager, gdouble magnification)
104{
105        g_return_if_fail (magnification > 0.0);
106
107        if (magnification != manager->magnification) {
108                manager->magnification = magnification;
109                html_font_manager_clear_font_cache (manager);
110        }
111}
112
113static gboolean
114destroy_font_set_foreach (gpointer key, gpointer font_set, gpointer data)
115{
116        g_free (key);
117        html_font_set_unref (font_set, HTML_PAINTER (data));
118
119        return TRUE;
120}
121
122static void
123clear_additional_font_sets (HTMLFontManager *manager)
124{
125        g_hash_table_foreach_remove (manager->font_sets, destroy_font_set_foreach, manager->painter);   
126}
127
128void
129html_font_manager_clear_font_cache (HTMLFontManager *manager)
130{
131        html_font_set_release (&manager->variable, manager->painter);
132        html_font_set_release (&manager->fixed, manager->painter);
133        clear_additional_font_sets (manager);
134}
135
136void
137html_font_manager_finalize (HTMLFontManager *manager)
138{
139        html_font_set_release (&manager->variable, manager->painter);
140        html_font_set_release (&manager->fixed, manager->painter);
141        g_free (manager->fixed.face);
142        g_free (manager->variable.face);
143
144        clear_additional_font_sets (manager);
145        g_hash_table_destroy (manager->font_sets);
146}
147
148void
149html_font_manager_set_default (HTMLFontManager *manager, gchar *variable, gchar *fixed,
150                               gint var_size, gboolean var_points, gint fix_size, gboolean fix_points)
151{
152        gboolean changed = FALSE;
153
154        /* variable width fonts */
155        changed = html_font_set_face (&manager->variable, variable);
156        if (manager->var_size != var_size || manager->var_points != var_points) {
157                manager->var_size = var_size;
158                manager->var_points = var_points;
159                clear_additional_font_sets (manager);
160                changed = TRUE;
161        }
162
163        if (changed) {
164                html_font_set_release (&manager->variable, manager->painter);
165        }
166
167        /* fixed width fonts */
168        changed = html_font_set_face (&manager->fixed, fixed);
169        if (manager->fix_size != fix_size || manager->fix_points != fix_points) {
170                manager->fix_size = fix_size;
171                manager->fix_points = fix_points;
172                changed = TRUE;
173        }
174
175        if (changed) {
176                /*
177                 * NOTE we clear both if fixed changes because the plain painter pulls nasty
178                 * tricks with using fixed fonts in the variable manager so if the fixed font
179                 * change the variable font may change too.
180                 */
181                html_font_set_release (&manager->variable, manager->painter);
182                html_font_set_release (&manager->fixed, manager->painter);
183        }
184}
185
186static gint
187get_font_num (GtkHTMLFontStyle style)
188{
189        style |= (style & GTK_HTML_FONT_STYLE_SIZE_MASK) ? 0 : GTK_HTML_FONT_STYLE_SIZE_3;
190       
191        return (style & GTK_HTML_FONT_STYLE_MAX_FONT_MASK);
192}
193
194static gint
195html_font_set_get_idx (GtkHTMLFontStyle style)
196{
197        return get_font_num (style) - 1;
198}
199
200static HTMLFontSet *
201get_font_set (HTMLFontManager *manager, gchar *face, GtkHTMLFontStyle style)
202{
203        return (face)
204                ? g_hash_table_lookup (manager->font_sets, face)
205                : ((style & GTK_HTML_FONT_STYLE_FIXED) ? &manager->fixed : &manager->variable);
206}
207
208static gdouble
209get_real_font_size (HTMLFontManager *manager, GtkHTMLFontStyle style)
210{
211        gint size = (get_font_num (style) & GTK_HTML_FONT_STYLE_SIZE_MASK) -  GTK_HTML_FONT_STYLE_SIZE_3;
212        gint base_size = style & GTK_HTML_FONT_STYLE_FIXED ? manager->fix_size : manager->var_size;
213
214        return manager->magnification * (base_size + (size > 0 ? (1 << size) : size) * base_size/8.0);
215}
216
217static void
218html_font_set_font (HTMLFontManager *manager, HTMLFontSet *set, GtkHTMLFontStyle style, HTMLFont *font)
219{
220        gint idx;
221
222        g_assert (font);
223        g_assert (set);
224
225        /* set font in font set */
226        idx = html_font_set_get_idx (style);
227        if (set->font [idx] && font != set->font [idx])
228                html_font_unref (set->font [idx], manager->painter);
229        set->font [idx] = font;
230}
231
232static HTMLFont *
233get_font (HTMLFontManager *manager, HTMLFontSet **set, gchar *face, GtkHTMLFontStyle style)
234{
235        HTMLFont *font = NULL;
236
237        *set = get_font_set (manager, face, style);
238        if (*set)
239                font = (*set)->font [html_font_set_get_idx (style)];
240        return font;
241}
242
243gchar *
244html_font_manager_get_attr (gchar *font_name, gint n)
245{
246    gchar *s, *end;
247
248    /* Search paramether */
249    for (s=font_name; n; n--,s++)
250            s = strchr (s,'-');
251
252    if (s && *s != 0) {
253            end = strchr (s, '-');
254            if (end)
255                    return g_strndup (s, end - s);
256            else
257                    return g_strdup (s);
258    } else
259            return g_strdup ("Unknown");
260}
261
262
263static gboolean
264get_points (HTMLFontManager *manager, GtkHTMLFontStyle style)
265{
266        return (style & GTK_HTML_FONT_STYLE_FIXED) ? manager->fix_points : manager->var_points;
267}
268
269static gpointer
270manager_alloc_font (HTMLFontManager *manager, gchar *face, GtkHTMLFontStyle style)
271{
272        return html_painter_alloc_font (manager->painter, face, get_real_font_size (manager, style), get_points (manager, style), style);
273}
274
275static gchar *
276strip_white_space (gchar *name)
277{
278        gint end;
279        while (name [0] == ' ' || name [0] == '\t')
280                name ++;
281        end = strlen (name);
282        while (end && (name [end - 1] == ' ' || name [end - 1] == '\t')) {
283                name [end - 1] = 0;
284                end --;
285        }
286
287        return name;
288}
289
290static HTMLFont *
291alloc_new_font (HTMLFontManager *manager, HTMLFontSet **set, gchar *face_list, GtkHTMLFontStyle style)
292{
293        HTMLFont *font = NULL;
294        gchar   **faces;
295        gchar   **face;
296
297        if (!(*set)) {
298                face = faces = g_strsplit (face_list, ",", 0);
299                while (*face) {
300                        gchar *face_name = strip_white_space (*face);
301
302                        /* first try to get font from available sets */
303                        font = get_font (manager, set, face_name, style);
304                        if (!font)
305                                font = manager_alloc_font (manager, face_name, style);
306                        if (font) {
307                                if (!(*set)) {
308                                        *set = html_font_set_new (face_name);
309                                        g_hash_table_insert (manager->font_sets, g_strdup (face_name), *set);
310                                }
311                                if (strcmp (face_list, *face)) {
312                                        (*set)->ref_count ++;
313                                        g_hash_table_insert (manager->font_sets, g_strdup (face_list), *set);
314                                }
315                                break;
316                        }
317                        face++;
318                }
319                g_strfreev (faces);
320                if (!(*set)) {
321                        /* none of faces exist, so create empty set for him and let manager later set fixed font here */
322                        *set = html_font_set_new (face_list);
323                        g_hash_table_insert (manager->font_sets, g_strdup (face_list), *set);
324                }
325        } else
326                font = manager_alloc_font (manager, (*set)->face, style);
327
328        if ((*set) && font)
329                html_font_set_font (manager, (*set), style, font);
330
331        return font;
332}
333
334HTMLFont *
335html_font_manager_get_font (HTMLFontManager *manager, gchar *face_list, GtkHTMLFontStyle style)
336{
337        HTMLFontSet *set;
338        HTMLFont *font = NULL;
339
340        font = get_font (manager, &set, face_list, style);
341
342        if (!font) {
343                /* first try to alloc right one */
344                font = alloc_new_font (manager, &set, face_list, style);
345                if (!font) {
346                        g_assert (set);
347                        if (!face_list) {
348                                /* default font, so the last chance is to get fixed font */
349                                font = html_painter_alloc_font (manager->painter, NULL,
350                                                                get_real_font_size (manager, style),
351                                                                get_points (manager, style), style);
352                                if (!font)
353                                        g_warning ("Cannot allocate fixed font\n");
354                        } else {
355                                /* some unavailable non-default font => use default one */
356                       
357                               font = html_font_manager_get_font (manager, NULL, style);
358                               html_font_ref (font, manager->painter);
359                        }
360                        if (font)
361                                html_font_set_font (manager, set, style, font);
362                }
363        }
364
365        return font;
366}
367
368HTMLFont *
369html_font_new (gpointer data,
370               guint space_width,
371               guint space_asc,
372               guint space_dsc,
373               guint nbsp_width,
374               guint tab_width,
375               guint e_width,
376               guint indent_width,
377               guint cite_width)
378{
379        HTMLFont *font = g_new (HTMLFont, 1);
380
381        font->data = data;
382        font->space_width = space_width;
383        font->space_asc = space_asc;
384        font->space_dsc = space_dsc;
385        font->nbsp_width = nbsp_width;
386        font->tab_width = tab_width;
387        font->e_width = e_width;
388        font->indent_width = indent_width;
389        font->cite_width = cite_width;
390        font->ref_count = 1;
391
392        return font;
393}
394
395void
396html_font_destroy (HTMLFont *font)
397{
398        g_free (font);
399}
400
401void
402html_font_ref (HTMLFont *font, HTMLPainter *painter)
403{
404        html_painter_ref_font (painter, font);
405        font->ref_count ++;
406}
407
408void
409html_font_unref (HTMLFont *font, HTMLPainter *painter)
410{
411        font->ref_count --;
412        html_painter_unref_font (painter, font);
413
414        if (font->ref_count < 1)
415                html_font_destroy (font);
416}
Note: See TracBrowser for help on using the repository browser.