respect fgcolor and bgcolor for twirling icon

This commit is contained in:
David Rose 2011-08-25 08:46:58 +00:00
parent 443fff604b
commit da3d88fefa
9 changed files with 209 additions and 94 deletions

View File

@ -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
//

View File

@ -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));
}
}

View File

@ -15,13 +15,15 @@
#ifndef GET_TWIRL_DATA_H
#define GET_TWIRL_DATA_H
#include "stddef.h"
#include <stddef.h>
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

View File

@ -26,6 +26,7 @@
#include "p3dUndefinedObject.h"
#include "p3dMultifileReader.h"
#include "p3dTemporaryFile.h"
#include "parse_color.h"
#include <sstream>
#include <algorithm>
@ -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

View File

@ -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();

View File

@ -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 <ctype.h>
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;
}

View File

@ -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 <string>
using namespace std;
bool parse_color(int &r, int &g, int &b, const string &color);
#endif

View File

@ -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);

View File

@ -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<P3D_token> 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;