Trouble with shapes

Hi. I’m having some trouble with drawing shapes.
I’m trying to draw a B and it doesn’t fill the whole shape.
Acording to the example on the beginContour() doc page, you don’t have to draw the starting point at the end, which I thought is needed. If you do, Processing wil set the coords to (0, 0). I understand, that the shape and the contour and the shape have to be drawn in oposite directions to each other.
I should also mention, that I’ve ran the sketch on Android.

``````void setup(){
fullScreen();
}

void draw(){
background(0);

pushMatrix();
translate(100, 100);
scale(2);
PVector[][] b = new PVector[][]{getPointsBOut(10), getPointsBTop(10), getPointsBBottom(10)};

fill(#FF0000);
noStroke();
stroke(255);

beginShape();
for(PVector pv:b[0]){
vertex(pv.x * 400 + 100, pv.y * 400 + 100);
}
//vertex(b[0][0].x, b[0][0].y);

beginContour();
for(int i = b[2].length - 1; i >= 0; i --){
PVector pv = b[2][i];
vertex(pv.x * 400 + 100, pv.y * 400 + 100);
}
//vertex(b[2][0].x, b[2][0].y);
endContour();

beginContour();
for(int i = b[1].length - 1; i >= 0; i --){
PVector pv = b[1][i];
vertex(pv.x * 400 + 100, pv.y * 400 + 100);
}
//vertex(b[1][0].x, b[1][0].y);
endContour();
endShape(CLOSE);

noFill();
stroke(#007FFF);

for(PVector[] pvl:b){
beginShape();
for(PVector pv:pvl){
vertex(pv.x * 400 + 100, pv.y * 400 + 100);
}
endShape(CLOSE);
}

for(PVector[] pvl:b){
for(PVector pv:pvl){
ellipse(pv.x * 400 + 100, pv.y * 400 + 100, 10, 10);
}
}
popMatrix();
}

PVector[] getPointsBOut(int curveDetail){
curveDetail = max(2, curveDetail);
PVector[] pts = new PVector[2 + curveDetail * 2];
pts[0] = new PVector(0, 0);
for(int i = 0; i < curveDetail; i ++){
pts[1 + i] = new PVector(0.4 + sin(i * PI / curveDetail) * 0.25, 0.25 - cos(i * PI / curveDetail) * 0.25);
}
for(int i = 0; i < curveDetail + 1; i ++){
pts[curveDetail + i] = new PVector(0.4 + sin(i * PI / curveDetail) * 0.25, 0.75 - cos(i * PI / curveDetail) * 0.25);
}
pts[pts.length - 1] = new PVector(0, 1);
return pts;
}

PVector[] getPointsBTop(int curveDetail){
curveDetail = max(2, curveDetail);
PVector[] pts = new PVector[3 + curveDetail];
pts[0] = new PVector(0.1, 0.1);
for(int i = 0; i < curveDetail + 1; i ++){
pts[1 + i] = new PVector(0.4 + sin(i * PI / curveDetail) * 0.15, 0.25 - cos(i * PI / curveDetail) * 0.15);
}
pts[pts.length - 1] = new PVector(0.1, 0.4);
return pts;
}

PVector[] getPointsBBottom(int curveDetail){
curveDetail = max(2, curveDetail);
PVector[] pts = new PVector[3 + curveDetail];
pts[0] = new PVector(0.1, 0.6);
for(int i = 0; i < curveDetail + 1; i ++){
pts[1 + i] = new PVector(0.4 + sin(i * PI / curveDetail) * 0.15, 0.75 - cos(i * PI / curveDetail) * 0.15);
}
pts[pts.length - 1] = new PVector(0.1, 0.9);
return pts;
}

``````

THAT IS YOUR PICTURE, i just copy out if your code, so we see it:

as your example is not so easy,
in a first step i needed to confirm that contour can CUT OUT
2 “windows” as needed for the inner of your “B”

looks good

``````int x,y,w,h;

void setup() {
size(200, 200);
}

void draw() {
background(200, 200, 0);
translate(width/2,height/2);
beginShape();
stroke(255);
fill(200, 0, 200);
// Exterior part of shape, clockwise winding
x = -40;
y = -40;
w = 80;
h = 80;
vertex(x, y);
vertex(x, y+h);
vertex(x+w, y+h);
vertex(x+w, y);

// Interior part of shape, counter-clockwise winding
x = -35;
y = -35;
w = 20;
h = 20;
beginContour();
vertex(x, y);
vertex(x+w, y);
vertex(x+w, y+h);
vertex(x, y+h);
endContour();

x = 15;
y = 15;
w = 20;
h = 20;
beginContour();
vertex(x, y);
vertex(x+w, y);
vertex(x+w, y+h);
vertex(x, y+h);
endContour();

endShape(CLOSE);
}

``````

your code / just with a reasonable setting for my monitor
works here

so, sorry must be a problem with your Android environment??

I mean, you can just use the text() function.

@kll Android Processing does have a lot of bugs and errors, so I’m not even surprised all that much.

@unique_username I don’t want a simple texture. I want to make an animation creating the outline and then filling the interior, like this. Also, this works on Android.

``````PGraphics[] gl;
int fps = 15;
float start = -0;
int frameImage = 0;
boolean realTimeGen = false;
float scale = 0.5;
int w = 1600;
int h = 1200;
float[] l = new float[]{1, 0.5, 0.5, 1, 0.5};
AriaEasingArgument[] aea = new AriaEasingArgument[]{
new AriaEasingArgument(AriaEasing.Type.SINE, 2, AriaEasing.Type.SINE, 2),
new AriaEasingArgument(AriaEasing.Type.EXPONENTIAL, 2, AriaEasing.Type.EXPONENTIAL, 2),
new AriaEasingArgument(AriaEasing.Type.POLYNOMIAL, 4, AriaEasing.Type.POLYNOMIAL, 4),
new AriaEasingArgument(AriaEasing.Type.SINE, 2, AriaEasing.Type.SINE, 2),
new AriaEasingArgument(AriaEasing.Type.POLYNOMIAL, 2, AriaEasing.Type.POLYNOMIAL, 2),
};
int[] sr = new int[]{-1, 0, 0, 1, 3};

void setup(){
//size(640, 480);
//surface.setResizable(true);
fullScreen();
frameRate(fps);
//orientation(LANDSCAPE);

w = width;
h = height;

float sum = 0;
for(float f:l) sum += f;
gl = new PGraphics[int(sum * fps - start * fps + 1)];
}

void draw(){
background(0);

textSize(50);
textAlign(LEFT, TOP);
imageMode(CENTER);
if(realTimeGen){
line(0, 100, frameImage * width / gl.length, 100);
text("Displaying " + frameImage + " / " + (gl.length - 1), 0, 120);
PGraphics pg = getImage();
float scale = min(float(width) / pg.width, float(height) / pg.height);
image(pg, width / 2, height / 2, pg.width * scale, pg.height * scale);
frameImage ++;
if(frameImage == gl.length) frameImage = gl.length - 1;
}
else{
line(0, 100, frameImage * width / gl.length, 100);
text("Loading " + frameImage + " / " + (gl.length - 1), 0, 120);
}
else{
line(0, 100, frameImage * width / gl.length, 100);
text("Displaying " + frameImage + " / " + (gl.length - 1), 0, 120);
float scale = min(float(width) / gl[frameImage].width, float(height) / gl[frameImage].height);
image(gl[frameImage], width / 2, height / 2, gl[frameImage].width * scale, gl[frameImage].height * scale);
frameImage ++;
if(frameImage == gl.length) frameImage = gl.length - 1;
}
}
save(dataPath((frameCount >= 10000 ? "" : "0") + (frameCount >= 1000 ? "" : "0") + (frameCount >= 100 ? "" : "0") + (frameCount >= 10 ? "" : "0") + frameCount + ".png"));
}

PGraphics getImage(){
float t = float(frameImage) / float(fps) + start;
//float t = (float)(millis()) / 4000;
return new LogoFurryNightShade().getGraphics(int(w * scale), int(h * scale), 1, t, l[0], l[1], l[2], l[3], l[4], sr, aea[0], aea[1], aea[2], aea[3], aea[4]);
}

gl[frameImage] = getImage();
frameImage ++;
if(frameImage == gl.length){
frameImage = 0;
}
}

//------------------------------------------------------------------------

//AriaEasing
//Version 1.0
//Doesn't require any other libraries

static class AriaEasing{
enum Type{
LINEAR, HOLD, IMMEDIATE, POLYNOMIAL, EXPONENTIAL, SINE, EULER
}

static double get(double time, double startTime, double endTime, double startValue, double endValue, AriaEasing.Type type, double tension){
if(startTime >= endTime) return endValue;
if(startValue == endValue) return endValue;
return startValue + (endValue - startValue) * AriaEasing.getNormalized((time - startTime) / (endTime - startTime), type, tension);
}
static double get(double time, double startTime, double endTime, double startValue, double endValue, AriaEasing.Type type1, double tension1, AriaEasing.Type type2, double tension2){
if(startTime >= endTime) return endValue;
if(startValue == endValue) return endValue;
return startValue + (endValue - startValue) * AriaEasing.getNormalized((time - startTime) / (endTime - startTime), type1, tension1, type2, tension2);
}
static double getNormalized(double time, AriaEasing.Type type1, double tension1, AriaEasing.Type type2, double tension2){
if(time < 0) return 0;
if(time > 1) return 1;
if(time == 0.5) return 0.5;
if(time < 0.5) return 0.5 * AriaEasing.getNormalized(time * 2, type1, tension1);
return 1 - 0.5 * AriaEasing.getNormalized(2 - time * 2, type2, tension2);
}
static double getNormalized(double time, AriaEasing.Type type, double tension){
if(time <= 0) return 0;
if(time >= 1) return 1;

if(Math.abs(tension) < 1) return 1 - AriaEasing.getNormalized(1 - time, type, 1 / tension);

double rawOutput = 0;

if(type == null) type = AriaEasing.Type.LINEAR;
if(type == AriaEasing.Type.LINEAR) rawOutput = AriaEasing.getLinear(time);
if(type == AriaEasing.Type.HOLD) rawOutput = AriaEasing.getHold(time);
if(type == AriaEasing.Type.IMMEDIATE) rawOutput = AriaEasing.getImmediate(time);
if(type == AriaEasing.Type.POLYNOMIAL) rawOutput = AriaEasing.getPolynomial(time, tension);
if(type == AriaEasing.Type.EXPONENTIAL) rawOutput = AriaEasing.getExponential(time, tension);
if(type == AriaEasing.Type.SINE) rawOutput = AriaEasing.getSine(time, tension);
if(type == AriaEasing.Type.EULER) rawOutput = AriaEasing.getEuler(time, tension);

return rawOutput;
}

static private double getLinear(double time){
return time;
}
static private double getHold(double time){
return time < 1 ? 0 : 1;
}
static private double getImmediate(double time){
return time > 0 ? 1 : 0;
}
static private double getPolynomial(double time, double tension){
if(tension < 0) return AriaEasing.getImmediate(time);
return Math.pow(time, tension);
}
static private double getExponential(double time, double tension){
return Math.pow(tension, time * 10 - 10);
}
static private double getSine(double time, double tension){
if(tension < 0) return AriaEasing.getImmediate(time);
if(tension < 1) return 1 - AriaEasing.getSine(1 - time, 1 / tension);
return Math.pow(1 - Math.cos(time * PI / 2), tension / 2);
}
static private double getEuler(double time, double tension){
if(tension < 0) return AriaEasing.getImmediate(time);
return (Math.pow(exp(1), time * tension) - 1) / (Math.pow(exp(1), tension) - 1);
}
}

//---------------------------------------------------

class AriaEasingArgument{
AriaEasing.Type type1, type2;
double tension1, tension2;

AriaEasingArgument(AriaEasing.Type type1, double tension1, AriaEasing.Type type2, double tension2){
this.type1 = type1;
this.type2 = type2;
this.tension1 = tension1;
this.tension2 = tension2;
}
}

//------------------------------------------------------

boolean procedureDebug = false;
boolean errorDebug = true;
boolean warningDebug = true;
boolean finalDebug = false;
String tabText = procedureDebug ? "   " : "";

PVector[] pointsf = new PVector[]{
new PVector(0, 0),
new PVector(4 / 9.0, 0),
new PVector(4 / 9.0, 1 / 9.0),
new PVector(1 / 9.0, 1 / 9.0),
new PVector(1 / 9.0, 3 / 9.0),
new PVector(3 / 9.0, 3 / 9.0),
new PVector(3 / 9.0, 4 / 9.0),
new PVector(1 / 9.0, 4 / 9.0),
new PVector(1 / 9.0, 6 / 9.0),
new PVector(0, 6 / 9.0)
};

PVector[] pointsu = new PVector[]{
new PVector(0, 2 / 9.0),
new PVector(1 / 9.0, 2 / 9.0),
new PVector(1 / 9.0, 5 / 9.0),
new PVector(2 / 9.0, 5 / 9.0),
new PVector(3 / 9.0, 4 / 9.0),
new PVector(3 / 9.0, 2 / 9.0),
new PVector(4 / 9.0, 2 / 9.0),
new PVector(4 / 9.0, 6 / 9.0),
new PVector(3 / 9.0, 6 / 9.0),
new PVector(3 / 9.0, 5 / 9.0),
new PVector(2 / 9.0, 6 / 9.0),
new PVector(1 / 9.0, 6 / 9.0),
new PVector(0, 5 / 9.0)
};

PVector[] pointsr = new PVector[]{
new PVector(0 / 9.0, 2 / 9.0),
new PVector(1 / 9.0, 2 / 9.0),
new PVector(1 / 9.0, 3 / 9.0),
new PVector(2 / 9.0, 2 / 9.0),
new PVector(4 / 9.0, 2 / 9.0),
new PVector(4 / 9.0, 3 / 9.0),
new PVector(2 / 9.0, 3 / 9.0),
new PVector(1 / 9.0, 4 / 9.0),
new PVector(1 / 9.0, 6 / 9.0),
new PVector(0 / 9.0, 6 / 9.0)
};

PVector[] pointsy = new PVector[]{
new PVector(0 / 9.0, 2 / 9.0),
new PVector(1 / 9.0, 2 / 9.0),
new PVector(1 / 9.0, 5 / 9.0),
new PVector(3 / 9.0, 5 / 9.0),
new PVector(3 / 9.0, 2 / 9.0),
new PVector(4 / 9.0, 2 / 9.0),
new PVector(4 / 9.0, 8 / 9.0),
new PVector(3 / 9.0, 9 / 9.0),
new PVector(1 / 9.0, 9 / 9.0),
new PVector(0 / 9.0, 8 / 9.0),
new PVector(0 / 9.0, 7 / 9.0),
new PVector(1 / 9.0, 7 / 9.0),
new PVector(1 / 9.0, 8 / 9.0),
new PVector(3 / 9.0, 8 / 9.0),
new PVector(3 / 9.0, 6 / 9.0),
new PVector(1 / 9.0, 6 / 9.0),
new PVector(0 / 9.0, 5 / 9.0)
};

PVector[] pointsn = new PVector[]{
new PVector(0 / 9.0, 0 / 9.0),
new PVector(1 / 9.0, 0 / 9.0),
new PVector(3 / 9.0, 4 / 9.0),
new PVector(3 / 9.0, 0 / 9.0),
new PVector(4 / 9.0, 0 / 9.0),
new PVector(4 / 9.0, 6 / 9.0),
new PVector(3 / 9.0, 6 / 9.0),
new PVector(1 / 9.0, 2 / 9.0),
new PVector(1 / 9.0, 6 / 9.0),
new PVector(0 / 9.0, 6 / 9.0)
};

PVector[] pointsi = new PVector[]{
new PVector(0 / 9.0, 3 / 9.0),
new PVector(1 / 9.0, 3 / 9.0),
new PVector(1 / 9.0, 6 / 9.0),
new PVector(0 / 9.0, 6 / 9.0)
};

PVector[] pointsic = new PVector[]{
new PVector(0 / 9.0, 1 / 9.0),
new PVector(1 / 9.0, 1 / 9.0),
new PVector(1 / 9.0, 2 / 9.0),
new PVector(0 / 9.0, 2 / 9.0)
};

PVector[] pointsg = new PVector[]{
new PVector(1 / 9.0, 2 / 9.0),
new PVector(3 / 9.0, 2 / 9.0),
new PVector(4 / 9.0, 3 / 9.0),
new PVector(4 / 9.0, 8 / 9.0),
new PVector(3 / 9.0, 9 / 9.0),
new PVector(1 / 9.0, 9 / 9.0),
new PVector(0 / 9.0, 8 / 9.0),
new PVector(0 / 9.0, 7 / 9.0),
new PVector(1 / 9.0, 7 / 9.0),
new PVector(1 / 9.0, 8 / 9.0),
new PVector(3 / 9.0, 8 / 9.0),
new PVector(3 / 9.0, 6 / 9.0),
new PVector(1 / 9.0, 6 / 9.0),
new PVector(0 / 9.0, 5 / 9.0),
new PVector(0 / 9.0, 3 / 9.0)
};

PVector[] pointsgc = new PVector[]{

new PVector(1 / 9.0, 3 / 9.0),
new PVector(1 / 9.0, 5 / 9.0),
new PVector(3 / 9.0, 5 / 9.0),
new PVector(3 / 9.0, 3 / 9.0)
};

PVector[] pointsh = new PVector[]{
new PVector(0 / 9.0, 0 / 9.0),
new PVector(1 / 9.0, 0 / 9.0),
new PVector(1 / 9.0, 3 / 9.0),
new PVector(3 / 9.0, 3 / 9.0),
new PVector(4 / 9.0, 4 / 9.0),
new PVector(4 / 9.0, 6 / 9.0),
new PVector(3 / 9.0, 6 / 9.0),
new PVector(3 / 9.0, 4 / 9.0),
new PVector(1 / 9.0, 4 / 9.0),
new PVector(1 / 9.0, 6 / 9.0),
new PVector(0 / 9.0, 6 / 9.0)
};

PVector[] pointst = new PVector[]{
new PVector(1 / 9.0, 2 / 9.0),
new PVector(2 / 9.0, 2 / 9.0),
new PVector(2 / 9.0, 3 / 9.0),
new PVector(3 / 9.0, 3 / 9.0),
new PVector(3 / 9.0, 4 / 9.0),
new PVector(2 / 9.0, 4 / 9.0),
new PVector(2 / 9.0, 5 / 9.0),
new PVector(4 / 9.0, 5 / 9.0),
new PVector(4 / 9.0, 6 / 9.0),
new PVector(1 / 9.0, 6 / 9.0),
new PVector(1 / 9.0, 4 / 9.0),
new PVector(0 / 9.0, 4 / 9.0),
new PVector(0 / 9.0, 3 / 9.0),
new PVector(1 / 9.0, 3 / 9.0)
};

PVector[] pointss = new PVector[]{
new PVector(0 / 9.0, 0 / 9.0),
new PVector(4 / 9.0, 0 / 9.0),
new PVector(4 / 9.0, 1 / 9.0),
new PVector(1 / 9.0, 1 / 9.0),
new PVector(1 / 9.0, 2 / 9.0),
new PVector(4 / 9.0, 3 / 9.0),
new PVector(4 / 9.0, 6 / 9.0),
new PVector(0 / 9.0, 6 / 9.0),
new PVector(0 / 9.0, 5 / 9.0),
new PVector(3 / 9.0, 5 / 9.0),
new PVector(3 / 9.0, 4 / 9.0),
new PVector(0 / 9.0, 3 / 9.0)
};

PVector[] pointsa = new PVector[]{

new PVector(3 / 9.0, 3 / 9.0),
new PVector(3 / 9.0, 2 / 9.0),
new PVector(1 / 9.0, 2 / 9.0),
new PVector(0 / 9.0, 3 / 9.0),
new PVector(0 / 9.0, 2 / 9.0),
new PVector(1 / 9.0, 1 / 9.0),
new PVector(3 / 9.0, 1 / 9.0),
new PVector(4 / 9.0, 2 / 9.0),
new PVector(4 / 9.0, 6 / 9.0),
new PVector(3 / 9.0, 6 / 9.0),
new PVector(3 / 9.0, 5 / 9.0),
new PVector(2 / 9.0, 6 / 9.0),
new PVector(1 / 9.0, 6 / 9.0),
new PVector(0 / 9.0, 5 / 9.0),
new PVector(0 / 9.0, 4 / 9.0),
new PVector(1 / 9.0, 3 / 9.0)
};

PVector[] pointsac = new PVector[]{
new PVector(3 / 9.0, 4 / 9.0),
new PVector(1 / 9.0, 4 / 9.0),
new PVector(1 / 9.0, 5 / 9.0),
new PVector(2 / 9.0, 5 / 9.0)
};

PVector[] pointsd = new PVector[]{

new PVector(1 / 9.0, 3 / 9.0),
new PVector(3 / 9.0, 3 / 9.0),
new PVector(3 / 9.0, 0 / 9.0),
new PVector(4 / 9.0, 0 / 9.0),
new PVector(4 / 9.0, 6 / 9.0),
new PVector(3 / 9.0, 6 / 9.0),
new PVector(3 / 9.0, 5 / 9.0),
new PVector(2 / 9.0, 6 / 9.0),
new PVector(1 / 9.0, 6 / 9.0),
new PVector(0 / 9.0, 5 / 9.0),
new PVector(0 / 9.0, 4 / 9.0)
};

PVector[] pointse = new PVector[]{
new PVector(1 / 9.0, 1 / 9.0),
new PVector(3 / 9.0, 1 / 9.0),
new PVector(4 / 9.0, 2 / 9.0),
new PVector(4 / 9.0, 3 / 9.0),
new PVector(3 / 9.0, 4 / 9.0),
new PVector(1 / 9.0, 4 / 9.0),
new PVector(1 / 9.0, 5 / 9.0),
new PVector(3 / 9.0, 5 / 9.0),
new PVector(4 / 9.0, 4 / 9.0),
new PVector(4 / 9.0, 5 / 9.0),
new PVector(3 / 9.0, 6 / 9.0),
new PVector(1 / 9.0, 6 / 9.0),
new PVector(0 / 9.0, 5 / 9.0),
new PVector(0 / 9.0, 2 / 9.0)
};

PVector[] pointsec = new PVector[]{
new PVector(3 / 9.0, 2 / 9.0),
new PVector(1 / 9.0, 2 / 9.0),
new PVector(1 / 9.0, 3 / 9.0),
new PVector(3 / 9.0, 3 / 9.0)
};

PVector[] pointsdc = this.pointsac;

float strokeSize = 0.02;
color strokeColor = #00F5FF;

}

this.strokeSize = strokeSize;
this.strokeColor = strokeColor;
}

PGraphics getGraphics(int x, int y, float logoSize, float animationTime, float animCS, float animM, float animCF, float animLS, float animLF, int[] startReq, AriaEasingArgument aeaCS, AriaEasingArgument aeaM, AriaEasingArgument aeaCF, AriaEasingArgument aeaLS, AriaEasingArgument aeaLF){
if(procedureDebug){
print("\nLogoFurryNightShade.getGraphics(x:" + x + ", y:" + y + ", logoSize:" + logoSize + ", animCS:" + animCS + ", animM:" + animM + ", animCF:" + animCF + ", animLS:" + animLS + ", animLF:" + animLF + ", startReq:");
if(startReq == null) println("null);");
else{
print("new int[]{");
for(int i = 0; i < startReq.length; i ++){
if(i != 0) print(", ");
print(startReq[i]);
}
print("});");
}
}

if(procedureDebug) println("Checking inpited values...");
if(x <= 0 || y <= 0){
if(errorDebug) println(tabText + "Error: Size must be greater than 0 in both directions (" + x + ", " + y + ").");
if(finalDebug) println(tabText + "Returned null.");
return null;
}
logoSize = constrain(logoSize, 0, 1);
if(logoSize <= 0){
if(errorDebug) println(tabText + "Error: Logo size must be greater than 0 (" + logoSize + ").");
if(finalDebug) println(tabText + "Returned empty PGraphics.");
return createGraphics(x, y);
}
if(animationTime <= 0){
if(errorDebug) println(tabText + "Error: Time must be greater than 0 (" + animationTime + ").");
if(finalDebug) println(tabText + "Returned rmpty PGraphics.");
return createGraphics(x, y);
}
animCF = animCF < 0 ? 0 : animCF;
animCS = animCS < 0 ? 0 : animCS;
animM = animM < 0 ? 0 : animM;
animLF = animLF < 0 ? 0 : animLF;
animLS = animLS < 0 ? 0 : animLS;

if(procedureDebug) println("Checking startReq...");
if(startReq == null){
if(warningDebug) println(tabText + "startReq is null. Setting startReq to default...");
startReq = new int[]{-1, 0, 1, 2, 3};
}
if(startReq.length != 5){
if(warningDebug) println(tabText + "startReq is not 5 values long(" + startReq.length + "). Setting startReq to default...");
startReq = new int[]{-1, 0, 1, 2, 3};
}

if(procedureDebug) println("Checking for startReq loops...");
for(int i = 0; i < startReq.length; i ++){
int req = startReq[i];
boolean loopFound = false;
IntList history = new IntList();
history.append(req);
while(req >= 0 && req < 5){
if(req == i){
loopFound = true;
history.append(req);
break;
}
history.append(req);
req = startReq[req];
}
if(loopFound){
if(errorDebug){
print(tabText + "Found a loop in startReq of length " + (history.size() - 1) + "(");
for(int j = 0; j < history.size(); j ++){
if(j != 0) print(" > ");
print(history.get(j));
}
print(").");
}
if(finalDebug) println(tabText + "Returned empty PGraphics.");
return createGraphics(x, y);
}
}

float scale = logoSize * min(x / 6.0, y / 1.0);
if(scale * x < 1 || scale * y < 1){
if(errorDebug) println(tabText + "Error: Scaled size must be greater than 0 in both directions (" + int(x * scale) + ", " + int(y * scale) + ").");
if(finalDebug) println(tabText + "Returned null.");
return null;
}

return this.generateGraphics(x, y, logoSize, animationTime, animCS, animM, animCF, animLS, animLF, startReq, aeaCS, aeaM, aeaCF, aeaLS, aeaLF);
}

private PGraphics generateGraphics(int x, int y, float logoSize, float animationTime, float animCS, float animM, float animCF, float animLS, float animLF, int[] startReq, AriaEasingArgument aeaCS, AriaEasingArgument aeaM, AriaEasingArgument aeaCF, AriaEasingArgument aeaLS, AriaEasingArgument aeaLF){
if(this.procedureDebug) println("Generating graphics...");
if(this.procedureDebug) println("Calculating time values...");
float[] animLength = new float[]{animCS, animM, animCF, animLS, animLF};
int[] deps = new int[5];
for(int i = 0; i < 5; i ++){
int l = -1;
int req = i;
while(req >= 0 && req < 5){
l ++;
req = startReq[req];
}
deps[i] = l;
}
float[] animStart = new float[5];
float[] animEnd = new float[5];
for(int dep = 0; dep < 5; dep ++){
for(int i = 0; i < 5; i ++){
if(deps[i] == dep){
if(dep == 0) animStart[i] = 0;
else animStart[i] = animEnd[startReq[i]];
animEnd[i] = animStart[i] + animLength[i];
}
}
}

if(frameCount == 30){
printArray(animStart);
printArray(animEnd);
}

float scale = logoSize * min(x * 9.0 / 72.0, y / 9.0);

float animCSP = constrain((animationTime - animStart[0]) / (animEnd[0] - animStart[0]), 0, 1);
float animMP = constrain((animationTime - animStart[1]) / (animEnd[1] - animStart[1]), 0, 1);
float animCFP = constrain((animationTime - animStart[2]) / (animEnd[2] - animStart[2]), 0, 1);
float animLSP = constrain((animationTime - animStart[3]) / (animEnd[3] - animStart[3]), 0, 1);
float animLFP = constrain((animationTime - animStart[4]) / (animEnd[4] - animStart[4]), 0, 1);

animCSP = (float)(aeaCS == null ? animCSP : (aeaCS.type2 == null ? AriaEasing.getNormalized(animCSP, aeaCS.type1, aeaCS.tension1) : AriaEasing.getNormalized(animCSP, aeaCS.type1, aeaCS.tension1, aeaCS.type2, aeaCS.tension2)));
animMP = (float)(aeaM == null ? animMP : (aeaM.type2 == null ? AriaEasing.getNormalized(animMP, aeaM.type1, aeaM.tension1) : AriaEasing.getNormalized(animMP, aeaM.type1, aeaM.tension1, aeaM.type2, aeaM.tension2)));
animCFP = (float)(aeaCF == null ? animCFP : (aeaCF.type2 == null ? AriaEasing.getNormalized(animCFP, aeaCF.type1, aeaCF.tension1) : AriaEasing.getNormalized(animCFP, aeaCF.type1, aeaCF.tension1, aeaCF.type2, aeaCF.tension2)));
animLSP = (float)(aeaCS == null ? animLSP : (aeaLS.type2 == null ? AriaEasing.getNormalized(animLSP, aeaLS.type1, aeaLS.tension1) : AriaEasing.getNormalized(animLSP, aeaLS.type1, aeaLS.tension1, aeaLS.type2, aeaLS.tension2)));
animLFP = (float)(aeaLF == null ? animLFP : (aeaLF.type2 == null ? AriaEasing.getNormalized(animLFP, aeaLF.type1, aeaLF.tension1) : AriaEasing.getNormalized(animLFP, aeaLF.type1, aeaLF.tension1, aeaLF.type2, aeaLF.tension2)));

float left = x / 2 - 72.0 / 18.0 * scale;
float right = x - left;
float top = y / 2 - scale;
float bottom = y - top;
float bw = (right - left) / 72;

if(this.procedureDebug) println("Generating fill templates...");
PImage bgTemplateCapital = createImage(int(right - left), int(bottom - top), RGB);
PImage bgTemplateLowercase = createImage(int(right - left), int(bottom - top), RGB);

for(int xc = 0; xc < bgTemplateCapital.width; xc ++){
for(int yc = 0; yc < bgTemplateCapital.height; yc ++){
float percentage = (xc + yc) / float(bgTemplateCapital.width + bgTemplateCapital.height);
bgTemplateCapital.pixels[xc + yc * bgTemplateCapital.width] = percentage <= animCFP ? lerpColor(this.bgGradLT, this.bgGradRB, percentage) : color(0, 0);
bgTemplateLowercase.pixels[xc + yc * bgTemplateLowercase.width] = percentage <= animLFP ? lerpColor(this.bgGradLT2, this.bgGradRB2, percentage) : color(0, 0);
}
}

bgTemplateCapital.updatePixels();
bgTemplateLowercase.updatePixels();

float lf = left + (28.5 - 28.5 * animMP) * bw;
float lu = lf + 5 * bw;
float lr1 = lf + 10 * bw;
float lr2 = lf + 15 * bw;
float ly = lf + 20 * bw;
float ln = left + (33.5 - 8.5 * animMP) * bw;
float li = ln + 5 * bw;
float lg = ln + 7 * bw;
float lh1 = ln + 12 * bw;
float lt = ln + 17 * bw;
float ls = left + (38.5 + 8.5 * animMP) * bw;
float lh2 = ls + 5 * bw;
float la = ls + 10 * bw;
float ld = ls + 15 * bw;
float le = ls + 20 * bw;
float lfes = lf + 5 * bw + 19 * bw * animMP;
float lnes = ln + 5 * bw + 16 * bw * animMP;
float lses = ls + 5 * bw + 19 * bw * animMP;

if(this.procedureDebug) println("Generating text template...");
PGraphics strokeText = createGraphics(x, y);
strokeText.beginDraw();
strokeText.stroke(this.strokeColor);
strokeText.noFill();
strokeText.strokeWeight(this.strokeSize * scale);

this.drawShapeStroke(this.pointsf, strokeText, lf, top, bw, animCSP, "F");
this.drawShapeStroke(this.pointsu, strokeText, lu, top, bw, animLSP, "u");
this.drawShapeStroke(this.pointsr, strokeText, lr1, top, bw, animLSP, "r");
this.drawShapeStroke(this.pointsr, strokeText, lr2, top, bw, animLSP, "r");
this.drawShapeStroke(this.pointsy, strokeText, ly, top, bw, animLSP, "y");
this.removeRight(strokeText, lfes);
this.drawShapeStroke(this.pointsn, strokeText, ln, top, bw, animCSP, "N");
this.drawShapeStroke(this.pointsi, strokeText, li, top, bw, animLSP, "i");
this.drawShapeStroke(this.pointsic, strokeText, li, top, bw, animLSP, "i");
this.drawShapeStroke(this.pointsg, strokeText, lg, top, bw, animLSP, "g");
this.drawShapeStroke(this.pointsgc, strokeText, lg, top, bw, animLSP, "g");
this.drawShapeStroke(this.pointsh, strokeText, lh1, top, bw, animLSP, "h");
this.drawShapeStroke(this.pointst, strokeText, lt, top, bw, animLSP, "t");
this.removeRight(strokeText, lnes);
this.drawShapeStroke(this.pointss, strokeText, ls, top, bw, animCSP, "S");
this.drawShapeStroke(this.pointsh, strokeText, lh2, top, bw, animLSP, "h");
this.drawShapeStroke(this.pointsa, strokeText, la, top, bw, animLSP, "a");
this.drawShapeStroke(this.pointsac, strokeText, la, top, bw, animLSP, "a");
this.drawShapeStroke(this.pointsd, strokeText, ld, top, bw, animLSP, "d");
this.drawShapeStroke(this.pointsdc, strokeText, ld, top, bw, animLSP, "d");
this.drawShapeStroke(this.pointse, strokeText, le, top, bw, animLSP, "e");
this.drawShapeStroke(this.pointsec, strokeText, le, top, bw, animLSP, "e");
this.removeRight(strokeText, lses);

strokeText.endDraw();

PGraphics fillTemplate = createGraphics(x, y);
fillTemplate.beginDraw();
fillTemplate.fill(255);
fillTemplate.noStroke();

this.drawShapeFill(this.pointsf, null, fillTemplate, lf, top, bw, "F");
this.drawShapeFill(this.pointsu, null, fillTemplate, lu, top, bw, "u");
this.drawShapeFill(this.pointsr, null, fillTemplate, lr1, top, bw, "r");
this.drawShapeFill(this.pointsr, null, fillTemplate, lr2, top, bw, "r");
this.drawShapeFill(this.pointsy, null, fillTemplate, ly, top, bw, "y");
this.removeRight(fillTemplate, lfes);
this.drawShapeFill(this.pointsn, null, fillTemplate, ln, top, bw, "N");
this.drawShapeFill(this.pointsi, null, fillTemplate, li, top, bw, "i");
this.drawShapeFill(this.pointsic, null, fillTemplate, li, top, bw, "i");
this.drawShapeFill(this.pointsg, this.pointsgc, fillTemplate, lg, top, bw, "g");
this.drawShapeFill(this.pointsh, null, fillTemplate, lh1, top, bw, "h");
this.drawShapeFill(this.pointst, null, fillTemplate, lt, top, bw, "t");
this.removeRight(fillTemplate, lnes);
this.drawShapeFill(this.pointss, null, fillTemplate, ls, top, bw, "S");
this.drawShapeFill(this.pointsh, null, fillTemplate, lh2, top, bw, "h");
this.drawShapeFill(this.pointsa, this.pointsac, fillTemplate, la, top, bw, "a");
this.drawShapeFill(this.pointsd, this.pointsdc, fillTemplate, ld, top, bw, "d");
this.drawShapeFill(this.pointse, this.pointsec, fillTemplate, le, top, bw, "e");
this.removeRight(fillTemplate, lses);

fillTemplate.endDraw();

if(this.procedureDebug) println("Generating final PGraphics...");
PGraphics pg = createGraphics(x, y);
pg.beginDraw();

for(int xc = 0; xc < bgTemplateCapital.width; xc ++){
for(int yc = 0; yc < bgTemplateCapital.height; yc ++){
boolean isAtCapital = false;
if(left + xc >= lf && left + xc <= lf + 4 * bw) isAtCapital = true;
else if(left + xc >= ln && left + xc <= ln + 4 * bw) isAtCapital = true;
else if(left + xc >= ls && left + xc <= ls + 4 * bw) isAtCapital = true;

if(isAtCapital)
if(fillTemplate.pixels[int(left) + xc + int(top + yc) * fillTemplate.width] == color(255)) pg.pixels[int(left) + xc + int(top + yc) * pg.width] = bgTemplateCapital.pixels[xc + yc * bgTemplateCapital.width];
if(!isAtCapital)
if(fillTemplate.pixels[int(left) + xc + int(top + yc) * fillTemplate.width] == color(255)) pg.pixels[int(left) + xc + int(top + yc) * pg.width] = bgTemplateLowercase.pixels[xc + yc * bgTemplateLowercase.width];
}
}
pg.updatePixels();
fillTemplate.updatePixels();
bgTemplateCapital.updatePixels();
bgTemplateLowercase.updatePixels();

pg.imageMode(CORNERS);
pg.image(strokeText, 0, 0);

pg.endDraw();

if(this.finalDebug) println("Returned PGraphics.");
return pg;
}

private void drawShapeStroke(PVector[] pts, PGraphics pg, float x, float y, float bw, float perc, String s){
if(this.procedureDebug) println("Generating text stroke template for '" + s + "'...");

float length = 0;
float usedDistance = 0;
for(int i = 0; i < pts.length; i ++){
PVector a = pts[i];
PVector b = pts[(i + 1) % pts.length];
length += dist(a.x, a.y, b.x, b.y);
}
length *= perc;

for(int i = 0; i < pts.length; i ++){
PVector a = pts[i];
PVector b = pts[(i + 1) % pts.length];
float d = dist(a.x, a.y, b.x, b.y);
float totald = d;
if(d >= length - usedDistance && perc != 1){
d = length - usedDistance;
float dp = d / totald;
//println(dp + " = " + d + " / " + totald);
float x1 = x + bw * 9 * a.x;
float y1 = y + bw * 9 * a.y;
float x2 = x + bw * 9 * ((b.x - a.x) * dp + a.x);
float y2 = y + bw * 9 * ((b.y - a.y) * dp + a.y);
pg.line(x1, y1, x2, y2);
break;
}
else{
pg.line(x + bw * a.x * 9, y + bw * a.y * 9, x + bw * b.x * 9, y + bw * b.y * 9);
usedDistance += d;
}
}
}

private void removeRight(PGraphics pg, float x){
for(int xc = int(x); xc < pg.width; xc ++){
for(int yc = 0; yc < pg.height; yc ++){
pg.pixels[xc + yc * pg.width] = color(0, 0);
}
}
pg.updatePixels();
}

private void drawShapeFill(PVector[] pts, PVector[] c, PGraphics pg, float x, float y, float bw, String s){
if(this.procedureDebug) println("Generating text fill template for '" + s + "'...");

pg.beginShape();
for(int i = 0; i < pts.length + 1; i ++){
PVector a = pts[(i + 1) % pts.length];

pg.vertex(x + bw * a.x * 9, y + bw * a.y * 9);
}
if(c != null){
pg.beginContour();
for(int i = 0; i < c.length + 1; i ++){
PVector a = c[(i) % c.length];

pg.vertex(x + bw * a.x * 9, y + bw * a.y * 9);
}
pg.endContour();
}
pg.endShape(CLOSE);

}
}
``````
1 Like