155 lines
4.3 KiB
C++
155 lines
4.3 KiB
C++
/* -----------------------------------------------------------------------------
|
|
GSFramework
|
|
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
|
----------------------------------------------------------------------------- */
|
|
|
|
|
|
#include <math.h>
|
|
#include "gpu/gpu_renderer.h"
|
|
#include "gpu/gpu_triangle_batch.h"
|
|
#include "core/raster_font.h"
|
|
#include "log/log.h"
|
|
|
|
using namespace GS;
|
|
using namespace GS::GPU;
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
void Renderer::Write(const Render::RasterFont &f, const char *t, float &x, float &y, const WriterConfig &config, float s, const Color *c, WriterAlignment a, bool mirrored)
|
|
{
|
|
Render::Texture *page = f.GetPage(0);
|
|
if (!page)
|
|
__ERRRAW__(__LOG_E__ << "No glyph page in raster font '" << f.name << "'.\n")
|
|
|
|
float scale_width = s;
|
|
if(mirrored)
|
|
scale_width = -s;
|
|
|
|
// Aspect ratio, texel/pixel mapping.
|
|
float ar = config.correct_ar ? viewport.GetHeight() / viewport.GetWidth() : 1.f; // w / h
|
|
|
|
Vector2 glyph_mapping((float)page->GetWidth() / viewport.GetWidth(), (float)page->GetHeight() / viewport.GetHeight()),
|
|
pixel_mapping(1.f / viewport.GetWidth(), 1.f / viewport.GetHeight());
|
|
|
|
if (!config.normalized)
|
|
{
|
|
x *= pixel_mapping.x;
|
|
y *= pixel_mapping.y;
|
|
y = floor(y * viewport.GetHeight()) / viewport.GetHeight(); // Stay on a pixel boundary.
|
|
}
|
|
float in_x = x;
|
|
|
|
Vector4 vtx[4];
|
|
Vector2 uv[4];
|
|
|
|
Color col[4];
|
|
for (uint n = 0; n < 4; ++n)
|
|
col[n] = c ? *c : Color(1, 1, 1, 1);
|
|
|
|
// Draw glyphs.
|
|
Render::Texture *t_page = NULL;
|
|
bool aligned = false;
|
|
|
|
TriangleBatch batch(*this);
|
|
|
|
for ( ; t[0]; ++t)
|
|
{
|
|
// Catch line feed.
|
|
if (t[0] == '\n')
|
|
{
|
|
x = in_x;
|
|
if (config.normalized)
|
|
y += f.GetHeight() * s;
|
|
else
|
|
{
|
|
y += f.GetHeight() * glyph_mapping.y * s;
|
|
y = floor(y * viewport.GetHeight()) / viewport.GetHeight(); // Avoid float drift, stay on pixel boundary.
|
|
}
|
|
|
|
aligned = false;
|
|
continue;
|
|
}
|
|
|
|
// Compute alignment.
|
|
if (!aligned)
|
|
{
|
|
switch (a)
|
|
{
|
|
case AlignMiddle:
|
|
if (config.normalized)
|
|
x -= f.ComputeLineRect(t).x * scale_width * 0.5f * ar;
|
|
else x -= f.ComputeLineRect(t).x * scale_width * 0.5f * glyph_mapping.x;
|
|
break;
|
|
|
|
case AlignRight:
|
|
if (config.normalized)
|
|
x -= f.ComputeLineRect(t).x * scale_width * ar;
|
|
else x -= f.ComputeLineRect(t).x * scale_width * glyph_mapping.x;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
// Make sure we stay as close as possible to a pixel boundary for non-normalized modes.
|
|
if (!config.normalized)
|
|
x = floor(x * viewport.GetWidth()) / viewport.GetWidth();
|
|
|
|
aligned = true;
|
|
}
|
|
|
|
// Output glyph.
|
|
if (const Render::RasterFont::Glyph *glyph = f.GetGlyphInfos(t[0]))
|
|
{
|
|
if ((t_page = f.GetPage(glyph->page)) != NULL)
|
|
{
|
|
float _x, _y, _w, _h;
|
|
|
|
if (config.normalized)
|
|
{
|
|
_x = x * 2.f - 1.f + glyph->offx * 1.f * scale_width;
|
|
_y = (1.f - y) * 2.f - 1.f - glyph->offy * 2.f * s;
|
|
_w = glyph->w * 2.f * scale_width * ar;
|
|
_h = glyph->h * 2.f * s;
|
|
|
|
_x *= GetGlobalAspectRatio();
|
|
_w *= GetGlobalAspectRatio();
|
|
}
|
|
else
|
|
{
|
|
_x = x * 2.f - 1.f + glyph->offx * 2.f * glyph_mapping.x * scale_width;
|
|
_y = (1.f - y) * 2.f - 1.f - glyph->offy * 2.f * glyph_mapping.y * s;
|
|
_w = glyph->w * 2.f * glyph_mapping.x * scale_width;
|
|
_h = glyph->h * 2.f * glyph_mapping.y * s;
|
|
}
|
|
|
|
vtx[0].Set(_x, _y, 0.5);
|
|
vtx[1].Set(_x + _w, _y, 0.5);
|
|
vtx[2].Set(_x + _w, _y - _h, 0.5);
|
|
vtx[3].Set(_x, _y - _h, 0.5);
|
|
|
|
uv[0].Set(glyph->u, glyph->v);
|
|
uv[1].Set(glyph->u + glyph->w, glyph->v);
|
|
uv[2].Set(glyph->u + glyph->w, glyph->v + glyph->h);
|
|
uv[3].Set(glyph->u, glyph->v + glyph->h);
|
|
|
|
const ushort indice[] = { 0, 1, 2, 0, 2, 3 }; // order is reversed because the quad is drawn from the baseline (bottom to top)
|
|
batch.DrawTriangle(2, 4, vtx, indice, col, uv, t_page, Core::Material::Blend_Alpha, (Core::Material::RenderWord)(Core::Material::Render_NoZTest | Core::Material::Render_NoZWrite | Core::Material::Render_DoubleSided));
|
|
}
|
|
|
|
if (config.normalized)
|
|
x += glyph->step * scale_width * ar;
|
|
else x += glyph->step * glyph_mapping.x * scale_width;
|
|
}
|
|
}
|
|
|
|
batch.Flush();
|
|
|
|
if (!config.normalized)
|
|
{
|
|
x /= pixel_mapping.x;
|
|
y /= pixel_mapping.y;
|
|
}
|
|
}
|
|
//------------------------------------------------------------------------------
|