libass 不支持subtitle字幕Underline问题

    libass中本身有Underline支持字体下画线参数的,但怎么设置也不正常,我跟踪了一下它的源代码,也没有找到其根本原因,我想mplayer中有它的插件,于是对比了一下它的mplayer中的区别,主要是增加了两个函数(事实上只要一个)即可解决;计划在视频转换软件thinkvd的 effect 功能中加上它

测试效果图如下:

libass 不支持subtitle字幕Underline问题_第1张图片


附上相关代码:(调用部分参考mplayer需要自己更改)

/*
 * Strike a glyph with a horizontal line; it's possible to underline it
 * and/or strike through it.  For the line's position and size, truetype
 * tables are consulted.  Obviously this relies on the data in the tables
 * being accurate.
 *
 */
static int ass_strike_outline_glyph(FT_Face face, ass_font_t *font,
                                    FT_Glyph glyph, int under, int through)
{
    TT_OS2 *os2 = FT_Get_Sfnt_Table(face, ft_sfnt_os2);
    TT_Postscript *ps = FT_Get_Sfnt_Table(face, ft_sfnt_post);
    FT_Outline *ol = &((FT_OutlineGlyph) glyph)->outline;
    int bear, advance, y_scale, i, dir;
   
    if (!under && !through)
        return 0;

    // Grow outline
    i = (under ? 4 : 0) + (through ? 4 : 0);
    ol->points = realloc(ol->points, sizeof(FT_Vector) *
                         (ol->n_points + i));
    ol->tags = realloc(ol->tags, ol->n_points + i);
    i = !!under + !!through;
    ol->contours = realloc(ol->contours, sizeof(short) *
                           (ol->n_contours + i));

    // If the bearing is negative, the glyph starts left of the current
    // pen position
    bear = FFMIN(face->glyph->metrics.horiBearingX, 0);
    // We're adding half a pixel to avoid small gaps
    advance = d16_to_d6(glyph->advance.x) + 32;
    y_scale = face->size->metrics.y_scale;

    // Reverse drawing direction for non-truetype fonts
    dir = FT_Outline_Get_Orientation(ol);

    // Add points to the outline
    if (under && ps) {
        int pos, size;
        pos = FT_MulFix(ps->underlinePosition, y_scale * font->scale_y);
        size = FT_MulFix(ps->underlineThickness,
                         y_scale * font->scale_y / 2);

        if (pos > 0 || size <= 0)
            return 1;

        FT_Vector points[4] = {
            {.x = bear,      .y = pos + size},
            {.x = advance,   .y = pos + size},
            {.x = advance,   .y = pos - size},
            {.x = bear,      .y = pos - size},
        };

        if (dir == FT_ORIENTATION_TRUETYPE) {
            for (i = 0; i < 4; i++) {
                ol->points[ol->n_points] = points[i];
                ol->tags[ol->n_points++] = 1;
            }
        } else {
            for (i = 3; i >= 0; i--) {
                ol->points[ol->n_points] = points[i];
                ol->tags[ol->n_points++] = 1;
            }
        }

        ol->contours[ol->n_contours++] = ol->n_points - 1;
    }

    if (through && os2) {
        int pos, size;
        pos = FT_MulFix(os2->yStrikeoutPosition, y_scale * font->scale_y);
        size = FT_MulFix(os2->yStrikeoutSize, y_scale * font->scale_y / 2);

        if (pos < 0 || size <= 0)
            return 1;

        FT_Vector points[4] = {
            {.x = bear,      .y = pos + size},
            {.x = advance,   .y = pos + size},
            {.x = advance,   .y = pos - size},
            {.x = bear,      .y = pos - size},
        };

        if (dir == FT_ORIENTATION_TRUETYPE) {
            for (i = 0; i < 4; i++) {
                ol->points[ol->n_points] = points[i];
                ol->tags[ol->n_points++] = 1;
            }
        } else {
            for (i = 3; i >= 0; i--) {
                ol->points[ol->n_points] = points[i];
                ol->tags[ol->n_points++] = 1;
            }
        }

        ol->contours[ol->n_contours++] = ol->n_points - 1;
    }

    return 0;
}

/**
 * Slightly embold a glyph without touching its metrics
 */
static void ass_glyph_embolden(FT_GlyphSlot slot)
{
    int str;

    if (slot->format != FT_GLYPH_FORMAT_OUTLINE)
        return;

    str = FT_MulFix(slot->face->units_per_EM,
                    slot->face->size->metrics.y_scale) / 64;

    FT_Outline_Embolden(&slot->outline, str);
}

/**
 * /brief Get a glyph
 * /param ch character code
 **/
FT_Glyph ass_font_get_glyph(void* fontconfig_priv, ass_font_t* font, uint32_t ch, ass_hinting_t hinting, int deco)
{
 int error;
 int index = 0;
 int i;
 FT_Glyph glyph;
 FT_Face face = 0;
 int flags = 0;
    int vertical = font->desc.vertical;

 if (ch < 0x20)
  return 0;
    // Handle NBSP like a regular space when rendering the glyph
    if (ch == 0xa0)
        ch = ' ';
 if (font->n_faces == 0)
  return 0;

 for (i = 0; i < font->n_faces; ++i) {
  face = font->faces[i];
  index = FT_Get_Char_Index(face, ch);
  if (index)
   break;
 }

#ifdef CONFIG_FONTCONFIG
 if (index == 0) {
  int face_idx;
  mp_msg(MSGT_ASS, MSGL_INFO, MSGTR_LIBASS_GlyphNotFoundReselectingFont,
         ch, font->desc.family, font->desc.bold, font->desc.italic);
  face_idx = add_face(fontconfig_priv, font, ch);
  if (face_idx >= 0) {
   face = font->faces[face_idx];
   index = FT_Get_Char_Index(face, ch);
   if (index == 0) {
    mp_msg(MSGT_ASS, MSGL_ERR, MSGTR_LIBASS_GlyphNotFound,
           ch, font->desc.family, font->desc.bold, font->desc.italic);
   }
  }
 }
#endif

 switch (hinting) {
 case ASS_HINTING_NONE: flags = FT_LOAD_NO_HINTING; break;
 case ASS_HINTING_LIGHT: flags = FT_LOAD_FORCE_AUTOHINT | FT_LOAD_TARGET_LIGHT; break;
 case ASS_HINTING_NORMAL: flags = FT_LOAD_FORCE_AUTOHINT; break;
 case ASS_HINTING_NATIVE: flags = 0; break;
 }
 
 error = FT_Load_Glyph(face, index, FT_LOAD_NO_BITMAP | flags);
 if (error) {
  mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_ErrorLoadingGlyph);
  return 0;
 }
 
#if (FREETYPE_MAJOR > 2) || /
    ((FREETYPE_MAJOR == 2) && (FREETYPE_MINOR >= 2)) || /
    ((FREETYPE_MAJOR == 2) && (FREETYPE_MINOR == 1) && (FREETYPE_PATCH >= 10))
// FreeType >= 2.1.10 required
 if (!(face->style_flags & FT_STYLE_FLAG_ITALIC) &&
   (font->desc.italic > 55)) {
  FT_GlyphSlot_Oblique(face->glyph);
 }
#endif
    if (!(face->style_flags & FT_STYLE_FLAG_BOLD) &&
        (font->desc.bold > 80)) {
        ass_glyph_embolden(face->glyph);
    }
 error = FT_Get_Glyph(face->glyph, &glyph);
 if (error) {
  mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_ErrorLoadingGlyph);
  return 0;
 }
 
    // Rotate glyph, if needed
    /*if (vertical && ch >= VERTICAL_LOWER_BOUND) {
        FT_Matrix m = { 0, double_to_d16(-1.0), double_to_d16(1.0), 0 };
        FT_Outline_Transform(&((FT_OutlineGlyph) glyph)->outline, &m);
        FT_Outline_Translate(&((FT_OutlineGlyph) glyph)->outline,
                             face->glyph->metrics.vertAdvance,
                             0);
        glyph->advance.x = face->glyph->linearVertAdvance;
    }*/

    // Apply scaling and shift
    FT_Matrix scale = { double_to_d16(font->scale_x), 0, 0,
                        double_to_d16(font->scale_y) };
    FT_Outline *outl = &((FT_OutlineGlyph) glyph)->outline;
    FT_Outline_Transform(outl, &scale);
    FT_Outline_Translate(outl, font->v.x, font->v.y);
    glyph->advance.x *= font->scale_x;

    ass_strike_outline_glyph(face, font, glyph, deco & DECO_UNDERLINE,
                             deco & DECO_STRIKETHROUGH);

 return glyph;
}

你可能感兴趣的:(libass 不支持subtitle字幕Underline问题)