From b977b77fb7ea75895ac65d64d99b056d95435bfc Mon Sep 17 00:00:00 2001 From: William Wilgus Date: Thu, 9 Nov 2017 18:03:33 +0100 Subject: Optimize is_diacritic is_diacritic is used for pretty much all of the text display sizing Timing here matters, so important it uses a priority buffer in order to cut down on searching the database. This patch is verified functionally equlivalent but saves 80 bytes and is ~20% faster for the clip+ I tested it on Several things were done: Optimizing the copy loop for the priority buffer Globbing some operations together but the main one has to do with the database structure its self -- Rather than a bit packed struct it combines the lower 8 bytes into one value [info] and uses flags to access the values instead Change-Id: I475073419b647639ef1eeaa3b9213e4e1067c0db --- firmware/common/diacritic.c | 49 +++++++++++++++++++++++++++------------------ 1 file changed, 29 insertions(+), 20 deletions(-) (limited to 'firmware/common') diff --git a/firmware/common/diacritic.c b/firmware/common/diacritic.c index aa2726c5fb..eca7b07b6e 100644 --- a/firmware/common/diacritic.c +++ b/firmware/common/diacritic.c @@ -10,6 +10,7 @@ * Copyright (C) 2009 Phinitnun Chanasabaeng * Initial work * Copyright (C) 2009 Tomer Shalev + * Copyright (C) 2018 William Wilgus * * Rockbox diacritic positioning * Based on initial work by Phinitnun Chanasabaeng @@ -27,19 +28,23 @@ #include "system.h" #define DIAC_NUM_RANGES (ARRAYLEN(diac_ranges)) +#define DIAC_RTL (1 << 7) +#define DIAC_CNT (0xFF ^ DIAC_RTL) /* Each diac_range_ struct defines a Unicode range that begins with * N diacritic characters, and continues with non-diacritic characters up to the - * base of the next item in the array */ + * base of the next item in the array, [info] packs RTL status and the count of + * diacritic chars after [base]. RTL occupies the MSB and CNT the (7) lower bits + */ + struct diac_range { - unsigned base : 16; - unsigned num_diacritics : 7; - unsigned is_rtl : 1; + uint16_t base; + uint8_t info; /* [RTL:1 CNT:7] */ }; #define DIAC_RANGE_ENTRY(first_diac, first_non_diac, is_rtl) \ - { first_diac, first_non_diac - first_diac, is_rtl } + { first_diac, ((first_non_diac - first_diac) & DIAC_CNT) | (is_rtl * DIAC_RTL)} /* Sorted by Unicode value */ static const struct diac_range diac_ranges[] = @@ -190,22 +195,28 @@ static const struct diac_range diac_ranges[] = #define MRU_MAX_LEN 32 -static unsigned short mru_len = 0; -static unsigned short diacritic_mru[MRU_MAX_LEN]; - bool is_diacritic(const unsigned short char_code, bool *is_rtl) { - unsigned short mru, i; + static uint8_t mru_len = 0; + static uint8_t diacritic_mru[MRU_MAX_LEN]; + + uint8_t i, itmp; + uint8_t info, mru; + const struct diac_range *diac; /* Search in MRU */ - for (mru = 0; mru < mru_len; mru++) + for (mru = 0, i = 0; mru < mru_len; mru++) { + + /* Items shifted >> 1 */ + itmp = i; i = diacritic_mru[mru]; + diacritic_mru[mru] = itmp; /* Found in MRU */ - if (diac_ranges[i].base <= char_code && - char_code < diac_ranges[i + 1].base) + if ((char_code >= (diac = &diac_ranges[i])->base) + && (char_code < (++diac)->base)) { goto Found; } @@ -219,23 +230,21 @@ bool is_diacritic(const unsigned short char_code, bool *is_rtl) break; } - /* Add MRU entry, or overwrite LRU if MRU array is full */ + /* Add MRU entry */ if (mru_len < MRU_MAX_LEN) mru_len++; - else - mru--; Found: + /* Promote MRU item to top of MRU */ - for ( ; mru > 0; mru--) - diacritic_mru[mru] = diacritic_mru[mru - 1]; diacritic_mru[0] = i; diac = &diac_ranges[i]; + info = diac->info; /* Update RTL */ if (is_rtl) - *is_rtl = diac->is_rtl; + *is_rtl = ((DIAC_RTL & info) == DIAC_RTL); - return (char_code < diac->base + diac->num_diacritics); -} + return (char_code < diac->base + (info & DIAC_CNT)); +} \ No newline at end of file -- cgit