<target name="junit-complexscripts" depends="junit-compile">
<junit-run title="complexscripts" testsuite="org.apache.fop.complexscripts.ComplexScriptsTestSuite" outfile="TEST-complexscripts"/>
</target>
+ <target name="junit-complexscripts-layout" depends="junit-compile" if="junit.present">
+ <junit-run title="standard layout engine" testsuite="org.apache.fop.complexscripts.layout.ComplexScriptsLayoutTestSuite" outfile="TEST-complexscripts-layout"/>
+ </target>
<target name="junit-reduced" depends="junit-userconfig, junit-basic, junit-transcoder,
junit-text-linebreak, junit-fotree, junit-fonts, junit-render-pdf, junit-render-ps,
- junit-complexscripts"/>
+ junit-complexscripts, junit-complexscripts-layout"/>
<target name="junit" depends="junit-all" description="Runs all of FOP's JUnit tests"
if="junit.present">
<fail><condition><or><isset property="fop.junit.error"/><isset
this(new FileInputStream(fopConfFile), fopConfFile.toURI(), resourceResolver);
}
- private FopConfParser(InputStream fopConfStream, URI baseURI, EnvironmentProfile enviro)
+ public FopConfParser(InputStream fopConfStream, URI baseURI, EnvironmentProfile enviro)
throws SAXException, IOException {
DefaultConfigurationBuilder cfgBuilder = new DefaultConfigurationBuilder();
Configuration cfg;
}
matchedLookups.put(lsm, lm);
}
- return lm;
+ if (lm.isEmpty() && !OTFScript.isDefault(script) && !OTFScript.isWildCard(script)) {
+ return matchLookups(OTFScript.DEFAULT, OTFLanguage.DEFAULT, feature);
+ } else {
+ return lm;
+ }
}
/**
return (UseSpec[]) uss.toArray(new UseSpec [ uss.size() ]);
}
+ /**
+ * Determine if table supports specific feature, i.e., supports at least one lookup.
+ *
+ * @param script to qualify feature lookup
+ * @param language to qualify feature lookup
+ * @param feature to test
+ * @return true if feature supported (has at least one lookup)
+ */
+ public boolean hasFeature(String script, String language, String feature) {
+ UseSpec[] usa = assembleLookups(new String[] { feature }, matchLookups(script, language, feature));
+ return usa.length > 0;
+ }
+
/** {@inheritDoc} */
public String toString() {
StringBuffer sb = new StringBuffer(super.toString());
* @param script a script identifier
* @param language a language identifier
* @param feature a feature identifier
- * @param permitEmpty if true the permit empty script, language, or feature
- * @param permitWildcard if true the permit wildcard script, language, or feature
+ * @param permitEmpty if true then permit empty script, language, or feature
+ * @param permitWildcard if true then permit wildcard script, language, or feature
*/
LookupSpec(String script, String language, String feature, boolean permitEmpty, boolean permitWildcard) {
if ((script == null) || (!permitEmpty && (script.length() == 0))) {
--- /dev/null
+/*
+ * 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.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.complexscripts.fonts;
+
+/**
+ * <p>Language system tags defined by OTF specification. Note that this set and their
+ * values do not correspond with ISO639* or any other language registry.</p>
+ *
+ * <p>This work was originally authored by Glenn Adams (gadams@apache.org).</p>
+ */
+public final class OTFLanguage {
+ public static final String ABAZA = "ABA";
+ public static final String ABKHAZIAN = "ABK";
+ public static final String ADYGHE = "ADY";
+ public static final String AFRIKAANS = "AFK";
+ public static final String AFAR = "AFR";
+ public static final String AGAW = "AGW";
+ public static final String ALSATIAN = "ALS";
+ public static final String ALTAI = "ALT";
+ public static final String AMHARIC = "AMH";
+ public static final String PHONETIC_AMERICANIST = "APPH";
+ public static final String ARABIC = "ARA";
+ public static final String AARI = "ARI";
+ public static final String ARAKANESE = "ARK";
+ public static final String ASSAMESE = "ASM";
+ public static final String ATHAPASKAN = "ATH";
+ public static final String AVAR = "AVR";
+ public static final String AWADHI = "AWA";
+ public static final String AYMARA = "AYM";
+ public static final String AZERI = "AZE";
+ public static final String BADAGA = "BAD";
+ public static final String BAGHELKHANDI = "BAG";
+ public static final String BALKAR = "BAL";
+ public static final String BAULE = "BAU";
+ public static final String BERBER = "BBR";
+ public static final String BENCH = "BCH";
+ public static final String BIBLE_CREE = "BCR";
+ public static final String BELARUSSIAN = "BEL";
+ public static final String BEMBA = "BEM";
+ public static final String BENGALI = "BEN";
+ public static final String BULGARIAN = "BGR";
+ public static final String BHILI = "BHI";
+ public static final String BHOJPURI = "BHO";
+ public static final String BIKOL = "BIK";
+ public static final String BILEN = "BIL";
+ public static final String BLACKFOOT = "BKF";
+ public static final String BALOCHI = "BLI";
+ public static final String BALANTE = "BLN";
+ public static final String BALTI = "BLT";
+ public static final String BAMBARA = "BMB";
+ public static final String BAMILEKE = "BML";
+ public static final String BOSNIAN = "BOS";
+ public static final String BRETON = "BRE";
+ public static final String BRAHUI = "BRH";
+ public static final String BRAJ_BHASHA = "BRI";
+ public static final String BURMESE = "BRM";
+ public static final String BASHKIR = "BSH";
+ public static final String BETI = "BTI";
+ public static final String CATALAN = "CAT";
+ public static final String CEBUANO = "CEB";
+ public static final String CHECHEN = "CHE";
+ public static final String CHAHA_GURAGE = "CHG";
+ public static final String CHATTISGARHI = "CHH";
+ public static final String CHICHEWA = "CHI";
+ public static final String CHUKCHI = "CHK";
+ public static final String CHIPEWYAN = "CHP";
+ public static final String CHEROKEE = "CHR";
+ public static final String CHUVASH = "CHU";
+ public static final String COMORIAN = "CMR";
+ public static final String COPTIC = "COP";
+ public static final String CORSICAN = "COS";
+ public static final String CREE = "CRE";
+ public static final String CARRIER = "CRR";
+ public static final String CRIMEAN_TATAR = "CRT";
+ public static final String CHURCH_SLAVONIC = "CSL";
+ public static final String CZECH = "CSY";
+ public static final String DANISH = "DAN";
+ public static final String DARGWA = "DAR";
+ public static final String WOODS_CREE = "DCR";
+ public static final String GERMAN = "DEU";
+ public static final String DEFAULT = "dflt";
+ public static final String DOGRI = "DGR";
+ public static final String DHIVEHI_DEPRECATED = "DHV";
+ public static final String DHIVEHI = "DIV";
+ public static final String DJERMA = "DJR";
+ public static final String DANGME = "DNG";
+ public static final String DINKA = "DNK";
+ public static final String DARI = "DRI";
+ public static final String DUNGAN = "DUN";
+ public static final String DZONGKHA = "DZN";
+ public static final String EBIRA = "EBI";
+ public static final String EASTERN_CREE = "ECR";
+ public static final String EDO = "EDO";
+ public static final String EFIK = "EFI";
+ public static final String GREEK = "ELL";
+ public static final String ENGLISH = "ENG";
+ public static final String ERZYA = "ERZ";
+ public static final String SPANISH = "ESP";
+ public static final String ESTONIAN = "ETI";
+ public static final String BASQUE = "EUQ";
+ public static final String EVENKI = "EVK";
+ public static final String EVEN = "EVN";
+ public static final String EWE = "EWE";
+ public static final String FRENCH_ANTILLEAN = "FAN";
+ public static final String FARSI = "FAR";
+ public static final String FINNISH = "FIN";
+ public static final String FIJIAN = "FJI";
+ public static final String FLEMISH = "FLE";
+ public static final String FOREST_NENETS = "FNE";
+ public static final String FON = "FON";
+ public static final String FAROESE = "FOS";
+ public static final String FRENCH = "FRA";
+ public static final String FRISIAN = "FRI";
+ public static final String FRIULIAN = "FRL";
+ public static final String FUTA = "FTA";
+ public static final String FULANI = "FUL";
+ public static final String GA = "GAD";
+ public static final String GAELIC = "GAE";
+ public static final String GAGAUZ = "GAG";
+ public static final String GALICIAN = "GAL";
+ public static final String GARSHUNI = "GAR";
+ public static final String GARHWALI = "GAW";
+ public static final String GEEZ = "GEZ";
+ public static final String GILYAK = "GIL";
+ public static final String GUMUZ = "GMZ";
+ public static final String GONDI = "GON";
+ public static final String GREENLANDIC = "GRN";
+ public static final String GARO = "GRO";
+ public static final String GUARANI = "GUA";
+ public static final String GUJARATI = "GUJ";
+ public static final String HAITIAN = "HAI";
+ public static final String HALAM = "HAL";
+ public static final String HARAUTI = "HAR";
+ public static final String HAUSA = "HAU";
+ public static final String HAWAIIN = "HAW";
+ public static final String HAMMER_BANNA = "HBN";
+ public static final String HILIGAYNON = "HIL";
+ public static final String HINDI = "HIN";
+ public static final String HIGH_MARI = "HMA";
+ public static final String HINDKO = "HND";
+ public static final String HO = "HO";
+ public static final String HARARI = "HRI";
+ public static final String CROATIAN = "HRV";
+ public static final String HUNGARIAN = "HUN";
+ public static final String ARMENIAN = "HYE";
+ public static final String IGBO = "IBO";
+ public static final String IJO = "IJO";
+ public static final String ILOKANO = "ILO";
+ public static final String INDONESIAN = "IND";
+ public static final String INGUSH = "ING";
+ public static final String INUKTITUT = "INU";
+ public static final String PHONETIC_IPA = "IPPH";
+ public static final String IRISH = "IRI";
+ public static final String IRISH_TRADITIONAL = "IRT";
+ public static final String ICELANDIC = "ISL";
+ public static final String INARI_SAMI = "ISM";
+ public static final String ITALIAN = "ITA";
+ public static final String HEBREW = "IWR";
+ public static final String JAVANESE = "JAV";
+ public static final String YIDDISH = "JII";
+ public static final String JAPANESE = "JAN";
+ public static final String JUDEZMO = "JUD";
+ public static final String JULA = "JUL";
+ public static final String KABARDIAN = "KAB";
+ public static final String KACHCHI = "KAC";
+ public static final String KALENJIN = "KAL";
+ public static final String KANNADA = "KAN";
+ public static final String KARACHAY = "KAR";
+ public static final String GEORGIAN = "KAT";
+ public static final String KAZAKH = "KAZ";
+ public static final String KEBENA = "KEB";
+ public static final String KHUTSURI_GEORGIAN = "KGE";
+ public static final String KHAKASS = "KHA";
+ public static final String KHANTY_KAZIM = "KHK";
+ public static final String KHMER = "KHM";
+ public static final String KHANTY_SHURISHKAR = "KHS";
+ public static final String KHANTY_VAKHI = "KHV";
+ public static final String KHOWAR = "KHW";
+ public static final String KIKUYU = "KIK";
+ public static final String KIRGHIZ = "KIR";
+ public static final String KISII = "KIS";
+ public static final String KOKNI = "KKN";
+ public static final String KALMYK = "KLM";
+ public static final String KAMBA = "KMB";
+ public static final String KUMAONI = "KMN";
+ public static final String KOMO = "KMO";
+ public static final String KOMSO = "KMS";
+ public static final String KANURI = "KNR";
+ public static final String KODAGU = "KOD";
+ public static final String KOREAN_OLD_HANGUL = "KOH";
+ public static final String KONKANI = "KOK";
+ public static final String KIKONGO = "KON";
+ public static final String KOMI_PERMYAK = "KOP";
+ public static final String KOREAN = "KOR";
+ public static final String KOMI_ZYRIAN = "KOZ";
+ public static final String KPELLE = "KPL";
+ public static final String KRIO = "KRI";
+ public static final String KARAKALPAK = "KRK";
+ public static final String KARELIAN = "KRL";
+ public static final String KARAIM = "KRM";
+ public static final String KAREN = "KRN";
+ public static final String KOORETE = "KRT";
+ public static final String KASHMIRI = "KSH";
+ public static final String KHASI = "KSI";
+ public static final String KILDIN_SAMI = "KSM";
+ public static final String KUI = "KUI";
+ public static final String KULVI = "KUL";
+ public static final String KUMYK = "KUM";
+ public static final String KURDISH = "KUR";
+ public static final String KURUKH = "KUU";
+ public static final String KUY = "KUY";
+ public static final String KORYAK = "KYK";
+ public static final String LADIN = "LAD";
+ public static final String LAHULI = "LAH";
+ public static final String LAK = "LAK";
+ public static final String LAMBANI = "LAM";
+ public static final String LAO = "LAO";
+ public static final String LATIN = "LAT";
+ public static final String LAZ = "LAZ";
+ public static final String L_CREE = "LCR";
+ public static final String LADAKHI = "LDK";
+ public static final String LEZGI = "LEZ";
+ public static final String LINGALA = "LIN";
+ public static final String LOW_MARI = "LMA";
+ public static final String LIMBU = "LMB";
+ public static final String LOMWE = "LMW";
+ public static final String LOWER_SORBIAN = "LSB";
+ public static final String LULE_SAMI = "LSM";
+ public static final String LITHUANIAN = "LTH";
+ public static final String LUXEMBOURGISH = "LTZ";
+ public static final String LUBA = "LUB";
+ public static final String LUGANDA = "LUG";
+ public static final String LUHYA = "LUH";
+ public static final String LUO = "LUO";
+ public static final String LATVIAN = "LVI";
+ public static final String MAJANG = "MAJ";
+ public static final String MAKUA = "MAK";
+ public static final String MALAYALAM_TRADITIONAL = "MAL";
+ public static final String MANSI = "MAN";
+ public static final String MAPUDUNGUN = "MAP";
+ public static final String MARATHI = "MAR";
+ public static final String MARWARI = "MAW";
+ public static final String MBUNDU = "MBN";
+ public static final String MANCHU = "MCH";
+ public static final String MOOSE_CREE = "MCR";
+ public static final String MENDE = "MDE";
+ public static final String MEEN = "MEN";
+ public static final String MIZO = "MIZ";
+ public static final String MACEDONIAN = "MKD";
+ public static final String MALE = "MLE";
+ public static final String MALAGASY = "MLG";
+ public static final String MALINKE = "MLN";
+ public static final String MALAYALAM_REFORMED = "MLR";
+ public static final String MALAY = "MLY";
+ public static final String MANDINKA = "MND";
+ public static final String MONGOLIAN = "MNG";
+ public static final String MANIPURI = "MNI";
+ public static final String MANINKA = "MNK";
+ public static final String MANX_GAELIC = "MNX";
+ public static final String MOHAWK = "MOH";
+ public static final String MOKSHA = "MOK";
+ public static final String MOLDAVIAN = "MOL";
+ public static final String MON = "MON";
+ public static final String MOROCCAN = "MOR";
+ public static final String MAORI = "MRI";
+ public static final String MAITHILI = "MTH";
+ public static final String MALTESE = "MTS";
+ public static final String MUNDARI = "MUN";
+ public static final String NAGA_ASSAMESE = "NAG";
+ public static final String NANAI = "NAN";
+ public static final String NASKAPI = "NAS";
+ public static final String N_CREE = "NCR";
+ public static final String NDEBELE = "NDB";
+ public static final String NDONGA = "NDG";
+ public static final String NEPALI = "NEP";
+ public static final String NEWARI = "NEW";
+ public static final String NAGARI = "NGR";
+ public static final String NORWAY_HOUSE_CREE = "NHC";
+ public static final String NISI = "NIS";
+ public static final String NIUEAN = "NIU";
+ public static final String NKOLE = "NKL";
+ public static final String NKO = "NKO";
+ public static final String DUTCH = "NLD";
+ public static final String NOGAI = "NOG";
+ public static final String NORWEGIAN = "NOR";
+ public static final String NORTHERN_SAMI = "NSM";
+ public static final String NORTHERN_TAI = "NTA";
+ public static final String ESPERANTO = "NTO";
+ public static final String NYNORSK = "NYN";
+ public static final String OCCITAN = "OCI";
+ public static final String OJI_CREE = "OCR";
+ public static final String OJIBWAY = "OJB";
+ public static final String ORIYA = "ORI";
+ public static final String OROMO = "ORO";
+ public static final String OSSETIAN = "OSS";
+ public static final String PALESTINIAN_ARAMAIC = "PAA";
+ public static final String PALI = "PAL";
+ public static final String PUNJABI = "PAN";
+ public static final String PALPA = "PAP";
+ public static final String PASHTO = "PAS";
+ public static final String POLYTONIC_GREEK = "PGR";
+ public static final String FILIPINO = "PIL";
+ public static final String PALAUNG = "PLG";
+ public static final String POLISH = "PLK";
+ public static final String PROVENCAL = "PRO";
+ public static final String PORTUGUESE = "PTG";
+ public static final String CHIN = "QIN";
+ public static final String RAJASTHANI = "RAJ";
+ public static final String R_CREE = "RCR";
+ public static final String RUSSIAN_BURIAT = "RBU";
+ public static final String RIANG = "RIA";
+ public static final String RHAETO_ROMANIC = "RMS";
+ public static final String ROMANIAN = "ROM";
+ public static final String ROMANY = "ROY";
+ public static final String RUSYN = "RSY";
+ public static final String RUANDA = "RUA";
+ public static final String RUSSIAN = "RUS";
+ public static final String SADRI = "SAD";
+ public static final String SANSKRIT = "SAN";
+ public static final String SANTALI = "SAT";
+ public static final String SAYISI = "SAY";
+ public static final String SEKOTA = "SEK";
+ public static final String SELKUP = "SEL";
+ public static final String SANGO = "SGO";
+ public static final String SHAN = "SHN";
+ public static final String SIBE = "SIB";
+ public static final String SIDAMO = "SID";
+ public static final String SILTE_GURAGE = "SIG";
+ public static final String SKOLT_SAMI = "SKS";
+ public static final String SLOVAK = "SKY";
+ public static final String SLAVEY = "SLA";
+ public static final String SLOVENIAN = "SLV";
+ public static final String SOMALI = "SML";
+ public static final String SAMOAN = "SMO";
+ public static final String SENA = "SNA";
+ public static final String SINDHI = "SND";
+ public static final String SINHALESE = "SNH";
+ public static final String SONINKE = "SNK";
+ public static final String SODO_GURAGE = "SOG";
+ public static final String SOTHO = "SOT";
+ public static final String ALBANIAN = "SQI";
+ public static final String SERBIAN = "SRB";
+ public static final String SARAIKI = "SRK";
+ public static final String SERER = "SRR";
+ public static final String SOUTH_SLAVEY = "SSL";
+ public static final String SOUTHERN_SAMI = "SSM";
+ public static final String SURI = "SUR";
+ public static final String SVAN = "SVA";
+ public static final String SWEDISH = "SVE";
+ public static final String SWADAYA_ARAMAIC = "SWA";
+ public static final String SWAHILI = "SWK";
+ public static final String SWAZI = "SWZ";
+ public static final String SUTU = "SXT";
+ public static final String SYRIAC = "SYR";
+ public static final String TABASARAN = "TAB";
+ public static final String TAJIKI = "TAJ";
+ public static final String TAMIL = "TAM";
+ public static final String TATAR = "TAT";
+ public static final String TH_CREE = "TCR";
+ public static final String TELUGU = "TEL";
+ public static final String TONGAN = "TGN";
+ public static final String TIGRE = "TGR";
+ public static final String TIGRINYA = "TGY";
+ public static final String THAI = "THA";
+ public static final String TAHITIAN = "THT";
+ public static final String TIBETAN = "TIB";
+ public static final String TURKMEN = "TKM";
+ public static final String TEMNE = "TMN";
+ public static final String TSWANA = "TNA";
+ public static final String TUNDRA_NENETS = "TNE";
+ public static final String TONGA = "TNG";
+ public static final String TODO = "TOD";
+ public static final String TURKISH = "TRK";
+ public static final String TSONGA = "TSG";
+ public static final String TUROYO_ARAMAIC = "TUA";
+ public static final String TULU = "TUL";
+ public static final String TUVIN = "TUV";
+ public static final String TWI = "TWI";
+ public static final String UDMURT = "UDM";
+ public static final String UKRAINIAN = "UKR";
+ public static final String URDU = "URD";
+ public static final String UPPER_SORBIAN = "USB";
+ public static final String UYGHUR = "UYG";
+ public static final String UZBEK = "UZB";
+ public static final String VENDA = "VEN";
+ public static final String VIETNAMESE = "VIT";
+ public static final String WA = "WA";
+ public static final String WAGDI = "WAG";
+ public static final String WEST_CREE = "WCR";
+ public static final String WELSH = "WEL";
+ public static final String WILDCARD = "*";
+ public static final String WOLOF = "WLF";
+ public static final String TAI_LUE = "XBD";
+ public static final String XHOSA = "XHS";
+ public static final String SAKHA = "YAK";
+ public static final String YORUBA = "YBA";
+ public static final String Y_CREE = "YCR";
+ public static final String YI_CLASSIC = "YIC";
+ public static final String YI_MODERN = "YIM";
+ public static final String CHINESE_HONG_KONG_SAR = "ZHH";
+ public static final String CHINESE_PHONETIC = "ZHP";
+ public static final String CHINESE_SIMPLIFIED = "ZHS";
+ public static final String CHINESE_TRADITIONAL = "ZHT";
+ public static final String ZANDE = "ZND";
+ public static final String ZULU = "ZUL";
+
+ public static boolean isDefault(String language) {
+ return (language != null) && language.equals(DEFAULT);
+ }
+
+ public static boolean isWildCard(String language) {
+ return (language != null) && language.equals(WILDCARD);
+ }
+
+ private OTFLanguage() {
+ }
+}
--- /dev/null
+/*
+ * 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.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.complexscripts.fonts;
+
+/**
+ * <p>Script tags defined by OTF specification. Note that this set and their
+ * values do not correspond with ISO 15924 or Unicode Script names.</p>
+ *
+ * <p>This work was originally authored by Glenn Adams (gadams@apache.org).</p>
+ */
+public final class OTFScript {
+ public static final String ARABIC = "arab";
+ public static final String ARMENIAN = "armn";
+ public static final String AVESTAN = "avst";
+ public static final String BALINESE = "bali";
+ public static final String BAMUM = "bamu";
+ public static final String BATAK = "batk";
+ public static final String BENGALI = "beng";
+ public static final String BENGALI_V2 = "bng2";
+ public static final String BOPOMOFO = "bopo";
+ public static final String BRAILLE = "brai";
+ public static final String BRAHMI = "brah";
+ public static final String BUGINESE = "bugi";
+ public static final String BUHID = "buhd";
+ public static final String BYZANTINE_MUSIC = "byzm";
+ public static final String CANADIAN_SYLLABICS = "cans";
+ public static final String CARIAN = "cari";
+ public static final String CHAKMA = "cakm";
+ public static final String CHAM = "cham";
+ public static final String CHEROKEE = "cher";
+ public static final String CJK_IDEOGRAPHIC = "hani";
+ public static final String COPTIC = "copt";
+ public static final String CYPRIOT_SYLLABARY = "cprt";
+ public static final String CYRILLIC = "cyrl";
+ public static final String DEFAULT = "DFLT";
+ public static final String DESERET = "dsrt";
+ public static final String DEVANAGARI = "deva";
+ public static final String DEVANAGARI_V2 = "dev2";
+ public static final String EGYPTIAN_HEIROGLYPHS = "egyp";
+ public static final String ETHIOPIC = "ethi";
+ public static final String GEORGIAN = "geor";
+ public static final String GLAGOLITIC = "glag";
+ public static final String GOTHIC = "goth";
+ public static final String GREEK = "grek";
+ public static final String GUJARATI = "gujr";
+ public static final String GUJARATI_V2 = "gjr2";
+ public static final String GURMUKHI = "guru";
+ public static final String GURMUKHI_V2 = "gur2";
+ public static final String HANGUL = "hang";
+ public static final String HANGUL_JAMO = "jamo";
+ public static final String HANUNOO = "hano";
+ public static final String HEBREW = "hebr";
+ public static final String HIRAGANA = "kana";
+ public static final String IMPERIAL_ARAMAIC = "armi";
+ public static final String INSCRIPTIONAL_PAHLAVI = "phli";
+ public static final String INSCRIPTIONAL_PARTHIAN = "prti";
+ public static final String JAVANESE = "java";
+ public static final String KAITHI = "kthi";
+ public static final String KANNADA = "knda";
+ public static final String KANNADA_V2 = "knd2";
+ public static final String KATAKANA = "kana";
+ public static final String KAYAH_LI = "kali";
+ public static final String KHAROSTHI = "khar";
+ public static final String KHMER = "khmr";
+ public static final String LAO = "lao";
+ public static final String LATIN = "latn";
+ public static final String LEPCHA = "lepc";
+ public static final String LIMBU = "limb";
+ public static final String LINEAR_B = "linb";
+ public static final String LISU = "lisu";
+ public static final String LYCIAN = "lyci";
+ public static final String LYDIAN = "lydi";
+ public static final String MALAYALAM = "mlym";
+ public static final String MALAYALAM_V2 = "mlm2";
+ public static final String MANDAIC = "mand";
+ public static final String MATHEMATICAL_ALPHANUMERIC_SYMBOLS = "math";
+ public static final String MEITEI = "mtei";
+ public static final String MEROITIC_CURSIVE = "merc";
+ public static final String MEROITIC_HIEROGLYPHS = "mero";
+ public static final String MONGOLIAN = "mong";
+ public static final String MUSICAL_SYMBOLS = "musc";
+ public static final String MYANMAR = "mymr";
+ public static final String NEW_TAI_LUE = "talu";
+ public static final String NKO = "nko";
+ public static final String OGHAM = "ogam";
+ public static final String OL_CHIKI = "olck";
+ public static final String OLD_ITALIC = "ital";
+ public static final String OLD_PERSIAN_CUNEIFORM = "xpeo";
+ public static final String OLD_SOUTH_ARABIAN = "sarb";
+ public static final String OLD_TURKIC = "orkh";
+ public static final String ORIYA = "orya";
+ public static final String ORIYA_V2 = "ory2";
+ public static final String OSMANYA = "osma";
+ public static final String PHAGS_PA = "phag";
+ public static final String PHOENICIAN = "phnx";
+ public static final String REJANG = "rjng";
+ public static final String RUNIC = "runr";
+ public static final String SAMARITAN = "samr";
+ public static final String SAURASHTRA = "saur";
+ public static final String SHARADA = "shrd";
+ public static final String SHAVIAN = "shaw";
+ public static final String SINHALA = "sinh";
+ public static final String SORA_SOMPENG = "sora";
+ public static final String SUMERO_AKKADIAN_CUNEIFORM = "xsux";
+ public static final String SUNDANESE = "sund";
+ public static final String SYLOTI_NAGRI = "sylo";
+ public static final String SYRIAC = "syrc";
+ public static final String TAGALOG = "tglg";
+ public static final String TAGBANWA = "tagb";
+ public static final String TAI_LE = "tale";
+ public static final String TAI_THAM = "lana";
+ public static final String TAI_VIET = "tavt";
+ public static final String TAKRI = "takr";
+ public static final String TAMIL = "taml";
+ public static final String TAMIL_V2 = "tml2";
+ public static final String TELUGU = "telu";
+ public static final String TELUGU_V2 = "tel2";
+ public static final String THAANA = "thaa";
+ public static final String THAI = "thai";
+ public static final String TIBETAN = "tibt";
+ public static final String TIFINAGH = "tfng";
+ public static final String UGARITIC_CUNEIFORM = "ugar";
+ public static final String VAI = "vai";
+ public static final String WILDCARD = "*";
+ public static final String YI = "yi";
+
+ public static boolean isDefault(String script) {
+ return (script != null) && script.equals(DEFAULT);
+ }
+
+ public static boolean isWildCard(String script) {
+ return (script != null) && script.equals(DEFAULT);
+ }
+
+ private OTFScript() {
+ }
+}
return metric.hasKerningInfo();
}
+ /** @return true if the font has feature (i.e., at least one lookup matches) */
+ public boolean hasFeature(int tableType, String script, String language, String feature) {
+ return metric.hasFeature(tableType, script, language, feature);
+ }
+
/**
* Returns the font's kerning table
* @return the kerning table
Rectangle getBoundingBox(int glyphIndex, int size);
/**
- * Indicates if the font has kering information.
- * @return True, if kerning is available.
+ * Indicates if the font has kerning information.
+ * @return true if kerning is available.
*/
boolean hasKerningInfo();
*/
int getStrikeoutThickness(int size);
+ /**
+ * Determine if metrics supports specific feature in specified font table.
+ *
+ * @param tableType type of table (GSUB, GPOS, ...), see GlyphTable.GLYPH_TABLE_TYPE_*
+ * @param script to qualify feature lookup
+ * @param language to qualify feature lookup
+ * @param feature to test
+ * @return true if feature supported (and has at least one lookup)
+ */
+ boolean hasFeature(int tableType, String script, String language, String feature);
}
import org.apache.commons.logging.LogFactory;
import org.apache.fop.complexscripts.fonts.GlyphPositioningTable;
+import org.apache.fop.complexscripts.fonts.GlyphTable;
import org.apache.fop.complexscripts.util.CharScript;
import org.apache.fop.traits.MinOptMax;
import org.apache.fop.util.CharUtilities;
CharSequence mcs = font.performSubstitution(ics, script, language, associations);
// 4. compute glyph position adjustments on (substituted) characters.
- int[][] gpa;
+ int[][] gpa = null;
if (font.performsPositioning()) {
// handle GPOS adjustments
gpa = font.performPositioning(mcs, script, language);
- } else if (font.hasKerning()) {
+ }
+ if (useKerningAdjustments(font, script, language)) {
// handle standard (non-GPOS) kerning adjustments
- gpa = getKerningAdjustments(mcs, font);
- } else {
- gpa = null;
+ gpa = getKerningAdjustments(mcs, font, gpa);
}
// 5. reorder combining marks so that they precede (within the mapped char sequence) the
associations);
}
+ private static boolean useKerningAdjustments(final Font font, String script, String language) {
+ return font.hasKerning() && !font.hasFeature(GlyphTable.GLYPH_TABLE_TYPE_POSITIONING, script, language, "kern");
+ }
+
/**
* Given a mapped character sequence MCS, obtain glyph position adjustments from the
* font's kerning data.
* @param font applicable font
* @return glyph position adjustments (or null if no kerning)
*/
- private static int[][] getKerningAdjustments(CharSequence mcs, final Font font) {
+ private static int[][] getKerningAdjustments(CharSequence mcs, final Font font, int[][] gpa) {
int nc = mcs.length();
// extract kerning array
int[] ka = new int[nc]; // kerning array
}
// if non-zero kerning, then create and return glyph position adjustment array
if (hasKerning) {
- int[][] gpa = new int[nc][4];
+ if (gpa == null) {
+ gpa = new int[nc][4];
+ }
for (int i = 0, n = nc; i < n; i++) {
if (i > 0) {
- gpa [i - 1][GlyphPositioningTable.Value.IDX_X_ADVANCE] = ka[i];
+ gpa [i - 1][GlyphPositioningTable.Value.IDX_X_ADVANCE] += ka[i];
}
}
return gpa;
return realFont.getKerningInfo();
}
+ /** {@inheritDoc} */
+ public boolean hasFeature(int tableType, String script, String language, String feature) {
+ load(true);
+ return realFont.hasFeature(tableType, script, language, feature);
+ }
+
// ---- FontDescriptor interface ----
/**
* {@inheritDoc}
import org.apache.fop.complexscripts.fonts.GlyphDefinitionTable;
import org.apache.fop.complexscripts.fonts.GlyphPositioningTable;
import org.apache.fop.complexscripts.fonts.GlyphSubstitutionTable;
+import org.apache.fop.complexscripts.fonts.GlyphTable;
import org.apache.fop.complexscripts.fonts.Positionable;
import org.apache.fop.complexscripts.fonts.Substitutable;
import org.apache.fop.complexscripts.util.GlyphSequence;
return cb;
}
+ @Override
+ public boolean hasFeature(int tableType, String script, String language, String feature) {
+ GlyphTable table;
+ if (tableType == GlyphTable.GLYPH_TABLE_TYPE_SUBSTITUTION) {
+ table = getGSUB();
+ } else if (tableType == GlyphTable.GLYPH_TABLE_TYPE_POSITIONING) {
+ table = getGPOS();
+ } else if (tableType == GlyphTable.GLYPH_TABLE_TYPE_DEFINITION) {
+ table = getGDEF();
+ } else {
+ table = null;
+ }
+ return (table != null) && table.hasFeature(script, language, feature);
+ }
+
public Map<Integer, Integer> getWidthsMap() {
return null;
}
return getAscender(size);
}
+ /** {@inheritDoc} */
+ public boolean hasFeature(int tableType, String script, String language, String feature) {
+ return false;
+ }
+
/**
* Sets the font event listener that can be used to receive events about particular events
* in this class.
--- /dev/null
+/*
+ * 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.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.complexscripts.layout;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.Source;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMResult;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.sax.SAXResult;
+import javax.xml.transform.sax.TransformerHandler;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.filefilter.AndFileFilter;
+import org.apache.commons.io.filefilter.IOFileFilter;
+import org.apache.commons.io.filefilter.NameFileFilter;
+import org.apache.commons.io.filefilter.PrefixFileFilter;
+import org.apache.commons.io.filefilter.SuffixFileFilter;
+import org.apache.commons.io.filefilter.TrueFileFilter;
+
+import org.apache.fop.DebugHelper;
+
+import org.apache.fop.apps.EnvironmentProfile;
+import org.apache.fop.apps.EnvironmentalProfileFactory;
+import org.apache.fop.apps.FOUserAgent;
+import org.apache.fop.apps.Fop;
+import org.apache.fop.apps.FopConfBuilder;
+import org.apache.fop.apps.FopConfParser;
+import org.apache.fop.apps.FopFactory;
+import org.apache.fop.apps.FopFactoryBuilder;
+import org.apache.fop.apps.FormattingResults;
+import org.apache.fop.apps.MimeConstants;
+import org.apache.fop.apps.PDFRendererConfBuilder;
+import org.apache.fop.apps.io.ResourceResolverFactory;
+import org.apache.fop.area.AreaTreeModel;
+import org.apache.fop.area.AreaTreeParser;
+import org.apache.fop.area.RenderPagesModel;
+import org.apache.fop.events.Event;
+import org.apache.fop.events.EventListener;
+import org.apache.fop.events.model.EventSeverity;
+import org.apache.fop.fonts.FontInfo;
+import org.apache.fop.intermediate.IFTester;
+import org.apache.fop.intermediate.TestAssistant;
+import org.apache.fop.layoutengine.ElementListCollector;
+import org.apache.fop.layoutengine.LayoutEngineCheck;
+import org.apache.fop.layoutengine.LayoutEngineChecksFactory;
+import org.apache.fop.layoutengine.LayoutResult;
+import org.apache.fop.layoutengine.TestFilesConfiguration;
+import org.apache.fop.layoutmgr.ElementListObserver;
+import org.apache.fop.render.Renderer;
+import org.apache.fop.render.intermediate.IFContext;
+import org.apache.fop.render.intermediate.IFRenderer;
+import org.apache.fop.render.intermediate.IFSerializer;
+import org.apache.fop.render.xml.XMLRenderer;
+import org.apache.fop.util.ConsoleEventListenerForTests;
+import org.apache.fop.util.DelegatingContentHandler;
+
+// CSOFF: LineLengthCheck
+
+/**
+ * Test complex script layout (end-to-end) functionality.
+ */
+@RunWith(Parameterized.class)
+public class ComplexScriptsLayoutTestCase {
+
+ private static final boolean DEBUG = false;
+ private static final String AREA_TREE_OUTPUT_DIRECTORY = "build/test-results/complexscripts";
+ private static File areaTreeOutputDir;
+
+ private TestAssistant testAssistant = new TestAssistant();
+ private LayoutEngineChecksFactory layoutEngineChecksFactory = new LayoutEngineChecksFactory();
+ private TestFilesConfiguration testConfig;
+ private File testFile;
+ private IFTester ifTester;
+ private TransformerFactory tfactory = TransformerFactory.newInstance();
+
+ public ComplexScriptsLayoutTestCase(TestFilesConfiguration testConfig, File testFile) {
+ this.testConfig = testConfig;
+ this.testFile = testFile;
+ this.ifTester = new IFTester(tfactory, areaTreeOutputDir);
+ }
+
+ @Parameters
+ public static Collection<Object[]> getParameters() throws IOException {
+ return getTestFiles();
+ }
+
+ @BeforeClass
+ public static void makeDirAndRegisterDebugHelper() throws IOException {
+ DebugHelper.registerStandardElementListObservers();
+ areaTreeOutputDir = new File(AREA_TREE_OUTPUT_DIRECTORY);
+ if (!areaTreeOutputDir.mkdirs() && !areaTreeOutputDir.exists()) {
+ throw new IOException("Failed to create the AT output directory at " + AREA_TREE_OUTPUT_DIRECTORY);
+ }
+ }
+
+ @Test
+ public void runTest() throws TransformerException, SAXException, IOException, ParserConfigurationException {
+ DOMResult domres = new DOMResult();
+ ElementListCollector elCollector = new ElementListCollector();
+ ElementListObserver.addObserver(elCollector);
+ Fop fop;
+ FopFactory effFactory;
+ EventsChecker eventsChecker = new EventsChecker(new ConsoleEventListenerForTests(testFile.getName(), EventSeverity.WARN));
+ try {
+ Document testDoc = testAssistant.loadTestCase(testFile);
+ effFactory = getFopFactory(testConfig, testDoc);
+ // Setup Transformer to convert the testcase XML to XSL-FO
+ Transformer transformer = testAssistant.getTestcase2FOStylesheet().newTransformer();
+ Source src = new DOMSource(testDoc);
+ // Setup Transformer to convert the area tree to a DOM
+ TransformerHandler athandler;
+ athandler = testAssistant.getTransformerFactory().newTransformerHandler();
+ athandler.setResult(domres);
+ // Setup FOP for area tree rendering
+ FOUserAgent ua = effFactory.newFOUserAgent();
+ ua.getEventBroadcaster().addEventListener(eventsChecker);
+ XMLRenderer atrenderer = new XMLRenderer(ua);
+ Renderer targetRenderer = ua.getRendererFactory().createRenderer(ua, MimeConstants.MIME_PDF);
+ atrenderer.mimicRenderer(targetRenderer);
+ atrenderer.setContentHandler(athandler);
+ ua.setRendererOverride(atrenderer);
+ fop = effFactory.newFop(ua);
+ SAXResult fores = new SAXResult(fop.getDefaultHandler());
+ transformer.transform(src, fores);
+ } finally {
+ ElementListObserver.removeObserver(elCollector);
+ }
+ Document doc = (Document)domres.getNode();
+ if (areaTreeOutputDir != null) {
+ testAssistant.saveDOM(doc, new File(areaTreeOutputDir, testFile.getName() + ".at.xml"));
+ }
+ FormattingResults results = fop.getResults();
+ LayoutResult result = new LayoutResult(doc, elCollector, results);
+ checkAll(effFactory, testFile, result, eventsChecker);
+ }
+
+ private FopFactory getFopFactory(TestFilesConfiguration testConfig, Document testDoc) throws SAXException, IOException {
+ EnvironmentProfile profile = EnvironmentalProfileFactory.createRestrictedIO(
+ testConfig.getTestDirectory().getParentFile().toURI(),
+ ResourceResolverFactory.createDefaultResourceResolver());
+ InputStream confStream =
+ new FopConfBuilder().setStrictValidation(true)
+ .setFontBaseURI("test/resources/fonts/ttf/")
+ .startRendererConfig(PDFRendererConfBuilder.class)
+ .startFontsConfig()
+ .startFont(null, "DejaVuLGCSerif.ttf")
+ .addTriplet("DejaVu LGC Serif", "normal", "normal")
+ .endFont()
+ .endFontConfig()
+ .endRendererConfig().build();
+ FopFactoryBuilder builder =
+ new FopConfParser(confStream, new File(".").toURI(), profile).getFopFactoryBuilder();
+ // builder.setStrictFOValidation(isStrictValidation(testDoc));
+ // builder.getFontManager().setBase14KerningEnabled(isBase14KerningEnabled(testDoc));
+ return builder.build();
+ }
+
+ private void checkAll(FopFactory fopFactory, File testFile, LayoutResult result, EventsChecker eventsChecker) throws TransformerException {
+ Element testRoot = testAssistant.getTestRoot(testFile);
+ NodeList nodes;
+ nodes = testRoot.getElementsByTagName("at-checks");
+ if (nodes.getLength() > 0) {
+ Element atChecks = (Element)nodes.item(0);
+ doATChecks(atChecks, result);
+ }
+ nodes = testRoot.getElementsByTagName("if-checks");
+ if (nodes.getLength() > 0) {
+ Element ifChecks = (Element)nodes.item(0);
+ Document ifDocument = createIF(fopFactory, testFile, result.getAreaTree());
+ ifTester.doIFChecks(testFile.getName(), ifChecks, ifDocument);
+ }
+ nodes = testRoot.getElementsByTagName("event-checks");
+ if (nodes.getLength() > 0) {
+ Element eventChecks = (Element) nodes.item(0);
+ doEventChecks(eventChecks, eventsChecker);
+ }
+ eventsChecker.emitUncheckedEvents();
+ }
+
+ private Document createIF(FopFactory fopFactory, File testFile, Document areaTreeXML) throws TransformerException {
+ try {
+ FOUserAgent ua = fopFactory.newFOUserAgent();
+ ua.getEventBroadcaster().addEventListener(new ConsoleEventListenerForTests(testFile.getName(), EventSeverity.WARN));
+ IFRenderer ifRenderer = new IFRenderer(ua);
+ IFSerializer serializer = new IFSerializer(new IFContext(ua));
+ DOMResult result = new DOMResult();
+ serializer.setResult(result);
+ ifRenderer.setDocumentHandler(serializer);
+ ua.setRendererOverride(ifRenderer);
+ FontInfo fontInfo = new FontInfo();
+ //Construct the AreaTreeModel that will received the individual pages
+ final AreaTreeModel treeModel = new RenderPagesModel(ua, null, fontInfo, null);
+ //Iterate over all intermediate files
+ AreaTreeParser parser = new AreaTreeParser();
+ ContentHandler handler = parser.getContentHandler(treeModel, ua);
+ DelegatingContentHandler proxy = new DelegatingContentHandler() {
+ public void endDocument() throws SAXException {
+ super.endDocument();
+ treeModel.endDocument();
+ }
+ };
+ proxy.setDelegateContentHandler(handler);
+ Transformer transformer = tfactory.newTransformer();
+ transformer.transform(new DOMSource(areaTreeXML), new SAXResult(proxy));
+ return (Document)result.getNode();
+ } catch (Exception e) {
+ throw new TransformerException("Error while generating intermediate format file: " + e.getMessage(), e);
+ }
+ }
+
+ private void doATChecks(Element checksRoot, LayoutResult result) {
+ List<LayoutEngineCheck> checks = layoutEngineChecksFactory.createCheckList(checksRoot);
+ if (checks.size() == 0) {
+ throw new RuntimeException("No available area tree check");
+ }
+ for (LayoutEngineCheck check : checks) {
+ check.check(result);
+ }
+ }
+
+ private void doEventChecks(Element eventChecks, EventsChecker eventsChecker) {
+ NodeList events = eventChecks.getElementsByTagName("event");
+ for (int i = 0; i < events.getLength(); i++) {
+ Element event = (Element) events.item(i);
+ NamedNodeMap attributes = event.getAttributes();
+ Map<String, String> params = new HashMap<String, String>();
+ String key = null;
+ for (int j = 0; j < attributes.getLength(); j++) {
+ Node attribute = attributes.item(j);
+ String name = attribute.getNodeName();
+ String value = attribute.getNodeValue();
+ if ("key".equals(name)) {
+ key = value;
+ } else {
+ params.put(name, value);
+ }
+ }
+ if (key == null) {
+ throw new RuntimeException("An event element must have a \"key\" attribute");
+ }
+ eventsChecker.checkEvent(key, params);
+ }
+ }
+
+ private static Collection<Object[]> getTestFiles(TestFilesConfiguration testConfig) {
+ File mainDir = testConfig.getTestDirectory();
+ IOFileFilter filter;
+ String single = testConfig.getSingleTest();
+ String startsWith = testConfig.getStartsWith();
+ if (single != null) {
+ filter = new NameFileFilter(single);
+ } else if (startsWith != null) {
+ filter = new PrefixFileFilter(startsWith);
+ filter = new AndFileFilter(filter, new SuffixFileFilter(testConfig.getFileSuffix()));
+ } else {
+ filter = new SuffixFileFilter(testConfig.getFileSuffix());
+ }
+ String testset = testConfig.getTestSet();
+ Collection<File> files = FileUtils.listFiles(new File(mainDir, testset), filter, TrueFileFilter.INSTANCE);
+ if (testConfig.hasPrivateTests()) {
+ Collection<File> privateFiles =
+ FileUtils.listFiles(new File(mainDir, "private-testcases"), filter, TrueFileFilter.INSTANCE);
+ files.addAll(privateFiles);
+ }
+ Collection<Object[]> parametersForJUnit4 = new ArrayList<Object[]>();
+ int index = 0;
+ for (File f : files) {
+ parametersForJUnit4.add(new Object[] { testConfig, f });
+ if (DEBUG) {
+ System.out.println(String.format("%3d %s", index++, f));
+ }
+ }
+ return parametersForJUnit4;
+ }
+
+ private static Collection<Object[]> getTestFiles() {
+ String testSet = System.getProperty("fop.complexscripts.testset");
+ testSet = (testSet != null ? testSet : "standard") + "-testcases";
+ return getTestFiles(testSet);
+ }
+
+ private static Collection<Object[]> getTestFiles(String testSetName) {
+ TestFilesConfiguration.Builder builder = new TestFilesConfiguration.Builder();
+ builder.testDir("test/resources/complexscripts/layout")
+ .singleProperty("fop.complexscripts.single")
+ .startsWithProperty("fop.complexscripts.starts-with")
+ .suffix(".xml")
+ .testSet(testSetName)
+ .privateTestsProperty("fop.complexscripts.private");
+ return getTestFiles(builder.build());
+ }
+
+ private static class EventsChecker implements EventListener {
+
+ private final List<Event> events = new ArrayList<Event>();
+ private final EventListener defaultListener;
+
+ public EventsChecker(EventListener fallbackListener) {
+ this.defaultListener = fallbackListener;
+ }
+
+ public void processEvent(Event event) {
+ events.add(event);
+ }
+
+ public void checkEvent(String expectedKey, Map<String, String> expectedParams) {
+ boolean eventFound = false;
+ for (Iterator<Event> iter = events.iterator(); !eventFound && iter.hasNext();) {
+ Event event = iter.next();
+ if (event.getEventKey().equals(expectedKey)) {
+ eventFound = true;
+ iter.remove();
+ checkParameters(event, expectedParams);
+ }
+ }
+ if (!eventFound) {
+ fail("Event did not occur but was expected to: " + expectedKey + expectedParams);
+ }
+ }
+
+ private void checkParameters(Event event, Map<String, String> expectedParams) {
+ Map<String, Object> actualParams = event.getParams();
+ for (Map.Entry<String, String> expectedParam : expectedParams.entrySet()) {
+ assertTrue("Event \"" + event.getEventKey()
+ + "\" is missing parameter \"" + expectedParam.getKey() + '"',
+ actualParams.containsKey(expectedParam.getKey()));
+ assertEquals("Event \"" + event.getEventKey()
+ + "\" has wrong value for parameter \"" + expectedParam.getKey() + "\";",
+ actualParams.get(expectedParam.getKey()).toString(),
+ expectedParam.getValue());
+ }
+ }
+
+ public void emitUncheckedEvents() {
+ for (Event event : events) {
+ defaultListener.processEvent(event);
+ }
+ }
+ }
+
+}
--- /dev/null
+/*
+ * 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.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.complexscripts.layout;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+import org.junit.runners.Suite.SuiteClasses;
+
+/**
+ * Test suite for running complex script layout tests under JUnit control.
+ */
+@RunWith(Suite.class)
+@SuiteClasses(ComplexScriptsLayoutTestCase.class)
+public class ComplexScriptsLayoutTestSuite {
+}
}
public FopFactory getFopFactory(Document testDoc) {
- boolean base14KerningEnabled = isBase14KerningEnabled(testDoc);
- boolean strictValidation = isStrictValidation(testDoc);
EnvironmentProfile envProfile = EnvironmentalProfileFactory.createRestrictedIO(
testDir.getParentFile().toURI(),
ResourceResolverFactory.createDefaultResourceResolver());
FopFactoryBuilder builder = new FopFactoryBuilder(envProfile);
- builder.setStrictFOValidation(strictValidation);
- builder.getFontManager().setBase14KerningEnabled(base14KerningEnabled);
+ builder.setStrictFOValidation(isStrictValidation(testDoc));
+ builder.getFontManager().setBase14KerningEnabled(isBase14KerningEnabled(testDoc));
return builder.build();
}
/**
* A factory class for creating {@link LayoutEngineCheck} instances.
*/
-final class LayoutEngineChecksFactory extends ChecksFactory<LayoutEngineCheck> {
+public final class LayoutEngineChecksFactory extends ChecksFactory<LayoutEngineCheck> {
- LayoutEngineChecksFactory() {
+ public LayoutEngineChecksFactory() {
registerCheckFactory("true", new CheckFactory<LayoutEngineCheck>() {
public LayoutEngineCheck createCheck(Element element) {
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+<!-- $Id$ -->
+<testcase>
+ <info>
+ <p>
+ Test fix for https://issues.apache.org/jira/browse/FOP-2213.
+ </p>
+ </info>
+ <fo>
+ <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
+ <fo:layout-master-set>
+ <fo:simple-page-master master-name="page"
+ page-height="300pt" page-width="400pt" margin="10pt">
+ <fo:region-body display-align="center"/>
+ </fo:simple-page-master>
+ </fo:layout-master-set>
+ <fo:page-sequence master-reference="page">
+ <fo:flow flow-name="xsl-region-body">
+ <fo:block font-size="200pt" text-align="center" font-family="DejaVu LGC Serif">Y.</fo:block>
+ </fo:flow>
+ </fo:page-sequence>
+ </fo:root>
+ </fo>
+ <checks>
+ <eval expected="2 Z2 -25600 Z5" xpath="(//word)[1]/@position-adjust"/>
+ </checks>
+</testcase>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+<!-- $Id$ -->
+<!-- This stylesheet extracts the checks from the testcase so the list of checks can be built in Java code. -->
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format">
+
+<xsl:variable name="basic-checks" select="document('basic-checks.xml')/checks/*" />
+
+<xsl:template match="testcase">
+ <checks>
+ <xsl:apply-templates select="checks"/>
+ <xsl:apply-templates select="if-checks"/>
+ <xsl:apply-templates select="event-checks"/>
+ </checks>
+</xsl:template>
+
+<xsl:template match="checks">
+ <at-checks>
+ <xsl:copy-of select="$basic-checks" />
+ <xsl:copy-of select="*" />
+ </at-checks>
+</xsl:template>
+
+<xsl:template match="if-checks">
+ <if-checks>
+ <xsl:copy-of select="*"/>
+ </if-checks>
+</xsl:template>
+
+<xsl:template match="event-checks">
+ <event-checks>
+ <xsl:copy-of select="*"/>
+ </event-checks>
+</xsl:template>
+
+<xsl:template match="text()" />
+
+</xsl:stylesheet>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+<!-- $Id$ -->
+<!-- This stylesheet extracts the FO part from the testcase so it can be passed to FOP for layout. -->
+<!--
+Variable substitution:
+
+For any attribute value that starts with a "##" the stylesheet looks for an element with the variable
+name under /testcase/variables, ex. "##img" looks for /testcase/variables/img and uses its element
+value as subsitution value.
+-->
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format">
+
+ <xsl:template match="testcase">
+ <xsl:apply-templates select="fo/*" mode="copy"/>
+ </xsl:template>
+
+ <xsl:template match="node()" mode="copy">
+ <xsl:copy>
+ <xsl:apply-templates select="@*|node()" mode="copy"/>
+ </xsl:copy>
+ </xsl:template>
+
+ <xsl:template match="@*" mode="copy">
+ <xsl:choose>
+ <xsl:when test="starts-with(., '##')">
+ <!-- variable substitution -->
+ <xsl:variable name="nodename" select="name()"/>
+ <xsl:variable name="varname" select="substring(., 3)"/>
+ <xsl:choose>
+ <xsl:when test="boolean(//variables/child::*[local-name() = $varname])">
+ <xsl:attribute name="{name(.)}">
+ <xsl:value-of select="//variables/child::*[local-name() = $varname]"/>
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <!-- if variable isn't defined, just copy -->
+ <xsl:copy-of select="." />
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:copy-of select="." />
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+</xsl:stylesheet>