slide.addShape(box2);
HSLFTextBox box3 = new HSLFTextBox();
- box3.getTextParagraphs().get(0).getTextRuns().get(0).setFontSize(32);
+ box3.getTextParagraphs().get(0).getTextRuns().get(0).setFontSize(32d);
box3.setText(
"Yegor Kozlov\r" +
"yegor - apache - org");
List<HSLFTextParagraph> tp = box2.getTextParagraphs();
for (int i : new byte[]{0,1,2,8}) {
- tp.get(i).getTextRuns().get(0).setFontSize(28);
+ tp.get(i).getTextRuns().get(0).setFontSize(28d);
}
for (int i : new byte[]{3,4,5,6,7}) {
- tp.get(i).getTextRuns().get(0).setFontSize(24);
+ tp.get(i).getTextRuns().get(0).setFontSize(24d);
tp.get(i).setIndentLevel(1);
}
box2.setAnchor(new Rectangle(36, 80, 648, 400));
HSLFTableCell cell = table1.getCell(i, j);
cell.setText(txt1[i][j]);
HSLFTextRun rt = cell.getTextParagraphs().get(0).getTextRuns().get(0);
- rt.setFontSize(10);
+ rt.setFontSize(10d);
rt.setFontFamily("Arial");
rt.setBold(true);
if(i == 0){
- rt.setFontSize(32);
+ rt.setFontSize(32d);
rt.setFontColor(Color.white);
cell.getFill().setForegroundColor(new Color(0, 153, 204));
} else {
- rt.setFontSize(28);
+ rt.setFontSize(28d);
cell.getFill().setForegroundColor(new Color(235, 239, 241));
}
cell.setVerticalAlignment(VerticalAlignment.MIDDLE);
HSLFTextBox box1 = new HSLFTextBox();
box1.setHorizontalCentered(true);
- box1.getTextParagraphs().get(0).getTextRuns().get(0).setFontSize(24);
+ 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);
HSLFTextBox box2 = new HSLFTextBox();
- box2.getTextParagraphs().get(0).getTextRuns().get(0).setFontSize(18);
+ 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);
rt3.setFontFamily("Courier New");
- rt3.setFontSize(8);
+ rt3.setFontSize(8d);
box3.setText(
"SlideShow ppt = new SlideShow();\u000b" +
"Slide slide = ppt.createSlide();\u000b" +
slide.addShape(box1);
HSLFTextBox box2 = new HSLFTextBox();
- box2.getTextParagraphs().get(0).getTextRuns().get(0).setFontSize(18);
+ 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);
rt3.setFontFamily("Courier New");
- rt3.setFontSize(8);
+ rt3.setFontSize(8d);
box3.setText(
"//bar chart data. The first value is the bar color, the second is the width\u000b" +
"Object[] def = new Object[]{\u000b" +
List<HSLFTextParagraph> tp = box2.getTextParagraphs();
for (int i : new byte[]{0,1,3}) {
- tp.get(i).getTextRuns().get(0).setFontSize(28);
+ tp.get(i).getTextRuns().get(0).setFontSize(28d);
}
for (int i : new byte[]{2,4,5}) {
- tp.get(i).getTextRuns().get(0).setFontSize(24);
+ tp.get(i).getTextRuns().get(0).setFontSize(24d);
tp.get(i).setIndentLevel(1);
}
HSLFTextBox shape = new HSLFTextBox();
HSLFTextParagraph rt = shape.getTextParagraphs().get(0);
- rt.getTextRuns().get(0).setFontSize(42);
+ rt.getTextRuns().get(0).setFontSize(42d);
rt.setBullet(true);
rt.setIndent(0d); //bullet offset
rt.setLeftMargin(50d); //text offset (should be greater than bullet offset)
HSLFTableCell cell = table1.getCell(i, j);
HSLFTextRun rt = cell.getTextParagraphs().get(0).getTextRuns().get(0);
rt.setFontFamily("Arial");
- rt.setFontSize(10);
+ rt.setFontSize(10d);
if(i == 0){
cell.getFill().setForegroundColor(new Color(227, 227, 227));
} else {
for (int j = 0; j < txt2[i].length; j++) {
HSLFTableCell cell = table2.getCell(i, j);
HSLFTextRun rt = cell.getTextParagraphs().get(0).getTextRuns().get(0);
- rt.setFontSize(10);
+ rt.setFontSize(10d);
rt.setFontFamily("Arial");
if(i == 0){
cell.getFill().setForegroundColor(new Color(0, 51, 102));
rt.setFontColor(Color.white);
rt.setBold(true);
- rt.setFontSize(14);
+ rt.setFontSize(14d);
cell.setHorizontalCentered(true);
} else {
rt.getTextParagraph().setBullet(true);
- rt.setFontSize(12);
+ rt.setFontSize(12d);
rt.getTextParagraph().setAlignment(TextAlign.LEFT);
cell.setHorizontalCentered(false);
}
XSLFTextParagraph p1 = shape1.addNewTextParagraph();\r
XSLFTextRun r1 = p1.addNewTextRun();\r
r1.setText("Paragraph Formatting");\r
- r1.setFontSize(24);\r
+ r1.setFontSize(24d);\r
r1.setFontColor(new Color(85, 142, 213));\r
\r
XSLFTextParagraph p2 = shape1.addNewTextParagraph();\r
p2.setSpaceAfter(300d); // 3 lines after the paragraph\r
XSLFTextRun r2 = p2.addNewTextRun();\r
r2.setText("Paragraph properties apply to all text residing within the corresponding paragraph.");\r
- r2.setFontSize(16);\r
+ r2.setFontSize(16d);\r
\r
XSLFTextParagraph p3 = shape1.addNewTextParagraph();\r
\r
XSLFTextRun r3 = p3.addNewTextRun();\r
r3.setText("Run Formatting");\r
- r3.setFontSize(24);\r
+ r3.setFontSize(24d);\r
r3.setFontColor(new Color(85, 142, 213));\r
\r
XSLFTextParagraph p4 = shape1.addNewTextParagraph();\r
p4.setSpaceBefore(-20d); // 20 pt from the previous paragraph\r
p4.setSpaceAfter(300d); // 3 lines after the paragraph\r
XSLFTextRun r4 = p4.addNewTextRun();\r
- r4.setFontSize(16);\r
+ r4.setFontSize(16d);\r
r4.setText(\r
"Run level formatting is the most granular property level and allows " +\r
"for the specifying of all low level text properties. The text run is " +\r
if (pr == null) {\r
pr = shape.getGrpSpPr();\r
}\r
+ if (pr == null) {\r
+ if (shape.getXmlObject() instanceof CTBackground) {\r
+ pr = shape.getXmlObject();\r
+ }\r
+ }\r
+ \r
if (pr == null) {\r
setValue(PaintStyle.TRANSPARENT_PAINT);\r
return true;\r
if (fillRef == null) {\r
fillRef = getBgRef();\r
}\r
- if (fillRef == null) {\r
- return PaintStyle.TRANSPARENT_PAINT;\r
- }\r
-\r
- // The idx attribute refers to the index of a fill style or\r
- // background fill style within the presentation's style matrix, defined by the fmtScheme element.\r
- // value of 0 or 1000 indicates no background,\r
- // values 1-999 refer to the index of a fill style within the fillStyleLst element\r
- // values 1001 and above refer to the index of a background fill style within the bgFillStyleLst element.\r
- int idx = (int)fillRef.getIdx();\r
- CTSchemeColor phClr = fillRef.getSchemeClr();\r
- XSLFSheet sheet = getSheet();\r
- XSLFTheme theme = sheet.getTheme();\r
- XmlObject fillProps = null;\r
- CTStyleMatrix matrix = theme.getXmlObject().getThemeElements().getFmtScheme();\r
- if(idx >= 1 && idx <= 999){\r
- fillProps = matrix.getFillStyleLst().selectPath("*")[idx - 1];\r
- } else if (idx >= 1001 ){\r
- fillProps = matrix.getBgFillStyleLst().selectPath("*")[idx - 1001];\r
- }\r
- if(fillProps != null) {\r
- paint = selectPaint(fillProps, phClr, sheet.getPackagePart());\r
- }\r
+ paint = selectPaint(fillRef);\r
\r
return paint == null ? PaintStyle.TRANSPARENT_PAINT : paint;\r
}\r
}\r
return _ph;\r
}\r
+\r
+ /**\r
+ * Specifies that the corresponding shape should be represented by the generating application\r
+ * as a placeholder. 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
+ * Different types of placeholders are allowed and can be specified by using the placeholder\r
+ * type attribute for this element\r
+ *\r
+ * @param placeholder\r
+ */\r
+ protected void setPlaceholder(Placeholder placeholder) {\r
+ String xquery = "declare namespace p='http://schemas.openxmlformats.org/presentationml/2006/main' .//*/p:nvPr";\r
+ CTApplicationNonVisualDrawingProps nv = selectProperty(CTApplicationNonVisualDrawingProps.class, xquery);\r
+ if (nv == null) return;\r
+ if(placeholder == null) {\r
+ if (nv.isSetPh()) nv.unsetPh();\r
+ _ph = null;\r
+ } else {\r
+ nv.addNewPh().setType(STPlaceholderType.Enum.forInt(placeholder.ordinal() + 1));\r
+ }\r
+ }\r
+ \r
\r
/**\r
* As there's no xmlbeans hierarchy, but XSLF works with subclassing, not all\r
return selectPaint((CTBlipFillProperties)obj, phClr, parentPart);\r
} else if (obj instanceof CTGradientFillProperties) {\r
return selectPaint((CTGradientFillProperties) obj, phClr, parentPart);\r
+ } else if (obj instanceof CTStyleMatrixReference) {\r
+ return selectPaint((CTStyleMatrixReference)obj);\r
} else {\r
return null;\r
}\r
}; \r
}\r
\r
-\r
+ protected PaintStyle selectPaint(CTStyleMatrixReference fillRef) {\r
+ if (fillRef == null) return null;\r
+ \r
+ // The idx attribute refers to the index of a fill style or\r
+ // background fill style within the presentation's style matrix, defined by the fmtScheme element.\r
+ // value of 0 or 1000 indicates no background,\r
+ // values 1-999 refer to the index of a fill style within the fillStyleLst element\r
+ // values 1001 and above refer to the index of a background fill style within the bgFillStyleLst element.\r
+ int idx = (int)fillRef.getIdx();\r
+ CTSchemeColor phClr = fillRef.getSchemeClr();\r
+ XSLFSheet sheet = getSheet();\r
+ XSLFTheme theme = sheet.getTheme();\r
+ XmlObject fillProps = null;\r
+ CTStyleMatrix matrix = theme.getXmlObject().getThemeElements().getFmtScheme();\r
+ if (idx >= 1 && idx <= 999) {\r
+ fillProps = matrix.getFillStyleLst().selectPath("*")[idx - 1];\r
+ } else if (idx >= 1001 ){\r
+ fillProps = matrix.getBgFillStyleLst().selectPath("*")[idx - 1001];\r
+ }\r
+ return (fillProps == null) ? null : selectPaint(fillProps, phClr, theme.getPackagePart());\r
+ }\r
}
\ No newline at end of file
\r
private double getBorderWidth(char bltr) {\r
CTLineProperties ln = getCTLine(bltr, false);\r
- return (ln == null) ? defaultBorderWidth : Units.toPoints(ln.getW());\r
+ return (ln == null || !ln.isSetW()) ? defaultBorderWidth : Units.toPoints(ln.getW());\r
}\r
\r
private void setBorderColor(char bltr, Color color) {\r
import org.apache.poi.sl.usermodel.TextParagraph;\r
import org.apache.poi.util.*;\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.presentationml.x2006.main.CTPlaceholder;\r
\r
@Override\r
public void setIndent(Double indent){\r
- if ((indent == null || indent == -1d) && !_p.isSetPPr()) return;\r
+ if ((indent == null) && !_p.isSetPPr()) return;\r
CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr();\r
- if(indent == -1) {\r
+ if(indent == null) {\r
if(pr.isSetIndent()) pr.unsetIndent();\r
} else {\r
pr.setIndent(Units.toEMU(indent));\r
public void setRightMargin(Double rightMargin){\r
if (rightMargin == null && !_p.isSetPPr()) return;\r
CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr();\r
- if(rightMargin == -1) {\r
+ if(rightMargin == null) {\r
if(pr.isSetMarR()) pr.unsetMarR();\r
} else {\r
pr.setMarR(Units.toEMU(rightMargin));\r
return ok;\r
}\r
\r
- void copy(XSLFTextParagraph p){\r
- TextAlign srcAlign = p.getTextAlign();\r
+ void copy(XSLFTextParagraph other){\r
+ if (other == this) return;\r
+ \r
+ CTTextParagraph thisP = getXmlObject();\r
+ CTTextParagraph otherP = other.getXmlObject();\r
+ \r
+ if (thisP.isSetPPr()) thisP.unsetPPr();\r
+ if (thisP.isSetEndParaRPr()) thisP.unsetEndParaRPr();\r
+ \r
+ _runs.clear();\r
+ for (int i=thisP.sizeOfBrArray(); i>0; i--) {\r
+ thisP.removeBr(i-1);\r
+ }\r
+ for (int i=thisP.sizeOfRArray(); i>0; i--) {\r
+ thisP.removeR(i-1);\r
+ }\r
+ for (int i=thisP.sizeOfFldArray(); i>0; i--) {\r
+ thisP.removeFld(i-1);\r
+ }\r
+\r
+ XmlCursor thisC = thisP.newCursor();\r
+ thisC.toEndToken();\r
+ XmlCursor otherC = otherP.newCursor();\r
+ otherC.copyXmlContents(thisC);\r
+ otherC.dispose();\r
+ thisC.dispose();\r
+ \r
+ List<XSLFTextRun> otherRs = other.getTextRuns();\r
+ int i=0;\r
+ for(CTRegularTextRun rtr : thisP.getRArray()) {\r
+ XSLFTextRun run = new XSLFTextRun(rtr, this);\r
+ run.copy(otherRs.get(i++));\r
+ _runs.add(run);\r
+ }\r
+ \r
+ \r
+ // set properties again, in case we are based on a different\r
+ // template\r
+ TextAlign srcAlign = other.getTextAlign();\r
if(srcAlign != getTextAlign()){\r
setTextAlign(srcAlign);\r
}\r
\r
- boolean isBullet = p.isBullet();\r
+ boolean isBullet = other.isBullet();\r
if(isBullet != isBullet()){\r
setBullet(isBullet);\r
if(isBullet) {\r
- String buFont = p.getBulletFont();\r
+ String buFont = other.getBulletFont();\r
if(buFont != null && !buFont.equals(getBulletFont())){\r
setBulletFont(buFont);\r
}\r
- String buChar = p.getBulletCharacter();\r
+ String buChar = other.getBulletCharacter();\r
if(buChar != null && !buChar.equals(getBulletCharacter())){\r
setBulletCharacter(buChar);\r
}\r
- Color buColor = p.getBulletFontColor();\r
+ Color buColor = other.getBulletFontColor();\r
if(buColor != null && !buColor.equals(getBulletFontColor())){\r
setBulletFontColor(buColor);\r
}\r
- double buSize = p.getBulletFontSize();\r
- if(buSize != getBulletFontSize()){\r
+ Double buSize = other.getBulletFontSize();\r
+ if(!doubleEquals(buSize, getBulletFontSize())){\r
setBulletFontSize(buSize);\r
}\r
}\r
}\r
\r
- Double leftMargin = p.getLeftMargin();\r
- if(leftMargin != getLeftMargin()){\r
+ Double leftMargin = other.getLeftMargin();\r
+ if (!doubleEquals(leftMargin, getLeftMargin())){\r
setLeftMargin(leftMargin);\r
}\r
\r
- Double indent = p.getIndent();\r
- if(indent != getIndent()){\r
+ Double indent = other.getIndent();\r
+ if (!doubleEquals(indent, getIndent())) {\r
setIndent(indent);\r
}\r
\r
- Double spaceAfter = p.getSpaceAfter();\r
- if(spaceAfter != getSpaceAfter()){\r
+ Double spaceAfter = other.getSpaceAfter();\r
+ if (!doubleEquals(spaceAfter, getSpaceAfter())) {\r
setSpaceAfter(spaceAfter);\r
}\r
\r
- Double spaceBefore = p.getSpaceBefore();\r
- if(spaceBefore != getSpaceBefore()){\r
+ Double spaceBefore = other.getSpaceBefore();\r
+ if (!doubleEquals(spaceBefore, getSpaceBefore())) {\r
setSpaceBefore(spaceBefore);\r
}\r
\r
- Double lineSpacing = p.getLineSpacing();\r
- if(lineSpacing != getLineSpacing()){\r
+ Double lineSpacing = other.getLineSpacing();\r
+ if (!doubleEquals(lineSpacing, getLineSpacing())) {\r
setLineSpacing(lineSpacing);\r
}\r
-\r
- List<XSLFTextRun> srcR = p.getTextRuns();\r
- List<XSLFTextRun> tgtR = getTextRuns();\r
- for(int i = 0; i < srcR.size(); i++){\r
- XSLFTextRun r1 = srcR.get(i);\r
- XSLFTextRun r2 = tgtR.get(i);\r
- r2.copy(r1);\r
- }\r
}\r
\r
+ private static boolean doubleEquals(Double d1, Double d2) {\r
+ return (d1 == d2 || (d1 != null && d1.equals(d2)));\r
+ }\r
+ \r
@Override\r
public Double getDefaultFontSize() {\r
CTTextCharacterProperties endPr = _p.getEndParaRPr();\r
return _r;\r
}\r
\r
- public void setFontColor(Color color){\r
+ @Override\r
+ public void setFontColor(Color color) {\r
CTTextCharacterProperties rPr = getRPr();\r
CTSolidColorFillProperties fill = rPr.isSetSolidFill() ? rPr.getSolidFill() : rPr.addNewSolidFill();\r
CTSRgbColor clr = fill.isSetSrgbClr() ? fill.getSrgbClr() : fill.addNewSrgbClr();\r
\r
}\r
\r
+ @Override\r
public Color getFontColor(){\r
final XSLFTheme theme = _p.getParentShape().getSheet().getTheme();\r
CTShapeStyle style = _p.getParentShape().getSpStyle();\r
return fetcher.getValue();\r
}\r
\r
- /**\r
- *\r
- * @param fontSize font size in points.\r
- * The value of <code>-1</code> unsets the Sz attribyte from the underlying xml bean\r
- */\r
- public void setFontSize(double fontSize){\r
+ @Override\r
+ public void setFontSize(Double fontSize){\r
CTTextCharacterProperties rPr = getRPr();\r
- if(fontSize == -1.0) {\r
- if(rPr.isSetSz()) rPr.unsetSz();\r
+ if(fontSize == null) {\r
+ if (rPr.isSetSz()) rPr.unsetSz();\r
} else {\r
- if(fontSize < 1.0) {\r
+ if (fontSize < 1.0) {\r
throw new IllegalArgumentException("Minimum font size is 1pt but was " + fontSize);\r
}\r
\r
}\r
}\r
\r
- /**\r
- * @return font size in points or null if font size is not set.\r
- */\r
@Override\r
public Double getFontSize(){\r
double scale = 1;\r
protected abstract CTTextBody getTextBody(boolean create);
+ @Override
+ public void setPlaceholder(Placeholder placeholder) {
+ super.setPlaceholder(placeholder);
+ }
public Placeholder getTextType(){
CTPlaceholder ph = getCTPlaceholder();
return Placeholder.values()[val - 1];
}
-
- /**
- * Specifies that the corresponding shape should be represented by the generating application
- * as a placeholder. When a shape is considered a placeholder by the generating application
- * it can have special properties to alert the user that they may enter content into the shape.
- * Different types of placeholders are allowed and can be specified by using the placeholder
- * type attribute for this element
- *
- * @param placeholder
- */
- public void setPlaceholder(Placeholder placeholder){
- String xquery = "declare namespace p='http://schemas.openxmlformats.org/presentationml/2006/main' .//*/p:nvPr";
- CTApplicationNonVisualDrawingProps nv = selectProperty(CTApplicationNonVisualDrawingProps.class, xquery);
- if (nv == null) return;
- if(placeholder == null) {
- if (nv.isSetPh()) nv.unsetPh();
- } else {
- nv.addNewPh().setType(STPlaceholderType.Enum.forInt(placeholder.ordinal() + 1));
- }
- }
-
@Override
public double getTextHeight(){
DrawFactory drawFact = DrawFactory.getInstance(null);
@Override
- void copy(XSLFShape sh){
- super.copy(sh);
-
- XSLFTextShape tsh = (XSLFTextShape)sh;
+ void copy(XSLFShape other){
+ super.copy(other);
+
+ XSLFTextShape otherTS = (XSLFTextShape)other;
+ CTTextBody otherTB = otherTS.getTextBody(false);
+ CTTextBody thisTB = getTextBody(true);
+ if (otherTB == null) {
+ return;
+ }
+
+ thisTB.setBodyPr((CTTextBodyProperties)otherTB.getBodyPr().copy());
- boolean srcWordWrap = tsh.getWordWrap();
+ if (thisTB.isSetLstStyle()) thisTB.unsetLstStyle();
+ if (otherTB.isSetLstStyle()) {
+ thisTB.setLstStyle((CTTextListStyle)otherTB.getLstStyle().copy());
+ }
+
+ boolean srcWordWrap = otherTS.getWordWrap();
if(srcWordWrap != getWordWrap()){
setWordWrap(srcWordWrap);
}
- double leftInset = tsh.getLeftInset();
+ double leftInset = otherTS.getLeftInset();
if(leftInset != getLeftInset()) {
setLeftInset(leftInset);
}
- double rightInset = tsh.getRightInset();
+ double rightInset = otherTS.getRightInset();
if(rightInset != getRightInset()) {
setRightInset(rightInset);
}
- double topInset = tsh.getTopInset();
+ double topInset = otherTS.getTopInset();
if(topInset != getTopInset()) {
setTopInset(topInset);
}
- double bottomInset = tsh.getBottomInset();
+ double bottomInset = otherTS.getBottomInset();
if(bottomInset != getBottomInset()) {
setBottomInset(bottomInset);
}
- VerticalAlignment vAlign = tsh.getVerticalAlignment();
+ VerticalAlignment vAlign = otherTS.getVerticalAlignment();
if(vAlign != getVerticalAlignment()) {
setVerticalAlignment(vAlign);
}
- List<XSLFTextParagraph> srcP = tsh.getTextParagraphs();
- List<XSLFTextParagraph> tgtP = getTextParagraphs();
- for(int i = 0; i < srcP.size(); i++){
- XSLFTextParagraph p1 = srcP.get(i);
- XSLFTextParagraph p2 = tgtP.get(i);
- p2.copy(p1);
+ clearText();
+
+ for (XSLFTextParagraph srcP : otherTS.getTextParagraphs()) {
+ XSLFTextParagraph tgtP = addNewTextParagraph();
+ tgtP.copy(srcP);
}
-
}
}
\ No newline at end of file
p.setIndent(2.0);\r
assertEquals(2.0, p.getIndent(), 0);\r
assertTrue(p.getXmlObject().getPPr().isSetIndent());\r
- p.setIndent(-1d);\r
+ p.setIndent(null);\r
assertNull(p.getIndent());\r
assertFalse(p.getXmlObject().getPPr().isSetIndent());\r
p.setIndent(10.0);\r
assertEquals(1000, r.getXmlObject().getRPr().getSz());\r
r.setFontSize(12.5);\r
assertEquals(1250, r.getXmlObject().getRPr().getSz());\r
- r.setFontSize(-1);\r
+ r.setFontSize(null);\r
assertFalse(r.getXmlObject().getRPr().isSetSz());\r
\r
assertFalse(r.getXmlObject().getRPr().isSetLatin());\r
assertFalse(r2.isItalic());\r
assertEquals(Color.white, r2.getFontColor());\r
assertEquals(new Color(148, 198, 0), sh2.getFillColor());\r
- assertEquals(new Color(74, 99, 0), sh2.getLineColor()); // slightly different from PowerPoint!\r
+ assertEquals(new Color(148, 198, 0), sh2.getLineColor()); // slightly different from PowerPoint!\r
\r
// the 5th slide has a picture and a texture fill\r
XSLFSlide slide2 = ppt.createSlide().importContent(src.getSlides().get(4));\r
assertEquals(20.0, r.getFontSize(), 0);\r
\r
pPr.unsetSz(); // Should never be\r
- assertEquals(-1.0, r.getFontSize(), 0);\r
-\r
+ assertNull(r.getFontSize());\r
}\r
}
\ No newline at end of file
import org.apache.poi.util.POILogFactory;\r
import org.apache.poi.util.POILogger;\r
import org.apache.poi.xslf.XSLFTestDataSamples;\r
+import org.junit.Assume;\r
import org.junit.Test;\r
\r
/**\r
\r
DrawTextParagraphProxy dtp = new DrawTextParagraphProxy(p);\r
\r
- double leftInset = sh.getLeftInset();\r
- double rightInset = sh.getRightInset();\r
+ Double leftInset = sh.getLeftInset();\r
+ Double rightInset = sh.getRightInset();\r
assertEquals(7.2, leftInset, 0);\r
assertEquals(7.2, rightInset, 0);\r
\r
- double leftMargin = p.getLeftMargin();\r
+ Double leftMargin = p.getLeftMargin();\r
assertEquals(0.0, leftMargin, 0);\r
\r
- double indent = p.getIndent();\r
- assertEquals(0.0, indent, 0); // default\r
+ Double indent = p.getIndent();\r
+ assertNull(indent); // default\r
\r
double expectedWidth;\r
\r
@Test\r
public void testBreakLines(){\r
String os = System.getProperty("os.name");\r
- if(os == null || !os.contains("Windows")) {\r
- _logger.log(POILogger.WARN, "Skipping testBreakLines(), it is executed only on Windows machines");\r
- return;\r
- }\r
+ Assume.assumeTrue("Skipping testBreakLines(), it is executed only on Windows machines", (os != null && os.contains("Windows")));\r
\r
XMLSlideShow ppt = new XMLSlideShow();\r
XSLFSlide slide = ppt.createSlide();\r
XSLFTextParagraph p = sh.addNewTextParagraph();\r
XSLFTextRun r = p.addNewTextRun();\r
r.setFontFamily("Arial"); // this should always be available\r
- r.setFontSize(12);\r
+ r.setFontSize(12d);\r
r.setText(\r
"Paragraph formatting allows for more granular control " +\r
"of text within a shape. Properties here apply to all text " +\r
lines = dtp.getLines();\r
assertEquals(4, lines.size());\r
\r
- // descrease the shape width from 300 pt to 100 pt\r
+ // decrease the shape width from 300 pt to 100 pt\r
sh.setAnchor(new Rectangle(50, 50, 100, 200));\r
dtp.breakText(graphics);\r
lines = dtp.getLines();\r
assertEquals(12, lines.size());\r
\r
- // descrease the shape width from 300 pt to 100 pt\r
+ // decrease the shape width from 300 pt to 100 pt\r
sh.setAnchor(new Rectangle(50, 50, 600, 200));\r
dtp.breakText(graphics);\r
lines = dtp.getLines();\r
XSLFTextParagraph p2 = sh2.addNewTextParagraph();\r
XSLFTextRun r2 = p2.addNewTextRun();\r
r2.setFontFamily("serif"); // this should always be available\r
- r2.setFontSize(30);\r
+ r2.setFontSize(30d);\r
r2.setText("Apache\n");\r
XSLFTextRun r3 = p2.addNewTextRun();\r
r3.setFontFamily("serif"); // this should always be available\r
- r3.setFontSize(10);\r
+ r3.setFontSize(10d);\r
r3.setText("POI");\r
+ dtp = new DrawTextParagraphProxy(p2);\r
dtp.breakText(graphics);\r
lines = dtp.getLines();\r
assertEquals(2, lines.size());\r
p.setBulletFontColor(Color.red);\r
assertEquals(Color.red, p.getBulletFontColor());\r
\r
- assertEquals(100.0, p.getBulletFontSize(), 0);\r
+ assertNull(p.getBulletFontSize());\r
p.setBulletFontSize(200.);\r
assertEquals(200., p.getBulletFontSize(), 0);\r
p.setBulletFontSize(-20.);\r
\r
assertEquals(72.0, p.getDefaultTabSize(), 0);\r
\r
- assertEquals(0.0, p.getIndent(), 0);\r
+ assertNull(p.getIndent());\r
p.setIndent(72.0);\r
assertEquals(72.0, p.getIndent(), 0);\r
- p.setIndent(-1.0); // the value of -1.0 resets to the defaults\r
- assertEquals(0.0, p.getIndent(), 0);\r
+ p.setIndent(-1d); // the value of -1.0 resets to the defaults (not any more ...)\r
+ assertEquals(-1d, p.getIndent(), 0);\r
+ p.setIndent(null); \r
+ assertNull(p.getIndent());\r
\r
assertEquals(0.0, p.getLeftMargin(), 0);\r
p.setLeftMargin(72.0);\r
assertEquals(72.0, p.getLeftMargin(), 0);\r
p.setLeftMargin(-1.0); // the value of -1.0 resets to the defaults\r
- assertEquals(0.0, p.getLeftMargin(), 0);\r
+ assertEquals(-1.0, p.getLeftMargin(), 0);\r
+ p.setLeftMargin(null);\r
+ assertEquals(0d, p.getLeftMargin(), 0); // default will be taken from master\r
\r
assertEquals(0, p.getIndentLevel());\r
p.setIndentLevel(1);\r
p.setIndentLevel(2);\r
assertEquals(2, p.getIndentLevel());\r
\r
- assertEquals(100., p.getLineSpacing(), 0);\r
+ assertNull(p.getLineSpacing());\r
p.setLineSpacing(200.);\r
assertEquals(200.0, p.getLineSpacing(), 0);\r
p.setLineSpacing(-15.);\r
assertEquals(-15.0, p.getLineSpacing(), 0);\r
\r
- assertEquals(0., p.getSpaceAfter(), 0);\r
+ assertNull(p.getSpaceAfter());\r
p.setSpaceAfter(200.);\r
assertEquals(200.0, p.getSpaceAfter(), 0);\r
p.setSpaceAfter(-15.);\r
assertEquals(-15.0, p.getSpaceAfter(), 0);\r
\r
- assertEquals(0., p.getSpaceBefore(), 0);\r
+ assertNull(p.getSpaceBefore());\r
p.setSpaceBefore(200.);\r
assertEquals(200.0, p.getSpaceBefore(), 0);\r
p.setSpaceBefore(-15.);\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
+import org.junit.Test;\r
import org.openxmlformats.schemas.drawingml.x2006.main.*;\r
import org.openxmlformats.schemas.presentationml.x2006.main.CTPlaceholder;\r
import org.openxmlformats.schemas.presentationml.x2006.main.STPlaceholderType;\r
*/\r
public class TestXSLFTextShape {\r
\r
+ @Test\r
public void testLayouts(){\r
XMLSlideShow ppt = XSLFTestDataSamples.openSampleDocument("layouts.pptx");\r
\r
assertEquals("10", sldNum.getText());\r
}\r
\r
-\r
+ @Test\r
public void testTitleStyles(){\r
XMLSlideShow ppt = new XMLSlideShow();\r
\r
assertEquals(TextAlign.CENTER, paragraph.getTextAlign());\r
}\r
\r
+ @Test\r
public void testBodyStyles(){\r
XMLSlideShow ppt = new XMLSlideShow();\r
\r
}\r
\r
void slide1(XSLFSlide slide){\r
- assertEquals(Color.white, slide.getBackground().getFillColor());\r
+ assertEquals(Color.WHITE, slide.getBackground().getFillColor());\r
\r
XSLFTheme theme = slide.getTheme();\r
assertEquals("Office Theme", theme.getName());\r
void slide2(XSLFSlide slide){\r
// Background 2, darker 10%\r
// YK: PPT shows slightly different color: new Color(221, 217, 195)\r
- assertEquals(new Color(214, 212, 203), slide.getBackground().getFillColor());\r
+ assertEquals(new Color(221, 217, 195), slide.getBackground().getFillColor());\r
}\r
\r
void slide3(XSLFSlide slide){\r
void slide7(XSLFSlide slide){\r
\r
//YK: PPT reports a slightly different color: r=189,g=239,b=87\r
- assertEquals(new Color(182, 218, 108), slide.getBackground().getFillColor());\r
+ assertEquals(new Color(189, 239, 87), slide.getBackground().getFillColor());\r
\r
assertFalse(slide.getFollowMasterGraphics());\r
}\r
txt.setText(s);
HSLFTextRun rt = txt.getTextParagraphs().get(0).getTextRuns().get(0);
- rt.setFontSize(_font.getSize());
+ rt.setFontSize((double)_font.getSize());
rt.setFontFamily(_font.getFamily());
if (getColor() != null) rt.setFontColor(getColor());
* @param propName The name of the Paragraph TextProp
* @param val The value to set for the TextProp
*/
- public void setCharTextPropVal(String propName, int val) {
+ public void setCharTextPropVal(String propName, Integer val) {
setPropVal(characterStyle, propName, val);
}
setPropVal(characterStyle, "superscript", val);
}
- /**
- * Gets the font size
- */
+ @Override
public Double getFontSize() {
TextProp tp = getPropVal(characterStyle, "font.size", parentParagraph);
return tp == null ? null : (double)tp.getValue();
}
- /**
- * Sets the font size
- */
- public void setFontSize(int fontSize) {
- setCharTextPropVal("font.size", fontSize);
+ @Override
+ public void setFontSize(Double fontSize) {
+ Integer iFontSize = (fontSize == null) ? null : fontSize.intValue();
+ setCharTextPropVal("font.size", iFontSize);
}
/**
package org.apache.poi.sl.draw;\r
\r
import static org.apache.poi.sl.usermodel.PaintStyle.TRANSPARENT_PAINT;\r
+\r
import java.awt.*;\r
import java.awt.MultipleGradientPaint.ColorSpaceType;\r
import java.awt.MultipleGradientPaint.CycleMethod;\r
-import java.awt.Shape;\r
import java.awt.geom.*;\r
-import java.awt.image.*;\r
import java.io.IOException;\r
import java.io.InputStream;\r
\r
import org.apache.poi.util.POILogger;\r
\r
\r
+/**\r
+ * This class handles color transformations\r
+ * \r
+ * @see HSL code taken from <a href="https://tips4java.wordpress.com/2009/07/05/hsl-color/">Java Tips Weblog</a>\r
+ */\r
public class DrawPaint {\r
+ // HSL code is public domain - see https://tips4java.wordpress.com/contact-us/\r
\r
private final static POILogger LOG = POILogFactory.getLogger(DrawPaint.class);\r
\r
}\r
\r
result = applyAlpha(result, color);\r
- result = applyLuminanace(result, color);\r
+ result = applyLuminance(result, color);\r
result = applyShade(result, color);\r
result = applyTint(result, color);\r
\r
\r
protected static Color applyAlpha(Color c, ColorStyle fc) {\r
int alpha = c.getAlpha();\r
- return (alpha == 0 || alpha == -1) ? c : new Color(c.getRed(), c.getGreen(), c.getBlue(), alpha); \r
+ return (alpha == 255) ? c : new Color(c.getRed(), c.getGreen(), c.getBlue(), alpha); \r
}\r
\r
/**\r
* @param lumMod luminance modulation in the range [0..100000]\r
* @param lumOff luminance offset in the range [0..100000]\r
* @return modified color\r
+ * \r
+ * @see <a href="https://msdn.microsoft.com/en-us/library/dd560821%28v=office.12%29.aspx">Using Office Open XML to Customize Document Formatting in the 2007 Office System</a>\r
*/\r
- protected static Color applyLuminanace(Color c, ColorStyle fc) {\r
+ protected static Color applyLuminance(Color c, ColorStyle fc) {\r
int lumMod = fc.getLumMod();\r
if (lumMod == -1) lumMod = 100000;\r
\r
\r
if (lumMod == 100000 && lumOff == 0) return c;\r
\r
- int r = c.getRed();\r
- int g = c.getGreen();\r
- int b = c.getBlue();\r
+ // The lumMod value is the percent luminance. A lumMod value of "60000",\r
+ // is 60% of the luminance of the original color.\r
+ // When the color is a shade of the original theme color, the lumMod\r
+ // attribute is the only one of the tags shown here that appears.\r
+ // The <a:lumOff> tag appears after the <a:lumMod> tag when the color is a\r
+ // tint of the original. The lumOff value always equals 1-lumMod, which is used in the tint calculation\r
+ //\r
+ // Despite having different ways to display the tint and shade percentages,\r
+ // all of the programs use the same method to calculate the resulting color.\r
+ // Convert the original RGB value to HSL ... and then adjust the luminance (L)\r
+ // with one of the following equations before converting the HSL value back to RGB.\r
+ // (The % tint in the following equations refers to the tint, themetint, themeshade,\r
+ // or lumMod values, as applicable.)\r
+ //\r
+ // For a shade, the equation is luminance * %tint.\r
+ //\r
+ // For a tint, the equation is luminance * %tint + (1-%tint).\r
+ // (Note that 1-%tint is equal to the lumOff value in DrawingML.)\r
\r
- float red,green,blue;\r
+ double fLumOff = lumOff / 100000d;\r
+ double fLumMod = lumMod / 100000d;\r
\r
- if (lumOff > 0) {\r
- float flumOff = lumOff / 100000.f;\r
- red = (255.f - r) * (1.f - flumOff) + r;\r
- green = (255.f - g) * flumOff + g;\r
- blue = (255.f - b) * flumOff + b;\r
- } else {\r
- float flumMod = lumMod / 100000.f;\r
- red = r * flumMod;\r
- green = g * flumMod;\r
- blue = b * flumMod;\r
- }\r
- return new Color(Math.round(red), Math.round(green), Math.round(blue), c.getAlpha());\r
+ double hsl[] = RGB2HSL(c);\r
+ hsl[2] = hsl[2]*fLumMod+fLumOff;\r
+\r
+ Color c2 = HSL2RGB(hsl[0], hsl[1], hsl[2], c.getAlpha()/255d);\r
+ return c2;\r
}\r
\r
/**\r
}\r
}\r
\r
- public static class PathGradientPaint implements Paint {\r
+ /**\r
+ * Convert HSL values to a RGB Color.\r
+ *\r
+ * @param h Hue is specified as degrees in the range 0 - 360.\r
+ * @param s Saturation is specified as a percentage in the range 1 - 100.\r
+ * @param l Luminance is specified as a percentage in the range 1 - 100.\r
+ * @param alpha the alpha value between 0 - 1\r
+ *\r
+ * @returns the RGB Color object\r
+ */\r
+ private static Color HSL2RGB(double h, double s, double l, double alpha) {\r
+ if (s <0.0f || s > 100.0f) {\r
+ String message = "Color parameter outside of expected range - Saturation";\r
+ throw new IllegalArgumentException( message );\r
+ }\r
\r
- // http://asserttrue.blogspot.de/2010/01/how-to-iimplement-custom-paint-in-50.html\r
- protected final Color colors[];\r
- protected final float fractions[];\r
- protected final int capStyle;\r
- protected final int joinStyle;\r
- protected final int transparency;\r
+ if (l <0.0f || l > 100.0f) {\r
+ String message = "Color parameter outside of expected range - Luminance";\r
+ throw new IllegalArgumentException( message );\r
+ }\r
\r
- \r
- public PathGradientPaint(Color colors[], float fractions[]) {\r
- this(colors,fractions,BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND);\r
+ if (alpha <0.0f || alpha > 1.0f) {\r
+ String message = "Color parameter outside of expected range - Alpha";\r
+ throw new IllegalArgumentException( message );\r
}\r
- \r
- public PathGradientPaint(Color colors[], float fractions[], int capStyle, int joinStyle) {\r
- this.colors = colors;\r
- this.fractions = fractions;\r
- this.capStyle = capStyle;\r
- this.joinStyle = joinStyle;\r
-\r
- // determine transparency\r
- boolean opaque = true;\r
- for (int i = 0; i < colors.length; i++){\r
- opaque = opaque && (colors[i].getAlpha() == 0xff);\r
- }\r
- this.transparency = opaque ? OPAQUE : TRANSLUCENT;\r
+\r
+ // Formula needs all values between 0 - 1.\r
+\r
+ h = h % 360.0f;\r
+ h /= 360f;\r
+ s /= 100f;\r
+ l /= 100f;\r
+\r
+ double q = (l < 0.5d)\r
+ ? l * (1d + s)\r
+ : (l + s) - (s * l);\r
+\r
+ double p = 2d * l - q;\r
+\r
+ double r = Math.max(0, HUE2RGB(p, q, h + (1.0d / 3.0d)));\r
+ double g = Math.max(0, HUE2RGB(p, q, h));\r
+ double b = Math.max(0, HUE2RGB(p, q, h - (1.0d / 3.0d)));\r
+\r
+ r = Math.min(r, 1.0d);\r
+ g = Math.min(g, 1.0d);\r
+ b = Math.min(b, 1.0d);\r
+\r
+ return new Color((float)r, (float)g, (float)b, (float)alpha);\r
+ }\r
+\r
+ private static double HUE2RGB(double p, double q, double h) {\r
+ if (h < 0d) h += 1d;\r
+\r
+ if (h > 1d) h -= 1d;\r
+\r
+ if (6d * h < 1d) {\r
+ return p + ((q - p) * 6d * h);\r
}\r
- \r
- public PaintContext createContext(ColorModel cm,\r
- Rectangle deviceBounds,\r
- Rectangle2D userBounds,\r
- AffineTransform transform,\r
- RenderingHints hints) {\r
- return new PathGradientContext(cm, deviceBounds, userBounds, transform, hints);\r
+\r
+ if (2d * h < 1d) {\r
+ return q;\r
}\r
- \r
- public int getTransparency() {\r
- return transparency;\r
+\r
+ if (3d * h < 2d) {\r
+ return p + ( (q - p) * 6d * ((2.0d / 3.0d) - h) );\r
}\r
\r
- class PathGradientContext implements PaintContext {\r
- protected final Rectangle deviceBounds;\r
- protected final Rectangle2D userBounds;\r
- protected final AffineTransform xform;\r
- protected final RenderingHints hints;\r
-\r
- /**\r
- * for POI: the shape will be only known when the subclasses determines the concrete implementation \r
- * in the draw/-content method, so we need to postpone the setting/creation as long as possible\r
- **/\r
- protected final Shape shape;\r
- protected final PaintContext pCtx;\r
- protected final int gradientSteps;\r
- WritableRaster raster;\r
-\r
- public PathGradientContext(\r
- ColorModel cm\r
- , Rectangle deviceBounds\r
- , Rectangle2D userBounds\r
- , AffineTransform xform\r
- , RenderingHints hints\r
- ) {\r
- shape = (Shape)hints.get(Drawable.GRADIENT_SHAPE);\r
- if (shape == null) {\r
- throw new IllegalPathStateException("PathGradientPaint needs a shape to be set via the rendering hint PathGradientPaint.GRADIANT_SHAPE.");\r
- }\r
-\r
- this.deviceBounds = deviceBounds;\r
- this.userBounds = userBounds;\r
- this.xform = xform;\r
- this.hints = hints;\r
-\r
- gradientSteps = getGradientSteps(shape);\r
-\r
- Point2D start = new Point2D.Double(0, 0);\r
- Point2D end = new Point2D.Double(gradientSteps, 0);\r
- LinearGradientPaint gradientPaint = new LinearGradientPaint(start, end, fractions, colors, CycleMethod.NO_CYCLE, ColorSpaceType.SRGB, new AffineTransform());\r
- \r
- Rectangle bounds = new Rectangle(0, 0, gradientSteps, 1);\r
- pCtx = gradientPaint.createContext(cm, bounds, bounds, new AffineTransform(), hints);\r
- }\r
+ return p;\r
+ }\r
\r
- public void dispose() {}\r
\r
- public ColorModel getColorModel() {\r
- return pCtx.getColorModel();\r
- }\r
+ /**\r
+ * Convert a RGB Color to it corresponding HSL values.\r
+ *\r
+ * @return an array containing the 3 HSL values.\r
+ */\r
+ private static double[] RGB2HSL(Color color)\r
+ {\r
+ // Get RGB values in the range 0 - 1\r
\r
- public Raster getRaster(int xOffset, int yOffset, int w, int h) {\r
- ColorModel cm = getColorModel();\r
- if (raster == null) createRaster();\r
-\r
- // TODO: eventually use caching here\r
- WritableRaster childRaster = cm.createCompatibleWritableRaster(w, h);\r
- Rectangle2D childRect = new Rectangle2D.Double(xOffset, yOffset, w, h);\r
- if (!childRect.intersects(deviceBounds)) {\r
- // usually doesn't happen ...\r
- return childRaster;\r
- }\r
- \r
- Rectangle2D destRect = new Rectangle2D.Double();\r
- Rectangle2D.intersect(childRect, deviceBounds, destRect);\r
- int dx = (int)(destRect.getX()-deviceBounds.getX());\r
- int dy = (int)(destRect.getY()-deviceBounds.getY());\r
- int dw = (int)destRect.getWidth();\r
- int dh = (int)destRect.getHeight();\r
- Object data = raster.getDataElements(dx, dy, dw, dh, null);\r
- dx = (int)(destRect.getX()-childRect.getX());\r
- dy = (int)(destRect.getY()-childRect.getY());\r
- childRaster.setDataElements(dx, dy, dw, dh, data);\r
- \r
- return childRaster;\r
- }\r
+ float[] rgb = color.getRGBColorComponents( null );\r
+ double r = rgb[0];\r
+ double g = rgb[1];\r
+ double b = rgb[2];\r
\r
- protected int getGradientSteps(Shape shape) {\r
- Rectangle rect = shape.getBounds();\r
- int lower = 1;\r
- int upper = (int)(Math.max(rect.getWidth(),rect.getHeight())/2.0);\r
- while (lower < upper-1) {\r
- int mid = lower + (upper - lower) / 2;\r
- BasicStroke bs = new BasicStroke(mid, capStyle, joinStyle);\r
- Area area = new Area(bs.createStrokedShape(shape));\r
- if (area.isSingular()) {\r
- upper = mid;\r
- } else {\r
- lower = mid;\r
- }\r
- }\r
- return upper;\r
- }\r
- \r
- \r
- \r
- protected void createRaster() {\r
- ColorModel cm = getColorModel();\r
- raster = cm.createCompatibleWritableRaster((int)deviceBounds.getWidth(), (int)deviceBounds.getHeight());\r
- BufferedImage img = new BufferedImage(cm, raster, false, null);\r
- Graphics2D graphics = img.createGraphics();\r
- graphics.setRenderingHints(hints);\r
- graphics.translate(-deviceBounds.getX(), -deviceBounds.getY());\r
- graphics.transform(xform);\r
-\r
- Raster img2 = pCtx.getRaster(0, 0, gradientSteps, 1);\r
- int rgb[] = new int[cm.getNumComponents()];\r
-\r
- for (int i = gradientSteps-1; i>=0; i--) {\r
- img2.getPixel(i, 0, rgb);\r
- Color c = new Color(rgb[0],rgb[1],rgb[2]);\r
- if (rgb.length == 4) {\r
- // it doesn't work to use just a color with transparency ...\r
- graphics.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC, rgb[3]/255.0f)); \r
- }\r
- graphics.setStroke(new BasicStroke(i+1, capStyle, joinStyle));\r
- graphics.setColor(c);\r
- graphics.draw(shape);\r
- }\r
- \r
- graphics.dispose();\r
- }\r
+ // Minimum and Maximum RGB values are used in the HSL calculations\r
+\r
+ double min = Math.min(r, Math.min(g, b));\r
+ double max = Math.max(r, Math.max(g, b));\r
+\r
+ // Calculate the Hue\r
+\r
+ double h = 0;\r
+\r
+ if (max == min) {\r
+ h = 0;\r
+ } else if (max == r) {\r
+ h = ((60d * (g - b) / (max - min)) + 360d) % 360d;\r
+ } else if (max == g) {\r
+ h = (60d * (b - r) / (max - min)) + 120d;\r
+ } else if (max == b) {\r
+ h = (60d * (r - g) / (max - min)) + 240d;\r
+ }\r
+\r
+ // Calculate the Luminance\r
+\r
+ double l = (max + min) / 2d;\r
+\r
+ // Calculate the Saturation\r
+\r
+ double s = 0;\r
+\r
+ if (max == min) {\r
+ s = 0;\r
+ } else if (l <= .5d) {\r
+ s = (max - min) / (max + min);\r
+ } else {\r
+ s = (max - min) / (2d - max - min);\r
}\r
+\r
+ return new double[] {h, s * 100, l * 100};\r
}\r
-}\r
+\r
+}
\ No newline at end of file
public class DrawTextParagraph<T extends TextRun> implements Drawable {\r
protected TextParagraph<T> paragraph;\r
double x, y;\r
- protected Insets2D insets = new Insets2D(0,0,0,0);\r
protected List<DrawTextFragment> lines = new ArrayList<DrawTextFragment>();\r
protected String rawText;\r
protected DrawTextFragment bullet;\r
this.paragraph = paragraph;\r
}\r
\r
- public Insets2D getInsets() {\r
- return insets;\r
- }\r
-\r
- public void setInsets(Insets2D insets) {\r
- this.insets.set(insets.top, insets.left, insets.bottom, insets.right);\r
- }\r
-\r
public void setPosition(double x, double y) {\r
// TODO: replace it, by applyTransform????\r
this.x = x;\r
public void draw(Graphics2D graphics){\r
if (lines.isEmpty()) return;\r
\r
+ Insets2D insets = paragraph.getParentShape().getInsets();\r
double leftInset = insets.left;\r
double rightInset = insets.right;\r
double penY = y;\r
protected double getWrappingWidth(boolean firstLine, Graphics2D graphics){\r
// internal margins for the text box\r
\r
+ Insets2D insets = paragraph.getParentShape().getInsets();\r
double leftInset = insets.left;\r
double rightInset = insets.right;\r
\r
if (startAt > autoNbrIdx) autoNbrIdx = startAt;\r
}\r
dp.setAutoNumberingIdx(autoNbrIdx);\r
- dp.setInsets(shapePadding);\r
dp.breakText(graphics);\r
\r
if (!isFirstLine) {\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
+import java.awt.*;\r
+import java.awt.MultipleGradientPaint.ColorSpaceType;\r
+import java.awt.MultipleGradientPaint.CycleMethod;\r
+import java.awt.geom.*;\r
+import java.awt.image.*;\r
+\r
+class PathGradientPaint implements Paint {\r
+\r
+ // http://asserttrue.blogspot.de/2010/01/how-to-iimplement-custom-paint-in-50.html\r
+ protected final Color colors[];\r
+ protected final float fractions[];\r
+ protected final int capStyle;\r
+ protected final int joinStyle;\r
+ protected final int transparency;\r
+\r
+ \r
+ public PathGradientPaint(Color colors[], float fractions[]) {\r
+ this(colors,fractions,BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND);\r
+ }\r
+ \r
+ public PathGradientPaint(Color colors[], float fractions[], int capStyle, int joinStyle) {\r
+ this.colors = colors;\r
+ this.fractions = fractions;\r
+ this.capStyle = capStyle;\r
+ this.joinStyle = joinStyle;\r
+\r
+ // determine transparency\r
+ boolean opaque = true;\r
+ for (int i = 0; i < colors.length; i++){\r
+ opaque = opaque && (colors[i].getAlpha() == 0xff);\r
+ }\r
+ this.transparency = opaque ? OPAQUE : TRANSLUCENT;\r
+ }\r
+ \r
+ public PaintContext createContext(ColorModel cm,\r
+ Rectangle deviceBounds,\r
+ Rectangle2D userBounds,\r
+ AffineTransform transform,\r
+ RenderingHints hints) {\r
+ return new PathGradientContext(cm, deviceBounds, userBounds, transform, hints);\r
+ }\r
+ \r
+ public int getTransparency() {\r
+ return transparency;\r
+ }\r
+\r
+ class PathGradientContext implements PaintContext {\r
+ protected final Rectangle deviceBounds;\r
+ protected final Rectangle2D userBounds;\r
+ protected final AffineTransform xform;\r
+ protected final RenderingHints hints;\r
+\r
+ /**\r
+ * for POI: the shape will be only known when the subclasses determines the concrete implementation \r
+ * in the draw/-content method, so we need to postpone the setting/creation as long as possible\r
+ **/\r
+ protected final Shape shape;\r
+ protected final PaintContext pCtx;\r
+ protected final int gradientSteps;\r
+ WritableRaster raster;\r
+\r
+ public PathGradientContext(\r
+ ColorModel cm\r
+ , Rectangle deviceBounds\r
+ , Rectangle2D userBounds\r
+ , AffineTransform xform\r
+ , RenderingHints hints\r
+ ) {\r
+ shape = (Shape)hints.get(Drawable.GRADIENT_SHAPE);\r
+ if (shape == null) {\r
+ throw new IllegalPathStateException("PathGradientPaint needs a shape to be set via the rendering hint PathGradientPaint.GRADIANT_SHAPE.");\r
+ }\r
+\r
+ this.deviceBounds = deviceBounds;\r
+ this.userBounds = userBounds;\r
+ this.xform = xform;\r
+ this.hints = hints;\r
+\r
+ gradientSteps = getGradientSteps(shape);\r
+\r
+ Point2D start = new Point2D.Double(0, 0);\r
+ Point2D end = new Point2D.Double(gradientSteps, 0);\r
+ LinearGradientPaint gradientPaint = new LinearGradientPaint(start, end, fractions, colors, CycleMethod.NO_CYCLE, ColorSpaceType.SRGB, new AffineTransform());\r
+ \r
+ Rectangle bounds = new Rectangle(0, 0, gradientSteps, 1);\r
+ pCtx = gradientPaint.createContext(cm, bounds, bounds, new AffineTransform(), hints);\r
+ }\r
+\r
+ public void dispose() {}\r
+\r
+ public ColorModel getColorModel() {\r
+ return pCtx.getColorModel();\r
+ }\r
+\r
+ public Raster getRaster(int xOffset, int yOffset, int w, int h) {\r
+ ColorModel cm = getColorModel();\r
+ if (raster == null) createRaster();\r
+\r
+ // TODO: eventually use caching here\r
+ WritableRaster childRaster = cm.createCompatibleWritableRaster(w, h);\r
+ Rectangle2D childRect = new Rectangle2D.Double(xOffset, yOffset, w, h);\r
+ if (!childRect.intersects(deviceBounds)) {\r
+ // usually doesn't happen ...\r
+ return childRaster;\r
+ }\r
+ \r
+ Rectangle2D destRect = new Rectangle2D.Double();\r
+ Rectangle2D.intersect(childRect, deviceBounds, destRect);\r
+ int dx = (int)(destRect.getX()-deviceBounds.getX());\r
+ int dy = (int)(destRect.getY()-deviceBounds.getY());\r
+ int dw = (int)destRect.getWidth();\r
+ int dh = (int)destRect.getHeight();\r
+ Object data = raster.getDataElements(dx, dy, dw, dh, null);\r
+ dx = (int)(destRect.getX()-childRect.getX());\r
+ dy = (int)(destRect.getY()-childRect.getY());\r
+ childRaster.setDataElements(dx, dy, dw, dh, data);\r
+ \r
+ return childRaster;\r
+ }\r
+\r
+ protected int getGradientSteps(Shape shape) {\r
+ Rectangle rect = shape.getBounds();\r
+ int lower = 1;\r
+ int upper = (int)(Math.max(rect.getWidth(),rect.getHeight())/2.0);\r
+ while (lower < upper-1) {\r
+ int mid = lower + (upper - lower) / 2;\r
+ BasicStroke bs = new BasicStroke(mid, capStyle, joinStyle);\r
+ Area area = new Area(bs.createStrokedShape(shape));\r
+ if (area.isSingular()) {\r
+ upper = mid;\r
+ } else {\r
+ lower = mid;\r
+ }\r
+ }\r
+ return upper;\r
+ }\r
+ \r
+ \r
+ \r
+ protected void createRaster() {\r
+ ColorModel cm = getColorModel();\r
+ raster = cm.createCompatibleWritableRaster((int)deviceBounds.getWidth(), (int)deviceBounds.getHeight());\r
+ BufferedImage img = new BufferedImage(cm, raster, false, null);\r
+ Graphics2D graphics = img.createGraphics();\r
+ graphics.setRenderingHints(hints);\r
+ graphics.translate(-deviceBounds.getX(), -deviceBounds.getY());\r
+ graphics.transform(xform);\r
+\r
+ Raster img2 = pCtx.getRaster(0, 0, gradientSteps, 1);\r
+ int rgb[] = new int[cm.getNumComponents()];\r
+\r
+ for (int i = gradientSteps-1; i>=0; i--) {\r
+ img2.getPixel(i, 0, rgb);\r
+ Color c = new Color(rgb[0],rgb[1],rgb[2]);\r
+ if (rgb.length == 4) {\r
+ // it doesn't work to use just a color with transparency ...\r
+ graphics.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC, rgb[3]/255.0f)); \r
+ }\r
+ graphics.setStroke(new BasicStroke(i+1, capStyle, joinStyle));\r
+ graphics.setColor(c);\r
+ graphics.draw(shape);\r
+ }\r
+ \r
+ graphics.dispose();\r
+ }\r
+ }\r
+}\r
TextCap getTextCap();
Color getFontColor();
+ void setFontColor(Color color);
+
+
+ /**
+ * @return font size in points or null if font size is not set.
+ */
Double getFontSize();
+
+ /**
+ * @param fontSize font size in points, if null the underlying fontsize will be unset
+ */
+ void setFontSize(Double fontSize);
String getFontFamily();
boolean isBold();
HSLFTextBox txtbox = new HSLFTextBox();
rt = txtbox.getTextParagraphs().get(0).getTextRuns().get(0);
txtbox.setText(val);
- rt.setFontSize(42);
+ rt.setFontSize(42d);
rt.setBold(true);
rt.setItalic(true);
rt.setUnderlined(false);
rt = txtbox.getTextParagraphs().get(0).getTextRuns().get(0);
txtbox.setText(val);
rt.setFontFamily("Arial");
- rt.setFontSize(42);
+ rt.setFontSize(42d);
rt.setBold(true);
rt.setItalic(true);
rt.setUnderlined(false);
// Change 2nd to different size and font
assertEquals(2, ssRichB.getFontCollection().getChildRecords().length); // Default + TNR
- rtrRb.setFontSize(18);
+ rtrRb.setFontSize(18d);
rtrRb.setFontFamily("Courier");
assertEquals(3, ssRichB.getFontCollection().getChildRecords().length); // Default + TNR + Courier
assertEquals(18, rtrRb.getFontSize(), 0);
assertNotNull(rtr.getTextParagraph().getParagraphStyle());
// Change Font size
- rtr.setFontSize(99);
+ rtr.setFontSize(99d);
assertEquals(99, rtr.getFontSize(), 0);
assertEquals(defaultFont, rtr.getFontFamily());
assertNotNull(rtr.getCharacterStyle());
assertEquals(1, ss.getFontCollection().getChildRecords().length); // Default
// Change Font size and name
- rtr.setFontSize(25);
+ rtr.setFontSize(25d);
rtr.setFontFamily("Times New Roman");
assertEquals(25, rtr.getFontSize(), 0);
assertEquals("Times New Roman", rtr.getFontFamily());
HSLFTextRun rtr = textParass.get(0).get(0).getTextRuns().get(0);
rtr.setBold(true);
- rtr.setFontSize(18);
+ rtr.setFontSize(18d);
rtr.setFontFamily("Courier");
HSLFTextParagraph.storeText(textParass.get(0));
// Tweak existing one again, to ensure really worked
rtr.setBold(false);
- rtr.setFontSize(17);
+ rtr.setFontSize(17d);
rtr.setFontFamily("CourierZZ");
// Check it took those changes
"Multiline text");
HSLFTextParagraph rt = shape.getTextParagraphs().get(0);
HSLFTextRun tr = rt.getTextRuns().get(0);
- tr.setFontSize(42);
+ tr.setFontSize(42d);
rt.setBullet(true);
rt.setLeftMargin(50d);
rt.setIndent(0d);