diff --git a/pipeline-braille-utils/css-utils/src/main/resources/xml/transform/block-translator-template.xsl b/pipeline-braille-utils/css-utils/src/main/resources/xml/transform/block-translator-template.xsl index 4ea085e5c..275a9daf1 100644 --- a/pipeline-braille-utils/css-utils/src/main/resources/xml/transform/block-translator-template.xsl +++ b/pipeline-braille-utils/css-utils/src/main/resources/xml/transform/block-translator-template.xsl @@ -77,8 +77,8 @@ + css:computed-properties($inline-properties, false(), $this) + [not(@value=css:initial-value(@name))]))"/> diff --git a/pipeline-braille-utils/css/css-calabash/src/main/java/org/daisy/braille/css/calabash/CSSInlineStep.java b/pipeline-braille-utils/css/css-calabash/src/main/java/org/daisy/braille/css/calabash/CSSInlineStep.java index 0b0765ace..1cc9e1c83 100755 --- a/pipeline-braille-utils/css/css-calabash/src/main/java/org/daisy/braille/css/calabash/CSSInlineStep.java +++ b/pipeline-braille-utils/css/css-calabash/src/main/java/org/daisy/braille/css/calabash/CSSInlineStep.java @@ -112,10 +112,12 @@ public void run() throws SaxonApiException { XdmNode source = sourcePipe.read(); Document doc = (Document)DocumentOverNodeInfo.wrap(source.getUnderlyingNode()); URL defaultSheet = asURL(emptyToNull(getOption(_default_stylesheet, ""))); - resultPipe.write((new InlineCSSWriter(doc, runtime, defaultSheet)).getResult()); } + resultPipe.write((new InlineCSSWriter(doc, runtime, defaultSheet)).getResult()); + } catch (Exception e) { logger.error("css:inline failed", e); - throw new XProcException(step.getNode(), e); } + throw new XProcException(step.getNode(), e); + } } @Component( @@ -202,7 +204,8 @@ else if (attr.getPrefix() != null) addAttribute(new QName(attr.getPrefix(), attr.getNamespaceURI(), attr.getLocalName()), attr.getNodeValue()); else if ("style".equals(attr.getLocalName())) {} else - addAttribute(new QName(attr.getNamespaceURI(), attr.getLocalName()), attr.getNodeValue()); } + addAttribute(new QName(attr.getNamespaceURI(), attr.getLocalName()), attr.getNodeValue()); + } StringBuilder style = new StringBuilder(); NodeData brailleData = brailleStylemap.get((Element)node); if (brailleData != null) @@ -226,17 +229,20 @@ else if ("style".equals(attr.getLocalName())) {} else page = pages.get(pageProperty.toString()); if (page != null) - insertPageStyle(style, page, pages.get("auto")); } + insertPageStyle(style, page, pages.get("auto")); + } else if (isRoot) { RulePage page = pages.get("auto"); if (page != null) - insertPageStyle(style, page, null); } - if (normalizeSpace(style).length() > 0) { - addAttribute(_style, style.toString().trim()); } + insertPageStyle(style, page, null); + } + if (normalizeSpace(style).length() > 0) + addAttribute(_style, style.toString().trim()); receiver.startContent(); for (Node child = node.getFirstChild(); child != null; child = child.getNextSibling()) traverse(child); - addEndElement(); } + addEndElement(); + } else if (node.getNodeType() == Node.COMMENT_NODE) addComment(node.getNodeValue()); else if (node.getNodeType() == Node.TEXT_NODE) @@ -256,7 +262,8 @@ public void addStartElement(Element element) { List namespaces = new ArrayList(); Iterators.addAll(namespaces, NamespaceIterator.iterateNamespaces(inode)); inscopeNS = Iterables.toArray(namespaces, NamespaceBinding.class); - seenRoot = true; } + seenRoot = true; + } receiver.setSystemId(element.getBaseURI()); addStartElement(new NameOfNode(inode), inode.getSchemaType(), inscopeNS); } @@ -282,14 +289,17 @@ private static void insertStyle(StringBuilder builder, NodeData nodeData) { builder.append(termToString.apply(value)); else { CSSProperty prop = nodeData.getProperty(key); - builder.append(prop); } - builder.append("; "); } + builder.append(prop); + } + builder.append("; "); + } } private static void insertPseudoStyle(StringBuilder builder, NodeData nodeData, Selector.PseudoDeclaration decl) { if (builder.length() > 0 && !builder.toString().endsWith("} ")) { builder.insert(0, "{ "); - builder.append("} "); } + builder.append("} "); + } builder.append(decl.isPseudoElement() ? "::" : ":").append(decl.value()).append(" { "); insertStyle(builder, nodeData); builder.append("} "); @@ -298,7 +308,8 @@ private static void insertPseudoStyle(StringBuilder builder, NodeData nodeData, private static void insertPageStyle(StringBuilder builder, RulePage rulePage, RulePage inheritFrom) { if (builder.length() > 0 && !builder.toString().endsWith("} ")) { builder.insert(0, "{ "); - builder.append("} "); } + builder.append("} "); + } builder.append("@page "); String pseudo = rulePage.getPseudo(); if (pseudo != null && !"".equals(pseudo)) @@ -307,7 +318,8 @@ private static void insertPageStyle(StringBuilder builder, RulePage rulePage, Ru List seen = new ArrayList(); for (Declaration decl : Iterables.filter(rulePage, Declaration.class)) { seen.add(decl.getProperty()); - insertDeclaration(builder, decl); } + insertDeclaration(builder, decl); + } if (inheritFrom != null) for (Declaration decl : Iterables.filter(inheritFrom, Declaration.class)) if (!seen.contains(decl.getProperty())) @@ -315,7 +327,8 @@ private static void insertPageStyle(StringBuilder builder, RulePage rulePage, Ru seen.clear(); for (RuleMargin margin : Iterables.filter(rulePage, RuleMargin.class)) { seen.add(margin.getMarginArea().value); - insertMarginStyle(builder, margin); } + insertMarginStyle(builder, margin); + } if (inheritFrom != null) for (RuleMargin margin : Iterables.filter(inheritFrom, RuleMargin.class)) if (!seen.contains(margin.getMarginArea().value)) diff --git a/pipeline-braille-utils/css/css-core/src/main/java/org/daisy/braille/css/BrailleCSSDeclarationTransformer.java b/pipeline-braille-utils/css/css-core/src/main/java/org/daisy/braille/css/BrailleCSSDeclarationTransformer.java index 2a0beacb1..522502edf 100644 --- a/pipeline-braille-utils/css/css-core/src/main/java/org/daisy/braille/css/BrailleCSSDeclarationTransformer.java +++ b/pipeline-braille-utils/css/css-core/src/main/java/org/daisy/braille/css/BrailleCSSDeclarationTransformer.java @@ -17,6 +17,7 @@ import org.daisy.braille.css.BrailleCSSProperty.Page; import org.daisy.braille.css.BrailleCSSProperty.StringSet; import org.daisy.braille.css.BrailleCSSProperty.TextIndent; +import org.daisy.braille.css.BrailleCSSProperty.TextTransform; import cz.vutbr.web.css.CSSFactory; import cz.vutbr.web.css.CSSProperty; @@ -281,6 +282,32 @@ private boolean processTextIndent(Declaration d, d, properties, values); } + @SuppressWarnings("unused") + private boolean processTextTransform(Declaration d, + Map properties, Map> values) { + if (d.size() == 1 && genericOneIdent(TextTransform.class, d, properties)) + return true; + + TermList list = tf.createList(); + for (Term t : d.asList()) { + if (t instanceof TermIdent) { + String value = ((TermIdent)t).getValue().toLowerCase(); + if (!value.equals("none") && !value.equals("auto") + && !value.equals("uppercase") && !value.equals("lowercase")) + list.add(t); + } + else + return false; + } + + if (list.isEmpty()) + return false; + + properties.put("text-transform", TextTransform.list_values); + values.put("text-transform", list); + return true; + } + /**************************************************************** * GENERIC METHODS ****************************************************************/ diff --git a/pipeline-braille-utils/css/css-core/src/main/java/org/daisy/braille/css/BrailleCSSProperty.java b/pipeline-braille-utils/css/css-core/src/main/java/org/daisy/braille/css/BrailleCSSProperty.java index 0f84bbe10..7b673d5f8 100644 --- a/pipeline-braille-utils/css/css-core/src/main/java/org/daisy/braille/css/BrailleCSSProperty.java +++ b/pipeline-braille-utils/css/css-core/src/main/java/org/daisy/braille/css/BrailleCSSProperty.java @@ -239,4 +239,27 @@ public String toString() { return text; } } + + public enum TextTransform implements BrailleCSSProperty { + list_values(""), NONE("none"), AUTO("auto"), UPPERCASE("uppercase"), LOWERCASE("lowercase"), INHERIT("inherit"); + + private String text; + + private TextTransform(String text) { + this.text = text; + } + + public boolean inherited() { + return false; + } + + public boolean equalsInherit() { + return this == INHERIT; + } + + @Override + public String toString() { + return text; + } + } } diff --git a/pipeline-braille-utils/css/css-core/src/main/java/org/daisy/braille/css/SupportedBrailleCSS.java b/pipeline-braille-utils/css/css-core/src/main/java/org/daisy/braille/css/SupportedBrailleCSS.java index ecb8c0204..91cabd3e2 100644 --- a/pipeline-braille-utils/css/css-core/src/main/java/org/daisy/braille/css/SupportedBrailleCSS.java +++ b/pipeline-braille-utils/css/css-core/src/main/java/org/daisy/braille/css/SupportedBrailleCSS.java @@ -32,6 +32,7 @@ import org.daisy.braille.css.BrailleCSSProperty.Page; import org.daisy.braille.css.BrailleCSSProperty.StringSet; import org.daisy.braille.css.BrailleCSSProperty.TextIndent; +import org.daisy.braille.css.BrailleCSSProperty.TextTransform; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -43,7 +44,7 @@ public class SupportedBrailleCSS implements SupportedCSS { private static Logger log = LoggerFactory.getLogger(SupportedBrailleCSS.class); - private static final int TOTAL_SUPPORTED_DECLARATIONS = 35; + private static final int TOTAL_SUPPORTED_DECLARATIONS = 36; private static final TermFactory tf = CSSFactory.getTermFactory(); @@ -231,6 +232,8 @@ private void setSupportedCSS() { embossedProperties.add("string-set"); props.put("content", Content.NONE); embossedProperties.add("content"); + props.put("text-transform", TextTransform.AUTO); + embossedProperties.add("text-transform"); /* ----------- */ /* media print */ diff --git a/pipeline-braille-utils/css/css-core/src/main/resources/xml/base.xsl b/pipeline-braille-utils/css/css-core/src/main/resources/xml/base.xsl index 22b670cd4..1a266e091 100644 --- a/pipeline-braille-utils/css/css-core/src/main/resources/xml/base.xsl +++ b/pipeline-braille-utils/css/css-core/src/main/resources/xml/base.xsl @@ -409,6 +409,12 @@ + + + + + + @@ -456,6 +462,17 @@ + + + + + + + + + + diff --git a/pipeline-braille-utils/css/css-core/src/main/resources/xml/braille-css.xsl b/pipeline-braille-utils/css/css-core/src/main/resources/xml/braille-css.xsl index 078e1f33d..25bd0d6d4 100644 --- a/pipeline-braille-utils/css/css-core/src/main/resources/xml/braille-css.xsl +++ b/pipeline-braille-utils/css/css-core/src/main/resources/xml/braille-css.xsl @@ -51,6 +51,7 @@ 'white-space', 'hyphens', 'size', + 'text-transform', 'font-style', 'font-weight', 'text-decoration', @@ -89,6 +90,7 @@ re:exact(re:or(('normal','pre-wrap','pre-line'))), re:exact(re:or(('auto','manual','none'))), re:exact(concat('(',$css:NON_NEGATIVE_INTEGER_RE,')\s+(',$css:NON_NEGATIVE_INTEGER_RE,')')), + re:exact(re:or(($css:IDENT_LIST_RE,'none','auto','uppercase','lowercase'))), re:exact(re:or(('normal','italic','oblique'))), re:exact(re:or(('normal','bold','100','200','300','400','500','600','700','800','900'))), re:exact(re:or(('none','underline','overline','line-through','blink'))), @@ -130,6 +132,7 @@ '.*', '.*', '.*', + '.*', '.*')"/> + + + + + + + + + + + + + + + + + + + + + + diff --git a/pipeline-braille-utils/css/css-core/src/test/xspec/test_braille-css.xspec b/pipeline-braille-utils/css/css-core/src/test/xspec/test_braille-css.xspec index 60dbef9b9..56237e9bf 100644 --- a/pipeline-braille-utils/css/css-core/src/test/xspec/test_braille-css.xspec +++ b/pipeline-braille-utils/css/css-core/src/test/xspec/test_braille-css.xspec @@ -322,4 +322,21 @@ + + + + + + <_ css:text-transform="bold"> + <_> + + + + + + + + + + diff --git a/pipeline-braille-utils/liblouis-utils/src/main/resources/xml/transform/liblouis-block-translate.xsl b/pipeline-braille-utils/liblouis-utils/src/main/resources/xml/transform/liblouis-block-translate.xsl index 4828c5e6c..e4389d32a 100755 --- a/pipeline-braille-utils/liblouis-utils/src/main/resources/xml/transform/liblouis-block-translate.xsl +++ b/pipeline-braille-utils/liblouis-utils/src/main/resources/xml/transform/liblouis-block-translate.xsl @@ -15,8 +15,8 @@ - + select="css:computed-properties($inline-properties, true(), parent::*)"/> + diff --git a/pipeline-braille-utils/liblouis-utils/src/test/xspec/test_liblouis-block-translate.xspec b/pipeline-braille-utils/liblouis-utils/src/test/xspec/test_liblouis-block-translate.xspec index 8622aa3b1..818eb7b19 100644 --- a/pipeline-braille-utils/liblouis-utils/src/test/xspec/test_liblouis-block-translate.xspec +++ b/pipeline-braille-utils/liblouis-utils/src/test/xspec/test_liblouis-block-translate.xspec @@ -23,4 +23,25 @@ + + + +

+ + foo bar + +

+
+
+ + +

+ + ⠋⠕⠕ ⠃⠜ + +

+
+
+
+ diff --git a/pipeline-braille-utils/liblouis/liblouis-core/src/main/java/org/daisy/pipeline/braille/liblouis/impl/LiblouisJnaImpl.java b/pipeline-braille-utils/liblouis/liblouis-core/src/main/java/org/daisy/pipeline/braille/liblouis/impl/LiblouisJnaImpl.java index 44cb5084e..f2eb13ef3 100644 --- a/pipeline-braille-utils/liblouis/liblouis-core/src/main/java/org/daisy/pipeline/braille/liblouis/impl/LiblouisJnaImpl.java +++ b/pipeline-braille-utils/liblouis/liblouis-core/src/main/java/org/daisy/pipeline/braille/liblouis/impl/LiblouisJnaImpl.java @@ -5,6 +5,7 @@ import java.net.URL; import java.util.ArrayList; import java.util.Arrays; +import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; @@ -91,11 +92,15 @@ public File[] invoke(String tableList, File base) { logger.debug("Resolved to " + join(resolved, ",")); else logger.error("Table could not be resolved"); - return resolved; }}; - Louis.getLibrary().lou_registerTableResolver(_tableResolver); } + return resolved; + } + }; + Louis.getLibrary().lou_registerTableResolver(_tableResolver); + } catch (Throwable e) { logger.error("liblouis service could not be loaded", e); - throw e; } + throw e; + } } @Deactivate @@ -116,7 +121,9 @@ protected void bindLibrary(BundledNativePath path) { if (libraryPath != null) { Louis.setLibraryPath(asFile(libraryPath)); nativePath = path; - logger.debug("Registering liblouis library: " + libraryPath); }} + logger.debug("Registering liblouis library: " + libraryPath); + } + } } protected void unbindLibrary(BundledNativePath path) { @@ -194,10 +201,14 @@ private Iterable get(final URI[] table, String hyphenator, L try { translators = Optional.fromNullable( new LiblouisTranslatorHyphenatorImpl(table) - ).asSet(); } + ).asSet(); + } catch (CompilationException e) { - logger.warn("Could not create translator for table: " + Arrays.toString(table), e); } - break; }} + logger.warn("Could not create translator for table: " + Arrays.toString(table), e); + } + break; + } + } String hyphenatorQuery = "(locale:" + locale + ")"; if (!"auto".equals(hyphenator)) hyphenatorQuery = hyphenatorQuery + "(hyphenator:" + hyphenator + ")"; @@ -208,18 +219,26 @@ private Iterable get(final URI[] table, String hyphenator, L hyphenators.get(hyphenatorQuery), new Function() { public LiblouisTranslator apply(Hyphenator hyphenator) { - try { return new LiblouisTranslatorImpl(table, hyphenator); } + try { return new LiblouisTranslatorImpl(table, hyphenator); + } catch (CompilationException e) { - logger.warn("Could not create translator for table: " + Arrays.toString(table), e); } - return null; }}), - Predicates.notNull())); } + logger.warn("Could not create translator for table: " + Arrays.toString(table), e); + } + return null; + } + }), + Predicates.notNull())); + } try { translators = Iterables.concat( translators, - Optional.fromNullable(new LiblouisTranslatorImpl(table)).asSet()); } + Optional.fromNullable(new LiblouisTranslatorImpl(table)).asSet()); + } catch (CompilationException e) { - logger.warn("Could not create translator for table: " + Arrays.toString(table), e); } - return translators; } + logger.warn("Could not create translator for table: " + Arrays.toString(table), e); + } + return translators; + } logger.debug("Could not resolve table: " + Arrays.toString(table)); return empty; } @@ -243,8 +262,12 @@ public Iterable delegate(String query) { tableProvider.get(locale), new Function>() { public Iterable apply(URI[] table) { - return LiblouisJnaImpl.this.get(table, hyphenator, locale); }})); - return empty; }}; + return LiblouisJnaImpl.this.get(table, hyphenator, locale); + } + })); + return empty; + } + }; public Iterable get(String query) { return provider.get(query); @@ -297,11 +320,20 @@ public String[] transform(String[] text, String[] cssStyle) { byte[] typeform = new byte[cssStyle.length]; boolean[] hyphenate = new boolean[cssStyle.length]; for (int i = 0; i < cssStyle.length; i++) { - Map style = CSS_PARSER.split(cssStyle[i]); - typeform[i] = typeformFromInlineCSS(style); + Map style = new HashMap(CSS_PARSER.split(cssStyle[i])); + String val = style.remove("text-transform"); + typeform[i] = Typeform.PLAIN; + if (val != null) { + text[i] = textFromTextTransform(text[i], val); + typeform[i] |= typeformFromTextTransform(val); + } + val = style.remove("hyphens"); hyphenate[i] = false; - if (style.containsKey("hyphens") && "auto".equals(style.get("hyphens"))) - hyphenate[i] = true; } + if (val != null) + if ("auto".equals(val)) + hyphenate[i] = true; + typeform[i] |= typeformFromInlineCSS(style); + } return transform(text, typeform, hyphenate); } @@ -339,7 +371,8 @@ public String[] transform(String[] text, byte[] typeform, boolean[] hyphenate) { boolean someNotHyphenate = false; for (int i = 0; i < hyphenate.length; i++) { if (hyphenate[i]) someHyphenate = true; - else someNotHyphenate = true; } + else someNotHyphenate = true; + } if (someHyphenate) { byte[] autoHyphens = doHyphenate(_text); if (someNotHyphenate) { @@ -353,9 +386,13 @@ public String[] transform(String[] text, byte[] typeform, boolean[] hyphenate) { for (int k = 0; k < unhyphenated[j].length() - 1; k++) autoHyphens[i++] = 0; if (i < autoHyphens.length) - autoHyphens[i++] = 0; }}} + autoHyphens[i++] = 0; + } + } + } for (int i = 0; i < autoHyphens.length; i++) - positions[i] += autoHyphens[i]; } + positions[i] += autoHyphens[i]; + } byte[] _typeform = null; for (byte b : typeform) if (b != Typeform.PLAIN) { @@ -363,11 +400,14 @@ public String[] transform(String[] text, byte[] typeform, boolean[] hyphenate) { int i = 0; while (unhyphenated[i].length() == 0) i++; for (int j = 0; j < _typeform.length; j++) { + _typeform[j] = typeform[i]; if (positions != null && j < positions.length && (positions[j] & 4) == 4) { i++; - while (unhyphenated[i].length() == 0) i++; } - _typeform[j] = typeform[i]; } - break; } + while (unhyphenated[i].length() == 0) i++; + } + } + break; + } try { // Translate @@ -388,7 +428,8 @@ public String[] transform(String[] text, byte[] typeform, boolean[] hyphenate) { for (String s : SEGMENT_SPLITTER.split(braille)) { rv[i++] = s; while (i < text.length && unhyphenated[i].length() == 0) - rv[i++] = ""; } + rv[i++] = ""; + } if (i == text.length) return rv; else { @@ -407,9 +448,11 @@ public String[] transform(String[] text, byte[] typeform, boolean[] hyphenate) { for (int j = 0; j < positions.length; j++) { if ((positions[j] & 4) == 4) { i++; - while (i < text.length && unhyphenated[i].length() == 0) i++; } + while (i < text.length && unhyphenated[i].length() == 0) i++; + } int n = (i % 31) + 1; - positions[j] |= (byte)(n << 3); } + positions[j] |= (byte)(n << 3); + } r = translator.translate(_text, positions, _typeform); braille = r.getBraille(); outputPositions = r.getHyphenPositions(); @@ -425,7 +468,9 @@ public String[] transform(String[] text, byte[] typeform, boolean[] hyphenate) { rv[i++] = b.toString(); b = new StringBuffer(); while (((n - i - 1) % 31) > 0) - rv[i++] = ""; }} + rv[i++] = ""; + } + } b.append(braille.charAt(braille.length() - 1)); rv[i++] = b.toString(); while (i < text.length && unhyphenated[i].length() == 0) @@ -433,9 +478,13 @@ public String[] transform(String[] text, byte[] typeform, boolean[] hyphenate) { if (i == text.length) return rv; else - throw new RuntimeException("Coding error"); }}} + throw new RuntimeException("Coding error"); + } + } + } catch (TranslationException e) { - throw new RuntimeException(e); } + throw new RuntimeException(e); + } } protected byte[] doHyphenate(String text) { @@ -446,9 +495,11 @@ protected byte[] doHyphenate(String text) { public String display(String braille) { try { - return translator.display(braille); } + return translator.display(braille); + } catch (TranslationException e) { - throw new RuntimeException(e); } + throw new RuntimeException(e); + } } } @@ -491,25 +542,30 @@ public String[] hyphenate(String text[]) { for (String s : SEGMENT_SPLITTER.split(_text)) { while (unhyphenated[i].length() == 0) rv[i++] = ""; - rv[i++] = s; } - while(i < text.length) + rv[i++] = s; + } + while (i < text.length) rv[i++] = ""; - return rv; } + return rv; + } } @Override protected byte[] doHyphenate(String text) { - try { return translator.hyphenate(text); } + try { + return translator.hyphenate(text); + } catch (TranslationException e) { - throw new RuntimeException(e); } + throw new RuntimeException(e); + } } } private final static Splitter.MapSplitter CSS_PARSER = Splitter.on(';').omitEmptyStrings().withKeyValueSeparator(Splitter.on(':').limit(2).trimResults()); - + /** - * @parameter cssStyle An inline CSS style + * @parameter style An inline CSS style * @returns the corresponding typeform. Possible values are: * - 0 = PLAIN * - 1 = ITALIC (font-style: italic|oblique) @@ -527,13 +583,61 @@ protected static byte typeformFromInlineCSS(Map style) { for (String prop : style.keySet()) { String value = style.get(prop); if (prop.equals("font-style") && (value.equals("italic") || value.equals("oblique"))) - typeform += Typeform.ITALIC; + typeform |= Typeform.ITALIC; else if (prop.equals("font-weight") && value.equals("bold")) - typeform += Typeform.BOLD; + typeform |= Typeform.BOLD; else if (prop.equals("text-decoration") && value.equals("underline")) - typeform += Typeform.UNDERLINE; + typeform |= Typeform.UNDERLINE; else - logger.warn("Inline CSS property {} not supported", prop); } + logger.warn("Inline CSS property {} not supported", prop); + } + return typeform; + } + + private final static Splitter TEXT_TRANSFORM_PARSER = Splitter.on(' ').omitEmptyStrings().trimResults(); + + /** + * @parameter text The text to be transformed. + * @parameter textTransform A text-transform value as a space separated list of keywords. + * @returns the transformed text, or the original text if no transformations were performed. + */ + protected static String textFromTextTransform(String text, String textTransform) { + for (String tt : TEXT_TRANSFORM_PARSER.split(textTransform)) { + if (tt.equals("uppercase")) + text = text.toUpperCase(); + else if (tt.equals("lowercase")) + text = text.toLowerCase(); + else + logger.warn("text-transform: {} not supported", tt); + } + return text; + } + + /** + * @parameter textTransform A text-transform value as a space separated list of keywords. + * @returns the corresponding typeform. Possible values are: + * - 0 = PLAIN + * - 1 = ITALIC (louis-ital) + * - 2 = BOLD (louis-bold) + * - 4 = UNDERLINE (louis-under) + * - 8 = COMPUTER (louis-comp) + * These values can be added for multiple emphasis. + * @see http://liblouis.googlecode.com/svn/documentation/liblouis.html#lou_translateString + */ + protected static byte typeformFromTextTransform(String textTransform) { + byte typeform = Typeform.PLAIN; + for (String tt : TEXT_TRANSFORM_PARSER.split(textTransform)) { + if (tt.equals("louis-ital")) + typeform |= Typeform.ITALIC; + else if (tt.equals("louis-bold")) + typeform |= Typeform.BOLD; + else if (tt.equals("louis-under")) + typeform |= Typeform.UNDERLINE; + else if (tt.equals("louis-comp")) + typeform |= Typeform.COMPUTER; + else + logger.warn("text-transform: {} not supported", tt); + } return typeform; } diff --git a/pipeline-braille-utils/liblouis/liblouis-core/src/test/java/org/daisy/pipeline/braille/liblouis/impl/LiblouisJnaImplTest.java b/pipeline-braille-utils/liblouis/liblouis-core/src/test/java/org/daisy/pipeline/braille/liblouis/impl/LiblouisJnaImplTest.java index c4f046c5f..04fbe29cd 100644 --- a/pipeline-braille-utils/liblouis/liblouis-core/src/test/java/org/daisy/pipeline/braille/liblouis/impl/LiblouisJnaImplTest.java +++ b/pipeline-braille-utils/liblouis/liblouis-core/src/test/java/org/daisy/pipeline/braille/liblouis/impl/LiblouisJnaImplTest.java @@ -13,4 +13,26 @@ public void testTypeformFromInlineCSS() { LiblouisJnaImpl.typeformFromInlineCSS( " text-decoration: underline ;font-weight: bold ; hyphens:auto; color: #FF00FF ")); } + + @Test + public void testTextFromTextTransform() { + assertEquals("IK BEN MOOS", + LiblouisJnaImpl.textFromTextTransform("Ik ben Moos", + " uppercase ")); + assertEquals("ik ben moos", + LiblouisJnaImpl.textFromTextTransform("Ik ben Moos", + " lowercase ")); + assertEquals("ik ben moos", + LiblouisJnaImpl.textFromTextTransform("Ik ben Moos", + " uppercase lowercase ")); + assertEquals("Ik ben Moos", + LiblouisJnaImpl.textFromTextTransform("Ik ben Moos", + " foo bar ")); + } + + @Test + public void testTypeformFromTextTransform() { + assertEquals(Typeform.BOLD + Typeform.UNDERLINE, + LiblouisJnaImpl.typeformFromTextTransform(" louis-bold ital louis-under foo ")); + } }