]> granicus.if.org Git - libass/commitdiff
Use bare outlines for drawings
authorGrigori Goronzy <greg@blackbox>
Mon, 20 Jun 2011 21:12:22 +0000 (23:12 +0200)
committerGrigori Goronzy <greg@blackbox>
Mon, 20 Jun 2011 21:20:25 +0000 (23:20 +0200)
This finally gets rid of the nasty hack that manipulated a glyph
we somehow got from FreeType. Simplifies drawing handling a bit and
decouples drawing code from all font handling and related (fontconfig,
etc.) code.

libass/ass_drawing.c
libass/ass_drawing.h
libass/ass_parse.c
libass/ass_render.c

index 940c66b02a694f19aac2516da548b4d318172626..e25f213527f306f83b861e94ddee53414504506a 100644 (file)
@@ -17,7 +17,6 @@
  */
 
 #include <ft2build.h>
-#include FT_GLYPH_H
 #include FT_OUTLINE_H
 #include FT_BBOX_H
 #include <math.h>
 #define GLYPH_INITIAL_POINTS 100
 #define GLYPH_INITIAL_CONTOURS 5
 
-/*
- * \brief Get and prepare a FreeType glyph
- */
-static void drawing_make_glyph(ASS_Drawing *drawing, void *fontconfig_priv,
-                               ASS_Font *font)
-{
-    FT_OutlineGlyph glyph;
-
-    // This is hacky...
-    glyph = (FT_OutlineGlyph) ass_font_get_glyph(fontconfig_priv, font,
-                                                 (uint32_t) ' ', 0, 0);
-    if (glyph) {
-        FT_Outline_Done(drawing->ftlibrary, &glyph->outline);
-        FT_Outline_New(drawing->ftlibrary, GLYPH_INITIAL_POINTS,
-                       GLYPH_INITIAL_CONTOURS, &glyph->outline);
-
-        glyph->outline.n_contours = 0;
-        glyph->outline.n_points = 0;
-        glyph->root.advance.x = glyph->root.advance.y = 0;
-    }
-    drawing->glyph = glyph;
-}
-
 /*
  * \brief Add a single point to a contour.
  */
 static inline void drawing_add_point(ASS_Drawing *drawing,
                                      FT_Vector *point)
 {
-    FT_Outline *ol = &drawing->glyph->outline;
+    FT_Outline *ol = &drawing->outline;
 
     if (ol->n_points >= drawing->max_points) {
         drawing->max_points *= 2;
@@ -75,11 +51,11 @@ static inline void drawing_add_point(ASS_Drawing *drawing,
 }
 
 /*
- * \brief Close a contour and check glyph size overflow.
+ * \brief Close a contour and check outline size overflow.
  */
 static inline void drawing_close_shape(ASS_Drawing *drawing)
 {
-    FT_Outline *ol = &drawing->glyph->outline;
+    FT_Outline *ol = &drawing->outline;
 
     if (ol->n_contours >= drawing->max_contours) {
         drawing->max_contours *= 2;
@@ -107,13 +83,13 @@ static void drawing_prepare(ASS_Drawing *drawing)
 
 /*
  * \brief Finish a drawing.  This only sets the horizontal advance according
- * to the glyph's bbox at the moment.
+ * to the outline's bbox at the moment.
  */
 static void drawing_finish(ASS_Drawing *drawing, int raw_mode)
 {
     int i, offset;
     FT_BBox bbox = drawing->cbox;
-    FT_Outline *ol = &drawing->glyph->outline;
+    FT_Outline *ol = &drawing->outline;
 
     // Close the last contour
     drawing_close_shape(drawing);
@@ -126,7 +102,7 @@ static void drawing_finish(ASS_Drawing *drawing, int raw_mode)
     if (raw_mode)
         return;
 
-    drawing->glyph->root.advance.x = d6_to_d16(bbox.xMax - bbox.xMin);
+    drawing->advance.x = bbox.xMax - bbox.xMin;
 
     drawing->desc = double_to_d6(-drawing->pbo * drawing->scale_y);
     drawing->asc = bbox.yMax - bbox.yMin + drawing->desc;
@@ -355,8 +331,7 @@ static void drawing_evaluate_curve(ASS_Drawing *drawing,
 /*
  * \brief Create and initialize a new drawing and return it
  */
-ASS_Drawing *ass_drawing_new(void *fontconfig_priv, ASS_Font *font,
-                             FT_Library lib)
+ASS_Drawing *ass_drawing_new(ASS_Library *lib, FT_Library ftlib)
 {
     ASS_Drawing *drawing;
 
@@ -365,17 +340,18 @@ ASS_Drawing *ass_drawing_new(void *fontconfig_priv, ASS_Font *font,
     drawing->size = DRAWING_INITIAL_SIZE;
     drawing->cbox.xMin = drawing->cbox.yMin = INT_MAX;
     drawing->cbox.xMax = drawing->cbox.yMax = INT_MIN;
-    drawing->fontconfig_priv = fontconfig_priv;
-    drawing->font = font;
-    drawing->ftlibrary = lib;
-    if (font)
-        drawing->library = font->library;
-
+    drawing->ftlibrary = ftlib;
+    drawing->library   = lib;
     drawing->scale_x = 1.;
     drawing->scale_y = 1.;
     drawing->max_contours = GLYPH_INITIAL_CONTOURS;
     drawing->max_points = GLYPH_INITIAL_POINTS;
 
+    FT_Outline_New(drawing->ftlibrary, GLYPH_INITIAL_POINTS,
+            GLYPH_INITIAL_CONTOURS, &drawing->outline);
+    drawing->outline.n_contours = 0;
+    drawing->outline.n_points = 0;
+
     return drawing;
 }
 
@@ -386,6 +362,7 @@ void ass_drawing_free(ASS_Drawing* drawing)
 {
     if (drawing) {
         free(drawing->text);
+        FT_Outline_Done(drawing->ftlibrary, &drawing->outline);
     }
     free(drawing);
 }
@@ -416,17 +393,12 @@ void ass_drawing_hash(ASS_Drawing* drawing)
 /*
  * \brief Convert token list to outline.  Calls the line and curve evaluators.
  */
-FT_OutlineGlyph *ass_drawing_parse(ASS_Drawing *drawing, int raw_mode)
+FT_Outline *ass_drawing_parse(ASS_Drawing *drawing, int raw_mode)
 {
     int started = 0;
     ASS_DrawingToken *token;
     FT_Vector pen = {0, 0};
 
-    if (drawing->font)
-        drawing_make_glyph(drawing, drawing->fontconfig_priv, drawing->font);
-    if (!drawing->glyph)
-        return NULL;
-
     drawing->tokens = drawing_tokenize(drawing->text);
     drawing_prepare(drawing);
 
@@ -486,5 +458,5 @@ FT_OutlineGlyph *ass_drawing_parse(ASS_Drawing *drawing, int raw_mode)
 
     drawing_finish(drawing, raw_mode);
     drawing_free_tokens(drawing->tokens);
-    return &drawing->glyph;
+    return &drawing->outline;
 }
index f677fcdddc26a52be0b037528217f04f88687afb..b17d7e3beadaee57aae2bd7c244549678016d651 100644 (file)
@@ -20,7 +20,7 @@
 #define LIBASS_DRAWING_H
 
 #include <ft2build.h>
-#include FT_GLYPH_H
+#include FT_OUTLINE_H
 
 #include "ass.h"
 
@@ -53,13 +53,12 @@ typedef struct {
     double scale_y;     // FontScaleY
     int asc;            // ascender
     int desc;           // descender
-    FT_OutlineGlyph glyph;  // the "fake" glyph created for later rendering
+    FT_Outline outline; // target outline
+    FT_Vector advance;  // advance (from cbox)
     int hash;           // hash value (for caching)
 
     // private
     FT_Library ftlibrary;   // needed for font ops
-    ASS_Font *font;         // dito
-    void *fontconfig_priv;  // dito
     ASS_Library *library;
     int size;           // current buffer size
     ASS_DrawingToken *tokens;    // tokenized drawing
@@ -70,11 +69,10 @@ typedef struct {
     FT_BBox cbox;   // bounding box, or let's say... VSFilter's idea of it
 } ASS_Drawing;
 
-ASS_Drawing *ass_drawing_new(void *fontconfig_priv, ASS_Font *font,
-                             FT_Library lib);
+ASS_Drawing *ass_drawing_new(ASS_Library *lib, FT_Library ftlib);
 void ass_drawing_free(ASS_Drawing* drawing);
 void ass_drawing_add_char(ASS_Drawing* drawing, char symbol);
 void ass_drawing_hash(ASS_Drawing* drawing);
-FT_OutlineGlyph *ass_drawing_parse(ASS_Drawing *drawing, int raw_mode);
+FT_Outline *ass_drawing_parse(ASS_Drawing *drawing, int raw_mode);
 
 #endif /* LIBASS_DRAWING_H */
index 7a6dd2541270595ff5ca39fa87c55e388171e782..d9fcb76d24492ff43ce61636e52a3cc7e874f925 100644 (file)
@@ -216,13 +216,9 @@ static char *parse_vector_clip(ASS_Renderer *render_priv, char *p)
     int res = 0;
     ASS_Drawing *drawing = render_priv->state.clip_drawing;
 
-    if (drawing && drawing->glyph)
-        FT_Done_Glyph((FT_Glyph) drawing->glyph);
     ass_drawing_free(drawing);
-    render_priv->state.clip_drawing = ass_drawing_new(
-        render_priv->fontconfig_priv,
-        render_priv->state.font,
-        render_priv->ftlibrary);
+    render_priv->state.clip_drawing =
+        ass_drawing_new(render_priv->library, render_priv->ftlibrary);
     drawing = render_priv->state.clip_drawing;
     skipopt('(');
     res = mystrtoi(&p, &scale);
index 9a1b911a6e7f5b315aecdbb1c0a5ce18f75bd9c7..021bfc4c59d8d7304e712bc02f52eb1c0dd77bf4 100644 (file)
@@ -559,8 +559,7 @@ static void blend_vector_clip(ASS_Renderer *render_priv,
         GlyphHashValue v;
 
         // Not found in cache, parse and rasterize it
-        ass_drawing_parse(drawing, 1);
-        outline = &drawing->glyph->outline;
+        outline = ass_drawing_parse(drawing, 1);
         if (!outline) {
             ass_msg(render_priv->library, MSGL_WARN,
                     "Clip vector parsing failed. Skipping.");
@@ -574,8 +573,7 @@ static void blend_vector_clip(ASS_Renderer *render_priv,
                 .x = int_to_d6(render_priv->settings.left_margin),
                 .y = -int_to_d6(render_priv->settings.top_margin),
             };
-            FT_Outline_Translate(&drawing->glyph->outline,
-                                 trans.x, trans.y);
+            FT_Outline_Translate(outline, trans.x, trans.y);
         }
 
         ass_msg(render_priv->library, MSGL_DBG2,
@@ -587,7 +585,6 @@ static void blend_vector_clip(ASS_Renderer *render_priv,
         if (clip_bm == NULL) {
             ass_msg(render_priv->library, MSGL_WARN,
                 "Clip vector rasterization failed: %d. Skipping.", error);
-            FT_Outline_Done(render_priv->ftlibrary, outline);
         }
 
         //clip_bm = (FT_BitmapGlyph) glyph;
@@ -682,7 +679,6 @@ blend_vector_error:
 
 blend_vector_exit:
     ass_free_bitmap(clip_bm);
-    FT_Outline_Done(render_priv->ftlibrary, outline);
     ass_drawing_free(render_priv->state.clip_drawing);
     render_priv->state.clip_drawing = 0;
 }
@@ -879,9 +875,8 @@ init_render_context(ASS_Renderer *render_priv, ASS_Event *event)
     render_priv->state.effect_timing = 0;
     render_priv->state.effect_skip_timing = 0;
     ass_drawing_free(render_priv->state.drawing);
-    render_priv->state.drawing = ass_drawing_new(render_priv->fontconfig_priv,
-                                                 render_priv->state.font,
-                                                 render_priv->ftlibrary);
+    render_priv->state.drawing = ass_drawing_new(render_priv->library,
+            render_priv->ftlibrary);
 
     apply_transition_effects(render_priv, event);
 }
@@ -1073,11 +1068,10 @@ get_outline_glyph(ASS_Renderer *render_priv, int symbol, GlyphInfo *info,
         if (drawing->hash) {
             if(!ass_drawing_parse(drawing, 0))
                 return;
-            outline_copy(render_priv->ftlibrary, &drawing->glyph->outline,
+            outline_copy(render_priv->ftlibrary, &drawing->outline,
                     &info->outline);
-            info->advance.x = d16_to_d6(((FT_Glyph)drawing->glyph)->advance.x);
-            info->advance.y = d16_to_d6(((FT_Glyph)drawing->glyph)->advance.y);
-            FT_Done_Glyph((FT_Glyph)drawing->glyph);
+            info->advance.x = drawing->advance.x;
+            info->advance.y = drawing->advance.y;
         } else {
             FT_Glyph glyph =
                 ass_font_get_glyph(render_priv->fontconfig_priv,
@@ -1805,9 +1799,7 @@ ass_render_event(ASS_Renderer *render_priv, ASS_Event *event,
         if (drawing->hash) {
             ass_drawing_free(drawing);
             drawing = render_priv->state.drawing =
-                ass_drawing_new(render_priv->fontconfig_priv,
-                    render_priv->state.font,
-                    render_priv->ftlibrary);
+                ass_drawing_new(render_priv->library, render_priv->ftlibrary);
         }
     }