static void Draw(void *obj) { AG_HSVPal *pal = obj; float cur_h, cur_s, cur_v; Uint8 r, g, b, a; int x, y; if (pal->surface == NULL) { if ((pal->surface = AG_SurfaceStdGL(WIDTH(pal), HEIGHT(pal))) == NULL) { return; } pal->surfaceId = AG_WidgetMapSurface(pal, pal->surface); } if (pal->flags & AG_HSVPAL_DIRTY) { pal->flags &= ~(AG_HSVPAL_DIRTY); RenderPalette(pal); AG_WidgetUpdateSurface(pal, pal->surfaceId); } cur_h = (AG_GetFloat(pal, "hue") / 360.0) * 2*AG_PI; cur_s = AG_GetFloat(pal, "saturation"); cur_v = AG_GetFloat(pal, "value"); a = (Uint8)(AG_GetFloat(pal, "alpha")*255); AG_WidgetBlitFrom(pal, pal, pal->surfaceId, NULL, 0, 0); /* Indicate the current selection. */ AG_DrawCircle(pal, pal->circle.x + (pal->circle.rin + pal->circle.width/2)*Cos(cur_h), pal->circle.y + (pal->circle.rin + pal->circle.width/2)*Sin(cur_h), pal->selcircle_r, AG_ColorRGB(0,0,0)); /* The rendering routine uses (v = 1 - x/h), so (x = -v*h + h). */ y = (int)((1.0 - cur_s) * (float)pal->triangle.h); x = (int)(-(cur_v*(float)pal->triangle.h - (float)pal->triangle.h)); if (x < 0) { x = 0; } if (x > y) { x = y; } AG_DrawCircle(pal, pal->triangle.x + x - y/2, pal->triangle.y + y, pal->selcircle_r, AG_ColorRGB(0,0,0)); x = a*pal->rAlpha.w/255; if (x > pal->rAlpha.w-3) { x = pal->rAlpha.w-3; } AG_HSV2RGB((cur_h*360.0)/(2*AG_PI), cur_s, cur_v, &r, &g, &b); /* Draw the color preview. */ if (!(pal->flags & AG_HSVPAL_NOPREVIEW)) { AG_DrawRectFilled(pal, AG_RECT(pal->rAlpha.x, pal->rAlpha.y, pal->rAlpha.w, 8), AG_ColorRGB(r,g,b)); } /* Draw the transparency color preview. */ if (!(pal->flags & AG_HSVPAL_NOALPHA)) { AG_DrawLineV(pal, pal->rAlpha.x + x, pal->rAlpha.y + 1, pal->rAlpha.y + pal->rAlpha.h, AG_ColorRGBA(0,0,0,0)); AG_DrawLineV(pal, pal->rAlpha.x + x + 1, pal->rAlpha.y + 1, pal->rAlpha.y + pal->rAlpha.h, AG_ColorRGBA(240,240,240,0)); AG_DrawLineV(pal, pal->rAlpha.x + x + 2, pal->rAlpha.y + 1, pal->rAlpha.y + pal->rAlpha.h, AG_ColorRGBA(0,0,0,0)); } /* Display RGB/HSV values */ if (pal->flags & (AG_HSVPAL_SHOW_RGB|AG_HSVPAL_SHOW_HSV)) { AG_Surface *s; /* XXX inefficient */ AG_PushTextState(); AG_TextBGColorRGB(0,0,0); AG_TextColorRGB(255,255,255); if ((pal->flags & AG_HSVPAL_SHOW_RGB) && (pal->flags & AG_HSVPAL_SHOW_HSV)) { s = AG_TextRenderf( "RGB: %u,%u,%u\n" "HSV: %.02f,%.02f,%.02f", r, g, b, (cur_h*360.0)/(2.0*AG_PI), cur_s, cur_v); } else if (pal->flags & AG_HSVPAL_SHOW_RGB) { s = AG_TextRenderf("RGB: %u,%u,%u", r, g, b); } else { s = AG_TextRenderf("HSV: %.01f,%.02f,%.02f", (cur_h*360.0)/(2.0*AG_PI), cur_s, cur_v); } AG_WidgetBlit(pal, s, WIDTH(pal)/2 - s->w/2, pal->rAlpha.y + pal->rAlpha.h/2 - s->h/2); AG_SurfaceFree(s); AG_PopTextState(); } }
static __inline__ void UpdatePixelFromHSVA(AG_HSVPal *pal) { Uint8 r, g, b, a; AG_Variable *bFormat, *bColor, *bv; AG_PixelFormat **pFormat; AG_Color *pColor; void *v; AG_HSV2RGB(AG_GetFloat(pal, "hue"), AG_GetFloat(pal, "saturation"), AG_GetFloat(pal, "value"), &r, &g, &b); a = GetAlpha8(pal); if ((bv = AG_GetVariable(pal, "RGBv", &v)) != NULL) { switch (AG_VARIABLE_TYPE(bv)) { case AG_VARIABLE_FLOAT: ((float *)v)[0] = (float)r/255.0; ((float *)v)[1] = (float)g/255.0; ((float *)v)[2] = (float)b/255.0; break; case AG_VARIABLE_DOUBLE: ((double *)v)[0] = (double)r/255.0; ((double *)v)[1] = (double)g/255.0; ((double *)v)[2] = (double)b/255.0; break; case AG_VARIABLE_INT: ((int *)v)[0] = (int)r; ((int *)v)[1] = (int)g; ((int *)v)[2] = (int)b; break; case AG_VARIABLE_UINT8: ((Uint8 *)v)[0] = r; ((Uint8 *)v)[1] = g; ((Uint8 *)v)[2] = b; break; default: break; } AG_UnlockVariable(bv); } if ((bv = AG_GetVariable(pal, "RGBAv", &v)) != NULL) { switch (AG_VARIABLE_TYPE(bv)) { case AG_VARIABLE_FLOAT: ((float *)v)[0] = (float)r/255.0; ((float *)v)[1] = (float)g/255.0; ((float *)v)[2] = (float)b/255.0; ((float *)v)[3] = (float)a/255.0; break; case AG_VARIABLE_DOUBLE: ((double *)v)[0] = (double)r/255.0; ((double *)v)[1] = (double)g/255.0; ((double *)v)[2] = (double)b/255.0; ((double *)v)[3] = (double)a/255.0; break; case AG_VARIABLE_INT: ((int *)v)[0] = (int)r; ((int *)v)[1] = (int)g; ((int *)v)[2] = (int)b; ((int *)v)[3] = (int)a; break; case AG_VARIABLE_UINT8: ((Uint8 *)v)[0] = r; ((Uint8 *)v)[1] = g; ((Uint8 *)v)[2] = b; ((Uint8 *)v)[3] = a; break; default: break; } AG_UnlockVariable(bv); } bFormat = AG_GetVariable(pal, "pixel-format", &pFormat); AG_SetUint32(pal, "pixel", AG_MapPixelRGBA(*pFormat, r,g,b,a)); AG_UnlockVariable(bFormat); bColor = AG_GetVariable(pal, "color", &pColor); pColor->r = r; pColor->g = g; pColor->b = b; pColor->a = a; AG_UnlockVariable(bColor); AG_Redraw(pal); }
static void RenderPalette(AG_HSVPal *pal) { AG_Surface *ds = pal->surface; float h, cur_h, cur_s, cur_v; AG_Color C; Uint32 px; /* Uint8 da; */ int x, y, i; AG_Rect rd; AG_FillRect(ds, NULL, AG_ColorRGB(0,0,0)); cur_h = (AG_GetFloat(pal, "hue")/360) * 2*AG_PI; cur_s = AG_GetFloat(pal, "saturation"); cur_v = AG_GetFloat(pal, "value"); /* Render the circle of hues. */ for (h = 0.0; h < 2*AG_PI; h += pal->circle.dh) { AG_HSV2RGB((h/(2*AG_PI)*360.0), 1.0, 1.0, &C.r, &C.g, &C.b); px = AG_MapColorRGB(ds->format, C); for (i = 0; i < pal->circle.width; i++) { x = (pal->circle.rout - i)*Cos(h); y = (pal->circle.rout - i)*Sin(h); AG_PUT_PIXEL2(ds, pal->circle.x+x, pal->circle.y+y, px); } } /* Render the triangle of saturation and value. */ for (y = 0; y < pal->triangle.h; y += 2) { float sat = (float)(pal->triangle.h - y) / (float)(pal->triangle.h); for (x = 0; x < y; x++) { AG_HSV2RGB((cur_h/(2*AG_PI))*360.0, sat, 1.0 - ((float)x/(float)pal->triangle.h), &C.r, &C.g, &C.b); px = AG_MapColorRGB(ds->format, C); AG_PUT_PIXEL2(ds, pal->triangle.x + x - y/2, pal->triangle.y + y, px); AG_PUT_PIXEL2(ds, pal->triangle.x + x - y/2, pal->triangle.y + y + 1, px); } } if (!(pal->flags & AG_HSVPAL_NOALPHA)) { /* Render the color preview. */ /* XXX overblending */ for (y = 8; y < pal->rAlpha.h+16; y+=8) { for (x = 0; x < pal->rAlpha.w; x+=16) { rd.w = 8; rd.h = 8; rd.x = pal->rAlpha.x+x; rd.y = pal->rAlpha.y+y; AG_FillRect(ds, &rd, pal->cTile); } y += 8; for (x = 8; x < pal->rAlpha.w; x+=16) { rd.w = 8; rd.h = 8; rd.x = pal->rAlpha.x+x; rd.y = pal->rAlpha.y+y; AG_FillRect(ds, &rd, pal->cTile); } } AG_HSV2RGB((cur_h/(2*AG_PI))*360.0, cur_s, cur_v, &C.r, &C.g, &C.b); /* da = MIN(1, ds->w/255); */ for (y = pal->rAlpha.y+8; y < ds->h; y++) { for (x = 0, C.a = 0; x < ds->w; x++) { AG_BLEND_RGBA2(ds, x, y, C.r, C.g, C.b, C.a, AG_ALPHA_SRC); C.a = x*255/ds->w; } } } }
AG_Color AG_ColorFromString(const char *s, const AG_Color *pColor) { char buf[128]; AG_Color cIn = (pColor != NULL) ? *pColor : AG_ColorRGB(0,0,0); AG_Color cOut = cIn; double v[4]; int isPct[4], isHSV = 0; char *c, *pc; int i, argc; Strlcpy(buf, s, sizeof(buf)); for (c = &buf[0]; *c != '\0' && isspace(*c); c++) { ;; } switch (*c) { case 'r': /* rgb(r,g,b[,a]) */ break; case 'h': /* hsv(h,s,v[,a]) */ isHSV = 1; break; default: return (cOut); } for (; *c != '\0' && *c != '('; c++) ;; if (*c == '\0' || c[1] == '\0') { goto out; } pc = &c[1]; for (i = 0, argc = 0; i < 4; i++) { char *tok, *ep; if ((tok = AG_Strsep(&pc, ",")) == NULL) { break; } v[i] = strtod(tok, &ep); isPct[i] = (*ep == '%'); argc++; } if (argc < 3) { goto out; } if (isHSV) { float hue, sat, val; AG_RGB2HSV(cIn.r, cIn.g, cIn.b, &hue, &sat, &val); hue = isPct[0] ? ColorPct(hue, v[0]) : v[0]; sat = isPct[1] ? ColorPct(sat, v[1]) : v[1]; val = isPct[2] ? ColorPct(val, v[2]) : v[2]; AG_HSV2RGB(hue, sat, val, &cOut.r, &cOut.g, &cOut.b); if (argc == 4) { cOut.a = isPct[3] ? ColorPct(cIn.a, v[3]) : v[3]; } else { cOut.a = cIn.a; } } else { cOut.r = isPct[0] ? (Uint8)ColorPct(cIn.r, v[0]) : (Uint8)v[0]; cOut.g = isPct[1] ? (Uint8)ColorPct(cIn.g, v[1]) : (Uint8)v[1]; cOut.b = isPct[2] ? (Uint8)ColorPct(cIn.b, v[2]) : (Uint8)v[2]; if (argc == 4) { cOut.a = isPct[3] ? (Uint8)ColorPct(cIn.a, v[3]) : (Uint8)v[3]; } else { cOut.a = cIn.a; } } out: return (cOut); }