/************************************************************************ * * DrawConverter.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-2009 by Henrik Just * * All Rights Reserved. * * Version 1.0 (2009-03-08) * */ package writer2latex.latex; import java.util.LinkedList; import java.util.Stack; import org.w3c.dom.Document; import org.w3c.dom.Element; //import org.w3c.dom.Node; import writer2latex.xmerge.EmbeddedObject; import writer2latex.xmerge.EmbeddedXMLObject; import writer2latex.latex.util.BeforeAfter; import writer2latex.latex.util.Context; //import writer2latex.office.ImageLoader; import writer2latex.office.MIMETypes; import writer2latex.office.OfficeReader; import writer2latex.office.StyleWithProperties; import writer2latex.office.XMLString; import writer2latex.util.CSVList; import writer2latex.util.Misc; import writer2latex.xmerge.BinaryGraphicsDocument; /** *
This class handles draw elements.
*/ public class DrawConverter extends ConverterHelper { private boolean bNeedGraphicx = false; private boolean bNeedOOoLaTeXPreamble = false; // Keep track of floating frames (images, textboxes...) private Stack floatingFramesStack = new Stack(); private Element getFrame(Element onode) { if (ofr.isOpenDocument()) return (Element) onode.getParentNode(); else return onode; } public DrawConverter(OfficeReader ofr, LaTeXConfig config, ConverterPalette palette) { super(ofr,config,palette); floatingFramesStack.push(new LinkedList()); } public void appendDeclarations(LaTeXDocumentPortion pack, LaTeXDocumentPortion decl) { if (bNeedGraphicx) { pack.append("\\usepackage"); if (config.getBackend()==LaTeXConfig.PDFTEX) pack.append("[pdftex]"); //else if (config.getBackend()==LaTeXConfig.XETEX) pack.append("[xetex]"); 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) { // Floating frames should be positioned *above* the label, hence // we use a separate ldp for the paragraphs and add this later LaTeXDocumentPortion capLdp = new LaTeXDocumentPortion(true); // Convert the caption if (oc.isInFigureFloat()) { // float capLdp.append("\\caption"); palette.getCaptionCv().handleCaptionBody(node,capLdp,oc,false); } else { // nonfloat capLdp.append("\\captionof{figure}"); palette.getCaptionCv().handleCaptionBody(node,capLdp,oc,true); } flushFloatingFrames(ldp,oc); ldp.append(capLdp); } public void handleDrawElement(Element node, LaTeXDocumentPortion ldp, Context oc) { // node must be an elment in the draw namespace String sName = node.getTagName(); if (sName.equals(XMLString.DRAW_OBJECT)) { handleDrawObject(node,ldp,oc); } else if (sName.equals(XMLString.DRAW_OBJECT_OLE)) { handleDrawObject(node,ldp,oc); } else if ((!oc.isInHeaderFooter()) && sName.equals(XMLString.DRAW_IMAGE)) { handleDrawImage(node,ldp,oc); } else if ((!oc.isInHeaderFooter()) && sName.equals(XMLString.DRAW_TEXT_BOX)) { handleDrawTextBox(node,ldp,oc); } else if (sName.equals(XMLString.DRAW_A)) { // we handle this like text:a palette.getFieldCv().handleAnchor(node,ldp,oc); } else if (sName.equals(XMLString.DRAW_FRAME)) { // OpenDocument: Get the actual draw element in the frame handleDrawElement(Misc.getFirstChildElement(node),ldp,oc); } else { // Other drawing objects (eg. shapes) are currently not supported ldp.append("[Warning: Draw object ignored]"); } } //----------------------------------------------------------------- // 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 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 settings = ((EmbeddedXMLObject) object).getSettingsDOM(); Document formuladoc = ((EmbeddedXMLObject) object).getContentDOM(); Element formula = Misc.getChildByTagName(formuladoc,XMLString.MATH_MATH); ldp.append(" $") .append(palette.getMathmlCv().convert(settings,formula)) .append("$"); if (Character.isLetterOrDigit(OfficeReader.getNextChar(node))) { ldp.append(" "); } } catch (org.xml.sax.SAXException e) { e.printStackTrace(); } catch (java.io.IOException e) { e.printStackTrace(); } } else { // unsupported object boolean bIgnore = true; if (ofr.isOpenDocument()) { // look for replacement image Element replacementImage = Misc.getChildByTagName(getFrame(node),XMLString.DRAW_IMAGE); if (replacementImage!=null) { handleDrawImage(replacementImage,ldp,oc); bIgnore = false; } } if (bIgnore) { ldp.append("[Warning: object ignored]"); } } } } } else { // flat xml, object is contained in node Element formula = Misc.getChildByTagName(node,XMLString.MATH_MATH); if (formula!=null) { ldp.append(" $") .append(palette.getMathmlCv().convert(null,formula)) .append("$"); if (Character.isLetterOrDigit(OfficeReader.getNextChar(node))) { ldp.append(" "); } } else { // unsupported object boolean bIgnore = true; if (ofr.isOpenDocument()) { // look for replacement image Element replacementImage = Misc.getChildByTagName(getFrame(node),XMLString.DRAW_IMAGE); if (replacementImage!=null) { handleDrawImage(replacementImage,ldp,oc); bIgnore = false; } } if (bIgnore) { ldp.append("[Warning: object ignored]"); } } } } //-------------------------------------------------------------------------- // Create float environment private void applyFigureFloat(BeforeAfter ba, Context oc) { // todo: check context... if (config.floatFigures() && !oc.isInFrame() && !oc.isInTable()) { if (oc.isInMulticols()) { ba.add("\\begin{figure*}","\\end{figure*}\n"); } else { ba.add("\\begin{figure}","\\end{figure}\n"); } if (config.getFloatOptions().length()>0) { ba.add("["+config.getFloatOptions()+"]",""); } ba.add("\n",""); oc.setInFigureFloat(true); } if (!oc.isInFrame() && config.alignFrames()) { // Avoid nesting center environment ba.add("\\begin{center}\n","\n\\end{center}\n"); } } //-------------------------------------------------------------------------- // Handle draw:image elements private void handleDrawImage(Element node, LaTeXDocumentPortion ldp, Context oc) { // Include graphics if allowed by the configuration switch (config.imageContent()) { case LaTeXConfig.IGNORE: // Ignore graphics silently return; case LaTeXConfig.WARNING: System.err.println("Warning: Images are not allowed"); return; case LaTeXConfig.ERROR: ldp.append("% Error in document: An image was ignored"); return; } Element frame = getFrame(node); 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