[Swfdec-commits] 29 commits - swfdec/Makefile.am swfdec/swfdec_actor.h swfdec/swfdec_marshal.list swfdec/swfdec_movie.c swfdec/swfdec_player.c swfdec/swfdec_player_internal.h swfdec/swfdec_text_attributes.c swfdec/swfdec_text_attributes.h swfdec/swfdec_text_buffer.c swfdec/swfdec_text_buffer.h swfdec/swfdec_text_field.c swfdec/swfdec_text_field_movie_as.c swfdec/swfdec_text_field_movie.c swfdec/swfdec_text_field_movie.h swfdec/swfdec_text_field_movie_html.c swfdec/swfdec_text_format.c swfdec/swfdec_text_format.h swfdec/swfdec_text_layout.c swfdec/swfdec_text_layout.h test/image test/trace
Benjamin Otte
company at kemper.freedesktop.org
Thu May 8 15:19:28 PDT 2008
swfdec/Makefile.am | 6
swfdec/swfdec_actor.h | 4
swfdec/swfdec_marshal.list | 1
swfdec/swfdec_movie.c | 33
swfdec/swfdec_player.c | 109 -
swfdec/swfdec_player_internal.h | 2
swfdec/swfdec_text_attributes.c | 161 ++
swfdec/swfdec_text_attributes.h | 115 +
swfdec/swfdec_text_buffer.c | 464 ++++++
swfdec/swfdec_text_buffer.h | 104 +
swfdec/swfdec_text_field.c | 16
swfdec/swfdec_text_field_movie.c | 1681 +++----------------------
swfdec/swfdec_text_field_movie.h | 92 -
swfdec/swfdec_text_field_movie_as.c | 185 +-
swfdec/swfdec_text_field_movie_html.c | 250 +--
swfdec/swfdec_text_format.c | 508 ++-----
swfdec/swfdec_text_format.h | 61
swfdec/swfdec_text_layout.c | 818 ++++++++++++
swfdec/swfdec_text_layout.h | 91 +
test/image/Makefile.am | 47
test/image/text-field-background-5.swf |binary
test/image/text-field-background-5.swf.png |binary
test/image/text-field-background-6.swf |binary
test/image/text-field-background-6.swf.png |binary
test/image/text-field-background-7.swf |binary
test/image/text-field-background-7.swf.png |binary
test/image/text-field-background-8.swf |binary
test/image/text-field-background-8.swf.png |binary
test/image/text-field-background.as | 18
test/image/text-field-border-5.swf |binary
test/image/text-field-border-5.swf.png |binary
test/image/text-field-border-6.swf |binary
test/image/text-field-border-6.swf.png |binary
test/image/text-field-border-7.swf |binary
test/image/text-field-border-7.swf.png |binary
test/image/text-field-border-8.swf |binary
test/image/text-field-border-8.swf.png |binary
test/image/text-field-border.as | 15
test/image/text-field-scale-negative-5.swf |binary
test/image/text-field-scale-negative-5.swf.png |binary
test/image/text-field-scale-negative-6.swf |binary
test/image/text-field-scale-negative-6.swf.png |binary
test/image/text-field-scale-negative-7.swf |binary
test/image/text-field-scale-negative-7.swf.png |binary
test/image/text-field-scale-negative-8.swf |binary
test/image/text-field-scale-negative-8.swf.png |binary
test/image/text-field-scale-negative.as | 22
test/image/text-field-scale-parents-5.swf |binary
test/image/text-field-scale-parents-5.swf.png |binary
test/image/text-field-scale-parents-6.swf |binary
test/image/text-field-scale-parents-6.swf.png |binary
test/image/text-field-scale-parents-7.swf |binary
test/image/text-field-scale-parents-7.swf.png |binary
test/image/text-field-scale-parents-8.swf |binary
test/image/text-field-scale-parents-8.swf.png |binary
test/image/text-field-scale-parents.as | 14
test/image/text-field-wordWrap-5.swf |binary
test/image/text-field-wordWrap-5.swf.png |binary
test/image/text-field-wordWrap-6.swf |binary
test/image/text-field-wordWrap-6.swf.png |binary
test/image/text-field-wordWrap-7.swf |binary
test/image/text-field-wordWrap-7.swf.png |binary
test/image/text-field-wordWrap-8.swf |binary
test/image/text-field-wordWrap-8.swf.png |binary
test/image/text-field-wordWrap.as | 24
test/trace/Makefile.am | 9
test/trace/text-field-hscroll-5.swf |binary
test/trace/text-field-hscroll-5.swf.trace | 6
test/trace/text-field-hscroll-6.swf |binary
test/trace/text-field-hscroll-6.swf.trace | 6
test/trace/text-field-hscroll-7.swf |binary
test/trace/text-field-hscroll-7.swf.trace | 6
test/trace/text-field-hscroll-8.swf |binary
test/trace/text-field-hscroll-8.swf.trace | 6
test/trace/text-field-hscroll.as | 29
75 files changed, 2729 insertions(+), 2174 deletions(-)
New commits:
commit 49c90e4ceef5ccae2e0976eddc7424a8754597e1
Author: Benjamin Otte <otte at gnome.org>
Date: Thu May 8 23:00:01 2008 +0200
add a simple hscroll test
diff --git a/test/trace/Makefile.am b/test/trace/Makefile.am
index b00b85b..c27dd2c 100644
--- a/test/trace/Makefile.am
+++ b/test/trace/Makefile.am
@@ -3296,6 +3296,15 @@ EXTRA_DIST = \
text-field-get-text-format-7.swf.trace \
text-field-get-text-format-8.swf \
text-field-get-text-format-8.swf.trace \
+ text-field-hscroll-5.swf \
+ text-field-hscroll-5.swf.trace \
+ text-field-hscroll-6.swf \
+ text-field-hscroll-6.swf.trace \
+ text-field-hscroll-7.swf \
+ text-field-hscroll-7.swf.trace \
+ text-field-hscroll-8.swf \
+ text-field-hscroll-8.swf.trace \
+ text-field-hscroll.as \
text-field-html-input.as \
text-field-html-input-5.swf \
text-field-html-input-5.swf.trace \
diff --git a/test/trace/text-field-hscroll-5.swf b/test/trace/text-field-hscroll-5.swf
new file mode 100644
index 0000000..aea0e49
Binary files /dev/null and b/test/trace/text-field-hscroll-5.swf differ
diff --git a/test/trace/text-field-hscroll-5.swf.trace b/test/trace/text-field-hscroll-5.swf.trace
new file mode 100644
index 0000000..8c4db68
--- /dev/null
+++ b/test/trace/text-field-hscroll-5.swf.trace
@@ -0,0 +1,6 @@
+undefined
+undefined
+undefined
+undefined
+undefined
+undefined
diff --git a/test/trace/text-field-hscroll-6.swf b/test/trace/text-field-hscroll-6.swf
new file mode 100644
index 0000000..99e4519
Binary files /dev/null and b/test/trace/text-field-hscroll-6.swf differ
diff --git a/test/trace/text-field-hscroll-6.swf.trace b/test/trace/text-field-hscroll-6.swf.trace
new file mode 100644
index 0000000..c16cb90
--- /dev/null
+++ b/test/trace/text-field-hscroll-6.swf.trace
@@ -0,0 +1,6 @@
+1
+1
+2
+1
+1
+1
diff --git a/test/trace/text-field-hscroll-7.swf b/test/trace/text-field-hscroll-7.swf
new file mode 100644
index 0000000..069b7f7
Binary files /dev/null and b/test/trace/text-field-hscroll-7.swf differ
diff --git a/test/trace/text-field-hscroll-7.swf.trace b/test/trace/text-field-hscroll-7.swf.trace
new file mode 100644
index 0000000..c16cb90
--- /dev/null
+++ b/test/trace/text-field-hscroll-7.swf.trace
@@ -0,0 +1,6 @@
+1
+1
+2
+1
+1
+1
diff --git a/test/trace/text-field-hscroll-8.swf b/test/trace/text-field-hscroll-8.swf
new file mode 100644
index 0000000..95a75c4
Binary files /dev/null and b/test/trace/text-field-hscroll-8.swf differ
diff --git a/test/trace/text-field-hscroll-8.swf.trace b/test/trace/text-field-hscroll-8.swf.trace
new file mode 100644
index 0000000..c16cb90
--- /dev/null
+++ b/test/trace/text-field-hscroll-8.swf.trace
@@ -0,0 +1,6 @@
+1
+1
+2
+1
+1
+1
diff --git a/test/trace/text-field-hscroll.as b/test/trace/text-field-hscroll.as
new file mode 100644
index 0000000..2d4e26e
--- /dev/null
+++ b/test/trace/text-field-hscroll.as
@@ -0,0 +1,29 @@
+// makeswf -v 7 -s 200x150 -r 1 -o text-field-hscroll.swf text-field-hscroll.as
+
+createTextField ("t", 0, 0, 0, 100, 32);
+var tf = new TextFormat ();
+tf.font = "Bitstream Vera Sans";
+t.setNewTextFormat (tf);
+t.border = true;
+
+t.text = "Hello\nWorld\nHey";
+tf.size = 24;
+t.setTextFormat (0, 5, tf);
+
+trace (t.scroll);
+trace (t.bottomScroll);
+trace (t.maxscroll);
+
+createTextField ("s", 1, 0, 50, 100, 10);
+var tf = new TextFormat ();
+tf.font = "Bitstream Vera Sans";
+s.setNewTextFormat (tf);
+s.border = true;
+
+s.text = "Hello World";
+
+trace (s.scroll);
+trace (s.bottomScroll);
+trace (s.maxscroll);
+
+getURL ("fscommand:quit", "");
commit 5e9205a7fcfde3e3828599558f52bc32c0b1cd56
Author: Benjamin Otte <otte at gnome.org>
Date: Thu May 8 22:54:44 2008 +0200
add support for vertical scrolling again
I didn't have a signle look at events yet...
diff --git a/swfdec/swfdec_text_field_movie.c b/swfdec/swfdec_text_field_movie.c
index cfe8783..e7fa1fb 100644
--- a/swfdec/swfdec_text_field_movie.c
+++ b/swfdec/swfdec_text_field_movie.c
@@ -132,94 +132,7 @@ swfdec_text_field_movie_render (SwfdecMovie *movie, cairo_t *cr,
text->stage_rect.height - BORDER_TOP - BORDER_BOTTOM);
cairo_clip (cr);
swfdec_text_layout_render (text->layout, cr, ctrans,
- 0, text->stage_rect.height - BORDER_TOP + BORDER_BOTTOM, &text->stage_rect);
-}
-
-void
-swfdec_text_field_movie_update_scroll (SwfdecTextFieldMovie *text,
- gboolean check_limits)
-{
-#if 0
- SwfdecLayout *layouts;
- int i, num, y, visible, all, height;
- double width, width_max;
-
- g_return_if_fail (SWFDEC_IS_TEXT_FIELD_MOVIE (text));
-
- layouts = swfdec_text_field_movie_get_layouts (text, &num, NULL, NULL, NULL);
-
- width = SWFDEC_MOVIE (text)->original_extents.x1 -
- SWFDEC_MOVIE (text)->original_extents.x0;
- height = SWFDEC_MOVIE (text)->original_extents.y1 -
- SWFDEC_MOVIE (text)->original_extents.y0;
-
- width_max = width;
- y = 0;
- all = 0;
- visible = 0;
-
- for (i = num - 1; i >= 0; i--)
- {
- SwfdecLayout *layout = &layouts[i];
- PangoLayoutIter *iter_line;
- PangoRectangle rect;
-
- if (layouts[i].width > width_max)
- width_max = layouts[i].width;
-
- y += layout->height;
-
- iter_line = pango_layout_get_iter (layout->layout);
-
- do {
- pango_layout_iter_get_line_extents (iter_line, NULL, &rect);
- pango_extents_to_pixels (NULL, &rect);
-
- if (y - rect.y <= height)
- visible++;
-
- all++;
- } while (pango_layout_iter_next_line (iter_line));
-
- pango_layout_iter_free (iter_line);
- }
-
- swfdec_text_field_movie_free_layouts (layouts);
- layouts = NULL;
-
- if (text->scroll_max != all - visible + 1) {
- text->scroll_max = all - visible + 1;
- text->scroll_changed = TRUE;
- }
- if (text->hscroll_max != SWFDEC_TWIPS_TO_DOUBLE (width_max - width)) {
- text->hscroll_max = SWFDEC_TWIPS_TO_DOUBLE (width_max - width);
- text->scroll_changed = TRUE;
- }
-
- if (check_limits) {
- if (text->scroll != CLAMP(text->scroll, 1, text->scroll_max)) {
- text->scroll = CLAMP(text->scroll, 1, text->scroll_max);
- text->scroll_changed = TRUE;
- }
- if (text->scroll_bottom != text->scroll + (visible > 0 ? visible - 1 : 0))
- {
- text->scroll_bottom = text->scroll + (visible > 0 ? visible - 1 : 0);
- text->scroll_changed = TRUE;
- }
- if (text->hscroll != CLAMP(text->hscroll, 0, text->hscroll_max)) {
- text->hscroll = CLAMP(text->hscroll, 0, text->hscroll_max);
- text->scroll_changed = TRUE;
- }
- } else {
- if (text->scroll_bottom < text->scroll ||
- text->scroll_bottom > text->scroll_max + visible - 1) {
- text->scroll_bottom = text->scroll;
- text->scroll_changed = TRUE;
- }
- }
-#else
- SWFDEC_STUB ("swfdec_text_field_movie_update_scroll");
-#endif
+ text->scroll, text->stage_rect.height - BORDER_TOP + BORDER_BOTTOM, &text->stage_rect);
}
gboolean
@@ -368,6 +281,31 @@ swfdec_text_field_movie_update_area (SwfdecTextFieldMovie *text)
}
}
+/* NB: can be run with unlocked player */
+void
+swfdec_text_field_movie_update_scroll (SwfdecTextFieldMovie *text)
+{
+ guint scroll_max, lines_visible, rows, height;
+
+ height = text->stage_rect.height - BORDER_TOP - BORDER_BOTTOM;
+ rows = swfdec_text_layout_get_n_rows (text->layout);
+ scroll_max = rows - swfdec_text_layout_get_visible_rows_end (text->layout, height);
+ if (scroll_max != text->scroll_max) {
+ text->scroll_max = scroll_max;
+ text->scroll_changed = TRUE;
+ }
+ if (scroll_max < text->scroll) {
+ text->scroll = scroll_max;
+ text->scroll_changed = TRUE;
+ }
+ lines_visible = swfdec_text_layout_get_visible_rows (text->layout,
+ text->scroll, height);
+ if (lines_visible != text->lines_visible) {
+ text->lines_visible = lines_visible;
+ text->scroll_changed = TRUE;
+ }
+}
+
/* NB: This signal can happen without a locked player */
static void
swfdec_text_field_movie_layout_changed (SwfdecTextLayout *layout,
@@ -387,6 +325,8 @@ swfdec_text_field_movie_layout_changed (SwfdecTextLayout *layout,
text->layout_height = h;
//swfdec_text_field_movie_auto_size (text);
}
+
+ swfdec_text_field_movie_update_scroll (text);
}
static void
@@ -803,7 +743,6 @@ swfdec_text_field_movie_init (SwfdecTextFieldMovie *text)
g_signal_connect (text->layout, "changed",
G_CALLBACK (swfdec_text_field_movie_layout_changed), text);
- text->scroll = 1;
text->mouse_wheel_enabled = TRUE;
swfdec_text_attributes_reset (&text->default_attributes);
@@ -979,7 +918,6 @@ swfdec_text_field_movie_replace_text (SwfdecTextFieldMovie *text,
}
swfdec_movie_invalidate_last (SWFDEC_MOVIE (text));
- swfdec_text_field_movie_update_scroll (text, TRUE);
}
void
@@ -1020,5 +958,4 @@ swfdec_text_field_movie_set_text (SwfdecTextFieldMovie *text, const char *str,
}
swfdec_movie_invalidate_last (SWFDEC_MOVIE (text));
- swfdec_text_field_movie_update_scroll (text, TRUE);
}
diff --git a/swfdec/swfdec_text_field_movie.h b/swfdec/swfdec_text_field_movie.h
index 82d8ae0..6789432 100644
--- a/swfdec/swfdec_text_field_movie.h
+++ b/swfdec/swfdec_text_field_movie.h
@@ -78,9 +78,10 @@ struct _SwfdecTextFieldMovie {
gboolean scroll_changed; /* if any of the scroll attributes have changed and we haven't fired the event yet */
guint changed; /* number of onChanged events we have to emit */
- int scroll;
- int scroll_max;
- int scroll_bottom;
+ /* scroll variables */
+ guint scroll; /* current scroll offset in lines (0-indexed) */
+ guint scroll_max; /* scroll must be smaller than this value */
+ guint lines_visible; /* number of lines currently visible */
int hscroll;
int hscroll_max;
gboolean mouse_wheel_enabled;
@@ -103,9 +104,8 @@ GType swfdec_text_field_movie_get_type (void);
void swfdec_text_field_movie_set_text (SwfdecTextFieldMovie * movie,
const char * str,
gboolean html);
+void swfdec_text_field_movie_update_scroll (SwfdecTextFieldMovie * text);
gboolean swfdec_text_field_movie_auto_size (SwfdecTextFieldMovie * text);
-void swfdec_text_field_movie_update_scroll (SwfdecTextFieldMovie * text,
- gboolean check_limits);
const char * swfdec_text_field_movie_get_text (SwfdecTextFieldMovie * text);
void swfdec_text_field_movie_set_listen_variable (SwfdecTextFieldMovie * text,
const char * value);
diff --git a/swfdec/swfdec_text_field_movie_as.c b/swfdec/swfdec_text_field_movie_as.c
index 05a1d5b..979341f 100644
--- a/swfdec/swfdec_text_field_movie_as.c
+++ b/swfdec/swfdec_text_field_movie_as.c
@@ -583,7 +583,7 @@ swfdec_text_field_movie_get_bottomScroll (SwfdecAsContext *cx,
SWFDEC_AS_CHECK (SWFDEC_TYPE_TEXT_FIELD_MOVIE, &text, "");
- SWFDEC_AS_VALUE_SET_NUMBER (ret, text->scroll_bottom);
+ SWFDEC_AS_VALUE_SET_NUMBER (ret, text->scroll + text->lines_visible);
}
static void
@@ -641,7 +641,7 @@ swfdec_text_field_movie_get_maxscroll (SwfdecAsContext *cx,
SWFDEC_AS_CHECK (SWFDEC_TYPE_TEXT_FIELD_MOVIE, &text, "");
- SWFDEC_AS_VALUE_SET_NUMBER (ret, text->scroll_max);
+ SWFDEC_AS_VALUE_SET_NUMBER (ret, text->scroll_max + 1);
}
static void
@@ -680,7 +680,7 @@ swfdec_text_field_movie_do_get_scroll (SwfdecAsContext *cx,
SWFDEC_AS_CHECK (SWFDEC_TYPE_TEXT_FIELD_MOVIE, &text, "");
- SWFDEC_AS_VALUE_SET_NUMBER (ret, text->scroll);
+ SWFDEC_AS_VALUE_SET_NUMBER (ret, text->scroll + 1);
}
static void
@@ -693,11 +693,11 @@ swfdec_text_field_movie_do_set_scroll (SwfdecAsContext *cx,
SWFDEC_AS_CHECK (SWFDEC_TYPE_TEXT_FIELD_MOVIE, &text, "i", &value);
- value = CLAMP (value, 1, text->scroll_max);
- if (value != text->scroll) {
- text->scroll_bottom += value - text->scroll;
+ value = CLAMP (value - 1, 0, (int) text->scroll_max);
+ if ((guint) value != text->scroll) {
text->scroll = value;
text->scroll_changed = TRUE;
+ swfdec_text_field_movie_update_scroll (text);
swfdec_movie_invalidate_last (SWFDEC_MOVIE (text));
}
}
@@ -1163,7 +1163,7 @@ swfdec_text_field_movie_setTextFormat (SwfdecAsContext *cx,
swfdec_movie_invalidate_last (SWFDEC_MOVIE (text));
swfdec_text_field_movie_auto_size (text);
// special case: update the max values, not the current values
- swfdec_text_field_movie_update_scroll (text, FALSE);
+ // swfdec_text_field_movie_update_scroll (text, FALSE);
}
SWFDEC_AS_NATIVE (104, 101, swfdec_text_field_movie_getTextFormat)
diff --git a/swfdec/swfdec_text_layout.c b/swfdec/swfdec_text_layout.c
index 7947bd2..8af09d0 100644
--- a/swfdec/swfdec_text_layout.c
+++ b/swfdec/swfdec_text_layout.c
@@ -662,6 +662,100 @@ swfdec_text_layout_find_row (SwfdecTextLayout *layout, guint row)
}
/**
+ * swfdec_text_layout_get_visible_rows:
+ * @layout: the layout
+ * @row: the first visible row
+ * @height: the height in pixels of visible text
+ *
+ * Queries the number of rows that would be rendered, if rendering were to start
+ * with @row and had to fit into @height pixels.
+ *
+ * Returns: the number of rows that would be rendered
+ **/
+guint
+swfdec_text_layout_get_visible_rows (SwfdecTextLayout *layout, guint row, guint height)
+{
+ GSequenceIter *iter;
+ SwfdecTextBlock *block;
+ PangoRectangle extents;
+ guint count = 0;
+
+ g_return_val_if_fail (SWFDEC_IS_TEXT_LAYOUT (layout), 1);
+ g_return_val_if_fail (row < swfdec_text_layout_get_n_rows (layout), 1);
+
+ swfdec_text_layout_ensure (layout);
+
+ iter = swfdec_text_layout_find_row (layout, row);
+ block = g_sequence_get (iter);
+ row -= block->row;
+
+ do {
+ block = g_sequence_get (iter);
+ for (;row < (guint) pango_layout_get_line_count (block->layout); row++) {
+ PangoLayoutLine *line = pango_layout_get_line_readonly (block->layout, row);
+
+ pango_layout_line_get_pixel_extents (line, NULL, &extents);
+ if (extents.height > (int) height)
+ goto out;
+ height -= extents.height;
+ count++;
+ }
+ row = 0;
+ if ((int) height <= pango_layout_get_spacing (block->layout) / PANGO_SCALE)
+ goto out;
+ height -= pango_layout_get_spacing (block->layout) / PANGO_SCALE;
+ iter = g_sequence_iter_next (iter);
+ } while (!g_sequence_iter_is_end (iter));
+
+out:
+ return MAX (count, 1);
+}
+
+/**
+ * swfdec_text_layout_get_visible_rows_end:
+ * @layout: the layout
+ * @height: the height in pixels
+ *
+ * Computes how many rows will be visible if only the last rows would be
+ * displayed. This is useful for computing maximal scroll offsets.
+ *
+ * Returns: The number of rows visible at the bottom.
+ **/
+guint
+swfdec_text_layout_get_visible_rows_end (SwfdecTextLayout *layout, guint height)
+{
+ GSequenceIter *iter;
+ SwfdecTextBlock *block;
+ PangoRectangle extents;
+ guint row, count = 0;
+
+ g_return_val_if_fail (SWFDEC_IS_TEXT_LAYOUT (layout), 1);
+
+ swfdec_text_layout_ensure (layout);
+ iter = g_sequence_get_end_iter (layout->blocks);
+
+ do {
+ iter = g_sequence_iter_prev (iter);
+ block = g_sequence_get (iter);
+ if ((int) height <= pango_layout_get_spacing (block->layout) / PANGO_SCALE)
+ goto out;
+ height -= pango_layout_get_spacing (block->layout) / PANGO_SCALE;
+ for (row = pango_layout_get_line_count (block->layout); row > 0; row--) {
+ PangoLayoutLine *line = pango_layout_get_line_readonly (block->layout, row - 1);
+
+ pango_layout_line_get_pixel_extents (line, NULL, &extents);
+ if (extents.height > (int) height)
+ goto out;
+ height -= extents.height;
+ count++;
+ }
+ } while (!g_sequence_iter_is_begin (iter));
+
+out:
+ return MAX (count, 1);
+}
+
+/**
* swfdec_text_layout_render:
* @layout: the layout to render
* @cr: the Cairo context to render to. The context will be transformed so that
@@ -694,7 +788,7 @@ swfdec_text_layout_render (SwfdecTextLayout *layout, cairo_t *cr,
iter = swfdec_text_layout_find_row (layout, row);
block = g_sequence_get (iter);
row -= block->row;
- while (!g_sequence_iter_is_end (iter)) {
+ do {
block = g_sequence_get (iter);
pango_cairo_update_layout (cr, block->layout);
cairo_translate (cr, block->rect.x, 0);
@@ -713,9 +807,12 @@ swfdec_text_layout_render (SwfdecTextLayout *layout, cairo_t *cr,
height -= extents.height;
cairo_translate (cr, 0, extents.height + extents.y);
}
+ if ((int) height <= pango_layout_get_spacing (block->layout) / PANGO_SCALE)
+ return;
+ height -= pango_layout_get_spacing (block->layout) / PANGO_SCALE;
cairo_translate (cr, -block->rect.x, pango_layout_get_spacing (block->layout) / PANGO_SCALE);
row = 0;
iter = g_sequence_iter_next (iter);
- }
+ } while (!g_sequence_iter_is_end (iter));
}
diff --git a/swfdec/swfdec_text_layout.h b/swfdec/swfdec_text_layout.h
index 0457901..75f969f 100644
--- a/swfdec/swfdec_text_layout.h
+++ b/swfdec/swfdec_text_layout.h
@@ -71,7 +71,13 @@ void swfdec_text_layout_set_scale (SwfdecTextLayout * layout,
double swfdec_text_layout_get_scale (SwfdecTextLayout * layout);
guint swfdec_text_layout_get_width (SwfdecTextLayout * layout);
guint swfdec_text_layout_get_height (SwfdecTextLayout * layout);
+
guint swfdec_text_layout_get_n_rows (SwfdecTextLayout * layout);
+guint swfdec_text_layout_get_visible_rows (SwfdecTextLayout * layout,
+ guint row,
+ guint height);
+guint swfdec_text_layout_get_visible_rows_end (SwfdecTextLayout * layout,
+ guint height);
void swfdec_text_layout_render (SwfdecTextLayout * layout,
cairo_t * cr,
commit dc3ba2caf1e7fd79b0028752e7ae21d380cfc3cf
Author: Benjamin Otte <otte at gnome.org>
Date: Thu May 8 20:56:47 2008 +0200
keep scale factors around
diff --git a/swfdec/swfdec_text_field_movie.c b/swfdec/swfdec_text_field_movie.c
index 5d36b39..cfe8783 100644
--- a/swfdec/swfdec_text_field_movie.c
+++ b/swfdec/swfdec_text_field_movie.c
@@ -359,6 +359,8 @@ swfdec_text_field_movie_update_area (SwfdecTextFieldMovie *text)
/* FIXME: floor, ceil or round? */
text->stage_rect.width = round (x) - text->stage_rect.x;
text->stage_rect.height = round (y) - text->stage_rect.y;
+ text->xscale = matrix.xx;
+ text->yscale = matrix.yy;
swfdec_text_layout_set_scale (text->layout, matrix.yy * SWFDEC_TWIPS_SCALE_FACTOR);
if (text->word_wrap && text->stage_rect.width >= BORDER_LEFT + BORDER_RIGHT) {
swfdec_text_layout_set_wrap_width (text->layout, text->stage_rect.width -
@@ -977,7 +979,6 @@ swfdec_text_field_movie_replace_text (SwfdecTextFieldMovie *text,
}
swfdec_movie_invalidate_last (SWFDEC_MOVIE (text));
- swfdec_text_field_movie_auto_size (text);
swfdec_text_field_movie_update_scroll (text, TRUE);
}
@@ -1019,6 +1020,5 @@ swfdec_text_field_movie_set_text (SwfdecTextFieldMovie *text, const char *str,
}
swfdec_movie_invalidate_last (SWFDEC_MOVIE (text));
- swfdec_text_field_movie_auto_size (text);
swfdec_text_field_movie_update_scroll (text, TRUE);
}
diff --git a/swfdec/swfdec_text_field_movie.h b/swfdec/swfdec_text_field_movie.h
index 4d1bae5..82d8ae0 100644
--- a/swfdec/swfdec_text_field_movie.h
+++ b/swfdec/swfdec_text_field_movie.h
@@ -44,6 +44,8 @@ struct _SwfdecTextFieldMovie {
SwfdecActor actor;
SwfdecRect extents; /* original extents (copied from graphic) */
+ double xscale; /* scale movie => stage in x direction */
+ double yscale; /* scale movie => stage in y direction */
SwfdecRectangle stage_rect; /* these extents in stage coordinates */
/* properties copied from textfield */
commit e01583685793c7ff29bc61f95e521c1573f1611e
Author: Benjamin Otte <otte at gnome.org>
Date: Thu May 8 15:57:44 2008 +0200
notice changes to the layout
Updates textWidth and textHeight automatically when this happens
diff --git a/swfdec/swfdec_text_field_movie.c b/swfdec/swfdec_text_field_movie.c
index 8c60cf3..5d36b39 100644
--- a/swfdec/swfdec_text_field_movie.c
+++ b/swfdec/swfdec_text_field_movie.c
@@ -293,6 +293,8 @@ swfdec_text_field_movie_dispose (GObject *object)
text->text = NULL;
}
if (text->layout) {
+ g_signal_handlers_disconnect_matched (text->layout, G_SIGNAL_MATCH_DATA,
+ 0, 0, NULL, NULL, text);
g_object_unref (text->layout);
text->layout = NULL;
}
@@ -321,6 +323,7 @@ swfdec_text_field_movie_mark (SwfdecAsObject *object)
SWFDEC_AS_OBJECT_CLASS (swfdec_text_field_movie_parent_class)->mark (object);
}
+/* NB: This signal can happen without a locked player */
static void
swfdec_text_field_movie_update_area (SwfdecTextFieldMovie *text)
{
@@ -357,12 +360,33 @@ swfdec_text_field_movie_update_area (SwfdecTextFieldMovie *text)
text->stage_rect.width = round (x) - text->stage_rect.x;
text->stage_rect.height = round (y) - text->stage_rect.y;
swfdec_text_layout_set_scale (text->layout, matrix.yy * SWFDEC_TWIPS_SCALE_FACTOR);
- if (text->word_wrap) {
+ if (text->word_wrap && text->stage_rect.width >= BORDER_LEFT + BORDER_RIGHT) {
swfdec_text_layout_set_wrap_width (text->layout, text->stage_rect.width -
BORDER_LEFT - BORDER_RIGHT);
}
}
+/* NB: This signal can happen without a locked player */
+static void
+swfdec_text_field_movie_layout_changed (SwfdecTextLayout *layout,
+ SwfdecTextFieldMovie *text)
+{
+ double scale;
+ guint w, h;
+
+ swfdec_movie_invalidate_last (SWFDEC_MOVIE (text));
+
+ scale = swfdec_text_layout_get_scale (layout);
+ w = swfdec_text_layout_get_width (layout) / scale;
+ h = swfdec_text_layout_get_height (layout) / scale;
+
+ if (w != text->layout_width || h != text->layout_height) {
+ text->layout_width = w;
+ text->layout_height = h;
+ //swfdec_text_field_movie_auto_size (text);
+ }
+}
+
static void
swfdec_text_field_movie_init_movie (SwfdecMovie *movie)
{
@@ -433,6 +457,7 @@ swfdec_text_field_movie_init_movie (SwfdecMovie *movie)
parent = parent->parent;
}
swfdec_text_field_movie_update_area (text);
+ swfdec_text_field_movie_layout_changed (text->layout, text);
}
static void
@@ -773,6 +798,8 @@ swfdec_text_field_movie_init (SwfdecTextFieldMovie *text)
G_CALLBACK (swfdec_text_field_movie_text_changed), text);
text->layout = swfdec_text_layout_new (text->text);
+ g_signal_connect (text->layout, "changed",
+ G_CALLBACK (swfdec_text_field_movie_layout_changed), text);
text->scroll = 1;
text->mouse_wheel_enabled = TRUE;
diff --git a/swfdec/swfdec_text_field_movie.h b/swfdec/swfdec_text_field_movie.h
index 43fcbde..4d1bae5 100644
--- a/swfdec/swfdec_text_field_movie.h
+++ b/swfdec/swfdec_text_field_movie.h
@@ -62,7 +62,6 @@ struct _SwfdecTextFieldMovie {
gboolean input_html; /* whether orginal input was given as HTML */
SwfdecTextLayout * layout; /* the layouted text */
- SwfdecRectangle layout_area; /* visible area of the layout */
guint layout_width; /* text width in pixels */
guint layout_height; /* text height in pixels */
commit 4bf45d8ce4693d1332639d3abcdbfa67b4a287b4
Author: Benjamin Otte <otte at gnome.org>
Date: Thu May 8 15:56:47 2008 +0200
setup a default PangoFontDescription for a PangoLayout
This is useful so that we can support empty lines properly.
diff --git a/swfdec/swfdec_text_layout.c b/swfdec/swfdec_text_layout.c
index 2f0cff8..7947bd2 100644
--- a/swfdec/swfdec_text_layout.c
+++ b/swfdec/swfdec_text_layout.c
@@ -39,10 +39,11 @@ enum {
static guint signals[LAST_SIGNAL] = { 0, };
-static PangoAttribute *
-swfdec_text_attribute_create_bold (SwfdecTextLayout *layout, const SwfdecTextAttributes *attr)
+static void
+swfdec_text_attribute_apply_bold (SwfdecTextLayout *layout, const SwfdecTextAttributes *attr,
+ PangoFontDescription *desc)
{
- return pango_attr_weight_new (attr->bold ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL);
+ pango_font_description_set_weight (desc, attr->bold ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL);
}
static PangoAttribute *
@@ -52,16 +53,19 @@ swfdec_text_attribute_create_color (SwfdecTextLayout *layout, const SwfdecTextAt
SWFDEC_COLOR_G (attr->color) * 255, SWFDEC_COLOR_B (attr->color) * 255);
}
-static PangoAttribute *
-swfdec_text_attribute_create_font (SwfdecTextLayout *layout, const SwfdecTextAttributes *attr)
+static void
+swfdec_text_attribute_apply_font (SwfdecTextLayout *layout, const SwfdecTextAttributes *attr,
+ PangoFontDescription *desc)
{
- return pango_attr_family_new (attr->font);
+ /* FIXME: resolve _sans, _serif and friends */
+ pango_font_description_set_family (desc, attr->font);
}
-static PangoAttribute *
-swfdec_text_attribute_create_italic (SwfdecTextLayout *layout, const SwfdecTextAttributes *attr)
+static void
+swfdec_text_attribute_apply_italic (SwfdecTextLayout *layout, const SwfdecTextAttributes *attr,
+ PangoFontDescription *desc)
{
- return pango_attr_style_new (attr->italic ? PANGO_STYLE_ITALIC : PANGO_STYLE_NORMAL);
+ pango_font_description_set_style (desc, attr->italic ? PANGO_STYLE_ITALIC : PANGO_STYLE_NORMAL);
}
static PangoAttribute *
@@ -70,12 +74,13 @@ swfdec_text_attribute_create_letter_spacing (SwfdecTextLayout *layout, const Swf
return pango_attr_letter_spacing_new (attr->letter_spacing * PANGO_SCALE);
}
-static PangoAttribute *
-swfdec_text_attribute_create_size (SwfdecTextLayout *layout, const SwfdecTextAttributes *attr)
+static void
+swfdec_text_attribute_apply_size (SwfdecTextLayout *layout, const SwfdecTextAttributes *attr,
+ PangoFontDescription *desc)
{
guint size = attr->size * layout->scale;
size = MAX (size, 1);
- return pango_attr_size_new_absolute (size * PANGO_SCALE);
+ pango_font_description_set_absolute_size (desc, size * PANGO_SCALE);
}
static PangoAttribute *
@@ -96,29 +101,30 @@ typedef enum {
struct {
FormatApplication application;
PangoAttribute * (* create_attribute) (SwfdecTextLayout *layout, const SwfdecTextAttributes *attr);
+ void (* apply_attribute) (SwfdecTextLayout *layout, const SwfdecTextAttributes *attr, PangoFontDescription *desc);
} format_table[] = {
/* unknown or unhandled properties */
- [SWFDEC_TEXT_ATTRIBUTE_DISPLAY] = { FORMAT_APPLY_UNKNOWN, NULL },
- [SWFDEC_TEXT_ATTRIBUTE_KERNING] = { FORMAT_APPLY_UNKNOWN, NULL },
+ [SWFDEC_TEXT_ATTRIBUTE_DISPLAY] = { FORMAT_APPLY_UNKNOWN, NULL, NULL },
+ [SWFDEC_TEXT_ATTRIBUTE_KERNING] = { FORMAT_APPLY_UNKNOWN, NULL, NULL },
/* per-paragraph options */
- [SWFDEC_TEXT_ATTRIBUTE_BULLET] = { FORMAT_APPLY_BLOCK, NULL },
- [SWFDEC_TEXT_ATTRIBUTE_INDENT] = { FORMAT_APPLY_BLOCK, NULL },
+ [SWFDEC_TEXT_ATTRIBUTE_BULLET] = { FORMAT_APPLY_BLOCK, NULL, NULL },
+ [SWFDEC_TEXT_ATTRIBUTE_INDENT] = { FORMAT_APPLY_BLOCK, NULL, NULL },
/* per-line options */
- [SWFDEC_TEXT_ATTRIBUTE_ALIGN] = { FORMAT_APPLY_LINE, NULL },
- [SWFDEC_TEXT_ATTRIBUTE_BLOCK_INDENT] = { FORMAT_APPLY_LINE, NULL },
- [SWFDEC_TEXT_ATTRIBUTE_LEADING] = { FORMAT_APPLY_LINE, NULL },
- [SWFDEC_TEXT_ATTRIBUTE_LEFT_MARGIN] = { FORMAT_APPLY_LINE, NULL },
- [SWFDEC_TEXT_ATTRIBUTE_RIGHT_MARGIN] = { FORMAT_APPLY_LINE, NULL },
- [SWFDEC_TEXT_ATTRIBUTE_TAB_STOPS] = { FORMAT_APPLY_LINE, NULL },
+ [SWFDEC_TEXT_ATTRIBUTE_ALIGN] = { FORMAT_APPLY_LINE, NULL, NULL },
+ [SWFDEC_TEXT_ATTRIBUTE_BLOCK_INDENT] = { FORMAT_APPLY_LINE, NULL, NULL },
+ [SWFDEC_TEXT_ATTRIBUTE_LEADING] = { FORMAT_APPLY_LINE, NULL, NULL },
+ [SWFDEC_TEXT_ATTRIBUTE_LEFT_MARGIN] = { FORMAT_APPLY_LINE, NULL, NULL },
+ [SWFDEC_TEXT_ATTRIBUTE_RIGHT_MARGIN] = { FORMAT_APPLY_LINE, NULL, NULL },
+ [SWFDEC_TEXT_ATTRIBUTE_TAB_STOPS] = { FORMAT_APPLY_LINE, NULL, NULL },
/* per-glyph options */
- [SWFDEC_TEXT_ATTRIBUTE_BOLD] = { FORMAT_APPLY_GLYPH, swfdec_text_attribute_create_bold },
- [SWFDEC_TEXT_ATTRIBUTE_COLOR] = { FORMAT_APPLY_GLYPH, swfdec_text_attribute_create_color },
- [SWFDEC_TEXT_ATTRIBUTE_FONT] = { FORMAT_APPLY_GLYPH, swfdec_text_attribute_create_font },
- [SWFDEC_TEXT_ATTRIBUTE_ITALIC] = { FORMAT_APPLY_GLYPH, swfdec_text_attribute_create_italic },
- [SWFDEC_TEXT_ATTRIBUTE_LETTER_SPACING] = { FORMAT_APPLY_GLYPH, swfdec_text_attribute_create_letter_spacing },
- [SWFDEC_TEXT_ATTRIBUTE_SIZE] = { FORMAT_APPLY_GLYPH, swfdec_text_attribute_create_size },
- [SWFDEC_TEXT_ATTRIBUTE_TARGET] = { FORMAT_APPLY_GLYPH, NULL },
- [SWFDEC_TEXT_ATTRIBUTE_UNDERLINE] = { FORMAT_APPLY_GLYPH, swfdec_text_attribute_create_underline },
+ [SWFDEC_TEXT_ATTRIBUTE_BOLD] = { FORMAT_APPLY_GLYPH, NULL, swfdec_text_attribute_apply_bold },
+ [SWFDEC_TEXT_ATTRIBUTE_COLOR] = { FORMAT_APPLY_GLYPH, swfdec_text_attribute_create_color, NULL },
+ [SWFDEC_TEXT_ATTRIBUTE_FONT] = { FORMAT_APPLY_GLYPH, NULL, swfdec_text_attribute_apply_font },
+ [SWFDEC_TEXT_ATTRIBUTE_ITALIC] = { FORMAT_APPLY_GLYPH, NULL, swfdec_text_attribute_apply_italic },
+ [SWFDEC_TEXT_ATTRIBUTE_LETTER_SPACING] = { FORMAT_APPLY_GLYPH, swfdec_text_attribute_create_letter_spacing, NULL },
+ [SWFDEC_TEXT_ATTRIBUTE_SIZE] = { FORMAT_APPLY_GLYPH, NULL, swfdec_text_attribute_apply_size },
+ [SWFDEC_TEXT_ATTRIBUTE_TARGET] = { FORMAT_APPLY_GLYPH, NULL, NULL },
+ [SWFDEC_TEXT_ATTRIBUTE_UNDERLINE] = { FORMAT_APPLY_GLYPH, swfdec_text_attribute_create_underline, NULL },
[SWFDEC_TEXT_ATTRIBUTE_URL] = { FORMAT_APPLY_GLYPH, NULL }
};
@@ -250,10 +256,24 @@ swfdec_text_layout_apply_line_attributes (SwfdecTextBlock *block,
}
static void
+swfdec_text_layout_apply_attributes_to_description (SwfdecTextLayout *layout,
+ const SwfdecTextAttributes *attr, PangoFontDescription *desc)
+{
+ guint i;
+
+ for (i = 0; i < G_N_ELEMENTS (format_table); i++) {
+ if (format_table[i].apply_attribute) {
+ format_table[i].apply_attribute (layout, attr, desc);
+ }
+ }
+}
+
+static void
swfdec_text_layout_apply_attributes (SwfdecTextLayout *layout, PangoAttrList *list,
const SwfdecTextAttributes *attr, guint start, guint end)
{
PangoAttribute *attribute;
+ PangoFontDescription *desc;
guint i;
for (i = 0; i < G_N_ELEMENTS (format_table); i++) {
@@ -264,6 +284,13 @@ swfdec_text_layout_apply_attributes (SwfdecTextLayout *layout, PangoAttrList *li
pango_attr_list_change (list, attribute);
}
}
+ desc = pango_font_description_new ();
+ swfdec_text_layout_apply_attributes_to_description (layout, attr, desc);
+ attribute = pango_attr_font_desc_new (desc);
+ pango_font_description_free (desc);
+ attribute->start_index = start;
+ attribute->end_index = end;
+ pango_attr_list_change (list, attribute);
}
static const SwfdecTextBlock *
@@ -276,6 +303,7 @@ swfdec_text_layout_create_paragraph (SwfdecTextLayout *layout, PangoContext *con
const char *string;
const SwfdecTextAttributes *attr, *attr_next;
gsize new_block, start_next;
+ PangoFontDescription *desc;
gboolean first = TRUE;
// TODO: kerning, display
@@ -300,6 +328,10 @@ swfdec_text_layout_create_paragraph (SwfdecTextLayout *layout, PangoContext *con
} else {
block->rect.width = layout->wrap_width;
}
+ desc = pango_font_description_new ();
+ swfdec_text_layout_apply_attributes_to_description (layout, attr, desc);
+ pango_layout_set_font_description (block->layout, desc);
+ pango_font_description_free (desc);
g_sequence_append (layout->blocks, block);
if (layout->password) {
commit 8eca2567cfdcf7c444eb9cec3b89b5d0a20af438
Author: Benjamin Otte <otte at gnome.org>
Date: Thu May 8 15:56:06 2008 +0200
LOG output more stuff from TextField parsing
diff --git a/swfdec/swfdec_text_field.c b/swfdec/swfdec_text_field.c
index 8eaa956..ddffb8d 100644
--- a/swfdec/swfdec_text_field.c
+++ b/swfdec/swfdec_text_field.c
@@ -143,6 +143,16 @@ tag_func_define_edit_text (SwfdecSwfDecoder * s, guint tag)
if (text->embed_fonts)
SWFDEC_FIXME ("Using embed fonts in TextField is not supported");
+ SWFDEC_LOG (" word wrap: %u", text->word_wrap);
+ SWFDEC_LOG (" multiline: %u", text->multiline);
+ SWFDEC_LOG (" password: %u", text->password);
+ SWFDEC_LOG (" editable: %u", text->editable);
+ SWFDEC_LOG (" autosize: %u", text->auto_size);
+ SWFDEC_LOG (" selectable: %u", text->selectable);
+ SWFDEC_LOG (" background: %u", text->background);
+ SWFDEC_LOG (" html: %u", text->html);
+ SWFDEC_LOG (" embedFonts: %u", text->embed_fonts);
+
if (has_font) {
SwfdecCharacter *font;
@@ -210,8 +220,10 @@ tag_func_define_edit_text (SwfdecSwfDecoder * s, guint tag)
text->variable = NULL;
}
- if (has_text)
+ if (has_text) {
text->input = swfdec_bits_get_string (b, s->version);
+ SWFDEC_LOG (" text = %s", text->input);
+ }
return SWFDEC_STATUS_OK;
}
commit 8f6725cfa0877c19d2a467abc628cd3e40af08df
Author: Benjamin Otte <otte at gnome.org>
Date: Thu May 8 11:28:10 2008 +0200
emit "matrix-changed" signals when sclaing is updated
This is pretty ugl code now, as the "matrix-changed" signal can be emitted
with and without the player being locked.
Maybe we should lock the player?
The only thing we definitely mustn't do is call script code...
diff --git a/swfdec/swfdec_player.c b/swfdec/swfdec_player.c
index 5b3ea00..1031f08 100644
--- a/swfdec/swfdec_player.c
+++ b/swfdec/swfdec_player.c
@@ -810,6 +810,48 @@ swfdec_player_get_property (GObject *object, guint param_id, GValue *value,
}
}
+static void
+swfdec_player_emit_signals (SwfdecPlayer *player)
+{
+ SwfdecPlayerPrivate *priv = player->priv;
+ GList *walk;
+
+ /* emit invalidate signal */
+ if (!swfdec_rectangle_is_empty (&priv->invalid_extents)) {
+ g_signal_emit (player, signals[INVALIDATE], 0, &priv->invalid_extents,
+ priv->invalidations->data, priv->invalidations->len);
+ swfdec_rectangle_init_empty (&priv->invalid_extents);
+ g_array_set_size (priv->invalidations, 0);
+ }
+
+ /* emit audio-added for all added audio streams */
+ for (walk = priv->audio; walk; walk = walk->next) {
+ SwfdecAudio *audio = walk->data;
+
+ if (audio->added)
+ continue;
+ g_signal_emit (player, signals[AUDIO_ADDED], 0, audio);
+ audio->added = TRUE;
+ }
+
+ /* emit missing-plugin signal for newly discovered plugins */
+ if (priv->missing_plugins) {
+ GSList *swalk;
+ guint i = 0, n_plugins = g_slist_length (priv->missing_plugins);
+ char **details = g_new (char *, n_plugins + 1);
+
+ for (swalk = priv->missing_plugins; swalk; swalk = swalk->next) {
+ details[i++] = swalk->data;
+ }
+ details[i] = NULL;
+ g_slist_free (priv->missing_plugins);
+ priv->missing_plugins = NULL;
+ SWFDEC_INFO ("emitting missing plugins signal for %u plugins", n_plugins);
+ g_signal_emit (player, signals[MISSING_PLUGINS], 0, details);
+ g_strfreev (details);
+ }
+}
+
void
swfdec_player_update_scale (SwfdecPlayer *player)
{
@@ -883,17 +925,14 @@ swfdec_player_update_scale (SwfdecPlayer *player)
if (cairo_matrix_invert (&priv->stage_to_global)) {
g_assert_not_reached ();
}
-#if 0
- /* FIXME: make this emit the signal at the right time */
- priv->invalid.x0 = 0;
- priv->invalid.y0 = 0;
- priv->invalid.x1 = priv->stage_width;
- priv->invalid.y1 = priv->stage_height;
-#endif
/* FIXME: notify textfields more gentle about the update */
+ /* FIXME: these events can cause invalidations in TextFields */
for (walk = priv->roots; walk; walk = walk->next) {
g_signal_emit_by_name (walk->data, "matrix-changed");
}
+ swfdec_player_invalidate (player, NULL);
+ if (!swfdec_player_is_locked (player))
+ swfdec_player_emit_signals (player);
}
static void
@@ -1386,48 +1425,6 @@ swfdec_player_do_mouse_release (SwfdecPlayer *player, guint button)
return TRUE;
}
-static void
-swfdec_player_emit_signals (SwfdecPlayer *player)
-{
- SwfdecPlayerPrivate *priv = player->priv;
- GList *walk;
-
- /* emit invalidate signal */
- if (!swfdec_rectangle_is_empty (&priv->invalid_extents)) {
- g_signal_emit (player, signals[INVALIDATE], 0, &priv->invalid_extents,
- priv->invalidations->data, priv->invalidations->len);
- swfdec_rectangle_init_empty (&priv->invalid_extents);
- g_array_set_size (priv->invalidations, 0);
- }
-
- /* emit audio-added for all added audio streams */
- for (walk = priv->audio; walk; walk = walk->next) {
- SwfdecAudio *audio = walk->data;
-
- if (audio->added)
- continue;
- g_signal_emit (player, signals[AUDIO_ADDED], 0, audio);
- audio->added = TRUE;
- }
-
- /* emit missing-plugin signal for newly discovered plugins */
- if (priv->missing_plugins) {
- GSList *swalk;
- guint i = 0, n_plugins = g_slist_length (priv->missing_plugins);
- char **details = g_new (char *, n_plugins + 1);
-
- for (swalk = priv->missing_plugins; swalk; swalk = swalk->next) {
- details[i++] = swalk->data;
- }
- details[i] = NULL;
- g_slist_free (priv->missing_plugins);
- priv->missing_plugins = NULL;
- SWFDEC_INFO ("emitting missing plugins signal for %u plugins", n_plugins);
- g_signal_emit (player, signals[MISSING_PLUGINS], 0, details);
- g_strfreev (details);
- }
-}
-
static int
swfdec_player_focus_sort (gconstpointer ca, gconstpointer cb)
{
@@ -1832,10 +1829,12 @@ void
swfdec_player_lock_soft (SwfdecPlayer *player)
{
g_return_if_fail (SWFDEC_IS_PLAYER (player));
+ g_assert (!swfdec_player_is_locked (player));
g_assert (swfdec_rectangle_is_empty (&player->priv->invalid_extents));
g_object_freeze_notify (G_OBJECT (player));
g_timer_start (player->priv->runtime);
+ player->priv->locked = TRUE;
SWFDEC_DEBUG ("LOCKED");
}
@@ -1843,6 +1842,7 @@ gboolean
swfdec_player_lock (SwfdecPlayer *player)
{
g_return_val_if_fail (SWFDEC_IS_PLAYER (player), FALSE);
+ g_assert (!swfdec_player_is_locked (player));
g_assert (swfdec_ring_buffer_get_n_elements (player->priv->actions[0]) == 0);
g_assert (swfdec_ring_buffer_get_n_elements (player->priv->actions[1]) == 0);
g_assert (swfdec_ring_buffer_get_n_elements (player->priv->actions[2]) == 0);
@@ -1945,6 +1945,7 @@ void
swfdec_player_unlock_soft (SwfdecPlayer *player)
{
g_return_if_fail (SWFDEC_IS_PLAYER (player));
+ g_assert (swfdec_player_is_locked (player));
SWFDEC_DEBUG ("UNLOCK");
g_timer_stop (player->priv->runtime);
@@ -1953,6 +1954,7 @@ swfdec_player_unlock_soft (SwfdecPlayer *player)
swfdec_player_update_focusrect (player);
g_object_thaw_notify (G_OBJECT (player));
swfdec_player_emit_signals (player);
+ player->priv->locked = FALSE;
}
void
@@ -2309,6 +2311,10 @@ swfdec_player_init (SwfdecPlayer *player)
priv->stage_width = -1;
priv->stage_height = -1;
priv->has_focus = TRUE;
+
+ cairo_matrix_init_scale (&priv->stage_to_global,
+ SWFDEC_TWIPS_SCALE_FACTOR, SWFDEC_TWIPS_SCALE_FACTOR);
+ priv->global_to_stage = priv->stage_to_global;
}
void
diff --git a/swfdec/swfdec_player_internal.h b/swfdec/swfdec_player_internal.h
index 5e354bf..4fe3dc4 100644
--- a/swfdec/swfdec_player_internal.h
+++ b/swfdec/swfdec_player_internal.h
@@ -62,6 +62,7 @@ struct _SwfdecPlayerPrivate
{
SwfdecPlayer * player; /* backlink */
+ gboolean locked; /* guard around swfdec_player_(un)lock */
/* global properties */
SwfdecSystem * system; /* our system properties */
gboolean initialized; /* if width and height are set already */
@@ -165,6 +166,7 @@ gboolean swfdec_player_lock (SwfdecPlayer * player);
void swfdec_player_lock_soft (SwfdecPlayer * player);
void swfdec_player_unlock (SwfdecPlayer * player);
void swfdec_player_unlock_soft (SwfdecPlayer * player);
+#define swfdec_player_is_locked(player) ((player)->priv->locked)
void swfdec_player_perform_actions (SwfdecPlayer * player);
#define swfdec_player_root(player, data, mark_func) \
commit 38a8bfa0d9a6bb31842aa43793f97385e2841b86
Author: Benjamin Otte <otte at gnome.org>
Date: Thu May 8 11:23:23 2008 +0200
remove checks that aren't needed anymore now that we always have at least one block
diff --git a/swfdec/swfdec_text_layout.c b/swfdec/swfdec_text_layout.c
index 641cdc6..2f0cff8 100644
--- a/swfdec/swfdec_text_layout.c
+++ b/swfdec/swfdec_text_layout.c
@@ -589,9 +589,6 @@ swfdec_text_layout_get_height (SwfdecTextLayout *layout)
swfdec_text_layout_ensure (layout);
iter = g_sequence_iter_prev (g_sequence_get_end_iter (layout->blocks));
- if (g_sequence_iter_is_end (iter))
- return 0;
-
block = g_sequence_get (iter);
return block->rect.y + block->rect.height;
}
@@ -607,9 +604,6 @@ swfdec_text_layout_get_n_rows (SwfdecTextLayout *layout)
swfdec_text_layout_ensure (layout);
iter = g_sequence_iter_prev (g_sequence_get_end_iter (layout->blocks));
- if (g_sequence_iter_is_end (iter))
- return 0;
-
block = g_sequence_get (iter);
return block->row + pango_layout_get_line_count (block->layout);
}
commit b1df96692e074363d025e62e1d3edace00b64c7e
Author: Benjamin Otte <otte at gnome.org>
Date: Thu May 8 11:20:59 2008 +0200
rework how an empty layout is handled and implement get_width/height()
Empty layouts used to contain nothing. Now they contain a single block.
Also implement functions for querying the width and height of a layout.
diff --git a/swfdec/swfdec_text_layout.c b/swfdec/swfdec_text_layout.c
index fbc5fef..641cdc6 100644
--- a/swfdec/swfdec_text_layout.c
+++ b/swfdec/swfdec_text_layout.c
@@ -280,7 +280,7 @@ swfdec_text_layout_create_paragraph (SwfdecTextLayout *layout, PangoContext *con
// TODO: kerning, display
string = swfdec_text_buffer_get_text (layout->text);
- while (start != end) {
+ do {
iter = swfdec_text_buffer_get_iter (layout->text, start);
attr = swfdec_text_buffer_iter_get_attributes (layout->text, iter);
new_block = end;
@@ -365,7 +365,7 @@ swfdec_text_layout_create_paragraph (SwfdecTextLayout *layout, PangoContext *con
block->rect.height += pango_layout_get_spacing (block->layout) / PANGO_SCALE;
last = block;
- }
+ } while (start != end);
return last;
}
@@ -382,6 +382,7 @@ swfdec_text_layout_create (SwfdecTextLayout *layout)
context = pango_cairo_font_map_create_context (PANGO_CAIRO_FONT_MAP (map));
p = string = swfdec_text_buffer_get_text (layout->text);
+ //g_print ("=====>\n %s\n<======\n", string);
for (;;) {
end = strpbrk (p, "\r\n");
if (end == NULL) {
@@ -404,9 +405,6 @@ swfdec_text_layout_ensure (SwfdecTextLayout *layout)
if (!g_sequence_iter_is_end (g_sequence_get_begin_iter (layout->blocks)))
return;
- if (swfdec_text_buffer_get_length (layout->text) == 0)
- return;
-
swfdec_text_layout_create (layout);
}
@@ -433,6 +431,8 @@ swfdec_text_layout_dispose (GObject *object)
{
SwfdecTextLayout *layout = SWFDEC_TEXT_LAYOUT (object);
+ g_signal_handlers_disconnect_matched (layout->text,
+ G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, layout);
g_object_unref (layout->text);
layout->text = NULL;
g_sequence_free (layout->blocks);
@@ -470,6 +470,8 @@ swfdec_text_layout_new (SwfdecTextBuffer *buffer)
layout = g_object_new (SWFDEC_TYPE_TEXT_LAYOUT, NULL);
layout->text = g_object_ref (buffer);
+ g_signal_connect_swapped (buffer, "text-changed",
+ G_CALLBACK (swfdec_text_layout_invalidate), layout);
return layout;
}
@@ -483,8 +485,8 @@ swfdec_text_layout_set_wrap_width (SwfdecTextLayout *layout, int wrap_width)
if (layout->wrap_width == wrap_width)
return;
- swfdec_text_layout_invalidate (layout);
layout->wrap_width = wrap_width;
+ swfdec_text_layout_invalidate (layout);
}
int
@@ -511,8 +513,8 @@ swfdec_text_layout_set_password (SwfdecTextLayout *layout, gboolean password)
if (layout->password == password)
return;
- swfdec_text_layout_invalidate (layout);
layout->password = password;
+ swfdec_text_layout_invalidate (layout);
}
double
@@ -532,8 +534,66 @@ swfdec_text_layout_set_scale (SwfdecTextLayout *layout, double scale)
if (layout->scale == scale)
return;
- swfdec_text_layout_invalidate (layout);
layout->scale = scale;
+ swfdec_text_layout_invalidate (layout);
+}
+
+/**
+ * swfdec_text_layout_get_width:
+ * @layout: the layout
+ *
+ * Computes the width of the layout in pixels. Note that the width can still
+ * exceed the width set with swfdec_text_layout_set_wrap_width() if some
+ * words are too long. Computing the width takes a long time, so it might be
+ * useful to cache the value.
+ *
+ * Returns: The width in pixels
+ **/
+guint
+swfdec_text_layout_get_width (SwfdecTextLayout *layout)
+{
+ GSequenceIter *iter;
+ SwfdecTextBlock *block;
+ guint width = 0;
+
+ g_return_val_if_fail (SWFDEC_IS_TEXT_LAYOUT (layout), 0);
+
+ swfdec_text_layout_ensure (layout);
+
+ for (iter = g_sequence_get_begin_iter (layout->blocks);
+ !g_sequence_iter_is_end (iter);
+ iter = g_sequence_iter_next (iter)) {
+ block = g_sequence_get (iter);
+ width = MAX (width, (guint) block->rect.x + block->rect.width);
+ }
+
+ return width;
+}
+
+/**
+ * swfdec_text_layout_get_height:
+ * @layout: the layout
+ *
+ * Computes the height of the layout in pixels. This is a fast operation.
+ *
+ * Returns: The height of the layout in pixels
+ **/
+guint
+swfdec_text_layout_get_height (SwfdecTextLayout *layout)
+{
+ GSequenceIter *iter;
+ SwfdecTextBlock *block;
+
+ g_return_val_if_fail (SWFDEC_IS_TEXT_LAYOUT (layout), 0);
+
+ swfdec_text_layout_ensure (layout);
+
+ iter = g_sequence_iter_prev (g_sequence_get_end_iter (layout->blocks));
+ if (g_sequence_iter_is_end (iter))
+ return 0;
+
+ block = g_sequence_get (iter);
+ return block->rect.y + block->rect.height;
}
guint
diff --git a/swfdec/swfdec_text_layout.h b/swfdec/swfdec_text_layout.h
index fe75923..0457901 100644
--- a/swfdec/swfdec_text_layout.h
+++ b/swfdec/swfdec_text_layout.h
@@ -69,6 +69,8 @@ gboolean swfdec_text_layout_get_password (SwfdecTextLayout * layout);
void swfdec_text_layout_set_scale (SwfdecTextLayout * layout,
double scale);
double swfdec_text_layout_get_scale (SwfdecTextLayout * layout);
+guint swfdec_text_layout_get_width (SwfdecTextLayout * layout);
+guint swfdec_text_layout_get_height (SwfdecTextLayout * layout);
guint swfdec_text_layout_get_n_rows (SwfdecTextLayout * layout);
void swfdec_text_layout_render (SwfdecTextLayout * layout,
commit 54a4ae2a24e30e934dd5e13bc559ba1294b5bc44
Author: Benjamin Otte <otte at gnome.org>
Date: Wed May 7 21:46:11 2008 +0200
add a simple word wrapping test
diff --git a/test/image/Makefile.am b/test/image/Makefile.am
index 1b6f0a6..7455a0b 100644
--- a/test/image/Makefile.am
+++ b/test/image/Makefile.am
@@ -426,6 +426,14 @@ EXTRA_DIST = \
text-field-scale-parents-7.swf.png \
text-field-scale-parents-8.swf \
text-field-scale-parents-8.swf.png \
- text-field-scale-parents.as
-
+ text-field-scale-parents.as \
+ text-field-wordWrap-5.swf \
+ text-field-wordWrap-5.swf.png \
+ text-field-wordWrap-6.swf \
+ text-field-wordWrap-6.swf.png \
+ text-field-wordWrap-7.swf \
+ text-field-wordWrap-7.swf.png \
+ text-field-wordWrap-8.swf \
+ text-field-wordWrap-8.swf.png \
+ text-field-wordWrap.as
diff --git a/test/image/text-field-wordWrap-5.swf b/test/image/text-field-wordWrap-5.swf
new file mode 100644
index 0000000..ed7fe23
Binary files /dev/null and b/test/image/text-field-wordWrap-5.swf differ
diff --git a/test/image/text-field-wordWrap-5.swf.png b/test/image/text-field-wordWrap-5.swf.png
new file mode 100644
index 0000000..a1d8f66
Binary files /dev/null and b/test/image/text-field-wordWrap-5.swf.png differ
diff --git a/test/image/text-field-wordWrap-6.swf b/test/image/text-field-wordWrap-6.swf
new file mode 100644
index 0000000..40308dd
Binary files /dev/null and b/test/image/text-field-wordWrap-6.swf differ
diff --git a/test/image/text-field-wordWrap-6.swf.png b/test/image/text-field-wordWrap-6.swf.png
new file mode 100644
index 0000000..3803380
Binary files /dev/null and b/test/image/text-field-wordWrap-6.swf.png differ
diff --git a/test/image/text-field-wordWrap-7.swf b/test/image/text-field-wordWrap-7.swf
new file mode 100644
index 0000000..db714b8
Binary files /dev/null and b/test/image/text-field-wordWrap-7.swf differ
diff --git a/test/image/text-field-wordWrap-7.swf.png b/test/image/text-field-wordWrap-7.swf.png
new file mode 100644
index 0000000..22033c9
Binary files /dev/null and b/test/image/text-field-wordWrap-7.swf.png differ
diff --git a/test/image/text-field-wordWrap-8.swf b/test/image/text-field-wordWrap-8.swf
new file mode 100644
index 0000000..50b9b44
Binary files /dev/null and b/test/image/text-field-wordWrap-8.swf differ
diff --git a/test/image/text-field-wordWrap-8.swf.png b/test/image/text-field-wordWrap-8.swf.png
new file mode 100644
index 0000000..43b09b6
Binary files /dev/null and b/test/image/text-field-wordWrap-8.swf.png differ
diff --git a/test/image/text-field-wordWrap.as b/test/image/text-field-wordWrap.as
new file mode 100644
index 0000000..7fd4e82
--- /dev/null
+++ b/test/image/text-field-wordWrap.as
@@ -0,0 +1,24 @@
+// makeswf -v 7 -s 200x150 -r 1 -o text-field-wordWrap.swf text-field-wordWrap.as
+
+function create (depth, x, y) {
+ var t = createTextField ("t" + depth, depth, x, y, 50, 40);
+ var t = this["t" + depth];
+ t.border = true;
+ var tf = new TextFormat ();
+ tf.font = "Bitstream Vera Sans";
+ //tf.leading = -5;
+ t.setNewTextFormat (tf);
+ t.text = "Hello,\nfinest World";
+};
+
+create (0, 25, 25);
+create (1, 100.5, 25);
+t1.wordWrap = true;
+create (2, 25, 75);
+t2._y += 0.4;
+t2.multiline = true;
+create (3, 100.5, 75);
+t3._y += 0.5;
+t3.wordWrap = true;
+t3.multiline = true;
+
commit d5199295685e2f10d2bd4d80c6c68b8b14e585f2
Author: Benjamin Otte <otte at gnome.org>
Date: Wed May 7 21:40:16 2008 +0200
implement word wrap
diff --git a/swfdec/swfdec_text_field_movie.c b/swfdec/swfdec_text_field_movie.c
index 8e2d773..8c60cf3 100644
--- a/swfdec/swfdec_text_field_movie.c
+++ b/swfdec/swfdec_text_field_movie.c
@@ -357,6 +357,10 @@ swfdec_text_field_movie_update_area (SwfdecTextFieldMovie *text)
text->stage_rect.width = round (x) - text->stage_rect.x;
text->stage_rect.height = round (y) - text->stage_rect.y;
swfdec_text_layout_set_scale (text->layout, matrix.yy * SWFDEC_TWIPS_SCALE_FACTOR);
+ if (text->word_wrap) {
+ swfdec_text_layout_set_wrap_width (text->layout, text->stage_rect.width -
+ BORDER_LEFT - BORDER_RIGHT);
+ }
}
static void
diff --git a/swfdec/swfdec_text_field_movie_as.c b/swfdec/swfdec_text_field_movie_as.c
index 2988d90..05a1d5b 100644
--- a/swfdec/swfdec_text_field_movie_as.c
+++ b/swfdec/swfdec_text_field_movie_as.c
@@ -829,6 +829,12 @@ swfdec_text_field_movie_set_wordWrap (SwfdecAsContext *cx,
if (text->word_wrap != value) {
text->word_wrap = value;
+ if (text->word_wrap) {
+ /* FIXME: find a proper way to use BORDER_LEFT and BORDER_RIGHT here */
+ swfdec_text_layout_set_wrap_width (text->layout, text->stage_rect.width - 4);
+ } else {
+ swfdec_text_layout_set_wrap_width (text->layout, -1);
+ }
swfdec_movie_invalidate_last (SWFDEC_MOVIE (text));
swfdec_text_field_movie_auto_size (text);
// special case: don't set scrolling
commit 9e92e2bb2f4259e0e05ce8545e862c7e1be8f2e3
Author: Benjamin Otte <otte at gnome.org>
Date: Wed May 7 21:40:01 2008 +0200
clip the right region when rendering
diff --git a/swfdec/swfdec_text_field_movie.c b/swfdec/swfdec_text_field_movie.c
index 5f0e044..8e2d773 100644
--- a/swfdec/swfdec_text_field_movie.c
+++ b/swfdec/swfdec_text_field_movie.c
@@ -126,9 +126,11 @@ swfdec_text_field_movie_render (SwfdecMovie *movie, cairo_t *cr,
if (swfdec_text_buffer_get_length (text->text) == 0)
return;
/* render the layout */
- cairo_rectangle (cr, text->stage_rect.x, text->stage_rect.y, text->stage_rect.width, text->stage_rect.height);
- cairo_clip (cr);
cairo_translate (cr, text->stage_rect.x + BORDER_LEFT, text->stage_rect.y + BORDER_TOP);
+ cairo_rectangle (cr, 0, 0,
+ text->stage_rect.width - BORDER_LEFT - BORDER_RIGHT,
+ text->stage_rect.height - BORDER_TOP - BORDER_BOTTOM);
+ cairo_clip (cr);
swfdec_text_layout_render (text->layout, cr, ctrans,
0, text->stage_rect.height - BORDER_TOP + BORDER_BOTTOM, &text->stage_rect);
}
commit b95ac67f62d415b7bfce56ebefccc9fd98fc9b5f
Author: Benjamin Otte <otte at gnome.org>
Date: Wed May 7 21:17:07 2008 +0200
scale the width correctly
diff --git a/swfdec/swfdec_text_layout.c b/swfdec/swfdec_text_layout.c
index 334cc4d..fbc5fef 100644
--- a/swfdec/swfdec_text_layout.c
+++ b/swfdec/swfdec_text_layout.c
@@ -316,7 +316,7 @@ swfdec_text_layout_create_paragraph (SwfdecTextLayout *layout, PangoContext *con
}
swfdec_text_layout_apply_line_attributes (block, attr);
if (layout->wrap_width != -1)
- pango_layout_set_width (block->layout, block->rect.width);
+ pango_layout_set_width (block->layout, block->rect.width * PANGO_SCALE);
iter = swfdec_text_buffer_get_iter (layout->text, start);
attr = swfdec_text_buffer_iter_get_attributes (layout->text, iter);
commit a1cb51dd160224793d75841b479dbf1082230b0a
Author: Benjamin Otte <otte at gnome.org>
Date: Wed May 7 21:05:34 2008 +0200
use scaling
and get rid of all debugging prints
diff --git a/swfdec/swfdec_text_field_movie.c b/swfdec/swfdec_text_field_movie.c
index 9c6c639..5f0e044 100644
--- a/swfdec/swfdec_text_field_movie.c
+++ b/swfdec/swfdec_text_field_movie.c
@@ -92,9 +92,6 @@ swfdec_text_field_movie_render (SwfdecMovie *movie, cairo_t *cr,
SwfdecTextFieldMovie *text = SWFDEC_TEXT_FIELD_MOVIE (movie);
SwfdecColor color;
- g_print ("render %d %d %d %d\n",
- text->stage_rect.x, text->stage_rect.y,
- text->stage_rect.width, text->stage_rect.height);
/* textfields don't mask */
if (swfdec_color_transform_is_mask (ctrans) ||
swfdec_rectangle_is_empty (&text->stage_rect))
@@ -333,7 +330,6 @@ swfdec_text_field_movie_update_area (SwfdecTextFieldMovie *text)
swfdec_movie_local_to_global_matrix (movie, &matrix);
cairo_matrix_multiply (&matrix, &matrix,
&SWFDEC_PLAYER (SWFDEC_AS_OBJECT (movie)->context)->priv->global_to_stage);
- g_print ("%g %g %g %g\n", matrix.xx, matrix.yx, matrix.xy, matrix.yy);
if (matrix.xy != 0.0 || matrix.yx != 0.0 ||
matrix.xx <= 0.0 || matrix.yy <= 0.0) {
swfdec_rectangle_init_empty (&text->stage_rect);
@@ -343,9 +339,7 @@ swfdec_text_field_movie_update_area (SwfdecTextFieldMovie *text)
translate = matrix;
x = text->extents.x0;
y = text->extents.y0;
- g_print ("%g %g\n", x, y);
cairo_matrix_transform_point (&matrix, &x, &y);
- g_print ("%g %g\n", x, y);
cairo_matrix_init_translate (&translate, round (x) - x, round (y) - y);
cairo_matrix_multiply (&matrix, &matrix, &translate);
@@ -360,9 +354,7 @@ swfdec_text_field_movie_update_area (SwfdecTextFieldMovie *text)
/* FIXME: floor, ceil or round? */
text->stage_rect.width = round (x) - text->stage_rect.x;
text->stage_rect.height = round (y) - text->stage_rect.y;
- g_print ("%d %d %d %d\n",
- text->stage_rect.x, text->stage_rect.y,
- text->stage_rect.width, text->stage_rect.height);
+ swfdec_text_layout_set_scale (text->layout, matrix.yy * SWFDEC_TWIPS_SCALE_FACTOR);
}
static void
commit b6a9681de023c6b87496512eb10851d3ae2e3b32
Author: Benjamin Otte <otte at gnome.org>
Date: Wed May 7 21:04:16 2008 +0200
implement scaling the layout
diff --git a/swfdec/swfdec_text_layout.c b/swfdec/swfdec_text_layout.c
index 37683fe..334cc4d 100644
--- a/swfdec/swfdec_text_layout.c
+++ b/swfdec/swfdec_text_layout.c
@@ -40,44 +40,46 @@ enum {
static guint signals[LAST_SIGNAL] = { 0, };
static PangoAttribute *
-swfdec_text_attribute_create_bold (const SwfdecTextAttributes *attr)
+swfdec_text_attribute_create_bold (SwfdecTextLayout *layout, const SwfdecTextAttributes *attr)
{
return pango_attr_weight_new (attr->bold ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL);
}
static PangoAttribute *
-swfdec_text_attribute_create_color (const SwfdecTextAttributes *attr)
+swfdec_text_attribute_create_color (SwfdecTextLayout *layout, const SwfdecTextAttributes *attr)
{
return pango_attr_foreground_new (SWFDEC_COLOR_R (attr->color) * 255,
SWFDEC_COLOR_G (attr->color) * 255, SWFDEC_COLOR_B (attr->color) * 255);
}
static PangoAttribute *
-swfdec_text_attribute_create_font (const SwfdecTextAttributes *attr)
+swfdec_text_attribute_create_font (SwfdecTextLayout *layout, const SwfdecTextAttributes *attr)
{
return pango_attr_family_new (attr->font);
}
static PangoAttribute *
-swfdec_text_attribute_create_italic (const SwfdecTextAttributes *attr)
+swfdec_text_attribute_create_italic (SwfdecTextLayout *layout, const SwfdecTextAttributes *attr)
{
return pango_attr_style_new (attr->italic ? PANGO_STYLE_ITALIC : PANGO_STYLE_NORMAL);
}
static PangoAttribute *
-swfdec_text_attribute_create_letter_spacing (const SwfdecTextAttributes *attr)
+swfdec_text_attribute_create_letter_spacing (SwfdecTextLayout *layout, const SwfdecTextAttributes *attr)
{
return pango_attr_letter_spacing_new (attr->letter_spacing * PANGO_SCALE);
}
static PangoAttribute *
-swfdec_text_attribute_create_size (const SwfdecTextAttributes *attr)
+swfdec_text_attribute_create_size (SwfdecTextLayout *layout, const SwfdecTextAttributes *attr)
{
- return pango_attr_size_new_absolute (MAX (attr->size, 1) * PANGO_SCALE);
+ guint size = attr->size * layout->scale;
+ size = MAX (size, 1);
+ return pango_attr_size_new_absolute (size * PANGO_SCALE);
}
static PangoAttribute *
-swfdec_text_attribute_create_underline (const SwfdecTextAttributes *attr)
+swfdec_text_attribute_create_underline (SwfdecTextLayout *layout, const SwfdecTextAttributes *attr)
{
return pango_attr_underline_new (attr->underline ? PANGO_UNDERLINE_SINGLE : PANGO_UNDERLINE_NONE);
}
@@ -93,7 +95,7 @@ typedef enum {
struct {
FormatApplication application;
- PangoAttribute * (* create_attribute) (const SwfdecTextAttributes *attr);
+ PangoAttribute * (* create_attribute) (SwfdecTextLayout *layout, const SwfdecTextAttributes *attr);
} format_table[] = {
/* unknown or unhandled properties */
[SWFDEC_TEXT_ATTRIBUTE_DISPLAY] = { FORMAT_APPLY_UNKNOWN, NULL },
@@ -248,15 +250,15 @@ swfdec_text_layout_apply_line_attributes (SwfdecTextBlock *block,
}
static void
-swfdec_text_layout_apply_attributes (PangoAttrList *list, const SwfdecTextAttributes *attr,
- guint start, guint end)
+swfdec_text_layout_apply_attributes (SwfdecTextLayout *layout, PangoAttrList *list,
+ const SwfdecTextAttributes *attr, guint start, guint end)
{
PangoAttribute *attribute;
guint i;
for (i = 0; i < G_N_ELEMENTS (format_table); i++) {
if (format_table[i].create_attribute) {
- attribute = format_table[i].create_attribute (attr);
+ attribute = format_table[i].create_attribute (layout, attr);
attribute->start_index = start;
attribute->end_index = end;
pango_attr_list_change (list, attribute);
@@ -328,7 +330,7 @@ swfdec_text_layout_create_paragraph (SwfdecTextLayout *layout, PangoContext *con
swfdec_text_buffer_get_length (layout->text);
start_next = MIN (start_next, end);
- swfdec_text_layout_apply_attributes (list, attr, start - block->start, start_next - block->start);
+ swfdec_text_layout_apply_attributes (layout, list, attr, start - block->start, start_next - block->start);
if (attr_next && new_block > start_next &&
(swfdec_text_attributes_diff (attr, attr_next) & SWFDEC_TEXT_ATTRIBUTES_MASK_NEW_BLOCK))
@@ -411,6 +413,9 @@ swfdec_text_layout_ensure (SwfdecTextLayout *layout)
static void
swfdec_text_layout_invalidate (SwfdecTextLayout *layout)
{
+ if (g_sequence_iter_is_end (g_sequence_get_begin_iter (layout->blocks)))
+ return;
+
g_sequence_remove_range (g_sequence_get_begin_iter (layout->blocks),
g_sequence_get_end_iter (layout->blocks));
g_signal_emit (layout, signals[CHANGED], 0);
@@ -452,6 +457,7 @@ static void
swfdec_text_layout_init (SwfdecTextLayout *layout)
{
layout->wrap_width = -1;
+ layout->scale = 1.0;
layout->blocks = g_sequence_new (swfdec_text_block_free);
}
@@ -489,6 +495,14 @@ swfdec_text_layout_get_wrap_width (SwfdecTextLayout *layout)
return layout->wrap_width;
}
+gboolean
+swfdec_text_layout_get_password (SwfdecTextLayout *layout)
+{
+ g_return_val_if_fail (SWFDEC_IS_TEXT_LAYOUT (layout), FALSE);
+
+ return layout->password;
+}
+
void
swfdec_text_layout_set_password (SwfdecTextLayout *layout, gboolean password)
{
@@ -501,6 +515,27 @@ swfdec_text_layout_set_password (SwfdecTextLayout *layout, gboolean password)
layout->password = password;
}
+double
+swfdec_text_layout_get_scale (SwfdecTextLayout *layout)
+{
+ g_return_val_if_fail (SWFDEC_IS_TEXT_LAYOUT (layout), 1.0);
+
+ return layout->scale;
+}
+
+void
+swfdec_text_layout_set_scale (SwfdecTextLayout *layout, double scale)
+{
+ g_return_if_fail (SWFDEC_IS_TEXT_LAYOUT (layout));
+ g_return_if_fail (scale > 0);
+
+ if (layout->scale == scale)
+ return;
+
+ swfdec_text_layout_invalidate (layout);
+ layout->scale = scale;
+}
+
guint
swfdec_text_layout_get_n_rows (SwfdecTextLayout *layout)
{
@@ -519,14 +554,6 @@ swfdec_text_layout_get_n_rows (SwfdecTextLayout *layout)
return block->row + pango_layout_get_line_count (block->layout);
}
-gboolean
-swfdec_text_layout_get_password (SwfdecTextLayout *layout)
-{
- g_return_val_if_fail (SWFDEC_IS_TEXT_LAYOUT (layout), FALSE);
-
- return layout->password;
-}
-
static GSequenceIter *
swfdec_text_layout_find_row (SwfdecTextLayout *layout, guint row)
{
diff --git a/swfdec/swfdec_text_layout.h b/swfdec/swfdec_text_layout.h
index cd68999..fe75923 100644
--- a/swfdec/swfdec_text_layout.h
+++ b/swfdec/swfdec_text_layout.h
@@ -41,10 +41,11 @@ struct _SwfdecTextLayout
{
GObject object;
- /* constant data */
SwfdecTextBuffer * text; /* the text we render */
+ /* properties */
int wrap_width; /* maximum width to use */
gboolean password; /* TRUE if the text should be displayed as asterisks */
+ double scale; /* scale factor in use */
/* layout data */
GSequence * blocks; /* ordered list of blocks */
@@ -65,6 +66,9 @@ int swfdec_text_layout_get_wrap_width (SwfdecTextLayout * layout);
void swfdec_text_layout_set_password (SwfdecTextLayout * layout,
gboolean password);
gboolean swfdec_text_layout_get_password (SwfdecTextLayout * layout);
+void swfdec_text_layout_set_scale (SwfdecTextLayout * layout,
+ double scale);
+double swfdec_text_layout_get_scale (SwfdecTextLayout * layout);
guint swfdec_text_layout_get_n_rows (SwfdecTextLayout * layout);
void swfdec_text_layout_render (SwfdecTextLayout * layout,
commit 4f6a2d744c9b6ab4a3c7fb07be9180dc3fd97223
Author: Benjamin Otte <otte at gnome.org>
Date: Wed May 7 18:43:41 2008 +0200
add a test that enusres negaitve scaling causes TextFields to not be scaled
diff --git a/test/image/Makefile.am b/test/image/Makefile.am
index 599bad7..1b6f0a6 100644
--- a/test/image/Makefile.am
+++ b/test/image/Makefile.am
@@ -409,6 +409,15 @@ EXTRA_DIST = \
text-field-empty-7.swf.png \
text-field-empty-8.swf \
text-field-empty-8.swf.png \
+ text-field-scale-negative-5.swf \
+ text-field-scale-negative-5.swf.png \
+ text-field-scale-negative-6.swf \
+ text-field-scale-negative-6.swf.png \
+ text-field-scale-negative-7.swf \
+ text-field-scale-negative-7.swf.png \
+ text-field-scale-negative-8.swf \
+ text-field-scale-negative-8.swf.png \
+ text-field-scale-negative.as \
text-field-scale-parents-5.swf \
text-field-scale-parents-5.swf.png \
text-field-scale-parents-6.swf \
diff --git a/test/image/text-field-scale-negative-5.swf b/test/image/text-field-scale-negative-5.swf
new file mode 100644
index 0000000..0df8aaf
Binary files /dev/null and b/test/image/text-field-scale-negative-5.swf differ
diff --git a/test/image/text-field-scale-negative-5.swf.png b/test/image/text-field-scale-negative-5.swf.png
new file mode 100644
index 0000000..916bba0
Binary files /dev/null and b/test/image/text-field-scale-negative-5.swf.png differ
diff --git a/test/image/text-field-scale-negative-6.swf b/test/image/text-field-scale-negative-6.swf
new file mode 100644
index 0000000..c881d62
Binary files /dev/null and b/test/image/text-field-scale-negative-6.swf differ
diff --git a/test/image/text-field-scale-negative-6.swf.png b/test/image/text-field-scale-negative-6.swf.png
new file mode 100644
index 0000000..b0845e4
Binary files /dev/null and b/test/image/text-field-scale-negative-6.swf.png differ
diff --git a/test/image/text-field-scale-negative-7.swf b/test/image/text-field-scale-negative-7.swf
new file mode 100644
index 0000000..a7a7d0a
Binary files /dev/null and b/test/image/text-field-scale-negative-7.swf differ
diff --git a/test/image/text-field-scale-negative-7.swf.png b/test/image/text-field-scale-negative-7.swf.png
new file mode 100644
index 0000000..fb13c45
Binary files /dev/null and b/test/image/text-field-scale-negative-7.swf.png differ
diff --git a/test/image/text-field-scale-negative-8.swf b/test/image/text-field-scale-negative-8.swf
new file mode 100644
index 0000000..c162cb5
Binary files /dev/null and b/test/image/text-field-scale-negative-8.swf differ
diff --git a/test/image/text-field-scale-negative-8.swf.png b/test/image/text-field-scale-negative-8.swf.png
new file mode 100644
index 0000000..12df204
Binary files /dev/null and b/test/image/text-field-scale-negative-8.swf.png differ
diff --git a/test/image/text-field-scale-negative.as b/test/image/text-field-scale-negative.as
new file mode 100644
index 0000000..08037d4
--- /dev/null
+++ b/test/image/text-field-scale-negative.as
@@ -0,0 +1,22 @@
+// makeswf -v 7 -s 200x150 -r 1 -o text-field-scale-negative.swf text-field-scale-negative.as
+
+function create (depth, x, y) {
+ var t = createTextField ("t" + depth, depth, x, y, 50, 40);
+ var t = this["t" + depth];
+ t.background = true;
+ t.backgroundColor = 0xFF;
+};
+
+create (0, 25, 25);
+create (1, 100.5, 25);
+t1._xscale = -100;
+t1._x += 50;
+create (2, 25, 75.4);
+t2._yscale = -100;
+t2._y += 40;
+create (3, 100.5, 75.5);
+t3._xscale = -100;
+t3._x += 50;
+t3._yscale = -100;
+t3._y += 40;
+
commit b071374a9ae70e3faf7d2b20aa41b22b5d717a00
Author: Benjamin Otte <otte at gnome.org>
Date: Wed May 7 18:29:26 2008 +0200
add test to check if scaling works
diff --git a/test/image/Makefile.am b/test/image/Makefile.am
index 375d9d7..599bad7 100644
--- a/test/image/Makefile.am
+++ b/test/image/Makefile.am
@@ -408,5 +408,15 @@ EXTRA_DIST = \
text-field-empty-7.swf \
text-field-empty-7.swf.png \
text-field-empty-8.swf \
- text-field-empty-8.swf.png
+ text-field-empty-8.swf.png \
+ text-field-scale-parents-5.swf \
+ text-field-scale-parents-5.swf.png \
+ text-field-scale-parents-6.swf \
+ text-field-scale-parents-6.swf.png \
+ text-field-scale-parents-7.swf \
+ text-field-scale-parents-7.swf.png \
+ text-field-scale-parents-8.swf \
+ text-field-scale-parents-8.swf.png \
+ text-field-scale-parents.as
+
diff --git a/test/image/text-field-scale-parents-5.swf b/test/image/text-field-scale-parents-5.swf
new file mode 100644
index 0000000..92e5382
Binary files /dev/null and b/test/image/text-field-scale-parents-5.swf differ
diff --git a/test/image/text-field-scale-parents-5.swf.png b/test/image/text-field-scale-parents-5.swf.png
new file mode 100644
index 0000000..5f3499f
Binary files /dev/null and b/test/image/text-field-scale-parents-5.swf.png differ
diff --git a/test/image/text-field-scale-parents-6.swf b/test/image/text-field-scale-parents-6.swf
new file mode 100644
index 0000000..a8f5453
Binary files /dev/null and b/test/image/text-field-scale-parents-6.swf differ
diff --git a/test/image/text-field-scale-parents-6.swf.png b/test/image/text-field-scale-parents-6.swf.png
new file mode 100644
index 0000000..e6c7482
Binary files /dev/null and b/test/image/text-field-scale-parents-6.swf.png differ
diff --git a/test/image/text-field-scale-parents-7.swf b/test/image/text-field-scale-parents-7.swf
new file mode 100644
index 0000000..4b2368e
Binary files /dev/null and b/test/image/text-field-scale-parents-7.swf differ
diff --git a/test/image/text-field-scale-parents-7.swf.png b/test/image/text-field-scale-parents-7.swf.png
new file mode 100644
index 0000000..fe8aaff
Binary files /dev/null and b/test/image/text-field-scale-parents-7.swf.png differ
diff --git a/test/image/text-field-scale-parents-8.swf b/test/image/text-field-scale-parents-8.swf
new file mode 100644
index 0000000..3c3bd8b
Binary files /dev/null and b/test/image/text-field-scale-parents-8.swf differ
diff --git a/test/image/text-field-scale-parents-8.swf.png b/test/image/text-field-scale-parents-8.swf.png
new file mode 100644
index 0000000..d2657e0
Binary files /dev/null and b/test/image/text-field-scale-parents-8.swf.png differ
diff --git a/test/image/text-field-scale-parents.as b/test/image/text-field-scale-parents.as
new file mode 100644
index 0000000..c86d3d0
--- /dev/null
+++ b/test/image/text-field-scale-parents.as
@@ -0,0 +1,14 @@
+// makeswf -v 7 -s 200x150 -r 1 -o text-field-scale-parents.swf text-field-scale-parents.as
+
+createEmptyMovieClip ("a", 0);
+a._xscale = -100;
+a.createEmptyMovieClip ("a", 0);
+a.a._xscale = -100;
+a.a.createTextField ("t", 0, 0, 0, 50, 40);
+a.a.t.background = true;
+a.a.t.backgroundColor = 0xFF;
+
+a.createTextField ("t", 1, -100, 0, 50, 40);
+a.t._xscale = -200;
+a.t.background = true;
+a.t.backgroundColor = 0xFF00;
commit bd86e710d3721fb03cb35020e0d171dcf3cca0fa
Author: Benjamin Otte <otte at gnome.org>
Date: Wed May 7 18:27:05 2008 +0200
fixes to computing the stage_rect correctly
diff --git a/swfdec/swfdec_text_field_movie.c b/swfdec/swfdec_text_field_movie.c
index 356c153..9c6c639 100644
--- a/swfdec/swfdec_text_field_movie.c
+++ b/swfdec/swfdec_text_field_movie.c
@@ -333,6 +333,7 @@ swfdec_text_field_movie_update_area (SwfdecTextFieldMovie *text)
swfdec_movie_local_to_global_matrix (movie, &matrix);
cairo_matrix_multiply (&matrix, &matrix,
&SWFDEC_PLAYER (SWFDEC_AS_OBJECT (movie)->context)->priv->global_to_stage);
+ g_print ("%g %g %g %g\n", matrix.xx, matrix.yx, matrix.xy, matrix.yy);
if (matrix.xy != 0.0 || matrix.yx != 0.0 ||
matrix.xx <= 0.0 || matrix.yy <= 0.0) {
swfdec_rectangle_init_empty (&text->stage_rect);
@@ -340,21 +341,21 @@ swfdec_text_field_movie_update_area (SwfdecTextFieldMovie *text)
}
translate = matrix;
- x = movie->original_extents.x0;
- y = movie->original_extents.y0;
+ x = text->extents.x0;
+ y = text->extents.y0;
g_print ("%g %g\n", x, y);
cairo_matrix_transform_point (&matrix, &x, &y);
g_print ("%g %g\n", x, y);
cairo_matrix_init_translate (&translate, round (x) - x, round (y) - y);
cairo_matrix_multiply (&matrix, &matrix, &translate);
- x = movie->original_extents.x0;
- y = movie->original_extents.y0;
+ x = text->extents.x0;
+ y = text->extents.y0;
cairo_matrix_transform_point (&matrix, &x, &y);
text->stage_rect.x = x;
text->stage_rect.y = y;
- x = movie->original_extents.x1;
- y = movie->original_extents.y1;
+ x = text->extents.x1;
+ y = text->extents.y1;
cairo_matrix_transform_point (&matrix, &x, &y);
/* FIXME: floor, ceil or round? */
text->stage_rect.width = round (x) - text->stage_rect.x;
@@ -433,6 +434,7 @@ swfdec_text_field_movie_init_movie (SwfdecMovie *movie)
G_CALLBACK (swfdec_text_field_movie_update_area), movie);
parent = parent->parent;
}
+ swfdec_text_field_movie_update_area (text);
}
static void
commit 57207ab58d9f06cf00ab7f422a09c880acbef45d
Author: Benjamin Otte <otte at gnome.org>
Date: Wed May 7 18:08:03 2008 +0200
rework the text field rendering, part 1
Nothing works atm, but I thought I get this in before I lose it.
The big change is using a SwfdecTextLayout object that renders in native
coordinates and making SwfdecTextFieldMovie the translation for it.
diff --git a/swfdec/Makefile.am b/swfdec/Makefile.am
index c91612f..4808c72 100644
--- a/swfdec/Makefile.am
+++ b/swfdec/Makefile.am
@@ -153,6 +153,7 @@ libswfdec_source_files = \
swfdec_text_field_movie_as.c \
swfdec_text_field_movie_html.c \
swfdec_text_format.c \
+ swfdec_text_layout.c \
swfdec_text_renderer.c \
swfdec_text_snapshot.c \
swfdec_transform.c \
@@ -298,6 +299,7 @@ noinst_HEADERS = \
swfdec_text_attributes.h \
swfdec_text_buffer.h \
swfdec_text_format.h \
+ swfdec_text_layout.h \
swfdec_types.h \
swfdec_utils.h \
swfdec_video.h \
diff --git a/swfdec/swfdec_actor.h b/swfdec/swfdec_actor.h
index 5c30bfd..c299769 100644
--- a/swfdec/swfdec_actor.h
+++ b/swfdec/swfdec_actor.h
@@ -43,12 +43,16 @@ struct _SwfdecActor
SwfdecEventList * events; /* events queued on this movie */
SwfdecFlashBool focusrect; /* if we should draw a focus rectangle or not */
+ guint needs_matrix; /* number of movies contained that need matrix updates */
};
struct _SwfdecActorClass
{
SwfdecMovieClass movie_class;
+ /* matrix updates go here */
+ void (* update_matrix) (SwfdecActor * actor);
+
/* iterating */
void (* iterate_start) (SwfdecActor * actor);
gboolean (* iterate_end) (SwfdecActor * actor);
diff --git a/swfdec/swfdec_movie.c b/swfdec/swfdec_movie.c
index 48a27d7..e4d1ed4 100644
--- a/swfdec/swfdec_movie.c
+++ b/swfdec/swfdec_movie.c
@@ -55,6 +55,13 @@ enum {
PROP_DEPTH
};
+enum {
+ MATRIX_CHANGED,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0, };
+
G_DEFINE_ABSTRACT_TYPE (SwfdecMovie, swfdec_movie, SWFDEC_TYPE_AS_OBJECT)
static void
@@ -248,6 +255,8 @@ swfdec_movie_end_update_matrix (SwfdecMovie *movie)
cairo_matrix_rotate (&movie->matrix, d * G_PI / 180);
}
swfdec_matrix_ensure_invertible (&movie->matrix, &movie->inverse_matrix);
+
+ g_signal_emit (movie, signals[MATRIX_CHANGED], 0);
}
static void
@@ -1288,6 +1297,10 @@ swfdec_movie_class_init (SwfdecMovieClass * movie_class)
asobject_class->foreach = swfdec_movie_foreach_variable;
asobject_class->debug = swfdec_movie_get_debug;
+ signals[MATRIX_CHANGED] = g_signal_new ("matrix-changed", G_TYPE_FROM_CLASS (movie_class),
+ G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
g_object_class_install_property (object_class, PROP_DEPTH,
g_param_spec_int ("depth", "depth", "z order inside the parent",
G_MININT, G_MAXINT, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
diff --git a/swfdec/swfdec_player.c b/swfdec/swfdec_player.c
index 78f3ed0..5b3ea00 100644
--- a/swfdec/swfdec_player.c
+++ b/swfdec/swfdec_player.c
@@ -816,6 +816,7 @@ swfdec_player_update_scale (SwfdecPlayer *player)
SwfdecPlayerPrivate *priv = player->priv;
int width, height;
double scale_x, scale_y;
+ GList *walk;
if (priv->fullscreen) {
priv->stage.width = priv->system->screen_width;
@@ -889,6 +890,10 @@ swfdec_player_update_scale (SwfdecPlayer *player)
priv->invalid.x1 = priv->stage_width;
priv->invalid.y1 = priv->stage_height;
#endif
+ /* FIXME: notify textfields more gentle about the update */
+ for (walk = priv->roots; walk; walk = walk->next) {
+ g_signal_emit_by_name (walk->data, "matrix-changed");
+ }
}
static void
diff --git a/swfdec/swfdec_text_attributes.h b/swfdec/swfdec_text_attributes.h
index 1736f4a..b1417f0 100644
--- a/swfdec/swfdec_text_attributes.h
+++ b/swfdec/swfdec_text_attributes.h
@@ -90,7 +90,7 @@ struct _SwfdecTextAttributes {
gboolean kerning;
int leading;
int left_margin;
- double letter_spacing; // number or null
+ double letter_spacing;
int right_margin;
int size;
guint * tab_stops;
diff --git a/swfdec/swfdec_text_field.c b/swfdec/swfdec_text_field.c
index 9d6285a..8eaa956 100644
--- a/swfdec/swfdec_text_field.c
+++ b/swfdec/swfdec_text_field.c
@@ -50,7 +50,7 @@ swfdec_text_field_create_movie (SwfdecGraphic *graphic, gsize *size)
ret->html = text->html;
ret->editable = text->editable;
- ret->password = text->password;
+ swfdec_text_layout_set_password (ret->layout, text->password);
ret->max_chars = text->max_chars;
ret->selectable = text->selectable;
ret->embed_fonts = text->embed_fonts;
diff --git a/swfdec/swfdec_text_field_movie.c b/swfdec/swfdec_text_field_movie.c
index 62bd5a4..356c153 100644
--- a/swfdec/swfdec_text_field_movie.c
+++ b/swfdec/swfdec_text_field_movie.c
@@ -39,8 +39,10 @@
G_DEFINE_TYPE (SwfdecTextFieldMovie, swfdec_text_field_movie, SWFDEC_TYPE_ACTOR)
-#define EXTRA_MARGIN 2
-#define BULLET_MARGIN 36
+#define BORDER_TOP 1
+#define BORDER_LEFT 2
+#define BORDER_RIGHT 2
+#define BORDER_BOTTOM 1
/*** VFUNCS ***/
@@ -72,737 +74,7 @@ swfdec_text_field_movie_invalidate (SwfdecMovie *movie, const cairo_matrix_t *ma
SWFDEC_PLAYER (SWFDEC_AS_OBJECT (movie)->context), &rect);
}
-static void
-swfdec_text_field_movie_ensure_asterisks (SwfdecTextFieldMovie *text,
- guint length)
-{
- g_return_if_fail (SWFDEC_IS_TEXT_FIELD_MOVIE (text));
-
- if (text->asterisks_length >= length)
- return;
-
- if (text->asterisks != NULL)
- g_free (text->asterisks);
-
- text->asterisks = g_malloc (length + 1);
- memset (text->asterisks, '*', length);
- text->asterisks[length] = 0;
- text->asterisks_length = length;
-}
-
-static void
-swfdec_text_paragraph_add_attribute (SwfdecParagraph *paragraph,
- PangoAttribute *attr)
-{
- paragraph->attrs = g_slist_prepend (paragraph->attrs, attr);
-}
-
-static void
-swfdec_text_paragraph_add_block (SwfdecParagraph *paragraph, int index_,
- const SwfdecTextAttributes *attr)
-{
- guint i;
- SwfdecBlock *block;
-
- block = g_new0 (SwfdecBlock, 1);
-
- block->index_ = index_;
-
- switch (attr->align) {
- case SWFDEC_TEXT_ALIGN_LEFT:
- block->align = PANGO_ALIGN_LEFT;
- block->justify = FALSE;
- break;
- case SWFDEC_TEXT_ALIGN_RIGHT:
- block->align = PANGO_ALIGN_RIGHT;
- block->justify = FALSE;
- break;
- case SWFDEC_TEXT_ALIGN_CENTER:
- block->align = PANGO_ALIGN_CENTER;
- block->justify = FALSE;
- break;
- case SWFDEC_TEXT_ALIGN_JUSTIFY:
- block->align = PANGO_ALIGN_LEFT;
- block->justify = TRUE;
- break;
- default:
- g_assert_not_reached ();
- }
- block->leading = attr->leading * 20 * PANGO_SCALE;
- block->block_indent = attr->block_indent * 20;
- block->left_margin = attr->left_margin * 20;
- block->right_margin = attr->right_margin * 20;
-
- if (attr->n_tab_stops != 0) {
- block->tab_stops = pango_tab_array_new (attr->n_tab_stops, TRUE);
- for (i = 0; i < attr->n_tab_stops; i++) {
- pango_tab_array_set_tab (block->tab_stops, i, PANGO_TAB_LEFT,
- attr->tab_stops[i] * 20);
- }
- } else {
- block->tab_stops = NULL;
- }
-
- paragraph->blocks = g_slist_prepend (paragraph->blocks, block);
-}
-
-static void
-swfdec_text_field_movie_generate_paragraph (SwfdecTextFieldMovie *text,
- SwfdecParagraph *paragraph, guint start_index, guint length)
-{
- guint index_;
- SwfdecTextBufferIter *iter;
- PangoAttribute *attr_bold, *attr_color, *attr_font, *attr_italic,
- *attr_letter_spacing, *attr_size, *attr_underline;
- const char *string;
- const SwfdecTextAttributes *attr, *attr_prev;
- // TODO: kerning, display
-
- g_assert (SWFDEC_IS_TEXT_FIELD_MOVIE (text));
- g_assert (paragraph != NULL);
- g_assert (start_index + length <= swfdec_text_buffer_get_length (text->text));
-
- string = swfdec_text_buffer_get_text (text->text);
- paragraph->index_ = start_index;
- paragraph->length = length;
- if (string[start_index + length - 1] == '\n' ||
- string[start_index + length - 1] == '\r') {
- paragraph->newline = TRUE;
- } else {
- paragraph->newline = FALSE;
- }
-
- paragraph->blocks = NULL;
- paragraph->attrs = NULL;
-
- iter = swfdec_text_buffer_get_iter (text->text, start_index);
- attr = swfdec_text_buffer_iter_get_attributes (text->text, iter);
-
- index_ = start_index;
-
- // Paragraph formats
- paragraph->bullet = attr->bullet;
- paragraph->indent = attr->indent * 20 * PANGO_SCALE;
-
- // Add new block
- swfdec_text_paragraph_add_block (paragraph, 0, attr);
-
- // Open attributes
- attr_bold = pango_attr_weight_new (
- (attr->bold ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL));
- attr_bold->start_index = 0;
-
- attr_color = pango_attr_foreground_new (SWFDEC_COLOR_R (attr->color) * 255,
- SWFDEC_COLOR_G (attr->color) * 255,
- SWFDEC_COLOR_B (attr->color) * 255);
- attr_color->start_index = 0;
-
- // FIXME: embed fonts
- attr_font = pango_attr_family_new (attr->font);
- attr_font->start_index = 0;
-
- attr_italic = pango_attr_style_new (
- (attr->italic ? PANGO_STYLE_ITALIC : PANGO_STYLE_NORMAL));
- attr_italic->start_index = 0;
-
- attr_letter_spacing = pango_attr_letter_spacing_new (
- attr->letter_spacing * 20 * PANGO_SCALE);
- attr_letter_spacing->start_index = 0;
-
- attr_size =
- pango_attr_size_new_absolute (MAX (attr->size, 1) * 20 * PANGO_SCALE);
- attr_size->start_index = 0;
-
- attr_underline = pango_attr_underline_new (
- (attr->underline ? PANGO_UNDERLINE_SINGLE : PANGO_UNDERLINE_NONE));
- attr_underline->start_index = 0;
-
- for (iter = swfdec_text_buffer_iter_next (text->text, iter);
- iter != NULL && swfdec_text_buffer_iter_get_start (text->text, iter) < start_index + length;
- iter = swfdec_text_buffer_iter_next (text->text, iter))
- {
- attr_prev = attr;
- index_ = swfdec_text_buffer_iter_get_start (text->text, iter);
- attr = swfdec_text_buffer_iter_get_attributes (text->text, iter);
-
- // Add new block if necessary
- if (attr_prev->align != attr->align ||
- attr_prev->bullet != attr->bullet ||
- attr_prev->indent != attr->indent ||
- attr_prev->leading != attr->leading ||
- attr_prev->block_indent != attr->block_indent ||
- attr_prev->left_margin != attr->left_margin)
- {
- swfdec_text_paragraph_add_block (paragraph, index_ - start_index, attr);
- }
-
- // Change attributes if necessary
- if (attr_prev->bold != attr->bold) {
- attr_bold->end_index = index_ - start_index;
- swfdec_text_paragraph_add_attribute (paragraph, attr_bold);
-
- attr_bold = pango_attr_weight_new (
- (attr->bold ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL));
- attr_bold->start_index = index_ - start_index;
- }
-
- if (attr_prev->color != attr->color) {
- attr_color->end_index = index_ - start_index;
- swfdec_text_paragraph_add_attribute (paragraph, attr_color);
-
- attr_color = pango_attr_foreground_new (
- SWFDEC_COLOR_R (attr->color) * 255,
- SWFDEC_COLOR_G (attr->color) * 255,
- SWFDEC_COLOR_B (attr->color) * 255);
- attr_color->start_index = index_ - start_index;
- }
-
- if (attr_prev->font != attr->font) {
- attr_font->end_index = index_ - start_index;
- swfdec_text_paragraph_add_attribute (paragraph, attr_font);
-
- // FIXME: embed fonts
- attr_font = pango_attr_family_new (attr->font);
- attr_font->start_index = index_ - start_index;
- }
-
- if (attr_prev->italic != attr->italic) {
- attr_italic->end_index = index_ - start_index;
- swfdec_text_paragraph_add_attribute (paragraph, attr_italic);
-
- attr_italic = pango_attr_style_new (
- (attr->italic ? PANGO_STYLE_ITALIC : PANGO_STYLE_NORMAL));
- attr_italic->start_index = index_ - start_index;
- }
-
- if (attr_prev->letter_spacing != attr->letter_spacing) {
- attr_letter_spacing->end_index = index_ - start_index;
- swfdec_text_paragraph_add_attribute (paragraph, attr_letter_spacing);
-
- attr_letter_spacing = pango_attr_letter_spacing_new (
- attr->letter_spacing * 20 * PANGO_SCALE);
- attr_letter_spacing->start_index = index_ - start_index;
- }
-
- if (attr_prev->size != attr->size) {
- attr_size->end_index = index_ - start_index;
- swfdec_text_paragraph_add_attribute (paragraph, attr_size);
-
- attr_size = pango_attr_size_new_absolute (
- MAX (1, attr->size) * 20 * PANGO_SCALE);
- attr_size->start_index = index_ - start_index;
- }
-
- if (attr_prev->underline != attr->underline) {
- attr_underline->end_index = index_ - start_index;
- swfdec_text_paragraph_add_attribute (paragraph, attr_underline);
-
- attr_underline = pango_attr_underline_new (
- (attr->underline ? PANGO_UNDERLINE_SINGLE : PANGO_UNDERLINE_NONE));
- attr_underline->start_index = index_ - start_index;
- }
- }
-
- // Close attributes
- attr_bold->end_index = length;
- swfdec_text_paragraph_add_attribute (paragraph, attr_bold);
- attr_bold = NULL;
-
- attr_color->end_index = length;
- swfdec_text_paragraph_add_attribute (paragraph, attr_color);
- attr_color = NULL;
-
- attr_font->end_index = length;
- swfdec_text_paragraph_add_attribute (paragraph, attr_font);
- attr_font = NULL;
-
- attr_italic->end_index = length;
- swfdec_text_paragraph_add_attribute (paragraph, attr_italic);
- attr_italic = NULL;
-
- attr_letter_spacing->end_index = length;
- swfdec_text_paragraph_add_attribute (paragraph, attr_letter_spacing);
- attr_letter_spacing = NULL;
-
- attr_size->end_index = length;
- swfdec_text_paragraph_add_attribute (paragraph, attr_size);
- attr_size = NULL;
-
- attr_underline->end_index = length;
- swfdec_text_paragraph_add_attribute (paragraph, attr_underline);
- attr_underline = NULL;
-
- // reverse blocks since we use prepend to add them
- paragraph->blocks = g_slist_reverse (paragraph->blocks);
-}
-
-static SwfdecParagraph *
-swfdec_text_field_movie_get_paragraphs (SwfdecTextFieldMovie *text, int *num)
-{
- GArray *paragraphs;
- SwfdecParagraph paragraph;
- const char *p, *end, *string;
- guint max_length;
-
- g_assert (SWFDEC_IS_TEXT_FIELD_MOVIE (text));
-
- paragraphs = g_array_new (TRUE, TRUE, sizeof (SwfdecParagraph));
-
- max_length = 0;
- p = string = swfdec_text_buffer_get_text (text->text);
- while (*p != '\0')
- {
- end = strpbrk (p, "\r\n");
- if (end == NULL) {
- end = strchr (p, '\0');
- } else {
- end++;
- }
-
- if ((guint) (end - p) > max_length)
- max_length = end - p;
-
- swfdec_text_field_movie_generate_paragraph (text, ¶graph,
- p - string, end - p);
- paragraphs = g_array_append_val (paragraphs, paragraph);
-
- p = end;
- }
-
- if (num != NULL)
- *num = paragraphs->len;
-
- if (text->password)
- swfdec_text_field_movie_ensure_asterisks (text, max_length);
-
- return (SwfdecParagraph *) (void *) g_array_free (paragraphs, FALSE);
-}
-
-static void
-swfdec_text_field_movie_free_paragraphs (SwfdecParagraph *paragraphs)
-{
- GSList *iter;
- int i;
-
- g_return_if_fail (paragraphs != NULL);
-
- for (i = 0; paragraphs[i].blocks != NULL; i++)
- {
- for (iter = paragraphs[i].blocks; iter != NULL; iter = iter->next) {
- if (((SwfdecBlock *)(iter->data))->tab_stops)
- pango_tab_array_free (((SwfdecBlock *)(iter->data))->tab_stops);
- g_free (iter->data);
- }
- g_slist_free (paragraphs[i].blocks);
-
- for (iter = paragraphs[i].attrs; iter != NULL; iter = iter->next) {
- pango_attribute_destroy ((PangoAttribute *)(iter->data));
- }
- g_slist_free (paragraphs[i].attrs);
- }
- g_free (paragraphs);
-}
-
-/*
- * Rendering
- */
-static PangoAttrList *
-swfdec_text_field_movie_paragraph_get_attr_list (
- const SwfdecParagraph *paragraph, guint index_,
- const SwfdecColorTransform *trans)
-{
- PangoAttrList *attr_list;
- GSList *iter;
-
- attr_list = pango_attr_list_new ();
-
- for (iter = paragraph->attrs; iter != NULL; iter = iter->next)
- {
- PangoAttribute *attr;
-
- if (((PangoAttribute *)iter->data)->end_index <= index_)
- continue;
-
- attr = pango_attribute_copy ((PangoAttribute *)iter->data);
-
- if (attr->klass->type == PANGO_ATTR_FOREGROUND && trans != NULL &&
- !swfdec_color_transform_is_identity (trans))
- {
- SwfdecColor color;
- PangoColor color_p;
-
- color_p = ((PangoAttrColor *)attr)->color;
-
- color = SWFDEC_COLOR_COMBINE (color_p.red >> 8, color_p.green >> 8,
- color_p.blue >> 8, 255);
- color = swfdec_color_apply_transform (color, trans);
-
- color_p.red = SWFDEC_COLOR_R (color) << 8;
- color_p.green = SWFDEC_COLOR_G (color) << 8;
- color_p.blue = SWFDEC_COLOR_B (color) << 8;
- }
-
- attr->start_index =
- (attr->start_index > index_ ? attr->start_index - index_ : 0);
- attr->end_index = attr->end_index - index_;
- pango_attr_list_insert (attr_list, attr);
- }
-
- return attr_list;
-}
-
-static void
-swfdec_text_field_movie_attr_list_get_ascent_descent (PangoAttrList *attr_list,
- guint pos, int *ascent, int *descent)
-{
- PangoAttrIterator *attr_iter;
- PangoFontDescription *desc;
- PangoFontMap *fontmap;
- PangoFont *font;
- PangoFontMetrics *metrics;
- PangoContext *pcontext;
- int end;
-
- if (ascent != NULL)
- *ascent = 0;
- if (descent != NULL)
- *descent = 0;
-
- g_return_if_fail (attr_list != NULL);
-
- attr_iter = pango_attr_list_get_iterator (attr_list);
- pango_attr_iterator_range (attr_iter, NULL, &end);
- while ((guint)end < pos && pango_attr_iterator_next (attr_iter)) {
- pango_attr_iterator_range (attr_iter, NULL, &end);
- }
- desc = pango_font_description_new ();
- pango_attr_iterator_get_font (attr_iter, desc, NULL, NULL);
- fontmap = pango_cairo_font_map_get_default ();
- pcontext =
- pango_cairo_font_map_create_context (PANGO_CAIRO_FONT_MAP (fontmap));
- font = pango_font_map_load_font (fontmap, pcontext, desc);
- metrics = pango_font_get_metrics (font, NULL);
-
- if (ascent != NULL)
- *ascent = pango_font_metrics_get_ascent (metrics) / PANGO_SCALE;
- if (descent != NULL)
- *descent = pango_font_metrics_get_descent (metrics) / PANGO_SCALE;
-
- g_object_unref (pcontext);
- pango_font_metrics_unref (metrics);
- pango_font_description_free (desc);
- pango_attr_iterator_destroy (attr_iter);
-}
-
-static SwfdecLayout *
-swfdec_text_field_movie_get_layouts (SwfdecTextFieldMovie *text, int *num,
- cairo_t *cr, const SwfdecParagraph *paragraphs,
- const SwfdecColorTransform *trans)
-{
- GArray *layouts;
- guint i;
- SwfdecParagraph *paragraphs_free;
- gsize cursor_start, cursor_end;
-
- g_assert (SWFDEC_IS_TEXT_FIELD_MOVIE (text));
-
- if (cr == NULL) {
- cr = cairo_create (swfdec_renderer_get_surface (
- SWFDEC_PLAYER (SWFDEC_AS_OBJECT (text)->context)->priv->renderer));
- } else {
- cairo_reference (cr);
- }
-
- if (paragraphs == NULL) {
- paragraphs_free = swfdec_text_field_movie_get_paragraphs (text, NULL);
- paragraphs = paragraphs_free;
- } else {
- paragraphs_free = NULL;
- }
-
- layouts = g_array_new (TRUE, TRUE, sizeof (SwfdecLayout));
- swfdec_text_buffer_get_selection (text->text, &cursor_start, &cursor_end);
-
- for (i = 0; paragraphs[i].blocks != NULL; i++)
- {
- GSList *iter;
- guint skip;
-
- skip = 0;
- for (iter = paragraphs[i].blocks; iter != NULL; iter = iter->next)
- {
- SwfdecLayout layout;
- PangoLayout *playout;
- PangoAttrList *attr_list;
- SwfdecBlock *block;
- int width;
- guint length;
-
- block = (SwfdecBlock *)iter->data;
- if (iter->next != NULL) {
- length =
- ((SwfdecBlock *)(iter->next->data))->index_ - block->index_;
- } else {
- length = paragraphs[i].length - block->index_;
- if (paragraphs[i].newline)
- length -= 1;
- }
-
- if (skip > length) {
- skip -= length;
- continue;
- }
-
- // create layout
- playout = layout.layout = pango_cairo_create_layout (cr);
- pango_layout_set_single_paragraph_mode (playout, TRUE);
-
- // set rendering position
- layout.offset_x = block->left_margin + block->block_indent;
- if (paragraphs[i].bullet)
- layout.offset_x += SWFDEC_DOUBLE_TO_TWIPS (BULLET_MARGIN);
-
- width = SWFDEC_MOVIE (text)->original_extents.x1 -
- SWFDEC_MOVIE (text)->original_extents.x0 - block->right_margin -
- layout.offset_x;
-
- if (block->index_ == 0 && paragraphs[i].indent < 0) {
- // limit negative indent to not go over leftMargin + blockIndent
- int indent = MAX (paragraphs[i].indent / PANGO_SCALE,
- -(block->left_margin + block->block_indent));
- layout.offset_x += indent;
- width += -indent;
- }
-
- if (text->word_wrap) {
- pango_layout_set_wrap (playout, PANGO_WRAP_WORD_CHAR);
- pango_layout_set_width (playout, width * PANGO_SCALE);
- pango_layout_set_alignment (playout, block->align);
- pango_layout_set_justify (playout, block->justify);
- } else {
- pango_layout_set_width (playout, -1);
- }
-
- // set paragraph styles
- if (block->index_ == 0) {
- pango_layout_set_indent (playout, paragraphs[i].indent);
- layout.bullet = paragraphs[i].bullet;
- } else {
- pango_layout_set_indent (playout, 0);
- layout.bullet = FALSE;
- }
-
- // set block styles
- pango_layout_set_spacing (playout, block->leading);
- if (block->tab_stops != NULL)
- pango_layout_set_tabs (playout, block->tab_stops);
-
- // set text attributes
- attr_list = swfdec_text_field_movie_paragraph_get_attr_list (
- ¶graphs[i], block->index_ + skip, trans);
-
- // add background for selection
- layout.index_ = paragraphs[i].index_ + block->index_ + skip;
- layout.index_end = layout.index_ + length;
- if (cursor_start != cursor_end &&
- layout.index_ < cursor_end) {
- SwfdecColor color;
- PangoAttribute *attr_fg, *attr_bg;
-
- color = SWFDEC_COLOR_COMBINE (255, 255, 255, 255);
- if (trans != NULL)
- color = swfdec_color_apply_transform (color, trans);
- attr_fg = pango_attr_foreground_new (SWFDEC_COLOR_R (color) << 8,
- SWFDEC_COLOR_G (color) << 8, SWFDEC_COLOR_B (color) << 8);
-
- color = SWFDEC_COLOR_COMBINE (0, 0, 0, 255);
- if (trans != NULL)
- color = swfdec_color_apply_transform (color, trans);
- attr_bg = pango_attr_background_new (SWFDEC_COLOR_R (color) << 8,
- SWFDEC_COLOR_G (color) << 8, SWFDEC_COLOR_B (color) << 8);
-
- if (cursor_start > layout.index_) {
- attr_fg->start_index = attr_bg->start_index = cursor_start - layout.index_;
- } else {
- attr_fg->start_index = attr_bg->start_index = 0;
- }
- attr_bg->end_index = attr_fg->end_index = cursor_end - layout.index_;
-
- pango_attr_list_insert (attr_list, attr_fg);
- pango_attr_list_insert (attr_list, attr_bg);
- }
-
- // add shape for newline character at the end
- if (paragraphs[i].newline) {
- int ascent, descent;
- PangoRectangle rect;
- PangoAttribute *attr;
-
- swfdec_text_field_movie_attr_list_get_ascent_descent (attr_list,
- paragraphs[i].length - block->index_ - skip, &ascent, &descent);
-
- rect.x = 0;
- rect.width = 0;
- rect.y = -ascent * PANGO_SCALE;
- rect.height = descent * PANGO_SCALE;
-
- attr = pango_attr_shape_new (&rect, &rect);
-
- attr->end_index = paragraphs[i].length - block->index_ - skip;
- attr->start_index = attr->end_index - 1;
-
- pango_attr_list_insert (attr_list, attr);
- }
-
- pango_layout_set_attributes (playout, attr_list);
-
- if (text->password) {
- pango_layout_set_text (playout, text->asterisks, paragraphs[i].length -
- block->index_ - skip);
- } else {
- pango_layout_set_text (playout,
- swfdec_text_buffer_get_text (text->text) + paragraphs[i].index_ + block->index_ + skip,
- paragraphs[i].length - block->index_ - skip);
- }
-
- if (iter->next != NULL && text->word_wrap)
- {
- PangoLayoutLine *line;
- int line_num;
- guint skip_new;
-
- pango_layout_index_to_line_x (playout, length - skip, FALSE, &line_num,
- NULL);
- if (line_num < pango_layout_get_line_count (playout) - 1) {
- line = pango_layout_get_line_readonly (playout, line_num);
- skip_new = line->start_index + line->length - (length - skip);
- pango_layout_set_text (playout,
- swfdec_text_buffer_get_text (text->text) + paragraphs[i].index_ + block->index_ + skip,
- length - skip + skip_new);
- skip = skip_new;
- }
- }
- else
- {
- if (!text->word_wrap && block->align != PANGO_ALIGN_LEFT) {
- int line_width;
- pango_layout_get_pixel_size (playout, &line_width, 0);
- if (line_width < width) {
- if (block->align == PANGO_ALIGN_RIGHT) {
- layout.offset_x += width - line_width;
- } else if (block->align == PANGO_ALIGN_CENTER) {
- layout.offset_x += (width - line_width) / 2;
- } else {
- g_assert_not_reached ();
- }
- }
- }
-
- skip = 0;
- }
-
- pango_layout_get_pixel_size (playout, &layout.width, &layout.height);
- layout.width += layout.offset_x + block->right_margin;
-
- pango_attr_list_unref (attr_list);
-
- // add leading to last line too
- layout.height += block->leading / PANGO_SCALE;
-
- layouts = g_array_append_val (layouts, layout);
-
- if (!text->word_wrap)
- break;
- }
- }
-
- if (paragraphs_free != NULL) {
- swfdec_text_field_movie_free_paragraphs (paragraphs_free);
- paragraphs_free = NULL;
- paragraphs = NULL;
- }
-
- if (num != NULL)
- *num = layouts->len;
- cairo_destroy (cr);
-
- return (SwfdecLayout *) (void *) g_array_free (layouts, FALSE);
-}
-
-static void
-swfdec_text_field_movie_free_layouts (SwfdecLayout *layouts)
-{
- int i;
-
- g_return_if_fail (layouts != NULL);
-
- for (i = 0; layouts[i].layout != NULL; i++) {
- g_object_unref (layouts[i].layout);
- }
-
- g_free (layouts);
-}
-
-static void
-swfdec_text_field_movie_line_position (SwfdecLayout *layouts, int line_num,
- int *pixels, int *layout_num, int *line_in_layout)
-{
- int current, i;
-
- if (pixels != NULL)
- *pixels = 0;
-
- if (layout_num != NULL)
- *layout_num = 0;
-
- if (line_in_layout != NULL)
- *line_in_layout = 0;
-
- g_return_if_fail (layouts != NULL);
-
- current = 1;
- for (i = 0; layouts[i].layout != NULL && current < line_num; i++) {
- current += pango_layout_get_line_count (layouts[i].layout);
-
- if (pixels != NULL)
- *pixels += layouts[i].height;
- }
-
- if (current > line_num) {
- PangoLayoutIter *iter_line;
-
- i--;
- current -= pango_layout_get_line_count (layouts[i].layout);
-
- if (pixels != NULL)
- *pixels -= layouts[i].height;
-
- iter_line = pango_layout_get_iter (layouts[i].layout);
-
- while (++current < line_num) {
- g_assert (!pango_layout_iter_at_last_line (iter_line));
- pango_layout_iter_next_line (iter_line);
-
- if (line_in_layout != NULL)
- (*line_in_layout)++;
- }
-
- if (pixels != NULL) {
- PangoRectangle rect;
-
- pango_layout_iter_get_line_extents (iter_line, NULL, &rect);
- pango_extents_to_pixels (NULL, &rect);
-
- *pixels += rect.y;
- }
-
- pango_layout_iter_free (iter_line);
- }
-
- if (layout_num != NULL)
- *layout_num = i;
-}
-
+#if 0
static gboolean
swfdec_text_field_movie_has_focus (SwfdecTextFieldMovie *text)
{
@@ -810,200 +82,65 @@ swfdec_text_field_movie_has_focus (SwfdecTextFieldMovie *text)
return swfdec_player_has_focus (player, SWFDEC_ACTOR (text));
}
+#endif
static void
swfdec_text_field_movie_render (SwfdecMovie *movie, cairo_t *cr,
- const SwfdecColorTransform *trans, const SwfdecRect *inval)
+ const SwfdecColorTransform *ctrans, const SwfdecRect *inval)
{
- SwfdecTextFieldMovie *text;
- SwfdecLayout *layouts;
- SwfdecRect limit;
+ static const cairo_matrix_t identity = { 1, 0, 0, 1, 0, 0 };
+ SwfdecTextFieldMovie *text = SWFDEC_TEXT_FIELD_MOVIE (movie);
SwfdecColor color;
- SwfdecParagraph *paragraphs;
- int i, y, x, skip;
- gboolean first;
- gsize cursor;
-
- g_return_if_fail (SWFDEC_IS_TEXT_FIELD_MOVIE (movie));
- g_return_if_fail (cr != NULL);
- g_return_if_fail (trans != NULL);
- g_return_if_fail (inval != NULL);
+ g_print ("render %d %d %d %d\n",
+ text->stage_rect.x, text->stage_rect.y,
+ text->stage_rect.width, text->stage_rect.height);
/* textfields don't mask */
- if (swfdec_color_transform_is_mask (trans))
+ if (swfdec_color_transform_is_mask (ctrans) ||
+ swfdec_rectangle_is_empty (&text->stage_rect))
return;
- text = SWFDEC_TEXT_FIELD_MOVIE (movie);
-
- paragraphs = swfdec_text_field_movie_get_paragraphs (text, NULL);
-
- swfdec_rect_intersect (&limit, &movie->original_extents, inval);
+ /* FIXME: need to handle the case where we're not drawing with identity */
+ cairo_set_matrix (cr, &identity);
if (text->background) {
- cairo_rectangle (cr, limit.x0, limit.y0, limit.x1 - limit.x0,
- limit.y1 - limit.y0);
- color = swfdec_color_apply_transform (text->background_color, trans);
- // always use full alpha
- swfdec_color_set_source (cr, color | SWFDEC_COLOR_COMBINE (0, 0, 0, 255));
+ cairo_rectangle (cr, text->stage_rect.x, text->stage_rect.y,
+ text->stage_rect.width, text->stage_rect.height);
+ color = swfdec_color_apply_transform (text->background_color, ctrans);
+ swfdec_color_set_source (cr, SWFDEC_COLOR_OPAQUE (color));
cairo_fill (cr);
}
-
if (text->border) {
- // FIXME: should not be scaled, but always be 1 pixel width
- // TODO: should clip before to make things faster?
- cairo_rectangle (cr, movie->original_extents.x0 +
- SWFDEC_DOUBLE_TO_TWIPS (0.5), movie->original_extents.y0 +
- SWFDEC_DOUBLE_TO_TWIPS (0.5),
- movie->original_extents.x1 - movie->original_extents.x0,
- movie->original_extents.y1 - movie->original_extents.y0);
- color = swfdec_color_apply_transform (text->border_color, trans);
- // always use full alpha
- swfdec_color_set_source (cr, color | SWFDEC_COLOR_COMBINE (0, 0, 0, 255));
- cairo_set_line_width (cr, SWFDEC_DOUBLE_TO_TWIPS (1));
+ cairo_rectangle (cr, text->stage_rect.x + 0.5, text->stage_rect.y + 0.5,
+ text->stage_rect.width, text->stage_rect.height);
+ color = swfdec_color_apply_transform (text->border_color, ctrans);
+ swfdec_color_set_source (cr, SWFDEC_COLOR_OPAQUE (color));
+ cairo_set_line_width (cr, 1.0);
cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
- cairo_set_antialias (cr, CAIRO_ANTIALIAS_NONE);
cairo_stroke (cr);
}
- cairo_rectangle (cr, limit.x0, limit.y0, limit.x1 - limit.x0,
- limit.y1 - limit.y0);
- cairo_clip (cr);
-
- layouts = swfdec_text_field_movie_get_layouts (text, NULL, cr,
- paragraphs, trans);
-
- first = TRUE;
- x = movie->original_extents.x0 + SWFDEC_DOUBLE_TO_TWIPS (EXTRA_MARGIN) +
- MIN (text->hscroll, text->hscroll_max);
- y = movie->original_extents.y0 + SWFDEC_DOUBLE_TO_TWIPS (EXTRA_MARGIN);
-
- swfdec_text_field_movie_line_position (layouts,
- MIN (text->scroll, text->scroll_max), NULL, &i, &skip);
-
- if (text->editable && swfdec_text_field_movie_has_focus (text) &&
- !swfdec_text_buffer_has_selection (text->text))
- cursor = swfdec_text_buffer_get_cursor (text->text);
- else
- cursor = G_MAXSIZE;
-
- for (; layouts[i].layout != NULL && y < limit.y1; i++)
- {
- SwfdecLayout *layout = &layouts[i];
- PangoLayoutIter *iter_line;
- PangoLayoutLine *line;
- PangoRectangle rect;
- int skipped;
-
- iter_line = pango_layout_get_iter (layout->layout);
-
- if (layout->bullet && skip == 0) {
- PangoColor color_p;
- PangoAttribute *attr;
- PangoAttrIterator *attr_iter;
-
- pango_layout_iter_get_line_extents (iter_line, NULL, &rect);
- pango_extents_to_pixels (NULL, &rect);
-
- cairo_new_sub_path (cr);
-
- // get current color
- attr_iter = pango_attr_list_get_iterator (
- pango_layout_get_attributes (layout->layout));
- attr = pango_attr_iterator_get (attr_iter, PANGO_ATTR_FOREGROUND);
- color_p = ((PangoAttrColor *)attr)->color;
- color = SWFDEC_COLOR_COMBINE (color_p.red >> 8, color_p.green >> 8,
- color_p.blue >> 8, 255);
- color = swfdec_color_apply_transform (color, trans);
- pango_attr_iterator_destroy (attr_iter);
-
- swfdec_color_set_source (cr, color);
-
- cairo_arc (cr, x + layout->offset_x +
- pango_layout_get_indent (layout->layout) -
- SWFDEC_DOUBLE_TO_TWIPS (BULLET_MARGIN) / 2,
- y + rect.height / 2, rect.height / 8, 20, 2 * M_PI);
- cairo_fill (cr);
- }
-
- if (skip > 0) {
- for (skipped = 0; skipped < skip; skipped++) {
- g_assert (!pango_layout_iter_at_last_line (iter_line));
- pango_layout_iter_next_line (iter_line);
- }
-
- pango_layout_iter_get_line_extents (iter_line, NULL, &rect);
- pango_extents_to_pixels (NULL, &rect);
-
- skipped = rect.y;
- skip = 0;
- } else {
- skipped = 0;
- }
-
- do {
- pango_layout_iter_get_line_extents (iter_line, NULL, &rect);
- pango_extents_to_pixels (NULL, &rect);
- line = pango_layout_iter_get_line_readonly (iter_line);
-
- if (!first && y + rect.y + rect.height > movie->original_extents.y1)
- break;
-
- first = FALSE;
-
- if (y + rect.y > limit.y1)
- break;
-
- if (y + rect.y + rect.height < limit.y0 ||
- x + layout->offset_x + rect.x > limit.x1 ||
- x + layout->offset_x + rect.x + rect.width < limit.x0)
- continue;
-
- cairo_move_to (cr, x, y);
- cairo_rel_move_to (cr, layout->offset_x + rect.x,
- pango_layout_iter_get_baseline (iter_line) / PANGO_SCALE - skipped);
-
- pango_cairo_show_layout_line (cr, line);
- line = NULL;
- } while (pango_layout_iter_next_line (iter_line));
-
- if (layouts[i].index_ <= cursor &&
- (layouts[i].index_end > cursor || (layouts[i].index_end == cursor && cursor == swfdec_text_buffer_get_length (text->text))) &&
- (line == NULL || layouts[i].index_ + line->start_index >= cursor)) {
- const SwfdecTextAttributes *attr = swfdec_text_buffer_get_attributes (text->text,
- swfdec_text_buffer_get_length (text->text));
- PangoRectangle cursor_rect;
-
- pango_layout_get_cursor_pos (layouts[i].layout,
- swfdec_text_buffer_get_cursor (text->text) - layouts[i].index_,
- &cursor_rect, NULL);
-
- cairo_save (cr);
- /* FIXME: or default attributes? */
- swfdec_color_set_source (cr, attr->color | SWFDEC_COLOR_COMBINE (0, 0, 0, 0xFF));
-
- /* FIXME: what's the proper line width here? */
- cairo_set_line_width (cr, SWFDEC_DOUBLE_TO_TWIPS (0.5));
- cairo_move_to (cr, x + layout->offset_x + rect.x, y - skipped);
- cairo_rel_move_to (cr, (double) cursor_rect.x / PANGO_SCALE, (double) cursor_rect.y / PANGO_SCALE);
- cairo_rel_line_to (cr, (double) cursor_rect.width / PANGO_SCALE, (double) cursor_rect.height / PANGO_SCALE);
- cairo_stroke (cr);
- cairo_restore (cr);
- }
-
- y += layout->height - skipped;
-
- pango_layout_iter_free (iter_line);
- }
-
- swfdec_text_field_movie_free_layouts (layouts);
+ /* no more stuff to do if area too small or no text in existance */
+ if (text->stage_rect.width <= BORDER_LEFT + BORDER_RIGHT ||
+ text->stage_rect.height <= BORDER_TOP + BORDER_BOTTOM)
+ return;
- swfdec_text_field_movie_free_paragraphs (paragraphs);
+ /* FIXME: we want to draw a cursor if there's no text, but for now... */
+ if (swfdec_text_buffer_get_length (text->text) == 0)
+ return;
+ /* render the layout */
+ cairo_rectangle (cr, text->stage_rect.x, text->stage_rect.y, text->stage_rect.width, text->stage_rect.height);
+ cairo_clip (cr);
+ cairo_translate (cr, text->stage_rect.x + BORDER_LEFT, text->stage_rect.y + BORDER_TOP);
+ swfdec_text_layout_render (text->layout, cr, ctrans,
+ 0, text->stage_rect.height - BORDER_TOP + BORDER_BOTTOM, &text->stage_rect);
}
void
swfdec_text_field_movie_update_scroll (SwfdecTextFieldMovie *text,
gboolean check_limits)
{
+#if 0
SwfdecLayout *layouts;
int i, num, y, visible, all, height;
double width, width_max;
@@ -1081,42 +218,9 @@ swfdec_text_field_movie_update_scroll (SwfdecTextFieldMovie *text,
text->scroll_changed = TRUE;
}
}
-}
-
-void
-swfdec_text_field_movie_get_text_size (SwfdecTextFieldMovie *text, int *width,
- int *height)
-{
- SwfdecLayout *layouts;
- int i;
-
- if (width != NULL)
- *width = 0;
- if (height != NULL)
- *height = 0;
-
- g_return_if_fail (SWFDEC_IS_TEXT_FIELD_MOVIE (text));
- g_return_if_fail (width != NULL || height != NULL);
-
- layouts = swfdec_text_field_movie_get_layouts (text, NULL, NULL, NULL, NULL);
-
- for (i = 0; layouts[i].layout != NULL; i++) {
- if (!text->word_wrap) {
- if (width != NULL && layouts[i].width > *width)
- *width = layouts[i].width;
- }
-
- if (height != NULL)
- *height += layouts[i].height;
- }
-
- // align to get integer amount after TWIPS_TO_DOUBLE
- if (width != NULL && *width % SWFDEC_TWIPS_SCALE_FACTOR != 0)
- *width += SWFDEC_TWIPS_SCALE_FACTOR - *width % SWFDEC_TWIPS_SCALE_FACTOR;
- if (height != NULL && *height % SWFDEC_TWIPS_SCALE_FACTOR != 0)
- *height += SWFDEC_TWIPS_SCALE_FACTOR - *height % SWFDEC_TWIPS_SCALE_FACTOR;
-
- swfdec_text_field_movie_free_layouts (layouts);
+#else
+ SWFDEC_STUB ("swfdec_text_field_movie_update_scroll");
+#endif
}
gboolean
@@ -1129,14 +233,8 @@ swfdec_text_field_movie_auto_size (SwfdecTextFieldMovie *text)
if (text->auto_size == SWFDEC_AUTO_SIZE_NONE)
return FALSE;
- swfdec_text_field_movie_get_text_size (text, &width, &height);
- width += SWFDEC_DOUBLE_TO_TWIPS (2 * EXTRA_MARGIN);
- height += SWFDEC_DOUBLE_TO_TWIPS (2 * EXTRA_MARGIN);
-
- if ((text->word_wrap ||
- text->extents.x1 - text->extents.x0 == width) &&
- text->extents.y1 - text->extents.y0 == height)
- return FALSE;
+ width = SWFDEC_DOUBLE_TO_TWIPS (text->layout_width + BORDER_LEFT + BORDER_RIGHT);
+ height = SWFDEC_DOUBLE_TO_TWIPS (text->layout_height + BORDER_TOP + BORDER_BOTTOM);
swfdec_movie_invalidate_next (SWFDEC_MOVIE (text));
@@ -1181,12 +279,6 @@ swfdec_text_field_movie_dispose (GObject *object)
swfdec_text_attributes_reset (&text->default_attributes);
- if (text->asterisks != NULL) {
- g_free (text->asterisks);
- text->asterisks = NULL;
- text->asterisks_length = 0;
- }
-
if (text->style_sheet) {
if (SWFDEC_IS_STYLESHEET (text->style_sheet)) {
g_signal_handlers_disconnect_matched (text->style_sheet,
@@ -1201,6 +293,10 @@ swfdec_text_field_movie_dispose (GObject *object)
g_object_unref (text->text);
text->text = NULL;
}
+ if (text->layout) {
+ g_object_unref (text->layout);
+ text->layout = NULL;
+ }
G_OBJECT_CLASS (swfdec_text_field_movie_parent_class)->dispose (object);
}
@@ -1227,12 +323,55 @@ swfdec_text_field_movie_mark (SwfdecAsObject *object)
}
static void
+swfdec_text_field_movie_update_area (SwfdecTextFieldMovie *text)
+{
+ SwfdecMovie *movie = SWFDEC_MOVIE (text);
+ cairo_matrix_t matrix, translate;
+ double x, y;
+
+ /* check if we indeed want to render */
+ swfdec_movie_local_to_global_matrix (movie, &matrix);
+ cairo_matrix_multiply (&matrix, &matrix,
+ &SWFDEC_PLAYER (SWFDEC_AS_OBJECT (movie)->context)->priv->global_to_stage);
+ if (matrix.xy != 0.0 || matrix.yx != 0.0 ||
+ matrix.xx <= 0.0 || matrix.yy <= 0.0) {
+ swfdec_rectangle_init_empty (&text->stage_rect);
+ return;
+ }
+
+ translate = matrix;
+ x = movie->original_extents.x0;
+ y = movie->original_extents.y0;
+ g_print ("%g %g\n", x, y);
+ cairo_matrix_transform_point (&matrix, &x, &y);
+ g_print ("%g %g\n", x, y);
+ cairo_matrix_init_translate (&translate, round (x) - x, round (y) - y);
+ cairo_matrix_multiply (&matrix, &matrix, &translate);
+
+ x = movie->original_extents.x0;
+ y = movie->original_extents.y0;
+ cairo_matrix_transform_point (&matrix, &x, &y);
+ text->stage_rect.x = x;
+ text->stage_rect.y = y;
+ x = movie->original_extents.x1;
+ y = movie->original_extents.y1;
+ cairo_matrix_transform_point (&matrix, &x, &y);
+ /* FIXME: floor, ceil or round? */
+ text->stage_rect.width = round (x) - text->stage_rect.x;
+ text->stage_rect.height = round (y) - text->stage_rect.y;
+ g_print ("%d %d %d %d\n",
+ text->stage_rect.x, text->stage_rect.y,
+ text->stage_rect.width, text->stage_rect.height);
+}
+
+static void
swfdec_text_field_movie_init_movie (SwfdecMovie *movie)
{
SwfdecTextFieldMovie *text = SWFDEC_TEXT_FIELD_MOVIE (movie);
SwfdecTextField *text_field = SWFDEC_TEXT_FIELD (movie->graphic);
SwfdecAsContext *cx;
SwfdecAsValue val;
+ SwfdecMovie *parent;
gboolean needs_unuse;
needs_unuse = swfdec_sandbox_try_use (movie->resource->sandbox);
@@ -1287,12 +426,27 @@ swfdec_text_field_movie_init_movie (SwfdecMovie *movie)
if (needs_unuse)
swfdec_sandbox_unuse (movie->resource->sandbox);
+
+ parent = movie;
+ while (parent) {
+ g_signal_connect_swapped (parent, "matrix-changed",
+ G_CALLBACK (swfdec_text_field_movie_update_area), movie);
+ parent = parent->parent;
+ }
}
static void
swfdec_text_field_movie_finish_movie (SwfdecMovie *movie)
{
SwfdecTextFieldMovie *text = SWFDEC_TEXT_FIELD_MOVIE (movie);
+ SwfdecMovie *parent;
+
+ parent = SWFDEC_MOVIE (text);
+ while (parent) {
+ g_signal_handlers_disconnect_matched (parent,
+ G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, text);
+ parent = parent->parent;
+ }
swfdec_text_field_movie_set_listen_variable (text, NULL);
}
@@ -1349,50 +503,12 @@ static gboolean
swfdec_text_field_movie_xy_to_index (SwfdecTextFieldMovie *text, double x,
double y, guint *index_, gboolean *before)
{
- SwfdecLayout *layouts;
- int i, layout_index, trailing, pixels;
- double layout_y, layout_x;
- gboolean direct;
-
- g_return_val_if_fail (index_ != NULL, FALSE);
- g_return_val_if_fail (SWFDEC_IS_TEXT_FIELD_MOVIE (text), FALSE);
-
- *index_ = 0;
- if (before != NULL)
- *before = FALSE;
-
- layouts = swfdec_text_field_movie_get_layouts (text, NULL, NULL, NULL, NULL);
-
- if (layouts[0].layout == NULL)
- return FALSE;
-
- layout_y = y - EXTRA_MARGIN - text->extents.y0;
- layout_x = x - EXTRA_MARGIN - text->extents.x0;
-
- // take scrolling into account
- swfdec_text_field_movie_line_position (layouts,
- MIN (text->scroll, text->scroll_max), &pixels, NULL, NULL);
- layout_y += pixels;
- layout_x += MIN (text->hscroll, text->hscroll_max);
-
- i = 0;
- while (layout_y > layouts[i].height && layouts[i + 1].layout != NULL) {
- layout_y -= layouts[i].height;
- i++;
- }
-
- layout_x -= layouts[i].offset_x;
-
- direct = pango_layout_xy_to_index (layouts[i].layout, layout_x * PANGO_SCALE,
- layout_y * PANGO_SCALE, &layout_index, &trailing);
-
- *index_ = layouts[i].index_ + layout_index;
+ SWFDEC_STUB ("swfdec_text_field_movie_xy_to_index");
+ if (index_)
+ *index_ = 0;
if (before)
- *before = (trailing == 0);
-
- swfdec_text_field_movie_free_layouts (layouts);
-
- return direct;
+ *before = FALSE;
+ return FALSE;
}
static SwfdecMouseCursor
@@ -1655,6 +771,9 @@ swfdec_text_field_movie_init (SwfdecTextFieldMovie *text)
G_CALLBACK (swfdec_text_field_movie_cursor_changed), text);
g_signal_connect (text->text, "text-changed",
G_CALLBACK (swfdec_text_field_movie_text_changed), text);
+
+ text->layout = swfdec_text_layout_new (text->text);
+
text->scroll = 1;
text->mouse_wheel_enabled = TRUE;
diff --git a/swfdec/swfdec_text_field_movie.h b/swfdec/swfdec_text_field_movie.h
index 80beb63..43fcbde 100644
--- a/swfdec/swfdec_text_field_movie.h
+++ b/swfdec/swfdec_text_field_movie.h
@@ -26,6 +26,7 @@
#include <swfdec/swfdec_style_sheet.h>
#include <swfdec/swfdec_text_buffer.h>
#include <swfdec/swfdec_text_format.h>
+#include <swfdec/swfdec_text_layout.h>
G_BEGIN_DECLS
@@ -39,56 +40,15 @@ typedef struct _SwfdecTextFieldMovieClass SwfdecTextFieldMovieClass;
#define SWFDEC_TEXT_FIELD_MOVIE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SWFDEC_TYPE_TEXT_FIELD_MOVIE, SwfdecTextFieldMovie))
#define SWFDEC_TEXT_FIELD_MOVIE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SWFDEC_TYPE_TEXT_FIELD_MOVIE, SwfdecTextFieldMovieClass))
-typedef struct {
- PangoLayout * layout; // layout to render
-
- guint index_; // byte offset where this layout's text starts in text->input->str
- guint index_end; // and the offset where it ends
-
- int offset_x; // x offset to apply before rendering
-
- // dimensions for this layout, including offset_x, might be bigger than the
- // rendering of PangoLayout needs
- int width;
- int height;
-
- // whether the layout starts with bullet point to be rendered separately
- gboolean bullet;
-} SwfdecLayout;
-
-typedef struct {
- guint index_;
-
- PangoAlignment align;
- gboolean justify;
- int leading;
- int block_indent;
- int left_margin;
- int right_margin;
- PangoTabArray * tab_stops;
-} SwfdecBlock;
-
-typedef struct {
- guint index_;
- guint length;
- gboolean newline; // ends in newline
-
- gboolean bullet;
- int indent;
-
- GSList * blocks; // SwfdecBlock
- GSList * attrs; // PangoAttribute
-} SwfdecParagraph;
-
struct _SwfdecTextFieldMovie {
SwfdecActor actor;
- SwfdecRect extents; /* the extents we were assigned / calculated during autosize */
+ SwfdecRect extents; /* original extents (copied from graphic) */
+ SwfdecRectangle stage_rect; /* these extents in stage coordinates */
/* properties copied from textfield */
gboolean html;
gboolean editable;
- gboolean password;
int max_chars;
gboolean selectable;
gboolean embed_fonts;
@@ -99,10 +59,13 @@ struct _SwfdecTextFieldMovie {
gboolean background;
SwfdecTextBuffer * text; /* the text + formatting */
- char * asterisks; /* bunch of asterisks that we display when password mode is enabled */
- guint asterisks_length;
gboolean input_html; /* whether orginal input was given as HTML */
+ SwfdecTextLayout * layout; /* the layouted text */
+ SwfdecRectangle layout_area; /* visible area of the layout */
+ guint layout_width; /* text width in pixels */
+ guint layout_height; /* text height in pixels */
+
const char * variable;
SwfdecTextAttributes default_attributes;
@@ -136,12 +99,9 @@ struct _SwfdecTextFieldMovieClass {
GType swfdec_text_field_movie_get_type (void);
-void swfdec_text_field_movie_set_text (SwfdecTextFieldMovie * movie,
+void swfdec_text_field_movie_set_text (SwfdecTextFieldMovie * movie,
const char * str,
gboolean html);
-void swfdec_text_field_movie_get_text_size (SwfdecTextFieldMovie * text,
- int * width,
- int * height);
gboolean swfdec_text_field_movie_auto_size (SwfdecTextFieldMovie * text);
void swfdec_text_field_movie_update_scroll (SwfdecTextFieldMovie * text,
gboolean check_limits);
@@ -163,5 +123,6 @@ void swfdec_text_field_movie_html_parse (SwfdecTextFieldMovie * text,
const char * str);
const char * swfdec_text_field_movie_get_html_text (SwfdecTextFieldMovie * text);
+
G_END_DECLS
#endif
diff --git a/swfdec/swfdec_text_field_movie_as.c b/swfdec/swfdec_text_field_movie_as.c
index 1f67f79..2988d90 100644
--- a/swfdec/swfdec_text_field_movie_as.c
+++ b/swfdec/swfdec_text_field_movie_as.c
@@ -423,12 +423,10 @@ swfdec_text_field_movie_get_textHeight (SwfdecAsContext *cx,
SwfdecAsValue *ret)
{
SwfdecTextFieldMovie *text;
- int height;
SWFDEC_AS_CHECK (SWFDEC_TYPE_TEXT_FIELD_MOVIE, &text, "");
- swfdec_text_field_movie_get_text_size (text, NULL, &height);
- SWFDEC_AS_VALUE_SET_NUMBER (ret, SWFDEC_TWIPS_TO_DOUBLE (height));
+ SWFDEC_AS_VALUE_SET_NUMBER (ret, text->layout_height);
}
static void
@@ -437,12 +435,10 @@ swfdec_text_field_movie_get_textWidth (SwfdecAsContext *cx,
SwfdecAsValue *ret)
{
SwfdecTextFieldMovie *text;
- int width;
SWFDEC_AS_CHECK (SWFDEC_TYPE_TEXT_FIELD_MOVIE, &text, "");
- swfdec_text_field_movie_get_text_size (text, &width, NULL);
- SWFDEC_AS_VALUE_SET_NUMBER (ret, SWFDEC_TWIPS_TO_DOUBLE (width));
+ SWFDEC_AS_VALUE_SET_NUMBER (ret, text->layout_width);
}
/*
@@ -788,7 +784,7 @@ swfdec_text_field_movie_get_password (SwfdecAsContext *cx,
SWFDEC_AS_CHECK (SWFDEC_TYPE_TEXT_FIELD_MOVIE, &text, "");
- SWFDEC_AS_VALUE_SET_BOOLEAN (ret, text->password);
+ SWFDEC_AS_VALUE_SET_BOOLEAN (ret, swfdec_text_layout_get_password (text->layout));
}
static void
@@ -803,15 +799,8 @@ swfdec_text_field_movie_set_password (SwfdecAsContext *cx,
swfdec_as_value_to_number (cx, &argv[0]);
- if (text->password != value) {
- text->password = value;
- if (!value && text->asterisks != NULL) {
- g_free (text->asterisks);
- text->asterisks = NULL;
- text->asterisks_length = 0;
- }
- swfdec_movie_invalidate_last (SWFDEC_MOVIE (text));
- }
+ swfdec_text_layout_set_password (text->layout, value);
+ swfdec_movie_invalidate_last (SWFDEC_MOVIE (text));
}
static void
@@ -1375,12 +1364,12 @@ swfdec_text_field_movie_createTextField (SwfdecAsContext *cx,
SWFDEC_GRAPHIC (edittext), name);
g_assert (SWFDEC_IS_TEXT_FIELD_MOVIE (movie));
g_object_unref (edittext);
- swfdec_movie_initialize (movie);
movie->matrix.x0 = SWFDEC_DOUBLE_TO_TWIPS (x);
movie->matrix.y0 = SWFDEC_DOUBLE_TO_TWIPS (y);
movie->modified = TRUE;
+ swfdec_movie_initialize (movie);
swfdec_movie_update (movie);
swfdec_as_object_get_variable (cx->global, SWFDEC_AS_STR_TextField, &val);
diff --git a/swfdec/swfdec_text_layout.c b/swfdec/swfdec_text_layout.c
new file mode 100644
index 0000000..37683fe
--- /dev/null
+++ b/swfdec/swfdec_text_layout.c
@@ -0,0 +1,608 @@
+/* Swfdec
+ * Copyright (C) 2006-2008 Benjamin Otte <otte at gnome.org>
+ * 2007 Pekka Lampila <pekka.lampila at iki.fi>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <pango/pango.h>
+#include <pango/pangocairo.h>
+#include <string.h>
+
+#include "swfdec_text_layout.h"
+#include "swfdec_debug.h"
+#include "swfdec_decoder.h"
+
+#define BULLET_MARGIN 36
+
+enum {
+ CHANGED,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0, };
+
+static PangoAttribute *
+swfdec_text_attribute_create_bold (const SwfdecTextAttributes *attr)
+{
+ return pango_attr_weight_new (attr->bold ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL);
+}
+
+static PangoAttribute *
+swfdec_text_attribute_create_color (const SwfdecTextAttributes *attr)
+{
+ return pango_attr_foreground_new (SWFDEC_COLOR_R (attr->color) * 255,
+ SWFDEC_COLOR_G (attr->color) * 255, SWFDEC_COLOR_B (attr->color) * 255);
+}
+
+static PangoAttribute *
+swfdec_text_attribute_create_font (const SwfdecTextAttributes *attr)
+{
+ return pango_attr_family_new (attr->font);
+}
+
+static PangoAttribute *
+swfdec_text_attribute_create_italic (const SwfdecTextAttributes *attr)
+{
+ return pango_attr_style_new (attr->italic ? PANGO_STYLE_ITALIC : PANGO_STYLE_NORMAL);
+}
+
+static PangoAttribute *
+swfdec_text_attribute_create_letter_spacing (const SwfdecTextAttributes *attr)
+{
+ return pango_attr_letter_spacing_new (attr->letter_spacing * PANGO_SCALE);
+}
+
+static PangoAttribute *
+swfdec_text_attribute_create_size (const SwfdecTextAttributes *attr)
+{
+ return pango_attr_size_new_absolute (MAX (attr->size, 1) * PANGO_SCALE);
+}
+
+static PangoAttribute *
+swfdec_text_attribute_create_underline (const SwfdecTextAttributes *attr)
+{
+ return pango_attr_underline_new (attr->underline ? PANGO_UNDERLINE_SINGLE : PANGO_UNDERLINE_NONE);
+}
+
+/*** THE BIG OPTIONS TABLE ***/
+
+typedef enum {
+ FORMAT_APPLY_UNKNOWN,
+ FORMAT_APPLY_BLOCK,
+ FORMAT_APPLY_LINE,
+ FORMAT_APPLY_GLYPH
+} FormatApplication;
+
+struct {
+ FormatApplication application;
+ PangoAttribute * (* create_attribute) (const SwfdecTextAttributes *attr);
+} format_table[] = {
+ /* unknown or unhandled properties */
+ [SWFDEC_TEXT_ATTRIBUTE_DISPLAY] = { FORMAT_APPLY_UNKNOWN, NULL },
+ [SWFDEC_TEXT_ATTRIBUTE_KERNING] = { FORMAT_APPLY_UNKNOWN, NULL },
+ /* per-paragraph options */
+ [SWFDEC_TEXT_ATTRIBUTE_BULLET] = { FORMAT_APPLY_BLOCK, NULL },
+ [SWFDEC_TEXT_ATTRIBUTE_INDENT] = { FORMAT_APPLY_BLOCK, NULL },
+ /* per-line options */
+ [SWFDEC_TEXT_ATTRIBUTE_ALIGN] = { FORMAT_APPLY_LINE, NULL },
+ [SWFDEC_TEXT_ATTRIBUTE_BLOCK_INDENT] = { FORMAT_APPLY_LINE, NULL },
+ [SWFDEC_TEXT_ATTRIBUTE_LEADING] = { FORMAT_APPLY_LINE, NULL },
+ [SWFDEC_TEXT_ATTRIBUTE_LEFT_MARGIN] = { FORMAT_APPLY_LINE, NULL },
+ [SWFDEC_TEXT_ATTRIBUTE_RIGHT_MARGIN] = { FORMAT_APPLY_LINE, NULL },
+ [SWFDEC_TEXT_ATTRIBUTE_TAB_STOPS] = { FORMAT_APPLY_LINE, NULL },
+ /* per-glyph options */
+ [SWFDEC_TEXT_ATTRIBUTE_BOLD] = { FORMAT_APPLY_GLYPH, swfdec_text_attribute_create_bold },
+ [SWFDEC_TEXT_ATTRIBUTE_COLOR] = { FORMAT_APPLY_GLYPH, swfdec_text_attribute_create_color },
+ [SWFDEC_TEXT_ATTRIBUTE_FONT] = { FORMAT_APPLY_GLYPH, swfdec_text_attribute_create_font },
+ [SWFDEC_TEXT_ATTRIBUTE_ITALIC] = { FORMAT_APPLY_GLYPH, swfdec_text_attribute_create_italic },
+ [SWFDEC_TEXT_ATTRIBUTE_LETTER_SPACING] = { FORMAT_APPLY_GLYPH, swfdec_text_attribute_create_letter_spacing },
+ [SWFDEC_TEXT_ATTRIBUTE_SIZE] = { FORMAT_APPLY_GLYPH, swfdec_text_attribute_create_size },
+ [SWFDEC_TEXT_ATTRIBUTE_TARGET] = { FORMAT_APPLY_GLYPH, NULL },
+ [SWFDEC_TEXT_ATTRIBUTE_UNDERLINE] = { FORMAT_APPLY_GLYPH, swfdec_text_attribute_create_underline },
+ [SWFDEC_TEXT_ATTRIBUTE_URL] = { FORMAT_APPLY_GLYPH, NULL }
+};
+
+#define SWFDEC_TEXT_ATTRIBUTES_MASK_NEW_BLOCK (\
+ (1 << SWFDEC_TEXT_ATTRIBUTE_ALIGN) | \
+ (1 << SWFDEC_TEXT_ATTRIBUTE_BLOCK_INDENT) | \
+ (1 << SWFDEC_TEXT_ATTRIBUTE_LEADING) | \
+ (1 << SWFDEC_TEXT_ATTRIBUTE_LEFT_MARGIN) | \
+ (1 << SWFDEC_TEXT_ATTRIBUTE_RIGHT_MARGIN) | \
+ (1 << SWFDEC_TEXT_ATTRIBUTE_TAB_STOPS))
+
+/*** BLOCK ***/
+
+/* A block is one vertical part of the layout that can be represented by exactly
+ * one PangoLayout. */
+
+typedef struct _SwfdecTextBlock SwfdecTextBlock;
+
+struct _SwfdecTextBlock {
+ PangoLayout * layout; /* the layout we render */
+ SwfdecRectangle rect; /* the area occupied by this layout */
+ guint row; /* index of start row */
+ gsize start; /* first character drawn */
+ gsize end; /* first character not drawn anymore */
+ gboolean bullet; /* TRUE if we need to draw a bullet in front of this layout */
+};
+
+static void
+swfdec_text_block_free (gpointer blockp)
+{
+ SwfdecTextBlock *block = blockp;
+
+ g_object_unref (block->layout);
+
+ g_slice_free (SwfdecTextBlock, block);
+}
+
+static SwfdecTextBlock *
+swfdec_text_block_new (PangoContext *context)
+{
+ SwfdecTextBlock *block;
+
+ block = g_slice_new0 (SwfdecTextBlock);
+ block->layout = pango_layout_new (context);
+ pango_layout_set_wrap (block->layout, PANGO_WRAP_WORD_CHAR);
+
+ return block;
+}
+
+/*** MAINTAINING THE LAYOUT ***/
+
+static void
+swfdec_text_layout_apply_paragraph_attributes (SwfdecTextLayout *layout,
+ SwfdecTextBlock *block, const SwfdecTextAttributes *attr)
+{
+ int indent;
+
+ /* SWFDEC_TEXT_ATTRIBUTE_BULLET */
+ block->bullet = attr->bullet;
+ if (block->bullet) {
+ block->rect.x += BULLET_MARGIN;
+ if (block->rect.width <= BULLET_MARGIN) {
+ SWFDEC_FIXME ("out of horizontal space, what now?");
+ block->rect.width = 0;
+ } else {
+ block->rect.width -= BULLET_MARGIN;
+ }
+ }
+
+ /* SWFDEC_TEXT_ATTRIBUTE_INDENT */
+ indent = attr->indent;
+ indent = MAX (indent, - attr->left_margin - attr->block_indent);
+ pango_layout_set_indent (block->layout, indent * PANGO_SCALE);
+}
+
+static void
+swfdec_text_layout_apply_line_attributes (SwfdecTextBlock *block,
+ const SwfdecTextAttributes *attr)
+{
+ /* SWFDEC_TEXT_ATTRIBUTE_ALIGN */
+ switch (attr->align) {
+ case SWFDEC_TEXT_ALIGN_LEFT:
+ pango_layout_set_alignment (block->layout, PANGO_ALIGN_LEFT);
+ pango_layout_set_justify (block->layout, FALSE);
+ break;
+ case SWFDEC_TEXT_ALIGN_RIGHT:
+ pango_layout_set_alignment (block->layout, PANGO_ALIGN_RIGHT);
+ pango_layout_set_justify (block->layout, FALSE);
+ break;
+ case SWFDEC_TEXT_ALIGN_CENTER:
+ pango_layout_set_alignment (block->layout, PANGO_ALIGN_CENTER);
+ pango_layout_set_justify (block->layout, FALSE);
+ break;
+ case SWFDEC_TEXT_ALIGN_JUSTIFY:
+ pango_layout_set_alignment (block->layout, PANGO_ALIGN_LEFT);
+ pango_layout_set_justify (block->layout, TRUE);
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+
+ /* SWFDEC_TEXT_ATTRIBUTE_BLOCK_INDENT */
+ /* SWFDEC_TEXT_ATTRIBUTE_LEFT_MARGIN */
+ /* SWFDEC_TEXT_ATTRIBUTE_RIGHT_MARGIN */
+ block->rect.x += attr->left_margin + attr->block_indent;
+ if (block->rect.width <= attr->left_margin + attr->block_indent + attr->right_margin) {
+ SWFDEC_FIXME ("out of horizontal space, what now?");
+ block->rect.width = 0;
+ } else {
+ block->rect.width -= attr->left_margin + attr->block_indent + attr->right_margin;
+ }
+
+ /* SWFDEC_TEXT_ATTRIBUTE_LEADING */
+ if (attr->leading > 0)
+ pango_layout_set_spacing (block->layout, attr->leading * PANGO_SCALE);
+ else
+ pango_layout_set_spacing (block->layout, (attr->leading - 1) * PANGO_SCALE);
+
+ /* SWFDEC_TEXT_ATTRIBUTE_TAB_STOPS */
+ if (attr->n_tab_stops != 0) {
+ PangoTabArray *tabs = pango_tab_array_new (attr->n_tab_stops, TRUE);
+ guint i;
+ for (i = 0; i < attr->n_tab_stops; i++) {
+ pango_tab_array_set_tab (tabs, i, PANGO_TAB_LEFT, attr->tab_stops[i]);
+ }
+ pango_layout_set_tabs (block->layout, tabs);
+ pango_tab_array_free (tabs);
+ }
+}
+
+static void
+swfdec_text_layout_apply_attributes (PangoAttrList *list, const SwfdecTextAttributes *attr,
+ guint start, guint end)
+{
+ PangoAttribute *attribute;
+ guint i;
+
+ for (i = 0; i < G_N_ELEMENTS (format_table); i++) {
+ if (format_table[i].create_attribute) {
+ attribute = format_table[i].create_attribute (attr);
+ attribute->start_index = start;
+ attribute->end_index = end;
+ pango_attr_list_change (list, attribute);
+ }
+ }
+}
+
+static const SwfdecTextBlock *
+swfdec_text_layout_create_paragraph (SwfdecTextLayout *layout, PangoContext *context,
+ const SwfdecTextBlock *last, gsize start, gsize end)
+{
+ SwfdecTextBufferIter *iter;
+ SwfdecTextBlock *block;
+ PangoAttrList *list;
+ const char *string;
+ const SwfdecTextAttributes *attr, *attr_next;
+ gsize new_block, start_next;
+ gboolean first = TRUE;
+ // TODO: kerning, display
+
+ string = swfdec_text_buffer_get_text (layout->text);
+ while (start != end) {
+ iter = swfdec_text_buffer_get_iter (layout->text, start);
+ attr = swfdec_text_buffer_iter_get_attributes (layout->text, iter);
+ new_block = end;
+
+ block = swfdec_text_block_new (context);
+ block->start = start;
+ block->rect.x = 0;
+ if (last) {
+ block->rect.y = last->rect.y + last->rect.height;
+ block->row = last->row + pango_layout_get_line_count (last->layout);
+ } else {
+ block->rect.y = 0;
+ block->row = 0;
+ }
+ if (layout->wrap_width == -1) {
+ block->rect.width = G_MAXINT;
+ } else {
+ block->rect.width = layout->wrap_width;
+ }
+ g_sequence_append (layout->blocks, block);
+
+ if (layout->password) {
+ /* requires sane line breaking so we can't just replace the text with * chars.
+ * A good idea might be using a custom font that replaces all chars upon
+ * rendering, so Pango still thinks it uses proper utf-8 */
+ SWFDEC_FIXME ("implement password handling.");
+ }
+ pango_layout_set_text (block->layout, string + start, end - start);
+
+ if (first) {
+ swfdec_text_layout_apply_paragraph_attributes (layout, block, attr);
+ first = FALSE;
+ }
+ swfdec_text_layout_apply_line_attributes (block, attr);
+ if (layout->wrap_width != -1)
+ pango_layout_set_width (block->layout, block->rect.width);
+
+ iter = swfdec_text_buffer_get_iter (layout->text, start);
+ attr = swfdec_text_buffer_iter_get_attributes (layout->text, iter);
+ list = pango_attr_list_new ();
+
+ while (start != end) {
+ g_assert (attr);
+ iter = swfdec_text_buffer_iter_next (layout->text, iter);
+ attr_next = iter ? swfdec_text_buffer_iter_get_attributes (layout->text, iter) : NULL;
+ start_next = iter ? swfdec_text_buffer_iter_get_start (layout->text, iter) :
+ swfdec_text_buffer_get_length (layout->text);
+ start_next = MIN (start_next, end);
+
+ swfdec_text_layout_apply_attributes (list, attr, start - block->start, start_next - block->start);
+
+ if (attr_next && new_block > start_next &&
+ (swfdec_text_attributes_diff (attr, attr_next) & SWFDEC_TEXT_ATTRIBUTES_MASK_NEW_BLOCK))
+ new_block = start_next;
+
+ attr = attr_next;
+ start = start_next;
+ }
+ pango_layout_set_attributes (block->layout, list);
+ pango_attr_list_unref (list);
+
+ if (new_block < end) {
+ int i;
+
+ for (i = 0; i < pango_layout_get_line_count (block->layout); i++) {
+ PangoLayoutLine *line = pango_layout_get_line_readonly (block->layout, i);
+ if ((gsize) line->start_index + line->length >= new_block) {
+ new_block = line->start_index + line->length;
+ /* I hope deleting lines actually works by removing text */
+ pango_layout_set_text (block->layout, string + start, new_block - start);
+ g_assert (i + 1 == pango_layout_get_line_count (block->layout));
+ break;
+ }
+ }
+ /* check that we have found a line */
+ g_assert (i < pango_layout_get_line_count (block->layout));
+ }
+
+ start = new_block;
+ pango_layout_get_pixel_size (block->layout, &block->rect.width, &block->rect.height);
+ /* add leading to last line, too */
+ block->rect.height += pango_layout_get_spacing (block->layout) / PANGO_SCALE;
+
+ last = block;
+ }
+
+ return last;
+}
+
+static void
+swfdec_text_layout_create (SwfdecTextLayout *layout)
+{
+ const char *p, *end, *string;
+ PangoContext *context;
+ PangoFontMap *map;
+ const SwfdecTextBlock *last = NULL;
+
+ map = pango_cairo_font_map_get_default ();
+ context = pango_cairo_font_map_create_context (PANGO_CAIRO_FONT_MAP (map));
+
+ p = string = swfdec_text_buffer_get_text (layout->text);
+ for (;;) {
+ end = strpbrk (p, "\r\n");
+ if (end == NULL) {
+ end = string + swfdec_text_buffer_get_length (layout->text);
+ }
+
+ last = swfdec_text_layout_create_paragraph (layout, context, last, p - string, end - string);
+
+ if (*end == '\0')
+ break;
+ p = end + 1;
+ }
+
+ g_object_unref (context);
+}
+
+static void
+swfdec_text_layout_ensure (SwfdecTextLayout *layout)
+{
+ if (!g_sequence_iter_is_end (g_sequence_get_begin_iter (layout->blocks)))
+ return;
+
+ if (swfdec_text_buffer_get_length (layout->text) == 0)
+ return;
+
+ swfdec_text_layout_create (layout);
+}
+
+static void
+swfdec_text_layout_invalidate (SwfdecTextLayout *layout)
+{
+ g_sequence_remove_range (g_sequence_get_begin_iter (layout->blocks),
+ g_sequence_get_end_iter (layout->blocks));
+ g_signal_emit (layout, signals[CHANGED], 0);
+}
+
+/*** LAYOUT ***/
+
+/* A layout represents the whole text of a TextFieldMovie, this includes the
+ * invisible parts. It also does not care about transformations.
+ * It's the job of the movie to take care of that. */
+G_DEFINE_TYPE (SwfdecTextLayout, swfdec_text_layout, G_TYPE_OBJECT)
+
+static void
+swfdec_text_layout_dispose (GObject *object)
+{
+ SwfdecTextLayout *layout = SWFDEC_TEXT_LAYOUT (object);
+
+ g_object_unref (layout->text);
+ layout->text = NULL;
+ g_sequence_free (layout->blocks);
+ layout->blocks = NULL;
+
+ G_OBJECT_CLASS (swfdec_text_layout_parent_class)->dispose (object);
+}
+
+static void
+swfdec_text_layout_class_init (SwfdecTextLayoutClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->dispose = swfdec_text_layout_dispose;
+
+ signals[CHANGED] = g_signal_new ("changed", G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+}
+
+static void
+swfdec_text_layout_init (SwfdecTextLayout *layout)
+{
+ layout->wrap_width = -1;
+ layout->blocks = g_sequence_new (swfdec_text_block_free);
+}
+
+SwfdecTextLayout *
+swfdec_text_layout_new (SwfdecTextBuffer *buffer)
+{
+ SwfdecTextLayout *layout;
+
+ g_return_val_if_fail (SWFDEC_IS_TEXT_BUFFER (buffer), NULL);
+
+ layout = g_object_new (SWFDEC_TYPE_TEXT_LAYOUT, NULL);
+ layout->text = g_object_ref (buffer);
+
+ return layout;
+}
+
+void
+swfdec_text_layout_set_wrap_width (SwfdecTextLayout *layout, int wrap_width)
+{
+ g_return_if_fail (SWFDEC_IS_TEXT_LAYOUT (layout));
+ g_return_if_fail (wrap_width >= -1);
+
+ if (layout->wrap_width == wrap_width)
+ return;
+
+ swfdec_text_layout_invalidate (layout);
+ layout->wrap_width = wrap_width;
+}
+
+int
+swfdec_text_layout_get_wrap_width (SwfdecTextLayout *layout)
+{
+ g_return_val_if_fail (SWFDEC_IS_TEXT_LAYOUT (layout), -1);
+
+ return layout->wrap_width;
+}
+
+void
+swfdec_text_layout_set_password (SwfdecTextLayout *layout, gboolean password)
+{
+ g_return_if_fail (SWFDEC_IS_TEXT_LAYOUT (layout));
+
+ if (layout->password == password)
+ return;
+
+ swfdec_text_layout_invalidate (layout);
+ layout->password = password;
+}
+
+guint
+swfdec_text_layout_get_n_rows (SwfdecTextLayout *layout)
+{
+ GSequenceIter *iter;
+ SwfdecTextBlock *block;
+
+ g_return_val_if_fail (SWFDEC_IS_TEXT_LAYOUT (layout), 0);
+
+ swfdec_text_layout_ensure (layout);
+
+ iter = g_sequence_iter_prev (g_sequence_get_end_iter (layout->blocks));
+ if (g_sequence_iter_is_end (iter))
+ return 0;
+
+ block = g_sequence_get (iter);
+ return block->row + pango_layout_get_line_count (block->layout);
+}
+
+gboolean
+swfdec_text_layout_get_password (SwfdecTextLayout *layout)
+{
+ g_return_val_if_fail (SWFDEC_IS_TEXT_LAYOUT (layout), FALSE);
+
+ return layout->password;
+}
+
+static GSequenceIter *
+swfdec_text_layout_find_row (SwfdecTextLayout *layout, guint row)
+{
+ GSequenceIter *begin, *end, *mid;
+ SwfdecTextBlock *cur;
+
+ begin = g_sequence_get_begin_iter (layout->blocks);
+ end = g_sequence_iter_prev (g_sequence_get_end_iter (layout->blocks));
+ while (begin != end) {
+ mid = g_sequence_range_get_midpoint (begin, end);
+ if (mid == begin)
+ mid = g_sequence_iter_next (mid);
+ cur = g_sequence_get (mid);
+ if (cur->row > row)
+ end = g_sequence_iter_prev (mid);
+ else
+ begin = mid;
+ }
+ return begin;
+}
+
+/**
+ * swfdec_text_layout_render:
+ * @layout: the layout to render
+ * @cr: the Cairo context to render to. The context will be transformed so that
+ * (0, 0) points to where the @row should be rendered.
+ * @ctrans: The color transform to apply.
+ * @row: index of the first row to render.
+ * @height: The height in pixels of the visible area.
+ * @inval: The invalid area.
+ *
+ * Renders the contents of the layout into the given Cairo context.
+ **/
+void
+swfdec_text_layout_render (SwfdecTextLayout *layout, cairo_t *cr,
+ const SwfdecColorTransform *ctrans, guint row, guint height,
+ const SwfdecRectangle *inval)
+{
+ GSequenceIter *iter;
+ SwfdecTextBlock *block;
+ PangoRectangle extents;
+ gboolean first_line = TRUE;
+
+ g_return_if_fail (SWFDEC_IS_TEXT_LAYOUT (layout));
+ g_return_if_fail (cr != NULL);
+ g_return_if_fail (ctrans != NULL);
+ g_return_if_fail (row < swfdec_text_layout_get_n_rows (layout));
+ g_return_if_fail (inval != NULL);
+
+ swfdec_text_layout_ensure (layout);
+
+ iter = swfdec_text_layout_find_row (layout, row);
+ block = g_sequence_get (iter);
+ row -= block->row;
+ while (!g_sequence_iter_is_end (iter)) {
+ block = g_sequence_get (iter);
+ pango_cairo_update_layout (cr, block->layout);
+ cairo_translate (cr, block->rect.x, 0);
+ if (block->bullet && row == 0) {
+ SWFDEC_FIXME ("render bullet");
+ }
+ for (;row < (guint) pango_layout_get_line_count (block->layout); row++) {
+ PangoLayoutLine *line = pango_layout_get_line_readonly (block->layout, row);
+
+ pango_layout_line_get_pixel_extents (line, NULL, &extents);
+ if (extents.height > (int) height && !first_line)
+ return;
+ first_line = FALSE;
+ cairo_translate (cr, 0, - extents.y);
+ pango_cairo_show_layout_line (cr, line);
+ height -= extents.height;
+ cairo_translate (cr, 0, extents.height + extents.y);
+ }
+ cairo_translate (cr, -block->rect.x, pango_layout_get_spacing (block->layout) / PANGO_SCALE);
+ row = 0;
+ iter = g_sequence_iter_next (iter);
+ }
+}
+
diff --git a/swfdec/swfdec_text_layout.h b/swfdec/swfdec_text_layout.h
new file mode 100644
index 0000000..cd68999
--- /dev/null
+++ b/swfdec/swfdec_text_layout.h
@@ -0,0 +1,79 @@
+/* Swfdec
+ * Copyright (C) 2006-2008 Benjamin Otte <otte at gnome.org>
+ * 2007 Pekka Lampila <pekka.lampila at iki.fi>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+
+#ifndef _SWFDEC_TEXT_LAYOUT_H_
+#define _SWFDEC_TEXT_LAYOUT_H_
+
+#include <swfdec_rectangle.h>
+#include <swfdec_renderer.h>
+#include <swfdec_text_buffer.h>
+
+G_BEGIN_DECLS
+
+typedef struct _SwfdecTextLayout SwfdecTextLayout;
+typedef struct _SwfdecTextLayoutClass SwfdecTextLayoutClass;
+
+#define SWFDEC_TYPE_TEXT_LAYOUT (swfdec_text_layout_get_type())
+#define SWFDEC_IS_TEXT_LAYOUT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SWFDEC_TYPE_TEXT_LAYOUT))
+#define SWFDEC_IS_TEXT_LAYOUT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SWFDEC_TYPE_TEXT_LAYOUT))
+#define SWFDEC_TEXT_LAYOUT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SWFDEC_TYPE_TEXT_LAYOUT, SwfdecTextLayout))
+#define SWFDEC_TEXT_LAYOUT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SWFDEC_TYPE_TEXT_LAYOUT, SwfdecTextLayoutClass))
+#define SWFDEC_TEXT_LAYOUT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SWFDEC_TYPE_TEXT_LAYOUT, SwfdecTextLayoutClass))
+
+struct _SwfdecTextLayout
+{
+ GObject object;
+
+ /* constant data */
+ SwfdecTextBuffer * text; /* the text we render */
+ int wrap_width; /* maximum width to use */
+ gboolean password; /* TRUE if the text should be displayed as asterisks */
+
+ /* layout data */
+ GSequence * blocks; /* ordered list of blocks */
+};
+
+struct _SwfdecTextLayoutClass
+{
+ GObjectClass object_class;
+};
+
+GType swfdec_text_layout_get_type (void);
+
+SwfdecTextLayout * swfdec_text_layout_new (SwfdecTextBuffer * buffer);
+
+void swfdec_text_layout_set_wrap_width (SwfdecTextLayout * layout,
+ int wrap_width);
+int swfdec_text_layout_get_wrap_width (SwfdecTextLayout * layout);
+void swfdec_text_layout_set_password (SwfdecTextLayout * layout,
+ gboolean password);
+gboolean swfdec_text_layout_get_password (SwfdecTextLayout * layout);
+guint swfdec_text_layout_get_n_rows (SwfdecTextLayout * layout);
+
+void swfdec_text_layout_render (SwfdecTextLayout * layout,
+ cairo_t * cr,
+ const SwfdecColorTransform *ctrans,
+ guint row,
+ guint height,
+ const SwfdecRectangle *inval);
+
+
+G_END_DECLS
+#endif
commit 9d6fc3d372011377a22eeb318aa2228118e17c21
Author: Benjamin Otte <otte at gnome.org>
Date: Wed May 7 12:24:09 2008 +0200
add another test
diff --git a/test/image/Makefile.am b/test/image/Makefile.am
index 43084df..375d9d7 100644
--- a/test/image/Makefile.am
+++ b/test/image/Makefile.am
@@ -377,7 +377,16 @@ EXTRA_DIST = \
text-field-autosize-7.swf.png \
text-field-autosize-8.swf \
text-field-autosize-8.swf.png \
- text-field-border-5.swf
+ text-field-background-5.swf \
+ text-field-background-5.swf.png \
+ text-field-background-6.swf \
+ text-field-background-6.swf.png \
+ text-field-background-7.swf \
+ text-field-background-7.swf.png \
+ text-field-background-8.swf \
+ text-field-background-8.swf.png \
+ text-field-background.as \
+ text-field-border-5.swf \
text-field-border-5.swf.png \
text-field-border-6.swf \
text-field-border-6.swf.png \
diff --git a/test/image/text-field-background-5.swf b/test/image/text-field-background-5.swf
new file mode 100644
index 0000000..6ef2f2c
Binary files /dev/null and b/test/image/text-field-background-5.swf differ
diff --git a/test/image/text-field-background-5.swf.png b/test/image/text-field-background-5.swf.png
new file mode 100644
index 0000000..3506302
Binary files /dev/null and b/test/image/text-field-background-5.swf.png differ
diff --git a/test/image/text-field-background-6.swf b/test/image/text-field-background-6.swf
new file mode 100644
index 0000000..6b2f06a
Binary files /dev/null and b/test/image/text-field-background-6.swf differ
diff --git a/test/image/text-field-background-6.swf.png b/test/image/text-field-background-6.swf.png
new file mode 100644
index 0000000..641cb9e
Binary files /dev/null and b/test/image/text-field-background-6.swf.png differ
diff --git a/test/image/text-field-background-7.swf b/test/image/text-field-background-7.swf
new file mode 100644
index 0000000..3fd128c
Binary files /dev/null and b/test/image/text-field-background-7.swf differ
diff --git a/test/image/text-field-background-7.swf.png b/test/image/text-field-background-7.swf.png
new file mode 100644
index 0000000..0345295
Binary files /dev/null and b/test/image/text-field-background-7.swf.png differ
diff --git a/test/image/text-field-background-8.swf b/test/image/text-field-background-8.swf
new file mode 100644
index 0000000..024a781
Binary files /dev/null and b/test/image/text-field-background-8.swf differ
diff --git a/test/image/text-field-background-8.swf.png b/test/image/text-field-background-8.swf.png
new file mode 100644
index 0000000..2922738
Binary files /dev/null and b/test/image/text-field-background-8.swf.png differ
diff --git a/test/image/text-field-background.as b/test/image/text-field-background.as
new file mode 100644
index 0000000..ca6c520
--- /dev/null
+++ b/test/image/text-field-background.as
@@ -0,0 +1,18 @@
+// makeswf -v 7 -s 200x150 -r 1 -o movie23.swf movie23.as
+
+function create (depth, x, y) {
+ var t = createTextField ("t" + depth, depth, x, y, 50, 25);
+ var t = this["t" + depth];
+ t.background = true;
+ t.backgroundColor = 0xFF0000;
+};
+
+create (0, 25, 25);
+t0.border = true;
+create (1, 100.5, 25);
+create (2, 25, 75);
+t2._y += 0.4;
+create (3, 100.5, 75);
+t3._y += 0.5;
+t3.border = true;
+
commit 07a9f1b43eb99757febe93ea0f17c8b4cb3c8d7f
Author: Benjamin Otte <otte at gnome.org>
Date: Wed May 7 12:22:56 2008 +0200
add a test about border handling
diff --git a/test/image/Makefile.am b/test/image/Makefile.am
index df1ee06..43084df 100644
--- a/test/image/Makefile.am
+++ b/test/image/Makefile.am
@@ -377,6 +377,15 @@ EXTRA_DIST = \
text-field-autosize-7.swf.png \
text-field-autosize-8.swf \
text-field-autosize-8.swf.png \
+ text-field-border-5.swf
+ text-field-border-5.swf.png \
+ text-field-border-6.swf \
+ text-field-border-6.swf.png \
+ text-field-border-7.swf \
+ text-field-border-7.swf.png \
+ text-field-border-8.swf \
+ text-field-border-8.swf.png \
+ text-field-border.as \
text-field-color-transform.as \
text-field-color-transform-6.swf \
text-field-color-transform-6.swf.png \
diff --git a/test/image/text-field-border-5.swf b/test/image/text-field-border-5.swf
new file mode 100644
index 0000000..fd2969f
Binary files /dev/null and b/test/image/text-field-border-5.swf differ
diff --git a/test/image/text-field-border-5.swf.png b/test/image/text-field-border-5.swf.png
new file mode 100644
index 0000000..66130d9
Binary files /dev/null and b/test/image/text-field-border-5.swf.png differ
diff --git a/test/image/text-field-border-6.swf b/test/image/text-field-border-6.swf
new file mode 100644
index 0000000..c0d6e2a
Binary files /dev/null and b/test/image/text-field-border-6.swf differ
diff --git a/test/image/text-field-border-6.swf.png b/test/image/text-field-border-6.swf.png
new file mode 100644
index 0000000..63a2a4b
Binary files /dev/null and b/test/image/text-field-border-6.swf.png differ
diff --git a/test/image/text-field-border-7.swf b/test/image/text-field-border-7.swf
new file mode 100644
index 0000000..58cfbc8
Binary files /dev/null and b/test/image/text-field-border-7.swf differ
diff --git a/test/image/text-field-border-7.swf.png b/test/image/text-field-border-7.swf.png
new file mode 100644
index 0000000..d880762
Binary files /dev/null and b/test/image/text-field-border-7.swf.png differ
diff --git a/test/image/text-field-border-8.swf b/test/image/text-field-border-8.swf
new file mode 100644
index 0000000..4149111
Binary files /dev/null and b/test/image/text-field-border-8.swf differ
diff --git a/test/image/text-field-border-8.swf.png b/test/image/text-field-border-8.swf.png
new file mode 100644
index 0000000..5f05547
Binary files /dev/null and b/test/image/text-field-border-8.swf.png differ
diff --git a/test/image/text-field-border.as b/test/image/text-field-border.as
new file mode 100644
index 0000000..c435c1d
--- /dev/null
+++ b/test/image/text-field-border.as
@@ -0,0 +1,15 @@
+// makeswf -v 7 -s 200x150 -r 1 -o text-field-border.swf text-field-border.as
+
+function create (depth, x, y) {
+ var t = createTextField ("t" + depth, depth, x, y, 50, 25);
+ t.border = true;
+ t.borderColor = 0;
+};
+
+create (0, 25, 25);
+create (1, 100.5, 25);
+create (2, 25, 75);
+t2._y += 0.4;
+create (3, 100.5, 75);
+t3._y += 0.5;
+
commit 057773835d9d4ea87a86a555988fdbce5ecf31ff
Author: Benjamin Otte <otte at gnome.org>
Date: Mon May 5 19:16:59 2008 +0200
add a text-changed signal
also contains some obvious bugfixes
diff --git a/swfdec/swfdec_text_buffer.c b/swfdec/swfdec_text_buffer.c
index 5efd95f..afd0af7 100644
--- a/swfdec/swfdec_text_buffer.c
+++ b/swfdec/swfdec_text_buffer.c
@@ -55,6 +55,7 @@ swfdec_text_buffer_format_free (SwfdecTextBufferFormat *format)
/*** OBJECT ***/
enum {
+ TEXT_CHANGED,
CURSOR_CHANGED,
LAST_SIGNAL
};
@@ -84,6 +85,9 @@ swfdec_text_buffer_class_init (SwfdecTextBufferClass *klass)
object_class->dispose = swfdec_text_buffer_dispose;
+ signals[TEXT_CHANGED] = g_signal_new ("text-changed", G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
signals[CURSOR_CHANGED] = g_signal_new ("cursor-changed", G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST, 0, NULL, NULL, swfdec_marshal_VOID__ULONG_ULONG,
G_TYPE_NONE, 2, G_TYPE_ULONG, G_TYPE_ULONG);
@@ -156,6 +160,8 @@ swfdec_text_buffer_insert_text (SwfdecTextBuffer *buffer,
g_return_if_fail (text != NULL);
len = strlen (text);
+ if (len == 0)
+ return;
g_string_insert_len (buffer->text, pos, text, len);
iter = g_sequence_get_end_iter (buffer->attributes);
for (;;) {
@@ -171,7 +177,11 @@ swfdec_text_buffer_insert_text (SwfdecTextBuffer *buffer,
buffer->cursor_start += len;
if (buffer->cursor_end >= pos)
buffer->cursor_end += len;
- /* FIXME: emit cursor-changed signal? */
+
+ g_signal_emit (buffer, signals[TEXT_CHANGED], 0);
+ g_signal_emit (buffer, signals[CURSOR_CHANGED], 0,
+ (gulong) MIN (buffer->cursor_start, buffer->cursor_end),
+ (gulong) MAX (buffer->cursor_start, buffer->cursor_end));
}
/* removes duplicates in the range [iter, end) */
@@ -236,7 +246,11 @@ swfdec_text_buffer_delete_text (SwfdecTextBuffer *buffer,
buffer->cursor_end -= length;
else if (buffer->cursor_end > pos)
buffer->cursor_end = pos;
- /* FIXME: emit cursor-changed signal? */
+
+ g_signal_emit (buffer, signals[TEXT_CHANGED], 0);
+ g_signal_emit (buffer, signals[CURSOR_CHANGED], 0,
+ (gulong) MIN (buffer->cursor_start, buffer->cursor_end),
+ (gulong) MAX (buffer->cursor_start, buffer->cursor_end));
}
const char *
@@ -352,6 +366,8 @@ swfdec_text_buffer_set_attributes (SwfdecTextBuffer *buffer, gsize start,
}
swfdec_text_attributes_copy (&format->attr, attr, mask);
swfdec_text_buffer_remove_duplicates (start_iter, iter);
+
+ g_signal_emit (buffer, signals[TEXT_CHANGED], 0);
}
/*** ITERATOR ***/
@@ -441,7 +457,7 @@ swfdec_text_buffer_set_cursor (SwfdecTextBuffer *buffer, gsize start, gsize end)
buffer->cursor_start = start;
buffer->cursor_end = end;
- g_signal_emit (buffer, signals[CURSOR_CHANGED],
+ g_signal_emit (buffer, signals[CURSOR_CHANGED], 0,
(gulong) MIN (buffer->cursor_start, buffer->cursor_end),
(gulong) MAX (buffer->cursor_start, buffer->cursor_end));
}
diff --git a/swfdec/swfdec_text_field_movie.c b/swfdec/swfdec_text_field_movie.c
index 44bbcc3..62bd5a4 100644
--- a/swfdec/swfdec_text_field_movie.c
+++ b/swfdec/swfdec_text_field_movie.c
@@ -1529,12 +1529,6 @@ swfdec_text_field_movie_focus_out (SwfdecActor *actor)
}
static void
-swfdec_text_field_movie_changed (SwfdecTextFieldMovie *text)
-{
- text->changed++;
-}
-
-static void
swfdec_text_field_movie_key_press (SwfdecActor *actor, guint keycode, guint character)
{
SwfdecTextFieldMovie *text = SWFDEC_TEXT_FIELD_MOVIE (actor);
@@ -1543,7 +1537,7 @@ swfdec_text_field_movie_key_press (SwfdecActor *actor, guint keycode, guint char
gsize start, end;
const char *string;
#define BACKWARD(text, _index) ((_index) == 0 ? 0 : (gsize) (g_utf8_prev_char ((text) + (_index)) - (text)))
-#define FORWARD(text, _index) ((text)[0] == 0 ? (_index) : (gsize) (g_utf8_next_char ((text) + (_index)) - (text)))
+#define FORWARD(text, _index) ((text)[_index] == 0 ? (_index) : (gsize) (g_utf8_next_char ((text) + (_index)) - (text)))
if (!text->editable)
return;
@@ -1574,7 +1568,6 @@ swfdec_text_field_movie_key_press (SwfdecActor *actor, guint keycode, guint char
}
if (start != end) {
swfdec_text_buffer_delete_text (text->text, start, end - start);
- swfdec_text_field_movie_changed (text);
}
return;
case SWFDEC_KEY_DELETE:
@@ -1583,7 +1576,6 @@ swfdec_text_field_movie_key_press (SwfdecActor *actor, guint keycode, guint char
}
if (start != end) {
swfdec_text_buffer_delete_text (text->text, start, end - start);
- swfdec_text_field_movie_changed (text);
}
return;
default:
@@ -1598,7 +1590,6 @@ swfdec_text_field_movie_key_press (SwfdecActor *actor, guint keycode, guint char
if (start != end)
swfdec_text_buffer_delete_text (text->text, start, end - start);
swfdec_text_buffer_insert_text (text->text, start, insert);
- swfdec_text_field_movie_changed (text);
}
}
@@ -1641,6 +1632,14 @@ swfdec_text_field_movie_class_init (SwfdecTextFieldMovieClass * g_class)
}
static void
+swfdec_text_field_movie_text_changed (SwfdecTextBuffer *buffer,
+ SwfdecTextFieldMovie *text)
+{
+ swfdec_movie_invalidate_last (SWFDEC_MOVIE (text));
+ text->changed++;
+}
+
+static void
swfdec_text_field_movie_cursor_changed (SwfdecTextBuffer *buffer,
gulong start, gulong end, SwfdecTextFieldMovie *text)
{
@@ -1654,6 +1653,8 @@ swfdec_text_field_movie_init (SwfdecTextFieldMovie *text)
text->text = swfdec_text_buffer_new ();
g_signal_connect (text->text, "cursor-changed",
G_CALLBACK (swfdec_text_field_movie_cursor_changed), text);
+ g_signal_connect (text->text, "text-changed",
+ G_CALLBACK (swfdec_text_field_movie_text_changed), text);
text->scroll = 1;
text->mouse_wheel_enabled = TRUE;
commit 986bbac09c5b280415628f7c6e854647ffa5db35
Author: Benjamin Otte <otte at gnome.org>
Date: Mon May 5 19:01:01 2008 +0200
split text handling into its own object - SwfdecTextBuffer
diff --git a/swfdec/Makefile.am b/swfdec/Makefile.am
index 9b743a7..c91612f 100644
--- a/swfdec/Makefile.am
+++ b/swfdec/Makefile.am
@@ -147,6 +147,7 @@ libswfdec_source_files = \
swfdec_tag.c \
swfdec_text.c \
swfdec_text_attributes.c \
+ swfdec_text_buffer.c \
swfdec_text_field.c \
swfdec_text_field_movie.c \
swfdec_text_field_movie_as.c \
@@ -295,6 +296,7 @@ noinst_HEADERS = \
swfdec_tag.h \
swfdec_text.h \
swfdec_text_attributes.h \
+ swfdec_text_buffer.h \
swfdec_text_format.h \
swfdec_types.h \
swfdec_utils.h \
diff --git a/swfdec/swfdec_marshal.list b/swfdec/swfdec_marshal.list
index 5aeeb44..20eba3c 100644
--- a/swfdec/swfdec_marshal.list
+++ b/swfdec/swfdec_marshal.list
@@ -4,3 +4,4 @@ VOID:BOXED,POINTER,UINT
VOID:ENUM,STRING,STRING,BOXED
VOID:STRING,STRING
VOID:ULONG,UINT
+VOID:ULONG,ULONG
diff --git a/swfdec/swfdec_text_buffer.c b/swfdec/swfdec_text_buffer.c
new file mode 100644
index 0000000..5efd95f
--- /dev/null
+++ b/swfdec/swfdec_text_buffer.c
@@ -0,0 +1,448 @@
+/* Swfdec
+ * Copyright (C) 2006-2008 Benjamin Otte <otte at gnome.org>
+ * 2007 Pekka Lampila <pekka.lampila at iki.fi>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+
+#include "swfdec_text_buffer.h"
+#include "swfdec_debug.h"
+#include "swfdec_marshal.h"
+
+typedef struct _SwfdecTextBufferFormat SwfdecTextBufferFormat;
+
+struct _SwfdecTextBufferFormat {
+ guint start;
+ SwfdecTextAttributes attr;
+};
+
+static SwfdecTextBufferFormat *
+swfdec_text_buffer_format_new (void)
+{
+ SwfdecTextBufferFormat *format;
+
+ format = g_slice_new0 (SwfdecTextBufferFormat);
+ swfdec_text_attributes_reset (&format->attr);
+ return format;
+}
+
+static void
+swfdec_text_buffer_format_free (SwfdecTextBufferFormat *format)
+{
+ swfdec_text_attributes_reset (&format->attr);
+ g_slice_free (SwfdecTextBufferFormat, format);
+}
+
+/*** OBJECT ***/
+
+enum {
+ CURSOR_CHANGED,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0, };
+
+G_DEFINE_TYPE (SwfdecTextBuffer, swfdec_text_buffer, G_TYPE_OBJECT)
+
+static void
+swfdec_text_buffer_dispose (GObject *object)
+{
+ SwfdecTextBuffer *buffer = SWFDEC_TEXT_BUFFER (object);
+
+ if (buffer->text != NULL) {
+ g_string_free (buffer->text, TRUE);
+ buffer->text = NULL;
+ }
+ g_sequence_free (buffer->attributes);
+
+ G_OBJECT_CLASS (swfdec_text_buffer_parent_class)->dispose (object);
+}
+
+static void
+swfdec_text_buffer_class_init (SwfdecTextBufferClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->dispose = swfdec_text_buffer_dispose;
+
+ signals[CURSOR_CHANGED] = g_signal_new ("cursor-changed", G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST, 0, NULL, NULL, swfdec_marshal_VOID__ULONG_ULONG,
+ G_TYPE_NONE, 2, G_TYPE_ULONG, G_TYPE_ULONG);
+}
+
+static void
+swfdec_text_buffer_init (SwfdecTextBuffer *text)
+{
+ text->text = g_string_new ("");
+ text->attributes = g_sequence_new ((GDestroyNotify) swfdec_text_buffer_format_free);
+ g_sequence_append (text->attributes, swfdec_text_buffer_format_new ());
+}
+
+SwfdecTextBuffer *
+swfdec_text_buffer_new (void)
+{
+ return g_object_new (SWFDEC_TYPE_TEXT_BUFFER, NULL);
+}
+
+static void
+swfdec_text_buffer_mark_one (gpointer entry, gpointer unused)
+{
+ SwfdecTextBufferFormat *format = entry;
+
+ swfdec_text_attributes_mark (&format->attr);
+}
+
+void
+swfdec_text_buffer_mark (SwfdecTextBuffer *buffer)
+{
+ g_return_if_fail (SWFDEC_IS_TEXT_BUFFER (buffer));
+
+ g_sequence_foreach (buffer->attributes, swfdec_text_buffer_mark_one, NULL);
+}
+
+static int
+swfdec_text_buffer_format_compare (gconstpointer a, gconstpointer b, gpointer unused)
+{
+ return ((const SwfdecTextBufferFormat *) a)->start -
+ ((const SwfdecTextBufferFormat *) b)->start;
+}
+
+/* return iter to format relevant for position, that is the format pointed to
+ * by iter will have a lower or equal start index than pos */
+static GSequenceIter *
+swfdec_text_buffer_get_iter_for_pos (SwfdecTextBuffer *buffer, guint pos)
+{
+ SwfdecTextBufferFormat format = { pos, };
+ GSequenceIter *iter;
+
+ iter = g_sequence_search (buffer->attributes, &format,
+ swfdec_text_buffer_format_compare, NULL);
+ if (g_sequence_iter_is_end (iter) ||
+ ((SwfdecTextBufferFormat *) g_sequence_get (iter))->start > pos)
+ iter = g_sequence_iter_prev (iter);
+
+ return iter;
+}
+
+void
+swfdec_text_buffer_insert_text (SwfdecTextBuffer *buffer,
+ gsize pos, const char *text)
+{
+ gsize len;
+ GSequenceIter *iter;
+ SwfdecTextBufferFormat *format;
+
+ g_return_if_fail (SWFDEC_IS_TEXT_BUFFER (buffer));
+ g_return_if_fail (pos <= buffer->text->len);
+ g_return_if_fail (text != NULL);
+
+ len = strlen (text);
+ g_string_insert_len (buffer->text, pos, text, len);
+ iter = g_sequence_get_end_iter (buffer->attributes);
+ for (;;) {
+ iter = g_sequence_iter_prev (iter);
+ format = g_sequence_get (iter);
+ if (format->start <= pos)
+ break;
+ format->start += len;
+ }
+
+ /* adapt cursor */
+ if (buffer->cursor_start >= pos)
+ buffer->cursor_start += len;
+ if (buffer->cursor_end >= pos)
+ buffer->cursor_end += len;
+ /* FIXME: emit cursor-changed signal? */
+}
+
+/* removes duplicates in the range [iter, end) */
+static void
+swfdec_text_buffer_remove_duplicates (GSequenceIter *iter, GSequenceIter *end)
+{
+ SwfdecTextBufferFormat *format, *next;
+
+ g_assert (iter != end);
+
+ format = g_sequence_get (iter);
+ for (iter = g_sequence_iter_next (iter); iter != end; iter = g_sequence_iter_next (iter)) {
+ next = g_sequence_get (iter);
+ if (swfdec_text_attributes_diff (&format->attr, &next->attr) == 0) {
+ GSequenceIter *prev = g_sequence_iter_prev (iter);
+ g_sequence_remove (iter);
+ iter = prev;
+ } else {
+ format = next;
+ }
+ }
+}
+
+void
+swfdec_text_buffer_delete_text (SwfdecTextBuffer *buffer,
+ gsize pos, gsize length)
+{
+ GSequenceIter *iter, *prev;
+ SwfdecTextBufferFormat *format;
+ gsize end;
+
+ g_return_if_fail (SWFDEC_IS_TEXT_BUFFER (buffer));
+ g_return_if_fail (pos + length <= buffer->text->len);
+ g_return_if_fail (length > 0);
+
+ g_string_erase (buffer->text, pos, length);
+ end = pos + length;
+ iter = g_sequence_get_end_iter (buffer->attributes);
+ for (;;) {
+ iter = g_sequence_iter_prev (iter);
+ format = g_sequence_get (iter);
+ if (format->start <= end) {
+ format->start = pos;
+ break;
+ }
+ format->start -= length;
+ }
+ while (!g_sequence_iter_is_begin (iter)) {
+ prev = g_sequence_iter_prev (iter);
+ format = g_sequence_get (prev);
+ if (format->start < pos)
+ break;
+ g_sequence_remove (prev);
+ }
+
+ /* adapt cursor */
+ if (buffer->cursor_start > end)
+ buffer->cursor_start -= length;
+ else if (buffer->cursor_start > pos)
+ buffer->cursor_start = pos;
+ if (buffer->cursor_end > end)
+ buffer->cursor_end -= length;
+ else if (buffer->cursor_end > pos)
+ buffer->cursor_end = pos;
+ /* FIXME: emit cursor-changed signal? */
+}
+
+const char *
+swfdec_text_buffer_get_text (SwfdecTextBuffer *buffer)
+{
+ g_return_val_if_fail (SWFDEC_IS_TEXT_BUFFER (buffer), NULL);
+
+ return buffer->text->str;
+}
+
+gsize
+swfdec_text_buffer_get_length (SwfdecTextBuffer *buffer)
+{
+ g_return_val_if_fail (SWFDEC_IS_TEXT_BUFFER (buffer), 0);
+
+ return buffer->text->len;
+}
+
+const SwfdecTextAttributes *
+swfdec_text_buffer_get_attributes (SwfdecTextBuffer *buffer, gsize pos)
+{
+ GSequenceIter *iter;
+ SwfdecTextBufferFormat *format;
+
+ g_return_val_if_fail (SWFDEC_IS_TEXT_BUFFER (buffer), NULL);
+ g_return_val_if_fail (pos <= buffer->text->len, NULL);
+
+ iter = swfdec_text_buffer_get_iter_for_pos (buffer, pos);
+ format = g_sequence_get (iter);
+ return &format->attr;
+}
+
+guint
+swfdec_text_buffer_get_unique (SwfdecTextBuffer *buffer,
+ gsize start, gsize length)
+{
+ guint result = SWFDEC_TEXT_ATTRIBUTES_MASK;
+ SwfdecTextBufferFormat *format, *cur;
+ GSequenceIter *iter;
+ gsize end;
+
+ g_return_val_if_fail (SWFDEC_IS_TEXT_BUFFER (buffer), 0);
+ g_return_val_if_fail (start + length <= buffer->text->len, 0);
+
+ end = start + length;
+ iter = swfdec_text_buffer_get_iter_for_pos (buffer, start);
+ format = g_sequence_get (iter);
+ for (iter = g_sequence_iter_next (iter); !g_sequence_iter_is_end (iter); iter = g_sequence_iter_next (iter)) {
+ cur = g_sequence_get (iter);
+ if (cur->start >= end)
+ break;
+ result &= ~swfdec_text_attributes_diff (&format->attr, &cur->attr);
+ }
+
+ return result;
+}
+
+static GSequenceIter *
+swfdec_text_buffer_copy_format (SwfdecTextBuffer *buffer, GSequenceIter *iter,
+ gsize pos)
+{
+ SwfdecTextBufferFormat *format, *new_format;
+
+ format = g_sequence_get (iter);
+ new_format = swfdec_text_buffer_format_new ();
+ new_format->start = pos;
+ swfdec_text_attributes_copy (&new_format->attr, &format->attr,
+ SWFDEC_TEXT_ATTRIBUTES_MASK);
+ return g_sequence_insert_before (g_sequence_iter_next (iter), new_format);
+}
+
+void
+swfdec_text_buffer_set_attributes (SwfdecTextBuffer *buffer, gsize start,
+ gsize length, const SwfdecTextAttributes *attr, guint mask)
+{
+ SwfdecTextBufferFormat *format;
+ GSequenceIter *start_iter, *iter;
+ gsize end;
+ gboolean need_new_format, last;
+
+ g_return_if_fail (SWFDEC_IS_TEXT_BUFFER (buffer));
+ g_return_if_fail (start + length <= buffer->text->len);
+ g_return_if_fail (length > 0 || start == buffer->text->len);
+ g_return_if_fail (attr != NULL);
+ g_return_if_fail (mask != 0);
+
+ end = start + length;
+ start_iter = swfdec_text_buffer_get_iter_for_pos (buffer, start);
+ format = g_sequence_get (start_iter);
+ if (format->start < start) {
+ iter = swfdec_text_buffer_copy_format (buffer, start_iter, start);
+ } else {
+ iter = start_iter;
+ }
+ last = FALSE;
+ for (;;) {
+ format = g_sequence_get (iter);
+ iter = g_sequence_iter_next (iter);
+ if (g_sequence_iter_is_end (iter)) {
+ need_new_format = end < buffer->text->len;
+ last = TRUE;
+ } else {
+ SwfdecTextBufferFormat *next = g_sequence_get (iter);
+ need_new_format = next->start > end;
+ last = next->start >= end;
+ }
+ if (last)
+ break;
+ swfdec_text_attributes_copy (&format->attr, attr, mask);
+ }
+ if (need_new_format) {
+ swfdec_text_buffer_copy_format (buffer, g_sequence_iter_prev (iter), end);
+ }
+ swfdec_text_attributes_copy (&format->attr, attr, mask);
+ swfdec_text_buffer_remove_duplicates (start_iter, iter);
+}
+
+/*** ITERATOR ***/
+
+SwfdecTextBufferIter *
+swfdec_text_buffer_get_iter (SwfdecTextBuffer *buffer, gsize pos)
+{
+ g_return_val_if_fail (SWFDEC_IS_TEXT_BUFFER (buffer), NULL);
+ g_return_val_if_fail (pos <= buffer->text->len, NULL);
+
+ return swfdec_text_buffer_get_iter_for_pos (buffer, pos);
+}
+
+SwfdecTextBufferIter *
+swfdec_text_buffer_iter_next (SwfdecTextBuffer *buffer, SwfdecTextBufferIter *iter)
+{
+ g_return_val_if_fail (SWFDEC_IS_TEXT_BUFFER (buffer), NULL);
+ g_return_val_if_fail (iter != NULL, NULL);
+
+ iter = g_sequence_iter_next (iter);
+ return g_sequence_iter_is_end (iter) ? NULL : iter;
+}
+
+const SwfdecTextAttributes *
+swfdec_text_buffer_iter_get_attributes (SwfdecTextBuffer *buffer, SwfdecTextBufferIter *iter)
+{
+ SwfdecTextBufferFormat *format;
+
+ g_return_val_if_fail (SWFDEC_IS_TEXT_BUFFER (buffer), NULL);
+ g_return_val_if_fail (iter != NULL, NULL);
+
+ format = g_sequence_get (iter);
+ return &format->attr;
+}
+
+gsize
+swfdec_text_buffer_iter_get_start (SwfdecTextBuffer *buffer, SwfdecTextBufferIter *iter)
+{
+ SwfdecTextBufferFormat *format;
+
+ g_return_val_if_fail (SWFDEC_IS_TEXT_BUFFER (buffer), 0);
+ g_return_val_if_fail (iter != NULL, 0);
+
+ format = g_sequence_get (iter);
+ return format->start;
+}
+
+/*** CURSOR API ***/
+
+gsize
+swfdec_text_buffer_get_cursor (SwfdecTextBuffer *buffer)
+{
+ g_return_val_if_fail (SWFDEC_IS_TEXT_BUFFER (buffer), 0);
+
+ return buffer->cursor_start;
+}
+
+gboolean
+swfdec_text_buffer_has_selection (SwfdecTextBuffer *buffer)
+{
+ g_return_val_if_fail (SWFDEC_IS_TEXT_BUFFER (buffer), FALSE);
+
+ return buffer->cursor_start != buffer->cursor_end;
+}
+
+void
+swfdec_text_buffer_get_selection (SwfdecTextBuffer *buffer, gsize *start, gsize *end)
+{
+ g_return_if_fail (SWFDEC_IS_TEXT_BUFFER (buffer));
+
+ if (start)
+ *start = MIN (buffer->cursor_start, buffer->cursor_end);
+ if (end)
+ *end = MAX (buffer->cursor_start, buffer->cursor_end);
+}
+
+void
+swfdec_text_buffer_set_cursor (SwfdecTextBuffer *buffer, gsize start, gsize end)
+{
+ g_return_if_fail (SWFDEC_IS_TEXT_BUFFER (buffer));
+ g_return_if_fail (start <= swfdec_text_buffer_get_length (buffer));
+ g_return_if_fail (end <= swfdec_text_buffer_get_length (buffer));
+
+ if (buffer->cursor_start == start &&
+ buffer->cursor_end == end)
+ return;
+
+ buffer->cursor_start = start;
+ buffer->cursor_end = end;
+ g_signal_emit (buffer, signals[CURSOR_CHANGED],
+ (gulong) MIN (buffer->cursor_start, buffer->cursor_end),
+ (gulong) MAX (buffer->cursor_start, buffer->cursor_end));
+}
+
diff --git a/swfdec/swfdec_text_buffer.h b/swfdec/swfdec_text_buffer.h
new file mode 100644
index 0000000..6dc661b
--- /dev/null
+++ b/swfdec/swfdec_text_buffer.h
@@ -0,0 +1,104 @@
+/* Swfdec
+ * Copyright (C) 2006-2008 Benjamin Otte <otte at gnome.org>
+ * 2007 Pekka Lampila <pekka.lampila at iki.fi>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+
+#ifndef _SWFDEC_TEXT_BUFFER_H_
+#define _SWFDEC_TEXT_BUFFER_H_
+
+#include <glib-object.h>
+#include <swfdec/swfdec_text_attributes.h>
+
+G_BEGIN_DECLS
+
+typedef struct _SwfdecTextBuffer SwfdecTextBuffer;
+typedef GSequenceIter SwfdecTextBufferIter;
+typedef struct _SwfdecTextBufferClass SwfdecTextBufferClass;
+
+#define SWFDEC_TYPE_TEXT_BUFFER (swfdec_text_buffer_get_type())
+#define SWFDEC_IS_TEXT_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SWFDEC_TYPE_TEXT_BUFFER))
+#define SWFDEC_IS_TEXT_BUFFER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SWFDEC_TYPE_TEXT_BUFFER))
+#define SWFDEC_TEXT_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SWFDEC_TYPE_TEXT_BUFFER, SwfdecTextBuffer))
+#define SWFDEC_TEXT_BUFFER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SWFDEC_TYPE_TEXT_BUFFER, SwfdecTextBufferClass))
+
+struct _SwfdecTextBuffer
+{
+ GObject object;
+
+ GString * text; /* the text in this buffer */
+ GSequence * attributes; /* the attributes that apply to this text */
+
+ gsize cursor_start; /* byte offset into text for start of cursor */
+ gsize cursor_end; /* if some text is selected smaller or bigger */
+};
+
+struct _SwfdecTextBufferClass
+{
+ GObjectClass object_class;
+};
+
+GType swfdec_text_buffer_get_type (void);
+
+SwfdecTextBuffer * swfdec_text_buffer_new (void);
+void swfdec_text_buffer_mark (SwfdecTextBuffer * buffer);
+
+void swfdec_text_buffer_insert_text (SwfdecTextBuffer * buffer,
+ gsize pos,
+ const char * text);
+#define swfdec_text_buffer_append_text(buffer, text) \
+ swfdec_text_buffer_insert_text ((buffer), swfdec_text_buffer_get_length (buffer), (text));
+void swfdec_text_buffer_delete_text (SwfdecTextBuffer * buffer,
+ gsize pos,
+ gsize length);
+
+const char * swfdec_text_buffer_get_text (SwfdecTextBuffer * buffer);
+gsize swfdec_text_buffer_get_length (SwfdecTextBuffer * buffer);
+const SwfdecTextAttributes *
+ swfdec_text_buffer_get_attributes (SwfdecTextBuffer * buffer,
+ gsize pos);
+void swfdec_text_buffer_set_attributes (SwfdecTextBuffer * buffer,
+ gsize start,
+ gsize length,
+ const SwfdecTextAttributes *attr,
+ guint mask);
+guint swfdec_text_buffer_get_unique (SwfdecTextBuffer * buffer,
+ gsize start,
+ gsize length);
+
+SwfdecTextBufferIter * swfdec_text_buffer_get_iter (SwfdecTextBuffer * buffer,
+ gsize pos);
+SwfdecTextBufferIter * swfdec_text_buffer_iter_next (SwfdecTextBuffer * buffer,
+ SwfdecTextBufferIter * iter);
+const SwfdecTextAttributes *
+ swfdec_text_buffer_iter_get_attributes (SwfdecTextBuffer * buffer,
+ SwfdecTextBufferIter * iter);
+gsize swfdec_text_buffer_iter_get_start (SwfdecTextBuffer * buffer,
+ SwfdecTextBufferIter * iter);
+
+gsize swfdec_text_buffer_get_cursor (SwfdecTextBuffer * buffer);
+gboolean swfdec_text_buffer_has_selection (SwfdecTextBuffer * buffer);
+void swfdec_text_buffer_get_selection (SwfdecTextBuffer * buffer,
+ gsize * start,
+ gsize * end);
+void swfdec_text_buffer_set_cursor (SwfdecTextBuffer * buffer,
+ gsize start,
+ gsize end);
+
+
+G_END_DECLS
+#endif
diff --git a/swfdec/swfdec_text_field_movie.c b/swfdec/swfdec_text_field_movie.c
index dfb64fe..44bbcc3 100644
--- a/swfdec/swfdec_text_field_movie.c
+++ b/swfdec/swfdec_text_field_movie.c
@@ -1,5 +1,5 @@
/* Swfdec
- * Copyright (C) 2006 Benjamin Otte <otte at gnome.org>
+ * Copyright (C) 2006-2008 Benjamin Otte <otte at gnome.org>
* 2007 Pekka Lampila <pekka.lampila at iki.fi>
*
* This library is free software; you can redistribute it and/or
@@ -42,45 +42,6 @@ G_DEFINE_TYPE (SwfdecTextFieldMovie, swfdec_text_field_movie, SWFDEC_TYPE_ACTOR)
#define EXTRA_MARGIN 2
#define BULLET_MARGIN 36
-/*** CURSOR API ***/
-
-static gsize
-swfdec_text_field_movie_get_cursor (SwfdecTextFieldMovie *text)
-{
- return text->cursor_start;
-}
-
-static gboolean
-swfdec_text_field_movie_has_cursor (SwfdecTextFieldMovie *text)
-{
- return text->cursor_start == text->cursor_end;
-}
-#define swfdec_text_field_movie_has_selection(text) (!swfdec_text_field_movie_has_cursor (text))
-
-static void
-swfdec_text_field_movie_get_selection (SwfdecTextFieldMovie *text, gsize *start, gsize *end)
-{
- if (start)
- *start = MIN (text->cursor_start, text->cursor_end);
- if (end)
- *end = MAX (text->cursor_start, text->cursor_end);
-}
-
-static void
-swfdec_text_field_movie_set_cursor (SwfdecTextFieldMovie *text, gsize start, gsize end)
-{
- g_return_if_fail (start <= text->input->len);
- g_return_if_fail (end <= text->input->len);
-
- if (text->cursor_start == start &&
- text->cursor_end == end)
- return;
-
- text->cursor_start = start;
- text->cursor_end = end;
- swfdec_movie_invalidate_last (SWFDEC_MOVIE (text));
-}
-
/*** VFUNCS ***/
static void
@@ -138,7 +99,7 @@ swfdec_text_paragraph_add_attribute (SwfdecParagraph *paragraph,
static void
swfdec_text_paragraph_add_block (SwfdecParagraph *paragraph, int index_,
- SwfdecTextFormat *format)
+ const SwfdecTextAttributes *attr)
{
guint i;
SwfdecBlock *block;
@@ -147,7 +108,7 @@ swfdec_text_paragraph_add_block (SwfdecParagraph *paragraph, int index_,
block->index_ = index_;
- switch (format->attr.align) {
+ switch (attr->align) {
case SWFDEC_TEXT_ALIGN_LEFT:
block->align = PANGO_ALIGN_LEFT;
block->justify = FALSE;
@@ -167,16 +128,16 @@ swfdec_text_paragraph_add_block (SwfdecParagraph *paragraph, int index_,
default:
g_assert_not_reached ();
}
- block->leading = format->attr.leading * 20 * PANGO_SCALE;
- block->block_indent = format->attr.block_indent * 20;
- block->left_margin = format->attr.left_margin * 20;
- block->right_margin = format->attr.right_margin * 20;
-
- if (format->attr.n_tab_stops != 0) {
- block->tab_stops = pango_tab_array_new (format->attr.n_tab_stops, TRUE);
- for (i = 0; i < format->attr.n_tab_stops; i++) {
+ block->leading = attr->leading * 20 * PANGO_SCALE;
+ block->block_indent = attr->block_indent * 20;
+ block->left_margin = attr->left_margin * 20;
+ block->right_margin = attr->right_margin * 20;
+
+ if (attr->n_tab_stops != 0) {
+ block->tab_stops = pango_tab_array_new (attr->n_tab_stops, TRUE);
+ for (i = 0; i < attr->n_tab_stops; i++) {
pango_tab_array_set_tab (block->tab_stops, i, PANGO_TAB_LEFT,
- format->attr.tab_stops[i] * 20);
+ attr->tab_stops[i] * 20);
}
} else {
block->tab_stops = NULL;
@@ -189,21 +150,23 @@ static void
swfdec_text_field_movie_generate_paragraph (SwfdecTextFieldMovie *text,
SwfdecParagraph *paragraph, guint start_index, guint length)
{
- SwfdecTextFormat *format, *format_prev;
guint index_;
- GSList *iter;
+ SwfdecTextBufferIter *iter;
PangoAttribute *attr_bold, *attr_color, *attr_font, *attr_italic,
*attr_letter_spacing, *attr_size, *attr_underline;
+ const char *string;
+ const SwfdecTextAttributes *attr, *attr_prev;
// TODO: kerning, display
g_assert (SWFDEC_IS_TEXT_FIELD_MOVIE (text));
g_assert (paragraph != NULL);
- g_assert (start_index + length <= text->input->len);
+ g_assert (start_index + length <= swfdec_text_buffer_get_length (text->text));
+ string = swfdec_text_buffer_get_text (text->text);
paragraph->index_ = start_index;
paragraph->length = length;
- if (text->input->str[start_index + length - 1] == '\n' ||
- text->input->str[start_index + length - 1] == '\r') {
+ if (string[start_index + length - 1] == '\n' ||
+ string[start_index + length - 1] == '\r') {
paragraph->newline = TRUE;
} else {
paragraph->newline = FALSE;
@@ -212,135 +175,130 @@ swfdec_text_field_movie_generate_paragraph (SwfdecTextFieldMovie *text,
paragraph->blocks = NULL;
paragraph->attrs = NULL;
- g_assert (text->formats != NULL);
- for (iter = text->formats; iter->next != NULL &&
- ((SwfdecFormatIndex *)(iter->next->data))->index_ <= start_index;
- iter = iter->next);
+ iter = swfdec_text_buffer_get_iter (text->text, start_index);
+ attr = swfdec_text_buffer_iter_get_attributes (text->text, iter);
index_ = start_index;
- format = ((SwfdecFormatIndex *)(iter->data))->format;
// Paragraph formats
- paragraph->bullet = format->attr.bullet;
- paragraph->indent = format->attr.indent * 20 * PANGO_SCALE;
+ paragraph->bullet = attr->bullet;
+ paragraph->indent = attr->indent * 20 * PANGO_SCALE;
// Add new block
- swfdec_text_paragraph_add_block (paragraph, 0, format);
+ swfdec_text_paragraph_add_block (paragraph, 0, attr);
// Open attributes
attr_bold = pango_attr_weight_new (
- (format->attr.bold ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL));
+ (attr->bold ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL));
attr_bold->start_index = 0;
- attr_color = pango_attr_foreground_new (SWFDEC_COLOR_R (format->attr.color) * 255,
- SWFDEC_COLOR_G (format->attr.color) * 255,
- SWFDEC_COLOR_B (format->attr.color) * 255);
+ attr_color = pango_attr_foreground_new (SWFDEC_COLOR_R (attr->color) * 255,
+ SWFDEC_COLOR_G (attr->color) * 255,
+ SWFDEC_COLOR_B (attr->color) * 255);
attr_color->start_index = 0;
// FIXME: embed fonts
- attr_font = pango_attr_family_new (format->attr.font);
+ attr_font = pango_attr_family_new (attr->font);
attr_font->start_index = 0;
attr_italic = pango_attr_style_new (
- (format->attr.italic ? PANGO_STYLE_ITALIC : PANGO_STYLE_NORMAL));
+ (attr->italic ? PANGO_STYLE_ITALIC : PANGO_STYLE_NORMAL));
attr_italic->start_index = 0;
attr_letter_spacing = pango_attr_letter_spacing_new (
- format->attr.letter_spacing * 20 * PANGO_SCALE);
+ attr->letter_spacing * 20 * PANGO_SCALE);
attr_letter_spacing->start_index = 0;
attr_size =
- pango_attr_size_new_absolute (MAX (format->attr.size, 1) * 20 * PANGO_SCALE);
+ pango_attr_size_new_absolute (MAX (attr->size, 1) * 20 * PANGO_SCALE);
attr_size->start_index = 0;
attr_underline = pango_attr_underline_new (
- (format->attr.underline ? PANGO_UNDERLINE_SINGLE : PANGO_UNDERLINE_NONE));
+ (attr->underline ? PANGO_UNDERLINE_SINGLE : PANGO_UNDERLINE_NONE));
attr_underline->start_index = 0;
- for (iter = iter->next;
- iter != NULL &&
- ((SwfdecFormatIndex *)(iter->data))->index_ < start_index + length;
- iter = iter->next)
+ for (iter = swfdec_text_buffer_iter_next (text->text, iter);
+ iter != NULL && swfdec_text_buffer_iter_get_start (text->text, iter) < start_index + length;
+ iter = swfdec_text_buffer_iter_next (text->text, iter))
{
- format_prev = format;
- index_ = ((SwfdecFormatIndex *)(iter->data))->index_;
- format = ((SwfdecFormatIndex *)(iter->data))->format;
+ attr_prev = attr;
+ index_ = swfdec_text_buffer_iter_get_start (text->text, iter);
+ attr = swfdec_text_buffer_iter_get_attributes (text->text, iter);
// Add new block if necessary
- if (format_prev->attr.align != format->attr.align ||
- format_prev->attr.bullet != format->attr.bullet ||
- format_prev->attr.indent != format->attr.indent ||
- format_prev->attr.leading != format->attr.leading ||
- format_prev->attr.block_indent != format->attr.block_indent ||
- format_prev->attr.left_margin != format->attr.left_margin)
+ if (attr_prev->align != attr->align ||
+ attr_prev->bullet != attr->bullet ||
+ attr_prev->indent != attr->indent ||
+ attr_prev->leading != attr->leading ||
+ attr_prev->block_indent != attr->block_indent ||
+ attr_prev->left_margin != attr->left_margin)
{
- swfdec_text_paragraph_add_block (paragraph, index_ - start_index,
- format);
+ swfdec_text_paragraph_add_block (paragraph, index_ - start_index, attr);
}
// Change attributes if necessary
- if (format_prev->attr.bold != format->attr.bold) {
+ if (attr_prev->bold != attr->bold) {
attr_bold->end_index = index_ - start_index;
swfdec_text_paragraph_add_attribute (paragraph, attr_bold);
attr_bold = pango_attr_weight_new (
- (format->attr.bold ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL));
+ (attr->bold ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL));
attr_bold->start_index = index_ - start_index;
}
- if (format_prev->attr.color != format->attr.color) {
+ if (attr_prev->color != attr->color) {
attr_color->end_index = index_ - start_index;
swfdec_text_paragraph_add_attribute (paragraph, attr_color);
attr_color = pango_attr_foreground_new (
- SWFDEC_COLOR_R (format->attr.color) * 255,
- SWFDEC_COLOR_G (format->attr.color) * 255,
- SWFDEC_COLOR_B (format->attr.color) * 255);
+ SWFDEC_COLOR_R (attr->color) * 255,
+ SWFDEC_COLOR_G (attr->color) * 255,
+ SWFDEC_COLOR_B (attr->color) * 255);
attr_color->start_index = index_ - start_index;
}
- if (format_prev->attr.font != format->attr.font) {
+ if (attr_prev->font != attr->font) {
attr_font->end_index = index_ - start_index;
swfdec_text_paragraph_add_attribute (paragraph, attr_font);
// FIXME: embed fonts
- attr_font = pango_attr_family_new (format->attr.font);
+ attr_font = pango_attr_family_new (attr->font);
attr_font->start_index = index_ - start_index;
}
- if (format_prev->attr.italic != format->attr.italic) {
+ if (attr_prev->italic != attr->italic) {
attr_italic->end_index = index_ - start_index;
swfdec_text_paragraph_add_attribute (paragraph, attr_italic);
attr_italic = pango_attr_style_new (
- (format->attr.italic ? PANGO_STYLE_ITALIC : PANGO_STYLE_NORMAL));
+ (attr->italic ? PANGO_STYLE_ITALIC : PANGO_STYLE_NORMAL));
attr_italic->start_index = index_ - start_index;
}
- if (format_prev->attr.letter_spacing != format->attr.letter_spacing) {
+ if (attr_prev->letter_spacing != attr->letter_spacing) {
attr_letter_spacing->end_index = index_ - start_index;
swfdec_text_paragraph_add_attribute (paragraph, attr_letter_spacing);
attr_letter_spacing = pango_attr_letter_spacing_new (
- format->attr.letter_spacing * 20 * PANGO_SCALE);
+ attr->letter_spacing * 20 * PANGO_SCALE);
attr_letter_spacing->start_index = index_ - start_index;
}
- if (format_prev->attr.size != format->attr.size) {
+ if (attr_prev->size != attr->size) {
attr_size->end_index = index_ - start_index;
swfdec_text_paragraph_add_attribute (paragraph, attr_size);
attr_size = pango_attr_size_new_absolute (
- MAX (1, format->attr.size) * 20 * PANGO_SCALE);
+ MAX (1, attr->size) * 20 * PANGO_SCALE);
attr_size->start_index = index_ - start_index;
}
- if (format_prev->attr.underline != format->attr.underline) {
+ if (attr_prev->underline != attr->underline) {
attr_underline->end_index = index_ - start_index;
swfdec_text_paragraph_add_attribute (paragraph, attr_underline);
attr_underline = pango_attr_underline_new (
- (format->attr.underline ? PANGO_UNDERLINE_SINGLE : PANGO_UNDERLINE_NONE));
+ (attr->underline ? PANGO_UNDERLINE_SINGLE : PANGO_UNDERLINE_NONE));
attr_underline->start_index = index_ - start_index;
}
}
@@ -383,7 +341,7 @@ swfdec_text_field_movie_get_paragraphs (SwfdecTextFieldMovie *text, int *num)
{
GArray *paragraphs;
SwfdecParagraph paragraph;
- const char *p, *end;
+ const char *p, *end, *string;
guint max_length;
g_assert (SWFDEC_IS_TEXT_FIELD_MOVIE (text));
@@ -391,7 +349,7 @@ swfdec_text_field_movie_get_paragraphs (SwfdecTextFieldMovie *text, int *num)
paragraphs = g_array_new (TRUE, TRUE, sizeof (SwfdecParagraph));
max_length = 0;
- p = text->input->str;
+ p = string = swfdec_text_buffer_get_text (text->text);
while (*p != '\0')
{
end = strpbrk (p, "\r\n");
@@ -405,7 +363,7 @@ swfdec_text_field_movie_get_paragraphs (SwfdecTextFieldMovie *text, int *num)
max_length = end - p;
swfdec_text_field_movie_generate_paragraph (text, ¶graph,
- p - text->input->str, end - p);
+ p - string, end - p);
paragraphs = g_array_append_val (paragraphs, paragraph);
p = end;
@@ -563,7 +521,7 @@ swfdec_text_field_movie_get_layouts (SwfdecTextFieldMovie *text, int *num,
}
layouts = g_array_new (TRUE, TRUE, sizeof (SwfdecLayout));
- swfdec_text_field_movie_get_selection (text, &cursor_start, &cursor_end);
+ swfdec_text_buffer_get_selection (text->text, &cursor_start, &cursor_end);
for (i = 0; paragraphs[i].blocks != NULL; i++)
{
@@ -646,7 +604,7 @@ swfdec_text_field_movie_get_layouts (SwfdecTextFieldMovie *text, int *num,
// add background for selection
layout.index_ = paragraphs[i].index_ + block->index_ + skip;
layout.index_end = layout.index_ + length;
- if (swfdec_text_field_movie_has_selection (text) &&
+ if (cursor_start != cursor_end &&
layout.index_ < cursor_end) {
SwfdecColor color;
PangoAttribute *attr_fg, *attr_bg;
@@ -703,7 +661,7 @@ swfdec_text_field_movie_get_layouts (SwfdecTextFieldMovie *text, int *num,
block->index_ - skip);
} else {
pango_layout_set_text (playout,
- text->input->str + paragraphs[i].index_ + block->index_ + skip,
+ swfdec_text_buffer_get_text (text->text) + paragraphs[i].index_ + block->index_ + skip,
paragraphs[i].length - block->index_ - skip);
}
@@ -719,7 +677,7 @@ swfdec_text_field_movie_get_layouts (SwfdecTextFieldMovie *text, int *num,
line = pango_layout_get_line_readonly (playout, line_num);
skip_new = line->start_index + line->length - (length - skip);
pango_layout_set_text (playout,
- text->input->str + paragraphs[i].index_ + block->index_ + skip,
+ swfdec_text_buffer_get_text (text->text) + paragraphs[i].index_ + block->index_ + skip,
length - skip + skip_new);
skip = skip_new;
}
@@ -923,8 +881,8 @@ swfdec_text_field_movie_render (SwfdecMovie *movie, cairo_t *cr,
MIN (text->scroll, text->scroll_max), NULL, &i, &skip);
if (text->editable && swfdec_text_field_movie_has_focus (text) &&
- swfdec_text_field_movie_has_cursor (text))
- cursor = swfdec_text_field_movie_get_cursor (text);
+ !swfdec_text_buffer_has_selection (text->text))
+ cursor = swfdec_text_buffer_get_cursor (text->text);
else
cursor = G_MAXSIZE;
@@ -1009,22 +967,21 @@ swfdec_text_field_movie_render (SwfdecMovie *movie, cairo_t *cr,
} while (pango_layout_iter_next_line (iter_line));
if (layouts[i].index_ <= cursor &&
- (layouts[i].index_end > cursor || (layouts[i].index_end == cursor && cursor == text->input->len)) &&
+ (layouts[i].index_end > cursor || (layouts[i].index_end == cursor && cursor == swfdec_text_buffer_get_length (text->text))) &&
(line == NULL || layouts[i].index_ + line->start_index >= cursor)) {
- SwfdecTextFormat *format = ((SwfdecFormatIndex *) g_slist_last (text->formats))->format;
+ const SwfdecTextAttributes *attr = swfdec_text_buffer_get_attributes (text->text,
+ swfdec_text_buffer_get_length (text->text));
PangoRectangle cursor_rect;
pango_layout_get_cursor_pos (layouts[i].layout,
- swfdec_text_field_movie_get_cursor (text) - layouts[i].index_,
+ swfdec_text_buffer_get_cursor (text->text) - layouts[i].index_,
&cursor_rect, NULL);
cairo_save (cr);
- if (format && SWFDEC_TEXT_ATTRIBUTE_IS_SET (format->values_set, SWFDEC_TEXT_ATTRIBUTE_COLOR))
- swfdec_color_set_source (cr, format->attr.color | SWFDEC_COLOR_COMBINE (0, 0, 0, 0xFF));
- else
- swfdec_color_set_source (cr, text->default_attributes.color | SWFDEC_COLOR_COMBINE (0, 0, 0, 0xFF));
+ /* FIXME: or default attributes? */
+ swfdec_color_set_source (cr, attr->color | SWFDEC_COLOR_COMBINE (0, 0, 0, 0xFF));
- /* FIXME: what's the propwer line width here? */
+ /* FIXME: what's the proper line width here? */
cairo_set_line_width (cr, SWFDEC_DOUBLE_TO_TWIPS (0.5));
cairo_move_to (cr, x + layout->offset_x + rect.x, y - skipped);
cairo_rel_move_to (cr, (double) cursor_rect.x / PANGO_SCALE, (double) cursor_rect.y / PANGO_SCALE);
@@ -1219,7 +1176,6 @@ static void
swfdec_text_field_movie_dispose (GObject *object)
{
SwfdecTextFieldMovie *text;
- GSList *iter;
text = SWFDEC_TEXT_FIELD_MOVIE (object);
@@ -1239,15 +1195,12 @@ swfdec_text_field_movie_dispose (GObject *object)
text->style_sheet = NULL;
}
- for (iter = text->formats; iter != NULL; iter = iter->next) {
- g_free (text->formats->data);
- text->formats->data = NULL;
+ if (text->text) {
+ g_signal_handlers_disconnect_matched (text->text, G_SIGNAL_MATCH_DATA,
+ 0, 0, NULL, NULL, text);
+ g_object_unref (text->text);
+ text->text = NULL;
}
- g_slist_free (text->formats);
- text->formats = NULL;
-
- g_string_free (text->input, TRUE);
- text->input = NULL;
G_OBJECT_CLASS (swfdec_text_field_movie_parent_class)->dispose (object);
}
@@ -1256,16 +1209,13 @@ static void
swfdec_text_field_movie_mark (SwfdecAsObject *object)
{
SwfdecTextFieldMovie *text;
- GSList *iter;
text = SWFDEC_TEXT_FIELD_MOVIE (object);
if (text->variable != NULL)
swfdec_as_string_mark (text->variable);
- for (iter = text->formats; iter != NULL; iter = iter->next) {
- swfdec_as_object_mark (
- SWFDEC_AS_OBJECT (((SwfdecFormatIndex *)(iter->data))->format));
- }
+
+ swfdec_text_buffer_mark (text->text);
if (text->style_sheet != NULL)
swfdec_as_object_mark (text->style_sheet);
if (text->style_sheet_input != NULL)
@@ -1378,41 +1328,20 @@ swfdec_text_field_movie_contains (SwfdecMovie *movie, double x, double y,
return movie;
}
-static SwfdecTextFormat *
-swfdec_text_field_movie_format_for_index (SwfdecTextFieldMovie *text,
- guint index_)
-{
- GSList *iter;
-
- g_return_val_if_fail (SWFDEC_IS_TEXT_FIELD_MOVIE (text), NULL);
- g_return_val_if_fail (index_ <= text->input->len, NULL);
-
- if (text->formats == NULL)
- return NULL;
-
- // get current format
- for (iter = text->formats; iter != NULL && iter->next != NULL &&
- ((SwfdecFormatIndex *)iter->next->data)->index_ < index_;
- iter = iter->next);
-
- return ((SwfdecFormatIndex *)iter->data)->format;
-}
-
static void
swfdec_text_field_movie_letter_clicked (SwfdecTextFieldMovie *text,
guint index_)
{
- SwfdecTextFormat *format;
+ const SwfdecTextAttributes *attr;
g_return_if_fail (SWFDEC_IS_TEXT_FIELD_MOVIE (text));
- g_return_if_fail (index_ <= text->input->len);
+ g_return_if_fail (index_ <= swfdec_text_buffer_get_length (text->text));
- format = swfdec_text_field_movie_format_for_index (text, index_);
+ attr = swfdec_text_buffer_get_attributes (text->text, index_);
- if (format != NULL && format->attr.url != NULL &&
- format->attr.url != SWFDEC_AS_STR_EMPTY) {
+ if (attr->url != SWFDEC_AS_STR_EMPTY) {
swfdec_player_launch (SWFDEC_PLAYER (SWFDEC_AS_OBJECT (text)->context),
- SWFDEC_LOADER_REQUEST_DEFAULT, format->attr.url, format->attr.target, NULL);
+ SWFDEC_LOADER_REQUEST_DEFAULT, attr->url, attr->target, NULL);
}
}
@@ -1472,18 +1401,17 @@ swfdec_text_field_movie_mouse_cursor (SwfdecActor *actor)
SwfdecTextFieldMovie *text = SWFDEC_TEXT_FIELD_MOVIE (actor);
double x, y;
guint index_;
- SwfdecTextFormat *format;
+ const SwfdecTextAttributes *attr;
swfdec_movie_get_mouse (SWFDEC_MOVIE (actor), &x, &y);
if (swfdec_text_field_movie_xy_to_index (text, x, y, &index_, NULL)) {
- format = swfdec_text_field_movie_format_for_index (text, index_);
+ attr = swfdec_text_buffer_get_attributes (text->text, index_);
} else {
- format = NULL;
+ attr = NULL;
}
- if (format != NULL && format->attr.url != NULL &&
- format->attr.url != SWFDEC_AS_STR_EMPTY) {
+ if (attr != NULL && attr->url != SWFDEC_AS_STR_EMPTY) {
return SWFDEC_MOUSE_CURSOR_CLICK;
} else if (text->editable || text->selectable) {
return SWFDEC_MOUSE_CURSOR_TEXT;
@@ -1519,9 +1447,9 @@ swfdec_text_field_movie_mouse_press (SwfdecActor *actor, guint button)
direct = swfdec_text_field_movie_xy_to_index (text, x, y, &index_, &before);
text->mouse_pressed = TRUE;
- if (!before && index_ < text->input->len)
+ if (!before && index_ < swfdec_text_buffer_get_length (text->text))
index_++;
- swfdec_text_field_movie_set_cursor (text, index_, index_);
+ swfdec_text_buffer_set_cursor (text->text, index_, index_);
if (direct) {
text->character_pressed = index_;
@@ -1547,10 +1475,10 @@ swfdec_text_field_movie_mouse_move (SwfdecActor *actor, double x, double y)
direct = swfdec_text_field_movie_xy_to_index (text, x, y, &index_, &before);
- if (!before && index_ < text->input->len)
+ if (!before && index_ < swfdec_text_buffer_get_length (text->text))
index_++;
- swfdec_text_field_movie_set_cursor (text, swfdec_text_field_movie_get_cursor (text), index_);
+ swfdec_text_buffer_set_cursor (text->text, swfdec_text_buffer_get_cursor (text->text), index_);
}
static void
@@ -1613,50 +1541,48 @@ swfdec_text_field_movie_key_press (SwfdecActor *actor, guint keycode, guint char
char insert[7];
guint len;
gsize start, end;
-#define BACKWARD(text, _index) ((_index) == 0 ? 0 : (gsize) (g_utf8_prev_char ((text)->input->str + (_index)) - (text)->input->str))
-#define FORWARD(text, _index) ((_index) == (text)->input->len ? (_index) : (gsize) (g_utf8_next_char ((text)->input->str + (_index)) - (text)->input->str))
+ const char *string;
+#define BACKWARD(text, _index) ((_index) == 0 ? 0 : (gsize) (g_utf8_prev_char ((text) + (_index)) - (text)))
+#define FORWARD(text, _index) ((text)[0] == 0 ? (_index) : (gsize) (g_utf8_next_char ((text) + (_index)) - (text)))
if (!text->editable)
return;
- swfdec_text_field_movie_get_selection (text, &start, &end);
+ string = swfdec_text_buffer_get_text (text->text);
+ swfdec_text_buffer_get_selection (text->text, &start, &end);
switch (keycode) {
case SWFDEC_KEY_LEFT:
- if (swfdec_text_field_movie_has_cursor (text)) {
- start = BACKWARD (text, start);
- swfdec_text_field_movie_set_cursor (text, start, start);
+ if (swfdec_text_buffer_has_selection (text->text)) {
+ swfdec_text_buffer_set_cursor (text->text, start, start);
} else {
- swfdec_text_field_movie_set_cursor (text, start, start);
+ start = BACKWARD (string, start);
+ swfdec_text_buffer_set_cursor (text->text, start, start);
}
return;
case SWFDEC_KEY_RIGHT:
- if (swfdec_text_field_movie_has_cursor (text)) {
- start = FORWARD (text, start);
- swfdec_text_field_movie_set_cursor (text, start, start);
+ if (swfdec_text_buffer_has_selection (text->text)) {
+ swfdec_text_buffer_set_cursor (text->text, end, end);
} else {
- swfdec_text_field_movie_set_cursor (text, end, end);
+ start = FORWARD (string, start);
+ swfdec_text_buffer_set_cursor (text->text, start, start);
}
return;
case SWFDEC_KEY_BACKSPACE:
- if (swfdec_text_field_movie_has_cursor (text)) {
- start = BACKWARD (text, start);
+ if (!swfdec_text_buffer_has_selection (text->text)) {
+ start = BACKWARD (string, start);
}
if (start != end) {
- swfdec_sandbox_use (SWFDEC_MOVIE (text)->resource->sandbox);
- swfdec_text_field_movie_replace_text (text, start, end, "");
- swfdec_sandbox_unuse (SWFDEC_MOVIE (text)->resource->sandbox);
+ swfdec_text_buffer_delete_text (text->text, start, end - start);
swfdec_text_field_movie_changed (text);
}
return;
case SWFDEC_KEY_DELETE:
- if (swfdec_text_field_movie_has_cursor (text)) {
- end = FORWARD (text, end);
+ if (!swfdec_text_buffer_has_selection (text->text)) {
+ end = FORWARD (string, end);
}
if (start != end) {
- swfdec_sandbox_use (SWFDEC_MOVIE (text)->resource->sandbox);
- swfdec_text_field_movie_replace_text (text, start, end, "");
- swfdec_sandbox_unuse (SWFDEC_MOVIE (text)->resource->sandbox);
+ swfdec_text_buffer_delete_text (text->text, start, end - start);
swfdec_text_field_movie_changed (text);
}
return;
@@ -1669,9 +1595,9 @@ swfdec_text_field_movie_key_press (SwfdecActor *actor, guint keycode, guint char
len = g_unichar_to_utf8 (character, insert);
if (len) {
insert[len] = 0;
- swfdec_sandbox_use (SWFDEC_MOVIE (text)->resource->sandbox);
- swfdec_text_field_movie_replace_text (text, start, end, insert);
- swfdec_sandbox_unuse (SWFDEC_MOVIE (text)->resource->sandbox);
+ if (start != end)
+ swfdec_text_buffer_delete_text (text->text, start, end - start);
+ swfdec_text_buffer_insert_text (text->text, start, insert);
swfdec_text_field_movie_changed (text);
}
}
@@ -1715,136 +1641,23 @@ swfdec_text_field_movie_class_init (SwfdecTextFieldMovieClass * g_class)
}
static void
+swfdec_text_field_movie_cursor_changed (SwfdecTextBuffer *buffer,
+ gulong start, gulong end, SwfdecTextFieldMovie *text)
+{
+ swfdec_movie_invalidate_last (SWFDEC_MOVIE (text));
+ /* FIXME: update selection */
+}
+
+static void
swfdec_text_field_movie_init (SwfdecTextFieldMovie *text)
{
- text->input = g_string_new ("");
+ text->text = swfdec_text_buffer_new ();
+ g_signal_connect (text->text, "cursor-changed",
+ G_CALLBACK (swfdec_text_field_movie_cursor_changed), text);
text->scroll = 1;
text->mouse_wheel_enabled = TRUE;
swfdec_text_attributes_reset (&text->default_attributes);
-
-}
-
-void
-swfdec_text_field_movie_set_text_format (SwfdecTextFieldMovie *text,
- SwfdecTextFormat *format, guint start_index, guint end_index)
-{
- SwfdecFormatIndex *findex, *findex_new, *findex_prev;
- guint findex_end_index;
- GSList *iter, *next;
-
- g_return_if_fail (SWFDEC_IS_TEXT_FIELD_MOVIE (text));
- g_return_if_fail (SWFDEC_IS_TEXT_FORMAT (format));
- g_return_if_fail (start_index < end_index);
- g_return_if_fail (end_index <= text->input->len);
-
- g_assert (text->formats != NULL);
- g_assert (text->formats->data != NULL);
- g_assert (((SwfdecFormatIndex *)text->formats->data)->index_ == 0);
-
- findex = NULL;
- for (iter = text->formats; iter != NULL &&
- ((SwfdecFormatIndex *)iter->data)->index_ < end_index;
- iter = next)
- {
- findex_prev = findex;
- next = iter->next;
- findex = iter->data;
- if (iter->next != NULL) {
- findex_end_index =
- ((SwfdecFormatIndex *)iter->next->data)->index_;
- } else {
- findex_end_index = text->input->len;
- }
-
- if (findex_end_index <= start_index)
- continue;
-
- if (swfdec_text_format_equal_or_undefined (findex->format, format))
- continue;
-
- if (findex_end_index > end_index) {
- findex_new = g_new (SwfdecFormatIndex, 1);
- findex_new->index_ = end_index;
- findex_new->format = swfdec_text_format_copy (findex->format);
- if (findex_new->format == NULL) {
- g_free (findex_new);
- break;
- }
-
- iter = g_slist_insert (iter, findex_new, 1);
- }
-
- if (findex->index_ < start_index) {
- findex_new = g_new (SwfdecFormatIndex, 1);
- findex_new->index_ = start_index;
- findex_new->format = swfdec_text_format_copy (findex->format);
- if (findex_new->format == NULL) {
- g_free (findex_new);
- break;
- }
- swfdec_text_format_add (findex_new->format, format);
-
- iter = g_slist_insert (iter, findex_new, 1);
- findex = findex_new;
- } else {
- swfdec_text_format_add (findex->format, format);
-
- // if current format now equals previous one, remove current
- if (findex_prev != NULL &&
- swfdec_text_format_equal (findex->format, findex_prev->format)) {
- text->formats = g_slist_remove (text->formats, findex);
- findex = findex_prev;
- }
- }
-
- // if current format now equals the next one, remove current
- if (findex_end_index <= end_index && next != NULL &&
- swfdec_text_format_equal (findex->format,
- ((SwfdecFormatIndex *)next->data)->format))
- {
- ((SwfdecFormatIndex *)next->data)->index_ = findex->index_;
- text->formats = g_slist_remove (text->formats, findex);
- findex = findex_prev;
- }
- }
-}
-
-SwfdecTextFormat *
-swfdec_text_field_movie_get_text_format (SwfdecTextFieldMovie *text,
- guint start_index, guint end_index)
-{
- SwfdecTextFormat *format;
- GSList *iter;
-
- g_assert (SWFDEC_IS_TEXT_FIELD_MOVIE (text));
- g_assert (start_index < end_index);
- g_assert (end_index <= text->input->len);
-
- g_assert (text->formats != NULL);
- g_assert (text->formats->data != NULL);
- g_assert (((SwfdecFormatIndex *)text->formats->data)->index_ == 0);
-
- format = NULL;
- for (iter = text->formats; iter != NULL &&
- ((SwfdecFormatIndex *)iter->data)->index_ < end_index;
- iter = iter->next)
- {
- if (iter->next != NULL &&
- ((SwfdecFormatIndex *)iter->next->data)->index_ <= start_index)
- continue;
-
- if (format == NULL) {
- swfdec_text_format_init_properties (SWFDEC_AS_OBJECT (text)->context);
- format =
- swfdec_text_format_copy (((SwfdecFormatIndex *)iter->data)->format);
- } else {
- swfdec_text_format_remove_different (format,
- ((SwfdecFormatIndex *)iter->data)->format);
- }
- }
-
- return format;
}
static void
@@ -1966,7 +1779,7 @@ swfdec_text_field_movie_get_text (SwfdecTextFieldMovie *text)
{
char *str, *p;
- str = g_strdup (text->input->str);
+ str = g_strdup (swfdec_text_buffer_get_text (text->text));
// if input was orginally html, remove all \r
if (text->input_html) {
@@ -1989,13 +1802,8 @@ void
swfdec_text_field_movie_replace_text (SwfdecTextFieldMovie *text,
guint start_index, guint end_index, const char *str)
{
- SwfdecFormatIndex *findex;
- GSList *iter;
- gboolean first;
- gsize len;
-
g_return_if_fail (SWFDEC_IS_TEXT_FIELD_MOVIE (text));
- g_return_if_fail (end_index <= text->input->len);
+ g_return_if_fail (end_index <= swfdec_text_buffer_get_length (text->text));
g_return_if_fail (start_index <= end_index);
g_return_if_fail (str != NULL);
@@ -2004,57 +1812,21 @@ swfdec_text_field_movie_replace_text (SwfdecTextFieldMovie *text,
if (text->style_sheet_input)
return;
- len = strlen (str);
- first = TRUE;
- iter = text->formats;
- while (iter) {
- findex = iter->data;
- iter = iter->next;
-
- /* remove formats of deleted text */
- if (findex->index_ >= start_index &&
- (end_index == text->input->len ||
- (iter != NULL &&
- ((SwfdecFormatIndex *) iter->data)->index_ <= end_index)) &&
- text->formats->next != NULL) {
- text->formats = g_slist_remove (text->formats, findex);
- g_free (findex);
- continue;
- }
- /* adapt indexes: remove deleted part, add to-be inserted text */
- if (findex->index_ > end_index) {
- findex->index_ = findex->index_ + start_index - end_index + len;
- } else if (findex->index_ > start_index) {
- findex->index_ = start_index;
- }
- }
+ if (end_index > start_index)
+ swfdec_text_buffer_delete_text (text->text, start_index, end_index - start_index);
- if (end_index == text->input->len && text->input->len > 0) {
+ if (start_index == swfdec_text_buffer_get_length (text->text) &&
+ start_index > 0) {
+ const SwfdecTextAttributes *attr = swfdec_text_buffer_get_attributes (text->text, 0);
if (SWFDEC_AS_OBJECT (text)->context->version < 8) {
SWFDEC_FIXME ("replaceText to the end of the TextField might use wrong text format on version 7");
}
- findex = g_new0 (SwfdecFormatIndex, 1);
- findex->index_ = start_index;
- findex->format = swfdec_text_format_copy (
- ((SwfdecFormatIndex *)text->formats->data)->format);
- text->formats = g_slist_append (text->formats, findex);
- }
-
- text->input = g_string_erase (text->input, start_index,
- end_index - start_index);
- text->input = g_string_insert (text->input, start_index, str);
-
- if (text->cursor_start >= start_index) {
- if (text->cursor_start <= end_index)
- text->cursor_start = start_index + len;
- else
- text->cursor_start += end_index - start_index + len;
- }
- if (text->cursor_end >= start_index) {
- if (text->cursor_end <= end_index)
- text->cursor_end = start_index + len;
- else
- text->cursor_end += end_index - start_index + len;
+ swfdec_text_buffer_insert_text (text->text, start_index, str);
+ swfdec_text_buffer_set_attributes (text->text, start_index,
+ swfdec_text_buffer_get_length (text->text) - start_index, attr,
+ SWFDEC_TEXT_ATTRIBUTES_MASK);
+ } else {
+ swfdec_text_buffer_insert_text (text->text, start_index, str);
}
swfdec_movie_invalidate_last (SWFDEC_MOVIE (text));
@@ -2066,33 +1838,20 @@ void
swfdec_text_field_movie_set_text (SwfdecTextFieldMovie *text, const char *str,
gboolean html)
{
- SwfdecFormatIndex *block;
+ gsize length;
g_return_if_fail (SWFDEC_IS_TEXT_FIELD_MOVIE (text));
g_return_if_fail (str != NULL);
- // remove old formatting info
- g_slist_foreach (text->formats, (GFunc) g_free, NULL);
- g_slist_free (text->formats);
- text->formats = NULL;
-
/* Flash 7 resets to default style here */
if (html && SWFDEC_AS_OBJECT (text)->context->version < 8)
swfdec_text_attributes_reset (&text->default_attributes);
- block = g_new (SwfdecFormatIndex, 1);
- block->index_ = 0;
- block->format = SWFDEC_TEXT_FORMAT (
- swfdec_text_format_new_no_properties (SWFDEC_AS_OBJECT (text)->context));
- if (block->format == NULL) {
- g_free (block);
- text->input = g_string_truncate (text->input, 0);
- return;
- }
- swfdec_text_attributes_copy (&block->format->attr, &text->default_attributes,
+ length = swfdec_text_buffer_get_length (text->text);
+ if (length)
+ swfdec_text_buffer_delete_text (text->text, 0, length);
+ swfdec_text_buffer_set_attributes (text->text, 0, 0, &text->default_attributes,
SWFDEC_TEXT_ATTRIBUTES_MASK);
- block->format->values_set = SWFDEC_TEXT_ATTRIBUTES_MASK;
- text->formats = g_slist_prepend (text->formats, block);
text->input_html = html;
@@ -2108,7 +1867,7 @@ swfdec_text_field_movie_set_text (SwfdecTextFieldMovie *text, const char *str,
if (html) {
swfdec_text_field_movie_html_parse (text, str);
} else {
- text->input = g_string_assign (text->input, str);
+ swfdec_text_buffer_insert_text (text->text, 0, str);
}
}
diff --git a/swfdec/swfdec_text_field_movie.h b/swfdec/swfdec_text_field_movie.h
index 4e22dc2..80beb63 100644
--- a/swfdec/swfdec_text_field_movie.h
+++ b/swfdec/swfdec_text_field_movie.h
@@ -1,5 +1,5 @@
/* Swfdec
- * Copyright (C) 2006 Benjamin Otte <otte at gnome.org>
+ * Copyright (C) 2006-2008 Benjamin Otte <otte at gnome.org>
* 2007 Pekka Lampila <pekka.lampila at iki.fi>
*
* This library is free software; you can redistribute it and/or
@@ -24,6 +24,7 @@
#include <swfdec/swfdec_actor.h>
#include <swfdec/swfdec_text_field.h>
#include <swfdec/swfdec_style_sheet.h>
+#include <swfdec/swfdec_text_buffer.h>
#include <swfdec/swfdec_text_format.h>
G_BEGIN_DECLS
@@ -79,11 +80,6 @@ typedef struct {
GSList * attrs; // PangoAttribute
} SwfdecParagraph;
-typedef struct {
- guint index_;
- SwfdecTextFormat * format;
-} SwfdecFormatIndex;
-
struct _SwfdecTextFieldMovie {
SwfdecActor actor;
@@ -102,7 +98,7 @@ struct _SwfdecTextFieldMovie {
gboolean border;
gboolean background;
- GString * input;
+ SwfdecTextBuffer * text; /* the text + formatting */
char * asterisks; /* bunch of asterisks that we display when password mode is enabled */
guint asterisks_length;
gboolean input_html; /* whether orginal input was given as HTML */
@@ -110,7 +106,6 @@ struct _SwfdecTextFieldMovie {
const char * variable;
SwfdecTextAttributes default_attributes;
- GSList * formats;
gboolean condense_white;
@@ -132,8 +127,6 @@ struct _SwfdecTextFieldMovie {
SwfdecColor background_color;
gboolean mouse_pressed;
- gsize cursor_start; /* index of cursor (aka insertion point) in ->input */
- gsize cursor_end; /* end of cursor, either equal to cursor_start or if text selected smaller or bigger */
guint character_pressed;
};
@@ -152,13 +145,6 @@ void swfdec_text_field_movie_get_text_size (SwfdecTextFieldMovie * text,
gboolean swfdec_text_field_movie_auto_size (SwfdecTextFieldMovie * text);
void swfdec_text_field_movie_update_scroll (SwfdecTextFieldMovie * text,
gboolean check_limits);
-void swfdec_text_field_movie_set_text_format (SwfdecTextFieldMovie * text,
- SwfdecTextFormat * format,
- guint start_index,
- guint end_index);
-SwfdecTextFormat *swfdec_text_field_movie_get_text_format (SwfdecTextFieldMovie * text,
- guint start_index,
- guint end_index);
const char * swfdec_text_field_movie_get_text (SwfdecTextFieldMovie * text);
void swfdec_text_field_movie_set_listen_variable (SwfdecTextFieldMovie * text,
const char * value);
diff --git a/swfdec/swfdec_text_field_movie_as.c b/swfdec/swfdec_text_field_movie_as.c
index 5a7f423..1f67f79 100644
--- a/swfdec/swfdec_text_field_movie_as.c
+++ b/swfdec/swfdec_text_field_movie_as.c
@@ -180,7 +180,7 @@ swfdec_text_field_movie_get_length (SwfdecAsContext *cx, SwfdecAsObject *object,
SWFDEC_AS_CHECK (SWFDEC_TYPE_TEXT_FIELD_MOVIE, &text, "");
- SWFDEC_AS_VALUE_SET_INT (ret, g_utf8_strlen (text->input->str, -1));
+ SWFDEC_AS_VALUE_SET_INT (ret, g_utf8_strlen (swfdec_text_buffer_get_text (text->text), -1));
}
/*
@@ -1116,34 +1116,41 @@ swfdec_text_field_movie_setTextFormat (SwfdecAsContext *cx,
{
SwfdecTextFieldMovie *text;
SwfdecTextFormat *format;
- int val, start_index, end_index;
+ int val;
guint i;
+ const char *string;
+ gsize start, end, length;
SWFDEC_AS_CHECK (SWFDEC_TYPE_TEXT_FIELD_MOVIE, &text, "");
if (argc < 1)
return;
- i = 0;
- if (argc <= i + 1) {
- start_index = 0;
- end_index = g_utf8_strlen (text->input->str, -1);
+ string = swfdec_text_buffer_get_text (text->text);
+ length = g_utf8_strlen (string, -1);
+ if (argc <= 1) {
+ start = 0;
+ end = length;
+ i = 0;
} else {
- start_index = val = swfdec_as_value_to_integer (cx, &argv[i++]);
- start_index = CLAMP (start_index, 0, g_utf8_strlen (text->input->str, -1));
- if (argc <= i + 1) {
+ val = swfdec_as_value_to_integer (cx, &argv[0]);
+ start = MAX (val, 0);
+ start = MIN (start, length);
+ if (argc <= 2) {
if (val < 0) { // fail
- start_index = end_index = 0;
- } else{
- end_index = start_index + 1;
+ return;
+ } else {
+ end = MIN (start + 1, length);
}
+ i = 1;
} else {
- end_index = swfdec_as_value_to_integer (cx, &argv[i++]);
+ val = swfdec_as_value_to_integer (cx, &argv[1]);
+ end = MAX (val, 0);
+ end = CLAMP (end, start, length);
+ i = 2;
}
- end_index =
- CLAMP (end_index, start_index, g_utf8_strlen (text->input->str, -1));
}
- if (start_index == end_index)
+ if (start == end)
return;
if (!SWFDEC_AS_VALUE_IS_OBJECT (&argv[i]))
@@ -1152,12 +1159,11 @@ swfdec_text_field_movie_setTextFormat (SwfdecAsContext *cx,
return;
format = SWFDEC_TEXT_FORMAT (SWFDEC_AS_VALUE_GET_OBJECT (&argv[i]));
+ start = g_utf8_offset_to_pointer (string, start) - string;
+ end = g_utf8_offset_to_pointer (string, end) - string;
- swfdec_text_field_movie_set_text_format (text, format,
- g_utf8_offset_to_pointer (text->input->str, start_index) -
- text->input->str,
- g_utf8_offset_to_pointer (text->input->str, end_index) -
- text->input->str);
+ swfdec_text_buffer_set_attributes (text->text, start, end - start,
+ &format->attr, format->values_set);
swfdec_movie_invalidate_last (SWFDEC_MOVIE (text));
swfdec_text_field_movie_auto_size (text);
@@ -1173,40 +1179,49 @@ swfdec_text_field_movie_getTextFormat (SwfdecAsContext *cx,
{
SwfdecTextFieldMovie *text;
SwfdecTextFormat *format;
- int val, start_index, end_index;
+ int val;
+ const char *string;
+ guint mask;
+ const SwfdecTextAttributes *attr;
+ gsize start, end, length;
SWFDEC_AS_CHECK (SWFDEC_TYPE_TEXT_FIELD_MOVIE, &text, "");
+ string = swfdec_text_buffer_get_text (text->text);
+ length = g_utf8_strlen (string, -1);
+
+ format = SWFDEC_TEXT_FORMAT (swfdec_text_format_new (cx));
+ SWFDEC_AS_VALUE_SET_OBJECT (ret, SWFDEC_AS_OBJECT (format));
+
if (argc == 0) {
- start_index = 0;
- end_index = g_utf8_strlen (text->input->str, -1);
+ start = 0;
+ end = length;
} else {
- start_index = val = swfdec_as_value_to_integer (cx, &argv[0]);
- start_index = CLAMP (start_index, 0, g_utf8_strlen (text->input->str, -1));
+ val = swfdec_as_value_to_integer (cx, &argv[0]);
+ start = MAX (val, 0);
+ start = MIN (start, length);
if (argc == 1) {
if (val < 0) { // fail
- start_index = end_index = 0;
- } else{
- end_index = start_index + 1;
+ return;
+ } else {
+ end = MIN (start + 1, length);
}
} else {
- end_index = swfdec_as_value_to_integer (cx, &argv[1]);
+ val = swfdec_as_value_to_integer (cx, &argv[1]);
+ end = MAX (val, 0);
+ end = CLAMP (end, start, length);
}
- end_index =
- CLAMP (end_index, start_index, g_utf8_strlen (text->input->str, -1));
}
- if (start_index == end_index) {
- format = SWFDEC_TEXT_FORMAT (swfdec_text_format_new (cx));
- } else {
- format = swfdec_text_field_movie_get_text_format (text,
- g_utf8_offset_to_pointer (text->input->str, start_index) -
- text->input->str,
- g_utf8_offset_to_pointer (text->input->str, end_index) -
- text->input->str);
- }
+ if (start == end)
+ return;
- SWFDEC_AS_VALUE_SET_OBJECT (ret, SWFDEC_AS_OBJECT (format));
+ start = g_utf8_offset_to_pointer (string, start) - string;
+ end = g_utf8_offset_to_pointer (string, end) - string;
+ mask = swfdec_text_buffer_get_unique (text->text, start, end - start);
+ attr = swfdec_text_buffer_get_attributes (text->text, start);
+ swfdec_text_attributes_copy (&format->attr, attr, mask);
+ format->values_set = mask;
}
SWFDEC_AS_NATIVE (104, 100, swfdec_text_field_movie_replaceSel)
@@ -1226,8 +1241,8 @@ swfdec_text_field_movie_replaceText (SwfdecAsContext *cx,
{
SwfdecTextFieldMovie *text;
int start_index, end_index;
- const char *str;
-
+ const char *string, *str;
+ gsize start, end;
SWFDEC_AS_CHECK (SWFDEC_TYPE_TEXT_FIELD_MOVIE, &text, "iis", &start_index,
&end_index, &str);
@@ -1237,14 +1252,14 @@ swfdec_text_field_movie_replaceText (SwfdecAsContext *cx,
if (end_index < start_index)
return;
- start_index = MIN (start_index, g_utf8_strlen (text->input->str, -1));
- end_index = MIN (end_index, g_utf8_strlen (text->input->str, -1));
+ string = swfdec_text_buffer_get_text (text->text);
+ start = end = g_utf8_strlen (string, -1);
+ start = MIN ((gsize) start_index, start);
+ end = MIN ((gsize) end_index, end);
+ start = g_utf8_offset_to_pointer (string, start) - string;
+ end = g_utf8_offset_to_pointer (string, end) - string;
- swfdec_text_field_movie_replace_text (text,
- g_utf8_offset_to_pointer (text->input->str, start_index) -
- text->input->str,
- g_utf8_offset_to_pointer (text->input->str, end_index) -
- text->input->str, str);
+ swfdec_text_field_movie_replace_text (text, start, end, str);
}
// static
diff --git a/swfdec/swfdec_text_field_movie_html.c b/swfdec/swfdec_text_field_movie_html.c
index bd8049f..96e7485 100644
--- a/swfdec/swfdec_text_field_movie_html.c
+++ b/swfdec/swfdec_text_field_movie_html.c
@@ -38,15 +38,15 @@ typedef struct {
int name_length;
guint index;
guint end_index;
- SwfdecTextFormat *format;
+ SwfdecTextFormat * format;
} ParserTag;
typedef struct {
- SwfdecAsContext *cx;
+ SwfdecAsContext * cx;
gboolean multiline;
gboolean condense_white;
- SwfdecStyleSheet *style_sheet;
- GString * text;
+ SwfdecStyleSheet * style_sheet;
+ SwfdecTextBuffer * text;
GSList * tags_open;
GSList * tags_closed;
} ParserData;
@@ -72,7 +72,7 @@ swfdec_text_field_movie_html_parse_close_tag (ParserData *data, ParserTag *tag,
ParserTag *n = g_new0 (ParserTag, 1);
n->name = f->name;
n->name_length = f->name_length;
- n->index = data->text->len;
+ n->index = swfdec_text_buffer_get_length (data->text);
n->end_index = n->index + 1;
if (f->format != NULL) {
n->format = swfdec_text_format_copy (f->format);
@@ -83,10 +83,10 @@ swfdec_text_field_movie_html_parse_close_tag (ParserData *data, ParserTag *tag,
break;
}
}
- data->text = g_string_append_c (data->text, '\n');
+ swfdec_text_buffer_append_text (data->text, "\n");
}
- tag->end_index = data->text->len;
+ tag->end_index = swfdec_text_buffer_get_length (data->text);
data->tags_open = g_slist_remove (data->tags_open, tag);
data->tags_closed = g_slist_prepend (data->tags_closed, tag);
@@ -337,7 +337,7 @@ swfdec_text_field_movie_html_parse_tag (ParserData *data, const char *p)
swfdec_text_field_movie_html_parse_close_tag (data, tag, TRUE);
}
if (data->multiline)
- data->text = g_string_append_c (data->text, '\n');
+ swfdec_text_buffer_append_text (data->text, "\n");
swfdec_text_field_movie_html_parse_close_tag (data, found->data,
TRUE);
}
@@ -360,19 +360,19 @@ swfdec_text_field_movie_html_parse_tag (ParserData *data, const char *p)
SwfdecAsValue val;
if (name_length == 3 && !g_strncasecmp (name, "tab", 3))
- data->text = g_string_append_c (data->text, '\t');
+ swfdec_text_buffer_append_text (data->text, "\t");
if (data->multiline) {
if (name_length == 2 && !g_strncasecmp (name, "br", 2))
{
- data->text = g_string_append_c (data->text, '\n');
+ swfdec_text_buffer_append_text (data->text, "\n");
}
else if (name_length == 2 && !g_strncasecmp (name, "li", 1))
{
- if (data->text->len > 0 &&
- data->text->str[data->text->len - 1] != '\n' &&
- data->text->str[data->text->len - 1] != '\r')
- data->text = g_string_append_c (data->text, '\n');
+ gsize length = swfdec_text_buffer_get_length (data->text);
+ const char *s = swfdec_text_buffer_get_text (data->text);
+ if (length > 0 && s[length-1] != '\n' && s[length-1] != '\r')
+ swfdec_text_buffer_append_text (data->text, "\n");
}
}
@@ -380,7 +380,7 @@ swfdec_text_field_movie_html_parse_tag (ParserData *data, const char *p)
tag->name = name;
tag->name_length = name_length;
tag->format = SWFDEC_TEXT_FORMAT (swfdec_text_format_new (data->cx));
- tag->index = data->text->len;
+ tag->index = swfdec_text_buffer_get_length (data->text);
data->tags_open = g_slist_prepend (data->tags_open, tag);
@@ -445,8 +445,9 @@ swfdec_text_field_movie_html_parse_text (ParserData *data, const char *p)
// condense the space with previous text also, if version >= 8
if (data->condense_white && data->cx->version >= 8) {
- if (data->text->len > 0 &&
- g_ascii_isspace (data->text->str[data->text->len - 1]))
+ gsize length = swfdec_text_buffer_get_length (data->text);
+ const char *s = swfdec_text_buffer_get_text (data->text);
+ if (length > 0 && g_ascii_isspace (s[length - 1]))
p += strspn (p, " \n\r\t");
}
@@ -462,11 +463,11 @@ swfdec_text_field_movie_html_parse_text (ParserData *data, const char *p)
}
unescaped = swfdec_xml_unescape_len (data->cx, p, end - p, TRUE);
- data->text = g_string_append (data->text, unescaped);
+ swfdec_text_buffer_append_text (data->text, unescaped);
g_free (unescaped);
if (data->condense_white && g_ascii_isspace (*end)) {
- data->text = g_string_append_c (data->text, ' ');
+ swfdec_text_buffer_append_text (data->text, " ");
p = end + strspn (end, " \n\r\t");
} else {
p = end;
@@ -485,8 +486,6 @@ swfdec_text_field_movie_html_parse (SwfdecTextFieldMovie *text, const char *str)
g_return_if_fail (SWFDEC_IS_TEXT_FIELD_MOVIE (text));
g_return_if_fail (str != NULL);
- text->input = g_string_assign (text->input, "");
-
data.cx = SWFDEC_AS_OBJECT (text)->context;
data.multiline = (data.cx->version < 7 || text->multiline);
data.condense_white = text->condense_white;
@@ -495,7 +494,7 @@ swfdec_text_field_movie_html_parse (SwfdecTextFieldMovie *text, const char *str)
} else {
data.style_sheet = NULL;
}
- data.text = text->input;
+ data.text = text->text;
data.tags_open = NULL;
data.tags_closed = NULL;
@@ -527,8 +526,8 @@ swfdec_text_field_movie_html_parse (SwfdecTextFieldMovie *text, const char *str)
ParserTag *tag = (ParserTag *)data.tags_closed->data;
if (tag->index != tag->end_index && tag->format != NULL) {
- swfdec_text_field_movie_set_text_format (text, tag->format, tag->index,
- tag->end_index);
+ swfdec_text_buffer_set_attributes (text->text, tag->index,
+ tag->end_index - tag->index, &tag->format->attr, tag->format->values_set);
}
g_free (tag);
@@ -576,8 +575,9 @@ static GString *
swfdec_text_field_movie_html_text_append_paragraph (SwfdecTextFieldMovie *text,
GString *string, guint start_index, guint end_index)
{
- SwfdecTextFormat *format, *format_prev, *format_font;
- GSList *iter, *fonts, *iter_font;
+ const SwfdecTextAttributes *attr, *attr_prev, *attr_font;
+ SwfdecTextBufferIter *iter;
+ GSList *fonts, *iter_font;
guint index_, index_prev;
gboolean textformat, bullet, font = FALSE;
char *escaped;
@@ -586,41 +586,37 @@ swfdec_text_field_movie_html_text_append_paragraph (SwfdecTextFieldMovie *text,
g_return_val_if_fail (string != NULL, string);
g_return_val_if_fail (start_index <= end_index, string);
- g_return_val_if_fail (text->formats != NULL, string);
- for (iter = text->formats; iter->next != NULL &&
- ((SwfdecFormatIndex *)(iter->next->data))->index_ <= start_index;
- iter = iter->next);
-
+ iter = swfdec_text_buffer_get_iter (text->text, start_index);
index_ = start_index;
- format = ((SwfdecFormatIndex *)(iter->data))->format;
+ attr = swfdec_text_buffer_iter_get_attributes (text->text, iter);
- if (format->attr.left_margin != 0 || format->attr.right_margin != 0 ||
- format->attr.indent != 0 || format->attr.leading != 0 ||
- format->attr.block_indent != 0 ||
- format->attr.n_tab_stops > 0)
+ if (attr->left_margin != 0 || attr->right_margin != 0 ||
+ attr->indent != 0 || attr->leading != 0 ||
+ attr->block_indent != 0 ||
+ attr->n_tab_stops > 0)
{
string = g_string_append (string, "<TEXTFORMAT");
- if (format->attr.left_margin) {
+ if (attr->left_margin) {
g_string_append_printf (string, " LEFTMARGIN=\"%i\"",
- format->attr.left_margin);
+ attr->left_margin);
}
- if (format->attr.right_margin) {
+ if (attr->right_margin) {
g_string_append_printf (string, " RIGHTMARGIN=\"%i\"",
- format->attr.right_margin);
+ attr->right_margin);
}
- if (format->attr.indent)
- g_string_append_printf (string, " INDENT=\"%i\"", format->attr.indent);
- if (format->attr.leading)
- g_string_append_printf (string, " LEADING=\"%i\"", format->attr.leading);
- if (format->attr.block_indent) {
+ if (attr->indent)
+ g_string_append_printf (string, " INDENT=\"%i\"", attr->indent);
+ if (attr->leading)
+ g_string_append_printf (string, " LEADING=\"%i\"", attr->leading);
+ if (attr->block_indent) {
g_string_append_printf (string, " BLOCKINDENT=\"%i\"",
- format->attr.block_indent);
+ attr->block_indent);
}
- if (format->attr.n_tab_stops > 0) {
+ if (attr->n_tab_stops > 0) {
guint i;
g_string_append (string, " TABSTOPS=\"\"");
- for (i = 0; i < format->attr.n_tab_stops; i++) {
- g_string_append_printf (string, "%d,", format->attr.tab_stops[i]);
+ for (i = 0; i < attr->n_tab_stops; i++) {
+ g_string_append_printf (string, "%d,", attr->tab_stops[i]);
}
string->str[string->len - 1] = '\"';
}
@@ -633,81 +629,81 @@ swfdec_text_field_movie_html_text_append_paragraph (SwfdecTextFieldMovie *text,
textformat = FALSE;
}
- if (format->attr.bullet) {
+ if (attr->bullet) {
string = g_string_append (string, "<LI>");
bullet = TRUE;
} else {
g_string_append_printf (string, "<P ALIGN=\"%s\">",
- swfdec_text_field_movie_html_text_align_to_string (format->attr.align));
+ swfdec_text_field_movie_html_text_align_to_string (attr->align));
bullet = FALSE;
}
- // note we don't escape format->attr.font, even thought it can have evil chars
+ // note we don't escape attr->font, even thought it can have evil chars
g_string_append_printf (string, "<FONT FACE=\"%s\" SIZE=\"%i\" COLOR=\"#%06X\" LETTERSPACING=\"%i\" KERNING=\"%i\">",
- format->attr.font, format->attr.size, format->attr.color, (int)format->attr.letter_spacing,
- (format->attr.kerning ? 1 : 0));
- fonts = g_slist_prepend (NULL, format);
+ attr->font, attr->size, attr->color, (int)attr->letter_spacing,
+ (attr->kerning ? 1 : 0));
+ fonts = g_slist_prepend (NULL, (gpointer) attr);
- if (format->attr.url != SWFDEC_AS_STR_EMPTY)
+ if (attr->url != SWFDEC_AS_STR_EMPTY)
g_string_append_printf (string, "<A HREF=\"%s\" TARGET=\"%s\">",
- format->attr.url, format->attr.target);
- if (format->attr.bold)
+ attr->url, attr->target);
+ if (attr->bold)
string = g_string_append (string, "<B>");
- if (format->attr.italic)
+ if (attr->italic)
string = g_string_append (string, "<I>");
- if (format->attr.underline)
+ if (attr->underline)
string = g_string_append (string, "<U>");
// special case: use <= instead of < to add some extra markup
- for (iter = iter->next;
- iter != NULL && ((SwfdecFormatIndex *)(iter->data))->index_ <= end_index;
- iter = iter->next)
+ for (iter = swfdec_text_buffer_iter_next (text->text, iter);
+ iter != NULL && swfdec_text_buffer_iter_get_start (text->text, iter) <= end_index;
+ iter = swfdec_text_buffer_iter_next (text->text, iter))
{
index_prev = index_;
- format_prev = format;
- index_ = ((SwfdecFormatIndex *)(iter->data))->index_;
- format = ((SwfdecFormatIndex *)(iter->data))->format;
+ attr_prev = attr;
+ index_ = swfdec_text_buffer_iter_get_start (text->text, iter);
+ attr = swfdec_text_buffer_iter_get_attributes (text->text, iter);
- escaped = swfdec_xml_escape_len (text->input->str + index_prev,
+ escaped = swfdec_xml_escape_len (swfdec_text_buffer_get_text (text->text) + index_prev,
index_ - index_prev);
string = g_string_append (string, escaped);
g_free (escaped);
escaped = NULL;
// Figure out what tags need to be rewritten
- if (format->attr.font != format_prev->attr.font ||
- format->attr.size != format_prev->attr.size ||
- format->attr.color != format_prev->attr.color ||
- (int)format->attr.letter_spacing != (int)format_prev->attr.letter_spacing ||
- format->attr.kerning != format_prev->attr.kerning) {
+ if (attr->font != attr_prev->font ||
+ attr->size != attr_prev->size ||
+ attr->color != attr_prev->color ||
+ (int)attr->letter_spacing != (int)attr_prev->letter_spacing ||
+ attr->kerning != attr_prev->kerning) {
font = TRUE;
- } else if (format->attr.url == format_prev->attr.url &&
- format->attr.target == format_prev->attr.target &&
- format->attr.bold == format_prev->attr.bold &&
- format->attr.italic == format_prev->attr.italic &&
- format->attr.underline == format_prev->attr.underline) {
+ } else if (attr->url == attr_prev->url &&
+ attr->target == attr_prev->target &&
+ attr->bold == attr_prev->bold &&
+ attr->italic == attr_prev->italic &&
+ attr->underline == attr_prev->underline) {
continue;
}
// Close tags
for (iter_font = fonts; iter_font != NULL; iter_font = iter_font->next)
{
- format_font = (SwfdecTextFormat *)iter_font->data;
- if (format->attr.font == format_font->attr.font &&
- format->attr.size == format_font->attr.size &&
- format->attr.color == format_font->attr.color &&
- (int)format->attr.letter_spacing == (int)format_font->attr.letter_spacing &&
- format->attr.kerning == format_font->attr.kerning) {
+ attr_font = iter_font->data;
+ if (attr->font == attr_font->font &&
+ attr->size == attr_font->size &&
+ attr->color == attr_font->color &&
+ (int)attr->letter_spacing == (int)attr_font->letter_spacing &&
+ attr->kerning == attr_font->kerning) {
break;
}
}
- if (format_prev->attr.underline)
+ if (attr_prev->underline)
string = g_string_append (string, "</U>");
- if (format_prev->attr.italic)
+ if (attr_prev->italic)
string = g_string_append (string, "</I>");
- if (format_prev->attr.bold)
+ if (attr_prev->bold)
string = g_string_append (string, "</B>");
- if (format_prev->attr.url != SWFDEC_AS_STR_EMPTY)
+ if (attr_prev->url != SWFDEC_AS_STR_EMPTY)
string = g_string_append (string, "</A>");
if (iter_font != NULL) {
while (fonts != iter_font) {
@@ -717,59 +713,59 @@ swfdec_text_field_movie_html_text_append_paragraph (SwfdecTextFieldMovie *text,
}
// Open tags
- format_font = (SwfdecTextFormat *)fonts->data;
- if (font && (format->attr.font != format_font->attr.font ||
- format->attr.size != format_font->attr.size ||
- format->attr.color != format_font->attr.color ||
- (int)format->attr.letter_spacing != (int)format_font->attr.letter_spacing ||
- format->attr.kerning != format_font->attr.kerning))
+ attr_font = fonts->data;
+ if (font && (attr->font != attr_font->font ||
+ attr->size != attr_font->size ||
+ attr->color != attr_font->color ||
+ (int)attr->letter_spacing != (int)attr_font->letter_spacing ||
+ attr->kerning != attr_font->kerning))
{
- fonts = g_slist_prepend (fonts, format);
+ fonts = g_slist_prepend (fonts, (gpointer) attr);
string = g_string_append (string, "<FONT");
- // note we don't escape format->attr.font, even thought it can have evil chars
- if (format->attr.font != format_font->attr.font)
- g_string_append_printf (string, " FACE=\"%s\"", format->attr.font);
- if (format->attr.size != format_font->attr.size)
- g_string_append_printf (string, " SIZE=\"%i\"", format->attr.size);
- if (format->attr.color != format_font->attr.color)
- g_string_append_printf (string, " COLOR=\"#%06X\"", format->attr.color);
- if ((int)format->attr.letter_spacing != (int)format_font->attr.letter_spacing) {
+ // note we don't escape attr->font, even thought it can have evil chars
+ if (attr->font != attr_font->font)
+ g_string_append_printf (string, " FACE=\"%s\"", attr->font);
+ if (attr->size != attr_font->size)
+ g_string_append_printf (string, " SIZE=\"%i\"", attr->size);
+ if (attr->color != attr_font->color)
+ g_string_append_printf (string, " COLOR=\"#%06X\"", attr->color);
+ if ((int)attr->letter_spacing != (int)attr_font->letter_spacing) {
g_string_append_printf (string, " LETTERSPACING=\"%i\"",
- (int)format->attr.letter_spacing);
+ (int)attr->letter_spacing);
}
- if (format->attr.kerning != format_font->attr.kerning) {
+ if (attr->kerning != attr_font->kerning) {
g_string_append_printf (string, " KERNING=\"%i\"",
- (format->attr.kerning ? 1 : 0));
+ (attr->kerning ? 1 : 0));
}
string = g_string_append (string, ">");
}
- if (format->attr.url != SWFDEC_AS_STR_EMPTY) {
+ if (attr->url != SWFDEC_AS_STR_EMPTY) {
g_string_append_printf (string, "<A HREF=\"%s\" TARGET=\"%s\">",
- format->attr.url, format->attr.target);
+ attr->url, attr->target);
}
- if (format->attr.bold)
+ if (attr->bold)
string = g_string_append (string, "<B>");
- if (format->attr.italic)
+ if (attr->italic)
string = g_string_append (string, "<I>");
- if (format->attr.underline)
+ if (attr->underline)
string = g_string_append (string, "<U>");
}
- escaped = swfdec_xml_escape_len (text->input->str + index_,
+ escaped = swfdec_xml_escape_len (swfdec_text_buffer_get_text (text->text) + index_,
end_index - index_);
string = g_string_append (string, escaped);
g_free (escaped);
- if (format->attr.underline)
+ if (attr->underline)
string = g_string_append (string, "</U>");
- if (format->attr.italic)
+ if (attr->italic)
string = g_string_append (string, "</I>");
- if (format->attr.bold)
+ if (attr->bold)
string = g_string_append (string, "</B>");
- if (format->attr.url != SWFDEC_AS_STR_EMPTY)
+ if (attr->url != SWFDEC_AS_STR_EMPTY)
string = g_string_append (string, "</A>");
- for (iter = fonts; iter != NULL; iter = iter->next)
+ for (iter_font = fonts; iter_font != NULL; iter_font = iter_font->next)
string = g_string_append (string, "</FONT>");
g_slist_free (fonts);
if (bullet) {
@@ -786,25 +782,22 @@ swfdec_text_field_movie_html_text_append_paragraph (SwfdecTextFieldMovie *text,
const char *
swfdec_text_field_movie_get_html_text (SwfdecTextFieldMovie *text)
{
- const char *p, *end;
+ const char *p, *end, *start;
GString *string;
g_return_val_if_fail (SWFDEC_IS_TEXT_FIELD_MOVIE (text),
SWFDEC_AS_STR_EMPTY);
- if (text->input == NULL)
- return SWFDEC_AS_STR_EMPTY;
-
string = g_string_new ("");
+ p = start = swfdec_text_buffer_get_text (text->text);
- p = text->input->str;
while (*p != '\0') {
end = strpbrk (p, "\r\n");
if (end == NULL)
end = strchr (p, '\0');
string = swfdec_text_field_movie_html_text_append_paragraph (text, string,
- p - text->input->str, end - text->input->str);
+ p - start, end - start);
p = end;
if (*p != '\0') p++;
commit ce1cbefc3cc3492f9acefc5d0a8876d0a4b1659f
Author: Benjamin Otte <otte at gnome.org>
Date: Sun May 4 21:29:58 2008 +0200
change the format_new TextFormat to a default_attributes TextAtrributes
diff --git a/swfdec/swfdec_text_field_movie.c b/swfdec/swfdec_text_field_movie.c
index 95ebe17..dfb64fe 100644
--- a/swfdec/swfdec_text_field_movie.c
+++ b/swfdec/swfdec_text_field_movie.c
@@ -1022,7 +1022,7 @@ swfdec_text_field_movie_render (SwfdecMovie *movie, cairo_t *cr,
if (format && SWFDEC_TEXT_ATTRIBUTE_IS_SET (format->values_set, SWFDEC_TEXT_ATTRIBUTE_COLOR))
swfdec_color_set_source (cr, format->attr.color | SWFDEC_COLOR_COMBINE (0, 0, 0, 0xFF));
else
- swfdec_color_set_source (cr, text->format_new->attr.color | SWFDEC_COLOR_COMBINE (0, 0, 0, 0xFF));
+ swfdec_color_set_source (cr, text->default_attributes.color | SWFDEC_COLOR_COMBINE (0, 0, 0, 0xFF));
/* FIXME: what's the propwer line width here? */
cairo_set_line_width (cr, SWFDEC_DOUBLE_TO_TWIPS (0.5));
@@ -1223,6 +1223,8 @@ swfdec_text_field_movie_dispose (GObject *object)
text = SWFDEC_TEXT_FIELD_MOVIE (object);
+ swfdec_text_attributes_reset (&text->default_attributes);
+
if (text->asterisks != NULL) {
g_free (text->asterisks);
text->asterisks = NULL;
@@ -1260,12 +1262,10 @@ swfdec_text_field_movie_mark (SwfdecAsObject *object)
if (text->variable != NULL)
swfdec_as_string_mark (text->variable);
- swfdec_as_object_mark (SWFDEC_AS_OBJECT (text->format_new));
for (iter = text->formats; iter != NULL; iter = iter->next) {
swfdec_as_object_mark (
SWFDEC_AS_OBJECT (((SwfdecFormatIndex *)(iter->data))->format));
}
- swfdec_as_object_mark (SWFDEC_AS_OBJECT (text->format_new));
if (text->style_sheet != NULL)
swfdec_as_object_mark (text->style_sheet);
if (text->style_sheet_input != NULL)
@@ -1302,28 +1302,21 @@ swfdec_text_field_movie_init_movie (SwfdecMovie *movie)
swfdec_as_object_call (SWFDEC_AS_OBJECT (movie), SWFDEC_AS_STR_addListener,
1, &val, NULL);
- // format
- text->format_new =
- SWFDEC_TEXT_FORMAT (swfdec_text_format_new_no_properties (cx));
- if (!text->format_new)
- goto out;
-
text->border_color = SWFDEC_COLOR_COMBINE (0, 0, 0, 0);
text->background_color = SWFDEC_COLOR_COMBINE (255, 255, 255, 0);
- swfdec_text_format_set_defaults (text->format_new);
if (text_field) {
- text->format_new->attr.color = text_field->color;
- text->format_new->attr.align = text_field->align;
+ text->default_attributes.color = text_field->color;
+ text->default_attributes.align = text_field->align;
if (text_field->font != NULL) {
- text->format_new->attr.font =
+ text->default_attributes.font =
swfdec_as_context_get_string (cx, text_field->font);
}
- text->format_new->attr.size = text_field->size / 20;
- text->format_new->attr.left_margin = text_field->left_margin / 20;
- text->format_new->attr.right_margin = text_field->right_margin / 20;
- text->format_new->attr.indent = text_field->indent / 20;
- text->format_new->attr.leading = text_field->leading / 20;
+ text->default_attributes.size = text_field->size / 20;
+ text->default_attributes.left_margin = text_field->left_margin / 20;
+ text->default_attributes.right_margin = text_field->right_margin / 20;
+ text->default_attributes.indent = text_field->indent / 20;
+ text->default_attributes.leading = text_field->leading / 20;
}
// text
@@ -1342,7 +1335,6 @@ swfdec_text_field_movie_init_movie (SwfdecMovie *movie)
swfdec_as_context_get_string (cx, text_field->variable));
}
-out:
if (needs_unuse)
swfdec_sandbox_unuse (movie->resource->sandbox);
}
@@ -1728,6 +1720,9 @@ swfdec_text_field_movie_init (SwfdecTextFieldMovie *text)
text->input = g_string_new ("");
text->scroll = 1;
text->mouse_wheel_enabled = TRUE;
+
+ swfdec_text_attributes_reset (&text->default_attributes);
+
}
void
@@ -2076,28 +2071,27 @@ swfdec_text_field_movie_set_text (SwfdecTextFieldMovie *text, const char *str,
g_return_if_fail (SWFDEC_IS_TEXT_FIELD_MOVIE (text));
g_return_if_fail (str != NULL);
- if (text->format_new == NULL) {
- text->input = g_string_truncate (text->input, 0);
- return;
- }
-
// remove old formatting info
g_slist_foreach (text->formats, (GFunc) g_free, NULL);
g_slist_free (text->formats);
text->formats = NULL;
- // add the default style
+ /* Flash 7 resets to default style here */
if (html && SWFDEC_AS_OBJECT (text)->context->version < 8)
- swfdec_text_format_set_defaults (text->format_new);
+ swfdec_text_attributes_reset (&text->default_attributes);
+
block = g_new (SwfdecFormatIndex, 1);
block->index_ = 0;
- g_assert (SWFDEC_IS_TEXT_FORMAT (text->format_new));
- block->format = swfdec_text_format_copy (text->format_new);
+ block->format = SWFDEC_TEXT_FORMAT (
+ swfdec_text_format_new_no_properties (SWFDEC_AS_OBJECT (text)->context));
if (block->format == NULL) {
g_free (block);
text->input = g_string_truncate (text->input, 0);
return;
}
+ swfdec_text_attributes_copy (&block->format->attr, &text->default_attributes,
+ SWFDEC_TEXT_ATTRIBUTES_MASK);
+ block->format->values_set = SWFDEC_TEXT_ATTRIBUTES_MASK;
text->formats = g_slist_prepend (text->formats, block);
text->input_html = html;
diff --git a/swfdec/swfdec_text_field_movie.h b/swfdec/swfdec_text_field_movie.h
index 7bd978b..4e22dc2 100644
--- a/swfdec/swfdec_text_field_movie.h
+++ b/swfdec/swfdec_text_field_movie.h
@@ -109,7 +109,7 @@ struct _SwfdecTextFieldMovie {
const char * variable;
- SwfdecTextFormat * format_new;
+ SwfdecTextAttributes default_attributes;
GSList * formats;
gboolean condense_white;
diff --git a/swfdec/swfdec_text_field_movie_as.c b/swfdec/swfdec_text_field_movie_as.c
index 94d543e..5a7f423 100644
--- a/swfdec/swfdec_text_field_movie_as.c
+++ b/swfdec/swfdec_text_field_movie_as.c
@@ -958,7 +958,7 @@ swfdec_text_field_movie_get_textColor (SwfdecAsContext *cx,
SWFDEC_AS_CHECK (SWFDEC_TYPE_TEXT_FIELD_MOVIE, &text, "");
- SWFDEC_AS_VALUE_SET_NUMBER (ret, text->format_new->attr.color);
+ SWFDEC_AS_VALUE_SET_NUMBER (ret, text->default_attributes.color);
}
// This doesn't work the same way as TextFormat's color setting
@@ -972,7 +972,7 @@ swfdec_text_field_movie_set_textColor (SwfdecAsContext *cx,
SWFDEC_AS_CHECK (SWFDEC_TYPE_TEXT_FIELD_MOVIE, &text, "i", &value);
- text->format_new->attr.color = swfdec_text_field_movie_int_to_color (cx, value);
+ text->default_attributes.color = swfdec_text_field_movie_int_to_color (cx, value);
}
SWFDEC_AS_NATIVE (104, 300, swfdec_text_field_movie_get_gridFitType)
@@ -1075,13 +1075,19 @@ swfdec_text_field_movie_getNewTextFormat (SwfdecAsContext *cx,
SwfdecAsValue *ret)
{
SwfdecTextFieldMovie *text;
+ SwfdecTextFormat *format;
SWFDEC_AS_CHECK (SWFDEC_TYPE_TEXT_FIELD_MOVIE, &text, "");
- swfdec_text_format_init_properties (cx);
+ format = SWFDEC_TEXT_FORMAT (swfdec_text_format_new (cx));
+ if (format == NULL)
+ return;
+
+ swfdec_text_attributes_copy (&format->attr, &text->default_attributes,
+ SWFDEC_TEXT_ATTRIBUTES_MASK);
+ format->values_set = SWFDEC_TEXT_ATTRIBUTES_MASK;
- SWFDEC_AS_VALUE_SET_OBJECT (ret,
- SWFDEC_AS_OBJECT (swfdec_text_format_copy (text->format_new)));
+ SWFDEC_AS_VALUE_SET_OBJECT (ret, SWFDEC_AS_OBJECT (format));
}
SWFDEC_AS_NATIVE (104, 105, swfdec_text_field_movie_setNewTextFormat)
@@ -1091,14 +1097,15 @@ swfdec_text_field_movie_setNewTextFormat (SwfdecAsContext *cx,
SwfdecAsValue *ret)
{
SwfdecTextFieldMovie *text;
- SwfdecAsObject *obj;
+ SwfdecTextFormat *format;
- SWFDEC_AS_CHECK (SWFDEC_TYPE_TEXT_FIELD_MOVIE, &text, "o", &obj);
+ SWFDEC_AS_CHECK (SWFDEC_TYPE_TEXT_FIELD_MOVIE, &text, "o", &format);
- if (!SWFDEC_IS_TEXT_FORMAT (obj))
+ if (!SWFDEC_IS_TEXT_FORMAT (format))
return;
- swfdec_text_format_add (text->format_new, SWFDEC_TEXT_FORMAT (obj));
+ swfdec_text_attributes_copy (&text->default_attributes, &format->attr,
+ format->values_set);
}
SWFDEC_AS_NATIVE (104, 102, swfdec_text_field_movie_setTextFormat)
diff --git a/swfdec/swfdec_text_field_movie_html.c b/swfdec/swfdec_text_field_movie_html.c
index 2c834cd..bd8049f 100644
--- a/swfdec/swfdec_text_field_movie_html.c
+++ b/swfdec/swfdec_text_field_movie_html.c
@@ -514,8 +514,10 @@ swfdec_text_field_movie_html_parse (SwfdecTextFieldMovie *text, const char *str)
// close remaining tags
while (data.tags_open != NULL) {
- swfdec_text_format_add (text->format_new,
- ((ParserTag *)data.tags_open->data)->format);
+ /* yes, this really appends to the default format */
+ swfdec_text_attributes_copy (&text->default_attributes,
+ &((ParserTag *)data.tags_open->data)->format->attr,
+ ((ParserTag *)data.tags_open->data)->format->values_set);
swfdec_text_field_movie_html_parse_close_tag (&data,
(ParserTag *)data.tags_open->data, TRUE);
}
commit 3f8d634fbbe4f927d7664f3ed706fdc68b48bb41
Author: Benjamin Otte <otte at gnome.org>
Date: Sun May 4 18:30:55 2008 +0200
add SWFEC_TEXT_ATTRIBUTES_MASK
diff --git a/swfdec/swfdec_text_attributes.h b/swfdec/swfdec_text_attributes.h
index 6d00d37..1736f4a 100644
--- a/swfdec/swfdec_text_attributes.h
+++ b/swfdec/swfdec_text_attributes.h
@@ -71,6 +71,8 @@ typedef enum {
SWFDEC_TEXT_ATTRIBUTE_URL,
} SwfdecTextAttribute;
+#define SWFDEC_TEXT_ATTRIBUTES_MASK ((1 << (SWFDEC_TEXT_ATTRIBUTE_URL + 1)) - 1)
+
#define SWFDEC_TEXT_ATTRIBUTE_SET(flags, attribute) ((flags) |= (1 << (attribute)))
#define SWFDEC_TEXT_ATTRIBUTE_UNSET(flags, attribute) ((flags) &= ~(1 << (attribute)))
#define SWFDEC_TEXT_ATTRIBUTE_IS_SET(flags, attribute) (((flags) & (1 << (attribute))) ? TRUE : FALSE)
diff --git a/swfdec/swfdec_text_format.c b/swfdec/swfdec_text_format.c
index f65b23e..b98179b 100644
--- a/swfdec/swfdec_text_format.c
+++ b/swfdec/swfdec_text_format.c
@@ -935,7 +935,7 @@ void
swfdec_text_format_set_defaults (SwfdecTextFormat *format)
{
swfdec_text_attributes_reset (&format->attr);
- format->values_set = -1;
+ format->values_set = SWFDEC_TEXT_ATTRIBUTES_MASK;
if (SWFDEC_AS_OBJECT (format)->context->version < 8) {
SWFDEC_TEXT_ATTRIBUTE_UNSET (format->values_set, SWFDEC_TEXT_ATTRIBUTE_KERNING);
commit 38259f931f9c17de8484b623b03825e61ba7fd97
Author: Benjamin Otte <otte at gnome.org>
Date: Sun May 4 14:55:12 2008 +0200
update loaded movie rendering to the recent image handling changes
diff --git a/swfdec/swfdec_movie.c b/swfdec/swfdec_movie.c
index 8ff6213..48a27d7 100644
--- a/swfdec/swfdec_movie.c
+++ b/swfdec/swfdec_movie.c
@@ -1182,18 +1182,26 @@ swfdec_movie_do_render (SwfdecMovie *movie, cairo_t *cr,
/* if the movie loaded an image, draw it here now */
if (movie->image) {
SwfdecRenderer *renderer = swfdec_renderer_get (cr);
- cairo_surface_t *surface = swfdec_image_create_surface_transformed (movie->image,
+ cairo_surface_t *surface;
+ cairo_pattern_t *pattern;
+
+ if (swfdec_color_transform_is_mask (ctrans))
+ surface = NULL;
+ else
+ surface = swfdec_image_create_surface_transformed (movie->image,
renderer, ctrans);
if (surface) {
static const cairo_matrix_t matrix = { 1.0 / SWFDEC_TWIPS_SCALE_FACTOR, 0, 0, 1.0 / SWFDEC_TWIPS_SCALE_FACTOR, 0, 0 };
- cairo_pattern_t *pattern = cairo_pattern_create_for_surface (surface);
+ pattern = cairo_pattern_create_for_surface (surface);
SWFDEC_LOG ("rendering loaded image");
cairo_pattern_set_matrix (pattern, &matrix);
- cairo_set_source (cr, pattern);
- cairo_paint (cr);
- cairo_pattern_destroy (pattern);
- cairo_surface_destroy (surface);
+ } else {
+ pattern = cairo_pattern_create_rgb (1.0, 0.0, 0.0);
}
+ cairo_set_source (cr, pattern);
+ cairo_paint (cr);
+ cairo_pattern_destroy (pattern);
+ cairo_surface_destroy (surface);
}
/* draw the children movies */
commit 17ea7d911622113890a73e032f2753e070817500
Author: Benjamin Otte <otte at gnome.org>
Date: Sun May 4 14:44:09 2008 +0200
fix list of included headers
diff --git a/swfdec/swfdec_text_attributes.h b/swfdec/swfdec_text_attributes.h
index 6e39926..6d00d37 100644
--- a/swfdec/swfdec_text_attributes.h
+++ b/swfdec/swfdec_text_attributes.h
@@ -21,10 +21,8 @@
#ifndef _SWFDEC_TEXT_ATTRIBUTES_H_
#define _SWFDEC_TEXT_ATTRIBUTES_H_
-#include <swfdec/swfdec_as_object.h>
-#include <swfdec/swfdec_as_array.h>
-#include <swfdec/swfdec_types.h>
-#include <swfdec/swfdec_script.h>
+#include <glib.h>
+#include <swfdec/swfdec_color.h>
G_BEGIN_DECLS
commit 65282460ffeebc2640190a30a2645a72bea884d1
Author: Benjamin Otte <otte at gnome.org>
Date: Sun May 4 13:29:02 2008 +0200
convert SwfdecTextFormat to use text attributes
diff --git a/swfdec/swfdec_text_attributes.h b/swfdec/swfdec_text_attributes.h
index 267002d..6e39926 100644
--- a/swfdec/swfdec_text_attributes.h
+++ b/swfdec/swfdec_text_attributes.h
@@ -73,9 +73,9 @@ typedef enum {
SWFDEC_TEXT_ATTRIBUTE_URL,
} SwfdecTextAttribute;
-#define SWFDEC_TEXT_ATTRIBUTE_SET(flags, attribute) ((flags) |= 1 << (attribute))
+#define SWFDEC_TEXT_ATTRIBUTE_SET(flags, attribute) ((flags) |= (1 << (attribute)))
#define SWFDEC_TEXT_ATTRIBUTE_UNSET(flags, attribute) ((flags) &= ~(1 << (attribute)))
-#define SWFDEC_TEXT_ATTRIBUTE_IS_SET(flags, attribute) ((flags) & (1 << (attribute)) ? TRUE : FALSE)
+#define SWFDEC_TEXT_ATTRIBUTE_IS_SET(flags, attribute) (((flags) & (1 << (attribute))) ? TRUE : FALSE)
struct _SwfdecTextAttributes {
SwfdecTextAlign align;
diff --git a/swfdec/swfdec_text_field_movie.c b/swfdec/swfdec_text_field_movie.c
index 7bf23d5..95ebe17 100644
--- a/swfdec/swfdec_text_field_movie.c
+++ b/swfdec/swfdec_text_field_movie.c
@@ -140,15 +140,14 @@ static void
swfdec_text_paragraph_add_block (SwfdecParagraph *paragraph, int index_,
SwfdecTextFormat *format)
{
- gint32 length, i;
+ guint i;
SwfdecBlock *block;
- SwfdecAsValue val;
block = g_new0 (SwfdecBlock, 1);
block->index_ = index_;
- switch (format->align) {
+ switch (format->attr.align) {
case SWFDEC_TEXT_ALIGN_LEFT:
block->align = PANGO_ALIGN_LEFT;
block->justify = FALSE;
@@ -168,19 +167,16 @@ swfdec_text_paragraph_add_block (SwfdecParagraph *paragraph, int index_,
default:
g_assert_not_reached ();
}
- block->leading = format->leading * 20 * PANGO_SCALE;
- block->block_indent = format->block_indent * 20;
- block->left_margin = format->left_margin * 20;
- block->right_margin = format->right_margin * 20;
-
- if (format->tab_stops != NULL) {
- length = swfdec_as_array_get_length (format->tab_stops);
- block->tab_stops = pango_tab_array_new (length, TRUE);
- for (i = 0; i < length; i++) {
- swfdec_as_array_get_value (format->tab_stops, i, &val);
- g_assert (SWFDEC_AS_VALUE_IS_NUMBER (&val));
+ block->leading = format->attr.leading * 20 * PANGO_SCALE;
+ block->block_indent = format->attr.block_indent * 20;
+ block->left_margin = format->attr.left_margin * 20;
+ block->right_margin = format->attr.right_margin * 20;
+
+ if (format->attr.n_tab_stops != 0) {
+ block->tab_stops = pango_tab_array_new (format->attr.n_tab_stops, TRUE);
+ for (i = 0; i < format->attr.n_tab_stops; i++) {
pango_tab_array_set_tab (block->tab_stops, i, PANGO_TAB_LEFT,
- SWFDEC_AS_VALUE_GET_NUMBER (&val) * 20);
+ format->attr.tab_stops[i] * 20);
}
} else {
block->tab_stops = NULL;
@@ -225,40 +221,40 @@ swfdec_text_field_movie_generate_paragraph (SwfdecTextFieldMovie *text,
format = ((SwfdecFormatIndex *)(iter->data))->format;
// Paragraph formats
- paragraph->bullet = format->bullet;
- paragraph->indent = format->indent * 20 * PANGO_SCALE;
+ paragraph->bullet = format->attr.bullet;
+ paragraph->indent = format->attr.indent * 20 * PANGO_SCALE;
// Add new block
swfdec_text_paragraph_add_block (paragraph, 0, format);
// Open attributes
attr_bold = pango_attr_weight_new (
- (format->bold ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL));
+ (format->attr.bold ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL));
attr_bold->start_index = 0;
- attr_color = pango_attr_foreground_new (SWFDEC_COLOR_R (format->color) * 255,
- SWFDEC_COLOR_G (format->color) * 255,
- SWFDEC_COLOR_B (format->color) * 255);
+ attr_color = pango_attr_foreground_new (SWFDEC_COLOR_R (format->attr.color) * 255,
+ SWFDEC_COLOR_G (format->attr.color) * 255,
+ SWFDEC_COLOR_B (format->attr.color) * 255);
attr_color->start_index = 0;
// FIXME: embed fonts
- attr_font = pango_attr_family_new (format->font);
+ attr_font = pango_attr_family_new (format->attr.font);
attr_font->start_index = 0;
attr_italic = pango_attr_style_new (
- (format->italic ? PANGO_STYLE_ITALIC : PANGO_STYLE_NORMAL));
+ (format->attr.italic ? PANGO_STYLE_ITALIC : PANGO_STYLE_NORMAL));
attr_italic->start_index = 0;
attr_letter_spacing = pango_attr_letter_spacing_new (
- format->letter_spacing * 20 * PANGO_SCALE);
+ format->attr.letter_spacing * 20 * PANGO_SCALE);
attr_letter_spacing->start_index = 0;
attr_size =
- pango_attr_size_new_absolute (MAX (format->size, 1) * 20 * PANGO_SCALE);
+ pango_attr_size_new_absolute (MAX (format->attr.size, 1) * 20 * PANGO_SCALE);
attr_size->start_index = 0;
attr_underline = pango_attr_underline_new (
- (format->underline ? PANGO_UNDERLINE_SINGLE : PANGO_UNDERLINE_NONE));
+ (format->attr.underline ? PANGO_UNDERLINE_SINGLE : PANGO_UNDERLINE_NONE));
attr_underline->start_index = 0;
for (iter = iter->next;
@@ -271,80 +267,80 @@ swfdec_text_field_movie_generate_paragraph (SwfdecTextFieldMovie *text,
format = ((SwfdecFormatIndex *)(iter->data))->format;
// Add new block if necessary
- if (format_prev->align != format->align ||
- format_prev->bullet != format->bullet ||
- format_prev->indent != format->indent ||
- format_prev->leading != format->leading ||
- format_prev->block_indent != format->block_indent ||
- format_prev->left_margin != format->left_margin)
+ if (format_prev->attr.align != format->attr.align ||
+ format_prev->attr.bullet != format->attr.bullet ||
+ format_prev->attr.indent != format->attr.indent ||
+ format_prev->attr.leading != format->attr.leading ||
+ format_prev->attr.block_indent != format->attr.block_indent ||
+ format_prev->attr.left_margin != format->attr.left_margin)
{
swfdec_text_paragraph_add_block (paragraph, index_ - start_index,
format);
}
// Change attributes if necessary
- if (format_prev->bold != format->bold) {
+ if (format_prev->attr.bold != format->attr.bold) {
attr_bold->end_index = index_ - start_index;
swfdec_text_paragraph_add_attribute (paragraph, attr_bold);
attr_bold = pango_attr_weight_new (
- (format->bold ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL));
+ (format->attr.bold ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL));
attr_bold->start_index = index_ - start_index;
}
- if (format_prev->color != format->color) {
+ if (format_prev->attr.color != format->attr.color) {
attr_color->end_index = index_ - start_index;
swfdec_text_paragraph_add_attribute (paragraph, attr_color);
attr_color = pango_attr_foreground_new (
- SWFDEC_COLOR_R (format->color) * 255,
- SWFDEC_COLOR_G (format->color) * 255,
- SWFDEC_COLOR_B (format->color) * 255);
+ SWFDEC_COLOR_R (format->attr.color) * 255,
+ SWFDEC_COLOR_G (format->attr.color) * 255,
+ SWFDEC_COLOR_B (format->attr.color) * 255);
attr_color->start_index = index_ - start_index;
}
- if (format_prev->font != format->font) {
+ if (format_prev->attr.font != format->attr.font) {
attr_font->end_index = index_ - start_index;
swfdec_text_paragraph_add_attribute (paragraph, attr_font);
// FIXME: embed fonts
- attr_font = pango_attr_family_new (format->font);
+ attr_font = pango_attr_family_new (format->attr.font);
attr_font->start_index = index_ - start_index;
}
- if (format_prev->italic != format->italic) {
+ if (format_prev->attr.italic != format->attr.italic) {
attr_italic->end_index = index_ - start_index;
swfdec_text_paragraph_add_attribute (paragraph, attr_italic);
attr_italic = pango_attr_style_new (
- (format->italic ? PANGO_STYLE_ITALIC : PANGO_STYLE_NORMAL));
+ (format->attr.italic ? PANGO_STYLE_ITALIC : PANGO_STYLE_NORMAL));
attr_italic->start_index = index_ - start_index;
}
- if (format_prev->letter_spacing != format->letter_spacing) {
+ if (format_prev->attr.letter_spacing != format->attr.letter_spacing) {
attr_letter_spacing->end_index = index_ - start_index;
swfdec_text_paragraph_add_attribute (paragraph, attr_letter_spacing);
attr_letter_spacing = pango_attr_letter_spacing_new (
- format->letter_spacing * 20 * PANGO_SCALE);
+ format->attr.letter_spacing * 20 * PANGO_SCALE);
attr_letter_spacing->start_index = index_ - start_index;
}
- if (format_prev->size != format->size) {
+ if (format_prev->attr.size != format->attr.size) {
attr_size->end_index = index_ - start_index;
swfdec_text_paragraph_add_attribute (paragraph, attr_size);
attr_size = pango_attr_size_new_absolute (
- MAX (1, format->size) * 20 * PANGO_SCALE);
+ MAX (1, format->attr.size) * 20 * PANGO_SCALE);
attr_size->start_index = index_ - start_index;
}
- if (format_prev->underline != format->underline) {
+ if (format_prev->attr.underline != format->attr.underline) {
attr_underline->end_index = index_ - start_index;
swfdec_text_paragraph_add_attribute (paragraph, attr_underline);
attr_underline = pango_attr_underline_new (
- (format->underline ? PANGO_UNDERLINE_SINGLE : PANGO_UNDERLINE_NONE));
+ (format->attr.underline ? PANGO_UNDERLINE_SINGLE : PANGO_UNDERLINE_NONE));
attr_underline->start_index = index_ - start_index;
}
}
@@ -1023,10 +1019,10 @@ swfdec_text_field_movie_render (SwfdecMovie *movie, cairo_t *cr,
&cursor_rect, NULL);
cairo_save (cr);
- if (format && format->values_set & (1 << SWFDEC_TEXT_FORMAT_COLOR))
- swfdec_color_set_source (cr, format->color | SWFDEC_COLOR_COMBINE (0, 0, 0, 0xFF));
+ if (format && SWFDEC_TEXT_ATTRIBUTE_IS_SET (format->values_set, SWFDEC_TEXT_ATTRIBUTE_COLOR))
+ swfdec_color_set_source (cr, format->attr.color | SWFDEC_COLOR_COMBINE (0, 0, 0, 0xFF));
else
- swfdec_color_set_source (cr, text->format_new->color | SWFDEC_COLOR_COMBINE (0, 0, 0, 0xFF));
+ swfdec_color_set_source (cr, text->format_new->attr.color | SWFDEC_COLOR_COMBINE (0, 0, 0, 0xFF));
/* FIXME: what's the propwer line width here? */
cairo_set_line_width (cr, SWFDEC_DOUBLE_TO_TWIPS (0.5));
@@ -1317,17 +1313,17 @@ swfdec_text_field_movie_init_movie (SwfdecMovie *movie)
swfdec_text_format_set_defaults (text->format_new);
if (text_field) {
- text->format_new->color = text_field->color;
- text->format_new->align = text_field->align;
+ text->format_new->attr.color = text_field->color;
+ text->format_new->attr.align = text_field->align;
if (text_field->font != NULL) {
- text->format_new->font =
+ text->format_new->attr.font =
swfdec_as_context_get_string (cx, text_field->font);
}
- text->format_new->size = text_field->size / 20;
- text->format_new->left_margin = text_field->left_margin / 20;
- text->format_new->right_margin = text_field->right_margin / 20;
- text->format_new->indent = text_field->indent / 20;
- text->format_new->leading = text_field->leading / 20;
+ text->format_new->attr.size = text_field->size / 20;
+ text->format_new->attr.left_margin = text_field->left_margin / 20;
+ text->format_new->attr.right_margin = text_field->right_margin / 20;
+ text->format_new->attr.indent = text_field->indent / 20;
+ text->format_new->attr.leading = text_field->leading / 20;
}
// text
@@ -1421,10 +1417,10 @@ swfdec_text_field_movie_letter_clicked (SwfdecTextFieldMovie *text,
format = swfdec_text_field_movie_format_for_index (text, index_);
- if (format != NULL && format->url != NULL &&
- format->url != SWFDEC_AS_STR_EMPTY) {
+ if (format != NULL && format->attr.url != NULL &&
+ format->attr.url != SWFDEC_AS_STR_EMPTY) {
swfdec_player_launch (SWFDEC_PLAYER (SWFDEC_AS_OBJECT (text)->context),
- SWFDEC_LOADER_REQUEST_DEFAULT, format->url, format->target, NULL);
+ SWFDEC_LOADER_REQUEST_DEFAULT, format->attr.url, format->attr.target, NULL);
}
}
@@ -1494,8 +1490,8 @@ swfdec_text_field_movie_mouse_cursor (SwfdecActor *actor)
format = NULL;
}
- if (format != NULL && format->url != NULL &&
- format->url != SWFDEC_AS_STR_EMPTY) {
+ if (format != NULL && format->attr.url != NULL &&
+ format->attr.url != SWFDEC_AS_STR_EMPTY) {
return SWFDEC_MOUSE_CURSOR_CLICK;
} else if (text->editable || text->selectable) {
return SWFDEC_MOUSE_CURSOR_TEXT;
diff --git a/swfdec/swfdec_text_field_movie_as.c b/swfdec/swfdec_text_field_movie_as.c
index 166e9ad..94d543e 100644
--- a/swfdec/swfdec_text_field_movie_as.c
+++ b/swfdec/swfdec_text_field_movie_as.c
@@ -958,7 +958,7 @@ swfdec_text_field_movie_get_textColor (SwfdecAsContext *cx,
SWFDEC_AS_CHECK (SWFDEC_TYPE_TEXT_FIELD_MOVIE, &text, "");
- SWFDEC_AS_VALUE_SET_NUMBER (ret, text->format_new->color);
+ SWFDEC_AS_VALUE_SET_NUMBER (ret, text->format_new->attr.color);
}
// This doesn't work the same way as TextFormat's color setting
@@ -972,7 +972,7 @@ swfdec_text_field_movie_set_textColor (SwfdecAsContext *cx,
SWFDEC_AS_CHECK (SWFDEC_TYPE_TEXT_FIELD_MOVIE, &text, "i", &value);
- text->format_new->color = swfdec_text_field_movie_int_to_color (cx, value);
+ text->format_new->attr.color = swfdec_text_field_movie_int_to_color (cx, value);
}
SWFDEC_AS_NATIVE (104, 300, swfdec_text_field_movie_get_gridFitType)
diff --git a/swfdec/swfdec_text_field_movie_html.c b/swfdec/swfdec_text_field_movie_html.c
index 1315f12..2c834cd 100644
--- a/swfdec/swfdec_text_field_movie_html.c
+++ b/swfdec/swfdec_text_field_movie_html.c
@@ -592,34 +592,35 @@ swfdec_text_field_movie_html_text_append_paragraph (SwfdecTextFieldMovie *text,
index_ = start_index;
format = ((SwfdecFormatIndex *)(iter->data))->format;
- if (format->left_margin != 0 || format->right_margin != 0 ||
- format->indent != 0 || format->leading != 0 ||
- format->block_indent != 0 ||
- swfdec_as_array_get_length (format->tab_stops) > 0)
+ if (format->attr.left_margin != 0 || format->attr.right_margin != 0 ||
+ format->attr.indent != 0 || format->attr.leading != 0 ||
+ format->attr.block_indent != 0 ||
+ format->attr.n_tab_stops > 0)
{
string = g_string_append (string, "<TEXTFORMAT");
- if (format->left_margin) {
+ if (format->attr.left_margin) {
g_string_append_printf (string, " LEFTMARGIN=\"%i\"",
- format->left_margin);
+ format->attr.left_margin);
}
- if (format->right_margin) {
+ if (format->attr.right_margin) {
g_string_append_printf (string, " RIGHTMARGIN=\"%i\"",
- format->right_margin);
+ format->attr.right_margin);
}
- if (format->indent)
- g_string_append_printf (string, " INDENT=\"%i\"", format->indent);
- if (format->leading)
- g_string_append_printf (string, " LEADING=\"%i\"", format->leading);
- if (format->block_indent) {
+ if (format->attr.indent)
+ g_string_append_printf (string, " INDENT=\"%i\"", format->attr.indent);
+ if (format->attr.leading)
+ g_string_append_printf (string, " LEADING=\"%i\"", format->attr.leading);
+ if (format->attr.block_indent) {
g_string_append_printf (string, " BLOCKINDENT=\"%i\"",
- format->block_indent);
+ format->attr.block_indent);
}
- if (swfdec_as_array_get_length (format->tab_stops) > 0) {
- SwfdecAsValue val;
- SWFDEC_AS_VALUE_SET_OBJECT (&val, SWFDEC_AS_OBJECT (format->tab_stops));
- g_string_append_printf (string, " TABSTOPS=\"%s\"",
- swfdec_as_value_to_string (SWFDEC_AS_OBJECT
- (format->tab_stops)->context, &val));
+ if (format->attr.n_tab_stops > 0) {
+ guint i;
+ g_string_append (string, " TABSTOPS=\"\"");
+ for (i = 0; i < format->attr.n_tab_stops; i++) {
+ g_string_append_printf (string, "%d,", format->attr.tab_stops[i]);
+ }
+ string->str[string->len - 1] = '\"';
}
string = g_string_append (string, ">");
@@ -630,29 +631,29 @@ swfdec_text_field_movie_html_text_append_paragraph (SwfdecTextFieldMovie *text,
textformat = FALSE;
}
- if (format->bullet) {
+ if (format->attr.bullet) {
string = g_string_append (string, "<LI>");
bullet = TRUE;
} else {
g_string_append_printf (string, "<P ALIGN=\"%s\">",
- swfdec_text_field_movie_html_text_align_to_string (format->align));
+ swfdec_text_field_movie_html_text_align_to_string (format->attr.align));
bullet = FALSE;
}
- // note we don't escape format->font, even thought it can have evil chars
+ // note we don't escape format->attr.font, even thought it can have evil chars
g_string_append_printf (string, "<FONT FACE=\"%s\" SIZE=\"%i\" COLOR=\"#%06X\" LETTERSPACING=\"%i\" KERNING=\"%i\">",
- format->font, format->size, format->color, (int)format->letter_spacing,
- (format->kerning ? 1 : 0));
+ format->attr.font, format->attr.size, format->attr.color, (int)format->attr.letter_spacing,
+ (format->attr.kerning ? 1 : 0));
fonts = g_slist_prepend (NULL, format);
- if (format->url != SWFDEC_AS_STR_EMPTY)
+ if (format->attr.url != SWFDEC_AS_STR_EMPTY)
g_string_append_printf (string, "<A HREF=\"%s\" TARGET=\"%s\">",
- format->url, format->target);
- if (format->bold)
+ format->attr.url, format->attr.target);
+ if (format->attr.bold)
string = g_string_append (string, "<B>");
- if (format->italic)
+ if (format->attr.italic)
string = g_string_append (string, "<I>");
- if (format->underline)
+ if (format->attr.underline)
string = g_string_append (string, "<U>");
// special case: use <= instead of < to add some extra markup
@@ -672,17 +673,17 @@ swfdec_text_field_movie_html_text_append_paragraph (SwfdecTextFieldMovie *text,
escaped = NULL;
// Figure out what tags need to be rewritten
- if (format->font != format_prev->font ||
- format->size != format_prev->size ||
- format->color != format_prev->color ||
- (int)format->letter_spacing != (int)format_prev->letter_spacing ||
- format->kerning != format_prev->kerning) {
+ if (format->attr.font != format_prev->attr.font ||
+ format->attr.size != format_prev->attr.size ||
+ format->attr.color != format_prev->attr.color ||
+ (int)format->attr.letter_spacing != (int)format_prev->attr.letter_spacing ||
+ format->attr.kerning != format_prev->attr.kerning) {
font = TRUE;
- } else if (format->url == format_prev->url &&
- format->target == format_prev->target &&
- format->bold == format_prev->bold &&
- format->italic == format_prev->italic &&
- format->underline == format_prev->underline) {
+ } else if (format->attr.url == format_prev->attr.url &&
+ format->attr.target == format_prev->attr.target &&
+ format->attr.bold == format_prev->attr.bold &&
+ format->attr.italic == format_prev->attr.italic &&
+ format->attr.underline == format_prev->attr.underline) {
continue;
}
@@ -690,21 +691,21 @@ swfdec_text_field_movie_html_text_append_paragraph (SwfdecTextFieldMovie *text,
for (iter_font = fonts; iter_font != NULL; iter_font = iter_font->next)
{
format_font = (SwfdecTextFormat *)iter_font->data;
- if (format->font == format_font->font &&
- format->size == format_font->size &&
- format->color == format_font->color &&
- (int)format->letter_spacing == (int)format_font->letter_spacing &&
- format->kerning == format_font->kerning) {
+ if (format->attr.font == format_font->attr.font &&
+ format->attr.size == format_font->attr.size &&
+ format->attr.color == format_font->attr.color &&
+ (int)format->attr.letter_spacing == (int)format_font->attr.letter_spacing &&
+ format->attr.kerning == format_font->attr.kerning) {
break;
}
}
- if (format_prev->underline)
+ if (format_prev->attr.underline)
string = g_string_append (string, "</U>");
- if (format_prev->italic)
+ if (format_prev->attr.italic)
string = g_string_append (string, "</I>");
- if (format_prev->bold)
+ if (format_prev->attr.bold)
string = g_string_append (string, "</B>");
- if (format_prev->url != SWFDEC_AS_STR_EMPTY)
+ if (format_prev->attr.url != SWFDEC_AS_STR_EMPTY)
string = g_string_append (string, "</A>");
if (iter_font != NULL) {
while (fonts != iter_font) {
@@ -715,41 +716,41 @@ swfdec_text_field_movie_html_text_append_paragraph (SwfdecTextFieldMovie *text,
// Open tags
format_font = (SwfdecTextFormat *)fonts->data;
- if (font && (format->font != format_font->font ||
- format->size != format_font->size ||
- format->color != format_font->color ||
- (int)format->letter_spacing != (int)format_font->letter_spacing ||
- format->kerning != format_font->kerning))
+ if (font && (format->attr.font != format_font->attr.font ||
+ format->attr.size != format_font->attr.size ||
+ format->attr.color != format_font->attr.color ||
+ (int)format->attr.letter_spacing != (int)format_font->attr.letter_spacing ||
+ format->attr.kerning != format_font->attr.kerning))
{
fonts = g_slist_prepend (fonts, format);
string = g_string_append (string, "<FONT");
- // note we don't escape format->font, even thought it can have evil chars
- if (format->font != format_font->font)
- g_string_append_printf (string, " FACE=\"%s\"", format->font);
- if (format->size != format_font->size)
- g_string_append_printf (string, " SIZE=\"%i\"", format->size);
- if (format->color != format_font->color)
- g_string_append_printf (string, " COLOR=\"#%06X\"", format->color);
- if ((int)format->letter_spacing != (int)format_font->letter_spacing) {
+ // note we don't escape format->attr.font, even thought it can have evil chars
+ if (format->attr.font != format_font->attr.font)
+ g_string_append_printf (string, " FACE=\"%s\"", format->attr.font);
+ if (format->attr.size != format_font->attr.size)
+ g_string_append_printf (string, " SIZE=\"%i\"", format->attr.size);
+ if (format->attr.color != format_font->attr.color)
+ g_string_append_printf (string, " COLOR=\"#%06X\"", format->attr.color);
+ if ((int)format->attr.letter_spacing != (int)format_font->attr.letter_spacing) {
g_string_append_printf (string, " LETTERSPACING=\"%i\"",
- (int)format->letter_spacing);
+ (int)format->attr.letter_spacing);
}
- if (format->kerning != format_font->kerning) {
+ if (format->attr.kerning != format_font->attr.kerning) {
g_string_append_printf (string, " KERNING=\"%i\"",
- (format->kerning ? 1 : 0));
+ (format->attr.kerning ? 1 : 0));
}
string = g_string_append (string, ">");
}
- if (format->url != SWFDEC_AS_STR_EMPTY) {
+ if (format->attr.url != SWFDEC_AS_STR_EMPTY) {
g_string_append_printf (string, "<A HREF=\"%s\" TARGET=\"%s\">",
- format->url, format->target);
+ format->attr.url, format->attr.target);
}
- if (format->bold)
+ if (format->attr.bold)
string = g_string_append (string, "<B>");
- if (format->italic)
+ if (format->attr.italic)
string = g_string_append (string, "<I>");
- if (format->underline)
+ if (format->attr.underline)
string = g_string_append (string, "<U>");
}
@@ -758,13 +759,13 @@ swfdec_text_field_movie_html_text_append_paragraph (SwfdecTextFieldMovie *text,
string = g_string_append (string, escaped);
g_free (escaped);
- if (format->underline)
+ if (format->attr.underline)
string = g_string_append (string, "</U>");
- if (format->italic)
+ if (format->attr.italic)
string = g_string_append (string, "</I>");
- if (format->bold)
+ if (format->attr.bold)
string = g_string_append (string, "</B>");
- if (format->url != SWFDEC_AS_STR_EMPTY)
+ if (format->attr.url != SWFDEC_AS_STR_EMPTY)
string = g_string_append (string, "</A>");
for (iter = fonts; iter != NULL; iter = iter->next)
string = g_string_append (string, "</FONT>");
diff --git a/swfdec/swfdec_text_format.c b/swfdec/swfdec_text_format.c
index e3e3d9b..f65b23e 100644
--- a/swfdec/swfdec_text_format.c
+++ b/swfdec/swfdec_text_format.c
@@ -1,5 +1,5 @@
/* Swfdec
- * Copyright (C) 2007 Benjamin Otte <otte at gnome.org>
+ * Copyright (C) 2007-2008 Benjamin Otte <otte at gnome.org>
* 2007 Pekka Lampila <pekka.lampila at iki.fi>
*
* This library is free software; you can redistribute it and/or
@@ -39,25 +39,25 @@
G_DEFINE_TYPE (SwfdecTextFormat, swfdec_text_format, SWFDEC_TYPE_AS_OBJECT)
static int property_offsets[] = {
- G_STRUCT_OFFSET (SwfdecTextFormat, align),
- G_STRUCT_OFFSET (SwfdecTextFormat, block_indent),
- G_STRUCT_OFFSET (SwfdecTextFormat, bold),
- G_STRUCT_OFFSET (SwfdecTextFormat, bullet),
- G_STRUCT_OFFSET (SwfdecTextFormat, color),
- G_STRUCT_OFFSET (SwfdecTextFormat, display),
- G_STRUCT_OFFSET (SwfdecTextFormat, font),
- G_STRUCT_OFFSET (SwfdecTextFormat, indent),
- G_STRUCT_OFFSET (SwfdecTextFormat, italic),
- G_STRUCT_OFFSET (SwfdecTextFormat, kerning),
- G_STRUCT_OFFSET (SwfdecTextFormat, leading),
- G_STRUCT_OFFSET (SwfdecTextFormat, left_margin),
- G_STRUCT_OFFSET (SwfdecTextFormat, letter_spacing),
- G_STRUCT_OFFSET (SwfdecTextFormat, right_margin),
- G_STRUCT_OFFSET (SwfdecTextFormat, size),
- G_STRUCT_OFFSET (SwfdecTextFormat, tab_stops),
- G_STRUCT_OFFSET (SwfdecTextFormat, target),
- G_STRUCT_OFFSET (SwfdecTextFormat, underline),
- G_STRUCT_OFFSET (SwfdecTextFormat, url)
+ G_STRUCT_OFFSET (SwfdecTextFormat, attr.align),
+ G_STRUCT_OFFSET (SwfdecTextFormat, attr.block_indent),
+ G_STRUCT_OFFSET (SwfdecTextFormat, attr.bold),
+ G_STRUCT_OFFSET (SwfdecTextFormat, attr.bullet),
+ G_STRUCT_OFFSET (SwfdecTextFormat, attr.color),
+ G_STRUCT_OFFSET (SwfdecTextFormat, attr.display),
+ G_STRUCT_OFFSET (SwfdecTextFormat, attr.font),
+ G_STRUCT_OFFSET (SwfdecTextFormat, attr.indent),
+ G_STRUCT_OFFSET (SwfdecTextFormat, attr.italic),
+ G_STRUCT_OFFSET (SwfdecTextFormat, attr.kerning),
+ G_STRUCT_OFFSET (SwfdecTextFormat, attr.leading),
+ G_STRUCT_OFFSET (SwfdecTextFormat, attr.left_margin),
+ G_STRUCT_OFFSET (SwfdecTextFormat, attr.letter_spacing),
+ G_STRUCT_OFFSET (SwfdecTextFormat, attr.right_margin),
+ G_STRUCT_OFFSET (SwfdecTextFormat, attr.size),
+ G_STRUCT_OFFSET (SwfdecTextFormat, attr.tab_stops),
+ G_STRUCT_OFFSET (SwfdecTextFormat, attr.target),
+ G_STRUCT_OFFSET (SwfdecTextFormat, attr.underline),
+ G_STRUCT_OFFSET (SwfdecTextFormat, attr.url)
};
static void
@@ -65,11 +65,7 @@ swfdec_text_format_do_mark (SwfdecAsObject *object)
{
SwfdecTextFormat *format = SWFDEC_TEXT_FORMAT (object);
- if (format->tab_stops != NULL)
- swfdec_as_object_mark (SWFDEC_AS_OBJECT (format->tab_stops));
- swfdec_as_string_mark (format->font);
- swfdec_as_string_mark (format->target);
- swfdec_as_string_mark (format->url);
+ swfdec_text_attributes_mark (&format->attr);
SWFDEC_AS_OBJECT_CLASS (swfdec_text_format_parent_class)->mark (object);
}
@@ -85,34 +81,12 @@ swfdec_text_format_class_init (SwfdecTextFormatClass *klass)
static void
swfdec_text_format_init (SwfdecTextFormat *format)
{
- format->font = SWFDEC_AS_STR_Times_New_Roman;
- format->target = SWFDEC_AS_STR_EMPTY;
- format->url = SWFDEC_AS_STR_EMPTY;
-}
-
-static gboolean
-swfdec_text_format_is_set (const SwfdecTextFormat *format, SwfdecTextFormatProperty property)
-{
- return (format->values_set & (1 << property));
-}
-
-static void
-swfdec_text_format_mark_set (SwfdecTextFormat *format,
- SwfdecTextFormatProperty property)
-{
- format->values_set |= (1 << property);
-}
-
-static void
-swfdec_text_format_mark_unset (SwfdecTextFormat *format,
- SwfdecTextFormatProperty property)
-{
- format->values_set &= ~(1 << property);
+ swfdec_text_attributes_reset (&format->attr);
}
static void
swfdec_text_format_get_string (SwfdecAsObject *object,
- SwfdecTextFormatProperty property, SwfdecAsValue *ret)
+ SwfdecTextAttribute property, SwfdecAsValue *ret)
{
SwfdecTextFormat *format;
@@ -120,7 +94,7 @@ swfdec_text_format_get_string (SwfdecAsObject *object,
return;
format = SWFDEC_TEXT_FORMAT (object);
- if (!swfdec_text_format_is_set (format, property)) {
+ if (!SWFDEC_TEXT_ATTRIBUTE_IS_SET (format->values_set, property)) {
SWFDEC_AS_VALUE_SET_NULL (ret);
return;
}
@@ -131,7 +105,7 @@ swfdec_text_format_get_string (SwfdecAsObject *object,
static void
swfdec_text_format_set_string (SwfdecAsObject *object,
- SwfdecTextFormatProperty property, guint argc, SwfdecAsValue *argv)
+ SwfdecTextAttribute property, guint argc, SwfdecAsValue *argv)
{
SwfdecTextFormat *format;
const char *s;
@@ -150,17 +124,17 @@ swfdec_text_format_set_string (SwfdecAsObject *object,
if (SWFDEC_AS_VALUE_IS_UNDEFINED (&argv[0]) ||
SWFDEC_AS_VALUE_IS_NULL (&argv[0])) {
/* FIXME: reset to defaults here? */
- swfdec_text_format_mark_unset (format, property);
+ SWFDEC_TEXT_ATTRIBUTE_UNSET (format->values_set, property);
} else {
G_STRUCT_MEMBER (const char *, format, property_offsets[property]) = s;
- swfdec_text_format_mark_set (format, property);
+ SWFDEC_TEXT_ATTRIBUTE_SET (format->values_set, property);
}
/* FIXME: figure out what to do here */
}
static void
swfdec_text_format_get_boolean (SwfdecAsObject *object,
- SwfdecTextFormatProperty property, SwfdecAsValue *ret)
+ SwfdecTextAttribute property, SwfdecAsValue *ret)
{
SwfdecTextFormat *format;
@@ -168,7 +142,7 @@ swfdec_text_format_get_boolean (SwfdecAsObject *object,
return;
format = SWFDEC_TEXT_FORMAT (object);
- if (!swfdec_text_format_is_set (format, property)) {
+ if (!SWFDEC_TEXT_ATTRIBUTE_IS_SET (format->values_set, property)) {
SWFDEC_AS_VALUE_SET_NULL (ret);
return;
}
@@ -182,7 +156,7 @@ swfdec_text_format_get_boolean (SwfdecAsObject *object,
static void
swfdec_text_format_set_boolean (SwfdecAsObject *object,
- SwfdecTextFormatProperty property, guint argc, SwfdecAsValue *argv)
+ SwfdecTextAttribute property, guint argc, SwfdecAsValue *argv)
{
SwfdecTextFormat *format;
@@ -199,17 +173,17 @@ swfdec_text_format_set_boolean (SwfdecAsObject *object,
if (SWFDEC_AS_VALUE_IS_UNDEFINED (&argv[0]) ||
SWFDEC_AS_VALUE_IS_NULL (&argv[0])) {
- swfdec_text_format_mark_unset (format, property);
+ SWFDEC_TEXT_ATTRIBUTE_UNSET (format->values_set, property);
} else {
G_STRUCT_MEMBER (gboolean, format, property_offsets[property]) =
swfdec_as_value_to_boolean (object->context, &argv[0]);
- swfdec_text_format_mark_set (format, property);
+ SWFDEC_TEXT_ATTRIBUTE_SET (format->values_set, property);
}
}
static void
swfdec_text_format_get_integer (SwfdecAsObject *object,
- SwfdecTextFormatProperty property, SwfdecAsValue *ret)
+ SwfdecTextAttribute property, SwfdecAsValue *ret)
{
SwfdecTextFormat *format;
@@ -217,7 +191,7 @@ swfdec_text_format_get_integer (SwfdecAsObject *object,
return;
format = SWFDEC_TEXT_FORMAT (object);
- if (!swfdec_text_format_is_set (format, property)) {
+ if (!SWFDEC_TEXT_ATTRIBUTE_IS_SET (format->values_set, property)) {
SWFDEC_AS_VALUE_SET_NULL (ret);
return;
}
@@ -268,7 +242,7 @@ swfdec_text_format_value_to_integer (SwfdecAsContext *cx, SwfdecAsValue *val,
static void
swfdec_text_format_set_integer (SwfdecAsObject *object,
- SwfdecTextFormatProperty property, guint argc, SwfdecAsValue *argv,
+ SwfdecTextAttribute property, guint argc, SwfdecAsValue *argv,
gboolean allow_negative)
{
SwfdecTextFormat *format;
@@ -282,12 +256,12 @@ swfdec_text_format_set_integer (SwfdecAsObject *object,
if (SWFDEC_AS_VALUE_IS_UNDEFINED (&argv[0]) ||
SWFDEC_AS_VALUE_IS_NULL (&argv[0])) {
- swfdec_text_format_mark_unset (format, property);
+ SWFDEC_TEXT_ATTRIBUTE_UNSET (format->values_set, property);
} else {
G_STRUCT_MEMBER (int, format, property_offsets[property]) =
swfdec_text_format_value_to_integer (object->context, &argv[0],
allow_negative);
- swfdec_text_format_mark_set (format, property);
+ SWFDEC_TEXT_ATTRIBUTE_SET (format->values_set, property);
}
}
@@ -301,12 +275,12 @@ swfdec_text_format_do_get_align (SwfdecAsContext *cx, SwfdecAsObject *object,
return;
format = SWFDEC_TEXT_FORMAT (object);
- if (!swfdec_text_format_is_set (format, SWFDEC_TEXT_FORMAT_ALIGN)) {
+ if (!SWFDEC_TEXT_ATTRIBUTE_IS_SET (format->values_set, SWFDEC_TEXT_ATTRIBUTE_ALIGN)) {
SWFDEC_AS_VALUE_SET_NULL (ret);
return;
}
- switch (format->align) {
+ switch (format->attr.align) {
case SWFDEC_TEXT_ALIGN_LEFT:
SWFDEC_AS_VALUE_SET_STRING (ret, SWFDEC_AS_STR_left);
break;
@@ -343,17 +317,17 @@ swfdec_text_format_do_set_align (SwfdecAsContext *cx, SwfdecAsObject *object,
s = swfdec_as_value_to_string (cx, &argv[0]);
if (!g_ascii_strcasecmp (s, "left")) {
- format->align = SWFDEC_TEXT_ALIGN_LEFT;
- swfdec_text_format_mark_set (format, SWFDEC_TEXT_FORMAT_ALIGN);
+ format->attr.align = SWFDEC_TEXT_ALIGN_LEFT;
+ SWFDEC_TEXT_ATTRIBUTE_SET (format->values_set, SWFDEC_TEXT_ATTRIBUTE_ALIGN);
} else if (!g_ascii_strcasecmp (s, "right")) {
- format->align = SWFDEC_TEXT_ALIGN_RIGHT;
- swfdec_text_format_mark_set (format, SWFDEC_TEXT_FORMAT_ALIGN);
+ format->attr.align = SWFDEC_TEXT_ALIGN_RIGHT;
+ SWFDEC_TEXT_ATTRIBUTE_SET (format->values_set, SWFDEC_TEXT_ATTRIBUTE_ALIGN);
} else if (!g_ascii_strcasecmp (s, "center")) {
- format->align = SWFDEC_TEXT_ALIGN_CENTER;
- swfdec_text_format_mark_set (format, SWFDEC_TEXT_FORMAT_ALIGN);
+ format->attr.align = SWFDEC_TEXT_ALIGN_CENTER;
+ SWFDEC_TEXT_ATTRIBUTE_SET (format->values_set, SWFDEC_TEXT_ATTRIBUTE_ALIGN);
} else if (!g_ascii_strcasecmp (s, "justify")) {
- format->align = SWFDEC_TEXT_ALIGN_JUSTIFY;
- swfdec_text_format_mark_set (format, SWFDEC_TEXT_FORMAT_ALIGN);
+ format->attr.align = SWFDEC_TEXT_ALIGN_JUSTIFY;
+ SWFDEC_TEXT_ATTRIBUTE_SET (format->values_set, SWFDEC_TEXT_ATTRIBUTE_ALIGN);
}
}
@@ -362,7 +336,7 @@ swfdec_text_format_do_get_block_indent (SwfdecAsContext *cx,
SwfdecAsObject *object, guint argc, SwfdecAsValue *argv,
SwfdecAsValue *ret)
{
- swfdec_text_format_get_integer (object, SWFDEC_TEXT_FORMAT_BLOCK_INDENT, ret);
+ swfdec_text_format_get_integer (object, SWFDEC_TEXT_ATTRIBUTE_BLOCK_INDENT, ret);
}
static void
@@ -370,7 +344,7 @@ swfdec_text_format_do_set_block_indent (SwfdecAsContext *cx,
SwfdecAsObject *object, guint argc, SwfdecAsValue *argv,
SwfdecAsValue *ret)
{
- swfdec_text_format_set_integer (object, SWFDEC_TEXT_FORMAT_BLOCK_INDENT, argc, argv,
+ swfdec_text_format_set_integer (object, SWFDEC_TEXT_ATTRIBUTE_BLOCK_INDENT, argc, argv,
cx->version >= 8);
}
@@ -378,28 +352,28 @@ static void
swfdec_text_format_do_get_bold (SwfdecAsContext *cx, SwfdecAsObject *object,
guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
{
- swfdec_text_format_get_boolean (object, SWFDEC_TEXT_FORMAT_BOLD, ret);
+ swfdec_text_format_get_boolean (object, SWFDEC_TEXT_ATTRIBUTE_BOLD, ret);
}
static void
swfdec_text_format_do_set_bold (SwfdecAsContext *cx, SwfdecAsObject *object,
guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
{
- swfdec_text_format_set_boolean (object, SWFDEC_TEXT_FORMAT_BOLD, argc, argv);
+ swfdec_text_format_set_boolean (object, SWFDEC_TEXT_ATTRIBUTE_BOLD, argc, argv);
}
static void
swfdec_text_format_do_get_bullet (SwfdecAsContext *cx, SwfdecAsObject *object,
guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
{
- swfdec_text_format_get_boolean (object, SWFDEC_TEXT_FORMAT_BULLET, ret);
+ swfdec_text_format_get_boolean (object, SWFDEC_TEXT_ATTRIBUTE_BULLET, ret);
}
static void
swfdec_text_format_do_set_bullet (SwfdecAsContext *cx, SwfdecAsObject *object,
guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
{
- swfdec_text_format_set_boolean (object, SWFDEC_TEXT_FORMAT_BULLET, argc, argv);
+ swfdec_text_format_set_boolean (object, SWFDEC_TEXT_ATTRIBUTE_BULLET, argc, argv);
}
static void
@@ -412,12 +386,12 @@ swfdec_text_format_do_get_color (SwfdecAsContext *cx, SwfdecAsObject *object,
return;
format = SWFDEC_TEXT_FORMAT (object);
- if (!swfdec_text_format_is_set (format, SWFDEC_TEXT_FORMAT_COLOR)) {
+ if (!SWFDEC_TEXT_ATTRIBUTE_IS_SET (format->values_set, SWFDEC_TEXT_ATTRIBUTE_COLOR)) {
SWFDEC_AS_VALUE_SET_NULL (ret);
return;
}
- SWFDEC_AS_VALUE_SET_NUMBER (ret, format->color);
+ SWFDEC_AS_VALUE_SET_NUMBER (ret, format->attr.color);
}
static void
@@ -435,13 +409,13 @@ swfdec_text_format_do_set_color (SwfdecAsContext *cx, SwfdecAsObject *object,
if (SWFDEC_AS_VALUE_IS_UNDEFINED (&argv[0]) ||
SWFDEC_AS_VALUE_IS_NULL (&argv[0])) {
- swfdec_text_format_mark_unset (format, SWFDEC_TEXT_FORMAT_COLOR);
+ SWFDEC_TEXT_ATTRIBUTE_UNSET (format->values_set, SWFDEC_TEXT_ATTRIBUTE_COLOR);
} else {
- format->color = (unsigned) swfdec_as_value_to_integer (cx, &argv[0]);
+ format->attr.color = (unsigned) swfdec_as_value_to_integer (cx, &argv[0]);
swfdec_as_value_to_integer (cx, &argv[0]);
swfdec_as_value_to_string (cx, &argv[0]);
- swfdec_text_format_mark_set (format, SWFDEC_TEXT_FORMAT_COLOR);
+ SWFDEC_TEXT_ATTRIBUTE_SET (format->values_set, SWFDEC_TEXT_ATTRIBUTE_COLOR);
}
}
@@ -455,13 +429,13 @@ swfdec_text_format_do_get_display (SwfdecAsContext *cx, SwfdecAsObject *object,
return;
format = SWFDEC_TEXT_FORMAT (object);
- if (!swfdec_text_format_is_set (format, SWFDEC_TEXT_FORMAT_DISPLAY))
+ if (!SWFDEC_TEXT_ATTRIBUTE_IS_SET (format->values_set, SWFDEC_TEXT_ATTRIBUTE_DISPLAY))
{
SWFDEC_AS_VALUE_SET_NULL (ret);
return;
}
- switch (format->display) {
+ switch (format->attr.display) {
case SWFDEC_TEXT_DISPLAY_NONE:
SWFDEC_AS_VALUE_SET_STRING (ret, SWFDEC_AS_STR_none);
break;
@@ -493,42 +467,42 @@ swfdec_text_format_do_set_display (SwfdecAsContext *cx, SwfdecAsObject *object,
s = swfdec_as_value_to_string (cx, &argv[0]); // oh yes, let's call it twice
if (!g_ascii_strcasecmp (s, "none")) {
- format->display = SWFDEC_TEXT_DISPLAY_NONE;
+ format->attr.display = SWFDEC_TEXT_DISPLAY_NONE;
} else if (!g_ascii_strcasecmp (s, "inline")) {
- format->display = SWFDEC_TEXT_DISPLAY_INLINE;
+ format->attr.display = SWFDEC_TEXT_DISPLAY_INLINE;
} else {
- format->display = SWFDEC_TEXT_DISPLAY_BLOCK;
+ format->attr.display = SWFDEC_TEXT_DISPLAY_BLOCK;
}
- swfdec_text_format_mark_set (format, SWFDEC_TEXT_FORMAT_DISPLAY);
+ SWFDEC_TEXT_ATTRIBUTE_SET (format->values_set, SWFDEC_TEXT_ATTRIBUTE_DISPLAY);
}
static void
swfdec_text_format_do_get_font (SwfdecAsContext *cx, SwfdecAsObject *object,
guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
{
- swfdec_text_format_get_string (object, SWFDEC_TEXT_FORMAT_FONT, ret);
+ swfdec_text_format_get_string (object, SWFDEC_TEXT_ATTRIBUTE_FONT, ret);
}
static void
swfdec_text_format_do_set_font (SwfdecAsContext *cx, SwfdecAsObject *object,
guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
{
- swfdec_text_format_set_string (object, SWFDEC_TEXT_FORMAT_FONT, argc, argv);
+ swfdec_text_format_set_string (object, SWFDEC_TEXT_ATTRIBUTE_FONT, argc, argv);
}
static void
swfdec_text_format_do_get_indent (SwfdecAsContext *cx, SwfdecAsObject *object,
guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
{
- swfdec_text_format_get_integer (object, SWFDEC_TEXT_FORMAT_INDENT, ret);
+ swfdec_text_format_get_integer (object, SWFDEC_TEXT_ATTRIBUTE_INDENT, ret);
}
static void
swfdec_text_format_do_set_indent (SwfdecAsContext *cx, SwfdecAsObject *object,
guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
{
- swfdec_text_format_set_integer (object, SWFDEC_TEXT_FORMAT_INDENT, argc, argv,
+ swfdec_text_format_set_integer (object, SWFDEC_TEXT_ATTRIBUTE_INDENT, argc, argv,
cx->version >= 8);
}
@@ -536,42 +510,42 @@ static void
swfdec_text_format_do_get_italic (SwfdecAsContext *cx, SwfdecAsObject *object,
guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
{
- swfdec_text_format_get_boolean (object, SWFDEC_TEXT_FORMAT_ITALIC, ret);
+ swfdec_text_format_get_boolean (object, SWFDEC_TEXT_ATTRIBUTE_ITALIC, ret);
}
static void
swfdec_text_format_do_set_italic (SwfdecAsContext *cx, SwfdecAsObject *object,
guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
{
- swfdec_text_format_set_boolean (object, SWFDEC_TEXT_FORMAT_ITALIC, argc, argv);
+ swfdec_text_format_set_boolean (object, SWFDEC_TEXT_ATTRIBUTE_ITALIC, argc, argv);
}
static void
swfdec_text_format_do_get_kerning (SwfdecAsContext *cx, SwfdecAsObject *object,
guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
{
- swfdec_text_format_get_boolean (object, SWFDEC_TEXT_FORMAT_KERNING, ret);
+ swfdec_text_format_get_boolean (object, SWFDEC_TEXT_ATTRIBUTE_KERNING, ret);
}
static void
swfdec_text_format_do_set_kerning (SwfdecAsContext *cx, SwfdecAsObject *object,
guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
{
- swfdec_text_format_set_boolean (object, SWFDEC_TEXT_FORMAT_KERNING, argc, argv);
+ swfdec_text_format_set_boolean (object, SWFDEC_TEXT_ATTRIBUTE_KERNING, argc, argv);
}
static void
swfdec_text_format_do_get_leading (SwfdecAsContext *cx, SwfdecAsObject *object,
guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
{
- swfdec_text_format_get_integer (object, SWFDEC_TEXT_FORMAT_LEADING, ret);
+ swfdec_text_format_get_integer (object, SWFDEC_TEXT_ATTRIBUTE_LEADING, ret);
}
static void
swfdec_text_format_do_set_leading (SwfdecAsContext *cx, SwfdecAsObject *object,
guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
{
- swfdec_text_format_set_integer (object, SWFDEC_TEXT_FORMAT_LEADING, argc, argv,
+ swfdec_text_format_set_integer (object, SWFDEC_TEXT_ATTRIBUTE_LEADING, argc, argv,
cx->version >= 8);
}
@@ -580,7 +554,7 @@ swfdec_text_format_do_get_left_margin (SwfdecAsContext *cx,
SwfdecAsObject *object, guint argc, SwfdecAsValue *argv,
SwfdecAsValue *ret)
{
- swfdec_text_format_get_integer (object, SWFDEC_TEXT_FORMAT_LEFT_MARGIN, ret);
+ swfdec_text_format_get_integer (object, SWFDEC_TEXT_ATTRIBUTE_LEFT_MARGIN, ret);
}
static void
@@ -588,7 +562,7 @@ swfdec_text_format_do_set_left_margin (SwfdecAsContext *cx,
SwfdecAsObject *object, guint argc, SwfdecAsValue *argv,
SwfdecAsValue *ret)
{
- swfdec_text_format_set_integer (object, SWFDEC_TEXT_FORMAT_LEFT_MARGIN, argc, argv, FALSE);
+ swfdec_text_format_set_integer (object, SWFDEC_TEXT_ATTRIBUTE_LEFT_MARGIN, argc, argv, FALSE);
}
static void
@@ -602,12 +576,12 @@ swfdec_text_format_do_get_letter_spacing (SwfdecAsContext *cx,
return;
format = SWFDEC_TEXT_FORMAT (object);
- if (!swfdec_text_format_is_set (format, SWFDEC_TEXT_FORMAT_LETTER_SPACING)) {
+ if (!SWFDEC_TEXT_ATTRIBUTE_IS_SET (format->values_set, SWFDEC_TEXT_ATTRIBUTE_LETTER_SPACING)) {
SWFDEC_AS_VALUE_SET_NULL (ret);
return;
}
- SWFDEC_AS_VALUE_SET_NUMBER (ret, format->letter_spacing);
+ SWFDEC_AS_VALUE_SET_NUMBER (ret, format->attr.letter_spacing);
}
static void
@@ -632,14 +606,14 @@ swfdec_text_format_do_set_letter_spacing (SwfdecAsContext *cx,
if (SWFDEC_AS_VALUE_IS_UNDEFINED (&argv[0]) ||
SWFDEC_AS_VALUE_IS_NULL (&argv[0]))
{
- swfdec_text_format_mark_unset (format,
- SWFDEC_TEXT_FORMAT_LETTER_SPACING);
+ SWFDEC_TEXT_ATTRIBUTE_UNSET (format->values_set,
+ SWFDEC_TEXT_ATTRIBUTE_LETTER_SPACING);
}
else
{
- format->letter_spacing = d;
- swfdec_text_format_mark_set (format,
- SWFDEC_TEXT_FORMAT_LETTER_SPACING);
+ format->attr.letter_spacing = d;
+ SWFDEC_TEXT_ATTRIBUTE_SET (format->values_set,
+ SWFDEC_TEXT_ATTRIBUTE_LETTER_SPACING);
}
}
@@ -648,7 +622,7 @@ swfdec_text_format_do_get_right_margin (SwfdecAsContext *cx,
SwfdecAsObject *object, guint argc, SwfdecAsValue *argv,
SwfdecAsValue *ret)
{
- swfdec_text_format_get_integer (object, SWFDEC_TEXT_FORMAT_RIGHT_MARGIN, ret);
+ swfdec_text_format_get_integer (object, SWFDEC_TEXT_ATTRIBUTE_RIGHT_MARGIN, ret);
}
static void
@@ -656,7 +630,7 @@ swfdec_text_format_do_set_right_margin (SwfdecAsContext *cx,
SwfdecAsObject *object, guint argc, SwfdecAsValue *argv,
SwfdecAsValue *ret)
{
- swfdec_text_format_set_integer (object, SWFDEC_TEXT_FORMAT_RIGHT_MARGIN, argc, argv,
+ swfdec_text_format_set_integer (object, SWFDEC_TEXT_ATTRIBUTE_RIGHT_MARGIN, argc, argv,
FALSE);
}
@@ -664,14 +638,14 @@ static void
swfdec_text_format_do_get_size (SwfdecAsContext *cx, SwfdecAsObject *object,
guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
{
- swfdec_text_format_get_integer (object, SWFDEC_TEXT_FORMAT_SIZE, ret);
+ swfdec_text_format_get_integer (object, SWFDEC_TEXT_ATTRIBUTE_SIZE, ret);
}
static void
swfdec_text_format_do_set_size (SwfdecAsContext *cx, SwfdecAsObject *object,
guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
{
- swfdec_text_format_set_integer (object, SWFDEC_TEXT_FORMAT_SIZE, argc, argv, TRUE);
+ swfdec_text_format_set_integer (object, SWFDEC_TEXT_ATTRIBUTE_SIZE, argc, argv, TRUE);
}
static void
@@ -680,18 +654,25 @@ swfdec_text_format_do_get_tab_stops (SwfdecAsContext *cx,
SwfdecAsValue *ret)
{
SwfdecTextFormat *format;
+ guint i;
+ SwfdecAsValue val;
+ SwfdecAsObject *array;
if (!SWFDEC_IS_TEXT_FORMAT (object))
return;
format = SWFDEC_TEXT_FORMAT (object);
- if (!swfdec_text_format_is_set (format, SWFDEC_TEXT_FORMAT_TAB_STOPS)) {
+ if (!SWFDEC_TEXT_ATTRIBUTE_IS_SET (format->values_set, SWFDEC_TEXT_ATTRIBUTE_TAB_STOPS)) {
SWFDEC_AS_VALUE_SET_NULL (ret);
return;
}
- g_return_if_fail (SWFDEC_IS_AS_OBJECT (format->tab_stops));
- SWFDEC_AS_VALUE_SET_OBJECT (ret, SWFDEC_AS_OBJECT (format->tab_stops));
+ array = swfdec_as_array_new (cx);
+ for (i = 0; i < format->attr.n_tab_stops; i++) {
+ SWFDEC_AS_VALUE_SET_INT (&val, format->attr.tab_stops[i]);
+ swfdec_as_array_push (SWFDEC_AS_ARRAY (array), &val);
+ }
+ SWFDEC_AS_VALUE_SET_OBJECT (ret, array);
}
static void
@@ -715,71 +696,62 @@ swfdec_text_format_do_set_tab_stops (SwfdecAsContext *cx,
if (SWFDEC_AS_VALUE_IS_UNDEFINED (&argv[0]) ||
SWFDEC_AS_VALUE_IS_NULL (&argv[0]))
{
- format->tab_stops = NULL;
- swfdec_text_format_mark_unset (format, SWFDEC_TEXT_FORMAT_TAB_STOPS);
+ g_free (format->attr.tab_stops);
+ format->attr.tab_stops = NULL;
+ format->attr.n_tab_stops = 0;
+ SWFDEC_TEXT_ATTRIBUTE_UNSET (format->values_set, SWFDEC_TEXT_ATTRIBUTE_TAB_STOPS);
}
else if (SWFDEC_AS_VALUE_IS_OBJECT (&argv[0]) &&
SWFDEC_IS_AS_ARRAY (SWFDEC_AS_VALUE_GET_OBJECT (&argv[0])))
{
SwfdecAsArray *array;
SwfdecAsValue val;
- gint32 len, i;
- int n;
+ guint i;
+ int len;
array = SWFDEC_AS_ARRAY (SWFDEC_AS_VALUE_GET_OBJECT (&argv[0]));
len = swfdec_as_array_get_length (array);
- if (!swfdec_text_format_is_set (format, SWFDEC_TEXT_FORMAT_TAB_STOPS)) {
+ if (!SWFDEC_TEXT_ATTRIBUTE_IS_SET (format->values_set, SWFDEC_TEXT_ATTRIBUTE_TAB_STOPS)) {
// special case, if we have null and array is empty, keep it at null
if (len == 0)
return;
- format->tab_stops = SWFDEC_AS_ARRAY (swfdec_as_array_new (cx));
- if (!format->tab_stops)
- return;
- swfdec_text_format_mark_set (format, SWFDEC_TEXT_FORMAT_TAB_STOPS);
+ SWFDEC_TEXT_ATTRIBUTE_SET (format->values_set, SWFDEC_TEXT_ATTRIBUTE_TAB_STOPS);
}
- swfdec_as_array_set_length (format->tab_stops, 0);
- for (i = 0; i < len; i++) {
+ g_free (format->attr.tab_stops);
+ format->attr.n_tab_stops = MAX (0, len);
+ format->attr.tab_stops = g_new (guint, format->attr.n_tab_stops);
+ for (i = 0; i < format->attr.n_tab_stops; i++) {
swfdec_as_array_get_value (array, i, &val);
- n = swfdec_text_format_value_to_integer (cx, &val, TRUE);
- SWFDEC_AS_VALUE_SET_INT (&val, n);
- swfdec_as_array_set_value (format->tab_stops, i, &val);
+ format->attr.tab_stops[i] = swfdec_text_format_value_to_integer (cx, &val, TRUE);
}
}
else if (SWFDEC_AS_VALUE_IS_STRING (&argv[0]))
{
- gsize i, len;
- SwfdecAsValue val;
-
- len = strlen (SWFDEC_AS_VALUE_GET_STRING (&argv[0]));
+ gsize i;
// special case: empty strings mean null
- if (len == 0) {
- format->tab_stops = NULL;
- swfdec_text_format_mark_unset (format,
- SWFDEC_TEXT_FORMAT_TAB_STOPS);
+ if (SWFDEC_AS_VALUE_GET_STRING (&argv[0]) == SWFDEC_AS_STR_EMPTY) {
+ g_free (format->attr.tab_stops);
+ format->attr.tab_stops = NULL;
+ format->attr.n_tab_stops = 0;
+ SWFDEC_TEXT_ATTRIBUTE_UNSET (format->values_set, SWFDEC_TEXT_ATTRIBUTE_TAB_STOPS);
} else {
- format->tab_stops = SWFDEC_AS_ARRAY (swfdec_as_array_new (cx));
- if (format->tab_stops != NULL) {
- swfdec_text_format_mark_set (format, SWFDEC_TEXT_FORMAT_TAB_STOPS);
- if (cx->version >= 8) {
- SWFDEC_AS_VALUE_SET_INT (&val, -2147483648);
- } else {
- SWFDEC_AS_VALUE_SET_INT (&val, 0);
- }
- for (i = 0; i < len; i++) {
- swfdec_as_array_push (format->tab_stops, &val);
- }
- } else {
- swfdec_text_format_mark_unset (format, SWFDEC_TEXT_FORMAT_TAB_STOPS);
+ int n = cx->version >= 8 ? G_MININT : 0;
+ SWFDEC_TEXT_ATTRIBUTE_SET (format->values_set, SWFDEC_TEXT_ATTRIBUTE_TAB_STOPS);
+ format->attr.n_tab_stops = strlen (SWFDEC_AS_VALUE_GET_STRING (&argv[0]));
+ format->attr.tab_stops = g_new (guint, format->attr.n_tab_stops);
+ for (i = 0; i < format->attr.n_tab_stops; i++) {
+ format->attr.tab_stops[i] = n;
}
}
}
- else if (swfdec_text_format_is_set (format, SWFDEC_TEXT_FORMAT_TAB_STOPS))
+ else if (SWFDEC_TEXT_ATTRIBUTE_IS_SET (format->values_set, SWFDEC_TEXT_ATTRIBUTE_TAB_STOPS))
{
- swfdec_as_array_set_length (format->tab_stops, 0);
- swfdec_text_format_mark_set (format, SWFDEC_TEXT_FORMAT_TAB_STOPS);
+ format->attr.n_tab_stops = 0;
+ g_free (format->attr.tab_stops);
+ format->attr.tab_stops = NULL;
}
}
@@ -787,14 +759,14 @@ static void
swfdec_text_format_do_get_target (SwfdecAsContext *cx, SwfdecAsObject *object,
guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
{
- swfdec_text_format_get_string (object, SWFDEC_TEXT_FORMAT_TARGET, ret);
+ swfdec_text_format_get_string (object, SWFDEC_TEXT_ATTRIBUTE_TARGET, ret);
}
static void
swfdec_text_format_do_set_target (SwfdecAsContext *cx, SwfdecAsObject *object,
guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
{
- swfdec_text_format_set_string (object, SWFDEC_TEXT_FORMAT_TARGET, argc, argv);
+ swfdec_text_format_set_string (object, SWFDEC_TEXT_ATTRIBUTE_TARGET, argc, argv);
}
static void
@@ -802,7 +774,7 @@ swfdec_text_format_do_get_underline (SwfdecAsContext *cx,
SwfdecAsObject *object, guint argc, SwfdecAsValue *argv,
SwfdecAsValue *ret)
{
- swfdec_text_format_get_boolean (object, SWFDEC_TEXT_FORMAT_UNDERLINE, ret);
+ swfdec_text_format_get_boolean (object, SWFDEC_TEXT_ATTRIBUTE_UNDERLINE, ret);
}
static void
@@ -810,21 +782,21 @@ swfdec_text_format_do_set_underline (SwfdecAsContext *cx,
SwfdecAsObject *object, guint argc, SwfdecAsValue *argv,
SwfdecAsValue *ret)
{
- swfdec_text_format_set_boolean (object, SWFDEC_TEXT_FORMAT_UNDERLINE, argc, argv);
+ swfdec_text_format_set_boolean (object, SWFDEC_TEXT_ATTRIBUTE_UNDERLINE, argc, argv);
}
static void
swfdec_text_format_do_get_url (SwfdecAsContext *cx, SwfdecAsObject *object,
guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
{
- swfdec_text_format_get_string (object, SWFDEC_TEXT_FORMAT_URL, ret);
+ swfdec_text_format_get_string (object, SWFDEC_TEXT_ATTRIBUTE_URL, ret);
}
static void
swfdec_text_format_do_set_url (SwfdecAsContext *cx, SwfdecAsObject *object,
guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
{
- swfdec_text_format_set_string (object, SWFDEC_TEXT_FORMAT_URL, argc, argv);
+ swfdec_text_format_set_string (object, SWFDEC_TEXT_ATTRIBUTE_URL, argc, argv);
}
static void
@@ -863,12 +835,12 @@ swfdec_text_format_getTextExtent (SwfdecAsContext *cx, SwfdecAsObject *object,
pango_shape (text, strlen (text), &analysis, glyph_string);
desc = pango_font_description_new ();
- pango_font_description_set_family_static (desc, format->font);
- pango_font_description_set_size (desc, format->size * PANGO_SCALE);
- if (format->bold){
+ pango_font_description_set_family_static (desc, format->attr.font);
+ pango_font_description_set_size (desc, format->attr.size * PANGO_SCALE);
+ if (format->attr.bold){
pango_font_description_set_weight (desc, PANGO_WEIGHT_BOLD);
}
- if (format->italic)
+ if (format->attr.italic)
pango_font_description_set_style (desc, PANGO_STYLE_ITALIC);
font = pango_font_map_load_font (fontmap, pcontext, desc);
@@ -881,14 +853,14 @@ swfdec_text_format_getTextExtent (SwfdecAsContext *cx, SwfdecAsObject *object,
g_object_unref (G_OBJECT (pcontext));
g_object_unref (G_OBJECT (font));
- width = ink_rect.width / PANGO_SCALE + format->left_margin
- + format->right_margin;
- height = ink_rect.height / PANGO_SCALE + format->leading;
+ width = ink_rect.width / PANGO_SCALE + format->attr.left_margin
+ + format->attr.right_margin;
+ height = ink_rect.height / PANGO_SCALE + format->attr.leading;
ascent = PANGO_ASCENT(ink_rect) / PANGO_SCALE;
descent = PANGO_DESCENT (ink_rect) / PANGO_SCALE;
- text_field_width = ink_rect.width / PANGO_SCALE + format->left_margin
- + format->right_margin + 4;
- text_field_height = ink_rect.height / PANGO_SCALE + 4 + format->leading;
+ text_field_width = ink_rect.width / PANGO_SCALE + format->attr.left_margin
+ + format->attr.right_margin + 4;
+ text_field_height = ink_rect.height / PANGO_SCALE + 4 + format->attr.leading;
}
SWFDEC_AS_VALUE_SET_INT (&val, width);
@@ -918,45 +890,7 @@ swfdec_text_format_add (SwfdecTextFormat *format, const SwfdecTextFormat *from)
g_return_if_fail (SWFDEC_IS_TEXT_FORMAT (format));
g_return_if_fail (SWFDEC_IS_TEXT_FORMAT (from));
- if (swfdec_text_format_is_set (from, SWFDEC_TEXT_FORMAT_ALIGN))
- format->align = from->align;
- if (swfdec_text_format_is_set (from, SWFDEC_TEXT_FORMAT_BLOCK_INDENT))
- format->block_indent = from->block_indent;
- if (swfdec_text_format_is_set (from, SWFDEC_TEXT_FORMAT_BOLD))
- format->bold = from->bold;
- if (swfdec_text_format_is_set (from, SWFDEC_TEXT_FORMAT_BULLET))
- format->bullet = from->bullet;
- if (swfdec_text_format_is_set (from, SWFDEC_TEXT_FORMAT_COLOR))
- format->color = from->color;
- if (swfdec_text_format_is_set (from, SWFDEC_TEXT_FORMAT_DISPLAY))
- format->display = from->display;
- if (swfdec_text_format_is_set (from, SWFDEC_TEXT_FORMAT_FONT))
- format->font = from->font;
- if (swfdec_text_format_is_set (from, SWFDEC_TEXT_FORMAT_INDENT))
- format->indent = from->indent;
- if (swfdec_text_format_is_set (from, SWFDEC_TEXT_FORMAT_ITALIC))
- format->italic = from->italic ;
- if (swfdec_text_format_is_set (from, SWFDEC_TEXT_FORMAT_KERNING))
- format->kerning = from->kerning;
- if (swfdec_text_format_is_set (from, SWFDEC_TEXT_FORMAT_LEADING))
- format->leading = from->leading;
- if (swfdec_text_format_is_set (from, SWFDEC_TEXT_FORMAT_LEFT_MARGIN))
- format->left_margin = from->left_margin;
- if (swfdec_text_format_is_set (from, SWFDEC_TEXT_FORMAT_LETTER_SPACING))
- format->letter_spacing = from->letter_spacing;
- if (swfdec_text_format_is_set (from, SWFDEC_TEXT_FORMAT_RIGHT_MARGIN))
- format->right_margin = from->right_margin;
- if (swfdec_text_format_is_set (from, SWFDEC_TEXT_FORMAT_SIZE))
- format->size = from->size;
- if (swfdec_text_format_is_set (from, SWFDEC_TEXT_FORMAT_TAB_STOPS))
- format->tab_stops = from->tab_stops;
- if (swfdec_text_format_is_set (from, SWFDEC_TEXT_FORMAT_TARGET))
- format->target = from->target;
- if (swfdec_text_format_is_set (from, SWFDEC_TEXT_FORMAT_UNDERLINE))
- format->underline = from->underline;
- if (swfdec_text_format_is_set (from, SWFDEC_TEXT_FORMAT_URL))
- format->url = from->url;
-
+ swfdec_text_attributes_copy (&format->attr, &from->attr, from->values_set);
format->values_set |= from->values_set;
}
@@ -964,116 +898,25 @@ void
swfdec_text_format_remove_different (SwfdecTextFormat *format,
const SwfdecTextFormat *from)
{
- int set;
-
g_return_if_fail (SWFDEC_IS_TEXT_FORMAT (format));
g_return_if_fail (SWFDEC_IS_TEXT_FORMAT (from));
- set = format->values_set & from->values_set;
-
- if (set & (1 << SWFDEC_TEXT_FORMAT_ALIGN) && format->align != from->align)
- set &= ~(1 << SWFDEC_TEXT_FORMAT_ALIGN);
- if (set & (1 << SWFDEC_TEXT_FORMAT_BLOCK_INDENT) &&
- format->block_indent != from->block_indent) {
- set &= ~(1 << SWFDEC_TEXT_FORMAT_BLOCK_INDENT);
- }
- if (set & (1 << SWFDEC_TEXT_FORMAT_BOLD) && format->bold != from->bold)
- set &= ~(1 << SWFDEC_TEXT_FORMAT_BOLD);
- if (set & (1 << SWFDEC_TEXT_FORMAT_BULLET) && format->bullet != from->bullet)
- set &= ~(1 << SWFDEC_TEXT_FORMAT_BULLET);
- if (set & (1 << SWFDEC_TEXT_FORMAT_COLOR) && format->color != from->color)
- set &= ~(1 << SWFDEC_TEXT_FORMAT_COLOR);
- if (set & (1 << SWFDEC_TEXT_FORMAT_DISPLAY) && format->display != from->display)
- set &= ~(1 << SWFDEC_TEXT_FORMAT_DISPLAY);
- if (set & (1 << SWFDEC_TEXT_FORMAT_FONT) && format->font != from->font)
- set &= ~(1 << SWFDEC_TEXT_FORMAT_FONT);
- if (set & (1 << SWFDEC_TEXT_FORMAT_INDENT) && format->indent != from->indent)
- set &= ~(1 << SWFDEC_TEXT_FORMAT_INDENT);
- if (set & (1 << SWFDEC_TEXT_FORMAT_ITALIC) && format->italic != from->italic)
- set &= ~(1 << SWFDEC_TEXT_FORMAT_ITALIC);
- if (set & (1 << SWFDEC_TEXT_FORMAT_KERNING) && format->kerning != from->kerning)
- set &= ~(1 << SWFDEC_TEXT_FORMAT_KERNING);
- if (set & (1 << SWFDEC_TEXT_FORMAT_LEADING) && format->leading != from->leading)
- set &= ~(1 << SWFDEC_TEXT_FORMAT_LEADING);
- if (set & (1 << SWFDEC_TEXT_FORMAT_LEFT_MARGIN) &&
- format->left_margin != from->left_margin) {
- set &= ~(1 << SWFDEC_TEXT_FORMAT_LEFT_MARGIN);
- }
- if (set & (1 << SWFDEC_TEXT_FORMAT_LETTER_SPACING) &&
- format->letter_spacing != from->letter_spacing) {
- set &= ~(1 << SWFDEC_TEXT_FORMAT_LETTER_SPACING);
- }
- if (set & (1 << SWFDEC_TEXT_FORMAT_RIGHT_MARGIN) &&
- format->right_margin != from->right_margin) {
- set &= ~(1 << SWFDEC_TEXT_FORMAT_RIGHT_MARGIN);
- }
- if (set & (1 << SWFDEC_TEXT_FORMAT_SIZE) && format->size != from->size)
- set &= ~(1 << SWFDEC_TEXT_FORMAT_SIZE);
- if (set & (1 << SWFDEC_TEXT_FORMAT_TAB_STOPS) && format->tab_stops != from->tab_stops)
- set &= ~(1 << SWFDEC_TEXT_FORMAT_TAB_STOPS);
- if (set & (1 << SWFDEC_TEXT_FORMAT_TARGET) && format->target != from->target)
- set &= ~(1 << SWFDEC_TEXT_FORMAT_TARGET);
- if (set & (1 << SWFDEC_TEXT_FORMAT_UNDERLINE) && format->underline != from->underline)
- set &= ~(1 << SWFDEC_TEXT_FORMAT_UNDERLINE);
- if (set & (1 << SWFDEC_TEXT_FORMAT_URL) && format->url != from->url)
- set &= ~(1 << SWFDEC_TEXT_FORMAT_URL);
-
- format->values_set = set;
+ format->values_set &= ~swfdec_text_attributes_diff (&format->attr, &from->attr);
}
gboolean
swfdec_text_format_equal_or_undefined (const SwfdecTextFormat *a,
const SwfdecTextFormat *b)
{
- int set;
-
- set = a->values_set & b->values_set;
+ int set, diff;
g_return_val_if_fail (SWFDEC_IS_TEXT_FORMAT (a), FALSE);
g_return_val_if_fail (SWFDEC_IS_TEXT_FORMAT (b), FALSE);
- if (set & (1 << SWFDEC_TEXT_FORMAT_ALIGN) && a->align != b->align)
- return FALSE;
- if (set & (1 << SWFDEC_TEXT_FORMAT_BLOCK_INDENT) && a->block_indent != b->block_indent)
- return FALSE;
- if (set & (1 << SWFDEC_TEXT_FORMAT_BOLD) && a->bold != b->bold)
- return FALSE;
- if (set & (1 << SWFDEC_TEXT_FORMAT_BULLET) && a->bullet != b->bullet)
- return FALSE;
- if (set & (1 << SWFDEC_TEXT_FORMAT_COLOR) && a->color != b->color)
- return FALSE;
- if (set & (1 << SWFDEC_TEXT_FORMAT_DISPLAY) && a->display != b->display)
- return FALSE;
- if (set & (1 << SWFDEC_TEXT_FORMAT_FONT) && a->font != b->font)
- return FALSE;
- if (set & (1 << SWFDEC_TEXT_FORMAT_INDENT) && a->indent != b->indent)
- return FALSE;
- if (set & (1 << SWFDEC_TEXT_FORMAT_ITALIC) && a->italic != b->italic)
- return FALSE;
- if (set & (1 << SWFDEC_TEXT_FORMAT_KERNING) && a->kerning != b->kerning)
- return FALSE;
- if (set & (1 << SWFDEC_TEXT_FORMAT_LEADING) && a->leading != b->leading)
- return FALSE;
- if (set & (1 << SWFDEC_TEXT_FORMAT_LEFT_MARGIN) && a->left_margin != b->left_margin)
- return FALSE;
- if (set & (1 << SWFDEC_TEXT_FORMAT_LETTER_SPACING) &&
- a->letter_spacing != b->letter_spacing) {
- return FALSE;
- }
- if (set & (1 << SWFDEC_TEXT_FORMAT_RIGHT_MARGIN) && a->right_margin != b->right_margin)
- return FALSE;
- if (set & (1 << SWFDEC_TEXT_FORMAT_SIZE) && a->size != b->size)
- return FALSE;
- if (set & (1 << SWFDEC_TEXT_FORMAT_TAB_STOPS) && a->tab_stops != b->tab_stops)
- return FALSE;
- if (set & (1 << SWFDEC_TEXT_FORMAT_TARGET) && a->target != b->target)
- return FALSE;
- if (set & (1 << SWFDEC_TEXT_FORMAT_UNDERLINE) && a->underline != b->underline)
- return FALSE;
- if (set & (1 << SWFDEC_TEXT_FORMAT_URL) && a->url != b->url)
- return FALSE;
+ set = a->values_set & b->values_set;
+ diff = swfdec_text_attributes_diff (&a->attr, &b->attr);
- return TRUE;
+ return (set & diff) == 0;
}
gboolean
@@ -1085,49 +928,28 @@ swfdec_text_format_equal (const SwfdecTextFormat *a, const SwfdecTextFormat *b)
if (a->values_set != b->values_set)
return FALSE;
- return swfdec_text_format_equal_or_undefined (a, b);
+ return (a->values_set & swfdec_text_attributes_diff (&a->attr, &b->attr)) == 0;
}
void
swfdec_text_format_set_defaults (SwfdecTextFormat *format)
{
- format->align = SWFDEC_TEXT_ALIGN_LEFT;
- format->block_indent = 0;
- format->bold = FALSE;
- format->bullet = FALSE;
- format->color = 0;
- format->display = SWFDEC_TEXT_DISPLAY_BLOCK;
- format->font = SWFDEC_AS_STR_Times_New_Roman;
- format->indent = 0;
- format->italic = FALSE;
- format->kerning = FALSE;
- format->leading = 0;
- format->left_margin = 0;
- format->letter_spacing = 0;
- format->right_margin = 0;
- format->size = 12;
- format->tab_stops =
- SWFDEC_AS_ARRAY (swfdec_as_array_new (SWFDEC_AS_OBJECT (format)->context));
- format->target = SWFDEC_AS_STR_EMPTY;
- format->url = SWFDEC_AS_STR_EMPTY;
- format->underline = FALSE;
-
- format->values_set = (1 << SWFDEC_TEXT_FORMAT_TOTAL) - 1;
+ swfdec_text_attributes_reset (&format->attr);
+ format->values_set = -1;
if (SWFDEC_AS_OBJECT (format)->context->version < 8) {
- swfdec_text_format_mark_unset (format, SWFDEC_TEXT_FORMAT_KERNING);
- swfdec_text_format_mark_unset (format, SWFDEC_TEXT_FORMAT_LETTER_SPACING);
+ SWFDEC_TEXT_ATTRIBUTE_UNSET (format->values_set, SWFDEC_TEXT_ATTRIBUTE_KERNING);
+ SWFDEC_TEXT_ATTRIBUTE_UNSET (format->values_set, SWFDEC_TEXT_ATTRIBUTE_LETTER_SPACING);
}
}
static void
swfdec_text_format_clear (SwfdecTextFormat *format)
{
- format->tab_stops = NULL;
format->values_set = 0;
- format->display = SWFDEC_TEXT_DISPLAY_BLOCK;
- swfdec_text_format_mark_set (format, SWFDEC_TEXT_FORMAT_DISPLAY);
+ format->attr.display = SWFDEC_TEXT_DISPLAY_BLOCK;
+ SWFDEC_TEXT_ATTRIBUTE_SET (format->values_set, SWFDEC_TEXT_ATTRIBUTE_DISPLAY);
}
void
@@ -1268,25 +1090,7 @@ swfdec_text_format_copy (const SwfdecTextFormat *copy_from)
return NULL;
copy_to = SWFDEC_TEXT_FORMAT (object_to);
- copy_to->align = copy_from->align;
- copy_to->block_indent = copy_from->block_indent;
- copy_to->bold = copy_from->bold;
- copy_to->bullet = copy_from->bullet;
- copy_to->color = copy_from->color;
- copy_to->display = copy_from->display;
- copy_to->font = copy_from->font;
- copy_to->indent = copy_from->indent;
- copy_to->italic = copy_from->italic ;
- copy_to->kerning = copy_from->kerning;
- copy_to->leading = copy_from->leading;
- copy_to->left_margin = copy_from->left_margin;
- copy_to->letter_spacing = copy_from->letter_spacing;
- copy_to->right_margin = copy_from->right_margin;
- copy_to->size = copy_from->size;
- copy_to->tab_stops = copy_from->tab_stops;
- copy_to->target = copy_from->target;
- copy_to->underline = copy_from->underline;
- copy_to->url = copy_from->url;
+ swfdec_text_attributes_copy (©_to->attr, ©_from->attr, -1);
copy_to->values_set = copy_from->values_set;
return copy_to;
diff --git a/swfdec/swfdec_text_format.h b/swfdec/swfdec_text_format.h
index 00a7d46..ed5ef75 100644
--- a/swfdec/swfdec_text_format.h
+++ b/swfdec/swfdec_text_format.h
@@ -1,5 +1,5 @@
/* Swfdec
- * Copyright (C) 2007 Benjamin Otte <otte at gnome.org>
+ * Copyright (C) 2007-2008 Benjamin Otte <otte at gnome.org>
* 2007 Pekka Lampila <pekka.lampila at iki.fi>
*
* This library is free software; you can redistribute it and/or
@@ -23,6 +23,7 @@
#include <swfdec/swfdec_as_object.h>
#include <swfdec/swfdec_as_array.h>
+#include <swfdec/swfdec_text_attributes.h>
#include <swfdec/swfdec_types.h>
#include <swfdec/swfdec_script.h>
@@ -38,66 +39,12 @@ typedef struct _SwfdecTextFormatClass SwfdecTextFormatClass;
#define SWFDEC_TEXT_FORMAT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SWFDEC_TYPE_TEXT_FORMAT, SwfdecTextFormatClass))
#define SWFDEC_TEXT_FORMAT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SWFDEC_TYPE_TEXT_FORMAT, SwfdecTextFormatClass))
-typedef enum {
- SWFDEC_TEXT_ALIGN_LEFT,
- SWFDEC_TEXT_ALIGN_RIGHT,
- SWFDEC_TEXT_ALIGN_CENTER,
- SWFDEC_TEXT_ALIGN_JUSTIFY
-} SwfdecTextAlign;
-
-typedef enum {
- SWFDEC_TEXT_DISPLAY_NONE,
- SWFDEC_TEXT_DISPLAY_INLINE,
- SWFDEC_TEXT_DISPLAY_BLOCK,
-} SwfdecTextDisplay;
-
-typedef enum {
- SWFDEC_TEXT_FORMAT_ALIGN = 0,
- SWFDEC_TEXT_FORMAT_BLOCK_INDENT,
- SWFDEC_TEXT_FORMAT_BOLD,
- SWFDEC_TEXT_FORMAT_BULLET,
- SWFDEC_TEXT_FORMAT_COLOR,
- SWFDEC_TEXT_FORMAT_DISPLAY,
- SWFDEC_TEXT_FORMAT_FONT,
- SWFDEC_TEXT_FORMAT_INDENT,
- SWFDEC_TEXT_FORMAT_ITALIC,
- SWFDEC_TEXT_FORMAT_KERNING,
- SWFDEC_TEXT_FORMAT_LEADING,
- SWFDEC_TEXT_FORMAT_LEFT_MARGIN,
- SWFDEC_TEXT_FORMAT_LETTER_SPACING,
- SWFDEC_TEXT_FORMAT_RIGHT_MARGIN,
- SWFDEC_TEXT_FORMAT_SIZE,
- SWFDEC_TEXT_FORMAT_TAB_STOPS,
- SWFDEC_TEXT_FORMAT_TARGET,
- SWFDEC_TEXT_FORMAT_UNDERLINE,
- SWFDEC_TEXT_FORMAT_URL,
- SWFDEC_TEXT_FORMAT_TOTAL
-} SwfdecTextFormatProperty;
-
struct _SwfdecTextFormat {
SwfdecAsObject object;
- SwfdecTextAlign align;
- int block_indent;
- gboolean bold;
- gboolean bullet;
- SwfdecColor color;
- SwfdecTextDisplay display;
- const char * font;
- int indent;
- gboolean italic;
- gboolean kerning;
- int leading;
- int left_margin;
- double letter_spacing; // number or null
- int right_margin;
- int size;
- SwfdecAsArray * tab_stops;
- const char * target;
- gboolean underline;
- const char * url;
+ SwfdecTextAttributes attr;
- int values_set;
+ guint values_set;
};
struct _SwfdecTextFormatClass {
commit 0e075e1dae2c8731f75daf744e384bb9f6146616
Author: Benjamin Otte <otte at gnome.org>
Date: Fri May 2 22:28:44 2008 +0200
add a new way to specify text attributes
diff --git a/swfdec/Makefile.am b/swfdec/Makefile.am
index bc94375..9b743a7 100644
--- a/swfdec/Makefile.am
+++ b/swfdec/Makefile.am
@@ -146,6 +146,7 @@ libswfdec_source_files = \
swfdec_system_security.c \
swfdec_tag.c \
swfdec_text.c \
+ swfdec_text_attributes.c \
swfdec_text_field.c \
swfdec_text_field_movie.c \
swfdec_text_field_movie_as.c \
@@ -293,6 +294,7 @@ noinst_HEADERS = \
swfdec_style_sheet.h \
swfdec_tag.h \
swfdec_text.h \
+ swfdec_text_attributes.h \
swfdec_text_format.h \
swfdec_types.h \
swfdec_utils.h \
diff --git a/swfdec/swfdec_text_attributes.c b/swfdec/swfdec_text_attributes.c
new file mode 100644
index 0000000..c4739a8
--- /dev/null
+++ b/swfdec/swfdec_text_attributes.c
@@ -0,0 +1,161 @@
+/* Swfdec
+ * Copyright (C) 2007-2008 Benjamin Otte <otte at gnome.org>
+ * 2007 Pekka Lampila <pekka.lampila at iki.fi>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+#include "swfdec_text_attributes.h"
+#include "swfdec_as_context.h"
+#include "swfdec_as_strings.h"
+#include "swfdec_debug.h"
+
+void
+swfdec_text_attributes_reset (SwfdecTextAttributes *attr)
+{
+ g_free (attr->tab_stops);
+
+ attr->align = SWFDEC_TEXT_ALIGN_LEFT;
+ attr->block_indent = 0;
+ attr->bold = FALSE;
+ attr->bullet = FALSE;
+ attr->color = 0;
+ attr->display = SWFDEC_TEXT_DISPLAY_BLOCK;
+ attr->font = SWFDEC_AS_STR_Times_New_Roman;
+ attr->indent = 0;
+ attr->italic = FALSE;
+ attr->kerning = FALSE;
+ attr->leading = 0;
+ attr->left_margin = 0;
+ attr->letter_spacing = 0;
+ attr->right_margin = 0;
+ attr->size = 12;
+ attr->tab_stops = NULL;
+ attr->n_tab_stops = 0;
+ attr->target = SWFDEC_AS_STR_EMPTY;
+ attr->url = SWFDEC_AS_STR_EMPTY;
+ attr->underline = FALSE;
+}
+
+void
+swfdec_text_attributes_copy (SwfdecTextAttributes *attr, const SwfdecTextAttributes *from,
+ guint flags)
+{
+ if (SWFDEC_TEXT_ATTRIBUTE_IS_SET (flags, SWFDEC_TEXT_ATTRIBUTE_ALIGN))
+ attr->align = from->align;
+ if (SWFDEC_TEXT_ATTRIBUTE_IS_SET (flags, SWFDEC_TEXT_ATTRIBUTE_BLOCK_INDENT))
+ attr->block_indent = from->block_indent;
+ if (SWFDEC_TEXT_ATTRIBUTE_IS_SET (flags, SWFDEC_TEXT_ATTRIBUTE_BOLD))
+ attr->bold = from->bold;
+ if (SWFDEC_TEXT_ATTRIBUTE_IS_SET (flags, SWFDEC_TEXT_ATTRIBUTE_BULLET))
+ attr->bullet = from->bullet;
+ if (SWFDEC_TEXT_ATTRIBUTE_IS_SET (flags, SWFDEC_TEXT_ATTRIBUTE_COLOR))
+ attr->color = from->color;
+ if (SWFDEC_TEXT_ATTRIBUTE_IS_SET (flags, SWFDEC_TEXT_ATTRIBUTE_DISPLAY))
+ attr->display = from->display;
+ if (SWFDEC_TEXT_ATTRIBUTE_IS_SET (flags, SWFDEC_TEXT_ATTRIBUTE_FONT))
+ attr->font = from->font;
+ if (SWFDEC_TEXT_ATTRIBUTE_IS_SET (flags, SWFDEC_TEXT_ATTRIBUTE_INDENT))
+ attr->indent = from->indent;
+ if (SWFDEC_TEXT_ATTRIBUTE_IS_SET (flags, SWFDEC_TEXT_ATTRIBUTE_ITALIC))
+ attr->italic = from->italic;
+ if (SWFDEC_TEXT_ATTRIBUTE_IS_SET (flags, SWFDEC_TEXT_ATTRIBUTE_KERNING))
+ attr->kerning = from->kerning;
+ if (SWFDEC_TEXT_ATTRIBUTE_IS_SET (flags, SWFDEC_TEXT_ATTRIBUTE_LEADING))
+ attr->leading = from->leading;
+ if (SWFDEC_TEXT_ATTRIBUTE_IS_SET (flags, SWFDEC_TEXT_ATTRIBUTE_LEFT_MARGIN))
+ attr->left_margin = from->left_margin;
+ if (SWFDEC_TEXT_ATTRIBUTE_IS_SET (flags, SWFDEC_TEXT_ATTRIBUTE_LETTER_SPACING))
+ attr->letter_spacing = from->letter_spacing;
+ if (SWFDEC_TEXT_ATTRIBUTE_IS_SET (flags, SWFDEC_TEXT_ATTRIBUTE_RIGHT_MARGIN))
+ attr->right_margin = from->right_margin;
+ if (SWFDEC_TEXT_ATTRIBUTE_IS_SET (flags, SWFDEC_TEXT_ATTRIBUTE_SIZE))
+ attr->size = from->size;
+ if (SWFDEC_TEXT_ATTRIBUTE_IS_SET (flags, SWFDEC_TEXT_ATTRIBUTE_TAB_STOPS)) {
+ g_free (attr->tab_stops);
+ attr->tab_stops = g_memdup (from->tab_stops, sizeof (guint) * from->n_tab_stops);
+ attr->n_tab_stops = from->n_tab_stops;
+ }
+ if (SWFDEC_TEXT_ATTRIBUTE_IS_SET (flags, SWFDEC_TEXT_ATTRIBUTE_TARGET))
+ attr->target = from->target;
+ if (SWFDEC_TEXT_ATTRIBUTE_IS_SET (flags, SWFDEC_TEXT_ATTRIBUTE_UNDERLINE))
+ attr->underline = from->underline;
+ if (SWFDEC_TEXT_ATTRIBUTE_IS_SET (flags, SWFDEC_TEXT_ATTRIBUTE_URL))
+ attr->url = from->url;
+}
+
+void
+swfdec_text_attributes_mark (SwfdecTextAttributes *attr)
+{
+ swfdec_as_string_mark (attr->font);
+ swfdec_as_string_mark (attr->target);
+ swfdec_as_string_mark (attr->url);
+}
+
+guint
+swfdec_text_attributes_diff (const SwfdecTextAttributes *a, const SwfdecTextAttributes *b)
+{
+ guint result = 0;
+
+ if (a->align != b->align)
+ SWFDEC_TEXT_ATTRIBUTE_SET (result, SWFDEC_TEXT_ATTRIBUTE_ALIGN);
+ if (a->block_indent != b->block_indent)
+ SWFDEC_TEXT_ATTRIBUTE_SET (result, SWFDEC_TEXT_ATTRIBUTE_BLOCK_INDENT);
+ if (a->bold != b->bold)
+ SWFDEC_TEXT_ATTRIBUTE_SET (result, SWFDEC_TEXT_ATTRIBUTE_BOLD);
+ if (a->bullet != b->bullet)
+ SWFDEC_TEXT_ATTRIBUTE_SET (result, SWFDEC_TEXT_ATTRIBUTE_BULLET);
+ if (a->color != b->color)
+ SWFDEC_TEXT_ATTRIBUTE_SET (result, SWFDEC_TEXT_ATTRIBUTE_COLOR);
+ if (a->display != b->display)
+ SWFDEC_TEXT_ATTRIBUTE_SET (result, SWFDEC_TEXT_ATTRIBUTE_DISPLAY);
+ if (a->font != b->font)
+ SWFDEC_TEXT_ATTRIBUTE_SET (result, SWFDEC_TEXT_ATTRIBUTE_FONT);
+ if (a->indent != b->indent)
+ SWFDEC_TEXT_ATTRIBUTE_SET (result, SWFDEC_TEXT_ATTRIBUTE_INDENT);
+ if (a->italic != b->italic)
+ SWFDEC_TEXT_ATTRIBUTE_SET (result, SWFDEC_TEXT_ATTRIBUTE_ITALIC);
+ if (a->kerning != b->kerning)
+ SWFDEC_TEXT_ATTRIBUTE_SET (result, SWFDEC_TEXT_ATTRIBUTE_KERNING);
+ if (a->leading != b->leading)
+ SWFDEC_TEXT_ATTRIBUTE_SET (result, SWFDEC_TEXT_ATTRIBUTE_LEADING);
+ if (a->left_margin != b->left_margin)
+ SWFDEC_TEXT_ATTRIBUTE_SET (result, SWFDEC_TEXT_ATTRIBUTE_LEFT_MARGIN);
+ if (a->letter_spacing != b->letter_spacing)
+ SWFDEC_TEXT_ATTRIBUTE_SET (result, SWFDEC_TEXT_ATTRIBUTE_LETTER_SPACING);
+ if (a->right_margin != b->right_margin)
+ SWFDEC_TEXT_ATTRIBUTE_SET (result, SWFDEC_TEXT_ATTRIBUTE_RIGHT_MARGIN);
+ if (a->size != b->size)
+ SWFDEC_TEXT_ATTRIBUTE_SET (result, SWFDEC_TEXT_ATTRIBUTE_SIZE);
+ if (a->n_tab_stops != b->n_tab_stops)
+ SWFDEC_TEXT_ATTRIBUTE_SET (result, SWFDEC_TEXT_ATTRIBUTE_TAB_STOPS);
+ else if (a->n_tab_stops != 0 &&
+ memcmp (a->tab_stops, b->tab_stops, sizeof (guint) & a->n_tab_stops) != 0)
+ SWFDEC_TEXT_ATTRIBUTE_SET (result, SWFDEC_TEXT_ATTRIBUTE_TAB_STOPS);
+ if (a->target != b->target)
+ SWFDEC_TEXT_ATTRIBUTE_SET (result, SWFDEC_TEXT_ATTRIBUTE_TARGET);
+ if (a->underline != b->underline)
+ SWFDEC_TEXT_ATTRIBUTE_SET (result, SWFDEC_TEXT_ATTRIBUTE_UNDERLINE);
+ if (a->url != b->url)
+ SWFDEC_TEXT_ATTRIBUTE_SET (result, SWFDEC_TEXT_ATTRIBUTE_URL);
+
+ return result;
+}
diff --git a/swfdec/swfdec_text_attributes.h b/swfdec/swfdec_text_attributes.h
new file mode 100644
index 0000000..267002d
--- /dev/null
+++ b/swfdec/swfdec_text_attributes.h
@@ -0,0 +1,115 @@
+/* Swfdec
+ * Copyright (C) 2007-2008 Benjamin Otte <otte at gnome.org>
+ * 2007 Pekka Lampila <pekka.lampila at iki.fi>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+
+#ifndef _SWFDEC_TEXT_ATTRIBUTES_H_
+#define _SWFDEC_TEXT_ATTRIBUTES_H_
+
+#include <swfdec/swfdec_as_object.h>
+#include <swfdec/swfdec_as_array.h>
+#include <swfdec/swfdec_types.h>
+#include <swfdec/swfdec_script.h>
+
+G_BEGIN_DECLS
+
+typedef struct _SwfdecTextAttributes SwfdecTextAttributes;
+typedef struct _SwfdecTextAttributesClass SwfdecTextAttributesClass;
+
+#define SWFDEC_TYPE_TEXT_ATTRIBUTES (swfdec_text_attributes_get_type())
+#define SWFDEC_IS_TEXT_ATTRIBUTES(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SWFDEC_TYPE_TEXT_ATTRIBUTES))
+#define SWFDEC_IS_TEXT_ATTRIBUTES_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SWFDEC_TYPE_TEXT_ATTRIBUTES))
+#define SWFDEC_TEXT_ATTRIBUTES(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SWFDEC_TYPE_TEXT_ATTRIBUTES, SwfdecTextAttributes))
+#define SWFDEC_TEXT_ATTRIBUTES_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SWFDEC_TYPE_TEXT_ATTRIBUTES, SwfdecTextAttributesClass))
+#define SWFDEC_TEXT_ATTRIBUTES_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SWFDEC_TYPE_TEXT_ATTRIBUTES, SwfdecTextAttributesClass))
+
+typedef enum {
+ SWFDEC_TEXT_ALIGN_LEFT,
+ SWFDEC_TEXT_ALIGN_RIGHT,
+ SWFDEC_TEXT_ALIGN_CENTER,
+ SWFDEC_TEXT_ALIGN_JUSTIFY
+} SwfdecTextAlign;
+
+typedef enum {
+ SWFDEC_TEXT_DISPLAY_NONE,
+ SWFDEC_TEXT_DISPLAY_INLINE,
+ SWFDEC_TEXT_DISPLAY_BLOCK,
+} SwfdecTextDisplay;
+
+typedef enum {
+ SWFDEC_TEXT_ATTRIBUTE_ALIGN = 0,
+ SWFDEC_TEXT_ATTRIBUTE_BLOCK_INDENT,
+ SWFDEC_TEXT_ATTRIBUTE_BOLD,
+ SWFDEC_TEXT_ATTRIBUTE_BULLET,
+ SWFDEC_TEXT_ATTRIBUTE_COLOR,
+ SWFDEC_TEXT_ATTRIBUTE_DISPLAY,
+ SWFDEC_TEXT_ATTRIBUTE_FONT,
+ SWFDEC_TEXT_ATTRIBUTE_INDENT,
+ SWFDEC_TEXT_ATTRIBUTE_ITALIC,
+ SWFDEC_TEXT_ATTRIBUTE_KERNING,
+ SWFDEC_TEXT_ATTRIBUTE_LEADING,
+ SWFDEC_TEXT_ATTRIBUTE_LEFT_MARGIN,
+ SWFDEC_TEXT_ATTRIBUTE_LETTER_SPACING,
+ SWFDEC_TEXT_ATTRIBUTE_RIGHT_MARGIN,
+ SWFDEC_TEXT_ATTRIBUTE_SIZE,
+ SWFDEC_TEXT_ATTRIBUTE_TAB_STOPS,
+ SWFDEC_TEXT_ATTRIBUTE_TARGET,
+ SWFDEC_TEXT_ATTRIBUTE_UNDERLINE,
+ SWFDEC_TEXT_ATTRIBUTE_URL,
+} SwfdecTextAttribute;
+
+#define SWFDEC_TEXT_ATTRIBUTE_SET(flags, attribute) ((flags) |= 1 << (attribute))
+#define SWFDEC_TEXT_ATTRIBUTE_UNSET(flags, attribute) ((flags) &= ~(1 << (attribute)))
+#define SWFDEC_TEXT_ATTRIBUTE_IS_SET(flags, attribute) ((flags) & (1 << (attribute)) ? TRUE : FALSE)
+
+struct _SwfdecTextAttributes {
+ SwfdecTextAlign align;
+ int block_indent;
+ gboolean bold;
+ gboolean bullet;
+ SwfdecColor color;
+ SwfdecTextDisplay display;
+ const char * font;
+ int indent;
+ gboolean italic;
+ gboolean kerning;
+ int leading;
+ int left_margin;
+ double letter_spacing; // number or null
+ int right_margin;
+ int size;
+ guint * tab_stops;
+ gsize n_tab_stops;
+ const char * target;
+ gboolean underline;
+ const char * url;
+};
+
+
+void swfdec_text_attributes_reset (SwfdecTextAttributes * attr);
+void swfdec_text_attributes_copy (SwfdecTextAttributes * attr,
+ const SwfdecTextAttributes * from,
+ guint flags);
+void swfdec_text_attributes_mark (SwfdecTextAttributes * attr);
+
+guint swfdec_text_attributes_diff (const SwfdecTextAttributes * a,
+ const SwfdecTextAttributes * b);
+
+
+G_END_DECLS
+#endif
More information about the Swfdec-commits
mailing list