From 09ae4d8636130d4c86ab3f8df8f823482f948f97 Mon Sep 17 00:00:00 2001 From: "Steinar H. Gunderson" Date: Tue, 1 Mar 2005 03:04:18 +0000 Subject: [PATCH] Let each screen get width and height in as a parameter on draw() instead of hardcoding it to SCREEN_WIDTH * SCREEN_HEIGHT. 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 --- bigscreen/ccbs_bigscreen.cpp | 2 +- bigscreen/groupscreen.cpp | 59 +++++++++++++++++---------------- bigscreen/groupscreen.h | 2 +- bigscreen/rotatescreen.cpp | 41 +++++++++++++++-------- bigscreen/rotatescreen.h | 2 +- bigscreen/screen.h | 2 +- bigscreen/splitscreen.cpp | 60 +++++++++++++++------------------- bigscreen/splitscreen.h | 6 ++-- bigscreen/top10scorescreen.cpp | 5 +-- bigscreen/top10scorescreen.h | 2 +- bigscreen/top5chosenscreen.cpp | 5 +-- bigscreen/top5chosenscreen.h | 2 +- 12 files changed, 99 insertions(+), 89 deletions(-) diff --git a/bigscreen/ccbs_bigscreen.cpp b/bigscreen/ccbs_bigscreen.cpp index b183ddd..dcf8a78 100644 --- a/bigscreen/ccbs_bigscreen.cpp +++ b/bigscreen/ccbs_bigscreen.cpp @@ -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 { diff --git a/bigscreen/groupscreen.cpp b/bigscreen/groupscreen.cpp index 9d3b9e7..713c3b9 100644 --- a/bigscreen/groupscreen.cpp +++ b/bigscreen/groupscreen.cpp @@ -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 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::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::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::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::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; diff --git a/bigscreen/groupscreen.h b/bigscreen/groupscreen.h index 1bff23f..fb27787 100644 --- a/bigscreen/groupscreen.h +++ b/bigscreen/groupscreen.h @@ -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(); }; diff --git a/bigscreen/rotatescreen.cpp b/bigscreen/rotatescreen.cpp index 78a0e78..4fc9fa0 100644 --- a/bigscreen/rotatescreen.cpp +++ b/bigscreen/rotatescreen.cpp @@ -1,10 +1,12 @@ +/* NOTE: this class will _NOT_ handle resolution changes cleanly. You have been warned. :-) */ + +#include #include #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::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); } diff --git a/bigscreen/rotatescreen.h b/bigscreen/rotatescreen.h index 6a5c35f..6f53e24 100644 --- a/bigscreen/rotatescreen.h +++ b/bigscreen/rotatescreen.h @@ -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); diff --git a/bigscreen/screen.h b/bigscreen/screen.h index e519279..bf3deba 100644 --- a/bigscreen/screen.h +++ b/bigscreen/screen.h @@ -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(); }; diff --git a/bigscreen/splitscreen.cpp b/bigscreen/splitscreen.cpp index 9d569b1..e4bb4c4 100644 --- a/bigscreen/splitscreen.cpp +++ b/bigscreen/splitscreen.cpp @@ -1,3 +1,5 @@ +/* NOTE: this class will _NOT_ handle resolution changes cleanly. You have been warned. :-) */ + #include #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); } } - + diff --git a/bigscreen/splitscreen.h b/bigscreen/splitscreen.h index bf68b82..28a659e 100644 --- a/bigscreen/splitscreen.h +++ b/bigscreen/splitscreen.h @@ -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) */ diff --git a/bigscreen/top10scorescreen.cpp b/bigscreen/top10scorescreen.cpp index 66306b4..c298dbb 100644 --- a/bigscreen/top10scorescreen.cpp +++ b/bigscreen/top10scorescreen.cpp @@ -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 scores; diff --git a/bigscreen/top10scorescreen.h b/bigscreen/top10scorescreen.h index 2a32901..439bfeb 100644 --- a/bigscreen/top10scorescreen.h +++ b/bigscreen/top10scorescreen.h @@ -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(); }; diff --git a/bigscreen/top5chosenscreen.cpp b/bigscreen/top5chosenscreen.cpp index 84b54ea..9057bc1 100644 --- a/bigscreen/top5chosenscreen.cpp +++ b/bigscreen/top5chosenscreen.cpp @@ -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 scores; diff --git a/bigscreen/top5chosenscreen.h b/bigscreen/top5chosenscreen.h index af2df73..8f5bd5f 100644 --- a/bigscreen/top5chosenscreen.h +++ b/bigscreen/top5chosenscreen.h @@ -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) */ -- 2.39.2