small improvements in gfx library

This commit is contained in:
Anya Helene Bagge 2018-03-07 13:26:00 +01:00
parent 32fa84ea0a
commit cb2daed48a
7 changed files with 176 additions and 4 deletions

View File

@ -25,4 +25,14 @@ public interface IPaintLayer {
*/
void layerToFront();
/**
* @return Width (in pixels) of graphics layer
*/
double getWidth();
/**
* @return Height (in pixels) of graphics layer
*/
double getHeight();
}

View File

@ -5,13 +5,45 @@ import javafx.scene.paint.Paint;
public interface IPainter extends IPaintLayer {
/**
* Restore graphics settings previously stored by {@link #save()}.
*
* @return {@code this}, for sending more draw commands
*/
IPainter restore();
/**
* Store graphics settings.
*
* @return {@code this}, for sending more draw commands
*/
IPainter save();
/**
* Set colour used to drawing and filling.
*
* @param ink A colour or paint
* @return {@code this}, for sending more draw commands
*/
IPainter setInk(Paint ink);
/**
* Start drawing a shape.
*
* @return An IShape for sending shape drawing commands
*/
IShape shape();
/**
* Start drawing with a turtle.
*
* @return An ITurtle for sending turtle drawing commands
*/
ITurtle turtle();
/**
* @return Current ink, as set by {@link #setInk(Paint)}
*/
Paint getInk();
}

View File

@ -2,7 +2,18 @@ package inf101.v18.gfx.gfxmode;
public interface ITurtle extends IPainter {
<T> T as(Class<T> class1);
/**
* This method is used to convert the turtle to an other type, determined by the
* class object given as an argument.
* <p>
* This can be used to access extra functionality not provided by this
* interface, such as direct access to the underlying graphics context.
*
* @param clazz
* @return This object or an appropriate closely related object of the given
* time; or <code>null</code> if no appropriate object can be found
*/
<T> T as(Class<T> clazz);
/**
* Move to the given position while drawing a curve
@ -236,7 +247,24 @@ public interface ITurtle extends IPainter {
*/
ITurtle turnTowards(double degrees, double percent);
double getWidth();
/**
* Jump (without drawing) to the given relative position.
* <p>
* The new position will be equal to getPos().move(relPos).
*
* @param relPos
* A position, interpreted relative to current position
* @return {@code this}, for sending more draw commands
*/
ITurtle jump(Point relPos);
/**
* Move to the given relative position while drawing a line
* <p>
* The new position will be equal to getPos().move(relPos).
*
* @return {@code this}, for sending more draw commands
*/
ITurtle draw(Point relPos);
double getHeight();
}

View File

@ -92,4 +92,25 @@ public class Point {
public String toString() {
return String.format("(%.2f,%.2f)", x, y);
}
/**
* Multiply this point by a scale factor.
*
* @param factor A scale factor
* @return A new Point, (getX()*factor, getY()*factor)
*/
public Point scale(double factor) {
return new Point(x*factor, y*factor);
}
/**
* Find difference between points.
* <p>
* The returned value will be such that <code>this.move(deltaTo(point)).equals(point)</code>.
* @param point Another point
* @return A new Point, (point.getX()-getX(), point.getY()-getY())
*/
public Point deltaTo(Point point) {
return new Point(point.x-x, point.y-y);
}
}

View File

@ -9,6 +9,8 @@ import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.paint.Color;
import javafx.scene.paint.Paint;
import javafx.scene.shape.StrokeLineCap;
import javafx.scene.shape.StrokeLineJoin;
public class TurtlePainter implements IPaintLayer, ITurtle {
@ -63,6 +65,8 @@ public class TurtlePainter implements IPaintLayer, ITurtle {
stateStack.add(new TurtleState());
state.dir = new Direction(1.0, 0.0);
state.pos = new Point(screen.getWidth() / 2, screen.getHeight() / 2);
context.setLineJoin(StrokeLineJoin.BEVEL);
context.setLineCap(StrokeLineCap.SQUARE);
}
@Override
@ -70,6 +74,8 @@ public class TurtlePainter implements IPaintLayer, ITurtle {
public <T> T as(Class<T> clazz) {
if (clazz == GraphicsContext.class)
return (T) context;
if (clazz == getClass())
return (T) this;
else
return null;
}
@ -113,6 +119,12 @@ public class TurtlePainter implements IPaintLayer, ITurtle {
return drawTo(to);
}
@Override
public ITurtle draw(Point relPos) {
Point to = state.pos.move(relPos);
return drawTo(to);
}
@Override
public ITurtle drawTo(double x, double y) {
Point to = new Point(x, y);
@ -122,6 +134,8 @@ public class TurtlePainter implements IPaintLayer, ITurtle {
@Override
public ITurtle drawTo(Point to) {
if (path) {
context.setStroke(state.ink);
context.setLineWidth(state.penSize);
context.lineTo(to.getX(), to.getY());
} else {
line(to);
@ -164,6 +178,18 @@ public class TurtlePainter implements IPaintLayer, ITurtle {
public ITurtle jump(double dist) {
state.inDir = state.dir;
state.pos = state.pos.move(state.dir, dist);
if (path)
context.moveTo(state.pos.getX(), state.pos.getY());
return this;
}
@Override
public ITurtle jump(Point relPos) {
// TODO: state.inDir = state.dir;
state.pos = state.pos.move(relPos);
if (path)
context.moveTo(state.pos.getX(), state.pos.getY());
return this;
}
@ -294,4 +320,44 @@ public class TurtlePainter implements IPaintLayer, ITurtle {
return painter;
}
public ITurtle beginPath() {
if (path)
throw new IllegalStateException("beginPath() after beginPath()");
path = true;
context.setStroke(state.ink);
context.beginPath();
context.moveTo(state.pos.getX(), state.pos.getY());
return this;
}
public ITurtle closePath() {
if (!path)
throw new IllegalStateException("closePath() without beginPath()");
context.closePath();
return this;
}
public ITurtle endPath() {
if (!path)
throw new IllegalStateException("endPath() without beginPath()");
path = false;
context.stroke();
return this;
}
public ITurtle fillPath() {
if (!path)
throw new IllegalStateException("fillPath() without beginPath()");
path = false;
context.save();
context.setFill(state.ink);
context.fill();
context.restore();
return this;
}
@Override
public Paint getInk() {
return state.ink;
}
}

View File

@ -14,6 +14,8 @@ import java.util.regex.Pattern;
import javafx.scene.paint.Color;
public class ControlSequences {
private static final boolean DEBUG = false;
public static class CsiPattern {
public static CsiPattern compile0(String pat, String desc, Consumer<Printer> handler) {
CsiPattern csiPattern = new CsiPattern(pat, 0, 0, desc, handler, null, null);
@ -73,10 +75,12 @@ public class ControlSequences {
String argStr = matcher.groupCount() > 0 ? matcher.group(1) : "";
String[] args = argStr.split(";");
if (handler0 != null) {
if(DEBUG)
System.out.println("Handling " + getDescription() + ".");
handler0.accept(printer);
} else if (handler1 != null) {
int arg = args.length > 0 && !args[0].equals("") ? Integer.valueOf(args[0]) : defaultArg;
if(DEBUG)
System.out.println("Handling " + getDescription() + ": " + arg);
handler1.accept(printer, arg);
} else if (handlerN != null) {
@ -90,7 +94,8 @@ public class ControlSequences {
while (argList.size() < numArgs) {
argList.add(defaultArg);
}
System.out.println("Handling " + getDescription() + ": " + argList);
if(DEBUG)
System.out.println("Handling " + getDescription() + ": " + argList);
handlerN.accept(printer, argList);
}
return true;

View File

@ -718,4 +718,14 @@ public class Printer implements IPaintLayer {
plot(x, y, (a, b) -> a & ~b);
}
@Override
public double getWidth() {
return textPage.getWidth();
}
@Override
public double getHeight() {
return textPage.getHeight();
}
}