1
0
mirror of https://github.com/VDR4Arch/vdr.git synced 2023-10-10 13:36:52 +02:00

Faster OSD by using bitmap

This commit is contained in:
Klaus Schmidinger 2000-10-03 10:34:48 +02:00
parent b4faf3787a
commit 6a50f37f25
17 changed files with 7558 additions and 75 deletions

View File

@ -204,6 +204,11 @@ Video Disk Recorder Revision History
is no stdin in daemon mode, so KBD makes no sense - plus it sometimes
crashed).
2000-09-21: Version 0.65
2000-10-01: Version 0.65
- Modified LIRC interface to better handle repeat function (by Carsten Koch).
- Faster OSD by first writing into a bitmap and then sending the entire bitmap
to the DVB driver at once (requires the patch 'dvb.c.071.diff' to be applied
against the version 0.71 DVB driver file 'dvb.c').
- When switching channels the channel is now immediately displayed, and the
current/next information is shown as soon as it becomes available.

19
INSTALL
View File

@ -15,18 +15,22 @@ If you have the DVB driver source in a different location
you will have to change the definition of DVBDIR in the
Makefile.
This program requires the card driver version 0.05 or higher
to work properly. If you are using driver version 0.7 you need
to load the dvb.o module with option outstream=0, so your insmod
statement should read 'insmod dvb.o outstream=0'. This is currently
necessary because 'vdr' works with AV_PES data and will change
once it has been modified to work directly with MPEG2.
This program requires the card driver version 0.71 or higher
to work properly. Currently you need to load the dvb.o module with
option outstream=0, so your insmod statement should read
'insmod dvb.o outstream=0'. This is necessary because 'vdr' works
with AV_PES data and will change once it has been modified to work
directly with MPEG2. You also need to apply the patch 'dvb.c.071.diff'
for the On Screen Display to work properly.
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
installed.
IMPORTANT: See "Configuration files" below for information on how
========= to set up the configuration files at the proper location!
The 'vdr' program can be controlled via the PC keyboard or
an infrared remote control unit. Define the REMOTE macro to one of the
following values 'make' call to activate the respective control mode:
@ -115,7 +119,8 @@ Configuration files:
There are three configuration files that hold information about
channels, remote control keys and timers. By default these files are
assumed to be located in the video directory, but a different directory
can be used with the '-c' option.
can be used with the '-c' option. For starters just copy all *.conf files from
the VDR directory into your video directory.
The configuration files can be edited with any text editor, or will be written
by the 'vdr' program if any changes are made inside the on-screen menus.

View File

@ -4,12 +4,15 @@
# See the main source file 'vdr.c' for copyright information and
# how to reach the author.
#
# $Id: Makefile 1.11 2000/09/20 17:01:57 kls Exp $
# $Id: Makefile 1.12 2000/10/01 14:27:12 kls Exp $
DVBDIR = ../DVB
INCLUDES = -I$(DVBDIR)/driver
OBJS = config.o dvbapi.o eit.o interface.o menu.o osd.o recording.o remote.o svdrp.o tools.o vdr.o videodir.o
OBJS = config.o dvbapi.o dvbosd.o eit.o font.o interface.o menu.o osd.o\
recording.o remote.o svdrp.o tools.o vdr.o videodir.o
OSDFONT = -adobe-helvetica-medium-r-normal--23-*-100-100-p-*-iso8859-1
ifndef REMOTE
REMOTE = KBD
@ -21,26 +24,52 @@ ifdef DEBUG_OSD
DEFINES += -DDEBUG_OSD
endif
all: vdr
font: genfontfile fontosd.c
@echo "font file created."
# Implicit rules:
%.o: %.c
g++ -g -O2 -Wall -m486 -c $(DEFINES) $(INCLUDES) $<
all: vdr
# Dependencies:
config.o : config.c config.h dvbapi.h eit.h interface.h svdrp.h tools.h
dvbapi.o : dvbapi.c config.h dvbapi.h interface.h svdrp.h tools.h videodir.h
config.o : config.c config.h dvbapi.h dvbosd.h eit.h font.h interface.h svdrp.h tools.h
dvbapi.o : dvbapi.c config.h dvbapi.h dvbosd.h font.h interface.h svdrp.h tools.h videodir.h
dvbosd.o : dvbosd.c dvbosd.h font.h tools.h
eit.o : eit.c eit.h tools.h
interface.o: interface.c config.h dvbapi.h eit.h interface.h remote.h svdrp.h tools.h
menu.o : menu.c config.h dvbapi.h interface.h menu.h osd.h recording.h svdrp.h tools.h
osd.o : osd.c config.h dvbapi.h interface.h osd.h svdrp.h tools.h
recording.o: recording.c config.h dvbapi.h interface.h recording.h svdrp.h tools.h videodir.h
remote.o : remote.c config.h dvbapi.h remote.h tools.h
svdrp.o : svdrp.c config.h dvbapi.h interface.h svdrp.h tools.h
font.o : font.c font.h fontosd.c tools.h
interface.o: interface.c config.h dvbapi.h dvbosd.h eit.h font.h interface.h remote.h svdrp.h tools.h
menu.o : menu.c config.h dvbapi.h dvbosd.h font.h interface.h menu.h osd.h recording.h svdrp.h tools.h
osd.o : osd.c config.h dvbapi.h dvbosd.h font.h interface.h osd.h svdrp.h tools.h
recording.o: recording.c config.h dvbapi.h dvbosd.h font.h interface.h recording.h svdrp.h tools.h videodir.h
remote.o : remote.c config.h dvbapi.h dvbosd.h font.h remote.h tools.h
svdrp.o : svdrp.c config.h dvbapi.h dvbosd.h font.h interface.h svdrp.h tools.h
tools.o : tools.c tools.h
vdr.o : vdr.c config.h dvbapi.h interface.h menu.h osd.h recording.h svdrp.h tools.h videodir.h
vdr.o : vdr.c config.h dvbapi.h dvbosd.h font.h interface.h menu.h osd.h recording.h svdrp.h tools.h videodir.h
videodir.o : videodir.c tools.h videodir.h
# The main program:
vdr: $(OBJS)
g++ -g -O2 $(OBJS) -lncurses -ljpeg -o vdr
# The font file:
fontosd.c:
genfontfile "cFont::tPixelData FontOsd" $(OSDFONT) > $@
# The font file generator:
genfontfile.o: genfontfile.c
gcc -O2 -c $<
genfontfile: genfontfile.o
gcc -o $@ -L/usr/X11R6/lib $< -lX11
# Housekeeping:
clean:
-rm $(OBJS) vdr
-rm -f $(OBJS) vdr genfontfile genfontfile.o
CLEAN: clean
-rm -f fontosd.c

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: config.h 1.21 2000/09/17 09:08:13 kls Exp $
* $Id: config.h 1.22 2000/10/01 14:14:18 kls Exp $
*/
#ifndef __CONFIG_H
@ -17,7 +17,7 @@
#include "dvbapi.h"
#include "tools.h"
#define VDRVERSION "0.64"
#define VDRVERSION "0.65"
#define MaxBuffer 10000

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: dvbapi.c 1.27 2000/09/17 12:45:55 kls Exp $
* $Id: dvbapi.c 1.28 2000/10/03 10:13:51 kls Exp $
*/
#include "dvbapi.h"
@ -19,6 +19,7 @@ extern "C" {
#include <sys/stat.h>
#include <sys/time.h>
#include <unistd.h>
#include "dvbapi.h"
#include "interface.h"
#include "tools.h"
#include "videodir.h"
@ -1087,6 +1088,8 @@ cDvbApi::cDvbApi(const char *FileName)
start_color();
leaveok(stdscr, true);
window = NULL;
#else
osd = NULL;
#endif
lastProgress = lastTotal = -1;
replayTitle = NULL;
@ -1488,8 +1491,9 @@ void cDvbApi::Open(int w, int h)
d *= lineHeight;
int x = (720 - MenuColumns * charWidth) / 2; //TODO PAL vs. NTSC???
int y = (576 - MenuLines * lineHeight) / 2 + d;
Cmd(OSD_Open, 4, x, y, x + w - 1, y + h - 1);
osd = new cDvbOsd(videoDev, x, y, x + w - 1, y + h - 1, 4);
#define SETCOLOR(n, r, g, b, o) Cmd(OSD_SetColor, n, r, g, b, o)
SETCOLOR(clrTransparent, 0x00, 0x00, 0x00, 0);
#endif
SETCOLOR(clrBackground, 0x00, 0x00, 0x00, 127); // background 50% gray
SETCOLOR(clrBlack, 0x00, 0x00, 0x00, 255);
@ -1512,7 +1516,8 @@ void cDvbApi::Close(void)
window = 0;
}
#else
Cmd(OSD_Close);
delete osd;
osd = NULL;
#endif
lastProgress = lastTotal = -1;
}
@ -1523,7 +1528,7 @@ void cDvbApi::Clear(void)
SetColor(clrBackground, clrBackground);
Fill(0, 0, cols, rows, clrBackground);
#else
Cmd(OSD_Clear);
osd->Clear();
#endif
}
@ -1539,7 +1544,7 @@ void cDvbApi::Fill(int x, int y, int w, int h, eDvbColor color)
}
wsyncup(window); // shouldn't be necessary because of 'syncok()', but w/o it doesn't work
#else
Cmd(OSD_FillBlock, color, x * charWidth, y * lineHeight, (x + w) * charWidth - 1, (y + h) * lineHeight - 1);
osd->Fill(x * charWidth, y * lineHeight, (x + w) * charWidth - 1, (y + h) * lineHeight - 1, color);
#endif
}
@ -1557,7 +1562,15 @@ void cDvbApi::Text(int x, int y, const char *s, eDvbColor colorFg, eDvbColor col
wmove(window, y, x); // ncurses wants 'y' before 'x'!
waddstr(window, s);
#else
Cmd(OSD_Text, (int(colorBg) << 16) | colorFg, x * charWidth, y * lineHeight, 1, 0, s);
osd->Text(x * charWidth, y * lineHeight, s, colorFg, colorBg);
#endif
}
void cDvbApi::Flush(void)
{
#ifndef DEBUG_OSD
if (osd)
osd->Flush();
#endif
}
@ -1567,11 +1580,13 @@ bool cDvbApi::ShowProgress(bool Initial)
if (GetIndex(&Current, &Total)) {
if (Initial) {
Clear();
if (replayTitle)
Text(0, 0, replayTitle);
}
if (Total != lastTotal)
Text(-7, 2, cIndexFile::Str(Total));
Flush();
#ifdef DEBUG_OSD
int p = cols * Current / Total;
Fill(0, 1, p, 1, clrGreen);
@ -1597,12 +1612,14 @@ bool cDvbApi::ShowProgress(bool Initial)
color = clrWhite;
}
if (lastProgress < 0)
Cmd(OSD_FillBlock, clrWhite, 0, y1, w - 1, y2);
Cmd(OSD_FillBlock, color, x1, y1, x2, y2);
osd->Fill(0, y1, w - 1, y2, clrWhite);
osd->Fill(x1, y1, x2, y2, color);
lastProgress = p;
}
Flush();
#endif
Text(0, 2, cIndexFile::Str(Current));
Flush();
lastTotal = Total;
return true;
}

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: dvbapi.h 1.16 2000/09/17 12:15:05 kls Exp $
* $Id: dvbapi.h 1.17 2000/10/01 14:28:49 kls Exp $
*/
#ifndef __DVBAPI_H
@ -20,6 +20,7 @@ typedef unsigned char __u8;
#endif
#include <stdio.h>
#include <dvb.h>
#include "dvbosd.h"
// Overlay facilities
#define MAXCLIPRECTS 100
@ -30,22 +31,6 @@ typedef struct CRect {
#define MenuLines 15
#define MenuColumns 40
enum eDvbColor { clrBackground,
#ifndef DEBUG_OSD
clrOBSOLETE, //FIXME apparently color '1' can't be used as FgColor with e.g. clrRed as BgColor???
clrBlack,
#else
clrBlack = clrBackground,
#endif
clrRed,
clrGreen,
clrYellow,
clrBlue,
clrMagenta,
clrCyan,
clrWhite,
};
class cDvbApi {
private:
int videoDev;
@ -106,6 +91,8 @@ private:
enum { MaxColorPairs = 16 };
int colorPairs[MaxColorPairs];
void SetColor(eDvbColor colorFg, eDvbColor colorBg = clrBackground);
#else
cDvbOsd *osd;
#endif
int cols, rows;
void Cmd(OSD_Command cmd, int color = 0, int x0 = 0, int y0 = 0, int x1 = 0, int y1 = 0, const void *data = NULL);
@ -116,6 +103,7 @@ public:
void Fill(int x, int y, int w, int h, eDvbColor color = clrBackground);
void ClrEol(int x, int y, eDvbColor color = clrBackground);
void Text(int x, int y, const char *s, eDvbColor colorFg = clrWhite, eDvbColor colorBg = clrBackground);
void Flush(void);
// Progress Display facilities

175
dvbosd.c Normal file
View File

@ -0,0 +1,175 @@
/*
* dvbosd.c: Interface to the DVB On Screen Display
*
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: dvbosd.c 1.1 2000/10/03 10:10:28 kls Exp $
*/
#include "dvbosd.h"
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/unistd.h>
#include "tools.h"
// --- cBitmap ---------------------------------------------------------------
cBitmap::cBitmap(int Width, int Height)
{
width = Width;
height = Height;
bitmap = NULL;
font = NULL;
if (width > 0 && height > 0) {
bitmap = new char[width * height];
if (bitmap) {
Clean();
memset(bitmap, clrTransparent, width * height);
SetFont(fontOsd);
}
else
esyslog(LOG_ERR, "ERROR: can't allocate bitmap!");
}
else
esyslog(LOG_ERR, "ERROR: illegal bitmap parameters (%d, %d)!", width, height);
}
cBitmap::~cBitmap()
{
delete font;
delete bitmap;
}
void cBitmap::SetFont(eDvbFont Font)
{
delete font;
font = new cFont(Font);
}
bool cBitmap::Dirty(void)
{
return dirtyX2 >= 0;
}
void cBitmap::Clean(void)
{
dirtyX1 = width;
dirtyY1 = height;
dirtyX2 = -1;
dirtyY2 = -1;
}
void cBitmap::SetPixel(int x, int y, eDvbColor Color)
{
if (bitmap) {
if (0 <= x && x < width && 0 <= y && y < height) {
if (bitmap[width * y + x] != Color) {
bitmap[width * y + x] = Color;
if (dirtyX1 > x) dirtyX1 = x;
if (dirtyY1 > y) dirtyY1 = y;
if (dirtyX2 < x) dirtyX2 = x;
if (dirtyY2 < y) dirtyY2 = y;
}
}
}
}
void cBitmap::Text(int x, int y, const char *s, eDvbColor ColorFg, eDvbColor ColorBg)
{
if (bitmap) {
int h = font->Height(s);
while (s && *s) {
const cFont::tCharData *CharData = font->CharData(*s++);
for (int row = 0; row < h; row++) {
cFont::tPixelData PixelData = CharData->lines[row];
for (int col = CharData->width; col-- > 0; ) {
SetPixel(x + col, y + row, (PixelData & 1) ? ColorFg : ColorBg);
PixelData >>= 1;
}
}
x += CharData->width;
}
}
}
void cBitmap::Fill(int x1, int y1, int x2, int y2, eDvbColor Color)
{
if (bitmap) {
for (int y = y1; y <= y2; y++)
for (int x = x1; x <= x2; x++)
SetPixel(x, y, Color);
}
}
void cBitmap::Clear(void)
{
Fill(0, 0, width - 1, height - 1, clrBackground);
}
// --- cDvbOsd ---------------------------------------------------------------
cDvbOsd::cDvbOsd(int VideoDev, int x1, int y1, int x2, int y2, int Bpp)
:cBitmap(x2 - x1 + 1, y2 - y1 + 1)
{
videoDev = VideoDev;
if (videoDev >= 0)
Cmd(OSD_Open, Bpp, x1, y1, x2, y2);
else
esyslog(LOG_ERR, "ERROR: illegal video device handle (%d)!", videoDev);
}
cDvbOsd::~cDvbOsd()
{
if (videoDev >= 0)
Cmd(OSD_Close);
}
void cDvbOsd::Cmd(OSD_Command cmd, int color, int x0, int y0, int x1, int y1, const void *data)
{
if (videoDev >= 0) {
struct drawcmd dc;
dc.cmd = cmd;
dc.color = color;
dc.x0 = x0;
dc.y0 = y0;
dc.x1 = x1;
dc.y1 = y1;
dc.data = (void *)data;
ioctl(videoDev, VIDIOCSOSDCOMMAND, &dc);
usleep(10); // XXX Workaround for a driver bug (cInterface::DisplayChannel() displayed texts at wrong places
// XXX and sometimes the OSD was no longer displayed).
// XXX Increase the value if the problem still persists on your particular system.
// TODO Check if this is still necessary with driver versions after 0.7.
}
}
void cDvbOsd::Flush(void)
{
if (Dirty()) {
//XXX Workaround: apparently the bitmap sent to the driver always has to be a multiple
//XXX of 8 bits wide, and (dx * dy) also has to be a multiple of 8.
//TODO Fix driver (should be able to handle any size bitmaps!)
while ((dirtyX1 > 0 || dirtyX2 < width - 1) && ((dirtyX2 - dirtyX1) & 7) != 7) {
if (dirtyX2 < width - 1)
dirtyX2++;
else if (dirtyX1 > 0)
dirtyX1--;
}
while ((dirtyY1 > 0 || dirtyY2 < height - 1) && (((dirtyX2 - dirtyX1 + 1) * (dirtyY2 - dirtyY1 + 1) / 2) & 7) != 0) {
if (dirtyY2 < height - 1)
dirtyY2++;
else if (dirtyY1 > 0)
dirtyY1--;
}
while ((dirtyX1 > 0 || dirtyX2 < width - 1) && (((dirtyX2 - dirtyX1 + 1) * (dirtyY2 - dirtyY1 + 1) / 2) & 7) != 0) {
if (dirtyX2 < width - 1)
dirtyX2++;
else if (dirtyX1 > 0)
dirtyX1--;
}
Cmd(OSD_SetBlock, width, dirtyX1, dirtyY1, dirtyX2, dirtyY2, &bitmap[dirtyY1 * width + dirtyX1]);
Clean();
}
}

74
dvbosd.h Normal file
View File

@ -0,0 +1,74 @@
/*
* dvbosd.h: Interface to the DVB On Screen Display
*
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: dvbosd.h 1.1 2000/10/01 15:00:00 kls Exp $
*/
#ifndef __DVBOSD_H
#define __DVBOSD_H
// FIXME: these should be defined in ../DVB/driver/dvb.h!!!
typedef unsigned int __u32;
typedef unsigned short __u16;
typedef unsigned char __u8;
#if defined(DEBUG_OSD) || defined(REMOTE_KBD)
#include <ncurses.h>
#endif
#include <stdio.h>
#include <dvb.h>
#include "font.h"
enum eDvbColor {
#ifndef DEBUG_OSD
clrTransparent,
#endif
clrBackground,
#ifdef DEBUG_OSD
clrTransparent = clrBackground,
clrBlack = clrBackground,
#else
clrBlack,
#endif
clrRed,
clrGreen,
clrYellow,
clrBlue,
clrMagenta,
clrCyan,
clrWhite,
};
class cBitmap {
private:
cFont *font;
protected:
int width, height;
char *bitmap;
int dirtyX1, dirtyY1, dirtyX2, dirtyY2;
void Clean(void);
public:
cBitmap(int Width, int Height);
virtual ~cBitmap();
void SetFont(eDvbFont Font);
bool Dirty(void);
void SetPixel(int x, int y, eDvbColor Color);
void Text(int x, int y, const char *s, eDvbColor ColorFg = clrWhite, eDvbColor ColorBg = clrBackground);
void Fill(int x1, int y1, int x2, int y2, eDvbColor Color);
void Clear(void);
};
class cDvbOsd : public cBitmap {
private:
int videoDev;
void Cmd(OSD_Command cmd, int color = 0, int x0 = 0, int y0 = 0, int x1 = 0, int y1 = 0, const void *data = NULL);
public:
cDvbOsd(int VideoDev, int x1, int y1, int x2, int y2, int Bpp);
~cDvbOsd();
void Flush(void);
};
#endif //__DVBOSD_H

6
eit.c
View File

@ -13,7 +13,7 @@
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* $Id: eit.c 1.3 2000/09/17 15:23:05 kls Exp $
* $Id: eit.c 1.4 2000/10/01 14:09:05 kls Exp $
***************************************************************************/
#include "eit.h"
@ -424,9 +424,8 @@ int cEIT::SetProgramNumber(unsigned short pnr)
evtRunning.bIsValid = false;
evtNext.bIsValid = false;
uProgramNumber = pnr;
return GetEIT();
}
return (IsValid() ? 1 : -1);
return 1;
}
/** retrieves the string for the running title */
@ -503,6 +502,7 @@ char * cEIT::GetNextTime()
/** */
bool cEIT::IsValid()
{
GetEIT();
return (evtRunning.bIsValid && evtNext.bIsValid);
}

41
font.c Normal file
View File

@ -0,0 +1,41 @@
/*
* 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.1 2000/10/01 15:01:49 kls Exp $
*/
#include "font.h"
#include "tools.h"
#include "fontosd.c"
cFont::cFont(eDvbFont Font)//XXX
{
switch (Font) {
default:
case fontOsd: for (int i = 0; i < NUMCHARS; i++)
data[i] = (tCharData *)&FontOsd[i < 32 ? 0 : i - 32];
break;
// TODO others...
}
}
int cFont::Width(const char *s)
{
int w = 0;
while (s && *s)
w += Width(*s++);
return w;
}
int cFont::Height(const char *s)
{
int h = 0;
if (s && *s)
h = Height(*s); // all characters have the same height!
return h;
}

40
font.h Normal file
View File

@ -0,0 +1,40 @@
/*
* font.h: 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.h 1.1 2000/10/01 15:00:35 kls Exp $
*/
#ifndef __FONT_H
#define __FONT_H
enum eDvbFont {
fontOsd,
/* TODO as soon as we have the font files...
fontTtxSmall,
fontTtxLarge,
*/
};
class cFont {
public:
enum { NUMCHARS = 256 };
typedef unsigned long tPixelData;
struct tCharData {
tPixelData width, height;
tPixelData lines[1];
};
private:
const tCharData *data[NUMCHARS];
public:
cFont(eDvbFont Font);
int Width(unsigned char c) { return data[c]->width; }
int Width(const char *s);
int Height(unsigned char c) { return data[c]->height; }
int Height(const char *s);
const tCharData *CharData(unsigned char c) { return data[c]; }
};
#endif //__FONT_H

6722
fontosd.c Normal file

File diff suppressed because it is too large Load Diff

378
genfontfile.c Normal file
View File

@ -0,0 +1,378 @@
/* Copyright (c) Mark J. Kilgard, 1997. */
/* This program is freely distributable without licensing fees and is
provided without guarantee or warrantee expressed or implied. This
program is -not- in the public domain. */
/* X compile line: cc -o gentexfont gentexfont.c -lX11 */
/* 2000-10-01: Stripped down the original code to get a simple bitmap C-code generator */
/* for use with the VDR project (see http://www.cadsoft.de/people/kls/vdr) */
/* Renamed the file 'genfontfile.c' since it no longer generates 'tex' data */
/* Klaus Schmidinger (kls@cadsoft.de) */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <math.h>
typedef struct {
unsigned short c; /* Potentially support 16-bit glyphs. */
unsigned char width;
unsigned char height;
signed char xoffset;
signed char yoffset;
signed char advance;
char dummy; /* Space holder for alignment reasons. */
short x;
short y;
} TexGlyphInfo;
typedef struct {
short width;
short height;
short xoffset;
short yoffset;
short advance;
unsigned char *bitmap;
} PerGlyphInfo, *PerGlyphInfoPtr;
typedef struct {
int min_char;
int max_char;
int max_ascent;
int max_descent;
PerGlyphInfo glyph[1];
} FontInfo, *FontInfoPtr;
Display *dpy;
FontInfoPtr fontinfo;
/* #define REPORT_GLYPHS */
#ifdef REPORT_GLYPHS
#define DEBUG_GLYPH4(msg,a,b,c,d) printf(msg,a,b,c,d)
#define DEBUG_GLYPH(msg) printf(msg)
#else
#define DEBUG_GLYPH4(msg,a,b,c,d) { /* nothing */ }
#define DEBUG_GLYPH(msg) { /* nothing */ }
#endif
#define MAX_GLYPHS_PER_GRAB 512 /* this is big enough for 2^9 glyph
character sets */
FontInfoPtr
SuckGlyphsFromServer(Display * dpy, Font font)
{
Pixmap offscreen;
XFontStruct *fontinfo;
XImage *image;
GC xgc;
XGCValues values;
int numchars;
int width, height, pixwidth;
int i, j;
XCharStruct *charinfo;
XChar2b character;
unsigned char *bitmapData;
int x, y;
int spanLength;
int charWidth, charHeight, maxSpanLength;
int grabList[MAX_GLYPHS_PER_GRAB];
int glyphsPerGrab = MAX_GLYPHS_PER_GRAB;
int numToGrab, thisglyph;
FontInfoPtr myfontinfo;
fontinfo = XQueryFont(dpy, font);
if (!fontinfo)
return NULL;
numchars = fontinfo->max_char_or_byte2 - fontinfo->min_char_or_byte2 + 1;
if (numchars < 1)
return NULL;
myfontinfo = (FontInfoPtr) malloc(sizeof(FontInfo) + (numchars - 1) * sizeof(PerGlyphInfo));
if (!myfontinfo)
return NULL;
myfontinfo->min_char = fontinfo->min_char_or_byte2;
myfontinfo->max_char = fontinfo->max_char_or_byte2;
myfontinfo->max_ascent = fontinfo->max_bounds.ascent;
myfontinfo->max_descent = fontinfo->max_bounds.descent;
width = fontinfo->max_bounds.rbearing - fontinfo->min_bounds.lbearing;
height = fontinfo->max_bounds.ascent + fontinfo->max_bounds.descent;
maxSpanLength = (width + 7) / 8;
/* Be careful determining the width of the pixmap; the X protocol allows
pixmaps of width 2^16-1 (unsigned short size) but drawing coordinates
max out at 2^15-1 (signed short size). If the width is too large, we
need to limit the glyphs per grab. */
if ((glyphsPerGrab * 8 * maxSpanLength) >= (1 << 15)) {
glyphsPerGrab = (1 << 15) / (8 * maxSpanLength);
}
pixwidth = glyphsPerGrab * 8 * maxSpanLength;
offscreen = XCreatePixmap(dpy, RootWindow(dpy, DefaultScreen(dpy)),
pixwidth, height, 1);
values.font = font;
values.background = 0;
values.foreground = 0;
xgc = XCreateGC(dpy, offscreen, GCFont | GCBackground | GCForeground, &values);
XFillRectangle(dpy, offscreen, xgc, 0, 0, 8 * maxSpanLength * glyphsPerGrab, height);
XSetForeground(dpy, xgc, 1);
numToGrab = 0;
if (fontinfo->per_char == NULL) {
charinfo = &(fontinfo->min_bounds);
charWidth = charinfo->rbearing - charinfo->lbearing;
charHeight = charinfo->ascent + charinfo->descent;
spanLength = (charWidth + 7) / 8;
}
for (i = 0; i < numchars; i++) {
if (fontinfo->per_char != NULL) {
charinfo = &(fontinfo->per_char[i]);
charWidth = charinfo->rbearing - charinfo->lbearing;
charHeight = charinfo->ascent + charinfo->descent;
if (charWidth == 0 || charHeight == 0) {
/* Still must move raster pos even if empty character */
myfontinfo->glyph[i].width = 0;
myfontinfo->glyph[i].height = 0;
myfontinfo->glyph[i].xoffset = 0;
myfontinfo->glyph[i].yoffset = 0;
myfontinfo->glyph[i].advance = charinfo->width;
myfontinfo->glyph[i].bitmap = NULL;
goto PossiblyDoGrab;
}
}
grabList[numToGrab] = i;
/* XXX is this right for large fonts? */
character.byte2 = (i + fontinfo->min_char_or_byte2) & 255;
character.byte1 = (i + fontinfo->min_char_or_byte2) >> 8;
/* XXX we could use XDrawImageString16 which would also paint the backing
rectangle but X server bugs in some scalable font rasterizers makes it
more effective to do XFillRectangles to clear the pixmap and
XDrawImage16 for the text. */
XDrawString16(dpy, offscreen, xgc,
-charinfo->lbearing + 8 * maxSpanLength * numToGrab,
charinfo->ascent, &character, 1);
numToGrab++;
PossiblyDoGrab:
if (numToGrab >= glyphsPerGrab || i == numchars - 1) {
image = XGetImage(dpy, offscreen,
0, 0, pixwidth, height, 1, XYPixmap);
for (j = 0; j < numToGrab; j++) {
thisglyph = grabList[j];
if (fontinfo->per_char != NULL) {
charinfo = &(fontinfo->per_char[thisglyph]);
charWidth = charinfo->rbearing - charinfo->lbearing;
charHeight = charinfo->ascent + charinfo->descent;
spanLength = (charWidth + 7) / 8;
}
bitmapData = calloc(height * spanLength, sizeof(char));
if (!bitmapData)
goto FreeFontAndReturn;
DEBUG_GLYPH4("index %d, glyph %d (%d by %d)\n",
j, thisglyph + fontinfo->min_char_or_byte2, charWidth, charHeight);
for (y = 0; y < charHeight; y++) {
for (x = 0; x < charWidth; x++) {
/* XXX The algorithm used to suck across the font ensures that
each glyph begins on a byte boundary. In theory this would
make it convienent to copy the glyph into a byte oriented
bitmap. We actually use the XGetPixel function to extract
each pixel from the image which is not that efficient. We
could either do tighter packing in the pixmap or more
efficient extraction from the image. Oh well. */
if (XGetPixel(image, j * maxSpanLength * 8 + x, charHeight - 1 - y)) {
DEBUG_GLYPH("x");
bitmapData[y * spanLength + x / 8] |= (1 << (x & 7));
} else {
DEBUG_GLYPH(" ");
}
}
DEBUG_GLYPH("\n");
}
myfontinfo->glyph[thisglyph].width = charWidth;
myfontinfo->glyph[thisglyph].height = charHeight;
myfontinfo->glyph[thisglyph].xoffset = charinfo->lbearing;
myfontinfo->glyph[thisglyph].yoffset = -charinfo->descent;
myfontinfo->glyph[thisglyph].advance = charinfo->width;
myfontinfo->glyph[thisglyph].bitmap = bitmapData;
}
XDestroyImage(image);
numToGrab = 0;
/* do we need to clear the offscreen pixmap to get more? */
if (i < numchars - 1) {
XSetForeground(dpy, xgc, 0);
XFillRectangle(dpy, offscreen, xgc, 0, 0, 8 * maxSpanLength * glyphsPerGrab, height);
XSetForeground(dpy, xgc, 1);
}
}
}
XFreeGC(dpy, xgc);
XFreePixmap(dpy, offscreen);
return myfontinfo;
FreeFontAndReturn:
XDestroyImage(image);
XFreeGC(dpy, xgc);
XFreePixmap(dpy, offscreen);
for (j = i - 1; j >= 0; j--) {
if (myfontinfo->glyph[j].bitmap)
free(myfontinfo->glyph[j].bitmap);
}
free(myfontinfo);
return NULL;
}
void
printGlyph(FontInfoPtr font, int c)
{
PerGlyphInfoPtr glyph;
unsigned char *bitmapData;
int width, height, spanLength;
int x, y, l;
char buf[1000], *b;
if (c < font->min_char || c > font->max_char) {
fprintf(stderr, "out of range glyph\n");
exit(1);
}
glyph = &font->glyph[c - font->min_char];
bitmapData = glyph->bitmap;
width = glyph->width;
spanLength = (width + 7) / 8;
height = glyph->height;
printf(" { // %d\n", c);
printf(" %d, %d,\n", glyph->advance, font->max_ascent + font->max_descent);
for (y = 0; y < font->max_ascent - glyph->yoffset - height; y++) {
printf(" 0x%08X, // ", 0);
for (x = 0; x < glyph->xoffset + width || x < glyph->advance; x++)
putchar('.');
putchar('\n');
}
for (y = height; y-- > 0;) {
l = 0;
b = buf;
for (x = 0; x < glyph->xoffset; x++)
*b++ = '.';
if (bitmapData) {
for (x = 0; x < width; x++) {
if (bitmapData[y * spanLength + x / 8] & (1 << (x & 7))) {
*b++ = '*';
l |= 1;
}
else
*b++ = '.';
l <<= 1;
}
for (x = 0; x < glyph->advance - width - glyph->xoffset; x++) {
*b++ = '.';
l <<= 1;
}
}
*b = 0;
printf(" 0x%08X, // %s\n", l, buf);
}
for (y = 0; y < font->max_descent + glyph->yoffset; y++) {
printf(" 0x%08X, // ", 0);
for (x = 0; x < glyph->xoffset + width || x < glyph->advance; x++)
putchar('.');
putchar('\n');
}
printf(" },\n");
}
void
getMetric(FontInfoPtr font, int c, TexGlyphInfo * tgi)
{
PerGlyphInfoPtr glyph;
unsigned char *bitmapData;
tgi->c = c;
if (c < font->min_char || c > font->max_char) {
tgi->width = 0;
tgi->height = 0;
tgi->xoffset = 0;
tgi->yoffset = 0;
tgi->dummy = 0;
tgi->advance = 0;
return;
}
glyph = &font->glyph[c - font->min_char];
bitmapData = glyph->bitmap;
if (bitmapData) {
tgi->width = glyph->width;
tgi->height = glyph->height;
tgi->xoffset = glyph->xoffset;
tgi->yoffset = glyph->yoffset;
} else {
tgi->width = 0;
tgi->height = 0;
tgi->xoffset = 0;
tgi->yoffset = 0;
}
tgi->dummy = 0;
tgi->advance = glyph->advance;
}
int
main(int argc, char *argv[])
{
int c;
TexGlyphInfo tgi;
int usageError = 0;
char *varname, *fontname;
XFontStruct *xfont;
int i;
if (argc == 3) {
varname = argv[1];
fontname = argv[2];
}
else
usageError = 1;
if (usageError) {
fprintf(stderr, "\n");
fprintf(stderr, "usage: genfontfile variable_name X_font_name\n");
fprintf(stderr, "\n");
exit(1);
}
dpy = XOpenDisplay(NULL);
if (!dpy) {
fprintf(stderr, "could not open display\n");
exit(1);
}
/* find an OpenGL-capable RGB visual with depth buffer */
xfont = XLoadQueryFont(dpy, fontname);
if (!xfont) {
fprintf(stderr, "could not get load X font: %s\n", fontname);
exit(1);
}
fontinfo = SuckGlyphsFromServer(dpy, xfont->fid);
if (!fontinfo) {
fprintf(stderr, "could not get font glyphs\n");
exit(1);
}
printf("%s[][%d] = {\n", varname, fontinfo->max_ascent + fontinfo->max_descent + 2);
for (c = 32; c < 256; c++) {
getMetric(fontinfo, c, &tgi);
printGlyph(fontinfo, c);
}
printf(" };\n");
return 0;
}

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: interface.c 1.19 2000/09/19 17:41:23 kls Exp $
* $Id: interface.c 1.20 2000/10/02 16:23:53 kls Exp $
*/
#include "interface.h"
@ -69,6 +69,8 @@ unsigned int cInterface::GetCh(bool Wait)
eKeys cInterface::GetKey(bool Wait)
{
if (open)
cDvbApi::PrimaryDvbApi->Flush();
if (SVDRP)
SVDRP->Process();
eKeys Key = keyFromWait != kNone ? keyFromWait : Keys.Get(GetCh(Wait));
@ -84,6 +86,8 @@ void cInterface::PutKey(eKeys Key)
eKeys cInterface::Wait(int Seconds, bool KeepChar)
{
eKeys Key = kNone;
if (open)
cDvbApi::PrimaryDvbApi->Flush();
RcIo.Flush(500);
if (cFile::AnyFileReady(-1, Seconds * 1000))
Key = GetKey();
@ -326,15 +330,8 @@ eKeys cInterface::DisplayChannel(int Number, const char *Name, bool WithInfo)
if (Number)
RcIo.Number(Number);
if (Name && !Recording()) {
char *RunningTitle = "", *RunningSubtitle = "", *NextTitle = "", *NextSubtitle = "";
int Lines = 0;
if (Number && WithInfo && EIT.IsValid()) {
if (*(RunningTitle = EIT.GetRunningTitle())) Lines++;
if (*(RunningSubtitle = EIT.GetRunningSubtitle())) Lines++;
if (*(NextTitle = EIT.GetNextTitle())) Lines++;
if (*(NextSubtitle = EIT.GetNextSubtitle())) Lines++;
}
Open(MenuColumns, Lines + 1);
Open(MenuColumns, 5);
cDvbApi::PrimaryDvbApi->Fill(0, 0, MenuColumns, 1, clrBackground);
int BufSize = MenuColumns + 1;
char buffer[BufSize];
if (Number)
@ -346,10 +343,21 @@ eKeys cInterface::DisplayChannel(int Number, const char *Name, bool WithInfo)
struct tm *now = localtime(&t);
snprintf(buffer, BufSize, "%02d:%02d", now->tm_hour, now->tm_min);
Write(-5, 0, buffer);
cDvbApi::PrimaryDvbApi->Flush();
char *RunningTitle = "", *RunningSubtitle = "", *NextTitle = "", *NextSubtitle = "";
int Lines = 0;
if (Number && WithInfo && EIT.IsValid()) {
if (*(RunningTitle = EIT.GetRunningTitle())) Lines++;
if (*(RunningSubtitle = EIT.GetRunningSubtitle())) Lines++;
if (*(NextTitle = EIT.GetNextTitle())) Lines++;
if (*(NextSubtitle = EIT.GetNextSubtitle())) Lines++;
}
if (Lines > 0) {
const int t = 6;
int w = MenuColumns - t;
int l = 1;
cDvbApi::PrimaryDvbApi->Fill(0, 1, MenuColumns, Lines, clrBackground);
if (*RunningTitle) {
Write(0, l, EIT.GetRunningTime(), clrYellow, clrBackground);
snprintf(buffer, BufSize, "%.*s", w, RunningTitle); Write(t, l, buffer, clrCyan, clrBackground);
@ -367,6 +375,7 @@ eKeys cInterface::DisplayChannel(int Number, const char *Name, bool WithInfo)
if (*NextSubtitle) {
snprintf(buffer, BufSize, "%.*s", w, NextSubtitle); Write(t, l, buffer, clrCyan, clrBackground);
}
cDvbApi::PrimaryDvbApi->Flush();
}
eKeys Key = Wait(5, true);
if (Key == kOk)

View File

@ -1,10 +1,10 @@
/*
* recording.h: Recording file handling
* recording.c: Recording file handling
*
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: recording.c 1.15 2000/07/29 14:08:17 kls Exp $
* $Id: recording.c 1.16 2000/10/03 10:33:40 kls Exp $
*/
#define _GNU_SOURCE

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: tools.c 1.19 2000/09/19 17:55:09 kls Exp $
* $Id: tools.c 1.20 2000/09/29 16:19:28 kls Exp $
*/
#define _GNU_SOURCE
@ -17,7 +17,6 @@
#endif
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <unistd.h>

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: tools.h 1.15 2000/09/17 07:58:19 kls Exp $
* $Id: tools.h 1.16 2000/09/29 16:19:31 kls Exp $
*/
#ifndef __TOOLS_H
@ -13,6 +13,7 @@
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <syslog.h>
#include <sys/stat.h>
#include <sys/types.h>