comparison libass/ass_render.c @ 23021:a81c390d4a22

Move outline glyph generation to a separate function, using outline glyph cache.
author eugeni
date Fri, 20 Apr 2007 23:09:48 +0000
parents f3b04984b0da
children 199a3c6f54e8
comparison
equal deleted inserted replaced
23020:1cce8d37847e 23021:a81c390d4a22
251 priv->ftlibrary = ft; 251 priv->ftlibrary = ft;
252 // images_root and related stuff is zero-filled in calloc 252 // images_root and related stuff is zero-filled in calloc
253 253
254 ass_font_cache_init(); 254 ass_font_cache_init();
255 ass_bitmap_cache_init(); 255 ass_bitmap_cache_init();
256 ass_glyph_cache_init();
256 257
257 text_info.glyphs = calloc(MAX_GLYPHS, sizeof(glyph_info_t)); 258 text_info.glyphs = calloc(MAX_GLYPHS, sizeof(glyph_info_t));
258 259
259 ass_init_exit: 260 ass_init_exit:
260 if (priv) mp_msg(MSGT_ASS, MSGL_INFO, MSGTR_LIBASS_Init); 261 if (priv) mp_msg(MSGT_ASS, MSGL_INFO, MSGTR_LIBASS_Init);
265 266
266 void ass_renderer_done(ass_renderer_t* priv) 267 void ass_renderer_done(ass_renderer_t* priv)
267 { 268 {
268 ass_font_cache_done(); 269 ass_font_cache_done();
269 ass_bitmap_cache_done(); 270 ass_bitmap_cache_done();
271 ass_glyph_cache_done();
270 if (render_context.stroker) { 272 if (render_context.stroker) {
271 FT_Stroker_Done(render_context.stroker); 273 FT_Stroker_Done(render_context.stroker);
272 render_context.stroker = 0; 274 render_context.stroker = 0;
273 } 275 }
274 if (priv && priv->ftlibrary) FT_Done_FreeType(priv->ftlibrary); 276 if (priv && priv->ftlibrary) FT_Done_FreeType(priv->ftlibrary);
1220 1222
1221 static void free_render_context(void) 1223 static void free_render_context(void)
1222 { 1224 {
1223 } 1225 }
1224 1226
1227 static int get_outline_glyph(int symbol, glyph_info_t* info, FT_Vector* advance)
1228 {
1229 int error;
1230 glyph_hash_val_t* val;
1231 glyph_hash_key_t key;
1232 key.font = render_context.font;
1233 key.size = render_context.font_size;
1234 key.ch = symbol;
1235 key.scale_x = (render_context.scale_x * 0xFFFF);
1236 key.scale_y = (render_context.scale_y * 0xFFFF);
1237 key.advance = *advance;
1238 key.bold = render_context.bold;
1239 key.italic = render_context.italic;
1240
1241 info->glyph = info->outline_glyph = 0;
1242
1243 val = cache_find_glyph(&key);
1244 if (val) {
1245 FT_Glyph_Copy(val->glyph, &info->glyph);
1246 info->bbox = val->bbox_scaled;
1247 info->advance.x = val->advance.x;
1248 info->advance.y = val->advance.y;
1249 } else {
1250 glyph_hash_val_t v;
1251 info->glyph = ass_font_get_glyph(frame_context.ass_priv->fontconfig_priv, render_context.font, symbol);
1252 if (!info->glyph)
1253 return 0;
1254 info->advance.x = d16_to_d6(info->glyph->advance.x);
1255 info->advance.y = d16_to_d6(info->glyph->advance.y);
1256 FT_Glyph_Get_CBox( info->glyph, FT_GLYPH_BBOX_PIXELS, &info->bbox);
1257
1258 FT_Glyph_Copy(info->glyph, &v.glyph);
1259 v.advance = info->advance;
1260 v.bbox_scaled = info->bbox;
1261 cache_add_glyph(&key, &v);
1262 }
1263
1264 if (render_context.stroker) {
1265 info->outline_glyph = info->glyph;
1266 error = FT_Glyph_StrokeBorder( &(info->outline_glyph), render_context.stroker, 0 , 0 ); // don't destroy original
1267 if (error) {
1268 mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_FT_Glyph_Stroke_Error, error);
1269 }
1270 }
1271 return 0;
1272 }
1273
1225 /** 1274 /**
1226 * \brief Get normal and outline glyphs from cache (if possible) or font face 1275 * \brief Get normal and outline glyphs from cache (if possible) or font face
1227 * \param index face glyph index 1276 * \param index face glyph index
1228 * \param symbol ucs4 char 1277 * \param symbol ucs4 char
1229 * \param info out: struct filled with extracted data 1278 * \param info out: struct filled with extracted data
1230 * \param advance advance vector of the extracted glyph 1279 * \param advance advance vector of the extracted glyph
1231 * \return 0 on success 1280 * \return 0 on success
1232 */ 1281 */
1233 static void get_glyph(int symbol, glyph_info_t* info, FT_Vector* advance) 1282 static int get_bitmap_glyph(int symbol, glyph_info_t* info, FT_Vector* advance)
1234 { 1283 {
1235 int error; 1284 int error;
1236 bitmap_hash_val_t* val; 1285 bitmap_hash_val_t* val;
1237 bitmap_hash_key_t* key = &(info->hash_key); 1286 bitmap_hash_key_t* key = &(info->hash_key);
1238 1287
1252 1301
1253 val = cache_find_bitmap(key); 1302 val = cache_find_bitmap(key);
1254 /* val = 0; */ 1303 /* val = 0; */
1255 1304
1256 if (val) { 1305 if (val) {
1257 info->glyph = info->outline_glyph = 0;
1258 info->bm = val->bm; 1306 info->bm = val->bm;
1259 info->bm_o = val->bm_o; 1307 info->bm_o = val->bm_o;
1260 info->bm_s = val->bm_s; 1308 info->bm_s = val->bm_s;
1261 info->bbox = val->bbox_scaled; 1309 info->bbox = val->bbox_scaled;
1262 info->advance.x = val->advance.x; 1310 info->advance.x = val->advance.x;
1263 info->advance.y = val->advance.y; 1311 info->advance.y = val->advance.y;
1264 1312 } else
1265 return; 1313 info->bm = info->bm_o = info->bm_s = 0;
1266 } 1314
1267 1315 return 0;
1268 // not found, get a new outline glyph from face
1269 // mp_msg(MSGT_ASS, MSGL_INFO, "miss, index = %d, symbol = %c, adv = (%d, %d)\n", index, symbol, advance->x, advance->y);
1270
1271 info->outline_glyph = 0;
1272 info->bm = info->bm_o = info->bm_s = 0;
1273 info->bbox.xMin = info->bbox.xMax = info->bbox.yMin = info->bbox.yMax = 0;
1274 info->advance.x = info->advance.y = 0;
1275
1276 info->glyph = ass_font_get_glyph(frame_context.ass_priv->fontconfig_priv, render_context.font, symbol);
1277 if (!info->glyph)
1278 return;
1279
1280 info->advance.x = d16_to_d6(info->glyph->advance.x);
1281 info->advance.y = d16_to_d6(info->glyph->advance.y);
1282
1283 if (render_context.stroker) {
1284 info->outline_glyph = info->glyph;
1285 error = FT_Glyph_StrokeBorder( &(info->outline_glyph), render_context.stroker, 0 , 0 ); // don't destroy original
1286 if (error) {
1287 mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_FT_Glyph_Stroke_Error, error);
1288 }
1289 }
1290 } 1316 }
1291 1317
1292 /** 1318 /**
1293 * This function goes through text_info and calculates text parameters. 1319 * This function goes through text_info and calculates text parameters.
1294 * The following text_info fields are filled: 1320 * The following text_info fields are filled:
1738 matrix.yx = (FT_Fixed)( 0 * 0x10000L ); 1764 matrix.yx = (FT_Fixed)( 0 * 0x10000L );
1739 matrix.yy = (FT_Fixed)( render_context.scale_y * 0x10000L ); 1765 matrix.yy = (FT_Fixed)( render_context.scale_y * 0x10000L );
1740 1766
1741 ass_font_set_transform(render_context.font, &matrix, &shift ); 1767 ass_font_set_transform(render_context.font, &matrix, &shift );
1742 } 1768 }
1743 1769
1744 get_glyph(code, text_info.glyphs + text_info.length, &shift); 1770 error = get_outline_glyph(code, text_info.glyphs + text_info.length, &shift);
1771 error |= get_bitmap_glyph(code, text_info.glyphs + text_info.length, &shift);
1772
1773 if (error) {
1774 continue;
1775 }
1745 1776
1746 text_info.glyphs[text_info.length].pos.x = pen.x >> 6; 1777 text_info.glyphs[text_info.length].pos.x = pen.x >> 6;
1747 text_info.glyphs[text_info.length].pos.y = pen.y >> 6; 1778 text_info.glyphs[text_info.length].pos.y = pen.y >> 6;
1748 1779
1749 pen.x += text_info.glyphs[text_info.length].advance.x; 1780 pen.x += text_info.glyphs[text_info.length].advance.x;
1750 pen.x += double_to_d6(render_context.hspacing); 1781 pen.x += double_to_d6(render_context.hspacing);
1751 pen.y += text_info.glyphs[text_info.length].advance.y; 1782 pen.y += text_info.glyphs[text_info.length].advance.y;
1752 1783
1753 // if it's an outline glyph, we still need to fill the bbox
1754 if (text_info.glyphs[text_info.length].glyph) {
1755 FT_Glyph_Get_CBox( text_info.glyphs[text_info.length].glyph, FT_GLYPH_BBOX_PIXELS, &(text_info.glyphs[text_info.length].bbox) );
1756 }
1757
1758 previous = code; 1784 previous = code;
1759 1785
1760 text_info.glyphs[text_info.length].symbol = code; 1786 text_info.glyphs[text_info.length].symbol = code;
1761 text_info.glyphs[text_info.length].linebreak = 0; 1787 text_info.glyphs[text_info.length].linebreak = 0;
1762 for (i = 0; i < 4; ++i) { 1788 for (i = 0; i < 4; ++i) {