b8180d9f6d41dc708a2f249ba892cbca311e7a06
jcasper
  Mon Feb 27 11:38:55 2023 -0800
Adding transparency support for colors refs #30569

diff --git src/inc/memgfx.h src/inc/memgfx.h
index cc08d04..4eec6b9 100644
--- src/inc/memgfx.h
+++ src/inc/memgfx.h
@@ -54,52 +54,54 @@
 #define MG_BROWN   0xff00a0a0
 
 #define MAKECOLOR_32_A(r,g,b,a) (((unsigned int)a<<24) | ((unsigned int)b<<16) | ((unsigned int)g << 8) | (unsigned int)r)
 #define MAKECOLOR_32(r,g,b) (((unsigned int)0xff<<24) | ((unsigned int)b<<16) | ((unsigned int)g << 8) | (unsigned int)r)
 #define COLOR_32_RED(c) ((c)&0xff)
 #define COLOR_32_GREEN(c) (((c)>>8)&0xff)
 #define COLOR_32_BLUE(c) (((c)>>16)&0xff)
 #define COLOR_32_ALPHA(c) (((c)>>24)&0xff)
 #endif
 
 #define MG_WRITE_MODE_NORMAL    0
 #define MG_WRITE_MODE_MULTIPLY  (1 << 0)
 
 struct rgbColor
     {
-    unsigned char r, g, b;
+    unsigned char r, g, b, a;
     };
 
 /* HSV and HSL structs can be used for changing lightness, darkness, or
  * color of RGB colors. Convert RGB->HS[LV], modify hue, saturation, or
  * value/lightness, then convert back to RGB.
  * The datatypes were chosen to be fast but also give accurate conversion
  * back to RGB.
  * Hue is a float [0,360) degrees 0=red, 120=green, 240=blue
  * S/V/L are integers [0,1000]
  */
 
 struct hsvColor
     {
     double h;
     unsigned short s, v;
+    unsigned char alpha;
     };
 
 struct hslColor
     {
     double h;
     unsigned short s, l;
+    unsigned char alpha;
     };
 
 extern struct rgbColor mgFixedColors[9];  /* Contains MG_WHITE - MG_GRAY */
 
 struct memGfx
     {
     Color *pixels;
     int width, height;
     struct rgbColor colorMap[256];
     int colorsUsed;
     int clipMinX, clipMaxX;
     int clipMinY, clipMaxY;
     struct colHash *colorHash;	/* Hash for fast look up of color. */
     unsigned int writeMode;
     unsigned int fontMethod;
@@ -405,49 +407,79 @@
 struct rgbColor mgRgbTransformHsv(struct rgbColor in, double h, double s, double v);
 /* Transform rgb 'in' value using
  *   hue shift 'h' (0..360 degrees), 
  *   saturation scale 's', and 
  *   value scale 'v'
  * Returns the transformed rgb value 
  * Use H=0, S=V=1 for identity transformation
  */
 
 struct rgbColor mgColorIxToRgb(struct memGfx *mg, int colorIx);
 /* Return rgb value at color index. */
 
 struct rgbColor colorIxToRgb(int colorIx);
 /* Return rgb value at color index. */
 
+INLINE void mixColor(Color *d, Color s)
+/* Blend the color at s into d, respecting alpha */
+{
+int aA = COLOR_32_ALPHA(s);
+int rA = COLOR_32_RED(s);
+int gA = COLOR_32_GREEN(s);
+int bA = COLOR_32_BLUE(s);
+
+int aB = COLOR_32_ALPHA(*d);
+int rB = COLOR_32_RED(*d);
+int gB = COLOR_32_GREEN(*d);
+int bB = COLOR_32_BLUE(*d);
+
+double aOut = aA + (aB * (255.0 - aA) / 255);
+int rOut, gOut, bOut;
+if (aOut == 0)
+    rOut = gOut = bOut = 0;
+else
+    {
+    rOut = (rA * aA + rB * aB * (255 - aA) / 255)/aOut ;
+    gOut = (gA * aA + gB * aB * (255 - aA) / 255)/aOut ;
+    bOut = (bA * aA + bB * aB * (255 - aA) / 255)/aOut ;
+    }
+*d = MAKECOLOR_32_A(rOut,gOut,bOut,aOut);
+}
+
 INLINE void mixDot(struct memGfx *img, int x, int y,  float frac, Color col)
 /* Puts a single dot on the image, mixing it with what is already there
  * based on the frac argument. */
 /* Shouldn't this pay attention to the transparency of the current pixel? */
 {
 if ((x < img->clipMinX) || (x >= img->clipMaxX) || (y < img->clipMinY) || (y >= img->clipMaxY))
     return;
 
 Color *pt = _mgPixAdr(img,x,y);
 
 /* algorithm borrowed from https://en.wikipedia.org/wiki/Alpha_compositing */
 int aA = frac * 255;
 int rA = COLOR_32_RED(col);
 int gA = COLOR_32_GREEN(col);
 int bA = COLOR_32_BLUE(col);
+int tempC = MAKECOLOR_32_A(rA, gA, bA, aA);
 
+mixColor(pt, tempC);
+/*
 int aB = COLOR_32_ALPHA(*pt);
 int rB = COLOR_32_RED(*pt);
 int gB = COLOR_32_GREEN(*pt);
 int bB = COLOR_32_BLUE(*pt);
 
 double aOut = aA + (aB * (255.0 - aA) / 255);
 int rOut, gOut, bOut;
 if (aOut == 0)
     rOut = gOut = bOut = 0;
 else
     {
     rOut = (rA * aA + rB * aB * (255 - aA) / 255)/aOut ;
     gOut = (gA * aA + gB * aB * (255 - aA) / 255)/aOut ;
     bOut = (bA * aA + bB * aB * (255 - aA) / 255)/aOut ;
     }
 mgPutDot(img,x,y,MAKECOLOR_32_A(rOut,gOut,bOut,aOut));
+*/
 }
 #endif /* MEMGFX_H */