123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769 |
- /* ====================================================================
- 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.xslf.usermodel;
-
- import org.apache.poi.util.Beta;
- import org.apache.poi.util.Internal;
- import org.apache.poi.util.Units;
- import org.apache.poi.xslf.model.ParagraphPropertyFetcher;
- import org.apache.xmlbeans.XmlObject;
- import org.openxmlformats.schemas.drawingml.x2006.main.CTRegularTextRun;
- import org.openxmlformats.schemas.drawingml.x2006.main.CTTextField;
- import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraph;
- import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraphProperties;
- import org.openxmlformats.schemas.drawingml.x2006.main.CTTextSpacing;
- import org.openxmlformats.schemas.drawingml.x2006.main.STTextAlignType;
- import org.openxmlformats.schemas.presentationml.x2006.main.CTPlaceholder;
- import org.openxmlformats.schemas.presentationml.x2006.main.STPlaceholderType;
-
- import java.awt.Color;
- import java.awt.Graphics2D;
- import java.awt.font.LineBreakMeasurer;
- import java.awt.font.TextAttribute;
- import java.awt.font.TextLayout;
- import java.awt.geom.Rectangle2D;
- import java.text.AttributedCharacterIterator;
- import java.text.AttributedString;
- import java.util.ArrayList;
- import java.util.Iterator;
- import java.util.List;
-
- /**
- * Represents a paragraph of text within the containing text body.
- * The paragraph is the highest level text separation mechanism.
- *
- * @author Yegor Kozlov
- * @since POI-3.8
- */
- @Beta
- public class XSLFTextParagraph implements Iterable<XSLFTextRun>{
- private final CTTextParagraph _p;
- private final List<XSLFTextRun> _runs;
- private final XSLFTextShape _shape;
- private List<TextFragment> _lines;
- private TextFragment _bullet;
-
- XSLFTextParagraph(CTTextParagraph p, XSLFTextShape shape){
- _p = p;
- _runs = new ArrayList<XSLFTextRun>();
- _shape = shape;
-
- for (CTRegularTextRun r : _p.getRList()) {
- _runs.add(new XSLFTextRun(r, this));
- }
-
- for (CTTextField f : _p.getFldList()) {
- CTRegularTextRun r = CTRegularTextRun.Factory.newInstance();
- r.setT(f.getT());
- _runs.add(new XSLFTextRun(r, this));
- }
- }
-
- public String getText(){
- StringBuilder out = new StringBuilder();
- for (XSLFTextRun r : _runs) {
- out.append(r.getText());
- }
- return out.toString();
- }
-
- private String getVisibleText(){
- StringBuilder out = new StringBuilder();
- for (XSLFTextRun r : _runs) {
- String txt = r.getText();
- switch (r.getTextCap()){
- case ALL:
- txt = txt.toUpperCase();
- break;
- case SMALL:
- txt = txt.toLowerCase();
- break;
- }
- out.append(txt);
- }
- return out.toString();
- }
-
- @Internal
- public CTTextParagraph getXmlObject(){
- return _p;
- }
-
- XSLFTextShape getParentShape() {
- return _shape;
-
- }
-
- public List<XSLFTextRun> getTextRuns(){
- return _runs;
- }
-
- public Iterator<XSLFTextRun> iterator(){
- return _runs.iterator();
- }
-
- public XSLFTextRun addNewTextRun(){
- CTRegularTextRun r = _p.addNewR();
- r.addNewRPr();
- XSLFTextRun run = new XSLFTextRun(r, this);
- _runs.add(run);
- return run;
- }
-
- public void addLineBreak(){
- _p.addNewBr();
- }
-
- /**
- * Returns the alignment that is applied to the paragraph.
- *
- * If this attribute is omitted, then a value of left is implied.
- * @return ??? alignment that is applied to the paragraph
- */
- public TextAlign getTextAlign(){
- ParagraphPropertyFetcher<TextAlign> fetcher = new ParagraphPropertyFetcher<TextAlign>(getLevel()){
- public boolean fetch(CTTextParagraphProperties props){
- if(props.isSetAlgn()){
- TextAlign val = TextAlign.values()[props.getAlgn().intValue() - 1];
- setValue(val);
- return true;
- }
- return false;
- }
- };
- fetchParagraphProperty(fetcher);
- return fetcher.getValue() == null ? TextAlign.LEFT : fetcher.getValue();
- }
-
- /**
- * Specifies the alignment that is to be applied to the paragraph.
- * Possible values for this include left, right, centered, justified and distributed,
- * see {@link org.apache.poi.xslf.usermodel.TextAlign}.
- *
- * @param align text align
- */
- public void setTextAlign(TextAlign align){
- CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr();
- if(align == null) {
- if(pr.isSetAlgn()) pr.unsetAlgn();
- } else {
- pr.setAlgn(STTextAlignType.Enum.forInt(align.ordinal() + 1));
- }
- }
-
-
- /**
- * @return the font to be used on bullet characters within a given paragraph
- */
- public String getBulletFont(){
- ParagraphPropertyFetcher<String> fetcher = new ParagraphPropertyFetcher<String>(getLevel()){
- public boolean fetch(CTTextParagraphProperties props){
- if(props.isSetBuFont()){
- setValue(props.getBuFont().getTypeface());
- return true;
- }
- return false;
- }
- };
- fetchParagraphProperty(fetcher);
- return fetcher.getValue();
- }
-
- /**
- * @return the character to be used in place of the standard bullet point
- */
- public String getBulletCharacter(){
- ParagraphPropertyFetcher<String> fetcher = new ParagraphPropertyFetcher<String>(getLevel()){
- public boolean fetch(CTTextParagraphProperties props){
- if(props.isSetBuChar()){
- setValue(props.getBuChar().getChar());
- return true;
- }
- return false;
- }
- };
- fetchParagraphProperty(fetcher);
- return fetcher.getValue();
- }
-
- public Color getBulletFontColor(){
- final XSLFTheme theme = getParentShape().getSheet().getTheme();
- ParagraphPropertyFetcher<Color> fetcher = new ParagraphPropertyFetcher<Color>(getLevel()){
- public boolean fetch(CTTextParagraphProperties props){
- if(props.isSetBuClr()){
- XSLFColor c = new XSLFColor(props.getBuClr(), theme, null);
- setValue(c.getColor());
- return true;
- }
- return false;
- }
- };
- fetchParagraphProperty(fetcher);
- return fetcher.getValue();
- }
-
- public double getBulletFontSize(){
- ParagraphPropertyFetcher<Double> fetcher = new ParagraphPropertyFetcher<Double>(getLevel()){
- public boolean fetch(CTTextParagraphProperties props){
- if(props.isSetBuSzPct()){
- setValue(props.getBuSzPct().getVal() * 0.001);
- return true;
- }
- if(props.isSetBuSzPts()){
- setValue( - props.getBuSzPts().getVal() * 0.01);
- return true;
- }
- return false;
- }
- };
- fetchParagraphProperty(fetcher);
- return fetcher.getValue() == null ? 100 : fetcher.getValue();
- }
-
- /**
- * Specifies the indent size that will be applied to the first line of text in the paragraph.
- *
- * @param value the indent in points. The value of -1 unsets the indent attribute
- * from the underlying xml bean.
- */
- public void setIndent(double value){
- CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr();
- if(value == -1) {
- if(pr.isSetIndent()) pr.unsetIndent();
- } else {
- pr.setIndent(Units.toEMU(value));
- }
- }
-
- /**
- *
- * @return the indent applied to the first line of text in the paragraph.
- */
- public double getIndent(){
-
- ParagraphPropertyFetcher<Double> fetcher = new ParagraphPropertyFetcher<Double>(getLevel()){
- public boolean fetch(CTTextParagraphProperties props){
- if(props.isSetIndent()){
- setValue(Units.toPoints(props.getIndent()));
- return true;
- }
- return false;
- }
- };
- fetchParagraphProperty(fetcher);
-
- return fetcher.getValue() == null ? 0 : fetcher.getValue();
- }
-
- /**
- * Specifies the left margin of the paragraph. This is specified in addition to the text body
- * inset and applies only to this text paragraph. That is the text body Inset and the LeftMargin
- * attributes are additive with respect to the text position.
- *
- * @param value the left margin of the paragraph
- */
- public void setLeftMargin(double value){
- CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr();
- pr.setMarL(Units.toEMU(value));
- }
-
- /**
- *
- * @return the left margin of the paragraph
- */
- public double getLeftMargin(){
- ParagraphPropertyFetcher<Double> fetcher = new ParagraphPropertyFetcher<Double>(getLevel()){
- public boolean fetch(CTTextParagraphProperties props){
- if(props.isSetMarL()){
- double val = Units.toPoints(props.getMarL());
- setValue(val);
- return true;
- }
- return false;
- }
- };
- fetchParagraphProperty(fetcher);
- return fetcher.getValue() == null ? 0 : fetcher.getValue();
- }
-
- /**
- * This element specifies the vertical line spacing that is to be used within a paragraph.
- * This may be specified in two different ways, percentage spacing and font point spacing:
- * <p>
- * If linespacing >= 0, then linespacing is a percentage of normal line height
- * If linespacing < 0, the absolute value of linespacing is the spacing in points
- * </p>
- * Examples:
- * <pre><code>
- * // spacing will be 120% of the size of the largest text on each line
- * paragraph.setLineSpacing(120);
- *
- * // spacing will be 200% of the size of the largest text on each line
- * paragraph.setLineSpacing(200);
- *
- * // spacing will be 48 points
- * paragraph.setLineSpacing(-48.0);
- * </code></pre>
- *
- * @param linespacing the vertical line spacing
- */
- public void setLineSpacing(double linespacing){
- CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr();
- CTTextSpacing spc = CTTextSpacing.Factory.newInstance();
- if(linespacing >= 0) spc.addNewSpcPct().setVal((int)(linespacing*1000));
- else spc.addNewSpcPts().setVal((int)(-linespacing*100));
- pr.setLnSpc(spc);
- }
-
- /**
- * Returns the vertical line spacing that is to be used within a paragraph.
- * This may be specified in two different ways, percentage spacing and font point spacing:
- * <p>
- * If linespacing >= 0, then linespacing is a percentage of normal line height.
- * If linespacing < 0, the absolute value of linespacing is the spacing in points
- * </p>
- *
- * @return the vertical line spacing.
- */
- public double getLineSpacing(){
- ParagraphPropertyFetcher<Double> fetcher = new ParagraphPropertyFetcher<Double>(getLevel()){
- public boolean fetch(CTTextParagraphProperties props){
- if(props.isSetLnSpc()){
- CTTextSpacing spc = props.getLnSpc();
-
- if(spc.isSetSpcPct()) setValue( spc.getSpcPct().getVal()*0.001 );
- else if (spc.isSetSpcPts()) setValue( -spc.getSpcPts().getVal()*0.01 );
- return true;
- }
- return false;
- }
- };
- fetchParagraphProperty(fetcher);
- return fetcher.getValue() == null ? 100 : fetcher.getValue();
- }
-
- /**
- * Set the amount of vertical white space that will be present before the paragraph.
- * This space is specified in either percentage or points:
- * <p>
- * If spaceBefore >= 0, then space is a percentage of normal line height.
- * If spaceBefore < 0, the absolute value of linespacing is the spacing in points
- * </p>
- * Examples:
- * <pre><code>
- * // The paragraph will be formatted to have a spacing before the paragraph text.
- * // The spacing will be 200% of the size of the largest text on each line
- * paragraph.setSpaceBefore(200);
- *
- * // The spacing will be a size of 48 points
- * paragraph.setSpaceBefore(-48.0);
- * </code></pre>
- *
- * @param spaceBefore the vertical white space before the paragraph.
- */
- public void setSpaceBefore(double spaceBefore){
- CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr();
- CTTextSpacing spc = CTTextSpacing.Factory.newInstance();
- if(spaceBefore >= 0) spc.addNewSpcPct().setVal((int)(spaceBefore*1000));
- else spc.addNewSpcPts().setVal((int)(-spaceBefore*100));
- pr.setSpcBef(spc);
- }
-
- /**
- * The amount of vertical white space before the paragraph
- * This may be specified in two different ways, percentage spacing and font point spacing:
- * <p>
- * If spaceBefore >= 0, then space is a percentage of normal line height.
- * If spaceBefore < 0, the absolute value of linespacing is the spacing in points
- * </p>
- *
- * @return the vertical white space before the paragraph
- */
- public double getSpaceBefore(){
- ParagraphPropertyFetcher<Double> fetcher = new ParagraphPropertyFetcher<Double>(getLevel()){
- public boolean fetch(CTTextParagraphProperties props){
- if(props.isSetSpcBef()){
- CTTextSpacing spc = props.getSpcBef();
-
- if(spc.isSetSpcPct()) setValue( spc.getSpcPct().getVal()*0.001 );
- else if (spc.isSetSpcPts()) setValue( -spc.getSpcPts().getVal()*0.01 );
- return true;
- }
- return false;
- }
- };
- fetchParagraphProperty(fetcher);
- return fetcher.getValue() == null ? 0 : fetcher.getValue();
- }
-
- /**
- * Set the amount of vertical white space that will be present after the paragraph.
- * This space is specified in either percentage or points:
- * <p>
- * If spaceAfter >= 0, then space is a percentage of normal line height.
- * If spaceAfter < 0, the absolute value of linespacing is the spacing in points
- * </p>
- * Examples:
- * <pre><code>
- * // The paragraph will be formatted to have a spacing after the paragraph text.
- * // The spacing will be 200% of the size of the largest text on each line
- * paragraph.setSpaceAfter(200);
- *
- * // The spacing will be a size of 48 points
- * paragraph.setSpaceAfter(-48.0);
- * </code></pre>
- *
- * @param spaceAfter the vertical white space after the paragraph.
- */
- public void setSpaceAfter(double spaceAfter){
- CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr();
- CTTextSpacing spc = CTTextSpacing.Factory.newInstance();
- if(spaceAfter >= 0) spc.addNewSpcPct().setVal((int)(spaceAfter*1000));
- else spc.addNewSpcPts().setVal((int)(-spaceAfter*100));
- pr.setSpcAft(spc);
- }
-
- /**
- * The amount of vertical white space after the paragraph
- * This may be specified in two different ways, percentage spacing and font point spacing:
- * <p>
- * If spaceBefore >= 0, then space is a percentage of normal line height.
- * If spaceBefore < 0, the absolute value of linespacing is the spacing in points
- * </p>
- *
- * @return the vertical white space after the paragraph
- */
- public double getSpaceAfter(){
- ParagraphPropertyFetcher<Double> fetcher = new ParagraphPropertyFetcher<Double>(getLevel()){
- public boolean fetch(CTTextParagraphProperties props){
- if(props.isSetSpcAft()){
- CTTextSpacing spc = props.getSpcAft();
-
- if(spc.isSetSpcPct()) setValue( spc.getSpcPct().getVal()*0.001 );
- else if (spc.isSetSpcPts()) setValue( -spc.getSpcPts().getVal()*0.01 );
- return true;
- }
- return false;
- }
- };
- fetchParagraphProperty(fetcher);
- return fetcher.getValue() == null ? 0 : fetcher.getValue();
- }
-
- /**
- * Specifies the particular level text properties that this paragraph will follow.
- * The value for this attribute formats the text according to the corresponding level
- * paragraph properties defined in the SlideMaster.
- *
- * @param level the level (0 ... 4)
- */
- public void setLevel(int level){
- CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr();
-
- pr.setLvl(level);
- }
-
- /**
- *
- * @return the text level of this paragraph. Default is 0.
- */
- public int getLevel(){
- CTTextParagraphProperties pr = _p.getPPr();
- if(pr == null) return 0;
-
- return pr.getLvl();
-
- }
-
- /**
- * Returns whether this paragraph has bullets
- */
- public boolean isBullet() {
- ParagraphPropertyFetcher<Boolean> fetcher = new ParagraphPropertyFetcher<Boolean>(getLevel()){
- public boolean fetch(CTTextParagraphProperties props){
- if(props.isSetBuNone()) {
- setValue(false);
- return true;
- }
- if(props.isSetBuFont()){
- setValue(true);
- return true;
- }
- return false;
- }
- };
- fetchParagraphProperty(fetcher);
- return fetcher.getValue() == null ? false : fetcher.getValue();
- }
-
- @Override
- public String toString(){
- return "[" + getClass() + "]" + getText();
- }
-
- List<TextFragment> getTextLines(){
- return _lines;
- }
-
- public double draw(Graphics2D graphics, double x, double y){
- double marginLeft = _shape.getLeftInset();
- double marginRight = _shape.getRightInset();
- Rectangle2D anchor = _shape.getAnchor();
- double penY = y;
-
- double textOffset = getLeftMargin();
- boolean firstLine = true;
- for(TextFragment line : _lines){
- double penX = x;
- switch (getTextAlign()) {
- case CENTER:
- penX += textOffset + (anchor.getWidth() - textOffset - line.getWidth() - marginLeft - marginRight) / 2;
- break;
- case RIGHT:
- penX += (anchor.getWidth() - line.getWidth() - marginLeft - marginRight);
- break;
- default:
- penX = x + textOffset;
- break;
- }
-
- if(_bullet != null && firstLine){
- _bullet.draw(graphics, penX + getIndent(), penY);
- }
- line.draw(graphics, penX, penY);
-
- //The vertical line spacing
- double spacing = getLineSpacing();
- if(spacing > 0) {
- // If linespacing >= 0, then linespacing is a percentage of normal line height.
- penY += spacing*0.01*line.getHeight();
- } else {
- // positive value means absolute spacing in points
- penY += -spacing;
- }
-
- firstLine = false;
- }
- return penY - y;
- }
-
- static class TextFragment {
- private TextLayout _layout;
- private AttributedString _str;
-
- TextFragment(TextLayout layout, AttributedString str){
- _layout = layout;
- _str = str;
- }
-
- void draw(Graphics2D graphics, double x, double y){
- double yBaseline = y + _layout.getAscent();
-
- Integer textMode = (Integer)graphics.getRenderingHint(XSLFRenderingHint.TEXT_RENDERING_MODE);
- if(textMode != null && textMode == XSLFRenderingHint.TEXT_MODE_GLYPHS){
- _layout.draw(graphics, (float)x, (float)yBaseline);
- } else {
- graphics.drawString(_str.getIterator(), (float)x, (float)yBaseline );
- }
- }
-
- public float getHeight(){
- return _layout.getAscent() + _layout.getDescent() + _layout.getLeading();
- }
- public float getWidth(){
- return _layout.getAdvance();
- }
-
- }
-
- AttributedString getAttributedString(Graphics2D graphics){
- String text = getVisibleText();
-
- AttributedString string = new AttributedString(text);
-
- int startIndex = 0;
- for (XSLFTextRun run : _runs){
- int length = run.getText().length();
- if(length == 0) {
- // skip empty runs
- continue;
- }
- int endIndex = startIndex + length;
-
- string.addAttribute(TextAttribute.FOREGROUND, run.getFontColor(), startIndex, endIndex);
-
- // user can pass an object to convert fonts via a rendering hint
- string.addAttribute(TextAttribute.FAMILY, run.getFontFamily(), startIndex, endIndex);
-
- string.addAttribute(TextAttribute.SIZE, (float)run.getFontSize(), startIndex, endIndex);
- if(run.isBold()) {
- string.addAttribute(TextAttribute.WEIGHT, TextAttribute.WEIGHT_BOLD, startIndex, endIndex);
- }
- if(run.isItalic()) {
- string.addAttribute(TextAttribute.POSTURE, TextAttribute.POSTURE_OBLIQUE, startIndex, endIndex);
- }
- if(run.isUnderline()) {
- string.addAttribute(TextAttribute.UNDERLINE, TextAttribute.UNDERLINE_ON, startIndex, endIndex);
- string.addAttribute(TextAttribute.INPUT_METHOD_UNDERLINE, TextAttribute.UNDERLINE_LOW_TWO_PIXEL, startIndex, endIndex);
- }
- if(run.isStrikethrough()) {
- string.addAttribute(TextAttribute.STRIKETHROUGH, TextAttribute.STRIKETHROUGH_ON, startIndex, endIndex);
- }
- if(run.isSubscript()) {
- string.addAttribute(TextAttribute.SUPERSCRIPT, TextAttribute.SUPERSCRIPT_SUB, startIndex, endIndex);
- }
- if(run.isSuperscript()) {
- string.addAttribute(TextAttribute.SUPERSCRIPT, TextAttribute.SUPERSCRIPT_SUPER, startIndex, endIndex);
- }
-
-
- startIndex = endIndex;
- }
-
- return string;
- }
-
- void breakText(Graphics2D graphics){
- _lines = new ArrayList<TextFragment>();
-
- AttributedString at = getAttributedString(graphics);
- AttributedCharacterIterator it = at.getIterator();
- if(it.getBeginIndex() == it.getEndIndex()) {
- return;
- }
- LineBreakMeasurer measurer = new LineBreakMeasurer(it, graphics.getFontRenderContext());
- for (;;) {
- int startIndex = measurer.getPosition();
- double wrappingWidth = getWrappingWidth() + 1; // add a pixel to compensate rounding errors
- TextLayout layout = measurer.nextLayout((float)wrappingWidth, it.getEndIndex(), true);
- if (layout == null) {
- // layout can be null if the entire word at the current position
- // does not fit within the wrapping width. Try with requireNextWord=false.
- layout = measurer.nextLayout((float)wrappingWidth, it.getEndIndex(), false);
- }
-
- int endIndex = measurer.getPosition();
-
- TextAlign hAlign = getTextAlign();
- if(hAlign == TextAlign.JUSTIFY || hAlign == TextAlign.JUSTIFY_LOW) {
- layout = layout.getJustifiedLayout((float)wrappingWidth);
- }
-
- AttributedString str = new AttributedString(it, startIndex, endIndex);
- TextFragment line = new TextFragment(layout, str);
- _lines.add(line);
-
- if(endIndex == it.getEndIndex()) break;
- }
-
- if(isBullet()) {
- String buCharacter = getBulletCharacter();
- String buFont = getBulletFont();
- if(buCharacter != null && buFont != null && _lines.size() > 0) {
- AttributedString str = new AttributedString(buCharacter);
-
- TextFragment firstLine = _lines.get(0);
- AttributedCharacterIterator bit = firstLine._str.getIterator();
-
- Color buColor = getBulletFontColor();
- str.addAttribute(TextAttribute.FOREGROUND, buColor == null ?
- bit.getAttribute(TextAttribute.FOREGROUND) : buColor);
- str.addAttribute(TextAttribute.FAMILY, buFont);
-
- float fontSize = (Float)bit.getAttribute(TextAttribute.SIZE);
- float buSz = (float)getBulletFontSize();
- if(buSz > 0) fontSize *= buSz* 0.01;
- else fontSize = -buSz;
-
- str.addAttribute(TextAttribute.SIZE, fontSize);
-
- TextLayout layout = new TextLayout(str.getIterator(), graphics.getFontRenderContext());
- _bullet = new TextFragment(layout, str);
- }
- }
-
- }
-
- double getWrappingWidth(){
- double width;
- if(!_shape.getWordWrap()) {
- width = _shape.getSheet().getSlideShow().getPageSize().getWidth();
- } else {
- width = _shape.getAnchor().getWidth() -
- _shape.getLeftInset() - _shape.getRightInset() - getLeftMargin();
- }
- return width;
- }
-
- CTTextParagraphProperties getDefaultStyle(){
- CTPlaceholder ph = _shape.getCTPlaceholder();
- String defaultStyleSelector;
- if(ph == null) defaultStyleSelector = "otherStyle";
- else {
- switch(ph.getType().intValue()){
- case STPlaceholderType.INT_TITLE:
- case STPlaceholderType.INT_CTR_TITLE:
- defaultStyleSelector = "titleStyle";
- break;
- case STPlaceholderType.INT_FTR:
- case STPlaceholderType.INT_SLD_NUM:
- case STPlaceholderType.INT_DT:
- defaultStyleSelector = "otherStyle";
- break;
- default:
- defaultStyleSelector = "bodyStyle";
- break;
- }
- }
-
- int level = getLevel();
-
- XSLFSheet masterSheet = _shape.getSheet();
- while (masterSheet.getMasterSheet() != null){
- masterSheet = masterSheet.getMasterSheet();
- }
-
- XmlObject[] o = masterSheet.getXmlObject().selectPath(
- "declare namespace p='http://schemas.openxmlformats.org/presentationml/2006/main' " +
- "declare namespace a='http://schemas.openxmlformats.org/drawingml/2006/main' " +
- ".//p:txStyles/p:" + defaultStyleSelector +"/a:lvl" +(level+1)+ "pPr");
- if(o.length == 1){
- return (CTTextParagraphProperties)o[0];
- }
- throw new IllegalArgumentException("Failed to fetch default style for " +
- defaultStyleSelector + " and level=" + level);
- }
-
-
- private boolean fetchParagraphProperty(ParagraphPropertyFetcher visitor){
- boolean ok = false;
-
- if(_p.isSetPPr()) ok = visitor.fetch(_p.getPPr());
-
- if(!ok) {
- XSLFTextShape shape = getParentShape();
- ok = shape.fetchShapeProperty(visitor);
- if(!ok) {
- CTTextParagraphProperties defaultProps = getDefaultStyle();
- if(defaultProps != null) ok = visitor.fetch(defaultProps);
- }
- }
-
- return ok;
- }
-
- }
|