Page MenuHomePhabricator (Chris)

No OneTemporary

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

File Metadata

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

Event Timeline