Processing bug?

NO ACTION REQUIRED
It has already been reported as an issue

I am not sure whether this is a bug in Processing or not. It runs fine in Eclipse using the Processing core fror v3.4 but has a runtime error in the Processing IDE

Before I report it as an issue I would like forum members to confirm whether they experience the same problem on their system. Simply copy and paste the code into your Processing IDE and let me know how you get on.
I am using

  • macOS 10.13.6
  • Processing 3.4
    The line indicated and the error message have been commented the problem appears to be with the statement v.color(...) on line 19
PGraphics v;

void setup() {
  size(300, 300, P2D);
  v = createGraphics(260, 200, JAVA2D);
  updateBuffer();
}

void draw() {
  background(200, 200, 255);
  image(v, 20, 20);
}

void updateBuffer() {
  v.beginDraw();
  v.background(255);
  v.colorMode(HSB, 360, 100, 100);
  int c;
  c = v.color(300, 100, 100); // 'unexpected token:.' runtime error?
  v.fill(c);
  v.noStroke();
  v.ellipse(130, 100, 130, 100);
  v.colorMode(RGB, 255, 255, 255);
  v.endDraw();
}
1 Like

NO ACTION REQUIRED
It has already been reported as an issue

Note that this problem can be seen in a smaller example:

void setup() {
  Test t = new Test();
  int c = t.color(300, 100, 100);
  println(c);
}

class Test {
  int color(int r, int g, int b) {
    return 42;
  }
}

The problem seems to be with the color keyword. Renaming the function to color2 fixes the issue.

However, I’m not really sure this is a bug. In Processing, color is a reserved keyword. It’s just like you can’t name a function float:

void setup() {
  Test t = new Test();
  int c = t.float(300, 100, 100);
  println(c);
}

class Test {
  int float(int r, int g, int b) {
    return 42;
  }
}
1 Like

I believe it is a bug because it is an unintended side effect of the pre-processor which means you can’t use the color method with an off-screen buffer.

In the example I posted I change the color mode for the buffer and then try to calculate a color value using that mode. I can’t simply use color(…) because it would use the main display color mode.

In Processing the data type color is an alias for int so v.color( gets translated to v.int(, hence the error message.

2 Likes

To add to what @quark said

  • Calling the .color() method on a PGraphics object should be valid, because PGraphics defines all the drawing methods like .line(), .stroke(), .rect(), and also .color().
  • Defining methods called color(), line(), or any other Processing keyword inside your class does work. Defining a method called draw() inside a class is actually common practice (for particles, for instance), although it may confuse less experienced users by making them think they are somehow Processing related.
  • Defining a method called float() is not ok, but not because it’s a Processing keyword, but because it’s a Java Keyword.
3 Likes

I agree it’s a bit buggy that you can’t call functions that are defined by the API. But out of curiosity: why do you need to do this?

Names like line and stroke are not reserved keywords though. You can have a function named draw() because it’s not a keyword, just like you can have a function or variable named main in Java.

You can. The issue is just with color, because as @quark mentioned, this is replaced by int by the preprocessor. What that means is that when you click run, but before the program is compiled, the word color is replaced by int. And in this case it makes a mistake by replacing somewhere where it should not be replace.

If you work in Idea or Eclipse, there’s no preprocessor, so color can be used without this unexpected behavior.

Here a very confusing program to demonstrate that you can use unexpected variable names:

void setup() {
  Test t = new Test("long", "dashed");
  t.rect();
  println(t.line, "and", t.stroke);
  println(t.HALF_PI, t.ArrayList);
}

class Test {
  String line;
  String stroke;
  int HALF_PI = 3;
  int ArrayList = 4;
  void rect() {
    println("rect");
  }
  Test(String l, String s) {
    line = l;
    stroke = s;
  }
}

The names you can’t use are in the link I included above with the Java keywords.

If a user wants to create and/or use an off-screen buffer this is a real pain. At least I found it a pain :grinning:

1 Like

B/c color() isn’t thread-safe, a Thread would be forced to have its own PGraphics just so it can invoke color() w/o messing w/ the “Animation” Thread. :thread:

Notice though that functions like background(), stroke(), fill(), etc. invoke color() internally too! :cold_sweat:

/**
 * Threaded color() Access Test (v1.0)
 * GoToLoop (2018/Dec/13)
 * https://Discourse.Processing.org/t/processing-bug/6561/10
 */

// Blinks magenta from time to time:
static final String THREADED_METHOD = "colorThreadBug";

// Always blue background():
//static final String THREADED_METHOD = "colorThreadWorkaround";

void setup() {
  size(300, 200);
  thread(THREADED_METHOD);
}

void draw() {
  background(#0000FF);
  getSurface().setTitle("Frames: " + frameCount);
}

void colorThreadBug() {
  for (;; delay(1))  color(#FF0000);
}

void colorThreadWorkaround() {
  final PGraphics offscreenColor = createGraphics(0, 0);
  final java.lang.reflect.Method colour;

  try {
    colour = PGraphics.class.getMethod("color", int.class);
  }
  catch (final NoSuchMethodException e) {
    throw new RuntimeException(e);
  }

  try {
    for (;; delay(1))  colour.invoke(offscreenColor, #FF0000);
  }
  catch (final ReflectiveOperationException e) {
    throw new RuntimeException(e);
  }
}

Yes, I understand that. I’m saying that the color() function is defined by the API, so it’s weird that you can’t call them. I’m agreeing with you guys that this seems buggy.

This program is not confusing. Reusing method or variable names is completely fine, as they are not reserved keywords. I can define my own ArrayList class, or overload the main() method if I want. This is all completely fine. Maybe a bad idea for other reasons, but syntactically valid.

My only point is that the color keyword is a type in Processing. So it makes sense that it would be treated as a reserved keyword. I understand that under the hood it’s an int, but I’m saying that there’s a certain logic for color to be disallowed. I agree that you should still be able to use the color() function.

Basically the original bug is that Processing used color as both a type and a function name, which makes it impossible to be consistent.

2 Likes

IMO the syntax changes in the Processing preprocessor cause more problems than they solve!

@GoToLoop one use for this is potentially different colour modes as per the OP, but still better just using the base PApplet functionality assuming you stay single threaded. And it’s pointless multithreading rendering, as various bits of the Processing infrastructure isn’t thread safe, and the underlying renderers don’t support parallelization anyway! (GL is single threaded, AWT has a global lock)

  • All color calculation is done by the base class PGraphics.
  • Which means it’s renderer independent!
  • Simply invoking color() doesn’t mutate the PGraphics’s canvas in any way.
  • Otherwise it woulda crashed the whole sketch if it was done by another Thread!
  • The reason multi-threaded color() messes up everything is b/c temporary calculations are stored in instance fields of the the PGraphics.
  • That’s just very bad programming!
  • Correct way would be to forward temporary calculation as method parameters.

I agree, where. are my lamdas!

In the issue page I added a terrible way to get around the color problem.

1 Like

Yes, I’m well aware of what the cause is, and have refactored half of it in my own code. Yes, its design is problematic, but it works fine in a single-threaded context. And given how much else isn’t multi-thread safe it’s not much of a hardship to treat it like that. Much rather have that than some naive and slow “fix” to make it concurrent. If it bothers you that much, put in a PR to fix it properly!

It’s not actually pertinent to this issue though.

Out of interest, what’s your use case for calling it via a PGraphics in the first place?

Not for us but I felt I needed to excuse myself in case someone finds that code and wonders.

1 Like

This is a difficult one because Processing was originally designed for non-programmers who would have struggled with OO concepts and syntax. The pre-processor hides the fact that Java is an object orientated language and gave beginners a simple syntax to write their sketches.

I do wonder how many programming newbies would continue with Processing without the pre-processor simplifying the language syntax.

Most of Processing and a huge chunk of Java is not thread safe. This is not a problem for the majority of Processing sketchers and for experienced programmers Java provides mechanisms for safe threading.

My personal interest in this area is G4P where all the controls have their own internal graphics buffer using lazy updates to improve performance. I should point out that G4P operates entirely within the main event thread with the exception of multiple windows where each window is effectively another Processing sketch.

I am currently working on the next version of G4P and I was creating an example sketch in Processing to demonstrate a new control when I hit the problem.

To be honest, I had come across this problem before but had forgotten about it. C’est la vie :grinning:

2 Likes

The pre-processor doesn’t simplify the language syntax! It complicates it, eg. by adding color as another type.

The structural changes around writing a class body rather than a whole class, adding default imports, etc. can be done without changing the underlying syntax. It’s something things like JShell do. And exactly what PraxisLIVE does for working with Processing code, which means it’s no more difficult than PDE to write code but all Java 8 syntax just works!

@neilcsmith

Also for a gui library where you might wan’t to draw on a different PGraphics instead of the main one.

add_solver(
    $("slider", "thumb"),
     (e, r) -> {
            g.fill(colors[0]);
            g.noStroke();
            g.rect(r.x, r.y, r.w, r.h);
    }
    , DRAW
);  

And about the preprocessor.
I would much more prefer that it get’s replaced by a dumber thing.
We would have to get rid of color as a primitive but I can live with that.
How difficult can it be, just explain we have millions of colors, each color has a number…

The when compiling paste a bunch required to make it working on top and at the bottom.
Maybe don’t allow for sketches without any function anymore. It was a nice and clean thing, but in practise hardly used.