Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /* ====================================================================
     Licensed to the Apache Software Foundation (ASF) under one or more
     contributor license agreements.  See the NOTICE file distributed with
     this work for additional information regarding copyright ownership.
     The ASF licenses this file to You under the Apache License, Version 2.0
     (the "License"); you may not use this file except in compliance with
     the License.  You may obtain a copy of the License at
  
         http://www.apache.org/licenses/LICENSE-2.0
 
    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
 ==================================================================== */
 
 package org.apache.poi.hslf.model;
 
 import java.awt.Color;
 import java.awt.Font;
 import java.util.List;
 import java.util.Map;
 
Paint text into java.awt.Graphics2D

Author(s):
Yegor Kozlov
 
 public final class TextPainter {
     public static final Key KEY_FONTFALLBACK = new Key(50, "Font fallback map");
     public static final Key KEY_FONTMAP = new Key(51, "Font map");
     
     protected POILogger logger = POILogFactory.getLogger(this.getClass());

    
Display unicode square if a bullet char can't be displayed, for example, if Wingdings font is used. TODO: map Wingdngs and Symbol to unicode Arial
 
     protected static final char DEFAULT_BULLET_CHAR = '\u25a0';
 
     protected TextShape _shape;
 
     public TextPainter(TextShape shape){
          = shape;
     }
 
     public AttributedString getAttributedString(TextRun txrun) {
         return getAttributedString(txrunnull);
     }
    
    
Convert the underlying set of rich text runs into java.text.AttributedString
 
     public AttributedString getAttributedString(TextRun txrunGraphics2D graphics){
         String text = txrun.getText();
         //TODO: properly process tabs
         text = text.replace('\t'' ');
         text = text.replace((char)160, ' ');
 
         AttributedString at = new AttributedString(text);
         RichTextRun[] rt = txrun.getRichTextRuns();
         for (int i = 0; i < rt.lengthi++) {
             int start = rt[i].getStartIndex();
             int end = rt[i].getEndIndex();
             if(start == end) {
                 .log(.,  "Skipping RichTextRun with zero length");
                 continue;
             }
 
             String mappedFont = rt[i].getFontName();
             String fallbackFont = .;
             if (graphics != null) {
                 @SuppressWarnings("unchecked")
                 Map<String,StringfontMap = (Map<String,String>)graphics.getRenderingHint();
                 if (fontMap != null && fontMap.containsKey(mappedFont)) {
                     mappedFont = fontMap.get(mappedFont);
                 }
                 @SuppressWarnings("unchecked")
                 Map<String,StringfallbackMap = (Map<String,String>)graphics.getRenderingHint();
                 if (fallbackMap != null && fallbackMap.containsKey(mappedFont)) {
                    fallbackFont = fallbackMap.get(mappedFont);
                }
            }
            
            at.addAttribute(.mappedFontstartend);
            at.addAttribute(.new Float(rt[i].getFontSize()), startend);
            at.addAttribute(.rt[i].getFontColor(), startend);
            if(rt[i].isBold()) at.addAttribute(..startend);
            if(rt[i].isItalic()) at.addAttribute(..startend);
            if(rt[i].isUnderlined()) {
                at.addAttribute(..startend);
            }
            if(rt[i].isStrikethrough()) at.addAttribute(..startend);
            int superScript = rt[i].getSuperscript();
            if(superScript != 0) at.addAttribute(.superScript > 0 ? . : .startend);
            
            
            int style = (rt[i].isBold() ? . : 0) | (rt[i].isItalic() ? . : 0);
            Font f = new Font(mappedFontstylert[i].getFontSize());
            
            // check for unsupported characters and add a fallback font for these
            char textChr[] = text.toCharArray();
            int nextEnd = f.canDisplayUpTo(textChrstartend);
            boolean isNextValid = nextEnd == start;
            for (int last = startnextEnd != -1 && nextEnd <= end; ) {
                if (isNextValid) {
                    nextEnd = f.canDisplayUpTo(textChrnextEndend);
                    isNextValid = false;
                } else {
                    if (nextEnd >= end || f.canDisplay(Character.codePointAt(textChrnextEndend)) ) {
                        at.addAttribute(.fallbackFontlast, Math.min(nextEnd,end));
                        if (nextEnd >= endbreak;
                        last = nextEnd;
                        isNextValid = true;
                    } else {
                        boolean isHS = Character.isHighSurrogate(textChr[nextEnd]);
                        nextEnd+=(isHS?2:1);
                    }
                }
            }            
        }
        return at;
    }
    public void paint(Graphics2D graphics){
        AffineTransform tx = graphics.getTransform();
        Rectangle2D anchor = .getLogicalAnchor2D();
        TextElement[] elem = getTextElements((float)anchor.getWidth(), graphics.getFontRenderContext(), graphics);
        if(elem == nullreturn;
        float textHeight = 0;
        for (int i = 0; i < elem.lengthi++) {
            textHeight += elem[i]. + elem[i].;
        }
        int valign = .getVerticalAlignment();
        double y0 = anchor.getY();
        switch (valign){
            case .:
            case .:
                y0 += .getMarginTop();
                break;
            case .:
                y0 += anchor.getHeight() - textHeight - .getMarginBottom();
                break;
            default:
            case .:
                float delta =  (float)anchor.getHeight() - textHeight - .getMarginTop() - .getMarginBottom();
                y0 += .getMarginTop()  + delta/2;
                break;
        }
        // Transform of text in flipped shapes is special.
        // At this point the flip and rotation transform is already applied
        // (see XSLFShape#applyTransform ), but we need to restore it to avoid painting "upside down".
        // See Bugzilla 54210.
        if(.getFlipVertical()){
            graphics.translate(anchor.getX(), anchor.getY() + anchor.getHeight());
            graphics.scale(1, -1);
            graphics.translate(-anchor.getX(), -anchor.getY());
            // text in vertically flipped shapes is rotated by 180 degrees
            double centerX = anchor.getX() + anchor.getWidth()/2;
            double centerY = anchor.getY() + anchor.getHeight()/2;
            graphics.translate(centerXcenterY);
            graphics.rotate(Math.toRadians(180));
            graphics.translate(-centerX, -centerY);
        }
        // Horizontal flipping applies only to shape outline and not to the text in the shape.
        // Applying flip second time restores the original not-flipped transform
        if(.getFlipHorizontal()){
            graphics.translate(anchor.getX() + anchor.getWidth(), anchor.getY());
            graphics.scale(-1, 1);
            graphics.translate(-anchor.getX() , -anchor.getY());
        }
        //finally draw the text fragments
        for (int i = 0; i < elem.lengthi++) {
            y0 += elem[i].;
            Point2D.Double pen = new Point2D.Double();
            pen.y = y0;
            switch (elem[i].) {
                default:
                case .:
                    pen.x = anchor.getX() + .getMarginLeft();
                    break;
                case .:
                    pen.x = anchor.getX() + .getMarginLeft() +
                            (anchor.getWidth() - elem[i]. - .getMarginLeft() - .getMarginRight()) / 2;
                    break;
                case .:
                    pen.x = anchor.getX() + .getMarginLeft() +
                            (anchor.getWidth() - elem[i]. - .getMarginLeft() - .getMarginRight());
                    break;
            }
            if(elem[i]. != null){
                graphics.drawString(elem[i]..getIterator(), (float)(pen.x + elem[i].), (float)pen.y);
            }
            AttributedCharacterIterator chIt = elem[i]..getIterator();
            if(chIt.getEndIndex() > chIt.getBeginIndex()) {
                graphics.drawString(chIt, (float)(pen.x + elem[i].), (float)pen.y);
            }
            y0 += elem[i].;
        }
        graphics.setTransform(tx);
    }
    public TextElement[] getTextElements(float textWidthFontRenderContext frc){
        return getTextElements(textWidthfrcnull);
    }
    
    public TextElement[] getTextElements(float textWidthFontRenderContext frcGraphics2D graphics){
        TextRun run = .getTextRun();
        if (run == nullreturn null;
        String text = run.getText();
        if (text == null || text.equals("")) return null;
        AttributedString at = getAttributedString(rungraphics);
        AttributedCharacterIterator it = at.getIterator();
        int paragraphStart = it.getBeginIndex();
        int paragraphEnd = it.getEndIndex();
        List<TextElementlines = new ArrayList<TextElement>();
        LineBreakMeasurer measurer = new LineBreakMeasurer(itfrc);
        measurer.setPosition(paragraphStart);
        while (measurer.getPosition() < paragraphEnd) {
            int startIndex = measurer.getPosition();
            int nextBreak = text.indexOf('\n'measurer.getPosition() + 1);
            boolean prStart = text.charAt(startIndex) == '\n';
            if(prStartmeasurer.setPosition(startIndex++);
            RichTextRun rt = run.getRichTextRunAt(startIndex == text.length() ? (startIndex-1) : startIndex);
            if(rt == null) {
                .log(.,  "RichTextRun not found at pos" + startIndex + "; text.length: " + text.length());
                break;
            }
            float wrappingWidth = textWidth - .getMarginLeft() - .getMarginRight();
            int bulletOffset = rt.getBulletOffset();
            int textOffset = rt.getTextOffset();
            int indent = rt.getIndentLevel();
            TextRulerAtom ruler = run.getTextRuler();
            if(ruler != null) {
                int bullet_val = ruler.getBulletOffsets()[indent]*./.;
                int text_val = ruler.getTextOffsets()[indent]*./.;
                if(bullet_val > text_val){
                    int a = bullet_val;
                    bullet_val = text_val;
                    text_val = a;
                }
                if(bullet_val != 0 ) bulletOffset = bullet_val;
                if(text_val != 0) textOffset = text_val;
            }
            if(bulletOffset > 0 || prStart || startIndex == 0) wrappingWidth -= textOffset;
            if (.getWordWrap() == .) {
                wrappingWidth = .getSheet().getSlideShow().getPageSize().;
            }
            TextLayout textLayout = measurer.nextLayout(wrappingWidth + 1,
                    nextBreak == -1 ? paragraphEnd : nextBreaktrue);
            if (textLayout == null) {
                textLayout = measurer.nextLayout(textWidth,
                    nextBreak == -1 ? paragraphEnd : nextBreakfalse);
            }
            if(textLayout == null){
                .log(."Failed to break text into lines: wrappingWidth: "+wrappingWidth+
                        "; text: " + rt.getText());
                measurer.setPosition(rt.getEndIndex());
                continue;
            }
            int endIndex = measurer.getPosition();
            float lineHeight = (float)textLayout.getBounds().getHeight();
            int linespacing = rt.getLineSpacing();
            if(linespacing == 0) linespacing = 100;
            TextElement el = new TextElement();
            if(linespacing >= 0){
                el.ascent = textLayout.getAscent()*linespacing/100;
            } else {
                el.ascent = -linespacing*./.;
            }
            el._align = rt.getAlignment();
            el.advance = textLayout.getAdvance();
            el._textOffset = textOffset;
            el._text = new AttributedString(itstartIndexendIndex);
            el.textStartIndex = startIndex;
            el.textEndIndex = endIndex;
            if (prStart){
                int sp = rt.getSpaceBefore();
                float spaceBefore;
                if(sp >= 0){
                    spaceBefore = lineHeight * sp/100;
                } else {
                    spaceBefore = -sp*./.;
                }
                el.ascent += spaceBefore;
            }
            float descent;
            if(linespacing >= 0){
                descent = (textLayout.getDescent() + textLayout.getLeading())*linespacing/100;
            } else {
                descent = -linespacing*./.;
            }
            if (prStart){
                int sp = rt.getSpaceAfter();
                float spaceAfter;
                if(sp >= 0){
                    spaceAfter = lineHeight * sp/100;
                } else {
                    spaceAfter = -sp*./.;
                }
                el.ascent += spaceAfter;
            }
            el.descent = descent;
            if(rt.isBullet() && (prStart || startIndex == 0)){
                it.setIndex(startIndex);
                AttributedString bat = new AttributedString(Character.toString(rt.getBulletChar()));
                Color clr = rt.getBulletColor();
                if (clr != nullbat.addAttribute(.clr);
                else bat.addAttribute(.it.getAttribute(.));
                int fontIdx = rt.getBulletFont();
                if(fontIdx == -1) fontIdx = rt.getFontIndex();
                PPFont bulletFont = .getSheet().getSlideShow().getFont(fontIdx);
                bat.addAttribute(.bulletFont.getFontName());
                int bulletSize = rt.getBulletSize();
                int fontSize = rt.getFontSize();
                if(bulletSize != -1) fontSize = Math.round(fontSize*bulletSize*0.01f);
                bat.addAttribute(.new Float(fontSize));
                if(!new Font(bulletFont.getFontName(), ., 1).canDisplay(rt.getBulletChar())){
                    bat.addAttribute(."Arial");
                    bat = new AttributedString("" + bat.getIterator().getAttributes());
                }
                if(text.substring(startIndexendIndex).length() > 1){
                    el._bullet = bat;
                    el._bulletOffset = bulletOffset;
                }
            }
            lines.add(el);
        }
        //finally draw the text fragments
        TextElement[] elems = new TextElement[lines.size()];
        return lines.toArray(elems);
    }
    public static class TextElement {
        public AttributedString _text;
        public int _textOffset;
        public AttributedString _bullet;
        public int _bulletOffset;
        public int _align;
        public float ascentdescent;
        public float advance;
        public int textStartIndextextEndIndex;
    }
    public static class Key extends RenderingHints.Key {
      String description;
      public Key(int paramIntString paramString) {
        super(paramInt);
        this. = paramString;
      }
      public final int getIndex() {
        return intKey();
      }
      public final String toString() {
        return this.;
      }
      public boolean isCompatibleValue(Object paramObject) {
        return true;
      }
    }
New to GrepCode? Check out our FAQ X