2 * Copyright (C) 2007-2008 Benjamin Otte <otte@gnome.org>
3 * 2007 Pekka Lampila <pekka.lampila@iki.fi>
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301 USA
27 #include <pango/pangocairo.h>
29 #include "swfdec_text_format.h"
30 #include "swfdec_as_native_function.h"
31 #include "swfdec_as_array.h"
32 #include "swfdec_as_object.h"
33 #include "swfdec_as_strings.h"
34 #include "swfdec_debug.h"
35 #include "swfdec_internal.h"
36 #include "swfdec_as_internal.h"
37 #include "swfdec_player_internal.h"
38 /* for getTextExtent */
39 #include "swfdec_text_buffer.h"
40 #include "swfdec_text_layout.h"
42 G_DEFINE_TYPE (SwfdecTextFormat
, swfdec_text_format
, SWFDEC_TYPE_AS_OBJECT
)
44 static int property_offsets
[] = {
45 G_STRUCT_OFFSET (SwfdecTextFormat
, attr
.align
),
46 G_STRUCT_OFFSET (SwfdecTextFormat
, attr
.block_indent
),
47 G_STRUCT_OFFSET (SwfdecTextFormat
, attr
.bold
),
48 G_STRUCT_OFFSET (SwfdecTextFormat
, attr
.bullet
),
49 G_STRUCT_OFFSET (SwfdecTextFormat
, attr
.color
),
50 G_STRUCT_OFFSET (SwfdecTextFormat
, attr
.display
),
51 G_STRUCT_OFFSET (SwfdecTextFormat
, attr
.font
),
52 G_STRUCT_OFFSET (SwfdecTextFormat
, attr
.indent
),
53 G_STRUCT_OFFSET (SwfdecTextFormat
, attr
.italic
),
54 G_STRUCT_OFFSET (SwfdecTextFormat
, attr
.kerning
),
55 G_STRUCT_OFFSET (SwfdecTextFormat
, attr
.leading
),
56 G_STRUCT_OFFSET (SwfdecTextFormat
, attr
.left_margin
),
57 G_STRUCT_OFFSET (SwfdecTextFormat
, attr
.letter_spacing
),
58 G_STRUCT_OFFSET (SwfdecTextFormat
, attr
.right_margin
),
59 G_STRUCT_OFFSET (SwfdecTextFormat
, attr
.size
),
60 G_STRUCT_OFFSET (SwfdecTextFormat
, attr
.tab_stops
),
61 G_STRUCT_OFFSET (SwfdecTextFormat
, attr
.target
),
62 G_STRUCT_OFFSET (SwfdecTextFormat
, attr
.underline
),
63 G_STRUCT_OFFSET (SwfdecTextFormat
, attr
.url
)
67 swfdec_text_format_mark (SwfdecGcObject
*object
)
69 SwfdecTextFormat
*format
= SWFDEC_TEXT_FORMAT (object
);
71 swfdec_text_attributes_mark (&format
->attr
);
73 SWFDEC_GC_OBJECT_CLASS (swfdec_text_format_parent_class
)->mark (object
);
77 swfdec_text_format_class_init (SwfdecTextFormatClass
*klass
)
79 SwfdecGcObjectClass
*gc_class
= SWFDEC_GC_OBJECT_CLASS (klass
);
81 gc_class
->mark
= swfdec_text_format_mark
;
85 swfdec_text_format_init (SwfdecTextFormat
*format
)
87 swfdec_text_attributes_reset (&format
->attr
);
91 swfdec_text_format_get_string (SwfdecAsObject
*object
,
92 SwfdecTextAttribute property
, SwfdecAsValue
*ret
)
94 SwfdecTextFormat
*format
;
96 if (!SWFDEC_IS_TEXT_FORMAT (object
))
98 format
= SWFDEC_TEXT_FORMAT (object
);
100 if (!SWFDEC_TEXT_ATTRIBUTE_IS_SET (format
->values_set
, property
)) {
101 SWFDEC_AS_VALUE_SET_NULL (ret
);
105 SWFDEC_AS_VALUE_SET_STRING (ret
,
106 G_STRUCT_MEMBER (const char *, format
, property_offsets
[property
]));
110 swfdec_text_format_set_string (SwfdecAsObject
*object
,
111 SwfdecTextAttribute property
, guint argc
, SwfdecAsValue
*argv
)
113 SwfdecTextFormat
*format
;
114 SwfdecAsContext
*context
;
117 if (!SWFDEC_IS_TEXT_FORMAT (object
))
119 format
= SWFDEC_TEXT_FORMAT (object
);
124 context
= swfdec_gc_object_get_context (format
);
125 swfdec_as_value_to_integer (context
, &argv
[0]);
126 swfdec_as_value_to_number (context
, &argv
[0]);
127 s
= swfdec_as_value_to_string (context
, &argv
[0]);
129 if (SWFDEC_AS_VALUE_IS_UNDEFINED (&argv
[0]) ||
130 SWFDEC_AS_VALUE_IS_NULL (&argv
[0])) {
131 /* FIXME: reset to defaults here? */
132 SWFDEC_TEXT_ATTRIBUTE_UNSET (format
->values_set
, property
);
134 G_STRUCT_MEMBER (const char *, format
, property_offsets
[property
]) = s
;
135 SWFDEC_TEXT_ATTRIBUTE_SET (format
->values_set
, property
);
137 /* FIXME: figure out what to do here */
141 swfdec_text_format_get_boolean (SwfdecAsObject
*object
,
142 SwfdecTextAttribute property
, SwfdecAsValue
*ret
)
144 SwfdecTextFormat
*format
;
146 if (!SWFDEC_IS_TEXT_FORMAT (object
))
148 format
= SWFDEC_TEXT_FORMAT (object
);
150 if (!SWFDEC_TEXT_ATTRIBUTE_IS_SET (format
->values_set
, property
)) {
151 SWFDEC_AS_VALUE_SET_NULL (ret
);
155 if (G_STRUCT_MEMBER (gboolean
, format
, property_offsets
[property
])) {
156 SWFDEC_AS_VALUE_SET_BOOLEAN (ret
, TRUE
);
158 SWFDEC_AS_VALUE_SET_BOOLEAN (ret
, FALSE
);
163 swfdec_text_format_set_boolean (SwfdecAsObject
*object
,
164 SwfdecTextAttribute property
, guint argc
, SwfdecAsValue
*argv
)
166 SwfdecTextFormat
*format
;
167 SwfdecAsContext
*context
;
169 if (!SWFDEC_IS_TEXT_FORMAT (object
))
171 format
= SWFDEC_TEXT_FORMAT (object
);
176 context
= swfdec_gc_object_get_context (format
);
177 swfdec_as_value_to_integer (context
, &argv
[0]);
178 swfdec_as_value_to_number (context
, &argv
[0]);
179 swfdec_as_value_to_string (context
, &argv
[0]);
181 if (SWFDEC_AS_VALUE_IS_UNDEFINED (&argv
[0]) ||
182 SWFDEC_AS_VALUE_IS_NULL (&argv
[0])) {
183 SWFDEC_TEXT_ATTRIBUTE_UNSET (format
->values_set
, property
);
185 G_STRUCT_MEMBER (gboolean
, format
, property_offsets
[property
]) =
186 swfdec_as_value_to_boolean (context
, &argv
[0]);
187 SWFDEC_TEXT_ATTRIBUTE_SET (format
->values_set
, property
);
192 swfdec_text_format_get_integer (SwfdecAsObject
*object
,
193 SwfdecTextAttribute property
, SwfdecAsValue
*ret
)
195 SwfdecTextFormat
*format
;
197 if (!SWFDEC_IS_TEXT_FORMAT (object
))
199 format
= SWFDEC_TEXT_FORMAT (object
);
201 if (!SWFDEC_TEXT_ATTRIBUTE_IS_SET (format
->values_set
, property
)) {
202 SWFDEC_AS_VALUE_SET_NULL (ret
);
206 SWFDEC_AS_VALUE_SET_NUMBER (ret
,
207 (double)G_STRUCT_MEMBER (int, format
, property_offsets
[property
]));
211 swfdec_text_format_value_to_integer (SwfdecAsContext
*cx
, SwfdecAsValue
*val
,
212 gboolean allow_negative
)
217 n
= swfdec_as_value_to_integer (cx
, val
);
218 d
= swfdec_as_value_to_number (cx
, val
);
219 swfdec_as_value_to_string (cx
, val
);
221 if (cx
->version
>= 8) {
223 return (allow_negative
? G_MININT32
: 0);
229 return (allow_negative
? G_MININT32
: 0);
232 if (d
> (double)G_MAXINT32
)
236 if (!allow_negative
&& n
< 0) {
242 if (!allow_negative
&& n
< 0) {
251 swfdec_text_format_set_integer (SwfdecAsObject
*object
,
252 SwfdecTextAttribute property
, guint argc
, SwfdecAsValue
*argv
,
253 gboolean allow_negative
)
255 SwfdecTextFormat
*format
;
257 if (!SWFDEC_IS_TEXT_FORMAT (object
))
259 format
= SWFDEC_TEXT_FORMAT (object
);
264 if (SWFDEC_AS_VALUE_IS_UNDEFINED (&argv
[0]) ||
265 SWFDEC_AS_VALUE_IS_NULL (&argv
[0])) {
266 SWFDEC_TEXT_ATTRIBUTE_UNSET (format
->values_set
, property
);
268 G_STRUCT_MEMBER (int, format
, property_offsets
[property
]) =
269 swfdec_text_format_value_to_integer (swfdec_gc_object_get_context (format
),
270 &argv
[0], allow_negative
);
271 SWFDEC_TEXT_ATTRIBUTE_SET (format
->values_set
, property
);
276 swfdec_text_format_do_get_align (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
277 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
279 SwfdecTextFormat
*format
;
281 if (!SWFDEC_IS_TEXT_FORMAT (object
))
283 format
= SWFDEC_TEXT_FORMAT (object
);
285 if (!SWFDEC_TEXT_ATTRIBUTE_IS_SET (format
->values_set
, SWFDEC_TEXT_ATTRIBUTE_ALIGN
)) {
286 SWFDEC_AS_VALUE_SET_NULL (ret
);
290 switch (format
->attr
.align
) {
291 case SWFDEC_TEXT_ALIGN_LEFT
:
292 SWFDEC_AS_VALUE_SET_STRING (ret
, SWFDEC_AS_STR_left
);
294 case SWFDEC_TEXT_ALIGN_RIGHT
:
295 SWFDEC_AS_VALUE_SET_STRING (ret
, SWFDEC_AS_STR_right
);
297 case SWFDEC_TEXT_ALIGN_CENTER
:
298 SWFDEC_AS_VALUE_SET_STRING (ret
, SWFDEC_AS_STR_center
);
300 case SWFDEC_TEXT_ALIGN_JUSTIFY
:
301 SWFDEC_AS_VALUE_SET_STRING (ret
, SWFDEC_AS_STR_justify
);
304 g_assert_not_reached ();
309 swfdec_text_format_do_set_align (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
310 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
312 SwfdecTextFormat
*format
;
315 if (!SWFDEC_IS_TEXT_FORMAT (object
))
317 format
= SWFDEC_TEXT_FORMAT (object
);
322 swfdec_as_value_to_integer (cx
, &argv
[0]);
323 swfdec_as_value_to_number (cx
, &argv
[0]);
324 s
= swfdec_as_value_to_string (cx
, &argv
[0]);
326 if (!g_ascii_strcasecmp (s
, "left")) {
327 format
->attr
.align
= SWFDEC_TEXT_ALIGN_LEFT
;
328 SWFDEC_TEXT_ATTRIBUTE_SET (format
->values_set
, SWFDEC_TEXT_ATTRIBUTE_ALIGN
);
329 } else if (!g_ascii_strcasecmp (s
, "right")) {
330 format
->attr
.align
= SWFDEC_TEXT_ALIGN_RIGHT
;
331 SWFDEC_TEXT_ATTRIBUTE_SET (format
->values_set
, SWFDEC_TEXT_ATTRIBUTE_ALIGN
);
332 } else if (!g_ascii_strcasecmp (s
, "center")) {
333 format
->attr
.align
= SWFDEC_TEXT_ALIGN_CENTER
;
334 SWFDEC_TEXT_ATTRIBUTE_SET (format
->values_set
, SWFDEC_TEXT_ATTRIBUTE_ALIGN
);
335 } else if (!g_ascii_strcasecmp (s
, "justify")) {
336 format
->attr
.align
= SWFDEC_TEXT_ALIGN_JUSTIFY
;
337 SWFDEC_TEXT_ATTRIBUTE_SET (format
->values_set
, SWFDEC_TEXT_ATTRIBUTE_ALIGN
);
342 swfdec_text_format_do_get_block_indent (SwfdecAsContext
*cx
,
343 SwfdecAsObject
*object
, guint argc
, SwfdecAsValue
*argv
,
346 swfdec_text_format_get_integer (object
, SWFDEC_TEXT_ATTRIBUTE_BLOCK_INDENT
, ret
);
350 swfdec_text_format_do_set_block_indent (SwfdecAsContext
*cx
,
351 SwfdecAsObject
*object
, guint argc
, SwfdecAsValue
*argv
,
354 swfdec_text_format_set_integer (object
, SWFDEC_TEXT_ATTRIBUTE_BLOCK_INDENT
, argc
, argv
,
359 swfdec_text_format_do_get_bold (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
360 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
362 swfdec_text_format_get_boolean (object
, SWFDEC_TEXT_ATTRIBUTE_BOLD
, ret
);
366 swfdec_text_format_do_set_bold (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
367 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
369 swfdec_text_format_set_boolean (object
, SWFDEC_TEXT_ATTRIBUTE_BOLD
, argc
, argv
);
373 swfdec_text_format_do_get_bullet (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
374 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
376 swfdec_text_format_get_boolean (object
, SWFDEC_TEXT_ATTRIBUTE_BULLET
, ret
);
380 swfdec_text_format_do_set_bullet (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
381 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
383 swfdec_text_format_set_boolean (object
, SWFDEC_TEXT_ATTRIBUTE_BULLET
, argc
, argv
);
387 swfdec_text_format_do_get_color (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
388 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
390 SwfdecTextFormat
*format
;
392 if (!SWFDEC_IS_TEXT_FORMAT (object
))
394 format
= SWFDEC_TEXT_FORMAT (object
);
396 if (!SWFDEC_TEXT_ATTRIBUTE_IS_SET (format
->values_set
, SWFDEC_TEXT_ATTRIBUTE_COLOR
)) {
397 SWFDEC_AS_VALUE_SET_NULL (ret
);
401 SWFDEC_AS_VALUE_SET_NUMBER (ret
, format
->attr
.color
);
405 swfdec_text_format_do_set_color (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
406 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
408 SwfdecTextFormat
*format
;
410 if (!SWFDEC_IS_TEXT_FORMAT (object
))
412 format
= SWFDEC_TEXT_FORMAT (object
);
417 if (SWFDEC_AS_VALUE_IS_UNDEFINED (&argv
[0]) ||
418 SWFDEC_AS_VALUE_IS_NULL (&argv
[0])) {
419 SWFDEC_TEXT_ATTRIBUTE_UNSET (format
->values_set
, SWFDEC_TEXT_ATTRIBUTE_COLOR
);
421 format
->attr
.color
= (unsigned) swfdec_as_value_to_integer (cx
, &argv
[0]);
422 swfdec_as_value_to_integer (cx
, &argv
[0]);
423 swfdec_as_value_to_string (cx
, &argv
[0]);
425 SWFDEC_TEXT_ATTRIBUTE_SET (format
->values_set
, SWFDEC_TEXT_ATTRIBUTE_COLOR
);
430 swfdec_text_format_do_get_display (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
431 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
433 SwfdecTextFormat
*format
;
435 if (!SWFDEC_IS_TEXT_FORMAT (object
))
437 format
= SWFDEC_TEXT_FORMAT (object
);
439 if (!SWFDEC_TEXT_ATTRIBUTE_IS_SET (format
->values_set
, SWFDEC_TEXT_ATTRIBUTE_DISPLAY
))
441 SWFDEC_AS_VALUE_SET_NULL (ret
);
445 switch (format
->attr
.display
) {
446 case SWFDEC_TEXT_DISPLAY_NONE
:
447 SWFDEC_AS_VALUE_SET_STRING (ret
, SWFDEC_AS_STR_none
);
449 case SWFDEC_TEXT_DISPLAY_INLINE
:
450 SWFDEC_AS_VALUE_SET_STRING (ret
, SWFDEC_AS_STR_inline
);
452 case SWFDEC_TEXT_DISPLAY_BLOCK
:
453 SWFDEC_AS_VALUE_SET_STRING (ret
, SWFDEC_AS_STR_block
);
456 g_assert_not_reached ();
461 swfdec_text_format_do_set_display (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
462 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
464 SwfdecTextFormat
*format
;
467 if (!SWFDEC_IS_TEXT_FORMAT (object
))
469 format
= SWFDEC_TEXT_FORMAT (object
);
471 swfdec_as_value_to_integer (cx
, &argv
[0]);
472 swfdec_as_value_to_number (cx
, &argv
[0]);
473 swfdec_as_value_to_string (cx
, &argv
[0]);
474 s
= swfdec_as_value_to_string (cx
, &argv
[0]); // oh yes, let's call it twice
476 if (!g_ascii_strcasecmp (s
, "none")) {
477 format
->attr
.display
= SWFDEC_TEXT_DISPLAY_NONE
;
478 } else if (!g_ascii_strcasecmp (s
, "inline")) {
479 format
->attr
.display
= SWFDEC_TEXT_DISPLAY_INLINE
;
481 format
->attr
.display
= SWFDEC_TEXT_DISPLAY_BLOCK
;
484 SWFDEC_TEXT_ATTRIBUTE_SET (format
->values_set
, SWFDEC_TEXT_ATTRIBUTE_DISPLAY
);
488 swfdec_text_format_do_get_font (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
489 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
491 swfdec_text_format_get_string (object
, SWFDEC_TEXT_ATTRIBUTE_FONT
, ret
);
495 swfdec_text_format_do_set_font (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
496 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
498 swfdec_text_format_set_string (object
, SWFDEC_TEXT_ATTRIBUTE_FONT
, argc
, argv
);
502 swfdec_text_format_do_get_indent (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
503 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
505 swfdec_text_format_get_integer (object
, SWFDEC_TEXT_ATTRIBUTE_INDENT
, ret
);
509 swfdec_text_format_do_set_indent (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
510 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
512 swfdec_text_format_set_integer (object
, SWFDEC_TEXT_ATTRIBUTE_INDENT
, argc
, argv
,
517 swfdec_text_format_do_get_italic (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
518 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
520 swfdec_text_format_get_boolean (object
, SWFDEC_TEXT_ATTRIBUTE_ITALIC
, ret
);
524 swfdec_text_format_do_set_italic (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
525 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
527 swfdec_text_format_set_boolean (object
, SWFDEC_TEXT_ATTRIBUTE_ITALIC
, argc
, argv
);
531 swfdec_text_format_do_get_kerning (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
532 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
534 swfdec_text_format_get_boolean (object
, SWFDEC_TEXT_ATTRIBUTE_KERNING
, ret
);
538 swfdec_text_format_do_set_kerning (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
539 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
541 swfdec_text_format_set_boolean (object
, SWFDEC_TEXT_ATTRIBUTE_KERNING
, argc
, argv
);
545 swfdec_text_format_do_get_leading (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
546 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
548 swfdec_text_format_get_integer (object
, SWFDEC_TEXT_ATTRIBUTE_LEADING
, ret
);
552 swfdec_text_format_do_set_leading (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
553 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
555 swfdec_text_format_set_integer (object
, SWFDEC_TEXT_ATTRIBUTE_LEADING
, argc
, argv
,
560 swfdec_text_format_do_get_left_margin (SwfdecAsContext
*cx
,
561 SwfdecAsObject
*object
, guint argc
, SwfdecAsValue
*argv
,
564 swfdec_text_format_get_integer (object
, SWFDEC_TEXT_ATTRIBUTE_LEFT_MARGIN
, ret
);
568 swfdec_text_format_do_set_left_margin (SwfdecAsContext
*cx
,
569 SwfdecAsObject
*object
, guint argc
, SwfdecAsValue
*argv
,
572 swfdec_text_format_set_integer (object
, SWFDEC_TEXT_ATTRIBUTE_LEFT_MARGIN
, argc
, argv
, FALSE
);
576 swfdec_text_format_do_get_letter_spacing (SwfdecAsContext
*cx
,
577 SwfdecAsObject
*object
, guint argc
, SwfdecAsValue
*argv
,
580 SwfdecTextFormat
*format
;
582 if (!SWFDEC_IS_TEXT_FORMAT (object
))
584 format
= SWFDEC_TEXT_FORMAT (object
);
586 if (!SWFDEC_TEXT_ATTRIBUTE_IS_SET (format
->values_set
, SWFDEC_TEXT_ATTRIBUTE_LETTER_SPACING
)) {
587 SWFDEC_AS_VALUE_SET_NULL (ret
);
591 SWFDEC_AS_VALUE_SET_NUMBER (ret
, format
->attr
.letter_spacing
);
595 swfdec_text_format_do_set_letter_spacing (SwfdecAsContext
*cx
,
596 SwfdecAsObject
*object
, guint argc
, SwfdecAsValue
*argv
,
599 SwfdecTextFormat
*format
;
602 if (!SWFDEC_IS_TEXT_FORMAT (object
))
604 format
= SWFDEC_TEXT_FORMAT (object
);
609 swfdec_as_value_to_integer (cx
, &argv
[0]);
610 d
= swfdec_as_value_to_number (cx
, &argv
[0]);
611 swfdec_as_value_to_string (cx
, &argv
[0]);
613 if (SWFDEC_AS_VALUE_IS_UNDEFINED (&argv
[0]) ||
614 SWFDEC_AS_VALUE_IS_NULL (&argv
[0]))
616 SWFDEC_TEXT_ATTRIBUTE_UNSET (format
->values_set
,
617 SWFDEC_TEXT_ATTRIBUTE_LETTER_SPACING
);
621 format
->attr
.letter_spacing
= d
;
622 SWFDEC_TEXT_ATTRIBUTE_SET (format
->values_set
,
623 SWFDEC_TEXT_ATTRIBUTE_LETTER_SPACING
);
628 swfdec_text_format_do_get_right_margin (SwfdecAsContext
*cx
,
629 SwfdecAsObject
*object
, guint argc
, SwfdecAsValue
*argv
,
632 swfdec_text_format_get_integer (object
, SWFDEC_TEXT_ATTRIBUTE_RIGHT_MARGIN
, ret
);
636 swfdec_text_format_do_set_right_margin (SwfdecAsContext
*cx
,
637 SwfdecAsObject
*object
, guint argc
, SwfdecAsValue
*argv
,
640 swfdec_text_format_set_integer (object
, SWFDEC_TEXT_ATTRIBUTE_RIGHT_MARGIN
, argc
, argv
,
645 swfdec_text_format_do_get_size (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
646 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
648 swfdec_text_format_get_integer (object
, SWFDEC_TEXT_ATTRIBUTE_SIZE
, ret
);
652 swfdec_text_format_do_set_size (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
653 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
655 swfdec_text_format_set_integer (object
, SWFDEC_TEXT_ATTRIBUTE_SIZE
, argc
, argv
, TRUE
);
659 swfdec_text_format_do_get_tab_stops (SwfdecAsContext
*cx
,
660 SwfdecAsObject
*object
, guint argc
, SwfdecAsValue
*argv
,
663 SwfdecTextFormat
*format
;
666 SwfdecAsObject
*array
;
668 if (!SWFDEC_IS_TEXT_FORMAT (object
))
670 format
= SWFDEC_TEXT_FORMAT (object
);
672 if (!SWFDEC_TEXT_ATTRIBUTE_IS_SET (format
->values_set
, SWFDEC_TEXT_ATTRIBUTE_TAB_STOPS
)) {
673 SWFDEC_AS_VALUE_SET_NULL (ret
);
677 array
= swfdec_as_array_new (cx
);
678 for (i
= 0; i
< format
->attr
.n_tab_stops
; i
++) {
679 SWFDEC_AS_VALUE_SET_INT (&val
, format
->attr
.tab_stops
[i
]);
680 swfdec_as_array_push (SWFDEC_AS_ARRAY (array
), &val
);
682 SWFDEC_AS_VALUE_SET_OBJECT (ret
, array
);
686 swfdec_text_format_do_set_tab_stops (SwfdecAsContext
*cx
,
687 SwfdecAsObject
*object
, guint argc
, SwfdecAsValue
*argv
,
690 SwfdecTextFormat
*format
;
692 if (!SWFDEC_IS_TEXT_FORMAT (object
))
694 format
= SWFDEC_TEXT_FORMAT (object
);
699 swfdec_as_value_to_integer (cx
, &argv
[0]);
700 swfdec_as_value_to_number (cx
, &argv
[0]);
701 swfdec_as_value_to_string (cx
, &argv
[0]);
703 if (SWFDEC_AS_VALUE_IS_UNDEFINED (&argv
[0]) ||
704 SWFDEC_AS_VALUE_IS_NULL (&argv
[0]))
706 g_free (format
->attr
.tab_stops
);
707 format
->attr
.tab_stops
= NULL
;
708 format
->attr
.n_tab_stops
= 0;
709 SWFDEC_TEXT_ATTRIBUTE_UNSET (format
->values_set
, SWFDEC_TEXT_ATTRIBUTE_TAB_STOPS
);
711 else if (SWFDEC_AS_VALUE_IS_OBJECT (&argv
[0]) &&
712 SWFDEC_IS_AS_ARRAY (SWFDEC_AS_VALUE_GET_OBJECT (&argv
[0])))
714 SwfdecAsArray
*array
;
719 array
= SWFDEC_AS_ARRAY (SWFDEC_AS_VALUE_GET_OBJECT (&argv
[0]));
720 len
= swfdec_as_array_get_length (array
);
722 if (!SWFDEC_TEXT_ATTRIBUTE_IS_SET (format
->values_set
, SWFDEC_TEXT_ATTRIBUTE_TAB_STOPS
)) {
723 // special case, if we have null and array is empty, keep it at null
726 SWFDEC_TEXT_ATTRIBUTE_SET (format
->values_set
, SWFDEC_TEXT_ATTRIBUTE_TAB_STOPS
);
729 g_free (format
->attr
.tab_stops
);
730 format
->attr
.n_tab_stops
= MAX (0, len
);
731 format
->attr
.tab_stops
= g_new (guint
, format
->attr
.n_tab_stops
);
732 for (i
= 0; i
< format
->attr
.n_tab_stops
; i
++) {
733 swfdec_as_array_get_value (array
, i
, &val
);
734 format
->attr
.tab_stops
[i
] = swfdec_text_format_value_to_integer (cx
, &val
, TRUE
);
737 else if (SWFDEC_AS_VALUE_IS_STRING (&argv
[0]))
741 // special case: empty strings mean null
742 if (SWFDEC_AS_VALUE_GET_STRING (&argv
[0]) == SWFDEC_AS_STR_EMPTY
) {
743 g_free (format
->attr
.tab_stops
);
744 format
->attr
.tab_stops
= NULL
;
745 format
->attr
.n_tab_stops
= 0;
746 SWFDEC_TEXT_ATTRIBUTE_UNSET (format
->values_set
, SWFDEC_TEXT_ATTRIBUTE_TAB_STOPS
);
748 int n
= cx
->version
>= 8 ? G_MININT
: 0;
749 SWFDEC_TEXT_ATTRIBUTE_SET (format
->values_set
, SWFDEC_TEXT_ATTRIBUTE_TAB_STOPS
);
750 format
->attr
.n_tab_stops
= strlen (SWFDEC_AS_VALUE_GET_STRING (&argv
[0]));
751 format
->attr
.tab_stops
= g_new (guint
, format
->attr
.n_tab_stops
);
752 for (i
= 0; i
< format
->attr
.n_tab_stops
; i
++) {
753 format
->attr
.tab_stops
[i
] = n
;
757 else if (SWFDEC_TEXT_ATTRIBUTE_IS_SET (format
->values_set
, SWFDEC_TEXT_ATTRIBUTE_TAB_STOPS
))
759 format
->attr
.n_tab_stops
= 0;
760 g_free (format
->attr
.tab_stops
);
761 format
->attr
.tab_stops
= NULL
;
766 swfdec_text_format_do_get_target (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
767 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
769 swfdec_text_format_get_string (object
, SWFDEC_TEXT_ATTRIBUTE_TARGET
, ret
);
773 swfdec_text_format_do_set_target (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
774 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
776 swfdec_text_format_set_string (object
, SWFDEC_TEXT_ATTRIBUTE_TARGET
, argc
, argv
);
780 swfdec_text_format_do_get_underline (SwfdecAsContext
*cx
,
781 SwfdecAsObject
*object
, guint argc
, SwfdecAsValue
*argv
,
784 swfdec_text_format_get_boolean (object
, SWFDEC_TEXT_ATTRIBUTE_UNDERLINE
, ret
);
788 swfdec_text_format_do_set_underline (SwfdecAsContext
*cx
,
789 SwfdecAsObject
*object
, guint argc
, SwfdecAsValue
*argv
,
792 swfdec_text_format_set_boolean (object
, SWFDEC_TEXT_ATTRIBUTE_UNDERLINE
, argc
, argv
);
796 swfdec_text_format_do_get_url (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
797 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
799 swfdec_text_format_get_string (object
, SWFDEC_TEXT_ATTRIBUTE_URL
, ret
);
803 swfdec_text_format_do_set_url (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
804 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
806 swfdec_text_format_set_string (object
, SWFDEC_TEXT_ATTRIBUTE_URL
, argc
, argv
);
810 swfdec_text_format_getTextExtent (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
811 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
813 SwfdecTextFormat
*format
;
814 SwfdecTextBuffer
*buffer
;
815 SwfdecTextLayout
*layout
;
821 SWFDEC_AS_CHECK (SWFDEC_TYPE_TEXT_FORMAT
, &format
, "s", &text
);
823 obj
= swfdec_as_object_new_empty (cx
);
825 buffer
= swfdec_text_buffer_new ();
826 swfdec_text_buffer_set_default_attributes (buffer
,
827 &format
->attr
, format
->values_set
);
828 swfdec_text_buffer_append_text (buffer
, text
);
829 layout
= swfdec_text_layout_new (buffer
);
831 i
= swfdec_text_layout_get_width (layout
);
832 SWFDEC_AS_VALUE_SET_INT (&val
, i
);
833 swfdec_as_object_set_variable (obj
, SWFDEC_AS_STR_width
, &val
);
836 SWFDEC_AS_VALUE_SET_INT (&val
, i
);
837 swfdec_as_object_set_variable (obj
, SWFDEC_AS_STR_textFieldWidth
, &val
);
839 i
= swfdec_text_layout_get_height (layout
);
840 SWFDEC_AS_VALUE_SET_INT (&val
, i
);
841 swfdec_as_object_set_variable (obj
, SWFDEC_AS_STR_height
, &val
);
844 SWFDEC_AS_VALUE_SET_INT (&val
, i
);
845 swfdec_as_object_set_variable (obj
, SWFDEC_AS_STR_textFieldHeight
, &val
);
847 swfdec_text_layout_get_ascent_descent (layout
, &i
, &j
);
848 SWFDEC_AS_VALUE_SET_INT (&val
, i
);
849 swfdec_as_object_set_variable (obj
, SWFDEC_AS_STR_ascent
, &val
);
850 SWFDEC_AS_VALUE_SET_INT (&val
, j
);
851 swfdec_as_object_set_variable (obj
, SWFDEC_AS_STR_descent
, &val
);
853 SWFDEC_AS_VALUE_SET_OBJECT (ret
, obj
);
854 g_object_unref (layout
);
855 g_object_unref (buffer
);
859 swfdec_text_format_add (SwfdecTextFormat
*format
, const SwfdecTextFormat
*from
)
861 g_return_if_fail (SWFDEC_IS_TEXT_FORMAT (format
));
862 g_return_if_fail (SWFDEC_IS_TEXT_FORMAT (from
));
864 swfdec_text_attributes_copy (&format
->attr
, &from
->attr
, from
->values_set
);
865 format
->values_set
|= from
->values_set
;
869 swfdec_text_format_remove_different (SwfdecTextFormat
*format
,
870 const SwfdecTextFormat
*from
)
872 g_return_if_fail (SWFDEC_IS_TEXT_FORMAT (format
));
873 g_return_if_fail (SWFDEC_IS_TEXT_FORMAT (from
));
875 format
->values_set
&= ~swfdec_text_attributes_diff (&format
->attr
, &from
->attr
);
879 swfdec_text_format_equal_or_undefined (const SwfdecTextFormat
*a
,
880 const SwfdecTextFormat
*b
)
884 g_return_val_if_fail (SWFDEC_IS_TEXT_FORMAT (a
), FALSE
);
885 g_return_val_if_fail (SWFDEC_IS_TEXT_FORMAT (b
), FALSE
);
887 set
= a
->values_set
& b
->values_set
;
888 diff
= swfdec_text_attributes_diff (&a
->attr
, &b
->attr
);
890 return (set
& diff
) == 0;
894 swfdec_text_format_equal (const SwfdecTextFormat
*a
, const SwfdecTextFormat
*b
)
896 g_return_val_if_fail (SWFDEC_IS_TEXT_FORMAT (a
), FALSE
);
897 g_return_val_if_fail (SWFDEC_IS_TEXT_FORMAT (b
), FALSE
);
899 if (a
->values_set
!= b
->values_set
)
902 return (a
->values_set
& swfdec_text_attributes_diff (&a
->attr
, &b
->attr
)) == 0;
906 swfdec_text_format_set_defaults (SwfdecTextFormat
*format
)
908 swfdec_text_attributes_reset (&format
->attr
);
909 format
->values_set
= SWFDEC_TEXT_ATTRIBUTES_MASK
;
911 if (swfdec_gc_object_get_context (format
)->version
< 8) {
912 SWFDEC_TEXT_ATTRIBUTE_UNSET (format
->values_set
, SWFDEC_TEXT_ATTRIBUTE_KERNING
);
913 SWFDEC_TEXT_ATTRIBUTE_UNSET (format
->values_set
, SWFDEC_TEXT_ATTRIBUTE_LETTER_SPACING
);
918 swfdec_text_format_clear (SwfdecTextFormat
*format
)
920 format
->values_set
= 0;
922 format
->attr
.display
= SWFDEC_TEXT_DISPLAY_BLOCK
;
923 SWFDEC_TEXT_ATTRIBUTE_SET (format
->values_set
, SWFDEC_TEXT_ATTRIBUTE_DISPLAY
);
927 swfdec_text_format_init_properties (SwfdecAsContext
*cx
)
930 SwfdecAsObject
*proto
;
932 // FIXME: We should only initialize if the prototype Object has not been
933 // initialized by any object's constructor with native properties
934 // (TextField, TextFormat, XML, XMLNode at least)
936 g_return_if_fail (SWFDEC_IS_AS_CONTEXT (cx
));
938 swfdec_as_object_get_variable (cx
->global
, SWFDEC_AS_STR_TextFormat
, &val
);
939 if (!SWFDEC_AS_VALUE_IS_OBJECT (&val
))
941 proto
= SWFDEC_AS_VALUE_GET_OBJECT (&val
);
942 swfdec_as_object_get_variable (proto
, SWFDEC_AS_STR_prototype
, &val
);
943 if (!SWFDEC_AS_VALUE_IS_OBJECT (&val
))
945 proto
= SWFDEC_AS_VALUE_GET_OBJECT (&val
);
947 swfdec_as_object_add_native_variable (proto
, SWFDEC_AS_STR_align
,
948 swfdec_text_format_do_get_align
, swfdec_text_format_do_set_align
);
949 swfdec_as_object_add_native_variable (proto
, SWFDEC_AS_STR_blockIndent
,
950 swfdec_text_format_do_get_block_indent
,
951 swfdec_text_format_do_set_block_indent
);
952 swfdec_as_object_add_native_variable (proto
, SWFDEC_AS_STR_bold
,
953 swfdec_text_format_do_get_bold
, swfdec_text_format_do_set_bold
);
954 swfdec_as_object_add_native_variable (proto
, SWFDEC_AS_STR_bullet
,
955 swfdec_text_format_do_get_bullet
, swfdec_text_format_do_set_bullet
);
956 swfdec_as_object_add_native_variable (proto
, SWFDEC_AS_STR_color
,
957 swfdec_text_format_do_get_color
, swfdec_text_format_do_set_color
);
958 swfdec_as_object_add_native_variable (proto
, SWFDEC_AS_STR_display
,
959 swfdec_text_format_do_get_display
, swfdec_text_format_do_set_display
);
960 swfdec_as_object_add_native_variable (proto
, SWFDEC_AS_STR_font
,
961 swfdec_text_format_do_get_font
, swfdec_text_format_do_set_font
);
962 swfdec_as_object_add_native_variable (proto
, SWFDEC_AS_STR_indent
,
963 swfdec_text_format_do_get_indent
, swfdec_text_format_do_set_indent
);
964 swfdec_as_object_add_native_variable (proto
, SWFDEC_AS_STR_italic
,
965 swfdec_text_format_do_get_italic
, swfdec_text_format_do_set_italic
);
966 if (cx
->version
>= 8) {
967 swfdec_as_object_add_native_variable (proto
, SWFDEC_AS_STR_kerning
,
968 swfdec_text_format_do_get_kerning
, swfdec_text_format_do_set_kerning
);
970 swfdec_as_object_add_native_variable (proto
, SWFDEC_AS_STR_leading
,
971 swfdec_text_format_do_get_leading
, swfdec_text_format_do_set_leading
);
972 swfdec_as_object_add_native_variable (proto
, SWFDEC_AS_STR_leftMargin
,
973 swfdec_text_format_do_get_left_margin
,
974 swfdec_text_format_do_set_left_margin
);
975 if (cx
->version
>= 8) {
976 swfdec_as_object_add_native_variable (proto
, SWFDEC_AS_STR_letterSpacing
,
977 swfdec_text_format_do_get_letter_spacing
,
978 swfdec_text_format_do_set_letter_spacing
);
980 swfdec_as_object_add_native_variable (proto
, SWFDEC_AS_STR_rightMargin
,
981 swfdec_text_format_do_get_right_margin
,
982 swfdec_text_format_do_set_right_margin
);
983 swfdec_as_object_add_native_variable (proto
, SWFDEC_AS_STR_size
,
984 swfdec_text_format_do_get_size
, swfdec_text_format_do_set_size
);
985 swfdec_as_object_add_native_variable (proto
, SWFDEC_AS_STR_tabStops
,
986 swfdec_text_format_do_get_tab_stops
,
987 swfdec_text_format_do_set_tab_stops
);
988 swfdec_as_object_add_native_variable (proto
, SWFDEC_AS_STR_target
,
989 swfdec_text_format_do_get_target
, swfdec_text_format_do_set_target
);
990 swfdec_as_object_add_native_variable (proto
, SWFDEC_AS_STR_underline
,
991 swfdec_text_format_do_get_underline
,
992 swfdec_text_format_do_set_underline
);
993 swfdec_as_object_add_native_variable (proto
, SWFDEC_AS_STR_url
,
994 swfdec_text_format_do_get_url
, swfdec_text_format_do_set_url
);
997 SWFDEC_AS_CONSTRUCTOR (110, 0, swfdec_text_format_construct
, swfdec_text_format_get_type
)
999 swfdec_text_format_construct (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
1000 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
1002 static const char *arguments
[] = {
1005 SWFDEC_AS_STR_color
,
1007 SWFDEC_AS_STR_italic
,
1008 SWFDEC_AS_STR_underline
,
1010 SWFDEC_AS_STR_target
,
1011 SWFDEC_AS_STR_align
,
1012 SWFDEC_AS_STR_leftMargin
,
1013 SWFDEC_AS_STR_rightMargin
,
1014 SWFDEC_AS_STR_indent
,
1015 SWFDEC_AS_STR_leading
,
1018 SwfdecAsFunction
*function
;
1019 SwfdecAsObject
*tmp
;
1023 if (!swfdec_as_context_is_constructing (cx
)) {
1024 SWFDEC_FIXME ("What do we do if not constructing?");
1028 g_assert (SWFDEC_IS_TEXT_FORMAT (object
));
1030 swfdec_text_format_init_properties (cx
);
1032 swfdec_text_format_clear (SWFDEC_TEXT_FORMAT (object
));
1034 // FIXME: Need better way to create function without prototype/constructor
1036 cx
->Function
= NULL
;
1037 function
= swfdec_as_native_function_new (cx
, SWFDEC_AS_STR_getTextExtent
,
1038 swfdec_text_format_getTextExtent
, NULL
);
1040 if (function
!= NULL
) {
1041 SWFDEC_AS_VALUE_SET_OBJECT (&val
, SWFDEC_AS_OBJECT (function
));
1042 swfdec_as_object_set_variable (object
, SWFDEC_AS_STR_getTextExtent
, &val
);
1045 for (i
= 0; i
< argc
&& arguments
[i
] != NULL
; i
++) {
1046 swfdec_as_object_set_variable (object
, arguments
[i
], &argv
[i
]);
1051 swfdec_text_format_copy (SwfdecTextFormat
*copy_from
)
1053 SwfdecAsObject
*object_to
;
1054 SwfdecTextFormat
*copy_to
;
1056 g_return_val_if_fail (SWFDEC_IS_TEXT_FORMAT (copy_from
), NULL
);
1058 object_to
= swfdec_text_format_new_no_properties (
1059 swfdec_gc_object_get_context (copy_from
));
1060 if (object_to
== NULL
)
1062 copy_to
= SWFDEC_TEXT_FORMAT (object_to
);
1064 swfdec_text_attributes_copy (©_to
->attr
, ©_from
->attr
, -1);
1065 copy_to
->values_set
= copy_from
->values_set
;
1071 swfdec_text_format_new_no_properties (SwfdecAsContext
*context
)
1073 SwfdecAsObject
*tmp
, *ret
;
1074 SwfdecAsFunction
*function
;
1077 g_return_val_if_fail (SWFDEC_IS_AS_CONTEXT (context
), NULL
);
1079 ret
= g_object_new (SWFDEC_TYPE_TEXT_FORMAT
, "context", context
, NULL
);
1081 swfdec_text_format_clear (SWFDEC_TEXT_FORMAT (ret
));
1082 swfdec_as_object_set_constructor_by_name (ret
, SWFDEC_AS_STR_TextFormat
, NULL
);
1084 // FIXME: Need better way to create function without prototype/constructor
1085 tmp
= context
->Function
;
1086 context
->Function
= NULL
;
1087 function
= swfdec_as_native_function_new (context
, SWFDEC_AS_STR_getTextExtent
,
1088 swfdec_text_format_getTextExtent
, NULL
);
1089 context
->Function
= tmp
;
1090 if (function
!= NULL
) {
1091 SWFDEC_AS_VALUE_SET_OBJECT (&val
, SWFDEC_AS_OBJECT (function
));
1092 swfdec_as_object_set_variable (ret
, SWFDEC_AS_STR_getTextExtent
, &val
);
1099 swfdec_text_format_new (SwfdecAsContext
*context
)
1101 g_return_val_if_fail (SWFDEC_IS_AS_CONTEXT (context
), NULL
);
1103 swfdec_text_format_init_properties (context
);
1105 return swfdec_text_format_new_no_properties (context
);