Shape bounds included in an other shape bounds

Hello,
I’m trying to test if a floating textbox is positionned inside a floating image.

with the following code:

String documentSrcPath = "input\\doc.docx";
Document doc = new Document(documentSrcPath);
        
NodeCollection<Shape> shapes = (NodeCollection<Shape>) doc.getChildNodes(NodeType.SHAPE, true);
        
int nbImgs = 0;
for (Shape shape : shapes) 
{
    if (shape.hasImage()) 
    {
        ++nbImgs;
    }
}
  
Shape [] image = new Shape[nbImgs];
String [] label = new String[nbImgs];
  
int i = 0;
for (Shape shape : shapes) 
{
    if (shape.hasImage()) 
    {
        image[i] = shape;
        ++i;
    }
}

for (Shape shape : shapes)
{
    if (shape.getShapeType() == ShapeType.TEXT_BOX) 
    {
        System.out.println();
        Rectangle2D.Float rectLabel = shape.getBounds();
        System.out.println("rectLabel bound: " + rectLabel);
        for (int k=0; k<image.length; ++k)
        {
            Rectangle2D.Float rectImg = image[k].getBounds();
            System.out.println("rectImg bound: " + rectImg);
            if(rectImg.contains(rectLabel))
            {
                label[k] = shape.getText().trim();
                System.out.println(label[k] + " is included in a shape");
                break;
            }
        }
        
    }
}

But the output shows that the boundaries are sometimes effectively in a image.
However in reality Textboxes with “Test” string inside should not be inside any image.
Could someone explain what is happening here. In my mind boundaries are the position in the document (x,y) with width and height.

output:
rectLabel bound: java.awt.geom.Rectangle2D$Float[x=220.5,y=1.7,w=73.15,h=23.0]
rectImg bound: java.awt.geom.Rectangle2D$Float[x=12.672048,y=0.633937,w=186.0,h=186.0]
rectImg bound: java.awt.geom.Rectangle2D$Float[x=252.35,y=0.5,w=237.85,h=178.35]
rectImg bound: java.awt.geom.Rectangle2D$Float[x=14.32,y=16.87803,w=225.2,h=126.15]

rectLabel bound: java.awt.geom.Rectangle2D$Float[x=14.9579525,y=3.3619685,w=73.15205,h=23.04]
rectImg bound: java.awt.geom.Rectangle2D$Float[x=12.672048,y=0.633937,w=186.0,h=186.0]
Green is included in a shape

rectLabel bound: java.awt.geom.Rectangle2D$Float[x=222.85803,y=0.3219685,w=73.15,h=23.0]
rectImg bound: java.awt.geom.Rectangle2D$Float[x=12.672048,y=0.633937,w=186.0,h=186.0]
rectImg bound: java.awt.geom.Rectangle2D$Float[x=252.35,y=0.5,w=237.85,h=178.35]
rectImg bound: java.awt.geom.Rectangle2D$Float[x=14.32,y=16.87803,w=225.2,h=126.15]

rectLabel bound: java.awt.geom.Rectangle2D$Float[x=358.28967,y=18.156614,w=73.15,h=23.0]
rectImg bound: java.awt.geom.Rectangle2D$Float[x=12.672048,y=0.633937,w=186.0,h=186.0]
rectImg bound: java.awt.geom.Rectangle2D$Float[x=252.35,y=0.5,w=237.85,h=178.35]
Test is included in a shape

rectLabel bound: java.awt.geom.Rectangle2D$Float[x=255.3604,y=3.4632285,w=73.15205,h=23.04]
rectImg bound: java.awt.geom.Rectangle2D$Float[x=12.672048,y=0.633937,w=186.0,h=186.0]
rectImg bound: java.awt.geom.Rectangle2D$Float[x=252.35,y=0.5,w=237.85,h=178.35]
Blue is included in a shape

rectLabel bound: java.awt.geom.Rectangle2D$Float[x=16.1,y=19.8,w=73.15,h=23.0]
rectImg bound: java.awt.geom.Rectangle2D$Float[x=12.672048,y=0.633937,w=186.0,h=186.0]
Red is included in a shape

rectLabel bound: java.awt.geom.Rectangle2D$Float[x=199.94528,y=5.9886613,w=73.15,h=23.0]
rectImg bound: java.awt.geom.Rectangle2D$Float[x=12.672048,y=0.633937,w=186.0,h=186.0]
rectImg bound: java.awt.geom.Rectangle2D$Float[x=252.35,y=0.5,w=237.85,h=178.35]
rectImg bound: java.awt.geom.Rectangle2D$Float[x=14.32,y=16.87803,w=225.2,h=126.15]

rectLabel bound: java.awt.geom.Rectangle2D$Float[x=256.99622,y=5.95189,w=73.15,h=23.0]
rectImg bound: java.awt.geom.Rectangle2D$Float[x=12.672048,y=0.633937,w=186.0,h=186.0]
rectImg bound: java.awt.geom.Rectangle2D$Float[x=252.35,y=0.5,w=237.85,h=178.35]
Test is included in a shape

rectLabel bound: java.awt.geom.Rectangle2D$Float[x=-3.10874,y=14.817402,w=73.15,h=23.0]
rectImg bound: java.awt.geom.Rectangle2D$Float[x=12.672048,y=0.633937,w=186.0,h=186.0]
rectImg bound: java.awt.geom.Rectangle2D$Float[x=252.35,y=0.5,w=237.85,h=178.35]
rectImg bound: java.awt.geom.Rectangle2D$Float[x=14.32,y=16.87803,w=225.2,h=126.15]

rectLabel bound: java.awt.geom.Rectangle2D$Float[x=19.989134,y=0.6,w=73.15,h=23.0]
rectImg bound: java.awt.geom.Rectangle2D$Float[x=12.672048,y=0.633937,w=186.0,h=186.0]
rectImg bound: java.awt.geom.Rectangle2D$Float[x=252.35,y=0.5,w=237.85,h=178.35]
rectImg bound: java.awt.geom.Rectangle2D$Float[x=14.32,y=16.87803,w=225.2,h=126.15]

rectLabel bound: java.awt.geom.Rectangle2D$Float[x=67.6174,y=12.482598,w=73.15,h=23.0]
rectImg bound: java.awt.geom.Rectangle2D$Float[x=12.672048,y=0.633937,w=186.0,h=186.0]
Test is included in a shape

doc.docx (97,1 Ko)

@Nkorbl Shape.Bounds property does not return an absolute bounds of the shape. For a top-level shape, the value is in points and relative to the shape anchor. For shapes in a group, the value is in the coordinate space and units of the parent group.

If it is required to calculate absolute bounding boxes of top level shapes in the document, you can use LayoutCollector and LayoutEnumerator. For example see the following code:

Document doc = new Document("C:\\Temp\\in.docx");
LayoutCollector collector = new LayoutCollector(doc);
LayoutEnumerator enumerator = new LayoutEnumerator(doc);

// Get shapes.
Iterable<Shape> shapes = doc.getChildNodes(NodeType.SHAPE, true);
for (Shape s : shapes)
{
    // LayoutCollector and LayoutEnumerator works only with top level shapes in the main document content.
    if (!s.isTopLevel())
        continue;
    if (s.getAncestor(NodeType.HEADER_FOOTER) != null)
        continue;

    // Get bounding box of the shape.
    enumerator.setCurrent(collector.getEntity(s));
    System.out.println(enumerator.getRectangle());
}

It works, thanks for the explanation.

1 Like