mirror of https://github.com/apache/poi.git
misc usermodel improvements in HSLF
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@645567 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
cbd9f621cc
commit
c1871175de
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,160 @@
|
|||
/* ====================================================================
|
||||
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.hslf.model;
|
||||
|
||||
import org.apache.poi.ddf.*;
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
|
||||
import java.awt.geom.Point2D;
|
||||
|
||||
/**
|
||||
* A simple closed polygon shape
|
||||
*
|
||||
* @author Yegor Kozlov
|
||||
*/
|
||||
public class Polygon extends AutoShape {
|
||||
/**
|
||||
* Create a Polygon object and initialize it from the supplied Record container.
|
||||
*
|
||||
* @param escherRecord <code>EscherSpContainer</code> container which holds information about this shape
|
||||
* @param parent the parent of the shape
|
||||
*/
|
||||
protected Polygon(EscherContainerRecord escherRecord, Shape parent){
|
||||
super(escherRecord, parent);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new Polygon. This constructor is used when a new shape is created.
|
||||
*
|
||||
* @param parent the parent of this Shape. For example, if this text box is a cell
|
||||
* in a table then the parent is Table.
|
||||
*/
|
||||
public Polygon(Shape parent){
|
||||
super(null, parent);
|
||||
_escherContainer = createSpContainer(ShapeTypes.NotPrimitive, parent instanceof ShapeGroup);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new Polygon. This constructor is used when a new shape is created.
|
||||
*
|
||||
*/
|
||||
public Polygon(){
|
||||
this(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the polygon vertices
|
||||
*
|
||||
* @param xPoints
|
||||
* @param yPoints
|
||||
*/
|
||||
public void setPoints(float[] xPoints, float[] yPoints)
|
||||
{
|
||||
float right = findBiggest(xPoints);
|
||||
float bottom = findBiggest(yPoints);
|
||||
float left = findSmallest(xPoints);
|
||||
float top = findSmallest(yPoints);
|
||||
|
||||
EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
|
||||
opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.GEOMETRY__RIGHT, (int)((right - left)*POINT_DPI/MASTER_DPI)));
|
||||
opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.GEOMETRY__BOTTOM, (int)((bottom - top)*POINT_DPI/MASTER_DPI)));
|
||||
|
||||
for (int i = 0; i < xPoints.length; i++) {
|
||||
xPoints[i] += -left;
|
||||
yPoints[i] += -top;
|
||||
}
|
||||
|
||||
int numpoints = xPoints.length;
|
||||
|
||||
EscherArrayProperty verticesProp = new EscherArrayProperty(EscherProperties.GEOMETRY__VERTICES, false, new byte[0] );
|
||||
verticesProp.setNumberOfElementsInArray(numpoints+1);
|
||||
verticesProp.setNumberOfElementsInMemory(numpoints+1);
|
||||
verticesProp.setSizeOfElements(0xFFF0);
|
||||
for (int i = 0; i < numpoints; i++)
|
||||
{
|
||||
byte[] data = new byte[4];
|
||||
LittleEndian.putShort(data, 0, (short)(xPoints[i]*POINT_DPI/MASTER_DPI));
|
||||
LittleEndian.putShort(data, 2, (short)(yPoints[i]*POINT_DPI/MASTER_DPI));
|
||||
verticesProp.setElement(i, data);
|
||||
}
|
||||
byte[] data = new byte[4];
|
||||
LittleEndian.putShort(data, 0, (short)(xPoints[0]*POINT_DPI/MASTER_DPI));
|
||||
LittleEndian.putShort(data, 2, (short)(yPoints[0]*POINT_DPI/MASTER_DPI));
|
||||
verticesProp.setElement(numpoints, data);
|
||||
opt.addEscherProperty(verticesProp);
|
||||
|
||||
EscherArrayProperty segmentsProp = new EscherArrayProperty(EscherProperties.GEOMETRY__SEGMENTINFO, false, null );
|
||||
segmentsProp.setSizeOfElements(0x0002);
|
||||
segmentsProp.setNumberOfElementsInArray(numpoints * 2 + 4);
|
||||
segmentsProp.setNumberOfElementsInMemory(numpoints * 2 + 4);
|
||||
segmentsProp.setElement(0, new byte[] { (byte)0x00, (byte)0x40 } );
|
||||
segmentsProp.setElement(1, new byte[] { (byte)0x00, (byte)0xAC } );
|
||||
for (int i = 0; i < numpoints; i++)
|
||||
{
|
||||
segmentsProp.setElement(2 + i * 2, new byte[] { (byte)0x01, (byte)0x00 } );
|
||||
segmentsProp.setElement(3 + i * 2, new byte[] { (byte)0x00, (byte)0xAC } );
|
||||
}
|
||||
segmentsProp.setElement(segmentsProp.getNumberOfElementsInArray() - 2, new byte[] { (byte)0x01, (byte)0x60 } );
|
||||
segmentsProp.setElement(segmentsProp.getNumberOfElementsInArray() - 1, new byte[] { (byte)0x00, (byte)0x80 } );
|
||||
opt.addEscherProperty(segmentsProp);
|
||||
|
||||
opt.sortProperties();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the polygon vertices
|
||||
*
|
||||
* @param points the polygon vertices
|
||||
*/
|
||||
public void setPoints(Point2D[] points)
|
||||
{
|
||||
float[] xpoints = new float[points.length];
|
||||
float[] ypoints = new float[points.length];
|
||||
for (int i = 0; i < points.length; i++) {
|
||||
xpoints[i] = (float)points[i].getX();
|
||||
ypoints[i] = (float)points[i].getY();
|
||||
|
||||
}
|
||||
|
||||
setPoints(xpoints, ypoints);
|
||||
}
|
||||
|
||||
private float findBiggest( float[] values )
|
||||
{
|
||||
float result = Float.MIN_VALUE;
|
||||
for ( int i = 0; i < values.length; i++ )
|
||||
{
|
||||
if (values[i] > result)
|
||||
result = values[i];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private float findSmallest( float[] values )
|
||||
{
|
||||
float result = Float.MAX_VALUE;
|
||||
for ( int i = 0; i < values.length; i++ )
|
||||
{
|
||||
if (values[i] < result)
|
||||
result = values[i];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -24,6 +24,7 @@ import org.apache.poi.util.POILogFactory;
|
|||
|
||||
import java.util.Iterator;
|
||||
import java.awt.*;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
|
@ -143,24 +144,39 @@ public abstract class Shape {
|
|||
* @return the anchor of this shape
|
||||
*/
|
||||
public java.awt.Rectangle getAnchor(){
|
||||
Rectangle2D anchor2d = getAnchor2D();
|
||||
return anchor2d.getBounds();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the anchor (the bounding box rectangle) of this shape.
|
||||
* All coordinates are expressed in points (72 dpi).
|
||||
*
|
||||
* @return the anchor of this shape
|
||||
*/
|
||||
public Rectangle2D getAnchor2D(){
|
||||
EscherSpRecord spRecord = _escherContainer.getChildById(EscherSpRecord.RECORD_ID);
|
||||
int flags = spRecord.getFlags();
|
||||
java.awt.Rectangle anchor=null;
|
||||
Rectangle2D anchor=null;
|
||||
if ((flags & EscherSpRecord.FLAG_CHILD) != 0){
|
||||
EscherChildAnchorRecord rec = (EscherChildAnchorRecord)getEscherChild(_escherContainer, EscherChildAnchorRecord.RECORD_ID);
|
||||
anchor = new java.awt.Rectangle();
|
||||
anchor.x = rec.getDx1()*POINT_DPI/MASTER_DPI;
|
||||
anchor.y = rec.getDy1()*POINT_DPI/MASTER_DPI;
|
||||
anchor.width = rec.getDx2()*POINT_DPI/MASTER_DPI - anchor.x;
|
||||
anchor.height = rec.getDy2()*POINT_DPI/MASTER_DPI - anchor.y;
|
||||
anchor = new Rectangle2D.Float(
|
||||
(float)rec.getDx1()*POINT_DPI/MASTER_DPI,
|
||||
(float)rec.getDy1()*POINT_DPI/MASTER_DPI,
|
||||
(float)(rec.getDx2()-rec.getDx1())*POINT_DPI/MASTER_DPI,
|
||||
(float)(rec.getDy2()-rec.getDy1())*POINT_DPI/MASTER_DPI
|
||||
);
|
||||
}
|
||||
else {
|
||||
EscherClientAnchorRecord rec = (EscherClientAnchorRecord)getEscherChild(_escherContainer, EscherClientAnchorRecord.RECORD_ID);
|
||||
anchor = new java.awt.Rectangle();
|
||||
anchor.y = rec.getFlag()*POINT_DPI/MASTER_DPI;
|
||||
anchor.x = rec.getCol1()*POINT_DPI/MASTER_DPI;
|
||||
anchor.width = (rec.getDx1() - rec.getCol1())*POINT_DPI/MASTER_DPI;
|
||||
anchor.height = (rec.getRow1() - rec.getFlag())*POINT_DPI/MASTER_DPI;
|
||||
anchor = new Rectangle2D.Float(
|
||||
(float)rec.getCol1()*POINT_DPI/MASTER_DPI,
|
||||
(float)rec.getFlag()*POINT_DPI/MASTER_DPI,
|
||||
(float)(rec.getDx1()-rec.getCol1())*POINT_DPI/MASTER_DPI,
|
||||
(float)(rec.getRow1()-rec.getFlag())*POINT_DPI/MASTER_DPI
|
||||
);
|
||||
}
|
||||
return anchor;
|
||||
}
|
||||
|
@ -171,22 +187,22 @@ public abstract class Shape {
|
|||
*
|
||||
* @param anchor new anchor
|
||||
*/
|
||||
public void setAnchor(java.awt.Rectangle anchor){
|
||||
public void setAnchor(Rectangle2D anchor){
|
||||
EscherSpRecord spRecord = _escherContainer.getChildById(EscherSpRecord.RECORD_ID);
|
||||
int flags = spRecord.getFlags();
|
||||
if ((flags & EscherSpRecord.FLAG_CHILD) != 0){
|
||||
EscherChildAnchorRecord rec = (EscherChildAnchorRecord)getEscherChild(_escherContainer, EscherChildAnchorRecord.RECORD_ID);
|
||||
rec.setDx1(anchor.x*MASTER_DPI/POINT_DPI);
|
||||
rec.setDy1(anchor.y*MASTER_DPI/POINT_DPI);
|
||||
rec.setDx2((anchor.width + anchor.x)*MASTER_DPI/POINT_DPI);
|
||||
rec.setDy2((anchor.height + anchor.y)*MASTER_DPI/POINT_DPI);
|
||||
rec.setDx1((int)(anchor.getX()*MASTER_DPI/POINT_DPI));
|
||||
rec.setDy1((int)(anchor.getY()*MASTER_DPI/POINT_DPI));
|
||||
rec.setDx2((int)((anchor.getWidth() + anchor.getX())*MASTER_DPI/POINT_DPI));
|
||||
rec.setDy2((int)((anchor.getHeight() + anchor.getY())*MASTER_DPI/POINT_DPI));
|
||||
}
|
||||
else {
|
||||
EscherClientAnchorRecord rec = (EscherClientAnchorRecord)getEscherChild(_escherContainer, EscherClientAnchorRecord.RECORD_ID);
|
||||
rec.setFlag((short)(anchor.y*MASTER_DPI/POINT_DPI));
|
||||
rec.setCol1((short)(anchor.x*MASTER_DPI/POINT_DPI));
|
||||
rec.setDx1((short)((anchor.width + anchor.x)*MASTER_DPI/POINT_DPI));
|
||||
rec.setRow1((short)((anchor.height + anchor.y)*MASTER_DPI/POINT_DPI));
|
||||
rec.setFlag((short)(anchor.getY()*MASTER_DPI/POINT_DPI));
|
||||
rec.setCol1((short)(anchor.getX()*MASTER_DPI/POINT_DPI));
|
||||
rec.setDx1((short)(((anchor.getWidth() + anchor.getX())*MASTER_DPI/POINT_DPI)));
|
||||
rec.setRow1((short)(((anchor.getHeight() + anchor.getY())*MASTER_DPI/POINT_DPI)));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -197,9 +213,9 @@ public abstract class Shape {
|
|||
* @param x the x coordinate of the top left corner of the shape
|
||||
* @param y the y coordinate of the top left corner of the shape
|
||||
*/
|
||||
public void moveTo(int x, int y){
|
||||
java.awt.Rectangle anchor = getAnchor();
|
||||
anchor.setLocation(x, y);
|
||||
public void moveTo(float x, float y){
|
||||
Rectangle2D anchor = getAnchor2D();
|
||||
anchor.setRect(x, y, anchor.getWidth(), anchor.getHeight());
|
||||
setAnchor(anchor);
|
||||
}
|
||||
|
||||
|
@ -254,6 +270,28 @@ public abstract class Shape {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set an simple escher property for this shape.
|
||||
*
|
||||
* @param propId The id of the property. One of the constants defined in EscherOptRecord.
|
||||
* @param value value of the property. If value = -1 then the property is removed.
|
||||
*/
|
||||
public void setEscherProperty(short propId, int value){
|
||||
EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
|
||||
setEscherProperty(opt, propId, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of a simple escher property for this shape.
|
||||
*
|
||||
* @param propId The id of the property. One of the constants defined in EscherOptRecord.
|
||||
*/
|
||||
public int getEscherProperty(short propId){
|
||||
EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
|
||||
EscherSimpleProperty prop = (EscherSimpleProperty)getEscherProperty(opt, propId);
|
||||
return prop == null ? 0 : prop.getPropertyNumber();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The shape container and it's children that can represent this
|
||||
* shape.
|
||||
|
|
|
@ -22,6 +22,7 @@ import org.apache.poi.util.POILogger;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
|
||||
/**
|
||||
* Represents a group of shapes.
|
||||
|
@ -186,16 +187,16 @@ public class ShapeGroup extends Shape{
|
|||
*
|
||||
* @return the anchor of this shape group
|
||||
*/
|
||||
public java.awt.Rectangle getAnchor(){
|
||||
public Rectangle2D getAnchor2D(){
|
||||
EscherContainerRecord groupInfoContainer = (EscherContainerRecord)_escherContainer.getChild(0);
|
||||
EscherSpgrRecord spgr = (EscherSpgrRecord)getEscherChild(groupInfoContainer, EscherSpgrRecord.RECORD_ID);
|
||||
java.awt.Rectangle anchor=null;
|
||||
Rectangle2D anchor = new Rectangle2D.Float(
|
||||
(float)spgr.getRectX1()*POINT_DPI/MASTER_DPI,
|
||||
(float)spgr.getRectY1()*POINT_DPI/MASTER_DPI,
|
||||
(float)(spgr.getRectX2() - spgr.getRectX1())*POINT_DPI/MASTER_DPI,
|
||||
(float)(spgr.getRectY2() - spgr.getRectY1())*POINT_DPI/MASTER_DPI
|
||||
);
|
||||
|
||||
anchor = new java.awt.Rectangle();
|
||||
anchor.x = spgr.getRectX1()*POINT_DPI/MASTER_DPI;
|
||||
anchor.y = spgr.getRectY1()*POINT_DPI/MASTER_DPI;
|
||||
anchor.width = (spgr.getRectX2() - spgr.getRectX1())*POINT_DPI/MASTER_DPI;
|
||||
anchor.height = (spgr.getRectY2() - spgr.getRectY1())*POINT_DPI/MASTER_DPI;
|
||||
return anchor;
|
||||
}
|
||||
|
||||
|
|
|
@ -105,9 +105,13 @@ public class SimpleShape extends Shape {
|
|||
*/
|
||||
public void setLineColor(Color color){
|
||||
EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
|
||||
int rgb = new Color(color.getBlue(), color.getGreen(), color.getRed(), 0).getRGB();
|
||||
setEscherProperty(opt, EscherProperties.LINESTYLE__COLOR, rgb);
|
||||
setEscherProperty(opt, EscherProperties.LINESTYLE__NOLINEDRAWDASH, color == null ? 0x180010 : 0x180018);
|
||||
if (color == null) {
|
||||
setEscherProperty(opt, EscherProperties.LINESTYLE__NOLINEDRAWDASH, 0x80000);
|
||||
} else {
|
||||
int rgb = new Color(color.getBlue(), color.getGreen(), color.getRed(), 0).getRGB();
|
||||
setEscherProperty(opt, EscherProperties.LINESTYLE__COLOR, rgb);
|
||||
setEscherProperty(opt, EscherProperties.LINESTYLE__NOLINEDRAWDASH, color == null ? 0x180010 : 0x180018);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -212,9 +216,13 @@ public class SimpleShape extends Shape {
|
|||
*/
|
||||
public void setFillColor(Color color){
|
||||
EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
|
||||
int rgb = new Color(color.getBlue(), color.getGreen(), color.getRed(), 0).getRGB();
|
||||
setEscherProperty(opt, EscherProperties.FILL__FILLCOLOR, rgb);
|
||||
setEscherProperty(opt, EscherProperties.FILL__NOFILLHITTEST, color == null ? 0x150010 : 0x150011);
|
||||
if(color == null) {
|
||||
setEscherProperty(opt, EscherProperties.FILL__NOFILLHITTEST, 0x150000);
|
||||
} else {
|
||||
int rgb = new Color(color.getBlue(), color.getGreen(), color.getRed(), 0).getRGB();
|
||||
setEscherProperty(opt, EscherProperties.FILL__FILLCOLOR, rgb);
|
||||
setEscherProperty(opt, EscherProperties.FILL__NOFILLHITTEST, 0x150011);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -98,7 +98,7 @@ public class TestTxMasterStyleAtom extends TestCase {
|
|||
assertEquals(0, prop.getValue());
|
||||
|
||||
prop = props.findByName("font.size");
|
||||
assertEquals(49, prop.getValue());
|
||||
assertEquals(44, prop.getValue());
|
||||
|
||||
}
|
||||
|
||||
|
@ -138,7 +138,7 @@ public class TestTxMasterStyleAtom extends TestCase {
|
|||
assertEquals(0, prop.getValue());
|
||||
|
||||
prop = props.findByName("font.size");
|
||||
assertEquals(36, prop.getValue());
|
||||
assertEquals(32, prop.getValue());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -164,7 +164,7 @@ public class TestTxMasterStyleAtom extends TestCase {
|
|||
assertEquals(0, prop.getValue());
|
||||
|
||||
prop = props.findByName("font.size");
|
||||
assertEquals(24, prop.getValue());
|
||||
assertEquals(18, prop.getValue());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue