sventon subversion web client - http://www.sventon.org
[show recent changes]
 
  Help
HEAD
Rev: 10305 - svn://svn.freehep.org/svn / freehep / branches / vectorgraphics-emfplus / freehep-graphicsio-emf / src / main / java / org / freehep / graphicsio / emf / gdiplus / GDIPlusObject.java
Unified Diff View - GDIPlusObject.java
Search for Help
/freehep/branches/vectorgraphics-emfplus/freehep-graphicsio-emf/src/main/java/org/freehep/graphicsio/emf/gdiplus/GDIPlusObject.java @ revision 10304
/freehep/branches/vectorgraphics-emfplus/freehep-graphicsio-emf/src/main/java/org/freehep/graphicsio/emf/gdiplus/GDIPlusObject.java @ revision 10305
@@ -1,14 +1,21 @@ // Copyright 2006, FreeHEP. package org.freehep.graphicsio.emf.gdiplus; -import java.awt.Shape; +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.GradientPaint; import java.awt.Paint; -import java.awt.geom.PathIterator; +import java.awt.Shape; +import java.awt.Stroke; +import java.awt.TexturePaint; +import java.awt.geom.AffineTransform; +import java.awt.image.RenderedImage; import java.io.IOException; +import java.util.Properties; +import org.freehep.graphicsio.ImageGraphics2D; import org.freehep.graphicsio.emf.EMFInputStream; import org.freehep.graphicsio.emf.EMFOutputStream; -import org.freehep.graphicsio.emf.EMFTag; /**  * The Object metafile record contains information on an object @@ -30,86 +37,303 @@  * and applications will have to be prepared for new Object records  * overwriting old ones with the same index.  * + * FIXME: no support for 16 bit + *  * @author Mark Donszelmann  * @version $Id$  */ public class GDIPlusObject extends EMFPlusTag { - private final static int INVALID = 0x000; - private final static int BRUSH = 0x100; - private final static int PEN = 0x200; - private final static int PATH = 0x300; - private final static int REGION = 0x400; - private final static int IMAGE = 0x500; - private final static int FONT = 0x600; - private final static int STRING_FORMAT = 0x700; - private final static int IMAGE_ATTRIBUTES = 0x800; - private final static int CUSTOM_LINE_CAP = 0x900; + protected final static int INVALID = 0x000; +    protected final static int BRUSH = 0x100; +    protected final static int PEN = 0x200; +    protected final static int PATH = 0x300; +    protected final static int REGION = 0x400; +    protected final static int IMAGE = 0x500; +    protected final static int FONT = 0x600; +    protected final static int STRING_FORMAT = 0x700; +    protected final static int IMAGE_ATTRIBUTES = 0x800; +    protected final static int CUSTOM_LINE_CAP = 0x900; +    protected final static int BRUSH_TYPE_SOLID_COLOR = 0; +    protected final static int BRUSH_TYPE_HATCH_FILL = 1; +    protected final static int BRUSH_TYPE_TEXTURE_GRADIENT = 2; +    protected final static int BRUSH_TYPE_PATH_GRADIENT = 3; +    protected final static int BRUSH_TYPE_LINEAR_GRADIENT = 4; + +    protected final static int WRAP_MODE_TYLE = 0; +    protected final static int WRAP_MODE_TYLE_FLIP_X = 1; +    protected final static int WRAP_MODE_TYLE_FLIP_Y = 2; +    protected final static int WRAP_MODE_TYLE_FLIP_XY = 3; +    protected final static int WRAP_MODE_CLAMP = 4; + +    protected final static int IMAGE_TYPE_UNKNOWN = 0; +    protected final static int IMAGE_TYPE_BITMAP = 1; +    protected final static int IMAGE_TYPE_METAFILE = 2; + +    protected final static int FILL_MODE_ALTERNATE = 0x0000; +    protected final static int FILL_MODE_WINDING = 0x2000; +  private Paint brush; - private Shape shape; - +    private BasicStroke stroke; +    private PathPoint[] path; +    private int pathFillMode; +    private RenderedImage image; +  public GDIPlusObject() { -  this(8,1); - } - - public GDIPlusObject(int index, Shape shape) { -  this(); -  this.shape = shape; -  flags = index | PATH; +  super(8,1);  } - public GDIPlusObject(int index, Paint brush) { +    public GDIPlusObject(int index, Paint brush) { +        this(); +        this.brush = brush; +        flags = index | BRUSH; +    } + +    public GDIPlusObject(int index, Stroke stroke, Paint brush) { +        this(); +        if (!(stroke instanceof BasicStroke)) throw new IllegalArgumentException(getClass()+": can only handle Stroke of class BasicStroke"); +        this.stroke = (BasicStroke)stroke; +        this.brush = brush; +        flags = index | PEN; +    } + + public GDIPlusObject(int index, Shape shape, boolean windingFill) {   this(); -  this.brush = brush; -  flags = index | BRUSH; +        try { +            EMFPlusPathConstructor p = new EMFPlusPathConstructor(); +            p.reset(); +            p.addPath(shape); +            path = p.getPath(); +            flags = index | PATH; +            pathFillMode = windingFill ? FILL_MODE_WINDING : FILL_MODE_ALTERNATE; +        } catch (IOException e) { +            // ignored +        }  } - @Override +    public GDIPlusObject(int index, RenderedImage image) { +        this(); +        this.image = image; +        flags = index | IMAGE; +    } +  public EMFPlusTag read(int tagID, int flags, EMFInputStream emf, int len)    throws IOException {   GDIPlusObject tag = new GDIPlusObject(); -  int type = flags & 0x0000FF00; +        tag.flags = flags; +        int type = flags & 0x0000FF00; +        // FIXME some missing   switch(type) {    case BRUSH: -    break; +       tag.brush = readBrush(emf); +                break; +            case PEN: +                emf.readUINT(); // magic word +                emf.readUINT(); // unknown +                emf.readUINT(); // additional flags, NOTE no join, endcap, miterlimit etc. +                emf.readUINT(); // unknown +                float lineWidth = emf.readFLOAT(); +                tag.stroke = new BasicStroke(lineWidth); +                tag.brush = readBrush(emf); +                break;    case PATH: -    break; +                emf.readUINT(); // magic word +                tag.path = new PathPoint[emf.readUINT()]; +                int moreFlags = emf.readUINT(); +                pathFillMode = moreFlags & 0x2000; +                for (int i=0; i<tag.path.length; i++) { +                    tag.path[i] = new PathPoint(); +                    tag.path[i].setX(emf.readFLOAT()); +                    tag.path[i].setY(emf.readFLOAT()); +                } +                for (int i=0; i<tag.path.length; i++) { +                    tag.path[i].setType(emf.readUnsignedByte()); +                } +                if (tag.path.length%4 > 0) { +                    for (int i=4-(tag.path.length%4); i>0; i--) { +                        emf.readBYTE(); +                    } +                } +                break;    case INVALID:    default: +                System.err.println ("GDIObject: Invalid TYPE: "+Integer.toHexString(type));     break;   }   return tag;  } - @Override - public void write(int tagID, EMFOutputStream emf) throws IOException { + public void write(int tagID, int flags, EMFOutputStream emf) throws IOException {   int type = flags & 0x0000FF00;   switch(type) {    case BRUSH: +                writeBrush(emf, brush);     break; +            case PEN: +                emf.writeUINT(0xDBC01001); +                emf.writeUINT(0x0000); // unknown +                emf.writeUINT(0x0000); // additional flags, NOTE no join, endcap, miterlimit etc. +                emf.writeUINT(0x0000); // unknown +                emf.writeFLOAT(stroke.getLineWidth()); +                writeBrush(emf, brush); +                break;    case PATH: -    EMFPlusPathConstructor p = new EMFPlusPathConstructor(); -    p.addShape(); -    p.flush(); -    Path[] path = p.getPath(); +                emf.writeUINT(0xDBC01001);     emf.writeUINT(path.length); -    int mode = 0; // FIXME Winding Mode -    emf.writeUINT(mode); -    for (int i=0; i<path.legth; i++) { -     emf.writeUINT(path[i].getX()); -     emf.writeUINT(path[i].getY()); -    } +    emf.writeUINT(pathFillMode);     for (int i=0; i<path.length; i++) { -     emf.writeBYTE(path[i].getType()); +     emf.writeFLOAT(path[i].getX()); +     emf.writeFLOAT(path[i].getY());     } -    for (int i=path.length%4; i>0; i--) { -     emf.writeBYTE(0); +    for (int i=0; i<path.length; i++) { +     emf.writeUnsignedByte(path[i].getType());     } +                if (path.length%4 > 0) { +                    for (int i=4-(path.length%4); i>0; i--) { +                        emf.writeBYTE(0); +                    } +                }     break; +            case IMAGE: +                writeImage(emf, image); +                break;    case INVALID:    default:     break;   }  } + +    public String toString() { +        StringBuffer sb = new StringBuffer(super.toString()); +        sb.append("\n "); +        int type = flags & 0x0000FF00; +        switch(type) { +            case BRUSH: +                sb.append("brush: "+brush); +                break; +            case PEN: +                sb.append("stroke: "+stroke); +                sb.append("\n brush: "+brush); +                break; +            case PATH: +                sb.append("fillMode: "+pathFillMode); +                sb.append("\n n: "+path.length); +                for (int i=0; i<path.length; i++) { +                    sb.append("\n 0x"+Integer.toHexString(path[i].getType())+" ("+path[i].getX()+", "+path[i].getY()+")"); +                } +                break; +            default: +                sb.append("UNKNOWN"); +                break; +        } +        return sb.toString(); +    } + +    private Paint readBrush(EMFInputStream emf) throws IOException { +        emf.readUINT(); // magic word +        int brushType = emf.readUINT(); +        switch(brushType) { +            case BRUSH_TYPE_SOLID_COLOR: +                return emf.readCOLOR(); +            case BRUSH_TYPE_LINEAR_GRADIENT: +                emf.readUINT(); // special mode ignored +                // FIXME, rest to be done +                return null; +/* +            emf.writeUINT(paint.isCyclic() ? WRAP_MODE_TYLE_FLIP_XY : WRAP_MODE_CLAMP); // NOTE: check +            float x1 = (float)paint.getPoint1().getX(); +            float y1 = (float)paint.getPoint1().getY(); +            float x2 = (float)paint.getPoint2().getX(); +            float y2 = (float)paint.getPoint2().getY(); +            emf.writeFLOAT(Math.min(x1, x2)); +            emf.writeFLOAT(Math.min(y1, y2)); +            emf.writeFLOAT(Math.abs(x1-x2)); +            emf.writeFLOAT(Math.abs(y1-y2)); +            emf.writeCOLOR(paint.getColor1()); +            emf.writeCOLOR(paint.getColor2()); +            emf.writeCOLOR(paint.getColor1()); +            emf.writeCOLOR(paint.getColor2()); +        } else if (brush instanceof TexturePaint) { +// emf.writeUINT(BRUSH_TYPE_TEXTURE_GRADIENT); +//FIXME later when image is done +            emf.writeUINT(BRUSH_TYPE_SOLID_COLOR); +            emf.writeCOLOR(Color.BLACK); +        } else { +            System.err.println("No Brush for paint of class: "+brush.getClass()+" defaulting to black"); +            emf.writeUINT(BRUSH_TYPE_SOLID_COLOR); +            emf.writeCOLOR(Color.BLACK); +        } +*/ +        } +        return Color.BLACK; +    } + + +    private void writeBrush(EMFOutputStream emf, Paint brush) throws IOException { +        emf.writeUINT(0xDBC01001); +        if (brush instanceof Color) { +            emf.writeUINT(BRUSH_TYPE_SOLID_COLOR); +            emf.writeCOLOR((Color)brush); +        } else if (brush instanceof GradientPaint) { +            GradientPaint paint = (GradientPaint)brush; +            emf.writeUINT(BRUSH_TYPE_LINEAR_GRADIENT); +            emf.writeUINT(0x02); // write Matrix +            emf.writeUINT(paint.isCyclic() ? WRAP_MODE_TYLE_FLIP_XY : WRAP_MODE_TYLE_FLIP_Y); // NOTE: check +            float x1 = (float)paint.getPoint1().getX(); +            float y1 = (float)paint.getPoint1().getY(); +            float x2 = (float)paint.getPoint2().getX(); +            float y2 = (float)paint.getPoint2().getY(); +            emf.writeFLOAT(Math.min(x1, x2)); +            emf.writeFLOAT(Math.min(y1, y2)); +            emf.writeFLOAT(Math.abs(x1-x2)); +            emf.writeFLOAT(Math.abs(y1-y2)); +            emf.writeCOLOR(paint.getColor1()); +            emf.writeCOLOR(paint.getColor2()); +            emf.writeCOLOR(paint.getColor1()); +            emf.writeCOLOR(paint.getColor2()); +            float dx = x2 - x1; +            float dy = y2 - y1; +            float scale = (float)paint.getPoint1().distance(paint.getPoint2())/dx; +            System.err.println(paint.getPoint1()+" "+paint.getPoint2()); +            System.err.println(x1+" "+x2+" " +y1+" "+y2+":"+dx+" "+dy+" "+scale); +            float angle = (float)Math.atan2(dy, dx); +            AffineTransform transform = new AffineTransform(scale, 0, 0, scale, dx +                    / 2 + x1, dy / 2 + y1); +            transform = new AffineTransform(); +            transform.scale(scale, scale); +            transform.rotate(angle); +            writeTransform(emf, transform); +        } else if (brush instanceof TexturePaint) { +            TexturePaint paint = (TexturePaint)brush; +            emf.writeUINT(BRUSH_TYPE_TEXTURE_GRADIENT); +            emf.writeUINT(0); // no special mode +            emf.writeUINT(WRAP_MODE_TYLE); +            writeImage(emf, paint.getImage()); +        } else { +            System.err.println("No Brush for paint of class: "+brush.getClass()+" defaulting to black"); +            emf.writeUINT(BRUSH_TYPE_SOLID_COLOR); +            emf.writeCOLOR(Color.BLACK); +        } +    } + +    public static void writeTransform(EMFOutputStream emf, AffineTransform transform) throws IOException { +        emf.writeFLOAT((float)transform.getScaleX()); +        emf.writeFLOAT((float)transform.getShearY()); +        emf.writeFLOAT((float)transform.getShearX()); +        emf.writeFLOAT((float)transform.getScaleY()); +        emf.writeFLOAT((float)transform.getTranslateX()); +        emf.writeFLOAT((float)transform.getTranslateY()); +    } + +    private void writeImage(EMFOutputStream emf, RenderedImage image) throws IOException { +        emf.writeUINT(0xDBC01001); +        emf.writeUINT(IMAGE_TYPE_BITMAP); +        emf.writeUINT(0); // width +        emf.writeUINT(0); // height +        emf.writeUINT(0); // stride +        emf.writeUINT(0); // pixelformat +        emf.writeUINT(0x000001); // 01 00 00 00 for non-native images +        ImageGraphics2D.writeImage(image, "png", new Properties(), emf); +    } }


feed icon

sventon 2.5.1