예제 #1
0
void FontGenerator::fillCharacterDescriptors(const std::string& face, int size, bool bold, CharDescriptorList& chars, 
		const CharacterRange& range, const vec2& extraOffsets)
{
	HDC dc = CreateCompatibleDC(0);
	int pointsSize = MulDiv(size, GetDeviceCaps(dc, LOGPIXELSY), 72);

	HFONT font = CreateFont(-pointsSize, 0, 0, 0, bold ? FW_BOLD : FW_NORMAL, 0, 0, 0, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, 
		CLIP_DEFAULT_PRECIS, CLEARTYPE_QUALITY, DEFAULT_PITCH, face.c_str());

	SelectObject(dc, font);

	for (CharacterRange::const_iterator i = range.begin(), e = range.end(); i != e; ++i)
	{
		SIZE charSize = { };
		wchar_t wStr[2] = { static_cast<wchar_t>(*i), 0 };
		GetTextExtentPointW(dc, wStr, 1, &charSize);

		CharDescriptor desc = CharDescriptor(*i, bold ? CharParameter_Bold : 0);
		desc.size.x = static_cast<float>(charSize.cx + 2) + extraOffsets.x;
		desc.size.y = static_cast<float>(charSize.cy) + extraOffsets.y;
		desc.extra.x = static_cast<int>(0.5f * extraOffsets.x + 1.0f);
		desc.extra.y = static_cast<int>(0.5f * extraOffsets.y - 1.0f);
		desc.extra.z = reinterpret_cast<int>(font);

		chars.push_back(desc);
	}

	DeleteDC(dc);
}
예제 #2
0
FontGeneratorResult FontGenerator::generate(ImageFormat fmt)
{
	if (!_outFileSet) 
		return FontGeneratorResult_OutputFileNotDefined;

	std::string _outInfoFile = _outFile + ".font";
	std::string _outLayoutFile = _outFile + ".layout" + ImageWriter::extensionForImageFormat(fmt);
	std::string _outFontFile = _outFile + ImageWriter::extensionForImageFormat(fmt);

	CharDescriptorList chars;
	fillCharacterDescriptors(_face, _size, false, chars, _characterRange, vec2(_offset));
	fillCharacterDescriptors(_face, _size, true, chars, _characterRange, vec2(_offset));

	int charsPerRow = static_cast<int>(::sqrt(static_cast<float>(chars.size()))) * 2;

	vec2i textureSize;
	float textureWidth = 0.0f;

	int index = 0;
	float x_pos = characterOffset;
	for (CharDescriptorList::iterator i = chars.begin(), e = chars.end(); i != e; ++i, ++index)
	{
		x_pos += i->size.x + characterOffset;
		if (index && (index % charsPerRow == 0))
		{
			textureWidth = etMax(x_pos, textureWidth);
			x_pos = characterOffset;
		}
	}

	textureWidth = etMin(1024.0f, textureWidth);

	bool foundOptimal = false;
	while (!foundOptimal)
	{
		float lineHeight = 0.0f;
		float y_pos = characterOffset;
		x_pos = characterOffset;
		textureSize.x = roundToHighestPowerOfTwo(static_cast<size_t>(textureWidth));
		textureWidth = static_cast<float>(textureSize.x);
		for (CharDescriptorList::iterator i = chars.begin(), e = chars.end(); i != e; ++i)
		{
			if (x_pos + i->size.x + characterOffset >= textureSize.x)
			{
				x_pos = characterOffset;
				y_pos += lineHeight + characterOffset;
				lineHeight = 0.0f;
			}

			i->origin = vec2(x_pos, y_pos);
			x_pos += i->size.x + characterOffset;
			lineHeight = etMax(i->size.y, lineHeight);
		}
		textureSize.y = roundToHighestPowerOfTwo( static_cast<size_t>(y_pos + lineHeight + characterOffset) );

		foundOptimal = textureSize.y / textureSize.x <= 1;

		if (foundOptimal) break;

		textureSize.x *= 2;
		textureWidth = static_cast<float>(textureSize.x);
	}

	for (CharDescriptorList::iterator i = chars.begin(), e = chars.end(); i != e; ++i)
	{
		i->uvOrigin.x = i->origin.x / static_cast<float>(textureSize.x);
		i->uvOrigin.y = 1.0f - i->origin.y / static_cast<float>(textureSize.y);
		i->uvSize.x = i->size.x / static_cast<float>(textureSize.x);
		i->uvSize.y = i->size.y / static_cast<float>(textureSize.y);
	}

	int dataSize = textureSize.square() * 4;

	BITMAPINFO bi = { sizeof(BITMAPINFO) };
	bi.bmiHeader.biPlanes = 1;
	bi.bmiHeader.biBitCount = 32;
	bi.bmiHeader.biHeight = textureSize.y;
	bi.bmiHeader.biWidth = textureSize.x;
	bi.bmiHeader.biSizeImage = dataSize;

	BinaryDataStorage data(dataSize);
	data.fill(0);

	HBITMAP bitmap = CreateBitmap(textureSize.x, textureSize.y, 1, 32, 0);

	HDC dc = CreateCompatibleDC(0);
	SelectObject(dc, bitmap);
	SetTextColor(dc, 0xffffff);
	SetBkMode(dc, TRANSPARENT);
	SetDIBits(dc, bitmap, 0, textureSize.y, data.data(), &bi, DIB_RGB_COLORS);

	for (CharDescriptorList::iterator i = chars.begin(), e = chars.end(); i != e; ++i)
	{
		wchar_t wStr[2] = { static_cast<wchar_t>(i->value), 0 };
		SelectObject(dc, reinterpret_cast<HFONT>(i->extra.z));

		TextOutW(dc, static_cast<int>(i->origin.x) + i->extra.x, 	static_cast<int>(i->origin.y) + i->extra.y, wStr, 1);
	}

	GetDIBits(dc, bitmap, 0, textureSize.y, data.data(), &bi, DIB_RGB_COLORS);

	for (int i = 0; i < dataSize / 4; ++i)
	{
		unsigned char r = data[4*i+0];
		unsigned char g = data[4*i+1];
		unsigned char b = data[4*i+2];
		data[4*i+0] = 255;
		data[4*i+1] = 255;
		data[4*i+2] = 255;
		data[4*i+3] = (76 * r + 151 * g + 28 * b) / 255;
	}

	FontGeneratorResult result = FontGeneratorResult_Success;

	if (!ImageWriter::writeImageToFile(_outFontFile, data, textureSize, 4, 8, fmt, false))
		result = FontGeneratorResult_OutputFileFailed;

	data.fill(0);

	for (CharDescriptorList::iterator i = chars.begin(), e = chars.end(); i != e; ++i)
	{
		unsigned char rndColor[3] = { 128 + rand() % 127, 128 + rand() % 127, 128 + rand() % 127 };

		int x = static_cast<int>(i->origin.x);
		int y = static_cast<int>(i->origin.y);
		int w = static_cast<int>(i->size.x);
		int h = static_cast<int>(i->size.y);
		for (int v = 0; v < h; ++v)
		{
			for (int u = 0; u < w; ++u)
			{
				int index = (x + u) + (textureSize.y - 1 - y - v) * textureSize.x;
				data[4 * index + 0] = rndColor[0];
				data[4 * index + 1] = rndColor[1];
				data[4 * index + 2] = rndColor[2];
				data[4 * index + 3] = 255;
			}
		}
	}

	if (!ImageWriter::writeImageToFile(_outLayoutFile, data, textureSize, 4, 8, fmt, false))
		result = FontGeneratorResult_OutputFileFailed;

	DeleteObject(bitmap);
	DeleteDC(dc);

	std::ofstream fontFile(_outInfoFile, std::ios::binary);
	if (fontFile.fail())
		return FontGeneratorResult_OutputFileFailed;

	serializeInt(fontFile, FontGenVersion);
	serializeString(fontFile, _face);
	serializeInt(fontFile, _size);
	serializeString(fontFile, getFileName(_outFontFile));
	serializeString(fontFile, getFileName(_outLayoutFile));
	serializeInt(fontFile, chars.size());
	for (CharDescriptorList::iterator i = chars.begin(), e = chars.end(); i != e; ++i)
	{
		CharDescriptor& desc = *i;
		fontFile.write(reinterpret_cast<const char*>(&desc), sizeof(CharDescriptor));
	}
	fontFile.close();


	return result;
}
예제 #3
0
void GuiRenderer::createStringVertices(GuiVertexList& vertices, const CharDescriptorList& chars,
	Alignment hAlign, Alignment vAlign, const vec2& pos, const vec4& color,
	const mat4& transform, RenderLayer layer)
{
	if (_saveFillRate)
		layer = RenderLayer_Layer0;
	
	vec4 line;
	std::vector<vec4> lines;

	for (const CharDescriptor& desc : chars)
	{
		line.w = etMax(line.w, desc.size.y);
		if ((desc.value == ET_NEWLINE) || (desc.value == ET_RETURN))
		{
			lines.push_back(line);
			line = vec4(0.0f, line.y + line.w, 0.0f, 0.0f);
		}
		else 
		{
			line.z += desc.size.x;
		}
	}
	lines.push_back(line);

	float hAlignFactor = alignmentFactor(hAlign);
	float vAlignFactor = alignmentFactor(vAlign);
	for (vec4& i : lines)
	{
		i.x -= hAlignFactor * i.z;
		i.y -= vAlignFactor * i.w;
	}
	
	size_t lineIndex = 0;
	line = lines.front();
	
	vec2 mask(layer == RenderLayer_Layer0 ? 0.0f : 1.0f, 0.0f);
	
	vertices.fitToSize(6 * chars.size());
	for (const CharDescriptor& desc : chars)
	{
		if ((desc.value == ET_NEWLINE) || (desc.value == ET_RETURN))
		{
			line = lines[++lineIndex];
		}
		else 
		{
			vec2 topLeft = line.xy() + pos;
			vec2 bottomLeft = topLeft + vec2(0.0f, desc.size.y);
			vec2 topRight = topLeft + vec2(desc.size.x, 0.0f);
			vec2 bottomRight = bottomLeft + vec2(desc.size.x, 0.0f);
			
			vec2 topLeftUV = desc.uvOrigin;
			vec2 topRightUV = topLeftUV + vec2(desc.uvSize.x, 0.0f);
			vec2 bottomLeftUV = desc.uvOrigin - vec2(0.0f, desc.uvSize.y);
			vec2 bottomRightUV = bottomLeftUV + vec2(desc.uvSize.x, 0.0f);
			vec4 charColor = desc.color * color;
			
			buildQuad(vertices,
				GuiVertex(floorv(transform * topLeft), vec4(topLeftUV, mask), charColor),
				GuiVertex(floorv(transform * topRight), vec4(topRightUV, mask), charColor),
				GuiVertex(floorv(transform * bottomLeft), vec4(bottomLeftUV, mask), charColor),
				GuiVertex(floorv(transform * bottomRight), vec4(bottomRightUV, mask), charColor));
			
			line.x += desc.size.x;
		}
	}
}