Репозиторий Sisyphus
Последнее обновление: 1 октября 2023 | Пакетов: 18631 | Посещений: 37545628
en ru br
Репозитории ALT

Группа :: Graphical desktop/MATE
Пакет: mate-control-center

 Главная   Изменения   Спек   Патчи   Sources   Загрузить   Gear   Bugs and FR  Repocop 

Патч: mate-control-center_fv-import-SushiFontLoader-and-SushiFontWidget.patch
Скачать


diff -uprN mate-control-center/font-viewer/Makefile.am mate-control-center-test/font-viewer/Makefile.am
--- mate-control-center/font-viewer/Makefile.am	2015-08-22 12:29:02.670185916 +0200
+++ mate-control-center-test/font-viewer/Makefile.am	2015-08-22 19:03:12.438205758 +0200
@@ -4,11 +4,15 @@ AM_CPPFLAGS = $(FONT_VIEWER_CFLAGS) $(MA
 
 bin_PROGRAMS = mate-thumbnail-font mate-font-viewer
 
+font_loader_SOURCES = \
+	sushi-font-loader.h \
+	sushi-font-loader.c
+
 mate_thumbnail_font_LDADD = $(MATECC_CAPPLETS_LIBS) $(FONT_VIEWER_LIBS)
-mate_thumbnail_font_SOURCES = ftstream-vfs.c ftstream-vfs.h font-thumbnailer.c totem-resources.c totem-resources.h
+mate_thumbnail_font_SOURCES = ftstream-vfs.c ftstream-vfs.h $(font_loader_SOURCES) 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 ftstream-vfs.h font-view.c
+mate_font_viewer_SOURCES = ftstream-vfs.c ftstream-vfs.h $(font_loader_SOURCES) sushi-font-widget.h sushi-font-widget.c font-view.c
 
 thumbnailerdir = $(datadir)/thumbnailers
 thumbnailer_DATA = mate-font-viewer.thumbnailer
diff -uprN mate-control-center/font-viewer/sushi-font-loader.c mate-control-center-test/font-viewer/sushi-font-loader.c
--- mate-control-center/font-viewer/sushi-font-loader.c	1970-01-01 01:00:00.000000000 +0100
+++ mate-control-center-test/font-viewer/sushi-font-loader.c	2015-08-22 19:04:18.059887621 +0200
@@ -0,0 +1,207 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * 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.
+ *
+ * The Sushi project hereby grant permission for non-gpl compatible GStreamer
+ * plugins to be used and distributed together with GStreamer and Sushi. This
+ * permission is above and beyond the permissions granted by the GPL license
+ * Sushi is covered by.
+ *
+ * Authors: Cosimo Cecchi <cosimoc@redhat.com>
+ *
+ */
+
+#include "sushi-font-loader.h"
+
+#include <stdlib.h>
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+#include <gio/gio.h>
+
+typedef struct {
+  FT_Library library;
+  FT_Long face_index;
+  GFile *file;
+  GSimpleAsyncResult *result;
+
+  gchar *face_contents;
+  gsize face_length;
+} FontLoadJob;
+
+static FontLoadJob *
+font_load_job_new (FT_Library library,
+                   const gchar *uri,
+                   GAsyncReadyCallback callback,
+                   gpointer user_data)
+{
+  FontLoadJob *job = g_slice_new0 (FontLoadJob);
+
+  job->library = library;
+  job->face_index = 0;
+  job->file = g_file_new_for_uri (uri);
+  job->result = g_simple_async_result_new
+    (NULL, callback, user_data,
+     sushi_new_ft_face_from_uri_async);
+
+  g_simple_async_result_set_op_res_gpointer (job->result, job, NULL);
+
+  return job;
+}
+
+static void
+font_load_job_free (FontLoadJob *job)
+{
+  g_clear_object (&job->result);
+  g_clear_object (&job->file);
+
+  g_slice_free (FontLoadJob, job);
+}
+
+static FT_Face
+create_face_from_contents (FontLoadJob *job,
+                           gchar **contents,
+                           GError **error)
+{
+  FT_Error ft_error;
+  FT_Face retval;
+
+  ft_error = FT_New_Memory_Face (job->library,
+                                 (const FT_Byte *) job->face_contents,
+                                 (FT_Long) job->face_length,
+                                 job->face_index,
+                                 &retval);
+
+  if (ft_error != 0) {
+    g_set_error_literal (error, G_IO_ERROR, 0,
+                         "Unable to read the font face file");
+    retval = NULL;
+    g_free (job->face_contents);
+  } else {
+    *contents = job->face_contents;
+  }
+
+  return retval;
+}
+
+static gboolean
+font_load_job_callback (gpointer user_data)
+{
+  FontLoadJob *job = user_data;
+
+  g_simple_async_result_complete (job->result);
+  font_load_job_free (job);
+
+  return FALSE;
+}
+
+static void
+font_load_job_do_load (FontLoadJob *job,
+                       GError **error)
+{
+  gchar *contents;
+  gsize length;
+
+  g_file_load_contents (job->file, NULL,
+                        &contents, &length, NULL, error);
+
+  if ((error != NULL) && (*error == NULL)) {
+    job->face_contents = contents;
+    job->face_length = length;
+  }
+}
+
+static gboolean
+font_load_job (GIOSchedulerJob *sched_job,
+               GCancellable *cancellable,
+               gpointer user_data)
+{
+  FontLoadJob *job = user_data;
+  GError *error = NULL;
+
+  font_load_job_do_load (job, &error);
+
+  if (error != NULL)
+    g_simple_async_result_take_error (job->result, error);
+
+  g_io_scheduler_job_send_to_mainloop_async (sched_job,
+                                             font_load_job_callback,
+                                             job, NULL);
+
+  return FALSE;
+}
+
+/**
+ * sushi_new_ft_face_from_uri: (skip)
+ *
+ */
+FT_Face
+sushi_new_ft_face_from_uri (FT_Library library,
+                            const gchar *uri,
+                            gchar **contents,
+                            GError **error)
+{
+  FontLoadJob *job = NULL;
+
+  job = font_load_job_new (library, uri, NULL, NULL);
+  font_load_job_do_load (job, error);
+
+  if ((error != NULL) && (*error != NULL)) {
+    g_object_unref (job);
+    return NULL;
+  }
+
+  return create_face_from_contents (job, contents, error);
+}
+
+/**
+ * sushi_new_ft_face_from_uri_async: (skip)
+ *
+ */
+void
+sushi_new_ft_face_from_uri_async (FT_Library library,
+                                  const gchar *uri,
+                                  GAsyncReadyCallback callback,
+                                  gpointer user_data)
+{
+  FontLoadJob *job = font_load_job_new (library, uri, callback, user_data);
+  g_io_scheduler_push_job (font_load_job,
+                           job, NULL,
+                           G_PRIORITY_DEFAULT,
+                           NULL);
+}
+
+/**
+ * sushi_new_ft_face_from_uri_finish: (skip)
+ *
+ */
+FT_Face
+sushi_new_ft_face_from_uri_finish (GAsyncResult *result,
+                                   gchar **contents,
+                                   GError **error)
+{
+  FontLoadJob *job;
+
+  if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result),
+                                             error))
+    return NULL;
+
+  job = g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (result));
+
+  return create_face_from_contents (job, contents, error);
+}
+
diff -uprN mate-control-center/font-viewer/sushi-font-loader.h mate-control-center-test/font-viewer/sushi-font-loader.h
--- mate-control-center/font-viewer/sushi-font-loader.h	1970-01-01 01:00:00.000000000 +0100
+++ mate-control-center-test/font-viewer/sushi-font-loader.h	2015-08-22 19:05:17.189502025 +0200
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * 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.
+ *
+ * The Sushi project hereby grant permission for non-gpl compatible GStreamer
+ * plugins to be used and distributed together with GStreamer and Sushi. This
+ * permission is above and beyond the permissions granted by the GPL license
+ * Sushi is covered by.
+ *
+ * Authors: Cosimo Cecchi <cosimoc@redhat.com>
+ *
+ */
+
+#ifndef __SUSHI_FONT_LOADER_H__
+#define __SUSHI_FONT_LOADER_H__
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+#include <gio/gio.h>
+
+FT_Face sushi_new_ft_face_from_uri (FT_Library library,
+                                    const gchar *uri,
+                                    gchar **contents,
+                                    GError **error);
+
+void sushi_new_ft_face_from_uri_async (FT_Library library,
+                                       const gchar *uri,
+                                       GAsyncReadyCallback callback,
+                                       gpointer user_data);
+
+FT_Face sushi_new_ft_face_from_uri_finish (GAsyncResult *result,
+                                           gchar **contents,
+                                           GError **error);
+
+#endif /* __SUSHI_FONT_LOADER_H__ */
+
diff -uprN mate-control-center/font-viewer/sushi-font-widget.c mate-control-center-test/font-viewer/sushi-font-widget.c
--- mate-control-center/font-viewer/sushi-font-widget.c	1970-01-01 01:00:00.000000000 +0100
+++ mate-control-center-test/font-viewer/sushi-font-widget.c	2015-08-22 19:06:06.859017427 +0200
@@ -0,0 +1,648 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * 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.
+ *
+ * The Sushi project hereby grant permission for non-gpl compatible GStreamer
+ * plugins to be used and distributed together with GStreamer and Sushi. This
+ * permission is above and beyond the permissions granted by the GPL license
+ * Sushi is covered by.
+ *
+ * Authors: Cosimo Cecchi <cosimoc@redhat.com>
+ *
+ */
+
+#include "sushi-font-widget.h"
+#include "sushi-font-loader.h"
+
+#include <math.h>
+
+enum {
+  PROP_URI = 1,
+  NUM_PROPERTIES
+};
+
+enum {
+  LOADED,
+  NUM_SIGNALS
+};
+
+struct _SushiFontWidgetPrivate {
+  gchar *uri;
+
+  FT_Library library;
+  FT_Face face;
+  gchar *face_contents;
+
+  const gchar *lowercase_text;
+  const gchar *uppercase_text;
+  const gchar *punctuation_text;
+
+  gchar *sample_string;
+
+  gchar *font_name;
+  gboolean font_supports_title;
+};
+
+static GParamSpec *properties[NUM_PROPERTIES] = { NULL, };
+static guint signals[NUM_SIGNALS] = { 0, };
+
+G_DEFINE_TYPE (SushiFontWidget, sushi_font_widget, GTK_TYPE_DRAWING_AREA);
+
+#define SURFACE_SIZE 4
+#define SECTION_SPACING 16
+
+#define TITLE_SIZE 6
+
+static const gchar lowercase_text_stock[] = "abcdefghijklmnopqrstuvwxyz";
+static const gchar uppercase_text_stock[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+static const gchar punctuation_text_stock[] = "0123456789.:,;(*!?')";
+
+/* adapted from gnome-utils:font-viewer/font-view.c
+ *
+ * Copyright (C) 2002-2003  James Henstridge <james@daa.com.au>
+ * Copyright (C) 2010 Cosimo Cecchi <cosimoc@gnome.org>
+ *
+ * License: GPLv2+
+ */
+static void
+draw_string (cairo_t *cr,
+             GtkBorder padding,
+	     const gchar *text,
+	     gint *pos_y)
+{
+  cairo_font_extents_t font_extents;
+  cairo_text_extents_t extents;
+
+  cairo_font_extents (cr, &font_extents);
+  cairo_text_extents (cr, text, &extents);
+
+  if (pos_y != NULL)
+    *pos_y += font_extents.ascent + font_extents.descent +
+      extents.y_advance + padding.top;
+
+  cairo_move_to (cr, padding.left, *pos_y);
+  cairo_show_text (cr, text);
+
+  *pos_y += padding.bottom;
+}
+
+static gboolean
+check_font_contain_text (FT_Face face,
+                         const gchar *text)
+{
+  gunichar *string;
+  glong len, idx, map;
+  FT_CharMap charmap;
+  gboolean retval;
+
+  string = g_utf8_to_ucs4_fast (text, -1, &len);
+
+  for (map = 0; map < face->num_charmaps; map++) {
+    charmap = face->charmaps[map];
+    FT_Set_Charmap (face, charmap);
+
+    retval = TRUE;
+
+    for (idx = 0; idx < len; idx++) {
+      gunichar c = string[idx];
+
+      if (!FT_Get_Char_Index (face, c)) {
+        retval = FALSE;
+        break;
+      }
+    }
+
+    if (retval)
+      break;
+  }
+
+  g_free (string);
+
+  return retval;
+}
+
+static gchar *
+build_charlist_for_face (FT_Face face)
+{
+  GString *string;
+  gulong c;
+  guint glyph;  
+
+  string = g_string_new (NULL);
+
+  /* exclude normal ASCII characters here */
+  c = 255;
+  glyph = 0;
+
+  do {
+    c = FT_Get_Next_Char (face, c, &glyph);
+    g_string_append_unichar (string, (gunichar) c);
+  } while (glyph != 0);
+
+  return g_string_free (string, FALSE);
+}
+
+static gchar *
+random_string_from_available_chars (FT_Face face,
+                                    gint n_chars)
+{
+  gchar *chars;
+  gint idx, rand, total_chars;
+  GString *retval;
+  gchar *ptr, *end;
+
+  idx = 0;
+  chars = build_charlist_for_face (face);
+
+  retval = g_string_new (NULL);
+  total_chars = g_utf8_strlen (chars, -1);
+
+  while (idx < n_chars) {
+    rand = g_random_int_range (0, total_chars);
+
+    ptr = g_utf8_offset_to_pointer (chars, rand);
+    end = g_utf8_find_next_char (ptr, NULL);
+
+    g_string_append_len (retval, ptr, end - ptr);
+    idx++;
+  }
+
+  return g_string_free (retval, FALSE);
+}
+
+static void
+build_strings_for_face (SushiFontWidget *self)
+{
+  const gchar *sample_string;
+
+  /* if we don't have lowercase/uppercase/punctuation text in the face,
+   * we omit it directly, and render a random text below.
+   */
+  if (check_font_contain_text (self->priv->face, lowercase_text_stock))
+    self->priv->lowercase_text = lowercase_text_stock;
+  else
+    self->priv->lowercase_text = NULL;
+
+  if (check_font_contain_text (self->priv->face, uppercase_text_stock))
+    self->priv->uppercase_text = uppercase_text_stock;
+  else
+    self->priv->uppercase_text = NULL;
+
+  if (check_font_contain_text (self->priv->face, punctuation_text_stock))
+    self->priv->punctuation_text = punctuation_text_stock;
+  else
+    self->priv->punctuation_text = NULL;
+
+  sample_string = pango_language_get_sample_string (NULL);
+
+  if (check_font_contain_text (self->priv->face, sample_string))
+    self->priv->sample_string = g_strdup (sample_string);
+  else
+    self->priv->sample_string = random_string_from_available_chars (self->priv->face, 36);
+
+  self->priv->font_name =
+    g_strconcat (self->priv->face->family_name, " ",
+                 self->priv->face->style_name, NULL);
+  self->priv->font_supports_title =
+    check_font_contain_text (self->priv->face, self->priv->font_name);
+}
+
+static gint *
+build_sizes_table (FT_Face face,
+		   gint *n_sizes,
+		   gint *alpha_size)
+{
+  gint *sizes = NULL;
+  gint i;
+
+  /* work out what sizes to render */
+  if (FT_IS_SCALABLE (face)) {
+    *n_sizes = 14;
+    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;
+    sizes[8] = 96;
+    sizes[9] = 120;
+    sizes[10] = 144;
+    sizes[11] = 168;
+    sizes[12] = 192;
+    sizes[13] = 216;
+    *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;
+    }
+  }
+
+  return sizes;
+}
+
+static void
+sushi_font_widget_size_request (GtkWidget *drawing_area,
+                                gint *width,
+                                gint *height,
+                                gint *min_height)
+{
+  SushiFontWidget *self = SUSHI_FONT_WIDGET (drawing_area);
+  SushiFontWidgetPrivate *priv = self->priv;
+  gint i, pixmap_width, pixmap_height;
+  cairo_text_extents_t extents;
+  cairo_font_extents_t font_extents;
+  cairo_font_face_t *font;
+  gint *sizes = NULL, n_sizes, alpha_size;
+  cairo_t *cr;
+  cairo_surface_t *surface;
+  FT_Face face = priv->face;
+  GtkStyleContext *context;
+  GtkStateFlags state;
+  GtkBorder padding;
+
+  if (face == NULL) {
+    if (width != NULL)
+      *width = 1;
+    if (height != NULL)
+      *height = 1;
+    if (min_height != NULL)
+      *min_height = 1;
+
+    return;
+  }
+
+  surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
+                                        SURFACE_SIZE, SURFACE_SIZE);
+  cr = cairo_create (surface);
+  context = gtk_widget_get_style_context (drawing_area);
+  state = gtk_style_context_get_state (context);
+  gtk_style_context_get_padding (context, state, &padding);
+
+  sizes = build_sizes_table (face, &n_sizes, &alpha_size);
+
+  /* calculate size of pixmap to use */
+  pixmap_width = padding.left + padding.right;
+  pixmap_height = 0;
+
+  font = cairo_ft_font_face_create_for_ft_face (face, 0);
+  cairo_set_font_face (cr, font);
+  cairo_font_face_destroy (font);
+
+  if (self->priv->font_supports_title) {
+      cairo_set_font_size (cr, sizes[TITLE_SIZE]);
+      cairo_font_extents (cr, &font_extents);
+      cairo_text_extents (cr, self->priv->font_name, &extents);
+      pixmap_height += font_extents.ascent + font_extents.descent +
+        extents.y_advance + padding.top + padding.bottom;
+      pixmap_width = MAX (pixmap_width, extents.width + padding.left + padding.right);
+  }
+
+  pixmap_height += SECTION_SPACING / 2;
+  cairo_set_font_size (cr, alpha_size);
+  cairo_font_extents (cr, &font_extents);
+
+  if (self->priv->lowercase_text != NULL) {
+    cairo_text_extents (cr, self->priv->lowercase_text, &extents);
+    pixmap_height += font_extents.ascent + font_extents.descent + 
+      extents.y_advance + padding.top + padding.bottom;
+    pixmap_width = MAX (pixmap_width, extents.width + padding.left + padding.right);
+  }
+
+  if (self->priv->uppercase_text != NULL) {
+    cairo_text_extents (cr, self->priv->uppercase_text, &extents);
+    pixmap_height += font_extents.ascent + font_extents.descent +
+      extents.y_advance + padding.top + padding.bottom;
+    pixmap_width = MAX (pixmap_width, extents.width + padding.left + padding.right);
+  }
+
+  if (self->priv->punctuation_text != NULL) {
+    cairo_text_extents (cr, self->priv->punctuation_text, &extents);
+    pixmap_height += font_extents.ascent + font_extents.descent +
+      extents.y_advance + padding.top + padding.bottom;
+    pixmap_width = MAX (pixmap_width, extents.width + padding.left + padding.right);
+  }
+
+  pixmap_height += SECTION_SPACING;
+
+  for (i = 0; i < n_sizes; i++) {
+    cairo_set_font_size (cr, sizes[i]);
+    cairo_font_extents (cr, &font_extents);
+    cairo_text_extents (cr, self->priv->sample_string, &extents);
+    pixmap_height += font_extents.ascent + font_extents.descent +
+      extents.y_advance + padding.top + padding.bottom;
+    pixmap_width = MAX (pixmap_width, extents.width + padding.left + padding.right);
+
+    if ((i == 7) && (min_height != NULL))
+      *min_height = pixmap_height;
+  }
+
+  pixmap_height += padding.bottom + SECTION_SPACING;
+
+  if (width != NULL)
+    *width = pixmap_width;
+
+  if (height != NULL)
+    *height = pixmap_height;
+
+  cairo_destroy (cr);
+  cairo_surface_destroy (surface);
+  g_free (sizes);
+}
+
+static void
+sushi_font_widget_get_preferred_width (GtkWidget *drawing_area,
+                                       gint *minimum_width,
+                                       gint *natural_width)
+{
+  gint width;
+
+  sushi_font_widget_size_request (drawing_area, &width, NULL, NULL);
+
+  *minimum_width = *natural_width = width;
+}
+
+static void
+sushi_font_widget_get_preferred_height (GtkWidget *drawing_area,
+                                        gint *minimum_height,
+                                        gint *natural_height)
+{
+  gint height, min_height;
+
+  sushi_font_widget_size_request (drawing_area, NULL, &height, &min_height);
+
+  *minimum_height = min_height;
+  *natural_height = height;
+}
+
+static gboolean
+sushi_font_widget_draw (GtkWidget *drawing_area,
+                        cairo_t *cr)
+{
+  SushiFontWidget *self = SUSHI_FONT_WIDGET (drawing_area);
+  SushiFontWidgetPrivate *priv = self->priv;
+  gint *sizes = NULL, n_sizes, alpha_size, pos_y = 0, i;
+  cairo_font_face_t *font;
+  FT_Face face = priv->face;
+  GtkStyleContext *context;
+  GdkRGBA color;
+  GtkBorder padding;
+  GtkStateFlags state;
+  gint allocated_height;
+
+  if (face == NULL)
+    goto end;
+
+  context = gtk_widget_get_style_context (drawing_area);
+  state = gtk_style_context_get_state (context);
+  gtk_style_context_get_color (context, state, &color);
+  gtk_style_context_get_padding (context, state, &padding);
+
+  gdk_cairo_set_source_rgba (cr, &color);
+
+  sizes = build_sizes_table (face, &n_sizes, &alpha_size);
+
+  font = cairo_ft_font_face_create_for_ft_face (face, 0);
+  cairo_set_font_face (cr, font);
+  cairo_font_face_destroy (font);
+
+  allocated_height = gtk_widget_get_allocated_height (drawing_area);
+
+  /* draw text */
+
+  if (self->priv->font_supports_title) {
+    cairo_set_font_size (cr, sizes[TITLE_SIZE]);
+    draw_string (cr, padding, self->priv->font_name, &pos_y);
+  }
+
+  if (pos_y > allocated_height)
+    goto end;
+
+  pos_y += SECTION_SPACING / 2;
+  cairo_set_font_size (cr, alpha_size);
+
+  if (self->priv->lowercase_text != NULL)
+    draw_string (cr, padding, self->priv->lowercase_text, &pos_y);
+  if (pos_y > allocated_height)
+    goto end;
+
+  if (self->priv->uppercase_text != NULL)
+    draw_string (cr, padding, self->priv->uppercase_text, &pos_y);
+  if (pos_y > allocated_height)
+    goto end;
+
+  if (self->priv->punctuation_text != NULL)
+    draw_string (cr, padding, self->priv->punctuation_text, &pos_y);
+  if (pos_y > allocated_height)
+    goto end;
+
+  pos_y += SECTION_SPACING;
+
+  for (i = 0; i < n_sizes; i++) {
+    cairo_set_font_size (cr, sizes[i]);
+    draw_string (cr, padding, self->priv->sample_string, &pos_y);
+    if (pos_y > allocated_height)
+      break;
+  }
+
+ end:
+  g_free (sizes);
+
+  return FALSE;
+}
+
+static void
+font_face_async_ready_cb (GObject *object,
+                          GAsyncResult *result,
+                          gpointer user_data)
+{
+  SushiFontWidget *self = user_data;
+  GError *error = NULL;
+
+  self->priv->face =
+    sushi_new_ft_face_from_uri_finish (result,
+                                       &self->priv->face_contents,
+                                       &error);
+
+  if (error != NULL) {
+    /* FIXME: need to signal the error */
+    g_print ("Can't load the font face: %s\n", error->message);
+    g_error_free (error);
+
+    return;
+  }
+
+  build_strings_for_face (self);
+
+  gtk_widget_queue_resize (GTK_WIDGET (self));
+  g_signal_emit (self, signals[LOADED], 0);
+}
+
+static void
+load_font_face (SushiFontWidget *self)
+{
+  sushi_new_ft_face_from_uri_async (self->priv->library,
+                                    self->priv->uri,
+                                    font_face_async_ready_cb,
+                                    self);
+}
+
+static void
+sushi_font_widget_set_uri (SushiFontWidget *self,
+                           const gchar *uri)
+{
+  g_free (self->priv->uri);
+  self->priv->uri = g_strdup (uri);
+
+  load_font_face (self);
+}
+
+static void
+sushi_font_widget_init (SushiFontWidget *self)
+{
+  FT_Error err;
+
+  self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, SUSHI_TYPE_FONT_WIDGET,
+                                            SushiFontWidgetPrivate);
+
+  self->priv->face = NULL;
+  err = FT_Init_FreeType (&self->priv->library);
+
+  if (err != FT_Err_Ok)
+    g_error ("Unable to initialize FreeType");
+}
+
+static void
+sushi_font_widget_get_property (GObject *object,
+                                guint       prop_id,
+                                GValue     *value,
+                                GParamSpec *pspec)
+{
+  SushiFontWidget *self = SUSHI_FONT_WIDGET (object);
+
+  switch (prop_id) {
+  case PROP_URI:
+    g_value_set_string (value, self->priv->uri);
+    break;
+  default:
+    G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    break;
+  }
+}
+
+static void
+sushi_font_widget_set_property (GObject *object,
+                               guint       prop_id,
+                               const GValue *value,
+                               GParamSpec *pspec)
+{
+  SushiFontWidget *self = SUSHI_FONT_WIDGET (object);
+
+  switch (prop_id) {
+  case PROP_URI:
+    sushi_font_widget_set_uri (self, g_value_get_string (value));
+    break;
+  default:
+    G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    break;
+  }
+}
+
+static void
+sushi_font_widget_finalize (GObject *object)
+{
+  SushiFontWidget *self = SUSHI_FONT_WIDGET (object);
+
+  g_free (self->priv->uri);
+
+  if (self->priv->face != NULL) {
+    FT_Done_Face (self->priv->face);
+    self->priv->face = NULL;
+  }
+
+  g_free (self->priv->font_name);
+  g_free (self->priv->sample_string);
+  g_free (self->priv->face_contents);
+
+  if (self->priv->library != NULL) {
+    FT_Done_FreeType (self->priv->library);
+    self->priv->library = NULL;
+  }
+
+  G_OBJECT_CLASS (sushi_font_widget_parent_class)->finalize (object);
+}
+
+static void
+sushi_font_widget_class_init (SushiFontWidgetClass *klass)
+{
+  GObjectClass *oclass = G_OBJECT_CLASS (klass);
+  GtkWidgetClass *wclass = GTK_WIDGET_CLASS (klass);
+
+  oclass->finalize = sushi_font_widget_finalize;
+  oclass->set_property = sushi_font_widget_set_property;
+  oclass->get_property = sushi_font_widget_get_property;
+
+  wclass->draw = sushi_font_widget_draw;
+  wclass->get_preferred_width = sushi_font_widget_get_preferred_width;
+  wclass->get_preferred_height = sushi_font_widget_get_preferred_height;
+
+  properties[PROP_URI] =
+    g_param_spec_string ("uri",
+                         "Uri", "Uri",
+                         NULL, G_PARAM_READWRITE);
+
+  signals[LOADED] =
+    g_signal_new ("loaded",
+                  G_TYPE_FROM_CLASS (klass),
+                  G_SIGNAL_RUN_FIRST,
+                  0, NULL, NULL,
+                  g_cclosure_marshal_VOID__VOID,
+                  G_TYPE_NONE, 0);
+
+  g_object_class_install_properties (oclass, NUM_PROPERTIES, properties);
+  g_type_class_add_private (klass, sizeof (SushiFontWidgetPrivate));
+}
+
+SushiFontWidget *
+sushi_font_widget_new (const gchar *uri)
+{
+  return g_object_new (SUSHI_TYPE_FONT_WIDGET,
+                       "uri", uri,
+                       NULL);
+}
+
+/**
+ * sushi_font_widget_get_ft_face: (skip)
+ *
+ */
+FT_Face
+sushi_font_widget_get_ft_face (SushiFontWidget *self)
+{
+  return self->priv->face;
+}
+
diff -uprN mate-control-center/font-viewer/sushi-font-widget.h mate-control-center-test/font-viewer/sushi-font-widget.h
--- mate-control-center/font-viewer/sushi-font-widget.h	1970-01-01 01:00:00.000000000 +0100
+++ mate-control-center-test/font-viewer/sushi-font-widget.h	2015-08-22 19:06:52.720492574 +0200
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * 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.
+ *
+ * The Sushi project hereby grant permission for non-gpl compatible GStreamer
+ * plugins to be used and distributed together with GStreamer and Sushi. This
+ * permission is above and beyond the permissions granted by the GPL license
+ * Sushi is covered by.
+ *
+ * Authors: Cosimo Cecchi <cosimoc@redhat.com>
+ *
+ */
+
+#ifndef __SUSHI_FONT_WIDGET_H__
+#define __SUSHI_FONT_WIDGET_H__
+
+#include <glib-object.h>
+#include <gtk/gtk.h>
+#include <cairo/cairo-ft.h>
+
+G_BEGIN_DECLS
+
+#define SUSHI_TYPE_FONT_WIDGET            (sushi_font_widget_get_type ())
+#define SUSHI_FONT_WIDGET(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), SUSHI_TYPE_FONT_WIDGET, SushiFontWidget))
+#define SUSHI_IS_FONT_WIDGET(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SUSHI_TYPE_FONT_WIDGET))
+#define SUSHI_FONT_WIDGET_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass),  SUSHI_TYPE_FONT_WIDGET, SushiFontWidgetClass))
+#define SUSHI_IS_FONT_WIDGET_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),  SUSHI_TYPE_FONT_WIDGET))
+#define SUSHI_FONT_WIDGET_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj),  SUSHI_TYPE_FONT_WIDGET, SushiFontWidgetClass))
+
+typedef struct _SushiFontWidget          SushiFontWidget;
+typedef struct _SushiFontWidgetPrivate   SushiFontWidgetPrivate;
+typedef struct _SushiFontWidgetClass     SushiFontWidgetClass;
+
+struct _SushiFontWidget
+{
+  GtkDrawingArea parent_instance;
+
+  SushiFontWidgetPrivate *priv;
+};
+
+struct _SushiFontWidgetClass
+{
+  GtkDrawingAreaClass parent_class;
+};
+
+GType    sushi_font_widget_get_type     (void) G_GNUC_CONST;
+
+SushiFontWidget *sushi_font_widget_new (const gchar *uri);
+
+FT_Face sushi_font_widget_get_ft_face (SushiFontWidget *self);
+
+G_END_DECLS
+
+#endif /* __SUSHI_FONT_WIDGET_H__ */
+
 
дизайн и разработка: Vladimir Lettiev aka crux © 2004-2005, Andrew Avramenko aka liks © 2007-2008
текущий майнтейнер: Michael Shigorin