mitsuba/src/libhw/font.cpp

157 lines
4.2 KiB
C++

/*
This file is part of Mitsuba, a physically based rendering system.
Copyright (c) 2007-2012 by Wenzel Jakob and others.
Mitsuba is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License Version 3
as published by the Free Software Foundation.
Mitsuba is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <mitsuba/hw/font.h>
#include <mitsuba/hw/gputexture.h>
#include <mitsuba/core/mstream.h>
#include <mitsuba/core/bitmap.h>
#include <mitsuba/core/zstream.h>
#include "data/veramono14_dsc.h"
#include "data/veramono14_png.h"
#include "data/vera14_dsc.h"
#include "data/vera14_png.h"
MTS_NAMESPACE_BEGIN
Font::Font(EFont font) {
uint32_t png_size = 0, dsc_size = 0;
uint8_t *png_ptr = NULL, *dsc_ptr = NULL;
switch (font) {
case EBitstreamVera14:
m_name = "Bitstream Vera 14";
dsc_ptr = vera14_dsc;
dsc_size = vera14_dsc_size;
png_ptr = vera14_png;
png_size = vera14_png_size;
break;
case EBitstreamVeraMono14:
m_name = "Bitstream Vera Mono 14";
dsc_ptr = veramono14_dsc;
dsc_size = veramono14_dsc_size;
png_ptr = veramono14_png;
png_size = veramono14_png_size;
break;
default:
Log(EError, "Font is not available!");
}
ref<Stream> pngStream = new MemoryStream(png_ptr, png_size);
ref<Stream> dscStream = new ZStream(
new MemoryStream(dsc_ptr, dsc_size), ZStream::EGZipStream);
dscStream->setByteOrder(Stream::ENetworkByteOrder);
m_maxVerticalBearing = 0;
m_bitmap = new Bitmap(Bitmap::EPNG, pngStream);
for (int i=0; i<256; ++i) {
Glyph &g = m_glyphs[i];
g.tx.x = dscStream->readSingle();
g.tx.y = dscStream->readSingle();
g.ts.x = dscStream->readSingle();
g.ts.y = dscStream->readSingle();
g.size = Vector2i(dscStream);
g.horizontalBearing = dscStream->readInt();
g.verticalBearing = dscStream->readInt();
g.horizontalAdvance = dscStream->readInt();
m_maxVerticalBearing = std::max(m_maxVerticalBearing, g.verticalBearing);
}
dscStream->read(m_kerningMatrix, 256*256);
}
void Font::convert(Bitmap::EPixelFormat pixelFormat, Bitmap::EComponentFormat componentFormat, Float gamma) {
m_bitmap = m_bitmap->convert(pixelFormat, componentFormat, gamma);
}
void Font::drawText(Bitmap *dest, Point2i pos, const std::string &text) const {
int initial = pos.x;
for (size_t i=0; i<text.length(); i++) {
char character = text[i];
if (character == '\r')
continue;
if (character == '\n') {
pos.x = initial;
pos.y += (int) (getMaxVerticalBearing()*4.0/3.0);
continue;
}
const Font::Glyph &glyph = getGlyph(character);
Point2i targetOffset = pos + Vector2i(
glyph.horizontalBearing,
getMaxVerticalBearing() - glyph.verticalBearing - 1
);
Point2i sourceOffset(
glyph.tx.x * m_bitmap->getWidth(),
glyph.tx.y * m_bitmap->getHeight());
dest->accumulate(m_bitmap.get(), sourceOffset, targetOffset, glyph.size);
pos.x += glyph.horizontalAdvance;
if (i+1 < text.length())
pos.x += getKerning(character, text[i+1]);
}
}
Vector2i Font::getSize(const std::string &text) const {
Vector2i size(0, getMaxVerticalBearing());
int pos = 0;
for (size_t i=0; i<text.length(); i++) {
char character = text[i];
if (character == '\r')
continue;
if (character == '\n') {
size.y += getMaxVerticalBearing()*(4.0 / 3.0);
size.x = std::max(size.x, pos);
pos = 0;
continue;
}
const Font::Glyph &glyph = getGlyph(character);
pos += glyph.horizontalAdvance;
if (i+1 < text.length())
pos += getKerning(character, text[i+1]);
}
size.x = std::max(size.x, pos);
return size;
}
void Font::init(Renderer *renderer) {
m_texture = renderer->createGPUTexture(m_name, m_bitmap);
m_texture->setFilterType(GPUTexture::ENearest);
m_texture->setMipMapped(false);
m_texture->init();
}
void Font::cleanup() {
m_texture->cleanup();
}
Font::~Font() {
}
MTS_IMPLEMENT_CLASS(Font, false, Object)
MTS_NAMESPACE_END