vdr/font.c

252 lines
5.4 KiB
C

/*
* font.c: Font handling for the DVB On Screen Display
*
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: font.c 1.12 2006/02/05 13:49:10 kls Exp $
*/
#include "config.h"
#include <ctype.h>
#include "font.h"
#include "tools.h"
#include "fontfix-iso8859-1.c"
#include "fontosd-iso8859-1.c"
#include "fontsml-iso8859-1.c"
#include "fontfix-iso8859-2.c"
#include "fontosd-iso8859-2.c"
#include "fontsml-iso8859-2.c"
#include "fontfix-iso8859-5.c"
#include "fontosd-iso8859-5.c"
#include "fontsml-iso8859-5.c"
#include "fontfix-iso8859-7.c"
#include "fontosd-iso8859-7.c"
#include "fontsml-iso8859-7.c"
#include "fontfix-iso8859-13.c"
#include "fontosd-iso8859-13.c"
#include "fontsml-iso8859-13.c"
#include "fontfix-iso8859-15.c"
#include "fontosd-iso8859-15.c"
#include "fontsml-iso8859-15.c"
// --- cFont -----------------------------------------------------------------
static const void *const FontData[eDvbCodeSize][eDvbFontSize] = {
{ FontOsd_iso8859_1, FontFix_iso8859_1, FontSml_iso8859_1 },
{ FontOsd_iso8859_2, FontFix_iso8859_2, FontSml_iso8859_2 },
{ FontOsd_iso8859_5, FontFix_iso8859_5, FontSml_iso8859_5 },
{ FontOsd_iso8859_7, FontFix_iso8859_7, FontSml_iso8859_7 },
{ FontOsd_iso8859_13, FontFix_iso8859_13, FontSml_iso8859_13 },
{ FontOsd_iso8859_15, FontFix_iso8859_15, FontSml_iso8859_15 },
};
static const char *FontCode[eDvbCodeSize] = {
"iso8859-1",
"iso8859-2",
"iso8859-5",
"iso8859-7",
"iso8859-13",
"iso8859-15",
};
eDvbCode cFont::code = code_iso8859_1;
cFont *cFont::fonts[eDvbFontSize] = { NULL };
cFont::cFont(const void *Data)
{
SetData(Data);
}
void cFont::SetData(const void *Data)
{
if (Data) {
height = ((tCharData *)Data)->height;
for (int i = 0; i < NUMCHARS; i++)
data[i] = (tCharData *)&((tPixelData *)Data)[(i < 32 ? 0 : i - 32) * (height + 2)];
}
else
height = 0;
}
int cFont::Width(const char *s) const
{
int w = 0;
while (s && *s)
w += Width(*s++);
return w;
}
int cFont::Height(const char *s) const
{
int h = 0;
if (s && *s)
h = height; // all characters have the same height!
return h;
}
bool cFont::SetCode(const char *Code)
{
for (int i = 0; i < eDvbCodeSize; i++) {
if (strcmp(Code, FontCode[i]) == 0) {
SetCode(eDvbCode(i));
return true;
}
}
return false;
}
void cFont::SetCode(eDvbCode Code)
{
if (code != Code) {
code = Code;
for (int i = 0; i < eDvbFontSize; i++) {
if (fonts[i])
fonts[i]->SetData(FontData[code][i]);
}
}
}
void cFont::SetFont(eDvbFont Font, const void *Data)
{
delete fonts[Font];
fonts[Font] = new cFont(Data ? Data : FontData[code][Font]);
}
const cFont *cFont::GetFont(eDvbFont Font)
{
if (Setup.UseSmallFont == 0 && Font == fontSml)
Font = fontOsd;
else if (Setup.UseSmallFont == 2 && Font == fontOsd)
Font = fontSml;
if (!fonts[Font])
SetFont(Font);
return fonts[Font];
}
// --- cTextWrapper ----------------------------------------------------------
cTextWrapper::cTextWrapper(void)
{
text = eol = NULL;
lines = 0;
lastLine = -1;
}
cTextWrapper::cTextWrapper(const char *Text, const cFont *Font, int Width)
{
text = NULL;
Set(Text, Font, Width);
}
cTextWrapper::~cTextWrapper()
{
free(text);
}
void cTextWrapper::Set(const char *Text, const cFont *Font, int Width)
{
free(text);
text = Text ? strdup(Text) : NULL;
eol = NULL;
lines = 0;
lastLine = -1;
if (!text)
return;
lines = 1;
if (Width <= 0)
return;
char *Blank = NULL;
char *Delim = NULL;
int w = 0;
stripspace(text); // strips trailing newlines
for (char *p = text; *p; ) {
if (*p == '\n') {
lines++;
w = 0;
Blank = Delim = NULL;
p++;
continue;
}
else if (isspace(*p))
Blank = p;
int cw = Font->Width(*p);
if (w + cw > Width) {
if (Blank) {
*Blank = '\n';
p = Blank;
continue;
}
else {
// Here's the ugly part, where we don't have any whitespace to
// punch in a newline, so we need to make room for it:
if (Delim)
p = Delim + 1; // let's fall back to the most recent delimiter
char *s = MALLOC(char, strlen(text) + 2); // The additional '\n' plus the terminating '\0'
int l = p - text;
strncpy(s, text, l);
s[l] = '\n';
strcpy(s + l + 1, p);
free(text);
text = s;
p = text + l;
continue;
}
}
else
w += cw;
if (strchr("-.,:;!?_", *p)) {
Delim = p;
Blank = NULL;
}
p++;
}
}
const char *cTextWrapper::Text(void)
{
if (eol) {
*eol = '\n';
eol = NULL;
}
return text;
}
const char *cTextWrapper::GetLine(int Line)
{
char *s = NULL;
if (Line < lines) {
if (eol) {
*eol = '\n';
if (Line == lastLine + 1)
s = eol + 1;
eol = NULL;
}
if (!s) {
s = text;
for (int i = 0; i < Line; i++) {
s = strchr(s, '\n');
if (s)
s++;
else
break;
}
}
if (s) {
if ((eol = strchr(s, '\n')) != NULL)
*eol = 0;
}
lastLine = Line;
}
return s;
}