瀏覽代碼

FOP-2213 use kern table when no GPOS kern lookups are present

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-ffa450edef68
tags/fop-2_0
Glenn Adams 9 年之前
父節點
當前提交
6300064cb5

+ 4
- 1
build.xml 查看文件

@@ -898,9 +898,12 @@ list of possible build targets.
<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

+ 1
- 1
src/java/org/apache/fop/apps/FopConfParser.java 查看文件

@@ -141,7 +141,7 @@ public class FopConfParser {
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;

+ 20
- 3
src/java/org/apache/fop/complexscripts/fonts/GlyphTable.java 查看文件

@@ -223,7 +223,11 @@ public class GlyphTable {
}
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;
}
}

/**
@@ -274,6 +278,19 @@ public class GlyphTable {
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());
@@ -350,8 +367,8 @@ public class GlyphTable {
* @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))) {

+ 434
- 0
src/java/org/apache/fop/complexscripts/fonts/OTFLanguage.java 查看文件

@@ -0,0 +1,434 @@
/*
* 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() {
}
}

+ 154
- 0
src/java/org/apache/fop/complexscripts/fonts/OTFScript.java 查看文件

@@ -0,0 +1,154 @@
/*
* 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() {
}
}

+ 5
- 0
src/java/org/apache/fop/fonts/Font.java 查看文件

@@ -160,6 +160,11 @@ public class Font implements Substitutable, Positionable {
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

+ 12
- 2
src/java/org/apache/fop/fonts/FontMetrics.java 查看文件

@@ -135,8 +135,8 @@ public interface FontMetrics {
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();

@@ -180,4 +180,14 @@ public interface FontMetrics {
*/
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);
}

+ 14
- 8
src/java/org/apache/fop/fonts/GlyphMapping.java 查看文件

@@ -25,6 +25,7 @@ import org.apache.commons.logging.Log;
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;
@@ -128,15 +129,14 @@ public class GlyphMapping {
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
@@ -166,6 +166,10 @@ public class GlyphMapping {
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.
@@ -174,7 +178,7 @@ public class GlyphMapping {
* @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
@@ -196,10 +200,12 @@ public class GlyphMapping {
}
// 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;

+ 6
- 0
src/java/org/apache/fop/fonts/LazyFont.java 查看文件

@@ -317,6 +317,12 @@ public class LazyFont extends Typeface implements FontDescriptor, Substitutable,
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}

+ 16
- 0
src/java/org/apache/fop/fonts/MultiByteFont.java 查看文件

@@ -35,6 +35,7 @@ import org.apache.fop.apps.io.InternalResourceResolver;
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;
@@ -651,6 +652,21 @@ public class MultiByteFont extends CIDFont implements Substitutable, Positionabl
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;
}

+ 5
- 0
src/java/org/apache/fop/fonts/Typeface.java 查看文件

@@ -103,6 +103,11 @@ public abstract class Typeface implements FontMetrics {
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.

+ 388
- 0
test/java/org/apache/fop/complexscripts/layout/ComplexScriptsLayoutTestCase.java 查看文件

@@ -0,0 +1,388 @@
/*
* 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);
}
}
}

}

+ 32
- 0
test/java/org/apache/fop/complexscripts/layout/ComplexScriptsLayoutTestSuite.java 查看文件

@@ -0,0 +1,32 @@
/*
* 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 {
}

+ 2
- 4
test/java/org/apache/fop/intermediate/TestAssistant.java 查看文件

@@ -116,14 +116,12 @@ public class TestAssistant {
}

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();
}


+ 2
- 2
test/java/org/apache/fop/layoutengine/LayoutEngineChecksFactory.java 查看文件

@@ -26,9 +26,9 @@ import org.apache.fop.check.ChecksFactory;
/**
* 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) {

+ 43
- 0
test/resources/complexscripts/layout/standard-testcases/inline_kerning_jira2213.xml 查看文件

@@ -0,0 +1,43 @@
<?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>

+ 53
- 0
test/resources/complexscripts/layout/testcase2checks.xsl 查看文件

@@ -0,0 +1,53 @@
<?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>

+ 62
- 0
test/resources/complexscripts/layout/testcase2fo.xsl 查看文件

@@ -0,0 +1,62 @@
<?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>

Loading…
取消
儲存