textrun.java

来自「EXCEL read and write」· Java 代码 · 共 718 行 · 第 1/2 页

JAVA
718
字号
/* ====================================================================   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.util.LinkedList;import java.util.Vector;import java.util.List;import org.apache.poi.hslf.model.textproperties.TextPropCollection;import org.apache.poi.hslf.record.*;import org.apache.poi.hslf.usermodel.RichTextRun;import org.apache.poi.hslf.usermodel.SlideShow;import org.apache.poi.util.StringUtil;/** * This class represents a run of text in a powerpoint document. That *  run could be text on a sheet, or text in a note. *  It is only a very basic class for now * * @author Nick Burch */public class TextRun{	// Note: These fields are protected to help with unit testing	//   Other classes shouldn't really go playing with them!	protected TextHeaderAtom _headerAtom;	protected TextBytesAtom  _byteAtom;	protected TextCharsAtom  _charAtom;	protected StyleTextPropAtom _styleAtom;    protected TextRulerAtom _ruler;    protected boolean _isUnicode;	protected RichTextRun[] _rtRuns;	private SlideShow slideShow;    private Sheet sheet;    private int shapeId;    private int slwtIndex; //position in the owning SlideListWithText    /**     * all text run records that follow TextHeaderAtom.     * (there can be misc InteractiveInfo, TxInteractiveInfo and other records)     */    protected Record[] _records;	/**	* Constructs a Text Run from a Unicode text block	*	* @param tha the TextHeaderAtom that defines what's what	* @param tca the TextCharsAtom containing the text	* @param sta the StyleTextPropAtom which defines the character stylings	*/	public TextRun(TextHeaderAtom tha, TextCharsAtom tca, StyleTextPropAtom sta) {		this(tha,null,tca,sta);	}	/**	* Constructs a Text Run from a Ascii text block	*	* @param tha the TextHeaderAtom that defines what's what	* @param tba the TextBytesAtom containing the text	* @param sta the StyleTextPropAtom which defines the character stylings	*/	public TextRun(TextHeaderAtom tha, TextBytesAtom tba, StyleTextPropAtom sta) {		this(tha,tba,null,sta);	}		/**	 * Internal constructor and initializer	 */	private TextRun(TextHeaderAtom tha, TextBytesAtom tba, TextCharsAtom tca, StyleTextPropAtom sta) {		_headerAtom = tha;		_styleAtom = sta;		if(tba != null) {			_byteAtom = tba;			_isUnicode = false;		} else {			_charAtom = tca;			_isUnicode = true;		}		String runRawText = getText();				// Figure out the rich text runs		LinkedList pStyles = new LinkedList();		LinkedList cStyles = new LinkedList();		if(_styleAtom != null) {			// Get the style atom to grok itself			_styleAtom.setParentTextSize(runRawText.length());			pStyles = _styleAtom.getParagraphStyles();			cStyles = _styleAtom.getCharacterStyles();		}        buildRichTextRuns(pStyles, cStyles, runRawText);	}		public void buildRichTextRuns(LinkedList pStyles, LinkedList cStyles, String runRawText){        // Handle case of no current style, with a default        if(pStyles.size() == 0 || cStyles.size() == 0) {            _rtRuns = new RichTextRun[1];            _rtRuns[0] = new RichTextRun(this, 0, runRawText.length());        } else {            // Build up Rich Text Runs, one for each            //  character/paragraph style pair            Vector rtrs = new Vector();            int pos = 0;            int curP = 0;            int curC = 0;            int pLenRemain = -1;            int cLenRemain = -1;            // Build one for each run with the same style            while(pos <= runRawText.length() && curP < pStyles.size() && curC < cStyles.size()) {                // Get the Props to use                TextPropCollection pProps = (TextPropCollection)pStyles.get(curP);                TextPropCollection cProps = (TextPropCollection)cStyles.get(curC);                int pLen = pProps.getCharactersCovered();                int cLen = cProps.getCharactersCovered();                // Handle new pass                boolean freshSet = false;                if(pLenRemain == -1 && cLenRemain == -1) { freshSet = true; }                if(pLenRemain == -1) { pLenRemain = pLen; }                if(cLenRemain == -1) { cLenRemain = cLen; }                // So we know how to build the eventual run                int runLen = -1;                boolean pShared = false;                boolean cShared = false;                // Same size, new styles - neither shared                if(pLen == cLen && freshSet) {                    runLen = cLen;                    pShared = false;                    cShared = false;                    curP++;                    curC++;                    pLenRemain = -1;                    cLenRemain = -1;                } else {                    // Some sharing                    // See if we are already in a shared block                    if(pLenRemain < pLen) {                        // Existing shared p block                        pShared = true;                        // Do we end with the c block, or either side of it?                        if(pLenRemain == cLenRemain) {                            // We end at the same time                            cShared = false;                            runLen = pLenRemain;                            curP++;                            curC++;                            pLenRemain = -1;                            cLenRemain = -1;                        } else if(pLenRemain < cLenRemain) {                            // We end before the c block                            cShared = true;                            runLen = pLenRemain;                            curP++;                            cLenRemain -= pLenRemain;                            pLenRemain = -1;                        } else {                            // We end after the c block                            cShared = false;                            runLen = cLenRemain;                            curC++;                            pLenRemain -= cLenRemain;                            cLenRemain = -1;                        }                    } else if(cLenRemain < cLen) {                        // Existing shared c block                        cShared = true;                        // Do we end with the p block, or either side of it?                        if(pLenRemain == cLenRemain) {                            // We end at the same time                            pShared = false;                            runLen = cLenRemain;                            curP++;                            curC++;                            pLenRemain = -1;                            cLenRemain = -1;                        } else if(cLenRemain < pLenRemain) {                            // We end before the p block                            pShared = true;                            runLen = cLenRemain;                            curC++;                            pLenRemain -= cLenRemain;                            cLenRemain = -1;                        } else {                            // We end after the p block                            pShared = false;                            runLen = pLenRemain;                            curP++;                            cLenRemain -= pLenRemain;                            pLenRemain = -1;                        }                    } else {                        // Start of a shared block                        if(pLenRemain < cLenRemain) {                            // Shared c block                            pShared = false;                            cShared = true;                            runLen = pLenRemain;                            curP++;                            cLenRemain -= pLenRemain;                            pLenRemain = -1;                        } else {                            // Shared p block                            pShared = true;                            cShared = false;                            runLen = cLenRemain;                            curC++;                            pLenRemain -= cLenRemain;                            cLenRemain = -1;                        }                    }                }                // Wind on                int prevPos = pos;                pos += runLen;                // Adjust for end-of-run extra 1 length                if(pos > runRawText.length()) {                    runLen--;                }                // Save                RichTextRun rtr = new RichTextRun(this, prevPos, runLen, pProps, cProps, pShared, cShared);                rtrs.add(rtr);            }            // Build the array            _rtRuns = new RichTextRun[rtrs.size()];            rtrs.copyInto(_rtRuns);        }    }    // Update methods follow		/**	 * Adds the supplied text onto the end of the TextRun, 	 *  creating a new RichTextRun (returned) for it to	 *  sit in. 	 * In many cases, before calling this, you'll want to add	 *  a newline onto the end of your last RichTextRun	 */	public RichTextRun appendText(String s) {		// We will need a StyleTextProp atom		ensureStyleAtomPresent();				// First up, append the text to the 		//  underlying text atom		int oldSize = getRawText().length();		storeText(				getRawText() + s		);				// If either of the previous styles overran		//  the text by one, we need to shuffle that		//  extra character onto the new ones		int pOverRun = _styleAtom.getParagraphTextLengthCovered() - oldSize;		int cOverRun = _styleAtom.getCharacterTextLengthCovered() - oldSize;		if(pOverRun > 0) {			TextPropCollection tpc = (TextPropCollection)				_styleAtom.getParagraphStyles().getLast();			tpc.updateTextSize(					tpc.getCharactersCovered() - pOverRun			);		}		if(cOverRun > 0) {			TextPropCollection tpc = (TextPropCollection)				_styleAtom.getCharacterStyles().getLast();			tpc.updateTextSize(					tpc.getCharactersCovered() - cOverRun			);		}				// Next, add the styles for its paragraph and characters		TextPropCollection newPTP =			_styleAtom.addParagraphTextPropCollection(s.length()+pOverRun);		TextPropCollection newCTP =			_styleAtom.addCharacterTextPropCollection(s.length()+cOverRun);				// Now, create the new RichTextRun		RichTextRun nr = new RichTextRun(				this, oldSize, s.length(), 				newPTP, newCTP, false, false		);				// Add the new RichTextRun onto our list		RichTextRun[] newRuns = new RichTextRun[_rtRuns.length+1];		System.arraycopy(_rtRuns, 0, newRuns, 0, _rtRuns.length);		newRuns[newRuns.length-1] = nr;		_rtRuns = newRuns;				// And return the new run to the caller		return nr;	}	/**	 * Saves the given string to the records. Doesn't 	 *  touch the stylings. 	 */	private void storeText(String s) {		// Remove a single trailing \r, as there is an implicit one at the		//  end of every record		if(s.endsWith("\r")) {			s = s.substring(0, s.length()-1);		}				// Store in the appropriate record		if(_isUnicode) {			// The atom can safely convert to unicode			_charAtom.setText(s);		} else {			// Will it fit in a 8 bit atom?			boolean hasMultibyte = StringUtil.hasMultibyte(s);			if(! hasMultibyte) {				// Fine to go into 8 bit atom				byte[] text = new byte[s.length()];				StringUtil.putCompressedUnicode(s,text,0);				_byteAtom.setText(text);			} else {				// Need to swap a TextBytesAtom for a TextCharsAtom								// Build the new TextCharsAtom				_charAtom = new TextCharsAtom();				_charAtom.setText(s);								// Use the TextHeaderAtom to do the swap on the parent				RecordContainer parent = _headerAtom.getParentRecord();				Record[] cr = parent.getChildRecords();				for(int i=0; i<cr.length; i++) {					// Look for TextBytesAtom					if(cr[i].equals(_byteAtom)) {						// Found it, so replace, then all done						cr[i] = _charAtom;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?