Page MenuHomePhabricator (Chris)

No OneTemporary

Authored By
Unknown
Size
221 KB
Referenced Files
None
Subscribers
None
diff --git a/util/graphics/allegro/bitmap.cpp b/util/graphics/allegro/bitmap.cpp
index 79199a90..32fb1c5c 100644
--- a/util/graphics/allegro/bitmap.cpp
+++ b/util/graphics/allegro/bitmap.cpp
@@ -1,1885 +1,1885 @@
/* allegro.h must be on top, don't move it!!!! */
#include <allegro.h>
#ifdef _WIN32
#include <winalleg.h>
#endif
#include "gif/algif.h"
#include "util/init.h"
#include "loadpng/loadpng.h"
#include <stdarg.h>
#include <vector>
#include <string>
#include <iostream>
#include <math.h>
#include "util/funcs.h"
#include <stdio.h>
#include "util/exceptions/load_exception.h"
#include "util/memory.h"
#include <sstream>
// #include <fblend.h>
#ifdef _WIN32
#include <winalleg.h>
#define EXTERNAL_VARIABLE __declspec(dllimport)
#else
#define EXTERNAL_VARIABLE
#endif
using namespace std;
#ifndef debug
#define debug cout<<"File: "<<__FILE__<<" Line: "<<__LINE__<<endl;
#endif
/* These have to go outside the Graphics namespace for some reason */
/* defined at allegro/include/internal/aintern.h:457 */
extern EXTERNAL_VARIABLE BLENDER_FUNC _blender_func16;
/* defined at allegro/include/internal/aintern.h:466 */
extern EXTERNAL_VARIABLE int _blender_col_16;
/* defined at allegro/include/internal/aintern.h:470 */
extern EXTERNAL_VARIABLE int _blender_alpha;
namespace Graphics{
enum DrawingModes{
MODE_TRANS,
MODE_SOLID
};
/* FIXME: try to get rid of these variables */
static int SCALE_X;
static int SCALE_Y;
static void paintown_draw_sprite_ex16( BITMAP * dst, BITMAP * src, int dx, int dy, int mode, int flip, Bitmap::Filter * filter);
static void paintown_draw_sprite_filter_ex16(BITMAP * dst, BITMAP * src, int x, int y, const Bitmap::Filter & filter);
static void paintown_light16(BITMAP * dst, const int x, const int y, const int width, const int height, const int start_y, const int focus_alpha, const int edge_alpha, const Color focus_color, const Color edge_color);
static void paintown_applyTrans16(BITMAP * dst, const Color color);
Color MaskColor(){
return Color(MASK_COLOR_16);
}
static Bitmap * Scaler = NULL;
static Bitmap * Buffer = NULL;
static void drawingMode(int mode){
// drawing_mode( DRAW_MODE_TRANS, NULL, 0, 0 );
switch( mode ){
case MODE_TRANS : {
drawing_mode( DRAW_MODE_TRANS, NULL, 0, 0 );
break;
}
case MODE_SOLID : {
drawing_mode( DRAW_MODE_SOLID, NULL, 0, 0 );
break;
}
}
}
Bitmap::Bitmap():
mustResize(false),
error( false ),
bit8MaskColor(0){
setData(Util::ReferenceCount<BitmapData>(new BitmapData(create_bitmap( 10, 10 ))));
if (! getData()->getBitmap()){
error = true;
cerr << "Could not create bitmap!" << endl;
} else {
clear();
}
}
Bitmap::Bitmap( int x, int y ):
mustResize(false),
error( false ),
bit8MaskColor(0){
if ( x < 1 ){
x = 1;
}
if ( y < 1 ){
y = 1;
}
setData(Util::ReferenceCount<BitmapData>(new BitmapData(create_bitmap(x, y))));
if ( ! getData()->getBitmap() ){
error = true;
cerr << "Could not create bitmap!" << endl;
} else {
clear();
}
}
static BITMAP * memoryPNG(const char * data, int length){
return load_memory_png(data, length, NULL);
}
static BITMAP * memoryGIF(const char * data, int length){
PACKFILE_VTABLE table = Memory::makeTable();
Memory::memory memory((unsigned char *) data, length);
PACKFILE * pack = pack_fopen_vtable(&table, &memory);
/* need to supply a proper palette at some point */
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){
// pack_fclose(pack);
ostringstream out;
out <<"Could not load gif from memory: " << (void*) data << " length " << length;
throw LoadException(__FILE__, __LINE__, out.str());
}
#if 0
/* converts 8-bit pcx mask to allegro's mask */
if (mask){
/* warning! 8-bit assumptions */
int colors = 256;
int maskR = (int)data[length - colors*3 + 0];
int maskG = (int)data[length - colors*3 + 1];
int maskB = (int)data[length - colors*3 + 2];
int mask = makeColor(maskR, maskG, maskB);
// printf("mask r %d g %d b %d = %d\n", maskR, maskG, maskB, mask);
if (mask != MaskColor()){
for( int i = 0; i < pcx->h; ++i ){
for( int j = 0; j < pcx->w; ++j ){
/* use getPixel/putPixel? */
int pix = getpixel(pcx,j,i);
if (pix == mask){
putpixel(pcx,j,i, MaskColor());
}
}
}
}
}
#endif
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);
return out;
}
static BITMAP * load_bitmap_from_memory(const char * data, int length, ImageFormat type){
switch (type){
case FormatPNG: {
return memoryPNG(data, length);
}
case FormatBMP: throw BitmapException(__FILE__, __LINE__, "Could not load .bmp file from memory");
case FormatJPG: throw BitmapException(__FILE__, __LINE__, "Could not load .jpg file from memory");
case FormatPCX: {
Bitmap pcx(memoryPCX((unsigned char * const) data, length, false));
BITMAP * out = create_bitmap(pcx.getWidth(), pcx.getHeight());
blit(pcx.getData()->getBitmap(), out, 0, 0, 0, 0, out->w, out->h);
return out;
}
case FormatTGA: throw BitmapException(__FILE__, __LINE__, "Could not load .tga file from memory");
case FormatTIF: throw BitmapException(__FILE__, __LINE__, "Could not load .tif file from memory");
case FormatXPM: throw BitmapException(__FILE__, __LINE__, "Could not load .xpm file from memory");
case FormatGIF: {
return memoryGIF(data, length);
}
case FormatUnknown: throw BitmapException(__FILE__, __LINE__, "Could not load unknown formatted image file");
}
throw BitmapException(__FILE__, __LINE__, "Internal error");
}
Bitmap::Bitmap(const char * data, int length):
mustResize(false),
error(false),
bit8MaskColor(0){
setData(Util::ReferenceCount<BitmapData>(new BitmapData(load_bitmap_from_memory(data, length, identifyImage((unsigned char *) data, length)))));
}
void Bitmap::loadFromMemory(const char * data, int length){
setData(Util::ReferenceCount<BitmapData>(new BitmapData(load_bitmap_from_memory(data, length, identifyImage((unsigned char *) data, length)))));
}
/* If a BITMAP is given to us, we didn't make it so we don't own it */
Bitmap::Bitmap( BITMAP * who, bool deep_copy ):
mustResize(false),
error( false ),
bit8MaskColor(0){
if ( deep_copy ){
BITMAP * his = who;
setData(Util::ReferenceCount<BitmapData>(new BitmapData(create_bitmap(his->w, his->h))));
if ( ! getData()->getBitmap() ){
cout << "Could not create bitmap" << endl;
error = true;
}
::blit( his, getData()->getBitmap(), 0, 0, 0, 0, his->w, his->h );
} else {
setData(Util::ReferenceCount<BitmapData>(new BitmapData(who)));
}
}
Bitmap::Bitmap( const char * load_file ):
mustResize(false),
error( false ),
bit8MaskColor(0){
internalLoadFile( load_file );
/*
my_bitmap = load_bitmap( load_file, NULL );
if ( !my_bitmap ){
my_bitmap = create_bitmap( 100, 100 );
clear( my_bitmap );
cout<<"Could not load "<<load_file<<endl;
error = true;
}
own = true;
*/
}
Bitmap::Bitmap( const string & load_file ):
mustResize(false),
error( false ),
bit8MaskColor(0){
internalLoadFile( load_file.c_str() );
}
Bitmap::Bitmap( const char * load_file, int sx, int sy ):
mustResize(false),
error( false ),
bit8MaskColor(0){
path = load_file;
BITMAP * temp = load_bitmap( load_file, NULL );
// my_bitmap = load_bitmap( load_file, NULL );
setData(Util::ReferenceCount<BitmapData>(new BitmapData(create_bitmap(sx, sy))));
// clear( my_bitmap );
if ( !temp || ! getData()->getBitmap() ){
cout<<"Could not load "<<load_file<<endl;
error = true;
} else {
clear();
stretch_blit( temp, getData()->getBitmap(), 0, 0, temp->w, temp->h, 0, 0, getData()->getBitmap()->w, getData()->getBitmap()->h );
destroy_bitmap( temp );
}
}
Bitmap::Bitmap( const char * load_file, int sx, int sy, double accuracy ):
mustResize(false),
error( false ),
bit8MaskColor(0){
path = load_file;
BITMAP * temp = load_bitmap( load_file, NULL );
if ( !temp ){
cout<<"Could not load "<<load_file<<endl;
setData(Util::ReferenceCount<BitmapData>(new BitmapData(create_bitmap( sx, sy ))));
// clear( my_bitmap );
clear();
error = true;
} else {
if ( temp->w > sx || temp->h > sy ){
double bx = temp->w / sx;
double by = temp->h / sy;
double use;
use = bx > by ? bx : by;
int fx = (int)(sx / use);
int fy = (int)(sy / use);
setData(Util::ReferenceCount<BitmapData>(new BitmapData(create_bitmap( fx, fy ))));
stretch_blit( temp, getData()->getBitmap(), 0, 0, temp->w, temp->h, 0, 0, getData()->getBitmap()->w, getData()->getBitmap()->h );
destroy_bitmap( temp );
} else {
setData(Util::ReferenceCount<BitmapData>(new BitmapData(temp)));
}
}
// own = true;
}
Bitmap::Bitmap( const Bitmap & copy, int sx, int sy ):
mustResize(false),
error( false ),
bit8MaskColor(copy.bit8MaskColor){
path = copy.getPath();
BITMAP * temp = copy.getData()->getBitmap();
setData(Util::ReferenceCount<BitmapData>(new BitmapData(create_bitmap(sx, sy))));
if ( ! getData()->getBitmap() ){
error = true;
cout << "Could not copy bitmap" << endl;
}
// clear( my_bitmap );
clear();
stretch_blit( temp, getData()->getBitmap(), 0, 0, temp->w, temp->h, 0, 0, getData()->getBitmap()->w, getData()->getBitmap()->h );
}
Bitmap::Bitmap( const Bitmap & copy, int sx, int sy, double accuracy ):
mustResize(false),
error( false ),
bit8MaskColor(copy.bit8MaskColor){
path = copy.getPath();
BITMAP * temp = copy.getData()->getBitmap();
if ( temp->w > sx || temp->h > sy ){
double bx = (double)temp->w / (double)sx;
double by = (double)temp->h / (double)sy;
double use;
use = bx > by ? bx : by;
int fx = (int)(temp->w / use);
int fy = (int)(temp->h / use);
setData(Util::ReferenceCount<BitmapData>(new BitmapData(create_bitmap(fx, fy))));
if ( ! getData()->getBitmap() ){
allegro_message("Could not create bitmap\n");
// own = false;
// own = copy.own;
// *own++;
error = true;
return;
}
stretch_blit( temp, getData()->getBitmap(), 0, 0, temp->w, temp->h, 0, 0, getData()->getBitmap()->w, getData()->getBitmap()->h );
// destroy_bitmap( temp );
} else {
setData(Util::ReferenceCount<BitmapData>(new BitmapData(create_bitmap(temp->w, temp->h))));
blit( temp, getData()->getBitmap(), 0, 0, 0, 0, temp->w, temp->h );
// own = new int
// own = true;
}
}
Bitmap::Bitmap( const Bitmap & copy, bool deep_copy ):
mustResize(false),
error( false ),
bit8MaskColor(copy.bit8MaskColor){
path = copy.getPath();
if ( deep_copy ){
BITMAP * his = copy.getData()->getBitmap();
setData(Util::ReferenceCount<BitmapData>(new BitmapData(create_bitmap(his->w, his->h))));
if ( ! getData()->getBitmap() ){
cout << "Could not create bitmap" << endl;
error = true;
}
::blit( his, getData()->getBitmap(), 0, 0, 0, 0, his->w, his->h );
} else {
setData(copy.getData());
}
/*
BITMAP * his = copy.getBitmap();
my_bitmap = create_bitmap( his->w, his->h );
::blit( his, my_bitmap, 0, 0, 0, 0, his->w, his->h );
own = true;
*/
}
Bitmap::Bitmap( const Bitmap & copy, int x, int y, int width, int height ):
mustResize(false),
error( false ),
bit8MaskColor(copy.bit8MaskColor){
path = copy.getPath();
BITMAP * his = copy.getData()->getBitmap();
if ( x < 0 )
x = 0;
if ( y < 0 )
y = 0;
if ( width + x > his->w )
width = his->w - x;
if ( height + y > his->h )
height = his->h - y;
setData(Util::ReferenceCount<BitmapData>(new BitmapData(create_sub_bitmap(his, x, y, width, height))));
if ( ! getData()->getBitmap() ){
cout<<"Could not create sub-bitmap"<<endl;
setData(Util::ReferenceCount<BitmapData>(new BitmapData(create_bitmap(10, 10))));
// clear( my_bitmap );
clear();
}
}
void Bitmap::internalLoadFile( const char * load_file ){
path = load_file;
setData(Util::ReferenceCount<BitmapData>(new BitmapData(load_bitmap(load_file, NULL))));
if ( ! getData()->getBitmap() ){
cout<<"Could not load "<<load_file<<". Using default"<<endl;
setData(Util::ReferenceCount<BitmapData>(new BitmapData(create_bitmap(10, 10))));
if ( ! getData()->getBitmap() ){
cout<<"Out of memory or Allegro not initialized"<<endl;
error = true;
return;
}
// clear( my_bitmap );
clear();
// cout<<"Could not load "<<load_file<<endl;
error = true;
}
}
void Bitmap::save( const string & str ) const {
save_bitmap( str.c_str(), getData()->getBitmap(), NULL );
}
Bitmap memoryPCX(unsigned char * const data, const int length, const bool mask){
PACKFILE_VTABLE table = Memory::makeTable();
Memory::memory memory(data, length);
PACKFILE * pack = pack_fopen_vtable(&table, &memory);
/* need to supply a proper palette at some point */
RGB * palette = NULL;
BITMAP * pcx = load_pcx_pf(pack, palette);
if (!pcx){
pack_fclose(pack);
ostringstream out;
out <<"Could not load pcx from memory: " << (void*) data << " length " << length;
throw LoadException(__FILE__, __LINE__, out.str());
}
int colors = 256;
int maskR = (int)data[length - colors*3 + 0];
int maskG = (int)data[length - colors*3 + 1];
int maskB = (int)data[length - colors*3 + 2];
Color maskColor = makeColor(maskR, maskG, maskB);
#if 0
/* converts 8-bit pcx mask to allegro's mask */
if (mask){
/* warning! 8-bit assumptions */
int colors = 256;
int maskR = (int)data[length - colors*3 + 0];
int maskG = (int)data[length - colors*3 + 1];
int maskB = (int)data[length - colors*3 + 2];
int mask = makeColor(maskR, maskG, maskB);
// printf("mask r %d g %d b %d = %d\n", maskR, maskG, maskB, mask);
if (mask != MaskColor()){
for( int i = 0; i < pcx->h; ++i ){
for( int j = 0; j < pcx->w; ++j ){
/* use getPixel/putPixel? */
int pix = getpixel(pcx,j,i);
if (pix == mask){
putpixel(pcx,j,i, MaskColor());
}
}
}
}
}
#endif
Bitmap bitmap(pcx, true);
bitmap.set8BitMaskColor(maskColor);
destroy_bitmap(pcx);
pack_fclose(pack);
return bitmap;
}
Bitmap * getScreenBuffer(){
return Scaler;
}
void initializeExtraStuff(){
/* nothing yet */
}
int Bitmap::getWidth() const{
return getData()->getBitmap()->w;
}
int Bitmap::getHeight() const{
return getData()->getBitmap()->h;
}
int getRed( Color x ){
return ::getr( x.color );
}
int getBlue( Color x ){
return ::getb( x.color );
}
int getGreen( Color x ){
return ::getg( x.color );
}
void Bitmap::setClipRect( int x1, int y1, int x2, int y2 ) const {
::set_clip_rect( getData()->getBitmap(), x1, y1, x2, y2 );
}
void Bitmap::getClipRect(int & x1, int & y1, int & x2, int & y2) const {
::get_clip_rect(getData()->getBitmap(), &x1, &y1, &x2, &y2);
}
/*
const string & Bitmap::getPath() const{
return path;
}
*/
void Bitmap::debugSelf() const{
cout<<"Bitmap: "<<endl;
cout<<"Self = "<< getData()->getBitmap() <<endl;
cout<<"Path = "<<path<<endl;
}
/*
Bitmap::~Bitmap(){
releaseInternalBitmap();
}
*/
void Bitmap::detach(){
/*
if ( own ){
(*own)--;
if ( *own == 0 ){
destroy_bitmap( getBitmap() );
delete own;
}
}
*/
}
/*
BITMAP * Bitmap::getBitmap() const{
return my_bitmap;
}
*/
bool Bitmap::getError(){
return error;
}
/*
int Bitmap::getWidth(){
return my_bitmap->w;
}
int Bitmap::getHeight(){
return my_bitmap->h;
}
*/
void Bitmap::acquire(){
acquire_bitmap( getData()->getBitmap() );
}
void Bitmap::release(){
release_bitmap( getData()->getBitmap() );
}
void Bitmap::circleFill( int x, int y, int radius, Color color ) const {
::circlefill( getData()->getBitmap(), x, y, radius, color.color );
}
void TranslucentBitmap::circleFill(int x, int y, int radius, Color color) const {
drawingMode(MODE_TRANS);
Bitmap::circleFill(x, y, radius, color);
drawingMode(MODE_SOLID);
}
void Bitmap::circle( int x, int y, int radius, Color color ) const{
::circle( getData()->getBitmap(), x, y, radius, color.color );
}
/* FIXME */
void Bitmap::circle( int x, int y, int radius, int thickness, Color color ) const{
::circle( getData()->getBitmap(), x, y, radius, color.color );
}
void Bitmap::line( const int x1, const int y1, const int x2, const int y2, const Color color ) const{
::fastline( getData()->getBitmap(), x1, y1, x2, y2, color.color );
}
void TranslucentBitmap::line(const int x1, const int y1, const int x2, const int y2, const Color color) const{
drawingMode(MODE_TRANS);
Bitmap::line(x1, y1, x2, y2, color);
drawingMode(MODE_SOLID);
}
void Bitmap::floodfill( const int x, const int y, const Color color ) const {
::floodfill( getData()->getBitmap(), x, y, color.color );
}
void Bitmap::drawCharacter( const int x, const int y, const Color color, const int background, const Bitmap & where ) const {
::draw_character_ex( where.getData()->getBitmap(), getData()->getBitmap(), x, y, color.color, background );
}
void Bitmap::alphaBlender(int source, int dest){
/* TODO */
}
void Bitmap::transBlender( int r, int g, int b, int a ){
set_trans_blender( r, g, b, a );
}
void Bitmap::multiplyBlender( int r, int g, int b, int a ){
set_multiply_blender( r, g, b, a );
}
void Bitmap::dissolveBlender( int r, int g, int b, int a ){
set_dissolve_blender( r, g, b, a );
}
void Bitmap::addBlender( int r, int g, int b, int a ){
set_add_blender( r, g, b, a );
}
void Bitmap::burnBlender( int r, int g, int b, int a ){
set_burn_blender( r, g, b, a );
}
void Bitmap::colorBlender( int r, int g, int b, int a ){
set_color_blender( r, g, b, a );
}
void Bitmap::differenceBlender( int r, int g, int b, int a ){
set_difference_blender( r, g, b, a );
}
void Bitmap::dodgeBlender( int r, int g, int b, int a ){
set_dodge_blender( r, g, b, a );
}
void Bitmap::hueBlender( int r, int g, int b, int a ){
set_hue_blender( r, g, b, a );
}
void Bitmap::luminanceBlender( int r, int g, int b, int a ){
set_luminance_blender( r, g, b, a );
}
void Bitmap::invertBlender( int r, int g, int b, int a ){
set_invert_blender( r, g, b, a );
}
void Bitmap::screenBlender( int r, int g, int b, int a ){
set_screen_blender( r, g, b, a );
}
void Bitmap::replaceColor(const Color & original, const Color & replaced){
int height = getHeight();
int width = getWidth();
BITMAP * bitmap = getData()->getBitmap();
for (int i = 0; i < height; ++i ){
for( int j = 0; j < width; ++j ){
/* use getPixel/putPixel? */
int pix = getpixel(bitmap, j, i);
if (pix == original.color){
putpixel(bitmap, j, i, replaced.color);
}
}
}
}
int changeGraphicsMode(int mode, int width, int height){
return setGraphicsMode(mode, width, height);
}
int setGraphicsMode( int mode, int width, int height ){
int ok = ::set_gfx_mode(mode, width, height, 0, 0);
if ( ok == 0 ){
if (SCALE_X == 0){
SCALE_X = width;
}
if (SCALE_Y == 0){
SCALE_Y = height;
}
if ( Screen != NULL ){
delete Screen;
Screen = NULL;
}
/*
if ( Scaler != NULL ){
delete Scaler;
Scaler = NULL;
}
*/
if ( Buffer != NULL ){
delete Buffer;
Buffer = NULL;
}
if (width != 0 && height != 0){
Screen = new Bitmap( ::screen );
Screen->getData()->setDestroy(false);
if (Scaler == NULL){
Scaler = new Bitmap(width, height);
} else {
Scaler->updateSize(width, height);
}
/*
if ( width != 0 && height != 0 && (width != SCALE_X || height != SCALE_Y) ){
Scaler = new Bitmap(width, height);
// Buffer = new Bitmap(SCALE_X, SCALE_Y);
}
*/
}
}
return ok;
}
void Bitmap::shutdown(){
delete Screen;
Screen = NULL;
delete Scaler;
Scaler = NULL;
delete Buffer;
Buffer = NULL;
}
/*
const int Bitmap::getWidth() const{
return getBitmap()->w;
}
const int Bitmap::getHeight() const{
return getBitmap()->h;
}
*/
Color Bitmap::getPixel( const int x, const int y ) const{
if ( x >= 0 && x < getData()->getBitmap()->w && y >= 0 && y < getData()->getBitmap()->h )
return Color(_getpixel16( getData()->getBitmap(), x, y ));
return Color(-1);
}
void Bitmap::readLine( vector< Color > & vec, int y ){
if ( y >= 0 && y < getData()->getBitmap()->h ){
for ( int q = 0; q < getData()->getBitmap()->w; q++ ){
// int col = my_bitmap->line[ y ][ q ];
int col = _getpixel16( getData()->getBitmap(), q, y );
vec.push_back(Color(col) );
}
}
}
int setGfxModeText(){
return setGraphicsMode(GFX_TEXT, 0, 0);
}
int setGfxModeFullscreen(int x, int y){
return setGraphicsMode(GFX_AUTODETECT_FULLSCREEN, x, y);
}
int setGfxModeWindowed(int x, int y){
return setGraphicsMode(GFX_AUTODETECT_WINDOWED, x, y);
}
Color makeColor( int r, int g, int b ){
return Color(::makecol16( r, g, b ));
}
void hsvToRGB( float h, float s, float v, int * r, int * g, int * b ){
::hsv_to_rgb( h, s, v, r, g, b );
}
void Bitmap::rgbToHSV(int r, int g, int b, float * h, float * s, float * v){
::rgb_to_hsv(r, g, b, h, s, v);
}
Color Bitmap::addColor( Color color1, Color color2 ){
return makeColor( getr( color1.color ) + getr( color2.color ),
getg( color1.color ) + getg( color2.color ),
getb( color1.color ) + getb( color2.color ) );
}
void Bitmap::putPixelNormal(int x, int y, Color col) const {
BITMAP * dst = getData()->getBitmap();
::putpixel(dst, x, y, col.color);
}
/* FIXME: its pretty slow to keep setting the drawing mode. Either
* 1) dont use translucent putpixel that much or
* 2) somehow cache the drawing mode so that its not reset every time
*/
void TranslucentBitmap::putPixelNormal(int x, int y, Color color) const {
drawingMode(MODE_TRANS);
Bitmap::putPixelNormal(x, y, color);
drawingMode(MODE_SOLID);
}
void Bitmap::putPixel( int x, int y, Color col ) const{
BITMAP * dst = getData()->getBitmap();
if (dst->clip && ((x < dst->cl) || (x >= dst->cr) || (y < dst->ct) || (y >= dst->cb))){
return;
}
if ( x >= 0 && x < getData()->getBitmap()->w && y >= 0 && y < getData()->getBitmap()->h )
_putpixel16( getData()->getBitmap(), x, y, col.color );
}
/*
void Bitmap::printf( int x, int y, int color, FONT * f, const char * str, ... ) const{
char buf[512];
va_list ap;
va_start(ap, str);
uvszprintf(buf, sizeof(buf), str, ap);
va_end(ap);
textout_ex( getBitmap(), f, buf, x, y, color, -1);
}
void Bitmap::printf( int x, int y, int color, const Font * const f, const char * str, ... ) const{
char buf[512];
va_list ap;
va_start(ap, str);
uvszprintf(buf, sizeof(buf), str, ap);
va_end(ap);
textout_ex( getBitmap(), f->getInternalFont(), buf, x, y, color, -1);
}
void Bitmap::printf( int x, int y, int color, const Font * const f, const string & str ) const{
printf( x, y, color, f, str.c_str() );
}
void Bitmap::printf( int x, int y, int color, const Font & f, const string & str ) const{
printf( x, y, color, &f, str );
}
void Bitmap::printfNormal( int x, int y, int color, const char * str, ... ) const{
char buf[512];
va_list ap;
va_start(ap, str);
uvszprintf(buf, sizeof(buf), str, ap);
va_end(ap);
textout_ex( getBitmap(), font, buf, x, y, color, -1);
}
void Bitmap::printfNormal( int x, int y, int color, const string & str ) const{
printfNormal( x, y, color, "%s", str.c_str() );
}
*/
void Bitmap::triangle( int x1, int y1, int x2, int y2, int x3, int y3, Color color ) const{
::triangle( getData()->getBitmap(), x1, y1, x2, y2, x3, y3, color.color );
}
void Bitmap::ellipse( int x, int y, int rx, int ry, Color color ) const {
::ellipse( getData()->getBitmap(), x, y, rx, ry, color.color );
}
void TranslucentBitmap::ellipse(int x, int y, int rx, int ry, Color color) const {
drawingMode(MODE_TRANS);
Bitmap::ellipse(x, y, rx, ry, color);
drawingMode(MODE_SOLID);
}
void TranslucentBitmap::ellipseFill(int x, int y, int rx, int ry, Color color) const {
drawingMode(MODE_TRANS);
Bitmap::ellipseFill(x, y, rx, ry, color);
drawingMode(MODE_SOLID);
}
void Bitmap::ellipseFill( int x, int y, int rx, int ry, Color color ) const {
::ellipsefill( getData()->getBitmap(), x, y, rx, ry, color.color );
}
void Bitmap::rectangle( int x1, int y1, int x2, int y2, Color color ) const{
::rect( getData()->getBitmap(), x1, y1, x2, y2, color.color );
}
void TranslucentBitmap::rectangle( int x1, int y1, int x2, int y2, Color color ) const {
drawingMode(MODE_TRANS);
Bitmap::rectangle(x1, y1, x2, y2, color);
drawingMode(MODE_SOLID);
}
void Bitmap::rectangleFill( int x1, int y1, int x2, int y2, Color color ) const{
::rectfill( getData()->getBitmap(), x1, y1, x2, y2, color.color );
}
void TranslucentBitmap::rectangleFill( int x1, int y1, int x2, int y2, Color color ) const{
drawingMode(MODE_TRANS);
Bitmap::rectangleFill(x1, y1, x2, y2, color);
drawingMode(MODE_SOLID);
}
/*
int Bitmap::getPixel( int x, int y ){
if ( x >= 0 && x < my_bitmap->w && y >= 0 && y <= my_bitmap->h )
return _getpixel16( my_bitmap, x, y );
return -1;
}
*/
/*
int Bitmap::makeColor( int r, int g, int b ){
return makecol16( r, g, b );
}
*/
void Bitmap::hLine( const int x1, const int y, const int x2, const Color color ) const{
::hline( getData()->getBitmap(), x1, y, x2, color.color );
}
void TranslucentBitmap::hLine( const int x1, const int y, const int x2, const Color color ) const{
drawingMode(MODE_TRANS);
::hline(getData()->getBitmap(), x1, y, x2, color.color);
drawingMode(MODE_SOLID);
}
void Bitmap::vLine( const int y1, const int x, const int y2, const Color color ) const{
::vline( getData()->getBitmap(), x, y1, y2, color.color );
}
void Bitmap::polygon( const int * verts, const int nverts, const Color color ) const{
::polygon( getData()->getBitmap(), nverts, verts, color.color );
}
/* These values are specified in 16.16 fixed point format, with 256 equal to
* a full circle, 64 a right angle, etc. Zero is to the right of the centre
* point, and larger values rotate anticlockwise from there.
*/
static const double RAD_TO_DEG = 180.0/Util::pi;
static const double DEG_TO_RAD = Util::pi/180.0;
static double toDegrees(double radians){
return RAD_TO_DEG * radians;
}
double toAllegroDegrees(double radians){
return toDegrees(radians) * 256.0 / 365;
}
void Bitmap::arc(const int x, const int y, const double ang1, const double ang2, const int radius, const Color color ) const {
::fixed angle1 = ::ftofix(toAllegroDegrees(-(ang1 - Util::pi/2)));
::fixed angle2 = ::ftofix(toAllegroDegrees(-(ang2 - Util::pi/2)));
if (angle1 > angle2){
::fixed swap = angle1;
angle1 = angle2;
angle2 = swap;
}
::arc(getData()->getBitmap(), x, y, angle1, angle2, radius, color.color);
}
void TranslucentBitmap::arc(const int x, const int y, const double ang1, const double ang2, const int radius, const Color color ) const {
drawingMode(MODE_TRANS);
Bitmap::arc(x, y, ang1, ang2, radius, color);
drawingMode(MODE_SOLID);
}
struct ArcPoint{
int x;
int y;
};
struct ArcPoints{
ArcPoints(int radius):
next(0),
size(0){
/* 1/4th of the circumference = 2 * pi * r / 4 */
size = (Util::pi * radius / 2);
if (size < 2){
size = 2;
}
points = new ArcPoint[size];
}
void save(int x, int y){
if (next < size){
points[next].x = x;
points[next].y = y;
next += 1;
}
}
~ArcPoints(){
delete[] points;
}
ArcPoint * points;
int next;
int size;
};
void store_arc_points(BITMAP * _store, int x, int y, int color){
ArcPoints * store = (ArcPoints*) _store;
store->save(x, y);
}
void drawFilledArc(const int x, const int y, ::fixed angle1, ::fixed angle2, int radius, Color color, BITMAP * paint){
// num_segments = fabs(delta_theta / (2 * ALLEGRO_PI) * ALLEGRO_PRIM_QUALITY * sqrtf(r));
ArcPoints store(radius);
do_arc((BITMAP*) &store, x, y, angle1, angle2, radius, color.color, store_arc_points);
/* for each point on the arc draw a vertical line */
for (int index = 0; index < store.next; index += 1){
int x1 = x;
int y1 = y;
int x2 = store.points[index].x;
int y2 = store.points[index].y;
::vline(paint, x2, y1, y2, color.color);
}
}
void Bitmap::arcFilled(const int x, const int y, const double ang1, const double ang2, const int radius, const Color color ) const{
::fixed angle1 = ::ftofix(toAllegroDegrees(-(ang1 - Util::pi/2)));
::fixed angle2 = ::ftofix(toAllegroDegrees(-(ang2 - Util::pi/2)));
if (angle1 > angle2){
::fixed swap = angle1;
angle1 = angle2;
angle2 = swap;
}
drawFilledArc(x, y, angle1, angle2, radius, color, getData()->getBitmap());
}
void TranslucentBitmap::arcFilled(const int x, const int y, const double ang1, const double ang2, const int radius, const Color color ) const {
drawingMode(MODE_TRANS);
Bitmap::arcFilled(x, y, ang1, ang2, radius, color);
drawingMode(MODE_SOLID);
}
/*
void Bitmap::clear(){
this->fill( 0 );
}
*/
void Bitmap::fill( Color color ) const{
::clear_to_color( getData()->getBitmap(), color.color );
}
/*
void TranslucentBitmap::fill(int color) const {
rectangleFill(0, 0, getWidth(), getHeight(), color);
}
*/
void Bitmap::draw( const int x, const int y, const Bitmap & where ) const {
paintown_draw_sprite_ex16( where.getData()->getBitmap(), getData()->getBitmap(), x, y, SPRITE_NORMAL, SPRITE_NO_FLIP, NULL);
// ::draw_sprite( where.getData().getBitmap(), getBitmap(), x, y );
}
void Bitmap::draw(const int x, const int y, Filter * filter, const Bitmap & where) const {
paintown_draw_sprite_ex16( where.getData()->getBitmap(), getData()->getBitmap(), x, y, SPRITE_NORMAL, SPRITE_NO_FLIP, filter);
}
void Bitmap::drawHFlip( const int x, const int y, const Bitmap & where ) const {
paintown_draw_sprite_ex16( where.getData()->getBitmap(), getData()->getBitmap(), x, y, SPRITE_NORMAL, SPRITE_H_FLIP, NULL);
// ::draw_sprite_h_flip( where.getBitmap(), getBitmap(), x, y );
}
void Bitmap::drawHFlip( const int x, const int y, Filter * filter, const Bitmap & where ) const {
paintown_draw_sprite_ex16( where.getData()->getBitmap(), getData()->getBitmap(), x, y, SPRITE_NORMAL, SPRITE_H_FLIP, filter);
// ::draw_sprite_h_flip( where.getBitmap(), getBitmap(), x, y );
}
void Bitmap::drawVFlip( const int x, const int y, const Bitmap & where ) const {
paintown_draw_sprite_ex16( where.getData()->getBitmap(), getData()->getBitmap(), x, y, SPRITE_NORMAL, SPRITE_V_FLIP, NULL);
}
void Bitmap::drawVFlip( const int x, const int y, Filter * filter, const Bitmap & where ) const {
paintown_draw_sprite_ex16( where.getData()->getBitmap(), getData()->getBitmap(), x, y, SPRITE_NORMAL, SPRITE_V_FLIP, filter);
}
void Bitmap::drawHVFlip( const int x, const int y, const Bitmap & where ) const {
paintown_draw_sprite_ex16( where.getData()->getBitmap(), getData()->getBitmap(), x, y, SPRITE_NORMAL, SPRITE_V_FLIP | SPRITE_H_FLIP, NULL);
}
void Bitmap::drawHVFlip( const int x, const int y, Filter * filter, const Bitmap & where ) const {
paintown_draw_sprite_ex16( where.getData()->getBitmap(), getData()->getBitmap(), x, y, SPRITE_NORMAL, SPRITE_V_FLIP | SPRITE_H_FLIP, filter);
}
/*
void Bitmap::drawLit( const int x, const int y, const int level, const Bitmap & where ) const{
::draw_lit_sprite( where.getBitmap(), getBitmap(), x, y, level );
}
*/
void TranslucentBitmap::draw( const int x, const int y, const Bitmap & where ) const{
// ::draw_trans_sprite( where.getBitmap(), getBitmap(), x, y );
paintown_draw_sprite_ex16( where.getData()->getBitmap(), getData()->getBitmap(), x, y, SPRITE_TRANS, SPRITE_NO_FLIP, NULL);
}
void TranslucentBitmap::draw( const int x, const int y, Filter * filter, const Bitmap & where ) const{
// ::draw_trans_sprite( where.getBitmap(), getBitmap(), x, y );
paintown_draw_sprite_ex16( where.getData()->getBitmap(), getData()->getBitmap(), x, y, SPRITE_TRANS, SPRITE_NO_FLIP, filter);
}
void TranslucentBitmap::drawHFlip( const int x, const int y, const Bitmap & where ) const {
paintown_draw_sprite_ex16( where.getData()->getBitmap(), getData()->getBitmap(), x, y, SPRITE_TRANS, SPRITE_H_FLIP, NULL);
}
void TranslucentBitmap::drawHFlip( const int x, const int y, Filter * filter, const Bitmap & where ) const {
paintown_draw_sprite_ex16( where.getData()->getBitmap(), getData()->getBitmap(), x, y, SPRITE_TRANS, SPRITE_H_FLIP, filter);
}
void TranslucentBitmap::drawVFlip( const int x, const int y, const Bitmap & where ) const {
paintown_draw_sprite_ex16( where.getData()->getBitmap(), getData()->getBitmap(), x, y, SPRITE_TRANS, SPRITE_V_FLIP, NULL);
}
void TranslucentBitmap::drawVFlip( const int x, const int y, Filter * filter, const Bitmap & where ) const {
paintown_draw_sprite_ex16( where.getData()->getBitmap(), getData()->getBitmap(), x, y, SPRITE_TRANS, SPRITE_V_FLIP, filter);
}
void TranslucentBitmap::drawHVFlip( const int x, const int y, const Bitmap & where ) const {
paintown_draw_sprite_ex16( where.getData()->getBitmap(), getData()->getBitmap(), x, y, SPRITE_TRANS, SPRITE_V_FLIP | SPRITE_H_FLIP, NULL);
}
void TranslucentBitmap::drawHVFlip( const int x, const int y, Filter * filter, const Bitmap & where ) const {
paintown_draw_sprite_ex16( where.getData()->getBitmap(), getData()->getBitmap(), x, y, SPRITE_TRANS, SPRITE_V_FLIP | SPRITE_H_FLIP, filter);
}
void Bitmap::drawRotate( const int x, const int y, const int angle, const Bitmap & where ){
::fixed fang = itofix( (360 - angle) % 360 * 256 / 360 );
::rotate_sprite( where.getData()->getBitmap(), getData()->getBitmap(), x, y, fang );
}
void Bitmap::drawPivot( const int centerX, const int centerY, const int x, const int y, const int angle, const Bitmap & where ){
::fixed fang = ftofix( (double)((360 - angle) % 360) * 256.0 / 360.0 );
::pivot_sprite( where.getData()->getBitmap(), getData()->getBitmap(), x, y, centerX, centerY, fang );
}
void Bitmap::drawPivot( const int centerX, const int centerY, const int x, const int y, const int angle, const double scale, const Bitmap & where ){
::fixed fscale = ftofix(scale);
::fixed fang = ftofix( (double)((360 - angle) % 360) * 256.0 / 360.0 );
::pivot_scaled_sprite( where.getData()->getBitmap(), getData()->getBitmap(), x, y, centerX, centerY, fang, fscale );
}
void Bitmap::drawStretched( const int x, const int y, const int new_width, const int new_height, const Bitmap & who ) const {
BITMAP * bmp = who.getData()->getBitmap();
::masked_stretch_blit( getData()->getBitmap(), bmp, 0, 0, getData()->getBitmap()->w, getData()->getBitmap()->h, x,y, new_width, new_height );
}
void Bitmap::light(int x, int y, int width, int height, int start_y, int focus_alpha, int edge_alpha, Color focus_color, Color edge_color) const {
paintown_light16(getData()->getBitmap(), x, y, width, height, start_y, focus_alpha, edge_alpha, focus_color, edge_color);
}
void Bitmap::applyTrans(const Color color) const {
paintown_applyTrans16(getData()->getBitmap(), color);
}
void Bitmap::StretchBy2( const Bitmap & where ){
BITMAP * bmp = where.getData()->getBitmap();
if ( where.getWidth() == getWidth() && where.getHeight() == getHeight() ){
::blit( getData()->getBitmap(), bmp, 0, 0, 0, 0, getData()->getBitmap()->w, getData()->getBitmap()->h );
return;
}
if ( where.getWidth() != getWidth()*2 ||
where.getHeight() != getHeight()*2 ){
cout<<"Wrong dimensions"<<endl;
cout<<"My: "<< getWidth() << " " << getHeight() << endl;
cout<<"Him: "<<where.getWidth()<< " " << where.getHeight()<<endl;
return;
}
// debug
::stretch_blit( getData()->getBitmap(), bmp, 0, 0, getData()->getBitmap()->w, getData()->getBitmap()->h, 0, 0, bmp->w, bmp->h );
// fblend_2x_stretch( my_bitmap, bmp, 0, 0, 0, 0, my_bitmap->w, my_bitmap->h);
// scale2x_allegro( my_bitmap, bmp, 2 );
// debug
}
void Bitmap::StretchBy4( const Bitmap & where ){
BITMAP * bmp = where.getData()->getBitmap();
if ( where.getWidth() != getWidth()*4 ||
where.getHeight() != getHeight()*4 ){
cout<<"Wrong dimensions"<<endl;
cout<<"My: "<< getWidth() << " " << getHeight() << endl;
cout<<"Him: "<<where.getWidth()<< " " << where.getHeight()<<endl;
cout<<"Scaled: "<<getWidth()*4<<" "<< getHeight()*4<<endl;
return;
}
// fblend_2x_stretch( my_bitmap, bmp, 0, 0, 0, 0, my_bitmap->w, my_bitmap->h);
// scale4x_allegro( my_bitmap, bmp, 2 );
::stretch_blit( getData()->getBitmap(), bmp, 0, 0, getData()->getBitmap()->w, getData()->getBitmap()->h, 0, 0, bmp->w, bmp->h );
}
#if 0
void Bitmap::Stretch( const Bitmap & where ) const {
Stretch( where, 0, 0, getData().getBitmap()->w, getData().getBitmap()->h, 0, 0, where.getData().getBitmap()->w, where.getData().getBitmap()->h );
/*
BITMAP * bmp = where.getBitmap();
::stretch_blit( getBitmap(), bmp, 0, 0, getBitmap()->w, getBitmap()->h, 0, 0, bmp->w, bmp->h );
*/
}
#endif
void Bitmap::StretchHqx(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::StretchXbr(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::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 {
BITMAP * bmp = where.getData()->getBitmap();
::stretch_blit( getData()->getBitmap(), bmp, sourceX, sourceY, sourceWidth, sourceHeight, destX, destY, destWidth, destHeight );
}
#if 0
void Bitmap::Blit( const int x, const int y, const Bitmap & where ) const {
BITMAP * bmp = where.getData().getBitmap();
/*
acquire_bitmap( bmp );
acquire_bitmap( my_bitmap );
*/
::blit( getData().getBitmap(), bmp, 0, 0, x, y, getData().getBitmap()->w, getData().getBitmap()->h );
/*
release_bitmap( my_bitmap );
release_bitmap( bmp );
*/
}
#endif
/*
void Bitmap::Blit( const int mx, const int my, const int wx, const int wy, const Bitmap & where ) const {
BITMAP * bmp = where.getData().getBitmap();
::blit( getData().getBitmap(), bmp, mx, my, wx, wy, getData().getBitmap()->w, getData().getBitmap()->h );
}
*/
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 {
BITMAP * bmp = where.getData()->getBitmap();
::blit( getData()->getBitmap(), bmp, mx, my, wx, wy, width, height );
}
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 {
BITMAP * bmp = where.getData()->getBitmap();
::masked_blit( getData()->getBitmap(), bmp, mx, my, wx, wy, width, height );
}
void Bitmap::BlitToScreen(const int upper_left_x, const int upper_left_y) const {
if ( Scaler == NULL ){
this->Blit( upper_left_x, upper_left_y, *Screen );
} else {
if (upper_left_x != 0 || upper_left_y != 0){
- Bitmap buffer = temporaryBitmap(getWidth(), getHeight());
+ Bitmap buffer(getWidth(), getHeight());
buffer.clear();
this->Blit(upper_left_x, upper_left_y, buffer);
buffer.Stretch(*Scaler);
} else {
this->Stretch(*Scaler);
}
Scaler->Blit( 0, 0, 0, 0, *Screen );
}
}
void Bitmap::BlitAreaToScreen(const int upper_left_x, const int upper_left_y) const {
if ( Scaler != NULL ){
double mult_x = (double) Scaler->getWidth() / (double) SCALE_X;
double mult_y = (double) Scaler->getHeight() / (double) SCALE_Y;
int x = (int)(upper_left_x * mult_x);
int y = (int)(upper_left_y * mult_y);
int w = (int)(this->getWidth() * mult_x);
int h = (int)(this->getHeight() * mult_y);
// printf("ux %d uy %d uw %d uh %d. x %d y %d w %d h %d\n", upper_left_x, upper_left_y, getWidth(), getHeight(), x, y, w, h );
this->Stretch( *Scaler, 0, 0, this->getWidth(), this->getHeight(), x, y, w, h );
Bitmap tmp(*Scaler, x, y, w, h );
tmp.Blit( x, y, *Screen );
// Scaler->Blit( x, y, w, h, *Screen );
} else {
this->Blit( upper_left_x, upper_left_y, *Screen );
}
}
void LitBitmap::draw( const int x, const int y, const Bitmap & where ) const {
paintown_draw_sprite_ex16( where.getData()->getBitmap(), getData()->getBitmap(), x, y, SPRITE_LIT, SPRITE_NO_FLIP, NULL);
}
void LitBitmap::draw( const int x, const int y, Filter * filter, const Bitmap & where ) const {
paintown_draw_sprite_ex16( where.getData()->getBitmap(), getData()->getBitmap(), x, y, SPRITE_LIT, SPRITE_NO_FLIP, filter);
}
void LitBitmap::drawHFlip( const int x, const int y, const Bitmap & where ) const {
paintown_draw_sprite_ex16(where.getData()->getBitmap(), getData()->getBitmap(), x, y, SPRITE_LIT, SPRITE_H_FLIP, NULL);
}
void LitBitmap::drawHFlip( const int x, const int y, Filter * filter, const Bitmap & where ) const {
paintown_draw_sprite_ex16(where.getData()->getBitmap(), getData()->getBitmap(), x, y, SPRITE_LIT, SPRITE_H_FLIP, filter);
}
void LitBitmap::drawVFlip( const int x, const int y, const Bitmap & where ) const {
paintown_draw_sprite_ex16(where.getData()->getBitmap(), getData()->getBitmap(), x, y, SPRITE_LIT, SPRITE_V_FLIP, NULL);
}
void LitBitmap::drawVFlip( const int x, const int y, Filter * filter, const Bitmap & where ) const {
paintown_draw_sprite_ex16(where.getData()->getBitmap(), getData()->getBitmap(), x, y, SPRITE_LIT, SPRITE_V_FLIP, filter);
}
void LitBitmap::drawHVFlip( const int x, const int y, const Bitmap & where ) const {
paintown_draw_sprite_ex16(where.getData()->getBitmap(), getData()->getBitmap(), x, y, SPRITE_LIT, SPRITE_V_FLIP | SPRITE_H_FLIP, NULL);
}
void LitBitmap::drawHVFlip( const int x, const int y, Filter * filter, const Bitmap & where ) const {
paintown_draw_sprite_ex16(where.getData()->getBitmap(), getData()->getBitmap(), x, y, SPRITE_LIT, SPRITE_V_FLIP | SPRITE_H_FLIP, filter);
}
/* this function should be in allegro but its not yet so just store it
* here for now
*/
#define PAINTOWN_DLS_BLENDER BLENDER_FUNC
#define PAINTOWN_DTS_BLENDER BLENDER_FUNC
#define PAINTOWN_MAKE_DLS_BLENDER(a) _blender_func16
#define PAINTOWN_MAKE_DTS_BLENDER() _blender_func16
#define PAINTOWN_PIXEL_PTR unsigned short*
#define PAINTOWN_OFFSET_PIXEL_PTR(p,x) ((PAINTOWN_PIXEL_PTR) (p) + (x))
#define PAINTOWN_INC_PIXEL_PTR(p) ((p)++)
#define PAINTOWN_INC_PIXEL_PTR_EX(p,d) ((p) += d)
#define PAINTOWN_GET_MEMORY_PIXEL(p) (*(p))
#define PAINTOWN_IS_SPRITE_MASK(b,c) ((unsigned long) (c) == (unsigned long) (b)->vtable->mask_color)
#define PAINTOWN_DLSX_BLEND(b,n) ((*(b))(_blender_col_16, (n), _blender_alpha))
#define PAINTOWN_GET_PIXEL(p) bmp_read16((uintptr_t) (p))
#define PAINTOWN_DTS_BLEND(b,o,n) ((*(b))((n), (o), ::_blender_alpha))
#define PAINTOWN_PUT_PIXEL(p,c) bmp_write16((uintptr_t) (p), (c))
#define PAINTOWN_PUT_MEMORY_PIXEL(p,c) (*(p) = (c))
#define PAINTOWN_SET_ALPHA(a) (_blender_alpha = (a))
static void paintown_draw_sprite_ex16( BITMAP * dst, BITMAP * src, int dx, int dy, int mode, int flip, Bitmap::Filter * filter ){
int x, y, w, h;
int x_dir = 1, y_dir = 1;
int dxbeg, dybeg;
int sxbeg, sybeg;
PAINTOWN_DLS_BLENDER lit_blender;
PAINTOWN_DTS_BLENDER trans_blender;
ASSERT(dst);
ASSERT(src);
if ( flip & SPRITE_V_FLIP ){
y_dir = -1;
}
if ( flip & SPRITE_H_FLIP ){
x_dir = -1;
}
if (dst->clip) {
int tmp;
tmp = dst->cl - dx;
sxbeg = ((tmp < 0) ? 0 : tmp);
dxbeg = sxbeg + dx;
tmp = dst->cr - dx;
w = ((tmp > src->w) ? src->w : tmp) - sxbeg;
if (w <= 0)
return;
if ( flip & SPRITE_H_FLIP ){
/* use backward drawing onto dst */
sxbeg = src->w - (sxbeg + w);
dxbeg += w - 1;
}
tmp = dst->ct - dy;
sybeg = ((tmp < 0) ? 0 : tmp);
dybeg = sybeg + dy;
tmp = dst->cb - dy;
h = ((tmp > src->h) ? src->h : tmp) - sybeg;
if (h <= 0)
return;
if ( flip & SPRITE_V_FLIP ){
/* use backward drawing onto dst */
sybeg = src->h - (sybeg + h);
dybeg += h - 1;
}
} else {
w = src->w;
h = src->h;
sxbeg = 0;
sybeg = 0;
dxbeg = dx;
if ( flip & SPRITE_H_FLIP ){
dxbeg = dx + w - 1;
}
dybeg = dy;
if ( flip & SPRITE_V_FLIP ){
dybeg = dy + h - 1;
}
}
lit_blender = PAINTOWN_MAKE_DLS_BLENDER(0);
trans_blender = PAINTOWN_MAKE_DTS_BLENDER();
if (dst->id & (BMP_ID_VIDEO | BMP_ID_SYSTEM)) {
bmp_select(dst);
#if 0
switch (mode){
case Bitmap::SPRITE_NORMAL : {
for (y = 0; y < h; y++) {
PAINTOWN_PIXEL_PTR s = PAINTOWN_OFFSET_PIXEL_PTR(src->line[sybeg + y], sxbeg);
PAINTOWN_PIXEL_PTR d = PAINTOWN_OFFSET_PIXEL_PTR(bmp_write_line(dst, dybeg + y * y_dir), dxbeg);
for (x = w - 1; x >= 0; PAINTOWN_INC_PIXEL_PTR(s), PAINTOWN_INC_PIXEL_PTR_EX(d,x_dir), x--) {
unsigned long c = PAINTOWN_GET_MEMORY_PIXEL(s);
if (!PAINTOWN_IS_SPRITE_MASK(src, c)) {
PAINTOWN_PUT_PIXEL(d, c);
}
}
}
break;
}
case Bitmap::SPRITE_LIT : {
for (y = 0; y < h; y++) {
PAINTOWN_PIXEL_PTR s = PAINTOWN_OFFSET_PIXEL_PTR(src->line[sybeg + y], sxbeg);
PAINTOWN_PIXEL_PTR d = PAINTOWN_OFFSET_PIXEL_PTR(bmp_write_line(dst, dybeg + y * y_dir), dxbeg);
for (x = w - 1; x >= 0; PAINTOWN_INC_PIXEL_PTR(s), PAINTOWN_INC_PIXEL_PTR_EX(d,x_dir), x--) {
unsigned long c = PAINTOWN_GET_MEMORY_PIXEL(s);
if (!PAINTOWN_IS_SPRITE_MASK(src, c)) {
c = PAINTOWN_DLSX_BLEND(lit_blender, c);
PAINTOWN_PUT_PIXEL(d, c);
}
}
}
break;
}
case Bitmap::SPRITE_TRANS : {
for (y = 0; y < h; y++) {
PAINTOWN_PIXEL_PTR s = PAINTOWN_OFFSET_PIXEL_PTR(src->line[sybeg + y], sxbeg);
PAINTOWN_PIXEL_PTR d = PAINTOWN_OFFSET_PIXEL_PTR(bmp_write_line(dst, dybeg + y * y_dir), dxbeg);
for (x = w - 1; x >= 0; PAINTOWN_INC_PIXEL_PTR(s), PAINTOWN_INC_PIXEL_PTR_EX(d,x_dir), x--) {
unsigned long c = PAINTOWN_GET_MEMORY_PIXEL(s);
if (!PAINTOWN_IS_SPRITE_MASK(src, c)) {
c = PAINTOWN_DTS_BLEND(trans_blender, PAINTOWN_GET_PIXEL(d), c);
PAINTOWN_PUT_PIXEL(d, c);
}
}
}
break;
}
}
#endif
for (y = 0; y < h; y++) {
PAINTOWN_PIXEL_PTR s = PAINTOWN_OFFSET_PIXEL_PTR(src->line[sybeg + y], sxbeg);
/* flipped if y_dir is -1 */
PAINTOWN_PIXEL_PTR d = PAINTOWN_OFFSET_PIXEL_PTR(bmp_write_line(dst, dybeg + y * y_dir), dxbeg);
/* d is incremented by x_dir, -1 if flipped */
for (x = w - 1; x >= 0; PAINTOWN_INC_PIXEL_PTR(s), PAINTOWN_INC_PIXEL_PTR_EX(d,x_dir), x--) {
unsigned long c = PAINTOWN_GET_MEMORY_PIXEL(s);
if (!PAINTOWN_IS_SPRITE_MASK(src, c)) {
switch (mode){
case SPRITE_NORMAL: {
if (filter){
c = filter->filter(Color(c)).color;
}
break;
}
case SPRITE_LIT : {
if (filter){
c = PAINTOWN_DLSX_BLEND(lit_blender, filter->filter(Color(c)).color);
} else {
c = PAINTOWN_DLSX_BLEND(lit_blender, c);
}
break;
}
case SPRITE_TRANS : {
if (filter){
c = PAINTOWN_DTS_BLEND(trans_blender, PAINTOWN_GET_PIXEL(d), filter->filter(Color(c)).color);
} else {
c = PAINTOWN_DTS_BLEND(trans_blender, PAINTOWN_GET_PIXEL(d), c);
}
break;
}
}
PAINTOWN_PUT_PIXEL(d, c);
}
}
}
bmp_unwrite_line(dst);
} else {
switch (mode){
case SPRITE_NORMAL : {
for (y = 0; y < h; y++) {
PAINTOWN_PIXEL_PTR s = PAINTOWN_OFFSET_PIXEL_PTR(src->line[sybeg + y], sxbeg);
PAINTOWN_PIXEL_PTR d = PAINTOWN_OFFSET_PIXEL_PTR(bmp_write_line(dst, dybeg + y * y_dir), dxbeg);
for (x = w - 1; x >= 0; PAINTOWN_INC_PIXEL_PTR(s), PAINTOWN_INC_PIXEL_PTR_EX(d,x_dir), x--) {
unsigned long c = PAINTOWN_GET_MEMORY_PIXEL(s);
if (!PAINTOWN_IS_SPRITE_MASK(src, c)) {
if (filter){
PAINTOWN_PUT_MEMORY_PIXEL(d, filter->filter(Color(c)).color);
} else {
PAINTOWN_PUT_MEMORY_PIXEL(d, c);
}
}
}
}
break;
}
case SPRITE_LIT : {
for (y = 0; y < h; y++) {
PAINTOWN_PIXEL_PTR s = PAINTOWN_OFFSET_PIXEL_PTR(src->line[sybeg + y], sxbeg);
PAINTOWN_PIXEL_PTR d = PAINTOWN_OFFSET_PIXEL_PTR(bmp_write_line(dst, dybeg + y * y_dir), dxbeg);
for (x = w - 1; x >= 0; PAINTOWN_INC_PIXEL_PTR(s), PAINTOWN_INC_PIXEL_PTR_EX(d,x_dir), x--) {
unsigned long c = PAINTOWN_GET_MEMORY_PIXEL(s);
if (!PAINTOWN_IS_SPRITE_MASK(src, c)) {
if (filter){
c = PAINTOWN_DLSX_BLEND(lit_blender, filter->filter(Color(c)).color);
} else {
c = PAINTOWN_DLSX_BLEND(lit_blender, c);
}
PAINTOWN_PUT_MEMORY_PIXEL(d, c);
}
}
}
break;
}
case SPRITE_TRANS : {
for (y = 0; y < h; y++) {
PAINTOWN_PIXEL_PTR s = PAINTOWN_OFFSET_PIXEL_PTR(src->line[sybeg + y], sxbeg);
PAINTOWN_PIXEL_PTR d = PAINTOWN_OFFSET_PIXEL_PTR(bmp_write_line(dst, dybeg + y * y_dir), dxbeg);
for (x = w - 1; x >= 0; PAINTOWN_INC_PIXEL_PTR(s), PAINTOWN_INC_PIXEL_PTR_EX(d,x_dir), x--) {
unsigned long c = PAINTOWN_GET_MEMORY_PIXEL(s);
if (!PAINTOWN_IS_SPRITE_MASK(src, c)) {
if (filter){
c = PAINTOWN_DTS_BLEND(trans_blender, PAINTOWN_GET_PIXEL(d), filter->filter(Color(c)).color);
} else {
c = PAINTOWN_DTS_BLEND(trans_blender, PAINTOWN_GET_PIXEL(d), c);
}
PAINTOWN_PUT_MEMORY_PIXEL(d, c);
}
}
}
break;
}
}
#if 0
for (y = 0; y < h; y++) {
PAINTOWN_PIXEL_PTR s = PAINTOWN_OFFSET_PIXEL_PTR(src->line[sybeg + y], sxbeg);
PAINTOWN_PIXEL_PTR d = PAINTOWN_OFFSET_PIXEL_PTR(bmp_write_line(dst, dybeg + y * y_dir), dxbeg);
for (x = w - 1; x >= 0; PAINTOWN_INC_PIXEL_PTR(s), PAINTOWN_INC_PIXEL_PTR_EX(d,x_dir), x--) {
unsigned long c = PAINTOWN_GET_MEMORY_PIXEL(s);
if (!PAINTOWN_IS_SPRITE_MASK(src, c)) {
switch( mode ){
case Bitmap::SPRITE_NORMAL : break;
case Bitmap::SPRITE_LIT : {
c = PAINTOWN_DLSX_BLEND(lit_blender, c);
break;
}
case Bitmap::SPRITE_TRANS : {
c = PAINTOWN_DTS_BLEND(trans_blender, PAINTOWN_GET_PIXEL(d), c);
break;
}
}
PAINTOWN_PUT_MEMORY_PIXEL(d, c);
}
}
}
#endif
}
}
/* mix pixels with the given color in with each non-masking pixel in dst */
static void paintown_applyTrans16(BITMAP * dst, const Color color){
int y1 = 0;
int y2 = dst->h;
int x1 = 0;
int x2 = dst->w - 1;
if (dst->clip){
y1 = dst->ct;
y2 = dst->cb - 1;
x1 = dst->cl;
x2 = dst->cr - 1;
}
PAINTOWN_DTS_BLENDER trans_blender;
trans_blender = PAINTOWN_MAKE_DTS_BLENDER();
if (dst->id & (BMP_ID_VIDEO | BMP_ID_SYSTEM)) {
} else {
for (int y = y1; y < y2; y++) {
PAINTOWN_PIXEL_PTR d = PAINTOWN_OFFSET_PIXEL_PTR(bmp_write_line(dst, y), x1);
for (int x = x2; x >= x1; PAINTOWN_INC_PIXEL_PTR_EX(d,1), x--) {
unsigned long c = PAINTOWN_GET_MEMORY_PIXEL(d);
if (!PAINTOWN_IS_SPRITE_MASK(dst, c)) {
c = PAINTOWN_DTS_BLEND(trans_blender, c, color.color);
PAINTOWN_PUT_MEMORY_PIXEL(d, c);
}
}
}
}
}
/* ultra special-case for drawing a light (like from a lamp).
* center of light is x,y and shines in a perfect isosolese triangle.
*/
static void paintown_light16(BITMAP * dst, const int x, const int y, const int width, const int height, const int start_y, const int focus_alpha, const int edge_alpha, const Color focus_color, const Color edge_color){
int dxbeg = x - width;
int x_dir = 1;
unsigned char * alphas = new unsigned char[width];
Color * colors = new Color[width];
for (int i = 0; i < width; i++){
alphas[i] = (unsigned char)((double)(edge_alpha - focus_alpha) * (double)i / (double)width + focus_alpha);
}
blend_palette(colors, width, focus_color, edge_color);
int min_y, max_y, min_x, max_x;
if (dst->clip){
min_y = dst->ct;
max_y = dst->cb - 1;
min_x = dst->cl;
max_x = dst->cr - 1;
} else {
min_y = y < 0 ? 0 : y;
max_y = dst->h - 1;
min_x = (x-width) < 0 ? 0 : x-width;
max_x = (x+width) > dst->w-1 ? dst->w-1 : x+width;
}
int dybeg = y;
/* tan(theta) = y / x */
double xtan = (double) height / (double) width;
PAINTOWN_DTS_BLENDER trans_blender;
trans_blender = PAINTOWN_MAKE_DTS_BLENDER();
if (dst->id & (BMP_ID_VIDEO | BMP_ID_SYSTEM)) {
} else {
for (int sy = start_y; sy < height; sy++) {
if (dybeg + sy < min_y || dybeg + sy > max_y){
continue;
}
/* x = y / tan(theta) */
int top_width = (int)((double) sy / xtan);
if (top_width == 0){
continue;
}
dxbeg = x - top_width;
PAINTOWN_PIXEL_PTR d = PAINTOWN_OFFSET_PIXEL_PTR(bmp_write_line(dst, dybeg + sy), dxbeg);
for (int sx = -top_width; sx <= top_width; PAINTOWN_INC_PIXEL_PTR_EX(d,x_dir), sx++) {
if (sx + x < min_x || sx + x > max_x){
continue;
}
unsigned long c = PAINTOWN_GET_MEMORY_PIXEL(d);
/* TODO:
* converting to a double and calling fabs is overkill, just
* write an integer abs() function.
*/
int sx_abs = (int) fabs((double) sx);
PAINTOWN_SET_ALPHA(alphas[sx_abs]);
int color = colors[sx_abs].color;
c = PAINTOWN_DTS_BLEND(trans_blender, c, color);
PAINTOWN_PUT_MEMORY_PIXEL(d, c);
}
}
}
delete[] alphas;
delete[] colors;
}
/* there is a bug in this function that causes memory corruption. if that bug
* is ever found then use this method, otherwise don't use it.
*/
static void paintown_draw_sprite_ex16_old( BITMAP * dst, BITMAP * src, int dx, int dy, int mode, int flip, Bitmap::Filter * filter){
int x, y, w, h;
int x_dir = 1, y_dir = 1;
int dxbeg, dybeg;
int sxbeg, sybeg;
PAINTOWN_DLS_BLENDER lit_blender;
PAINTOWN_DTS_BLENDER trans_blender;
ASSERT(dst);
ASSERT(src);
if ( flip & SPRITE_V_FLIP ){
y_dir = -1;
}
if ( flip & SPRITE_H_FLIP ){
x_dir = -1;
}
if (dst->clip) {
int tmp;
tmp = dst->cl - dx;
sxbeg = ((tmp < 0) ? 0 : tmp);
dxbeg = sxbeg + dx;
tmp = dst->cr - dx;
w = ((tmp > src->w) ? src->w : tmp) - sxbeg;
if (w <= 0)
return;
if ( flip & SPRITE_H_FLIP ){
/* use backward drawing onto dst */
sxbeg = src->w - (sxbeg + w);
dxbeg += w - 1;
}
tmp = dst->ct - dy;
sybeg = ((tmp < 0) ? 0 : tmp);
dybeg = sybeg + dy;
tmp = dst->cb - dy;
h = ((tmp > src->h) ? src->h : tmp) - sybeg;
if (h <= 0)
return;
if ( flip & SPRITE_V_FLIP ){
/* use backward drawing onto dst */
sybeg = src->h - (sybeg + h);
dybeg += h - 1;
}
} else {
w = src->w;
h = src->h;
sxbeg = 0;
sybeg = 0;
dxbeg = dx;
if ( flip & SPRITE_H_FLIP ){
dxbeg = dx + w - 1;
}
dybeg = dy;
if ( flip & SPRITE_V_FLIP ){
dybeg = dy + h - 1;
}
}
lit_blender = PAINTOWN_MAKE_DLS_BLENDER(0);
trans_blender = PAINTOWN_MAKE_DTS_BLENDER();
if (dst->id & (BMP_ID_VIDEO | BMP_ID_SYSTEM)) {
bmp_select(dst);
for (y = 0; y < h; y++) {
PAINTOWN_PIXEL_PTR s = PAINTOWN_OFFSET_PIXEL_PTR(src->line[sybeg + y], sxbeg);
/* flipped if y_dir is -1 */
PAINTOWN_PIXEL_PTR d = PAINTOWN_OFFSET_PIXEL_PTR(bmp_write_line(dst, dybeg + y * y_dir), dxbeg);
/* d is incremented by x_dir, -1 if flipped */
for (x = w - 1; x >= 0; PAINTOWN_INC_PIXEL_PTR(s), PAINTOWN_INC_PIXEL_PTR_EX(d,x_dir), x--) {
unsigned long c = PAINTOWN_GET_MEMORY_PIXEL(s);
if (!PAINTOWN_IS_SPRITE_MASK(src, c)) {
switch( mode ){
case SPRITE_NORMAL : break;
case SPRITE_LIT : {
if (filter){
c = PAINTOWN_DLSX_BLEND(lit_blender, filter->filter(Color(c)).color);
} else {
c = PAINTOWN_DLSX_BLEND(lit_blender, c);
}
break;
}
case SPRITE_TRANS : {
if (filter){
c = PAINTOWN_DTS_BLEND(trans_blender, PAINTOWN_GET_PIXEL(d), filter->filter(Color(c)).color);
} else {
c = PAINTOWN_DTS_BLEND(trans_blender, PAINTOWN_GET_PIXEL(d), c);
}
break;
}
}
PAINTOWN_PUT_PIXEL(d, c);
}
}
}
bmp_unwrite_line(dst);
}
else {
for (y = 0; y < h; y++) {
PAINTOWN_PIXEL_PTR s = PAINTOWN_OFFSET_PIXEL_PTR(src->line[sybeg + y], sxbeg);
PAINTOWN_PIXEL_PTR d = PAINTOWN_OFFSET_PIXEL_PTR(bmp_write_line(dst, dybeg + y * y_dir), dxbeg);
for (x = w - 1; x >= 0; PAINTOWN_INC_PIXEL_PTR(s), PAINTOWN_INC_PIXEL_PTR_EX(d,x_dir), x--) {
unsigned long c = PAINTOWN_GET_MEMORY_PIXEL(s);
if (!PAINTOWN_IS_SPRITE_MASK(src, c)) {
switch( mode ){
case SPRITE_NORMAL : break;
case SPRITE_LIT : {
if (filter){
c = PAINTOWN_DLSX_BLEND(lit_blender, filter->filter(Color(c)).color);
} else {
c = PAINTOWN_DLSX_BLEND(lit_blender, c);
}
break;
}
case SPRITE_TRANS : {
if (filter){
c = PAINTOWN_DTS_BLEND(trans_blender, PAINTOWN_GET_PIXEL(d), filter->filter(Color(c)).color);
} else {
c = PAINTOWN_DTS_BLEND(trans_blender, PAINTOWN_GET_PIXEL(d), c);
}
break;
}
}
PAINTOWN_PUT_MEMORY_PIXEL(d, c);
}
}
}
}
}
static void paintown_draw_sprite_filter_ex16(BITMAP * dst, BITMAP * src, int dx, int dy, const Bitmap::Filter & filter){
int x, y, w, h;
int x_dir = 1, y_dir = 1;
int dxbeg, dybeg;
int sxbeg, sybeg;
if (true /* dst->clip*/ ) {
int tmp;
tmp = dst->cl - dx;
sxbeg = ((tmp < 0) ? 0 : tmp);
dxbeg = sxbeg + dx;
tmp = dst->cr - dx;
w = ((tmp > src->w) ? src->w : tmp) - sxbeg;
if (w <= 0)
return;
tmp = dst->ct - dy;
sybeg = ((tmp < 0) ? 0 : tmp);
dybeg = sybeg + dy;
tmp = dst->cb - dy;
h = ((tmp > src->h) ? src->h : tmp) - sybeg;
if (h <= 0)
return;
}
unsigned int mask = MaskColor().color;
// int bpp = src->format->BytesPerPixel;
for (y = 0; y < h; y++) {
PAINTOWN_PIXEL_PTR s = PAINTOWN_OFFSET_PIXEL_PTR(src->line[sybeg + y], sxbeg);
PAINTOWN_PIXEL_PTR d = PAINTOWN_OFFSET_PIXEL_PTR(bmp_write_line(dst, dybeg + y * y_dir), dxbeg);
for (x = w - 1; x >= 0; PAINTOWN_INC_PIXEL_PTR(s), PAINTOWN_INC_PIXEL_PTR_EX(d,x_dir), x--) {
unsigned long c = PAINTOWN_GET_MEMORY_PIXEL(s);
if (!PAINTOWN_IS_SPRITE_MASK(src, c)) {
PAINTOWN_PUT_MEMORY_PIXEL(d, filter.filter(Color(c)).color);
} else {
PAINTOWN_PUT_MEMORY_PIXEL(d, mask);
}
}
}
}
}
#include "../software-renderer/bitmap.cpp"
diff --git a/util/graphics/allegro5/bitmap.cpp b/util/graphics/allegro5/bitmap.cpp
index 5e7e4170..fbffd461 100644
--- a/util/graphics/allegro5/bitmap.cpp
+++ b/util/graphics/allegro5/bitmap.cpp
@@ -1,1542 +1,1542 @@
#include <sstream>
#include <allegro5/allegro5.h>
#include <allegro5/allegro_memfile.h>
#include <allegro5/allegro_primitives.h>
#include "util/debug.h"
#include "util/thread.h"
#include <vector>
namespace Graphics{
ALLEGRO_DISPLAY * the_display = NULL;
static std::vector<ALLEGRO_SHADER*> shaders;
// static ALLEGRO_SHADER * shader_default;
static ALLEGRO_SHADER * shader_shadow;
static ALLEGRO_SHADER * shader_lit_sprite;
enum BlendingType{
Translucent,
Add,
Difference,
Multiply
};
struct BlendingData{
BlendingData():
red(0), green(0), blue(0), alpha(0), type(Translucent){
}
int red, green, blue, alpha;
BlendingType type;
};
static BlendingData globalBlend;
Color makeColorAlpha(unsigned char red, unsigned char green, unsigned char blue, unsigned char alpha){
return Color(al_map_rgba(red, green, blue, alpha));
}
Color MaskColor(){
static Color mask = makeColorAlpha(0, 0, 0, 0);
return mask;
}
Color getBlendColor(){
/* sort of a hack */
if (globalBlend.type == Multiply){
return makeColorAlpha(255, 255, 255, 255);
}
return makeColorAlpha(255, 255, 255, globalBlend.alpha);
}
Color doTransBlend(const Color & color, int alpha){
unsigned char red, green, blue;
al_unmap_rgb(color.color, &red, &green, &blue);
return makeColorAlpha(red, green, blue, alpha);
/*
red *= alpha_f;
green *= alpha_f;
blue *= alpha_f;
return al_map_rgb_f(red, green, blue);
*/
}
Color transBlendColor(const Color & color){
return doTransBlend(color, globalBlend.alpha);
}
int getRealWidth(const Bitmap & what){
return al_get_bitmap_width(what.getData()->getBitmap());
}
int getRealHeight(const Bitmap & what){
return al_get_bitmap_height(what.getData()->getBitmap());
}
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_ALPHA, ALLEGRO_INVERSE_ALPHA);
}
};
class LitBlender: public Blender {
public:
LitBlender(ALLEGRO_COLOR lit){
// al_set_blend_color(lit);
// al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE_MINUS_DST_COLOR, ALLEGRO_ZERO);
}
};
class TransBlender: public Blender {
public:
TransBlender(){
switch (globalBlend.type){
case Translucent: al_set_blender(ALLEGRO_ADD, ALLEGRO_ALPHA, ALLEGRO_INVERSE_ALPHA); break;
case Add: al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_ONE); break;
case Multiply: al_set_blender(ALLEGRO_ADD, ALLEGRO_DST_COLOR, ALLEGRO_INVERSE_ALPHA); break;
case Difference: al_set_blender(ALLEGRO_DEST_MINUS_SRC, ALLEGRO_ONE, ALLEGRO_ONE); break;
}
}
};
static const int WINDOWED = 0;
static const int FULLSCREEN = 1;
// static Bitmap * Scaler = NULL;
Bitmap::Bitmap():
mustResize(false),
bit8MaskColor(makeColor(0, 0, 0)),
width(0),
height(0){
/* TODO */
}
Bitmap::Bitmap( const char * load_file ):
mustResize(false),
bit8MaskColor(makeColor(0, 0, 0)){
internalLoadFile(load_file);
width = al_get_bitmap_width(getData()->getBitmap());
height = al_get_bitmap_height(getData()->getBitmap());
}
Bitmap::Bitmap( const std::string & load_file ):
mustResize(false),
bit8MaskColor(makeColor(0, 0, 0)){
internalLoadFile(load_file.c_str());
width = al_get_bitmap_width(getData()->getBitmap());
height = al_get_bitmap_height(getData()->getBitmap());
}
Bitmap::Bitmap(ALLEGRO_BITMAP * who, bool deep_copy):
mustResize(false),
bit8MaskColor(makeColor(0, 0, 0)){
if (deep_copy){
ALLEGRO_BITMAP * clone = al_clone_bitmap(who);
setData(Util::ReferenceCount<BitmapData>(new BitmapData(clone)));
} else {
setData(Util::ReferenceCount<BitmapData>(new BitmapData(who)));
}
this->width = al_get_bitmap_width(getData()->getBitmap());
this->height = al_get_bitmap_height(getData()->getBitmap());
}
Bitmap::Bitmap(int width, int height):
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());
}
/*
if (al_get_bitmap_flags(bitmap) & ALLEGRO_VIDEO_BITMAP){
ALLEGRO_BITMAP * old = al_get_target_bitmap();
al_set_target_bitmap(bitmap);
al_use_shader(shader_default);
al_set_target_bitmap(old);
}
*/
setData(Util::ReferenceCount<BitmapData>(new BitmapData(bitmap)));
this->width = al_get_bitmap_width(getData()->getBitmap());
this->height = al_get_bitmap_height(getData()->getBitmap());
}
Bitmap::Bitmap( const Bitmap & copy, bool deep_copy):
mustResize(false),
bit8MaskColor(copy.bit8MaskColor),
width(copy.width),
height(copy.height){
if (deep_copy){
ALLEGRO_BITMAP * clone = al_clone_bitmap(copy.getData()->getBitmap());
setData(Util::ReferenceCount<BitmapData>(new BitmapData(clone)));
} else {
setData(copy.getData());
}
}
void Bitmap::convertToVideo(){
ALLEGRO_BITMAP * original = getData()->getBitmap();
ALLEGRO_BITMAP * copy = al_clone_bitmap(original);
if (copy == NULL){
throw BitmapException(__FILE__, __LINE__, "Could not create video bitmap");
}
al_destroy_bitmap(getData()->getBitmap());
getData()->setBitmap(copy);
/*
if (al_get_bitmap_flags(copy) & ALLEGRO_VIDEO_BITMAP){
ALLEGRO_BITMAP * old = al_get_target_bitmap();
al_set_target_bitmap(copy);
al_use_shader(shader_default);
al_set_target_bitmap(old);
}
*/
}
void changeTarget(const Bitmap & from, const Bitmap & who){
/* pray that if drawing is held then who is already the current target */
if (!al_is_bitmap_drawing_held()){
if (al_get_target_bitmap() != who.getData()->getBitmap()){
al_set_target_bitmap(who.getData()->getBitmap());
}
if ((al_get_bitmap_flags(who.getData()->getBitmap()) & ALLEGRO_VIDEO_BITMAP) &&
(al_get_bitmap_flags(from.getData()->getBitmap()) & ALLEGRO_MEMORY_BITMAP)){
((Bitmap&) from).convertToVideo();
/* How can from == who? If they were the same then the bitmap flags above
* would not have been different.
*/
if (&from == &who){
al_set_target_bitmap(who.getData()->getBitmap());
}
}
}
}
void changeTarget(const Bitmap * from, const Bitmap & who){
changeTarget(*from, who);
}
void changeTarget(const Bitmap & from, const Bitmap * who){
changeTarget(from, *who);
}
void changeTarget(const Bitmap * from, const Bitmap * who){
changeTarget(*from, *who);
}
void dumpColor(const Color & color){
unsigned char red, green, blue, alpha;
al_unmap_rgba(color.color, &red, &green, &blue, &alpha);
Global::debug(0) << "red " << (int) red << " green " << (int) green << " blue " << (int) blue << " alpha " << (int) alpha << std::endl;
}
Color pcxMaskColor(unsigned char * data, const int length){
if (length >= 769){
if (data[length - 768 - 1] == 12){
unsigned char * palette = &data[length - 768];
unsigned char red = palette[0];
unsigned char green = palette[1];
unsigned char blue = palette[2];
return makeColorAlpha(red, green, blue, 255);
}
}
return makeColorAlpha(255, 255, 255, 255);
}
Bitmap memoryPCX(unsigned char * const data, const int length, const bool mask){
ALLEGRO_FILE * memory = al_open_memfile((void *) data, length, "r");
ALLEGRO_BITMAP * pcx = al_load_bitmap_f(memory, ".pcx");
al_fclose(memory);
if (pcx == NULL){
throw BitmapException(__FILE__, __LINE__, "Could not load pcx");
}
// dumpColor(al_get_pixel(pcx, 0, 0));
Bitmap out(pcx);
out.set8BitMaskColor(pcxMaskColor(data, length));
return out;
}
static bool isVideoBitmap(ALLEGRO_BITMAP * bitmap){
return (al_get_bitmap_flags(bitmap) & ALLEGRO_VIDEO_BITMAP) &&
!(al_get_bitmap_flags(bitmap) & ALLEGRO_MEMORY_BITMAP);
}
void Bitmap::replaceColor(const Color & original, const Color & replaced){
changeTarget(this, this);
if (isVideoBitmap(getData()->getBitmap())){
al_lock_bitmap(getData()->getBitmap(), ALLEGRO_PIXEL_FORMAT_ANY, ALLEGRO_LOCK_READWRITE);
}
int width = getRealWidth(*this);
int height = getRealHeight(*this);
for (int x = 0; x < width; x++){
for (int y = 0; y < height; y++){
Color pixel = getPixel(x, y);
if (pixel == original){
al_put_pixel(x, y, replaced.color);
}
}
}
if (isVideoBitmap(getData()->getBitmap())){
al_unlock_bitmap(getData()->getBitmap());
}
}
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());
}
al_convert_mask_to_alpha(loaded, al_map_rgb(255, 0, 255));
setData(Util::ReferenceCount<BitmapData>(new BitmapData(loaded)));
}
static ALLEGRO_BITMAP * do_load_from_memory(const char * data, int length, const char * type){
ALLEGRO_FILE * memory = al_open_memfile((void*) data, length, "r");
ALLEGRO_BITMAP * bitmap = al_load_bitmap_f(memory, type);
al_fclose(memory);
al_convert_mask_to_alpha(bitmap, al_map_rgb(255, 0, 255));
return bitmap;
}
static ALLEGRO_BITMAP * load_bitmap_from_memory(const char * data, int length, ImageFormat type){
switch (type){
case FormatBMP: return do_load_from_memory(data, length, ".bmp");
case FormatPNG: return do_load_from_memory(data, length, ".png");
case FormatJPG: return do_load_from_memory(data, length, ".jpg");
case FormatPCX: return do_load_from_memory(data, length, ".pcx");
case FormatTGA: return do_load_from_memory(data, length, ".tga");
case FormatTIF: return do_load_from_memory(data, length, ".tif");
case FormatXPM: return do_load_from_memory(data, length, ".xpm");
case FormatUnknown: break;
case FormatGIF : {
return memoryGIF(data, length);
break;
}
}
std::ostringstream out;
out << "Could not load the bitmap because its format was not known";
throw BitmapException(__FILE__, __LINE__, out.str());
}
Bitmap::Bitmap(const char * data, int length):
mustResize(false),
bit8MaskColor(makeColor(0, 0, 0)){
loadFromMemory(data, length);
}
void Bitmap::loadFromMemory(const char * data, int length){
setData(Util::ReferenceCount<BitmapData>(new BitmapData(load_bitmap_from_memory(data, length, identifyImage((const unsigned char *) data, length)))));
if (getData()->getBitmap() == NULL){
std::ostringstream out;
out << "Could not create bitmap from memory";
throw BitmapException(__FILE__, __LINE__, out.str());
}
width = al_get_bitmap_width(getData()->getBitmap());
height = al_get_bitmap_height(getData()->getBitmap());
}
Bitmap::Bitmap( const Bitmap & copy, int x, int y, int width, int height ):
mustResize(false),
bit8MaskColor(copy.bit8MaskColor),
width(width),
height(height){
path = copy.getPath();
ALLEGRO_BITMAP * his = copy.getData()->getBitmap();
if (x < 0)
x = 0;
if (y < 0)
y = 0;
if (width < 1 || height < 1){
std::ostringstream out;
out << "Attempting to create a sub-bitmap.";
if (width < 1){
out << " Width was less than 1: " << width;
}
if (height < 1){
out << " Height was less than 1: " << height;
}
throw BitmapException(__FILE__, __LINE__, out.str());
}
/*
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 * old_target = al_get_target_bitmap();
ALLEGRO_TRANSFORM transform;
al_identity_transform(&transform);
if (al_get_target_bitmap() != copy.getData()->getBitmap()){
al_set_target_bitmap(copy.getData()->getBitmap());
}
if (al_get_current_transform() != NULL){
if (old_target != copy.getData()->getBitmap()){
al_set_target_bitmap(copy.getData()->getBitmap());
}
al_copy_transform(&transform, al_get_current_transform());
}
float x_scaled = x;
float y_scaled = y;
float width_scaled = width;
float height_scaled = height;
al_transform_coordinates(&transform, &x_scaled, &y_scaled);
al_transform_coordinates(&transform, &width_scaled, &height_scaled);
// ALLEGRO_BITMAP * sub = al_create_sub_bitmap(his, x, y, width, height);
ALLEGRO_BITMAP * sub = al_create_sub_bitmap(his, (int) x_scaled, (int) y_scaled, (int) width_scaled, (int) height_scaled);
// ALLEGRO_BITMAP * sub = al_create_sub_bitmap(his, (int) x_scaled, (int) y_scaled, width, height);
setData(Util::ReferenceCount<BitmapData>(new BitmapData(sub)));
al_set_target_bitmap(sub);
al_use_transform(&transform);
al_set_target_bitmap(old_target);
}
static bool isBackBuffer(ALLEGRO_BITMAP * bitmap){
return bitmap == al_get_backbuffer(the_display);
}
int Bitmap::getWidth() const {
/* Always return the true dimensions of the backbuffer */
if (getData() != NULL && isBackBuffer(getData()->getBitmap())){
return al_get_bitmap_width(getData()->getBitmap());
}
return width;
/*
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.color, &red, &green, &blue);
return red;
}
int getAlpha(Color color){
unsigned char red, green, blue, alpha;
al_unmap_rgba(color.color, &red, &green, &blue, &alpha);
return alpha;
}
int getGreen(Color color){
unsigned char red, green, blue;
al_unmap_rgb(color.color, &red, &green, &blue);
return green;
}
int getBlue(Color color){
unsigned char red, green, blue;
al_unmap_rgb(color.color, &red, &green, &blue);
return blue;
}
Color makeColor(int red, int blue, int green){
return Color(al_map_rgb(red, blue, green));
}
int Bitmap::getHeight() const {
if (getData() != NULL && isBackBuffer(getData()->getBitmap())){
return al_get_bitmap_height(getData()->getBitmap());
}
return height;
/*
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);
}
std::string defaultVertexShader(){
return std::string(al_get_default_shader_source(ALLEGRO_SHADER_GLSL, ALLEGRO_VERTEX_SHADER));
}
std::string defaultPixelShader(){
return std::string(al_get_default_shader_source(ALLEGRO_SHADER_GLSL, ALLEGRO_PIXEL_SHADER));
}
void setShaderSampler(ALLEGRO_SHADER * shader, const std::string & name, const Bitmap & texture, int unit){
al_set_shader_sampler(name.c_str(), texture.getData()->getBitmap(), unit);
}
void setShaderBool(ALLEGRO_SHADER * shader, const std::string & name, bool value){
setShaderInt(shader, name, value);
}
void setShaderInt(ALLEGRO_SHADER * shader, const std::string & name, int value){
al_set_shader_int(name.c_str(), value);
}
void setShaderFloat(ALLEGRO_SHADER * shader, const std::string & name, float value){
al_set_shader_float(name.c_str(), value);
}
void setShaderVec4(ALLEGRO_SHADER * shader, const std::string & name, float v1, float v2, float v3, float v4){
float vector[4];
vector[0] = v1;
vector[1] = v2;
vector[2] = v3;
vector[3] = v4;
al_set_shader_float_vector(name.c_str(), 4, &vector[0], 1);
}
ALLEGRO_SHADER * create_shader(const std::string & vertex, const std::string & pixel){
ALLEGRO_SHADER * shader = al_create_shader(ALLEGRO_SHADER_GLSL);
if (shader == NULL){
return NULL;
}
if (!al_attach_shader_source(shader, ALLEGRO_VERTEX_SHADER, vertex.c_str())){
Global::debug(0) << "attach vertex shader source failed: " << al_get_shader_log(shader) << std::endl << vertex << std::endl;
return NULL;
}
if (!al_attach_shader_source(shader, ALLEGRO_PIXEL_SHADER, pixel.c_str())){
Global::debug(0) << "attach pixel shader source failed: " << al_get_shader_log(shader) << std::endl << pixel << std::endl;
return NULL;
}
if (!al_build_shader(shader)){
Global::debug(0) << "shader al_link_shader failed: " << al_get_shader_log(shader) << std::endl;
return NULL;
}
return shader;
}
int changeGraphicsMode(int mode, int width, int height){
/* FIXME: handle mode */
return !al_resize_display(the_display, width, height);
}
static int createShaders(){
try{
shader_shadow = create_shader(defaultVertexShader(), Storage::readFile(Storage::instance().find(Filesystem::RelativePath("shaders/shadow.fragment.glsl"))));
if (shader_shadow == NULL){
return 1;
}
shaders.push_back(shader_shadow);
Global::debug(1) << "Created shadow shader" << std::endl;
} catch (const Filesystem::NotFound & fail){
Global::debug(0) << "Could not load shadow shader: " << fail.getTrace() << std::endl;
return 1;
}
try{
shader_lit_sprite = create_shader(defaultVertexShader(), Storage::readFile(Storage::instance().find(Filesystem::RelativePath("shaders/lit-sprite.fragment.glsl"))));
if (shader_lit_sprite == NULL){
return 1;
}
shaders.push_back(shader_lit_sprite);
Global::debug(1) << "Created lit sprite shader" << std::endl;
} catch (const Filesystem::NotFound & fail){
Global::debug(0) << "Could not load lit sprite shader: " << fail.getTrace() << std::endl;
return 1;
}
return 0;
}
int setGraphicsMode(int mode, int width, int height){
initializeExtraStuff();
/* FIXME: the configuration should pass in fullscreen mode here */
#ifdef IPHONE
mode = FULLSCREEN;
#endif
switch (mode){
case FULLSCREEN: {
#ifdef IPHONE
al_set_new_display_option(ALLEGRO_SUPPORTED_ORIENTATIONS, ALLEGRO_DISPLAY_ORIENTATION_LANDSCAPE, ALLEGRO_SUGGEST);
al_set_new_display_flags(ALLEGRO_FULLSCREEN_WINDOW | ALLEGRO_PROGRAMMABLE_PIPELINE);
#else
al_set_new_display_flags(ALLEGRO_FULLSCREEN | ALLEGRO_PROGRAMMABLE_PIPELINE);
#endif
break;
}
case WINDOWED: {
al_set_new_display_flags(ALLEGRO_WINDOWED | ALLEGRO_RESIZABLE |
ALLEGRO_PROGRAMMABLE_PIPELINE |
ALLEGRO_OPENGL);
break;
}
default: break;
}
the_display = al_create_display(width, height);
if (the_display == NULL){
std::ostringstream out;
out << "Could not create display with dimensions " << width << ", " << height;
throw BitmapException(__FILE__, __LINE__, out.str());
}
// Global::debug(0) << "Set width " << al_get_display_width(the_display) << " height " << al_get_display_height(the_display) << std::endl;
// Global::debug(0) << "Backbuffer width " << al_get_bitmap_width(al_get_backbuffer(the_display)) << " height " << al_get_bitmap_height(al_get_backbuffer(the_display)) << std::endl;
try{
/* TODO: maybe find a more general way to get the icon */
ALLEGRO_BITMAP * icon = al_load_bitmap(Storage::instance().find(Filesystem::RelativePath("menu/icon.bmp")).path().c_str());
if (icon != NULL){
al_set_display_icon(the_display, icon);
}
} catch (const Filesystem::NotFound & fail){
Global::debug(0) << "Could not set window icon: " << fail.getTrace() << std::endl;
}
Screen = new Bitmap(al_get_backbuffer(the_display));
/* dont destroy the backbuffer */
Screen->getData()->setDestroy(false);
/*
ALLEGRO_TRANSFORM transformation;
al_identity_transform(&transformation);
al_scale_transform(&transformation, (double) Screen->getWidth() / (double) width, (double) Screen->getHeight() / (double) height);
al_set_target_bitmap(Screen->getData()->getBitmap());
al_use_transform(&transformation);
*/
// Scaler = new Bitmap(width, height);
/* default drawing mode */
// al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_ZERO);
al_set_blender(ALLEGRO_ADD, ALLEGRO_ALPHA, ALLEGRO_INVERSE_ALPHA);
// shader_default = create_shader(defaultVertexShader(), defaultPixelShader());
// al_use_shader(shader_default);
/* Default shader */
/*
shader_default = al_create_shader(ALLEGRO_SHADER_GLSL);
al_attach_shader_source(shader_default, ALLEGRO_VERTEX_SHADER, al_get_default_glsl_vertex_shader());
al_attach_shader_source(shader_default, ALLEGRO_PIXEL_SHADER, al_get_default_glsl_pixel_shader());
if (!al_link_shader(shader_default)){
Global::debug(0) << "default shader al_link_shader failed: " << al_get_shader_log(shader_default) << std::endl;
return 1;
}
*/
// al_set_shader(the_display, shader_default);
// shaders.push_back(shader_default);
// Global::debug(1) << "Created default shader" << std::endl;
if (createShaders()){
return 1;
}
return 0;
}
void Bitmap::lock() const {
al_lock_bitmap(getData()->getBitmap(), ALLEGRO_PIXEL_FORMAT_ANY, ALLEGRO_LOCK_READWRITE);
}
void Bitmap::lock(int x, int y, int width, int height) const {
al_lock_bitmap_region(getData()->getBitmap(), x, y, width, height, ALLEGRO_PIXEL_FORMAT_ANY, ALLEGRO_LOCK_READWRITE);
}
void Bitmap::unlock() const {
al_unlock_bitmap(getData()->getBitmap());
}
Color Bitmap::getPixel(const int x, const int y) const {
// changeTarget(this, this);
return Color(al_get_pixel(getData()->getBitmap(), x, y));
}
void Bitmap::putPixel(int x, int y, Color pixel) const {
changeTarget(this, this);
// al_put_pixel(x, y, pixel);
al_draw_pixel(x, y, pixel.color);
}
void Bitmap::putPixelNormal(int x, int y, Color col) const {
putPixel(x, y, col);
/*
changeTarget(this, this);
al_put_pixel(x, y, col.color);
*/
}
void Bitmap::fill(Color color) const {
changeTarget(this, this);
al_clear_to_color(color.color);
}
void Bitmap::startDrawing() const {
/* we are about to draw on this bitmap so make sure we are the target */
changeTarget(this, this);
al_hold_bitmap_drawing(true);
}
void Bitmap::endDrawing() const {
al_hold_bitmap_drawing(false);
}
void TranslucentBitmap::startDrawing() const {
al_set_blender(ALLEGRO_ADD, ALLEGRO_ALPHA, ALLEGRO_INVERSE_ALPHA);
}
void TranslucentBitmap::endDrawing() const {
al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_ZERO);
}
Color Bitmap::blendColor(const Color & input) const {
return input;
}
Color TranslucentBitmap::blendColor(const Color & color) const {
unsigned char red, green, blue;
unsigned char alpha = globalBlend.alpha;
al_unmap_rgb(color.color, &red, &green, &blue);
return makeColorAlpha(red, green, blue, alpha);
}
void Bitmap::StretchHqx(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::StretchXbr(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::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 {
changeTarget(this, where);
al_draw_scaled_bitmap(getData()->getBitmap(),
sourceX, sourceY, sourceWidth, sourceHeight,
destX, destY, destWidth, destHeight,
0);
}
void Bitmap::StretchBy2(const Bitmap & where){
Stretch(where, 0, 0, getWidth(), getHeight(), 0, 0, getWidth() * 2, getHeight() * 2);
}
void Bitmap::StretchBy4(const Bitmap & where){
Stretch(where, 0, 0, getWidth(), getHeight(), 0, 0, getWidth() * 4, getHeight() * 4);
}
void Bitmap::drawRotate(const int x, const int y, const int angle, const Bitmap & where ){
changeTarget(this, where);
MaskedBlender blender;
al_draw_rotated_bitmap(getData()->getBitmap(), getWidth() / 2, getHeight() / 2, x, y, Util::radians(angle), ALLEGRO_FLIP_HORIZONTAL);
}
void Bitmap::drawPivot( const int centerX, const int centerY, const int x, const int y, const int angle, const Bitmap & where ){
changeTarget(this, where);
MaskedBlender blender;
al_draw_rotated_bitmap(getData()->getBitmap(), getWidth() / 2, getHeight() / 2, x, y, Util::radians(-angle), 0);
}
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 {
/* FIXME */
changeTarget(this, who);
MaskedBlender blender;
al_draw_scaled_bitmap(getData()->getBitmap(), 0, 0, al_get_bitmap_width(getData()->getBitmap()), al_get_bitmap_height(getData()->getBitmap()), x, y, new_width, new_height, 0);
#if 0
ALLEGRO_TRANSFORM save;
al_copy_transform(&save, al_get_current_transform());
ALLEGRO_TRANSFORM stretch;
al_identity_transform(&stretch);
// al_translate_transform(&stretch, x / ((double) new_width / getWidth()), y / ((double) new_height / getHeight()));
al_scale_transform(&stretch, (double) new_width / getWidth(), (double) new_height / getHeight());
al_translate_transform(&stretch, x, y);
// al_translate_transform(&stretch, -x / ((double) new_width / getWidth()), -y / ((double) (new_height / getHeight())));
al_use_transform(&stretch);
/* any source pixels with an alpha value of 0 will be masked */
// al_draw_bitmap(getData().getBitmap(), x, y, 0);
al_draw_bitmap(getData().getBitmap(), 0, 0, 0);
al_use_transform(&save);
#endif
}
Bitmap Bitmap::scaleTo(const int width, const int height) const {
if (width == getRealWidth(*this) && height == getRealHeight(*this)){
return *this;
}
Bitmap scaled(width, height);
changeTarget(*this, scaled);
al_draw_scaled_bitmap(getData()->getBitmap(), 0, 0, getRealWidth(*this), getRealHeight(*this),
0, 0, width, height, 0);
return scaled;
}
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();
// changeTarget(this, where);
// al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_ZERO);
/*
if (&where != Screen){
al_draw_bitmap(getData().getBitmap(), wx, wy, 0);
}
*/
changeTarget(this, where);
Bitmap part(*this, mx, my, width, height);
// al_use_shader(shader_default);
// al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_ZERO);
al_draw_bitmap(part.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 {
draw(x, y, NULL, where, ALLEGRO_FLIP_HORIZONTAL);
}
void Bitmap::drawHFlip(const int x, const int y, Filter * filter, const Bitmap & where) const {
draw(x, y, filter, where, ALLEGRO_FLIP_HORIZONTAL);
}
void Bitmap::drawVFlip( const int x, const int y, const Bitmap & where ) const {
draw(x, y, NULL, where, ALLEGRO_FLIP_VERTICAL);
}
void Bitmap::drawVFlip( const int x, const int y, Filter * filter, const Bitmap & where ) const {
draw(x, y, filter, where, ALLEGRO_FLIP_VERTICAL);
}
void Bitmap::drawHVFlip( const int x, const int y, const Bitmap & where ) const {
draw(x, y, NULL, where, ALLEGRO_FLIP_HORIZONTAL | ALLEGRO_FLIP_VERTICAL);
}
void Bitmap::drawHVFlip( const int x, const int y, Filter * filter, const Bitmap & where ) const {
draw(x, y, filter, where, ALLEGRO_FLIP_HORIZONTAL | ALLEGRO_FLIP_VERTICAL);
}
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();
}
*/
changeTarget(this, Screen);
if (getData()->getBitmap() != Screen->getData()->getBitmap()){
Blit(*Screen);
}
al_flip_display();
}
void Bitmap::BlitAreaToScreen(const int upper_left_x, const int upper_left_y) const {
changeTarget(this, Screen);
/*
if (getData()->getBitmap() != Screen->getData()->getBitmap()){
Blit(upper_left_y, upper_left_y, *Screen);
}
*/
al_flip_display();
}
void Bitmap::draw(const int x, const int y, Filter * filter, const Bitmap & where, int flags) const {
changeTarget(this, where);
MaskedBlender blender;
Util::ReferenceCount<Shader> shader;
if (filter != NULL){
shader = filter->getShader();
}
ALLEGRO_SHADER * a5shader = NULL;
if (shader != NULL){
a5shader = shader->getShader();
}
if (a5shader != NULL){
al_use_shader(a5shader);
filter->setupShader(shader);
}
/* any source pixels with an alpha value of 0 will be masked */
al_draw_bitmap(getData()->getBitmap(), x, y, flags);
if (a5shader != NULL){
al_use_shader(NULL);
}
}
void Bitmap::draw(const int x, const int y, const Bitmap & where) const {
draw(x, y, NULL, where, 0);
/*
// TransBlender blender;
changeTarget(this, where);
MaskedBlender blender;
/ * any source pixels with an alpha value of 0 will be masked * /
al_draw_bitmap(getData()->getBitmap(), x, y, 0);
*/
}
void Bitmap::draw(const int x, const int y, Filter * filter, const Bitmap & where) const {
draw(x, y, filter, where, 0);
}
void Bitmap::drawShadow(Bitmap & where, int x, int y, int intensity, Color color, double scale, bool facingRight) const {
changeTarget(this, where);
MaskedBlender blender;
int newHeight = fabs(scale) * getHeight();
int flags = 0;
if (!facingRight){
flags |= ALLEGRO_FLIP_HORIZONTAL;
}
float shadowColor[4];
al_unmap_rgb_f(color.color, &shadowColor[0], &shadowColor[1], &shadowColor[2]);
shadowColor[3] = (float) intensity / 255.0;
al_use_shader(shader_shadow);
if (!al_set_shader_float_vector("shadow", 4, shadowColor, 1)){
/* Well.. thats not good. Did the shader source get messed up? */
}
al_draw_scaled_bitmap(getData()->getBitmap(), 0, 0, getWidth(), getHeight(), x, y - newHeight, getWidth(), newHeight, flags);
al_use_shader(NULL);
}
void Bitmap::hLine(const int x1, const int y, const int x2, const Color color) const {
line(x1, y, x2, y, color);
}
void Bitmap::vLine(const int y1, const int x, const int y2, const Color color) const {
line(x, y1, x, y2, color);
}
void Bitmap::arc(const int x, const int y, const double ang1, const double ang2, const int radius, const Color color ) const {
changeTarget(this, this);
al_draw_arc(x, y, radius, ang1 - Util::pi/2, ang2 - ang1, color.color, 1);
}
void TranslucentBitmap::arc(const int x, const int y, const double ang1, const double ang2, const int radius, const Color color ) const {
TransBlender blender;
Bitmap::arc(x, y, ang1, ang2, radius, transBlendColor(color));
/*
changeTarget(this);
al_draw_arc(x, y, radius, ang1 + S_PI/2, ang2 - ang1, doTransBlend(color, globalBlend.alpha), 0);
*/
}
/* from http://www.allegro.cc/forums/thread/605684/892721#target */
#if 0
void al_draw_filled_pieslice(float cx, float cy, float r, float start_theta,
float delta_theta, ALLEGRO_COLOR color){
ALLEGRO_VERTEX vertex_cache[ALLEGRO_VERTEX_CACHE_SIZE];
int num_segments, ii;
num_segments = fabs(delta_theta / (2 * ALLEGRO_PI) * ALLEGRO_PRIM_QUALITY * sqrtf(r));
if (num_segments < 2)
return;
if (num_segments >= ALLEGRO_VERTEX_CACHE_SIZE) {
num_segments = ALLEGRO_VERTEX_CACHE_SIZE - 1;
}
al_calculate_arc(&(vertex_cache[1].x), sizeof(ALLEGRO_VERTEX), cx, cy, r, r, start_theta, delta_theta, 0, num_segments);
vertex_cache[0].x = cx; vertex_cache[0].y = cy;
for (ii = 0; ii < num_segments + 1; ii++) {
vertex_cache[ii].color = color;
vertex_cache[ii].z = 0;
}
al_draw_prim(vertex_cache, NULL, NULL, 0, num_segments + 1, ALLEGRO_PRIM_TRIANGLE_FAN);
// al_draw_prim(vertex_cache, NULL, NULL, 0, 3, ALLEGRO_PRIM_TRIANGLE_FAN);
}
#endif
void Bitmap::arcFilled(const int x, const int y, const double ang1, const double ang2, const int radius, const Color color ) const {
changeTarget(this, this);
al_draw_filled_pieslice(x, y, radius, ang1 - Util::pi/2, ang2 - ang1, color.color);
}
void TranslucentBitmap::arcFilled(const int x, const int y, const double ang1, const double ang2, const int radius, const Color color ) const {
TransBlender blender;
Bitmap::arcFilled(x, y, ang1, ang2, radius, transBlendColor(color));
}
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 {
al_draw_line(x1, y1, x2, y2, color.color, 1.5);
}
void TranslucentBitmap::line(const int x1, const int y1, const int x2, const int y2, const Color color) const {
TransBlender blender;
Bitmap::line(x1, y1, x2, y2, transBlendColor(color));
}
void Bitmap::circleFill(int x, int y, int radius, Color color) const {
changeTarget(this, this);
al_draw_filled_circle(x, y, radius, color.color);
}
void Bitmap::circle(int x, int y, int radius, Color color) const {
changeTarget(this, this);
al_draw_circle(x, y, radius, color.color, 0);
}
void Bitmap::circle(int x, int y, int radius, int thickness, Color color) const {
changeTarget(this, this);
al_draw_circle(x, y, radius, color.color, thickness);
}
void Bitmap::rectangle( int x1, int y1, int x2, int y2, Color color ) const {
changeTarget(this, this);
al_draw_rectangle(x1, y1, x2, y2, color.color, 0);
}
void Bitmap::rectangleFill( int x1, int y1, int x2, int y2, Color color ) const {
changeTarget(this, this);
al_draw_filled_rectangle(x1 - 0.5, y1 - 0.5, x2 + 0.5, y2 + 0.5, color.color);
}
void Bitmap::triangle( int x1, int y1, int x2, int y2, int x3, int y3, Color color ) const {
changeTarget(this, this);
al_draw_filled_triangle(x1, y1, x2, y2, x3, y3, color.color);
}
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 {
changeTarget(this, this);
al_draw_ellipse(x, y, rx, ry, color.color, 0);
}
void Bitmap::ellipseFill( int x, int y, int rx, int ry, Color color ) const {
changeTarget(this, this);
al_draw_filled_ellipse(x, y, rx, ry, color.color);
}
void Bitmap::applyTrans(const Color color) const {
TransBlender blender;
changeTarget(this, this);
al_draw_filled_rectangle(0, 0, getWidth(), getHeight(), transBlendColor(color).color);
}
void Bitmap::light(int x, int y, int width, int height, int start_y, int focus_alpha, int edge_alpha, Color focus_color, Color edge_color) const {
/* TODO */
}
void Bitmap::drawCharacter( const int x, const int y, const Color 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, Filter * filter, const Bitmap & where, int flags) const {
changeTarget(this, where);
TransBlender blender;
Util::ReferenceCount<Shader> shader;
if (filter != NULL){
shader = filter->getShader();
}
ALLEGRO_SHADER * a5shader = NULL;
if (shader != NULL){
a5shader = shader->getShader();
}
if (a5shader != NULL){
al_use_shader(a5shader);
filter->setupShader(shader);
}
al_draw_tinted_bitmap(getData()->getBitmap(), getBlendColor().color, x, y, flags);
if (a5shader != NULL){
al_use_shader(NULL);
}
}
void TranslucentBitmap::draw(const int x, const int y, const Bitmap & where) const {
draw(x, y, NULL, where, 0);
}
void LitBitmap::draw(const int x, const int y, const Bitmap & where) const {
draw(x, y, NULL, where, 0);
}
void LitBitmap::draw(const int x, const int y, Filter * filter, const Bitmap & where, int flags) const {
if (filter == NULL){
changeTarget(this, where);
/*
TransBlender blender;
Util::ReferenceCount<Shader> shader;
if (filter != NULL){
shader = filter->getShader();
}
ALLEGRO_SHADER * a5shader = NULL;
if (shader != NULL){
a5shader = shader->getShader();
}
if (a5shader != NULL){
al_set_shader(the_display, a5shader);
al_use_shader(a5shader, true);
}
al_draw_tinted_bitmap(getData()->getBitmap(), getBlendColor().color, x, y, flags);
if (a5shader != NULL){
al_set_shader(the_display, shader_default);
al_use_shader(shader_default, true);
}
*/
MaskedBlender blender;
ALLEGRO_SHADER * shader = shader_lit_sprite;
float light[4];
Color color = makeColor(globalBlend.red, globalBlend.green, globalBlend.blue);
al_unmap_rgb_f(color.color, &light[0], &light[1], &light[2]);
light[3] = 1;
float intensity = (float) globalBlend.alpha / 255.0;
al_use_shader(shader);
if (!al_set_shader_float_vector("light_color", 4, light, 1)){
/* Well.. thats not good. Did the shader source get messed up? */
}
if (!al_set_shader_float("light_intensity", intensity)){
}
al_draw_bitmap(getData()->getBitmap(), x, y, flags);
al_use_shader(NULL);
} else {
- Bitmap temp = temporaryBitmap(getWidth(), getHeight());
+ Bitmap temp(getWidth(), getHeight());
temp.fill(MaskColor());
Bitmap::draw(0, 0, filter, temp, 0);
LitBitmap(temp).draw(x, y, NULL, where, flags);
}
}
void LitBitmap::draw( const int x, const int y, Filter * filter, const Bitmap & where ) const {
draw(x, y, filter, where, 0);
// LitBlender blender(makeColorAlpha(globalBlend.red, globalBlend.green, globalBlend.blue, globalBlend.alpha));
// TransBlender blender;
// al_draw_bitmap(getData()->getBitmap(), x, y, 0);
// al_draw_tinted_bitmap(getData()->getBitmap(), al_map_rgba_f(1, 0, 0, 1), x, y, 0);
}
void LitBitmap::drawHFlip( const int x, const int y, const Bitmap & where ) const {
draw(x, y, NULL, where, ALLEGRO_FLIP_HORIZONTAL);
}
void LitBitmap::drawHFlip( const int x, const int y, Filter * filter, const Bitmap & where ) const {
draw(x, y, filter, where, ALLEGRO_FLIP_HORIZONTAL);
}
void LitBitmap::drawVFlip( const int x, const int y, const Bitmap & where ) const {
draw(x, y, NULL, where, ALLEGRO_FLIP_VERTICAL);
}
void LitBitmap::drawVFlip( const int x, const int y, Filter * filter, const Bitmap & where ) const {
draw(x, y, filter, where, ALLEGRO_FLIP_VERTICAL);
}
void LitBitmap::drawHVFlip( const int x, const int y, const Bitmap & where ) const {
draw(x, y, NULL, where, ALLEGRO_FLIP_HORIZONTAL | ALLEGRO_FLIP_VERTICAL);
}
void LitBitmap::drawHVFlip( const int x, const int y, Filter * filter, const Bitmap & where ) const {
draw(x, y, filter, where, ALLEGRO_FLIP_HORIZONTAL | ALLEGRO_FLIP_VERTICAL);
}
void TranslucentBitmap::draw( const int x, const int y, Filter * filter, const Bitmap & where ) const {
draw(x, y, filter, where, 0);
}
void TranslucentBitmap::drawHFlip( const int x, const int y, const Bitmap & where ) const {
draw(x, y, NULL, where, ALLEGRO_FLIP_HORIZONTAL);
}
void TranslucentBitmap::drawHFlip( const int x, const int y, Filter * filter, const Bitmap & where ) const {
draw(x, y, filter, where, ALLEGRO_FLIP_HORIZONTAL);
}
void TranslucentBitmap::drawVFlip( const int x, const int y, const Bitmap & where ) const {
draw(x, y, NULL, where, ALLEGRO_FLIP_VERTICAL);
}
void TranslucentBitmap::drawVFlip( const int x, const int y, Filter * filter, const Bitmap & where ) const {
draw(x, y, filter, where, ALLEGRO_FLIP_VERTICAL);
}
void TranslucentBitmap::drawHVFlip( const int x, const int y, const Bitmap & where ) const {
draw(x, y, NULL, where, ALLEGRO_FLIP_HORIZONTAL | ALLEGRO_FLIP_VERTICAL);
}
void TranslucentBitmap::drawHVFlip( const int x, const int y, Filter * filter,const Bitmap & where ) const {
draw(x, y, filter, where, ALLEGRO_FLIP_HORIZONTAL | ALLEGRO_FLIP_VERTICAL);
}
void TranslucentBitmap::hLine( const int x1, const int y, const int x2, const Color color ) const {
TransBlender blender;
Bitmap::hLine(x1, y, x2, doTransBlend(color, globalBlend.alpha));
}
void TranslucentBitmap::circleFill(int x, int y, int radius, Color color) const {
TransBlender blender;
Bitmap::circleFill(x, y, radius, doTransBlend(color, globalBlend.alpha));
}
void TranslucentBitmap::putPixelNormal(int x, int y, Color color) const {
TransBlender blender;
Bitmap::putPixelNormal(x, y, doTransBlend(color, globalBlend.alpha));
}
void TranslucentBitmap::rectangle( int x1, int y1, int x2, int y2, Color color ) const {
TransBlender blender;
Bitmap::rectangle(x1, y1, x2, y2, doTransBlend(color, globalBlend.alpha));
}
void TranslucentBitmap::rectangleFill(int x1, int y1, int x2, int y2, Color color) const {
TransBlender blender;
Bitmap::rectangleFill(x1, y1, x2, y2, doTransBlend(color, globalBlend.alpha));
}
void TranslucentBitmap::ellipse( int x, int y, int rx, int ry, Color color ) const {
TransBlender blender;
Bitmap::ellipse(x, y, rx, ry, doTransBlend(color, globalBlend.alpha));
}
void TranslucentBitmap::ellipseFill( int x, int y, int rx, int ry, Color color ) const {
TransBlender blender;
Bitmap::ellipseFill(x, y, rx, ry, doTransBlend(color, globalBlend.alpha));
}
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 */
}
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::alphaBlender(int source, int dest){
/* 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.type = Translucent;
}
void Bitmap::addBlender(int r, int g, int b, int a){
globalBlend.red = r;
globalBlend.green = g;
globalBlend.blue = b;
globalBlend.alpha = a;
globalBlend.type = Add;
}
void Bitmap::differenceBlender( int r, int g, int b, int a ){
globalBlend.red = r;
globalBlend.green = g;
globalBlend.blue = b;
globalBlend.alpha = a;
globalBlend.type = Difference;
}
void Bitmap::multiplyBlender( int r, int g, int b, int a ){
globalBlend.red = r;
globalBlend.green = g;
globalBlend.blue = b;
globalBlend.alpha = a;
globalBlend.type = Multiply;
}
/*
void Bitmap::drawingMode(int type){
}
*/
void Bitmap::shutdown(){
/* Make sure the display is set */
al_set_target_bitmap(Screen->getData()->getBitmap());
al_use_shader(NULL);
for (std::vector<ALLEGRO_SHADER*>::iterator it = shaders.begin(); it != shaders.end(); it++){
ALLEGRO_SHADER * shader = *it;
al_destroy_shader(shader);
}
delete Screen;
Screen = NULL;
al_destroy_display(the_display);
the_display = NULL;
/*
delete Scaler;
Scaler = NULL;
delete Buffer;
Buffer = NULL;
*/
}
StretchedBitmap::StretchedBitmap(int width, int height, const Bitmap & parent, QualityFilter filter):
Bitmap(parent, 0, 0, parent.getWidth(), parent.getHeight()),
width(width),
height(height),
where(parent),
filter(filter){
scale_x = (double) parent.getWidth() / width;
scale_y = (double) parent.getHeight() / height;
ALLEGRO_BITMAP * old_target = al_get_target_bitmap();
if (al_get_target_bitmap() != parent.getData()->getBitmap()){
al_set_target_bitmap(parent.getData()->getBitmap());
}
ALLEGRO_TRANSFORM transform;
al_identity_transform(&transform);
if (al_get_current_transform() != NULL){
al_copy_transform(&transform, al_get_current_transform());
}
al_scale_transform(&transform, scale_x, scale_y);
if (al_get_target_bitmap() != getData()->getBitmap()){
al_set_target_bitmap(getData()->getBitmap());
}
al_use_transform(&transform);
if (old_target != al_get_target_bitmap()){
al_set_target_bitmap(old_target);
}
/* TODO: handle filter */
}
void StretchedBitmap::start(){
#if 0
ALLEGRO_TRANSFORM transform;
changeTarget(this, this);
al_copy_transform(&transform, al_get_current_transform());
// al_identity_transform(&transform);
// al_scale_transform(&transform, Bitmap::getWidth() / width, Bitmap::getHeight() / height);
al_scale_transform(&transform, scale_x, scale_y);
al_use_transform(&transform);
#endif
}
void StretchedBitmap::finish(){
#if 0
ALLEGRO_TRANSFORM transform;
changeTarget(this, this);
al_copy_transform(&transform, al_get_current_transform());
/* apply the inverse transform */
al_scale_transform(&transform, 1.0/scale_x, 1.0/scale_y);
// al_identity_transform(&transform);
al_use_transform(&transform);
#endif
}
TranslatedBitmap::TranslatedBitmap(int x, int y, const Bitmap & where):
Bitmap(where),
x(x),
y(y){
ALLEGRO_TRANSFORM transform;
changeTarget(this, where);
al_identity_transform(&transform);
if (al_get_current_transform() != NULL){
al_copy_transform(&transform, al_get_current_transform());
}
al_translate_transform(&transform, x, y);
al_use_transform(&transform);
}
void TranslatedBitmap::BlitToScreen() const {
Bitmap::BlitToScreen();
}
TranslatedBitmap::~TranslatedBitmap(){
ALLEGRO_TRANSFORM transform;
al_copy_transform(&transform, al_get_current_transform());
al_translate_transform(&transform, -x, -y);
al_use_transform(&transform);
}
Bitmap * getScreenBuffer(){
return Screen;
}
RestoreState::RestoreState(){
al_store_state(&state, ALLEGRO_STATE_ALL);
}
RestoreState::~RestoreState(){
al_restore_state(&state);
}
Shader::Shader():
shader(NULL){
}
Shader::~Shader(){
if (shader != NULL){
al_destroy_shader(shader);
}
}
Shader::Shader(ALLEGRO_SHADER * shader):
shader(shader){
}
ALLEGRO_SHADER * Shader::getShader(){
return shader;
}
}
static inline bool close(float x, float y){
static float epsilon = 0.001;
return fabs(x - y) < epsilon;
}
static inline bool sameColor(const ALLEGRO_COLOR & color1, const ALLEGRO_COLOR & color2){
// return memcmp(&color1, &color2, sizeof(Graphics::Color)) == 0;
float r1, g1, b1, a1;
float r2, g2, b2, a2;
al_unmap_rgba_f(color1, &r1, &g1, &b1, &a1);
al_unmap_rgba_f(color2, &r2, &g2, &b2, &a2);
return close(r1, r2) &&
close(g1, g2) &&
close(b1, b2) &&
close(a1, a2);
/*
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/graphics/bitmap.cpp b/util/graphics/bitmap.cpp
index d3ec91e6..39de2179 100644
--- a/util/graphics/bitmap.cpp
+++ b/util/graphics/bitmap.cpp
@@ -1,593 +1,595 @@
#include "../funcs.h"
#include "bitmap.h"
#include "../file-system.h"
#include <string>
#include <stdio.h>
#include <math.h>
namespace Graphics{
static Bitmap * Screen = NULL;
/* bitmaps that should always be resized to the dimensions of the screen */
static std::vector<Bitmap*> needResize;
Util::Parameter<Bitmap*> screenParameter;
Util::Parameter<Util::ReferenceCount<ShaderManager> > shaderManager;
ShaderManager::ShaderManager(){
}
ShaderManager::~ShaderManager(){
}
Util::ReferenceCount<Shader> ShaderManager::getShader(const std::string & name, Util::ReferenceCount<Shader> (*create)()){
std::map<std::string, Util::ReferenceCount<Shader> >::iterator it = shaders.find(name);
if (it == shaders.end()){
shaders[name] = create();
it = shaders.find(name);
}
return it->second;
}
/* implementation independant definitions can go here */
Bitmap * Bitmap::temporary_bitmap = NULL;
Bitmap * Bitmap::temporary_bitmap2 = NULL;
/*
int SCALE_X = 0;
int SCALE_Y = 0;
*/
/*
const int Bitmap::MODE_TRANS = 0;
const int Bitmap::MODE_SOLID = 1;
*/
const int SPRITE_NO_FLIP = 0;
const int SPRITE_V_FLIP = 1;
const int SPRITE_H_FLIP = 2;
const int SPRITE_NORMAL = 1;
const int SPRITE_LIT = 2;
const int SPRITE_TRANS = 3;
static inline int max(int a, int b){
return a > b ? a : b;
}
INTERNAL_COLOR Color::defaultColor(){
return makeColor(0, 0, 0).color;
}
void initializeExtraStuff();
Bitmap::Bitmap(Storage::File & file):
mustResize(false),
error(false),
bit8MaskColor(makeColor(0, 0, 0)){
int length = file.getSize();
if (length == -1){
throw BitmapException(__FILE__, __LINE__, std::string("Could not read from file"));
}
char * data = new char[length];
try{
file.readLine(data, length);
loadFromMemory(data, length);
delete[] data;
} catch (const BitmapException & fail){
delete[] data;
throw;
} catch (...){
delete[] data;
throw;
}
}
QualityFilter qualityFilterName(const std::string & type){
if (type == "xbr"){
return XbrFilter;
}
if (type == "hqx"){
return HqxFilter;
}
return NoFilter;
}
Bitmap::~Bitmap(){
if (mustResize){
for (std::vector<Bitmap*>::iterator it = needResize.begin(); it != needResize.end(); it++){
Bitmap * who = *it;
if (who == this){
needResize.erase(it);
break;
}
}
}
}
static Bitmap makeTemporaryBitmap(Bitmap *& temporary, int w, int h){
if (temporary == NULL){
temporary = new Bitmap(w, h);
} else if (temporary->getWidth() < w || temporary->getHeight() < h){
int mw = max(temporary->getWidth(), w);
int mh = max(temporary->getHeight(), h);
// printf("Create temporary bitmap %d %d\n", mw, mh);
delete temporary;
temporary = new Bitmap(mw, mh);
}
if (temporary == NULL){
printf("*bug* temporary bitmap is null\n");
}
return Bitmap(*temporary, 0, 0, w, h);
}
+/*
Bitmap Bitmap::temporaryBitmap(int w, int h){
return makeTemporaryBitmap(temporary_bitmap, w, h);
}
Bitmap Bitmap::temporaryBitmap2(int w, int h){
return makeTemporaryBitmap(temporary_bitmap2, w, h);
}
+*/
void Bitmap::cleanupTemporaryBitmaps(){
if (temporary_bitmap != NULL){
delete temporary_bitmap;
temporary_bitmap = NULL;
}
if (temporary_bitmap2 != NULL){
delete temporary_bitmap2;
temporary_bitmap2 = NULL;
}
}
Bitmap & Bitmap::operator=(const Bitmap & copy){
path = copy.getPath();
this->width = copy.getWidth();
this->height = copy.getHeight();
setData(copy.getData());
return *this;
}
double Bitmap::getScale(){
/* the game is pretty much hard coded to run at 320 scaled upto 640
* and then scaled to whatever the user wants, but as long as
* 320 and 640 remain this number will be 2.
* maybe calculate this at some point
*/
return 2;
/*
if (Scaler != NULL && Buffer != NULL){
double x1 = Scaler->getWidth();
double x2 = Buffer->getWidth();
return x2 / x1;
}
return 1;
*/
}
/* taken from the color addon from allegro 4.9 */
static void al_color_cmyk_to_rgb(float cyan, float magenta, float yellow, float key, float *red, float *green, float *blue){
float max = 1 - key;
*red = max - cyan * max;
*green = max - magenta * max;
*blue = max - yellow * max;
}
void Bitmap::cymkToRGB(int c, int y, int m, int k, int * r, int * g, int * b){
float fc = (float)c / 255.0;
float fy = (float)y / 255.0;
float fm = (float)m / 255.0;
float fk = (float)k / 255.0;
float fr, fg, fb;
al_color_cmyk_to_rgb(fc, fm, fy, fk, &fr, &fg, &fb);
*r = (int)(fr * 255.0);
*g = (int)(fg * 255.0);
*b = (int)(fb * 255.0);
}
void Bitmap::updateOnResize(){
if (!mustResize){
mustResize = true;
needResize.push_back(this);
}
}
void Bitmap::updateSize(const int width, const int height){
if (getWidth() == width && getHeight() == height){
return;
}
Bitmap created(width, height);
*this = created;
}
/* resize the internal bitmap. not guaranteed to destroy the internal bitmap */
void Bitmap::resize(const int width, const int height){
/* if internal bitmap is already the proper size, do nothing */
if (getWidth() == width && getHeight() == height){
return;
}
Bitmap created(width, height);
Stretch(created);
*this = created;
}
/* decrement bitmap reference counter and free memory if counter hits 0 */
#if 0
void Bitmap::releaseInternalBitmap(){
const int MAGIC_DEBUG = 0xa5a5a5;
if (own != NULL){
if (*own == MAGIC_DEBUG){
printf("[bitmap] Trying to delete an already deleted reference counter %p\n", own);
}
(*own) -= 1;
if ( *own == 0 ){
*own = MAGIC_DEBUG;
delete own;
destroyPrivateData();
own = NULL;
}
}
}
#endif
void Bitmap::BlitToScreen() const {
// this->Blit( *Bitmap::Screen );
this->BlitToScreen(0, 0);
}
void Bitmap::load( const std::string & str ){
// releaseInternalBitmap();
internalLoadFile( str.c_str() );
}
Bitmap Bitmap::scaleBy(const double widthRatio, const double heightRatio) const {
return scaleTo(getWidth() * widthRatio, getHeight() * heightRatio);
}
void Bitmap::border( int min, int max, Color color ) const {
int w = getWidth();
int h = getHeight();
for (int i = min; i < max; i++){
rectangle(i, i, w - 1 - i, h - 1 - i, color);
}
}
void Bitmap::drawHFlip(const int x, const int y, const int startWidth, const int startHeight, const int width, const int height, const Bitmap & where) const {
drawHFlip(x, y, startWidth, startHeight, width, height, NULL, where);
}
void Bitmap::drawHFlip(const int x, const int y, const int startWidth, const int startHeight, const int width, const int height, Filter * filter, const Bitmap & where) const {
Bitmap sub(*this, getWidth() - width, getHeight() - height, getWidth() - startWidth, getHeight() - startHeight);
sub.drawHFlip(x + startWidth, y + startHeight, filter, where);
}
void Bitmap::drawRotateCenter(const int x, const int y, const int angle, const Bitmap & where){
drawRotate(x - getWidth() / 2, y - getHeight() / 2, angle, where);
}
void Bitmap::drawCenter(const int x, const int y, const Bitmap & where) const {
draw(x - getWidth() / 2, y - getHeight() / 2, where);
}
void Bitmap::drawStretched(const Bitmap & who) const {
drawStretched(0, 0, who.getWidth(), who.getHeight(), who);
}
void Bitmap::draw(const int x, const int y, const int startWidth, const int startHeight, const int width, const int height, const Bitmap & where) const {
draw(x, y, startWidth, startHeight, width, height, NULL, where);
/*
Bitmap sub(*this, startWidth, startHeight, width, height);
sub.draw(x + startWidth, y + startHeight, where);
*/
}
void Bitmap::draw(const int x, const int y, const int startWidth, const int startHeight, const int width, const int height, Filter * filter, const Bitmap & where) const {
Bitmap sub(*this, startWidth, startHeight, width, height);
sub.draw(x + startWidth, y + startHeight, filter, where);
}
void Bitmap::horizontalLine( const int x1, const int y, const int x2, const Graphics::Color color ) const{
this->hLine(x1, y, x2, color);
}
void Bitmap::equilateralTriangle(int x, int y, int angle, int size, Color color) const {
double radians = Util::radians(angle);
int x1 = x + size / 2 * cos(radians + 2 * Util::pi / 3);
int y1 = y + size / 2 * sin(radians + 2 * Util::pi / 3);
int x2 = x + size / 2 * cos(radians - 2 * Util::pi / 3);
int y2 = y + size / 2 * sin(radians - 2 * Util::pi / 3);
int x3 = x + size / 2 * cos(radians);
int y3 = y + size / 2 * sin(radians);
triangle(x1, y1, x2, y2, x3, y3, color);
}
Bitmap Bitmap::greyScale(){
Bitmap grey(getWidth(), getHeight());
for (int x = 0; x < getWidth(); x++){
for (int y = 0; y < getHeight(); y++){
Color pixel = getPixel(x, y);
int val = (int)((0.299*getRed(pixel) + 0.587*getGreen(pixel) + 0.114*getBlue(pixel) + 0.5) + 16);
if (val > 255){
val = 255;
}
grey.putPixel(x, y, makeColor(val, val, val));
}
}
return grey;
}
bool Bitmap::inRange(int x, int y) const {
int x1 = 0, y1 = 0, x2 = 0, y2 = 0;
getClipRect(x1, y1, x2, y2);
return (x >= x1 && x <= x2 &&
y >= y1 && y <= y2);
}
void Bitmap::drawMask( const int _x, const int _y, const Bitmap & where ){
Color mask = MaskColor();
for (int x = 0; x < getWidth(); x++){
for (int y = 0; y < getHeight(); y++){
if (getPixel(x,y) == mask){
where.putPixel(x+_x, y+_y, mask);
}
}
}
}
void Bitmap::set8BitMaskColor(const Color & color){
bit8MaskColor = color;
}
Color Bitmap::get8BitMaskColor(){
return bit8MaskColor;
}
void Bitmap::setFakeGraphicsMode(int width, int height){
initializeExtraStuff();
Screen = new Bitmap(width, height);
}
void Bitmap::Blit( const std::string & xpath ) const {
Bitmap duh(xpath);
duh.Blit(*this);
}
void Bitmap::Blit(const Bitmap & where) const {
this->Blit(0, 0, where);
}
void Bitmap::Blit(const int x, const int y, const Bitmap & where) const {
Blit(0, 0, x, y, where);
}
void Bitmap::Blit(const int mx, const int my, const int wx, const int wy, const Bitmap & where) const {
Blit(mx, my, getWidth(), getHeight(), wx, wy, where);
}
void Bitmap::BlitFromScreen(const int x, const int y) const {
Screen->Blit(x, y, getWidth(), getHeight(), 0, 0, *this);
}
//! min (borrowed from allegro)
static inline int Min(int x, int y){ return (((x) < (y)) ? (x) : (y)); }
//! max (borrowed from allegro)
static inline int Max(int x, int y){ return (((x) > (y)) ? (x) : (y)); }
//! mid (borrowed from allegro)
static inline int Mid(int x,int y,int z){ return (Max((x), Min((y), (z)))); }
void Bitmap::roundRect(int radius, int x1, int y1, int x2, int y2, Color color) const {
const int width = x2 - x1;
const int height = y2 - y1;
radius = Mid(0, radius, Min((x1+width - x1)/2, (y1+height - y1)/2));
line(x1+radius, y1, x1+width-radius, y1, color);
line(x1+radius, y1+height, x1+width-radius,y1+height, color);
line(x1, y1+radius,x1, y1+height-radius, color);
line(x1+width, y1+radius,x1+width, y1+height-radius, color);
double quarterTurn = Util::pi / 2;
double quadrant1 = 0;
/* signs are flipped because the coordinate system is reflected over the y-axis */
double quadrant2 = -Util::pi / 2;
double quadrant3 = Util::pi;
double quadrant4 = -3 * Util::pi / 2;
/* upper right. draw from 90 to 0 */
arc(x1+radius + (width - radius *2), y1 + radius, quadrant1, quadrant1 + quarterTurn, radius, color);
/* upper left. draw from 180 to 270 */
arc(x1 + radius, y1 + radius, quadrant2, quadrant2 + quarterTurn, radius, color);
/* lower left. draw from 180 to 270 */
arc(x1 + radius, y1 + height - radius, quadrant3, quadrant3 + quarterTurn, radius, color);
/* lower right. draw from 0 to 270 */
arc(x1+width-radius, y1+height-radius, quadrant4, quadrant4 + quarterTurn, radius, color);
}
void Bitmap::roundRectFill(int radius, int x1, int y1, int x2, int y2, Graphics::Color color) const {
const int width = x2 - x1;
const int height = y2 - y1;
radius = Mid(0, radius, Min((x1+width - x1)/2, (y1+height - y1)/2));
double quarterTurn = Util::pi / 2;
double quadrant1 = 0;
/* signs are flipped because the coordinate system is reflected over the y-axis */
double quadrant2 = -Util::pi / 2;
double quadrant3 = Util::pi;
double quadrant4 = -3 * Util::pi / 2;
/* upper right. draw from 90 to 0 */
arcFilled(x1+radius + (width - radius *2), y1 + radius, quadrant1, quadrant1 + quarterTurn, radius, color);
/* upper left. draw from 180 to 270 */
arcFilled(x1 + radius, y1 + radius, quadrant2, quadrant2 + quarterTurn, radius, color);
/* lower left. draw from 180 to 270 */
arcFilled(x1 + radius, y1 + height - radius, quadrant3, quadrant3 + quarterTurn, radius, color);
/* lower right. draw from 0 to 270 */
arcFilled(x1+width-radius, y1+height-radius, quadrant4, quadrant4 + quarterTurn, radius, color);
rectangleFill(x1+radius + 1, y1, x2-radius - 1, y1+radius - 1, color);
rectangleFill(x1, y1+radius, x2, y2-radius, color);
rectangleFill(x1+radius + 1, y2-radius + 1, x2-radius - 1, y2, color);
}
int Bitmap::getScreenWidth(){
if (Screen != 0){
return Screen->getWidth();
}
return 0;
}
int Bitmap::getScreenHeight(){
if (Screen != 0){
return Screen->getHeight();
}
return 0;
}
void Bitmap::clear() const {
fill(makeColor(0, 0, 0));
}
void Bitmap::copy(const Bitmap & him){
resize(him.getWidth(), him.getHeight());
him.Blit(*this);
}
void Bitmap::Stretch( const Bitmap & where ) const {
if (getWidth() == where.getWidth() && getHeight() == where.getHeight()){
Blit(where);
} else {
Stretch(where, 0, 0, getWidth(), getHeight(), 0, 0, where.getWidth(), where.getHeight());
}
}
void Bitmap::StretchHqx(const Bitmap & where) const {
if (getWidth() == where.getWidth() && getHeight() == where.getHeight()){
Blit(where);
} else {
StretchHqx(where, 0, 0, getWidth(), getHeight(), 0, 0, where.getWidth(), where.getHeight());
}
}
void Bitmap::StretchXbr(const Bitmap & where) const {
if (getWidth() == where.getWidth() && getHeight() == where.getHeight()){
Blit(where);
} else {
StretchXbr(where, 0, 0, getWidth(), getHeight(), 0, 0, where.getWidth(), where.getHeight());
}
}
Color darken(Color color, double factor ){
int r = (int)((double)getRed(color) / factor);
int g = (int)((double)getGreen(color) / factor);
int b = (int)((double)getBlue(color) / factor);
return makeColor(r, g, b);
}
LitBitmap::LitBitmap(const Bitmap & b):
Bitmap(b){
int x1, y1, x2, y2;
b.getClipRect(x1, y1, x2, y2);
setClipRect(x1, y1, x2, y2);
}
LitBitmap::LitBitmap():
Bitmap(){
}
LitBitmap::~LitBitmap(){
}
LitBitmap Bitmap::lit() const {
return LitBitmap(*this);
}
TranslucentBitmap Bitmap::translucent() const {
return TranslucentBitmap(*this);
}
TranslucentBitmap Bitmap::translucent(int red, int green, int blue, int alpha) const {
transBlender(red, green, blue, alpha);
return TranslucentBitmap(*this);
}
TranslucentBitmap::TranslucentBitmap(const Bitmap & b):
Bitmap(b){
int x1, y1, x2, y2;
b.getClipRect(x1, y1, x2, y2);
setClipRect(x1, y1, x2, y2);
}
TranslucentBitmap::TranslucentBitmap():
Bitmap(){
}
TranslucentBitmap::~TranslucentBitmap(){
}
void TranslucentBitmap::fill(Color color) const {
Bitmap::applyTrans(color);
}
int StretchedBitmap::getWidth() const {
return width;
}
int StretchedBitmap::getHeight() const {
return height;
}
double StretchedBitmap::getScaleWidth() const {
return (double) where.getWidth() / (double) getWidth();
}
double StretchedBitmap::getScaleHeight() const {
return (double) where.getHeight() / (double) getHeight();
}
void blend_palette(Color * pal, int mp, Color startColor, Color endColor){
/*
ASSERT(pal);
ASSERT(mp != 0);
*/
int sc_r = Graphics::getRed(startColor);
int sc_g = Graphics::getGreen(startColor);
int sc_b = Graphics::getBlue(startColor);
int ec_r = Graphics::getRed(endColor);
int ec_g = Graphics::getGreen(endColor);
int ec_b = Graphics::getBlue(endColor);
for ( int q = 0; q < mp; q++ ) {
float j = (float)( q + 1 ) / (float)( mp );
int f_r = (int)( 0.5 + (float)( sc_r ) + (float)( ec_r-sc_r ) * j );
int f_g = (int)( 0.5 + (float)( sc_g ) + (float)( ec_g-sc_g ) * j );
int f_b = (int)( 0.5 + (float)( sc_b ) + (float)( ec_b-sc_b ) * j );
pal[q] = Graphics::makeColor( f_r, f_g, f_b );
}
}
}
#ifdef USE_ALLEGRO
#include "allegro/bitmap.cpp"
#endif
#ifdef USE_SDL
#include "sdl/bitmap.cpp"
#endif
#ifdef USE_ALLEGRO5
#include "allegro5/bitmap.cpp"
#endif
diff --git a/util/graphics/bitmap.h b/util/graphics/bitmap.h
index 0a3d5d08..4acfd48b 100644
--- a/util/graphics/bitmap.h
+++ b/util/graphics/bitmap.h
@@ -1,719 +1,721 @@
#ifndef _paintown_bitmap_h_
#define _paintown_bitmap_h_
#include "../exceptions/exception.h"
#include "../pointer.h"
#include "../parameter.h"
#include <string>
#include <vector>
#include <map>
#include <iostream>
#ifdef USE_ALLEGRO
#include "allegro/bitmap.h"
#endif
#ifdef USE_SDL
#include "sdl/bitmap.h"
#endif
#ifdef USE_ALLEGRO5
#include "allegro5/bitmap.h"
struct ALLEGRO_SHADER;
#endif
#include "color.h"
#if !defined(USE_ALLEGRO) && !defined(USE_SDL) && !defined(USE_ALLEGRO5)
#error No backend specified. Define one of USE_ALLEGRO, USE_SDL, or USE_ALLEGRO5
#endif
namespace Storage{
class File;
}
namespace Graphics{
class Bitmap;
class Color{
public:
explicit Color(const INTERNAL_COLOR & color):
color(color){
}
static INTERNAL_COLOR defaultColor();
Color():
color(defaultColor()){
}
Color & operator=(const Color & him){
this->color = him.color;
return *this;
}
bool operator==(const Color & him) const {
return color == him.color;
}
bool operator!=(const Color & him) const {
return !(*this == him);
}
bool operator<(const Color & him) const {
return this->color < him.color;
}
INTERNAL_COLOR color;
};
enum ImageFormat{
FormatPNG,
FormatBMP,
FormatJPG,
FormatPCX,
FormatTGA,
FormatTIF,
FormatXPM,
FormatGIF,
FormatUnknown
};
ImageFormat identifyImage(const unsigned char * data, int length);
class TranslucentBitmap;
class LitBitmap;
class Bitmap;
extern Util::Parameter<Bitmap*> screenParameter;
extern const int SPRITE_NORMAL;
extern const int SPRITE_LIT;
extern const int SPRITE_TRANS;
extern const int SPRITE_NO_FLIP;
extern const int SPRITE_V_FLIP;
extern const int SPRITE_H_FLIP;
/*
extern int SCALE_X;
extern int SCALE_Y;
*/
class BitmapException: public Exception::Base {
public:
BitmapException(const std::string & file, int line, const std::string & reason):
Base(file, line),
reason(reason){
}
BitmapException(const BitmapException & copy):
Base(copy),
reason(copy.reason){
}
virtual void throwSelf() const {
throw *this;
}
virtual ~BitmapException() throw () {
}
protected:
virtual const std::string getReason() const {
return reason;
}
std::string reason;
};
/* create a color from components */
Color makeColor(int r, int g, int b);
Color darken(Color color, double factor);
void hsvToRGB( float h, float s, float v, int * r, int * g, int * b );
int setGfxModeText();
int setGfxModeFullscreen( int x, int y );
int setGfxModeWindowed( int x, int y );
/* Only call this method once, from init. After that call changeGraphicsMode */
int setGraphicsMode(int mode, int width, int height);
int changeGraphicsMode(int mode, int width, int height);
/* get color components */
int getRed(Color x);
int getBlue(Color x);
int getGreen(Color x);
int getAlpha(Color x);
Color MaskColor();
enum QualityFilter{
NoFilter,
HqxFilter,
XbrFilter
};
QualityFilter qualityFilterName(const std::string & type);
class Shader{
public:
Shader();
virtual ~Shader();
#ifdef USE_ALLEGRO5
Shader(ALLEGRO_SHADER * shader);
ALLEGRO_SHADER * getShader();
ALLEGRO_SHADER * shader;
#endif
};
class ShaderManager{
public:
ShaderManager();
Util::ReferenceCount<Shader> getShader(const std::string & name, Util::ReferenceCount<Shader> (*create)());
virtual ~ShaderManager();
protected:
std::map<std::string, Util::ReferenceCount<Shader> > shaders;
};
extern Util::Parameter<Util::ReferenceCount<ShaderManager> > shaderManager;
#ifdef USE_ALLEGRO5
ALLEGRO_SHADER * create_shader(const std::string & vertex, const std::string & pixel);
void setShaderSampler(ALLEGRO_SHADER * shader, const std::string & name, const Bitmap & texture, int unit);
void setShaderBool(ALLEGRO_SHADER * shader, const std::string & name, bool value);
void setShaderInt(ALLEGRO_SHADER * shader, const std::string & name, int value);
void setShaderFloat(ALLEGRO_SHADER * shader, const std::string & name, float value);
void setShaderVec4(ALLEGRO_SHADER * shader, const std::string & name, float v1, float v2, float v3, float v4);
std::string defaultVertexShader();
std::string defaultPixelShader();
#endif
class Bitmap{
private:
/* these constructors don't really matter, get rid of them at some point */
Bitmap( const Bitmap & copy, int sx, int sy, double accuracy );
Bitmap( const char * load_file, int sx, int sy, double accuracy );
public:
/* equivalent to a GPU shader */
class Filter{
public:
virtual Color filter(Color pixel) const = 0;
/* getShader should only return the Shader object and not set any uniforms/attributes */
virtual Util::ReferenceCount<Shader> getShader() = 0;
/* set the uniforms/attributes */
virtual void setupShader(const Util::ReferenceCount<Shader> &) = 0;
virtual ~Filter(){
}
};
/* default constructor makes 10x10 bitmap */
Bitmap();
Bitmap( int x, int y );
Bitmap( const char * load_file );
Bitmap(const char * data, int length);
Bitmap( const std::string & load_file );
Bitmap( const char * load_file, int sx, int sy );
/* Load a bitmap from an abstract file */
Bitmap(Storage::File & file);
/* 4/24/2010: remove this at some point */
#ifdef USE_ALLEGRO
explicit Bitmap( BITMAP * who, bool deep_copy = false );
#endif
#ifdef USE_SDL
explicit Bitmap(SDL_Surface * who, bool deep_copy = false );
#endif
#ifdef USE_ALLEGRO5
explicit Bitmap(ALLEGRO_BITMAP * who, bool deep_copy = false );
#endif
Bitmap( const Bitmap & copy, bool deep_copy = false );
Bitmap( const Bitmap & copy, int sx, int sy );
Bitmap( const Bitmap & copy, int x, int y, int width, int height );
virtual ~Bitmap();
virtual TranslucentBitmap translucent() const;
/* will call transBlender() with the supplied values for you */
virtual TranslucentBitmap translucent(int red, int green, int blue, int alpha) const;
virtual LitBitmap lit() const;
virtual void save( const std::string & str ) const;
virtual Bitmap & operator=( const Bitmap & );
virtual void load( const std::string & str );
virtual int getWidth() const;
virtual int getHeight() const;
/*
inline const int getWidth() const{
return getBitmap()->w;
}
inline const int getHeight() const{
return getBitmap()->h;
}
*/
/*
inline const int getWidth() const{
return my_bitmap->w;
}
inline const int getHeight() const{
return my_bitmap->h;
}
*/
void detach();
/* replace all pixels that have value `original' with `replaced' */
void replaceColor(const Color & original, const Color & replaced);
void set8BitMaskColor(const Color & color);
Color get8BitMaskColor();
/* Blend between source pixel and destination pixel.
* Source and dest should be 0-255.
* source = 64, dest = 128
* pixel = source_pixel * source / 255 + dest_pixel * dest / 255
*/
static void alphaBlender(int source, int dest);
static void transBlender( int r, int g, int b, int a );
static void multiplyBlender( int r, int g, int b, int a );
static void dissolveBlender( int r, int g, int b, int a );
static void addBlender( int r, int g, int b, int a );
static void burnBlender( int r, int g, int b, int a );
static void colorBlender( int r, int g, int b, int a );
static void differenceBlender( int r, int g, int b, int a );
static void dodgeBlender( int r, int g, int b, int a );
static void hueBlender( int r, int g, int b, int a );
static void luminanceBlender( int r, int g, int b, int a );
static void invertBlender( int r, int g, int b, int a );
static void screenBlender( int r, int g, int b, int a );
/* for testing */
static void setFakeGraphicsMode(int width, int height);
/* clean up any remaining state */
static void shutdown();
// static void drawingMode( int type );
virtual Color blendColor(const Color & input) const;
/* sets the blend state. try not to use these function unless
* absolutely necessary.
*/
virtual void startDrawing() const;
virtual void endDrawing() const;
void acquire();
void release();
void updateOnResize();
/* Resizes the bitmap and stretches the old pixels to the new bitmap */
void resize(const int width, const int height);
/* Just resizes the bitmap without copying pixels */
void updateSize(const int width, const int height);
/* Makes this bitmap the same as the parameter.
* Width/height is copied and then a Blit is called.
*/
void copy(const Bitmap & him);
void debugSelf() const;
/* convert to a grey scale version */
virtual Bitmap greyScale();
virtual void triangle( int x1, int y1, int x2, int y2, int x3, int y3, Color color ) const;
/* draws an equilateral triangle centered at (x,y) pointing at `angle'
* where each side has `size' pixels using the color.
*/
virtual void equilateralTriangle(int x, int y, int angle, int size, Color color) const;
virtual void ellipse( int x, int y, int rx, int ry, Color color ) const;
virtual void ellipseFill( int x, int y, int rx, int ry, Color color ) const;
virtual void light(int x, int y, int width, int height, int start_y, int focus_alpha, int edge_alpha, Color focus_color, Color edge_color) const;
virtual void applyTrans(const Color color) const;
virtual void border( int min, int max, Color color ) const;
virtual void rectangle( int x1, int y1, int x2, int y2, Color color ) const;
virtual void rectangleFill( int x1, int y1, int x2, int y2, Color color ) const;
virtual void circleFill( int x, int y, int radius, Color color ) const;
virtual void circle( int x, int y, int radius, Color color ) const;
virtual void circle(int x, int y, int radius, int thickness, Color color) const;
virtual void line( const int x1, const int y1, const int x2, const int y2, const Color color ) const;
virtual void floodfill( const int x, const int y, const Color color ) const;
virtual void horizontalLine( const int x1, const int y, const int x2, const Color color ) const;
virtual void hLine( const int x1, const int y, const int x2, const Color color ) const;
virtual void vLine( const int y1, const int x, const int y2, const Color color ) const;
virtual void polygon( const int * verts, const int nverts, const Color color ) const;
virtual void arc(const int x, const int y, const double ang1, const double ang2, const int radius, const Color color ) const;
virtual void arcFilled(const int x, const int y, const double ang1, const double ang2, const int radius, const Color color ) const;
/* x/y is in the center of the bitmap */
virtual void drawCenter(const int x, const int y, const Bitmap & where) const;
virtual void draw(const int x, const int y, const Bitmap & where) const;
virtual void draw(const int x, const int y, Filter * filter, const Bitmap & where) const;
virtual void draw(const int x, const int y, const int startWidth, const int startHeight, const int width, const int height, const Bitmap & where) const;
virtual void draw(const int x, const int y, const int startWidth, const int startHeight, const int width, const int height, Filter * filter, const Bitmap & where) const;
virtual void drawCharacter( const int x, const int y, const Color color, const int background, const Bitmap & where ) const;
/* flip horizontally */
virtual void drawHFlip(const int x, const int y, const Bitmap & where) const;
virtual void drawHFlip(const int x, const int y, Filter * filter, const Bitmap & where) const;
virtual void drawHFlip(const int x, const int y, const int startWidth, const int startHeight, const int width, const int height, const Bitmap & where) const;
virtual void drawHFlip(const int x, const int y, const int startWidth, const int startHeight, const int width, const int height, Filter * filter, const Bitmap & where) const;
/* flip vertically */
virtual void drawVFlip( const int x, const int y, const Bitmap & where ) const;
virtual void drawVFlip( const int x, const int y, Filter * filter, const Bitmap & where ) const;
/* flip horizontal and vertical */
virtual void drawHVFlip( const int x, const int y, const Bitmap & where ) const;
virtual void drawHVFlip( const int x, const int y, Filter * filter, const Bitmap & where ) const;
// virtual void drawTrans( const int x, const int y, const Bitmap & where ) const;
// virtual void drawTrans( const int x, const int y, Filter * filter, const Bitmap & where ) const;
// virtual void drawTransHFlip( const int x, const int y, const Bitmap & where ) const;
// virtual void drawTransHFlip( const int x, const int y, Filter * filter, const Bitmap & where ) const;
// virtual void drawTransVFlip( const int x, const int y, const Bitmap & where ) const;
// virtual void drawTransVFlip( const int x, const int y, Filter * filter, const Bitmap & where ) const;
// virtual void drawTransHVFlip( const int x, const int y, const Bitmap & where ) const;
// virtual void drawTransHVFlip( const int x, const int y, Filter * filter, const Bitmap & where ) const;
virtual void drawMask( const int x, const int y, const Bitmap & where );
virtual void drawStretched( const int x, const int y, const int new_width, const int new_height, const Bitmap & who ) const;
virtual void drawStretched(const Bitmap & who) const;
/* middle of the bitmap is at x, y */
virtual void drawRotateCenter(const int x, const int y, const int angle, const Bitmap & where);
/* upper left hand corner is at x, y*/
virtual void drawRotate(const int x, const int y, const int angle, const Bitmap & where);
virtual void drawPivot( const int centerX, const int centerY, const int x, const int y, const int angle, const Bitmap & where );
virtual void drawPivot( const int centerX, const int centerY, const int x, const int y, const int angle, const double scale, const Bitmap & where );
/* Stretch using the hqx algorithm */
virtual void StretchHqx(const Bitmap & where) const;
virtual void StretchHqx(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;
/* Xbr is defined here:
* http://board.byuu.org/viewtopic.php?f=10&t=2248
*/
virtual void StretchXbr(const Bitmap & where) const;
virtual void StretchXbr(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;
/* Just copies pixels (fast) */
virtual void Stretch(const Bitmap & where) const;
virtual void 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;
virtual void StretchBy2( const Bitmap & where );
virtual void StretchBy4( const Bitmap & where );
virtual void Blit( const std::string & xpath ) const;
virtual void Blit( const Bitmap & where ) const;
virtual void Blit( const int x, const int y, const Bitmap & where ) const;
virtual void Blit( const int mx, const int my, const int wx, const int wy, const Bitmap & where ) const;
virtual void Blit( const int mx, const int my, const int width, const int height, const int wx, const int wy, const Bitmap & where ) const;
virtual void BlitMasked( const int mx, const int my, const int width, const int height, const int wx, const int wy, const Bitmap & where ) const;
virtual void BlitToScreen() const;
virtual void BlitAreaToScreen(const int upper_left_x, const int upper_left_y) const;
virtual void BlitToScreen(const int upper_left_x, const int upper_left_y) const;
virtual void BlitFromScreen(const int x, const int y) const;
void roundRect(int radius, int x1, int y1, int x2, int y2, Color color) const;
void roundRectFill(int radius, int x1, int y1, int x2, int y2, Graphics::Color color) const;
virtual void drawShadow(Bitmap & where, int x, int y, int intensity, Color color, double scale, bool facingRight) const;
/* returned a scaled version of this bitmap of the given dimensions */
virtual Bitmap scaleTo(const int width, const int height) const;
/* scale the image by the given ratios, i.e: a ratio of 1 means do nothing.
* less than 1 will make it smaller and larger than 1 will make it larger.
*/
virtual Bitmap scaleBy(const double widthRatio, const double heightRatio) const;
/* try to call Global::getScreenWidth/Height() instead of these directly */
static int getScreenWidth();
static int getScreenHeight();
virtual void fill(Color color) const;
virtual void clear() const;
inline void clearToMask() const{
this->fill(MaskColor());
}
bool getError();
inline const Util::ReferenceCount<BitmapData> & getData() const {
return data;
}
inline Util::ReferenceCount<BitmapData> getData(){
return data;
}
void setData(Util::ReferenceCount<BitmapData> data){
this->data = data;
}
virtual void readLine( std::vector<Color> & vec, int y );
Color getPixel( const int x, const int y ) const;
/* lock video bitmap to memory */
void lock() const;
void lock(int x, int y, int width, int height) const;
void unlock() const;
/* true if the point is within the bounds of the bitmap */
bool inRange(int x, int y) const;
/* uses _putpixel16 underneath which ignores translucent behavior */
void putPixel( int x, int y, Color col ) const;
/* respects the current trans mode */
virtual void putPixelNormal(int x, int y, Color col) const;
/*
inline int getPixel( int x, int y ) const{
if ( x >= 0 && x < my_bitmap->w && y >= 0 && y <= my_bitmap->h )
return _getpixel16( my_bitmap, x, y );
return -1;
}
inline void putPixel( int x, int y, int col ) const{
if ( x >= 0 && x < my_bitmap->w && y >= 0 && y <= my_bitmap->h )
_putpixel16( my_bitmap, x, y, col );
}
*/
void setClipRect( int x1, int y1, int x2, int y2 ) const;
void getClipRect( int & x1, int & y1, int & x2, int & y2 ) const;
inline const std::string & getPath() const{
return path;
}
/* produce a temporary bitmap that is not guaranteed to be preserved
* after your function returns. do *not* hold references to this bitmap
* and if you make a temporary bitmap, do *not* call functions that
* might also make temporary bitmaps.
*/
+ /*
static Bitmap temporaryBitmap(int w, int h);
static Bitmap temporaryBitmap2(int w, int h);
+ */
/* call this method to delete all temporary bitmaps.
* don't call this unless you know what you are doing
*/
static void cleanupTemporaryBitmaps();
static double getScale();
/*
* Convert color values between the HSV and RGB color spaces. The RGB values
* range from 0 to 255, hue is from 0 to 360, and saturation and value are
* from 0 to 1.
*/
static void rgbToHSV(int r, int g, int b, float * h, float * s, float * v);
/* convert cymk to rgb. values should be in the range 0-255 */
static void cymkToRGB(int c, int y, int m, int k, int * r, int * g, int * b);
/* Add two RGB16 colors together
* r = c1.r + c2.r
* g = c1.g + c2.g
* b = c1.b + c2.b
*/
static Color addColor( Color color1, Color color2 );
/*
inline static int makeColor( int r, int g, int b ){
return makecol16( r, g, b );
}
*/
// static const int MaskColor = MASK_COLOR_16;
/*
static const int MODE_TRANS;
static const int MODE_SOLID;
*/
#ifdef USE_ALLEGRO5
void convertToVideo();
#endif
protected:
#ifdef USE_ALLEGRO5
virtual void draw(const int x, const int y, Filter * filter, const Bitmap & where, int flags) const;
#endif
/* release a reference count, and possibly destroy data */
// void releaseInternalBitmap();
/* really destroy private data */
// void destroyPrivateData();
/*
inline void setBitmap( BITMAP * bitmap ){
if ( bitmap == NULL ){
std::cout << "*FATAL* Setting null bitmap" << std::endl;
}
_my_bitmap = bitmap;
}
*/
void loadFromMemory(const char * data, int length);
void internalLoadFile( const char * load_file );
/* implementation specific data */
Util::ReferenceCount<BitmapData> data;
// int * own;
bool mustResize;
// bool own;
bool error;
std::string path;
static Bitmap * temporary_bitmap;
static Bitmap * temporary_bitmap2;
Color bit8MaskColor;
/* only used by allegro5 for now */
int width, height;
};
/* 8-bit bitmap that supports a palette */
class PaletteBitmap: public Bitmap {
public:
PaletteBitmap();
virtual ~PaletteBitmap();
using Bitmap::operator=;
protected:
Color palette[256];
};
Bitmap memoryPCX(unsigned char * const data, const int length, const bool mask = true);
/* creates a bitmap that can be used as a buffer for the screen.
* on opengl/allegro5 systems this will return the current backbuffer
*/
Bitmap * getScreenBuffer();
void blend_palette(Color * pal, int mp, Color sc, Color ec);
// bool sameColors(Color color1, Color color2);
class LitBitmap: public Bitmap {
public:
LitBitmap( const Bitmap & b );
LitBitmap();
virtual ~LitBitmap();
using Bitmap::draw;
virtual void draw(const int x, const int y, const Bitmap & where) const;
virtual void draw(const int x, const int y, Filter * filter, const Bitmap & where ) const;
using Bitmap::drawHFlip;
virtual void drawHFlip( const int x, const int y, const Bitmap & where ) const;
virtual void drawHFlip( const int x, const int y, Filter * filter, const Bitmap & where ) const;
using Bitmap::drawVFlip;
virtual void drawVFlip( const int x, const int y, const Bitmap & where ) const;
virtual void drawVFlip( const int x, const int y, Filter * filter, const Bitmap & where ) const;
using Bitmap::drawHVFlip;
virtual void drawHVFlip( const int x, const int y, const Bitmap & where ) const;
virtual void drawHVFlip( const int x, const int y, Filter * filter, const Bitmap & where ) const;
using Bitmap::operator=;
protected:
#ifdef USE_ALLEGRO5
virtual void draw(const int x, const int y, Filter * filter, const Bitmap & where, int flags) const;
#endif
};
class StretchedBitmap: public Bitmap {
public:
StretchedBitmap(int width, int height, const Bitmap & where, QualityFilter filter = NoFilter);
void finish();
void start();
virtual int getWidth() const;
virtual int getHeight() const;
using Bitmap::operator=;
virtual double getScaleWidth() const;
virtual double getScaleHeight() const;
protected:
double width;
double height;
double scale_x, scale_y;
const Bitmap & where;
const QualityFilter filter;
Bitmap scaleToFilter;
};
class TranslatedBitmap: public Bitmap {
public:
TranslatedBitmap(int x, int y, const Bitmap & where);
using Bitmap::operator=;
using Bitmap::BlitToScreen;
virtual void BlitToScreen() const;
virtual ~TranslatedBitmap();
public:
int x, y;
};
class TranslucentBitmap: public Bitmap {
public:
TranslucentBitmap(const Bitmap & b);
TranslucentBitmap();
virtual ~TranslucentBitmap();
using Bitmap::operator=;
virtual Color blendColor(const Color & color) const;
virtual void startDrawing() const;
virtual void endDrawing() const;
virtual void putPixelNormal(int x, int y, Color col) const;
virtual void rectangleFill(int x1, int y1, int x2, int y2, Color color) const;
virtual void rectangle(int x1, int y1, int x2, int y2, Color color) const;
virtual void fill(Color color) const;
virtual void line( const int x1, const int y1, const int x2, const int y2, const Color color ) const;
virtual void hLine( const int x1, const int y, const int x2, const Color color ) const;
virtual void arc(const int x, const int y, const double ang1, const double ang2, const int radius, const Color color) const;
virtual void arcFilled(const int x, const int y, const double ang1, const double ang2, const int radius, const Color color ) const;
virtual void circleFill( int x, int y, int radius, Color color ) const;
virtual void ellipse( int x, int y, int rx, int ry, Color color ) const;
virtual void ellipseFill( int x, int y, int rx, int ry, Color color ) const;
using Bitmap::draw;
virtual void draw(const int x, const int y, const Bitmap & where) const;
virtual void draw(const int x, const int y, Filter * filter, const Bitmap & where) const;
// virtual void draw(const int x, const int y, const int startWidth, const int startHeight, const int width, const int height, const Bitmap & where) const;
// virtual void draw(const int x, const int y, const int startWidth, const int startHeight, const int width, const int height, Filter * filter, const Bitmap & where) const;
using Bitmap::drawHFlip;
virtual void drawHFlip(const int x, const int y, const Bitmap & where) const;
virtual void drawHFlip(const int x, const int y, Filter * filter, const Bitmap & where) const;
// virtual void drawHFlip(const int x, const int y, const int startWidth, const int startHeight, const int width, const int height, const Bitmap & where) const;
// virtual void drawHFlip(const int x, const int y, const int startWidth, const int startHeight, const int width, const int height, Filter * filter, const Bitmap & where) const;
virtual void drawVFlip( const int x, const int y, const Bitmap & where ) const;
virtual void drawVFlip( const int x, const int y, Filter * filter, const Bitmap & where ) const;
virtual void drawHVFlip( const int x, const int y, const Bitmap & where ) const;
virtual void drawHVFlip( const int x, const int y, Filter * filter, const Bitmap & where ) const;
protected:
#ifdef USE_ALLEGRO5
virtual void draw(const int x, const int y, Filter * filter, const Bitmap & where, int flags) const;
#endif
};
}
#endif
diff --git a/util/graphics/software-renderer/bitmap.cpp b/util/graphics/software-renderer/bitmap.cpp
index 35ec2a0d..9050f443 100644
--- a/util/graphics/software-renderer/bitmap.cpp
+++ b/util/graphics/software-renderer/bitmap.cpp
@@ -1,187 +1,187 @@
/* generic software implementation of various bitmap operations */
namespace Graphics{
Color Bitmap::blendColor(const Color & input) const {
return input;
}
Color TranslucentBitmap::blendColor(const Color & input) const {
return input;
}
void Bitmap::startDrawing() const {
}
void Bitmap::endDrawing() const {
}
int getAlpha(Color input){
return 255;
}
void Bitmap::drawShadow(Bitmap & where, int x, int y, int intensity, Color color, double scale, bool facingRight) const {
const double newheight = getHeight() * scale;
- Bitmap shade = temporaryBitmap(getWidth(), (int) fabs(newheight));
+ Bitmap shade(getWidth(), (int) fabs(newheight));
Stretch(shade);
/* Could be slow, but meh, lets do it for now to make it look like a real shadow */
for (int h = 0; h < shade.getHeight(); ++h){
for (int w = 0; w < shade.getWidth(); ++w){
Color pix = shade.getPixel(w, h);
if (pix != MaskColor()){
shade.putPixel(w, h, color);
}
}
}
transBlender(0, 0, 0, intensity);
if (scale > 0){
if (facingRight){
shade.translucent().drawVFlip(x, y, where);
} else {
shade.translucent().drawHVFlip(x, y, where);
}
} else if (scale < 0){
y -= fabs(newheight);
if (facingRight){
shade.translucent().draw(x + 3, y, where);
} else {
shade.translucent().drawHFlip(x - 3, y, where);
}
}
}
void TranslucentBitmap::startDrawing() const {
}
void TranslucentBitmap::endDrawing() const {
}
void Bitmap::lock() const {
}
void Bitmap::unlock() const {
}
Bitmap Bitmap::scaleTo(const int width, const int height) const {
if (width == getWidth() && height == getHeight()){
return *this;
}
Bitmap scaled(width, height);
this->Stretch(scaled);
return scaled;
}
/* Filters only work for multiples of 320x240 up to 4x */
static bool filterMultiple(int width, int height, int toWidth, int toHeight){
return (toWidth == width * 2 && toHeight == height * 2) ||
(toWidth == width * 3 && toHeight == height * 3) ||
(toWidth == width * 4 && toHeight == height * 4);
}
static void closestMultipleSize(int width, int height, int toWidth, int toHeight, int * outWidth, int * outHeight){
/* If we are down-scaling then we don't need any filters */
if (toWidth < width || toHeight < height){
*outWidth = 1;
*outHeight = 1;
} else if (toWidth < width * 2 && toHeight < height * 2){
*outWidth = 1;
*outHeight = 1;
} else if (toWidth < width * 3 && toHeight < height * 3){
*outWidth = width * 2;
*outHeight = height * 2;
} else {
*outWidth = width * 3;
*outHeight = height * 3;
}
}
StretchedBitmap::StretchedBitmap(int width, int height, const Bitmap & parent, QualityFilter filter):
Bitmap(1, 1),
width(1),
height(1),
where(parent),
filter(filter),
scaleToFilter(1, 1){
if (width == parent.getWidth() && height == parent.getHeight()){
setData(parent.getData());
} else {
updateSize(width, height);
}
if (!filterMultiple(width, height, parent.getWidth(), parent.getHeight()) &&
filter != NoFilter){
int multipleWidth, multipleHeight;
closestMultipleSize(width, height, parent.getWidth(), parent.getHeight(), &multipleWidth, &multipleHeight);
scaleToFilter.updateSize(multipleWidth, multipleHeight);
}
this->width = width;
this->height = height;
}
void StretchedBitmap::start(){
}
void StretchedBitmap::finish(){
if (getData() != where.getData()){
switch (filter){
case NoFilter: Stretch(where); break;
case HqxFilter: {
if (scaleToFilter.getWidth() > 1 &&
scaleToFilter.getHeight() > 1){
StretchHqx(scaleToFilter);
scaleToFilter.Stretch(where);
} else {
StretchHqx(where);
}
break;
}
case XbrFilter: {
if (scaleToFilter.getWidth() > 1 &&
scaleToFilter.getHeight() > 1){
StretchXbr(scaleToFilter);
scaleToFilter.Stretch(where);
} else {
StretchXbr(where);
}
break;
}
}
}
}
/*
Bitmap getScreenBuffer(){
return Bitmap(GFX_X, GFX_Y);
}
*/
RestoreState::RestoreState(){
}
RestoreState::~RestoreState(){
}
TranslatedBitmap::TranslatedBitmap(int x, int y, const Bitmap & where):
Bitmap(where),
x(x),
y(y){
}
void TranslatedBitmap::BlitToScreen() const {
Bitmap::BlitToScreen(x, y);
}
TranslatedBitmap::~TranslatedBitmap(){
}
Shader::Shader(){
}
Shader::~Shader(){
}
}
diff --git a/util/gui/animation.cpp b/util/gui/animation.cpp
index 3fefd9f6..fd78e546 100644
--- a/util/gui/animation.cpp
+++ b/util/gui/animation.cpp
@@ -1,1233 +1,1233 @@
#include "animation.h"
#include <stdio.h>
#include <vector>
#include <math.h>
#include <sstream>
#include "util/token.h"
#include "util/graphics/bitmap.h"
#include "util/font.h"
#include "util/graphics/gradient.h"
#include "../debug.h"
#include "../funcs.h"
#include "../file-system.h"
#include "util/exceptions/load_exception.h"
using namespace std;
using namespace Gui;
// Temporary solution
static void renderSprite(const Graphics::Bitmap & bmp, const int x, const int y, const int alpha, const bool hflip, const bool vflip, const Graphics::Bitmap & work){
if (alpha != 255){
Graphics::Bitmap::transBlender( 0, 0, 0, alpha );
if (hflip && !vflip){
bmp.translucent().drawHFlip(x,y, work);
} else if (!hflip && vflip){
bmp.translucent().drawVFlip(x,y, work);
} else if (hflip && vflip){
bmp.translucent().drawHVFlip(x,y, work);
} else if (!hflip && !vflip){
bmp.translucent().draw(x,y, work);
}
} else {
if (hflip && !vflip){
bmp.drawHFlip(x,y, work);
} else if (!hflip && vflip){
bmp.drawVFlip(x,y, work);
} else if (hflip && vflip){
bmp.drawHVFlip(x,y, work);
} else if (!hflip && !vflip){
bmp.draw(x,y, work);
}
}
}
Element::Element(const Token * token):
time(50),
alpha(255){
if (token != NULL){
TokenView view = token->view();
while (view.hasMore()){
try{
const Token * tok;
view >> tok;
parseToken(tok);
} catch ( const TokenException & ex ) {
throw LoadException(__FILE__, __LINE__, ex, "Gui::Animation::Element parse error");
} catch ( const LoadException & ex ) {
throw ex;
}
}
}
}
Element::~Element(){
}
void Element::parseToken(const Token * token){
if (*token == "alpha"){
// get alpha
token->view() >> alpha;
} else if (*token == "offset"){
// Get the offset location it defaults to 0,0
double x=0, y=0;
try {
token->view() >> x >> y;
} catch (const TokenException & ex){
}
offset.set(x,y);
} else if (*token == "time"){
// time to display
token->view() >> time;
} else {
Global::debug( 3 ) << "Unhandled Gui::Animation::Element attribute: " << endl;
if (Global::getDebug() >= 3){
token->print(" ");
}
}
}
void Element::act(double xvel, double yvel){
scrollOffset.moveBy(xvel, yvel);
}
ImageFrame::ImageFrame(const Token *the_token, ImageMap &images, const string & baseDir):
Element(the_token),
bmp(NULL),
horizontalFlip(false),
verticalFlip(false){
/*
if (*the_token != "frame"){
throw LoadException(__FILE__, __LINE__, "Not an frame");
}
*/
/* The usual setup of an animation frame is
// use image -1 to not draw anything, it can be used to get a blinking effect
(frame (image NUM) (alpha NUM) (offset x y) (hflip 0|1) (vflip 0|1) (time NUM))
*/
TokenView view = the_token->view();
while (view.hasMore()){
try{
const Token * token;
view >> token;
parseToken(token, baseDir, images);
} catch ( const TokenException & ex ) {
throw LoadException(__FILE__, __LINE__, ex, "Menu animation parse error");
} catch ( const LoadException & ex ) {
throw ex;
}
}
}
void ImageFrame::parseToken(const Token * token, const string & baseDir, ImageMap & images){
if (*token == "image"){
// get the number
string maybeNumber;
token->view() >> maybeNumber;
if (Util::matchRegex(maybeNumber, Util::Regex("\\d+"))){
int num;
token->view() >> num;
if (images.find(num) == images.end()){
ostringstream out;
out << "No image for index " << num;
throw LoadException(__FILE__, __LINE__, out.str());
}
// now assign the bitmap
bmp = images[num];
} else {
bmp = Util::ReferenceCount<Graphics::Bitmap>(new Graphics::Bitmap(Storage::instance().find(Filesystem::RelativePath(baseDir + "/" + maybeNumber)).path()));
}
} else if (*token == "hflip"){
// horizontal flip
token->view() >> horizontalFlip;
} else if (*token == "vflip"){
// horizontal flip
token->view() >> verticalFlip;
} else {
Global::debug( 3 ) << "Unhandled Gui::Animation::ImageFrame attribute: "<<endl;
if (Global::getDebug() >= 3){
token->print(" ");
}
}
}
ImageFrame::ImageFrame(Util::ReferenceCount<Graphics::Bitmap> bmp):
Element(NULL),
bmp(bmp),
horizontalFlip(false),
verticalFlip(false){
time = -1;
}
ImageFrame::~ImageFrame(){
}
static bool closeFloat(double a, double b){
const double epsilon = 0.001;
return fabs(a-b) < epsilon;
}
void ImageFrame::act(double xvel, double yvel){
scrollOffset.moveBy(xvel, yvel);
if (bmp != NULL){
if (scrollOffset.getDistanceFromCenterX() >= bmp->getWidth()){
scrollOffset.setX(0);
} else if (scrollOffset.getDistanceFromCenterX() <= -(bmp->getWidth())){
scrollOffset.setX(0);
}
if (scrollOffset.getDistanceFromCenterY() >= bmp->getHeight()){
scrollOffset.setY(0);
} else if (scrollOffset.getDistanceFromCenterY() <= -(bmp->getHeight())){
scrollOffset.setY(0);
}
}
}
void ImageFrame::draw(const int xaxis, const int yaxis, const Graphics::Bitmap & work){
if (!bmp){
return;
}
if (!closeFloat(scrollOffset.getDistanceFromCenterX(), 0) || !closeFloat(scrollOffset.getDistanceFromCenterY(), 0)){
// Lets do some scrolling
// Graphics::Bitmap temp = Graphics::Bitmap::temporaryBitmap(bmp->getWidth(), bmp->getHeight());
//AnimationPoint loc;
AbsolutePoint loc;
if (scrollOffset.getRelativeX() < 0){
loc.setX(scrollOffset.getDistanceFromCenterX() + bmp->getWidth());
} else if (scrollOffset.getRelativeX() > 0){
loc.setX(scrollOffset.getDistanceFromCenterX() - bmp->getWidth());
}
if (scrollOffset.getRelativeY() < 0){
loc.setY(scrollOffset.getDistanceFromCenterY() + bmp->getHeight());
} else if (scrollOffset.getRelativeY() > 0){
loc.setY(scrollOffset.getDistanceFromCenterY() - bmp->getHeight());
}
/*
bmp->Blit((int) scrollOffset.getDistanceFromCenterX(), (int) scrollOffset.getDistanceFromCenterY(), temp);
bmp->Blit((int) scrollOffset.getDistanceFromCenterX(), (int) loc.getY(), temp);
bmp->Blit((int) loc.getX(), (int) scrollOffset.getDistanceFromCenterY(), temp);
bmp->Blit((int) loc.getX(), (int) loc.getY(), temp);
renderSprite(temp, (int)(xaxis+offset.getDistanceFromCenterX()), (int)(yaxis+offset.getDistanceFromCenterY()), alpha, horizontalFlip, verticalFlip, work);
*/
double x = xaxis+offset.getDistanceFromCenterX();
double y = yaxis+offset.getDistanceFromCenterY();
renderSprite(*bmp,
(int)(x + scrollOffset.getDistanceFromCenterX()),
(int)(y + scrollOffset.getDistanceFromCenterY()),
alpha, horizontalFlip, verticalFlip, work);
renderSprite(*bmp,
(int)(x + loc.getX()),
(int)(y + scrollOffset.getDistanceFromCenterY()),
alpha, horizontalFlip, verticalFlip, work);
renderSprite(*bmp,
(int)(x + scrollOffset.getDistanceFromCenterX()),
(int)(y + loc.getY()),
alpha, horizontalFlip, verticalFlip, work);
renderSprite(*bmp,
(int)(x + loc.getX()),
(int)(y + loc.getY()),
alpha, horizontalFlip, verticalFlip, work);
} else {
renderSprite(*bmp, (int)(xaxis+offset.getDistanceFromCenterX()), (int)(yaxis+offset.getDistanceFromCenterY()), alpha, horizontalFlip, verticalFlip, work);
}
}
/* This is mainly called from select-list to draw the cells. I'm not sure
* of the utility of stretching the bitmap to fit the cell dimensions. Most
* likely the cell will contain an image and the image will be the same
* size as the cell.
*/
void ImageFrame::draw(const Graphics::Bitmap & work){
- const Graphics::Bitmap & temp = Graphics::Bitmap::temporaryBitmap(bmp->getWidth(), bmp->getHeight());
+ Graphics::Bitmap temp(bmp->getWidth(), bmp->getHeight());
temp.clearToMask();
renderSprite(*bmp, 0, 0, alpha, horizontalFlip, verticalFlip, temp);
temp.drawStretched(work);
/* FIXME: This should work, but it doesn't.. */
/*
Graphics::StretchedBitmap show(bmp->getWidth(), bmp->getHeight(), work);
show.start();
renderSprite(*bmp, 0, 0, alpha, horizontalFlip, verticalFlip, show);
show.finish();
*/
}
void ImageFrame::reset(){
scrollOffset = RelativePoint();
}
void ImageFrame::setToEnd(const RelativePoint & end){
scrollOffset = end;
}
static const char * FRAME_TEXT = "Offset: ( %f, %f)\nScroll Offset: ( %f, %f)\nTime: %d\nHorizontal Flip: %d\nVertical Flip: %d\nAlpha: %d\n\n";
const std::string ImageFrame::getInfo(){
char info[255];
sprintf(info, FRAME_TEXT, offset.getRelativeX(), offset.getRelativeY(), scrollOffset.getRelativeX(), scrollOffset.getRelativeY(), time, horizontalFlip, verticalFlip, alpha);
return std::string(info);
}
TextFrame::TextFrame(const Token *token):
Element(token),
fontWidth(20),
fontHeight(20){
TokenView view = token->view();
while (view.hasMore()){
try{
const Token * token;
view >> token;
parseToken(token);
} catch ( const TokenException & ex ) {
throw LoadException(__FILE__, __LINE__, ex, "Menu animation parse error");
} catch ( const LoadException & ex ) {
throw ex;
}
}
}
TextFrame::~TextFrame(){
}
void TextFrame::act(double xvel, double yvel){
gradient.forward();
Element::act(xvel, yvel);
}
static const Font & getFont(const string & font, int width, int height){
if (font != ""){
return Font::getFont(Filesystem::RelativePath(font), width, height);
}
return Font::getDefaultFont(width, height);
}
void TextFrame::draw(int xaxis, int yaxis, const Graphics::Bitmap & work){
double x = xaxis + offset.getDistanceFromCenterX() + scrollOffset.getDistanceFromCenterX();
double y = yaxis + offset.getDistanceFromCenterY() + scrollOffset.getDistanceFromCenterY();
const Font & font = getFont(this->font, fontWidth, fontHeight);
font.printf((int) x, (int) y, gradient.current(), work, "%s", 0, message.c_str());
}
void TextFrame::draw(const Graphics::Bitmap & work){
/* Probably don't need this.. but implement it if you do! */
}
void TextFrame::reset(){
scrollOffset = RelativePoint();
}
void TextFrame::setToEnd(const RelativePoint & point){
scrollOffset = point;
}
const std::string TextFrame::getInfo(){
return message;
}
void TextFrame::parseToken(const Token * token){
if (*token == "message"){
token->view() >> message;
} else if (*token == "font"){
TokenView view = token->view();
view >> font;
try{
view >> fontWidth >> fontHeight;
} catch (const TokenException & ignore){
}
if (fontWidth < 1){
fontWidth = 1;
}
if (fontHeight < 1){
fontHeight = 1;
}
} else if (*token == "color"){
int red, green, blue;
token->view() >> red >> green >> blue;
gradient = Effects::Gradient(Graphics::makeColor(red, green, blue));
} else if (*token == "gradient"){
gradient = Effects::Gradient(token);
}
}
Sequence::Sequence(){
}
Sequence::~Sequence(){
}
SequenceFrame::SequenceFrame(const Util::ReferenceCount<Element> & frame):
frame(frame),
ticks(0){
}
void SequenceFrame::draw(int xaxis, int yaxis, const Graphics::Bitmap & work) const {
frame->draw(xaxis, yaxis, work);
}
Util::ReferenceCount<Element> SequenceFrame::getCurrentFrame() const {
return frame;
}
int SequenceFrame::totalTicks() const {
return frame->getTime();
}
void SequenceFrame::setToEnd(){
ticks = frame->getTime();
}
bool SequenceFrame::forward(int tickCount, double velocityX, double velocityY){
frame->act(tickCount * velocityX, tickCount * velocityY);
ticks += tickCount;
return ticks > frame->getTime();
}
bool SequenceFrame::reverse(int tickCount, double velocityX, double velocityY){
frame->act(-tickCount * velocityX, -tickCount * velocityY);
ticks -= tickCount;
return ticks < 0;
}
void SequenceFrame::forwardFrame(){
/* nop */
}
void SequenceFrame::backFrame(){
/* nop */
}
void SequenceFrame::reset(){
ticks = 0;
frame->reset();
}
void SequenceFrame::resetTicks(){
ticks = 0;
}
SequenceLoop::SequenceLoop(int loops):
currentFrame(0),
currentLoop(loops),
loopTimes(loops){
}
Util::ReferenceCount<Element> SequenceLoop::getCurrentFrame() const {
if (currentFrame < frames.size()){
return frames[currentFrame]->getCurrentFrame();
} else {
/* Return the last frame */
if (frames.size() > 0){
return frames[frames.size() - 1]->getCurrentFrame();
}
}
return Util::ReferenceCount<Element>(NULL);
}
Util::ReferenceCount<Sequence> SequenceLoop::getCurrentSequence() const {
if (currentFrame < frames.size()){
return frames[currentFrame];
} else {
/* Return the last frame */
if (frames.size() > 0){
return frames[frames.size() - 1];
}
}
return Util::ReferenceCount<Sequence>(NULL);
}
void SequenceLoop::draw(int xaxis, int yaxis, const Graphics::Bitmap & work) const {
Util::ReferenceCount<Sequence> current = getCurrentSequence();
if (current != NULL){
current->draw(xaxis, yaxis, work);
}
}
void SequenceLoop::reset(){
currentFrame = 0;
currentLoop = loopTimes;
for (vector<Util::ReferenceCount<Sequence> >::iterator it = frames.begin(); it != frames.end(); it++){
Util::ReferenceCount<Sequence> & sequence = *it;
sequence->reset();
}
}
/* Does the same thing as reset except for calling resetTicks on children nodes */
void SequenceLoop::resetTicks(){
currentFrame = 0;
currentLoop = loopTimes;
for (vector<Util::ReferenceCount<Sequence> >::iterator it = frames.begin(); it != frames.end(); it++){
Util::ReferenceCount<Sequence> & sequence = *it;
sequence->resetTicks();
}
}
/* Similar to resetTicks but doesn't reset the current frame or loop */
void SequenceLoop::resetChildrenTicks(){
for (vector<Util::ReferenceCount<Sequence> >::iterator it = frames.begin(); it != frames.end(); it++){
Util::ReferenceCount<Sequence> & sequence = *it;
sequence->resetTicks();
}
}
void SequenceLoop::setToEnd(){
/* FIXME */
}
void SequenceLoop::addSequence(const Util::ReferenceCount<Sequence> & sequence){
frames.push_back(sequence);
}
static Util::ReferenceCount<Sequence> parseSequence(const Token * token, ImageMap & images, const string & baseDir){
if (*token == "frame"){
Util::ReferenceCount<Element> frame(new ImageFrame(token, images, baseDir));
return Util::ReferenceCount<Sequence>(new SequenceFrame(frame));
} else if (*token == "text"){
Util::ReferenceCount<Element> frame(new TextFrame(token));
return Util::ReferenceCount<Sequence>(new SequenceFrame(frame));
} else if (*token == "loop"){
int times;
token->view() >> times;
Util::ReferenceCount<SequenceLoop> loop(new SequenceLoop(times));
loop->parse(token, images, baseDir);
return loop.convert<Sequence>();
} else if (*token == "all"){
return Util::ReferenceCount<Sequence>(new SequenceAll(token, images, baseDir));
} else if (*token == "random"){
return Util::ReferenceCount<Sequence>(new SequenceRandom(token, images, baseDir));
}
return Util::ReferenceCount<Sequence>(NULL);
}
void SequenceLoop::parse(const Token * token, ImageMap & images, const string & baseDir){
TokenView view = token->view();
/* first ignore the number of times to loop */
int ignore;
view >> ignore;
while (view.hasMore()){
const Token * next;
view >> next;
Util::ReferenceCount<Sequence> sequence = parseSequence(next, images, baseDir);
if (sequence != NULL){
addSequence(sequence);
}
}
}
int SequenceLoop::totalTicks() const {
int total = 0;
for (vector<Util::ReferenceCount<Sequence> >::const_iterator it = frames.begin(); it != frames.end(); it++){
const Util::ReferenceCount<Sequence> & sequence = *it;
total += sequence->totalTicks();
}
return total * (1 + loopTimes);
}
bool SequenceLoop::forward(int tickCount, double velocityX, double velocityY){
Util::ReferenceCount<Sequence> current = getCurrentSequence();
if (current != NULL){
if (current->forward(tickCount, velocityX, velocityY)){
forwardFrame();
}
}
return currentFrame == frames.size();
}
bool SequenceLoop::reverse(int tickCount, double velocityX, double velocityY){
Util::ReferenceCount<Sequence> current = getCurrentSequence();
if (current != NULL){
if (current->reverse(tickCount, velocityX, velocityY)){
backFrame();
}
}
return currentFrame == frames.size();
}
void SequenceLoop::forwardFrame(){
currentFrame += 1;
/* do the loop */
if (currentFrame == frames.size() && currentLoop > 0){
currentLoop -= 1;
currentFrame = 0;
resetChildrenTicks();
}
}
void SequenceLoop::backFrame(){
currentFrame -= 1;
/* do the loop */
if (currentFrame <= 0 && currentLoop > 0){
currentLoop -= 1;
resetChildrenTicks();
if (frames.size() > 0){
currentFrame = frames.size() - 1;
} else {
currentFrame = 0;
}
}
}
SequenceAll::SequenceAll(const Token * token, ImageMap & images, const string & baseDir){
TokenView view = token->view();
while (view.hasMore()){
const Token * next;
view >> next;
Util::ReferenceCount<Sequence> sequence = parseSequence(next, images, baseDir);
if (sequence != NULL){
addSequence(sequence);
}
}
}
Util::ReferenceCount<Element> SequenceAll::getCurrentFrame() const {
return Util::ReferenceCount<Element>(NULL);
}
void SequenceAll::reset(){
for (SequenceIterator it = sequences.begin(); it != sequences.end(); it++){
Util::ReferenceCount<Sequence> & next = *it;
next->reset();
}
}
void SequenceAll::resetTicks(){
for (SequenceIterator it = sequences.begin(); it != sequences.end(); it++){
Util::ReferenceCount<Sequence> & next = *it;
next->resetTicks();
}
}
void SequenceAll::setToEnd(){
for (SequenceIterator it = sequences.begin(); it != sequences.end(); it++){
Util::ReferenceCount<Sequence> & next = *it;
next->setToEnd();
}
}
void SequenceAll::addSequence(const Util::ReferenceCount<Sequence> & sequence){
sequences.push_back(sequence);
}
void SequenceAll::draw(int xaxis, int yaxis, const Graphics::Bitmap & work) const {
for (SequenceConstIterator it = sequences.begin(); it != sequences.end(); it++){
const Util::ReferenceCount<Sequence> & next = *it;
next->draw(xaxis, yaxis, work);
}
}
/* Maximum ticks of any sequence */
int SequenceAll::totalTicks() const {
int max = 0;
for (SequenceConstIterator it = sequences.begin(); it != sequences.end(); it++){
const Util::ReferenceCount<Sequence> & next = *it;
int what = next->totalTicks();
if (what > max){
max = what;
}
}
return max;
}
bool SequenceAll::forward(int tickCount, double velocityX, double velocityY){
bool go = false;
for (SequenceIterator it = sequences.begin(); it != sequences.end(); it++){
Util::ReferenceCount<Sequence> & next = *it;
go = next->forward(tickCount, velocityX, velocityY) && go;
}
return go;
}
bool SequenceAll::reverse(int tickCount, double velocityX, double velocityY){
bool go = false;
for (SequenceIterator it = sequences.begin(); it != sequences.end(); it++){
Util::ReferenceCount<Sequence> & next = *it;
go = next->reverse(tickCount, velocityX, velocityY) && go;
}
return go;
}
void SequenceAll::forwardFrame(){
for (SequenceIterator it = sequences.begin(); it != sequences.end(); it++){
Util::ReferenceCount<Sequence> & next = *it;
next->forwardFrame();
}
}
void SequenceAll::backFrame(){
for (SequenceIterator it = sequences.begin(); it != sequences.end(); it++){
Util::ReferenceCount<Sequence> & next = *it;
next->backFrame();
}
}
SequenceRandom::SequenceRandom(const Token * token, ImageMap & images, const std::string & baseDir):
current(0){
TokenView view = token->view();
while (view.hasMore()){
const Token * next;
view >> next;
Util::ReferenceCount<Sequence> sequence = parseSequence(next, images, baseDir);
if (sequence != NULL){
addSequence(sequence);
}
}
current = Util::rnd(sequences.size());
}
Util::ReferenceCount<Element> SequenceRandom::getCurrentFrame() const {
return Util::ReferenceCount<Element>(NULL);
}
void SequenceRandom::reset(){
current = Util::rnd(sequences.size());
for (SequenceIterator it = sequences.begin(); it != sequences.end(); it++){
Util::ReferenceCount<Sequence> & next = *it;
next->reset();
}
}
void SequenceRandom::resetTicks(){
current = Util::rnd(sequences.size());
for (SequenceIterator it = sequences.begin(); it != sequences.end(); it++){
Util::ReferenceCount<Sequence> & next = *it;
next->resetTicks();
}
}
void SequenceRandom::setToEnd(){
for (SequenceIterator it = sequences.begin(); it != sequences.end(); it++){
Util::ReferenceCount<Sequence> & next = *it;
next->setToEnd();
}
}
void SequenceRandom::addSequence(const Util::ReferenceCount<Sequence> & sequence){
sequences.push_back(sequence);
}
void SequenceRandom::draw(int xaxis, int yaxis, const Graphics::Bitmap & work) const {
if (current < sequences.size()){
Util::ReferenceCount<Sequence> now = sequences[current];
now->draw(xaxis, yaxis, work);
}
}
int SequenceRandom::totalTicks() const {
int max = 0;
for (SequenceConstIterator it = sequences.begin(); it != sequences.end(); it++){
const Util::ReferenceCount<Sequence> & next = *it;
int what = next->totalTicks();
if (what > max){
max = what;
}
}
return max;
}
bool SequenceRandom::forward(int tickCount, double velocityX, double velocityY){
if (current < sequences.size()){
Util::ReferenceCount<Sequence> now = sequences[current];
return now->forward(tickCount, velocityX, velocityY);
}
return true;
}
bool SequenceRandom::reverse(int tickCount, double velocityX, double velocityY){
if (current < sequences.size()){
Util::ReferenceCount<Sequence> now = sequences[current];
return now->reverse(tickCount, velocityX, velocityY);
}
return true;
}
void SequenceRandom::forwardFrame(){
if (current < sequences.size()){
sequences[current]->forwardFrame();
}
}
void SequenceRandom::backFrame(){
if (current < sequences.size()){
sequences[current]->backFrame();
}
}
static int CURRENT_ID = 0;
static int getNextId(){
return CURRENT_ID++;
}
Animation::Animation(const Token *the_token):
id(getNextId()),
depth(BackgroundBottom),
allowReset(true),
sequence(0){
/* Whats this for? */
images[-1] = 0;
std::string basedir = ".";
if ( *the_token != "anim" && *the_token != "animation" ){
throw LoadException(__FILE__, __LINE__, "Not an animation");
}
/* The usual setup of an animation is
The images must be listed prior to listing any frames, basedir can be used to set the directory where the images are located
loop will begin at the subsequent frame listed after loop
axis is the location in which the drawing must be placed
location *old* - used to render in background or foreground (0 == background [default]| 1 == foreground)
depth - used to render in background or foreground space (depth background bottom|middle|top) | (depth foreground bottom|midle|top)
reset - used to allow resetting of animation (0 == no | 1 == yes [default])
velocity - used to get a wrapping scroll effect while animating
window - area in which the item will be contained
(anim (id NUM)
(location NUM)
(scale NUM) ;; optional
(depth background|foreground NUM)
(basedir LOCATION)
(image NUM FILE [SCALE])
(velocity x y)
(axis x y)
(frame "Read comments above in constructor")
(loop 2)
(reset NUM)
(window x1 y1 x2 y2))
*/
double scale = 1.0;
bool scaleSet = false;
const Token & tok = *the_token;
TokenView view = tok.view();
while (view.hasMore()){
try{
const Token * token;
view >> token;
if (*token == "id"){
// get the id
token->view() >> id;
} else if (*token == "location"){
// translate location to depth
/*int location = 0;
token->view() >> location;
if (location == 0){
depth = BackgroundBottom;
} else if (location == 1){
depth = ForegroundBottom;
}*/
Global::debug(0) << "The option (" << token->getLineage() << ") in the file '" << token->getFileName() << "' is no longer valid and will be ignored. Consider using 'depth' instead." << std::endl;
} else if (*token == "scale"){
token->view() >> scale;
scaleSet = true;
} else if (*token == "depth"){
// get the depth
std::string name, level;
token->view() >> name >> level;
if (name == "background"){
if (level == "bottom"){
depth = BackgroundBottom;
} else if (level == "middle"){
depth = BackgroundMiddle;
} else if (level == "top"){
depth = BackgroundTop;
}
} else if (name == "foreground"){
if (level == "bottom"){
depth = ForegroundBottom;
} else if (level == "middle"){
depth = ForegroundMiddle;
} else if (level == "top"){
depth = ForegroundTop;
}
}
} else if (*token == "basedir"){
// set the base directory for loading images
token->view() >> basedir;
} else if (*token == "image"){
// add bitmaps by number to the map
int number;
std::string temp;
double localScale = 1;
bool localScaleSet = false;
TokenView view = token->view();
view >> number >> temp;
try{
view >> localScale;
localScaleSet = true;
} catch (const TokenException & fail){
}
Util::ReferenceCount<Graphics::Bitmap> bmp(new Graphics::Bitmap(*Storage::instance().open(Storage::instance().find(Filesystem::RelativePath(basedir + "/" + temp)))));
if (!bmp->getError()){
if (scaleSet || localScaleSet){
if (localScaleSet){
*bmp = bmp->scaleBy(localScale, localScale);
} else {
*bmp = bmp->scaleBy(scale, scale);
}
}
images[number] = bmp;
}
} else if (*token == "axis"){
// Get the axis location it defaults to 0,0
double x=0, y=0;
try {
token->view() >> x >> y;
} catch (const TokenException & ex){
}
axis.set(x,y);
} else if (*token == "window"){
// Windowed area where to clip if necessary otherwise it defaults to max
double x1=0,x2=0, y1=0,y2=0;
try {
token->view() >> x1 >> y1 >> x2 >> y2;
} catch (const TokenException & ex){
}
window.set(x1,y1,x2,y2);
} else if (*token == "velocity"){
// This allows the animation to get a wrapping scroll action going on
double x=0, y=0;
try {
token->view() >> x >> y;
} catch (const TokenException & ex){
}
velocity.set(x,y);
} else if (*token == "frame"){
Util::ReferenceCount<Element> frame(new ImageFrame(token, images, basedir));
sequence.addSequence(Util::ReferenceCount<Sequence>(new SequenceFrame(frame)));
} else if (*token == "text"){
Util::ReferenceCount<Element> frame(new TextFrame(token));
sequence.addSequence(Util::ReferenceCount<Sequence>(new SequenceFrame(frame)));
} else if (*token == "all"){
sequence.addSequence(Util::ReferenceCount<Sequence>(new SequenceAll(token, images, basedir)));
} else if (*token == "random"){
sequence.addSequence(Util::ReferenceCount<Sequence>(new SequenceRandom(token, images, basedir)));
} else if (*token == "loop"){
// start loop here
int times;
token->view() >> times;
Util::ReferenceCount<SequenceLoop> loop(new SequenceLoop(times));
loop->parse(token, images, basedir);
sequence.addSequence(loop.convert<Sequence>());
/*
if (l >= (int)frames.size()){
ostringstream out;
out << "Loop location is larger than the number of frames. Loop: " << loop << " Frames: " << frames.size();
throw LoadException(__FILE__, __LINE__, out.str());
}
*/
} else if (*token == "reset"){
// Allow reset of animation
token->view() >> allowReset;
} else {
Global::debug( 3 ) << "Unhandled menu attribute: "<<endl;
if (Global::getDebug() >= 3){
token->print(" ");
}
}
} catch ( const TokenException & ex ) {
throw LoadException(__FILE__, __LINE__, ex, "Menu animation parse error");
} catch ( const LoadException & ex ) {
throw ex;
}
}
}
Animation::Animation(const std::string & background):
id(getNextId()),
depth(BackgroundBottom),
allowReset(true),
sequence(0){
// add bitmap
Util::ReferenceCount<Graphics::Bitmap> bmp(new Graphics::Bitmap(*Storage::instance().open(Storage::instance().find(Filesystem::RelativePath(background)))));
if (bmp->getError()){
throw LoadException(__FILE__,__LINE__, "Problem loading file: " + background);
} else {
images[0] = bmp;
}
Util::ReferenceCount<Element> frame(new ImageFrame(bmp));
sequence.addSequence(Util::ReferenceCount<Sequence>(new SequenceFrame(frame)));
}
Animation::Animation(const Filesystem::AbsolutePath & path):
id(getNextId()),
depth(BackgroundBottom),
allowReset(true),
sequence(0){
// add bitmap
Util::ReferenceCount<Graphics::Bitmap> bmp(new Graphics::Bitmap(*Storage::instance().open(path)));
if (bmp->getError()){
throw LoadException(__FILE__,__LINE__, "Problem loading file: " + path.path());
} else {
images[0] = bmp;
}
Util::ReferenceCount<Element> frame(new ImageFrame(bmp));
sequence.addSequence(Util::ReferenceCount<Sequence>(new SequenceFrame(frame)));
}
Animation::Animation(Util::ReferenceCount<Graphics::Bitmap> image):
id(getNextId()),
depth(BackgroundBottom),
allowReset(true),
sequence(0){
images[0] = image;
Util::ReferenceCount<Element> frame(new ImageFrame(image));
sequence.addSequence(Util::ReferenceCount<Sequence>(new SequenceFrame(frame)));
}
Animation::~Animation(){
}
int Animation::totalTicks() const {
return sequence.totalTicks();
}
void Animation::forward(int tickCount){
sequence.forward(tickCount, velocity.getRelativeX(), velocity.getRelativeY());
}
void Animation::reverse(int tickCount){
sequence.reverse(tickCount, velocity.getRelativeX(), velocity.getRelativeY());
}
void Animation::act(){
forward();
}
void Animation::draw(const Graphics::Bitmap & work) const {
/* FIXME: should use sub-bitmaps here */
/*const int x = window.getX();
const int y = window.getY();
const int width = window.getWidth();
const int height = window.getHeight();
Global::debug(0) << "Distance x2: " << width << " Distance y2: " << height << std::endl;
Graphics::Bitmap clipped(work, x, y, height, width);
frames[currentFrame]->draw(0, 0,clipped);*/
// Set clip from the axis default is 0,0,bitmap width, bitmap height
work.setClipRect(-window.getPosition().getDistanceFromCenterX(),
-window.getPosition().getDistanceFromCenterY(),
work.getWidth() - window.getPosition2().getDistanceFromCenterX(),
work.getHeight() - window.getPosition2().getDistanceFromCenterY());
sequence.draw(axis.getDistanceFromCenterX(), axis.getDistanceFromCenterY(), work);
work.setClipRect(0, 0, work.getWidth(), work.getHeight());
}
void Animation::draw(int x, int y, int width, int height, const Graphics::Bitmap & work) const {
const Util::ReferenceCount<Element> & frame = sequence.getCurrentFrame();
if (frame != NULL){
Graphics::Bitmap clipped(work, x, y, width, height);
frame->draw(clipped);
}
}
void Animation::forwardFrame(){
sequence.forwardFrame();
}
void Animation::backFrame(){
sequence.backFrame();
}
void Animation::reset(){
sequence.reset();
}
void Animation::resetAll(){
sequence.reset();
}
void Animation::setToEnd(){
/* FIXME */
sequence.setToEnd();
// currentFrame = frames.size()-1;
// currentLoop = 0;
// Set offsets
/*
for (std::vector<Util::ReferenceCount<Element> >::iterator i = frames.begin(); i != frames.end(); ++i){
Util::ReferenceCount<Element> frame = *i;
frame->setToEnd(RelativePoint(ticks * velocity.getRelativeX(), ticks * velocity.getRelativeY()));
}
*/
}
const std::string Animation::getInfo(){
/*
static const char * ANIMATION_TEXT = "Animation ID: %d\nTicks: %d\nFrame Index: %d\nLoop From: %d\nAxis: ( %f, %f)\nVelocity: ( %f, %f)\n";
char info[255];
sprintf(info, ANIMATION_TEXT, id, ticks, currentFrame, loop, axis.getRelativeX(), axis.getRelativeY(), velocity.getRelativeX(), velocity.getRelativeY());
return std::string(info) + frames[currentFrame]->getInfo();
*/
/* FIXME */
ostringstream out;
out << "Animation ID: " << id;
return out.str();
}
AnimationManager::AnimationManager(){
// Set the current id to 0 for each context
CURRENT_ID = 0;
}
AnimationManager::AnimationManager(const AnimationManager & copy):
animations(copy.animations){
// Set the current id to 0 for each context
CURRENT_ID = 0;
}
AnimationManager::~AnimationManager(){
}
const AnimationManager & AnimationManager::operator=(const AnimationManager & copy){
animations = copy.animations;
return *this;
}
void AnimationManager::forward(int tickCount){
for (std::map<Gui::Animation::Depth, std::vector<Util::ReferenceCount<Gui::Animation> > >::iterator i = animations.begin(); i != animations.end(); ++i){
std::vector<Util::ReferenceCount<Gui::Animation> > & animations = i->second;
for (std::vector<Util::ReferenceCount<Gui::Animation> >::iterator j = animations.begin(); j != animations.end(); ++j){
Util::ReferenceCount<Gui::Animation> animation = *j;
if (animation != NULL){
animation->forward(tickCount);
}
}
}
}
void AnimationManager::reverse(int tickCount){
for (std::map<Gui::Animation::Depth, std::vector<Util::ReferenceCount<Gui::Animation> > >::iterator i = animations.begin(); i != animations.end(); ++i){
std::vector<Util::ReferenceCount<Gui::Animation> > & animations = i->second;
for (std::vector<Util::ReferenceCount<Gui::Animation> >::iterator j = animations.begin(); j != animations.end(); ++j){
Util::ReferenceCount<Gui::Animation> animation = *j;
if (animation != NULL){
animation->reverse(tickCount);
}
}
}
}
void AnimationManager::act(){
forward();
}
void AnimationManager::render(const Gui::Animation::Depth & depth, const Graphics::Bitmap & work) const {
std::map< Gui::Animation::Depth, std::vector< Util::ReferenceCount<Gui::Animation> > >::const_iterator animation = animations.find(depth);
if (animation != animations.end()){
const vector<Util::ReferenceCount<Gui::Animation> > & all = animation->second;
for (std::vector<Util::ReferenceCount<Gui::Animation> >::const_iterator i = all.begin(); i != all.end(); ++i){
Util::ReferenceCount<Gui::Animation> animation = *i;
if (animation != NULL){
animation->draw(work);
}
}
}
}
void AnimationManager::add(Util::ReferenceCount<Gui::Animation > animation){
animations[animation->getDepth()].push_back(animation);
}
void AnimationManager::reset(){
for (std::map<Gui::Animation::Depth, std::vector<Util::ReferenceCount<Gui::Animation> > >::iterator i = animations.begin(); i != animations.end(); ++i){
std::vector<Util::ReferenceCount<Gui::Animation> > & animations = i->second;
for (std::vector<Util::ReferenceCount<Gui::Animation> >::iterator j = animations.begin(); j != animations.end(); ++j){
Util::ReferenceCount<Gui::Animation> animation = *j;
if (animation != NULL){
animation->resetAll();
}
}
}
}
int AnimationManager::totalTicks() const {
int count = 0;
for (map<Gui::Animation::Depth, vector<Util::ReferenceCount<Gui::Animation> > >::const_iterator it = animations.begin(); it != animations.end(); it++){
Gui::Animation::Depth depth = it->first;
const vector<Util::ReferenceCount<Gui::Animation> > & stuff = it->second;
int next = countTicks(stuff);
/* If any animation takes infinite time then the whole thing takes infinite time */
if (next == -1){
return -1;
}
if (next > count){
count = next;
}
}
return count;
}
int AnimationManager::countTicks(const vector<Util::ReferenceCount<Animation> > & toCount) const {
int total = 0;
for (vector<Util::ReferenceCount<Animation> >::const_iterator it = toCount.begin(); it != toCount.end(); it++){
const Util::ReferenceCount<Animation> & animation = *it;
int ticks = animation->totalTicks();
if (ticks == -1){
return ticks;
}
total += ticks;
}
return total;
}
void AnimationManager::setToEnd(){
for (std::map<Gui::Animation::Depth, std::vector<Util::ReferenceCount<Gui::Animation> > >::iterator i = animations.begin(); i != animations.end(); ++i){
std::vector<Util::ReferenceCount<Gui::Animation> > & animations = i->second;
for (std::vector<Util::ReferenceCount<Gui::Animation> >::iterator j = animations.begin(); j != animations.end(); ++j){
Util::ReferenceCount<Gui::Animation> animation = *j;
if (animation != NULL){
animation->setToEnd();
}
}
}
}
const std::string AnimationManager::getInfo(int id, bool all){
std::string info("");
for (std::map<Gui::Animation::Depth, std::vector<Util::ReferenceCount<Gui::Animation> > >::iterator i = animations.begin(); i != animations.end(); ++i){
std::vector<Util::ReferenceCount<Gui::Animation> > & animations = i->second;
for (std::vector<Util::ReferenceCount<Gui::Animation> >::iterator j = animations.begin(); j != animations.end(); ++j){
Util::ReferenceCount<Gui::Animation> animation = *j;
if (animation != NULL){
if (id == animation->getID() || all){
info += animation->getInfo();
}
}
}
}
return info;
}
const std::vector<int> AnimationManager::getIdList(){
std::vector<int> list;
for (std::map<Gui::Animation::Depth, std::vector<Util::ReferenceCount<Gui::Animation> > >::iterator i = animations.begin(); i != animations.end(); ++i){
std::vector<Util::ReferenceCount<Gui::Animation> > & animations = i->second;
for (std::vector<Util::ReferenceCount<Gui::Animation> >::iterator j = animations.begin(); j != animations.end(); ++j){
Util::ReferenceCount<Gui::Animation> animation = *j;
if (animation != NULL){
list.push_back(animation->getID());
}
}
}
return list;
}
diff --git a/util/gui/tabbed-box.cpp b/util/gui/tabbed-box.cpp
index f4edaeae..bc0b6b3a 100644
--- a/util/gui/tabbed-box.cpp
+++ b/util/gui/tabbed-box.cpp
@@ -1,330 +1,330 @@
#include "util/graphics/bitmap.h"
#include "tabbed-box.h"
#include "util/font.h"
#include "context-box.h"
using namespace Gui;
Tab::Tab():
active(false){
// Set alpha to 0 as we are not interested in the box
context.setRenderOnlyText(true);
}
Tab::~Tab(){
}
void Tab::addOption(const Util::ReferenceCount<ContextItem> & item){
context.addItem(item);
}
void Tab::render(const Graphics::Bitmap & area, const Font & font){
context.render(area, font);
}
void Tab::act(const Font & font){
context.act(font);
}
void Tab::setList(const std::vector<Util::ReferenceCount<ContextItem> > & list){
context.setList(list);
}
void Tab::setName(const std::string & name){
this->name = name;
}
void Tab::close(){
context.close();
}
void Tab::open(){
context.open();
}
void Tab::previous(const Font & font){
context.previous(font);
}
void Tab::next(const Font & font){
context.next(font);
}
void Tab::adjustLeft(){
context.adjustLeft();
}
void Tab::adjustRight(){
context.adjustRight();
}
int Tab::getCurrentIndex(){
return context.getCurrentIndex();
}
TabbedBox::TabbedBox():
current(0),
fontWidth(24),
fontHeight(24),
inTab(false),
tabWidthMax(0),
tabFontColor(Graphics::makeColor(255,255,255)),
currentTabFontColor(Graphics::makeColor(0,0,255)){
activeTabFontColor = new Effects::Gradient(50, tabFontColor, currentTabFontColor);
}
TabbedBox::TabbedBox(const TabbedBox & b):
activeTabFontColor(NULL){
this->location = b.location;
}
TabbedBox::~TabbedBox(){
for (std::vector<Gui::Tab *>::iterator i = tabs.begin(); i != tabs.end(); ++i){
Gui::Tab * tab = *i;
if (tab){
delete tab;
}
}
if (activeTabFontColor){
delete activeTabFontColor;
}
}
TabbedBox &TabbedBox::operator=( const TabbedBox &copy){
location = copy.location;
return *this;
}
// Logic
void TabbedBox::act(const Font & font){
if (!tabs.empty()){
const int width = font.textLength(tabs[current]->name.c_str()) + 5;
if (tabs.size() > 1){
tabWidthMax = (location.getWidth() - width) / (tabs.size() - 1);
} else {
tabWidthMax = location.getWidth() - width;
}
} else {
return;
}
if (!tabs[current]->active){
tabs[current]->active = true;
}
tabs[current]->act(font);
if (inTab){
if (activeTabFontColor){
activeTabFontColor->update();
}
}
}
void TabbedBox::render(const Graphics::Bitmap & work){
/* nothing */
}
// Render
void TabbedBox::render(const Graphics::Bitmap & work, const Font & font){
const int tabHeight = fontHeight + 5;
// checkWorkArea();
Graphics::Bitmap area(work, location.getX(), location.getY(), location.getWidth(), location.getHeight());
// Check if we are using a rounded box
if (transforms.getRadius() > 0){
const int offset = transforms.getRadius() * 4;
- const Graphics::Bitmap & temp = Graphics::Bitmap::temporaryBitmap(location.getWidth(), offset/2);
+ Graphics::Bitmap temp(location.getWidth(), offset/2);
temp.clearToMask();
temp.roundRectFill((int)transforms.getRadius(), 0, offset/2 * -1, location.getWidth()-1, (offset/2)-1, colors.body);
temp.roundRect((int)transforms.getRadius(), 0, offset/2 * -1, location.getWidth()-1, (offset/2)-1, colors.border);
temp.translucent().draw(0,location.getHeight() - offset/2, area);
area.translucent().rectangleFill(0, tabHeight+1, location.getWidth()-1, location.getHeight()-1 - offset/2, colors.body );
area.translucent().vLine(tabHeight,0,location.getHeight()-1 - offset/2,colors.border);
area.translucent().vLine(tabHeight,location.getWidth()-1,location.getHeight()-1 - offset/2,colors.border);
} else {
area.translucent().rectangleFill(0, tabHeight+1, location.getWidth()-1, location.getHeight()-1, colors.body );
area.translucent().vLine(tabHeight,0,location.getHeight()-1,colors.border);
area.translucent().hLine(0,location.getHeight()-1,location.getWidth()-1,colors.border);
area.translucent().vLine(tabHeight,location.getWidth()-1,location.getHeight()-1,colors.border);
}
tabs[current]->render(area, font);
renderTabs(area, font);
/* FIXME: only render the background in translucent mode, the text should
* not be translucent
*/
// workArea->draw(location.getX(), location.getY(), work);
}
// Add tab
void TabbedBox::addTab(const std::string & name, const std::vector<Util::ReferenceCount<ContextItem> > & list){
for (std::vector<Tab *>::iterator i = tabs.begin(); i != tabs.end(); ++i){
Tab * tab = *i;
if (tab->name == name){
return;
}
}
Tab * tab = new Tab();
tab->name = name;
tab->setList(list);
addTab(tab);
}
void TabbedBox::addTab(Tab * tab){
const int modifier = fontHeight * .35;
tab->getContext().location.setPosition(Gui::AbsolutePoint(0, fontHeight + modifier));
tab->getContext().location.setPosition2(Gui::AbsolutePoint(location.getWidth(), location.getHeight()- modifier));
tab->open();
tabs.push_back(tab);
}
void TabbedBox::moveTab(int direction){
tabs[current]->close();
tabs[current]->active = false;
current = (unsigned int) ((int)current + direction + (int) tabs.size()) % tabs.size();
tabs[current]->open();
tabs[current]->active = true;
}
void TabbedBox::up(const Font & font){
if (tabs.size() == 0){
return;
}
if (!inTab){
moveTab(-1);
} else {
tabs[current]->previous(font);
}
}
void TabbedBox::down(const Font & font){
if (tabs.size() == 0){
return;
}
if (!inTab){
moveTab(1);
} else {
tabs[current]->next(font);
}
}
void TabbedBox::left(const Font & font){
if (tabs.size() == 0){
return;
}
if (!inTab){
moveTab(-1);
} else {
tabs[current]->adjustLeft();
}
}
void TabbedBox::right(const Font & font){
if (tabs.size() == 0){
return;
}
if (!inTab){
moveTab(1);
} else {
tabs[current]->adjustRight();
}
}
void TabbedBox::toggleTabSelect(){
inTab = !inTab;
}
unsigned int TabbedBox::getCurrentIndex() const {
if (tabs.size() == 0){
return 0;
}
return this->tabs[current]->getCurrentIndex();
}
void TabbedBox::setTabFontColor(Graphics::Color color){
tabFontColor = color;
if (activeTabFontColor){
delete activeTabFontColor;
}
activeTabFontColor = new Effects::Gradient(50, tabFontColor, currentTabFontColor);
}
void TabbedBox::setSelectedTabFontColor(Graphics::Color color){
currentTabFontColor = color;
if (activeTabFontColor){
delete activeTabFontColor;
}
activeTabFontColor = new Effects::Gradient(50, tabFontColor, currentTabFontColor);
}
void TabbedBox::renderTabs(const Graphics::Bitmap & bmp, const Font & vFont){
const int tabHeight = fontHeight + 5;
int x = 0;
Graphics::Bitmap::transBlender(0, 0, 0, colors.bodyAlpha);
for (std::vector<Gui::Tab *>::iterator i = tabs.begin(); i != tabs.end(); ++i){
Gui::Tab * tab = *i;
const int textWidth = vFont.textLength(tab->name.c_str()) + 5;
// for last tab
int modifier = 0;
// Check last tab so we can ensure proper sizing
if ( i == (tabs.begin() + tabs.size() -1)){
if ( ( (tabWidthMax * (tabs.size() - 1) ) + textWidth ) != (unsigned int)location.getWidth() ){
modifier = location.getWidth() - x - (tab->active ? textWidth : tabWidthMax);
}
}
if (transforms.getRadius() > 0){
const int offset = transforms.getRadius() * 4;
if (tab->active){
Graphics::Bitmap area(bmp, x, 0, x+textWidth+modifier-1, tabHeight+1);
if (!inTab){
area.translucent().roundRectFill((int)transforms.getRadius(), 0, 0, textWidth+modifier-1, tabHeight*2, colors.body);
area.translucent().roundRect((int)transforms.getRadius(), 0, 0, textWidth+modifier-1, tabHeight*2, colors.border);
vFont.printf((((textWidth + modifier)/2)-(((textWidth + modifier) - 5)/2)), 0, currentTabFontColor, area, tab->name, 0 );
} else {
area.translucent().roundRectFill((int)transforms.getRadius(), 0, 0, textWidth+modifier-1, tabHeight*2, colors.body);
area.translucent().roundRect((int)transforms.getRadius(), 0, 0, textWidth+modifier-1, tabHeight*2, colors.border);
vFont.printf((((textWidth + modifier)/2)-(((textWidth + modifier) - 5)/2)), 0, activeTabFontColor->current(), area, tab->name, 0 );
}
x+=textWidth + modifier;
} else {
const int heightMod = tabHeight * .15;
Graphics::Bitmap area(bmp, x, 1 + heightMod, x+tabWidthMax+modifier-1, tabHeight-heightMod);
area.translucent().roundRectFill((int)transforms.getRadius(),0,0,tabWidthMax+modifier-1,tabHeight*2,Graphics::makeColor(105, 105, 105));
area.translucent().roundRect((int)transforms.getRadius(),0,0,tabWidthMax+modifier-1,tabHeight*2,Graphics::makeColor(58, 58, 58));
area.translucent().hLine(0,tabHeight,tabWidthMax+modifier-1,colors.border);
vFont.printf((((tabWidthMax + modifier)/2)-((textWidth + modifier)/2)), 0, tabFontColor, area, tab->name, 0 );
x += tabWidthMax + modifier;
}
} else {
if (tab->active){
Graphics::Bitmap area(bmp, x, 0, x+textWidth+modifier-1, tabHeight+1);
if (!inTab){
area.translucent().rectangleFill(0, 0, textWidth+modifier-1, tabHeight*2, colors.body);
area.translucent().rectangle(0, 0, textWidth+modifier-1, tabHeight*2, colors.border);
vFont.printf((((textWidth + modifier)/2)-(((textWidth + modifier) - 5)/2)), 0, currentTabFontColor, area, tab->name, 0 );
} else {
area.translucent().rectangleFill(0, 0, textWidth+modifier-1, tabHeight*2, colors.body);
area.translucent().rectangle(0, 0, textWidth+modifier-1, tabHeight*2, colors.border);
vFont.printf((((textWidth + modifier)/2)-(((textWidth + modifier) - 5)/2)), 0, activeTabFontColor->current(), area, tab->name, 0 );
}
x+=textWidth + modifier;
} else {
const int heightMod = tabHeight * .15;
Graphics::Bitmap area(bmp, x, 1 + heightMod, x+tabWidthMax+modifier-1, tabHeight-heightMod);
area.translucent().rectangleFill(0,0,tabWidthMax+modifier-1,tabHeight*2,Graphics::makeColor(105, 105, 105));
area.translucent().rectangle(0,0,tabWidthMax+modifier-1,tabHeight*2,Graphics::makeColor(58, 58, 58));
area.translucent().hLine(0,tabHeight,tabWidthMax+modifier-1,colors.border);
vFont.printf((((tabWidthMax + modifier)/2)-((textWidth + modifier)/2)), 0, tabFontColor, area, tab->name, 0 );
x += tabWidthMax + modifier;
}
}
}
}

File Metadata

Mime Type
text/x-diff
Expires
Tue, Jun 16, 12:22 AM (2 w, 1 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
71083
Default Alt Text
(221 KB)

Event Timeline