]> granicus.if.org Git - libass/blob - libass/ass_shaper.c
shaper: print version info string
[libass] / libass / ass_shaper.c
1 /*
2  * Copyright (C) 2011 Grigori Goronzy <greg@chown.ath.cx>
3  *
4  * This file is part of libass.
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18
19 #include <fribidi/fribidi.h>
20
21 #include "ass_render.h"
22 #include "ass_shaper.h"
23
24 /**
25  * \brief Print version information
26  */
27 void ass_shaper_info(ASS_Library *lib)
28 {
29     ass_msg(lib, MSGL_V, "Complex text layout enabled, using FriBidi "
30             FRIBIDI_VERSION);
31 }
32
33 /**
34  * \brief Shape an event's text. Calculates directional runs and shapes them.
35  * \param text_info event's text
36  * \param ctypes returns character types
37  * \param emblevels returns embedding levels (directional runs)
38  */
39 void ass_shaper_shape(TextInfo *text_info, FriBidiCharType *ctypes,
40                       FriBidiLevel *emblevels)
41 {
42     int i, last_break;
43     FriBidiParType dir;
44     FriBidiChar *event_text = calloc(sizeof(*event_text), text_info->length);
45     GlyphInfo *glyphs = text_info->glyphs;
46
47     // Get bidi character types and embedding levels
48     last_break = 0;
49     for (i = 0; i < text_info->length; i++) {
50         event_text[i] = glyphs[i].symbol;
51         // embedding levels should be calculated paragraph by paragraph
52         if (glyphs[i].symbol == '\n' || i == text_info->length - 1) {
53             //printf("paragraph from %d to %d\n", last_break, i);
54             dir = FRIBIDI_PAR_ON;
55             fribidi_get_bidi_types(event_text + last_break, i - last_break + 1,
56                     ctypes + last_break);
57             fribidi_get_par_embedding_levels(ctypes + last_break,
58                     i - last_break + 1, &dir, emblevels + last_break);
59             last_break = i + 1;
60         }
61     }
62
63 #if 0
64     printf("levels ");
65     for (i = 0; i < text_info->length; i++) {
66         printf("%d:%d ", ctypes[i], emblevels[i]);
67     }
68     printf("\n");
69 #endif
70
71     // Call FriBidi's glyph mirroring shaper.
72     // This shaper implements rule L4 of the bidi algorithm
73     fribidi_shape_mirroring(emblevels, text_info->length, event_text);
74     for (i = 0; i < text_info->length; i++) {
75         glyphs[i].symbol = event_text[i];
76     }
77
78     // XXX: insert HarfBuzz shaper here
79
80     // Skip direction override characters
81     // NOTE: Behdad said HarfBuzz is supposed to remove these, but this hasn't
82     // been implemented yet
83     for (i = 0; i < text_info->length; i++) {
84         if (glyphs[i].symbol <= 0x202F && glyphs[i].symbol >= 0x202a) {
85             glyphs[i].symbol = 0;
86             glyphs[i].skip++;
87         }
88     }
89
90     free(event_text);
91 }
92
93 void ass_shaper_reorder(TextInfo *text_info, FriBidiCharType *ctypes,
94                         FriBidiLevel *emblevels, FriBidiStrIndex *cmap)
95 {
96     int i;
97     FriBidiParType dir = FRIBIDI_PAR_LTR;
98
99     // Initialize reorder map
100     for (i = 0; i < text_info->length; i++)
101         cmap[i] = i;
102
103     // Create reorder map line-by-line
104     for (i = 0; i < text_info->n_lines; i++) {
105         LineInfo *line = text_info->lines + i;
106         int level;
107
108         // FIXME: we should actually specify
109         // the correct paragraph base direction
110         level = fribidi_reorder_line(FRIBIDI_FLAGS_DEFAULT,
111                 ctypes + line->offset, line->len, 0, dir,
112                 emblevels + line->offset, NULL, cmap + line->offset);
113         //printf("reorder line %d to level %d\n", i, level);
114     }
115
116 #if 0
117     printf("map ");
118     for (i = 0; i < text_info->length; i++) {
119         printf("%d ", cmap[i]);
120     }
121     printf("\n");
122 #endif
123
124 }