예제 #1
0
static void setup_players(void) {
  n_players = 2;

  players = malloc(n_players * sizeof(player_t));

  init_player(&players[0], mkcolor(255, 0, 0));
  players[0].keydefs[0] = KEYDEF(3, 0x10000000) /* right */;
  players[0].keydefs[1] = KEYDEF(3, 0x40000000) /* up */;
  players[0].keydefs[2] = KEYDEF(3, 0x08000000) /* left */;
  players[0].keydefs[3] = KEYDEF(3, 0x20000000) /* down */;

  init_player(&players[1], mkcolor(0, 255, 0));
  players[1].keydefs[0] = KEYDEF(0, 0x00000002) /* s */;
  players[1].keydefs[1] = KEYDEF(0, 0x00002000) /* w */;
  players[1].keydefs[2] = KEYDEF(0, 0x00000001) /* a */;
  players[1].keydefs[3] = KEYDEF(0, 0x00000040) /* z */;
}
예제 #2
0
파일: gif.c 프로젝트: scanlime/picogui
/* Transcribe one scanline from the GIF to the picogui bitmap */
void dither_transcribe_line(hwrdither d, GifFileType *f, 
		     int transparent_flag, int transparent_color) {
  pgcolor c;
  u8 pixel;
  GifColorType *color;
  int x;

  for (x=0;x<f->Image.Width;x++) {
    DGifGetPixel(f, &pixel);
    color = f->SColorMap->Colors + (pixel % f->SColorMap->ColorCount);
    if (transparent_flag) {
      c = mkcolora(pixel==transparent_color ? 0 : 127,color->Red,color->Green,color->Blue);
    }
    else {
      c = mkcolor(color->Red,color->Green,color->Blue);
    }
    vid->dither_store(d,c,PG_LGOP_NONE);
  }
}
예제 #3
0
파일: gif.c 프로젝트: scanlime/picogui
/* Transcribe one scanline from the GIF to the picogui bitmap */
void transcribe_line(hwrbitmap b, GifFileType *f, int y, 
		     int transparent_flag, int transparent_color) {
  pgcolor c;
  u8 pixel;
  GifColorType *color;
  int x;

  for (x=0;x<f->Image.Width;x++) {
    DGifGetPixel(f, &pixel);
    color = f->SColorMap->Colors + (pixel % f->SColorMap->ColorCount);
    if (transparent_flag) {
      c = mkcolora(pixel==transparent_color ? 0 : 127,color->Red,color->Green,color->Blue);
    }
    else {
      c = mkcolor(color->Red,color->Green,color->Blue);
    }
    vid->pixel(b,x,y,VID(color_pgtohwr)(c),PG_LGOP_NONE);
  }
}
예제 #4
0
파일: jpeg.c 프로젝트: scanlime/picogui
g_error jpeg_load(hwrbitmap *hbmp, const u8 *data, u32 datalen) {
  /* Convert from any of the pbmplus formats in binary or ascii */
  struct stdbitmap **bmp = (struct stdbitmap **) hbmp;
  g_error e;
  int i,r,g,b,x,y;

  int pixels;
  int bytes;
  int scanline_bytes;
  struct jpeg_decompress_struct cinfo; 
  struct jpeg_error_mgr jerr; 
  JSAMPARRAY buffer;		/* Output row buffer */
#ifdef CONFIG_DITHER
  hwrdither dither;
#endif

  g_error efmt = mkerror(PG_ERRT_BADPARAM,48);

  if (!datalen) return efmt;

  /* get jpeg info */
  cinfo.err = jpeg_std_error(&jerr); 
  jpeg_create_decompress(&cinfo); 
  jpeg_mem_src(&cinfo, (unsigned char *) data, datalen);  
  jpeg_read_header(&cinfo, TRUE); 
  jpeg_start_decompress(&cinfo);

  /* determine memory requirements */
  pixels = cinfo.output_width * cinfo.output_height;
  bytes  = pixels * cinfo.output_components;
  scanline_bytes = cinfo.output_components * cinfo.output_width;

#if DEBUG
  printf(__FUNCTION__ "() image is %dx%dx%d (%d bytes), colorspace=%d\n",	   cinfo.output_width,
	 cinfo.output_height,
	 cinfo.output_components,
	 bytes,
	 cinfo.out_color_components);
#endif

  /* Set up the bitmap */
  e = vid->bitmap_new((hwrbitmap *)bmp,cinfo.output_width,
		      cinfo.output_height,vid->bpp);
  errorcheck;

#ifdef CONFIG_DITHER
  /* Start dithering */
  e = vid->dither_start(&dither, *bmp, 0,0,0,cinfo.output_width,cinfo.output_height);
  errorcheck;
#endif

  /* Make a one-row-high sample array that will go away when done with image */
  buffer = (*cinfo.mem->alloc_sarray)
		((j_common_ptr) &cinfo, JPOOL_IMAGE, scanline_bytes, 1);

  y = 0;
  while (cinfo.output_scanline <   cinfo.output_height  ) 
  {

    jpeg_read_scanlines(&cinfo, buffer, 1);

    /* process scanline */
    for (i=0,x=0;i<scanline_bytes;x++) {

      switch(cinfo.out_color_components) {
      case 3:
	r = (*buffer)[i++];
	g = (*buffer)[i++];
	b = (*buffer)[i++];
	break;
      default:
	r = g = b = (*buffer)[i++];
      }

#ifdef CONFIG_DITHER
      vid->dither_store(dither, mkcolor(r,g,b), PG_LGOP_NONE);
#else
      vid->pixel(*bmp,x,y,vid->color_pgtohwr(mkcolor(r,g,b)),PG_LGOP_NONE);
#endif
    }
    y++;
  }
  jpeg_finish_decompress(&cinfo);
  jpeg_destroy_decompress(&cinfo);
#ifdef CONFIG_DITHER
  vid->dither_finish(dither);
#endif

  return success;
}
예제 #5
0
g_error load_custom_palette(const char *name) {
  int i;
  FILE *f;
  char linebuffer[256];
  char *p;
  int r,g,b;

  if (name) {
    /* Load a gimp-format palette from file */
   
    f = fopen(name,"r");
    if (!f)
      return mkerror(PG_ERRT_IO,110);    /* Can't open palette */

    /* Zero unused entries */
    memset(palette8_custom,0,sizeof(palette8_custom));
    i = 0;

    while (fgets(linebuffer,sizeof(linebuffer)-1,f)) {
      linebuffer[sizeof(linebuffer)-1] = 0;

      /* Strip comments out */
      p = strchr(linebuffer,'#');
      if (p)
	*p = 0;

      /* Strip leading whitespace */
      p = linebuffer;
      while (isspace(*p))
	p++;

      /* If there's anything else, read in the palette entry */
      if (*p) {
	sscanf(p, "%d %d %d", &r,&g,&b);
	palette8_custom[(i++)&0xFF] = mkcolor(r,g,b);
      }
    }
    fclose(f);
  }
  else {
    /* Load a default palette.
     * Grayscale is an easy fallback, but we can optionally include
     * a copy of the visibone2 palette from Gimp
     */
    
#ifdef CONFIG_PAL8_VISIBONE2
    memcpy(palette8_custom,visibone2_palette,sizeof(palette8_custom));
#else
    for (i=0;i<256;i++)
      palette8_custom[i] = mkcolor(i,i,i);
#endif
  }    

  /* Now sort the palette by luminance so the AND/OR effects and such work */
  qsort(palette8_custom, 256, sizeof(pgcolor), compare_luminance);

  /* Build the palette hash table if we're using one.
   * Note the extra care in bitshifting so that we really do get pure white,
   * rather than always truncating a bit or three
   */

#ifdef CONFIG_PAL8_LOOKUP_32K
  for (i=0;i<sizeof(palette_hash)/sizeof(palette_hash[0]);i++) {
    int r = i >> 10;
    int g = (i >> 5 ) & 0x1F;
    int b = i & 0x1F;
    palette_hash[i] = palette_lookup(mkcolor( (r >> 2) | (r << 3),
					      (g >> 2) | (g << 3),
					      (b >> 2) | (b << 3) ));
  }
#endif

#ifdef CONFIG_PAL8_LOOKUP_256K
  for (i=0;i<sizeof(palette_hash)/sizeof(palette_hash[0]);i++) {
    int r = i >> 12;
    int g = (i >> 6 ) & 0x3F;
    int b = i & 0x3F;
    palette_hash[i] = palette_lookup(mkcolor( (r >> 4) | (r << 2),
					      (g >> 4) | (g << 2),
					      (b >> 4) | (b << 2) ));
  }
#endif

  return success;
}
예제 #6
0
파일: png.c 프로젝트: UIKit0/picogui
g_error png_load(hwrbitmap *hbmp, const u8 *data, u32 datalen) {
  png_structp png_ptr;
  png_infop info_ptr;
  struct datablock d;
  png_bytep *row_pointers;
  png_uint_32 width, height;
  int bit_depth,colortype,interlace;
  int x,y;
  u8 r,g,b,a;
  pgcolor c;
  png_bytep p;
  g_error e;
  png_colorp palette;
  int num_palette;
  png_colorp pp;
  png_bytep trans;
  int num_trans = 0;
#ifdef CONFIG_DITHER
  hwrdither dither;
#endif

  png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
  if (!png_ptr)
    return mkerror(PG_ERRT_IO, 68);   /* Error initializing libpng */
  
  info_ptr = png_create_info_struct(png_ptr);
  if (!info_ptr) {
    png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
    return mkerror(PG_ERRT_IO, 68);   /* Error initializing libpng */
  }

  /* Set libpng error handler */
  if (setjmp(png_jmpbuf(png_ptr))) {
    png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
    return mkerror(PG_ERRT_IO, 71);   /* Error reading PNG */
  }

  /* Set libpng read handler */
  d.data = data;
  d.length = datalen;
  png_set_read_fn(png_ptr, &d, (png_rw_ptr) &png_user_read_data);

  /* Read the png into memory */
  png_read_png(png_ptr, info_ptr, 
	       PNG_TRANSFORM_STRIP_16 | 
	       PNG_TRANSFORM_PACKING, 
	       NULL);
  row_pointers = png_get_rows(png_ptr, info_ptr);
  png_get_IHDR(png_ptr, info_ptr, &width, &height,
	       &bit_depth, &colortype, &interlace, NULL, NULL);
  if (colortype == PNG_COLOR_TYPE_PALETTE) {
    png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette);
    png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, NULL);
  }
  if (interlace != PNG_INTERLACE_NONE)
    fprintf(stderr, "png loader: OOPS... interlaced image, will b0rk\n");
  
  /* Allocate the picogui bitmap
   *
   * Important note: normally we create bitmaps at the display's
   *                 color depth, but if we have an alpha channel
   *                 we need room for ARGB colors.
   */
  if (colortype == PNG_COLOR_TYPE_GRAY_ALPHA ||
      colortype == PNG_COLOR_TYPE_RGB_ALPHA ||
      num_trans)
    e = vid->bitmap_new(hbmp,width,height,32);
  else
    e = vid->bitmap_new(hbmp,width,height,vid->bpp);
  if (iserror(e))
    png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);    
  errorcheck;

#ifdef CONFIG_DITHER
  /* Start dithering */
  e = vid->dither_start(&dither, *hbmp, 0,0,0,width,height);
  errorcheck;
#endif

  /* Transcribe it into a picogui bitmap. 
   * This method is slow, but ensures compatibility 
   */
  for (y=0;y<height;y++) {
    p = row_pointers[y];
    for (x=0;x<width;x++) {
      switch (colortype) {

      case PNG_COLOR_TYPE_GRAY:
	g = *(p++);
	c = mkcolor(g,g,g);
	break;

      case PNG_COLOR_TYPE_GRAY_ALPHA:
	g = *(p++);
	a = *(p++);
	c = mkcolora(a>>1,g,g,g);
	break;

      case PNG_COLOR_TYPE_PALETTE:
	pp = &palette[ (*p) % num_palette ];
	if (*p < num_trans)
	  c = mkcolora(trans[*p]>>1, pp->red, pp->green, pp->blue);
	else if (num_trans)
	  c = mkcolora(0x7f, pp->red, pp->green, pp->blue);
	else
	  c = mkcolor(pp->red, pp->green, pp->blue);
	p++;
	break;

      case PNG_COLOR_TYPE_RGB:
	r = *(p++);
	g = *(p++);
	b = *(p++);
	c = mkcolor(r,g,b);
	break;

      case PNG_COLOR_TYPE_RGB_ALPHA:
	r = *(p++);
	g = *(p++);
	b = *(p++);
	a = *(p++);
	c = mkcolora(a>>1,r,g,b);
	break;
	
      }
#ifdef CONFIG_DITHER
      vid->dither_store(dither, c, PG_LGOP_NONE);
#else
      vid->pixel(*hbmp,x,y,VID(color_pgtohwr)(c),PG_LGOP_NONE);
#endif
    }
  }
예제 #7
0
/* 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 */
  }