diff options
author | Owen Taylor <otaylor@redhat.com> | 2000-02-01 06:55:09 +0000 |
---|---|---|
committer | Owen Taylor <otaylor@src.gnome.org> | 2000-02-01 06:55:09 +0000 |
commit | 532c6902c34f47d5f838623c951e53d5fcdd395f (patch) | |
tree | 1a336bca112ada6b934f264b9c832bceb6fe1771 /pango/pango-coverage.c | |
parent | 635469870a2b1375105cb305b9f4b09fa05d2208 (diff) | |
download | pango-532c6902c34f47d5f838623c951e53d5fcdd395f.tar.gz |
The great header file reorganization. Split up roughtly by objects.
Wed Feb 2 00:07:13 2000 Owen Taylor <otaylor@redhat.com>
* libpango/pango-*.h: The great header file reorganization.
Split up roughtly by objects.
* libpango/pango-font.h libpango/fonts.h: Add generic
font-loading and listing interfaces.
* libpango/pangox.c: Implement font-listing/loading interfaces
for X.
* libpango/pango-context.[ch]: Flesh out context structure.
Add appropriate accesors, font loading-methods, etc.
* libpango/pango-coverage.[ch]: Coverage map objects.
* examples/viewer.c: First stab at adding font-selection. Majorly
deficient for the moment until we add font lists and fallbacks
based on coverage maps.
Diffstat (limited to 'pango/pango-coverage.c')
-rw-r--r-- | pango/pango-coverage.c | 299 |
1 files changed, 299 insertions, 0 deletions
diff --git a/pango/pango-coverage.c b/pango/pango-coverage.c new file mode 100644 index 00000000..38bc62ca --- /dev/null +++ b/pango/pango-coverage.c @@ -0,0 +1,299 @@ +/* Pango + * pango-coverage.c: Coverage maps for fonts + * + * Copyright (C) 2000 Red Hat Software + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#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 +{ + int n_blocks; + int data_size; + + PangoBlockInfo *blocks; +}; + +/** + * pango_coverage_new: + * + * Create a new #PangoCoverage + * + * Return value: a new PangoCoverage object, initialized to PANGO_COVERAGE_NONE + **/ +PangoCoverage * +pango_coverage_new (void) +{ + int i; + PangoCoverage *coverage = g_new (PangoCoverage, 1); + + coverage->n_blocks = N_BLOCKS_INCREMENT; + coverage->blocks = g_new (PangoBlockInfo, coverage->n_blocks); + + for (i=0; i<coverage->n_blocks; i++) + { + coverage->blocks[i].data = NULL; + coverage->blocks[i].level = PANGO_COVERAGE_NONE; + } + + return coverage; +} + +/** + * pango_coverage_copy: + * @coverage: a #PangoCoverage + * + * Copy an existing #PangoCoverage + * + * Return value: a copy of @coverage + **/ +PangoCoverage * +pango_coverage_copy (PangoCoverage *coverage) +{ + int i; + PangoCoverage *result = g_new (PangoCoverage, 1); + + g_return_val_if_fail (coverage != NULL, NULL); + + result->n_blocks = coverage->n_blocks; + result->blocks = g_new (PangoBlockInfo, coverage->n_blocks); + + 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; +} + +/** + * pango_coverage_destroy: + * @coverage: a #PangoCoverage + * + * Destroy a #PangoCoverage object, freeing associated memory + **/ +void pango_coverage_destroy (PangoCoverage *coverage) +{ + int i; + + g_return_if_fail (coverage != NULL); + + for (i=0; i<coverage->n_blocks; i++) + { + if (coverage->blocks[i].data) + g_free (coverage->blocks[i].data); + } + + g_free (coverage); +} + +/** + * pango_coverage_get: + * @coverage: a #PangoCoverage + * @index: the index to check + * + * Determine whether a particular index is covered by @coverage + * + * Return value: + **/ +PangoCoverageLevel +pango_coverage_get (PangoCoverage *coverage, + int index) +{ + int block_index; + + g_return_val_if_fail (coverage != NULL, 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; + } +} + +/** + * pango_coverage_set: + * @coverage: a #PangoCoverage + * @index: the index to modify + * @level: the new level for @index + * + * Modify a particular index within @coverage + **/ +void 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 (level < 0 || level > 3); + + block_index = index / 256; + + if (block_index > coverage->n_blocks) + { + coverage->n_blocks += N_BLOCKS_INCREMENT; + coverage->blocks = g_renew (PangoBlockInfo, coverage->blocks, coverage->n_blocks); + } + + data = coverage->blocks[block_index].data; + if (!data) + { + if (level == coverage->blocks[block_index].level) + return; + + data = g_new0 (guchar, 64); + coverage->blocks[block_index].data = data; + } + + i = index % 256; + data[i] |= level << ((i % 4) * 2); +} + +/** + * pango_coverage_max: + * @coverage: a #PangoCoverage + * @other: another #PangoCoverage + * + * 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. + **/ +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 += N_BLOCKS_INCREMENT; + 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 & 0xc00); + } + } + 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 & 0xc00); + } + } + } +} + + |