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

com.adobe.fontengine.Properties Maven / Gradle / Ivy

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

/**
 * With minor simplifications and Java porting details, this code was extracted directly
 * from CTS_AGL_Properties.c. Refer to that code for more information or for comparison
 * if you think you see a bug here.
 */
public final class Properties
{
	public static final int MAX_CASE_EXPANSION = 3;
	public static final int CASE_TAILORING_NONE = 0x0;
	public static final int CASE_TAILORING_DOTTED_I = 0x1;
	public static final int CASE_TAILORING_SHARP_S = 0x2;
	public static final int CASE_TAILORING_SUBSCRIPT_IOTA = 0x4;

	public static int getFullUpperCase(int usv, int tailorings, int result[])
	{
		int arg = 0;
		int entry = searchRangeTable(UnicodeData.caseTable, UnicodeData.caseAsciiLimit, UnicodeData.caseLatin1Limit, UnicodeData.caseUnicodeLimit, usv);
		switch ((entry >> 29) & 7) {
		case UnicodeData.CASE_SELF:
		case UnicodeData.CASE_LOWER_BY_DELTA:
			result[0] = usv;
			return 1;
		case UnicodeData.CASE_EVEN_UPPER_LOWER_PAIR:
			if (usv % 2 == 0) {
				result[0] = usv;
			} else {
				result[0] = usv - 1;
			}
			return 1;
		case UnicodeData.CASE_ODD_UPPER_LOWER_PAIR:
			if (usv % 2 == 1) {
				result[0] = usv;
			} else {
				result[0] = usv - 1;
			}
			return 1;
		case UnicodeData.CASE_UPPER_TITLE_LOWER:
			arg = (entry >> 21) & 0xff;
			result[0] = usv - arg;
			return 1;
		case UnicodeData.CASE_UPPER_BY_DELTA:
			result[0] = usv - UnicodeData.caseTableDelta[(entry >> 21) & 0xff];
			return 1;
		case UnicodeData.CASE_COMPLEX:
			arg = (entry >> 21) & 0xff;
			entry = UnicodeData.caseTableComplex[arg];
			/* use the tailored mappings if needed */
			if (((entry >> 28) & tailorings) != 0) {
				entry = UnicodeData.caseTableComplex[arg+1];
			}
			int cpIndex = entry & 0xffff;
			int nbUsvs = (entry >> 26) & 0x3;
			if (nbUsvs == 0) {
				result[0] = usv;
				return 1;
			}
			for (int i = 0; i < nbUsvs; i++) {
				result[i] = UnicodeData.caseTableCp[cpIndex++];
			}
			return nbUsvs;
		}
		return 0;
	}

	public static int getFullLowerCase(int usv, int tailorings, int result[])
	{
		int arg = 0;
		int entry = searchRangeTable(UnicodeData.caseTable, UnicodeData.caseAsciiLimit, UnicodeData.caseLatin1Limit, UnicodeData.caseUnicodeLimit, usv);
		switch ((entry >> 29) & 7) {
		case UnicodeData.CASE_SELF:
		case UnicodeData.CASE_UPPER_BY_DELTA:
			result[0] = usv;
			return 1;
		case UnicodeData.CASE_EVEN_UPPER_LOWER_PAIR:
			if (usv % 2 == 0) {
				result[0] = usv + 1;
			} else {
				result[0] = usv;
			}
			return 1;
		case UnicodeData.CASE_ODD_UPPER_LOWER_PAIR:
			if (usv % 2 == 1) {
				result[0] = usv + 1;
			} else {
				result[0] = usv;
			}
			return 1;
		case UnicodeData.CASE_UPPER_TITLE_LOWER:
			arg = (entry >> 21) & 0xff;
			result[0] = usv + 2 - arg;
			return 1;
		case UnicodeData.CASE_LOWER_BY_DELTA:
			result[0] = usv + UnicodeData.caseTableDelta[(entry >> 21) & 0xff];
			return 1;
		case UnicodeData.CASE_COMPLEX:
			arg = (entry >> 21) & 0xff;
			entry = UnicodeData.caseTableComplex[arg];
			/* use the tailored mappings if needed */
			if (((entry >> 28) & tailorings) != 0) {
				entry = UnicodeData.caseTableComplex[arg+1];
			}
			int cpIndex = entry & 0xffff;
			cpIndex += (entry >> 26) & 0x3;   /* skip the uppercase */
			cpIndex += (entry >> 24) & 0x3;   /* skip the titlecase */
			int nbUsvs = (entry >> 22) & 0x3;
			if (nbUsvs == 0) {
				result[0] = usv;
				return 1;
			}
			for (int i = 0; i < nbUsvs; i++) {
				result[i] = UnicodeData.caseTableCp[cpIndex++];
			}
			return nbUsvs;
		}
		return 0;
	}

	static int searchRangeTable(int table[], int asciiLimit, int latin1Limit, int unicodeLimit, int usv)
	{
		int min = 0;
		int max = 0;
		if (usv < 0x80) {
			min = 0;
			max = asciiLimit;
		} else if (usv < 0x100) {
			min = asciiLimit - 1;
			max = latin1Limit;
		} else {
			min = latin1Limit - 1;
			max = unicodeLimit;
		}
		while (min < max) {
			int median = (min + max) / 2;
			int u1 = table[median] & 0x001fffff;
			int u2 = table[median+1]  & 0x001fffff;
			if (usv < u1) {
				max = median;
			} else if (u2 <= usv) {
				min = median + 1;
			} else {
				return table[median];
			}
		}
		return 0;
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy