有人知道Office Open XML x
中y
和wrapPolygon
的含义和单位是什么吗?
documentation指出:
“在x轴上指定一个坐标。此坐标的原点应由父XML元素指定。...此属性的可能值由ST_Coordinate简单类型(第5.1.12.16节)定义。”
听起来好像应该在图片的左上角描述一个从x
= 0和y
= 0开始的多边形。单位是EMU
。
但这不能成立,因为如果在代码Change image layout or wrap in DOCX with Apache POI中使用,则执行以下操作:
...
+"<wp:wrapTight wrapText=\"bothSides\">"
+"<wp:wrapPolygon edited=\"0\">"
+"<wp:start x=\"0\" y=\"0\"/>"
+"<wp:lineTo x=\"0\" y=\""+height+"\"/>"
+"<wp:lineTo x=\""+width+"\" y=\""+height+"\"/>"
+"<wp:lineTo x=\""+width+"\" y=\"0\"/>"
+"<wp:lineTo x=\"0\" y=\"0\"/>"
+"</wp:wrapPolygon>"
+"</wp:wrapTight>"
...
则最终的包裹点就远在图片之外。
而是描述一个正方形多边形21600 x 21600
...
+"<wp:wrapPolygon edited=\"0\">"
+"<wp:start x=\"0\" y=\"0\"/>"
+"<wp:lineTo x=\"0\" y=\"21600\"/>"
+"<wp:lineTo x=\"21600\" y=\"21600\"/>"
+"<wp:lineTo x=\"21600\" y=\"0\"/>"
+"<wp:lineTo x=\"0\" y=\"0\"/>"
+"</wp:wrapPolygon>"
...
导致换行点位于图片的全宽x高。
这与图片大小本身无关。它可能是所有可能尺寸的正方形或矩形尺寸的图片。
因此,尽管“此坐标的原点应由父XML元素指定”。并且多边形从图片左上角的
x
= 0和y
= 0开始,因此宽度和高度的单位不能为EMU
。而且,如果图片是矩形,则正方形多边形21600 x 21600会导致矩形换行点,因此多边形本身的含义也不清楚。这是在某处记录的吗?
最佳答案
好吧,似乎没人回答。因此,我至少将提供一个示例说明该规则的原因:“一个正方形多边形21600 x 21600导致折点的全宽x高与图片大小无关。”可能会有用。
如果需要设置更复杂的环绕点,则需要一个椭圆,例如,仅将该椭圆描绘为21600 x 21600的正方形即可,而与图片大小无关。这比根据实际图片大小计算环绕点要简单得多。因此,我们可以强制Word
将图片真正地紧紧包裹在图片周围。
示例代码:
import java.io.FileOutputStream;
import java.io.FileInputStream;
import java.io.InputStream;
import org.apache.poi.xwpf.usermodel.*;
import org.apache.poi.util.Units;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTDrawing;
import org.openxmlformats.schemas.drawingml.x2006.main.CTGraphicalObject;
import org.openxmlformats.schemas.drawingml.x2006.wordprocessingDrawing.CTAnchor;
public class WordPicturesWrapTight {
private static CTAnchor getAnchorWithGraphic(CTGraphicalObject graphicalobject,
String drawingDescr, int width, int height,
int left, int top) throws Exception {
String anchorXML =
"<wp:anchor xmlns:wp=\"http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing\" "
+"simplePos=\"0\" relativeHeight=\"0\" behindDoc=\"1\" locked=\"0\" layoutInCell=\"1\" allowOverlap=\"1\">"
+"<wp:simplePos x=\"0\" y=\"0\"/>"
+"<wp:positionH relativeFrom=\"column\"><wp:posOffset>"+left+"</wp:posOffset></wp:positionH>"
+"<wp:positionV relativeFrom=\"paragraph\"><wp:posOffset>"+top+"</wp:posOffset></wp:positionV>"
+"<wp:extent cx=\""+width+"\" cy=\""+height+"\"/>"
+"<wp:effectExtent l=\"0\" t=\"0\" r=\"0\" b=\"0\"/>"
+"<wp:wrapTight wrapText=\"bothSides\">"
+"<wp:wrapPolygon edited=\"1\">"; //Set edited 1, so Word will not destroying the wrap points.
//A square polygon 21600 x 21600 leads to wrap points in fully width x height independent of picture size.
//So if the need is setting more complex wrap points, a ellipse for example, only depicting this ellipse
//to a square 21600 x 21600 is needed independent of picture size.
long[] x = new long[5];
long[] y = new long[5];
for (int i = 0; i < 5; i++) {
x[i] = i * 2700L; //2700 = 21600/2/4
y[i] = Math.round(Math.sqrt(116640000d - Math.pow(i * 2700d, 2d))); //116640000 = (21600/2)^2
}
anchorXML += "<wp:start x=\""+(x[0]+10800)+"\" y=\""+(10800-y[0])+"\"/>";
for (int i = 1; i < 5; i++) {
anchorXML += "<wp:lineTo x=\""+(x[i]+10800)+"\" y=\""+(10800-y[i])+"\"/>";
}
for (int i = 3; i > -1; i--) {
anchorXML += "<wp:lineTo x=\""+(x[i]+10800)+"\" y=\""+(10800+y[i])+"\"/>";
}
for (int i = 1; i < 5; i++) {
anchorXML += "<wp:lineTo x=\""+(10800-x[i])+"\" y=\""+(10800+y[i])+"\"/>";
}
for (int i = 3; i > -1; i--) {
anchorXML += "<wp:lineTo x=\""+(10800-x[i])+"\" y=\""+(10800-y[i])+"\"/>";
}
anchorXML += "</wp:wrapPolygon>"
+"</wp:wrapTight>"
+"<wp:docPr id=\"1\" name=\"Drawing 0\" descr=\""+drawingDescr+"\"/><wp:cNvGraphicFramePr/>"
+"</wp:anchor>";
CTDrawing drawing = CTDrawing.Factory.parse(anchorXML);
CTAnchor anchor = drawing.getAnchorArray(0);
anchor.setGraphic(graphicalobject);
return anchor;
}
public static void main(String[] args) throws Exception {
XWPFDocument document = new XWPFDocument();
XWPFParagraph paragraph = document.createParagraph();
XWPFRun run = paragraph.createRun();
InputStream in = new FileInputStream("ellipticSample.png");
run.addPicture(in, Document.PICTURE_TYPE_PNG, "ellipticSample.png", Units.toEMU(100), Units.toEMU(60));
in.close();
CTDrawing drawing = run.getCTR().getDrawingArray(0);
CTGraphicalObject graphicalobject = drawing.getInlineArray(0).getGraphic();
CTAnchor anchor = getAnchorWithGraphic(graphicalobject, "ellipticSample.png",
Units.toEMU(100), Units.toEMU(60),
Units.toEMU(100), Units.toEMU(16));
drawing.setAnchorArray(new CTAnchor[]{anchor});
drawing.removeInline(0);
run = paragraph.createRun();
run.setText("The picture is anchored wrap tight. This means text will wrap this according to a polygon described by wrap points. Seems a square polygon 21600 x 21600 leads to wrap points in fully width x height independent of picture size. So if the need is setting more complex wrap points, a ellipse for example, only depicting this ellipse to a square 21600 x 21600 is needed independent of the picture size. This is much more simple if more complex wrap points shall be set. But it's a shame, that this feature not seems documented. So can we rely on it or not?");
document.write(new FileOutputStream("WordPicturesWrapTight.docx"));
document.close();
}
}
结果:
关于ms-word - Office Open XML`wrapPolygon`中`x`和`y`的含义和单位,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/47717419/