diff --git a/direct/src/plugin/Sources.pp b/direct/src/plugin/Sources.pp index 86f4cd8aba..be639ea6bb 100644 --- a/direct/src/plugin/Sources.pp +++ b/direct/src/plugin/Sources.pp @@ -33,6 +33,7 @@ handleStream.cxx handleStream.h handleStream.I \ handleStreamBuf.cxx handleStreamBuf.h handleStreamBuf.I \ mkdir_complete.cxx mkdir_complete.h \ + parse_color.cxx parse_color.h \ p3d_lock.h p3d_plugin.h \ p3d_plugin_config.h \ p3d_plugin_common.h \ @@ -182,7 +183,8 @@ $[if $[IS_OSX],find_root_dir_assist.mm] \ is_pathsep.h is_pathsep.I \ mkdir_complete.cxx mkdir_complete.h \ - get_twirl_data.cxx get_twirl_data.h + get_twirl_data.cxx get_twirl_data.h \ + parse_color.cxx parse_color.h #begin static_lib_target // diff --git a/direct/src/plugin/get_twirl_data.cxx b/direct/src/plugin/get_twirl_data.cxx index 86c18540be..30ef249289 100755 --- a/direct/src/plugin/get_twirl_data.cxx +++ b/direct/src/plugin/get_twirl_data.cxx @@ -689,19 +689,25 @@ static const unsigned char * const twirl_data[3] = { //////////////////////////////////////////////////////////////////// // Function: get_twirl_data // Description: Fills the indicated data array with a string of -// twirl_width * twirl_height bytes, representing the -// grayscale pixel values of the twirl_width x +// twirl_width * twirl_height * 3 bytes, representing +// the RGB pixel values of the twirl_width x // twirl_height image at frame number step of -// twirl_num_steps frames. Returns true on success, -// false on failure. +// twirl_num_steps frames. The specified fg and bg +// colors are applied to the array appropriately. +// +// Returns true on success, false on failure. On false, +// the array is initialized with zero. // // You must pass data_length = twirl_width * -// twirl_height; this value is passed as a sanity check -// on array size. You should pass step so that 0 <= -// step < twirl_num_steps. +// twirl_height * 3; this value is passed as a sanity +// check on array size. You should pass step so that 0 +// <= step < twirl_num_steps. //////////////////////////////////////////////////////////////////// bool -get_twirl_data(unsigned char data[], size_t data_length, int step) { +get_twirl_data(unsigned char data[], size_t data_length, int step, + int fg_r, int fg_g, int fg_b, + int bg_r, int bg_g, int bg_b) { + if (step < 0 || step >= twirl_num_steps) { memset(data, 0, data_length); return false; @@ -715,6 +721,7 @@ get_twirl_data(unsigned char data[], size_t data_length, int step) { const unsigned char *in_data = twirl_data[flip._index]; for (int yi = 0; yi < twirl_height; ++yi) { + const unsigned char *sp = &in_data[yi * twirl_width]; for (int xi = 0; xi < twirl_width; ++xi) { int xo = xi; int yo = yi; @@ -729,8 +736,15 @@ get_twirl_data(unsigned char data[], size_t data_length, int step) { xo = yo; yo = t; } + unsigned char *dp = &data[yo * twirl_width * 3]; + dp += 3 * xo; - data[yo * twirl_width + xo] = in_data[yi * twirl_width + xi]; + double t = (double)(*sp) / 255.0; + ++sp; + + dp[0] = (unsigned char)(fg_r + t * (bg_r - fg_r)); + dp[1] = (unsigned char)(fg_g + t * (bg_g - fg_g)); + dp[2] = (unsigned char)(fg_b + t * (bg_b - fg_b)); } } diff --git a/direct/src/plugin/get_twirl_data.h b/direct/src/plugin/get_twirl_data.h index 31bb16c29c..f9c9d81577 100755 --- a/direct/src/plugin/get_twirl_data.h +++ b/direct/src/plugin/get_twirl_data.h @@ -15,13 +15,15 @@ #ifndef GET_TWIRL_DATA_H #define GET_TWIRL_DATA_H -#include "stddef.h" +#include static const int twirl_width = 48; static const int twirl_height = 48; static const int twirl_num_steps = 12; -bool get_twirl_data(unsigned char data[], size_t data_length, int step); +bool get_twirl_data(unsigned char data[], size_t data_length, int step, + int fg_r, int fg_g, int fg_b, + int bg_r, int bg_g, int bg_b); #endif diff --git a/direct/src/plugin/p3dInstance.cxx b/direct/src/plugin/p3dInstance.cxx index 1f42fd3364..912dc12278 100644 --- a/direct/src/plugin/p3dInstance.cxx +++ b/direct/src/plugin/p3dInstance.cxx @@ -26,6 +26,7 @@ #include "p3dUndefinedObject.h" #include "p3dMultifileReader.h" #include "p3dTemporaryFile.h" +#include "parse_color.h" #include #include @@ -3872,68 +3873,6 @@ send_notify(const string &message) { add_baked_request(request); } -//////////////////////////////////////////////////////////////////// -// Function: P3DInstance::parse_color -// Access: Private, Static -// Description: Parses a HTML color spec of the form #rgb or #rrggbb. -// Returns true on success, false on failure. On -// success, fills r, g, b with the color values in the -// range 0..255. On failure, r, g, b are undefined. -//////////////////////////////////////////////////////////////////// -bool P3DInstance:: -parse_color(int &r, int &g, int &b, const string &color) { - if (color.empty() || color[0] != '#') { - return false; - } - if (color.length() == 4) { - if (!parse_hexdigit(r, color[1]) || - !parse_hexdigit(g, color[2]) || - !parse_hexdigit(b, color[3])) { - return false; - } - r *= 0x11; - g *= 0x11; - b *= 0x11; - return true; - } - if (color.length() == 7) { - int rh, rl, gh, gl, bh, bl; - if (!parse_hexdigit(rh, color[1]) || - !parse_hexdigit(rl, color[2]) || - !parse_hexdigit(gh, color[3]) || - !parse_hexdigit(gl, color[4]) || - !parse_hexdigit(bh, color[5]) || - !parse_hexdigit(bl, color[6])) { - return false; - } - r = (rh << 4) | rl; - g = (gh << 4) | gl; - b = (bh << 4) | bl; - return true; - } - - return false; -} - -//////////////////////////////////////////////////////////////////// -// Function: P3DInstance::parse_hexdigit -// Access: Private, Static -// Description: Parses a single hex digit. Returns true on success, -// false on failure. On success, fills result with the -// parsed value, an integer in the range 0..15. -//////////////////////////////////////////////////////////////////// -bool P3DInstance:: -parse_hexdigit(int &result, char digit) { - if (isdigit(digit)) { - result = digit - '0'; - return true; - } else if (isxdigit(digit)) { - result = tolower(digit) - 'a' + 10; - return true; - } - return false; -} - #ifdef __APPLE__ //////////////////////////////////////////////////////////////////// // Function: P3DInstance::alloc_swbuffer diff --git a/direct/src/plugin/p3dInstance.h b/direct/src/plugin/p3dInstance.h index 34f57083ca..cf06e7b707 100644 --- a/direct/src/plugin/p3dInstance.h +++ b/direct/src/plugin/p3dInstance.h @@ -220,9 +220,6 @@ private: void send_notify(const string &message); - static bool parse_color(int &r, int &g, int &b, const string &color); - static bool parse_hexdigit(int &result, char digit); - #ifdef __APPLE__ void alloc_swbuffer(); void free_swbuffer(); diff --git a/direct/src/plugin/parse_color.cxx b/direct/src/plugin/parse_color.cxx new file mode 100644 index 0000000000..fce44da69b --- /dev/null +++ b/direct/src/plugin/parse_color.cxx @@ -0,0 +1,78 @@ +// Filename: parse_color.cxx +// Created by: drose (25Aug11) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) Carnegie Mellon University. All rights reserved. +// +// All use of this software is subject to the terms of the revised BSD +// license. You should have received a copy of this license along +// with this source code in a file named "LICENSE." +// +//////////////////////////////////////////////////////////////////// + +#include "parse_color.h" +#include + +static bool parse_hexdigit(int &result, char digit); + +//////////////////////////////////////////////////////////////////// +// Function: parse_color +// Description: Parses a HTML color spec of the form #rgb or #rrggbb. +// Returns true on success, false on failure. On +// success, fills r, g, b with the color values in the +// range 0..255. On failure, r, g, b are undefined. +//////////////////////////////////////////////////////////////////// +bool +parse_color(int &r, int &g, int &b, const string &color) { + if (color.empty() || color[0] != '#') { + return false; + } + if (color.length() == 4) { + if (!parse_hexdigit(r, color[1]) || + !parse_hexdigit(g, color[2]) || + !parse_hexdigit(b, color[3])) { + return false; + } + r *= 0x11; + g *= 0x11; + b *= 0x11; + return true; + } + if (color.length() == 7) { + int rh, rl, gh, gl, bh, bl; + if (!parse_hexdigit(rh, color[1]) || + !parse_hexdigit(rl, color[2]) || + !parse_hexdigit(gh, color[3]) || + !parse_hexdigit(gl, color[4]) || + !parse_hexdigit(bh, color[5]) || + !parse_hexdigit(bl, color[6])) { + return false; + } + r = (rh << 4) | rl; + g = (gh << 4) | gl; + b = (bh << 4) | bl; + return true; + } + + return false; +} + +//////////////////////////////////////////////////////////////////// +// Function: parse_hexdigit +// Description: Parses a single hex digit. Returns true on success, +// false on failure. On success, fills result with the +// parsed value, an integer in the range 0..15. +//////////////////////////////////////////////////////////////////// +bool +parse_hexdigit(int &result, char digit) { + if (isdigit(digit)) { + result = digit - '0'; + return true; + } else if (isxdigit(digit)) { + result = tolower(digit) - 'a' + 10; + return true; + } + return false; +} diff --git a/direct/src/plugin/parse_color.h b/direct/src/plugin/parse_color.h new file mode 100644 index 0000000000..13f7710b2c --- /dev/null +++ b/direct/src/plugin/parse_color.h @@ -0,0 +1,24 @@ +// Filename: parse_color.h +// Created by: drose (25Aug11) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) Carnegie Mellon University. All rights reserved. +// +// All use of this software is subject to the terms of the revised BSD +// license. You should have received a copy of this license along +// with this source code in a file named "LICENSE." +// +//////////////////////////////////////////////////////////////////// + +#ifndef PARSE_COLOR_H +#define PARSE_COLOR_H + +#include +using namespace std; + +bool parse_color(int &r, int &g, int &b, const string &color); + +#endif + diff --git a/direct/src/plugin_npapi/ppInstance.cxx b/direct/src/plugin_npapi/ppInstance.cxx index 46d8866095..37f86a8797 100644 --- a/direct/src/plugin_npapi/ppInstance.cxx +++ b/direct/src/plugin_npapi/ppInstance.cxx @@ -20,6 +20,7 @@ #include "p3d_plugin_config.h" #include "find_root_dir.h" #include "mkdir_complete.h" +#include "parse_color.h" #include "nppanda3d_common.h" // We can include this header file to get the DTOOL_PLATFORM @@ -96,6 +97,36 @@ PPInstance(NPMIMEType pluginType, NPP instance, uint16_t mode, _p3d_temp_file_total_size = 0; _p3d_instance_id = 0; + // fgcolor and bgcolor are useful to know here (in case we have to + // draw a twirling icon). + + // The default fgcolor is white. + _bgcolor_r = _bgcolor_g = _bgcolor_b = 0xff; + if (has_token("bgcolor")) { + int r, g, b; + if (parse_color(r, g, b, lookup_token("bgcolor"))) { + _bgcolor_r = r; + _bgcolor_g = g; + _bgcolor_b = b; + } + } + + // The default fgcolor is either black or white, according to the + // brightness of the bgcolor. + if (_bgcolor_r + _bgcolor_g + _bgcolor_b > 0x80 + 0x80 + 0x80) { + _fgcolor_r = _fgcolor_g = _fgcolor_b = 0x00; + } else { + _fgcolor_r = _fgcolor_g = _fgcolor_b = 0xff; + } + if (has_token("fgcolor")) { + int r, g, b; + if (parse_color(r, g, b, lookup_token("fgcolor"))) { + _fgcolor_r = r; + _fgcolor_g = g; + _fgcolor_b = b; + } + } + _got_window = false; _python_window_open = false; #ifdef _WIN32 @@ -1927,6 +1958,25 @@ lookup_token(const string &keyword) const { return string(); } +//////////////////////////////////////////////////////////////////// +// Function: PPInstance::has_token +// Access: Public +// Description: Returns true if the named token appears in the list, +// false otherwise. +//////////////////////////////////////////////////////////////////// +bool PPInstance:: +has_token(const string &keyword) const { + Tokens::const_iterator ti; + for (ti = _tokens.begin(); ti != _tokens.end(); ++ti) { + if ((*ti)._keyword == keyword) { + return true; + } + } + + return false; +} + + //////////////////////////////////////////////////////////////////// // Function: PPInstance::compare_seq // Access: Private, Static @@ -2203,22 +2253,24 @@ win_get_twirl_bitmaps() { HDC dc = GetDC(_hwnd); static const size_t twirl_size = twirl_width * twirl_height; - unsigned char twirl_data[twirl_size]; + unsigned char twirl_data[twirl_size * 3]; unsigned char new_data[twirl_size * 4]; for (int step = 0; step < twirl_num_steps; ++step) { - get_twirl_data(twirl_data, twirl_size, step); + get_twirl_data(twirl_data, twirl_size, step, + _fgcolor_r, _fgcolor_g, _fgcolor_b, + _bgcolor_r, _bgcolor_g, _bgcolor_b); - // Replicate out the grayscale channels into RGBA. + // Expand out the RGB channels into RGBA. for (int yi = 0; yi < twirl_height; ++yi) { - const unsigned char *sp = twirl_data + yi * twirl_width; + const unsigned char *sp = twirl_data + yi * twirl_width * 3; unsigned char *dp = new_data + yi * twirl_width * 4; for (int xi = 0; xi < twirl_width; ++xi) { dp[0] = sp[0]; - dp[1] = sp[0]; - dp[2] = sp[0]; + dp[1] = sp[1]; + dp[2] = sp[2]; dp[3] = (unsigned char)0xff; - sp += 1; + sp += 3; dp += 4; } } @@ -2457,24 +2509,26 @@ osx_get_twirl_images() { _got_twirl_images = true; static const size_t twirl_size = twirl_width * twirl_height; - unsigned char twirl_data[twirl_size]; + unsigned char twirl_data[twirl_size * 3]; for (int step = 0; step < twirl_num_steps; ++step) { - get_twirl_data(twirl_data, twirl_size, step); + get_twirl_data(twirl_data, twirl_size, step, + _fgcolor_r, _fgcolor_g, _fgcolor_b, + _bgcolor_r, _bgcolor_g, _bgcolor_b); unsigned char *new_data = new unsigned char[twirl_size * 4]; - // Replicate out the grayscale channels into RGBA. Flip - // upside-down too. + // Expand the RGB channels into RGBA. Flip upside-down too. for (int yi = 0; yi < twirl_height; ++yi) { - const unsigned char *sp = twirl_data + (twirl_height - 1 - yi) * twirl_width; + const unsigned char *sp = twirl_data + (twirl_height - 1 - yi) * twirl_width * 3; unsigned char *dp = new_data + yi * twirl_width * 4; for (int xi = 0; xi < twirl_width; ++xi) { - dp[0] = sp[0]; - dp[1] = sp[0]; + // RGB <= BGR. + dp[0] = sp[2]; + dp[1] = sp[1]; dp[2] = sp[0]; dp[3] = (unsigned char)0xff; - sp += 1; + sp += 3; dp += 4; } } @@ -2547,8 +2601,8 @@ osx_release_twirl_images() { //////////////////////////////////////////////////////////////////// void PPInstance:: paint_twirl_osx_cgcontext(CGContextRef context) { - // Clear the whole region to white before beginning. - CGFloat bg_components[] = { 1, 1, 1, 1 }; + // Clear the whole region to the bgcolor before beginning. + CGFloat bg_components[] = { _bgcolor_r / 255.0f, _bgcolor_g / 255.0f, _bgcolor_b / 255.0f, 1 }; CGColorSpaceRef rgb_space = CGColorSpaceCreateDeviceRGB(); CGColorRef bg = CGColorCreate(rgb_space, bg_components); diff --git a/direct/src/plugin_npapi/ppInstance.h b/direct/src/plugin_npapi/ppInstance.h index 3f362034ef..cf5a775a8f 100644 --- a/direct/src/plugin_npapi/ppInstance.h +++ b/direct/src/plugin_npapi/ppInstance.h @@ -96,6 +96,7 @@ private: bool copy_file(const string &from_filename, const string &to_filename); string lookup_token(const string &keyword) const; + bool has_token(const string &keyword) const; static int compare_seq(const string &seq_a, const string &seq_b); static int compare_seq_int(const char *&num_a, const char *&num_b); @@ -145,6 +146,10 @@ private: typedef vector Tokens; Tokens _tokens; + // Set from fgcolor & bgcolor. + int _fgcolor_r, _fgcolor_b, _fgcolor_g; + int _bgcolor_r, _bgcolor_b, _bgcolor_g; + string _root_dir; string _standard_url_prefix; string _download_url_prefix;