annotate libass/ass_shaper.c @ 34346:3d0c795524b0

Fix bug with wrong focus in file selector. The focus can only be set to fsFNameList after it's realized and mapped. This also removes the irritating selection of the fsPathCombo.
author ib
date Sun, 11 Dec 2011 16:02:02 +0000
parents 575ad51cc996
children 49fc594fda43
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));
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
216 val = ass_cache_put(metrics->metrics_cache, &metrics->hash_key, &new_val);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
217 }
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
218
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
219 return val;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
220 }
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
221
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
222 static hb_bool_t
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
223 get_glyph(hb_font_t *font, void *font_data, hb_codepoint_t unicode,
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
224 hb_codepoint_t variation, hb_codepoint_t *glyph, void *user_data)
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
225 {
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
226 FT_Face face = font_data;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
227
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
228 if (variation)
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
229 *glyph = FT_Face_GetCharVariantIndex(face, unicode, variation);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
230 else
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
231 *glyph = FT_Get_Char_Index(face, unicode);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
232
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
233 return *glyph != 0;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
234 }
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
235
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
236 static hb_position_t
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
237 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
238 void *user_data)
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
239 {
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
240 FT_Face face = font_data;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
241 struct ass_shaper_metrics_data *metrics_priv = user_data;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
242 GlyphMetricsHashValue *metrics = get_cached_metrics(metrics_priv, face, glyph);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
243
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
244 if (!metrics)
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
245 return 0;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
246
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
247 if (metrics_priv->vertical && glyph > VERTICAL_LOWER_BOUND)
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
248 return metrics->metrics.vertAdvance;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
249
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
250 return metrics->metrics.horiAdvance;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
251 }
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
252
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
253 static hb_position_t
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
254 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
255 void *user_data)
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
256 {
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
257 FT_Face face = font_data;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
258 struct ass_shaper_metrics_data *metrics_priv = user_data;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
259 GlyphMetricsHashValue *metrics = get_cached_metrics(metrics_priv, face, glyph);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
260
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
261 if (!metrics)
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
262 return 0;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
263
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
264 return metrics->metrics.vertAdvance;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
265
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
266 }
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
267
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
268 static hb_bool_t
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
269 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
270 hb_position_t *x, hb_position_t *y, void *user_data)
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
271 {
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
272 return 1;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
273 }
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
274
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
275 static hb_bool_t
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
276 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
277 hb_position_t *x, hb_position_t *y, void *user_data)
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
278 {
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
279 FT_Face face = font_data;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
280 struct ass_shaper_metrics_data *metrics_priv = user_data;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
281 GlyphMetricsHashValue *metrics = get_cached_metrics(metrics_priv, face, glyph);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
282
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
283 if (!metrics)
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
284 return 0;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
285
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
286 *x = metrics->metrics.horiBearingX - metrics->metrics.vertBearingX;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
287 *y = metrics->metrics.horiBearingY - (-metrics->metrics.vertBearingY);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
288
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
289 return 1;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
290 }
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
291
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
292 static hb_position_t
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
293 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
294 hb_codepoint_t second, void *user_data)
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
295 {
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
296 FT_Face face = font_data;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
297 FT_Vector kern;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
298
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
299 if (FT_Get_Kerning (face, first, second, FT_KERNING_DEFAULT, &kern))
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
300 return 0;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
301
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
302 return kern.x;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
303 }
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
304
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
305 static hb_position_t
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
306 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
307 hb_codepoint_t second, void *user_data)
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
308 {
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
309 return 0;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
310 }
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
311
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
312 static hb_bool_t
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
313 cached_extents(hb_font_t *font, void *font_data, hb_codepoint_t glyph,
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
314 hb_glyph_extents_t *extents, void *user_data)
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
315 {
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
316 FT_Face face = font_data;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
317 struct ass_shaper_metrics_data *metrics_priv = user_data;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
318 GlyphMetricsHashValue *metrics = get_cached_metrics(metrics_priv, face, glyph);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
319
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
320 if (!metrics)
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
321 return 0;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
322
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
323 extents->x_bearing = metrics->metrics.horiBearingX;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
324 extents->y_bearing = metrics->metrics.horiBearingY;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
325 extents->width = metrics->metrics.width;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
326 extents->height = metrics->metrics.height;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
327
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
328 return 1;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
329 }
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
330
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
331 static hb_bool_t
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
332 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
333 unsigned int point_index, hb_position_t *x,
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
334 hb_position_t *y, void *user_data)
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
335 {
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
336 FT_Face face = font_data;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
337 int load_flags = FT_LOAD_DEFAULT | FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
338 | FT_LOAD_IGNORE_TRANSFORM;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
339
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
340 if (FT_Load_Glyph(face, glyph, load_flags))
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
341 return 0;
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 (point_index >= (unsigned)face->glyph->outline.n_points)
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 *x = face->glyph->outline.points[point_index].x;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
347 *y = face->glyph->outline.points[point_index].y;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
348
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
349 return 1;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
350 }
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
351
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
352 /**
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
353 * \brief Retrieve HarfBuzz font from cache.
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
354 * Create it from FreeType font, if needed.
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
355 * \param info glyph cluster
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
356 * \return HarfBuzz font
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
357 */
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
358 static hb_font_t *get_hb_font(ASS_Shaper *shaper, GlyphInfo *info)
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
359 {
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
360 ASS_Font *font = info->font;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
361 hb_font_t **hb_fonts;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
362
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
363 if (!font->shaper_priv)
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
364 font->shaper_priv = calloc(sizeof(ASS_ShaperFontData), 1);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
365
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
366
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
367 hb_fonts = font->shaper_priv->fonts;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
368 if (!hb_fonts[info->face_index]) {
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
369 hb_fonts[info->face_index] =
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
370 hb_ft_font_create(font->faces[info->face_index], NULL);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
371
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
372 // set up cached metrics access
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
373 font->shaper_priv->metrics_data[info->face_index] =
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
374 calloc(sizeof(struct ass_shaper_metrics_data), 1);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
375 struct ass_shaper_metrics_data *metrics =
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 metrics->metrics_cache = shaper->metrics_cache;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
378 metrics->vertical = info->font->desc.vertical;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
379
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
380 hb_font_funcs_t *funcs = hb_font_funcs_create();
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
381 font->shaper_priv->font_funcs[info->face_index] = funcs;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
382 hb_font_funcs_set_glyph_func(funcs, get_glyph,
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
383 metrics, NULL);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
384 hb_font_funcs_set_glyph_h_advance_func(funcs, cached_h_advance,
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
385 metrics, NULL);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
386 hb_font_funcs_set_glyph_v_advance_func(funcs, cached_v_advance,
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
387 metrics, NULL);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
388 hb_font_funcs_set_glyph_h_origin_func(funcs, cached_h_origin,
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
389 metrics, NULL);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
390 hb_font_funcs_set_glyph_v_origin_func(funcs, cached_v_origin,
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
391 metrics, NULL);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
392 hb_font_funcs_set_glyph_h_kerning_func(funcs, get_h_kerning,
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
393 metrics, NULL);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
394 hb_font_funcs_set_glyph_v_kerning_func(funcs, get_v_kerning,
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
395 metrics, NULL);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
396 hb_font_funcs_set_glyph_extents_func(funcs, cached_extents,
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
397 metrics, NULL);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
398 hb_font_funcs_set_glyph_contour_point_func(funcs, get_contour_point,
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
399 metrics, NULL);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
400 hb_font_set_funcs(hb_fonts[info->face_index], funcs,
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
401 font->faces[info->face_index], NULL);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
402 }
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
403
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
404 ass_face_set_size(font->faces[info->face_index], info->font_size);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
405 update_hb_size(hb_fonts[info->face_index], font->faces[info->face_index]);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
406
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
407 // update hash key for cached metrics
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
408 struct ass_shaper_metrics_data *metrics =
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
409 font->shaper_priv->metrics_data[info->face_index];
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
410 metrics->hash_key.font = info->font;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
411 metrics->hash_key.face_index = info->face_index;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
412 metrics->hash_key.size = info->font_size;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
413 metrics->hash_key.scale_x = double_to_d6(info->scale_x);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
414 metrics->hash_key.scale_y = double_to_d6(info->scale_y);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
415
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
416 return hb_fonts[info->face_index];
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
417 }
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
418
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
419 /**
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
420 * \brief Shape event text with HarfBuzz. Full OpenType shaping.
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
421 * \param glyphs glyph clusters
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
422 * \param len number of clusters
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
423 */
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
424 static void shape_harfbuzz(ASS_Shaper *shaper, GlyphInfo *glyphs, size_t len)
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
425 {
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
426 int i, j;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
427 int run = 0;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
428 struct {
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
429 int offset;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
430 int end;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
431 hb_buffer_t *buf;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
432 hb_font_t *font;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
433 } runs[MAX_RUNS];
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
434
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
435
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
436 for (i = 0; i < len && run < MAX_RUNS; i++, run++) {
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
437 // get length and level of the current run
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
438 int k = i;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
439 int level = glyphs[i].shape_run_id;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
440 int direction = shaper->emblevels[k] % 2;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
441 while (i < (len - 1) && level == glyphs[i+1].shape_run_id)
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
442 i++;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
443 runs[run].offset = k;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
444 runs[run].end = i;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
445 runs[run].buf = hb_buffer_create();
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
446 runs[run].font = get_hb_font(shaper, glyphs + k);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
447 set_run_features(shaper, glyphs + k);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
448 hb_buffer_pre_allocate(runs[run].buf, i - k + 1);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
449 hb_buffer_set_direction(runs[run].buf, direction ? HB_DIRECTION_RTL :
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
450 HB_DIRECTION_LTR);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
451 hb_buffer_set_language(runs[run].buf, shaper->language);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
452 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
453 0, i - k + 1);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
454 hb_shape(runs[run].font, runs[run].buf, shaper->features,
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
455 shaper->n_features);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
456 }
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
457
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
458 // Initialize: skip all glyphs, this is undone later as needed
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
459 for (i = 0; i < len; i++)
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
460 glyphs[i].skip = 1;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
461
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
462 // Update glyph indexes, positions and advances from the shaped runs
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
463 for (i = 0; i < run; i++) {
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
464 int num_glyphs = hb_buffer_get_length(runs[i].buf);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
465 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
466 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
467
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
468 for (j = 0; j < num_glyphs; j++) {
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
469 int idx = glyph_info[j].cluster + runs[i].offset;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
470 GlyphInfo *info = glyphs + idx;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
471 GlyphInfo *root = info;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
472
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
473 // if we have more than one glyph per cluster, allocate a new one
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
474 // and attach to the root glyph
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
475 if (info->skip == 0) {
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
476 while (info->next)
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
477 info = info->next;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
478 info->next = malloc(sizeof(GlyphInfo));
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
479 memcpy(info->next, info, sizeof(GlyphInfo));
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
480 info = info->next;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
481 info->next = NULL;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
482 }
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
483
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
484 // set position and advance
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
485 info->skip = 0;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
486 info->glyph_index = glyph_info[j].codepoint;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
487 info->offset.x = pos[j].x_offset * info->scale_x;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
488 info->offset.y = -pos[j].y_offset * info->scale_y;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
489 info->advance.x = pos[j].x_advance * info->scale_x;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
490 info->advance.y = -pos[j].y_advance * info->scale_y;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
491
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
492 // accumulate advance in the root glyph
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
493 root->cluster_advance.x += info->advance.x;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
494 root->cluster_advance.y += info->advance.y;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
495 }
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
496 }
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
497
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
498 // Free runs and associated data
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
499 for (i = 0; i < run; i++) {
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
500 hb_buffer_destroy(runs[i].buf);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
501 }
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
502
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
503 }
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
504 #endif
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
505
34342
575ad51cc996 Allow compiling libass without fribidi again.
reimar
parents: 34300
diff changeset
506 #ifdef CONFIG_FRIBIDI
34300
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
507 /**
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
508 * \brief Shape event text with FriBidi. Does mirroring and simple
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
509 * Arabic shaping.
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
510 * \param len number of clusters
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
511 */
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
512 static void shape_fribidi(ASS_Shaper *shaper, GlyphInfo *glyphs, size_t len)
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
513 {
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
514 int i;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
515 FriBidiJoiningType *joins = calloc(sizeof(*joins), len);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
516
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
517 // shape on codepoint level
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
518 fribidi_get_joining_types(shaper->event_text, len, joins);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
519 fribidi_join_arabic(shaper->ctypes, len, shaper->emblevels, joins);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
520 fribidi_shape(FRIBIDI_FLAGS_DEFAULT | FRIBIDI_FLAGS_ARABIC,
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
521 shaper->emblevels, len, joins, shaper->event_text);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
522
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
523 // update indexes
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
524 for (i = 0; i < len; i++) {
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
525 GlyphInfo *info = glyphs + i;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
526 FT_Face face = info->font->faces[info->face_index];
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
527 info->symbol = shaper->event_text[i];
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
528 info->glyph_index = FT_Get_Char_Index(face, shaper->event_text[i]);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
529 }
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
530
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
531 free(joins);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
532 }
34342
575ad51cc996 Allow compiling libass without fribidi again.
reimar
parents: 34300
diff changeset
533 #endif
34300
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
534
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
535 /**
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
536 * \brief Toggle kerning for HarfBuzz shaping.
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
537 * NOTE: currently only works with OpenType fonts, the TrueType fallback *always*
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
538 * kerns. It's a bug in HarfBuzz.
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
539 */
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
540 void ass_shaper_set_kerning(ASS_Shaper *shaper, int kern)
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
541 {
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
542 #ifdef CONFIG_HARFBUZZ
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
543 shaper->features[KERN].value = !!kern;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
544 #endif
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
545 }
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
546
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
547 /**
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
548 * \brief Find shape runs according to the event's selected fonts
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
549 */
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
550 void ass_shaper_find_runs(ASS_Shaper *shaper, ASS_Renderer *render_priv,
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
551 GlyphInfo *glyphs, size_t len)
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
552 {
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
553 int i;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
554 int shape_run = 0;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
555
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
556 for (i = 0; i < len; i++) {
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
557 GlyphInfo *last = glyphs + i - 1;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
558 GlyphInfo *info = glyphs + i;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
559 // skip drawings
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
560 if (info->symbol == 0xfffc)
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
561 continue;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
562 // set size and get glyph index
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
563 ass_font_get_index(render_priv->fontconfig_priv, info->font,
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
564 info->symbol, &info->face_index, &info->glyph_index);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
565 // shape runs share the same font face and size
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
566 if (i > 0 && (last->font != info->font ||
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
567 last->font_size != info->font_size ||
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
568 last->face_index != info->face_index))
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
569 shape_run++;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
570 info->shape_run_id = shape_run;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
571 }
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
572
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
573 }
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
574
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
575 /**
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
576 * \brief Set base direction (paragraph direction) of the text.
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
577 * \param dir base direction
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
578 */
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
579 void ass_shaper_set_base_direction(ASS_Shaper *shaper, FriBidiParType dir)
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
580 {
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
581 shaper->base_direction = dir;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
582 }
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
583
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
584 /**
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
585 * \brief Set language hint. Some languages have specific character variants,
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
586 * like Serbian Cyrillic.
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
587 * \param lang ISO 639-1 two-letter language code
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
588 */
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
589 void ass_shaper_set_language(ASS_Shaper *shaper, const char *code)
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
590 {
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
591 #ifdef CONFIG_HARFBUZZ
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
592 shaper->language = hb_language_from_string(code, -1);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
593 #endif
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
594 }
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
595
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
596 /**
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
597 * Set shaping level. Essentially switches between FriBidi and HarfBuzz.
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
598 */
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
599 void ass_shaper_set_level(ASS_Shaper *shaper, ASS_ShapingLevel level)
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
600 {
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
601 shaper->shaping_level = level;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
602 }
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
603
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
604 /**
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
605 * \brief Shape an event's text. Calculates directional runs and shapes them.
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
606 * \param text_info event's text
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
607 */
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
608 void ass_shaper_shape(ASS_Shaper *shaper, TextInfo *text_info)
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
609 {
34342
575ad51cc996 Allow compiling libass without fribidi again.
reimar
parents: 34300
diff changeset
610 #ifndef CONFIG_FRIBIDI
575ad51cc996 Allow compiling libass without fribidi again.
reimar
parents: 34300
diff changeset
611 check_allocations(shaper, text_info->length);
575ad51cc996 Allow compiling libass without fribidi again.
reimar
parents: 34300
diff changeset
612 #else
34300
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
613 int i, last_break;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
614 FriBidiParType dir;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
615 GlyphInfo *glyphs = text_info->glyphs;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
616
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
617 check_allocations(shaper, text_info->length);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
618
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
619 // Get bidi character types and embedding levels
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
620 last_break = 0;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
621 for (i = 0; i < text_info->length; i++) {
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
622 shaper->event_text[i] = glyphs[i].symbol;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
623 // embedding levels should be calculated paragraph by paragraph
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
624 if (glyphs[i].symbol == '\n' || i == text_info->length - 1) {
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
625 dir = shaper->base_direction;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
626 fribidi_get_bidi_types(shaper->event_text + last_break,
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
627 i - last_break + 1, shaper->ctypes + last_break);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
628 fribidi_get_par_embedding_levels(shaper->ctypes + last_break,
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
629 i - last_break + 1, &dir, shaper->emblevels + last_break);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
630 last_break = i + 1;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
631 }
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
632 }
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
633
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
634 // add embedding levels to shape runs for final runs
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
635 for (i = 0; i < text_info->length; i++) {
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
636 glyphs[i].shape_run_id += shaper->emblevels[i];
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
637 }
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
638
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
639 #ifdef CONFIG_HARFBUZZ
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
640 switch (shaper->shaping_level) {
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
641 case ASS_SHAPING_SIMPLE:
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
642 shape_fribidi(shaper, glyphs, text_info->length);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
643 break;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
644 case ASS_SHAPING_COMPLEX:
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
645 shape_harfbuzz(shaper, glyphs, text_info->length);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
646 break;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
647 }
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
648 #else
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
649 shape_fribidi(shaper, glyphs, text_info->length);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
650 #endif
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
651
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
652
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
653 // clean up
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
654 for (i = 0; i < text_info->length; i++) {
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
655 // Skip direction override control characters
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
656 // NOTE: Behdad said HarfBuzz is supposed to remove these, but this hasn't
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
657 // been implemented yet
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
658 if (glyphs[i].symbol <= 0x202F && glyphs[i].symbol >= 0x202a) {
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
659 glyphs[i].symbol = 0;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
660 glyphs[i].skip++;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
661 }
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
662 }
34342
575ad51cc996 Allow compiling libass without fribidi again.
reimar
parents: 34300
diff changeset
663 #endif
34300
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
664 }
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
665
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 Create a new shaper instance and preallocate data structures
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
668 * \param prealloc preallocation size
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
669 */
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
670 ASS_Shaper *ass_shaper_new(size_t prealloc)
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
671 {
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
672 ASS_Shaper *shaper = calloc(sizeof(*shaper), 1);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
673
34342
575ad51cc996 Allow compiling libass without fribidi again.
reimar
parents: 34300
diff changeset
674 #ifdef CONFIG_FRIBIDI
34300
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
675 shaper->base_direction = FRIBIDI_PAR_ON;
34342
575ad51cc996 Allow compiling libass without fribidi again.
reimar
parents: 34300
diff changeset
676 #endif
34300
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
677 check_allocations(shaper, prealloc);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
678
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
679 #ifdef CONFIG_HARFBUZZ
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
680 init_features(shaper);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
681 shaper->metrics_cache = ass_glyph_metrics_cache_create();
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
682 #endif
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
683
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
684 return shaper;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
685 }
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
686
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
687
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
688 /**
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
689 * \brief clean up additional data temporarily needed for shaping and
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
690 * (e.g. additional glyphs allocated)
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
691 */
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
692 void ass_shaper_cleanup(ASS_Shaper *shaper, TextInfo *text_info)
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
693 {
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
694 int i;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
695
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
696 for (i = 0; i < text_info->length; i++) {
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
697 GlyphInfo *info = text_info->glyphs + i;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
698 info = info->next;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
699 while (info) {
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
700 GlyphInfo *next = info->next;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
701 free(info);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
702 info = next;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
703 }
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 /**
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
708 * \brief Calculate reorder map to render glyphs in visual order
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
709 */
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
710 FriBidiStrIndex *ass_shaper_reorder(ASS_Shaper *shaper, TextInfo *text_info)
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
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
714 // Initialize reorder map
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
715 for (i = 0; i < text_info->length; i++)
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
716 shaper->cmap[i] = i;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
717
34342
575ad51cc996 Allow compiling libass without fribidi again.
reimar
parents: 34300
diff changeset
718 #ifdef CONFIG_FRIBIDI
34300
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
719 // Create reorder map line-by-line
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
720 for (i = 0; i < text_info->n_lines; i++) {
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
721 LineInfo *line = text_info->lines + i;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
722 int level;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
723 FriBidiParType dir = FRIBIDI_PAR_ON;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
724
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
725 level = fribidi_reorder_line(0,
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
726 shaper->ctypes + line->offset, line->len, 0, dir,
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
727 shaper->emblevels + line->offset, NULL,
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
728 shaper->cmap + line->offset);
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
729 }
34342
575ad51cc996 Allow compiling libass without fribidi again.
reimar
parents: 34300
diff changeset
730 #endif
34300
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
731
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
732 return shaper->cmap;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
733 }
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
734
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
735 /**
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
736 * \brief Resolve a Windows font encoding number to a suitable
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
737 * base direction. 177 and 178 are Hebrew and Arabic respectively, and
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
738 * they map to RTL. 1 is autodetection and is mapped to just that.
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
739 * Everything else is mapped to LTR.
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
740 * \param enc Windows font encoding
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
741 */
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
742 FriBidiParType resolve_base_direction(int enc)
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
743 {
34342
575ad51cc996 Allow compiling libass without fribidi again.
reimar
parents: 34300
diff changeset
744 #ifdef CONFIG_FRIBIDI
34300
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
745 switch (enc) {
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
746 case 1:
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
747 return FRIBIDI_PAR_ON;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
748 case 177:
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
749 case 178:
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
750 return FRIBIDI_PAR_RTL;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
751 default:
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
752 return FRIBIDI_PAR_LTR;
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
753 }
34342
575ad51cc996 Allow compiling libass without fribidi again.
reimar
parents: 34300
diff changeset
754 #else
575ad51cc996 Allow compiling libass without fribidi again.
reimar
parents: 34300
diff changeset
755 return 0;
575ad51cc996 Allow compiling libass without fribidi again.
reimar
parents: 34300
diff changeset
756 #endif
34300
77976b68285b Commit added forgotten in previous commit.
reimar
parents:
diff changeset
757 }