Let each screen get width and height in as a parameter on draw() instead of hardcodin...
authorSteinar H. Gunderson <sesse@samfundet.no>
Tue, 1 Mar 2005 03:04:18 +0000 (03:04 +0000)
committerSteinar H. Gunderson <sesse@samfundet.no>
Tue, 1 Mar 2005 03:04:18 +0000 (03:04 +0000)
This is quite ugly at places, but it seems to work well. This isn't really done for the speed
boost (although fades etc. are quite a lot smoother when the split screen can do all its work
in the native resolution instead of fading and _then_ downscaling), but primarily for the
legibility (ie. let FreeType _understand_ that we are on a smaller screen, so get hinting etc.
right), which seems to have improved by quite a lot (the overall "polish" look is a bit down,
though, probably the autohinter is evil).

19:30-04:00

12 files changed:
bigscreen/ccbs_bigscreen.cpp
bigscreen/groupscreen.cpp
bigscreen/groupscreen.h
bigscreen/rotatescreen.cpp
bigscreen/rotatescreen.h
bigscreen/screen.h
bigscreen/splitscreen.cpp
bigscreen/splitscreen.h
bigscreen/top10scorescreen.cpp
bigscreen/top10scorescreen.h
bigscreen/top5chosenscreen.cpp
bigscreen/top5chosenscreen.h

index b183ddd..dcf8a78 100644 (file)
@@ -116,7 +116,7 @@ void main_loop(pqxx::connection &conn)
        }
 
        if (mainscreen && mainscreen->check_invalidated()) {
-               mainscreen->draw(framebuf);
+               mainscreen->draw(framebuf, SCREEN_WIDTH, SCREEN_HEIGHT);
                ptc_update(framebuf);
                conn.await_notification(0, 10000);
        } else {
index 9d3b9e7..713c3b9 100644 (file)
@@ -36,11 +36,12 @@ bool GroupScreen::check_invalidated()
        return needs_update;
 }
 
-void GroupScreen::draw(unsigned char *buf)
+void GroupScreen::draw(unsigned char *buf, unsigned width, unsigned height)
 {
        std::vector<TextDefer> td;
        
        scores_changed.reset_flag();
+       set_screen_size(width, height);
 
        /*
         * We'll probably need some values from here later on (although not all), just fetch them
@@ -54,7 +55,7 @@ void GroupScreen::draw(unsigned char *buf)
        conn.perform(FetchGroup(tournament, round, parallel, &group));
        gettimeofday(&last_updated, NULL);
 
-       memset(buf, 0, SCREEN_WIDTH * SCREEN_HEIGHT * 4);
+       memset(buf, 0, width * height * 4);
 
        // main heading
        char heading[64];
@@ -80,40 +81,40 @@ void GroupScreen::draw(unsigned char *buf)
        // Find out how wide each column has to be. First try unlimited width (ie.
        // long titles for everything); if that gets too long, try again with short
        // titles for chosen songs.
-       unsigned width[16], num_scores;
+       unsigned colwidth[16], num_scores;
        unsigned max_num_width = my_draw_text("8888", NULL, 22.0);
-       unsigned sumwidth;
+       unsigned sumcolwidth;
        for (unsigned mode = 0; mode < 2; ++mode) {
                for (unsigned i = 0; i < 16; ++i)
-                       width[i] = 0;
+                       colwidth[i] = 0;
 
                for (std::vector<Player>::const_iterator i = group.players.begin(); i != group.players.end(); ++i) {
                        unsigned col = 1;
-                       width[0] = std::max(width[0], my_draw_text(i->nick, NULL, 18.0));
+                       colwidth[0] = std::max(colwidth[0], my_draw_text(i->nick, NULL, 18.0));
 
                        for (std::vector<Score>::const_iterator j = i->scores.begin(); j != i->scores.end(); ++j, ++col) {
                                if (j->chosen) {
-                                       width[col] = std::max(width[col], my_draw_text((mode == 0) ? j->song.title : j->song.short_title, NULL, 12.0) + 
+                                       colwidth[col] = std::max(colwidth[col], my_draw_text((mode == 0) ? j->song.title : j->song.short_title, NULL, 12.0) + 
                                                        max_num_width + 10);
                                } else {                
-                                       width[col] = std::max(width[col], my_draw_text(j->song.short_title, NULL, 12.0));
-                                       width[col] = std::max(width[col], max_num_width);
+                                       colwidth[col] = std::max(colwidth[col], my_draw_text(j->song.short_title, NULL, 12.0));
+                                       colwidth[col] = std::max(colwidth[col], max_num_width);
                                }
                        }
                }
 
                num_scores = group.players[0].scores.size();
 
-               width[num_scores + 1] = std::max(my_draw_text("Total", NULL, 12.0), max_num_width);
-               width[num_scores + 2] = my_draw_text("Rank", NULL, 12.0);
+               colwidth[num_scores + 1] = std::max(my_draw_text("Total", NULL, 12.0), max_num_width);
+               colwidth[num_scores + 2] = my_draw_text("Rank", NULL, 12.0);
 
                // if we're at long titles and that works, don't try the short ones
-               sumwidth = 0;
+               sumcolwidth = 0;
                        
                for (unsigned i = 0; i <= num_scores + 2; ++i)
-                       sumwidth += width[i] + 20;
+                       sumcolwidth += colwidth[i] + 20;
                        
-               if (sumwidth < 780)
+               if (sumcolwidth < 780)
                        break;
        }
 
@@ -121,7 +122,7 @@ void GroupScreen::draw(unsigned char *buf)
         * If we have space to go, distribute as much as we can to the chosen song column, so we won't have
         * total and rank jumping around.
         */
-       if (sumwidth < 780) {
+       if (sumcolwidth < 780) {
                int first_chosen_col = -1;
                unsigned col = 1;
 
@@ -133,24 +134,24 @@ void GroupScreen::draw(unsigned char *buf)
                }
 
                if (first_chosen_col != -1) {
-                       width[first_chosen_col] += 780 - sumwidth;
+                       colwidth[first_chosen_col] += 780 - sumcolwidth;
                }
        }
 
        // make column headings from the first player's songs
        unsigned col = 1;
-       unsigned x = 40 + width[0];
+       unsigned x = 40 + colwidth[0];
        for (std::vector<Score>::const_iterator i = group.players[0].scores.begin(); i != group.players[0].scores.end(); ++i, ++col) {
                if (!i->chosen) {
                        unsigned this_width = my_draw_text(i->song.short_title, NULL, 12.0);
-                       my_draw_text_deferred(td, i->song.short_title, 12.0, x + width[col] / 2 - this_width / 2, 100);
+                       my_draw_text_deferred(td, i->song.short_title, 12.0, x + colwidth[col] / 2 - this_width / 2, 100);
                }
-               x += width[col] + 20;
+               x += colwidth[col] + 20;
        }
 
-       my_draw_text_deferred(td, "Total", 12.0, x + width[num_scores + 1] / 2 - my_draw_text("Total", NULL, 12.0) / 2, 100);
-       x += width[num_scores + 1] + 20;
-       my_draw_text_deferred(td, "Rank", 12.0, x + width[num_scores + 2] / 2 - my_draw_text("Rank", NULL, 12.0) / 2, 100);
+       my_draw_text_deferred(td, "Total", 12.0, x + colwidth[num_scores + 1] / 2 - my_draw_text("Total", NULL, 12.0) / 2, 100);
+       x += colwidth[num_scores + 1] + 20;
+       my_draw_text_deferred(td, "Rank", 12.0, x + colwidth[num_scores + 2] / 2 - my_draw_text("Rank", NULL, 12.0) / 2, 100);
        
        // show all the players and the scores
        unsigned num_players_this_machine = (group.players.size() + num_machines - machine - 1) / num_machines;
@@ -164,7 +165,7 @@ void GroupScreen::draw(unsigned char *buf)
 
                my_draw_text_deferred(td, i->nick, 18.0, 20, y);
 
-               unsigned x = 40 + width[0];
+               unsigned x = 40 + colwidth[0];
 
                unsigned col = 1;
                for (std::vector<Score>::const_iterator j = i->scores.begin(); j != i->scores.end(); ++j, ++col) {
@@ -178,15 +179,15 @@ void GroupScreen::draw(unsigned char *buf)
                                my_draw_text_deferred(td, text, 22.0, x + max_num_width - this_width, y);
 
                                // draw the long name if we can, otherwise use the short one
-                               if (my_draw_text(j->song.title, NULL, 12.0) > (width[col] - 10 - max_num_width)) {
+                               if (my_draw_text(j->song.title, NULL, 12.0) > (colwidth[col] - 10 - max_num_width)) {
                                        my_draw_text_deferred(td, j->song.short_title, 12.0, x + max_num_width + 10, y);
                                } else {
                                        my_draw_text_deferred(td, j->song.title, 12.0, x + max_num_width + 10, y);
                                }
                        } else {
-                               my_draw_text_deferred(td, text, 22.0, x + width[col] / 2 - this_width / 2, y);
+                               my_draw_text_deferred(td, text, 22.0, x + colwidth[col] / 2 - this_width / 2, y);
                        }
-                       x += width[col] + 20;
+                       x += colwidth[col] + 20;
                }
 
                // draw total
@@ -195,8 +196,8 @@ void GroupScreen::draw(unsigned char *buf)
                        std::sprintf(text, "%u", i->total);
                        
                        unsigned this_width = my_draw_text(text, NULL, 22.0);
-                       my_draw_text_deferred(td, text, 22.0, x + width[num_scores + 1] / 2 - this_width / 2, y);
-                       x += width[num_scores + 1] + 20;
+                       my_draw_text_deferred(td, text, 22.0, x + colwidth[num_scores + 1] / 2 - this_width / 2, y);
+                       x += colwidth[num_scores + 1] + 20;
                }
 
                if (show_players > 7)
@@ -275,7 +276,7 @@ void GroupScreen::draw(unsigned char *buf)
                        continue;
                
                unsigned this_width = my_draw_text(text, NULL, 22.0);
-               my_draw_text_deferred(td, text, 22.0, x + width[num_scores + 2] / 2 - this_width / 2, y);
+               my_draw_text_deferred(td, text, 22.0, x + colwidth[num_scores + 2] / 2 - this_width / 2, y);
 
                if (show_players > 7)
                        y += 40 - (show_players - 7) * 4;
index 1bff23f..fb27787 100644 (file)
@@ -26,7 +26,7 @@ public:
        virtual ~GroupScreen();
 
        bool check_invalidated();
-       void draw(unsigned char *buf);
+       void draw(unsigned char *buf, unsigned width, unsigned height);
        int get_priority();
 };
 
index 78a0e78..4fc9fa0 100644 (file)
@@ -1,10 +1,12 @@
+/* NOTE: this class will _NOT_ handle resolution changes cleanly. You have been warned. :-) */
+
+#include <cstdio>
 #include <cstring>
 #include "rotatescreen.h"
 
 RotateScreen::RotateScreen()
-       : valid(false), current_screen(0), in_fade(false)
+       : fadefrom_buf(NULL), valid(false), current_screen(0), in_fade(false)
 {
-       fadefrom_buf = new unsigned char[SCREEN_WIDTH * SCREEN_HEIGHT * 4];
 }
 
 RotateScreen::~RotateScreen()
@@ -24,15 +26,27 @@ bool RotateScreen::check_invalidated()
                return false;
        
        for (unsigned i = 0; i < subscreens.size(); ++i) {
-               if (subscreens[i].screen->check_invalidated())
+               if (subscreens[i].buf == NULL || subscreens[i].screen->check_invalidated())
                        return true;
        }
 
        return false;
 }
 
-void RotateScreen::draw(unsigned char *buf)
+void RotateScreen::draw(unsigned char *buf, unsigned width, unsigned height)
 {
+       // see line 1 for all of this
+       if (fadefrom_buf == NULL) {
+               fadefrom_buf = new unsigned char[width * height * 4];
+       }
+       for (std::vector<Subscreen>::iterator i = subscreens.begin(); i != subscreens.end(); ++i) {
+               if (i->buf == NULL) {
+                       i->buf = new unsigned char[width * height * 4];
+                       i->screen->draw(i->buf, width, height);
+               }
+       }
+       // end of "line 1"-code :-)
+       
        bool force = false;
 
        if (subscreens.size() == 0) {
@@ -58,9 +72,9 @@ void RotateScreen::draw(unsigned char *buf)
                        in_fade = false;
 
                        // ugly hack here? :-)
-                       subscreens[current_screen].screen->draw(subscreens[current_screen].buf);
+                       subscreens[current_screen].screen->draw(subscreens[current_screen].buf, width, height);
                        
-                       memcpy(buf, subscreens[current_screen].buf, SCREEN_WIDTH * SCREEN_HEIGHT * 4);
+                       memcpy(buf, subscreens[current_screen].buf, width * height * 4);
                } else {
                        // find the fade factors
                        int fr, fg, fb, fa;
@@ -80,7 +94,7 @@ void RotateScreen::draw(unsigned char *buf)
 
                        if (fade_to_new_info && elapsed_fade >= 0.5) {
                                // fade G&B to be = R
-                               for (unsigned i = 0; i < SCREEN_WIDTH * SCREEN_HEIGHT; ++i) {
+                               for (unsigned i = 0; i < width * height; ++i) {
                                        dptr[0] = sptr2[0] + (((int(sptr2[2]) - int(sptr2[0])) * fb) >> 8);
                                        dptr[1] = sptr2[1] + (((int(sptr2[2]) - int(sptr2[1])) * fg) >> 8);
                                        dptr[2] = sptr2[2];
@@ -89,7 +103,7 @@ void RotateScreen::draw(unsigned char *buf)
                                        sptr1 += 4, sptr2 += 4, dptr += 4;
                                }
                        } else {
-                               for (unsigned i = 0; i < SCREEN_WIDTH * SCREEN_HEIGHT; ++i) {
+                               for (unsigned i = 0; i < width * height; ++i) {
                                        dptr[0] = sptr1[0] + (((int(sptr2[0]) - int(sptr1[0])) * fb) >> 8);
                                        dptr[1] = sptr1[1] + (((int(sptr2[1]) - int(sptr1[1])) * fg) >> 8);
                                        dptr[2] = sptr1[2] + (((int(sptr2[2]) - int(sptr1[2])) * fr) >> 8);
@@ -126,10 +140,11 @@ void RotateScreen::draw(unsigned char *buf)
                        fade_found_start_time = false;
                        fade_to_new_info = force;
                        
-                       memcpy(fadefrom_buf, subscreens[old_current_screen].buf, SCREEN_WIDTH * SCREEN_HEIGHT * 4);
+                       memcpy(fadefrom_buf, subscreens[old_current_screen].buf, width * height * 4);
 
-                       if (subscreens[current_screen].screen->check_invalidated())
-                               subscreens[current_screen].screen->draw(subscreens[current_screen].buf);
+                       if (subscreens[current_screen].screen->check_invalidated()) {
+                               subscreens[current_screen].screen->draw(subscreens[current_screen].buf, width, height);
+                       }
                }
        }
 
@@ -170,11 +185,9 @@ bool RotateScreen::can_update()
 void RotateScreen::add_screen(GenericScreen *screen)
 {
        Subscreen ss;
-       ss.buf = new unsigned char[SCREEN_WIDTH * SCREEN_HEIGHT * 4];
+       ss.buf = NULL;
        ss.screen = screen;
 
-       screen->draw(ss.buf);
-       
        subscreens.push_back(ss);
 }
 
index 6a5c35f..6f53e24 100644 (file)
@@ -33,7 +33,7 @@ public:
        virtual ~RotateScreen();
 
        bool check_invalidated();
-       void draw(unsigned char *buf);
+       void draw(unsigned char *buf, unsigned width, unsigned height);
 
        void add_screen(GenericScreen *screen);
 //     void remove_screen(GenericScreen *screen);
index e519279..bf3deba 100644 (file)
@@ -11,7 +11,7 @@ protected:
 public:
        virtual ~GenericScreen();
        virtual bool check_invalidated() = 0;
-       virtual void draw(unsigned char *buf) = 0;
+       virtual void draw(unsigned char *buf, unsigned width, unsigned height) = 0;
        virtual int get_priority();
 };
 
index 9d569b1..e4bb4c4 100644 (file)
@@ -1,3 +1,5 @@
+/* NOTE: this class will _NOT_ handle resolution changes cleanly. You have been warned. :-) */
+
 #include <cstring>
 #include "splitscreen.h"
 
@@ -9,10 +11,8 @@ SplitScreen::SplitScreen(GenericScreen *s1, GenericScreen *s2, GenericScreen *s3
        subscreens[2] = s3;
        subscreens[3] = s4;
 
-       memset(subbufs[0], 0, SCREEN_WIDTH*SCREEN_HEIGHT*4);
-       memset(subbufs[1], 0, SCREEN_WIDTH*SCREEN_HEIGHT*4);
-       memset(subbufs[2], 0, SCREEN_WIDTH*SCREEN_HEIGHT*4);
-       memset(subbufs[3], 0, SCREEN_WIDTH*SCREEN_HEIGHT*4);
+       for (unsigned i = 0; i < 4; ++i)
+               subbufs[i] = NULL;
 }
 
 SplitScreen::~SplitScreen()
@@ -32,58 +32,52 @@ bool SplitScreen::check_invalidated()
        return false;
 }
 
-void SplitScreen::draw(unsigned char *buf)
+void SplitScreen::draw(unsigned char *buf, unsigned width, unsigned height)
 {
        for (unsigned i = 0; i < 4; ++i) {
+               if (subbufs[i] == NULL) {  // see line 1
+                       subbufs[i] = new unsigned char[width/2 * height/2 * 4];
+                       memset(subbufs[i], 0, width/2 * height/2 * 4);
+               }
                if (subscreens[i] && subscreens[i]->check_invalidated()) {
-                       subscreens[i]->draw(subbufs[i]);
+                       subscreens[i]->draw(subbufs[i], width/2, height/2);
                }
        }
        
-       downscale_2x2(buf, subbufs[0]);
-       downscale_2x2(buf + (SCREEN_WIDTH/2) * 4, subbufs[1]);
-       downscale_2x2(buf + SCREEN_WIDTH * (SCREEN_HEIGHT/2) * 4, subbufs[2]);
-       downscale_2x2(buf + SCREEN_WIDTH * (SCREEN_HEIGHT/2) * 4 + (SCREEN_WIDTH/2) * 4, subbufs[3]); 
-
+       copy_subscreen(buf, subbufs[0], width, height);
+       copy_subscreen(buf + (width/2) * 4, subbufs[1], width, height);
+       copy_subscreen(buf + width * (height/2) * 4, subbufs[2], width, height);
+       copy_subscreen(buf + width * (height/2) * 4 + (width/2) * 4, subbufs[3], width, height); 
+       
        // make divider lines
-       unsigned char *ptr = buf + (SCREEN_HEIGHT/2) * SCREEN_WIDTH * 4;
-       for (unsigned x = 0; x < SCREEN_WIDTH; ++x) {
+       unsigned char *ptr = buf + (height/2) * width * 4;
+       for (unsigned x = 0; x < width; ++x) {
                *ptr++ = 255;
                *ptr++ = 255;
                *ptr++ = 255;
                *ptr++ = 0;
        }
        
-       ptr = buf + (SCREEN_WIDTH/2) * 4;
-       for (unsigned y = 0; y < SCREEN_HEIGHT; ++y) {
+       ptr = buf + (width/2) * 4;
+       for (unsigned y = 0; y < height; ++y) {
                ptr[0] = 255;
                ptr[1] = 255;
                ptr[2] = 255;
                ptr[3] = 0;
 
-               ptr += SCREEN_WIDTH * 4;
+               ptr += width * 4;
        }
        
        valid = true;
 }
-       
-// simple box filter (blah)
-void SplitScreen::downscale_2x2(unsigned char *dst, unsigned char *src)
+
+void SplitScreen::copy_subscreen(unsigned char *dst, unsigned char *src, unsigned width, unsigned height)
 {
-       for (unsigned y = 0; y < (SCREEN_HEIGHT/2); ++y) {
-               unsigned char *sptr1 = src + (y*2) * SCREEN_WIDTH * 4;
-               unsigned char *sptr2 = src + (y*2+1) * SCREEN_WIDTH * 4;
-               unsigned char *dptr = dst + y * SCREEN_WIDTH * 4;
-               
-               for (unsigned x = 0; x < (SCREEN_WIDTH/2); ++x) {
-                       *dptr++ = (sptr1[0] + sptr1[4] + sptr2[0] + sptr2[4]) >> 2;  // red
-                       *dptr++ = (sptr1[1] + sptr1[5] + sptr2[1] + sptr2[5]) >> 2;  // green
-                       *dptr++ = (sptr1[2] + sptr1[6] + sptr2[2] + sptr2[6]) >> 2;  // blue
-                       *dptr++ = (sptr1[3] + sptr1[7] + sptr2[3] + sptr2[7]) >> 2;  // alpha
+       for (unsigned y = 0; y < height/2; ++y) {
+               unsigned char *sptr = src + y * width/2 * 4;
+               unsigned char *dptr = dst + y * width * 4;
 
-                       sptr1 += 8;
-                       sptr2 += 8;
-               }
+               memcpy(dptr, sptr, width/2 * 4);
        }
 }
-
+       
index bf68b82..28a659e 100644 (file)
@@ -6,18 +6,18 @@
 /* A 4x4 split class */
 class SplitScreen : public GenericScreen {
 private:
-       unsigned char subbufs[4][SCREEN_WIDTH * SCREEN_HEIGHT * 4];
+       unsigned char *subbufs[4];
        GenericScreen *subscreens[4];
        bool valid;
 
-       void downscale_2x2(unsigned char *dst, unsigned char *src);
+       void copy_subscreen(unsigned char *dst, unsigned char *src, unsigned width, unsigned height);
        
 public:
        SplitScreen(GenericScreen *s1, GenericScreen *s2, GenericScreen *s3, GenericScreen *s4);
        virtual ~SplitScreen();
 
        bool check_invalidated();
-       void draw(unsigned char *buf);
+       void draw(unsigned char *buf, unsigned width, unsigned height);
 };
 
 #endif /* !defined(_SPLITSCREEN_H) */
index 66306b4..c298dbb 100644 (file)
@@ -34,10 +34,11 @@ bool Top10ScoreScreen::check_invalidated()
        return false;
 }
 
-void Top10ScoreScreen::draw(unsigned char *buf)
+void Top10ScoreScreen::draw(unsigned char *buf, unsigned width, unsigned height)
 {
        scores_changed.reset_flag();
-       memset(buf, 0, SCREEN_WIDTH * SCREEN_HEIGHT * 4);
+       memset(buf, 0, width * height * 4);
+       set_screen_size(width, height);
 
        // fetch the top 10 scores
        std::vector<TopScore> scores;
index 2a32901..439bfeb 100644 (file)
@@ -22,7 +22,7 @@ public:
        virtual ~Top10ScoreScreen();
 
        bool check_invalidated();
-       void draw(unsigned char *buf);
+       void draw(unsigned char *buf, unsigned width, unsigned height);
        int get_priority();
 };
 
index 84b54ea..9057bc1 100644 (file)
@@ -34,10 +34,11 @@ bool Top5ChosenScreen::check_invalidated()
        return false;
 }
 
-void Top5ChosenScreen::draw(unsigned char *buf)
+void Top5ChosenScreen::draw(unsigned char *buf, unsigned width, unsigned height)
 {
        scores_changed.reset_flag();
-       memset(buf, 0, SCREEN_WIDTH * SCREEN_HEIGHT * 4);
+       memset(buf, 0, width * height * 4);
+       set_screen_size(width, height);
 
        // fetch the top 5 chosen songs
        std::vector<TopChosen> scores;
index af2df73..8f5bd5f 100644 (file)
@@ -22,7 +22,7 @@ public:
        virtual ~Top5ChosenScreen();
 
        bool check_invalidated();
-       void draw(unsigned char *buf);
+       void draw(unsigned char *buf, unsigned width, unsigned height);
 };
 
 #endif /* !defined(_TOP5CHOSENSCREEN_H) */