summaryrefslogtreecommitdiffstats
path: root/libass/ass_shaper.c
diff options
context:
space:
mode:
Diffstat (limited to 'libass/ass_shaper.c')
-rw-r--r--libass/ass_shaper.c115
1 files changed, 115 insertions, 0 deletions
diff --git a/libass/ass_shaper.c b/libass/ass_shaper.c
new file mode 100644
index 0000000..86814be
--- /dev/null
+++ b/libass/ass_shaper.c
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2011 Grigori Goronzy <greg@chown.ath.cx>
+ *
+ * This file is part of libass.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <fribidi/fribidi.h>
+
+#include "ass_render.h"
+#include "ass_shaper.h"
+
+/**
+ * \brief Shape an event's text. Calculates directional runs and shapes them.
+ * \param text_info event's text
+ * \param ctypes returns character types
+ * \param emblevels returns embedding levels (directional runs)
+ */
+void ass_shaper_shape(TextInfo *text_info, FriBidiCharType *ctypes,
+ FriBidiLevel *emblevels)
+{
+ int i, last_break;
+ FriBidiParType dir;
+ FriBidiChar *event_text = calloc(sizeof(*event_text), text_info->length);
+ GlyphInfo *glyphs = text_info->glyphs;
+
+ // Get bidi character types and embedding levels
+ last_break = 0;
+ for (i = 0; i < text_info->length; i++) {
+ event_text[i] = glyphs[i].symbol;
+ // embedding levels should be calculated paragraph by paragraph
+ if (glyphs[i].symbol == '\n' || i == text_info->length - 1) {
+ //printf("paragraph from %d to %d\n", last_break, i);
+ dir = FRIBIDI_PAR_ON;
+ fribidi_get_bidi_types(event_text + last_break, i - last_break + 1,
+ ctypes + last_break);
+ fribidi_get_par_embedding_levels(ctypes + last_break,
+ i - last_break + 1, &dir, emblevels + last_break);
+ last_break = i + 1;
+ }
+ }
+
+#if 0
+ printf("levels ");
+ for (i = 0; i < text_info->length; i++) {
+ printf("%d:%d ", ctypes[i], emblevels[i]);
+ }
+ printf("\n");
+#endif
+
+ // Call FriBidi's glyph mirroring shaper.
+ // This shaper implements rule L4 of the bidi algorithm
+ fribidi_shape_mirroring(emblevels, text_info->length, event_text);
+ for (i = 0; i < text_info->length; i++) {
+ glyphs[i].symbol = event_text[i];
+ }
+
+ // XXX: insert HarfBuzz shaper here
+
+ // Skip direction override characters
+ // NOTE: Behdad said HarfBuzz is supposed to remove these, but this hasn't
+ // been implemented yet
+ for (i = 0; i < text_info->length; i++) {
+ if (glyphs[i].symbol <= 0x202F && glyphs[i].symbol >= 0x202a) {
+ glyphs[i].symbol = 0;
+ glyphs[i].skip++;
+ }
+ }
+
+ free(event_text);
+}
+
+void ass_shaper_reorder(TextInfo *text_info, FriBidiCharType *ctypes,
+ FriBidiLevel *emblevels, FriBidiStrIndex *cmap)
+{
+ int i;
+ FriBidiParType dir = FRIBIDI_PAR_LTR;
+
+ // Initialize reorder map
+ for (i = 0; i < text_info->length; i++)
+ cmap[i] = i;
+
+ // Create reorder map line-by-line
+ for (i = 0; i < text_info->n_lines; i++) {
+ LineInfo *line = text_info->lines + i;
+ int level;
+
+ // FIXME: we should actually specify
+ // the correct paragraph base direction
+ level = fribidi_reorder_line(FRIBIDI_FLAGS_DEFAULT,
+ ctypes + line->offset, line->len, 0, dir,
+ emblevels + line->offset, NULL, cmap + line->offset);
+ //printf("reorder line %d to level %d\n", i, level);
+ }
+
+#if 0
+ printf("map ");
+ for (i = 0; i < text_info->length; i++) {
+ printf("%d ", cmap[i]);
+ }
+ printf("\n");
+#endif
+
+}