FOP-2094 preliminary support for mapping OTF script tags from @script property FOP-2094 when no lookups match specified or auto script, retry using DFLT script FOP-2093 preliminary support for mapping OTF language tags from @language property git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@1623885 13f79535-47bb-0310-9956-ffa450edef68pull/28/head
<target name="junit-complexscripts" depends="junit-compile"> | <target name="junit-complexscripts" depends="junit-compile"> | ||||
<junit-run title="complexscripts" testsuite="org.apache.fop.complexscripts.ComplexScriptsTestSuite" outfile="TEST-complexscripts"/> | <junit-run title="complexscripts" testsuite="org.apache.fop.complexscripts.ComplexScriptsTestSuite" outfile="TEST-complexscripts"/> | ||||
</target> | </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, | <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-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" | <target name="junit" depends="junit-all" description="Runs all of FOP's JUnit tests" | ||||
if="junit.present"> | if="junit.present"> | ||||
<fail><condition><or><isset property="fop.junit.error"/><isset | <fail><condition><or><isset property="fop.junit.error"/><isset |
this(new FileInputStream(fopConfFile), fopConfFile.toURI(), resourceResolver); | 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 { | throws SAXException, IOException { | ||||
DefaultConfigurationBuilder cfgBuilder = new DefaultConfigurationBuilder(); | DefaultConfigurationBuilder cfgBuilder = new DefaultConfigurationBuilder(); | ||||
Configuration cfg; | Configuration cfg; |
} | } | ||||
matchedLookups.put(lsm, lm); | 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() ]); | 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} */ | /** {@inheritDoc} */ | ||||
public String toString() { | public String toString() { | ||||
StringBuffer sb = new StringBuffer(super.toString()); | StringBuffer sb = new StringBuffer(super.toString()); | ||||
* @param script a script identifier | * @param script a script identifier | ||||
* @param language a language identifier | * @param language a language identifier | ||||
* @param feature a feature 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) { | LookupSpec(String script, String language, String feature, boolean permitEmpty, boolean permitWildcard) { | ||||
if ((script == null) || (!permitEmpty && (script.length() == 0))) { | if ((script == null) || (!permitEmpty && (script.length() == 0))) { |
/* | |||||
* 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() { | |||||
} | |||||
} |
/* | |||||
* 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 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 | * Returns the font's kerning table | ||||
* @return the kerning table | * @return the kerning table |
Rectangle getBoundingBox(int glyphIndex, int size); | 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(); | boolean hasKerningInfo(); | ||||
*/ | */ | ||||
int getStrikeoutThickness(int size); | 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.commons.logging.LogFactory; | ||||
import org.apache.fop.complexscripts.fonts.GlyphPositioningTable; | 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.complexscripts.util.CharScript; | ||||
import org.apache.fop.traits.MinOptMax; | import org.apache.fop.traits.MinOptMax; | ||||
import org.apache.fop.util.CharUtilities; | import org.apache.fop.util.CharUtilities; | ||||
CharSequence mcs = font.performSubstitution(ics, script, language, associations); | CharSequence mcs = font.performSubstitution(ics, script, language, associations); | ||||
// 4. compute glyph position adjustments on (substituted) characters. | // 4. compute glyph position adjustments on (substituted) characters. | ||||
int[][] gpa; | |||||
int[][] gpa = null; | |||||
if (font.performsPositioning()) { | if (font.performsPositioning()) { | ||||
// handle GPOS adjustments | // handle GPOS adjustments | ||||
gpa = font.performPositioning(mcs, script, language); | gpa = font.performPositioning(mcs, script, language); | ||||
} else if (font.hasKerning()) { | |||||
} | |||||
if (useKerningAdjustments(font, script, language)) { | |||||
// handle standard (non-GPOS) kerning adjustments | // 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 | // 5. reorder combining marks so that they precede (within the mapped char sequence) the | ||||
associations); | 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 | * Given a mapped character sequence MCS, obtain glyph position adjustments from the | ||||
* font's kerning data. | * font's kerning data. | ||||
* @param font applicable font | * @param font applicable font | ||||
* @return glyph position adjustments (or null if no kerning) | * @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(); | int nc = mcs.length(); | ||||
// extract kerning array | // extract kerning array | ||||
int[] ka = new int[nc]; // kerning array | int[] ka = new int[nc]; // kerning array | ||||
} | } | ||||
// if non-zero kerning, then create and return glyph position adjustment array | // if non-zero kerning, then create and return glyph position adjustment array | ||||
if (hasKerning) { | 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++) { | for (int i = 0, n = nc; i < n; i++) { | ||||
if (i > 0) { | 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 gpa; |
return realFont.getKerningInfo(); | 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 ---- | // ---- FontDescriptor interface ---- | ||||
/** | /** | ||||
* {@inheritDoc} | * {@inheritDoc} |
import org.apache.fop.complexscripts.fonts.GlyphDefinitionTable; | import org.apache.fop.complexscripts.fonts.GlyphDefinitionTable; | ||||
import org.apache.fop.complexscripts.fonts.GlyphPositioningTable; | import org.apache.fop.complexscripts.fonts.GlyphPositioningTable; | ||||
import org.apache.fop.complexscripts.fonts.GlyphSubstitutionTable; | 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.Positionable; | ||||
import org.apache.fop.complexscripts.fonts.Substitutable; | import org.apache.fop.complexscripts.fonts.Substitutable; | ||||
import org.apache.fop.complexscripts.util.GlyphSequence; | import org.apache.fop.complexscripts.util.GlyphSequence; | ||||
return cb; | 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() { | public Map<Integer, Integer> getWidthsMap() { | ||||
return null; | return null; | ||||
} | } |
return getAscender(size); | 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 | * Sets the font event listener that can be used to receive events about particular events | ||||
* in this class. | * in this class. |
/* | |||||
* 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); | |||||
} | |||||
} | |||||
} | |||||
} |
/* | |||||
* 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) { | public FopFactory getFopFactory(Document testDoc) { | ||||
boolean base14KerningEnabled = isBase14KerningEnabled(testDoc); | |||||
boolean strictValidation = isStrictValidation(testDoc); | |||||
EnvironmentProfile envProfile = EnvironmentalProfileFactory.createRestrictedIO( | EnvironmentProfile envProfile = EnvironmentalProfileFactory.createRestrictedIO( | ||||
testDir.getParentFile().toURI(), | testDir.getParentFile().toURI(), | ||||
ResourceResolverFactory.createDefaultResourceResolver()); | ResourceResolverFactory.createDefaultResourceResolver()); | ||||
FopFactoryBuilder builder = new FopFactoryBuilder(envProfile); | FopFactoryBuilder builder = new FopFactoryBuilder(envProfile); | ||||
builder.setStrictFOValidation(strictValidation); | |||||
builder.getFontManager().setBase14KerningEnabled(base14KerningEnabled); | |||||
builder.setStrictFOValidation(isStrictValidation(testDoc)); | |||||
builder.getFontManager().setBase14KerningEnabled(isBase14KerningEnabled(testDoc)); | |||||
return builder.build(); | return builder.build(); | ||||
} | } | ||||
/** | /** | ||||
* A factory class for creating {@link LayoutEngineCheck} instances. | * 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>() { | registerCheckFactory("true", new CheckFactory<LayoutEngineCheck>() { | ||||
public LayoutEngineCheck createCheck(Element element) { | public LayoutEngineCheck createCheck(Element element) { |
<?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> |
<?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> |
<?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> |