diff options
-rw-r--r-- | include/font.h | 2 | ||||
-rw-r--r-- | include/mcolor.h | 5 | ||||
-rw-r--r-- | include/shape.h | 18 | ||||
-rw-r--r-- | lib/font.cc | 69 | ||||
-rw-r--r-- | lib/mcolor.cc | 21 | ||||
-rw-r--r-- | lib/shape.cc | 147 |
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; } |