All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.adobe.xfa.text.DispMap Maven / Gradle / Ivy

There is a newer version: 2024.11.18751.20241128T090041Z-241100
Show newest version
package com.adobe.xfa.text;

import com.adobe.xfa.ut.Storage;

/**
 * @exclude from published api.
 */

class DispMap {
	private final Storage moMap = new Storage();

	DispMap () {
	}

	int findItem (int nItemIndex) {
		int nMapIndex = search (nItemIndex);

		if ((nMapIndex < moMap.size()) && (getItem(nMapIndex).getMapIndex() == nItemIndex)) {
			return nMapIndex;
		}

		while (nMapIndex > 0) {
			nMapIndex--;
			DispMapItem oItem = getItem (nMapIndex);
			if ((nItemIndex >= oItem.getMapIndex())
			 && (nItemIndex <= (oItem.getMapIndex() + oItem.getMapLength()))) {
				return nMapIndex;
			}
		}

		return moMap.size();
	}

	boolean isValidMapIndex (int nMapIndex) {
		return nMapIndex < moMap.size();
	}

	int add (DispMapItem delegate, int nIndex, int nLength) {
		return add (delegate.cloneMapItem (nIndex, nLength));
	}

	int add (DispMapItem delegate, int nIndex) {
		return add (delegate, nIndex, 1);
	}

	int add (DispMapItem oAdd) {
		int nSlot = moMap.size();

		if ((moMap.size() > 0) && (oAdd.getMapIndex() < last().getMapIndex())) {
			int nEnd = oAdd.getMapIndex() + oAdd.getMapLength();
			nSlot = search (oAdd.getMapIndex());
			while (nSlot < moMap.size()) {
				int nSlotIndex = getItem(nSlot).getMapIndex();
				if (oAdd.getMapIndex() != nSlotIndex) {
					break;
				}
				int nSlotEnd = nSlotIndex + getItem(nSlot).getMapLength();
				if (nEnd < nSlotEnd) {
					break;
				}
				nSlot++;
			}
		}

		moMap.add (nSlot, oAdd);

		return nSlot;
	}

	void removeRange (int nCharIndex, int nCharLength /*, SplitFunc pfnSplit */) {	// TODO:
// Removes data from a map corresponding to a given character range and
// optionally splits the item containing the removal (it it is contained
// in a single item).
		int nMapIndex = findItem (nCharIndex);
		if (nMapIndex >= moMap.size()) {
			return;
		}

// The bStarted flag is to handle the (common) case where the removal
// starts in the middle of a map item.	The loop iterates once for each
// item directly affected by the removal.
		boolean bStarted = getItem(nMapIndex).getMapIndex() == nCharIndex;
		int nLeft = nCharLength;

		while (nLeft > 0) {
			DispMapItem poItem = getItem (nMapIndex);
			int nAvail = poItem.getMapLength();
			if (! bStarted) {
				nAvail -= nCharIndex - poItem.getMapIndex();
			}
			int nRemove = nLeft; // how much to remove this time

			if (nRemove > nAvail) {
				nRemove = nAvail;
			}
			int nRemaining = poItem.getMapLength() - nRemove;

// If this map item is completely gutted, get rid of it, rather than
// carrying an empty one.
			if ((nRemaining == 0) && (moMap.size() > 1)) {
				moMap.remove (nMapIndex);
			}

			else {
// Otherwise, this item still maps to some characters and is the subject
// of a partial removal.

// Removing all it has available: this is removing from the given
// character index to the end of the item.	Simply truncate its length.
				if (nRemove == nAvail) {
					poItem.setMapLength (nRemaining);
				}

// If started, we're removing from the start of the item up to the end of
// the removal range.  If a split function was provided, use it to
// indicate the removal.  Then update the index and length to account for
// the removed characters.
				else if (bStarted) {
//					if (pfnSplit != null) {				// TODO:
//						(pfnSplit) (poItem, nRemove);
//					}
					poItem.setMapIndex (nCharIndex);
					poItem.setMapLength (nRemaining);
				}

// Otherwise, it is a removal from the middle of an item.  If there is no
// split function, simply set its new length to account for the removed
// characters.
				else /* if (pfnSplit == null) */ {		// TODO:
					poItem.setMapLength (nRemaining);
				}

// Removal from the middle with a split: Need to create a new item
// corresponding to the second part of the split item, and adjust this
// item's length to just the beginning part.  Also increment map index to
// account for the new item created.
//				else {									// TODO:
//					int nBefore = nCharIndex - poItem.getMapIndex();
//					int nAfter = nRemaining - nBefore;
//					T oSplit (poItem);
//					(pfnSplit) (oSplit, nBefore + nRemove);
//					Add (oSplit, poItem.getMapIndex() + nBefore, nAfter);
//					poItem.setMapLength (nBefore);
//					nMapIndex++;
//				}

// In all cases where the item isn't removed entirely, need to increment
// the map index (which is used in the subsequent loop), because we're
// done with this item.
				nMapIndex++;
			}

			nLeft -= nRemove;
			bStarted = true;
		}

// Update the start index of all items that come after those directly
// affected by the removal.
		for (; nMapIndex < moMap.size(); nMapIndex++) {
			DispMapItem poItem = getItem(nMapIndex);
			poItem.setMapIndex (poItem.getMapIndex() - nCharLength);
		}
	}

	void insertMap (DispMap oSourceMap, int nCharIndex, int nCharLength /*, SplitFunc pfnSplit */) {	// TODO:
		int nMapIndex = findItem (nCharIndex);
		if (nMapIndex >= moMap.size()) {
			return;
		}

		int i;
		DispMapItem poItem = getItem (nMapIndex);

		if (nCharIndex != poItem.getMapIndex()) {
			int nSplitFirst = nCharIndex - poItem.getMapIndex();
			int nSplitSecond = poItem.getMapLength() - nSplitFirst;
			poItem.setMapLength (nSplitFirst);
//			if (pfnSplit == null) {		// TODO:
				add (poItem, nCharIndex, nSplitSecond);
//			} else {
//				T oNew (poItem);
//				(pfnSplit) (oNew, nSplitFirst);
//				Add (oNew, nCharIndex, nSplitSecond);
//			}
			nMapIndex++;
		}

		for (i = nMapIndex; i < moMap.size(); i++) {
			poItem = getItem(i);
			poItem.setMapIndex (poItem.getMapIndex() + nCharLength);
		}

		for (i = 0; i < oSourceMap.size(); i++) {
			poItem = oSourceMap.getItem(i);
			add (poItem, nCharIndex, poItem.getMapLength());
			nCharIndex += poItem.getMapLength();
		}
	}

	void empty () {
		moMap.clear();
	}

	int size () {
		return moMap.size();
	}

	DispMapItem last () {
		return getItem (moMap.size() - 1);
	}

	DispMapItem getItem (int index) {
		return moMap.get (index);
	}

	void preAlloc (int nSize, boolean bPreserve) {
		if (nSize > moMap.size()) {
			moMap.ensureCapacity (nSize);
		}
	}

	private int search (int nItemIndex) {
		int nLow = 0;
		int nHigh = moMap.size();
		while (nLow < nHigh) {
			int nSplit = (nLow + nHigh) / 2;
			int nTest = getItem(nSplit).getMapIndex();
			if (nItemIndex < nTest) {
				nHigh = nSplit;
			} else if (nItemIndex > nTest) {
				nLow = nSplit + 1;
			} else {
				nLow = nHigh = nSplit;
			}
		}

		for (; nLow > 0; nLow--) {
			if (getItem(nLow-1).getMapIndex() != nItemIndex) {
				break;
			}
		}

		return nLow;
	}
}

class DispMapSet {
	int[] mpcCharData;
	int[] mpeBreakData;
	int mnCharCount;
	int mnCharMax;

	DispMap moEmbedMap = new DispMap();		// TODO: could delay creation of embed and glyph loc maps
	DispMap moGlyphLocMap = new DispMap();
	DispMap moPosnMap = new DispMap();
	DispMap moRunMap = new DispMap();

	Storage moGlyphs;

	DispMapSet () {
	}

	void clear () {
		mnCharCount = 0;

//		for (int i = 0; i < moPositionMap.size(); i++) {
//			moPositionMap[i].associate (null);
//		}
//		for (i = 0; i < moRunMap.size(); i++) {
//			moRunMap[i].setAttr (null);
//		}

		moEmbedMap.empty();
		moGlyphLocMap.empty();
		moPosnMap.empty();
		moRunMap.empty();
		moGlyphs.clear();
	}

	int getChar (int nIndex) {
		return mpcCharData[nIndex];
	}

	int[] getCharArray () {
		return mpcCharData;
	}

	int getBreakData (int nIndex) {
		return mpeBreakData[nIndex];
	}

	int[] getBreakArray () {
		return mpeBreakData;
	}

	void addChar (int c, int eData) {
		setChar (mnCharCount++, c, eData);
	}

	void setChar (int nIndex, int c, int eData) {
		assert (nIndex < mnCharMax);
		mpcCharData[nIndex] = c;
		mpeBreakData[nIndex] = eData;
	}

	void setBreakData (int nIndex, int eData) {
		mpeBreakData[nIndex] = eData;
	}

	void preAllocChars (int nChars, boolean bPreserve) {
		if (nChars > mnCharMax) {
			int[] newChar = new int [nChars];
			int[] newBreak = new int [nChars];
			if (bPreserve) {
				for (int i = 0; i < mnCharCount; i++) {
					newChar[i] = mpcCharData[i];
					newBreak[i] = mpeBreakData[i];
				}
			}
			mpcCharData = newChar;
			mpeBreakData = newBreak;
			mnCharMax = nChars;
		}

		if (bPreserve) {
			mnCharCount = nChars;
		} else {
			mnCharCount = 0;
		}
	}

	void preAllocChars (int nChars) {
		preAllocChars (nChars, false);
	}

	Glyph getGlyph (int index) {
		return moGlyphs.get (index);
	}

	int getEmbedCount () {
		return moEmbedMap.size();
	}

	DispEmbed getEmbed (int index) {
		return (DispEmbed) moEmbedMap.getItem (index);
	}

	int getGlyphLocCount () {
		return moGlyphLocMap.size();
	}

	GlyphLoc getGlyphLoc (int index) {
		return (GlyphLoc) moGlyphLocMap.getItem (index);
	}

	void preAllocGlyphs (int nGlyphs, boolean bAllocGlyphLocs, boolean bPreserve) {
		if (moGlyphs == null) {
			moGlyphs = new Storage();
		}
		moGlyphs.ensureCapacity (nGlyphs);
		if (bAllocGlyphLocs) {
			moGlyphLocMap.preAlloc (nGlyphs, bPreserve);
		}
	}

	void preAllocGlyphs (int nGlyphs, boolean bAllocGlyphLocs) {
		preAllocGlyphs (nGlyphs, bAllocGlyphLocs, false);
	}

	int getPositionCount () {
		return moPosnMap.size();
	}

	DispPosn getPosition (int index) {
		return (DispPosn) moPosnMap.getItem (index);
	}

	int getRunCount () {
		return moRunMap.size();
	}

	DispRun getRun (int index) {
		return (DispRun) moRunMap.getItem (index);
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy