Logo Search packages:      
Sourcecode: xawtv version File versions  Download package

vbi-x11.c

/*
 * vbi-x11  --  render videotext into X11 drawables
 *
 *   (c) 2002 Gerd Knorr <kraxel@bytesex.org>
 */

#include "config.h"

#ifdef HAVE_ZVBI

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <pthread.h>
#include <iconv.h>
#include <langinfo.h>
#include <sys/types.h>
#include <sys/time.h>

#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <X11/keysym.h>
#include <X11/Intrinsic.h>
#include <X11/StringDefs.h>

#include "atoms.h"
#include "list.h"
#include "vbi-data.h"
#include "vbi-x11.h"

/* --------------------------------------------------------------------- */

struct vbi_font vbi_fonts[] = {
    {
      .label = "Teletext 20",
      .xlfd1 = "-*-teletext-medium-r-normal--20-*-*-*-*-*-iso10646-1",
      .xlfd2 = "-*-teletext-medium-r-normal--40-*-*-*-*-*-iso10646-1",
    },{
      .label = "Teletext 10",
      .xlfd1 = "-*-teletext-medium-r-normal--10-*-*-*-*-*-iso10646-1",
      .xlfd2 = "-*-teletext-medium-r-normal--20-*-*-*-*-*-iso10646-1",
    },{
      .label = "Fixed 18",
      .xlfd1 = "-*-fixed-medium-r-normal--18-*-*-*-*-*-iso10646-1",
    },{
      .label = "Fixed 13",
      .xlfd1 = "-misc-fixed-medium-r-semicondensed--13-*-*-*-*-*-iso10646-1",
    },{
      /* end of list */
    }
};

/* --------------------------------------------------------------------- */
/* render teletext pages                                                 */

static int vbi_render_try_font(Widget shell, struct vbi_window *vw,
                        struct vbi_font *fnt)
{
    if (NULL == vw->xft_font  &&  NULL != fnt->xlfd1) {
      vw->font1 = XLoadQueryFont(XtDisplay(shell), fnt->xlfd1);
      if (NULL != fnt->xlfd2)
          vw->font2 = XLoadQueryFont(XtDisplay(shell), fnt->xlfd2);
      if (NULL != vw->font1) {
          vw->a      = vw->font1->max_bounds.ascent;
          vw->d      = vw->font1->max_bounds.descent;
          vw->w      = vw->font1->max_bounds.width;
          vw->h      = vw->a + vw->d;
          return 0;
      }
    }
    return 1;
}

void vbi_render_free_font(Widget shell, struct vbi_window *vw)
{
#ifdef HAVE_XFT
    if (NULL != vw->xft_font) {
      XftFontClose(XtDisplay(shell),vw->xft_font);
      vw->xft_font = NULL;
    }
#endif
    if (NULL != vw->font1) {
      XFreeFont(XtDisplay(shell),vw->font1);
      vw->font1 = NULL;
    }
    if (NULL != vw->font2) {
      XFreeFont(XtDisplay(shell),vw->font2);
      vw->font2 = NULL;
    }
}

void vbi_render_set_font(Widget shell, struct vbi_window *vw, char *label)
{
#ifdef HAVE_XFT
    FcPattern  *pattern;
    FcResult   rc;
#endif
    int        i;

    /* free old stuff */
    vbi_render_free_font(shell,vw);

    if (NULL != label) {
      /* try core font */
      for (i = 0; vbi_fonts[i].label != NULL; i++) {
          if (0 != strcasecmp(label,vbi_fonts[i].label))
            continue;
          if (0 == vbi_render_try_font(shell, vw, &vbi_fonts[i]))
            return;
      }
      
#ifdef HAVE_XFT
      /* try xft */
      pattern = FcNameParse(label);
      pattern = XftFontMatch(XtDisplay(shell),
                         XScreenNumberOfScreen(XtScreen(shell)),
                         pattern,&rc);
      vw->xft_font = XftFontOpenPattern(XtDisplay(shell), pattern);
      if (vw->xft_font) {
          vw->a = vw->xft_font->ascent;
          vw->d = vw->xft_font->descent;
          vw->w = vw->xft_font->max_advance_width;
          vw->h = vw->xft_font->height;
          return;
      }
#endif
    }

    /* walk through the whole list as fallback */
    for (i = 0; vbi_fonts[i].label != NULL; i++) {
      if (0 == vbi_render_try_font(shell, vw, &vbi_fonts[i]))
          return;
    }
    fprintf(stderr,"Oops: can't load any font\n");
    exit(1);
}

struct vbi_window*
vbi_render_init(Widget shell, Widget tt, struct vbi_state *vbi)
{
    struct vbi_window *vw;
    XColor color,dummy;
    int i;

    vw = malloc(sizeof(*vw));
    memset(vw,0,sizeof(*vw));
    
    vw->shell = shell;
    vw->tt    = tt;
    vw->vbi   = vbi;
    vw->gc    = XCreateGC(XtDisplay(shell),
                    RootWindowOfScreen(XtScreen(shell)),
                    0, NULL);

    XtVaGetValues(tt, XtNcolormap, &vw->cmap, NULL);
    for (i = 0; i < 8; i++) {
#ifdef HAVE_XFT
      XftColorAllocName(XtDisplay(shell),
                    DefaultVisualOfScreen(XtScreen(shell)),
                    vw->cmap, vbi_colors[i], &vw->xft_color[i]);
#endif
      XAllocNamedColor(XtDisplay(shell), vw->cmap, vbi_colors[i],
                   &color, &dummy);
      vw->colors[i] = color.pixel;
    }
    vbi_render_set_font(shell,vw,NULL);

    INIT_LIST_HEAD(&vw->selections);
    return vw;
}

void
vbi_render_line(struct vbi_window *vw, Drawable d, struct vbi_char *ch,
            int y, int top, int left, int right)
{
    XGCValues values;
    XChar2b line[42];
    int x1,x2,i,code,sy;
#ifdef HAVE_XFT
    FcChar32 wline[42];
    XftDraw *xft_draw = NULL;
#endif

    for (x1 = left; x1 < right; x1 = x2) {
      for (x2 = x1; x2 < right; x2++) {
          if (ch[x1].foreground != ch[x2].foreground)
            break;
          if (ch[x1].background != ch[x2].background)
            break;
          if (ch[x1].size != ch[x2].size)
            break;
      }
      sy = 1;
      if (vw->font2) {
          if (ch[x1].size == VBI_DOUBLE_HEIGHT ||
            ch[x1].size == VBI_DOUBLE_SIZE)
            sy = 2;
          if (ch[x1].size == VBI_DOUBLE_HEIGHT2 ||
            ch[x1].size == VBI_DOUBLE_SIZE2)
            continue;
      }

      for (i = x1; i < x2; i++) {
          code = ch[i].unicode;
          if (ch[i].conceal)
            code = ' ';
          if (ch[i].size == VBI_OVER_TOP       ||
            ch[i].size == VBI_OVER_BOTTOM    ||
            ch[i].size == VBI_DOUBLE_HEIGHT2 ||
            ch[i].size == VBI_DOUBLE_SIZE2)
            code = ' ';
          line[i-x1].byte1 = (code >> 8) & 0xff;
          line[i-x1].byte2 =  code       & 0xff;
#ifdef HAVE_XFT
          wline[i-x1] = code;
#endif
      }

      values.function   = GXcopy;
      values.foreground = vw->colors[ch[x1].background & 7];
      XChangeGC(XtDisplay(vw->tt), vw->gc, GCForeground|GCFunction, &values);
      XFillRectangle(XtDisplay(vw->tt), d, 
                   vw->gc, (x1-left)*vw->w, (y-top)*vw->h,
                   vw->w * (x2-x1), vw->h * sy);

      if (vw->xft_font) {
#ifdef HAVE_XFT
          if (NULL == xft_draw)
            xft_draw = XftDrawCreate(XtDisplay(vw->tt), d,
                               DefaultVisualOfScreen(XtScreen(vw->tt)),
                               vw->cmap);
          XftDrawString32(xft_draw, &vw->xft_color[ch[x1].foreground & 7],
                      vw->xft_font,
                      (x1-left)*vw->w, vw->a + (y-top+sy-1)*vw->h,
                      wline, x2-x1);
#endif
      } else {
          values.foreground = vw->colors[ch[x1].foreground & 7];
          values.font = (1 == sy) ? vw->font1->fid : vw->font2->fid;
          XChangeGC(XtDisplay(vw->tt), vw->gc, GCForeground|GCFont, &values);
          XDrawString16(XtDisplay(vw->tt), d, vw->gc,
                    (x1-left)*vw->w, vw->a + (y-top+sy-1)*vw->h,
                    line, x2-x1);
      }
    }
#ifdef HAVE_XFT
    if (NULL != xft_draw)
      XftDrawDestroy(xft_draw);
#endif
}

Pixmap
vbi_export_pixmap(struct vbi_window *vw,
              struct vbi_page *pg, struct vbi_rect *rect)
{
    Pixmap pix;
    vbi_char *ch;
    int y;

    pix = XCreatePixmap(XtDisplay(vw->tt), XtWindow(vw->tt),
                  vw->w * (rect->x2 - rect->x1),
                  vw->h * (rect->y2 - rect->y1),
                  DefaultDepthOfScreen(XtScreen(vw->tt)));
    for (y = rect->y1; y < rect->y2; y++) {
      ch = vw->pg.text + 41*y;
      vbi_render_line(vw,pix,ch,y,rect->y1,rect->x1,rect->x2);
    }
    return pix;
}

#endif /* HAVE_ZVBI */

Generated by  Doxygen 1.6.0   Back to index