xine - font pro titulky

Mirek Dobsicek m.dobsicek na sh.cvut.cz
Úterý Únor 12 00:56:17 CET 2002


Ivo Panacek wrote:

> Ahoj,
> 
> pred nedavnem se tu nekdo zminil, ze xine
> jiz umi externi titulky.
> 
> Umi (snad od verze 0.9.7):
> 
> xine soubor.avi:soubor.sub
> 
> Ale nedari se mi zjistit, jak si zvolit
> font pro titulky, resp. font s ceskymi
> znaky.
> 
> Muzete poradit, prosim ?
> 
> ivo
> 

zkompilujes ...
pustis, das tomu treba arial.ttf, ono to vygeneruje takovy fontiky 
vhodny pro xine, a ty nakopirejes do adresare ke xine k jeho fontum
pak uz jenom zeditujes config file a napises tam jmeno toho tvyho 
vygenerovanyho fontu
------------- další část ---------------
/*
 * Copyright (C) 2001 the xine project
 * 
 * This file is part of xine, a unix video player.
 * 
 * xine is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 * 
 * xine is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
 *
 * OSD stuff (text and graphic primitives)
 *
 * xine-fontconv.c  
 *
 * converts ttf fonts to xine osd fonts
 *
 * compile:
 *   gcc -o xine-fontconv xine-fontconv.c -lfreetype -lz -I/usr/include/freetype2
 *
 * usage:
 *   xine-fontconv font.ttf fontname
 *
 * begin                : Sat Dec 1 2001
 * copyright            : (C) 2001 by Miguel Freitas
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <zlib.h>
#include <iconv.h>

#ifndef OLD_FREETYPE2
#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_GLYPH_H
#else                   /* freetype 2.0.1 */
#include <freetype/freetype.h>
#include <freetype/ftglyph.h>
#endif

#define MAX(a, b) ((a) > (b)? (a) : (b))

#define f266ToInt(x)            (((x)+32)>>6)   /* round fractional fixed point */
                                                /* coordinates are in 26.6 pixels (i.e. 1/64th of pixels)*/
#define f266CeilToInt(x)        (((x)+63)>>6)   /* ceiling */
#define f266FloorToInt(x)       ((x)>>6)        /* floor */

/* xine stuff */
typedef struct osd_fontchar_s osd_fontchar_t;
typedef struct osd_font_s     osd_font_t;
typedef unsigned short        uint16_t;
typedef unsigned char         uint8_t;

struct osd_fontchar_s {
  uint16_t code;
  uint16_t width;
  uint16_t height;
  uint8_t *bmp;
};

struct osd_font_s {
  char             name[40];
  uint16_t         version;
  uint16_t         size;
  uint16_t         num_fontchars;
  osd_fontchar_t  *fontchar;
  osd_font_t      *next;
}; 

osd_fontchar_t fontchar;
osd_font_t     font;

iconv_t cd;					// iconv conversion descriptor

void print_bitmap (FT_Bitmap *bitmap) {

  int x,y;
  
  for( y = 0; y < bitmap->rows; y++ ) {
    for( x = 0; x < bitmap->width; x++ ) {
      if( bitmap->buffer[y*bitmap->width+x] > 1 )
        printf("%02x ", bitmap->buffer[y*bitmap->width+x] );
      else
        printf("   ");
    }
    printf("\n");
  }
}

FT_Bitmap *create_bitmap (int width, int height) {
  FT_Bitmap * bitmap;
  printf("Bitmap char %d %d\n",width,height);
  bitmap = malloc( sizeof( FT_Bitmap ) );
  bitmap->rows = height;
  bitmap->width = width;
  bitmap->buffer = malloc(width*height);
  memset( bitmap->buffer, 0, width*height );
  
  return bitmap;
}

void destroy_bitmap (FT_Bitmap * bitmap) {
  free(bitmap->buffer);
  free(bitmap);
}
 

/* 
   This function is called to blend a slightly deslocated
   version of the bitmap. This will produce the border effect.
   Note that the displacement may be smaller than 1 pixel
   as the bitmap is generated in freetype 1/64 units.
   This border is antialiased to the background.
*/
void add_border_bitmap( FT_Bitmap *dst, FT_Bitmap *src, int left, int top )
{
  int x,y;
  int x1, y1;
  int dstpos, srcpos;
  
  for( y = 0; y < src->rows; y++ ) {
    for( x = 0; x < src->width; x++ ) {
      srcpos = y * src->width + x;
      
      x1 = x + left;
      if( x1 < 0 || x1 >= dst->width )
        continue;
        
      y1 = y + top;
      if( y1 < 0 || y1 >= dst->rows )
        continue;

      dstpos = y1 * dst->width + x1;
      src->buffer[srcpos] /= 51;
      if( src->buffer[srcpos] > dst->buffer[dstpos] )
        dst->buffer[dstpos] = src->buffer[srcpos];
    }
  }
}

/*
   Blend the final version of bitmap (the foreground color) over the
   already generated border. It will be antialiased to the border.
   
   Final palette will be:
   
   0: not used by font, always transparent
   1: font background, usually transparent, may be used to implement
      translucid boxes where the font will be printed.
   2-5: transition between background and border (usually only alpha
        value changes).
   6: font border. if the font is to be displayed without border this
      will probably be adjusted to font background or near.
   7-9: transition between border and foreground
   10: font color (foreground)   
*/
void add_final_bitmap( FT_Bitmap *dst, FT_Bitmap *src, int left, int top )
{
  int x,y;
  int x1, y1;
  int dstpos, srcpos;
  
  for( y = 0; y < src->rows; y++ ) {
    for( x = 0; x < src->width; x++ ) {
      srcpos = y * src->width + x;
      
      x1 = x + left;
      if( x1 < 0 || x1 >= dst->width )
        continue;
        
      y1 = y + top;
      if( y1 < 0 || y1 >= dst->rows )
        continue;

      dstpos = y1 * dst->width + x1;
      src->buffer[srcpos] /= 52;
      if( src->buffer[srcpos] )
        dst->buffer[dstpos] = src->buffer[srcpos] + 5;
    }
  }
  
  for( y = 0; y < dst->rows; y++ ) {
    for( x = 0; x < dst->width; x++ ) {
      dstpos = y * dst->width + x;
      dst->buffer[dstpos]++;
    }
  }

}


void render_font (FT_Face face, char *fontname, int size, int thickness) {

  char                filename[1024];
  FT_Bitmap          *out_bitmap;
  gzFile             *fp;
  int                 error;
  int                 glyph_index;
  FT_Glyph            glyph;
  FT_BitmapGlyph      glyph_bitmap;
  FT_Vector           origin;
  int                 max_bearing_y = 0;        
  int                 i;
  int                 converted;
  unsigned char	      c;

  static int border_pos[9][2] = {
    {-1,0},{1,0},{0,-1},{0,1},
    {-1,-1},{1,-1},{-1,1},{1,1}, {0,0}
  };

  
  /* 
   * generate filename, open file
   */
   
  sprintf (filename, "%s-%d.xinefont.gz", fontname, size);

  fp = gzopen(filename,"w");
 
  if (!fp) {
    printf ("error opening output file %s\n", filename);
    return;
  }

  /* 
   * set up font
   */

  strcpy(font.name, fontname);
  font.version       = 1;
  font.num_fontchars = 0;
  font.size          = size;

  error = FT_Set_Pixel_Sizes( face,     /* handle to face object */
                              0,        /* pixel_width           */
                              size );   /* pixel_height          */
                              
  if (error) {
    printf("error setting size\n");
    return;
  }

  if( !thickness )
    thickness = size * 64 / 30;

  /* 
   * calc max bearing y.
   * this is needed to align all bitmaps by the upper position.
   */

  for (c = 32; c < 0xff; c++) {
    unsigned int o=0;
    char *inbuf = &c;
    char *outbuf = (char*)&o;
    int inbytesleft = 1;
    int outbytesleft = sizeof(unsigned int);

    size_t count = iconv(cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft);

//    printf("Started char %d\n",c);
    
    if (count==-1)
	continue;

//    printf("Started char %d\n",c);
    
    glyph_index = FT_Get_Char_Index( face, o);

//    printf("Index %d\n",glyph_index);

    if (!glyph_index)
      continue;

//    printf("Index char %d\n",c);
      
    error = FT_Load_Glyph (face,               /* handle to face object */
                           glyph_index,        /* glyph index           */
                           FT_LOAD_DEFAULT );  /* load flags            */
                         
    if (error) {
      continue;
    }

    printf("bearing_y %d\n",face->glyph->metrics.horiBearingY);

    if( (face->glyph->metrics.horiBearingY >> 6) > max_bearing_y )
      max_bearing_y = (face->glyph->metrics.horiBearingY >> 6);
    font.num_fontchars++;
  }

  printf("max_bearing_y: %d\n", max_bearing_y + f266CeilToInt(thickness));

  gzwrite (fp, &font, 40+6);
 
  for (c = 32; c < 0xff; c++) {
    unsigned int o=0;
    char *inbuf = &c;
    char *outbuf = (char*)&o;
    int inbytesleft = 1;
    int outbytesleft = sizeof(unsigned int);
    
    size_t count = iconv(cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft);

//    printf("Started char %d\n",c);
    
    converted = 0;

    if (count==-1)
	continue;

    
    for( i=0; i < 9; i++ ) {

      glyph_index = FT_Get_Char_Index( face, o);

        
      if (glyph_index) {
          
        error = FT_Load_Glyph( face,          /* handle to face object */
                               glyph_index,   /* glyph index           */
                               FT_LOAD_DEFAULT );  /* load flags */
          
        if (!error) {
          error = FT_Get_Glyph( face->glyph, &glyph );
	    
//	  printf("%d\n",(max_bearing_y<<6) - face->glyph->metrics.horiBearingY +  face->glyph->metrics.height + thickness);
//	  printf("%d %d %d %d\n",(max_bearing_y<<6), face->glyph->metrics.horiBearingY,face->glyph->metrics.height,thickness);

          if( i == 0 ) {
            out_bitmap = create_bitmap( f266CeilToInt(MAX(face->glyph->metrics.horiAdvance, face->glyph->metrics.width + face->glyph->metrics.horiBearingX)),
                                        f266CeilToInt((max_bearing_y<<6) - face->glyph->metrics.horiBearingY + 
                                        face->glyph->metrics.height + thickness) );
          }

          origin.x = thickness + border_pos[i][0]*thickness;
          origin.y = thickness + border_pos[i][1]*thickness;

          error = FT_Glyph_To_Bitmap( &glyph, ft_render_mode_normal, &origin, 1 );  


          if (error) {
            printf("error generating bitmap [%d]\n",c);
            return;
          }

          glyph_bitmap = (FT_BitmapGlyph)glyph;

          if( i < 8 )
            add_border_bitmap( out_bitmap, &glyph_bitmap->bitmap, glyph_bitmap->left,
                               max_bearing_y - glyph_bitmap->top );
          else
            add_final_bitmap( out_bitmap, &glyph_bitmap->bitmap, glyph_bitmap->left,
                              max_bearing_y - glyph_bitmap->top );
          converted = 1;          
                              
          FT_Done_Glyph( glyph );
        
	}
      }
    }
    
    if( converted ) {
      printf("[%c:%d] bitmap width: %d height: %d\n", c, c, out_bitmap->width, out_bitmap->rows );
      /* 
      print_bitmap(out_bitmap);
      */
      fontchar.code = c;
      fontchar.width = out_bitmap->width;
      fontchar.height = out_bitmap->rows;
  
      gzwrite (fp, &fontchar,6);
      gzwrite (fp, out_bitmap->buffer, out_bitmap->width*out_bitmap->rows);
    }
  }
  gzclose(fp);

  printf ("generated %s (%d)\n", filename, font.num_fontchars);
}  

int main(int argc, char *argv[]) {

  int                 error;
  int                 len;
  FT_Library          library;
  FT_Face             face;
  int thickness = 0;
  char* encoding;

  /*
   * command line parsing
   */

  if (argc<3) {
    printf ("usage:%s font.ttf fontname [encoding]\n", argv[0]);
    exit (1);
  }
  
  len = strlen (argv[1]);

  if (strncasecmp (&argv[1][len-4],".ttf",3)) {
    printf ("font name must have .ttf suffix (is %s)\n", &argv[1][len-4]);
    exit (1);
  }

  error = FT_Init_FreeType( &library );
  if( error ) {
    printf("error initializing freetype\n");
  }
  
  error = FT_New_Face( library, 
                       argv[1],
                       0,
                       &face );
  if (error) {
    printf("error loading font\n");
    return 1;
  }

  if (argc=3) {
    encoding=argv[3];
  } else {
    encoding="UNICODE"; //default tagret charset - no conv
  }    

  cd = iconv_open("UNICODE", encoding);
  if (cd==(iconv_t)-1) {
    printf("Unsupported encoding");
    return 1;
    }

  render_font (face, argv[2], 16, thickness);
  render_font (face, argv[2], 20, thickness);
  render_font (face, argv[2], 24, thickness);
  render_font (face, argv[2], 32, thickness);

  iconv_close(cd);

  /*
   * some rgb -> yuv conversion,
   * can be used to calc new palettes
   */
  /*
  { 
    float f;
    for (f=1.0; f<6.0; f+=1.0) {

      float R=f*40.0;
      float G=f*40.0;
      float B=f*42.0;
      float Y, Cb, Cr;

      Y  =  0.29900 * R + 0.58700 * G + 0.11400 * B ;
      Cb = -0.16874 * R - 0.33126 * G + 0.50000 * B  + 128.0;
      Cr =  0.50000 * R - 0.41869 * G - 0.08131 * B  + 128.0;
      
      printf ("CLUT_Y_CR_CB_INIT(0x%x, 0x%x, 0x%x),\n", (int) Y, (int) Cr, (int) Cb);
    }
  }
  */
  return 0;
}




Další informace o konferenci Linux