diff --git a/clay.h b/clay.h index 6818004..c0962c9 100644 --- a/clay.h +++ b/clay.h @@ -385,10 +385,6 @@ typedef struct { // CLAY_TEXT_ALIGN_CENTER - Horizontally aligns wrapped lines of text to the center of their bounding box. // CLAY_TEXT_ALIGN_RIGHT - Horizontally aligns wrapped lines of text to the right hand side of their bounding box. Clay_TextAlignment textAlignment; - // When set to true, clay will hash the entire text contents of this string as an identifier for its internal - // text measurement cache, rather than just the pointer and length. This will incur significant performance cost for - // long bodies of text. - bool hashStringContents; } Clay_TextElementConfig; CLAY__WRAPPER_STRUCT(Clay_TextElementConfig); @@ -877,8 +873,7 @@ CLAY_DLL_EXPORT int32_t Clay_GetMaxMeasureTextCacheWordCount(void); // Modifies the maximum number of measured "words" (whitespace seperated runs of characters) that Clay can store in its internal text measurement cache. // This may require reallocating additional memory, and re-calling Clay_Initialize(); CLAY_DLL_EXPORT void Clay_SetMaxMeasureTextCacheWordCount(int32_t maxMeasureTextCacheWordCount); -// Resets Clay's internal text measurement cache, useful if memory to represent strings is being re-used. -// Similar behaviour can be achieved on an individual text element level by using Clay_TextElementConfig.hashStringContents +// Resets Clay's internal text measurement cache. Useful if font mappings have changed or fonts have been reloaded. CLAY_DLL_EXPORT void Clay_ResetMeasureTextCache(void); // Internal API functions required by macros ---------------------- @@ -1350,18 +1345,15 @@ Clay_ElementId Clay__HashString(Clay_String key, const uint32_t offset, const ui } #if !defined(CLAY_DISABLE_SIMD) && (defined(__x86_64__) || defined(_M_X64) || defined(_M_AMD64)) -// Rotate left in AVX (equivalent to _mm_rol_epi64 in AVX2) static inline __m128i Clay__SIMDRotateLeft(__m128i x, int r) { return _mm_or_si128(_mm_slli_epi64(x, r), _mm_srli_epi64(x, 64 - r)); } -// A simple ARX mix function (AVX) static inline void Clay__SIMDARXMix(__m128i* a, __m128i* b) { *a = _mm_add_epi64(*a, *b); *b = _mm_xor_si128(Clay__SIMDRotateLeft(*b, 17), *a); } -// SIMD ARX hash function (AVX) uint64_t Clay__HashData(const uint8_t* data, size_t len) { // Pinched these constants from the BLAKE implementation __m128i v0 = _mm_set1_epi64x(0x6a09e667f3bcc908ULL); @@ -1409,19 +1401,16 @@ uint64_t Clay__HashData(const uint8_t* data, size_t len) { return result[0] ^ result[1]; } #elif !defined(CLAY_DISABLE_SIMD) && defined(__aarch64__) -// Rotate left in NEON (simulating _mm256_rol_epi64) static inline uint64x2_t Clay__SIMDRotateLeft(uint64x2_t x, int r) { return vorrq_u64(vshlq_n_u64(x, 17), vshrq_n_u64(x, 64 - 17)); } -// A simple ARX mix function static inline void Clay__SIMDARXMix(uint64x2_t* a, uint64x2_t* b) { *a = vaddq_u64(*a, *b); *b = veorq_u64(Clay__SIMDRotateLeft(*b, 17), *a); } -// SIMD ARX hash function (NEON) -uint64_t Clay__HashData(const uint8_t* data, size_t len) { +uint64_t Clay__HashData(const uint8_t* data, size_t length) { // Pinched these constants from the BLAKE implementation uint64x2_t v0 = vdupq_n_u64(0x6a09e667f3bcc908ULL); uint64x2_t v1 = vdupq_n_u64(0xbb67ae8584caa73bULL); @@ -1431,31 +1420,30 @@ uint64_t Clay__HashData(const uint8_t* data, size_t len) { uint8_t overflowBuffer[8] = { 0 }; // Process 16-byte chunks - while (len > 0) { + while (length > 0) { uint64x2_t msg; - if (len > 16) { + if (length > 16) { msg = vld1q_u64((const uint64_t*)data); data += 16; - len -= 16; + length -= 16; } - else if (len > 8) { + else if (length > 8) { msg = vcombine_u64(vld1_u64((const uint64_t*)data), vdup_n_u64(0)); data += 8; - len -= 8; + length -= 8; } else { - for (int i = 0; i < len; i++) { + for (int i = 0; i < length; i++) { overflowBuffer[i] = data[i]; } - uint8x8_t lower = vld1_u8(overflowBuffer); // Load up to 8 bytes - msg = vcombine_u8(lower, vdup_n_u8(0)); // Zero upper 8 bytes - len = 0; + uint8x8_t lower = vld1_u8(overflowBuffer); + msg = vcombine_u8(lower, vdup_n_u8(0)); + length = 0; } v0 = veorq_u64(v0, msg); Clay__SIMDARXMix(&v0, &v1); Clay__SIMDARXMix(&v2, &v3); - // Cross-lane mixing v0 = vaddq_u64(v0, v2); v1 = vaddq_u64(v1, v3); } @@ -1463,15 +1451,15 @@ uint64_t Clay__HashData(const uint8_t* data, size_t len) { // Final mixing rounds Clay__SIMDARXMix(&v0, &v1); Clay__SIMDARXMix(&v2, &v3); - v0 = vaddq_u64(v0, v2); - v1 = vaddq_u64(v1, v3); + v0 = vaddq_u64(v0, v2); + v1 = vaddq_u64(v1, v3); - // Extract final hash - uint64_t result[2]; - vst1q_u64(result, v0); + // Extract final hash + uint64_t result[2]; + vst1q_u64(result, v0); - return result[0] ^ result[1]; - } + return result[0] ^ result[1]; +} #else uint64_t Clay__HashData(const uint8_t* data, size_t length) { uint64_t hash = 0; @@ -1486,10 +1474,7 @@ uint64_t Clay__HashData(const uint8_t* data, size_t length) { #endif uint32_t Clay__HashStringContentsWithConfig(Clay_String *text, Clay_TextElementConfig *config) { - uint32_t hash = 0; - uintptr_t pointerAsNumber = (uintptr_t)text->chars; - - hash = Clay__HashData((const uint8_t *)text->chars, text->length) % UINT32_MAX; + uint32_t hash = Clay__HashData((const uint8_t *)text->chars, text->length) % UINT32_MAX; hash += config->fontId; hash += (hash << 10);