import java.io.IOException;
import java.util.List;
-import org.apache.poi.hslf.model.PPGraphics2D;
-import org.apache.poi.hslf.record.TextHeaderAtom;
-import org.apache.poi.hslf.usermodel.HSLFAutoShape;
-import org.apache.poi.hslf.usermodel.HSLFGroupShape;
-import org.apache.poi.hslf.usermodel.HSLFSlide;
import org.apache.poi.hslf.usermodel.HSLFSlideShow;
-import org.apache.poi.hslf.usermodel.HSLFTable;
-import org.apache.poi.hslf.usermodel.HSLFTableCell;
-import org.apache.poi.hslf.usermodel.HSLFTextBox;
-import org.apache.poi.hslf.usermodel.HSLFTextParagraph;
-import org.apache.poi.hslf.usermodel.HSLFTextRun;
-import org.apache.poi.hslf.usermodel.HSLFLine;
+import org.apache.poi.sl.draw.DrawTableShape;
+import org.apache.poi.sl.draw.SLGraphics;
+import org.apache.poi.sl.usermodel.AutoShape;
+import org.apache.poi.sl.usermodel.GroupShape;
import org.apache.poi.sl.usermodel.ShapeType;
+import org.apache.poi.sl.usermodel.Slide;
+import org.apache.poi.sl.usermodel.SlideShow;
+import org.apache.poi.sl.usermodel.TableCell;
+import org.apache.poi.sl.usermodel.TableShape;
+import org.apache.poi.sl.usermodel.TextBox;
+import org.apache.poi.sl.usermodel.TextParagraph;
+import org.apache.poi.sl.usermodel.TextRun;
+import org.apache.poi.sl.usermodel.TextShape.TextPlaceholder;
import org.apache.poi.sl.usermodel.VerticalAlignment;
/**
public final class ApacheconEU08 {
public static void main(String[] args) throws IOException {
- HSLFSlideShow ppt = new HSLFSlideShow();
+ SlideShow<?,?> ppt = new HSLFSlideShow();
+ // SlideShow<?,?> ppt = new XMLSlideShow();
ppt.setPageSize(new Dimension(720, 540));
slide1(ppt);
slide11(ppt);
slide12(ppt);
- FileOutputStream out = new FileOutputStream("apachecon_eu_08.ppt");
+ String ext = ppt.getClass().getName().contains("HSLF") ? "ppt" : "pptx";
+ FileOutputStream out = new FileOutputStream("apachecon_eu_08."+ext);
ppt.write(out);
out.close();
}
- public static void slide1(HSLFSlideShow ppt) throws IOException {
- HSLFSlide slide = ppt.createSlide();
+ public static void slide1(SlideShow<?,?> ppt) throws IOException {
+ Slide<?,?> slide = ppt.createSlide();
- HSLFTextBox box1 = new HSLFTextBox();
- box1.setRunType(TextHeaderAtom.CENTER_TITLE_TYPE);
+ TextBox<?,?> box1 = slide.createTextBox();
+ box1.setTextPlaceholder(TextPlaceholder.CENTER_TITLE);
box1.setText("POI-HSLF");
box1.setAnchor(new Rectangle(54, 78, 612, 115));
- slide.addShape(box1);
- HSLFTextBox box2 = new HSLFTextBox();
- box2.setRunType(TextHeaderAtom.CENTRE_BODY_TYPE);
+ TextBox<?,?> box2 = slide.createTextBox();
+ box2.setTextPlaceholder(TextPlaceholder.CENTER_BODY);
box2.setText("Java API To Access Microsoft PowerPoint Format Files");
box2.setAnchor(new Rectangle(108, 204, 504, 138));
- slide.addShape(box2);
- HSLFTextBox box3 = new HSLFTextBox();
+ TextBox<?,?> box3 = slide.createTextBox();
box3.getTextParagraphs().get(0).getTextRuns().get(0).setFontSize(32d);
box3.setText(
"Yegor Kozlov\r" +
"yegor - apache - org");
box3.setHorizontalCentered(true);
box3.setAnchor(new Rectangle(206, 348, 310, 84));
- slide.addShape(box3);
}
- public static void slide2(HSLFSlideShow ppt) throws IOException {
- HSLFSlide slide = ppt.createSlide();
+ public static void slide2(SlideShow<?,?> ppt) throws IOException {
+ Slide<?,?> slide = ppt.createSlide();
- HSLFTextBox box1 = new HSLFTextBox();
- box1.setRunType(TextHeaderAtom.TITLE_TYPE);
+ TextBox<?,?> box1 = slide.createTextBox();
+ box1.setTextPlaceholder(TextPlaceholder.TITLE);
box1.setText("What is HSLF?");
box1.setAnchor(new Rectangle(36, 21, 648, 90));
- slide.addShape(box1);
- HSLFTextBox box2 = new HSLFTextBox();
- box2.setRunType(TextHeaderAtom.BODY_TYPE);
+ TextBox<?,?> box2 = slide.createTextBox();
+ box2.setTextPlaceholder(TextPlaceholder.BODY);
box2.setText("HorribleSLideshowFormat is the POI Project's pure Java implementation " +
"of the Powerpoint binary file format. \r" +
"POI sub-project since 2005\r" +
- "Started by Nick Birch, Yegor Kozlov joined soon after");
+ "Started by Nick Burch, Yegor Kozlov joined soon after");
box2.setAnchor(new Rectangle(36, 126, 648, 356));
- slide.addShape(box2);
-
-
}
- public static void slide3(HSLFSlideShow ppt) throws IOException {
- HSLFSlide slide = ppt.createSlide();
+ public static void slide3(SlideShow<?,?> ppt) throws IOException {
+ Slide<?,?> slide = ppt.createSlide();
- HSLFTextBox box1 = new HSLFTextBox();
- box1.setRunType(TextHeaderAtom.TITLE_TYPE);
+ TextBox<?,?> box1 = slide.createTextBox();
+ box1.setTextPlaceholder(TextPlaceholder.TITLE);
box1.setText("HSLF in a Nutshell");
box1.setAnchor(new Rectangle(36, 15, 648, 65));
- slide.addShape(box1);
- HSLFTextBox box2 = new HSLFTextBox();
- box2.setRunType(TextHeaderAtom.BODY_TYPE);
+ TextBox<?,?> box2 = slide.createTextBox();
+ box2.setTextPlaceholder(TextPlaceholder.BODY);
box2.setText(
"HSLF provides a way to read, create and modify MS PowerPoint presentations\r" +
"Pure Java API - you don't need PowerPoint to read and write *.ppt files\r" +
"Access to low level data structures"
);
- List<HSLFTextParagraph> tp = box2.getTextParagraphs();
+ List<? extends TextParagraph<?,?,?>> tp = box2.getTextParagraphs();
for (int i : new byte[]{0,1,2,8}) {
tp.get(i).getTextRuns().get(0).setFontSize(28d);
}
tp.get(i).setIndentLevel(1);
}
box2.setAnchor(new Rectangle(36, 80, 648, 400));
- slide.addShape(box2);
}
- public static void slide4(HSLFSlideShow ppt) throws IOException {
- HSLFSlide slide = ppt.createSlide();
+ public static void slide4(SlideShow<?,?> ppt) throws IOException {
+ Slide<?,?> slide = ppt.createSlide();
String[][] txt1 = {
{"Note"},
{"This presentation was created programmatically using POI HSLF"}
};
- HSLFTable table1 = new HSLFTable(2, 1);
+ TableShape<?,?> table1 = slide.createTable(2, 1);
for (int i = 0; i < txt1.length; i++) {
for (int j = 0; j < txt1[i].length; j++) {
- HSLFTableCell cell = table1.getCell(i, j);
+ TableCell<?,?> cell = table1.getCell(i, j);
cell.setText(txt1[i][j]);
- HSLFTextRun rt = cell.getTextParagraphs().get(0).getTextRuns().get(0);
+ TextRun rt = cell.getTextParagraphs().get(0).getTextRuns().get(0);
rt.setFontSize(10d);
rt.setFontFamily("Arial");
rt.setBold(true);
if(i == 0){
rt.setFontSize(32d);
rt.setFontColor(Color.white);
- cell.getFill().setForegroundColor(new Color(0, 153, 204));
+ cell.setFillColor(new Color(0, 153, 204));
} else {
rt.setFontSize(28d);
- cell.getFill().setForegroundColor(new Color(235, 239, 241));
+ cell.setFillColor(new Color(235, 239, 241));
}
cell.setVerticalAlignment(VerticalAlignment.MIDDLE);
}
}
- HSLFLine border1 = table1.createBorder();
- border1.setLineColor(Color.black);
- border1.setLineWidth(1.0);
- table1.setAllBorders(border1);
-
- HSLFLine border2 = table1.createBorder();
- border2.setLineColor(Color.black);
- border2.setLineWidth(2.0);
- table1.setOutsideBorders(border2);
+ DrawTableShape dts = new DrawTableShape(table1);
+ dts.setAllBorders(1.0, Color.black);
+ dts.setOutsideBorders(4.0);
- table1.setColumnWidth(0, 510);
- table1.setRowHeight(0, 60);
- table1.setRowHeight(1, 100);
- slide.addShape(table1);
+ table1.setColumnWidth(0, 450);
+ table1.setRowHeight(0, 50);
+ table1.setRowHeight(1, 80);
- table1.moveTo(100, 100);
+ Dimension dim = ppt.getPageSize();
+ Rectangle oldAnchor = table1.getAnchor();
+ table1.setAnchor(new Rectangle((dim.width-450)/2, 100, oldAnchor.width, oldAnchor.height));
- HSLFTextBox box1 = new HSLFTextBox();
+ TextBox<?,?> box1 = slide.createTextBox();
box1.setHorizontalCentered(true);
box1.getTextParagraphs().get(0).getTextRuns().get(0).setFontSize(24d);
box1.setText("The source code is available at\r" +
"http://people.apache.org/~yegor/apachecon_eu08/");
box1.setAnchor(new Rectangle(80, 356, 553, 65));
- slide.addShape(box1);
-
}
- public static void slide5(HSLFSlideShow ppt) throws IOException {
- HSLFSlide slide = ppt.createSlide();
+ public static void slide5(SlideShow<?,?> ppt) throws IOException {
+ Slide<?,?> slide = ppt.createSlide();
- HSLFTextBox box1 = new HSLFTextBox();
- box1.setRunType(TextHeaderAtom.TITLE_TYPE);
+ TextBox<?,?> box1 = slide.createTextBox();
+ box1.setTextPlaceholder(TextPlaceholder.TITLE);
box1.setText("HSLF in Action - 1\rData Extraction");
box1.setAnchor(new Rectangle(36, 21, 648, 100));
- slide.addShape(box1);
- HSLFTextBox box2 = new HSLFTextBox();
- box2.setRunType(TextHeaderAtom.BODY_TYPE);
+ TextBox<?,?> box2 = slide.createTextBox();
+ box2.setTextPlaceholder(TextPlaceholder.BODY);
box2.setText(
"Text from slides and notes\r" +
"Images\r" +
"Shapes and their properties (type, position in the slide, color, font, etc.)");
box2.setAnchor(new Rectangle(36, 150, 648, 300));
- slide.addShape(box2);
-
-
}
- public static void slide6(HSLFSlideShow ppt) throws IOException {
- HSLFSlide slide = ppt.createSlide();
+ public static void slide6(SlideShow<?,?> ppt) throws IOException {
+ Slide<?,?> slide = ppt.createSlide();
- HSLFTextBox box1 = new HSLFTextBox();
- box1.setRunType(TextHeaderAtom.TITLE_TYPE);
+ TextBox<?,?> box1 = slide.createTextBox();
+ box1.setTextPlaceholder(TextPlaceholder.TITLE);
box1.setText("HSLF in Action - 2");
box1.setAnchor(new Rectangle(36, 20, 648, 90));
- slide.addShape(box1);
- HSLFTextBox box2 = new HSLFTextBox();
+ TextBox<?,?> box2 = slide.createTextBox();
box2.getTextParagraphs().get(0).getTextRuns().get(0).setFontSize(18d);
box2.setText("Creating a simple presentation from scratch");
box2.setAnchor(new Rectangle(170, 100, 364, 30));
- slide.addShape(box2);
- HSLFTextBox box3 = new HSLFTextBox();
- HSLFTextRun rt3 = box3.getTextParagraphs().get(0).getTextRuns().get(0);
+ TextBox<?,?> box3 = slide.createTextBox();
+ TextRun rt3 = box3.getTextParagraphs().get(0).getTextRuns().get(0);
rt3.setFontFamily("Courier New");
rt3.setFontSize(8d);
box3.setText(
"out.close();");
box3.setAnchor(new Rectangle(30, 150, 618, 411));
box3.setHorizontalCentered(true);
- slide.addShape(box3);
}
- public static void slide7(HSLFSlideShow ppt) throws IOException {
- HSLFSlide slide = ppt.createSlide();
+ public static void slide7(SlideShow<?,?> ppt) throws IOException {
+ Slide<?,?> slide = ppt.createSlide();
- HSLFTextBox box2 = new HSLFTextBox();
+ TextBox<?,?> box2 = slide.createTextBox();
box2.setHorizontalCentered(true);
box2.setVerticalAlignment(VerticalAlignment.MIDDLE);
box2.setText("Java Code");
- box2.getFill().setForegroundColor(new Color(187, 224, 227));
- box2.setLineColor(Color.black);
- box2.setLineWidth(0.75);
+ box2.setFillColor(new Color(187, 224, 227));
+ box2.setStrokeStyle(0.75, Color.black);
box2.setAnchor(new Rectangle(66, 243, 170, 170));
- slide.addShape(box2);
- HSLFTextBox box3 = new HSLFTextBox();
+ TextBox<?,?> box3 = slide.createTextBox();
box3.setHorizontalCentered(true);
box3.setVerticalAlignment(VerticalAlignment.MIDDLE);
box3.setText("*.ppt file");
- box3.setLineWidth(0.75);
- box3.setLineColor(Color.black);
- box3.getFill().setForegroundColor(new Color(187, 224, 227));
+ box3.setFillColor(new Color(187, 224, 227));
+ box3.setStrokeStyle(0.75, Color.black);
box3.setAnchor(new Rectangle(473, 243, 170, 170));
- slide.addShape(box3);
- HSLFAutoShape box4 = new HSLFAutoShape(ShapeType.RIGHT_ARROW);
- box4.getFill().setForegroundColor(new Color(187, 224, 227));
- box4.setLineWidth(0.75);
- box4.setLineColor(Color.black);
+ AutoShape<?,?> box4 = slide.createAutoShape();
+ box4.setShapeType(ShapeType.RIGHT_ARROW);
+ box4.setFillColor(new Color(187, 224, 227));
+ box4.setStrokeStyle(0.75, Color.black);
box4.setAnchor(new Rectangle(253, 288, 198, 85));
- slide.addShape(box4);
}
- public static void slide8(HSLFSlideShow ppt) throws IOException {
- HSLFSlide slide = ppt.createSlide();
+ public static void slide8(SlideShow<?,?> ppt) throws IOException {
+ Slide<?,?> slide = ppt.createSlide();
- HSLFTextBox box1 = new HSLFTextBox();
- box1.setRunType(TextHeaderAtom.TITLE_TYPE);
+ TextBox<?,?> box1 = slide.createTextBox();
+ box1.setTextPlaceholder(TextPlaceholder.TITLE);
box1.setText("Wait, there is more!");
box1.setAnchor(new Rectangle(36, 21, 648, 90));
- slide.addShape(box1);
- HSLFTextBox box2 = new HSLFTextBox();
- box2.setRunType(TextHeaderAtom.BODY_TYPE);
+ TextBox<?,?> box2 = slide.createTextBox();
+ box2.setTextPlaceholder(TextPlaceholder.BODY);
box2.setText(
"Rich text\r" +
"Tables\r" +
"Pictures (JPEG, PNG, BMP, WMF, PICT)\r" +
"Comprehensive formatting features");
box2.setAnchor(new Rectangle(36, 126, 648, 356));
- slide.addShape(box2);
}
- public static void slide9(HSLFSlideShow ppt) throws IOException {
- HSLFSlide slide = ppt.createSlide();
+ public static void slide9(SlideShow<?,?> ppt) throws IOException {
+ Slide<?,?> slide = ppt.createSlide();
- HSLFTextBox box1 = new HSLFTextBox();
- box1.setRunType(TextHeaderAtom.TITLE_TYPE);
+ TextBox<?,?> box1 = slide.createTextBox();
+ box1.setTextPlaceholder(TextPlaceholder.TITLE);
box1.setText("HSLF in Action - 3");
box1.setAnchor(new Rectangle(36, 20, 648, 50));
- slide.addShape(box1);
- HSLFTextBox box2 = new HSLFTextBox();
+ TextBox<?,?> box2 = slide.createTextBox();
box2.getTextParagraphs().get(0).getTextRuns().get(0).setFontSize(18d);
box2.setText("PPGraphics2D: PowerPoint Graphics2D driver");
box2.setAnchor(new Rectangle(178, 70, 387, 30));
- slide.addShape(box2);
- HSLFTextBox box3 = new HSLFTextBox();
- HSLFTextRun rt3 = box3.getTextParagraphs().get(0).getTextRuns().get(0);
+ TextBox<?,?> box3 = slide.createTextBox();
+ TextRun rt3 = box3.getTextParagraphs().get(0).getTextRuns().get(0);
rt3.setFontFamily("Courier New");
rt3.setFontSize(8d);
box3.setText(
"out.close();");
box3.setAnchor(new Rectangle(96, 110, 499, 378));
box3.setHorizontalCentered(true);
- slide.addShape(box3);
}
- public static void slide10(HSLFSlideShow ppt) throws IOException {
+ public static void slide10(SlideShow<?,?> ppt) throws IOException {
//bar chart data. The first value is the bar color, the second is the width
Object[] def = new Object[]{
Color.yellow, new Integer(100),
Color.red, new Integer(200),
};
- HSLFSlide slide = ppt.createSlide();
+ Slide<?,?> slide = ppt.createSlide();
- HSLFGroupShape group = new HSLFGroupShape();
+ GroupShape<?,?> group = slide.createGroup();
//define position of the drawing in the slide
Rectangle bounds = new java.awt.Rectangle(200, 100, 350, 300);
group.setAnchor(bounds);
- slide.addShape(group);
- Graphics2D graphics = new PPGraphics2D(group);
+ Graphics2D graphics = new SLGraphics(group);
//draw a simple bar graph
int x = bounds.x + 50, y = bounds.y + 50;
}
- public static void slide11(HSLFSlideShow ppt) throws IOException {
- HSLFSlide slide = ppt.createSlide();
+ public static void slide11(SlideShow<?,?> ppt) throws IOException {
+ Slide<?,?> slide = ppt.createSlide();
- HSLFTextBox box1 = new HSLFTextBox();
- box1.setRunType(TextHeaderAtom.TITLE_TYPE);
+ TextBox<?,?> box1 = slide.createTextBox();
+ box1.setTextPlaceholder(TextPlaceholder.TITLE);
box1.setText("HSLF Development Plans");
box1.setAnchor(new Rectangle(36, 21, 648, 90));
- slide.addShape(box1);
- HSLFTextBox box2 = new HSLFTextBox();
- box2.setRunType(TextHeaderAtom.BODY_TYPE);
+ TextBox<?,?> box2 = slide.createTextBox();
+ box2.setTextPlaceholder(TextPlaceholder.BODY);
box2.setText(
"Support for more PowerPoint functionality\r" +
"Rendering slides into java.awt.Graphics2D\r" +
"PPT2PDF transcoder"
);
- List<HSLFTextParagraph> tp = box2.getTextParagraphs();
+ List<? extends TextParagraph<?,?,?>> tp = box2.getTextParagraphs();
for (int i : new byte[]{0,1,3}) {
tp.get(i).getTextRuns().get(0).setFontSize(28d);
}
}
box2.setAnchor(new Rectangle(36, 126, 648, 400));
- slide.addShape(box2);
}
- public static void slide12(HSLFSlideShow ppt) throws IOException {
- HSLFSlide slide = ppt.createSlide();
+ public static void slide12(SlideShow<?,?> ppt) throws IOException {
+ Slide<?,?> slide = ppt.createSlide();
- HSLFTextBox box1 = new HSLFTextBox();
- box1.setRunType(TextHeaderAtom.CENTER_TITLE_TYPE);
+ TextBox<?,?> box1 = slide.createTextBox();
+ box1.setTextPlaceholder(TextPlaceholder.CENTER_TITLE);
box1.setText("Questions?");
box1.setAnchor(new Rectangle(54, 167, 612, 115));
- slide.addShape(box1);
- HSLFTextBox box2 = new HSLFTextBox();
- box2.setRunType(TextHeaderAtom.CENTRE_BODY_TYPE);
+ TextBox<?,?> box2 = slide.createTextBox();
+ box2.setTextPlaceholder(TextPlaceholder.CENTER_BODY);
box2.setText(
"http://poi.apache.org/hslf/\r" +
"http://people.apache.org/~yegor");
box2.setAnchor(new Rectangle(108, 306, 504, 138));
- slide.addShape(box2);
}
}
import org.apache.poi.hslf.usermodel.HSLFTable;
import org.apache.poi.hslf.usermodel.HSLFTableCell;
import org.apache.poi.hslf.usermodel.HSLFTextRun;
-import org.apache.poi.hslf.usermodel.HSLFLine;
+import org.apache.poi.sl.draw.DrawTableShape;
import org.apache.poi.sl.usermodel.TextParagraph.TextAlign;
import org.apache.poi.sl.usermodel.VerticalAlignment;
HSLFSlide slide = ppt.createSlide();
//six rows, two columns
- HSLFTable table1 = new HSLFTable(6, 2);
+ HSLFTable table1 = slide.createTable(6, 2);
for (int i = 0; i < txt1.length; i++) {
for (int j = 0; j < txt1[i].length; j++) {
HSLFTableCell cell = table1.getCell(i, j);
}
}
- HSLFLine border1 = table1.createBorder();
- border1.setLineColor(Color.black);
- border1.setLineWidth(1.0);
- table1.setAllBorders(border1);
+ DrawTableShape dts1 = new DrawTableShape(table1);
+ dts1.setAllBorders(1.0, Color.black);
table1.setColumnWidth(0, 300);
table1.setColumnWidth(1, 150);
- slide.addShape(table1);
int pgWidth = ppt.getPageSize().width;
table1.moveTo((pgWidth - table1.getAnchor().width)/2, 100);
};
//two rows, one column
- HSLFTable table2 = new HSLFTable(2, 1);
+ HSLFTable table2 = slide.createTable(2, 1);
for (int i = 0; i < txt2.length; i++) {
for (int j = 0; j < txt2[i].length; j++) {
HSLFTableCell cell = table2.getCell(i, j);
table2.setRowHeight(0, 30);
table2.setRowHeight(1, 70);
- HSLFLine border2 = table2.createBorder();
- table2.setOutsideBorders(border2);
+ DrawTableShape dts2 = new DrawTableShape(table2);
+ dts2.setOutsideBorders(Color.black, 1.0);
- slide.addShape(table2);
table2.moveTo(200, 400);
FileOutputStream out = new FileOutputStream("hslf-table.ppt");
import java.io.FileOutputStream;\r
import java.io.IOException;\r
\r
+import org.apache.poi.sl.usermodel.SimpleShape.Placeholder;\r
+\r
/**\r
* How to set slide title\r
*\r
import java.io.FileOutputStream;\r
import java.io.IOException;\r
\r
+import org.apache.poi.sl.usermodel.TableCell.BorderEdge;\r
import org.apache.poi.sl.usermodel.TextParagraph.TextAlign;\r
\r
/**\r
r.setBold(true);\r
r.setFontColor(Color.white);\r
th.setFillColor(new Color(79, 129, 189));\r
- th.setBorderBottom(2);\r
- th.setBorderBottomColor(Color.white);\r
+ th.setBorderWidth(BorderEdge.bottom, 2.0);\r
+ th.setBorderColor(BorderEdge.bottom, Color.white);\r
\r
tbl.setColumnWidth(i, 150); // all columns are equally sized\r
}\r
\r
package org.apache.poi.sl.draw;\r
\r
+import java.awt.Color;\r
import java.awt.Graphics2D;\r
\r
import org.apache.poi.sl.usermodel.GroupShape;\r
+import org.apache.poi.sl.usermodel.StrokeStyle;\r
+import org.apache.poi.sl.usermodel.StrokeStyle.LineCompound;\r
+import org.apache.poi.sl.usermodel.StrokeStyle.LineDash;\r
+import org.apache.poi.sl.usermodel.TableCell;\r
+import org.apache.poi.sl.usermodel.TableCell.BorderEdge;\r
import org.apache.poi.sl.usermodel.TableShape;\r
\r
public class DrawTableShape extends DrawShape {\r
}\r
}\r
\r
+ @Override\r
+ protected TableShape<?,?> getShape() {\r
+ return (TableShape<?,?>)shape;\r
+ } \r
+ \r
+ /**\r
+ * Format the table and apply the specified Line to all cell boundaries,\r
+ * both outside and inside.\r
+ * An empty args parameter removes the affected border.\r
+ *\r
+ * @param args a varargs array possible containing {@link Double} (width),\r
+ * {@link StrokeStyle.LineCompound}, {@link Color}, {@link StrokeStyle.LineDash}\r
+ */\r
+ public void setAllBorders(Object... args) {\r
+ TableShape<?,?> table = getShape();\r
+ final int rows = table.getNumberOfRows();\r
+ final int cols = table.getNumberOfColumns();\r
+ \r
+ BorderEdge edges[] = { BorderEdge.top, BorderEdge.left, null, null };\r
+ for (int row = 0; row < rows; row++) {\r
+ for (int col = 0; col < cols; col++) {\r
+ edges[2] = (col == cols - 1) ? BorderEdge.right : null;\r
+ edges[3] = (row == rows - 1) ? BorderEdge.bottom : null;\r
+ setEdges(table.getCell(row, col), edges, args);\r
+ }\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Format the outside border using the specified Line object\r
+ * An empty args parameter removes the affected border.\r
+ *\r
+ * @param args a varargs array possible containing {@link Double} (width),\r
+ * {@link StrokeStyle.LineCompound}, {@link Color}, {@link StrokeStyle.LineDash}\r
+ */\r
+ public void setOutsideBorders(Object... args){\r
+ if (args.length == 0) return;\r
+ \r
+ TableShape<?,?> table = getShape();\r
+ final int rows = table.getNumberOfRows();\r
+ final int cols = table.getNumberOfColumns();\r
+ \r
+ BorderEdge edges[] = new BorderEdge[4];\r
+ for (int row = 0; row < rows; row++) {\r
+ for (int col = 0; col < cols; col++) {\r
+ edges[0] = (col == 0) ? BorderEdge.left : null;\r
+ edges[1] = (col == cols - 1) ? BorderEdge.right : null;\r
+ edges[2] = (row == 0) ? BorderEdge.top : null;\r
+ edges[3] = (row == rows - 1) ? BorderEdge.bottom : null;\r
+ setEdges(table.getCell(row, col), edges, args);\r
+ }\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Format the inside border using the specified Line object\r
+ * An empty args parameter removes the affected border.\r
+ *\r
+ * @param args a varargs array possible containing {@link Double} (width),\r
+ * {@link StrokeStyle.LineCompound}, {@link Color}, {@link StrokeStyle.LineDash}\r
+ */\r
+ public void setInsideBorders(Object... args) {\r
+ if (args.length == 0) return;\r
+ \r
+ TableShape<?,?> table = getShape();\r
+ final int rows = table.getNumberOfRows();\r
+ final int cols = table.getNumberOfColumns();\r
+ \r
+ BorderEdge edges[] = new BorderEdge[2];\r
+ for (int row = 0; row < rows; row++) {\r
+ for (int col = 0; col < cols; col++) {\r
+ edges[0] = (col > 0 && col < cols - 1) ? BorderEdge.right : null;\r
+ edges[1] = (row > 0 && row < rows - 1) ? BorderEdge.bottom : null;\r
+ setEdges(table.getCell(row, col), edges, args);\r
+ }\r
+ }\r
+ }\r
+ \r
+ /**\r
+ * Apply the border attributes (args) to the given cell and edges\r
+ *\r
+ * @param cell the cell\r
+ * @param edges the border edges\r
+ * @param args the border attributes\r
+ */\r
+ private static void setEdges(TableCell<?,?> cell, BorderEdge edges[], Object... args) {\r
+ for (BorderEdge be : edges) {\r
+ if (be != null) {\r
+ if (args.length == 0) {\r
+ cell.removeBorder(be);\r
+ } else {\r
+ for (Object o : args) {\r
+ if (o instanceof Double) {\r
+ cell.setBorderWidth(be, (Double)o);\r
+ } else if (o instanceof Color) {\r
+ cell.setBorderColor(be, (Color)o);\r
+ } else if (o instanceof LineDash) {\r
+ cell.setBorderDash(be, (LineDash)o);\r
+ } else if (o instanceof LineCompound) {\r
+ cell.setBorderCompound(be, (LineCompound)o);\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
\r
}\r
--- /dev/null
+/* ====================================================================\r
+ Licensed to the Apache Software Foundation (ASF) under one or more\r
+ contributor license agreements. See the NOTICE file distributed with\r
+ this work for additional information regarding copyright ownership.\r
+ The ASF licenses this file to You under the Apache License, Version 2.0\r
+ (the "License"); you may not use this file except in compliance with\r
+ the License. You may obtain a copy of the License at\r
+\r
+ http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+ Unless required by applicable law or agreed to in writing, software\r
+ distributed under the License is distributed on an "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ See the License for the specific language governing permissions and\r
+ limitations under the License.\r
+==================================================================== */\r
+\r
+package org.apache.poi.sl.draw;\r
+\r
+\r
+import java.awt.BasicStroke;\r
+import java.awt.Color;\r
+import java.awt.Composite;\r
+import java.awt.Font;\r
+import java.awt.FontMetrics;\r
+import java.awt.Graphics;\r
+import java.awt.Graphics2D;\r
+import java.awt.GraphicsConfiguration;\r
+import java.awt.GraphicsEnvironment;\r
+import java.awt.Image;\r
+import java.awt.Paint;\r
+import java.awt.Rectangle;\r
+import java.awt.RenderingHints;\r
+import java.awt.Shape;\r
+import java.awt.Stroke;\r
+import java.awt.Toolkit;\r
+import java.awt.font.FontRenderContext;\r
+import java.awt.font.GlyphVector;\r
+import java.awt.font.TextLayout;\r
+import java.awt.geom.AffineTransform;\r
+import java.awt.geom.Arc2D;\r
+import java.awt.geom.Ellipse2D;\r
+import java.awt.geom.GeneralPath;\r
+import java.awt.geom.Line2D;\r
+import java.awt.geom.RoundRectangle2D;\r
+import java.awt.image.BufferedImage;\r
+import java.awt.image.BufferedImageOp;\r
+import java.awt.image.ImageObserver;\r
+import java.awt.image.RenderedImage;\r
+import java.awt.image.renderable.RenderableImage;\r
+import java.text.AttributedCharacterIterator;\r
+import java.util.Map;\r
+\r
+import org.apache.poi.sl.usermodel.FreeformShape;\r
+import org.apache.poi.sl.usermodel.GroupShape;\r
+import org.apache.poi.sl.usermodel.Insets2D;\r
+import org.apache.poi.sl.usermodel.SimpleShape;\r
+import org.apache.poi.sl.usermodel.StrokeStyle;\r
+import org.apache.poi.sl.usermodel.TextBox;\r
+import org.apache.poi.sl.usermodel.TextRun;\r
+import org.apache.poi.sl.usermodel.VerticalAlignment;\r
+import org.apache.poi.util.POILogFactory;\r
+import org.apache.poi.util.POILogger;\r
+import org.apache.poi.util.SuppressForbidden;\r
+\r
+/**\r
+ * Translates Graphics2D calls into PowerPoint.\r
+ *\r
+ * @author Yegor Kozlov\r
+ */\r
+public final class SLGraphics extends Graphics2D implements Cloneable {\r
+\r
+ protected POILogger log = POILogFactory.getLogger(this.getClass());\r
+\r
+ //The ppt object to write into.\r
+ private GroupShape<?,?> _group;\r
+\r
+ private AffineTransform _transform;\r
+ private Stroke _stroke;\r
+ private Paint _paint;\r
+ private Font _font;\r
+ private Color _foreground;\r
+ private Color _background;\r
+ private RenderingHints _hints;\r
+\r
+ /**\r
+ * Construct Java Graphics object which translates graphic calls in ppt drawing layer.\r
+ *\r
+ * @param group The shape group to write the graphics calls into.\r
+ */\r
+ public SLGraphics(GroupShape<?,?> group){\r
+ this._group = group;\r
+\r
+ _transform = new AffineTransform();\r
+ _stroke = new BasicStroke();\r
+ _paint = Color.black;\r
+ _font = new Font("Arial", Font.PLAIN, 12);\r
+ _background = Color.black;\r
+ _foreground = Color.white;\r
+ _hints = new RenderingHints(null);\r
+ }\r
+\r
+ /**\r
+ * @return the shape group being used for drawing\r
+ */\r
+ public GroupShape<?,?> getShapeGroup(){\r
+ return _group;\r
+ }\r
+\r
+ /**\r
+ * Gets the current font.\r
+ * @return this graphics context's current font.\r
+ * @see java.awt.Font\r
+ * @see java.awt.Graphics#setFont(Font)\r
+ */\r
+ public Font getFont(){\r
+ return _font;\r
+ }\r
+\r
+ /**\r
+ * Sets this graphics context's font to the specified font.\r
+ * All subsequent text operations using this graphics context\r
+ * use this font.\r
+ * @param font the font.\r
+ * @see java.awt.Graphics#getFont\r
+ * @see java.awt.Graphics#drawString(java.lang.String, int, int)\r
+ * @see java.awt.Graphics#drawBytes(byte[], int, int, int, int)\r
+ * @see java.awt.Graphics#drawChars(char[], int, int, int, int)\r
+ */\r
+ public void setFont(Font font){\r
+ this._font = font;\r
+ }\r
+\r
+ /**\r
+ * Gets this graphics context's current color.\r
+ * @return this graphics context's current color.\r
+ * @see java.awt.Color\r
+ * @see java.awt.Graphics#setColor\r
+ */\r
+ public Color getColor(){\r
+ return _foreground;\r
+ }\r
+\r
+ /**\r
+ * Sets this graphics context's current color to the specified\r
+ * color. All subsequent graphics operations using this graphics\r
+ * context use this specified color.\r
+ * @param c the new rendering color.\r
+ * @see java.awt.Color\r
+ * @see java.awt.Graphics#getColor\r
+ */\r
+ public void setColor(Color c) {\r
+ setPaint(c);\r
+ }\r
+\r
+ /**\r
+ * Returns the current <code>Stroke</code> in the\r
+ * <code>Graphics2D</code> context.\r
+ * @return the current <code>Graphics2D</code> <code>Stroke</code>,\r
+ * which defines the line style.\r
+ * @see #setStroke\r
+ */\r
+ public Stroke getStroke(){\r
+ return _stroke;\r
+ }\r
+\r
+ /**\r
+ * Sets the <code>Stroke</code> for the <code>Graphics2D</code> context.\r
+ * @param s the <code>Stroke</code> object to be used to stroke a\r
+ * <code>Shape</code> during the rendering process\r
+ */\r
+ public void setStroke(Stroke s){\r
+ this._stroke = s;\r
+ }\r
+\r
+ /**\r
+ * Returns the current <code>Paint</code> of the\r
+ * <code>Graphics2D</code> context.\r
+ * @return the current <code>Graphics2D</code> <code>Paint</code>,\r
+ * which defines a color or pattern.\r
+ * @see #setPaint\r
+ * @see java.awt.Graphics#setColor\r
+ */\r
+ public Paint getPaint(){\r
+ return _paint;\r
+ }\r
+\r
+ /**\r
+ * Sets the <code>Paint</code> attribute for the\r
+ * <code>Graphics2D</code> context. Calling this method\r
+ * with a <code>null</code> <code>Paint</code> object does\r
+ * not have any effect on the current <code>Paint</code> attribute\r
+ * of this <code>Graphics2D</code>.\r
+ * @param paint the <code>Paint</code> object to be used to generate\r
+ * color during the rendering process, or <code>null</code>\r
+ * @see java.awt.Graphics#setColor\r
+ */\r
+ public void setPaint(Paint paint){\r
+ if(paint == null) return;\r
+\r
+ this._paint = paint;\r
+ if (paint instanceof Color) _foreground = (Color)paint;\r
+ }\r
+\r
+ /**\r
+ * Returns a copy of the current <code>Transform</code> in the\r
+ * <code>Graphics2D</code> context.\r
+ * @return the current <code>AffineTransform</code> in the\r
+ * <code>Graphics2D</code> context.\r
+ * @see #_transform\r
+ * @see #setTransform\r
+ */\r
+ public AffineTransform getTransform(){\r
+ return new AffineTransform(_transform);\r
+ }\r
+\r
+ /**\r
+ * Sets the <code>Transform</code> in the <code>Graphics2D</code>\r
+ * context.\r
+ * @param Tx the <code>AffineTransform</code> object to be used in the\r
+ * rendering process\r
+ * @see #_transform\r
+ * @see AffineTransform\r
+ */\r
+ public void setTransform(AffineTransform Tx) {\r
+ _transform = new AffineTransform(Tx);\r
+ }\r
+\r
+ /**\r
+ * Strokes the outline of a <code>Shape</code> using the settings of the\r
+ * current <code>Graphics2D</code> context. The rendering attributes\r
+ * applied include the <code>Clip</code>, <code>Transform</code>,\r
+ * <code>Paint</code>, <code>Composite</code> and\r
+ * <code>Stroke</code> attributes.\r
+ * @param shape the <code>Shape</code> to be rendered\r
+ * @see #setStroke\r
+ * @see #setPaint\r
+ * @see java.awt.Graphics#setColor\r
+ * @see #_transform\r
+ * @see #setTransform\r
+ * @see #clip\r
+ * @see #setClip\r
+ * @see #setComposite\r
+ */\r
+ public void draw(Shape shape){\r
+ GeneralPath path = new GeneralPath(_transform.createTransformedShape(shape));\r
+ FreeformShape<?,?> p = _group.createFreeform();\r
+ p.setPath(path);\r
+ p.setFillColor(null);\r
+ applyStroke(p);\r
+ if (_paint instanceof Color) {\r
+ p.setStrokeStyle((Color)_paint);\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Renders the text specified by the specified <code>String</code>,\r
+ * using the current text attribute state in the <code>Graphics2D</code> context.\r
+ * The baseline of the first character is at position\r
+ * (<i>x</i>, <i>y</i>) in the User Space.\r
+ * The rendering attributes applied include the <code>Clip</code>,\r
+ * <code>Transform</code>, <code>Paint</code>, <code>Font</code> and\r
+ * <code>Composite</code> attributes. For characters in script systems\r
+ * such as Hebrew and Arabic, the glyphs can be rendered from right to\r
+ * left, in which case the coordinate supplied is the location of the\r
+ * leftmost character on the baseline.\r
+ * @param s the <code>String</code> to be rendered\r
+ * @param x the x coordinate of the location where the\r
+ * <code>String</code> should be rendered\r
+ * @param y the y coordinate of the location where the\r
+ * <code>String</code> should be rendered\r
+ * @throws NullPointerException if <code>str</code> is\r
+ * <code>null</code>\r
+ * @see #setPaint\r
+ * @see java.awt.Graphics#setColor\r
+ * @see java.awt.Graphics#setFont\r
+ * @see #setTransform\r
+ * @see #setComposite\r
+ * @see #setClip\r
+ */\r
+ public void drawString(String s, float x, float y) {\r
+ TextBox<?,?> txt = _group.createTextBox();\r
+\r
+ TextRun rt = txt.getTextParagraphs().get(0).getTextRuns().get(0);\r
+ rt.setFontSize((double)_font.getSize());\r
+ rt.setFontFamily(_font.getFamily());\r
+\r
+ if (getColor() != null) rt.setFontColor(DrawPaint.createSolidPaint(getColor()));\r
+ if (_font.isBold()) rt.setBold(true);\r
+ if (_font.isItalic()) rt.setItalic(true);\r
+\r
+ txt.setText(s);\r
+\r
+ txt.setInsets(new Insets2D(0,0,0,0));\r
+ txt.setWordWrap(false);\r
+ txt.setHorizontalCentered(false);\r
+ txt.setVerticalAlignment(VerticalAlignment.MIDDLE);\r
+\r
+\r
+ TextLayout layout = new TextLayout(s, _font, getFontRenderContext());\r
+ float ascent = layout.getAscent();\r
+\r
+ float width = (float) Math.floor(layout.getAdvance());\r
+ /**\r
+ * Even if top and bottom margins are set to 0 PowerPoint\r
+ * always sets extra space between the text and its bounding box.\r
+ *\r
+ * The approximation height = ascent*2 works good enough in most cases\r
+ */\r
+ float height = ascent * 2;\r
+\r
+ /*\r
+ In powerpoint anchor of a shape is its top left corner.\r
+ Java graphics sets string coordinates by the baseline of the first character\r
+ so we need to shift up by the height of the textbox\r
+ */\r
+ y -= height / 2 + ascent / 2;\r
+\r
+ /*\r
+ In powerpoint anchor of a shape is its top left corner.\r
+ Java graphics sets string coordinates by the baseline of the first character\r
+ so we need to shift down by the height of the textbox\r
+ */\r
+ txt.setAnchor(new Rectangle((int)x, (int)y, (int)width, (int)height));\r
+ }\r
+\r
+ /**\r
+ * Fills the interior of a <code>Shape</code> using the settings of the\r
+ * <code>Graphics2D</code> context. The rendering attributes applied\r
+ * include the <code>Clip</code>, <code>Transform</code>,\r
+ * <code>Paint</code>, and <code>Composite</code>.\r
+ * @param shape the <code>Shape</code> to be filled\r
+ * @see #setPaint\r
+ * @see java.awt.Graphics#setColor\r
+ * @see #_transform\r
+ * @see #setTransform\r
+ * @see #setComposite\r
+ * @see #clip\r
+ * @see #setClip\r
+ */\r
+ public void fill(Shape shape){\r
+ GeneralPath path = new GeneralPath(_transform.createTransformedShape(shape));\r
+ FreeformShape<?,?> p = _group.createFreeform();\r
+ p.setPath(path);\r
+ applyPaint(p);\r
+ p.setStrokeStyle(); //Fills must be "No Line"\r
+ }\r
+\r
+ /**\r
+ * Translates the origin of the graphics context to the point\r
+ * (<i>x</i>, <i>y</i>) in the current coordinate system.\r
+ * Modifies this graphics context so that its new origin corresponds\r
+ * to the point (<i>x</i>, <i>y</i>) in this graphics context's\r
+ * original coordinate system. All coordinates used in subsequent\r
+ * rendering operations on this graphics context will be relative\r
+ * to this new origin.\r
+ * @param x the <i>x</i> coordinate.\r
+ * @param y the <i>y</i> coordinate.\r
+ */\r
+ public void translate(int x, int y){\r
+ _transform.translate(x, y);\r
+ }\r
+\r
+ /**\r
+ * Intersects the current <code>Clip</code> with the interior of the\r
+ * specified <code>Shape</code> and sets the <code>Clip</code> to the\r
+ * resulting intersection. The specified <code>Shape</code> is\r
+ * transformed with the current <code>Graphics2D</code>\r
+ * <code>Transform</code> before being intersected with the current\r
+ * <code>Clip</code>. This method is used to make the current\r
+ * <code>Clip</code> smaller.\r
+ * To make the <code>Clip</code> larger, use <code>setClip</code>.\r
+ * The <i>user clip</i> modified by this method is independent of the\r
+ * clipping associated with device bounds and visibility. If no clip has\r
+ * previously been set, or if the clip has been cleared using\r
+ * {@link java.awt.Graphics#setClip(Shape) setClip} with a\r
+ * <code>null</code> argument, the specified <code>Shape</code> becomes\r
+ * the new user clip.\r
+ * @param s the <code>Shape</code> to be intersected with the current\r
+ * <code>Clip</code>. If <code>s</code> is <code>null</code>,\r
+ * this method clears the current <code>Clip</code>.\r
+ */\r
+ public void clip(Shape s){\r
+ if (log.check(POILogger.WARN)) {\r
+ log.log(POILogger.WARN, "Not implemented");\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Gets the current clipping area.\r
+ * This method returns the user clip, which is independent of the\r
+ * clipping associated with device bounds and window visibility.\r
+ * If no clip has previously been set, or if the clip has been\r
+ * cleared using <code>setClip(null)</code>, this method returns\r
+ * <code>null</code>.\r
+ * @return a <code>Shape</code> object representing the\r
+ * current clipping area, or <code>null</code> if\r
+ * no clip is set.\r
+ * @see java.awt.Graphics#getClipBounds()\r
+ * @see java.awt.Graphics#clipRect\r
+ * @see java.awt.Graphics#setClip(int, int, int, int)\r
+ * @see java.awt.Graphics#setClip(Shape)\r
+ * @since JDK1.1\r
+ */\r
+ public Shape getClip(){\r
+ if (log.check(POILogger.WARN)) {\r
+ log.log(POILogger.WARN, "Not implemented");\r
+ }\r
+ return null;\r
+ }\r
+\r
+ /**\r
+ * Concatenates the current <code>Graphics2D</code>\r
+ * <code>Transform</code> with a scaling transformation\r
+ * Subsequent rendering is resized according to the specified scaling\r
+ * factors relative to the previous scaling.\r
+ * This is equivalent to calling <code>transform(S)</code>, where S is an\r
+ * <code>AffineTransform</code> represented by the following matrix:\r
+ * <pre>\r
+ * [ sx 0 0 ]\r
+ * [ 0 sy 0 ]\r
+ * [ 0 0 1 ]\r
+ * </pre>\r
+ * @param sx the amount by which X coordinates in subsequent\r
+ * rendering operations are multiplied relative to previous\r
+ * rendering operations.\r
+ * @param sy the amount by which Y coordinates in subsequent\r
+ * rendering operations are multiplied relative to previous\r
+ * rendering operations.\r
+ */\r
+ public void scale(double sx, double sy){\r
+ _transform.scale(sx, sy);\r
+ }\r
+\r
+ /**\r
+ * Draws an outlined round-cornered rectangle using this graphics\r
+ * context's current color. The left and right edges of the rectangle\r
+ * are at <code>x</code> and <code>x + width</code>,\r
+ * respectively. The top and bottom edges of the rectangle are at\r
+ * <code>y</code> and <code>y + height</code>.\r
+ * @param x the <i>x</i> coordinate of the rectangle to be drawn.\r
+ * @param y the <i>y</i> coordinate of the rectangle to be drawn.\r
+ * @param width the width of the rectangle to be drawn.\r
+ * @param height the height of the rectangle to be drawn.\r
+ * @param arcWidth the horizontal diameter of the arc\r
+ * at the four corners.\r
+ * @param arcHeight the vertical diameter of the arc\r
+ * at the four corners.\r
+ * @see java.awt.Graphics#fillRoundRect\r
+ */\r
+ public void drawRoundRect(int x, int y, int width, int height,\r
+ int arcWidth, int arcHeight){\r
+ RoundRectangle2D rect = new RoundRectangle2D.Float(x, y, width, height, arcWidth, arcHeight);\r
+ draw(rect);\r
+ }\r
+\r
+ /**\r
+ * Draws the text given by the specified string, using this\r
+ * graphics context's current font and color. The baseline of the\r
+ * first character is at position (<i>x</i>, <i>y</i>) in this\r
+ * graphics context's coordinate system.\r
+ * @param str the string to be drawn.\r
+ * @param x the <i>x</i> coordinate.\r
+ * @param y the <i>y</i> coordinate.\r
+ * @see java.awt.Graphics#drawBytes\r
+ * @see java.awt.Graphics#drawChars\r
+ */\r
+ public void drawString(String str, int x, int y){\r
+ drawString(str, (float)x, (float)y);\r
+ }\r
+\r
+ /**\r
+ * Fills an oval bounded by the specified rectangle with the\r
+ * current color.\r
+ * @param x the <i>x</i> coordinate of the upper left corner\r
+ * of the oval to be filled.\r
+ * @param y the <i>y</i> coordinate of the upper left corner\r
+ * of the oval to be filled.\r
+ * @param width the width of the oval to be filled.\r
+ * @param height the height of the oval to be filled.\r
+ * @see java.awt.Graphics#drawOval\r
+ */\r
+ public void fillOval(int x, int y, int width, int height){\r
+ Ellipse2D oval = new Ellipse2D.Float(x, y, width, height);\r
+ fill(oval);\r
+ }\r
+\r
+ /**\r
+ * Fills the specified rounded corner rectangle with the current color.\r
+ * The left and right edges of the rectangle\r
+ * are at <code>x</code> and <code>x + width - 1</code>,\r
+ * respectively. The top and bottom edges of the rectangle are at\r
+ * <code>y</code> and <code>y + height - 1</code>.\r
+ * @param x the <i>x</i> coordinate of the rectangle to be filled.\r
+ * @param y the <i>y</i> coordinate of the rectangle to be filled.\r
+ * @param width the width of the rectangle to be filled.\r
+ * @param height the height of the rectangle to be filled.\r
+ * @param arcWidth the horizontal diameter\r
+ * of the arc at the four corners.\r
+ * @param arcHeight the vertical diameter\r
+ * of the arc at the four corners.\r
+ * @see java.awt.Graphics#drawRoundRect\r
+ */\r
+ public void fillRoundRect(int x, int y, int width, int height,\r
+ int arcWidth, int arcHeight){\r
+\r
+ RoundRectangle2D rect = new RoundRectangle2D.Float(x, y, width, height, arcWidth, arcHeight);\r
+ fill(rect);\r
+ }\r
+\r
+ /**\r
+ * Fills a circular or elliptical arc covering the specified rectangle.\r
+ * <p>\r
+ * The resulting arc begins at <code>startAngle</code> and extends\r
+ * for <code>arcAngle</code> degrees.\r
+ * Angles are interpreted such that 0 degrees\r
+ * is at the 3 o'clock position.\r
+ * A positive value indicates a counter-clockwise rotation\r
+ * while a negative value indicates a clockwise rotation.\r
+ * <p>\r
+ * The center of the arc is the center of the rectangle whose origin\r
+ * is (<i>x</i>, <i>y</i>) and whose size is specified by the\r
+ * <code>width</code> and <code>height</code> arguments.\r
+ * <p>\r
+ * The resulting arc covers an area\r
+ * <code>width + 1</code> pixels wide\r
+ * by <code>height + 1</code> pixels tall.\r
+ * <p>\r
+ * The angles are specified relative to the non-square extents of\r
+ * the bounding rectangle such that 45 degrees always falls on the\r
+ * line from the center of the ellipse to the upper right corner of\r
+ * the bounding rectangle. As a result, if the bounding rectangle is\r
+ * noticeably longer in one axis than the other, the angles to the\r
+ * start and end of the arc segment will be skewed farther along the\r
+ * longer axis of the bounds.\r
+ * @param x the <i>x</i> coordinate of the\r
+ * upper-left corner of the arc to be filled.\r
+ * @param y the <i>y</i> coordinate of the\r
+ * upper-left corner of the arc to be filled.\r
+ * @param width the width of the arc to be filled.\r
+ * @param height the height of the arc to be filled.\r
+ * @param startAngle the beginning angle.\r
+ * @param arcAngle the angular extent of the arc,\r
+ * relative to the start angle.\r
+ * @see java.awt.Graphics#drawArc\r
+ */\r
+ public void fillArc(int x, int y, int width, int height,\r
+ int startAngle, int arcAngle){\r
+ Arc2D arc = new Arc2D.Float(x, y, width, height, startAngle, arcAngle, Arc2D.PIE);\r
+ fill(arc);\r
+ }\r
+\r
+ /**\r
+ * Draws the outline of a circular or elliptical arc\r
+ * covering the specified rectangle.\r
+ * <p>\r
+ * The resulting arc begins at <code>startAngle</code> and extends\r
+ * for <code>arcAngle</code> degrees, using the current color.\r
+ * Angles are interpreted such that 0 degrees\r
+ * is at the 3 o'clock position.\r
+ * A positive value indicates a counter-clockwise rotation\r
+ * while a negative value indicates a clockwise rotation.\r
+ * <p>\r
+ * The center of the arc is the center of the rectangle whose origin\r
+ * is (<i>x</i>, <i>y</i>) and whose size is specified by the\r
+ * <code>width</code> and <code>height</code> arguments.\r
+ * <p>\r
+ * The resulting arc covers an area\r
+ * <code>width + 1</code> pixels wide\r
+ * by <code>height + 1</code> pixels tall.\r
+ * <p>\r
+ * The angles are specified relative to the non-square extents of\r
+ * the bounding rectangle such that 45 degrees always falls on the\r
+ * line from the center of the ellipse to the upper right corner of\r
+ * the bounding rectangle. As a result, if the bounding rectangle is\r
+ * noticeably longer in one axis than the other, the angles to the\r
+ * start and end of the arc segment will be skewed farther along the\r
+ * longer axis of the bounds.\r
+ * @param x the <i>x</i> coordinate of the\r
+ * upper-left corner of the arc to be drawn.\r
+ * @param y the <i>y</i> coordinate of the\r
+ * upper-left corner of the arc to be drawn.\r
+ * @param width the width of the arc to be drawn.\r
+ * @param height the height of the arc to be drawn.\r
+ * @param startAngle the beginning angle.\r
+ * @param arcAngle the angular extent of the arc,\r
+ * relative to the start angle.\r
+ * @see java.awt.Graphics#fillArc\r
+ */\r
+ public void drawArc(int x, int y, int width, int height,\r
+ int startAngle, int arcAngle) {\r
+ Arc2D arc = new Arc2D.Float(x, y, width, height, startAngle, arcAngle, Arc2D.OPEN);\r
+ draw(arc);\r
+ }\r
+\r
+\r
+ /**\r
+ * Draws a sequence of connected lines defined by\r
+ * arrays of <i>x</i> and <i>y</i> coordinates.\r
+ * Each pair of (<i>x</i>, <i>y</i>) coordinates defines a point.\r
+ * The figure is not closed if the first point\r
+ * differs from the last point.\r
+ * @param xPoints an array of <i>x</i> points\r
+ * @param yPoints an array of <i>y</i> points\r
+ * @param nPoints the total number of points\r
+ * @see java.awt.Graphics#drawPolygon(int[], int[], int)\r
+ * @since JDK1.1\r
+ */\r
+ public void drawPolyline(int[] xPoints, int[] yPoints,\r
+ int nPoints){\r
+ if(nPoints > 0){\r
+ GeneralPath path = new GeneralPath();\r
+ path.moveTo(xPoints[0], yPoints[0]);\r
+ for(int i=1; i<nPoints; i++)\r
+ path.lineTo(xPoints[i], yPoints[i]);\r
+\r
+ draw(path);\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Draws the outline of an oval.\r
+ * The result is a circle or ellipse that fits within the\r
+ * rectangle specified by the <code>x</code>, <code>y</code>,\r
+ * <code>width</code>, and <code>height</code> arguments.\r
+ * <p>\r
+ * The oval covers an area that is\r
+ * <code>width + 1</code> pixels wide\r
+ * and <code>height + 1</code> pixels tall.\r
+ * @param x the <i>x</i> coordinate of the upper left\r
+ * corner of the oval to be drawn.\r
+ * @param y the <i>y</i> coordinate of the upper left\r
+ * corner of the oval to be drawn.\r
+ * @param width the width of the oval to be drawn.\r
+ * @param height the height of the oval to be drawn.\r
+ * @see java.awt.Graphics#fillOval\r
+ */\r
+ public void drawOval(int x, int y, int width, int height){\r
+ Ellipse2D oval = new Ellipse2D.Float(x, y, width, height);\r
+ draw(oval);\r
+ }\r
+\r
+ /**\r
+ * Draws as much of the specified image as is currently available.\r
+ * The image is drawn with its top-left corner at\r
+ * (<i>x</i>, <i>y</i>) in this graphics context's coordinate\r
+ * space. Transparent pixels are drawn in the specified\r
+ * background color.\r
+ * <p>\r
+ * This operation is equivalent to filling a rectangle of the\r
+ * width and height of the specified image with the given color and then\r
+ * drawing the image on top of it, but possibly more efficient.\r
+ * <p>\r
+ * This method returns immediately in all cases, even if the\r
+ * complete image has not yet been loaded, and it has not been dithered\r
+ * and converted for the current output device.\r
+ * <p>\r
+ * If the image has not yet been completely loaded, then\r
+ * <code>drawImage</code> returns <code>false</code>. As more of\r
+ * the image becomes available, the process that draws the image notifies\r
+ * the specified image observer.\r
+ * @param img the specified image to be drawn.\r
+ * @param x the <i>x</i> coordinate.\r
+ * @param y the <i>y</i> coordinate.\r
+ * @param bgcolor the background color to paint under the\r
+ * non-opaque portions of the image.\r
+ * @param observer object to be notified as more of\r
+ * the image is converted.\r
+ * @see java.awt.Image\r
+ * @see java.awt.image.ImageObserver\r
+ * @see java.awt.image.ImageObserver#imageUpdate(java.awt.Image, int, int, int, int, int)\r
+ */\r
+ public boolean drawImage(Image img, int x, int y,\r
+ Color bgcolor,\r
+ ImageObserver observer){\r
+ if (log.check(POILogger.WARN)) {\r
+ log.log(POILogger.WARN, "Not implemented");\r
+ }\r
+\r
+ return false;\r
+ }\r
+\r
+ /**\r
+ * Draws as much of the specified image as has already been scaled\r
+ * to fit inside the specified rectangle.\r
+ * <p>\r
+ * The image is drawn inside the specified rectangle of this\r
+ * graphics context's coordinate space, and is scaled if\r
+ * necessary. Transparent pixels are drawn in the specified\r
+ * background color.\r
+ * This operation is equivalent to filling a rectangle of the\r
+ * width and height of the specified image with the given color and then\r
+ * drawing the image on top of it, but possibly more efficient.\r
+ * <p>\r
+ * This method returns immediately in all cases, even if the\r
+ * entire image has not yet been scaled, dithered, and converted\r
+ * for the current output device.\r
+ * If the current output representation is not yet complete then\r
+ * <code>drawImage</code> returns <code>false</code>. As more of\r
+ * the image becomes available, the process that draws the image notifies\r
+ * the specified image observer.\r
+ * <p>\r
+ * A scaled version of an image will not necessarily be\r
+ * available immediately just because an unscaled version of the\r
+ * image has been constructed for this output device. Each size of\r
+ * the image may be cached separately and generated from the original\r
+ * data in a separate image production sequence.\r
+ * @param img the specified image to be drawn.\r
+ * @param x the <i>x</i> coordinate.\r
+ * @param y the <i>y</i> coordinate.\r
+ * @param width the width of the rectangle.\r
+ * @param height the height of the rectangle.\r
+ * @param bgcolor the background color to paint under the\r
+ * non-opaque portions of the image.\r
+ * @param observer object to be notified as more of\r
+ * the image is converted.\r
+ * @see java.awt.Image\r
+ * @see java.awt.image.ImageObserver\r
+ * @see java.awt.image.ImageObserver#imageUpdate(java.awt.Image, int, int, int, int, int)\r
+ */\r
+ public boolean drawImage(Image img, int x, int y,\r
+ int width, int height,\r
+ Color bgcolor,\r
+ ImageObserver observer){\r
+ if (log.check(POILogger.WARN)) {\r
+ log.log(POILogger.WARN, "Not implemented");\r
+ }\r
+\r
+ return false;\r
+ }\r
+\r
+\r
+ /**\r
+ * Draws as much of the specified area of the specified image as is\r
+ * currently available, scaling it on the fly to fit inside the\r
+ * specified area of the destination drawable surface. Transparent pixels\r
+ * do not affect whatever pixels are already there.\r
+ * <p>\r
+ * This method returns immediately in all cases, even if the\r
+ * image area to be drawn has not yet been scaled, dithered, and converted\r
+ * for the current output device.\r
+ * If the current output representation is not yet complete then\r
+ * <code>drawImage</code> returns <code>false</code>. As more of\r
+ * the image becomes available, the process that draws the image notifies\r
+ * the specified image observer.\r
+ * <p>\r
+ * This method always uses the unscaled version of the image\r
+ * to render the scaled rectangle and performs the required\r
+ * scaling on the fly. It does not use a cached, scaled version\r
+ * of the image for this operation. Scaling of the image from source\r
+ * to destination is performed such that the first coordinate\r
+ * of the source rectangle is mapped to the first coordinate of\r
+ * the destination rectangle, and the second source coordinate is\r
+ * mapped to the second destination coordinate. The subimage is\r
+ * scaled and flipped as needed to preserve those mappings.\r
+ * @param img the specified image to be drawn\r
+ * @param dx1 the <i>x</i> coordinate of the first corner of the\r
+ * destination rectangle.\r
+ * @param dy1 the <i>y</i> coordinate of the first corner of the\r
+ * destination rectangle.\r
+ * @param dx2 the <i>x</i> coordinate of the second corner of the\r
+ * destination rectangle.\r
+ * @param dy2 the <i>y</i> coordinate of the second corner of the\r
+ * destination rectangle.\r
+ * @param sx1 the <i>x</i> coordinate of the first corner of the\r
+ * source rectangle.\r
+ * @param sy1 the <i>y</i> coordinate of the first corner of the\r
+ * source rectangle.\r
+ * @param sx2 the <i>x</i> coordinate of the second corner of the\r
+ * source rectangle.\r
+ * @param sy2 the <i>y</i> coordinate of the second corner of the\r
+ * source rectangle.\r
+ * @param observer object to be notified as more of the image is\r
+ * scaled and converted.\r
+ * @see java.awt.Image\r
+ * @see java.awt.image.ImageObserver\r
+ * @see java.awt.image.ImageObserver#imageUpdate(java.awt.Image, int, int, int, int, int)\r
+ * @since JDK1.1\r
+ */\r
+ public boolean drawImage(Image img,\r
+ int dx1, int dy1, int dx2, int dy2,\r
+ int sx1, int sy1, int sx2, int sy2,\r
+ ImageObserver observer){\r
+ if (log.check(POILogger.WARN)) {\r
+ log.log(POILogger.WARN, "Not implemented");\r
+ }\r
+ return false;\r
+ }\r
+\r
+ /**\r
+ * Draws as much of the specified area of the specified image as is\r
+ * currently available, scaling it on the fly to fit inside the\r
+ * specified area of the destination drawable surface.\r
+ * <p>\r
+ * Transparent pixels are drawn in the specified background color.\r
+ * This operation is equivalent to filling a rectangle of the\r
+ * width and height of the specified image with the given color and then\r
+ * drawing the image on top of it, but possibly more efficient.\r
+ * <p>\r
+ * This method returns immediately in all cases, even if the\r
+ * image area to be drawn has not yet been scaled, dithered, and converted\r
+ * for the current output device.\r
+ * If the current output representation is not yet complete then\r
+ * <code>drawImage</code> returns <code>false</code>. As more of\r
+ * the image becomes available, the process that draws the image notifies\r
+ * the specified image observer.\r
+ * <p>\r
+ * This method always uses the unscaled version of the image\r
+ * to render the scaled rectangle and performs the required\r
+ * scaling on the fly. It does not use a cached, scaled version\r
+ * of the image for this operation. Scaling of the image from source\r
+ * to destination is performed such that the first coordinate\r
+ * of the source rectangle is mapped to the first coordinate of\r
+ * the destination rectangle, and the second source coordinate is\r
+ * mapped to the second destination coordinate. The subimage is\r
+ * scaled and flipped as needed to preserve those mappings.\r
+ * @param img the specified image to be drawn\r
+ * @param dx1 the <i>x</i> coordinate of the first corner of the\r
+ * destination rectangle.\r
+ * @param dy1 the <i>y</i> coordinate of the first corner of the\r
+ * destination rectangle.\r
+ * @param dx2 the <i>x</i> coordinate of the second corner of the\r
+ * destination rectangle.\r
+ * @param dy2 the <i>y</i> coordinate of the second corner of the\r
+ * destination rectangle.\r
+ * @param sx1 the <i>x</i> coordinate of the first corner of the\r
+ * source rectangle.\r
+ * @param sy1 the <i>y</i> coordinate of the first corner of the\r
+ * source rectangle.\r
+ * @param sx2 the <i>x</i> coordinate of the second corner of the\r
+ * source rectangle.\r
+ * @param sy2 the <i>y</i> coordinate of the second corner of the\r
+ * source rectangle.\r
+ * @param bgcolor the background color to paint under the\r
+ * non-opaque portions of the image.\r
+ * @param observer object to be notified as more of the image is\r
+ * scaled and converted.\r
+ * @see java.awt.Image\r
+ * @see java.awt.image.ImageObserver\r
+ * @see java.awt.image.ImageObserver#imageUpdate(java.awt.Image, int, int, int, int, int)\r
+ * @since JDK1.1\r
+ */\r
+ public boolean drawImage(Image img,\r
+ int dx1, int dy1, int dx2, int dy2,\r
+ int sx1, int sy1, int sx2, int sy2,\r
+ Color bgcolor,\r
+ ImageObserver observer){\r
+ if (log.check(POILogger.WARN)) {\r
+ log.log(POILogger.WARN, "Not implemented");\r
+ }\r
+ return false;\r
+ }\r
+\r
+ /**\r
+ * Draws as much of the specified image as is currently available.\r
+ * The image is drawn with its top-left corner at\r
+ * (<i>x</i>, <i>y</i>) in this graphics context's coordinate\r
+ * space. Transparent pixels in the image do not affect whatever\r
+ * pixels are already there.\r
+ * <p>\r
+ * This method returns immediately in all cases, even if the\r
+ * complete image has not yet been loaded, and it has not been dithered\r
+ * and converted for the current output device.\r
+ * <p>\r
+ * If the image has completely loaded and its pixels are\r
+ * no longer being changed, then\r
+ * <code>drawImage</code> returns <code>true</code>.\r
+ * Otherwise, <code>drawImage</code> returns <code>false</code>\r
+ * and as more of\r
+ * the image becomes available\r
+ * or it is time to draw another frame of animation,\r
+ * the process that loads the image notifies\r
+ * the specified image observer.\r
+ * @param img the specified image to be drawn. This method does\r
+ * nothing if <code>img</code> is null.\r
+ * @param x the <i>x</i> coordinate.\r
+ * @param y the <i>y</i> coordinate.\r
+ * @param observer object to be notified as more of\r
+ * the image is converted.\r
+ * @return <code>false</code> if the image pixels are still changing;\r
+ * <code>true</code> otherwise.\r
+ * @see java.awt.Image\r
+ * @see java.awt.image.ImageObserver\r
+ * @see java.awt.image.ImageObserver#imageUpdate(java.awt.Image, int, int, int, int, int)\r
+ */\r
+ public boolean drawImage(Image img, int x, int y,\r
+ ImageObserver observer) {\r
+ if (log.check(POILogger.WARN)) {\r
+ log.log(POILogger.WARN, "Not implemented");\r
+ }\r
+ return false;\r
+ }\r
+\r
+ /**\r
+ * Disposes of this graphics context and releases\r
+ * any system resources that it is using.\r
+ * A <code>Graphics</code> object cannot be used after\r
+ * <code>dispose</code>has been called.\r
+ * <p>\r
+ * When a Java program runs, a large number of <code>Graphics</code>\r
+ * objects can be created within a short time frame.\r
+ * Although the finalization process of the garbage collector\r
+ * also disposes of the same system resources, it is preferable\r
+ * to manually free the associated resources by calling this\r
+ * method rather than to rely on a finalization process which\r
+ * may not run to completion for a long period of time.\r
+ * <p>\r
+ * Graphics objects which are provided as arguments to the\r
+ * <code>paint</code> and <code>update</code> methods\r
+ * of components are automatically released by the system when\r
+ * those methods return. For efficiency, programmers should\r
+ * call <code>dispose</code> when finished using\r
+ * a <code>Graphics</code> object only if it was created\r
+ * directly from a component or another <code>Graphics</code> object.\r
+ * @see java.awt.Graphics#finalize\r
+ * @see java.awt.Component#paint\r
+ * @see java.awt.Component#update\r
+ * @see java.awt.Component#getGraphics\r
+ * @see java.awt.Graphics#create\r
+ */\r
+ public void dispose() {\r
+ ;\r
+ }\r
+\r
+ /**\r
+ * Draws a line, using the current color, between the points\r
+ * <code>(x1, y1)</code> and <code>(x2, y2)</code>\r
+ * in this graphics context's coordinate system.\r
+ * @param x1 the first point's <i>x</i> coordinate.\r
+ * @param y1 the first point's <i>y</i> coordinate.\r
+ * @param x2 the second point's <i>x</i> coordinate.\r
+ * @param y2 the second point's <i>y</i> coordinate.\r
+ */\r
+ public void drawLine(int x1, int y1, int x2, int y2){\r
+ Line2D line = new Line2D.Float(x1, y1, x2, y2);\r
+ draw(line);\r
+ }\r
+\r
+ /**\r
+ * Fills a closed polygon defined by\r
+ * arrays of <i>x</i> and <i>y</i> coordinates.\r
+ * <p>\r
+ * This method draws the polygon defined by <code>nPoint</code> line\r
+ * segments, where the first <code>nPoint - 1</code>\r
+ * line segments are line segments from\r
+ * <code>(xPoints[i - 1], yPoints[i - 1])</code>\r
+ * to <code>(xPoints[i], yPoints[i])</code>, for\r
+ * 1 ≤ <i>i</i> ≤ <code>nPoints</code>.\r
+ * The figure is automatically closed by drawing a line connecting\r
+ * the final point to the first point, if those points are different.\r
+ * <p>\r
+ * The area inside the polygon is defined using an\r
+ * even-odd fill rule, also known as the alternating rule.\r
+ * @param xPoints a an array of <code>x</code> coordinates.\r
+ * @param yPoints a an array of <code>y</code> coordinates.\r
+ * @param nPoints a the total number of points.\r
+ * @see java.awt.Graphics#drawPolygon(int[], int[], int)\r
+ */\r
+ public void fillPolygon(int[] xPoints, int[] yPoints,\r
+ int nPoints){\r
+ java.awt.Polygon polygon = new java.awt.Polygon(xPoints, yPoints, nPoints);\r
+ fill(polygon);\r
+ }\r
+\r
+ /**\r
+ * Fills the specified rectangle.\r
+ * The left and right edges of the rectangle are at\r
+ * <code>x</code> and <code>x + width - 1</code>.\r
+ * The top and bottom edges are at\r
+ * <code>y</code> and <code>y + height - 1</code>.\r
+ * The resulting rectangle covers an area\r
+ * <code>width</code> pixels wide by\r
+ * <code>height</code> pixels tall.\r
+ * The rectangle is filled using the graphics context's current color.\r
+ * @param x the <i>x</i> coordinate\r
+ * of the rectangle to be filled.\r
+ * @param y the <i>y</i> coordinate\r
+ * of the rectangle to be filled.\r
+ * @param width the width of the rectangle to be filled.\r
+ * @param height the height of the rectangle to be filled.\r
+ * @see java.awt.Graphics#clearRect\r
+ * @see java.awt.Graphics#drawRect\r
+ */\r
+ public void fillRect(int x, int y, int width, int height){\r
+ Rectangle rect = new Rectangle(x, y, width, height);\r
+ fill(rect);\r
+ }\r
+\r
+ /**\r
+ * Draws the outline of the specified rectangle.\r
+ * The left and right edges of the rectangle are at\r
+ * <code>x</code> and <code>x + width</code>.\r
+ * The top and bottom edges are at\r
+ * <code>y</code> and <code>y + height</code>.\r
+ * The rectangle is drawn using the graphics context's current color.\r
+ * @param x the <i>x</i> coordinate\r
+ * of the rectangle to be drawn.\r
+ * @param y the <i>y</i> coordinate\r
+ * of the rectangle to be drawn.\r
+ * @param width the width of the rectangle to be drawn.\r
+ * @param height the height of the rectangle to be drawn.\r
+ * @see java.awt.Graphics#fillRect\r
+ * @see java.awt.Graphics#clearRect\r
+ */\r
+ public void drawRect(int x, int y, int width, int height) {\r
+ Rectangle rect = new Rectangle(x, y, width, height);\r
+ draw(rect);\r
+ }\r
+\r
+ /**\r
+ * Draws a closed polygon defined by\r
+ * arrays of <i>x</i> and <i>y</i> coordinates.\r
+ * Each pair of (<i>x</i>, <i>y</i>) coordinates defines a point.\r
+ * <p>\r
+ * This method draws the polygon defined by <code>nPoint</code> line\r
+ * segments, where the first <code>nPoint - 1</code>\r
+ * line segments are line segments from\r
+ * <code>(xPoints[i - 1], yPoints[i - 1])</code>\r
+ * to <code>(xPoints[i], yPoints[i])</code>, for\r
+ * 1 ≤ <i>i</i> ≤ <code>nPoints</code>.\r
+ * The figure is automatically closed by drawing a line connecting\r
+ * the final point to the first point, if those points are different.\r
+ * @param xPoints a an array of <code>x</code> coordinates.\r
+ * @param yPoints a an array of <code>y</code> coordinates.\r
+ * @param nPoints a the total number of points.\r
+ * @see java.awt.Graphics#fillPolygon(int[],int[],int)\r
+ * @see java.awt.Graphics#drawPolyline\r
+ */\r
+ public void drawPolygon(int[] xPoints, int[] yPoints,\r
+ int nPoints){\r
+ java.awt.Polygon polygon = new java.awt.Polygon(xPoints, yPoints, nPoints);\r
+ draw(polygon);\r
+ }\r
+\r
+ /**\r
+ * Intersects the current clip with the specified rectangle.\r
+ * The resulting clipping area is the intersection of the current\r
+ * clipping area and the specified rectangle. If there is no\r
+ * current clipping area, either because the clip has never been\r
+ * set, or the clip has been cleared using <code>setClip(null)</code>,\r
+ * the specified rectangle becomes the new clip.\r
+ * This method sets the user clip, which is independent of the\r
+ * clipping associated with device bounds and window visibility.\r
+ * This method can only be used to make the current clip smaller.\r
+ * To set the current clip larger, use any of the setClip methods.\r
+ * Rendering operations have no effect outside of the clipping area.\r
+ * @param x the x coordinate of the rectangle to intersect the clip with\r
+ * @param y the y coordinate of the rectangle to intersect the clip with\r
+ * @param width the width of the rectangle to intersect the clip with\r
+ * @param height the height of the rectangle to intersect the clip with\r
+ * @see #setClip(int, int, int, int)\r
+ * @see #setClip(Shape)\r
+ */\r
+ public void clipRect(int x, int y, int width, int height){\r
+ clip(new Rectangle(x, y, width, height));\r
+ }\r
+\r
+ /**\r
+ * Sets the current clipping area to an arbitrary clip shape.\r
+ * Not all objects that implement the <code>Shape</code>\r
+ * interface can be used to set the clip. The only\r
+ * <code>Shape</code> objects that are guaranteed to be\r
+ * supported are <code>Shape</code> objects that are\r
+ * obtained via the <code>getClip</code> method and via\r
+ * <code>Rectangle</code> objects. This method sets the\r
+ * user clip, which is independent of the clipping associated\r
+ * with device bounds and window visibility.\r
+ * @param clip the <code>Shape</code> to use to set the clip\r
+ * @see java.awt.Graphics#getClip()\r
+ * @see java.awt.Graphics#clipRect\r
+ * @see java.awt.Graphics#setClip(int, int, int, int)\r
+ * @since JDK1.1\r
+ */\r
+ public void setClip(Shape clip) {\r
+ if (log.check(POILogger.WARN)) {\r
+ log.log(POILogger.WARN, "Not implemented");\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Returns the bounding rectangle of the current clipping area.\r
+ * This method refers to the user clip, which is independent of the\r
+ * clipping associated with device bounds and window visibility.\r
+ * If no clip has previously been set, or if the clip has been\r
+ * cleared using <code>setClip(null)</code>, this method returns\r
+ * <code>null</code>.\r
+ * The coordinates in the rectangle are relative to the coordinate\r
+ * system origin of this graphics context.\r
+ * @return the bounding rectangle of the current clipping area,\r
+ * or <code>null</code> if no clip is set.\r
+ * @see java.awt.Graphics#getClip\r
+ * @see java.awt.Graphics#clipRect\r
+ * @see java.awt.Graphics#setClip(int, int, int, int)\r
+ * @see java.awt.Graphics#setClip(Shape)\r
+ * @since JDK1.1\r
+ */\r
+ public Rectangle getClipBounds(){\r
+ Shape c = getClip();\r
+ if (c==null) {\r
+ return null;\r
+ }\r
+ return c.getBounds();\r
+ }\r
+\r
+ /**\r
+ * Draws the text given by the specified iterator, using this\r
+ * graphics context's current color. The iterator has to specify a font\r
+ * for each character. The baseline of the\r
+ * first character is at position (<i>x</i>, <i>y</i>) in this\r
+ * graphics context's coordinate system.\r
+ * @param iterator the iterator whose text is to be drawn\r
+ * @param x the <i>x</i> coordinate.\r
+ * @param y the <i>y</i> coordinate.\r
+ * @see java.awt.Graphics#drawBytes\r
+ * @see java.awt.Graphics#drawChars\r
+ */\r
+ public void drawString(AttributedCharacterIterator iterator,\r
+ int x, int y){\r
+ drawString(iterator, (float)x, (float)y);\r
+ }\r
+\r
+ /**\r
+ * Clears the specified rectangle by filling it with the background\r
+ * color of the current drawing surface. This operation does not\r
+ * use the current paint mode.\r
+ * <p>\r
+ * Beginning with Java 1.1, the background color\r
+ * of offscreen images may be system dependent. Applications should\r
+ * use <code>setColor</code> followed by <code>fillRect</code> to\r
+ * ensure that an offscreen image is cleared to a specific color.\r
+ * @param x the <i>x</i> coordinate of the rectangle to clear.\r
+ * @param y the <i>y</i> coordinate of the rectangle to clear.\r
+ * @param width the width of the rectangle to clear.\r
+ * @param height the height of the rectangle to clear.\r
+ * @see java.awt.Graphics#fillRect(int, int, int, int)\r
+ * @see java.awt.Graphics#drawRect\r
+ * @see java.awt.Graphics#setColor(java.awt.Color)\r
+ * @see java.awt.Graphics#setPaintMode\r
+ * @see java.awt.Graphics#setXORMode(java.awt.Color)\r
+ */\r
+ public void clearRect(int x, int y, int width, int height) {\r
+ Paint paint = getPaint();\r
+ setColor(getBackground());\r
+ fillRect(x, y, width, height);\r
+ setPaint(paint);\r
+ }\r
+\r
+ public void copyArea(int x, int y, int width, int height, int dx, int dy) {\r
+ ;\r
+ }\r
+\r
+ /**\r
+ * Sets the current clip to the rectangle specified by the given\r
+ * coordinates. This method sets the user clip, which is\r
+ * independent of the clipping associated with device bounds\r
+ * and window visibility.\r
+ * Rendering operations have no effect outside of the clipping area.\r
+ * @param x the <i>x</i> coordinate of the new clip rectangle.\r
+ * @param y the <i>y</i> coordinate of the new clip rectangle.\r
+ * @param width the width of the new clip rectangle.\r
+ * @param height the height of the new clip rectangle.\r
+ * @see java.awt.Graphics#clipRect\r
+ * @see java.awt.Graphics#setClip(Shape)\r
+ * @since JDK1.1\r
+ */\r
+ public void setClip(int x, int y, int width, int height){\r
+ setClip(new Rectangle(x, y, width, height));\r
+ }\r
+\r
+ /**\r
+ * Concatenates the current <code>Graphics2D</code>\r
+ * <code>Transform</code> with a rotation transform.\r
+ * Subsequent rendering is rotated by the specified radians relative\r
+ * to the previous origin.\r
+ * This is equivalent to calling <code>transform(R)</code>, where R is an\r
+ * <code>AffineTransform</code> represented by the following matrix:\r
+ * <pre>\r
+ * [ cos(theta) -sin(theta) 0 ]\r
+ * [ sin(theta) cos(theta) 0 ]\r
+ * [ 0 0 1 ]\r
+ * </pre>\r
+ * Rotating with a positive angle theta rotates points on the positive\r
+ * x axis toward the positive y axis.\r
+ * @param theta the angle of rotation in radians\r
+ */\r
+ public void rotate(double theta){\r
+ _transform.rotate(theta);\r
+ }\r
+\r
+ /**\r
+ * Concatenates the current <code>Graphics2D</code>\r
+ * <code>Transform</code> with a translated rotation\r
+ * transform. Subsequent rendering is transformed by a transform\r
+ * which is constructed by translating to the specified location,\r
+ * rotating by the specified radians, and translating back by the same\r
+ * amount as the original translation. This is equivalent to the\r
+ * following sequence of calls:\r
+ * <pre>\r
+ * translate(x, y);\r
+ * rotate(theta);\r
+ * translate(-x, -y);\r
+ * </pre>\r
+ * Rotating with a positive angle theta rotates points on the positive\r
+ * x axis toward the positive y axis.\r
+ * @param theta the angle of rotation in radians\r
+ * @param x x coordinate of the origin of the rotation\r
+ * @param y y coordinate of the origin of the rotation\r
+ */\r
+ public void rotate(double theta, double x, double y){\r
+ _transform.rotate(theta, x, y);\r
+ }\r
+\r
+ /**\r
+ * Concatenates the current <code>Graphics2D</code>\r
+ * <code>Transform</code> with a shearing transform.\r
+ * Subsequent renderings are sheared by the specified\r
+ * multiplier relative to the previous position.\r
+ * This is equivalent to calling <code>transform(SH)</code>, where SH\r
+ * is an <code>AffineTransform</code> represented by the following\r
+ * matrix:\r
+ * <pre>\r
+ * [ 1 shx 0 ]\r
+ * [ shy 1 0 ]\r
+ * [ 0 0 1 ]\r
+ * </pre>\r
+ * @param shx the multiplier by which coordinates are shifted in\r
+ * the positive X axis direction as a function of their Y coordinate\r
+ * @param shy the multiplier by which coordinates are shifted in\r
+ * the positive Y axis direction as a function of their X coordinate\r
+ */\r
+ public void shear(double shx, double shy){\r
+ _transform.shear(shx, shy);\r
+ }\r
+\r
+ /**\r
+ * Get the rendering context of the <code>Font</code> within this\r
+ * <code>Graphics2D</code> context.\r
+ * The {@link FontRenderContext}\r
+ * encapsulates application hints such as anti-aliasing and\r
+ * fractional metrics, as well as target device specific information\r
+ * such as dots-per-inch. This information should be provided by the\r
+ * application when using objects that perform typographical\r
+ * formatting, such as <code>Font</code> and\r
+ * <code>TextLayout</code>. This information should also be provided\r
+ * by applications that perform their own layout and need accurate\r
+ * measurements of various characteristics of glyphs such as advance\r
+ * and line height when various rendering hints have been applied to\r
+ * the text rendering.\r
+ *\r
+ * @return a reference to an instance of FontRenderContext.\r
+ * @see java.awt.font.FontRenderContext\r
+ * @see java.awt.Font#createGlyphVector(FontRenderContext,char[])\r
+ * @see java.awt.font.TextLayout\r
+ * @since JDK1.2\r
+ */\r
+ public FontRenderContext getFontRenderContext() {\r
+ boolean isAntiAliased = RenderingHints.VALUE_TEXT_ANTIALIAS_ON.equals(\r
+ getRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING));\r
+ boolean usesFractionalMetrics = RenderingHints.VALUE_FRACTIONALMETRICS_ON.equals(\r
+ getRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS));\r
+\r
+\r
+ return new FontRenderContext(new AffineTransform(), isAntiAliased, usesFractionalMetrics);\r
+ }\r
+\r
+ /**\r
+ * Composes an <code>AffineTransform</code> object with the\r
+ * <code>Transform</code> in this <code>Graphics2D</code> according\r
+ * to the rule last-specified-first-applied. If the current\r
+ * <code>Transform</code> is Cx, the result of composition\r
+ * with Tx is a new <code>Transform</code> Cx'. Cx' becomes the\r
+ * current <code>Transform</code> for this <code>Graphics2D</code>.\r
+ * Transforming a point p by the updated <code>Transform</code> Cx' is\r
+ * equivalent to first transforming p by Tx and then transforming\r
+ * the result by the original <code>Transform</code> Cx. In other\r
+ * words, Cx'(p) = Cx(Tx(p)). A copy of the Tx is made, if necessary,\r
+ * so further modifications to Tx do not affect rendering.\r
+ * @param Tx the <code>AffineTransform</code> object to be composed with\r
+ * the current <code>Transform</code>\r
+ * @see #setTransform\r
+ * @see AffineTransform\r
+ */\r
+ public void transform(AffineTransform Tx) {\r
+ _transform.concatenate(Tx);\r
+ }\r
+\r
+ /**\r
+ * Renders a <code>BufferedImage</code> that is\r
+ * filtered with a\r
+ * {@link BufferedImageOp}.\r
+ * The rendering attributes applied include the <code>Clip</code>,\r
+ * <code>Transform</code>\r
+ * and <code>Composite</code> attributes. This is equivalent to:\r
+ * <pre>\r
+ * img1 = op.filter(img, null);\r
+ * drawImage(img1, new AffineTransform(1f,0f,0f,1f,x,y), null);\r
+ * </pre>\r
+ * @param img the <code>BufferedImage</code> to be rendered\r
+ * @param op the filter to be applied to the image before rendering\r
+ * @param x the x coordinate in user space where the image is rendered\r
+ * @param y the y coordinate in user space where the image is rendered\r
+ * @see #_transform\r
+ * @see #setTransform\r
+ * @see #setComposite\r
+ * @see #clip\r
+ * @see #setClip(Shape)\r
+ */\r
+ public void drawImage(BufferedImage img,\r
+ BufferedImageOp op,\r
+ int x,\r
+ int y){\r
+ img = op.filter(img, null);\r
+ drawImage(img, x, y, null);\r
+ }\r
+\r
+ /**\r
+ * Sets the background color for the <code>Graphics2D</code> context.\r
+ * The background color is used for clearing a region.\r
+ * When a <code>Graphics2D</code> is constructed for a\r
+ * <code>Component</code>, the background color is\r
+ * inherited from the <code>Component</code>. Setting the background color\r
+ * in the <code>Graphics2D</code> context only affects the subsequent\r
+ * <code>clearRect</code> calls and not the background color of the\r
+ * <code>Component</code>. To change the background\r
+ * of the <code>Component</code>, use appropriate methods of\r
+ * the <code>Component</code>.\r
+ * @param color the background color that isused in\r
+ * subsequent calls to <code>clearRect</code>\r
+ * @see #getBackground\r
+ * @see java.awt.Graphics#clearRect\r
+ */\r
+ public void setBackground(Color color) {\r
+ if(color == null)\r
+ return;\r
+\r
+ _background = color;\r
+ }\r
+\r
+ /**\r
+ * Returns the background color used for clearing a region.\r
+ * @return the current <code>Graphics2D</code> <code>Color</code>,\r
+ * which defines the background color.\r
+ * @see #setBackground\r
+ */\r
+ public Color getBackground(){\r
+ return _background;\r
+ }\r
+\r
+ /**\r
+ * Sets the <code>Composite</code> for the <code>Graphics2D</code> context.\r
+ * The <code>Composite</code> is used in all drawing methods such as\r
+ * <code>drawImage</code>, <code>drawString</code>, <code>draw</code>,\r
+ * and <code>fill</code>. It specifies how new pixels are to be combined\r
+ * with the existing pixels on the graphics device during the rendering\r
+ * process.\r
+ * <p>If this <code>Graphics2D</code> context is drawing to a\r
+ * <code>Component</code> on the display screen and the\r
+ * <code>Composite</code> is a custom object rather than an\r
+ * instance of the <code>AlphaComposite</code> class, and if\r
+ * there is a security manager, its <code>checkPermission</code>\r
+ * method is called with an <code>AWTPermission("readDisplayPixels")</code>\r
+ * permission.\r
+ *\r
+ * @param comp the <code>Composite</code> object to be used for rendering\r
+ * @throws SecurityException\r
+ * if a custom <code>Composite</code> object is being\r
+ * used to render to the screen and a security manager\r
+ * is set and its <code>checkPermission</code> method\r
+ * does not allow the operation.\r
+ * @see java.awt.Graphics#setXORMode\r
+ * @see java.awt.Graphics#setPaintMode\r
+ * @see java.awt.AlphaComposite\r
+ */\r
+ public void setComposite(Composite comp){\r
+ if (log.check(POILogger.WARN)) {\r
+ log.log(POILogger.WARN, "Not implemented");\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Returns the current <code>Composite</code> in the\r
+ * <code>Graphics2D</code> context.\r
+ * @return the current <code>Graphics2D</code> <code>Composite</code>,\r
+ * which defines a compositing style.\r
+ * @see #setComposite\r
+ */\r
+ public Composite getComposite(){\r
+ if (log.check(POILogger.WARN)) {\r
+ log.log(POILogger.WARN, "Not implemented");\r
+ }\r
+ return null;\r
+ }\r
+\r
+ /**\r
+ * Returns the value of a single preference for the rendering algorithms.\r
+ * Hint categories include controls for rendering quality and overall\r
+ * time/quality trade-off in the rendering process. Refer to the\r
+ * <code>RenderingHints</code> class for definitions of some common\r
+ * keys and values.\r
+ * @param hintKey the key corresponding to the hint to get.\r
+ * @return an object representing the value for the specified hint key.\r
+ * Some of the keys and their associated values are defined in the\r
+ * <code>RenderingHints</code> class.\r
+ * @see RenderingHints\r
+ */\r
+ public Object getRenderingHint(RenderingHints.Key hintKey){\r
+ return _hints.get(hintKey);\r
+ }\r
+\r
+ /**\r
+ * Sets the value of a single preference for the rendering algorithms.\r
+ * Hint categories include controls for rendering quality and overall\r
+ * time/quality trade-off in the rendering process. Refer to the\r
+ * <code>RenderingHints</code> class for definitions of some common\r
+ * keys and values.\r
+ * @param hintKey the key of the hint to be set.\r
+ * @param hintValue the value indicating preferences for the specified\r
+ * hint category.\r
+ * @see RenderingHints\r
+ */\r
+ public void setRenderingHint(RenderingHints.Key hintKey, Object hintValue){\r
+ _hints.put(hintKey, hintValue);\r
+ }\r
+\r
+\r
+ /**\r
+ * Renders the text of the specified\r
+ * {@link GlyphVector} using\r
+ * the <code>Graphics2D</code> context's rendering attributes.\r
+ * The rendering attributes applied include the <code>Clip</code>,\r
+ * <code>Transform</code>, <code>Paint</code>, and\r
+ * <code>Composite</code> attributes. The <code>GlyphVector</code>\r
+ * specifies individual glyphs from a {@link Font}.\r
+ * The <code>GlyphVector</code> can also contain the glyph positions.\r
+ * This is the fastest way to render a set of characters to the\r
+ * screen.\r
+ *\r
+ * @param g the <code>GlyphVector</code> to be rendered\r
+ * @param x the x position in user space where the glyphs should be\r
+ * rendered\r
+ * @param y the y position in user space where the glyphs should be\r
+ * rendered\r
+ *\r
+ * @see java.awt.Font#createGlyphVector(FontRenderContext, char[])\r
+ * @see java.awt.font.GlyphVector\r
+ * @see #setPaint\r
+ * @see java.awt.Graphics#setColor\r
+ * @see #setTransform\r
+ * @see #setComposite\r
+ * @see #setClip(Shape)\r
+ */\r
+ public void drawGlyphVector(GlyphVector g, float x, float y) {\r
+ Shape glyphOutline = g.getOutline(x, y);\r
+ fill(glyphOutline);\r
+ }\r
+\r
+ /**\r
+ * Returns the device configuration associated with this\r
+ * <code>Graphics2D</code>.\r
+ * @return the device configuration\r
+ */\r
+ public GraphicsConfiguration getDeviceConfiguration() {\r
+ return GraphicsEnvironment.getLocalGraphicsEnvironment().\r
+ getDefaultScreenDevice().getDefaultConfiguration();\r
+ }\r
+\r
+ /**\r
+ * Sets the values of an arbitrary number of preferences for the\r
+ * rendering algorithms.\r
+ * Only values for the rendering hints that are present in the\r
+ * specified <code>Map</code> object are modified.\r
+ * All other preferences not present in the specified\r
+ * object are left unmodified.\r
+ * Hint categories include controls for rendering quality and\r
+ * overall time/quality trade-off in the rendering process.\r
+ * Refer to the <code>RenderingHints</code> class for definitions of\r
+ * some common keys and values.\r
+ * @param hints the rendering hints to be set\r
+ * @see RenderingHints\r
+ */\r
+ public void addRenderingHints(Map<?,?> hints){\r
+ this._hints.putAll(hints);\r
+ }\r
+\r
+ /**\r
+ * Concatenates the current\r
+ * <code>Graphics2D</code> <code>Transform</code>\r
+ * with a translation transform.\r
+ * Subsequent rendering is translated by the specified\r
+ * distance relative to the previous position.\r
+ * This is equivalent to calling transform(T), where T is an\r
+ * <code>AffineTransform</code> represented by the following matrix:\r
+ * <pre>\r
+ * [ 1 0 tx ]\r
+ * [ 0 1 ty ]\r
+ * [ 0 0 1 ]\r
+ * </pre>\r
+ * @param tx the distance to translate along the x-axis\r
+ * @param ty the distance to translate along the y-axis\r
+ */\r
+ public void translate(double tx, double ty){\r
+ _transform.translate(tx, ty);\r
+ }\r
+\r
+ /**\r
+ * Renders the text of the specified iterator, using the\r
+ * <code>Graphics2D</code> context's current <code>Paint</code>. The\r
+ * iterator must specify a font\r
+ * for each character. The baseline of the\r
+ * first character is at position (<i>x</i>, <i>y</i>) in the\r
+ * User Space.\r
+ * The rendering attributes applied include the <code>Clip</code>,\r
+ * <code>Transform</code>, <code>Paint</code>, and\r
+ * <code>Composite</code> attributes.\r
+ * For characters in script systems such as Hebrew and Arabic,\r
+ * the glyphs can be rendered from right to left, in which case the\r
+ * coordinate supplied is the location of the leftmost character\r
+ * on the baseline.\r
+ * @param iterator the iterator whose text is to be rendered\r
+ * @param x the x coordinate where the iterator's text is to be\r
+ * rendered\r
+ * @param y the y coordinate where the iterator's text is to be\r
+ * rendered\r
+ * @see #setPaint\r
+ * @see java.awt.Graphics#setColor\r
+ * @see #setTransform\r
+ * @see #setComposite\r
+ * @see #setClip\r
+ */\r
+ public void drawString(AttributedCharacterIterator iterator, float x, float y) {\r
+ if (log.check(POILogger.WARN)) {\r
+ log.log(POILogger.WARN, "Not implemented");\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Checks whether or not the specified <code>Shape</code> intersects\r
+ * the specified {@link Rectangle}, which is in device\r
+ * space. If <code>onStroke</code> is false, this method checks\r
+ * whether or not the interior of the specified <code>Shape</code>\r
+ * intersects the specified <code>Rectangle</code>. If\r
+ * <code>onStroke</code> is <code>true</code>, this method checks\r
+ * whether or not the <code>Stroke</code> of the specified\r
+ * <code>Shape</code> outline intersects the specified\r
+ * <code>Rectangle</code>.\r
+ * The rendering attributes taken into account include the\r
+ * <code>Clip</code>, <code>Transform</code>, and <code>Stroke</code>\r
+ * attributes.\r
+ * @param rect the area in device space to check for a hit\r
+ * @param s the <code>Shape</code> to check for a hit\r
+ * @param onStroke flag used to choose between testing the\r
+ * stroked or the filled shape. If the flag is <code>true</code>, the\r
+ * <code>Stroke</code> oultine is tested. If the flag is\r
+ * <code>false</code>, the filled <code>Shape</code> is tested.\r
+ * @return <code>true</code> if there is a hit; <code>false</code>\r
+ * otherwise.\r
+ * @see #setStroke\r
+ * @see #fill(Shape)\r
+ * @see #draw(Shape)\r
+ * @see #_transform\r
+ * @see #setTransform\r
+ * @see #clip\r
+ * @see #setClip(Shape)\r
+ */\r
+ public boolean hit(Rectangle rect,\r
+ Shape s,\r
+ boolean onStroke){\r
+ if (onStroke) {\r
+ s = getStroke().createStrokedShape(s);\r
+ }\r
+\r
+ s = getTransform().createTransformedShape(s);\r
+\r
+ return s.intersects(rect);\r
+ }\r
+\r
+ /**\r
+ * Gets the preferences for the rendering algorithms. Hint categories\r
+ * include controls for rendering quality and overall time/quality\r
+ * trade-off in the rendering process.\r
+ * Returns all of the hint key/value pairs that were ever specified in\r
+ * one operation. Refer to the\r
+ * <code>RenderingHints</code> class for definitions of some common\r
+ * keys and values.\r
+ * @return a reference to an instance of <code>RenderingHints</code>\r
+ * that contains the current preferences.\r
+ * @see RenderingHints\r
+ */\r
+ public RenderingHints getRenderingHints(){\r
+ return _hints;\r
+ }\r
+\r
+ /**\r
+ * Replaces the values of all preferences for the rendering\r
+ * algorithms with the specified <code>hints</code>.\r
+ * The existing values for all rendering hints are discarded and\r
+ * the new set of known hints and values are initialized from the\r
+ * specified {@link Map} object.\r
+ * Hint categories include controls for rendering quality and\r
+ * overall time/quality trade-off in the rendering process.\r
+ * Refer to the <code>RenderingHints</code> class for definitions of\r
+ * some common keys and values.\r
+ * @param hints the rendering hints to be set\r
+ * @see RenderingHints\r
+ */\r
+ public void setRenderingHints(Map<?,?> hints){\r
+ this._hints = new RenderingHints(null);\r
+ this._hints.putAll(hints);\r
+ }\r
+\r
+ /**\r
+ * Renders an image, applying a transform from image space into user space\r
+ * before drawing.\r
+ * The transformation from user space into device space is done with\r
+ * the current <code>Transform</code> in the <code>Graphics2D</code>.\r
+ * The specified transformation is applied to the image before the\r
+ * transform attribute in the <code>Graphics2D</code> context is applied.\r
+ * The rendering attributes applied include the <code>Clip</code>,\r
+ * <code>Transform</code>, and <code>Composite</code> attributes.\r
+ * Note that no rendering is done if the specified transform is\r
+ * noninvertible.\r
+ * @param img the <code>Image</code> to be rendered\r
+ * @param xform the transformation from image space into user space\r
+ * @param obs the {@link ImageObserver}\r
+ * to be notified as more of the <code>Image</code>\r
+ * is converted\r
+ * @return <code>true</code> if the <code>Image</code> is\r
+ * fully loaded and completely rendered;\r
+ * <code>false</code> if the <code>Image</code> is still being loaded.\r
+ * @see #_transform\r
+ * @see #setTransform\r
+ * @see #setComposite\r
+ * @see #clip\r
+ * @see #setClip(Shape)\r
+ */\r
+ public boolean drawImage(Image img, AffineTransform xform, ImageObserver obs) {\r
+ if (log.check(POILogger.WARN)) {\r
+ log.log(POILogger.WARN, "Not implemented");\r
+ }\r
+ return false;\r
+ }\r
+\r
+ /**\r
+ * Draws as much of the specified image as has already been scaled\r
+ * to fit inside the specified rectangle.\r
+ * <p>\r
+ * The image is drawn inside the specified rectangle of this\r
+ * graphics context's coordinate space, and is scaled if\r
+ * necessary. Transparent pixels do not affect whatever pixels\r
+ * are already there.\r
+ * <p>\r
+ * This method returns immediately in all cases, even if the\r
+ * entire image has not yet been scaled, dithered, and converted\r
+ * for the current output device.\r
+ * If the current output representation is not yet complete, then\r
+ * <code>drawImage</code> returns <code>false</code>. As more of\r
+ * the image becomes available, the process that loads the image notifies\r
+ * the image observer by calling its <code>imageUpdate</code> method.\r
+ * <p>\r
+ * A scaled version of an image will not necessarily be\r
+ * available immediately just because an unscaled version of the\r
+ * image has been constructed for this output device. Each size of\r
+ * the image may be cached separately and generated from the original\r
+ * data in a separate image production sequence.\r
+ * @param img the specified image to be drawn. This method does\r
+ * nothing if <code>img</code> is null.\r
+ * @param x the <i>x</i> coordinate.\r
+ * @param y the <i>y</i> coordinate.\r
+ * @param width the width of the rectangle.\r
+ * @param height the height of the rectangle.\r
+ * @param observer object to be notified as more of\r
+ * the image is converted.\r
+ * @return <code>false</code> if the image pixels are still changing;\r
+ * <code>true</code> otherwise.\r
+ * @see java.awt.Image\r
+ * @see java.awt.image.ImageObserver\r
+ * @see java.awt.image.ImageObserver#imageUpdate(java.awt.Image, int, int, int, int, int)\r
+ */\r
+ public boolean drawImage(Image img, int x, int y,\r
+ int width, int height,\r
+ ImageObserver observer) {\r
+ if (log.check(POILogger.WARN)) {\r
+ log.log(POILogger.WARN, "Not implemented");\r
+ }\r
+ return false;\r
+ }\r
+\r
+ /**\r
+ * Creates a new <code>Graphics</code> object that is\r
+ * a copy of this <code>Graphics</code> object.\r
+ * @return a new graphics context that is a copy of\r
+ * this graphics context.\r
+ */\r
+ public Graphics create() {\r
+ try {\r
+ return (Graphics)clone();\r
+ } catch (CloneNotSupportedException e){\r
+ throw new RuntimeException(e);\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Gets the font metrics for the specified font.\r
+ * @return the font metrics for the specified font.\r
+ * @param f the specified font\r
+ * @see java.awt.Graphics#getFont\r
+ * @see java.awt.FontMetrics\r
+ * @see java.awt.Graphics#getFontMetrics()\r
+ */\r
+ @SuppressWarnings("deprecation")\r
+ @SuppressForbidden\r
+ public FontMetrics getFontMetrics(Font f) {\r
+ return Toolkit.getDefaultToolkit().getFontMetrics(f);\r
+ }\r
+\r
+ /**\r
+ * Sets the paint mode of this graphics context to alternate between\r
+ * this graphics context's current color and the new specified color.\r
+ * This specifies that logical pixel operations are performed in the\r
+ * XOR mode, which alternates pixels between the current color and\r
+ * a specified XOR color.\r
+ * <p>\r
+ * When drawing operations are performed, pixels which are the\r
+ * current color are changed to the specified color, and vice versa.\r
+ * <p>\r
+ * Pixels that are of colors other than those two colors are changed\r
+ * in an unpredictable but reversible manner; if the same figure is\r
+ * drawn twice, then all pixels are restored to their original values.\r
+ * @param c1 the XOR alternation color\r
+ */\r
+ public void setXORMode(Color c1) {\r
+ if (log.check(POILogger.WARN)) {\r
+ log.log(POILogger.WARN, "Not implemented");\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Sets the paint mode of this graphics context to overwrite the\r
+ * destination with this graphics context's current color.\r
+ * This sets the logical pixel operation function to the paint or\r
+ * overwrite mode. All subsequent rendering operations will\r
+ * overwrite the destination with the current color.\r
+ */\r
+ public void setPaintMode() {\r
+ if (log.check(POILogger.WARN)) {\r
+ log.log(POILogger.WARN, "Not implemented");\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Renders a\r
+ * {@link RenderableImage},\r
+ * applying a transform from image space into user space before drawing.\r
+ * The transformation from user space into device space is done with\r
+ * the current <code>Transform</code> in the <code>Graphics2D</code>.\r
+ * The specified transformation is applied to the image before the\r
+ * transform attribute in the <code>Graphics2D</code> context is applied.\r
+ * The rendering attributes applied include the <code>Clip</code>,\r
+ * <code>Transform</code>, and <code>Composite</code> attributes. Note\r
+ * that no rendering is done if the specified transform is\r
+ * noninvertible.\r
+ *<p>\r
+ * Rendering hints set on the <code>Graphics2D</code> object might\r
+ * be used in rendering the <code>RenderableImage</code>.\r
+ * If explicit control is required over specific hints recognized by a\r
+ * specific <code>RenderableImage</code>, or if knowledge of which hints\r
+ * are used is required, then a <code>RenderedImage</code> should be\r
+ * obtained directly from the <code>RenderableImage</code>\r
+ * and rendered using\r
+ *{@link #drawRenderedImage(RenderedImage, AffineTransform) drawRenderedImage}.\r
+ * @param img the image to be rendered. This method does\r
+ * nothing if <code>img</code> is null.\r
+ * @param xform the transformation from image space into user space\r
+ * @see #_transform\r
+ * @see #setTransform\r
+ * @see #setComposite\r
+ * @see #clip\r
+ * @see #setClip\r
+ * @see #drawRenderedImage\r
+ */\r
+ public void drawRenderedImage(RenderedImage img, AffineTransform xform) {\r
+ if (log.check(POILogger.WARN)) {\r
+ log.log(POILogger.WARN, "Not implemented");\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Renders a {@link RenderedImage},\r
+ * applying a transform from image\r
+ * space into user space before drawing.\r
+ * The transformation from user space into device space is done with\r
+ * the current <code>Transform</code> in the <code>Graphics2D</code>.\r
+ * The specified transformation is applied to the image before the\r
+ * transform attribute in the <code>Graphics2D</code> context is applied.\r
+ * The rendering attributes applied include the <code>Clip</code>,\r
+ * <code>Transform</code>, and <code>Composite</code> attributes. Note\r
+ * that no rendering is done if the specified transform is\r
+ * noninvertible.\r
+ * @param img the image to be rendered. This method does\r
+ * nothing if <code>img</code> is null.\r
+ * @param xform the transformation from image space into user space\r
+ * @see #_transform\r
+ * @see #setTransform\r
+ * @see #setComposite\r
+ * @see #clip\r
+ * @see #setClip\r
+ */\r
+ public void drawRenderableImage(RenderableImage img, AffineTransform xform) {\r
+ if (log.check(POILogger.WARN)) {\r
+ log.log(POILogger.WARN, "Not implemented");\r
+ }\r
+ }\r
+\r
+ protected void applyStroke(SimpleShape<?,?> shape) {\r
+ if (_stroke instanceof BasicStroke){\r
+ BasicStroke bs = (BasicStroke)_stroke;\r
+ shape.setStrokeStyle((double)bs.getLineWidth());\r
+ float[] dash = bs.getDashArray();\r
+ if (dash != null) {\r
+ //TODO: implement more dashing styles\r
+ shape.setStrokeStyle(StrokeStyle.LineDash.DASH);\r
+ }\r
+ }\r
+ }\r
+\r
+ protected void applyPaint(SimpleShape<?,?> shape) {\r
+ if (_paint instanceof Color) {\r
+ shape.setFillColor((Color)_paint);\r
+ }\r
+ }\r
+}\r
package org.apache.poi.sl.usermodel;
+import java.awt.Color;
+
import org.apache.poi.sl.draw.geom.CustomGeometry;
import org.apache.poi.sl.draw.geom.IAdjustableShape;
S extends Shape<S,P>,
P extends TextParagraph<S,P,?>
> extends Shape<S,P>, IAdjustableShape, PlaceableShape<S,P> {
+
+ enum Placeholder {
+ TITLE,
+ BODY,
+ CENTERED_TITLE,
+ SUBTITLE,
+ DATETIME,
+ SLIDE_NUMBER,
+ FOOTER,
+ HEADER,
+ CONTENT,
+ CHART,
+ TABLE,
+ CLIP_ART,
+ DGM,
+ MEDIA,
+ SLIDE_IMAGE,
+ PICTURE
+ }
+
FillStyle getFillStyle();
+
LineDecoration getLineDecoration();
+
StrokeStyle getStrokeStyle();
+
+ /**
+ * Sets the line attributes.
+ * Possible attributes are Double (width), LineCap, LineDash, LineCompound, Color
+ * (implementations of PaintStyle aren't yet supported ...)
+ *
+ * If no styles are given, the line will be hidden
+ *
+ * @param styles the line attributes
+ */
+ void setStrokeStyle(Object... styles);
CustomGeometry getGeometry();
-
+
ShapeType getShapeType();
+ void setShapeType(ShapeType type);
boolean isPlaceholder();
-
+
Shadow<S,P> getShadow();
+
+ /**
+ * Returns the solid color fill.
+ *
+ * @return solid fill color of null if not set or fill color
+ * is not solid (pattern or gradient)
+ */
+ Color getFillColor();
+
+ /**
+ * Specifies a solid color fill. The shape is filled entirely with the
+ * specified color.
+ *
+ * @param color the solid color fill. The value of <code>null</code> unsets
+ * the solid fill attribute from the underlying implementation
+ */
+ void setFillColor(Color color);
}
* @return the page size
*/
Dimension getPageSize();
+
+ /**
+ * Change the current page size
+ *
+ * @param pgsize page size (in points)
+ */
+ void setPageSize(Dimension pgsize);
/**
* Returns all Pictures of this slideshow.
public interface StrokeStyle {
enum LineCap {
/** Rounded ends */
- ROUND(1),
+ ROUND(0,1),
/** Square protrudes by half line width */
- SQUARE(2),
+ SQUARE(1,2),
/** Line ends at end point*/
- FLAT(3);
+ FLAT(2,3);
+ public final int nativeId;
public final int ooxmlId;
- LineCap(int ooxmlId) {
+ LineCap(int nativeId, int ooxmlId) {
+ this.nativeId = nativeId;
this.ooxmlId = ooxmlId;
}
+ public static LineCap fromNativeId(int nativeId) {
+ for (LineCap ld : values()) {
+ if (ld.nativeId == nativeId) return ld;
+ }
+ return null;
+ }
+
public static LineCap fromOoxmlId(int ooxmlId) {
for (LineCap lc : values()) {
if (lc.ooxmlId == ooxmlId) return lc;
enum LineCompound {
/** Single line (of width lineWidth) - native 0 / ooxml default */
- SINGLE(0),
+ SINGLE(0, 1),
/** Double lines of equal width - native 1 / ooxml "dbl" */
- DOUBLE(1),
+ DOUBLE(1, 2),
/** Double lines, one thick, one thin - native 2 / ooxml "thickThin" */
- THICK_THIN(2),
+ THICK_THIN(2, 3),
/** Double lines, reverse order - native 3 / ooxml "thinThick" */
- THIN_THICK(3),
+ THIN_THICK(3, 4),
/** Three lines, thin, thick, thin - native 4 / ooxml "tri" */
- TRIPLE(4);
+ TRIPLE(4, 5);
public final int nativeId;
+ public final int ooxmlId;
- LineCompound(int nativeId) {
+ LineCompound(int nativeId, int ooxmlId) {
this.nativeId = nativeId;
+ this.ooxmlId = ooxmlId;
}
public static LineCompound fromNativeId(int nativeId) {
}
return null;
}
+
+ public static LineCompound fromOoxmlId(int ooxmlId) {
+ for (LineCompound lc : values()) {
+ if (lc.ooxmlId == ooxmlId) return lc;
+ }
+ return null;
+ }
}
\r
package org.apache.poi.sl.usermodel;\r
\r
+import java.awt.Color;\r
+\r
+import org.apache.poi.sl.usermodel.StrokeStyle.LineCompound;\r
+import org.apache.poi.sl.usermodel.StrokeStyle.LineDash;\r
+\r
public interface TableCell<\r
S extends Shape<S,P>,\r
P extends TextParagraph<S,P,?>\r
> extends TextShape<S,P> {\r
+ enum BorderEdge { bottom, left, top, right };\r
+ \r
+ /**\r
+ * Return line style of given edge or {@code null} if border is not defined\r
+ *\r
+ * @param edge the border edge\r
+ * @return line style of given edge or {@code null} if border is not defined\r
+ */\r
+ StrokeStyle getBorderStyle(BorderEdge edge);\r
+ \r
+ /**\r
+ * Sets the {@link StrokeStyle} of the given border edge.\r
+ * A {@code null} property of the style is ignored.\r
+ *\r
+ * @param edge border edge\r
+ * @param style the new stroke style\r
+ */\r
+ void setBorderStyle(BorderEdge edge, StrokeStyle style);\r
+ \r
+ /**\r
+ * Convenience method for setting the border width.\r
+ *\r
+ * @param edge border edge\r
+ * @param width the new border width\r
+ */\r
+ void setBorderWidth(BorderEdge edge, double width);\r
+\r
+ /**\r
+ * Convenience method for setting the border color.\r
+ *\r
+ * @param edge border edge\r
+ * @param color the new border color\r
+ */\r
+ void setBorderColor(BorderEdge edge, Color color);\r
+\r
+ /**\r
+ * Convenience method for setting the border line compound.\r
+ *\r
+ * @param edge border edge\r
+ * @param compound the new border line compound\r
+ */\r
+ void setBorderCompound(BorderEdge edge, LineCompound compound);\r
\r
+ /**\r
+ * Convenience method for setting the border line dash.\r
+ *\r
+ * @param edge border edge\r
+ * @param dash the new border line dash\r
+ */\r
+ void setBorderDash(BorderEdge edge, LineDash dash);\r
+ \r
+ /**\r
+ * Remove all line attributes of the given border edge\r
+ *\r
+ * @param edge the border edge to be cleared\r
+ */\r
+ void removeBorder(BorderEdge edge);\r
}\r
S extends Shape<S,P>,\r
P extends TextParagraph<S,P,?>\r
> extends Shape<S,P>, PlaceableShape<S,P> {\r
- // to be defined ...\r
+ int getNumberOfColumns();\r
+ \r
+ int getNumberOfRows();\r
+ \r
+ TableCell<S,P> getCell(int row, int col);\r
+ \r
+ /**\r
+ * Sets the width (in points) of the n-th column\r
+ *\r
+ * @param idx the column index (0-based)\r
+ * @param width the width (in points)\r
+ */\r
+ void setColumnWidth(int idx, double width);\r
+\r
+ /**\r
+ * Sets the row height.\r
+ *\r
+ * @param row the row index (0-based)\r
+ * @param height the height to set (in points)\r
+ */\r
+ void setRowHeight(int row, double height);\r
}\r
package org.apache.poi.sl.usermodel;
+/**
+ * Represents a TextFrame shape in PowerPoint.
+ * <p>
+ * Contains the text in a text frame as well as the properties and methods
+ * that control alignment and anchoring of the text.
+ * </p>
+ */
public interface TextBox<
S extends Shape<S,P>,
P extends TextParagraph<S,P,?>
package org.apache.poi.sl.usermodel;\r
\r
import java.awt.Color;\r
+import java.util.List;\r
\r
\r
\r
\r
\r
TextShape<S,P> getParentShape();\r
+ \r
+ /**\r
+ * Fetch the text runs that are contained within this block of text\r
+ */\r
+ List<T> getTextRuns();\r
}\r
SMALL,
ALL
}
-
+
String getRawText();
- void setText(String text);
-
- TextCap getTextCap();
-
- /**
- * Returns the font color.
- * This usually returns a {@link SolidPaint}, but but also other classes are possible
- *
- * @return the font color/paint
- *
+ void setText(String text);
+
+ TextCap getTextCap();
+
+ /**
+ * Returns the font color.
+ * This usually returns a {@link SolidPaint}, but but also other classes are possible
+ *
+ * @return the font color/paint
+ *
* @see org.apache.poi.sl.draw.DrawPaint#getPaint(java.awt.Graphics2D, PaintStyle)
* @see SolidPaint#getSolidColor()
- * @see org.apache.poi.sl.draw.DrawPaint#applyColorTransform(ColorStyle)
- */
- PaintStyle getFontColor();
+ * @see org.apache.poi.sl.draw.DrawPaint#applyColorTransform(ColorStyle)
+ */
+ PaintStyle getFontColor();
/**
* Sets the (solid) font color - convenience function
void setFontColor(Color color);
/**
- * Sets the font color
- *
- * @param color the color
- *
- * @see org.apache.poi.sl.draw.DrawPaint#createSolidPaint(Color)
- */
- void setFontColor(PaintStyle color);
-
-
+ * Sets the font color
+ *
+ * @param color the color
+ *
+ * @see org.apache.poi.sl.draw.DrawPaint#createSolidPaint(Color)
+ */
+ void setFontColor(PaintStyle color);
+
+
/**
* Returns the font size which is either set directly on this text run or
* given from the slide layout
- *
+ *
* @return font size in points or null if font size is not set.
*/
- Double getFontSize();
+ Double getFontSize();
/**
* Sets the font size directly on this text run, if null is given, the
* font size defaults to the values given from the slide layout
- *
+ *
* @param fontSize font size in points, if null the underlying fontsize will be unset
*/
- void setFontSize(Double fontSize);
- String getFontFamily();
-
- boolean isBold();
- boolean isItalic();
- boolean isUnderlined();
- boolean isStrikethrough();
- boolean isSubscript();
- boolean isSuperscript();
-
- /**
- * @return the pitch and family id or -1 if not applicable
- */
- byte getPitchAndFamily();
+ void setFontSize(Double fontSize);
+
+ /**
+ * @return font family or null if not set
+ */
+ String getFontFamily();
+
+ /**
+ * Specifies the typeface, or name of the font that is to be used for this text run.
+ *
+ * @param typeface the font to apply to this text run.
+ * The value of <code>null</code> unsets the Typeface attrubute from the underlying xml.
+ */
+ void setFontFamily(String typeface);
+
+ /**
+ * @return true, if text is bold
+ */
+ boolean isBold();
+
+ /**
+ * Sets the bold state
+ *
+ * @param bold set to true for bold text, false for normal weight
+ */
+ void setBold(boolean bold);
+
+ /**
+ * @return true, if text is italic
+ */
+ boolean isItalic();
+
+ /**
+ * Sets the italic state
+ *
+ * @param italic set to true for italic text, false for non-italics
+ */
+ void setItalic(boolean italic);
+
+ /**
+ * @return true, if text is underlined
+ */
+ boolean isUnderlined();
+
+ /**
+ * Sets the underlined state
+ *
+ * @param underlined set to true for underlined text, false for no underlining
+ */
+ void setUnderlined(boolean underlined);
+
+ /**
+ * @return true, if text is stroked
+ */
+ boolean isStrikethrough();
+
+ /**
+ * Sets the strikethrough state
+ *
+ * @param stroked set to true for stroked text, false for no stroking
+ */
+ void setStrikethrough(boolean stroked);
+
+ /**
+ * @return true, if text is sub scripted
+ */
+ boolean isSubscript();
+
+ /**
+ * @return true, if text is super scripted
+ */
+ boolean isSuperscript();
+
+ /**
+ * @return the pitch and family id or -1 if not applicable
+ */
+ byte getPitchAndFamily();
}
/**\r
* Vertical Text Types\r
*/\r
- public enum TextDirection {\r
+ enum TextDirection {\r
/**\r
* Horizontal text. This should be default.\r
*/\r
* Auto-fitting is when text within a shape is scaled in order to contain all the text inside\r
* </p>\r
*/\r
- public enum TextAutofit {\r
+ enum TextAutofit {\r
/**\r
* Specifies that text within the text body should not be auto-fit to the bounding box.\r
* Auto-fitting is when text within a text box is scaled in order to remain inside\r
*/\r
SHAPE\r
}\r
+\r
+ /**\r
+ * This enum represents a compromise for the handling of\r
+ * HSLF run types (see org.apache.poi.hslf.record.TextHeaderAtom) and\r
+ * XSLF placeholders (see org.apache.poi.xslf.usermodel.Placeholder).\r
+ * When a shape is considered a placeholder by the generating application\r
+ * it can have special properties to alert the user that they may enter content into the shape.\r
+ * \r
+ * This enum and the handling around it may change significantly in future releases\r
+ */\r
+ enum TextPlaceholder {\r
+ /** Title placeholder shape text */\r
+ TITLE,\r
+ /** Body placeholder shape text */\r
+ BODY,\r
+ /** Center title placeholder shape text */\r
+ CENTER_TITLE,\r
+ /** Center body placeholder shape text */\r
+ CENTER_BODY,\r
+ /** Half-sized body placeholder shape text */\r
+ HALF_BODY,\r
+ /** Quarter-sized body placeholder shape text */\r
+ QUARTER_BODY,\r
+ /** Notes placeholder shape text */\r
+ NOTES,\r
+ /** Any other text */\r
+ OTHER\r
+ }\r
+\r
+ /**\r
+ * Sets (overwrites) the current text.\r
+ * Uses the properties of the first paragraph / textrun.\r
+ * Text paragraphs are split by \\r or \\n.\r
+ * New lines within text run are split by \\u000b\r
+ * \r
+ * @param text the text string used by this object.\r
+ * \r
+ * @return the last text run of the - potential split - text\r
+ */\r
+ TextRun setText(String text);\r
\r
/**\r
* @return the TextParagraphs for this text box\r
* @return text shape margin\r
*/\r
Insets2D getInsets();\r
+ \r
+ /**\r
+ * Sets the shape margins\r
+ *\r
+ * @param insets the new shape margins\r
+ */\r
+ void setInsets(Insets2D insets);\r
\r
/**\r
* Compute the cumulative height occupied by the text\r
*/\r
VerticalAlignment getVerticalAlignment();\r
\r
+ /**\r
+ * Sets the type of vertical alignment for the text.\r
+ *\r
+ * @param vAlign - the type of alignment.\r
+ * A {@code null} values unsets this property.\r
+ */\r
+ void setVerticalAlignment(VerticalAlignment vAlign);\r
+ \r
/**\r
* Returns if the text is centered.\r
* If true and if the individual paragraph settings allow it,\r
*/\r
boolean isHorizontalCentered();\r
\r
+ /**\r
+ * Sets if the paragraphs are horizontal centered\r
+ *\r
+ * @param isCentered true, if the paragraphs are horizontal centered\r
+ * A {@code null} values unsets this property.\r
+ */\r
+ void setHorizontalCentered(Boolean isCentered);\r
+ \r
/**\r
* @return whether to wrap words within the bounding rectangle\r
*/\r
boolean getWordWrap();\r
\r
+ /**\r
+ * @param wrap whether to wrap words within the bounding rectangle\r
+ */\r
+ void setWordWrap(boolean wrap);\r
+ \r
/**\r
* @return vertical orientation of the text\r
*/\r
TextDirection getTextDirection();\r
+ \r
+ /**\r
+ * Sets the text placeholder\r
+ */\r
+ void setTextPlaceholder(TextPlaceholder placeholder);\r
+ \r
+ /**\r
+ * @return the text placeholder\r
+ */\r
+ TextPlaceholder getTextPlaceholder();\r
}\r
+++ /dev/null
-/*\r
- * ====================================================================\r
- * Licensed to the Apache Software Foundation (ASF) under one or more\r
- * contributor license agreements. See the NOTICE file distributed with\r
- * this work for additional information regarding copyright ownership.\r
- * The ASF licenses this file to You under the Apache License, Version 2.0\r
- * (the "License"); you may not use this file except in compliance with\r
- * the License. You may obtain a copy of the License at\r
- *\r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- * ====================================================================\r
- */\r
-package org.apache.poi.xslf.usermodel;\r
-\r
-/**\r
- * @author Yegor Kozlov\r
- */\r
-public enum Placeholder {\r
- TITLE,\r
- BODY,\r
- CENTERED_TITLE,\r
- SUBTITLE,\r
- DATETIME,\r
- SLIDE_NUMBER,\r
- FOOTER,\r
- HEADER,\r
- CONTENT,\r
- CHART,\r
- TABLE,\r
- CLIP_ART,\r
- DGM,\r
- MEDIA,\r
- SLIDE_IMAGE,\r
- PICTURE\r
-}\r
import org.apache.poi.sl.usermodel.Resources;
import org.apache.poi.sl.usermodel.SlideShow;
import org.apache.poi.util.Beta;
-import org.apache.poi.util.DocumentHelper;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.Internal;
import org.apache.poi.util.LittleEndian;
return slide;
}
- /**
- * Returns the current page size
- *
- * @return the page size
- */
+ @Override
public Dimension getPageSize(){
CTSlideSize sz = _presentation.getSldSz();
int cx = sz.getCx();
return new Dimension((int)Units.toPoints(cx), (int)Units.toPoints(cy));
}
- /**
- * Sets the page size to the given <code>Dimension</code> object.
- *
- * @param pgSize page size
- */
+ @Override
public void setPageSize(Dimension pgSize){
CTSlideSize sz = CTSlideSize.Factory.newInstance();
sz.setCx(Units.toEMU(pgSize.getWidth()));
import org.openxmlformats.schemas.drawingml.x2006.main.CTPresetGeometry2D;\r
import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeProperties;\r
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextBody;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTTextBodyProperties;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTTextCharacterProperties;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraph;\r
import org.openxmlformats.schemas.drawingml.x2006.main.STShapeType;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.STTextAlignType;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.STTextAnchoringType;\r
import org.openxmlformats.schemas.presentationml.x2006.main.CTShape;\r
import org.openxmlformats.schemas.presentationml.x2006.main.CTShapeNonVisual;\r
\r
prst.addNewAvLst();\r
return ct;\r
}\r
+ \r
+ protected static void initTextBody(CTTextBody txBody) {\r
+ CTTextBodyProperties bodypr = txBody.addNewBodyPr();\r
+ bodypr.setAnchor(STTextAnchoringType.T);\r
+ bodypr.setRtlCol(false);\r
+ CTTextParagraph p = txBody.addNewP();\r
+ p.addNewPPr().setAlgn(STTextAlignType.L);\r
+ CTTextCharacterProperties endPr = p.addNewEndParaRPr();\r
+ endPr.setLang("en-US");\r
+ endPr.setSz(1100); \r
+ p.addNewR().setT("");\r
+ txBody.addNewLstStyle();\r
+ }\r
\r
protected CTTextBody getTextBody(boolean create){\r
CTShape shape = (CTShape)getXmlObject();\r
CTTextBody txBody = shape.getTxBody();\r
if (txBody == null && create) {\r
txBody = shape.addNewTxBody();\r
- txBody.addNewBodyPr();\r
- txBody.addNewLstStyle();\r
+ initTextBody(txBody);\r
}\r
return txBody;\r
}\r
import org.apache.poi.sl.usermodel.PaintStyle.GradientPaint;\r
import org.apache.poi.sl.usermodel.PaintStyle.TexturePaint;\r
import org.apache.poi.sl.usermodel.PlaceableShape;\r
+import org.apache.poi.sl.usermodel.SimpleShape.Placeholder;\r
import org.apache.poi.sl.usermodel.Shape;\r
import org.apache.poi.util.Beta;\r
import org.apache.poi.util.Internal;\r
import org.apache.poi.sl.draw.DrawPictureShape;
import org.apache.poi.sl.draw.Drawable;
import org.apache.poi.sl.usermodel.PictureData;
+import org.apache.poi.sl.usermodel.SimpleShape.Placeholder;
import org.apache.poi.sl.usermodel.Sheet;
import org.apache.poi.util.Beta;
import org.apache.poi.util.IOUtils;
super(shape,sheet);\r
}\r
\r
- /**\r
- *\r
- * @param type\r
- */\r
- public void setShapeType(ShapeType type){\r
+ @Override\r
+ public void setShapeType(ShapeType type) {\r
STShapeType.Enum geom = STShapeType.Enum.forInt(type.ooxmlId);\r
getSpPr().getPrstGeom().setPrst(geom);\r
}\r
\r
+ @Override\r
public ShapeType getShapeType(){\r
STShapeType.Enum geom = getSpPr().getPrstGeom().getPrst();\r
return ShapeType.forId(geom.intValue(), true);\r
}\r
- \r
+\r
protected CTTransform2D getSafeXfrm() {\r
CTTransform2D xfrm = getXfrm();\r
return (xfrm == null ? getSpPr().addNewXfrm() : xfrm);\r
}\r
- \r
+\r
protected CTTransform2D getXfrm() {\r
PropertyFetcher<CTTransform2D> fetcher = new PropertyFetcher<CTTransform2D>() {\r
public boolean fetch(XSLFShape shape) {\r
ext.setCx(cx);\r
ext.setCy(cy);\r
}\r
- \r
+\r
@Override\r
public void setRotation(double theta) {\r
getSafeXfrm().setRot((int) (theta * 60000));\r
return (xfrm == null || !xfrm.isSetFlipV()) ? false : getXfrm().getFlipV();\r
}\r
\r
- \r
+\r
/**\r
* Get default line properties defined in the theme (if any).\r
* Used internally to resolve shape properties.\r
if (lnRef == null) return null;\r
// 1-based index of a line style within the style matrix\r
int idx = (int)lnRef.getIdx();\r
- \r
+\r
XSLFTheme theme = getSheet().getTheme();\r
if (theme == null) return null;\r
CTBaseStyles styles = theme.getXmlObject().getThemeElements();\r
if (styleMatrix == null) return null;\r
CTLineStyleList lineStyles = styleMatrix.getLnStyleLst();\r
if (lineStyles == null || lineStyles.sizeOfLnArray() < idx) return null;\r
- \r
+\r
return lineStyles.getLnArray(idx - 1);\r
}\r
\r
setValue(null); // use it as 'nofill' value\r
return true;\r
}\r
- \r
+\r
PaintStyle paint = null;\r
PackagePart pp = getSheet().getPackagePart();\r
for (XmlObject obj : spPr.selectPath("*")) {\r
\r
PaintStyle paint = fetcher.getValue();\r
if (paint != null) return paint;\r
- \r
+\r
// line color was not found, check if it is defined in the theme\r
CTShapeStyle style = getSpStyle();\r
if (style == null) return null;\r
- \r
+\r
// get a reference to a line style within the style matrix.\r
CTStyleMatrixReference lnRef = style.getLnRef();\r
int idx = (int)lnRef.getIdx();\r
\r
return paint;\r
}\r
- \r
+\r
/**\r
*\r
* @param width line width in points. <code>0</code> means no line\r
return lineWidth;\r
}\r
\r
+\r
+ /**\r
+ * @param compound set the line compound style\r
+ */\r
+ public void setLineCompound(LineCompound compound) {\r
+ CTShapeProperties spPr = getSpPr();\r
+ if (compound == null) {\r
+ if (spPr.isSetLn() && spPr.getLn().isSetCmpd())\r
+ spPr.getLn().unsetCmpd();\r
+ } else {\r
+ CTLineProperties ln = spPr.isSetLn() ? spPr.getLn() : spPr.addNewLn();\r
+ STCompoundLine.Enum xCmpd;\r
+ switch (compound) {\r
+ default:\r
+ case SINGLE:\r
+ xCmpd = STCompoundLine.SNG;\r
+ break;\r
+ case DOUBLE:\r
+ xCmpd = STCompoundLine.DBL;\r
+ break;\r
+ case THICK_THIN:\r
+ xCmpd = STCompoundLine.THICK_THIN;\r
+ break;\r
+ case THIN_THICK:\r
+ xCmpd = STCompoundLine.THIN_THICK;\r
+ break;\r
+ case TRIPLE:\r
+ xCmpd = STCompoundLine.TRI;\r
+ break;\r
+ }\r
+ ln.setCmpd(xCmpd);\r
+ }\r
+ }\r
+\r
/**\r
* @return the line compound\r
*/\r
}\r
}\r
}\r
- \r
+\r
if (cmpd == null) return null;\r
\r
switch (cmpd) {\r
public void setLineDash(LineDash dash) {\r
CTShapeProperties spPr = getSpPr();\r
if (dash == null) {\r
- if (spPr.isSetLn() && spPr.getLn().isSetPrstDash())\r
+ if (spPr.isSetLn() && spPr.getLn().isSetPrstDash())\r
spPr.getLn().unsetPrstDash();\r
} else {\r
- CTPresetLineDashProperties val = CTPresetLineDashProperties.Factory\r
- .newInstance();\r
- val.setVal(STPresetLineDashVal.Enum.forInt(dash.ooxmlId));\r
- CTLineProperties ln = spPr.isSetLn() ? spPr.getLn() : spPr\r
- .addNewLn();\r
- ln.setPrstDash(val);\r
+ CTLineProperties ln = spPr.isSetLn() ? spPr.getLn() : spPr.addNewLn();\r
+ CTPresetLineDashProperties ldp = ln.isSetPrstDash() ? ln.getPrstDash() : ln.addNewPrstDash();\r
+ ldp.setVal(STPresetLineDashVal.Enum.forInt(dash.ooxmlId));\r
}\r
}\r
\r
return cap;\r
}\r
\r
- /**\r
- * Specifies a solid color fill. The shape is filled entirely with the\r
- * specified color.\r
- *\r
- * @param color the solid color fill. The value of <code>null</code> unsets\r
- * the solidFIll attribute from the underlying xml\r
- */\r
+ @Override\r
public void setFillColor(Color color) {\r
CTShapeProperties spPr = getSpPr();\r
if (color == null) {\r
}\r
}\r
\r
- /**\r
- * @return solid fill color of null if not set or fill color\r
- * is not solid (pattern or gradient)\r
- */\r
+ @Override\r
public Color getFillColor() {\r
PaintStyle ps = getFillPaint();\r
if (ps instanceof SolidPaint) {\r
}\r
return geom;\r
}\r
- \r
+\r
@Override\r
void copy(XSLFShape sh){\r
super.copy(sh);\r
String relId = getSheet().importBlip(blipId, s.getSheet().getPackagePart());\r
blip.setEmbed(relId);\r
}\r
- \r
+\r
Color srcLineColor = s.getLineColor();\r
Color tgtLineColor = getLineColor();\r
if(srcLineColor != null && !srcLineColor.equals(tgtLineColor)) {\r
public LineCompound getLineCompound() {\r
return XSLFSimpleShape.this.getLineCompound();\r
}\r
- \r
+\r
};\r
}\r
+\r
+ @Override\r
+ public void setStrokeStyle(Object... styles) {\r
+ if (styles.length == 0) {\r
+ // remove stroke\r
+ setLineColor(null);\r
+ return;\r
+ }\r
+ \r
+ // TODO: handle PaintStyle\r
+ for (Object st : styles) {\r
+ if (st instanceof Number) {\r
+ setLineWidth(((Number)st).doubleValue());\r
+ } else if (st instanceof LineCap) {\r
+ setLineCap((LineCap)st);\r
+ } else if (st instanceof LineDash) {\r
+ setLineDash((LineDash)st);\r
+ } else if (st instanceof LineCompound) {\r
+ setLineCompound((LineCompound)st);\r
+ } else if (st instanceof Color) {\r
+ setLineColor((Color)st);\r
+ }\r
+ }\r
+ }\r
}\r
import org.apache.poi.sl.draw.DrawFactory;
import org.apache.poi.sl.draw.Drawable;
import org.apache.poi.sl.usermodel.Notes;
+import org.apache.poi.sl.usermodel.SimpleShape.Placeholder;
import org.apache.poi.sl.usermodel.Slide;
import org.apache.poi.util.Beta;
-import org.apache.poi.util.DocumentHelper;
import org.apache.xmlbeans.XmlException;
import org.openxmlformats.schemas.drawingml.x2006.main.CTBlip;
import org.openxmlformats.schemas.drawingml.x2006.main.CTGroupShapeProperties;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.opc.PackageRelationship;
import org.apache.poi.sl.usermodel.MasterSheet;
+import org.apache.poi.sl.usermodel.SimpleShape.Placeholder;
import org.apache.poi.util.Beta;
-import org.apache.poi.util.DocumentHelper;
import org.apache.poi.util.Internal;
import org.apache.xmlbeans.XmlException;
import org.openxmlformats.schemas.presentationml.x2006.main.CTBackground;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.opc.PackageRelationship;
import org.apache.poi.sl.usermodel.MasterSheet;
+import org.apache.poi.sl.usermodel.SimpleShape.Placeholder;
import org.apache.poi.util.Beta;
-import org.apache.poi.util.DocumentHelper;
import org.apache.xmlbeans.XmlException;
import org.openxmlformats.schemas.drawingml.x2006.main.CTColorMapping;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextListStyle;
for(CTTableRow row : trArray) _rows.add(new XSLFTableRow(row, this));\r
}\r
\r
+ @Override\r
+ public XSLFTableCell getCell(int row, int col) {\r
+ return getRows().get(row).getCells().get(col);\r
+ }\r
+ \r
@Internal\r
public CTTable getCTTable(){\r
return _table;\r
}\r
\r
+ @Override\r
public int getNumberOfColumns() {\r
return _table.getTblGrid().sizeOfGridColArray();\r
}\r
\r
+ @Override\r
public int getNumberOfRows() {\r
return _table.sizeOfTrArray();\r
}\r
_table.getTblGrid().getGridColArray(idx).getW());\r
}\r
\r
- public void setColumnWidth(int idx, double width){\r
+ @Override\r
+ public void setColumnWidth(int idx, double width) {\r
_table.getTblGrid().getGridColArray(idx).setW(Units.toEMU(width));\r
}\r
\r
+ @Override\r
+ public void setRowHeight(int row, double height) {\r
+ _table.getTrArray(row).setH(Units.toEMU(height));\r
+ }\r
+ \r
public Iterator<XSLFTableRow> iterator(){\r
return _rows.iterator();\r
}\r
\r
import java.awt.Color;\r
\r
+import org.apache.poi.sl.draw.DrawPaint;\r
+import org.apache.poi.sl.usermodel.PaintStyle;\r
+import org.apache.poi.sl.usermodel.StrokeStyle;\r
+import org.apache.poi.sl.usermodel.StrokeStyle.LineCap;\r
+import org.apache.poi.sl.usermodel.StrokeStyle.LineCompound;\r
+import org.apache.poi.sl.usermodel.StrokeStyle.LineDash;\r
import org.apache.poi.sl.usermodel.TableCell;\r
import org.apache.poi.sl.usermodel.VerticalAlignment;\r
import org.apache.poi.util.Units;\r
* Represents a cell of a table in a .pptx presentation\r
*/\r
public class XSLFTableCell extends XSLFTextShape implements TableCell<XSLFShape,XSLFTextParagraph> {\r
- static double defaultBorderWidth = 1.0;\r
private CTTableCellProperties _tcPr = null;\r
\r
/*package*/ XSLFTableCell(CTTableCell cell, XSLFSheet sheet){\r
CTTextBody txBody = cell.getTxBody();\r
if (txBody == null && create) {\r
txBody = cell.addNewTxBody();\r
- txBody.addNewBodyPr();\r
- txBody.addNewLstStyle();\r
+ XSLFAutoShape.initTextBody(txBody);\r
}\r
return txBody;\r
}\r
}\r
return _tcPr;\r
}\r
- \r
+\r
@Override\r
public void setLeftInset(double margin){\r
CTTableCellProperties pr = getCellProperties(true);\r
pr.setMarB(Units.toEMU(margin));\r
}\r
\r
- private CTLineProperties getCTLine(char bltr, boolean create) {\r
+ private CTLineProperties getCTLine(BorderEdge edge, boolean create) {\r
+ if (edge == null) {\r
+ throw new IllegalArgumentException("BorderEdge needs to be specified.");\r
+ }\r
+\r
CTTableCellProperties pr = getCellProperties(create);\r
if (pr == null) return null;\r
- \r
- switch (bltr) {\r
- case 'b':\r
+\r
+ switch (edge) {\r
+ case bottom:\r
return (pr.isSetLnB()) ? pr.getLnB() : (create ? pr.addNewLnB() : null);\r
- case 'l':\r
+ case left:\r
return (pr.isSetLnL()) ? pr.getLnL() : (create ? pr.addNewLnL() : null);\r
- case 't':\r
+ case top:\r
return (pr.isSetLnT()) ? pr.getLnT() : (create ? pr.addNewLnT() : null);\r
- case 'r':\r
+ case right:\r
return (pr.isSetLnR()) ? pr.getLnR() : (create ? pr.addNewLnR() : null);\r
default:\r
return null;\r
}\r
}\r
+\r
+ @Override\r
+ public void removeBorder(BorderEdge edge) {\r
+ CTTableCellProperties pr = getCellProperties(false);\r
+ if (pr == null) return;\r
+ switch (edge) {\r
+ case bottom:\r
+ if (pr.isSetLnB()) {\r
+ pr.unsetLnB();\r
+ }\r
+ break;\r
+ case left:\r
+ if (pr.isSetLnL()) {\r
+ pr.unsetLnL();\r
+ }\r
+ break;\r
+ case top:\r
+ if (pr.isSetLnT()) {\r
+ pr.unsetLnT();\r
+ }\r
+ break;\r
+ case right:\r
+ if (pr.isSetLnR()) {\r
+ pr.unsetLnB();\r
+ }\r
+ break;\r
+ default:\r
+ throw new IllegalArgumentException();\r
+ }\r
+ }\r
+\r
+ @Override\r
+ public StrokeStyle getBorderStyle(final BorderEdge edge) {\r
+ final Double width = getBorderWidth(edge);\r
+ return (width == null) ? null : new StrokeStyle() {\r
+ public PaintStyle getPaint() {\r
+ return DrawPaint.createSolidPaint(getBorderColor(edge));\r
+ }\r
+\r
+ public LineCap getLineCap() {\r
+ return getBorderCap(edge);\r
+ }\r
+\r
+ public LineDash getLineDash() {\r
+ return getBorderDash(edge);\r
+ }\r
+\r
+ public LineCompound getLineCompound() {\r
+ return getBorderCompound(edge);\r
+ }\r
+\r
+ public double getLineWidth() {\r
+ return width;\r
+ }\r
+ };\r
+ }\r
\r
- private void setBorderWidth(char bltr, double width) {\r
- CTLineProperties ln = getCTLine(bltr, true);\r
- ln.setW(Units.toEMU(width));\r
+ @Override\r
+ public void setBorderStyle(BorderEdge edge, StrokeStyle style) {\r
+ if (style == null) {\r
+ throw new IllegalArgumentException("StrokeStyle needs to be specified.");\r
+ }\r
+ \r
+ LineCap cap = style.getLineCap();\r
+ if (cap != null) {\r
+ setBorderCap(edge, cap);\r
+ }\r
+ \r
+ LineCompound compound = style.getLineCompound();\r
+ if (compound != null) {\r
+ setBorderCompound(edge, compound);\r
+ }\r
+ \r
+ LineDash dash = style.getLineDash();\r
+ if (dash != null) {\r
+ setBorderDash(edge, dash);\r
+ }\r
+ \r
+ double width = style.getLineWidth();\r
+ setBorderWidth(edge, width);\r
}\r
\r
- private double getBorderWidth(char bltr) {\r
- CTLineProperties ln = getCTLine(bltr, false);\r
- return (ln == null || !ln.isSetW()) ? defaultBorderWidth : Units.toPoints(ln.getW());\r
+ public Double getBorderWidth(BorderEdge edge) {\r
+ CTLineProperties ln = getCTLine(edge, false);\r
+ return (ln == null || !ln.isSetW()) ? null : Units.toPoints(ln.getW());\r
}\r
\r
- private void setBorderColor(char bltr, Color color) {\r
- CTLineProperties ln = getCTLine(bltr, true);\r
+ @Override\r
+ public void setBorderWidth(BorderEdge edge, double width) {\r
+ CTLineProperties ln = getCTLine(edge, true);\r
+ ln.setW(Units.toEMU(width));\r
+ }\r
\r
- if(color == null){\r
- ln.addNewNoFill();\r
- if(ln.isSetSolidFill()) ln.unsetSolidFill();\r
- } else {\r
- if(ln.isSetNoFill()) ln.unsetNoFill();\r
+ private CTLineProperties setBorderDefaults(BorderEdge edge) {\r
+ CTLineProperties ln = getCTLine(edge, true);\r
+ if (ln.isSetNoFill()) {\r
+ ln.unsetNoFill();\r
+ }\r
\r
- if(!ln.isSetPrstDash()) ln.addNewPrstDash().setVal(STPresetLineDashVal.SOLID);\r
+ if(!ln.isSetPrstDash()) {\r
+ ln.addNewPrstDash().setVal(STPresetLineDashVal.SOLID);\r
+ }\r
+ if (!ln.isSetCmpd()) {\r
ln.setCmpd(STCompoundLine.SNG);\r
+ }\r
+ if (!ln.isSetAlgn()) {\r
ln.setAlgn(STPenAlignment.CTR);\r
+ }\r
+ if (!ln.isSetCap()) {\r
ln.setCap(STLineCap.FLAT);\r
+ }\r
+ if (!ln.isSetRound()) {\r
ln.addNewRound();\r
+ }\r
\r
+ if (!ln.isSetHeadEnd()) {\r
CTLineEndProperties hd = ln.addNewHeadEnd();\r
hd.setType(STLineEndType.NONE);\r
hd.setW(STLineEndWidth.MED);\r
hd.setLen(STLineEndLength.MED);\r
+ }\r
\r
+ if (!ln.isSetTailEnd()) {\r
CTLineEndProperties tl = ln.addNewTailEnd();\r
tl.setType(STLineEndType.NONE);\r
tl.setW(STLineEndWidth.MED);\r
tl.setLen(STLineEndLength.MED);\r
+ }\r
\r
- CTSRgbColor rgb = CTSRgbColor.Factory.newInstance();\r
- rgb.setVal(new byte[]{(byte)color.getRed(), (byte)color.getGreen(), (byte)color.getBlue()});\r
- ln.addNewSolidFill().setSrgbClr(rgb);\r
+ return ln;\r
+ }\r
+\r
+ @Override\r
+ public void setBorderColor(BorderEdge edge, Color color) {\r
+ if (color == null) {\r
+ throw new IllegalArgumentException("Colors need to be specified.");\r
}\r
- } \r
- \r
- private Color getBorderColor(char bltr) {\r
- CTLineProperties ln = getCTLine(bltr,false);\r
+\r
+ CTLineProperties ln = setBorderDefaults(edge);\r
+\r
+ CTSRgbColor rgb = CTSRgbColor.Factory.newInstance();\r
+ rgb.setVal(new byte[]{(byte)color.getRed(), (byte)color.getGreen(), (byte)color.getBlue()});\r
+ ln.addNewSolidFill().setSrgbClr(rgb);\r
+ }\r
+\r
+ public Color getBorderColor(BorderEdge edge) {\r
+ CTLineProperties ln = getCTLine(edge, false);\r
if (ln == null || ln.isSetNoFill() || !ln.isSetSolidFill()) return null;\r
\r
CTSolidColorFillProperties fill = ln.getSolidFill();\r
}\r
byte[] val = fill.getSrgbClr().getVal();\r
return new Color(0xFF & val[0], 0xFF & val[1], 0xFF & val[2]);\r
- } \r
- \r
- public void setBorderLeft(double width) {\r
- setBorderWidth('l', width);\r
}\r
\r
- public double getBorderLeft() {\r
- return getBorderWidth('l');\r
- }\r
-\r
- public void setBorderLeftColor(Color color) {\r
- setBorderColor('l', color);\r
- }\r
-\r
- public Color getBorderLeftColor() {\r
- return getBorderColor('l');\r
- }\r
+ public LineCompound getBorderCompound(BorderEdge edge) {\r
+ CTLineProperties ln = getCTLine(edge, false);\r
+ if (ln == null || ln.isSetNoFill() || !ln.isSetSolidFill() || !ln.isSetCmpd()) {\r
+ return null;\r
+ }\r
\r
- public void setBorderRight(double width) {\r
- setBorderWidth('r', width);\r
+ return LineCompound.fromOoxmlId(ln.getCmpd().intValue());\r
}\r
\r
- public double getBorderRight() {\r
- return getBorderWidth('r');\r
- }\r
+ @Override\r
+ public void setBorderCompound(BorderEdge edge, LineCompound compound) {\r
+ if (compound == null) {\r
+ throw new IllegalArgumentException("LineCompound need to be specified.");\r
+ }\r
\r
- public void setBorderRightColor(Color color) {\r
- setBorderColor('r', color);\r
+ CTLineProperties ln = setBorderDefaults(edge);\r
+ ln.setCmpd(STCompoundLine.Enum.forInt(compound.ooxmlId));\r
}\r
\r
- public Color getBorderRightColor() {\r
- return getBorderColor('r');\r
- }\r
+ public LineDash getBorderDash(BorderEdge edge) {\r
+ CTLineProperties ln = getCTLine(edge, false);\r
+ if (ln == null || ln.isSetNoFill() || !ln.isSetSolidFill() || !ln.isSetPrstDash()) {\r
+ return null;\r
+ }\r
\r
- public void setBorderTop(double width) {\r
- setBorderWidth('t', width);\r
+ return LineDash.fromOoxmlId(ln.getPrstDash().getVal().intValue());\r
}\r
\r
- public double getBorderTop() {\r
- return getBorderWidth('t');\r
- }\r
+ @Override\r
+ public void setBorderDash(BorderEdge edge, LineDash dash) {\r
+ if (dash == null) {\r
+ throw new IllegalArgumentException("LineDash need to be specified.");\r
+ }\r
\r
- public void setBorderTopColor(Color color) {\r
- setBorderColor('t', color);\r
+ CTLineProperties ln = setBorderDefaults(edge);\r
+ ln.getPrstDash().setVal(STPresetLineDashVal.Enum.forInt(dash.ooxmlId));\r
}\r
\r
- public Color getBorderTopColor() {\r
- return getBorderColor('t');\r
+ public LineCap getBorderCap(BorderEdge edge) {\r
+ CTLineProperties ln = getCTLine(edge, false);\r
+ if (ln == null || ln.isSetNoFill() || !ln.isSetSolidFill() || !ln.isSetCap()) {\r
+ return null;\r
+ }\r
+ \r
+ return LineCap.fromOoxmlId(ln.getCap().intValue());\r
}\r
\r
- public void setBorderBottom(double width) {\r
- setBorderWidth('b', width);\r
- }\r
+ public void setBorderCap(BorderEdge edge, LineCap cap) {\r
+ if (cap == null) {\r
+ throw new IllegalArgumentException("LineCap need to be specified.");\r
+ }\r
\r
- public double getBorderBottom() {\r
- return getBorderWidth('b');\r
+ CTLineProperties ln = setBorderDefaults(edge);\r
+ ln.setCap(STLineCap.Enum.forInt(cap.ooxmlId));\r
}\r
\r
- public void setBorderBottomColor(Color color) {\r
- setBorderColor('b', color);\r
- }\r
\r
- public Color getBorderBottomColor(){\r
- return getBorderColor('b');\r
- }\r
\r
/**\r
* Specifies a solid color fill. The shape is filled entirely with the specified color.\r
void setVMerge(boolean merge_) {\r
((CTTableCell)getXmlObject()).setVMerge(merge_);\r
}\r
- \r
+\r
@Override\r
public void setVerticalAlignment(VerticalAlignment anchor){\r
CTTableCellProperties cellProps = getCellProperties(true);\r
prst.setPrst(STShapeType.RECT);\r
prst.addNewAvLst();\r
CTTextBody txBody = ct.addNewTxBody();\r
- txBody.addNewBodyPr();\r
- txBody.addNewLstStyle();\r
+ XSLFAutoShape.initTextBody(txBody);\r
\r
return ct;\r
}\r
import org.apache.poi.xslf.model.ParagraphPropertyFetcher;\r
import org.apache.xmlbeans.XmlCursor;\r
import org.apache.xmlbeans.XmlObject;\r
-import org.openxmlformats.schemas.drawingml.x2006.main.*;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTColor;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTRegularTextRun;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTSRgbColor;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTTextAutonumberBullet;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTTextBulletSizePercent;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTTextBulletSizePoint;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTTextCharBullet;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTTextCharacterProperties;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTTextField;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTTextFont;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTTextLineBreak;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTTextNormalAutofit;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraph;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraphProperties;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTTextSpacing;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTTextTabStop;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTTextTabStopList;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.STTextAlignType;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.STTextAutonumberScheme;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.STTextFontAlignType;\r
import org.openxmlformats.schemas.presentationml.x2006.main.CTPlaceholder;\r
import org.openxmlformats.schemas.presentationml.x2006.main.STPlaceholderType;\r
\r
\r
}\r
\r
+ @Override\r
public List<XSLFTextRun> getTextRuns(){\r
return _runs;\r
}\r
}\r
}\r
\r
- /**\r
- * Specifies the typeface, or name of the font that is to be used for this text run.\r
- *\r
- * @param typeface the font to apply to this text run.\r
- * The value of <code>null</code> unsets the Typeface attrubute from the underlying xml.\r
- */\r
+ @Override\r
public void setFontFamily(String typeface){\r
setFontFamily(typeface, (byte)-1, (byte)-1, false);\r
}\r
}\r
}\r
\r
- /**\r
- * @return font family or null if not set\r
- */\r
+ @Override\r
public String getFontFamily(){\r
final XSLFTheme theme = _p.getParentShape().getSheet().getTheme();\r
\r
return visitor.getValue() == null ? 0 : visitor.getValue();\r
}\r
\r
- /**\r
- * Specifies whether a run of text will be formatted as strikethrough text.\r
- *\r
- * @param strike whether a run of text will be formatted as strikethrough text.\r
- */\r
+ @Override\r
public void setStrikethrough(boolean strike) {\r
getRPr().setStrike(strike ? STTextStrikeType.SNG_STRIKE : STTextStrikeType.NO_STRIKE);\r
}\r
\r
- /**\r
- * @return whether a run of text will be formatted as strikethrough text. Default is false.\r
- */\r
+ @Override\r
public boolean isStrikethrough() {\r
CharacterPropertyFetcher<Boolean> fetcher = new CharacterPropertyFetcher<Boolean>(_p.getIndentLevel()){\r
public boolean fetch(CTTextCharacterProperties props){\r
return fetcher.getValue() == null ? false : fetcher.getValue();\r
}\r
\r
- /**\r
- * @return whether a run of text will be formatted as a superscript text. Default is false.\r
- */\r
+ @Override\r
public boolean isSuperscript() {\r
CharacterPropertyFetcher<Boolean> fetcher = new CharacterPropertyFetcher<Boolean>(_p.getIndentLevel()){\r
public boolean fetch(CTTextCharacterProperties props){\r
setBaselineOffset(flag ? -25.0 : 0.);\r
}\r
\r
- /**\r
- * @return whether a run of text will be formatted as a superscript text. Default is false.\r
- */\r
+ @Override\r
public boolean isSubscript() {\r
CharacterPropertyFetcher<Boolean> fetcher = new CharacterPropertyFetcher<Boolean>(_p.getIndentLevel()){\r
public boolean fetch(CTTextCharacterProperties props){\r
return fetcher.getValue() == null ? TextCap.NONE : fetcher.getValue();\r
}\r
\r
- /**\r
- * Specifies whether this run of text will be formatted as bold text\r
- *\r
- * @param bold whether this run of text will be formatted as bold text\r
- */\r
+ @Override\r
public void setBold(boolean bold){\r
getRPr().setB(bold);\r
}\r
\r
- /**\r
- * @return whether this run of text is formatted as bold text\r
- */\r
+ @Override\r
public boolean isBold(){\r
CharacterPropertyFetcher<Boolean> fetcher = new CharacterPropertyFetcher<Boolean>(_p.getIndentLevel()){\r
public boolean fetch(CTTextCharacterProperties props){\r
return fetcher.getValue() == null ? false : fetcher.getValue();\r
}\r
\r
- /**\r
- * @param italic whether this run of text is formatted as italic text\r
- */\r
+ @Override\r
public void setItalic(boolean italic){\r
getRPr().setI(italic);\r
}\r
\r
- /**\r
- * @return whether this run of text is formatted as italic text\r
- */\r
+ @Override\r
public boolean isItalic(){\r
CharacterPropertyFetcher<Boolean> fetcher = new CharacterPropertyFetcher<Boolean>(_p.getIndentLevel()){\r
public boolean fetch(CTTextCharacterProperties props){\r
return fetcher.getValue() == null ? false : fetcher.getValue();\r
}\r
\r
- /**\r
- * @param underline whether this run of text is formatted as underlined text\r
- */\r
- public void setUnderline(boolean underline) {\r
+ @Override\r
+ public void setUnderlined(boolean underline) {\r
getRPr().setU(underline ? STTextUnderlineType.SNG : STTextUnderlineType.NONE);\r
}\r
\r
- /**\r
- * @return whether this run of text is formatted as underlined text\r
- */\r
+ @Override\r
public boolean isUnderlined(){\r
CharacterPropertyFetcher<Boolean> fetcher = new CharacterPropertyFetcher<Boolean>(_p.getIndentLevel()){\r
public boolean fetch(CTTextCharacterProperties props){\r
CTPlaceholder ph = shape.getCTPlaceholder();\r
if (ph == null){\r
// if it is a plain text box then take defaults from presentation.xml\r
+ @SuppressWarnings("resource")\r
XMLSlideShow ppt = sheet.getSlideShow();\r
CTTextParagraphProperties themeProps = ppt.getDefaultParagraphStyle(_p.getIndentLevel());\r
if (themeProps != null) {\r
if(italic != isItalic()) setItalic(italic);\r
\r
boolean underline = r.isUnderlined();\r
- if(underline != isUnderlined()) setUnderline(underline);\r
+ if(underline != isUnderlined()) setUnderlined(underline);\r
\r
boolean strike = r.isStrikethrough();\r
if(strike != isStrikethrough()) setStrikethrough(strike);\r
import org.apache.xmlbeans.XmlObject;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextBody;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextBodyProperties;
+import org.openxmlformats.schemas.drawingml.x2006.main.CTTextCharacterProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextListStyle;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraph;
+import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraphProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.STTextAnchoringType;
import org.openxmlformats.schemas.drawingml.x2006.main.STTextVerticalType;
import org.openxmlformats.schemas.drawingml.x2006.main.STTextWrappingType;
txBody.setPArray(null); // remove any existing paragraphs
}
- public void setText(String text){
- clearText();
+ @Override
+ public XSLFTextRun setText(String text) {
+ // copy properties from first paragraph / textrun
+ CTTextParagraphProperties pPr = null;
+ CTTextCharacterProperties rPr = null;
+ if (!_paragraphs.isEmpty()) {
+ XSLFTextParagraph p0 = _paragraphs.get(0);
+ pPr = p0.getXmlObject().getPPr();
+ if (!p0.getTextRuns().isEmpty()) {
+ XSLFTextRun r0 = p0.getTextRuns().get(0);
+ rPr = r0.getXmlObject().getRPr();
+ }
+ }
- addNewTextParagraph().addNewTextRun().setText(text);
+ // can't call clearText otherwise we receive a XmlValueDisconnectedException
+ _paragraphs.clear();
+ CTTextBody txBody = getTextBody(true);
+ int cntPs = txBody.sizeOfPArray();
+
+ // split text by paragraph and new line char
+ XSLFTextRun r = null;
+ for (String paraText : text.split("\\r\\n?|\\n")) {
+ XSLFTextParagraph para = addNewTextParagraph();
+ if (pPr != null) {
+ para.getXmlObject().setPPr(pPr);
+ }
+ boolean first = true;
+ for (String runText : paraText.split("[\u000b]")) {
+ if (!first) {
+ para.addLineBreak();
+ }
+ r = para.addNewTextRun();
+ r.setText(runText);
+ if (rPr != null) {
+ r.getXmlObject().setRPr(rPr);
+ }
+ first = false;
+ }
+ }
+
+ // simply setting a new pArray leads to XmlValueDisconnectedException
+ for (int i = cntPs-1; i >= 0; i--) {
+ txBody.removeP(i);
+ }
+
+ return r;
}
@Override
return paragraph;
}
-
- /**
- * Sets the type of vertical alignment for the text.
- *
- * @param anchor - the type of alignment.
- * A {@code null} values unsets this property.
- */
+ @Override
public void setVerticalAlignment(VerticalAlignment anchor){
CTTextBodyProperties bodyPr = getTextBodyPr();
if (bodyPr != null) {
}
}
- /**
- * Returns the type of vertical alignment for the text.
- *
- * @return the type of vertical alignment
- */
+ @Override
public VerticalAlignment getVerticalAlignment(){
PropertyFetcher<VerticalAlignment> fetcher = new TextBodyPropertyFetcher<VerticalAlignment>(){
public boolean fetch(CTTextBodyProperties props){
return fetcher.getValue() == null ? VerticalAlignment.TOP : fetcher.getValue();
}
- /**
- * Sets if the paragraphs are horizontal centered
- *
- * @param isCentered true, if the paragraphs are horizontal centered
- * A {@code null} values unsets this property.
- *
- * @see TextShape#isHorizontalCentered()
- */
+ @Override
public void setHorizontalCentered(Boolean isCentered){
CTTextBodyProperties bodyPr = getTextBodyPr();
if (bodyPr != null) {
return insets;
}
-
- /**
- * @return whether to wrap words within the bounding rectangle
- */
+ @Override
+ public void setInsets(Insets2D insets) {
+ setTopInset(insets.top);
+ setLeftInset(insets.left);
+ setBottomInset(insets.bottom);
+ setRightInset(insets.right);
+ }
+
+ @Override
public boolean getWordWrap(){
PropertyFetcher<Boolean> fetcher = new TextBodyPropertyFetcher<Boolean>(){
public boolean fetch(CTTextBodyProperties props){
return fetcher.getValue() == null ? true : fetcher.getValue();
}
- /**
- *
- * @param wrap whether to wrap words within the bounding rectangle
- */
+ @Override
public void setWordWrap(boolean wrap){
CTTextBodyProperties bodyPr = getTextBodyPr();
if (bodyPr != null) {
tgtP.copy(srcP);
}
}
+
+ @Override
+ public void setTextPlaceholder(TextPlaceholder placeholder) {
+ switch (placeholder) {
+ default:
+ case NOTES:
+ case HALF_BODY:
+ case QUARTER_BODY:
+ case BODY:
+ setPlaceholder(Placeholder.BODY);
+ break;
+ case TITLE:
+ setPlaceholder(Placeholder.TITLE);
+ break;
+ case CENTER_BODY:
+ setPlaceholder(Placeholder.BODY);
+ setHorizontalCentered(true);
+ break;
+ case CENTER_TITLE:
+ setPlaceholder(Placeholder.CENTERED_TITLE);
+ break;
+ case OTHER:
+ setPlaceholder(Placeholder.CONTENT);
+ break;
+ }
+ }
+
+ @Override
+ public TextPlaceholder getTextPlaceholder() {
+ Placeholder ph = getTextType();
+ if (ph == null) return TextPlaceholder.BODY;
+ switch (ph) {
+ case BODY: return TextPlaceholder.BODY;
+ case TITLE: return TextPlaceholder.TITLE;
+ case CENTERED_TITLE: return TextPlaceholder.CENTER_TITLE;
+ default:
+ case CONTENT: return TextPlaceholder.OTHER;
+ }
+ }
+
+
}
\ No newline at end of file
\r
assertFalse(r.isUnderlined());\r
assertFalse(r.getXmlObject().getRPr().isSetU());\r
- r.setUnderline(true);\r
+ r.setUnderlined(true);\r
assertTrue(r.isUnderlined());\r
assertEquals(STTextUnderlineType.SNG, r.getXmlObject().getRPr().getU());\r
\r
import static org.junit.Assert.assertNotNull;\r
import static org.junit.Assert.assertNull;\r
\r
+import java.io.IOException;\r
+\r
+import org.apache.poi.sl.usermodel.SimpleShape.Placeholder;\r
import org.apache.poi.xslf.XSLFTestDataSamples;\r
import org.junit.Test;\r
\r
public class TestXSLFNotes {\r
\r
@Test\r
- public void createNewNote() {\r
+ public void createNewNote() throws IOException {\r
\r
XMLSlideShow ppt = new XMLSlideShow();\r
XSLFSlide slide1 = ppt.createSlide();\r
}\r
assertNotNull(note);\r
assertEquals("New Note", note);\r
+ \r
+ ppt.close();\r
}\r
\r
@Test\r
- public void addNote() {\r
+ public void addNote() throws IOException {\r
\r
XMLSlideShow ppt = XSLFTestDataSamples.openSampleDocument("sample.pptx");\r
\r
}\r
assertNotNull(note);\r
assertEquals("New Note", note);\r
+ \r
+ ppt.close();\r
}\r
\r
@Test\r
- public void replaceNotes() {\r
+ public void replaceNotes() throws IOException {\r
\r
XMLSlideShow ppt = XSLFTestDataSamples.openSampleDocument("sample.pptx");\r
\r
assertNotNull(note);\r
assertEquals("New Note", note);\r
}\r
+ \r
+ ppt.close();\r
}\r
}\r
import java.util.List;\r
\r
import org.apache.poi.sl.draw.geom.TestPresetGeometries;\r
+import org.apache.poi.sl.usermodel.SimpleShape.Placeholder;\r
import org.apache.poi.sl.usermodel.StrokeStyle.LineCap;\r
import org.apache.poi.sl.usermodel.StrokeStyle.LineDash;\r
import org.apache.poi.util.Units;\r
}\r
\r
@Test\r
- public void testDefaultProperties() {\r
+ public void testDefaultProperties() throws IOException {\r
XMLSlideShow ppt = XSLFTestDataSamples.openSampleDocument("shapes.pptx");\r
\r
XSLFSlide slide6 = ppt.getSlides().get(5);\r
assertEquals(50000, ref5.getLumModArray(0).getVal());\r
assertEquals("accent1", ref5.getVal().toString());\r
assertEquals(new Color(79, 129, 189), s5.getFillColor());\r
+ \r
+ ppt.close();\r
}\r
\r
@Test\r
- public void testAnchor(){\r
+ public void testAnchor() throws IOException {\r
XMLSlideShow ppt = XSLFTestDataSamples.openSampleDocument("shapes.pptx");\r
List<XSLFSlide> slide = ppt.getSlides();\r
\r
assertNotNull(layout5.getSlideMaster().getTextShapeByType(Placeholder.TITLE).getSpPr().getXfrm());\r
assertEquals(shTitle.getAnchor(), layout5.getSlideMaster().getTextShapeByType(Placeholder.TITLE).getAnchor());\r
\r
+ ppt.close();\r
}\r
\r
@SuppressWarnings({ "deprecation", "unused" })\r
==================================================================== */\r
package org.apache.poi.xslf.usermodel;\r
\r
-import static org.junit.Assert.*;\r
+import static org.junit.Assert.assertEquals;\r
+import static org.junit.Assert.assertNotNull;\r
+import static org.junit.Assert.assertNull;\r
+import static org.junit.Assert.assertSame;\r
+import static org.junit.Assert.assertTrue;\r
\r
+import java.awt.Color;\r
+import java.io.IOException;\r
+import java.util.List;\r
+\r
+import org.apache.poi.sl.usermodel.TableCell.BorderEdge;\r
import org.apache.poi.sl.usermodel.VerticalAlignment;\r
import org.apache.poi.xslf.XSLFTestDataSamples;\r
import org.junit.Test;\r
import org.openxmlformats.schemas.drawingml.x2006.main.CTTableCell;\r
import org.openxmlformats.schemas.presentationml.x2006.main.CTGraphicalObjectFrame;\r
\r
-import java.awt.Color;\r
-import java.util.List;\r
-\r
/**\r
* @author Yegor Kozlov\r
*/\r
public class TestXSLFTable {\r
@Test\r
- public void testRead(){\r
+ public void testRead() throws IOException {\r
XMLSlideShow ppt = XSLFTestDataSamples.openSampleDocument("shapes.pptx");\r
\r
XSLFSlide slide = ppt.getSlides().get(3);\r
assertEquals("A1", cells1.get(0).getText());\r
assertEquals("B1", cells1.get(1).getText());\r
assertEquals("C1", cells1.get(2).getText());\r
+ \r
+ ppt.close();\r
}\r
\r
@Test\r
- public void testCreate() {\r
+ public void testCreate() throws IOException {\r
XMLSlideShow ppt = new XMLSlideShow();\r
XSLFSlide slide = ppt.createSlide();\r
\r
cell1.addNewTextParagraph().addNewTextRun().setText("Apache");\r
assertEquals("Apache", cell1.getText());\r
\r
- assertEquals(1.0, cell1.getBorderBottom(), 0);\r
- cell1.setBorderBottom(2.0);\r
- assertEquals(2.0, cell1.getBorderBottom(), 0);\r
- assertNull(cell1.getBorderBottomColor());\r
- cell1.setBorderBottomColor(Color.yellow);\r
- assertEquals(Color.yellow, cell1.getBorderBottomColor());\r
-\r
- assertEquals(1.0, cell1.getBorderTop(), 0);\r
- cell1.setBorderTop(2.0);\r
- assertEquals(2.0, cell1.getBorderTop(), 0);\r
- assertNull(cell1.getBorderTopColor());\r
- cell1.setBorderTopColor(Color.yellow);\r
- assertEquals(Color.yellow, cell1.getBorderTopColor());\r
-\r
- assertEquals(1.0, cell1.getBorderLeft(), 0);\r
- cell1.setBorderLeft(2.0);\r
- assertEquals(2.0, cell1.getBorderLeft(), 0);\r
- assertNull(cell1.getBorderLeftColor());\r
- cell1.setBorderLeftColor(Color.yellow);\r
- assertEquals(Color.yellow, cell1.getBorderLeftColor());\r
-\r
- assertEquals(1.0, cell1.getBorderRight(), 0);\r
- cell1.setBorderRight(2.0);\r
- assertEquals(2.0, cell1.getBorderRight(), 0);\r
- assertNull(cell1.getBorderRightColor());\r
- cell1.setBorderRightColor(Color.yellow);\r
- assertEquals(Color.yellow, cell1.getBorderRightColor());\r
+ for (BorderEdge edge : BorderEdge.values()) {\r
+ assertNull(cell1.getBorderWidth(edge));\r
+ cell1.setBorderWidth(edge, 2.0);\r
+ assertEquals(2.0, cell1.getBorderWidth(edge), 0);\r
+ assertNull(cell1.getBorderColor(edge));\r
+ cell1.setBorderColor(edge, Color.yellow);\r
+ assertEquals(Color.yellow, cell1.getBorderColor(edge));\r
+ }\r
\r
assertEquals(VerticalAlignment.TOP, cell1.getVerticalAlignment());\r
cell1.setVerticalAlignment(VerticalAlignment.MIDDLE);\r
assertEquals(VerticalAlignment.MIDDLE, cell1.getVerticalAlignment());\r
cell1.setVerticalAlignment(null);\r
assertEquals(VerticalAlignment.TOP, cell1.getVerticalAlignment());\r
+ \r
+ ppt.close();\r
}\r
}
\ No newline at end of file
import static org.junit.Assert.assertEquals;\r
import static org.junit.Assert.assertNull;\r
\r
+import java.io.IOException;\r
+\r
+import org.apache.poi.sl.usermodel.SimpleShape.Placeholder;\r
import org.junit.Test;\r
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextCharacterProperties;\r
\r
public class TestXSLFTextBox {\r
\r
@Test\r
- public void testPlaceholder() {\r
+ public void testPlaceholder() throws IOException {\r
XMLSlideShow ppt = new XMLSlideShow();\r
XSLFSlide slide = ppt.createSlide();\r
\r
shape.setPlaceholder(null);\r
assertNull(shape.getTextType());\r
shape.setText("Apache POI");\r
+ \r
+ ppt.close();\r
}\r
\r
/**\r
* text box inherits default text proeprties from presentation.xml\r
*/\r
@Test\r
- public void testDefaultTextStyle() {\r
+ public void testDefaultTextStyle() throws IOException {\r
XMLSlideShow ppt = new XMLSlideShow();\r
XSLFSlide slide = ppt.createSlide();\r
\r
\r
pPr.unsetSz(); // Should never be\r
assertNull(r.getFontSize());\r
+ \r
+ ppt.close();\r
}\r
}
\ No newline at end of file
import java.io.IOException;\r
import java.util.List;\r
\r
+import org.apache.poi.sl.usermodel.SimpleShape.Placeholder;\r
import org.apache.poi.sl.usermodel.TextParagraph.TextAlign;\r
import org.apache.poi.sl.usermodel.VerticalAlignment;\r
import org.apache.poi.xslf.XSLFTestDataSamples;\r
public class TestXSLFTextShape {\r
\r
@Test\r
- public void testLayouts(){\r
+ public void testLayouts() throws IOException {\r
XMLSlideShow ppt = XSLFTestDataSamples.openSampleDocument("layouts.pptx");\r
\r
List<XSLFSlide> slide = ppt.getSlides();\r
verifySlide7(slide.get(6));\r
verifySlide8(slide.get(7));\r
verifySlide10(slide.get(9));\r
+ \r
+ ppt.close();\r
}\r
\r
void verifySlide1(XSLFSlide slide){\r
txt.setTopInset(0);
txt.setLeftInset(0);
txt.setRightInset(0);
- txt.setWordWrap(HSLFTextBox.WrapNone);
+ txt.setWordWrap(false);
txt.setHorizontalCentered(false);
txt.setVerticalAlignment(VerticalAlignment.MIDDLE);
float[] dash = bs.getDashArray();
if (dash != null) {
//TODO: implement more dashing styles
- shape.setLineDashing(StrokeStyle.LineDash.DASH);
+ shape.setLineDash(StrokeStyle.LineDash.DASH);
}
}
}
+++ /dev/null
-/* ====================================================================
- 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.hslf.record.OEPlaceholderAtom;
-import org.apache.poi.hslf.usermodel.HSLFShape;
-import org.apache.poi.hslf.usermodel.HSLFTextBox;
-import org.apache.poi.hslf.usermodel.HSLFTextParagraph;
-import org.apache.poi.hslf.exceptions.HSLFException;
-import org.apache.poi.sl.usermodel.ShapeContainer;
-
-import java.io.ByteArrayOutputStream;
-
-/**
- * Represents a Placeholder in PowerPoint.
- *
- * @author Yegor Kozlov
- */
-public final class Placeholder extends HSLFTextBox {
-
- protected Placeholder(EscherContainerRecord escherRecord, ShapeContainer<HSLFShape,HSLFTextParagraph> parent){
- super(escherRecord, parent);
- }
-
- public Placeholder(ShapeContainer<HSLFShape,HSLFTextParagraph> parent){
- super(parent);
- }
-
- public Placeholder(){
- super();
- }
-
- /**
- * Create a new Placeholder and initialize internal structures
- *
- * @return the created <code>EscherContainerRecord</code> which holds shape data
- */
- protected EscherContainerRecord createSpContainer(boolean isChild){
- _escherContainer = super.createSpContainer(isChild);
-
- EscherSpRecord spRecord = _escherContainer.getChildById(EscherSpRecord.RECORD_ID);
- spRecord.setFlags(EscherSpRecord.FLAG_HAVEANCHOR | EscherSpRecord.FLAG_HAVEMASTER);
-
- EscherClientDataRecord cldata = new EscherClientDataRecord();
- cldata.setOptions((short)15);
-
- AbstractEscherOptRecord opt = getEscherOptRecord();
-
- //Placeholders can't be grouped
- setEscherProperty(opt, EscherProperties.PROTECTION__LOCKAGAINSTGROUPING, 262144);
-
- //OEPlaceholderAtom tells powerpoint that this shape is a placeholder
- //
- OEPlaceholderAtom oep = new OEPlaceholderAtom();
- /**
- * Extarct from MSDN:
- *
- * There is a special case when the placeholder does not have a position in the layout.
- * This occurs when the user has moved the placeholder from its original position.
- * In this case the placeholder ID is -1.
- */
- oep.setPlacementId(-1);
-
- oep.setPlaceholderId(OEPlaceholderAtom.Body);
-
- //convert hslf into ddf record
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- try {
- oep.writeOut(out);
- } catch(Exception e){
- throw new HSLFException(e);
- }
- cldata.setRemainingData(out.toByteArray());
-
- //append placeholder container before EscherTextboxRecord
- _escherContainer.addChildBefore(cldata, EscherTextboxRecord.RECORD_ID);
-
- return _escherContainer;
- }
-}
protected void setDefaultTextProperties(HSLFTextParagraph _txtrun){
setVerticalAlignment(VerticalAlignment.MIDDLE);
setHorizontalCentered(true);
- setWordWrap(HSLFTextBox.WrapNone);
+ setWordWrap(false);
}
/**
*/
public class HSLFGroupShape extends HSLFShape
implements HSLFShapeContainer, GroupShape<HSLFShape,HSLFTextParagraph> {
-
/**
* Create a new ShapeGroup. This constructor is used when a new shape is created.
*
super(escherRecord, parent);
}
- /**
- * Sets the anchor (the bounding box rectangle) of this shape.
- * All coordinates should be expressed in Master units (576 dpi).
- *
- * @param anchor new anchor
- */
- public void setAnchor(java.awt.Rectangle anchor){
-
+ @Override
+ public void setAnchor(Rectangle anchor) {
EscherClientAnchorRecord clientAnchor = getEscherChild(EscherClientAnchorRecord.RECORD_ID);
- //hack. internal variable EscherClientAnchorRecord.shortRecord can be
- //initialized only in fillFields(). We need to set shortRecord=false;
- byte[] header = new byte[16];
- LittleEndian.putUShort(header, 0, 0);
- LittleEndian.putUShort(header, 2, 0);
- LittleEndian.putInt(header, 4, 8);
- clientAnchor.fillFields(header, 0, null);
-
- clientAnchor.setFlag((short)Units.pointsToMaster(anchor.y));
- clientAnchor.setCol1((short)Units.pointsToMaster(anchor.x));
- clientAnchor.setDx1((short)Units.pointsToMaster(anchor.width + anchor.x));
- clientAnchor.setRow1((short)Units.pointsToMaster(anchor.height + anchor.y));
-
- EscherSpgrRecord spgr = getEscherChild(EscherSpgrRecord.RECORD_ID);
-
- spgr.setRectX1(Units.pointsToMaster(anchor.x));
- spgr.setRectY1(Units.pointsToMaster(anchor.y));
- spgr.setRectX2(Units.pointsToMaster(anchor.x + anchor.width));
- spgr.setRectY2(Units.pointsToMaster(anchor.y + anchor.height));
+ boolean isInitialized = !(clientAnchor.getDx1() == 0 && clientAnchor.getRow1() == 0);
+
+ if (isInitialized) {
+ moveAndScale(anchor);
+ } else {
+ setExteriorAnchor(anchor);
+ }
}
@Override
spgr.setRectY1(y1);
spgr.setRectX2(x2);
spgr.setRectY2(y2);
-
}
@Override
return new Rectangle(x1,y1,x2-x1,y2-y1);
}
+ protected void setExteriorAnchor(Rectangle anchor) {
+ EscherClientAnchorRecord clientAnchor = getEscherChild(EscherClientAnchorRecord.RECORD_ID);
+
+ //hack. internal variable EscherClientAnchorRecord.shortRecord can be
+ //initialized only in fillFields(). We need to set shortRecord=false;
+ byte[] header = new byte[16];
+ LittleEndian.putUShort(header, 0, 0);
+ LittleEndian.putUShort(header, 2, 0);
+ LittleEndian.putInt(header, 4, 8);
+ clientAnchor.fillFields(header, 0, null);
+
+ // All coordinates need to be converted to Master units (576 dpi)
+ clientAnchor.setFlag((short)Units.pointsToMaster(anchor.y));
+ clientAnchor.setCol1((short)Units.pointsToMaster(anchor.x));
+ clientAnchor.setDx1((short)Units.pointsToMaster(anchor.width + anchor.x));
+ clientAnchor.setRow1((short)Units.pointsToMaster(anchor.height + anchor.y));
+
+ // TODO: does this make sense?
+ setInteriorAnchor(anchor);
+ }
+
/**
* Create a new ShapeGroup and create an instance of <code>EscherSpgrContainer</code> which represents a group of shapes
*/
}
/**
- * Moves this <code>ShapeGroup</code> to the specified location.
- * <p>
- * @param x the x coordinate of the top left corner of the shape in new location
- * @param y the y coordinate of the top left corner of the shape in new location
+ * Moves and scales this <code>ShapeGroup</code> to the specified anchor.
*/
- public void moveTo(int x, int y){
- Rectangle anchor = getAnchor();
- int dx = x - anchor.x;
- int dy = y - anchor.y;
- anchor.translate(dx, dy);
- setAnchor(anchor);
+ protected void moveAndScale(Rectangle anchorDest){
+ Rectangle anchorSrc = getAnchor();
+ double scaleX = (anchorSrc.width == 0) ? 0 : anchorDest.width / (double)anchorSrc.width;
+ double scaleY = (anchorSrc.height == 0) ? 0 : anchorDest.height / (double)anchorSrc.height;
+ setExteriorAnchor(anchorDest);
for (HSLFShape shape : getShapes()) {
Rectangle chanchor = shape.getAnchor();
- chanchor.translate(dx, dy);
- shape.setAnchor(chanchor);
+ int x = (int)Math.rint(anchorDest.x+(chanchor.x-anchorSrc.x)*scaleX);
+ int y = (int)Math.rint(anchorDest.y+(chanchor.y-anchorSrc.y)*scaleY);
+ int width = (int)Math.rint(chanchor.width*scaleX);
+ int height = (int)Math.rint(chanchor.height*scaleY);
+ shape.setAnchor(new Rectangle(x, y, width, height));
}
}
throw new UnsupportedOperationException();
}
- /**
- * @return the shapes contained in this group container
- */
@Override
public List<HSLFShape> getShapes() {
// Out escher container record should contain several
--- /dev/null
+/* ====================================================================
+ 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.usermodel;
+
+import org.apache.poi.ddf.EscherContainerRecord;
+import org.apache.poi.sl.usermodel.SimpleShape.Placeholder;
+import org.apache.poi.sl.usermodel.ShapeContainer;
+
+/**
+ * Represents a Placeholder in PowerPoint.
+ *
+ * @author Yegor Kozlov
+ */
+public final class HSLFPlaceholder extends HSLFTextBox {
+
+ protected HSLFPlaceholder(EscherContainerRecord escherRecord, ShapeContainer<HSLFShape,HSLFTextParagraph> parent){
+ super(escherRecord, parent);
+ }
+
+ public HSLFPlaceholder(ShapeContainer<HSLFShape,HSLFTextParagraph> parent){
+ super(parent);
+ }
+
+ public HSLFPlaceholder(){
+ super();
+ }
+
+ /**
+ * Create a new Placeholder and initialize internal structures
+ *
+ * @return the created <code>EscherContainerRecord</code> which holds shape data
+ */
+ protected EscherContainerRecord createSpContainer(boolean isChild){
+ _escherContainer = super.createSpContainer(isChild);
+
+ setPlaceholder(Placeholder.BODY);
+
+ return _escherContainer;
+ }
+}
return getShapeType().nativeName;
}
- /**
- * @return type of the shape.
- * @see org.apache.poi.hslf.record.RecordTypes
- */
public ShapeType getShapeType(){
EscherSpRecord spRecord = getEscherChild(EscherSpRecord.RECORD_ID);
return ShapeType.forId(spRecord.getShapeType(), false);
}
- /**
- * @param type type of the shape.
- * @see org.apache.poi.hslf.record.RecordTypes
- */
public void setShapeType(ShapeType type){
EscherSpRecord spRecord = getEscherChild(EscherSpRecord.RECORD_ID);
spRecord.setShapeType( (short) type.nativeId );
* @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(float x, float y){
+ public final void moveTo(float x, float y) {
+ // This convenience method should be implemented via setAnchor in subclasses
+ // see HSLFGroupShape.setAnchor() for a reference
Rectangle anchor = getAnchor();
anchor.setRect(x, y, anchor.getWidth(), anchor.getHeight());
setAnchor(anchor);
EscherPropertyFactory f = new EscherPropertyFactory();
List<EscherProperty> props = f.createProperties( opt.serialize(), 8, opt.getInstance() );
for (EscherProperty ep : props) {
- if (ep.getPropertyNumber() == 0x39F
+ if (ep.getPropertyNumber() == EscherProperties.GROUPSHAPE__TABLEPROPERTIES
&& ep instanceof EscherSimpleProperty
&& ((EscherSimpleProperty)ep).getPropertyValue() == 1) {
isTable = true;
}
}
- HSLFGroupShape group = (isTable)
- ? new HSLFTable(spContainer, parent)
- : new HSLFGroupShape(spContainer, parent);
+ HSLFGroupShape group;
+ if (isTable) {
+ group = new HSLFTable(spContainer, parent);
+
+ } else {
+ group = new HSLFGroupShape(spContainer, parent);
+ }
return group;
}
shape = new HSLFTextBox(spContainer, parent);
break;
case HOST_CONTROL:
- case FRAME: {
- InteractiveInfo info = getClientDataRecord(spContainer, RecordTypes.InteractiveInfo.typeID);
- OEShapeAtom oes = getClientDataRecord(spContainer, RecordTypes.OEShapeAtom.typeID);
- if(info != null && info.getInteractiveInfoAtom() != null){
- switch(info.getInteractiveInfoAtom().getAction()){
- case InteractiveInfoAtom.ACTION_OLE:
- shape = new OLEShape(spContainer, parent);
- break;
- case InteractiveInfoAtom.ACTION_MEDIA:
- shape = new MovieShape(spContainer, parent);
- break;
- default:
- break;
- }
- } else if (oes != null){
- shape = new OLEShape(spContainer, parent);
- }
-
- if(shape == null) shape = new HSLFPictureShape(spContainer, parent);
+ case FRAME:
+ shape = createFrame(spContainer, parent);
break;
- }
case LINE:
shape = new HSLFLine(spContainer, parent);
break;
- case NOT_PRIMITIVE: {
- AbstractEscherOptRecord opt = HSLFShape.getEscherChild(spContainer, EscherOptRecord.RECORD_ID);
- EscherProperty prop = HSLFShape.getEscherProperty(opt, EscherProperties.GEOMETRY__VERTICES);
- if(prop != null)
- shape = new HSLFFreeformShape(spContainer, parent);
- else {
- logger.log(POILogger.INFO, "Creating AutoShape for a NotPrimitive shape");
- shape = new HSLFAutoShape(spContainer, parent);
- }
+ case NOT_PRIMITIVE:
+ shape = createNonPrimitive(spContainer, parent);
break;
- }
default:
- shape = new HSLFAutoShape(spContainer, parent);
+ EscherTextboxRecord etr = spContainer.getChildById(EscherTextboxRecord.RECORD_ID);
+ if (parent instanceof HSLFTable && etr != null) {
+ shape = new HSLFTableCell(spContainer, (HSLFTable)parent);
+ } else {
+ shape = new HSLFAutoShape(spContainer, parent);
+ }
break;
}
return shape;
-
}
+ private static HSLFShape createFrame(EscherContainerRecord spContainer, ShapeContainer<HSLFShape,HSLFTextParagraph> parent) {
+ InteractiveInfo info = getClientDataRecord(spContainer, RecordTypes.InteractiveInfo.typeID);
+ if(info != null && info.getInteractiveInfoAtom() != null){
+ switch(info.getInteractiveInfoAtom().getAction()){
+ case InteractiveInfoAtom.ACTION_OLE:
+ return new OLEShape(spContainer, parent);
+ case InteractiveInfoAtom.ACTION_MEDIA:
+ return new MovieShape(spContainer, parent);
+ default:
+ break;
+ }
+ }
+
+ OEShapeAtom oes = getClientDataRecord(spContainer, RecordTypes.OEShapeAtom.typeID);
+ if (oes != null){
+ return new OLEShape(spContainer, parent);
+ }
+
+ return new HSLFPictureShape(spContainer, parent);
+ }
+
+ private static HSLFShape createNonPrimitive(EscherContainerRecord spContainer, ShapeContainer<HSLFShape,HSLFTextParagraph> parent) {
+ AbstractEscherOptRecord opt = HSLFShape.getEscherChild(spContainer, EscherOptRecord.RECORD_ID);
+ EscherProperty prop = HSLFShape.getEscherProperty(opt, EscherProperties.GEOMETRY__VERTICES);
+ if(prop != null) {
+ return new HSLFFreeformShape(spContainer, parent);
+ }
+
+ logger.log(POILogger.INFO, "Creating AutoShape for a NotPrimitive shape");
+ return new HSLFAutoShape(spContainer, parent);
+ }
+
@SuppressWarnings("unchecked")
protected static <T extends Record> T getClientDataRecord(EscherContainerRecord spContainer, int recordType) {
- Record oep = null;
for (Iterator<EscherRecord> it = spContainer.getChildIterator(); it.hasNext();) {
EscherRecord obj = it.next();
if (obj.getRecordId() == EscherClientDataRecord.RECORD_ID) {
byte[] data = obj.serialize();
- Record[] records = Record.findChildRecords(data, 8, data.length - 8);
- for (int j = 0; j < records.length; j++) {
- if (records[j].getRecordType() == recordType) {
- return (T)records[j];
+ for (Record r : Record.findChildRecords(data, 8, data.length - 8)) {
+ if (r.getRecordType() == recordType) {
+ return (T)r;
}
}
}
}
- return (T)oep;
+ return null;
}
}
throw new IllegalArgumentException("numRows and numCols must be greater than 0");
}
HSLFTable s = new HSLFTable(numRows,numCols);
- s.setAnchor(new Rectangle(0, 0, 100, 100));
+ // anchor is set in constructor based on numRows/numCols
addShape(s);
return s;
}
import org.apache.poi.sl.draw.geom.*;
import org.apache.poi.sl.usermodel.*;
import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint;
+import org.apache.poi.sl.usermodel.StrokeStyle.LineCap;
import org.apache.poi.sl.usermodel.StrokeStyle.LineCompound;
import org.apache.poi.sl.usermodel.StrokeStyle.LineDash;
import org.apache.poi.util.LittleEndian;
return clr == null ? Color.black : clr;
}
+ /**
+ * Gets line cap.
+ *
+ * @return cap of the line.
+ */
+ public LineCap getLineCap(){
+ AbstractEscherOptRecord opt = getEscherOptRecord();
+ EscherSimpleProperty prop = getEscherProperty(opt, EscherProperties.LINESTYLE__LINEENDCAPSTYLE);
+ return (prop == null) ? LineCap.FLAT : LineCap.fromNativeId(prop.getPropertyValue());
+ }
+
+ /**
+ * Sets line cap.
+ *
+ * @param pen new style of the line.
+ */
+ public void setLineCap(LineCap pen){
+ AbstractEscherOptRecord opt = getEscherOptRecord();
+ setEscherProperty(opt, EscherProperties.LINESTYLE__LINEENDCAPSTYLE, pen == LineCap.FLAT ? -1 : pen.nativeId);
+ }
+
/**
* Gets line dashing.
*
* @return dashing of the line.
*/
- public LineDash getLineDashing(){
+ public LineDash getLineDash(){
AbstractEscherOptRecord opt = getEscherOptRecord();
EscherSimpleProperty prop = getEscherProperty(opt, EscherProperties.LINESTYLE__LINEDASHING);
return (prop == null) ? LineDash.SOLID : LineDash.fromNativeId(prop.getPropertyValue());
*
* @param pen new style of the line.
*/
- public void setLineDashing(LineDash pen){
+ public void setLineDash(LineDash pen){
AbstractEscherOptRecord opt = getEscherOptRecord();
setEscherProperty(opt, EscherProperties.LINESTYLE__LINEDASHING, pen == LineDash.SOLID ? -1 : pen.nativeId);
}
EscherSimpleProperty prop = getEscherProperty(opt, EscherProperties.LINESTYLE__LINESTYLE);
return (prop == null) ? LineCompound.SINGLE : LineCompound.fromNativeId(prop.getPropertyValue());
}
-
+
/**
* Sets the line compound style
*
}
public LineDash getLineDash() {
- return HSLFSimpleShape.this.getLineDashing();
+ return HSLFSimpleShape.this.getLineDash();
}
public LineCompound getLineCompound() {
public double getLineWidth() {
return HSLFSimpleShape.this.getLineWidth();
}
-
+
};
}
- /**
- * The color used to fill this shape.
- */
- public Color getFillColor(){
+ @Override
+ public Color getFillColor() {
return getFill().getForegroundColor();
}
- /**
- * The color used to fill this shape.
- *
- * @param color the background color
- */
- public void setFillColor(Color color){
+ @Override
+ public void setFillColor(Color color) {
getFill().setForegroundColor(color);
}
if (name == null || !name.matches("adj([1-9]|10)?")) {
throw new IllegalArgumentException("Adjust value '"+name+"' not supported.");
}
-
+
name = name.replace("adj", "");
if ("".equals(name)) name = "1";
-
+
short escherProp;
switch (Integer.parseInt(name)) {
case 1: escherProp = EscherProperties.GEOMETRY__ADJUSTVALUE; break;
case 10: escherProp = EscherProperties.GEOMETRY__ADJUST10VALUE; break;
default: throw new RuntimeException();
}
-
+
int adjval = getEscherProperty(escherProp, -1);
return (adjval == -1) ? null : new Guide(name, "val "+adjval);
}
logger.log(POILogger.WARN, "No preset shape definition for shapeType: "+name);
return null;
}
-
+
return geom;
}
int offY = (prop == null) ? 0 : prop.getPropertyValue();
return Math.toDegrees(Math.atan2(offY, offX));
}
-
+
public double getShadowDistance() {
AbstractEscherOptRecord opt = getEscherOptRecord();
EscherSimpleProperty prop = getEscherProperty(opt, EscherProperties.SHADOWSTYLE__OFFSETX);
public Color getShadowColor(){
Color clr = getColor(EscherProperties.SHADOWSTYLE__COLOR, EscherProperties.SHADOWSTYLE__OPACITY, -1);
return clr == null ? Color.black : clr;
- }
-
+ }
+
public Shadow<HSLFShape,HSLFTextParagraph> getShadow() {
AbstractEscherOptRecord opt = getEscherOptRecord();
EscherProperty shadowType = opt.lookup(EscherProperties.SHADOWSTYLE__TYPE);
if (shadowType == null) return null;
-
+
return new Shadow<HSLFShape,HSLFTextParagraph>(){
public SimpleShape<HSLFShape,HSLFTextParagraph> getShadowParent() {
return HSLFSimpleShape.this;
public SolidPaint getFillStyle() {
return DrawPaint.createSolidPaint(getShadowColor());
}
-
+
};
}
}
};
}
-}
+
+ protected void setPlaceholder(Placeholder placeholder) {
+ EscherSpRecord spRecord = _escherContainer.getChildById(EscherSpRecord.RECORD_ID);
+ int flags = spRecord.getFlags();
+ flags |= EscherSpRecord.FLAG_HAVEANCHOR | EscherSpRecord.FLAG_HAVEMASTER;
+ spRecord.setFlags(flags);
+
+ EscherClientDataRecord cldata = _escherContainer.getChildById(EscherClientDataRecord.RECORD_ID);
+ if (cldata == null) {
+ cldata = new EscherClientDataRecord();
+ // append placeholder container before EscherTextboxRecord
+ _escherContainer.addChildBefore(cldata, EscherTextboxRecord.RECORD_ID);
+ }
+ cldata.setOptions((short)15);
+
+ AbstractEscherOptRecord opt = getEscherOptRecord();
+
+ // Placeholders can't be grouped
+ setEscherProperty(opt, EscherProperties.PROTECTION__LOCKAGAINSTGROUPING, 262144);
+
+ // OEPlaceholderAtom tells powerpoint that this shape is a placeholder
+ OEPlaceholderAtom oep = new OEPlaceholderAtom();
+
+ /**
+ * Extarct from MSDN:
+ *
+ * There is a special case when the placeholder does not have a position in the layout.
+ * This occurs when the user has moved the placeholder from its original position.
+ * In this case the placeholder ID is -1.
+ */
+ oep.setPlacementId(-1);
+
+ boolean isMaster = (getSheet() instanceof HSLFSlideMaster);
+ boolean isNotes = (getSheet() instanceof HSLFNotes);
+ byte phId;
+ switch (placeholder) {
+ case TITLE:
+ phId = (isMaster) ? OEPlaceholderAtom.MasterTitle : OEPlaceholderAtom.Title;
+ break;
+ case BODY:
+ phId = (isMaster) ? OEPlaceholderAtom.MasterBody :
+ ((isNotes) ? OEPlaceholderAtom.NotesBody : OEPlaceholderAtom.Body);
+ break;
+ case CENTERED_TITLE:
+ phId = (isMaster) ? OEPlaceholderAtom.MasterCenteredTitle : OEPlaceholderAtom.CenteredTitle;
+ break;
+ case SUBTITLE:
+ phId = (isMaster) ? OEPlaceholderAtom.MasterSubTitle : OEPlaceholderAtom.Subtitle;
+ break;
+ case DATETIME:
+ phId = OEPlaceholderAtom.MasterDate;
+ break;
+ case SLIDE_NUMBER:
+ phId = OEPlaceholderAtom.MasterSlideNumber;
+ break;
+ case FOOTER:
+ phId = OEPlaceholderAtom.MasterFooter;
+ break;
+ case HEADER:
+ phId = OEPlaceholderAtom.MasterHeader;
+ break;
+ case DGM:
+ case CHART:
+ phId = OEPlaceholderAtom.Graph;
+ break;
+ case TABLE:
+ phId = OEPlaceholderAtom.Table;
+ break;
+ case PICTURE:
+ case CLIP_ART:
+ phId = OEPlaceholderAtom.ClipArt;
+ break;
+ case MEDIA:
+ phId = OEPlaceholderAtom.MediaClip;
+ break;
+ case SLIDE_IMAGE:
+ phId = (isMaster) ? OEPlaceholderAtom.MasterNotesSlideImage : OEPlaceholderAtom.NotesSlideImage;
+ break;
+ default:
+ case CONTENT:
+ phId = OEPlaceholderAtom.Object;
+ break;
+ }
+ oep.setPlaceholderId(phId);
+
+ //convert hslf into ddf record
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ try {
+ oep.writeOut(out);
+ } catch(Exception e){
+ throw new HSLFException(e);
+ }
+ cldata.setRemainingData(out.toByteArray());
+ }
+
+
+ @Override
+ public void setStrokeStyle(Object... styles) {
+ if (styles.length == 0) {
+ // remove stroke
+ setLineColor(null);
+ return;
+ }
+
+ // TODO: handle PaintStyle
+ for (Object st : styles) {
+ if (st instanceof Number) {
+ setLineWidth(((Number)st).doubleValue());
+ } else if (st instanceof LineCap) {
+ setLineCap((LineCap)st);
+ } else if (st instanceof LineDash) {
+ setLineDash((LineDash)st);
+ } else if (st instanceof LineCompound) {
+ setLineCompound((LineCompound)st);
+ } else if (st instanceof Color) {
+ setLineColor((Color)st);
+ }
+ }
+ }
+}
\ No newline at end of file
import org.apache.poi.ddf.EscherSpRecord;
import org.apache.poi.hslf.model.Comment;
import org.apache.poi.hslf.model.HeadersFooters;
-import org.apache.poi.hslf.model.Placeholder;
import org.apache.poi.hslf.record.ColorSchemeAtom;
import org.apache.poi.hslf.record.Comment2000;
import org.apache.poi.hslf.record.EscherTextboxWrapper;
* @return <code>TextBox</code> object that represents the slide's title.
*/
public HSLFTextBox addTitle() {
- Placeholder pl = new Placeholder();
+ HSLFPlaceholder pl = new HSLFPlaceholder();
pl.setShapeType(ShapeType.RECT);
pl.setRunType(TextHeaderAtom.TITLE_TYPE);
pl.setText("Click to edit title");
return HSLFSoundData.find(_documentRecord);
}
- /**
- * Return the current page size
- */
+ @Override
public Dimension getPageSize() {
DocumentAtom docatom = _documentRecord.getDocumentAtom();
int pgx = (int)Units.masterToPoints((int)docatom.getSlideSizeX());
return new Dimension(pgx, pgy);
}
- /**
- * Change the current page size
- *
- * @param pgsize
- * page size (in points)
- */
+ @Override
public void setPageSize(Dimension pgsize) {
DocumentAtom docatom = _documentRecord.getDocumentAtom();
docatom.setSlideSizeX(Units.pointsToMaster(pgsize.width));
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
-import java.util.Iterator;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
import org.apache.poi.ddf.AbstractEscherOptRecord;
import org.apache.poi.ddf.EscherArrayProperty;
import org.apache.poi.ddf.EscherContainerRecord;
import org.apache.poi.ddf.EscherOptRecord;
import org.apache.poi.ddf.EscherProperties;
-import org.apache.poi.ddf.EscherRecord;
import org.apache.poi.ddf.EscherSimpleProperty;
-import org.apache.poi.ddf.EscherTextboxRecord;
import org.apache.poi.hslf.record.RecordTypes;
import org.apache.poi.sl.usermodel.ShapeContainer;
import org.apache.poi.sl.usermodel.TableShape;
public final class HSLFTable extends HSLFGroupShape
implements HSLFShapeContainer, TableShape<HSLFShape,HSLFTextParagraph> {
- protected static final int BORDER_TOP = 1;
- protected static final int BORDER_RIGHT = 2;
- protected static final int BORDER_BOTTOM = 3;
- protected static final int BORDER_LEFT = 4;
-
protected static final int BORDERS_ALL = 5;
protected static final int BORDERS_OUTSIDE = 6;
protected static final int BORDERS_INSIDE = 7;
* @param numRows the number of rows
* @param numCols the number of columns
*/
- public HSLFTable(int numRows, int numCols) {
+ protected HSLFTable(int numRows, int numCols) {
this(numRows, numCols, null);
}
-
+
/**
* Create a new Table of the given number of rows and columns
*
* @param numCols the number of columns
* @param parent the parent shape, or null if table is added to sheet
*/
- public HSLFTable(int numRows, int numCols, ShapeContainer<HSLFShape,HSLFTextParagraph> parent) {
+ protected HSLFTable(int numRows, int numCols, ShapeContainer<HSLFShape,HSLFTextParagraph> parent) {
super(parent);
if(numRows < 1) throw new IllegalArgumentException("The number of rows must be greater than 1");
}
tblWidth = x;
tblHeight = y;
- setAnchor(new Rectangle(0, 0, tblWidth, tblHeight));
+ setExteriorAnchor(new Rectangle(0, 0, tblWidth, tblHeight));
EscherContainerRecord spCont = (EscherContainerRecord) getSpContainer().getChild(0);
AbstractEscherOptRecord opt = new EscherOptRecord();
opt.setRecordId((short)RecordTypes.EscherUserDefined);
- opt.addEscherProperty(new EscherSimpleProperty((short)0x39F, 1));
- EscherArrayProperty p = new EscherArrayProperty((short)(0x4000 | 0x3A0), false, null);
+ opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.GROUPSHAPE__TABLEPROPERTIES, 1));
+ EscherArrayProperty p = new EscherArrayProperty((short)(0x4000 | EscherProperties.GROUPSHAPE__TABLEROWPROPERTIES), false, null);
p.setSizeOfElements(0x0004);
p.setNumberOfElementsInArray(numRows);
p.setNumberOfElementsInMemory(numRows);
}
/**
- * Create a Table object and initilize it from the supplied Record container.
+ * Create a Table 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
*/
- public HSLFTable(EscherContainerRecord escherRecord, ShapeContainer<HSLFShape,HSLFTextParagraph> parent) {
+ protected HSLFTable(EscherContainerRecord escherRecord, ShapeContainer<HSLFShape,HSLFTextParagraph> parent) {
super(escherRecord, parent);
}
return cells[row][col];
}
+ @Override
public int getNumberOfColumns() {
return cells[0].length;
}
+
+ @Override
public int getNumberOfRows() {
return cells.length;
}
protected void afterInsert(HSLFSheet sh){
super.afterInsert(sh);
- EscherContainerRecord spCont = (EscherContainerRecord) getSpContainer().getChild(0);
- List<EscherRecord> lst = spCont.getChildRecords();
- AbstractEscherOptRecord opt = (AbstractEscherOptRecord)lst.get(lst.size()-2);
- EscherArrayProperty p = opt.lookup(0x3A0);
- for (int i = 0; i < cells.length; i++) {
- HSLFTableCell cell = cells[i][0];
- int rowHeight = Units.pointsToMaster(cell.getAnchor().height);
- byte[] val = new byte[4];
- LittleEndian.putInt(val, 0, rowHeight);
- p.setElement(i, val);
- for (int j = 0; j < cells[i].length; j++) {
- HSLFTableCell c = cells[i][j];
+ Set<HSLFLine> lineSet = new HashSet<HSLFLine>();
+ for (HSLFTableCell row[] : cells) {
+ for (HSLFTableCell c : row) {
addShape(c);
+ for (HSLFLine bt : new HSLFLine[]{ c.borderTop, c.borderRight, c.borderBottom, c.borderLeft }) {
+ if (bt != null) {
+ lineSet.add(bt);
+ }
+ }
+ }
+ }
+
+ for (HSLFLine l : lineSet) {
+ addShape(l);
+ }
- HSLFLine bt = c.getBorderTop();
- if(bt != null) addShape(bt);
+ updateRowHeightsProperty();
+ }
+
+ private static class TableCellComparator implements Comparator<HSLFShape> {
+ public int compare( HSLFShape o1, HSLFShape o2 ) {
+ Rectangle anchor1 = o1.getAnchor();
+ Rectangle anchor2 = o2.getAnchor();
+ int delta = anchor1.y - anchor2.y;
+ if (delta == 0) delta = anchor1.x - anchor2.x;
+ // descending size
+ if (delta == 0) delta = (anchor2.width*anchor2.height)-(anchor1.width*anchor1.height);
+ return delta;
+ }
+ }
- HSLFLine br = c.getBorderRight();
- if(br != null) addShape(br);
+ private void cellListToArray() {
+ List<HSLFTableCell> htc = new ArrayList<HSLFTableCell>();
+ for (HSLFShape h : getShapes()) {
+ if (h instanceof HSLFTableCell) {
+ htc.add((HSLFTableCell)h);
+ }
+ }
+
+ if (htc.isEmpty()) {
+ throw new IllegalStateException("HSLFTable without HSLFTableCells");
+ }
- HSLFLine bb = c.getBorderBottom();
- if(bb != null) addShape(bb);
+ Collections.sort(htc, new TableCellComparator());
- HSLFLine bl = c.getBorderLeft();
- if(bl != null) addShape(bl);
+ List<HSLFTableCell[]> lst = new ArrayList<HSLFTableCell[]>();
+ List<HSLFTableCell> row = new ArrayList<HSLFTableCell>();
+ int y0 = htc.get(0).getAnchor().y;
+ for (HSLFTableCell sh : htc) {
+ Rectangle anchor = sh.getAnchor();
+ boolean isNextRow = (anchor.y > y0);
+ if (isNextRow) {
+ y0 = anchor.y;
+ lst.add(row.toArray(new HSLFTableCell[row.size()]));
+ row.clear();
}
+ row.add(sh);
}
+ lst.add(row.toArray(new HSLFTableCell[row.size()]));
+ cells = lst.toArray(new HSLFTableCell[lst.size()][]);
}
- protected void initTable(){
- List<HSLFShape> shapeList = getShapes();
-
- Iterator<HSLFShape> shapeIter = shapeList.iterator();
- while (shapeIter.hasNext()) {
- HSLFShape shape = shapeIter.next();
- if (shape instanceof HSLFAutoShape) {
- HSLFAutoShape autoShape = (HSLFAutoShape)shape;
- EscherTextboxRecord etr = autoShape.getEscherChild(EscherTextboxRecord.RECORD_ID);
- if (etr != null) continue;
- }
- shapeIter.remove();
- }
-
- Collections.sort(shapeList, new Comparator<HSLFShape>(){
- public int compare( HSLFShape o1, HSLFShape o2 ) {
- Rectangle anchor1 = o1.getAnchor();
- Rectangle anchor2 = o2.getAnchor();
- int delta = anchor1.y - anchor2.y;
- if (delta == 0) delta = anchor1.x - anchor2.x;
- // descending size
- if (delta == 0) delta = (anchor2.width*anchor2.height)-(anchor1.width*anchor1.height);
- return delta;
- }
- });
-
- int y0 = (shapeList.isEmpty()) ? -1 : shapeList.get(0).getAnchor().y - 1;
- int maxrowlen = 0;
- List<List<HSLFShape>> lst = new ArrayList<List<HSLFShape>>();
- List<HSLFShape> row = null;
- for (HSLFShape sh : shapeList) {
- if(sh instanceof HSLFTextShape){
- Rectangle anchor = sh.getAnchor();
- if(anchor.y != y0){
- y0 = anchor.y;
- row = new ArrayList<HSLFShape>();
- lst.add(row);
- }
- row.add(sh);
- maxrowlen = Math.max(maxrowlen, row.size());
+ static class LineRect {
+ final HSLFLine l;
+ final double lx1, lx2, ly1, ly2;
+ LineRect(HSLFLine l) {
+ this.l = l;
+ Rectangle r = l.getAnchor();
+ lx1 = r.getMinX();
+ lx2 = r.getMaxX();
+ ly1 = r.getMinY();
+ ly2 = r.getMaxY();
+ }
+ int leftFit(double x1, double x2, double y1, double y2) {
+ return (int)(Math.abs(x1-lx1)+Math.abs(y1-ly1)+Math.abs(x1-lx2)+Math.abs(y2-ly2));
+ }
+ int topFit(double x1, double x2, double y1, double y2) {
+ return (int)(Math.abs(x1-lx1)+Math.abs(y1-ly1)+Math.abs(x2-lx2)+Math.abs(y1-ly2));
+ }
+ int rightFit(double x1, double x2, double y1, double y2) {
+ return (int)(Math.abs(x2-lx1)+Math.abs(y1-ly1)+Math.abs(x2-lx2)+Math.abs(y2-ly2));
+ }
+ int bottomFit(double x1, double x2, double y1, double y2) {
+ return (int)(Math.abs(x1-lx1)+Math.abs(y2-ly1)+Math.abs(x2-lx2)+Math.abs(y2-ly2));
+ }
+ }
+
+ private void fitLinesToCells() {
+ List<LineRect> lines = new ArrayList<LineRect>();
+ for (HSLFShape h : getShapes()) {
+ if (h instanceof HSLFLine) {
+ lines.add(new LineRect((HSLFLine)h));
}
}
- cells = new HSLFTableCell[lst.size()][maxrowlen];
- for (int i = 0; i < lst.size(); i++) {
- row = lst.get(i);
- for (int j = 0; j < row.size(); j++) {
- HSLFTextShape tx = (HSLFTextShape)row.get(j);
- cells[i][j] = new HSLFTableCell(tx.getSpContainer(), getParent());
- cells[i][j].setSheet(tx.getSheet());
+
+ final int threshold = 5;
+
+ // TODO: this only works for non-rotated tables
+ for (HSLFTableCell[] tca : cells) {
+ for (HSLFTableCell tc : tca) {
+ final Rectangle cellAnchor = tc.getAnchor();
+
+ /**
+ * x1/y1 --------+
+ * | |
+ * +---------x2/y2
+ */
+ final double x1 = cellAnchor.getMinX();
+ final double x2 = cellAnchor.getMaxX();
+ final double y1 = cellAnchor.getMinY();
+ final double y2 = cellAnchor.getMaxY();
+
+ LineRect lline = null, tline = null, rline = null, bline = null;
+ int lfit = Integer.MAX_VALUE, tfit = Integer.MAX_VALUE, rfit = Integer.MAX_VALUE, bfit = Integer.MAX_VALUE;
+
+ for (LineRect lr : lines) {
+ // calculate border fit
+ int lfitx = lr.leftFit(x1, x2, y1, y2);
+ if (lfitx < lfit) {
+ lfit = lfitx;
+ lline = lr;
+ }
+
+ int tfitx = lr.topFit(x1, x2, y1, y2);
+ if (tfitx < tfit) {
+ tfit = tfitx;
+ tline = lr;
+ }
+
+ int rfitx = lr.rightFit(x1, x2, y1, y2);
+ if (rfitx < rfit) {
+ rfit = rfitx;
+ rline = lr;
+ }
+
+ int bfitx = lr.bottomFit(x1, x2, y1, y2);
+ if (bfitx < bfit) {
+ bfit = bfitx;
+ bline = lr;
+ }
+ }
+
+ if (lfit < threshold) {
+ tc.borderLeft = lline.l;
+ }
+ if (tfit < threshold) {
+ tc.borderTop = tline.l;
+ }
+ if (rfit < threshold) {
+ tc.borderRight = rline.l;
+ }
+ if (bfit < threshold) {
+ tc.borderBottom = bline.l;
+ }
}
}
}
+ protected void initTable(){
+ cellListToArray();
+ fitLinesToCells();
+ }
+
/**
* Assign the <code>SlideShow</code> this shape belongs to
*
*/
public void setSheet(HSLFSheet sheet){
super.setSheet(sheet);
- if(cells == null) initTable();
+ if (cells == null) {
+ initTable();
+ } else {
+ for (HSLFTableCell cols[] : cells) {
+ for (HSLFTableCell col : cols) {
+ col.setSheet(sheet);
+ }
+ }
+ }
}
- /**
- * Sets the row height.
- *
- * @param row the row index (0-based)
- * @param height the height to set (in pixels)
- */
- public void setRowHeight(int row, int height){
+ @Override
+ public void setRowHeight(int row, double height) {
+ int pxHeight = Units.pointsToPixel(height);
int currentHeight = cells[row][0].getAnchor().height;
- int dy = height - currentHeight;
+ int dy = pxHeight - currentHeight;
for (int i = row; i < cells.length; i++) {
for (int j = 0; j < cells[i].length; j++) {
Rectangle anchor = cells[i][j].getAnchor();
- if(i == row) anchor.height = height;
- else anchor.y += dy;
+ if(i == row) {
+ anchor.height = pxHeight;
+ } else {
+ anchor.y += dy;
+ }
cells[i][j].setAnchor(anchor);
}
}
Rectangle tblanchor = getAnchor();
tblanchor.height += dy;
- setAnchor(tblanchor);
+ setExteriorAnchor(tblanchor);
}
- /**
- * Sets the column width.
- *
- * @param col the column index (0-based)
- * @param width the width to set (in pixels)
- */
- public void setColumnWidth(int col, int width){
- int currentWidth = cells[0][col].getAnchor().width;
- int dx = width - currentWidth;
- for (int i = 0; i < cells.length; i++) {
- Rectangle anchor = cells[i][col].getAnchor();
- anchor.width = width;
- cells[i][col].setAnchor(anchor);
-
- if(col < cells[i].length - 1) for (int j = col+1; j < cells[i].length; j++) {
- anchor = cells[i][j].getAnchor();
- anchor.x += dx;
- cells[i][j].setAnchor(anchor);
+ @Override
+ public void setColumnWidth(int col, final double width){
+ if (col < 0 || col >= cells[0].length) {
+ throw new IllegalArgumentException("Column index '"+col+"' is not within range [0-"+(cells[0].length-1)+"]");
+ }
+ double currentWidth = cells[0][col].getAnchor().getWidth();
+ double dx = width - currentWidth;
+ for (HSLFTableCell cols[] : cells) {
+ Rectangle anchor = cols[col].getAnchor();
+ anchor.width = (int)Math.rint(width);
+ cols[col].setAnchor(anchor);
+
+ if (col < cols.length - 1) {
+ for (int j = col+1; j < cols.length; j++) {
+ anchor = cols[j].getAnchor();
+ anchor.x += dx;
+ cols[j].setAnchor(anchor);
+ }
}
}
Rectangle tblanchor = getAnchor();
tblanchor.width += dx;
- setAnchor(tblanchor);
+ setExteriorAnchor(tblanchor);
}
- /**
- * Format the table and apply the specified Line to all cell boundaries,
- * both outside and inside
- *
- * @param line the border line
- */
- public void setAllBorders(HSLFLine line){
- for (int i = 0; i < cells.length; i++) {
- for (int j = 0; j < cells[i].length; j++) {
- HSLFTableCell cell = cells[i][j];
- cell.setBorderTop(cloneBorder(line));
- cell.setBorderLeft(cloneBorder(line));
- if(j == cells[i].length - 1) cell.setBorderRight(cloneBorder(line));
- if(i == cells.length - 1) cell.setBorderBottom(cloneBorder(line));
- }
- }
- }
-
- /**
- * Format the outside border using the specified Line object
- *
- * @param line the border line
- */
- public void setOutsideBorders(HSLFLine line){
- for (int i = 0; i < cells.length; i++) {
- for (int j = 0; j < cells[i].length; j++) {
- HSLFTableCell cell = cells[i][j];
-
- if(j == 0) cell.setBorderLeft(cloneBorder(line));
- if(j == cells[i].length - 1) cell.setBorderRight(cloneBorder(line));
- else {
- cell.setBorderLeft(null);
- cell.setBorderLeft(null);
- }
-
- if(i == 0) cell.setBorderTop(cloneBorder(line));
- else if(i == cells.length - 1) cell.setBorderBottom(cloneBorder(line));
- else {
- cell.setBorderTop(null);
- cell.setBorderBottom(null);
+ protected HSLFTableCell getRelativeCell(HSLFTableCell origin, int row, int col) {
+ int thisRow = 0, thisCol = 0;
+ boolean found = false;
+ outer: for (HSLFTableCell[] tca : cells) {
+ thisCol = 0;
+ for (HSLFTableCell tc : tca) {
+ if (tc == origin) {
+ found = true;
+ break outer;
}
+ thisCol++;
}
+ thisRow++;
}
- }
-
- /**
- * Format the inside border using the specified Line object
- *
- * @param line the border line
- */
- public void setInsideBorders(HSLFLine line){
- for (int i = 0; i < cells.length; i++) {
- for (int j = 0; j < cells[i].length; j++) {
- HSLFTableCell cell = cells[i][j];
- if(j != cells[i].length - 1)
- cell.setBorderRight(cloneBorder(line));
- else {
- cell.setBorderLeft(null);
- cell.setBorderLeft(null);
- }
- if(i != cells.length - 1) cell.setBorderBottom(cloneBorder(line));
- else {
- cell.setBorderTop(null);
- cell.setBorderBottom(null);
- }
- }
- }
+ int otherRow = thisRow + row;
+ int otherCol = thisCol + col;
+ return (found
+ && 0 <= otherRow && otherRow < cells.length
+ && 0 <= otherCol && otherCol < cells[otherRow].length)
+ ? cells[otherRow][otherCol] : null;
}
- private HSLFLine cloneBorder(HSLFLine line){
- HSLFLine border = createBorder();
- border.setLineWidth(line.getLineWidth());
- border.setLineDashing(line.getLineDashing());
- border.setLineColor(line.getLineColor());
- border.setLineCompound(line.getLineCompound());
- return border;
+ @Override
+ protected void moveAndScale(Rectangle anchorDest){
+ super.moveAndScale(anchorDest);
+ updateRowHeightsProperty();
}
- /**
- * Create a border to format this table
- *
- * @return the created border
- */
- public HSLFLine createBorder(){
- HSLFLine line = new HSLFLine(this);
-
+ private void updateRowHeightsProperty() {
AbstractEscherOptRecord opt = getEscherOptRecord();
- setEscherProperty(opt, EscherProperties.GEOMETRY__SHAPEPATH, -1);
- setEscherProperty(opt, EscherProperties.GEOMETRY__FILLOK, -1);
- setEscherProperty(opt, EscherProperties.SHADOWSTYLE__SHADOWOBSURED, 0x20000);
- setEscherProperty(opt, EscherProperties.THREED__LIGHTFACE, 0x80000);
-
- return line;
+ EscherArrayProperty p = opt.lookup(EscherProperties.GROUPSHAPE__TABLEROWPROPERTIES);
+ byte[] val = new byte[4];
+ for (int rowIdx = 0; rowIdx < cells.length; rowIdx++) {
+ int rowHeight = Units.pointsToMaster(cells[rowIdx][0].getAnchor().height);
+ LittleEndian.putInt(val, 0, rowHeight);
+ p.setElement(rowIdx, val);
+ }
}
}
package org.apache.poi.hslf.usermodel;
+import java.awt.Color;
import java.awt.Rectangle;
import org.apache.poi.ddf.AbstractEscherOptRecord;
import org.apache.poi.ddf.EscherContainerRecord;
import org.apache.poi.ddf.EscherProperties;
-import org.apache.poi.sl.usermodel.ShapeContainer;
+import org.apache.poi.sl.draw.DrawPaint;
+import org.apache.poi.sl.usermodel.PaintStyle;
import org.apache.poi.sl.usermodel.ShapeType;
+import org.apache.poi.sl.usermodel.StrokeStyle;
+import org.apache.poi.sl.usermodel.StrokeStyle.LineCompound;
+import org.apache.poi.sl.usermodel.StrokeStyle.LineDash;
import org.apache.poi.sl.usermodel.TableCell;
/**
protected static final int DEFAULT_WIDTH = 100;
protected static final int DEFAULT_HEIGHT = 40;
- private HSLFLine borderLeft;
- private HSLFLine borderRight;
- private HSLFLine borderTop;
- private HSLFLine borderBottom;
+ /* package */ HSLFLine borderLeft;
+ /* package */ HSLFLine borderRight;
+ /* package */ HSLFLine borderTop;
+ /* package */ HSLFLine borderBottom;
/**
* Create a TableCell object and initialize it from the supplied Record container.
* @param escherRecord EscherSpContainer which holds information about this shape
* @param parent the parent of the shape
*/
- protected HSLFTableCell(EscherContainerRecord escherRecord, ShapeContainer<HSLFShape,HSLFTextParagraph> parent){
+ protected HSLFTableCell(EscherContainerRecord escherRecord, HSLFTable parent){
super(escherRecord, parent);
}
* @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 HSLFTableCell(ShapeContainer<HSLFShape,HSLFTextParagraph> parent){
+ public HSLFTableCell(HSLFTable parent){
super(parent);
setShapeType(ShapeType.RECT);
return _escherContainer;
}
- protected void anchorBorder(int type, HSLFLine line){
+ private void anchorBorder(BorderEdge edge, final HSLFLine line) {
+ if (line == null) {
+ return;
+ }
Rectangle cellAnchor = getAnchor();
Rectangle lineAnchor = new Rectangle();
- switch(type){
- case HSLFTable.BORDER_TOP:
+ switch(edge){
+ case top:
lineAnchor.x = cellAnchor.x;
lineAnchor.y = cellAnchor.y;
lineAnchor.width = cellAnchor.width;
lineAnchor.height = 0;
break;
- case HSLFTable.BORDER_RIGHT:
+ case right:
lineAnchor.x = cellAnchor.x + cellAnchor.width;
lineAnchor.y = cellAnchor.y;
lineAnchor.width = 0;
lineAnchor.height = cellAnchor.height;
break;
- case HSLFTable.BORDER_BOTTOM:
+ case bottom:
lineAnchor.x = cellAnchor.x;
lineAnchor.y = cellAnchor.y + cellAnchor.height;
lineAnchor.width = cellAnchor.width;
lineAnchor.height = 0;
break;
- case HSLFTable.BORDER_LEFT:
+ case left:
lineAnchor.x = cellAnchor.x;
lineAnchor.y = cellAnchor.y;
lineAnchor.width = 0;
lineAnchor.height = cellAnchor.height;
break;
default:
- throw new IllegalArgumentException("Unknown border type: " + type);
+ throw new IllegalArgumentException();
}
line.setAnchor(lineAnchor);
}
- public HSLFLine getBorderLeft() {
- return borderLeft;
+ public void setAnchor(Rectangle anchor){
+ super.setAnchor(anchor);
+
+ anchorBorder(BorderEdge.top, borderTop);
+ anchorBorder(BorderEdge.right, borderRight);
+ anchorBorder(BorderEdge.bottom, borderBottom);
+ anchorBorder(BorderEdge.left, borderLeft);
}
- public void setBorderLeft(HSLFLine line) {
- if(line != null) anchorBorder(HSLFTable.BORDER_LEFT, line);
- this.borderLeft = line;
+ @Override
+ public StrokeStyle getBorderStyle(final BorderEdge edge) {
+ final Double width = getBorderWidth(edge);
+ return (width == null) ? null : new StrokeStyle() {
+ public PaintStyle getPaint() {
+ return DrawPaint.createSolidPaint(getBorderColor(edge));
+ }
+
+ public LineCap getLineCap() {
+ return null;
+ }
+
+ public LineDash getLineDash() {
+ return getBorderDash(edge);
+ }
+
+ public LineCompound getLineCompound() {
+ return getBorderCompound(edge);
+ }
+
+ public double getLineWidth() {
+ return width;
+ }
+ };
}
- public HSLFLine getBorderRight() {
- return borderRight;
+ @Override
+ public void setBorderStyle(BorderEdge edge, StrokeStyle style) {
+ if (style == null) {
+ throw new IllegalArgumentException("StrokeStyle needs to be specified.");
+ }
+
+ // setting the line cap is not implemented, as the border lines aren't connected
+
+ LineCompound compound = style.getLineCompound();
+ if (compound != null) {
+ setBorderCompound(edge, compound);
+ }
+
+ LineDash dash = style.getLineDash();
+ if (dash != null) {
+ setBorderDash(edge, dash);
+ }
+
+ double width = style.getLineWidth();
+ setBorderWidth(edge, width);
}
- public void setBorderRight(HSLFLine line) {
- if(line != null) anchorBorder(HSLFTable.BORDER_RIGHT, line);
- this.borderRight = line;
+
+ public Double getBorderWidth(BorderEdge edge) {
+ HSLFLine l;
+ switch (edge) {
+ case bottom: l = borderBottom; break;
+ case top: l = borderTop; break;
+ case right: l = borderRight; break;
+ case left: l = borderLeft; break;
+ default: throw new IllegalArgumentException();
+ }
+ return (l == null) ? null : l.getLineWidth();
+ }
+
+ @Override
+ public void setBorderWidth(BorderEdge edge, double width) {
+ HSLFLine l = addLine(edge);
+ l.setLineWidth(width);
}
- public HSLFLine getBorderTop() {
- return borderTop;
+ public Color getBorderColor(BorderEdge edge) {
+ HSLFLine l;
+ switch (edge) {
+ case bottom: l = borderBottom; break;
+ case top: l = borderTop; break;
+ case right: l = borderRight; break;
+ case left: l = borderLeft; break;
+ default: throw new IllegalArgumentException();
+ }
+ return (l == null) ? null : l.getLineColor();
}
- public void setBorderTop(HSLFLine line) {
- if(line != null) anchorBorder(HSLFTable.BORDER_TOP, line);
- this.borderTop = line;
+ @Override
+ public void setBorderColor(BorderEdge edge, Color color) {
+ if (edge == null || color == null) {
+ throw new IllegalArgumentException("BorderEdge and/or Color need to be specified.");
+ }
+
+ HSLFLine l = addLine(edge);
+ l.setLineColor(color);
}
- public HSLFLine getBorderBottom() {
- return borderBottom;
+ public LineDash getBorderDash(BorderEdge edge) {
+ HSLFLine l;
+ switch (edge) {
+ case bottom: l = borderBottom; break;
+ case top: l = borderTop; break;
+ case right: l = borderRight; break;
+ case left: l = borderLeft; break;
+ default: throw new IllegalArgumentException();
+ }
+ return (l == null) ? null : l.getLineDash();
+ }
+
+ @Override
+ public void setBorderDash(BorderEdge edge, LineDash dash) {
+ if (edge == null || dash == null) {
+ throw new IllegalArgumentException("BorderEdge and/or LineDash need to be specified.");
+ }
+
+ HSLFLine l = addLine(edge);
+ l.setLineDash(dash);
}
- public void setBorderBottom(HSLFLine line) {
- if(line != null) anchorBorder(HSLFTable.BORDER_BOTTOM, line);
- this.borderBottom = line;
+ public LineCompound getBorderCompound(BorderEdge edge) {
+ HSLFLine l;
+ switch (edge) {
+ case bottom: l = borderBottom; break;
+ case top: l = borderTop; break;
+ case right: l = borderRight; break;
+ case left: l = borderLeft; break;
+ default: throw new IllegalArgumentException();
+ }
+ return (l == null) ? null : l.getLineCompound();
+ }
+
+ @Override
+ public void setBorderCompound(BorderEdge edge, LineCompound compound) {
+ if (edge == null || compound == null) {
+ throw new IllegalArgumentException("BorderEdge and/or LineCompound need to be specified.");
+ }
+
+ HSLFLine l = addLine(edge);
+ l.setLineCompound(compound);
}
- public void setAnchor(Rectangle anchor){
- super.setAnchor(anchor);
- if(borderTop != null) anchorBorder(HSLFTable.BORDER_TOP, borderTop);
- if(borderRight != null) anchorBorder(HSLFTable.BORDER_RIGHT, borderRight);
- if(borderBottom != null) anchorBorder(HSLFTable.BORDER_BOTTOM, borderBottom);
- if(borderLeft != null) anchorBorder(HSLFTable.BORDER_LEFT, borderLeft);
+ protected HSLFLine addLine(BorderEdge edge) {
+ switch (edge) {
+ case bottom: {
+ if (borderBottom == null) {
+ borderBottom = createBorder(edge);
+ HSLFTableCell c = getSiblingCell(1,0);
+ if (c != null) {
+ assert(c.borderTop == null);
+ c.borderTop = borderBottom;
+ }
+ }
+ return borderBottom;
+ }
+ case top: {
+ if (borderTop == null) {
+ borderTop = createBorder(edge);
+ HSLFTableCell c = getSiblingCell(-1,0);
+ if (c != null) {
+ assert(c.borderBottom == null);
+ c.borderBottom = borderTop;
+ }
+ }
+ return borderTop;
+ }
+ case right: {
+ if (borderRight == null) {
+ borderRight = createBorder(edge);
+ HSLFTableCell c = getSiblingCell(0,1);
+ if (c != null) {
+ assert(c.borderLeft == null);
+ c.borderLeft = borderRight;
+ }
+ }
+ return borderRight;
+ }
+ case left: {
+ if (borderLeft == null) {
+ borderLeft = createBorder(edge);
+ HSLFTableCell c = getSiblingCell(0,-1);
+ if (c != null) {
+ assert(c.borderRight == null);
+ c.borderRight = borderLeft;
+ }
+ }
+ return borderLeft;
+ }
+ default:
+ throw new IllegalArgumentException();
+ }
+ }
+
+ @Override
+ public void removeBorder(BorderEdge edge) {
+ switch (edge) {
+ case bottom: {
+ if (borderBottom == null) break;
+ getParent().removeShape(borderBottom);
+ borderBottom = null;
+ HSLFTableCell c = getSiblingCell(1,0);
+ if (c != null) {
+ c.borderTop = null;
+ }
+ break;
+ }
+ case top: {
+ if (borderTop == null) break;
+ getParent().removeShape(borderTop);
+ borderTop = null;
+ HSLFTableCell c = getSiblingCell(-1,0);
+ if (c != null) {
+ c.borderBottom = null;
+ }
+ break;
+ }
+ case right: {
+ if (borderRight == null) break;
+ getParent().removeShape(borderRight);
+ borderRight = null;
+ HSLFTableCell c = getSiblingCell(0,1);
+ if (c != null) {
+ c.borderLeft = null;
+ }
+ break;
+ }
+ case left: {
+ if (borderLeft == null) break;
+ getParent().removeShape(borderLeft);
+ borderLeft = null;
+ HSLFTableCell c = getSiblingCell(0,-1);
+ if (c != null) {
+ c.borderRight = null;
+ }
+ break;
+ }
+ default:
+ throw new IllegalArgumentException();
+ }
+ }
+
+ protected HSLFTableCell getSiblingCell(int row, int col) {
+ return getParent().getRelativeCell(this, row, col);
+ }
+
+ /**
+ * Create a border to format this table
+ *
+ * @return the created border
+ */
+ private HSLFLine createBorder(BorderEdge edge) {
+ HSLFTable table = getParent();
+ HSLFLine line = new HSLFLine(table);
+ table.addShape(line);
+
+ AbstractEscherOptRecord opt = getEscherOptRecord();
+ setEscherProperty(opt, EscherProperties.GEOMETRY__SHAPEPATH, -1);
+ setEscherProperty(opt, EscherProperties.GEOMETRY__FILLOK, -1);
+ setEscherProperty(opt, EscherProperties.SHADOWSTYLE__SHADOWOBSURED, 0x20000);
+ setEscherProperty(opt, EscherProperties.THREED__LIGHTFACE, 0x80000);
+
+ anchorBorder(edge, line);
+
+ return line;
+ }
+
+ protected void applyLineProperties(BorderEdge edge, HSLFLine other) {
+ HSLFLine line = addLine(edge);
+ line.setLineWidth(other.getLineWidth());
+ line.setLineColor(other.getLineColor());
+ // line.setLineCompound(other.getLineCompound());
+ // line.setLineDashing(other.getLineDashing());
+ }
+
+ @Override
+ public HSLFTable getParent() {
+ return (HSLFTable)super.getParent();
}
}
* This class represents a run of text in a powerpoint document. That\r
* run could be text on a sheet, or text in a note.\r
* It is only a very basic class for now\r
- * \r
+ *\r
* @author Nick Burch\r
*/\r
\r
private int shapeId;\r
\r
private StyleTextProp9Atom styleTextProp9Atom;\r
- \r
+\r
private boolean _dirty = false;\r
\r
/**\r
* Constructs a Text Run from a Unicode text block.\r
* Either a {@link TextCharsAtom} or a {@link TextBytesAtom} needs to be provided.\r
- * \r
+ *\r
* @param tha the TextHeaderAtom that defines what's what\r
* @param tba the TextBytesAtom containing the text or null if {@link TextCharsAtom} is provided\r
* @param tca the TextCharsAtom containing the text or null if {@link TextBytesAtom} is provided\r
*/\r
- /* package */ HSLFTextParagraph(\r
+ /* package */ HSLFTextParagraph(\r
TextHeaderAtom tha,\r
TextBytesAtom tba,\r
TextCharsAtom tca\r
_runs.add(run);\r
}\r
\r
- /**\r
- * Fetch the rich text runs (runs of text with the same styling) that\r
- * are contained within this block of text\r
- */\r
+ @Override\r
public List<HSLFTextRun> getTextRuns() {\r
return _runs;\r
}\r
\r
/**\r
* Sets the index of the paragraph in the SLWT container\r
- * \r
+ *\r
* @param index\r
*/\r
protected void setIndex(int index) {\r
/**\r
* Returns records that make up the list of text paragraphs\r
* (there can be misc InteractiveInfo, TxInteractiveInfo and other records)\r
- * \r
+ *\r
* @return text run records\r
*/\r
public Record[] getRecords() {\r
}\r
\r
/** Numbered List info */\r
- public void setStyleTextProp9Atom(final StyleTextProp9Atom styleTextProp9Atom) {\r
+ public void setStyleTextProp9Atom(final StyleTextProp9Atom styleTextProp9Atom) {\r
this.styleTextProp9Atom = styleTextProp9Atom;\r
}\r
\r
public StyleTextProp9Atom getStyleTextProp9Atom() {\r
return this.styleTextProp9Atom;\r
}\r
- \r
+\r
@Override\r
public Iterator<HSLFTextRun> iterator() {\r
return _runs.iterator();\r
if (!_runs.isEmpty()) {\r
d = _runs.get(0).getFontSize();\r
}\r
- \r
+\r
return (d != null) ? d : 12d;\r
}\r
\r
/**\r
* Sets the type of horizontal alignment for the paragraph.\r
- * \r
+ *\r
* @param align - the type of alignment\r
*/\r
public void setAlignment(org.apache.poi.sl.usermodel.TextParagraph.TextAlign align) {\r
public FontAlign getFontAlign() {\r
TextProp tp = getPropVal(_paragraphStyle, FontAlignmentProp.NAME, this);\r
if (tp == null) return null;\r
- \r
+\r
switch (tp.getValue()) {\r
case FontAlignmentProp.BASELINE: return FontAlign.BASELINE;\r
case FontAlignmentProp.TOP: return FontAlign.TOP;\r
assert(startAt != null);\r
return startAt.intValue();\r
}\r
- \r
- \r
+\r
+\r
@Override\r
public BulletStyle getBulletStyle() {\r
if (!isBullet() && getAutoNumberingScheme() == null) return null;\r
public void setBulletFontColor(Color color) {\r
setBulletFontColor(DrawPaint.createSolidPaint(color));\r
}\r
- \r
+\r
@Override\r
public void setBulletFontColor(PaintStyle color) {\r
if (!(color instanceof SolidPaint)) {\r
Color col = DrawPaint.applyColorTransform(sp.getSolidColor());\r
HSLFTextParagraph.this.setBulletColor(col);\r
}\r
- \r
+\r
@Override\r
public PaintStyle getBulletFontColor() {\r
Color col = HSLFTextParagraph.this.getBulletColor();\r
// TODO: implement\r
return null;\r
}\r
- \r
+\r
private Double getPctOrPoints(String propName) {\r
TextProp tp = getPropVal(_paragraphStyle, propName, this);\r
if (tp == null) return null;\r
}\r
setParagraphTextPropVal(propName, ival);\r
}\r
- \r
+\r
private boolean getFlag(int index) {\r
BitMaskTextProp tp = (BitMaskTextProp)getPropVal(_paragraphStyle, ParagraphFlagsTextProp.NAME, this);\r
return (tp == null) ? false : tp.getSubValue(index);\r
/**\r
* Returns the named TextProp, either by fetching it (if it exists) or\r
* adding it (if it didn't)\r
- * \r
+ *\r
* @param props the TextPropCollection to fetch from / add into\r
* @param name the name of the TextProp to fetch/add\r
* @param val the value, null if unset\r
props.removeByName(name);\r
return;\r
}\r
- \r
+\r
// Fetch / Add the TextProp\r
TextProp tp = props.addWithName(name);\r
tp.setValue(val);\r
}\r
- \r
+\r
/**\r
* Check and add linebreaks to text runs leading other paragraphs\r
- * \r
+ *\r
* @param paragraphs\r
*/\r
protected static void fixLineEndings(List<HSLFTextParagraph> paragraphs) {\r
\r
/**\r
* Search for a StyleTextPropAtom is for this text header (list of paragraphs)\r
- * \r
+ *\r
* @param header the header\r
* @param textLen the length of the rawtext, or -1 if the length is not known\r
*/\r
throw new RuntimeException("failed dummy write", e);\r
}\r
}\r
- \r
+\r
for (HSLFTextParagraph p : paragraphs) {\r
p._dirty = false;\r
}\r
/**\r
* Adds the supplied text onto the end of the TextParagraphs,\r
* creating a new RichTextRun for it to sit in.\r
- * \r
+ *\r
* @param text the text string used by this object.\r
*/\r
protected static HSLFTextRun appendText(List<HSLFTextParagraph> paragraphs, String text, boolean newParagraph) {\r
HSLFTextParagraph htp = paragraphs.get(paragraphs.size() - 1);\r
HSLFTextRun htr = htp.getTextRuns().get(htp.getTextRuns().size() - 1);\r
\r
- boolean isFirst = !newParagraph;\r
+ boolean addParagraph = newParagraph;\r
for (String rawText : text.split("(?<=\r)")) {\r
- if (!isFirst) {\r
+ // special case, if last text paragraph or run is empty, we will reuse it\r
+ boolean lastRunEmpty = (htr.getLength() == 0);\r
+ boolean lastParaEmpty = lastRunEmpty && (htp.getTextRuns().size() == 1);\r
+\r
+ if (addParagraph && !lastParaEmpty) {\r
TextPropCollection tpc = htp.getParagraphStyle();\r
HSLFTextParagraph prevHtp = htp;\r
htp = new HSLFTextParagraph(htp._headerAtom, htp._byteAtom, htp._charAtom);\r
htp.supplySheet(prevHtp.getSheet());\r
paragraphs.add(htp);\r
}\r
- isFirst = false;\r
+ addParagraph = true;\r
\r
- TextPropCollection tpc = htr.getCharacterStyle();\r
- // special case, last text run is empty, we will reuse it\r
- if (htr.getLength() > 0) {\r
+ if (!lastRunEmpty) {\r
+ TextPropCollection tpc = htr.getCharacterStyle();\r
htr = new HSLFTextRun(htp);\r
htr.getCharacterStyle().copy(tpc);\r
htp.addTextRun(htr);\r
/**\r
* Sets (overwrites) the current text.\r
* Uses the properties of the first paragraph / textrun\r
- * \r
+ *\r
* @param text the text string used by this object.\r
*/\r
public static HSLFTextRun setText(List<HSLFTextParagraph> paragraphs, String text) {\r
/**\r
* Converts raw text from the text paragraphs to a formatted string,\r
* i.e. it converts certain control characters used in the raw txt\r
- * \r
+ *\r
* @param rawText the raw text\r
* @param runType the run type of the shape, paragraph or headerAtom.\r
* use -1 if unknown\r
* Scans through the supplied record array, looking for\r
* a TextHeaderAtom followed by one of a TextBytesAtom or\r
* a TextCharsAtom. Builds up TextRuns from these\r
- * \r
+ *\r
* @param wrapper an EscherTextboxWrapper\r
*/\r
protected static List<HSLFTextParagraph> findTextParagraphs(EscherTextboxWrapper wrapper, HSLFSheet sheet) {\r
* Scans through the supplied record array, looking for\r
* a TextHeaderAtom followed by one of a TextBytesAtom or\r
* a TextCharsAtom. Builds up TextRuns from these\r
- * \r
+ *\r
* @param records the records to build from\r
*/\r
protected static List<List<HSLFTextParagraph>> findTextParagraphs(Record[] records) {\r
EscherTextboxWrapper wrapper = new EscherTextboxWrapper();\r
return createEmptyParagraph(wrapper);\r
}\r
- \r
+\r
protected static List<HSLFTextParagraph> createEmptyParagraph(EscherTextboxWrapper wrapper) {\r
TextHeaderAtom tha = new TextHeaderAtom();\r
tha.setParentRecord(wrapper);\r
public EscherTextboxWrapper getTextboxWrapper() {\r
return (EscherTextboxWrapper) _headerAtom.getParentRecord();\r
}\r
- \r
+\r
protected static Color getColorFromColorIndexStruct(int rgb, HSLFSheet sheet) {\r
int cidx = rgb >>> 24;\r
- Color tmp; \r
+ Color tmp;\r
switch (cidx) {\r
// Background ... Accent 3 color\r
case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:\r
setPropVal(_paragraphStyle, propName, val);\r
setDirty();\r
}\r
- \r
+\r
/**\r
* marks this paragraph dirty, so its records will be renewed on save\r
*/\r
public void setDirty() {\r
_dirty = true;\r
}\r
- \r
+\r
public boolean isDirty() {\r
return _dirty;\r
}\r
-}\r
+}
\ No newline at end of file
// --------------- Friendly getters / setters on rich text properties -------
- /**
- * Is the text bold?
- */
+ @Override
public boolean isBold() {
return isCharFlagsTextPropVal(CharFlagsTextProp.BOLD_IDX);
}
- /**
- * Is the text bold?
- */
+ @Override
public void setBold(boolean bold) {
setCharFlagsTextPropVal(CharFlagsTextProp.BOLD_IDX, bold);
}
- /**
- * Is the text italic?
- */
+ @Override
public boolean isItalic() {
return isCharFlagsTextPropVal(CharFlagsTextProp.ITALIC_IDX);
}
- /**
- * Is the text italic?
- */
+ @Override
public void setItalic(boolean italic) {
setCharFlagsTextPropVal(CharFlagsTextProp.ITALIC_IDX, italic);
}
- /**
- * Is the text underlined?
- */
+ @Override
public boolean isUnderlined() {
return isCharFlagsTextPropVal(CharFlagsTextProp.UNDERLINE_IDX);
}
- /**
- * Is the text underlined?
- */
+ @Override
public void setUnderlined(boolean underlined) {
setCharFlagsTextPropVal(CharFlagsTextProp.UNDERLINE_IDX, underlined);
}
setCharFlagsTextPropVal(CharFlagsTextProp.RELIEF_IDX, flag);
}
- /**
- * Gets the strikethrough flag
- */
+ @Override
public boolean isStrikethrough() {
return isCharFlagsTextPropVal(CharFlagsTextProp.STRIKETHROUGH_IDX);
}
- /**
- * Sets the strikethrough flag
- */
+ @Override
public void setStrikethrough(boolean flag) {
setCharFlagsTextPropVal(CharFlagsTextProp.STRIKETHROUGH_IDX, flag);
}
setCharTextPropVal("font.index", idx);
}
-
- /**
- * Sets the font name to use
- */
+ @Override
public void setFontFamily(String fontFamily) {
HSLFSheet sheet = parentParagraph.getSheet();
HSLFSlideShow slideShow = (sheet == null) ? null : sheet.getSlideShow();
return;
}
// Get the index for this font (adding if needed)
- int fontIdx = slideShow.getFontCollection().addFont(fontFamily);
+ Integer fontIdx = (fontFamily == null) ? null : slideShow.getFontCollection().addFont(fontFamily);
setCharTextPropVal("font.index", fontIdx);
}
- /**
- * Gets the font name
- */
@Override
public String getFontFamily() {
HSLFSheet sheet = parentParagraph.getSheet();
return TextCap.NONE;
}
+ @Override
public boolean isSubscript() {
- return false;
+ return getSuperscript() < 0;
}
+ @Override
public boolean isSuperscript() {
- return false;
+ return getSuperscript() > 0;
}
public byte getPitchAndFamily() {
package org.apache.poi.hslf.usermodel;
-import static org.apache.poi.hslf.record.RecordTypes.*;
+import static org.apache.poi.hslf.record.RecordTypes.OEPlaceholderAtom;
+import static org.apache.poi.hslf.record.RecordTypes.RoundTripHFPlaceholder12;
import java.awt.Rectangle;
import java.awt.font.FontRenderContext;
import java.awt.geom.Rectangle2D;
import java.io.IOException;
-import java.util.*;
-
-import org.apache.poi.ddf.*;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.poi.ddf.AbstractEscherOptRecord;
+import org.apache.poi.ddf.EscherContainerRecord;
+import org.apache.poi.ddf.EscherProperties;
+import org.apache.poi.ddf.EscherSimpleProperty;
+import org.apache.poi.ddf.EscherTextboxRecord;
import org.apache.poi.hslf.exceptions.HSLFException;
-import org.apache.poi.hslf.record.*;
+import org.apache.poi.hslf.record.EscherTextboxWrapper;
+import org.apache.poi.hslf.record.InteractiveInfo;
+import org.apache.poi.hslf.record.InteractiveInfoAtom;
+import org.apache.poi.hslf.record.OEPlaceholderAtom;
+import org.apache.poi.hslf.record.PPDrawing;
+import org.apache.poi.hslf.record.RoundTripHFPlaceholder12;
+import org.apache.poi.hslf.record.TextHeaderAtom;
+import org.apache.poi.hslf.record.TxInteractiveInfoAtom;
import org.apache.poi.sl.draw.DrawFactory;
import org.apache.poi.sl.draw.DrawTextShape;
-import org.apache.poi.sl.usermodel.*;
+import org.apache.poi.sl.usermodel.Insets2D;
+import org.apache.poi.sl.usermodel.ShapeContainer;
+import org.apache.poi.sl.usermodel.TextShape;
+import org.apache.poi.sl.usermodel.VerticalAlignment;
import org.apache.poi.util.POILogger;
import org.apache.poi.util.Units;
/* package */ static final int AnchorBottomCenteredBaseline = 9;
/**
- * How to wrap the text
+ * Specifies that a line of text will continue on subsequent lines instead
+ * of extending into or beyond a margin.
+ * Office Excel 2007, Excel 2010, PowerPoint 97, and PowerPoint 2010 read
+ * and use this value properly but do not write it.
*/
public static final int WrapSquare = 0;
+ /**
+ * Specifies a wrapping rule that is equivalent to that of WrapSquare
+ * Excel 97, Excel 2000, Excel 2002, and Office Excel 2003 use this value.
+ * All other product versions listed at the beginning of this appendix ignore this value.
+ */
public static final int WrapByPoints = 1;
+ /**
+ * Specifies that a line of text will extend into or beyond a margin instead
+ * of continuing on subsequent lines.
+ * Excel 97, Word 97, Excel 2000, Word 2000, Excel 2002,
+ * and Office Excel 2003 do not use this value.
+ */
public static final int WrapNone = 2;
+ /**
+ * Specifies a wrapping rule that is undefined and MUST be ignored.
+ */
public static final int WrapTopBottom = 3;
+ /**
+ * Specifies a wrapping rule that is undefined and MUST be ignored.
+ */
public static final int WrapThrough = 4;
+
/**
* TextRun object which holds actual text and format data
*/
setEscherProperty(EscherProperties.TEXT__ANCHORTEXT, align2);
}
- @Override
- public VerticalAlignment getVerticalAlignment() {
- int va = getAlignment();
- switch (va) {
- case AnchorTop:
- case AnchorTopCentered:
- case AnchorTopBaseline:
- case AnchorTopCenteredBaseline: return VerticalAlignment.TOP;
- case AnchorBottom:
- case AnchorBottomCentered:
- case AnchorBottomBaseline:
- case AnchorBottomCenteredBaseline: return VerticalAlignment.BOTTOM;
- default:
- case AnchorMiddle:
- case AnchorMiddleCentered: return VerticalAlignment.MIDDLE;
- }
- }
-
/**
* @return true, if vertical alignment is relative to baseline
* this is only used for older versions less equals Office 2003
return false;
}
}
+
+ @Override
+ public void setHorizontalCentered(Boolean isCentered) {
+ setAlignment(isCentered, getVerticalAlignment());
+ }
- public void setVerticalAlignment(VerticalAlignment vAlign) {
- setAlignment(isHorizontalCentered(), vAlign);
+ @Override
+ public VerticalAlignment getVerticalAlignment() {
+ int va = getAlignment();
+ switch (va) {
+ case AnchorTop:
+ case AnchorTopCentered:
+ case AnchorTopBaseline:
+ case AnchorTopCenteredBaseline: return VerticalAlignment.TOP;
+ case AnchorBottom:
+ case AnchorBottomCentered:
+ case AnchorBottomBaseline:
+ case AnchorBottomCenteredBaseline: return VerticalAlignment.BOTTOM;
+ default:
+ case AnchorMiddle:
+ case AnchorMiddleCentered: return VerticalAlignment.MIDDLE;
+ }
}
- /**
- * Sets if the paragraphs are horizontal centered
- *
- * @param isCentered true, if the paragraphs are horizontal centered
- * A {@code null} values unsets this property.
- *
- * @see TextShape#isHorizontalCentered()
- */
- public void setHorizontalCentered(Boolean isCentered){
- setAlignment(isCentered, getVerticalAlignment());
+ @Override
+ public void setVerticalAlignment(VerticalAlignment vAlign) {
+ setAlignment(isHorizontalCentered(), vAlign);
}
/**
setEscherProperty(propId, Units.toEMU(margin));
}
- @Override
- public boolean getWordWrap(){
- int ww = getWordWrapEx();
- return (ww != WrapNone);
- }
-
/**
* Returns the value indicating word wrap.
*
EscherSimpleProperty prop = getEscherProperty(opt, EscherProperties.TEXT__WRAPTEXT);
return prop == null ? WrapSquare : prop.getPropertyValue();
}
-
+
/**
* Specifies how the text should be wrapped
*
* @param wrap the value indicating how the text should be wrapped.
* Must be one of the <code>Wrap*</code> constants defined in this class.
*/
- public void setWordWrap(int wrap){
+ public void setWordWrapEx(int wrap){
setEscherProperty(EscherProperties.TEXT__WRAPTEXT, wrap);
}
+ @Override
+ public boolean getWordWrap(){
+ int ww = getWordWrapEx();
+ return (ww != WrapNone);
+ }
+
+ @Override
+ public void setWordWrap(boolean wrap) {
+ setWordWrapEx(wrap ? WrapSquare : WrapNone);
+ }
+
/**
* @return id for the text.
*/
return insets;
}
+ @Override
+ public void setInsets(Insets2D insets) {
+ setTopInset(insets.top);
+ setLeftInset(insets.left);
+ setBottomInset(insets.bottom);
+ setRightInset(insets.right);
+ }
+
@Override
public double getTextHeight(){
DrawFactory drawFact = DrawFactory.getInstance(null);
return HSLFTextParagraph.appendText(paras, text, newParagraph);
}
- /**
- * Sets (overwrites) the current text.
- * Uses the properties of the first paragraph / textrun
- *
- * @param text the text string used by this object.
- *
- * @return the last text run of the splitted text
- */
+ @Override
public HSLFTextRun setText(String text) {
// init paragraphs
List<HSLFTextParagraph> paras = getTextParagraphs();
return HSLFHyperlink.find(this);
}
+ @Override
+ public void setTextPlaceholder(TextPlaceholder placeholder) {
+ // TOOD: check for correct placeholder handling - see org.apache.poi.hslf.model.Placeholder
+ Placeholder ph = null;
+ int runType;
+ switch (placeholder) {
+ default:
+ case BODY:
+ runType = TextHeaderAtom.BODY_TYPE;
+ ph = Placeholder.BODY;
+ break;
+ case TITLE:
+ runType = TextHeaderAtom.TITLE_TYPE;
+ ph = Placeholder.TITLE;
+ break;
+ case CENTER_BODY:
+ runType = TextHeaderAtom.CENTRE_BODY_TYPE;
+ ph = Placeholder.BODY;
+ break;
+ case CENTER_TITLE:
+ runType = TextHeaderAtom.CENTER_TITLE_TYPE;
+ ph = Placeholder.TITLE;
+ break;
+ case HALF_BODY:
+ runType = TextHeaderAtom.HALF_BODY_TYPE;
+ ph = Placeholder.BODY;
+ break;
+ case QUARTER_BODY:
+ runType = TextHeaderAtom.QUARTER_BODY_TYPE;
+ ph = Placeholder.BODY;
+ break;
+ case NOTES:
+ runType = TextHeaderAtom.NOTES_TYPE;
+ break;
+ case OTHER:
+ runType = TextHeaderAtom.OTHER_TYPE;
+ break;
+ }
+ setRunType(runType);
+ if (ph != null) {
+ setPlaceholder(ph);
+ }
+ }
+ @Override
+ public TextPlaceholder getTextPlaceholder() {
+ switch (getRunType()) {
+ default:
+ case TextHeaderAtom.BODY_TYPE: return TextPlaceholder.BODY;
+ case TextHeaderAtom.TITLE_TYPE: return TextPlaceholder.TITLE;
+ case TextHeaderAtom.NOTES_TYPE: return TextPlaceholder.NOTES;
+ case TextHeaderAtom.OTHER_TYPE: return TextPlaceholder.OTHER;
+ case TextHeaderAtom.CENTRE_BODY_TYPE: return TextPlaceholder.CENTER_BODY;
+ case TextHeaderAtom.CENTER_TITLE_TYPE: return TextPlaceholder.CENTER_TITLE;
+ case TextHeaderAtom.HALF_BODY_TYPE: return TextPlaceholder.HALF_BODY;
+ case TextHeaderAtom.QUARTER_BODY_TYPE: return TextPlaceholder.QUARTER_BODY;
+ }
+ }
+
+
}
\ No newline at end of file
*/
line = new HSLFLine();
line.setAnchor(new java.awt.Rectangle(450, 200, 300, 0));
- line.setLineDashing(LineDash.SOLID);
+ line.setLineDash(LineDash.SOLID);
slide.addShape(line);
line = new HSLFLine();
line.setAnchor(new java.awt.Rectangle(450, 230, 300, 0));
- line.setLineDashing(LineDash.DASH);
+ line.setLineDash(LineDash.DASH);
slide.addShape(line);
line = new HSLFLine();
line.setAnchor(new java.awt.Rectangle(450, 260, 300, 0));
- line.setLineDashing(LineDash.DOT);
+ line.setLineDash(LineDash.DOT);
slide.addShape(line);
line = new HSLFLine();
line.setAnchor(new java.awt.Rectangle(450, 290, 300, 0));
- line.setLineDashing(LineDash.DASH_DOT);
+ line.setLineDash(LineDash.DASH_DOT);
slide.addShape(line);
line = new HSLFLine();
line.setAnchor(new java.awt.Rectangle(450, 320, 300, 0));
- line.setLineDashing(LineDash.LG_DASH_DOT_DOT);
+ line.setLineDash(LineDash.LG_DASH_DOT_DOT);
slide.addShape(line);
/**
*/
line = new HSLFLine();
line.setAnchor(new java.awt.Rectangle(75, 400, 300, 0));
- line.setLineDashing(LineDash.DASH_DOT);
+ line.setLineDash(LineDash.DASH_DOT);
line.setLineCompound(LineCompound.TRIPLE);
line.setLineWidth(5.0);
slide.addShape(line);
line = new HSLFLine();
line.setAnchor(new java.awt.Rectangle(75, 430, 300, 0));
- line.setLineDashing(LineDash.DASH);
+ line.setLineDash(LineDash.DASH);
line.setLineCompound(LineCompound.THICK_THIN);
line.setLineWidth(4.0);
slide.addShape(line);
line = new HSLFLine();
line.setAnchor(new java.awt.Rectangle(75, 460, 300, 0));
- line.setLineDashing(LineDash.DOT);
+ line.setLineDash(LineDash.DOT);
line.setLineCompound(LineCompound.DOUBLE);
line.setLineWidth(8.0);
slide.addShape(line);
java.awt.Rectangle lineAnchor = new java.awt.Rectangle(100, 200, 50, 60);
line.setAnchor(lineAnchor);
line.setLineWidth(3);
- line.setLineDashing(LineDash.DASH);
+ line.setLineDash(LineDash.DASH);
line.setLineColor(Color.red);
slide.addShape(line);
java.awt.Rectangle ellipseAnchor = new Rectangle(320, 154, 55, 111);
ellipse.setAnchor(ellipseAnchor);
ellipse.setLineWidth(2);
- ellipse.setLineDashing(LineDash.SOLID);
+ ellipse.setLineDash(LineDash.SOLID);
ellipse.setLineColor(Color.green);
ellipse.setFillColor(Color.lightGray);
slide.addShape(ellipse);
HSLFSlide slide = ppt.createSlide();
- HSLFTable tbl = new HSLFTable(2, 5);
- slide.addShape(tbl);
+ HSLFTable tbl = slide.createTable(2, 5);
HSLFTableCell cell = tbl.getCell(0, 0);
//table cells have type=TextHeaderAtom.OTHER_TYPE, see bug #46033
assertEquals(TextHeaderAtom.OTHER_TYPE, cell.getTextParagraphs().get(0).getRunType());
- assertTrue(slide.getShapes().get(0) instanceof HSLFTable);
- HSLFTable tbl2 = (HSLFTable)slide.getShapes().get(0);
+ HSLFShape tblSh = slide.getShapes().get(0);
+ assertTrue(tblSh instanceof HSLFTable);
+ HSLFTable tbl2 = (HSLFTable)tblSh;
assertEquals(tbl.getNumberOfColumns(), tbl2.getNumberOfColumns());
assertEquals(tbl.getNumberOfRows(), tbl2.getNumberOfRows());
HSLFSlideShow ppt = new HSLFSlideShow();
HSLFSlide slide = ppt.createSlide();
List<HSLFShape> shapes;
- HSLFTable tbl1 = new HSLFTable(1, 5);
+ HSLFTable tbl1 = slide.createTable(1, 5);
assertEquals(5, tbl1.getNumberOfColumns());
assertEquals(1, tbl1.getNumberOfRows());
- slide.addShape(tbl1);
shapes = slide.getShapes();
assertEquals(1, shapes.size());
@Test
public void testIllegalCOnstruction(){
+ HSLFSlideShow ppt = new HSLFSlideShow();
+ HSLFSlide slide = ppt.createSlide();
try {
- new HSLFTable(0, 5);
+ slide.createTable(0, 5);
fail("Table(rownum, colnum) must throw IllegalArgumentException if any of tghe arguments is less than 1");
} catch (IllegalArgumentException e){
}
try {
- new HSLFTable(5, 0);
+ slide.createTable(5, 0);
fail("Table(rownum, colnum) must throw IllegalArgumentException if any of tghe arguments is less than 1");
} catch (IllegalArgumentException e){
package org.apache.poi.hslf.usermodel;
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import java.awt.Color;
+import java.awt.Rectangle;
import java.util.List;
import org.apache.poi.POIDataSamples;
+import org.apache.poi.sl.draw.DrawTableShape;
+import org.apache.poi.sl.usermodel.StrokeStyle;
import org.junit.Test;
/**
- * Test that checks numbered list functionality.
- *
- * @author Alex Nikiforov [mailto:anikif@gmail.com]
+ * Table related tests
*/
public class TestTable {
private static POIDataSamples _slTests = POIDataSamples.getSlideShowInstance();
+ @Test
+ public void moveTable() throws Exception {
+ HSLFSlideShow ppt = new HSLFSlideShow();
+ HSLFSlide slide = ppt.createSlide();
+ int rows = 3, cols = 5;
+ HSLFTable table = slide.createTable(rows, cols);
+ for (int row=0; row<rows; row++) {
+ for (int col=0; col<cols; col++) {
+ HSLFTableCell c = table.getCell(row, col);
+ c.setText("r"+row+"c"+col);
+ }
+ }
+
+ new DrawTableShape(table).setAllBorders(1.0, Color.black, StrokeStyle.LineDash.DASH_DOT);
+
+ table.setAnchor(new Rectangle(100, 100, 400, 400));
+
+ Rectangle rectExp = new Rectangle(420,367,80,133);
+ Rectangle rectAct = table.getCell(rows-1, cols-1).getAnchor();
+ assertEquals(rectExp, rectAct);
+ }
+
@Test
public void testTable() throws Exception {
HSLFSlideShow ppt = new HSLFSlideShow(_slTests.openResourceAsStream("54111.ppt"));
}
}
+ @Test
+ public void testAppendEmpty() throws IOException {
+ HSLFSlideShow ppt = new HSLFSlideShow();
+ HSLFSlide s = ppt.createSlide();
+ HSLFTextBox title = s.addTitle();
+ title.setText("");
+ title.appendText("\n", true);
+ title.appendText("para", true);
+ }
}