split code for drawing character into separate function. (save_pixbuf):
2002-12-02 James Henstridge <james@daa.com.au> * src/thumbnailer.c (draw_char): split code for drawing character into separate function. (save_pixbuf): function to save the pixbuf. We crop the pixbuf leaving PAD_PIXELS pixels round the edges. * src/ftstream-vfs.c (FT_New_URI_Face): unset the FT_FACE_FLAG_EXTERNAL_STREAM flag on the face, so that it gets freed with the face. (this is a bit of a hack ...).
This commit is contained in:
parent
dd78dff000
commit
01e468fc57
3 changed files with 146 additions and 50 deletions
|
@ -1,5 +1,10 @@
|
||||||
2002-12-02 James Henstridge <james@daa.com.au>
|
2002-12-02 James Henstridge <james@daa.com.au>
|
||||||
|
|
||||||
|
* src/thumbnailer.c (draw_char): split code for drawing character
|
||||||
|
into separate function.
|
||||||
|
(save_pixbuf): function to save the pixbuf. We crop the pixbuf
|
||||||
|
leaving PAD_PIXELS pixels round the edges.
|
||||||
|
|
||||||
* src/ftstream-vfs.c (FT_New_URI_Face): unset the
|
* src/ftstream-vfs.c (FT_New_URI_Face): unset the
|
||||||
FT_FACE_FLAG_EXTERNAL_STREAM flag on the face, so that it gets
|
FT_FACE_FLAG_EXTERNAL_STREAM flag on the face, so that it gets
|
||||||
freed with the face. (this is a bit of a hack ...).
|
freed with the face. (this is a bit of a hack ...).
|
||||||
|
|
|
@ -108,7 +108,7 @@ FT_New_URI_Face(FT_Library library,
|
||||||
error = FT_Open_Face(library, &args, face_index, aface);
|
error = FT_Open_Face(library, &args, face_index, aface);
|
||||||
|
|
||||||
if (error != FT_Err_Ok) {
|
if (error != FT_Err_Ok) {
|
||||||
stream->close(stream);
|
if (stream->close) stream->close(stream);
|
||||||
free(stream);
|
free(stream);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,16 @@
|
||||||
/* -*- mode: C; c-basic-offset: 4 -*- */
|
/* -*- mode: C; c-basic-offset: 4 -*- */
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
#include <ft2build.h>
|
#include <ft2build.h>
|
||||||
#include FT_FREETYPE_H
|
#include FT_FREETYPE_H
|
||||||
|
|
||||||
#include <libgnomevfs/gnome-vfs.h>
|
#include <libgnomevfs/gnome-vfs.h>
|
||||||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||||
|
|
||||||
|
#define FONT_SIZE 64
|
||||||
|
#define PAD_PIXELS 4
|
||||||
|
|
||||||
FT_Error FT_New_URI_Face(FT_Library library,
|
FT_Error FT_New_URI_Face(FT_Library library,
|
||||||
const gchar *uri,
|
const gchar *uri,
|
||||||
FT_Long face_index,
|
FT_Long face_index,
|
||||||
|
@ -41,102 +46,188 @@ draw_bitmap(GdkPixbuf *pixbuf, FT_Bitmap *bitmap, gint off_x, gint off_y)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
draw_char(GdkPixbuf *pixbuf, FT_Face face, gchar character,
|
||||||
|
gint *pen_x, gint *pen_y)
|
||||||
|
{
|
||||||
|
FT_Error error;
|
||||||
|
FT_GlyphSlot slot;
|
||||||
|
|
||||||
|
slot = face->glyph;
|
||||||
|
error = FT_Load_Char(face, character, FT_LOAD_RENDER);
|
||||||
|
if (error) {
|
||||||
|
g_printerr("could not load character '%c'\n", character);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
g_assert(slot->bitmap.pixel_mode == ft_pixel_mode_grays);
|
||||||
|
|
||||||
|
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);
|
||||||
|
gdk_pixbuf_unref(subpixbuf);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char **argv)
|
main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
FT_Error error;
|
FT_Error error;
|
||||||
FT_Library library;
|
FT_Library library;
|
||||||
FT_Face face;
|
FT_Face face;
|
||||||
FT_GlyphSlot slot;
|
|
||||||
GdkPixbuf *pixbuf, *pixbuf2;
|
GdkPixbuf *pixbuf, *pixbuf2;
|
||||||
guchar *buffer;
|
guchar *buffer;
|
||||||
gint width, height, i, len, pen_x, pen_y, max_width, max_height;
|
gint i, len, pen_x, pen_y;
|
||||||
|
|
||||||
if (argc != 3) {
|
if (argc != 3) {
|
||||||
g_message("eek: bad args");
|
g_printerr("usage: thumbnailer fontfile output-image\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!gnome_vfs_init()) {
|
if (!gnome_vfs_init()) {
|
||||||
g_message("eek: gnome-vfs init");
|
g_printerr("could not initialise gnome-vfs\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
error = FT_Init_FreeType(&library);
|
error = FT_Init_FreeType(&library);
|
||||||
if (error) {
|
if (error) {
|
||||||
g_message("eek: library");
|
g_printerr("could not initialise freetype\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
error = FT_New_URI_Face(library, argv[1], 0, &face);
|
error = FT_New_URI_Face(library, argv[1], 0, &face);
|
||||||
if (error) {
|
if (error) {
|
||||||
g_message("eek: face");
|
g_printerr("could not load face '%s'\n", argv[1]);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
slot = face->glyph;
|
error = FT_Set_Pixel_Sizes(face, 0, FONT_SIZE);
|
||||||
|
|
||||||
error = FT_Set_Pixel_Sizes(face, 0, 64);
|
|
||||||
if (error) {
|
if (error) {
|
||||||
g_message("eek: set pixel size");
|
g_printerr("could not set pixel size\n");
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
error = FT_Load_Char(face, 'A', FT_LOAD_RENDER);
|
|
||||||
if (error) {
|
|
||||||
g_message("eek: load char");
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_assert(slot->bitmap.pixel_mode == ft_pixel_mode_grays);
|
pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8,
|
||||||
|
FONT_SIZE*3, FONT_SIZE*1.5);
|
||||||
width = slot->bitmap.width;
|
if (!pixbuf) {
|
||||||
height = slot->bitmap.rows;
|
g_printerr("could not create pixbuf\n");
|
||||||
|
return 1;
|
||||||
pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, width*3, height*1.5);
|
}
|
||||||
buffer = gdk_pixbuf_get_pixels(pixbuf);
|
buffer = gdk_pixbuf_get_pixels(pixbuf);
|
||||||
|
|
||||||
len = gdk_pixbuf_get_rowstride(pixbuf) * gdk_pixbuf_get_height(pixbuf);
|
len = gdk_pixbuf_get_rowstride(pixbuf) * gdk_pixbuf_get_height(pixbuf);
|
||||||
for (i = 0; i < len; i++)
|
for (i = 0; i < len; i++)
|
||||||
buffer[i] = 255;
|
buffer[i] = 255;
|
||||||
|
|
||||||
pen_x = 0;
|
pen_x = FONT_SIZE/2;
|
||||||
pen_y = slot->bitmap_top;
|
pen_y = FONT_SIZE;
|
||||||
max_height = height;
|
|
||||||
max_width = pen_x + slot->bitmap_left + width;
|
|
||||||
|
|
||||||
draw_bitmap(pixbuf, &slot->bitmap,
|
draw_char(pixbuf, face, 'A', &pen_x, &pen_y);
|
||||||
pen_x + slot->bitmap_left, pen_y - slot->bitmap_top);
|
draw_char(pixbuf, face, 'a', &pen_x, &pen_y);
|
||||||
|
|
||||||
pen_x += slot->advance.x >> 6;
|
save_pixbuf(pixbuf, argv[2]);
|
||||||
|
|
||||||
error = FT_Load_Char(face, 'a', FT_LOAD_RENDER);
|
|
||||||
if (error) {
|
|
||||||
g_message("ekk: load char 2");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
max_height = MAX(max_height, pen_y + slot->bitmap.rows -
|
|
||||||
slot->bitmap_top);
|
|
||||||
max_width = pen_x + slot->bitmap_left + slot->bitmap.width;
|
|
||||||
|
|
||||||
draw_bitmap(pixbuf, &slot->bitmap,
|
|
||||||
pen_x + slot->bitmap_left, pen_y - slot->bitmap_top);
|
|
||||||
|
|
||||||
pixbuf2 = gdk_pixbuf_new_subpixbuf(pixbuf, 0,0, max_width,max_height);
|
|
||||||
|
|
||||||
gdk_pixbuf_save(pixbuf2, argv[2], "png", NULL, NULL);
|
|
||||||
gdk_pixbuf_unref(pixbuf2);
|
|
||||||
gdk_pixbuf_unref(pixbuf);
|
gdk_pixbuf_unref(pixbuf);
|
||||||
|
|
||||||
/* freeing the face causes a crash I haven't tracked down yet */
|
/* freeing the face causes a crash I haven't tracked down yet */
|
||||||
error = FT_Done_Face(face);
|
error = FT_Done_Face(face);
|
||||||
if (error) {
|
if (error) {
|
||||||
g_message("eek: done face");
|
g_printerr("could not unload face\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
error = FT_Done_FreeType(library);
|
error = FT_Done_FreeType(library);
|
||||||
if (error) {
|
if (error) {
|
||||||
g_message("eek: done library");
|
g_printerr("could not finalise freetype library\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue