2 * Copyright (C) 2003-2006 David Schleef <ds@schleef.org>
3 * 2005-2006 Eric Anholt <eric@anholt.net>
4 * 2006-2007 Benjamin Otte <otte@gnome.org>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
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 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301 USA
26 #include "swfdec_font.h"
27 #include "swfdec_bits.h"
28 #include "swfdec_debug.h"
29 #include "swfdec_shape_parser.h"
30 #include "swfdec_swf_decoder.h"
31 #include "swfdec_tag.h"
33 G_DEFINE_TYPE (SwfdecFont
, swfdec_font
, SWFDEC_TYPE_CHARACTER
)
36 swfdec_font_dispose (GObject
*object
)
38 SwfdecFont
* font
= SWFDEC_FONT (object
);
42 for (i
= 0; i
< font
->glyphs
->len
; i
++) {
43 SwfdecDraw
*draw
= g_array_index (font
->glyphs
, SwfdecFontEntry
, i
).draw
;
45 g_object_unref (draw
);
47 g_array_free (font
->glyphs
, TRUE
);
51 pango_font_description_free (font
->desc
);
56 g_free (font
->display_name
);
57 font
->display_name
= NULL
;
58 g_free (font
->copyright
);
59 font
->copyright
= NULL
;
61 G_OBJECT_CLASS (swfdec_font_parent_class
)->dispose (object
);
65 swfdec_font_class_init (SwfdecFontClass
* g_class
)
67 GObjectClass
*object_class
= G_OBJECT_CLASS (g_class
);
69 object_class
->dispose
= swfdec_font_dispose
;
73 swfdec_font_init (SwfdecFont
* font
)
75 font
->glyphs
= g_array_new (FALSE
, TRUE
, sizeof (SwfdecFontEntry
));
79 * swfdec_font_get_glyph:
80 * @font: a #SwfdecFont
81 * @glyph: id of glyph to render
83 * Tries to get the shape associated with the given glyph id. It is valid to
84 * call this function with any glyph id. If no such glyph exists, this function
87 * Returns: the shape of the requested glyph or %NULL if no such glyph exists.
90 swfdec_font_get_glyph (SwfdecFont
* font
, guint glyph
)
92 g_return_val_if_fail (SWFDEC_IS_FONT (font
), NULL
);
94 if (glyph
>= font
->glyphs
->len
)
97 return g_array_index (font
->glyphs
, SwfdecFontEntry
, glyph
).draw
;
102 convert_from_language (const char *s
, SwfdecLanguage language
)
105 const char *langcode
;
108 case SWFDEC_LANGUAGE_LATIN
:
111 case SWFDEC_LANGUAGE_JAPANESE
:
112 langcode
= "SHIFT_JIS";
115 case SWFDEC_LANGUAGE_KOREAN
:
116 case SWFDEC_LANGUAGE_CHINESE
:
117 case SWFDEC_LANGUAGE_CHINESE_TRADITIONAL
:
119 SWFDEC_ERROR ("can't convert given text from language %u", language
);
122 SWFDEC_LOG ("converting text from %s", langcode
);
123 ret
= g_convert (s
, -1, "UTF-8", langcode
, NULL
, NULL
, NULL
);
125 SWFDEC_ERROR ("given text is not in language %s", langcode
);
131 tag_func_define_font_info (SwfdecSwfDecoder
*s
, guint tag
)
135 int reserved
, wide
, ansi
, jis
;
137 /* we just assume Latin1 (FIXME: option to change this?) */
138 SwfdecLanguage language
= SWFDEC_LANGUAGE_LATIN
;
140 id
= swfdec_bits_get_u16 (&s
->b
);
141 font
= swfdec_swf_decoder_get_character (s
, id
);
142 if (!SWFDEC_IS_FONT (font
)) {
143 SWFDEC_WARNING ("didn't find a font with id %u", id
);
144 return SWFDEC_STATUS_OK
;
146 len
= swfdec_bits_get_u8 (&s
->b
);
147 /* this string is locale specific */
148 name
= swfdec_bits_get_string_length (&s
->b
, len
, s
->version
);
149 reserved
= swfdec_bits_getbits (&s
->b
, 2);
150 font
->small
= swfdec_bits_getbit (&s
->b
);
151 jis
= swfdec_bits_getbit (&s
->b
);
152 ansi
= swfdec_bits_getbit (&s
->b
);
153 if (jis
!= 0 || ansi
!= 0) {
154 SWFDEC_LOG ("ansi = %d, jis = %d", ansi
, jis
);
155 if (tag
== SWFDEC_TAG_DEFINEFONTINFO2
)
156 SWFDEC_INFO ("ANSI and JIS flags are supposed to be 0 in DefineFontInfo");
158 language
= SWFDEC_LANGUAGE_JAPANESE
;
160 font
->italic
= swfdec_bits_getbit (&s
->b
);
161 font
->bold
= swfdec_bits_getbit (&s
->b
);
162 wide
= swfdec_bits_getbit (&s
->b
);
163 if (tag
== SWFDEC_TAG_DEFINEFONTINFO2
)
164 language
= swfdec_bits_get_u8 (&s
->b
);
167 SWFDEC_LOG ("Creating font description for font %d", id
);
168 font
->desc
= pango_font_description_new ();
169 pango_font_description_set_family_static (font
->desc
, font
->name
);
171 pango_font_description_set_weight (font
->desc
, PANGO_WEIGHT_BOLD
);
173 pango_font_description_set_style (font
->desc
, PANGO_STYLE_ITALIC
);
175 for (i
= 0; i
< font
->glyphs
->len
; i
++) {
176 g_array_index (font
->glyphs
, SwfdecFontEntry
, i
).value
=
177 wide
? swfdec_bits_get_u16 (&s
->b
) : swfdec_bits_get_u8 (&s
->b
);
180 return SWFDEC_STATUS_OK
;
184 swfdec_font_parse_shape (SwfdecSwfDecoder
*s
, SwfdecFontEntry
*entry
, guint size
)
187 SwfdecShapeParser
*parser
;
190 swfdec_bits_init_bits (&bits
, &s
->b
, size
);
191 parser
= swfdec_shape_parser_new (NULL
, NULL
, NULL
);
192 swfdec_shape_parser_parse (parser
, &bits
);
193 list
= swfdec_shape_parser_free (parser
);
195 entry
->draw
= g_object_ref (list
->data
);
196 g_slist_foreach (list
, (GFunc
) g_object_unref
, NULL
);
202 if (swfdec_bits_left (&bits
)) {
203 SWFDEC_WARNING ("parsing shape didn't use %d bytes",
204 swfdec_bits_left (&bits
) / 8);
209 tag_func_define_font (SwfdecSwfDecoder
* s
, guint tag
)
211 guint i
, id
, n_glyphs
, offset
, next_offset
;
215 id
= swfdec_bits_get_u16 (&s
->b
);
216 font
= swfdec_swf_decoder_create_character (s
, id
, SWFDEC_TYPE_FONT
);
218 return SWFDEC_STATUS_OK
;
219 font
->scale_factor
= SWFDEC_TEXT_SCALE_FACTOR
;
221 offset
= swfdec_bits_get_u16 (&s
->b
);
223 SWFDEC_ERROR ("first offset is odd?!");
225 n_glyphs
= offset
/ 2;
227 return SWFDEC_STATUS_OK
;
228 swfdec_bits_init_bits (&offsets
, &s
->b
, offset
- 2);
230 g_array_set_size (font
->glyphs
, n_glyphs
);
231 for (i
= 0; i
< n_glyphs
&& swfdec_bits_left (&s
->b
); i
++) {
232 SwfdecFontEntry
*entry
= &g_array_index (font
->glyphs
, SwfdecFontEntry
, i
);
233 if (i
+ 1 == n_glyphs
)
234 next_offset
= offset
+ swfdec_bits_left (&s
->b
) / 8;
236 next_offset
= swfdec_bits_get_u16 (&offsets
);
237 swfdec_font_parse_shape (s
, entry
, next_offset
- offset
);
238 offset
= next_offset
;
241 SWFDEC_ERROR ("data was only enough for %u glyphs, not %u", i
, n_glyphs
);
242 g_array_set_size (font
->glyphs
, i
);
245 return SWFDEC_STATUS_OK
;
249 swfdec_font_parse_kerning_table (SwfdecSwfDecoder
*s
, SwfdecFont
*font
, gboolean wide_codes
)
251 SwfdecBits
*bits
= &s
->b
;
254 n_kernings
= swfdec_bits_get_u16 (bits
);
255 for (i
= 0; i
< n_kernings
; i
++) {
257 swfdec_bits_get_u16 (bits
);
258 swfdec_bits_get_u16 (bits
);
260 swfdec_bits_get_u8 (bits
);
261 swfdec_bits_get_u8 (bits
);
263 swfdec_bits_get_s16 (bits
);
268 tag_func_define_font_2 (SwfdecSwfDecoder
* s
, guint tag
)
270 SwfdecBits offsets
, *bits
= &s
->b
;
272 SwfdecLanguage language
;
273 guint i
, id
, len
, n_glyphs
, offset
, next_offset
;
274 gboolean layout
, shift_jis
, ansi
, wide_offsets
, wide_codes
;
276 id
= swfdec_bits_get_u16 (bits
);
277 font
= swfdec_swf_decoder_create_character (s
, id
, SWFDEC_TYPE_FONT
);
279 return SWFDEC_STATUS_OK
;
280 SWFDEC_LOG (" id = %u", id
);
281 font
->scale_factor
= SWFDEC_TEXT_SCALE_FACTOR
* (tag
== SWFDEC_TAG_DEFINEFONT3
? 20 : 1);
283 layout
= swfdec_bits_getbit (bits
);
284 SWFDEC_LOG (" layout = %d", layout
);
285 shift_jis
= swfdec_bits_getbit (bits
);
286 SWFDEC_LOG (" JIS = %d", shift_jis
);
287 font
->small
= swfdec_bits_getbit (bits
);
288 SWFDEC_LOG (" small = %d", font
->small
);
289 ansi
= swfdec_bits_getbit (bits
);
290 SWFDEC_LOG (" ansi = %d", ansi
);
291 wide_offsets
= swfdec_bits_getbit (bits
);
292 SWFDEC_LOG (" wide offsets = %d", wide_offsets
);
293 wide_codes
= swfdec_bits_getbit (bits
);
294 SWFDEC_LOG (" wide codes = %d", wide_codes
);
295 font
->italic
= swfdec_bits_getbit (bits
);
296 SWFDEC_LOG (" italic = %d", font
->italic
);
297 font
->bold
= swfdec_bits_getbit (bits
);
298 SWFDEC_LOG (" bold = %d", font
->bold
);
299 language
= swfdec_bits_get_u8 (&s
->b
);
300 SWFDEC_LOG (" language = %u", (guint
) language
);
301 len
= swfdec_bits_get_u8 (&s
->b
);
302 font
->name
= swfdec_bits_get_string_length (&s
->b
, len
, s
->version
);
303 if (font
->name
== NULL
) {
304 SWFDEC_ERROR ("error reading font name");
306 SWFDEC_LOG (" font name = %s", font
->name
);
308 n_glyphs
= swfdec_bits_get_u16 (&s
->b
);
309 SWFDEC_LOG (" n_glyphs = %u", n_glyphs
);
312 offset
= swfdec_bits_get_u32 (bits
);
313 swfdec_bits_init_bits (&offsets
, bits
, n_glyphs
* 4);
315 offset
= swfdec_bits_get_u16 (bits
);
316 swfdec_bits_init_bits (&offsets
, bits
, n_glyphs
* 2);
318 g_array_set_size (font
->glyphs
, n_glyphs
);
319 for (i
= 0; i
< n_glyphs
&& swfdec_bits_left (bits
); i
++) {
320 SwfdecFontEntry
*entry
= &g_array_index (font
->glyphs
, SwfdecFontEntry
, i
);
322 next_offset
= swfdec_bits_get_u32 (&offsets
);
324 next_offset
= swfdec_bits_get_u16 (&offsets
);
325 swfdec_font_parse_shape (s
, entry
, next_offset
- offset
);
326 offset
= next_offset
;
329 SWFDEC_ERROR ("data was only enough for %u glyphs, not %u", i
, n_glyphs
);
330 g_array_set_size (font
->glyphs
, i
);
333 for (i
= 0; i
< n_glyphs
&& swfdec_bits_left (bits
); i
++) {
334 SwfdecFontEntry
*entry
= &g_array_index (font
->glyphs
, SwfdecFontEntry
, i
);
336 entry
->value
= swfdec_bits_get_u16 (bits
);
338 entry
->value
= swfdec_bits_get_u8 (bits
);
341 font
->ascent
= swfdec_bits_get_u16 (bits
);
342 font
->descent
= swfdec_bits_get_u16 (bits
);
343 font
->leading
= swfdec_bits_get_u16 (bits
);
344 for (i
= 0; i
< n_glyphs
&& swfdec_bits_left (bits
); i
++) {
345 SwfdecFontEntry
*entry
= &g_array_index (font
->glyphs
, SwfdecFontEntry
, i
);
346 entry
->advance
= swfdec_bits_get_u16 (bits
);
348 for (i
= 0; i
< n_glyphs
&& swfdec_bits_left (bits
); i
++) {
349 SwfdecFontEntry
*entry
= &g_array_index (font
->glyphs
, SwfdecFontEntry
, i
);
350 swfdec_bits_get_rect (bits
, &entry
->extents
);
352 swfdec_font_parse_kerning_table (s
, font
, wide_codes
);
354 font
->ascent
= font
->scale_factor
;
357 for (i
= 0; i
< n_glyphs
&& swfdec_bits_left (bits
); i
++) {
358 SwfdecFontEntry
*entry
= &g_array_index (font
->glyphs
, SwfdecFontEntry
, i
);
359 entry
->advance
= font
->scale_factor
;
360 entry
->extents
.x0
= entry
->extents
.y0
= 0;
361 entry
->extents
.x1
= entry
->extents
.y1
= font
->scale_factor
;
365 return SWFDEC_STATUS_OK
;
369 tag_func_define_font_name (SwfdecSwfDecoder
* s
, guint tag
)
374 id
= swfdec_bits_get_u16 (&s
->b
);
375 font
= swfdec_swf_decoder_get_character (s
, id
);
377 if (!SWFDEC_IS_FONT (font
)) {
378 SWFDEC_ERROR ("didn't find a font with id %u", id
);
379 return SWFDEC_STATUS_OK
;
382 font
->display_name
= swfdec_bits_get_string (&s
->b
, s
->version
);
383 font
->copyright
= swfdec_bits_get_string (&s
->b
, s
->version
);
385 return SWFDEC_STATUS_OK
;