Ms word Office开放XML包装中x和y的含义和单位`

Ms word Office开放XML包装中x和y的含义和单位`,ms-word,apache-poi,openxml,Ms Word,Apache Poi,Openxml,有人知道Office Open XML中的x和y的含义和单位是什么吗 各国: “指定x轴上的坐标。此坐标的原点应由父XML元素指定……此属性的可能值由ST_坐标简单类型(§5.1.12.16)定义。” 这听起来像是在描述一个多边形,从图片左上角的x=0和y=0开始。单位为EMU 但这不可能是真的,因为如果在代码中使用,那么,如果我执行以下操作: ... +"<wp:wrapTight wrapText=\"bothSides\">" +"<wp:wrapPolygon

有人知道Office Open XML中的
x
y
的含义和单位是什么吗

各国:

“指定x轴上的坐标。此坐标的原点应由父XML元素指定……此属性的可能值由ST_坐标简单类型(§5.1.12.16)定义。”

这听起来像是在描述一个多边形,从图片左上角的
x
=0和
y
=0开始。单位为
EMU

但这不可能是真的,因为如果在代码中使用,那么,如果我执行以下操作:

...
  +"<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();
 }
}
import java.io.FileOutputStream;
导入java.io.FileInputStream;
导入java.io.InputStream;
导入org.apache.poi.xwpf.usermodel.*;
导入org.apache.poi.util.Units;
导入org.openxmlformats.schemas.wordprocessingml.x2006.main.CTDrawing;
导入org.openxmlformats.schemas.drawingml.x2006.main.CTGraphicalObject;
导入org.openxmlformats.schemas.drawingml.x2006.wordprocessingDrawing.CTAnchor;
公共类单词PicturesWraptight{
专用静态CTAnchor getAnchorWithGraphic(CTGraphicalObject graphicalobject,
字符串绘制描述,整数宽度,整数高度,
int left,int top)引发异常{
字符串锚定XML=
""
+""
+“”+左+“”
+“”+top+“”
+""
+""
+""
+“”;//设置为1,以便Word不会破坏包裹点。
//正方形多边形21600 x 21600导致完全宽度x高度的包裹点,与图片大小无关。
//因此,如果需要设置更复杂的包裹点,例如椭圆,仅描绘该椭圆
//与图片大小无关,需要21600 x 21600的正方形。
长[]x=新长[5];
长[]y=新长[5];
对于(int i=0;i<5;i++){
x[i]=i*2700L;//2700=21600/2/4
y[i]=Math.round(Math.sqrt(11664000d-Math.pow(i*2700d,2d));//116640000=(21600/2)^2
}
主播XML+=“”;
对于(int i=1;i<5;i++){
主播XML+=“”;
}
对于(int i=3;i>-1;i--){
主播XML+=“”;
}
对于(int i=1;i<5;i++){
主播XML+=“”;
}
对于(int i=3;i>-1;i--){
主播XML+=“”;
}
主播XML+=“”
+""
+""
+"";
CTDrawing=CTDrawing.Factory.parse(anchorXML);
CTAnchor anchor=图纸。GetAnchorary(0);
anchor.setGraphic(graphicalobject);
回锚;
}
公共静态void main(字符串[]args)引发异常{
XWPFDocument document=新的XWPFDocument();
XWPFParagraph paragraph paragraph=document.createParagraph();
XWPFRun=段落.createRun();
InputStream in=新文件InputStream(“ellipticSample.png”);
run.addPicture(在,Document.PICTURE_TYPE_PNG,“elliticsample.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,“elliticsample.png”,
单位。toEMU(100),单位。toEMU(60),
单位。托姆(100),单位。托姆(16);
图纸:Setanchorary(新CTAnchor[]{anchor});
图纸。移除细脉线(0);
run=段落.createRun();
run.setText("图片被锚定为紧密包裹。这意味着文本将根据包裹点描述的多边形进行包裹。似乎方形多边形21600 x 21600会导致完全宽度x高度的包裹点,与图片大小无关。因此,如果需要设置更复杂的包裹点,例如椭圆,只将该椭圆描绘为方形21600 x与图片大小无关,需要21600。如果需要设置更复杂的包裹点,则更为简单。但遗憾的是,此功能似乎没有记录在案。因此,我们是否可以依赖它?”;
write(新文件输出流(“wordpictureswrapight.docx”);
document.close();
}
}
结果: