diff options
Diffstat (limited to 'thirdparty')
129 files changed, 3936 insertions, 1600 deletions
diff --git a/thirdparty/README.md b/thirdparty/README.md index 3da9896247..5ecbffac13 100644 --- a/thirdparty/README.md +++ b/thirdparty/README.md @@ -87,7 +87,7 @@ Files extracted from upstream source: ## certs - Upstream: Mozilla, via https://github.com/bagder/ca-bundle -- Version: git (bef37a977ccb45fb4c1b213b79dd6ba438077561, 2023) +- Version: git (c5a419971b1bec220368c619aaafd0b818aa119f, 2024) - License: MPL 2.0 @@ -194,7 +194,7 @@ commits. ## enet - Upstream: https://github.com/lsalzman/enet -- Version: git (ea4607a90dbfbcf4da2669ea998585253d8e70b1, 2023) +- Version: git (c44b7d0f7ff21edb702745e4c019d0537928c373, 2024) - License: MIT Files extracted from upstream source: @@ -318,7 +318,7 @@ Files extracted from upstream source: ## glad - Upstream: https://github.com/Dav1dde/glad -- Version: 2.0.4 (d08b1aa01f8fe57498f04d47b5fa8c48725be877, 2023) +- Version: 2.0.6 (658f48e72aee3c6582e80b05ac0f8787a64fe6bb, 2024) - License: CC0 1.0 and Apache 2.0 Files extracted from upstream source: @@ -334,11 +334,11 @@ Files generated from [upstream web instance](https://gen.glad.sh/): - `glx.c` - `glad/glx.h` -See the permalinks in `glad/gl.h` and `glad/glx.h` to regenrate the files with -a new version of the web instance. +See the permalinks in `glad/egl.h`, `glad/gl.h`, and `glad/glx.h` to regenrate +the files with a new version of the web instance. -Some changes have been made in order to allow loading OpenGL and OpenGLES APIs at the same time. -See the patches in the `patches` directory. +Some changes have been made in order to allow loading OpenGL and OpenGLES APIs +at the same time. See the patches in the `patches` directory. ## glslang @@ -377,16 +377,15 @@ Files extracted from upstream source: ## harfbuzz - Upstream: https://github.com/harfbuzz/harfbuzz -- Version: 8.3.0 (894a1f72ee93a1fd8dc1d9218cb3fd8f048be29a, 2023) +- Version: 8.4.0 (63973005bc07aba599b47fdd4cf788647b601ccd, 2024) - License: MIT Files extracted from upstream source: - `AUTHORS`, `COPYING`, `THANKS` - From the `src` folder, recursively: - - All the `.c`, `.cc`, `.h`, `.hh` files - - Except `main.cc`, `harfbuzz*.cc`, `failing-alloc.c`, `test*.cc`, `hb-wasm*.*`, - and the `wasm` folder + - All the `.cc`, `.h`, `.hh` files + - Except `main.cc`, `harfbuzz*.cc`, `failing-alloc.c`, `test*.cc`, `hb-wasm*.*` ## icu4c @@ -432,18 +431,18 @@ Files extracted from upstream source: ## libktx - Upstream: https://github.com/KhronosGroup/KTX-Software -- Version: 4.3.1 (c0214158d551cfc779624b0f84130bcbbefef59a, 2024) +- Version: 4.3.2 (91ace88675ac59a97e55d0378a6602a9ae6b98bd, 2024) - License: Apache-2.0 Files extracted from upstream source: - `LICENSE.md` -- `include/*` +- `include/` - `lib/dfdutils/LICENSE.adoc` as `LICENSE.dfdutils.adoc` (in root) - `lib/dfdutils/LICENSES/Apache-2.0.txt` as `Apache-2.0.txt` (in root) -- `lib/dfdutils/{KHR/*,dfd.h,colourspaces.c,createdfd.c,interpretdfd.c,printdfd.c,queries.c,dfd2vk.inl,vk2dfd.*}` -- `lib/{basis_sgd.h,formatsize.h,gl_format.h,ktxint.h,uthash.h,vk_format.h,vkformat_enum.h,checkheader.c,swap.c,hashlist.c,vkformat_check.c,basis_transcode.cpp,miniz_wrapper.cpp,filestream.*,memstream.*,texture*}` -- `other_include/KHR/*` +- `lib/dfdutils/{KHR/,dfd.h,colourspaces.c,createdfd.c,interpretdfd.c,printdfd.c,queries.c,dfd2vk.inl,vk2dfd.*}` +- `lib/{basis_sgd.h,formatsize.h,gl_format.h,ktxint.h,uthash.h,vk_format.h,vkformat_enum.h,checkheader.c,swap.c,hashlist.c,vkformat_check.c,vkformat_typesize.c,basis_transcode.cpp,miniz_wrapper.cpp,filestream.*,memstream.*,texture*}` +- `other_include/KHR/` - `utils/unused.h` Some Godot-specific changes are applied via patches included in the `patches` folder. @@ -521,7 +520,7 @@ in the MSVC debugger. ## mbedtls - Upstream: https://github.com/Mbed-TLS/mbedtls -- Version: 2.28.7 (555f84735aecdbd76a566cf087ec8425dfb0c8ab, 2024) +- Version: 2.28.8 (5a764e5555c64337ed17444410269ff21cb617b1, 2024) - License: Apache 2.0 File extracted from upstream release tarball: @@ -592,7 +591,7 @@ to solve some MSVC warnings. See the patches in the `patches` directory. ## miniupnpc - Upstream: https://github.com/miniupnp/miniupnp -- Version: 2.2.6 (faad29d7300f1bfa9dc7795031993c04c5191f59, 2024) +- Version: 2.2.7 (d4d5ec7d48c093b37b2ea5d7171ede21ce9d7ff2, 2024) - License: BSD-3-Clause Files extracted from upstream source: @@ -838,11 +837,13 @@ folder. Files extracted from upstream source: +- `LICENSE.txt` - All `.cpp`, `.h` and `.inl` files -Important: Some files have Godot-made changes. -They are marked with `// -- GODOT start --` and `// -- GODOT end --` -comments and a patch is provided in the squish/ folder. +Some downstream changes have been made and are identified by +`// -- GODOT begin --` and `// -- GODOT end --` comments. +They can be reapplied using the patches included in the `patches` +folder. ## tinyexr diff --git a/thirdparty/certs/ca-certificates.crt b/thirdparty/certs/ca-certificates.crt index df7a026bed..f437587091 100644 --- a/thirdparty/certs/ca-certificates.crt +++ b/thirdparty/certs/ca-certificates.crt @@ -1,7 +1,7 @@ ## ## Bundle of CA Root Certificates ## -## Certificate data from Mozilla as of: Wed Dec 13 07:16:08 2023 GMT +## Certificate data from Mozilla as of: Mon Mar 11 15:15:21 2024 GMT ## ## This is a bundle of X.509 certificates of public Certificate Authorities ## (CA). These were automatically extracted from Mozilla's root certificates @@ -14,7 +14,7 @@ ## Just configure this file as the SSLCACertificateFile. ## ## Conversion done with mk-ca-bundle.pl version 1.29. -## SHA256: 1970dd65858925d68498d2356aea6d03f764422523c5887deca8ce3ba9e1f845 +## SHA256: 4d96bd539f4719e9ace493757afbe4a23ee8579de1c97fbebc50bba3c12e8c1e ## @@ -3532,3 +3532,50 @@ dVwPaFsdZcJfMw8eD/A7hvWwTruc9+olBdytoptLFwG+Qt81IR2tq670v64fG9PiO/yzcnMcmyiQ iRM9HcEARwmWmjgb3bHPDcK0RPOWlc4yOo80nOAXx17Org3bhzjlP1v9mxnhMUF6cKojawHhRUzN lM47ni3niAIi9G7oyOzWPPO5std3eqx7 -----END CERTIFICATE----- + +Telekom Security TLS ECC Root 2020 +================================== +-----BEGIN CERTIFICATE----- +MIICQjCCAcmgAwIBAgIQNjqWjMlcsljN0AFdxeVXADAKBggqhkjOPQQDAzBjMQswCQYDVQQGEwJE +RTEnMCUGA1UECgweRGV1dHNjaGUgVGVsZWtvbSBTZWN1cml0eSBHbWJIMSswKQYDVQQDDCJUZWxl +a29tIFNlY3VyaXR5IFRMUyBFQ0MgUm9vdCAyMDIwMB4XDTIwMDgyNTA3NDgyMFoXDTQ1MDgyNTIz +NTk1OVowYzELMAkGA1UEBhMCREUxJzAlBgNVBAoMHkRldXRzY2hlIFRlbGVrb20gU2VjdXJpdHkg +R21iSDErMCkGA1UEAwwiVGVsZWtvbSBTZWN1cml0eSBUTFMgRUNDIFJvb3QgMjAyMDB2MBAGByqG +SM49AgEGBSuBBAAiA2IABM6//leov9Wq9xCazbzREaK9Z0LMkOsVGJDZos0MKiXrPk/OtdKPD/M1 +2kOLAoC+b1EkHQ9rK8qfwm9QMuU3ILYg/4gND21Ju9sGpIeQkpT0CdDPf8iAC8GXs7s1J8nCG6NC +MEAwHQYDVR0OBBYEFONyzG6VmUex5rNhTNHLq+O6zd6fMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0P +AQH/BAQDAgEGMAoGCCqGSM49BAMDA2cAMGQCMHVSi7ekEE+uShCLsoRbQuHmKjYC2qBuGT8lv9pZ +Mo7k+5Dck2TOrbRBR2Diz6fLHgIwN0GMZt9Ba9aDAEH9L1r3ULRn0SyocddDypwnJJGDSA3PzfdU +ga/sf+Rn27iQ7t0l +-----END CERTIFICATE----- + +Telekom Security TLS RSA Root 2023 +================================== +-----BEGIN CERTIFICATE----- +MIIFszCCA5ugAwIBAgIQIZxULej27HF3+k7ow3BXlzANBgkqhkiG9w0BAQwFADBjMQswCQYDVQQG +EwJERTEnMCUGA1UECgweRGV1dHNjaGUgVGVsZWtvbSBTZWN1cml0eSBHbWJIMSswKQYDVQQDDCJU +ZWxla29tIFNlY3VyaXR5IFRMUyBSU0EgUm9vdCAyMDIzMB4XDTIzMDMyODEyMTY0NVoXDTQ4MDMy +NzIzNTk1OVowYzELMAkGA1UEBhMCREUxJzAlBgNVBAoMHkRldXRzY2hlIFRlbGVrb20gU2VjdXJp +dHkgR21iSDErMCkGA1UEAwwiVGVsZWtvbSBTZWN1cml0eSBUTFMgUlNBIFJvb3QgMjAyMzCCAiIw +DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAO01oYGA88tKaVvC+1GDrib94W7zgRJ9cUD/h3VC +KSHtgVIs3xLBGYSJwb3FKNXVS2xE1kzbB5ZKVXrKNoIENqil/Cf2SfHVcp6R+SPWcHu79ZvB7JPP +GeplfohwoHP89v+1VmLhc2o0mD6CuKyVU/QBoCcHcqMAU6DksquDOFczJZSfvkgdmOGjup5czQRx +UX11eKvzWarE4GC+j4NSuHUaQTXtvPM6Y+mpFEXX5lLRbtLevOP1Czvm4MS9Q2QTps70mDdsipWo +l8hHD/BeEIvnHRz+sTugBTNoBUGCwQMrAcjnj02r6LX2zWtEtefdi+zqJbQAIldNsLGyMcEWzv/9 +FIS3R/qy8XDe24tsNlikfLMR0cN3f1+2JeANxdKz+bi4d9s3cXFH42AYTyS2dTd4uaNir73Jco4v +zLuu2+QVUhkHM/tqty1LkCiCc/4YizWN26cEar7qwU02OxY2kTLvtkCJkUPg8qKrBC7m8kwOFjQg +rIfBLX7JZkcXFBGk8/ehJImr2BrIoVyxo/eMbcgByU/J7MT8rFEz0ciD0cmfHdRHNCk+y7AO+oML +KFjlKdw/fKifybYKu6boRhYPluV75Gp6SG12mAWl3G0eQh5C2hrgUve1g8Aae3g1LDj1H/1Joy7S +WWO/gLCMk3PLNaaZlSJhZQNg+y+TS/qanIA7AgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIBBjAdBgNV +HQ4EFgQUtqeXgj10hZv3PJ+TmpV5dVKMbUcwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBS2 +p5eCPXSFm/c8n5OalXl1UoxtRzANBgkqhkiG9w0BAQwFAAOCAgEAqMxhpr51nhVQpGv7qHBFfLp+ +sVr8WyP6Cnf4mHGCDG3gXkaqk/QeoMPhk9tLrbKmXauw1GLLXrtm9S3ul0A8Yute1hTWjOKWi0Fp +kzXmuZlrYrShF2Y0pmtjxrlO8iLpWA1WQdH6DErwM807u20hOq6OcrXDSvvpfeWxm4bu4uB9tPcy +/SKE8YXJN3nptT+/XOR0so8RYgDdGGah2XsjX/GO1WfoVNpbOms2b/mBsTNHM3dA+VKq3dSDz4V4 +mZqTuXNnQkYRIer+CqkbGmVps4+uFrb2S1ayLfmlyOw7YqPta9BO1UAJpB+Y1zqlklkg5LB9zVtz +aL1txKITDmcZuI1CfmwMmm6gJC3VRRvcxAIU/oVbZZfKTpBQCHpCNfnqwmbU+AGuHrS+w6jv/naa +oqYfRvaE7fzbzsQCzndILIyy7MMAo+wsVRjBfhnu4S/yrYObnqsZ38aKL4x35bcF7DvB7L6Gs4a8 +wPfc5+pbrrLMtTWGS9DiP7bY+A4A7l3j941Y/8+LN+ljX273CXE2whJdV/LItM3z7gLfEdxquVeE +HVlNjM7IDiPCtyaaEBRx/pOyiriA8A4QntOoUAw3gi/q4Iqd4Sw5/7W0cwDk90imc6y/st53BIe0 +o82bNSQ3+pCTE4FCxpgmdTdmQRCsu/WU48IxK63nI1bMNSWSs1A= +-----END CERTIFICATE----- diff --git a/thirdparty/enet/patches/godot_socket.patch b/thirdparty/enet/patches/godot_socket.patch index 364b3536be..d0fb97fb92 100644 --- a/thirdparty/enet/patches/godot_socket.patch +++ b/thirdparty/enet/patches/godot_socket.patch @@ -1,5 +1,5 @@ diff --git a/thirdparty/enet/enet/enet.h b/thirdparty/enet/enet/enet.h -index fc45cbd0c9..77f8004b80 100644 +index 4a207041b3..5232f8a869 100644 --- a/thirdparty/enet/enet/enet.h +++ b/thirdparty/enet/enet/enet.h @@ -10,13 +10,19 @@ extern "C" @@ -22,7 +22,7 @@ index fc45cbd0c9..77f8004b80 100644 #include "enet/types.h" #include "enet/protocol.h" -@@ -86,11 +92,15 @@ typedef enum _ENetSocketShutdown +@@ -87,11 +93,15 @@ typedef enum _ENetSocketShutdown * but not for enet_host_create. Once a server responds to a broadcast, the * address is updated from ENET_HOST_BROADCAST to the server's actual IP address. */ @@ -38,7 +38,7 @@ index fc45cbd0c9..77f8004b80 100644 /** * Packet flag bit constants. -@@ -604,6 +614,10 @@ ENET_API size_t enet_range_coder_decompress (void *, const enet_uint8 *, size_t, +@@ -608,6 +618,10 @@ ENET_API size_t enet_range_coder_decompress (void *, const enet_uint8 *, size_t, extern size_t enet_protocol_command_size (enet_uint8); @@ -50,7 +50,7 @@ index fc45cbd0c9..77f8004b80 100644 } #endif diff --git a/thirdparty/enet/host.c b/thirdparty/enet/host.c -index 3b2180f7fd..21ab27e247 100644 +index fff946a392..adb3533cf1 100644 --- a/thirdparty/enet/host.c +++ b/thirdparty/enet/host.c @@ -87,7 +87,7 @@ enet_host_create (const ENetAddress * address, size_t peerCount, size_t channelL @@ -63,10 +63,10 @@ index 3b2180f7fd..21ab27e247 100644 host -> receivedData = NULL; host -> receivedDataLength = 0; diff --git a/thirdparty/enet/protocol.c b/thirdparty/enet/protocol.c -index 9d654f1d96..d7fe80f117 100644 +index 843a719af3..5f18700599 100644 --- a/thirdparty/enet/protocol.c +++ b/thirdparty/enet/protocol.c -@@ -309,7 +309,7 @@ enet_protocol_handle_connect (ENetHost * host, ENetProtocolHeader * header, ENet +@@ -318,7 +318,7 @@ enet_protocol_handle_connect (ENetHost * host, ENetProtocolHeader * header, ENet } else if (currentPeer -> state != ENET_PEER_STATE_CONNECTING && @@ -75,7 +75,7 @@ index 9d654f1d96..d7fe80f117 100644 { if (currentPeer -> address.port == host -> receivedAddress.port && currentPeer -> connectID == command -> connect.connectID) -@@ -1031,9 +1031,8 @@ enet_protocol_handle_incoming_commands (ENetHost * host, ENetEvent * event) +@@ -1043,9 +1043,8 @@ enet_protocol_handle_incoming_commands (ENetHost * host, ENetEvent * event) if (peer -> state == ENET_PEER_STATE_DISCONNECTED || peer -> state == ENET_PEER_STATE_ZOMBIE || @@ -87,7 +87,7 @@ index 9d654f1d96..d7fe80f117 100644 (peer -> outgoingPeerID < ENET_PROTOCOL_MAXIMUM_PEER_ID && sessionID != peer -> incomingSessionID)) return 0; -@@ -1075,7 +1074,7 @@ enet_protocol_handle_incoming_commands (ENetHost * host, ENetEvent * event) +@@ -1090,7 +1089,7 @@ enet_protocol_handle_incoming_commands (ENetHost * host, ENetEvent * event) if (peer != NULL) { diff --git a/thirdparty/enet/protocol.c b/thirdparty/enet/protocol.c index af307af7e5..5f18700599 100644 --- a/thirdparty/enet/protocol.c +++ b/thirdparty/enet/protocol.c @@ -1071,11 +1071,14 @@ enet_protocol_handle_incoming_commands (ENetHost * host, ENetEvent * event) if (host -> checksum != NULL) { - enet_uint32 * checksum = (enet_uint32 *) & host -> receivedData [headerSize - sizeof (enet_uint32)], - desiredChecksum = * checksum; + enet_uint32 * checksum = (enet_uint32 *) & host -> receivedData [headerSize - sizeof (enet_uint32)]; + enet_uint32 desiredChecksum, newChecksum; ENetBuffer buffer; + /* Checksum may be an unaligned pointer, use memcpy to avoid undefined behaviour. */ + memcpy (& desiredChecksum, checksum, sizeof (enet_uint32)); - * checksum = peer != NULL ? peer -> connectID : 0; + newChecksum = peer != NULL ? peer -> connectID : 0; + memcpy (checksum, & newChecksum, sizeof (enet_uint32)); buffer.data = host -> receivedData; buffer.dataLength = host -> receivedDataLength; @@ -1703,9 +1706,12 @@ enet_protocol_send_outgoing_commands (ENetHost * host, ENetEvent * event, int ch if (host -> checksum != NULL) { enet_uint32 * checksum = (enet_uint32 *) & headerData [host -> buffers -> dataLength]; - * checksum = currentPeer -> outgoingPeerID < ENET_PROTOCOL_MAXIMUM_PEER_ID ? currentPeer -> connectID : 0; + enet_uint32 newChecksum = currentPeer -> outgoingPeerID < ENET_PROTOCOL_MAXIMUM_PEER_ID ? currentPeer -> connectID : 0; + /* Checksum may be unaligned, use memcpy to avoid undefined behaviour. */ + memcpy(checksum, & newChecksum, sizeof (enet_uint32)); host -> buffers -> dataLength += sizeof (enet_uint32); - * checksum = host -> checksum (host -> buffers, host -> bufferCount); + newChecksum = host -> checksum (host -> buffers, host -> bufferCount); + memcpy(checksum, & newChecksum, sizeof (enet_uint32)); } if (shouldCompress > 0) diff --git a/thirdparty/glad/EGL/eglplatform.h b/thirdparty/glad/EGL/eglplatform.h index 99362a23de..6786afd90b 100644 --- a/thirdparty/glad/EGL/eglplatform.h +++ b/thirdparty/glad/EGL/eglplatform.h @@ -64,6 +64,12 @@ typedef HDC EGLNativeDisplayType; typedef HBITMAP EGLNativePixmapType; typedef HWND EGLNativeWindowType; +#elif defined(__QNX__) + +typedef khronos_uintptr_t EGLNativeDisplayType; +typedef struct _screen_pixmap* EGLNativePixmapType; /* screen_pixmap_t */ +typedef struct _screen_window* EGLNativeWindowType; /* screen_window_t */ + #elif defined(__EMSCRIPTEN__) typedef int EGLNativeDisplayType; diff --git a/thirdparty/glad/gl.c b/thirdparty/glad/gl.c index ee0cc188fc..38ecb514bd 100644 --- a/thirdparty/glad/gl.c +++ b/thirdparty/glad/gl.c @@ -453,6 +453,7 @@ PFNGLMULTITEXCOORDP3UIPROC glad_glMultiTexCoordP3ui = NULL; PFNGLMULTITEXCOORDP3UIVPROC glad_glMultiTexCoordP3uiv = NULL; PFNGLMULTITEXCOORDP4UIPROC glad_glMultiTexCoordP4ui = NULL; PFNGLMULTITEXCOORDP4UIVPROC glad_glMultiTexCoordP4uiv = NULL; +PFNGLNAMEDFRAMEBUFFERTEXTUREMULTIVIEWOVRPROC glad_glNamedFramebufferTextureMultiviewOVR = NULL; PFNGLNEWLISTPROC glad_glNewList = NULL; PFNGLNORMAL3BPROC glad_glNormal3b = NULL; PFNGLNORMAL3BVPROC glad_glNormal3bv = NULL; @@ -2108,40 +2109,29 @@ static void glad_gl_load_GL_EXT_framebuffer_object( GLADuserptrloadfunc load, vo static void glad_gl_load_GL_OVR_multiview( GLADuserptrloadfunc load, void* userptr) { if(!GLAD_GL_OVR_multiview) return; glad_glFramebufferTextureMultiviewOVR = (PFNGLFRAMEBUFFERTEXTUREMULTIVIEWOVRPROC) load(userptr, "glFramebufferTextureMultiviewOVR"); + glad_glNamedFramebufferTextureMultiviewOVR = (PFNGLNAMEDFRAMEBUFFERTEXTUREMULTIVIEWOVRPROC) load(userptr, "glNamedFramebufferTextureMultiviewOVR"); } -#if defined(GL_ES_VERSION_3_0) || defined(GL_VERSION_3_0) -#define GLAD_GL_IS_SOME_NEW_VERSION 1 -#else -#define GLAD_GL_IS_SOME_NEW_VERSION 0 -#endif - -static int glad_gl_get_extensions( int version, const char **out_exts, unsigned int *out_num_exts_i, char ***out_exts_i) { -#if GLAD_GL_IS_SOME_NEW_VERSION - if(GLAD_VERSION_MAJOR(version) < 3) { -#else - GLAD_UNUSED(version); - GLAD_UNUSED(out_num_exts_i); - GLAD_UNUSED(out_exts_i); -#endif - if (glad_glGetString == NULL) { - return 0; +static void glad_gl_free_extensions(char **exts_i) { + if (exts_i != NULL) { + unsigned int index; + for(index = 0; exts_i[index]; index++) { + free((void *) (exts_i[index])); } - *out_exts = (const char *)glad_glGetString(GL_EXTENSIONS); -#if GLAD_GL_IS_SOME_NEW_VERSION - } else { + free((void *)exts_i); + exts_i = NULL; + } +} +static int glad_gl_get_extensions( const char **out_exts, char ***out_exts_i) { +#if defined(GL_ES_VERSION_3_0) || defined(GL_VERSION_3_0) + if (glad_glGetStringi != NULL && glad_glGetIntegerv != NULL) { unsigned int index = 0; unsigned int num_exts_i = 0; char **exts_i = NULL; - if (glad_glGetStringi == NULL || glad_glGetIntegerv == NULL) { - return 0; - } glad_glGetIntegerv(GL_NUM_EXTENSIONS, (int*) &num_exts_i); - if (num_exts_i > 0) { - exts_i = (char **) malloc(num_exts_i * (sizeof *exts_i)); - } + exts_i = (char **) malloc((num_exts_i + 1) * (sizeof *exts_i)); if (exts_i == NULL) { return 0; } @@ -2150,31 +2140,40 @@ static int glad_gl_get_extensions( int version, const char **out_exts, unsigned size_t len = strlen(gl_str_tmp) + 1; char *local_str = (char*) malloc(len * sizeof(char)); - if(local_str != NULL) { - memcpy(local_str, gl_str_tmp, len * sizeof(char)); + if(local_str == NULL) { + exts_i[index] = NULL; + glad_gl_free_extensions(exts_i); + return 0; } + memcpy(local_str, gl_str_tmp, len * sizeof(char)); exts_i[index] = local_str; } + exts_i[index] = NULL; - *out_num_exts_i = num_exts_i; *out_exts_i = exts_i; + + return 1; } +#else + GLAD_UNUSED(out_exts_i); #endif + if (glad_glGetString == NULL) { + return 0; + } + *out_exts = (const char *)glad_glGetString(GL_EXTENSIONS); return 1; } -static void glad_gl_free_extensions(char **exts_i, unsigned int num_exts_i) { - if (exts_i != NULL) { +static int glad_gl_has_extension(const char *exts, char **exts_i, const char *ext) { + if(exts_i) { unsigned int index; - for(index = 0; index < num_exts_i; index++) { - free((void *) (exts_i[index])); + for(index = 0; exts_i[index]; index++) { + const char *e = exts_i[index]; + if(strcmp(e, ext) == 0) { + return 1; + } } - free((void *)exts_i); - exts_i = NULL; - } -} -static int glad_gl_has_extension(int version, const char *exts, unsigned int num_exts_i, char **exts_i, const char *ext) { - if(GLAD_VERSION_MAJOR(version) < 3 || !GLAD_GL_IS_SOME_NEW_VERSION) { + } else { const char *extensions; const char *loc; const char *terminator; @@ -2194,14 +2193,6 @@ static int glad_gl_has_extension(int version, const char *exts, unsigned int num } extensions = terminator; } - } else { - unsigned int index; - for(index = 0; index < num_exts_i; index++) { - const char *e = exts_i[index]; - if(strcmp(e, ext) == 0) { - return 1; - } - } } return 0; } @@ -2210,22 +2201,21 @@ static GLADapiproc glad_gl_get_proc_from_userptr(void *userptr, const char* name return (GLAD_GNUC_EXTENSION (GLADapiproc (*)(const char *name)) userptr)(name); } -static int glad_gl_find_extensions_gl( int version) { +static int glad_gl_find_extensions_gl(void) { const char *exts = NULL; - unsigned int num_exts_i = 0; char **exts_i = NULL; - if (!glad_gl_get_extensions(version, &exts, &num_exts_i, &exts_i)) return 0; + if (!glad_gl_get_extensions(&exts, &exts_i)) return 0; - GLAD_GL_ARB_debug_output = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_debug_output"); - GLAD_GL_ARB_framebuffer_object = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_framebuffer_object"); - GLAD_GL_ARB_get_program_binary = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_get_program_binary"); - GLAD_GL_EXT_framebuffer_blit = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_framebuffer_blit"); - GLAD_GL_EXT_framebuffer_multisample = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_framebuffer_multisample"); - GLAD_GL_EXT_framebuffer_object = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_framebuffer_object"); - GLAD_GL_OVR_multiview = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OVR_multiview"); - GLAD_GL_OVR_multiview2 = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OVR_multiview2"); + GLAD_GL_ARB_debug_output = glad_gl_has_extension(exts, exts_i, "GL_ARB_debug_output"); + GLAD_GL_ARB_framebuffer_object = glad_gl_has_extension(exts, exts_i, "GL_ARB_framebuffer_object"); + GLAD_GL_ARB_get_program_binary = glad_gl_has_extension(exts, exts_i, "GL_ARB_get_program_binary"); + GLAD_GL_EXT_framebuffer_blit = glad_gl_has_extension(exts, exts_i, "GL_EXT_framebuffer_blit"); + GLAD_GL_EXT_framebuffer_multisample = glad_gl_has_extension(exts, exts_i, "GL_EXT_framebuffer_multisample"); + GLAD_GL_EXT_framebuffer_object = glad_gl_has_extension(exts, exts_i, "GL_EXT_framebuffer_object"); + GLAD_GL_OVR_multiview = glad_gl_has_extension(exts, exts_i, "GL_OVR_multiview"); + GLAD_GL_OVR_multiview2 = glad_gl_has_extension(exts, exts_i, "GL_OVR_multiview2"); - glad_gl_free_extensions(exts_i, num_exts_i); + glad_gl_free_extensions(exts_i); return 1; } @@ -2275,7 +2265,6 @@ int gladLoadGLUserPtr( GLADuserptrloadfunc load, void *userptr) { glad_glGetString = (PFNGLGETSTRINGPROC) load(userptr, "glGetString"); if(glad_glGetString == NULL) return 0; - if(glad_glGetString(GL_VERSION) == NULL) return 0; version = glad_gl_find_core_gl(); glad_gl_load_GL_VERSION_1_0(load, userptr); @@ -2291,7 +2280,7 @@ int gladLoadGLUserPtr( GLADuserptrloadfunc load, void *userptr) { glad_gl_load_GL_VERSION_3_2(load, userptr); glad_gl_load_GL_VERSION_3_3(load, userptr); - if (!glad_gl_find_extensions_gl(version)) return 0; + if (!glad_gl_find_extensions_gl()) return 0; glad_gl_load_GL_ARB_debug_output(load, userptr); glad_gl_load_GL_ARB_framebuffer_object(load, userptr); glad_gl_load_GL_ARB_get_program_binary(load, userptr); @@ -2310,16 +2299,15 @@ int gladLoadGL( GLADloadfunc load) { return gladLoadGLUserPtr( glad_gl_get_proc_from_userptr, GLAD_GNUC_EXTENSION (void*) load); } -static int glad_gl_find_extensions_gles2( int version) { +static int glad_gl_find_extensions_gles2(void) { const char *exts = NULL; - unsigned int num_exts_i = 0; char **exts_i = NULL; - if (!glad_gl_get_extensions(version, &exts, &num_exts_i, &exts_i)) return 0; + if (!glad_gl_get_extensions(&exts, &exts_i)) return 0; - GLAD_GL_OVR_multiview = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OVR_multiview"); - GLAD_GL_OVR_multiview2 = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OVR_multiview2"); + GLAD_GL_OVR_multiview = glad_gl_has_extension(exts, exts_i, "GL_OVR_multiview"); + GLAD_GL_OVR_multiview2 = glad_gl_has_extension(exts, exts_i, "GL_OVR_multiview2"); - glad_gl_free_extensions(exts_i, num_exts_i); + glad_gl_free_extensions(exts_i); return 1; } @@ -2361,7 +2349,6 @@ int gladLoadGLES2UserPtr( GLADuserptrloadfunc load, void *userptr) { glad_glGetString = (PFNGLGETSTRINGPROC) load(userptr, "glGetString"); if(glad_glGetString == NULL) return 0; - if(glad_glGetString(GL_VERSION) == NULL) return 0; version = glad_gl_find_core_gles2(); glad_gl_load_GL_ES_VERSION_2_0(load, userptr); @@ -2369,7 +2356,7 @@ int gladLoadGLES2UserPtr( GLADuserptrloadfunc load, void *userptr) { glad_gl_load_GL_ES_VERSION_3_1(load, userptr); glad_gl_load_GL_ES_VERSION_3_2(load, userptr); - if (!glad_gl_find_extensions_gles2(version)) return 0; + if (!glad_gl_find_extensions_gles2()) return 0; glad_gl_load_GL_OVR_multiview(load, userptr); @@ -2627,10 +2614,9 @@ static GLADapiproc glad_dlsym_handle(void* handle, const char *name) { typedef __eglMustCastToProperFunctionPointerType (GLAD_API_PTR *PFNEGLGETPROCADDRESSPROC)(const char *name); #endif extern __eglMustCastToProperFunctionPointerType emscripten_GetProcAddress(const char *name); -#elif EGL_STATIC - typedef void (*__eglMustCastToProperFunctionPointerType)(void); +#elif defined(GLAD_GLES2_USE_SYSTEM_EGL) + #include <EGL/egl.h> typedef __eglMustCastToProperFunctionPointerType (GLAD_API_PTR *PFNEGLGETPROCADDRESSPROC)(const char *name); - extern __eglMustCastToProperFunctionPointerType GLAD_API_PTR eglGetProcAddress(const char *name); #else #include <glad/egl.h> #endif @@ -2658,7 +2644,7 @@ static GLADapiproc glad_gles2_get_proc(void *vuserptr, const char* name) { return result; } -static void* _glad_GL_loader_handle = NULL; +static void* _glad_GLES2_loader_handle = NULL; static void* glad_gles2_dlopen_handle(void) { #if GLAD_PLATFORM_EMSCRIPTEN @@ -2674,11 +2660,11 @@ static void* glad_gles2_dlopen_handle(void) { GLAD_UNUSED(glad_get_dlopen_handle); return NULL; #else - if (_glad_GL_loader_handle == NULL) { - _glad_GL_loader_handle = glad_get_dlopen_handle(NAMES, sizeof(NAMES) / sizeof(NAMES[0])); + if (_glad_GLES2_loader_handle == NULL) { + _glad_GLES2_loader_handle = glad_get_dlopen_handle(NAMES, sizeof(NAMES) / sizeof(NAMES[0])); } - return _glad_GL_loader_handle; + return _glad_GLES2_loader_handle; #endif } @@ -2708,11 +2694,12 @@ int gladLoaderLoadGLES2(void) { userptr.get_proc_address_ptr = emscripten_GetProcAddress; version = gladLoadGLES2UserPtr(glad_gles2_get_proc, &userptr); #else +#ifndef GLAD_GLES2_USE_SYSTEM_EGL if (eglGetProcAddress == NULL) { return 0; } - - did_load = _glad_GL_loader_handle == NULL; +#endif + did_load = _glad_GLES2_loader_handle == NULL; handle = glad_gles2_dlopen_handle(); if (handle != NULL) { userptr = glad_gles2_build_userptr(handle); @@ -2731,9 +2718,9 @@ int gladLoaderLoadGLES2(void) { void gladLoaderUnloadGLES2(void) { - if (_glad_GL_loader_handle != NULL) { - glad_close_dlopen_handle(_glad_GL_loader_handle); - _glad_GL_loader_handle = NULL; + if (_glad_GLES2_loader_handle != NULL) { + glad_close_dlopen_handle(_glad_GLES2_loader_handle); + _glad_GLES2_loader_handle = NULL; } } diff --git a/thirdparty/glad/glad/egl.h b/thirdparty/glad/glad/egl.h index 1bf35c1404..053c5853a7 100644 --- a/thirdparty/glad/glad/egl.h +++ b/thirdparty/glad/glad/egl.h @@ -1,5 +1,5 @@ /** - * Loader generated by glad 2.0.3 on Fri Feb 3 07:06:48 2023 + * Loader generated by glad 2.0.6 on Fri Apr 5 08:17:09 2024 * * SPDX-License-Identifier: (WTFPL OR CC0-1.0) AND Apache-2.0 * @@ -141,7 +141,7 @@ extern "C" { #define GLAD_VERSION_MAJOR(version) (version / 10000) #define GLAD_VERSION_MINOR(version) (version % 10000) -#define GLAD_GENERATOR_VERSION "2.0.3" +#define GLAD_GENERATOR_VERSION "2.0.6" typedef void (*GLADapiproc)(void); diff --git a/thirdparty/glad/glad/gl.h b/thirdparty/glad/glad/gl.h index 307ea4dbb8..1301d10b65 100644 --- a/thirdparty/glad/glad/gl.h +++ b/thirdparty/glad/glad/gl.h @@ -1,5 +1,5 @@ /** - * Loader generated by glad 2.0.4 on Mon May 22 13:18:29 2023 + * Loader generated by glad 2.0.6 on Fri Apr 5 08:14:44 2024 * * SPDX-License-Identifier: (WTFPL OR CC0-1.0) AND Apache-2.0 * @@ -178,7 +178,7 @@ extern "C" { #define GLAD_VERSION_MAJOR(version) (version / 10000) #define GLAD_VERSION_MINOR(version) (version % 10000) -#define GLAD_GENERATOR_VERSION "2.0.4" +#define GLAD_GENERATOR_VERSION "2.0.6" typedef void (*GLADapiproc)(void); @@ -2394,6 +2394,7 @@ typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORDP3UIPROC)(GLenum texture, GLenum t typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORDP3UIVPROC)(GLenum texture, GLenum type, const GLuint * coords); typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORDP4UIPROC)(GLenum texture, GLenum type, GLuint coords); typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORDP4UIVPROC)(GLenum texture, GLenum type, const GLuint * coords); +typedef void (GLAD_API_PTR *PFNGLNAMEDFRAMEBUFFERTEXTUREMULTIVIEWOVRPROC)(GLuint framebuffer, GLenum attachment, GLuint texture, GLint level, GLint baseViewIndex, GLsizei numViews); typedef void (GLAD_API_PTR *PFNGLNEWLISTPROC)(GLuint list, GLenum mode); typedef void (GLAD_API_PTR *PFNGLNORMAL3BPROC)(GLbyte nx, GLbyte ny, GLbyte nz); typedef void (GLAD_API_PTR *PFNGLNORMAL3BVPROC)(const GLbyte * v); @@ -3654,6 +3655,8 @@ GLAD_API_CALL PFNGLMULTITEXCOORDP4UIPROC glad_glMultiTexCoordP4ui; #define glMultiTexCoordP4ui glad_glMultiTexCoordP4ui GLAD_API_CALL PFNGLMULTITEXCOORDP4UIVPROC glad_glMultiTexCoordP4uiv; #define glMultiTexCoordP4uiv glad_glMultiTexCoordP4uiv +GLAD_API_CALL PFNGLNAMEDFRAMEBUFFERTEXTUREMULTIVIEWOVRPROC glad_glNamedFramebufferTextureMultiviewOVR; +#define glNamedFramebufferTextureMultiviewOVR glad_glNamedFramebufferTextureMultiviewOVR GLAD_API_CALL PFNGLNEWLISTPROC glad_glNewList; #define glNewList glad_glNewList GLAD_API_CALL PFNGLNORMAL3BPROC glad_glNormal3b; diff --git a/thirdparty/glad/glad/glx.h b/thirdparty/glad/glad/glx.h index cf7663a3af..a2fa0dadee 100644 --- a/thirdparty/glad/glad/glx.h +++ b/thirdparty/glad/glad/glx.h @@ -1,5 +1,5 @@ /** - * Loader generated by glad 2.0.4 on Mon May 22 13:18:29 2023 + * Loader generated by glad 2.0.6 on Fri Apr 5 08:14:31 2024 * * SPDX-License-Identifier: (WTFPL OR CC0-1.0) AND Apache-2.0 * @@ -152,7 +152,7 @@ extern "C" { #define GLAD_VERSION_MAJOR(version) (version / 10000) #define GLAD_VERSION_MINOR(version) (version % 10000) -#define GLAD_GENERATOR_VERSION "2.0.4" +#define GLAD_GENERATOR_VERSION "2.0.6" typedef void (*GLADapiproc)(void); diff --git a/thirdparty/glad/patches/patch_enable_both_gl_and_gles.diff b/thirdparty/glad/patches/patch_enable_both_gl_and_gles.diff index a98efe51d8..88c5510166 100644 --- a/thirdparty/glad/patches/patch_enable_both_gl_and_gles.diff +++ b/thirdparty/glad/patches/patch_enable_both_gl_and_gles.diff @@ -1,8 +1,8 @@ diff --git a/thirdparty/glad/gl.c b/thirdparty/glad/gl.c -index a0b59dbbfb..9f10f6544a 100644 +index 3f0884a3dc..38ecb514bd 100644 --- a/thirdparty/glad/gl.c +++ b/thirdparty/glad/gl.c -@@ -2475,7 +2475,7 @@ static GLADapiproc glad_gl_get_proc(void *vuserptr, const char *name) { +@@ -2462,7 +2462,7 @@ static GLADapiproc glad_gl_get_proc(void *vuserptr, const char *name) { return result; } @@ -11,7 +11,7 @@ index a0b59dbbfb..9f10f6544a 100644 static void* glad_gl_dlopen_handle(void) { #if GLAD_PLATFORM_APPLE -@@ -2497,11 +2497,11 @@ static void* glad_gl_dlopen_handle(void) { +@@ -2484,11 +2484,11 @@ static void* glad_gl_dlopen_handle(void) { }; #endif @@ -26,7 +26,7 @@ index a0b59dbbfb..9f10f6544a 100644 } static struct _glad_gl_userptr glad_gl_build_userptr(void *handle) { -@@ -2527,7 +2527,7 @@ int gladLoaderLoadGL(void) { +@@ -2514,7 +2514,7 @@ int gladLoaderLoadGL(void) { int did_load = 0; struct _glad_gl_userptr userptr; @@ -35,7 +35,7 @@ index a0b59dbbfb..9f10f6544a 100644 handle = glad_gl_dlopen_handle(); if (handle) { userptr = glad_gl_build_userptr(handle); -@@ -2545,9 +2545,9 @@ int gladLoaderLoadGL(void) { +@@ -2532,9 +2532,9 @@ int gladLoaderLoadGL(void) { void gladLoaderUnloadGL(void) { @@ -49,7 +49,7 @@ index a0b59dbbfb..9f10f6544a 100644 } diff --git a/thirdparty/glad/glad/gl.h b/thirdparty/glad/glad/gl.h -index 905c16aeed..f3cb7d8cb5 100644 +index 77c6f33cab..1301d10b65 100644 --- a/thirdparty/glad/glad/gl.h +++ b/thirdparty/glad/glad/gl.h @@ -67,6 +67,7 @@ diff --git a/thirdparty/harfbuzz/src/OT/Color/COLR/COLR.hh b/thirdparty/harfbuzz/src/OT/Color/COLR/COLR.hh index b632a1d9eb..623775a771 100644 --- a/thirdparty/harfbuzz/src/OT/Color/COLR/COLR.hh +++ b/thirdparty/harfbuzz/src/OT/Color/COLR/COLR.hh @@ -68,7 +68,7 @@ public: hb_font_t *font; unsigned int palette_index; hb_color_t foreground; - VarStoreInstancer &instancer; + ItemVarStoreInstancer &instancer; hb_map_t current_glyphs; hb_map_t current_layers; int depth_left = HB_MAX_NESTING_LEVEL; @@ -80,7 +80,7 @@ public: hb_font_t *font_, unsigned int palette_, hb_color_t foreground_, - VarStoreInstancer &instancer_) : + ItemVarStoreInstancer &instancer_) : base (base_), funcs (funcs_), data (data_), @@ -245,7 +245,7 @@ struct Variable { value.closurev1 (c); } bool subset (hb_subset_context_t *c, - const VarStoreInstancer &instancer) const + const ItemVarStoreInstancer &instancer) const { TRACE_SUBSET (this); if (!value.subset (c, instancer, varIdxBase)) return_trace (false); @@ -270,7 +270,7 @@ struct Variable void get_color_stop (hb_paint_context_t *c, hb_color_stop_t *stop, - const VarStoreInstancer &instancer) const + const ItemVarStoreInstancer &instancer) const { value.get_color_stop (c, stop, varIdxBase, instancer); } @@ -305,7 +305,7 @@ struct NoVariable { value.closurev1 (c); } bool subset (hb_subset_context_t *c, - const VarStoreInstancer &instancer) const + const ItemVarStoreInstancer &instancer) const { TRACE_SUBSET (this); return_trace (value.subset (c, instancer, varIdxBase)); @@ -325,7 +325,7 @@ struct NoVariable void get_color_stop (hb_paint_context_t *c, hb_color_stop_t *stop, - const VarStoreInstancer &instancer) const + const ItemVarStoreInstancer &instancer) const { value.get_color_stop (c, stop, VarIdx::NO_VARIATION, instancer); } @@ -348,7 +348,7 @@ struct ColorStop { c->add_palette_index (paletteIndex); } bool subset (hb_subset_context_t *c, - const VarStoreInstancer &instancer, + const ItemVarStoreInstancer &instancer, uint32_t varIdxBase) const { TRACE_SUBSET (this); @@ -374,7 +374,7 @@ struct ColorStop void get_color_stop (hb_paint_context_t *c, hb_color_stop_t *out, uint32_t varIdx, - const VarStoreInstancer &instancer) const + const ItemVarStoreInstancer &instancer) const { out->offset = stopOffset.to_float(instancer (varIdx, 0)); out->color = c->get_color (paletteIndex, @@ -410,7 +410,7 @@ struct ColorLine } bool subset (hb_subset_context_t *c, - const VarStoreInstancer &instancer) const + const ItemVarStoreInstancer &instancer) const { TRACE_SUBSET (this); auto *out = c->serializer->start_embed (this); @@ -439,7 +439,7 @@ struct ColorLine unsigned int start, unsigned int *count, hb_color_stop_t *color_stops, - const VarStoreInstancer &instancer) const + const ItemVarStoreInstancer &instancer) const { unsigned int len = stops.len; @@ -543,7 +543,7 @@ struct Affine2x3 } bool subset (hb_subset_context_t *c, - const VarStoreInstancer &instancer, + const ItemVarStoreInstancer &instancer, uint32_t varIdxBase) const { TRACE_SUBSET (this); @@ -588,7 +588,7 @@ struct PaintColrLayers void closurev1 (hb_colrv1_closure_context_t* c) const; bool subset (hb_subset_context_t *c, - const VarStoreInstancer &instancer HB_UNUSED) const + const ItemVarStoreInstancer &instancer HB_UNUSED) const { TRACE_SUBSET (this); auto *out = c->serializer->embed (this); @@ -620,7 +620,7 @@ struct PaintSolid { c->add_palette_index (paletteIndex); } bool subset (hb_subset_context_t *c, - const VarStoreInstancer &instancer, + const ItemVarStoreInstancer &instancer, uint32_t varIdxBase) const { TRACE_SUBSET (this); @@ -669,7 +669,7 @@ struct PaintLinearGradient { (this+colorLine).closurev1 (c); } bool subset (hb_subset_context_t *c, - const VarStoreInstancer &instancer, + const ItemVarStoreInstancer &instancer, uint32_t varIdxBase) const { TRACE_SUBSET (this); @@ -736,7 +736,7 @@ struct PaintRadialGradient { (this+colorLine).closurev1 (c); } bool subset (hb_subset_context_t *c, - const VarStoreInstancer &instancer, + const ItemVarStoreInstancer &instancer, uint32_t varIdxBase) const { TRACE_SUBSET (this); @@ -803,7 +803,7 @@ struct PaintSweepGradient { (this+colorLine).closurev1 (c); } bool subset (hb_subset_context_t *c, - const VarStoreInstancer &instancer, + const ItemVarStoreInstancer &instancer, uint32_t varIdxBase) const { TRACE_SUBSET (this); @@ -863,7 +863,7 @@ struct PaintGlyph void closurev1 (hb_colrv1_closure_context_t* c) const; bool subset (hb_subset_context_t *c, - const VarStoreInstancer &instancer) const + const ItemVarStoreInstancer &instancer) const { TRACE_SUBSET (this); auto *out = c->serializer->embed (this); @@ -906,7 +906,7 @@ struct PaintColrGlyph void closurev1 (hb_colrv1_closure_context_t* c) const; bool subset (hb_subset_context_t *c, - const VarStoreInstancer &instancer HB_UNUSED) const + const ItemVarStoreInstancer &instancer HB_UNUSED) const { TRACE_SUBSET (this); auto *out = c->serializer->embed (this); @@ -936,7 +936,7 @@ struct PaintTransform HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const; bool subset (hb_subset_context_t *c, - const VarStoreInstancer &instancer) const + const ItemVarStoreInstancer &instancer) const { TRACE_SUBSET (this); auto *out = c->serializer->embed (this); @@ -975,7 +975,7 @@ struct PaintTranslate HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const; bool subset (hb_subset_context_t *c, - const VarStoreInstancer &instancer, + const ItemVarStoreInstancer &instancer, uint32_t varIdxBase) const { TRACE_SUBSET (this); @@ -1024,7 +1024,7 @@ struct PaintScale HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const; bool subset (hb_subset_context_t *c, - const VarStoreInstancer &instancer, + const ItemVarStoreInstancer &instancer, uint32_t varIdxBase) const { TRACE_SUBSET (this); @@ -1073,7 +1073,7 @@ struct PaintScaleAroundCenter HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const; bool subset (hb_subset_context_t *c, - const VarStoreInstancer &instancer, + const ItemVarStoreInstancer &instancer, uint32_t varIdxBase) const { TRACE_SUBSET (this); @@ -1132,7 +1132,7 @@ struct PaintScaleUniform HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const; bool subset (hb_subset_context_t *c, - const VarStoreInstancer &instancer, + const ItemVarStoreInstancer &instancer, uint32_t varIdxBase) const { TRACE_SUBSET (this); @@ -1176,7 +1176,7 @@ struct PaintScaleUniformAroundCenter HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const; bool subset (hb_subset_context_t *c, - const VarStoreInstancer &instancer, + const ItemVarStoreInstancer &instancer, uint32_t varIdxBase) const { TRACE_SUBSET (this); @@ -1232,7 +1232,7 @@ struct PaintRotate HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const; bool subset (hb_subset_context_t *c, - const VarStoreInstancer &instancer, + const ItemVarStoreInstancer &instancer, uint32_t varIdxBase) const { TRACE_SUBSET (this); @@ -1276,7 +1276,7 @@ struct PaintRotateAroundCenter HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const; bool subset (hb_subset_context_t *c, - const VarStoreInstancer &instancer, + const ItemVarStoreInstancer &instancer, uint32_t varIdxBase) const { TRACE_SUBSET (this); @@ -1332,7 +1332,7 @@ struct PaintSkew HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const; bool subset (hb_subset_context_t *c, - const VarStoreInstancer &instancer, + const ItemVarStoreInstancer &instancer, uint32_t varIdxBase) const { TRACE_SUBSET (this); @@ -1381,7 +1381,7 @@ struct PaintSkewAroundCenter HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const; bool subset (hb_subset_context_t *c, - const VarStoreInstancer &instancer, + const ItemVarStoreInstancer &instancer, uint32_t varIdxBase) const { TRACE_SUBSET (this); @@ -1440,7 +1440,7 @@ struct PaintComposite void closurev1 (hb_colrv1_closure_context_t* c) const; bool subset (hb_subset_context_t *c, - const VarStoreInstancer &instancer) const + const ItemVarStoreInstancer &instancer) const { TRACE_SUBSET (this); auto *out = c->serializer->embed (this); @@ -1491,7 +1491,7 @@ struct ClipBoxFormat1 return_trace (c->check_struct (this)); } - void get_clip_box (ClipBoxData &clip_box, const VarStoreInstancer &instancer HB_UNUSED) const + void get_clip_box (ClipBoxData &clip_box, const ItemVarStoreInstancer &instancer HB_UNUSED) const { clip_box.xMin = xMin; clip_box.yMin = yMin; @@ -1500,7 +1500,7 @@ struct ClipBoxFormat1 } bool subset (hb_subset_context_t *c, - const VarStoreInstancer &instancer, + const ItemVarStoreInstancer &instancer, uint32_t varIdxBase) const { TRACE_SUBSET (this); @@ -1533,7 +1533,7 @@ struct ClipBoxFormat1 struct ClipBoxFormat2 : Variable<ClipBoxFormat1> { - void get_clip_box (ClipBoxData &clip_box, const VarStoreInstancer &instancer) const + void get_clip_box (ClipBoxData &clip_box, const ItemVarStoreInstancer &instancer) const { value.get_clip_box(clip_box, instancer); if (instancer) @@ -1549,7 +1549,7 @@ struct ClipBoxFormat2 : Variable<ClipBoxFormat1> struct ClipBox { bool subset (hb_subset_context_t *c, - const VarStoreInstancer &instancer) const + const ItemVarStoreInstancer &instancer) const { TRACE_SUBSET (this); switch (u.format) { @@ -1572,7 +1572,7 @@ struct ClipBox } bool get_extents (hb_glyph_extents_t *extents, - const VarStoreInstancer &instancer) const + const ItemVarStoreInstancer &instancer) const { ClipBoxData clip_box; switch (u.format) { @@ -1608,7 +1608,7 @@ struct ClipRecord bool subset (hb_subset_context_t *c, const void *base, - const VarStoreInstancer &instancer) const + const ItemVarStoreInstancer &instancer) const { TRACE_SUBSET (this); auto *out = c->serializer->embed (*this); @@ -1625,7 +1625,7 @@ struct ClipRecord bool get_extents (hb_glyph_extents_t *extents, const void *base, - const VarStoreInstancer &instancer) const + const ItemVarStoreInstancer &instancer) const { return (base+clipBox).get_extents (extents, instancer); } @@ -1642,7 +1642,7 @@ DECLARE_NULL_NAMESPACE_BYTES (OT, ClipRecord); struct ClipList { unsigned serialize_clip_records (hb_subset_context_t *c, - const VarStoreInstancer &instancer, + const ItemVarStoreInstancer &instancer, const hb_set_t& gids, const hb_map_t& gid_offset_map) const { @@ -1695,7 +1695,7 @@ struct ClipList } bool subset (hb_subset_context_t *c, - const VarStoreInstancer &instancer) const + const ItemVarStoreInstancer &instancer) const { TRACE_SUBSET (this); auto *out = c->serializer->start_embed (*this); @@ -1735,7 +1735,7 @@ struct ClipList bool get_extents (hb_codepoint_t gid, hb_glyph_extents_t *extents, - const VarStoreInstancer &instancer) const + const ItemVarStoreInstancer &instancer) const { auto *rec = clips.as_array ().bsearch (gid); if (rec) @@ -1855,7 +1855,7 @@ struct BaseGlyphPaintRecord bool serialize (hb_serialize_context_t *s, const hb_map_t* glyph_map, const void* src_base, hb_subset_context_t *c, - const VarStoreInstancer &instancer) const + const ItemVarStoreInstancer &instancer) const { TRACE_SERIALIZE (this); auto *out = s->embed (this); @@ -1884,7 +1884,7 @@ struct BaseGlyphPaintRecord struct BaseGlyphList : SortedArray32Of<BaseGlyphPaintRecord> { bool subset (hb_subset_context_t *c, - const VarStoreInstancer &instancer) const + const ItemVarStoreInstancer &instancer) const { TRACE_SUBSET (this); auto *out = c->serializer->start_embed (this); @@ -1916,7 +1916,7 @@ struct LayerList : Array32OfOffset32To<Paint> { return this+(*this)[i]; } bool subset (hb_subset_context_t *c, - const VarStoreInstancer &instancer) const + const ItemVarStoreInstancer &instancer) const { TRACE_SUBSET (this); auto *out = c->serializer->start_embed (this); @@ -2206,7 +2206,7 @@ struct COLR auto snap = c->serializer->snapshot (); if (!c->serializer->allocate_size<void> (5 * HBUINT32::static_size)) return_trace (false); - VarStoreInstancer instancer (varStore ? &(this+varStore) : nullptr, + ItemVarStoreInstancer instancer (varStore ? &(this+varStore) : nullptr, varIdxMap ? &(this+varIdxMap) : nullptr, c->plan->normalized_coords.as_array ()); @@ -2250,7 +2250,7 @@ struct COLR if (version != 1) return false; - VarStoreInstancer instancer (&(this+varStore), + ItemVarStoreInstancer instancer (&(this+varStore), &(this+varIdxMap), hb_array (font->coords, font->num_coords)); @@ -2301,7 +2301,7 @@ struct COLR bool get_clip (hb_codepoint_t glyph, hb_glyph_extents_t *extents, - const VarStoreInstancer instancer) const + const ItemVarStoreInstancer instancer) const { return (this+clipList).get_extents (glyph, extents, @@ -2312,7 +2312,7 @@ struct COLR bool paint_glyph (hb_font_t *font, hb_codepoint_t glyph, hb_paint_funcs_t *funcs, void *data, unsigned int palette_index, hb_color_t foreground, bool clip = true) const { - VarStoreInstancer instancer (&(this+varStore), + ItemVarStoreInstancer instancer (&(this+varStore), &(this+varIdxMap), hb_array (font->coords, font->num_coords)); hb_paint_context_t c (this, funcs, data, font, palette_index, foreground, instancer); @@ -2327,7 +2327,7 @@ struct COLR { // COLRv1 glyph - VarStoreInstancer instancer (&(this+varStore), + ItemVarStoreInstancer instancer (&(this+varStore), &(this+varIdxMap), hb_array (font->coords, font->num_coords)); @@ -2413,7 +2413,7 @@ struct COLR Offset32To<LayerList> layerList; Offset32To<ClipList> clipList; // Offset to ClipList table (may be NULL) Offset32To<DeltaSetIndexMap> varIdxMap; // Offset to DeltaSetIndexMap table (may be NULL) - Offset32To<VariationStore> varStore; + Offset32To<ItemVariationStore> varStore; public: DEFINE_SIZE_MIN (14); }; diff --git a/thirdparty/harfbuzz/src/OT/Layout/GDEF/GDEF.hh b/thirdparty/harfbuzz/src/OT/Layout/GDEF/GDEF.hh index 14a9b5e5cd..317b96c714 100644 --- a/thirdparty/harfbuzz/src/OT/Layout/GDEF/GDEF.hh +++ b/thirdparty/harfbuzz/src/OT/Layout/GDEF/GDEF.hh @@ -189,7 +189,7 @@ struct CaretValueFormat3 friend struct CaretValue; hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction, - const VariationStore &var_store) const + const ItemVariationStore &var_store) const { return HB_DIRECTION_IS_HORIZONTAL (direction) ? font->em_scale_x (coordinate) + (this+deviceTable).get_x_delta (font, var_store) : @@ -251,7 +251,7 @@ struct CaretValue hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction, hb_codepoint_t glyph_id, - const VariationStore &var_store) const + const ItemVariationStore &var_store) const { switch (u.format) { case 1: return u.format1.get_caret_value (font, direction); @@ -316,7 +316,7 @@ struct LigGlyph unsigned get_lig_carets (hb_font_t *font, hb_direction_t direction, hb_codepoint_t glyph_id, - const VariationStore &var_store, + const ItemVariationStore &var_store, unsigned start_offset, unsigned *caret_count /* IN/OUT */, hb_position_t *caret_array /* OUT */) const @@ -372,7 +372,7 @@ struct LigCaretList unsigned int get_lig_carets (hb_font_t *font, hb_direction_t direction, hb_codepoint_t glyph_id, - const VariationStore &var_store, + const ItemVariationStore &var_store, unsigned int start_offset, unsigned int *caret_count /* IN/OUT */, hb_position_t *caret_array /* OUT */) const @@ -609,7 +609,7 @@ struct GDEFVersion1_2 * definitions--from beginning of GDEF * header (may be NULL). Introduced * in version 0x00010002. */ - Offset32To<VariationStore> + Offset32To<ItemVariationStore> varStore; /* Offset to the table of Item Variation * Store--from beginning of GDEF * header (may be NULL). Introduced @@ -663,21 +663,16 @@ struct GDEFVersion1_2 auto *out = c->serializer->start_embed (*this); if (unlikely (!c->serializer->extend_min (out))) return_trace (false); - out->version.major = version.major; - out->version.minor = version.minor; - bool subset_glyphclassdef = out->glyphClassDef.serialize_subset (c, glyphClassDef, this, nullptr, false, true); - bool subset_attachlist = out->attachList.serialize_subset (c, attachList, this); - bool subset_markattachclassdef = out->markAttachClassDef.serialize_subset (c, markAttachClassDef, this, nullptr, false, true); - - bool subset_markglyphsetsdef = false; + // Push var store first (if it's needed) so that it's last in the + // serialization order. Some font consumers assume that varstore runs to + // the end of the GDEF table. + // See: https://github.com/harfbuzz/harfbuzz/issues/4636 auto snapshot_version0 = c->serializer->snapshot (); - if (version.to_int () >= 0x00010002u) - { - if (unlikely (!c->serializer->embed (markGlyphSetsDef))) return_trace (false); - subset_markglyphsetsdef = out->markGlyphSetsDef.serialize_subset (c, markGlyphSetsDef, this); - } + if (unlikely (version.to_int () >= 0x00010002u && !c->serializer->embed (markGlyphSetsDef))) + return_trace (false); bool subset_varstore = false; + unsigned varstore_index = (unsigned) -1; auto snapshot_version2 = c->serializer->snapshot (); if (version.to_int () >= 0x00010003u) { @@ -690,35 +685,58 @@ struct GDEFVersion1_2 { item_variations_t item_vars; if (item_vars.instantiate (this+varStore, c->plan, true, true, - c->plan->gdef_varstore_inner_maps.as_array ())) + c->plan->gdef_varstore_inner_maps.as_array ())) { subset_varstore = out->varStore.serialize_serialize (c->serializer, item_vars.has_long_word (), c->plan->axis_tags, item_vars.get_region_list (), item_vars.get_vardata_encodings ()); + varstore_index = c->serializer->last_added_child_index(); + } remap_varidx_after_instantiation (item_vars.get_varidx_map (), c->plan->layout_variation_idx_delta_map); } } else + { subset_varstore = out->varStore.serialize_subset (c, varStore, this, c->plan->gdef_varstore_inner_maps.as_array ()); + varstore_index = c->serializer->last_added_child_index(); + } + } + + out->version.major = version.major; + out->version.minor = version.minor; + + if (!subset_varstore && version.to_int () >= 0x00010002u) { + c->serializer->revert (snapshot_version2); } + bool subset_markglyphsetsdef = false; + if (version.to_int () >= 0x00010002u) + { + subset_markglyphsetsdef = out->markGlyphSetsDef.serialize_subset (c, markGlyphSetsDef, this); + } if (subset_varstore) { out->version.minor = 3; c->plan->has_gdef_varstore = true; } else if (subset_markglyphsetsdef) { - out->version.minor = 2; - c->serializer->revert (snapshot_version2); + out->version.minor = 2; } else { out->version.minor = 0; c->serializer->revert (snapshot_version0); } + bool subset_glyphclassdef = out->glyphClassDef.serialize_subset (c, glyphClassDef, this, nullptr, false, true); + bool subset_attachlist = out->attachList.serialize_subset (c, attachList, this); + bool subset_markattachclassdef = out->markAttachClassDef.serialize_subset (c, markAttachClassDef, this, nullptr, false, true); bool subset_ligcaretlist = out->ligCaretList.serialize_subset (c, ligCaretList, this); + if (subset_varstore && varstore_index != (unsigned) -1) { + c->serializer->repack_last(varstore_index); + } + return_trace (subset_glyphclassdef || subset_attachlist || subset_ligcaretlist || subset_markattachclassdef || (out->version.to_int () >= 0x00010002u && subset_markglyphsetsdef) || @@ -884,14 +902,14 @@ struct GDEF default: return false; } } - const VariationStore &get_var_store () const + const ItemVariationStore &get_var_store () const { switch (u.version.major) { - case 1: return u.version.to_int () >= 0x00010003u ? this+u.version1.varStore : Null(VariationStore); + case 1: return u.version.to_int () >= 0x00010003u ? this+u.version1.varStore : Null(ItemVariationStore); #ifndef HB_NO_BEYOND_64K case 2: return this+u.version2.varStore; #endif - default: return Null(VariationStore); + default: return Null(ItemVariationStore); } } @@ -1011,9 +1029,9 @@ struct GDEF hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *layout_variation_idx_delta_map /* OUT */) const { if (!has_var_store ()) return; - const VariationStore &var_store = get_var_store (); + const ItemVariationStore &var_store = get_var_store (); float *store_cache = var_store.create_cache (); - + unsigned new_major = 0, new_minor = 0; unsigned last_major = (layout_variation_indices->get_min ()) >> 16; for (unsigned idx : layout_variation_indices->iter ()) diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/PairPosFormat2.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/PairPosFormat2.hh index dd02da887d..9c805b39a1 100644 --- a/thirdparty/harfbuzz/src/OT/Layout/GPOS/PairPosFormat2.hh +++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/PairPosFormat2.hh @@ -324,17 +324,8 @@ struct PairPosFormat2_4 : ValueBase } } - const hb_set_t &glyphset = *c->plan->glyphset_gsub (); - const hb_map_t &glyph_map = *c->plan->glyph_map; - - auto it = - + hb_iter (this+coverage) - | hb_filter (glyphset) - | hb_map_retains_sorting (glyph_map) - ; - - out->coverage.serialize_serialize (c->serializer, it); - return_trace (out->class1Count && out->class2Count && bool (it)); + bool ret = out->coverage.serialize_subset(c, coverage, this); + return_trace (out->class1Count && out->class2Count && ret); } diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/ValueFormat.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/ValueFormat.hh index 17f57db1f5..9442cc1cc5 100644 --- a/thirdparty/harfbuzz/src/OT/Layout/GPOS/ValueFormat.hh +++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/ValueFormat.hh @@ -116,7 +116,7 @@ struct ValueFormat : HBUINT16 if (!use_x_device && !use_y_device) return ret; - const VariationStore &store = c->var_store; + const ItemVariationStore &store = c->var_store; auto *cache = c->var_store_cache; /* pixel -> fractional pixel */ diff --git a/thirdparty/harfbuzz/src/OT/glyf/CompositeGlyph.hh b/thirdparty/harfbuzz/src/OT/glyf/CompositeGlyph.hh index 60858a5a58..5c0ecd5133 100644 --- a/thirdparty/harfbuzz/src/OT/glyf/CompositeGlyph.hh +++ b/thirdparty/harfbuzz/src/OT/glyf/CompositeGlyph.hh @@ -240,7 +240,8 @@ struct CompositeGlyphRecord } if (is_anchored ()) tx = ty = 0; - trans.init ((float) tx, (float) ty); + /* set is_end_point flag to true, used by IUP delta optimization */ + trans.init ((float) tx, (float) ty, true); { const F2DOT14 *points = (const F2DOT14 *) p; diff --git a/thirdparty/harfbuzz/src/OT/glyf/Glyph.hh b/thirdparty/harfbuzz/src/OT/glyf/Glyph.hh index 5ea611948f..69a0b625c7 100644 --- a/thirdparty/harfbuzz/src/OT/glyf/Glyph.hh +++ b/thirdparty/harfbuzz/src/OT/glyf/Glyph.hh @@ -103,6 +103,9 @@ struct Glyph } } + bool is_composite () const + { return type == COMPOSITE; } + bool get_all_points_without_var (const hb_face_t *face, contour_point_vector_t &points /* OUT */) const { diff --git a/thirdparty/harfbuzz/src/OT/glyf/glyf-helpers.hh b/thirdparty/harfbuzz/src/OT/glyf/glyf-helpers.hh index d0a5a132f0..f157bf0020 100644 --- a/thirdparty/harfbuzz/src/OT/glyf/glyf-helpers.hh +++ b/thirdparty/harfbuzz/src/OT/glyf/glyf-helpers.hh @@ -38,7 +38,7 @@ _write_loca (IteratorIn&& it, unsigned padded_size = *it++; offset += padded_size; - DEBUG_MSG (SUBSET, nullptr, "loca entry gid %u offset %u padded-size %u", gid, offset, padded_size); + DEBUG_MSG (SUBSET, nullptr, "loca entry gid %" PRIu32 " offset %u padded-size %u", gid, offset, padded_size); value = offset >> right_shift; *dest++ = value; diff --git a/thirdparty/harfbuzz/src/graph/classdef-graph.hh b/thirdparty/harfbuzz/src/graph/classdef-graph.hh index 9cf845a82d..da6378820b 100644 --- a/thirdparty/harfbuzz/src/graph/classdef-graph.hh +++ b/thirdparty/harfbuzz/src/graph/classdef-graph.hh @@ -134,20 +134,23 @@ struct ClassDef : public OT::ClassDef struct class_def_size_estimator_t { + // TODO(garretrieger): update to support beyond64k coverage/classdef tables. + constexpr static unsigned class_def_format1_base_size = 6; + constexpr static unsigned class_def_format2_base_size = 4; + constexpr static unsigned coverage_base_size = 4; + constexpr static unsigned bytes_per_range = 6; + constexpr static unsigned bytes_per_glyph = 2; + template<typename It> class_def_size_estimator_t (It glyph_and_class) - : gids_consecutive (true), num_ranges_per_class (), glyphs_per_class () + : num_ranges_per_class (), glyphs_per_class () { - unsigned last_gid = (unsigned) -1; + reset(); for (auto p : + glyph_and_class) { unsigned gid = p.first; unsigned klass = p.second; - if (last_gid != (unsigned) -1 && gid != last_gid + 1) - gids_consecutive = false; - last_gid = gid; - hb_set_t* glyphs; if (glyphs_per_class.has (klass, &glyphs) && glyphs) { glyphs->add (gid); @@ -177,28 +180,54 @@ struct class_def_size_estimator_t } } - // Incremental increase in the Coverage and ClassDef table size - // (worst case) if all glyphs associated with 'klass' were added. - unsigned incremental_coverage_size (unsigned klass) const + void reset() { + class_def_1_size = class_def_format1_base_size; + class_def_2_size = class_def_format2_base_size; + included_glyphs.clear(); + included_classes.clear(); + } + + // Compute the size of coverage for all glyphs added via 'add_class_def_size'. + unsigned coverage_size () const { - // Coverage takes 2 bytes per glyph worst case, - return 2 * glyphs_per_class.get (klass).get_population (); + unsigned format1_size = coverage_base_size + bytes_per_glyph * included_glyphs.get_population(); + unsigned format2_size = coverage_base_size + bytes_per_range * num_glyph_ranges(); + return hb_min(format1_size, format2_size); } - // Incremental increase in the Coverage and ClassDef table size - // (worst case) if all glyphs associated with 'klass' were added. - unsigned incremental_class_def_size (unsigned klass) const + // Compute the new size of the ClassDef table if all glyphs associated with 'klass' were added. + unsigned add_class_def_size (unsigned klass) { - // ClassDef takes 6 bytes per range - unsigned class_def_2_size = 6 * num_ranges_per_class.get (klass); - if (gids_consecutive) - { - // ClassDef1 takes 2 bytes per glyph, but only can be used - // when gids are consecutive. - return hb_min (2 * glyphs_per_class.get (klass).get_population (), class_def_2_size); + if (!included_classes.has(klass)) { + hb_set_t* glyphs = nullptr; + if (glyphs_per_class.has(klass, &glyphs)) { + included_glyphs.union_(*glyphs); + } + + class_def_1_size = class_def_format1_base_size; + if (!included_glyphs.is_empty()) { + unsigned min_glyph = included_glyphs.get_min(); + unsigned max_glyph = included_glyphs.get_max(); + class_def_1_size += bytes_per_glyph * (max_glyph - min_glyph + 1); + } + + class_def_2_size += bytes_per_range * num_ranges_per_class.get (klass); + + included_classes.add(klass); } - return class_def_2_size; + return hb_min (class_def_1_size, class_def_2_size); + } + + unsigned num_glyph_ranges() const { + hb_codepoint_t start = HB_SET_VALUE_INVALID; + hb_codepoint_t end = HB_SET_VALUE_INVALID; + + unsigned count = 0; + while (included_glyphs.next_range (&start, &end)) { + count++; + } + return count; } bool in_error () @@ -214,9 +243,12 @@ struct class_def_size_estimator_t } private: - bool gids_consecutive; hb_hashmap_t<unsigned, unsigned> num_ranges_per_class; hb_hashmap_t<unsigned, hb_set_t> glyphs_per_class; + hb_set_t included_classes; + hb_set_t included_glyphs; + unsigned class_def_1_size; + unsigned class_def_2_size; }; diff --git a/thirdparty/harfbuzz/src/graph/graph.hh b/thirdparty/harfbuzz/src/graph/graph.hh index 26ad00bdd9..2a9d8346c0 100644 --- a/thirdparty/harfbuzz/src/graph/graph.hh +++ b/thirdparty/harfbuzz/src/graph/graph.hh @@ -195,6 +195,15 @@ struct graph_t return incoming_edges_; } + unsigned incoming_edges_from_parent (unsigned parent_index) const { + if (single_parent != (unsigned) -1) { + return single_parent == parent_index ? 1 : 0; + } + + unsigned* count; + return parents.has(parent_index, &count) ? *count : 0; + } + void reset_parents () { incoming_edges_ = 0; @@ -334,6 +343,16 @@ struct graph_t return true; } + bool give_max_priority () + { + bool result = false; + while (!has_max_priority()) { + result = true; + priority++; + } + return result; + } + bool has_max_priority () const { return priority >= 3; } @@ -1023,6 +1042,11 @@ struct graph_t * Creates a copy of child and re-assigns the link from * parent to the clone. The copy is a shallow copy, objects * linked from child are not duplicated. + * + * Returns the index of the newly created duplicate. + * + * If the child_idx only has incoming edges from parent_idx, this + * will do nothing and return the original child_idx. */ unsigned duplicate_if_shared (unsigned parent_idx, unsigned child_idx) { @@ -1036,18 +1060,20 @@ struct graph_t * Creates a copy of child and re-assigns the link from * parent to the clone. The copy is a shallow copy, objects * linked from child are not duplicated. + * + * Returns the index of the newly created duplicate. + * + * If the child_idx only has incoming edges from parent_idx, + * duplication isn't possible and this will return -1. */ unsigned duplicate (unsigned parent_idx, unsigned child_idx) { update_parents (); - unsigned links_to_child = 0; - for (const auto& l : vertices_[parent_idx].obj.all_links ()) - { - if (l.objidx == child_idx) links_to_child++; - } + const auto& child = vertices_[child_idx]; + unsigned links_to_child = child.incoming_edges_from_parent(parent_idx); - if (vertices_[child_idx].incoming_edges () <= links_to_child) + if (child.incoming_edges () <= links_to_child) { // Can't duplicate this node, doing so would orphan the original one as all remaining links // to child are from parent. @@ -1060,7 +1086,7 @@ struct graph_t parent_idx, child_idx); unsigned clone_idx = duplicate (child_idx); - if (clone_idx == (unsigned) -1) return false; + if (clone_idx == (unsigned) -1) return -1; // duplicate shifts the root node idx, so if parent_idx was root update it. if (parent_idx == clone_idx) parent_idx++; @@ -1076,6 +1102,62 @@ struct graph_t return clone_idx; } + /* + * Creates a copy of child and re-assigns the links from + * parents to the clone. The copy is a shallow copy, objects + * linked from child are not duplicated. + * + * Returns the index of the newly created duplicate. + * + * If the child_idx only has incoming edges from parents, + * duplication isn't possible or duplication fails and this will + * return -1. + */ + unsigned duplicate (const hb_set_t* parents, unsigned child_idx) + { + if (parents->is_empty()) { + return -1; + } + + update_parents (); + + const auto& child = vertices_[child_idx]; + unsigned links_to_child = 0; + unsigned last_parent = parents->get_max(); + unsigned first_parent = parents->get_min(); + for (unsigned parent_idx : *parents) { + links_to_child += child.incoming_edges_from_parent(parent_idx); + } + + if (child.incoming_edges () <= links_to_child) + { + // Can't duplicate this node, doing so would orphan the original one as all remaining links + // to child are from parent. + DEBUG_MSG (SUBSET_REPACK, nullptr, " Not duplicating %u, ..., %u => %u", first_parent, last_parent, child_idx); + return -1; + } + + DEBUG_MSG (SUBSET_REPACK, nullptr, " Duplicating %u, ..., %u => %u", first_parent, last_parent, child_idx); + + unsigned clone_idx = duplicate (child_idx); + if (clone_idx == (unsigned) -1) return false; + + for (unsigned parent_idx : *parents) { + // duplicate shifts the root node idx, so if parent_idx was root update it. + if (parent_idx == clone_idx) parent_idx++; + auto& parent = vertices_[parent_idx]; + for (auto& l : parent.obj.all_links_writer ()) + { + if (l.objidx != child_idx) + continue; + + reassign_link (l, parent_idx, clone_idx); + } + } + + return clone_idx; + } + /* * Adds a new node to the graph, not connected to anything. diff --git a/thirdparty/harfbuzz/src/graph/pairpos-graph.hh b/thirdparty/harfbuzz/src/graph/pairpos-graph.hh index f7f74b18c9..fd46861de4 100644 --- a/thirdparty/harfbuzz/src/graph/pairpos-graph.hh +++ b/thirdparty/harfbuzz/src/graph/pairpos-graph.hh @@ -247,8 +247,8 @@ struct PairPosFormat2 : public OT::Layout::GPOS_impl::PairPosFormat2_4<SmallType for (unsigned i = 0; i < class1_count; i++) { unsigned accumulated_delta = class1_record_size; - coverage_size += estimator.incremental_coverage_size (i); - class_def_1_size += estimator.incremental_class_def_size (i); + class_def_1_size = estimator.add_class_def_size (i); + coverage_size = estimator.coverage_size (); max_coverage_size = hb_max (max_coverage_size, coverage_size); max_class_def_1_size = hb_max (max_class_def_1_size, class_def_1_size); @@ -280,8 +280,10 @@ struct PairPosFormat2 : public OT::Layout::GPOS_impl::PairPosFormat2_4<SmallType split_points.push (i); // split does not include i, so add the size for i when we reset the size counters. accumulated = base_size + accumulated_delta; - coverage_size = 4 + estimator.incremental_coverage_size (i); - class_def_1_size = 4 + estimator.incremental_class_def_size (i); + + estimator.reset(); + class_def_1_size = estimator.add_class_def_size(i); + coverage_size = estimator.coverage_size(); visited.clear (); // node sharing isn't allowed between splits. } } diff --git a/thirdparty/harfbuzz/src/hb-aat-layout-morx-table.hh b/thirdparty/harfbuzz/src/hb-aat-layout-morx-table.hh index 06c9334b37..8436551324 100644 --- a/thirdparty/harfbuzz/src/hb-aat-layout-morx-table.hh +++ b/thirdparty/harfbuzz/src/hb-aat-layout-morx-table.hh @@ -552,6 +552,7 @@ struct LigatureSubtable { DEBUG_MSG (APPLY, nullptr, "Skipping ligature component"); if (unlikely (!buffer->move_to (match_positions[--match_length % ARRAY_LENGTH (match_positions)]))) return; + buffer->cur().unicode_props() |= UPROPS_MASK_IGNORABLE; if (unlikely (!buffer->replace_glyph (DELETED_GLYPH))) return; } diff --git a/thirdparty/harfbuzz/src/hb-algs.hh b/thirdparty/harfbuzz/src/hb-algs.hh index ea97057165..efa6074a42 100644 --- a/thirdparty/harfbuzz/src/hb-algs.hh +++ b/thirdparty/harfbuzz/src/hb-algs.hh @@ -671,7 +671,7 @@ struct hb_pair_t return 0; } - friend void swap (hb_pair_t& a, hb_pair_t& b) + friend void swap (hb_pair_t& a, hb_pair_t& b) noexcept { hb_swap (a.first, b.first); hb_swap (a.second, b.second); @@ -1053,6 +1053,18 @@ _hb_cmp_method (const void *pkey, const void *pval, Ts... ds) return val.cmp (key, ds...); } +template <typename K, typename V> +static int +_hb_cmp_operator (const void *pkey, const void *pval) +{ + const K& key = * (const K*) pkey; + const V& val = * (const V*) pval; + + if (key < val) return -1; + if (key > val) return 1; + return 0; +} + template <typename V, typename K, typename ...Ts> static inline bool hb_bsearch_impl (unsigned *pos, /* Out */ diff --git a/thirdparty/harfbuzz/src/hb-bit-set-invertible.hh b/thirdparty/harfbuzz/src/hb-bit-set-invertible.hh index 2626251807..d5d1326d9f 100644 --- a/thirdparty/harfbuzz/src/hb-bit-set-invertible.hh +++ b/thirdparty/harfbuzz/src/hb-bit-set-invertible.hh @@ -39,10 +39,10 @@ struct hb_bit_set_invertible_t hb_bit_set_invertible_t () = default; hb_bit_set_invertible_t (const hb_bit_set_invertible_t& o) = default; - hb_bit_set_invertible_t (hb_bit_set_invertible_t&& other) : hb_bit_set_invertible_t () { hb_swap (*this, other); } + hb_bit_set_invertible_t (hb_bit_set_invertible_t&& other) noexcept : hb_bit_set_invertible_t () { hb_swap (*this, other); } hb_bit_set_invertible_t& operator= (const hb_bit_set_invertible_t& o) = default; - hb_bit_set_invertible_t& operator= (hb_bit_set_invertible_t&& other) { hb_swap (*this, other); return *this; } - friend void swap (hb_bit_set_invertible_t &a, hb_bit_set_invertible_t &b) + hb_bit_set_invertible_t& operator= (hb_bit_set_invertible_t&& other) noexcept { hb_swap (*this, other); return *this; } + friend void swap (hb_bit_set_invertible_t &a, hb_bit_set_invertible_t &b) noexcept { if (likely (!a.s.successful || !b.s.successful)) return; diff --git a/thirdparty/harfbuzz/src/hb-bit-set.hh b/thirdparty/harfbuzz/src/hb-bit-set.hh index 1dbcce5cbd..5f4c6f0afe 100644 --- a/thirdparty/harfbuzz/src/hb-bit-set.hh +++ b/thirdparty/harfbuzz/src/hb-bit-set.hh @@ -38,10 +38,10 @@ struct hb_bit_set_t ~hb_bit_set_t () = default; hb_bit_set_t (const hb_bit_set_t& other) : hb_bit_set_t () { set (other, true); } - hb_bit_set_t ( hb_bit_set_t&& other) : hb_bit_set_t () { hb_swap (*this, other); } + hb_bit_set_t ( hb_bit_set_t&& other) noexcept : hb_bit_set_t () { hb_swap (*this, other); } hb_bit_set_t& operator= (const hb_bit_set_t& other) { set (other); return *this; } - hb_bit_set_t& operator= (hb_bit_set_t&& other) { hb_swap (*this, other); return *this; } - friend void swap (hb_bit_set_t &a, hb_bit_set_t &b) + hb_bit_set_t& operator= (hb_bit_set_t&& other) noexcept { hb_swap (*this, other); return *this; } + friend void swap (hb_bit_set_t &a, hb_bit_set_t &b) noexcept { if (likely (!a.successful || !b.successful)) return; diff --git a/thirdparty/harfbuzz/src/hb-blob.cc b/thirdparty/harfbuzz/src/hb-blob.cc index 265effba03..873d9b257a 100644 --- a/thirdparty/harfbuzz/src/hb-blob.cc +++ b/thirdparty/harfbuzz/src/hb-blob.cc @@ -598,6 +598,11 @@ _open_resource_fork (const char *file_name, hb_mapped_file_t *file) * Creates a new blob containing the data from the * specified binary font file. * + * The filename is passed directly to the system on all platforms, + * except on Windows, where the filename is interpreted as UTF-8. + * Only if the filename is not valid UTF-8, it will be interpreted + * according to the system codepage. + * * Returns: An #hb_blob_t pointer with the content of the file, * or hb_blob_get_empty() if failed. * @@ -617,6 +622,11 @@ hb_blob_create_from_file (const char *file_name) * Creates a new blob containing the data from the * specified binary font file. * + * The filename is passed directly to the system on all platforms, + * except on Windows, where the filename is interpreted as UTF-8. + * Only if the filename is not valid UTF-8, it will be interpreted + * according to the system codepage. + * * Returns: An #hb_blob_t pointer with the content of the file, * or `NULL` if failed. * @@ -672,10 +682,19 @@ fail_without_close: if (unlikely (!file)) return nullptr; HANDLE fd; + int conversion; unsigned int size = strlen (file_name) + 1; 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); + + /* Assume file name is given in UTF-8 encoding */ + conversion = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, file_name, -1, wchar_file_name, size); + if (conversion <= 0) + { + /* Conversion failed due to invalid UTF-8 characters, + Repeat conversion based on system code page */ + mbstowcs(wchar_file_name, file_name, size); + } #if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) && WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) { CREATEFILE2_EXTENDED_PARAMETERS ceparams = { 0 }; diff --git a/thirdparty/harfbuzz/src/hb-buffer-verify.cc b/thirdparty/harfbuzz/src/hb-buffer-verify.cc index 15a53919de..671d6eda8c 100644 --- a/thirdparty/harfbuzz/src/hb-buffer-verify.cc +++ b/thirdparty/harfbuzz/src/hb-buffer-verify.cc @@ -149,7 +149,7 @@ buffer_verify_unsafe_to_break (hb_buffer_t *buffer, } assert (text_start < text_end); - if (0) + if (false) printf("start %u end %u text start %u end %u\n", start, end, text_start, text_end); hb_buffer_clear_contents (fragment); @@ -288,7 +288,7 @@ buffer_verify_unsafe_to_concat (hb_buffer_t *buffer, } assert (text_start < text_end); - if (0) + if (false) printf("start %u end %u text start %u end %u\n", start, end, text_start, text_end); #if 0 diff --git a/thirdparty/harfbuzz/src/hb-buffer.cc b/thirdparty/harfbuzz/src/hb-buffer.cc index 934c6c2129..d621a7cc55 100644 --- a/thirdparty/harfbuzz/src/hb-buffer.cc +++ b/thirdparty/harfbuzz/src/hb-buffer.cc @@ -309,6 +309,7 @@ hb_buffer_t::clear () deallocate_var_all (); serial = 0; + random_state = 1; scratch_flags = HB_BUFFER_SCRATCH_FLAG_DEFAULT; } @@ -1359,6 +1360,49 @@ hb_buffer_get_not_found_glyph (const hb_buffer_t *buffer) return buffer->not_found; } +/** + * hb_buffer_set_random_state: + * @buffer: An #hb_buffer_t + * @state: the new random state + * + * Sets the random state of the buffer. The state changes + * every time a glyph uses randomness (eg. the `rand` + * OpenType feature). This function together with + * hb_buffer_get_random_state() allow for transferring + * the current random state to a subsequent buffer, to + * get better randomness distribution. + * + * Defaults to 1 and when buffer contents are cleared. + * A value of 0 disables randomness during shaping. + * + * Since: 8.4.0 + **/ +void +hb_buffer_set_random_state (hb_buffer_t *buffer, + unsigned state) +{ + if (unlikely (hb_object_is_immutable (buffer))) + return; + + buffer->random_state = state; +} + +/** + * hb_buffer_get_random_state: + * @buffer: An #hb_buffer_t + * + * See hb_buffer_set_random_state(). + * + * Return value: + * The @buffer random state + * + * Since: 8.4.0 + **/ +unsigned +hb_buffer_get_random_state (const hb_buffer_t *buffer) +{ + return buffer->random_state; +} /** * hb_buffer_clear_contents: diff --git a/thirdparty/harfbuzz/src/hb-buffer.h b/thirdparty/harfbuzz/src/hb-buffer.h index 3573127ff0..f75fe96b21 100644 --- a/thirdparty/harfbuzz/src/hb-buffer.h +++ b/thirdparty/harfbuzz/src/hb-buffer.h @@ -487,6 +487,12 @@ hb_buffer_set_not_found_glyph (hb_buffer_t *buffer, HB_EXTERN hb_codepoint_t hb_buffer_get_not_found_glyph (const hb_buffer_t *buffer); +HB_EXTERN void +hb_buffer_set_random_state (hb_buffer_t *buffer, + unsigned state); + +HB_EXTERN unsigned +hb_buffer_get_random_state (const hb_buffer_t *buffer); /* * Content API. diff --git a/thirdparty/harfbuzz/src/hb-buffer.hh b/thirdparty/harfbuzz/src/hb-buffer.hh index f04ad58f11..0a198722d6 100644 --- a/thirdparty/harfbuzz/src/hb-buffer.hh +++ b/thirdparty/harfbuzz/src/hb-buffer.hh @@ -116,6 +116,7 @@ struct hb_buffer_t uint8_t allocated_var_bits; uint8_t serial; + uint32_t random_state; hb_buffer_scratch_flags_t scratch_flags; /* Have space-fallback, etc. */ unsigned int max_len; /* Maximum allowed len. */ int max_ops; /* Maximum allowed operations. */ diff --git a/thirdparty/harfbuzz/src/hb-cff-interp-dict-common.hh b/thirdparty/harfbuzz/src/hb-cff-interp-dict-common.hh index 53226b227e..a08b10b5ff 100644 --- a/thirdparty/harfbuzz/src/hb-cff-interp-dict-common.hh +++ b/thirdparty/harfbuzz/src/hb-cff-interp-dict-common.hh @@ -54,8 +54,8 @@ struct top_dict_values_t : dict_values_t<OPSTR> } void fini () { dict_values_t<OPSTR>::fini (); } - unsigned int charStringsOffset; - unsigned int FDArrayOffset; + int charStringsOffset; + int FDArrayOffset; }; struct dict_opset_t : opset_t<number_t> @@ -157,11 +157,11 @@ struct top_dict_opset_t : dict_opset_t { switch (op) { case OpCode_CharStrings: - dictval.charStringsOffset = env.argStack.pop_uint (); + dictval.charStringsOffset = env.argStack.pop_int (); env.clear_args (); break; case OpCode_FDArray: - dictval.FDArrayOffset = env.argStack.pop_uint (); + dictval.FDArrayOffset = env.argStack.pop_int (); env.clear_args (); break; case OpCode_FontMatrix: diff --git a/thirdparty/harfbuzz/src/hb-cff2-interp-cs.hh b/thirdparty/harfbuzz/src/hb-cff2-interp-cs.hh index 915b10cf39..55b1d3bf8d 100644 --- a/thirdparty/harfbuzz/src/hb-cff2-interp-cs.hh +++ b/thirdparty/harfbuzz/src/hb-cff2-interp-cs.hh @@ -168,7 +168,7 @@ struct cff2_cs_interp_env_t : cs_interp_env_t<ELEM, CFF2Subrs> protected: const int *coords; unsigned int num_coords; - const CFF2VariationStore *varStore; + const CFF2ItemVariationStore *varStore; unsigned int region_count; unsigned int ivs; hb_vector_t<float> scalars; diff --git a/thirdparty/harfbuzz/src/hb-common.cc b/thirdparty/harfbuzz/src/hb-common.cc index 0c13c7d171..4b8bae4422 100644 --- a/thirdparty/harfbuzz/src/hb-common.cc +++ b/thirdparty/harfbuzz/src/hb-common.cc @@ -996,7 +996,7 @@ hb_feature_to_string (hb_feature_t *feature, if (feature->value > 1) { s[len++] = '='; - len += hb_max (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%u", feature->value)); + len += hb_max (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%" PRIu32, feature->value)); } assert (len < ARRAY_LENGTH (s)); len = hb_min (len, size - 1); diff --git a/thirdparty/harfbuzz/src/hb-common.h b/thirdparty/harfbuzz/src/hb-common.h index a9fe666b39..533de91562 100644 --- a/thirdparty/harfbuzz/src/hb-common.h +++ b/thirdparty/harfbuzz/src/hb-common.h @@ -47,14 +47,10 @@ # endif /* !__cplusplus */ #endif -#if defined (_SVR4) || defined (SVR4) || defined (__OpenBSD__) || \ - defined (_sgi) || defined (__sun) || defined (sun) || \ - defined (__digital__) || defined (__HP_cc) -# include <inttypes.h> -#elif defined (_AIX) +#if defined (_AIX) # include <sys/inttypes.h> #elif defined (_MSC_VER) && _MSC_VER < 1600 -/* VS 2010 (_MSC_VER 1600) has stdint.h */ +/* VS 2010 (_MSC_VER 1600) has stdint.h */ typedef __int8 int8_t; typedef unsigned __int8 uint8_t; typedef __int16 int16_t; @@ -63,10 +59,11 @@ typedef __int32 int32_t; typedef unsigned __int32 uint32_t; typedef __int64 int64_t; typedef unsigned __int64 uint64_t; -#elif defined (__KERNEL__) -# include <linux/types.h> -#else +#elif defined (_MSC_VER) && _MSC_VER < 1800 +/* VS 2013 (_MSC_VER 1800) has inttypes.h */ # include <stdint.h> +#else +# include <inttypes.h> #endif #if defined(__GNUC__) && ((__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) diff --git a/thirdparty/harfbuzz/src/hb-cplusplus.hh b/thirdparty/harfbuzz/src/hb-cplusplus.hh index 531ef1b7c8..a640e192de 100644 --- a/thirdparty/harfbuzz/src/hb-cplusplus.hh +++ b/thirdparty/harfbuzz/src/hb-cplusplus.hh @@ -56,15 +56,15 @@ struct shared_ptr explicit shared_ptr (T *p = nullptr) : p (p) {} shared_ptr (const shared_ptr &o) : p (v::reference (o.p)) {} - shared_ptr (shared_ptr &&o) : p (o.p) { o.p = nullptr; } + shared_ptr (shared_ptr &&o) noexcept : p (o.p) { o.p = nullptr; } shared_ptr& operator = (const shared_ptr &o) { if (p != o.p) { destroy (); p = o.p; reference (); } return *this; } - shared_ptr& operator = (shared_ptr &&o) { v::destroy (p); p = o.p; o.p = nullptr; return *this; } + shared_ptr& operator = (shared_ptr &&o) noexcept { v::destroy (p); p = o.p; o.p = nullptr; return *this; } ~shared_ptr () { v::destroy (p); p = nullptr; } T* get() const { return p; } - void swap (shared_ptr &o) { std::swap (p, o.p); } - friend void swap (shared_ptr &a, shared_ptr &b) { std::swap (a.p, b.p); } + void swap (shared_ptr &o) noexcept { std::swap (p, o.p); } + friend void swap (shared_ptr &a, shared_ptr &b) noexcept { std::swap (a.p, b.p); } operator T * () const { return p; } T& operator * () const { return *get (); } @@ -98,16 +98,16 @@ struct unique_ptr explicit unique_ptr (T *p = nullptr) : p (p) {} unique_ptr (const unique_ptr &o) = delete; - unique_ptr (unique_ptr &&o) : p (o.p) { o.p = nullptr; } + unique_ptr (unique_ptr &&o) noexcept : p (o.p) { o.p = nullptr; } unique_ptr& operator = (const unique_ptr &o) = delete; - unique_ptr& operator = (unique_ptr &&o) { v::destroy (p); p = o.p; o.p = nullptr; return *this; } + unique_ptr& operator = (unique_ptr &&o) noexcept { v::destroy (p); p = o.p; o.p = nullptr; return *this; } ~unique_ptr () { v::destroy (p); p = nullptr; } T* get() const { return p; } T* release () { T* v = p; p = nullptr; return v; } - void swap (unique_ptr &o) { std::swap (p, o.p); } - friend void swap (unique_ptr &a, unique_ptr &b) { std::swap (a.p, b.p); } + void swap (unique_ptr &o) noexcept { std::swap (p, o.p); } + friend void swap (unique_ptr &a, unique_ptr &b) noexcept { std::swap (a.p, b.p); } operator T * () const { return p; } T& operator * () const { return *get (); } diff --git a/thirdparty/harfbuzz/src/hb-directwrite.cc b/thirdparty/harfbuzz/src/hb-directwrite.cc index 42764a244b..6c90265d0b 100644 --- a/thirdparty/harfbuzz/src/hb-directwrite.cc +++ b/thirdparty/harfbuzz/src/hb-directwrite.cc @@ -173,7 +173,7 @@ _hb_directwrite_shaper_face_data_create (hb_face_t *face) t_DWriteCreateFactory p_DWriteCreateFactory; -#if defined(__GNUC__) +#if defined(__GNUC__) || defined(__clang__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wcast-function-type" #endif @@ -181,7 +181,7 @@ _hb_directwrite_shaper_face_data_create (hb_face_t *face) p_DWriteCreateFactory = (t_DWriteCreateFactory) GetProcAddress (data->dwrite_dll, "DWriteCreateFactory"); -#if defined(__GNUC__) +#if defined(__GNUC__) || defined(__clang__) #pragma GCC diagnostic pop #endif diff --git a/thirdparty/harfbuzz/src/hb-features.h b/thirdparty/harfbuzz/src/hb-features.h new file mode 100644 index 0000000000..9199864195 --- /dev/null +++ b/thirdparty/harfbuzz/src/hb-features.h @@ -0,0 +1,119 @@ +/* + * Copyright © 2022 Red Hat, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +#ifndef HB_FEATURES_H +#define HB_FEATURES_H + +HB_BEGIN_DECLS + +/** + * SECTION: hb-features + * @title: hb-features + * @short_description: Feature detection + * @include: hb-features.h + * + * Macros for detecting optional HarfBuzz features at build time. + **/ + +/** + * HB_HAS_CAIRO: + * + * Defined if Harfbuzz has been built with cairo support. + */ +# + +/** + * HB_HAS_CORETEXT: + * + * Defined if Harfbuzz has been built with CoreText support. + */ +#undef HB_HAS_CORETEXT + +/** + * HB_HAS_DIRECTWRITE: + * + * Defined if Harfbuzz has been built with DirectWrite support. + */ +#undef HB_HAS_DIRECTWRITE + +/** + * HB_HAS_FREETYPE: + * + * Defined if Harfbuzz has been built with Freetype support. + */ +#define HB_HAS_FREETYPE 1 + +/** + * HB_HAS_GDI: + * + * Defined if Harfbuzz has been built with GDI support. + */ +#undef HB_HAS_GDI + +/** + * HB_HAS_GLIB: + * + * Defined if Harfbuzz has been built with GLib support. + */ +#define HB_HAS_GLIB 1 + +/** + * HB_HAS_GOBJECT: + * + * Defined if Harfbuzz has been built with GObject support. + */ +#undef HB_HAS_GOBJECT + +/** + * HB_HAS_GRAPHITE: + * + * Defined if Harfbuzz has been built with Graphite support. + */ +#undef HB_HAS_GRAPHITE + +/** + * HB_HAS_ICU: + * + * Defined if Harfbuzz has been built with ICU support. + */ +#undef HB_HAS_ICU + +/** + * HB_HAS_UNISCRIBE: + * + * Defined if Harfbuzz has been built with Uniscribe support. + */ +#undef HB_HAS_UNISCRIBE + +/** + * HB_HAS_WASM: + * + * Defined if Harfbuzz has been built with WebAssembly support. + */ +#undef HB_HAS_WASM + + +HB_END_DECLS + +#endif /* HB_FEATURES_H */ diff --git a/thirdparty/harfbuzz/src/hb-font.hh b/thirdparty/harfbuzz/src/hb-font.hh index f503575c34..4c8190b0dd 100644 --- a/thirdparty/harfbuzz/src/hb-font.hh +++ b/thirdparty/harfbuzz/src/hb-font.hh @@ -651,7 +651,7 @@ struct hb_font_t { if (get_glyph_name (glyph, s, size)) return; - if (size && snprintf (s, size, "gid%u", glyph) < 0) + if (size && snprintf (s, size, "gid%" PRIu32, glyph) < 0) *s = '\0'; } diff --git a/thirdparty/harfbuzz/src/hb-ft.cc b/thirdparty/harfbuzz/src/hb-ft.cc index 955a9081e0..3de4a6d5d4 100644 --- a/thirdparty/harfbuzz/src/hb-ft.cc +++ b/thirdparty/harfbuzz/src/hb-ft.cc @@ -224,7 +224,7 @@ _hb_ft_hb_font_check_changed (hb_font_t *font, * * Sets the FT_Load_Glyph load flags for the specified #hb_font_t. * - * For more information, see + * For more information, see * <https://freetype.org/freetype2/docs/reference/ft2-glyph_retrieval.html#ft_load_xxx> * * This function works with #hb_font_t objects created by @@ -252,7 +252,7 @@ hb_ft_font_set_load_flags (hb_font_t *font, int load_flags) * * Fetches the FT_Load_Glyph load flags of the specified #hb_font_t. * - * For more information, see + * For more information, see * <https://freetype.org/freetype2/docs/reference/ft2-glyph_retrieval.html#ft_load_xxx> * * This function works with #hb_font_t objects created by @@ -1118,10 +1118,10 @@ _hb_ft_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data * This variant of the function does not provide any life-cycle management. * * Most client programs should use hb_ft_face_create_referenced() - * (or, perhaps, hb_ft_face_create_cached()) instead. + * (or, perhaps, hb_ft_face_create_cached()) instead. * * If you know you have valid reasons not to use hb_ft_face_create_referenced(), - * then it is the client program's responsibility to destroy @ft_face + * then it is the client program's responsibility to destroy @ft_face * after the #hb_face_t face object has been destroyed. * * Return value: (transfer full): the new #hb_face_t face object @@ -1215,7 +1215,7 @@ hb_ft_face_finalize (void *arg) hb_face_t * hb_ft_face_create_cached (FT_Face ft_face) { - if (unlikely (!ft_face->generic.data || ft_face->generic.finalizer != (FT_Generic_Finalizer) hb_ft_face_finalize)) + if (unlikely (!ft_face->generic.data || ft_face->generic.finalizer != hb_ft_face_finalize)) { if (ft_face->generic.finalizer) ft_face->generic.finalizer (ft_face); @@ -1241,13 +1241,13 @@ hb_ft_face_create_cached (FT_Face ft_face) * This variant of the function does not provide any life-cycle management. * * Most client programs should use hb_ft_font_create_referenced() - * instead. + * instead. * * If you know you have valid reasons not to use hb_ft_font_create_referenced(), - * then it is the client program's responsibility to destroy @ft_face + * then it is the client program's responsibility to destroy @ft_face * after the #hb_font_t font object has been destroyed. * - * HarfBuzz will use the @destroy callback on the #hb_font_t font object + * HarfBuzz will use the @destroy callback on the #hb_font_t font object * if it is supplied when you use this function. However, even if @destroy * is provided, it is the client program's responsibility to destroy @ft_face, * and it is the client program's responsibility to ensure that @ft_face is diff --git a/thirdparty/harfbuzz/src/hb-icu.cc b/thirdparty/harfbuzz/src/hb-icu.cc index e46401f7a6..3707ec30f8 100644 --- a/thirdparty/harfbuzz/src/hb-icu.cc +++ b/thirdparty/harfbuzz/src/hb-icu.cc @@ -93,15 +93,16 @@ hb_icu_script_to_script (UScriptCode script) UScriptCode hb_icu_script_from_script (hb_script_t script) { + UScriptCode out = USCRIPT_INVALID_CODE; + if (unlikely (script == HB_SCRIPT_INVALID)) - return USCRIPT_INVALID_CODE; + return out; - unsigned int numScriptCode = 1 + u_getIntPropertyMaxValue (UCHAR_SCRIPT); - for (unsigned int i = 0; i < numScriptCode; i++) - if (unlikely (hb_icu_script_to_script ((UScriptCode) i) == script)) - return (UScriptCode) i; + UErrorCode icu_err = U_ZERO_ERROR; + const unsigned char buf[5] = {HB_UNTAG (script), 0}; + uscript_getCode ((const char *) buf, &out, 1, &icu_err); - return USCRIPT_UNKNOWN; + return out; } diff --git a/thirdparty/harfbuzz/src/hb-limits.hh b/thirdparty/harfbuzz/src/hb-limits.hh index 25c1e71e13..7efc893eae 100644 --- a/thirdparty/harfbuzz/src/hb-limits.hh +++ b/thirdparty/harfbuzz/src/hb-limits.hh @@ -106,7 +106,7 @@ #endif #ifndef HB_COLRV1_MAX_EDGE_COUNT -#define HB_COLRV1_MAX_EDGE_COUNT 65536 +#define HB_COLRV1_MAX_EDGE_COUNT 2048 #endif diff --git a/thirdparty/harfbuzz/src/hb-map.hh b/thirdparty/harfbuzz/src/hb-map.hh index 45a02b830c..6521b1a41d 100644 --- a/thirdparty/harfbuzz/src/hb-map.hh +++ b/thirdparty/harfbuzz/src/hb-map.hh @@ -70,9 +70,9 @@ struct hb_hashmap_t alloc (o.population); hb_copy (o, *this); } - hb_hashmap_t (hb_hashmap_t&& o) : hb_hashmap_t () { hb_swap (*this, o); } + hb_hashmap_t (hb_hashmap_t&& o) noexcept : hb_hashmap_t () { hb_swap (*this, o); } hb_hashmap_t& operator= (const hb_hashmap_t& o) { reset (); alloc (o.population); hb_copy (o, *this); return *this; } - hb_hashmap_t& operator= (hb_hashmap_t&& o) { hb_swap (*this, o); return *this; } + hb_hashmap_t& operator= (hb_hashmap_t&& o) noexcept { hb_swap (*this, o); return *this; } hb_hashmap_t (std::initializer_list<hb_pair_t<K, V>> lst) : hb_hashmap_t () { @@ -137,26 +137,23 @@ struct hb_hashmap_t }; hb_object_header_t header; - unsigned int successful : 1; /* Allocations successful */ - unsigned int population : 31; /* Not including tombstones. */ + bool successful; /* Allocations successful */ + unsigned short max_chain_length; + unsigned int population; /* Not including tombstones. */ unsigned int occupancy; /* Including tombstones. */ unsigned int mask; unsigned int prime; - unsigned int max_chain_length; item_t *items; - friend void swap (hb_hashmap_t& a, hb_hashmap_t& b) + friend void swap (hb_hashmap_t& a, hb_hashmap_t& b) noexcept { if (unlikely (!a.successful || !b.successful)) return; - unsigned tmp = a.population; - a.population = b.population; - b.population = tmp; - //hb_swap (a.population, b.population); + hb_swap (a.max_chain_length, b.max_chain_length); + hb_swap (a.population, b.population); hb_swap (a.occupancy, b.occupancy); hb_swap (a.mask, b.mask); hb_swap (a.prime, b.prime); - hb_swap (a.max_chain_length, b.max_chain_length); hb_swap (a.items, b.items); } void init () @@ -164,10 +161,10 @@ struct hb_hashmap_t hb_object_init (this); successful = true; + max_chain_length = 0; population = occupancy = 0; mask = 0; prime = 0; - max_chain_length = 0; items = nullptr; } void fini () @@ -558,7 +555,7 @@ struct hb_map_t : hb_hashmap_t<hb_codepoint_t, ~hb_map_t () = default; hb_map_t () : hashmap () {} hb_map_t (const hb_map_t &o) : hashmap ((hashmap &) o) {} - hb_map_t (hb_map_t &&o) : hashmap (std::move ((hashmap &) o)) {} + hb_map_t (hb_map_t &&o) noexcept : hashmap (std::move ((hashmap &) o)) {} hb_map_t& operator= (const hb_map_t&) = default; hb_map_t& operator= (hb_map_t&&) = default; hb_map_t (std::initializer_list<hb_codepoint_pair_t> lst) : hashmap (lst) {} diff --git a/thirdparty/harfbuzz/src/hb-object.hh b/thirdparty/harfbuzz/src/hb-object.hh index e2c2c3394c..5cffe1666b 100644 --- a/thirdparty/harfbuzz/src/hb-object.hh +++ b/thirdparty/harfbuzz/src/hb-object.hh @@ -325,7 +325,7 @@ retry: hb_user_data_array_t *user_data = obj->header.user_data.get_acquire (); if (unlikely (!user_data)) { - user_data = (hb_user_data_array_t *) hb_calloc (sizeof (hb_user_data_array_t), 1); + user_data = (hb_user_data_array_t *) hb_calloc (1, sizeof (hb_user_data_array_t)); if (unlikely (!user_data)) return false; user_data->init (); diff --git a/thirdparty/harfbuzz/src/hb-open-type.hh b/thirdparty/harfbuzz/src/hb-open-type.hh index 6967bca3d4..9c11f14344 100644 --- a/thirdparty/harfbuzz/src/hb-open-type.hh +++ b/thirdparty/harfbuzz/src/hb-open-type.hh @@ -985,6 +985,13 @@ struct SortedArrayOf : ArrayOf<Type, LenType> return_trace (ret); } + SortedArrayOf* copy (hb_serialize_context_t *c) const + { + TRACE_SERIALIZE (this); + SortedArrayOf* out = reinterpret_cast<SortedArrayOf *> (ArrayOf<Type, LenType>::copy (c)); + return_trace (out); + } + template <typename T> Type &bsearch (const T &x, Type ¬_found = Crap (Type)) { return *as_array ().bsearch (x, ¬_found); } diff --git a/thirdparty/harfbuzz/src/hb-ot-cff-common.hh b/thirdparty/harfbuzz/src/hb-ot-cff-common.hh index 4fdba197ac..c7c3264c08 100644 --- a/thirdparty/harfbuzz/src/hb-ot-cff-common.hh +++ b/thirdparty/harfbuzz/src/hb-ot-cff-common.hh @@ -41,10 +41,21 @@ using namespace OT; using objidx_t = hb_serialize_context_t::objidx_t; using whence_t = hb_serialize_context_t::whence_t; -/* utility macro */ -template<typename Type> -static inline const Type& StructAtOffsetOrNull (const void *P, unsigned int offset) -{ return offset ? StructAtOffset<Type> (P, offset) : Null (Type); } +/* CFF offsets can technically be negative */ +template<typename Type, typename ...Ts> +static inline const Type& StructAtOffsetOrNull (const void *P, int offset, hb_sanitize_context_t &sc, Ts&&... ds) +{ + if (!offset) return Null (Type); + + const char *p = (const char *) P + offset; + if (!sc.check_point (p)) return Null (Type); + + const Type &obj = *reinterpret_cast<const Type *> (p); + if (!obj.sanitize (&sc, std::forward<Ts> (ds)...)) return Null (Type); + + return obj; +} + struct code_pair_t { diff --git a/thirdparty/harfbuzz/src/hb-ot-cff1-table.hh b/thirdparty/harfbuzz/src/hb-ot-cff1-table.hh index c869e90554..1bbd463841 100644 --- a/thirdparty/harfbuzz/src/hb-ot-cff1-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-cff1-table.hh @@ -763,9 +763,9 @@ struct cff1_top_dict_values_t : top_dict_values_t<cff1_top_dict_val_t> unsigned int ros_supplement; unsigned int cidCount; - unsigned int EncodingOffset; - unsigned int CharsetOffset; - unsigned int FDSelectOffset; + int EncodingOffset; + int CharsetOffset; + int FDSelectOffset; table_info_t privateDictInfo; }; @@ -821,24 +821,24 @@ struct cff1_top_dict_opset_t : top_dict_opset_t<cff1_top_dict_val_t> break; case OpCode_Encoding: - dictval.EncodingOffset = env.argStack.pop_uint (); + dictval.EncodingOffset = env.argStack.pop_int (); env.clear_args (); if (unlikely (dictval.EncodingOffset == 0)) return; break; case OpCode_charset: - dictval.CharsetOffset = env.argStack.pop_uint (); + dictval.CharsetOffset = env.argStack.pop_int (); env.clear_args (); if (unlikely (dictval.CharsetOffset == 0)) return; break; case OpCode_FDSelect: - dictval.FDSelectOffset = env.argStack.pop_uint (); + dictval.FDSelectOffset = env.argStack.pop_int (); env.clear_args (); break; case OpCode_Private: - dictval.privateDictInfo.offset = env.argStack.pop_uint (); + dictval.privateDictInfo.offset = env.argStack.pop_int (); dictval.privateDictInfo.size = env.argStack.pop_uint (); env.clear_args (); break; @@ -913,7 +913,7 @@ struct cff1_private_dict_values_base_t : dict_values_t<VAL> } void fini () { dict_values_t<VAL>::fini (); } - unsigned int subrsOffset; + int subrsOffset; const CFF1Subrs *localSubrs; }; @@ -948,7 +948,7 @@ struct cff1_private_dict_opset_t : dict_opset_t env.clear_args (); break; case OpCode_Subrs: - dictval.subrsOffset = env.argStack.pop_uint (); + dictval.subrsOffset = env.argStack.pop_int (); env.clear_args (); break; @@ -990,7 +990,7 @@ struct cff1_private_dict_opset_subset_t : dict_opset_t break; case OpCode_Subrs: - dictval.subrsOffset = env.argStack.pop_uint (); + dictval.subrsOffset = env.argStack.pop_int (); env.clear_args (); break; @@ -1090,8 +1090,8 @@ struct cff1 goto fail; hb_barrier (); - topDictIndex = &StructAtOffset<CFF1TopDictIndex> (nameIndex, nameIndex->get_size ()); - if ((topDictIndex == &Null (CFF1TopDictIndex)) || !topDictIndex->sanitize (&sc) || (topDictIndex->count == 0)) + topDictIndex = &StructAtOffsetOrNull<CFF1TopDictIndex> (nameIndex, nameIndex->get_size (), sc); + if (topDictIndex == &Null (CFF1TopDictIndex) || (topDictIndex->count == 0)) goto fail; hb_barrier (); @@ -1108,20 +1108,18 @@ struct cff1 charset = &Null (Charset); else { - charset = &StructAtOffsetOrNull<Charset> (cff, topDict.CharsetOffset); - if (unlikely ((charset == &Null (Charset)) || !charset->sanitize (&sc, &num_charset_entries))) goto fail; - hb_barrier (); + charset = &StructAtOffsetOrNull<Charset> (cff, topDict.CharsetOffset, sc, &num_charset_entries); + if (unlikely (charset == &Null (Charset))) goto fail; } fdCount = 1; if (is_CID ()) { - fdArray = &StructAtOffsetOrNull<CFF1FDArray> (cff, topDict.FDArrayOffset); - fdSelect = &StructAtOffsetOrNull<CFF1FDSelect> (cff, topDict.FDSelectOffset); - if (unlikely ((fdArray == &Null (CFF1FDArray)) || !fdArray->sanitize (&sc) || - (fdSelect == &Null (CFF1FDSelect)) || !fdSelect->sanitize (&sc, fdArray->count))) + fdArray = &StructAtOffsetOrNull<CFF1FDArray> (cff, topDict.FDArrayOffset, sc); + fdSelect = &StructAtOffsetOrNull<CFF1FDSelect> (cff, topDict.FDSelectOffset, sc, fdArray->count); + if (unlikely (fdArray == &Null (CFF1FDArray) || + fdSelect == &Null (CFF1FDSelect))) goto fail; - hb_barrier (); fdCount = fdArray->count; } @@ -1140,27 +1138,19 @@ struct cff1 { if (!is_predef_encoding ()) { - encoding = &StructAtOffsetOrNull<Encoding> (cff, topDict.EncodingOffset); - if (unlikely ((encoding == &Null (Encoding)) || !encoding->sanitize (&sc))) goto fail; - hb_barrier (); + encoding = &StructAtOffsetOrNull<Encoding> (cff, topDict.EncodingOffset, sc); + if (unlikely (encoding == &Null (Encoding))) goto fail; } } - stringIndex = &StructAtOffset<CFF1StringIndex> (topDictIndex, topDictIndex->get_size ()); - if ((stringIndex == &Null (CFF1StringIndex)) || !stringIndex->sanitize (&sc)) + stringIndex = &StructAtOffsetOrNull<CFF1StringIndex> (topDictIndex, topDictIndex->get_size (), sc); + if (stringIndex == &Null (CFF1StringIndex)) goto fail; - hb_barrier (); - globalSubrs = &StructAtOffset<CFF1Subrs> (stringIndex, stringIndex->get_size ()); - if ((globalSubrs != &Null (CFF1Subrs)) && !globalSubrs->sanitize (&sc)) + globalSubrs = &StructAtOffsetOrNull<CFF1Subrs> (stringIndex, stringIndex->get_size (), sc); + charStrings = &StructAtOffsetOrNull<CFF1CharStrings> (cff, topDict.charStringsOffset, sc); + if (charStrings == &Null (CFF1CharStrings)) goto fail; - hb_barrier (); - - charStrings = &StructAtOffsetOrNull<CFF1CharStrings> (cff, topDict.charStringsOffset); - - if ((charStrings == &Null (CFF1CharStrings)) || unlikely (!charStrings->sanitize (&sc))) - goto fail; - hb_barrier (); num_glyphs = charStrings->count; if (num_glyphs != sc.get_num_glyphs ()) @@ -1188,19 +1178,13 @@ struct cff1 font->init (); if (unlikely (!font_interp.interpret (*font))) goto fail; PRIVDICTVAL *priv = &privateDicts[i]; - const hb_ubytes_t privDictStr = StructAtOffset<UnsizedByteStr> (cff, font->privateDictInfo.offset).as_ubytes (font->privateDictInfo.size); - if (unlikely (!privDictStr.sanitize (&sc))) goto fail; - hb_barrier (); + const hb_ubytes_t privDictStr = StructAtOffsetOrNull<UnsizedByteStr> (cff, font->privateDictInfo.offset, sc, font->privateDictInfo.size).as_ubytes (font->privateDictInfo.size); num_interp_env_t env2 (privDictStr); dict_interpreter_t<PRIVOPSET, PRIVDICTVAL> priv_interp (env2); priv->init (); if (unlikely (!priv_interp.interpret (*priv))) goto fail; - priv->localSubrs = &StructAtOffsetOrNull<CFF1Subrs> (&privDictStr, priv->subrsOffset); - if (priv->localSubrs != &Null (CFF1Subrs) && - unlikely (!priv->localSubrs->sanitize (&sc))) - goto fail; - hb_barrier (); + priv->localSubrs = &StructAtOffsetOrNull<CFF1Subrs> (&privDictStr, priv->subrsOffset, sc); } } else /* non-CID */ @@ -1208,18 +1192,13 @@ struct cff1 cff1_top_dict_values_t *font = &topDict; PRIVDICTVAL *priv = &privateDicts[0]; - const hb_ubytes_t privDictStr = StructAtOffset<UnsizedByteStr> (cff, font->privateDictInfo.offset).as_ubytes (font->privateDictInfo.size); - if (unlikely (!privDictStr.sanitize (&sc))) goto fail; - hb_barrier (); + const hb_ubytes_t privDictStr = StructAtOffsetOrNull<UnsizedByteStr> (cff, font->privateDictInfo.offset, sc, font->privateDictInfo.size).as_ubytes (font->privateDictInfo.size); num_interp_env_t env (privDictStr); dict_interpreter_t<PRIVOPSET, PRIVDICTVAL> priv_interp (env); priv->init (); if (unlikely (!priv_interp.interpret (*priv))) goto fail; - priv->localSubrs = &StructAtOffsetOrNull<CFF1Subrs> (&privDictStr, priv->subrsOffset); - if (priv->localSubrs != &Null (CFF1Subrs) && - unlikely (!priv->localSubrs->sanitize (&sc))) - goto fail; + priv->localSubrs = &StructAtOffsetOrNull<CFF1Subrs> (&privDictStr, priv->subrsOffset, sc); hb_barrier (); } @@ -1437,7 +1416,7 @@ struct cff1 hb_sorted_vector_t<gname_t> *names = glyph_names.get_acquire (); if (unlikely (!names)) { - names = (hb_sorted_vector_t<gname_t> *) hb_calloc (sizeof (hb_sorted_vector_t<gname_t>), 1); + names = (hb_sorted_vector_t<gname_t> *) hb_calloc (1, sizeof (hb_sorted_vector_t<gname_t>)); if (likely (names)) { names->init (); diff --git a/thirdparty/harfbuzz/src/hb-ot-cff2-table.hh b/thirdparty/harfbuzz/src/hb-ot-cff2-table.hh index 652748b737..4b3bdc9315 100644 --- a/thirdparty/harfbuzz/src/hb-ot-cff2-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-cff2-table.hh @@ -111,7 +111,7 @@ struct CFF2FDSelect DEFINE_SIZE_MIN (2); }; -struct CFF2VariationStore +struct CFF2ItemVariationStore { bool sanitize (hb_sanitize_context_t *c) const { @@ -122,11 +122,11 @@ struct CFF2VariationStore varStore.sanitize (c)); } - bool serialize (hb_serialize_context_t *c, const CFF2VariationStore *varStore) + bool serialize (hb_serialize_context_t *c, const CFF2ItemVariationStore *varStore) { TRACE_SERIALIZE (this); unsigned int size_ = varStore->get_size (); - CFF2VariationStore *dest = c->allocate_size<CFF2VariationStore> (size_); + CFF2ItemVariationStore *dest = c->allocate_size<CFF2ItemVariationStore> (size_); if (unlikely (!dest)) return_trace (false); hb_memcpy (dest, varStore, size_); return_trace (true); @@ -135,9 +135,9 @@ struct CFF2VariationStore unsigned int get_size () const { return HBUINT16::static_size + size; } HBUINT16 size; - VariationStore varStore; + ItemVariationStore varStore; - DEFINE_SIZE_MIN (2 + VariationStore::min_size); + DEFINE_SIZE_MIN (2 + ItemVariationStore::min_size); }; struct cff2_top_dict_values_t : top_dict_values_t<> @@ -150,8 +150,8 @@ struct cff2_top_dict_values_t : top_dict_values_t<> } void fini () { top_dict_values_t<>::fini (); } - unsigned int vstoreOffset; - unsigned int FDSelectOffset; + int vstoreOffset; + int FDSelectOffset; }; struct cff2_top_dict_opset_t : top_dict_opset_t<> @@ -169,11 +169,11 @@ struct cff2_top_dict_opset_t : top_dict_opset_t<> break; case OpCode_vstore: - dictval.vstoreOffset = env.argStack.pop_uint (); + dictval.vstoreOffset = env.argStack.pop_int (); env.clear_args (); break; case OpCode_FDSelect: - dictval.FDSelectOffset = env.argStack.pop_uint (); + dictval.FDSelectOffset = env.argStack.pop_int (); env.clear_args (); break; @@ -241,7 +241,7 @@ struct cff2_private_dict_values_base_t : dict_values_t<VAL> } void fini () { dict_values_t<VAL>::fini (); } - unsigned int subrsOffset; + int subrsOffset; const CFF2Subrs *localSubrs; unsigned int ivs; }; @@ -295,7 +295,7 @@ struct cff2_private_dict_opset_t : dict_opset_t env.clear_args (); break; case OpCode_Subrs: - dictval.subrsOffset = env.argStack.pop_uint (); + dictval.subrsOffset = env.argStack.pop_int (); env.clear_args (); break; case OpCode_vsindexdict: @@ -344,7 +344,7 @@ struct cff2_private_dict_opset_subset_t : dict_opset_t return; case OpCode_Subrs: - dictval.subrsOffset = env.argStack.pop_uint (); + dictval.subrsOffset = env.argStack.pop_int (); env.clear_args (); break; @@ -426,18 +426,15 @@ struct cff2 if (unlikely (!top_interp.interpret (topDict))) goto fail; } - globalSubrs = &StructAtOffset<CFF2Subrs> (cff2, cff2->topDict + cff2->topDictSize); - varStore = &StructAtOffsetOrNull<CFF2VariationStore> (cff2, topDict.vstoreOffset); - charStrings = &StructAtOffsetOrNull<CFF2CharStrings> (cff2, topDict.charStringsOffset); - fdArray = &StructAtOffsetOrNull<CFF2FDArray> (cff2, topDict.FDArrayOffset); - fdSelect = &StructAtOffsetOrNull<CFF2FDSelect> (cff2, topDict.FDSelectOffset); - - if (((varStore != &Null (CFF2VariationStore)) && unlikely (!varStore->sanitize (&sc))) || - (charStrings == &Null (CFF2CharStrings)) || unlikely (!charStrings->sanitize (&sc)) || - (globalSubrs == &Null (CFF2Subrs)) || unlikely (!globalSubrs->sanitize (&sc)) || - (fdArray == &Null (CFF2FDArray)) || unlikely (!fdArray->sanitize (&sc)) || - !hb_barrier () || - (((fdSelect != &Null (CFF2FDSelect)) && unlikely (!fdSelect->sanitize (&sc, fdArray->count))))) + globalSubrs = &StructAtOffsetOrNull<CFF2Subrs> (cff2, cff2->topDict + cff2->topDictSize, sc); + varStore = &StructAtOffsetOrNull<CFF2ItemVariationStore> (cff2, topDict.vstoreOffset, sc); + charStrings = &StructAtOffsetOrNull<CFF2CharStrings> (cff2, topDict.charStringsOffset, sc); + fdArray = &StructAtOffsetOrNull<CFF2FDArray> (cff2, topDict.FDArrayOffset, sc); + fdSelect = &StructAtOffsetOrNull<CFF2FDSelect> (cff2, topDict.FDSelectOffset, sc, fdArray->count); + + if (charStrings == &Null (CFF2CharStrings) || + globalSubrs == &Null (CFF2Subrs) || + fdArray == &Null (CFF2FDArray)) goto fail; num_glyphs = charStrings->count; @@ -462,19 +459,13 @@ struct cff2 font->init (); if (unlikely (!font_interp.interpret (*font))) goto fail; - const hb_ubytes_t privDictStr = StructAtOffsetOrNull<UnsizedByteStr> (cff2, font->privateDictInfo.offset).as_ubytes (font->privateDictInfo.size); - if (unlikely (!privDictStr.sanitize (&sc))) goto fail; - hb_barrier (); + const hb_ubytes_t privDictStr = StructAtOffsetOrNull<UnsizedByteStr> (cff2, font->privateDictInfo.offset, sc, font->privateDictInfo.size).as_ubytes (font->privateDictInfo.size); cff2_priv_dict_interp_env_t env2 (privDictStr); dict_interpreter_t<PRIVOPSET, PRIVDICTVAL, cff2_priv_dict_interp_env_t> priv_interp (env2); privateDicts[i].init (); if (unlikely (!priv_interp.interpret (privateDicts[i]))) goto fail; - privateDicts[i].localSubrs = &StructAtOffsetOrNull<CFF2Subrs> (&privDictStr[0], privateDicts[i].subrsOffset); - if (privateDicts[i].localSubrs != &Null (CFF2Subrs) && - unlikely (!privateDicts[i].localSubrs->sanitize (&sc))) - goto fail; - hb_barrier (); + privateDicts[i].localSubrs = &StructAtOffsetOrNull<CFF2Subrs> (&privDictStr[0], privateDicts[i].subrsOffset, sc); } return; @@ -509,7 +500,7 @@ struct cff2 hb_blob_t *blob = nullptr; cff2_top_dict_values_t topDict; const CFF2Subrs *globalSubrs = nullptr; - const CFF2VariationStore *varStore = nullptr; + const CFF2ItemVariationStore *varStore = nullptr; const CFF2CharStrings *charStrings = nullptr; const CFF2FDArray *fdArray = nullptr; const CFF2FDSelect *fdSelect = nullptr; diff --git a/thirdparty/harfbuzz/src/hb-ot-cmap-table.hh b/thirdparty/harfbuzz/src/hb-ot-cmap-table.hh index e2e2581855..64d2b13880 100644 --- a/thirdparty/harfbuzz/src/hb-ot-cmap-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-cmap-table.hh @@ -41,6 +41,30 @@ namespace OT { +static inline uint8_t unicode_to_macroman (hb_codepoint_t u) +{ + uint16_t mapping[] = { + 0x00C4, 0x00C5, 0x00C7, 0x00C9, 0x00D1, 0x00D6, 0x00DC, 0x00E1, + 0x00E0, 0x00E2, 0x00E4, 0x00E3, 0x00E5, 0x00E7, 0x00E9, 0x00E8, + 0x00EA, 0x00EB, 0x00ED, 0x00EC, 0x00EE, 0x00EF, 0x00F1, 0x00F3, + 0x00F2, 0x00F4, 0x00F6, 0x00F5, 0x00FA, 0x00F9, 0x00FB, 0x00FC, + 0x2020, 0x00B0, 0x00A2, 0x00A3, 0x00A7, 0x2022, 0x00B6, 0x00DF, + 0x00AE, 0x00A9, 0x2122, 0x00B4, 0x00A8, 0x2260, 0x00C6, 0x00D8, + 0x221E, 0x00B1, 0x2264, 0x2265, 0x00A5, 0x00B5, 0x2202, 0x2211, + 0x220F, 0x03C0, 0x222B, 0x00AA, 0x00BA, 0x03A9, 0x00E6, 0x00F8, + 0x00BF, 0x00A1, 0x00AC, 0x221A, 0x0192, 0x2248, 0x2206, 0x00AB, + 0x00BB, 0x2026, 0x00A0, 0x00C0, 0x00C3, 0x00D5, 0x0152, 0x0153, + 0x2013, 0x2014, 0x201C, 0x201D, 0x2018, 0x2019, 0x00F7, 0x25CA, + 0x00FF, 0x0178, 0x2044, 0x20AC, 0x2039, 0x203A, 0xFB01, 0xFB02, + 0x2021, 0x00B7, 0x201A, 0x201E, 0x2030, 0x00C2, 0x00CA, 0x00C1, + 0x00CB, 0x00C8, 0x00CD, 0x00CE, 0x00CF, 0x00CC, 0x00D3, 0x00D4, + 0xF8FF, 0x00D2, 0x00DA, 0x00DB, 0x00D9, 0x0131, 0x02C6, 0x02DC, + 0x00AF, 0x02D8, 0x02D9, 0x02DA, 0x00B8, 0x02DD, 0x02DB, 0x02C7 + }; + uint16_t *c = hb_bsearch (u, mapping, ARRAY_LENGTH (mapping), sizeof (mapping[0]), + _hb_cmp_operator<uint16_t, uint16_t>); + return c ? (c - mapping) + 0x7F : 0; +} struct CmapSubtableFormat0 { @@ -1465,8 +1489,11 @@ struct EncodingRecord int ret; ret = platformID.cmp (other.platformID); if (ret) return ret; - ret = encodingID.cmp (other.encodingID); - if (ret) return ret; + if (other.encodingID != 0xFFFF) + { + ret = encodingID.cmp (other.encodingID); + if (ret) return ret; + } return 0; } @@ -1814,9 +1841,13 @@ struct cmap c->plan)); } - const CmapSubtable *find_best_subtable (bool *symbol = nullptr) const + const CmapSubtable *find_best_subtable (bool *symbol = nullptr, + bool *mac = nullptr, + bool *macroman = nullptr) const { if (symbol) *symbol = false; + if (mac) *mac = false; + if (macroman) *macroman = false; const CmapSubtable *subtable; @@ -1841,6 +1872,20 @@ struct cmap if ((subtable = this->find_subtable (0, 1))) return subtable; if ((subtable = this->find_subtable (0, 0))) return subtable; + /* MacRoman subtable. */ + if ((subtable = this->find_subtable (1, 0))) + { + if (mac) *mac = true; + if (macroman) *macroman = true; + return subtable; + } + /* Any other Mac subtable; we just map ASCII for these. */ + if ((subtable = this->find_subtable (1, 0xFFFF))) + { + if (mac) *mac = true; + return subtable; + } + /* Meh. */ return &Null (CmapSubtable); } @@ -1852,8 +1897,8 @@ struct cmap accelerator_t (hb_face_t *face) { this->table = hb_sanitize_context_t ().reference_table<cmap> (face); - bool symbol; - this->subtable = table->find_best_subtable (&symbol); + bool symbol, mac, macroman; + this->subtable = table->find_best_subtable (&symbol, &mac, ¯oman); this->subtable_uvs = &Null (CmapSubtableFormat14); { const CmapSubtable *st = table->find_subtable (0, 5); @@ -1862,6 +1907,7 @@ struct cmap } this->get_glyph_data = subtable; +#ifndef HB_NO_CMAP_LEGACY_SUBTABLES if (unlikely (symbol)) { switch ((unsigned) face->table.OS2->get_font_page ()) { @@ -1881,7 +1927,16 @@ struct cmap break; } } + else if (unlikely (macroman)) + { + this->get_glyph_funcZ = get_glyph_from_macroman<CmapSubtable>; + } + else if (unlikely (mac)) + { + this->get_glyph_funcZ = get_glyph_from_ascii<CmapSubtable>; + } else +#endif { switch (subtable->u.format) { /* Accelerate format 4 and format 12. */ @@ -1924,7 +1979,7 @@ struct cmap hb_codepoint_t *glyph, cache_t *cache = nullptr) const { - if (unlikely (!this->get_glyph_funcZ)) return 0; + if (unlikely (!this->get_glyph_funcZ)) return false; return _cached_get (unicode, glyph, cache); } @@ -2006,6 +2061,28 @@ struct cmap return false; } + template <typename Type> + HB_INTERNAL static bool get_glyph_from_ascii (const void *obj, + hb_codepoint_t codepoint, + hb_codepoint_t *glyph) + { + const Type *typed_obj = (const Type *) obj; + return codepoint < 0x80 && typed_obj->get_glyph (codepoint, glyph); + } + + template <typename Type> + HB_INTERNAL static bool get_glyph_from_macroman (const void *obj, + hb_codepoint_t codepoint, + hb_codepoint_t *glyph) + { + if (get_glyph_from_ascii<Type> (obj, codepoint, glyph)) + return true; + + const Type *typed_obj = (const Type *) obj; + unsigned c = unicode_to_macroman (codepoint); + return c && typed_obj->get_glyph (c, glyph); + } + private: hb_nonnull_ptr_t<const CmapSubtable> subtable; hb_nonnull_ptr_t<const CmapSubtableFormat14> subtable_uvs; @@ -2035,28 +2112,6 @@ struct cmap return &(this+result.subtable); } - const EncodingRecord *find_encodingrec (unsigned int platform_id, - unsigned int encoding_id) const - { - EncodingRecord key; - key.platformID = platform_id; - key.encodingID = encoding_id; - - return encodingRecord.as_array ().bsearch (key); - } - - bool find_subtable (unsigned format) const - { - auto it = - + hb_iter (encodingRecord) - | hb_map (&EncodingRecord::subtable) - | hb_map (hb_add (this)) - | hb_filter ([&] (const CmapSubtable& _) { return _.u.format == format; }) - ; - - return it.len (); - } - public: bool sanitize (hb_sanitize_context_t *c) const diff --git a/thirdparty/harfbuzz/src/hb-ot-font.cc b/thirdparty/harfbuzz/src/hb-ot-font.cc index b3677c6a4c..1da869d697 100644 --- a/thirdparty/harfbuzz/src/hb-ot-font.cc +++ b/thirdparty/harfbuzz/src/hb-ot-font.cc @@ -208,12 +208,12 @@ hb_ot_get_glyph_h_advances (hb_font_t* font, void* font_data, #if !defined(HB_NO_VAR) && !defined(HB_NO_OT_FONT_ADVANCE_CACHE) const OT::HVAR &HVAR = *hmtx.var_table; - const OT::VariationStore &varStore = &HVAR + HVAR.varStore; - OT::VariationStore::cache_t *varStore_cache = font->num_coords * count >= 128 ? varStore.create_cache () : nullptr; + const OT::ItemVariationStore &varStore = &HVAR + HVAR.varStore; + OT::ItemVariationStore::cache_t *varStore_cache = font->num_coords * count >= 128 ? varStore.create_cache () : nullptr; bool use_cache = font->num_coords; #else - OT::VariationStore::cache_t *varStore_cache = nullptr; + OT::ItemVariationStore::cache_t *varStore_cache = nullptr; bool use_cache = false; #endif @@ -277,7 +277,7 @@ hb_ot_get_glyph_h_advances (hb_font_t* font, void* font_data, } #if !defined(HB_NO_VAR) && !defined(HB_NO_OT_FONT_ADVANCE_CACHE) - OT::VariationStore::destroy_cache (varStore_cache); + OT::ItemVariationStore::destroy_cache (varStore_cache); #endif if (font->x_strength && !font->embolden_in_place) @@ -313,10 +313,10 @@ hb_ot_get_glyph_v_advances (hb_font_t* font, void* font_data, { #if !defined(HB_NO_VAR) && !defined(HB_NO_OT_FONT_ADVANCE_CACHE) const OT::VVAR &VVAR = *vmtx.var_table; - const OT::VariationStore &varStore = &VVAR + VVAR.varStore; - OT::VariationStore::cache_t *varStore_cache = font->num_coords ? varStore.create_cache () : nullptr; + const OT::ItemVariationStore &varStore = &VVAR + VVAR.varStore; + OT::ItemVariationStore::cache_t *varStore_cache = font->num_coords ? varStore.create_cache () : nullptr; #else - OT::VariationStore::cache_t *varStore_cache = nullptr; + OT::ItemVariationStore::cache_t *varStore_cache = nullptr; #endif for (unsigned int i = 0; i < count; i++) @@ -327,7 +327,7 @@ hb_ot_get_glyph_v_advances (hb_font_t* font, void* font_data, } #if !defined(HB_NO_VAR) && !defined(HB_NO_OT_FONT_ADVANCE_CACHE) - OT::VariationStore::destroy_cache (varStore_cache); + OT::ItemVariationStore::destroy_cache (varStore_cache); #endif } else diff --git a/thirdparty/harfbuzz/src/hb-ot-hmtx-table.hh b/thirdparty/harfbuzz/src/hb-ot-hmtx-table.hh index 89640b43f1..48bd536121 100644 --- a/thirdparty/harfbuzz/src/hb-ot-hmtx-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-hmtx-table.hh @@ -145,6 +145,29 @@ struct hmtxvmtx table->minTrailingBearing = min_rsb; table->maxExtent = max_extent; } + + if (T::is_horizontal) + { + const auto &OS2 = *c->plan->source->table.OS2; + if (OS2.has_data () && + table->ascender == OS2.sTypoAscender && + table->descender == OS2.sTypoDescender && + table->lineGap == OS2.sTypoLineGap) + { + table->ascender = static_cast<int> (roundf (OS2.sTypoAscender + + MVAR.get_var (HB_OT_METRICS_TAG_HORIZONTAL_ASCENDER, + c->plan->normalized_coords.arrayZ, + c->plan->normalized_coords.length))); + table->descender = static_cast<int> (roundf (OS2.sTypoDescender + + MVAR.get_var (HB_OT_METRICS_TAG_HORIZONTAL_DESCENDER, + c->plan->normalized_coords.arrayZ, + c->plan->normalized_coords.length))); + table->lineGap = static_cast<int> (roundf (OS2.sTypoLineGap + + MVAR.get_var (HB_OT_METRICS_TAG_HORIZONTAL_LINE_GAP, + c->plan->normalized_coords.arrayZ, + c->plan->normalized_coords.length))); + } + } } #endif @@ -374,7 +397,7 @@ struct hmtxvmtx unsigned get_advance_with_var_unscaled (hb_codepoint_t glyph, hb_font_t *font, - VariationStore::cache_t *store_cache = nullptr) const + ItemVariationStore::cache_t *store_cache = nullptr) const { unsigned int advance = get_advance_without_var_unscaled (glyph); diff --git a/thirdparty/harfbuzz/src/hb-ot-layout-base-table.hh b/thirdparty/harfbuzz/src/hb-ot-layout-base-table.hh index a23b6377d1..0278399069 100644 --- a/thirdparty/harfbuzz/src/hb-ot-layout-base-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-layout-base-table.hh @@ -46,6 +46,12 @@ struct BaseCoordFormat1 return HB_DIRECTION_IS_HORIZONTAL (direction) ? font->em_scale_y (coordinate) : font->em_scale_x (coordinate); } + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + return_trace ((bool) c->serializer->embed (*this)); + } + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); @@ -67,6 +73,17 @@ struct BaseCoordFormat2 return HB_DIRECTION_IS_HORIZONTAL (direction) ? font->em_scale_y (coordinate) : font->em_scale_x (coordinate); } + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + auto *out = c->serializer->embed (*this); + if (unlikely (!out)) return_trace (false); + + return_trace (c->serializer->check_assign (out->referenceGlyph, + c->plan->glyph_map->get (referenceGlyph), + HB_SERIALIZE_ERROR_INT_OVERFLOW)); + } + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); @@ -86,7 +103,7 @@ struct BaseCoordFormat2 struct BaseCoordFormat3 { hb_position_t get_coord (hb_font_t *font, - const VariationStore &var_store, + const ItemVariationStore &var_store, hb_direction_t direction) const { const Device &device = this+deviceTable; @@ -96,6 +113,23 @@ struct BaseCoordFormat3 : font->em_scale_x (coordinate) + device.get_x_delta (font, var_store); } + void collect_variation_indices (hb_set_t& varidx_set /* OUT */) const + { + unsigned varidx = (this+deviceTable).get_variation_index (); + varidx_set.add (varidx); + } + + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + auto *out = c->serializer->embed (*this); + if (unlikely (!out)) return_trace (false); + + return_trace (out->deviceTable.serialize_copy (c->serializer, deviceTable, + this, 0, + hb_serialize_context_t::Head, + &c->plan->base_variation_idx_map)); + } bool sanitize (hb_sanitize_context_t *c) const { @@ -120,7 +154,7 @@ struct BaseCoord bool has_data () const { return u.format; } hb_position_t get_coord (hb_font_t *font, - const VariationStore &var_store, + const ItemVariationStore &var_store, hb_direction_t direction) const { switch (u.format) { @@ -131,6 +165,27 @@ struct BaseCoord } } + void collect_variation_indices (hb_set_t& varidx_set /* OUT */) const + { + switch (u.format) { + case 3: u.format3.collect_variation_indices (varidx_set); + default:return; + } + } + + template <typename context_t, typename ...Ts> + typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const + { + if (unlikely (!c->may_dispatch (this, &u.format))) return c->no_dispatch_return_value (); + TRACE_DISPATCH (this, u.format); + switch (u.format) { + case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...)); + case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...)); + case 3: return_trace (c->dispatch (u.format3, std::forward<Ts> (ds)...)); + default:return_trace (c->default_return_value ()); + } + } + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); @@ -161,12 +216,37 @@ struct FeatMinMaxRecord bool has_data () const { return tag; } + hb_tag_t get_feature_tag () const { return tag; } + void get_min_max (const BaseCoord **min, const BaseCoord **max) const { if (likely (min)) *min = &(this+minCoord); if (likely (max)) *max = &(this+maxCoord); } + void collect_variation_indices (const hb_subset_plan_t* plan, + const void *base, + hb_set_t& varidx_set /* OUT */) const + { + if (!plan->layout_features.has (tag)) + return; + + (base+minCoord).collect_variation_indices (varidx_set); + (base+maxCoord).collect_variation_indices (varidx_set); + } + + bool subset (hb_subset_context_t *c, + const void *base) const + { + TRACE_SUBSET (this); + auto *out = c->serializer->embed (*this); + if (unlikely (!out)) return_trace (false); + if (!(out->minCoord.serialize_subset (c, minCoord, base))) + return_trace (false); + + return_trace (out->maxCoord.serialize_subset (c, maxCoord, base)); + } + bool sanitize (hb_sanitize_context_t *c, const void *base) const { TRACE_SANITIZE (this); @@ -206,6 +286,39 @@ struct MinMax } } + void collect_variation_indices (const hb_subset_plan_t* plan, + hb_set_t& varidx_set /* OUT */) const + { + (this+minCoord).collect_variation_indices (varidx_set); + (this+maxCoord).collect_variation_indices (varidx_set); + for (const FeatMinMaxRecord& record : featMinMaxRecords) + record.collect_variation_indices (plan, this, varidx_set); + } + + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + auto *out = c->serializer->start_embed (*this); + if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false); + + if (!(out->minCoord.serialize_subset (c, minCoord, this)) || + !(out->maxCoord.serialize_subset (c, maxCoord, this))) + return_trace (false); + + unsigned len = 0; + for (const FeatMinMaxRecord& _ : featMinMaxRecords) + { + hb_tag_t feature_tag = _.get_feature_tag (); + if (!c->plan->layout_features.has (feature_tag)) + continue; + + if (!_.subset (c, this)) return false; + len++; + } + return_trace (c->serializer->check_assign (out->featMinMaxRecords.len, len, + HB_SERIALIZE_ERROR_INT_OVERFLOW)); + } + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); @@ -240,6 +353,26 @@ struct BaseValues return this+baseCoords[baseline_tag_index]; } + void collect_variation_indices (hb_set_t& varidx_set /* OUT */) const + { + for (const auto& _ : baseCoords) + (this+_).collect_variation_indices (varidx_set); + } + + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + auto *out = c->serializer->start_embed (*this); + if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false); + out->defaultIndex = defaultIndex; + + for (const auto& _ : baseCoords) + if (!subset_offset_array (c, out->baseCoords, this) (_)) + return_trace (false); + + return_trace (bool (out->baseCoords)); + } + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); @@ -270,6 +403,20 @@ struct BaseLangSysRecord const MinMax &get_min_max () const { return this+minMax; } + void collect_variation_indices (const hb_subset_plan_t* plan, + hb_set_t& varidx_set /* OUT */) const + { (this+minMax).collect_variation_indices (plan, varidx_set); } + + bool subset (hb_subset_context_t *c, + const void *base) const + { + TRACE_SUBSET (this); + auto *out = c->serializer->embed (*this); + if (unlikely (!out)) return_trace (false); + + return_trace (out->minMax.serialize_subset (c, minMax, base)); + } + bool sanitize (hb_sanitize_context_t *c, const void *base) const { TRACE_SANITIZE (this); @@ -300,6 +447,35 @@ struct BaseScript bool has_values () const { return baseValues; } bool has_min_max () const { return defaultMinMax; /* TODO What if only per-language is present? */ } + void collect_variation_indices (const hb_subset_plan_t* plan, + hb_set_t& varidx_set /* OUT */) const + { + (this+baseValues).collect_variation_indices (varidx_set); + (this+defaultMinMax).collect_variation_indices (plan, varidx_set); + + for (const BaseLangSysRecord& _ : baseLangSysRecords) + _.collect_variation_indices (plan, varidx_set); + } + + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + auto *out = c->serializer->start_embed (*this); + if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false); + + if (baseValues && !out->baseValues.serialize_subset (c, baseValues, this)) + return_trace (false); + + if (defaultMinMax && !out->defaultMinMax.serialize_subset (c, defaultMinMax, this)) + return_trace (false); + + for (const auto& _ : baseLangSysRecords) + if (!_.subset (c, this)) return_trace (false); + + return_trace (c->serializer->check_assign (out->baseLangSysRecords.len, baseLangSysRecords.len, + HB_SERIALIZE_ERROR_INT_OVERFLOW)); + } + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); @@ -332,9 +508,31 @@ struct BaseScriptRecord bool has_data () const { return baseScriptTag; } + hb_tag_t get_script_tag () const { return baseScriptTag; } + const BaseScript &get_base_script (const BaseScriptList *list) const { return list+baseScript; } + void collect_variation_indices (const hb_subset_plan_t* plan, + const void* list, + hb_set_t& varidx_set /* OUT */) const + { + if (!plan->layout_scripts.has (baseScriptTag)) + return; + + (list+baseScript).collect_variation_indices (plan, varidx_set); + } + + bool subset (hb_subset_context_t *c, + const void *base) const + { + TRACE_SUBSET (this); + auto *out = c->serializer->embed (*this); + if (unlikely (!out)) return_trace (false); + + return_trace (out->baseScript.serialize_subset (c, baseScript, base)); + } + bool sanitize (hb_sanitize_context_t *c, const void *base) const { TRACE_SANITIZE (this); @@ -361,6 +559,33 @@ struct BaseScriptList return record->has_data () ? record->get_base_script (this) : Null (BaseScript); } + void collect_variation_indices (const hb_subset_plan_t* plan, + hb_set_t& varidx_set /* OUT */) const + { + for (const BaseScriptRecord& _ : baseScriptRecords) + _.collect_variation_indices (plan, this, varidx_set); + } + + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + auto *out = c->serializer->start_embed (*this); + if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false); + + unsigned len = 0; + for (const BaseScriptRecord& _ : baseScriptRecords) + { + hb_tag_t script_tag = _.get_script_tag (); + if (!c->plan->layout_scripts.has (script_tag)) + continue; + + if (!_.subset (c, this)) return false; + len++; + } + return_trace (c->serializer->check_assign (out->baseScriptRecords.len, len, + HB_SERIALIZE_ERROR_INT_OVERFLOW)); + } + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); @@ -422,6 +647,20 @@ struct Axis return true; } + void collect_variation_indices (const hb_subset_plan_t* plan, + hb_set_t& varidx_set /* OUT */) const + { (this+baseScriptList).collect_variation_indices (plan, varidx_set); } + + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + auto *out = c->serializer->embed (*this); + if (unlikely (!out)) return_trace (false); + + out->baseTagList.serialize_copy (c->serializer, baseTagList, this); + return_trace (out->baseScriptList.serialize_subset (c, baseScriptList, this)); + } + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); @@ -453,8 +692,41 @@ struct BASE const Axis &get_axis (hb_direction_t direction) const { return HB_DIRECTION_IS_VERTICAL (direction) ? this+vAxis : this+hAxis; } - const VariationStore &get_var_store () const - { return version.to_int () < 0x00010001u ? Null (VariationStore) : this+varStore; } + bool has_var_store () const + { return version.to_int () >= 0x00010001u && varStore != 0; } + + const ItemVariationStore &get_var_store () const + { return version.to_int () < 0x00010001u ? Null (ItemVariationStore) : this+varStore; } + + void collect_variation_indices (const hb_subset_plan_t* plan, + hb_set_t& varidx_set /* OUT */) const + { + (this+hAxis).collect_variation_indices (plan, varidx_set); + (this+vAxis).collect_variation_indices (plan, varidx_set); + } + + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + auto *out = c->serializer->start_embed (*this); + if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false); + + out->version = version; + if (hAxis && !out->hAxis.serialize_subset (c, hAxis, this)) + return_trace (false); + + if (vAxis && !out->vAxis.serialize_subset (c, vAxis, this)) + return_trace (false); + + if (has_var_store ()) + { + if (!c->serializer->allocate_size<Offset32To<ItemVariationStore>> (Offset32To<ItemVariationStore>::static_size)) + return_trace (false); + return_trace (out->varStore.serialize_subset (c, varStore, this, c->plan->base_varstore_inner_maps.as_array ())); + } + + return_trace (true); + } bool get_baseline (hb_font_t *font, hb_tag_t baseline_tag, @@ -487,7 +759,7 @@ struct BASE &min_coord, &max_coord)) return false; - const VariationStore &var_store = get_var_store (); + const ItemVariationStore &var_store = get_var_store (); if (likely (min && min_coord)) *min = min_coord->get_coord (font, var_store, direction); if (likely (max && max_coord)) *max = max_coord->get_coord (font, var_store, direction); return true; @@ -510,7 +782,7 @@ struct BASE * of BASE table (may be NULL) */ Offset16To<Axis>vAxis; /* Offset to vertical Axis table, from beginning * of BASE table (may be NULL) */ - Offset32To<VariationStore> + Offset32To<ItemVariationStore> varStore; /* Offset to the table of Item Variation * Store--from beginning of BASE * header (may be NULL). Introduced diff --git a/thirdparty/harfbuzz/src/hb-ot-layout-common.hh b/thirdparty/harfbuzz/src/hb-ot-layout-common.hh index 6b359cceb7..aba427368c 100644 --- a/thirdparty/harfbuzz/src/hb-ot-layout-common.hh +++ b/thirdparty/harfbuzz/src/hb-ot-layout-common.hh @@ -188,7 +188,7 @@ struct hb_subset_layout_context_t : unsigned lookup_index_count; }; -struct VariationStore; +struct ItemVariationStore; struct hb_collect_variation_indices_context_t : hb_dispatch_context_t<hb_collect_variation_indices_context_t> { @@ -3036,7 +3036,7 @@ struct VarData DEFINE_SIZE_ARRAY (6, regionIndices); }; -struct VariationStore +struct ItemVariationStore { friend struct item_variations_t; using cache_t = VarRegionList::cache_t; @@ -3141,7 +3141,7 @@ struct VariationStore } bool serialize (hb_serialize_context_t *c, - const VariationStore *src, + const ItemVariationStore *src, const hb_array_t <const hb_inc_bimap_t> &inner_maps) { TRACE_SERIALIZE (this); @@ -3197,7 +3197,7 @@ struct VariationStore return_trace (true); } - VariationStore *copy (hb_serialize_context_t *c) const + ItemVariationStore *copy (hb_serialize_context_t *c) const { TRACE_SERIALIZE (this); auto *out = c->start_embed (this); @@ -3227,7 +3227,7 @@ struct VariationStore return_trace (false); #endif - VariationStore *varstore_prime = c->serializer->start_embed<VariationStore> (); + ItemVariationStore *varstore_prime = c->serializer->start_embed<ItemVariationStore> (); if (unlikely (!varstore_prime)) return_trace (false); varstore_prime->serialize (c->serializer, this, inner_maps); @@ -4030,13 +4030,13 @@ struct VariationDevice private: hb_position_t get_x_delta (hb_font_t *font, - const VariationStore &store, - VariationStore::cache_t *store_cache = nullptr) const + const ItemVariationStore &store, + ItemVariationStore::cache_t *store_cache = nullptr) const { return font->em_scalef_x (get_delta (font, store, store_cache)); } hb_position_t get_y_delta (hb_font_t *font, - const VariationStore &store, - VariationStore::cache_t *store_cache = nullptr) const + const ItemVariationStore &store, + ItemVariationStore::cache_t *store_cache = nullptr) const { return font->em_scalef_y (get_delta (font, store, store_cache)); } VariationDevice* copy (hb_serialize_context_t *c, @@ -4070,10 +4070,10 @@ struct VariationDevice private: float get_delta (hb_font_t *font, - const VariationStore &store, - VariationStore::cache_t *store_cache = nullptr) const + const ItemVariationStore &store, + ItemVariationStore::cache_t *store_cache = nullptr) const { - return store.get_delta (varIdx, font->coords, font->num_coords, (VariationStore::cache_t *) store_cache); + return store.get_delta (varIdx, font->coords, font->num_coords, (ItemVariationStore::cache_t *) store_cache); } protected: @@ -4097,8 +4097,8 @@ struct DeviceHeader struct Device { hb_position_t get_x_delta (hb_font_t *font, - const VariationStore &store=Null (VariationStore), - VariationStore::cache_t *store_cache = nullptr) const + const ItemVariationStore &store=Null (ItemVariationStore), + ItemVariationStore::cache_t *store_cache = nullptr) const { switch (u.b.format) { @@ -4115,8 +4115,8 @@ struct Device } } hb_position_t get_y_delta (hb_font_t *font, - const VariationStore &store=Null (VariationStore), - VariationStore::cache_t *store_cache = nullptr) const + const ItemVariationStore &store=Null (ItemVariationStore), + ItemVariationStore::cache_t *store_cache = nullptr) const { switch (u.b.format) { diff --git a/thirdparty/harfbuzz/src/hb-ot-layout-gsubgpos.hh b/thirdparty/harfbuzz/src/hb-ot-layout-gsubgpos.hh index 499ad673e4..c65ea32b8a 100644 --- a/thirdparty/harfbuzz/src/hb-ot-layout-gsubgpos.hh +++ b/thirdparty/harfbuzz/src/hb-ot-layout-gsubgpos.hh @@ -708,8 +708,8 @@ struct hb_ot_apply_context_t : recurse_func_t recurse_func = nullptr; const GDEF &gdef; const GDEF::accelerator_t &gdef_accel; - const VariationStore &var_store; - VariationStore::cache_t *var_store_cache; + const ItemVariationStore &var_store; + ItemVariationStore::cache_t *var_store_cache; hb_set_digest_t digest; hb_direction_t direction; @@ -723,7 +723,6 @@ struct hb_ot_apply_context_t : bool auto_zwj = true; bool per_syllable = false; bool random = false; - uint32_t random_state = 1; unsigned new_syllables = (unsigned) -1; signed last_base = -1; // GPOS uses @@ -766,7 +765,7 @@ struct hb_ot_apply_context_t : ~hb_ot_apply_context_t () { #ifndef HB_NO_VAR - VariationStore::destroy_cache (var_store_cache); + ItemVariationStore::destroy_cache (var_store_cache); #endif } @@ -788,8 +787,8 @@ struct hb_ot_apply_context_t : uint32_t random_number () { /* http://www.cplusplus.com/reference/random/minstd_rand/ */ - random_state = random_state * 48271 % 2147483647; - return random_state; + buffer->random_state = buffer->random_state * 48271 % 2147483647; + return buffer->random_state; } bool match_properties_mark (hb_codepoint_t glyph, diff --git a/thirdparty/harfbuzz/src/hb-ot-layout.cc b/thirdparty/harfbuzz/src/hb-ot-layout.cc index 2eb8535db5..a4c13abadf 100644 --- a/thirdparty/harfbuzz/src/hb-ot-layout.cc +++ b/thirdparty/harfbuzz/src/hb-ot-layout.cc @@ -2127,7 +2127,7 @@ hb_ot_layout_get_font_extents (hb_font_t *font, hb_tag_t language_tag, hb_font_extents_t *extents) { - hb_position_t min, max; + hb_position_t min = 0, max = 0; if (font->face->table.BASE->get_min_max (font, direction, script_tag, language_tag, HB_TAG_NONE, &min, &max)) { diff --git a/thirdparty/harfbuzz/src/hb-ot-math-table.hh b/thirdparty/harfbuzz/src/hb-ot-math-table.hh index 32e497aef6..5839059fde 100644 --- a/thirdparty/harfbuzz/src/hb-ot-math-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-math-table.hh @@ -344,27 +344,20 @@ struct MathKern const MathValueRecord* kernValue = mathValueRecordsZ.arrayZ + heightCount; int sign = font->y_scale < 0 ? -1 : +1; - /* The description of the MathKern table is a ambiguous, but interpreting - * "between the two heights found at those indexes" for 0 < i < len as - * - * correctionHeight[i-1] < correction_height <= correctionHeight[i] - * - * makes the result consistent with the limit cases and we can just use the - * binary search algorithm of std::upper_bound: + /* According to OpenType spec (v1.9), except for the boundary cases, the index + * chosen for kern value should be i such that + * correctionHeight[i-1] <= correction_height < correctionHeight[i] + * We can use the binary search algorithm of std::upper_bound(). Or, we can + * use the internal hb_bsearch_impl. */ - unsigned int i = 0; - unsigned int count = heightCount; - while (count > 0) - { - unsigned int half = count / 2; - hb_position_t height = correctionHeight[i + half].get_y_value (font, this); - if (sign * height < sign * correction_height) - { - i += half + 1; - count -= half + 1; - } else - count = half; - } + unsigned int pos; + auto cmp = +[](const void* key, const void* p, + int sign, hb_font_t* font, const MathKern* mathKern) -> int { + return sign * *(hb_position_t*)key - sign * ((MathValueRecord*)p)->get_y_value(font, mathKern); + }; + unsigned int i = hb_bsearch_impl(&pos, correction_height, correctionHeight, + heightCount, MathValueRecord::static_size, + cmp, sign, font, this) ? pos + 1 : pos; return kernValue[i].get_x_value (font, this); } diff --git a/thirdparty/harfbuzz/src/hb-ot-os2-table.hh b/thirdparty/harfbuzz/src/hb-ot-os2-table.hh index 8c2e696f56..43b58d9bbf 100644 --- a/thirdparty/harfbuzz/src/hb-ot-os2-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-os2-table.hh @@ -223,7 +223,7 @@ struct OS2 } } - return num ? (unsigned) roundf (total_width / num) : 0; + return num ? (unsigned) roundf ((double) total_width / (double) num) : 0; } bool subset (hb_subset_context_t *c) const @@ -284,12 +284,12 @@ struct OS2 os2_prime->usWidthClass = width_class; } - if (c->plan->flags & HB_SUBSET_FLAGS_NO_PRUNE_UNICODE_RANGES) - return_trace (true); - os2_prime->usFirstCharIndex = hb_min (0xFFFFu, c->plan->unicodes.get_min ()); os2_prime->usLastCharIndex = hb_min (0xFFFFu, c->plan->unicodes.get_max ()); + if (c->plan->flags & HB_SUBSET_FLAGS_NO_PRUNE_UNICODE_RANGES) + return_trace (true); + _update_unicode_ranges (&c->plan->unicodes, os2_prime->ulUnicodeRange); return_trace (true); diff --git a/thirdparty/harfbuzz/src/hb-ot-shape.cc b/thirdparty/harfbuzz/src/hb-ot-shape.cc index 90f596ae79..148830022e 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shape.cc +++ b/thirdparty/harfbuzz/src/hb-ot-shape.cc @@ -155,7 +155,7 @@ hb_ot_shape_planner_t::compile (hb_ot_shape_plan_t &plan, #endif bool has_gpos = !disable_gpos && hb_ot_layout_has_positioning (face); if (false) - ; + {} #ifndef HB_NO_AAT_SHAPE /* Prefer GPOS over kerx if GSUB is present; * https://github.com/harfbuzz/harfbuzz/issues/3008 */ @@ -167,15 +167,16 @@ hb_ot_shape_planner_t::compile (hb_ot_shape_plan_t &plan, if (!plan.apply_kerx && (!has_gpos_kern || !plan.apply_gpos)) { + if (false) {} #ifndef HB_NO_AAT_SHAPE - if (has_kerx) + else if (has_kerx) plan.apply_kerx = true; - else #endif #ifndef HB_NO_OT_KERN - if (hb_ot_layout_has_kerning (face)) + else if (hb_ot_layout_has_kerning (face)) plan.apply_kern = true; #endif + else {} } plan.apply_fallback_kern = !(plan.apply_gpos || plan.apply_kerx || plan.apply_kern); diff --git a/thirdparty/harfbuzz/src/hb-ot-shaper-arabic.cc b/thirdparty/harfbuzz/src/hb-ot-shaper-arabic.cc index 72dcc84df5..d70746ed2b 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shaper-arabic.cc +++ b/thirdparty/harfbuzz/src/hb-ot-shaper-arabic.cc @@ -560,9 +560,9 @@ apply_stch (const hb_ot_shape_plan_t *plan HB_UNUSED, DEBUG_MSG (ARABIC, nullptr, "%s stretch at (%u,%u,%u)", step == MEASURE ? "measuring" : "cutting", context, start, end); - DEBUG_MSG (ARABIC, nullptr, "rest of word: count=%u width %d", start - context, w_total); - DEBUG_MSG (ARABIC, nullptr, "fixed tiles: count=%d width=%d", n_fixed, w_fixed); - DEBUG_MSG (ARABIC, nullptr, "repeating tiles: count=%d width=%d", n_repeating, w_repeating); + DEBUG_MSG (ARABIC, nullptr, "rest of word: count=%u width %" PRId32, start - context, w_total); + DEBUG_MSG (ARABIC, nullptr, "fixed tiles: count=%d width=%" PRId32, n_fixed, w_fixed); + DEBUG_MSG (ARABIC, nullptr, "repeating tiles: count=%d width=%" PRId32, n_repeating, w_repeating); /* Number of additional times to repeat each repeating tile. */ int n_copies = 0; @@ -602,7 +602,7 @@ apply_stch (const hb_ot_shape_plan_t *plan HB_UNUSED, if (info[k - 1].arabic_shaping_action() == STCH_REPEATING) repeat += n_copies; - DEBUG_MSG (ARABIC, nullptr, "appending %u copies of glyph %u; j=%u", + DEBUG_MSG (ARABIC, nullptr, "appending %u copies of glyph %" PRIu32 "; j=%u", repeat, info[k - 1].codepoint, j); pos[k - 1].x_advance = 0; for (unsigned int n = 0; n < repeat; n++) diff --git a/thirdparty/harfbuzz/src/hb-ot-stat-table.hh b/thirdparty/harfbuzz/src/hb-ot-stat-table.hh index 58b3cd74df..e88c82a13c 100644 --- a/thirdparty/harfbuzz/src/hb-ot-stat-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-stat-table.hh @@ -349,7 +349,7 @@ struct AxisValueFormat4 struct AxisValue { - bool get_value (unsigned int axis_index) const + float get_value (unsigned int axis_index) const { switch (u.format) { @@ -357,7 +357,7 @@ struct AxisValue case 2: return u.format2.get_value (); case 3: return u.format3.get_value (); case 4: return u.format4.get_axis_record (axis_index).get_value (); - default:return 0; + default:return 0.f; } } @@ -485,7 +485,7 @@ struct STAT hb_array_t<const Offset16To<AxisValue>> axis_values = get_axis_value_offsets (); for (unsigned int i = 0; i < axis_values.length; i++) { - const AxisValue& axis_value = this+axis_values[i]; + const AxisValue& axis_value = this+offsetToAxisValueOffsets+axis_values[i]; if (axis_value.get_axis_index () == axis_index) { if (value) diff --git a/thirdparty/harfbuzz/src/hb-ot-tag-table.hh b/thirdparty/harfbuzz/src/hb-ot-tag-table.hh index 032a7c866c..db92f4664a 100644 --- a/thirdparty/harfbuzz/src/hb-ot-tag-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-tag-table.hh @@ -6,8 +6,8 @@ * * on files with these headers: * - * <meta name="updated_at" content="2022-09-30 11:47 PM" /> - * File-Date: 2023-08-02 + * <meta name="updated_at" content="2023-09-30 01:21 AM" /> + * File-Date: 2024-03-07 */ #ifndef HB_OT_TAG_TABLE_HH @@ -31,7 +31,7 @@ static const LangTag ot_languages2[] = { {HB_TAG('b','i',' ',' '), HB_TAG('B','I','S',' ')}, /* Bislama */ {HB_TAG('b','i',' ',' '), HB_TAG('C','P','P',' ')}, /* Bislama -> Creoles */ {HB_TAG('b','m',' ',' '), HB_TAG('B','M','B',' ')}, /* Bambara (Bamanankan) */ - {HB_TAG('b','n',' ',' '), HB_TAG('B','E','N',' ')}, /* Bengali */ + {HB_TAG('b','n',' ',' '), HB_TAG('B','E','N',' ')}, /* Bangla */ {HB_TAG('b','o',' ',' '), HB_TAG('T','I','B',' ')}, /* Tibetan */ {HB_TAG('b','r',' ',' '), HB_TAG('B','R','E',' ')}, /* Breton */ {HB_TAG('b','s',' ',' '), HB_TAG('B','O','S',' ')}, /* Bosnian */ @@ -64,7 +64,7 @@ static const LangTag ot_languages2[] = { {HB_TAG('f','r',' ',' '), HB_TAG('F','R','A',' ')}, /* French */ {HB_TAG('f','y',' ',' '), HB_TAG('F','R','I',' ')}, /* Western Frisian -> Frisian */ {HB_TAG('g','a',' ',' '), HB_TAG('I','R','I',' ')}, /* Irish */ - {HB_TAG('g','d',' ',' '), HB_TAG('G','A','E',' ')}, /* Scottish Gaelic (Gaelic) */ + {HB_TAG('g','d',' ',' '), HB_TAG('G','A','E',' ')}, /* Scottish Gaelic */ {HB_TAG('g','l',' ',' '), HB_TAG('G','A','L',' ')}, /* Galician */ {HB_TAG('g','n',' ',' '), HB_TAG('G','U','A',' ')}, /* Guarani [macrolanguage] */ {HB_TAG('g','u',' ',' '), HB_TAG('G','U','J',' ')}, /* Gujarati */ @@ -132,7 +132,7 @@ static const LangTag ot_languages2[] = { {HB_TAG('m','l',' ',' '), HB_TAG('M','A','L',' ')}, /* Malayalam -> Malayalam Traditional */ {HB_TAG('m','l',' ',' '), HB_TAG('M','L','R',' ')}, /* Malayalam -> Malayalam Reformed */ {HB_TAG('m','n',' ',' '), HB_TAG('M','N','G',' ')}, /* Mongolian [macrolanguage] */ - {HB_TAG('m','o',' ',' '), HB_TAG('M','O','L',' ')}, /* Moldavian (retired code) */ + {HB_TAG('m','o',' ',' '), HB_TAG('M','O','L',' ')}, /* Moldavian (retired code) -> Romanian (Moldova) */ {HB_TAG('m','o',' ',' '), HB_TAG('R','O','M',' ')}, /* Moldavian (retired code) -> Romanian */ {HB_TAG('m','r',' ',' '), HB_TAG('M','A','R',' ')}, /* Marathi */ {HB_TAG('m','s',' ',' '), HB_TAG('M','L','Y',' ')}, /* Malay [macrolanguage] */ @@ -153,7 +153,7 @@ static const LangTag ot_languages2[] = { {HB_TAG('o','c',' ',' '), HB_TAG('O','C','I',' ')}, /* Occitan (post 1500) */ {HB_TAG('o','j',' ',' '), HB_TAG('O','J','B',' ')}, /* Ojibwa [macrolanguage] -> Ojibway */ {HB_TAG('o','m',' ',' '), HB_TAG('O','R','O',' ')}, /* Oromo [macrolanguage] */ - {HB_TAG('o','r',' ',' '), HB_TAG('O','R','I',' ')}, /* Odia (formerly Oriya) [macrolanguage] */ + {HB_TAG('o','r',' ',' '), HB_TAG('O','R','I',' ')}, /* Odia [macrolanguage] */ {HB_TAG('o','s',' ',' '), HB_TAG('O','S','S',' ')}, /* Ossetian */ {HB_TAG('p','a',' ',' '), HB_TAG('P','A','N',' ')}, /* Punjabi */ {HB_TAG('p','i',' ',' '), HB_TAG('P','A','L',' ')}, /* Pali */ @@ -166,7 +166,7 @@ static const LangTag ot_languages2[] = { {HB_TAG('r','o',' ',' '), HB_TAG('R','O','M',' ')}, /* Romanian */ {HB_TAG('r','u',' ',' '), HB_TAG('R','U','S',' ')}, /* Russian */ {HB_TAG('r','w',' ',' '), HB_TAG('R','U','A',' ')}, /* Kinyarwanda */ - {HB_TAG('s','a',' ',' '), HB_TAG('S','A','N',' ')}, /* Sanskrit */ + {HB_TAG('s','a',' ',' '), HB_TAG('S','A','N',' ')}, /* Sanskrit [macrolanguage] */ {HB_TAG('s','c',' ',' '), HB_TAG('S','R','D',' ')}, /* Sardinian [macrolanguage] */ {HB_TAG('s','d',' ',' '), HB_TAG('S','N','D',' ')}, /* Sindhi */ {HB_TAG('s','e',' ',' '), HB_TAG('N','S','M',' ')}, /* Northern Sami */ @@ -465,6 +465,7 @@ static const LangTag ot_languages3[] = { {HB_TAG('c','l','d',' '), HB_TAG('S','Y','R',' ')}, /* Chaldean Neo-Aramaic -> Syriac */ {HB_TAG('c','l','e',' '), HB_TAG('C','C','H','N')}, /* Lealao Chinantec -> Chinantec */ {HB_TAG('c','l','j',' '), HB_TAG('Q','I','N',' ')}, /* Laitu Chin -> Chin */ + {HB_TAG('c','l','s',' '), HB_TAG('S','A','N',' ')}, /* Classical Sanskrit -> Sanskrit */ {HB_TAG('c','l','t',' '), HB_TAG('Q','I','N',' ')}, /* Lautu Chin -> Chin */ {HB_TAG('c','m','n',' '), HB_TAG('Z','H','S',' ')}, /* Mandarin Chinese -> Chinese, Simplified */ {HB_TAG('c','m','r',' '), HB_TAG('Q','I','N',' ')}, /* Mro-Khimi Chin -> Chin */ @@ -637,7 +638,7 @@ static const LangTag ot_languages3[] = { {HB_TAG('g','a','a',' '), HB_TAG('G','A','D',' ')}, /* Ga */ {HB_TAG('g','a','c',' '), HB_TAG('C','P','P',' ')}, /* Mixed Great Andamanese -> Creoles */ {HB_TAG('g','a','d',' '), HB_TAG_NONE }, /* Gaddang != Ga */ - {HB_TAG('g','a','e',' '), HB_TAG_NONE }, /* Guarequena != Scottish Gaelic (Gaelic) */ + {HB_TAG('g','a','e',' '), HB_TAG_NONE }, /* Guarequena != Scottish Gaelic */ /*{HB_TAG('g','a','g',' '), HB_TAG('G','A','G',' ')},*/ /* Gagauz */ {HB_TAG('g','a','l',' '), HB_TAG_NONE }, /* Galolen != Galician */ {HB_TAG('g','a','n',' '), HB_TAG('Z','H','S',' ')}, /* Gan Chinese -> Chinese, Simplified */ @@ -1160,7 +1161,7 @@ static const LangTag ot_languages3[] = { {HB_TAG('o','r','o',' '), HB_TAG_NONE }, /* Orokolo != Oromo */ {HB_TAG('o','r','r',' '), HB_TAG('I','J','O',' ')}, /* Oruma -> Ijo */ {HB_TAG('o','r','s',' '), HB_TAG('M','L','Y',' ')}, /* Orang Seletar -> Malay */ - {HB_TAG('o','r','y',' '), HB_TAG('O','R','I',' ')}, /* Odia (formerly Oriya) */ + {HB_TAG('o','r','y',' '), HB_TAG('O','R','I',' ')}, /* Odia */ {HB_TAG('o','t','w',' '), HB_TAG('O','J','B',' ')}, /* Ottawa -> Ojibway */ {HB_TAG('o','u','a',' '), HB_TAG('B','B','R',' ')}, /* Tagargrent -> Berber */ {HB_TAG('p','a','a',' '), HB_TAG_NONE }, /* Papuan [collection] != Palestinian Aramaic */ @@ -1395,7 +1396,7 @@ static const LangTag ot_languages3[] = { /*{HB_TAG('s','n','k',' '), HB_TAG('S','N','K',' ')},*/ /* Soninke */ {HB_TAG('s','o','g',' '), HB_TAG_NONE }, /* Sogdian != Sodo Gurage */ /*{HB_TAG('s','o','p',' '), HB_TAG('S','O','P',' ')},*/ /* Songe */ - {HB_TAG('s','p','v',' '), HB_TAG('O','R','I',' ')}, /* Sambalpuri -> Odia (formerly Oriya) */ + {HB_TAG('s','p','v',' '), HB_TAG('O','R','I',' ')}, /* Sambalpuri -> Odia */ {HB_TAG('s','p','y',' '), HB_TAG('K','A','L',' ')}, /* Sabaot -> Kalenjin */ {HB_TAG('s','r','b',' '), HB_TAG_NONE }, /* Sora != Serbian */ {HB_TAG('s','r','c',' '), HB_TAG('S','R','D',' ')}, /* Logudorese Sardinian -> Sardinian */ @@ -1533,6 +1534,7 @@ static const LangTag ot_languages3[] = { {HB_TAG('v','l','s',' '), HB_TAG('F','L','E',' ')}, /* Vlaams -> Dutch (Flemish) */ {HB_TAG('v','m','w',' '), HB_TAG('M','A','K',' ')}, /* Makhuwa */ /*{HB_TAG('v','r','o',' '), HB_TAG('V','R','O',' ')},*/ /* Võro */ + {HB_TAG('v','s','n',' '), HB_TAG('S','A','N',' ')}, /* Vedic Sanskrit -> Sanskrit */ {HB_TAG('w','a','g',' '), HB_TAG_NONE }, /* Wa'ema != Wagdi */ /*{HB_TAG('w','a','r',' '), HB_TAG('W','A','R',' ')},*/ /* Waray (Philippines) -> Waray-Waray */ {HB_TAG('w','b','m',' '), HB_TAG('W','A',' ',' ')}, /* Wa */ @@ -2643,7 +2645,7 @@ out: /* Romanian; Moldova */ unsigned int i; hb_tag_t possible_tags[] = { - HB_TAG('M','O','L',' '), /* Moldavian */ + HB_TAG('M','O','L',' '), /* Romanian (Moldova) */ HB_TAG('R','O','M',' '), /* Romanian */ }; for (i = 0; i < 2 && i < *count; i++) @@ -2920,7 +2922,7 @@ hb_ot_ambiguous_tag_to_language (hb_tag_t tag) return hb_language_from_string ("mn", -1); /* Mongolian [macrolanguage] */ case HB_TAG('M','N','K',' '): /* Maninka */ return hb_language_from_string ("man", -1); /* Mandingo [macrolanguage] */ - case HB_TAG('M','O','L',' '): /* Moldavian */ + case HB_TAG('M','O','L',' '): /* Romanian (Moldova) */ return hb_language_from_string ("ro-MD", -1); /* Romanian; Moldova */ case HB_TAG('M','O','N','T'): /* Thailand Mon */ return hb_language_from_string ("mnw-TH", -1); /* Mon; Thailand */ @@ -2958,6 +2960,8 @@ hb_ot_ambiguous_tag_to_language (hb_tag_t tag) return hb_language_from_string ("ro", -1); /* Romanian */ case HB_TAG('R','O','Y',' '): /* Romany */ return hb_language_from_string ("rom", -1); /* Romany [macrolanguage] */ + case HB_TAG('S','A','N',' '): /* Sanskrit */ + return hb_language_from_string ("sa", -1); /* Sanskrit [macrolanguage] */ case HB_TAG('S','Q','I',' '): /* Albanian */ return hb_language_from_string ("sq", -1); /* Albanian [macrolanguage] */ case HB_TAG('S','R','B',' '): /* Serbian */ diff --git a/thirdparty/harfbuzz/src/hb-ot-tag.cc b/thirdparty/harfbuzz/src/hb-ot-tag.cc index 53b6b38f66..0c63756b14 100644 --- a/thirdparty/harfbuzz/src/hb-ot-tag.cc +++ b/thirdparty/harfbuzz/src/hb-ot-tag.cc @@ -547,7 +547,7 @@ hb_ot_tag_to_language (hb_tag_t tag) buf[3] = '-'; str += 4; } - snprintf (str, 16, "x-hbot-%08x", tag); + snprintf (str, 16, "x-hbot-%08" PRIx32, tag); return hb_language_from_string (&*buf, -1); } } diff --git a/thirdparty/harfbuzz/src/hb-ot-var-avar-table.hh b/thirdparty/harfbuzz/src/hb-ot-var-avar-table.hh index b2e5d87a3c..9149959d79 100644 --- a/thirdparty/harfbuzz/src/hb-ot-var-avar-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-var-avar-table.hh @@ -57,7 +57,7 @@ struct avarV2Tail protected: Offset32To<DeltaSetIndexMap> varIdxMap; /* Offset from the beginning of 'avar' table. */ - Offset32To<VariationStore> varStore; /* Offset from the beginning of 'avar' table. */ + Offset32To<ItemVariationStore> varStore; /* Offset from the beginning of 'avar' table. */ public: DEFINE_SIZE_STATIC (8); @@ -230,7 +230,7 @@ struct SegmentMaps : Array16Of<AxisValueMap> * duplicates here */ if (mapping.must_include ()) continue; - value_mappings.push (std::move (mapping)); + value_mappings.push (mapping); } AxisValueMap m; @@ -343,7 +343,7 @@ struct avar for (unsigned i = 0; i < coords_length; i++) coords[i] = out[i]; - OT::VariationStore::destroy_cache (var_store_cache); + OT::ItemVariationStore::destroy_cache (var_store_cache); #endif } diff --git a/thirdparty/harfbuzz/src/hb-ot-var-common.hh b/thirdparty/harfbuzz/src/hb-ot-var-common.hh index eff6df380f..379e164059 100644 --- a/thirdparty/harfbuzz/src/hb-ot-var-common.hh +++ b/thirdparty/harfbuzz/src/hb-ot-var-common.hh @@ -28,6 +28,7 @@ #include "hb-ot-layout-common.hh" #include "hb-priority-queue.hh" +#include "hb-subset-instancer-iup.hh" namespace OT { @@ -221,9 +222,9 @@ struct DeltaSetIndexMap }; -struct VarStoreInstancer +struct ItemVarStoreInstancer { - VarStoreInstancer (const VariationStore *varStore, + ItemVarStoreInstancer (const ItemVariationStore *varStore, const DeltaSetIndexMap *varIdxMap, hb_array_t<int> coords) : varStore (varStore), varIdxMap (varIdxMap), coords (coords) {} @@ -235,7 +236,7 @@ struct VarStoreInstancer float operator() (uint32_t varIdx, unsigned short offset = 0) const { return coords ? varStore->get_delta (varIdxMap ? varIdxMap->map (VarIdx::add (varIdx, offset)) : varIdx + offset, coords) : 0; } - const VariationStore *varStore; + const ItemVariationStore *varStore; const DeltaSetIndexMap *varIdxMap; hb_array_t<int> coords; }; @@ -460,7 +461,7 @@ struct tuple_delta_t tuple_delta_t () = default; tuple_delta_t (const tuple_delta_t& o) = default; - friend void swap (tuple_delta_t& a, tuple_delta_t& b) + friend void swap (tuple_delta_t& a, tuple_delta_t& b) noexcept { hb_swap (a.axis_tuples, b.axis_tuples); hb_swap (a.indices, b.indices); @@ -471,10 +472,10 @@ struct tuple_delta_t hb_swap (a.compiled_peak_coords, b.compiled_peak_coords); } - tuple_delta_t (tuple_delta_t&& o) : tuple_delta_t () + tuple_delta_t (tuple_delta_t&& o) noexcept : tuple_delta_t () { hb_swap (*this, o); } - tuple_delta_t& operator = (tuple_delta_t&& o) + tuple_delta_t& operator = (tuple_delta_t&& o) noexcept { hb_swap (*this, o); return *this; @@ -609,7 +610,9 @@ struct tuple_delta_t const hb_map_t& axes_old_index_tag_map, const hb_hashmap_t<const hb_vector_t<char>*, unsigned>* shared_tuples_idx_map) { - if (!compiled_deltas) return false; + /* compiled_deltas could be empty after iup delta optimization, we can skip + * compiling this tuple and return true */ + if (!compiled_deltas) return true; unsigned cur_axis_count = axes_index_map.get_population (); /* allocate enough memory: 1 peak + 2 intermediate coords + fixed header size */ @@ -723,22 +726,28 @@ struct tuple_delta_t } bool compile_deltas () + { return compile_deltas (indices, deltas_x, deltas_y, compiled_deltas); } + + bool compile_deltas (const hb_vector_t<bool> &point_indices, + const hb_vector_t<float> &x_deltas, + const hb_vector_t<float> &y_deltas, + hb_vector_t<char> &compiled_deltas /* OUT */) { hb_vector_t<int> rounded_deltas; - if (unlikely (!rounded_deltas.alloc (indices.length))) + if (unlikely (!rounded_deltas.alloc (point_indices.length))) return false; - for (unsigned i = 0; i < indices.length; i++) + for (unsigned i = 0; i < point_indices.length; i++) { - if (!indices[i]) continue; - int rounded_delta = (int) roundf (deltas_x[i]); + if (!point_indices[i]) continue; + int rounded_delta = (int) roundf (x_deltas.arrayZ[i]); rounded_deltas.push (rounded_delta); } - if (!rounded_deltas) return false; + if (!rounded_deltas) return true; /* allocate enough memories 3 * num_deltas */ unsigned alloc_len = 3 * rounded_deltas.length; - if (deltas_y) + if (y_deltas) alloc_len *= 2; if (unlikely (!compiled_deltas.resize (alloc_len))) return false; @@ -746,14 +755,14 @@ struct tuple_delta_t unsigned i = 0; unsigned encoded_len = encode_delta_run (i, compiled_deltas.as_array (), rounded_deltas); - if (deltas_y) + if (y_deltas) { - /* reuse the rounded_deltas vector, check that deltas_y have the same num of deltas as deltas_x */ + /* reuse the rounded_deltas vector, check that y_deltas have the same num of deltas as x_deltas */ unsigned j = 0; - for (unsigned idx = 0; idx < indices.length; idx++) + for (unsigned idx = 0; idx < point_indices.length; idx++) { - if (!indices[idx]) continue; - int rounded_delta = (int) roundf (deltas_y[idx]); + if (!point_indices[idx]) continue; + int rounded_delta = (int) roundf (y_deltas.arrayZ[idx]); if (j >= rounded_deltas.length) return false; @@ -761,7 +770,7 @@ struct tuple_delta_t } if (j != rounded_deltas.length) return false; - /* reset i because we reuse rounded_deltas for deltas_y */ + /* reset i because we reuse rounded_deltas for y_deltas */ i = 0; encoded_len += encode_delta_run (i, compiled_deltas.as_array ().sub_array (encoded_len), rounded_deltas); } @@ -1020,6 +1029,171 @@ struct tuple_delta_t return true; } + bool optimize (const contour_point_vector_t& contour_points, + bool is_composite, + float tolerance = 0.5f) + { + unsigned count = contour_points.length; + if (deltas_x.length != count || + deltas_y.length != count) + return false; + + hb_vector_t<bool> opt_indices; + hb_vector_t<int> rounded_x_deltas, rounded_y_deltas; + + if (unlikely (!rounded_x_deltas.alloc (count) || + !rounded_y_deltas.alloc (count))) + return false; + + for (unsigned i = 0; i < count; i++) + { + int rounded_x_delta = (int) roundf (deltas_x.arrayZ[i]); + int rounded_y_delta = (int) roundf (deltas_y.arrayZ[i]); + rounded_x_deltas.push (rounded_x_delta); + rounded_y_deltas.push (rounded_y_delta); + } + + if (!iup_delta_optimize (contour_points, rounded_x_deltas, rounded_y_deltas, opt_indices, tolerance)) + return false; + + unsigned ref_count = 0; + for (bool ref_flag : opt_indices) + ref_count += ref_flag; + + if (ref_count == count) return true; + + hb_vector_t<float> opt_deltas_x, opt_deltas_y; + bool is_comp_glyph_wo_deltas = (is_composite && ref_count == 0); + if (is_comp_glyph_wo_deltas) + { + if (unlikely (!opt_deltas_x.resize (count) || + !opt_deltas_y.resize (count))) + return false; + + opt_indices.arrayZ[0] = true; + for (unsigned i = 1; i < count; i++) + opt_indices.arrayZ[i] = false; + } + + hb_vector_t<char> opt_point_data; + if (!compile_point_set (opt_indices, opt_point_data)) + return false; + hb_vector_t<char> opt_deltas_data; + if (!compile_deltas (opt_indices, + is_comp_glyph_wo_deltas ? opt_deltas_x : deltas_x, + is_comp_glyph_wo_deltas ? opt_deltas_y : deltas_y, + opt_deltas_data)) + return false; + + hb_vector_t<char> point_data; + if (!compile_point_set (indices, point_data)) + return false; + hb_vector_t<char> deltas_data; + if (!compile_deltas (indices, deltas_x, deltas_y, deltas_data)) + return false; + + if (opt_point_data.length + opt_deltas_data.length < point_data.length + deltas_data.length) + { + indices.fini (); + indices = std::move (opt_indices); + + if (is_comp_glyph_wo_deltas) + { + deltas_x.fini (); + deltas_x = std::move (opt_deltas_x); + + deltas_y.fini (); + deltas_y = std::move (opt_deltas_y); + } + } + return !indices.in_error () && !deltas_x.in_error () && !deltas_y.in_error (); + } + + static bool compile_point_set (const hb_vector_t<bool> &point_indices, + hb_vector_t<char>& compiled_points /* OUT */) + { + unsigned num_points = 0; + for (bool i : point_indices) + if (i) num_points++; + + /* when iup optimization is enabled, num of referenced points could be 0 */ + if (!num_points) return true; + + unsigned indices_length = point_indices.length; + /* If the points set consists of all points in the glyph, it's encoded with a + * single zero byte */ + if (num_points == indices_length) + return compiled_points.resize (1); + + /* allocate enough memories: 2 bytes for count + 3 bytes for each point */ + unsigned num_bytes = 2 + 3 *num_points; + if (unlikely (!compiled_points.resize (num_bytes, false))) + return false; + + unsigned pos = 0; + /* binary data starts with the total number of reference points */ + if (num_points < 0x80) + compiled_points.arrayZ[pos++] = num_points; + else + { + compiled_points.arrayZ[pos++] = ((num_points >> 8) | 0x80); + compiled_points.arrayZ[pos++] = num_points & 0xFF; + } + + const unsigned max_run_length = 0x7F; + unsigned i = 0; + unsigned last_value = 0; + unsigned num_encoded = 0; + while (i < indices_length && num_encoded < num_points) + { + unsigned run_length = 0; + unsigned header_pos = pos; + compiled_points.arrayZ[pos++] = 0; + + bool use_byte_encoding = false; + bool new_run = true; + while (i < indices_length && num_encoded < num_points && + run_length <= max_run_length) + { + // find out next referenced point index + while (i < indices_length && !point_indices[i]) + i++; + + if (i >= indices_length) break; + + unsigned cur_value = i; + unsigned delta = cur_value - last_value; + + if (new_run) + { + use_byte_encoding = (delta <= 0xFF); + new_run = false; + } + + if (use_byte_encoding && delta > 0xFF) + break; + + if (use_byte_encoding) + compiled_points.arrayZ[pos++] = delta; + else + { + compiled_points.arrayZ[pos++] = delta >> 8; + compiled_points.arrayZ[pos++] = delta & 0xFF; + } + i++; + last_value = cur_value; + run_length++; + num_encoded++; + } + + if (use_byte_encoding) + compiled_points.arrayZ[header_pos] = run_length - 1; + else + compiled_points.arrayZ[header_pos] = (run_length - 1) | 0x80; + } + return compiled_points.resize (pos, false); + } + static float infer_delta (float target_val, float prev_val, float next_val, float prev_delta, float next_delta) { if (prev_val == next_val) @@ -1071,41 +1245,41 @@ struct TupleVariationData private: /* referenced point set->compiled point data map */ - hb_hashmap_t<const hb_vector_t<bool>*, hb_bytes_t> point_data_map; + hb_hashmap_t<const hb_vector_t<bool>*, hb_vector_t<char>> point_data_map; /* referenced point set-> count map, used in finding shared points */ hb_hashmap_t<const hb_vector_t<bool>*, unsigned> point_set_count_map; /* empty for non-gvar tuples. - * shared_points_bytes is just a copy of some value in the point_data_map, + * shared_points_bytes is a pointer to some value in the point_data_map, * which will be freed during map destruction. Save it for serialization, so * no need to do find_shared_points () again */ - hb_bytes_t shared_points_bytes; + hb_vector_t<char> *shared_points_bytes = nullptr; /* total compiled byte size as TupleVariationData format, initialized to its * min_size: 4 */ unsigned compiled_byte_size = 4; + /* for gvar iup delta optimization: whether this is a composite glyph */ + bool is_composite = false; + public: tuple_variations_t () = default; tuple_variations_t (const tuple_variations_t&) = delete; tuple_variations_t& operator=(const tuple_variations_t&) = delete; tuple_variations_t (tuple_variations_t&&) = default; tuple_variations_t& operator=(tuple_variations_t&&) = default; - ~tuple_variations_t () { fini (); } - void fini () - { - for (auto _ : point_data_map.values ()) - _.fini (); - - point_set_count_map.fini (); - tuple_vars.fini (); - } + ~tuple_variations_t () = default; explicit operator bool () const { return bool (tuple_vars); } unsigned get_var_count () const { - unsigned count = tuple_vars.length; - if (shared_points_bytes.length) + unsigned count = 0; + /* when iup delta opt is enabled, compiled_deltas could be empty and we + * should skip this tuple */ + for (auto& tuple: tuple_vars) + if (tuple.compiled_deltas) count++; + + if (shared_points_bytes && shared_points_bytes->length) count |= TupleVarCount::SharedPointNumbers; return count; } @@ -1119,26 +1293,27 @@ struct TupleVariationData bool is_gvar, const hb_map_t *axes_old_index_tag_map, const hb_vector_t<unsigned> &shared_indices, - const hb_array_t<const F2DOT14> shared_tuples) + const hb_array_t<const F2DOT14> shared_tuples, + bool is_composite_glyph) { do { const HBUINT8 *p = iterator.get_serialized_data (); unsigned int length = iterator.current_tuple->get_data_size (); if (unlikely (!iterator.var_data_bytes.check_range (p, length))) - { fini (); return false; } + return false; hb_hashmap_t<hb_tag_t, Triple> axis_tuples; if (!iterator.current_tuple->unpack_axis_tuples (iterator.get_axis_count (), shared_tuples, axes_old_index_tag_map, axis_tuples) || axis_tuples.is_empty ()) - { fini (); return false; } + return false; hb_vector_t<unsigned> private_indices; bool has_private_points = iterator.current_tuple->has_private_points (); const HBUINT8 *end = p + length; if (has_private_points && !TupleVariationData::unpack_points (p, private_indices, end)) - { fini (); return false; } + return false; const hb_vector_t<unsigned> &indices = has_private_points ? private_indices : shared_indices; bool apply_to_all = (indices.length == 0); @@ -1148,24 +1323,24 @@ struct TupleVariationData if (unlikely (!deltas_x.resize (num_deltas, false) || !TupleVariationData::unpack_deltas (p, deltas_x, end))) - { fini (); return false; } + return false; hb_vector_t<int> deltas_y; if (is_gvar) { if (unlikely (!deltas_y.resize (num_deltas, false) || !TupleVariationData::unpack_deltas (p, deltas_y, end))) - { fini (); return false; } + return false; } tuple_delta_t var; var.axis_tuples = std::move (axis_tuples); if (unlikely (!var.indices.resize (point_count) || !var.deltas_x.resize (point_count, false))) - { fini (); return false; } + return false; if (is_gvar && unlikely (!var.deltas_y.resize (point_count, false))) - { fini (); return false; } + return false; for (unsigned i = 0; i < num_deltas; i++) { @@ -1178,6 +1353,8 @@ struct TupleVariationData } tuple_vars.push (std::move (var)); } while (iterator.move_to_next ()); + + is_composite = is_composite_glyph; return true; } @@ -1261,7 +1438,7 @@ struct TupleVariationData unsigned new_len = new_vars.length + out.length; if (unlikely (!new_vars.alloc (new_len, false))) - { fini (); return false;} + return false; for (unsigned i = 0; i < out.length; i++) new_vars.push (std::move (out[i])); @@ -1272,8 +1449,9 @@ struct TupleVariationData return true; } - /* merge tuple variations with overlapping tents */ - void merge_tuple_variations () + /* merge tuple variations with overlapping tents, if iup delta optimization + * is enabled, add default deltas to contour_points */ + bool merge_tuple_variations (contour_point_vector_t* contour_points = nullptr) { hb_vector_t<tuple_delta_t> new_vars; hb_hashmap_t<const hb_hashmap_t<hb_tag_t, Triple>*, unsigned> m; @@ -1281,7 +1459,15 @@ struct TupleVariationData for (const tuple_delta_t& var : tuple_vars) { /* if all axes are pinned, drop the tuple variation */ - if (var.axis_tuples.is_empty ()) continue; + if (var.axis_tuples.is_empty ()) + { + /* if iup_delta_optimize is enabled, add deltas to contour coords */ + if (contour_points && !contour_points->add_deltas (var.deltas_x, + var.deltas_y, + var.indices)) + return false; + continue; + } unsigned *idx; if (m.has (&(var.axis_tuples), &idx)) @@ -1291,98 +1477,14 @@ struct TupleVariationData else { new_vars.push (var); - m.set (&(var.axis_tuples), i); + if (!m.set (&(var.axis_tuples), i)) + return false; i++; } } tuple_vars.fini (); tuple_vars = std::move (new_vars); - } - - hb_bytes_t compile_point_set (const hb_vector_t<bool> &point_indices) - { - unsigned num_points = 0; - for (bool i : point_indices) - if (i) num_points++; - - unsigned indices_length = point_indices.length; - /* If the points set consists of all points in the glyph, it's encoded with a - * single zero byte */ - if (num_points == indices_length) - { - char *p = (char *) hb_calloc (1, sizeof (char)); - if (unlikely (!p)) return hb_bytes_t (); - - return hb_bytes_t (p, 1); - } - - /* allocate enough memories: 2 bytes for count + 3 bytes for each point */ - unsigned num_bytes = 2 + 3 *num_points; - char *p = (char *) hb_calloc (num_bytes, sizeof (char)); - if (unlikely (!p)) return hb_bytes_t (); - - unsigned pos = 0; - /* binary data starts with the total number of reference points */ - if (num_points < 0x80) - p[pos++] = num_points; - else - { - p[pos++] = ((num_points >> 8) | 0x80); - p[pos++] = num_points & 0xFF; - } - - const unsigned max_run_length = 0x7F; - unsigned i = 0; - unsigned last_value = 0; - unsigned num_encoded = 0; - while (i < indices_length && num_encoded < num_points) - { - unsigned run_length = 0; - unsigned header_pos = pos; - p[pos++] = 0; - - bool use_byte_encoding = false; - bool new_run = true; - while (i < indices_length && num_encoded < num_points && - run_length <= max_run_length) - { - // find out next referenced point index - while (i < indices_length && !point_indices[i]) - i++; - - if (i >= indices_length) break; - - unsigned cur_value = i; - unsigned delta = cur_value - last_value; - - if (new_run) - { - use_byte_encoding = (delta <= 0xFF); - new_run = false; - } - - if (use_byte_encoding && delta > 0xFF) - break; - - if (use_byte_encoding) - p[pos++] = delta; - else - { - p[pos++] = delta >> 8; - p[pos++] = delta & 0xFF; - } - i++; - last_value = cur_value; - run_length++; - num_encoded++; - } - - if (use_byte_encoding) - p[header_pos] = run_length - 1; - else - p[header_pos] = (run_length - 1) | 0x80; - } - return hb_bytes_t (p, pos); + return true; } /* compile all point set and store byte data in a point_set->hb_bytes_t hashmap, @@ -1402,11 +1504,11 @@ struct TupleVariationData continue; } - hb_bytes_t compiled_data = compile_point_set (*points_set); - if (unlikely (compiled_data == hb_bytes_t ())) + hb_vector_t<char> compiled_point_data; + if (!tuple_delta_t::compile_point_set (*points_set, compiled_point_data)) return false; - if (!point_data_map.set (points_set, compiled_data) || + if (!point_data_map.set (points_set, std::move (compiled_point_data)) || !point_set_count_map.set (points_set, 1)) return false; } @@ -1414,31 +1516,33 @@ struct TupleVariationData } /* find shared points set which saves most bytes */ - hb_bytes_t find_shared_points () + void find_shared_points () { unsigned max_saved_bytes = 0; - hb_bytes_t res{}; - for (const auto& _ : point_data_map.iter ()) + for (const auto& _ : point_data_map.iter_ref ()) { const hb_vector_t<bool>* points_set = _.first; unsigned data_length = _.second.length; + if (!data_length) continue; unsigned *count; if (unlikely (!point_set_count_map.has (points_set, &count) || *count <= 1)) - return hb_bytes_t (); + { + shared_points_bytes = nullptr; + return; + } unsigned saved_bytes = data_length * ((*count) -1); if (saved_bytes > max_saved_bytes) { max_saved_bytes = saved_bytes; - res = _.second; + shared_points_bytes = &(_.second); } } - return res; } - bool calc_inferred_deltas (contour_point_vector_t& contour_points) + bool calc_inferred_deltas (const contour_point_vector_t& contour_points) { for (tuple_delta_t& var : tuple_vars) if (!var.calc_inferred_deltas (contour_points)) @@ -1447,10 +1551,21 @@ struct TupleVariationData return true; } + bool iup_optimize (const contour_point_vector_t& contour_points) + { + for (tuple_delta_t& var : tuple_vars) + { + if (!var.optimize (contour_points, is_composite)) + return false; + } + return true; + } + public: bool instantiate (const hb_hashmap_t<hb_tag_t, Triple>& normalized_axes_location, const hb_hashmap_t<hb_tag_t, TripleDistances>& axes_triple_distances, - contour_point_vector_t* contour_points = nullptr) + contour_point_vector_t* contour_points = nullptr, + bool optimize = false) { if (!tuple_vars) return true; if (!change_tuple_variations_axis_limits (normalized_axes_location, axes_triple_distances)) @@ -1460,7 +1575,14 @@ struct TupleVariationData if (!calc_inferred_deltas (*contour_points)) return false; - merge_tuple_variations (); + /* if iup delta opt is on, contour_points can't be null */ + if (optimize && !contour_points) + return false; + + if (!merge_tuple_variations (optimize ? contour_points : nullptr)) + return false; + + if (optimize && !iup_optimize (*contour_points)) return false; return !tuple_vars.in_error (); } @@ -1475,21 +1597,27 @@ struct TupleVariationData if (use_shared_points) { - shared_points_bytes = find_shared_points (); - compiled_byte_size += shared_points_bytes.length; + find_shared_points (); + if (shared_points_bytes) + compiled_byte_size += shared_points_bytes->length; } // compile delta and tuple var header for each tuple variation for (auto& tuple: tuple_vars) { const hb_vector_t<bool>* points_set = &(tuple.indices); - hb_bytes_t *points_data; + hb_vector_t<char> *points_data; if (unlikely (!point_data_map.has (points_set, &points_data))) return false; + /* when iup optimization is enabled, num of referenced points could be 0 + * and thus the compiled points bytes is empty, we should skip compiling + * this tuple */ + if (!points_data->length) + continue; if (!tuple.compile_deltas ()) return false; - unsigned points_data_length = (*points_data != shared_points_bytes) ? points_data->length : 0; + unsigned points_data_length = (points_data != shared_points_bytes) ? points_data->length : 0; if (!tuple.compile_tuple_var_header (axes_index_map, points_data_length, axes_old_index_tag_map, shared_tuples_idx_map)) return false; @@ -1513,18 +1641,24 @@ struct TupleVariationData bool serialize_var_data (hb_serialize_context_t *c, bool is_gvar) const { TRACE_SERIALIZE (this); - if (is_gvar) - shared_points_bytes.copy (c); + if (is_gvar && shared_points_bytes) + { + hb_bytes_t s (shared_points_bytes->arrayZ, shared_points_bytes->length); + s.copy (c); + } for (const auto& tuple: tuple_vars) { const hb_vector_t<bool>* points_set = &(tuple.indices); - hb_bytes_t *point_data; + hb_vector_t<char> *point_data; if (!point_data_map.has (points_set, &point_data)) return_trace (false); - if (!is_gvar || *point_data != shared_points_bytes) - point_data->copy (c); + if (!is_gvar || point_data != shared_points_bytes) + { + hb_bytes_t s (point_data->arrayZ, point_data->length); + s.copy (c); + } tuple.compiled_deltas.as_array ().copy (c); if (c->in_error ()) return_trace (false); @@ -1711,13 +1845,15 @@ struct TupleVariationData const hb_map_t *axes_old_index_tag_map, const hb_vector_t<unsigned> &shared_indices, const hb_array_t<const F2DOT14> shared_tuples, - tuple_variations_t& tuple_variations /* OUT */) const + tuple_variations_t& tuple_variations, /* OUT */ + bool is_composite_glyph = false) const { return tuple_variations.create_from_tuple_var_data (iterator, tupleVarCount, point_count, is_gvar, axes_old_index_tag_map, shared_indices, - shared_tuples); + shared_tuples, + is_composite_glyph); } bool serialize (hb_serialize_context_t *c, @@ -1831,7 +1967,7 @@ struct item_variations_t const hb_map_t& get_varidx_map () const { return varidx_map; } - bool instantiate (const VariationStore& varStore, + bool instantiate (const ItemVariationStore& varStore, const hb_subset_plan_t *plan, bool optimize=true, bool use_no_variation_idx=true, @@ -1845,7 +1981,7 @@ struct item_variations_t } /* keep below APIs public only for unit test: test-item-varstore */ - bool create_from_item_varstore (const VariationStore& varStore, + bool create_from_item_varstore (const ItemVariationStore& varStore, const hb_map_t& axes_old_index_tag_map, const hb_array_t <const hb_inc_bimap_t> inner_maps = hb_array_t<const hb_inc_bimap_t> ()) { diff --git a/thirdparty/harfbuzz/src/hb-ot-var-gvar-table.hh b/thirdparty/harfbuzz/src/hb-ot-var-gvar-table.hh index 1c7a1f6c1e..59aad57e37 100644 --- a/thirdparty/harfbuzz/src/hb-ot-var-gvar-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-var-gvar-table.hh @@ -101,10 +101,15 @@ struct glyph_variations_t continue; } + bool is_composite_glyph = false; +#ifdef HB_EXPERIMENTAL_API + is_composite_glyph = plan->composite_new_gids.has (new_gid); +#endif if (!p->decompile_tuple_variations (all_contour_points->length, true /* is_gvar */, iterator, &(plan->axes_old_index_tag_map), shared_indices, shared_tuples, - tuple_vars /* OUT */)) + tuple_vars, /* OUT */ + is_composite_glyph)) return false; glyph_variations.push (std::move (tuple_vars)); } @@ -114,13 +119,17 @@ struct glyph_variations_t bool instantiate (const hb_subset_plan_t *plan) { unsigned count = plan->new_to_old_gid_list.length; + bool iup_optimize = false; +#ifdef HB_EXPERIMENTAL_API + iup_optimize = plan->flags & HB_SUBSET_FLAGS_OPTIMIZE_IUP_DELTAS; +#endif for (unsigned i = 0; i < count; i++) { hb_codepoint_t new_gid = plan->new_to_old_gid_list[i].first; contour_point_vector_t *all_points; if (!plan->new_gid_contour_points_map.has (new_gid, &all_points)) return false; - if (!glyph_variations[i].instantiate (plan->axes_location, plan->axes_triple_distances, all_points)) + if (!glyph_variations[i].instantiate (plan->axes_location, plan->axes_triple_distances, all_points, iup_optimize)) return false; } return true; @@ -340,7 +349,8 @@ struct gvar const glyph_variations_t& glyph_vars, Iterator it, unsigned axis_count, - unsigned num_glyphs) const + unsigned num_glyphs, + bool force_long_offsets) const { TRACE_SERIALIZE (this); gvar *out = c->allocate_min<gvar> (); @@ -352,7 +362,7 @@ struct gvar out->glyphCountX = hb_min (0xFFFFu, num_glyphs); unsigned glyph_var_data_size = glyph_vars.compiled_byte_size (); - bool long_offset = glyph_var_data_size & ~0xFFFFu; + bool long_offset = glyph_var_data_size & ~0xFFFFu || force_long_offsets; out->flags = long_offset ? 1 : 0; HBUINT8 *glyph_var_data_offsets = c->allocate_size<HBUINT8> ((long_offset ? 4 : 2) * (num_glyphs + 1), false); @@ -393,7 +403,12 @@ struct gvar unsigned axis_count = c->plan->axes_index_map.get_population (); unsigned num_glyphs = c->plan->num_output_glyphs (); auto it = hb_iter (c->plan->new_to_old_gid_list); - return_trace (serialize (c->serializer, glyph_vars, it, axis_count, num_glyphs)); + + bool force_long_offsets = false; +#ifdef HB_EXPERIMENTAL_API + force_long_offsets = c->plan->flags & HB_SUBSET_FLAGS_IFTB_REQUIREMENTS; +#endif + return_trace (serialize (c->serializer, glyph_vars, it, axis_count, num_glyphs, force_long_offsets)); } bool subset (hb_subset_context_t *c) const @@ -429,7 +444,7 @@ struct gvar } bool long_offset = (subset_data_size & ~0xFFFFu); - #ifdef HB_EXPERIMENTAL_API +#ifdef HB_EXPERIMENTAL_API long_offset = long_offset || (c->plan->flags & HB_SUBSET_FLAGS_IFTB_REQUIREMENTS); #endif out->flags = long_offset ? 1 : 0; diff --git a/thirdparty/harfbuzz/src/hb-ot-var-hvar-table.hh b/thirdparty/harfbuzz/src/hb-ot-var-hvar-table.hh index 53a4642d38..33a4e1a40e 100644 --- a/thirdparty/harfbuzz/src/hb-ot-var-hvar-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-var-hvar-table.hh @@ -188,7 +188,7 @@ struct hvarvvar_subset_plan_t ~hvarvvar_subset_plan_t() { fini (); } void init (const hb_array_t<const DeltaSetIndexMap *> &index_maps, - const VariationStore &_var_store, + const ItemVariationStore &_var_store, const hb_subset_plan_t *plan) { index_map_plans.resize (index_maps.length); @@ -263,7 +263,7 @@ struct hvarvvar_subset_plan_t hb_inc_bimap_t outer_map; hb_vector_t<hb_inc_bimap_t> inner_maps; hb_vector_t<index_map_subset_plan_t> index_map_plans; - const VariationStore *var_store; + const ItemVariationStore *var_store; protected: hb_vector_t<hb_set_t *> inner_sets; @@ -296,7 +296,7 @@ struct HVARVVAR rsbMap.sanitize (c, this)); } - const VariationStore& get_var_store () const + const ItemVariationStore& get_var_store () const { return this+varStore; } void listup_index_maps (hb_vector_t<const DeltaSetIndexMap *> &index_maps) const @@ -384,7 +384,7 @@ struct HVARVVAR float get_advance_delta_unscaled (hb_codepoint_t glyph, const int *coords, unsigned int coord_count, - VariationStore::cache_t *store_cache = nullptr) const + ItemVariationStore::cache_t *store_cache = nullptr) const { uint32_t varidx = (this+advMap).map (glyph); return (this+varStore).get_delta (varidx, @@ -405,7 +405,7 @@ struct HVARVVAR public: FixedVersion<>version; /* Version of the metrics variation table * initially set to 0x00010000u */ - Offset32To<VariationStore> + Offset32To<ItemVariationStore> varStore; /* Offset to item variation store table. */ Offset32To<DeltaSetIndexMap> advMap; /* Offset to advance var-idx mapping. */ diff --git a/thirdparty/harfbuzz/src/hb-ot-var-mvar-table.hh b/thirdparty/harfbuzz/src/hb-ot-var-mvar-table.hh index 6d69777618..1f0401d1d3 100644 --- a/thirdparty/harfbuzz/src/hb-ot-var-mvar-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-var-mvar-table.hh @@ -56,7 +56,7 @@ struct VariationValueRecord public: Tag valueTag; /* Four-byte tag identifying a font-wide measure. */ - VarIdx varIdx; /* Outer/inner index into VariationStore item. */ + VarIdx varIdx; /* Outer/inner index into ItemVariationStore item. */ public: DEFINE_SIZE_STATIC (8); @@ -106,7 +106,7 @@ struct MVAR out->valueRecordCount = valueRecordCount; item_variations_t item_vars; - const VariationStore& src_var_store = this+varStore; + const ItemVariationStore& src_var_store = this+varStore; if (!item_vars.instantiate (src_var_store, c->plan)) return_trace (false); @@ -159,7 +159,7 @@ protected: HBUINT16 valueRecordSize;/* The size in bytes of each value record — * must be greater than zero. */ HBUINT16 valueRecordCount;/* The number of value records — may be zero. */ - Offset16To<VariationStore> + Offset16To<ItemVariationStore> varStore; /* Offset to item variation store table. */ UnsizedArrayOf<HBUINT8> valuesZ; /* Array of value records. The records must be diff --git a/thirdparty/harfbuzz/src/hb-priority-queue.hh b/thirdparty/harfbuzz/src/hb-priority-queue.hh index 9b962a29d9..274d5df4c5 100644 --- a/thirdparty/harfbuzz/src/hb-priority-queue.hh +++ b/thirdparty/harfbuzz/src/hb-priority-queue.hh @@ -163,7 +163,7 @@ struct hb_priority_queue_t goto repeat; } - void swap (unsigned a, unsigned b) + void swap (unsigned a, unsigned b) noexcept { assert (a < heap.length); assert (b < heap.length); diff --git a/thirdparty/harfbuzz/src/hb-repacker.hh b/thirdparty/harfbuzz/src/hb-repacker.hh index e9cd376ad3..ed40f271cc 100644 --- a/thirdparty/harfbuzz/src/hb-repacker.hh +++ b/thirdparty/harfbuzz/src/hb-repacker.hh @@ -239,6 +239,54 @@ bool _try_isolating_subgraphs (const hb_vector_t<graph::overflow_record_t>& over } static inline +bool _resolve_shared_overflow(const hb_vector_t<graph::overflow_record_t>& overflows, + int overflow_index, + graph_t& sorted_graph) +{ + const graph::overflow_record_t& r = overflows[overflow_index]; + + // Find all of the parents in overflowing links that link to this + // same child node. We will then try duplicating the child node and + // re-assigning all of these parents to the duplicate. + hb_set_t parents; + parents.add(r.parent); + for (int i = overflow_index - 1; i >= 0; i--) { + const graph::overflow_record_t& r2 = overflows[i]; + if (r2.child == r.child) { + parents.add(r2.parent); + } + } + + unsigned result = sorted_graph.duplicate(&parents, r.child); + if (result == (unsigned) -1 && parents.get_population() > 2) { + // All links to the child are overflowing, so we can't include all + // in the duplication. Remove one parent from the duplication. + // Remove the lowest index parent, which will be the closest to the child. + parents.del(parents.get_min()); + result = sorted_graph.duplicate(&parents, r.child); + } + + if (result == (unsigned) -1) return result; + + if (parents.get_population() > 1) { + // If the duplicated node has more than one parent pre-emptively raise it's priority to the maximum. + // This will place it close to the parents. Node's with only one parent, don't need this as normal overflow + // resolution will raise priority if needed. + // + // Reasoning: most of the parents to this child are likely at the same layer in the graph. Duplicating + // the child will theoretically allow it to be placed closer to it's parents. However, due to the shortest + // distance sort by default it's placement will remain in the same layer, thus it will remain in roughly the + // same position (and distance from parents) as the original child node. The overflow resolution will attempt + // to move nodes closer, but only for non-shared nodes. Since this node is shared, it will simply be given + // further duplication which defeats the attempt to duplicate with multiple parents. To fix this we + // pre-emptively raise priority now which allows the duplicated node to pack into the same layer as it's parents. + sorted_graph.vertices_[result].give_max_priority(); + } + + return result; +} + +static inline bool _process_overflows (const hb_vector_t<graph::overflow_record_t>& overflows, hb_set_t& priority_bumped_parents, graph_t& sorted_graph) @@ -254,7 +302,7 @@ bool _process_overflows (const hb_vector_t<graph::overflow_record_t>& overflows, { // The child object is shared, we may be able to eliminate the overflow // by duplicating it. - if (sorted_graph.duplicate (r.parent, r.child) == (unsigned) -1) continue; + if (!_resolve_shared_overflow(overflows, i, sorted_graph)) continue; return true; } @@ -388,7 +436,7 @@ template<typename T> inline hb_blob_t* hb_resolve_overflows (const T& packed, hb_tag_t table_tag, - unsigned max_rounds = 20, + unsigned max_rounds = 32, bool recalculate_extensions = false) { graph_t sorted_graph (packed); if (sorted_graph.in_error ()) diff --git a/thirdparty/harfbuzz/src/hb-serialize.hh b/thirdparty/harfbuzz/src/hb-serialize.hh index 15eccb6a09..e988451eb3 100644 --- a/thirdparty/harfbuzz/src/hb-serialize.hh +++ b/thirdparty/harfbuzz/src/hb-serialize.hh @@ -91,7 +91,27 @@ struct hb_serialize_context_t } #endif - friend void swap (object_t& a, object_t& b) + bool add_virtual_link (objidx_t objidx) + { + if (!objidx) + return false; + + auto& link = *virtual_links.push (); + if (virtual_links.in_error ()) + return false; + + link.objidx = objidx; + // Remaining fields were previously zero'd by push(): + // link.width = 0; + // link.is_signed = 0; + // link.whence = 0; + // link.position = 0; + // link.bias = 0; + + return true; + } + + friend void swap (object_t& a, object_t& b) noexcept { hb_swap (a.head, b.head); hb_swap (a.tail, b.tail); @@ -156,9 +176,9 @@ struct hb_serialize_context_t object_t *next; auto all_links () const HB_AUTO_RETURN - (( hb_concat (this->real_links, this->virtual_links) )); + (( hb_concat (real_links, virtual_links) )); auto all_links_writer () HB_AUTO_RETURN - (( hb_concat (this->real_links.writer (), this->virtual_links.writer ()) )); + (( hb_concat (real_links.writer (), virtual_links.writer ()) )); }; struct snapshot_t @@ -469,16 +489,40 @@ struct hb_serialize_context_t assert (current); - auto& link = *current->virtual_links.push (); - if (current->virtual_links.in_error ()) + if (!current->add_virtual_link(objidx)) err (HB_SERIALIZE_ERROR_OTHER); + } - link.width = 0; - link.objidx = objidx; - link.is_signed = 0; - link.whence = 0; - link.position = 0; - link.bias = 0; + objidx_t last_added_child_index() const { + if (unlikely (in_error ())) return (objidx_t) -1; + + assert (current); + if (!bool(current->real_links)) { + return (objidx_t) -1; + } + + return current->real_links[current->real_links.length - 1].objidx; + } + + // For the current object ensure that the sub-table bytes for child objidx are always placed + // after the subtable bytes for any other existing children. This only ensures that the + // repacker will not move the target subtable before the other children + // (by adding virtual links). It is up to the caller to ensure the initial serialization + // order is correct. + void repack_last(objidx_t objidx) { + if (unlikely (in_error ())) return; + + if (!objidx) + return; + + assert (current); + for (auto& l : current->real_links) { + if (l.objidx == objidx) { + continue; + } + + packed[l.objidx]->add_virtual_link(objidx); + } } template <typename T> diff --git a/thirdparty/harfbuzz/src/hb-set.hh b/thirdparty/harfbuzz/src/hb-set.hh index ff2a170d2d..ce69ea2c9b 100644 --- a/thirdparty/harfbuzz/src/hb-set.hh +++ b/thirdparty/harfbuzz/src/hb-set.hh @@ -44,10 +44,10 @@ struct hb_sparseset_t ~hb_sparseset_t () { fini (); } hb_sparseset_t (const hb_sparseset_t& other) : hb_sparseset_t () { set (other); } - hb_sparseset_t (hb_sparseset_t&& other) : hb_sparseset_t () { s = std::move (other.s); } + hb_sparseset_t (hb_sparseset_t&& other) noexcept : hb_sparseset_t () { s = std::move (other.s); } hb_sparseset_t& operator = (const hb_sparseset_t& other) { set (other); return *this; } - hb_sparseset_t& operator = (hb_sparseset_t&& other) { s = std::move (other.s); return *this; } - friend void swap (hb_sparseset_t& a, hb_sparseset_t& b) { hb_swap (a.s, b.s); } + hb_sparseset_t& operator = (hb_sparseset_t&& other) noexcept { s = std::move (other.s); return *this; } + friend void swap (hb_sparseset_t& a, hb_sparseset_t& b) noexcept { hb_swap (a.s, b.s); } hb_sparseset_t (std::initializer_list<hb_codepoint_t> lst) : hb_sparseset_t () { @@ -166,7 +166,7 @@ struct hb_set_t : hb_sparseset_t<hb_bit_set_invertible_t> ~hb_set_t () = default; hb_set_t () : sparseset () {}; hb_set_t (const hb_set_t &o) : sparseset ((sparseset &) o) {}; - hb_set_t (hb_set_t&& o) : sparseset (std::move ((sparseset &) o)) {} + hb_set_t (hb_set_t&& o) noexcept : sparseset (std::move ((sparseset &) o)) {} hb_set_t& operator = (const hb_set_t&) = default; hb_set_t& operator = (hb_set_t&&) = default; hb_set_t (std::initializer_list<hb_codepoint_t> lst) : sparseset (lst) {} diff --git a/thirdparty/harfbuzz/src/hb-subset-cff2.cc b/thirdparty/harfbuzz/src/hb-subset-cff2.cc index abc108e571..eb5cb0c625 100644 --- a/thirdparty/harfbuzz/src/hb-subset-cff2.cc +++ b/thirdparty/harfbuzz/src/hb-subset-cff2.cc @@ -248,7 +248,7 @@ struct cff2_subr_subsetter_t : subr_subsetter_t<cff2_subr_subsetter_t, CFF2Subrs struct cff2_private_blend_encoder_param_t { cff2_private_blend_encoder_param_t (hb_serialize_context_t *c, - const CFF2VariationStore *varStore, + const CFF2ItemVariationStore *varStore, hb_array_t<int> normalized_coords) : c (c), varStore (varStore), normalized_coords (normalized_coords) {} @@ -284,7 +284,7 @@ struct cff2_private_blend_encoder_param_t unsigned ivs = 0; unsigned region_count = 0; hb_vector_t<float> scalars; - const CFF2VariationStore *varStore = nullptr; + const CFF2ItemVariationStore *varStore = nullptr; hb_array_t<int> normalized_coords; }; @@ -378,7 +378,7 @@ struct cff2_private_dict_blend_opset_t : dict_opset_t struct cff2_private_dict_op_serializer_t : op_serializer_t { cff2_private_dict_op_serializer_t (bool desubroutinize_, bool drop_hints_, bool pinned_, - const CFF::CFF2VariationStore* varStore_, + const CFF::CFF2ItemVariationStore* varStore_, hb_array_t<int> normalized_coords_) : desubroutinize (desubroutinize_), drop_hints (drop_hints_), pinned (pinned_), varStore (varStore_), normalized_coords (normalized_coords_) {} @@ -416,7 +416,7 @@ struct cff2_private_dict_op_serializer_t : op_serializer_t const bool desubroutinize; const bool drop_hints; const bool pinned; - const CFF::CFF2VariationStore* varStore; + const CFF::CFF2ItemVariationStore* varStore; hb_array_t<int> normalized_coords; }; @@ -628,10 +628,10 @@ OT::cff2::accelerator_subset_t::serialize (hb_serialize_context_t *c, } /* variation store */ - if (varStore != &Null (CFF2VariationStore) && + if (varStore != &Null (CFF2ItemVariationStore) && !plan.pinned) { - auto *dest = c->push<CFF2VariationStore> (); + auto *dest = c->push<CFF2ItemVariationStore> (); if (unlikely (!dest->serialize (c, varStore))) { c->pop_discard (); diff --git a/thirdparty/harfbuzz/src/hb-subset-input.cc b/thirdparty/harfbuzz/src/hb-subset-input.cc index 1e0a89a630..68a3e77788 100644 --- a/thirdparty/harfbuzz/src/hb-subset-input.cc +++ b/thirdparty/harfbuzz/src/hb-subset-input.cc @@ -24,6 +24,7 @@ * Google Author(s): Garret Rieger, Rod Sheeter, Behdad Esfahbod */ +#include "hb-subset-instancer-solver.hh" #include "hb-subset.hh" #include "hb-set.hh" #include "hb-utf.hh" @@ -50,7 +51,6 @@ hb_subset_input_t::hb_subset_input_t () HB_TAG ('k', 'e', 'r', 'n'), // Copied from fontTools: - HB_TAG ('B', 'A', 'S', 'E'), HB_TAG ('J', 'S', 'T', 'F'), HB_TAG ('D', 'S', 'I', 'G'), HB_TAG ('E', 'B', 'D', 'T'), @@ -418,6 +418,46 @@ hb_subset_input_keep_everything (hb_subset_input_t *input) #ifndef HB_NO_VAR /** + * hb_subset_input_pin_all_axes_to_default: (skip) + * @input: a #hb_subset_input_t object. + * @face: a #hb_face_t object. + * + * Pin all axes to default locations in the given subset input object. + * + * All axes in a font must be pinned. Additionally, `CFF2` table, if present, + * will be de-subroutinized. + * + * Return value: `true` if success, `false` otherwise + * + * Since: 8.3.1 + **/ +HB_EXTERN hb_bool_t +hb_subset_input_pin_all_axes_to_default (hb_subset_input_t *input, + hb_face_t *face) +{ + unsigned axis_count = hb_ot_var_get_axis_count (face); + if (!axis_count) return false; + + hb_ot_var_axis_info_t *axis_infos = (hb_ot_var_axis_info_t *) hb_calloc (axis_count, sizeof (hb_ot_var_axis_info_t)); + if (unlikely (!axis_infos)) return false; + + (void) hb_ot_var_get_axis_infos (face, 0, &axis_count, axis_infos); + + for (unsigned i = 0; i < axis_count; i++) + { + hb_tag_t axis_tag = axis_infos[i].tag; + float default_val = axis_infos[i].default_value; + if (!input->axes_location.set (axis_tag, Triple (default_val, default_val, default_val))) + { + hb_free (axis_infos); + return false; + } + } + hb_free (axis_infos); + return true; +} + +/** * hb_subset_input_pin_axis_to_default: (skip) * @input: a #hb_subset_input_t object. * @face: a #hb_face_t object. @@ -481,16 +521,13 @@ hb_subset_input_pin_axis_location (hb_subset_input_t *input, * @input: a #hb_subset_input_t object. * @face: a #hb_face_t object. * @axis_tag: Tag of the axis - * @axis_min_value: Minimum value of the axis variation range to set - * @axis_max_value: Maximum value of the axis variation range to set - * @axis_def_value: Default value of the axis variation range to set, in case of - * null, it'll be determined automatically + * @axis_min_value: Minimum value of the axis variation range to set, if NaN the existing min will be used. + * @axis_max_value: Maximum value of the axis variation range to set if NaN the existing max will be used. + * @axis_def_value: Default value of the axis variation range to set, if NaN the existing default will be used. * * Restricting the range of variation on an axis in the given subset input object. * New min/default/max values will be clamped if they're not within the fvar axis range. - * If the new default value is null: - * If the fvar axis default value is within the new range, then new default - * value is the same as original default value. + * * If the fvar axis default value is not within the new range, the new default * value will be changed to the new min or max value, whichever is closer to the fvar * axis default. @@ -509,21 +546,57 @@ hb_subset_input_set_axis_range (hb_subset_input_t *input, hb_tag_t axis_tag, float axis_min_value, float axis_max_value, - float *axis_def_value /* IN, maybe NULL */) + float axis_def_value) { - if (axis_min_value > axis_max_value) - return false; - hb_ot_var_axis_info_t axis_info; if (!hb_ot_var_find_axis_info (face, axis_tag, &axis_info)) return false; - float new_min_val = hb_clamp(axis_min_value, axis_info.min_value, axis_info.max_value); - float new_max_val = hb_clamp(axis_max_value, axis_info.min_value, axis_info.max_value); - float new_default_val = axis_def_value ? *axis_def_value : axis_info.default_value; - new_default_val = hb_clamp(new_default_val, new_min_val, new_max_val); + float min = !std::isnan(axis_min_value) ? axis_min_value : axis_info.min_value; + float max = !std::isnan(axis_max_value) ? axis_max_value : axis_info.max_value; + float def = !std::isnan(axis_def_value) ? axis_def_value : axis_info.default_value; + + if (min > max) + return false; + + float new_min_val = hb_clamp(min, axis_info.min_value, axis_info.max_value); + float new_max_val = hb_clamp(max, axis_info.min_value, axis_info.max_value); + float new_default_val = hb_clamp(def, new_min_val, new_max_val); return input->axes_location.set (axis_tag, Triple (new_min_val, new_default_val, new_max_val)); } + +/** + * hb_subset_input_get_axis_range: (skip) + * @input: a #hb_subset_input_t object. + * @axis_tag: Tag of the axis + * @axis_min_value: Set to the previously configured minimum value of the axis variation range. + * @axis_max_value: Set to the previously configured maximum value of the axis variation range. + * @axis_def_value: Set to the previously configured default value of the axis variation range. + * + * Gets the axis range assigned by previous calls to hb_subset_input_set_axis_range. + * + * Return value: `true` if a range has been set for this axis tag, `false` otherwise. + * + * XSince: EXPERIMENTAL + **/ +HB_EXTERN hb_bool_t +hb_subset_input_get_axis_range (hb_subset_input_t *input, + hb_tag_t axis_tag, + float *axis_min_value, + float *axis_max_value, + float *axis_def_value) + +{ + Triple* triple; + if (!input->axes_location.has(axis_tag, &triple)) { + return false; + } + + *axis_min_value = triple->minimum; + *axis_def_value = triple->middle; + *axis_max_value = triple->maximum; + return true; +} #endif #endif diff --git a/thirdparty/harfbuzz/src/hb-subset-instancer-iup.cc b/thirdparty/harfbuzz/src/hb-subset-instancer-iup.cc new file mode 100644 index 0000000000..35a964d082 --- /dev/null +++ b/thirdparty/harfbuzz/src/hb-subset-instancer-iup.cc @@ -0,0 +1,532 @@ +/* + * Copyright © 2024 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +#include "hb-subset-instancer-iup.hh" + +/* This file is a straight port of the following: + * + * https://github.com/fonttools/fonttools/blob/main/Lib/fontTools/varLib/iup.py + * + * Where that file returns optimzied deltas vector, we return optimized + * referenced point indices. + */ + +constexpr static unsigned MAX_LOOKBACK = 8; + +static void _iup_contour_bound_forced_set (const hb_array_t<const contour_point_t> contour_points, + const hb_array_t<const int> x_deltas, + const hb_array_t<const int> y_deltas, + hb_set_t& forced_set, /* OUT */ + float tolerance = 0.f) +{ + unsigned len = contour_points.length; + unsigned next_i = 0; + for (int i = len - 1; i >= 0; i--) + { + unsigned last_i = (len + i -1) % len; + for (unsigned j = 0; j < 2; j++) + { + float cj, lcj, ncj; + int dj, ldj, ndj; + if (j == 0) + { + cj = contour_points.arrayZ[i].x; + dj = x_deltas.arrayZ[i]; + lcj = contour_points.arrayZ[last_i].x; + ldj = x_deltas.arrayZ[last_i]; + ncj = contour_points.arrayZ[next_i].x; + ndj = x_deltas.arrayZ[next_i]; + } + else + { + cj = contour_points.arrayZ[i].y; + dj = y_deltas.arrayZ[i]; + lcj = contour_points.arrayZ[last_i].y; + ldj = y_deltas.arrayZ[last_i]; + ncj = contour_points.arrayZ[next_i].y; + ndj = y_deltas.arrayZ[next_i]; + } + + float c1, c2; + int d1, d2; + if (lcj <= ncj) + { + c1 = lcj; + c2 = ncj; + d1 = ldj; + d2 = ndj; + } + else + { + c1 = ncj; + c2 = lcj; + d1 = ndj; + d2 = ldj; + } + + bool force = false; + if (c1 == c2) + { + if (abs (d1 - d2) > tolerance && abs (dj) > tolerance) + force = true; + } + else if (c1 <= cj && cj <= c2) + { + if (!(hb_min (d1, d2) - tolerance <= dj && + dj <= hb_max (d1, d2) + tolerance)) + force = true; + } + else + { + if (d1 != d2) + { + if (cj < c1) + { + if (abs (dj) > tolerance && + abs (dj - d1) > tolerance && + ((dj - tolerance < d1) != (d1 < d2))) + force = true; + } + else + { + if (abs (dj) > tolerance && + abs (dj - d2) > tolerance && + ((d2 < dj + tolerance) != (d1 < d2))) + force = true; + } + } + } + + if (force) + { + forced_set.add (i); + break; + } + } + next_i = i; + } +} + +template <typename T, + hb_enable_if (hb_is_trivially_copyable (T))> +static bool rotate_array (const hb_array_t<const T>& org_array, + int k, + hb_vector_t<T>& out) +{ + unsigned n = org_array.length; + if (!n) return true; + if (unlikely (!out.resize (n, false))) + return false; + + unsigned item_size = hb_static_size (T); + if (k < 0) + k = n - (-k) % n; + else + k %= n; + + hb_memcpy ((void *) out.arrayZ, (const void *) (org_array.arrayZ + n - k), k * item_size); + hb_memcpy ((void *) (out.arrayZ + k), (const void *) org_array.arrayZ, (n - k) * item_size); + return true; +} + +static bool rotate_set (const hb_set_t& org_set, + int k, + unsigned n, + hb_set_t& out) +{ + if (!n) return false; + k %= n; + if (k < 0) + k = n + k; + + if (k == 0) + { + out.set (org_set); + } + else + { + for (auto v : org_set) + out.add ((v + k) % n); + } + return !out.in_error (); +} + +/* Given two reference coordinates (start and end of contour_points array), + * output interpolated deltas for points in between */ +static bool _iup_segment (const hb_array_t<const contour_point_t> contour_points, + const hb_array_t<const int> x_deltas, + const hb_array_t<const int> y_deltas, + const contour_point_t& p1, const contour_point_t& p2, + int p1_dx, int p2_dx, + int p1_dy, int p2_dy, + hb_vector_t<float>& interp_x_deltas, /* OUT */ + hb_vector_t<float>& interp_y_deltas /* OUT */) +{ + unsigned n = contour_points.length; + if (unlikely (!interp_x_deltas.resize (n, false) || + !interp_y_deltas.resize (n, false))) + return false; + + for (unsigned j = 0; j < 2; j++) + { + float x1, x2, d1, d2; + float *out; + if (j == 0) + { + x1 = p1.x; + x2 = p2.x; + d1 = p1_dx; + d2 = p2_dx; + out = interp_x_deltas.arrayZ; + } + else + { + x1 = p1.y; + x2 = p2.y; + d1 = p1_dy; + d2 = p2_dy; + out = interp_y_deltas.arrayZ; + } + + if (x1 == x2) + { + if (d1 == d2) + { + for (unsigned i = 0; i < n; i++) + out[i] = d1; + } + else + { + for (unsigned i = 0; i < n; i++) + out[i] = 0.f; + } + continue; + } + + if (x1 > x2) + { + hb_swap (x1, x2); + hb_swap (d1, d2); + } + + float scale = (d2 - d1) / (x2 - x1); + for (unsigned i = 0; i < n; i++) + { + float x = j == 0 ? contour_points.arrayZ[i].x : contour_points.arrayZ[i].y; + float d; + if (x <= x1) + d = d1; + else if (x >= x2) + d = d2; + else + d = d1 + (x - x1) * scale; + + out[i] = d; + } + } + return true; +} + +static bool _can_iup_in_between (const hb_array_t<const contour_point_t> contour_points, + const hb_array_t<const int> x_deltas, + const hb_array_t<const int> y_deltas, + const contour_point_t& p1, const contour_point_t& p2, + int p1_dx, int p2_dx, + int p1_dy, int p2_dy, + float tolerance) +{ + hb_vector_t<float> interp_x_deltas, interp_y_deltas; + if (!_iup_segment (contour_points, x_deltas, y_deltas, + p1, p2, p1_dx, p2_dx, p1_dy, p2_dy, + interp_x_deltas, interp_y_deltas)) + return false; + + unsigned num = contour_points.length; + + for (unsigned i = 0; i < num; i++) + { + float dx = x_deltas.arrayZ[i] - interp_x_deltas.arrayZ[i]; + float dy = y_deltas.arrayZ[i] - interp_y_deltas.arrayZ[i]; + + if (sqrtf ((float)dx * dx + (float)dy * dy) > tolerance) + return false; + } + return true; +} + +static bool _iup_contour_optimize_dp (const contour_point_vector_t& contour_points, + const hb_vector_t<int>& x_deltas, + const hb_vector_t<int>& y_deltas, + const hb_set_t& forced_set, + float tolerance, + unsigned lookback, + hb_vector_t<unsigned>& costs, /* OUT */ + hb_vector_t<int>& chain /* OUT */) +{ + unsigned n = contour_points.length; + if (unlikely (!costs.resize (n, false) || + !chain.resize (n, false))) + return false; + + lookback = hb_min (lookback, MAX_LOOKBACK); + + for (unsigned i = 0; i < n; i++) + { + unsigned best_cost = (i == 0 ? 1 : costs.arrayZ[i-1] + 1); + + costs.arrayZ[i] = best_cost; + chain.arrayZ[i] = (i == 0 ? -1 : i - 1); + + if (i > 0 && forced_set.has (i - 1)) + continue; + + int lookback_index = hb_max ((int) i - (int) lookback + 1, -1); + for (int j = i - 2; j >= lookback_index; j--) + { + unsigned cost = j == -1 ? 1 : costs.arrayZ[j] + 1; + /* num points between i and j */ + unsigned num_points = i - j - 1; + unsigned p1 = (j == -1 ? n - 1 : j); + if (cost < best_cost && + _can_iup_in_between (contour_points.as_array ().sub_array (j + 1, num_points), + x_deltas.as_array ().sub_array (j + 1, num_points), + y_deltas.as_array ().sub_array (j + 1, num_points), + contour_points.arrayZ[p1], contour_points.arrayZ[i], + x_deltas.arrayZ[p1], x_deltas.arrayZ[i], + y_deltas.arrayZ[p1], y_deltas.arrayZ[i], + tolerance)) + { + best_cost = cost; + costs.arrayZ[i] = best_cost; + chain.arrayZ[i] = j; + } + + if (j > 0 && forced_set.has (j)) + break; + } + } + return true; +} + +static bool _iup_contour_optimize (const hb_array_t<const contour_point_t> contour_points, + const hb_array_t<const int> x_deltas, + const hb_array_t<const int> y_deltas, + hb_array_t<bool> opt_indices, /* OUT */ + float tolerance = 0.f) +{ + unsigned n = contour_points.length; + if (opt_indices.length != n || + x_deltas.length != n || + y_deltas.length != n) + return false; + + bool all_within_tolerance = true; + for (unsigned i = 0; i < n; i++) + { + int dx = x_deltas.arrayZ[i]; + int dy = y_deltas.arrayZ[i]; + if (sqrtf ((float)dx * dx + (float)dy * dy) > tolerance) + { + all_within_tolerance = false; + break; + } + } + + /* If all are within tolerance distance, do nothing, opt_indices is + * initilized to false */ + if (all_within_tolerance) + return true; + + /* If there's exactly one point, return it */ + if (n == 1) + { + opt_indices.arrayZ[0] = true; + return true; + } + + /* If all deltas are exactly the same, return just one (the first one) */ + bool all_deltas_are_equal = true; + for (unsigned i = 1; i < n; i++) + if (x_deltas.arrayZ[i] != x_deltas.arrayZ[0] || + y_deltas.arrayZ[i] != y_deltas.arrayZ[0]) + { + all_deltas_are_equal = false; + break; + } + + if (all_deltas_are_equal) + { + opt_indices.arrayZ[0] = true; + return true; + } + + /* else, solve the general problem using Dynamic Programming */ + hb_set_t forced_set; + _iup_contour_bound_forced_set (contour_points, x_deltas, y_deltas, forced_set, tolerance); + + if (!forced_set.is_empty ()) + { + int k = n - 1 - forced_set.get_max (); + if (k < 0) + return false; + + hb_vector_t<int> rot_x_deltas, rot_y_deltas; + contour_point_vector_t rot_points; + hb_set_t rot_forced_set; + if (!rotate_array (contour_points, k, rot_points) || + !rotate_array (x_deltas, k, rot_x_deltas) || + !rotate_array (y_deltas, k, rot_y_deltas) || + !rotate_set (forced_set, k, n, rot_forced_set)) + return false; + + hb_vector_t<unsigned> costs; + hb_vector_t<int> chain; + + if (!_iup_contour_optimize_dp (rot_points, rot_x_deltas, rot_y_deltas, + rot_forced_set, tolerance, n, + costs, chain)) + return false; + + hb_set_t solution; + int index = n - 1; + while (index != -1) + { + solution.add (index); + index = chain.arrayZ[index]; + } + + if (solution.is_empty () || + forced_set.get_population () > solution.get_population ()) + return false; + + for (unsigned i : solution) + opt_indices.arrayZ[i] = true; + + hb_vector_t<bool> rot_indices; + const hb_array_t<const bool> opt_indices_array (opt_indices.arrayZ, opt_indices.length); + rotate_array (opt_indices_array, -k, rot_indices); + + for (unsigned i = 0; i < n; i++) + opt_indices.arrayZ[i] = rot_indices.arrayZ[i]; + } + else + { + hb_vector_t<int> repeat_x_deltas, repeat_y_deltas; + contour_point_vector_t repeat_points; + + if (unlikely (!repeat_x_deltas.resize (n * 2, false) || + !repeat_y_deltas.resize (n * 2, false) || + !repeat_points.resize (n * 2, false))) + return false; + + unsigned contour_point_size = hb_static_size (contour_point_t); + for (unsigned i = 0; i < n; i++) + { + hb_memcpy ((void *) repeat_x_deltas.arrayZ, (const void *) x_deltas.arrayZ, n * sizeof (float)); + hb_memcpy ((void *) (repeat_x_deltas.arrayZ + n), (const void *) x_deltas.arrayZ, n * sizeof (float)); + + hb_memcpy ((void *) repeat_y_deltas.arrayZ, (const void *) y_deltas.arrayZ, n * sizeof (float)); + hb_memcpy ((void *) (repeat_y_deltas.arrayZ + n), (const void *) y_deltas.arrayZ, n * sizeof (float)); + + hb_memcpy ((void *) repeat_points.arrayZ, (const void *) contour_points.arrayZ, n * contour_point_size); + hb_memcpy ((void *) (repeat_points.arrayZ + n), (const void *) contour_points.arrayZ, n * contour_point_size); + } + + hb_vector_t<unsigned> costs; + hb_vector_t<int> chain; + if (!_iup_contour_optimize_dp (repeat_points, repeat_x_deltas, repeat_y_deltas, + forced_set, tolerance, n, + costs, chain)) + return false; + + unsigned best_cost = n + 1; + int len = costs.length; + hb_set_t best_sol; + for (int start = n - 1; start < len; start++) + { + hb_set_t solution; + int i = start; + int lookback = start - (int) n; + while (i > lookback) + { + solution.add (i % n); + i = chain.arrayZ[i]; + } + if (i == lookback) + { + unsigned cost_i = i < 0 ? 0 : costs.arrayZ[i]; + unsigned cost = costs.arrayZ[start] - cost_i; + if (cost <= best_cost) + { + best_sol.set (solution); + best_cost = cost; + } + } + } + + for (unsigned i = 0; i < n; i++) + if (best_sol.has (i)) + opt_indices.arrayZ[i] = true; + } + return true; +} + +bool iup_delta_optimize (const contour_point_vector_t& contour_points, + const hb_vector_t<int>& x_deltas, + const hb_vector_t<int>& y_deltas, + hb_vector_t<bool>& opt_indices, /* OUT */ + float tolerance) +{ + if (!opt_indices.resize (contour_points.length)) + return false; + + hb_vector_t<unsigned> end_points; + unsigned count = contour_points.length; + if (unlikely (!end_points.alloc (count))) + return false; + + for (unsigned i = 0; i < count - 4; i++) + if (contour_points.arrayZ[i].is_end_point) + end_points.push (i); + + /* phantom points */ + for (unsigned i = count - 4; i < count; i++) + end_points.push (i); + + if (end_points.in_error ()) return false; + + unsigned start = 0; + for (unsigned end : end_points) + { + unsigned len = end - start + 1; + if (!_iup_contour_optimize (contour_points.as_array ().sub_array (start, len), + x_deltas.as_array ().sub_array (start, len), + y_deltas.as_array ().sub_array (start, len), + opt_indices.as_array ().sub_array (start, len), + tolerance)) + return false; + start = end + 1; + } + return true; +} diff --git a/thirdparty/harfbuzz/src/hb-subset-instancer-iup.hh b/thirdparty/harfbuzz/src/hb-subset-instancer-iup.hh new file mode 100644 index 0000000000..7eac5935a4 --- /dev/null +++ b/thirdparty/harfbuzz/src/hb-subset-instancer-iup.hh @@ -0,0 +1,37 @@ +/* + * Copyright © 2024 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +#ifndef HB_SUBSET_INSTANCER_IUP_HH +#define HB_SUBSET_INSTANCER_IUP_HH + +#include "hb-subset-plan.hh" +/* given contour points and deltas, optimize a set of referenced points within error + * tolerance. Returns optimized referenced point indices */ +HB_INTERNAL bool iup_delta_optimize (const contour_point_vector_t& contour_points, + const hb_vector_t<int>& x_deltas, + const hb_vector_t<int>& y_deltas, + hb_vector_t<bool>& opt_indices, /* OUT */ + float tolerance = 0.f); + +#endif /* HB_SUBSET_INSTANCER_IUP_HH */ diff --git a/thirdparty/harfbuzz/src/hb-subset-instancer-solver.cc b/thirdparty/harfbuzz/src/hb-subset-instancer-solver.cc index 4876bc4379..70783c0a0d 100644 --- a/thirdparty/harfbuzz/src/hb-subset-instancer-solver.cc +++ b/thirdparty/harfbuzz/src/hb-subset-instancer-solver.cc @@ -256,7 +256,10 @@ _solve (Triple tent, Triple axisLimit, bool negative = false) */ float newUpper = peak + (1 - gain) * (upper - peak); assert (axisMax <= newUpper); // Because outGain > gain - if (newUpper <= axisDef + (axisMax - axisDef) * 2) + /* Disabled because ots doesn't like us: + * https://github.com/fonttools/fonttools/issues/3350 */ + + if (false && (newUpper <= axisDef + (axisMax - axisDef) * 2)) { upper = newUpper; if (!negative && axisDef + (axisMax - axisDef) * MAX_F2DOT14 < upper) diff --git a/thirdparty/harfbuzz/src/hb-subset-plan-member-list.hh b/thirdparty/harfbuzz/src/hb-subset-plan-member-list.hh index 71da80e387..74416b92f9 100644 --- a/thirdparty/harfbuzz/src/hb-subset-plan-member-list.hh +++ b/thirdparty/harfbuzz/src/hb-subset-plan-member-list.hh @@ -140,6 +140,15 @@ HB_SUBSET_PLAN_MEMBER (mutable hb_vector_t<unsigned>, bounds_height_vec) //map: new_gid -> contour points vector HB_SUBSET_PLAN_MEMBER (mutable hb_hashmap_t E(<hb_codepoint_t, contour_point_vector_t>), new_gid_contour_points_map) +//new gids set for composite glyphs +HB_SUBSET_PLAN_MEMBER (hb_set_t, composite_new_gids) + +//Old BASE item variation index -> (New varidx, 0) mapping +HB_SUBSET_PLAN_MEMBER (hb_hashmap_t E(<unsigned, hb_pair_t E(<unsigned, int>)>), base_variation_idx_map) + +//BASE table varstore retained varidx mapping +HB_SUBSET_PLAN_MEMBER (hb_vector_t<hb_inc_bimap_t>, base_varstore_inner_maps) + #ifdef HB_EXPERIMENTAL_API // name table overrides map: hb_ot_name_record_ids_t-> name string new value or // None to indicate should remove diff --git a/thirdparty/harfbuzz/src/hb-subset-plan.cc b/thirdparty/harfbuzz/src/hb-subset-plan.cc index 5786223196..068fddaedd 100644 --- a/thirdparty/harfbuzz/src/hb-subset-plan.cc +++ b/thirdparty/harfbuzz/src/hb-subset-plan.cc @@ -32,6 +32,7 @@ #include "hb-ot-cmap-table.hh" #include "hb-ot-glyf-table.hh" +#include "hb-ot-layout-base-table.hh" #include "hb-ot-layout-gdef-table.hh" #include "hb-ot-layout-gpos-table.hh" #include "hb-ot-layout-gsub-table.hh" @@ -431,6 +432,52 @@ _collect_layout_variation_indices (hb_subset_plan_t* plan) gdef.destroy (); gpos.destroy (); } + +#ifndef HB_NO_BASE +/* used by BASE table only, delta is always set to 0 in the output map */ +static inline void +_remap_variation_indices (const hb_set_t& indices, + unsigned subtable_count, + hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>>& variation_idx_delta_map /* OUT */) +{ + unsigned new_major = 0, new_minor = 0; + unsigned last_major = (indices.get_min ()) >> 16; + for (unsigned idx : indices) + { + uint16_t major = idx >> 16; + if (major >= subtable_count) break; + if (major != last_major) + { + new_minor = 0; + ++new_major; + } + + unsigned new_idx = (new_major << 16) + new_minor; + variation_idx_delta_map.set (idx, hb_pair_t<unsigned, int> (new_idx, 0)); + ++new_minor; + last_major = major; + } +} + +static inline void +_collect_base_variation_indices (hb_subset_plan_t* plan) +{ + hb_blob_ptr_t<OT::BASE> base = plan->source_table<OT::BASE> (); + if (!base->has_var_store ()) + { + base.destroy (); + return; + } + + hb_set_t varidx_set; + base->collect_variation_indices (plan, varidx_set); + unsigned subtable_count = base->get_var_store ().get_sub_table_count (); + base.destroy (); + + _remap_variation_indices (varidx_set, subtable_count, plan->base_variation_idx_map); + _generate_varstore_inner_maps (varidx_set, subtable_count, plan->base_varstore_inner_maps); +} +#endif #endif static inline void @@ -994,8 +1041,8 @@ _update_instance_metrics_map_from_cff2 (hb_subset_plan_t *plan) OT::cff2::accelerator_t cff2 (plan->source); if (!cff2.is_valid ()) return; - hb_font_t *font = nullptr; - if (unlikely (!plan->check_success (font = _get_hb_font_with_variations (plan)))) + hb_font_t *font = _get_hb_font_with_variations (plan); + if (unlikely (!plan->check_success (font != nullptr))) { hb_font_destroy (font); return; @@ -1073,8 +1120,8 @@ _update_instance_metrics_map_from_cff2 (hb_subset_plan_t *plan) static bool _get_instance_glyphs_contour_points (hb_subset_plan_t *plan) { - /* contour_points vector only needed for updating gvar table (infer delta) - * during partial instancing */ + /* contour_points vector only needed for updating gvar table (infer delta and + * iup delta optimization) during partial instancing */ if (plan->user_axes_location.is_empty () || plan->all_axes_pinned) return true; @@ -1092,10 +1139,17 @@ _get_instance_glyphs_contour_points (hb_subset_plan_t *plan) } hb_codepoint_t old_gid = _.second; - if (unlikely (!glyf.glyph_for_gid (old_gid).get_all_points_without_var (plan->source, all_points))) + auto glyph = glyf.glyph_for_gid (old_gid); + if (unlikely (!glyph.get_all_points_without_var (plan->source, all_points))) return false; if (unlikely (!plan->new_gid_contour_points_map.set (new_gid, all_points))) return false; + +#ifdef HB_EXPERIMENTAL_API + /* composite new gids are only needed by iup delta optimization */ + if ((plan->flags & HB_SUBSET_FLAGS_OPTIMIZE_IUP_DELTAS) && glyph.is_composite ()) + plan->composite_new_gids.add (new_gid); +#endif } return true; } @@ -1205,6 +1259,13 @@ hb_subset_plan_t::hb_subset_plan_t (hb_face_t *face, if (!drop_tables.has (HB_OT_TAG_GDEF)) _remap_used_mark_sets (this, used_mark_sets_map); +#ifndef HB_NO_VAR +#ifndef HB_NO_BASE + if (!drop_tables.has (HB_OT_TAG_BASE)) + _collect_base_variation_indices (this); +#endif +#endif + if (unlikely (in_error ())) return; diff --git a/thirdparty/harfbuzz/src/hb-subset-plan.hh b/thirdparty/harfbuzz/src/hb-subset-plan.hh index 1f19a58c1e..19a9fa6918 100644 --- a/thirdparty/harfbuzz/src/hb-subset-plan.hh +++ b/thirdparty/harfbuzz/src/hb-subset-plan.hh @@ -78,6 +78,13 @@ struct contour_point_t y = x * matrix[1] + y * matrix[3]; x = x_; } + + void add_delta (float delta_x, float delta_y) + { + x += delta_x; + y += delta_y; + } + HB_ALWAYS_INLINE void translate (const contour_point_t &p) { x += p.x; y += p.y; } @@ -99,6 +106,22 @@ struct contour_point_vector_t : hb_vector_t<contour_point_t> unsigned count = a.length; hb_memcpy (arrayZ, a.arrayZ, count * sizeof (arrayZ[0])); } + + bool add_deltas (const hb_vector_t<float> deltas_x, + const hb_vector_t<float> deltas_y, + const hb_vector_t<bool> indices) + { + if (indices.length != deltas_x.length || + indices.length != deltas_y.length) + return false; + + for (unsigned i = 0; i < indices.length; i++) + { + if (!indices.arrayZ[i]) continue; + arrayZ[i].add_delta (deltas_x.arrayZ[i], deltas_y.arrayZ[i]); + } + return true; + } }; namespace OT { @@ -147,7 +170,7 @@ struct hb_subset_plan_t bool gsub_insert_catch_all_feature_variation_rec; bool gpos_insert_catch_all_feature_variation_rec; - // whether GDEF VarStore is retained + // whether GDEF ItemVariationStore is retained mutable bool has_gdef_varstore; #define HB_SUBSET_PLAN_MEMBER(Type, Name) Type Name; diff --git a/thirdparty/harfbuzz/src/hb-subset.cc b/thirdparty/harfbuzz/src/hb-subset.cc index 06e77dd8eb..f10ef54dbd 100644 --- a/thirdparty/harfbuzz/src/hb-subset.cc +++ b/thirdparty/harfbuzz/src/hb-subset.cc @@ -48,6 +48,7 @@ #include "hb-ot-cff2-table.hh" #include "hb-ot-vorg-table.hh" #include "hb-ot-name-table.hh" +#include "hb-ot-layout-base-table.hh" #include "hb-ot-layout-gsub-table.hh" #include "hb-ot-layout-gpos-table.hh" #include "hb-ot-var-avar-table.hh" @@ -503,6 +504,7 @@ _subset_table (hb_subset_plan_t *plan, case HB_OT_TAG_CBLC: return _subset<const OT::CBLC> (plan, buf); case HB_OT_TAG_CBDT: return true; /* skip CBDT, handled by CBLC */ case HB_OT_TAG_MATH: return _subset<const OT::MATH> (plan, buf); + case HB_OT_TAG_BASE: return _subset<const OT::BASE> (plan, buf); #ifndef HB_NO_SUBSET_CFF case HB_OT_TAG_CFF1: return _subset<const OT::cff1> (plan, buf); @@ -548,6 +550,7 @@ _subset_table (hb_subset_plan_t *plan, } #endif return _passthrough (plan, tag); + default: if (plan->flags & HB_SUBSET_FLAGS_PASSTHROUGH_UNRECOGNIZED) return _passthrough (plan, tag); diff --git a/thirdparty/harfbuzz/src/hb-subset.h b/thirdparty/harfbuzz/src/hb-subset.h index d79e7f762a..73dcae4660 100644 --- a/thirdparty/harfbuzz/src/hb-subset.h +++ b/thirdparty/harfbuzz/src/hb-subset.h @@ -76,6 +76,8 @@ typedef struct hb_subset_plan_t hb_subset_plan_t; * @HB_SUBSET_FLAGS_IFTB_REQUIREMENTS: If set enforce requirements on the output subset * to allow it to be used with incremental font transfer IFTB patches. Primarily, * this forces all outline data to use long (32 bit) offsets. Since: EXPERIMENTAL + * @HB_SUBSET_FLAGS_OPTIMIZE_IUP_DELTAS: If set perform IUP delta optimization on the + * remaining gvar table's deltas. Since: EXPERIMENTAL * * List of boolean properties that can be configured on the subset input. * @@ -95,6 +97,7 @@ typedef enum { /*< flags >*/ HB_SUBSET_FLAGS_NO_LAYOUT_CLOSURE = 0x00000200u, #ifdef HB_EXPERIMENTAL_API HB_SUBSET_FLAGS_IFTB_REQUIREMENTS = 0x00000400u, + HB_SUBSET_FLAGS_OPTIMIZE_IUP_DELTAS = 0x00000800u, #endif } hb_subset_flags_t; @@ -171,6 +174,10 @@ hb_subset_input_set_flags (hb_subset_input_t *input, unsigned value); HB_EXTERN hb_bool_t +hb_subset_input_pin_all_axes_to_default (hb_subset_input_t *input, + hb_face_t *face); + +HB_EXTERN hb_bool_t hb_subset_input_pin_axis_to_default (hb_subset_input_t *input, hb_face_t *face, hb_tag_t axis_tag); @@ -183,12 +190,19 @@ hb_subset_input_pin_axis_location (hb_subset_input_t *input, #ifdef HB_EXPERIMENTAL_API HB_EXTERN hb_bool_t +hb_subset_input_get_axis_range (hb_subset_input_t *input, + hb_tag_t axis_tag, + float *axis_min_value, + float *axis_max_value, + float *axis_def_value); + +HB_EXTERN hb_bool_t hb_subset_input_set_axis_range (hb_subset_input_t *input, hb_face_t *face, hb_tag_t axis_tag, float axis_min_value, float axis_max_value, - float *axis_def_value); + float axis_def_value); HB_EXTERN hb_bool_t hb_subset_input_override_name_table (hb_subset_input_t *input, diff --git a/thirdparty/harfbuzz/src/hb-vector.hh b/thirdparty/harfbuzz/src/hb-vector.hh index dfe1b7d1c7..c0cc7063ff 100644 --- a/thirdparty/harfbuzz/src/hb-vector.hh +++ b/thirdparty/harfbuzz/src/hb-vector.hh @@ -78,7 +78,7 @@ struct hb_vector_t if (unlikely (in_error ())) return; copy_array (o); } - hb_vector_t (hb_vector_t &&o) + hb_vector_t (hb_vector_t &&o) noexcept { allocated = o.allocated; length = o.length; @@ -122,7 +122,7 @@ struct hb_vector_t resize (0); } - friend void swap (hb_vector_t& a, hb_vector_t& b) + friend void swap (hb_vector_t& a, hb_vector_t& b) noexcept { hb_swap (a.allocated, b.allocated); hb_swap (a.length, b.length); @@ -139,7 +139,7 @@ struct hb_vector_t return *this; } - hb_vector_t& operator = (hb_vector_t &&o) + hb_vector_t& operator = (hb_vector_t &&o) noexcept { hb_swap (*this, o); return *this; diff --git a/thirdparty/harfbuzz/src/hb-version.h b/thirdparty/harfbuzz/src/hb-version.h index b08dd1f09f..68681874ca 100644 --- a/thirdparty/harfbuzz/src/hb-version.h +++ b/thirdparty/harfbuzz/src/hb-version.h @@ -47,7 +47,7 @@ HB_BEGIN_DECLS * * The minor component of the library version available at compile-time. */ -#define HB_VERSION_MINOR 3 +#define HB_VERSION_MINOR 4 /** * HB_VERSION_MICRO: * @@ -60,7 +60,7 @@ HB_BEGIN_DECLS * * A string literal containing the library version available at compile-time. */ -#define HB_VERSION_STRING "8.3.0" +#define HB_VERSION_STRING "8.4.0" /** * HB_VERSION_ATLEAST: diff --git a/thirdparty/harfbuzz/src/hb.hh b/thirdparty/harfbuzz/src/hb.hh index 972608d6a3..0ceeb99f50 100644 --- a/thirdparty/harfbuzz/src/hb.hh +++ b/thirdparty/harfbuzz/src/hb.hh @@ -64,6 +64,7 @@ #pragma GCC diagnostic error "-Wbitwise-instead-of-logical" #pragma GCC diagnostic error "-Wcast-align" #pragma GCC diagnostic error "-Wcast-function-type" +#pragma GCC diagnostic error "-Wcast-function-type-strict" #pragma GCC diagnostic error "-Wconstant-conversion" #pragma GCC diagnostic error "-Wcomma" #pragma GCC diagnostic error "-Wdelete-non-virtual-dtor" @@ -177,6 +178,11 @@ #define HB_EXTERN __declspec (dllexport) extern #endif +// https://github.com/harfbuzz/harfbuzz/pull/4619 +#ifndef __STDC_FORMAT_MACROS +#define __STDC_FORMAT_MACROS 1 +#endif + #include "hb.h" #define HB_H_IN #include "hb-ot.h" @@ -212,6 +218,12 @@ #include <winapifamily.h> #endif +#ifndef PRId32 +# define PRId32 "d" +# define PRIu32 "u" +# define PRIx32 "x" +#endif + #define HB_PASTE1(a,b) a##b #define HB_PASTE(a,b) HB_PASTE1(a,b) diff --git a/thirdparty/libktx/lib/dfdutils/createdfd.c b/thirdparty/libktx/lib/dfdutils/createdfd.c index 2a5af00c7e..eb64204189 100644 --- a/thirdparty/libktx/lib/dfdutils/createdfd.c +++ b/thirdparty/libktx/lib/dfdutils/createdfd.c @@ -94,6 +94,10 @@ static uint32_t setChannelFlags(uint32_t channel, enum VkSuffix suffix) channel |= KHR_DF_SAMPLE_DATATYPE_LINEAR; } break; + case s_S10_5: + channel |= + KHR_DF_SAMPLE_DATATYPE_SIGNED; + break; } return channel; } @@ -109,7 +113,6 @@ static void writeSample(uint32_t *DFD, int sampleNo, int channel, float f; } lower, upper; uint32_t *sample = DFD + 1 + KHR_DF_WORD_SAMPLESTART + sampleNo * KHR_DF_WORD_SAMPLEWORDS; - if (channel == 3) channel = KHR_DF_CHANNEL_RGBSDA_ALPHA; if (channel == 3) channel = KHR_DF_CHANNEL_RGBSDA_ALPHA; channel = setChannelFlags(channel, suffix); @@ -159,6 +162,10 @@ static void writeSample(uint32_t *DFD, int sampleNo, int channel, upper.f = 1.0f; lower.f = 0.0f; break; + case s_S10_5: + assert(bits == 16 && "Format with this suffix must be 16 bits per channel."); + upper.i = 32; + lower.i = ~upper.i + 1; // -32 } sample[KHR_DF_SAMPLEWORD_SAMPLELOWER] = lower.i; sample[KHR_DF_SAMPLEWORD_SAMPLEUPPER] = upper.i; @@ -230,8 +237,9 @@ uint32_t *createDFDUnpacked(int bigEndian, int numChannels, int bytes, * @param bits[] An array of length numChannels. * Each entry is the number of bits composing the channel, in * order starting at bit 0 of the packed type. - * @param paddings[] An array of length numChannels. - * Each entry is the number of padding bits after each channel. + * @param shiftBits[] An array of length numChannels. + * Each entry is the number of bits each channel is shifted + * and thus padded with insignificant bits. * @param channels[] An array of length numChannels. * Each entry enumerates the channel type: 0 = red, 1 = green, * 2 = blue, 15 = alpha, in order starting at bit 0 of the @@ -243,9 +251,9 @@ uint32_t *createDFDUnpacked(int bigEndian, int numChannels, int bytes, * @return A data format descriptor in malloc'd data. The caller is responsible * for freeing the descriptor. **/ -uint32_t *createDFDPackedPadded(int bigEndian, int numChannels, - int bits[], int paddings[], int channels[], - enum VkSuffix suffix) +uint32_t *createDFDPackedShifted(int bigEndian, int numChannels, + int bits[], int shiftBits[], int channels[], + enum VkSuffix suffix) { uint32_t *DFD = 0; if (numChannels == 6) { @@ -291,17 +299,18 @@ uint32_t *createDFDPackedPadded(int bigEndian, int numChannels, int sampleCounter; for (channelCounter = 0; channelCounter < numChannels; ++channelCounter) { beChannelStart[channelCounter] = totalBits; - totalBits += bits[channelCounter] + paddings[channelCounter]; + totalBits += shiftBits[channelCounter] + bits[channelCounter]; } BEMask = (totalBits - 1) & 0x18; for (channelCounter = 0; channelCounter < numChannels; ++channelCounter) { + bitOffset += shiftBits[channelCounter]; bitChannel[bitOffset ^ BEMask] = channelCounter; if (((bitOffset + bits[channelCounter] - 1) & ~7) != (bitOffset & ~7)) { /* Continuation sample */ bitChannel[((bitOffset + bits[channelCounter] - 1) & ~7) ^ BEMask] = channelCounter; numSamples++; } - bitOffset += bits[channelCounter] + paddings[channelCounter]; + bitOffset += bits[channelCounter]; } DFD = writeHeader(numSamples, totalBits >> 3, suffix, i_COLOR); @@ -343,16 +352,17 @@ uint32_t *createDFDPackedPadded(int bigEndian, int numChannels, int totalBits = 0; int bitOffset = 0; for (sampleCounter = 0; sampleCounter < numChannels; ++sampleCounter) { - totalBits += bits[sampleCounter] + paddings[sampleCounter]; + totalBits += shiftBits[sampleCounter] + bits[sampleCounter]; } /* One sample per channel */ DFD = writeHeader(numChannels, totalBits >> 3, suffix, i_COLOR); for (sampleCounter = 0; sampleCounter < numChannels; ++sampleCounter) { + bitOffset += shiftBits[sampleCounter]; writeSample(DFD, sampleCounter, channels[sampleCounter], bits[sampleCounter], bitOffset, 1, 1, suffix); - bitOffset += bits[sampleCounter] + paddings[sampleCounter]; + bitOffset += bits[sampleCounter]; } } return DFD; @@ -383,12 +393,12 @@ uint32_t *createDFDPacked(int bigEndian, int numChannels, int bits[], int channels[], enum VkSuffix suffix) { assert(numChannels <= 6); - int paddings[] = {0, 0, 0, 0, 0, 0}; - return createDFDPackedPadded(bigEndian, numChannels, bits, paddings, channels, suffix); + int shiftBits[] = {0, 0, 0, 0, 0, 0}; + return createDFDPackedShifted(bigEndian, numChannels, bits, shiftBits, channels, suffix); } uint32_t *createDFD422(int bigEndian, int numSamples, - int bits[], int paddings[], int channels[], + int bits[], int shiftBits[], int channels[], int position_xs[], int position_ys[], enum VkSuffix suffix) { assert(!bigEndian); (void) bigEndian; @@ -396,7 +406,7 @@ uint32_t *createDFD422(int bigEndian, int numSamples, int totalBits = 0; for (int i = 0; i < numSamples; ++i) - totalBits += bits[i] + paddings[i]; + totalBits += shiftBits[i] + bits[i]; assert(totalBits % 8 == 0); uint32_t BDFDSize = sizeof(uint32_t) * (KHR_DF_WORD_SAMPLESTART + numSamples * KHR_DF_WORD_SAMPLEWORDS); @@ -428,6 +438,7 @@ uint32_t *createDFD422(int bigEndian, int numSamples, int bitOffset = 0; for (int i = 0; i < numSamples; ++i) { + bitOffset += shiftBits[i]; KHR_DFDSETSVAL(BDFD, i, BITOFFSET, bitOffset); KHR_DFDSETSVAL(BDFD, i, BITLENGTH, bits[i] - 1); KHR_DFDSETSVAL(BDFD, i, CHANNELID, channels[i]); @@ -438,7 +449,7 @@ uint32_t *createDFD422(int bigEndian, int numSamples, KHR_DFDSETSVAL(BDFD, i, SAMPLEPOSITION3, 0); KHR_DFDSETSVAL(BDFD, i, SAMPLELOWER, 0); KHR_DFDSETSVAL(BDFD, i, SAMPLEUPPER, (1u << bits[i]) - 1u); - bitOffset += bits[i] + paddings[i]; + bitOffset += bits[i]; } return DFD; diff --git a/thirdparty/libktx/lib/dfdutils/dfd.h b/thirdparty/libktx/lib/dfdutils/dfd.h index 7f1fb74a6b..756490fc82 100644 --- a/thirdparty/libktx/lib/dfdutils/dfd.h +++ b/thirdparty/libktx/lib/dfdutils/dfd.h @@ -35,7 +35,8 @@ enum VkSuffix { s_SINT, /*!< Signed integer format. */ s_SFLOAT, /*!< Signed float format. */ s_UFLOAT, /*!< Unsigned float format. */ - s_SRGB /*!< sRGB normalized format. */ + s_SRGB, /*!< sRGB normalized format. */ + s_S10_5 /*!< 2's complement fixed-point; 5 fractional bits. */ }; /** Compression scheme, in Vulkan terms. */ @@ -68,15 +69,16 @@ typedef unsigned int uint32_t; #endif uint32_t* vk2dfd(enum VkFormat format); +enum VkFormat dfd2vk(uint32_t* dfd); /* Create a Data Format Descriptor for an unpacked format. */ uint32_t *createDFDUnpacked(int bigEndian, int numChannels, int bytes, int redBlueSwap, enum VkSuffix suffix); /* Create a Data Format Descriptor for a packed padded format. */ -uint32_t *createDFDPackedPadded(int bigEndian, int numChannels, - int bits[], int paddings[], int channels[], - enum VkSuffix suffix); +uint32_t *createDFDPackedShifted(int bigEndian, int numChannels, + int bits[], int shiftBits[], + int channels[], enum VkSuffix suffix); /* Create a Data Format Descriptor for a packed format. */ uint32_t *createDFDPacked(int bigEndian, int numChannels, @@ -85,7 +87,7 @@ uint32_t *createDFDPacked(int bigEndian, int numChannels, /* Create a Data Format Descriptor for a 4:2:2 format. */ uint32_t *createDFD422(int bigEndian, int numChannels, - int bits[], int paddings[], int channels[], + int bits[], int shiftBits[], int channels[], int position_xs[], int position_ys[], enum VkSuffix suffix); @@ -111,10 +113,11 @@ enum InterpretDFDResult { i_SRGB_FORMAT_BIT = 1u << 2u, /*!< sRGB transfer function. */ i_NORMALIZED_FORMAT_BIT = 1u << 3u, /*!< Normalized (UNORM or SNORM). */ i_SIGNED_FORMAT_BIT = 1u << 4u, /*!< Format is signed. */ - i_FLOAT_FORMAT_BIT = 1u << 5u, /*!< Format is floating point. */ - i_COMPRESSED_FORMAT_BIT = 1u << 6u, /*!< Format is block compressed (422). */ - i_YUVSDA_FORMAT_BIT = 1u << 7u, /*!< Color model is YUVSDA. */ - i_UNSUPPORTED_ERROR_BIT = 1u << 8u, /*!< Format not successfully interpreted. */ + i_FIXED_FORMAT_BIT = 1u << 5u, /*!< Format is a fixed-point representation. */ + i_FLOAT_FORMAT_BIT = 1u << 6u, /*!< Format is floating point. */ + i_COMPRESSED_FORMAT_BIT = 1u << 7u, /*!< Format is block compressed (422). */ + i_YUVSDA_FORMAT_BIT = 1u << 8u, /*!< Color model is YUVSDA. */ + i_UNSUPPORTED_ERROR_BIT = 1u << 9u, /*!< Format not successfully interpreted. */ /** "NONTRIVIAL_ENDIANNESS" means not big-endian, not little-endian * (a channel has bits that are not consecutive in either order). **/ i_UNSUPPORTED_NONTRIVIAL_ENDIANNESS = i_UNSUPPORTED_ERROR_BIT, @@ -198,9 +201,12 @@ getDFDComponentInfoUnpacked(const uint32_t* DFD, uint32_t* numComponents, /* Return the number of components described by a DFD. */ uint32_t getDFDNumComponents(const uint32_t* DFD); -/* Recreate and return the value of bytesPlane0 as it should be for the data +/* Reconstruct and return the value of bytesPlane0 as it should be for the data * post-inflation from variable-rate compression. */ +uint32_t +reconstructDFDBytesPlane0FromSamples(const uint32_t* DFD); +/* Deprecated. For backward compatibility. */ void recreateBytesPlane0FromSampleInfo(const uint32_t* DFD, uint32_t* bytesPlane0); diff --git a/thirdparty/libktx/lib/dfdutils/dfd2vk.inl b/thirdparty/libktx/lib/dfdutils/dfd2vk.inl index 8b4de41597..a616566c74 100644 --- a/thirdparty/libktx/lib/dfdutils/dfd2vk.inl +++ b/thirdparty/libktx/lib/dfdutils/dfd2vk.inl @@ -4,12 +4,20 @@ /***************************** Do not edit. ***************************** Automatically generated by makedfd2vk.pl. *************************************************************************/ -if (KHR_DFDVAL(dfd + 1, MODEL) == KHR_DF_MODEL_RGBSDA) { +if (KHR_DFDVAL(dfd + 1, MODEL) == KHR_DF_MODEL_RGBSDA || KHR_DFDVAL(dfd + 1, MODEL) == KHR_DF_MODEL_YUVSDA) { enum InterpretDFDResult r; InterpretedDFDChannel R = {0,0}; InterpretedDFDChannel G = {0,0}; InterpretedDFDChannel B = {0,0}; InterpretedDFDChannel A = {0,0}; + /* interpretDFD channel overloadings for YUVSDA formats. These are + * different from the mapping used by Vulkan. */ + #define Y1 R + #define Y2 A + #define CB G + #define U G + #define CR B + #define V B uint32_t wordBytes; /* Special case exponent format */ @@ -44,8 +52,17 @@ if (KHR_DFDVAL(dfd + 1, MODEL) == KHR_DF_MODEL_RGBSDA) { else if (wordBytes == 2) { /* PACK16 */ if (A.size == 4) { if (R.offset == 12) return VK_FORMAT_R4G4B4A4_UNORM_PACK16; - else return VK_FORMAT_B4G4R4A4_UNORM_PACK16; - } else if (A.size == 0) { /* Three channels */ + else if (B.offset == 12) return VK_FORMAT_B4G4R4A4_UNORM_PACK16; + else if (A.offset == 12) { + if (R.offset == 8) return VK_FORMAT_A4R4G4B4_UNORM_PACK16; + else return VK_FORMAT_A4B4G4R4_UNORM_PACK16; + } + } else if (G.size == 0 && B.size == 0 && A.size == 0) { /* One channel */ + if (R.size == 10) + return VK_FORMAT_R10X6_UNORM_PACK16; + else if (R.size ==12) + return VK_FORMAT_R12X4_UNORM_PACK16; + } else if (A.size == 0) { /* Three channels */ if (B.offset == 0) return VK_FORMAT_R5G6B5_UNORM_PACK16; else return VK_FORMAT_B5G6R5_UNORM_PACK16; } else { /* Four channels, one-bit alpha */ @@ -54,7 +71,7 @@ if (KHR_DFDVAL(dfd + 1, MODEL) == KHR_DF_MODEL_RGBSDA) { if (B.offset == 10) return VK_FORMAT_A1B5G5R5_UNORM_PACK16_KHR; return VK_FORMAT_B5G5R5A1_UNORM_PACK16; } - } else if (wordBytes == 4) { /* PACK32 */ + } else if (wordBytes == 4) { /* PACK32 or 2PACK16 */ if (A.size == 8) { if ((r & i_SRGB_FORMAT_BIT)) return VK_FORMAT_A8B8G8R8_SRGB_PACK32; if ((r & i_NORMALIZED_FORMAT_BIT) && !(r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_A8B8G8R8_UNORM_PACK32; @@ -71,133 +88,171 @@ if (KHR_DFDVAL(dfd + 1, MODEL) == KHR_DF_MODEL_RGBSDA) { if ((r & i_NORMALIZED_FORMAT_BIT) && (r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_A2B10G10R10_SNORM_PACK32; if (!(r & i_NORMALIZED_FORMAT_BIT) && !(r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_A2B10G10R10_UINT_PACK32; if (!(r & i_NORMALIZED_FORMAT_BIT) && (r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_A2B10G10R10_SINT_PACK32; - } else if (R.size == 11) return VK_FORMAT_B10G11R11_UFLOAT_PACK32; + } else if (R.size == 11) { + return VK_FORMAT_B10G11R11_UFLOAT_PACK32; + } else if (R.size == 10 && G.size == 10 && B.size == 0) { + return VK_FORMAT_R10X6G10X6_UNORM_2PACK16; + } else if (R.size == 12 && G.size == 12 && B.size == 0) { + return VK_FORMAT_R12X4G12X4_UNORM_2PACK16; + } + } else if (wordBytes == 8) { /* 4PACK16 */ + if (r & i_YUVSDA_FORMAT_BIT) { + /* In Vulkan G = Y, R = Cr, B = Cb. */ + if (Y1.size == 10 && Y1.offset == 6 && Y2.size == 10 && Y2.offset == 38) + return VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16; + if (Y1.size == 10 && Y1.offset == 22 && Y2.size == 10 && Y2.offset == 54) + return VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16; + if (Y1.size == 12 && Y1.offset == 4 && Y2.size == 12 && Y2.offset == 36) + return VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16; + if (Y1.size == 12 && Y1.offset == 20 && Y2.size == 12 && Y2.offset == 52) + return VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16; + } else { + if (R.size == 10) + return VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16; + else if (R.size == 12) + return VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16; + } } } else { /* Not a packed format */ - if (wordBytes == 1) { - if (A.size > 8 && R.size == 0 && G.size == 0 && B.size == 0 && (r & i_NORMALIZED_FORMAT_BIT) && !(r & i_SIGNED_FORMAT_BIT)) { - return VK_FORMAT_A8_UNORM_KHR; - } - if (A.size > 0) { /* 4 channels */ - if (R.offset == 0) { /* RGBA */ - if ((r & i_SRGB_FORMAT_BIT)) return VK_FORMAT_R8G8B8A8_SRGB; - if ((r & i_NORMALIZED_FORMAT_BIT) && !(r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R8G8B8A8_UNORM; - if ((r & i_NORMALIZED_FORMAT_BIT) && (r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R8G8B8A8_SNORM; - if (!(r & i_NORMALIZED_FORMAT_BIT) && !(r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R8G8B8A8_UINT; - if (!(r & i_NORMALIZED_FORMAT_BIT) && (r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R8G8B8A8_SINT; - } else { /* BGRA */ - if ((r & i_SRGB_FORMAT_BIT)) return VK_FORMAT_B8G8R8A8_SRGB; - if ((r & i_NORMALIZED_FORMAT_BIT) && !(r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_B8G8R8A8_UNORM; - if ((r & i_NORMALIZED_FORMAT_BIT) && (r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_B8G8R8A8_SNORM; - if (!(r & i_NORMALIZED_FORMAT_BIT) && !(r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_B8G8R8A8_UINT; - if (!(r & i_NORMALIZED_FORMAT_BIT) && (r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_B8G8R8A8_SINT; - } - } else if (B.size > 0) { /* 3 channels */ - if (R.offset == 0) { /* RGB */ - if ((r & i_SRGB_FORMAT_BIT)) return VK_FORMAT_R8G8B8_SRGB; - if ((r & i_NORMALIZED_FORMAT_BIT) && !(r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R8G8B8_UNORM; - if ((r & i_NORMALIZED_FORMAT_BIT) && (r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R8G8B8_SNORM; - if (!(r & i_NORMALIZED_FORMAT_BIT) && !(r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R8G8B8_UINT; - if (!(r & i_NORMALIZED_FORMAT_BIT) && (r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R8G8B8_SINT; - } else { /* BGR */ - if ((r & i_SRGB_FORMAT_BIT)) return VK_FORMAT_B8G8R8_SRGB; - if ((r & i_NORMALIZED_FORMAT_BIT) && !(r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_B8G8R8_UNORM; - if ((r & i_NORMALIZED_FORMAT_BIT) && (r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_B8G8R8_SNORM; - if (!(r & i_NORMALIZED_FORMAT_BIT) && !(r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_B8G8R8_UINT; - if (!(r & i_NORMALIZED_FORMAT_BIT) && (r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_B8G8R8_SINT; + if (r & i_YUVSDA_FORMAT_BIT) { + /* In Vulkan G = Y, R = Cr, B = Cb. */ + if (Y1.size == 1 && Y1.offset == 0 && Y2.size == 1 && Y2.offset == 2) + return VK_FORMAT_G8B8G8R8_422_UNORM; + else if (Y1.size == 1 && Y1.offset == 1 && Y2.size == 1 && Y2.offset == 3) + return VK_FORMAT_B8G8R8G8_422_UNORM; + else if (Y1.size == 2 && Y1.offset == 0 && Y2.size == 2 && Y2.offset == 4) + return VK_FORMAT_G16B16G16R16_422_UNORM; + else if (Y1.size == 2 && Y1.offset == 2 && Y2.size == 2 && Y2.offset == 6) + return VK_FORMAT_B16G16R16G16_422_UNORM; + else + return VK_FORMAT_UNDEFINED; // Until support added. + } else { /* Not YUV */ + if (wordBytes == 1) { + if (A.size == 1 && R.size == 0 && G.size == 0 && B.size == 0 && (r & i_NORMALIZED_FORMAT_BIT) && !(r & i_SIGNED_FORMAT_BIT)) { + return VK_FORMAT_A8_UNORM_KHR; } - } else if (G.size > 0) { /* 2 channels */ + if (A.size > 0) { /* 4 channels */ + if (R.offset == 0) { /* RGBA */ + if ((r & i_SRGB_FORMAT_BIT)) return VK_FORMAT_R8G8B8A8_SRGB; + if ((r & i_NORMALIZED_FORMAT_BIT) && !(r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R8G8B8A8_UNORM; + if ((r & i_NORMALIZED_FORMAT_BIT) && (r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R8G8B8A8_SNORM; + if (!(r & i_NORMALIZED_FORMAT_BIT) && !(r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R8G8B8A8_UINT; + if (!(r & i_NORMALIZED_FORMAT_BIT) && (r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R8G8B8A8_SINT; + } else { /* BGRA */ + if ((r & i_SRGB_FORMAT_BIT)) return VK_FORMAT_B8G8R8A8_SRGB; + if ((r & i_NORMALIZED_FORMAT_BIT) && !(r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_B8G8R8A8_UNORM; + if ((r & i_NORMALIZED_FORMAT_BIT) && (r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_B8G8R8A8_SNORM; + if (!(r & i_NORMALIZED_FORMAT_BIT) && !(r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_B8G8R8A8_UINT; + if (!(r & i_NORMALIZED_FORMAT_BIT) && (r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_B8G8R8A8_SINT; + } + } else if (B.size > 0) { /* 3 channels */ + if (R.offset == 0) { /* RGB */ + if ((r & i_SRGB_FORMAT_BIT)) return VK_FORMAT_R8G8B8_SRGB; + if ((r & i_NORMALIZED_FORMAT_BIT) && !(r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R8G8B8_UNORM; + if ((r & i_NORMALIZED_FORMAT_BIT) && (r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R8G8B8_SNORM; + if (!(r & i_NORMALIZED_FORMAT_BIT) && !(r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R8G8B8_UINT; + if (!(r & i_NORMALIZED_FORMAT_BIT) && (r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R8G8B8_SINT; + } else { /* BGR */ + if ((r & i_SRGB_FORMAT_BIT)) return VK_FORMAT_B8G8R8_SRGB; + if ((r & i_NORMALIZED_FORMAT_BIT) && !(r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_B8G8R8_UNORM; + if ((r & i_NORMALIZED_FORMAT_BIT) && (r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_B8G8R8_SNORM; + if (!(r & i_NORMALIZED_FORMAT_BIT) && !(r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_B8G8R8_UINT; + if (!(r & i_NORMALIZED_FORMAT_BIT) && (r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_B8G8R8_SINT; + } + } else if (G.size > 0) { /* 2 channels */ if ((r & i_SRGB_FORMAT_BIT)) return VK_FORMAT_R8G8_SRGB; if ((r & i_NORMALIZED_FORMAT_BIT) && !(r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R8G8_UNORM; if ((r & i_NORMALIZED_FORMAT_BIT) && (r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R8G8_SNORM; if (!(r & i_NORMALIZED_FORMAT_BIT) && !(r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R8G8_UINT; if (!(r & i_NORMALIZED_FORMAT_BIT) && (r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R8G8_SINT; - } else { /* 1 channel */ + } else { /* 1 channel */ if ((r & i_SRGB_FORMAT_BIT)) return VK_FORMAT_R8_SRGB; if ((r & i_NORMALIZED_FORMAT_BIT) && !(r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R8_UNORM; if ((r & i_NORMALIZED_FORMAT_BIT) && (r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R8_SNORM; if (!(r & i_NORMALIZED_FORMAT_BIT) && !(r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R8_UINT; if (!(r & i_NORMALIZED_FORMAT_BIT) && (r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R8_SINT; - } - } else if (wordBytes == 2) { - if (A.size > 0) { /* 4 channels */ - if (R.offset == 0) { /* RGBA */ - if ((r & i_FLOAT_FORMAT_BIT)) return VK_FORMAT_R16G16B16A16_SFLOAT; - if ((r & i_NORMALIZED_FORMAT_BIT) && !(r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R16G16B16A16_UNORM; - if ((r & i_NORMALIZED_FORMAT_BIT) && (r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R16G16B16A16_SNORM; - if (!(r & i_NORMALIZED_FORMAT_BIT) && !(r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R16G16B16A16_UINT; - if (!(r & i_NORMALIZED_FORMAT_BIT) && (r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R16G16B16A16_SINT; - } else { /* BGRA */ } - } else if (B.size > 0) { /* 3 channels */ - if (R.offset == 0) { /* RGB */ - if ((r & i_FLOAT_FORMAT_BIT)) return VK_FORMAT_R16G16B16_SFLOAT; - if ((r & i_NORMALIZED_FORMAT_BIT) && !(r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R16G16B16_UNORM; - if ((r & i_NORMALIZED_FORMAT_BIT) && (r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R16G16B16_SNORM; - if (!(r & i_NORMALIZED_FORMAT_BIT) && !(r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R16G16B16_UINT; - if (!(r & i_NORMALIZED_FORMAT_BIT) && (r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R16G16B16_SINT; - } else { /* BGR */ - } - } else if (G.size > 0) { /* 2 channels */ + } else if (wordBytes == 2) { + if ((r & i_FIXED_FORMAT_BIT) && R.size == 2 && G.size == 2) return VK_FORMAT_R16G16_S10_5_NV; + if (A.size > 0) { /* 4 channels */ + if (R.offset == 0) { /* RGBA */ + if ((r & i_FLOAT_FORMAT_BIT)) return VK_FORMAT_R16G16B16A16_SFLOAT; + if ((r & i_NORMALIZED_FORMAT_BIT) && !(r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R16G16B16A16_UNORM; + if ((r & i_NORMALIZED_FORMAT_BIT) && (r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R16G16B16A16_SNORM; + if (!(r & i_NORMALIZED_FORMAT_BIT) && !(r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R16G16B16A16_UINT; + if (!(r & i_NORMALIZED_FORMAT_BIT) && (r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R16G16B16A16_SINT; + } else { /* BGRA */ + } + } else if (B.size > 0) { /* 3 channels */ + if (R.offset == 0) { /* RGB */ + if ((r & i_FLOAT_FORMAT_BIT)) return VK_FORMAT_R16G16B16_SFLOAT; + if ((r & i_NORMALIZED_FORMAT_BIT) && !(r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R16G16B16_UNORM; + if ((r & i_NORMALIZED_FORMAT_BIT) && (r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R16G16B16_SNORM; + if (!(r & i_NORMALIZED_FORMAT_BIT) && !(r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R16G16B16_UINT; + if (!(r & i_NORMALIZED_FORMAT_BIT) && (r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R16G16B16_SINT; + } else { /* BGR */ + } + } else if (G.size > 0) { /* 2 channels */ if ((r & i_FLOAT_FORMAT_BIT)) return VK_FORMAT_R16G16_SFLOAT; if ((r & i_NORMALIZED_FORMAT_BIT) && !(r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R16G16_UNORM; if ((r & i_NORMALIZED_FORMAT_BIT) && (r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R16G16_SNORM; if (!(r & i_NORMALIZED_FORMAT_BIT) && !(r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R16G16_UINT; if (!(r & i_NORMALIZED_FORMAT_BIT) && (r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R16G16_SINT; - } else { /* 1 channel */ + } else { /* 1 channel */ if ((r & i_FLOAT_FORMAT_BIT)) return VK_FORMAT_R16_SFLOAT; if ((r & i_NORMALIZED_FORMAT_BIT) && !(r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R16_UNORM; if ((r & i_NORMALIZED_FORMAT_BIT) && (r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R16_SNORM; if (!(r & i_NORMALIZED_FORMAT_BIT) && !(r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R16_UINT; if (!(r & i_NORMALIZED_FORMAT_BIT) && (r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R16_SINT; - } - } else if (wordBytes == 4) { - if (A.size > 0) { /* 4 channels */ - if (R.offset == 0) { /* RGBA */ - if ((r & i_FLOAT_FORMAT_BIT)) return VK_FORMAT_R32G32B32A32_SFLOAT; - if (!(r & i_NORMALIZED_FORMAT_BIT) && !(r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R32G32B32A32_UINT; - if (!(r & i_NORMALIZED_FORMAT_BIT) && (r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R32G32B32A32_SINT; - } else { /* BGRA */ - } - } else if (B.size > 0) { /* 3 channels */ - if (R.offset == 0) { /* RGB */ - if ((r & i_FLOAT_FORMAT_BIT)) return VK_FORMAT_R32G32B32_SFLOAT; - if (!(r & i_NORMALIZED_FORMAT_BIT) && !(r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R32G32B32_UINT; - if (!(r & i_NORMALIZED_FORMAT_BIT) && (r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R32G32B32_SINT; - } else { /* BGR */ } - } else if (G.size > 0) { /* 2 channels */ + } else if (wordBytes == 4) { + if (A.size > 0) { /* 4 channels */ + if (R.offset == 0) { /* RGBA */ + if ((r & i_FLOAT_FORMAT_BIT)) return VK_FORMAT_R32G32B32A32_SFLOAT; + if (!(r & i_NORMALIZED_FORMAT_BIT) && !(r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R32G32B32A32_UINT; + if (!(r & i_NORMALIZED_FORMAT_BIT) && (r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R32G32B32A32_SINT; + } else { /* BGRA */ + } + } else if (B.size > 0) { /* 3 channels */ + if (R.offset == 0) { /* RGB */ + if ((r & i_FLOAT_FORMAT_BIT)) return VK_FORMAT_R32G32B32_SFLOAT; + if (!(r & i_NORMALIZED_FORMAT_BIT) && !(r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R32G32B32_UINT; + if (!(r & i_NORMALIZED_FORMAT_BIT) && (r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R32G32B32_SINT; + } else { /* BGR */ + } + } else if (G.size > 0) { /* 2 channels */ if ((r & i_FLOAT_FORMAT_BIT)) return VK_FORMAT_R32G32_SFLOAT; if (!(r & i_NORMALIZED_FORMAT_BIT) && !(r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R32G32_UINT; if (!(r & i_NORMALIZED_FORMAT_BIT) && (r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R32G32_SINT; - } else { /* 1 channel */ + } else { /* 1 channel */ if ((r & i_FLOAT_FORMAT_BIT)) return VK_FORMAT_R32_SFLOAT; if (!(r & i_NORMALIZED_FORMAT_BIT) && !(r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R32_UINT; if (!(r & i_NORMALIZED_FORMAT_BIT) && (r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R32_SINT; - } - } else if (wordBytes == 8) { - if (A.size > 0) { /* 4 channels */ - if (R.offset == 0) { /* RGBA */ - if ((r & i_FLOAT_FORMAT_BIT)) return VK_FORMAT_R64G64B64A64_SFLOAT; - if (!(r & i_NORMALIZED_FORMAT_BIT) && !(r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R64G64B64A64_UINT; - if (!(r & i_NORMALIZED_FORMAT_BIT) && (r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R64G64B64A64_SINT; - } else { /* BGRA */ - } - } else if (B.size > 0) { /* 3 channels */ - if (R.offset == 0) { /* RGB */ - if ((r & i_FLOAT_FORMAT_BIT)) return VK_FORMAT_R64G64B64_SFLOAT; - if (!(r & i_NORMALIZED_FORMAT_BIT) && !(r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R64G64B64_UINT; - if (!(r & i_NORMALIZED_FORMAT_BIT) && (r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R64G64B64_SINT; - } else { /* BGR */ } - } else if (G.size > 0) { /* 2 channels */ + } else if (wordBytes == 8) { + if (A.size > 0) { /* 4 channels */ + if (R.offset == 0) { /* RGBA */ + if ((r & i_FLOAT_FORMAT_BIT)) return VK_FORMAT_R64G64B64A64_SFLOAT; + if (!(r & i_NORMALIZED_FORMAT_BIT) && !(r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R64G64B64A64_UINT; + if (!(r & i_NORMALIZED_FORMAT_BIT) && (r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R64G64B64A64_SINT; + } else { /* BGRA */ + } + } else if (B.size > 0) { /* 3 channels */ + if (R.offset == 0) { /* RGB */ + if ((r & i_FLOAT_FORMAT_BIT)) return VK_FORMAT_R64G64B64_SFLOAT; + if (!(r & i_NORMALIZED_FORMAT_BIT) && !(r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R64G64B64_UINT; + if (!(r & i_NORMALIZED_FORMAT_BIT) && (r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R64G64B64_SINT; + } else { /* BGR */ + } + } else if (G.size > 0) { /* 2 channels */ if ((r & i_FLOAT_FORMAT_BIT)) return VK_FORMAT_R64G64_SFLOAT; if (!(r & i_NORMALIZED_FORMAT_BIT) && !(r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R64G64_UINT; if (!(r & i_NORMALIZED_FORMAT_BIT) && (r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R64G64_SINT; - } else { /* 1 channel */ + } else { /* 1 channel */ if ((r & i_FLOAT_FORMAT_BIT)) return VK_FORMAT_R64_SFLOAT; if (!(r & i_NORMALIZED_FORMAT_BIT) && !(r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R64_UINT; if (!(r & i_NORMALIZED_FORMAT_BIT) && (r & i_SIGNED_FORMAT_BIT)) return VK_FORMAT_R64_SINT; + } } } } diff --git a/thirdparty/libktx/lib/dfdutils/interpretdfd.c b/thirdparty/libktx/lib/dfdutils/interpretdfd.c index 6d25f33a1b..b58a79fb43 100644 --- a/thirdparty/libktx/lib/dfdutils/interpretdfd.c +++ b/thirdparty/libktx/lib/dfdutils/interpretdfd.c @@ -29,18 +29,37 @@ static uint32_t bit_ceil(uint32_t x) { * @~English * @brief Interpret a Data Format Descriptor for a simple format. * - * @param DFD Pointer to a Data Format Descriptor to interpret, - described as 32-bit words in native endianness. - Note that this is the whole descriptor, not just - the basic descriptor block. - * @param R Information about the decoded red channel or the depth channel, if any. - * @param G Information about the decoded green channel or the stencil channel, if any. - * @param B Information about the decoded blue channel, if any. - * @param A Information about the decoded alpha channel, if any. - * @param wordBytes Byte size of the channels (unpacked) or total size (packed). + * Handles "simple" cases that can be translated to things a GPU can access. + * For simplicity, it ignores the compressed formats, which are generally a + * single sample (and I believe are all defined to be little-endian in their + * in-memory layout, even if some documentation confuses this). Focuses on + * the layout and ignores sRGB except for reporting if that is the transfer + * function by way of a bit in the returned value. + * + * @param[in] DFD Pointer to a Data Format Descriptor to interpret, + * described as 32-bit words in native endianness. + * Note that this is the whole descriptor, not just + * the basic descriptor block. + * @param R[in,out] Pointer to struct to receive information about the decoded + * red channel, the Y channel, if YUV, or the depth channel, + * if any. + * @param G[in,out] Pointer to struct to receive information about the decoded + * green channel, the U (Cb) channel, if YUV, or the stencil + * channel, if any. + * @param B[in,out] Pointer to struct to receive information about the decoded + * blue channel, if any or the V (Cr) channel, if YUV. + * @param A[in,out] Pointer to struct to receive information about the decoded + * alpha channel, if any or the second Y channel, if YUV and + * any. + * @param wordBytes[in,out] Pointer to a uint32_t to receive the byte size of + * the channels (unpacked) or total size (packed). * * @return An enumerant describing the decoded value, * or an error code in case of failure. + * + * The mapping of YUV channels to the parameter names used here is based on + * the channel ids in @c khr_df.h and is different from the convention used + * in format names in the Vulkan specification where G == Y, R = Cr and B = Cb. **/ enum InterpretDFDResult interpretDFD(const uint32_t *DFD, InterpretedDFDChannel *R, @@ -49,14 +68,6 @@ enum InterpretDFDResult interpretDFD(const uint32_t *DFD, InterpretedDFDChannel *A, uint32_t *wordBytes) { - /* We specifically handle "simple" cases that can be translated */ - /* to things a GPU can access. For simplicity, we also ignore */ - /* the compressed formats, which are generally a single sample */ - /* (and I believe are all defined to be little-endian in their */ - /* in-memory layout, even if some documentation confuses this). */ - /* We also just worry about layout and ignore sRGB, since that's */ - /* trivial to extract anyway. */ - /* DFD points to the whole descriptor, not the basic descriptor block. */ /* Make everything else relative to the basic descriptor block. */ const uint32_t *BDFDB = DFD+1; @@ -78,7 +89,7 @@ enum InterpretDFDResult interpretDFD(const uint32_t *DFD, /* First rule out the multiple planes case (trivially) */ /* - that is, we check that only bytesPlane0 is non-zero. */ - /* This means we don't handle YUV even if the API could. */ + /* This means we don't handle multi-plane YUV, even if the API could. */ /* (We rely on KHR_DF_WORD_BYTESPLANE0..3 being the same and */ /* KHR_DF_WORD_BYTESPLANE4..7 being the same as a short cut.) */ if ((BDFDB[KHR_DF_WORD_BYTESPLANE0] & ~KHR_DF_MASK_BYTESPLANE0) @@ -104,6 +115,8 @@ enum InterpretDFDResult interpretDFD(const uint32_t *DFD, bool hasSigned = false; bool hasFloat = false; bool hasNormalized = false; + bool hasFixed = false; + khr_df_model_e model = KHR_DFDVAL(BDFDB, MODEL); // Note: We're ignoring 9995, which is weird and worth special-casing // rather than trying to generalise to all float formats. @@ -116,13 +129,23 @@ enum InterpretDFDResult interpretDFD(const uint32_t *DFD, // (i.e. set to the maximum bit value, and check min value) on // the assumption that we're looking at a format which *came* from // an API we can support. - const bool isNormalized = isFloat ? - *(float*) (void*) &BDFDB[KHR_DF_WORD_SAMPLESTART + + bool isFixed; + bool isNormalized; + if (isFloat) { + isNormalized = *(float*) (void*) &BDFDB[KHR_DF_WORD_SAMPLESTART + KHR_DF_WORD_SAMPLEWORDS * i + - KHR_DF_SAMPLEWORD_SAMPLEUPPER] != 1.0f : - KHR_DFDSVAL(BDFDB, i, SAMPLEUPPER) != 1U; - + KHR_DF_SAMPLEWORD_SAMPLEUPPER] != 1.0f; + isFixed = false; + } else { + uint32_t sampleUpper = KHR_DFDSVAL(BDFDB, i, SAMPLEUPPER); + uint32_t maxVal = 1U << KHR_DFDSVAL(BDFDB, i, BITLENGTH); + if (!isSigned) maxVal <<= 1; + maxVal--; + isFixed = 1U < sampleUpper && sampleUpper < maxVal; + isNormalized = !isFixed && sampleUpper != 1U; + } hasSigned |= isSigned; + hasFixed |= isFixed; hasFloat |= isFloat; // By our definition the normalizedness of a single bit channel (like in RGBA 5:5:5:1) // is ambiguous. Ignore these during normalized checks. @@ -132,9 +155,10 @@ enum InterpretDFDResult interpretDFD(const uint32_t *DFD, result |= hasSigned ? i_SIGNED_FORMAT_BIT : 0; result |= hasFloat ? i_FLOAT_FORMAT_BIT : 0; result |= hasNormalized ? i_NORMALIZED_FORMAT_BIT : 0; + result |= hasFixed ? i_FIXED_FORMAT_BIT : 0; // Checks based on color model - if (KHR_DFDVAL(BDFDB, MODEL) == KHR_DF_MODEL_YUVSDA) { + if (model == KHR_DF_MODEL_YUVSDA) { result |= i_NORMALIZED_FORMAT_BIT; result |= i_COMPRESSED_FORMAT_BIT; result |= i_YUVSDA_FORMAT_BIT; @@ -165,7 +189,7 @@ enum InterpretDFDResult interpretDFD(const uint32_t *DFD, *wordBytes = ((result & i_PACKED_FORMAT_BIT) ? 4 : 1) * bit_ceil(largestSampleSize) / 8; } else if (KHR_DFDVAL(BDFDB, MODEL) == KHR_DF_MODEL_RGBSDA) { - /* We only pay attention to sRGB. */ + /* Check if transfer is sRGB. */ if (KHR_DFDVAL(BDFDB, TRANSFER) == KHR_DF_TRANSFER_SRGB) result |= i_SRGB_FORMAT_BIT; /* We only support samples at coordinate 0,0,0,0. */ @@ -175,7 +199,11 @@ enum InterpretDFDResult interpretDFD(const uint32_t *DFD, if (KHR_DFDSVAL(BDFDB, sampleCounter, SAMPLEPOSITION_ALL)) return i_UNSUPPORTED_MULTIPLE_SAMPLE_LOCATIONS; } + } + if (model == KHR_DF_MODEL_RGBSDA || model == KHR_DF_MODEL_YUVSDA) { + /* The values of the DEPTH and STENCIL tokens are the same for */ + /* RGBSDA and YUVSDA. */ /* For Depth/Stencil formats mixed channels are allowed */ for (uint32_t sampleCounter = 0; sampleCounter < numSamples; ++sampleCounter) { switch (KHR_DFDSVAL(BDFDB, sampleCounter, CHANNELID)) { @@ -206,6 +234,9 @@ enum InterpretDFDResult interpretDFD(const uint32_t *DFD, } } + /* This all relies on the channel id values for RGB being equal to */ + /* those for YUV. */ + /* Remember: the canonical ordering of samples is to start with */ /* the lowest bit of the channel/location which touches bit 0 of */ /* the data, when the latter is concatenated in little-endian order, */ @@ -288,8 +319,20 @@ enum InterpretDFDResult interpretDFD(const uint32_t *DFD, currentByteOffset = sampleByteOffset; currentBitLength = sampleBitLength; if (sampleChannelPtr->size) { - /* Uh-oh, we've seen this channel before. */ - return i_UNSUPPORTED_NONTRIVIAL_ENDIANNESS; + if (model == KHR_DF_MODEL_YUVSDA && sampleChannel == KHR_DF_CHANNEL_YUVSDA_Y) { + if (sampleChannelPtr == R) { + /* We've got another Y channel. Record details in A. */ + if (A->size == 0) { + sampleChannelPtr = A; + } else { + /* Uh-oh, we've already got a second Y or an alpha channel. */ + return i_UNSUPPORTED_CHANNEL_TYPES; + } + } + } else { + /* Uh-oh, we've seen this channel before. */ + return i_UNSUPPORTED_NONTRIVIAL_ENDIANNESS; + } } /* For now, record the bit offset in little-endian terms, */ /* because we may not know to reverse it yet. */ @@ -378,8 +421,20 @@ enum InterpretDFDResult interpretDFD(const uint32_t *DFD, currentByteOffset = sampleByteOffset; currentByteLength = sampleByteLength; if (sampleChannelPtr->size) { - /* Uh-oh, we've seen this channel before. */ - return i_UNSUPPORTED_NONTRIVIAL_ENDIANNESS; + if (model == KHR_DF_MODEL_YUVSDA && sampleChannel == KHR_DF_CHANNEL_YUVSDA_Y) { + if (sampleChannelPtr == R) { + /* We've got another Y channel. Record details in A. */ + if (A->size == 0) { + sampleChannelPtr = A; + } else { + /* Uh-oh, we've already got a second Y or an alpha channel. */ + return i_UNSUPPORTED_CHANNEL_TYPES; + } + } + } else { + /* Uh-oh, we've seen this channel before. */ + return i_UNSUPPORTED_NONTRIVIAL_ENDIANNESS; + } } /* For now, record the byte offset in little-endian terms, */ /* because we may not know to reverse it yet. */ diff --git a/thirdparty/libktx/lib/dfdutils/queries.c b/thirdparty/libktx/lib/dfdutils/queries.c index 19488f9e33..66d77cf6ad 100644 --- a/thirdparty/libktx/lib/dfdutils/queries.c +++ b/thirdparty/libktx/lib/dfdutils/queries.c @@ -41,15 +41,15 @@ getDFDComponentInfoUnpacked(const uint32_t* DFD, uint32_t* numComponents, { const uint32_t *BDFDB = DFD+1; uint32_t numSamples = KHR_DFDSAMPLECOUNT(BDFDB); - uint32_t sampleCounter; + uint32_t sampleNumber; uint32_t currentChannel = ~0U; /* Don't start matched. */ /* This is specifically for unpacked formats which means the size of */ /* each component is the same. */ *numComponents = 0; - for (sampleCounter = 0; sampleCounter < numSamples; ++sampleCounter) { - uint32_t sampleByteLength = (KHR_DFDSVAL(BDFDB, sampleCounter, BITLENGTH) + 1) >> 3U; - uint32_t sampleChannel = KHR_DFDSVAL(BDFDB, sampleCounter, CHANNELID); + for (sampleNumber = 0; sampleNumber < numSamples; ++sampleNumber) { + uint32_t sampleByteLength = (KHR_DFDSVAL(BDFDB, sampleNumber, BITLENGTH) + 1) >> 3U; + uint32_t sampleChannel = KHR_DFDSVAL(BDFDB, sampleNumber, CHANNELID); if (sampleChannel == currentChannel) { /* Continuation of the same channel. */ @@ -85,10 +85,10 @@ uint32_t getDFDNumComponents(const uint32_t* DFD) uint32_t currentChannel = ~0U; /* Don't start matched. */ uint32_t numComponents = 0; uint32_t numSamples = KHR_DFDSAMPLECOUNT(BDFDB); - uint32_t sampleCounter; + uint32_t sampleNumber; - for (sampleCounter = 0; sampleCounter < numSamples; ++sampleCounter) { - uint32_t sampleChannel = KHR_DFDSVAL(BDFDB, sampleCounter, CHANNELID); + for (sampleNumber = 0; sampleNumber < numSamples; ++sampleNumber) { + uint32_t sampleChannel = KHR_DFDSVAL(BDFDB, sampleNumber, CHANNELID); if (sampleChannel != currentChannel) { numComponents++; currentChannel = sampleChannel; @@ -97,50 +97,83 @@ uint32_t getDFDNumComponents(const uint32_t* DFD) return numComponents; } + /** * @~English - * @brief Recreate the value of bytesPlane0 from sample info. + * @brief Reconstruct the value of bytesPlane0 from sample info. * - * This can be use to recreate the value of bytesPlane0 for data that - * has been variable-rate compressed so has bytesPlane0 = 0. For DFDs - * that are valid for KTX files. Little-endian data only and no multi-plane - * formats. + * Reconstruct the value for data that has been variable-rate compressed so + * has bytesPlane0 = 0. For DFDs that are valid for KTX files. Little-endian + * data only and no multi-plane formats. * * @param DFD Pointer to a Data Format Descriptor for which, * described as 32-bit words in native endianness. * Note that this is the whole descriptor, not just * the basic descriptor block. - * @param bytesPlane0 pointer to a 32-bit word in which the recreated - * value of bytesPlane0 will be written. */ -void -recreateBytesPlane0FromSampleInfo(const uint32_t* DFD, uint32_t* bytesPlane0) +uint32_t +reconstructDFDBytesPlane0FromSamples(const uint32_t* DFD) { const uint32_t *BDFDB = DFD+1; uint32_t numSamples = KHR_DFDSAMPLECOUNT(BDFDB); - uint32_t sampleCounter; + uint32_t sampleNumber; uint32_t bitsPlane0 = 0; - uint32_t* bitOffsets = malloc(sizeof(uint32_t) * numSamples); - memset(bitOffsets, -1, sizeof(uint32_t) * numSamples); - for (sampleCounter = 0; sampleCounter < numSamples; ++sampleCounter) { - uint32_t sampleBitOffset = KHR_DFDSVAL(BDFDB, sampleCounter, BITOFFSET); - /* The sample bitLength field stores the bit length - 1. */ - uint32_t sampleBitLength = KHR_DFDSVAL(BDFDB, sampleCounter, BITLENGTH) + 1; - uint32_t i; - for (i = 0; i < numSamples; i++) { - if (sampleBitOffset == bitOffsets[i]) { - // This sample is being repeated as in e.g. RGB9E5. - break; + int32_t largestOffset = 0; + uint32_t sampleNumberWithLargestOffset = 0; + + // Special case these depth{,-stencil} formats. The unused bits are + // in the MSBs so have no visibility in the DFD therefore the max offset + // algorithm below returns a value that is too small. + if (KHR_DFDSVAL(BDFDB, 0, CHANNELID) == KHR_DF_CHANNEL_COMMON_DEPTH) { + if (numSamples == 1) { + if (KHR_DFDSVAL(BDFDB, 0, BITLENGTH) + 1 == 24) { + // X8_D24_UNORM_PACK32, + return 4; + } + } else if (numSamples == 2) { + if (KHR_DFDSVAL(BDFDB, 0, BITLENGTH) + 1 == 16) { + // D16_UNORM_S8_UINT + return 4; + } + if (KHR_DFDSVAL(BDFDB, 0, BITLENGTH) + 1 == 32 + && KHR_DFDSVAL(BDFDB, 1, CHANNELID) == KHR_DF_CHANNEL_COMMON_STENCIL) { + // D32_SFLOAT_S8_UINT + return 8; } } - if (i == numSamples) { - // Previously unseen bitOffset. Bump size. - bitsPlane0 += sampleBitLength; - bitOffsets[sampleCounter] = sampleBitOffset; + } + for (sampleNumber = 0; sampleNumber < numSamples; ++sampleNumber) { + int32_t sampleBitOffset = KHR_DFDSVAL(BDFDB, sampleNumber, BITOFFSET); + if (sampleBitOffset > largestOffset) { + largestOffset = sampleBitOffset; + sampleNumberWithLargestOffset = sampleNumber; } } - free(bitOffsets); - *bytesPlane0 = bitsPlane0 >> 3U; + + /* The sample bitLength field stores the bit length - 1. */ + uint32_t sampleBitLength = KHR_DFDSVAL(BDFDB, sampleNumberWithLargestOffset, BITLENGTH) + 1; + bitsPlane0 = largestOffset + sampleBitLength; + return bitsPlane0 >> 3U; } +/** + * @~English + * @brief Reconstruct the value of bytesPlane0 from sample info. + * + * @see reconstructDFDBytesPlane0FromSamples for details. + * @deprecated For backward comparibility only. Use + * reconstructDFDBytesPlane0FromSamples. + * + * @param DFD Pointer to a Data Format Descriptor for which, + * described as 32-bit words in native endianness. + * Note that this is the whole descriptor, not just + * the basic descriptor block. + * @param bytesPlane0 pointer to a 32-bit word in which the recreated + * value of bytesPlane0 will be written. + */ +void +recreateBytesPlane0FromSampleInfo(const uint32_t* DFD, uint32_t* bytesPlane0) +{ + *bytesPlane0 = reconstructDFDBytesPlane0FromSamples(DFD); +} diff --git a/thirdparty/libktx/lib/dfdutils/vk2dfd.inl b/thirdparty/libktx/lib/dfdutils/vk2dfd.inl index 25c7a2c238..3398441e8c 100644 --- a/thirdparty/libktx/lib/dfdutils/vk2dfd.inl +++ b/thirdparty/libktx/lib/dfdutils/vk2dfd.inl @@ -277,68 +277,68 @@ case VK_FORMAT_ASTC_12x10_SRGB_BLOCK: return createDFDCompressed(c_ASTC, 12, 10, case VK_FORMAT_ASTC_12x12_UNORM_BLOCK: return createDFDCompressed(c_ASTC, 12, 12, 1, s_UNORM); case VK_FORMAT_ASTC_12x12_SRGB_BLOCK: return createDFDCompressed(c_ASTC, 12, 12, 1, s_SRGB); case VK_FORMAT_G8B8G8R8_422_UNORM: { - int channels[] = {0, 1, 0, 2}; int bits[] = {8, 8, 8, 8}; int paddings[] = {0, 0, 0, 0}; + int channels[] = {0, 1, 0, 2}; int bits[] = {8, 8, 8, 8}; int shiftBits[] = {0, 0, 0, 0}; int position_xs[] = {64, 64, 192, 64}; int position_ys[] = {128, 128, 128, 128}; - return createDFD422(0, 4, bits, paddings, channels, position_xs, position_ys, s_UNORM); + return createDFD422(0, 4, bits, shiftBits, channels, position_xs, position_ys, s_UNORM); } case VK_FORMAT_B8G8R8G8_422_UNORM: { - int channels[] = {1, 0, 2, 0}; int bits[] = {8, 8, 8, 8}; int paddings[] = {0, 0, 0, 0}; + int channels[] = {1, 0, 2, 0}; int bits[] = {8, 8, 8, 8}; int shiftBits[] = {0, 0, 0, 0}; int position_xs[] = {64, 64, 64, 192}; int position_ys[] = {128, 128, 128, 128}; - return createDFD422(0, 4, bits, paddings, channels, position_xs, position_ys, s_UNORM); + return createDFD422(0, 4, bits, shiftBits, channels, position_xs, position_ys, s_UNORM); } case VK_FORMAT_R10X6_UNORM_PACK16: { - int channels[] = {0}; int bits[] = {10}; int paddings[] = {6}; - return createDFDPackedPadded(0, 1, bits, paddings, channels, s_UNORM); + int channels[] = {0}; int bits[] = {10}; int shiftBits[] = {6}; + return createDFDPackedShifted(0, 1, bits, shiftBits, channels, s_UNORM); } case VK_FORMAT_R10X6G10X6_UNORM_2PACK16: { - int channels[] = {0, 1}; int bits[] = {10, 10}; int paddings[] = {6, 6}; - return createDFDPackedPadded(0, 2, bits, paddings, channels, s_UNORM); + int channels[] = {0, 1}; int bits[] = {10, 10}; int shiftBits[] = {6, 6}; + return createDFDPackedShifted(0, 2, bits, shiftBits, channels, s_UNORM); } case VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16: { - int channels[] = {0, 1, 2, 3}; int bits[] = {10, 10, 10, 10}; int paddings[] = {6, 6, 6, 6}; - return createDFDPackedPadded(0, 4, bits, paddings, channels, s_UNORM); + int channels[] = {0, 1, 2, 3}; int bits[] = {10, 10, 10, 10}; int shiftBits[] = {6, 6, 6, 6}; + return createDFDPackedShifted(0, 4, bits, shiftBits, channels, s_UNORM); } case VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16: { - int channels[] = {0, 1, 0, 2}; int bits[] = {10, 10, 10, 10}; int paddings[] = {6, 6, 6, 6}; + int channels[] = {0, 1, 0, 2}; int bits[] = {10, 10, 10, 10}; int shiftBits[] = {6, 6, 6, 6}; int position_xs[] = {64, 64, 192, 64}; int position_ys[] = {128, 128, 128, 128}; - return createDFD422(0, 4, bits, paddings, channels, position_xs, position_ys, s_UNORM); + return createDFD422(0, 4, bits, shiftBits, channels, position_xs, position_ys, s_UNORM); } case VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16: { - int channels[] = {1, 0, 2, 0}; int bits[] = {10, 10, 10, 10}; int paddings[] = {6, 6, 6, 6}; + int channels[] = {1, 0, 2, 0}; int bits[] = {10, 10, 10, 10}; int shiftBits[] = {6, 6, 6, 6}; int position_xs[] = {64, 64, 64, 192}; int position_ys[] = {128, 128, 128, 128}; - return createDFD422(0, 4, bits, paddings, channels, position_xs, position_ys, s_UNORM); + return createDFD422(0, 4, bits, shiftBits, channels, position_xs, position_ys, s_UNORM); } case VK_FORMAT_R12X4_UNORM_PACK16: { - int channels[] = {0}; int bits[] = {12}; int paddings[] = {4}; - return createDFDPackedPadded(0, 1, bits, paddings, channels, s_UNORM); + int channels[] = {0}; int bits[] = {12}; int shiftBits[] = {4}; + return createDFDPackedShifted(0, 1, bits, shiftBits, channels, s_UNORM); } case VK_FORMAT_R12X4G12X4_UNORM_2PACK16: { - int channels[] = {0, 1}; int bits[] = {12, 12}; int paddings[] = {4, 4}; - return createDFDPackedPadded(0, 2, bits, paddings, channels, s_UNORM); + int channels[] = {0, 1}; int bits[] = {12, 12}; int shiftBits[] = {4, 4}; + return createDFDPackedShifted(0, 2, bits, shiftBits, channels, s_UNORM); } case VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16: { - int channels[] = {0, 1, 2, 3}; int bits[] = {12, 12, 12, 12}; int paddings[] = {4, 4, 4, 4}; - return createDFDPackedPadded(0, 4, bits, paddings, channels, s_UNORM); + int channels[] = {0, 1, 2, 3}; int bits[] = {12, 12, 12, 12}; int shiftBits[] = {4, 4, 4, 4}; + return createDFDPackedShifted(0, 4, bits, shiftBits, channels, s_UNORM); } case VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16: { - int channels[] = {0, 1, 0, 2}; int bits[] = {12, 12, 12, 12}; int paddings[] = {4, 4, 4, 4}; + int channels[] = {0, 1, 0, 2}; int bits[] = {12, 12, 12, 12}; int shiftBits[] = {4, 4, 4, 4}; int position_xs[] = {64, 64, 192, 64}; int position_ys[] = {128, 128, 128, 128}; - return createDFD422(0, 4, bits, paddings, channels, position_xs, position_ys, s_UNORM); + return createDFD422(0, 4, bits, shiftBits, channels, position_xs, position_ys, s_UNORM); } case VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16: { - int channels[] = {1, 0, 2, 0}; int bits[] = {12, 12, 12, 12}; int paddings[] = {4, 4, 4, 4}; + int channels[] = {1, 0, 2, 0}; int bits[] = {12, 12, 12, 12}; int shiftBits[] = {4, 4, 4, 4}; int position_xs[] = {64, 64, 64, 192}; int position_ys[] = {128, 128, 128, 128}; - return createDFD422(0, 4, bits, paddings, channels, position_xs, position_ys, s_UNORM); + return createDFD422(0, 4, bits, shiftBits, channels, position_xs, position_ys, s_UNORM); } case VK_FORMAT_G16B16G16R16_422_UNORM: { - int channels[] = {0, 1, 0, 2}; int bits[] = {16, 16, 16, 16}; int paddings[] = {0, 0, 0, 0}; + int channels[] = {0, 1, 0, 2}; int bits[] = {16, 16, 16, 16}; int shiftBits[] = {0, 0, 0, 0}; int position_xs[] = {64, 64, 192, 64}; int position_ys[] = {128, 128, 128, 128}; - return createDFD422(0, 4, bits, paddings, channels, position_xs, position_ys, s_UNORM); + return createDFD422(0, 4, bits, shiftBits, channels, position_xs, position_ys, s_UNORM); } case VK_FORMAT_B16G16R16G16_422_UNORM: { - int channels[] = {1, 0, 2, 0}; int bits[] = {16, 16, 16, 16}; int paddings[] = {0, 0, 0, 0}; + int channels[] = {1, 0, 2, 0}; int bits[] = {16, 16, 16, 16}; int shiftBits[] = {0, 0, 0, 0}; int position_xs[] = {64, 64, 64, 192}; int position_ys[] = {128, 128, 128, 128}; - return createDFD422(0, 4, bits, paddings, channels, position_xs, position_ys, s_UNORM); + return createDFD422(0, 4, bits, shiftBits, channels, position_xs, position_ys, s_UNORM); } case VK_FORMAT_A4R4G4B4_UNORM_PACK16: { int channels[] = {2,1,0,3}; int bits[] = {4,4,4,4}; @@ -402,6 +402,7 @@ case VK_FORMAT_ASTC_6x6x6_UNORM_BLOCK_EXT: return createDFDCompressed(c_ASTC, 6, case VK_FORMAT_ASTC_6x6x6_SRGB_BLOCK_EXT: return createDFDCompressed(c_ASTC, 6, 6, 6, s_SRGB); case VK_FORMAT_ASTC_6x6x6_SFLOAT_BLOCK_EXT: return createDFDCompressed(c_ASTC, 6, 6, 6, s_SFLOAT); #endif +case VK_FORMAT_R16G16_S10_5_NV: return createDFDUnpacked(0, 2, 2, 0, s_S10_5); case VK_FORMAT_A1B5G5R5_UNORM_PACK16_KHR: { int channels[] = {0,1,2,3}; int bits[] = {5,5,5,1}; return createDFDPacked(0, 4, bits, channels, s_UNORM); diff --git a/thirdparty/libktx/lib/gl_format.h b/thirdparty/libktx/lib/gl_format.h index 3986bc430c..44abd2c6d4 100644 --- a/thirdparty/libktx/lib/gl_format.h +++ b/thirdparty/libktx/lib/gl_format.h @@ -1,4 +1,4 @@ -/* +/* ================================================================================================ Description : OpenGL formats/types and properties. @@ -70,7 +70,6 @@ static inline GLenum glGetFormatFromInternalFormat( const GLenum internalFormat static inline GLenum glGetTypeFromInternalFormat( const GLenum internalFormat ); static inline void glGetFormatSize( const GLenum internalFormat, GlFormatSize * pFormatSize ); static inline unsigned int glGetTypeSizeFromType( const GLenum type ); -static inline GLenum glGetInternalFormatFromVkFormat ( VkFormat format ); MODIFICATIONS for use in libktx =============================== @@ -79,7 +78,6 @@ MODIFICATIONS for use in libktx 2019.3.09 #if 0 around GL type declarations. 〃 2019.5.30 Use common ktxFormatSize to return results. 〃 2019.5.30 Return blockSizeInBits 0 for default case of glGetFormatSize. 〃 -2019.5.30 Added glGetInternalFormatFromVkFormat. 〃 ================================================================================================ */ @@ -101,6 +99,7 @@ MODIFICATIONS for use in libktx #endif // __cplusplus #endif + /* =========================================================================== Avoid warnings or even errors when using strict C99. "Redefinition of @@ -2436,219 +2435,4 @@ static inline void glGetFormatSize( const GLenum internalFormat, ktxFormatSize * } } -static inline GLint glGetInternalFormatFromVkFormat( VkFormat vkFormat ) -{ - switch ( vkFormat ) - { - // - // 8 bits per component - // - case VK_FORMAT_R8_UNORM: return GL_R8; // 1-component, 8-bit unsigned normalized - case VK_FORMAT_R8G8_UNORM: return GL_RG8; // 2-component, 8-bit unsigned normalized - case VK_FORMAT_R8G8B8_UNORM: return GL_RGB8; // 3-component, 8-bit unsigned normalized - case VK_FORMAT_R8G8B8A8_UNORM: return GL_RGBA8; // 4-component, 8-bit unsigned normalized - - case VK_FORMAT_R8_SNORM: return GL_R8_SNORM; // 1-component, 8-bit signed normalized - case VK_FORMAT_R8G8_SNORM: return GL_RG8_SNORM; // 2-component, 8-bit signed normalized - case VK_FORMAT_R8G8B8_SNORM: return GL_RGB8_SNORM; // 3-component, 8-bit signed normalized - case VK_FORMAT_R8G8B8A8_SNORM: return GL_RGBA8_SNORM; // 4-component, 8-bit signed normalized - - case VK_FORMAT_R8_UINT: return GL_R8UI; // 1-component, 8-bit unsigned integer - case VK_FORMAT_R8G8_UINT: return GL_RG8UI; // 2-component, 8-bit unsigned integer - case VK_FORMAT_R8G8B8_UINT: return GL_RGB8UI; // 3-component, 8-bit unsigned integer - case VK_FORMAT_R8G8B8A8_UINT: return GL_RGBA8UI; // 4-component, 8-bit unsigned integer - - case VK_FORMAT_R8_SINT: return GL_R8I; // 1-component, 8-bit signed integer - case VK_FORMAT_R8G8_SINT: return GL_RG8I; // 2-component, 8-bit signed integer - case VK_FORMAT_R8G8B8_SINT: return GL_RGB8I; // 3-component, 8-bit signed integer - case VK_FORMAT_R8G8B8A8_SINT: return GL_RGBA8I; // 4-component, 8-bit signed integer - - case VK_FORMAT_R8_SRGB: return GL_SR8; // 1-component, 8-bit sRGB - case VK_FORMAT_R8G8_SRGB: return GL_SRG8; // 2-component, 8-bit sRGB - case VK_FORMAT_R8G8B8_SRGB: return GL_SRGB8; // 3-component, 8-bit sRGB - case VK_FORMAT_R8G8B8A8_SRGB: return GL_SRGB8_ALPHA8; // 4-component, 8-bit sRGB - - // - // 16 bits per component - // - case VK_FORMAT_R16_UNORM: return GL_R16; // 1-component, 16-bit unsigned normalized - case VK_FORMAT_R16G16_UNORM: return GL_RG16; // 2-component, 16-bit unsigned normalized - case VK_FORMAT_R16G16B16_UNORM: return GL_RGB16; // 3-component, 16-bit unsigned normalized - case VK_FORMAT_R16G16B16A16_UNORM: return GL_RGBA16; // 4-component, 16-bit unsigned normalized - - case VK_FORMAT_R16_SNORM: return GL_R16_SNORM; // 1-component, 16-bit signed normalized - case VK_FORMAT_R16G16_SNORM: return GL_RG16_SNORM; // 2-component, 16-bit signed normalized - case VK_FORMAT_R16G16B16_SNORM: return GL_RGB16_SNORM; // 3-component, 16-bit signed normalized - case VK_FORMAT_R16G16B16A16_SNORM: return GL_RGBA16_SNORM; // 4-component, 16-bit signed normalized - - case VK_FORMAT_R16_UINT: return GL_R16UI; // 1-component, 16-bit unsigned integer - case VK_FORMAT_R16G16_UINT: return GL_RG16UI; // 2-component, 16-bit unsigned integer - case VK_FORMAT_R16G16B16_UINT: return GL_RGB16UI; // 3-component, 16-bit unsigned integer - case VK_FORMAT_R16G16B16A16_UINT: return GL_RGBA16UI; // 4-component, 16-bit unsigned integer - - case VK_FORMAT_R16_SINT: return GL_R16I; // 1-component, 16-bit signed integer - case VK_FORMAT_R16G16_SINT: return GL_RG16I; // 2-component, 16-bit signed integer - case VK_FORMAT_R16G16B16_SINT: return GL_RGB16I; // 3-component, 16-bit signed integer - case VK_FORMAT_R16G16B16A16_SINT: return GL_RGBA16I; // 4-component, 16-bit signed integer - - case VK_FORMAT_R16_SFLOAT: return GL_R16F; // 1-component, 16-bit floating-point - case VK_FORMAT_R16G16_SFLOAT: return GL_RG16F; // 2-component, 16-bit floating-point - case VK_FORMAT_R16G16B16_SFLOAT: return GL_RGB16F; // 3-component, 16-bit floating-point - case VK_FORMAT_R16G16B16A16_SFLOAT: return GL_RGBA16F; // 4-component, 16-bit floating-point - - // - // 32 bits per component - // - case VK_FORMAT_R32_UINT: return GL_R32UI; // 1-component, 32-bit unsigned integer - case VK_FORMAT_R32G32_UINT: return GL_RG32UI; // 2-component, 32-bit unsigned integer - case VK_FORMAT_R32G32B32_UINT: return GL_RGB32UI; // 3-component, 32-bit unsigned integer - case VK_FORMAT_R32G32B32A32_UINT: return GL_RGBA32UI; // 4-component, 32-bit unsigned integer - - case VK_FORMAT_R32_SINT: return GL_R32I; // 1-component, 32-bit signed integer - case VK_FORMAT_R32G32_SINT: return GL_RG32I; // 2-component, 32-bit signed integer - case VK_FORMAT_R32G32B32_SINT: return GL_RGB32I; // 3-component, 32-bit signed integer - case VK_FORMAT_R32G32B32A32_SINT: return GL_RGBA32I; // 4-component, 32-bit signed integer - - case VK_FORMAT_R32_SFLOAT: return GL_R32F; // 1-component, 32-bit floating-point - case VK_FORMAT_R32G32_SFLOAT: return GL_RG32F; // 2-component, 32-bit floating-point - case VK_FORMAT_R32G32B32_SFLOAT: return GL_RGB32F; // 3-component, 32-bit floating-point - case VK_FORMAT_R32G32B32A32_SFLOAT: return GL_RGBA32F; // 4-component, 32-bit floating-point - - // - // Packed - // - case VK_FORMAT_R5G5B5A1_UNORM_PACK16: return GL_RGB5; // 3-component 5:5:5, unsigned normalized - case VK_FORMAT_R5G6B5_UNORM_PACK16: return GL_RGB565; // 3-component 5:6:5, unsigned normalized - case VK_FORMAT_R4G4B4A4_UNORM_PACK16: return GL_RGBA4; // 4-component 4:4:4:4, unsigned normalized - case VK_FORMAT_A1R5G5B5_UNORM_PACK16: return GL_RGB5_A1; // 4-component 5:5:5:1, unsigned normalized - case VK_FORMAT_A2R10G10B10_UNORM_PACK32: return GL_RGB10_A2; // 4-component 10:10:10:2, unsigned normalized - case VK_FORMAT_A2R10G10B10_UINT_PACK32: return GL_RGB10_A2UI; // 4-component 10:10:10:2, unsigned integer - case VK_FORMAT_B10G11R11_UFLOAT_PACK32: return GL_R11F_G11F_B10F; // 3-component 11:11:10, floating-point - case VK_FORMAT_E5B9G9R9_UFLOAT_PACK32: return GL_RGB9_E5; // 3-component/exp 9:9:9/5, floating-point - - // - // S3TC/DXT/BC - // - - case VK_FORMAT_BC1_RGB_UNORM_BLOCK: return GL_COMPRESSED_RGB_S3TC_DXT1_EXT; // line through 3D space, 4x4 blocks, unsigned normalized - case VK_FORMAT_BC1_RGBA_UNORM_BLOCK: return GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; // line through 3D space plus 1-bit alpha, 4x4 blocks, unsigned normalized - case VK_FORMAT_BC2_UNORM_BLOCK: return GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; // line through 3D space plus line through 1D space, 4x4 blocks, unsigned normalized - case VK_FORMAT_BC3_UNORM_BLOCK: return GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; // line through 3D space plus 4-bit alpha, 4x4 blocks, unsigned normalized - - case VK_FORMAT_BC1_RGB_SRGB_BLOCK: return GL_COMPRESSED_SRGB_S3TC_DXT1_EXT; // line through 3D space, 4x4 blocks, sRGB - case VK_FORMAT_BC1_RGBA_SRGB_BLOCK: return GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT; // line through 3D space plus 1-bit alpha, 4x4 blocks, sRGB - case VK_FORMAT_BC2_SRGB_BLOCK: return GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT; // line through 3D space plus line through 1D space, 4x4 blocks, sRGB - case VK_FORMAT_BC3_SRGB_BLOCK: return GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT; // line through 3D space plus 4-bit alpha, 4x4 blocks, sRGB - - case VK_FORMAT_BC4_UNORM_BLOCK: return GL_COMPRESSED_RED_RGTC1; // line through 1D space, 4x4 blocks, unsigned normalized - case VK_FORMAT_BC5_UNORM_BLOCK: return GL_COMPRESSED_RG_RGTC2; // two lines through 1D space, 4x4 blocks, unsigned normalized - case VK_FORMAT_BC4_SNORM_BLOCK: return GL_COMPRESSED_SIGNED_RED_RGTC1; // line through 1D space, 4x4 blocks, signed normalized - case VK_FORMAT_BC5_SNORM_BLOCK: return GL_COMPRESSED_SIGNED_RG_RGTC2; // two lines through 1D space, 4x4 blocks, signed normalized - - case VK_FORMAT_BC6H_UFLOAT_BLOCK: return GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT; // 3-component, 4x4 blocks, unsigned floating-point - case VK_FORMAT_BC6H_SFLOAT_BLOCK: return GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT; // 3-component, 4x4 blocks, signed floating-point - case VK_FORMAT_BC7_UNORM_BLOCK: return GL_COMPRESSED_RGBA_BPTC_UNORM; // 4-component, 4x4 blocks, unsigned normalized - case VK_FORMAT_BC7_SRGB_BLOCK: return GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM; // 4-component, 4x4 blocks, sRGB - - // - // ETC - // - case VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK: return GL_COMPRESSED_RGB8_ETC2; // 3-component ETC2, 4x4 blocks, unsigned normalized - case VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK: return GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2; // 4-component ETC2 with 1-bit alpha, 4x4 blocks, unsigned normalized - case VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK: return GL_COMPRESSED_RGBA8_ETC2_EAC; // 4-component ETC2, 4x4 blocks, unsigned normalized - - case VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK: return GL_COMPRESSED_SRGB8_ETC2; // 3-component ETC2, 4x4 blocks, sRGB - case VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK: return GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2; // 4-component ETC2 with 1-bit alpha, 4x4 blocks, sRGB - case VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK: return GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC; // 4-component ETC2, 4x4 blocks, sRGB - - case VK_FORMAT_EAC_R11_UNORM_BLOCK: return GL_COMPRESSED_R11_EAC; // 1-component ETC, 4x4 blocks, unsigned normalized - case VK_FORMAT_EAC_R11G11_UNORM_BLOCK: return GL_COMPRESSED_RG11_EAC; // 2-component ETC, 4x4 blocks, unsigned normalized - case VK_FORMAT_EAC_R11_SNORM_BLOCK: return GL_COMPRESSED_SIGNED_R11_EAC; // 1-component ETC, 4x4 blocks, signed normalized - case VK_FORMAT_EAC_R11G11_SNORM_BLOCK: return GL_COMPRESSED_SIGNED_RG11_EAC; // 2-component ETC, 4x4 blocks, signed normalized - - // - // PVRTC - // - case VK_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG: return GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG; // 3- or 4-component PVRTC, 16x8 blocks, unsigned normalized - case VK_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG: return GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG; // 3- or 4-component PVRTC, 8x8 blocks, unsigned normalized - case VK_FORMAT_PVRTC2_2BPP_UNORM_BLOCK_IMG: return GL_COMPRESSED_RGBA_PVRTC_2BPPV2_IMG; // 3- or 4-component PVRTC, 16x8 blocks, unsigned normalized - case VK_FORMAT_PVRTC2_4BPP_UNORM_BLOCK_IMG: return GL_COMPRESSED_RGBA_PVRTC_4BPPV2_IMG; // 3- or 4-component PVRTC, 4x4 blocks, unsigned normalized - - case VK_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG: return GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT; // 4-component PVRTC, 16x8 blocks, sRGB - case VK_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG: return GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT; // 4-component PVRTC, 8x8 blocks, sRGB - case VK_FORMAT_PVRTC2_2BPP_SRGB_BLOCK_IMG: return GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV2_IMG; // 4-component PVRTC, 8x4 blocks, sRGB - case VK_FORMAT_PVRTC2_4BPP_SRGB_BLOCK_IMG: return GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV2_IMG; // 4-component PVRTC, 4x4 blocks, sRGB - - // - // ASTC - // - case VK_FORMAT_ASTC_4x4_UNORM_BLOCK: return GL_COMPRESSED_RGBA_ASTC_4x4_KHR; // 4-component ASTC, 4x4 blocks, unsigned normalized - case VK_FORMAT_ASTC_5x4_UNORM_BLOCK: return GL_COMPRESSED_RGBA_ASTC_5x4_KHR; // 4-component ASTC, 5x4 blocks, unsigned normalized - case VK_FORMAT_ASTC_5x5_UNORM_BLOCK: return GL_COMPRESSED_RGBA_ASTC_5x5_KHR; // 4-component ASTC, 5x5 blocks, unsigned normalized - case VK_FORMAT_ASTC_6x5_UNORM_BLOCK: return GL_COMPRESSED_RGBA_ASTC_6x5_KHR; // 4-component ASTC, 6x5 blocks, unsigned normalized - case VK_FORMAT_ASTC_6x6_UNORM_BLOCK: return GL_COMPRESSED_RGBA_ASTC_6x6_KHR; // 4-component ASTC, 6x6 blocks, unsigned normalized - case VK_FORMAT_ASTC_8x5_UNORM_BLOCK: return GL_COMPRESSED_RGBA_ASTC_8x5_KHR; // 4-component ASTC, 8x5 blocks, unsigned normalized - case VK_FORMAT_ASTC_8x6_UNORM_BLOCK: return GL_COMPRESSED_RGBA_ASTC_8x6_KHR; // 4-component ASTC, 8x6 blocks, unsigned normalized - case VK_FORMAT_ASTC_8x8_UNORM_BLOCK: return GL_COMPRESSED_RGBA_ASTC_8x8_KHR; // 4-component ASTC, 8x8 blocks, unsigned normalized - case VK_FORMAT_ASTC_10x5_UNORM_BLOCK: return GL_COMPRESSED_RGBA_ASTC_10x5_KHR; // 4-component ASTC, 10x5 blocks, unsigned normalized - case VK_FORMAT_ASTC_10x6_UNORM_BLOCK: return GL_COMPRESSED_RGBA_ASTC_10x6_KHR; // 4-component ASTC, 10x6 blocks, unsigned normalized - case VK_FORMAT_ASTC_10x8_UNORM_BLOCK: return GL_COMPRESSED_RGBA_ASTC_10x8_KHR; // 4-component ASTC, 10x8 blocks, unsigned normalized - case VK_FORMAT_ASTC_10x10_UNORM_BLOCK: return GL_COMPRESSED_RGBA_ASTC_10x10_KHR; // 4-component ASTC, 10x10 blocks, unsigned normalized - case VK_FORMAT_ASTC_12x10_UNORM_BLOCK: return GL_COMPRESSED_RGBA_ASTC_12x10_KHR; // 4-component ASTC, 12x10 blocks, unsigned normalized - case VK_FORMAT_ASTC_12x12_UNORM_BLOCK: return GL_COMPRESSED_RGBA_ASTC_12x12_KHR; // 4-component ASTC, 12x12 blocks, unsigned normalized - - case VK_FORMAT_ASTC_4x4_SRGB_BLOCK: return GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR; // 4-component ASTC, 4x4 blocks, sRGB - case VK_FORMAT_ASTC_5x4_SRGB_BLOCK: return GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR; // 4-component ASTC, 5x4 blocks, sRGB - case VK_FORMAT_ASTC_5x5_SRGB_BLOCK: return GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR; // 4-component ASTC, 5x5 blocks, sRGB - case VK_FORMAT_ASTC_6x5_SRGB_BLOCK: return GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR; // 4-component ASTC, 6x5 blocks, sRGB - case VK_FORMAT_ASTC_6x6_SRGB_BLOCK: return GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR; // 4-component ASTC, 6x6 blocks, sRGB - case VK_FORMAT_ASTC_8x5_SRGB_BLOCK: return GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR; // 4-component ASTC, 8x5 blocks, sRGB - case VK_FORMAT_ASTC_8x6_SRGB_BLOCK: return GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR; // 4-component ASTC, 8x6 blocks, sRGB - case VK_FORMAT_ASTC_8x8_SRGB_BLOCK: return GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR; // 4-component ASTC, 8x8 blocks, sRGB - case VK_FORMAT_ASTC_10x5_SRGB_BLOCK: return GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR; // 4-component ASTC, 10x5 blocks, sRGB - case VK_FORMAT_ASTC_10x6_SRGB_BLOCK: return GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR; // 4-component ASTC, 10x6 blocks, sRGB - case VK_FORMAT_ASTC_10x8_SRGB_BLOCK: return GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR; // 4-component ASTC, 10x8 blocks, sRGB - case VK_FORMAT_ASTC_10x10_SRGB_BLOCK: return GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR; // 4-component ASTC, 10x10 blocks, sRGB - case VK_FORMAT_ASTC_12x10_SRGB_BLOCK: return GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR; // 4-component ASTC, 12x10 blocks, sRGB - case VK_FORMAT_ASTC_12x12_SRGB_BLOCK: return GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR; // 4-component ASTC, 12x12 blocks, sRGB - - // XXX FIXME Update once Vulkan ASTC HDR & 3D extensions are released. -#if 0 - case VK_FORMAT_UNDEFINED: return GL_COMPRESSED_RGBA_ASTC_3x3x3_OES; // 4-component ASTC, 3x3x3 blocks, unsigned normalized - case VK_FORMAT_UNDEFINED: return GL_COMPRESSED_RGBA_ASTC_4x3x3_OES; // 4-component ASTC, 4x3x3 blocks, unsigned normalized - case VK_FORMAT_UNDEFINED: return GL_COMPRESSED_RGBA_ASTC_4x4x3_OES; // 4-component ASTC, 4x4x3 blocks, unsigned normalized - case VK_FORMAT_UNDEFINED: return GL_COMPRESSED_RGBA_ASTC_4x4x4_OES; // 4-component ASTC, 4x4x4 blocks, unsigned normalized - case VK_FORMAT_UNDEFINED: return GL_COMPRESSED_RGBA_ASTC_5x4x4_OES; // 4-component ASTC, 5x4x4 blocks, unsigned normalized - case VK_FORMAT_UNDEFINED: return GL_COMPRESSED_RGBA_ASTC_5x5x4_OES; // 4-component ASTC, 5x5x4 blocks, unsigned normalized - case VK_FORMAT_UNDEFINED: return GL_COMPRESSED_RGBA_ASTC_5x5x5_OES; // 4-component ASTC, 5x5x5 blocks, unsigned normalized - case VK_FORMAT_UNDEFINED: return GL_COMPRESSED_RGBA_ASTC_6x5x5_OES; // 4-component ASTC, 6x5x5 blocks, unsigned normalized - case VK_FORMAT_UNDEFINED: return GL_COMPRESSED_RGBA_ASTC_6x6x5_OES; // 4-component ASTC, 6x6x5 blocks, unsigned normalized - case VK_FORMAT_UNDEFINED: return GL_COMPRESSED_RGBA_ASTC_6x6x6_OES; // 4-component ASTC, 6x6x6 blocks, unsigned normalized - - case VK_FORMAT_UNDEFINED: return GL_COMPRESSED_SRGB8_ALPHA8_ASTC_3x3x3_OES; // 4-component ASTC, 3x3x3 blocks, sRGB - case VK_FORMAT_UNDEFINED: return GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x3x3_OES; // 4-component ASTC, 4x3x3 blocks, sRGB - case VK_FORMAT_UNDEFINED: return GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4x3_OES; // 4-component ASTC, 4x4x3 blocks, sRGB - case VK_FORMAT_UNDEFINED: return GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4x4_OES; // 4-component ASTC, 4x4x4 blocks, sRGB - case VK_FORMAT_UNDEFINED: return GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4x4_OES; // 4-component ASTC, 5x4x4 blocks, sRGB - case VK_FORMAT_UNDEFINED: return GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5x4_OES; // 4-component ASTC, 5x5x4 blocks, sRGB - case VK_FORMAT_UNDEFINED: return GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5x5_OES; // 4-component ASTC, 5x5x5 blocks, sRGB - case VK_FORMAT_UNDEFINED: return GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5x5_OES; // 4-component ASTC, 6x5x5 blocks, sRGB - case VK_FORMAT_UNDEFINED: return GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6x5_OES; // 4-component ASTC, 6x6x5 blocks, sRGB - case VK_FORMAT_UNDEFINED: return GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6x6_OES; // 4-component ASTC, 6x6x6 blocks, sRGB -#endif - - // - // Depth/stencil - // - case VK_FORMAT_D16_UNORM: return GL_DEPTH_COMPONENT16; - case VK_FORMAT_X8_D24_UNORM_PACK32: return GL_DEPTH_COMPONENT24; - case VK_FORMAT_D32_SFLOAT: return GL_DEPTH_COMPONENT32F; - case VK_FORMAT_S8_UINT: return GL_STENCIL_INDEX8; - case VK_FORMAT_D24_UNORM_S8_UINT: return GL_DEPTH24_STENCIL8; - case VK_FORMAT_D32_SFLOAT_S8_UINT: return GL_DEPTH32F_STENCIL8; - - default: return GL_INVALID_VALUE; - } -} - #endif // !GL_FORMAT_H diff --git a/thirdparty/libktx/lib/texture2.c b/thirdparty/libktx/lib/texture2.c index 173e5026d9..014612fb57 100644 --- a/thirdparty/libktx/lib/texture2.c +++ b/thirdparty/libktx/lib/texture2.c @@ -20,6 +20,7 @@ #define _CRT_SECURE_NO_WARNINGS #endif +#include <assert.h> #include <stdlib.h> #include <string.h> #include <math.h> @@ -34,12 +35,13 @@ #include "memstream.h" #include "texture2.h" #include "unused.h" -#include "vk_format.h" // FIXME: Test this #define and put it in a header somewhere. //#define IS_BIG_ENDIAN (1 == *(unsigned char *)&(const int){0x01000000ul}) #define IS_BIG_ENDIAN 0 +extern uint32_t vkFormatTypeSize(VkFormat format); + struct ktxTexture_vtbl ktxTexture2_vtbl; struct ktxTexture_vtblInt ktxTexture2_vtblInt; @@ -217,18 +219,18 @@ ktx_uint32_t e5b9g9r9_ufloat_comparator[e5b9g9r9_bdbwordcount] = { #endif /** -* @private -* @~English -* @brief Initialize a ktxFormatSize object from the info in a DFD. -* -* This is used instead of referring to the DFD directly so code dealing -* with format info can be common to KTX 1 & 2. -* -* @param[in] This pointer the ktxTexture2 whose DFD to use. -* @param[in] fi pointer to the ktxFormatSize object to initialize. -* -* @return KTX_TRUE on success, otherwise KTX_FALSE. -*/ + * @private + * @~English + * @brief Initialize a ktxFormatSize object from the info in a DFD. + * + * This is used instead of referring to the DFD directly so code dealing + * with format info can be common to KTX 1 & 2. + * + * @param[in] This pointer the ktxFormatSize to initialize. + * @param[in] pDFD pointer to the DFD whose data to use. + * + * @return KTX_TRUE on success, otherwise KTX_FALSE. + */ bool ktxFormatSize_initFromDfd(ktxFormatSize* This, ktx_uint32_t* pDfd) { @@ -308,9 +310,10 @@ ktxFormatSize_initFromDfd(ktxFormatSize* This, ktx_uint32_t* pDfd) // the following reasons. (1) in v2 files levelIndex is always used to // calculate data size and, of course, for the level offsets. (2) Finer // grain access to supercompressed data than levels is not possible. - uint32_t blockByteLength; - recreateBytesPlane0FromSampleInfo(pDfd, &blockByteLength); - This->blockSizeInBits = blockByteLength * 8; + // + // The value set here is applied to the DFD after the data has been + // inflated during loading. + This->blockSizeInBits = reconstructDFDBytesPlane0FromSamples(pDfd) * 8; } return true; } @@ -427,34 +430,11 @@ ktxTexture2_construct(ktxTexture2* This, ktxTextureCreateInfo* createInfo, This->vkFormat = createInfo->vkFormat; - // Ideally we'd set all these things in ktxFormatSize_initFromDfd - // but This->_protected is not allocated until ktxTexture_construct; - if (This->isCompressed && (formatSize.flags & KTX_FORMAT_SIZE_YUVSDA_BIT) == 0) { - This->_protected->_typeSize = 1; - } else if (formatSize.flags & (KTX_FORMAT_SIZE_DEPTH_BIT | KTX_FORMAT_SIZE_STENCIL_BIT)) { - switch (createInfo->vkFormat) { - case VK_FORMAT_S8_UINT: - This->_protected->_typeSize = 1; - break; - case VK_FORMAT_D16_UNORM: // [[fallthrough]]; - case VK_FORMAT_D16_UNORM_S8_UINT: - This->_protected->_typeSize = 2; - break; - case VK_FORMAT_X8_D24_UNORM_PACK32: // [[fallthrough]]; - case VK_FORMAT_D24_UNORM_S8_UINT: // [[fallthrough]]; - case VK_FORMAT_D32_SFLOAT: // [[fallthrough]]; - case VK_FORMAT_D32_SFLOAT_S8_UINT: - This->_protected->_typeSize = 4; - break; - } - } else if (formatSize.flags & KTX_FORMAT_SIZE_PACKED_BIT) { - This->_protected->_typeSize = formatSize.blockSizeInBits / 8; - } else { - // Unpacked and uncompressed - uint32_t numComponents; - getDFDComponentInfoUnpacked(This->pDfd, &numComponents, - &This->_protected->_typeSize); - } + // The typeSize cannot be reconstructed just from the DFD as the BDFD + // does not capture the packing expressed by the [m]PACK[n] layout + // information in the VkFormat, so we calculate the typeSize directly + // from the vkFormat + This->_protected->_typeSize = vkFormatTypeSize(createInfo->vkFormat); This->supercompressionScheme = KTX_SS_NONE; diff --git a/thirdparty/libktx/lib/vk_format.h b/thirdparty/libktx/lib/vk_format.h index 18adf33b59..ab8a1ecbb6 100644 --- a/thirdparty/libktx/lib/vk_format.h +++ b/thirdparty/libktx/lib/vk_format.h @@ -401,6 +401,7 @@ static inline VkFormat vkGetFormatFromOpenGLFormat( const GLenum format, const G return VK_FORMAT_UNDEFINED; } +#if defined(NEED_VK_GET_FORMAT_FROM_OPENGL_TYPE) static inline VkFormat vkGetFormatFromOpenGLType( const GLenum type, const GLuint numComponents, const GLboolean normalized ) { switch ( type ) @@ -566,6 +567,7 @@ static inline VkFormat vkGetFormatFromOpenGLType( const GLenum type, const GLuin return VK_FORMAT_UNDEFINED; } +#endif static inline VkFormat vkGetFormatFromOpenGLInternalFormat( const GLenum internalFormat ) { @@ -823,6 +825,7 @@ static inline VkFormat vkGetFormatFromOpenGLInternalFormat( const GLenum interna } } +#if defined(NEED_VK_GET_FORMAT_SIZE) static inline void vkGetFormatSize( const VkFormat format, ktxFormatSize * pFormatSize ) { pFormatSize->minBlocksX = pFormatSize->minBlocksY = 1; @@ -1384,5 +1387,6 @@ static inline void vkGetFormatSize( const VkFormat format, ktxFormatSize * pForm break; } } +#endif #endif // !VK_FORMAT_H diff --git a/thirdparty/libktx/lib/vkformat_check.c b/thirdparty/libktx/lib/vkformat_check.c index e987b3d76a..5b86e3c8fe 100644 --- a/thirdparty/libktx/lib/vkformat_check.c +++ b/thirdparty/libktx/lib/vkformat_check.c @@ -30,13 +30,8 @@ isProhibitedFormat(VkFormat format) case VK_FORMAT_R8G8B8A8_SSCALED: case VK_FORMAT_B8G8R8A8_USCALED: case VK_FORMAT_B8G8R8A8_SSCALED: - case VK_FORMAT_A8B8G8R8_UNORM_PACK32: - case VK_FORMAT_A8B8G8R8_SNORM_PACK32: case VK_FORMAT_A8B8G8R8_USCALED_PACK32: case VK_FORMAT_A8B8G8R8_SSCALED_PACK32: - case VK_FORMAT_A8B8G8R8_UINT_PACK32: - case VK_FORMAT_A8B8G8R8_SINT_PACK32: - case VK_FORMAT_A8B8G8R8_SRGB_PACK32: case VK_FORMAT_A2R10G10B10_USCALED_PACK32: case VK_FORMAT_A2R10G10B10_SSCALED_PACK32: case VK_FORMAT_A2B10G10R10_USCALED_PACK32: diff --git a/thirdparty/libktx/lib/vkformat_typesize.c b/thirdparty/libktx/lib/vkformat_typesize.c new file mode 100644 index 0000000000..92fb468045 --- /dev/null +++ b/thirdparty/libktx/lib/vkformat_typesize.c @@ -0,0 +1,584 @@ + +/***************************** Do not edit. ***************************** + Automatically generated from vulkan_core.h version 267 by mkvkformatfiles. + *************************************************************************/ + +/* +** Copyright 2015-2023 The Khronos Group Inc. +** +** SPDX-License-Identifier: Apache-2.0 +*/ + + +#include <stdint.h> + +#include "vkformat_enum.h" + +uint32_t +vkFormatTypeSize(VkFormat format) +{ + switch (format) { + case VK_FORMAT_UNDEFINED: + return 1; + case VK_FORMAT_R4G4_UNORM_PACK8: + return 1; + case VK_FORMAT_R4G4B4A4_UNORM_PACK16: + return 2; + case VK_FORMAT_B4G4R4A4_UNORM_PACK16: + return 2; + case VK_FORMAT_R5G6B5_UNORM_PACK16: + return 2; + case VK_FORMAT_B5G6R5_UNORM_PACK16: + return 2; + case VK_FORMAT_R5G5B5A1_UNORM_PACK16: + return 2; + case VK_FORMAT_B5G5R5A1_UNORM_PACK16: + return 2; + case VK_FORMAT_A1R5G5B5_UNORM_PACK16: + return 2; + case VK_FORMAT_R8_UNORM: + return 1; + case VK_FORMAT_R8_SNORM: + return 1; + case VK_FORMAT_R8_USCALED: + return 1; + case VK_FORMAT_R8_SSCALED: + return 1; + case VK_FORMAT_R8_UINT: + return 1; + case VK_FORMAT_R8_SINT: + return 1; + case VK_FORMAT_R8_SRGB: + return 1; + case VK_FORMAT_R8G8_UNORM: + return 1; + case VK_FORMAT_R8G8_SNORM: + return 1; + case VK_FORMAT_R8G8_USCALED: + return 1; + case VK_FORMAT_R8G8_SSCALED: + return 1; + case VK_FORMAT_R8G8_UINT: + return 1; + case VK_FORMAT_R8G8_SINT: + return 1; + case VK_FORMAT_R8G8_SRGB: + return 1; + case VK_FORMAT_R8G8B8_UNORM: + return 1; + case VK_FORMAT_R8G8B8_SNORM: + return 1; + case VK_FORMAT_R8G8B8_USCALED: + return 1; + case VK_FORMAT_R8G8B8_SSCALED: + return 1; + case VK_FORMAT_R8G8B8_UINT: + return 1; + case VK_FORMAT_R8G8B8_SINT: + return 1; + case VK_FORMAT_R8G8B8_SRGB: + return 1; + case VK_FORMAT_B8G8R8_UNORM: + return 1; + case VK_FORMAT_B8G8R8_SNORM: + return 1; + case VK_FORMAT_B8G8R8_USCALED: + return 1; + case VK_FORMAT_B8G8R8_SSCALED: + return 1; + case VK_FORMAT_B8G8R8_UINT: + return 1; + case VK_FORMAT_B8G8R8_SINT: + return 1; + case VK_FORMAT_B8G8R8_SRGB: + return 1; + case VK_FORMAT_R8G8B8A8_UNORM: + return 1; + case VK_FORMAT_R8G8B8A8_SNORM: + return 1; + case VK_FORMAT_R8G8B8A8_USCALED: + return 1; + case VK_FORMAT_R8G8B8A8_SSCALED: + return 1; + case VK_FORMAT_R8G8B8A8_UINT: + return 1; + case VK_FORMAT_R8G8B8A8_SINT: + return 1; + case VK_FORMAT_R8G8B8A8_SRGB: + return 1; + case VK_FORMAT_B8G8R8A8_UNORM: + return 1; + case VK_FORMAT_B8G8R8A8_SNORM: + return 1; + case VK_FORMAT_B8G8R8A8_USCALED: + return 1; + case VK_FORMAT_B8G8R8A8_SSCALED: + return 1; + case VK_FORMAT_B8G8R8A8_UINT: + return 1; + case VK_FORMAT_B8G8R8A8_SINT: + return 1; + case VK_FORMAT_B8G8R8A8_SRGB: + return 1; + case VK_FORMAT_A8B8G8R8_UNORM_PACK32: + return 4; + case VK_FORMAT_A8B8G8R8_SNORM_PACK32: + return 4; + case VK_FORMAT_A8B8G8R8_USCALED_PACK32: + return 4; + case VK_FORMAT_A8B8G8R8_SSCALED_PACK32: + return 4; + case VK_FORMAT_A8B8G8R8_UINT_PACK32: + return 4; + case VK_FORMAT_A8B8G8R8_SINT_PACK32: + return 4; + case VK_FORMAT_A8B8G8R8_SRGB_PACK32: + return 4; + case VK_FORMAT_A2R10G10B10_UNORM_PACK32: + return 4; + case VK_FORMAT_A2R10G10B10_SNORM_PACK32: + return 4; + case VK_FORMAT_A2R10G10B10_USCALED_PACK32: + return 4; + case VK_FORMAT_A2R10G10B10_SSCALED_PACK32: + return 4; + case VK_FORMAT_A2R10G10B10_UINT_PACK32: + return 4; + case VK_FORMAT_A2R10G10B10_SINT_PACK32: + return 4; + case VK_FORMAT_A2B10G10R10_UNORM_PACK32: + return 4; + case VK_FORMAT_A2B10G10R10_SNORM_PACK32: + return 4; + case VK_FORMAT_A2B10G10R10_USCALED_PACK32: + return 4; + case VK_FORMAT_A2B10G10R10_SSCALED_PACK32: + return 4; + case VK_FORMAT_A2B10G10R10_UINT_PACK32: + return 4; + case VK_FORMAT_A2B10G10R10_SINT_PACK32: + return 4; + case VK_FORMAT_R16_UNORM: + return 2; + case VK_FORMAT_R16_SNORM: + return 2; + case VK_FORMAT_R16_USCALED: + return 2; + case VK_FORMAT_R16_SSCALED: + return 2; + case VK_FORMAT_R16_UINT: + return 2; + case VK_FORMAT_R16_SINT: + return 2; + case VK_FORMAT_R16_SFLOAT: + return 2; + case VK_FORMAT_R16G16_UNORM: + return 2; + case VK_FORMAT_R16G16_SNORM: + return 2; + case VK_FORMAT_R16G16_USCALED: + return 2; + case VK_FORMAT_R16G16_SSCALED: + return 2; + case VK_FORMAT_R16G16_UINT: + return 2; + case VK_FORMAT_R16G16_SINT: + return 2; + case VK_FORMAT_R16G16_SFLOAT: + return 2; + case VK_FORMAT_R16G16B16_UNORM: + return 2; + case VK_FORMAT_R16G16B16_SNORM: + return 2; + case VK_FORMAT_R16G16B16_USCALED: + return 2; + case VK_FORMAT_R16G16B16_SSCALED: + return 2; + case VK_FORMAT_R16G16B16_UINT: + return 2; + case VK_FORMAT_R16G16B16_SINT: + return 2; + case VK_FORMAT_R16G16B16_SFLOAT: + return 2; + case VK_FORMAT_R16G16B16A16_UNORM: + return 2; + case VK_FORMAT_R16G16B16A16_SNORM: + return 2; + case VK_FORMAT_R16G16B16A16_USCALED: + return 2; + case VK_FORMAT_R16G16B16A16_SSCALED: + return 2; + case VK_FORMAT_R16G16B16A16_UINT: + return 2; + case VK_FORMAT_R16G16B16A16_SINT: + return 2; + case VK_FORMAT_R16G16B16A16_SFLOAT: + return 2; + case VK_FORMAT_R32_UINT: + return 4; + case VK_FORMAT_R32_SINT: + return 4; + case VK_FORMAT_R32_SFLOAT: + return 4; + case VK_FORMAT_R32G32_UINT: + return 4; + case VK_FORMAT_R32G32_SINT: + return 4; + case VK_FORMAT_R32G32_SFLOAT: + return 4; + case VK_FORMAT_R32G32B32_UINT: + return 4; + case VK_FORMAT_R32G32B32_SINT: + return 4; + case VK_FORMAT_R32G32B32_SFLOAT: + return 4; + case VK_FORMAT_R32G32B32A32_UINT: + return 4; + case VK_FORMAT_R32G32B32A32_SINT: + return 4; + case VK_FORMAT_R32G32B32A32_SFLOAT: + return 4; + case VK_FORMAT_R64_UINT: + return 8; + case VK_FORMAT_R64_SINT: + return 8; + case VK_FORMAT_R64_SFLOAT: + return 8; + case VK_FORMAT_R64G64_UINT: + return 8; + case VK_FORMAT_R64G64_SINT: + return 8; + case VK_FORMAT_R64G64_SFLOAT: + return 8; + case VK_FORMAT_R64G64B64_UINT: + return 8; + case VK_FORMAT_R64G64B64_SINT: + return 8; + case VK_FORMAT_R64G64B64_SFLOAT: + return 8; + case VK_FORMAT_R64G64B64A64_UINT: + return 8; + case VK_FORMAT_R64G64B64A64_SINT: + return 8; + case VK_FORMAT_R64G64B64A64_SFLOAT: + return 8; + case VK_FORMAT_B10G11R11_UFLOAT_PACK32: + return 4; + case VK_FORMAT_E5B9G9R9_UFLOAT_PACK32: + return 4; + case VK_FORMAT_D16_UNORM: + return 2; + case VK_FORMAT_X8_D24_UNORM_PACK32: + return 4; + case VK_FORMAT_D32_SFLOAT: + return 4; + case VK_FORMAT_S8_UINT: + return 1; + case VK_FORMAT_D16_UNORM_S8_UINT: + return 2; + case VK_FORMAT_D24_UNORM_S8_UINT: + return 4; + case VK_FORMAT_D32_SFLOAT_S8_UINT: + return 4; + case VK_FORMAT_BC1_RGB_UNORM_BLOCK: + return 1; + case VK_FORMAT_BC1_RGB_SRGB_BLOCK: + return 1; + case VK_FORMAT_BC1_RGBA_UNORM_BLOCK: + return 1; + case VK_FORMAT_BC1_RGBA_SRGB_BLOCK: + return 1; + case VK_FORMAT_BC2_UNORM_BLOCK: + return 1; + case VK_FORMAT_BC2_SRGB_BLOCK: + return 1; + case VK_FORMAT_BC3_UNORM_BLOCK: + return 1; + case VK_FORMAT_BC3_SRGB_BLOCK: + return 1; + case VK_FORMAT_BC4_UNORM_BLOCK: + return 1; + case VK_FORMAT_BC4_SNORM_BLOCK: + return 1; + case VK_FORMAT_BC5_UNORM_BLOCK: + return 1; + case VK_FORMAT_BC5_SNORM_BLOCK: + return 1; + case VK_FORMAT_BC6H_UFLOAT_BLOCK: + return 1; + case VK_FORMAT_BC6H_SFLOAT_BLOCK: + return 1; + case VK_FORMAT_BC7_UNORM_BLOCK: + return 1; + case VK_FORMAT_BC7_SRGB_BLOCK: + return 1; + case VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK: + return 1; + case VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK: + return 1; + case VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK: + return 1; + case VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK: + return 1; + case VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK: + return 1; + case VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK: + return 1; + case VK_FORMAT_EAC_R11_UNORM_BLOCK: + return 1; + case VK_FORMAT_EAC_R11_SNORM_BLOCK: + return 1; + case VK_FORMAT_EAC_R11G11_UNORM_BLOCK: + return 1; + case VK_FORMAT_EAC_R11G11_SNORM_BLOCK: + return 1; + case VK_FORMAT_ASTC_4x4_UNORM_BLOCK: + return 1; + case VK_FORMAT_ASTC_4x4_SRGB_BLOCK: + return 1; + case VK_FORMAT_ASTC_5x4_UNORM_BLOCK: + return 1; + case VK_FORMAT_ASTC_5x4_SRGB_BLOCK: + return 1; + case VK_FORMAT_ASTC_5x5_UNORM_BLOCK: + return 1; + case VK_FORMAT_ASTC_5x5_SRGB_BLOCK: + return 1; + case VK_FORMAT_ASTC_6x5_UNORM_BLOCK: + return 1; + case VK_FORMAT_ASTC_6x5_SRGB_BLOCK: + return 1; + case VK_FORMAT_ASTC_6x6_UNORM_BLOCK: + return 1; + case VK_FORMAT_ASTC_6x6_SRGB_BLOCK: + return 1; + case VK_FORMAT_ASTC_8x5_UNORM_BLOCK: + return 1; + case VK_FORMAT_ASTC_8x5_SRGB_BLOCK: + return 1; + case VK_FORMAT_ASTC_8x6_UNORM_BLOCK: + return 1; + case VK_FORMAT_ASTC_8x6_SRGB_BLOCK: + return 1; + case VK_FORMAT_ASTC_8x8_UNORM_BLOCK: + return 1; + case VK_FORMAT_ASTC_8x8_SRGB_BLOCK: + return 1; + case VK_FORMAT_ASTC_10x5_UNORM_BLOCK: + return 1; + case VK_FORMAT_ASTC_10x5_SRGB_BLOCK: + return 1; + case VK_FORMAT_ASTC_10x6_UNORM_BLOCK: + return 1; + case VK_FORMAT_ASTC_10x6_SRGB_BLOCK: + return 1; + case VK_FORMAT_ASTC_10x8_UNORM_BLOCK: + return 1; + case VK_FORMAT_ASTC_10x8_SRGB_BLOCK: + return 1; + case VK_FORMAT_ASTC_10x10_UNORM_BLOCK: + return 1; + case VK_FORMAT_ASTC_10x10_SRGB_BLOCK: + return 1; + case VK_FORMAT_ASTC_12x10_UNORM_BLOCK: + return 1; + case VK_FORMAT_ASTC_12x10_SRGB_BLOCK: + return 1; + case VK_FORMAT_ASTC_12x12_UNORM_BLOCK: + return 1; + case VK_FORMAT_ASTC_12x12_SRGB_BLOCK: + return 1; + case VK_FORMAT_G8B8G8R8_422_UNORM: + return 1; + case VK_FORMAT_B8G8R8G8_422_UNORM: + return 1; + case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM: + return 1; + case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM: + return 1; + case VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM: + return 1; + case VK_FORMAT_G8_B8R8_2PLANE_422_UNORM: + return 1; + case VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM: + return 1; + case VK_FORMAT_R10X6_UNORM_PACK16: + return 2; + case VK_FORMAT_R10X6G10X6_UNORM_2PACK16: + return 2; + case VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16: + return 2; + case VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16: + return 2; + case VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16: + return 2; + case VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16: + return 2; + case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16: + return 2; + case VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16: + return 2; + case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16: + return 2; + case VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16: + return 2; + case VK_FORMAT_R12X4_UNORM_PACK16: + return 2; + case VK_FORMAT_R12X4G12X4_UNORM_2PACK16: + return 2; + case VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16: + return 2; + case VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16: + return 2; + case VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16: + return 2; + case VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16: + return 2; + case VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16: + return 2; + case VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16: + return 2; + case VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16: + return 2; + case VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16: + return 2; + case VK_FORMAT_G16B16G16R16_422_UNORM: + return 2; + case VK_FORMAT_B16G16R16G16_422_UNORM: + return 2; + case VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM: + return 2; + case VK_FORMAT_G16_B16R16_2PLANE_420_UNORM: + return 2; + case VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM: + return 2; + case VK_FORMAT_G16_B16R16_2PLANE_422_UNORM: + return 2; + case VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM: + return 2; + case VK_FORMAT_G8_B8R8_2PLANE_444_UNORM: + return 1; + case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_444_UNORM_3PACK16: + return 2; + case VK_FORMAT_G12X4_B12X4R12X4_2PLANE_444_UNORM_3PACK16: + return 2; + case VK_FORMAT_G16_B16R16_2PLANE_444_UNORM: + return 2; + case VK_FORMAT_A4R4G4B4_UNORM_PACK16: + return 2; + case VK_FORMAT_A4B4G4R4_UNORM_PACK16: + return 2; + case VK_FORMAT_ASTC_4x4_SFLOAT_BLOCK: + return 1; + case VK_FORMAT_ASTC_5x4_SFLOAT_BLOCK: + return 1; + case VK_FORMAT_ASTC_5x5_SFLOAT_BLOCK: + return 1; + case VK_FORMAT_ASTC_6x5_SFLOAT_BLOCK: + return 1; + case VK_FORMAT_ASTC_6x6_SFLOAT_BLOCK: + return 1; + case VK_FORMAT_ASTC_8x5_SFLOAT_BLOCK: + return 1; + case VK_FORMAT_ASTC_8x6_SFLOAT_BLOCK: + return 1; + case VK_FORMAT_ASTC_8x8_SFLOAT_BLOCK: + return 1; + case VK_FORMAT_ASTC_10x5_SFLOAT_BLOCK: + return 1; + case VK_FORMAT_ASTC_10x6_SFLOAT_BLOCK: + return 1; + case VK_FORMAT_ASTC_10x8_SFLOAT_BLOCK: + return 1; + case VK_FORMAT_ASTC_10x10_SFLOAT_BLOCK: + return 1; + case VK_FORMAT_ASTC_12x10_SFLOAT_BLOCK: + return 1; + case VK_FORMAT_ASTC_12x12_SFLOAT_BLOCK: + return 1; + case VK_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG: + return 1; + case VK_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG: + return 1; + case VK_FORMAT_PVRTC2_2BPP_UNORM_BLOCK_IMG: + return 1; + case VK_FORMAT_PVRTC2_4BPP_UNORM_BLOCK_IMG: + return 1; + case VK_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG: + return 1; + case VK_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG: + return 1; + case VK_FORMAT_PVRTC2_2BPP_SRGB_BLOCK_IMG: + return 1; + case VK_FORMAT_PVRTC2_4BPP_SRGB_BLOCK_IMG: + return 1; + case VK_FORMAT_ASTC_3x3x3_UNORM_BLOCK_EXT: + return 1; + case VK_FORMAT_ASTC_3x3x3_SRGB_BLOCK_EXT: + return 1; + case VK_FORMAT_ASTC_3x3x3_SFLOAT_BLOCK_EXT: + return 1; + case VK_FORMAT_ASTC_4x3x3_UNORM_BLOCK_EXT: + return 1; + case VK_FORMAT_ASTC_4x3x3_SRGB_BLOCK_EXT: + return 1; + case VK_FORMAT_ASTC_4x3x3_SFLOAT_BLOCK_EXT: + return 1; + case VK_FORMAT_ASTC_4x4x3_UNORM_BLOCK_EXT: + return 1; + case VK_FORMAT_ASTC_4x4x3_SRGB_BLOCK_EXT: + return 1; + case VK_FORMAT_ASTC_4x4x3_SFLOAT_BLOCK_EXT: + return 1; + case VK_FORMAT_ASTC_4x4x4_UNORM_BLOCK_EXT: + return 1; + case VK_FORMAT_ASTC_4x4x4_SRGB_BLOCK_EXT: + return 1; + case VK_FORMAT_ASTC_4x4x4_SFLOAT_BLOCK_EXT: + return 1; + case VK_FORMAT_ASTC_5x4x4_UNORM_BLOCK_EXT: + return 1; + case VK_FORMAT_ASTC_5x4x4_SRGB_BLOCK_EXT: + return 1; + case VK_FORMAT_ASTC_5x4x4_SFLOAT_BLOCK_EXT: + return 1; + case VK_FORMAT_ASTC_5x5x4_UNORM_BLOCK_EXT: + return 1; + case VK_FORMAT_ASTC_5x5x4_SRGB_BLOCK_EXT: + return 1; + case VK_FORMAT_ASTC_5x5x4_SFLOAT_BLOCK_EXT: + return 1; + case VK_FORMAT_ASTC_5x5x5_UNORM_BLOCK_EXT: + return 1; + case VK_FORMAT_ASTC_5x5x5_SRGB_BLOCK_EXT: + return 1; + case VK_FORMAT_ASTC_5x5x5_SFLOAT_BLOCK_EXT: + return 1; + case VK_FORMAT_ASTC_6x5x5_UNORM_BLOCK_EXT: + return 1; + case VK_FORMAT_ASTC_6x5x5_SRGB_BLOCK_EXT: + return 1; + case VK_FORMAT_ASTC_6x5x5_SFLOAT_BLOCK_EXT: + return 1; + case VK_FORMAT_ASTC_6x6x5_UNORM_BLOCK_EXT: + return 1; + case VK_FORMAT_ASTC_6x6x5_SRGB_BLOCK_EXT: + return 1; + case VK_FORMAT_ASTC_6x6x5_SFLOAT_BLOCK_EXT: + return 1; + case VK_FORMAT_ASTC_6x6x6_UNORM_BLOCK_EXT: + return 1; + case VK_FORMAT_ASTC_6x6x6_SRGB_BLOCK_EXT: + return 1; + case VK_FORMAT_ASTC_6x6x6_SFLOAT_BLOCK_EXT: + return 1; + case VK_FORMAT_R16G16_S10_5_NV: + return 2; + case VK_FORMAT_A1B5G5R5_UNORM_PACK16_KHR: + return 2; + case VK_FORMAT_A8_UNORM_KHR: + return 1; + default: + return 0; + } +} diff --git a/thirdparty/libktx/patches/godot.patch b/thirdparty/libktx/patches/godot.patch index 28db86cf9b..13468813fb 100644 --- a/thirdparty/libktx/patches/godot.patch +++ b/thirdparty/libktx/patches/godot.patch @@ -16,7 +16,7 @@ index ca68545e4a..d7ecb7a0fd 100644 #undef DECLARE_PRIVATE #undef DECLARE_PROTECTED diff --git a/thirdparty/libktx/lib/dfdutils/vk2dfd.inl b/thirdparty/libktx/lib/dfdutils/vk2dfd.inl -index 85d53202a5..25c7a2c238 100644 +index 5104c8fcb4..3398441e8c 100644 --- a/thirdparty/libktx/lib/dfdutils/vk2dfd.inl +++ b/thirdparty/libktx/lib/dfdutils/vk2dfd.inl @@ -370,6 +370,7 @@ case VK_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG: return createDFDCompressed(c_PVRTC, 8 @@ -32,9 +32,9 @@ index 85d53202a5..25c7a2c238 100644 case VK_FORMAT_ASTC_6x6x6_SRGB_BLOCK_EXT: return createDFDCompressed(c_ASTC, 6, 6, 6, s_SRGB); case VK_FORMAT_ASTC_6x6x6_SFLOAT_BLOCK_EXT: return createDFDCompressed(c_ASTC, 6, 6, 6, s_SFLOAT); +#endif + case VK_FORMAT_R16G16_S10_5_NV: return createDFDUnpacked(0, 2, 2, 0, s_S10_5); case VK_FORMAT_A1B5G5R5_UNORM_PACK16_KHR: { int channels[] = {0,1,2,3}; int bits[] = {5,5,5,1}; - return createDFDPacked(0, 4, bits, channels, s_UNORM); diff --git a/thirdparty/libktx/lib/miniz_wrapper.cpp b/thirdparty/libktx/lib/miniz_wrapper.cpp index 07920c4809..cbd7da540a 100644 --- a/thirdparty/libktx/lib/miniz_wrapper.cpp diff --git a/thirdparty/mbedtls/include/mbedtls/aesni.h b/thirdparty/mbedtls/include/mbedtls/aesni.h index b636c100ae..93f067304d 100644 --- a/thirdparty/mbedtls/include/mbedtls/aesni.h +++ b/thirdparty/mbedtls/include/mbedtls/aesni.h @@ -46,7 +46,7 @@ * macros that may change in future releases. */ #undef MBEDTLS_AESNI_HAVE_INTRINSICS -#if defined(_MSC_VER) +#if defined(_MSC_VER) && !defined(__clang__) /* Visual Studio supports AESNI intrinsics since VS 2008 SP1. We only support * VS 2013 and up for other reasons anyway, so no need to check the version. */ #define MBEDTLS_AESNI_HAVE_INTRINSICS @@ -54,7 +54,7 @@ /* GCC-like compilers: currently, we only support intrinsics if the requisite * target flag is enabled when building the library (e.g. `gcc -mpclmul -msse2` * or `clang -maes -mpclmul`). */ -#if defined(__GNUC__) && defined(__AES__) && defined(__PCLMUL__) +#if (defined(__GNUC__) || defined(__clang__)) && defined(__AES__) && defined(__PCLMUL__) #define MBEDTLS_AESNI_HAVE_INTRINSICS #endif diff --git a/thirdparty/mbedtls/include/mbedtls/config.h b/thirdparty/mbedtls/include/mbedtls/config.h index ac2146ea11..4842fd494c 100644 --- a/thirdparty/mbedtls/include/mbedtls/config.h +++ b/thirdparty/mbedtls/include/mbedtls/config.h @@ -1571,6 +1571,26 @@ //#define MBEDTLS_PSA_INJECT_ENTROPY /** + * \def MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS + * + * Assume all buffers passed to PSA functions are owned exclusively by the + * PSA function and are not stored in shared memory. + * + * This option may be enabled if all buffers passed to any PSA function reside + * in memory that is accessible only to the PSA function during its execution. + * + * This option MUST be disabled whenever buffer arguments are in memory shared + * with an untrusted party, for example where arguments to PSA calls are passed + * across a trust boundary. + * + * \note Enabling this option reduces memory usage and code size. + * + * \note Enabling this option causes overlap of input and output buffers + * not to be supported by PSA functions. + */ +//#define MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS + +/** * \def MBEDTLS_RSA_NO_CRT * * Do not use the Chinese Remainder Theorem diff --git a/thirdparty/mbedtls/include/mbedtls/ecp.h b/thirdparty/mbedtls/include/mbedtls/ecp.h index e4e40c003c..33ea14d7e2 100644 --- a/thirdparty/mbedtls/include/mbedtls/ecp.h +++ b/thirdparty/mbedtls/include/mbedtls/ecp.h @@ -1265,6 +1265,8 @@ int mbedtls_ecp_gen_key(mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key, /** * \brief This function reads an elliptic curve private key. * + * \note This function does not support Curve448 yet. + * * \param grp_id The ECP group identifier. * \param key The destination key. * \param buf The buffer containing the binary representation of the @@ -1286,17 +1288,43 @@ int mbedtls_ecp_read_key(mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key, /** * \brief This function exports an elliptic curve private key. * + * \note Note that although this function accepts an output + * buffer that is smaller or larger than the key, most key + * import interfaces require the output to have exactly + * key's nominal length. It is generally simplest to + * pass the key's nominal length as \c buflen, after + * checking that the output buffer is large enough. + * See the description of the \p buflen parameter for + * how to calculate the nominal length. + * + * \note If the private key was not set in \p key, + * the output is unspecified. Future versions + * may return an error in that case. + * + * \note This function does not support Curve448 yet. + * * \param key The private key. * \param buf The output buffer for containing the binary representation - * of the key. (Big endian integer for Weierstrass curves, byte - * string for Montgomery curves.) + * of the key. + * For Weierstrass curves, this is the big-endian + * representation, padded with null bytes at the beginning + * to reach \p buflen bytes. + * For Montgomery curves, this is the standard byte string + * representation (which is little-endian), padded with + * null bytes at the end to reach \p buflen bytes. * \param buflen The total length of the buffer in bytes. + * The length of the output is + * (`grp->nbits` + 7) / 8 bytes + * where `grp->nbits` is the private key size in bits. + * For Weierstrass keys, if the output buffer is smaller, + * leading zeros are trimmed to fit if possible. For + * Montgomery keys, the output buffer must always be large + * enough for the nominal length. * * \return \c 0 on success. - * \return #MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL if the \p key - representation is larger than the available space in \p buf. - * \return #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the operation for - * the group is not implemented. + * \return #MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL or + * #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if the \p key + * representation is larger than the available space in \p buf. * \return Another negative error code on different kinds of failure. */ int mbedtls_ecp_write_key(mbedtls_ecp_keypair *key, diff --git a/thirdparty/mbedtls/include/mbedtls/net_sockets.h b/thirdparty/mbedtls/include/mbedtls/net_sockets.h index 2d3fe3f949..1a12c9c803 100644 --- a/thirdparty/mbedtls/include/mbedtls/net_sockets.h +++ b/thirdparty/mbedtls/include/mbedtls/net_sockets.h @@ -140,7 +140,7 @@ int mbedtls_net_bind(mbedtls_net_context *ctx, const char *bind_ip, const char * * \param client_ctx Will contain the connected client socket * \param client_ip Will contain the client IP address, can be NULL * \param buf_size Size of the client_ip buffer - * \param ip_len Will receive the size of the client IP written, + * \param cip_len Will receive the size of the client IP written, * can be NULL if client_ip is null * * \return 0 if successful, or @@ -153,7 +153,7 @@ int mbedtls_net_bind(mbedtls_net_context *ctx, const char *bind_ip, const char * */ int mbedtls_net_accept(mbedtls_net_context *bind_ctx, mbedtls_net_context *client_ctx, - void *client_ip, size_t buf_size, size_t *ip_len); + void *client_ip, size_t buf_size, size_t *cip_len); /** * \brief Check and wait for the context to be ready for read/write diff --git a/thirdparty/mbedtls/include/mbedtls/version.h b/thirdparty/mbedtls/include/mbedtls/version.h index 0533bca681..bbe76b1739 100644 --- a/thirdparty/mbedtls/include/mbedtls/version.h +++ b/thirdparty/mbedtls/include/mbedtls/version.h @@ -26,16 +26,16 @@ */ #define MBEDTLS_VERSION_MAJOR 2 #define MBEDTLS_VERSION_MINOR 28 -#define MBEDTLS_VERSION_PATCH 7 +#define MBEDTLS_VERSION_PATCH 8 /** * The single version number has the following structure: * MMNNPP00 * Major version | Minor version | Patch version */ -#define MBEDTLS_VERSION_NUMBER 0x021C0700 -#define MBEDTLS_VERSION_STRING "2.28.7" -#define MBEDTLS_VERSION_STRING_FULL "Mbed TLS 2.28.7" +#define MBEDTLS_VERSION_NUMBER 0x021C0800 +#define MBEDTLS_VERSION_STRING "2.28.8" +#define MBEDTLS_VERSION_STRING_FULL "Mbed TLS 2.28.8" #if defined(MBEDTLS_VERSION_C) diff --git a/thirdparty/mbedtls/library/aes.c b/thirdparty/mbedtls/library/aes.c index 24d7ab92fb..836367cea7 100644 --- a/thirdparty/mbedtls/library/aes.c +++ b/thirdparty/mbedtls/library/aes.c @@ -322,7 +322,7 @@ static const uint32_t RT3[256] = { RT }; /* * Round constants */ -static const uint32_t RCON[10] = +static const uint32_t round_constants[10] = { 0x00000001, 0x00000002, 0x00000004, 0x00000008, 0x00000010, 0x00000020, 0x00000040, 0x00000080, @@ -369,7 +369,7 @@ static uint32_t RT3[256]; /* * Round constants */ -static uint32_t RCON[10]; +static uint32_t round_constants[10]; /* * Tables generation code @@ -399,7 +399,7 @@ static void aes_gen_tables(void) * calculate the round constants */ for (i = 0, x = 1; i < 10; i++) { - RCON[i] = (uint32_t) x; + round_constants[i] = (uint32_t) x; x = MBEDTLS_BYTE_0(XTIME(x)); } @@ -625,7 +625,7 @@ int mbedtls_aes_setkey_enc(mbedtls_aes_context *ctx, const unsigned char *key, case 10: for (i = 0; i < 10; i++, RK += 4) { - RK[4] = RK[0] ^ RCON[i] ^ + RK[4] = RK[0] ^ round_constants[i] ^ ((uint32_t) FSb[MBEDTLS_BYTE_1(RK[3])]) ^ ((uint32_t) FSb[MBEDTLS_BYTE_2(RK[3])] << 8) ^ ((uint32_t) FSb[MBEDTLS_BYTE_3(RK[3])] << 16) ^ @@ -640,7 +640,7 @@ int mbedtls_aes_setkey_enc(mbedtls_aes_context *ctx, const unsigned char *key, case 12: for (i = 0; i < 8; i++, RK += 6) { - RK[6] = RK[0] ^ RCON[i] ^ + RK[6] = RK[0] ^ round_constants[i] ^ ((uint32_t) FSb[MBEDTLS_BYTE_1(RK[5])]) ^ ((uint32_t) FSb[MBEDTLS_BYTE_2(RK[5])] << 8) ^ ((uint32_t) FSb[MBEDTLS_BYTE_3(RK[5])] << 16) ^ @@ -657,7 +657,7 @@ int mbedtls_aes_setkey_enc(mbedtls_aes_context *ctx, const unsigned char *key, case 14: for (i = 0; i < 7; i++, RK += 8) { - RK[8] = RK[0] ^ RCON[i] ^ + RK[8] = RK[0] ^ round_constants[i] ^ ((uint32_t) FSb[MBEDTLS_BYTE_1(RK[7])]) ^ ((uint32_t) FSb[MBEDTLS_BYTE_2(RK[7])] << 8) ^ ((uint32_t) FSb[MBEDTLS_BYTE_3(RK[7])] << 16) ^ diff --git a/thirdparty/mbedtls/library/aesni.c b/thirdparty/mbedtls/library/aesni.c index dd84c2b4ea..74bae91f5e 100644 --- a/thirdparty/mbedtls/library/aesni.c +++ b/thirdparty/mbedtls/library/aesni.c @@ -27,10 +27,12 @@ #if defined(MBEDTLS_AESNI_HAVE_CODE) #if MBEDTLS_AESNI_HAVE_CODE == 2 -#if !defined(_WIN32) +#if defined(__GNUC__) #include <cpuid.h> -#else +#elif defined(_MSC_VER) #include <intrin.h> +#else +#error "`__cpuid` required by MBEDTLS_AESNI_C is not supported by the compiler" #endif #include <immintrin.h> #endif @@ -45,7 +47,7 @@ int mbedtls_aesni_has_support(unsigned int what) if (!done) { #if MBEDTLS_AESNI_HAVE_CODE == 2 - static unsigned info[4] = { 0, 0, 0, 0 }; + static int info[4] = { 0, 0, 0, 0 }; #if defined(_MSC_VER) __cpuid(info, 1); #else @@ -179,7 +181,7 @@ void mbedtls_aesni_gcm_mult(unsigned char c[16], const unsigned char a[16], const unsigned char b[16]) { - __m128i aa, bb, cc, dd; + __m128i aa = { 0 }, bb = { 0 }, cc, dd; /* The inputs are in big-endian order, so byte-reverse them */ for (size_t i = 0; i < 16; i++) { diff --git a/thirdparty/mbedtls/library/common.h b/thirdparty/mbedtls/library/common.h index bf18d725cc..49e2c97ea0 100644 --- a/thirdparty/mbedtls/library/common.h +++ b/thirdparty/mbedtls/library/common.h @@ -350,4 +350,31 @@ static inline const unsigned char *mbedtls_buffer_offset_const( #define MBEDTLS_STATIC_ASSERT(expr, msg) #endif +/* Suppress compiler warnings for unused functions and variables. */ +#if !defined(MBEDTLS_MAYBE_UNUSED) && defined(__has_attribute) +# if __has_attribute(unused) +# define MBEDTLS_MAYBE_UNUSED __attribute__((unused)) +# endif +#endif +#if !defined(MBEDTLS_MAYBE_UNUSED) && defined(__GNUC__) +# define MBEDTLS_MAYBE_UNUSED __attribute__((unused)) +#endif +#if !defined(MBEDTLS_MAYBE_UNUSED) && defined(__IAR_SYSTEMS_ICC__) && defined(__VER__) +/* IAR does support __attribute__((unused)), but only if the -e flag (extended language support) + * is given; the pragma always works. + * Unfortunately the pragma affects the rest of the file where it is used, but this is harmless. + * Check for version 5.2 or later - this pragma may be supported by earlier versions, but I wasn't + * able to find documentation). + */ +# if (__VER__ >= 5020000) +# define MBEDTLS_MAYBE_UNUSED _Pragma("diag_suppress=Pe177") +# endif +#endif +#if !defined(MBEDTLS_MAYBE_UNUSED) && defined(_MSC_VER) +# define MBEDTLS_MAYBE_UNUSED __pragma(warning(suppress:4189)) +#endif +#if !defined(MBEDTLS_MAYBE_UNUSED) +# define MBEDTLS_MAYBE_UNUSED +#endif + #endif /* MBEDTLS_LIBRARY_COMMON_H */ diff --git a/thirdparty/mbedtls/library/ecp.c b/thirdparty/mbedtls/library/ecp.c index 31a6b9e305..cfe02b0d2c 100644 --- a/thirdparty/mbedtls/library/ecp.c +++ b/thirdparty/mbedtls/library/ecp.c @@ -927,7 +927,7 @@ int mbedtls_ecp_point_read_binary(const mbedtls_ecp_group *grp, size_t plen; ECP_VALIDATE_RET(grp != NULL); ECP_VALIDATE_RET(pt != NULL); - ECP_VALIDATE_RET(buf != NULL); + ECP_VALIDATE_RET(ilen == 0 || buf != NULL); if (ilen < 1) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; @@ -996,7 +996,7 @@ int mbedtls_ecp_tls_read_point(const mbedtls_ecp_group *grp, ECP_VALIDATE_RET(grp != NULL); ECP_VALIDATE_RET(pt != NULL); ECP_VALIDATE_RET(buf != NULL); - ECP_VALIDATE_RET(*buf != NULL); + ECP_VALIDATE_RET(buf_len == 0 || *buf != NULL); /* * We must have at least two bytes (1 for length, at least one for data) @@ -1068,7 +1068,7 @@ int mbedtls_ecp_tls_read_group(mbedtls_ecp_group *grp, mbedtls_ecp_group_id grp_id; ECP_VALIDATE_RET(grp != NULL); ECP_VALIDATE_RET(buf != NULL); - ECP_VALIDATE_RET(*buf != NULL); + ECP_VALIDATE_RET(len == 0 || *buf != NULL); if ((ret = mbedtls_ecp_tls_read_group_id(&grp_id, buf, len)) != 0) { return ret; @@ -1088,7 +1088,7 @@ int mbedtls_ecp_tls_read_group_id(mbedtls_ecp_group_id *grp, const mbedtls_ecp_curve_info *curve_info; ECP_VALIDATE_RET(grp != NULL); ECP_VALIDATE_RET(buf != NULL); - ECP_VALIDATE_RET(*buf != NULL); + ECP_VALIDATE_RET(len == 0 || *buf != NULL); /* * We expect at least three bytes (see below) @@ -2614,8 +2614,8 @@ static int ecp_mul_mxz(mbedtls_ecp_group *grp, mbedtls_ecp_point *R, /* RP.X might be slightly larger than P, so reduce it */ MOD_ADD(RP.X); + /* Randomize coordinates of the starting point */ #if defined(MBEDTLS_ECP_NO_INTERNAL_RNG) - /* Derandomize coordinates of the starting point */ if (f_rng == NULL) { have_rng = 0; } @@ -3358,10 +3358,10 @@ cleanup: int mbedtls_ecp_write_key(mbedtls_ecp_keypair *key, unsigned char *buf, size_t buflen) { - int ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; ECP_VALIDATE_RET(key != NULL); - ECP_VALIDATE_RET(buf != NULL); + ECP_VALIDATE_RET(buflen == 0 || buf != NULL); #if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED) if (mbedtls_ecp_get_type(&key->grp) == MBEDTLS_ECP_TYPE_MONTGOMERY) { diff --git a/thirdparty/mbedtls/library/ecp_curves.c b/thirdparty/mbedtls/library/ecp_curves.c index c7565cce5d..61a1046f3a 100644 --- a/thirdparty/mbedtls/library/ecp_curves.c +++ b/thirdparty/mbedtls/library/ecp_curves.c @@ -535,10 +535,10 @@ static inline void ecp_mpi_load(mbedtls_mpi *X, const mbedtls_mpi_uint *p, size_ */ static inline void ecp_mpi_set1(mbedtls_mpi *X) { - static mbedtls_mpi_uint one[] = { 1 }; + static const mbedtls_mpi_uint one[] = { 1 }; X->s = 1; X->n = 1; - X->p = one; + X->p = (mbedtls_mpi_uint *) one; /* X->p will not be modified so the cast is safe */ } /* @@ -1348,7 +1348,7 @@ cleanup: */ #define P_KOBLITZ_MAX (256 / 8 / sizeof(mbedtls_mpi_uint)) // Max limbs in P #define P_KOBLITZ_R (8 / sizeof(mbedtls_mpi_uint)) // Limbs in R -static inline int ecp_mod_koblitz(mbedtls_mpi *N, mbedtls_mpi_uint *Rp, size_t p_limbs, +static inline int ecp_mod_koblitz(mbedtls_mpi *N, const mbedtls_mpi_uint *Rp, size_t p_limbs, size_t adjust, size_t shift, mbedtls_mpi_uint mask) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; @@ -1362,7 +1362,7 @@ static inline int ecp_mod_koblitz(mbedtls_mpi *N, mbedtls_mpi_uint *Rp, size_t p /* Init R */ R.s = 1; - R.p = Rp; + R.p = (mbedtls_mpi_uint *) Rp; /* R.p will not be modified so the cast is safe */ R.n = P_KOBLITZ_R; /* Common setup for M */ @@ -1433,7 +1433,7 @@ cleanup: */ static int ecp_mod_p192k1(mbedtls_mpi *N) { - static mbedtls_mpi_uint Rp[] = { + static const mbedtls_mpi_uint Rp[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x11, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00) }; @@ -1450,7 +1450,7 @@ static int ecp_mod_p192k1(mbedtls_mpi *N) */ static int ecp_mod_p224k1(mbedtls_mpi *N) { - static mbedtls_mpi_uint Rp[] = { + static const mbedtls_mpi_uint Rp[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0x1A, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00) }; @@ -1472,7 +1472,7 @@ static int ecp_mod_p224k1(mbedtls_mpi *N) */ static int ecp_mod_p256k1(mbedtls_mpi *N) { - static mbedtls_mpi_uint Rp[] = { + static const mbedtls_mpi_uint Rp[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00) }; diff --git a/thirdparty/mbedtls/library/entropy_poll.c b/thirdparty/mbedtls/library/entropy_poll.c index 4c5184686e..727f848b93 100644 --- a/thirdparty/mbedtls/library/entropy_poll.c +++ b/thirdparty/mbedtls/library/entropy_poll.c @@ -5,7 +5,7 @@ * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ -#if defined(__linux__) && !defined(_GNU_SOURCE) +#if defined(__linux__) || defined(__midipix__) && !defined(_GNU_SOURCE) /* Ensure that syscall() is available even when compiling with -std=c99 */ #define _GNU_SOURCE #endif diff --git a/thirdparty/mbedtls/library/gcm.c b/thirdparty/mbedtls/library/gcm.c index 86d5fa2b5f..d3e773278f 100644 --- a/thirdparty/mbedtls/library/gcm.c +++ b/thirdparty/mbedtls/library/gcm.c @@ -241,7 +241,7 @@ int mbedtls_gcm_starts(mbedtls_gcm_context *ctx, uint64_t iv_bits; GCM_VALIDATE_RET(ctx != NULL); - GCM_VALIDATE_RET(iv != NULL); + GCM_VALIDATE_RET(iv_len == 0 || iv != NULL); GCM_VALIDATE_RET(add_len == 0 || add != NULL); /* IV and AD are limited to 2^64 bits, so 2^61 bytes */ @@ -433,7 +433,7 @@ int mbedtls_gcm_crypt_and_tag(mbedtls_gcm_context *ctx, int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; GCM_VALIDATE_RET(ctx != NULL); - GCM_VALIDATE_RET(iv != NULL); + GCM_VALIDATE_RET(iv_len == 0 || iv != NULL); GCM_VALIDATE_RET(add_len == 0 || add != NULL); GCM_VALIDATE_RET(length == 0 || input != NULL); GCM_VALIDATE_RET(length == 0 || output != NULL); @@ -470,7 +470,7 @@ int mbedtls_gcm_auth_decrypt(mbedtls_gcm_context *ctx, int diff; GCM_VALIDATE_RET(ctx != NULL); - GCM_VALIDATE_RET(iv != NULL); + GCM_VALIDATE_RET(iv_len == 0 || iv != NULL); GCM_VALIDATE_RET(add_len == 0 || add != NULL); GCM_VALIDATE_RET(tag != NULL); GCM_VALIDATE_RET(length == 0 || input != NULL); diff --git a/thirdparty/mbedtls/library/net_sockets.c b/thirdparty/mbedtls/library/net_sockets.c index 8140eeade4..5d985ef001 100644 --- a/thirdparty/mbedtls/library/net_sockets.c +++ b/thirdparty/mbedtls/library/net_sockets.c @@ -321,7 +321,7 @@ static int net_would_block(const mbedtls_net_context *ctx) */ int mbedtls_net_accept(mbedtls_net_context *bind_ctx, mbedtls_net_context *client_ctx, - void *client_ip, size_t buf_size, size_t *ip_len) + void *client_ip, size_t buf_size, size_t *cip_len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; int type; @@ -404,22 +404,22 @@ int mbedtls_net_accept(mbedtls_net_context *bind_ctx, if (client_ip != NULL) { if (client_addr.ss_family == AF_INET) { struct sockaddr_in *addr4 = (struct sockaddr_in *) &client_addr; - *ip_len = sizeof(addr4->sin_addr.s_addr); + *cip_len = sizeof(addr4->sin_addr.s_addr); - if (buf_size < *ip_len) { + if (buf_size < *cip_len) { return MBEDTLS_ERR_NET_BUFFER_TOO_SMALL; } - memcpy(client_ip, &addr4->sin_addr.s_addr, *ip_len); + memcpy(client_ip, &addr4->sin_addr.s_addr, *cip_len); } else { struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *) &client_addr; - *ip_len = sizeof(addr6->sin6_addr.s6_addr); + *cip_len = sizeof(addr6->sin6_addr.s6_addr); - if (buf_size < *ip_len) { + if (buf_size < *cip_len) { return MBEDTLS_ERR_NET_BUFFER_TOO_SMALL; } - memcpy(client_ip, &addr6->sin6_addr.s6_addr, *ip_len); + memcpy(client_ip, &addr6->sin6_addr.s6_addr, *cip_len); } } diff --git a/thirdparty/mbedtls/library/pk_wrap.c b/thirdparty/mbedtls/library/pk_wrap.c index 14c6d3f99c..dd460a6a0c 100644 --- a/thirdparty/mbedtls/library/pk_wrap.c +++ b/thirdparty/mbedtls/library/pk_wrap.c @@ -53,7 +53,23 @@ static int rsa_can_do(mbedtls_pk_type_t type) static size_t rsa_get_bitlen(const void *ctx) { const mbedtls_rsa_context *rsa = (const mbedtls_rsa_context *) ctx; - return 8 * mbedtls_rsa_get_len(rsa); + /* Unfortunately, the rsa.h interface does not have a direct way + * to access the bit-length that works with MBEDTLS_RSA_ALT. + * So we have to do a little work here. + */ + mbedtls_mpi N; + mbedtls_mpi_init(&N); + int ret = mbedtls_rsa_export(rsa, &N, NULL, NULL, NULL, NULL); + /* If the export fails for some reason (e.g. the RSA_ALT implementation + * does not support export, or there is not enough memory), + * we have no way of returning an error from this function. + * As a fallback, return the byte-length converted in bits, which is + * the correct value if the modulus size is a multiple of 8 bits, which + * is very often the case in practice. */ + size_t bitlen = (ret == 0 ? mbedtls_mpi_bitlen(&N) : + 8 * mbedtls_rsa_get_len(rsa)); + mbedtls_mpi_free(&N); + return bitlen; } static int rsa_verify_wrap(void *ctx, mbedtls_md_type_t md_alg, diff --git a/thirdparty/mbedtls/library/pkcs12.c b/thirdparty/mbedtls/library/pkcs12.c index 712488233f..55de216edb 100644 --- a/thirdparty/mbedtls/library/pkcs12.c +++ b/thirdparty/mbedtls/library/pkcs12.c @@ -244,21 +244,22 @@ int mbedtls_pkcs12_pbe_ext(mbedtls_asn1_buf *pbe_params, int mode, } #if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) - /* PKCS12 uses CBC with PKCS7 padding */ - - mbedtls_cipher_padding_t padding = MBEDTLS_PADDING_PKCS7; + { + /* PKCS12 uses CBC with PKCS7 padding */ + mbedtls_cipher_padding_t padding = MBEDTLS_PADDING_PKCS7; #if !defined(MBEDTLS_CIPHER_PADDING_PKCS7) - /* For historical reasons, when decrypting, this function works when - * decrypting even when support for PKCS7 padding is disabled. In this - * case, it ignores the padding, and so will never report a - * password mismatch. - */ - if (mode == MBEDTLS_PKCS12_PBE_DECRYPT) { - padding = MBEDTLS_PADDING_NONE; - } + /* For historical reasons, when decrypting, this function works when + * decrypting even when support for PKCS7 padding is disabled. In this + * case, it ignores the padding, and so will never report a + * password mismatch. + */ + if (mode == MBEDTLS_PKCS12_PBE_DECRYPT) { + padding = MBEDTLS_PADDING_NONE; + } #endif - if ((ret = mbedtls_cipher_set_padding_mode(&cipher_ctx, padding)) != 0) { - goto exit; + if ((ret = mbedtls_cipher_set_padding_mode(&cipher_ctx, padding)) != 0) { + goto exit; + } } #endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */ diff --git a/thirdparty/mbedtls/library/pkcs5.c b/thirdparty/mbedtls/library/pkcs5.c index 8e5b751a38..90703c45f9 100644 --- a/thirdparty/mbedtls/library/pkcs5.c +++ b/thirdparty/mbedtls/library/pkcs5.c @@ -239,23 +239,25 @@ int mbedtls_pkcs5_pbes2_ext(const mbedtls_asn1_buf *pbe_params, int mode, } #if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) - /* PKCS5 uses CBC with PKCS7 padding (which is the same as - * "PKCS5 padding" except that it's typically only called PKCS5 - * with 64-bit-block ciphers). - */ - mbedtls_cipher_padding_t padding = MBEDTLS_PADDING_PKCS7; + { + /* PKCS5 uses CBC with PKCS7 padding (which is the same as + * "PKCS5 padding" except that it's typically only called PKCS5 + * with 64-bit-block ciphers). + */ + mbedtls_cipher_padding_t padding = MBEDTLS_PADDING_PKCS7; #if !defined(MBEDTLS_CIPHER_PADDING_PKCS7) - /* For historical reasons, when decrypting, this function works when - * decrypting even when support for PKCS7 padding is disabled. In this - * case, it ignores the padding, and so will never report a - * password mismatch. - */ - if (mode == MBEDTLS_DECRYPT) { - padding = MBEDTLS_PADDING_NONE; - } + /* For historical reasons, when decrypting, this function works when + * decrypting even when support for PKCS7 padding is disabled. In this + * case, it ignores the padding, and so will never report a + * password mismatch. + */ + if (mode == MBEDTLS_DECRYPT) { + padding = MBEDTLS_PADDING_NONE; + } #endif - if ((ret = mbedtls_cipher_set_padding_mode(&cipher_ctx, padding)) != 0) { - goto exit; + if ((ret = mbedtls_cipher_set_padding_mode(&cipher_ctx, padding)) != 0) { + goto exit; + } } #endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */ if ((ret = mbedtls_cipher_crypt(&cipher_ctx, iv, enc_scheme_params.len, diff --git a/thirdparty/mbedtls/library/pkwrite.c b/thirdparty/mbedtls/library/pkwrite.c index fafcf0e1a7..534290df4e 100644 --- a/thirdparty/mbedtls/library/pkwrite.c +++ b/thirdparty/mbedtls/library/pkwrite.c @@ -559,38 +559,49 @@ end_of_export: int mbedtls_pk_write_pubkey_pem(mbedtls_pk_context *key, unsigned char *buf, size_t size) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - unsigned char output_buf[PUB_DER_MAX_BYTES]; + unsigned char *output_buf = NULL; + output_buf = mbedtls_calloc(1, PUB_DER_MAX_BYTES); + if (output_buf == NULL) { + return MBEDTLS_ERR_PK_ALLOC_FAILED; + } size_t olen = 0; PK_VALIDATE_RET(key != NULL); PK_VALIDATE_RET(buf != NULL || size == 0); if ((ret = mbedtls_pk_write_pubkey_der(key, output_buf, - sizeof(output_buf))) < 0) { - return ret; + PUB_DER_MAX_BYTES)) < 0) { + goto cleanup; } if ((ret = mbedtls_pem_write_buffer(PEM_BEGIN_PUBLIC_KEY, PEM_END_PUBLIC_KEY, - output_buf + sizeof(output_buf) - ret, + output_buf + PUB_DER_MAX_BYTES - ret, ret, buf, size, &olen)) != 0) { - return ret; + goto cleanup; } - return 0; + ret = 0; +cleanup: + mbedtls_free(output_buf); + return ret; } int mbedtls_pk_write_key_pem(mbedtls_pk_context *key, unsigned char *buf, size_t size) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - unsigned char output_buf[PRV_DER_MAX_BYTES]; + unsigned char *output_buf = NULL; + output_buf = mbedtls_calloc(1, PRV_DER_MAX_BYTES); + if (output_buf == NULL) { + return MBEDTLS_ERR_PK_ALLOC_FAILED; + } const char *begin, *end; size_t olen = 0; PK_VALIDATE_RET(key != NULL); PK_VALIDATE_RET(buf != NULL || size == 0); - if ((ret = mbedtls_pk_write_key_der(key, output_buf, sizeof(output_buf))) < 0) { - return ret; + if ((ret = mbedtls_pk_write_key_der(key, output_buf, PRV_DER_MAX_BYTES)) < 0) { + goto cleanup; } #if defined(MBEDTLS_RSA_C) @@ -605,15 +616,22 @@ int mbedtls_pk_write_key_pem(mbedtls_pk_context *key, unsigned char *buf, size_t end = PEM_END_PRIVATE_KEY_EC; } else #endif - return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; + { + ret = MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; + goto cleanup; + } if ((ret = mbedtls_pem_write_buffer(begin, end, - output_buf + sizeof(output_buf) - ret, + output_buf + PRV_DER_MAX_BYTES - ret, ret, buf, size, &olen)) != 0) { - return ret; + goto cleanup; } - return 0; + ret = 0; +cleanup: + mbedtls_platform_zeroize(output_buf, PRV_DER_MAX_BYTES); + mbedtls_free(output_buf); + return ret; } #endif /* MBEDTLS_PEM_WRITE_C */ diff --git a/thirdparty/mbedtls/library/platform_util.c b/thirdparty/mbedtls/library/platform_util.c index a86b07fa3f..df34167a8f 100644 --- a/thirdparty/mbedtls/library/platform_util.c +++ b/thirdparty/mbedtls/library/platform_util.c @@ -66,10 +66,10 @@ void mbedtls_platform_zeroize(void *buf, size_t len) #include <time.h> #if !defined(_WIN32) && (defined(unix) || \ defined(__unix) || defined(__unix__) || (defined(__APPLE__) && \ - defined(__MACH__))) + defined(__MACH__)) || defined(__midipix__)) #include <unistd.h> #endif /* !_WIN32 && (unix || __unix || __unix__ || - * (__APPLE__ && __MACH__)) */ + * (__APPLE__ && __MACH__)) || __midipix__ */ #if !((defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L) || \ (defined(_POSIX_THREAD_SAFE_FUNCTIONS) && \ diff --git a/thirdparty/mbedtls/library/ssl_tls.c b/thirdparty/mbedtls/library/ssl_tls.c index 1a2bc7bc9e..c667a2923b 100644 --- a/thirdparty/mbedtls/library/ssl_tls.c +++ b/thirdparty/mbedtls/library/ssl_tls.c @@ -992,8 +992,7 @@ static int ssl_populate_transform(mbedtls_ssl_transform *transform, !defined(MBEDTLS_SSL_EXPORT_KEYS) && \ !defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) && \ !defined(MBEDTLS_DEBUG_C) - ssl = NULL; /* make sure we don't use it except for those cases */ - (void) ssl; + (void) ssl; /* ssl is unused except for those cases */ #endif /* @@ -5205,6 +5204,12 @@ const mbedtls_ssl_session *mbedtls_ssl_get_session_pointer(const mbedtls_ssl_con #define SSL_SERIALIZED_SESSION_CONFIG_CRT 0 #endif /* MBEDTLS_X509_CRT_PARSE_C */ +#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) +#define SSL_SERIALIZED_SESSION_CONFIG_KEEP_PEER_CRT 1 +#else +#define SSL_SERIALIZED_SESSION_CONFIG_KEEP_PEER_CRT 0 +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + #if defined(MBEDTLS_SSL_CLI_C) && defined(MBEDTLS_SSL_SESSION_TICKETS) #define SSL_SERIALIZED_SESSION_CONFIG_CLIENT_TICKET 1 #else @@ -5242,6 +5247,7 @@ const mbedtls_ssl_session *mbedtls_ssl_get_session_pointer(const mbedtls_ssl_con #define SSL_SERIALIZED_SESSION_CONFIG_TRUNC_HMAC_BIT 4 #define SSL_SERIALIZED_SESSION_CONFIG_ETM_BIT 5 #define SSL_SERIALIZED_SESSION_CONFIG_TICKET_BIT 6 +#define SSL_SERIALIZED_SESSION_CONFIG_KEEP_PEER_CRT_BIT 7 #define SSL_SERIALIZED_SESSION_CONFIG_BITFLAG \ ((uint16_t) ( \ @@ -5253,9 +5259,11 @@ const mbedtls_ssl_session *mbedtls_ssl_get_session_pointer(const mbedtls_ssl_con (SSL_SERIALIZED_SESSION_CONFIG_TRUNC_HMAC << \ SSL_SERIALIZED_SESSION_CONFIG_TRUNC_HMAC_BIT) | \ (SSL_SERIALIZED_SESSION_CONFIG_ETM << SSL_SERIALIZED_SESSION_CONFIG_ETM_BIT) | \ - (SSL_SERIALIZED_SESSION_CONFIG_TICKET << SSL_SERIALIZED_SESSION_CONFIG_TICKET_BIT))) + (SSL_SERIALIZED_SESSION_CONFIG_TICKET << SSL_SERIALIZED_SESSION_CONFIG_TICKET_BIT) | \ + (SSL_SERIALIZED_SESSION_CONFIG_KEEP_PEER_CRT << \ + SSL_SERIALIZED_SESSION_CONFIG_KEEP_PEER_CRT_BIT))) -static unsigned char ssl_serialized_session_header[] = { +static const unsigned char ssl_serialized_session_header[] = { MBEDTLS_VERSION_MAJOR, MBEDTLS_VERSION_MINOR, MBEDTLS_VERSION_PATCH, @@ -5279,19 +5287,36 @@ static unsigned char ssl_serialized_session_header[] = { * // the setting of those compile-time * // configuration options which influence * // the structure of mbedtls_ssl_session. - * uint64 start_time; - * uint8 ciphersuite[2]; // defined by the standard - * uint8 compression; // 0 or 1 - * uint8 session_id_len; // at most 32 - * opaque session_id[32]; - * opaque master[48]; // fixed length in the standard - * uint32 verify_result; - * opaque peer_cert<0..2^24-1>; // length 0 means no peer cert - * opaque ticket<0..2^24-1>; // length 0 means no ticket - * uint32 ticket_lifetime; - * uint8 mfl_code; // up to 255 according to standard - * uint8 trunc_hmac; // 0 or 1 - * uint8 encrypt_then_mac; // 0 or 1 + * #if defined(MBEDTLS_HAVE_TIME) + * uint64 start_time; + * #endif + * uint8 ciphersuite[2]; // defined by the standard + * uint8 compression; // 0 or 1 + * uint8 session_id_len; // at most 32 + * opaque session_id[32]; + * opaque master[48]; // fixed length in the standard + * uint32 verify_result; + * #if defined(MBEDTLS_X509_CRT_PARSE_C) + * #if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + * opaque peer_cert<0..2^24-1>; // length 0 means no peer cert + * #else + * uint8 peer_cert_digest_type; + * opaque peer_cert_digest<0..2^8-1> + * #endif + * #endif + * #if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) + * opaque ticket<0..2^24-1>; // length 0 means no ticket + * uint32 ticket_lifetime; + * #endif + * #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + * uint8 mfl_code; // up to 255 according to standard + * #endif + * #if defined(MBEDTLS_SSL_TRUNCATED_HMAC) + * uint8 trunc_hmac; // 0 or 1 + * #endif + * #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + * uint8 encrypt_then_mac; // 0 or 1 + * #endif * * The order is the same as in the definition of the structure, except * verify_result is put before peer_cert so that all mandatory fields come @@ -6124,7 +6149,7 @@ void mbedtls_ssl_session_free(mbedtls_ssl_session *session) (SSL_SERIALIZED_CONTEXT_CONFIG_ALPN << SSL_SERIALIZED_CONTEXT_CONFIG_ALPN_BIT) | \ 0u)) -static unsigned char ssl_serialized_context_header[] = { +static const unsigned char ssl_serialized_context_header[] = { MBEDTLS_VERSION_MAJOR, MBEDTLS_VERSION_MINOR, MBEDTLS_VERSION_PATCH, @@ -6655,7 +6680,7 @@ static int ssl_context_load(mbedtls_ssl_context *ssl, /* alpn_chosen should point to an item in the configured list */ for (cur = ssl->conf->alpn_list; *cur != NULL; cur++) { if (strlen(*cur) == alpn_len && - memcmp(p, cur, alpn_len) == 0) { + memcmp(p, *cur, alpn_len) == 0) { ssl->alpn_chosen = *cur; break; } @@ -6822,7 +6847,7 @@ void mbedtls_ssl_config_init(mbedtls_ssl_config *conf) } #if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) -static int ssl_preset_default_hashes[] = { +static const int ssl_preset_default_hashes[] = { #if defined(MBEDTLS_SHA512_C) MBEDTLS_MD_SHA512, #endif @@ -6840,14 +6865,14 @@ static int ssl_preset_default_hashes[] = { }; #endif -static int ssl_preset_suiteb_ciphersuites[] = { +static const int ssl_preset_suiteb_ciphersuites[] = { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, 0 }; #if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) -static int ssl_preset_suiteb_hashes[] = { +static const int ssl_preset_suiteb_hashes[] = { MBEDTLS_MD_SHA256, MBEDTLS_MD_SHA384, MBEDTLS_MD_NONE @@ -6855,7 +6880,7 @@ static int ssl_preset_suiteb_hashes[] = { #endif #if defined(MBEDTLS_ECP_C) -static mbedtls_ecp_group_id ssl_preset_suiteb_curves[] = { +static const mbedtls_ecp_group_id ssl_preset_suiteb_curves[] = { #if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) MBEDTLS_ECP_DP_SECP256R1, #endif diff --git a/thirdparty/mbedtls/library/timing.c b/thirdparty/mbedtls/library/timing.c index 7ef9f473b5..ec2cff1084 100644 --- a/thirdparty/mbedtls/library/timing.c +++ b/thirdparty/mbedtls/library/timing.c @@ -403,6 +403,7 @@ int mbedtls_timing_self_test(int verbose) uint32_t a = 0, b = 0; mbedtls_timing_delay_context ctx; + memset(&ctx, 0, sizeof(ctx)); if (verbose != 0) { mbedtls_printf(" TIMING tests note: will take some time!\n"); } diff --git a/thirdparty/mbedtls/library/version_features.c b/thirdparty/mbedtls/library/version_features.c index 779325744b..6f663b12a7 100644 --- a/thirdparty/mbedtls/library/version_features.c +++ b/thirdparty/mbedtls/library/version_features.c @@ -456,6 +456,9 @@ static const char * const features[] = { #if defined(MBEDTLS_PSA_INJECT_ENTROPY) "MBEDTLS_PSA_INJECT_ENTROPY", #endif /* MBEDTLS_PSA_INJECT_ENTROPY */ +#if defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) + "MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS", +#endif /* MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS */ #if defined(MBEDTLS_RSA_NO_CRT) "MBEDTLS_RSA_NO_CRT", #endif /* MBEDTLS_RSA_NO_CRT */ diff --git a/thirdparty/miniupnpc/src/miniupnpcstrings.h b/thirdparty/miniupnpc/src/miniupnpcstrings.h index bd4dd317c1..f5730111af 100644 --- a/thirdparty/miniupnpc/src/miniupnpcstrings.h +++ b/thirdparty/miniupnpc/src/miniupnpcstrings.h @@ -2,7 +2,7 @@ #define MINIUPNPCSTRINGS_H_INCLUDED #define OS_STRING "Godot Engine/1.0" -#define MINIUPNPC_VERSION_STRING "2.2.6" +#define MINIUPNPC_VERSION_STRING "2.2.7" #if 0 /* according to "UPnP Device Architecture 1.0" */ diff --git a/thirdparty/squish/LICENSE.txt b/thirdparty/squish/LICENSE.txt new file mode 100644 index 0000000000..e491e36226 --- /dev/null +++ b/thirdparty/squish/LICENSE.txt @@ -0,0 +1,20 @@ +Copyright (c) 2006 Simon Brown si@sjbrown.co.uk + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/thirdparty/squish/godot-changes.patch b/thirdparty/squish/godot-changes.patch deleted file mode 100644 index 555fbc51d0..0000000000 --- a/thirdparty/squish/godot-changes.patch +++ /dev/null @@ -1,211 +0,0 @@ -diff --git a/thirdparty/squish/colourblock.cpp b/thirdparty/squish/colourblock.cpp -index af8b98036..3d87adaa7 100644 ---- a/thirdparty/squish/colourblock.cpp -+++ b/thirdparty/squish/colourblock.cpp -@@ -24,6 +24,9 @@ - -------------------------------------------------------------------------- */ - - #include "colourblock.h" -+// -- Godot start -- -+#include "alpha.h" -+// -- Godot end -- - - namespace squish { - -@@ -211,4 +214,23 @@ void DecompressColour( u8* rgba, void const* block, bool isDxt1 ) - } - } - -+// -- Godot start -- -+void DecompressColourBc5( u8* rgba, void const* block) -+{ -+ void const* rblock = block; -+ void const* gblock = reinterpret_cast< u8 const* >( block ) + 8; -+ DecompressAlphaDxt5(rgba,rblock); -+ for ( int i = 0; i < 16; ++i ) { -+ rgba[i*4] = rgba[i*4 + 3]; -+ } -+ DecompressAlphaDxt5(rgba,gblock); -+ for ( int i = 0; i < 16; ++i ) { -+ rgba[i*4+1] = rgba[i*4 + 3]; -+ rgba[i*4 + 2] = 0; -+ rgba[i*4 + 3] = 255; -+ } -+} -+// -- GODOT end -- -+ -+ - } // namespace squish -diff --git a/thirdparty/squish/colourblock.h b/thirdparty/squish/colourblock.h -index fee2cd7c5..3cb9b7e3b 100644 ---- a/thirdparty/squish/colourblock.h -+++ b/thirdparty/squish/colourblock.h -@@ -35,6 +35,9 @@ void WriteColourBlock3( Vec3::Arg start, Vec3::Arg end, u8 const* indices, void* - void WriteColourBlock4( Vec3::Arg start, Vec3::Arg end, u8 const* indices, void* block ); - - void DecompressColour( u8* rgba, void const* block, bool isDxt1 ); -+// -- GODOT start -- -+void DecompressColourBc5( u8* rgba, void const* block ); -+// -- GODOT end -- - - } // namespace squish - -diff --git a/thirdparty/squish/config.h b/thirdparty/squish/config.h -index 92edefe96..05f8d7259 100644 ---- a/thirdparty/squish/config.h -+++ b/thirdparty/squish/config.h -@@ -32,6 +32,26 @@ - #endif - - // Set to 1 or 2 when building squish to use SSE or SSE2 instructions. -+// -- GODOT start -- -+#ifdef _MSC_VER -+ #if defined(_M_IX86_FP) -+ #if _M_IX86_FP >= 2 -+ #define SQUISH_USE_SSE 2 -+ #elif _M_IX86_FP >= 1 -+ #define SQUISH_USE_SSE 1 -+ #endif -+ #elif defined(_M_X64) -+ #define SQUISH_USE_SSE 2 -+ #endif -+#else -+ #if defined(__SSE2__) -+ #define SQUISH_USE_SSE 2 -+ #elif defined(__SSE__) -+ #define SQUISH_USE_SSE 1 -+ #endif -+#endif -+// -- GODOT end -- -+ - #ifndef SQUISH_USE_SSE - #define SQUISH_USE_SSE 0 - #endif -diff --git a/thirdparty/squish/squish.cpp b/thirdparty/squish/squish.cpp -index 1d22a64ad..fd11a147d 100644 ---- a/thirdparty/squish/squish.cpp -+++ b/thirdparty/squish/squish.cpp -@@ -135,7 +135,13 @@ void Decompress( u8* rgba, void const* block, int flags ) - colourBlock = reinterpret_cast< u8 const* >( block ) + 8; - - // decompress colour -- DecompressColour( rgba, colourBlock, ( flags & kDxt1 ) != 0 ); -+ // -- GODOT start -- -+ //DecompressColour( rgba, colourBlock, ( flags & kDxt1 ) != 0 ); -+ if(( flags & ( kBc5 ) ) != 0) -+ DecompressColourBc5( rgba, colourBlock); -+ else -+ DecompressColour( rgba, colourBlock, ( flags & kDxt1 ) != 0 ); -+ // -- GODOT end -- - - // decompress alpha separately if necessary - if( ( flags & kDxt3 ) != 0 ) - -diff --git a/thirdparty/squish/colourblock.cpp b/thirdparty/squish/colourblock.cpp -index 49401358bc..f14c9362bd 100644 ---- a/thirdparty/squish/colourblock.cpp -+++ b/thirdparty/squish/colourblock.cpp -@@ -24,9 +24,9 @@ - -------------------------------------------------------------------------- */ - - #include "colourblock.h" --// -- Godot start -- -+// -- GODOT start -- - #include "alpha.h" --// -- Godot end -- -+// -- GODOT end -- - - namespace squish { - -diff --git a/thirdparty/squish/godot-changes.patch b/thirdparty/squish/godot-changes.patch -index ef7bafb4b4..655a8cffc2 100644 ---- a/thirdparty/squish/godot-changes.patch -+++ b/thirdparty/squish/godot-changes.patch -@@ -1,22 +1,33 @@ - diff --git a/thirdparty/squish/colourblock.cpp b/thirdparty/squish/colourblock.cpp --index af8b98036..3d87adaa7 100644 -+index af8b980365..f14c9362bd 100644 - --- a/thirdparty/squish/colourblock.cpp - +++ b/thirdparty/squish/colourblock.cpp - @@ -24,6 +24,9 @@ - -------------------------------------------------------------------------- */ - - #include "colourblock.h" --+// -- Godot start -- -++// -- GODOT start -- - +#include "alpha.h" --+// -- Godot end -- -++// -- GODOT end -- - - namespace squish { - --@@ -211,4 +214,23 @@ void DecompressColour( u8* rgba, void const* block, bool isDxt1 ) -+@@ -211,4 +214,34 @@ void DecompressColour( u8* rgba, void const* block, bool isDxt1 ) - } - } - --+// -- Godot start -- -++// -- GODOT start -- -++void DecompressColourBc4( u8* rgba, void const* block) -++{ -++ DecompressAlphaDxt5(rgba,block); -++ for ( int i = 0; i < 16; ++i ) { -++ rgba[i*4] = rgba[i*4 + 3]; -++ rgba[i*4 + 1] = 0; -++ rgba[i*4 + 2] = 0; -++ rgba[i*4 + 3] = 255; -++ } -++} -++ - +void DecompressColourBc5( u8* rgba, void const* block) - +{ - + void const* rblock = block; -@@ -37,21 +48,22 @@ index af8b98036..3d87adaa7 100644 - + - } // namespace squish - diff --git a/thirdparty/squish/colourblock.h b/thirdparty/squish/colourblock.h --index fee2cd7c5..3cb9b7e3b 100644 -+index fee2cd7c5d..e1eb9e4917 100644 - --- a/thirdparty/squish/colourblock.h - +++ b/thirdparty/squish/colourblock.h --@@ -35,6 +35,9 @@ void WriteColourBlock3( Vec3::Arg start, Vec3::Arg end, u8 const* indices, void* -+@@ -35,6 +35,10 @@ void WriteColourBlock3( Vec3::Arg start, Vec3::Arg end, u8 const* indices, void* - void WriteColourBlock4( Vec3::Arg start, Vec3::Arg end, u8 const* indices, void* block ); - - void DecompressColour( u8* rgba, void const* block, bool isDxt1 ); - +// -- GODOT start -- -++void DecompressColourBc4( u8* rgba, void const* block ); - +void DecompressColourBc5( u8* rgba, void const* block ); - +// -- GODOT end -- - - } // namespace squish - - diff --git a/thirdparty/squish/config.h b/thirdparty/squish/config.h --index 92edefe96..05f8d7259 100644 -+index 92edefe966..05f8d72598 100644 - --- a/thirdparty/squish/config.h - +++ b/thirdparty/squish/config.h - @@ -32,6 +32,26 @@ -@@ -82,17 +94,19 @@ index 92edefe96..05f8d7259 100644 - #define SQUISH_USE_SSE 0 - #endif - diff --git a/thirdparty/squish/squish.cpp b/thirdparty/squish/squish.cpp --index 1d22a64ad..fd11a147d 100644 -+index 1d22a64ad6..086ba11cd0 100644 - --- a/thirdparty/squish/squish.cpp - +++ b/thirdparty/squish/squish.cpp --@@ -135,7 +135,13 @@ void Decompress( u8* rgba, void const* block, int flags ) -+@@ -135,7 +135,15 @@ void Decompress( u8* rgba, void const* block, int flags ) - colourBlock = reinterpret_cast< u8 const* >( block ) + 8; - - // decompress colour - - DecompressColour( rgba, colourBlock, ( flags & kDxt1 ) != 0 ); - + // -- GODOT start -- - + //DecompressColour( rgba, colourBlock, ( flags & kDxt1 ) != 0 ); --+ if(( flags & ( kBc5 ) ) != 0) -++ if(( flags & ( kBc4 ) ) != 0) -++ DecompressColourBc4( rgba, colourBlock); -++ else if(( flags & ( kBc5 ) ) != 0) - + DecompressColourBc5( rgba, colourBlock); - + else - + DecompressColour( rgba, colourBlock, ( flags & kDxt1 ) != 0 );
\ No newline at end of file diff --git a/thirdparty/squish/patches/config_sse.patch b/thirdparty/squish/patches/config_sse.patch new file mode 100644 index 0000000000..047701ee32 --- /dev/null +++ b/thirdparty/squish/patches/config_sse.patch @@ -0,0 +1,31 @@ +diff --git a/thirdparty/squish/config.h b/thirdparty/squish/config.h +index 92edefe966..05f8d72598 100644 +--- a/thirdparty/squish/config.h ++++ b/thirdparty/squish/config.h +@@ -32,6 +32,26 @@ + #endif + + // Set to 1 or 2 when building squish to use SSE or SSE2 instructions. ++// -- GODOT start -- ++#ifdef _MSC_VER ++ #if defined(_M_IX86_FP) ++ #if _M_IX86_FP >= 2 ++ #define SQUISH_USE_SSE 2 ++ #elif _M_IX86_FP >= 1 ++ #define SQUISH_USE_SSE 1 ++ #endif ++ #elif defined(_M_X64) ++ #define SQUISH_USE_SSE 2 ++ #endif ++#else ++ #if defined(__SSE2__) ++ #define SQUISH_USE_SSE 2 ++ #elif defined(__SSE__) ++ #define SQUISH_USE_SSE 1 ++ #endif ++#endif ++// -- GODOT end -- ++ + #ifndef SQUISH_USE_SSE + #define SQUISH_USE_SSE 0 + #endif diff --git a/thirdparty/squish/patches/decompress_bc4_bc5.patch b/thirdparty/squish/patches/decompress_bc4_bc5.patch new file mode 100644 index 0000000000..949375560c --- /dev/null +++ b/thirdparty/squish/patches/decompress_bc4_bc5.patch @@ -0,0 +1,85 @@ +diff --git a/thirdparty/squish/colourblock.cpp b/thirdparty/squish/colourblock.cpp +index af8b980365..f14c9362bd 100644 +--- a/thirdparty/squish/colourblock.cpp ++++ b/thirdparty/squish/colourblock.cpp +@@ -24,6 +24,9 @@ + -------------------------------------------------------------------------- */ + + #include "colourblock.h" ++// -- GODOT start -- ++#include "alpha.h" ++// -- GODOT end -- + + namespace squish { + +@@ -211,4 +214,34 @@ void DecompressColour( u8* rgba, void const* block, bool isDxt1 ) + } + } + ++// -- GODOT start -- ++void DecompressColourBc4( u8* rgba, void const* block) ++{ ++ DecompressAlphaDxt5(rgba,block); ++ for ( int i = 0; i < 16; ++i ) { ++ rgba[i*4] = rgba[i*4 + 3]; ++ rgba[i*4 + 1] = 0; ++ rgba[i*4 + 2] = 0; ++ rgba[i*4 + 3] = 255; ++ } ++} ++ ++void DecompressColourBc5( u8* rgba, void const* block) ++{ ++ void const* rblock = block; ++ void const* gblock = reinterpret_cast< u8 const* >( block ) + 8; ++ DecompressAlphaDxt5(rgba,rblock); ++ for ( int i = 0; i < 16; ++i ) { ++ rgba[i*4] = rgba[i*4 + 3]; ++ } ++ DecompressAlphaDxt5(rgba,gblock); ++ for ( int i = 0; i < 16; ++i ) { ++ rgba[i*4+1] = rgba[i*4 + 3]; ++ rgba[i*4 + 2] = 0; ++ rgba[i*4 + 3] = 255; ++ } ++} ++// -- GODOT end -- ++ ++ + } // namespace squish +diff --git a/thirdparty/squish/colourblock.h b/thirdparty/squish/colourblock.h +index fee2cd7c5d..e1eb9e4917 100644 +--- a/thirdparty/squish/colourblock.h ++++ b/thirdparty/squish/colourblock.h +@@ -35,6 +35,10 @@ void WriteColourBlock3( Vec3::Arg start, Vec3::Arg end, u8 const* indices, void* + void WriteColourBlock4( Vec3::Arg start, Vec3::Arg end, u8 const* indices, void* block ); + + void DecompressColour( u8* rgba, void const* block, bool isDxt1 ); ++// -- GODOT start -- ++void DecompressColourBc4( u8* rgba, void const* block ); ++void DecompressColourBc5( u8* rgba, void const* block ); ++// -- GODOT end -- + + } // namespace squish + +diff --git a/thirdparty/squish/squish.cpp b/thirdparty/squish/squish.cpp +index 1d22a64ad6..086ba11cd0 100644 +--- a/thirdparty/squish/squish.cpp ++++ b/thirdparty/squish/squish.cpp +@@ -135,7 +135,15 @@ void Decompress( u8* rgba, void const* block, int flags ) + colourBlock = reinterpret_cast< u8 const* >( block ) + 8; + + // decompress colour +- DecompressColour( rgba, colourBlock, ( flags & kDxt1 ) != 0 ); ++ // -- GODOT start -- ++ //DecompressColour( rgba, colourBlock, ( flags & kDxt1 ) != 0 ); ++ if(( flags & ( kBc4 ) ) != 0) ++ DecompressColourBc4( rgba, colourBlock); ++ else if(( flags & ( kBc5 ) ) != 0) ++ DecompressColourBc5( rgba, colourBlock); ++ else ++ DecompressColour( rgba, colourBlock, ( flags & kDxt1 ) != 0 ); ++ // -- GODOT end -- + + // decompress alpha separately if necessary + if( ( flags & kDxt3 ) != 0 ) diff --git a/thirdparty/thorvg/inc/config.h b/thirdparty/thorvg/inc/config.h index 67716b66cc..31baceca67 100644 --- a/thirdparty/thorvg/inc/config.h +++ b/thirdparty/thorvg/inc/config.h @@ -10,5 +10,5 @@ // For internal debugging: //#define THORVG_LOG_ENABLED -#define THORVG_VERSION_STRING "0.12.9" +#define THORVG_VERSION_STRING "0.12.10" #endif diff --git a/thirdparty/thorvg/src/common/tvgMath.cpp b/thirdparty/thorvg/src/common/tvgMath.cpp index 42bc2cf4aa..37a8879cb5 100644 --- a/thirdparty/thorvg/src/common/tvgMath.cpp +++ b/thirdparty/thorvg/src/common/tvgMath.cpp @@ -71,7 +71,7 @@ void mathRotate(Matrix* m, float degree) { if (degree == 0.0f) return; - auto radian = degree / 180.0f * M_PI; + auto radian = degree / 180.0f * MATH_PI; auto cosVal = cosf(radian); auto sinVal = sinf(radian); diff --git a/thirdparty/thorvg/src/common/tvgMath.h b/thirdparty/thorvg/src/common/tvgMath.h index 7f6708262b..32f4e6b7d1 100644 --- a/thirdparty/thorvg/src/common/tvgMath.h +++ b/thirdparty/thorvg/src/common/tvgMath.h @@ -70,7 +70,7 @@ static inline bool mathEqual(const Matrix& a, const Matrix& b) static inline bool mathRightAngle(const Matrix* m) { auto radian = fabsf(atan2f(m->e21, m->e11)); - if (radian < FLT_EPSILON || mathEqual(radian, float(M_PI_2)) || mathEqual(radian, float(M_PI))) return true; + if (radian < FLT_EPSILON || mathEqual(radian, MATH_PI2) || mathEqual(radian, MATH_PI)) return true; return false; } diff --git a/thirdparty/thorvg/src/loaders/svg/tvgSvgLoader.cpp b/thirdparty/thorvg/src/loaders/svg/tvgSvgLoader.cpp index 7a4f544539..f2fbc07b4a 100644 --- a/thirdparty/thorvg/src/loaders/svg/tvgSvgLoader.cpp +++ b/thirdparty/thorvg/src/loaders/svg/tvgSvgLoader.cpp @@ -743,10 +743,10 @@ static Matrix* _parseTransformationMatrix(const char* value) } else goto error; } else if (state == MatrixState::Rotate) { //Transform to signed. - points[0] = fmod(points[0], 360); - if (points[0] < 0) points[0] += 360; - auto c = cosf(points[0] * (M_PI / 180.0)); - auto s = sinf(points[0] * (M_PI / 180.0)); + points[0] = fmodf(points[0], 360.0f); + if (points[0] < 0) points[0] += 360.0f; + auto c = cosf(points[0] * (MATH_PI / 180.0f)); + auto s = sinf(points[0] * (MATH_PI / 180.0f)); if (ptCount == 1) { Matrix tmp = { c, -s, 0, s, c, 0, 0, 0, 1 }; *matrix = mathMultiply(matrix, &tmp); @@ -769,12 +769,12 @@ static Matrix* _parseTransformationMatrix(const char* value) *matrix = mathMultiply(matrix, &tmp); } else if (state == MatrixState::SkewX) { if (ptCount != 1) goto error; - auto deg = tanf(points[0] * (M_PI / 180.0)); + auto deg = tanf(points[0] * (MATH_PI / 180.0f)); Matrix tmp = { 1, deg, 0, 0, 1, 0, 0, 0, 1 }; *matrix = mathMultiply(matrix, &tmp); } else if (state == MatrixState::SkewY) { if (ptCount != 1) goto error; - auto deg = tanf(points[0] * (M_PI / 180.0)); + auto deg = tanf(points[0] * (MATH_PI / 180.0f)); Matrix tmp = { 1, 0, 0, deg, 1, 0, 0, 0, 1 }; *matrix = mathMultiply(matrix, &tmp); } @@ -1919,6 +1919,19 @@ static SvgNode* _findNodeById(SvgNode *node, const char* id) } +static SvgNode* _findParentById(SvgNode* node, char* id, SvgNode* doc) +{ + SvgNode *parent = node->parent; + while (parent != nullptr && parent != doc) { + if (parent->id && !strcmp(parent->id, id)) { + return parent; + } + parent = parent->parent; + } + return nullptr; +} + + static constexpr struct { const char* tag; @@ -1959,8 +1972,12 @@ static bool _attrParseUseNode(void* data, const char* key, const char* value) defs = _getDefsNode(node); nodeFrom = _findNodeById(defs, id); if (nodeFrom) { - _cloneNode(nodeFrom, node, 0); - if (nodeFrom->type == SvgNodeType::Symbol) use->symbol = nodeFrom; + if (!_findParentById(node, id, loader->doc)) { + _cloneNode(nodeFrom, node, 0); + if (nodeFrom->type == SvgNodeType::Symbol) use->symbol = nodeFrom; + } else { + TVGLOG("SVG", "%s is ancestor element. This reference is invalid.", id); + } free(id); } else { //some svg export software include <defs> element at the end of the file @@ -2669,7 +2686,7 @@ static void _inheritGradient(SvgLoaderData* loader, SvgStyleGradient* to, SvgSty if (to->transform) memcpy(to->transform, from->transform, sizeof(Matrix)); } - if (to->type == SvgGradientType::Linear && from->type == SvgGradientType::Linear) { + if (to->type == SvgGradientType::Linear) { for (unsigned int i = 0; i < sizeof(linear_tags) / sizeof(linear_tags[0]); i++) { bool coordSet = to->flags & linear_tags[i].flag; if (!(to->flags & linear_tags[i].flag) && (from->flags & linear_tags[i].flag)) { @@ -2686,7 +2703,7 @@ static void _inheritGradient(SvgLoaderData* loader, SvgStyleGradient* to, SvgSty linear_tags[i].tagInheritedRecalc(loader, to->linear, to->userSpace); } } - } else if (to->type == SvgGradientType::Radial && from->type == SvgGradientType::Radial) { + } else if (to->type == SvgGradientType::Radial) { for (unsigned int i = 0; i < sizeof(radialTags) / sizeof(radialTags[0]); i++) { bool coordSet = (to->flags & radialTags[i].flag); if (!(to->flags & radialTags[i].flag) && (from->flags & radialTags[i].flag)) { @@ -2696,10 +2713,16 @@ static void _inheritGradient(SvgLoaderData* loader, SvgStyleGradient* to, SvgSty //GradUnits not set directly, coord set if (!gradUnitSet && coordSet) { radialTags[i].tagRecalc(loader, to->radial, to->userSpace); + //If fx and fy are not set, set cx and cy. + if (!strcmp(radialTags[i].tag, "cx") && !(to->flags & SvgGradientFlags::Fx)) to->radial->fx = to->radial->cx; + if (!strcmp(radialTags[i].tag, "cy") && !(to->flags & SvgGradientFlags::Fy)) to->radial->fy = to->radial->cy; } //GradUnits set, coord not set directly if (to->userSpace == from->userSpace) continue; if (gradUnitSet && !coordSet) { + //If fx and fx are not set, do not call recalc. + if (!strcmp(radialTags[i].tag, "fx") && !(to->flags & SvgGradientFlags::Fx)) continue; + if (!strcmp(radialTags[i].tag, "fy") && !(to->flags & SvgGradientFlags::Fy)) continue; radialTags[i].tagInheritedRecalc(loader, to->radial, to->userSpace); } } @@ -3018,9 +3041,13 @@ static void _clonePostponedNodes(Array<SvgNodeIdPair>* cloneNodes, SvgNode* doc) auto defs = _getDefsNode(nodeIdPair.node); auto nodeFrom = _findNodeById(defs, nodeIdPair.id); if (!nodeFrom) nodeFrom = _findNodeById(doc, nodeIdPair.id); - _cloneNode(nodeFrom, nodeIdPair.node, 0); - if (nodeFrom && nodeFrom->type == SvgNodeType::Symbol && nodeIdPair.node->type == SvgNodeType::Use) { - nodeIdPair.node->node.use.symbol = nodeFrom; + if (!_findParentById(nodeIdPair.node, nodeIdPair.id, doc)) { + _cloneNode(nodeFrom, nodeIdPair.node, 0); + if (nodeFrom && nodeFrom->type == SvgNodeType::Symbol && nodeIdPair.node->type == SvgNodeType::Use) { + nodeIdPair.node->node.use.symbol = nodeFrom; + } + } else { + TVGLOG("SVG", "%s is ancestor element. This reference is invalid.", nodeIdPair.id); } free(nodeIdPair.id); } diff --git a/thirdparty/thorvg/src/loaders/svg/tvgSvgPath.cpp b/thirdparty/thorvg/src/loaders/svg/tvgSvgPath.cpp index f9780749a9..691cde1fc5 100644 --- a/thirdparty/thorvg/src/loaders/svg/tvgSvgPath.cpp +++ b/thirdparty/thorvg/src/loaders/svg/tvgSvgPath.cpp @@ -126,7 +126,7 @@ void _pathAppendArcTo(Array<PathCommand>* cmds, Array<Point>* pts, Point* cur, P rx = fabsf(rx); ry = fabsf(ry); - angle = angle * M_PI / 180.0f; + angle = angle * MATH_PI / 180.0f; cosPhi = cosf(angle); sinPhi = sinf(angle); dx2 = (sx - x) / 2.0f; @@ -195,24 +195,24 @@ void _pathAppendArcTo(Array<PathCommand>* cmds, Array<Point>* pts, Point* cur, P //http://www.euclideanspace.com/maths/algebra/vectors/angleBetween/index.htm //Note: atan2 (0.0, 1.0) == 0.0 at = atan2(((y1p - cyp) / ry), ((x1p - cxp) / rx)); - theta1 = (at < 0.0f) ? 2.0f * M_PI + at : at; + theta1 = (at < 0.0f) ? 2.0f * MATH_PI + at : at; nat = atan2(((-y1p - cyp) / ry), ((-x1p - cxp) / rx)); - deltaTheta = (nat < at) ? 2.0f * M_PI - at + nat : nat - at; + deltaTheta = (nat < at) ? 2.0f * MATH_PI - at + nat : nat - at; if (sweep) { //Ensure delta theta < 0 or else add 360 degrees - if (deltaTheta < 0.0f) deltaTheta += (float)(2.0f * M_PI); + if (deltaTheta < 0.0f) deltaTheta += 2.0f * MATH_PI; } else { //Ensure delta theta > 0 or else substract 360 degrees - if (deltaTheta > 0.0f) deltaTheta -= (float)(2.0f * M_PI); + if (deltaTheta > 0.0f) deltaTheta -= 2.0f * MATH_PI; } //Add several cubic bezier to approximate the arc //(smaller than 90 degrees) //We add one extra segment because we want something //Smaller than 90deg (i.e. not 90 itself) - segments = static_cast<int>(fabsf(deltaTheta / float(M_PI_2)) + 1.0f); + segments = static_cast<int>(fabsf(deltaTheta / MATH_PI2) + 1.0f); delta = deltaTheta / segments; //http://www.stillhq.com/ctpfaq/2001/comp.text.pdf-faq-2001-04.txt (section 2.13) diff --git a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwShape.cpp b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwShape.cpp index 03261a4b7f..5e79bb6ffa 100644 --- a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwShape.cpp +++ b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwShape.cpp @@ -28,6 +28,7 @@ /* Internal Class Implementation */ /************************************************************************/ + struct Line { Point pt1; @@ -55,23 +56,24 @@ static void _lineSplitAt(const Line& cur, float at, Line& left, Line& right) } -static void _outlineEnd(SwOutline& outline) +static bool _outlineEnd(SwOutline& outline) { - if (outline.pts.empty()) return; + //Make a contour if lineTo/curveTo without calling close/moveTo beforehand. + if (outline.pts.empty()) return false; outline.cntrs.push(outline.pts.count - 1); outline.closed.push(false); + return false; } -static void _outlineMoveTo(SwOutline& outline, const Point* to, const Matrix* transform) +static bool _outlineMoveTo(SwOutline& outline, const Point* to, const Matrix* transform, bool closed = false) { - if (outline.pts.count > 0) { - outline.cntrs.push(outline.pts.count - 1); - outline.closed.push(false); - } + //make it a contour, if the last contour is not closed yet. + if (!closed) _outlineEnd(outline); outline.pts.push(mathTransform(to, transform)); outline.types.push(SW_CURVE_TYPE_POINT); + return false; } @@ -95,20 +97,22 @@ static void _outlineCubicTo(SwOutline& outline, const Point* ctrl1, const Point* } -static void _outlineClose(SwOutline& outline) +static bool _outlineClose(SwOutline& outline) { - uint32_t i = 0; - + uint32_t i; if (outline.cntrs.count > 0) i = outline.cntrs.last() + 1; - else i = 0; //First Path + else i = 0; //Make sure there is at least one point in the current path - if (outline.pts.count == i) return; + if (outline.pts.count == i) return false; //Close the path outline.pts.push(outline.pts[i]); + outline.cntrs.push(outline.pts.count - 1); outline.types.push(SW_CURVE_TYPE_POINT); outline.closed.push(true); + + return true; } @@ -306,7 +310,7 @@ static SwOutline* _genDashOutline(const RenderShape* rshape, const Matrix* trans bool isOdd = dash.cnt % 2; if (isOdd) patternLength *= 2; - offset = fmod(offset, patternLength); + offset = fmodf(offset, patternLength); if (offset < 0) offset += patternLength; for (size_t i = 0; i < dash.cnt * (1 + (size_t)isOdd); ++i, ++offIdx) { @@ -425,25 +429,28 @@ static bool _genOutline(SwShape* shape, const RenderShape* rshape, const Matrix* shape->outline = mpoolReqOutline(mpool, tid); auto outline = shape->outline; + bool closed = false; //Generate Outlines while (cmdCnt-- > 0) { switch (*cmds) { case PathCommand::Close: { - _outlineClose(*outline); + if (!closed) closed = _outlineClose(*outline); break; } case PathCommand::MoveTo: { - _outlineMoveTo(*outline, pts, transform); + closed = _outlineMoveTo(*outline, pts, transform, closed); ++pts; break; } case PathCommand::LineTo: { + if (closed) closed = _outlineEnd(*outline); _outlineLineTo(*outline, pts, transform); ++pts; break; } case PathCommand::CubicTo: { + if (closed) closed = _outlineEnd(*outline); _outlineCubicTo(*outline, pts, pts + 1, pts + 2, transform); pts += 3; break; @@ -452,7 +459,7 @@ static bool _genOutline(SwShape* shape, const RenderShape* rshape, const Matrix* ++cmds; } - _outlineEnd(*outline); + if (!closed) _outlineEnd(*outline); outline->fillRule = rshape->rule; shape->outline = outline; diff --git a/thirdparty/thorvg/src/renderer/tvgPaint.cpp b/thirdparty/thorvg/src/renderer/tvgPaint.cpp index 13ec4183d6..227ce10a0d 100644 --- a/thirdparty/thorvg/src/renderer/tvgPaint.cpp +++ b/thirdparty/thorvg/src/renderer/tvgPaint.cpp @@ -41,20 +41,26 @@ } -static bool _compFastTrack(Paint* cmpTarget, const RenderTransform* pTransform, RenderTransform* rTransform, RenderRegion& viewport) + +static Result _compFastTrack(Paint* cmpTarget, const RenderTransform* pTransform, RenderTransform* rTransform, RenderRegion& viewport) { /* Access Shape class by Paint is bad... but it's ok still it's an internal usage. */ auto shape = static_cast<Shape*>(cmpTarget); //Rectangle Candidates? const Point* pts; - if (shape->pathCoords(&pts) != 4) return false; + auto ptsCnt = shape->pathCoords(&pts); + + //nothing to clip + if (ptsCnt == 0) return Result::InvalidArguments; + + if (ptsCnt != 4) return Result::InsufficientCondition; if (rTransform) rTransform->update(); //No rotation and no skewing - if (pTransform && (!mathRightAngle(&pTransform->m) || mathSkewed(&pTransform->m))) return false; - if (rTransform && (!mathRightAngle(&rTransform->m) || mathSkewed(&rTransform->m))) return false; + if (pTransform && (!mathRightAngle(&pTransform->m) || mathSkewed(&pTransform->m))) return Result::InsufficientCondition; + if (rTransform && (!mathRightAngle(&rTransform->m) || mathSkewed(&rTransform->m))) return Result::InsufficientCondition; //Perpendicular Rectangle? auto pt1 = pts + 0; @@ -99,10 +105,9 @@ static bool _compFastTrack(Paint* cmpTarget, const RenderTransform* pTransform, if (viewport.w < 0) viewport.w = 0; if (viewport.h < 0) viewport.h = 0; - return true; + return Result::Success; } - - return false; + return Result::InsufficientCondition; } @@ -235,7 +240,7 @@ RenderData Paint::Impl::update(RenderMethod* renderer, const RenderTransform* pT /* 1. Composition Pre Processing */ RenderData trd = nullptr; //composite target render data RenderRegion viewport; - bool compFastTrack = false; + Result compFastTrack = Result::InsufficientCondition; bool childClipper = false; if (compData) { @@ -260,7 +265,7 @@ RenderData Paint::Impl::update(RenderMethod* renderer, const RenderTransform* pT } if (tryFastTrack) { RenderRegion viewport2; - if ((compFastTrack = _compFastTrack(target, pTransform, target->pImpl->rTransform, viewport2))) { + if ((compFastTrack = _compFastTrack(target, pTransform, target->pImpl->rTransform, viewport2)) == Result::Success) { viewport = renderer->viewport(); viewport2.intersect(viewport); renderer->viewport(viewport2); @@ -268,7 +273,7 @@ RenderData Paint::Impl::update(RenderMethod* renderer, const RenderTransform* pT } } } - if (!compFastTrack) { + if (compFastTrack == Result::InsufficientCondition) { childClipper = compData->method == CompositeMethod::ClipPath ? true : false; trd = target->pImpl->update(renderer, pTransform, clips, 255, pFlag, childClipper); if (childClipper) clips.push(trd); @@ -285,7 +290,7 @@ RenderData Paint::Impl::update(RenderMethod* renderer, const RenderTransform* pT PAINT_METHOD(rd, update(renderer, &outTransform, clips, opacity, newFlag, clipper)); /* 3. Composition Post Processing */ - if (compFastTrack) renderer->viewport(viewport); + if (compFastTrack == Result::Success) renderer->viewport(viewport); else if (childClipper) clips.pop(); return rd; diff --git a/thirdparty/thorvg/src/renderer/tvgShape.cpp b/thirdparty/thorvg/src/renderer/tvgShape.cpp index ab1f378b47..a42060e241 100644 --- a/thirdparty/thorvg/src/renderer/tvgShape.cpp +++ b/thirdparty/thorvg/src/renderer/tvgShape.cpp @@ -164,7 +164,7 @@ Result Shape::appendArc(float cx, float cy, float radius, float startAngle, floa } for (int i = 0; i < nCurves; ++i) { - auto endAngle = startAngle + ((i != nCurves - 1) ? float(M_PI_2) * sweepSign : fract); + auto endAngle = startAngle + ((i != nCurves - 1) ? MATH_PI2 * sweepSign : fract); Point end = {radius * cosf(endAngle), radius * sinf(endAngle)}; //variables needed to calculate bezier control points diff --git a/thirdparty/thorvg/update-thorvg.sh b/thirdparty/thorvg/update-thorvg.sh index 7a754c09b9..afe05e629e 100755 --- a/thirdparty/thorvg/update-thorvg.sh +++ b/thirdparty/thorvg/update-thorvg.sh @@ -1,6 +1,6 @@ #!/bin/bash -e -VERSION=0.12.9 +VERSION=0.12.10 cd thirdparty/thorvg/ || true rm -rf AUTHORS LICENSE inc/ src/ *.zip *.tar.gz tmp/ |