Example #1
0
// ----------------------------------------------------------------------------
void FontWithFace::loadGlyphInfo(wchar_t c)
{
    unsigned int font_number = 0;
    unsigned int glyph_index = 0;
    while (font_number < m_face_ttf->getTotalFaces())
    {
        glyph_index = FT_Get_Char_Index(m_face_ttf->getFace(font_number), c);
        if (glyph_index > 0) break;
        font_number++;
    }
    m_character_glyph_info_map[c] = GlyphInfo(font_number, glyph_index);
}   // loadGlyphInfo
Example #2
0
bool
ParagraphLayout::_AppendGlyphInfo(uint32 charCode, float width,
	const CharacterStyle& style)
{
	if (style.Width() >= 0.0f) {
		// Use the metrics provided by the CharacterStyle and override
		// the font provided metrics passed in "width"
		width = style.Width();
	}

	width += style.GlyphSpacing();

	return fGlyphInfos.Add(GlyphInfo(charCode, 0.0f, width, 0));
}
	GlyphInfo ResourceTrueTypeFont::createFaceGlyphInfo(Char _codePoint, int _fontAscent, FT_GlyphSlot _glyph)
	{
		float bearingX = _glyph->metrics.horiBearingX / 64.0f;

		// The following calculations aren't currently needed but are kept here for future use.
		// float ascent = _glyph->metrics.horiBearingY / 64.0f;
		// float descent = (_glyph->metrics.height / 64.0f) - ascent;

		return GlyphInfo(
			_codePoint,
			std::max((float)_glyph->bitmap.width, _glyph->metrics.width / 64.0f),
			std::max((float)_glyph->bitmap.rows, _glyph->metrics.height / 64.0f),
			(_glyph->advance.x / 64.0f) - bearingX,
			bearingX,
			std::floor(_fontAscent - (_glyph->metrics.horiBearingY / 64.0f) - mOffsetHeight));
	}
Example #4
0
ComposingStick::ComposingStick(FontRenderer* renderer, 
							   PixelSize size, 
							   euint32 numChars,
							   xhn::static_string filename)
: m_renderer(renderer)
, m_pixelSize(size)
, m_filename(filename)
{
	int numCharsPerRow = (int)sqrtf((float)numChars + 0.5f);
	euint32 fontPixelWidth = (euint32)size;
	euint32 fontPixelHeight = fontPixelWidth;
    euint32 texPixelWidth = (euint32)(numCharsPerRow + 1) * fontPixelWidth;
	euint32 texPixelHeight = texPixelWidth;

	euint32 numHoris = numCharsPerRow;
	euint32 numVerts = numCharsPerRow;
	for (euint32 y = 0; y < numVerts; y++)
	{
		for (euint32 x = 0; x < numHoris; x++)
		{
			GlyphInfo* info = ENEW GlyphInfo();
			info->x = x * fontPixelWidth;
			info->y = y * fontPixelHeight;
			info->width = fontPixelWidth;
			info->height = fontPixelHeight;
			info->usageCount = 0;
			m_freeGlyphPool.push_back(info);
		}
	}
	/// here create texture
	m_texture = RenderSystem_new_texture2d(filename.c_str(), "Texture");
	m_texture->Create(RGBA8, texPixelWidth, texPixelHeight);
	EColor color;
	color.red = 0.0f;
	color.green = 0.0f;
	color.blue = 0.0f;
	color.alpha = 0.0f;
	m_texture->LoadFromColor(color);
}
Example #5
0
	void ResourceManualFont::deserialization(xml::ElementPtr _node, Version _version)
	{
		Base::deserialization(_node, _version);

		xml::ElementEnumerator node = _node->getElementEnumerator();
		while (node.next())
		{
			if (node->getName() == "Property")
			{
				const std::string& key = node->findAttribute("key");
				const std::string& value = node->findAttribute("value");
				if (key == "Source") mSource = value;
				else if (key == "DefaultHeight") mDefaultHeight = utility::parseInt(value);
			}
		}

		loadTexture();

		if (mTexture != nullptr)
		{
			int textureWidth = mTexture->getWidth();
			int textureHeight = mTexture->getHeight();

			node = _node->getElementEnumerator();
			while (node.next())
			{
				if (node->getName() == "Codes")
				{
					xml::ElementEnumerator element = node->getElementEnumerator();
					while (element.next("Code"))
					{
						std::string value;
						// описане глифов
						if (element->findAttribute("index", value))
						{
							Char id = 0;
							if (value == "cursor")
								id = static_cast<Char>(FontCodeType::Cursor);
							else if (value == "selected")
								id = static_cast<Char>(FontCodeType::Selected);
							else if (value == "selected_back")
								id = static_cast<Char>(FontCodeType::SelectedBack);
							else if (value == "substitute")
								id = static_cast<Char>(FontCodeType::NotDefined);
							else
								id = utility::parseUInt(value);

							float advance(utility::parseValue<float>(element->findAttribute("advance")));
							FloatPoint bearing(utility::parseValue<FloatPoint>(element->findAttribute("bearing")));

							// texture coordinates
							FloatCoord coord(utility::parseValue<FloatCoord>(element->findAttribute("coord")));

							// glyph size, default to texture coordinate size
							std::string sizeString;
							FloatSize size(coord.width, coord.height);
							if (element->findAttribute("size", sizeString))
							{
								size = utility::parseValue<FloatSize>(sizeString);
							}

							if (advance == 0.0f)
								advance = size.width;

							GlyphInfo& glyphInfo = mCharMap.insert(CharMap::value_type(id, GlyphInfo(
								id,
								size.width,
								size.height,
								advance,
								bearing.left,
								bearing.top,
								FloatRect(
									coord.left / textureWidth,
									coord.top / textureHeight,
									coord.right() / textureWidth,
									coord.bottom() / textureHeight)
								))).first->second;

							if (id == FontCodeType::NotDefined)
								mSubstituteGlyphInfo = &glyphInfo;
						}
					}
				}
			}
		}
	}
	void ResourceTrueTypeFont::initialiseFreeType()
	{
		//-------------------------------------------------------------------//
		// Initialise FreeType and load the font.
		//-------------------------------------------------------------------//

		FT_Library ftLibrary;

		if (FT_Init_FreeType(&ftLibrary) != 0)
			MYGUI_EXCEPT("ResourceTrueTypeFont: Could not init the FreeType library!");

		uint8* fontBuffer = nullptr;

		FT_Face ftFace = loadFace(ftLibrary, fontBuffer);

		if (ftFace == nullptr)
		{
			MYGUI_LOG(Error, "ResourceTrueTypeFont: Could not load the font '" << getResourceName() << "'!");
			return;
		}

		//-------------------------------------------------------------------//
		// Calculate the font metrics.
		//-------------------------------------------------------------------//

		// The font's overall ascent and descent are defined in three different places in a TrueType font, and with different
		// values in each place. The most reliable source for these metrics is usually the "usWinAscent" and "usWinDescent" pair of
		// values in the OS/2 header; however, some fonts contain inaccurate data there. To be safe, we use the highest of the set
		// of values contained in the face metrics and the two sets of values contained in the OS/2 header.
		int fontAscent = ftFace->size->metrics.ascender >> 6;
		int fontDescent = -ftFace->size->metrics.descender >> 6;

		TT_OS2* os2 = (TT_OS2*)FT_Get_Sfnt_Table(ftFace, ft_sfnt_os2);

		if (os2 != nullptr)
		{
			setMax(fontAscent, os2->usWinAscent * ftFace->size->metrics.y_ppem / ftFace->units_per_EM);
			setMax(fontDescent, os2->usWinDescent * ftFace->size->metrics.y_ppem / ftFace->units_per_EM);

			setMax(fontAscent, os2->sTypoAscender * ftFace->size->metrics.y_ppem / ftFace->units_per_EM);
			setMax(fontDescent, -os2->sTypoDescender * ftFace->size->metrics.y_ppem / ftFace->units_per_EM);
		}

		// The nominal font height is calculated as the sum of its ascent and descent as specified by the font designer. Previously
		// it was defined by MyGUI in terms of the maximum ascent and descent of the glyphs currently in use, but this caused the
		// font's line spacing to change whenever glyphs were added to or removed from the font definition. Doing it this way
		// instead prevents a lot of layout problems, and it is also more typographically correct and more aesthetically pleasing.
		mDefaultHeight = fontAscent + fontDescent;

		// Set the load flags based on the specified type of hinting.
		FT_Int32 ftLoadFlags;

		switch (mHinting)
		{
		case HintingForceAuto:
			ftLoadFlags = FT_LOAD_FORCE_AUTOHINT;
			break;
		case HintingDisableAuto:
			ftLoadFlags = FT_LOAD_NO_AUTOHINT;
			break;
		case HintingDisableAll:
			// When hinting is completely disabled, glyphs must always be rendered -- even during layout calculations -- due to
			// discrepancies between the glyph metrics and the actual rendered bitmap metrics.
			ftLoadFlags = FT_LOAD_NO_HINTING | FT_LOAD_RENDER;
			break;
		case HintingUseNative:
			ftLoadFlags = FT_LOAD_DEFAULT;
			break;
		}

		//-------------------------------------------------------------------//
		// Create the glyphs and calculate their metrics.
		//-------------------------------------------------------------------//

		GlyphHeightMap glyphHeightMap;
		int texWidth = 0;

		// Before creating the glyphs, add the "Space" code point to force that glyph to be created. For historical reasons, MyGUI
		// users are accustomed to omitting this code point in their font definitions.
		addCodePoint(FontCodeType::Space);

		// Create the standard glyphs.
		for (CharMap::iterator iter = mCharMap.begin(); iter != mCharMap.end(); )
		{
			const Char& codePoint = iter->first;
			FT_UInt glyphIndex = FT_Get_Char_Index(ftFace, codePoint);

			texWidth += createFaceGlyph(glyphIndex, codePoint, fontAscent, ftFace, ftLoadFlags, glyphHeightMap);

			// If the newly created glyph is the "Not Defined" glyph, it means that the code point is not supported by the font.
			// Remove it from the character map so that we can provide our own substitute instead of letting FreeType do it.
			if (iter->second != 0)
				++iter;
			else
				mCharMap.erase(iter++);
		}

		// Do some special handling for the "Space" and "Tab" glyphs.
		GlyphInfo* spaceGlyphInfo = getGlyphInfo(FontCodeType::Space);

		if (spaceGlyphInfo != nullptr && spaceGlyphInfo->codePoint == FontCodeType::Space)
		{
			// Adjust the width of the "Space" glyph if it has been customized.
			if (mSpaceWidth != 0.0f)
			{
				texWidth += (int)std::ceil(mSpaceWidth) - (int)std::ceil(spaceGlyphInfo->width);
				spaceGlyphInfo->width = mSpaceWidth;
				spaceGlyphInfo->advance = mSpaceWidth;
			}

			// If the width of the "Tab" glyph hasn't been customized, make it eight spaces wide.
			if (mTabWidth == 0.0f)
				mTabWidth = mDefaultTabWidth * spaceGlyphInfo->advance;
		}

		// Create the special glyphs. They must be created after the standard glyphs so that they take precedence in case of a
		// collision. To make sure that the indices of the special glyphs don't collide with any glyph indices in the font, we must
		// use glyph indices higher than the highest glyph index in the font.
		FT_UInt nextGlyphIndex = (FT_UInt)ftFace->num_glyphs;

		float height = (float)mDefaultHeight;

		texWidth += createGlyph(nextGlyphIndex++, GlyphInfo(static_cast<Char>(FontCodeType::Tab), 0.0f, 0.0f, mTabWidth, 0.0f, 0.0f), glyphHeightMap);
		texWidth += createGlyph(nextGlyphIndex++, GlyphInfo(static_cast<Char>(FontCodeType::Selected), mSelectedWidth, height, 0.0f, 0.0f, 0.0f), glyphHeightMap);
		texWidth += createGlyph(nextGlyphIndex++, GlyphInfo(static_cast<Char>(FontCodeType::SelectedBack), mSelectedWidth, height, 0.0f, 0.0f, 0.0f), glyphHeightMap);
		texWidth += createGlyph(nextGlyphIndex++, GlyphInfo(static_cast<Char>(FontCodeType::Cursor), mCursorWidth, height, 0.0f, 0.0f, 0.0f), glyphHeightMap);

		// If a substitute code point has been specified, check to make sure that it exists in the character map. If it doesn't,
		// revert to the default "Not Defined" code point. This is not a real code point but rather an invalid Unicode value that
		// is guaranteed to cause the "Not Defined" special glyph to be created.
		if (mSubstituteCodePoint != FontCodeType::NotDefined && mCharMap.find(mSubstituteCodePoint) == mCharMap.end())
			mSubstituteCodePoint = static_cast<Char>(FontCodeType::NotDefined);

		// Create the "Not Defined" code point (and its corresponding glyph) if it's in use as the substitute code point.
		if (mSubstituteCodePoint == FontCodeType::NotDefined)
			texWidth += createFaceGlyph(0, static_cast<Char>(FontCodeType::NotDefined), fontAscent, ftFace, ftLoadFlags, glyphHeightMap);

		// Cache a pointer to the substitute glyph info for fast lookup.
		mSubstituteGlyphInfo = &mGlyphMap.find(mSubstituteCodePoint)->second;

		// Calculate the average height of all of the glyphs that are in use. This value will be used for estimating how large the
		// texture needs to be.
		double averageGlyphHeight = 0.0;

		for (GlyphHeightMap::const_iterator j = glyphHeightMap.begin(); j != glyphHeightMap.end(); ++j)
			averageGlyphHeight += j->first * j->second.size();

		averageGlyphHeight /= mGlyphMap.size();

		//-------------------------------------------------------------------//
		// Calculate the final texture size.
		//-------------------------------------------------------------------//

		// Round the current texture width and height up to the nearest powers of two.
		texWidth = Bitwise::firstPO2From(texWidth);
		int texHeight = Bitwise::firstPO2From((int)ceil(averageGlyphHeight) + mGlyphSpacing);

		// At this point, the texture is only one glyph high and is probably very wide. For efficiency reasons, we need to make the
		// texture as square as possible. If the texture cannot be made perfectly square, make it taller than it is wide, because
		// the height may decrease in the final layout due to height packing.
		while (texWidth > texHeight)
		{
			texWidth /= 2;
			texHeight *= 2;
		}

		// Calculate the final layout of all of the glyphs in the texture, packing them tightly by first arranging them by height.
		// We assume that the texture width is fixed but that the texture height can be adjusted up or down depending on how much
		// space is actually needed.
		// In most cases, the final texture will end up square or almost square. In some rare cases, however, we can end up with a
		// texture that's more than twice as high as it is wide; when this happens, we double the width and try again.
		do
		{
			if (texHeight > texWidth * 2)
				texWidth *= 2;

			int texX = mGlyphSpacing;
			int 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;

					int glyphWidth = (int)std::ceil(info.width);
					int glyphHeight = (int)std::ceil(info.height);

					autoWrapGlyphPos(glyphWidth, texWidth, glyphHeight, texX, texY);

					if (glyphWidth > 0)
						texX += mGlyphSpacing + glyphWidth;
				}
			}

			texHeight = Bitwise::firstPO2From(texY + glyphHeightMap.rbegin()->first);
		}
		while (texHeight > texWidth * 2);

		//-------------------------------------------------------------------//
		// Create the texture and render the glyphs onto it.
		//-------------------------------------------------------------------//

		if (mTexture)
		{
			RenderManager::getInstance().destroyTexture( mTexture );
			mTexture = nullptr;
		}

		mTexture = RenderManager::getInstance().createTexture(MyGUI::utility::toString((size_t)this, "_TrueTypeFont"));

		mTexture->createManual(texWidth, texHeight, TextureUsage::Static | TextureUsage::Write, Pixel<LAMode>::getFormat());
		mTexture->setInvalidateListener(this);

		uint8* texBuffer = static_cast<uint8*>(mTexture->lock(TextureUsage::Write));

		if (texBuffer != nullptr)
		{
			// Make the texture background transparent white.
			for (uint8* dest = texBuffer, * endDest = dest + texWidth * texHeight * Pixel<LAMode>::getNumBytes(); dest != endDest; )
				Pixel<LAMode, false, false>::set(dest, charMaskWhite, charMaskBlack);

			renderGlyphs<LAMode, Antialias>(glyphHeightMap, ftLibrary, ftFace, ftLoadFlags, texBuffer, texWidth, texHeight);

			mTexture->unlock();

			MYGUI_LOG(Info, "ResourceTrueTypeFont: Font '" << getResourceName() << "' using texture size " << texWidth << " x " << texHeight << ".");
			MYGUI_LOG(Info, "ResourceTrueTypeFont: Font '" << getResourceName() << "' using real height " << mDefaultHeight << " pixels.");
		}
		else
		{
			MYGUI_LOG(Error, "ResourceTrueTypeFont: Error locking texture; pointer is nullptr.");
		}

		FT_Done_Face(ftFace);
		FT_Done_FreeType(ftLibrary);

		delete [] fontBuffer;
	}