diff options
author | Perberos <[email protected]> | 2011-12-01 21:51:44 -0300 |
---|---|---|
committer | Perberos <[email protected]> | 2011-12-01 21:51:44 -0300 |
commit | 0b0e6bc987da4fd88a7854ebb12bde705e92c428 (patch) | |
tree | 47d329edd31c67eaa36b2147780e37e197e901b5 /font-viewer | |
download | mate-control-center-0b0e6bc987da4fd88a7854ebb12bde705e92c428.tar.bz2 mate-control-center-0b0e6bc987da4fd88a7854ebb12bde705e92c428.tar.xz |
moving from https://github.com/perberos/mate-desktop-environment
Diffstat (limited to 'font-viewer')
-rw-r--r-- | font-viewer/Makefile.am | 48 | ||||
-rw-r--r-- | font-viewer/font-thumbnailer.c | 399 | ||||
-rw-r--r-- | font-viewer/font-view.c | 608 | ||||
-rw-r--r-- | font-viewer/fontilus.schemas.in | 109 | ||||
-rw-r--r-- | font-viewer/ftstream-vfs.c | 154 | ||||
-rw-r--r-- | font-viewer/mate-font-viewer.desktop.in.in | 14 | ||||
-rw-r--r-- | font-viewer/totem-resources.c | 123 | ||||
-rw-r--r-- | font-viewer/totem-resources.h | 33 |
8 files changed, 1488 insertions, 0 deletions
diff --git a/font-viewer/Makefile.am b/font-viewer/Makefile.am new file mode 100644 index 00000000..9fd87eac --- /dev/null +++ b/font-viewer/Makefile.am @@ -0,0 +1,48 @@ + +INCLUDES = $(FONT_VIEWER_CFLAGS) $(MATECC_CAPPLETS_CFLAGS) -DDIRECTORY_DIR=\"$(directorydir)\" \ + -DMATELOCALEDIR=\"$(datadir)/locale\" + +bin_PROGRAMS = mate-thumbnail-font mate-font-viewer + +mate_thumbnail_font_LDADD = $(MATECC_CAPPLETS_LIBS) $(FONT_VIEWER_LIBS) +mate_thumbnail_font_SOURCES = ftstream-vfs.c font-thumbnailer.c totem-resources.c totem-resources.h + +mate_font_viewer_LDADD = $(MATECC_CAPPLETS_LIBS) $(FONT_VIEWER_LIBS) +mate_font_viewer_SOURCES = ftstream-vfs.c font-view.c + +schemasdir = $(MATECONF_SCHEMA_FILE_DIR) +schemas_DATA = fontilus.schemas + +desktopdir = $(datadir)/applications +desktop_in_files = mate-font-viewer.desktop.in +desktop_DATA = $(desktop_in_files:.desktop.in=.desktop) + +install-data-local: install-mateconf-schemas install-desktop-database + +if MATECONF_SCHEMAS_INSTALL +install-mateconf-schemas: + if test -z "$(DESTDIR)"; then \ + MATECONF_CONFIG_SOURCE=$(MATECONF_SCHEMA_CONFIG_SOURCE) $(MATECONFTOOL) --makefile-install-rule fontilus.schemas; \ + fi +else +install-mateconf-schemas: +endif + +install-desktop-database: install-desktopDATA + update-desktop-database $(DESTDIR)$(desktopdir) + +uninstall-local: + rm -f $(DESTDIR)$(desktopdir)/mimeinfo.cache + +@INTLTOOL_DESKTOP_RULE@ +@INTLTOOL_DIRECTORY_RULE@ +@INTLTOOL_SCHEMAS_RULE@ + +CLEANFILES = $(desktop_in_files) $(desktop_DATA) \ + $(schemas_DATA) $(directory_DATA) + +EXTRA_DIST = \ + fontilus.schemas.in \ + mate-font-viewer.desktop.in.in + +-include $(top_srcdir)/git.mk diff --git a/font-viewer/font-thumbnailer.c b/font-viewer/font-thumbnailer.c new file mode 100644 index 00000000..da9f42a9 --- /dev/null +++ b/font-viewer/font-thumbnailer.c @@ -0,0 +1,399 @@ +/* -*- mode: C; c-basic-offset: 4 -*- + * fontilus - a collection of font utilities for MATE + * Copyright (C) 2002-2003 James Henstridge <[email protected]> + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <stdio.h> +#include <locale.h> + +#include <ft2build.h> +#include FT_FREETYPE_H + +#include <gdk-pixbuf/gdk-pixbuf.h> + +#include <gio/gio.h> +#include <glib/gi18n.h> + +#include "totem-resources.h" + +static const gchar * +get_ft_error(FT_Error error) +{ +#undef __FTERRORS_H__ +#define FT_ERRORDEF(e,v,s) case e: return s; +#define FT_ERROR_START_LIST +#define FT_ERROR_END_LIST + switch (error) { +#include FT_ERRORS_H + default: + return "unknown"; + } +} + +#define FONT_SIZE 64 +#define PAD_PIXELS 4 + +FT_Error FT_New_Face_From_URI(FT_Library library, + const gchar *uri, + FT_Long face_index, + FT_Face *aface); + +static void +draw_bitmap(GdkPixbuf *pixbuf, FT_Bitmap *bitmap, gint off_x, gint off_y) +{ + guchar *buffer; + gint p_width, p_height, p_rowstride; + gint i, j; + + buffer = gdk_pixbuf_get_pixels(pixbuf); + p_width = gdk_pixbuf_get_width(pixbuf); + p_height = gdk_pixbuf_get_height(pixbuf); + p_rowstride = gdk_pixbuf_get_rowstride(pixbuf); + + for (j = 0; j < bitmap->rows; j++) { + if (j + off_y < 0 || j + off_y >= p_height) + continue; + for (i = 0; i < bitmap->width; i++) { + guchar pixel; + gint pos; + + if (i + off_x < 0 || i + off_x >= p_width) + continue; + switch (bitmap->pixel_mode) { + case ft_pixel_mode_mono: + pixel = bitmap->buffer[j * bitmap->pitch + i/8]; + pixel = 255 - ((pixel >> (7 - i % 8)) & 0x1) * 255; + break; + case ft_pixel_mode_grays: + pixel = 255 - bitmap->buffer[j*bitmap->pitch + i]; + break; + default: + pixel = 255; + } + pos = (j + off_y) * p_rowstride + 3 * (i + off_x); + buffer[pos] = pixel; + buffer[pos+1] = pixel; + buffer[pos+2] = pixel; + } + } +} + +static void +draw_char(GdkPixbuf *pixbuf, FT_Face face, FT_UInt glyph_index, + gint *pen_x, gint *pen_y) +{ + FT_Error error; + FT_GlyphSlot slot; + + slot = face->glyph; + + error = FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT); + if (error) { + g_printerr("could not load glyph index '%ud': %s\n", glyph_index, + get_ft_error(error)); + return; + } + + error = FT_Render_Glyph(slot, ft_render_mode_normal); + if (error) { + g_printerr("could not render glyph index '%ud': %s\n", glyph_index, + get_ft_error(error)); + return; + } + + draw_bitmap(pixbuf, &slot->bitmap, + *pen_x + slot->bitmap_left, + *pen_y - slot->bitmap_top); + + *pen_x += slot->advance.x >> 6; +} + +static void +save_pixbuf(GdkPixbuf *pixbuf, gchar *filename) +{ + guchar *buffer; + gint p_width, p_height, p_rowstride; + gint i, j; + gint trim_left, trim_right, trim_top, trim_bottom; + GdkPixbuf *subpixbuf; + + buffer = gdk_pixbuf_get_pixels(pixbuf); + p_width = gdk_pixbuf_get_width(pixbuf); + p_height = gdk_pixbuf_get_height(pixbuf); + p_rowstride = gdk_pixbuf_get_rowstride(pixbuf); + + for (i = 0; i < p_width; i++) { + gboolean seen_pixel = FALSE; + + for (j = 0; j < p_height; j++) { + gint offset = j * p_rowstride + 3*i; + + seen_pixel = (buffer[offset] != 0xff || + buffer[offset+1] != 0xff || + buffer[offset+2] != 0xff); + if (seen_pixel) + break; + } + if (seen_pixel) + break; + } + trim_left = MIN(p_width, i); + trim_left = MAX(trim_left - PAD_PIXELS, 0); + + for (i = p_width-1; i >= trim_left; i--) { + gboolean seen_pixel = FALSE; + + for (j = 0; j < p_height; j++) { + gint offset = j * p_rowstride + 3*i; + + seen_pixel = (buffer[offset] != 0xff || + buffer[offset+1] != 0xff || + buffer[offset+2] != 0xff); + if (seen_pixel) + break; + } + if (seen_pixel) + break; + } + trim_right = MAX(trim_left, i); + trim_right = MIN(trim_right + PAD_PIXELS, p_width-1); + + for (j = 0; j < p_height; j++) { + gboolean seen_pixel = FALSE; + + for (i = 0; i < p_width; i++) { + gint offset = j * p_rowstride + 3*i; + + seen_pixel = (buffer[offset] != 0xff || + buffer[offset+1] != 0xff || + buffer[offset+2] != 0xff); + if (seen_pixel) + break; + } + if (seen_pixel) + break; + } + trim_top = MIN(p_height, j); + trim_top = MAX(trim_top - PAD_PIXELS, 0); + + for (j = p_height-1; j >= trim_top; j--) { + gboolean seen_pixel = FALSE; + + for (i = 0; i < p_width; i++) { + gint offset = j * p_rowstride + 3*i; + + seen_pixel = (buffer[offset] != 0xff || + buffer[offset+1] != 0xff || + buffer[offset+2] != 0xff); + if (seen_pixel) + break; + } + if (seen_pixel) + break; + } + trim_bottom = MAX(trim_top, j); + trim_bottom = MIN(trim_bottom + PAD_PIXELS, p_height-1); + + subpixbuf = gdk_pixbuf_new_subpixbuf(pixbuf, trim_left, trim_top, + trim_right - trim_left, + trim_bottom - trim_top); + gdk_pixbuf_save(subpixbuf, filename, "png", NULL, NULL); + g_object_unref(subpixbuf); +} + +int +main(int argc, char **argv) +{ + FT_Error error; + FT_Library library; + FT_Face face; + FT_UInt glyph_index1, glyph_index2; + GFile *file; + gchar *uri; + GdkPixbuf *pixbuf; + guchar *buffer; + gint i, len, pen_x, pen_y; + gunichar *thumbstr = NULL; + glong thumbstr_len = 2; + gint font_size = FONT_SIZE; + gchar *thumbstr_utf8 = NULL; + gchar **arguments = NULL; + GOptionContext *context; + GError *gerror = NULL; + gboolean retval, default_thumbstr = TRUE; + gint rv = 1; + const GOptionEntry options[] = { + { "text", 't', 0, G_OPTION_ARG_STRING, &thumbstr_utf8, + N_("Text to thumbnail (default: Aa)"), N_("TEXT") }, + { "size", 's', 0, G_OPTION_ARG_INT, &font_size, + N_("Font size (default: 64)"), N_("SIZE") }, + { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &arguments, + NULL, N_("FONT-FILE OUTPUT-FILE") }, + { NULL } + }; + + bindtextdomain (GETTEXT_PACKAGE, MATELOCALEDIR); + bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); + textdomain (GETTEXT_PACKAGE); + + setlocale (LC_ALL, ""); + + g_type_init (); + g_thread_init (NULL); + + context = g_option_context_new (NULL); + g_option_context_add_main_entries (context, options, GETTEXT_PACKAGE); + + retval = g_option_context_parse (context, &argc, &argv, &gerror); + g_option_context_free (context); + if (!retval) { + g_printerr (_("Error parsing arguments: %s\n"), gerror->message); + g_error_free (gerror); + return 1; + } + + if (!arguments || g_strv_length (arguments) != 2) { + /* FIXME: once glib bug 336089 is fixed, use print_help here instead! */ + g_printerr("usage: %s [--text TEXT] [--size SIZE] FONT-FILE OUTPUT-FILE\n", argv[0]); + goto out; + } + + if (thumbstr_utf8 != NULL) { + /* build ucs4 version of string to thumbnail */ + gerror = NULL; + thumbstr = g_utf8_to_ucs4 (thumbstr_utf8, strlen (thumbstr_utf8), + NULL, &thumbstr_len, &gerror); + default_thumbstr = FALSE; + + /* Not sure this can really happen... */ + if (gerror != NULL) { + g_printerr("Failed to convert: %s\n", gerror->message); + g_error_free (gerror); + goto out; + } + } + + error = FT_Init_FreeType(&library); + if (error) { + g_printerr("could not initialise freetype: %s\n", get_ft_error(error)); + goto out; + } + + totem_resources_monitor_start (arguments[0], 30 * G_USEC_PER_SEC); + + file = g_file_new_for_commandline_arg (arguments[0]); + uri = g_file_get_uri (file); + g_object_unref (file); + + error = FT_New_Face_From_URI(library, uri, 0, &face); + if (error) { + g_printerr("could not load face '%s': %s\n", uri, + get_ft_error(error)); + g_free (uri); + goto out; + } + + g_free (uri); + + error = FT_Set_Pixel_Sizes(face, 0, font_size); + if (error) { + g_printerr("could not set pixel size: %s\n", get_ft_error(error)); + /* goto out; */ + } + + for (i = 0; i < face->num_charmaps; i++) { + if (face->charmaps[i]->encoding == ft_encoding_latin_1 || + face->charmaps[i]->encoding == ft_encoding_unicode || + face->charmaps[i]->encoding == ft_encoding_apple_roman) { + error = FT_Set_Charmap(face, face->charmaps[i]); + if (error) { + g_printerr("could not set charmap: %s\n", get_ft_error(error)); + /* goto out; */ + } + break; + } + } + + pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, + font_size*3*thumbstr_len/2, font_size*1.5); + if (!pixbuf) { + g_printerr("could not create pixbuf\n"); + goto out; + } + buffer = gdk_pixbuf_get_pixels(pixbuf); + len = gdk_pixbuf_get_rowstride(pixbuf) * gdk_pixbuf_get_height(pixbuf); + for (i = 0; i < len; i++) + buffer[i] = 255; + + pen_x = font_size/2; + pen_y = font_size; + + if (default_thumbstr) { + glyph_index1 = FT_Get_Char_Index (face, 'A'); + glyph_index2 = FT_Get_Char_Index (face, 'a'); + + /* if the glyphs for those letters don't exist, pick some other + * glyphs. */ + if (glyph_index1 == 0) glyph_index1 = MIN (65, face->num_glyphs-1); + if (glyph_index2 == 0) glyph_index2 = MIN (97, face->num_glyphs-1); + + draw_char(pixbuf, face, glyph_index1, &pen_x, &pen_y); + draw_char(pixbuf, face, glyph_index2, &pen_x, &pen_y); + } + else { + gunichar *p = thumbstr; + FT_Select_Charmap (face, FT_ENCODING_UNICODE); + i = 0; + while (i < thumbstr_len) { + glyph_index1 = FT_Get_Char_Index (face, *p); + draw_char(pixbuf, face, glyph_index1, &pen_x, &pen_y); + i++; + p++; + } + } + save_pixbuf(pixbuf, arguments[1]); + g_object_unref(pixbuf); + + totem_resources_monitor_stop (); + + /* freeing the face causes a crash I haven't tracked down yet */ + error = FT_Done_Face(face); + if (error) { + g_printerr("could not unload face: %s\n", get_ft_error(error)); + goto out; + } + error = FT_Done_FreeType(library); + if (error) { + g_printerr("could not finalise freetype library: %s\n", + get_ft_error(error)); + goto out; + } + + rv = 0; /* success */ + + out: + + g_strfreev (arguments); + g_free (thumbstr); + g_free (thumbstr_utf8); + + return rv; +} diff --git a/font-viewer/font-view.c b/font-viewer/font-view.c new file mode 100644 index 00000000..f9fd94bc --- /dev/null +++ b/font-viewer/font-view.c @@ -0,0 +1,608 @@ +/* -*- mode: C; c-basic-offset: 4 -*- + * fontilus - a collection of font utilities for MATE + * Copyright (C) 2002-2003 James Henstridge <[email protected]> + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <ft2build.h> +#include FT_FREETYPE_H +#include FT_TYPE1_TABLES_H +#include FT_SFNT_NAMES_H +#include FT_TRUETYPE_IDS_H +#include <X11/Xlib.h> +#include <X11/Xft/Xft.h> + +#include <gio/gio.h> +#include <gtk/gtk.h> +#include <gdk/gdkx.h> +#include <glib/gi18n.h> + +FT_Error FT_New_Face_From_URI(FT_Library library, + const gchar *uri, + FT_Long face_index, + FT_Face *aface); + +static const gchar lowercase_text[] = "abcdefghijklmnopqrstuvwxyz"; +static const gchar uppercase_text[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; +static const gchar punctuation_text[] = "0123456789.:,;(*!?')"; + +static inline XftFont * +get_font(Display *xdisplay, FT_Face face, gint size, FcCharSet *charset) +{ + FcPattern *pattern; + XftFont *font; + int screen = DefaultScreen (xdisplay); + + pattern = FcPatternBuild(NULL, + FC_FT_FACE, FcTypeFTFace, face, + FC_PIXEL_SIZE, FcTypeDouble, (double)size, + NULL); + + if (charset) + FcPatternAddCharSet (pattern, "charset", charset); + + FcConfigSubstitute (NULL, pattern, FcMatchPattern); + XftDefaultSubstitute (xdisplay, screen, pattern); + + font = XftFontOpenPattern(xdisplay, pattern); + + return font; +} + +static inline void +draw_string(Display *xdisplay, XftDraw *draw, XftFont *font, XftColor *colour, + const gchar *text, gint *pos_y) +{ + XGlyphInfo extents; + gint len = strlen(text); + + XftTextExtentsUtf8(xdisplay, font, (guchar *)text, len, &extents); + XftDrawStringUtf8(draw, colour, font, 4, *pos_y + extents.y, (guchar *)text, len); + *pos_y += extents.height + 4; +} + +static gboolean +check_font_contain_text (FT_Face face, const gchar *text) +{ + while (text && *text) + { + gunichar wc = g_utf8_get_char (text); + if (!FT_Get_Char_Index (face, wc)) + return FALSE; + + text = g_utf8_next_char (text); + } + + return TRUE; +} + + +static gboolean expose_event(GtkWidget *widget, GdkEventExpose *event, GdkPixmap *pixmap); + +static GdkPixmap * +create_text_pixmap(GtkWidget *drawing_area, FT_Face face) +{ + gint i, pixmap_width, pixmap_height, pos_y, textlen; + GdkPixmap *pixmap = NULL; + const gchar *text; + Display *xdisplay; + Drawable xdrawable; + Visual *xvisual; + Colormap xcolormap; + XftDraw *draw; + XftColor colour; + XGlyphInfo extents; + XftFont *font; + gint *sizes = NULL, n_sizes, alpha_size; + FcCharSet *charset = NULL; + GdkWindow *window = gtk_widget_get_window (drawing_area); + + text = pango_language_get_sample_string(NULL); + if (! check_font_contain_text (face, text)) + { + pango_language_get_sample_string (pango_language_from_string ("en_US")); + } + + textlen = strlen(text); + + /* create the XftDraw */ + xdisplay = GDK_PIXMAP_XDISPLAY(window); + + #if GTK_CHECK_VERSION(3, 0, 0) + xvisual = GDK_VISUAL_XVISUAL(gdk_window_get_visual(window)); + #else + xvisual = GDK_VISUAL_XVISUAL(gdk_drawable_get_visual(window)); + #endif + + xcolormap = GDK_COLORMAP_XCOLORMAP(gdk_drawable_get_colormap(window)); + XftColorAllocName(xdisplay, xvisual, xcolormap, "black", &colour); + + /* work out what sizes to render */ + if (FT_IS_SCALABLE(face)) { + n_sizes = 8; + sizes = g_new(gint, n_sizes); + sizes[0] = 8; + sizes[1] = 10; + sizes[2] = 12; + sizes[3] = 18; + sizes[4] = 24; + sizes[5] = 36; + sizes[6] = 48; + sizes[7] = 72; + alpha_size = 24; + } else { + /* use fixed sizes */ + n_sizes = face->num_fixed_sizes; + sizes = g_new(gint, n_sizes); + alpha_size = 0; + for (i = 0; i < face->num_fixed_sizes; i++) { + sizes[i] = face->available_sizes[i].height; + + /* work out which font size to render */ + if (face->available_sizes[i].height <= 24) + alpha_size = face->available_sizes[i].height; + } + } + + /* calculate size of pixmap to use (with 4 pixels padding) ... */ + pixmap_width = 8; + pixmap_height = 8; + + font = get_font(xdisplay, face, alpha_size, charset); + charset = FcCharSetCopy (font->charset); + XftTextExtentsUtf8(xdisplay, font, + (guchar *)lowercase_text, strlen(lowercase_text), &extents); + pixmap_height += extents.height + 4; + pixmap_width = MAX(pixmap_width, 8 + extents.width); + XftTextExtentsUtf8(xdisplay, font, + (guchar *)uppercase_text, strlen(uppercase_text), &extents); + pixmap_height += extents.height + 4; + pixmap_width = MAX(pixmap_width, 8 + extents.width); + XftTextExtentsUtf8(xdisplay, font, + (guchar *)punctuation_text, strlen(punctuation_text), &extents); + pixmap_height += extents.height + 4; + pixmap_width = MAX(pixmap_width, 8 + extents.width); + XftFontClose(xdisplay, font); + + pixmap_height += 8; + + for (i = 0; i < n_sizes; i++) { + font = get_font(xdisplay, face, sizes[i], charset); + if (!font) continue; + XftTextExtentsUtf8(xdisplay, font, (guchar *)text, textlen, &extents); + pixmap_height += extents.height + 4; + pixmap_width = MAX(pixmap_width, 8 + extents.width); + XftFontClose(xdisplay, font); + } + + /* create pixmap */ + gtk_widget_set_size_request(drawing_area, pixmap_width, pixmap_height); + pixmap = gdk_pixmap_new(window, + pixmap_width, pixmap_height, -1); + if (!pixmap) + goto end; + gdk_draw_rectangle(pixmap, gtk_widget_get_style(drawing_area)->white_gc, + TRUE, 0, 0, pixmap_width, pixmap_height); + + xdrawable = GDK_DRAWABLE_XID(pixmap); + draw = XftDrawCreate(xdisplay, xdrawable, xvisual, xcolormap); + + /* draw text */ + pos_y = 4; + font = get_font(xdisplay, face, alpha_size, charset); + draw_string(xdisplay, draw, font, &colour, lowercase_text, &pos_y); + draw_string(xdisplay, draw, font, &colour, uppercase_text, &pos_y); + draw_string(xdisplay, draw, font, &colour, punctuation_text, &pos_y); + XftFontClose(xdisplay, font); + + pos_y += 8; + for (i = 0; i < n_sizes; i++) { + font = get_font(xdisplay, face, sizes[i], charset); + if (!font) continue; + draw_string(xdisplay, draw, font, &colour, text, &pos_y); + XftFontClose(xdisplay, font); + } + + g_signal_connect(drawing_area, "expose-event", G_CALLBACK(expose_event), + pixmap); + + end: + g_free(sizes); + FcCharSetDestroy (charset); + return pixmap; +} + +static void +add_row(GtkWidget *table, gint *row_p, + const gchar *name, const gchar *value, gboolean multiline, + gboolean expand) +{ + gchar *bold_name; + GtkWidget *name_w; + + bold_name = g_strconcat("<b>", name, "</b>", NULL); + name_w = gtk_label_new(bold_name); + g_free(bold_name); + gtk_misc_set_alignment(GTK_MISC(name_w), 0.0, 0.0); + gtk_label_set_use_markup(GTK_LABEL(name_w), TRUE); + + gtk_table_attach(GTK_TABLE(table), name_w, 0, 1, *row_p, *row_p + 1, + GTK_FILL, GTK_FILL, 0, 0); + + if (multiline) { + GtkWidget *label, *viewport; + GtkScrolledWindow *swin; + guint flags; + + label = gtk_label_new (value); + gtk_label_set_line_wrap (GTK_LABEL (label), TRUE); + gtk_label_set_selectable (GTK_LABEL (label), TRUE); + gtk_widget_set_size_request (label, 200, -1); + gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.0); + + + swin = GTK_SCROLLED_WINDOW(gtk_scrolled_window_new(NULL, NULL)); + gtk_scrolled_window_set_policy(swin, + GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); + + viewport = gtk_viewport_new (gtk_scrolled_window_get_hadjustment (swin), + gtk_scrolled_window_get_vadjustment (swin)); + gtk_viewport_set_shadow_type (GTK_VIEWPORT (viewport), GTK_SHADOW_NONE); + + gtk_container_add (GTK_CONTAINER(swin), viewport); + (*row_p)++; + if (expand) + flags = GTK_FILL|GTK_EXPAND; + else + flags = GTK_FILL; + gtk_table_attach(GTK_TABLE(table), GTK_WIDGET(swin), 0, 2, *row_p, *row_p + 1, + GTK_FILL|GTK_EXPAND, flags, 0, 0); + + gtk_container_add (GTK_CONTAINER (viewport), label); + } else { + GtkWidget *label = gtk_label_new(value); + gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); + gtk_label_set_selectable(GTK_LABEL(label), TRUE); + gtk_table_attach(GTK_TABLE(table), label, 1, 2, *row_p, *row_p + 1, + GTK_FILL|GTK_EXPAND, GTK_FILL, 0, 0); + } + + + (*row_p)++; +} + +static void +add_face_info(GtkWidget *table, gint *row_p, const gchar *uri, FT_Face face) +{ + gchar *s; + GFile *file; + GFileInfo *info; + PS_FontInfoRec ps_info; + + add_row(table, row_p, _("Name:"), face->family_name, FALSE, FALSE); + + if (face->style_name) + add_row(table, row_p, _("Style:"), face->style_name, FALSE, FALSE); + + file = g_file_new_for_uri (uri); + + info = g_file_query_info (file, + G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE "," + G_FILE_ATTRIBUTE_STANDARD_SIZE, + G_FILE_QUERY_INFO_NONE, + NULL, NULL); + g_object_unref (file); + + if (info) { + s = g_content_type_get_description (g_file_info_get_content_type (info)); + add_row (table, row_p, _("Type:"), s, FALSE, FALSE); + g_free (s); + + s = g_format_size_for_display (g_file_info_get_size (info)); + add_row (table, row_p, _("Size:"), s, FALSE, FALSE); + g_free (s); + + g_object_unref (info); + } + + if (FT_IS_SFNT(face)) { + gint i, len; + gchar *version = NULL, *copyright = NULL, *description = NULL; + + len = FT_Get_Sfnt_Name_Count(face); + for (i = 0; i < len; i++) { + FT_SfntName sname; + + if (FT_Get_Sfnt_Name(face, i, &sname) != 0) + continue; + + /* only handle the unicode names for US langid */ + if (!(sname.platform_id == TT_PLATFORM_MICROSOFT && + sname.encoding_id == TT_MS_ID_UNICODE_CS && + sname.language_id == TT_MS_LANGID_ENGLISH_UNITED_STATES)) + continue; + + switch (sname.name_id) { + case TT_NAME_ID_COPYRIGHT: + g_free(copyright); + copyright = g_convert((gchar *)sname.string, sname.string_len, + "UTF-8", "UTF-16BE", NULL, NULL, NULL); + break; + case TT_NAME_ID_VERSION_STRING: + g_free(version); + version = g_convert((gchar *)sname.string, sname.string_len, + "UTF-8", "UTF-16BE", NULL, NULL, NULL); + break; + case TT_NAME_ID_DESCRIPTION: + g_free(description); + description = g_convert((gchar *)sname.string, sname.string_len, + "UTF-8", "UTF-16BE", NULL, NULL, NULL); + break; + default: + break; + } + } + if (version) { + add_row(table, row_p, _("Version:"), version, FALSE, FALSE); + g_free(version); + } + if (copyright) { + add_row(table, row_p, _("Copyright:"), copyright, TRUE, TRUE); + g_free(copyright); + } + if (description) { + add_row(table, row_p, _("Description:"), description, TRUE, TRUE); + g_free(description); + } + } else if (FT_Get_PS_Font_Info(face, &ps_info) == 0) { + if (ps_info.version && g_utf8_validate(ps_info.version, -1, NULL)) + add_row(table, row_p, _("Version:"), ps_info.version, FALSE, FALSE); + if (ps_info.notice && g_utf8_validate(ps_info.notice, -1, NULL)) + add_row(table, row_p, _("Copyright:"), ps_info.notice, TRUE, FALSE); + } +} + +static gboolean +expose_event(GtkWidget *widget, GdkEventExpose *event, GdkPixmap *pixmap) +{ + gdk_draw_drawable(gtk_widget_get_window (widget), + gtk_widget_get_style (widget)->fg_gc[gtk_widget_get_state (widget)], + pixmap, + event->area.x, event->area.y, + event->area.x, event->area.y, + event->area.width, event->area.height); + return FALSE; +} + +static void +set_icon(GtkWindow *window, const gchar *uri) +{ + GFile *file; + GIcon *icon; + GFileInfo *info; + GdkScreen *screen; + GtkIconTheme *icon_theme; + const gchar *icon_name = NULL, *content_type; + + screen = gtk_widget_get_screen (GTK_WIDGET (window)); + icon_theme = gtk_icon_theme_get_for_screen (screen); + + file = g_file_new_for_uri (uri); + + info = g_file_query_info (file, G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE, + G_FILE_QUERY_INFO_NONE, NULL, NULL); + g_object_unref (file); + + if (! info) + return; + + content_type = g_file_info_get_content_type (info); + icon = g_content_type_get_icon (content_type); + + if (G_IS_THEMED_ICON (icon)) { + const gchar * const *names = NULL; + + names = g_themed_icon_get_names (G_THEMED_ICON (icon)); + if (names) { + gint i; + for (i = 0; names[i]; i++) { + if (gtk_icon_theme_has_icon (icon_theme, names[i])) { + icon_name = names[i]; + break; + } + } + } + } + + if (icon_name) { + gtk_window_set_icon_name (window, icon_name); + } + + g_object_unref (icon); +} + +static void +font_install_finished_cb (GObject *source_object, + GAsyncResult *res, + gpointer data) +{ + GError *err = NULL; + + g_file_copy_finish (G_FILE (source_object), res, &err); + + if (!err) { + gtk_button_set_label (GTK_BUTTON (data), _("Installed")); + } + else { + gtk_button_set_label (GTK_BUTTON (data), _("Install Failed")); + g_debug ("Install failed: %s", err->message); + g_error_free (err); + } + gtk_widget_set_sensitive (GTK_WIDGET (data), FALSE); +} + +static void +install_button_clicked_cb (GtkButton *button, + const gchar *font_file) +{ + GFile *src, *dest; + gchar *dest_path, *dest_filename; + + GError *err = NULL; + + /* first check if ~/.fonts exists */ + dest_path = g_build_filename (g_get_home_dir (), ".fonts", NULL); + if (!g_file_test (dest_path, G_FILE_TEST_EXISTS)) { + GFile *f = g_file_new_for_path (dest_path); + g_file_make_directory_with_parents (f, NULL, &err); + g_object_unref (f); + if (err) { + /* TODO: show error dialog */ + g_warning ("Could not create fonts directory: %s", err->message); + g_error_free (err); + g_free (dest_path); + return; + } + } + g_free (dest_path); + + /* create destination filename */ + src = g_file_new_for_uri (font_file); + + dest_filename = g_file_get_basename (src); + dest_path = g_build_filename (g_get_home_dir (), ".fonts", dest_filename, NULL); + g_free (dest_filename); + + dest = g_file_new_for_path (dest_path); + + /* TODO: show error dialog if file exists */ + g_file_copy_async (src, dest, G_FILE_COPY_NONE, 0, NULL, NULL, NULL, + font_install_finished_cb, button); + + g_object_unref (src); + g_object_unref (dest); + g_free (dest_path); +} + +int +main(int argc, char **argv) +{ + FT_Error error; + FT_Library library; + FT_Face face; + GFile *file; + gchar *font_file, *title; + gint row; + GtkWidget *window, *hbox, *table, *swin, *drawing_area; + GdkPixmap *pixmap; + GdkColor white = { 0, 0xffff, 0xffff, 0xffff }; + GtkWidget *button, *align; + + bindtextdomain(GETTEXT_PACKAGE, MATELOCALEDIR); + bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8"); + textdomain(GETTEXT_PACKAGE); + + gtk_init(&argc, &argv); + + if (argc != 2) { + g_printerr(_("usage: %s fontfile\n"), argv[0]); + return 1; + } + + if (!XftInitFtLibrary()) { + g_printerr("could not initialise freetype library\n"); + return 1; + } + + error = FT_Init_FreeType(&library); + if (error) { + g_printerr("could not initialise freetype\n"); + return 1; + } + + file = g_file_new_for_commandline_arg (argv[1]); + font_file = g_file_get_uri (file); + g_object_unref (file); + + if (!font_file) { + g_printerr("could not parse argument into a URI\n"); + return 1; + } + + error = FT_New_Face_From_URI(library, font_file, 0, &face); + if (error) { + g_printerr("could not load face '%s'\n", font_file); + return 1; + } + + window = gtk_window_new(GTK_WINDOW_TOPLEVEL); + title = g_strconcat(face->family_name, + face->style_name ? ", " : "", + face->style_name, NULL); + gtk_window_set_title(GTK_WINDOW(window), title); + set_icon(GTK_WINDOW(window), font_file); + g_free(title); + gtk_window_set_resizable(GTK_WINDOW(window), TRUE); + + hbox = gtk_hbox_new(FALSE, 0); + gtk_container_add(GTK_CONTAINER(window), hbox); + + swin = gtk_scrolled_window_new(NULL, NULL); + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(swin), + GTK_POLICY_AUTOMATIC, GTK_POLICY_NEVER); + gtk_box_pack_start(GTK_BOX(hbox), swin, TRUE, TRUE, 0); + + drawing_area = gtk_drawing_area_new(); + gtk_widget_modify_bg(drawing_area, GTK_STATE_NORMAL, &white); + gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(swin), + drawing_area); + g_signal_connect (drawing_area, "realize", create_text_pixmap, face); + + /* set the minimum size on the scrolled window to prevent + * unnecessary scrolling */ + gtk_widget_set_size_request(swin, 500, -1); + + g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL); + + table = gtk_table_new(1, 2, FALSE); + gtk_container_set_border_width(GTK_CONTAINER(table), 5); + gtk_box_pack_start(GTK_BOX(hbox), table, FALSE, TRUE, 0); + + row = 0; + add_face_info(table, &row, font_file, face); + + /* add install button */ + align = gtk_alignment_new (1.0, 0.5, 0.0, 0.0); + gtk_table_attach (GTK_TABLE (table), align, 0, 2, row, row + 1, + GTK_FILL|GTK_EXPAND, GTK_FILL, 0, 0); + + button = gtk_button_new_with_mnemonic (_("I_nstall Font")); + g_signal_connect (button, "clicked", + G_CALLBACK (install_button_clicked_cb), font_file); + gtk_container_add (GTK_CONTAINER (align), button); + + + gtk_table_set_col_spacings(GTK_TABLE(table), 8); + gtk_table_set_row_spacings(GTK_TABLE(table), 2); + gtk_widget_show_all(window); + + gtk_main(); + return 0; +} diff --git a/font-viewer/fontilus.schemas.in b/font-viewer/fontilus.schemas.in new file mode 100644 index 00000000..2e303465 --- /dev/null +++ b/font-viewer/fontilus.schemas.in @@ -0,0 +1,109 @@ +<?xml version="1.0"?> +<mateconfschemafile> + <schemalist> + <schema> + <key>/schemas/desktop/mate/thumbnailers/application@x-font-ttf/command</key> + <applyto>/desktop/mate/thumbnailers/application@x-font-ttf/command</applyto> + <type>string</type> + <default>mate-thumbnail-font %u %o</default> + <locale name="C"> + <short>Thumbnail command for TrueType fonts</short> + <long> + Set this key to the command used to create thumbnails for + TrueType fonts. + </long> + </locale> + </schema> + <schema> + <key>/schemas/desktop/mate/thumbnailers/application@x-font-ttf/enable</key> + <applyto>/desktop/mate/thumbnailers/application@x-font-ttf/enable</applyto> + <type>bool</type> + <default>true</default> + <locale name="C"> + <short>Whether to thumbnail TrueType fonts</short> + <long> + If set to true, then TrueType fonts will be thumbnailed. + </long> + </locale> + </schema> + + <schema> + <key>/schemas/desktop/mate/thumbnailers/application@x-font-type1/command</key> + <applyto>/desktop/mate/thumbnailers/application@x-font-type1/command</applyto> + <type>string</type> + <default>mate-thumbnail-font %u %o</default> + <locale name="C"> + <short>Thumbnail command for Type1 fonts</short> + <long> + Set this key to the command used to create thumbnails for + Type1 fonts. + </long> + </locale> + </schema> + <schema> + <key>/schemas/desktop/mate/thumbnailers/application@x-font-type1/enable</key> + <applyto>/desktop/mate/thumbnailers/application@x-font-type1/enable</applyto> + <type>bool</type> + <default>true</default> + <locale name="C"> + <short>Whether to thumbnail Type1 fonts</short> + <long> + If set to true, then Type1 fonts will be thumbnailed. + </long> + </locale> + </schema> + + <schema> + <key>/schemas/desktop/mate/thumbnailers/application@x-font-pcf/command</key> + <applyto>/desktop/mate/thumbnailers/application@x-font-pcf/command</applyto> + <type>string</type> + <default>mate-thumbnail-font %u %o</default> + <locale name="C"> + <short>Thumbnail command for PCF fonts</short> + <long> + Set this key to the command used to create thumbnails for + PCF fonts. + </long> + </locale> + </schema> + <schema> + <key>/schemas/desktop/mate/thumbnailers/application@x-font-pcf/enable</key> + <applyto>/desktop/mate/thumbnailers/application@x-font-pcf/enable</applyto> + <type>bool</type> + <default>true</default> + <locale name="C"> + <short>Whether to thumbnail PCF fonts</short> + <long> + If set to true, then PCF fonts will be thumbnailed. + </long> + </locale> + </schema> + + <schema> + <key>/schemas/desktop/mate/thumbnailers/application@x-font-otf/command</key> + <applyto>/desktop/mate/thumbnailers/application@x-font-otf/command</applyto> + <type>string</type> + <default>mate-thumbnail-font %u %o</default> + <locale name="C"> + <short>Thumbnail command for OpenType fonts</short> + <long> + Set this key to the command used to create thumbnails for + OpenType fonts. + </long> + </locale> + </schema> + <schema> + <key>/schemas/desktop/mate/thumbnailers/application@x-font-otf/enable</key> + <applyto>/desktop/mate/thumbnailers/application@x-font-otf/enable</applyto> + <type>bool</type> + <default>true</default> + <locale name="C"> + <short>Whether to thumbnail OpenType fonts</short> + <long> + If set to true, then OpenType fonts will be thumbnailed. + </long> + </locale> + </schema> + + </schemalist> +</mateconfschemafile> diff --git a/font-viewer/ftstream-vfs.c b/font-viewer/ftstream-vfs.c new file mode 100644 index 00000000..8bfcf397 --- /dev/null +++ b/font-viewer/ftstream-vfs.c @@ -0,0 +1,154 @@ +/* -*- mode: C; c-basic-offset: 4 -*- + * fontilus - a collection of font utilities for MATE + * Copyright (C) 2002-2003 James Henstridge <[email protected]> + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <stdlib.h> +#include <ft2build.h> +#include FT_FREETYPE_H + +#include <gio/gio.h> + +static unsigned long +vfs_stream_read(FT_Stream stream, + unsigned long offset, + unsigned char *buffer, + unsigned long count) +{ + GFileInputStream *handle = (GFileInputStream *)stream->descriptor.pointer; + gssize bytes_read = 0; + + if (! g_seekable_seek (G_SEEKABLE (handle), offset, G_SEEK_SET, NULL, NULL)) + return 0; + + if (count > 0) { + bytes_read = g_input_stream_read (G_INPUT_STREAM (handle), buffer, count, NULL, NULL); + + if (bytes_read == -1) + return 0; + } + + return bytes_read; +} + +static void +vfs_stream_close(FT_Stream stream) +{ + GFileInputStream *handle = (GFileInputStream *)stream->descriptor.pointer; + + if (! handle) + return; + + g_object_unref (handle); + + stream->descriptor.pointer = NULL; + stream->size = 0; + stream->base = NULL; +} + +static FT_Error +vfs_stream_open(FT_Stream stream, + const char *uri) +{ + GFile *file; + GError *error = NULL; + GFileInfo *info; + GFileInputStream *handle; + + if (!stream) + return FT_Err_Invalid_Stream_Handle; + + file = g_file_new_for_uri (uri); + + handle = g_file_read (file, NULL, &error); + if (! handle) { + g_message ("%s", error->message); + g_object_unref (file); + + g_error_free (error); + return FT_Err_Cannot_Open_Resource; + } + + info = g_file_query_info (file, G_FILE_ATTRIBUTE_STANDARD_SIZE, + G_FILE_QUERY_INFO_NONE, NULL, &error); + g_object_unref (file); + + if (! info) { + g_warning ("%s", error->message); + + g_error_free (error); + return FT_Err_Cannot_Open_Resource; + } + + stream->size = g_file_info_get_size (info); + + g_object_unref (info); + + stream->descriptor.pointer = handle; + stream->pathname.pointer = NULL; + stream->pos = 0; + + stream->read = vfs_stream_read; + stream->close = vfs_stream_close; + + return FT_Err_Ok; +} + +/* load a typeface from a URI */ +FT_Error +FT_New_Face_From_URI(FT_Library library, + const gchar* uri, + FT_Long face_index, + FT_Face *aface) +{ + FT_Open_Args args; + FT_Stream stream; + FT_Error error; + + if ((stream = calloc(1, sizeof(*stream))) == NULL) + return FT_Err_Out_Of_Memory; + + error = vfs_stream_open(stream, uri); + if (error != FT_Err_Ok) { + free(stream); + return error; + } + + /* freetype-2.1.3 accidentally broke compatibility. */ +#if defined(FT_OPEN_STREAM) && !defined(ft_open_stream) +# define ft_open_stream FT_OPEN_STREAM +#endif + args.flags = ft_open_stream; + args.stream = stream; + + error = FT_Open_Face(library, &args, face_index, aface); + + if (error != FT_Err_Ok) { + if (stream->close) stream->close(stream); + free(stream); + return error; + } + + /* so that freetype will free the stream */ + (*aface)->face_flags &= ~FT_FACE_FLAG_EXTERNAL_STREAM; + + return error; +} diff --git a/font-viewer/mate-font-viewer.desktop.in.in b/font-viewer/mate-font-viewer.desktop.in.in new file mode 100644 index 00000000..9c78f678 --- /dev/null +++ b/font-viewer/mate-font-viewer.desktop.in.in @@ -0,0 +1,14 @@ +[Desktop Entry] +_Name=Font Viewer +_Comment=Preview fonts +Icon=preferences-desktop-font +Exec=mate-font-viewer %u +Terminal=false +Type=Application +StartupNotify=true +NoDisplay=true +MimeType=application/x-font-ttf;application/x-font-pcf;application/x-font-type1;application/x-font-otf; +X-MATE-Bugzilla-Bugzilla=MATE +X-MATE-Bugzilla-Product=mate-control-center +X-MATE-Bugzilla-Component=font properties +X-MATE-Bugzilla-Version=@VERSION@ diff --git a/font-viewer/totem-resources.c b/font-viewer/totem-resources.c new file mode 100644 index 00000000..3d107737 --- /dev/null +++ b/font-viewer/totem-resources.c @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2007 Bastien Nocera <[email protected]> + * + * 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. + * + * The Totem project hereby grant permission for non-gpl compatible GStreamer + * plugins to be used and distributed together with GStreamer and Totem. This + * permission are above and beyond the permissions granted by the GPL license + * Totem is covered by. + * + * Monday 7th February 2005: Christian Schaller: Add exception clause. + * See license_change file for details. + * + */ + +#include "config.h" + +#include <glib.h> +#include <glib/gstdio.h> + +#include <unistd.h> +#include <stdlib.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/resource.h> + +#include "totem-resources.h" + +#define MAX_HELPER_MEMORY (256 * 1024 * 1024) /* 256 MB */ +#define MAX_HELPER_SECONDS (15) /* 15 seconds */ +#define DEFAULT_SLEEP_TIME (30 * G_USEC_PER_SEC) /* 30 seconds */ + +static guint sleep_time = DEFAULT_SLEEP_TIME; +static gboolean finished = TRUE; + +static void +set_resource_limits (const char *input) +{ + struct rlimit limit; + struct stat buf; + rlim_t max; + + max = MAX_HELPER_MEMORY; + + /* Set the maximum virtual size depending on the size + * of the file to process, as we wouldn't be able to + * mmap it otherwise */ + if (input == NULL) { + max = MAX_HELPER_MEMORY; + } else if (g_stat (input, &buf) == 0) { + max = MAX_HELPER_MEMORY + buf.st_size; + } else if (g_str_has_prefix (input, "file://") != FALSE) { + char *file; + file = g_filename_from_uri (input, NULL, NULL); + if (file != NULL && g_stat (file, &buf) == 0) + max = MAX_HELPER_MEMORY + buf.st_size; + g_free (file); + } + + limit.rlim_cur = max; + limit.rlim_max = max; + + setrlimit (RLIMIT_DATA, &limit); + + limit.rlim_cur = MAX_HELPER_SECONDS; + limit.rlim_max = MAX_HELPER_SECONDS; + setrlimit (RLIMIT_CPU, &limit); +} + +G_GNUC_NORETURN static gpointer +time_monitor (gpointer data) +{ + const char *app_name; + + g_usleep (sleep_time); + + if (finished != FALSE) + g_thread_exit (NULL); + + app_name = g_get_application_name (); + if (app_name == NULL) + app_name = g_get_prgname (); + g_print ("%s couldn't process file: '%s'\n" + "Reason: Took too much time to process.\n", + app_name, + (const char *) data); + + exit (0); +} + +void +totem_resources_monitor_start (const char *input, gint wall_clock_time) +{ + set_resource_limits (input); + + if (wall_clock_time < 0) + return; + + if (wall_clock_time > 0) + sleep_time = wall_clock_time; + + finished = FALSE; + g_thread_create (time_monitor, (gpointer) input, FALSE, NULL); +} + +void +totem_resources_monitor_stop (void) +{ + finished = TRUE; +} + diff --git a/font-viewer/totem-resources.h b/font-viewer/totem-resources.h new file mode 100644 index 00000000..421a03ca --- /dev/null +++ b/font-viewer/totem-resources.h @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2007 Bastien Nocera <[email protected]> + * + * 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. + * + * The Totem project hereby grant permission for non-gpl compatible GStreamer + * plugins to be used and distributed together with GStreamer and Totem. This + * permission are above and beyond the permissions granted by the GPL license + * Totem is covered by. + * + * Monday 7th February 2005: Christian Schaller: Add exception clause. + * See license_change file for details. + * + */ + +#include <glib.h> + +void totem_resources_monitor_start (const char *input, + gint wall_clock_time); +void totem_resources_monitor_stop (void); + |