clean debug code, move util
This commit is contained in:
parent
8c1393d95f
commit
fec4554a43
6 changed files with 409 additions and 500 deletions
|
@ -26,12 +26,12 @@ public class PDFProcessor implements Processor {
|
||||||
AbsoluteToRelativeTransformsFilter absoluteToRelativeTransformsFilter = new AbsoluteToRelativeTransformsFilter(commands);
|
AbsoluteToRelativeTransformsFilter absoluteToRelativeTransformsFilter = new AbsoluteToRelativeTransformsFilter(commands);
|
||||||
FillPaintedShapeAsImageFilter paintedShapeAsImageFilter = new FillPaintedShapeAsImageFilter(absoluteToRelativeTransformsFilter);
|
FillPaintedShapeAsImageFilter paintedShapeAsImageFilter = new FillPaintedShapeAsImageFilter(absoluteToRelativeTransformsFilter);
|
||||||
Iterable<Command<?>> filtered = new StateChangeGroupingFilter(paintedShapeAsImageFilter);
|
Iterable<Command<?>> filtered = new StateChangeGroupingFilter(paintedShapeAsImageFilter);
|
||||||
PDFProcessorResult doc = new PDFProcessorResult(pageSize);
|
PDFProcessorResult processorResult = new PDFProcessorResult(pageSize);
|
||||||
doc.setCompressed(compressed);
|
processorResult.setCompressed(compressed);
|
||||||
for (Command<?> command : filtered) {
|
for (Command<?> command : filtered) {
|
||||||
doc.handle(command);
|
processorResult.handle(command);
|
||||||
}
|
}
|
||||||
doc.close();
|
processorResult.close();
|
||||||
return doc;
|
return processorResult;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package org.xbib.graphics.io.vector;
|
package org.xbib.graphics.io.vector;
|
||||||
|
|
||||||
|
import static org.xbib.graphics.io.vector.util.ImageUtil.toBufferedImage;
|
||||||
import org.xbib.graphics.io.vector.commands.CreateCommand;
|
import org.xbib.graphics.io.vector.commands.CreateCommand;
|
||||||
import org.xbib.graphics.io.vector.commands.DisposeCommand;
|
import org.xbib.graphics.io.vector.commands.DisposeCommand;
|
||||||
import org.xbib.graphics.io.vector.commands.DrawImageCommand;
|
import org.xbib.graphics.io.vector.commands.DrawImageCommand;
|
||||||
|
@ -31,7 +32,6 @@ import java.awt.Graphics2D;
|
||||||
import java.awt.GraphicsConfiguration;
|
import java.awt.GraphicsConfiguration;
|
||||||
import java.awt.GraphicsDevice;
|
import java.awt.GraphicsDevice;
|
||||||
import java.awt.GraphicsEnvironment;
|
import java.awt.GraphicsEnvironment;
|
||||||
import java.awt.HeadlessException;
|
|
||||||
import java.awt.Image;
|
import java.awt.Image;
|
||||||
import java.awt.Paint;
|
import java.awt.Paint;
|
||||||
import java.awt.Polygon;
|
import java.awt.Polygon;
|
||||||
|
@ -40,7 +40,6 @@ import java.awt.RenderingHints;
|
||||||
import java.awt.RenderingHints.Key;
|
import java.awt.RenderingHints.Key;
|
||||||
import java.awt.Shape;
|
import java.awt.Shape;
|
||||||
import java.awt.Stroke;
|
import java.awt.Stroke;
|
||||||
import java.awt.Transparency;
|
|
||||||
import java.awt.font.FontRenderContext;
|
import java.awt.font.FontRenderContext;
|
||||||
import java.awt.font.GlyphVector;
|
import java.awt.font.GlyphVector;
|
||||||
import java.awt.font.TextLayout;
|
import java.awt.font.TextLayout;
|
||||||
|
@ -56,22 +55,17 @@ import java.awt.geom.RoundRectangle2D;
|
||||||
import java.awt.image.AffineTransformOp;
|
import java.awt.image.AffineTransformOp;
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.awt.image.BufferedImageOp;
|
import java.awt.image.BufferedImageOp;
|
||||||
import java.awt.image.ColorModel;
|
|
||||||
import java.awt.image.ImageObserver;
|
import java.awt.image.ImageObserver;
|
||||||
import java.awt.image.PixelGrabber;
|
|
||||||
import java.awt.image.RenderedImage;
|
import java.awt.image.RenderedImage;
|
||||||
import java.awt.image.WritableRaster;
|
|
||||||
import java.awt.image.renderable.RenderableImage;
|
import java.awt.image.renderable.RenderableImage;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.text.AttributedCharacterIterator;
|
import java.text.AttributedCharacterIterator;
|
||||||
import java.util.Hashtable;
|
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
import javax.swing.ImageIcon;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base for classes that want to implement vector export.
|
* Base for classes that want to implement vector export.
|
||||||
|
@ -101,13 +95,17 @@ public class VectorGraphics2D extends Graphics2D implements Cloneable {
|
||||||
|
|
||||||
private GraphicsState state;
|
private GraphicsState state;
|
||||||
|
|
||||||
private Graphics2D debugValidateGraphics;
|
private Graphics2D graphics2D;
|
||||||
|
|
||||||
public VectorGraphics2D() {
|
public VectorGraphics2D() {
|
||||||
this(null, null);
|
this(null, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public VectorGraphics2D(Processor processor, PageSize pageSize) {
|
public VectorGraphics2D(Processor processor, PageSize pageSize) {
|
||||||
|
this(processor, pageSize, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public VectorGraphics2D(Processor processor, PageSize pageSize, Graphics2D graphics2D) {
|
||||||
this.processor = processor;
|
this.processor = processor;
|
||||||
this.pageSize = pageSize;
|
this.pageSize = pageSize;
|
||||||
this.commands = new LinkedList<>();
|
this.commands = new LinkedList<>();
|
||||||
|
@ -121,9 +119,13 @@ public class VectorGraphics2D extends Graphics2D implements Cloneable {
|
||||||
}
|
}
|
||||||
fontRenderContext = new FontRenderContext(null, false, true);
|
fontRenderContext = new FontRenderContext(null, false, true);
|
||||||
state = new GraphicsState();
|
state = new GraphicsState();
|
||||||
BufferedImage _debug_validate_bimg = new BufferedImage(200, 250, BufferedImage.TYPE_INT_ARGB);
|
if (graphics2D == null) {
|
||||||
debugValidateGraphics = (Graphics2D) _debug_validate_bimg.getGraphics();
|
BufferedImage bufferedImage = new BufferedImage(200, 250, BufferedImage.TYPE_INT_ARGB);
|
||||||
debugValidateGraphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
this.graphics2D = (Graphics2D) bufferedImage.getGraphics();
|
||||||
|
this.graphics2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
||||||
|
} else {
|
||||||
|
this.graphics2D = graphics2D;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public PageSize getPageSize() {
|
public PageSize getPageSize() {
|
||||||
|
@ -161,29 +163,17 @@ public class VectorGraphics2D extends Graphics2D implements Cloneable {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void clip(Shape s) {
|
public void clip(Shape s) {
|
||||||
debugValidateGraphics.clip(s);
|
|
||||||
Shape clipOld = getClip();
|
|
||||||
Shape clip = getClip();
|
|
||||||
if ((clip != null) && (s != null)) {
|
|
||||||
s = intersectShapes(clip, s);
|
|
||||||
}
|
|
||||||
setClip(s);
|
|
||||||
Shape clipNew = getClip();
|
|
||||||
if ((clipNew == null || debugValidateGraphics.getClip() == null) && clipNew != debugValidateGraphics.getClip()) {
|
|
||||||
throw new IllegalStateException("clip() validation failed: clip(" + clipOld + ", " + s + ") => " + clipNew + " != " + debugValidateGraphics.getClip());
|
|
||||||
}
|
|
||||||
if (clipNew != null && notEquals(clipNew, debugValidateGraphics.getClip())) {
|
|
||||||
throw new IllegalStateException("clip() validation failed: clip(" + clipOld + ", " + s + ") => " + clipNew + " != " + debugValidateGraphics.getClip());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void draw(Shape s) {
|
|
||||||
if (isDisposed() || s == null) {
|
if (isDisposed() || s == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
emit(new DrawShapeCommand(s));
|
if (graphics2D != null) {
|
||||||
debugValidateGraphics.draw(s);
|
graphics2D.clip(s);
|
||||||
|
}
|
||||||
|
Shape clip = getClip();
|
||||||
|
if (clip != null) {
|
||||||
|
s = intersectShapes(clip, s);
|
||||||
|
}
|
||||||
|
setClip(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -192,11 +182,22 @@ public class VectorGraphics2D extends Graphics2D implements Cloneable {
|
||||||
draw(s);
|
draw(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void draw(Shape s) {
|
||||||
|
if (isDisposed() || s == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
emit(new DrawShapeCommand(s));
|
||||||
|
if (graphics2D != null) {
|
||||||
|
graphics2D.draw(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean drawImage(Image img, AffineTransform xform, ImageObserver obs) {
|
public boolean drawImage(Image img, AffineTransform xform, ImageObserver obs) {
|
||||||
BufferedImage bimg = getTransformedImage(img, xform);
|
BufferedImage bufferedImage = getTransformedImage(img, xform);
|
||||||
return drawImage(bimg, bimg.getMinX(), bimg.getMinY(),
|
return drawImage(bufferedImage, bufferedImage.getMinX(), bufferedImage.getMinY(),
|
||||||
bimg.getWidth(), bimg.getHeight(), null, null);
|
bufferedImage.getWidth(), bufferedImage.getHeight(), null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -228,16 +229,9 @@ public class VectorGraphics2D extends Graphics2D implements Cloneable {
|
||||||
if (isDisposed() || str == null || str.trim().length() == 0) {
|
if (isDisposed() || str == null || str.trim().length() == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
boolean isTextAsVectors = false;
|
emit(new DrawStringCommand(str, x, y));
|
||||||
if (isTextAsVectors) {
|
if (graphics2D != null) {
|
||||||
TextLayout layout = new TextLayout(str, getFont(),
|
graphics2D.drawString(str, x, y);
|
||||||
getFontRenderContext());
|
|
||||||
Shape s = layout.getOutline(
|
|
||||||
AffineTransform.getTranslateInstance(x, y));
|
|
||||||
fill(s);
|
|
||||||
} else {
|
|
||||||
emit(new DrawStringCommand(str, x, y));
|
|
||||||
debugValidateGraphics.drawString(str, x, y);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -249,8 +243,7 @@ public class VectorGraphics2D extends Graphics2D implements Cloneable {
|
||||||
@Override
|
@Override
|
||||||
public void drawString(AttributedCharacterIterator iterator, float x, float y) {
|
public void drawString(AttributedCharacterIterator iterator, float x, float y) {
|
||||||
StringBuilder buf = new StringBuilder();
|
StringBuilder buf = new StringBuilder();
|
||||||
for (char c = iterator.first(); c != AttributedCharacterIterator.DONE;
|
for (char c = iterator.first(); c != AttributedCharacterIterator.DONE; c = iterator.next()) {
|
||||||
c = iterator.next()) {
|
|
||||||
buf.append(c);
|
buf.append(c);
|
||||||
}
|
}
|
||||||
drawString(buf.toString(), x, y);
|
drawString(buf.toString(), x, y);
|
||||||
|
@ -262,7 +255,9 @@ public class VectorGraphics2D extends Graphics2D implements Cloneable {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
emit(new FillShapeCommand(s));
|
emit(new FillShapeCommand(s));
|
||||||
debugValidateGraphics.fill(s);
|
if (graphics2D != null) {
|
||||||
|
graphics2D.fill(s);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -277,9 +272,8 @@ public class VectorGraphics2D extends Graphics2D implements Cloneable {
|
||||||
}
|
}
|
||||||
emit(new SetBackgroundCommand(color));
|
emit(new SetBackgroundCommand(color));
|
||||||
state.setBackground(color);
|
state.setBackground(color);
|
||||||
debugValidateGraphics.setBackground(color);
|
if (graphics2D != null) {
|
||||||
if (!getBackground().equals(debugValidateGraphics.getBackground())) {
|
graphics2D.setBackground(color);
|
||||||
throw new IllegalStateException("setBackground() validation failed");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -298,9 +292,8 @@ public class VectorGraphics2D extends Graphics2D implements Cloneable {
|
||||||
}
|
}
|
||||||
emit(new SetCompositeCommand(comp));
|
emit(new SetCompositeCommand(comp));
|
||||||
state.setComposite(comp);
|
state.setComposite(comp);
|
||||||
debugValidateGraphics.setComposite(comp);
|
if (graphics2D != null) {
|
||||||
if (!getComposite().equals(debugValidateGraphics.getComposite())) {
|
graphics2D.setComposite(comp);
|
||||||
throw new IllegalStateException("setComposite() validation failed");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -333,9 +326,8 @@ public class VectorGraphics2D extends Graphics2D implements Cloneable {
|
||||||
}
|
}
|
||||||
emit(new SetPaintCommand(paint));
|
emit(new SetPaintCommand(paint));
|
||||||
state.setPaint(paint);
|
state.setPaint(paint);
|
||||||
debugValidateGraphics.setPaint(paint);
|
if (graphics2D != null) {
|
||||||
if (!getPaint().equals(debugValidateGraphics.getPaint())) {
|
graphics2D.setPaint(paint);
|
||||||
throw new IllegalStateException("setPaint() validation failed");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -382,10 +374,8 @@ public class VectorGraphics2D extends Graphics2D implements Cloneable {
|
||||||
}
|
}
|
||||||
emit(new SetStrokeCommand(s));
|
emit(new SetStrokeCommand(s));
|
||||||
state.setStroke(s);
|
state.setStroke(s);
|
||||||
|
if (graphics2D != null) {
|
||||||
debugValidateGraphics.setStroke(s);
|
graphics2D.setStroke(s);
|
||||||
if (!getStroke().equals(debugValidateGraphics.getStroke())) {
|
|
||||||
throw new IllegalStateException("setStroke() validation failed");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -397,12 +387,9 @@ public class VectorGraphics2D extends Graphics2D implements Cloneable {
|
||||||
}
|
}
|
||||||
hitShape = state.transformShape(hitShape);
|
hitShape = state.transformShape(hitShape);
|
||||||
boolean hit = hitShape.intersects(rect);
|
boolean hit = hitShape.intersects(rect);
|
||||||
|
if (graphics2D != null) {
|
||||||
boolean _debug_hit = debugValidateGraphics.hit(rect, s, onStroke);
|
graphics2D.hit(rect, s, onStroke);
|
||||||
if (hit != _debug_hit) {
|
|
||||||
throw new IllegalStateException("setClip() validation failed");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return hit;
|
return hit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -427,10 +414,8 @@ public class VectorGraphics2D extends Graphics2D implements Cloneable {
|
||||||
}
|
}
|
||||||
emit(new SetTransformCommand(tx));
|
emit(new SetTransformCommand(tx));
|
||||||
state.setTransform(tx);
|
state.setTransform(tx);
|
||||||
|
if (graphics2D != null) {
|
||||||
debugValidateGraphics.setTransform(tx);
|
graphics2D.setTransform(tx);
|
||||||
if (!getTransform().equals(debugValidateGraphics.getTransform())) {
|
|
||||||
throw new IllegalStateException("setTransform() validation failed");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -443,10 +428,8 @@ public class VectorGraphics2D extends Graphics2D implements Cloneable {
|
||||||
txNew.shear(shx, shy);
|
txNew.shear(shx, shy);
|
||||||
emit(new ShearCommand(shx, shy));
|
emit(new ShearCommand(shx, shy));
|
||||||
state.setTransform(txNew);
|
state.setTransform(txNew);
|
||||||
|
if ( graphics2D != null) {
|
||||||
debugValidateGraphics.shear(shx, shy);
|
graphics2D.shear(shx, shy);
|
||||||
if (!getTransform().equals(debugValidateGraphics.getTransform())) {
|
|
||||||
throw new IllegalStateException("shear() validation failed");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -459,10 +442,8 @@ public class VectorGraphics2D extends Graphics2D implements Cloneable {
|
||||||
txNew.concatenate(tx);
|
txNew.concatenate(tx);
|
||||||
emit(new TransformCommand(tx));
|
emit(new TransformCommand(tx));
|
||||||
state.setTransform(txNew);
|
state.setTransform(txNew);
|
||||||
|
if (graphics2D != null) {
|
||||||
debugValidateGraphics.transform(tx);
|
graphics2D.transform(tx);
|
||||||
if (!getTransform().equals(debugValidateGraphics.getTransform())) {
|
|
||||||
throw new IllegalStateException("transform() validation failed");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -480,9 +461,8 @@ public class VectorGraphics2D extends Graphics2D implements Cloneable {
|
||||||
txNew.translate(tx, ty);
|
txNew.translate(tx, ty);
|
||||||
emit(new TranslateCommand(tx, ty));
|
emit(new TranslateCommand(tx, ty));
|
||||||
state.setTransform(txNew);
|
state.setTransform(txNew);
|
||||||
debugValidateGraphics.translate(tx, ty);
|
if (graphics2D != null) {
|
||||||
if (!getTransform().equals(debugValidateGraphics.getTransform())) {
|
graphics2D.translate(tx, ty);
|
||||||
throw new IllegalStateException("translate() validation failed");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -505,14 +485,12 @@ public class VectorGraphics2D extends Graphics2D implements Cloneable {
|
||||||
emit(new RotateCommand(theta, x, y));
|
emit(new RotateCommand(theta, x, y));
|
||||||
state.setTransform(txNew);
|
state.setTransform(txNew);
|
||||||
if (x == 0.0 && y == 0.0) {
|
if (x == 0.0 && y == 0.0) {
|
||||||
debugValidateGraphics.rotate(theta);
|
if (graphics2D != null) {
|
||||||
if (!getTransform().equals(debugValidateGraphics.getTransform())) {
|
graphics2D.rotate(theta);
|
||||||
throw new IllegalStateException("rotate(theta) validation failed");
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
debugValidateGraphics.rotate(theta, x, y);
|
if (graphics2D != null) {
|
||||||
if (!getTransform().equals(debugValidateGraphics.getTransform())) {
|
graphics2D.rotate(theta, x, y);
|
||||||
throw new IllegalStateException("rotate(theta,x,y) validation failed");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -526,9 +504,8 @@ public class VectorGraphics2D extends Graphics2D implements Cloneable {
|
||||||
affineTransform.scale(sx, sy);
|
affineTransform.scale(sx, sy);
|
||||||
emit(new ScaleCommand(sx, sy));
|
emit(new ScaleCommand(sx, sy));
|
||||||
state.setTransform(affineTransform);
|
state.setTransform(affineTransform);
|
||||||
debugValidateGraphics.scale(sx, sy);
|
if (graphics2D != null) {
|
||||||
if (!getTransform().equals(debugValidateGraphics.getTransform())) {
|
graphics2D.scale(sx, sy);
|
||||||
throw new IllegalStateException("scale() validation failed");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -547,6 +524,7 @@ public class VectorGraphics2D extends Graphics2D implements Cloneable {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void copyArea(int x, int y, int width, int height, int dx, int dy) {
|
public void copyArea(int x, int y, int width, int height, int dx, int dy) {
|
||||||
|
// unable to implement
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -561,7 +539,9 @@ public class VectorGraphics2D extends Graphics2D implements Cloneable {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
emit(new CreateCommand(clone));
|
emit(new CreateCommand(clone));
|
||||||
clone.debugValidateGraphics = (Graphics2D) debugValidateGraphics.create();
|
if (graphics2D != null) {
|
||||||
|
clone.graphics2D = (Graphics2D) graphics2D.create();
|
||||||
|
}
|
||||||
return clone;
|
return clone;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -572,13 +552,14 @@ public class VectorGraphics2D extends Graphics2D implements Cloneable {
|
||||||
}
|
}
|
||||||
emit(new DisposeCommand(this));
|
emit(new DisposeCommand(this));
|
||||||
disposed = true;
|
disposed = true;
|
||||||
debugValidateGraphics.dispose();
|
if (graphics2D != null) {
|
||||||
|
graphics2D.dispose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void drawArc(int x, int y, int width, int height, int startAngle, int arcAngle) {
|
public void drawArc(int x, int y, int width, int height, int startAngle, int arcAngle) {
|
||||||
draw(new Arc2D.Double(x, y, width, height,
|
draw(new Arc2D.Double(x, y, width, height, startAngle, arcAngle, Arc2D.OPEN));
|
||||||
startAngle, arcAngle, Arc2D.OPEN));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -587,21 +568,17 @@ public class VectorGraphics2D extends Graphics2D implements Cloneable {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean drawImage(Image img, int x, int y, Color bgcolor,
|
public boolean drawImage(Image img, int x, int y, Color bgcolor, ImageObserver observer) {
|
||||||
ImageObserver observer) {
|
return drawImage(img, x, y, img.getWidth(observer), img.getHeight(observer), bgcolor, observer);
|
||||||
return drawImage(img, x, y, img.getWidth(observer),
|
|
||||||
img.getHeight(observer), bgcolor, observer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean drawImage(Image img, int x, int y, int width, int height,
|
public boolean drawImage(Image img, int x, int y, int width, int height, ImageObserver observer) {
|
||||||
ImageObserver observer) {
|
|
||||||
return drawImage(img, x, y, width, height, null, observer);
|
return drawImage(img, x, y, width, height, null, observer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean drawImage(Image img, int x, int y, int width, int height,
|
public boolean drawImage(Image img, int x, int y, int width, int height, Color bgcolor, ImageObserver observer) {
|
||||||
Color bgcolor, ImageObserver observer) {
|
|
||||||
if (isDisposed() || img == null) {
|
if (isDisposed() || img == null) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -615,7 +592,9 @@ public class VectorGraphics2D extends Graphics2D implements Cloneable {
|
||||||
setColor(bgcolorOld);
|
setColor(bgcolorOld);
|
||||||
}
|
}
|
||||||
emit(new DrawImageCommand(img, imageWidth, imageHeight, x, y, width, height));
|
emit(new DrawImageCommand(img, imageWidth, imageHeight, x, y, width, height));
|
||||||
debugValidateGraphics.drawImage(img, x, y, width, height, bgcolor, observer);
|
if (graphics2D != null) {
|
||||||
|
graphics2D.drawImage(img, x, y, width, height, bgcolor, observer);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -737,16 +716,8 @@ public class VectorGraphics2D extends Graphics2D implements Cloneable {
|
||||||
}
|
}
|
||||||
emit(new SetClipCommand(clip));
|
emit(new SetClipCommand(clip));
|
||||||
state.setClip(clip);
|
state.setClip(clip);
|
||||||
|
if (graphics2D != null) {
|
||||||
debugValidateGraphics.setClip(clip);
|
graphics2D.setClip(clip);
|
||||||
if (getClip() == null) {
|
|
||||||
if (debugValidateGraphics.getClip() != null) {
|
|
||||||
throw new IllegalStateException("setClip() validation failed: clip=null, validation=" +
|
|
||||||
debugValidateGraphics.getClip());
|
|
||||||
}
|
|
||||||
} else if (notEquals(getClip(), debugValidateGraphics.getClip())) {
|
|
||||||
throw new IllegalStateException("setClip() validation failed: clip=" + getClip() + ", validation=" +
|
|
||||||
debugValidateGraphics.getClip());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -771,9 +742,8 @@ public class VectorGraphics2D extends Graphics2D implements Cloneable {
|
||||||
emit(new SetColorCommand(c));
|
emit(new SetColorCommand(c));
|
||||||
state.setColor(c);
|
state.setColor(c);
|
||||||
state.setPaint(c);
|
state.setPaint(c);
|
||||||
debugValidateGraphics.setColor(c);
|
if (graphics2D != null) {
|
||||||
if (!getColor().equals(debugValidateGraphics.getColor())) {
|
graphics2D.setColor(c);
|
||||||
throw new IllegalStateException("setColor() validation failed");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -789,9 +759,8 @@ public class VectorGraphics2D extends Graphics2D implements Cloneable {
|
||||||
}
|
}
|
||||||
emit(new SetFontCommand(font));
|
emit(new SetFontCommand(font));
|
||||||
state.setFont(font);
|
state.setFont(font);
|
||||||
debugValidateGraphics.setFont(font);
|
if (graphics2D != null) {
|
||||||
if (!getFont().equals(debugValidateGraphics.getFont())) {
|
graphics2D.setFont(font);
|
||||||
throw new IllegalStateException("setFont() validation failed");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -812,7 +781,9 @@ public class VectorGraphics2D extends Graphics2D implements Cloneable {
|
||||||
@Override
|
@Override
|
||||||
public void setPaintMode() {
|
public void setPaintMode() {
|
||||||
setComposite(AlphaComposite.SrcOver);
|
setComposite(AlphaComposite.SrcOver);
|
||||||
debugValidateGraphics.setPaintMode();
|
if (graphics2D != null) {
|
||||||
|
graphics2D.setPaintMode();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -822,7 +793,9 @@ public class VectorGraphics2D extends Graphics2D implements Cloneable {
|
||||||
}
|
}
|
||||||
emit(new SetXORModeCommand(c1));
|
emit(new SetXORModeCommand(c1));
|
||||||
state.setXorMode(c1);
|
state.setXorMode(c1);
|
||||||
debugValidateGraphics.setXORMode(c1);
|
if (graphics2D != null) {
|
||||||
|
graphics2D.setXORMode(c1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Color getXORMode() {
|
public Color getXORMode() {
|
||||||
|
@ -849,13 +822,10 @@ public class VectorGraphics2D extends Graphics2D implements Cloneable {
|
||||||
* @return Image with transformed content
|
* @return Image with transformed content
|
||||||
*/
|
*/
|
||||||
private BufferedImage getTransformedImage(Image image, AffineTransform xform) {
|
private BufferedImage getTransformedImage(Image image, AffineTransform xform) {
|
||||||
Integer interpolationType =
|
Integer interpolationType = (Integer) getRenderingHint(RenderingHints.KEY_INTERPOLATION);
|
||||||
(Integer) getRenderingHint(RenderingHints.KEY_INTERPOLATION);
|
if (RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR.equals(interpolationType)) {
|
||||||
if (RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR
|
|
||||||
.equals(interpolationType)) {
|
|
||||||
interpolationType = AffineTransformOp.TYPE_NEAREST_NEIGHBOR;
|
interpolationType = AffineTransformOp.TYPE_NEAREST_NEIGHBOR;
|
||||||
} else if (RenderingHints.VALUE_INTERPOLATION_BILINEAR
|
} else if (RenderingHints.VALUE_INTERPOLATION_BILINEAR.equals(interpolationType)) {
|
||||||
.equals(interpolationType)) {
|
|
||||||
interpolationType = AffineTransformOp.TYPE_BILINEAR;
|
interpolationType = AffineTransformOp.TYPE_BILINEAR;
|
||||||
} else {
|
} else {
|
||||||
interpolationType = AffineTransformOp.TYPE_BICUBIC;
|
interpolationType = AffineTransformOp.TYPE_BICUBIC;
|
||||||
|
@ -865,7 +835,7 @@ public class VectorGraphics2D extends Graphics2D implements Cloneable {
|
||||||
return op.filter(bufferedImage, null);
|
return op.filter(bufferedImage, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean notEquals(Shape shapeA, Shape shapeB) {
|
/*private static boolean notEquals(Shape shapeA, Shape shapeB) {
|
||||||
PathIterator pathAIterator = shapeA.getPathIterator(null);
|
PathIterator pathAIterator = shapeA.getPathIterator(null);
|
||||||
PathIterator pathBIterator = shapeB.getPathIterator(null);
|
PathIterator pathBIterator = shapeB.getPathIterator(null);
|
||||||
if (pathAIterator.getWindingRule() != pathBIterator.getWindingRule()) {
|
if (pathAIterator.getWindingRule() != pathBIterator.getWindingRule()) {
|
||||||
|
@ -888,99 +858,7 @@ public class VectorGraphics2D extends Graphics2D implements Cloneable {
|
||||||
pathBIterator.next();
|
pathBIterator.next();
|
||||||
}
|
}
|
||||||
return !pathBIterator.isDone();
|
return !pathBIterator.isDone();
|
||||||
}
|
}*/
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts an arbitrary image to a {@code BufferedImage}.
|
|
||||||
*
|
|
||||||
* @param image Image that should be converted.
|
|
||||||
* @return a buffered image containing the image pixels, or the original
|
|
||||||
* instance if the image already was of type {@code BufferedImage}.
|
|
||||||
*/
|
|
||||||
static BufferedImage toBufferedImage(RenderedImage image) {
|
|
||||||
if (image instanceof BufferedImage) {
|
|
||||||
return (BufferedImage) image;
|
|
||||||
}
|
|
||||||
ColorModel cm = image.getColorModel();
|
|
||||||
WritableRaster raster = cm.createCompatibleWritableRaster(image.getWidth(), image.getHeight());
|
|
||||||
boolean isRasterPremultiplied = cm.isAlphaPremultiplied();
|
|
||||||
Hashtable<String, Object> properties = null;
|
|
||||||
if (image.getPropertyNames() != null) {
|
|
||||||
properties = new Hashtable<>();
|
|
||||||
for (String key : image.getPropertyNames()) {
|
|
||||||
properties.put(key, image.getProperty(key));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
BufferedImage bimage = new BufferedImage(cm, raster, isRasterPremultiplied, properties);
|
|
||||||
image.copyData(raster);
|
|
||||||
return bimage;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method returns a buffered image with the contents of an image.
|
|
||||||
* Taken from http://www.exampledepot.com/egs/java.awt.image/Image2Buf.html
|
|
||||||
*
|
|
||||||
* @param image Image to be converted
|
|
||||||
* @return a buffered image with the contents of the specified image
|
|
||||||
*/
|
|
||||||
static BufferedImage toBufferedImage(Image image) {
|
|
||||||
if (image instanceof BufferedImage) {
|
|
||||||
return (BufferedImage) image;
|
|
||||||
}
|
|
||||||
image = new ImageIcon(image).getImage();
|
|
||||||
boolean hasAlpha = hasAlpha(image);
|
|
||||||
BufferedImage bimage;
|
|
||||||
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
|
|
||||||
try {
|
|
||||||
int transparency = Transparency.OPAQUE;
|
|
||||||
if (hasAlpha) {
|
|
||||||
transparency = Transparency.TRANSLUCENT;
|
|
||||||
}
|
|
||||||
GraphicsDevice gs = ge.getDefaultScreenDevice();
|
|
||||||
GraphicsConfiguration gc = gs.getDefaultConfiguration();
|
|
||||||
bimage = gc.createCompatibleImage(image.getWidth(null), image.getHeight(null), transparency);
|
|
||||||
} catch (HeadlessException e) {
|
|
||||||
bimage = null;
|
|
||||||
}
|
|
||||||
if (bimage == null) {
|
|
||||||
int type = BufferedImage.TYPE_INT_RGB;
|
|
||||||
if (hasAlpha) {
|
|
||||||
type = BufferedImage.TYPE_INT_ARGB;
|
|
||||||
}
|
|
||||||
bimage = new BufferedImage(image.getWidth(null), image.getHeight(null), type);
|
|
||||||
}
|
|
||||||
Graphics g = bimage.createGraphics();
|
|
||||||
g.drawImage(image, 0, 0, null);
|
|
||||||
g.dispose();
|
|
||||||
return bimage;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method returns {@code true} if the specified image has the
|
|
||||||
* possibility to store transparent pixels.
|
|
||||||
* Inspired by http://www.exampledepot.com/egs/java.awt.image/HasAlpha.html
|
|
||||||
*
|
|
||||||
* @param image Image that should be checked for alpha channel.
|
|
||||||
* @return {@code true} if the specified image can have transparent pixels,
|
|
||||||
* {@code false} otherwise
|
|
||||||
*/
|
|
||||||
static boolean hasAlpha(Image image) {
|
|
||||||
ColorModel cm;
|
|
||||||
if (image instanceof BufferedImage) {
|
|
||||||
BufferedImage bimage = (BufferedImage) image;
|
|
||||||
cm = bimage.getColorModel();
|
|
||||||
} else {
|
|
||||||
PixelGrabber pg = new PixelGrabber(image, 0, 0, 1, 1, false);
|
|
||||||
try {
|
|
||||||
pg.grabPixels();
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
cm = pg.getColorModel();
|
|
||||||
}
|
|
||||||
return cm.hasAlpha();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Shape intersectShapes(Shape s1, Shape s2) {
|
private static Shape intersectShapes(Shape s1, Shape s2) {
|
||||||
if (s1 instanceof Rectangle2D && s2 instanceof Rectangle2D) {
|
if (s1 instanceof Rectangle2D && s2 instanceof Rectangle2D) {
|
||||||
|
|
|
@ -0,0 +1,111 @@
|
||||||
|
package org.xbib.graphics.io.vector.util;
|
||||||
|
|
||||||
|
import java.awt.Graphics;
|
||||||
|
import java.awt.GraphicsConfiguration;
|
||||||
|
import java.awt.GraphicsDevice;
|
||||||
|
import java.awt.GraphicsEnvironment;
|
||||||
|
import java.awt.HeadlessException;
|
||||||
|
import java.awt.Image;
|
||||||
|
import java.awt.Transparency;
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
|
import java.awt.image.ColorModel;
|
||||||
|
import java.awt.image.PixelGrabber;
|
||||||
|
import java.awt.image.RenderedImage;
|
||||||
|
import java.awt.image.WritableRaster;
|
||||||
|
import java.util.Hashtable;
|
||||||
|
import javax.swing.ImageIcon;
|
||||||
|
|
||||||
|
public class ImageUtil {
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts an arbitrary image to a {@code BufferedImage}.
|
||||||
|
*
|
||||||
|
* @param image Image that should be converted.
|
||||||
|
* @return a buffered image containing the image pixels, or the original
|
||||||
|
* instance if the image already was of type {@code BufferedImage}.
|
||||||
|
*/
|
||||||
|
public static BufferedImage toBufferedImage(RenderedImage image) {
|
||||||
|
if (image instanceof BufferedImage) {
|
||||||
|
return (BufferedImage) image;
|
||||||
|
}
|
||||||
|
ColorModel cm = image.getColorModel();
|
||||||
|
WritableRaster raster = cm.createCompatibleWritableRaster(image.getWidth(), image.getHeight());
|
||||||
|
boolean isRasterPremultiplied = cm.isAlphaPremultiplied();
|
||||||
|
Hashtable<String, Object> properties = null;
|
||||||
|
if (image.getPropertyNames() != null) {
|
||||||
|
properties = new Hashtable<>();
|
||||||
|
for (String key : image.getPropertyNames()) {
|
||||||
|
properties.put(key, image.getProperty(key));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
BufferedImage bimage = new BufferedImage(cm, raster, isRasterPremultiplied, properties);
|
||||||
|
image.copyData(raster);
|
||||||
|
return bimage;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method returns a buffered image with the contents of an image.
|
||||||
|
* Taken from http://www.exampledepot.com/egs/java.awt.image/Image2Buf.html
|
||||||
|
*
|
||||||
|
* @param image Image to be converted
|
||||||
|
* @return a buffered image with the contents of the specified image
|
||||||
|
*/
|
||||||
|
public static BufferedImage toBufferedImage(Image image) {
|
||||||
|
if (image instanceof BufferedImage) {
|
||||||
|
return (BufferedImage) image;
|
||||||
|
}
|
||||||
|
image = new ImageIcon(image).getImage();
|
||||||
|
boolean hasAlpha = hasAlpha(image);
|
||||||
|
BufferedImage bimage;
|
||||||
|
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
|
||||||
|
try {
|
||||||
|
int transparency = Transparency.OPAQUE;
|
||||||
|
if (hasAlpha) {
|
||||||
|
transparency = Transparency.TRANSLUCENT;
|
||||||
|
}
|
||||||
|
GraphicsDevice gs = ge.getDefaultScreenDevice();
|
||||||
|
GraphicsConfiguration gc = gs.getDefaultConfiguration();
|
||||||
|
bimage = gc.createCompatibleImage(image.getWidth(null), image.getHeight(null), transparency);
|
||||||
|
} catch (HeadlessException e) {
|
||||||
|
bimage = null;
|
||||||
|
}
|
||||||
|
if (bimage == null) {
|
||||||
|
int type = BufferedImage.TYPE_INT_RGB;
|
||||||
|
if (hasAlpha) {
|
||||||
|
type = BufferedImage.TYPE_INT_ARGB;
|
||||||
|
}
|
||||||
|
bimage = new BufferedImage(image.getWidth(null), image.getHeight(null), type);
|
||||||
|
}
|
||||||
|
Graphics g = bimage.createGraphics();
|
||||||
|
g.drawImage(image, 0, 0, null);
|
||||||
|
g.dispose();
|
||||||
|
return bimage;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method returns {@code true} if the specified image has the
|
||||||
|
* possibility to store transparent pixels.
|
||||||
|
* Inspired by http://www.exampledepot.com/egs/java.awt.image/HasAlpha.html
|
||||||
|
*
|
||||||
|
* @param image Image that should be checked for alpha channel.
|
||||||
|
* @return {@code true} if the specified image can have transparent pixels,
|
||||||
|
* {@code false} otherwise
|
||||||
|
*/
|
||||||
|
public static boolean hasAlpha(Image image) {
|
||||||
|
ColorModel cm;
|
||||||
|
if (image instanceof BufferedImage) {
|
||||||
|
BufferedImage bimage = (BufferedImage) image;
|
||||||
|
cm = bimage.getColorModel();
|
||||||
|
} else {
|
||||||
|
PixelGrabber pg = new PixelGrabber(image, 0, 0, 1, 1, false);
|
||||||
|
try {
|
||||||
|
pg.grabPixels();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
cm = pg.getColorModel();
|
||||||
|
}
|
||||||
|
return cm.hasAlpha();
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,265 +0,0 @@
|
||||||
package org.xbib.graphics.io.vector;
|
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.IdentityHashMap;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.TreeMap;
|
|
||||||
import java.util.regex.Matcher;
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
public abstract class TestUtils {
|
|
||||||
|
|
||||||
protected TestUtils() {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void assertTemplateEquals(Template expected, Template actual) {
|
|
||||||
Iterator<Object> itExpected = expected.iterator();
|
|
||||||
Iterator<Object> itActual = actual.iterator();
|
|
||||||
while (itExpected.hasNext() && itActual.hasNext()) {
|
|
||||||
Object lineExpected = itExpected.next();
|
|
||||||
Object lineActual = itActual.next();
|
|
||||||
if (lineExpected == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
assertTrue(lineActual instanceof String,
|
|
||||||
String.format("Line is of type %s, expected String.", lineActual.getClass()));
|
|
||||||
if (lineExpected instanceof String) {
|
|
||||||
assertEquals(lineExpected, lineActual);
|
|
||||||
} else if (lineExpected instanceof Pattern) {
|
|
||||||
Pattern expectedPattern = (Pattern) lineExpected;
|
|
||||||
Matcher matcher = expectedPattern.matcher((String) lineActual);
|
|
||||||
assertTrue(matcher.matches(),
|
|
||||||
String.format("Line didn't match pattern.\nExpected: \"%s\"\nActual: \"%s\"", matcher.pattern(), lineActual));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
assertEquals(expected.size(), actual.size(), "Wrong number of lines in template.");
|
|
||||||
}
|
|
||||||
|
|
||||||
private static List<XMLFragment> parseXML(String xmlString) {
|
|
||||||
XMLFragment frag;
|
|
||||||
List<XMLFragment> fragments = new LinkedList<XMLFragment>();
|
|
||||||
int startPos = 0;
|
|
||||||
while ((frag = XMLFragment.parse(xmlString, startPos)) != null) {
|
|
||||||
fragments.add(frag);
|
|
||||||
startPos = frag.matchEnd;
|
|
||||||
}
|
|
||||||
return fragments;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void assertXMLEquals(String expected, String actual) {
|
|
||||||
List<XMLFragment> expectedFrags = parseXML(expected);
|
|
||||||
List<XMLFragment> actualFrags = parseXML(actual);
|
|
||||||
|
|
||||||
Iterator<XMLFragment> itExpected = expectedFrags.iterator();
|
|
||||||
Iterator<XMLFragment> itActual = actualFrags.iterator();
|
|
||||||
while (itExpected.hasNext() && itActual.hasNext()) {
|
|
||||||
XMLFragment expectedFrag = itExpected.next();
|
|
||||||
XMLFragment actualFrag = itActual.next();
|
|
||||||
assertEquals(expectedFrag, actualFrag);
|
|
||||||
}
|
|
||||||
|
|
||||||
assertEquals(expectedFrags.size(), actualFrags.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("serial")
|
|
||||||
public static class Template extends LinkedList<Object> {
|
|
||||||
public Template(Object[] lines) {
|
|
||||||
Collections.addAll(this, lines);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Template(Template[] templates) {
|
|
||||||
for (Template template : templates) {
|
|
||||||
addAll(template);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class XMLFragment {
|
|
||||||
|
|
||||||
private static final Pattern CDATA = Pattern.compile("\\s*<!\\[CDATA\\[(.*?)\\]\\]>");
|
|
||||||
|
|
||||||
private static final Pattern COMMENT = Pattern.compile("\\s*<!--(.*?)-->");
|
|
||||||
|
|
||||||
private static final Pattern TAG_BEGIN = Pattern.compile("\\s*<(/|\\?|!)?\\s*([^\\s>/\\?]+)");
|
|
||||||
|
|
||||||
private static final Pattern TAG_END = Pattern.compile("\\s*(/|\\?)?>");
|
|
||||||
|
|
||||||
private static final Pattern TAG_ATTRIBUTE = Pattern.compile("\\s*([^\\s>=]+)=(\"[^\"]*\"|'[^']*')");
|
|
||||||
|
|
||||||
private static final Pattern DOCTYPE_PART = Pattern.compile("\\s*(\"[^\"]*\"|'[^']*'|[^\\s>]+)");
|
|
||||||
|
|
||||||
public final String name;
|
|
||||||
|
|
||||||
public final FragmentType type;
|
|
||||||
|
|
||||||
public final Map<String, String> attributes;
|
|
||||||
|
|
||||||
public final int matchStart;
|
|
||||||
|
|
||||||
public final int matchEnd;
|
|
||||||
|
|
||||||
public XMLFragment(String name, FragmentType type, Map<String, String> attributes,
|
|
||||||
int matchStart, int matchEnd) {
|
|
||||||
this.name = name;
|
|
||||||
this.type = type;
|
|
||||||
this.attributes = Collections.unmodifiableMap(
|
|
||||||
new TreeMap<String, String>(attributes));
|
|
||||||
this.matchStart = matchStart;
|
|
||||||
this.matchEnd = matchEnd;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static XMLFragment parse(String xmlString, int matchStart) {
|
|
||||||
Map<String, String> attrs = new IdentityHashMap<String, String>();
|
|
||||||
|
|
||||||
Matcher cdataMatch = CDATA.matcher(xmlString);
|
|
||||||
cdataMatch.region(matchStart, xmlString.length());
|
|
||||||
if (cdataMatch.lookingAt()) {
|
|
||||||
attrs.put("value", cdataMatch.group(1));
|
|
||||||
return new XMLFragment("", FragmentType.CDATA, attrs, matchStart, cdataMatch.end());
|
|
||||||
}
|
|
||||||
|
|
||||||
Matcher commentMatch = COMMENT.matcher(xmlString);
|
|
||||||
commentMatch.region(matchStart, xmlString.length());
|
|
||||||
if (commentMatch.lookingAt()) {
|
|
||||||
attrs.put("value", commentMatch.group(1).trim());
|
|
||||||
return new XMLFragment("", FragmentType.COMMENT, attrs, matchStart, commentMatch.end());
|
|
||||||
}
|
|
||||||
|
|
||||||
Matcher beginMatch = TAG_BEGIN.matcher(xmlString);
|
|
||||||
beginMatch.region(matchStart, xmlString.length());
|
|
||||||
if (!beginMatch.lookingAt()) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
int matchEndPrev = beginMatch.end();
|
|
||||||
|
|
||||||
String modifiers = beginMatch.group(1);
|
|
||||||
String name = beginMatch.group(2);
|
|
||||||
boolean endTag = "/".equals(modifiers);
|
|
||||||
boolean declarationStart = "?".equals(modifiers);
|
|
||||||
boolean doctype = "!".equals(modifiers) && "DOCTYPE".equals(name);
|
|
||||||
|
|
||||||
if (doctype) {
|
|
||||||
int partNo = 0;
|
|
||||||
while (true) {
|
|
||||||
Matcher attrMatch = DOCTYPE_PART.matcher(xmlString);
|
|
||||||
attrMatch.region(matchEndPrev, xmlString.length());
|
|
||||||
if (!attrMatch.lookingAt()) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
matchEndPrev = attrMatch.end();
|
|
||||||
|
|
||||||
String partValue = attrMatch.group(1);
|
|
||||||
if (partValue.startsWith("\"") || partValue.startsWith("'")) {
|
|
||||||
partValue = partValue.substring(1, partValue.length() - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
String partId = String.format("doctype %02d", partNo++);
|
|
||||||
attrs.put(partId, partValue);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
while (true) {
|
|
||||||
Matcher attrMatch = TAG_ATTRIBUTE.matcher(xmlString);
|
|
||||||
attrMatch.region(matchEndPrev, xmlString.length());
|
|
||||||
if (!attrMatch.lookingAt()) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
matchEndPrev = attrMatch.end();
|
|
||||||
|
|
||||||
String attrName = attrMatch.group(1);
|
|
||||||
String attrValue = attrMatch.group(2);
|
|
||||||
attrValue = attrValue.substring(1, attrValue.length() - 1);
|
|
||||||
attrs.put(attrName, attrValue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Matcher endMatch = TAG_END.matcher(xmlString);
|
|
||||||
endMatch.region(matchEndPrev, xmlString.length());
|
|
||||||
if (!endMatch.lookingAt()) {
|
|
||||||
throw new AssertionError(String.format("No tag end found: %s", xmlString.substring(0, matchEndPrev)));
|
|
||||||
}
|
|
||||||
matchEndPrev = endMatch.end();
|
|
||||||
|
|
||||||
modifiers = endMatch.group(1);
|
|
||||||
boolean emptyElement = "/".equals(modifiers);
|
|
||||||
boolean declarationEnd = "?".equals(modifiers);
|
|
||||||
|
|
||||||
FragmentType type = FragmentType.START_TAG;
|
|
||||||
if (endTag) {
|
|
||||||
type = FragmentType.END_TAG;
|
|
||||||
} else if (emptyElement) {
|
|
||||||
type = FragmentType.EMPTY_ELEMENT;
|
|
||||||
} else if (declarationStart && declarationEnd) {
|
|
||||||
type = FragmentType.DECLARATION;
|
|
||||||
} else if (doctype) {
|
|
||||||
type = FragmentType.DOCTYPE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new XMLFragment(name, type, attrs, matchStart, matchEndPrev);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
if (!(o instanceof XMLFragment)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
XMLFragment frag = (XMLFragment) o;
|
|
||||||
if (!type.equals(frag.type) || !name.equals(frag.name)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
Iterator<Map.Entry<String, String>> itThis = attributes.entrySet().iterator();
|
|
||||||
Iterator<Map.Entry<String, String>> itFrag = frag.attributes.entrySet().iterator();
|
|
||||||
while (itThis.hasNext() && itFrag.hasNext()) {
|
|
||||||
Map.Entry<String, String> attrThis = itThis.next();
|
|
||||||
Map.Entry<String, String> attrFrag = itFrag.next();
|
|
||||||
if (!attrThis.getKey().equals(attrFrag.getKey()) ||
|
|
||||||
!attrThis.getValue().equals(attrFrag.getValue())) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return type.hashCode() ^ attributes.hashCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
StringBuilder s = new StringBuilder("<");
|
|
||||||
if (FragmentType.END_TAG.equals(type)) {
|
|
||||||
s.append("/");
|
|
||||||
} else if (FragmentType.DECLARATION.equals(type)) {
|
|
||||||
s.append("?");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (FragmentType.DOCTYPE.equals(type)) {
|
|
||||||
s.append("!").append(name);
|
|
||||||
for (String partValue : attributes.values()) {
|
|
||||||
s.append(" ").append(partValue);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
s.append(name);
|
|
||||||
for (Map.Entry<String, String> attr : attributes.entrySet()) {
|
|
||||||
s.append(" ").append(attr.getKey()).append("=\"").append(attr.getValue()).append("\"");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (FragmentType.DECLARATION.equals(type)) {
|
|
||||||
s.append("?");
|
|
||||||
}
|
|
||||||
s.append(">");
|
|
||||||
return s.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum FragmentType {
|
|
||||||
START_TAG, END_TAG, EMPTY_ELEMENT, CDATA,
|
|
||||||
DECLARATION, DOCTYPE, COMMENT
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -3,8 +3,13 @@ package org.xbib.graphics.io.vector;
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.xbib.graphics.io.vector.TestUtils.XMLFragment;
|
import java.util.Collections;
|
||||||
|
import java.util.IdentityHashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.TreeMap;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
public class TestUtilsTest {
|
public class TestUtilsTest {
|
||||||
|
|
||||||
|
@ -186,4 +191,188 @@ public class TestUtilsTest {
|
||||||
assertEquals(0, frag.matchStart);
|
assertEquals(0, frag.matchStart);
|
||||||
assertEquals(xmlString.length(), frag.matchEnd);
|
assertEquals(xmlString.length(), frag.matchEnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static class XMLFragment {
|
||||||
|
|
||||||
|
private static final Pattern CDATA = Pattern.compile("\\s*<!\\[CDATA\\[(.*?)\\]\\]>");
|
||||||
|
|
||||||
|
private static final Pattern COMMENT = Pattern.compile("\\s*<!--(.*?)-->");
|
||||||
|
|
||||||
|
private static final Pattern TAG_BEGIN = Pattern.compile("\\s*<(/|\\?|!)?\\s*([^\\s>/\\?]+)");
|
||||||
|
|
||||||
|
private static final Pattern TAG_END = Pattern.compile("\\s*(/|\\?)?>");
|
||||||
|
|
||||||
|
private static final Pattern TAG_ATTRIBUTE = Pattern.compile("\\s*([^\\s>=]+)=(\"[^\"]*\"|'[^']*')");
|
||||||
|
|
||||||
|
private static final Pattern DOCTYPE_PART = Pattern.compile("\\s*(\"[^\"]*\"|'[^']*'|[^\\s>]+)");
|
||||||
|
|
||||||
|
public final String name;
|
||||||
|
|
||||||
|
public final FragmentType type;
|
||||||
|
|
||||||
|
public final Map<String, String> attributes;
|
||||||
|
|
||||||
|
public final int matchStart;
|
||||||
|
|
||||||
|
public final int matchEnd;
|
||||||
|
|
||||||
|
public XMLFragment(String name, FragmentType type, Map<String, String> attributes,
|
||||||
|
int matchStart, int matchEnd) {
|
||||||
|
this.name = name;
|
||||||
|
this.type = type;
|
||||||
|
this.attributes = Collections.unmodifiableMap(
|
||||||
|
new TreeMap<String, String>(attributes));
|
||||||
|
this.matchStart = matchStart;
|
||||||
|
this.matchEnd = matchEnd;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static XMLFragment parse(String xmlString, int matchStart) {
|
||||||
|
Map<String, String> attrs = new IdentityHashMap<String, String>();
|
||||||
|
|
||||||
|
Matcher cdataMatch = CDATA.matcher(xmlString);
|
||||||
|
cdataMatch.region(matchStart, xmlString.length());
|
||||||
|
if (cdataMatch.lookingAt()) {
|
||||||
|
attrs.put("value", cdataMatch.group(1));
|
||||||
|
return new XMLFragment("", FragmentType.CDATA, attrs, matchStart, cdataMatch.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
Matcher commentMatch = COMMENT.matcher(xmlString);
|
||||||
|
commentMatch.region(matchStart, xmlString.length());
|
||||||
|
if (commentMatch.lookingAt()) {
|
||||||
|
attrs.put("value", commentMatch.group(1).trim());
|
||||||
|
return new XMLFragment("", FragmentType.COMMENT, attrs, matchStart, commentMatch.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
Matcher beginMatch = TAG_BEGIN.matcher(xmlString);
|
||||||
|
beginMatch.region(matchStart, xmlString.length());
|
||||||
|
if (!beginMatch.lookingAt()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
int matchEndPrev = beginMatch.end();
|
||||||
|
|
||||||
|
String modifiers = beginMatch.group(1);
|
||||||
|
String name = beginMatch.group(2);
|
||||||
|
boolean endTag = "/".equals(modifiers);
|
||||||
|
boolean declarationStart = "?".equals(modifiers);
|
||||||
|
boolean doctype = "!".equals(modifiers) && "DOCTYPE".equals(name);
|
||||||
|
|
||||||
|
if (doctype) {
|
||||||
|
int partNo = 0;
|
||||||
|
while (true) {
|
||||||
|
Matcher attrMatch = DOCTYPE_PART.matcher(xmlString);
|
||||||
|
attrMatch.region(matchEndPrev, xmlString.length());
|
||||||
|
if (!attrMatch.lookingAt()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
matchEndPrev = attrMatch.end();
|
||||||
|
|
||||||
|
String partValue = attrMatch.group(1);
|
||||||
|
if (partValue.startsWith("\"") || partValue.startsWith("'")) {
|
||||||
|
partValue = partValue.substring(1, partValue.length() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
String partId = String.format("doctype %02d", partNo++);
|
||||||
|
attrs.put(partId, partValue);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
while (true) {
|
||||||
|
Matcher attrMatch = TAG_ATTRIBUTE.matcher(xmlString);
|
||||||
|
attrMatch.region(matchEndPrev, xmlString.length());
|
||||||
|
if (!attrMatch.lookingAt()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
matchEndPrev = attrMatch.end();
|
||||||
|
|
||||||
|
String attrName = attrMatch.group(1);
|
||||||
|
String attrValue = attrMatch.group(2);
|
||||||
|
attrValue = attrValue.substring(1, attrValue.length() - 1);
|
||||||
|
attrs.put(attrName, attrValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Matcher endMatch = TAG_END.matcher(xmlString);
|
||||||
|
endMatch.region(matchEndPrev, xmlString.length());
|
||||||
|
if (!endMatch.lookingAt()) {
|
||||||
|
throw new AssertionError(String.format("No tag end found: %s", xmlString.substring(0, matchEndPrev)));
|
||||||
|
}
|
||||||
|
matchEndPrev = endMatch.end();
|
||||||
|
|
||||||
|
modifiers = endMatch.group(1);
|
||||||
|
boolean emptyElement = "/".equals(modifiers);
|
||||||
|
boolean declarationEnd = "?".equals(modifiers);
|
||||||
|
|
||||||
|
FragmentType type = FragmentType.START_TAG;
|
||||||
|
if (endTag) {
|
||||||
|
type = FragmentType.END_TAG;
|
||||||
|
} else if (emptyElement) {
|
||||||
|
type = FragmentType.EMPTY_ELEMENT;
|
||||||
|
} else if (declarationStart && declarationEnd) {
|
||||||
|
type = FragmentType.DECLARATION;
|
||||||
|
} else if (doctype) {
|
||||||
|
type = FragmentType.DOCTYPE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new XMLFragment(name, type, attrs, matchStart, matchEndPrev);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (!(o instanceof XMLFragment)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
XMLFragment frag = (XMLFragment) o;
|
||||||
|
if (!type.equals(frag.type) || !name.equals(frag.name)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Iterator<Map.Entry<String, String>> itThis = attributes.entrySet().iterator();
|
||||||
|
Iterator<Map.Entry<String, String>> itFrag = frag.attributes.entrySet().iterator();
|
||||||
|
while (itThis.hasNext() && itFrag.hasNext()) {
|
||||||
|
Map.Entry<String, String> attrThis = itThis.next();
|
||||||
|
Map.Entry<String, String> attrFrag = itFrag.next();
|
||||||
|
if (!attrThis.getKey().equals(attrFrag.getKey()) ||
|
||||||
|
!attrThis.getValue().equals(attrFrag.getValue())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return type.hashCode() ^ attributes.hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
StringBuilder s = new StringBuilder("<");
|
||||||
|
if (FragmentType.END_TAG.equals(type)) {
|
||||||
|
s.append("/");
|
||||||
|
} else if (FragmentType.DECLARATION.equals(type)) {
|
||||||
|
s.append("?");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FragmentType.DOCTYPE.equals(type)) {
|
||||||
|
s.append("!").append(name);
|
||||||
|
for (String partValue : attributes.values()) {
|
||||||
|
s.append(" ").append(partValue);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
s.append(name);
|
||||||
|
for (Map.Entry<String, String> attr : attributes.entrySet()) {
|
||||||
|
s.append(" ").append(attr.getKey()).append("=\"").append(attr.getValue()).append("\"");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (FragmentType.DECLARATION.equals(type)) {
|
||||||
|
s.append("?");
|
||||||
|
}
|
||||||
|
s.append(">");
|
||||||
|
return s.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum FragmentType {
|
||||||
|
START_TAG, END_TAG, EMPTY_ELEMENT, CDATA,
|
||||||
|
DECLARATION, DOCTYPE, COMMENT
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,8 +4,8 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
import static org.xbib.graphics.io.vector.VectorGraphics2D.hasAlpha;
|
import static org.xbib.graphics.io.vector.util.ImageUtil.hasAlpha;
|
||||||
import static org.xbib.graphics.io.vector.VectorGraphics2D.toBufferedImage;
|
import static org.xbib.graphics.io.vector.util.ImageUtil.toBufferedImage;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.xbib.graphics.io.vector.commands.CreateCommand;
|
import org.xbib.graphics.io.vector.commands.CreateCommand;
|
||||||
import org.xbib.graphics.io.vector.commands.DisposeCommand;
|
import org.xbib.graphics.io.vector.commands.DisposeCommand;
|
||||||
|
@ -62,7 +62,6 @@ public class VectorGraphics2DTest {
|
||||||
assertEquals(Color.BLUE, ((DisposeCommand) lastCommand).getValue().getColor());
|
assertEquals(Color.BLUE, ((DisposeCommand) lastCommand).getValue().getColor());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testToBufferedImage() {
|
public void testToBufferedImage() {
|
||||||
Image[] images = {
|
Image[] images = {
|
||||||
|
@ -78,7 +77,6 @@ public class VectorGraphics2DTest {
|
||||||
}
|
}
|
||||||
))
|
))
|
||||||
};
|
};
|
||||||
|
|
||||||
for (Image image : images) {
|
for (Image image : images) {
|
||||||
BufferedImage bimage = toBufferedImage(image);
|
BufferedImage bimage = toBufferedImage(image);
|
||||||
assertNotNull(bimage);
|
assertNotNull(bimage);
|
||||||
|
@ -90,11 +88,9 @@ public class VectorGraphics2DTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testHasAlpha() {
|
public void testHasAlpha() {
|
||||||
Image image;
|
Image image = new BufferedImage(320, 240, BufferedImage.TYPE_INT_ARGB);
|
||||||
image = new BufferedImage(320, 240, BufferedImage.TYPE_INT_ARGB);
|
|
||||||
assertTrue(hasAlpha(image));
|
assertTrue(hasAlpha(image));
|
||||||
image = new BufferedImage(320, 240, BufferedImage.TYPE_INT_RGB);
|
image = new BufferedImage(320, 240, BufferedImage.TYPE_INT_RGB);
|
||||||
assertFalse(hasAlpha(image));
|
assertFalse(hasAlpha(image));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue