diff options
Diffstat (limited to 'pango/pango-coverage.c')
-rw-r--r-- | pango/pango-coverage.c | 411 |
1 files changed, 75 insertions, 336 deletions
diff --git a/pango/pango-coverage.c b/pango/pango-coverage.c index 80fded2b..41943720 100644 --- a/pango/pango-coverage.c +++ b/pango/pango-coverage.c @@ -32,29 +32,72 @@ #include "config.h" #include <string.h> -#include "pango-coverage.h" +#include "pango-coverage-private.h" -typedef struct _PangoBlockInfo PangoBlockInfo; +G_DEFINE_TYPE (PangoCoverage, pango_coverage, G_TYPE_OBJECT) -#define N_BLOCKS_INCREMENT 256 +static void +pango_coverage_init (PangoCoverage *coverage) +{ +} -/* 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. - */ +static void +pango_coverage_finalize (GObject *object) +{ + PangoCoverage *coverage = PANGO_COVERAGE (object); + + if (coverage->chars) + hb_set_destroy (coverage->chars); + + G_OBJECT_CLASS (pango_coverage_parent_class)->finalize (object); +} + +static PangoCoverageLevel +pango_coverage_real_get (PangoCoverage *coverage, + int index) +{ + if (hb_set_has (coverage->chars, (hb_codepoint_t)index)) + return PANGO_COVERAGE_EXACT; + else + return PANGO_COVERAGE_NONE; +} + +static void +pango_coverage_real_set (PangoCoverage *coverage, + int index, + PangoCoverageLevel level) +{ + if (level != PANGO_COVERAGE_NONE) + hb_set_add (coverage->chars, (hb_codepoint_t)index); + else + hb_set_del (coverage->chars, (hb_codepoint_t)index); +} -struct _PangoBlockInfo +static PangoCoverage * +pango_coverage_real_copy (PangoCoverage *coverage) { - guchar *data; - PangoCoverageLevel level; /* Used if data == NULL */ -}; + PangoCoverage *copy; -struct _PangoCoverage + g_return_val_if_fail (coverage != NULL, NULL); + + copy = g_object_new (PANGO_TYPE_COVERAGE, NULL); + hb_set_destroy (copy->chars); + copy->chars = hb_set_reference (coverage->chars); + + return copy; +} + +static void +pango_coverage_class_init (PangoCoverageClass *class) { - guint ref_count; - int n_blocks; + GObjectClass *object_class = G_OBJECT_CLASS (class); + + object_class->finalize = pango_coverage_finalize; - PangoBlockInfo *blocks; -}; + class->get = pango_coverage_real_get; + class->set = pango_coverage_real_set; + class->copy = pango_coverage_real_copy; +} /** * pango_coverage_new: @@ -69,13 +112,7 @@ struct _PangoCoverage PangoCoverage * 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; - - return coverage; + return g_object_new (PANGO_TYPE_COVERAGE, NULL); } /** @@ -92,30 +129,7 @@ pango_coverage_new (void) PangoCoverage * pango_coverage_copy (PangoCoverage *coverage) { - int i; - PangoCoverage *result; - - 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; - - for (i=0; i<coverage->n_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; - - result->blocks[i].level = coverage->blocks[i].level; - } - - return result; + return PANGO_COVERAGE_GET_CLASS (coverage)->copy (coverage); } /** @@ -129,11 +143,7 @@ pango_coverage_copy (PangoCoverage *coverage) PangoCoverage * pango_coverage_ref (PangoCoverage *coverage) { - g_return_val_if_fail (coverage != NULL, NULL); - - g_atomic_int_inc ((int *) &coverage->ref_count); - - return coverage; + return g_object_ref (coverage); } /** @@ -146,19 +156,7 @@ 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; i<coverage->n_blocks; i++) - g_slice_free1 (64, coverage->blocks[i].data); - - g_free (coverage->blocks); - g_slice_free (PangoCoverage, coverage); - } + g_object_unref (coverage); } /** @@ -174,33 +172,7 @@ PangoCoverageLevel pango_coverage_get (PangoCoverage *coverage, int index) { - int block_index; - - 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_GET_CLASS (coverage)->get (coverage, index); } /** @@ -216,48 +188,7 @@ 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); + PANGO_COVERAGE_GET_CLASS (coverage)->set (coverage, index, level); } /** @@ -268,97 +199,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 +216,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) -{ - int i, j; - int size = 8 + 4 * coverage->n_blocks; - guchar *data; - int offset; - - for (i=0; i<coverage->n_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; i<coverage->n_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) +pango_coverage_to_bytes (PangoCoverage *coverage, + guchar **bytes, + int *n_bytes) { - guint32 val; - - memcpy (&val, *ptr, 4); - *ptr += 4; - - return g_ntohl (val); + *bytes = NULL; + *n_bytes = 0; } /** @@ -459,53 +239,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; } - - |