🛠️🐜 Antkeeper superbuild with dependencies included https://antkeeper.com
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

386 lines
9.1 KiB

  1. /****************************************************************************
  2. *
  3. * ftsystem.c
  4. *
  5. * Windows-specific FreeType low-level system interface (body).
  6. *
  7. * Copyright (C) 2021 by
  8. * David Turner, Robert Wilhelm, and Werner Lemberg.
  9. *
  10. * This file is part of the FreeType project, and may only be used,
  11. * modified, and distributed under the terms of the FreeType project
  12. * license, LICENSE.TXT. By continuing to use, modify, or distribute
  13. * this file you indicate that you have read the license and
  14. * understand and accept it fully.
  15. *
  16. */
  17. #include <ft2build.h>
  18. /* we use our special ftconfig.h file, not the standard one */
  19. #include FT_CONFIG_CONFIG_H
  20. #include <freetype/internal/ftdebug.h>
  21. #include <freetype/ftsystem.h>
  22. #include <freetype/fterrors.h>
  23. #include <freetype/fttypes.h>
  24. #include <freetype/internal/ftstream.h>
  25. /* memory-mapping includes and definitions */
  26. #include <windows.h>
  27. #include <stdlib.h>
  28. /**************************************************************************
  29. *
  30. * MEMORY MANAGEMENT INTERFACE
  31. *
  32. */
  33. /**************************************************************************
  34. *
  35. * It is not necessary to do any error checking for the
  36. * allocation-related functions. This will be done by the higher level
  37. * routines like ft_mem_alloc() or ft_mem_realloc().
  38. *
  39. */
  40. /**************************************************************************
  41. *
  42. * @Function:
  43. * ft_alloc
  44. *
  45. * @Description:
  46. * The memory allocation function.
  47. *
  48. * @Input:
  49. * memory ::
  50. * A pointer to the memory object.
  51. *
  52. * size ::
  53. * The requested size in bytes.
  54. *
  55. * @Return:
  56. * The address of newly allocated block.
  57. */
  58. FT_CALLBACK_DEF( void* )
  59. ft_alloc( FT_Memory memory,
  60. long size )
  61. {
  62. FT_UNUSED( memory );
  63. return malloc( size );
  64. }
  65. /**************************************************************************
  66. *
  67. * @Function:
  68. * ft_realloc
  69. *
  70. * @Description:
  71. * The memory reallocation function.
  72. *
  73. * @Input:
  74. * memory ::
  75. * A pointer to the memory object.
  76. *
  77. * cur_size ::
  78. * The current size of the allocated memory block.
  79. *
  80. * new_size ::
  81. * The newly requested size in bytes.
  82. *
  83. * block ::
  84. * The current address of the block in memory.
  85. *
  86. * @Return:
  87. * The address of the reallocated memory block.
  88. */
  89. FT_CALLBACK_DEF( void* )
  90. ft_realloc( FT_Memory memory,
  91. long cur_size,
  92. long new_size,
  93. void* block )
  94. {
  95. FT_UNUSED( memory );
  96. FT_UNUSED( cur_size );
  97. return realloc( block, new_size );
  98. }
  99. /**************************************************************************
  100. *
  101. * @Function:
  102. * ft_free
  103. *
  104. * @Description:
  105. * The memory release function.
  106. *
  107. * @Input:
  108. * memory ::
  109. * A pointer to the memory object.
  110. *
  111. * block ::
  112. * The address of block in memory to be freed.
  113. */
  114. FT_CALLBACK_DEF( void )
  115. ft_free( FT_Memory memory,
  116. void* block )
  117. {
  118. FT_UNUSED( memory );
  119. free( block );
  120. }
  121. /**************************************************************************
  122. *
  123. * RESOURCE MANAGEMENT INTERFACE
  124. *
  125. */
  126. /**************************************************************************
  127. *
  128. * The macro FT_COMPONENT is used in trace mode. It is an implicit
  129. * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
  130. * messages during execution.
  131. */
  132. #undef FT_COMPONENT
  133. #define FT_COMPONENT io
  134. /* We use the macro STREAM_FILE for convenience to extract the */
  135. /* system-specific stream handle from a given FreeType stream object */
  136. #define STREAM_FILE( stream ) ( (FILE*)stream->descriptor.pointer )
  137. /**************************************************************************
  138. *
  139. * @Function:
  140. * ft_close_stream_by_munmap
  141. *
  142. * @Description:
  143. * The function to close a stream which is opened by mmap.
  144. *
  145. * @Input:
  146. * stream :: A pointer to the stream object.
  147. */
  148. FT_CALLBACK_DEF( void )
  149. ft_close_stream_by_munmap( FT_Stream stream )
  150. {
  151. UnmapViewOfFile( (LPCVOID)stream->descriptor.pointer );
  152. stream->descriptor.pointer = NULL;
  153. stream->size = 0;
  154. stream->base = 0;
  155. }
  156. /**************************************************************************
  157. *
  158. * @Function:
  159. * ft_close_stream_by_free
  160. *
  161. * @Description:
  162. * The function to close a stream which is created by ft_alloc.
  163. *
  164. * @Input:
  165. * stream :: A pointer to the stream object.
  166. */
  167. FT_CALLBACK_DEF( void )
  168. ft_close_stream_by_free( FT_Stream stream )
  169. {
  170. ft_free( NULL, stream->descriptor.pointer );
  171. stream->descriptor.pointer = NULL;
  172. stream->size = 0;
  173. stream->base = 0;
  174. }
  175. /* documentation is in ftobjs.h */
  176. FT_BASE_DEF( FT_Error )
  177. FT_Stream_Open( FT_Stream stream,
  178. const char* filepathname )
  179. {
  180. HANDLE file;
  181. HANDLE fm;
  182. LARGE_INTEGER size;
  183. if ( !stream )
  184. return FT_THROW( Invalid_Stream_Handle );
  185. /* open the file */
  186. file = CreateFileA( filepathname, GENERIC_READ, FILE_SHARE_READ, NULL,
  187. OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0 );
  188. if ( file == INVALID_HANDLE_VALUE )
  189. {
  190. FT_ERROR(( "FT_Stream_Open:" ));
  191. FT_ERROR(( " could not open `%s'\n", filepathname ));
  192. return FT_THROW( Cannot_Open_Resource );
  193. }
  194. if ( GetFileSizeEx( file, &size ) == FALSE )
  195. {
  196. FT_ERROR(( "FT_Stream_Open:" ));
  197. FT_ERROR(( " could not retrieve size of file `%s'\n", filepathname ));
  198. goto Fail_Open;
  199. }
  200. /* `stream->size' is typedef'd to unsigned long (in `ftsystem.h'); */
  201. /* So avoid overflow caused by fonts in huge files larger than */
  202. /* 2GB, do a test. */
  203. if ( size.QuadPart > LONG_MAX )
  204. {
  205. FT_ERROR(( "FT_Stream_Open: file is too big\n" ));
  206. goto Fail_Open;
  207. }
  208. else if ( size.QuadPart == 0 )
  209. {
  210. FT_ERROR(( "FT_Stream_Open: zero-length file\n" ));
  211. goto Fail_Open;
  212. }
  213. fm = CreateFileMapping( file, NULL, PAGE_READONLY, 0, 0, NULL );
  214. if ( fm == NULL )
  215. {
  216. FT_ERROR(( "FT_Stream_Open: can not map file\n" ));
  217. goto Fail_Open;
  218. }
  219. /* Store only the low part of this 64 bits integer because long is */
  220. /* a 32 bits type. Anyway, a check has been done above to forbid */
  221. /* a size greater than LONG_MAX */
  222. stream->size = size.LowPart;
  223. stream->pos = 0;
  224. stream->base = (unsigned char *)
  225. MapViewOfFile( fm, FILE_MAP_READ, 0, 0, 0 );
  226. CloseHandle( fm );
  227. if ( stream->base != NULL )
  228. stream->close = ft_close_stream_by_munmap;
  229. else
  230. {
  231. DWORD total_read_count;
  232. FT_ERROR(( "FT_Stream_Open:" ));
  233. FT_ERROR(( " could not `mmap' file `%s'\n", filepathname ));
  234. stream->base = (unsigned char*)ft_alloc( NULL, stream->size );
  235. if ( !stream->base )
  236. {
  237. FT_ERROR(( "FT_Stream_Open:" ));
  238. FT_ERROR(( " could not `alloc' memory\n" ));
  239. goto Fail_Map;
  240. }
  241. total_read_count = 0;
  242. do
  243. {
  244. DWORD read_count;
  245. if ( ReadFile( file,
  246. stream->base + total_read_count,
  247. stream->size - total_read_count,
  248. &read_count, NULL ) == FALSE )
  249. {
  250. FT_ERROR(( "FT_Stream_Open:" ));
  251. FT_ERROR(( " error while `read'ing file `%s'\n", filepathname ));
  252. goto Fail_Read;
  253. }
  254. total_read_count += read_count;
  255. } while ( total_read_count != stream->size );
  256. stream->close = ft_close_stream_by_free;
  257. }
  258. CloseHandle( file );
  259. stream->descriptor.pointer = stream->base;
  260. stream->pathname.pointer = (char*)filepathname;
  261. stream->read = 0;
  262. FT_TRACE1(( "FT_Stream_Open:" ));
  263. FT_TRACE1(( " opened `%s' (%ld bytes) successfully\n",
  264. filepathname, stream->size ));
  265. return FT_Err_Ok;
  266. Fail_Read:
  267. ft_free( NULL, stream->base );
  268. Fail_Map:
  269. CloseHandle( file );
  270. Fail_Open:
  271. CloseHandle( file );
  272. stream->base = NULL;
  273. stream->size = 0;
  274. stream->pos = 0;
  275. return FT_THROW( Cannot_Open_Stream );
  276. }
  277. #ifdef FT_DEBUG_MEMORY
  278. extern FT_Int
  279. ft_mem_debug_init( FT_Memory memory );
  280. extern void
  281. ft_mem_debug_done( FT_Memory memory );
  282. #endif
  283. /* documentation is in ftobjs.h */
  284. FT_BASE_DEF( FT_Memory )
  285. FT_New_Memory( void )
  286. {
  287. FT_Memory memory;
  288. memory = (FT_Memory)malloc( sizeof ( *memory ) );
  289. if ( memory )
  290. {
  291. memory->user = 0;
  292. memory->alloc = ft_alloc;
  293. memory->realloc = ft_realloc;
  294. memory->free = ft_free;
  295. #ifdef FT_DEBUG_MEMORY
  296. ft_mem_debug_init( memory );
  297. #endif
  298. }
  299. return memory;
  300. }
  301. /* documentation is in ftobjs.h */
  302. FT_BASE_DEF( void )
  303. FT_Done_Memory( FT_Memory memory )
  304. {
  305. #ifdef FT_DEBUG_MEMORY
  306. ft_mem_debug_done( memory );
  307. #endif
  308. memory->free( memory, memory );
  309. }
  310. /* END */