const TSet<FName>& FCompositeFontCache::GetFontAttributes(const FFontData& InFontData)
{
	static const TSet<FName> DummyAttributes;

	TSharedPtr<FFreeTypeFace> FaceAndMemory = GetFontFace(InFontData);
	return (FaceAndMemory.IsValid()) ? FaceAndMemory->GetAttributes() : DummyAttributes;
}
Пример #2
0
void CFPF_SkiaFontMgr::ScanFile(const CFX_ByteString& file) {
  FXFT_Face face = GetFontFace(file.AsStringC());
  if (face) {
    CFPF_SkiaPathFont* pFontDesc = new CFPF_SkiaPathFont;
    pFontDesc->SetPath(file.c_str());
    ReportFace(face, pFontDesc);
    m_FontFaces.push_back(pFontDesc);
    FXFT_Done_Face(face);
  }
}
void CFPF_SkiaFontMgr::ScanFile(FX_BSTR file)
{
    FXFT_Face face = GetFontFace(file);
    if (face) {
        CFPF_SkiaPathFont *pFontDesc = new CFPF_SkiaPathFont;
        pFontDesc->SetPath(file.GetCStr());
        ReportFace(face, pFontDesc);
        m_FontFaces.Add(pFontDesc);
        FXFT_Done_Face(face);
    }
}
Пример #4
0
uint GetGlyphWidth(FontSize size, WChar key)
{
	FT_Face face = GetFontFace(size);
	GlyphEntry *glyph;

	if (face == NULL || (key >= SCC_SPRITE_START && key <= SCC_SPRITE_END)) {
		SpriteID sprite = GetUnicodeGlyph(size, key);
		if (sprite == 0) sprite = GetUnicodeGlyph(size, '?');
		return SpriteExists(sprite) ? GetSprite(sprite, ST_FONT)->width + (size != FS_NORMAL && size != FS_MONO) : 0;
	}

	glyph = GetGlyphPtr(size, key);
	if (glyph == NULL || glyph->sprite == NULL) {
		GetGlyph(size, key);
		glyph = GetGlyphPtr(size, key);
	}

	return glyph->width;
}
const FFontData& FCompositeFontCache::GetFontDataForCharacter(const FSlateFontInfo& InFontInfo, const TCHAR InChar, float& OutScalingFactor)
{
	static const FFontData DummyFontData;

	auto FontDataHasCharacter = [&](const FFontData& InFontData) -> bool
	{
#if WITH_FREETYPE
		TSharedPtr<FFreeTypeFace> FaceAndMemory = GetFontFace(InFontData);
		return FaceAndMemory.IsValid() && FT_Get_Char_Index(FaceAndMemory->GetFace(), InChar) != 0;
#else  // WITH_FREETYPE
		return false;
#endif // WITH_FREETYPE
	};

	const FCompositeFont* const ResolvedCompositeFont = InFontInfo.GetCompositeFont();
	const FCachedTypefaceData* const CachedTypefaceData = GetCachedTypefaceForCharacter(ResolvedCompositeFont, InChar);
	if (CachedTypefaceData)
	{
		OutScalingFactor = CachedTypefaceData->GetScalingFactor();

		const FCachedTypefaceData* const CachedDefaultTypefaceData = GetDefaultCachedTypeface(ResolvedCompositeFont);
		if (CachedDefaultTypefaceData)
		{
			const bool bIsDefaultTypeface = CachedTypefaceData == CachedDefaultTypefaceData;

			// Try to find the correct font from the typeface
			const FFontData* FoundFontData = CachedTypefaceData->GetFontData(InFontInfo.TypefaceFontName);
			if (FoundFontData && (bIsDefaultTypeface || FontDataHasCharacter(*FoundFontData)))
			{
				return *FoundFontData;
			}

			// Failing that, try and find a font by the attributes of the default font with the given name
			if (!bIsDefaultTypeface)
			{
				const FFontData* const FoundDefaultFontData = CachedDefaultTypefaceData->GetFontData(InFontInfo.TypefaceFontName);
				if (FoundDefaultFontData)
				{
					const TSet<FName>& DefaultFontAttributes = GetFontAttributes(*FoundDefaultFontData);
					FoundFontData = GetBestMatchFontForAttributes(CachedTypefaceData, DefaultFontAttributes);
					if (FoundFontData && FontDataHasCharacter(*FoundFontData))
					{
						return *FoundFontData;
					}
				}
			}

			// Failing that, return the first font available (the "None" font)
			FoundFontData = CachedTypefaceData->GetFontData(NAME_None);
			if (FoundFontData && (bIsDefaultTypeface || FontDataHasCharacter(*FoundFontData)))
			{
				return *FoundFontData;
			}

			// Failing that, try again using the default font (as the sub-font may not have actually supported the character we needed)
			if (!bIsDefaultTypeface)
			{
				OutScalingFactor = CachedDefaultTypefaceData->GetScalingFactor();

				// Try to find the correct font from the typeface
				FoundFontData = CachedDefaultTypefaceData->GetFontData(InFontInfo.TypefaceFontName);
				if (FoundFontData)
				{
					return *FoundFontData;
				}

				// Failing that, return the first font available (the "None" font)
				FoundFontData = CachedDefaultTypefaceData->GetFontData(NAME_None);
				if (FoundFontData)
				{
					return *FoundFontData;
				}
			}
		}
		else
		{
			// Try to find the correct font from the typeface
			const FFontData* FoundFontData = CachedTypefaceData->GetFontData(InFontInfo.TypefaceFontName);
			if (FoundFontData && FontDataHasCharacter(*FoundFontData))
			{
				return *FoundFontData;
			}
		}
	}

	OutScalingFactor = 1.0f;
	return DummyFontData;
}
Пример #6
0
bool GetDrawGlyphShadow()
{
	return GetFontFace(FS_NORMAL) != NULL && GetFontAAState(FS_NORMAL);
}
Пример #7
0
const Sprite *GetGlyph(FontSize size, WChar key)
{
	FT_Face face = GetFontFace(size);
	FT_GlyphSlot slot;
	GlyphEntry new_glyph;
	GlyphEntry *glyph;
	SpriteLoader::Sprite sprite;
	int width;
	int height;
	int x;
	int y;

	assert(IsPrintable(key));

	/* Bail out if no face loaded, or for our special characters */
	if (face == NULL || (key >= SCC_SPRITE_START && key <= SCC_SPRITE_END)) {
		SpriteID sprite = GetUnicodeGlyph(size, key);
		if (sprite == 0) sprite = GetUnicodeGlyph(size, '?');

		/* Load the sprite if it's known. */
		if (sprite != 0) return GetSprite(sprite, ST_FONT);

		/* For the 'rare' case there is no font available at all. */
		if (face == NULL) error("No sprite font and no real font either... bailing!");

		/* Use the '?' from the freetype font. */
		key = '?';
	}

	/* Check for the glyph in our cache */
	glyph = GetGlyphPtr(size, key);
	if (glyph != NULL && glyph->sprite != NULL) return glyph->sprite;

	slot = face->glyph;

	bool aa = GetFontAAState(size);

	FT_UInt glyph_index = FT_Get_Char_Index(face, key);
	if (glyph_index == 0) {
		if (key == '?') {
			/* The font misses the '?' character. Use sprite font. */
			SpriteID sprite = GetUnicodeGlyph(size, key);
			Sprite *spr = (Sprite*)GetRawSprite(sprite, ST_FONT, AllocateFont);
			assert(spr != NULL);
			new_glyph.sprite = spr;
			new_glyph.width  = spr->width + (size != FS_NORMAL);
			SetGlyphPtr(size, key, &new_glyph, false);
			return new_glyph.sprite;
		} else {
			/* Use '?' for missing characters. */
			GetGlyph(size, '?');
			glyph = GetGlyphPtr(size, '?');
			SetGlyphPtr(size, key, glyph, true);
			return glyph->sprite;
		}
	}
	FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT);
	FT_Render_Glyph(face->glyph, aa ? FT_RENDER_MODE_NORMAL : FT_RENDER_MODE_MONO);

	/* Despite requesting a normal glyph, FreeType may have returned a bitmap */
	aa = (slot->bitmap.pixel_mode == FT_PIXEL_MODE_GRAY);

	/* Add 1 pixel for the shadow on the medium font. Our sprite must be at least 1x1 pixel */
	width  = max(1, slot->bitmap.width + (size == FS_NORMAL));
	height = max(1, slot->bitmap.rows  + (size == FS_NORMAL));

	/* Limit glyph size to prevent overflows later on. */
	if (width > 256 || height > 256) usererror("Font glyph is too large");

	/* FreeType has rendered the glyph, now we allocate a sprite and copy the image into it */
	sprite.AllocateData(width * height);
	sprite.type = ST_FONT;
	sprite.width = width;
	sprite.height = height;
	sprite.x_offs = slot->bitmap_left;
	sprite.y_offs = _ascender[size] - slot->bitmap_top;

	/* Draw shadow for medium size */
	if (size == FS_NORMAL && !aa) {
		for (y = 0; y < slot->bitmap.rows; y++) {
			for (x = 0; x < slot->bitmap.width; x++) {
				if (aa ? (slot->bitmap.buffer[x + y * slot->bitmap.pitch] > 0) : HasBit(slot->bitmap.buffer[(x / 8) + y * slot->bitmap.pitch], 7 - (x % 8))) {
					sprite.data[1 + x + (1 + y) * sprite.width].m = SHADOW_COLOUR;
					sprite.data[1 + x + (1 + y) * sprite.width].a = aa ? slot->bitmap.buffer[x + y * slot->bitmap.pitch] : 0xFF;
				}
			}
		}
	}

	for (y = 0; y < slot->bitmap.rows; y++) {
		for (x = 0; x < slot->bitmap.width; x++) {
			if (aa ? (slot->bitmap.buffer[x + y * slot->bitmap.pitch] > 0) : HasBit(slot->bitmap.buffer[(x / 8) + y * slot->bitmap.pitch], 7 - (x % 8))) {
				sprite.data[x + y * sprite.width].m = FACE_COLOUR;
				sprite.data[x + y * sprite.width].a = aa ? slot->bitmap.buffer[x + y * slot->bitmap.pitch] : 0xFF;
			}
		}
	}

	new_glyph.sprite = BlitterFactoryBase::GetCurrentBlitter()->Encode(&sprite, AllocateFont);
	new_glyph.width  = slot->advance.x >> 6;

	SetGlyphPtr(size, key, &new_glyph);

	return new_glyph.sprite;
}
Пример #8
0
const Sprite *GetGlyph(FontSize size, WChar key)
{
	FT_Face face = GetFontFace(size);
	FT_GlyphSlot slot;
	GlyphEntry new_glyph;
	GlyphEntry *glyph;
	SpriteLoader::Sprite sprite;
	int width;
	int height;
	int x;
	int y;

	assert(IsPrintable(key));

	/* Bail out if no face loaded, or for our special characters */
	if (face == NULL || (key >= SCC_SPRITE_START && key <= SCC_SPRITE_END)) {
		SpriteID sprite = GetUnicodeGlyph(size, key);
		if (sprite == 0) sprite = GetUnicodeGlyph(size, '?');
		return GetSprite(sprite, ST_FONT);
	}

	/* Check for the glyph in our cache */
	glyph = GetGlyphPtr(size, key);
	if (glyph != NULL && glyph->sprite != NULL) return glyph->sprite;

	slot = face->glyph;

	bool aa = GetFontAAState(size);

	FT_Load_Char(face, key, FT_LOAD_DEFAULT);
	FT_Render_Glyph(face->glyph, aa ? FT_RENDER_MODE_NORMAL : FT_RENDER_MODE_MONO);

	/* Despite requesting a normal glyph, FreeType may have returned a bitmap */
	aa = (slot->bitmap.pixel_mode == FT_PIXEL_MODE_GRAY);

	/* Add 1 pixel for the shadow on the medium font. Our sprite must be at least 1x1 pixel */
	width  = max(1, slot->bitmap.width + (size == FS_NORMAL));
	height = max(1, slot->bitmap.rows  + (size == FS_NORMAL));

	/* FreeType has rendered the glyph, now we allocate a sprite and copy the image into it */
	sprite.AllocateData(width * height);
	sprite.width = width;
	sprite.height = height;
	sprite.x_offs = slot->bitmap_left;
	sprite.y_offs = _ascender[size] - slot->bitmap_top;

	/* Draw shadow for medium size */
	if (size == FS_NORMAL) {
		for (y = 0; y < slot->bitmap.rows; y++) {
			for (x = 0; x < slot->bitmap.width; x++) {
				if (aa ? (slot->bitmap.buffer[x + y * slot->bitmap.pitch] > 0) : HasBit(slot->bitmap.buffer[(x / 8) + y * slot->bitmap.pitch], 7 - (x % 8))) {
					sprite.data[1 + x + (1 + y) * sprite.width].m = SHADOW_COLOUR;
					sprite.data[1 + x + (1 + y) * sprite.width].a = aa ? slot->bitmap.buffer[x + y * slot->bitmap.pitch] : 0xFF;
				}
			}
		}
	}

	for (y = 0; y < slot->bitmap.rows; y++) {
		for (x = 0; x < slot->bitmap.width; x++) {
			if (aa ? (slot->bitmap.buffer[x + y * slot->bitmap.pitch] > 0) : HasBit(slot->bitmap.buffer[(x / 8) + y * slot->bitmap.pitch], 7 - (x % 8))) {
				sprite.data[x + y * sprite.width].m = FACE_COLOUR;
				sprite.data[x + y * sprite.width].a = aa ? slot->bitmap.buffer[x + y * slot->bitmap.pitch] : 0xFF;
			}
		}
	}

	new_glyph.sprite = BlitterFactoryBase::GetCurrentBlitter()->Encode(&sprite, AllocateFont);
	new_glyph.width  = slot->advance.x >> 6;

	SetGlyphPtr(size, key, &new_glyph);

	return new_glyph.sprite;
}