3#include <cgv/media/riff.h> 
    9PBITMAPINFO CreateBitmapInfoStruct(HBITMAP hBmp)
 
   16    if (!GetObject(hBmp, 
sizeof(BITMAP), (LPSTR)&bmp)) 
 
   20    cClrBits = (WORD)(bmp.bmPlanes * bmp.bmBitsPixel); 
 
   23    else if (cClrBits <= 4) 
 
   25    else if (cClrBits <= 8) 
 
   27    else if (cClrBits <= 16) 
 
   29    else if (cClrBits <= 24) 
 
   38         pbmi = (PBITMAPINFO) LocalAlloc(LPTR, 
 
   39                    sizeof(BITMAPINFOHEADER) + 
 
   40                    sizeof(RGBQUAD) * (
size_t(1) << cClrBits)); 
 
   45         pbmi = (PBITMAPINFO) LocalAlloc(LPTR, 
 
   46                    sizeof(BITMAPINFOHEADER)); 
 
   50    pbmi->bmiHeader.biSize = 
sizeof(BITMAPINFOHEADER); 
 
   51    pbmi->bmiHeader.biWidth = bmp.bmWidth; 
 
   52    pbmi->bmiHeader.biHeight = bmp.bmHeight; 
 
   53    pbmi->bmiHeader.biPlanes = bmp.bmPlanes; 
 
   54    pbmi->bmiHeader.biBitCount = bmp.bmBitsPixel; 
 
   56        pbmi->bmiHeader.biClrUsed = (1<<cClrBits); 
 
   59    pbmi->bmiHeader.biCompression = BI_RGB; 
 
   65    pbmi->bmiHeader.biSizeImage = ((pbmi->bmiHeader.biWidth * cClrBits +31) & ~31) /8
 
   66                                  * pbmi->bmiHeader.biHeight; 
 
   69     pbmi->bmiHeader.biClrImportant = 0; 
 
   73unsigned char* get_bitmap_data(HBITMAP hbmp, 
unsigned& tex_w, 
unsigned& tex_h)
 
   76    if (!GetObject(hbmp, 
sizeof(BITMAP), (LPSTR)&bmp)) 
 
   78    PBITMAPINFO pbi = CreateBitmapInfoStruct(hbmp);
 
   79    PBITMAPINFOHEADER pbih = (PBITMAPINFOHEADER) pbi;
 
   80    unsigned my_size = 4 * pbih->biWidth * pbih->biHeight;
 
   81    if (pbih->biSizeImage >= my_size)
 
   82        my_size = pbih->biSizeImage;
 
   83    unsigned char* lpBits = 
new unsigned char[my_size];
 
   86    if (!GetDIBits(GetDC(NULL), hbmp, 0, (WORD) pbih->biHeight, lpBits, pbi, DIB_RGB_COLORS))
 
   93unsigned char* get_cursor_bitmap(HCURSOR hc, 
unsigned& w, 
unsigned& h, 
int anim_step = 0)
 
   98    if (!GetObject(ii.hbmColor ? ii.hbmColor : ii.hbmMask, sizeof(BITMAP), (LPSTR)&bmp)) 
 
  104    HDC dc = GetDC(NULL);
 
  105    HDC mem_dc = CreateCompatibleDC(dc);
 
  106    HBITMAP hbm = CreateCompatibleBitmap (dc, w, h);
 
  107    HBITMAP old_bm = (HBITMAP)SelectObject(mem_dc, hbm);
 
  113    HBRUSH black = CreateSolidBrush(RGB(0,0,0));
 
  115    FillRect(mem_dc,&r, black);
 
  116    if (DrawIconEx(mem_dc,0,0,hc,w,h,anim_step,NULL,DI_NORMAL | DI_COMPAT) == FALSE) {
 
  117        SelectObject(mem_dc, old_bm);
 
  125    SelectObject(mem_dc, old_bm);
 
  126    unsigned char* data_b = get_bitmap_data(hbm,w,h);
 
  128    old_bm = (HBITMAP)SelectObject(mem_dc, hbm);
 
  129    HBRUSH white = CreateSolidBrush(RGB(255,255,255));
 
  130    FillRect(mem_dc,&r, white);
 
  131    DrawIconEx(mem_dc,0,0,hc,w,h,anim_step,NULL,DI_NORMAL | DI_COMPAT);
 
  132    SelectObject(mem_dc, old_bm);
 
  133    unsigned char* data_w = get_bitmap_data(hbm,w,h);
 
  136    for (
unsigned i=0; i<n; ++i) {
 
  138        for (
unsigned j=0; j<3; ++j)
 
  139            sum_alpha += 255+(
int)data_b[4*i+j]-(int)data_w[4*i+j];
 
  140        if (sum_alpha > 3*255)
 
  142        unsigned char alpha = (
unsigned char)(sum_alpha/3);
 
  143        data_b[4*i+3] = alpha;
 
  145            for (
unsigned j=0; j<3; ++j) {
 
  146                float v = data_b[4*i+j]*255.0f/alpha;
 
  149                data_b[4*i+j] = (
unsigned char) v;
 
  164unsigned create_texture_from_cursor(HCURSOR hc, 
unsigned& tex_w, 
unsigned& tex_h, 
int& hot_x, 
int& hot_y, 
int anim_step = 0)
 
  168    GetIconInfo(hc, &ii);
 
  172    unsigned char* bgra_data = get_cursor_bitmap(hc, tex_w, tex_h, anim_step);
 
  175    if (anim_step == 1) {
 
  177        unsigned char* first_bgra_data = get_cursor_bitmap(hc, w, h, 0);
 
  179        bool found_diff = 
false;
 
  180        for (
int j=0; !found_diff && (j<m); ++j)
 
  181            if (first_bgra_data[j] != bgra_data[j])
 
  183        delete [] first_bgra_data;
 
  191    glGenTextures(1, &tex_id);
 
  192    glBindTexture(GL_TEXTURE_2D, tex_id);
 
  193    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex_w, tex_h, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, bgra_data);
 
  194    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_NEAREST);
 
  195    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,GL_NEAREST);
 
  213    return tex_ids.size() > 0;
 
 
  216void gl_cursor::clear()
 
  218    while (tex_ids.size() > 0) {
 
  219        glDeleteTextures(1, &tex_ids.back());
 
  226void gl_cursor::add_frame(
unsigned tex_id)
 
  229    tex_ids.push_back(tex_id);
 
  237std::wstring str2wstr(
const std::string& s)
 
  242    int n = MultiByteToWideChar(CP_ACP,0,s.c_str(),(
int)s.size(),&ws[0],(
int)ws.size());
 
  245    std::cerr << 
"str2wstr(const std::string& s) not implemented" << std::endl;
 
  251bool create_from_cursor(HCURSOR hc, gl_cursor* c)
 
  256    unsigned tex_id, i = 0;
 
  258        tex_id = create_texture_from_cursor(hc, c->w, c->h, c->hot_x, c->hot_y, i);
 
  260            c->add_frame(tex_id);
 
  262    } 
while (tex_id != -1);
 
  263    return c->is_created();
 
  268    static struct { 
const char* id; 
 
  276        { 
"startup", IDC_APPSTARTING },
 
  277        { 
"arrow", IDC_ARROW },
 
  278        { 
"cross", IDC_CROSS },
 
  279        { 
"wait", IDC_WAIT },
 
  280        { 
"hand", IDC_HAND },
 
  281        { 
"help", IDC_HELP },
 
  283        { 
"ns", IDC_SIZENS },
 
  284        { 
"we", IDC_SIZEWE },
 
  285        { 
"move", IDC_SIZEALL },
 
  286        { 
"nesw", IDC_SIZENESW },
 
  287        { 
"nwse", IDC_SIZENWSE }
 
  294    for (
unsigned i=0; i<10; ++i)
 
  295        if (
id == lookup[i].
id) {
 
  301    return create_from_cursor(LoadCursor(NULL, cid), 
this);
 
  304#include <cgv/type/standard_types.h> 
  327    ani_riff_handler(gl_cursor* _c) : c(_c)
 
  333    void process_chunk_data(
media::fourcc id, 
unsigned size, 
void* data_ptr)
 
  336            anih_structure& as = *((anih_structure*)data_ptr);
 
  337            nr_frames = as.nr_frames;
 
  338            nr_steps = as.nr_steps;
 
  339            period = as.display_rate == 0 ? 3 : as.display_rate;
 
  340            c->tex_ids.resize(nr_frames);
 
  341            c->frames.resize(nr_steps);
 
  342            c->periods.resize(nr_steps);
 
  344            for (i=0; i<nr_steps; ++i) {
 
  345                c->frames[i] = i % nr_frames;
 
  346                c->periods[i] = period;
 
  348            for (i=0; i<nr_frames; ++i)
 
  350            c->update_duration();
 
  352        else if (
id == 
"seq") {
 
  353            unsigned count = size/4;
 
  354            unsigned *values = (
unsigned*)data_ptr;
 
  355            c->frames.resize(count);
 
  356            c->periods.resize(count);
 
  357            if (count != c->periods.size())
 
  358                std::cerr << 
"found wrong number of seq entries" << std::endl;
 
  360                for (
unsigned i=0; i<count; ++i)
 
  361                    c->frames[i] = values[i];
 
  363        else if (
id == 
"rate") {
 
  364            unsigned count = size/4;
 
  365            unsigned *values = (
unsigned*)data_ptr;
 
  366            if (count != c->periods.size())
 
  367                std::cerr << 
"found wrong number of rate entries" << std::endl;
 
  369                for (
unsigned i=0; i<count; ++i)
 
  370                    c->periods[i] = values[i];
 
  371            c->update_duration();
 
  379    unsigned dot = (unsigned)file_name.find_last_of(
'.');
 
  380    if (dot == std::string::npos)
 
  382    std::string ext = file_name.substr(dot+1);
 
  383    for (
unsigned i=0; i<ext.size(); ++i)
 
  384        if (ext[i] >= 
'a' && ext[i] <= 
'z') {
 
  391        return create_from_cursor(LoadCursorFromFile(
 
  393            str2wstr(file_name).c_str()
 
  400    else if (ext == 
"ANI") {
 
  403        ani_riff_handler arh(
this);
 
  405        if (!rr.read(file_name))
 
  408        HCURSOR hc = LoadCursorFromFile(
 
  410            str2wstr(file_name).c_str()
 
  418            if (tex_ids[frames[i]] == -1) {
 
  419                tex_ids[frames[i]] = create_texture_from_cursor(hc, w, h, hot_x, hot_y, i);
 
  420                if (tex_ids[frames[i]] == -1) {
 
  434    std::cerr << 
"gl_cursor::create only implemented under WIN32" << std::endl;
 
 
  439    std::cerr << 
"gl_cursor::create_from_file only implemented under WIN32" << std::endl;
 
 
  445void gl_cursor::update_duration()
 
  448    for (
unsigned i=0; i<periods.size(); ++i)
 
  449        duration += periods[i];
 
  455    return (
unsigned)frames.size();
 
 
  461    return (
unsigned)tex_ids.size();
 
 
  467    return tex_ids[frame_idx];
 
 
  473    return frames[step_idx];
 
 
  479    frames[step_idx] = frame_idx;
 
 
  485    return periods[step_idx];
 
 
  491    periods[step_idx] = period;
 
 
  498    frames.push_back(frame_idx);
 
  499    periods.push_back(period);
 
 
  506    unsigned i, period = ((int)(elapsed_seconds * 60))%duration;
 
  507    for (i=0; i<periods.size(); ++i) {
 
  508        if (periods[i] > period)
 
  510        period -= periods[i];
 
  512    return i % periods.size();
 
 
  517    if (frame_idx >= tex_ids.size())
 
  519    if (tex_ids[frame_idx] == -1) 
 
  522    glPushAttrib(GL_COLOR_BUFFER_BIT|GL_TEXTURE_BIT);
 
  523    glEnable(GL_ALPHA_TEST);
 
  525    glAlphaFunc(GL_GREATER, 0.0f);
 
  526    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 
  527    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, use_color ? GL_MODULATE : GL_REPLACE);
 
  528    glBindTexture(GL_TEXTURE_2D, tex_ids[frame_idx]);
 
  531    glEnable(GL_TEXTURE_2D);
 
 
complete implementation of method actions that only call one method when entering a node
unsigned get_nr_steps() const
return the number of animation steps
gl_cursor()
construct empty gl_cursor instance
void append_step(unsigned frame_idx, unsigned period)
append an animation step given by frame index and step period
bool is_created() const
check whether cursor has been created
void set_step_period(unsigned step_idx, unsigned period)
return the period of given step in 1/60th of a second
unsigned get_texture_id(unsigned frame_idx=0) const
return the gl texture id of the given frame
unsigned get_step_period(unsigned step_idx) const
return the period of given step in 1/60th of a second
bool create(const std::string &id="arrow")
Create cursor from textual name of default cursor.
unsigned get_step_frame(unsigned step_idx) const
return the frame index of given step
void set_step_frame(unsigned step_idx, unsigned frame_idx)
set the frame index of given step
unsigned get_nr_frames() const
return the number of animation frames
void draw(int x, int y, bool use_color=false, unsigned frame_idx=0)
draw the cursor at the given location
bool create_from_file(const std::string &file_name)
Create cursor from a file of type .cur or .ani.
unsigned find_step_index(double elapsed_seconds) const
find the step index of a given elapsed time in seconds
namespace for compile time type information