source: trunk/third/gtkhtml/src/htmlfontmanager.c @ 19188

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