From 79b1c68ffbe11ada50d8e288efc0255eba268185 Mon Sep 17 00:00:00 2001 From: Klaus Schmidinger Date: Sun, 17 Jun 2007 11:12:46 +0200 Subject: [PATCH] Now using 'fontconfig' to determine which fonts to use --- CONTRIBUTORS | 1 + HISTORY | 4 ++- INSTALL | 4 +-- Makefile | 4 +-- font.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++----- font.h | 13 +++++++-- menu.c | 35 ++++++++++++------------ tools.c | 39 ++++++++++++++++----------- tools.h | 42 ++++++++++++++++++++++++----- 9 files changed, 165 insertions(+), 53 deletions(-) diff --git a/CONTRIBUTORS b/CONTRIBUTORS index d96279a4..51041238 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -2024,6 +2024,7 @@ Anssi Hannula for improving handling Transfer Mode devices when selecting a device to receive for fixing handling frequencies in NitFilter::Process() for making non-primary devices in Transfer mode be also used for recording + for code and hints on how to use 'fontconfig' to determine which fonts to use Antti Hartikainen for updating 'S13E' in 'sources.conf' diff --git a/HISTORY b/HISTORY index af89fbe1..33795add 100644 --- a/HISTORY +++ b/HISTORY @@ -5230,7 +5230,7 @@ Video Disk Recorder Revision History - Changes to the OSD settings in the "Setup/OSD" menu now immediately take effect when the "Ok" key is pressed. -2007-06-16: Version 1.5.4 +2007-06-17: Version 1.5.4 - Increased APIVERSION (forgot to do that in 1.5.2 and 1.5.3). - Fixed a crash in i18n character set conversion (thanks to Alexander Riedel, @@ -5242,3 +5242,5 @@ Video Disk Recorder Revision History canonical spelling with '-' (thanks to Ludwig Nussel for pointing this out). - Modified handling invalid characters in VFAT mode. - Replaced strn0cpy() with Utf8Strn0Cpy() where necessary. +- Now using 'fontconfig' to determine which fonts to use (thanks to Anssi Hannula + for code and hints on how to do this). diff --git a/INSTALL b/INSTALL index 26af9d90..77ad9322 100644 --- a/INSTALL +++ b/INSTALL @@ -22,6 +22,7 @@ to work properly. You will also need to install the following libraries, as well as their "devel" packages to get the necessary header files for compiling VDR: + fontconfig freetype2 libcap libjpeg @@ -29,9 +30,6 @@ You will also need to install the following libraries, as well as their If the "capability" module is not compiled into your kernel, you may need to do "modprobe capability" before running VDR. -When running VDR, the Freetype fonts must be installed in the directory -/usr/share/fonts/truetype. - After extracting the package, change into the VDR directory and type 'make'. This should produce an executable file named 'vdr', which can be run after the DVB driver has been diff --git a/Makefile b/Makefile index 7f711db4..7aa75f31 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ # See the main source file 'vdr.c' for copyright information and # how to reach the author. # -# $Id: Makefile 1.100 2007/05/28 11:22:42 kls Exp $ +# $Id: Makefile 1.101 2007/06/16 10:48:59 kls Exp $ .DELETE_ON_ERROR: @@ -17,7 +17,7 @@ CXXFLAGS ?= -g -O2 -Wall -Woverloaded-virtual LSIDIR = ./libsi MANDIR = /usr/local/man BINDIR = /usr/local/bin -LIBS = -ljpeg -lpthread -ldl -lcap -lfreetype +LIBS = -ljpeg -lpthread -ldl -lcap -lfreetype -lfontconfig INCLUDES = -I/usr/include/freetype2 PLUGINDIR= ./PLUGINS diff --git a/font.c b/font.c index af8b7cbf..f0722744 100644 --- a/font.c +++ b/font.c @@ -4,11 +4,12 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: font.c 1.15 2007/06/09 14:41:27 kls Exp $ + * $Id: font.c 1.16 2007/06/17 11:03:33 kls Exp $ */ #include "font.h" #include +#include #include #include FT_FREETYPE_H #include "config.h" @@ -22,7 +23,7 @@ struct tKerning { uint prevSym; int kerning; - tKerning(uint PrevSym, int Kerning) { prevSym = PrevSym; kerning = Kerning; } + tKerning(uint PrevSym, int Kerning = 0) { prevSym = PrevSym; kerning = Kerning; } }; class cGlyph : public cListObject { @@ -293,7 +294,7 @@ cFont *cFont::fonts[eDvbFontSize] = { NULL }; void cFont::SetFont(eDvbFont Font, const char *Name, int CharHeight) { delete fonts[Font]; - fonts[Font] = new cFreetypeFont(*Name == '/' ? Name : *AddDirectory(FONTDIR, Name), CharHeight); + fonts[Font] = new cFreetypeFont(GetFontFileName(Name), CharHeight); } const cFont *cFont::GetFont(eDvbFont Font) @@ -304,14 +305,77 @@ const cFont *cFont::GetFont(eDvbFont Font) Font = fontSml; if (!fonts[Font]) { switch (Font) { - case fontOsd: SetFont(Font, AddDirectory(FONTDIR, Setup.FontOsd), Setup.FontOsdSize); break; - case fontSml: SetFont(Font, AddDirectory(FONTDIR, Setup.FontSml), Setup.FontSmlSize); break; - case fontFix: SetFont(Font, AddDirectory(FONTDIR, Setup.FontFix), Setup.FontFixSize); break; + case fontOsd: SetFont(Font, Setup.FontOsd, Setup.FontOsdSize); break; + case fontSml: SetFont(Font, Setup.FontSml, Setup.FontSmlSize); break; + case fontFix: SetFont(Font, Setup.FontFix, Setup.FontFixSize); break; } } return fonts[Font]; } +bool cFont::GetAvailableFontNames(cStringList *FontNames, bool Monospaced) +{ + if (!FontNames->Size()) { + FcInit(); + FcObjectSet *os = FcObjectSetBuild(FC_FAMILY, FC_STYLE, NULL); + FcPattern *pat = FcPatternCreate(); + FcPatternAddBool(pat, FC_SCALABLE, FcTrue); + if (Monospaced) + FcPatternAddInteger(pat, FC_SPACING, FC_MONO); + FcFontSet* fontset = FcFontList(NULL, pat, os); + for (int i = 0; i < fontset->nfont; i++) { + char *s = (char *)FcNameUnparse(fontset->fonts[i]); + if (s) { + // Strip i18n stuff: + char *p = strchr(s, ','); + if (p) + *p = 0; + // Make it user presentable: + s = strreplace(s, "\\", ""); // '-' is escaped + s = strreplace(s, "style=", ""); + FontNames->Append(s); // takes ownership of s + } + } + FcFontSetDestroy(fontset); + FcPatternDestroy(pat); + FcObjectSetDestroy(os); + FcFini(); + FontNames->Sort(); + } + return FontNames->Size() > 0; +} + +cString cFont::GetFontFileName(const char *FontName) +{ + cString FontFileName; + if (FontName) { + char *fn = strdup(FontName); + fn = strreplace(fn, ":", ":style="); + fn = strreplace(fn, "-", "\\-"); + FcInit(); + FcPattern *pat = FcNameParse((FcChar8 *)fn); + FcPatternAddBool(pat, FC_SCALABLE, FcTrue); + FcConfigSubstitute(NULL, pat, FcMatchPattern); + FcDefaultSubstitute(pat); + FcFontSet *fontset = FcFontSort(NULL, pat, FcFalse, NULL, NULL); + for (int i = 0; i < fontset->nfont; i++) { + FcBool scalable; + FcPatternGetBool(fontset->fonts[i], FC_SCALABLE, 0, &scalable); + if (scalable) { + FcChar8 *s = NULL; + FcPatternGetString(fontset->fonts[i], FC_FILE, 0, &s); + FontFileName = (char *)s; + break; + } + } + FcFontSetDestroy(fontset); + FcPatternDestroy(pat); + free(fn); + FcFini(); + } + return FontFileName; +} + // --- cTextWrapper ---------------------------------------------------------- cTextWrapper::cTextWrapper(void) diff --git a/font.h b/font.h index b2ab293c..081199e0 100644 --- a/font.h +++ b/font.h @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: font.h 1.16 2007/06/10 12:58:54 kls Exp $ + * $Id: font.h 1.17 2007/06/17 11:07:15 kls Exp $ */ #ifndef __FONT_H @@ -12,10 +12,10 @@ #include #include +#include "tools.h" #define MAXFONTNAME 64 #define MAXFONTSIZE 64 -#define FONTDIR "/usr/share/fonts/truetype" enum eDvbFont { fontOsd, @@ -53,6 +53,15 @@ public: ///< The caller must not use the returned font outside the scope in which ///< it was retrieved by the call to GetFont(), because a call to SetFont() ///< may delete an existing font. + static bool GetAvailableFontNames(cStringList *FontNames, bool Monospaced = false); + ///< Queries the font configuration for a list of available font names, + ///< which is returned in FontNames. If Monospaced is true, only + ///< monospaced fonts will be returned. The resulting font names are + ///< in a format that can be used with GetFontFileName() to get the name + ///< of the actual font file. + ///< Returns true if any font names were found. + static cString GetFontFileName(const char *FontName); + ///< Retruns the actual font file name for the given FontName. }; class cTextWrapper { diff --git a/menu.c b/menu.c index f86414ae..6217d693 100644 --- a/menu.c +++ b/menu.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: menu.c 1.452 2007/06/16 09:33:21 kls Exp $ + * $Id: menu.c 1.453 2007/06/17 11:01:13 kls Exp $ */ #include "menu.h" @@ -2160,7 +2160,7 @@ private: cThemes themes; int originalThemeIndex; int themeIndex; - cFileNameList fontNames; + cStringList fontOsdNames, fontSmlNames, fontFixNames; int fontOsdIndex, fontSmlIndex, fontFixIndex; virtual void Set(void); public: @@ -2176,12 +2176,15 @@ cMenuSetupOSD::cMenuSetupOSD(void) skinDescriptions = new const char*[numSkins]; themes.Load(Skins.Current()->Name()); themeIndex = originalThemeIndex = Skins.Current()->Theme() ? themes.GetThemeIndex(Skins.Current()->Theme()->Description()) : 0; - fontNames.Load(FONTDIR); - if (fontNames.Size()) { - fontOsdIndex = max(0, fontNames.Find(Setup.FontOsd)); - fontSmlIndex = max(0, fontNames.Find(Setup.FontSml)); - fontFixIndex = max(0, fontNames.Find(Setup.FontFix)); - } + cFont::GetAvailableFontNames(&fontOsdNames); + cFont::GetAvailableFontNames(&fontSmlNames); + cFont::GetAvailableFontNames(&fontFixNames, true); + fontOsdNames.Insert(strdup("Sans Serif:Bold")); + fontSmlNames.Insert(strdup("Sans Serif")); + fontFixNames.Insert(strdup("Courier:Bold")); + fontOsdIndex = max(0, fontOsdNames.Find(Setup.FontOsd)); + fontSmlIndex = max(0, fontSmlNames.Find(Setup.FontSml)); + fontFixIndex = max(0, fontFixNames.Find(Setup.FontFix)); Set(); } @@ -2211,11 +2214,9 @@ void cMenuSetupOSD::Set(void) Add(new cMenuEditIntItem( tr("Setup.OSD$Message time (s)"), &data.OSDMessageTime, 1, 60)); Add(new cMenuEditStraItem(tr("Setup.OSD$Use small font"), &data.UseSmallFont, 3, useSmallFontTexts)); Add(new cMenuEditBoolItem(tr("Setup.OSD$Anti-alias"), &data.AntiAlias)); - if (fontNames.Size()) { - Add(new cMenuEditStraItem(tr("Setup.OSD$OSD font name"), &fontOsdIndex, fontNames.Size(), &fontNames[0])); - Add(new cMenuEditStraItem(tr("Setup.OSD$Small font name"), &fontSmlIndex, fontNames.Size(), &fontNames[0])); - Add(new cMenuEditStraItem(tr("Setup.OSD$Fixed font name"), &fontFixIndex, fontNames.Size(), &fontNames[0])); - } + Add(new cMenuEditStraItem(tr("Setup.OSD$OSD font name"), &fontOsdIndex, fontOsdNames.Size(), &fontOsdNames[0])); + Add(new cMenuEditStraItem(tr("Setup.OSD$Small font name"), &fontSmlIndex, fontSmlNames.Size(), &fontSmlNames[0])); + Add(new cMenuEditStraItem(tr("Setup.OSD$Fixed font name"), &fontFixIndex, fontFixNames.Size(), &fontFixNames[0])); Add(new cMenuEditIntItem( tr("Setup.OSD$OSD font size (pixel)"), &data.FontOsdSize, 10, MAXFONTSIZE)); Add(new cMenuEditIntItem( tr("Setup.OSD$Small font size (pixel)"),&data.FontSmlSize, 10, MAXFONTSIZE)); Add(new cMenuEditIntItem( tr("Setup.OSD$Fixed font size (pixel)"),&data.FontFixSize, 10, MAXFONTSIZE)); @@ -2255,11 +2256,9 @@ eOSState cMenuSetupOSD::ProcessKey(eKeys Key) } if (data.UseSmallFont != Setup.UseSmallFont || data.AntiAlias != Setup.AntiAlias) ModifiedApperance = true; - if (fontNames.Size()) { - Utf8Strn0Cpy(data.FontOsd, fontNames[fontOsdIndex], sizeof(data.FontOsd)); - Utf8Strn0Cpy(data.FontSml, fontNames[fontSmlIndex], sizeof(data.FontSml)); - Utf8Strn0Cpy(data.FontFix, fontNames[fontFixIndex], sizeof(data.FontFix)); - } + Utf8Strn0Cpy(data.FontOsd, fontOsdNames[fontOsdIndex], sizeof(data.FontOsd)); + Utf8Strn0Cpy(data.FontSml, fontSmlNames[fontSmlIndex], sizeof(data.FontSml)); + Utf8Strn0Cpy(data.FontFix, fontFixNames[fontFixIndex], sizeof(data.FontFix)); if (strcmp(data.FontOsd, Setup.FontOsd) || data.FontOsdSize != Setup.FontOsdSize) { cFont::SetFont(fontOsd, data.FontOsd, data.FontOsdSize); ModifiedApperance = true; diff --git a/tools.c b/tools.c index 0faf1ea2..dd2395ad 100644 --- a/tools.c +++ b/tools.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: tools.c 1.128 2007/06/16 09:22:40 kls Exp $ + * $Id: tools.c 1.129 2007/06/17 11:02:34 kls Exp $ */ #include "tools.h" @@ -1136,21 +1136,39 @@ struct dirent *cReadDir::Next(void) return directory && readdir_r(directory, &u.d, &result) == 0 ? result : NULL; } -// --- cFileNameList --------------------------------------------------------- +// --- cStringList ----------------------------------------------------------- -cFileNameList::cFileNameList(const char *Directory) +cStringList::~cStringList() { - Load(Directory); + Clear(); } -cFileNameList::~cFileNameList() +int cStringList::Find(const char *s) const +{ + for (int i = 0; i < Size(); i++) { + if (!strcmp(s, At(i))) + return i; + } + return -1; +} + +void cStringList::Clear(void) { for (int i = 0; i < Size(); i++) free(At(i)); } +// --- cFileNameList --------------------------------------------------------- + +// TODO better GetFileNames(const char *Directory, cStringList *List)? +cFileNameList::cFileNameList(const char *Directory) +{ + Load(Directory); +} + bool cFileNameList::Load(const char *Directory) { + Clear(); if (Directory) { cReadDir d(Directory); struct dirent *e; @@ -1159,7 +1177,7 @@ bool cFileNameList::Load(const char *Directory) if (strcmp(e->d_name, ".") && strcmp(e->d_name, "..")) Append(strdup(e->d_name)); } - Sort(CompareStrings); + Sort(); return true; } else @@ -1168,15 +1186,6 @@ bool cFileNameList::Load(const char *Directory) return false; } -int cFileNameList::Find(const char *FileName) -{ - for (int i = 0; i < Size(); i++) { - if (!strcmp(FileName, At(i))) - return i; - } - return -1; -} - // --- cFile ----------------------------------------------------------------- bool cFile::files[FD_SETSIZE] = { false }; diff --git a/tools.h b/tools.h index 6feda29f..89119675 100644 --- a/tools.h +++ b/tools.h @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: tools.h 1.101 2007/06/16 09:15:40 kls Exp $ + * $Id: tools.h 1.102 2007/06/17 11:00:20 kls Exp $ */ #ifndef __TOOLS_H @@ -402,7 +402,17 @@ private: mutable int allocated; mutable int size; mutable T *data; - void Realloc(int NewAllocated) const { data = (T *)realloc(data, (allocated = NewAllocated) * sizeof(T)); } + cVector(const cVector &Vector) {} // don't copy... + cVector &operator=(const cVector &Vector) { return *this; } // ...or assign this! + void Realloc(int Index) const + { + if (++Index > allocated) { + data = (T *)realloc(data, Index * sizeof(T)); + for (int i = allocated; i < Index; i++) + data[i] = T(0); + allocated = Index; + } + } public: cVector(int Allocated = 10) { @@ -414,8 +424,9 @@ public: virtual ~cVector() { free(data); } T& At(int Index) const { + Realloc(Index); if (Index >= size) - Realloc(size = Index + 1); + size = Index + 1; return data[Index]; } const T& operator[](int Index) const @@ -427,12 +438,24 @@ public: return At(Index); } int Size(void) const { return size; } + virtual void Insert(T Data, int Before = 0) + { + if (Before < size) { + Realloc(size); + memmove(&data[Before + 1], &data[Before], (size - Before) * sizeof(T)); + size++; + data[Before] = Data; + } + else + Append(Data); + } virtual void Append(T Data) { if (size >= allocated) Realloc(allocated * 4 / 2); // increase size by 50% data[size++] = Data; } + virtual void Clear(void) {} void Sort(__compar_fn_t Compare) { qsort(data, size, sizeof(T), Compare); @@ -444,12 +467,19 @@ inline int CompareStrings(const void *a, const void *b) return strcmp(*(const char **)a, *(const char **)b); } -class cFileNameList : public cVector { +class cStringList : public cVector { +public: + cStringList(int Allocated = 10): cVector(Allocated) {} + virtual ~cStringList(); + int Find(const char *s) const; + void Sort(void) { cVector::Sort(CompareStrings); } + virtual void Clear(void); + }; + +class cFileNameList : public cStringList { public: cFileNameList(const char *Directory = NULL); - virtual ~cFileNameList(); bool Load(const char *Directory); - int Find(const char *FileName); }; class cHashObject : public cListObject {