Remove old fonts support

pull/1193/head
Hleb Valoshka 2021-11-29 22:58:03 +02:00
parent f46a00f4f1
commit 41936fc6bf
47 changed files with 0 additions and 598 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1,19 +0,0 @@
set(CELTFX_SOURCES
texturefont.cpp
texturefont.h
)
add_library(celtxf STATIC ${CELTFX_SOURCES})
#[[
add_library(celtxf SHARED ${CELTFX_SOURCES})
set_target_properties(celtxf PROPERTIES
VERSION ${VERSION}
SOVERSION ${VERSION}
)
]]#
add_dependencies(celtxf celutil)
target_link_libraries(celtxf celutil)
#install(TARGETS celtxf LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})

View File

@ -1,468 +0,0 @@
// texturefont.cpp
//
// Copyright (C) 2001, Chris Laurel <claurel@shatters.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
#include <cassert>
#include <cstring>
#include <fstream>
#include <config.h>
#include <celutil/debug.h>
#include <celutil/bytes.h>
#include <celutil/utf8.h>
#include <celutil/util.h>
#include <celengine/glsupport.h>
#include <celengine/render.h>
#include "texturefont.h"
using namespace std;
TextureFont::TextureFont(const Renderer *r) :
renderer(r)
{
}
TextureFont::~TextureFont()
{
if (texName != 0)
glDeleteTextures(1, (const GLuint*) &texName);
delete[] fontImage;
delete[] glyphLookup;
}
struct FontVertex
{
FontVertex(float _x, float _y, float _u, float _v) :
x(_x), y(_y), u(_u), v(_v)
{}
float x, y;
float u, v;
};
/** Render a single character of the font, adding the specified offset
* to the location.
*/
float TextureFont::render(wchar_t ch, float xoffset, float yoffset) const
{
const Glyph* glyph = getGlyph(ch);
if (glyph == nullptr) glyph = getGlyph((wchar_t)'?');
if (glyph != nullptr)
{
const float x1 = glyph->xoff + xoffset;
const float y1 = glyph->yoff + yoffset;
const float x2 = glyph->xoff + glyph->width + xoffset;
const float y2 = glyph->yoff + glyph->height + yoffset;
FontVertex vertices[4] = {
{x1, y1, glyph->texCoords[0].u, glyph->texCoords[0].v},
{x2, y1, glyph->texCoords[1].u, glyph->texCoords[1].v},
{x2, y2, glyph->texCoords[2].u, glyph->texCoords[2].v},
{x1, y2, glyph->texCoords[3].u, glyph->texCoords[3].v}
};
glEnableVertexAttribArray(CelestiaGLProgram::VertexCoordAttributeIndex);
glEnableVertexAttribArray(CelestiaGLProgram::TextureCoord0AttributeIndex);
glVertexAttribPointer(CelestiaGLProgram::VertexCoordAttributeIndex,
2, GL_FLOAT, GL_FALSE, sizeof(FontVertex), &vertices[0].x);
glVertexAttribPointer(CelestiaGLProgram::TextureCoord0AttributeIndex,
2, GL_FLOAT, GL_FALSE, sizeof(FontVertex), &vertices[0].u);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
glDisableVertexAttribArray(CelestiaGLProgram::VertexCoordAttributeIndex);
glDisableVertexAttribArray(CelestiaGLProgram::TextureCoord0AttributeIndex);
return glyph->advance;
}
return 0;
}
/** Render a string with the specified offset. Do *not* automatically update
* the modelview transform.
*/
float TextureFont::render(const string& s, float xoffset, float yoffset) const
{
int len = s.length();
bool validChar = true;
int i = 0;
float width = 0;
while (i < len && validChar) {
wchar_t ch = 0;
validChar = UTF8Decode(s, i, ch);
i += UTF8EncodedSize(ch);
render(ch, xoffset, yoffset);
const Glyph* glyph = getGlyph(ch);
if (glyph == nullptr)
glyph = getGlyph((wchar_t)'?');
xoffset += glyph->advance;
width += glyph->advance;
}
return width;
}
int TextureFont::getWidth(const string& s) const
{
int width = 0;
int len = s.length();
bool validChar = true;
int i = 0;
while (i < len && validChar)
{
wchar_t ch = 0;
validChar = UTF8Decode(s, i, ch);
i += UTF8EncodedSize(ch);
const Glyph* g = getGlyph(ch);
if (g != nullptr)
width += g->advance;
}
return width;
}
int TextureFont::getHeight() const
{
return maxAscent + maxDescent;
}
int TextureFont::getMaxWidth() const
{
return maxWidth;
}
int TextureFont::getMaxAscent() const
{
return maxAscent;
}
void TextureFont::setMaxAscent(int _maxAscent)
{
maxAscent = _maxAscent;
}
int TextureFont::getMaxDescent() const
{
return maxDescent;
}
void TextureFont::setMaxDescent(int _maxDescent)
{
maxDescent = _maxDescent;
}
int TextureFont::getTextureName() const
{
return texName;
}
void TextureFont::bind()
{
auto *prog = renderer->getShaderManager().getShader("text");
if (prog == nullptr)
return;
if (texName != 0)
{
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texName);
prog->use();
prog->samplerParam("atlasTex") = 0;
}
}
void TextureFont::unbind()
{
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, 0);
glUseProgram(0);
}
void TextureFont::addGlyph(const TextureFont::Glyph& g)
{
glyphs.push_back(g);
if (g.width > maxWidth)
maxWidth = g.width;
}
const TextureFont::Glyph* TextureFont::getGlyph(wchar_t ch) const
{
if (ch >= (wchar_t)glyphLookupTableSize)
return nullptr;
return glyphLookup[ch];
}
bool TextureFont::buildTexture()
{
assert(fontImage != nullptr);
if (texName != 0)
glDeleteTextures(1, (const GLuint*) &texName);
glGenTextures(1, (GLuint*) &texName);
if (texName == 0)
{
DPRINTF(LOG_LEVEL_ERROR, "Failed to allocate texture object for font.\n");
return false;
}
glBindTexture(GL_TEXTURE_2D, texName);
// Don't build mipmaps . . . should really make them an option.
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA,
texWidth, texHeight,
0,
GL_ALPHA, GL_UNSIGNED_BYTE,
fontImage);
return true;
}
void TextureFont::rebuildGlyphLookupTable()
{
if (glyphs.size() == 0)
return;
// Find the largest glyph id
int maxID = glyphs[0].__id;
vector<Glyph>::const_iterator iter;
for (iter = glyphs.begin(); iter != glyphs.end(); iter++)
{
if (iter->__id > maxID)
maxID = iter->__id;
}
// If there was already a lookup table, delete it.
delete[] glyphLookup;
DPRINTF(LOG_LEVEL_INFO, "texturefont: allocating glyph lookup table with %d entries.\n",
maxID + 1);
glyphLookup = new const Glyph*[maxID + 1];
for (int i = 0; i <= maxID; i++)
glyphLookup[i] = nullptr;
// Fill the table with glyph pointers
for (iter = glyphs.begin(); iter != glyphs.end(); iter++)
glyphLookup[iter->__id] = &(*iter);
glyphLookupTableSize = (unsigned int) maxID + 1;
}
static uint32_t readUint32(istream& in, bool swap)
{
uint32_t x;
in.read(reinterpret_cast<char*>(&x), sizeof x);
return swap ? bswap_32(x) : x;
}
static uint16_t readUint16(istream& in, bool swap)
{
uint16_t x;
in.read(reinterpret_cast<char*>(&x), sizeof x);
return swap ? bswap_16(x) : x;
}
static uint8_t readUint8(istream& in)
{
uint8_t x;
in.read(reinterpret_cast<char*>(&x), sizeof x);
return x;
}
/* Not currently used
static int32_t readInt32(istream& in, bool swap)
{
int32_t x;
in.read(reinterpret_cast<char*>(&x), sizeof x);
return swap ? static_cast<int32_t>(bswap_32(static_cast<uint32_t>(x))) : x;
}*/
static int16_t readInt16(istream& in, bool swap)
{
int16_t x;
in.read(reinterpret_cast<char*>(&x), sizeof x);
return swap ? static_cast<int16_t>(bswap_16(static_cast<uint16_t>(x))) : x;
}
static int8_t readInt8(istream& in)
{
int8_t x;
in.read(reinterpret_cast<char*>(&x), sizeof x);
return x;
}
TextureFont* TextureFont::load(const Renderer *r, istream& in)
{
char header[4];
in.read(header, sizeof header);
if (!in.good() || strncmp(header, "\377txf", 4) != 0)
{
DPRINTF(LOG_LEVEL_ERROR, "Stream is not a texture font!.\n");
return nullptr;
}
uint32_t endiannessTest = 0;
in.read(reinterpret_cast<char*>(&endiannessTest), sizeof endiannessTest);
if (!in.good())
{
DPRINTF(LOG_LEVEL_ERROR, "Error reading endianness bytes in txf header.\n");
return nullptr;
}
bool byteSwap;
if (endiannessTest == 0x78563412)
byteSwap = true;
else if (endiannessTest == 0x12345678)
byteSwap = false;
else
{
DPRINTF(LOG_LEVEL_ERROR, "Stream is not a texture font!.\n");
return nullptr;
}
int format = readUint32(in, byteSwap);
unsigned int texWidth = readUint32(in, byteSwap);
unsigned int texHeight = readUint32(in, byteSwap);
unsigned int maxAscent = readUint32(in, byteSwap);
unsigned int maxDescent = readUint32(in, byteSwap);
unsigned int nGlyphs = readUint32(in, byteSwap);
if (!in)
{
DPRINTF(LOG_LEVEL_ERROR, "Texture font stream is incomplete");
return nullptr;
}
DPRINTF(LOG_LEVEL_INFO, "Font contains %d glyphs.\n", nGlyphs);
auto* font = new TextureFont(r);
assert(font != nullptr);
font->setMaxAscent(maxAscent);
font->setMaxDescent(maxDescent);
float dx = 0.5f / texWidth;
float dy = 0.5f / texHeight;
for (unsigned int i = 0; i < nGlyphs; i++)
{
uint16_t __id = readUint16(in, byteSwap);
TextureFont::Glyph glyph(__id);
glyph.width = readUint8(in);
glyph.height = readUint8(in);
glyph.xoff = readInt8(in);
glyph.yoff = readInt8(in);
glyph.advance = readInt8(in);
readInt8(in);
glyph.x = readInt16(in, byteSwap);
glyph.y = readInt16(in, byteSwap);
if (!in)
{
DPRINTF(LOG_LEVEL_ERROR, "Error reading glyph %ud from texture font stream.\n", i);
delete font;
return nullptr;
}
float fWidth = texWidth;
float fHeight = texHeight;
glyph.texCoords[0].u = glyph.x / fWidth + dx;
glyph.texCoords[0].v = glyph.y / fHeight + dy;
glyph.texCoords[1].u = (glyph.x + glyph.width) / fWidth + dx;
glyph.texCoords[1].v = glyph.y / fHeight + dy;
glyph.texCoords[2].u = (glyph.x + glyph.width) / fWidth + dx;
glyph.texCoords[2].v = (glyph.y + glyph.height) / fHeight + dy;
glyph.texCoords[3].u = glyph.x / fWidth + dx;
glyph.texCoords[3].v = (glyph.y + glyph.height) / fHeight + dy;
font->addGlyph(glyph);
}
font->texWidth = texWidth;
font->texHeight = texHeight;
if (format == TxfByte)
{
auto* fontImage = new unsigned char[texWidth * texHeight];
DPRINTF(LOG_LEVEL_INFO, "Reading %d x %d 8-bit font image.\n", texWidth, texHeight);
in.read(reinterpret_cast<char*>(fontImage), texWidth * texHeight);
if (in.gcount() != (signed)(texWidth * texHeight))
{
DPRINTF(LOG_LEVEL_ERROR, "Missing bitmap data in font stream.\n");
delete font;
delete[] fontImage;
return nullptr;
}
font->fontImage = fontImage;
}
else
{
int rowBytes = (texWidth + 7) >> 3;
auto* fontBits = new unsigned char[rowBytes * texHeight];
auto* fontImage = new unsigned char[texWidth * texHeight];
DPRINTF(LOG_LEVEL_INFO, "Reading %d x %d 1-bit font image.\n", texWidth, texHeight);
in.read(reinterpret_cast<char*>(fontBits), rowBytes * texHeight);
if (in.gcount() != (signed)(rowBytes * texHeight))
{
DPRINTF(LOG_LEVEL_ERROR, "Missing bitmap data in font stream.\n");
delete font;
delete[] fontImage;
delete[] fontBits;
return nullptr;
}
for (unsigned int y = 0; y < texHeight; y++)
{
for (unsigned int x = 0; x < texWidth; x++)
{
if ((fontBits[y * rowBytes + (x >> 3)] & (1 << (x & 0x7))) != 0)
fontImage[y * texWidth + x] = 0xff;
else
fontImage[y * texWidth + x] = 0x0;
}
}
font->fontImage = fontImage;
delete[] fontBits;
}
font->rebuildGlyphLookupTable();
return font;
}
TextureFont* LoadTextureFont(const Renderer *r, const fs::path& filename)
{
fs::path localeFilename = LocaleFilename(filename);
ifstream in(localeFilename.string(), ios::in | ios::binary);
if (!in.good())
{
DPRINTF(LOG_LEVEL_ERROR, "Could not open font file %s\n", filename);
return nullptr;
}
return TextureFont::load(r, in);
}

View File

@ -1,111 +0,0 @@
// texturefont.h
//
// Copyright (C) 2001, Chris Laurel <claurel@shatters.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
#ifndef _TEXTUREFONT_H_
#define _TEXTUREFONT_H_
#include <vector>
#include <string>
#include <iostream>
#include <celcompat/filesystem.h>
class Renderer;
class TextureFont
{
TextureFont(const Renderer*);
public:
TextureFont() = delete;
~TextureFont();
float render(wchar_t ch, float xoffset = 0.0f, float yoffset = 0.0f) const;
float render(const std::string& s, float xoffset = 0.0f, float yoffset = 0.0f) const;
int getWidth(const std::string&) const;
int getWidth(int c) const;
int getMaxWidth() const;
int getHeight() const;
int getMaxAscent() const;
void setMaxAscent(int);
int getMaxDescent() const;
void setMaxDescent(int);
short getAdvance(wchar_t c)
{
const Glyph* glyph = getGlyph(c);
if (glyph == nullptr)
glyph = getGlyph((wchar_t) '?');
return glyph->advance;
}
int getTextureName() const;
void bind();
void unbind();
void flush() {};
bool buildTexture();
public:
struct TexCoord
{
float u, v;
};
struct Glyph
{
Glyph(unsigned short _id) : __id(_id) {};
unsigned short __id;
unsigned short width;
unsigned short height;
short x;
short xoff;
short y;
short yoff;
short advance;
TexCoord texCoords[4];
};
enum
{
TxfByte = 0,
TxfBitmap = 1,
};
private:
void addGlyph(const Glyph&);
const TextureFont::Glyph* getGlyph(wchar_t) const;
void rebuildGlyphLookupTable();
private:
const Renderer *renderer;
int maxAscent{ 0 };
int maxDescent{ 0 };
int maxWidth{ 0 };
int texWidth{ 0 };
int texHeight{ 0 };
unsigned char* fontImage{ nullptr };
unsigned int texName{ 0 };
std::vector<Glyph> glyphs;
const Glyph** glyphLookup{ nullptr };
unsigned int glyphLookupTableSize{ 0 };
public:
static TextureFont* load(const Renderer*, std::istream& in);
};
TextureFont* LoadTextureFont(const Renderer*, const fs::path&);
#endif // _TEXTUREFONT_H_