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.h"
30 #include "swfdec_stroke.h"
31 #include "swfdec_swf_decoder.h"
32 #include "swfdec_tag.h"
34 G_DEFINE_TYPE (SwfdecFont
, swfdec_font
, SWFDEC_TYPE_CHARACTER
)
37 swfdec_font_dispose (GObject
*object
)
39 SwfdecFont
* font
= SWFDEC_FONT (object
);
43 for (i
= 0; i
< font
->glyphs
->len
; i
++) {
44 g_object_unref (g_array_index (font
->glyphs
, SwfdecFontEntry
, i
).shape
);
46 g_array_free (font
->glyphs
, TRUE
);
50 pango_font_description_free (font
->desc
);
58 G_OBJECT_CLASS (swfdec_font_parent_class
)->dispose (object
);
62 swfdec_font_class_init (SwfdecFontClass
* g_class
)
64 GObjectClass
*object_class
= G_OBJECT_CLASS (g_class
);
66 object_class
->dispose
= swfdec_font_dispose
;
70 swfdec_font_init (SwfdecFont
* font
)
72 font
->glyphs
= g_array_new (FALSE
, TRUE
, sizeof (SwfdecFontEntry
));
76 * swfdec_font_get_glyph:
77 * @font: a #SwfdecFont
78 * @glyph: id of glyph to render
80 * Tries to get the shape associated with the given glyph id. It is valid to
81 * call this function with any glyph id. If no such glyph exists, this function
84 * Returns: the shape of the requested glyph or %NULL if no such glyph exists.
87 swfdec_font_get_glyph (SwfdecFont
* font
, guint glyph
)
89 g_return_val_if_fail (SWFDEC_IS_FONT (font
), NULL
);
91 if (glyph
>= font
->glyphs
->len
)
94 return g_array_index (font
->glyphs
, SwfdecFontEntry
, glyph
).shape
;
99 convert_from_language (const char *s
, SwfdecLanguage language
)
102 const char *langcode
;
105 case SWFDEC_LANGUAGE_LATIN
:
108 case SWFDEC_LANGUAGE_JAPANESE
:
109 langcode
= "SHIFT_JIS";
112 case SWFDEC_LANGUAGE_KOREAN
:
113 case SWFDEC_LANGUAGE_CHINESE
:
114 case SWFDEC_LANGUAGE_CHINESE_TRADITIONAL
:
116 SWFDEC_ERROR ("can't convert given text from language %u", language
);
119 SWFDEC_LOG ("converting text from %s", langcode
);
120 ret
= g_convert (s
, -1, "UTF-8", langcode
, NULL
, NULL
, NULL
);
122 SWFDEC_ERROR ("given text is not in language %s", langcode
);
128 tag_func_define_font_info (SwfdecSwfDecoder
*s
, guint tag
)
132 int reserved
, wide
, ansi
, jis
;
134 /* we just assume Latin1 (FIXME: option to change this?) */
135 SwfdecLanguage language
= SWFDEC_LANGUAGE_LATIN
;
137 id
= swfdec_bits_get_u16 (&s
->b
);
138 font
= swfdec_swf_decoder_get_character (s
, id
);
139 if (!SWFDEC_IS_FONT (font
)) {
140 SWFDEC_WARNING ("didn't find a font with id %u", id
);
141 return SWFDEC_STATUS_OK
;
143 len
= swfdec_bits_get_u8 (&s
->b
);
144 /* this string is locale specific */
145 name
= swfdec_bits_get_string_length (&s
->b
, len
);
146 reserved
= swfdec_bits_getbits (&s
->b
, 2);
147 font
->small
= swfdec_bits_getbit (&s
->b
);
148 jis
= swfdec_bits_getbit (&s
->b
);
149 ansi
= swfdec_bits_getbit (&s
->b
);
150 if (jis
!= 0 || ansi
!= 0) {
151 SWFDEC_LOG ("ansi = %d, jis = %d", ansi
, jis
);
152 if (tag
== SWFDEC_TAG_DEFINEFONTINFO2
)
153 SWFDEC_INFO ("ANSI and JIS flags are supposed to be 0 in DefineFontInfo");
155 language
= SWFDEC_LANGUAGE_JAPANESE
;
157 font
->italic
= swfdec_bits_getbit (&s
->b
);
158 font
->bold
= swfdec_bits_getbit (&s
->b
);
159 wide
= swfdec_bits_getbit (&s
->b
);
160 if (tag
== SWFDEC_TAG_DEFINEFONTINFO2
)
161 language
= swfdec_bits_get_u8 (&s
->b
);
164 SWFDEC_LOG ("Creating font description for font %d", id
);
165 font
->desc
= pango_font_description_new ();
166 pango_font_description_set_family_static (font
->desc
, font
->name
);
168 pango_font_description_set_weight (font
->desc
, PANGO_WEIGHT_BOLD
);
170 pango_font_description_set_style (font
->desc
, PANGO_STYLE_ITALIC
);
172 for (i
= 0; i
< font
->glyphs
->len
; i
++) {
173 g_array_index (font
->glyphs
, SwfdecFontEntry
, i
).value
=
174 wide
? swfdec_bits_get_u16 (&s
->b
) : swfdec_bits_get_u8 (&s
->b
);
177 return SWFDEC_STATUS_OK
;
181 swfdec_font_parse_shape (SwfdecSwfDecoder
*s
, SwfdecFontEntry
*entry
, guint size
)
183 SwfdecBits save_bits
= s
->b
;
184 SwfdecShape
*shape
= g_object_new (SWFDEC_TYPE_SHAPE
, NULL
);
185 entry
->shape
= shape
;
187 g_ptr_array_add (shape
->fills
, swfdec_pattern_new_color (0xFFFFFFFF));
188 g_ptr_array_add (shape
->lines
, swfdec_stroke_new (20, 0xFFFFFFFF));
190 swfdec_bits_init_bits (&s
->b
, &save_bits
, size
);
192 shape
->n_fill_bits
= swfdec_bits_getbits (&s
->b
, 4);
193 SWFDEC_LOG ("n_fill_bits = %d", shape
->n_fill_bits
);
194 shape
->n_line_bits
= swfdec_bits_getbits (&s
->b
, 4);
195 SWFDEC_LOG ("n_line_bits = %d", shape
->n_line_bits
);
196 swfdec_shape_get_recs (s
, shape
, swfdec_pattern_parse
, swfdec_stroke_parse
);
198 swfdec_bits_syncbits (&s
->b
);
199 if (swfdec_bits_left (&s
->b
)) {
200 SWFDEC_WARNING ("parsing shape didn't use %d bytes",
201 swfdec_bits_left (&s
->b
) / 8);
207 tag_func_define_font (SwfdecSwfDecoder
* s
, guint tag
)
209 guint i
, id
, n_glyphs
, offset
, next_offset
;
213 id
= swfdec_bits_get_u16 (&s
->b
);
214 font
= swfdec_swf_decoder_create_character (s
, id
, SWFDEC_TYPE_FONT
);
216 return SWFDEC_STATUS_OK
;
217 font
->scale_factor
= SWFDEC_TEXT_SCALE_FACTOR
;
220 n_glyphs
= swfdec_bits_get_u16 (&s
->b
);
222 SWFDEC_ERROR ("first offset is odd?!");
225 if (swfdec_bits_skip_bytes (&s
->b
, n_glyphs
* 2 - 2) != n_glyphs
* 2 - 2) {
226 SWFDEC_ERROR ("invalid glyph offsets");
227 return SWFDEC_STATUS_OK
;
230 g_array_set_size (font
->glyphs
, n_glyphs
);
231 offset
= swfdec_bits_get_u16 (&offsets
);
232 for (i
= 0; i
< n_glyphs
&& swfdec_bits_left (&s
->b
); i
++) {
233 SwfdecFontEntry
*entry
= &g_array_index (font
->glyphs
, SwfdecFontEntry
, i
);
234 if (i
+ 1 == n_glyphs
)
235 next_offset
= offset
+ swfdec_bits_left (&s
->b
) / 8;
237 next_offset
= swfdec_bits_get_u16 (&offsets
);
238 swfdec_font_parse_shape (s
, entry
, next_offset
- offset
);
239 offset
= next_offset
;
242 SWFDEC_ERROR ("data was only enough for %u glyphs, not %u", i
, n_glyphs
);
243 g_array_set_size (font
->glyphs
, i
);
246 return SWFDEC_STATUS_OK
;
250 swfdec_font_parse_kerning_table (SwfdecSwfDecoder
*s
, SwfdecFont
*font
, gboolean wide_codes
)
252 SwfdecBits
*bits
= &s
->b
;
255 n_kernings
= swfdec_bits_get_u16 (bits
);
256 for (i
= 0; i
< n_kernings
; i
++) {
258 swfdec_bits_get_u16 (bits
);
259 swfdec_bits_get_u16 (bits
);
261 swfdec_bits_get_u8 (bits
);
262 swfdec_bits_get_u8 (bits
);
264 swfdec_bits_get_s16 (bits
);
269 tag_func_define_font_2 (SwfdecSwfDecoder
* s
, guint tag
)
271 SwfdecBits
*bits
= &s
->b
;
288 int code_table_offset
;
295 id
= swfdec_bits_get_u16 (bits
);
296 font
= swfdec_swf_decoder_create_character (s
, id
, SWFDEC_TYPE_FONT
);
298 return SWFDEC_STATUS_OK
;
299 font
->scale_factor
= SWFDEC_TEXT_SCALE_FACTOR
;
301 has_layout
= swfdec_bits_getbit (bits
);
302 shift_jis
= swfdec_bits_getbit (bits
);
303 reserved
= swfdec_bits_getbit (bits
);
304 ansi
= swfdec_bits_getbit (bits
);
305 wide_offsets
= swfdec_bits_getbit (bits
);
306 wide_codes
= swfdec_bits_getbit (bits
);
307 italic
= swfdec_bits_getbit (bits
);
308 bold
= swfdec_bits_getbit (bits
);
310 langcode
= swfdec_bits_get_u8 (bits
);
311 SWFDEC_DEBUG("langcode %d", langcode
);
313 font_name_len
= swfdec_bits_get_u8 (bits
);
314 font
->name
= swfdec_bits_get_string_length (bits
, font_name_len
);
315 if (font
->name
== NULL
) {
316 SWFDEC_ERROR ("error reading font name");
318 SWFDEC_LOG (" font name = %s", font
->name
);
321 n_glyphs
= swfdec_bits_get_u16 (bits
);
324 if (swfdec_bits_skip_bytes (bits
, skip
) != skip
) {
325 SWFDEC_ERROR ("could not skip %u bytes", skip
);
326 return SWFDEC_STATUS_OK
;
328 code_table_offset
= swfdec_bits_get_u32 (bits
);
331 if (swfdec_bits_skip_bytes (bits
, skip
) != skip
) {
332 SWFDEC_ERROR ("could not skip %u bytes", skip
);
333 return SWFDEC_STATUS_OK
;
335 code_table_offset
= swfdec_bits_get_u16 (bits
);
338 g_array_set_size (font
->glyphs
, n_glyphs
);
340 for (i
= 0; i
< n_glyphs
&& swfdec_bits_left (&s
->b
); i
++) {
341 SwfdecFontEntry
*entry
= &g_array_index (font
->glyphs
, SwfdecFontEntry
, i
);
342 shape
= g_object_new (SWFDEC_TYPE_SHAPE
, NULL
);
343 entry
->shape
= shape
;
345 g_ptr_array_add (shape
->fills
, swfdec_pattern_new_color (0xFFFFFFFF));
346 g_ptr_array_add (shape
->lines
, swfdec_stroke_new (20, 0xFFFFFFFF));
348 shape
->n_fill_bits
= swfdec_bits_getbits (&s
->b
, 4);
349 SWFDEC_LOG ("n_fill_bits = %d", shape
->n_fill_bits
);
350 shape
->n_line_bits
= swfdec_bits_getbits (&s
->b
, 4);
351 SWFDEC_LOG ("n_line_bits = %d", shape
->n_line_bits
);
353 swfdec_shape_get_recs (s
, shape
, swfdec_pattern_parse
, swfdec_stroke_parse
);
354 swfdec_bits_syncbits (&s
->b
);
357 SWFDEC_ERROR ("data was only enough for %u glyphs, not %u", i
, n_glyphs
);
358 g_array_set_size (font
->glyphs
, i
);
362 swfdec_bits_skip_bytes (bits
, 2 * n_glyphs
);
364 swfdec_bits_skip_bytes (bits
, 1 * n_glyphs
);
367 font_ascent
= swfdec_bits_get_s16 (bits
);
368 font_descent
= swfdec_bits_get_s16 (bits
);
369 font_leading
= swfdec_bits_get_s16 (bits
);
370 //font_advance_table = swfdec_bits_get_s16(bits);
371 swfdec_bits_skip_bytes (bits
, 2 * n_glyphs
);
372 for (i
= 0; i
< n_glyphs
&& swfdec_bits_left (bits
); i
++) {
373 swfdec_bits_get_rect (bits
, &rect
);
375 swfdec_font_parse_kerning_table (s
, font
, wide_codes
);
378 return SWFDEC_STATUS_OK
;
382 tag_func_define_font_3 (SwfdecSwfDecoder
* s
, guint tag
)
384 SwfdecBits offsets
, *bits
= &s
->b
;
386 SwfdecLanguage language
;
387 guint i
, id
, len
, n_glyphs
, offset
, next_offset
;
388 gboolean layout
, shift_jis
, ansi
, wide_offsets
, wide_codes
;
390 id
= swfdec_bits_get_u16 (bits
);
391 font
= swfdec_swf_decoder_create_character (s
, id
, SWFDEC_TYPE_FONT
);
393 return SWFDEC_STATUS_OK
;
394 SWFDEC_LOG (" id = %u", id
);
395 font
->scale_factor
= 20 * SWFDEC_TEXT_SCALE_FACTOR
;
397 layout
= swfdec_bits_getbit (bits
);
398 SWFDEC_LOG (" layout = %d", layout
);
399 shift_jis
= swfdec_bits_getbit (bits
);
400 SWFDEC_LOG (" JIS = %d", shift_jis
);
401 font
->small
= swfdec_bits_getbit (bits
);
402 SWFDEC_LOG (" small = %d", font
->small
);
403 ansi
= swfdec_bits_getbit (bits
);
404 SWFDEC_LOG (" ansi = %d", ansi
);
405 wide_offsets
= swfdec_bits_getbit (bits
);
406 SWFDEC_LOG (" wide offsets = %d", wide_offsets
);
407 wide_codes
= swfdec_bits_getbit (bits
);
408 SWFDEC_LOG (" wide codes = %d", wide_codes
);
409 if (wide_codes
== 0) {
410 SWFDEC_ERROR (" wide codes should be set in DefineFont3");
412 font
->italic
= swfdec_bits_getbit (bits
);
413 SWFDEC_LOG (" italic = %d", font
->small
);
414 font
->bold
= swfdec_bits_getbit (bits
);
415 SWFDEC_LOG (" bold = %d", font
->small
);
416 language
= swfdec_bits_get_u8 (&s
->b
);
417 SWFDEC_LOG (" language = %u", (guint
) language
);
418 len
= swfdec_bits_get_u8 (&s
->b
);
419 font
->name
= swfdec_bits_get_string_length (&s
->b
, len
);
420 if (font
->name
== NULL
) {
421 SWFDEC_ERROR ("error reading font name");
423 SWFDEC_LOG (" font name = %s", font
->name
);
425 n_glyphs
= swfdec_bits_get_u16 (&s
->b
);
426 SWFDEC_LOG (" n_glyphs = %u", n_glyphs
);
430 if (swfdec_bits_skip_bytes (bits
, n_glyphs
* 4 + 4) != n_glyphs
* 4 + 4) {
431 SWFDEC_ERROR ("DefineFont3 too short");
432 return SWFDEC_STATUS_OK
;
434 offset
= swfdec_bits_get_u32 (&offsets
);
436 if (swfdec_bits_skip_bytes (bits
, n_glyphs
* 2 + 2) != n_glyphs
* 2 + 2) {
437 SWFDEC_ERROR ("DefineFont3 too short");
438 return SWFDEC_STATUS_OK
;
440 offset
= swfdec_bits_get_u16 (&offsets
);
442 g_array_set_size (font
->glyphs
, n_glyphs
);
443 for (i
= 0; i
< n_glyphs
&& swfdec_bits_left (&s
->b
); i
++) {
444 SwfdecFontEntry
*entry
= &g_array_index (font
->glyphs
, SwfdecFontEntry
, i
);
446 next_offset
= swfdec_bits_get_u32 (&offsets
);
448 next_offset
= swfdec_bits_get_u16 (&offsets
);
449 swfdec_font_parse_shape (s
, entry
, next_offset
- offset
);
450 offset
= next_offset
;
453 SWFDEC_ERROR ("data was only enough for %u glyphs, not %u", i
, n_glyphs
);
454 g_array_set_size (font
->glyphs
, i
);
457 for (i
= 0; i
< n_glyphs
&& swfdec_bits_left (bits
); i
++) {
458 SwfdecFontEntry
*entry
= &g_array_index (font
->glyphs
, SwfdecFontEntry
, i
);
460 entry
->value
= swfdec_bits_get_u16 (bits
);
462 entry
->value
= swfdec_bits_get_u8 (bits
);
465 guint ascent
, descent
, leading
;
467 ascent
= swfdec_bits_get_u16 (bits
);
468 descent
= swfdec_bits_get_u16 (bits
);
469 leading
= swfdec_bits_get_u16 (bits
);
470 for (i
= 0; i
< n_glyphs
&& swfdec_bits_left (bits
); i
++) {
471 /* guint advance = */ swfdec_bits_get_u16 (bits
);
473 for (i
= 0; i
< n_glyphs
&& swfdec_bits_left (bits
); i
++) {
475 swfdec_bits_get_rect (bits
, &rect
);
477 swfdec_font_parse_kerning_table (s
, font
, wide_codes
);
480 return SWFDEC_STATUS_OK
;