summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/font.h2
-rw-r--r--include/mcolor.h5
-rw-r--r--include/shape.h18
-rw-r--r--lib/font.cc69
-rw-r--r--lib/mcolor.cc21
-rw-r--r--lib/shape.cc147
6 files changed, 229 insertions, 33 deletions
diff --git a/include/font.h b/include/font.h
index 3377ef0..3a1d1c7 100644
--- a/include/font.h
+++ b/include/font.h
@@ -37,7 +37,9 @@ namespace mogltk {
texture * alloctexture();
void Bind(int);
private:
+ void checknbind(int, ColorP);
texture ** fonttex;
+ texture ** fontcache[16];
Uint16 * corresp;
};
extern font * SystemFont;
diff --git a/include/mcolor.h b/include/mcolor.h
index 88ca27f..1202572 100644
--- a/include/mcolor.h
+++ b/include/mcolor.h
@@ -7,10 +7,13 @@
namespace mogltk {
class ColorP : public Base {
public:
- ColorP(const Color &);
+ ColorP(const Color & = WHITE);
ColorP(Uint8, Uint8, Uint8, Uint8);
+ bool operator==(const ColorP &);
void Bind();
+ void Norm();
Uint32 toSDL(SDL_PixelFormat * = 0);
+ void fromSDL(Uint32, SDL_PixelFormat * = 0);
static Color Min;
static Color Max;
Color c;
diff --git a/include/shape.h b/include/shape.h
index 720d4a2..07e88ed 100644
--- a/include/shape.h
+++ b/include/shape.h
@@ -40,18 +40,18 @@ namespace mogltk {
int GetX() const;
int GetY() const;
void walk(fillwalker *);
+ point * look(int);
private:
int x;
point * next;
sline * header;
- point * look(int);
};
int y;
sline * next;
+ fill * header;
sline * look(int);
protected:
point * pheader;
- fill * header;
friend class point;
};
protected:
@@ -63,15 +63,17 @@ namespace mogltk {
virtual void pixel(int x, int y, ColorP = WHITE);
virtual void circle(int x, int y, int r, ColorP = WHITE);
virtual void pcircle(int x, int y, int r, ColorP = WHITE);
- virtual void arc(int x, int y, int r, double a1, double a2, ColorP = WHITE);
- virtual void arc(int x, int y, int r, int x1, int y1, int x2, int y2, ColorP = WHITE);
- virtual void box(int x1, int y1, int x2, int y2, ColorP = WHITE);
+ virtual fill * fcircle(int x, int y, int r);
+ virtual void fdraw(fill *, ColorP = WHITE);
+ virtual void arc(int x, int y, int r, double a1, double a2, ColorP = DOS_WHITE);
+ virtual void arc(int x, int y, int r, int x1, int y1, int x2, int y2, ColorP = DOS_WHITE);
+ virtual void box(int x1, int y1, int x2, int y2, ColorP = DOS_WHITE);
virtual void box3d(int x1, int y1, int x2, int y2, ColorP = DOS_WHITE, ColorP = DOS_HIGH_WHITE, ColorP = DOS_GRAY, int = 2, bool = false);
- virtual void obox(int x1, int y1, int x2, int y2, ColorP = WHITE);
+ virtual void obox(int x1, int y1, int x2, int y2, ColorP = DOS_WHITE);
virtual void obox3d(int x1, int y1, int x2, int y2, ColorP = DOS_HIGH_WHITE, ColorP = DOS_GRAY, bool = false);
- virtual void hline(int x1, int x2, int y, ColorP = WHITE);
+ virtual void hline(int x1, int x2, int y, ColorP = DOS_WHITE);
virtual void hline3d(int x1, int x2, int y, ColorP = DOS_HIGH_WHITE, ColorP = DOS_GRAY, bool = false);
- virtual void vline(int x, int y1, int y2, ColorP = WHITE);
+ virtual void vline(int x, int y1, int y2, ColorP = DOS_WHITE);
virtual void vline3d(int x, int y1, int y2, ColorP = DOS_HIGH_WHITE, ColorP = DOS_GRAY, bool = false);
virtual void window(int x1, int y1, int x2, int y2,
const String & title = "",
diff --git a/lib/font.cc b/lib/font.cc
index 93588bf..d878399 100644
--- a/lib/font.cc
+++ b/lib/font.cc
@@ -79,8 +79,27 @@ nbT = number of textures
*/
+mogltk::ColorP colorcached[16] = {
+ DOS_BLACK,
+ DOS_BLUE,
+ DOS_GREEN,
+ DOS_CYAN,
+ DOS_RED,
+ DOS_MAGENTA,
+ DOS_BRAWN,
+ DOS_WHITE,
+ DOS_GRAY,
+ DOS_HIGH_BLUE,
+ DOS_HIGH_GREEN,
+ DOS_HIGH_CYAN,
+ DOS_HIGH_RED,
+ DOS_HIGH_MAGENTA,
+ DOS_YELLOW,
+ DOS_HIGH_WHITE
+};
+
mogltk::font::font(Handle * ffont) : textcolor(255, 255, 255, 255), shadow(0), wspace(0) {
- int i;
+ int i, j;
nbentries = ffont->readU16();
flags = ffont->readU8();
@@ -104,9 +123,16 @@ mogltk::font::font(Handle * ffont) : textcolor(255, 255, 255, 255), shadow(0), w
printm(M_INFO, "Which makes %i texture(s), with %i char by texture, %i on X, and %i on Y\n", nbT, nbcT, nbcU, nbcV);
fonttex = (texture **) malloc(nbT * sizeof(texture *));
+ for (i = 0; i < 16; i++) {
+ fontcache[i] = (texture **) malloc(nbT * sizeof(texture *));
+ }
for (i = 0; i < nbT; i++) {
fonttex[i] = alloctexture();
+ for (j = 0; j < 15; j++) {
+ fontcache[j][i] = 0;
+ }
+ fontcache[15][i] = fonttex[i];
}
sizes = (Uint8 *) malloc(nbentries * sizeof(Uint8));
@@ -155,10 +181,14 @@ mogltk::font::font(Handle * ffont) : textcolor(255, 255, 255, 255), shadow(0), w
}
mogltk::font::~font() {
- int i;
- for (i = 0; i < nbT; i++) {
- delete fonttex[i];
- }
+ int i, j;
+ for (i = 0; i < nbT; i++)
+ for (j = 0; j < 16; j++)
+ if (fontcache[j][i])
+ delete fontcache[j][i];
+
+ for (i = 0; i < 16; i++)
+ free((void *&) fontcache[i]);
free((void *&) fonttex);
free(sizes);
@@ -174,7 +204,6 @@ void mogltk::font::drawentry(Uint16 entry, int x, int y, ColorP c) {
SDL_LockSurface(mogltk::engine::base_o->getsurface());
}
-#if 0
if (shadow) {
int os = shadow;
shadow = 0;
@@ -183,7 +212,8 @@ void mogltk::font::drawentry(Uint16 entry, int x, int y, ColorP c) {
shadow = os;
}
-#endif
+
+ checknbind(entry / nbcT, c);
y -= base;
@@ -321,3 +351,28 @@ mogltk::texture * mogltk::font::alloctexture() {
void mogltk::font::Bind(int f) {
fonttex[f]->Bind();
}
+
+void mogltk::font::checknbind(int index, ColorP c) {
+ int i, x, y;
+ ColorP oldmax = ColorP::Max, t;
+ ColorP::Max = c.c;
+ SDL_PixelFormat * f = fonttex[0]->GetSurface()->format;
+
+ for (i = 0; i < 15; i++)
+ if (c == colorcached[i])
+ break;
+
+ if (!fontcache[i][index]) {
+ fontcache[i][index] = alloctexture();
+ for (y = 0; y < 256; y++) {
+ for (x = 0; x < 256; x++) {
+ t.fromSDL(fontcache[15][index]->GetPixels()[(y << 8) + x], f);
+ fontcache[i][index]->GetPixels()[(y << 8) + x] = t.toSDL(f);
+ }
+ }
+ }
+
+ fonttex[index] = fontcache[i][index];
+
+ ColorP::Max = oldmax.c;
+}
diff --git a/lib/mcolor.cc b/lib/mcolor.cc
index 806a812..1c13717 100644
--- a/lib/mcolor.cc
+++ b/lib/mcolor.cc
@@ -16,9 +16,26 @@ void mogltk::ColorP::Bind() {
}
Uint32 mogltk::ColorP::toSDL(SDL_PixelFormat * f) {
- if (!f) {
+ if (!f)
f = mogltk::engine::base_o->getsurface()->format;
- }
return SDL_MapRGBA(f, MIN(MAX(c.R, Min.R), Max.R), MIN(MAX(c.G, Min.G), Max.G), MIN(MAX(c.B, Min.B), Max.B), MIN(MAX(c.A, Min.A), Max.A));
}
+
+void mogltk::ColorP::fromSDL(Uint32 p, SDL_PixelFormat * f) {
+ if (!f)
+ f = mogltk::engine::base_o->getsurface()->format;
+
+ SDL_GetRGBA(p, f, &c.R, &c.G, &c.B, &c.A);
+}
+
+void mogltk::ColorP::Norm() {
+ c.R = MIN(MAX(c.R, Min.R), Max.R);
+ c.G = MIN(MAX(c.R, Min.G), Max.G);
+ c.B = MIN(MAX(c.R, Min.B), Max.B);
+ c.A = MIN(MAX(c.R, Min.A), Max.A);
+}
+
+bool mogltk::ColorP::operator==(const ColorP & nc) {
+ return c == nc.c;
+}
diff --git a/lib/shape.cc b/lib/shape.cc
index b9bdd87..9ba4f0c 100644
--- a/lib/shape.cc
+++ b/lib/shape.cc
@@ -15,6 +15,9 @@ mogltk::fillwalker::fillwalker() {
mogltk::fillwalker::~fillwalker() {
}
+void mogltk::fillwalker::step(int x, int y) {
+}
+
mogltk::fill::fill() : header(0) {
}
@@ -28,12 +31,13 @@ void mogltk::fill::walk(fillwalker * w) {
}
void mogltk::fill::insert(int x, int y) {
- if (!header)
+ if (!header) {
new sline(y, this);
+ }
header->insert(x, y);
}
-mogltk::fill::sline::sline(int _y, fill * _header) : y(_y), pheader(0), header(_header) {
+mogltk::fill::sline::sline(int _y, fill * _header) : y(_y), header(_header), pheader(0) {
if (!header->header) {
header->header = this;
} else {
@@ -56,13 +60,13 @@ mogltk::fill::sline::sline(int _y, fill * _header) : y(_y), pheader(0), header(_
}
mogltk::fill::sline::~sline() {
- if (header)
- delete header;
+ if (pheader)
+ delete pheader;
if (next)
delete next;
}
-int mogltk::fill::sline::GetY() {
+int mogltk::fill::sline::GetY() const {
return y;
}
@@ -75,17 +79,88 @@ void mogltk::fill::sline::insert(int ax, int ay) {
else if (!pheader->look(ax))
new point(ax, this);
} else {
- f = look(y);
+ f = header->header->look(ay);
- if (!f)
- f = new sline(y, header);
+ if (!f) {
+ f = new sline(ay, header);
+ }
f->insert(ax, ay);
}
}
void mogltk::fill::sline::walk(fillwalker * w) {
+ if (pheader)
+ pheader->walk(w);
+ if (next)
+ next->walk(w);
+}
+
+mogltk::fill::sline::point::point(int _x, sline * _header) : x(_x), header(_header) {
+ if (!header->pheader) {
+ header->pheader = this;
+ } else {
+ if (header->pheader->x > x) {
+ next = header->pheader;
+ header->pheader = this;
+ } else {
+ point * p;
+ for (p = header->pheader; p->next; p = p->next) {
+ if (p->next->x > x) {
+ next = p->next;
+ p->next = this;
+ return;
+ }
+ }
+ p->next = this;
+ next = 0;
+ }
+ }
+}
+
+mogltk::fill::sline::point::~point() {
+ if (next)
+ delete next;
+}
+
+int mogltk::fill::sline::point::GetX() const {
+ return x;
+}
+
+int mogltk::fill::sline::point::GetY() const {
+ return header->GetY();
+}
+
+void mogltk::fill::sline::point::walk(fillwalker * w) {
w->step(GetX(), GetY());
+ if (next)
+ next->walk(w);
+}
+
+mogltk::fill::sline::point * mogltk::fill::sline::point::look(int _x) {
+ if (x > _x)
+ return 0;
+
+ if (x == _x)
+ return this;
+
+ if (!next)
+ return 0;
+
+ return next->look(_x);
+}
+
+mogltk::fill::sline * mogltk::fill::sline::look(int _y) {
+ if (y > _y)
+ return 0;
+
+ if (y == _y)
+ return this;
+
+ if (!next)
+ return 0;
+
+ return next->look(_y);
}
void mogltk::shape::box(int x1, int y1, int x2, int y2, ColorP c) {
@@ -205,32 +280,74 @@ void mogltk::shape::circle(int x0, int y0, int r, ColorP c) {
LEAVE;
}
-void mogltk::shape::pcircle(int x0, int y0, int r, ColorP c) {
- ENTER;
-
+mogltk::fill * mogltk::shape::fcircle(int x0, int y0, int r) {
int x = 0;
int y = r - 1;
int d = 3 - 2 * r;
int dI = 10 - 4 * r;
int rI = 6;
+ mogltk::fill * f = new fill();
+ bool t = true;
while (x <= y) {
- hline(x0 - x, x0 + x, y0 + y, c);
- hline(x0 - x, x0 + x, y0 - y, c);
- hline(x0 - y, x0 + y, y0 + x, c);
- hline(x0 - y, x0 + y, y0 - x, c);
+ if (t) {
+ f->insert(x0 - x, y0 - y);
+ f->insert(x0 + x, y0 - y);
+ f->insert(x0 - x, y0 + y);
+ f->insert(x0 + x, y0 + y);
+ }
+ f->insert(x0 - y, y0 - x);
+ f->insert(x0 + y, y0 - x);
+ f->insert(x0 - y, y0 + x);
+ f->insert(x0 + y, y0 + x);
if (d >= 0) {
d += dI;
dI += 8;
y -= 1;
+ t = true;
} else {
d += rI;
dI += 4;
+ t = false;
}
rI += 4;
x += 1;
}
+ return f;
+}
+void mogltk::shape::pcircle(int x, int y, int r, ColorP c) {
+ fill * f = fcircle(x, y, r);
+ fdraw(f, c);
+ delete f;
+}
+
+class filldrawer : public mogltk::fillwalker {
+ public:
+ filldrawer(mogltk::shape * _s, mogltk::ColorP _c = DOS_WHITE) : s(_s), c(_c), oldx(-1), oldy(-1) { }
+ virtual ~filldrawer() { }
+ virtual void step(int x, int y) {
+ if (oldy != y)
+ oldx = -1;
+ if (oldx == -1) {
+ oldx = x;
+ } else {
+ s->hline(oldx, x, y, c);
+ oldx = -1;
+ }
+ oldy = y;
+ }
+ private:
+ mogltk::shape * s;
+ mogltk::ColorP c;
+ int oldx, oldy;
+};
+
+void mogltk::shape::fdraw(fill * f, ColorP c) {
+ ENTER;
+ filldrawer * w = new filldrawer(this, c);
+ f->walk(w);
+ delete w;
LEAVE;
}