GlyphBLF *blf_glyph_add(FontBLF *font, unsigned int index, unsigned int c)
{
	FT_GlyphSlot slot;
	GlyphBLF *g;
	FT_Error err;
	FT_Bitmap bitmap, tempbitmap;
	const bool is_sharp = (U.text_render & USER_TEXT_DISABLE_AA) != 0;
	int flags = FT_LOAD_TARGET_NORMAL | FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP;
	FT_BBox bbox;
	unsigned int key;

	g = blf_glyph_search(font->glyph_cache, c);
	if (g)
		return g;

	/* glyphs are dynamically created as needed by font rendering. this means that
	 * to make font rendering thread safe we have to do locking here. note that this
	 * must be a lock for the whole library and not just per font, because the font
	 * renderer uses a shared buffer internally */
	BLI_spin_lock(font->ft_lib_mutex);

	/* search again after locking */
	g = blf_glyph_search(font->glyph_cache, c);
	if (g) {
		BLI_spin_unlock(font->ft_lib_mutex);
		return g;
	}

	if (font->flags & BLF_HINTING)
		flags &= ~FT_LOAD_NO_HINTING;
	
	if (is_sharp)
		err = FT_Load_Glyph(font->face, (FT_UInt)index, FT_LOAD_TARGET_MONO);
	else
		err = FT_Load_Glyph(font->face, (FT_UInt)index, flags);  

	if (err) {
		BLI_spin_unlock(font->ft_lib_mutex);
		return NULL;
	}

	/* get the glyph. */
	slot = font->face->glyph;

	if (is_sharp) {
		err = FT_Render_Glyph(slot, FT_RENDER_MODE_MONO);

		/* Convert result from 1 bit per pixel to 8 bit per pixel */
		/* Accum errors for later, fine if not interested beyond "ok vs any error" */
		FT_Bitmap_New(&tempbitmap);
		err += FT_Bitmap_Convert(font->ft_lib, &slot->bitmap, &tempbitmap, 1); /* Does Blender use Pitch 1 always? It works so far */
		err += FT_Bitmap_Copy(font->ft_lib, &tempbitmap, &slot->bitmap);
		err += FT_Bitmap_Done(font->ft_lib, &tempbitmap);
	}
	else {
		err = FT_Render_Glyph(slot, FT_RENDER_MODE_NORMAL);
	}

	if (err || slot->format != FT_GLYPH_FORMAT_BITMAP) {
		BLI_spin_unlock(font->ft_lib_mutex);
		return NULL;
	}

	g = (GlyphBLF *)MEM_callocN(sizeof(GlyphBLF), "blf_glyph_add");
	g->c = c;
	g->idx = (FT_UInt)index;
	g->xoff = -1;
	g->yoff = -1;
	bitmap = slot->bitmap;
	g->width = (int)bitmap.width;
	g->height = (int)bitmap.rows;

	if (g->width && g->height) {
		if (is_sharp) {
			/* Font buffer uses only 0 or 1 values, Blender expects full 0..255 range */
			int i;
			for (i = 0; i < (g->width * g->height); i++) {
				bitmap.buffer[i] = bitmap.buffer[i] ? 255 : 0;
			}
		}

		g->bitmap = (unsigned char *)MEM_mallocN((size_t)(g->width * g->height), "glyph bitmap");
		memcpy((void *)g->bitmap, (void *)bitmap.buffer, (size_t)(g->width * g->height));
	}

	g->advance = ((float)slot->advance.x) / 64.0f;
	g->advance_i = (int)g->advance;
	g->pos_x = (float)slot->bitmap_left;
	g->pos_y = (float)slot->bitmap_top;
	g->pitch = slot->bitmap.pitch;

	FT_Outline_Get_CBox(&(slot->outline), &bbox);
	g->box.xmin = ((float)bbox.xMin) / 64.0f;
	g->box.xmax = ((float)bbox.xMax) / 64.0f;
	g->box.ymin = ((float)bbox.yMin) / 64.0f;
	g->box.ymax = ((float)bbox.yMax) / 64.0f;

	key = blf_hash(g->c);
	BLI_addhead(&(font->glyph_cache->bucket[key]), g);

	BLI_spin_unlock(font->ft_lib_mutex);

	return g;
}
Exemple #2
0
/** 转换FT_GlyphSlot类型数据为LCUI_FontBMP */
static int Convert_FTGlyph( LCUI_FontBMP *bmp, FT_GlyphSlot slot, int mode )
{
	int error;
	size_t size;
	FT_BitmapGlyph bitmap_glyph;
	FT_Glyph  glyph;

	/* 从字形槽中提取一个字形图像
	 * 请注意,创建的FT_Glyph对象必须与FT_Done_Glyph成对使用 */
	error = FT_Get_Glyph( slot, &glyph );
	if(error) {
		return -1;
	}
	/*---------------------- 打印字体信息 --------------------------
	printf(" width= %ld,  met->height= %ld\n"
	"horiBearingX = %ld, horiBearingY = %ld, horiAdvance = %ld\n"
	"vertBearingX = %ld, vertBearingY = %ld,  vertAdvance = %ld\n",
	slot->metrics.width>>6, slot->metrics.height>>6,
	slot->metrics.horiBearingX>>6, slot->metrics.horiBearingY>>6,
	slot->metrics.horiAdvance>>6, slot->metrics.vertBearingX>>6,
	slot->metrics.vertBearingY>>6, slot->metrics.vertAdvance>>6 );
	------------------------------------------------------------*/
	if ( glyph->format != FT_GLYPH_FORMAT_BITMAP ) {
		error = FT_Glyph_To_Bitmap(&glyph, mode, 0 ,1);
		if(error) {
			return -1;
		}
	}
	bitmap_glyph = (FT_BitmapGlyph)glyph;
	/*
	 * FT_Glyph_Metrics结构体中保存字形度量,通过face->glyph->metrics结
	 * 构访问,可得到字形的宽、高、左边界距、上边界距、水平跨距等等。
	 * 注意:因为不是所有的字体都包含垂直度量,当FT_HAS_VERTICAL为假时,
	 * vertBearingX,vertBearingY和vertAdvance的值是不可靠的,目前暂不考虑
	 * 此情况的处理。
	 * */
	bmp->top = bitmap_glyph->top;
	bmp->left = slot->metrics.horiBearingX>>6;
	bmp->rows = bitmap_glyph->bitmap.rows;
	bmp->width = bitmap_glyph->bitmap.width;
	bmp->advance.x = slot->metrics.horiAdvance>>6;	/* 水平跨距 */
	bmp->advance.y = slot->metrics.vertAdvance>>6;	/* 垂直跨距 */
	/* 分配内存,用于保存字体位图 */
	size = bmp->rows * bmp->width * sizeof(uchar_t);
	bmp->buffer = (uchar_t*)malloc( size );
	if( !bmp->buffer ) {
		FT_Done_Glyph(glyph);
		return -1;
	}

	switch( bitmap_glyph->bitmap.pixel_mode ) {
	    /* 8位灰度位图,直接拷贝 */
	    case FT_PIXEL_MODE_GRAY:
		memcpy( bmp->buffer, bitmap_glyph->bitmap.buffer, size );
		break;
	    /* 单色点阵图,需要转换 */
	    case FT_PIXEL_MODE_MONO: {
		FT_Bitmap bitmap;
		FT_Library lib;
		FT_Int x, y;
		uchar_t *t, *s;

		lib = FontLIB_GetLibrary();
		FT_Bitmap_New( &bitmap );
		/* 转换位图bitmap_glyph->bitmap至bitmap,1个像素占1个字节 */
		FT_Bitmap_Convert( lib, &bitmap_glyph->bitmap, &bitmap, 1);
		s = bitmap.buffer;
		t = bmp->buffer;
		for( y=0; y<bmp->rows; ++y ) {
			for( x=0; x<bmp->width; ++x ) {
				*t = *s?255:0;
				++t,++s;
			}
		}
		FT_Bitmap_Done( lib, &bitmap );
		break;
	    }
	    /* 其它像素模式的位图,暂时先直接填充255,等需要时再完善 */
	    default:
		memset( bmp->buffer, 255, size );
		break;
	}
	FT_Done_Glyph(glyph);
	return size;
}
	void ResourceTrueTypeFont::renderGlyphs(const GlyphHeightMap& _glyphHeightMap, const FT_Library& _ftLibrary, const FT_Face& _ftFace, FT_Int32 _ftLoadFlags, uint8* _texBuffer, int _texWidth, int _texHeight)
	{
		FT_Bitmap ftBitmap;
		FT_Bitmap_New(&ftBitmap);

		int texX = mGlyphSpacing, texY = mGlyphSpacing;

		for (GlyphHeightMap::const_iterator j = _glyphHeightMap.begin(); j != _glyphHeightMap.end(); ++j)
		{
			for (GlyphHeightMap::mapped_type::const_iterator i = j->second.begin(); i != j->second.end(); ++i)
			{
				GlyphInfo& info = *i->second;

				switch (info.codePoint)
				{
				case FontCodeType::Selected:
				case FontCodeType::SelectedBack:
				{
					renderGlyph<LAMode, false, false>(info, charMaskWhite, charMaskBlack, charMask.find(info.codePoint)->second, j->first, _texBuffer, _texWidth, _texHeight, texX, texY);

					// Manually adjust the glyph's width to zero. This prevents artifacts from appearing at the seams when
					// rendering multi-character selections.
					GlyphInfo* glyphInfo = getGlyphInfo(info.codePoint);
					glyphInfo->width = 0.0f;
					glyphInfo->uvRect.right = glyphInfo->uvRect.left;
				}
				break;

				case FontCodeType::Cursor:
				case FontCodeType::Tab:
					renderGlyph<LAMode, false, false>(info, charMaskWhite, charMaskBlack, charMask.find(info.codePoint)->second, j->first, _texBuffer, _texWidth, _texHeight, texX, texY);
					break;

				default:
					if (FT_Load_Glyph(_ftFace, i->first, _ftLoadFlags | FT_LOAD_RENDER) == 0)
					{
						if (_ftFace->glyph->bitmap.buffer != nullptr)
						{
							uint8* glyphBuffer = nullptr;

							switch (_ftFace->glyph->bitmap.pixel_mode)
							{
							case FT_PIXEL_MODE_GRAY:
								glyphBuffer = _ftFace->glyph->bitmap.buffer;
								break;

							case FT_PIXEL_MODE_MONO:
								// Convert the monochrome bitmap to 8-bit before rendering it.
								if (FT_Bitmap_Convert(_ftLibrary, &_ftFace->glyph->bitmap, &ftBitmap, 1) == 0)
								{
									// Go through the bitmap and convert all of the nonzero values to 0xFF (white).
									for (uint8* p = ftBitmap.buffer, * endP = p + ftBitmap.width * ftBitmap.rows; p != endP; ++p)
										*p ^= -*p ^ *p;

									glyphBuffer = ftBitmap.buffer;
								}
								break;
							}

							if (glyphBuffer != nullptr)
								renderGlyph<LAMode, true, Antialias>(info, charMaskWhite, charMaskWhite, charMaskWhite, j->first, _texBuffer, _texWidth, _texHeight, texX, texY, glyphBuffer);
						}
					}
					else
					{
						MYGUI_LOG(Warning, "ResourceTrueTypeFont: Cannot render glyph " << i->first << " for character " << info.codePoint << " in font '" << getResourceName() << "'.");
					}
					break;
				}
			}
		}

		FT_Bitmap_Done(_ftLibrary, &ftBitmap);
	}
Exemple #4
0
GlyphBLF *blf_glyph_add(FontBLF *font, unsigned int index, unsigned int c)
{
	FT_GlyphSlot slot;
	GlyphBLF *g;
	FT_Error err;
	FT_Bitmap bitmap, tempbitmap;
	int sharp = (U.text_render & USER_TEXT_DISABLE_AA);
	FT_BBox bbox;
	unsigned int key;

	g = blf_glyph_search(font->glyph_cache, c);
	if (g)
		return g;

	if (sharp)
		err = FT_Load_Glyph(font->face, (FT_UInt)index, FT_LOAD_TARGET_MONO);
	else
		err = FT_Load_Glyph(font->face, (FT_UInt)index, FT_LOAD_TARGET_NORMAL | FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP); /* Sure about NO_* flags? */
	if (err)
		return NULL;

	/* get the glyph. */
	slot = font->face->glyph;

	if (sharp) {
		err = FT_Render_Glyph(slot, FT_RENDER_MODE_MONO);

		/* Convert result from 1 bit per pixel to 8 bit per pixel */
		/* Accum errors for later, fine if not interested beyond "ok vs any error" */
		FT_Bitmap_New(&tempbitmap);
		err += FT_Bitmap_Convert(font->ft_lib, &slot->bitmap, &tempbitmap, 1); /* Does Blender use Pitch 1 always? It works so far */
		err += FT_Bitmap_Copy(font->ft_lib, &tempbitmap, &slot->bitmap);
		err += FT_Bitmap_Done(font->ft_lib, &tempbitmap);
	}
	else {
		err = FT_Render_Glyph(slot, FT_RENDER_MODE_NORMAL);
	}

	if (err || slot->format != FT_GLYPH_FORMAT_BITMAP)
		return NULL;

	g = (GlyphBLF *)MEM_callocN(sizeof(GlyphBLF), "blf_glyph_add");
	g->c = c;
	g->idx = (FT_UInt)index;
	g->xoff = -1;
	g->yoff = -1;
	bitmap = slot->bitmap;
	g->width = bitmap.width;
	g->height = bitmap.rows;

	if (g->width && g->height) {
		if (sharp) {
			/* Font buffer uses only 0 or 1 values, Blender expects full 0..255 range */
			int i;
			for (i = 0; i < (g->width * g->height); i++) {
				bitmap.buffer[i] = 255 * bitmap.buffer[i];
			}
		}

		g->bitmap = (unsigned char *)MEM_mallocN(g->width * g->height, "glyph bitmap");
		memcpy((void *)g->bitmap, (void *)bitmap.buffer, g->width * g->height);
	}

	g->advance = ((float)slot->advance.x) / 64.0f;
	g->pos_x = slot->bitmap_left;
	g->pos_y = slot->bitmap_top;
	g->pitch = slot->bitmap.pitch;

	FT_Outline_Get_CBox(&(slot->outline), &bbox);
	g->box.xmin = ((float)bbox.xMin) / 64.0f;
	g->box.xmax = ((float)bbox.xMax) / 64.0f;
	g->box.ymin = ((float)bbox.yMin) / 64.0f;
	g->box.ymax = ((float)bbox.yMax) / 64.0f;

	key = blf_hash(g->c);
	BLI_addhead(&(font->glyph_cache->bucket[key]), g);
	return g;
}
  FT_Error
  FTDemo_Glyph_To_Bitmap( FTDemo_Handle*  handle,
                          FT_Glyph        glyf,
                          grBitmap*       target,
                          int*            left,
                          int*            top,
                          int*            x_advance,
                          int*            y_advance,
                          FT_Glyph*       aglyf )
  {
    FT_BitmapGlyph  bitmap;
    FT_Bitmap*      source;


    *aglyf = NULL;

    error = FT_Err_Ok;

    if ( glyf->format == FT_GLYPH_FORMAT_OUTLINE )
    {
      FT_Render_Mode  render_mode = FT_RENDER_MODE_MONO;


      if ( handle->antialias )
      {
        if ( handle->lcd_mode == 0 )
          render_mode = FT_RENDER_MODE_NORMAL;
        else if ( handle->lcd_mode == 1 )
          render_mode = FT_RENDER_MODE_LIGHT;
        else if ( handle->lcd_mode <= 3 )
          render_mode = FT_RENDER_MODE_LCD;
        else
          render_mode = FT_RENDER_MODE_LCD_V;
      }

      /* render the glyph to a bitmap, don't destroy original */
      error = FT_Glyph_To_Bitmap( &glyf, render_mode, NULL, 0 );
      if ( error )
        return error;

      *aglyf = glyf;
    }

    if ( glyf->format != FT_GLYPH_FORMAT_BITMAP )
      PanicZ( "invalid glyph format returned!" );

    bitmap = (FT_BitmapGlyph)glyf;
    source = &bitmap->bitmap;

    target->rows   = source->rows;
    target->width  = source->width;
    target->pitch  = source->pitch;
    target->buffer = source->buffer;
    target->grays  = source->num_grays;

    switch ( source->pixel_mode )
    {
    case FT_PIXEL_MODE_MONO:
      target->mode = gr_pixel_mode_mono;
      break;

    case FT_PIXEL_MODE_GRAY:
      target->mode  = gr_pixel_mode_gray;
      target->grays = source->num_grays;
      break;

    case FT_PIXEL_MODE_GRAY2:
    case FT_PIXEL_MODE_GRAY4:
      (void)FT_Bitmap_Convert( handle->library, source, &handle->bitmap, 1 );
      target->pitch  = handle->bitmap.pitch;
      target->buffer = handle->bitmap.buffer;
      target->mode   = gr_pixel_mode_gray;
      target->grays  = handle->bitmap.num_grays;
      break;

    case FT_PIXEL_MODE_LCD:
      target->mode  = handle->lcd_mode == 2 ? gr_pixel_mode_lcd
                                            : gr_pixel_mode_lcd2;
      target->grays = source->num_grays;
      break;

    case FT_PIXEL_MODE_LCD_V:
      target->mode  = handle->lcd_mode == 4 ? gr_pixel_mode_lcdv
                                            : gr_pixel_mode_lcdv2;
      target->grays = source->num_grays;
      break;

    case FT_PIXEL_MODE_BGRA:
      target->mode  = gr_pixel_mode_bgra;
      target->grays = source->num_grays;
      break;

    default:
      return FT_Err_Invalid_Glyph_Format;
    }

    *left = bitmap->left;
    *top  = bitmap->top;

    *x_advance = ( glyf->advance.x + 0x8000 ) >> 16;
    *y_advance = ( glyf->advance.y + 0x8000 ) >> 16;

    return error;
  }