]> granicus.if.org Git - libass/commitdiff
Store bitmap glyphs in a separate struct, instead of FreeType's internal buffer.
authoreugeni <eugeni@b3059339-0415-0410-9bf9-f77b7e298cf2>
Sat, 16 Sep 2006 13:08:17 +0000 (13:08 +0000)
committereugeni <eugeni@b3059339-0415-0410-9bf9-f77b7e298cf2>
Sat, 16 Sep 2006 13:08:17 +0000 (13:08 +0000)
This is required for various bitmap modifications (like blur, outline and shadow).

git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@19852 b3059339-0415-0410-9bf9-f77b7e298cf2

libass/Makefile
libass/ass_bitmap.c [new file with mode: 0644]
libass/ass_bitmap.h [new file with mode: 0644]
libass/ass_cache.c
libass/ass_cache.h
libass/ass_render.c

index 3385a4c067afa1b1eb75d7ce3fa8405147fb9e00..070c8529bedc2ecefe4c62963c1b754dd2ae492d 100644 (file)
@@ -5,7 +5,7 @@ LIBNAME=libass.a
 
 LIBS=$(LIBNAME)
 
-SRCS=ass.c ass_cache.c ass_fontconfig.c ass_render.c ass_utils.c ass_mp.c
+SRCS=ass.c ass_cache.c ass_fontconfig.c ass_render.c ass_utils.c ass_mp.c ass_bitmap.c
 
 OBJS=$(SRCS:.c=.o)
 
diff --git a/libass/ass_bitmap.c b/libass/ass_bitmap.c
new file mode 100644 (file)
index 0000000..9d98ec0
--- /dev/null
@@ -0,0 +1,91 @@
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <assert.h>
+#include <ft2build.h>
+#include FT_GLYPH_H
+
+#include "mp_msg.h"
+#include "ass_bitmap.h"
+
+static bitmap_t* alloc_bitmap(int w, int h)
+{
+       bitmap_t* bm;
+       bm = calloc(1, sizeof(bitmap_t));
+       bm->buffer = malloc(w*h);
+       bm->w = w;
+       bm->h = h;
+       bm->left = bm->top = 0;
+       return bm;
+}
+
+void ass_free_bitmap(bitmap_t* bm)
+{
+       if (bm) {
+               if (bm->buffer) free(bm->buffer);
+               free(bm);
+       }
+}
+
+static bitmap_t* glyph_to_bitmap_internal(FT_Glyph glyph, int bord)
+{
+       FT_BitmapGlyph bg;
+       FT_Bitmap* bit;
+       bitmap_t* bm;
+       int w, h;
+       unsigned char* src;
+       unsigned char* dst;
+       int i;
+       int error;
+
+       error = FT_Glyph_To_Bitmap(&glyph, FT_RENDER_MODE_NORMAL, 0, 0);
+       if (error) {
+               mp_msg(MSGT_GLOBAL, MSGL_WARN, "FT_Glyph_To_Bitmap error %d \n", error);
+               return 0;
+       }
+
+       bg = (FT_BitmapGlyph)glyph;
+       bit = &(bg->bitmap);
+       if (bit->pixel_mode != FT_PIXEL_MODE_GRAY) {
+               mp_msg(MSGT_GLOBAL, MSGL_WARN, "Unsupported pixel mode: %d\n", (int)(bit->pixel_mode));
+               FT_Done_Glyph(glyph);
+               return 0;
+       }
+
+       w = bit->width;
+       h = bit->rows;
+       bm = alloc_bitmap(w + 2*bord, h + 2*bord);
+       memset(bm->buffer, 0, bm->w * bm->h);
+       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;
+       }
+
+       return bm;
+}
+
+int glyph_to_bitmap(FT_Glyph glyph, FT_Glyph outline_glyph, bitmap_t** bm_g, bitmap_t** bm_o)
+{
+       assert(bm_g);
+
+       if (glyph)
+               *bm_g = glyph_to_bitmap_internal(glyph, 0);
+       if (!*bm_g)
+               return 1;
+       if (outline_glyph && bm_o) {
+               *bm_o = glyph_to_bitmap_internal(outline_glyph, 0);
+               if (!*bm_o) {
+                       ass_free_bitmap(*bm_g);
+                       return 1;
+               }
+       }
+
+       return 0;
+}
+
diff --git a/libass/ass_bitmap.h b/libass/ass_bitmap.h
new file mode 100644 (file)
index 0000000..edf4790
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef __ASS_BITMAP_H__
+#define __ASS_BITMAP_H__
+
+typedef struct bitmap_s {
+       int left, top;
+       int w, h; // width, height
+       unsigned char* buffer; // w x h buffer
+} bitmap_t;
+
+int glyph_to_bitmap(FT_Glyph glyph, FT_Glyph outline_glyph, bitmap_t** bm_g, bitmap_t** bm_o);
+void ass_free_bitmap(bitmap_t* bm);
+
+#endif
+
index 64f915becf7354e833a05fa6ae8f307a09c19ff7..2dce591d93da08ff3296e4768e9c343a2c1e910d 100644 (file)
@@ -2,11 +2,13 @@
 
 #include <ft2build.h>
 #include FT_FREETYPE_H
+#include FT_GLYPH_H
 
 #include <assert.h>
 
 #include "mp_msg.h"
 #include "ass_fontconfig.h"
+#include "ass_bitmap.h"
 #include "ass_cache.h"
 
 
@@ -197,8 +199,8 @@ void ass_glyph_cache_done(void)
                glyph_hash_item_t* item = glyph_hash_root[i];
                while (item) {
                        glyph_hash_item_t* next = item->next;
-                       if (item->val.glyph) FT_Done_Glyph(item->val.glyph);
-                       if (item->val.outline_glyph) FT_Done_Glyph(item->val.outline_glyph);
+                       if (item->val.bm) ass_free_bitmap(item->val.bm);
+                       if (item->val.bm_o) ass_free_bitmap(item->val.bm_o);
                        free(item);
                        item = next;
                }
index 68f57296bf1886fdba904b460969cdad21a60f6f..f24886e8730c5f925d161d12301d077df93575e8 100644 (file)
@@ -35,8 +35,8 @@ typedef struct glyph_hash_key_s {
 } glyph_hash_key_t;
 
 typedef struct glyph_hash_val_s {
-       FT_Glyph glyph; // the actual glyphs
-       FT_Glyph outline_glyph;
+       bitmap_t* bm; // the actual glyph bitmaps
+       bitmap_t* bm_o;
        FT_BBox bbox_scaled; // bbox after scaling, but before rotation
        FT_Vector advance; // 26.6, advance distance to the next glyph in line
 } glyph_hash_val_t;
index 6aee3cd8d4bb56882a9886a1ea4a1d5ec45d621e..e0096ca21983c93a560aa3995a5caf0ce77861ad 100644 (file)
@@ -12,6 +12,7 @@
 #include "mp_msg.h"
 
 #include "ass.h"
+#include "ass_bitmap.h"
 #include "ass_cache.h"
 #include "ass_utils.h"
 #include "ass_fontconfig.h"
@@ -51,11 +52,12 @@ typedef struct glyph_info_s {
        unsigned symbol;
        FT_Glyph glyph;
        FT_Glyph outline_glyph;
+       bitmap_t* bm;
+       bitmap_t* bm_o;
        FT_BBox bbox;
        FT_Vector pos;
        char linebreak; // the first (leading) glyph of some line ?
        uint32_t c[4]; // colors
-       char bitmap; // bool
        FT_Vector advance; // 26.6
        effect_t effect_type;
        int effect_timing; // time duration of current karaoke word
@@ -223,6 +225,7 @@ ass_instance_t* ass_init(void)
                fontconfig_done(fc_priv);
                goto ass_init_exit;
        }
+
        priv->library = ft;
        priv->fontconfig_priv = fc_priv;
        // images_root and related stuff is zero-filled in calloc
@@ -280,7 +283,7 @@ static ass_image_t* my_draw_bitmap(unsigned char* bitmap, int bitmap_w, int bitm
  * \return pointer to the new list tail
  * Performs clipping. Uses my_draw_bitmap for actual bitmap convertion.
  */
-static ass_image_t** render_glyph(FT_BitmapGlyph bit, int dst_x, int dst_y, uint32_t color, uint32_t color2, int brk, ass_image_t** tail)
+static ass_image_t** render_glyph(bitmap_t* bm, int dst_x, int dst_y, uint32_t color, uint32_t color2, int brk, ass_image_t** tail)
 {
        // brk is relative to dst_x
        // color = color left of brk
@@ -288,19 +291,12 @@ static ass_image_t** render_glyph(FT_BitmapGlyph bit, int dst_x, int dst_y, uint
        int b_x0, b_y0, b_x1, b_y1; // visible part of the bitmap
        int clip_x0, clip_y0, clip_x1, clip_y1;
        int tmp;
-       FT_Bitmap* bitmap;
        ass_image_t* img;
 
-       bitmap = &(bit->bitmap);
-       dst_x += bit->left;
-       dst_y -= bit->top;
-       brk -= bit->left;
+       dst_x += bm->left;
+       dst_y += bm->top;
+       brk -= bm->left;
        
-       if (bitmap->pixel_mode != FT_PIXEL_MODE_GRAY) {
-               mp_msg(MSGT_GLOBAL, MSGL_WARN, "Unsupported pixel mode: %d\n", (int)(bitmap->pixel_mode));
-               return tail;
-       }
-
        // clipping
        clip_x0 = render_context.clip_x0;
        clip_y0 = render_context.clip_y0;
@@ -308,8 +304,8 @@ static ass_image_t** render_glyph(FT_BitmapGlyph bit, int dst_x, int dst_y, uint
        clip_y1 = render_context.clip_y1;
        b_x0 = 0;
        b_y0 = 0;
-       b_x1 = bitmap->width;
-       b_y1 = bitmap->rows;
+       b_x1 = bm->w;
+       b_y1 = bm->h;
        
        tmp = dst_x - clip_x0;
        if (tmp < 0) {
@@ -321,15 +317,15 @@ static ass_image_t** render_glyph(FT_BitmapGlyph bit, int dst_x, int dst_y, uint
                mp_msg(MSGT_GLOBAL, MSGL_DBG2, "clip top\n");
                b_y0 = - tmp;
        }
-       tmp = clip_x1 - dst_x - bitmap->width;
+       tmp = clip_x1 - dst_x - bm->w;
        if (tmp < 0) {
                mp_msg(MSGT_GLOBAL, MSGL_DBG2, "clip right\n");
-               b_x1 = bitmap->width + tmp;
+               b_x1 = bm->w + tmp;
        }
-       tmp = clip_y1 - dst_y - bitmap->rows;
+       tmp = clip_y1 - dst_y - bm->h;
        if (tmp < 0) {
                mp_msg(MSGT_GLOBAL, MSGL_DBG2, "clip bottom\n");
-               b_y1 = bitmap->rows + tmp;
+               b_y1 = bm->h + tmp;
        }
        
        if ((b_y0 >= b_y1) || (b_x0 >= b_x1))
@@ -337,16 +333,16 @@ static ass_image_t** render_glyph(FT_BitmapGlyph bit, int dst_x, int dst_y, uint
 
        if (brk > b_x0) { // draw left part
                if (brk > b_x1) brk = b_x1;
-               img = my_draw_bitmap(bitmap->buffer + bitmap->pitch * b_y0 + b_x0, 
-                       brk - b_x0, b_y1 - b_y0, bitmap->pitch,
+               img = my_draw_bitmap(bm->buffer + bm->w * b_y0 + b_x0, 
+                       brk - b_x0, b_y1 - b_y0, bm->w,
                        dst_x + b_x0, dst_y + b_y0, color);
                *tail = img;
                tail = &img->next;
        }
        if (brk < b_x1) { // draw right part
                if (brk < b_x0) brk = b_x0;
-               img = my_draw_bitmap(bitmap->buffer + bitmap->pitch * b_y0 + brk, 
-                       b_x1 - brk, b_y1 - b_y0, bitmap->pitch,
+               img = my_draw_bitmap(bm->buffer + bm->w * b_y0 + brk, 
+                       b_x1 - brk, b_y1 - b_y0, bm->w,
                        dst_x + brk, dst_y + b_y0, color2);
                *tail = img;
                tail = &img->next;
@@ -361,37 +357,31 @@ static ass_image_t** render_glyph(FT_BitmapGlyph bit, int dst_x, int dst_y, uint
 static ass_image_t* render_text(text_info_t* text_info, int dst_x, int dst_y)
 {
        int pen_x, pen_y;
-       int error, error2;
-       int i;
-       FT_Glyph image;
-       FT_BitmapGlyph bit;
+       int i, error;
+       bitmap_t* bm;
        glyph_hash_val_t hash_val;
        ass_image_t* head;
        ass_image_t** tail = &head;
 
        for (i = 0; i < text_info->length; ++i) {
-               if (text_info->glyphs[i].bitmap != 1) {
+               if (text_info->glyphs[i].glyph) {
                        if ((text_info->glyphs[i].symbol == '\n') || (text_info->glyphs[i].symbol == 0))
                                continue;
-                       error = FT_Glyph_To_Bitmap( &(text_info->glyphs[i].outline_glyph), FT_RENDER_MODE_NORMAL, 0, 1);
-                       error2 = FT_Glyph_To_Bitmap( &(text_info->glyphs[i].glyph), FT_RENDER_MODE_NORMAL, 0, 1);
-
-                       if (error || error2) {
-                               FT_Done_Glyph(text_info->glyphs[i].outline_glyph);
-                               FT_Done_Glyph(text_info->glyphs[i].glyph);
-                               mp_msg(MSGT_GLOBAL, MSGL_WARN, "FT_Glyph_To_Bitmap error %d %d, symbol %d, index %d\n", 
-                                               error, error2, text_info->glyphs[i].symbol, text_info->glyphs[i].hash_key.index);
-                               text_info->glyphs[i].symbol = 0; // do not render
-                               continue;
-                       }
+                       error = glyph_to_bitmap(text_info->glyphs[i].glyph, text_info->glyphs[i].outline_glyph,
+                                       &text_info->glyphs[i].bm, &text_info->glyphs[i].bm_o);
+                       if (error)
+                               text_info->glyphs[i].symbol = 0;
+                       FT_Done_Glyph(text_info->glyphs[i].glyph);
+                       FT_Done_Glyph(text_info->glyphs[i].outline_glyph);
+
                        // cache
-                       text_info->glyphs[i].hash_key.bitmap = 1; // other hash_key fields were set in get_glyph()
                        hash_val.bbox_scaled = text_info->glyphs[i].bbox;
-                       hash_val.outline_glyph = text_info->glyphs[i].outline_glyph;
-                       hash_val.glyph = text_info->glyphs[i].glyph;
+                       hash_val.bm_o = text_info->glyphs[i].bm_o;
+                       hash_val.bm = text_info->glyphs[i].bm;
                        hash_val.advance.x = text_info->glyphs[i].advance.x;
                        hash_val.advance.y = text_info->glyphs[i].advance.y;
                        cache_add_glyph(&(text_info->glyphs[i].hash_key), &hash_val);
+
                }
        }
 
@@ -402,13 +392,12 @@ static ass_image_t* render_text(text_info_t* text_info, int dst_x, int dst_y)
 
                pen_x = dst_x + info->pos.x;
                pen_y = dst_y + info->pos.y;
-               image = info->outline_glyph;
-               bit = (FT_BitmapGlyph)image;
+               bm = info->bm_o;
                
                if ((info->effect_type == EF_KARAOKE_KO) && (info->effect_timing <= info->bbox.xMax)) {
                        // do nothing
                } else
-                       tail = render_glyph(bit, pen_x, pen_y, info->c[2], 0, 1000000, tail);
+                       tail = render_glyph(bm, pen_x, pen_y, info->c[2], 0, 1000000, tail);
        }
        for (i = 0; i < text_info->length; ++i) {
                glyph_info_t* info = text_info->glyphs + i;
@@ -417,18 +406,17 @@ static ass_image_t* render_text(text_info_t* text_info, int dst_x, int dst_y)
 
                pen_x = dst_x + info->pos.x;
                pen_y = dst_y + info->pos.y;
-               image = info->glyph;
-               bit = (FT_BitmapGlyph)image;
+               bm = info->bm;
 
                if ((info->effect_type == EF_KARAOKE) || (info->effect_type == EF_KARAOKE_KO)) {
                        if (info->effect_timing > info->bbox.xMax)
-                               tail = render_glyph(bit, pen_x, pen_y, info->c[0], 0, 1000000, tail);
+                               tail = render_glyph(bm, pen_x, pen_y, info->c[0], 0, 1000000, tail);
                        else
-                               tail = render_glyph(bit, pen_x, pen_y, info->c[1], 0, 1000000, tail);
+                               tail = render_glyph(bm, pen_x, pen_y, info->c[1], 0, 1000000, tail);
                } else if (info->effect_type == EF_KARAOKE_KF) {
-                       tail = render_glyph(bit, pen_x, pen_y, info->c[0], info->c[1], info->effect_timing, tail);
+                       tail = render_glyph(bm, pen_x, pen_y, info->c[0], info->c[1], info->effect_timing, tail);
                } else
-                       tail = render_glyph(bit, pen_x, pen_y, info->c[0], 0, 1000000, tail);
+                       tail = render_glyph(bm, pen_x, pen_y, info->c[0], 0, 1000000, tail);
        }
 
        *tail = 0;
@@ -1206,20 +1194,16 @@ static int get_glyph(int index, int symbol, glyph_info_t* info, FT_Vector* advan
        key->bold = render_context.bold;
        key->italic = render_context.italic;
 
-       key->bitmap = 1; // looking for bitmap glyph
-
-       
        val = cache_find_glyph(key);
 //     val = 0;
        
        if (val) {
-               // bitmap glyph found, no need for FT_Glyph_Copy
-               info->glyph = val->glyph;
-               info->outline_glyph = val->outline_glyph;
+               info->glyph = info->outline_glyph = 0;
+               info->bm = val->bm;
+               info->bm_o = val->bm_o;
                info->bbox = val->bbox_scaled;
                info->advance.x = val->advance.x;
                info->advance.y = val->advance.y;
-               info->bitmap = 1; // bitmap glyph
 
                return 0;
        }
@@ -1258,7 +1242,7 @@ static int get_glyph(int index, int symbol, glyph_info_t* info, FT_Vector* advan
                FT_Glyph_Copy(info->glyph, &info->outline_glyph);
        }
 
-       info->bitmap = 0; // outline glyph
+       info->bm = info->bm_o = 0;
 
        return 0;
 }
@@ -1599,7 +1583,7 @@ static int ass_render_event(ass_event_t* event, event_images_t* event_images)
                pen.y += text_info.glyphs[text_info.length].advance.y;
                
                // if it's an outline glyph, we still need to fill the bbox
-               if (text_info.glyphs[text_info.length].bitmap != 1) {
+               if (text_info.glyphs[text_info.length].glyph) {
                        FT_Glyph_Get_CBox( text_info.glyphs[text_info.length].glyph, FT_GLYPH_BBOX_PIXELS, &(text_info.glyphs[text_info.length].bbox) );
                }
 
@@ -1822,7 +1806,7 @@ static int ass_render_event(ass_event_t* event, event_images_t* event_images)
                        info->pos.y -= start.y >> 6;
 
 //                     mp_msg(MSGT_GLOBAL, MSGL_DBG2, "shift: %d, %d\n", start.x / 64, start.y / 64);
-                       if (info->bitmap != 1) {
+                       if (info->glyph) {
                                FT_Glyph_Transform( info->glyph, &matrix_rotate, 0 );
                                FT_Glyph_Transform( info->outline_glyph, &matrix_rotate, 0 );
                        }