summaryrefslogtreecommitdiff
path: root/font-viewer/ftstream-vfs.c
diff options
context:
space:
mode:
Diffstat (limited to 'font-viewer/ftstream-vfs.c')
-rw-r--r--font-viewer/ftstream-vfs.c154
1 files changed, 154 insertions, 0 deletions
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;
+}