From 3e65090bef37843dc0d85c10cb2864925c2fb718 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Thu, 11 Jul 2019 18:10:25 -0400 Subject: Reimplement PangoCoverage on top of hb_set_t This drops the language dependency and coverage levels, both of which are not used in pango. --- pango/pango-coverage.c | 340 ++++-------------------------------------------- pango/pango-coverage.h | 10 +- pango/pangofc-fontmap.c | 5 +- 3 files changed, 35 insertions(+), 320 deletions(-) diff --git a/pango/pango-coverage.c b/pango/pango-coverage.c index 80fded2b..fa6fb731 100644 --- a/pango/pango-coverage.c +++ b/pango/pango-coverage.c @@ -34,26 +34,11 @@ #include "pango-coverage.h" -typedef struct _PangoBlockInfo PangoBlockInfo; - -#define N_BLOCKS_INCREMENT 256 - -/* The structure of a PangoCoverage object is a two-level table, with blocks of size 256. - * each block is stored as a packed array of 2 bit values for each index, in LSB order. - */ - -struct _PangoBlockInfo -{ - guchar *data; - PangoCoverageLevel level; /* Used if data == NULL */ -}; - struct _PangoCoverage { guint ref_count; - int n_blocks; - PangoBlockInfo *blocks; + hb_set_t *chars; }; /** @@ -71,10 +56,10 @@ pango_coverage_new (void) { PangoCoverage *coverage = g_slice_new (PangoCoverage); - coverage->n_blocks = N_BLOCKS_INCREMENT; - coverage->blocks = g_new0 (PangoBlockInfo, coverage->n_blocks); coverage->ref_count = 1; + coverage->chars = hb_set_create (); + return coverage; } @@ -92,30 +77,17 @@ pango_coverage_new (void) PangoCoverage * pango_coverage_copy (PangoCoverage *coverage) { - int i; - PangoCoverage *result; + PangoCoverage *copy; g_return_val_if_fail (coverage != NULL, NULL); - result = g_slice_new (PangoCoverage); - result->n_blocks = coverage->n_blocks; - result->blocks = g_new (PangoBlockInfo, coverage->n_blocks); - result->ref_count = 1; + copy = g_slice_new (PangoCoverage); - for (i=0; in_blocks; i++) - { - if (coverage->blocks[i].data) - { - result->blocks[i].data = g_new (guchar, 64); - memcpy (result->blocks[i].data, coverage->blocks[i].data, 64); - } - else - result->blocks[i].data = NULL; + copy->ref_count = 1; - result->blocks[i].level = coverage->blocks[i].level; - } + copy->chars = hb_set_reference (coverage->chars); - return result; + return copy; } /** @@ -146,17 +118,12 @@ pango_coverage_ref (PangoCoverage *coverage) void pango_coverage_unref (PangoCoverage *coverage) { - int i; - g_return_if_fail (coverage != NULL); g_return_if_fail (coverage->ref_count > 0); if (g_atomic_int_dec_and_test ((int *) &coverage->ref_count)) { - for (i=0; in_blocks; i++) - g_slice_free1 (64, coverage->blocks[i].data); - - g_free (coverage->blocks); + hb_set_destroy (coverage->chars); g_slice_free (PangoCoverage, coverage); } } @@ -174,33 +141,10 @@ PangoCoverageLevel pango_coverage_get (PangoCoverage *coverage, int index) { - int block_index; + if (hb_set_has (coverage->chars, (hb_codepoint_t)index)) + return PANGO_COVERAGE_EXACT; - g_return_val_if_fail (coverage != NULL, PANGO_COVERAGE_NONE); - - /* index should really have been defined unsigned. Work around - * it by just returning NONE. - */ - if (G_UNLIKELY (index < 0)) - return PANGO_COVERAGE_NONE; - - block_index = index / 256; - - if (block_index >= coverage->n_blocks) - return PANGO_COVERAGE_NONE; - else - { - guchar *data = coverage->blocks[block_index].data; - if (data) - { - int i = index % 256; - int shift = (i % 4) * 2; - - return (data[i/4] >> shift) & 0x3; - } - else - return coverage->blocks[block_index].level; - } + return PANGO_COVERAGE_NONE; } /** @@ -216,48 +160,10 @@ pango_coverage_set (PangoCoverage *coverage, int index, PangoCoverageLevel level) { - int block_index, i; - guchar *data; - - g_return_if_fail (coverage != NULL); - g_return_if_fail (index >= 0); - g_return_if_fail ((guint) level <= 3); - - block_index = index / 256; - - if (block_index >= coverage->n_blocks) - { - int old_n_blocks = coverage->n_blocks; - - coverage->n_blocks = - N_BLOCKS_INCREMENT * ((block_index + N_BLOCKS_INCREMENT) / N_BLOCKS_INCREMENT); - - coverage->blocks = g_renew (PangoBlockInfo, coverage->blocks, coverage->n_blocks); - memset (coverage->blocks + old_n_blocks, 0, - sizeof (PangoBlockInfo) * (coverage->n_blocks - old_n_blocks)); - } - - data = coverage->blocks[block_index].data; - if (!data) - { - guchar byte; - - if (level == coverage->blocks[block_index].level) - return; - - data = g_slice_alloc (64); - coverage->blocks[block_index].data = data; - - byte = coverage->blocks[block_index].level | - (coverage->blocks[block_index].level << 2) | - (coverage->blocks[block_index].level << 4) | - (coverage->blocks[block_index].level << 6); - - memset (data, byte, 64); - } - - i = index % 256; - data[i/4] |= level << ((i % 4) * 2); + if (level != PANGO_COVERAGE_NONE) + hb_set_add (coverage->chars, (hb_codepoint_t)index); + else + hb_set_del (coverage->chars, (hb_codepoint_t)index); } /** @@ -268,97 +174,15 @@ pango_coverage_set (PangoCoverage *coverage, * Set the coverage for each index in @coverage to be the max (better) * value of the current coverage for the index and the coverage for * the corresponding index in @other. + * + * Deprecated: 1.44: This function does nothing **/ void pango_coverage_max (PangoCoverage *coverage, PangoCoverage *other) { - int block_index, i; - int old_blocks; - - g_return_if_fail (coverage != NULL); - - old_blocks = MIN (coverage->n_blocks, other->n_blocks); - - if (other->n_blocks > coverage->n_blocks) - { - coverage->n_blocks = other->n_blocks; - coverage->blocks = g_renew (PangoBlockInfo, coverage->blocks, coverage->n_blocks); - - for (block_index = old_blocks; block_index < coverage->n_blocks; block_index++) - { - if (other->blocks[block_index].data) - { - coverage->blocks[block_index].data = g_new (guchar, 64); - memcpy (coverage->blocks[block_index].data, other->blocks[block_index].data, 64); - } - else - coverage->blocks[block_index].data = NULL; - - coverage->blocks[block_index].level = other->blocks[block_index].level; - } - } - - for (block_index = 0; block_index < old_blocks; block_index++) - { - if (!coverage->blocks[block_index].data && !other->blocks[block_index].data) - { - coverage->blocks[block_index].level = MAX (coverage->blocks[block_index].level, other->blocks[block_index].level); - } - else if (coverage->blocks[block_index].data && other->blocks[block_index].data) - { - guchar *data = coverage->blocks[block_index].data; - - for (i=0; i<64; i++) - { - int byte1 = data[i]; - int byte2 = other->blocks[block_index].data[i]; - - /* There are almost certainly some clever logical ops to do this */ - data[i] = - MAX (byte1 & 0x3, byte2 & 0x3) | - MAX (byte1 & 0xc, byte2 & 0xc) | - MAX (byte1 & 0x30, byte2 & 0x30) | - MAX (byte1 & 0xc0, byte2 & 0xc0); - } - } - else - { - guchar *src, *dest; - int level, byte2; - - if (coverage->blocks[block_index].data) - { - src = dest = coverage->blocks[block_index].data; - level = other->blocks[block_index].level; - } - else - { - src = other->blocks[block_index].data; - dest = g_new (guchar, 64); - coverage->blocks[block_index].data = dest; - level = coverage->blocks[block_index].level; - } - - byte2 = level | (level << 2) | (level << 4) | (level << 6); - - for (i=0; i<64; i++) - { - int byte1 = src[i]; - - /* There are almost certainly some clever logical ops to do this */ - dest[i] = - MAX (byte1 & 0x3, byte2 & 0x3) | - MAX (byte1 & 0xc, byte2 & 0xc) | - MAX (byte1 & 0x30, byte2 & 0x30) | - MAX (byte1 & 0xc0, byte2 & 0xc0); - } - } - } } -#define PANGO_COVERAGE_MAGIC 0xc89dbd5e - /** * pango_coverage_to_bytes: * @coverage: a #PangoCoverage @@ -367,85 +191,16 @@ pango_coverage_max (PangoCoverage *coverage, * @n_bytes: (out): location to store size of result * * Convert a #PangoCoverage structure into a flat binary format + * + * Deprecated: 1.44: This returns %NULL **/ void -pango_coverage_to_bytes (PangoCoverage *coverage, - guchar **bytes, - int *n_bytes) +pango_coverage_to_bytes (PangoCoverage *coverage, + guchar **bytes, + int *n_bytes) { - int i, j; - int size = 8 + 4 * coverage->n_blocks; - guchar *data; - int offset; - - for (i=0; in_blocks; i++) - { - if (coverage->blocks[i].data) - size += 64; - } - - data = g_malloc (size); - - *(guint32 *)&data[0] = g_htonl (PANGO_COVERAGE_MAGIC); /* Magic */ - *(guint32 *)&data[4] = g_htonl (coverage->n_blocks); - offset = 8; - - for (i=0; in_blocks; i++) - { - guint32 header_val; - - /* Check for solid blocks. This is a sort of random place - * to do the optimization, but we care most about getting - * it right when storing it somewhere persistant. - */ - if (coverage->blocks[i].data != NULL) - { - guchar *data = coverage->blocks[i].data; - guchar first_val = data[0]; - - if (first_val == 0 || first_val == 0xff) - { - for (j = 1 ; j < 64; j++) - if (data[j] != first_val) - break; - - if (j == 64) - { - g_slice_free1 (64, data); - coverage->blocks[i].data = NULL; - coverage->blocks[i].level = first_val & 0x3; - } - } - } - - if (coverage->blocks[i].data != NULL) - header_val = (guint32)-1; - else - header_val = coverage->blocks[i].level; - - *(guint32 *)&data[offset] = g_htonl (header_val); - offset += 4; - - if (coverage->blocks[i].data) - { - memcpy (data + offset, coverage->blocks[i].data, 64); - offset += 64; - } - } - - *bytes = data; - *n_bytes = size; -} - -static guint32 -pango_coverage_get_uint32 (guchar **ptr) -{ - guint32 val; - - memcpy (&val, *ptr, 4); - *ptr += 4; - - return g_ntohl (val); + *bytes = NULL; + *n_bytes = 0; } /** @@ -459,53 +214,12 @@ pango_coverage_get_uint32 (guchar **ptr) * * Return value: (transfer full) (nullable): a newly allocated * #PangoCoverage, or %NULL if the data was invalid. + * + * Deprecated: 1.44: This returns %NULL **/ PangoCoverage * pango_coverage_from_bytes (guchar *bytes, int n_bytes) { - PangoCoverage *coverage = g_slice_new0 (PangoCoverage); - guchar *ptr = bytes; - int i; - - coverage->ref_count = 1; - - if (n_bytes < 8) - goto error; - - if (pango_coverage_get_uint32 (&ptr) != PANGO_COVERAGE_MAGIC) - goto error; - - coverage->n_blocks = pango_coverage_get_uint32 (&ptr); - coverage->blocks = g_new0 (PangoBlockInfo, coverage->n_blocks); - - for (i = 0; i < coverage->n_blocks; i++) - { - guint val; - - if (ptr + 4 > bytes + n_bytes) - goto error; - - val = pango_coverage_get_uint32 (&ptr); - if (val == (guint32)-1) - { - if (ptr + 64 > bytes + n_bytes) - goto error; - - coverage->blocks[i].data = g_new (guchar, 64); - memcpy (coverage->blocks[i].data, ptr, 64); - ptr += 64; - } - else - coverage->blocks[i].level = val; - } - - return coverage; - - error: - - pango_coverage_unref (coverage); return NULL; } - - diff --git a/pango/pango-coverage.h b/pango/pango-coverage.h index b83d5108..e46f34d1 100644 --- a/pango/pango-coverage.h +++ b/pango/pango-coverage.h @@ -25,6 +25,7 @@ #include #include +#include G_BEGIN_DECLS @@ -50,6 +51,9 @@ typedef struct _PangoCoverage PangoCoverage; * * Used to indicate how well a font can represent a particular Unicode * character point for a particular script. + * + * Since 1.44, only %PANGO_COVERAGE_NONE and %PANGO_COVERAGE_EXACT + * will be returned. */ typedef enum { PANGO_COVERAGE_NONE, @@ -73,15 +77,15 @@ PANGO_AVAILABLE_IN_ALL void pango_coverage_set (PangoCoverage *coverage, int index_, PangoCoverageLevel level); -PANGO_AVAILABLE_IN_ALL +PANGO_DEPRECATED_IN_1_44 void pango_coverage_max (PangoCoverage *coverage, PangoCoverage *other); -PANGO_AVAILABLE_IN_ALL +PANGO_DEPRECATED_IN_1_44 void pango_coverage_to_bytes (PangoCoverage *coverage, guchar **bytes, int *n_bytes); -PANGO_AVAILABLE_IN_ALL +PANGO_DEPRECATED_IN_1_44 PangoCoverage *pango_coverage_from_bytes (guchar *bytes, int n_bytes); diff --git a/pango/pangofc-fontmap.c b/pango/pangofc-fontmap.c index e88ac431..d90e78c3 100644 --- a/pango/pangofc-fontmap.c +++ b/pango/pangofc-fontmap.c @@ -1985,9 +1985,6 @@ _pango_fc_font_map_get_coverage (PangoFcFontMap *fcfontmap, PangoFcFontFaceData *data; FcCharSet *charset; - if (G_UNLIKELY (!fcfont->font_pattern)) - return NULL; - data = pango_fc_font_map_get_font_face_data (fcfontmap, fcfont->font_pattern); if (G_UNLIKELY (!data)) return NULL; @@ -1999,7 +1996,7 @@ _pango_fc_font_map_get_coverage (PangoFcFontMap *fcfontmap, * doesn't require loading the font */ if (FcPatternGetCharSet (fcfont->font_pattern, FC_CHARSET, 0, &charset) != FcResultMatch) - return NULL; + return NULL; data->coverage = _pango_fc_font_map_fc_to_coverage (charset); } -- cgit v1.2.1