package org.docx4j.model.images;
import org.docx4j.XmlUtils;
import org.docx4j.openpackaging.exceptions.Docx4JException;
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
import org.docx4j.openpackaging.parts.Part;
import org.docx4j.openpackaging.parts.WordprocessingML.BinaryPart;
import org.docx4j.openpackaging.parts.WordprocessingML.MetafileEmfPart;
import org.docx4j.openpackaging.parts.WordprocessingML.MetafileWmfPart;
import org.docx4j.openpackaging.parts.WordprocessingML.MetafileWmfPart.SvgDocument;
import org.docx4j.relationships.Relationship;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.DocumentFragment;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.Text;
/**
* Generate HTML/XSLFO
*/
public abstract class AbstractWordXmlPicture {
protected static Logger log = LoggerFactory.getLogger(AbstractWordXmlPicture.class);
WordprocessingMLPackage wmlPackage;
protected Dimensions dimensions;
// TODO: partially implemented
private BinaryPart metaFile;
protected final static String IMAGE_URL = "http://docxwave.appspot.com/image?";
public static DocumentFragment getHtmlDocumentFragment(AbstractWordXmlPicture picture) {
DocumentFragment docfrag=null;
Document d=null;
try {
if (picture==null) {
log.warn("picture was null!");
d = XmlUtils.getNewDocumentBuilder().newDocument();
Element span = d.createElement("span");
span.setAttribute("style", "color:red;");
d.appendChild(span);
Text err = d.createTextNode( "[null img]" );
span.appendChild(err);
} else if (picture.metaFile==null) {
// Usual case
d = picture.createHtmlImageElement();
} else if (picture.metaFile instanceof MetafileWmfPart) {
SvgDocument svgdoc = ((MetafileWmfPart)picture.metaFile).toSVG();
d = svgdoc.getDomDocument();
}
else if (picture.metaFile instanceof MetafileEmfPart) {
d = XmlUtils.getNewDocumentBuilder().newDocument();
//log.info("Document: " + document.getClass().getName() );
Node span = d.createElement("span");
d.appendChild(span);
Text err = d.createTextNode( "[TODO emf image]" );
span.appendChild(err);
}
} catch (Exception e) {
log.error(e.getMessage(), e);
d = XmlUtils.getNewDocumentBuilder().newDocument();
Element span = d.createElement("span");
span.setAttribute("style", "color:red;");
d.appendChild(span);
Text err = d.createTextNode( e.getMessage() );
span.appendChild(err);
}
docfrag = d.createDocumentFragment();
docfrag.appendChild(d.getDocumentElement());
return docfrag;
}
public Document createHtmlImageElement()
{
try {
// Create a DOM builder and parse the fragment
Document document = XmlUtils.getNewDocumentBuilder().newDocument();
Element imageElement = document.createElement("img");
if (src !=null && !src.equals(""))
{
imageElement.setAttribute("src", src);
}
if (id !=null && !id.equals("") )
{
imageElement.setAttribute("id", id);
}
if (alt !=null && !alt.equals("") )
{
imageElement.setAttribute("alt", alt);
}
if (style !=null && !style.equals("") )
{
imageElement.setAttribute("style", style);
}
if (dimensions.width>0)
{
imageElement.setAttribute("width", Integer.toString(dimensions.width));
}
if (dimensions.height>0)
{
imageElement.setAttribute("height", Integer.toString(dimensions.height));
}
if (hlinkRef !=null && !hlinkRef.equals(""))
{
Element linkElement = document.createElement("a");
linkElement.setAttribute( "href", hlinkRef);
if (targetFrame !=null && !targetFrame.equals(""))
{
linkElement.setAttribute( "target", targetFrame);
}
if (tooltip !=null && !tooltip.equals(""))
{
linkElement.setAttribute( "title", tooltip);
}
linkElement.appendChild(imageElement);
imageElement = linkElement;
}
document.appendChild(imageElement);
return document;
} catch (Exception e) {
e.printStackTrace();
log.error(e.getMessage(), e);
return null;
}
}
protected Document createXslFoImageElement()
{
try {
// Create a DOM builder and parse the fragment
Document document = XmlUtils.getNewDocumentBuilder().newDocument();
Element imageElement = document.createElementNS("http://www.w3.org/1999/XSL/Format",
"fo:external-graphic");
if (src !=null && !src.equals(""))
{
imageElement.setAttribute("src", src);
} else {
log.error("@src missing!");
}
// if (id !=null && !id.equals("") )
// {
// setAttribute("id", id);
// }
//
// if (alt !=null && !alt.equals("") )
// {
// setAttribute("alt", alt);
// }
//
// if (style !=null && !style.equals("") )
// {
// setAttribute("style", style);
// }
//
if (dimensions.width>0)
{
imageElement.setAttribute("content-width", Integer.toString(dimensions.width)+dimensions.widthUnit);
}
if (dimensions.height>0)
{
imageElement.setAttribute("content-height", Integer.toString(dimensions.height)+dimensions.heightUnit);
}
//
// if (hlinkRef !=null && !hlinkRef.equals(""))
// {
// linkElement = document.createElement("a");
//
// setAttribute(linkElement, "href", hlinkRef);
//
// if (targetFrame !=null && !targetFrame.equals(""))
// {
// setAttribute(linkElement, "target", targetFrame);
// }
//
// if (tooltip !=null && !tooltip.equals(""))
// {
// setAttribute(linkElement, "title", tooltip);
// }
//
// linkElement.appendChild(imageElement);
//
// imageElement = linkElement;
// }
document.appendChild(imageElement);
return document;
} catch (Exception e) {
log.error(e.getMessage(), e);
return null;
}
}
protected void handleImageRel(ConversionImageHandler imageHandler, String imgRelId, Part sourcePart) {
Relationship rel = sourcePart.getRelationshipsPart().getRelationshipByID(imgRelId);
Part part = null;
String uri = null;
boolean ignoreImage = false;
setID(imgRelId);
part = sourcePart.getRelationshipsPart().getPart(rel);
/* a part == null is ok if it is an external image,
* and hasn't been loaded (loadExternalTargets == false)
* but the relationship can be external,
* but the part avaiable (loadExternalTargets == true)
*/
if ((part != null) && (!(part instanceof BinaryPart))) {
log.error("Invalid part type id: " + imgRelId + ", class = " + part.getClass().getName());
ignoreImage = true;
}
if (!ignoreImage) {
uri = handlePart(imageHandler, this, rel, (BinaryPart)part);
if (uri != null) {
this.setSrc(uri);
}
}
}
/**
* @param imageHandler
* @param picture
* @param relationship
* @param part
* @return uri for the image we've saved, or null
*/
protected String handlePart(ConversionImageHandler imageHandler, AbstractWordXmlPicture picture, Relationship relationship, BinaryPart binaryPart) {
String uri = null;
try {
uri = imageHandler.handleImage(picture, relationship, binaryPart);
}
catch (Docx4JException de) {
if (relationship != null) {
log.error("Exception handling image id: " + relationship.getId() + ", target '" + relationship.getTarget() + "': " + de.toString(), de);
}
else {
log.error("Exception handling image: " + de.toString(), de);
}
}
return uri;
}
// void setAttribute(Node imageElement, String name, String value) {
//
// setAttribute( document, imageElement, name, value );
//
// }
// void setAttribute(Document document, Element element, String name, String value) {
//
//
// org.w3c.dom.Attr tmpAtt = document.createAttribute(name);
// tmpAtt.setValue(value);
// element.getAttributes().setNamedItem(tmpAtt);
//
// log.debug("<" + element.getLocalName() + " @"+ name + "=\"" + value);
//
// }
/**
* Values as parsed from E10 CSS.
*
*/
public class Dimensions {
public int height;
public String heightUnit;
public int width;
public String widthUnit;
// /**
// * If the docx does not explicitly size the
// * image, check that it will fit on the page
// */
// private void ensureFitsPage(ImageInfo imageInfo, PageDimensions page) {
//
//
// CxCy cxcy = BinaryPartAbstractImage.CxCy.scale(imageInfo, page);
//
// if (cxcy.isScaled() ) {
// log.info("Scaled to fit page width");
// this.setWidth( Math.round(cxcy.getCx()/extentToPixelConversionFactor) );
// this.setHeight( Math.round(cxcy.getCy()/extentToPixelConversionFactor) );
// // That gives pixels, which is ok for HTML, but for XSL FO, we want pt or mm etc
// }
//
// }
}
// Hyperlink stuff - Only in E20?
protected String hlinkRef;
public String getHlinkReference() {
return this.hlinkRef;
}
public void setHlinkReference(String value) {
this.hlinkRef = value;
}
protected String targetFrame;
public String getTargetFrame() {
return this.targetFrame;
}
public void setTargetFrame(String value) {
this.targetFrame = value;
}
protected String tooltip;
public String getTooltip() {
return this.tooltip;
}
public void setTooltip(String value) {
this.tooltip = value;
}
// Alt - only in E10?
protected String alt;
// / The attribute of the v:shape node which maps to the
// / 'alt' attribute of and HTML 'img' tag.
public String getAlt() {
return this.alt;
}
public void setAlt(String value) {
this.alt = value;
}
// private byte[] data;
// // / <summary>
// // / The decoded data from the corresponding 'w:bindata'
// /// node of the Word Document.
// /// </summary>
// /// <remarks>
// /// This property is set by the conversion process.
// /// </remarks>
// /// <value>
// /// </value>
// /// <id guid="130108bf-d980-4753-b674-4d489acf485c" />
// /// <owner alias="ROrleth" />
// public byte[] getData() {
// return this.data;
// }
//
// public void setData(byte[] value) {
// this.data = value;
// }
protected String id;
// / The identifier of the picture unique only within the scope of
// / the Word Document.
public String getID() {
return this.id;
}
public void setID(String value) {
this.id = value;
}
private String src;
public String getSrc() {
return this.src;
}
public void setSrc(String value) {
this.src = value;
}
protected String style;
// / The attribute of the v:shape node which maps to the
/// 'style' attribute of and HTML 'img' tag.
public String getStyle() {
return this.style;
}
public void setStyle(String value) {
this.style = value;
}
protected String pType;
/**
* The type of the picture as specified by the attribute of the v:shape node
* within the Word Document. This value is used as an identifier for a v:type
* node, which used to specify
* properties of the picture within the Word Document.
* @return
*/
public String getPType() {
return this.pType;
}
public void setPType(String value) {
this.pType = value;
}
}