Mercurial > mplayer.hg
annotate libass/ass_bitmap.c @ 33073:334e19411421
Improve handling of the comment character.
The comment character is safe now between (double) quotation marks.
This simplifies handling in the font description file and allows it
to be used in label texts.
author | ib |
---|---|
date | Wed, 30 Mar 2011 14:24:11 +0000 |
parents | ac6e48baa03d |
children | 88eebbbbd6a0 |
rev | line source |
---|---|
20008
fa122b7c71c6
Add copyright notice and vim/emacs comments to libass and vf_ass.c.
eugeni
parents:
19966
diff
changeset
|
1 /* |
26723 | 2 * Copyright (C) 2006 Evgeniy Stepanov <eugeni.stepanov@gmail.com> |
3 * | |
26738
588ce97b44f2
Speak of libass instead of MPlayer in the libass license headers.
diego
parents:
26723
diff
changeset
|
4 * This file is part of libass. |
26723 | 5 * |
26738
588ce97b44f2
Speak of libass instead of MPlayer in the libass license headers.
diego
parents:
26723
diff
changeset
|
6 * libass is free software; you can redistribute it and/or modify |
26723 | 7 * it under the terms of the GNU General Public License as published by |
8 * the Free Software Foundation; either version 2 of the License, or | |
9 * (at your option) any later version. | |
10 * | |
26738
588ce97b44f2
Speak of libass instead of MPlayer in the libass license headers.
diego
parents:
26723
diff
changeset
|
11 * libass is distributed in the hope that it will be useful, |
26723 | 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 * GNU General Public License for more details. | |
15 * | |
16 * You should have received a copy of the GNU General Public License along | |
26738
588ce97b44f2
Speak of libass instead of MPlayer in the libass license headers.
diego
parents:
26723
diff
changeset
|
17 * with libass; if not, write to the Free Software Foundation, Inc., |
26723 | 18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
19 */ | |
20008
fa122b7c71c6
Add copyright notice and vim/emacs comments to libass and vf_ass.c.
eugeni
parents:
19966
diff
changeset
|
20 |
19846
bcc792bfa431
Store bitmap glyphs in a separate struct, instead of FreeType's internal buffer.
eugeni
parents:
diff
changeset
|
21 #include <stdlib.h> |
bcc792bfa431
Store bitmap glyphs in a separate struct, instead of FreeType's internal buffer.
eugeni
parents:
diff
changeset
|
22 #include <string.h> |
bcc792bfa431
Store bitmap glyphs in a separate struct, instead of FreeType's internal buffer.
eugeni
parents:
diff
changeset
|
23 #include <math.h> |
bcc792bfa431
Store bitmap glyphs in a separate struct, instead of FreeType's internal buffer.
eugeni
parents:
diff
changeset
|
24 #include <assert.h> |
bcc792bfa431
Store bitmap glyphs in a separate struct, instead of FreeType's internal buffer.
eugeni
parents:
diff
changeset
|
25 #include <ft2build.h> |
bcc792bfa431
Store bitmap glyphs in a separate struct, instead of FreeType's internal buffer.
eugeni
parents:
diff
changeset
|
26 #include FT_GLYPH_H |
bcc792bfa431
Store bitmap glyphs in a separate struct, instead of FreeType's internal buffer.
eugeni
parents:
diff
changeset
|
27 |
30200 | 28 #include "ass_utils.h" |
19846
bcc792bfa431
Store bitmap glyphs in a separate struct, instead of FreeType's internal buffer.
eugeni
parents:
diff
changeset
|
29 #include "ass_bitmap.h" |
bcc792bfa431
Store bitmap glyphs in a separate struct, instead of FreeType's internal buffer.
eugeni
parents:
diff
changeset
|
30 |
30200 | 31 struct ass_synth_priv { |
32 int tmp_w, tmp_h; | |
33 unsigned short *tmp; | |
19848 | 34 |
30200 | 35 int g_r; |
36 int g_w; | |
19848 | 37 |
30200 | 38 unsigned *g; |
39 unsigned *gt2; | |
28436
12e936031c36
Allow \be with arguments other than 0 or 1. Implement \blur.
eugeni
parents:
27409
diff
changeset
|
40 |
30200 | 41 double radius; |
19848 | 42 }; |
43 | |
44 static const unsigned int maxcolor = 255; | |
45 static const unsigned base = 256; | |
46 | |
30200 | 47 static int generate_tables(ASS_SynthPriv *priv, double radius) |
19848 | 48 { |
30200 | 49 double A = log(1.0 / base) / (radius * radius * 2); |
50 int mx, i; | |
51 double volume_diff, volume_factor = 0; | |
52 unsigned volume; | |
19848 | 53 |
30200 | 54 if (priv->radius == radius) |
55 return 0; | |
56 else | |
57 priv->radius = radius; | |
28436
12e936031c36
Allow \be with arguments other than 0 or 1. Implement \blur.
eugeni
parents:
27409
diff
changeset
|
58 |
30200 | 59 priv->g_r = ceil(radius); |
60 priv->g_w = 2 * priv->g_r + 1; | |
19955
2792de2ca069
Cosmetics. Change indentation of block of code to make it consistent with
eugeni
parents:
19941
diff
changeset
|
61 |
30200 | 62 if (priv->g_r) { |
63 priv->g = realloc(priv->g, priv->g_w * sizeof(unsigned)); | |
64 priv->gt2 = realloc(priv->gt2, 256 * priv->g_w * sizeof(unsigned)); | |
65 if (priv->g == NULL || priv->gt2 == NULL) { | |
66 return -1; | |
67 } | |
68 } | |
19848 | 69 |
30200 | 70 if (priv->g_r) { |
71 // gaussian curve with volume = 256 | |
72 for (volume_diff = 10000000; volume_diff > 0.0000001; | |
73 volume_diff *= 0.5) { | |
74 volume_factor += volume_diff; | |
75 volume = 0; | |
76 for (i = 0; i < priv->g_w; ++i) { | |
77 priv->g[i] = | |
78 (unsigned) (exp(A * (i - priv->g_r) * (i - priv->g_r)) * | |
79 volume_factor + .5); | |
80 volume += priv->g[i]; | |
81 } | |
82 if (volume > 256) | |
83 volume_factor -= volume_diff; | |
84 } | |
85 volume = 0; | |
86 for (i = 0; i < priv->g_w; ++i) { | |
87 priv->g[i] = | |
88 (unsigned) (exp(A * (i - priv->g_r) * (i - priv->g_r)) * | |
89 volume_factor + .5); | |
90 volume += priv->g[i]; | |
91 } | |
19955
2792de2ca069
Cosmetics. Change indentation of block of code to make it consistent with
eugeni
parents:
19941
diff
changeset
|
92 |
30200 | 93 // gauss table: |
94 for (mx = 0; mx < priv->g_w; mx++) { | |
95 for (i = 0; i < 256; i++) { | |
96 priv->gt2[mx + i * priv->g_w] = i * priv->g[mx]; | |
97 } | |
98 } | |
99 } | |
19955
2792de2ca069
Cosmetics. Change indentation of block of code to make it consistent with
eugeni
parents:
19941
diff
changeset
|
100 |
30200 | 101 return 0; |
19848 | 102 } |
103 | |
30200 | 104 static void resize_tmp(ASS_SynthPriv *priv, int w, int h) |
19848 | 105 { |
30200 | 106 if (priv->tmp_w >= w && priv->tmp_h >= h) |
107 return; | |
108 if (priv->tmp_w == 0) | |
109 priv->tmp_w = 64; | |
110 if (priv->tmp_h == 0) | |
111 priv->tmp_h = 64; | |
112 while (priv->tmp_w < w) | |
113 priv->tmp_w *= 2; | |
114 while (priv->tmp_h < h) | |
115 priv->tmp_h *= 2; | |
31875 | 116 free(priv->tmp); |
30200 | 117 priv->tmp = malloc((priv->tmp_w + 1) * priv->tmp_h * sizeof(short)); |
19848 | 118 } |
119 | |
30200 | 120 ASS_SynthPriv *ass_synth_init(double radius) |
19848 | 121 { |
30200 | 122 ASS_SynthPriv *priv = calloc(1, sizeof(ASS_SynthPriv)); |
123 generate_tables(priv, radius); | |
124 return priv; | |
19848 | 125 } |
126 | |
30200 | 127 void ass_synth_done(ASS_SynthPriv *priv) |
19848 | 128 { |
31875 | 129 free(priv->tmp); |
130 free(priv->g); | |
131 free(priv->gt2); | |
30200 | 132 free(priv); |
19848 | 133 } |
134 | |
30200 | 135 static Bitmap *alloc_bitmap(int w, int h) |
19846
bcc792bfa431
Store bitmap glyphs in a separate struct, instead of FreeType's internal buffer.
eugeni
parents:
diff
changeset
|
136 { |
30200 | 137 Bitmap *bm; |
31853 | 138 bm = malloc(sizeof(Bitmap)); |
139 bm->buffer = calloc(w, h); | |
30200 | 140 bm->w = w; |
141 bm->h = h; | |
142 bm->left = bm->top = 0; | |
143 return bm; | |
19846
bcc792bfa431
Store bitmap glyphs in a separate struct, instead of FreeType's internal buffer.
eugeni
parents:
diff
changeset
|
144 } |
bcc792bfa431
Store bitmap glyphs in a separate struct, instead of FreeType's internal buffer.
eugeni
parents:
diff
changeset
|
145 |
30200 | 146 void ass_free_bitmap(Bitmap *bm) |
19846
bcc792bfa431
Store bitmap glyphs in a separate struct, instead of FreeType's internal buffer.
eugeni
parents:
diff
changeset
|
147 { |
31875 | 148 if (bm) |
149 free(bm->buffer); | |
150 free(bm); | |
19846
bcc792bfa431
Store bitmap glyphs in a separate struct, instead of FreeType's internal buffer.
eugeni
parents:
diff
changeset
|
151 } |
bcc792bfa431
Store bitmap glyphs in a separate struct, instead of FreeType's internal buffer.
eugeni
parents:
diff
changeset
|
152 |
30200 | 153 static Bitmap *copy_bitmap(const Bitmap *src) |
19965 | 154 { |
30200 | 155 Bitmap *dst = alloc_bitmap(src->w, src->h); |
156 dst->left = src->left; | |
157 dst->top = src->top; | |
158 memcpy(dst->buffer, src->buffer, src->w * src->h); | |
159 return dst; | |
19965 | 160 } |
161 | |
31853 | 162 int check_glyph_area(ASS_Library *library, FT_Glyph glyph) |
26035
501ea0b13962
Check glyph bounding box before rasterizing and complain if it is too large.
eugeni
parents:
22886
diff
changeset
|
163 { |
30200 | 164 FT_BBox bbox; |
165 long long dx, dy; | |
166 FT_Glyph_Get_CBox(glyph, FT_GLYPH_BBOX_TRUNCATE, &bbox); | |
167 dx = bbox.xMax - bbox.xMin; | |
168 dy = bbox.yMax - bbox.yMin; | |
169 if (dx * dy > 8000000) { | |
170 ass_msg(library, MSGL_WARN, "Glyph bounding box too large: %dx%dpx", | |
171 (int) dx, (int) dy); | |
172 return 1; | |
173 } else | |
174 return 0; | |
26035
501ea0b13962
Check glyph bounding box before rasterizing and complain if it is too large.
eugeni
parents:
22886
diff
changeset
|
175 } |
501ea0b13962
Check glyph bounding box before rasterizing and complain if it is too large.
eugeni
parents:
22886
diff
changeset
|
176 |
30200 | 177 static Bitmap *glyph_to_bitmap_internal(ASS_Library *library, |
178 FT_Glyph glyph, int bord) | |
19846
bcc792bfa431
Store bitmap glyphs in a separate struct, instead of FreeType's internal buffer.
eugeni
parents:
diff
changeset
|
179 { |
30200 | 180 FT_BitmapGlyph bg; |
181 FT_Bitmap *bit; | |
182 Bitmap *bm; | |
183 int w, h; | |
184 unsigned char *src; | |
185 unsigned char *dst; | |
186 int i; | |
187 int error; | |
19846
bcc792bfa431
Store bitmap glyphs in a separate struct, instead of FreeType's internal buffer.
eugeni
parents:
diff
changeset
|
188 |
30200 | 189 if (check_glyph_area(library, glyph)) |
190 return 0; | |
191 error = FT_Glyph_To_Bitmap(&glyph, FT_RENDER_MODE_NORMAL, 0, 0); | |
192 if (error) { | |
193 ass_msg(library, MSGL_WARN, "FT_Glyph_To_Bitmap error %d", | |
194 error); | |
195 return 0; | |
196 } | |
19846
bcc792bfa431
Store bitmap glyphs in a separate struct, instead of FreeType's internal buffer.
eugeni
parents:
diff
changeset
|
197 |
30200 | 198 bg = (FT_BitmapGlyph) glyph; |
199 bit = &(bg->bitmap); | |
200 if (bit->pixel_mode != FT_PIXEL_MODE_GRAY) { | |
201 ass_msg(library, MSGL_WARN, "Unsupported pixel mode: %d", | |
202 (int) (bit->pixel_mode)); | |
203 FT_Done_Glyph(glyph); | |
204 return 0; | |
205 } | |
19846
bcc792bfa431
Store bitmap glyphs in a separate struct, instead of FreeType's internal buffer.
eugeni
parents:
diff
changeset
|
206 |
30200 | 207 w = bit->width; |
208 h = bit->rows; | |
209 bm = alloc_bitmap(w + 2 * bord, h + 2 * bord); | |
210 bm->left = bg->left - bord; | |
211 bm->top = -bg->top - bord; | |
19846
bcc792bfa431
Store bitmap glyphs in a separate struct, instead of FreeType's internal buffer.
eugeni
parents:
diff
changeset
|
212 |
30200 | 213 src = bit->buffer; |
214 dst = bm->buffer + bord + bm->w * bord; | |
215 for (i = 0; i < h; ++i) { | |
216 memcpy(dst, src, w); | |
217 src += bit->pitch; | |
218 dst += bm->w; | |
219 } | |
19846
bcc792bfa431
Store bitmap glyphs in a separate struct, instead of FreeType's internal buffer.
eugeni
parents:
diff
changeset
|
220 |
30200 | 221 FT_Done_Glyph(glyph); |
222 return bm; | |
19846
bcc792bfa431
Store bitmap glyphs in a separate struct, instead of FreeType's internal buffer.
eugeni
parents:
diff
changeset
|
223 } |
bcc792bfa431
Store bitmap glyphs in a separate struct, instead of FreeType's internal buffer.
eugeni
parents:
diff
changeset
|
224 |
19966 | 225 /** |
30200 | 226 * \brief fix outline bitmap |
227 * | |
228 * The glyph bitmap is subtracted from outline bitmap. This way looks much | |
229 * better in some cases. | |
19966 | 230 */ |
30200 | 231 static void fix_outline(Bitmap *bm_g, Bitmap *bm_o) |
232 { | |
233 int x, y; | |
234 const int l = bm_o->left > bm_g->left ? bm_o->left : bm_g->left; | |
235 const int t = bm_o->top > bm_g->top ? bm_o->top : bm_g->top; | |
236 const int r = | |
237 bm_o->left + bm_o->w < | |
238 bm_g->left + bm_g->w ? bm_o->left + bm_o->w : bm_g->left + bm_g->w; | |
239 const int b = | |
240 bm_o->top + bm_o->h < | |
241 bm_g->top + bm_g->h ? bm_o->top + bm_o->h : bm_g->top + bm_g->h; | |
242 | |
243 unsigned char *g = | |
244 bm_g->buffer + (t - bm_g->top) * bm_g->w + (l - bm_g->left); | |
245 unsigned char *o = | |
246 bm_o->buffer + (t - bm_o->top) * bm_o->w + (l - bm_o->left); | |
247 | |
248 for (y = 0; y < b - t; ++y) { | |
249 for (x = 0; x < r - l; ++x) { | |
250 unsigned char c_g, c_o; | |
251 c_g = g[x]; | |
252 c_o = o[x]; | |
253 o[x] = (c_o > c_g) ? c_o - (c_g / 2) : 0; | |
254 } | |
255 g += bm_g->w; | |
256 o += bm_o->w; | |
257 } | |
258 } | |
259 | |
260 /** | |
261 * \brief Shift a bitmap by the fraction of a pixel in x and y direction | |
262 * expressed in 26.6 fixed point | |
263 */ | |
264 static void shift_bitmap(unsigned char *buf, int w, int h, int shift_x, | |
265 int shift_y) | |
19856 | 266 { |
30200 | 267 int x, y, b; |
268 | |
269 // Shift in x direction | |
270 if (shift_x > 0) { | |
271 for (y = 0; y < h; y++) { | |
272 for (x = w - 1; x > 0; x--) { | |
273 b = (buf[x + y * w - 1] * shift_x) >> 6; | |
274 buf[x + y * w - 1] -= b; | |
275 buf[x + y * w] += b; | |
276 } | |
277 } | |
278 } else if (shift_x < 0) { | |
279 shift_x = -shift_x; | |
280 for (y = 0; y < h; y++) { | |
281 for (x = 0; x < w - 1; x++) { | |
282 b = (buf[x + y * w + 1] * shift_x) >> 6; | |
283 buf[x + y * w + 1] -= b; | |
284 buf[x + y * w] += b; | |
285 } | |
286 } | |
287 } | |
19965 | 288 |
30200 | 289 // Shift in y direction |
290 if (shift_y > 0) { | |
291 for (x = 0; x < w; x++) { | |
292 for (y = h - 1; y > 0; y--) { | |
293 b = (buf[x + (y - 1) * w] * shift_y) >> 6; | |
294 buf[x + (y - 1) * w] -= b; | |
295 buf[x + y * w] += b; | |
296 } | |
297 } | |
298 } else if (shift_y < 0) { | |
299 shift_y = -shift_y; | |
300 for (x = 0; x < w; x++) { | |
301 for (y = 0; y < h - 1; y++) { | |
302 b = (buf[x + (y + 1) * w] * shift_y) >> 6; | |
303 buf[x + (y + 1) * w] -= b; | |
304 buf[x + y * w] += b; | |
305 } | |
306 } | |
307 } | |
308 } | |
309 | |
310 /* | |
311 * Gaussian blur. An fast pure C implementation from MPlayer. | |
312 */ | |
313 static void ass_gauss_blur(unsigned char *buffer, unsigned short *tmp2, | |
314 int width, int height, int stride, int *m2, | |
315 int r, int mwidth) | |
316 { | |
317 | |
318 int x, y; | |
319 | |
320 unsigned char *s = buffer; | |
321 unsigned short *t = tmp2 + 1; | |
322 for (y = 0; y < height; y++) { | |
323 memset(t - 1, 0, (width + 1) * sizeof(short)); | |
19965 | 324 |
30200 | 325 for (x = 0; x < r; x++) { |
326 const int src = s[x]; | |
327 if (src) { | |
328 register unsigned short *dstp = t + x - r; | |
329 int mx; | |
330 unsigned *m3 = (unsigned *) (m2 + src * mwidth); | |
331 for (mx = r - x; mx < mwidth; mx++) { | |
332 dstp[mx] += m3[mx]; | |
333 } | |
334 } | |
335 } | |
336 | |
337 for (; x < width - r; x++) { | |
338 const int src = s[x]; | |
339 if (src) { | |
340 register unsigned short *dstp = t + x - r; | |
341 int mx; | |
342 unsigned *m3 = (unsigned *) (m2 + src * mwidth); | |
343 for (mx = 0; mx < mwidth; mx++) { | |
344 dstp[mx] += m3[mx]; | |
345 } | |
346 } | |
347 } | |
348 | |
349 for (; x < width; x++) { | |
350 const int src = s[x]; | |
351 if (src) { | |
352 register unsigned short *dstp = t + x - r; | |
353 int mx; | |
354 const int x2 = r + width - x; | |
355 unsigned *m3 = (unsigned *) (m2 + src * mwidth); | |
356 for (mx = 0; mx < x2; mx++) { | |
357 dstp[mx] += m3[mx]; | |
358 } | |
359 } | |
360 } | |
361 | |
362 s += stride; | |
363 t += width + 1; | |
364 } | |
365 | |
366 t = tmp2; | |
367 for (x = 0; x < width; x++) { | |
368 for (y = 0; y < r; y++) { | |
369 unsigned short *srcp = t + y * (width + 1) + 1; | |
370 int src = *srcp; | |
371 if (src) { | |
372 register unsigned short *dstp = srcp - 1 + width + 1; | |
373 const int src2 = (src + 128) >> 8; | |
374 unsigned *m3 = (unsigned *) (m2 + src2 * mwidth); | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28802
diff
changeset
|
375 |
30200 | 376 int mx; |
377 *srcp = 128; | |
378 for (mx = r - 1; mx < mwidth; mx++) { | |
379 *dstp += m3[mx]; | |
380 dstp += width + 1; | |
381 } | |
382 } | |
383 } | |
384 for (; y < height - r; y++) { | |
385 unsigned short *srcp = t + y * (width + 1) + 1; | |
386 int src = *srcp; | |
387 if (src) { | |
388 register unsigned short *dstp = srcp - 1 - r * (width + 1); | |
389 const int src2 = (src + 128) >> 8; | |
390 unsigned *m3 = (unsigned *) (m2 + src2 * mwidth); | |
19965 | 391 |
30200 | 392 int mx; |
393 *srcp = 128; | |
394 for (mx = 0; mx < mwidth; mx++) { | |
395 *dstp += m3[mx]; | |
396 dstp += width + 1; | |
397 } | |
398 } | |
399 } | |
400 for (; y < height; y++) { | |
401 unsigned short *srcp = t + y * (width + 1) + 1; | |
402 int src = *srcp; | |
403 if (src) { | |
404 const int y2 = r + height - y; | |
405 register unsigned short *dstp = srcp - 1 - r * (width + 1); | |
406 const int src2 = (src + 128) >> 8; | |
407 unsigned *m3 = (unsigned *) (m2 + src2 * mwidth); | |
408 | |
409 int mx; | |
410 *srcp = 128; | |
411 for (mx = 0; mx < y2; mx++) { | |
412 *dstp += m3[mx]; | |
413 dstp += width + 1; | |
414 } | |
415 } | |
416 } | |
417 t++; | |
418 } | |
419 | |
420 t = tmp2; | |
421 s = buffer; | |
422 for (y = 0; y < height; y++) { | |
423 for (x = 0; x < width; x++) { | |
424 s[x] = t[x] >> 8; | |
425 } | |
426 s += stride; | |
427 t += width + 1; | |
428 } | |
19856 | 429 } |
430 | |
28799
65b83aee82fb
Use blur with kernel [[1,2,1], [2,4,2], [1,2,1]] for \be.
greg
parents:
28781
diff
changeset
|
431 /** |
65b83aee82fb
Use blur with kernel [[1,2,1], [2,4,2], [1,2,1]] for \be.
greg
parents:
28781
diff
changeset
|
432 * \brief Blur with [[1,2,1]. [2,4,2], [1,2,1]] kernel |
65b83aee82fb
Use blur with kernel [[1,2,1], [2,4,2], [1,2,1]] for \be.
greg
parents:
28781
diff
changeset
|
433 * This blur is the same as the one employed by vsfilter. |
65b83aee82fb
Use blur with kernel [[1,2,1], [2,4,2], [1,2,1]] for \be.
greg
parents:
28781
diff
changeset
|
434 */ |
30200 | 435 static void be_blur(unsigned char *buf, int w, int h) |
436 { | |
437 unsigned int x, y; | |
438 unsigned int old_sum, new_sum; | |
28799
65b83aee82fb
Use blur with kernel [[1,2,1], [2,4,2], [1,2,1]] for \be.
greg
parents:
28781
diff
changeset
|
439 |
30200 | 440 for (y = 0; y < h; y++) { |
441 old_sum = 2 * buf[y * w]; | |
442 for (x = 0; x < w - 1; x++) { | |
443 new_sum = buf[y * w + x] + buf[y * w + x + 1]; | |
444 buf[y * w + x] = (old_sum + new_sum) >> 2; | |
445 old_sum = new_sum; | |
446 } | |
447 } | |
28799
65b83aee82fb
Use blur with kernel [[1,2,1], [2,4,2], [1,2,1]] for \be.
greg
parents:
28781
diff
changeset
|
448 |
30200 | 449 for (x = 0; x < w; x++) { |
450 old_sum = 2 * buf[x]; | |
451 for (y = 0; y < h - 1; y++) { | |
452 new_sum = buf[y * w + x] + buf[(y + 1) * w + x]; | |
453 buf[y * w + x] = (old_sum + new_sum) >> 2; | |
454 old_sum = new_sum; | |
455 } | |
456 } | |
28799
65b83aee82fb
Use blur with kernel [[1,2,1], [2,4,2], [1,2,1]] for \be.
greg
parents:
28781
diff
changeset
|
457 } |
65b83aee82fb
Use blur with kernel [[1,2,1], [2,4,2], [1,2,1]] for \be.
greg
parents:
28781
diff
changeset
|
458 |
30200 | 459 int glyph_to_bitmap(ASS_Library *library, ASS_SynthPriv *priv_blur, |
460 FT_Glyph glyph, FT_Glyph outline_glyph, | |
461 Bitmap **bm_g, Bitmap **bm_o, Bitmap **bm_s, | |
462 int be, double blur_radius, FT_Vector shadow_offset, | |
463 int border_style) | |
19846
bcc792bfa431
Store bitmap glyphs in a separate struct, instead of FreeType's internal buffer.
eugeni
parents:
diff
changeset
|
464 { |
30200 | 465 blur_radius *= 2; |
466 int bbord = be > 0 ? sqrt(2 * be) : 0; | |
467 int gbord = blur_radius > 0.0 ? blur_radius + 1 : 0; | |
468 int bord = FFMAX(bbord, gbord); | |
469 if (bord == 0 && (shadow_offset.x || shadow_offset.y)) | |
470 bord = 1; | |
19848 | 471 |
30200 | 472 assert(bm_g && bm_o && bm_s); |
19965 | 473 |
30200 | 474 *bm_g = *bm_o = *bm_s = 0; |
19846
bcc792bfa431
Store bitmap glyphs in a separate struct, instead of FreeType's internal buffer.
eugeni
parents:
diff
changeset
|
475 |
30200 | 476 if (glyph) |
477 *bm_g = glyph_to_bitmap_internal(library, glyph, bord); | |
478 if (!*bm_g) | |
479 return 1; | |
480 | |
481 if (outline_glyph) { | |
482 *bm_o = glyph_to_bitmap_internal(library, outline_glyph, bord); | |
483 if (!*bm_o) { | |
484 return 1; | |
485 } | |
486 } | |
19965 | 487 |
30200 | 488 // Apply box blur (multiple passes, if requested) |
489 while (be--) { | |
490 if (*bm_o) | |
491 be_blur((*bm_o)->buffer, (*bm_o)->w, (*bm_o)->h); | |
492 else | |
493 be_blur((*bm_g)->buffer, (*bm_g)->w, (*bm_g)->h); | |
494 } | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28802
diff
changeset
|
495 |
30200 | 496 // Apply gaussian blur |
497 if (blur_radius > 0.0) { | |
498 if (*bm_o) | |
499 resize_tmp(priv_blur, (*bm_o)->w, (*bm_o)->h); | |
500 else | |
501 resize_tmp(priv_blur, (*bm_g)->w, (*bm_g)->h); | |
502 generate_tables(priv_blur, blur_radius); | |
503 if (*bm_o) | |
504 ass_gauss_blur((*bm_o)->buffer, priv_blur->tmp, | |
505 (*bm_o)->w, (*bm_o)->h, (*bm_o)->w, | |
506 (int *) priv_blur->gt2, priv_blur->g_r, | |
507 priv_blur->g_w); | |
508 else | |
509 ass_gauss_blur((*bm_g)->buffer, priv_blur->tmp, | |
510 (*bm_g)->w, (*bm_g)->h, (*bm_g)->w, | |
511 (int *) priv_blur->gt2, priv_blur->g_r, | |
512 priv_blur->g_w); | |
513 } | |
19856 | 514 |
30200 | 515 // Create shadow and fix outline as needed |
516 if (*bm_o && border_style != 3) { | |
517 *bm_s = copy_bitmap(*bm_o); | |
518 fix_outline(*bm_g, *bm_o); | |
519 } else if (*bm_o) { | |
520 *bm_s = copy_bitmap(*bm_o); | |
521 } else | |
522 *bm_s = copy_bitmap(*bm_g); | |
523 | |
524 assert(bm_s); | |
525 | |
526 shift_bitmap((*bm_s)->buffer, (*bm_s)->w,(*bm_s)->h, | |
527 shadow_offset.x, shadow_offset.y); | |
528 | |
529 return 0; | |
19846
bcc792bfa431
Store bitmap glyphs in a separate struct, instead of FreeType's internal buffer.
eugeni
parents:
diff
changeset
|
530 } |