SHARE
TWEET

Untitled

a guest Aug 22nd, 2011 303 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. commit d0bfd1267bbef621c1fdd771dd5c8f523f558c92
  2. Author: Grigori Goronzy <greg@blackbox>
  3. Date:   Mon Aug 22 01:07:12 2011 +0200
  4.  
  5.     libass: Windows GDI font provider
  6.    
  7.     Add a simple GDI-based font provider to use system fonts without any
  8.     help from fontconfig.
  9.    
  10.     There are some limitations: doesn't get all localized fullnames;
  11.     TrueType font collections are not properly supported (only the first
  12.     font); fonts are buffered in memory (needs RAM, sometimes slow).
  13.  
  14. diff --git a/configure.ac b/configure.ac
  15. index fb53386..ff0afc1 100644
  16. --- a/configure.ac
  17. +++ b/configure.ac
  18. @@ -3397,7 +3397,7 @@ AC_ARG_ENABLE(wingdi,
  19.  if test "${enable_wingdi}" != "no"; then
  20.    if test "${SYS}" = "mingw32"; then
  21.      VLC_ADD_PLUGIN([wingdi])
  22. -    VLC_ADD_LIBS([wingdi],[-lgdi32 -lole32])
  23. +    VLC_ADD_LIBS([wingdi libass],[-lgdi32 -lole32])
  24.    fi
  25.    if test "${SYS}" = "mingwce"; then
  26.      VLC_ADD_PLUGIN([wingdi wingapi])
  27. diff --git a/modules/codec/Modules.am b/modules/codec/Modules.am
  28. index 10ca915..33b5f96 100644
  29. --- a/modules/codec/Modules.am
  30. +++ b/modules/codec/Modules.am
  31. @@ -31,7 +31,7 @@ SOURCES_fluidsynth = fluidsynth.c
  32.  SOURCES_cc = cc.c cc.h substext.h
  33.  SOURCES_kate = kate.c
  34.  SOURCES_schroedinger = schroedinger.c
  35. -SOURCES_libass = libass.c
  36. +SOURCES_libass = libass.c libass_win32.c
  37.  SOURCES_aes3 = aes3.c
  38.  SOURCES_subsdec = subsdec.c substext.h
  39.  SOURCES_subsusf = subsusf.c
  40. diff --git a/modules/codec/libass.c b/modules/codec/libass.c
  41. index 829e1fe..5f8d9ef 100644
  42. --- a/modules/codec/libass.c
  43. +++ b/modules/codec/libass.c
  44. @@ -44,8 +44,10 @@
  45.  
  46.  #if defined(WIN32)
  47.  #   include <vlc_charset.h>
  48. +ASS_FontProvider *gdi_fonts_add_provider(ASS_Renderer *renderer);
  49.  #endif
  50.  
  51. +
  52.  /*****************************************************************************
  53.   * Module descriptor
  54.   *****************************************************************************/
  55. @@ -78,6 +80,7 @@ struct decoder_sys_t
  56.      /* */
  57.      ASS_Library    *p_library;
  58.      ASS_Renderer   *p_renderer;
  59. +    ASS_FontProvider *p_provider;
  60.      video_format_t fmt;
  61.  
  62.      /* */
  63. @@ -231,6 +234,7 @@ static int Create( vlc_object_t *p_this )
  64.  #endif
  65.      ass_set_fonts( p_renderer, psz_font, psz_family, true, NULL, 1 );  // setup default font/family
  66.  #ifdef WIN32
  67. +    p_sys->p_provider = gdi_fonts_add_provider( p_renderer );
  68.      if( p_dialog )
  69.      {
  70.          dialog_ProgressSet( p_dialog, NULL, 1.0 );
  71. @@ -242,6 +246,8 @@ static int Create( vlc_object_t *p_this )
  72.      ass_set_fonts( p_renderer, psz_font, psz_family, false, NULL, 1 );
  73.  #endif
  74.  
  75. +
  76. +
  77.      /* Add a track */
  78.      ASS_Track *p_track = p_sys->p_track = ass_new_track( p_sys->p_library );
  79.      if( !p_track )
  80. @@ -288,6 +294,8 @@ static void DecSysRelease( decoder_sys_t *p_sys )
  81.  
  82.      if( p_sys->p_track )
  83.          ass_free_track( p_sys->p_track );
  84. +    if( p_sys->p_provider )
  85. +        ass_font_provider_free( p_sys->p_provider );
  86.      if( p_sys->p_renderer )
  87.          ass_renderer_done( p_sys->p_renderer );
  88.      if( p_sys->p_library )
  89. diff --git a/modules/codec/libass_win32.c b/modules/codec/libass_win32.c
  90. new file mode 100644
  91. index 0000000..6925358
  92. --- /dev/null
  93. +++ b/modules/codec/libass_win32.c
  94. @@ -0,0 +1,251 @@
  95. +/*****************************************************************************
  96. + * libass Windows GDI font support
  97. + *****************************************************************************
  98. + * Copyright (C) 2011 the VideoLAN team
  99. + * $Id$
  100. + *
  101. + * Authors: Grigori Goronzy <greg@chown.ath.cx
  102. + *
  103. + * This program is free software; you can redistribute it and/or modify
  104. + * it under the terms of the GNU General Public License as published by
  105. + * the Free Software Foundation; either version 2 of the License, or
  106. + * (at your option) any later version.
  107. + *
  108. + * This program is distributed in the hope that it will be useful,
  109. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  110. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  111. + * GNU General Public License for more details.
  112. + *
  113. + * You should have received a copy of the GNU General Public License
  114. + * along with this program; if not, write to the Free Software
  115. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  116. + *****************************************************************************/
  117. +
  118. +#ifdef HAVE_CONFIG_H
  119. +#   include "config.h"
  120. +#endif
  121. +
  122. +#ifdef WIN32
  123. +
  124. +#define WINVER 0x0501
  125. +#include <windows.h>
  126. +#include <wingdi.h>
  127. +#include <stdio.h>
  128. +#include <conio.h>
  129. +#include <shlobj.h>
  130. +
  131. +#include <ass/ass.h>
  132. +
  133. +#define TTCF_TAG 0x66637474
  134. +
  135. +ASS_FontProvider *gdi_fonts_add_provider(ASS_Renderer *renderer);
  136. +
  137. +typedef struct enumerate_families EnumerateFamilies;
  138. +struct enumerate_families {
  139. +    char **names;
  140. +    int n_family;
  141. +    int n_alloc;
  142. +};
  143. +
  144. +typedef struct enumerate_family_faces EnumerateFamilyFaces;
  145. +struct enumerate_family_faces {
  146. +    HDC hdc;
  147. +    ASS_FontProvider *provider;
  148. +};
  149. +
  150. +typedef struct font_data_gdi FontDataGDI;
  151. +struct font_data_gdi {
  152. +    HDC      hdc;
  153. +    HFONT    hf;    // caching this seems to be very effective
  154. +    LOGFONT  lf;
  155. +    GLYPHSET *gs;
  156. +
  157. +    void *buf;
  158. +    size_t len;
  159. +};
  160. +
  161. +static int CALLBACK
  162. +font_family_cb(ENUMLOGFONTEX *lpelfe, NEWTEXTMETRICEX *lpntme,
  163. +               int type, LPARAM lparam)
  164. +{
  165. +    EnumerateFamilies *families = (EnumerateFamilies *)lparam;
  166. +
  167. +    if (type != TRUETYPE_FONTTYPE)
  168. +        return 1;
  169. +
  170. +    // skip duplicate pseudo-vertical variants
  171. +    if (lpelfe->elfLogFont.lfFaceName[0] == '@')
  172. +        return 1;
  173. +
  174. +    // check allocation
  175. +    if (families->n_family >= families->n_alloc) {
  176. +        families->n_alloc = !families->n_alloc ? 1 : families->n_alloc * 2;
  177. +        families->names = realloc(families->names,
  178. +                families->n_alloc * sizeof(char *));
  179. +    }
  180. +
  181. +    // add to list
  182. +    families->names[families->n_family] = strdup(lpelfe->elfLogFont.lfFaceName);
  183. +    families->n_family++;
  184. +
  185. +    return 1;
  186. +}
  187. +
  188. +static int CALLBACK
  189. +font_info_cb(ENUMLOGFONTEX *lpelfe, NEWTEXTMETRICEX *lpntme,
  190. +             int type, LPARAM lparam)
  191. +{
  192. +    char *fnp;
  193. +    EnumerateFamilyFaces *data = (EnumerateFamilyFaces *)lparam;
  194. +    LOGFONT *lf = &lpelfe->elfLogFont;
  195. +    ASS_FontProviderMetaData meta;
  196. +    FontDataGDI *gdi;
  197. +
  198. +    if (type != TRUETYPE_FONTTYPE)
  199. +        return 1;
  200. +
  201. +    meta.family       = lf->lfFaceName;
  202. +    meta.fullnames    = &fnp;
  203. +    meta.fullnames[0] = (char *)lpelfe->elfFullName;
  204. +    meta.n_fullname   = 1;
  205. +    meta.weight       = lf->lfWeight;
  206. +    meta.slant        = !!lf->lfItalic * 110;
  207. +
  208. +    gdi = calloc(1, sizeof(FontDataGDI));
  209. +    gdi->hdc = data->hdc;
  210. +    gdi->lf  = *lf;
  211. +
  212. +    // FIXME: what about the glyph index of TrueType collections?
  213. +
  214. +    ass_font_provider_add_font(data->provider, &meta, NULL, 0, gdi);
  215. +
  216. +    return 1;
  217. +}
  218. +
  219. +static int check_glyph_gdi(void *data, uint32_t codepoint)
  220. +{
  221. +    int i;
  222. +    FontDataGDI *fd = (FontDataGDI *)data;
  223. +
  224. +    if (codepoint == 0)
  225. +        return 1;
  226. +
  227. +    // create GLYPHSET if we don't have a cached copy already
  228. +    if (!fd->gs) {
  229. +        if (!fd->hf)
  230. +            fd->hf = CreateFontIndirect(&fd->lf);
  231. +        //HFONT hf = CreateFontIndirect(&fd->lf);
  232. +        HGDIOBJ old = SelectObject(fd->hdc, fd->hf);
  233. +        int gs_alloc;
  234. +
  235. +        gs_alloc = GetFontUnicodeRanges(fd->hdc, NULL);
  236. +        fd->gs   = malloc(gs_alloc);
  237. +        GetFontUnicodeRanges(fd->hdc, fd->gs);
  238. +
  239. +        //SelectObject(fd->hdc, old);
  240. +        //DeleteObject(hf);
  241. +    }
  242. +
  243. +    for (i = 0; i < (int)fd->gs->cRanges; i++) {
  244. +        unsigned low = fd->gs->ranges[i].wcLow;
  245. +        unsigned high = low + fd->gs->ranges[i].cGlyphs - 1;
  246. +        if (low <= codepoint && high >= codepoint)
  247. +            return 1;
  248. +        if (low > codepoint)
  249. +            break;
  250. +    }
  251. +
  252. +    return 0;
  253. +}
  254. +
  255. +static void destroy_font_gdi(void *data)
  256. +{
  257. +    FontDataGDI *gdi = (FontDataGDI *)data;
  258. +
  259. +    DeleteObject(gdi->hf);
  260. +    free(gdi->buf);
  261. +    free(gdi->gs);
  262. +    free(gdi);
  263. +}
  264. +
  265. +static void destroy_provider_gdi(void *data)
  266. +{
  267. +    HDC hdc = (HDC)data;
  268. +
  269. +    ReleaseDC(NULL, hdc);
  270. +}
  271. +
  272. +static void *get_face_gdi(void *data, size_t *len)
  273. +{
  274. +    FontDataGDI *fd = (FontDataGDI *)data;
  275. +
  276. +    if (!fd->buf) {
  277. +        if (!fd->hf)
  278. +            fd->hf = CreateFontIndirect(&fd->lf);
  279. +        //HFONT hf = CreateFontIndirect(&fd->lf);
  280. +        HGDIOBJ old = SelectObject(fd->hdc, fd->hf);
  281. +        uint32_t tag = TTCF_TAG;
  282. +
  283. +        // first try to open it as a font collection
  284. +        // if that fails, it must be a normal font
  285. +        fd->len = GetFontData(fd->hdc, TTCF_TAG, 0, NULL, 0);
  286. +        if (fd->len == GDI_ERROR) {
  287. +            fd->len = GetFontData(fd->hdc, 0, 0, NULL, 0);
  288. +            tag = 0;
  289. +        }
  290. +
  291. +        fd->buf = malloc(fd->len);
  292. +        GetFontData(fd->hdc, tag, 0, fd->buf, fd->len);
  293. +
  294. +        //SelectObject(fd->hdc, old);
  295. +        //DeleteObject(hf);
  296. +    }
  297. +
  298. +    *len = fd->len;
  299. +    return fd->buf;
  300. +}
  301. +
  302. +static ASS_FontProviderFuncs gdi_funcs = {
  303. +    get_face_gdi,
  304. +    check_glyph_gdi,
  305. +    destroy_font_gdi,
  306. +    destroy_provider_gdi
  307. +};
  308. +
  309. +ASS_FontProvider *gdi_fonts_add_provider(ASS_Renderer *renderer)
  310. +{
  311. +    int i;
  312. +    HDC hDC = GetDC(NULL);
  313. +    LOGFONT lf;
  314. +    ASS_FontProvider *provider;
  315. +    EnumerateFamilies families;
  316. +    EnumerateFamilyFaces info_data;
  317. +
  318. +    // initialize font provider
  319. +    provider = ass_create_font_provider(renderer, &gdi_funcs, hDC);
  320. +
  321. +    // first iteration
  322. +    // get all unique family names
  323. +    memset(&families, 0, sizeof(EnumerateFamilies));
  324. +    lf.lfFaceName[0] = '\0';
  325. +    lf.lfCharSet  = ANSI_CHARSET;   // use a specific charset. if we do not specify
  326. +                                    // one, e.g. use DEFAULT_CHARSET, families are
  327. +                                    // enumerated multiple times!
  328. +    lf.lfPitchAndFamily = 0;
  329. +    EnumFontFamiliesEx(hDC, &lf, (FONTENUMPROC)font_family_cb, (LPARAM)&families, 0);
  330. +
  331. +    // second iteration
  332. +    // iterate over all families to get detailed info about all styles
  333. +    info_data.hdc = hDC;
  334. +    info_data.provider = provider;
  335. +    for (i = 0; i < families.n_family; i++) {
  336. +        strcpy(&lf.lfFaceName[0], families.names[i]);
  337. +        EnumFontFamiliesEx(hDC, &lf, (FONTENUMPROC)font_info_cb, (LPARAM)&info_data, 0);
  338. +        free(families.names[i]);
  339. +    }
  340. +    free(families.names);
  341. +
  342. +    return provider;
  343. +}
  344. +
  345. +#endif
RAW Paste Data
Top