Logo Search packages:      
Sourcecode: beryl-plugins version File versions

text.c

/*
 * text.c - adds text image support to beryl.
 * Copyright: (C) 2006 Patrick Niklaus
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 *
 */

#include <string.h>
#include <stdio.h>
#include <stdlib.h>

#include <cairo-xlib-xrender.h>
#include <pango/pango.h>
#include <pango/pangocairo.h>

#include <beryl.h>

#include "beryl-text.h"

#define TEXT_DISPLAY_OPTION_NUM           0

static int displayPrivateIndex;

typedef struct _TextDisplay
{
      CompOption opt[TEXT_DISPLAY_OPTION_NUM];

      FileToImageProc fileToImage;
} TextDisplay;


#define GET_TEXT_DISPLAY(d)                         \
    ((TextDisplay *) (d)->privates[displayPrivateIndex].ptr)

#define TEXT_DISPLAY(d)              \
    TextDisplay *td = GET_TEXT_DISPLAY (d)

#define NUM_OPTIONS(d) (sizeof ((d)->opt) / sizeof (CompOption))


static Bool textFileToImage(CompDisplay *d,
                     const char *path,
                     const char *name,
                     int *width, int *height, int *stride, void **data)
{
      Bool status = FALSE;

      if (path && name &&     strcmp(path, TEXT_ID) == 0)
      {
            cairo_t *cr;
            cairo_surface_t *surface;
            PangoLayout *layout;
            Pixmap pixmap;
            XRenderPictFormat *format;
            CompTextAttrib *text_attrib = (CompTextAttrib*) name; // get it through the name
            int w,h;

            Display *display = d->display;
            Screen *screen = ScreenOfDisplay(display, text_attrib->screen->screenNum);

            if (!screen) {
                  printf("ERROR: Couldn't get screen for %d...\n", 
                              text_attrib->screen->screenNum);
                  return FALSE;
            }

            format = XRenderFindStandardFormat(display, PictStandardARGB32);
            if (!format) {
                  printf("ERROR: Couldn't get format...\n");
                  return FALSE;
            }

            pixmap = XCreatePixmap(display, text_attrib->screen->root, 1, 1, 32);
            if (!pixmap) {
                  printf("ERROR: Couldn't create pixmap...\n");
                  return FALSE;
            }

            surface = cairo_xlib_surface_create_with_xrender_format(
                                    display, pixmap, screen, format, 1, 1);

            if (cairo_surface_status(surface) != CAIRO_STATUS_SUCCESS) {
                  printf("ERROR: Couldn't create surface...\n");
                  XFreePixmap(display, pixmap);
                  return FALSE;
            }

            cr = cairo_create(surface);
            if (cairo_status(cr) != CAIRO_STATUS_SUCCESS) {
                  printf("ERROR: Couldn't create cairo context...\n");
                  XFreePixmap(display, pixmap);
                  return FALSE;
            }

            // init pango
            layout = pango_cairo_create_layout(cr);
            if (!layout) {
                  printf("ERROR: Couldn't create pango layout...\n");
                  XFreePixmap(display, pixmap);
                  return FALSE;
            }

            PangoFontDescription *font = pango_font_description_new();


            pango_font_description_set_family(font, text_attrib->family);
            pango_font_description_set_absolute_size(font, text_attrib->size * PANGO_SCALE);

            pango_font_description_set_style(font, PANGO_STYLE_NORMAL);

            if (text_attrib->style & TEXT_STYLE_BOLD)
                  pango_font_description_set_weight(font, PANGO_WEIGHT_BOLD);

            if (text_attrib->style & TEXT_STYLE_ITALIC)
                  pango_font_description_set_style(font, PANGO_STYLE_ITALIC);

            pango_layout_set_font_description(layout, font);

            if (text_attrib->ellipsize)
                  pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_END);

            pango_layout_set_text(layout, text_attrib->text, -1);

            pango_layout_get_pixel_size(layout, &w, &h);

            w = MIN(text_attrib->maxwidth, w);
            h = MIN(text_attrib->maxheight, h);
            
            // update the size of the pango layout
            pango_layout_set_width(layout, w*PANGO_SCALE);

            cairo_surface_destroy(surface);
            cairo_destroy(cr);
            XFreePixmap(display, pixmap);


            pixmap = XCreatePixmap(display, text_attrib->screen->root, w, h, 32);

            surface = cairo_xlib_surface_create_with_xrender_format(display, pixmap,
                          screen, format, w, h);

            if (cairo_surface_status(surface) != CAIRO_STATUS_SUCCESS) {
                  printf("ERROR: Couldn't create surface...\n");
                  XFreePixmap(display, pixmap);
                  return FALSE;
            }

            cr = cairo_create(surface);
            if (cairo_status(cr) != CAIRO_STATUS_SUCCESS) {
                  printf("ERROR: Couldn't create cairo context...\n");
                  XFreePixmap(display, pixmap);
                  return FALSE;
            }

            pango_cairo_update_layout(cr,layout);

            cairo_save(cr);
            cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR);
            cairo_paint(cr);
            cairo_restore(cr);

            cairo_set_operator(cr, CAIRO_OPERATOR_OVER);

            cairo_set_source_rgba(cr,
                                            text_attrib->color[0] / 65535.0,
                                            text_attrib->color[1] / 65535.0,
                                            text_attrib->color[2] / 65535.0,
                                            text_attrib->color[3] / 65535.0);
            pango_cairo_show_layout(cr, layout);

            g_object_unref(layout);
            cairo_surface_destroy(surface);
            cairo_destroy(cr);
            pango_font_description_free(font);

            *width = w;
            *height = h;
            *data = (void *)pixmap;

            return TRUE;
      }

      TEXT_DISPLAY(d);

      UNWRAP(td, d, fileToImage);
      status = (*d->fileToImage) (d, path, name, width, height, stride, data);
      WRAP(td, d, fileToImage, textFileToImage);

      return status;
}

static void textDisplayInitOptions(TextDisplay *td)
{
      //CompOption *o;
}

static CompOption *textGetDisplayOptions(CompDisplay *display, int *count)
{
      if (display)
      {
            TEXT_DISPLAY(display);

            *count = NUM_OPTIONS(td);
            return td->opt;
      } else {
            TextDisplay *td = malloc(sizeof(TextDisplay));

            textDisplayInitOptions(td);
            *count = NUM_OPTIONS(td);
            return td->opt;
      }
}

static Bool
textSetDisplayOption(CompDisplay *display, char *name, CompOptionValue *value)
{
      CompOption *o;
      int index;

      TEXT_DISPLAY(display);

      o = compFindOption(td->opt, NUM_OPTIONS(td), name, &index);
      if (!o)
          return FALSE;

      switch (index)
      {
      default:
            break;
      }

      return FALSE;
}

static Bool textInitDisplay(CompPlugin *p, CompDisplay *d)
{
      TextDisplay *td;
      CompScreen *s;

      td = malloc(sizeof(TextDisplay));
      if (!td)
            return FALSE;

      WRAP(td, d, fileToImage, textFileToImage);

      d->privates[displayPrivateIndex].ptr = td;

      textDisplayInitOptions(td);

      for (s = d->screens; s; s = s->next)
            updateDefaultIcon(s);

      return TRUE;
}

static void textFiniDisplay(CompPlugin *p, CompDisplay *d)
{
      CompScreen *s;

      TEXT_DISPLAY(d);

      UNWRAP(td, d, fileToImage);

      for (s = d->screens; s; s = s->next)
            updateDefaultIcon(s);

      free(td);
}


static Bool textInit(CompPlugin *p)
{
      displayPrivateIndex = allocateDisplayPrivateIndex();
      if (displayPrivateIndex < 0)
            return FALSE;

      return TRUE;
}

static void textFini(CompPlugin *p)
{
      if (displayPrivateIndex >= 0)
            freeDisplayPrivateIndex(displayPrivateIndex);
}

CompPluginFeature textFeatures[]={
      {"TextToPixmap"}
};

CompPluginVTable textVTable = {
      "text",
      N_("Text"),
      N_("Render text to texture plugin"),
      textInit,
      textFini,
      textInitDisplay,
      textFiniDisplay,
      0,
      0,
      0,
      0,
      textGetDisplayOptions,
      textSetDisplayOption,
      0,
      0,
      0,
      0,
      textFeatures,
      sizeof(textFeatures)/sizeof(textFeatures[0]),
      BERYL_ABI_INFO,
      "beryl-plugins-extra",
      "imageformat",
      0,
      0,
      True,
};

CompPluginVTable *getCompPluginInfo(void)
{
      return &textVTable;
}

Generated by  Doxygen 1.6.0   Back to index