% $Id: tex4ht-oo-xtpipes.tex 740 2020-06-13 22:35:32Z karl $ % htlatex tex4ht-oo-xtpipes "xhtml,next,3" "" "-d./" % % Copyright 2009-2020 TeX Users Group % Copyright 2001-2009 Eitan M. Gurari % Released under LPPL 1.3c+. % See tex4ht-cpright.tex for license text. \documentclass{article} \Configure{ProTex}{log,<<<>>>,title,list,`,[[]]} \usepackage{url} \begin{document} \input{common} \input{tex4ht-cpright} \input{tex4ht-dir} %%%%%%%%%%%%%%%%%% \section{Outline} %%%%%%%%%%%%%%%%%% %%%%%%%%%%%%% \subsection{Math} %%%%%%%%%%%%% \AtEndDocument{\OutputCodE\} \Needs{"xmllint --valid --noout oo-math.4xt"} \<<< >>> \<<< ` ` ` >>> \<<< >>> %%%%%%%%%%%%% \subsection{Text} %%%%%%%%%%%%% \AtEndDocument{\OutputCodE\} \Needs{"xmllint --valid --noout oo-text.4xt"} \<<< >>> %%%%%%%%%%%%% \subsubsection{Cross References} %%%%%%%%%%%%% This is not used anymore, the make4ht-t4htlinks DOM filter is used instead. The following code may produce broken or empty links, so it is not really usable. \<<< ` ` ` >>> \<<< ` ` ` >>> \<<< >>> \<<< reference-ref text >>> \<<< simple >>> \<<< reference-ref text >>> \begin{itemize} \item External \begin{verbatim} ... \end{verbatim} \item internal \url{http://www.linuxjournal.com/article/8112} \begin{verbatim} is above \end{verbatim} \end{itemize} %%%%%%%%%%%%% \subsection{Java Utilities} %%%%%%%%%%%%% \AtEndDocument{\OutputCodE\} \ifdojava \Needs{" javac OoUtilities.java -d \XTPIPES "} \fi \<<< package tex4ht; /* OoUtilities.java (`version), generated from `jobname.tex Copyright (C) 2009-2013 TeX Users Group Copyright (C) `CopyYear.2006. Eitan M. Gurari ` */ import org.w3c.dom.*; public class OoUtilities { ` ` ` } >>> ` %%%%%%%%%%%%%%%%%% \section{Text Table} %%%%%%%%%%%%%%%%%% % % % % \<<< % % ` % ` % ` % % % >>> % % \<<< % % % % % % >>> % % % \<<< % % % % % % >>> % % % %%%%%%%%%%%%% \subsection{Outline} %%%%%%%%%%%%% \<<< >>> \<<< public static void table(Node dom) { Node tblRow, tblCell, d; // int cols = 0; Node node = dom.getFirstChild(); ` ` if( (tblRow != null) && (tblRow.getPreviousSibling() != null) ){ ` if( !bool ){ ` ` tblCell = tblRow.getFirstChild(); if( (tblCell != null) && (tblCell.getNextSibling() == null) && justSpace(tblCell) ){ node.removeChild(tblRow); } } } ` ` } >>> \begin{verbatim} .... .... \end{verbatim} %%%%%%%%%%%%% \subsection{Remove Rows} %%%%%%%%%%%%% \<<< tblRow = node.getLastChild(); while( (tblRow != null) // && (tblRow.getNodeType() == Node.TEXT_NODE) // && tblRow.getNodeValue().trim().equals("") && tblRow.getTextContent().trim().equals("") ){ node.removeChild(tblRow); tblRow = node.getLastChild(); } >>> %%%%%%%%%%%%% \subsection{Remove Extra Column Declarations} %%%%%%%%%%%%% \<<< tblCell = tblRow.getFirstChild(); while( tblCell != null){ d = tblCell.getNextSibling(); if( justSpace(tblCell) ){ tblRow.removeChild(tblCell); } tblCell = d; } >>> \<<< int n = 0; tblRow = node.getFirstChild(); while( tblRow != null ){ if( (tblRow.getNodeType() == Node.ELEMENT_NODE) && tblRow.getNodeName().equals("table:table-row") ){ ` if( m > n ){ n = m; } } tblRow = tblRow.getNextSibling(); } >>> \<<< int m = 0; tblCell = tblRow.getFirstChild(); while( tblCell != null ){ if( (tblCell.getNodeType() == Node.ELEMENT_NODE) && tblCell.getNodeName().equals("table:table-cell") ){ m++; ` } tblCell = tblCell.getNextSibling(); } >>> \<<< tblRow = node.getFirstChild(); while( tblRow != null ){ d = tblRow.getNextSibling(); if( (tblRow.getNodeType() == Node.ELEMENT_NODE) && tblRow.getNodeName().equals("table:table-column") ){ n--; if( n < 0 ){ tblRow.getParentNode().removeChild(tblRow); } } tblRow = d; } >>> %%%%%%%%%%%%% \subsection{Remove Empty Paragraphs within Table Cell} %%%%%%%%%%%%% There is an exception for paragraphs that are the only child elements. \<<< Node child = tblCell.getLastChild(); while( child != null ){ Node prevChild = child.getPreviousSibling(); if( (child.getNodeType() == Node.ELEMENT_NODE) && child.getNodeName().equals("text:p") ){ Node sibling = child.getPreviousSibling(); while( (sibling != null) && (sibling.getNodeType() != Node.ELEMENT_NODE) ){ sibling = sibling.getPreviousSibling(); } if( sibling == null ){ sibling = child.getNextSibling(); while( (sibling != null) && (sibling.getNodeType() != Node.ELEMENT_NODE) ){ sibling = sibling.getNextSibling(); } } if( (sibling != null) && child.getTextContent().trim().equals("") ){ tblCell.removeChild(child); } } child = prevChild; } >>> %%%%%%%%%%%%% \subsection{Test for Empty Nodes} %%%%%%%%%%%%% \<<< static boolean justSpace(Node node){ if( node == null ){ return true; } if( node.getNodeType() == Node.TEXT_NODE ){ if( !node.getNodeValue().trim().equals("") ){ return false; } } else { if( node.getNodeType() == Node.ELEMENT_NODE ){ String nm = node.getNodeName(); if( !nm.equals("table:table-cell") && !nm.equals("text:p") ){ return false; } } } if(!justSpace( node.getNextSibling() )){ return false; } if(!justSpace( node.getFirstChild() )){ return false; } return true; } >>> \<<< boolean bool = false; if( tblRow.getNodeName().equals("table:table-row") && tblRow.hasAttributes() ){ NamedNodeMap attributes = tblRow.getAttributes(); Node styleAttr = attributes.getNamedItem( "table:style-name" ); String style = (styleAttr==null)? null : styleAttr.getNodeValue(); if( (style != null) && ( style.equals("hline-row") || style.equals("cline-row") ) ){ bool = true; } } >>> %%%%%%%%%%%%%%%%%% \section{Nested Paragraphs (OoUtilities)} %%%%%%%%%%%%%%%%%% \<<< ` ` ` ` ` >>> \<<< start-subjclass end-subjclass >>> \<<< >>> \<<< start end_ >>> \<<< >>> \<<< _ _ >>> \<<< >>> \<<< >>> \<<< System.out.println("handle mixed content " + name); int i=0; for( Node nd = first; nd != null; nd = nd.getNextSibling() ){ nodeType = nd.getNodeType(); ` i++; } System.out.println("end handle mixed content " + name); >>> \<<< System.out.println("text:p into text:section"); >>> \<<< System.out.println( i + " "+ ((Boolean)v.get(i)) + ((nodeType == Node.TEXT_NODE)? (" TEXT: " + nd.getNodeValue() ) : ( (nodeType == Node.ELEMENT_NODE)? (" " + nd.getNodeName()) : "" ) )); >>>> %%%%%%%%%%%%%%%%%% \section{Spaces for Headers} %%%%%%%%%%%%%%%%%% \<<< ` ` ` ` >>> \<<< >>> \<<< >>> \<<< >>> \<<< >>> %%%%%%%%%%%%%%%%%% \section{mo} %%%%%%%%%%%%%%%%%% \<<< ` ` ` ` >>> A translation of \begin{verbatim} 2 + \end{verbatim} to \begin{verbatim} 2 + \end{verbatim} fails to satisfy OO. So the following alternative is offered \begin{verbatim} 2 + \end{verbatim} \<<< >>> Isolated mo elements are problematic (e.g., \verb'=') in OpenOffice (\url{http://lists.w3.org/Archives/Public/www-math/2006Jul/0012.html}) so they are converted into mtext elements. \<<< >>> The original condition `not(preceding-sibling::* or following-sibling::*)' failed with java 1.6 at a MS OS. \begin{verbatim} import java.io.*; import javax.xml.transform.*; import javax.xml.transform.stream.*; public class Test { public static void main(String[] args) throws TransformerConfigurationException, TransformerException { try{ StreamSource xslt = new StreamSource(new File("test.xslt")); TransformerFactory fc = TransformerFactory.newInstance(); Transformer transformer = fc.newTransformer( xslt ); } catch (javax.xml.transform.TransformerConfigurationException e){ } catch (Exception e){ System.err.println(e); } } } \end{verbatim} Failes on braces within mo elements \verb+{+. Accepts them within mtext elements. \<<< >>> \begin{verbatim} A \begin{eqnarray}a&=&b\end{eqnarray} is translated by tex4ht into a=b and is loaded as matrix {a # = # b} by OO2 into a broken display. The xtpipe phase `fixes' the problem by producing improper mathml output a=b which OO2 loads as matrix {a # "=" # b} and provides proper display. \end{verbatim} \<<< >>> In cases like \verb!$m \bmod n$!, OpenOffice swallos the characters following the first one. \<<< >>> %%%%%%%%%%%%%%%%%% \section{mrow} %%%%%%%%%%%%%%%%%% OpenOffice 2 loads \begin{verbatim} x i j \end{verbatim} and \begin{verbatim} x i j \end{verbatim} into \verb'x_i_j' which is a broken expression. Editing in OpenOffice the source into \verb'x_{i_j}' or \verb'{x}_{{i}_{j}}' \<<< ` ` ` >>> \<<< >>> \begin{verbatim} The output of tex4ht on $x_{i_j}$ is x i j and OO2 loads the code into a broken format and view x_i_j. The same outcome occurs when tex4ht is modified to produce the following output. x i j A manual editing of x_i_j into {x}_{{i}_{j}} or x_{i_j} provides the proper display (and identical mathml code). \end{verbatim} %%%%%%%%%%%%%%%%%% \section{Dimenstions of Math Tables} %%%%%%%%%%%%%%%%%% %%%%%%%%%%%%% \subsection{Background} %%%%%%%%%%%%% All columns explicitly require identical number of columns. Broken: \begin{verbatim} 1 2 1 \end{verbatim} Works: \begin{verbatim} 1 2 1 \end{verbatim} The last \verb+\\+ produces extra line with single entry and no data. \begin{verbatim} $ \begin{cases} 1 & 2\\ 3 & 4\\ \end{cases} $ \end{verbatim} Singlton mspace breaks math tables: \begin{verbatim} 1 \end{verbatim} %%%%%%%%%%%%% \subsection{Outline} %%%%%%%%%%%%% \<<< >>> \<<< public static void mtable(Node dom) { Node mtr, mtd, d; int cols = 0; Node node = dom.getFirstChild(); ` ` } >>> %%%%%%%%%%%%% \subsection{Remove Trailing Entries} %%%%%%%%%%%%% \<<< if (node.hasChildNodes()) { mtr = node.getLastChild(); while( mtr != null){ if( mtr.getNodeType() == Node.ELEMENT_NODE ){ if (mtr.hasChildNodes()) { mtd = mtr.getLastChild(); int count = 0; while( mtd != null){ if( mtd.getNodeType() == Node.ELEMENT_NODE ){ count++; d = mtd.getFirstChild(); if( d != null ){ ` } if( d != null ){ ` } } d = mtd; mtd = mtd.getPreviousSibling(); ` if( (d != null) && (d.getNodeType() == Node.ELEMENT_NODE) ){ ` if( d == null ){ count--; } } } if( count > cols ){ cols = count; } } } d = mtr; mtr = mtr.getPreviousSibling(); ` if( d != null ){ ` } } } >>> \<<< if( (d.getNodeType() == Node.TEXT_NODE) && d.getNodeValue().trim().equals("") ){ d.getParentNode().removeChild(d); d = null; } >>> \<<< if( (d.getNextSibling()==null) && (d.getFirstChild()==null) ){ d.getParentNode().removeChild(d); d = null; } >>> %%%%%%%%%%%%% \subsection{Fill Rows} %%%%%%%%%%%%% \<<< if (node.hasChildNodes()) { mtr = node.getFirstChild(); while( mtr != null){ if( mtr.getNodeType() == Node.ELEMENT_NODE ){ int count = 0; if (mtr.hasChildNodes()) { mtd = mtr.getFirstChild(); while( mtd != null){ if( mtd.getNodeType() == Node.ELEMENT_NODE ){ ` count++; } mtd = mtd.getNextSibling(); } } if( count < cols ){ ` } } mtr = mtr.getNextSibling(); } } >>> \<<< for(int i = count; i < cols; i++){ mtr.appendChild( ((Document) dom).createElement("math:mtd") ); } >>> \<<< mtr.insertBefore( ((Document) dom).createTextNode("\n"), mtd ); >>> %%%%%%%%%%%%% \subsection{mspace} %%%%%%%%%%%%% \<<< boolean remove = true; for(Node i=d; i!=null; i=i.getNextSibling() ){ if( (i.getNodeType() == Node.ELEMENT_NODE) && !i.getNodeName().equals("math:mspace") ) { remove = false; break; } } if( remove ){ while( d != null ){ mtd.removeChild(d); d = mtd.getFirstChild(); } } >>> %%%%%%%%%%%%%%%%%% \section{Shared} %%%%%%%%%%%%%%%%%% %%%%%%%%%%%%% \subsection{XSLT Setup} %%%%%%%%%%%%% \<<< >>> \<<< >>> \<<< ]]> >>> %%%%%%%%%%%%% \subsection{Text Namespaces} %%%%%%%%%%%%% \<<< ((Element) node).setAttribute( "xmlns:office", "urn:oasis:names:tc:opendocument:xmlns:office:1.0" ); ((Element) node).setAttribute( "xmlns:style", "urn:oasis:names:tc:opendocument:xmlns:style:1.0" ); ((Element) node).setAttribute( "xmlns:text", "urn:oasis:names:tc:opendocument:xmlns:text:1.0" ); ((Element) node).setAttribute( "xmlns:table", "urn:oasis:names:tc:opendocument:xmlns:table:1.0" ); ((Element) node).setAttribute( "xmlns:draw", "urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" ); ((Element) node).setAttribute( "xmlns:fo", "http://www.w3.org/1999/XSL/Format" ); ((Element) node).setAttribute( "xmlns:xlink", "http://www.w3.org/1999/xlink" ); ((Element) node).setAttribute( "xmlns:dc", "http://purl.org/dc/elements/1.1/" ); ((Element) node).setAttribute( "xmlns:meta", "urn:oasis:names:tc:opendocument:xmlns:meta:1.0" ); ((Element) node).setAttribute( "xmlns:number", "urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" ); ((Element) node).setAttribute( "xmlns:svg", "http://www.w3.org/2000/svg" ); ((Element) node).setAttribute( "xmlns:chart", "urn:oasis:names:tc:opendocument:xmlns:chart:1.0" ); ((Element) node).setAttribute( "xmlns:dr3d", "urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" ); ((Element) node).setAttribute( "xmlns:math", "http://www.w3.org/1998/Math/MathML" ); ((Element) node).setAttribute( "xmlns:form", "urn:oasis:names:tc:opendocument:xmlns:form:1.0" ); ((Element) node).setAttribute( "xmlns:script", "urn:oasis:names:tc:opendocument:xmlns:script:1.0" ); ((Element) node).setAttribute( "xmlns:ooo", "http://openoffice.org/2004/office" ); ((Element) node).setAttribute( "xmlns:ooow", "http://openoffice.org/2004/writer" ); ((Element) node).setAttribute( "xmlns:oooc", "http://openoffice.org/2004/calc" ); ((Element) node).setAttribute( "xmlns:dom", "http://www.w3.org/2001/xml-events" ); ((Element) node).setAttribute( "xmlns:xforms", "http://www.w3.org/2002/xforms" ); ((Element) node).setAttribute( "xmlns:xsd", "http://www.w3.org/2001/XMLSchema" ); ((Element) node).setAttribute( "xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance" ); >>> %%%%%%%%%%%%%%%%%% \section{Unicode in mtex} %%%%%%%%%%%%%%%%%% Openoffice dies on non-breaking space characters \verb+ + within mtext. \begin{verbatim} \documentclass{amsart} \begin{document} $\text{ the number of spanning trees of }$ \end{document} \end{verbatim} \AtEndDocument{\OutputCodE\} \ifdojava \Needs{" javac OomFilter.java -d \XTPIPES "} \fi \<<< package tex4ht; /* OomFilter.java (`version), generated from `jobname.tex Copyright (C) 2009-2010 TeX Users Group Copyright (C) `CopyYear.2002. Eitan M. Gurari ` */ import org.xml.sax.helpers.*; import org.xml.sax.*; import java.io.PrintWriter; public class OomFilter extends XMLFilterImpl { PrintWriter out = null; boolean mtext = false; public OomFilter( PrintWriter out, PrintWriter log, boolean trace ){ this.out = out; } public void startElement(String ns, String sName, String qName, Attributes attr) { if( qName.equals( "math:mtext" ) ){ mtext = true; } try{ super.startElement(ns, sName, qName, attr); } catch( Exception e ){ System.err.println( "--- OomFilter Error 1 --- " + e); } } public void endElement(String ns, String sName, String qName){ if( qName.equals( "math:mtext" ) ){ mtext = false; } try{ super.endElement(ns, sName, qName); } catch( Exception e ){ System.err.println( "--- OomFilter Error 2 --- " + e); } } public void characters(char[] ch, int start, int length){ try{ if ( mtext ) { for(int i = start; i>> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \section{OoFilter} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%% \subsection{Outline} %%%%%%%%%%%%% \AtEndDocument{\OutputCodE\} \ifdojava \Needs{" javac OoFilter.java -d \XTPIPES "} \fi \<<< package tex4ht; /* OoFilter.java (`version), generated from `jobname.tex Copyright (C) 2009-2010 TeX Users Group Copyright (C) `CopyYear.2002. Eitan M. Gurari ` */ ` public class OoFilter extends XMLFilterImpl { PrintWriter out = null; public OoFilter( PrintWriter out, PrintWriter log, boolean trace ){ this.out = out; } public void startElement(String ns, String sName, String qName, Attributes attr) { if( qName.equals( "draw:frame" ) ){ ` } try{ super.startElement(ns, sName, qName, attr); } catch( Exception e ){ System.err.println( "--- OoFilter Error 1 --- " + e); } } public void processingInstruction(String target, String fileName) { if( target.equals("tex4ht-lg") ){ fileName = fileName.trim(); if( fileName.replaceAll(" ","").startsWith("file=") ){ ` ` } } } } >>> %%%%%%%%%%%%% \subsection{Dimensions for Figures} %%%%%%%%%%%%% \<<< String name = attr.getValue("draw:name"); if( (name != null) && (attr.getValue("svg:width") == null) && (attr.getValue("svg:height") == null) ){ java.awt.Image image = new javax.swing.ImageIcon(name).getImage(); int width = image.getWidth(null); int height = image.getHeight(null); if( (width>0) && (height>0) ){ org.xml.sax.helpers.AttributesImpl attrs = new org.xml.sax.helpers.AttributesImpl( attr ); attrs.addAttribute(null, "svg:width", "svg:width", "String", (width * 72 / 110) + "pt"); attrs.addAttribute(null, "svg:width", "svg:height", "String", (height * 72 / 110) + "pt"); attr = attrs; } } >>> %%%%%%%%%%%%% \subsection{Font Styles} %%%%%%%%%%%%% \<<< int length = fileName.length(); int loc = fileName.indexOf(fileName.charAt(length-1)); fileName = fileName.substring(loc+1,length-1); try{ String s = ""; FileReader fr = new FileReader( fileName ); BufferedReader in = new BufferedReader( fr ); ` ` ` ` ` ` ` ` ` } catch(Exception e){ System.err.println( "--- OoFilter Error 2 --- " + e); } >>> \<<< in.close(); fr = new FileReader( fileName ); in = new BufferedReader( fr ); >>> \<<< try{ String key = "", body = ""; while( (s=in.readLine()) != null ){ if( s.startsWith("htfcss: ") ){ s = s.substring(8); int idx = s.indexOf(' '); if( idx == 0 ){ body += s; } else { ` if( idx == -1 ){ key = s; body = ""; } else { key = s.substring(0,idx); body = s.substring(idx); } } } } ` } catch(java.lang.NumberFormatException e){ System.err.println( "--- OoFilter Error 3 --- Improper record: " + s); } >>> \<<< body = body.trim(); if( body.startsWith( "@media " ) ){ body = body.substring(7).trim(); if( body.startsWith("print ") ){ body = body.substring(6).trim(); } else { key = ""; } } if( !key.equals("") ){ String [] property = body.split(";"); for( int i=0; i } } } } } >>> \<<< if( map.containsKey(key) ){ HashMap entry = map.get(key); entry.put(name,value); } else { HashMap entry = new HashMap (); entry.put(name,value); map.put(key,entry); } >>> \<<< HashMap > map = new HashMap>(); >>> \<<< try{ while( (s=in.readLine()) != null ){ if( s.startsWith("Font_css_base: ") ){ int idx = s.indexOf("Font_css_mag: "); if( idx != -1 ){ String [] pattern = s.substring(15,idx).trim().split("%s"); if( pattern.length == 3 ){ font_css_base = pattern; } pattern = (s+' ').substring(idx).trim().split("%s"); if( pattern.length == 2 ){ font_css_mag = pattern; } } } } } catch(Exception e){ System.err.println( "--- OoFilter Error 4 --- Improper record: " + s); } >>> \<<< try{ while( (s=in.readLine()) != null ){ if( s.startsWith("Font_Size:") ){ base_font_size = Integer.parseInt( s.substring(10).trim() ); } } } catch(java.lang.NumberFormatException e){ System.err.println( "--- OoFilter Error 5 --- Improper record: " + s); } >>> \<<< try{ while( (s=in.readLine()) != null ){ if( s.startsWith("Font(") ){ String [] match = s.split("\""); match[1] = match[1].trim(); match[2] = match[3].trim(); match[3] = match[5].trim(); match[4] = match[7].trim(); ` ` } } } catch(Exception e){ System.err.println( "--- OoFilter Error 6 --- Improper record: " + s); } >>> \<<< HashMap entry = map.get(match[1]); if( (entry != null) || (second < 98) || (second > 102) ){ String styleName = font_css_base[0] + match[1] + font_css_base[1] + match[2] + font_css_base[2]; if( !match[4].equals("100") ){ styleName += font_css_mag[0] + match[4] + font_css_mag[1]; } ` super.startElement(null, "style:style", "style:style", attr); ` super.startElement(null, "style:text-properties", "style:text-properties", attr); super.endElement(null, "style:text-properties", "style:text-properties"); super.endElement(null, "style:style", "style:style"); } >>> \<<< org.xml.sax.helpers.AttributesImpl attr = new org.xml.sax.helpers.AttributesImpl(); attr.addAttribute("", "style:name", "style:name", "String", styleName); attr.addAttribute("", "style:family", "style:family", "String", "text"); >>> \<<< attr = new org.xml.sax.helpers.AttributesImpl(); if( entry != null ){ Object [] name = entry.keySet().toArray(); for(int i=0; i < name.length; i++){ String value = entry.get(name[i]); attr.addAttribute("", "fo:" + (String) name[i], "fo:" + (String) name[i], "String", value); } } if( (second < 98) || (second > 102) ){ attr.addAttribute("", "fo:font-size", "fo:font-size", "String", (second / 10.0) + "pt"); } >>> % style:font-family-generic=\"swiss\" % style:font-pitch=\"variable\" \<<< String [] font_css_base = {"" , "-", ""}; String [] font_css_mag = {"x-x-", ""}; >>> \<<< (IGNORED) fprintf(css_file, (Font_css_base == NULL)? ".%s-%s" : Font_css_base, match[1], match[2]); if( !eq_str(match[4],"100") ){ (IGNORED) fprintf(css_file, (Font_css_mag == NULL)? "x-x-%s" : Font_css_mag, match[4]); } (IGNORED) fprintf(css_file, "{"); if( (second < 98) || (second > 102) ){ (IGNORED) fprintf(css_file, "font-size:%d%c;", second, '%'); } if( font_sty ) { (IGNORED) fprintf(css_file, font_sty->body); } (IGNORED) fprintf(css_file, "}\n"); >>> \<<< { if( match[3].replaceAll("[0-9]","").equals("") ){ second = (int) ( Integer.parseInt( match[3] ) * Long.parseLong( match[4] ) / base_font_size ); while( second > 700 ){ second /= 10; } } else { second = 100; } ` } >>> The following case handles cases like that of `\verb'Font("ecti","1095","10","100")'', where \verb=base_font_size= is 11. \<<< if( (int) ( Double.parseDouble(match[2]) / Long.parseLong(match[4]) + 0.5 ) == base_font_size ){ second = 100; }; >>> \<<< int base_font_size = 10; int second; >>> \<<< import java.util.*; import org.xml.sax.helpers.*; import org.xml.sax.*; import java.io.PrintWriter; import java.io.BufferedReader; import java.io.FileReader; >>> \ifdojava \AtEndDocument{\Needs{% "pushd \XTPIPES || exit 1 ; jar cf tex4ht.jar * ; popd ; mv \XTPIPES tex4ht.jar \TEXMFTEXivBIN ; if [ ! -d \TEXMFTEXivXTPIPES\space]; then exit 1; fi ; cp \XTPIPES xtpipes/lib/* \TEXMFTEXivXTPIPES "}} \fi \end{document}