Far-fetched workaround for No. 3.but …
import geomerative.*;
import java.awt.Point;
import java.util.Queue;
import java.util.LinkedList;
PImage img;
RFont f;
RShape grp;
RShape grp2;
RPoint[] pts;
RPoint[][] pointPaths;
void setup() {
size(450, 250);
RG.init(this);
grp = RG.getText("Belli", "FreeSans.ttf", 200, CENTER);
}
void draw() {
background(255);
strokeWeight(2);
RG.setPolygonizer(RG.UNIFORMLENGTH);
pts = grp.getPoints();
pointPaths = grp.getPointsInPaths();
translate(200, 200);
noFill();
stroke(0);
for (int i = pointPaths.length-1; i >= 0; i--) {
if (pointPaths[i] != null) {
beginShape();
for (int j = pointPaths[i].length-1; j >= 0; j --) {
curveVertex(pointPaths[i][j].x + sin(frameCount*0.05 + pointPaths[i][j].y*0.1)*5, pointPaths[i][j].y);
}
endShape(CLOSE);
}
}
img = get();
fillShape(50, 60);
fillShape(200, 100);
fillShape(291, 79);
fillShape(336, 168);
fillShape(381, 61);
fillShape(381, 61);
fillShape(381, 174);
image(img, -200, -200, width, height);
}
void fillShape(int x, int y) {
img.loadPixels();
Queue<Point> queue = new LinkedList<Point>();
queue.add(new Point(x, y));
while (!queue.isEmpty()) {
Point p = queue.remove();
if (check(p.x, p.y)) {
queue.add(new Point(p.x, p.y-1));
queue.add(new Point(p.x, p.y+1));
queue.add(new Point(p.x-1, p.y));
queue.add(new Point(p.x+1, p.y));
}
}
img.updatePixels();
}
boolean check(int x, int y) {
if (x < 0 || y < 0 || y >= img.height || x >= img.width) return false;
int pp = img.pixels[x+(y*img.width)];
if (pp != color(255)) return false;
img.pixels[x + (y * img.width)] = color(0, 167, 230);
return true;
}