More math and TexMaths work

git-svn-id: svn://svn.code.sf.net/p/writer2latex/code/trunk@160 f0f2a975-2e09-46c8-9428-3b39399b9f3c
This commit is contained in:
henrikjust 2014-08-13 06:39:15 +00:00
parent 79ae252419
commit 3dff4f20b4
15 changed files with 514 additions and 525 deletions

View file

@ -16,11 +16,11 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*
* Copyright: 2002-2012 by Henrik Just
* Copyright: 2002-2014 by Henrik Just
*
* All Rights Reserved.
*
* Version 1.2 (2012-02-26)
* Version 1.4 (2014-08-10)
*
*/
@ -80,7 +80,7 @@ public final class ConverterPalette extends ConverterBase {
private InlineConverter inlineCv;
private FieldConverter fieldCv;
private DrawConverter drawCv;
private MathmlConverter mathmlCv;
private MathConverter mathCv;
private Info info;
// Constructor
@ -117,7 +117,7 @@ public final class ConverterPalette extends ConverterBase {
public InlineConverter getInlineCv() { return inlineCv; }
public FieldConverter getFieldCv() { return fieldCv; }
public DrawConverter getDrawCv() { return drawCv; }
public MathmlConverter getMathmlCv() { return mathmlCv; }
public MathConverter getMathCv() { return mathCv; }
public Info getInfo() { return info; }
@ -172,7 +172,7 @@ public final class ConverterPalette extends ConverterBase {
inlineCv = new InlineConverter(ofr,config,this);
fieldCv = new FieldConverter(ofr,config,this);
drawCv = new DrawConverter(ofr,config,this);
mathmlCv = new MathmlConverter(ofr,config,this);
mathCv = new MathConverter(ofr,config,this);
info = new Info(ofr,config,this);
// Create master document and add this
@ -223,7 +223,7 @@ public final class ConverterPalette extends ConverterBase {
inlineCv.appendDeclarations(packages,declarations);
fieldCv.appendDeclarations(packages,declarations);
drawCv.appendDeclarations(packages,declarations);
mathmlCv.appendDeclarations(packages,declarations);
mathCv.appendDeclarations(packages,declarations);
// Add custom preamble
String sCustomPreamble = config.getCustomPreamble();

View file

@ -20,7 +20,7 @@
*
* All Rights Reserved.
*
* Version 1.4 (2014-08-06)
* Version 1.4 (2014-08-11)
*
*/
@ -31,17 +31,13 @@ import java.util.Stack;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
//import org.w3c.dom.Node;
import writer2latex.latex.util.BeforeAfter;
import writer2latex.latex.util.Context;
//import writer2latex.office.ImageLoader;
import writer2latex.office.EmbeddedObject;
import writer2latex.office.EmbeddedXMLObject;
import writer2latex.office.MIMETypes;
import writer2latex.office.OfficeReader;
import writer2latex.office.StyleWithProperties;
import writer2latex.office.XMLString;
import writer2latex.util.CSVList;
import writer2latex.util.Misc;
@ -53,9 +49,8 @@ import writer2latex.xmerge.BinaryGraphicsDocument;
public class DrawConverter extends ConverterHelper {
private boolean bNeedGraphicx = false;
private boolean bNeedOOoLaTeXPreamble = false;
// Keep track of floating frames (images, textboxes...)
// Keep track of floating frames (images, text boxes...)
private Stack<LinkedList<Element>> floatingFramesStack = new Stack<LinkedList<Element>>();
private Element getFrame(Element onode) {
@ -76,17 +71,6 @@ public class DrawConverter extends ConverterHelper {
else if (config.getBackend()==LaTeXConfig.DVIPS) pack.append("[dvips]");
pack.append("{graphicx}").nl();
}
if (bNeedOOoLaTeXPreamble) {
// The preamble may be stored in the description
String sDescription = palette.getMetaData().getDescription();
int nStart = sDescription.indexOf("%%% OOoLatex Preamble %%%%%%%%%%%%%%");
int nEnd = sDescription.indexOf("%%% End OOoLatex Preamble %%%%%%%%%%%%");
if (nStart>-1 && nEnd>nStart) {
decl.append("% OOoLaTeX preamble").nl()
.append(sDescription.substring(nStart+37,nEnd));
}
// TODO: Otherwise try the user settings...
}
}
public void handleCaption(Element node, LaTeXDocumentPortion ldp, Context oc) {
@ -129,25 +113,16 @@ public class DrawConverter extends ConverterHelper {
palette.getFieldCv().handleAnchor(node,ldp,oc);
}
else if (sName.equals(XMLString.DRAW_FRAME)) {
Element equation = palette.getTexMathsEquation(node);
if (equation!=null) {
palette.getMathmlCv().handleTexMathsEquation(equation,ldp,oc);
}
else {
if (!palette.getMathCv().handleTexMathsEquation(node,ldp)) {
// OpenDocument: Get the actual draw element in the frame
handleDrawElement(Misc.getFirstChildElement(node),ldp,oc);
}
}
else if (sName.equals(XMLString.DRAW_G)) {
Element equation = palette.getTexMathsEquation(node);
if (equation!=null) {
palette.getMathmlCv().handleTexMathsEquation(equation,ldp,oc);
}
else {
if (!palette.getMathCv().handleTexMathsEquation(node,ldp)) {
// Shapes are currently not supported
ldp.append("[Warning: Draw object ignored]");
}
}
else {
// Other drawing objects are currently not supported
@ -159,6 +134,7 @@ public class DrawConverter extends ConverterHelper {
// handle draw:object elements (OOo objects such as Chart, Math,...)
private void handleDrawObject(Element node, LaTeXDocumentPortion ldp, Context oc) {
String sHref = Misc.getAttribute(node,XMLString.XLINK_HREF);
if (sHref!=null) { // Embedded object in package or linked object
@ -169,13 +145,13 @@ public class DrawConverter extends ConverterHelper {
if (object!=null) {
if (MIMETypes.MATH.equals(object.getType()) || MIMETypes.ODF.equals(object.getType())) { // Formula!
try {
Document settings = ((EmbeddedXMLObject) object).getSettingsDOM();
Element settings = ((EmbeddedXMLObject) object).getSettingsDOM().getDocumentElement();
Document formuladoc = ((EmbeddedXMLObject) object).getContentDOM();
Element formula = Misc.getChildByTagName(formuladoc,XMLString.MATH); // Since OOo3.2
if (formula==null) {
formula = Misc.getChildByTagName(formuladoc,XMLString.MATH_MATH);
}
String sLaTeX = palette.getMathmlCv().convert(settings,formula);
String sLaTeX = palette.getMathCv().convert(settings,formula);
if (!" ".equals(sLaTeX)) { // ignore empty formulas
ldp.append(" $")
.append(sLaTeX)
@ -214,7 +190,7 @@ public class DrawConverter extends ConverterHelper {
}
if (formula!=null) {
ldp.append(" $")
.append(palette.getMathmlCv().convert(null,formula))
.append(palette.getMathCv().convert(null,formula))
.append("$");
if (Character.isLetterOrDigit(OfficeReader.getNextChar(node))) { ldp.append(" "); }
}
@ -233,7 +209,6 @@ public class DrawConverter extends ConverterHelper {
}
}
}
//--------------------------------------------------------------------------
@ -288,47 +263,6 @@ public class DrawConverter extends ConverterHelper {
String sName = frame.getAttribute(XMLString.DRAW_NAME);
palette.getFieldCv().addTarget(sName,"|graphic",ldp);
String sAnchor = frame.getAttribute(XMLString.TEXT_ANCHOR_TYPE);
// TODO: Recognize Jex equations (needs further testing of Jex)
/*Element desc = Misc.getChildByTagName(frame,XMLString.SVG_DESC);
if (desc!=null) {
String sDesc = Misc.getPCDATA(desc);
if (sDesc.startsWith("jex149$tex={") && sDesc.endsWith("}")) {
String sTeX = sDesc.substring(12,sDesc.length()-1);
if (sTeX.length()>0) {
// Succesfully extracted Jex equation!
ldp.append("$"+sTeX+"$");
return;
}
}
}*/
// Recognize OOoLaTeX equation
// The LaTeX code is embedded in a custom style attribute:
StyleWithProperties style = ofr.getFrameStyle(
Misc.getAttribute(frame, XMLString.DRAW_STYLE_NAME));
if (style!=null) {
String sOOoLaTeX = style.getProperty("OOoLatexArgs");
// The content of the attribute is <point size><paragraph sign><mode><paragraph sign><TeX code>
int n=0;
if (sOOoLaTeX!=null) {
if ((n=sOOoLaTeX.indexOf("\u00A7display\u00A7"))>-1) {
ldp.append("\\[").append(sOOoLaTeX.substring(n+9)).append("\\]");
bNeedOOoLaTeXPreamble = true;
return;
}
else if ((n=sOOoLaTeX.indexOf("\u00A7inline\u00A7"))>-1) {
ldp.append("$").append(sOOoLaTeX.substring(n+8)).append("$");
bNeedOOoLaTeXPreamble = true;
return;
}
else if ((n=sOOoLaTeX.indexOf("\u00A7text\u00A7"))>-1) {
ldp.append(sOOoLaTeX.substring(n+6));
bNeedOOoLaTeXPreamble = true;
return;
}
}
}
//if (oc.isInFrame() || "as-char".equals(sAnchor)) {
if ("as-char".equals(sAnchor)) {

View file

@ -0,0 +1,392 @@
/************************************************************************
*
* MathConverter.java
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License version 2.1, as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*
* Copyright: 2002-2014 by Henrik Just
*
* All Rights Reserved.
*
* Version 1.4 (2014-08-13)
*
*/
package writer2latex.latex;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import writer2latex.base.ConverterBase.TexMathsStyle;
import writer2latex.office.EmbeddedObject;
import writer2latex.office.EmbeddedXMLObject;
import writer2latex.office.MIMETypes;
import writer2latex.office.OfficeReader;
import writer2latex.office.StyleWithProperties;
import writer2latex.office.TableReader;
import writer2latex.office.XMLString;
import writer2latex.util.Misc;
/**
* This ConverterHelper converts mathematical content to LaTeX.
* It works slightly different than the other helpers: A number of elements may or may not
* have content that should be converted to math. Thus the methods offered first examines
* the content. If it turns out to be a mathematical formula, it is converted. Otherwise
* nothing is done, and the method returns false.
* Mathematical content may be MathML (with StarMath annotation), TexMaths or (the now obsolete) OOoLaTeX
*/
public final class MathConverter extends ConverterHelper {
private StarMathConverter smc;
private boolean bContainsFormulas = false;
private boolean bAddParAfterDisplay = false;
private boolean bNeedOOoLaTeXPreamble = false;
private Element theEquation = null;
private Element theSequence = null;
public MathConverter(OfficeReader ofr,LaTeXConfig config, ConverterPalette palette) {
super(ofr,config,palette);
smc = new StarMathConverter(palette.getI18n(),config);
bAddParAfterDisplay = config.formatting()>=LaTeXConfig.CONVERT_MOST;
}
public void appendDeclarations(LaTeXDocumentPortion pack, LaTeXDocumentPortion decl) {
if (bContainsFormulas) {
if (config.useOoomath()) {
pack.append("\\usepackage{ooomath}").nl();
}
else {
smc.appendDeclarations(pack,decl);
}
}
if (bNeedOOoLaTeXPreamble) {
// The preamble may be stored in the description
String sDescription = palette.getMetaData().getDescription();
int nStart = sDescription.indexOf("%%% OOoLatex Preamble %%%%%%%%%%%%%%");
int nEnd = sDescription.indexOf("%%% End OOoLatex Preamble %%%%%%%%%%%%");
if (nStart>-1 && nEnd>nStart) {
decl.append("% OOoLaTeX preamble").nl()
.append(sDescription.substring(nStart+37,nEnd));
}
}
}
// TODO: Replace with a method "handleEquation"
public String convert(Element settings, Element formula) {
// TODO: Use settings to determine display mode/text mode
// formula must be a math:math node
// First try to find a StarMath annotation
Node semantics = Misc.getChildByTagName(formula,XMLString.SEMANTICS); // Since OOo 3.2
if (semantics==null) {
semantics = Misc.getChildByTagName(formula,XMLString.MATH_SEMANTICS);
}
if (semantics!=null) {
Node annotation = Misc.getChildByTagName(semantics,XMLString.ANNOTATION); // Since OOo 3.2
if (annotation==null) {
annotation = Misc.getChildByTagName(semantics,XMLString.MATH_ANNOTATION);
}
if (annotation!=null) {
String sStarMath = "";
if (annotation.hasChildNodes()) {
NodeList anl = annotation.getChildNodes();
int nLen = anl.getLength();
for (int i=0; i<nLen; i++) {
if (anl.item(i).getNodeType() == Node.TEXT_NODE) {
sStarMath+=anl.item(i).getNodeValue();
}
}
bContainsFormulas = true;
return smc.convert(sStarMath);
}
}
}
// No annotation was found. In this case we should convert the mathml,
// but currently we ignore the problem.
// TODO: Investigate if Vasil I. Yaroshevich's MathML->LaTeX
// XSL transformation could be used here. (Potential problem:
// OOo uses MathML 1.01, not MathML 2)
if (formula.hasChildNodes()) {
return "\\text{Warning: No StarMath annotation}";
}
else { // empty formula
return " ";
}
}
/** Try to convert a draw:frame or draw:g element as an (inline) TexMaths or OOoLaTeX equation
*
* @param the element containing the equation (draw:frame or draw:g)
* @param ldp the LaTeXDocumentPortion to contain the converted equation
*
* @return true if this elements happen to be a TexMaths equation, otherwise false
*/
public boolean handleTexMathsEquation(Element node, LaTeXDocumentPortion ldp) {
String sLaTeX = null;
Element equation = palette.getTexMathsEquation(node);
if (equation!=null) {
sLaTeX = Misc.getPCDATA(equation);
}
else { // Try OOoLaTeX
// The LaTeX code is embedded in a custom style attribute:
StyleWithProperties style = ofr.getFrameStyle(Misc.getAttribute(node, XMLString.DRAW_STYLE_NAME));
if (style!=null) {
sLaTeX = style.getProperty("OOoLatexArgs");
}
}
if (sLaTeX!=null) {
// Format is <point size>X<mode>X<TeX code>X<format>X<resolution>X<transparency>
// where X is a paragraph sign
switch (palette.getTexMathsStyle(sLaTeX)) {
case inline:
ldp.append("$").append(palette.getTexMathsEquation(sLaTeX)).append("$");
break;
case display:
ldp.append("$\\displaystyle ").append(palette.getTexMathsEquation(sLaTeX)).append("$");
break;
case latex:
ldp.append(palette.getTexMathsEquation(sLaTeX));
}
return true;
}
return false;
}
/** Try to convert a table as a display equation:
* A 1 row by 2 columns table in which each cell contains exactly one paragraph,
* the left cell contains exactly one formula and the right cell contains exactly
* one sequence number is treated as a (numbered) display equation.
* This happens to coincide with the AutoText provided with OOo Writer :-)
* @param table the table reader
* @param ldp the LaTeXDocumentPortion to contain the converted equation
* @return true if the conversion was successful, false if the table
* did not represent a display equation
*/
public boolean handleDisplayEquation(TableReader table, LaTeXDocumentPortion ldp) {
if (table.getRowCount()==1 && table.getColCount()==2 &&
OfficeReader.isSingleParagraph(table.getCell(0, 0)) && OfficeReader.isSingleParagraph(table.getCell(0, 1)) ) {
// Table of the desired form
if (parseDisplayEquation(Misc.getFirstChildElement(table.getCell(0, 0))) && theEquation!=null && theSequence==null) {
// Found equation in first cell
Element myEquation = theEquation;
if (parseDisplayEquation(Misc.getFirstChildElement(table.getCell(0, 1))) && theEquation==null && theSequence!=null) {
// Found sequence in second cell
handleDisplayEquation(myEquation, theSequence, ldp);
return true;
}
}
}
return false;
}
/**Try to convert a paragraph as a display equation:
* A paragraph which contains exactly one formula + at most one sequence
* number is treated as a display equation. Other content must be brackets
* or whitespace (possibly with formatting).
* @param node the paragraph
* @param ldp the LaTeXDocumentPortion to contain the converted equation
* @return true if the conversion was successful, false if the paragraph
* did not contain a display equation
*/
public boolean handleDisplayEquation(Element node, LaTeXDocumentPortion ldp) {
if (parseDisplayEquation(node) && theEquation!=null) {
handleDisplayEquation(theEquation, theSequence, ldp);
return true;
}
else {
return false;
}
}
private void handleDisplayEquation(Element equation, Element sequence, LaTeXDocumentPortion ldp) {
boolean bTexMaths = equation.getTagName().equals(XMLString.SVG_DESC);
TexMathsStyle style = TexMathsStyle.inline;
String sLaTeX;
if (bTexMaths) {
// TeXMaths equation
sLaTeX = palette.getTexMathsEquation(Misc.getPCDATA(equation));
style = palette.getTexMathsStyle(Misc.getPCDATA(equation));
}
else {
// MathML equation
sLaTeX = convert(null,equation);
}
if (!" ".equals(sLaTeX)) { // ignore empty formulas
if (!bTexMaths || style!=TexMathsStyle.latex) {
if (sequence!=null) {
// Numbered equation
ldp.append("\\begin{equation}");
palette.getFieldCv().handleSequenceLabel(sequence,ldp);
if (bTexMaths && style==TexMathsStyle.inline) {
ldp.append("\\textstyle ");
}
ldp.nl()
.append(sLaTeX).nl()
.append("\\end{equation}").nl();
}
else {
// Unnumbered equation
ldp.append("\\begin{equation*}");
if (bTexMaths && style==TexMathsStyle.inline) {
ldp.append("\\textstyle ");
}
ldp.nl()
.append(sLaTeX).nl()
.append("\\end{equation*}").nl();
}
}
else {
ldp.append(sLaTeX).nl();
}
if (bAddParAfterDisplay) { ldp.nl(); }
}
}
/** Determine whether or not a paragraph contains a display equation.
* A paragraph is a display equation if it contains a single formula and no text content except whitespace
* and an optional sequence number which may be in brackets.
* As a side effect, this method keeps a reference to the equation and the sequence number
*
* @param node the paragraph
* @return true if this is a display equation
*/
public boolean parseDisplayEquation(Node node) {
theEquation = null;
theSequence = null;
return doParseDisplayEquation(node);
}
private boolean doParseDisplayEquation(Node node) {
Node child = node.getFirstChild();
while (child!=null) {
if (Misc.isElement(child)) {
Element elm = (Element) child;
String sName = elm.getTagName();
// First check for MathML or TexMaths equation
Element equation = getMathmlEquation(elm);
if (equation==null) {
equation = palette.getTexMathsEquation(elm);
}
if (equation!=null) {
if (theEquation==null) {
theEquation = equation;
}
else { // two or more equations -> not a display
return false;
}
}
else if (XMLString.TEXT_SEQUENCE.equals(sName)) {
if (theSequence==null) {
theSequence = elm;
}
else { // two sequence numbers -> not a display
return false;
}
}
else if (XMLString.TEXT_SPAN.equals(sName)) {
if (!doParseDisplayEquation(child)) {
return false;
}
}
else if (XMLString.TEXT_S.equals(sName)) {
// Spaces are allowed
}
else if (XMLString.TEXT_TAB.equals(sName)) {
// Tab stops are allowed
}
else if (XMLString.TEXT_TAB_STOP.equals(sName)) { // old
// Tab stops are allowed
}
else if (XMLString.TEXT_SOFT_PAGE_BREAK.equals(sName)) { // since ODF 1.1
// Soft page breaks are allowed
}
else {
// Other elements -> not a display
return false;
}
}
else if (Misc.isText(child)) {
String s = child.getNodeValue();
int nLen = s.length();
for (int i=0; i<nLen; i++) {
char c = s.charAt(i);
if (c!='(' && c!=')' && c!='[' && c!=']' && c!='{' && c!='}' && c!=' ' && c!='\u00A0') {
// Characters except brackets and whitespace -> not a display
return false;
}
}
}
child = child.getNextSibling();
}
return true;
}
/** Get a MathML formula from a draw:frame
*
* @param node the draw:frame
* @return the MathML element, or null if this is not a MathML formula
*/
public Element getMathmlEquation(Element node) {
if (node.getTagName().equals(XMLString.DRAW_FRAME)) {
node=Misc.getFirstChildElement(node);
}
String sHref = Misc.getAttribute(node,XMLString.XLINK_HREF);
if (sHref!=null) { // Embedded object in package or linked object
if (ofr.isInPackage(sHref)) { // Embedded object in package
if (sHref.startsWith("#")) { sHref=sHref.substring(1); }
if (sHref.startsWith("./")) { sHref=sHref.substring(2); }
EmbeddedObject object = palette.getEmbeddedObject(sHref);
if (object!=null) {
if (MIMETypes.MATH.equals(object.getType()) || MIMETypes.ODF.equals(object.getType())) { // Formula!
try {
Document formuladoc = ((EmbeddedXMLObject) object).getContentDOM();
Element formula = Misc.getChildByTagName(formuladoc,XMLString.MATH); // Since OOo 3.2
if (formula==null) {
formula = Misc.getChildByTagName(formuladoc,XMLString.MATH_MATH);
}
return formula;
}
catch (org.xml.sax.SAXException e) {
e.printStackTrace();
}
catch (java.io.IOException e) {
e.printStackTrace();
}
}
}
}
}
else { // flat XML, object is contained in node
Element formula = Misc.getChildByTagName(node,XMLString.MATH); // Since OOo 3.2
if (formula==null) {
formula = Misc.getChildByTagName(node,XMLString.MATH_MATH);
}
return formula;
}
return null;
}
}

View file

@ -1,249 +0,0 @@
/************************************************************************
*
* MathmlConverter.java
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License version 2.1, as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*
* Copyright: 2002-2014 by Henrik Just
*
* All Rights Reserved.
*
* Version 1.4 (2014-08-08)
*
*/
package writer2latex.latex;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import writer2latex.latex.util.Context;
import writer2latex.office.OfficeReader;
import writer2latex.office.TableReader;
import writer2latex.office.XMLString;
import writer2latex.util.Misc;
/**
* This class converts MathML nodes to LaTeX.
* The class name is slightly misleading:
* It only converts the StarMath annotation, if available
* and it also converts TexMaths formulas
*/
public final class MathmlConverter extends ConverterHelper {
private enum TexMathsStyle {inline, display, latex};
private StarMathConverter smc;
private boolean bContainsFormulas = false;
private boolean bAddParAfterDisplay = false;
public MathmlConverter(OfficeReader ofr,LaTeXConfig config, ConverterPalette palette) {
super(ofr,config,palette);
smc = new StarMathConverter(palette.getI18n(),config);
bAddParAfterDisplay = config.formatting()>=LaTeXConfig.CONVERT_MOST;
}
public void appendDeclarations(LaTeXDocumentPortion pack, LaTeXDocumentPortion decl) {
if (bContainsFormulas) {
if (config.useOoomath()) {
pack.append("\\usepackage{ooomath}").nl();
}
else {
smc.appendDeclarations(pack,decl);
}
}
}
public String convert(Node settings, Node formula) {
// TODO: Use settings to determine display mode/text mode
// formula must be a math:math node
// First try to find a StarMath annotation
Node semantics = Misc.getChildByTagName(formula,XMLString.SEMANTICS); // Since OOo 3.2
if (semantics==null) {
semantics = Misc.getChildByTagName(formula,XMLString.MATH_SEMANTICS);
}
if (semantics!=null) {
Node annotation = Misc.getChildByTagName(semantics,XMLString.ANNOTATION); // Since OOo 3.2
if (annotation==null) {
annotation = Misc.getChildByTagName(semantics,XMLString.MATH_ANNOTATION);
}
if (annotation!=null) {
String sStarMath = "";
if (annotation.hasChildNodes()) {
NodeList anl = annotation.getChildNodes();
int nLen = anl.getLength();
for (int i=0; i<nLen; i++) {
if (anl.item(i).getNodeType() == Node.TEXT_NODE) {
sStarMath+=anl.item(i).getNodeValue();
}
}
bContainsFormulas = true;
return smc.convert(sStarMath);
}
}
}
// No annotation was found. In this case we should convert the mathml,
// but currently we ignore the problem.
// TODO: Investigate if Vasil I. Yaroshevich's MathML->LaTeX
// XSL transformation could be used here. (Potential problem:
// OOo uses MathML 1.01, not MathML 2)
if (formula.hasChildNodes()) {
return "\\text{Warning: No StarMath annotation}";
}
else { // empty formula
return " ";
}
}
/** Handle an (inline) TexMaths equation
*
* @param node the equation (an svg:desc element containing the formula)
* @param ldp the LaTeXDocumentPortion to contain the converted equation
* @param oc the current context
*/
public void handleTexMathsEquation(Element node, LaTeXDocumentPortion ldp, Context oc) {
// LaTeX code is contained in svg:desc
// Format is <point size>X<mode>X<TeX code>X<format>X<resolution>X<transparency>
// where X is a paragraph sign
switch (getTexMathsStyle(node)) {
case inline:
ldp.append("$").append(getTexMathsEquation(node)).append("$");
break;
case display:
ldp.append("$\\displaystyle ").append(getTexMathsEquation(node)).append("$");
break;
case latex:
ldp.append(getTexMathsEquation(node));
}
}
private TexMathsStyle getTexMathsStyle(Element node) {
String[] sContent = Misc.getPCDATA(node).split("\u00a7");
if (sContent.length>=3) { // we only need 3 items of 6
if ("display".equals(sContent[1])) {
return TexMathsStyle.display;
}
else if ("latex".equals(sContent[1])) {
return TexMathsStyle.latex;
}
}
return TexMathsStyle.inline;
}
private String getTexMathsEquation(Element node) {
String[] sContent = Misc.getPCDATA(node).split("\u00a7");
if (sContent.length>=3) { // we only need 3 items of 6
return sContent[2];
}
else {
return "";
}
}
/** Try to convert a table as a display equation:
* A 1 row by 2 columns table in which each cell contains exactly one paragraph,
* the left cell contains exactly one formula and the right cell contains exactly
* one sequence number is treated as a (numbered) display equation.
* This happens to coincide with the AutoText provided with OOo Writer :-)
* @param table the table reader
* @param ldp the LaTeXDocumentPortion to contain the converted equation
* @return true if the conversion was successful, false if the table
* did not represent a display equation
*/
public boolean handleDisplayEquation(TableReader table, LaTeXDocumentPortion ldp) {
if (table.getRowCount()==1 && table.getColCount()==2 &&
OfficeReader.isSingleParagraph(table.getCell(0, 0)) && OfficeReader.isSingleParagraph(table.getCell(0, 1)) ) {
// Table of the desired form
if (palette.parseDisplayEquation(Misc.getFirstChildElement(table.getCell(0, 0))) && palette.getEquation()!=null && palette.getSequence()==null) {
// Found equation in first cell
Element myEquation = palette.getEquation();
if (palette.parseDisplayEquation(Misc.getFirstChildElement(table.getCell(0, 1))) && palette.getEquation()==null && palette.getSequence()!=null) {
// Found sequence in second cell
handleDisplayEquation(myEquation, palette.getSequence(), ldp);
return true;
}
}
}
return false;
}
/**Try to convert a paragraph as a display equation:
* A paragraph which contains exactly one formula + at most one sequence
* number is treated as a display equation. Other content must be brackets
* or whitespace (possibly with formatting).
* @param node the paragraph
* @param ldp the LaTeXDocumentPortion to contain the converted equation
* @return true if the conversion was successful, false if the paragraph
* did not contain a display equation
*/
public boolean handleDisplayEquation(Element node, LaTeXDocumentPortion ldp) {
if (palette.parseDisplayEquation(node) && palette.getEquation()!=null) {
handleDisplayEquation(palette.getEquation(), palette.getSequence(), ldp);
return true;
}
else {
return false;
}
}
private void handleDisplayEquation(Element equation, Element sequence, LaTeXDocumentPortion ldp) {
boolean bTexMaths = equation.getTagName().equals(XMLString.SVG_DESC);
TexMathsStyle style = TexMathsStyle.inline;
String sLaTeX;
if (bTexMaths) {
// TeXMaths equation
sLaTeX = getTexMathsEquation(equation);
style = getTexMathsStyle(equation);
}
else {
// MathML equation
sLaTeX = convert(null,equation);
}
if (!" ".equals(sLaTeX)) { // ignore empty formulas
if (!bTexMaths || style!=TexMathsStyle.latex) {
if (sequence!=null) {
// Numbered equation
ldp.append("\\begin{equation}");
palette.getFieldCv().handleSequenceLabel(sequence,ldp);
if (bTexMaths && style==TexMathsStyle.inline) {
ldp.append("\\textstyle ");
}
ldp.nl()
.append(sLaTeX).nl()
.append("\\end{equation}").nl();
}
else {
// Unnumbered equation
ldp.append("\\begin{equation*}");
if (bTexMaths && style==TexMathsStyle.inline) {
ldp.append("\\textstyle ");
}
ldp.nl()
.append(sLaTeX).nl()
.append("\\end{equation*}").nl();
}
}
else {
ldp.append(sLaTeX).nl();
}
if (bAddParAfterDisplay) { ldp.nl(); }
}
}
}

View file

@ -98,7 +98,7 @@ public class ParConverter extends StyleConverter {
* \end{enumerate}).
*/
public void handleParagraph(Element node, LaTeXDocumentPortion ldp, Context oc, boolean bLastInBlock) {
if (palette.getMathmlCv().handleDisplayEquation(node,ldp)) { return; }
if (palette.getMathCv().handleDisplayEquation(node,ldp)) { return; }
// Get the style name for this paragraph
String sStyleName = node.getAttribute(XMLString.TEXT_STYLE_NAME);

View file

@ -166,7 +166,7 @@ public class TableConverter extends ConverterHelper {
// Read the table
table = ofr.getTableReader(node);
if (palette.getMathmlCv().handleDisplayEquation(table,ldp)) { return; }
if (palette.getMathCv().handleDisplayEquation(table,ldp)) { return; }
// Get formatter and update flags according to formatter
formatter = new TableFormatter(ofr,config,palette,table,!oc.isInMulticols(),oc.isInTable());