Package org.librebiz.pureport.context

Source Code of org.librebiz.pureport.context.TextBuilder$TextBuilderIterator

/*
    Pureport, a report generator for Java
    Copyright (C) 2011  Maurice Perry <maurice@perry.ch>

    Project Web Site: http://code.google.com/p/pureport/

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
package org.librebiz.pureport.context;

import java.awt.Graphics2D;
import java.awt.font.FontRenderContext;
import java.awt.font.LineBreakMeasurer;
import java.awt.font.TextAttribute;
import java.awt.font.TextLayout;
import java.io.Serializable;
import java.text.AttributedCharacterIterator;
import java.text.AttributedCharacterIterator.Attribute;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class TextBuilder implements Serializable {
    public static final int ALIGN_CENTER = 0;
    public static final int ALIGN_LEFT = 1;
    public static final int ALIGN_RIGHT = 2;
    public static final int ALIGN_JUSTIFY = 3;

    private StringBuilder charsBuffer = new StringBuilder();
    private List<Map<Attribute,Object>> attrsBuffer
            = new ArrayList<Map<Attribute,Object>>();
    private Map<Attribute,Object> attributes = new HashMap<Attribute,Object>();
    private boolean hasChanged = false;
    private double height;

    public Object getAttribute(TextAttribute key) {
        return attributes.get(key);
    }

    public void setAttribute(TextAttribute key, Object value) {
        if (!hasChanged) {
            attributes = new HashMap(attributes);
            hasChanged = true;
        }
        if (value == null) {
            attributes.remove(key);
        } else {
            attributes.put(key, value);
        }
    }

    public int length() {
        return charsBuffer.length();
    }

    public char getChar(int ix) {
        return charsBuffer.charAt(ix);
    }

    public Map getAttributes(int ix) {
        return (Map)attrsBuffer.get(ix);
    }

    public void append(char c) {
        charsBuffer.append(c);
        attrsBuffer.add(attributes);
        hasChanged = false;
    }

    public void append(char chars[]) {
        append(chars, 0, chars.length);
    }

    public void append(char chars[], int offs, int len) {
        int end = offs+len;
        for (int i = offs; i < end; ++i) {
            append(chars[i]);
        }
    }

    public void append(String s) {
        append(s.toCharArray());
    }

    public void append(boolean value) {
        append(Boolean.toString(value));
    }

    public void append(int value) {
        append(Integer.toString(value));
    }

    public void append(long value) {
        append(Long.toString(value));
    }

    public void append(double value) {
        append(Double.toString(value));
    }

    public void append(Object obj) {
        append("" + obj);
    }

    public void delete(int start, int end) {
        charsBuffer.delete(start, end);
        for (int i = start; i < end; ++i) {
            attrsBuffer.remove(i);
        }
    }

    public void insert(int ix, char c, Map attrs) {
        charsBuffer.insert(ix, c);
        attrsBuffer.add(ix, attrs);
    }

    public void insert(int ix, char chars[], Map attrs) {
        insert(ix, chars, 0, chars.length, attrs);
    }

    public void insert(int ix, char chars[], int offs, int len, Map attrs) {
        int end = offs+len;
        for (int i = offs; i < end; ++i) {
            insert(ix, chars[i], attrs);
            ++ix;
        }
    }

    public void insert(int ix, String s, Map attrs) {
        insert(ix, s.toCharArray(), attrs);
    }

    public void insert(int ix, boolean value, Map attrs) {
        insert(ix, Boolean.toString(value), attrs);
    }

    public void insert(int ix, int value, Map attrs) {
        insert(ix, Integer.toString(value), attrs);
    }

    public void insert(int ix, long value, Map attrs) {
        insert(ix, Long.toString(value), attrs);
    }

    public void insert(int ix, double value, Map attrs) {
        insert(ix, Double.toString(value), attrs);
    }

    public void insert(int ix, Object obj, Map attrs) {
        insert(ix, "" + obj, attrs);
    }

    public AttributedCharacterIterator getIterator() {
        return new TextBuilderIterator();
    }

    public void format(FontRenderContext frc, double width) {
        height = 0;
        if (length() > 0) {
            LineBreakMeasurer lbm = new LineBreakMeasurer(getIterator(), frc);
            if (lbm.getPosition() < length()) {
                while (true) {
                    TextLayout layout = lbm.nextLayout((float)width);
                    height += layout.getAscent() + layout.getDescent();
                    if (lbm.getPosition() >= length()) {
                        break;
                    }
                    height += layout.getLeading();
                }
            }
        }
    }

    public double getHeight() {
        return height;
    }

    public void draw(Graphics2D g, double x, double y, double width, int align) {
        if (length() > 0) {
            LineBreakMeasurer lbm = new LineBreakMeasurer(getIterator(),
                    g.getFontRenderContext());
            if (lbm.getPosition() < length()) {
                while (true) {
                    TextLayout layout = lbm.nextLayout((float)width);
                    double xx = x;
                    if (align == ALIGN_RIGHT) {
                        xx += width-layout.getAdvance();
                    } else if (align == ALIGN_CENTER) {
                        xx += (width-layout.getAdvance())/2;
                    } else if (align == ALIGN_JUSTIFY && lbm.getPosition() < length()) {
                        layout = layout.getJustifiedLayout((float)width);
                    }
                    y += layout.getAscent();
                    layout.draw(g, (float)xx, (float)y);
                    y += layout.getDescent();
                    if (lbm.getPosition() >= length()) {
                        break;
                    }
                    y += layout.getLeading();
                }
            }
        }
    }

    private static boolean sameAttrs(Set keys, Map attrs1, Map attrs2) {
        if (attrs1 != attrs2) {
            for (Iterator it = keys.iterator(); it.hasNext(); ) {
                Object key = it.next();
                if (!same(attrs1.get(key), attrs2.get(key))) {
                    return false;
                }
            }
        }
        return true;
    }

    private static boolean sameAttr(Object key, Map attrs1, Map attrs2) {
        return attrs1 == attrs2 || same(attrs1.get(key), attrs2.get(key));
    }

    private static boolean same(Object a, Object b) {
        if (a == b) {
            return true;
        } else if (a == null || b == null) {
            return false;
        } else {
            return a.equals(b);
        }
    }

    private class TextBuilderIterator implements AttributedCharacterIterator {
        private int index;

        private TextBuilderIterator() {
            this(0);
        }

        private TextBuilderIterator(int index) {
            this.index = index;
        }

        @Override
        public int getRunStart() {
            Map attrs = getAttrs();
            int ix = index;
            do {
                --ix;
            } while (ix > getBeginIndex() && getAttrs(ix) == attrs);
            return ix+1;
        }

        @Override
        public int getRunStart(Set keys) {
            Map attrs = getAttrs();
            int ix = index;
            do {
                --ix;
            } while (ix > getBeginIndex() && sameAttrs(keys, getAttrs(ix), attrs));
            return ix+1;
        }

        @Override
        public int getRunStart(Attribute key) {
            Map attrs = getAttrs();
            int ix = index;
            do {
                --ix;
            } while (ix > getBeginIndex() && sameAttr(key, getAttrs(ix-1), attrs));
            return ix+1;
        }

        @Override
        public int getRunLimit() {
            Map attrs = getAttrs();
            int ix = index;
            do {
                ++ix;
            } while (ix < getEndIndex() && getAttrs(ix) == attrs);
            return ix;
        }

        @Override
        public int getRunLimit(Set keys) {
            Map attrs = getAttrs();
            int ix = index;
            do {
                ++ix;
            } while (ix < getEndIndex() && sameAttrs(keys, getAttrs(ix), attrs));
            return ix;
        }

        @Override
        public int getRunLimit(Attribute key) {
            Map attrs = getAttrs();
            int ix = index;
            do {
                ++ix;
            } while (ix < getEndIndex() && sameAttr(key, getAttrs(ix), attrs));
            return ix;
        }

        public Map<Attribute,Object> getAttributes() {
            Map<Attribute,Object> attrs = getAttrs();
            Object attr = attrs.get(TextAttribute.CHAR_REPLACEMENT);
            if (attr instanceof ImageAttribute) {
                ImageAttribute iattr = (ImageAttribute)attr;
                attrs = new HashMap<Attribute,Object>(attrs);
                attrs.put(TextAttribute.CHAR_REPLACEMENT,
                        iattr.toGraphicAttribute());
            }
            return attrs;
        }

        private Map<Attribute,Object> getAttrs() {
            if (index < getBeginIndex() || index >= getEndIndex()) {
                return Collections.EMPTY_MAP;
            }
            return attrsBuffer.get(index);
        }

        private Map<Attribute,Object> getAttrs(int ix) {
            return attrsBuffer.get(ix);
        }

        @Override
        public Set getAllAttributeKeys() {
            return getAttrs().keySet();
        }

        @Override
        public Object getAttribute(Attribute key) {
            return getAttrs().get(key);
        }

        @Override
        public char current() {
            if (index < getBeginIndex() || index >= getEndIndex()) {
                return DONE;
            }
            return charsBuffer.charAt(index);
        }

        @Override
        public char first() {
            index = getBeginIndex();
            return current();
        }

        @Override
        public char last() {
            index = getEndIndex()-1;
            if (index < getBeginIndex()) {
                index = getBeginIndex();
            }
            return current();
        }

        @Override
        public char next() {
            if (index == getEndIndex()) {
                return DONE;
            }
            ++index;
            return current();
        }

        @Override
        public char previous() {
            if (index == getBeginIndex()) {
                return DONE;
            }
            --index;
            return current();
        }

        @Override
        public int getBeginIndex() {
            return 0;
        }

        @Override
        public int getEndIndex() {
            return charsBuffer.length();
        }

        @Override
        public int getIndex() {
            return index;
        }

        @Override
        public char setIndex(int newValue) {
            if (newValue < getBeginIndex() || newValue > getEndIndex()) {
                throw new IllegalArgumentException("Invalid index " + newValue);
            }
            index = newValue;
            return index >= charsBuffer.length() ? DONE : charsBuffer.charAt(index);
        }

        @Override
        public Object clone() {
            return new TextBuilderIterator(index);
        }
    }
}
TOP

Related Classes of org.librebiz.pureport.context.TextBuilder$TextBuilderIterator

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.