Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.hwmf.record;
import java.awt.Shape;
import java.awt.geom.Arc2D;
import java.awt.geom.Area;
import java.awt.geom.Dimension2D;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.awt.geom.Path2D;
import java.awt.geom.PathIterator;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.awt.geom.RoundRectangle2D;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.apache.poi.hwmf.draw.HwmfGraphics;
import org.apache.poi.hwmf.draw.HwmfGraphics.FillDrawStyle;
import org.apache.poi.util.Internal;
import org.apache.poi.util.LittleEndianConsts;
import org.apache.poi.util.LittleEndianInputStream;
public class HwmfDraw {
/**
* The META_MOVETO record sets the output position in the playback device context to a specified
* point.
*/
public static class WmfMoveTo implements HwmfRecord {
protected final Point2D point = new Point2D.Double();
@Override
public HwmfRecordType getWmfRecordType() {
return HwmfRecordType.moveTo;
}
@Override
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
return readPointS(leis, point);
}
@Override
public void draw(HwmfGraphics ctx) {
ctx.getProperties().setLocation(point);
}
@Override
public String toString() {
return pointToString(point);
}
}
/**
* The META_LINETO record draws a line from the drawing position that is defined in the playback
* device context up to, but not including, the specified point.
*/
public static class WmfLineTo implements HwmfRecord {
protected final Point2D point = new Point2D.Double();
@Override
public HwmfRecordType getWmfRecordType() {
return HwmfRecordType.lineTo;
}
@Override
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
return readPointS(leis, point);
}
@Override
public void draw(HwmfGraphics ctx) {
Point2D start = ctx.getProperties().getLocation();
Line2D line = new Line2D.Double(start, point);
ctx.draw(line);
ctx.getProperties().setLocation(point);
}
@Override
public String toString() {
return pointToString(point);
}
}
/**
* The META_POLYGON record paints a polygon consisting of two or more vertices connected by
* straight lines. The polygon is outlined by using the pen and filled by using the brush and polygon fill
* mode that are defined in the playback device context.
*/
public static class WmfPolygon implements HwmfRecord {
protected Path2D poly;
@Override
public HwmfRecordType getWmfRecordType() {
return HwmfRecordType.polygon;
}
@Override
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
/**
* A 16-bit signed integer that defines the number of points in the array.
*/
int numberofPoints = leis.readShort();
poly = new Path2D.Double(Path2D.WIND_EVEN_ODD, numberofPoints);
for (int i=0; i polyList = new ArrayList<>();
@Override
public HwmfRecordType getWmfRecordType() {
return HwmfRecordType.polyPolygon;
}
@Override
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
// see http://secunia.com/gfx/pdf/SA31675_BA.pdf ;)
/**
* A 16-bit unsigned integer that defines the number of polygons in the object.
*/
int numberOfPolygons = leis.readUShort();
/**
* A NumberOfPolygons array of 16-bit unsigned integers that define the number of
* points for each polygon in the object.
*/
int[] pointsPerPolygon = new int[numberOfPolygons];
int size = LittleEndianConsts.SHORT_SIZE;
for (int i=0; i 0 ? 0 : 360);
if (startAngle < 0) {
startAngle += 360;
}
boolean fillShape;
int arcClosure;
switch (getWmfRecordType()) {
default:
case arc:
arcClosure = Arc2D.OPEN;
break;
case chord:
arcClosure = Arc2D.CHORD;
break;
case pie:
arcClosure = Arc2D.PIE;
break;
}
return new Arc2D.Double(bounds.getX(), bounds.getY(), bounds.getWidth(), bounds.getHeight(), startAngle, arcAngle, arcClosure);
}
@Override
public String toString() {
Arc2D arc = getShape();
return
"{ startPoint: "+pointToString(startPoint)+
", endPoint: "+pointToString(endPoint)+
", startAngle: "+arc.getAngleStart()+
", extentAngle: "+arc.getAngleExtent()+
", bounds: "+boundsToString(bounds)+
" }";
}
}
/**
* The META_PIE record draws a pie-shaped wedge bounded by the intersection of an ellipse and two
* radials. The pie is outlined by using the pen and filled by using the brush that are defined in the
* playback device context.
*/
public static class WmfPie extends WmfArc {
@Override
public HwmfRecordType getWmfRecordType() {
return HwmfRecordType.pie;
}
}
/**
* The META_CHORD record draws a chord, which is defined by a region bounded by the intersection of
* an ellipse with a line segment. The chord is outlined using the pen and filled using the brush
* that are defined in the playback device context.
*/
public static class WmfChord extends WmfArc {
@Override
public HwmfRecordType getWmfRecordType() {
return HwmfRecordType.chord;
}
}
/**
* The META_SELECTOBJECT record specifies a graphics object for the playback device context. The
* new object replaces the previous object of the same type, unless if the previous object is a palette
* object. If the previous object is a palette object, then the META_SELECTPALETTE record must be
* used instead of the META_SELECTOBJECT record, as the META_SELECTOBJECT record does not
* support replacing the palette object type.
*/
public static class WmfSelectObject implements HwmfRecord {
/**
* A 16-bit unsigned integer used to index into the WMF Object Table to
* get the object to be selected.
*/
protected int objectIndex;
@Override
public HwmfRecordType getWmfRecordType() {
return HwmfRecordType.selectObject;
}
@Override
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
objectIndex = leis.readUShort();
return LittleEndianConsts.SHORT_SIZE;
}
@Override
public void draw(HwmfGraphics ctx) {
ctx.applyObjectTableEntry(objectIndex);
}
@Override
public String toString() {
return "{ index: "+objectIndex +" }";
}
}
static int readBounds(LittleEndianInputStream leis, Rectangle2D bounds) {
/**
* The 16-bit signed integers that defines the corners of the bounding rectangle.
*/
int bottom = leis.readShort();
int right = leis.readShort();
int top = leis.readShort();
int left = leis.readShort();
int x = Math.min(left, right);
int y = Math.min(top, bottom);
int w = Math.abs(left - right - 1);
int h = Math.abs(top - bottom - 1);
bounds.setRect(x, y, w, h);
return 4 * LittleEndianConsts.SHORT_SIZE;
}
static int readRectS(LittleEndianInputStream leis, Rectangle2D bounds) {
/**
* The 16-bit signed integers that defines the corners of the bounding rectangle.
*/
int left = leis.readShort();
int top = leis.readShort();
int right = leis.readShort();
int bottom = leis.readShort();
int x = Math.min(left, right);
int y = Math.min(top, bottom);
int w = Math.abs(left - right - 1);
int h = Math.abs(top - bottom - 1);
bounds.setRect(x, y, w, h);
return 4 * LittleEndianConsts.SHORT_SIZE;
}
static int readPointS(LittleEndianInputStream leis, Point2D point) {
/** a signed integer that defines the x/y-coordinate, in logical units. */
int y = leis.readShort();
int x = leis.readShort();
point.setLocation(x, y);
return 2*LittleEndianConsts.SHORT_SIZE;
}
static String polyToString(Path2D poly) {
StringBuilder sb = new StringBuilder();
sb.append("[");
final PathIterator iter = poly.getPathIterator(null);
double[] pnts = new double[6];
while (!iter.isDone()) {
int segType = iter.currentSegment(pnts);
switch (segType) {
case PathIterator.SEG_MOVETO:
sb.append("{ type: 'move', x: "+pnts[0]+", y: "+pnts[1]+" }, ");
break;
case PathIterator.SEG_LINETO:
sb.append("{ type: 'lineto', x: "+pnts[0]+", y: "+pnts[1]+" }, ");
break;
case PathIterator.SEG_QUADTO:
sb.append("{ type: 'quad', x1: "+pnts[0]+", y1: "+pnts[1]+", x2: "+pnts[2]+", y2: "+pnts[3]+" }, ");
break;
case PathIterator.SEG_CUBICTO:
sb.append("{ type: 'cubic', x1: "+pnts[0]+", y1: "+pnts[1]+", x2: "+pnts[2]+", y2: "+pnts[3]+", x3: "+pnts[4]+", y3: "+pnts[5]+" }, ");
break;
case PathIterator.SEG_CLOSE:
sb.append("{ type: 'close' }, ");
break;
}
iter.next();
}
sb.append("]");
return sb.toString();
}
@Internal
public static String pointToString(Point2D point) {
return "{ x: "+point.getX()+", y: "+point.getY()+" }";
}
@Internal
public static String boundsToString(Rectangle2D bounds) {
return "{ x: "+bounds.getX()+", y: "+bounds.getY()+", w: "+bounds.getWidth()+", h: "+bounds.getHeight()+" }";
}
@Internal
public static String dimToString(Dimension2D dim) {
return "{ w: "+dim.getWidth()+", h: "+dim.getHeight()+" }";
}
@Internal
public static Rectangle2D normalizeBounds(Rectangle2D bounds) {
return (bounds.getWidth() >= 0 && bounds.getHeight() >= 0) ? bounds
: new Rectangle2D.Double(
bounds.getWidth() >= 0 ? bounds.getMinX() : bounds.getMaxX(),
bounds.getHeight() >= 0 ? bounds.getMinY() : bounds.getMaxY(),
Math.abs(bounds.getWidth()),
Math.abs(bounds.getHeight())
);
}
}