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

com.adobe.xfa.gfx.GFXMappingList Maven / Gradle / Ivy

There is a newer version: 2024.11.18598.20241113T125352Z-241000
Show newest version
package com.adobe.xfa.gfx;

import java.util.Collections;
import java.util.Comparator;

import com.adobe.xfa.ut.FindBugsSuppress;
import com.adobe.xfa.ut.Storage;

/**
 * A mapping list represents the complete set of mappings for some set
 * of glyphs and corresponding Unicode characters.	The mapping list
 * does not store Unicode character values nor Glyph IDs; instead it
 * stores simply indexes.  The caller must maintain its character and
 * glyph arrays separately.
 * 

* The mapping list is made up of individual mappings. Each mapping * describes the smallest indivisible relationship between one or more * characters and one or more glyphs. For example, a mapping list that * describes a simple 1:1 relationship between N left-to-right * characters and their corresponding N glyphs would contain N * individual mappings. *

*

* Character indexes and lengths refer to actual Unicode characters * stored elsewhere by the application. If it chooses to use class * String to store Unicode characters, it needs to be aware that these * indexes are not the same as the UTF-8 byte indexes prevalent in many * String method signatures. Fortunately, that class also provides * Unicode character iteration methods. *

*

* Both Unicode character indexes and glyph indexes start at zero. *

* @exclude from published api. */ public class GFXMappingList { public final static int MAPPING_ERR_CHAR_OVERLAP = 0; // TODO: error handling public final static int MAPPING_ERR_CHAR_UNMAPPED = 1; public final static int MAPPING_ERR_CHAR_MAP_RANGE = 2; public final static int MAPPING_ERR_GLYPH_OVERLAP = 3; public final static int MAPPING_ERR_GLYPH_UNMAPPED = 4; public final static int MAPPING_ERR_GLYPH_MAP_RANGE = 5; private final Storage moMappings = new Storage(); /** * Default constructor. *

* Constructs a mapping list that is initially empty of any mappings. */ public GFXMappingList () { } /** * Constructor that initializes the mapping list. *

* The caller can provide a size hint to reduce the number of * reallocations that occur in building the mapping. In addition, the * caller can request an automatic mapuseful if the text is simple 1:1 * left-to-right Latin, with no substitutions. * @param nSizeHint - Size to pre-allocate the internal list of * mappings. This can be larger or smaller than the eventual number of * mappings; the implementation will not use excess space, and will * reallocate if necessary when mappings are added. * @param bAutoMap - If true, the mapping list is initialized to * represent a simple 1:1 left-to-right Latin mapping, with no * substitutions. The size hint indicates the number of mappings * required. */ public GFXMappingList (int nSizeHint, boolean bAutoMap) { if (bAutoMap) { autoMap (nSizeHint); } else { moMappings.ensureCapacity (nSizeHint); } } public GFXMappingList (int nSizeHint) { this (nSizeHint, false); } public GFXMappingList (GFXMappingList source) { copyFrom (source); } /** * Reset the mapping list to its initial state. *

* The client typically calls this method after consuming the contents * of a mapping list, if it wishes to reuse the object instance. There * is no harm in calling Reset() repeatedly or calling it on a * just-created mapping list object. */ public void reset () { moMappings.setSize (0); } /** * Repopulate the mapping list with a simple Latin-based 1:1 LTR * mapping. *

* This is a convenience method that maps glyphs to characters 1:1 from * left to right. Any previous contents of the mapping list are first * removed. * @param nMappings - Number of 1:1 mappings to create. */ public void autoMap (int nMappings) { moMappings.setSize (nMappings); for (int i = 0; i < nMappings; i++) { moMappings.set (i, new GFXMapping (i, i)); } } /** * Add one character/glyph mapping to the line. This overload allows * the caller to add a single mapping to the list, with complete control * over the contents of that mapping. For more information, see the * documentation for class GFXMapping. * @param oMapping - Mapping to add to the list. */ public void addMapping (GFXMapping oMapping) { moMappings.add (oMapping); } /** * Add one character/glyph mapping to the line. *

* This is a convenience method that eliminates the need to create a * GFXMapping object, but does not allow for the rare case of disjoint * character or glyph ranges. *

*

* The client specifies the mapping in terms of four parameters * identifying both a sequential run of characters and a sequential run * of glyphs. Given the parameter names listed in the method * declaration, the mapping is interpreted as the nCharLength characters * in the Unicode text, starting at index nCharIndex, map to the * nGlyphLength glyphs in the rendering starting at nGlyphIndex. *

*

* Note that it takes multiple mappings to ensure all characters and * glyphs are mapped, even when the mapping for each is 1:1. For * example, specifying that two consecutive characters map to two * consecutive glyphs in no way implies that the first character of the * pair maps to the first glyph of the pair. It simply means there is a * mapping between the pair of glyphs and the pair of characters that * cannot be further refined. *

*

* Typically (though not always) at least one length parameter has a * value of one; often both lengths have a value of one. *

* @param nCharStart - Starting character index of the mapping. * @param nGlyphStart - Starting glyph index of the mapping. * @param nCharLength - Number of consecutive Unicode characters in the * mapping. * @param nGlyphLength - Number of consecutive glyphs in the mapping. */ public void addMapping (int nCharStart, int nGlyphStart, int nCharLength, int nGlyphLength) { moMappings.add (new GFXMapping (nCharStart, nGlyphStart, nCharLength, nGlyphLength)); } public void addMapping (int nCharStart, int nGlyphStart, int nCharLength) { addMapping (nCharStart, nGlyphStart, nCharLength, 1); } public void addMapping (int nCharStart, int nGlyphStart) { addMapping (nCharStart, nGlyphStart, 1, 1); } /** * Return the number of mappings currently in the list. * @return Number of mappings currently in the list. */ public int getMappingCount () { return moMappings.size(); } /** * Extract one mapping from the list, by index. * @param nIndex - Index of the desired mapping. Index numbers start at * zero. Unpredictable results will occur if the index is out of range. * @return The desired mapping. */ public GFXMapping getMapping (int nIndex) { return moMappings.get (nIndex); } /** * Validate the contents of the mapping list. *

* Validation ensures that no glyph or character is included in two or * more mappings. In addition, the caller can request that characters * and/or glyphs be tested for coverage and overflow. If the client * specifies the number of characters expected, the validation process * also ensures that every character index is included in a mapping and * that no character index exceeds the maximum. The caller can request * similar testing of glyph indexes by providing the maximum number of * glyphs expected. *

*

* This method reports errors as exceptions, using the XTG exception * mechanism. *

* @param pnExpectedChars - Pointer to number of characters. If null, * no character index coverage or overflow testing occurs. * @param pnExpectedGlyphs - Pointer to number of glyphs. If null, no * glyph index coverage or overflow testing occurs. */ public void validate (int pnExpectedChars, int pnExpectedGlyphs) { validateMappings (false, pnExpectedChars, MAPPING_ERR_CHAR_OVERLAP, MAPPING_ERR_CHAR_UNMAPPED, MAPPING_ERR_CHAR_MAP_RANGE); validateMappings (true, pnExpectedGlyphs, MAPPING_ERR_GLYPH_OVERLAP, MAPPING_ERR_GLYPH_UNMAPPED, MAPPING_ERR_GLYPH_MAP_RANGE); } public void validate (int pnExpectedChars) { validate (pnExpectedChars, -1); } public void validate () { validate (-1, -1); } /** * Rearrange the mappings in the list, so that they are ordered by * lowest character index in each mapping. *

* This is useful for applications that are driven by the Unicode * content. */ public void orderByCharacter () { sortMappings (false); } /** * Rearrange the mappings in the list, so that they are ordered by * lowest glyph index in each mapping. *

* This is useful for applications that are driven by the rendered * glyphs. */ public void orderByGlyph () { sortMappings (true); } public void copyFrom (GFXMappingList source) { int size = source.moMappings.size(); moMappings.setSize (size); for (int i = 0; i < size; i++) { moMappings.set (i, new GFXMapping (source.getMapping (i))); } } @FindBugsSuppress(pattern="NP_NULL_ON_SOME_PATH") // oVisited private void validateMappings (boolean bGlyph, int pnExpected, int nErrorDuplicate, int nErrorMissing, int nErrorOverflow) { int i; int nMinIndex = 0; int nIndexCount = 0; if (pnExpected < 0) { nMinIndex = Integer.MAX_VALUE; int nMaxIndex = 0; for (i = 0; i < moMappings.size(); i++) { GFXMapping oMapping = getMapping (i); int nLow = oMapping.getLowestIndex (bGlyph); int nHigh = oMapping.getHighestIndex (bGlyph); if (nLow < nMinIndex) { nMinIndex = nLow; } if (nHigh > nMaxIndex) { nMaxIndex = nHigh; } } if (nMinIndex <= nMaxIndex) { nIndexCount = nMaxIndex + nMinIndex + 1; } } else { nMinIndex = 0; nIndexCount = pnExpected; } boolean[] oVisited = null; if (nIndexCount > 0) { oVisited = new boolean [nIndexCount]; for (i = 0; i < nIndexCount; i++) { oVisited[i] = false; } } int nIndexLimit = nMinIndex + nIndexCount; for (i = 0; i < moMappings.size(); i++) { GFXMapping oMapping = getMapping (i); int nCount = oMapping.getCount (bGlyph); for (int j = 0; j < nCount; j++) { int nIndex = oMapping.getIndex (bGlyph, j); if (nIndex >= nIndexLimit) { throwError (nErrorOverflow, nIndex); } int nVisitedIndex = nIndex - nMinIndex; if ((oVisited != null) && oVisited[nVisitedIndex]) { throwError (nErrorDuplicate, nIndex); } oVisited[nVisitedIndex] = true; } } if (pnExpected >= 0) { for (i = 0; i < nIndexCount; i++) { if (! oVisited[i]) { throwError (nErrorMissing, i); } } } } private void sortMappings (final boolean bGlyph) { Collections.sort(moMappings, new Comparator() { public int compare(GFXMapping mapping1, GFXMapping mapping2) { int lowestIndex1 = mapping1.getLowestIndex(bGlyph); int lowestIndex2 = mapping2.getLowestIndex(bGlyph); return lowestIndex1 < lowestIndex2 ? -1 : lowestIndex1 > lowestIndex2 ? 1 : 0; } }); } private static void throwError (int nError, int nValue) { assert (false); // FormatPos oFormat (nError); // oFormat << nValue; // ExFull oEx (oFormat); // throw oEx; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy