move color functions, finish scouring the main PGraphics class

This commit is contained in:
benfry
2008-10-02 21:51:15 +00:00
parent f8d726fe1a
commit 870ccb59ed
2 changed files with 272 additions and 251 deletions
+11
View File
@@ -349,6 +349,11 @@ style(PStyle s)
protected void backgroundFromCalc()
protected void backgroundImpl()
public final int color(int gray)
public final int color(int gray, int alpha)
public final int color(int rgb, float alpha)
public final int color(int x, int y, int z)
public final float alpha(int what)
public final float red(int what)
public final float green(int what)
@@ -360,6 +365,12 @@ style(PStyle s)
public int lerpColor(int c1, int c2, float amt)
static public int lerpColor(int c1, int c2, float amt, int mode)
public void beginRaw(PGraphics rawGraphics)
public void endRaw()
static public void showWarning(String msg)
static public void showException(String msg)
public boolean displayable()
public boolean dimensional() // better name for this?
+261 -251
View File
@@ -3764,230 +3764,6 @@ public class PGraphics extends PImage implements PConstants {
//////////////////////////////////////////////////////////////
// COLOR MODE
public void colorMode(int mode) {
colorMode(mode, colorModeX, colorModeY, colorModeZ, colorModeA);
}
public void colorMode(int mode, float max) {
colorMode(mode, max, max, max, max);
}
/**
* Set the colorMode and the maximum values for (r, g, b)
* or (h, s, b).
* <P>
* Note that this doesn't set the maximum for the alpha value,
* which might be confusing if for instance you switched to
* <PRE>colorMode(HSB, 360, 100, 100);</PRE>
* because the alpha values were still between 0 and 255.
*/
public void colorMode(int mode, float maxX, float maxY, float maxZ) {
colorMode(mode, maxX, maxY, maxZ, colorModeA);
}
public void colorMode(int mode,
float maxX, float maxY, float maxZ, float maxA) {
colorMode = mode;
colorModeX = maxX; // still needs to be set for hsb
colorModeY = maxY;
colorModeZ = maxZ;
colorModeA = maxA;
// if color max values are all 1, then no need to scale
colorModeScale =
((maxA != 1) || (maxX != maxY) || (maxY != maxZ) || (maxZ != maxA));
// if color is rgb/0..255 this will make it easier for the
// red() green() etc functions
colorModeDefault = (colorMode == RGB) &&
(colorModeA == 255) && (colorModeX == 255) &&
(colorModeY == 255) && (colorModeZ == 255);
}
//////////////////////////////////////////////////////////////
// COLOR CALCULATIONS
// Given input values for coloring, these functions will fill the calcXxxx
// variables with values that have been properly filtered through the
// current colorMode settings.
// Renderers that need to subclass any drawing properties such as fill or
// stroke will usally want to override methods like fillFromCalc (or the
// same for stroke, ambient, etc.) That way the color calcuations are
// covered by this based PGraphics class, leaving only a single function
// to override/implement in the subclass.
/**
* Set the fill to either a grayscale value or an ARGB int.
* <P>
* The problem with this code is that it has to detect between these two
* situations automatically. This is done by checking to see if the high bits
* (the alpha for 0xAA000000) is set, and if not, whether the color value
* that follows is less than colorModeX (first param passed to colorMode).
* <P>
* This auto-detect would break in the following situation:
* <PRE>size(256, 256);
* for (int i = 0; i < 256; i++) {
* color c = color(0, 0, 0, i);
* stroke(c);
* line(i, 0, i, 256);
* }</PRE>
* ...on the first time through the loop, where (i == 0), since the color
* itself is zero (black) then it would appear indistinguishable from code
* that reads "fill(0)". The solution is to use the four parameter versions
* of stroke or fill to more directly specify the desired result.
*/
protected void colorCalc(int rgb) {
if (((rgb & 0xff000000) == 0) && (rgb <= colorModeX)) {
colorCalc((float) rgb);
} else {
colorCalcARGB(rgb, colorModeA);
}
}
protected void colorCalc(int rgb, float alpha) {
if (((rgb & 0xff000000) == 0) && (rgb <= colorModeX)) { // see above
colorCalc((float) rgb, alpha);
} else {
colorCalcARGB(rgb, alpha);
}
}
protected void colorCalc(float gray) {
colorCalc(gray, colorModeA);
}
protected void colorCalc(float gray, float alpha) {
if (gray > colorModeX) gray = colorModeX;
if (alpha > colorModeA) alpha = colorModeA;
if (gray < 0) gray = 0;
if (alpha < 0) alpha = 0;
calcR = colorModeScale ? (gray / colorModeX) : gray;
calcG = calcR;
calcB = calcR;
calcA = colorModeScale ? (alpha / colorModeA) : alpha;
calcRi = (int)(calcR*255); calcGi = (int)(calcG*255);
calcBi = (int)(calcB*255); calcAi = (int)(calcA*255);
calcColor = (calcAi << 24) | (calcRi << 16) | (calcGi << 8) | calcBi;
calcAlpha = (calcAi != 255);
}
protected void colorCalc(float x, float y, float z) {
colorCalc(x, y, z, colorModeA);
}
protected void colorCalc(float x, float y, float z, float a) {
if (x > colorModeX) x = colorModeX;
if (y > colorModeY) y = colorModeY;
if (z > colorModeZ) z = colorModeZ;
if (a > colorModeA) a = colorModeA;
if (x < 0) x = 0;
if (y < 0) y = 0;
if (z < 0) z = 0;
if (a < 0) a = 0;
switch (colorMode) {
case RGB:
if (colorModeScale) {
calcR = x / colorModeX;
calcG = y / colorModeY;
calcB = z / colorModeZ;
calcA = a / colorModeA;
} else {
calcR = x; calcG = y; calcB = z; calcA = a;
}
break;
case HSB:
x /= colorModeX; // h
y /= colorModeY; // s
z /= colorModeZ; // b
calcA = colorModeScale ? (a/colorModeA) : a;
if (y == 0) { // saturation == 0
calcR = calcG = calcB = z;
} else {
float which = (x - (int)x) * 6.0f;
float f = which - (int)which;
float p = z * (1.0f - y);
float q = z * (1.0f - y * f);
float t = z * (1.0f - (y * (1.0f - f)));
switch ((int)which) {
case 0: calcR = z; calcG = t; calcB = p; break;
case 1: calcR = q; calcG = z; calcB = p; break;
case 2: calcR = p; calcG = z; calcB = t; break;
case 3: calcR = p; calcG = q; calcB = z; break;
case 4: calcR = t; calcG = p; calcB = z; break;
case 5: calcR = z; calcG = p; calcB = q; break;
}
}
break;
}
calcRi = (int)(255*calcR); calcGi = (int)(255*calcG);
calcBi = (int)(255*calcB); calcAi = (int)(255*calcA);
calcColor = (calcAi << 24) | (calcRi << 16) | (calcGi << 8) | calcBi;
calcAlpha = (calcAi != 255);
}
/**
* Unpacks AARRGGBB color for direct use with colorCalc.
* <P>
* Handled here with its own function since this is indepenent
* of the color mode.
* <P>
* Strangely the old version of this code ignored the alpha
* value. not sure if that was a bug or what.
* <P>
* Note, no need for a bounds check since it's a 32 bit number.
*/
protected void colorCalcARGB(int argb, float alpha) {
if (alpha == colorModeA) {
calcAi = (argb >> 24) & 0xff;
calcColor = argb;
} else {
calcAi = (int) (((argb >> 24) & 0xff) * (alpha / colorModeA));
calcColor = (calcAi << 24) | (argb & 0xFFFFFF);
}
calcRi = (argb >> 16) & 0xff;
calcGi = (argb >> 8) & 0xff;
calcBi = argb & 0xff;
calcA = (float)calcAi / 255.0f;
calcR = (float)calcRi / 255.0f;
calcG = (float)calcGi / 255.0f;
calcB = (float)calcBi / 255.0f;
calcAlpha = (calcAi != 255);
}
//////////////////////////////////////////////////////////////
// STROKE CAP/JOIN/WEIGHT
@@ -4632,11 +4408,239 @@ public class PGraphics extends PImage implements PConstants {
//////////////////////////////////////////////////////////////
// COLOR MANIPULATION
// COLOR MODE
// these functions are really slow, but easy to use
// if folks are advanced enough to want something faster,
// they can write it themselves (not difficult)
public void colorMode(int mode) {
colorMode(mode, colorModeX, colorModeY, colorModeZ, colorModeA);
}
public void colorMode(int mode, float max) {
colorMode(mode, max, max, max, max);
}
/**
* Set the colorMode and the maximum values for (r, g, b)
* or (h, s, b).
* <P>
* Note that this doesn't set the maximum for the alpha value,
* which might be confusing if for instance you switched to
* <PRE>colorMode(HSB, 360, 100, 100);</PRE>
* because the alpha values were still between 0 and 255.
*/
public void colorMode(int mode, float maxX, float maxY, float maxZ) {
colorMode(mode, maxX, maxY, maxZ, colorModeA);
}
public void colorMode(int mode,
float maxX, float maxY, float maxZ, float maxA) {
colorMode = mode;
colorModeX = maxX; // still needs to be set for hsb
colorModeY = maxY;
colorModeZ = maxZ;
colorModeA = maxA;
// if color max values are all 1, then no need to scale
colorModeScale =
((maxA != 1) || (maxX != maxY) || (maxY != maxZ) || (maxZ != maxA));
// if color is rgb/0..255 this will make it easier for the
// red() green() etc functions
colorModeDefault = (colorMode == RGB) &&
(colorModeA == 255) && (colorModeX == 255) &&
(colorModeY == 255) && (colorModeZ == 255);
}
//////////////////////////////////////////////////////////////
// COLOR CALCULATIONS
// Given input values for coloring, these functions will fill the calcXxxx
// variables with values that have been properly filtered through the
// current colorMode settings.
// Renderers that need to subclass any drawing properties such as fill or
// stroke will usally want to override methods like fillFromCalc (or the
// same for stroke, ambient, etc.) That way the color calcuations are
// covered by this based PGraphics class, leaving only a single function
// to override/implement in the subclass.
/**
* Set the fill to either a grayscale value or an ARGB int.
* <P>
* The problem with this code is that it has to detect between these two
* situations automatically. This is done by checking to see if the high bits
* (the alpha for 0xAA000000) is set, and if not, whether the color value
* that follows is less than colorModeX (first param passed to colorMode).
* <P>
* This auto-detect would break in the following situation:
* <PRE>size(256, 256);
* for (int i = 0; i < 256; i++) {
* color c = color(0, 0, 0, i);
* stroke(c);
* line(i, 0, i, 256);
* }</PRE>
* ...on the first time through the loop, where (i == 0), since the color
* itself is zero (black) then it would appear indistinguishable from code
* that reads "fill(0)". The solution is to use the four parameter versions
* of stroke or fill to more directly specify the desired result.
*/
protected void colorCalc(int rgb) {
if (((rgb & 0xff000000) == 0) && (rgb <= colorModeX)) {
colorCalc((float) rgb);
} else {
colorCalcARGB(rgb, colorModeA);
}
}
protected void colorCalc(int rgb, float alpha) {
if (((rgb & 0xff000000) == 0) && (rgb <= colorModeX)) { // see above
colorCalc((float) rgb, alpha);
} else {
colorCalcARGB(rgb, alpha);
}
}
protected void colorCalc(float gray) {
colorCalc(gray, colorModeA);
}
protected void colorCalc(float gray, float alpha) {
if (gray > colorModeX) gray = colorModeX;
if (alpha > colorModeA) alpha = colorModeA;
if (gray < 0) gray = 0;
if (alpha < 0) alpha = 0;
calcR = colorModeScale ? (gray / colorModeX) : gray;
calcG = calcR;
calcB = calcR;
calcA = colorModeScale ? (alpha / colorModeA) : alpha;
calcRi = (int)(calcR*255); calcGi = (int)(calcG*255);
calcBi = (int)(calcB*255); calcAi = (int)(calcA*255);
calcColor = (calcAi << 24) | (calcRi << 16) | (calcGi << 8) | calcBi;
calcAlpha = (calcAi != 255);
}
protected void colorCalc(float x, float y, float z) {
colorCalc(x, y, z, colorModeA);
}
protected void colorCalc(float x, float y, float z, float a) {
if (x > colorModeX) x = colorModeX;
if (y > colorModeY) y = colorModeY;
if (z > colorModeZ) z = colorModeZ;
if (a > colorModeA) a = colorModeA;
if (x < 0) x = 0;
if (y < 0) y = 0;
if (z < 0) z = 0;
if (a < 0) a = 0;
switch (colorMode) {
case RGB:
if (colorModeScale) {
calcR = x / colorModeX;
calcG = y / colorModeY;
calcB = z / colorModeZ;
calcA = a / colorModeA;
} else {
calcR = x; calcG = y; calcB = z; calcA = a;
}
break;
case HSB:
x /= colorModeX; // h
y /= colorModeY; // s
z /= colorModeZ; // b
calcA = colorModeScale ? (a/colorModeA) : a;
if (y == 0) { // saturation == 0
calcR = calcG = calcB = z;
} else {
float which = (x - (int)x) * 6.0f;
float f = which - (int)which;
float p = z * (1.0f - y);
float q = z * (1.0f - y * f);
float t = z * (1.0f - (y * (1.0f - f)));
switch ((int)which) {
case 0: calcR = z; calcG = t; calcB = p; break;
case 1: calcR = q; calcG = z; calcB = p; break;
case 2: calcR = p; calcG = z; calcB = t; break;
case 3: calcR = p; calcG = q; calcB = z; break;
case 4: calcR = t; calcG = p; calcB = z; break;
case 5: calcR = z; calcG = p; calcB = q; break;
}
}
break;
}
calcRi = (int)(255*calcR); calcGi = (int)(255*calcG);
calcBi = (int)(255*calcB); calcAi = (int)(255*calcA);
calcColor = (calcAi << 24) | (calcRi << 16) | (calcGi << 8) | calcBi;
calcAlpha = (calcAi != 255);
}
/**
* Unpacks AARRGGBB color for direct use with colorCalc.
* <P>
* Handled here with its own function since this is indepenent
* of the color mode.
* <P>
* Strangely the old version of this code ignored the alpha
* value. not sure if that was a bug or what.
* <P>
* Note, no need for a bounds check since it's a 32 bit number.
*/
protected void colorCalcARGB(int argb, float alpha) {
if (alpha == colorModeA) {
calcAi = (argb >> 24) & 0xff;
calcColor = argb;
} else {
calcAi = (int) (((argb >> 24) & 0xff) * (alpha / colorModeA));
calcColor = (calcAi << 24) | (argb & 0xFFFFFF);
}
calcRi = (argb >> 16) & 0xff;
calcGi = (argb >> 8) & 0xff;
calcBi = argb & 0xff;
calcA = (float)calcAi / 255.0f;
calcR = (float)calcRi / 255.0f;
calcG = (float)calcGi / 255.0f;
calcB = (float)calcBi / 255.0f;
calcAlpha = (calcAi != 255);
}
//////////////////////////////////////////////////////////////
// COLOR DATATYPE STUFFING
// The 'color' primitive type in Processing syntax is in fact a 32-bit int.
// These functions handle stuffing color values into a 32-bit cage based
// on the current colorMode settings.
// These functions are really slow (because they take the current colorMode
// into account), but they're easy to use. Advanced users can write their
// own bit shifting operations to setup 'color' data types.
public final int color(int gray) { // ignore
@@ -4654,6 +4658,7 @@ public class PGraphics extends PImage implements PConstants {
return calcColor;
}
public final int color(float gray) { // ignore
colorCalc(gray);
return calcColor;
@@ -4675,6 +4680,7 @@ public class PGraphics extends PImage implements PConstants {
return calcColor;
}
/**
* @param rgb can be packed ARGB or a gray in this case
*/
@@ -4687,6 +4693,7 @@ public class PGraphics extends PImage implements PConstants {
return calcColor;
}
public final int color(float gray, float alpha) { // ignore
colorCalc(gray, alpha);
return calcColor;
@@ -4706,6 +4713,7 @@ public class PGraphics extends PImage implements PConstants {
return calcColor;
}
public final int color(float x, float y, float z) { // ignore
colorCalc(x, y, z);
return calcColor;
@@ -4726,11 +4734,20 @@ public class PGraphics extends PImage implements PConstants {
return calcColor;
}
public final int color(float x, float y, float z, float a) { // ignore
colorCalc(x, y, z, a);
return calcColor;
}
//////////////////////////////////////////////////////////////
// COLOR DATATYPE EXTRACTION
// Vee have veys of making the colors talk.
public final float alpha(int what) {
float c = (what >> 24) & 0xff;
@@ -4738,18 +4755,21 @@ public class PGraphics extends PImage implements PConstants {
return (c / 255.0f) * colorModeA;
}
public final float red(int what) {
float c = (what >> 16) & 0xff;
if (colorModeDefault) return c;
return (c / 255.0f) * colorModeX;
}
public final float green(int what) {
float c = (what >> 8) & 0xff;
if (colorModeDefault) return c;
return (c / 255.0f) * colorModeY;
}
public final float blue(int what) {
float c = (what) & 0xff;
if (colorModeDefault) return c;
@@ -4766,6 +4786,7 @@ public class PGraphics extends PImage implements PConstants {
return cacheHsbValue[0] * colorModeX;
}
public final float saturation(int what) {
if (what != cacheHsbKey) {
Color.RGBtoHSB((what >> 16) & 0xff, (what >> 8) & 0xff,
@@ -4775,6 +4796,7 @@ public class PGraphics extends PImage implements PConstants {
return cacheHsbValue[1] * colorModeY;
}
public final float brightness(int what) {
if (what != cacheHsbKey) {
Color.RGBtoHSB((what >> 16) & 0xff, (what >> 8) & 0xff,
@@ -4785,6 +4807,14 @@ public class PGraphics extends PImage implements PConstants {
}
//////////////////////////////////////////////////////////////
// COLOR DATATYPE INTERPOLATION
// Against our better judgement.
/**
* Interpolate between two colors, using the current color mode.
*/
@@ -4864,32 +4894,12 @@ public class PGraphics extends PImage implements PConstants {
return 0;
}
//////////////////////////////////////////////////////////////
/**
* Use with caution on PGraphics. This should not be used with
* the base PGraphics that's tied to a PApplet, but it can be used
* with user-created PGraphics objects that are drawn to the screen.
*/
public void mask(int alpha[]) { // ignore
super.mask(alpha);
}
/**
* Use with caution on PGraphics. This should not be used with
* the base PGraphics that's tied to a PApplet, but it can be used
* with user-created PGraphics objects that are drawn to the screen.
*/
public void mask(PImage alpha) { // ignore
super.mask(alpha);
}
//////////////////////////////////////////////////////////////
// BEGINRAW/ENDRAW
/**
* Record individual lines and triangles by echoing them to another renderer.