Page MenuHomePhabricator (Chris)

No OneTemporary

Authored By
Unknown
Size
194 KB
Referenced Files
None
Subscribers
None
diff --git a/util/allegro/bitmap.cpp b/util/allegro/bitmap.cpp
index 88142534..86ed6703 100644
--- a/util/allegro/bitmap.cpp
+++ b/util/allegro/bitmap.cpp
@@ -1,1803 +1,1798 @@
/* allegro.h must be on top, don't move it!!!! */
#include <allegro.h>
#ifdef _WIN32
#include <winalleg.h>
#endif
#include "../gif/algif.h"
#include "../bitmap.h"
#include "../lit_bitmap.h"
#include "../trans-bitmap.h"
#include "../init.h"
#include <stdarg.h>
#include <vector>
#include <string>
#include <iostream>
#include <math.h>
#include "../funcs.h"
#include <stdio.h>
#include "../load_exception.h"
#include "../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{
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 int focus_color, const int edge_color);
static void paintown_applyTrans16(BITMAP * dst, const int color);
int MaskColor(){
return MASK_COLOR_16;
}
static Bitmap * Scaler = NULL;
static Bitmap * Buffer = NULL;
Bitmap::Bitmap():
own( NULL ),
mustResize(false),
error( false ),
bit8MaskColor(0){
getData().setBitmap( create_bitmap( 10, 10 ) );
if (! getData().getBitmap()){
error = true;
cerr << "Could not create bitmap!" << endl;
} else {
clear();
own = new int;
*own = 1;
}
}
Bitmap::Bitmap( int x, int y ):
own( NULL ),
mustResize(false),
error( false ),
bit8MaskColor(0){
if ( x < 1 ){
x = 1;
}
if ( y < 1 ){
y = 1;
}
getData().setBitmap( create_bitmap( x, y ) );
if ( ! getData().getBitmap() ){
error = true;
cerr << "Could not create bitmap!" << endl;
} else {
clear();
own = new int;
*own = 1;
}
}
enum Format{
PNG,
GIF,
};
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, Format type){
switch (type){
case PNG : {
break;
}
case GIF : {
return memoryGIF(data, length);
break;
}
}
throw Exception::Base(__FILE__, __LINE__);
}
Bitmap::Bitmap(const char * data, int length):
own(NULL),
mustResize(false),
error(false),
bit8MaskColor(0){
/* FIXME: pass the type in */
Format type = GIF;
getData().setBitmap(load_bitmap_from_memory(data, length, type));
own = new int;
*own = 1;
}
/* 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 ):
own( NULL ),
mustResize(false),
error( false ),
bit8MaskColor(0){
if ( deep_copy ){
BITMAP * his = who;
getData().setBitmap( 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 );
own = new int;
*own = 1;
} else {
getData().setBitmap( who );
own = NULL;
}
}
Bitmap::Bitmap( const char * load_file ):
own( NULL ),
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 ):
own( NULL ),
mustResize(false),
error( false ),
bit8MaskColor(0){
internalLoadFile( load_file.c_str() );
}
Bitmap::Bitmap( const char * load_file, int sx, int sy ):
own( NULL ),
mustResize(false),
error( false ),
bit8MaskColor(0){
path = load_file;
BITMAP * temp = load_bitmap( load_file, NULL );
// my_bitmap = load_bitmap( load_file, NULL );
getData().setBitmap( 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 );
}
// own = true;
own = new int;
*own = 1;
}
Bitmap::Bitmap( const char * load_file, int sx, int sy, double accuracy ):
own( NULL ),
mustResize(false),
error( false ),
bit8MaskColor(0){
path = load_file;
BITMAP * temp = load_bitmap( load_file, NULL );
own = new int;
*own = 1;
if ( !temp ){
cout<<"Could not load "<<load_file<<endl;
getData().setBitmap( 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);
getData().setBitmap( 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 getData().setBitmap( temp );
}
// own = true;
}
Bitmap::Bitmap( const Bitmap & copy, int sx, int sy ):
own( NULL ),
mustResize(false),
error( false ),
bit8MaskColor(copy.bit8MaskColor){
path = copy.getPath();
BITMAP * temp = copy.getData().getBitmap();
getData().setBitmap( 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 );
// own = true;
// own = copy.own;
own = new int;
*own = 1;
}
Bitmap::Bitmap( const Bitmap & copy, int sx, int sy, double accuracy ):
own( NULL ),
mustResize(false),
error( false ),
bit8MaskColor(copy.bit8MaskColor){
path = copy.getPath();
BITMAP * temp = copy.getData().getBitmap();
own = new int;
*own = 1;
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);
getData().setBitmap( 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 {
getData().setBitmap( 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 ):
own( NULL ),
mustResize(false),
error( false ),
bit8MaskColor(copy.bit8MaskColor){
path = copy.getPath();
if ( deep_copy ){
BITMAP * his = copy.getData().getBitmap();
getData().setBitmap( 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 );
own = new int;
*own = 1;
} else {
getData().setBitmap( copy.getData().getBitmap() );
// own = false;
own = copy.own;
if ( own ){
*own = *own + 1;
}
}
/*
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 ):
own( NULL ),
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;
getData().setBitmap( create_sub_bitmap( his, x, y, width, height ) );
if ( ! getData().getBitmap() ){
cout<<"Could not create sub-bitmap"<<endl;
getData().setBitmap( create_bitmap( 10, 10 ) );
// clear( my_bitmap );
clear();
}
// own = true;
own = new int;
*own = 1;
}
void Bitmap::internalLoadFile( const char * load_file ){
path = load_file;
getData().setBitmap( load_bitmap( load_file, NULL ) );
if ( ! getData().getBitmap() ){
cout<<"Could not load "<<load_file<<". Using default"<<endl;
getData().setBitmap( 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;
}
// own = true;
own = new int;
*own = 1;
}
void Bitmap::save( const string & str ) const {
save_bitmap( str.c_str(), getData().getBitmap(), NULL );
}
Bitmap 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];
int 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;
}
void initializeExtraStuff(){
/* nothing yet */
}
void Bitmap::destroyPrivateData(){
destroy_bitmap(getData().getBitmap());
}
int Bitmap::getWidth() const{
return getData().getBitmap()->w;
}
int Bitmap::getHeight() const{
return getData().getBitmap()->h;
}
int getRed( int x ){
return ::getr( x );
}
int getBlue( int x ){
return ::getb( x );
}
int getGreen( int x ){
return ::getg( x );
}
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<<"Own = "<< own <<" : "<< *own <<endl;
cout<<"Path = "<<path<<endl;
}
Bitmap & Bitmap::operator=( const Bitmap & copy ){
/*
if ( own ){
(*own)--;
if ( *own == 0 ){
destroy_bitmap( getBitmap() );
delete own;
}
}
*/
releaseInternalBitmap();
path = copy.getPath();
getData().setBitmap( copy.getData().getBitmap() );
// own = false;
own = copy.own;
if ( own )
*own += 1;
return *this;
}
/*
Bitmap::~Bitmap(){
releaseInternalBitmap();
}
*/
void Bitmap::detach(){
/*
if ( own ){
(*own)--;
if ( *own == 0 ){
destroy_bitmap( getBitmap() );
delete own;
}
}
*/
releaseInternalBitmap();
}
/*
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, int color ) const {
::circlefill( getData().getBitmap(), x, y, radius, color );
}
void TranslucentBitmap::circleFill(int x, int y, int radius, int color) const {
drawingMode(MODE_TRANS);
Bitmap::circleFill(x, y, radius, color);
drawingMode(MODE_SOLID);
}
void Bitmap::circle( int x, int y, int radius, int color ) const{
::circle( getData().getBitmap(), x, y, radius, color );
}
void Bitmap::line( const int x1, const int y1, const int x2, const int y2, const int color ) const{
::fastline( getData().getBitmap(), x1, y1, x2, y2, color );
}
void Bitmap::floodfill( const int x, const int y, const int color ) const {
::floodfill( getData().getBitmap(), x, y, color );
}
void Bitmap::drawCharacter( const int x, const int y, const int color, const int background, const Bitmap & where ) const {
::draw_character_ex( where.getData().getBitmap(), getData().getBitmap(), x, y, color, background );
}
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(int original, int 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){
putpixel(bitmap, j, i, replaced);
}
}
}
}
void Bitmap::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;
}
}
}
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 );
Scaler = new Bitmap(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;
}
*/
int Bitmap::getPixel( const int x, const int y ) const{
if ( x >= 0 && x < getData().getBitmap()->w && y >= 0 && y < getData().getBitmap()->h )
return _getpixel16( getData().getBitmap(), x, y );
return -1;
}
void Bitmap::readLine( vector< int > & 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( 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);
}
int makeColor( int r, int g, int b ){
return ::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);
}
int Bitmap::addColor( int color1, int color2 ){
return makeColor( getr( color1 ) + getr( color2 ),
getg( color1 ) + getg( color2 ),
getb( color1 ) + getb( color2 ) );
}
void Bitmap::putPixelNormal(int x, int y, int col) const {
BITMAP * dst = getData().getBitmap();
::putpixel(dst, x, y, col);
}
/* 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, int color) const {
drawingMode(MODE_TRANS);
Bitmap::putPixelNormal(x, y, color);
drawingMode(MODE_SOLID);
}
void Bitmap::putPixel( int x, int y, int 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 );
}
/*
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, int color ) const{
::triangle( getData().getBitmap(), x1, y1, x2, y2, x3, y3, color );
}
void Bitmap::ellipse( int x, int y, int rx, int ry, int color ) const {
::ellipse( getData().getBitmap(), x, y, rx, ry, color );
}
void TranslucentBitmap::ellipse(int x, int y, int rx, int ry, int color) const {
drawingMode(MODE_TRANS);
Bitmap::ellipse(x, y, rx, ry, color);
drawingMode(MODE_SOLID);
}
void Bitmap::ellipseFill( int x, int y, int rx, int ry, int color ) const {
::ellipsefill( getData().getBitmap(), x, y, rx, ry, color );
}
void Bitmap::rectangle( int x1, int y1, int x2, int y2, int color ) const{
::rect( getData().getBitmap(), x1, y1, x2, y2, color );
}
void TranslucentBitmap::rectangle( int x1, int y1, int x2, int y2, int 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, int color ) const{
::rectfill( getData().getBitmap(), x1, y1, x2, y2, color );
}
void TranslucentBitmap::rectangleFill( int x1, int y1, int x2, int y2, int 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 int color ) const{
::hline( getData().getBitmap(), x1, y, x2, color );
}
void TranslucentBitmap::hLine( const int x1, const int y, const int x2, const int color ) const{
drawingMode(MODE_TRANS);
::hline(getData().getBitmap(), x1, y, x2, color);
drawingMode(MODE_SOLID);
}
void Bitmap::vLine( const int y1, const int x, const int y2, const int color ) const{
::vline( getData().getBitmap(), x, y1, y2, color );
}
void Bitmap::polygon( const int * verts, const int nverts, const int color ) const{
::polygon( getData().getBitmap(), nverts, verts, color );
}
void Bitmap::arc(const int x, const int y, const double ang1, const double ang2, const int radius, const int color ) const{
::arc( getData().getBitmap(), x, y, ::ftofix(ang1), ::ftofix(ang2), radius, color );
}
/*
void Bitmap::clear(){
this->fill( 0 );
}
*/
void Bitmap::fill( int color ) const{
::clear_to_color( getData().getBitmap(), 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, int focus_color, int 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 int 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::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());
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(c);
}
break;
}
case SPRITE_LIT : {
if (filter){
c = PAINTOWN_DLSX_BLEND(lit_blender, filter->filter(c));
} 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(c));
} 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(c));
} 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(c));
} 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(c));
} 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 int 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);
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 int focus_color, const int edge_color){
int dxbeg = x - width;
int x_dir = 1;
unsigned char * alphas = new unsigned char[width];
int * colors = new int[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];
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(c));
} 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(c));
} 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(c));
} 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(c));
} 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 = makeColor(255, 0, 255);
// 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(c));
} else {
PAINTOWN_PUT_MEMORY_PIXEL(d, mask);
}
}
}
}
-Bitmap getScreenBuffer(){
- return Bitmap(GFX_X, GFX_Y);
}
-void resetDisplay(){
-}
-
-}
+#include "../software-renderer/bitmap.cpp"
diff --git a/util/allegro5/bitmap.cpp b/util/allegro5/bitmap.cpp
index 987fcfbf..1aac0cef 100644
--- a/util/allegro5/bitmap.cpp
+++ b/util/allegro5/bitmap.cpp
@@ -1,795 +1,840 @@
#include <sstream>
#include <allegro5/allegro_memfile.h>
#include <allegro5/allegro_primitives.h>
#include "util/debug.h"
namespace Graphics{
/* it doesnt look like we need to pack colors into 16-bit values */
#if 0
static const int rgb_r_shift_16 = 0;
static const int rgb_g_shift_16 = 5;
static const int rgb_b_shift_16 = 11;
static inline int pack565(unsigned char red, unsigned char green, unsigned char blue){
return (((red >> 3) << rgb_r_shift_16) |
((green >> 2) << rgb_g_shift_16) |
((blue >> 3) << rgb_b_shift_16));
}
/* from allegro4 */
static inline void unpack565(int color, unsigned char * red, unsigned char * green, unsigned char * blue){
static int _rgb_scale_5[32] = {
0, 8, 16, 24, 33, 41, 49, 57,
66, 74, 82, 90, 99, 107, 115, 123,
132, 140, 148, 156, 165, 173, 181, 189,
198, 206, 214, 222, 231, 239, 247, 255
};
static int _rgb_scale_6[64] = {
0, 4, 8, 12, 16, 20, 24, 28,
32, 36, 40, 44, 48, 52, 56, 60,
65, 69, 73, 77, 81, 85, 89, 93,
97, 101, 105, 109, 113, 117, 121, 125,
130, 134, 138, 142, 146, 150, 154, 158,
162, 166, 170, 174, 178, 182, 186, 190,
195, 199, 203, 207, 211, 215, 219, 223,
227, 231, 235, 239, 243, 247, 251, 255
};
*red = _rgb_scale_5[(color >> rgb_r_shift_16) & 0x1F];
*green = _rgb_scale_6[(color >> rgb_g_shift_16) & 0x3F];
*blue = _rgb_scale_5[(color >> rgb_b_shift_16) & 0x1F];
}
#endif
struct BlendingData{
BlendingData():
red(0), green(0), blue(0), alpha(0){
}
int red, green, blue, alpha;
};
static BlendingData globalBlend;
Color makeColorAlpha(unsigned char red, unsigned char green, unsigned char blue, unsigned char alpha){
return al_map_rgba(red, blue, green, alpha);
}
Color MaskColor(){
static Color mask = makeColorAlpha(0, 0, 0, 0);
return mask;
}
Color getBlendColor(){
return makeColorAlpha(255, 255, 255, globalBlend.alpha);
}
class Blender{
public:
Blender(){
}
virtual ~Blender(){
/* default is to draw the source and ignore the destination */
al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_ZERO);
}
};
class MaskedBlender: public Blender {
public:
MaskedBlender(){
- al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_ZERO);
+ al_set_blender(ALLEGRO_ADD, ALLEGRO_ALPHA, ALLEGRO_INVERSE_ALPHA);
}
};
class TransBlender: public Blender {
public:
TransBlender(){
// al_set_blender(ALLEGRO_ADD, ALLEGRO_ALPHA, ALLEGRO_ONE);
al_set_blender(ALLEGRO_ADD, ALLEGRO_ALPHA, ALLEGRO_INVERSE_ALPHA);
}
};
static const int WINDOWED = 0;
static const int FULLSCREEN = 1;
static Bitmap * Scaler = NULL;
Bitmap::Bitmap():
own(NULL),
mustResize(false),
bit8MaskColor(makeColor(0, 0, 0)){
/* TODO */
}
Bitmap::Bitmap( const char * load_file ):
own(NULL),
mustResize(false),
bit8MaskColor(makeColor(0, 0, 0)){
internalLoadFile(load_file);
}
Bitmap::Bitmap( const std::string & load_file ):
own(NULL),
mustResize(false),
bit8MaskColor(makeColor(0, 0, 0)){
internalLoadFile(load_file.c_str());
}
Bitmap::Bitmap(ALLEGRO_BITMAP * who, bool deep_copy):
own(NULL),
mustResize(false),
bit8MaskColor(makeColor(0, 0, 0)){
if (deep_copy){
ALLEGRO_BITMAP * clone = al_clone_bitmap(who);
getData().setBitmap(clone);
own = new int;
*own = 1;
} else {
getData().setBitmap(who);
}
}
Bitmap::Bitmap(int width, int height):
own(NULL),
mustResize(false),
bit8MaskColor(makeColor(0, 0, 0)){
ALLEGRO_BITMAP * bitmap = al_create_bitmap(width, height);
if (bitmap == NULL){
std::ostringstream out;
out << "Could not create bitmap with dimensions " << width << ", " << height;
throw BitmapException(__FILE__, __LINE__, out.str());
}
getData().setBitmap(bitmap);
own = new int;
*own = 1;
}
Bitmap::Bitmap( const Bitmap & copy, bool deep_copy):
own(NULL),
mustResize(false),
bit8MaskColor(copy.bit8MaskColor){
if (deep_copy){
ALLEGRO_BITMAP * clone = al_clone_bitmap(copy.getData().getBitmap());
getData().setBitmap(clone);
own = new int;
*own = 1;
} else {
getData().setBitmap(copy.getData().getBitmap());
own = copy.own;
if (own){
*own += 1;
}
}
}
enum Format{
PNG,
GIF,
};
Bitmap Bitmap::memoryPCX(unsigned char * const data, const int length, const bool mask){
/* TODO */
return Bitmap();
}
void Bitmap::replaceColor(Color original, Color replaced){
/* TODO */
}
static ALLEGRO_BITMAP * memoryGIF(const char * data, int length){
ALLEGRO_FILE * memory = al_open_memfile((void *) data, length, "r");
al_fclose(memory);
/* FIXME: get gif addon for a5 */
#if 0
RGB * palette = NULL;
/* algif will close the packfile for us in both error and success cases */
BITMAP * gif = load_gif_packfile(pack, palette);
if (!gif){
al_fclose(memory);
// pack_fclose(pack);
ostringstream out;
out <<"Could not load gif from memory: " << (void*) data << " length " << length;
throw LoadException(__FILE__, __LINE__, out.str());
}
BITMAP * out = create_bitmap(gif->w, gif->h);
blit(gif, out, 0, 0, 0, 0, gif->w, gif->h);
destroy_bitmap(gif);
// pack_fclose(pack);
#endif
ALLEGRO_BITMAP * out = NULL;
return out;
}
void Bitmap::internalLoadFile(const char * path){
this->path = path;
ALLEGRO_BITMAP * loaded = al_load_bitmap(path);
if (loaded == NULL){
std::ostringstream out;
out << "Could not load file '" << path << "'";
throw BitmapException(__FILE__, __LINE__, out.str());
}
al_convert_mask_to_alpha(loaded, al_map_rgb(255, 0, 255));
getData().setBitmap(loaded);
own = new int;
*own = 1;
}
static ALLEGRO_BITMAP * load_bitmap_from_memory(const char * data, int length, Format type){
switch (type){
case PNG : {
break;
}
case GIF : {
return memoryGIF(data, length);
break;
}
}
throw Exception::Base(__FILE__, __LINE__);
}
Bitmap::Bitmap(const char * data, int length):
own(NULL),
mustResize(false),
bit8MaskColor(makeColor(0, 0, 0)){
Format type = GIF;
getData().setBitmap(load_bitmap_from_memory(data, length, type));
if (getData().getBitmap() == NULL){
std::ostringstream out;
out << "Could not create bitmap from memory";
throw BitmapException(__FILE__, __LINE__, out.str());
}
own = new int;
*own = 1;
}
Bitmap::Bitmap( const Bitmap & copy, int x, int y, int width, int height ):
own(NULL),
mustResize(false),
bit8MaskColor(copy.bit8MaskColor){
path = copy.getPath();
ALLEGRO_BITMAP * his = copy.getData().getBitmap();
if (x < 0)
x = 0;
if (y < 0)
y = 0;
if (width + x > al_get_bitmap_width(his)){
width = al_get_bitmap_width(his) - x;
}
if (height + y > al_get_bitmap_height(his)){
height = al_get_bitmap_height(his) - y;
}
ALLEGRO_BITMAP * sub = al_create_sub_bitmap(his, x, y, width, height);
getData().setBitmap(sub);
own = new int;
*own = 1;
}
int Bitmap::getWidth() const {
if (getData().getBitmap() != NULL){
return al_get_bitmap_width(getData().getBitmap());
}
return 0;
}
int getRed(Color color){
unsigned char red, green, blue;
al_unmap_rgb(color, &red, &green, &blue);
return red;
}
int getGreen(Color color){
unsigned char red, green, blue;
al_unmap_rgb(color, &red, &green, &blue);
return green;
}
int getBlue(Color color){
unsigned char red, green, blue;
al_unmap_rgb(color, &red, &green, &blue);
return blue;
}
Color makeColor(int red, int blue, int green){
return al_map_rgb(red, blue, green);
}
int Bitmap::getHeight() const {
if (getData().getBitmap() != NULL){
return al_get_bitmap_height(getData().getBitmap());
}
return 0;
}
void initializeExtraStuff(){
// al_set_new_bitmap_format(ALLEGRO_PIXEL_FORMAT_RGB_565);
}
int setGraphicsMode(int mode, int width, int height){
initializeExtraStuff();
switch (mode){
case FULLSCREEN: {
al_set_new_display_flags(ALLEGRO_FULLSCREEN);
break;
}
case WINDOWED: {
al_set_new_display_flags(ALLEGRO_WINDOWED | ALLEGRO_RESIZABLE);
break;
}
default: break;
}
ALLEGRO_DISPLAY * display = al_create_display(width, height);
if (display == NULL){
std::ostringstream out;
out << "Could not create display with dimensions " << width << ", " << height;
throw BitmapException(__FILE__, __LINE__, out.str());
}
Screen = new Bitmap(al_get_backbuffer(display));
Scaler = new Bitmap(width, height);
/* default drawing mode */
al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_ZERO);
return 0;
}
Color Bitmap::getPixel(const int x, const int y) const {
return al_get_pixel(getData().getBitmap(), x, y);
// Color color = al_get_pixel(getData().getBitmap(), x, y);
// return pack565(color.r, color.g, color.b);
}
void Bitmap::putPixel(int x, int y, Color pixel) const {
al_set_target_bitmap(getData().getBitmap());
al_put_pixel(x, y, pixel);
}
void Bitmap::putPixelNormal(int x, int y, Color col) const {
putPixel(x, y, col);
}
void Bitmap::fill(Color color) const {
/*
unsigned char red, green, blue;
unpack565(color, &red, &green, &blue);
al_set_target_bitmap(getData().getBitmap());
al_clear_to_color(al_map_rgb(red, green, blue));
*/
al_set_target_bitmap(getData().getBitmap());
al_clear_to_color(color);
}
void Bitmap::transBlender(int r, int g, int b, int a){
globalBlend.red = r;
globalBlend.green = g;
globalBlend.blue = b;
globalBlend.alpha = a;
}
void Bitmap::Stretch( const Bitmap & where, const int sourceX, const int sourceY, const int sourceWidth, const int sourceHeight, const int destX, const int destY, const int destWidth, const int destHeight ) const {
/* TODO */
}
void Bitmap::StretchBy2( const Bitmap & where ){
/* TODO */
}
void Bitmap::StretchBy4( const Bitmap & where ){
/* TODO */
}
void Bitmap::drawRotate( const int x, const int y, const int angle, const Bitmap & where ){
/* TODO */
}
void Bitmap::drawPivot( const int centerX, const int centerY, const int x, const int y, const int angle, const Bitmap & where ){
/* TODO */
}
void Bitmap::drawPivot( const int centerX, const int centerY, const int x, const int y, const int angle, const double scale, const Bitmap & where ){
/* TODO */
}
void Bitmap::drawStretched( const int x, const int y, const int new_width, const int new_height, const Bitmap & who ) const {
/* FIXME */
- MaskedBlender blender;
al_set_target_bitmap(who.getData().getBitmap());
+ MaskedBlender blender;
/* any source pixels with an alpha value of 0 will be masked */
al_draw_bitmap(getData().getBitmap(), x, y, 0);
}
void Bitmap::Blit(const int mx, const int my, const int width, const int height, const int wx, const int wy, const Bitmap & where) const {
// double start = al_get_time();
al_set_target_bitmap(where.getData().getBitmap());
// al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_ZERO);
/*
if (&where != Screen){
al_draw_bitmap(getData().getBitmap(), wx, wy, 0);
}
*/
+ /* FIXME: deal with mx, my, width, height */
+
// al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_ZERO);
al_draw_bitmap(getData().getBitmap(), wx, wy, 0);
/*
double end = al_get_time();
Global::debug(0) << "Draw in " << (end - start) << " seconds" << std::endl;
*/
}
void Bitmap::drawHFlip(const int x, const int y, const Bitmap & where) const {
- /* TODO */
+ al_set_target_bitmap(where.getData().getBitmap());
+ MaskedBlender blender;
+ /* any source pixels with an alpha value of 0 will be masked */
+ al_draw_bitmap(getData().getBitmap(), x, y, ALLEGRO_FLIP_HORIZONTAL);
}
void Bitmap::drawHFlip(const int x, const int y, Filter * filter, const Bitmap & where) const {
- /* TODO */
+ /* FIXME: deal with filter */
+ al_set_target_bitmap(where.getData().getBitmap());
+ MaskedBlender blender;
+ /* any source pixels with an alpha value of 0 will be masked */
+ al_draw_bitmap(getData().getBitmap(), x, y, ALLEGRO_FLIP_HORIZONTAL);
}
void Bitmap::drawVFlip( const int x, const int y, const Bitmap & where ) const {
- /* TODO */
+ al_set_target_bitmap(where.getData().getBitmap());
+ MaskedBlender blender;
+ /* any source pixels with an alpha value of 0 will be masked */
+ al_draw_bitmap(getData().getBitmap(), x, y, ALLEGRO_FLIP_VERTICAL);
}
void Bitmap::drawVFlip( const int x, const int y, Filter * filter, const Bitmap & where ) const {
- /* TODO */
+ /* FIXME: deal with filter */
+ al_set_target_bitmap(where.getData().getBitmap());
+ MaskedBlender blender;
+ /* any source pixels with an alpha value of 0 will be masked */
+ al_draw_bitmap(getData().getBitmap(), x, y, ALLEGRO_FLIP_VERTICAL);
}
void Bitmap::drawHVFlip( const int x, const int y, const Bitmap & where ) const {
- /* TODO */
+ al_set_target_bitmap(where.getData().getBitmap());
+ MaskedBlender blender;
+ /* any source pixels with an alpha value of 0 will be masked */
+ al_draw_bitmap(getData().getBitmap(), x, y, ALLEGRO_FLIP_VERTICAL | ALLEGRO_FLIP_HORIZONTAL);
}
void Bitmap::drawHVFlip( const int x, const int y, Filter * filter, const Bitmap & where ) const {
- /* TODO */
+ /* FIXME: deal with filter */
+ al_set_target_bitmap(where.getData().getBitmap());
+ MaskedBlender blender;
+ /* any source pixels with an alpha value of 0 will be masked */
+ al_draw_bitmap(getData().getBitmap(), x, y, ALLEGRO_FLIP_VERTICAL | ALLEGRO_FLIP_HORIZONTAL);
}
void Bitmap::BlitMasked(const int mx, const int my, const int width, const int height, const int wx, const int wy, const Bitmap & where) const {
/* TODO */
}
void Bitmap::BlitToScreen(const int upper_left_x, const int upper_left_y) const {
#if 0
if (getWidth() != Screen->getWidth() || getHeight() != Screen->getHeight()){
/*
this->Blit( upper_left_x, upper_left_y, *Buffer );
Buffer->Stretch(*Scaler);
Scaler->Blit(0, 0, 0, 0, *Screen);
*/
this->Stretch(*Scaler, 0, 0, getWidth(), getHeight(), upper_left_x, upper_left_y, Scaler->getWidth(), Scaler->getHeight());
Scaler->Blit(0, 0, 0, 0, *Screen);
} else {
this->Blit(upper_left_x, upper_left_y, *Screen);
}
#endif
/*
if (&where == Screen){
al_flip_display();
}
*/
al_flip_display();
}
void Bitmap::BlitAreaToScreen(const int upper_left_x, const int upper_left_y) const {
al_flip_display();
}
void Bitmap::draw(const int x, const int y, const Bitmap & where) const {
// TransBlender blender;
- MaskedBlender blender;
al_set_target_bitmap(where.getData().getBitmap());
+ 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 {
/* FIXME */
- MaskedBlender blender;
al_set_target_bitmap(where.getData().getBitmap());
+ MaskedBlender blender;
/* any source pixels with an alpha value of 0 will be masked */
al_draw_bitmap(getData().getBitmap(), x, y, 0);
}
void Bitmap::hLine( const int x1, const int y, const int x2, const Color color ) const {
/* TODO */
}
void Bitmap::vLine( const int x1, const int y, const int x2, const Color color ) const {
/* TODO */
}
static const double S_PI = 3.14159265358979323846;
void Bitmap::arc(const int x, const int y, const double ang1, const double ang2, const int radius, const Color color ) const {
al_set_target_bitmap(getData().getBitmap());
al_draw_arc(x, y, radius, ang1 + S_PI/2, ang2 - ang1, color, 0);
}
void Bitmap::floodfill( const int x, const int y, const Color color ) const {
/* TODO */
}
void Bitmap::line( const int x1, const int y1, const int x2, const int y2, const Color color ) const {
/* TODO */
}
void Bitmap::circleFill(int x, int y, int radius, Color color) const {
al_set_target_bitmap(getData().getBitmap());
al_draw_filled_circle(x, y, radius, color);
}
void Bitmap::circle(int x, int y, int radius, Color color) const {
al_set_target_bitmap(getData().getBitmap());
al_draw_circle(x, y, radius, color, 0);
}
void Bitmap::rectangle( int x1, int y1, int x2, int y2, Color color ) const {
al_set_target_bitmap(getData().getBitmap());
al_draw_rectangle(x1, y1, x2, y2, color, 0);
}
void Bitmap::rectangleFill( int x1, int y1, int x2, int y2, Color color ) const {
/*
unsigned char red, green, blue;
unpack565(color, &red, &green, &blue);
*/
al_set_target_bitmap(getData().getBitmap());
al_draw_filled_rectangle(x1, y1, x2, y2, color);
}
void Bitmap::triangle( int x1, int y1, int x2, int y2, int x3, int y3, Color color ) const {
/* TODO */
}
void Bitmap::polygon( const int * verts, const int nverts, const Color color ) const {
/* TODO */
}
void Bitmap::ellipse( int x, int y, int rx, int ry, Color color ) const {
/* TODO */
}
void Bitmap::ellipseFill( int x, int y, int rx, int ry, Color color ) const {
/* TODO */
}
void Bitmap::applyTrans(const Color color) const {
/* TODO */
}
void Bitmap::light(int x, int y, int width, int height, int start_y, int focus_alpha, int edge_alpha, int focus_color, Color edge_color) const {
/* TODO */
}
void Bitmap::drawCharacter( const int x, const int y, const int color, const int background, const Bitmap & where ) const {
/* TODO */
}
void Bitmap::save( const std::string & str ) const {
/* TODO */
}
void Bitmap::readLine(std::vector<Color> & line, int y){
/* TODO */
}
void TranslucentBitmap::draw(const int x, const int y, const Bitmap & where) const {
- TransBlender blender;
al_set_target_bitmap(where.getData().getBitmap());
+ TransBlender blender;
al_draw_tinted_bitmap(getData().getBitmap(), getBlendColor(), x, y, 0);
}
void LitBitmap::draw( const int x, const int y, const Bitmap & where ) const {
/* TODO */
}
void LitBitmap::draw( const int x, const int y, Filter * filter, const Bitmap & where ) const {
/* TODO */
}
void LitBitmap::drawHFlip( const int x, const int y, const Bitmap & where ) const {
/* TODO */
}
void LitBitmap::drawHFlip( const int x, const int y, Filter * filter, const Bitmap & where ) const {
/* TODO */
}
void LitBitmap::drawVFlip( const int x, const int y, const Bitmap & where ) const {
/* TODO */
}
void LitBitmap::drawVFlip( const int x, const int y, Filter * filter, const Bitmap & where ) const {
/* TODO */
}
void LitBitmap::drawHVFlip( const int x, const int y, const Bitmap & where ) const {
/* TODO */
}
void LitBitmap::drawHVFlip( const int x, const int y, Filter * filter, const Bitmap & where ) const {
/* TODO */
}
void TranslucentBitmap::draw( const int x, const int y, Filter * filter, const Bitmap & where ) const {
/* TODO */
}
void TranslucentBitmap::drawHFlip( const int x, const int y, const Bitmap & where ) const {
/* TODO */
}
void TranslucentBitmap::drawHFlip( const int x, const int y, Filter * filter, const Bitmap & where ) const {
/* TODO */
}
void TranslucentBitmap::drawVFlip( const int x, const int y, const Bitmap & where ) const {
/* TODO */
}
void TranslucentBitmap::drawVFlip( const int x, const int y, Filter * filter, const Bitmap & where ) const {
/* TODO */
}
void TranslucentBitmap::drawHVFlip( const int x, const int y, const Bitmap & where ) const {
/* TODO */
}
void TranslucentBitmap::drawHVFlip( const int x, const int y, Filter * filter,const Bitmap & where ) const {
/* TODO */
}
void TranslucentBitmap::hLine( const int x1, const int y, const int x2, const Color color ) const {
/* TODO */
}
void TranslucentBitmap::circleFill(int x, int y, int radius, Color color) const {
/* TODO */
}
Color doTransBlend(const Color & color, int alpha){
float red, green, blue;
float alpha_f = alpha / 255.0;
al_unmap_rgb_f(color, &red, &green, &blue);
red *= alpha_f;
green *= alpha_f;
blue *= alpha_f;
return al_map_rgb_f(red, green, blue);
}
void TranslucentBitmap::putPixelNormal(int x, int y, Color color) const {
- TransBlender blender;
al_set_target_bitmap(getData().getBitmap());
+ TransBlender blender;
al_put_pixel(x, y, doTransBlend(color, globalBlend.alpha));
}
void TranslucentBitmap::rectangle( int x1, int y1, int x2, int y2, Color color ) const {
/* TODO */
}
void TranslucentBitmap::rectangleFill(int x1, int y1, int x2, int y2, Color color) const {
/* TODO */
}
void TranslucentBitmap::ellipse( int x, int y, int rx, int ry, Color color ) const {
/* TODO */
}
Bitmap & Bitmap::operator=(const Bitmap & copy){
releaseInternalBitmap();
path = copy.getPath();
getData().setBitmap(copy.getData().getBitmap());
// own = false;
own = copy.own;
if (own)
*own += 1;
return *this;
}
void Bitmap::setClipRect( int x1, int y1, int x2, int y2 ) const {
/* TODO */
}
void Bitmap::getClipRect(int & x1, int & y1, int & x2, int & y2) const {
/* TODO */
}
void Bitmap::destroyPrivateData(){
al_destroy_bitmap(getData().getBitmap());
// al_set_target_bitmap(Screen->getData().getBitmap());
}
int setGfxModeFullscreen(int x, int y){
return setGraphicsMode(FULLSCREEN, x, y);
}
int setGfxModeWindowed( int x, int y ){
return setGraphicsMode(WINDOWED, x, y);
}
int setGfxModeText(){
/* TODO */
return 0;
}
bool Bitmap::getError(){
/* TODO */
return false;
}
void Bitmap::addBlender( int r, int g, int b, int a ){
/* TODO */
}
void Bitmap::differenceBlender( int r, int g, int b, int a ){
/* TODO */
}
void Bitmap::multiplyBlender( int r, int g, int b, int a ){
/* TODO */
}
void Bitmap::drawingMode(int type){
/* TODO */
}
void Bitmap::shutdown(){
delete Screen;
Screen = NULL;
/*
delete Scaler;
Scaler = NULL;
delete Buffer;
Buffer = NULL;
*/
}
+StretchedBitmap::StretchedBitmap(int width, int height, const Bitmap & parent):
+Bitmap(parent, 0, 0, parent.getWidth(), parent.getHeight()),
+width(width),
+height(height),
+where(parent){
+}
+
+void StretchedBitmap::start(){
+ ALLEGRO_TRANSFORM transform;
+ al_set_target_bitmap(getData().getBitmap());
+ al_identity_transform(&transform);
+ al_scale_transform(&transform, getWidth() / width, getHeight() / height);
+ al_use_transform(&transform);
+}
+
+void StretchedBitmap::finish(){
+ ALLEGRO_TRANSFORM transform;
+ al_set_target_bitmap(getData().getBitmap());
+ al_identity_transform(&transform);
+ al_use_transform(&transform);
+}
+
Bitmap getScreenBuffer(){
return *Screen;
}
void resetDisplay(){
al_set_target_bitmap(Screen->getData().getBitmap());
}
}
static bool sameColor(Graphics::Color color1, Graphics::Color color2){
unsigned char r1, g1, b1, a1;
unsigned char r2, g2, b2, a2;
al_unmap_rgba(color1, &r1, &g1, &b1, &a1);
al_unmap_rgba(color2, &r2, &g2, &b2, &a2);
return r1 == r2 &&
g1 == g2 &&
b1 == b2 &&
a1 == a2;
}
static uint32_t quantify(const ALLEGRO_COLOR & color){
unsigned char red, green, blue, alpha;
al_unmap_rgba(color, &red, &green, &blue, &alpha);
return (red << 24) |
(green << 16) |
(blue << 8) |
alpha;
}
bool operator<(const ALLEGRO_COLOR color1, const ALLEGRO_COLOR color2){
return quantify(color1) < quantify(color2);
}
bool operator!=(const ALLEGRO_COLOR color1, const ALLEGRO_COLOR color2){
return !(color1 == color2);
}
bool operator==(const ALLEGRO_COLOR color1, const ALLEGRO_COLOR color2){
return sameColor(color1, color2);
}
diff --git a/util/bitmap.cpp b/util/bitmap.cpp
index 05e18639..9038a3a4 100644
--- a/util/bitmap.cpp
+++ b/util/bitmap.cpp
@@ -1,411 +1,412 @@
/*
#ifdef USE_ALLEGRO
#include <allegro.h>
#endif
*/
#include "funcs.h"
#include "bitmap.h"
#include "trans-bitmap.h"
+#include "stretch-bitmap.h"
#include "lit_bitmap.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;
/* 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;
}
void initializeExtraStuff();
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;
}
}
}
releaseInternalBitmap();
}
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;
}
}
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);
}
}
/* 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;
/*
BITMAP * b = create_bitmap( width, height );
::stretch_blit( getData().getBitmap(), b, 0, 0, getData().getBitmap()->w, getData().getBitmap()->h, 0, 0, b->w, b->h );
releaseInternalBitmap();
own = new int;
getData().setBitmap( b );
*own = 1;
*/
}
/* decrement bitmap reference counter and free memory if counter hits 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;
}
}
}
void Bitmap::BlitToScreen() const {
// this->Blit( *Bitmap::Screen );
this->BlitToScreen(0, 0);
}
void Bitmap::load( const std::string & str ){
releaseInternalBitmap();
internalLoadFile( str.c_str() );
}
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::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, y1, x2, y2;
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(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);
}
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::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());
}
}
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(){
}
TranslucentBitmap Bitmap::translucent() const {
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);
}
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/init.cpp b/util/init.cpp
index e02bd337..bf315690 100644
--- a/util/init.cpp
+++ b/util/init.cpp
@@ -1,587 +1,587 @@
#ifdef USE_ALLEGRO
#include <allegro.h>
#ifdef ALLEGRO_WINDOWS
#include <winalleg.h>
#endif
#endif
#ifdef USE_ALLEGRO5
#include <allegro5/allegro.h>
#include <allegro5/allegro_image.h>
#include <allegro5/allegro_primitives.h>
#endif
#ifdef USE_SDL
#include <SDL.h>
#endif
#ifndef WINDOWS
#include <signal.h>
#include <string.h>
#include <unistd.h>
#endif
#ifdef LINUX
#include <execinfo.h>
#endif
/* don't be a boring tuna */
// #warning you are ugly
#include "globals.h"
#include "init.h"
#include "network/network.h"
#include "thread.h"
#include <time.h>
#include <ostream>
#include "dumb/include/dumb.h"
#ifdef USE_ALLEGRO
#include "dumb/include/aldumb.h"
#include "loadpng/loadpng.h"
#include "gif/algif.h"
#endif
#include "bitmap.h"
#include "funcs.h"
#include "file-system.h"
#include "font.h"
#include "sound.h"
#include "configuration.h"
#include "music.h"
#include "loading.h"
#include "input/keyboard.h"
#include "message-queue.h"
#ifdef WII
#include <fat.h>
#endif
using namespace std;
volatile int Global::speed_counter4 = 0;
/* enough seconds for 136 years */
volatile unsigned int Global::second_counter = 0;
/* the original engine was running at 90 ticks per second, but we dont
* need to render that fast, so TICS_PER_SECOND is really fps and
* LOGIC_MULTIPLIER will be used to adjust the speed counter to its
* original value.
*/
const int Global::TICS_PER_SECOND = 40;
const double Global::LOGIC_MULTIPLIER = (double) 90 / (double) Global::TICS_PER_SECOND;
#ifdef USE_ALLEGRO
const int Global::WINDOWED = GFX_AUTODETECT_WINDOWED;
const int Global::FULLSCREEN = GFX_AUTODETECT_FULLSCREEN;
#else
/* FIXME: use enums here or something */
const int Global::WINDOWED = 0;
const int Global::FULLSCREEN = 1;
#endif
/* game counter, controls FPS */
static void inc_speed_counter(){
/* probably put input polling here, InputManager::poll(). no, don't do that.
* polling is done in the standardLoop now.
*/
Global::speed_counter4 += 1;
}
#ifdef USE_ALLEGRO
END_OF_FUNCTION(inc_speed_counter)
#endif
/* if you need to count seconds for some reason.. */
static void inc_second_counter() {
Global::second_counter += 1;
}
#ifdef USE_ALLEGRO
END_OF_FUNCTION(inc_second_counter)
#endif
#if !defined(WINDOWS) && !defined(WII) && !defined(MINPSPW) && !defined(PS3) && !defined(NDS)
#ifdef LINUX
static void print_stack_trace(){
/* use addr2line on these addresses to get a filename and line number */
void *trace[128];
int frames = backtrace(trace, 128);
printf("Stack trace\n");
for (int i = 0; i < frames; i++){
printf(" %p\n", trace[i]);
}
}
#endif
static void handleSigSegV(int i, siginfo_t * sig, void * data){
const char * message = "Bug! Caught a memory violation. Shutting down..\n";
int dont_care = write(1, message, 48);
dont_care = dont_care;
#ifdef LINUX
print_stack_trace();
#endif
// Global::shutdown_message = "Bug! Caught a memory violation. Shutting down..";
Graphics::setGfxModeText();
#ifdef USE_ALLEGRO
allegro_exit();
#endif
#ifdef USE_SDL
SDL_Quit();
#endif
/* write to a log file or something because sigsegv shouldn't
* normally happen.
*/
exit(1);
}
#else
#endif
/* catch a socket being closed prematurely on unix */
#if !defined(WINDOWS) && !defined(WII) && !defined(MINPSPW) && !defined(PS3) && !defined(NDS)
static void handleSigPipe( int i, siginfo_t * sig, void * data ){
}
/*
static void handleSigUsr1( int i, siginfo_t * sig, void * data ){
pthread_exit( NULL );
}
*/
#endif
static void registerSignals(){
#if !defined(WINDOWS) && !defined(WII) && !defined(MINPSPW) && !defined(PS3) && !defined(NDS)
struct sigaction action;
memset( &action, 0, sizeof(struct sigaction) );
action.sa_sigaction = handleSigPipe;
sigaction( SIGPIPE, &action, NULL );
memset( &action, 0, sizeof(struct sigaction) );
action.sa_sigaction = handleSigSegV;
sigaction( SIGSEGV, &action, NULL );
/*
action.sa_sigaction = handleSigUsr1;
sigaction( SIGUSR1, &action, NULL );
*/
#endif
}
/* should probably call the janitor here or something */
static void close_paintown(){
Music::pause();
Graphics::setGfxModeText();
#ifdef USE_ALLEGRO
allegro_exit();
#endif
exit(0);
}
namespace Global{
extern int do_shutdown;
}
static void close_window(){
/* when do_shutdown is 1 the game will attempt to throw ShutdownException
* wherever it is. If the game is stuck or the code doesn't throw
* ShutdownException then when the user tries to close the window
* twice we just forcifully shutdown.
*/
Global::do_shutdown += 1;
if (Global::do_shutdown == 2){
close_paintown();
}
}
#ifdef USE_ALLEGRO
END_OF_FUNCTION(close_window)
#endif
#ifdef USE_ALLEGRO5
struct TimerInfo{
TimerInfo(void (*x)(), ALLEGRO_TIMER * y):
tick(x), timer(y){}
void (*tick)();
ALLEGRO_TIMER * timer;
};
static void * do_timer(void * info){
TimerInfo * timerInfo = (TimerInfo*) info;
ALLEGRO_EVENT_SOURCE * source = al_get_timer_event_source(timerInfo->timer);
ALLEGRO_EVENT_QUEUE * queue = al_create_event_queue();
al_register_event_source(queue, source);
while (true){
ALLEGRO_EVENT event;
al_wait_for_event(queue, &event);
timerInfo->tick();
}
al_destroy_event_queue(queue);
al_destroy_timer(timerInfo->timer);
delete timerInfo;
}
static Util::Thread::Id start_timer(void (*func)(), int frequency){
ALLEGRO_TIMER * timer = al_create_timer(ALLEGRO_BPS_TO_SECS(frequency));
if (timer == NULL){
Global::debug(0) << "Could not create timer" << endl;
}
al_start_timer(timer);
TimerInfo * info = new TimerInfo(func, timer);
Util::Thread::Id thread;
Util::Thread::createThread(&thread, NULL, (Util::Thread::ThreadFunction) do_timer, (void*) info);
return thread;
}
static void initSystem(ostream & out){
out << "Allegro5 initialize " << (al_init() ? "Ok" : "Failed") << endl;
uint32_t version = al_get_allegro_version();
int major = version >> 24;
int minor = (version >> 16) & 255;
int revision = (version >> 8) & 255;
int release = version & 255;
out << "Allegro5 version " << major << "." << minor << "." << revision << "." << release << endl;
out << "Allegro5 image addon " << al_init_image_addon() << endl;
al_init_primitives_addon();
al_install_keyboard();
al_set_app_name("Paintown");
start_timer(inc_speed_counter, Global::TICS_PER_SECOND);
- // start_timer(inc_second_counter, 1);
+ start_timer(inc_second_counter, 1);
}
#endif
#ifdef USE_ALLEGRO
static void initSystem(ostream & out){
out << "Allegro version: " << ALLEGRO_VERSION_STR << endl;
out << "Allegro init: " <<allegro_init()<<endl;
out << "Install timer: " <<install_timer()<<endl;
/* png */
loadpng_init();
algif_init();
out<<"Install keyboard: "<<install_keyboard()<<endl;
/* do we need the mouse?? */
// out<<"Install mouse: "<<install_mouse()<<endl;
out<<"Install joystick: "<<install_joystick(JOY_TYPE_AUTODETECT)<<endl;
/* 16 bit color depth */
set_color_depth(16);
LOCK_VARIABLE( speed_counter4 );
LOCK_VARIABLE( second_counter );
LOCK_FUNCTION( (void *)inc_speed_counter );
LOCK_FUNCTION( (void *)inc_second_counter );
/* set up the timers */
out<<"Install game timer: "<< install_int_ex(inc_speed_counter, BPS_TO_TIMER(Global::TICS_PER_SECOND))<<endl;
out<<"Install second timer: "<<install_int_ex(inc_second_counter, BPS_TO_TIMER(1))<<endl;
/* keep running in the background */
set_display_switch_mode(SWITCH_BACKGROUND);
/* close window when the X is pressed */
LOCK_FUNCTION(close_window);
set_close_button_callback(close_window);
}
#endif
#ifdef USE_SDL
// static pthread_t events;
struct TimerInfo{
TimerInfo(void (*x)(), int y):
tick(x), frequency(y){}
void (*tick)();
int frequency;
};
static void * do_timer(void * arg){
TimerInfo info = *(TimerInfo *) arg;
uint32_t delay = (uint32_t)(1000.0 / (double) info.frequency);
/* assuming SDL_GetTicks() starts at 0, this should last for about 50 days
* before overflowing. overflow should work out fine. Assuming activate occurs
* when the difference between now and ticks is at least 6, the following will happen.
* ticks now now-ticks
* 4294967294 4294967294 0
* 4294967294 4294967295 1
* 4294967294 0 2
* 4294967294 1 3
* 4294967294 2 4
* 4294967294 3 5
* 4294967294 4 6
* Activate
* 3 5 2
* 3 6 3
* 3 7 4
* 3 8 5
* 3 9 6
* Activate
*
* Can 'now' ever be much larger than 'ticks' due to overflow?
* It doesn't seem like it.
*/
uint32_t ticks = SDL_GetTicks();
/* TODO: pass in some variable that tells this loop to quit */
while (true){
uint32_t now = SDL_GetTicks();
while (now - ticks >= delay){
// Global::debug(0) << "Tick!" << endl;
info.tick();
ticks += delay;
}
SDL_Delay(1);
}
delete (TimerInfo *) arg;
return NULL;
}
static Util::Thread::Id start_timer(void (*func)(), int frequency){
TimerInfo * speed = new TimerInfo(func, frequency);
/*
speed.tick = func;
speed.frequency = frequency;
*/
Util::Thread::Id thread;
Util::Thread::createThread(&thread, NULL, (Util::Thread::ThreadFunction) do_timer, (void*) speed);
return thread;
}
#if 0
static void * handleEvents(void * arg){
bool done = false;
while (!done){
SDL_Event event;
int ok = SDL_WaitEvent(&event);
if (ok){
switch (event.type){
case SDL_QUIT : {
done = true;
close_window();
break;
}
default : {
// Global::debug(0) << "Ignoring SDL event " << event.type << endl;
break;
}
}
}
}
return NULL;
}
#endif
/*
static void doSDLQuit(){
SDL_Event quit;
quit.type = SDL_QUIT;
SDL_PushEvent(&quit);
Global::debug(0) << "Waiting for SDL event handler to finish" << endl;
pthread_join(events, NULL);
SDL_Quit();
}
*/
static void initSystem(ostream & out){
out << "SDL Init: ";
int ok = SDL_Init(SDL_INIT_VIDEO |
SDL_INIT_AUDIO |
SDL_INIT_TIMER |
SDL_INIT_JOYSTICK |
SDL_INIT_NOPARACHUTE);
if (ok == 0){
out << "Ok" << endl;
} else {
out << "Failed (" << ok << ") - " << SDL_GetError() << endl;
exit(ok);
}
/* Just do SDL thread init
#ifdef MINPSPW
pthread_init();
#endif
*/
start_timer(inc_speed_counter, Global::TICS_PER_SECOND);
start_timer(inc_second_counter, 1);
try{
SDL_Surface * icon = SDL_LoadBMP(Filesystem::find(Filesystem::RelativePath("menu/icon.bmp")).path().c_str());
if (icon != NULL){
SDL_WM_SetIcon(icon, NULL);
}
} catch (const Filesystem::NotFound & failed){
Global::debug(0) << "Could not find window icon: " << failed.getTrace() << endl;
}
SDL_WM_SetCaption("Paintown", NULL);
SDL_EnableUNICODE(1);
SDL_JoystickEventState(1);
atexit(SDL_Quit);
// atexit(doSDLQuit);
}
#endif
/* mostly used for testing purposes */
bool Global::initNoGraphics(){
/* copy/pasting the init code isn't ideal, maybe fix it later */
ostream & out = Global::debug(0);
out << "-- BEGIN init --" << endl;
out << "Data path is " << Util::getDataPath2().path() << endl;
out << "Paintown version " << Global::getVersionString() << endl;
out << "Build date " << __DATE__ << " " << __TIME__ << endl;
#ifdef WII
/* <WinterMute> fatInitDefault will set working dir to argv[0] passed by launcher,
* or root of first device mounted
*/
out << "Fat init " << (fatInitDefault() == true ? "Ok" : "Failed") << endl;
#endif
/*
char buffer[512];
if (getcwd(buffer, 512) != 0){
printf("Working directory '%s'\n", buffer);
}
*/
if (!Filesystem::exists(Util::getDataPath2())){
Global::debug(0) << "Cannot find data path '" << Util::getDataPath2().path() << "'! Either use the -d switch to specify the data directory or find the data directory and move it to that path" << endl;
return false;
}
/* do implementation specific setup */
initSystem(out);
dumb_register_stdfiles();
// Sound::initialize();
Filesystem::initialize();
Graphics::SCALE_X = GFX_X;
Graphics::SCALE_Y = GFX_Y;
Configuration::loadConfigurations();
const int sx = Configuration::getScreenWidth();
const int sy = Configuration::getScreenHeight();
Graphics::Bitmap::setFakeGraphicsMode(sx, sy);
/* music */
atexit(&dumb_exit);
out << "Initialize random number generator" << endl;
/* initialize random number generator */
srand(time(NULL));
registerSignals();
#ifdef HAVE_NETWORKING
out << "Initialize network" << endl;
Network::init();
atexit(Network::closeAll);
#endif
/* this mutex is used to show the loading screen while the game loads */
// Util::Thread::initializeLock(&Loader::loading_screen_mutex);
out << "-- END init --" << endl;
return true;
}
bool Global::init(int gfx){
ostream & out = Global::debug( 0 );
out << "-- BEGIN init --" << endl;
out << "Data path is " << Util::getDataPath2().path() << endl;
out << "Paintown version " << Global::getVersionString() << endl;
out << "Build date " << __DATE__ << " " << __TIME__ << endl;
#ifdef WII
/* <WinterMute> fatInitDefault will set working dir to argv[0] passed by launcher,
* or root of first device mounted
*/
out << "Fat init " << (fatInitDefault() == 0 ? "Ok" : "Failed") << endl;
#endif
/*
char buffer[512];
if (getcwd(buffer, 512) != 0){
printf("Working directory '%s'\n", buffer);
}
*/
if (!Filesystem::exists(Util::getDataPath2())){
Global::debug(0) << "Cannot find data path '" << Util::getDataPath2().path() << "'! Either use the -d switch to specify the data directory or find the data directory and move it to that path" << endl;
return false;
}
/* do implementation specific setup */
initSystem(out);
dumb_register_stdfiles();
Sound::initialize();
Filesystem::initialize();
Graphics::SCALE_X = GFX_X;
Graphics::SCALE_Y = GFX_Y;
Configuration::loadConfigurations();
const int sx = Configuration::getScreenWidth();
const int sy = Configuration::getScreenHeight();
if (gfx == -1){
gfx = Configuration::getFullscreen() ? Global::FULLSCREEN : Global::WINDOWED;
} else {
Configuration::setFullscreen(gfx == Global::FULLSCREEN);
}
/* set up the screen */
int gfxCode = Graphics::setGraphicsMode(gfx, sx, sy);
if (gfxCode == 0){
out << "Set graphics mode: Ok" << endl;
} else {
out << "Set graphics mode: Failed! (" << gfxCode << ")" << endl;
return false;
}
/* music */
atexit(&dumb_exit);
out << "Initialize random number generator" << endl;
/* initialize random number generator */
srand(time(NULL));
registerSignals();
#ifdef HAVE_NETWORKING
out << "Initialize network" << endl;
Network::init();
atexit(Network::closeAll);
#endif
/* this mutex is used to show the loading screen while the game loads */
Util::Thread::initializeLock(&Global::messageLock);
out << "-- END init --" << endl;
/*
const Font & font = Font::getDefaultFont();
// font.setSize(30, 30);
Bitmap temp(font.textLength("Loading") + 1, font.getHeight("Loading") + 1);
font.printf(0, 0, Bitmap::makeColor(255, 255, 255), temp, "Loading", 0);
temp.BlitToScreen(sx / 2, sy / 2);
*/
Graphics::Bitmap white(Graphics::getScreenBuffer());
white.fill(Graphics::makeColor(255, 255, 255));
white.BlitToScreen();
return true;
}
diff --git a/util/loading.cpp b/util/loading.cpp
index 03aaa0d0..fac789e4 100644
--- a/util/loading.cpp
+++ b/util/loading.cpp
@@ -1,488 +1,492 @@
#include "bitmap.h"
#include "trans-bitmap.h"
#include <math.h>
#include <iostream>
/* FIXME: get rid of this dependancy */
#include "paintown-engine/level/utils.h"
#include "messages.h"
#include "loading.h"
#include "file-system.h"
#include "font.h"
#include "funcs.h"
#include "gradient.h"
#include "parameter.h"
#include "thread.h"
#include "globals.h"
#include <vector>
#include "thread.h"
#include "message-queue.h"
#include "init.h"
#include "events.h"
using namespace std;
namespace Loader{
volatile bool done_loading = true;
typedef struct pair{
int x, y;
} ppair;
class Info{
public:
Info(){
Global::registerInfo(&messages);
}
bool transferMessages(Messages & box){
bool did = false;
while (messages.hasAny()){
const string & str = messages.get();
box.addMessage(str);
did = true;
}
return did;
}
~Info(){
Global::unregisterInfo(&messages);
}
private:
MessageQueue messages;
};
void * loadingScreenSimple1(void * arg);
static void setupBackground(const Graphics::Bitmap & background, int load_x, int load_y, int load_width, int load_height, int infobox_x, int infobox_y, int infoWidth, int infoHeight, const Graphics::Bitmap & infoBackground, const Graphics::Bitmap & work){
background.Blit(load_x, load_y, load_width, load_height, 0, 0, work);
Font::getDefaultFont().printf( 400, 480 - Font::getDefaultFont().getHeight() * 5 / 2 - Font::getDefaultFont().getHeight(), Graphics::makeColor( 192, 192, 192 ), background, "Paintown version %s", 0, Global::getVersionString().c_str());
Font::getDefaultFont().printf( 400, 480 - Font::getDefaultFont().getHeight() * 5 / 2, Graphics::makeColor( 192, 192, 192 ), background, "Made by Jon Rafkind", 0 );
background.BlitToScreen();
background.Blit(infobox_x, infobox_y, infoWidth, infoHeight, 0, 0, infoBackground);
}
/* converts a bitmap with some text on it into a sequence of points */
static vector<ppair> generateFontPixels(const Font & myFont, const string & message, int width, int height){
Graphics::Bitmap letters(width, height);
letters.fill(Graphics::MaskColor());
myFont.printf( 0, 0, Graphics::makeColor(255, 255, 255), letters, message.c_str(), 0 );
vector< ppair > pairs;
/* store every pixel we need to draw */
for (int x = 0; x < letters.getWidth(); x++){
for (int y = 0; y < letters.getHeight(); y++){
Graphics::Color pixel = letters.getPixel(x, y);
if (pixel != Graphics::MaskColor()){
ppair p;
p.x = x;
p.y = y;
pairs.push_back(p);
}
}
}
+ Graphics::resetDisplay();
+
return pairs;
}
/* shows time elapsed */
class TimeCounter{
public:
TimeCounter():
work(200, 40){
start = Global::second_counter;
last = 0;
}
void draw(int x, int y){
const Font & font = Font::getDefaultFont(24, 24);
if (Global::second_counter != last){
work.clear();
last = Global::second_counter;
font.printf(0, 0, Graphics::makeColor(192, 192, 192), work, "Waiting.. %d", 0, last - start);
work.BlitAreaToScreen(x, y);
}
}
Graphics::Bitmap work;
unsigned int start;
unsigned int last;
};
static void loadingScreen1(LoadingContext & context, const Level::LevelInfo & levelInfo){
int load_x = 80;
int load_y = 220;
const int infobox_width = 300;
const int infobox_height = 150;
+ Graphics::resetDisplay();
const Font & myFont = Font::getFont(Global::DEFAULT_FONT, 24, 24);
if (levelInfo.getPositionX() != -1){
load_x = levelInfo.getPositionX();
}
if (levelInfo.getPositionY() != -1){
load_y = levelInfo.getPositionY();
}
// const char * the_string = (arg != NULL) ? (const char *) arg : "Loading...";
int load_width = myFont.textLength(levelInfo.loadingMessage().c_str());
int load_height = myFont.getHeight(levelInfo.loadingMessage().c_str());
Global::debug(2) << "loading screen" << endl;
Messages infobox(infobox_width, infobox_height);
const int MAX_COLOR = 200;
/* blend from dark grey to light red */
Effects::Gradient gradient(MAX_COLOR, Graphics::makeColor(16, 16, 16), Graphics::makeColor(192, 8, 8));
TimeCounter counter;
struct State{
bool drawInfo;
};
class Logic: public Util::Logic {
public:
Logic(LoadingContext & context, State & state, Effects::Gradient & gradient, Messages & infoBox):
context(context),
state(state),
gradient(gradient),
infobox(infoBox){
}
LoadingContext & context;
State & state;
Effects::Gradient & gradient;
Info info;
Messages & infobox;
void run(){
gradient.backward();
state.drawInfo = info.transferMessages(infobox) || state.drawInfo;
}
double ticks(double system){
return system;
}
bool done(){
return context.done();
}
};
class Draw: public Util::Draw {
public:
Draw(const Level::LevelInfo & levelInfo, State & state, Messages & infobox, Effects::Gradient & gradient, int load_width, int load_height, int infobox_width, int infobox_height, int load_x, int load_y):
gradient(gradient),
state(state),
infobox(infobox),
work(load_width, load_height),
infoWork(infobox_width, infobox_height),
infoBackground(infobox_width, infobox_height),
infobox_x(load_x),
infobox_y(load_y + load_height * 2),
load_x(load_x),
load_y(load_y){
const Font & myFont = Font::getFont(Global::DEFAULT_FONT, 24, 24);
pairs = generateFontPixels(myFont, levelInfo.loadingMessage(), load_width, load_height);
if (levelInfo.getBackground() != 0){
setupBackground(*levelInfo.getBackground(), load_x, load_y, load_width, load_height, infobox_x, infobox_y, infoBackground.getWidth(), infoBackground.getHeight(), infoBackground, work);
} else {
setupBackground(Graphics::Bitmap(levelInfo.loadingBackground().path()), load_x, load_y, load_width, load_height, infobox_x, infobox_y, infoBackground.getWidth(), infoBackground.getHeight(), infoBackground, work);
}
}
Effects::Gradient & gradient;
State & state;
Messages & infobox;
Graphics::Bitmap work;
Graphics::Bitmap infoWork;
Graphics::Bitmap infoBackground;
vector<ppair> pairs;
const int infobox_x;
const int infobox_y;
const int load_x;
const int load_y;
void draw(){
for (vector< ppair >::iterator it = pairs.begin(); it != pairs.end(); it++){
Graphics::Color color = gradient.current(it->x);
work.putPixel(it->x, it->y, color);
}
if (state.drawInfo){
infoBackground.Blit(infoWork);
const Font & infoFont = Font::getFont(Global::DEFAULT_FONT, 24, 24);
/* cheesy hack to change the font size. the font
* should store the size and change it on its own
*/
Font::getFont(Global::DEFAULT_FONT, 13, 13);
infobox.draw(0, 0, infoWork, infoFont);
Font::getFont(Global::DEFAULT_FONT, 24, 24);
infoWork.BlitAreaToScreen(infobox_x, infobox_y);
state.drawInfo = false;
}
/* work already contains the correct background */
// work.Blit( load_x, load_y, *Bitmap::Screen );
work.BlitAreaToScreen(load_x, load_y);
}
};
State state;
state.drawInfo = true;
Logic logic(context, state, gradient, infobox);
Draw draw(levelInfo, state, infobox, gradient, load_width, load_height, infobox_width, infobox_height, load_x, load_y);
Util::standardLoop(logic, draw);
+ Graphics::resetDisplay();
#if 0
while (! context.done()){
/* true if a logic loop has passed */
bool draw = firstDraw;
/* will be true if any new info messages appeared */
bool drawInfo = firstDraw;
firstDraw = false;
if ( Global::speed_counter > 0 ){
double think = Global::speed_counter;
Global::speed_counter = 0;
draw = true;
while ( think > 0 ){
gradient.backward();
think -= 1;
}
/* if no new messages appeared this will be false */
drawInfo = info.transferMessages(infobox);
} else {
Util::rest( 1 );
}
if (draw){
for ( vector< ppair >::iterator it = pairs.begin(); it != pairs.end(); it++ ){
int color = gradient.current(it->x);
work.putPixel(it->x, it->y, color);
}
// counter.draw(200, 100);
/* we might not have to draw the whole info box again if no new
* messages appeared.
*/
if (drawInfo){
infoBackground.Blit(infoWork);
/* cheesy hack to change the font size. the font
* should store the size and change it on its own
*/
Font::getFont(Global::DEFAULT_FONT, 13, 13);
infobox.draw(0, 0, infoWork, infoFont);
Font::getFont(Global::DEFAULT_FONT, 24, 24);
infoWork.BlitAreaToScreen(infobox_x, infobox_y);
}
/* work already contains the correct background */
// work.Blit( load_x, load_y, *Bitmap::Screen );
work.BlitAreaToScreen(load_x, load_y);
}
}
#endif
}
static void loadingScreenSimpleX1(LoadingContext & context, const Level::LevelInfo & levelInfo){
class Logic: public Util::Logic {
public:
Logic(LoadingContext & context, int & angle, int speed):
context(context),
speed(speed),
angle(angle){
}
LoadingContext & context;
/* speed of rotation */
const int speed;
int & angle;
double ticks(double system){
return system / 2;
}
bool done(){
return context.done();
}
void run(){
angle += speed * 2;
}
};
class Draw: public Util::Draw {
public:
Draw(int & angle, const int speed):
work(*Util::Parameter<Graphics::Bitmap*>::current(), 0, 0, 40, 40),
original(40, 40),
angle(angle),
speed(speed){
original.BlitFromScreen(0, 0);
color1 = Graphics::makeColor(0, 0, 0);
color2 = Graphics::makeColor(0x00, 0x99, 0xff);
color3 = Graphics::makeColor(0xff, 0x22, 0x33);
color4 = Graphics::makeColor(0x44, 0x77, 0x33);
colors[0] = color1;
colors[1] = color2;
colors[2] = color3;
colors[3] = color4;
Graphics::Bitmap::transBlender(0, 0, 0, 64);
}
Graphics::Bitmap work;
Graphics::Bitmap original;
int & angle;
const int speed;
Graphics::Color color1;
Graphics::Color color2;
Graphics::Color color3;
Graphics::Color color4;
/* the length of this array is the number of circles to show */
Graphics::Color colors[4];
~Draw(){
Graphics::resetDisplay();
}
void draw(){
int max = sizeof(colors) / sizeof(int);
double middleX = work.getWidth() / 2;
double middleY = work.getHeight() / 2;
original.Blit(work);
for (int i = 0; i < max; i++){
double x = cos(Util::radians(angle + 360 / max * i)) * 15;
double y = sin(Util::radians(angle + 360 / max * i)) * 15;
/* ghost circle */
work.translucent().circleFill(middleX + x, middleY + y, 2, colors[i]);
x = cos(Util::radians(angle + speed + 360 / max * i)) * 15;
y = sin(Util::radians(angle + speed + 360 / max * i)) * 15;
/* real circle */
work.circleFill(middleX + x, middleY + y, 2, colors[i]);
}
work.BlitAreaToScreen(0, 0);
}
};
int angle = 0;
int speed = 7;
Logic logic(context, angle, speed);
Draw draw(angle, speed);
Util::standardLoop(logic, draw);
#if 0
while (! context.done()){
bool draw = false;
if (Global::speed_counter > 0){
double think = Global::speed_counter;
Global::speed_counter = 0;
draw = true;
while (think > 0){
angle += speed;
think -= 1;
}
} else {
Util::rest(1);
}
if (draw){
int max = sizeof(colors) / sizeof(int);
double middleX = work.getWidth() / 2;
double middleY = work.getHeight() / 2;
original.Blit(work);
for (int i = 0; i < max; i++){
double x = cos(Util::radians(angle + 360 / max * i)) * 15;
double y = sin(Util::radians(angle + 360 / max * i)) * 15;
/* ghost circle */
work.translucent().circleFill(middleX + x, middleY + y, 2, colors[i]);
x = cos(Util::radians(angle + speed + 360 / max * i)) * 15;
y = sin(Util::radians(angle + speed + 360 / max * i)) * 15;
/* real circle */
work.circleFill(middleX + x, middleY + y, 2, colors[i]);
}
work.BlitAreaToScreen(0, 0);
}
}
#endif
}
LoadingContext::LoadingContext():
finished(false){
Util::Thread::initializeLock(&lock);
}
LoadingContext::~LoadingContext(){
}
void LoadingContext::doLoad(){
this->load();
Util::Thread::acquireLock(&lock);
finished = true;
Util::Thread::releaseLock(&lock);
}
bool LoadingContext::done(){
bool ok = false;
Util::Thread::acquireLock(&lock);
ok = this->finished;
Util::Thread::releaseLock(&lock);
return ok;
}
void * LoadingContext::load_it(void * arg){
LoadingContext * context = (LoadingContext*) arg;
context->doLoad();
return NULL;
}
static void showLoadMessage(){
int screenX = 80;
int screenY = 50;
Graphics::Bitmap work(110, 50);
work.BlitFromScreen(screenX, screenY);
Graphics::Bitmap top(110, 50);
top.fill(Graphics::makeColor(0, 0, 0));
Font::getDefaultFont(25, 25).printf(10, 5, Graphics::makeColor(192, 192, 192), top, "Loading", 0);
Graphics::Bitmap::transBlender(0, 0, 0, 200);
top.translucent().draw(0, 0, work);
work.BlitAreaToScreen(screenX, screenY);
}
void loadScreen(LoadingContext & context, const Level::LevelInfo & info, Kind kind){
Util::Thread::Id loadingThread;
bool created = Util::Thread::createThread(&loadingThread, NULL, (Util::Thread::ThreadFunction) LoadingContext::load_it, &context);
if (!created){
Global::debug(0) << "Could not create loading thread. Loading will occur in the main thread" << endl;
showLoadMessage();
LoadingContext::load_it(&context);
// throw LoadException(__FILE__, __LINE__, "Could not create loader thread");
} else {
switch (kind){
case Default: loadingScreen1(context, info); break;
case SimpleCircle: loadingScreenSimpleX1(context, info); break;
default: loadingScreen1(context, info); break;
}
Util::Thread::joinThread(loadingThread);
}
}
}
diff --git a/util/sdl/bitmap.cpp b/util/sdl/bitmap.cpp
index 2f48edeb..c60a5711 100644
--- a/util/sdl/bitmap.cpp
+++ b/util/sdl/bitmap.cpp
@@ -1,1884 +1,1879 @@
#include "../bitmap.h"
#include "../lit_bitmap.h"
#include "../trans-bitmap.h"
#include "../funcs.h"
#include "../../util/debug.h"
#include "../system.h"
#include "../init.h"
#include "sprig/sprig.h"
#include "stretch/SDL_stretch.h"
#include <SDL.h>
#include "image/SDL_image.h"
#include <math.h>
#include "exceptions/exception.h"
#include <string>
#include <sstream>
namespace Graphics{
static const int WINDOWED = 0;
static const int FULLSCREEN = 1;
/* bits per pixel */
static int SCREEN_DEPTH = 16;
static SDL_Surface * screen;
static SDL_PixelFormat format565;
typedef unsigned int (*blender)(unsigned int color1, unsigned int color2, unsigned int alpha);
/* taken from allegro 4.2: src/colblend.c, _blender_trans16 */
/* this function performs a psuedo-SIMD operation on the pixel
* components in RGB 5-6-5 format. To get this to work for some
* other format probably all that needs to happen is to change
* the 0x7E0F81F constant to something else. 5-5-5:
* binary: 0011 1110 000 0111 1100 0001 1111
* hex: 0x174076037
*/
static inline unsigned int transBlender(unsigned int x, unsigned int y, unsigned int n){
unsigned long result;
if (n)
n = (n + 1) / 8;
/* hex: 0x7E0F81F
* binary: 0111 1110 0000 1111 1000 0001 1111
*/
x = ((x & 0xFFFF) | (x << 16)) & 0x7E0F81F;
y = ((y & 0xFFFF) | (y << 16)) & 0x7E0F81F;
result = ((x - y) * n / 32 + y) & 0x7E0F81F;
return ((result & 0xFFFF) | (result >> 16));
}
static inline unsigned int multiplyBlender(unsigned int x, unsigned int y, unsigned int n){
Uint8 redX = 0;
Uint8 greenX = 0;
Uint8 blueX = 0;
SDL_GetRGB(x, &format565, &redX, &greenX, &blueX);
Uint8 redY = 0;
Uint8 greenY = 0;
Uint8 blueY = 0;
SDL_GetRGB(y, &format565, &redY, &greenY, &blueY);
int r = redX * redY / 256;
int g = greenX * greenY / 256;
int b = blueX * blueY / 256;
return transBlender(makeColor(r, g, b), y, n);
}
static inline unsigned int addBlender(unsigned int x, unsigned int y, unsigned int n){
Uint8 redX = 0;
Uint8 greenX = 0;
Uint8 blueX = 0;
SDL_GetRGB(x, &format565, &redX, &greenX, &blueX);
Uint8 redY = 0;
Uint8 greenY = 0;
Uint8 blueY = 0;
SDL_GetRGB(y, &format565, &redY, &greenY, &blueY);
int r = redY + redX * n / 256;
int g = greenY + greenX * n / 256;
int b = blueY + blueX * n / 256;
r = Util::min(r, 255);
g = Util::min(g, 255);
b = Util::min(b, 255);
return makeColor(r, g, b);
}
static inline int iabs(int x){
return x < 0 ? -x : x;
}
static inline unsigned int differenceBlender(unsigned int x, unsigned int y, unsigned int n){
Uint8 redX = 0;
Uint8 greenX = 0;
Uint8 blueX = 0;
SDL_GetRGB(x, &format565, &redX, &greenX, &blueX);
Uint8 redY = 0;
Uint8 greenY = 0;
Uint8 blueY = 0;
SDL_GetRGB(y, &format565, &redY, &greenY, &blueY);
// int r = iabs(redY - redX);
// int g = iabs(greenY - greenX);
// int b = iabs(blueY - blueX);
int r = redY - redX;
int g = greenY - greenX;
int b = blueY - blueX;
if (r < 0){
r = 0;
}
if (g < 0){
g = 0;
}
if (b < 0){
b = 0;
}
return transBlender(makeColor(r, g, b), y, n);
}
static inline unsigned int burnBlender(unsigned int x, unsigned int y, unsigned int n){
Uint8 redX = 0;
Uint8 greenX = 0;
Uint8 blueX = 0;
SDL_GetRGB(x, &format565, &redX, &greenX, &blueX);
Uint8 redY = 0;
Uint8 greenY = 0;
Uint8 blueY = 0;
SDL_GetRGB(y, &format565, &redY, &greenY, &blueY);
int r = redX - redY;
int g = greenX - greenY;
int b = blueX - blueY;
if (r < 0){
r = 0;
}
if (g < 0){
g = 0;
}
if (b < 0){
g = 0;
}
return transBlender(makeColor(r, g, b), y, n);
}
static inline unsigned int noBlender(unsigned int a, unsigned int b, unsigned int c){
return a;
}
struct BlendingData{
BlendingData():
red(0), green(0), blue(0), alpha(0), currentBlender(noBlender){}
int red, green, blue, alpha;
blender currentBlender;
};
static BlendingData globalBlend;
static int drawingMode = Bitmap::MODE_SOLID;
static int drawingAlpha(){
if (drawingMode == Bitmap::MODE_SOLID){
return 255;
}
if (drawingMode == Bitmap::MODE_TRANS){
return globalBlend.alpha;
}
return 255;
}
static void paintown_applyTrans16(SDL_Surface * dst, const int color);
static void paintown_replace16(SDL_Surface * dst, const int original, const int replace);
static void paintown_draw_sprite_ex16(SDL_Surface * dst, SDL_Surface * src, int dx, int dy, int mode, int flip, Bitmap::Filter * filter);
static void paintown_draw_sprite_filter_ex16(SDL_Surface * dst, SDL_Surface * src, int x, int y, Bitmap::Filter * filter);
static void paintown_light16(SDL_Surface * dst, const int x, const int y, int width, int height, const int start_y, const int focus_alpha, const int edge_alpha, const int focus_color, const int edge_color);
int MaskColor(){
static int mask = makeColor(255, 0, 255);
return mask;
}
static SDL_Surface * optimizedSurface(SDL_Surface * in){
/* SDL_DisplayFormat will return 0 if a graphics context is not set,
* like if a test is running instead of the real game.
*/
// SDL_Surface * out = SDL_DisplayFormat(in);
SDL_Surface * out = SDL_ConvertSurface(in, &format565, SDL_SWSURFACE);
if (out == NULL){
// out = SDL_CreateRGBSurface(SDL_SWSURFACE, in->w, in->h, in->format->BitsPerPixel, 0, 0, 0, 0);
out = SDL_CreateRGBSurface(SDL_SWSURFACE, in->w, in->h, SCREEN_DEPTH, format565.Rmask, format565.Gmask, format565.Bmask, format565.Amask);
if (out == NULL){
std::ostringstream out;
out << "Could not create RGB surface of size " << in->w << ", " << in->h << ". Memory usage: " << System::memoryUsage();
throw BitmapException(__FILE__, __LINE__, out.str());
}
SDL_Rect source;
SDL_Rect destination;
source.w = in->w;
source.h = in->h;
source.x = 0;
source.y = 0;
destination.w = in->w;
destination.h = in->h;
destination.x = 0;
destination.y = 0;
SDL_BlitSurface(in, &source, out, &destination);
}
return out;
}
static Bitmap * Scaler = NULL;
static Bitmap * Buffer = NULL;
void BitmapData::setSurface(SDL_Surface * surface){
this->surface = surface;
clip_left = 0;
clip_top = 0;
if (surface){
clip_right = surface->w;
clip_bottom = surface->h;
} else {
clip_right = 0;
clip_bottom = 0;
}
}
Bitmap::Bitmap():
own(NULL),
mustResize(false),
bit8MaskColor(0){
/* TODO */
}
Bitmap::Bitmap(const char * data, int length):
own(NULL),
mustResize(false),
bit8MaskColor(0){
SDL_RWops * ops = SDL_RWFromConstMem(data, length);
SDL_Surface * loaded = IMG_Load_RW(ops, 1);
if (loaded){
getData().setSurface(optimizedSurface(loaded));
SDL_FreeSurface(loaded);
} else {
std::ostringstream out;
out << "Could not load surface from memory " << (void*) data << " length " << length;
throw BitmapException(__FILE__, __LINE__, out.str());
}
own = new int;
*own = 1;
}
Bitmap::Bitmap(SDL_Surface * who, bool deep_copy):
own(NULL),
mustResize(false),
bit8MaskColor(0){
if (deep_copy){
SDL_Surface * surface = SDL_CreateRGBSurface(SDL_SWSURFACE, who->w, who->h, SCREEN_DEPTH, format565.Rmask, format565.Gmask, format565.Bmask, format565.Amask);
SDL_Rect source;
SDL_Rect destination;
source.w = surface->w;
source.h = surface->h;
source.x = 0;
source.y = 0;
destination.w = surface->w;
destination.h = surface->h;
destination.x = 0;
destination.y = 0;
SDL_BlitSurface(who, &source, surface, &destination);
getData().setSurface(surface);
own = new int;
*own = 1;
} else {
getData().setSurface(who);
}
}
Bitmap::Bitmap(int w, int h):
mustResize(false),
bit8MaskColor(0){
SDL_Surface * surface = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, SCREEN_DEPTH, format565.Rmask, format565.Gmask, format565.Bmask, format565.Amask);
if (surface == NULL){
std::ostringstream out;
out << "Could not create surface with dimensions " << w << ", " << h;
throw BitmapException(__FILE__, __LINE__, out.str());
}
getData().setSurface(surface);
own = new int;
*own = 1;
}
Bitmap::Bitmap( const char * load_file ):
own(NULL),
mustResize(false),
bit8MaskColor(0){
internalLoadFile(load_file);
}
Bitmap::Bitmap( const std::string & load_file ):
own(NULL),
mustResize(false){
internalLoadFile(load_file.c_str());
}
Bitmap::Bitmap( const char * load_file, int sx, int sy ):
own(NULL),
mustResize(false),
bit8MaskColor(0){
Bitmap temp(load_file);
SDL_Surface * surface = SDL_CreateRGBSurface(SDL_SWSURFACE, sx, sy, SCREEN_DEPTH, format565.Rmask, format565.Gmask, format565.Bmask, format565.Amask);
getData().setSurface(surface);
own = new int;
*own = 1;
temp.Stretch(*this);
}
/* unused */
Bitmap::Bitmap( const char * load_file, int sx, int sy, double accuracy ):
own(NULL),
mustResize(false),
bit8MaskColor(0){
throw BitmapException(__FILE__, __LINE__, "Unimplemented constructor");
}
Bitmap::Bitmap( const Bitmap & copy, bool deep_copy):
own(NULL),
mustResize(false),
bit8MaskColor(copy.bit8MaskColor){
if (deep_copy){
SDL_Surface * who = copy.getData().getSurface();
SDL_Surface * surface = SDL_CreateRGBSurface(SDL_SWSURFACE, who->w, who->h, SCREEN_DEPTH, format565.Rmask, format565.Gmask, format565.Bmask, format565.Amask);
SDL_Rect source;
SDL_Rect destination;
source.w = surface->w;
source.h = surface->h;
source.x = 0;
source.y = 0;
destination.w = surface->w;
destination.h = surface->h;
destination.x = 0;
destination.y = 0;
SDL_BlitSurface(who, &source, surface, &destination);
getData().setSurface(surface);
own = new int;
*own = 1;
} else {
getData().setSurface(copy.getData().getSurface());
own = copy.own;
if (own){
*own += 1;
}
}
}
Bitmap::Bitmap( const Bitmap & copy, int sx, int sy ):
own(NULL),
mustResize(false),
bit8MaskColor(copy.bit8MaskColor){
/* TODO */
}
Bitmap::Bitmap( const Bitmap & copy, int sx, int sy, double accuracy ):
own(NULL),
mustResize(false),
bit8MaskColor(copy.bit8MaskColor){
/* TODO */
}
static inline Uint8* computeOffset(SDL_Surface * surface, int x, int y){
int bpp = surface->format->BytesPerPixel;
return ((Uint8*)surface->pixels) + y * surface->pitch + x * bpp;
}
Bitmap::Bitmap( const Bitmap & copy, int x, int y, int width, int height ):
own(NULL),
mustResize(false),
bit8MaskColor(copy.bit8MaskColor){
path = copy.getPath();
SDL_Surface * his = copy.getData().getSurface();
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;
SDL_Surface * sub = SDL_CreateRGBSurfaceFrom(computeOffset(his, x, y), width, height, SCREEN_DEPTH, his->pitch, format565.Rmask, format565.Gmask, format565.Bmask, format565.Amask);
getData().setSurface(sub);
own = new int;
*own = 1;
}
void Bitmap::internalLoadFile(const char * path){
this->path = path;
SDL_Surface * loaded = IMG_Load(path);
if (loaded){
getData().setSurface(optimizedSurface(loaded));
SDL_FreeSurface(loaded);
} else {
std::ostringstream out;
out << "Could not load file '" << path << "'";
throw BitmapException(__FILE__, __LINE__, out.str());
}
own = new int;
*own = 1;
}
int Bitmap::getWidth() const {
if (getData().getSurface() != NULL){
return getData().getSurface()->w;
}
return 0;
}
int Bitmap::getHeight() const {
if (getData().getSurface() != NULL){
return getData().getSurface()->h;
}
return 0;
}
int getRed(int c){
Uint8 red = 0;
Uint8 green = 0;
Uint8 blue = 0;
SDL_GetRGB(c, &format565, &red, &green, &blue);
return red;
}
int getBlue(int c){
Uint8 red = 0;
Uint8 green = 0;
Uint8 blue = 0;
SDL_GetRGB(c, &format565, &red, &green, &blue);
return blue;
}
int getGreen(int c){
Uint8 red = 0;
Uint8 green = 0;
Uint8 blue = 0;
SDL_GetRGB(c, &format565, &red, &green, &blue);
return green;
}
int makeColor(int red, int blue, int green){
return SDL_MapRGB(&format565, red, blue, green);
}
void initializeExtraStuff(){
/* this is as good a place as any to initialize our format */
format565.palette = 0;
format565.BitsPerPixel = 16;
format565.BytesPerPixel = 2;
format565.Rloss = 3;
format565.Gloss = 2;
format565.Bloss = 3;
format565.Aloss = 0;
format565.Rshift = 11;
format565.Gshift = 5;
format565.Bshift = 0;
format565.Ashift = 0;
format565.Rmask = 63488;
format565.Gmask = 2016;
format565.Bmask = 31;
format565.Amask = 0;
#ifndef PS3
format565.colorkey = 0;
format565.alpha = 255;
#endif
}
int setGraphicsMode(int mode, int width, int height){
initializeExtraStuff();
switch (mode){
case WINDOWED : {
// screen = SDL_SetVideoMode(width, height, SCREEN_DEPTH, SDL_HWSURFACE | SDL_DOUBLEBUF | SDL_RESIZABLE);
screen = SDL_SetVideoMode(width, height, SCREEN_DEPTH, SDL_SWSURFACE | SDL_RESIZABLE);
SDL_ShowCursor(0);
// screen = SDL_SetVideoMode(width, height, SCREEN_DEPTH, SDL_SWSURFACE | SDL_DOUBLEBUF);
if (!screen){
return 1;
}
break;
}
case FULLSCREEN : {
screen = SDL_SetVideoMode(width, height, SCREEN_DEPTH, SDL_HWSURFACE | SDL_DOUBLEBUF | SDL_FULLSCREEN);
SDL_ShowCursor(0);
// screen = SDL_SetVideoMode(width, height, SCREEN_DEPTH, SDL_SWSURFACE | SDL_DOUBLEBUF);
if (!screen){
return 1;
}
break;
}
}
Global::debug(1) << "SDL Screen format palette: " << screen->format->palette <<
" bits per pixel: " << (int) screen->format->BitsPerPixel <<
" bytes per pixel: " << (int) screen->format->BytesPerPixel <<
" rloss: " << (int) screen->format->Rloss <<
" gloss: " << (int) screen->format->Gloss <<
" bloss: " << (int) screen->format->Bloss <<
" aloss: " << (int) screen->format->Aloss <<
" rshift: " << (int) screen->format->Rshift <<
" gshift: " << (int) screen->format->Gshift <<
" bshift: " << (int) screen->format->Bshift <<
" ashift: " << (int) screen->format->Ashift <<
" rmask: " << (int) screen->format->Rmask <<
" gmask: " << (int) screen->format->Gmask <<
" bmask: " << (int) screen->format->Bmask <<
" amask: " << (int) screen->format->Amask <<
#ifndef PS3
" colorkey: " << (int) screen->format->colorkey <<
" alpha: " << (int) screen->format->alpha << std::endl;
#else
std::endl;
#endif
if (SCALE_X == 0){
SCALE_X = width;
}
SCALE_X = width;
if (SCALE_Y == 0){
SCALE_Y = height;
}
SCALE_Y = height;
/* does this need to be here? I think configuration will set SCALE_ */
SCALE_X = 640;
SCALE_Y = 480;
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);
Scaler = new Bitmap(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);
}
*/
}
for (std::vector<Bitmap*>::iterator it = needResize.begin(); it != needResize.end(); it++){
Bitmap * who = *it;
who->resize(width, height);
}
return 0;
}
void Bitmap::shutdown(){
delete Screen;
Screen = NULL;
delete Scaler;
Scaler = NULL;
delete Buffer;
Buffer = NULL;
}
void Bitmap::addBlender( int r, int g, int b, int a ){
globalBlend.red = r;
globalBlend.green = g;
globalBlend.blue = b;
globalBlend.alpha = a;
globalBlend.currentBlender = Graphics::addBlender;
}
void Bitmap::multiplyBlender( int r, int g, int b, int a ){
globalBlend.red = r;
globalBlend.green = g;
globalBlend.blue = b;
globalBlend.alpha = a;
globalBlend.currentBlender = Graphics::multiplyBlender;
}
void Bitmap::differenceBlender( int r, int g, int b, int a ){
globalBlend.red = r;
globalBlend.green = g;
globalBlend.blue = b;
globalBlend.alpha = a;
globalBlend.currentBlender = Graphics::differenceBlender;
}
void Bitmap::burnBlender(int r, int g, int b, int a){
globalBlend.red = r;
globalBlend.green = g;
globalBlend.blue = b;
globalBlend.alpha = a;
globalBlend.currentBlender = Graphics::burnBlender;
}
Bitmap & Bitmap::operator=(const Bitmap & copy){
releaseInternalBitmap();
path = copy.getPath();
getData().setSurface(copy.getData().getSurface());
// own = false;
own = copy.own;
if (own)
*own += 1;
return *this;
}
int setGfxModeText(){
/* TODO */
return 0;
}
int setGfxModeFullscreen(int x, int y){
return setGraphicsMode(FULLSCREEN, x, y);
}
int setGfxModeWindowed( int x, int y ){
return setGraphicsMode(WINDOWED, x, y);
}
void Bitmap::drawingMode(int type){
Graphics::drawingMode = type;
}
void Bitmap::transBlender( int r, int g, int b, int a ){
globalBlend.red = r;
globalBlend.green = g;
globalBlend.blue = b;
globalBlend.alpha = a;
globalBlend.currentBlender = Graphics::transBlender;
}
void Bitmap::setClipRect( int x1, int y1, int x2, int y2 ) const {
SDL_Rect area;
area.x = x1;
area.y = y1;
area.w = x2 - x1;
area.h = y2 - y1;
SDL_SetClipRect(getData().getSurface(), &area);
SDL_GetClipRect(getData().getSurface(), &area);
getData().setClip(area.x, area.y, area.x + area.w, area.y + area.h);
}
void Bitmap::getClipRect(int & x1, int & y1, int & x2, int & y2) const {
x1 = getData().clip_left;
y1 = getData().clip_top;
x2 = getData().clip_right;
y2 = getData().clip_bottom;
}
void Bitmap::destroyPrivateData(){
SDL_FreeSurface(getData().getSurface());
}
static void doPutPixel(SDL_Surface * surface, int x, int y, int pixel, bool translucent){
if (SDL_MUSTLOCK(surface)){
SDL_LockSurface(surface);
}
int bpp = surface->format->BytesPerPixel;
/* Here p is the address to the pixel we want to set */
Uint8 *p = computeOffset(surface, x, y);
switch(bpp) {
case 1:
*p = pixel;
break;
case 2:
if (translucent){
*(Uint16 *)p = globalBlend.currentBlender(pixel, *(Uint16*)p, globalBlend.alpha);
} else {
*(Uint16 *)p = pixel;
}
break;
case 3:
if(SDL_BYTEORDER == SDL_BIG_ENDIAN) {
p[0] = (pixel >> 16) & 0xff;
p[1] = (pixel >> 8) & 0xff;
p[2] = pixel & 0xff;
} else {
p[0] = pixel & 0xff;
p[1] = (pixel >> 8) & 0xff;
p[2] = (pixel >> 16) & 0xff;
}
break;
case 4:
*(Uint32 *)p = pixel;
break;
}
if (SDL_MUSTLOCK(surface)){
SDL_UnlockSurface(surface);
}
}
void Bitmap::putPixel(int x, int y, int pixel) const {
/* clip it */
if (getData().isClipped(x, y)){
return;
}
SDL_Surface * surface = getData().getSurface();
doPutPixel(surface, x, y, pixel, false);
}
void Bitmap::putPixelNormal(int x, int y, int col) const {
putPixel(x, y, col);
}
void TranslucentBitmap::putPixelNormal(int x, int y, int color) const {
if (getData().isClipped(x, y)){
return;
}
SDL_Surface * surface = getData().getSurface();
doPutPixel(surface, x, y, color, true);
}
bool Bitmap::getError(){
/* TODO */
return false;
}
void Bitmap::rectangle( int x1, int y1, int x2, int y2, int color ) const {
SPG_Rect(getData().getSurface(), x1, y1, x2, y2, color);
}
void TranslucentBitmap::rectangle( int x1, int y1, int x2, int y2, int color ) const {
int alpha = globalBlend.alpha;
SPG_RectBlend(getData().getSurface(), x1, y1, x2, y2, color, alpha);
}
void Bitmap::rectangleFill( int x1, int y1, int x2, int y2, int color ) const {
SPG_RectFilled(getData().getSurface(), x1, y1, x2, y2, color);
}
void TranslucentBitmap::rectangleFill(int x1, int y1, int x2, int y2, int color) const {
int alpha = globalBlend.alpha;
SPG_RectFilledBlend(getData().getSurface(), x1, y1, x2, y2, color, alpha);
}
void Bitmap::circleFill(int x, int y, int radius, int color) const {
if (Graphics::drawingMode == MODE_SOLID){
SPG_CircleFilled(getData().getSurface(), x, y, radius, color);
} else if (Graphics::drawingMode == MODE_TRANS){
int alpha = globalBlend.alpha;
SPG_CircleFilledBlend(getData().getSurface(), x, y, radius, color, alpha);
}
}
void TranslucentBitmap::circleFill(int x, int y, int radius, int color) const {
int alpha = globalBlend.alpha;
SPG_CircleFilledBlend(getData().getSurface(), x, y, radius, color, alpha);
}
void Bitmap::circle(int x, int y, int radius, int color) const {
// Uint8 red, green, blue;
// SDL_GetRGB(color, getData().getSurface()->format, &red, &green, &blue);
// int alpha = 255;
if (Graphics::drawingMode == MODE_SOLID){
SPG_Circle(getData().getSurface(), x, y, radius, color);
} else if (Graphics::drawingMode == MODE_TRANS){
int alpha = globalBlend.alpha;
SPG_CircleBlend(getData().getSurface(), x, y, radius, color, alpha);
}
// circleRGBA(getData().getSurface(), x, y, radius, red, green, blue, alpha);
}
void Bitmap::line( const int x1, const int y1, const int x2, const int y2, const int color ) const {
if (Graphics::drawingMode == MODE_SOLID){
SPG_Line(getData().getSurface(), x1, y1, x2, y2, color);
} else if (Graphics::drawingMode == MODE_TRANS){
int alpha = globalBlend.alpha;
SPG_LineBlend(getData().getSurface(), x1, y1, x2, y2, color, alpha);
}
}
void Bitmap::draw(const int x, const int y, const Bitmap & where) const {
if (getData().getSurface() != NULL){
paintown_draw_sprite_ex16(where.getData().getSurface(), getData().getSurface(), x, y, SPRITE_NORMAL, SPRITE_NO_FLIP, NULL);
/*
SDL_SetColorKey(getData().getSurface(), SDL_SRCCOLORKEY, makeColor(255, 0, 255));
Blit(x, y, where);
*/
}
}
void Bitmap::drawHFlip(const int x, const int y, const Bitmap & where) const {
paintown_draw_sprite_ex16( where.getData().getSurface(), getData().getSurface(), x, y, SPRITE_NORMAL, SPRITE_H_FLIP, NULL);
}
void Bitmap::drawHFlip(const int x, const int y, Filter * filter, const Bitmap & where) const {
paintown_draw_sprite_ex16( where.getData().getSurface(), getData().getSurface(), x, y, SPRITE_NORMAL, SPRITE_H_FLIP, filter);
}
void Bitmap::drawVFlip( const int x, const int y, const Bitmap & where ) const {
paintown_draw_sprite_ex16(where.getData().getSurface(), getData().getSurface(), 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().getSurface(), getData().getSurface(), 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().getSurface(), getData().getSurface(), 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().getSurface(), getData().getSurface(), x, y, SPRITE_NORMAL, SPRITE_V_FLIP | SPRITE_H_FLIP, filter);
}
void TranslucentBitmap::draw(const int x, const int y, const Bitmap & where) const {
paintown_draw_sprite_ex16(where.getData().getSurface(), getData().getSurface(), x, y, SPRITE_TRANS, SPRITE_NO_FLIP, NULL);
}
void TranslucentBitmap::draw( const int x, const int y, Filter * filter, const Bitmap & where ) const {
paintown_draw_sprite_ex16(where.getData().getSurface(), getData().getSurface(), 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().getSurface(), getData().getSurface(), 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().getSurface(), getData().getSurface(), 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().getSurface(), getData().getSurface(), 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().getSurface(), getData().getSurface(), 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().getSurface(), getData().getSurface(), 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().getSurface(), getData().getSurface(), x, y, SPRITE_TRANS, SPRITE_V_FLIP | SPRITE_H_FLIP, filter);
}
void Bitmap::drawStretched( const int x, const int y, const int new_width, const int new_height, const Bitmap & who ) const {
if (getData().getSurface() != NULL){
SDL_SetColorKey(getData().getSurface(), SDL_SRCCOLORKEY, makeColor(255, 0, 255));
SDL_Surface * src = getData().getSurface();
SDL_Surface * dst = who.getData().getSurface();
int myWidth = src->w;
int myHeight = src->h;
int hisWidth = new_width;
int hisHeight = new_height;
int useX = x;
int useY = y;
int myX = 0;
int myY = 0;
float xscale = (float) hisWidth / (float) myWidth;
float yscale = (float) hisHeight / (float) myHeight;
/* sprig wont do the clipping right, if you start drawing from a negative offset
* sprig will do nothing.
*/
if (useX < 0){
useX = 0;
myX = -x / xscale;
}
if (useY < 0){
useY = 0;
myY = -y / yscale;
}
SPG_TransformX(src, dst, 0, xscale, yscale, myX, myY, useX, useY, SPG_TCOLORKEY);
}
}
static void doBlit(SDL_Surface * mine, const int mx, const int my, const int width, const int height, const int wx, const int wy, const Bitmap & where ){
SDL_Rect source;
SDL_Rect destination;
source.w = width;
source.h = height;
source.x = mx;
source.y = my;
destination.w = width;
destination.h = height;
destination.x = wx;
destination.y = wy;
SDL_BlitSurface(mine, &source, where.getData().getSurface(), &destination);
}
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 {
SDL_SetColorKey(getData().getSurface(), 0, MaskColor());
doBlit(getData().getSurface(), mx, my, width, height, wx, wy, where);
/* FIXME: this is a hack, maybe put a call here for the other bitmap to update stuff
* like where->Blitted()
*/
if (&where == Screen){
SDL_Flip(Screen->getData().getSurface());
}
}
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 {
SDL_SetColorKey(getData().getSurface(), SDL_SRCCOLORKEY, MaskColor());
doBlit(getData().getSurface(),mx, my, width, height, wx, wy, where);
/* FIXME: this is a hack, maybe put a call here for the other bitmap to update stuff
* like where->Blitted()
*/
if (&where == Screen){
SDL_Flip(Screen->getData().getSurface());
}
}
void Bitmap::BlitToScreen(const int upper_left_x, const int upper_left_y) const {
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 );
}
/*
if ( Scaler == NULL ){
this->Blit( upper_left_x, upper_left_y, *Screen );
} else {
this->Blit( upper_left_x, upper_left_y, *Buffer );
Buffer->Stretch(*Scaler);
Scaler->Blit(0, 0, 0, 0, *Screen);
}
*/
// SDL_Flip(Screen->getData().getSurface());
// SDL_UpdateRect(Screen->getData().getSurface(), 0, 0, Screen->getWidth(), Screen->getHeight());
}
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 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::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 {
if (destWidth <= 0 || destHeight <= 0 ||
sourceWidth <= 0 || sourceHeight <= 0){
return;
}
Bitmap subSource(*this, sourceX, sourceY, sourceWidth, sourceHeight);
Bitmap subDestination(where, destX, destY, destWidth, destHeight);
SDL_Surface * src = subSource.getData().getSurface();
SDL_Surface * dst = subDestination.getData().getSurface();
if (SDL_MUSTLOCK(src)){
SDL_LockSurface(src);
}
if (SDL_MUSTLOCK(dst)){
SDL_LockSurface(dst);
}
SDL_StretchSurfaceRect(src, NULL, dst, NULL);
if (SDL_MUSTLOCK(src)){
SDL_UnlockSurface(src);
}
if (SDL_MUSTLOCK(dst)){
SDL_UnlockSurface(dst);
}
/*
SDL_Surface * src = getData().getSurface();
SDL_Surface * dst = where.getData().getSurface();
*/
/*
float xscale = (float) destWidth / (float) sourceWidth;
float yscale = (float) destHeight / (float) sourceHeight;
SDL_SetColorKey(src, 0, MaskColor());
SPG_TransformX(src, dst, 0, xscale, yscale, sourceX, sourceY, destX, destY, SPG_NONE);
*/
/*
SDL_Rect source;
SDL_Rect destination;
source.x = sourceX;
source.y = sourceY;
source.w = sourceWidth;
source.h = sourceHeight;
destination.x = destX;
destination.y = destY;
destination.w = destWidth;
destination.h = destHeight;
// SDL_StretchSurfaceRect(getData().getSurface(), &source, where.getData().getSurface(), &destination);
SDL_Surface * src = getData().getSurface();
SDL_Surface * dst = where.getData().getSurface();
if (SDL_MUSTLOCK(src)){
SDL_LockSurface(src);
}
if (SDL_MUSTLOCK(dst)){
SDL_LockSurface(dst);
}
SDL_StretchSurfaceRect(src, &source, dst, &destination);
if (SDL_MUSTLOCK(src)){
SDL_UnlockSurface(src);
}
if (SDL_MUSTLOCK(dst)){
SDL_UnlockSurface(dst);
}
*/
}
void Bitmap::save( const std::string & str ) const {
/* TODO */
}
void Bitmap::triangle( int x1, int y1, int x2, int y2, int x3, int y3, int color ) const {
if (Graphics::drawingMode == MODE_SOLID){
SPG_TrigonFilled(getData().getSurface(), x1, y1, x2, y2, x3, y3, color);
} else if (Graphics::drawingMode == MODE_TRANS){
int alpha = globalBlend.alpha;
SPG_TrigonFilledBlend(getData().getSurface(), x1, y1, x2, y2, x3, y3, color, alpha);
}
}
void Bitmap::ellipse( int x, int y, int rx, int ry, int color ) const {
if (Graphics::drawingMode == MODE_SOLID){
SPG_Ellipse(getData().getSurface(), x, y, rx, ry, color);
} else if (Graphics::drawingMode == MODE_TRANS){
int alpha = globalBlend.alpha;
SPG_EllipseBlend(getData().getSurface(), x, y, rx, ry, color, alpha);
}
}
void TranslucentBitmap::ellipse( int x, int y, int rx, int ry, int color ) const {
int alpha = globalBlend.alpha;
SPG_EllipseBlend(getData().getSurface(), x, y, rx, ry, color, alpha);
}
void Bitmap::ellipseFill( int x, int y, int rx, int ry, int color ) const {
SPG_EllipseFilled(getData().getSurface(), x, y, rx, ry, color);
}
void Bitmap::light(int x, int y, int width, int height, int start_y, int focus_alpha, int edge_alpha, int focus_color, int edge_color) const {
paintown_light16(getData().getSurface(), x, y, width, height, start_y, focus_alpha, edge_alpha, focus_color, edge_color);
}
void Bitmap::applyTrans(const int color) const {
paintown_applyTrans16(getData().getSurface(), color);
}
void Bitmap::floodfill( const int x, const int y, const int color ) const {
SPG_FloodFill(getData().getSurface(), x, y, color);
}
/*
void Bitmap::horizontalLine( const int x1, const int y, const int x2, const int color ) const {
SPG_LineH(getData().getSurface(), x1, y, x2, color);
}
*/
void Bitmap::hLine( const int x1, const int y, const int x2, const int color ) const {
SPG_LineH(getData().getSurface(), x1, y, x2, color);
}
void TranslucentBitmap::hLine( const int x1, const int y, const int x2, const int color ) const {
int alpha = globalBlend.alpha;
SPG_LineHBlend(getData().getSurface(), x1, y, x2, color, alpha);
}
void Bitmap::vLine( const int y1, const int x, const int y2, const int color ) const {
SPG_LineV(getData().getSurface(), x, y1, y2, color);
}
void Bitmap::polygon( const int * verts, const int nverts, const int color ) const {
SPG_Point * points = new SPG_Point[nverts];
for (int i = 0; i < nverts; i++){
points[i].x = verts[i*2];
points[i].y = verts[i*2+1];
}
SPG_PolygonFilled(getData().getSurface(), nverts, points, color);
delete[] points;
}
static const double S_PI = 3.14159265358979323846;
static const double RAD_TO_DEG = 180.0/S_PI;
static const double DEG_TO_RAD = S_PI/180.0;
static double toDegrees(double radians){
return RAD_TO_DEG * radians;
}
/* 0 = right. pi/2 = up. pi = left. 3pi/2 = down */
void Bitmap::arc(const int x, const int y, const double ang1, const double ang2, const int radius, const int color ) const {
SPG_Arc(getData().getSurface(), x, y, radius, toDegrees(ang1 + S_PI/2), toDegrees(ang2 + S_PI/2), color);
}
void Bitmap::fill(int color) const {
SDL_Rect area;
area.x = 0;
area.y = 0;
area.w = getWidth();
area.h = getHeight();
SDL_FillRect(getData().getSurface(), &area, color);
}
/*
void TranslucentBitmap::fill(int color) const {
rectangleFill(0, 0, getWidth(), getHeight(), color);
}
*/
void Bitmap::drawCharacter( const int x, const int y, const int color, const int background, const Bitmap & where ) const {
/* TODO */
}
void Bitmap::drawRotate( const int x, const int y, const int angle, const Bitmap & where ){
SDL_SetColorKey(getData().getSurface(), SDL_SRCCOLORKEY, MaskColor());
SDL_Surface * src = getData().getSurface();
SDL_Surface * dst = where.getData().getSurface();
SPG_TransformX(src, dst, angle, 1, 1, 0, 0, x, y, SPG_TCOLORKEY);
}
void Bitmap::drawPivot( const int centerX, const int centerY, const int x, const int y, const int angle, const Bitmap & where ){
SDL_SetColorKey(getData().getSurface(), SDL_SRCCOLORKEY, MaskColor());
SDL_Surface * src = getData().getSurface();
SDL_Surface * dst = where.getData().getSurface();
SPG_TransformX(src, dst, angle, 1, 1, centerX, centerY, x, y, SPG_TCOLORKEY);
}
void Bitmap::drawPivot( const int centerX, const int centerY, const int x, const int y, const int angle, const double scale, const Bitmap & where ){
SDL_SetColorKey(getData().getSurface(), SDL_SRCCOLORKEY, MaskColor());
SDL_Surface * src = getData().getSurface();
SDL_Surface * dst = where.getData().getSurface();
SPG_TransformX(src, dst, angle, scale, scale, centerX, centerY, x, y, SPG_TCOLORKEY);
}
void Bitmap::replaceColor(int original, int replaced){
paintown_replace16(getData().getSurface(), original, replaced);
}
Bitmap Bitmap::memoryPCX(unsigned char * const data, const int length, const bool mask){
SDL_RWops * ops = SDL_RWFromConstMem(data, length);
SDL_Surface * pcx = IMG_LoadPCX_RW(ops);
SDL_FreeRW(ops);
if (!pcx){
std::ostringstream out;
out << "Could not load PCX file at " << (void*) data << " length " << length;
throw BitmapException(__FILE__, __LINE__, out.str());
}
SDL_Surface * display = optimizedSurface(pcx);
Bitmap out(display, true);
#ifndef PS3
if (pcx->format->BitsPerPixel == 8){
SDL_Color color = pcx->format->palette->colors[pcx->format->colorkey];
int bad = makeColor(color.r, color.g, color.b);
out.set8BitMaskColor(bad);
// int mask = MaskColor();
// out.replaceColor(bad, mask);
}
#endif
SDL_FreeSurface(pcx);
SDL_FreeSurface(display);
// out.floodfill(0, 0, makeColor(255, 0, 255));
return out;
}
int Bitmap::getPixel( const int x, const int y ) const {
return SPG_GetPixel(getData().getSurface(), x, y);
}
void Bitmap::readLine( std::vector< int > & line, int y ){
for (int x = 0; x < getWidth(); x++){
line.push_back(getPixel(x, y));
}
}
void Bitmap::StretchBy2( const Bitmap & where ){
/* TODO */
}
void Bitmap::StretchBy4( const Bitmap & where ){
/* TODO */
}
void Bitmap::draw(const int x, const int y, Filter * filter, const Bitmap & where) const {
// paintown_draw_sprite_filter_ex16(where.getData().getSurface(), getData().getSurface(), x, y, filter);
paintown_draw_sprite_ex16(where.getData().getSurface(), getData().getSurface(), x, y, SPRITE_NORMAL, SPRITE_NO_FLIP, filter);
}
void LitBitmap::draw( const int x, const int y, const Bitmap & where ) const {
paintown_draw_sprite_ex16( where.getData().getSurface(), getData().getSurface(), 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().getSurface(), getData().getSurface(), 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().getSurface(), getData().getSurface(), 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().getSurface(), getData().getSurface(), 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().getSurface(), getData().getSurface(), 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().getSurface(), getData().getSurface(), 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().getSurface(), getData().getSurface(), 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().getSurface(), getData().getSurface(), x, y, SPRITE_LIT, SPRITE_V_FLIP | SPRITE_H_FLIP, filter);
}
/*
#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) MASK_COLOR)
#define PAINTOWN_DLSX_BLEND(b,n) ((*(b))(_blender_col_16, (n), globalBlend.alpha))
#define PAINTOWN_GET_PIXEL(p) *((unsigned short *) (p))
#define PAINTOWN_DTS_BLEND(b,o,n) ((*(b))((n), (o), globalBlend.alpha))
#define PAINTOWN_PUT_PIXEL(p,c) (*((unsigned short *) p) = (c))
#define PAINTOWN_PUT_MEMORY_PIXEL(p,c) (*(p) = (c))
#define PAINTOWN_SET_ALPHA(a) (globalBlend.alpha = (a))
*/
static void paintown_applyTrans16(SDL_Surface * dst, const int color){
int y1 = 0;
int y2 = dst->h;
int x1 = 0;
int x2 = dst->w - 1;
y1 = dst->clip_rect.y;
y2 = dst->clip_rect.y + dst->clip_rect.h;
x1 = dst->clip_rect.x;
x2 = dst->clip_rect.x + dst->clip_rect.w;
int bpp = dst->format->BytesPerPixel;
unsigned int mask = makeColor(255, 0, 255);
for (int y = y1; y < y2; y++) {
Uint8 * sourceLine = computeOffset(dst, x1, y);
for (int x = x2 - 1; x >= x1; sourceLine += bpp, x--) {
unsigned long sourcePixel = *(Uint16*) sourceLine;
if (!(sourcePixel == mask)){
sourcePixel = globalBlend.currentBlender(color, sourcePixel, globalBlend.alpha);
*(Uint16 *)sourceLine = sourcePixel;
}
}
}
}
static void paintown_replace16(SDL_Surface * dst, const int original, const int replace){
int y1 = 0;
int y2 = dst->h;
int x1 = 0;
int x2 = dst->w - 1;
y1 = dst->clip_rect.y;
y2 = dst->clip_rect.y + dst->clip_rect.h;
x1 = dst->clip_rect.x;
x2 = dst->clip_rect.x + dst->clip_rect.w;
int bpp = dst->format->BytesPerPixel;
/* Attempted manual unrolling. Gcc can optimize the naive loop below better
* than this unrolling attempt.
*/
/*
for (int y = y1; y < y2; y += 4){
switch (y2 - y1){
case 1 : {
Uint8 * source1 = computeOffset(dst, x1, y);
for (int x = x2 - 1; x >= x1; source1 += bpp, x--) {
unsigned long sourcePixel = *(Uint16*) source1;
if ((int) sourcePixel == original){
*(Uint16 *)source1 = replace;
}
}
break;
}
case 2 : {
Uint8 * source1 = computeOffset(dst, x1, y);
Uint8 * source2 = computeOffset(dst, x1, y + 1);
for (int x = x2 - 1; x >= x1; source1 += bpp, source2 += bpp, x--) {
unsigned long sourcePixel = *(Uint16*) source1;
unsigned long sourcePixel2 = *(Uint16*) source2;
if ((int) sourcePixel == original){
*(Uint16 *)source1 = replace;
}
if ((int) sourcePixel2 == original){
*(Uint16 *)source2 = replace;
}
}
break;
}
case 3 : {
Uint8 * source1 = computeOffset(dst, x1, y);
Uint8 * source2 = computeOffset(dst, x1, y + 1);
Uint8 * source3 = computeOffset(dst, x1, y + 2);
for (int x = x2 - 1; x >= x1; source1 += bpp, source2 += bpp, source3 += bpp, x--) {
unsigned long sourcePixel = *(Uint16*) source1;
unsigned long sourcePixel2 = *(Uint16*) source2;
unsigned long sourcePixel3 = *(Uint16*) source3;
if ((int) sourcePixel == original){
*(Uint16 *)source1 = replace;
}
if ((int) sourcePixel2 == original){
*(Uint16 *)source2 = replace;
}
if ((int) sourcePixel3 == original){
*(Uint16 *)source3 = replace;
}
}
break;
}
default:
case 4 : {
Uint8 * source1 = computeOffset(dst, x1, y);
Uint8 * source2 = computeOffset(dst, x1, y + 1);
Uint8 * source3 = computeOffset(dst, x1, y + 2);
Uint8 * source4 = computeOffset(dst, x1, y + 3);
for (int x = x2 - 1; x >= x1; source1 += bpp, source2 += bpp, source3 += bpp, source4 += bpp, x--) {
unsigned long sourcePixel = *(Uint16*) source1;
unsigned long sourcePixel2 = *(Uint16*) source2;
unsigned long sourcePixel3 = *(Uint16*) source3;
unsigned long sourcePixel4 = *(Uint16*) source4;
if ((int) sourcePixel == original){
*(Uint16 *)source1 = replace;
}
if ((int) sourcePixel2 == original){
*(Uint16 *)source2 = replace;
}
if ((int) sourcePixel3 == original){
*(Uint16 *)source3 = replace;
}
if ((int) sourcePixel4 == original){
*(Uint16 *)source4 = replace;
}
}
break;
}
}
}
*/
if (SDL_MUSTLOCK(dst)){
SDL_LockSurface(dst);
}
for (int y = y1; y < y2; y++) {
Uint8 * sourceLine = computeOffset(dst, x1, y);
for (int x = x2 - 1; x >= x1; sourceLine += bpp, x--) {
unsigned long sourcePixel = *(Uint16*) sourceLine;
if ((int) sourcePixel == original){
*(Uint16 *)sourceLine = replace;
}
}
}
if (SDL_MUSTLOCK(dst)){
SDL_UnlockSurface(dst);
}
}
static void paintown_draw_sprite_filter_ex16(SDL_Surface * dst, SDL_Surface * src, int dx, int dy, Bitmap::Filter * filter){
int x, y, w, h;
int x_dir = 1, y_dir = 1;
int dxbeg, dybeg;
int sxbeg, sybeg;
if (SDL_MUSTLOCK(dst)){
SDL_LockSurface(dst);
}
if (true /* dst->clip*/ ) {
int tmp;
tmp = dst->clip_rect.x - dx;
sxbeg = ((tmp < 0) ? 0 : tmp);
dxbeg = sxbeg + dx;
tmp = dst->clip_rect.x + dst->clip_rect.w - dx;
w = ((tmp > src->w) ? src->w : tmp) - sxbeg;
if (w <= 0)
return;
tmp = dst->clip_rect.y - dy;
sybeg = ((tmp < 0) ? 0 : tmp);
dybeg = sybeg + dy;
tmp = dst->clip_rect.y + dst->clip_rect.h - dy;
h = ((tmp > src->h) ? src->h : tmp) - sybeg;
if (h <= 0)
return;
}
unsigned int mask = makeColor(255, 0, 255);
int bpp = src->format->BytesPerPixel;
for (y = 0; y < h; y++) {
Uint8 * sourceLine = computeOffset(src, sxbeg, sybeg + y);
Uint8 * destLine = computeOffset(dst, dxbeg, dybeg + y * y_dir);
for (x = w - 1; x >= 0; sourceLine += bpp, destLine += bpp * x_dir, x--) {
unsigned long sourcePixel = *(Uint16*) sourceLine;
if (!(sourcePixel == mask)){
*(Uint16 *)destLine = filter->filter(sourcePixel);
} else {
*(Uint16 *)destLine = mask;
}
}
}
if (SDL_MUSTLOCK(dst)){
SDL_UnlockSurface(dst);
}
}
static void paintown_draw_sprite_ex16(SDL_Surface * dst, SDL_Surface * 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 (SDL_MUSTLOCK(src)){
SDL_LockSurface(src);
}
if (SDL_MUSTLOCK(dst)){
SDL_LockSurface(dst);
}
if ( flip & SPRITE_V_FLIP ){
y_dir = -1;
}
if ( flip & SPRITE_H_FLIP ){
x_dir = -1;
}
if (true /* dst->clip*/ ) {
int tmp;
tmp = dst->clip_rect.x - dx;
sxbeg = ((tmp < 0) ? 0 : tmp);
dxbeg = sxbeg + dx;
tmp = dst->clip_rect.x + dst->clip_rect.w - 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->clip_rect.y - dy;
sybeg = ((tmp < 0) ? 0 : tmp);
dybeg = sybeg + dy;
tmp = dst->clip_rect.y + dst->clip_rect.h - 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 0
if (dst->id & (BMP_ID_VIDEO | BMP_ID_SYSTEM)) {
bmp_select(dst);
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;
}
}
#xendif
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 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_PIXEL(d, c);
}
}
}
bmp_unwrite_line(dst);
}
else {
#endif
{
switch (mode){
case SPRITE_NORMAL : {
unsigned int mask = makeColor(255, 0, 255);
int bpp = src->format->BytesPerPixel;
for (y = 0; y < h; y++) {
Uint8 * sourceLine = computeOffset(src, sxbeg, sybeg + y);
Uint8 * destLine = computeOffset(dst, dxbeg, dybeg + y * y_dir);
for (x = w - 1; x >= 0; sourceLine += bpp, destLine += bpp * x_dir, x--) {
unsigned long sourcePixel = *(Uint16*) sourceLine;
if (!(sourcePixel == mask)){
// unsigned int destPixel = *(Uint16*) destLine;
// sourcePixel = globalBlend.currentBlender(destPixel, sourcePixel, globalBlend.alpha);
if (filter != NULL){
*(Uint16 *)destLine = filter->filter(sourcePixel);
} else {
*(Uint16 *)destLine = sourcePixel;
}
}
}
}
break;
}
case SPRITE_LIT : {
int bpp = src->format->BytesPerPixel;
int litColor = makeColor(globalBlend.red, globalBlend.green, globalBlend.blue);
unsigned int mask = makeColor(255, 0, 255);
for (y = 0; y < h; y++) {
Uint8 * sourceLine = computeOffset(src, sxbeg, sybeg + y);
Uint8 * destLine = computeOffset(dst, dxbeg, dybeg + y * y_dir);
for (x = w - 1; x >= 0; sourceLine += bpp, destLine += bpp * x_dir, x--) {
unsigned long sourcePixel = *(Uint16*) sourceLine;
if (!(sourcePixel == mask)){
// unsigned int destPixel = *(Uint16*) destLine;
if (filter != NULL){
sourcePixel = globalBlend.currentBlender(litColor, filter->filter(sourcePixel), globalBlend.alpha);
*(Uint16 *)destLine = sourcePixel;
} else {
sourcePixel = globalBlend.currentBlender(litColor, sourcePixel, globalBlend.alpha);
*(Uint16 *)destLine = sourcePixel;
}
}
}
}
break;
}
case SPRITE_TRANS : {
int bpp = src->format->BytesPerPixel;
unsigned int mask = makeColor(255, 0, 255);
for (y = 0; y < h; y++) {
Uint8 * sourceLine = computeOffset(src, sxbeg, sybeg + y);
Uint8 * destLine = computeOffset(dst, dxbeg, dybeg + y * y_dir);
for (x = w - 1; x >= 0; sourceLine += bpp, destLine += bpp * x_dir, x--) {
unsigned long sourcePixel = *(Uint16*) sourceLine;
if (!(sourcePixel == mask)){
unsigned int destPixel = *(Uint16*) destLine;
if (filter != NULL){
sourcePixel = globalBlend.currentBlender(filter->filter(sourcePixel), destPixel, globalBlend.alpha);
*(Uint16 *)destLine = sourcePixel;
} else {
sourcePixel = globalBlend.currentBlender(sourcePixel, destPixel, globalBlend.alpha);
*(Uint16 *)destLine = sourcePixel;
}
}
}
}
break;
}
default : { 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
}
if (SDL_MUSTLOCK(src)){
SDL_UnlockSurface(src);
}
if (SDL_MUSTLOCK(dst)){
SDL_UnlockSurface(dst);
}
}
/* 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(SDL_Surface * dst, const int x, const int y, int width, int height, const int start_y, const int focus_alpha, const int edge_alpha, const int focus_color, const int edge_color){
if (width > dst->w){
width = dst->w;
}
if (height > dst->h){
height = dst->h;
}
int dxbeg = x - width;
int x_dir = 1;
unsigned char * alphas = new unsigned char[width];
int * colors = new int[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);
if (SDL_MUSTLOCK(dst)){
SDL_LockSurface(dst);
}
int min_y, max_y, min_x, max_x;
min_y = dst->clip_rect.y;
max_y = dst->clip_rect.y + dst->clip_rect.h - 1;
min_x = dst->clip_rect.x;
max_x = dst->clip_rect.x + dst->clip_rect.w - 1;
int dybeg = y;
/* tan(theta) = y / x */
double xtan = (double) height / (double) width;
int bpp = dst->format->BytesPerPixel;
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;
Uint8* line = computeOffset(dst, dxbeg, dybeg + y);
for (int sx = -top_width; sx <= top_width; line += x_dir * bpp, sx++) {
if (sx + x < min_x || sx + x > max_x){
continue;
}
unsigned long c = *(Uint16*) line;
/* TODO:
* converting to a double and calling fabs is overkill, just
* write an integer abs() function.
*/
int sx_abs = (int) fabs((double) sx);
int alphaUse = alphas[sx_abs];
int color = colors[sx_abs];
c = globalBlend.currentBlender(color, c, alphaUse);
*(Uint16*) line = c;
}
}
delete[] alphas;
delete[] colors;
if (SDL_MUSTLOCK(dst)){
SDL_UnlockSurface(dst);
}
}
-Bitmap getScreenBuffer(){
- return Bitmap(GFX_X, GFX_Y);
}
-void resetDisplay(){
-}
-
-}
+#include "../software-renderer/bitmap.cpp"
diff --git a/util/software-renderer/bitmap.cpp b/util/software-renderer/bitmap.cpp
new file mode 100644
index 00000000..cd03cafc
--- /dev/null
+++ b/util/software-renderer/bitmap.cpp
@@ -0,0 +1,26 @@
+/* generic software implementation of various bitmap operations */
+
+namespace Graphics{
+
+StretchedBitmap::StretchedBitmap(int width, int height, const Bitmap & parent):
+Bitmap(width, height),
+width(width),
+height(height),
+where(parent){
+}
+
+void StretchedBitmap::start(){
+}
+
+void StretchedBitmap::finish(){
+ Stretch(where);
+}
+
+Bitmap getScreenBuffer(){
+ return Bitmap(GFX_X, GFX_Y);
+}
+
+void resetDisplay(){
+}
+
+}
diff --git a/util/stretch-bitmap.h b/util/stretch-bitmap.h
new file mode 100644
index 00000000..1691e4bf
--- /dev/null
+++ b/util/stretch-bitmap.h
@@ -0,0 +1,21 @@
+#ifndef _paintown_stretch_bitmap_h
+#define _paintown_stretch_bitmap_h
+
+#include "bitmap.h"
+
+namespace Graphics{
+
+class StretchedBitmap: public Bitmap {
+public:
+ StretchedBitmap(int width, int height, const Bitmap & where);
+ void finish();
+ void start();
+protected:
+ double width;
+ double height;
+ const Bitmap & where;
+};
+
+}
+
+#endif

File Metadata

Mime Type
text/x-diff
Expires
Thu, Jun 11, 10:57 AM (3 w, 5 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
68584
Default Alt Text
(194 KB)

Event Timeline