diff options
Diffstat (limited to 'src/3rdparty/harfbuzz-ng/src/hb-blob.cc')
-rw-r--r-- | src/3rdparty/harfbuzz-ng/src/hb-blob.cc | 284 |
1 files changed, 190 insertions, 94 deletions
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-blob.cc b/src/3rdparty/harfbuzz-ng/src/hb-blob.cc index 2e72683c8b..265effba03 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-blob.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-blob.cc @@ -25,18 +25,6 @@ * Red Hat Author(s): Behdad Esfahbod */ - -/* https://github.com/harfbuzz/harfbuzz/issues/1308 - * http://www.gnu.org/software/libc/manual/html_node/Feature-Test-Macros.html - * https://www.oracle.com/technetwork/articles/servers-storage-dev/standardheaderfiles-453865.html - */ -#if !defined(_POSIX_C_SOURCE) && !defined(_MSC_VER) && !defined(__NetBSD__) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-macros" -#define _POSIX_C_SOURCE 200809L -#pragma GCC diagnostic pop -#endif - #include "hb.hh" #include "hb-blob.hh" @@ -47,9 +35,6 @@ #include <sys/mman.h> #endif /* HAVE_SYS_MMAN_H */ -#include <stdio.h> -#include <stdlib.h> - /** * SECTION: hb-blob @@ -70,7 +55,7 @@ * @length: Length of @data in bytes. * @mode: Memory mode for @data. * @user_data: Data parameter to pass to @destroy. - * @destroy: Callback to call when @data is not needed anymore. + * @destroy: (nullable): Callback to call when @data is not needed anymore. * * Creates a new "blob" object wrapping @data. The @mode parameter is used * to negotiate ownership and lifecycle of @data. @@ -87,14 +72,52 @@ hb_blob_create (const char *data, void *user_data, hb_destroy_func_t destroy) { + if (!length) + { + if (destroy) + destroy (user_data); + return hb_blob_get_empty (); + } + + hb_blob_t *blob = hb_blob_create_or_fail (data, length, mode, + user_data, destroy); + return likely (blob) ? blob : hb_blob_get_empty (); +} + +/** + * hb_blob_create_or_fail: (skip) + * @data: Pointer to blob data. + * @length: Length of @data in bytes. + * @mode: Memory mode for @data. + * @user_data: Data parameter to pass to @destroy. + * @destroy: (nullable): Callback to call when @data is not needed anymore. + * + * Creates a new "blob" object wrapping @data. The @mode parameter is used + * to negotiate ownership and lifecycle of @data. + * + * Note that this function returns a freshly-allocated empty blob even if @length + * is zero. This is in contrast to hb_blob_create(), which returns the singleton + * empty blob (as returned by hb_blob_get_empty()) if @length is zero. + * + * Return value: New blob, or `NULL` if failed. Destroy with hb_blob_destroy(). + * + * Since: 2.8.2 + **/ +hb_blob_t * +hb_blob_create_or_fail (const char *data, + unsigned int length, + hb_memory_mode_t mode, + void *user_data, + hb_destroy_func_t destroy) +{ hb_blob_t *blob; - if (!length || - length >= 1u << 31 || - !(blob = hb_object_create<hb_blob_t> ())) { + if (length >= 1u << 31 || + !(blob = hb_object_create<hb_blob_t> ())) + { if (destroy) destroy (user_data); - return hb_blob_get_empty (); + return nullptr; } blob->data = data; @@ -106,9 +129,10 @@ hb_blob_create (const char *data, if (blob->mode == HB_MEMORY_MODE_DUPLICATE) { blob->mode = HB_MEMORY_MODE_READONLY; - if (!blob->try_make_writable ()) { + if (!blob->try_make_writable ()) + { hb_blob_destroy (blob); - return hb_blob_get_empty (); + return nullptr; } } @@ -128,7 +152,7 @@ _hb_blob_destroy (void *data) * @length: Length of sub-blob. * * Returns a blob that represents a range of bytes in @parent. The new - * blob is always created with %HB_MEMORY_MODE_READONLY, meaning that it + * blob is always created with #HB_MEMORY_MODE_READONLY, meaning that it * will never modify data in the parent blob. The parent data is not * expected to be modified, and will result in undefined behavior if it * is. @@ -168,7 +192,7 @@ hb_blob_create_sub_blob (hb_blob_t *parent, * * Makes a writable copy of @blob. * - * Return value: New blob, or nullptr if allocation failed. + * Return value: The new blob, or nullptr if allocation failed * * Since: 1.8.0 **/ @@ -194,14 +218,14 @@ hb_blob_copy_writable_or_fail (hb_blob_t *blob) * * See TODO:link object types for more information. * - * Return value: (transfer full): the empty blob. + * Return value: (transfer full): The empty blob. * * Since: 0.9.2 **/ hb_blob_t * hb_blob_get_empty () { - return const_cast<hb_blob_t *> (&Null(hb_blob_t)); + return const_cast<hb_blob_t *> (&Null (hb_blob_t)); } /** @@ -239,20 +263,20 @@ hb_blob_destroy (hb_blob_t *blob) { if (!hb_object_destroy (blob)) return; - blob->fini_shallow (); - - free (blob); + hb_free (blob); } /** * hb_blob_set_user_data: (skip) - * @blob: a blob. - * @key: key for data to set. - * @data: data to set. - * @destroy: callback to call when @data is not needed anymore. - * @replace: whether to replace an existing data with the same key. + * @blob: An #hb_blob_t + * @key: The user-data key to set + * @data: A pointer to the user data to set + * @destroy: (nullable): A callback to call when @data is not needed anymore + * @replace: Whether to replace an existing data with the same key * - * Return value: + * Attaches a user-data key/data pair to the specified blob. + * + * Return value: `true` if success, `false` otherwise * * Since: 0.9.2 **/ @@ -268,17 +292,18 @@ hb_blob_set_user_data (hb_blob_t *blob, /** * hb_blob_get_user_data: (skip) - * @blob: a blob. - * @key: key for data to get. + * @blob: a blob + * @key: The user-data key to query * + * Fetches the user data associated with the specified key, + * attached to the specified font-functions structure. * - * - * Return value: (transfer none): + * Return value: (transfer none): A pointer to the user data * * Since: 0.9.2 **/ void * -hb_blob_get_user_data (hb_blob_t *blob, +hb_blob_get_user_data (const hb_blob_t *blob, hb_user_data_key_t *key) { return hb_object_get_user_data (blob, key); @@ -287,9 +312,9 @@ hb_blob_get_user_data (hb_blob_t *blob, /** * hb_blob_make_immutable: - * @blob: a blob. - * + * @blob: a blob * + * Makes a blob immutable. * * Since: 0.9.2 **/ @@ -306,9 +331,9 @@ hb_blob_make_immutable (hb_blob_t *blob) * hb_blob_is_immutable: * @blob: a blob. * + * Tests whether a blob is immutable. * - * - * Return value: TODO + * Return value: `true` if @blob is immutable, `false` otherwise * * Since: 0.9.2 **/ @@ -323,9 +348,9 @@ hb_blob_is_immutable (hb_blob_t *blob) * hb_blob_get_length: * @blob: a blob. * + * Fetches the length of a blob's data. * - * - * Return value: the length of blob data in bytes. + * Return value: the length of @blob data in bytes. * * Since: 0.9.2 **/ @@ -338,11 +363,11 @@ hb_blob_get_length (hb_blob_t *blob) /** * hb_blob_get_data: * @blob: a blob. - * @length: (out): - * + * @length: (out): The length in bytes of the data retrieved * + * Fetches the data from a blob. * - * Returns: (transfer none) (array length=length): + * Returns: (nullable) (transfer none) (array length=length): the byte data of @blob. * * Since: 0.9.2 **/ @@ -367,23 +392,21 @@ hb_blob_get_data (hb_blob_t *blob, unsigned int *length) * fails. * * Returns: (transfer none) (array length=length): Writable blob data, - * or %NULL if failed. + * or `NULL` if failed. * * Since: 0.9.2 **/ char * hb_blob_get_data_writable (hb_blob_t *blob, unsigned int *length) { - if (!blob->try_make_writable ()) { - if (length) - *length = 0; - + if (hb_object_is_immutable (blob) || + !blob->try_make_writable ()) + { + if (length) *length = 0; return nullptr; } - if (length) - *length = blob->length; - + if (length) *length = blob->length; return const_cast<char *> (blob->data); } @@ -449,8 +472,8 @@ hb_blob_t::try_make_writable_inplace () bool hb_blob_t::try_make_writable () { - if (hb_object_is_immutable (this)) - return false; + if (unlikely (!length)) + mode = HB_MEMORY_MODE_WRITABLE; if (this->mode == HB_MEMORY_MODE_WRITABLE) return true; @@ -466,18 +489,18 @@ hb_blob_t::try_make_writable () char *new_data; - new_data = (char *) malloc (this->length); + new_data = (char *) hb_malloc (this->length); if (unlikely (!new_data)) return false; DEBUG_MSG_FUNC (BLOB, this, "dupped successfully -> %p\n", this->data); - memcpy (new_data, this->data, this->length); + hb_memcpy (new_data, this->data, this->length); this->destroy_user_data (); this->mode = HB_MEMORY_MODE_WRITABLE; this->data = new_data; this->user_data = new_data; - this->destroy = free; + this->destroy = hb_free; return true; } @@ -488,6 +511,9 @@ hb_blob_t::try_make_writable () #ifndef HB_NO_OPEN #ifdef HAVE_MMAP +# if !defined(HB_NO_RESOURCE_FORK) && defined(__APPLE__) +# include <sys/paths.h> +# endif # include <sys/types.h> # include <sys/stat.h> # include <fcntl.h> @@ -528,26 +554,82 @@ _hb_mapped_file_destroy (void *file_) assert (0); // If we don't have mmap we shouldn't reach here #endif - free (file); + hb_free (file); +} +#endif + +#ifdef _PATH_RSRCFORKSPEC +static int +_open_resource_fork (const char *file_name, hb_mapped_file_t *file) +{ + size_t name_len = strlen (file_name); + size_t len = name_len + sizeof (_PATH_RSRCFORKSPEC); + + char *rsrc_name = (char *) hb_malloc (len); + if (unlikely (!rsrc_name)) return -1; + + strncpy (rsrc_name, file_name, name_len); + strncpy (rsrc_name + name_len, _PATH_RSRCFORKSPEC, + sizeof (_PATH_RSRCFORKSPEC)); + + int fd = open (rsrc_name, O_RDONLY | O_BINARY, 0); + hb_free (rsrc_name); + + if (fd != -1) + { + struct stat st; + if (fstat (fd, &st) != -1) + file->length = (unsigned long) st.st_size; + else + { + close (fd); + fd = -1; + } + } + + return fd; } #endif /** * hb_blob_create_from_file: - * @file_name: font filename. + * @file_name: A font filename + * + * Creates a new blob containing the data from the + * specified binary font file. * - * Returns: A hb_blob_t pointer with the content of the file + * Returns: An #hb_blob_t pointer with the content of the file, + * or hb_blob_get_empty() if failed. * * Since: 1.7.7 **/ hb_blob_t * hb_blob_create_from_file (const char *file_name) { + hb_blob_t *blob = hb_blob_create_from_file_or_fail (file_name); + return likely (blob) ? blob : hb_blob_get_empty (); +} + +/** + * hb_blob_create_from_file_or_fail: + * @file_name: A font filename + * + * Creates a new blob containing the data from the + * specified binary font file. + * + * Returns: An #hb_blob_t pointer with the content of the file, + * or `NULL` if failed. + * + * Since: 2.8.2 + **/ +hb_blob_t * +hb_blob_create_from_file_or_fail (const char *file_name) +{ /* Adopted from glib's gmappedfile.c with Matthias Clasen and Allison Lortie permission but changed a lot to suit our need. */ #if defined(HAVE_MMAP) && !defined(HB_NO_MMAP) - hb_mapped_file_t *file = (hb_mapped_file_t *) calloc (1, sizeof (hb_mapped_file_t)); - if (unlikely (!file)) return hb_blob_get_empty (); + hb_mapped_file_t *file = (hb_mapped_file_t *) hb_calloc (1, sizeof (hb_mapped_file_t)); + if (unlikely (!file)) return nullptr; int fd = open (file_name, O_RDONLY | O_BINARY, 0); if (unlikely (fd == -1)) goto fail_without_close; @@ -556,6 +638,19 @@ hb_blob_create_from_file (const char *file_name) if (unlikely (fstat (fd, &st) == -1)) goto fail; file->length = (unsigned long) st.st_size; + +#ifdef _PATH_RSRCFORKSPEC + if (unlikely (file->length == 0)) + { + int rfd = _open_resource_fork (file_name, file); + if (rfd != -1) + { + close (fd); + fd = rfd; + } + } +#endif + file->contents = (char *) mmap (nullptr, file->length, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, fd, 0); @@ -563,25 +658,25 @@ hb_blob_create_from_file (const char *file_name) close (fd); - return hb_blob_create (file->contents, file->length, - HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE, (void *) file, - (hb_destroy_func_t) _hb_mapped_file_destroy); + return hb_blob_create_or_fail (file->contents, file->length, + HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE, (void *) file, + (hb_destroy_func_t) _hb_mapped_file_destroy); fail: close (fd); fail_without_close: - free (file); + hb_free (file); #elif defined(_WIN32) && !defined(HB_NO_MMAP) - hb_mapped_file_t *file = (hb_mapped_file_t *) calloc (1, sizeof (hb_mapped_file_t)); - if (unlikely (!file)) return hb_blob_get_empty (); + hb_mapped_file_t *file = (hb_mapped_file_t *) hb_calloc (1, sizeof (hb_mapped_file_t)); + if (unlikely (!file)) return nullptr; HANDLE fd; unsigned int size = strlen (file_name) + 1; - wchar_t * wchar_file_name = (wchar_t *) malloc (sizeof (wchar_t) * size); - if (unlikely (wchar_file_name == nullptr)) goto fail_without_close; + wchar_t * wchar_file_name = (wchar_t *) hb_malloc (sizeof (wchar_t) * size); + if (unlikely (!wchar_file_name)) goto fail_without_close; mbstowcs (wchar_file_name, file_name, size); -#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_PC_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP) +#if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) && WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) { CREATEFILE2_EXTENDED_PARAMETERS ceparams = { 0 }; ceparams.dwSize = sizeof(CREATEFILE2_EXTENDED_PARAMETERS); @@ -598,11 +693,11 @@ fail_without_close: OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED, nullptr); #endif - free (wchar_file_name); + hb_free (wchar_file_name); if (unlikely (fd == INVALID_HANDLE_VALUE)) goto fail_without_close; -#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_PC_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP) +#if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) && WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) { LARGE_INTEGER length; GetFileSizeEx (fd, &length); @@ -613,35 +708,35 @@ fail_without_close: file->length = (unsigned long) GetFileSize (fd, nullptr); file->mapping = CreateFileMapping (fd, nullptr, PAGE_READONLY, 0, 0, nullptr); #endif - if (unlikely (file->mapping == nullptr)) goto fail; + if (unlikely (!file->mapping)) goto fail; -#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_PC_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP) +#if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) && WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) file->contents = (char *) MapViewOfFileFromApp (file->mapping, FILE_MAP_READ, 0, 0); #else file->contents = (char *) MapViewOfFile (file->mapping, FILE_MAP_READ, 0, 0, 0); #endif - if (unlikely (file->contents == nullptr)) goto fail; + if (unlikely (!file->contents)) goto fail; CloseHandle (fd); - return hb_blob_create (file->contents, file->length, - HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE, (void *) file, - (hb_destroy_func_t) _hb_mapped_file_destroy); + return hb_blob_create_or_fail (file->contents, file->length, + HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE, (void *) file, + (hb_destroy_func_t) _hb_mapped_file_destroy); fail: CloseHandle (fd); fail_without_close: - free (file); + hb_free (file); #endif /* The following tries to read a file without knowing its size beforehand It's used as a fallback for systems without mmap or to read from pipes */ unsigned long len = 0, allocated = BUFSIZ * 16; - char *data = (char *) malloc (allocated); - if (unlikely (data == nullptr)) return hb_blob_get_empty (); + char *data = (char *) hb_malloc (allocated); + if (unlikely (!data)) return nullptr; FILE *fp = fopen (file_name, "rb"); - if (unlikely (fp == nullptr)) goto fread_fail_without_close; + if (unlikely (!fp)) goto fread_fail_without_close; while (!feof (fp)) { @@ -651,8 +746,8 @@ fail_without_close: /* Don't allocate and go more than ~536MB, our mmap reader still can cover files like that but lets limit our fallback reader */ if (unlikely (allocated > (2 << 28))) goto fread_fail; - char *new_data = (char *) realloc (data, allocated); - if (unlikely (new_data == nullptr)) goto fread_fail; + char *new_data = (char *) hb_realloc (data, allocated); + if (unlikely (!new_data)) goto fread_fail; data = new_data; } @@ -666,14 +761,15 @@ fail_without_close: len += addition; } + fclose (fp); - return hb_blob_create (data, len, HB_MEMORY_MODE_WRITABLE, data, - (hb_destroy_func_t) free); + return hb_blob_create_or_fail (data, len, HB_MEMORY_MODE_WRITABLE, data, + (hb_destroy_func_t) hb_free); fread_fail: fclose (fp); fread_fail_without_close: - free (data); - return hb_blob_get_empty (); + hb_free (data); + return nullptr; } #endif /* !HB_NO_OPEN */ |