Page MenuHomePhabricator (Chris)

No OneTemporary

Authored By
Unknown
Size
132 KB
Referenced Files
None
Subscribers
None
diff --git a/util/bitmap.h b/util/bitmap.h
index ada2db1b..8c742aed 100644
--- a/util/bitmap.h
+++ b/util/bitmap.h
@@ -1,352 +1,355 @@
#ifndef _paintown_bitmap_h_
#define _paintown_bitmap_h_
#ifdef USE_ALLEGRO
#include "allegro/bitmap.h"
#endif
#ifdef USE_SDL
#include "sdl/bitmap.h"
#endif
#include <string>
#include <vector>
#include <iostream>
class TranslucentBitmap;
class Bitmap{
private:
static Bitmap * Screen;
/* these constructors don't really matter, get rid of them at some point */
Bitmap( const Bitmap & copy, int sx, int sy, double accuracy );
Bitmap( const char * load_file, int sx, int sy, double accuracy );
public:
/* equivalent to a GPU shader */
class Filter{
public:
virtual unsigned int filter(unsigned int pixel) const = 0;
virtual ~Filter(){
}
};
static int SCALE_X;
static int SCALE_Y;
/* default constructor makes 10x10 bitmap */
Bitmap();
Bitmap( int x, int y );
Bitmap( const char * load_file );
Bitmap(const char * data, int length);
Bitmap( const std::string & load_file );
Bitmap( const char * load_file, int sx, int sy );
/* 4/24/2010: remove this at some point */
#ifdef USE_ALLEGRO
explicit Bitmap( BITMAP * who, bool deep_copy = false );
#endif
#ifdef USE_SDL
explicit Bitmap(SDL_Surface * who, bool deep_copy = false );
#endif
Bitmap( const Bitmap & copy, bool deep_copy = false );
Bitmap( const Bitmap & copy, int sx, int sy );
Bitmap( const Bitmap & copy, int x, int y, int width, int height );
virtual ~Bitmap();
virtual TranslucentBitmap translucent() const;
virtual void save( const std::string & str ) const;
Bitmap & operator=( const Bitmap & );
virtual void load( const std::string & str );
int getWidth() const;
int getHeight() const;
/*
inline const int getWidth() const{
return getBitmap()->w;
}
inline const int getHeight() const{
return getBitmap()->h;
}
*/
/*
inline const int getWidth() const{
return my_bitmap->w;
}
inline const int getHeight() const{
return my_bitmap->h;
}
*/
static Bitmap memoryPCX(unsigned char * const data, const int length, const bool mask = true);
void detach();
/* replace all pixels that have value `original' with `replaced' */
void replaceColor(int original, int replaced);
void set8BitMaskColor(int color);
int get8BitMaskColor();
static void transBlender( int r, int g, int b, int a );
static void multiplyBlender( int r, int g, int b, int a );
static void dissolveBlender( int r, int g, int b, int a );
static void addBlender( int r, int g, int b, int a );
static void burnBlender( int r, int g, int b, int a );
static void colorBlender( int r, int g, int b, int a );
static void differenceBlender( int r, int g, int b, int a );
static void dodgeBlender( int r, int g, int b, int a );
static void hueBlender( int r, int g, int b, int a );
static void luminanceBlender( int r, int g, int b, int a );
static void invertBlender( int r, int g, int b, int a );
static void screenBlender( int r, int g, int b, int a );
static int setGraphicsMode( int mode, int width, int height );
/* for testing */
static void setFakeGraphicsMode(int width, int height);
/* clean up any remaining state */
static void shutdown();
static void drawingMode( int type );
void acquire();
void release();
void updateOnResize();
void resize(const int width, const int height);
void debugSelf() const;
/* convert to a grey scale version */
virtual Bitmap greyScale();
virtual void triangle( int x1, int y1, int x2, int y2, int x3, int y3, int color ) const;
/* draws an equilateral triangle centered at (x,y) pointing at `angle'
* where each side has `size' pixels using the color.
*/
virtual void equilateralTriangle(int x, int y, int angle, int size, int color) const;
virtual void ellipse( int x, int y, int rx, int ry, int color ) const;
virtual void ellipseFill( int x, int y, int rx, int ry, int color ) const;
virtual void 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;
virtual void applyTrans(const int color) const;
virtual void border( int min, int max, int color ) const;
virtual void rectangle( int x1, int y1, int x2, int y2, int color ) const;
virtual void rectangleFill( int x1, int y1, int x2, int y2, int color ) const;
virtual void circleFill( int x, int y, int radius, int color ) const;
virtual void circle( int x, int y, int radius, int color ) const;
virtual void line( const int x1, const int y1, const int x2, const int y2, const int color ) const;
virtual void floodfill( const int x, const int y, const int color ) const;
virtual void horizontalLine( const int x1, const int y, const int x2, const int color ) const;
virtual void hLine( const int x1, const int y, const int x2, const int color ) const;
virtual void vLine( const int y1, const int x, const int y2, const int color ) const;
virtual void polygon( const int * verts, const int nverts, const int color ) const;
virtual void arc(const int x, const int y, const double ang1, const double ang2, const int radius, const int color ) const;
virtual void draw(const int x, const int y, const Bitmap & where) const;
virtual void draw(const int x, const int y, Filter * filter, const Bitmap & where) const;
virtual void draw(const int x, const int y, const int startWidth, const int startHeight, const int width, const int height, const Bitmap & where) const;
virtual void draw(const int x, const int y, const int startWidth, const int startHeight, const int width, const int height, Filter * filter, const Bitmap & where) const;
virtual void drawCharacter( const int x, const int y, const int color, const int background, const Bitmap & where ) const;
- /* to draw lit use LitBitmap */
- // virtual void drawLit( const int x, const int y, const int level, const Bitmap & where ) const;
+
+ /* flip horizontally */
virtual void drawHFlip(const int x, const int y, const Bitmap & where) const;
virtual void drawHFlip(const int x, const int y, Filter * filter, const Bitmap & where) const;
virtual void drawHFlip(const int x, const int y, const int startWidth, const int startHeight, const int width, const int height, const Bitmap & where) const;
virtual void drawHFlip(const int x, const int y, const int startWidth, const int startHeight, const int width, const int height, Filter * filter, const Bitmap & where) const;
+ /* flip vertically */
virtual void drawVFlip( const int x, const int y, const Bitmap & where ) const;
virtual void drawVFlip( const int x, const int y, Filter * filter, const Bitmap & where ) const;
+
+ /* flip horizontal and vertical */
virtual void drawHVFlip( const int x, const int y, const Bitmap & where ) const;
virtual void drawHVFlip( const int x, const int y, Filter * filter, const Bitmap & where ) const;
- virtual void drawTrans( const int x, const int y, const Bitmap & where ) const;
- virtual void drawTrans( const int x, const int y, Filter * filter, const Bitmap & where ) const;
- virtual void drawTransHFlip( const int x, const int y, const Bitmap & where ) const;
- virtual void drawTransHFlip( const int x, const int y, Filter * filter, const Bitmap & where ) const;
- virtual void drawTransVFlip( const int x, const int y, const Bitmap & where ) const;
- virtual void drawTransVFlip( const int x, const int y, Filter * filter, const Bitmap & where ) const;
- virtual void drawTransHVFlip( const int x, const int y, const Bitmap & where ) const;
- virtual void drawTransHVFlip( const int x, const int y, Filter * filter, const Bitmap & where ) const;
+ // virtual void drawTrans( const int x, const int y, const Bitmap & where ) const;
+ // virtual void drawTrans( const int x, const int y, Filter * filter, const Bitmap & where ) const;
+ // virtual void drawTransHFlip( const int x, const int y, const Bitmap & where ) const;
+ // virtual void drawTransHFlip( const int x, const int y, Filter * filter, const Bitmap & where ) const;
+ // virtual void drawTransVFlip( const int x, const int y, const Bitmap & where ) const;
+ // virtual void drawTransVFlip( const int x, const int y, Filter * filter, const Bitmap & where ) const;
+ // virtual void drawTransHVFlip( const int x, const int y, const Bitmap & where ) const;
+ // virtual void drawTransHVFlip( const int x, const int y, Filter * filter, const Bitmap & where ) const;
virtual void drawMask( const int x, const int y, const Bitmap & where );
virtual void drawStretched( const int x, const int y, const int new_width, const int new_height, const Bitmap & who );
virtual void drawRotate( const int x, const int y, const int angle, const Bitmap & where );
virtual void drawPivot( const int centerX, const int centerY, const int x, const int y, const int angle, const Bitmap & where );
virtual void drawPivot( const int centerX, const int centerY, const int x, const int y, const int angle, const double scale, const Bitmap & where );
virtual void Stretch( const Bitmap & where ) const;
virtual void Stretch( const Bitmap & where, const int sourceX, const int sourceY, const int sourceWidth, const int sourceHeight, const int destX, const int destY, const int destWidth, const int destHeight ) const;
virtual void StretchBy2( const Bitmap & where );
virtual void StretchBy4( const Bitmap & where );
virtual void Blit( const std::string & xpath ) const;
virtual void Blit( const Bitmap & where ) const;
virtual void Blit( const int x, const int y, const Bitmap & where ) const;
virtual void Blit( const int mx, const int my, const int wx, const int wy, const Bitmap & where ) const;
virtual void Blit( const int mx, const int my, const int width, const int height, const int wx, const int wy, const Bitmap & where ) const;
virtual void BlitMasked( const int mx, const int my, const int width, const int height, const int wx, const int wy, const Bitmap & where ) const;
virtual void BlitToScreen() const;
virtual void BlitAreaToScreen(const int upper_left_x, const int upper_left_y) const;
virtual void BlitToScreen(const int upper_left_x, const int upper_left_y) const;
virtual void BlitFromScreen(const int x, const int y) const;
/* try to call Global::getScreenWidth/Height() instead of these directly */
static int getScreenWidth();
static int getScreenHeight();
virtual void fill( int color ) const;
inline void clear() const{
this->fill( 0 );
}
inline void clearToMask() const{
this->fill(MaskColor());
}
bool getError();
inline const BitmapData & getData() const {
return data;
}
inline BitmapData & getData(){
return data;
}
virtual void readLine( std::vector< int > & vec, int y );
int getPixel( const int x, const int y ) const;
/* true if the point is within the bounds of the bitmap */
bool inRange(int x, int y) const;
/* uses _putpixel16 underneath which ignores translucent behavior */
void putPixel( int x, int y, int col ) const;
/* respects the current trans mode */
virtual void putPixelNormal(int x, int y, int col) const;
/*
inline int getPixel( int x, int y ) const{
if ( x >= 0 && x < my_bitmap->w && y >= 0 && y <= my_bitmap->h )
return _getpixel16( my_bitmap, x, y );
return -1;
}
inline void putPixel( int x, int y, int col ) const{
if ( x >= 0 && x < my_bitmap->w && y >= 0 && y <= my_bitmap->h )
_putpixel16( my_bitmap, x, y, col );
}
*/
void setClipRect( int x1, int y1, int x2, int y2 ) const;
void getClipRect( int & x1, int & y1, int & x2, int & y2 ) const;
inline const std::string & getPath() const{
return path;
}
/* produce a temporary bitmap that is not guaranteed to be preserved
* after your function returns. do *not* hold references to this bitmap
* and if you make a temporary bitmap, do *not* call functions that
* might also make temporary bitmaps.
*/
static Bitmap temporaryBitmap(int w, int h);
static Bitmap temporaryBitmap2(int w, int h);
/* call this method to delete all temporary bitmaps.
* don't call this unless you know what you are doing
*/
static void cleanupTemporaryBitmaps();
static double getScale();
static int setGfxModeText();
static int setGfxModeFullscreen( int x, int y );
static int setGfxModeWindowed( int x, int y );
static int makeColor( int r, int g, int b );
static int darken( int color, double factor );
static void hsvToRGB( float h, float s, float v, int * r, int * g, int * b );
/*
* Convert color values between the HSV and RGB color spaces. The RGB values
* range from 0 to 255, hue is from 0 to 360, and saturation and value are
* from 0 to 1.
*/
static void rgbToHSV(int r, int g, int b, float * h, float * s, float * v);
/* convert cymk to rgb. values should be in the range 0-255 */
static void cymkToRGB(int c, int y, int m, int k, int * r, int * g, int * b);
static int getRed( int x );
static int getBlue( int x );
static int getGreen( int x );
/* Add two RGB16 colors together
* r = c1.r + c2.r
* g = c1.g + c2.g
* b = c1.b + c2.b
*/
static int addColor( int color1, int color2 );
/*
inline static int makeColor( int r, int g, int b ){
return makecol16( r, g, b );
}
*/
// static const int MaskColor = MASK_COLOR_16;
static int MaskColor();
static const int MODE_TRANS;
static const int MODE_SOLID;
static const int SPRITE_NO_FLIP;
static const int SPRITE_V_FLIP;
static const int SPRITE_H_FLIP;
static const int SPRITE_NORMAL;
static const int SPRITE_LIT;
static const int SPRITE_TRANS;
protected:
static void initializeExtraStuff();
/* release a reference count, and possibly destroy data */
void releaseInternalBitmap();
/* really destroy private data */
void destroyPrivateData();
/*
inline void setBitmap( BITMAP * bitmap ){
if ( bitmap == NULL ){
std::cout << "*FATAL* Setting null bitmap" << std::endl;
}
_my_bitmap = bitmap;
}
*/
void internalLoadFile( const char * load_file );
/* implementation specific data */
BitmapData data;
int * own;
bool mustResize;
// bool own;
bool error;
std::string path;
static Bitmap * temporary_bitmap;
static Bitmap * temporary_bitmap2;
int bit8MaskColor;
/* bitmaps that should always be resized to the dimensions of the screen */
static std::vector<Bitmap*> needResize;
};
#endif
diff --git a/util/funcs.cpp b/util/funcs.cpp
index 0577103b..66699061 100644
--- a/util/funcs.cpp
+++ b/util/funcs.cpp
@@ -1,318 +1,319 @@
#ifdef USE_ALLEGRO
#include <allegro.h>
#endif
#ifdef USE_SDL
#include <SDL.h>
#endif
#include "funcs.h"
#include "globals.h"
#include "debug.h"
#include <vector>
#include <string>
#include <string.h>
#include <algorithm>
#include "file-system.h"
#include "bitmap.h"
+#include "trans-bitmap.h"
#include "font.h"
#include "init.h"
#include <sstream>
#ifndef USE_ALLEGRO
/* FIXME: move this to the filesystem module */
#include "sfl/sfl.h"
#include "sfl/sflfile.h"
#endif
#ifndef WINDOWS
#include <unistd.h>
#endif
#ifdef max
#undef max
#endif
#ifdef min
#undef min
#endif
using namespace std;
/* remove this once cmake and scons properly set DATA_PATH */
#ifndef DATA_PATH
#define DATA_PATH "data"
#endif
/* the build system should define DATA_PATH */
static string dataPath = DATA_PATH;
const double Util::pi = 3.14159265;
double Util::radians(double degree){
return degree * pi / 180.0;
}
/*
inline int rnd( int q ){
if ( q <= 0 ) return 0;
return (int)( rand() % q );
}
*/
int Util::max(int a, int b){
if (a>b){
return a;
}
return b;
}
/*
int Util::min(int a, int b){
if (a<b){
return a;
}
return b;
}
*/
int Util::clamp(int value, int min, int max){
return Util::min(Util::max(value, min), max);
}
int Util::rnd( int q, int min, int range ){
return q - min + rnd( range );
}
int Util::rnd( int min, int max ){
return rnd( max - min ) + min;
}
/* sleep for `x' milliseconds */
void Util::rest( int x ){
#ifdef USE_ALLEGRO
::rest(x);
#endif
#ifdef USE_SDL
SDL_Delay(x);
#endif
}
void Util::restSeconds(double x){
Util::rest((int)(x * 1000));
}
bool Util::checkVersion(int version){
if (version == Global::getVersion()){
return true;
}
/* when an incompatible version is made, add a check here, like
* version < getVersion(3, 5)
* would mean any client below version 3.5 is incompatible.
*
* assume versions of client's greater than ourself is compatible, but
* this may not be true. There is no way to check this.
*/
if (version < 0){
return false;
}
return true;
}
void Util::setDataPath( const string & str ){
dataPath = str;
}
Filesystem::AbsolutePath Util::getDataPath2(){
return Filesystem::AbsolutePath(dataPath + "/");
}
bool Util::exists( const string & file ){
#ifdef USE_ALLEGRO
return ::exists(file.c_str()) != 0;
#else
return file_exists(file.c_str());
#endif
}
/*
vector<Filesystem::AbsolutePath> Util::getFiles(const Filesystem::AbsolutePath & dataPath, const string & find){
return Filesystem::getFiles(dataPath, find);
}
*/
void Util::blend_palette(int * pal, int mp, int startColor, int endColor ) {
/*
ASSERT(pal);
ASSERT(mp != 0);
*/
int sc_r = Bitmap::getRed(startColor);
int sc_g = Bitmap::getGreen(startColor);
int sc_b = Bitmap::getBlue(startColor);
int ec_r = Bitmap::getRed(endColor);
int ec_g = Bitmap::getGreen(endColor);
int ec_b = Bitmap::getBlue(endColor);
for ( int q = 0; q < mp; q++ ) {
float j = (float)( q + 1 ) / (float)( mp );
int f_r = (int)( 0.5 + (float)( sc_r ) + (float)( ec_r-sc_r ) * j );
int f_g = (int)( 0.5 + (float)( sc_g ) + (float)( ec_g-sc_g ) * j );
int f_b = (int)( 0.5 + (float)( sc_b ) + (float)( ec_b-sc_b ) * j );
pal[q] = Bitmap::makeColor( f_r, f_g, f_b );
}
}
string Util::trim(const std::string & str){
string s;
size_t startpos = str.find_first_not_of(" \t");
size_t endpos = str.find_last_not_of(" \t");
// if all spaces or empty return an empty string
if ((string::npos == startpos) ||
(string::npos == endpos)){
return "";
} else {
return str.substr(startpos, endpos-startpos+1);
}
return str;
}
/* makes the first letter of a string upper case */
string Util::upcase(std::string str){
if ( str.length() > 0 && (str[0] >= 'a' && str[0] <= 'z') ){
str[0] = str[0] - 'a' + 'A';
}
return str;
}
static int lowerCase(int c){
return tolower(c);
}
static int upperCase(int c){
return toupper(c);
}
string Util::upperCaseAll(std::string str){
std::transform(str.begin(), str.end(), str.begin(), upperCase);
return str;
}
string Util::lowerCaseAll(std::string str){
std::transform(str.begin(), str.end(), str.begin(), lowerCase);
/*
for (unsigned int i = 0; i < str.length(); i++){
if (str[0] >= 'A' && str[0] <= 'Z'){
str[0] = str[0] - 'A' + 'a';
}
}
*/
return str;
}
/*Gets the minimum of three values*/
static int minimum(int a,int b,int c){
int min=a;
if(b<min)
min=b;
if(c<min)
min=c;
return min;
}
/* Compute levenshtein distance between s and t
* from: http://www.merriampark.com/ldc.htm
*/
static int levenshtein_distance(const char *s, const char *t){
//Step 1
int k,i,j,n,m,cost,distance;
int * d;
n=strlen(s);
m=strlen(t);
if(n!=0&&m!=0){
d = (int*) malloc((sizeof(int))*(m+1)*(n+1));
m++;
n++;
//Step 2
for(k=0;k<n;k++)
d[k]=k;
for(k=0;k<m;k++)
d[k*n]=k;
//Step 3 and 4
for(i=1;i<n;i++)
for(j=1;j<m;j++)
{
//Step 5
if(s[i-1]==t[j-1])
cost=0;
else
cost=1;
//Step 6
d[j*n+i]=minimum(d[(j-1)*n+i]+1,d[j*n+i-1]+1,d[(j-1)*n+i-1]+cost);
}
distance=d[n*m-1];
free(d);
return distance;
} else {
return -1; //a negative return value means that one or both strings are empty.
}
}
int Util::levenshtein(const std::string & str1, const std::string & str2){
return levenshtein_distance(str1.c_str(), str2.c_str());
}
void Util::limitPrintf(char * buffer, int size, const char * format, va_list args){
#ifdef USE_ALLEGRO
uvszprintf(buffer, size, format, args);
#else
vsnprintf(buffer, size, format, args);
#endif
}
#ifndef WINDOWS
int Util::getPipe(int files[2]){
return pipe(files);
}
#endif
void Util::showError(const Bitmap & screen, const Exception::Base & exception, const string & info){
screen.BlitFromScreen(0, 0);
Bitmap error(screen.getWidth() - 100, screen.getHeight() - 100);
error.fill(Bitmap::darken(Bitmap::makeColor(160, 0, 0), 3));
error.border(1, 2, Bitmap::makeColor(240, 0, 0));
const Font & font = Font::getFont(Global::DEFAULT_FONT, 17, 17);
int y = 10;
std::ostringstream out;
out << info;
out << " " << exception.getTrace();
font.printfWrap(10, 10, Bitmap::makeColor(240, 240, 240), error, error.getWidth() - 20, out.str(), 0);
Global::debug(0) << out.str() << std::endl;
Bitmap::transBlender(0, 0, 0, 220);
- error.drawTrans(50, 50, screen);
+ error.translucent().draw(50, 50, screen);
screen.BlitToScreen();
}
void Util::showError(const Exception::Base & exception, const std::string & info){
Bitmap screen(GFX_X, GFX_Y);
showError(screen, exception, info);
}
string Util::niceSize(unsigned long size){
const char sizes[] = {'b', 'k', 'm', 'g', 't'};
double real = size;
for (unsigned int i = 0; i < sizeof(sizes) / sizeof(const char); i++){
if (real > 1024){
real /= 1024.0;
} else {
ostringstream in;
in << real << sizes[i];
return in.str();
}
}
ostringstream in;
in << real << "t";
return in.str();
}
diff --git a/util/gui/animation.cpp b/util/gui/animation.cpp
index 00ce7be2..07f2341c 100644
--- a/util/gui/animation.cpp
+++ b/util/gui/animation.cpp
@@ -1,385 +1,386 @@
#include "animation.h"
#include <vector>
#include <math.h>
#include <sstream>
#include "util/token.h"
+#include "util/trans-bitmap.h"
#include "util/bitmap.h"
#include "globals.h"
#include "../debug.h"
#include "../funcs.h"
#include "../file-system.h"
using namespace std;
using namespace Gui;
// Temporary solution
static void renderSprite(const Bitmap & bmp, const int x, const int y, const int alpha, const bool hflip, const bool vflip, const Bitmap & work){
if (alpha != 255){
Bitmap::transBlender( 0, 0, 0, alpha );
if (hflip && !vflip){
- bmp.drawTransHFlip(x,y, work);
+ bmp.translucent().drawHFlip(x,y, work);
} else if (!hflip && vflip){
- bmp.drawTransVFlip(x,y, work);
+ bmp.translucent().drawVFlip(x,y, work);
} else if (hflip && vflip){
- bmp.drawTransHVFlip(x,y, work);
+ bmp.translucent().drawHVFlip(x,y, work);
} else if (!hflip && !vflip){
- bmp.drawTrans(x,y, work);
+ bmp.translucent().draw(x,y, work);
}
} else {
if (hflip && !vflip){
bmp.drawHFlip(x,y, work);
} else if (!hflip && vflip){
bmp.drawVFlip(x,y, work);
} else if (hflip && vflip){
bmp.drawHVFlip(x,y, work);
} else if (!hflip && !vflip){
bmp.draw(x,y, work);
}
}
}
Frame::Frame(const Token *the_token, imageMap &images) throw (LoadException):
bmp(0),
time(0),
horizontalFlip(false),
verticalFlip(false),
alpha(255){
if ( *the_token != "frame" ){
throw LoadException(__FILE__, __LINE__, "Not an frame");
}
const Token & tok = *the_token;
/* The usual setup of an animation frame is
// use image -1 to not draw anything, it can be used to get a blinking effect
(frame (image NUM) (alpha NUM) (offset x y) (hflip 0|1) (vflip 0|1) (time NUM))
*/
TokenView view = tok.view();
while (view.hasMore()){
try{
const Token * token;
view >> token;
if (*token == "image"){
// get the number
int num;
token->view() >> num;
// now assign the bitmap
bmp = images[num];
} else if (*token == "alpha"){
// get alpha
token->view() >> alpha;
} else if (*token == "offset"){
// Get the offset location it defaults to 0,0
double x=0, y=0;
try {
token->view() >> x >> y;
} catch (const TokenException & ex){
}
offset.set(x,y);
} else if (*token == "hflip"){
// horizontal flip
token->view() >> horizontalFlip;
} else if (*token == "vflip"){
// horizontal flip
token->view() >> verticalFlip;
} else if (*token == "time"){
// time to display
token->view() >> time;
} else {
Global::debug( 3 ) << "Unhandled menu attribute: "<<endl;
if (Global::getDebug() >= 3){
token->print(" ");
}
}
} catch ( const TokenException & ex ) {
throw LoadException(__FILE__, __LINE__, ex, "Menu animation parse error");
} catch ( const LoadException & ex ) {
throw ex;
}
}
}
Frame::Frame(Bitmap * bmp):
bmp(bmp),
time(0),
horizontalFlip(false),
verticalFlip(false),
alpha(255){
}
Frame::~Frame(){
}
void Frame::act(double xvel, double yvel){
scrollOffset.moveBy(xvel,yvel);
if (scrollOffset.getDistanceFromCenterX() >=bmp->getWidth()){
scrollOffset.setX(0);
} else if (scrollOffset.getDistanceFromCenterX() <= -(bmp->getWidth())){
scrollOffset.setX(0);
}
if (scrollOffset.getDistanceFromCenterY() >=bmp->getHeight()){
scrollOffset.setY(0);
} else if (scrollOffset.getDistanceFromCenterY() <= -(bmp->getHeight())){
scrollOffset.setY(0);
}
}
static bool closeFloat(double a, double b){
const double epsilon = 0.001;
return fabs(a-b) < epsilon;
}
void Frame::draw(const int xaxis, const int yaxis, const Bitmap & work){
if (!bmp){
return;
}
if (!closeFloat(scrollOffset.getDistanceFromCenterX(), 0) || !closeFloat(scrollOffset.getDistanceFromCenterY(), 0)){
// Lets do some scrolling
Bitmap temp = Bitmap::temporaryBitmap(bmp->getWidth(), bmp->getHeight());
//AnimationPoint loc;
AbsolutePoint loc;
if (scrollOffset.getRelativeX() < 0){
loc.setX(scrollOffset.getDistanceFromCenterX() + bmp->getWidth());
} else if (scrollOffset.getRelativeX() > 0){
loc.setX(scrollOffset.getDistanceFromCenterX() - bmp->getWidth());
}
if (scrollOffset.getRelativeY() < 0){
loc.setY(scrollOffset.getDistanceFromCenterY() + bmp->getHeight());
} else if (scrollOffset.getRelativeY() > 0){
loc.setY(scrollOffset.getDistanceFromCenterY() - bmp->getHeight());
}
bmp->Blit((int) scrollOffset.getDistanceFromCenterX(), (int) scrollOffset.getDistanceFromCenterY(), temp);
bmp->Blit((int) scrollOffset.getDistanceFromCenterX(), (int) loc.getY(), temp);
bmp->Blit((int) loc.getX(), (int) scrollOffset.getDistanceFromCenterY(), temp);
bmp->Blit((int) loc.getX(), (int) loc.getY(), temp);
renderSprite(temp, (int)(xaxis+offset.getDistanceFromCenterX()), (int)(yaxis+offset.getDistanceFromCenterY()), alpha, horizontalFlip, verticalFlip, work);
} else {
renderSprite(*bmp, (int)(xaxis+offset.getDistanceFromCenterX()), (int)(yaxis+offset.getDistanceFromCenterY()), alpha, horizontalFlip, verticalFlip, work);
}
}
Animation::Animation(const Token *the_token) throw (LoadException):
id(0),
depth(BackgroundBottom),
ticks(0),
currentFrame(0),
loop(0),
allowReset(true){
images[-1] = 0;
std::string basedir = "";
if ( *the_token != "anim" ){
throw LoadException(__FILE__, __LINE__, "Not an animation");
}
/* The usual setup of an animation is
The images must be listed prior to listing any frames, basedir can be used to set the directory where the images are located
loop will begin at the subsequent frame listed after loop
axis is the location in which the drawing must be placed
location *old* - used to render in background or foreground (0 == background [default]| 1 == foreground)
depth - used to render in background or foreground space (depth background bottom|middle|top) | (depth foreground bottom|midle|top)
reset - used to allow resetting of animation (0 == no | 1 == yes [default])
velocity - used to get a wrapping scroll effect while animating
window - area in which the item will be contained
(anim (id NUM)
(location NUM)
(depth background|foreground NUM)
(basedir LOCATION)
(image NUM FILE)
(velocity x y)
(axis x y)
(frame "Read comments above in constructor")
(loop)
(reset NUM)
(window x1 y1 x2 y2))
*/
const Token & tok = *the_token;
TokenView view = tok.view();
while (view.hasMore()){
try{
const Token * token;
view >> token;
if (*token == "id"){
// get the id
token->view() >> id;
} else if (*token == "location"){
// translate location to depth
int location = 0;
token->view() >> location;
if (location == 0){
depth = BackgroundBottom;
} else if (location == 1){
depth = ForegroundBottom;
}
} else if (*token == "depth"){
// get the depth
std::string name, level;
token->view() >> name >> level;
if (name == "background"){
if (level == "bottom"){
depth = BackgroundBottom;
} else if (level == "middle"){
depth = BackgroundMiddle;
} else if (level == "top"){
depth = BackgroundTop;
}
} else if (name == "foreground"){
if (level == "bottom"){
depth = ForegroundBottom;
} else if (level == "middle"){
depth = ForegroundMiddle;
} else if (level == "top"){
depth = ForegroundTop;
}
}
} else if (*token == "basedir"){
// set the base directory for loading images
token->view() >> basedir;
} else if (*token == "image"){
// add bitmaps by number to the map
int number;
std::string temp;
token->view() >> number >> temp;
Bitmap *bmp = new Bitmap(Filesystem::find(Filesystem::RelativePath(basedir + temp)).path());
if (bmp->getError()){
delete bmp;
} else {
images[number] = bmp;
}
} else if (*token == "axis"){
// Get the axis location it defaults to 0,0
double x=0, y=0;
try {
token->view() >> x >> y;
} catch (const TokenException & ex){
}
axis.set(x,y);
} else if (*token == "window"){
// Windowed area where to clip if necessary otherwise it defaults to max
double x1=0,x2=0, y1=0,y2=0;
try {
token->view() >> x1 >> y1 >> x2 >> y2;
} catch (const TokenException & ex){
}
window.set(x1,y1,x2,y2);
} else if (*token == "velocity"){
// This allows the animation to get a wrapping scroll action going on
double x=0, y=0;
try {
token->view() >> x >> y;
} catch (const TokenException & ex){
}
velocity.set(x,y);
} else if (*token == "frame"){
// new frame
Frame *frame = new Frame(token, images);
frames.push_back(frame);
} else if (*token == "loop"){
// start loop here
int l;
token->view() >> l;
if (l >= (int)frames.size()){
ostringstream out;
out << "Loop location is larger than the number of frames. Loop: " << loop << " Frames: " << frames.size();
throw LoadException(__FILE__, __LINE__, out.str());
}
loop = l;
} else if (*token == "reset"){
// Allow reset of animation
token->view() >> allowReset;
} else {
Global::debug( 3 ) << "Unhandled menu attribute: "<<endl;
if (Global::getDebug() >= 3){
token->print(" ");
}
}
} catch ( const TokenException & ex ) {
throw LoadException(__FILE__, __LINE__, ex, "Menu animation parse error");
} catch ( const LoadException & ex ) {
throw ex;
}
}
}
Animation::Animation(const std::string & background) throw (LoadException):
id(0),
depth(BackgroundBottom),
ticks(0),
currentFrame(0),
loop(0),
allowReset(true){
// add bitmap
Bitmap *bmp = new Bitmap(Filesystem::find(Filesystem::RelativePath(background)).path());
if (bmp->getError()){
delete bmp;
throw LoadException(__FILE__,__LINE__, "Problem loading file: " + background);
} else {
images[0] = bmp;
}
Frame *frame = new Frame(bmp);
frames.push_back(frame);
}
Animation::Animation(Bitmap * image):
id(0),
depth(BackgroundBottom),
ticks(0),
currentFrame(0),
loop(0),
allowReset(true){
images[0] = image;
Frame *frame = new Frame(image);
frames.push_back(frame);
}
Animation::~Animation(){
for (std::vector<Frame *>::iterator i = frames.begin(); i != frames.end(); ++i){
if (*i){
delete *i;
}
}
for (imageMap::iterator i = images.begin(); i != images.end(); ++i){
if (i->second){
delete i->second;
}
}
}
void Animation::act(){
// Used for scrolling
for (std::vector<Frame *>::iterator i = frames.begin(); i != frames.end(); ++i){
(*i)->act(velocity.getRelativeX(), velocity.getRelativeY());
}
if( frames[currentFrame]->time != -1 ){
ticks++;
if(ticks >= frames[currentFrame]->time){
ticks = 0;
forwardFrame();
}
}
}
void Animation::draw(const Bitmap & work){
/* should use sub-bitmaps here */
// Set clip from the axis default is 0,0,bitmap width, bitmap height
work.setClipRect(-(window.getPosition().getDistanceFromCenterX()),-(window.getPosition().getDistanceFromCenterY()),work.getWidth() - window.getPosition2().getDistanceFromCenterX(),work.getHeight() - window.getPosition2().getDistanceFromCenterY());
frames[currentFrame]->draw(axis.getDistanceFromCenterX(), axis.getDistanceFromCenterY(),work);
work.setClipRect(0,0,work.getWidth(),work.getHeight());
}
void Animation::forwardFrame(){
if (currentFrame < frames.size() -1){
currentFrame++;
} else {
currentFrame = loop;
}
}
void Animation::backFrame(){
if (currentFrame > loop){
currentFrame--;
} else {
currentFrame = frames.size() - 1;
}
}
diff --git a/util/gui/box.cpp b/util/gui/box.cpp
index d8e18361..dfae2bcd 100644
--- a/util/gui/box.cpp
+++ b/util/gui/box.cpp
@@ -1,72 +1,73 @@
#include "util/bitmap.h"
+#include "util/trans-bitmap.h"
#include "box.h"
#include "menu/menu.h"
#include "util/font.h"
using namespace Gui;
Box::Box(){
// Nothing yet
}
Box::Box( const Box & b ){
this->location = b.location;
this->workArea = b.workArea;
}
Box::~Box(){
// Nothing yet
}
Box &Box::operator=( const Box &copy){
location = copy.location;
workArea = copy.workArea;
return *this;
}
// Logic
void Box::act(const Font & font){
// Nothing yet
}
// Render
void Box::render(const Bitmap & work){
checkWorkArea();
// Check if we are using a rounded box
if (location.getRadius() > 0){
roundRectFill(*workArea, (int)location.getRadius(), 0, 0, location.getWidth()-1, location.getHeight()-1, colors.body);
roundRect(*workArea, (int)location.getRadius(), 0, 0, location.getWidth()-1, location.getHeight()-1, colors.border);
} else {
workArea->rectangleFill(0, 0, location.getWidth()-1, location.getHeight()-1, colors.body );
workArea->rectangle(0, 0, location.getWidth()-1, location.getHeight()-1, colors.border );
}
Bitmap::transBlender( 0, 0, 0, colors.bodyAlpha );
// workArea->drawingMode( Bitmap::MODE_TRANS );
- workArea->drawTrans(location.getX(), location.getY(), work);
+ workArea->translucent().draw(location.getX(), location.getY(), work);
// work.drawingMode( Bitmap::MODE_SOLID );
}
void Box::messageDialog(int centerWidth, int centerHeight, const std::string & message, int radius){
/* FIXME Get rid of this */
#if 0
const Font &vFont = Font::getFont(OldMenu::Menu::getFont(),OldMenu::Menu::getFontWidth(),OldMenu::Menu::getFontHeight());
const int width = vFont.textLength(message.c_str()) + 10;
const int height = vFont.getHeight() + 10;
const int x = (centerWidth/2) - (width/2);
const int y = (centerHeight/2) - (height/2);
Box dialog;
dialog.location.setDimensions(width, height);
dialog.location.setRadius(radius);
dialog.colors.body = Bitmap::makeColor(0,0,0);
dialog.colors.bodyAlpha = 200;
dialog.colors.border = Bitmap::makeColor(255,255,255);
dialog.colors.borderAlpha = 255;
Bitmap temp = Bitmap::temporaryBitmap(width,height);
dialog.render(temp);
vFont.printf( 5, 5, Bitmap::makeColor(255,255,255), temp, message, -1);
temp.BlitToScreen(x,y);
#endif
}
diff --git a/util/gui/lineedit.cpp b/util/gui/lineedit.cpp
index 0f9981b9..f70bc1ad 100644
--- a/util/gui/lineedit.cpp
+++ b/util/gui/lineedit.cpp
@@ -1,359 +1,360 @@
#include "util/bitmap.h"
+#include "util/trans-bitmap.h"
#include "util/font.h"
#include "lineedit.h"
#include "keys.h"
#include "globals.h"
#include "util/debug.h"
#include <iostream>
using namespace Gui;
static std::ostream & debug( int level ){
Global::debug(level) << "[line edit] ";
return Global::debug(level);
}
LineEdit::LineEdit() :
currentSetFont(0),
hAlignment(T_Middle),
hAlignMod(T_Middle),
vAlignment(T_Middle),
inputTypeValue(inputGeneral),
changed_(0),
autoResizable(0),
textX(0),
textY(0),
cursorX(0),
cursorY(0),
cursorIndex(0),
textColor(0),
textSizeH(0),
limit(0),
blinkRate(500),
blink(false),
focused(false),
changeCounter(0){
cursorTime.reset();
}
LineEdit::~LineEdit()
{
}
void LineEdit::hookKey(int key, void (*callback)(void *), void * arg){
input.addBlockingHandle(key, callback, arg);
}
bool LineEdit::didChanged(unsigned long long & counter){
bool did = counter < changeCounter;
counter = changeCounter;
return did;
}
// If the font size changes
void LineEdit::fontChange(){
changed();
}
// Update
void LineEdit::act(const Font & font){
if (cursorTime.msecs() >= blinkRate){
cursorTime.reset();
blink = !blink;
changed();
}
/*
if ((blinkRate * 2) <= cursorTime.msecs()){
cursorTime.reset();
changed();
}
*/
if (input.doInput()){
changed();
cursorIndex = input.getText().size();
}
if (changed_){
textSizeH = currentSetFont->getHeight();
if (autoResizable) {
location.setDimensions(textSizeH+2, currentSetFont->textLength(input.getText().c_str()) + 4);
} else {
if (hAlignMod==T_Left){
if (currentSetFont->textLength(input.getText().c_str())>location.getWidth()){
hAlignment = T_Right;
} else {
hAlignment = T_Left;
}
}
}
switch (hAlignment) {
case T_Left:
textX = 2;
cursorX = textX + currentSetFont->textLength(input.getText().substr(0,cursorIndex).c_str()) + 1;
break;
case T_Middle:
textX = (location.getWidth()/2) - (currentSetFont->textLength(input.getText().c_str())/2);
cursorX = (textX) + currentSetFont->textLength(input.getText().substr(0,cursorIndex).c_str()) + 1;
break;
case T_Right:
textX = location.getWidth() - currentSetFont->textLength(input.getText().c_str());//(position.width - 1)-2;
cursorX = location.getWidth() - currentSetFont->textLength(input.getText().substr(0, input.getText().length()-cursorIndex).c_str());
break;
case T_Bottom:
case T_Top:
break;
}
switch (vAlignment) {
case T_Top:
textY = 1;
cursorY = 1;
break;
case T_Middle:
textY = cursorY = (location.getHeight() - textSizeH-(5))/2;
break;
case T_Bottom:
textY = (location.getHeight() - 1) - textSizeH - 1;
cursorY = textY - textSizeH;
break;
case T_Right:
case T_Left:
break;
}
//textY++;
//textX++;
stable();
}
}
// Draw
void LineEdit::render(const Bitmap & work){
checkWorkArea();
// Check if we are using a rounded box
if (location.getRadius()>0) {
Bitmap::transBlender( 0, 0, 0, colors.bodyAlpha );
roundRectFill( *workArea, (int)location.getRadius(), 0, 0, location.getWidth()-1, location.getHeight()-1, colors.body );
- workArea->drawTrans(location.getX(),location.getY(),work);
+ workArea->translucent().draw(location.getX(),location.getY(),work);
workArea->fill(Bitmap::makeColor(255,0,255));
Bitmap::transBlender( 0, 0, 0, colors.borderAlpha );
roundRect( *workArea, (int)location.getRadius(), 0, 0, location.getWidth()-1, location.getHeight()-1, colors.border );
- workArea->drawTrans(location.getX(),location.getY(),work);
+ workArea->translucent().draw(location.getX(),location.getY(),work);
} else {
Bitmap::transBlender( 0, 0, 0, colors.bodyAlpha );
workArea->rectangleFill( 0, 0, location.getWidth()-1, location.getHeight()-1, colors.body );
- workArea->drawTrans(location.getX(),location.getY(),work);
+ workArea->translucent().draw(location.getX(),location.getY(),work);
workArea->fill(Bitmap::makeColor(255,0,255));
Bitmap::transBlender( 0, 0, 0, colors.borderAlpha );
workArea->rectangle( 0, 0, location.getWidth()-1, location.getHeight()-1, colors.border );
- workArea->drawTrans(location.getX(),location.getY(),work);
+ workArea->translucent().draw(location.getX(),location.getY(),work);
}
- work.drawingMode( Bitmap::MODE_SOLID );
+ // work.drawingMode( Bitmap::MODE_SOLID );
workArea->fill(Bitmap::makeColor(255,0,255));
if (currentSetFont){
currentSetFont->printf(textX,textY,textColor,*workArea, input.getText(), 0);
}
if (focused){
/*
if (cursorTime.msecs() <= blinkRate){
workArea->line(cursorX,cursorY,cursorX,cursorY+textSizeH-5,textColor);
}
*/
if (blink){
workArea->line(cursorX,cursorY,cursorX,cursorY+textSizeH-5,textColor);
}
}
workArea->draw(location.getX(), location.getY(), work);
}
#if 0
// Keypresses
sigslot::slot LineEdit::keyPress(const keys &k)
{
debug( 5 ) << "Received key press " << k.getValue() << std::endl;
if(focused)
{
if(k.isCharacter())
{
char keyValue = k.getValue();
bool addValue = false;
switch(inputTypeValue){
case inputNumerical:
if ( k.isNumber() ) addValue = !addValue;
break;
case inputNoCaps:
keyValue = tolower(keyValue);
addValue = !addValue;
break;
case inputAllCaps:
keyValue = toupper(keyValue);
addValue = !addValue;
break;
case inputGeneral:
default:
addValue = !addValue;
break;
}
if(addValue){
if(limit!=0)
{
if(currentSetText.length()<limit)
{
//currentSetText += k.getValue();
currentSetText.insert(cursorIndex, std::string(1,keyValue));
++cursorIndex;
changed();
}
}
else
{
//currentSetText += k.getValue();
currentSetText.insert(cursorIndex, std::string(1,keyValue));
++cursorIndex;
changed();
}
}
}
else
{
switch(k.getValue())
{
case keys::DEL:
if(cursorIndex<currentSetText.length())
{
currentSetText.erase(cursorIndex,1);
}
break;
case keys::BACKSPACE:
if(cursorIndex>0)
{
currentSetText.erase(cursorIndex - 1, 1);
--cursorIndex;
}
break;
case keys::RIGHT:
if(cursorIndex<currentSetText.length())++cursorIndex;
break;
case keys::LEFT:
if(cursorIndex>0)--cursorIndex;
break;
case keys::INSERT:
break;
}
changed();
}
}
}
#endif
// Set text
void LineEdit::setText(const std::string & text){
input.setText(text);
if (limit!=0) {
if (input.getText().length() > limit) {
while (input.getText().length() > limit){
// currentSetText.erase(currentSetText.begin()+currentSetText.length()-1);
}
}
}
cursorIndex = input.getText().length();
changed();
}
//! Get text
const std::string LineEdit::getText(){
return input.getText();
}
//! Clear text
void LineEdit::clearText(){
input.clearInput();
cursorIndex=0;
changed();
}
//! Set text limit
void LineEdit::setLimit(unsigned int l){
limit = l;
if (limit!=0){
if (input.getText().length()>limit){
while (input.getText().length()>limit){
// currentSetText.erase(currentSetText.begin()+currentSetText.length()-1);
}
}
}
cursorIndex = input.getText().length();
changed();
}
// Set Horizontal Alignment
void LineEdit::setHorizontalAlign(const textAlign & a){
hAlignment = hAlignMod = a;
changed();
}
// Set Vertical Alignment
void LineEdit::setVerticalAlign(const textAlign & a){
vAlignment = a;
changed();
}
//! Set the type of input default general
void LineEdit::setInputType(const inputType i){
inputTypeValue = i;
}
// Set textColor
void LineEdit::setTextColor(const int color){
textColor = color;
}
//! Set textColor
void LineEdit::setCursorColor(const int color){
textColor = color;
}
// Set font
void LineEdit::setFont(const Font *f){
currentSetFont = f;
if (currentSetFont) changed();
}
// Set autoResizeable
void LineEdit::setAutoResize(bool r){
autoResizable = r;
}
// Set the cursor blink rate in miliseconds (default 500)
void LineEdit::setCursorBlinkRate(unsigned int msecs){
blinkRate = msecs;
}
//! set Focus
void LineEdit::setFocused(bool focus){
focused = focus;
if (focus){
input.enable();
} else {
input.disable();
}
}
//! check Focus
bool LineEdit::isFocused(){
return focused;
}
diff --git a/util/lit_bitmap.h b/util/lit_bitmap.h
index 2ea4e00a..1d665e24 100644
--- a/util/lit_bitmap.h
+++ b/util/lit_bitmap.h
@@ -1,20 +1,22 @@
#ifndef _paintown_lit_bitmap_h
#define _paintown_lit_bitmap_h
#include "bitmap.h"
class LitBitmap: public Bitmap {
public:
LitBitmap( const Bitmap & b );
LitBitmap();
virtual ~LitBitmap();
using Bitmap::draw;
virtual void draw( const int x, const int y, const Bitmap & where ) const;
using Bitmap::drawHFlip;
virtual void drawHFlip( const int x, const int y, const Bitmap & where ) const;
+ using Bitmap::drawVFlip;
virtual void drawVFlip( const int x, const int y, const Bitmap & where ) const;
+ using Bitmap::drawHVFlip;
virtual void drawHVFlip( const int x, const int y, const Bitmap & where ) const;
};
#endif
diff --git a/util/loading.cpp b/util/loading.cpp
index 52a9eab6..9b226956 100644
--- a/util/loading.cpp
+++ b/util/loading.cpp
@@ -1,530 +1,530 @@
#include "bitmap.h"
#include "trans-bitmap.h"
#include <math.h>
#include <iostream>
/* FIXME: get rid of this dependancy */
#include "paintown-engine/level/utils.h"
#include "messages.h"
#include "loading.h"
#include "file-system.h"
#include "font.h"
#include "funcs.h"
#include "gradient.h"
#include "thread.h"
#include "globals.h"
#include <vector>
#include "thread.h"
#include "message-queue.h"
#include "init.h"
using namespace std;
namespace Loader{
// Util::Thread::Lock loading_screen_mutex;
volatile bool done_loading = true;
typedef struct pair{
int x, y;
} ppair;
class Info{
public:
Info(){
Global::registerInfo(&messages);
}
bool transferMessages(Messages & box){
bool did = false;
while (messages.hasAny()){
const string & str = messages.get();
box.addMessage(str);
did = true;
}
return did;
}
~Info(){
Global::unregisterInfo(&messages);
}
private:
MessageQueue messages;
};
void * loadingScreenSimple1(void * arg);
#if 0
void startLoading(Util::Thread::Id * thread, void * arg, Kind kind){
bool create = false;
Util::Thread::acquireLock(&loading_screen_mutex);
create = done_loading;
done_loading = false;
Util::Thread::releaseLock(&loading_screen_mutex);
/* prevent multiple loading threads from being made */
if (create){
switch (kind){
case Default: Util::Thread::createThread(thread, NULL, (Util::Thread::ThreadFunction) loadingScreen, arg); break;
case SimpleCircle: Util::Thread::createThread(thread, NULL, (Util::Thread::ThreadFunction) loadingScreenSimple1, arg); break;
}
}
}
void stopLoading(Util::Thread::Id thread){
bool needJoin = false;
Util::Thread::acquireLock( &loading_screen_mutex );
needJoin = ! done_loading;
done_loading = true;
Util::Thread::releaseLock( &loading_screen_mutex );
if (needJoin){
Util::Thread::joinThread(thread);
}
}
#endif
static void setupBackground(const Bitmap & background, int load_x, int load_y, int load_width, int load_height, int infobox_x, int infobox_y, int infoWidth, int infoHeight, const Bitmap & infoBackground, const Bitmap & work){
background.Blit(load_x, load_y, load_width, load_height, 0, 0, work);
Font::getDefaultFont().printf( 400, 480 - Font::getDefaultFont().getHeight() * 5 / 2 - Font::getDefaultFont().getHeight(), Bitmap::makeColor( 192, 192, 192 ), background, "Paintown version %s", 0, Global::getVersionString().c_str());
Font::getDefaultFont().printf( 400, 480 - Font::getDefaultFont().getHeight() * 5 / 2, Bitmap::makeColor( 192, 192, 192 ), background, "Made by Jon Rafkind", 0 );
background.BlitToScreen();
background.Blit(infobox_x, infobox_y, infoWidth, infoHeight, 0, 0, infoBackground);
}
static vector<ppair> generateFontPixels(const Font & myFont, const string & message, int width, int height){
Bitmap letters(width, height);
letters.fill( Bitmap::MaskColor() );
myFont.printf( 0, 0, Bitmap::makeColor(255, 255, 255), letters, message.c_str(), 0 );
vector< ppair > pairs;
/* store every pixel we need to draw */
for ( int x = 0; x < letters.getWidth(); x++ ){
for ( int y = 0; y < letters.getHeight(); y++ ){
int pixel = letters.getPixel(x, y);
if (pixel != Bitmap::MaskColor()){
ppair p;
p.x = x;
p.y = y;
pairs.push_back( p );
}
}
}
return pairs;
}
/* shows time elapsed */
class TimeCounter{
public:
TimeCounter():
work(200, 40){
start = Global::second_counter;
last = 0;
}
void draw(int x, int y){
const Font & font = Font::getDefaultFont(24, 24);
if (Global::second_counter != last){
work.clear();
last = Global::second_counter;
font.printf(0, 0, Bitmap::makeColor(192, 192, 192), work, "Waiting.. %d", 0, last - start);
work.BlitAreaToScreen(x, y);
}
}
Bitmap work;
unsigned int start;
unsigned int last;
};
/* FIXME: get rid of this method */
#if 0
void * loadingScreen(void * arg){
int load_x = 80;
int load_y = 220;
const int infobox_width = 300;
const int infobox_height = 150;
Info info;
const Font & myFont = Font::getFont(Global::DEFAULT_FONT, 24, 24);
const Font & infoFont = Font::getFont(Global::DEFAULT_FONT, 24, 24);
Level::LevelInfo levelInfo;
if (arg != NULL){
levelInfo = *(Level::LevelInfo*) arg;
}
if (levelInfo.getPositionX() != -1){
load_x = levelInfo.getPositionX();
}
if (levelInfo.getPositionY() != -1){
load_y = levelInfo.getPositionY();
}
// const char * the_string = (arg != NULL) ? (const char *) arg : "Loading...";
int load_width = myFont.textLength(levelInfo.loadingMessage().c_str());
int load_height = myFont.getHeight(levelInfo.loadingMessage().c_str());
const int infobox_x = load_x;
const int infobox_y = load_y + load_height * 2;
Global::debug( 2 ) << "loading screen" << endl;
Bitmap work( load_width, load_height );
vector<ppair> pairs = generateFontPixels(myFont, levelInfo.loadingMessage(), load_width, load_height);
Messages infobox(infobox_width, infobox_height);
Bitmap infoWork(infobox_width, infobox_height);
Bitmap infoBackground(infobox_width, infobox_height);
const int MAX_COLOR = 200;
/* blend from dark grey to light red */
Effects::Gradient gradient(MAX_COLOR, Bitmap::makeColor(16, 16, 16), Bitmap::makeColor(192, 8, 8));
Global::speed_counter = 0;
if (levelInfo.getBackground() != 0){
setupBackground(*levelInfo.getBackground(), load_x, load_y, load_width, load_height, infobox_x, infobox_y, infoBackground.getWidth(), infoBackground.getHeight(), infoBackground, work);
} else {
setupBackground(Bitmap(levelInfo.loadingBackground().path()), load_x, load_y, load_width, load_height, infobox_x, infobox_y, infoBackground.getWidth(), infoBackground.getHeight(), infoBackground, work);
}
Util::ThreadBoolean quit(done_loading, loading_screen_mutex);
TimeCounter counter;
bool firstDraw = true;
while ( ! quit.get() ){
/* true if a logic loop has passed */
bool draw = firstDraw;
/* will be true if any new info messages appeared */
bool drawInfo = firstDraw;
firstDraw = false;
if ( Global::speed_counter > 0 ){
double think = Global::speed_counter;
Global::speed_counter = 0;
draw = true;
while ( think > 0 ){
gradient.backward();
think -= 1;
}
/* if no new messages appeared this will be false */
drawInfo = info.transferMessages(infobox);
} else {
Util::rest( 1 );
}
if (draw){
for ( vector< ppair >::iterator it = pairs.begin(); it != pairs.end(); it++ ){
int color = gradient.current(it->x);
work.putPixel(it->x, it->y, color);
}
// counter.draw(200, 100);
/* we might not have to draw the whole info box again if no new
* messages appeared.
*/
if (drawInfo){
infoBackground.Blit(infoWork);
/* cheesy hack to change the font size. the font
* should store the size and change it on its own
*/
Font::getFont(Global::DEFAULT_FONT, 13, 13);
infobox.draw(0, 0, infoWork, infoFont);
Font::getFont(Global::DEFAULT_FONT, 24, 24);
infoWork.BlitAreaToScreen(infobox_x, infobox_y);
}
/* work already contains the correct background */
// work.Blit( load_x, load_y, *Bitmap::Screen );
work.BlitAreaToScreen(load_x, load_y);
}
}
return NULL;
}
#endif
static void loadingScreen1(LoadingContext & context, const Level::LevelInfo & levelInfo){
int load_x = 80;
int load_y = 220;
const int infobox_width = 300;
const int infobox_height = 150;
Info info;
const Font & myFont = Font::getFont(Global::DEFAULT_FONT, 24, 24);
const Font & infoFont = Font::getFont(Global::DEFAULT_FONT, 24, 24);
if (levelInfo.getPositionX() != -1){
load_x = levelInfo.getPositionX();
}
if (levelInfo.getPositionY() != -1){
load_y = levelInfo.getPositionY();
}
// const char * the_string = (arg != NULL) ? (const char *) arg : "Loading...";
int load_width = myFont.textLength(levelInfo.loadingMessage().c_str());
int load_height = myFont.getHeight(levelInfo.loadingMessage().c_str());
const int infobox_x = load_x;
const int infobox_y = load_y + load_height * 2;
Global::debug(2) << "loading screen" << endl;
Bitmap work(load_width, load_height);
vector<ppair> pairs = generateFontPixels(myFont, levelInfo.loadingMessage(), load_width, load_height);
Messages infobox(infobox_width, infobox_height);
Bitmap infoWork(infobox_width, infobox_height);
Bitmap infoBackground(infobox_width, infobox_height);
const int MAX_COLOR = 200;
/* blend from dark grey to light red */
Effects::Gradient gradient(MAX_COLOR, Bitmap::makeColor(16, 16, 16), Bitmap::makeColor(192, 8, 8));
Global::speed_counter = 0;
if (levelInfo.getBackground() != 0){
setupBackground(*levelInfo.getBackground(), load_x, load_y, load_width, load_height, infobox_x, infobox_y, infoBackground.getWidth(), infoBackground.getHeight(), infoBackground, work);
} else {
setupBackground(Bitmap(levelInfo.loadingBackground().path()), load_x, load_y, load_width, load_height, infobox_x, infobox_y, infoBackground.getWidth(), infoBackground.getHeight(), infoBackground, work);
}
TimeCounter counter;
bool firstDraw = true;
while (! context.done()){
/* true if a logic loop has passed */
bool draw = firstDraw;
/* will be true if any new info messages appeared */
bool drawInfo = firstDraw;
firstDraw = false;
if ( Global::speed_counter > 0 ){
double think = Global::speed_counter;
Global::speed_counter = 0;
draw = true;
while ( think > 0 ){
gradient.backward();
think -= 1;
}
/* if no new messages appeared this will be false */
drawInfo = info.transferMessages(infobox);
} else {
Util::rest( 1 );
}
if (draw){
for ( vector< ppair >::iterator it = pairs.begin(); it != pairs.end(); it++ ){
int color = gradient.current(it->x);
work.putPixel(it->x, it->y, color);
}
// counter.draw(200, 100);
/* we might not have to draw the whole info box again if no new
* messages appeared.
*/
if (drawInfo){
infoBackground.Blit(infoWork);
/* cheesy hack to change the font size. the font
* should store the size and change it on its own
*/
Font::getFont(Global::DEFAULT_FONT, 13, 13);
infobox.draw(0, 0, infoWork, infoFont);
Font::getFont(Global::DEFAULT_FONT, 24, 24);
infoWork.BlitAreaToScreen(infobox_x, infobox_y);
}
/* work already contains the correct background */
// work.Blit( load_x, load_y, *Bitmap::Screen );
work.BlitAreaToScreen(load_x, load_y);
}
}
}
/* shows some circles rotating around a center point */
/* FIXME: get rid of this method */
#if 0
void * loadingScreenSimple1(void * arg){
Bitmap work(40, 40);
Bitmap original(40, 40);
original.BlitFromScreen(0, 0);
Util::ThreadBoolean quit(done_loading, loading_screen_mutex);
Global::speed_counter = 0;
int angle = 0;
int color1 = Bitmap::makeColor(0, 0, 0);
int color2 = Bitmap::makeColor(0x00, 0x99, 0xff);
int color3 = Bitmap::makeColor(0xff, 0x22, 0x33);
int color4 = Bitmap::makeColor(0x44, 0x77, 0x33);
/* the length of this array is the number of circles to show */
int colors[4] = {color1, color2, color3, color4};
Bitmap::transBlender(0, 0, 0, 64);
/* speed of rotation */
int speed = 7;
while (! quit.get()){
bool draw = false;
if (Global::speed_counter > 0){
double think = Global::speed_counter;
Global::speed_counter = 0;
draw = true;
while (think > 0){
angle += speed;
think -= 1;
}
} else {
Util::rest(1);
}
if (draw){
int max = sizeof(colors) / sizeof(int);
double middleX = work.getWidth() / 2;
double middleY = work.getHeight() / 2;
original.Blit(work);
for (int i = 0; i < max; i++){
double x = cos(Util::radians(angle + 360 / max * i)) * 15;
double y = sin(Util::radians(angle + 360 / max * i)) * 15;
/* ghost circle */
work.translucent().circleFill(middleX + x, middleY + y, 2, colors[i]);
x = cos(Util::radians(angle + speed + 360 / max * i)) * 15;
y = sin(Util::radians(angle + speed + 360 / max * i)) * 15;
/* real circle */
work.circleFill(middleX + x, middleY + y, 2, colors[i]);
}
work.BlitAreaToScreen(0, 0);
}
}
return NULL;
}
#endif
static void loadingScreenSimpleX1(LoadingContext & context, const Level::LevelInfo & levelInfo){
Bitmap work(40, 40);
Bitmap original(40, 40);
original.BlitFromScreen(0, 0);
Global::speed_counter = 0;
int angle = 0;
int color1 = Bitmap::makeColor(0, 0, 0);
int color2 = Bitmap::makeColor(0x00, 0x99, 0xff);
int color3 = Bitmap::makeColor(0xff, 0x22, 0x33);
int color4 = Bitmap::makeColor(0x44, 0x77, 0x33);
/* the length of this array is the number of circles to show */
int colors[4] = {color1, color2, color3, color4};
Bitmap::transBlender(0, 0, 0, 64);
/* speed of rotation */
int speed = 7;
while (! context.done()){
bool draw = false;
if (Global::speed_counter > 0){
double think = Global::speed_counter;
Global::speed_counter = 0;
draw = true;
while (think > 0){
angle += speed;
think -= 1;
}
} else {
Util::rest(1);
}
if (draw){
int max = sizeof(colors) / sizeof(int);
double middleX = work.getWidth() / 2;
double middleY = work.getHeight() / 2;
original.Blit(work);
for (int i = 0; i < max; i++){
double x = cos(Util::radians(angle + 360 / max * i)) * 15;
double y = sin(Util::radians(angle + 360 / max * i)) * 15;
/* ghost circle */
work.translucent().circleFill(middleX + x, middleY + y, 2, colors[i]);
x = cos(Util::radians(angle + speed + 360 / max * i)) * 15;
y = sin(Util::radians(angle + speed + 360 / max * i)) * 15;
/* real circle */
work.circleFill(middleX + x, middleY + y, 2, colors[i]);
}
work.BlitAreaToScreen(0, 0);
}
}
}
LoadingContext::LoadingContext():
finished(false){
Util::Thread::initializeLock(&lock);
}
LoadingContext::~LoadingContext(){
}
void LoadingContext::doLoad(){
this->load();
Util::Thread::acquireLock(&lock);
finished = true;
Util::Thread::releaseLock(&lock);
}
bool LoadingContext::done(){
bool ok = false;
Util::Thread::acquireLock(&lock);
ok = this->finished;
Util::Thread::releaseLock(&lock);
return ok;
}
void * LoadingContext::load_it(void * arg){
LoadingContext * context = (LoadingContext*) arg;
context->doLoad();
return NULL;
}
static void showLoadMessage(){
int screenX = 80;
int screenY = 50;
Bitmap work(110, 50);
work.BlitFromScreen(screenX, screenY);
Bitmap top(110, 50);
top.fill(Bitmap::makeColor(0, 0, 0));
Font::getDefaultFont(25, 25).printf(10, 5, Bitmap::makeColor(192, 192, 192), top, "Loading", 0);
Bitmap::transBlender(0, 0, 0, 200);
- top.drawTrans(0, 0, work);
+ top.translucent().draw(0, 0, work);
work.BlitAreaToScreen(screenX, screenY);
}
void loadScreen(LoadingContext & context, const Level::LevelInfo & info, Kind kind){
Util::Thread::Id loadingThread;
bool created = Util::Thread::createThread(&loadingThread, NULL, (Util::Thread::ThreadFunction) LoadingContext::load_it, &context);
if (!created){
Global::debug(0) << "Could not create loading thread. Loading will occur in the main thread" << endl;
showLoadMessage();
LoadingContext::load_it(&context);
// throw LoadException(__FILE__, __LINE__, "Could not create loader thread");
} else {
switch (kind){
case Default: loadingScreen1(context, info); break;
case SimpleCircle: loadingScreenSimpleX1(context, info); break;
default: loadingScreen1(context, info); break;
}
Util::Thread::joinThread(loadingThread);
}
}
}
diff --git a/util/sdl/bitmap.cpp b/util/sdl/bitmap.cpp
index 344fb08c..7474e5ab 100644
--- a/util/sdl/bitmap.cpp
+++ b/util/sdl/bitmap.cpp
@@ -1,1788 +1,1788 @@
#include "../bitmap.h"
#include "../lit_bitmap.h"
#include "../trans-bitmap.h"
#include "../funcs.h"
#include "../../util/debug.h"
#include "sprig/sprig.h"
#include <SDL.h>
#include "image/SDL_image.h"
#include <math.h>
#include "exceptions/exception.h"
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(Bitmap::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 Bitmap::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);
return transBlender(Bitmap::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(){
switch (::drawingMode){
case Bitmap::MODE_SOLID : return 255;
case Bitmap::MODE_TRANS : return globalBlend.alpha;
default : 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 Bitmap::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){
throw Exception::Base(__FILE__, __LINE__);
}
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;
}
Bitmap * Bitmap::Screen = NULL;
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 {
throw Exception::Base(__FILE__, __LINE__);
}
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){
throw Exception::Base(__FILE__, __LINE__);
}
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 Exception::Base(__FILE__, __LINE__);
}
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 {
/* FIXME: throw a standard bitmap exception */
throw Exception::Base(__FILE__, __LINE__);
}
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 Bitmap::getRed(int c){
Uint8 red = 0;
Uint8 green = 0;
Uint8 blue = 0;
SDL_GetRGB(c, &format565, &red, &green, &blue);
return red;
}
int Bitmap::getBlue(int c){
Uint8 red = 0;
Uint8 green = 0;
Uint8 blue = 0;
SDL_GetRGB(c, &format565, &red, &green, &blue);
return blue;
}
int Bitmap::getGreen(int c){
Uint8 red = 0;
Uint8 green = 0;
Uint8 blue = 0;
SDL_GetRGB(c, &format565, &red, &green, &blue);
return green;
}
int Bitmap::makeColor(int red, int blue, int green){
return SDL_MapRGB(&format565, red, blue, green);
}
void Bitmap::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;
format565.colorkey = 0;
format565.alpha = 255;
}
int Bitmap::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 <<
" colorkey: " << (int) screen->format->colorkey <<
" alpha: " << (int) screen->format->alpha << std::endl;
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 = ::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 = ::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 = ::differenceBlender;
}
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 Bitmap::setGfxModeText(){
/* TODO */
return 0;
}
int Bitmap::setGfxModeFullscreen(int x, int y){
return setGraphicsMode(FULLSCREEN, x, y);
}
int Bitmap::setGfxModeWindowed( int x, int y ){
return setGraphicsMode(WINDOWED, x, y);
}
void Bitmap::drawingMode(int type){
::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 = ::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 {
switch (::drawingMode){
case MODE_SOLID : {
SPG_CircleFilled(getData().getSurface(), x, y, radius, color);
break;
}
case MODE_TRANS : {
int alpha = globalBlend.alpha;
SPG_CircleFilledBlend(getData().getSurface(), x, y, radius, color, alpha);
break;
}
}
}
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;
switch (::drawingMode){
case MODE_SOLID : {
SPG_Circle(getData().getSurface(), x, y, radius, color);
break;
}
case MODE_TRANS : {
int alpha = globalBlend.alpha;
SPG_CircleBlend(getData().getSurface(), x, y, radius, color, alpha);
break;
}
}
// 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 {
switch (::drawingMode){
case MODE_SOLID : {
SPG_Line(getData().getSurface(), x1, y1, x2, y2, color);
break;
}
case MODE_TRANS : {
int alpha = globalBlend.alpha;
SPG_LineBlend(getData().getSurface(), x1, y1, x2, y2, color, alpha);
break;
}
}
}
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, Bitmap::SPRITE_NORMAL, Bitmap::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, Bitmap::SPRITE_NORMAL, Bitmap::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, Bitmap::SPRITE_NORMAL, Bitmap::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, Bitmap::SPRITE_NORMAL, Bitmap::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, Bitmap::SPRITE_NORMAL, Bitmap::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, Bitmap::SPRITE_NORMAL, Bitmap::SPRITE_V_FLIP | Bitmap::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, Bitmap::SPRITE_NORMAL, Bitmap::SPRITE_V_FLIP | Bitmap::SPRITE_H_FLIP, filter);
}
-void Bitmap::drawTrans( const int x, const int y, const Bitmap & where ) const {
+void TranslucentBitmap::draw(const int x, const int y, const Bitmap & where) const {
paintown_draw_sprite_ex16(where.getData().getSurface(), getData().getSurface(), x, y, Bitmap::SPRITE_TRANS, Bitmap::SPRITE_NO_FLIP, NULL);
}
-void Bitmap::drawTrans( const int x, const int y, Filter * filter, const Bitmap & where ) const {
+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, Bitmap::SPRITE_TRANS, Bitmap::SPRITE_NO_FLIP, filter);
}
-void Bitmap::drawTransHFlip( const int x, const int y, const Bitmap & where ) const {
+void TranslucentBitmap::drawHFlip( const int x, const int y, const Bitmap & where ) const {
paintown_draw_sprite_ex16(where.getData().getSurface(), getData().getSurface(), x, y, Bitmap::SPRITE_TRANS, Bitmap::SPRITE_H_FLIP, NULL);
}
-void Bitmap::drawTransHFlip( const int x, const int y, Filter * filter, const Bitmap & where ) const {
+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, Bitmap::SPRITE_TRANS, Bitmap::SPRITE_H_FLIP, filter);
}
-void Bitmap::drawTransVFlip( const int x, const int y, const Bitmap & where ) const {
+void TranslucentBitmap::drawVFlip( const int x, const int y, const Bitmap & where ) const {
paintown_draw_sprite_ex16(where.getData().getSurface(), getData().getSurface(), x, y, Bitmap::SPRITE_TRANS, Bitmap::SPRITE_V_FLIP, NULL);
}
-void Bitmap::drawTransVFlip( const int x, const int y, Filter * filter, const Bitmap & where ) const {
+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, Bitmap::SPRITE_TRANS, Bitmap::SPRITE_V_FLIP, filter);
}
-void Bitmap::drawTransHVFlip( const int x, const int y, const Bitmap & where ) const {
+void TranslucentBitmap::drawHVFlip( const int x, const int y, const Bitmap & where ) const {
paintown_draw_sprite_ex16(where.getData().getSurface(), getData().getSurface(), x, y, Bitmap::SPRITE_TRANS, SPRITE_V_FLIP | SPRITE_H_FLIP, NULL);
}
-void Bitmap::drawTransHVFlip( const int x, const int y, Filter * filter,const Bitmap & where ) const {
+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, Bitmap::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 ){
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);
}
}
void Bitmap::Blit( const Bitmap & where ) const {
Blit(0, 0, where);
}
void Bitmap::Blit( const int x, const int y, const Bitmap & where ) const {
Blit(0, 0, x, y, where);
}
void Bitmap::Blit( const int mx, const int my, const int wx, const int wy, const Bitmap & where ) const {
Blit(mx, my, getWidth(), getHeight(), wx, wy, where);
}
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 {
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 {
switch (::drawingMode){
case MODE_SOLID : {
SPG_TrigonFilled(getData().getSurface(), x1, y1, x2, y2, x3, y3, color);
break;
}
case MODE_TRANS : {
int alpha = globalBlend.alpha;
SPG_TrigonFilledBlend(getData().getSurface(), x1, y1, x2, y2, x3, y3, color, alpha);
break;
}
}
}
void Bitmap::ellipse( int x, int y, int rx, int ry, int color ) const {
switch (::drawingMode){
case MODE_SOLID : {
SPG_Ellipse(getData().getSurface(), x, y, rx, ry, color);
break;
}
case MODE_TRANS : {
int alpha = globalBlend.alpha;
SPG_EllipseBlend(getData().getSurface(), x, y, rx, ry, color, alpha);
break;
}
}
}
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;
}
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, ang1, ang2, 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);
}
*/
int Bitmap::darken( int color, double factor ){
int r = (int)((double)getRed(color) / factor);
int g = (int)((double)getGreen(color) / factor);
int b = (int)((double)getBlue(color) / factor);
return makeColor(r, g, b);
}
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){
throw Exception::Base(__FILE__, __LINE__);
}
SDL_Surface * display = optimizedSurface(pcx);
Bitmap out(display, true);
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);
}
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, Bitmap::SPRITE_NORMAL, Bitmap::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, Bitmap::SPRITE_LIT, Bitmap::SPRITE_NO_FLIP, NULL);
}
void LitBitmap::drawHFlip( const int x, const int y, const Bitmap & where ) const {
paintown_draw_sprite_ex16( where.getData().getSurface(), getData().getSurface(), x, y, Bitmap::SPRITE_LIT, Bitmap::SPRITE_H_FLIP, NULL);
}
void LitBitmap::drawVFlip( const int x, const int y, const Bitmap & where ) const {
paintown_draw_sprite_ex16( where.getData().getSurface(), getData().getSurface(), x, y, Bitmap::SPRITE_LIT, Bitmap::SPRITE_V_FLIP, NULL);
}
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);
}
/*
#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 = Bitmap::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 = Bitmap::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 & Bitmap::SPRITE_V_FLIP ){
y_dir = -1;
}
if ( flip & Bitmap::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 & Bitmap::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 & Bitmap::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 & Bitmap::SPRITE_H_FLIP ){
dxbeg = dx + w - 1;
}
dybeg = dy;
if ( flip & Bitmap::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 Bitmap::SPRITE_NORMAL : {
unsigned int mask = Bitmap::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 Bitmap::SPRITE_LIT : {
int bpp = src->format->BytesPerPixel;
int litColor = Bitmap::makeColor(globalBlend.red, globalBlend.green, globalBlend.blue);
unsigned int mask = Bitmap::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 Bitmap::SPRITE_TRANS : {
int bpp = src->format->BytesPerPixel;
unsigned int mask = Bitmap::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);
}
Util::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);
}
}
diff --git a/util/trans-bitmap.h b/util/trans-bitmap.h
index 05fe78f4..15bb33bf 100644
--- a/util/trans-bitmap.h
+++ b/util/trans-bitmap.h
@@ -1,21 +1,38 @@
#ifndef _paintown_trans_bitmap_h
#define _paintown_trans_bitmap_h
#include "bitmap.h"
class TranslucentBitmap: public Bitmap {
public:
TranslucentBitmap(const Bitmap & b);
TranslucentBitmap();
virtual ~TranslucentBitmap();
virtual void putPixelNormal(int x, int y, int col) const;
virtual void rectangleFill(int x1, int y1, int x2, int y2, int color) const;
virtual void rectangle(int x1, int y1, int x2, int y2, int color) const;
virtual void fill(int color) const;
virtual void hLine( const int x1, const int y, const int x2, const int color ) const;
virtual void circleFill( int x, int y, int radius, int color ) const;
virtual void ellipse( int x, int y, int rx, int ry, int color ) const;
+
+ using Bitmap::draw;
+ virtual void draw(const int x, const int y, const Bitmap & where) const;
+ virtual void draw(const int x, const int y, Filter * filter, const Bitmap & where) const;
+ // virtual void draw(const int x, const int y, const int startWidth, const int startHeight, const int width, const int height, const Bitmap & where) const;
+ // virtual void draw(const int x, const int y, const int startWidth, const int startHeight, const int width, const int height, Filter * filter, const Bitmap & where) const;
+
+ using Bitmap::drawHFlip;
+ virtual void drawHFlip(const int x, const int y, const Bitmap & where) const;
+ virtual void drawHFlip(const int x, const int y, Filter * filter, const Bitmap & where) const;
+ // virtual void drawHFlip(const int x, const int y, const int startWidth, const int startHeight, const int width, const int height, const Bitmap & where) const;
+ // virtual void drawHFlip(const int x, const int y, const int startWidth, const int startHeight, const int width, const int height, Filter * filter, const Bitmap & where) const;
+ virtual void drawVFlip( const int x, const int y, const Bitmap & where ) const;
+ virtual void drawVFlip( const int x, const int y, Filter * filter, const Bitmap & where ) const;
+ virtual void drawHVFlip( const int x, const int y, const Bitmap & where ) const;
+ virtual void drawHVFlip( const int x, const int y, Filter * filter, const Bitmap & where ) const;
+
};
#endif

File Metadata

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

Event Timeline