From bae5826b65412ebfa354d34024af971e94cd1839 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 12 Jan 2015 16:52:36 +1100 Subject: [PATCH] Fix T42069: Fonts /w non-ascii paths fail in win32 Workaround freetype's use of fopen by swapping FT_New_Face for our own version which uses BLI_fopen. --- source/blender/blenfont/CMakeLists.txt | 6 + source/blender/blenfont/intern/blf_font.c | 4 + .../blenfont/intern/blf_font_win32_compat.c | 145 ++++++++++++++++++ source/blender/blenfont/intern/blf_internal.h | 7 + 4 files changed, 162 insertions(+) create mode 100644 source/blender/blenfont/intern/blf_font_win32_compat.c diff --git a/source/blender/blenfont/CMakeLists.txt b/source/blender/blenfont/CMakeLists.txt index 346d5bc64b8..392a9ede100 100644 --- a/source/blender/blenfont/CMakeLists.txt +++ b/source/blender/blenfont/CMakeLists.txt @@ -56,6 +56,12 @@ set(SRC intern/blf_internal_types.h ) +if(WIN32) + list(APPEND SRC + intern/blf_font_win32_compat.c + ) +endif() + if(WITH_INTERNATIONAL) add_definitions(-DWITH_INTERNATIONAL) endif() diff --git a/source/blender/blenfont/intern/blf_font.c b/source/blender/blenfont/intern/blf_font.c index 4891c332c87..087c7c7345e 100644 --- a/source/blender/blenfont/intern/blf_font.c +++ b/source/blender/blenfont/intern/blf_font.c @@ -65,6 +65,10 @@ #include "BLI_strict_flags.h" +#ifdef WIN32 +# define FT_New_Face FT_New_Face__win32_compat +#endif + /* freetype2 handle ONLY for this file!. */ static FT_Library ft_lib; static SpinLock ft_lib_mutex; diff --git a/source/blender/blenfont/intern/blf_font_win32_compat.c b/source/blender/blenfont/intern/blf_font_win32_compat.c new file mode 100644 index 00000000000..dd4a443e69f --- /dev/null +++ b/source/blender/blenfont/intern/blf_font_win32_compat.c @@ -0,0 +1,145 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * 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. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/blenfont/intern/blf_font_win32_compat.c + * \ingroup blf + * + * Workaround for win32 which needs to use BLI_fopen to access files. + * + * defines #FT_New_Face__win32_compat, a drop-in replacement for \a #FT_New_Face. + */ + +#ifdef WIN32 + +#include + +#include +#include FT_FREETYPE_H + +#include "MEM_guardedalloc.h" + +#include "BLI_utildefines.h" +#include "BLI_fileops.h" + +#include "blf_internal.h" + +/* internal freetype defines */ +#define STREAM_FILE(stream) ((FILE *)stream->descriptor.pointer) +#define FT_THROW(e) -1 + +static void ft_ansi_stream_close( + FT_Stream stream) +{ + fclose(STREAM_FILE(stream)); + + stream->descriptor.pointer = NULL; + stream->size = 0; + stream->base = 0; + + /* WARNING: this works but be careful! + * Checked freetype sources, there isn't any access after closing. */ + MEM_freeN(stream); +} + +static unsigned long ft_ansi_stream_io( + FT_Stream stream, + unsigned long offset, + unsigned char *buffer, + unsigned long count) +{ + FILE *file; + if (!count && offset > stream->size) + return 1; + + file = STREAM_FILE(stream); + + if (stream->pos != offset) + fseek(file, offset, SEEK_SET); + + return fread(buffer, 1, count, file); +} + +static FT_Error FT_Stream_Open__win32_compat(FT_Stream stream, const char *filepathname) +{ + FILE *file; + BLI_assert(stream); + + stream->descriptor.pointer = NULL; + stream->pathname.pointer = (char *)filepathname; + stream->base = 0; + stream->pos = 0; + stream->read = NULL; + stream->close = NULL; + + file = BLI_fopen(filepathname, "rb"); + if (!file) { + fprintf(stderr, + "FT_Stream_Open: " + "could not open `%s'\n", filepathname); + return FT_THROW(Cannot_Open_Resource); + } + + fseek(file, 0, SEEK_END); + stream->size = ftell(file); + if (!stream->size) { + fprintf(stderr, + "FT_Stream_Open: " + "opened `%s' but zero-sized\n", filepathname); + fclose(file); + return FT_THROW(Cannot_Open_Stream); + } + + fseek(file, 0, SEEK_SET); + + stream->descriptor.pointer = file; + stream->read = ft_ansi_stream_io; + stream->close = ft_ansi_stream_close; + + return FT_Err_Ok; +} + +FT_Error FT_New_Face__win32_compat( + FT_Library library, + const char *pathname, + FT_Long face_index, + FT_Face *aface) +{ + FT_Error err; + FT_Open_Args open; + FT_Stream stream = NULL; + stream = MEM_callocN(sizeof(*stream), __func__); + + open.flags = FT_OPEN_STREAM; + open.stream = stream; + stream->pathname.pointer = (char *)pathname; + + err = FT_Stream_Open__win32_compat(stream, pathname); + if (err) { + MEM_freeN(stream); + return err; + } + + err = FT_Open_Face(library, &open, face_index, aface); + /* no need to free 'stream', its handled by FT_Open_Face if an error occurs */ + + return err; +} + +#endif /* WIN32 */ diff --git a/source/blender/blenfont/intern/blf_internal.h b/source/blender/blenfont/intern/blf_internal.h index 8cb2d377449..39b3e3397be 100644 --- a/source/blender/blenfont/intern/blf_internal.h +++ b/source/blender/blenfont/intern/blf_internal.h @@ -75,4 +75,11 @@ struct GlyphBLF *blf_glyph_add(struct FontBLF *font, unsigned int index, unsigne void blf_glyph_free(struct GlyphBLF *g); void blf_glyph_render(struct FontBLF *font, struct GlyphBLF *g, float x, float y); +#ifdef WIN32 +/* blf_font_win32_compat.c */ +# ifdef FT_FREETYPE_H +extern FT_Error FT_New_Face__win32_compat(FT_Library library, const char *pathname, FT_Long face_index, FT_Face *aface); +# endif +#endif + #endif /* __BLF_INTERNAL_H__ */