⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pango-coverage.c

📁 GTK+-2.0源码之pango-1.15.6.tar.gz
💻 C
字号:
/* 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 <config.h>#include <string.h>#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;  int data_size;  PangoBlockInfo *blocks;};/** * pango_coverage_new: * * Create a new #PangoCoverage * * Return value: the newly allocated #PangoCoverage, *               initialized to %PANGO_COVERAGE_NONE *               with a reference count of one, which *               should be freed with pango_coverage_unref(). **/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;}/** * pango_coverage_copy: * @coverage: a #PangoCoverage * * Copy an existing #PangoCoverage. (This function may now be unnecessary * since we refcount the structure. File a bug if you use it.) * * Return value: the newly allocated #PangoCoverage, *               with a reference count of one, which *               should be freed with pango_coverage_unref(). **/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;}/** * pango_coverage_ref: * @coverage: a #PangoCoverage * * Increase the reference count on the #PangoCoverage by one * * Return value: @coverage **/PangoCoverage *pango_coverage_ref (PangoCoverage *coverage){  g_return_val_if_fail (coverage != NULL, NULL);  coverage->ref_count++;  return coverage;}/** * pango_coverage_unref: * @coverage: a #PangoCoverage * * Increase the reference count on the #PangoCoverage by one. * if the result is zero, free the coverage and all associated memory. **/voidpango_coverage_unref (PangoCoverage *coverage){  int i;  g_return_if_fail (coverage != NULL);  g_return_if_fail (coverage->ref_count > 0);  coverage->ref_count--;  if (coverage->ref_count == 0)    {      for (i=0; i<coverage->n_blocks; i++)	g_free (coverage->blocks[i].data);      g_free (coverage->blocks);      g_slice_free (PangoCoverage, coverage);    }}/** * pango_coverage_get: * @coverage: a #PangoCoverage * @index_: the index to check * * Determine whether a particular index is covered by @coverage * * Return value: the coverage level of @coverage for character @index_. **/PangoCoverageLevelpango_coverage_get (PangoCoverage *coverage,		    int            index){  int block_index;  g_return_val_if_fail (coverage != NULL, PANGO_COVERAGE_NONE);  g_return_val_if_fail (index >= 0, 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 **/voidpango_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 (level >= 0 && 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_new (guchar, 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_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. **/voidpango_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 * @bytes: location to store result (must be freed with g_free()) * @n_bytes: location to store size of result * * Convert a #PangoCoverage structure into a flat binary format **/voidpango_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];	  for (j = 1 ; j < 64; j++)	    if (data[j] != first_val)	      break;	  if (j == 64)	    {	      g_free (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 guint32pango_coverage_get_uint32 (guchar **ptr){  guint32 val;  memcpy (&val, *ptr, 4);  *ptr += 4;  return g_ntohl (val);}/** * pango_coverage_from_bytes: * @bytes: binary data representing a #PangoCoverage * @n_bytes: the size of @bytes in bytes * * Convert data generated from pango_converage_to_bytes() back * to a #PangoCoverage * * Return value: a newly allocated #PangoCoverage, or %NULL if *               the data was invalid. **/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;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -