Merge branch 'master' into kkn015

This commit is contained in:
Anya Helene Bagge 2018-03-18 20:13:42 +01:00
commit 3971345fdb
3 changed files with 139 additions and 17 deletions

View File

@ -61,6 +61,7 @@ public class Printer implements IPaintLayer {
1.0000, 1.0000, true);
private static final Paint DEFAULT_BACKGROUND = Color.TRANSPARENT;
private static final TextMode DEFAULT_MODE = TextMode.MODE_40X22;
private static final boolean DEBUG_REDRAW = false;
public static String center(String s, int width) {
for (; s.length() < width; s = " " + s + " ")
@ -103,6 +104,12 @@ public class Printer implements IPaintLayer {
private final double width;
private final double height;
private int dirtyX0 = Integer.MAX_VALUE;
private int dirtyX1 = Integer.MIN_VALUE;
private int dirtyY0 = Integer.MAX_VALUE;
private int dirtyY1 = Integer.MIN_VALUE;
private boolean useBuffer = true;
public Printer(double width, double height) {
this.screen = null;
this.textPage = null;
@ -239,7 +246,10 @@ public class Printer implements IPaintLayer {
y = constrainY(y);
if (y > 0 && y <= TextMode.PAGE_HEIGHT_MAX) {
Arrays.fill(lineBuffer.get(y - 1), null);
redrawTextPage();
dirty(1, y);
dirty(getLineWidth(), y);
if (!useBuffer)
redrawDirty();
}
}
@ -257,7 +267,10 @@ public class Printer implements IPaintLayer {
for (int i = y1; i <= y2; i++) {
Arrays.fill(lineBuffer.get(i - 1), x1 - 1, x2, null);
}
redrawTextPage();
dirty(x1, y1);
dirty(x2, y2);
if (!useBuffer)
redrawDirty();
}
private int constrainX(int x) {
@ -296,11 +309,16 @@ public class Printer implements IPaintLayer {
textMode = textMode.nextMode();
if (adjustDisplayAspect && screen != null)
screen.setAspect(textMode.getAspect());
redrawTextPage();
dirty(1, 1);
dirty(getLineWidth(), getPageHeight());
if (!useBuffer)
redrawDirty();
}
private void drawChar(int x, int y, Char c) {
if (c != null && textPage != null) {
if (useBuffer) {
dirty(x, y);
} else if (c != null && textPage != null) {
GraphicsContext context = textPage.getGraphicsContext2D();
context.setFill(c.fill);
@ -510,6 +528,11 @@ public class Printer implements IPaintLayer {
}
public void redrawTextPage() {
redrawTextPage(1, 1, getLineWidth(), getPageHeight());
clean();
}
private void redrawTextPage(int x0, int y0, int x1, int y1) {
/*
* System.out.printf("redrawTextPage benchmark");
* System.out.printf(" %5s %5s %7s %4s %5s %5s %5s%n", "ms", "chars",
@ -520,21 +543,27 @@ public class Printer implements IPaintLayer {
return;
GraphicsContext context = textPage.getGraphicsContext2D();
double px0 = (x0 - 1) * getCharWidth(), py0 = (y0 - 1) * getCharHeight();
double px1 = x1 * getCharWidth(), py1 = y1 * getCharHeight();
if (DEBUG_REDRAW)
System.out.printf("redrawTextPage(): Area to clear: (%2f,%2f)(%2f,%2f)%n", px0, py0, px1, py1);
if (background != null && background != Color.TRANSPARENT) {
context.setFill(background);
context.fillRect(0.0, 0.0, textPage.getWidth(), textPage.getHeight());
} else
context.clearRect(0.0, 0.0, textPage.getWidth(), textPage.getHeight());
for (int tmpY = 1; tmpY <= getPageHeight(); tmpY++) {
context.fillRect(px0, py0, px1 - px0, py1 - py0);
} else {
context.clearRect(px0, py0, px1 - px0, py1 - py0);
}
for (int tmpY = y0; tmpY <= y1; tmpY++) {
Char[] line = lineBuffer.get(tmpY - 1);
for (int tmpX = 1; tmpX <= getLineWidth(); tmpX++) {
for (int tmpX = x0; tmpX <= x1; tmpX++) {
Char c = line[tmpX - 1];
if (c != null) {
context.save();
context.setFill(c.fill);
context.setStroke(c.stroke);
font.drawTextAt(context, (tmpX - 1) * getCharWidth(), tmpY * getCharHeight(), c.s,
textMode.getCharWidth() / textMode.getCharBoxSize(), c.mode/* m */, c.bg);
Paint bg = c.bg == background ? null : c.bg;
font.drawTextNoClearAt(context, (tmpX - 1) * getCharWidth(), tmpY * getCharHeight(), c.s,
textMode.getCharWidth() / textMode.getCharBoxSize(), c.mode/* m */, bg);
context.restore();
// n++;
@ -590,14 +619,20 @@ public class Printer implements IPaintLayer {
Char[] remove = lineBuffer.remove(lineBuffer.size() - 1);
Arrays.fill(remove, null);
lineBuffer.add(0, remove);
redrawTextPage();
dirty(1, 1);
dirty(getLineWidth(), getPageHeight());
if (!useBuffer)
redrawDirty();
}
public void scrollUp() {
Char[] remove = lineBuffer.remove(0);
Arrays.fill(remove, null);
lineBuffer.add(remove);
redrawTextPage();
dirty(1, 1);
dirty(getLineWidth(), getPageHeight());
if (!useBuffer)
redrawDirty();
}
public boolean setAutoScroll(boolean autoScroll) {
@ -703,7 +738,10 @@ public class Printer implements IPaintLayer {
textMode = mode;
if (adjustDisplayAspect && screen != null)
screen.setAspect(textMode.getAspect());
redrawTextPage();
dirty(1, 1);
dirty(getLineWidth(), getPageHeight());
if (!useBuffer)
redrawDirty();
}
public void setTopMargin() {
@ -744,4 +782,63 @@ public class Printer implements IPaintLayer {
return height;
}
private boolean isDirty() {
return dirtyX0 <= dirtyX1 || dirtyY0 <= dirtyY1;
}
/**
* Expand the dirty region (area that should be redrawn) to include the given
* position
*
* @param x
* @param y
*/
private void dirty(int x, int y) {
dirtyX0 = Math.max(Math.min(x, dirtyX0), 1);
dirtyX1 = Math.min(Math.max(x, dirtyX1), getLineWidth());
dirtyY0 = Math.max(Math.min(y, dirtyY0), 1);
dirtyY1 = Math.min(Math.max(y, dirtyY1), getPageHeight());
}
/**
* Redraw the part of the page that has changed since last redraw.
*/
public void redrawDirty() {
if (isDirty()) {
if (DEBUG_REDRAW)
System.out.printf("redrawDirty(): Dirty region is (%d,%d)(%d,%d)%n", dirtyX0, dirtyY0, dirtyX1,
dirtyY1);
redrawTextPage(dirtyX0, dirtyY0, dirtyX1, dirtyY1);
clean();
}
}
/**
* Mark the entire page as clean
*/
private void clean() {
dirtyX0 = Integer.MAX_VALUE;
dirtyX1 = Integer.MIN_VALUE;
dirtyY0 = Integer.MAX_VALUE;
dirtyY1 = Integer.MIN_VALUE;
}
/**
* With buffered printing, nothing is actually drawn until
* {@link #redrawDirty()} or {@link #redrawTextPage()} is called.
*
* @param buffering
* Whether to use buffering
*/
public void setBuffering(boolean buffering) {
useBuffer = buffering;
}
/**
* @return True if buffering is enabled
* @see #setBuffering(boolean)
*/
public boolean getBuffering() {
return useBuffer;
}
}

View File

@ -514,13 +514,12 @@ public class TextFont {
/**
* Draw the given text at position (x, y), with horizontal scaling.
*
* Text will be clipped so each character fits its expected square-shaped area,
* and the area will be cleared to transparency before drwaing.
* The area will be cleared to transparency before drawing.
*
* The graphics context's current path will be overwritten.
*
* @param ctx
* a grapics context
* a graphics context
* @param x
* X-position of the lower left corner of the text
* @param y
@ -535,6 +534,29 @@ public class TextFont {
textAt(ctx, x, y, text, xScaleFactor, true, false, ctx.getFill(), null, mode, bg);
}
/**
* Draw the given text at position (x, y), with horizontal scaling.
*
* The area will not be cleared to transparency before drawing.
*
* The graphics context's current path will be overwritten.
*
* @param ctx
* a graphics context
* @param x
* X-position of the lower left corner of the text
* @param y
* Y-position of the lower left corner of the text
* @param text
* string to be printed
* @param xScaleFactor
* a horizontal scaling factor
*/
public void drawTextNoClearAt(GraphicsContext ctx, double x, double y, String text, double xScaleFactor, int mode,
Paint bg) {
textAt(ctx, x, y, text, xScaleFactor, false, false, ctx.getFill(), null, mode, bg);
}
private void fakeBlockElement(GraphicsContext ctx, String text, double xScaleFactor) {
text.codePoints().forEach((int c) -> {
// System.out.printf("%s %x%n", text, c);

View File

@ -103,6 +103,7 @@ public class Main extends Application {
if (grid)
printer.drawCharCells();
game.draw();
printer.redrawDirty();
return true;
} else if (code == KeyCode.A) {
screen.cycleAspect();
@ -153,6 +154,7 @@ public class Main extends Application {
game.displayDebug("Exception: " + e.getMessage());
}
}
printer.redrawDirty();
return true;
}
return false;
@ -175,6 +177,7 @@ public class Main extends Application {
System.out.println("doTurn() took " + (System.currentTimeMillis() - t) + "ms");
long t2 = System.currentTimeMillis();
game.draw();
printer.redrawDirty();
if (DEBUG_TIME) {
System.out.println("draw() took " + (System.currentTimeMillis() - t2) + "ms");
System.out.println("doTurn()+draw() took " + (System.currentTimeMillis() - t) + "ms");