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

📄 devfont.caching.c

📁 开放源码实时操作系统源码.
💻 C
📖 第 1 页 / 共 5 页
字号:
Get_Glyph_Width(PMWFREETYPEFONT pf, TT_UShort glyph_index)
{
	TT_Glyph_Metrics metrics;

    	if (TT_Load_Glyph ( pf->instance, pf->glyph,
		TT_Char_Index (pf->char_map,glyph_index),
		TTLOAD_SCALE_GLYPH|TTLOAD_HINT_GLYPH) != TT_Err_Ok)
    	{
		/* Try to load default glyph: index 0 */
		if (TT_Load_Glyph ( pf->instance, pf->glyph, 0,
			TTLOAD_SCALE_GLYPH|TTLOAD_HINT_GLYPH) != TT_Err_Ok)
		    return 0;
	}

	TT_Get_Glyph_Metrics (pf->glyph, &metrics);
	return((metrics.advance & 0xFFFFFFC0) >> 6);
}

static MWFREETYPEFONTCACHE *
find_cache_glyph ( PMWFREETYPEFONT pf, unsigned curchar )
{
  MWFREETYPEFONTCACHE ** inode = &pf->glyph_cache;

  while (1)
    {
      if (*inode == 0)
	{
	  *inode = calloc(sizeof(MWFREETYPEFONTCACHE),1);
	  (*inode)->curchar = curchar;
	}

      if (curchar < (*inode)->curchar)
	inode = &(*inode)->l;
      else if (curchar > (*inode)->curchar)
	inode = &(*inode)->r;
      else
	return *inode;
    }
}

static void
free_cache_glyph ( MWFREETYPEFONTCACHE * node )
{
  if (node->l != 0)
    free_cache_glyph(node->l);

  if (node->r != 0)
    free_cache_glyph(node->r);

  free(node);
}

/* Render a single glyph*/
static void
drawchar(PMWFREETYPEFONT pf, PSD psd, unsigned curchar, int x_offset,
	int y_offset)
{
	TT_F26Dot6 	xmin, ymin, xmax, ymax, x, y, z;
	unsigned char 	*src, *srcptr;
	MWPIXELVAL 	*dst, *dstptr;
	MWPIXELVAL 	*bitmap;
	int 		size, width, height;
	TT_Outline 	outline;
	TT_BBox 	bbox;
	TT_Raster_Map 	Raster;
	TT_Error 	error;
	/*MWPIXELVAL 	save;*/
        MWFREETYPEFONTCACHE * cache;

	/* we begin by grid-fitting the bounding box */
	TT_Get_Glyph_Outline (pf->glyph, &outline);
	TT_Get_Outline_BBox (&outline, &bbox);

	xmin = (bbox.xMin & -64) >> 6;
	ymin = (bbox.yMin & -64) >> 6;
	xmax = ((bbox.xMax + 63) & -64) >> 6;
	ymax = ((bbox.yMax + 63) & -64) >> 6;
	width = xmax - xmin;
	height = ymax - ymin;
	size = width * height;

	/* now re-allocate the raster bitmap */
	Raster.rows = height;
	Raster.width = width;

	if (pf->fontattr&MWTF_ANTIALIAS)
		Raster.cols = (Raster.width + 3) & -4;	/* pad to 32-bits */
	else
		Raster.cols = (Raster.width + 7) & -8;	/* pad to 64-bits ??? */

        cache = find_cache_glyph(pf,curchar);
        /* SDR: if cache is 0 here, something really really bad happened */

	Raster.flow = TT_Flow_Up;
	Raster.size = Raster.rows * Raster.cols;
	Raster.bitmap = cache->buffer;

	if (Raster.bitmap == 0)
	  {
	    Raster.bitmap = malloc (Raster.size);

	    memset (Raster.bitmap, 0, Raster.size);

	    /* now render the glyph in the small pixmap */

	    /* IMPORTANT NOTE: the offset parameters passed to the function     */
	    /* TT_Get_Glyph_Bitmap() must be integer pixel values, i.e.,        */
	    /* multiples of 64.  HINTING WILL BE RUINED IF THIS ISN'T THE CASE! */
	    /* This is why we _did_ grid-fit the bounding box, especially xmin  */
	    /* and ymin.                                                        */

	    if (!(pf->fontattr&MWTF_ANTIALIAS))
	      error = TT_Get_Glyph_Bitmap (pf->glyph, &Raster,
					   -xmin * 64, -ymin * 64);
	    else
	      error = TT_Get_Glyph_Pixmap (pf->glyph, &Raster,
					   -xmin * 64, -ymin * 64);

	    if (error) {
	      free (Raster.bitmap);
	      return;
	    }

            cache->buffer = Raster.bitmap;
	  }

#if MWFREETYPEFONT_CACHEBITMAP
	if ((memcmp(&gr_foreground,&cache->fg,sizeof(gr_foreground)) != 0) || 
	    (memcmp(&gr_background,&cache->bg,sizeof(gr_background)) != 0) || 
	    (gr_usebg != cache->usebg))
	  {
	    if (cache->bitmap)
	      {
		free(cache->bitmap);
		cache->bitmap = 0;
	      }
	  }

	bitmap = cache->bitmap;
#else
	bitmap = 0;
#endif

	if (bitmap == 0)
	  {
	    bitmap = malloc (size * sizeof (MWPIXELVAL));
	    memset (bitmap, 0, size * sizeof (MWPIXELVAL));

	    src = (char *) Raster.bitmap;
	    dst = bitmap + (size - width);

	    for (y = ymin; y < ymax; y++) 
	      {
		srcptr = src;
		dstptr = dst;

		for (x = xmin; x < xmax; x++) 
		  {
		    if (pf->fontattr&MWTF_ANTIALIAS)
		      *dstptr++ = gray_palette[(int) *srcptr];
		    else
		      {
		        for ( z=0;
			      z <= ((xmax-x-1) < 7 ? (xmax-x-1) : 7);
			      z++ )
			    *dstptr++ = ((*srcptr << z) & 0x80) ? gr_foreground : gr_background;
			x += 7;
		      }

		    srcptr++;
		  }

		src += Raster.cols;
		dst -= width;
	      }
#if MWFREETYPEFONT_CACHEBITMAP
	    cache->fg = gr_foreground;
	    cache->bg = gr_background;
	    cache->usebg = gr_usebg;
	    cache->bitmap = bitmap;
#endif
	  }

	/* Now draw the bitmap ... */
	GdArea(psd, x_offset + xmin, y_offset - (ymin + height), width, height,
		bitmap, MWPF_PIXELVAL);

#if !MWFREETYPEFONT_CACHEBITMAP
	free(bitmap);
#endif
}

/*
 * Draw unicode 16 text string using FREETYPE type font
 */
static void
freetype_drawtext(PMWFONT pfont, PSD psd, MWCOORD ax, MWCOORD ay,
	const void *text, int cc, int flags)
{
	PMWFREETYPEFONT	pf = (PMWFREETYPEFONT)pfont;
	const unsigned short *	str = text;
	TT_F26Dot6 	x = ax, y = ay;
	TT_Pos 		vec_x, vec_y;
	int 		i;
	TT_F26Dot6	startx, starty;
	TT_Outline 	outline;
	TT_UShort 	curchar;
	TT_Glyph_Metrics metrics;
	TT_Face_Properties properties;
	TT_Instance_Metrics imetrics;
	TT_F26Dot6 ascent, descent;
	static unsigned char blend[5] = { 0x00, 0x44, 0x88, 0xcc, 0xff };
	static unsigned char virtual_palette[5] = { 0, 1, 2, 3, 4 };

	pf->last_glyph_code = -1;		/* reset kerning*/
	pf->last_pen_pos = -32767;

	/* 
	 * Compute instance ascent & descent values
	 * in fractional units (1/64th pixel)
	 */
	TT_Get_Face_Properties (pf->face, &properties);
	TT_Get_Instance_Metrics(pf->instance, &imetrics);	
  
	ascent = ((properties.horizontal->Ascender * imetrics.y_scale)/0x10000);
	descent = ((properties.horizontal->Descender*imetrics.y_scale)/0x10000);

	/* 
	 * Offset the starting point if necessary,
	 * FreeType always aligns at baseline
	 */
	if (flags&MWTF_BOTTOM) {
		vec_x = 0;
		vec_y = descent;
		TT_Transform_Vector(&vec_x, &vec_y,&pf->matrix);
		x -= vec_x / 64;
		y += vec_y / 64;
	} else if (flags&MWTF_TOP) {
		vec_x = 0;
		vec_y = ascent;
		TT_Transform_Vector(&vec_x, &vec_y,&pf->matrix);
		x -= vec_x / 64;
		y += vec_y / 64;
	}

	/* Set the "graylevels" */
	if (pf->fontattr&MWTF_ANTIALIAS) {
		TT_Set_Raster_Gray_Palette (engine, virtual_palette);

		alphablend(psd, gray_palette, gr_foreground, gr_background,
			blend, 5);
	}

	startx = x;
	starty = y;
	for (i = 0; i < cc; i++) {
		curchar = TT_Char_Index (pf->char_map, str[i]);

		if (TT_Load_Glyph (pf->instance, pf->glyph, curchar,
			TTLOAD_DEFAULT) != TT_Err_Ok)
				continue;

		if (pf->fontrotation) {
			TT_Get_Glyph_Outline (pf->glyph, &outline);
			TT_Transform_Outline (&outline, &pf->matrix);
		}

		TT_Get_Glyph_Metrics (pf->glyph, &metrics);

		if ((pf->fontattr&MWTF_KERNING) && pf->can_kern) {
			if (pf->fontrotation) {
				vec_x = compute_kernval(pf, curchar);
				vec_y = 0;
				TT_Transform_Vector(&vec_x, &vec_y,&pf->matrix);

				x += vec_x / 64;
				y -= vec_y / 64;
			} else
				x += compute_kernval(pf, curchar) / 64;
		}
			
		drawchar(pf, psd, curchar, x, y);

		if (pf->fontrotation) {
			vec_x = metrics.advance;
			vec_y = 0;
			TT_Transform_Vector (&vec_x, &vec_y, &pf->matrix);

			x += vec_x / 64;
			y -= vec_y / 64;
		} else {
			x += metrics.advance / 64;

			/* Kerning point syndrome avoidance */
			if (pf->last_pen_pos > x)
				x = pf->last_pen_pos;
			pf->last_pen_pos = x;
		}

		pf->last_glyph_code = curchar;
	}

	if (pf->fontattr & MWTF_UNDERLINE)
		GdLine(psd, startx, starty, x, y, FALSE);
}

/*
 * Return information about a specified font.
 */
static MWBOOL
freetype_getfontinfo(PMWFONT pfont, PMWFONTINFO pfontinfo)
{
	int	i;
	PMWFREETYPEFONT	pf = (PMWFREETYPEFONT)pfont;
	TT_Face_Properties 	properties;
	TT_Instance_Metrics imetrics;
	TT_UShort last_glyph_index;

	TT_Get_Face_Properties (pf->face, &properties);
	TT_Get_Instance_Metrics(pf->instance, &imetrics);

	/* Fill up the fields */
	pfontinfo->height = (((properties.horizontal->Ascender * \
	                        imetrics.y_scale)/ 0x10000) >> 6) -
	                    (((properties.horizontal->Descender * \
	                        imetrics.y_scale)/ 0x10000) >> 6);
	pfontinfo->maxwidth = ((properties.horizontal->xMax_Extent * \
	                        imetrics.x_scale)/ 0x10000) >> 6;
	pfontinfo->baseline = ((properties.horizontal->Ascender * \
	                        imetrics.y_scale)/ 0x10000) >> 6;
	pfontinfo->firstchar = TT_CharMap_First(pf->char_map, NULL);
	pfontinfo->lastchar = TT_CharMap_Last(pf->char_map, NULL);
	pfontinfo->fixed = properties.postscript->isFixedPitch;
		
	last_glyph_index = properties.num_Glyphs > 255 ? 255: properties.num_Glyphs-1;

	/* Doesn't work ... don't know why ....*/
#if 0
	if (TT_Get_Face_Widths( pf->face, 0,
				last_glyph_index, widths, NULL ) != TT_Err_Ok) {
	  return TRUE;
	}

	for(i=0; i<=last_glyph_index; i++)
	  DPRINTF("widths[%d]: %d\n", i, widths[i]);
#endif

	/* Get glyphs widths */
	for(i=0; i<=last_glyph_index; i++)
	  pfontinfo->widths[i] = Get_Glyph_Width(pf, i);

#if 0
	DPRINTF("x_ppem: %d\ny_ppem: %d\nx_scale: %d\ny_scale: %d\n\
    x_resolution: %d\ny_resolution: %d\n",
    imetrics.x_ppem, imetrics.y_ppem, imetrics.x_scale, \
    imetrics.y_scale, imetrics.x_resolution, imetrics.y_resolution);

    DPRINTF("Ascender: %d\nDescender: %d\nxMax_Extent: %d\n\
    Mac Style Say Italic?: %d\nMac Style Say Bold?: %d\n\
    sTypoAscender: %d\nsTypoDescender: %d\nusWinAscent: %d\n\
    usWinDescent: %d\nusFirstCharIndex: %d\nusLastCharIndex: %d\n\
    OS2 Say Italic?: %d\nOS2 Say Bold?: %d\nOS2 Say monospaced?: %d\n\
    Postscript Say monospaced?: %d\n",\
    properties.horizontal->Ascender,
    properties.horizontal->Descender,
    properties.horizontal->xMax_Extent,
    (properties.header->Mac_Style & 0x2)?1:0,
    (properties.header->Mac_Style & 0x1)?1:0,
    properties.os2->sTypoAscender,
    properties.os2->sTypoDescender,
    properties.os2->usWinAscent,
    properties.os2->usWinDescent,
    properties.os2->usFirstCharIndex,
    properties.os2->usLastCharIndex,
    (properties.os2->fsSelection & 0x1)?1:0,
    (properties.os2->fsSelection & 0x20)?1:0,
    properties.postscript->isFixedPitch,
    (properties.os2->panose[3] == 9)?1:0);
#endif	
			
	return TRUE;
}

static void
freetype_gettextsize(PMWFONT pfont, const void *text, int cc,
	MWCOORD *pwidth, MWCOORD *pheight, MWCOORD *pbase)
{
	PMWFREETYPEFONT	pf = (PMWFREETYPEFONT)pfont;
	const unsigned short *	str = text;
	TT_F26Dot6 	x = 0;
	int 		i;
	TT_UShort 	curchar;
	TT_Glyph_Metrics metrics;
	TT_Face_Properties 	properties;
	TT_Instance_Metrics imetrics;

	TT_Get_Face_Properties (pf->face, &properties);
	TT_Get_Instance_Metrics(pf->instance, &imetrics);
	
	pf->last_glyph_code = -1;		/* reset kerning*/
	pf->last_pen_pos = -32767;
	
	for (i = 0; i < cc; i++) {
		curchar = TT_Char_Index (pf->char_map, str[i]);

		if (TT_Load_Glyph (pf->instance, pf->glyph, curchar,
			TTLOAD_SCALE_GLYPH|TTLOAD_HINT_GLYPH) != TT_Err_Ok)
				continue;

		TT_Get_Glyph_Metrics (pf->glyph, &metrics);

		if ((pf->fontattr&MWTF_KERNING) && pf->can_kern) {
				x += compute_kernval(pf, curchar) / 64;
		}
		
		x += metrics.advance / 64;

		/* Kerning point syndrome avoidance */
		if (pf->last_pen_pos > x)
			x = pf->last_pen_pos;
		pf->last_pen_pos = x;

		pf->last_glyph_code = curchar;
	}

	*pwidth = x;
	*pheight =  (((properties.horizontal->Ascender * 
	                imetrics.y_scale)/ 0x10000) >> 6) -
	            (((properties.horizontal->Descender * 
	            imetrics.y_scale)/ 0x10000) >> 6);
    	/* FIXME: is it what's required ?? */
	*pbase = (((-properties.horizontal->Descender) * 
	            imetrics.y_scale)/ 0x10000) >> 6;
}

static void
freetype_destroyfont(PMWFONT pfont)
{
	PMWFREETYPEFONT	pf = (PMWFREETYPEFONT)pfont;

	TT_Close_Face(pf->face);

	/*----------*/

	if (pf->glyph_cache != 0)
	  free_cache_glyph(pf->glyph_cache);

	/*----------*/

	free(pf);
}

static void
freetype_setfontsize(PMWFONT pfont, MWCOORD fontsize)
{
	PMWFREETYPEFONT	pf = (PMWFREETYPEFONT)pfont;
	
	pf->fontsize = fontsize;
	
	/* We want real pixel sizes ... not points ...*/
	TT_Set_Instance_PixelSizes( pf->instance, pf->fontsize,
                                pf->fontsize, pf->fontsize * 64 );
#if 0
	/* set charsize (convert to points for freetype)*/
	TT_Set_Instance_CharSize (pf->instance,
		((pf->fontsize * 72 + 96/2) / 96) * 64);
#endif
}

static void
freetype_setfontrotation(PMWFONT pfont, int tenthdegrees)
{
	PMWFREETYPEFONT	pf = (PMWFREETYPEFONT)pfont;
	float 		angle;
	
	pf->fontrotation = tenthdegrees;

	/* Build the rotation matrix with the given angle */
	TT_Set_Instance_Transform_Flags (pf->instance, TRUE, FALSE);

	angle = pf->fontrotation * M_PI / 1800;
	pf->matrix.yy = (TT_Fixed) (cos (angle) * (1 << 16));
	pf->matrix.yx = (TT_Fixed) (sin (angle) * (1 << 16));
	pf->matrix.xx = pf->matrix.yy;
	pf->matrix.xy = -pf->matrix.yx;
}

#endif /* HAVE_FREETYPE_SUPPORT*/

/* UTF-8 to UTF-16 conversion.  Surrogates are handeled properly, e.g.
 * a single 4-byte UTF-8 character is encoded into a surrogate pair.
 * On the other hand, if the UTF-8 string contains surrogate values, this
 * is considered an error and returned as such.
 *
 * The destination array must be able to hold as many Unicode-16 characters
 * as there are ASCII characters in the UTF-8 string.  This in case all UTF-8
 * characters are ASCII characters.  No more will be needed.
 *
 * Copyright (c) 2000 Morten Rolland, Screen Media
 */
static int
utf8_to_utf16(const unsigned char *utf8, int cc, unsigned short *unicode16)
{
	int count = 0;
	unsigned char c0, c1;
	unsigned long scalar;

	while(--cc >= 0) {
		c0 = *utf8++;
		/*DPRINTF("Trying: %02x\n",c0);*/

		if ( c0 < 0x80 ) {
			/* Plain ASCII character, simple translation :-) */

⌨️ 快捷键说明

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