gnustep-dev
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Color handling implemented in GSGState


From: Alexander Malmberg
Subject: Re: Color handling implemented in GSGState
Date: Mon, 13 May 2002 01:00:54 +0200

[snip]
> There seems to be a few problems with color conversions and out-of-range
> inputs to the color functions; I'll probably send a patch for that soon.

And here it is. Inputs to the color-setting functions are now clamped
properly. Hue==1.0 is converted to rgb properly (wasn't being caught in
the switch since i==6). Color conversions to cmyk and hsb are
implemented (I took the hsb code from NSColor; the cmyk black component
part is a bit of a hack, but it shows how it can be done it it's 
necessary).

- Alexander Malmberg
Index: Source/gsc/GSGState.m
===================================================================
RCS file: /cvsroot/gnustep/gnustep/core/back/Source/gsc/GSGState.m,v
retrieving revision 1.4
diff -u -r1.4 GSGState.m
--- Source/gsc/GSGState.m       10 May 2002 15:06:17 -0000      1.4
+++ Source/gsc/GSGState.m       12 May 2002 22:43:24 -0000
@@ -236,32 +238,46 @@
   *r = gcolor.field[0]; *g = gcolor.field[1]; *b = gcolor.field[2];
 }
 
+#define CLAMP(x) \
+  if (x < 0.0) x = 0.0; \
+  if (x > 1.0) x = 1.0;
+
 - (void) DPSsetalpha: (float)a
 {
+  CLAMP(a)
   fillColor.field[AINDEX] = strokeColor.field[AINDEX] = a;
-  /* Is this necessary?
   [self setColor: fillColor state: COLOR_FILL];
   [self setColor: strokeColor state: COLOR_STROKE];
-  */
 }
 
 - (void) DPSsetcmykcolor: (float)c : (float)m : (float)y : (float)k
 {
+  CLAMP(c)
+  CLAMP(m)
+  CLAMP(y)
+  CLAMP(k)
   [self setColor: gsMakeColor(cmyk_colorspace, c, m, y, k) state: COLOR_BOTH];
 }
 
 - (void) DPSsetgray: (float)gray
 {
+  CLAMP(gray)
   [self setColor: gsMakeColor(gray_colorspace, gray, 0, 0, 0) state: 
COLOR_BOTH];
 }
 
 - (void) DPSsethsbcolor: (float)h : (float)s : (float)b
 {
+  CLAMP(h)
+  CLAMP(s)
+  CLAMP(b)
   [self setColor: gsMakeColor(hsb_colorspace, h, s, b, 0) state: COLOR_BOTH];
 }
 
 - (void) DPSsetrgbcolor: (float)r : (float)g : (float)b
 {
+  CLAMP(r)
+  CLAMP(g)
+  CLAMP(b)
   [self setColor: gsMakeColor(rgb_colorspace, r, g, b, 0) state: COLOR_BOTH];
 }
 
Index: Source/gsc/gscolors.c
===================================================================
RCS file: /cvsroot/gnustep/gnustep/core/back/Source/gsc/gscolors.c,v
retrieving revision 1.1
diff -u -r1.1 gscolors.c
--- Source/gsc/gscolors.c       10 May 2002 15:06:17 -0000      1.1
+++ Source/gsc/gscolors.c       12 May 2002 22:43:24 -0000
@@ -71,6 +71,7 @@
   
   switch (i) 
     {
+    default: /* catch h==1.0 */
     case 0:
       red = v;
       green = t;
@@ -118,7 +119,7 @@
   y = color.field[2];
   k = color.field[3];
   white = 1 - k;
-             
+
   if (k == 0)
     {
       red = 1 - c;
@@ -190,7 +191,6 @@
   return new;
 }
 
-/* FIXME: Not implemented */
 device_color_t 
 gsColorToCMYK(device_color_t color)
 {
@@ -200,10 +200,46 @@
   switch(color.space)
     {
     case gray_colorspace:
-      break;
-    case rgb_colorspace:
+      new.field[0] = 0.0;
+      new.field[1] = 0.0;
+      new.field[2] = 0.0;
+      new.field[3] = color.field[0];
       break;
     case hsb_colorspace:
+      color = gsColorToRGB(color);
+      /* NO BREAK */
+    case rgb_colorspace:
+      new.field[0] = 1.0 - color.field[0];
+      new.field[1] = 1.0 - color.field[1];
+      new.field[2] = 1.0 - color.field[2];
+      new.field[3] = 0;
+
+      /* Add a bit of black if possible (for no reason, really). */
+      new.field[3] = new.field[0];
+      new.field[0] = 0.0;
+      new.field[1] -= new.field[3];
+      new.field[2] -= new.field[3];
+      if (new.field[1] > new.field[2])
+       {
+         if (new.field[2] < 0.0)
+           {
+             new.field[0] -= new.field[2];
+             new.field[1] -= new.field[2];
+             new.field[3] += new.field[2];
+             new.field[2] = 0;
+           }
+       }
+      else
+       {
+         if (new.field[1] < 0.0)
+           {
+             new.field[0] -= new.field[1];
+             new.field[2] -= new.field[1];
+             new.field[3] += new.field[1];
+             new.field[1] = 0;
+           }
+       }
+      
       break;
     case cmyk_colorspace: 
       new = color;
@@ -214,7 +250,6 @@
   return new;
 }
 
-/* FIXME: Not implemented */
 device_color_t 
 gsColorToHSB(device_color_t color)
 {
@@ -224,13 +259,65 @@
   switch(color.space)
     {
     case gray_colorspace:
+      new.field[0] = 0.0;
+      new.field[1] = 0.0;
+      new.field[2] = color.field[0];
       break;
+    case cmyk_colorspace:
+      color = gsColorToRGB(color);
+      /* NO BREAK */
     case rgb_colorspace:
+      {
+       float r = color.field[0];
+       float g = color.field[1];
+       float b = color.field[2];
+       float _hue_component, _saturation_component, _brightness_component;
+
+       if (r == g && r == b)
+         {
+           _hue_component = 0;
+           _saturation_component = 0;
+           _brightness_component = r;
+         }
+       else
+         {
+           double H;
+           double V;
+           double Temp;
+           double diff;
+       
+           V = (r > g ? r : g);
+           V = (b > V ? b : V);
+           Temp = (r < g ? r : g);
+           Temp = (b < Temp ? b : Temp);
+           diff = V - Temp;
+           if (V == r)
+             {
+               H = (g - b)/diff;
+             }
+           else if (V == g)
+             {
+               H = (b - r)/diff + 2;
+             }
+           else
+             {
+               H = (r - g)/diff + 4;
+             }
+           if (H < 0)
+             {
+               H += 6;
+             }
+           _hue_component = H/6;
+           _saturation_component = diff/V;
+           _brightness_component = V;
+         }
+       new.field[0] = _hue_component;
+       new.field[1] = _saturation_component;
+       new.field[2] = _brightness_component;
+      }
       break;
     case hsb_colorspace:
-      new = color;
-      break;
-    case cmyk_colorspace: 
+      new = color = gsColorToRGB(color);
       break;
     default:
       break;


reply via email to

[Prev in Thread] Current Thread [Next in Thread]