/* * 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 #include #include #include #include #include #include #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; }