static const gchar * get_sample_string (FT_Face face) { const gchar *text; text = pango_language_get_sample_string (NULL); if (!check_font_contain_text (face, text)) { text = pango_language_get_sample_string (pango_language_from_string ("en_US")); } return text; }
static void build_strings_for_face (SushiFontWidget *self) { /* 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; if (!set_pango_sample_string (self)) self->priv->sample_string = random_string_from_available_chars (self->priv->face, 36); g_free (self->priv->font_name); self->priv->font_name = NULL; if (self->priv->face->family_name != NULL) { gchar *font_name = g_strconcat (self->priv->face->family_name, " ", self->priv->face->style_name, NULL); if (check_font_contain_text (self->priv->face, font_name)) self->priv->font_name = font_name; else g_free (font_name); } }
static gboolean set_pango_sample_string (SushiFontWidget *self) { const gchar *sample_string; gboolean retval = FALSE; sample_string = pango_language_get_sample_string (pango_language_from_string (NULL)); if (check_font_contain_text (self->priv->face, sample_string)) retval = TRUE; if (!retval) { sample_string = pango_language_get_sample_string (pango_language_from_string ("C")); if (check_font_contain_text (self->priv->face, sample_string)) retval = TRUE; } if (retval) { g_free (self->priv->sample_string); self->priv->sample_string = g_strdup (sample_string); } return retval; }
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; cairo_t *cr; 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; cr = gdk_cairo_create (pixmap); cairo_set_source_rgb (cr, 1, 1, 1); cairo_paint (cr); cairo_destroy (cr); 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; }
int main (int argc, char **argv) { FT_Error error; FT_Library library; FT_Face face; GFile *file; gint font_size, thumb_size = THUMB_SIZE; gchar *thumbstr_utf8 = NULL, *help, *uri; gchar **arguments = NULL; GOptionContext *context; GError *gerror = NULL; gchar *contents = NULL; gboolean retval, default_thumbstr = TRUE; gint rv = 1; GdkRGBA white = { 1.0, 1.0, 1.0, 1.0 }; GdkRGBA black = { 0.0, 0.0, 0.0, 1.0 }; cairo_surface_t *surface; cairo_t *cr; cairo_text_extents_t text_extents; cairo_font_face_t *font; gchar *str; gdouble scale, scale_x, scale_y; 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, &thumb_size, N_("Thumbnail size (default: 128)"), N_("SIZE") }, { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &arguments, NULL, N_("FONT-FILE OUTPUT-FILE") }, { NULL } }; bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR); bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); textdomain (GETTEXT_PACKAGE); setlocale (LC_ALL, ""); g_type_init (); 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); if (!retval) { g_printerr ("Error parsing arguments: %s\n", gerror->message); g_option_context_free (context); g_error_free (gerror); return 1; } if (!arguments || g_strv_length (arguments) != 2) { help = g_option_context_get_help (context, TRUE, NULL); g_printerr ("%s", help); g_option_context_free (context); goto out; } g_option_context_free (context); if (thumbstr_utf8 != NULL) default_thumbstr = FALSE; 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); face = sushi_new_ft_face_from_uri (library, uri, &contents, &gerror); if (gerror) { g_printerr ("Could not load face '%s': %s\n", uri, gerror->message); g_free (uri); g_error_free (gerror); goto out; } g_free (uri); if (default_thumbstr) { if (check_font_contain_text (face, "Aa")) str = g_strdup ("Aa"); else str = build_fallback_thumbstr (face); } else { str = thumbstr_utf8; } surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, thumb_size, thumb_size); cr = cairo_create (surface); gdk_cairo_set_source_rgba (cr, &white); cairo_paint (cr); font = cairo_ft_font_face_create_for_ft_face (face, 0); cairo_set_font_face (cr, font); cairo_font_face_destroy (font); font_size = thumb_size - 2 * PADDING_VERTICAL; cairo_set_font_size (cr, font_size); cairo_text_extents (cr, str, &text_extents); if ((text_extents.width) > (thumb_size - 2 * PADDING_HORIZONTAL)) { scale_x = (gdouble) (thumb_size - 2 * PADDING_HORIZONTAL) / (text_extents.width); } else { scale_x = 1.0; } if ((text_extents.height) > (thumb_size - 2 * PADDING_VERTICAL)) { scale_y = (gdouble) (thumb_size - 2 * PADDING_VERTICAL) / (text_extents.height); } else { scale_y = 1.0; } scale = MIN (scale_x, scale_y); cairo_scale (cr, scale, scale); cairo_translate (cr, PADDING_HORIZONTAL - text_extents.x_bearing + (thumb_size - scale * text_extents.width) / 2.0, PADDING_VERTICAL - text_extents.y_bearing + (thumb_size - scale * text_extents.height) / 2.0); gdk_cairo_set_source_rgba (cr, &black); cairo_show_text (cr, str); cairo_destroy (cr); cairo_surface_write_to_png (surface, arguments[1]); cairo_surface_destroy (surface); totem_resources_monitor_stop (); 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 finalize freetype library: %s\n", get_ft_error (error)); goto out; } rv = 0; /* success */ out: g_strfreev (arguments); g_free (str); g_free (contents); return rv; }