summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGrigori Goronzy <greg@blackbox>2011-06-13 22:39:26 +0200
committerGrigori Goronzy <greg@blackbox>2011-06-13 22:39:26 +0200
commit2c1c093253daf69b2244f654893456ff7f80fa27 (patch)
tree9be8e099f4eea7b6db3a3db30b9f4c3710bf7494
parentdc4e13bdab03b352825d8dbd46966fa932832d28 (diff)
downloadlibass-2c1c093253daf69b2244f654893456ff7f80fa27.tar.bz2
libass-2c1c093253daf69b2244f654893456ff7f80fa27.tar.xz
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.
-rw-r--r--libass/ass_bitmap.c75
1 files 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 <eugeni.stepanov@gmail.com>
+ * Copyright (C) 2011 Grigori Goronzy <greg@chown.ath.cx>
*
* This file is part of libass.
*
@@ -22,6 +23,7 @@
#include <assert.h>
#include <ft2build.h>
#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;
}