From 2c1c093253daf69b2244f654893456ff7f80fa27 Mon Sep 17 00:00:00 2001 From: Grigori Goronzy Date: Mon, 13 Jun 2011 22:39:26 +0200 Subject: Render outlines, not glyphs libass can render both regular glyphs (extracted from a font) and drawings, which are inserted into an existing glyph so far. This is a rather crude hack. However, it is necessary, as the renderer only works with FT_Glyphs. The obvious solution is to work on the underlying outlines directly instead. This is the first step to make this possible: change the basic rasterizer to use the outline-specific rasterization functions. There are more advantages: - It's more efficient. The bitmap can be directly rendered into the bordered target bitmap. - This should make it easier to adapt the renderer to run-based rendering later on (the pixels are ORed into the target) The higher-level rendering code still needs to be adjusted. --- libass/ass_bitmap.c | 75 +++++++++++++++++++++++++++++------------------------ 1 file changed, 41 insertions(+), 34 deletions(-) diff --git a/libass/ass_bitmap.c b/libass/ass_bitmap.c index 6ecdbc6..2d3f0d5 100644 --- a/libass/ass_bitmap.c +++ b/libass/ass_bitmap.c @@ -1,5 +1,6 @@ /* * Copyright (C) 2006 Evgeniy Stepanov + * Copyright (C) 2011 Grigori Goronzy * * This file is part of libass. * @@ -22,6 +23,7 @@ #include #include #include FT_GLYPH_H +#include FT_OUTLINE_H #include "ass_utils.h" #include "ass_bitmap.h" @@ -175,48 +177,53 @@ int check_glyph_area(ASS_Library *library, FT_Glyph glyph) static Bitmap *glyph_to_bitmap_internal(ASS_Library *library, FT_Glyph glyph, int bord) { - FT_BitmapGlyph bg; - FT_Bitmap *bit; Bitmap *bm; int w, h; - unsigned char *src; - unsigned char *dst; - int i; int error; - - if (check_glyph_area(library, glyph)) - return 0; - error = FT_Glyph_To_Bitmap(&glyph, FT_RENDER_MODE_NORMAL, 0, 0); - if (error) { - ass_msg(library, MSGL_WARN, "FT_Glyph_To_Bitmap error %d", - error); - return 0; - } - - bg = (FT_BitmapGlyph) glyph; - bit = &(bg->bitmap); - if (bit->pixel_mode != FT_PIXEL_MODE_GRAY) { - ass_msg(library, MSGL_WARN, "Unsupported pixel mode: %d", - (int) (bit->pixel_mode)); - FT_Done_Glyph(glyph); - return 0; + FT_BBox bbox; + FT_Bitmap bitmap; + FT_Outline *outline = &((FT_OutlineGlyph)glyph)->outline; + + FT_Outline_Get_CBox(outline, &bbox); + // move glyph to origin (0, 0) + bbox.xMin &= ~63; + bbox.yMin &= ~63; + FT_Outline_Translate(outline, -bbox.xMin, -bbox.yMin); + // bitmap size + bbox.xMax = (bbox.xMax + 63) & ~63; + bbox.yMax = (bbox.yMax + 63) & ~63; + w = (bbox.xMax - bbox.xMin) >> 6; + h = (bbox.yMax - bbox.yMin) >> 6; + // pen offset + bbox.xMin >>= 6; + bbox.yMax >>= 6; + + if (w * h > 8000000) { + ass_msg(library, MSGL_WARN, "Glyph bounding box too large: %dx%dpx", + w, h); + return NULL; } - w = bit->width; - h = bit->rows; + // allocate and set up bitmap bm = alloc_bitmap(w + 2 * bord, h + 2 * bord); - bm->left = bg->left - bord; - bm->top = -bg->top - bord; - - src = bit->buffer; - dst = bm->buffer + bord + bm->w * bord; - for (i = 0; i < h; ++i) { - memcpy(dst, src, w); - src += bit->pitch; - dst += bm->w; + bm->left = bbox.xMin - bord; + bm->top = -bbox.yMax - bord; + bitmap.width = w; + bitmap.rows = h; + bitmap.pitch = bm->w; + bitmap.buffer = bm->buffer + bord + bm->w * bord; + bitmap.num_grays = 256; + bitmap.pixel_mode = FT_PIXEL_MODE_GRAY; + + // render into target bitmap + // XXX: this uses the FT_Library from the glyph. Instead a reference to the + // FT_Library should be passed to this function (plus outline) + if ((error = FT_Outline_Get_Bitmap(glyph->library, outline, &bitmap))) { + ass_msg(library, MSGL_WARN, "Failed to rasterize glyph: %d\n", error); + ass_free_bitmap(bm); + return NULL; } - FT_Done_Glyph(glyph); return bm; } -- cgit v1.2.3