doxygen: add newline after \file
[blender.git] / source / blender / blenfont / intern / blf_font_win32_compat.c
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  */
16
17 /** \file
18  * \ingroup blf
19  *
20  * Workaround for win32 which needs to use BLI_fopen to access files.
21  *
22  * defines #FT_New_Face__win32_compat, a drop-in replacement for \a #FT_New_Face.
23  */
24
25 #ifdef WIN32
26
27 #include <stdio.h>
28
29 #include <ft2build.h>
30 #include FT_FREETYPE_H
31
32 #include "MEM_guardedalloc.h"
33
34 #include "BLI_utildefines.h"
35 #include "BLI_fileops.h"
36
37 #include "blf_internal.h"
38
39 /* internal freetype defines */
40 #define STREAM_FILE(stream)  ((FILE *)stream->descriptor.pointer)
41 #define FT_THROW(e) -1
42
43 static void ft_ansi_stream_close(
44         FT_Stream stream)
45 {
46         fclose(STREAM_FILE(stream));
47
48         stream->descriptor.pointer = NULL;
49         stream->size               = 0;
50         stream->base               = 0;
51
52         /* WARNING: this works but be careful!
53          * Checked freetype sources, there isn't any access after closing. */
54         MEM_freeN(stream);
55 }
56
57 static unsigned long ft_ansi_stream_io(
58         FT_Stream       stream,
59         unsigned long   offset,
60         unsigned char  *buffer,
61         unsigned long   count)
62 {
63         FILE *file;
64         if (!count && offset > stream->size)
65                 return 1;
66
67         file = STREAM_FILE(stream);
68
69         if (stream->pos != offset)
70                 fseek(file, offset, SEEK_SET);
71
72         return fread(buffer, 1, count, file);
73 }
74
75 static FT_Error FT_Stream_Open__win32_compat(FT_Stream stream, const char *filepathname)
76 {
77         FILE *file;
78         BLI_assert(stream);
79
80         stream->descriptor.pointer = NULL;
81         stream->pathname.pointer   = (char *)filepathname;
82         stream->base               = 0;
83         stream->pos                = 0;
84         stream->read               = NULL;
85         stream->close              = NULL;
86
87         file = BLI_fopen(filepathname, "rb");
88         if (!file) {
89                 fprintf(stderr,
90                         "FT_Stream_Open: "
91                         "could not open `%s'\n", filepathname);
92                 return FT_THROW(Cannot_Open_Resource);
93         }
94
95         fseek(file, 0, SEEK_END);
96         stream->size = ftell(file);
97         if (!stream->size) {
98                 fprintf(stderr,
99                         "FT_Stream_Open: "
100                         "opened `%s' but zero-sized\n", filepathname);
101                 fclose(file);
102                 return FT_THROW(Cannot_Open_Stream);
103         }
104
105         fseek(file, 0, SEEK_SET);
106
107         stream->descriptor.pointer = file;
108         stream->read  = ft_ansi_stream_io;
109         stream->close = ft_ansi_stream_close;
110
111         return FT_Err_Ok;
112 }
113
114 FT_Error FT_New_Face__win32_compat(
115         FT_Library   library,
116         const char  *pathname,
117         FT_Long      face_index,
118         FT_Face     *aface)
119 {
120         FT_Error err;
121         FT_Open_Args open;
122         FT_Stream stream = NULL;
123         stream = MEM_callocN(sizeof(*stream), __func__);
124
125         open.flags = FT_OPEN_STREAM;
126         open.stream = stream;
127         stream->pathname.pointer = (char *)pathname;
128
129         err = FT_Stream_Open__win32_compat(stream, pathname);
130         if (err) {
131                 MEM_freeN(stream);
132                 return err;
133         }
134
135         err = FT_Open_Face(library, &open, face_index, aface);
136         /* no need to free 'stream', its handled by FT_Open_Face if an error occurs */
137
138         return err;
139 }
140
141 #endif  /* WIN32 */