Mercurial > mplayer.hg
annotate libass/ass_bitmap.c @ 34808:275c92f137ac
build: Check if SCTP is available
Test for SCTP and remove it from the list of libavformat
protocols in case the test did not succeed or the feature
was explicitly disabled.
Unconditionally trying to build it, as it was done before
if you had a new enough libavformat version that contains
that feature, is obviously not a good idea.
This patch is closely based on a patch from Johan Andersson.
author | al |
---|---|
date | Sun, 13 May 2012 19:55:27 +0000 |
parents | 6e7f60f6f9d4 |
children | c3aaaf17c721 |
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> |
34295 | 3 * Copyright (C) 2011 Grigori Goronzy <greg@chown.ath.cx> |
26723 | 4 * |
26738
588ce97b44f2
Speak of libass instead of MPlayer in the libass license headers.
diego
parents:
26723
diff
changeset
|
5 * This file is part of libass. |
26723 | 6 * |
34011 | 7 * Permission to use, copy, modify, and distribute this software for any |
8 * purpose with or without fee is hereby granted, provided that the above | |
9 * copyright notice and this permission notice appear in all copies. | |
26723 | 10 * |
34011 | 11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | |
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | |
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
26723 | 18 */ |
20008
fa122b7c71c6
Add copyright notice and vim/emacs comments to libass and vf_ass.c.
eugeni
parents:
19966
diff
changeset
|
19 |
19846
bcc792bfa431
Store bitmap glyphs in a separate struct, instead of FreeType's internal buffer.
eugeni
parents:
diff
changeset
|
20 #include <stdlib.h> |
bcc792bfa431
Store bitmap glyphs in a separate struct, instead of FreeType's internal buffer.
eugeni
parents:
diff
changeset
|
21 #include <string.h> |
bcc792bfa431
Store bitmap glyphs in a separate struct, instead of FreeType's internal buffer.
eugeni
parents:
diff
changeset
|
22 #include <math.h> |
bcc792bfa431
Store bitmap glyphs in a separate struct, instead of FreeType's internal buffer.
eugeni
parents:
diff
changeset
|
23 #include <assert.h> |
bcc792bfa431
Store bitmap glyphs in a separate struct, instead of FreeType's internal buffer.
eugeni
parents:
diff
changeset
|
24 #include <ft2build.h> |
bcc792bfa431
Store bitmap glyphs in a separate struct, instead of FreeType's internal buffer.
eugeni
parents:
diff
changeset
|
25 #include FT_GLYPH_H |
34295 | 26 #include FT_OUTLINE_H |
19846
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; |
34295 | 138 unsigned s = w; // XXX: alignment |
31853 | 139 bm = malloc(sizeof(Bitmap)); |
34295 | 140 bm->buffer = calloc(s, h); |
30200 | 141 bm->w = w; |
142 bm->h = h; | |
34295 | 143 bm->stride = s; |
30200 | 144 bm->left = bm->top = 0; |
145 return bm; | |
19846
bcc792bfa431
Store bitmap glyphs in a separate struct, instead of FreeType's internal buffer.
eugeni
parents:
diff
changeset
|
146 } |
bcc792bfa431
Store bitmap glyphs in a separate struct, instead of FreeType's internal buffer.
eugeni
parents:
diff
changeset
|
147 |
30200 | 148 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
|
149 { |
31875 | 150 if (bm) |
151 free(bm->buffer); | |
152 free(bm); | |
19846
bcc792bfa431
Store bitmap glyphs in a separate struct, instead of FreeType's internal buffer.
eugeni
parents:
diff
changeset
|
153 } |
bcc792bfa431
Store bitmap glyphs in a separate struct, instead of FreeType's internal buffer.
eugeni
parents:
diff
changeset
|
154 |
30200 | 155 static Bitmap *copy_bitmap(const Bitmap *src) |
19965 | 156 { |
30200 | 157 Bitmap *dst = alloc_bitmap(src->w, src->h); |
158 dst->left = src->left; | |
159 dst->top = src->top; | |
34295 | 160 memcpy(dst->buffer, src->buffer, src->stride * src->h); |
30200 | 161 return dst; |
19965 | 162 } |
163 | |
34295 | 164 Bitmap *outline_to_bitmap(ASS_Library *library, FT_Library ftlib, |
165 FT_Outline *outline, int bord) | |
26035
501ea0b13962
Check glyph bounding box before rasterizing and complain if it is too large.
eugeni
parents:
22886
diff
changeset
|
166 { |
30200 | 167 Bitmap *bm; |
168 int w, h; | |
169 int error; | |
34295 | 170 FT_BBox bbox; |
171 FT_Bitmap bitmap; | |
19846
bcc792bfa431
Store bitmap glyphs in a separate struct, instead of FreeType's internal buffer.
eugeni
parents:
diff
changeset
|
172 |
34295 | 173 FT_Outline_Get_CBox(outline, &bbox); |
174 // move glyph to origin (0, 0) | |
175 bbox.xMin &= ~63; | |
176 bbox.yMin &= ~63; | |
177 FT_Outline_Translate(outline, -bbox.xMin, -bbox.yMin); | |
178 // bitmap size | |
179 bbox.xMax = (bbox.xMax + 63) & ~63; | |
180 bbox.yMax = (bbox.yMax + 63) & ~63; | |
181 w = (bbox.xMax - bbox.xMin) >> 6; | |
182 h = (bbox.yMax - bbox.yMin) >> 6; | |
183 // pen offset | |
184 bbox.xMin >>= 6; | |
185 bbox.yMax >>= 6; | |
186 | |
187 if (w * h > 8000000) { | |
188 ass_msg(library, MSGL_WARN, "Glyph bounding box too large: %dx%dpx", | |
189 w, h); | |
190 return NULL; | |
30200 | 191 } |
19846
bcc792bfa431
Store bitmap glyphs in a separate struct, instead of FreeType's internal buffer.
eugeni
parents:
diff
changeset
|
192 |
34295 | 193 // allocate and set up bitmap |
194 bm = alloc_bitmap(w + 2 * bord, h + 2 * bord); | |
195 bm->left = bbox.xMin - bord; | |
196 bm->top = -bbox.yMax - bord; | |
197 bitmap.width = w; | |
198 bitmap.rows = h; | |
199 bitmap.pitch = bm->stride; | |
200 bitmap.buffer = bm->buffer + bord + bm->stride * bord; | |
201 bitmap.num_grays = 256; | |
202 bitmap.pixel_mode = FT_PIXEL_MODE_GRAY; | |
203 | |
204 // render into target bitmap | |
205 if ((error = FT_Outline_Get_Bitmap(ftlib, outline, &bitmap))) { | |
206 ass_msg(library, MSGL_WARN, "Failed to rasterize glyph: %d\n", error); | |
207 ass_free_bitmap(bm); | |
208 return NULL; | |
30200 | 209 } |
19846
bcc792bfa431
Store bitmap glyphs in a separate struct, instead of FreeType's internal buffer.
eugeni
parents:
diff
changeset
|
210 |
30200 | 211 return bm; |
19846
bcc792bfa431
Store bitmap glyphs in a separate struct, instead of FreeType's internal buffer.
eugeni
parents:
diff
changeset
|
212 } |
bcc792bfa431
Store bitmap glyphs in a separate struct, instead of FreeType's internal buffer.
eugeni
parents:
diff
changeset
|
213 |
19966 | 214 /** |
30200 | 215 * \brief fix outline bitmap |
216 * | |
217 * The glyph bitmap is subtracted from outline bitmap. This way looks much | |
218 * better in some cases. | |
19966 | 219 */ |
30200 | 220 static void fix_outline(Bitmap *bm_g, Bitmap *bm_o) |
221 { | |
222 int x, y; | |
223 const int l = bm_o->left > bm_g->left ? bm_o->left : bm_g->left; | |
224 const int t = bm_o->top > bm_g->top ? bm_o->top : bm_g->top; | |
225 const int r = | |
34295 | 226 bm_o->left + bm_o->stride < |
227 bm_g->left + bm_g->stride ? bm_o->left + bm_o->stride : bm_g->left + bm_g->stride; | |
30200 | 228 const int b = |
229 bm_o->top + bm_o->h < | |
230 bm_g->top + bm_g->h ? bm_o->top + bm_o->h : bm_g->top + bm_g->h; | |
231 | |
232 unsigned char *g = | |
34295 | 233 bm_g->buffer + (t - bm_g->top) * bm_g->stride + (l - bm_g->left); |
30200 | 234 unsigned char *o = |
34295 | 235 bm_o->buffer + (t - bm_o->top) * bm_o->stride + (l - bm_o->left); |
30200 | 236 |
237 for (y = 0; y < b - t; ++y) { | |
238 for (x = 0; x < r - l; ++x) { | |
239 unsigned char c_g, c_o; | |
240 c_g = g[x]; | |
241 c_o = o[x]; | |
242 o[x] = (c_o > c_g) ? c_o - (c_g / 2) : 0; | |
243 } | |
34295 | 244 g += bm_g->stride; |
245 o += bm_o->stride; | |
30200 | 246 } |
247 } | |
248 | |
249 /** | |
250 * \brief Shift a bitmap by the fraction of a pixel in x and y direction | |
251 * expressed in 26.6 fixed point | |
252 */ | |
34295 | 253 static void shift_bitmap(Bitmap *bm, int shift_x, int shift_y) |
19856 | 254 { |
30200 | 255 int x, y, b; |
34295 | 256 int w = bm->w; |
257 int h = bm->h; | |
258 int s = bm->stride; | |
259 unsigned char *buf = bm->buffer; | |
30200 | 260 |
261 // Shift in x direction | |
262 if (shift_x > 0) { | |
263 for (y = 0; y < h; y++) { | |
264 for (x = w - 1; x > 0; x--) { | |
34295 | 265 b = (buf[x + y * s - 1] * shift_x) >> 6; |
266 buf[x + y * s - 1] -= b; | |
267 buf[x + y * s] += b; | |
30200 | 268 } |
269 } | |
270 } else if (shift_x < 0) { | |
271 shift_x = -shift_x; | |
272 for (y = 0; y < h; y++) { | |
273 for (x = 0; x < w - 1; x++) { | |
34295 | 274 b = (buf[x + y * s + 1] * shift_x) >> 6; |
275 buf[x + y * s + 1] -= b; | |
276 buf[x + y * s] += b; | |
30200 | 277 } |
278 } | |
279 } | |
19965 | 280 |
30200 | 281 // Shift in y direction |
282 if (shift_y > 0) { | |
283 for (x = 0; x < w; x++) { | |
284 for (y = h - 1; y > 0; y--) { | |
34295 | 285 b = (buf[x + (y - 1) * s] * shift_y) >> 6; |
286 buf[x + (y - 1) * s] -= b; | |
287 buf[x + y * s] += b; | |
30200 | 288 } |
289 } | |
290 } else if (shift_y < 0) { | |
291 shift_y = -shift_y; | |
292 for (x = 0; x < w; x++) { | |
293 for (y = 0; y < h - 1; y++) { | |
34295 | 294 b = (buf[x + (y + 1) * s] * shift_y) >> 6; |
295 buf[x + (y + 1) * s] -= b; | |
296 buf[x + y * s] += b; | |
30200 | 297 } |
298 } | |
299 } | |
300 } | |
301 | |
302 /* | |
303 * Gaussian blur. An fast pure C implementation from MPlayer. | |
304 */ | |
305 static void ass_gauss_blur(unsigned char *buffer, unsigned short *tmp2, | |
306 int width, int height, int stride, int *m2, | |
307 int r, int mwidth) | |
308 { | |
309 | |
310 int x, y; | |
311 | |
312 unsigned char *s = buffer; | |
313 unsigned short *t = tmp2 + 1; | |
314 for (y = 0; y < height; y++) { | |
315 memset(t - 1, 0, (width + 1) * sizeof(short)); | |
19965 | 316 |
30200 | 317 for (x = 0; x < r; x++) { |
318 const int src = s[x]; | |
319 if (src) { | |
320 register unsigned short *dstp = t + x - r; | |
321 int mx; | |
322 unsigned *m3 = (unsigned *) (m2 + src * mwidth); | |
323 for (mx = r - x; mx < mwidth; mx++) { | |
324 dstp[mx] += m3[mx]; | |
325 } | |
326 } | |
327 } | |
328 | |
329 for (; x < width - r; x++) { | |
330 const int src = s[x]; | |
331 if (src) { | |
332 register unsigned short *dstp = t + x - r; | |
333 int mx; | |
334 unsigned *m3 = (unsigned *) (m2 + src * mwidth); | |
335 for (mx = 0; mx < mwidth; mx++) { | |
336 dstp[mx] += m3[mx]; | |
337 } | |
338 } | |
339 } | |
340 | |
341 for (; x < width; x++) { | |
342 const int src = s[x]; | |
343 if (src) { | |
344 register unsigned short *dstp = t + x - r; | |
345 int mx; | |
346 const int x2 = r + width - x; | |
347 unsigned *m3 = (unsigned *) (m2 + src * mwidth); | |
348 for (mx = 0; mx < x2; mx++) { | |
349 dstp[mx] += m3[mx]; | |
350 } | |
351 } | |
352 } | |
353 | |
354 s += stride; | |
355 t += width + 1; | |
356 } | |
357 | |
358 t = tmp2; | |
359 for (x = 0; x < width; x++) { | |
360 for (y = 0; y < r; y++) { | |
361 unsigned short *srcp = t + y * (width + 1) + 1; | |
362 int src = *srcp; | |
363 if (src) { | |
364 register unsigned short *dstp = srcp - 1 + width + 1; | |
365 const int src2 = (src + 128) >> 8; | |
366 unsigned *m3 = (unsigned *) (m2 + src2 * mwidth); | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28802
diff
changeset
|
367 |
30200 | 368 int mx; |
369 *srcp = 128; | |
370 for (mx = r - 1; mx < mwidth; mx++) { | |
371 *dstp += m3[mx]; | |
372 dstp += width + 1; | |
373 } | |
374 } | |
375 } | |
376 for (; y < height - r; y++) { | |
377 unsigned short *srcp = t + y * (width + 1) + 1; | |
378 int src = *srcp; | |
379 if (src) { | |
380 register unsigned short *dstp = srcp - 1 - r * (width + 1); | |
381 const int src2 = (src + 128) >> 8; | |
382 unsigned *m3 = (unsigned *) (m2 + src2 * mwidth); | |
19965 | 383 |
30200 | 384 int mx; |
385 *srcp = 128; | |
386 for (mx = 0; mx < mwidth; mx++) { | |
387 *dstp += m3[mx]; | |
388 dstp += width + 1; | |
389 } | |
390 } | |
391 } | |
392 for (; y < height; y++) { | |
393 unsigned short *srcp = t + y * (width + 1) + 1; | |
394 int src = *srcp; | |
395 if (src) { | |
396 const int y2 = r + height - y; | |
397 register unsigned short *dstp = srcp - 1 - r * (width + 1); | |
398 const int src2 = (src + 128) >> 8; | |
399 unsigned *m3 = (unsigned *) (m2 + src2 * mwidth); | |
400 | |
401 int mx; | |
402 *srcp = 128; | |
403 for (mx = 0; mx < y2; mx++) { | |
404 *dstp += m3[mx]; | |
405 dstp += width + 1; | |
406 } | |
407 } | |
408 } | |
409 t++; | |
410 } | |
411 | |
412 t = tmp2; | |
413 s = buffer; | |
414 for (y = 0; y < height; y++) { | |
415 for (x = 0; x < width; x++) { | |
416 s[x] = t[x] >> 8; | |
417 } | |
418 s += stride; | |
419 t += width + 1; | |
420 } | |
19856 | 421 } |
422 | |
28799
65b83aee82fb
Use blur with kernel [[1,2,1], [2,4,2], [1,2,1]] for \be.
greg
parents:
28781
diff
changeset
|
423 /** |
65b83aee82fb
Use blur with kernel [[1,2,1], [2,4,2], [1,2,1]] for \be.
greg
parents:
28781
diff
changeset
|
424 * \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
|
425 * 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
|
426 */ |
34295 | 427 static void be_blur(Bitmap *bm) |
30200 | 428 { |
34295 | 429 int w = bm->w; |
430 int h = bm->h; | |
431 int s = bm->stride; | |
432 unsigned char *buf = bm->buffer; | |
30200 | 433 unsigned int x, y; |
434 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
|
435 |
30200 | 436 for (y = 0; y < h; y++) { |
34295 | 437 old_sum = 2 * buf[y * s]; |
30200 | 438 for (x = 0; x < w - 1; x++) { |
34295 | 439 new_sum = buf[y * s + x] + buf[y * s + x + 1]; |
440 buf[y * s + x] = (old_sum + new_sum) >> 2; | |
30200 | 441 old_sum = new_sum; |
442 } | |
443 } | |
28799
65b83aee82fb
Use blur with kernel [[1,2,1], [2,4,2], [1,2,1]] for \be.
greg
parents:
28781
diff
changeset
|
444 |
30200 | 445 for (x = 0; x < w; x++) { |
446 old_sum = 2 * buf[x]; | |
447 for (y = 0; y < h - 1; y++) { | |
34295 | 448 new_sum = buf[y * s + x] + buf[(y + 1) * s + x]; |
449 buf[y * s + x] = (old_sum + new_sum) >> 2; | |
30200 | 450 old_sum = new_sum; |
451 } | |
452 } | |
28799
65b83aee82fb
Use blur with kernel [[1,2,1], [2,4,2], [1,2,1]] for \be.
greg
parents:
28781
diff
changeset
|
453 } |
65b83aee82fb
Use blur with kernel [[1,2,1], [2,4,2], [1,2,1]] for \be.
greg
parents:
28781
diff
changeset
|
454 |
34295 | 455 int outline_to_bitmap3(ASS_Library *library, ASS_SynthPriv *priv_blur, |
456 FT_Library ftlib, FT_Outline *outline, FT_Outline *border, | |
457 Bitmap **bm_g, Bitmap **bm_o, Bitmap **bm_s, | |
458 int be, double blur_radius, FT_Vector shadow_offset, | |
459 int border_style) | |
19846
bcc792bfa431
Store bitmap glyphs in a separate struct, instead of FreeType's internal buffer.
eugeni
parents:
diff
changeset
|
460 { |
30200 | 461 blur_radius *= 2; |
462 int bbord = be > 0 ? sqrt(2 * be) : 0; | |
463 int gbord = blur_radius > 0.0 ? blur_radius + 1 : 0; | |
464 int bord = FFMAX(bbord, gbord); | |
465 if (bord == 0 && (shadow_offset.x || shadow_offset.y)) | |
466 bord = 1; | |
19848 | 467 |
30200 | 468 assert(bm_g && bm_o && bm_s); |
19965 | 469 |
30200 | 470 *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
|
471 |
34295 | 472 if (outline) |
473 *bm_g = outline_to_bitmap(library, ftlib, outline, bord); | |
30200 | 474 if (!*bm_g) |
475 return 1; | |
476 | |
34295 | 477 if (border) { |
478 *bm_o = outline_to_bitmap(library, ftlib, border, bord); | |
30200 | 479 if (!*bm_o) { |
480 return 1; | |
481 } | |
482 } | |
19965 | 483 |
30200 | 484 // Apply box blur (multiple passes, if requested) |
485 while (be--) { | |
486 if (*bm_o) | |
34295 | 487 be_blur(*bm_o); |
30200 | 488 else |
34295 | 489 be_blur(*bm_g); |
30200 | 490 } |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28802
diff
changeset
|
491 |
30200 | 492 // Apply gaussian blur |
493 if (blur_radius > 0.0) { | |
494 if (*bm_o) | |
495 resize_tmp(priv_blur, (*bm_o)->w, (*bm_o)->h); | |
496 else | |
497 resize_tmp(priv_blur, (*bm_g)->w, (*bm_g)->h); | |
498 generate_tables(priv_blur, blur_radius); | |
499 if (*bm_o) | |
500 ass_gauss_blur((*bm_o)->buffer, priv_blur->tmp, | |
34295 | 501 (*bm_o)->w, (*bm_o)->h, (*bm_o)->stride, |
30200 | 502 (int *) priv_blur->gt2, priv_blur->g_r, |
503 priv_blur->g_w); | |
504 else | |
505 ass_gauss_blur((*bm_g)->buffer, priv_blur->tmp, | |
34295 | 506 (*bm_g)->w, (*bm_g)->h, (*bm_g)->stride, |
30200 | 507 (int *) priv_blur->gt2, priv_blur->g_r, |
508 priv_blur->g_w); | |
509 } | |
19856 | 510 |
30200 | 511 // Create shadow and fix outline as needed |
512 if (*bm_o && border_style != 3) { | |
513 *bm_s = copy_bitmap(*bm_o); | |
514 fix_outline(*bm_g, *bm_o); | |
515 } else if (*bm_o) { | |
516 *bm_s = copy_bitmap(*bm_o); | |
517 } else | |
518 *bm_s = copy_bitmap(*bm_g); | |
519 | |
520 assert(bm_s); | |
521 | |
34295 | 522 shift_bitmap(*bm_s, shadow_offset.x, shadow_offset.y); |
30200 | 523 |
524 return 0; | |
19846
bcc792bfa431
Store bitmap glyphs in a separate struct, instead of FreeType's internal buffer.
eugeni
parents:
diff
changeset
|
525 } |