/* qsort comparison function to sort by luminance */ int compare_luminance(const void *a, const void *b) { pgcolor color_a = *(pgcolor *)a; pgcolor color_b = *(pgcolor *)b; int lum_a = getred(color_a)*30 + getgreen(color_a)*59 + getblue(color_a)*11; int lum_b = getred(color_b)*30 + getgreen(color_b)*59 + getblue(color_b)*11; if (lum_a < lum_b) return -1; if (lum_a > lum_b) return 1; return 0; }
void directfb_pixel(hwrbitmap dest,s16 x,s16 y,hwrcolor c,s16 lgop) { DFBResult err; DFBSurfaceDrawingFlags flags; if (dest) { def_pixel(dest,x,y,c,lgop); return; } #ifdef DEBUG_VIDEO if (!directfb) printf("Directfb driver: pixel at %d,%d set when uninitialized\n",x,y); if (x<0 || y<0 || (x>=vid->xres) || (y>=vid->yres)) printf("Directfb driver: pixel out of bounds at %d,%d\n",x,y); #endif err = primary->SetColor (primary, getred(c), getgreen(c), getblue(c), h_getalpha(c)); dfb_errcheck_die; // FIXME: should support all lgops switch (lgop) { case PG_LGOP_NONE: flags = DSDRAW_NOFX; break; case PG_LGOP_ALPHA: flags = DSDRAW_BLEND; break; default: flags = DSDRAW_NOFX; printf("ignoring lgop: %d\n", lgop); } err = primary->SetDrawingFlags (primary, flags); dfb_errcheck_die; err = DrawPixel (primary, x, y); dfb_errcheck_die; }
void directfb_alpha_charblit(hwrbitmap dest, u8 *chardat, s16 x, s16 y, s16 w, s16 h, int char_pitch, u8 *gammatable, s16 angle, hwrcolor c, struct pgquad *clip, s16 lgop) { int i,j,xp,yp; u8 *l; u8 red, green, blue, alpha; DFBResult err; DFBSurfaceDrawingFlags flags; if (dest) { def_alpha_charblit(dest, chardat, x, y, w, h, char_pitch, gammatable, angle, c, clip, lgop); return; } // FIXME: we're effectively ignoring the lgop flags = DSDRAW_BLEND; err = primary->SetDrawingFlags (primary, flags); dfb_errcheck_die; /* little stupid optimization */ red = getred(c); green = getgreen(c); blue = getblue(c); for (j=0;j<h;j++,chardat+=char_pitch) for (i=0,l=chardat;i<w;i++,l++) { switch (angle) { case 0: xp = x+i; yp = y+j; break; case 90: xp = x+j; yp = y-i; break; case 180: xp = x-i; yp = y-j; break; case 270: xp = x-j; yp = y+i; break; } if (clip) if (xp < clip->x1 || xp > clip->x2 || yp < clip->y1 || yp > clip->y2) continue; if (gammatable) alpha = gammatable[*l]; else alpha = *l; err = primary->SetColor (primary, red, green, blue, alpha); dfb_errcheck_die; err = DrawPixel (primary, xp, yp); dfb_errcheck_die; } }
void alter_colors (iImage * source, int o_r, int o_g, int o_b, int r2, int g2, int b2) { int i, j; int r, g, b; //float bright; //int red_ratio; //int green_ratio; //int blue_ratio; for (i = 0; i < source->GetWidth (); i++) for (j = 0; j < source->GetHeight (); j++) { r = getred (source, i, j); g = getgreen (source, i, j); b = getblue (source, i, j); //bright=sqrt(r*r+g*g+b*b); setred (source, i, j, (int)(r2 * sqrt (o_r * r + o_g * g + o_b * b) / 255) ); setgreen (source, i, j,(int)( g2 * sqrt (o_r * r + o_g * g + o_b * b) / 255)); setblue (source, i, j,(int)(b2 * sqrt (o_r * r + o_g * g + o_b * b) / 255)); } }
//sux void invert_brightness (iImage * source) { int i, j; int r, g, b; //float bright; for (i = 0; i < source->GetWidth (); i++) for (j = 0; j < source->GetHeight (); j++) { r = getred (source, i, j); g = getgreen (source, i, j); b = getblue (source, i, j); r = 255 - r; g = 255 - g; b = 255 - b; setred (source, i, j, r); setgreen (source, i, j, g); setblue (source, i, j, b); } }
inline void gl_color(hwrcolor c) { if (c & PGCF_ALPHA) { /* Convert 7-bit alpha channel to 8-bit */ glColor4ub(getred(c), getgreen(c), getblue(c), c>>23 | ((c>>24)&1)); }
/* Look up a pgcolor in the palette. Really slow... */ hwrcolor palette_lookup(pgcolor c) { /* The downside of custom palettes is that we have to spend a good bit of * time looking up the color. Make this a little faster by caching the * most recently looked up color, since in image conversion there are usually * areas of equal color. */ static pgcolor cached_color = 0xFFFFFFFF; /* An invalid value that we won't get a cache hit on */ static u8 cached_index = 0; int i; int distance, d; int r,g,b,rd,gd,bd; pgcolor pcolor; if (cached_color == c) return cached_index; /* Since our palette is sorted by luminance, we can handle black and white easily */ if (c == 0xFFFFFF) return 255; if (c == 0) return 0; /* Now search for the closest color in RGB space */ distance = 195076; /* This is one greater than the distance between black and white */ cached_color = c; r = getred(c); g = getgreen(c); b = getblue(c); for (i=0;i<256;i++) { pcolor = palette8_custom[i]; rd = r - getred(pcolor); gd = g - getgreen(pcolor); bd = b - getblue(pcolor); d = rd*rd + gd*gd + bd*bd; if (d < distance) { distance = d; cached_index = i; } } return cached_index; }
hwrcolor def_color_pgtohwr(pgcolor c) { if (c & PGCF_ALPHA) { /* ARGB conversion, just premultiply the RGB color */ return mkcolora( getalpha(c), (getred(c) * getalpha(c)) >> 7, (getgreen(c) * getalpha(c)) >> 7, (getblue(c) * getalpha(c)) >> 7 ); } else if (vid->bpp==0) {
void blit_alpha (iImage * source, iImage * dest, int source_startx, int source_starty, int destx, int desty, int source_endx, int source_endy, int range) { int x; int y; //check if its out of range yourself :P int r, g, b, a; int i, j; //int r2,g2,b2; x = dest->GetWidth (); y = dest->GetHeight (); if (source_endx + destx - source_startx >= x) source_endx = x - destx + source_startx; if (source_endy + desty - source_starty >= y) source_endy = y - desty + source_starty; i = 0; j = 0; for (x = source_startx; x < source_endx; x++) { for (y = source_starty; y < source_endy; y++) { r = getred (source, x, y); g = getgreen (source, x, y); b = getblue (source, x, y); a = getalpha (source, x, y); if (a - range < 1) { } else { setred (dest, i + destx, j + desty, r); setgreen (dest, i + destx, j + desty, g); setblue (dest, i + destx, j + desty, b); } j++; } j = 0; i++; } }
void yuv16_422_planar_pixel(hwrbitmap dest, s16 x, s16 y, hwrcolor c, s16 lgop) { struct stdbitmap *dstbit = (struct stdbitmap *) dest; if (yuv16_422_planar_is_offscreen(dstbit->bits)) { /* we are offscreen */ def_pixel(dest, x, y, c, lgop); return; } else { unsigned long r = getred(c); unsigned long g = getgreen(c); unsigned long b = getblue(c); unsigned long a = getalpha(c); size_t offset = (dstbit->pitch)*y + x; u8 *dst_y = dstbit->bits + offset; u8 *dst_uv = dstbit->bits + yuv16_422_planar_y_plane_size + (offset&~1); switch (lgop) { case PG_LGOP_NONE: { int y, cb, cr; yuv16_rgb_shadow_buffer[offset] = c; /* * Alpha is null...We're transparent */ if (!a) { y = 0; cb = 0; cr = 0; } else rgb_to_ycbcr(r, g, b, &y, &cb, &cr); *dst_y = (char)y; *dst_uv++ = (char)cb; *dst_uv = (char)cr; break; } default: /* Not supported yet */ return; } } }
//the except is where you have a 0... //if o_r ==0 and o_g>0 and o_b>0 rng=10 no colors with red greater than 10 will be replaced void alter_colors_except (iImage * source, int o_r, int o_g, int o_b, int r2, int g2, int b2, int rng) { int i, j; int r, g, b; int ok; for (i = 0; i < source->GetWidth (); i++) for (j = 0; j < source->GetHeight (); j++) { ok = 1; r = getred (source, i, j); g = getgreen (source, i, j); b = getblue (source, i, j); if (o_r == 0) if (r > rng) ok = 0; if (o_g == 0) if (g > rng) ok = 0; if (o_b == 0) if (b > rng) ok = 0; if (ok == 1) { setred (source, i, j,(int)( r2 * sqrt (o_r * r + o_g * g + o_b * b) / 255)); setgreen (source, i, j,(int)( g2 * sqrt (o_r * r + o_g * g + o_b * b) / 255)); setblue (source, i, j,(int)( b2 * sqrt (o_r * r + o_g * g + o_b * b) / 255)); } } }
//This Blit conserves the alpha, Blit_merge blends the alphaed color in with background. void blit (iImage * source, iImage * dest, int source_startx, int source_starty, int destx, int desty, int source_endx, int source_endy) { int x; int y; int r, g, b; int i, j; int a; x = dest->GetWidth (); y = dest->GetHeight (); if (source_endx + destx - source_startx >= x) source_endx = x - destx + source_startx; if (source_endy + desty - source_starty >= y) source_endy = y - desty + source_starty; i = 0; j = 0; for (x = source_startx; x < source_endx; x++) { for (y = source_starty; y < source_endy; y++) { r = getred (source, x, y); g = getgreen (source, x, y); b = getblue (source, x, y); a = getalpha (source, x, y); setred (dest, i + destx, j + desty, r); setgreen (dest, i + destx, j + desty, g); setblue (dest, i + destx, j + desty, b); setalpha (dest, i + destx, j + desty, a); j++; } j = 0; i++; } }
void swap_blue_to_red (iImage * source) { int i, j; int r, g, b; //float bright; for (i = 0; i < source->GetWidth (); i++) for (j = 0; j < source->GetHeight (); j++) { r = getred (source, i, j); g = getgreen (source, i, j); b = getblue (source, i, j); setred (source, i, j, b); setgreen (source, i, j, g); setblue (source, i, j, r); } }
void blit_transparent (iImage * source, iImage * dest, int source_startx, int source_starty, int destx, int desty, int source_endx, int source_endy, int r0, int g0, int b0, int range) { int x; int y; int r, g, b; int i, j; int r2, g2, b2; x = dest->GetWidth (); y = dest->GetHeight (); if (source_endx + destx - source_startx >= x) source_endx = x - destx + source_startx; if (source_endy + desty - source_starty >= y) source_endy = y - desty + source_starty; i = 0; j = 0; for (x = source_startx; x < source_endx; x++) { for (y = source_starty; y < source_endy; y++) { r = getred (source, x, y); g = getgreen (source, x, y); b = getblue (source, x, y); r2 = abs (r0 - r); g2 = abs (g0 - g); b2 = abs (b0 - b); if (r2 < range && g2 < range && b2 < range) { r = r0; setalpha (dest, i + destx, j + desty, 0); } else { setred (dest, i + destx, j + desty, r); setgreen (dest, i + destx, j + desty, g); setblue (dest, i + destx, j + desty, b); setalpha (dest, i + destx, j + desty, 255); } j++; } j = 0; i++; } }
//RNG is the times difference void alter_colors_ratio (iImage * source, int o_r, int o_g, int o_b, int r2, int g2, int b2, int rng) { int i, j; int r, g, b; //int a1; //float bright; //int r3,g3,b3; float rg_rat, gb_rat, br_rat; //Which way do the ratio's face: int rg_way = -1, gb_way = -1, br_way = -1; float rg_fly=0; float gb_fly, br_fly; int ok; //Rat values: 0 - none of one element // greater than 0: green is greater than red // less than 0: red is less than green -inverse 1/ number- greater than... // greater than 0: How many times difference //compare: times difference, against current times difference, and see if within range if (o_r == 0) rg_rat = 0; else { rg_rat = o_g / o_r; if (rg_rat < 0) { rg_rat = 1 / rg_rat; rg_way = 1; } } if (o_g == 0) gb_rat = 0; else { gb_rat = o_b / o_g; if (gb_rat < 0) { gb_rat = 1 / gb_rat; gb_way = 1; } } if (o_b == 0) br_rat = 0; else { br_rat = o_r / o_b; if (br_rat < 0) { br_rat = 1 / br_rat; br_way = 1; } } for (i = 0; i < source->GetWidth (); i++) for (j = 0; j < source->GetHeight (); j++) { ok = 1; r = getred (source, i, j); g = getgreen (source, i, j); b = getblue (source, i, j); //Check which way rg goes if (rg_way == -1) { //everything is cool if 0's.0 stops division by 0 if (r == 0) { if (o_r > 0) ok = 0; } else { rg_fly = g / r; //make sure we got green to red, and not red to green(insta failure for now) //invert and negatize it, so its on a scale goin the other direction if (rg_fly < 0) rg_fly = -(1 / rg_fly); rg_fly = abs ((int)(rg_fly - rg_rat)); if (rg_fly > rng) ok = 0; } } if (rg_way == 1) { rg_fly = r / g; if (rg_fly < 0) rg_fly = -(1 / rg_fly); rg_fly = abs ((int)(rg_fly - rg_rat)); if (rg_fly > rng) ok = 0; } if (gb_way == -1) { //everything is cool if 0's.0 stops division by 0 if (g == 0) { if (o_g > 0) ok = 0; } else { gb_fly = b / g; //make sure we got green to red, and not red to green(insta failure for now) //invert and negatize it, so its on a scale goin the other direction if (gb_fly < 0) gb_fly = -(1 / gb_fly); gb_fly = abs ((int)(gb_fly - gb_rat)); if (gb_fly > rng) ok = 0; } } if (gb_way == 1) { gb_fly = g / b; if (rg_fly < 0) gb_fly = -(1 / gb_fly); gb_fly = abs ((int)(gb_fly - gb_rat)); if (gb_fly > rng) ok = 0; } if (br_way == -1) { //everything is cool if 0's.0 stops division by 0 if (b == 0) { if (o_b > 0) ok = 0; } else { br_fly = r / b; //make sure we got green to red, and not red to green(insta failure for now) //invert and negatize it, so its on a scale goin the other direction if (br_fly < 0) br_fly = -(1 / br_fly); br_fly = abs ((int)(br_fly - br_rat)); if (br_fly > rng) ok = 0; } } if (br_way == 1) { br_fly = b / r; if (rg_fly < 0) br_fly = -(1 / br_fly); br_fly = abs ((int)(br_fly - br_rat)); if (br_fly > rng) ok = 0; } if (ok == 1) { setred (source, i, j,(int)( r2 * sqrt (o_r * r + o_g * g + o_b * b) / 255)); setgreen (source, i, j,(int)( g2 * sqrt (o_r * r + o_g * g + o_b * b) / 255)); setblue (source, i, j,(int)( b2 * sqrt (o_r * r + o_g * g + o_b * b) / 255)); } } }
void yuv16_422_planar_slab (hwrbitmap dest, s16 x, s16 y, s16 w, hwrcolor c, s16 lgop) { struct stdbitmap * dstbit = (struct stdbitmap *) dest; if (yuv16_422_planar_is_offscreen (dstbit->bits)) { /* we are offscreen */ def_slab (dest, x, y, w, c, lgop); return; } else { unsigned long r = getred(c); unsigned long g = getgreen(c); unsigned long b = getblue(c); unsigned long a = getalpha(c); int i; size_t offset = (dstbit->pitch) * y + x; u8 * dst_y = dstbit->bits + offset; u8 * dst_uv = dstbit->bits + yuv16_422_planar_y_plane_size + (offset &~ 1); switch (lgop) { case PG_LGOP_NONE: { int y, cb, cr; /* * Alpha is null...We're transparent */ if (!a) { y = 0; cb = 0; cr = 0; } else rgb_to_ycbcr (r, g, b, & y, & cb, & cr); memset (dst_y, (char) y, w); if (cb == cr) { memset (dst_uv, (char) cb, w * 2); } else { for (i = 0; i < w; i += 2) { * dst_uv++ = (char) cb; * dst_uv = (char) cr; } } if (c == 0) { memset (yuv16_rgb_shadow_buffer, 0, w * sizeof (c)); } else { for (i = 0; i < w; i++) { yuv16_rgb_shadow_buffer [offset + i] = c; } } break; } default: /* Not supported yet */ def_slab (dest, x, y, w, c, lgop); return; } } }
/* Fillstyle interpreter- generates/refreshes a gropnode list */ g_error exec_fillstyle_inner(struct gropctxt *ctx,u16 state, u16 property) { g_error e; u32 fssize; /* Fillstyle size */ unsigned char *fs; /* Pointer to the actual fillstyle data */ unsigned char *p,*plimit; unsigned char op; int r,g,b; /* For color arithmetic */ struct widget *w; int stackframe = fsstkpos-4; /* Look up the fillstyle */ e = rdhandle((void**)&fs,PG_TYPE_FILLSTYLE,-1,theme_lookup(state,property)); errorcheck; if (!fs) { /* When our best just isn't good enough... */ if (property == PGTH_P_BACKDROP || property == PGTH_P_BORDER_FILL) return success; /* The default fillstyle, if no theme is loaded or no theme has defined the property*/ addgrop(ctx,PG_GROP_SETCOLOR); ctx->current->param[0] = VID(color_pgtohwr) (0x000000); switch (state) { case PGTH_O_BUTTON_ON: /* 2 borders */ addgropsz(ctx,PG_GROP_FRAME,ctx->r.x,ctx->r.y,ctx->r.w,ctx->r.h); ctx->r.x += 1; ctx->r.y += 1; ctx->r.w -= 2; ctx->r.h -= 2; default: /* 1 border */ addgropsz(ctx,PG_GROP_FRAME,ctx->r.x,ctx->r.y,ctx->r.w,ctx->r.h); ctx->r.x += 1; ctx->r.y += 1; ctx->r.w -= 2; ctx->r.h -= 2; case PGTH_O_LABEL_SCROLL: /* No border */ addgrop(ctx,PG_GROP_SETCOLOR); ctx->current->param[0] = VID(color_pgtohwr) (theme_lookup(state,PGTH_P_BGCOLOR)); addgropsz(ctx,PG_GROP_RECT,ctx->r.x,ctx->r.y,ctx->r.w,ctx->r.h); } return success; } /* Process the opcodes */ fssize = *(((u32 *)fs)++); p = fs; plimit = fs+fssize; while (p<plimit) { op = *(p++); /* These must occur in MSB to LSB order! (see constants.h) */ if (op & PGTH_OPSIMPLE_GROP) { /* 1-byte gropnode */ e = fsgrop(ctx,op & (PGTH_OPSIMPLE_GROP-1)); errorcheck; } else if (op & PGTH_OPSIMPLE_LITERAL) { /* 1-byte literal */ fsstack[fsstkpos++] = op & (PGTH_OPSIMPLE_LITERAL-1); } else if (op & PGTH_OPSIMPLE_CMDCODE) { /* Command code */ switch (op) { case PGTH_OPCMD_LONGLITERAL: if ((plimit-p)<4) return mkerror(PG_ERRT_BADPARAM,91); /* Truncated opcode */ fsstack[fsstkpos++] = NEXTLONG; p += 4; break; case PGTH_OPCMD_LONGGROP: if ((plimit-p)<2) return mkerror(PG_ERRT_BADPARAM,91); /* Truncated opcode */ e = fsgrop(ctx,NEXTSHORT); p += 2; errorcheck; break; case PGTH_OPCMD_LONGGET: if (plimit<=p) return mkerror(PG_ERRT_BADPARAM,91); /* Truncated opcode */ e = fsget(*(p++)+stackframe); errorcheck; break; case PGTH_OPCMD_LONGSET: if (plimit<=p) return mkerror(PG_ERRT_BADPARAM,91); /* Truncated opcode */ e = fsset(*(p++)+stackframe); errorcheck; break; case PGTH_OPCMD_PROPERTY: if ((plimit-p)<4) return mkerror(PG_ERRT_BADPARAM,91); /* Truncated opcode */ fsa = NEXTSHORT; p += 2; fsb = NEXTSHORT; p += 2; fsstack[fsstkpos++] = theme_lookup(fsa,fsb); #ifdef CONFIG_ANIMATION /* If it depends on time or randomness, turn on the animated flag in the divnode */ if ((fsb==PGTH_P_TICKS || fsb==PGTH_P_RANDOM) && ctx->owner) ctx->owner->flags |= DIVNODE_ANIMATED; #endif break; case PGTH_OPCMD_LOCALPROP: if ((plimit-p)<2) return mkerror(PG_ERRT_BADPARAM,91); /* Truncated opcode */ fsa = NEXTSHORT; p += 2; #ifdef DEBUG_THEME printf("Local theme lookup, property %d\n",(int)fsa); #endif fsstack[fsstkpos++] = theme_lookup(state,fsa); #ifdef CONFIG_ANIMATION /* If it depends on time or randomness, turn on the animated flag in the divnode */ if ((fsa==PGTH_P_TICKS || fsa==PGTH_P_RANDOM) && ctx->owner) ctx->owner->flags |= DIVNODE_ANIMATED; #endif break; case PGTH_OPCMD_PLUS: e = fspopargs(); errorcheck; fsstack[fsstkpos++] = fsa + fsb; break; case PGTH_OPCMD_MINUS: e = fspopargs(); errorcheck; fsstack[fsstkpos++] = fsa - fsb; break; case PGTH_OPCMD_MULTIPLY: e = fspopargs(); errorcheck; fsstack[fsstkpos++] = fsa * fsb; break; case PGTH_OPCMD_SHIFTL: e = fspopargs(); errorcheck; fsstack[fsstkpos++] = fsa << fsb; break; case PGTH_OPCMD_SHIFTR: e = fspopargs(); errorcheck; fsstack[fsstkpos++] = fsa >> fsb; break; case PGTH_OPCMD_OR: e = fspopargs(); errorcheck; fsstack[fsstkpos++] = fsa | fsb; break; case PGTH_OPCMD_AND: e = fspopargs(); errorcheck; fsstack[fsstkpos++] = fsa & fsb; break; case PGTH_OPCMD_EQ: e = fspopargs(); errorcheck; fsstack[fsstkpos++] = fsa == fsb; break; case PGTH_OPCMD_LT: e = fspopargs(); errorcheck; fsstack[fsstkpos++] = fsa < fsb; break; case PGTH_OPCMD_GT: e = fspopargs(); errorcheck; fsstack[fsstkpos++] = fsa > fsb; break; case PGTH_OPCMD_LOGICAL_OR: e = fspopargs(); errorcheck; fsstack[fsstkpos++] = fsa || fsb; break; case PGTH_OPCMD_LOGICAL_AND: e = fspopargs(); errorcheck; fsstack[fsstkpos++] = fsa && fsb; break; case PGTH_OPCMD_LOGICAL_NOT: fsstack[fsstkpos-1] = !fsstack[fsstkpos-1]; break; case PGTH_OPCMD_DIVIDE: e = fspopargs(); errorcheck; if (fsb) fsstack[fsstkpos++] = fsa / fsb; else fsstack[fsstkpos++] = 0xFFFFFFFF; /* limit of fsa/fsb as fsb approaches 0 */ break; case PGTH_OPCMD_COLORADD: e = fspopargs(); errorcheck; r = getred(fsa); g = getgreen(fsa); b = getblue(fsa); r += getred(fsb); g += getgreen(fsb); b += getblue(fsb); if (r>255) r = 255; if (g>255) g = 255; if (b>255) b = 255; fsstack[fsstkpos++] = mkcolor(r,g,b); break; case PGTH_OPCMD_COLORSUB: e = fspopargs(); errorcheck; r = getred(fsa); g = getgreen(fsa); b = getblue(fsa); r -= getred(fsb); g -= getgreen(fsb); b -= getblue(fsb); if (r<0) r = 0; if (g<0) g = 0; if (b<0) b = 0; fsstack[fsstkpos++] = mkcolor(r,g,b); break; case PGTH_OPCMD_COLORDIV: e = fspopargs(); errorcheck; r = getred(fsa); g = getgreen(fsa); b = getblue(fsa); r = getred(fsb) ? (r/getred(fsb)) : 0xFF; /* Avoid divide by zero */ g = getgreen(fsb) ? (g/getgreen(fsb)) : 0xFF; b = getred(fsb) ? (b/getblue(fsb)) : 0xFF; fsstack[fsstkpos++] = mkcolor(r,g,b); break; case PGTH_OPCMD_COLORMULT: e = fspopargs(); errorcheck; r = getred(fsa); g = getgreen(fsa); b = getblue(fsa); r *= getred(fsb); g *= getgreen(fsb); b *= getblue(fsb); if (r>255) r = 255; if (g>255) g = 255; if (b>255) b = 255; fsstack[fsstkpos++] = mkcolor(r,g,b); break; case PGTH_OPCMD_QUESTIONCOLON: if (fsstkpos<3) return mkerror(PG_ERRT_BADPARAM,88); /* Stack underflow */ fsstkpos -= 2; fsstack[fsstkpos-1] = fsstack[fsstkpos+1] ? fsstack[fsstkpos] : fsstack[fsstkpos-1]; break; case PGTH_OPCMD_WIDGET: if (ctx->owner && ctx->owner->owner) fsstack[fsstkpos++] = hlookup(ctx->owner->owner,NULL); else fsstack[fsstkpos++] = 0; break; case PGTH_OPCMD_TRAVERSEWGT: if (fsstkpos<3) return mkerror(PG_ERRT_BADPARAM,88); /* Stack underflow */ fsstkpos -= 2; e = rdhandle((void**)&w, PG_TYPE_WIDGET, -1, fsstack[fsstkpos+1]); errorcheck; if (w) fsstack[fsstkpos-1] = hlookup(widget_traverse(w,fsstack[fsstkpos],fsstack[fsstkpos-1]),NULL); else fsstack[fsstkpos-1] = 0; break; case PGTH_OPCMD_GETWIDGET: e = fspopargs(); errorcheck; e = rdhandle((void**)&w, PG_TYPE_WIDGET, -1, fsa); errorcheck; if (w) fsstack[fsstkpos++] = widget_get(w,fsb); else fsstack[fsstkpos++] = 0; break; case PGTH_OPCMD_CALL: if ((plimit-p)<4) return mkerror(PG_ERRT_BADPARAM,91); /* Truncated opcode */ fsa = NEXTSHORT; p += 2; fsb = NEXTSHORT; p += 2; e = exec_fillstyle_inner(ctx,fsa,fsb); errorcheck; break; case PGTH_OPCMD_LOCALCALL: if ((plimit-p)<2) return mkerror(PG_ERRT_BADPARAM,91); /* Truncated opcode */ fsb = NEXTSHORT; p += 2; e = exec_fillstyle_inner(ctx,state,fsb); errorcheck; break; case PGTH_OPCMD_EXTENDED: /* extended command */ op = *(p++); switch (op) { case PGTH_EXCMD_SKIP_IF: if (!fsstack[--fsstkpos]) { --fsstkpos; break; } /* else proceed to EXCMD_SKIP */ case PGTH_EXCMD_SKIP: p += (s32)fsstack[--fsstkpos]; break; } break; } } else if (op & PGTH_OPSIMPLE_GET) { /* 1-byte get */ e = fsget((op & (PGTH_OPSIMPLE_GET-1)) + stackframe); errorcheck; } else { /* 1-byte set */ e = fsset(op + stackframe); errorcheck; } #ifdef DEBUG_THEME /* trace */ printf("FILLSTYLE --- Op: 0x%02X Stk:",op); for (fsa=0;fsa<fsstkpos;fsa++) printf(" %d",(int)fsstack[fsa]); printf("\n"); #endif /* check for stack over/underflow */ if (fsstkpos<0) return mkerror(PG_ERRT_BADPARAM,88); /* Stack underflow */ if (fsstkpos>=FSSTACKSIZE) return mkerror(PG_ERRT_BADPARAM,89); /* Stack overflow */ }