- add resize methods with Graphics argument git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1801329 13f79535-47bb-0310-9956-ffa450edef68tags/REL_3_17_FINAL
* @param oldGraphics the graphics context, which properties are to be copied, may be null | * @param oldGraphics the graphics context, which properties are to be copied, may be null | ||||
* @return the height in points | * @return the height in points | ||||
*/ | */ | ||||
protected double getTextHeight(Graphics2D oldGraphics) { | |||||
public double getTextHeight(Graphics2D oldGraphics) { | |||||
// dry-run in a 1x1 image and return the vertical advance | // dry-run in a 1x1 image and return the vertical advance | ||||
BufferedImage img = new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB); | BufferedImage img = new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB); | ||||
Graphics2D graphics = img.createGraphics(); | Graphics2D graphics = img.createGraphics(); |
package org.apache.poi.sl.usermodel; | package org.apache.poi.sl.usermodel; | ||||
import java.awt.Graphics2D; | |||||
import java.awt.geom.Rectangle2D; | |||||
import java.util.List; | import java.util.List; | ||||
public interface TextShape< | public interface TextShape< | ||||
/** | /** | ||||
* Compute the cumulative height occupied by the text | * Compute the cumulative height occupied by the text | ||||
* | |||||
* @return the cumulative height occupied by the text | |||||
*/ | */ | ||||
double getTextHeight(); | double getTextHeight(); | ||||
/** | |||||
* Compute the cumulative height occupied by the text | |||||
* | |||||
* @param graphics a customized graphics context, e.g. which contains font mappings | |||||
* | |||||
* @return the cumulative height occupied by the text | |||||
* | |||||
* @since POI 3.17-beta2 | |||||
*/ | |||||
double getTextHeight(Graphics2D graphics); | |||||
/** | /** | ||||
* Returns the type of vertical alignment for the text. | * Returns the type of vertical alignment for the text. | ||||
* @return the text placeholder | * @return the text placeholder | ||||
*/ | */ | ||||
TextPlaceholder getTextPlaceholder(); | TextPlaceholder getTextPlaceholder(); | ||||
/** | |||||
* Adjust the size of the shape so it encompasses the text inside it. | |||||
* | |||||
* @return a {@code Rectangle2D} that is the bounds of this shape. | |||||
* | |||||
* @since POI 3.17-beta2 | |||||
*/ | |||||
Rectangle2D resizeToFitText(); | |||||
/** | |||||
* Adjust the size of the shape so it encompasses the text inside it. | |||||
* | |||||
* @param graphics a customized graphics context, e.g. which contains font mappings | |||||
* | |||||
* @return a {@code Rectangle2D} that is the bounds of this shape. | |||||
* | |||||
* @since POI 3.17-beta2 | |||||
*/ | |||||
Rectangle2D resizeToFitText(Graphics2D graphics); | |||||
} | } |
return _p; | return _p; | ||||
} | } | ||||
@Override | |||||
public String getRawText(){ | public String getRawText(){ | ||||
if (_r instanceof CTTextField) { | if (_r instanceof CTTextField) { | ||||
return ((CTTextField)_r).getT(); | return ((CTTextField)_r).getT(); | ||||
return buf.toString(); | return buf.toString(); | ||||
} | } | ||||
@Override | |||||
public void setText(String text){ | public void setText(String text){ | ||||
if (_r instanceof CTTextField) { | if (_r instanceof CTTextField) { | ||||
((CTTextField)_r).setT(text); | ((CTTextField)_r).setT(text); | ||||
public PaintStyle getFontColor(){ | public PaintStyle getFontColor(){ | ||||
final boolean hasPlaceholder = getParentParagraph().getParentShape().getPlaceholder() != null; | final boolean hasPlaceholder = getParentParagraph().getParentShape().getPlaceholder() != null; | ||||
CharacterPropertyFetcher<PaintStyle> fetcher = new CharacterPropertyFetcher<PaintStyle>(_p.getIndentLevel()){ | CharacterPropertyFetcher<PaintStyle> fetcher = new CharacterPropertyFetcher<PaintStyle>(_p.getIndentLevel()){ | ||||
@Override | |||||
public boolean fetch(CTTextCharacterProperties props){ | public boolean fetch(CTTextCharacterProperties props){ | ||||
if (props == null) { | if (props == null) { | ||||
return false; | return false; | ||||
public void setFontSize(Double fontSize){ | public void setFontSize(Double fontSize){ | ||||
CTTextCharacterProperties rPr = getRPr(true); | CTTextCharacterProperties rPr = getRPr(true); | ||||
if(fontSize == null) { | if(fontSize == null) { | ||||
if (rPr.isSetSz()) rPr.unsetSz(); | |||||
if (rPr.isSetSz()) { | |||||
rPr.unsetSz(); | |||||
} | |||||
} else { | } else { | ||||
if (fontSize < 1.0) { | if (fontSize < 1.0) { | ||||
throw new IllegalArgumentException("Minimum font size is 1pt but was " + fontSize); | throw new IllegalArgumentException("Minimum font size is 1pt but was " + fontSize); | ||||
public Double getFontSize(){ | public Double getFontSize(){ | ||||
double scale = 1; | double scale = 1; | ||||
CTTextNormalAutofit afit = getParentParagraph().getParentShape().getTextBodyPr().getNormAutofit(); | CTTextNormalAutofit afit = getParentParagraph().getParentShape().getTextBodyPr().getNormAutofit(); | ||||
if(afit != null) scale = (double)afit.getFontScale() / 100000; | |||||
if(afit != null) { | |||||
scale = (double)afit.getFontScale() / 100000; | |||||
} | |||||
CharacterPropertyFetcher<Double> fetcher = new CharacterPropertyFetcher<Double>(_p.getIndentLevel()){ | CharacterPropertyFetcher<Double> fetcher = new CharacterPropertyFetcher<Double>(_p.getIndentLevel()){ | ||||
@Override | |||||
public boolean fetch(CTTextCharacterProperties props){ | public boolean fetch(CTTextCharacterProperties props){ | ||||
if (props != null && props.isSetSz()) { | if (props != null && props.isSetSz()) { | ||||
setValue(props.getSz()*0.01); | setValue(props.getSz()*0.01); | ||||
public double getCharacterSpacing(){ | public double getCharacterSpacing(){ | ||||
CharacterPropertyFetcher<Double> fetcher = new CharacterPropertyFetcher<Double>(_p.getIndentLevel()){ | CharacterPropertyFetcher<Double> fetcher = new CharacterPropertyFetcher<Double>(_p.getIndentLevel()){ | ||||
@Override | |||||
public boolean fetch(CTTextCharacterProperties props){ | public boolean fetch(CTTextCharacterProperties props){ | ||||
if (props != null && props.isSetSpc()) { | if (props != null && props.isSetSpc()) { | ||||
setValue(props.getSpc()*0.01); | setValue(props.getSpc()*0.01); | ||||
public void setCharacterSpacing(double spc){ | public void setCharacterSpacing(double spc){ | ||||
CTTextCharacterProperties rPr = getRPr(true); | CTTextCharacterProperties rPr = getRPr(true); | ||||
if(spc == 0.0) { | if(spc == 0.0) { | ||||
if(rPr.isSetSpc()) rPr.unsetSpc(); | |||||
if(rPr.isSetSpc()) { | |||||
rPr.unsetSpc(); | |||||
} | |||||
} else { | } else { | ||||
rPr.setSpc((int)(100*spc)); | rPr.setSpc((int)(100*spc)); | ||||
} | } | ||||
CTTextCharacterProperties rPr = getRPr(true); | CTTextCharacterProperties rPr = getRPr(true); | ||||
if(typeface == null){ | if(typeface == null){ | ||||
if(rPr.isSetLatin()) rPr.unsetLatin(); | |||||
if(rPr.isSetCs()) rPr.unsetCs(); | |||||
if(rPr.isSetSym()) rPr.unsetSym(); | |||||
if(rPr.isSetLatin()) { | |||||
rPr.unsetLatin(); | |||||
} | |||||
if(rPr.isSetCs()) { | |||||
rPr.unsetCs(); | |||||
} | |||||
if(rPr.isSetSym()) { | |||||
rPr.unsetSym(); | |||||
} | |||||
} else { | } else { | ||||
if(isSymbol){ | if(isSymbol){ | ||||
CTTextFont font = rPr.isSetSym() ? rPr.getSym() : rPr.addNewSym(); | CTTextFont font = rPr.isSetSym() ? rPr.getSym() : rPr.addNewSym(); | ||||
} else { | } else { | ||||
CTTextFont latin = rPr.isSetLatin() ? rPr.getLatin() : rPr.addNewLatin(); | CTTextFont latin = rPr.isSetLatin() ? rPr.getLatin() : rPr.addNewLatin(); | ||||
latin.setTypeface(typeface); | latin.setTypeface(typeface); | ||||
if(charset != -1) latin.setCharset(charset); | |||||
if(pictAndFamily != -1) latin.setPitchFamily(pictAndFamily); | |||||
if(charset != -1) { | |||||
latin.setCharset(charset); | |||||
} | |||||
if(pictAndFamily != -1) { | |||||
latin.setPitchFamily(pictAndFamily); | |||||
} | |||||
} | } | ||||
} | } | ||||
} | } | ||||
final XSLFTheme theme = _p.getParentShape().getSheet().getTheme(); | final XSLFTheme theme = _p.getParentShape().getSheet().getTheme(); | ||||
CharacterPropertyFetcher<String> visitor = new CharacterPropertyFetcher<String>(_p.getIndentLevel()){ | CharacterPropertyFetcher<String> visitor = new CharacterPropertyFetcher<String>(_p.getIndentLevel()){ | ||||
@Override | |||||
public boolean fetch(CTTextCharacterProperties props){ | public boolean fetch(CTTextCharacterProperties props){ | ||||
if (props != null) { | if (props != null) { | ||||
CTTextFont font = props.getLatin(); | CTTextFont font = props.getLatin(); | ||||
return visitor.getValue(); | return visitor.getValue(); | ||||
} | } | ||||
@Override | |||||
public byte getPitchAndFamily(){ | public byte getPitchAndFamily(){ | ||||
// final XSLFTheme theme = _p.getParentShape().getSheet().getTheme(); | // final XSLFTheme theme = _p.getParentShape().getSheet().getTheme(); | ||||
CharacterPropertyFetcher<Byte> visitor = new CharacterPropertyFetcher<Byte>(_p.getIndentLevel()){ | CharacterPropertyFetcher<Byte> visitor = new CharacterPropertyFetcher<Byte>(_p.getIndentLevel()){ | ||||
@Override | |||||
public boolean fetch(CTTextCharacterProperties props){ | public boolean fetch(CTTextCharacterProperties props){ | ||||
if (props != null) { | if (props != null) { | ||||
CTTextFont font = props.getLatin(); | CTTextFont font = props.getLatin(); | ||||
@Override | @Override | ||||
public boolean isStrikethrough() { | public boolean isStrikethrough() { | ||||
CharacterPropertyFetcher<Boolean> fetcher = new CharacterPropertyFetcher<Boolean>(_p.getIndentLevel()){ | CharacterPropertyFetcher<Boolean> fetcher = new CharacterPropertyFetcher<Boolean>(_p.getIndentLevel()){ | ||||
@Override | |||||
public boolean fetch(CTTextCharacterProperties props){ | public boolean fetch(CTTextCharacterProperties props){ | ||||
if(props != null && props.isSetStrike()) { | if(props != null && props.isSetStrike()) { | ||||
setValue(props.getStrike() != STTextStrikeType.NO_STRIKE); | setValue(props.getStrike() != STTextStrikeType.NO_STRIKE); | ||||
@Override | @Override | ||||
public boolean isSuperscript() { | public boolean isSuperscript() { | ||||
CharacterPropertyFetcher<Boolean> fetcher = new CharacterPropertyFetcher<Boolean>(_p.getIndentLevel()){ | CharacterPropertyFetcher<Boolean> fetcher = new CharacterPropertyFetcher<Boolean>(_p.getIndentLevel()){ | ||||
@Override | |||||
public boolean fetch(CTTextCharacterProperties props){ | public boolean fetch(CTTextCharacterProperties props){ | ||||
if (props != null && props.isSetBaseline()) { | if (props != null && props.isSetBaseline()) { | ||||
setValue(props.getBaseline() > 0); | setValue(props.getBaseline() > 0); | ||||
@Override | @Override | ||||
public boolean isSubscript() { | public boolean isSubscript() { | ||||
CharacterPropertyFetcher<Boolean> fetcher = new CharacterPropertyFetcher<Boolean>(_p.getIndentLevel()){ | CharacterPropertyFetcher<Boolean> fetcher = new CharacterPropertyFetcher<Boolean>(_p.getIndentLevel()){ | ||||
@Override | |||||
public boolean fetch(CTTextCharacterProperties props){ | public boolean fetch(CTTextCharacterProperties props){ | ||||
if (props != null && props.isSetBaseline()) { | if (props != null && props.isSetBaseline()) { | ||||
setValue(props.getBaseline() < 0); | setValue(props.getBaseline() < 0); | ||||
/** | /** | ||||
* @return whether a run of text will be formatted as a superscript text. Default is false. | * @return whether a run of text will be formatted as a superscript text. Default is false. | ||||
*/ | */ | ||||
@Override | |||||
public TextCap getTextCap() { | public TextCap getTextCap() { | ||||
CharacterPropertyFetcher<TextCap> fetcher = new CharacterPropertyFetcher<TextCap>(_p.getIndentLevel()){ | CharacterPropertyFetcher<TextCap> fetcher = new CharacterPropertyFetcher<TextCap>(_p.getIndentLevel()){ | ||||
@Override | |||||
public boolean fetch(CTTextCharacterProperties props){ | public boolean fetch(CTTextCharacterProperties props){ | ||||
if (props != null && props.isSetCap()) { | if (props != null && props.isSetCap()) { | ||||
int idx = props.getCap().intValue() - 1; | int idx = props.getCap().intValue() - 1; | ||||
@Override | @Override | ||||
public boolean isBold(){ | public boolean isBold(){ | ||||
CharacterPropertyFetcher<Boolean> fetcher = new CharacterPropertyFetcher<Boolean>(_p.getIndentLevel()){ | CharacterPropertyFetcher<Boolean> fetcher = new CharacterPropertyFetcher<Boolean>(_p.getIndentLevel()){ | ||||
@Override | |||||
public boolean fetch(CTTextCharacterProperties props){ | public boolean fetch(CTTextCharacterProperties props){ | ||||
if (props != null && props.isSetB()) { | if (props != null && props.isSetB()) { | ||||
setValue(props.getB()); | setValue(props.getB()); | ||||
@Override | @Override | ||||
public boolean isItalic(){ | public boolean isItalic(){ | ||||
CharacterPropertyFetcher<Boolean> fetcher = new CharacterPropertyFetcher<Boolean>(_p.getIndentLevel()){ | CharacterPropertyFetcher<Boolean> fetcher = new CharacterPropertyFetcher<Boolean>(_p.getIndentLevel()){ | ||||
@Override | |||||
public boolean fetch(CTTextCharacterProperties props){ | public boolean fetch(CTTextCharacterProperties props){ | ||||
if (props != null && props.isSetI()) { | if (props != null && props.isSetI()) { | ||||
setValue(props.getI()); | setValue(props.getI()); | ||||
@Override | @Override | ||||
public boolean isUnderlined(){ | public boolean isUnderlined(){ | ||||
CharacterPropertyFetcher<Boolean> fetcher = new CharacterPropertyFetcher<Boolean>(_p.getIndentLevel()){ | CharacterPropertyFetcher<Boolean> fetcher = new CharacterPropertyFetcher<Boolean>(_p.getIndentLevel()){ | ||||
@Override | |||||
public boolean fetch(CTTextCharacterProperties props){ | public boolean fetch(CTTextCharacterProperties props){ | ||||
if (props != null && props.isSetU()) { | if (props != null && props.isSetU()) { | ||||
setValue(props.getU() != STTextUnderlineType.NONE); | setValue(props.getU() != STTextUnderlineType.NONE); | ||||
} | } | ||||
boolean bold = r.isBold(); | boolean bold = r.isBold(); | ||||
if(bold != isBold()) setBold(bold); | |||||
if(bold != isBold()) { | |||||
setBold(bold); | |||||
} | |||||
boolean italic = r.isItalic(); | boolean italic = r.isItalic(); | ||||
if(italic != isItalic()) setItalic(italic); | |||||
if(italic != isItalic()) { | |||||
setItalic(italic); | |||||
} | |||||
boolean underline = r.isUnderlined(); | boolean underline = r.isUnderlined(); | ||||
if(underline != isUnderlined()) setUnderlined(underline); | |||||
if(underline != isUnderlined()) { | |||||
setUnderlined(underline); | |||||
} | |||||
boolean strike = r.isStrikethrough(); | boolean strike = r.isStrikethrough(); | ||||
if(strike != isStrikethrough()) setStrikethrough(strike); | |||||
if(strike != isStrikethrough()) { | |||||
setStrikethrough(strike); | |||||
} | |||||
} | } | ||||
package org.apache.poi.xslf.usermodel; | package org.apache.poi.xslf.usermodel; | ||||
import java.awt.Graphics2D; | |||||
import java.awt.geom.Rectangle2D; | import java.awt.geom.Rectangle2D; | ||||
import java.util.ArrayList; | import java.util.ArrayList; | ||||
import java.util.Iterator; | import java.util.Iterator; | ||||
@Override | @Override | ||||
public double getTextHeight(){ | public double getTextHeight(){ | ||||
DrawFactory drawFact = DrawFactory.getInstance(null); | |||||
return getTextHeight(null); | |||||
} | |||||
@Override | |||||
public double getTextHeight(Graphics2D graphics){ | |||||
DrawFactory drawFact = DrawFactory.getInstance(graphics); | |||||
DrawTextShape dts = drawFact.getDrawable(this); | DrawTextShape dts = drawFact.getDrawable(this); | ||||
return dts.getTextHeight(); | |||||
return dts.getTextHeight(graphics); | |||||
} | } | ||||
/** | |||||
* Adjust the size of the shape so it encompasses the text inside it. | |||||
* | |||||
* @return a <code>Rectangle2D</code> that is the bounds of this shape. | |||||
*/ | |||||
@Override | |||||
public Rectangle2D resizeToFitText(){ | public Rectangle2D resizeToFitText(){ | ||||
return resizeToFitText(null); | |||||
} | |||||
@Override | |||||
public Rectangle2D resizeToFitText(Graphics2D graphics) { | |||||
Rectangle2D anchor = getAnchor(); | Rectangle2D anchor = getAnchor(); | ||||
if(anchor.getWidth() == 0.) { | if(anchor.getWidth() == 0.) { | ||||
throw new POIXMLException("Anchor of the shape was not set."); | throw new POIXMLException("Anchor of the shape was not set."); | ||||
} | } | ||||
double height = getTextHeight(); | |||||
double height = getTextHeight(graphics); | |||||
height += 1; // add a pixel to compensate rounding errors | height += 1; // add a pixel to compensate rounding errors | ||||
Insets2D insets = getInsets(); | Insets2D insets = getInsets(); |
/* | |||||
* ==================================================================== | |||||
* 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.sl; | |||||
import java.io.IOException; | |||||
import java.io.InputStream; | |||||
import org.apache.poi.POIDataSamples; | |||||
import org.apache.poi.sl.usermodel.SlideShow; | |||||
import org.apache.poi.sl.usermodel.SlideShowFactory; | |||||
public class SLCommonUtils { | |||||
private static POIDataSamples _slTests = POIDataSamples.getSlideShowInstance(); | |||||
/** a generic way to open a sample slideshow document **/ | |||||
public static SlideShow<?,?> openSampleSlideshow(String sampleName) throws IOException { | |||||
InputStream is = _slTests.openResourceAsStream(sampleName); | |||||
try { | |||||
return SlideShowFactory.create(is); | |||||
} catch (Exception e) { | |||||
throw new RuntimeException(e); | |||||
} finally { | |||||
is.close(); | |||||
} | |||||
} | |||||
/** | |||||
* Tests, if the scratchpad classes are on the classpath | |||||
* | |||||
* @return true, if only xslf is on the classpath, and false, if both classpaths | |||||
* (XSLF and HSLF) can be used/referenced | |||||
*/ | |||||
public static boolean xslfOnly() { | |||||
try { | |||||
Class.forName("org.apache.poi.hslf.usermodel.HSLFSlideShow"); | |||||
return false; | |||||
} catch (Exception e) { | |||||
return true; | |||||
} | |||||
} | |||||
} |
/* ==================================================================== | |||||
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.sl; | |||||
import static org.apache.poi.sl.SLCommonUtils.xslfOnly; | |||||
import static org.junit.Assert.assertEquals; | |||||
import static org.junit.Assume.assumeFalse; | |||||
import java.awt.Color; | |||||
import java.awt.Dimension; | |||||
import java.awt.Font; | |||||
import java.awt.FontFormatException; | |||||
import java.awt.Graphics2D; | |||||
import java.awt.GraphicsEnvironment; | |||||
import java.awt.Rectangle; | |||||
import java.awt.RenderingHints; | |||||
import java.awt.geom.Rectangle2D; | |||||
import java.awt.image.BufferedImage; | |||||
import java.io.IOException; | |||||
import java.util.HashMap; | |||||
import java.util.Map; | |||||
import org.apache.poi.POIDataSamples; | |||||
import org.apache.poi.hslf.usermodel.HSLFSlideShow; | |||||
import org.apache.poi.sl.draw.DrawFactory; | |||||
import org.apache.poi.sl.draw.Drawable; | |||||
import org.apache.poi.sl.usermodel.Slide; | |||||
import org.apache.poi.sl.usermodel.SlideShow; | |||||
import org.apache.poi.sl.usermodel.StrokeStyle.LineDash; | |||||
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.xslf.usermodel.XMLSlideShow; | |||||
import org.apache.poi.xslf.usermodel.XSLFTextRun; | |||||
import org.junit.BeforeClass; | |||||
import org.junit.Test; | |||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTRegularTextRun; | |||||
/** | |||||
* Test rendering - specific to font handling | |||||
*/ | |||||
public class TestFonts { | |||||
private static POIDataSamples _slTests = POIDataSamples.getSlideShowInstance(); | |||||
private static final String JPTEXT = | |||||
"\u3061\u3087\u3063\u3068\u65E9\u3044\u3051\u3069T\u30B7\u30E3\u30C4\u304C\u7740\u305F\u304F\u306A" + | |||||
"\u308B\u5B63\u7BC0\u2661\u304A\u6BCD\u3055\u3093\u306E\u5F71\u97FF\u304B\u3001\u975E\u5E38\u306B" + | |||||
"\u6050\u7ADC\u304C\u5927\u597D\u304D\u3067\u3059\u3002\u3082\u3046\u98FC\u3044\u305F\u3044\u304F" + | |||||
"\u3089\u3044\u5927\u597D\u304D\u3067\u3059\u3002#\u30B8\u30E5\u30E9\u30B7\u30C3\u30AF\u30EF\u30FC" + | |||||
"\u30EB\u30C9 \u306E\u30E9\u30D7\u30C8\u30EB4\u59C9\u59B9\u3068\u304B\u6FC0\u7684\u306B\u53EF\u611B" + | |||||
"\u304F\u3066\u53EF\u611B\u304F\u3066\u53EF\u611B\u304F\u3066\u53EF\u611B\u3044\u3067\u3059\u3002" + | |||||
"\u3081\u308D\u3081\u308D\u3001\u5927\u597D\u304D\u2661\u304A\u6BCD\u3055\u3093\u3082\u6050\u7ADC" + | |||||
"\u304C\u597D\u304D\u3067\u3001\u5C0F\u3055\u3044\u9803\u3001\u53E4\u4EE3\u751F\u7269\u306E\u56F3" + | |||||
"\u9451\u3092\u4E00\u7DD2\u306B\u898B\u3066\u305F\u306E\u601D\u3044\u51FA\u3059\u301C\u3068\u3044"; | |||||
private static final String INIT_FONTS[] = { "mona.ttf" }; | |||||
@BeforeClass | |||||
public static void initGE() throws FontFormatException, IOException { | |||||
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); | |||||
for (String s : INIT_FONTS) { | |||||
Font font = Font.createFont(Font.TRUETYPE_FONT, _slTests.getFile(s)); | |||||
ge.registerFont(font); | |||||
} | |||||
} | |||||
@Test | |||||
public void resizeToFitTextHSLF() throws IOException { | |||||
assumeFalse(xslfOnly()); | |||||
SlideShow<?,?> ppt = new HSLFSlideShow(); | |||||
TextBox<?,?> tb = resizeToFitText(ppt); | |||||
Rectangle2D anc = tb.getAnchor(); | |||||
// ignore font metrics differences on windows / linux (... hopefully ...) | |||||
assertEquals(anc.getHeight(), 312d, 5); | |||||
// setFont(tb, "Mona"); | |||||
// FileOutputStream fos = new FileOutputStream("bla-hslf.ppt"); | |||||
// ppt.write(fos); | |||||
// fos.close(); | |||||
ppt.close(); | |||||
} | |||||
@Test | |||||
public void resizeToFitTextXSLF() throws IOException { | |||||
SlideShow<?,?> ppt = new XMLSlideShow(); | |||||
TextBox<?,?> tb = resizeToFitText(ppt); | |||||
Rectangle2D anc = tb.getAnchor(); | |||||
// ignore font metrics differences on windows / linux (... hopefully ...) | |||||
assertEquals(anc.getHeight(), 312d, 5); | |||||
// setFont(tb, "Mona"); | |||||
// FileOutputStream fos = new FileOutputStream("bla-xslf.ppt"); | |||||
// ppt.write(fos); | |||||
// fos.close(); | |||||
ppt.close(); | |||||
} | |||||
private TextBox<?,?> resizeToFitText(SlideShow<?,?> slideshow) throws IOException { | |||||
Slide<?,?> sld = slideshow.createSlide(); | |||||
TextBox<?,?> tb = sld.createTextBox(); | |||||
tb.setAnchor(new Rectangle(50, 50, 200, 50)); | |||||
tb.setStrokeStyle(Color.black, LineDash.SOLID, 3); | |||||
tb.setText(JPTEXT); | |||||
setFont(tb, "NoSuchFont"); | |||||
Dimension pgsize = slideshow.getPageSize(); | |||||
int width = (int)pgsize.getWidth(); | |||||
int height = (int)pgsize.getHeight(); | |||||
BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); | |||||
Graphics2D graphics = img.createGraphics(); | |||||
Map<String,String> fallbackMap = new HashMap<String,String>(); | |||||
fallbackMap.put("NoSuchFont", "Mona"); | |||||
graphics.setRenderingHint(Drawable.FONT_FALLBACK, fallbackMap); | |||||
graphics.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON); | |||||
DrawFactory.getInstance(graphics).fixFonts(graphics); | |||||
tb.resizeToFitText(graphics); | |||||
graphics.dispose(); | |||||
return tb; | |||||
} | |||||
private void setFont(TextBox<?,?> tb, String fontFamily) { | |||||
// TODO: set east asian font family - MS Office uses "MS Mincho" or "MS Gothic" as a fallback | |||||
// see https://stackoverflow.com/questions/26063828 for good explanation about the font metrics | |||||
// differences on different environments | |||||
for (TextParagraph<?,?,? extends TextRun> p : tb.getTextParagraphs()) { | |||||
for (TextRun r : p.getTextRuns()) { | |||||
r.setFontFamily(fontFamily); | |||||
if (r instanceof XSLFTextRun) { | |||||
// TODO: provide API for HSLF | |||||
XSLFTextRun xr = (XSLFTextRun)r; | |||||
CTRegularTextRun tr = (CTRegularTextRun)xr.getXmlObject(); | |||||
tr.getRPr().addNewEa().setTypeface(fontFamily); | |||||
} | |||||
} | |||||
} | |||||
} | |||||
} |
package org.apache.poi.sl; | package org.apache.poi.sl; | ||||
import static org.apache.poi.sl.TestTable.openSampleSlideshow; | |||||
import static org.apache.poi.sl.SLCommonUtils.openSampleSlideshow; | |||||
import static org.apache.poi.sl.SLCommonUtils.xslfOnly; | |||||
import static org.junit.Assert.assertEquals; | import static org.junit.Assert.assertEquals; | ||||
import static org.junit.Assert.assertFalse; | import static org.junit.Assert.assertFalse; | ||||
import static org.junit.Assert.assertNull; | import static org.junit.Assert.assertNull; | ||||
import org.apache.poi.sl.usermodel.SlideShow; | import org.apache.poi.sl.usermodel.SlideShow; | ||||
import org.apache.poi.sl.usermodel.TextParagraph; | import org.apache.poi.sl.usermodel.TextParagraph; | ||||
import org.apache.poi.sl.usermodel.TextShape; | import org.apache.poi.sl.usermodel.TextShape; | ||||
import org.junit.BeforeClass; | |||||
import org.junit.Test; | import org.junit.Test; | ||||
public class TestHeadersFooters { | public class TestHeadersFooters { | ||||
private static boolean xslfOnly = false; | |||||
@BeforeClass | |||||
public static void checkHslf() { | |||||
try { | |||||
Class.forName("org.apache.poi.hslf.usermodel.HSLFSlideShow"); | |||||
} catch (Exception e) { | |||||
xslfOnly = true; | |||||
} | |||||
} | |||||
@Test | @Test | ||||
public void bug58144a() throws IOException { | public void bug58144a() throws IOException { | ||||
assumeFalse(xslfOnly); | |||||
assumeFalse(xslfOnly()); | |||||
SlideShow<?,?> ppt = openSampleSlideshow("bug58144-headers-footers-2003.ppt"); | SlideShow<?,?> ppt = openSampleSlideshow("bug58144-headers-footers-2003.ppt"); | ||||
HSLFSlide sl = (HSLFSlide)ppt.getSlides().get(0); | HSLFSlide sl = (HSLFSlide)ppt.getSlides().get(0); | ||||
HeadersFooters hfs = sl.getHeadersFooters(); | HeadersFooters hfs = sl.getHeadersFooters(); | ||||
@Test | @Test | ||||
public void bug58144b() throws IOException { | public void bug58144b() throws IOException { | ||||
assumeFalse(xslfOnly); | |||||
assumeFalse(xslfOnly()); | |||||
SlideShow<?,?> ppt = openSampleSlideshow("bug58144-headers-footers-2007.ppt"); | SlideShow<?,?> ppt = openSampleSlideshow("bug58144-headers-footers-2007.ppt"); | ||||
Slide<?,?> sl = ppt.getSlides().get(0); | Slide<?,?> sl = ppt.getSlides().get(0); | ||||
HeadersFooters hfs2 = ((HSLFSlide)sl).getHeadersFooters(); | HeadersFooters hfs2 = ((HSLFSlide)sl).getHeadersFooters(); |
package org.apache.poi.sl; | package org.apache.poi.sl; | ||||
import static org.apache.poi.sl.SLCommonUtils.openSampleSlideshow; | |||||
import static org.apache.poi.sl.SLCommonUtils.xslfOnly; | |||||
import static org.junit.Assert.assertEquals; | import static org.junit.Assert.assertEquals; | ||||
import static org.junit.Assert.assertFalse; | import static org.junit.Assert.assertFalse; | ||||
import static org.junit.Assert.assertNotNull; | import static org.junit.Assert.assertNotNull; | ||||
import java.io.IOException; | import java.io.IOException; | ||||
import java.io.InputStream; | import java.io.InputStream; | ||||
import org.apache.poi.POIDataSamples; | |||||
import org.apache.poi.hslf.usermodel.HSLFSlideShow; | import org.apache.poi.hslf.usermodel.HSLFSlideShow; | ||||
import org.apache.poi.sl.usermodel.Slide; | import org.apache.poi.sl.usermodel.Slide; | ||||
import org.apache.poi.sl.usermodel.SlideShow; | import org.apache.poi.sl.usermodel.SlideShow; | ||||
import org.apache.poi.sl.usermodel.TableShape; | import org.apache.poi.sl.usermodel.TableShape; | ||||
import org.apache.poi.sl.usermodel.TextShape.TextDirection; | import org.apache.poi.sl.usermodel.TextShape.TextDirection; | ||||
import org.apache.poi.xslf.usermodel.XMLSlideShow; | import org.apache.poi.xslf.usermodel.XMLSlideShow; | ||||
import org.junit.BeforeClass; | |||||
import org.junit.Test; | import org.junit.Test; | ||||
public class TestTable { | public class TestTable { | ||||
private static POIDataSamples _slTests = POIDataSamples.getSlideShowInstance(); | |||||
private static boolean xslfOnly = false; | |||||
@BeforeClass | |||||
public static void checkHslf() { | |||||
try { | |||||
Class.forName("org.apache.poi.hslf.usermodel.HSLFSlideShow"); | |||||
} catch (Exception e) { | |||||
xslfOnly = true; | |||||
} | |||||
} | |||||
/** a generic way to open a sample slideshow document **/ | |||||
public static SlideShow<?,?> openSampleSlideshow(String sampleName) throws IOException { | |||||
InputStream is = _slTests.openResourceAsStream(sampleName); | |||||
try { | |||||
return SlideShowFactory.create(is); | |||||
} catch (Exception e) { | |||||
throw new RuntimeException(e); | |||||
} finally { | |||||
is.close(); | |||||
} | |||||
} | |||||
@Test | @Test | ||||
public void colWidthRowHeight() throws IOException { | public void colWidthRowHeight() throws IOException { | ||||
assumeFalse(xslfOnly); | |||||
assumeFalse(xslfOnly()); | |||||
// Test of table dimensions of same slideshow saved as ppt/x | // Test of table dimensions of same slideshow saved as ppt/x | ||||
// to check if both return similar (points) value | // to check if both return similar (points) value | ||||
@Test | @Test | ||||
public void directionHSLF() throws IOException { | public void directionHSLF() throws IOException { | ||||
assumeFalse(xslfOnly); | |||||
assumeFalse(xslfOnly()); | |||||
SlideShow<?,?> ppt1 = new HSLFSlideShow(); | SlideShow<?,?> ppt1 = new HSLFSlideShow(); | ||||
testTextDirection(ppt1); | testTextDirection(ppt1); | ||||
ppt1.close(); | ppt1.close(); | ||||
@Test | @Test | ||||
public void tableSpan() throws IOException { | public void tableSpan() throws IOException { | ||||
String files[] = (xslfOnly) ? new String[]{ "bug60993.pptx" } : new String[]{ "bug60993.pptx", "bug60993.ppt" }; | |||||
String files[] = (xslfOnly()) ? new String[]{ "bug60993.pptx" } : new String[]{ "bug60993.pptx", "bug60993.ppt" }; | |||||
for (String f : files) { | for (String f : files) { | ||||
SlideShow<?,?> ppt = openSampleSlideshow(f); | SlideShow<?,?> ppt = openSampleSlideshow(f); | ||||
Slide<?,?> slide = ppt.getSlides().get(0); | Slide<?,?> slide = ppt.getSlides().get(0); |
import static org.apache.poi.hslf.record.RecordTypes.OEPlaceholderAtom; | import static org.apache.poi.hslf.record.RecordTypes.OEPlaceholderAtom; | ||||
import static org.apache.poi.hslf.record.RecordTypes.RoundTripHFPlaceholder12; | import static org.apache.poi.hslf.record.RecordTypes.RoundTripHFPlaceholder12; | ||||
import java.awt.Graphics2D; | |||||
import java.awt.geom.Rectangle2D; | import java.awt.geom.Rectangle2D; | ||||
import java.io.IOException; | import java.io.IOException; | ||||
import java.util.ArrayList; | import java.util.ArrayList; | ||||
} | } | ||||
} | } | ||||
@Override | |||||
public Rectangle2D resizeToFitText() { | |||||
return resizeToFitText(null); | |||||
} | |||||
/** | |||||
* Adjust the size of the shape so it encompasses the text inside it. | |||||
* | |||||
* @return a <code>Rectangle2D</code> that is the bounds of this shape. | |||||
*/ | |||||
public Rectangle2D resizeToFitText(){ | |||||
@Override | |||||
public Rectangle2D resizeToFitText(Graphics2D graphics) { | |||||
Rectangle2D anchor = getAnchor(); | Rectangle2D anchor = getAnchor(); | ||||
if(anchor.getWidth() == 0.) { | if(anchor.getWidth() == 0.) { | ||||
LOG.log(POILogger.WARN, "Width of shape wasn't set. Defaulting to 200px"); | LOG.log(POILogger.WARN, "Width of shape wasn't set. Defaulting to 200px"); | ||||
anchor.setRect(anchor.getX(), anchor.getY(), 200., anchor.getHeight()); | anchor.setRect(anchor.getX(), anchor.getY(), 200., anchor.getHeight()); | ||||
setAnchor(anchor); | setAnchor(anchor); | ||||
} | } | ||||
double height = getTextHeight(); | |||||
double height = getTextHeight(graphics); | |||||
height += 1; // add a pixel to compensate rounding errors | height += 1; // add a pixel to compensate rounding errors | ||||
Insets2D insets = getInsets(); | Insets2D insets = getInsets(); | ||||
} | } | ||||
@Override | @Override | ||||
public double getTextHeight(){ | |||||
DrawFactory drawFact = DrawFactory.getInstance(null); | |||||
public double getTextHeight() { | |||||
return getTextHeight(null); | |||||
} | |||||
@Override | |||||
public double getTextHeight(Graphics2D graphics) { | |||||
DrawFactory drawFact = DrawFactory.getInstance(graphics); | |||||
DrawTextShape dts = drawFact.getDrawable(this); | DrawTextShape dts = drawFact.getDrawable(this); | ||||
return dts.getTextHeight(); | |||||
return dts.getTextHeight(graphics); | |||||
} | } | ||||
@Override | @Override |