annotate libass/ass_shaper.c @ 36363:c3aaaf17c721

Update libass to latest git version.
author reimar
date Tue, 24 Sep 2013 20:50:02 +0000
parents 4f4a90b80a9a
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
34300
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
1 /*
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
2 * Copyright (C) 2011 Grigori Goronzy <greg@chown.ath.cx>
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
3 *
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
4 * This file is part of libass.
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
5 *
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
6 * Permission to use, copy, modify, and distribute this software for any
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
7 * purpose with or without fee is hereby granted, provided that the above
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
8 * copyright notice and this permission notice appear in all copies.
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
9 *
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
17 */
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
18
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
19 #include "config.h"
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
20
34342
575ad51cc996 Allow compiling libass without fribidi again.
reimar
parents: 34300
diff changeset
21 #ifdef CONFIG_FRIBIDI
34300
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
22 #include <fribidi/fribidi.h>
34342
575ad51cc996 Allow compiling libass without fribidi again.
reimar
parents: 34300
diff changeset
23 #endif
34300
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
24
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
25 #include "ass_shaper.h"
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
26 #include "ass_render.h"
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
27 #include "ass_font.h"
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
28 #include "ass_parse.h"
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
29 #include "ass_cache.h"
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
30
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
31 #define MAX_RUNS 50
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
32
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
33 #ifdef CONFIG_HARFBUZZ
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
34 #include <hb-ft.h>
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
35 enum {
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
36 VERT = 0,
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
37 VKNA,
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
38 KERN
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
39 };
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
40 #define NUM_FEATURES 3
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
41 #endif
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
42
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
43 struct ass_shaper {
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
44 ASS_ShapingLevel shaping_level;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
45
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
46 // FriBidi log2vis
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
47 int n_glyphs;
34342
575ad51cc996 Allow compiling libass without fribidi again.
reimar
parents: 34300
diff changeset
48 #ifdef CONFIG_FRIBIDI
34300
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
49 FriBidiChar *event_text;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
50 FriBidiCharType *ctypes;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
51 FriBidiLevel *emblevels;
34342
575ad51cc996 Allow compiling libass without fribidi again.
reimar
parents: 34300
diff changeset
52 #endif
34300
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
53 FriBidiStrIndex *cmap;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
54 FriBidiParType base_direction;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
55
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
56 #ifdef CONFIG_HARFBUZZ
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
57 // OpenType features
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
58 int n_features;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
59 hb_feature_t *features;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
60 hb_language_t language;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
61
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
62 // Glyph metrics cache, to speed up shaping
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
63 Cache *metrics_cache;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
64 #endif
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
65 };
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
66
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
67 #ifdef CONFIG_HARFBUZZ
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
68 struct ass_shaper_metrics_data {
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
69 Cache *metrics_cache;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
70 GlyphMetricsHashKey hash_key;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
71 int vertical;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
72 };
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
73
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
74 struct ass_shaper_font_data {
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
75 hb_font_t *fonts[ASS_FONT_MAX_FACES];
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
76 hb_font_funcs_t *font_funcs[ASS_FONT_MAX_FACES];
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
77 struct ass_shaper_metrics_data *metrics_data[ASS_FONT_MAX_FACES];
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
78 };
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
79 #endif
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
80
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
81 /**
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
82 * \brief Print version information
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
83 */
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
84 void ass_shaper_info(ASS_Library *lib)
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
85 {
34342
575ad51cc996 Allow compiling libass without fribidi again.
reimar
parents: 34300
diff changeset
86 ass_msg(lib, MSGL_V, "Shaper:"
575ad51cc996 Allow compiling libass without fribidi again.
reimar
parents: 34300
diff changeset
87 #ifdef CONFIG_FRIBIDI
575ad51cc996 Allow compiling libass without fribidi again.
reimar
parents: 34300
diff changeset
88 " FriBidi " FRIBIDI_VERSION " (SIMPLE)"
575ad51cc996 Allow compiling libass without fribidi again.
reimar
parents: 34300
diff changeset
89 #endif
34300
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
90 #ifdef CONFIG_HARFBUZZ
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
91 " HarfBuzz-ng %s (COMPLEX)", hb_version_string()
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
92 #endif
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
93 );
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
94 }
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
95
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
96 /**
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
97 * \brief grow arrays, if needed
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
98 * \param new_size requested size
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
99 */
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
100 static void check_allocations(ASS_Shaper *shaper, size_t new_size)
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
101 {
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
102 if (new_size > shaper->n_glyphs) {
34342
575ad51cc996 Allow compiling libass without fribidi again.
reimar
parents: 34300
diff changeset
103 #ifdef CONFIG_FRIBIDI
34300
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
104 shaper->event_text = realloc(shaper->event_text, sizeof(FriBidiChar) * new_size);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
105 shaper->ctypes = realloc(shaper->ctypes, sizeof(FriBidiCharType) * new_size);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
106 shaper->emblevels = realloc(shaper->emblevels, sizeof(FriBidiLevel) * new_size);
34342
575ad51cc996 Allow compiling libass without fribidi again.
reimar
parents: 34300
diff changeset
107 #endif
34300
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
108 shaper->cmap = realloc(shaper->cmap, sizeof(FriBidiStrIndex) * new_size);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
109 }
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
110 }
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
111
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
112 /**
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
113 * \brief Free shaper and related data
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
114 */
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
115 void ass_shaper_free(ASS_Shaper *shaper)
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
116 {
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
117 #ifdef CONFIG_HARFBUZZ
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
118 ass_cache_done(shaper->metrics_cache);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
119 free(shaper->features);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
120 #endif
34342
575ad51cc996 Allow compiling libass without fribidi again.
reimar
parents: 34300
diff changeset
121 #ifdef CONFIG_FRIBIDI
34300
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
122 free(shaper->event_text);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
123 free(shaper->ctypes);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
124 free(shaper->emblevels);
34342
575ad51cc996 Allow compiling libass without fribidi again.
reimar
parents: 34300
diff changeset
125 #endif
34300
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
126 free(shaper->cmap);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
127 free(shaper);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
128 }
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
129
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
130 void ass_shaper_font_data_free(ASS_ShaperFontData *priv)
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
131 {
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
132 #ifdef CONFIG_HARFBUZZ
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
133 int i;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
134 for (i = 0; i < ASS_FONT_MAX_FACES; i++)
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
135 if (priv->fonts[i]) {
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
136 free(priv->metrics_data[i]);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
137 hb_font_destroy(priv->fonts[i]);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
138 hb_font_funcs_destroy(priv->font_funcs[i]);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
139 }
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
140 free(priv);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
141 #endif
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
142 }
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
143
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
144 #ifdef CONFIG_HARFBUZZ
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
145 /**
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
146 * \brief set up the HarfBuzz OpenType feature list with some
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
147 * standard features.
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
148 */
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
149 static void init_features(ASS_Shaper *shaper)
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
150 {
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
151 shaper->features = calloc(sizeof(hb_feature_t), NUM_FEATURES);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
152
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
153 shaper->n_features = NUM_FEATURES;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
154 shaper->features[VERT].tag = HB_TAG('v', 'e', 'r', 't');
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
155 shaper->features[VERT].end = INT_MAX;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
156 shaper->features[VKNA].tag = HB_TAG('v', 'k', 'n', 'a');
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
157 shaper->features[VKNA].end = INT_MAX;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
158 shaper->features[KERN].tag = HB_TAG('k', 'e', 'r', 'n');
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
159 shaper->features[KERN].end = INT_MAX;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
160 }
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
161
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
162 /**
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
163 * \brief Set features depending on properties of the run
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
164 */
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
165 static void set_run_features(ASS_Shaper *shaper, GlyphInfo *info)
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
166 {
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
167 // enable vertical substitutions for @font runs
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
168 if (info->font->desc.vertical)
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
169 shaper->features[VERT].value = shaper->features[VKNA].value = 1;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
170 else
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
171 shaper->features[VERT].value = shaper->features[VKNA].value = 0;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
172 }
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
173
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
174 /**
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
175 * \brief Update HarfBuzz's idea of font metrics
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
176 * \param hb_font HarfBuzz font
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
177 * \param face associated FreeType font face
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
178 */
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
179 static void update_hb_size(hb_font_t *hb_font, FT_Face face)
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
180 {
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
181 hb_font_set_scale (hb_font,
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
182 ((uint64_t) face->size->metrics.x_scale * (uint64_t) face->units_per_EM) >> 16,
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
183 ((uint64_t) face->size->metrics.y_scale * (uint64_t) face->units_per_EM) >> 16);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
184 hb_font_set_ppem (hb_font, face->size->metrics.x_ppem,
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
185 face->size->metrics.y_ppem);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
186 }
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
187
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
188
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
189 /*
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
190 * Cached glyph metrics getters follow
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
191 *
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
192 * These functions replace HarfBuzz' standard FreeType font functions
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
193 * and provide cached access to essential glyph metrics. This usually
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
194 * speeds up shaping a lot. It also allows us to use custom load flags.
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
195 *
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
196 */
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
197
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
198 GlyphMetricsHashValue *
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
199 get_cached_metrics(struct ass_shaper_metrics_data *metrics, FT_Face face,
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
200 hb_codepoint_t glyph)
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
201 {
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
202 GlyphMetricsHashValue *val;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
203
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
204 metrics->hash_key.glyph_index = glyph;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
205 val = ass_cache_get(metrics->metrics_cache, &metrics->hash_key);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
206
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
207 if (!val) {
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
208 int load_flags = FT_LOAD_DEFAULT | FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
209 | FT_LOAD_IGNORE_TRANSFORM;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
210 GlyphMetricsHashValue new_val;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
211
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
212 if (FT_Load_Glyph(face, glyph, load_flags))
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
213 return NULL;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
214
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
215 memcpy(&new_val.metrics, &face->glyph->metrics, sizeof(FT_Glyph_Metrics));
36363
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
216
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
217 // if @font rendering is enabled and the glyph should be rotated,
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
218 // make cached_h_advance pick up the right advance later
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
219 if (metrics->vertical && glyph >= VERTICAL_LOWER_BOUND)
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
220 new_val.metrics.horiAdvance = new_val.metrics.vertAdvance;
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
221
34300
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
222 val = ass_cache_put(metrics->metrics_cache, &metrics->hash_key, &new_val);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
223 }
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
224
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
225 return val;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
226 }
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
227
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
228 static hb_bool_t
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
229 get_glyph(hb_font_t *font, void *font_data, hb_codepoint_t unicode,
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
230 hb_codepoint_t variation, hb_codepoint_t *glyph, void *user_data)
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
231 {
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
232 FT_Face face = font_data;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
233
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
234 if (variation)
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
235 *glyph = FT_Face_GetCharVariantIndex(face, unicode, variation);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
236 else
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
237 *glyph = FT_Get_Char_Index(face, unicode);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
238
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
239 return *glyph != 0;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
240 }
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
241
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
242 static hb_position_t
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
243 cached_h_advance(hb_font_t *font, void *font_data, hb_codepoint_t glyph,
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
244 void *user_data)
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
245 {
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
246 FT_Face face = font_data;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
247 struct ass_shaper_metrics_data *metrics_priv = user_data;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
248 GlyphMetricsHashValue *metrics = get_cached_metrics(metrics_priv, face, glyph);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
249
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
250 if (!metrics)
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
251 return 0;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
252
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
253 return metrics->metrics.horiAdvance;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
254 }
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
255
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
256 static hb_position_t
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
257 cached_v_advance(hb_font_t *font, void *font_data, hb_codepoint_t glyph,
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
258 void *user_data)
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
259 {
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
260 FT_Face face = font_data;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
261 struct ass_shaper_metrics_data *metrics_priv = user_data;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
262 GlyphMetricsHashValue *metrics = get_cached_metrics(metrics_priv, face, glyph);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
263
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
264 if (!metrics)
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
265 return 0;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
266
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
267 return metrics->metrics.vertAdvance;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
268
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
269 }
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
270
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
271 static hb_bool_t
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
272 cached_h_origin(hb_font_t *font, void *font_data, hb_codepoint_t glyph,
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
273 hb_position_t *x, hb_position_t *y, void *user_data)
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
274 {
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
275 return 1;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
276 }
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
277
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
278 static hb_bool_t
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
279 cached_v_origin(hb_font_t *font, void *font_data, hb_codepoint_t glyph,
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
280 hb_position_t *x, hb_position_t *y, void *user_data)
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
281 {
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
282 FT_Face face = font_data;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
283 struct ass_shaper_metrics_data *metrics_priv = user_data;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
284 GlyphMetricsHashValue *metrics = get_cached_metrics(metrics_priv, face, glyph);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
285
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
286 if (!metrics)
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
287 return 0;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
288
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
289 *x = metrics->metrics.horiBearingX - metrics->metrics.vertBearingX;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
290 *y = metrics->metrics.horiBearingY - (-metrics->metrics.vertBearingY);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
291
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
292 return 1;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
293 }
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
294
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
295 static hb_position_t
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
296 get_h_kerning(hb_font_t *font, void *font_data, hb_codepoint_t first,
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
297 hb_codepoint_t second, void *user_data)
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
298 {
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
299 FT_Face face = font_data;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
300 FT_Vector kern;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
301
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
302 if (FT_Get_Kerning (face, first, second, FT_KERNING_DEFAULT, &kern))
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
303 return 0;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
304
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
305 return kern.x;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
306 }
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
307
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
308 static hb_position_t
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
309 get_v_kerning(hb_font_t *font, void *font_data, hb_codepoint_t first,
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
310 hb_codepoint_t second, void *user_data)
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
311 {
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
312 return 0;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
313 }
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
314
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
315 static hb_bool_t
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
316 cached_extents(hb_font_t *font, void *font_data, hb_codepoint_t glyph,
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
317 hb_glyph_extents_t *extents, void *user_data)
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
318 {
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
319 FT_Face face = font_data;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
320 struct ass_shaper_metrics_data *metrics_priv = user_data;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
321 GlyphMetricsHashValue *metrics = get_cached_metrics(metrics_priv, face, glyph);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
322
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
323 if (!metrics)
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
324 return 0;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
325
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
326 extents->x_bearing = metrics->metrics.horiBearingX;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
327 extents->y_bearing = metrics->metrics.horiBearingY;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
328 extents->width = metrics->metrics.width;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
329 extents->height = metrics->metrics.height;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
330
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
331 return 1;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
332 }
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
333
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
334 static hb_bool_t
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
335 get_contour_point(hb_font_t *font, void *font_data, hb_codepoint_t glyph,
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
336 unsigned int point_index, hb_position_t *x,
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
337 hb_position_t *y, void *user_data)
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
338 {
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
339 FT_Face face = font_data;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
340 int load_flags = FT_LOAD_DEFAULT | FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
341 | FT_LOAD_IGNORE_TRANSFORM;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
342
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
343 if (FT_Load_Glyph(face, glyph, load_flags))
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
344 return 0;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
345
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
346 if (point_index >= (unsigned)face->glyph->outline.n_points)
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
347 return 0;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
348
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
349 *x = face->glyph->outline.points[point_index].x;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
350 *y = face->glyph->outline.points[point_index].y;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
351
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
352 return 1;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
353 }
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
354
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
355 /**
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
356 * \brief Retrieve HarfBuzz font from cache.
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
357 * Create it from FreeType font, if needed.
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
358 * \param info glyph cluster
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
359 * \return HarfBuzz font
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
360 */
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
361 static hb_font_t *get_hb_font(ASS_Shaper *shaper, GlyphInfo *info)
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
362 {
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
363 ASS_Font *font = info->font;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
364 hb_font_t **hb_fonts;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
365
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
366 if (!font->shaper_priv)
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
367 font->shaper_priv = calloc(sizeof(ASS_ShaperFontData), 1);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
368
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
369
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
370 hb_fonts = font->shaper_priv->fonts;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
371 if (!hb_fonts[info->face_index]) {
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
372 hb_fonts[info->face_index] =
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
373 hb_ft_font_create(font->faces[info->face_index], NULL);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
374
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
375 // set up cached metrics access
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
376 font->shaper_priv->metrics_data[info->face_index] =
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
377 calloc(sizeof(struct ass_shaper_metrics_data), 1);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
378 struct ass_shaper_metrics_data *metrics =
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
379 font->shaper_priv->metrics_data[info->face_index];
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
380 metrics->metrics_cache = shaper->metrics_cache;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
381 metrics->vertical = info->font->desc.vertical;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
382
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
383 hb_font_funcs_t *funcs = hb_font_funcs_create();
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
384 font->shaper_priv->font_funcs[info->face_index] = funcs;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
385 hb_font_funcs_set_glyph_func(funcs, get_glyph,
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
386 metrics, NULL);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
387 hb_font_funcs_set_glyph_h_advance_func(funcs, cached_h_advance,
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
388 metrics, NULL);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
389 hb_font_funcs_set_glyph_v_advance_func(funcs, cached_v_advance,
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
390 metrics, NULL);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
391 hb_font_funcs_set_glyph_h_origin_func(funcs, cached_h_origin,
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
392 metrics, NULL);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
393 hb_font_funcs_set_glyph_v_origin_func(funcs, cached_v_origin,
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
394 metrics, NULL);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
395 hb_font_funcs_set_glyph_h_kerning_func(funcs, get_h_kerning,
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
396 metrics, NULL);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
397 hb_font_funcs_set_glyph_v_kerning_func(funcs, get_v_kerning,
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
398 metrics, NULL);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
399 hb_font_funcs_set_glyph_extents_func(funcs, cached_extents,
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
400 metrics, NULL);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
401 hb_font_funcs_set_glyph_contour_point_func(funcs, get_contour_point,
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
402 metrics, NULL);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
403 hb_font_set_funcs(hb_fonts[info->face_index], funcs,
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
404 font->faces[info->face_index], NULL);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
405 }
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
406
35262
49fc594fda43 Updated libass to 0.10.1
SubJunk
parents: 34342
diff changeset
407 // XXX: this is a rather crude hack
49fc594fda43 Updated libass to 0.10.1
SubJunk
parents: 34342
diff changeset
408 const double ft_size = 256.0;
49fc594fda43 Updated libass to 0.10.1
SubJunk
parents: 34342
diff changeset
409 ass_face_set_size(font->faces[info->face_index], ft_size);
34300
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
410 update_hb_size(hb_fonts[info->face_index], font->faces[info->face_index]);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
411
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
412 // update hash key for cached metrics
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
413 struct ass_shaper_metrics_data *metrics =
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
414 font->shaper_priv->metrics_data[info->face_index];
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
415 metrics->hash_key.font = info->font;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
416 metrics->hash_key.face_index = info->face_index;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
417 metrics->hash_key.size = info->font_size;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
418 metrics->hash_key.scale_x = double_to_d6(info->scale_x);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
419 metrics->hash_key.scale_y = double_to_d6(info->scale_y);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
420
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
421 return hb_fonts[info->face_index];
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
422 }
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
423
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
424 /**
36363
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
425 * \brief Map script to default language.
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
426 *
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
427 * This maps a script to a language, if a script has a representative
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
428 * language it is typically used with. Otherwise, the invalid language
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
429 * is returned.
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
430 *
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
431 * The mapping is similar to Pango's pango-language.c.
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
432 *
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
433 * \param script script tag
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
434 * \return language tag
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
435 */
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
436 static hb_language_t script_to_language(hb_script_t script)
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
437 {
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
438 switch (script) {
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
439 // Unicode 1.1
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
440 case HB_SCRIPT_ARABIC: return hb_language_from_string("ar", -1); break;
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
441 case HB_SCRIPT_ARMENIAN: return hb_language_from_string("hy", -1); break;
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
442 case HB_SCRIPT_BENGALI: return hb_language_from_string("bn", -1); break;
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
443 case HB_SCRIPT_CANADIAN_ABORIGINAL: return hb_language_from_string("iu", -1); break;
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
444 case HB_SCRIPT_CHEROKEE: return hb_language_from_string("chr", -1); break;
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
445 case HB_SCRIPT_COPTIC: return hb_language_from_string("cop", -1); break;
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
446 case HB_SCRIPT_CYRILLIC: return hb_language_from_string("ru", -1); break;
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
447 case HB_SCRIPT_DEVANAGARI: return hb_language_from_string("hi", -1); break;
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
448 case HB_SCRIPT_GEORGIAN: return hb_language_from_string("ka", -1); break;
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
449 case HB_SCRIPT_GREEK: return hb_language_from_string("el", -1); break;
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
450 case HB_SCRIPT_GUJARATI: return hb_language_from_string("gu", -1); break;
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
451 case HB_SCRIPT_GURMUKHI: return hb_language_from_string("pa", -1); break;
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
452 case HB_SCRIPT_HANGUL: return hb_language_from_string("ko", -1); break;
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
453 case HB_SCRIPT_HEBREW: return hb_language_from_string("he", -1); break;
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
454 case HB_SCRIPT_HIRAGANA: return hb_language_from_string("ja", -1); break;
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
455 case HB_SCRIPT_KANNADA: return hb_language_from_string("kn", -1); break;
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
456 case HB_SCRIPT_KATAKANA: return hb_language_from_string("ja", -1); break;
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
457 case HB_SCRIPT_LAO: return hb_language_from_string("lo", -1); break;
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
458 case HB_SCRIPT_LATIN: return hb_language_from_string("en", -1); break;
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
459 case HB_SCRIPT_MALAYALAM: return hb_language_from_string("ml", -1); break;
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
460 case HB_SCRIPT_MONGOLIAN: return hb_language_from_string("mn", -1); break;
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
461 case HB_SCRIPT_ORIYA: return hb_language_from_string("or", -1); break;
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
462 case HB_SCRIPT_SYRIAC: return hb_language_from_string("syr", -1); break;
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
463 case HB_SCRIPT_TAMIL: return hb_language_from_string("ta", -1); break;
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
464 case HB_SCRIPT_TELUGU: return hb_language_from_string("te", -1); break;
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
465 case HB_SCRIPT_THAI: return hb_language_from_string("th", -1); break;
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
466
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
467 // Unicode 2.0
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
468 case HB_SCRIPT_TIBETAN: return hb_language_from_string("bo", -1); break;
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
469
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
470 // Unicode 3.0
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
471 case HB_SCRIPT_ETHIOPIC: return hb_language_from_string("am", -1); break;
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
472 case HB_SCRIPT_KHMER: return hb_language_from_string("km", -1); break;
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
473 case HB_SCRIPT_MYANMAR: return hb_language_from_string("my", -1); break;
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
474 case HB_SCRIPT_SINHALA: return hb_language_from_string("si", -1); break;
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
475 case HB_SCRIPT_THAANA: return hb_language_from_string("dv", -1); break;
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
476
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
477 // Unicode 3.2
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
478 case HB_SCRIPT_BUHID: return hb_language_from_string("bku", -1); break;
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
479 case HB_SCRIPT_HANUNOO: return hb_language_from_string("hnn", -1); break;
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
480 case HB_SCRIPT_TAGALOG: return hb_language_from_string("tl", -1); break;
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
481 case HB_SCRIPT_TAGBANWA: return hb_language_from_string("tbw", -1); break;
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
482
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
483 // Unicode 4.0
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
484 case HB_SCRIPT_UGARITIC: return hb_language_from_string("uga", -1); break;
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
485
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
486 // Unicode 4.1
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
487 case HB_SCRIPT_BUGINESE: return hb_language_from_string("bug", -1); break;
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
488 case HB_SCRIPT_OLD_PERSIAN: return hb_language_from_string("peo", -1); break;
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
489 case HB_SCRIPT_SYLOTI_NAGRI: return hb_language_from_string("syl", -1); break;
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
490
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
491 // Unicode 5.0
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
492 case HB_SCRIPT_NKO: return hb_language_from_string("nko", -1); break;
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
493
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
494 // no representative language exists
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
495 default: return HB_LANGUAGE_INVALID; break;
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
496 }
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
497 }
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
498
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
499 /**
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
500 * \brief Determine language to be used for shaping a run.
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
501 *
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
502 * \param shaper shaper instance
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
503 * \param script script tag associated with run
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
504 * \return language tag
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
505 */
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
506 static hb_language_t
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
507 hb_shaper_get_run_language(ASS_Shaper *shaper, hb_script_t script)
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
508 {
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
509 hb_language_t lang;
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
510
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
511 // override set, use it
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
512 if (shaper->language != HB_LANGUAGE_INVALID)
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
513 return shaper->language;
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
514
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
515 // get default language for given script
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
516 lang = script_to_language(script);
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
517
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
518 // no dice, use system default
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
519 if (lang == HB_LANGUAGE_INVALID)
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
520 lang = hb_language_get_default();
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
521
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
522 return lang;
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
523 }
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
524
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
525 /**
34300
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
526 * \brief Shape event text with HarfBuzz. Full OpenType shaping.
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
527 * \param glyphs glyph clusters
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
528 * \param len number of clusters
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
529 */
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
530 static void shape_harfbuzz(ASS_Shaper *shaper, GlyphInfo *glyphs, size_t len)
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
531 {
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
532 int i, j;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
533 int run = 0;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
534 struct {
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
535 int offset;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
536 int end;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
537 hb_buffer_t *buf;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
538 hb_font_t *font;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
539 } runs[MAX_RUNS];
35262
49fc594fda43 Updated libass to 0.10.1
SubJunk
parents: 34342
diff changeset
540 const double ft_size = 256.0;
34300
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
541
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
542 for (i = 0; i < len && run < MAX_RUNS; i++, run++) {
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
543 // get length and level of the current run
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
544 int k = i;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
545 int level = glyphs[i].shape_run_id;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
546 int direction = shaper->emblevels[k] % 2;
36363
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
547 hb_script_t script = glyphs[i].script;
34300
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
548 while (i < (len - 1) && level == glyphs[i+1].shape_run_id)
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
549 i++;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
550 runs[run].offset = k;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
551 runs[run].end = i;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
552 runs[run].buf = hb_buffer_create();
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
553 runs[run].font = get_hb_font(shaper, glyphs + k);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
554 set_run_features(shaper, glyphs + k);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
555 hb_buffer_pre_allocate(runs[run].buf, i - k + 1);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
556 hb_buffer_set_direction(runs[run].buf, direction ? HB_DIRECTION_RTL :
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
557 HB_DIRECTION_LTR);
36363
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
558 hb_buffer_set_language(runs[run].buf,
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
559 hb_shaper_get_run_language(shaper, script));
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
560 hb_buffer_set_script(runs[run].buf, script);
34300
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
561 hb_buffer_add_utf32(runs[run].buf, shaper->event_text + k, i - k + 1,
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
562 0, i - k + 1);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
563 hb_shape(runs[run].font, runs[run].buf, shaper->features,
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
564 shaper->n_features);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
565 }
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
566
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
567 // Initialize: skip all glyphs, this is undone later as needed
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
568 for (i = 0; i < len; i++)
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
569 glyphs[i].skip = 1;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
570
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
571 // Update glyph indexes, positions and advances from the shaped runs
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
572 for (i = 0; i < run; i++) {
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
573 int num_glyphs = hb_buffer_get_length(runs[i].buf);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
574 hb_glyph_info_t *glyph_info = hb_buffer_get_glyph_infos(runs[i].buf, NULL);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
575 hb_glyph_position_t *pos = hb_buffer_get_glyph_positions(runs[i].buf, NULL);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
576
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
577 for (j = 0; j < num_glyphs; j++) {
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
578 int idx = glyph_info[j].cluster + runs[i].offset;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
579 GlyphInfo *info = glyphs + idx;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
580 GlyphInfo *root = info;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
581
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
582 // if we have more than one glyph per cluster, allocate a new one
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
583 // and attach to the root glyph
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
584 if (info->skip == 0) {
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
585 while (info->next)
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
586 info = info->next;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
587 info->next = malloc(sizeof(GlyphInfo));
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
588 memcpy(info->next, info, sizeof(GlyphInfo));
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
589 info = info->next;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
590 info->next = NULL;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
591 }
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
592
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
593 // set position and advance
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
594 info->skip = 0;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
595 info->glyph_index = glyph_info[j].codepoint;
35262
49fc594fda43 Updated libass to 0.10.1
SubJunk
parents: 34342
diff changeset
596 info->offset.x = pos[j].x_offset * info->scale_x * (info->font_size / ft_size);
49fc594fda43 Updated libass to 0.10.1
SubJunk
parents: 34342
diff changeset
597 info->offset.y = -pos[j].y_offset * info->scale_y * (info->font_size / ft_size);
49fc594fda43 Updated libass to 0.10.1
SubJunk
parents: 34342
diff changeset
598 info->advance.x = pos[j].x_advance * info->scale_x * (info->font_size / ft_size);
49fc594fda43 Updated libass to 0.10.1
SubJunk
parents: 34342
diff changeset
599 info->advance.y = -pos[j].y_advance * info->scale_y * (info->font_size / ft_size);
34300
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
600
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
601 // accumulate advance in the root glyph
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
602 root->cluster_advance.x += info->advance.x;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
603 root->cluster_advance.y += info->advance.y;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
604 }
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
605 }
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
606
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
607 // Free runs and associated data
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
608 for (i = 0; i < run; i++) {
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
609 hb_buffer_destroy(runs[i].buf);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
610 }
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
611
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
612 }
36363
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
613
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
614 /**
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
615 * \brief Determine script property of all characters. Characters of script
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
616 * common and inherited get their script from their context.
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
617 *
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
618 */
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
619 void ass_shaper_determine_script(ASS_Shaper *shaper, GlyphInfo *glyphs,
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
620 size_t len)
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
621 {
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
622 int i;
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
623 int backwards_scan = 0;
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
624 hb_unicode_funcs_t *ufuncs = hb_unicode_funcs_get_default();
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
625 hb_script_t last_script = HB_SCRIPT_UNKNOWN;
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
626
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
627 // determine script (forward scan)
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
628 for (i = 0; i < len; i++) {
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
629 GlyphInfo *info = glyphs + i;
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
630 info->script = hb_unicode_script(ufuncs, info->symbol);
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
631
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
632 // common/inherit codepoints inherit script from context
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
633 if (info->script == HB_SCRIPT_COMMON ||
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
634 info->script == HB_SCRIPT_INHERITED) {
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
635 // unknown is not a valid context
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
636 if (last_script != HB_SCRIPT_UNKNOWN)
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
637 info->script = last_script;
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
638 else
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
639 // do a backwards scan to check if next codepoint
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
640 // contains a valid script for context
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
641 backwards_scan = 1;
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
642 } else {
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
643 last_script = info->script;
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
644 }
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
645 }
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
646
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
647 // determine script (backwards scan, if needed)
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
648 last_script = HB_SCRIPT_UNKNOWN;
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
649 for (i = len - 1; i >= 0 && backwards_scan; i--) {
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
650 GlyphInfo *info = glyphs + i;
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
651
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
652 // common/inherit codepoints inherit script from context
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
653 if (info->script == HB_SCRIPT_COMMON ||
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
654 info->script == HB_SCRIPT_INHERITED) {
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
655 // unknown script is not a valid context
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
656 if (last_script != HB_SCRIPT_UNKNOWN)
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
657 info->script = last_script;
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
658 } else {
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
659 last_script = info->script;
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
660 }
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
661 }
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
662 }
34300
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
663 #endif
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
664
34342
575ad51cc996 Allow compiling libass without fribidi again.
reimar
parents: 34300
diff changeset
665 #ifdef CONFIG_FRIBIDI
34300
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
666 /**
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
667 * \brief Shape event text with FriBidi. Does mirroring and simple
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
668 * Arabic shaping.
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
669 * \param len number of clusters
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
670 */
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
671 static void shape_fribidi(ASS_Shaper *shaper, GlyphInfo *glyphs, size_t len)
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
672 {
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
673 int i;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
674 FriBidiJoiningType *joins = calloc(sizeof(*joins), len);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
675
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
676 // shape on codepoint level
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
677 fribidi_get_joining_types(shaper->event_text, len, joins);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
678 fribidi_join_arabic(shaper->ctypes, len, shaper->emblevels, joins);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
679 fribidi_shape(FRIBIDI_FLAGS_DEFAULT | FRIBIDI_FLAGS_ARABIC,
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
680 shaper->emblevels, len, joins, shaper->event_text);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
681
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
682 // update indexes
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
683 for (i = 0; i < len; i++) {
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
684 GlyphInfo *info = glyphs + i;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
685 FT_Face face = info->font->faces[info->face_index];
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
686 info->symbol = shaper->event_text[i];
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
687 info->glyph_index = FT_Get_Char_Index(face, shaper->event_text[i]);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
688 }
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
689
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
690 free(joins);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
691 }
34342
575ad51cc996 Allow compiling libass without fribidi again.
reimar
parents: 34300
diff changeset
692 #endif
34300
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
693
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
694 /**
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
695 * \brief Toggle kerning for HarfBuzz shaping.
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
696 * NOTE: currently only works with OpenType fonts, the TrueType fallback *always*
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
697 * kerns. It's a bug in HarfBuzz.
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
698 */
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
699 void ass_shaper_set_kerning(ASS_Shaper *shaper, int kern)
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
700 {
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
701 #ifdef CONFIG_HARFBUZZ
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
702 shaper->features[KERN].value = !!kern;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
703 #endif
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
704 }
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
705
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
706 /**
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
707 * \brief Find shape runs according to the event's selected fonts
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
708 */
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
709 void ass_shaper_find_runs(ASS_Shaper *shaper, ASS_Renderer *render_priv,
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
710 GlyphInfo *glyphs, size_t len)
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
711 {
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
712 int i;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
713 int shape_run = 0;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
714
36363
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
715 #ifdef CONFIG_HARFBUZZ
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
716 ass_shaper_determine_script(shaper, glyphs, len);
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
717 #endif
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
718
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
719 // find appropriate fonts for the shape runs
34300
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
720 for (i = 0; i < len; i++) {
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
721 GlyphInfo *last = glyphs + i - 1;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
722 GlyphInfo *info = glyphs + i;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
723 // skip drawings
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
724 if (info->symbol == 0xfffc)
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
725 continue;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
726 // set size and get glyph index
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
727 ass_font_get_index(render_priv->fontconfig_priv, info->font,
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
728 info->symbol, &info->face_index, &info->glyph_index);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
729 // shape runs share the same font face and size
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
730 if (i > 0 && (last->font != info->font ||
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
731 last->font_size != info->font_size ||
36363
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
732 last->face_index != info->face_index ||
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
733 last->script != info->script))
34300
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
734 shape_run++;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
735 info->shape_run_id = shape_run;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
736 }
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
737 }
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
738
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
739 /**
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
740 * \brief Set base direction (paragraph direction) of the text.
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
741 * \param dir base direction
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
742 */
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
743 void ass_shaper_set_base_direction(ASS_Shaper *shaper, FriBidiParType dir)
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
744 {
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
745 shaper->base_direction = dir;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
746 }
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
747
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
748 /**
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
749 * \brief Set language hint. Some languages have specific character variants,
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
750 * like Serbian Cyrillic.
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
751 * \param lang ISO 639-1 two-letter language code
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
752 */
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
753 void ass_shaper_set_language(ASS_Shaper *shaper, const char *code)
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
754 {
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
755 #ifdef CONFIG_HARFBUZZ
36363
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
756 hb_language_t lang;
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
757
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
758 if (code)
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
759 lang = hb_language_from_string(code, -1);
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
760 else
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
761 lang = HB_LANGUAGE_INVALID;
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
762
c3aaaf17c721 Update libass to latest git version.
reimar
parents: 35274
diff changeset
763 shaper->language = lang;
34300
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
764 #endif
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
765 }
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
766
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
767 /**
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
768 * Set shaping level. Essentially switches between FriBidi and HarfBuzz.
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
769 */
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
770 void ass_shaper_set_level(ASS_Shaper *shaper, ASS_ShapingLevel level)
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
771 {
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
772 shaper->shaping_level = level;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
773 }
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
774
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
775 /**
35262
49fc594fda43 Updated libass to 0.10.1
SubJunk
parents: 34342
diff changeset
776 * \brief Remove all zero-width invisible characters from the text.
49fc594fda43 Updated libass to 0.10.1
SubJunk
parents: 34342
diff changeset
777 * \param text_info text
49fc594fda43 Updated libass to 0.10.1
SubJunk
parents: 34342
diff changeset
778 */
49fc594fda43 Updated libass to 0.10.1
SubJunk
parents: 34342
diff changeset
779 static void ass_shaper_skip_characters(TextInfo *text_info)
49fc594fda43 Updated libass to 0.10.1
SubJunk
parents: 34342
diff changeset
780 {
49fc594fda43 Updated libass to 0.10.1
SubJunk
parents: 34342
diff changeset
781 int i;
49fc594fda43 Updated libass to 0.10.1
SubJunk
parents: 34342
diff changeset
782 GlyphInfo *glyphs = text_info->glyphs;
49fc594fda43 Updated libass to 0.10.1
SubJunk
parents: 34342
diff changeset
783
49fc594fda43 Updated libass to 0.10.1
SubJunk
parents: 34342
diff changeset
784 for (i = 0; i < text_info->length; i++) {
49fc594fda43 Updated libass to 0.10.1
SubJunk
parents: 34342
diff changeset
785 // Skip direction override control characters
49fc594fda43 Updated libass to 0.10.1
SubJunk
parents: 34342
diff changeset
786 if ((glyphs[i].symbol <= 0x202e && glyphs[i].symbol >= 0x202a)
49fc594fda43 Updated libass to 0.10.1
SubJunk
parents: 34342
diff changeset
787 || (glyphs[i].symbol <= 0x200f && glyphs[i].symbol >= 0x200b)
49fc594fda43 Updated libass to 0.10.1
SubJunk
parents: 34342
diff changeset
788 || (glyphs[i].symbol <= 0x2063 && glyphs[i].symbol >= 0x2060)
49fc594fda43 Updated libass to 0.10.1
SubJunk
parents: 34342
diff changeset
789 || glyphs[i].symbol == 0xfeff
49fc594fda43 Updated libass to 0.10.1
SubJunk
parents: 34342
diff changeset
790 || glyphs[i].symbol == 0x00ad
49fc594fda43 Updated libass to 0.10.1
SubJunk
parents: 34342
diff changeset
791 || glyphs[i].symbol == 0x034f) {
49fc594fda43 Updated libass to 0.10.1
SubJunk
parents: 34342
diff changeset
792 glyphs[i].symbol = 0;
49fc594fda43 Updated libass to 0.10.1
SubJunk
parents: 34342
diff changeset
793 glyphs[i].skip++;
49fc594fda43 Updated libass to 0.10.1
SubJunk
parents: 34342
diff changeset
794 }
49fc594fda43 Updated libass to 0.10.1
SubJunk
parents: 34342
diff changeset
795 }
49fc594fda43 Updated libass to 0.10.1
SubJunk
parents: 34342
diff changeset
796 }
49fc594fda43 Updated libass to 0.10.1
SubJunk
parents: 34342
diff changeset
797
49fc594fda43 Updated libass to 0.10.1
SubJunk
parents: 34342
diff changeset
798 /**
34300
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
799 * \brief Shape an event's text. Calculates directional runs and shapes them.
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
800 * \param text_info event's text
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
801 */
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
802 void ass_shaper_shape(ASS_Shaper *shaper, TextInfo *text_info)
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
803 {
34342
575ad51cc996 Allow compiling libass without fribidi again.
reimar
parents: 34300
diff changeset
804 #ifndef CONFIG_FRIBIDI
575ad51cc996 Allow compiling libass without fribidi again.
reimar
parents: 34300
diff changeset
805 check_allocations(shaper, text_info->length);
575ad51cc996 Allow compiling libass without fribidi again.
reimar
parents: 34300
diff changeset
806 #else
34300
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
807 int i, last_break;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
808 FriBidiParType dir;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
809 GlyphInfo *glyphs = text_info->glyphs;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
810
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
811 check_allocations(shaper, text_info->length);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
812
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
813 // Get bidi character types and embedding levels
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
814 last_break = 0;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
815 for (i = 0; i < text_info->length; i++) {
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
816 shaper->event_text[i] = glyphs[i].symbol;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
817 // embedding levels should be calculated paragraph by paragraph
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
818 if (glyphs[i].symbol == '\n' || i == text_info->length - 1) {
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
819 dir = shaper->base_direction;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
820 fribidi_get_bidi_types(shaper->event_text + last_break,
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
821 i - last_break + 1, shaper->ctypes + last_break);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
822 fribidi_get_par_embedding_levels(shaper->ctypes + last_break,
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
823 i - last_break + 1, &dir, shaper->emblevels + last_break);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
824 last_break = i + 1;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
825 }
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
826 }
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
827
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
828 // add embedding levels to shape runs for final runs
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
829 for (i = 0; i < text_info->length; i++) {
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
830 glyphs[i].shape_run_id += shaper->emblevels[i];
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
831 }
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
832
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
833 #ifdef CONFIG_HARFBUZZ
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
834 switch (shaper->shaping_level) {
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
835 case ASS_SHAPING_SIMPLE:
35274
4f4a90b80a9a libass: Fixed RTL languages
SubJunk
parents: 35262
diff changeset
836 shape_fribidi(shaper, glyphs, text_info->length);
35262
49fc594fda43 Updated libass to 0.10.1
SubJunk
parents: 34342
diff changeset
837 ass_shaper_skip_characters(text_info);
34300
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
838 break;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
839 case ASS_SHAPING_COMPLEX:
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
840 shape_harfbuzz(shaper, glyphs, text_info->length);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
841 break;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
842 }
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
843 #else
35274
4f4a90b80a9a libass: Fixed RTL languages
SubJunk
parents: 35262
diff changeset
844 shape_fribidi(shaper, glyphs, text_info->length);
35262
49fc594fda43 Updated libass to 0.10.1
SubJunk
parents: 34342
diff changeset
845 ass_shaper_skip_characters(text_info);
34300
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
846 #endif
34342
575ad51cc996 Allow compiling libass without fribidi again.
reimar
parents: 34300
diff changeset
847 #endif
34300
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
848 }
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
849
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
850 /**
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
851 * \brief Create a new shaper instance and preallocate data structures
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
852 * \param prealloc preallocation size
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
853 */
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
854 ASS_Shaper *ass_shaper_new(size_t prealloc)
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
855 {
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
856 ASS_Shaper *shaper = calloc(sizeof(*shaper), 1);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
857
34342
575ad51cc996 Allow compiling libass without fribidi again.
reimar
parents: 34300
diff changeset
858 #ifdef CONFIG_FRIBIDI
34300
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
859 shaper->base_direction = FRIBIDI_PAR_ON;
34342
575ad51cc996 Allow compiling libass without fribidi again.
reimar
parents: 34300
diff changeset
860 #endif
34300
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
861 check_allocations(shaper, prealloc);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
862
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
863 #ifdef CONFIG_HARFBUZZ
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
864 init_features(shaper);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
865 shaper->metrics_cache = ass_glyph_metrics_cache_create();
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
866 #endif
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
867
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
868 return shaper;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
869 }
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
870
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
871
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
872 /**
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
873 * \brief clean up additional data temporarily needed for shaping and
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
874 * (e.g. additional glyphs allocated)
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
875 */
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
876 void ass_shaper_cleanup(ASS_Shaper *shaper, TextInfo *text_info)
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
877 {
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
878 int i;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
879
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
880 for (i = 0; i < text_info->length; i++) {
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
881 GlyphInfo *info = text_info->glyphs + i;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
882 info = info->next;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
883 while (info) {
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
884 GlyphInfo *next = info->next;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
885 free(info);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
886 info = next;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
887 }
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
888 }
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
889 }
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
890
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
891 /**
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
892 * \brief Calculate reorder map to render glyphs in visual order
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
893 */
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
894 FriBidiStrIndex *ass_shaper_reorder(ASS_Shaper *shaper, TextInfo *text_info)
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
895 {
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
896 int i;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
897
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
898 // Initialize reorder map
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
899 for (i = 0; i < text_info->length; i++)
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
900 shaper->cmap[i] = i;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
901
34342
575ad51cc996 Allow compiling libass without fribidi again.
reimar
parents: 34300
diff changeset
902 #ifdef CONFIG_FRIBIDI
34300
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
903 // Create reorder map line-by-line
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
904 for (i = 0; i < text_info->n_lines; i++) {
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
905 LineInfo *line = text_info->lines + i;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
906 int level;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
907 FriBidiParType dir = FRIBIDI_PAR_ON;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
908
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
909 level = fribidi_reorder_line(0,
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
910 shaper->ctypes + line->offset, line->len, 0, dir,
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
911 shaper->emblevels + line->offset, NULL,
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
912 shaper->cmap + line->offset);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
913 }
34342
575ad51cc996 Allow compiling libass without fribidi again.
reimar
parents: 34300
diff changeset
914 #endif
34300
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
915
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
916 return shaper->cmap;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
917 }
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
918
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
919 /**
35262
49fc594fda43 Updated libass to 0.10.1
SubJunk
parents: 34342
diff changeset
920 * \brief Resolve a Windows font charset number to a suitable
34300
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
921 * base direction. 177 and 178 are Hebrew and Arabic respectively, and
35262
49fc594fda43 Updated libass to 0.10.1
SubJunk
parents: 34342
diff changeset
922 * they map to RTL. Everything else maps to LTR for compatibility
49fc594fda43 Updated libass to 0.10.1
SubJunk
parents: 34342
diff changeset
923 * reasons. The special value -1, which is not a legal Windows font charset
49fc594fda43 Updated libass to 0.10.1
SubJunk
parents: 34342
diff changeset
924 * number, can be used for autodetection.
34300
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
925 * \param enc Windows font encoding
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
926 */
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
927 FriBidiParType resolve_base_direction(int enc)
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
928 {
34342
575ad51cc996 Allow compiling libass without fribidi again.
reimar
parents: 34300
diff changeset
929 #ifdef CONFIG_FRIBIDI
34300
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
930 switch (enc) {
35262
49fc594fda43 Updated libass to 0.10.1
SubJunk
parents: 34342
diff changeset
931 case -1:
34300
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
932 return FRIBIDI_PAR_ON;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
933 case 177:
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
934 case 178:
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
935 return FRIBIDI_PAR_RTL;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
936 default:
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
937 return FRIBIDI_PAR_LTR;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
938 }
34342
575ad51cc996 Allow compiling libass without fribidi again.
reimar
parents: 34300
diff changeset
939 #else
575ad51cc996 Allow compiling libass without fribidi again.
reimar
parents: 34300
diff changeset
940 return 0;
575ad51cc996 Allow compiling libass without fribidi again.
reimar
parents: 34300
diff changeset
941 #endif
34300
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
942 }