Permalink
Browse files

Fix issue with caret position in text boxes caused by a bad hash func…

…tion. Fletcher is 2-bytes-at-a-time and thus very inappropriate for short strings.
  • Loading branch information...
hrydgard committed Oct 24, 2017
1 parent 2c8fb0f commit d1d1e1f742ab21ed9c5023724f46d03f4ab683a7
@@ -46,7 +46,7 @@ bool TextDrawerAndroid::IsReady() const {
uint32_t TextDrawerAndroid::SetFont(const char *fontName, int size, int flags) {
// We will only use the default font but just for consistency let's still involve
// the font name.
uint32_t fontHash = hash::Fletcher((const uint8_t *)fontName, strlen(fontName));
uint32_t fontHash = hash::Adler32((const uint8_t *)fontName, strlen(fontName));
fontHash ^= size;
fontHash ^= flags << 10;
@@ -79,7 +79,7 @@ std::string TextDrawerAndroid::NormalizeString(std::string str) {
}
void TextDrawerAndroid::MeasureString(const char *str, size_t len, float *w, float *h) {
uint32_t stringHash = hash::Fletcher((const uint8_t *)str, len);
uint32_t stringHash = hash::Adler32((const uint8_t *)str, len);
uint32_t entryHash = stringHash ^ fontHash_;
TextMeasureEntry *entry;
@@ -129,7 +129,7 @@ void TextDrawerAndroid::MeasureStringRect(const char *str, size_t len, const Bou
float total_w = 0.0f;
float total_h = 0.0f;
for (size_t i = 0; i < lines.size(); i++) {
uint32_t stringHash = hash::Fletcher((const uint8_t *)&lines[i][0], lines[i].length());
uint32_t stringHash = hash::Adler32((const uint8_t *)&lines[i][0], lines[i].length());
uint32_t entryHash = stringHash ^ fontHash_;
TextMeasureEntry *entry;
@@ -168,7 +168,7 @@ void TextDrawerAndroid::DrawString(DrawBuffer &target, const char *str, float x,
int result = javaVM->GetEnv((void **)&env, JNI_VERSION_1_6);
assert(env == env_);
uint32_t stringHash = hash::Fletcher((const uint8_t *)text.data(), text.size());
uint32_t stringHash = hash::Adler32((const uint8_t *)text.data(), text.size());
uint32_t entryHash = stringHash ^ fontHash_ ^ (align << 24);
target.Flush(true);
@@ -24,7 +24,7 @@ TextDrawerQt::~TextDrawerQt() {
uint32_t TextDrawerQt::SetFont(const char *fontName, int size, int flags) {
// We will only use the default font
uint32_t fontHash = 0; //hash::Fletcher((const uint8_t *)fontName, strlen(fontName));
uint32_t fontHash = 0; //hash::Adler32((const uint8_t *)fontName, strlen(fontName));
fontHash ^= size;
fontHash ^= flags << 10;
@@ -72,7 +72,7 @@ void TextDrawerQt::DrawString(DrawBuffer &target, const char *str, float x, floa
if (!strlen(str))
return;
uint32_t stringHash = hash::Fletcher((const uint8_t *)str, strlen(str));
uint32_t stringHash = hash::Adler32((const uint8_t *)str, strlen(str));
uint32_t entryHash = stringHash ^ fontHash_ ^ (align << 24);
target.Flush(true);
@@ -83,7 +83,7 @@ TextDrawerWin32::~TextDrawerWin32() {
}
uint32_t TextDrawerWin32::SetFont(const char *fontName, int size, int flags) {
uint32_t fontHash = fontName ? hash::Fletcher((const uint8_t *)fontName, strlen(fontName)) : 0;
uint32_t fontHash = fontName ? hash::Adler32((const uint8_t *)fontName, strlen(fontName)) : 0;
fontHash ^= size;
fontHash ^= flags << 10;
@@ -119,7 +119,7 @@ void TextDrawerWin32::SetFont(uint32_t fontHandle) {
}
void TextDrawerWin32::MeasureString(const char *str, size_t len, float *w, float *h) {
uint32_t stringHash = hash::Fletcher((const uint8_t *)str, len);
uint32_t stringHash = hash::Adler32((const uint8_t *)str, len);
uint32_t entryHash = stringHash ^ fontHash_;
TextMeasureEntry *entry;
@@ -164,7 +164,7 @@ void TextDrawerWin32::MeasureStringRect(const char *str, size_t len, const Bound
float total_w = 0.0f;
float total_h = 0.0f;
for (size_t i = 0; i < lines.size(); i++) {
uint32_t stringHash = hash::Fletcher((const uint8_t *)&lines[i][0], lines[i].length());
uint32_t stringHash = hash::Adler32((const uint8_t *)&lines[i][0], lines[i].length());
uint32_t entryHash = stringHash ^ fontHash_;
TextMeasureEntry *entry;
@@ -197,7 +197,7 @@ void TextDrawerWin32::DrawString(DrawBuffer &target, const char *str, float x, f
if (!strlen(str))
return;
uint32_t stringHash = hash::Fletcher((const uint8_t *)str, strlen(str));
uint32_t stringHash = hash::Adler32((const uint8_t *)str, strlen(str));
uint32_t entryHash = stringHash ^ fontHash_ ^ (align << 24);
target.Flush(true);
@@ -3,35 +3,7 @@
namespace hash {
// uint32_t
// WARNING - may read one more byte! Fine if the input is a null-terminated string.
// Implementation from Wikipedia.
uint32_t Fletcher(const uint8_t *data_uint8, size_t length) {
const uint16_t *data = (const uint16_t *)data_uint8;
size_t len = (length + 1) / 2;
uint32_t sum1 = 0xffff, sum2 = 0xffff;
while (len) {
size_t tlen = len > 360 ? 360 : len;
len -= tlen;
do {
sum1 += *data++;
sum2 += sum1;
} while (--tlen);
sum1 = (sum1 & 0xffff) + (sum1 >> 16);
sum2 = (sum2 & 0xffff) + (sum2 >> 16);
}
/* Second reduction step to reduce sums to 16 bits */
sum1 = (sum1 & 0xffff) + (sum1 >> 16);
sum2 = (sum2 & 0xffff) + (sum2 >> 16);
return sum2 << 16 | sum1;
}
// Implementation from Wikipedia
// Slightly slower than Fletcher above, but slighly more reliable.
#define MOD_ADLER 65521
// data: Pointer to the data to be summed; len is in bytes
uint32_t Adler32(const uint8_t *data, size_t len) {
@@ -1,14 +1,14 @@
#ifndef _UTIL_HASH_HASH_H
#define _UTIL_HASH_HASH_H
#include <stdlib.h>
#include <cstdlib>
#include "base/basictypes.h"
namespace hash {
uint32_t Fletcher(const uint8_t *data_u8, size_t length); // FAST. Length & 1 == 0.
uint32_t Adler32(const uint8_t *data, size_t len); // Fairly accurate, slightly slower
// Fairly decent function for hashing strings.
uint32_t Adler32(const uint8_t *data, size_t len);
} // namespace hash

0 comments on commit d1d1e1f

Please sign in to comment.