diff options
author | Henry Stiles <henry.stiles@artifex.com> | 1998-07-28 06:22:20 +0000 |
---|---|---|
committer | Henry Stiles <henry.stiles@artifex.com> | 1998-07-28 06:22:20 +0000 |
commit | 5fbdbaab7335a147a3a7890b5c6fc123926815db (patch) | |
tree | 154edc89b06c38333fd6d4b9abaf0ee8740ddf6a /gs/src/gxccman.c | |
parent | 14cf10e3738f95f7864978c5a4778b50fb39524b (diff) |
This commit was generated by cvs2svn to compensate for changes in r257,
which included commits to RCS files with non-trunk default branches.
git-svn-id: http://svn.ghostscript.com/ghostpcl/trunk/ghostpcl@258 06663e23-700e-0410-b217-a244a6096597
Diffstat (limited to 'gs/src/gxccman.c')
-rw-r--r-- | gs/src/gxccman.c | 1191 |
1 files changed, 601 insertions, 590 deletions
diff --git a/gs/src/gxccman.c b/gs/src/gxccman.c index 681328a7d..36a578fca 100644 --- a/gs/src/gxccman.c +++ b/gs/src/gxccman.c @@ -1,20 +1,20 @@ /* Copyright (C) 1989, 1995, 1996, 1997 Aladdin Enterprises. All rights reserved. - - This file is part of Aladdin Ghostscript. - - Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND. No author - or distributor accepts any responsibility for the consequences of using it, - or for whether it serves any particular purpose or works at all, unless he - or she says so in writing. Refer to the Aladdin Ghostscript Free Public - License (the "License") for full details. - - Every copy of Aladdin Ghostscript must include a copy of the License, - normally in a plain ASCII text file named PUBLIC. The License grants you - the right to copy, modify and redistribute Aladdin Ghostscript, but only - under certain conditions described in the License. Among other things, the - License requires that the copyright notice and this notice be preserved on - all copies. -*/ + + This file is part of Aladdin Ghostscript. + + Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND. No author + or distributor accepts any responsibility for the consequences of using it, + or for whether it serves any particular purpose or works at all, unless he + or she says so in writing. Refer to the Aladdin Ghostscript Free Public + License (the "License") for full details. + + Every copy of Aladdin Ghostscript must include a copy of the License, + normally in a plain ASCII text file named PUBLIC. The License grants you + the right to copy, modify and redistribute Aladdin Ghostscript, but only + under certain conditions described in the License. Among other things, the + License requires that the copyright notice and this notice be preserved on + all copies. + */ /* gxccman.c */ /* Character cache management routines for Ghostscript library */ @@ -24,7 +24,7 @@ #include "gserrors.h" #include "gsstruct.h" #include "gsbitops.h" -#include "gsutil.h" /* for gs_next_ids */ +#include "gsutil.h" /* for gs_next_ids */ #include "gxfixed.h" #include "gxmatrix.h" #include "gzstate.h" @@ -39,19 +39,23 @@ /* Define the descriptors for the cache structures. */ private_st_cached_fm_pair(); private_st_cached_fm_pair_elt(); -/*private_st_cached_char();*/ /* unused */ -private_st_cached_char_ptr(); /* unused */ + /*private_st_cached_char(); *//* unused */ +private_st_cached_char_ptr(); /* unused */ private_st_cached_char_ptr_elt(); /* GC procedures */ /* We do all the work in font_dir_enum/reloc_ptrs in gsfont.c. */ /* See gxfcache.h for details. */ -private ENUM_PTRS_BEGIN(cc_ptr_enum_ptrs) return 0; +private +ENUM_PTRS_BEGIN(cc_ptr_enum_ptrs) return 0; + ENUM_PTRS_END -private RELOC_PTRS_BEGIN(cc_ptr_reloc_ptrs) { -} RELOC_PTRS_END +private RELOC_PTRS_BEGIN(cc_ptr_reloc_ptrs) +{ +} +RELOC_PTRS_END /* Forward references */ -private gx_xfont *lookup_xfont_by_name(P6(gx_device *, gx_xfont_procs *, gs_font_name *, int, const cached_fm_pair *, const gs_matrix *)); +private gx_xfont * lookup_xfont_by_name(P6(gx_device *, gx_xfont_procs *, gs_font_name *, int, const cached_fm_pair *, const gs_matrix *)); private cached_char *alloc_char(P2(gs_font_dir *, ulong)); private cached_char *alloc_char_in_chunk(P2(gs_font_dir *, ulong)); private void hash_remove_cached_char(P2(gs_font_dir *, uint)); @@ -61,63 +65,64 @@ private void shorten_cached_char(P3(gs_font_dir *, cached_char *, uint)); /* Allocate and initialize the character cache elements of a font directory. */ int -gx_char_cache_alloc(gs_memory_t *mem, register gs_font_dir *pdir, - uint bmax, uint mmax, uint cmax, uint upper) -{ /* Since we use open hashing, we must increase cmax somewhat. */ - uint chsize = (cmax + (cmax >> 1)) | 31; - cached_fm_pair *mdata; - cached_char **chars; - - /* Round up chsize to a power of 2. */ - while ( chsize & (chsize + 1) ) - chsize |= chsize >> 1; - chsize++; - mdata = gs_alloc_struct_array(mem, mmax, cached_fm_pair, - &st_cached_fm_pair_element, - "font_dir_alloc(mdata)"); - chars = gs_alloc_struct_array(mem, chsize, cached_char *, - &st_cached_char_ptr_element, - "font_dir_alloc(chars)"); - if ( mdata == 0 || chars == 0 ) - { gs_free_object(mem, chars, "font_dir_alloc(chars)"); - gs_free_object(mem, mdata, "font_dir_alloc(mdata)"); - return_error(gs_error_VMerror); - } - pdir->fmcache.mmax = mmax; - pdir->fmcache.mdata = mdata; - pdir->ccache.memory = mem; - pdir->ccache.bmax = bmax; - pdir->ccache.cmax = cmax; - pdir->ccache.lower = upper / 10; - pdir->ccache.upper = upper; - pdir->ccache.table = chars; - pdir->ccache.table_mask = chsize - 1; - gx_char_cache_init(pdir); - return 0; +gx_char_cache_alloc(gs_memory_t * mem, register gs_font_dir * pdir, + uint bmax, uint mmax, uint cmax, uint upper) +{ /* Since we use open hashing, we must increase cmax somewhat. */ + uint chsize = (cmax + (cmax >> 1)) | 31; + cached_fm_pair *mdata; + cached_char **chars; + + /* Round up chsize to a power of 2. */ + while (chsize & (chsize + 1)) + chsize |= chsize >> 1; + chsize++; + mdata = gs_alloc_struct_array(mem, mmax, cached_fm_pair, + &st_cached_fm_pair_element, + "font_dir_alloc(mdata)"); + chars = gs_alloc_struct_array(mem, chsize, cached_char *, + &st_cached_char_ptr_element, + "font_dir_alloc(chars)"); + if (mdata == 0 || chars == 0) { + gs_free_object(mem, chars, "font_dir_alloc(chars)"); + gs_free_object(mem, mdata, "font_dir_alloc(mdata)"); + return_error(gs_error_VMerror); + } + pdir->fmcache.mmax = mmax; + pdir->fmcache.mdata = mdata; + pdir->ccache.memory = mem; + pdir->ccache.bmax = bmax; + pdir->ccache.cmax = cmax; + pdir->ccache.lower = upper / 10; + pdir->ccache.upper = upper; + pdir->ccache.table = chars; + pdir->ccache.table_mask = chsize - 1; + gx_char_cache_init(pdir); + return 0; } /* Initialize the character cache. */ void -gx_char_cache_init(register gs_font_dir *dir) -{ int i; - cached_fm_pair *pair; - char_cache_chunk *cck = - (char_cache_chunk *)gs_malloc(1, sizeof(char_cache_chunk), - "initial_chunk"); - - dir->fmcache.msize = 0; - dir->fmcache.mnext = 0; - gx_bits_cache_chunk_init(cck, NULL, 0); - gx_bits_cache_init((gx_bits_cache *)&dir->ccache, cck); - dir->ccache.bspace = 0; - memset((char *)dir->ccache.table, 0, - (dir->ccache.table_mask + 1) * sizeof(cached_char *)); - for ( i = 0, pair = dir->fmcache.mdata; - i < dir->fmcache.mmax; i++, pair++ - ) - { pair->index = i; - fm_pair_init(pair); - } +gx_char_cache_init(register gs_font_dir * dir) +{ + int i; + cached_fm_pair *pair; + char_cache_chunk *cck = + (char_cache_chunk *) gs_malloc(1, sizeof(char_cache_chunk), + "initial_chunk"); + + dir->fmcache.msize = 0; + dir->fmcache.mnext = 0; + gx_bits_cache_chunk_init(cck, NULL, 0); + gx_bits_cache_init((gx_bits_cache *) & dir->ccache, cck); + dir->ccache.bspace = 0; + memset((char *)dir->ccache.table, 0, + (dir->ccache.table_mask + 1) * sizeof(cached_char *)); + for (i = 0, pair = dir->fmcache.mdata; + i < dir->fmcache.mmax; i++, pair++ + ) { + pair->index = i; + fm_pair_init(pair); + } } /* ====== Purging ====== */ @@ -125,20 +130,21 @@ gx_char_cache_init(register gs_font_dir *dir) /* Purge from the character cache all entries selected by */ /* a client-supplied procedure. */ void -gx_purge_selected_cached_chars(gs_font_dir *dir, - bool (*proc)(P2(cached_char *, void *)), void *proc_data) -{ int chi; - int cmax = dir->ccache.table_mask; - - for ( chi = 0; chi <= cmax; ) - { cached_char *cc = dir->ccache.table[chi]; - if ( cc != 0 && (*proc)(cc, proc_data) ) - { hash_remove_cached_char(dir, chi); - gx_free_cached_char(dir, cc); - } - else - chi++; - } +gx_purge_selected_cached_chars(gs_font_dir * dir, + bool(*proc) (P2(cached_char *, void *)), void *proc_data) +{ + int chi; + int cmax = dir->ccache.table_mask; + + for (chi = 0; chi <= cmax;) { + cached_char *cc = dir->ccache.table[chi]; + + if (cc != 0 && (*proc) (cc, proc_data)) { + hash_remove_cached_char(dir, chi); + gx_free_cached_char(dir, cc); + } else + chi++; + } } /* ====== Font-level routines ====== */ @@ -146,113 +152,112 @@ gx_purge_selected_cached_chars(gs_font_dir *dir, /* Add a font/matrix pair to the cache. */ /* (This is only exported for gxccache.c.) */ cached_fm_pair * -gx_add_fm_pair(register gs_font_dir *dir, gs_font *font, const gs_uid *puid, - const gs_state *pgs) -{ register cached_fm_pair *pair = - dir->fmcache.mdata + dir->fmcache.mnext; - cached_fm_pair *mend = - dir->fmcache.mdata + dir->fmcache.mmax; - - if ( dir->fmcache.msize == dir->fmcache.mmax ) /* cache is full */ - { /* Prefer an entry with num_chars == 0, if any. */ - int count; - for ( count = dir->fmcache.mmax; - --count >= 0 && pair->num_chars != 0; - ) - if ( ++pair == mend ) - pair = dir->fmcache.mdata; - gs_purge_fm_pair(dir, pair, 0); - } - else - { /* Look for an empty entry. (We know there is one.) */ - while ( !fm_pair_is_free(pair) ) - if ( ++pair == mend ) - pair = dir->fmcache.mdata; - } - dir->fmcache.msize++; - dir->fmcache.mnext = pair + 1 - dir->fmcache.mdata; - if ( dir->fmcache.mnext == dir->fmcache.mmax ) - dir->fmcache.mnext = 0; - pair->font = font; - pair->UID = *puid; - pair->FontType = font->FontType; - /* The OSF/1 compiler doesn't like casting a pointer to */ - /* a shorter int.... */ - pair->hash = (uint)(ulong)pair % 549; /* scramble bits */ - pair->mxx = pgs->char_tm.xx, pair->mxy = pgs->char_tm.xy; - pair->myx = pgs->char_tm.yx, pair->myy = pgs->char_tm.yy; - pair->num_chars = 0; - pair->xfont_tried = false; - pair->xfont = 0; - if_debug8('k', "[k]adding pair 0x%lx: font=0x%lx [%g %g %g %g] UID %ld, 0x%lx\n", - (ulong)pair, (ulong)font, - pair->mxx, pair->mxy, pair->myx, pair->myy, - (long)pair->UID.id, (ulong)pair->UID.xvalues); - return pair; +gx_add_fm_pair(register gs_font_dir * dir, gs_font * font, const gs_uid * puid, + const gs_state * pgs) +{ + register cached_fm_pair *pair = + dir->fmcache.mdata + dir->fmcache.mnext; + cached_fm_pair *mend = + dir->fmcache.mdata + dir->fmcache.mmax; + + if (dir->fmcache.msize == dir->fmcache.mmax) { /* cache is full *//* Prefer an entry with num_chars == 0, if any. */ + int count; + + for (count = dir->fmcache.mmax; + --count >= 0 && pair->num_chars != 0; + ) + if (++pair == mend) + pair = dir->fmcache.mdata; + gs_purge_fm_pair(dir, pair, 0); + } else { /* Look for an empty entry. (We know there is one.) */ + while (!fm_pair_is_free(pair)) + if (++pair == mend) + pair = dir->fmcache.mdata; + } + dir->fmcache.msize++; + dir->fmcache.mnext = pair + 1 - dir->fmcache.mdata; + if (dir->fmcache.mnext == dir->fmcache.mmax) + dir->fmcache.mnext = 0; + pair->font = font; + pair->UID = *puid; + pair->FontType = font->FontType; + /* The OSF/1 compiler doesn't like casting a pointer to */ + /* a shorter int.... */ + pair->hash = (uint) (ulong) pair % 549; /* scramble bits */ + pair->mxx = pgs->char_tm.xx, pair->mxy = pgs->char_tm.xy; + pair->myx = pgs->char_tm.yx, pair->myy = pgs->char_tm.yy; + pair->num_chars = 0; + pair->xfont_tried = false; + pair->xfont = 0; + if_debug8('k', "[k]adding pair 0x%lx: font=0x%lx [%g %g %g %g] UID %ld, 0x%lx\n", + (ulong) pair, (ulong) font, + pair->mxx, pair->mxy, pair->myx, pair->myy, + (long)pair->UID.id, (ulong) pair->UID.xvalues); + return pair; } /* Look up the xfont for a font/matrix pair. */ /* (This is only exported for gxccache.c.) */ void -gx_lookup_xfont(const gs_state *pgs, cached_fm_pair *pair, int encoding_index) -{ gx_device *dev = gs_currentdevice(pgs); - gx_device *fdev = (*dev_proc(dev, get_xfont_device))(dev); - gs_font *font = pair->font; - gx_xfont_procs *procs = (*dev_proc(fdev, get_xfont_procs))(fdev); - gx_xfont *xf = 0; - - /* We mustn't attempt to use xfonts for stroked characters, */ - /* because such characters go outside their bounding box. */ - if ( procs != 0 && font->PaintType == 0 ) - { gs_matrix mat; - - mat.xx = pair->mxx, mat.xy = pair->mxy; - mat.yx = pair->myx, mat.yy = pair->myy; - mat.tx = 0, mat.ty = 0; - /* xfonts can outlive their invocations, */ - /* but restore purges them properly. */ - pair->memory = pgs->memory; - if ( font->key_name.size != 0 ) - xf = lookup_xfont_by_name(fdev, procs, - &font->key_name, encoding_index, - pair, &mat); +gx_lookup_xfont(const gs_state * pgs, cached_fm_pair * pair, int encoding_index) +{ + gx_device *dev = gs_currentdevice(pgs); + gx_device *fdev = (*dev_proc(dev, get_xfont_device)) (dev); + gs_font *font = pair->font; + gx_xfont_procs *procs = (*dev_proc(fdev, get_xfont_procs)) (fdev); + gx_xfont *xf = 0; + + /* We mustn't attempt to use xfonts for stroked characters, */ + /* because such characters go outside their bounding box. */ + if (procs != 0 && font->PaintType == 0) { + gs_matrix mat; + + mat.xx = pair->mxx, mat.xy = pair->mxy; + mat.yx = pair->myx, mat.yy = pair->myy; + mat.tx = 0, mat.ty = 0; + /* xfonts can outlive their invocations, */ + /* but restore purges them properly. */ + pair->memory = pgs->memory; + if (font->key_name.size != 0) + xf = lookup_xfont_by_name(fdev, procs, + &font->key_name, encoding_index, + pair, &mat); #define font_name_eq(pfn1,pfn2)\ ((pfn1)->size == (pfn2)->size && (pfn1)->size != 0 &&\ !memcmp((char *)(pfn1)->chars, (char *)(pfn2)->chars, (pfn1)->size)) - if ( xf == 0 && font->font_name.size != 0 && - /* Avoid redundant lookup */ - !font_name_eq(&font->font_name, &font->key_name) - ) - xf = lookup_xfont_by_name(fdev, procs, - &font->font_name, encoding_index, - pair, &mat); - if ( xf == 0 && font->FontType != ft_composite && - uid_is_valid(&((gs_font_base *)font)->UID) - ) - { /* Look for an original font with the same UID. */ - gs_font_dir *pdir = font->dir; - gs_font *pfont; - - for ( pfont = pdir->orig_fonts; pfont != 0; - pfont = pfont->next - ) - { if ( pfont->FontType != ft_composite && - uid_equal(&((gs_font_base *)pfont)->UID, - &((gs_font_base *)font)->UID) && - pfont->key_name.size != 0 && - !font_name_eq(&font->key_name, - &pfont->key_name) - ) - { xf = lookup_xfont_by_name(fdev, procs, - &pfont->key_name, - encoding_index, pair, &mat); - if ( xf != 0 ) - break; - } - } + if (xf == 0 && font->font_name.size != 0 && + /* Avoid redundant lookup */ + !font_name_eq(&font->font_name, &font->key_name) + ) + xf = lookup_xfont_by_name(fdev, procs, + &font->font_name, encoding_index, + pair, &mat); + if (xf == 0 && font->FontType != ft_composite && + uid_is_valid(&((gs_font_base *) font)->UID) + ) { /* Look for an original font with the same UID. */ + gs_font_dir *pdir = font->dir; + gs_font *pfont; + + for (pfont = pdir->orig_fonts; pfont != 0; + pfont = pfont->next + ) { + if (pfont->FontType != ft_composite && + uid_equal(&((gs_font_base *) pfont)->UID, + &((gs_font_base *) font)->UID) && + pfont->key_name.size != 0 && + !font_name_eq(&font->key_name, + &pfont->key_name) + ) { + xf = lookup_xfont_by_name(fdev, procs, + &pfont->key_name, + encoding_index, pair, &mat); + if (xf != 0) + break; } + } } - pair->xfont = xf; + } + pair->xfont = xf; } /* ------ Internal routines ------ */ @@ -261,57 +266,61 @@ gx_lookup_xfont(const gs_state *pgs, cached_fm_pair *pair, int encoding_index) /* or just characters that depend on its xfont. */ #define cpair ((cached_fm_pair *)vpair) private bool -purge_fm_pair_char(cached_char *cc, void *vpair) -{ return cc_pair(cc) == cpair; +purge_fm_pair_char(cached_char * cc, void *vpair) +{ + return cc_pair(cc) == cpair; } private bool -purge_fm_pair_char_xfont(cached_char *cc, void *vpair) -{ return cc_pair(cc) == cpair && cpair->xfont == 0 && !cc_has_bits(cc); +purge_fm_pair_char_xfont(cached_char * cc, void *vpair) +{ + return cc_pair(cc) == cpair && cpair->xfont == 0 && !cc_has_bits(cc); } #undef cpair void -gs_purge_fm_pair(gs_font_dir *dir, cached_fm_pair *pair, int xfont_only) -{ if_debug2('k', "[k]purging pair 0x%lx%s\n", - (ulong)pair, (xfont_only ? " (xfont only)" : "")); - if ( pair->xfont != 0 ) - { (*pair->xfont->common.procs->release)(pair->xfont, - pair->memory); - pair->xfont_tried = false; - pair->xfont = 0; - } - gx_purge_selected_cached_chars(dir, - (xfont_only ? purge_fm_pair_char_xfont : - purge_fm_pair_char), - pair); - if ( !xfont_only ) - { +gs_purge_fm_pair(gs_font_dir * dir, cached_fm_pair * pair, int xfont_only) +{ + if_debug2('k', "[k]purging pair 0x%lx%s\n", + (ulong) pair, (xfont_only ? " (xfont only)" : "")); + if (pair->xfont != 0) { + (*pair->xfont->common.procs->release) (pair->xfont, + pair->memory); + pair->xfont_tried = false; + pair->xfont = 0; + } + gx_purge_selected_cached_chars(dir, + (xfont_only ? purge_fm_pair_char_xfont : + purge_fm_pair_char), + pair); + if (!xfont_only) { #ifdef DEBUG - if ( pair->num_chars != 0 ) - { lprintf1("Error in gs_purge_fm_pair: num_chars =%d\n", - pair->num_chars); - } + if (pair->num_chars != 0) { + lprintf1("Error in gs_purge_fm_pair: num_chars =%d\n", + pair->num_chars); + } #endif - fm_pair_set_free(pair); - dir->fmcache.msize--; - } + fm_pair_set_free(pair); + dir->fmcache.msize--; + } } /* Look up an xfont by name. */ /* The caller must already have done get_xfont_device to get the proper */ /* device to pass as the first argument to lookup_font. */ private gx_xfont * -lookup_xfont_by_name(gx_device *fdev, gx_xfont_procs *procs, - gs_font_name *pfstr, int encoding_index, const cached_fm_pair *pair, - const gs_matrix *pmat) -{ gx_xfont *xf; - if_debug5('k', "[k]lookup xfont %s [%g %g %g %g]\n", - pfstr->chars, pmat->xx, pmat->xy, pmat->yx, pmat->yy); - xf = (*procs->lookup_font)(fdev, - &pfstr->chars[0], pfstr->size, - encoding_index, &pair->UID, - pmat, pair->memory); - if_debug1('k', "[k]... xfont=0x%lx\n", (ulong)xf); - return xf; +lookup_xfont_by_name(gx_device * fdev, gx_xfont_procs * procs, + gs_font_name * pfstr, int encoding_index, const cached_fm_pair * pair, + const gs_matrix * pmat) +{ + gx_xfont *xf; + + if_debug5('k', "[k]lookup xfont %s [%g %g %g %g]\n", + pfstr->chars, pmat->xx, pmat->xy, pmat->yx, pmat->yy); + xf = (*procs->lookup_font) (fdev, + &pfstr->chars[0], pfstr->size, + encoding_index, &pair->UID, + pmat, pair->memory); + if_debug1('k', "[k]... xfont=0x%lx\n", (ulong) xf); + return xf; } /* ====== Character-level routines ====== */ @@ -332,432 +341,434 @@ lookup_xfont_by_name(gx_device *fdev, gx_xfont_procs *procs, * device) as target. */ cached_char * -gx_alloc_char_bits(gs_font_dir *dir, gx_device_memory *dev, - gx_device_memory *dev2, ushort iwidth, ushort iheight, - const gs_log2_scale_point *pscale, int depth) -{ int log2_xscale = pscale->x; - int log2_yscale = pscale->y; - int log2_depth = depth >> 1; /* works for 1,2,4 */ - uint nwidth_bits = (iwidth >> log2_xscale) << log2_depth; - ulong isize, icdsize; - uint iraster; - cached_char *cc; - gx_device_memory mdev; - gx_device_memory *pdev = dev; - gx_device_memory *pdev2; - - if ( dev == NULL ) - { mdev.memory = 0; - mdev.target = 0; - pdev = &mdev; - } - pdev2 = (dev2 == 0 ? pdev : dev2); - - /* Compute the scaled-down bitmap size, and test against */ - /* the maximum cachable character size. */ +gx_alloc_char_bits(gs_font_dir * dir, gx_device_memory * dev, + gx_device_memory * dev2, ushort iwidth, ushort iheight, + const gs_log2_scale_point * pscale, int depth) +{ + int log2_xscale = pscale->x; + int log2_yscale = pscale->y; + int log2_depth = depth >> 1; /* works for 1,2,4 */ + uint nwidth_bits = (iwidth >> log2_xscale) << log2_depth; + ulong isize, icdsize; + uint iraster; + cached_char *cc; + gx_device_memory mdev; + gx_device_memory *pdev = dev; + gx_device_memory *pdev2; + + if (dev == NULL) { + mdev.memory = 0; + mdev.target = 0; + pdev = &mdev; + } + pdev2 = (dev2 == 0 ? pdev : dev2); + + /* Compute the scaled-down bitmap size, and test against */ + /* the maximum cachable character size. */ + + iraster = bitmap_raster(nwidth_bits); + if (iraster != 0 && iheight >> log2_yscale > dir->ccache.upper / iraster) { + if_debug5('k', "[k]no cache bits: scale=%dx%d, raster/scale=%u, height/scale=%u, upper=%u\n", + 1 << log2_xscale, 1 << log2_yscale, + iraster, iheight, dir->ccache.upper); + return 0; /* too big */ + } + /* Compute the actual bitmap size(s) and allocate the bits. */ + + if (dev2 == 0) { /* Render to a full (possibly oversampled) bitmap; */ + /* compress (if needed) when done. */ + gs_make_mem_mono_device(pdev, pdev->memory, pdev->target); + pdev->width = iwidth; + pdev->height = iheight; + isize = gdev_mem_bitmap_size(pdev); + } else { /* Use an alpha-buffer device to compress as we go. */ + gs_make_mem_alpha_device(dev2, dev2->memory, NULL, depth); + dev2->width = iwidth >> log2_xscale; + dev2->height = iheight >> log2_yscale; + gs_make_mem_abuf_device(dev, dev->memory, (gx_device *) dev2, + pscale, depth, 0); + dev->width = iwidth; + dev->height = 2 << log2_yscale; + isize = gdev_mem_bitmap_size(dev) + + gdev_mem_bitmap_size(dev2); + } + icdsize = isize + sizeof_cached_char; + cc = alloc_char(dir, icdsize); + if (cc == 0) + return 0; + if_debug4('k', "[k]adding char 0x%lx:%u(%u,%u)\n", + (ulong) cc, (uint) icdsize, iwidth, iheight); + + /* Fill in the entry. */ + + cc_set_depth(cc, depth); + cc->xglyph = gx_no_xglyph; + /* Set the width and height to those of the device. */ + /* Note that if we are oversampling without an alpha buffer. */ + /* these are not the final unscaled dimensions. */ + cc->width = pdev2->width; + cc->height = pdev2->height; + cc->shift = 0; + cc_set_raster(cc, gdev_mem_raster(pdev2)); + cc_set_pair_only(cc, 0); /* not linked in yet */ + cc->id = gx_no_bitmap_id; + + /* Open the cache device(s). */ + + if (dev2) { /* The second device is an alpha device that targets */ + /* the real storage for the character. */ + byte *bits = cc_bits(cc); + uint bsize = (uint) gdev_mem_bitmap_size(dev2); - iraster = bitmap_raster(nwidth_bits); - if ( iraster != 0 && iheight >> log2_yscale > dir->ccache.upper / iraster ) - { if_debug5('k', "[k]no cache bits: scale=%dx%d, raster/scale=%u, height/scale=%u, upper=%u\n", - 1 << log2_xscale, 1 << log2_yscale, - iraster, iheight, dir->ccache.upper); - return 0; /* too big */ - } + memset(bits, 0, bsize); + dev2->base = bits; + (*dev_proc(dev2, open_device)) ((gx_device *) dev2); + dev->base = bits + bsize; + (*dev_proc(dev, open_device)) ((gx_device *) dev); + } else if (dev) + gx_open_cache_device(dev, cc); - /* Compute the actual bitmap size(s) and allocate the bits. */ - - if ( dev2 == 0 ) - { /* Render to a full (possibly oversampled) bitmap; */ - /* compress (if needed) when done. */ - gs_make_mem_mono_device(pdev, pdev->memory, pdev->target); - pdev->width = iwidth; - pdev->height = iheight; - isize = gdev_mem_bitmap_size(pdev); - } - else - { /* Use an alpha-buffer device to compress as we go. */ - gs_make_mem_alpha_device(dev2, dev2->memory, NULL, depth); - dev2->width = iwidth >> log2_xscale; - dev2->height = iheight >> log2_yscale; - gs_make_mem_abuf_device(dev, dev->memory, (gx_device *)dev2, - pscale, depth, 0); - dev->width = iwidth; - dev->height = 2 << log2_yscale; - isize = gdev_mem_bitmap_size(dev) + - gdev_mem_bitmap_size(dev2); - } - icdsize = isize + sizeof_cached_char; - cc = alloc_char(dir, icdsize); - if ( cc == 0 ) - return 0; - if_debug4('k', "[k]adding char 0x%lx:%u(%u,%u)\n", - (ulong)cc, (uint)icdsize, iwidth, iheight); - - /* Fill in the entry. */ - - cc_set_depth(cc, depth); - cc->xglyph = gx_no_xglyph; - /* Set the width and height to those of the device. */ - /* Note that if we are oversampling without an alpha buffer. */ - /* these are not the final unscaled dimensions. */ - cc->width = pdev2->width; - cc->height = pdev2->height; - cc->shift = 0; - cc_set_raster(cc, gdev_mem_raster(pdev2)); - cc_set_pair_only(cc, 0); /* not linked in yet */ - cc->id = gx_no_bitmap_id; - - /* Open the cache device(s). */ - - if ( dev2 ) - { /* The second device is an alpha device that targets */ - /* the real storage for the character. */ - byte *bits = cc_bits(cc); - uint bsize = (uint)gdev_mem_bitmap_size(dev2); - - memset(bits, 0, bsize); - dev2->base = bits; - (*dev_proc(dev2, open_device))((gx_device *)dev2); - dev->base = bits + bsize; - (*dev_proc(dev, open_device))((gx_device *)dev); - } - else if ( dev ) - gx_open_cache_device(dev, cc); - - return cc; + return cc; } /* Open the cache device. */ void -gx_open_cache_device(gx_device_memory *dev, cached_char *cc) -{ byte *bits = cc_bits(cc); - - dev->width = cc->width; - dev->height = cc->height; - memset((char *)bits, 0, (uint)gdev_mem_bitmap_size(dev)); - dev->base = bits; - (*dev_proc(dev, open_device))((gx_device *)dev); /* initialize */ +gx_open_cache_device(gx_device_memory * dev, cached_char * cc) +{ + byte *bits = cc_bits(cc); + + dev->width = cc->width; + dev->height = cc->height; + memset((char *)bits, 0, (uint) gdev_mem_bitmap_size(dev)); + dev->base = bits; + (*dev_proc(dev, open_device)) ((gx_device *) dev); /* initialize */ } /* Remove a character from the cache. */ void -gx_free_cached_char(gs_font_dir *dir, cached_char *cc) -{ char_cache_chunk *cck = cc->chunk; - - dir->ccache.chunks = cck; - dir->ccache.cnext = (byte *)cc - cck->data; - if ( cc_pair(cc) != 0 ) - { /* might be allocated but not added to table yet */ - cc_pair(cc)->num_chars--; - } - if_debug2('k', "[k]freeing char 0x%lx, pair=0x%lx\n", - (ulong)cc, (ulong)cc_pair(cc)); - gx_bits_cache_free((gx_bits_cache *)&dir->ccache, &cc->head, cck); +gx_free_cached_char(gs_font_dir * dir, cached_char * cc) +{ + char_cache_chunk *cck = cc->chunk; + + dir->ccache.chunks = cck; + dir->ccache.cnext = (byte *) cc - cck->data; + if (cc_pair(cc) != 0) { /* might be allocated but not added to table yet */ + cc_pair(cc)->num_chars--; + } + if_debug2('k', "[k]freeing char 0x%lx, pair=0x%lx\n", + (ulong) cc, (ulong) cc_pair(cc)); + gx_bits_cache_free((gx_bits_cache *) & dir->ccache, &cc->head, cck); } /* Add a character to the cache */ void -gx_add_cached_char(gs_font_dir *dir, gx_device_memory *dev, - cached_char *cc, cached_fm_pair *pair, const gs_log2_scale_point *pscale) -{ if_debug5('k', "[k]chaining char 0x%lx: pair=0x%lx, glyph=0x%lx, wmode=%d, depth=%d\n", - (ulong)cc, (ulong)pair, (ulong)cc->code, - cc->wmode, cc_depth(cc)); - if ( dev != NULL ) - { static const gs_log2_scale_point no_scale = { 0, 0 }; - /* Close the device, to flush the alpha buffer if any. */ - (*dev_proc(dev, close_device))((gx_device *)dev); - gx_add_char_bits(dir, cc, - (gs_device_is_abuf((gx_device *)dev) ? - &no_scale : pscale)); - } - /* Add the new character to the hash table. */ - { uint chi = chars_head_index(cc->code, pair); - while ( dir->ccache.table[chi &= dir->ccache.table_mask] != 0 ) - chi++; - dir->ccache.table[chi] = cc; - cc_set_pair(cc, pair); - pair->num_chars++; - } +gx_add_cached_char(gs_font_dir * dir, gx_device_memory * dev, +cached_char * cc, cached_fm_pair * pair, const gs_log2_scale_point * pscale) +{ + if_debug5('k', "[k]chaining char 0x%lx: pair=0x%lx, glyph=0x%lx, wmode=%d, depth=%d\n", + (ulong) cc, (ulong) pair, (ulong) cc->code, + cc->wmode, cc_depth(cc)); + if (dev != NULL) { + static const gs_log2_scale_point no_scale = + {0, 0}; + + /* Close the device, to flush the alpha buffer if any. */ + (*dev_proc(dev, close_device)) ((gx_device *) dev); + gx_add_char_bits(dir, cc, + (gs_device_is_abuf((gx_device *) dev) ? + &no_scale : pscale)); + } + /* Add the new character to the hash table. */ + { + uint chi = chars_head_index(cc->code, pair); + + while (dir->ccache.table[chi &= dir->ccache.table_mask] != 0) + chi++; + dir->ccache.table[chi] = cc; + cc_set_pair(cc, pair); + pair->num_chars++; + } } /* Adjust the bits of a newly-rendered character, by unscaling */ /* and compressing or converting to alpha values if necessary. */ void -gx_add_char_bits(gs_font_dir *dir, cached_char *cc, - const gs_log2_scale_point *plog2_scale) -{ int log2_x = plog2_scale->x, log2_y = plog2_scale->y; - uint raster = cc_raster(cc); - byte *bits = cc_bits(cc); - int depth = cc_depth(cc); - int log2_depth = depth >> 1; /* works for 1,2,4 */ - uint nwidth_bits, nraster; - gs_int_rect bbox; +gx_add_char_bits(gs_font_dir * dir, cached_char * cc, + const gs_log2_scale_point * plog2_scale) +{ + int log2_x = plog2_scale->x, log2_y = plog2_scale->y; + uint raster = cc_raster(cc); + byte *bits = cc_bits(cc); + int depth = cc_depth(cc); + int log2_depth = depth >> 1; /* works for 1,2,4 */ + uint nwidth_bits, nraster; + gs_int_rect bbox; #ifdef DEBUG - if ( cc->width % (1 << log2_x) != 0 || - cc->height % (1 << log2_y) != 0 - ) - { lprintf4("size %d,%d not multiple of scale %d,%d!\n", - cc->width, cc->height, - 1 << log2_x, 1 << log2_y); - cc->width &= -1 << log2_x; - cc->height &= -1 << log2_y; - } + if (cc->width % (1 << log2_x) != 0 || + cc->height % (1 << log2_y) != 0 + ) { + lprintf4("size %d,%d not multiple of scale %d,%d!\n", + cc->width, cc->height, + 1 << log2_x, 1 << log2_y); + cc->width &= -1 << log2_x; + cc->height &= -1 << log2_y; + } #endif + /* + * Compute the bounding box before compressing. + * We may have to scan more bits, but this is a lot faster than + * compressing the white space. Note that all bbox values are + * in bits, not pixels. + */ + + bits_bounding_box(bits, cc->height, raster, &bbox); + + /* + * If the character was oversampled, compress it now. + * In this case we know that log2_depth <= log2_x. + * If the character was not oversampled, or if we converted + * oversampling to alpha dynamically (using an alpha buffer + * intermediate device), log2_x and log2_y are both zero, + * but in the latter case we may still have depth > 1. + */ + + if ((log2_x | log2_y) != 0) { + if_debug5('k', "[k]compressing %dx%d by %dx%d to depth=%d\n", + cc->width, cc->height, 1 << log2_x, 1 << log2_y, + depth); + if (gs_debug_c('K')) + debug_dump_bitmap(bits, raster, cc->height, + "[K]uncompressed bits"); + /* Truncate/round the bbox to a multiple of the scale. */ + { + int scale_x = 1 << log2_x; + + bbox.p.x &= -scale_x; + bbox.q.x = (bbox.q.x + scale_x - 1) & -scale_x; + } + { + int scale_y = 1 << log2_y; + + bbox.p.y &= -scale_y; + bbox.q.y = (bbox.q.y + scale_y - 1) & -scale_y; + } + cc->width = (bbox.q.x - bbox.p.x) >> log2_x; + cc->height = (bbox.q.y - bbox.p.y) >> log2_y; + nwidth_bits = cc->width << log2_depth; + nraster = bitmap_raster(nwidth_bits); + bits_compress_scaled(bits + raster * bbox.p.y, bbox.p.x, + cc->width << log2_x, + cc->height << log2_y, + raster, + bits, nraster, plog2_scale, log2_depth); + bbox.p.x >>= log2_x; + bbox.p.y >>= log2_y; + } else { /* No oversampling, just remove white space. */ + const byte *from = bits + raster * bbox.p.y + (bbox.p.x >> 3); + + cc->height = bbox.q.y - bbox.p.y; /* - * Compute the bounding box before compressing. - * We may have to scan more bits, but this is a lot faster than - * compressing the white space. Note that all bbox values are - * in bits, not pixels. + * We'd like to trim off left and right blank space, + * but currently we're only willing to move bytes, not bits. + * (If we ever want to do better, we must remember that + * we can only trim whole pixels, and a pixel may occupy + * more than one bit.) */ + bbox.p.x &= ~7; /* adjust to byte boundary */ + bbox.p.x >>= log2_depth; /* bits => pixels */ + bbox.q.x = (bbox.q.x + depth - 1) >> log2_depth; /* ditto */ + cc->width = bbox.q.x - bbox.p.x; + nwidth_bits = cc->width << log2_depth; + nraster = bitmap_raster(nwidth_bits); + if (bbox.p.x != 0 || nraster != raster) { /* Move the bits down and over. */ + byte *to = bits; + uint n = cc->height; + + /* We'd like to move only + uint nbytes = (nwidth_bits + 7) >> 3; + * bytes per scan line, but unfortunately this drops + * the guaranteed zero padding at the end. + */ + + for (; n--; from += raster, to += nraster) + memmove(to, from, /*nbytes */ nraster); + } else if (bbox.p.y != 0) { /* Just move the bits down. */ + memmove(bits, from, raster * cc->height); + } + } - bits_bounding_box(bits, cc->height, raster, &bbox); + /* Adjust the offsets to account for removed white space. */ - /* - * If the character was oversampled, compress it now. - * In this case we know that log2_depth <= log2_x. - * If the character was not oversampled, or if we converted - * oversampling to alpha dynamically (using an alpha buffer - * intermediate device), log2_x and log2_y are both zero, - * but in the latter case we may still have depth > 1. - */ + cc->offset.x -= int2fixed(bbox.p.x); + cc->offset.y -= int2fixed(bbox.p.y); - if ( (log2_x | log2_y) != 0 ) - { if_debug5('k', "[k]compressing %dx%d by %dx%d to depth=%d\n", - cc->width, cc->height, 1 << log2_x, 1 << log2_y, - depth); - if ( gs_debug_c('K') ) - debug_dump_bitmap(bits, raster, cc->height, - "[K]uncompressed bits"); - /* Truncate/round the bbox to a multiple of the scale. */ - { int scale_x = 1 << log2_x; - bbox.p.x &= -scale_x; - bbox.q.x = (bbox.q.x + scale_x - 1) & -scale_x; - } - { int scale_y = 1 << log2_y; - bbox.p.y &= -scale_y; - bbox.q.y = (bbox.q.y + scale_y - 1) & -scale_y; - } - cc->width = (bbox.q.x - bbox.p.x) >> log2_x; - cc->height = (bbox.q.y - bbox.p.y) >> log2_y; - nwidth_bits = cc->width << log2_depth; - nraster = bitmap_raster(nwidth_bits); - bits_compress_scaled(bits + raster * bbox.p.y, bbox.p.x, - cc->width << log2_x, - cc->height << log2_y, - raster, - bits, nraster, plog2_scale, log2_depth); - bbox.p.x >>= log2_x; - bbox.p.y >>= log2_y; - } - else - { /* No oversampling, just remove white space. */ - const byte *from = bits + raster * bbox.p.y + (bbox.p.x >> 3); - - cc->height = bbox.q.y - bbox.p.y; - /* - * We'd like to trim off left and right blank space, - * but currently we're only willing to move bytes, not bits. - * (If we ever want to do better, we must remember that - * we can only trim whole pixels, and a pixel may occupy - * more than one bit.) - */ - bbox.p.x &= ~7; /* adjust to byte boundary */ - bbox.p.x >>= log2_depth; /* bits => pixels */ - bbox.q.x = (bbox.q.x + depth - 1) >> log2_depth; /* ditto */ - cc->width = bbox.q.x - bbox.p.x; - nwidth_bits = cc->width << log2_depth; - nraster = bitmap_raster(nwidth_bits); - if ( bbox.p.x != 0 || nraster != raster ) - { /* Move the bits down and over. */ - byte *to = bits; - uint n = cc->height; - /* We'd like to move only - uint nbytes = (nwidth_bits + 7) >> 3; - * bytes per scan line, but unfortunately this drops - * the guaranteed zero padding at the end. - */ - - for ( ; n--; from += raster, to += nraster ) - memmove(to, from, /*nbytes*/nraster); - } - else if ( bbox.p.y != 0 ) - { /* Just move the bits down. */ - memmove(bits, from, raster * cc->height); - } - } - - /* Adjust the offsets to account for removed white space. */ - - cc->offset.x -= int2fixed(bbox.p.x); - cc->offset.y -= int2fixed(bbox.p.y); - - /* Discard the memory device overhead that follows the bits, */ - /* and any space reclaimed from unscaling or compression. */ - - cc_set_raster(cc, nraster); - { uint diff = round_down(cc->head.size - sizeof_cached_char - - nraster * cc->height, - align_cached_char_mod); - - if ( diff >= sizeof(cached_char_head) ) - { shorten_cached_char(dir, cc, diff); - if_debug2('K', "[K]shortening char 0x%lx by %u (adding)\n", - (ulong)cc, diff); - } + /* Discard the memory device overhead that follows the bits, */ + /* and any space reclaimed from unscaling or compression. */ + + cc_set_raster(cc, nraster); + { + uint diff = round_down(cc->head.size - sizeof_cached_char - + nraster * cc->height, + align_cached_char_mod); + + if (diff >= sizeof(cached_char_head)) { + shorten_cached_char(dir, cc, diff); + if_debug2('K', "[K]shortening char 0x%lx by %u (adding)\n", + (ulong) cc, diff); } + } - /* Assign a bitmap id. */ + /* Assign a bitmap id. */ - cc->id = gs_next_ids(1); + cc->id = gs_next_ids(1); } /* Purge from the caches all references to a given font. */ void -gs_purge_font_from_char_caches(gs_font_dir *dir, const gs_font *font) -{ cached_fm_pair *pair = dir->fmcache.mdata; - int count = dir->fmcache.mmax; - - if_debug1('k', "[k]purging font 0x%lx\n", - (ulong)font); - while ( count-- ) - { if ( pair->font == font ) - { if ( uid_is_valid(&pair->UID) ) - { /* Keep the entry. */ - pair->font = 0; - } - else - gs_purge_fm_pair(dir, pair, 0); - } - pair++; +gs_purge_font_from_char_caches(gs_font_dir * dir, const gs_font * font) +{ + cached_fm_pair *pair = dir->fmcache.mdata; + int count = dir->fmcache.mmax; + + if_debug1('k', "[k]purging font 0x%lx\n", + (ulong) font); + while (count--) { + if (pair->font == font) { + if (uid_is_valid(&pair->UID)) { /* Keep the entry. */ + pair->font = 0; + } else + gs_purge_fm_pair(dir, pair, 0); } + pair++; + } } /* ------ Internal routines ------ */ /* Allocate data space for a cached character, adding a new chunk if needed. */ private cached_char * -alloc_char(gs_font_dir *dir, ulong icdsize) -{ /* Try allocating at the current position first. */ - cached_char *cc = alloc_char_in_chunk(dir, icdsize); - - if ( cc == 0 ) - { if ( dir->ccache.bspace < dir->ccache.bmax ) - { /* Allocate another chunk. */ - char_cache_chunk *cck_prev = dir->ccache.chunks; - char_cache_chunk *cck; - uint cksize = dir->ccache.bmax / 5 + 1; - uint tsize = dir->ccache.bmax - dir->ccache.bspace; - byte *cdata; - - if ( cksize > tsize ) - cksize = tsize; - if ( icdsize + sizeof(cached_char_head) > cksize ) - { if_debug2('k', "[k]no cache bits: cdsize+head=%lu, cksize=%u\n", - icdsize + sizeof(cached_char_head), - cksize); - return 0; /* wouldn't fit */ - } - cck = (char_cache_chunk *)gs_malloc(1, sizeof(*cck), - "char cache chunk"); - if ( cck == 0 ) - return 0; - cdata = (byte *)gs_malloc(cksize, 1, - "char cache chunk"); - if ( cdata == 0 ) - { gs_free((char *)cck, 1, sizeof(*cck), - "char cache chunk"); - return 0; - } - gx_bits_cache_chunk_init(cck, cdata, cksize); - cck->next = cck_prev->next; - cck_prev->next = cck; - dir->ccache.bspace += cksize; - dir->ccache.chunks = cck; - } - else - { /* Cycle through existing chunks. */ - char_cache_chunk *cck_init = dir->ccache.chunks; - char_cache_chunk *cck = cck_init; - while ( (dir->ccache.chunks = cck = cck->next) != cck_init ) - { dir->ccache.cnext = 0; - cc = alloc_char_in_chunk(dir, icdsize); - if ( cc != 0 ) - return cc; - } - } +alloc_char(gs_font_dir * dir, ulong icdsize) +{ /* Try allocating at the current position first. */ + cached_char *cc = alloc_char_in_chunk(dir, icdsize); + + if (cc == 0) { + if (dir->ccache.bspace < dir->ccache.bmax) { /* Allocate another chunk. */ + char_cache_chunk *cck_prev = dir->ccache.chunks; + char_cache_chunk *cck; + uint cksize = dir->ccache.bmax / 5 + 1; + uint tsize = dir->ccache.bmax - dir->ccache.bspace; + byte *cdata; + + if (cksize > tsize) + cksize = tsize; + if (icdsize + sizeof(cached_char_head) > cksize) { + if_debug2('k', "[k]no cache bits: cdsize+head=%lu, cksize=%u\n", + icdsize + sizeof(cached_char_head), + cksize); + return 0; /* wouldn't fit */ + } + cck = (char_cache_chunk *) gs_malloc(1, sizeof(*cck), + "char cache chunk"); + if (cck == 0) + return 0; + cdata = (byte *) gs_malloc(cksize, 1, + "char cache chunk"); + if (cdata == 0) { + gs_free((char *)cck, 1, sizeof(*cck), + "char cache chunk"); + return 0; + } + gx_bits_cache_chunk_init(cck, cdata, cksize); + cck->next = cck_prev->next; + cck_prev->next = cck; + dir->ccache.bspace += cksize; + dir->ccache.chunks = cck; + } else { /* Cycle through existing chunks. */ + char_cache_chunk *cck_init = dir->ccache.chunks; + char_cache_chunk *cck = cck_init; + + while ((dir->ccache.chunks = cck = cck->next) != cck_init) { dir->ccache.cnext = 0; cc = alloc_char_in_chunk(dir, icdsize); + if (cc != 0) + return cc; + } } - return cc; + dir->ccache.cnext = 0; + cc = alloc_char_in_chunk(dir, icdsize); + } + return cc; } /* Allocate a character in the current chunk. */ private cached_char * -alloc_char_in_chunk(gs_font_dir *dir, ulong icdsize) -{ char_cache_chunk *cck = dir->ccache.chunks; - cached_char_head *cch; +alloc_char_in_chunk(gs_font_dir * dir, ulong icdsize) +{ + char_cache_chunk *cck = dir->ccache.chunks; + cached_char_head *cch; + #define cc ((cached_char *)cch) - while ( gx_bits_cache_alloc((gx_bits_cache *)&dir->ccache, - icdsize, &cch) < 0 - ) - { if ( cch == 0 ) - { /* Not enough room to allocate in this chunk. */ - return 0; - } - { /* Free the character */ - cached_fm_pair *pair = cc_pair(cc); - - if ( pair != 0 ) - { uint chi = chars_head_index(cc->code, pair); - while ( dir->ccache.table[chi & dir->ccache.table_mask] != cc ) - chi++; - hash_remove_cached_char(dir, chi); - } - gx_free_cached_char(dir, cc); - } + while (gx_bits_cache_alloc((gx_bits_cache *) & dir->ccache, + icdsize, &cch) < 0 + ) { + if (cch == 0) { /* Not enough room to allocate in this chunk. */ + return 0; + } { /* Free the character */ + cached_fm_pair *pair = cc_pair(cc); + + if (pair != 0) { + uint chi = chars_head_index(cc->code, pair); + + while (dir->ccache.table[chi & dir->ccache.table_mask] != cc) + chi++; + hash_remove_cached_char(dir, chi); + } + gx_free_cached_char(dir, cc); } - cc->chunk = cck; - cc->loc = (byte *)cc - cck->data; - return cc; + } + cc->chunk = cck; + cc->loc = (byte *) cc - cck->data; + return cc; #undef cc } /* Remove the cached_char at a given index in the hash table. */ /* In order not to slow down lookup, we relocate following entries. */ private void -hash_remove_cached_char(gs_font_dir *dir, uint chi) -{ uint mask = dir->ccache.table_mask; - uint from = ((chi &= mask) + 1) & mask; - cached_char *cc; - - dir->ccache.table[chi] = 0; - while ( (cc = dir->ccache.table[from]) != 0 ) - { /* Loop invariants: chars[chi] == 0; */ - /* chars[chi+1..from] != 0. */ - uint fchi = chars_head_index(cc->code, cc_pair(cc)); - - /* If chi <= fchi < from, we relocate the character. */ - /* Note that '<=' must take wraparound into account. */ - if ( (chi < from ? chi <= fchi && fchi < from : - chi <= fchi || fchi < from) - ) - { dir->ccache.table[chi] = cc; - dir->ccache.table[from] = 0; - chi = from; - } - from = (from + 1) & mask; - } +hash_remove_cached_char(gs_font_dir * dir, uint chi) +{ + uint mask = dir->ccache.table_mask; + uint from = ((chi &= mask) + 1) & mask; + cached_char *cc; + + dir->ccache.table[chi] = 0; + while ((cc = dir->ccache.table[from]) != 0) { /* Loop invariants: chars[chi] == 0; */ + /* chars[chi+1..from] != 0. */ + uint fchi = chars_head_index(cc->code, cc_pair(cc)); + + /* If chi <= fchi < from, we relocate the character. */ + /* Note that '<=' must take wraparound into account. */ + if ((chi < from ? chi <= fchi && fchi < from : + chi <= fchi || fchi < from) + ) { + dir->ccache.table[chi] = cc; + dir->ccache.table[from] = 0; + chi = from; + } + from = (from + 1) & mask; + } } /* Shorten a cached character. */ /* diff >= sizeof(cached_char_head). */ private void -shorten_cached_char(gs_font_dir *dir, cached_char *cc, uint diff) -{ gx_bits_cache_shorten((gx_bits_cache *)&dir->ccache, &cc->head, - diff, cc->chunk); - if_debug2('K', "[K]shortening creates free block 0x%lx(%u)\n", - (ulong)((byte *)cc + cc->head.size), diff); +shorten_cached_char(gs_font_dir * dir, cached_char * cc, uint diff) +{ + gx_bits_cache_shorten((gx_bits_cache *) & dir->ccache, &cc->head, + diff, cc->chunk); + if_debug2('K', "[K]shortening creates free block 0x%lx(%u)\n", + (ulong) ((byte *) cc + cc->head.size), diff); } |