Example #1
0
void Font_CacheGlyphs(FontObj* font, const std::string& text)
{
	// Convert to UTF32

	unsigned int buffer[1024];
	unsigned int bufferSize = ARRAYSIZE(buffer);
	if (!UTF8ToUTF32((const unsigned char*) text.c_str(), text.length(), buffer, bufferSize))
		return;

	// Make sure all glyphs are present

	Font_CacheGlyphs(font, buffer, bufferSize);
}
Example #2
0
STRING NormalizeUTF8String(bool decompose, const char* str8) {
  GenericVector<char32> str32, out_str32, norm_str;
  UTF8ToUTF32(str8, &str32);
  for (int i = 0; i < str32.length(); ++i) {
    norm_str.clear();
    NormalizeChar32(str32[i], decompose, &norm_str);
    for (int j = 0; j < norm_str.length(); ++j) {
      out_str32.push_back(norm_str[j]);
    }
  }
  STRING out_str8;
  UTF32ToUTF8(out_str32, &out_str8);
  return out_str8;
}
Example #3
0
void Font_Draw(FontObj* font, const Text::DrawParams* params)
{
	// Convert to UTF32

	unsigned int buffer[1024];
	unsigned int bufferSize = ARRAYSIZE(buffer);
	if (!UTF8ToUTF32((const unsigned char*) params->text.c_str(), params->text.length(), buffer, bufferSize))
		return;

	// Make sure all glyphs are present

	Font_CacheGlyphs(font, buffer, bufferSize);

	// Generate positions and uvs for the text

	if (!font->texture)
		return;

	const float scale = params->scale;

	std::vector<float> xy;
	std::vector<float> uv;

	float x = params->position.x;
	float y = params->position.y;
	for (unsigned int i = 0; i < bufferSize; i++)
	{
		if (buffer[i] == '\r')
			continue;
		if (buffer[i] == '\n')
		{
			y += (float) font->size * scale;
			x = params->position.x;
			continue;
		}

		Glyph* glyph = map_find(font->glyphs, buffer[i]);
		if (!glyph)
			continue;

		uv.push_back(glyph->uv.left); uv.push_back(glyph->uv.top);
		uv.push_back(glyph->uv.left + glyph->uv.width); uv.push_back(glyph->uv.top);
		uv.push_back(glyph->uv.left + glyph->uv.width); uv.push_back(glyph->uv.top + glyph->uv.height);
		uv.push_back(glyph->uv.left); uv.push_back(glyph->uv.top + glyph->uv.height);
		uv.push_back(*(uv.end() - 8)); uv.push_back(*(uv.end() - 8));
		uv.push_back(*(uv.end() - 6)); uv.push_back(*(uv.end() - 6));

		xy.push_back(x + glyph->pos.left * scale); xy.push_back(y + glyph->pos.top * scale);
		xy.push_back(x + (glyph->pos.left + glyph->pos.width) * scale); xy.push_back(y + glyph->pos.top * scale);
		xy.push_back(x + (glyph->pos.left + glyph->pos.width) * scale); xy.push_back(y + (glyph->pos.top + glyph->pos.height) * scale);
		xy.push_back(x + glyph->pos.left * scale); xy.push_back(y + (glyph->pos.top + glyph->pos.height) * scale);
		xy.push_back(*(xy.end() - 8)); xy.push_back(*(xy.end() - 8));
		xy.push_back(*(xy.end() - 6)); xy.push_back(*(xy.end() - 6));

		x += glyph->advancePos * scale;
	}

	// Determine mins and maxes of the text

	float minX = (float) INT_MAX, maxX = (float) INT_MIN, minY = (float) INT_MAX, maxY = (float) INT_MIN;
	for (unsigned int i = 0; i < xy.size(); i += 2)
	{
		minX = min(minX, xy[i]);
		maxX = max(maxX, xy[i]);
		minY = min(minY, xy[i + 1]);
		maxY = max(maxY, xy[i + 1]);
	}

	// Determine the center of the text

	float centerX = 0.0f, centerY = 0.0f;
	if (params->width == 0.0f || params->height == 0.0f)
	{
		centerX = (minX + maxX) * 0.5f;
		centerY = (minY + maxY) * 0.5f;
	}
	else
	{
		centerX = params->position.x + params->width * 0.5f;
		centerY = params->position.y + params->height * 0.5f;
	}

	// Align the text

	switch (params->horizontalAlignment)
	{
		case Text::HorizontalAlignment_Center:
		{
			const float offset = params->position.x + params->width * 0.5f - (minX + maxX) * 0.5f;
			for (unsigned int i = 0; i < xy.size(); i += 2)
				xy[i] += offset;
			break;
		}
		case Text::HorizontalAlignment_Right:
		{
			const float offset = params->position.x + params->width - maxX;
			for (unsigned int i = 0; i < xy.size(); i += 2)
				xy[i] += offset;
			break;
		}
		default:
		//case Text::HorizontalAlignment_Left
			:
            break;
	}

	switch (params->verticalAlignment)
	{
		case Text::VerticalAlignment_Center:
		{
			const float offset = params->position.y + params->height * 0.5f - (minY + maxY) * 0.5f;
			for (unsigned int i = 1; i < xy.size(); i += 2)
				xy[i] += offset;
			break;
		}
		case Text::VerticalAlignment_Bottom:
		{
			const float offset = params->position.y + params->height - maxY;
			for (unsigned int i = 1; i < xy.size(); i += 2)
				xy[i] += offset;
			break;
		}
		default:
		//case Text::VerticalAlignment_Top:
            break;
	}

	// Set up draw params

	Shape::DrawParams texParams;
	texParams.SetGeometryType(Shape::Geometry::Type_Triangles);
	texParams.SetNumVerts(xy.size() / 2);
	texParams.SetTexCoord(&uv[0]);

	// Draw shadow

	if (params->drawShadow)
	{
		// Offset verts for the shadow rendering

		std::vector<float> xyShadow = xy;

		for (unsigned int i = 0; i < xyShadow.size(); i += 2)
		{
			xyShadow[i] += params->shadowOffset.x;
			xyShadow[i + 1] += params->shadowOffset.y;
		}

		// Rotate the shadow text

		if (params->rotation != 0)
		{
			const float rotationSin = sinf(params->rotation);
			const float rotationCos = cosf(params->rotation);

			for (unsigned int i = 0; i < xyShadow.size(); i += 2)
				Vertex_Rotate(xyShadow[i], xyShadow[i + 1], centerX, centerY, rotationSin, rotationCos);
		}

		// Draw the shadow

		texParams.color = params->shadowColor;
		texParams.SetPosition(&xyShadow[0]);

		Texture_Draw(font->texture, &texParams);
	}

	// Rotate the text

	if (params->rotation != 0)
	{
		const float rotationSin = sinf(params->rotation);
		const float rotationCos = cosf(params->rotation);

		for (unsigned int i = 0; i < xy.size(); i += 2)
			Vertex_Rotate(xy[i], xy[i + 1], centerX, centerY, rotationSin, rotationCos);
	}

	// Draw

	texParams.color = params->color;
	texParams.SetPosition(&xy[0]);

	Texture_Draw(font->texture, &texParams);
}