GlyphBLF *blf_glyph_search(GlyphCacheBLF *gc, unsigned int c)
{
	GlyphBLF *p;
	unsigned int key;

	key = blf_hash(c);
	p = gc->bucket[key].first;
	while (p) {
		if (p->c == c)
			return p;
		p = p->next;
	}
	return NULL;
}
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;
}
Beispiel #3
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;
}