Page MenuHomePhabricator (Chris)

No OneTemporary

Authored By
Unknown
Size
70 KB
Referenced Files
None
Subscribers
None
diff --git a/util/allegro5/bitmap.cpp b/util/allegro5/bitmap.cpp
index 61a3ec99..3d57d509 100644
--- a/util/allegro5/bitmap.cpp
+++ b/util/allegro5/bitmap.cpp
@@ -1,732 +1,786 @@
#include <sstream>
#include <allegro5/allegro_memfile.h>
#include <allegro5/allegro_primitives.h>
#include "util/debug.h"
namespace Graphics{
static const int rgb_r_shift_16 = 0;
static const int rgb_g_shift_16 = 5;
static const int rgb_b_shift_16 = 11;
static inline int pack565(unsigned char red, unsigned char green, unsigned char blue){
return (((red >> 3) << rgb_r_shift_16) |
((green >> 2) << rgb_g_shift_16) |
((blue >> 3) << rgb_b_shift_16));
}
/* from allegro4 */
static inline void unpack565(int color, unsigned char * red, unsigned char * green, unsigned char * blue){
static int _rgb_scale_5[32] = {
0, 8, 16, 24, 33, 41, 49, 57,
66, 74, 82, 90, 99, 107, 115, 123,
132, 140, 148, 156, 165, 173, 181, 189,
198, 206, 214, 222, 231, 239, 247, 255
};
static int _rgb_scale_6[64] = {
0, 4, 8, 12, 16, 20, 24, 28,
32, 36, 40, 44, 48, 52, 56, 60,
65, 69, 73, 77, 81, 85, 89, 93,
97, 101, 105, 109, 113, 117, 121, 125,
130, 134, 138, 142, 146, 150, 154, 158,
162, 166, 170, 174, 178, 182, 186, 190,
195, 199, 203, 207, 211, 215, 219, 223,
227, 231, 235, 239, 243, 247, 251, 255
};
*red = _rgb_scale_5[(color >> rgb_r_shift_16) & 0x1F];
*green = _rgb_scale_6[(color >> rgb_g_shift_16) & 0x3F];
*blue = _rgb_scale_5[(color >> rgb_b_shift_16) & 0x1F];
}
+struct BlendingData{
+ BlendingData():
+ red(0), green(0), blue(0), alpha(0){
+ }
+
+ int red, green, blue, alpha;
+};
+
+static BlendingData globalBlend;
+
Color makeColorAlpha(unsigned char red, unsigned char green, unsigned char blue, unsigned char alpha){
return al_map_rgba(red, blue, green, alpha);
}
Color MaskColor(){
- static Color mask = makeColorAlpha(255, 0, 255, 0);
+ static Color mask = makeColorAlpha(0, 0, 0, 0);
return mask;
}
+Color getBlendColor(){
+ return makeColorAlpha(255, 255, 255, globalBlend.alpha);
+}
+
+class Blender{
+public:
+ Blender(){
+ }
+
+ virtual ~Blender(){
+ /* default is to draw the source and ignore the destination */
+ al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_ZERO);
+ }
+};
+
+class MaskedBlender: public Blender {
+public:
+ MaskedBlender(){
+ al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_ZERO);
+ }
+};
+
+class TransBlender: public Blender {
+public:
+ TransBlender(){
+ // al_set_blender(ALLEGRO_ADD, ALLEGRO_ALPHA, ALLEGRO_ONE);
+ al_set_blender(ALLEGRO_ADD, ALLEGRO_ALPHA, ALLEGRO_INVERSE_ALPHA);
+ }
+};
+
static const int WINDOWED = 0;
static const int FULLSCREEN = 1;
static Bitmap * Scaler = NULL;
Bitmap::Bitmap():
own(NULL),
mustResize(false),
bit8MaskColor(makeColor(0, 0, 0)){
/* TODO */
}
Bitmap::Bitmap( const char * load_file ):
own(NULL),
mustResize(false),
bit8MaskColor(makeColor(0, 0, 0)){
internalLoadFile(load_file);
}
Bitmap::Bitmap( const std::string & load_file ):
own(NULL),
mustResize(false),
bit8MaskColor(makeColor(0, 0, 0)){
internalLoadFile(load_file.c_str());
}
Bitmap::Bitmap(ALLEGRO_BITMAP * who, bool deep_copy):
own(NULL),
mustResize(false),
bit8MaskColor(makeColor(0, 0, 0)){
if (deep_copy){
ALLEGRO_BITMAP * clone = al_clone_bitmap(who);
getData().setBitmap(clone);
own = new int;
*own = 1;
} else {
getData().setBitmap(who);
}
}
Bitmap::Bitmap(int width, int height):
own(NULL),
mustResize(false),
bit8MaskColor(makeColor(0, 0, 0)){
ALLEGRO_BITMAP * bitmap = al_create_bitmap(width, height);
if (bitmap == NULL){
std::ostringstream out;
out << "Could not create bitmap with dimensions " << width << ", " << height;
throw BitmapException(__FILE__, __LINE__, out.str());
}
getData().setBitmap(bitmap);
own = new int;
*own = 1;
}
Bitmap::Bitmap( const Bitmap & copy, bool deep_copy):
own(NULL),
mustResize(false),
bit8MaskColor(copy.bit8MaskColor){
if (deep_copy){
ALLEGRO_BITMAP * clone = al_clone_bitmap(copy.getData().getBitmap());
getData().setBitmap(clone);
own = new int;
*own = 1;
} else {
getData().setBitmap(copy.getData().getBitmap());
own = copy.own;
if (own){
*own += 1;
}
}
}
enum Format{
PNG,
GIF,
};
Bitmap Bitmap::memoryPCX(unsigned char * const data, const int length, const bool mask){
/* TODO */
return Bitmap();
}
void Bitmap::replaceColor(Color original, Color replaced){
/* TODO */
}
static ALLEGRO_BITMAP * memoryGIF(const char * data, int length){
ALLEGRO_FILE * memory = al_open_memfile((void *) data, length, "r");
al_fclose(memory);
/* FIXME: get gif addon for a5 */
#if 0
RGB * palette = NULL;
/* algif will close the packfile for us in both error and success cases */
BITMAP * gif = load_gif_packfile(pack, palette);
if (!gif){
al_fclose(memory);
// pack_fclose(pack);
ostringstream out;
out <<"Could not load gif from memory: " << (void*) data << " length " << length;
throw LoadException(__FILE__, __LINE__, out.str());
}
BITMAP * out = create_bitmap(gif->w, gif->h);
blit(gif, out, 0, 0, 0, 0, gif->w, gif->h);
destroy_bitmap(gif);
// pack_fclose(pack);
#endif
ALLEGRO_BITMAP * out = NULL;
return out;
}
void Bitmap::internalLoadFile(const char * path){
this->path = path;
ALLEGRO_BITMAP * loaded = al_load_bitmap(path);
if (loaded == NULL){
std::ostringstream out;
out << "Could not load file '" << path << "'";
throw BitmapException(__FILE__, __LINE__, out.str());
}
getData().setBitmap(loaded);
/*
ALLEGRO_BITMAP * loaded = IMG_Load(path);
if (loaded){
getData().setSurface(optimizedSurface(loaded));
SDL_FreeSurface(loaded);
} else {
std::ostringstream out;
out << "Could not load file '" << path << "'";
throw BitmapException(__FILE__, __LINE__, out.str());
}
*/
own = new int;
*own = 1;
}
static ALLEGRO_BITMAP * load_bitmap_from_memory(const char * data, int length, Format type){
switch (type){
case PNG : {
break;
}
case GIF : {
return memoryGIF(data, length);
break;
}
}
throw Exception::Base(__FILE__, __LINE__);
}
Bitmap::Bitmap(const char * data, int length):
own(NULL),
mustResize(false),
bit8MaskColor(makeColor(0, 0, 0)){
Format type = GIF;
getData().setBitmap(load_bitmap_from_memory(data, length, type));
if (getData().getBitmap() == NULL){
std::ostringstream out;
out << "Could not create bitmap from memory";
throw BitmapException(__FILE__, __LINE__, out.str());
}
own = new int;
*own = 1;
}
Bitmap::Bitmap( const Bitmap & copy, int x, int y, int width, int height ):
own(NULL),
mustResize(false),
bit8MaskColor(copy.bit8MaskColor){
path = copy.getPath();
ALLEGRO_BITMAP * his = copy.getData().getBitmap();
if (x < 0)
x = 0;
if (y < 0)
y = 0;
if (width + x > al_get_bitmap_width(his)){
width = al_get_bitmap_width(his) - x;
}
if (height + y > al_get_bitmap_height(his)){
height = al_get_bitmap_height(his) - y;
}
ALLEGRO_BITMAP * sub = al_create_sub_bitmap(his, x, y, width, height);
getData().setBitmap(sub);
own = new int;
*own = 1;
}
int Bitmap::getWidth() const {
if (getData().getBitmap() != NULL){
return al_get_bitmap_width(getData().getBitmap());
}
return 0;
}
int getRed(Color color){
unsigned char red, green, blue;
al_unmap_rgb(color, &red, &green, &blue);
return red;
}
int getGreen(Color color){
unsigned char red, green, blue;
al_unmap_rgb(color, &red, &green, &blue);
return green;
}
int getBlue(Color color){
unsigned char red, green, blue;
al_unmap_rgb(color, &red, &green, &blue);
return blue;
}
Color makeColor(int red, int blue, int green){
return al_map_rgb(red, blue, green);
}
int Bitmap::getHeight() const {
if (getData().getBitmap() != NULL){
return al_get_bitmap_height(getData().getBitmap());
}
return 0;
}
void initializeExtraStuff(){
al_set_new_bitmap_format(ALLEGRO_PIXEL_FORMAT_RGB_565);
}
int setGraphicsMode(int mode, int width, int height){
initializeExtraStuff();
switch (mode){
case FULLSCREEN: {
al_set_new_display_flags(ALLEGRO_FULLSCREEN);
break;
}
case WINDOWED: {
al_set_new_display_flags(ALLEGRO_WINDOWED | ALLEGRO_RESIZABLE);
break;
}
default: break;
}
ALLEGRO_DISPLAY * display = al_create_display(width, height);
if (display == NULL){
std::ostringstream out;
out << "Could not create display with dimensions " << width << ", " << height;
throw BitmapException(__FILE__, __LINE__, out.str());
}
Screen = new Bitmap(al_get_backbuffer(display));
Scaler = new Bitmap(width, height);
+ /* default drawing mode */
+ al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_ZERO);
return 0;
}
Color Bitmap::getPixel(const int x, const int y) const {
return al_get_pixel(getData().getBitmap(), x, y);
// Color color = al_get_pixel(getData().getBitmap(), x, y);
// return pack565(color.r, color.g, color.b);
}
void Bitmap::putPixel(int x, int y, Color pixel) const {
- /* TODO */
+ al_set_target_bitmap(getData().getBitmap());
+ al_put_pixel(x, y, pixel);
}
void Bitmap::putPixelNormal(int x, int y, Color col) const {
putPixel(x, y, col);
}
void Bitmap::fill(Color color) const {
/*
unsigned char red, green, blue;
unpack565(color, &red, &green, &blue);
al_set_target_bitmap(getData().getBitmap());
al_clear_to_color(al_map_rgb(red, green, blue));
*/
al_set_target_bitmap(getData().getBitmap());
al_clear_to_color(color);
}
-void Bitmap::transBlender( int r, int g, int b, int a ){
- /* TODO */
- /*
+void Bitmap::transBlender(int r, int g, int b, int a){
globalBlend.red = r;
globalBlend.green = g;
globalBlend.blue = b;
globalBlend.alpha = a;
- globalBlend.currentBlender = ::transBlender;
- */
}
void Bitmap::Stretch( const Bitmap & where, const int sourceX, const int sourceY, const int sourceWidth, const int sourceHeight, const int destX, const int destY, const int destWidth, const int destHeight ) const {
/* TODO */
}
void Bitmap::StretchBy2( const Bitmap & where ){
/* TODO */
}
void Bitmap::StretchBy4( const Bitmap & where ){
/* TODO */
}
void Bitmap::drawRotate( const int x, const int y, const int angle, const Bitmap & where ){
/* TODO */
}
void Bitmap::drawPivot( const int centerX, const int centerY, const int x, const int y, const int angle, const Bitmap & where ){
/* TODO */
}
void Bitmap::drawPivot( const int centerX, const int centerY, const int x, const int y, const int angle, const double scale, const Bitmap & where ){
/* TODO */
}
void Bitmap::drawStretched( const int x, const int y, const int new_width, const int new_height, const Bitmap & who ) const {
/* TODO */
}
void Bitmap::Blit(const int mx, const int my, const int width, const int height, const int wx, const int wy, const Bitmap & where) const {
// double start = al_get_time();
al_set_target_bitmap(where.getData().getBitmap());
// al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_ZERO);
/*
if (&where != Screen){
al_draw_bitmap(getData().getBitmap(), wx, wy, 0);
}
*/
- al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_ZERO);
+
+ // al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_ZERO);
al_draw_bitmap(getData().getBitmap(), wx, wy, 0);
/*
double end = al_get_time();
Global::debug(0) << "Draw in " << (end - start) << " seconds" << std::endl;
*/
}
void Bitmap::drawHFlip(const int x, const int y, const Bitmap & where) const {
/* TODO */
}
void Bitmap::drawHFlip(const int x, const int y, Filter * filter, const Bitmap & where) const {
/* TODO */
}
void Bitmap::drawVFlip( const int x, const int y, const Bitmap & where ) const {
/* TODO */
}
void Bitmap::drawVFlip( const int x, const int y, Filter * filter, const Bitmap & where ) const {
/* TODO */
}
void Bitmap::drawHVFlip( const int x, const int y, const Bitmap & where ) const {
/* TODO */
}
void Bitmap::drawHVFlip( const int x, const int y, Filter * filter, const Bitmap & where ) const {
/* TODO */
}
void Bitmap::BlitMasked(const int mx, const int my, const int width, const int height, const int wx, const int wy, const Bitmap & where) const {
/* TODO */
}
void Bitmap::BlitToScreen(const int upper_left_x, const int upper_left_y) const {
#if 0
if (getWidth() != Screen->getWidth() || getHeight() != Screen->getHeight()){
/*
this->Blit( upper_left_x, upper_left_y, *Buffer );
Buffer->Stretch(*Scaler);
Scaler->Blit(0, 0, 0, 0, *Screen);
*/
this->Stretch(*Scaler, 0, 0, getWidth(), getHeight(), upper_left_x, upper_left_y, Scaler->getWidth(), Scaler->getHeight());
Scaler->Blit(0, 0, 0, 0, *Screen);
} else {
this->Blit(upper_left_x, upper_left_y, *Screen);
}
#endif
/*
if (&where == Screen){
al_flip_display();
}
*/
al_flip_display();
}
void Bitmap::BlitAreaToScreen(const int upper_left_x, const int upper_left_y) const {
/* TODO */
}
void Bitmap::draw(const int x, const int y, const Bitmap & where) const {
+ // TransBlender blender;
+ MaskedBlender blender;
al_set_target_bitmap(where.getData().getBitmap());
/* any source pixels with an alpha value of 0 will be masked */
- al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_ALPHA);
al_draw_bitmap(getData().getBitmap(), x, y, 0);
}
void Bitmap::draw(const int x, const int y, Filter * filter, const Bitmap & where) const {
/* TODO */
}
void Bitmap::hLine( const int x1, const int y, const int x2, const Color color ) const {
/* TODO */
}
void Bitmap::vLine( const int x1, const int y, const int x2, const Color color ) const {
/* TODO */
}
void Bitmap::arc(const int x, const int y, const double ang1, const double ang2, const int radius, const Color color ) const {
/* TODO */
}
void Bitmap::floodfill( const int x, const int y, const Color color ) const {
/* TODO */
}
void Bitmap::line( const int x1, const int y1, const int x2, const int y2, const Color color ) const {
/* TODO */
}
void Bitmap::circleFill(int x, int y, int radius, Color color) const {
- /* TODO */
+ al_set_target_bitmap(getData().getBitmap());
+ al_draw_filled_circle(x, y, radius, color);
}
void Bitmap::circle(int x, int y, int radius, Color color) const {
- /* TODO */
+ al_set_target_bitmap(getData().getBitmap());
+ al_draw_circle(x, y, radius, color, 0);
}
void Bitmap::rectangle( int x1, int y1, int x2, int y2, Color color ) const {
al_set_target_bitmap(getData().getBitmap());
al_draw_rectangle(x1, y1, x2, y2, color, 0);
}
void Bitmap::rectangleFill( int x1, int y1, int x2, int y2, Color color ) const {
/*
unsigned char red, green, blue;
unpack565(color, &red, &green, &blue);
*/
al_set_target_bitmap(getData().getBitmap());
al_draw_filled_rectangle(x1, y1, x2, y2, color);
}
void Bitmap::triangle( int x1, int y1, int x2, int y2, int x3, int y3, Color color ) const {
/* TODO */
}
void Bitmap::polygon( const int * verts, const int nverts, const Color color ) const {
/* TODO */
}
void Bitmap::ellipse( int x, int y, int rx, int ry, Color color ) const {
/* TODO */
}
void Bitmap::ellipseFill( int x, int y, int rx, int ry, Color color ) const {
/* TODO */
}
void Bitmap::applyTrans(const Color color) const {
/* TODO */
}
void Bitmap::light(int x, int y, int width, int height, int start_y, int focus_alpha, int edge_alpha, int focus_color, Color edge_color) const {
/* TODO */
}
void Bitmap::drawCharacter( const int x, const int y, const int color, const int background, const Bitmap & where ) const {
/* TODO */
}
void Bitmap::save( const std::string & str ) const {
/* TODO */
}
void Bitmap::readLine(std::vector<Color> & line, int y){
/* TODO */
}
void TranslucentBitmap::draw(const int x, const int y, const Bitmap & where) const {
- /* FIXME */
+ TransBlender blender;
al_set_target_bitmap(where.getData().getBitmap());
- // al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_ONE);
- al_draw_bitmap(getData().getBitmap(), x, y, 0);
+ al_draw_tinted_bitmap(getData().getBitmap(), getBlendColor(), x, y, 0);
}
void LitBitmap::draw( const int x, const int y, const Bitmap & where ) const {
/* TODO */
}
void LitBitmap::draw( const int x, const int y, Filter * filter, const Bitmap & where ) const {
/* TODO */
}
void LitBitmap::drawHFlip( const int x, const int y, const Bitmap & where ) const {
/* TODO */
}
void LitBitmap::drawHFlip( const int x, const int y, Filter * filter, const Bitmap & where ) const {
/* TODO */
}
void LitBitmap::drawVFlip( const int x, const int y, const Bitmap & where ) const {
/* TODO */
}
void LitBitmap::drawVFlip( const int x, const int y, Filter * filter, const Bitmap & where ) const {
/* TODO */
}
void LitBitmap::drawHVFlip( const int x, const int y, const Bitmap & where ) const {
/* TODO */
}
void LitBitmap::drawHVFlip( const int x, const int y, Filter * filter, const Bitmap & where ) const {
/* TODO */
}
void TranslucentBitmap::draw( const int x, const int y, Filter * filter, const Bitmap & where ) const {
/* TODO */
}
void TranslucentBitmap::drawHFlip( const int x, const int y, const Bitmap & where ) const {
/* TODO */
}
void TranslucentBitmap::drawHFlip( const int x, const int y, Filter * filter, const Bitmap & where ) const {
/* TODO */
}
void TranslucentBitmap::drawVFlip( const int x, const int y, const Bitmap & where ) const {
/* TODO */
}
void TranslucentBitmap::drawVFlip( const int x, const int y, Filter * filter, const Bitmap & where ) const {
/* TODO */
}
void TranslucentBitmap::drawHVFlip( const int x, const int y, const Bitmap & where ) const {
/* TODO */
}
void TranslucentBitmap::drawHVFlip( const int x, const int y, Filter * filter,const Bitmap & where ) const {
/* TODO */
}
void TranslucentBitmap::hLine( const int x1, const int y, const int x2, const Color color ) const {
/* TODO */
}
void TranslucentBitmap::circleFill(int x, int y, int radius, Color color) const {
/* TODO */
}
+Color doTransBlend(const Color & color, int alpha){
+ float red, green, blue;
+ float alpha_f = alpha / 255.0;
+ al_unmap_rgb_f(color, &red, &green, &blue);
+ red *= alpha_f;
+ green *= alpha_f;
+ blue *= alpha_f;
+ return al_map_rgb_f(red, green, blue);
+}
+
void TranslucentBitmap::putPixelNormal(int x, int y, Color color) const {
- /* TODO */
+ TransBlender blender;
+ al_set_target_bitmap(getData().getBitmap());
+ al_put_pixel(x, y, doTransBlend(color, globalBlend.alpha));
}
void TranslucentBitmap::rectangle( int x1, int y1, int x2, int y2, Color color ) const {
/* TODO */
}
void TranslucentBitmap::rectangleFill(int x1, int y1, int x2, int y2, Color color) const {
/* TODO */
}
void TranslucentBitmap::ellipse( int x, int y, int rx, int ry, Color color ) const {
/* TODO */
}
Bitmap & Bitmap::operator=(const Bitmap & copy){
releaseInternalBitmap();
path = copy.getPath();
getData().setBitmap(copy.getData().getBitmap());
// own = false;
own = copy.own;
if (own)
*own += 1;
return *this;
}
void Bitmap::setClipRect( int x1, int y1, int x2, int y2 ) const {
/* TODO */
}
void Bitmap::getClipRect(int & x1, int & y1, int & x2, int & y2) const {
/* TODO */
}
void Bitmap::destroyPrivateData(){
al_destroy_bitmap(getData().getBitmap());
}
int setGfxModeFullscreen(int x, int y){
return setGraphicsMode(FULLSCREEN, x, y);
}
int setGfxModeWindowed( int x, int y ){
return setGraphicsMode(WINDOWED, x, y);
}
int setGfxModeText(){
/* TODO */
return 0;
}
bool Bitmap::getError(){
/* TODO */
return false;
}
void Bitmap::addBlender( int r, int g, int b, int a ){
/* TODO */
}
void Bitmap::differenceBlender( int r, int g, int b, int a ){
/* TODO */
}
void Bitmap::multiplyBlender( int r, int g, int b, int a ){
/* TODO */
}
void Bitmap::drawingMode(int type){
/* TODO */
}
void Bitmap::shutdown(){
delete Screen;
Screen = NULL;
/*
delete Scaler;
Scaler = NULL;
delete Buffer;
Buffer = NULL;
*/
}
Bitmap getScreenBuffer(){
return *Screen;
}
}
static bool sameColor(Graphics::Color color1, Graphics::Color color2){
unsigned char r1, g1, b1, a1;
unsigned char r2, g2, b2, a2;
al_unmap_rgba(color1, &r1, &g1, &b1, &a1);
al_unmap_rgba(color2, &r2, &g2, &b2, &a2);
return r1 == r2 &&
g1 == g2 &&
b1 == b2 &&
a1 == a2;
}
static uint32_t quantify(const ALLEGRO_COLOR & color){
unsigned char red, green, blue, alpha;
al_unmap_rgba(color, &red, &green, &blue, &alpha);
return (red << 24) |
(green << 16) |
(blue << 8) |
alpha;
}
bool operator<(const ALLEGRO_COLOR color1, const ALLEGRO_COLOR color2){
return quantify(color1) < quantify(color2);
}
bool operator!=(const ALLEGRO_COLOR color1, const ALLEGRO_COLOR color2){
return !(color1 == color2);
}
bool operator==(const ALLEGRO_COLOR color1, const ALLEGRO_COLOR color2){
return sameColor(color1, color2);
}
diff --git a/util/font.cpp b/util/font.cpp
index b45a3c64..4e5725de 100644
--- a/util/font.cpp
+++ b/util/font.cpp
@@ -1,306 +1,302 @@
#ifdef USE_ALLEGRO
/* for textout_* and whatnot */
#include <allegro.h>
#endif
#include "bitmap.h"
#include "font.h"
#include "funcs.h"
#include "init.h"
#include "ftalleg.h"
#include "factory/font_factory.h"
#include <string.h>
using namespace std;
Font::Font(){
}
/* copy/pasted from network/message.cpp */
static vector< string > wrapStrings( const string & left, const string & right, const Font & font, int max, vector< string > accum ){
if ( left == "" ){
return accum;
}
int length = font.textLength(left.c_str());
if (length >= max){
return wrapStrings( left.substr( 0, left.length() / 2 ), left.substr( left.length() / 2 ) + right, font, max, accum );
} else if ( length >= max - font.textLength( "E" ) || right == "" ){
accum.push_back( left );
return wrapStrings( right, "", font, max, accum );
} else {
return wrapStrings( left + right.substr( 0, 1 ), right.substr( 1 ), font, max, accum );
}
}
void Font::printfWrapLine(int x, int & y, Graphics::Color color, const Graphics::Bitmap & work, int maxWidth, const char * line) const {
vector< string > all;
all = wrapStrings(string(line), "", *this, maxWidth, all );
for ( vector< string >::iterator str = all.begin(); str != all.end(); str++ ){
printf(x, y, color, work, *str, 0);
y += getHeight();
}
y += getHeight() / 2;
}
#if 0
void Font::printfWrapLine2(int x, int & y, int color, const Bitmap & work, int maxWidth, const char * line) const {
int height = getHeight();
while (*line != '\0'){
char tmp2[1024];
int left = strlen(line);
int min = 0;
int max = left;
int current = (min + max) / 2;
strncpy(tmp2, line, current);
tmp2[current] = '\0';
bool done = false;
while (!done){
int length = textLength(tmp2);
if (length >= maxWidth){
max = current;
current = (min + max) / 2;
strncpy(tmp2, line, current);
tmp2[current] = '\0';
} else if (length < maxWidth && current < max){
min = current;
current = (min + max) / 2;
if (current == max - 1){
current = max;
done = true;
}
strncpy(tmp2, line, current);
tmp2[current] = '\0';
} else {
done = true;
}
}
printf(x, y, color, work, string(tmp2), 0);
y += height;
line += current;
}
y += height / 2;
}
#endif
void Font::printfWrap(int x, int y, Graphics::Color color, const Graphics::Bitmap & work, int maxWidth, const std::string & str, int marker, ... ) const {
char buf[4096];
va_list ap;
va_start(ap, marker);
Util::limitPrintf(buf, sizeof(buf), str.c_str(), ap);
va_end(ap);
char * start = buf;
char * end = strchr(start, '\n');
while (end != NULL){
char tmp[1024];
unsigned int ender = end - start;
if (ender >= sizeof(tmp) - 1){
ender = sizeof(tmp) - 1;
}
strncpy(tmp, start, ender);
tmp[ender] = '\0';
printfWrapLine(x, y, color, work, maxWidth, tmp);
start = end + 1;
end = strchr(start, '\n');
}
printfWrapLine(x, y, color, work, maxWidth, start);
}
Font::~Font(){
}
#ifdef USE_ALLEGRO
AllegroFont::AllegroFont( const FONT * const font ):
font(font){
}
AllegroFont::AllegroFont( const AllegroFont & copy ):
font( copy.getInternalFont() ){
}
AllegroFont::~AllegroFont(){
}
int AllegroFont::textLength( const char * text ) const{
return text_length( getInternalFont(), text );
}
int AllegroFont::getHeight( const string & str ) const {
return getHeight();
}
int AllegroFont::getHeight() const {
return text_height( getInternalFont() );
}
void AllegroFont::setSize( const int x, const int y ){
}
int AllegroFont::getSizeX() const {
return 0;
}
int AllegroFont::getSizeY() const {
return 0;
}
void AllegroFont::printf( int x, int y, int xSize, int ySize, int color, const Graphics::Bitmap & work, const string & str, int marker, ... ) const {
char buf[512];
va_list ap;
va_start(ap, marker);
Util::limitPrintf(buf, sizeof(buf), str.c_str(), ap);
va_end(ap);
textout_ex(work.getData().getBitmap(), getInternalFont(), buf, x, y, color, -1);
}
void AllegroFont::printf( int x, int y, int color, const Graphics::Bitmap & work, const string & str, int marker, ... ) const {
char buf[512];
va_list ap;
va_start(ap, marker);
uvszprintf(buf, sizeof(buf), str.c_str(), ap);
va_end(ap);
textout_ex(work.getData().getBitmap(), getInternalFont(), buf, x, y, color, -1);
}
#endif
const Font & Font::getDefaultFont(){
// return getFont( "tmp/comic.ttf" );
// return *FontFactory::getFont(Filesystem::RelativePath("bios"), 16, 16);
return *FontFactory::getFont(Filesystem::RelativePath("fonts/arial.ttf"), 16, 16);
}
const Font & Font::getDefaultFont(int width, int height){
return *FontFactory::getFont(Filesystem::RelativePath("fonts/arial.ttf"), width, height);
}
/* name should be the path of a .ttf file in the fonts/ directory.
* something like 'arial.ttf'
*/
const Font & Font::getFont(const Filesystem::RelativePath & name, const int x, const int y){
Font & font = *FontFactory::getFont(name, x, y);
/* sanity check */
if (font.getHeight("A") == 0){
return getDefaultFont();
}
return font;
}
const Font & Font::getFont( const Filesystem::AbsolutePath & name, const int x, const int y){
return *FontFactory::getFont(name, x, y);
}
FreeTypeFont::FreeTypeFont(const Filesystem::AbsolutePath & str ):
-sizeX( 16 ),
-sizeY( 16 ),
+sizeX(16),
+sizeY(16),
own(true){
- this->font = new ftalleg::freetype(str, getSizeX(), getSizeY() );
+ this->font = new ftalleg::freetype(str, getSizeX(), getSizeY() );
}
int FreeTypeFont::getHeight( const string & str ) const {
- return this->font->getHeight( str );
+ return this->font->getHeight(str);
}
int FreeTypeFont::getHeight() const {
- return getHeight( "A" );
+ return getHeight("A");
}
int FreeTypeFont::textLength( const char * text ) const {
return this->font->getLength(string(text));
}
void FreeTypeFont::printf( int x, int y, int xSize, int ySize, Graphics::Color color, const Graphics::Bitmap & work, const string & str, int marker, ... ) const {
char buf[512];
va_list ap;
va_start(ap, marker);
vsnprintf(buf, sizeof(buf), str.c_str(), ap);
va_end(ap);
int old_x = 0;
int old_y = 0;
this->font->getSize(&old_x, &old_y);
-
this->font->setSize(xSize, ySize);
-
- this->font->render( x, y, color, work, ftalleg::freetype::ftLeft, string( buf ), 0 );
-
+ this->font->render(x, y, color, work, ftalleg::freetype::ftLeft, string(buf), 0);
this->font->setSize(old_x, old_y);
-
}
void FreeTypeFont::printf( int x, int y, Graphics::Color color, const Graphics::Bitmap & work, const string & str, int marker, ... ) const {
char buf[512];
va_list ap;
va_start(ap, marker);
vsnprintf(buf, sizeof(buf), str.c_str(), ap);
va_end(ap);
this->font->render(x, y, color, work, ftalleg::freetype::ftLeft, string(buf), 0);
}
void FreeTypeFont::setSize( const int x, const int y ){
this->sizeX = x;
this->sizeY = y;
this->font->setSize( this->sizeX, this->sizeY );
}
int FreeTypeFont::getSizeX() const {
return this->sizeX;
}
int FreeTypeFont::getSizeY() const {
return this->sizeY;
}
FreeTypeFont::~FreeTypeFont(){
// cout << "Delete font " << this->font << endl;
if (own){
delete this->font;
}
}
NullFont::NullFont(){
}
NullFont::~NullFont(){
}
void NullFont::setSize( const int x, const int y ){
}
int NullFont::getSizeX() const {
return 0;
}
int NullFont::getSizeY() const {
return 0;
}
int NullFont::textLength( const char * text ) const {
return 0;
}
int NullFont::getHeight( const std::string & str ) const {
return 0;
}
int NullFont::getHeight() const {
return 0;
}
void NullFont::printf( int x, int y, int xSize, int ySize, Graphics::Color color, const Graphics::Bitmap & work, const std::string & str, int marker, ... ) const {
}
void NullFont::printf( int x, int y, Graphics::Color color, const Graphics::Bitmap & work, const std::string & str, int marker, ... ) const {
}
diff --git a/util/font.h b/util/font.h
index 73f2e694..3a92e062 100644
--- a/util/font.h
+++ b/util/font.h
@@ -1,120 +1,120 @@
#ifndef _paintown_font_h
#define _paintown_font_h
#include <string>
#include <vector>
#include "bitmap.h"
// #include "ftalleg.h"
struct FONT;
namespace ftalleg{
class freetype;
}
namespace Filesystem{
class RelativePath;
class AbsolutePath;
}
/* handle allegro fonts and true type fonts */
class Font{
public:
Font();
virtual ~Font();
virtual void setSize( const int x, const int y ) = 0;
virtual int getSizeX() const = 0;
virtual int getSizeY() const = 0;
virtual int textLength( const char * text ) const = 0;
virtual int getHeight( const std::string & str ) const = 0;
virtual int getHeight() const = 0;
virtual void printf( int x, int y, int xSize, int ySize, Graphics::Color color, const Graphics::Bitmap & work, const std::string & str, int marker, ... ) const = 0;
virtual void printf( int x, int y, Graphics::Color color, const Graphics::Bitmap & work, const std::string & str, int marker, ... ) const = 0;
virtual void printfWrap( int x, int y, Graphics::Color color, const Graphics::Bitmap & work, int maxWidth, const std::string & str, int marker, ... ) const;
static const Font & getDefaultFont();
static const Font & getDefaultFont(int width, int height);
static const Font & getFont( const Filesystem::RelativePath & name, const int x = 32, const int y = 32 );
static const Font & getFont( const Filesystem::AbsolutePath & name, const int x = 32, const int y = 32 );
/* store all the freetype fonts forever */
// static std::vector< ftalleg::freetype * > cacheFreeType;
protected:
void printfWrapLine(int x, int & y, Graphics::Color color, const Graphics::Bitmap & work, int maxWidth, const char * line) const;
};
class NullFont: public Font {
public:
NullFont();
virtual ~NullFont();
virtual void setSize( const int x, const int y );
virtual int getSizeX() const;
virtual int getSizeY() const;
virtual int textLength( const char * text ) const;
virtual int getHeight( const std::string & str ) const;
virtual int getHeight() const;
virtual void printf( int x, int y, int xSize, int ySize, Graphics::Color color, const Graphics::Bitmap & work, const std::string & str, int marker, ... ) const;
virtual void printf( int x, int y, Graphics::Color color, const Graphics::Bitmap & work, const std::string & str, int marker, ... ) const;
};
#ifdef USE_ALLEGRO
class AllegroFont: public Font {
public:
AllegroFont( const FONT * const font );
AllegroFont( const AllegroFont & copy );
virtual ~AllegroFont();
virtual int getHeight() const;
virtual int getHeight( const std::string & str ) const;
virtual int textLength( const char * text ) const;
virtual void printf( int x, int y, Graphics::Color color, const Graphics::Bitmap & work, const std::string & str, int marker, ... ) const;
virtual void printf( int x, int y, int xSize, int ySize, Graphics::Color color, const Graphics::Bitmap & work, const std::string & str, int marker, ... ) const;
virtual void setSize( const int x, const int y );
virtual int getSizeX() const;
virtual int getSizeY() const;
private:
inline const FONT * getInternalFont() const {
return font;
}
const FONT * const font;
};
#endif
class FreeTypeFont: public Font {
public:
FreeTypeFont(const Filesystem::AbsolutePath & filename);
FreeTypeFont(const FreeTypeFont & copy);
virtual ~FreeTypeFont();
virtual int getHeight() const;
virtual int getHeight( const std::string & str ) const;
virtual int textLength( const char * text ) const;
virtual void printf( int x, int y, Graphics::Color color, const Graphics::Bitmap & work, const std::string & str, int marker, ... ) const;
virtual void printf( int x, int y, int xSize, int ySize, Graphics::Color color, const Graphics::Bitmap & work, const std::string & str, int marker, ... ) const;
virtual void setSize( const int x, const int y );
virtual int getSizeX() const;
virtual int getSizeY() const;
private:
- ftalleg::freetype * font;
- int sizeX;
- int sizeY;
- bool own;
+ ftalleg::freetype * font;
+ int sizeX;
+ int sizeY;
+ bool own;
};
#endif
diff --git a/util/ftalleg.cpp b/util/ftalleg.cpp
index 80172af0..3875494f 100644
--- a/util/ftalleg.cpp
+++ b/util/ftalleg.cpp
@@ -1,598 +1,681 @@
/*
--------------
About
--------------
A Freetype wrapper for use with allegro
Feel free to do whatever you like with this, by all means enjoy!
Just add it to your project
--------------
Linking
--------------
on linux:
g++ `freetype-config --cflags` ftalleg.cpp myfiles.cpp `freetype-config --libs` `allegro-config --libs`
on windows (you may need to include the freetype dir location, ie -Ic:/mingw/include):
g++ ftalleg.cpp myfiles.cpp -lfreetype -lalleg
--------------
Disclaimer
--------------
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE
SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef FT_FONT_CPP
#define FT_FONT_CPP
#include "bitmap.h"
/*
#include <allegro.h>
#ifdef _WIN32
#include <winalleg.h>
#endif
*/
#include "ftalleg.h"
#include <iostream>
#include <sstream>
#include <cassert>
#include <exception>
+#ifdef USE_ALLEGRO5
+#include <allegro5/allegro_font.h>
+#include <allegro5/allegro_ttf.h>
+#endif
namespace ftalleg{
Exception::Exception():
std::exception(){
}
Exception::Exception(const std::string reason):
std::exception(),
reason(reason){
}
Exception::~Exception() throw(){
}
// typedef void (*pixeler)( BITMAP * bitmap, int x, int y, int color );
static Graphics::Color fixColor(const unsigned char c, short grays){
// Safety checks
// assert(c != 0);
assert(grays != 1);
// invariant: c can be dereferenced safely
// invariant: (grays - 1) != 0, thus it can be used as divisor.
int red = c * 255 / (grays - 1);
int green = c * 255 / (grays - 1);
int blue = c * 255 / (grays - 1);
//alpha = *c * 255 / (grays - 1);
return Graphics::makeColor(red,green,blue);
}
// Static count of instances of fonts to track library
static int instances = 0;
static FT_Library ftLibrary = 0;
character::character() {
}
character::~character() {
if (line){
delete [] line;
}
}
fontSize::fontSize() {
width = height = italics = angle = 0;
}
fontSize::~fontSize() {
}
bool fontSize::operator<(const fontSize &fs) const {
return (width<fs.width || height<fs.height || italics<fs.italics);
}
/* im not sure this is a very unique key.. */
int fontSize::createKey() const {
return ((width+10) * (height+20) * (italics+250));
}
+#ifdef USE_ALLEGRO5
+ freetype::freetype(const Filesystem::AbsolutePath & str, const int x, const int y):
+ font(NULL),
+ width(x),
+ height(y){
+ if (instances == 0){
+ al_init_font_addon();
+ al_init_ttf_addon();
+ }
+ instances += 1;
+
+ font = al_load_font(str.path().c_str(), x, 0);
+ }
+
+ freetype::~freetype(){
+ if (font != NULL){
+ al_destroy_font(font);
+ }
+ instances -= 1;
+ if (instances == 0){
+ al_shutdown_font_addon();
+ }
+ }
+
+ int freetype::getHeight(const std::string & str) const {
+ /* sort of a hack but we need to set the display to the screen. with
+ * allegro5 the screen buffer will be the actual screen so no allocation
+ * will occur.
+ */
+ al_set_target_bitmap(Graphics::getScreenBuffer().getData().getBitmap());
+ return al_get_font_line_height(font);
+ }
+
+ int freetype::getLength(const std::string & text) const {
+ al_set_target_bitmap(Graphics::getScreenBuffer().getData().getBitmap());
+ return al_get_text_width(font, text.c_str());
+ }
+
+ void freetype::setSize(unsigned int w, unsigned int h){
+ /* FIXME */
+ }
+
+ void freetype::getSize(int * w, int * h) const {
+ *w = width;
+ *h = height;
+ }
+
+ void freetype::render(int x, int y, const Graphics::Color & color, const Graphics::Bitmap & bmp, ftAlign alignment, const std::string & text, int marker, ...){
+ std::ostringstream str;
+
+ /* use vsnprintf/Util::limitPrintf here? */
+
+ // Get extra arguments
+ va_list ap;
+ va_start(ap, marker);
+ for(unsigned int i = 0; i<text.length();++i) {
+ if (text[i] == '%') {
+ if(text[i+1]=='s') {
+ str << va_arg(ap, char *);
+ ++i;
+ } else if(text[i+1]=='d'||text[i+1]=='i') {
+ str << va_arg(ap, signed int);
+ ++i;
+ } else if(text[i+1]=='c') {
+ str << (char)va_arg(ap, int);
+ ++i;
+ } else str << text[i];
+ } else {
+ str << text[i];
+ }
+ }
+ va_end(ap);
+
+ std::string fixedText(str.str());
+ al_set_target_bitmap(bmp.getData().getBitmap());
+ al_draw_text(font, color, x, y, 0, fixedText.c_str());
+ }
+#else
//! Constructor
freetype::freetype(const Filesystem::AbsolutePath & str, const int x, const int y ):
face(NULL){
//Load library
if (!ftLibrary){
FT_Init_FreeType(&ftLibrary);
}
instances += 1;
faceLoaded = kerning = false;
currentIndex = 0;
currentFilename = "";
faceName = "";
// currentChar = new character;
systemName = "";
internalFix = false;
this->load(str, 0, x, y );
}
//! Destructor
freetype::~freetype(){
//if(face!=NULL)FT_Done_Face(face);
if (faceLoaded && face != NULL){
FT_Done_Face(face);
face = NULL;
}
instances -= 1;
if (instances == 0){
FT_Done_FreeType(ftLibrary);
ftLibrary = NULL;
}
destroyGlyphIndex();
/*
if ( currentChar ){
delete currentChar;
}
*/
}
void freetype::destroyGlyphIndex(){
for (std::map<int, std::map<signed long, character*> >::iterator i1 = fontTable.begin(); i1 != fontTable.end(); i1++){
std::map<signed long, character*> & characters = (*i1).second;
for (std::map<signed long, character*>::iterator i2 = characters.begin(); i2 != characters.end(); i2++){
character * character = (*i2).second;
delete character;
}
}
}
// Extract glyph
character * freetype::extractGlyph(signed long unicode){
int w, h, ew;
character * tempChar = new character();
// Translate it according to the given italics
double italics = (double)(size.italics)*GLYPH_PI/180;
FT_Matrix matrix;
matrix.xx = 0x10000L;
matrix.xy = (FT_Fixed)( sin( italics ) * (GLYPH_SQRT2*0x10000L) );
matrix.yx = 0;
matrix.yy = 0x10000L;
FT_Set_Transform( face, &matrix, 0 );
FT_Load_Char(face, unicode, FT_LOAD_TARGET_NORMAL | FT_LOAD_RENDER | FT_LOAD_FORCE_AUTOHINT);
w = face->glyph->bitmap.width;
h = face->glyph->bitmap.rows;
ew = 0;
if (!w)ew = 1;
if (!h)h = 1;
tempChar->width = (w + ew);
tempChar->height = h;
tempChar->rows = face->glyph->bitmap.rows;
tempChar->grays = face->glyph->bitmap.num_grays;
tempChar->pitch = face->glyph->bitmap.pitch;
tempChar->line = new unsigned char[tempChar->rows * tempChar->pitch];
memcpy(tempChar->line, face->glyph->bitmap.buffer, tempChar->rows * tempChar->pitch);
tempChar->left = face->glyph->bitmap_left;
tempChar->top = face->glyph->bitmap_top;
tempChar->right = face->glyph->advance.x >> 6;
tempChar->unicode = unicode;
tempChar->length = ((w + ew)+face->glyph->advance.x) >> 6;
return tempChar;
}
// Create single index
void freetype::createIndex(){
std::map<int, std::map<signed long, character*> >::iterator p;
p = fontTable.find(size.createKey());
if (p == fontTable.end()){
FT_Set_Pixel_Sizes(face, size.width, size.height);
FT_UInt glyphIndex;
FT_ULong unicode = FT_Get_First_Char(face, &glyphIndex);
std::map<signed long, character*> tempMap;
while (glyphIndex != 0){
tempMap.insert(std::make_pair(unicode, extractGlyph(unicode)));
unicode = FT_Get_Next_Char(face, unicode, &glyphIndex);
}
fontTable.insert(std::make_pair(size.createKey(), tempMap));
}
if (fontTable.find(size.createKey()) == fontTable.end()){
printf("ftalleg: inconsistency error\n");
throw std::exception();
}
}
/*
pixeler getPutPixel(){
switch( get_color_depth() ){
case 8 : return _putpixel;
case 15 : return _putpixel15;
case 16 : return _putpixel16;
case 24 : return _putpixel24;
case 32 : return _putpixel32;
default : return putpixel;
}
}
*/
void drawOneCharacter(const character * tempChar, int & x1, int & y1, FT_UInt sizeHeight, const Graphics::Bitmap & bitmap, const Graphics::Color & color){
unsigned char * line = tempChar->line;
int colorRed = Graphics::getRed(color);
int colorGreen = Graphics::getGreen(color);
int colorBlue = Graphics::getBlue(color);
/* cache the last color, there is a good chance it will be reused */
unsigned char lastData = -1;
short lastGrays = -1;
Graphics::Color black = Graphics::makeColor(0, 0, 0);
Graphics::Color lastColor = black;
for (int y = 0; y < tempChar->rows; y++){
unsigned char * buffer = line;
for (int x = 0; x < tempChar->width; x++){
Graphics::Color finalColor = black;
unsigned char current = *buffer;
buffer++;
if (current == lastData && lastGrays == tempChar->grays){
finalColor = lastColor;
} else {
Graphics::Color col = fixColor(current, tempChar->grays);
int red = Graphics::getRed(col);
int green = Graphics::getGreen(col);
int blue = Graphics::getBlue(col);
if ((red < 50) ||
(green < 50) ||
(blue < 50)){
continue;
}
red = red * colorRed / 255;
green = green * colorGreen / 255;
blue = blue * colorBlue / 255;
finalColor = Graphics::makeColor(red, green, blue);
lastData = current;
lastColor = finalColor;
lastGrays = tempChar->grays;
}
//col.alpha= col.alpha * color.alpha / 255;
// putpixel(bitmap,x1+tempChar.left+x,y1 - tempChar.top+y + size.height,makecol(red,blue,green));
/* dangerous! putter is probably one of the _putpixel* routines so if x or y are off the bitmap
* you will get a segfault
*/
// putter(bitmap,x1+tempChar.left+x,y1 - tempChar.top+y + size.height,makecol(red,blue,green));
// putter = 0;
int finalX = x1+tempChar->left+x;
int finalY = y1 - tempChar->top + y + sizeHeight;
bitmap.putPixelNormal(finalX, finalY, finalColor);
}
line += tempChar->pitch;
}
x1 += tempChar->right;
}
// Render a character from the lookup table
void freetype::drawCharacter(signed long unicode, int &x1, int &y1, const Graphics::Bitmap & bitmap, const Graphics::Color &color){
// pixeler putter = getPutPixel();
std::map<int, std::map<signed long, character*> >::iterator ft;
ft = fontTable.find(size.createKey());
if (ft != fontTable.end()){
std::map<signed long, character*>::iterator p;
p = (ft->second).find(unicode);
if (p != ft->second.end()){
const character * tempChar = p->second;
drawOneCharacter(tempChar, x1, y1, size.height, bitmap, color);
}
}
}
//! Load font from memory
bool freetype::load(const unsigned char *memoryFont, unsigned int length, int index, unsigned int width, unsigned int height) {
if(!FT_New_Memory_Face(ftLibrary,memoryFont, length,index,&face)) {
currentFilename = "memoryFont";
currentIndex = index;
faceLoaded = true;
size.italics = 0;
setSize(width, height);
if (FT_HAS_GLYPH_NAMES(face)){
char buff[1024];
if(!FT_Get_Glyph_Name(face, currentIndex,buff, sizeof(buff))){
faceName = currentFilename;
}
else faceName = std::string(buff);
} else {
faceName = currentFilename;
}
if(FT_HAS_KERNING(face))kerning=true;
else kerning = false;
} else {
faceLoaded=false;
std::cout << "Load system font failed\n";
}
return faceLoaded;
}
//! Load font from file
bool freetype::load(const Filesystem::AbsolutePath & filename, int index, unsigned int width, unsigned int height){
FT_Error error = FT_New_Face(ftLibrary, filename.path().c_str(), index, &face);
if (error == 0){
currentFilename = filename.path();
currentIndex = index;
faceLoaded = true;
size.italics = 0;
setSize(width, height);
if (FT_HAS_GLYPH_NAMES(face)){
char buff[1024];
if (!FT_Get_Glyph_Name(face, currentIndex, buff, sizeof(buff))) {
faceName = currentFilename;
} else {
faceName = std::string(buff);
}
} else {
faceName = currentFilename;
}
kerning = FT_HAS_KERNING(face);
} else {
faceLoaded=false;
}
return faceLoaded;
}
/* utf8 decoding */
static long decodeUnicode(const std::string & input, unsigned int * position){
unsigned char byte1 = (unsigned char) input[*position];
/* one byte - ascii */
if (byte1 >> 7 == 0){
return byte1;
}
if (byte1 >> 5 == 6){
*position += 1;
unsigned char byte2 = (unsigned char) input[*position];
int top = byte1 & 31;
int bottom = byte2 & 63;
return (top << 6) + bottom;
}
if (byte1 >> 4 == 14){
*position += 1;
unsigned char byte2 = (unsigned char) input[*position];
*position += 1;
unsigned char byte3 = (unsigned char) input[*position];
int top4 = byte1 & 15;
int middle6 = byte2 & 63;
int bottom6 = byte3 & 63;
return (top4 << (6+6)) + (middle6 << 6) + bottom6;
}
if (byte1 >> 3 == 30){
*position += 1;
unsigned char byte2 = (unsigned char) input[*position];
*position += 1;
unsigned char byte3 = (unsigned char) input[*position];
*position += 1;
unsigned char byte4 = (unsigned char) input[*position];
int unit1 = byte1 & 7;
int unit2 = byte2 & 63;
int unit3 = byte3 & 63;
int unit4 = byte4 & 63;
return (unit1 << 18) + (unit2 << 12) + (unit3 << 6) + unit4;
}
return 0;
}
//! Get text length
int freetype::getLength(const std::string & text) {
Util::Thread::ScopedLock locked(lock);
int length=0;
std::map<int, std::map<signed long, character*> >::iterator ft;
ft = fontTable.find(size.createKey());
if (ft != fontTable.end()){
for (unsigned int i = 0; i < text.length(); i++) {
std::map<signed long, character*>::iterator p;
signed long unicode = decodeUnicode(text, &i);
p = (ft->second).find(unicode);
if (p != (ft->second).end()){
if (p != fontTable[size.createKey()].end()){
length += (p->second)->length;
}
}
}
}
return length;
}
//! Render font to a bitmap
void freetype::render(int x, int y, const Graphics::Color & color, const Graphics::Bitmap & bmp, ftAlign alignment, const std::string & text, int marker ...) {
if (faceLoaded){
int rend_x = 0;
int rend_y = 0;
std::ostringstream str;
/* use vsnprintf/Util::limitPrintf here? */
// Get extra arguments
va_list ap;
va_start(ap, marker);
for(unsigned int i = 0; i<text.length();++i) {
if (text[i] == '%') {
if(text[i+1]=='s') {
str << va_arg(ap, char *);
++i;
} else if(text[i+1]=='d'||text[i+1]=='i') {
str << va_arg(ap, signed int);
++i;
} else if(text[i+1]=='c') {
str << (char)va_arg(ap, int);
++i;
} else str << text[i];
} else {
str << text[i];
}
}
va_end(ap);
std::string fixedText(str.str());
switch (alignment) {
case ftLeft:
rend_x = x;
rend_y = y;
break;
case ftCenter:
rend_x = x - getLength(fixedText)/2;
rend_y = y;
break;
case ftRight:
rend_x = x - getLength(fixedText);
rend_y = y;
break;
default:
rend_x = x;
rend_y = y;
break;
}
int previous = 0;
int next = 0;
for (unsigned int i = 0; i<fixedText.length(); i++){
long unicode = decodeUnicode(fixedText, &i);
if (kerning && previous && next){
next = FT_Get_Char_Index(face, unicode);
FT_Vector delta;
FT_Get_Kerning(face, previous, next, FT_KERNING_DEFAULT, &delta);
rend_x += delta.x >> 6;
previous = next;
}
drawCharacter(unicode, rend_x, rend_y, bmp, color);
}
}
}
int freetype::calculateMaximumHeight(){
Util::Thread::ScopedLock locked(lock);
/* uhh, comment out the printf's ?? */
std::map<int, std::map<signed long, character*> >::iterator ft;
ft = fontTable.find(size.createKey());
int top = 0;
long code = 0;
if ( ft != fontTable.end() ){
std::map<signed long, character*>::iterator p;
std::map< signed long, character* > & map = ft->second;
for ( p = map.begin(); p != map.end(); p++ ){
const character * ch = p->second;
printf( "%c( %ld ). top = %d. rows = %d. total = %d\n", (char) ch->unicode, ch->unicode, ch->top, ch->rows, ch->top + ch->rows );
if ( ch->top + ch->rows > top ){
code = ch->unicode;
top = ch->top + ch->rows;
}
}
}
printf( "Largest letter = %ld\n", code );
return top;
}
int freetype::height(long code) const {
Util::Thread::ScopedLock locked(lock);
std::map<int, std::map<signed long, character*> >::const_iterator ft;
ft = fontTable.find(size.createKey());
if (ft != fontTable.end()){
std::map<signed long, character*>::const_iterator p;
p = (ft->second).find( code );
if ( p != (ft->second).end() ){
const character * temp = p->second;
// printf( "%c top = %d rows = %d\n", (char) code, temp.top, temp.rows );
return temp->top + temp->rows;
}
} else {
throw Exception("Internal inconsistency");
}
return 0;
}
int freetype::calculateHeight( const std::string & str ) const {
int max = 0;
for ( unsigned int i = 0; i < str.length(); i++ ){
int q = height( str[ i ] );
// printf( "Height of %c is %d\n", str[ i ], q );
if ( q > max ){
max = q;
}
}
return max;
}
//! Set size
void freetype::setSize( unsigned int w, unsigned int h){
Util::Thread::ScopedLock locked(lock);
if ( w != size.width || h != size.height ){
if (internalFix)return;
if (w<=0 || h<=0)return;
size.width = w;
size.height = h;
createIndex();
// maximumHeight = calculateMaximumHeight();
}
}
//! Set italics
void freetype::setItalics(int i){
Util::Thread::ScopedLock locked(lock);
if(internalFix)return;
if(i<-45)i=(-45);
else if(i>45)i=45;
size.italics = i;
createIndex();
}
void freetype::getSize(int * w, int * h) const {
*w = size.width;
*h = size.height;
}
//! Get Width
int freetype::getWidth() const {
return size.width;
}
//! Get Height
int freetype::getHeight( const std::string & str ) const {
// return size.height;
return calculateHeight(str);
}
//! Get Italics
int freetype::getItalics(){
return size.italics;
}
+#endif
}
#endif /* FONT_BASE_CPP */
diff --git a/util/ftalleg.h b/util/ftalleg.h
index e6031013..6d286714 100644
--- a/util/ftalleg.h
+++ b/util/ftalleg.h
@@ -1,242 +1,268 @@
/*
--------------
About
--------------
A Freetype wrapper for use with allegro
Feel free to do whatever you like with this, by all means enjoy!
Just add it to your project
--------------
Linking
--------------
on linux:
g++ `freetype-config --cflags` ftalleg.cpp myfiles.cpp `freetype-config --libs` `allegro-config --libs`
on windows (you may need to include the freetype dir location, ie -Ic:/mingw/include):
g++ ftalleg.cpp myfiles.cpp -lfreetype -lalleg
--------------
Disclaimer
--------------
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE
SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef FT_FONT_H
#define FT_FONT_H
// #include <allegro.h>
#include <map>
#include <string>
#include <math.h>
#include <exception>
#include "file-system.h"
#include <ft2build.h>
#include FT_FREETYPE_H
#include "thread.h"
#include "color.h"
+
+#ifdef USE_ALLEGRO5
+struct ALLEGRO_FONT;
+#endif
#define GLYPH_PI 3.14159265358979323846
#define GLYPH_SQRT2 1.41421356237309504880
namespace Graphics{
class Bitmap;
}
+
namespace ftalleg {
class Exception: public std::exception {
public:
Exception();
Exception(const std::string reason);
inline const std::string & getReason() const {
return reason;
}
virtual ~Exception() throw();
protected:
std::string reason;
};
//! Internal class for freetype to use
/*!
* This holds necessary information regarding a character \n
* from Freetype.
*/
- class character
- {
- public:
- //! Constructor
- character();
-
- //! Destructor
- ~character();
-
- //! Unicode representation of character
- signed long unicode;
-
- //! Width of character
- int width;
-
- //! Height of character
- int height;
-
- //! Space on the left of a character (assists on positioning the character)
- int left;
-
- //! Space on top of the character (assists on positioning the character)
- int top;
-
- //! Space on the right of a character (assists on positioning the character)
- int right;
-
- //! Pitch of a character (assists on positioning the character)
- int pitch;
-
- //! Amount of shades of grays the FT_Bitmap holds
- int grays;
-
- //! Entire rows of the FT_Bitmap
- int rows;
-
- //! Entire length of the character with spacing and all
- int length;
-
- //! FT_Bitmap raw data
- unsigned char *line;
- };
+ class character{
+ public:
+ //! Constructor
+ character();
+
+ //! Destructor
+ ~character();
+
+ //! Unicode representation of character
+ signed long unicode;
+
+ //! Width of character
+ int width;
+
+ //! Height of character
+ int height;
+
+ //! Space on the left of a character (assists on positioning the character)
+ int left;
+
+ //! Space on top of the character (assists on positioning the character)
+ int top;
+
+ //! Space on the right of a character (assists on positioning the character)
+ int right;
+
+ //! Pitch of a character (assists on positioning the character)
+ int pitch;
+
+ //! Amount of shades of grays the FT_Bitmap holds
+ int grays;
+
+ //! Entire rows of the FT_Bitmap
+ int rows;
+
+ //! Entire length of the character with spacing and all
+ int length;
+
+ //! FT_Bitmap raw data
+ unsigned char *line;
+ };
//! Internal class for freetype to use
/*!
* Properties used for indexing a given font according to its size and matrix \n
*/
- class fontSize
- {
- public:
- fontSize();
- ~fontSize();
- FT_UInt width;
- FT_UInt height;
- int italics;
- int angle;
-
- bool operator<(const fontSize &fs) const;
-
- int createKey() const;
- };
+ class fontSize{
+ public:
+ fontSize();
+ ~fontSize();
+ FT_UInt width;
+ FT_UInt height;
+ int italics;
+ int angle;
+
+ bool operator<(const fontSize &fs) const;
+
+ int createKey() const;
+ };
+#ifdef USE_ALLEGRO5
+ class freetype{
+ public:
+ freetype(const Filesystem::AbsolutePath & str, const int x, const int y);
+ ~freetype();
+
+ enum ftAlign{
+ ftLeft = 0,
+ ftCenter = 1,
+ ftRight = 2
+ };
+
+ void setSize( unsigned int w, unsigned int h);
+ int getHeight(const std::string & str) const;
+ int getLength(const std::string & text) const;
+ void getSize(int * w, int * h) const;
+ void render(int x, int y, const Graphics::Color & color, const Graphics::Bitmap & bmp, ftAlign alignment, const std::string & text, int marker, ...);
+ private:
+ ALLEGRO_FONT * font;
+ int width;
+ int height;
+ };
+#else
//! Freetype based font system
/*!
* Allows us to use freetype in allegro
*/
- class freetype
- {
- private:
- //! Filename
- std::string currentFilename;
-
- //! Is the face loaded
- bool faceLoaded;
-
- //! Does the face have kerning
- bool kerning;
-
- //! Current index default 0
- int currentIndex;
-
- //! for internal use disregard
- bool internalFix;
-
- int maximumHeight;
-
- //! Font size
- fontSize size;
-
- //! Current Set system name
- std::string systemName;
-
- //! Face
- FT_Face face;
-
- //! Face Name
- std::string faceName;
-
- /*
- //! Current character
- character *currentChar;
- */
-
- Util::Thread::LockObject lock;
-
- //! Lookup Table by size
- std::map<int, std::map<signed long, character*> >fontTable;
-
- //! Extract glyph
- character * extractGlyph(signed long unicode);
-
- int calculateMaximumHeight();
-
- //! Create single index
- void createIndex();
-
- //! Render a character from the lookup table (utilizing the workBitmap)
- void drawCharacter(signed long unicode, int &x1, int &y1, const Graphics::Bitmap & bitmap, const Graphics::Color & color);
-
- int height( long code ) const;
- int calculateHeight( const std::string & str ) const;
-
- /* only called by the destructor */
- void destroyGlyphIndex();
-
- public:
- //! Constructor
- freetype(const Filesystem::AbsolutePath & str, const int x, const int y );
-
- //! Destructor
- ~freetype();
-
- //! Enum list of alignments
- enum ftAlign
- {
- ftLeft = 0,
- ftCenter = 1,
- ftRight = 2
- };
-
- //! Load font from memory
- bool load(const unsigned char *memoryFont, unsigned int length, int index, unsigned int width, unsigned int height);
-
- //! Load font from file
- bool load(const Filesystem::AbsolutePath & filename, int index, unsigned int width, unsigned int height);
-
- //! Get text length
- int getLength(const std::string & text);
-
- //! Render font to a bitmap
- void render(int x, int y, const Graphics::Color & color, const Graphics::Bitmap & bmp, ftAlign alignment, const std::string & text, int marker, ...);
-
- //! Set size
- void setSize( unsigned int w, unsigned int h);
-
- //! Set italics
- void setItalics(int i);
-
- /* get the size attributes (close to width/height) */
- void getSize(int * w, int * h) const;
-
- //! Get Width
- int getWidth() const;
-
- //! Get Height
- int getHeight( const std::string & str ) const;
-
- //! Get Italics
- int getItalics();
- };
+ class freetype{
+ private:
+ //! Filename
+ std::string currentFilename;
+
+ //! Is the face loaded
+ bool faceLoaded;
+
+ //! Does the face have kerning
+ bool kerning;
+
+ //! Current index default 0
+ int currentIndex;
+
+ //! for internal use disregard
+ bool internalFix;
+
+ int maximumHeight;
+
+ //! Font size
+ fontSize size;
+
+ //! Current Set system name
+ std::string systemName;
+
+ //! Face
+ FT_Face face;
+
+ //! Face Name
+ std::string faceName;
+
+ /*
+ //! Current character
+ character *currentChar;
+ */
+
+ Util::Thread::LockObject lock;
+
+
+ //! Lookup Table by size
+ std::map<int, std::map<signed long, character*> >fontTable;
+
+ //! Extract glyph
+ character * extractGlyph(signed long unicode);
+
+ int calculateMaximumHeight();
+
+ //! Create single index
+ void createIndex();
+
+ //! Render a character from the lookup table (utilizing the workBitmap)
+ void drawCharacter(signed long unicode, int &x1, int &y1, const Graphics::Bitmap & bitmap, const Graphics::Color & color);
+
+ int height( long code ) const;
+ int calculateHeight( const std::string & str ) const;
+
+ /* only called by the destructor */
+ void destroyGlyphIndex();
+
+ public:
+ //! Constructor
+ freetype(const Filesystem::AbsolutePath & str, const int x, const int y );
+
+ //! Destructor
+ ~freetype();
+
+ //! Enum list of alignments
+ enum ftAlign{
+ ftLeft = 0,
+ ftCenter = 1,
+ ftRight = 2
+ };
+
+ //! Load font from memory
+ bool load(const unsigned char *memoryFont, unsigned int length, int index, unsigned int width, unsigned int height);
+
+ //! Load font from file
+ bool load(const Filesystem::AbsolutePath & filename, int index, unsigned int width, unsigned int height);
+
+ //! Get text length
+ int getLength(const std::string & text);
+
+ //! Render font to a bitmap
+ void render(int x, int y, const Graphics::Color & color, const Graphics::Bitmap & bmp, ftAlign alignment, const std::string & text, int marker, ...);
+
+ //! Set size
+ void setSize( unsigned int w, unsigned int h);
+
+ //! Set italics
+ void setItalics(int i);
+
+ /* get the size attributes (close to width/height) */
+ void getSize(int * w, int * h) const;
+
+ //! Get Width
+ int getWidth() const;
+
+ //! Get Height
+ int getHeight( const std::string & str ) const;
+
+ //! Get Italics
+ int getItalics();
+ };
+#endif
}
#endif /* FT_FONT_H */

File Metadata

Mime Type
text/x-diff
Expires
Thu, Jun 11, 11:01 AM (3 w, 4 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
68606
Default Alt Text
(70 KB)

Event Timeline