MonoGummi.hxx from gzz at Krugle
Show MonoGummi.hxx syntax highlighted
/*
MonoGummi.hxx
*
* Copyright (c) 2003, Tuomas J. Lukka
*
* This file is part of Gzz.
*
* Gzz is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Gzz 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 Lesser General
* Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with Gzz; if not, write to the Free
* Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*
*
*/
/*
* Written by Tuomas J. Lukka
*/
#include "Gummi.hxx"
#include "ScreenshotGummi.hxx"
#include <algorithm>
namespace MonoGummi {
using namespace Gummi::Font;
using namespace Gummi::Distort;
using ScreenshotGummi::Screenshot;
using Gummi::Rectangle;
using Gummi::Point;
/** A container for fixed-width characters.
*/
class MonoTextContainer {
unsigned width;
unsigned height;
vector<char> chars; // Width x Height
public:
MonoTextContainer(unsigned width, unsigned height) :
width(width), height(height),
chars(width * height) {
}
void setLine(int line, const string &s) {
int l = std::min(width, s.length());
for(int i=0; i<l; i++)
chars[line * width + i] = s[i];
}
char& operator() (unsigned x, unsigned y) {
return chars[x + y * width];
}
template <class Apply, class Param1, class Param2>
void forAll(Apply &apply, Param1 ¶m1, Param2 param2) {
forRect(apply, param1, param2, 0, 0, width-1, height-1);
}
template <class Apply, class Param1, class Param2>
void forRect(Apply &apply, Param1 ¶m1, Param2 param2,
int x0, int y0, int x1, int y1) {
for(int x = x0; x <= x1; x++)
for(int y = y0; y <= y1; y++) {
if(x < 0 || x >= (int)width) continue;
if(y < 0 || y >= (int)height) continue;
char cur = (*this)((unsigned)x, (unsigned)y);
if(cur == 0 || cur == ' ') continue;
apply(param1, param2, x, y, cur);
}
}
};
using Gummi::Font::Font;
using Gummi::Font::Font_Bordered;
class MonoGummiWindow {
typedef PerspectiveLike<Direct> MyDistort;
typedef DenseGlyphs<char> MyDenseGlyphs;
typedef RandomRenderer<MyDenseGlyphs, char> MyRenderer;
/** The size of the window, in pixels.
*/
int pixWidth, pixHeight;
/** The size of the window, in characters.
*/
int charWidth, charHeight;
float scale;
vector<unsigned char> fgColors;
/** The size of the font, in texels.
*/
int fontHeight, fontWidth;
/** The ascent of the font.
*/
int fontYOffs;
MonoTextContainer content;
Screenshot screenshot;
Font *lof;
Font *hif;
MyRenderer *lorend;
MyRenderer *hirend;
MyDistort distort;
bool recreateBg;
public:
MonoGummiWindow(int cwidth, int cheight, Font *lof, Font *hif)
: content(cwidth, cheight), lof(lof), hif(hif) {
hirend = new MyRenderer(hif);
lorend = new MyRenderer(lof);
Glyph aGlyph = hif->getRaster('A');
fontHeight = hif->getLineHeight();
fontWidth = aGlyph.extents.xadvance;
fontYOffs = hif->getLineOffset();
charWidth = cwidth;
charHeight = cheight;
renderLoresContent = true;
renderHiresContent = true;
renderWithScissoring = true;
}
void setLine(int line, const string &s) { content.setLine(line, s); }
void setSize(int pixWidth, int pixHeight) {
this->pixWidth = pixWidth;
this->pixHeight = pixHeight;
}
void reshape(int w, int h) {
pixHeight = h;
pixWidth = w;
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0, w, 0, h);
// glTranslatef(0, h, 0);
// glScalef(1, -1, 1);
glMatrixMode(GL_MODELVIEW);
float scale1 = pixWidth / ((float)charWidth * fontWidth);
float scale2 = pixHeight / ((float)charHeight * fontHeight);
scale = std::min(scale1, scale2);
recreateBg = true;
}
void mouseMovedTo(int x, int y) {
distort.setCursor((int)(x / scale), (int)(y / scale));
}
void mouseDrag(int button, int dx, int dy) {
distort.add(button, dx, dy);
}
template<class T> void operator()(T vertex, MyRenderer *r, unsigned x, unsigned y, char ch) {
r->renderChar(ch, x * fontWidth, y * fontHeight + fontYOffs, vertex);
}
void modes() {
glLoadIdentity();
glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
glEnable(GL_ALPHA_TEST);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glTranslatef(0, pixHeight, 0);
glScalef(scale, - scale , 1);
glColor3f(1, 1, 1);
}
void createBackground() {
glClear(GL_COLOR_BUFFER_BIT);
modes();
Direct dir;
lorend->startRendering();
content.forAll(*this, dir, lorend);
lorend->endRendering();
screenshot.update(pixWidth, pixHeight);
}
/** Return the coordinates of the character into which
* the given texel-coordinate point falls.
*/
Point<int> mapTexelToChar(Point<int> in) {
return Point<int>(in.x / fontWidth, in.y / fontHeight);
}
bool renderLoresContent;
bool renderHiresContent;
bool renderWithScissoring;
void updateDisplay() {
if(recreateBg) {
createBackground();
recreateBg = false;
}
glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity();
glRasterPos2i(0, 0);
glColor3f(1, 1, 1);
glDisable(GL_TEXTURE_2D);
glBegin(GL_TRIANGLES);
glColor4f(1, 0, 0, 0.4);
glVertex2i(50, 50);
glColor4f(0, 1, 0, 0.4);
glVertex2i(200, 50);
glColor4f(0, 0, 1, 0.4);
glVertex2i(50, 200);
glEnd();
modes();
if(renderLoresContent) {
screenshot.drawDistorted(0, 0, pixWidth, pixHeight,
0, 0, int(pixWidth / scale), int(pixHeight / scale),
100, distort);
}
Rectangle<int> r = distort.getLODBounds();
Rectangle<int> outr = distort.getLODBoundsOut();
Point<int> ul = mapTexelToChar(r.ul());
Point<int> lr = mapTexelToChar(r.lr());
if(renderWithScissoring) {
glEnable(GL_SCISSOR_TEST);
glScissor(int(scale * outr.x),
int(pixHeight - scale * (outr.y+outr.h)),
int(scale * outr.w),
int(scale * outr.h));
glClear(GL_COLOR_BUFFER_BIT);
}
if(renderHiresContent) {
hirend->startRendering();
content.forRect(*this, distort, hirend,
ul.x,
ul.y,
lr.x,
lr.y);
hirend->endRendering();
}
glDisable(GL_SCISSOR_TEST);
/*
screenshot.draw();
*/
/*
Rectangle<int> r = distort.getMagBounds();
Point<int> ul = mapTexelToChar(r.ul());
Point<int> lr = mapTexelToChar(r.lr());
cout << "Magbounds: "<<r<<" trans "<<ul<<" "<<lr<<"\n";
ft8->startRendering();
content.forRect(*this, distort,
ul.x,
ul.y,
lr.x,
lr.y);
ft8->endRendering();
*/
}
};
}
See more files for this project here