Shapes being rendered in a different order

Hello! I found inconsistent orders of rendering word shapes to images.
I’d like to know why, in the example provided, the header shapes of a page are being rendered before the shapes in the previous page. Without setting the license, this order is different.

Environment

  1. Python 3.12.9
  2. Debian 12
  3. Aspose.Words 25.7.0

Sample code

import aspose.words as aw

doc = aw.Document("sample.docx")
i = 0
for node in doc.get_child_nodes(aw.NodeType.SHAPE, True):
    i+=1
    node.as_shape().get_shape_renderer().save(f"./output_folder_path/shape{i}.png", aw.saving.ImageSaveOptions(aw.SaveFormat.PNG))

By running the above script, and looking at the output folder, notice how it’s rendering first the shapes in the second page header, then first page header, and lastly the shapes in the pages body.
If you run the script without setting the license (free version), the shapes are being rendered in the reversed order. Is there a specific order you follow to iterate through a document’s shapes?

Additionally, we’d like to know what other ways of identifying a shape besides by its name you offer. I found an older ticket asking you to import the ids from the document and adding it to the shape, is there an estimation date for releasing this? Here is the ticket: How to get Shape property wp:docPr id=“...” using .NET
Thank you!

Attachments
sample.docx (32.9 KB)

@lbraguesdodoc

Hello,

The rendering order of shapes in Aspose.Words can vary based on the document structure and the licensing state. When using the licensed version, the library may optimize rendering by processing headers and footers before body content, which can lead to the observed behavior. In contrast, the free version may follow a different order, resulting in the reversed sequence.

To identify shapes beyond their names, you can consider properties like their position, size, or type. As for the request regarding shape IDs, I recommend keeping an eye on updates from the development team for any timelines on feature releases.

Thank you for your understanding.

Best regards,
Professionalize.Discourse Bot

@lbraguesdodoc Unfortunately, there is no other way to identify shapes except names. The issue you have mentioned is not resolved yet.
Regarding order of returned shapes, you can update your code to control this. You can loop through section, header/footer in each section and body of each section. For example see the following code:

hf_types = [ aw.HeaderFooterType.HEADER_FIRST, aw.HeaderFooterType.HEADER_PRIMARY, aw.HeaderFooterType.HEADER_EVEN, aw.HeaderFooterType.FOOTER_FIRST, aw.HeaderFooterType.FOOTER_PRIMARY, aw.HeaderFooterType.FOOTER_EVEN ]

doc = aw.Document("C:\\Temp\\sample.docx")
i = 0

for s in doc.sections:
    s = s.as_section()
    # Render shapes in headers/footers. Order of headers/footer is defined in the list above.
    for hf_type in hf_types:
        hf = s.headers_footers.get_by_header_footer_type(hf_type)
        if hf != None:
            hf = hf.as_header_footer()
            for node in hf.get_child_nodes(aw.NodeType.SHAPE, True):
                i+=1
                node.as_shape().get_shape_renderer().save(f"C:\\Temp\\shape{i}.png", aw.saving.ImageSaveOptions(aw.SaveFormat.PNG))

    # Render shapes in hte section's body.
    for node in s.body.get_child_nodes(aw.NodeType.SHAPE, True):
        i+=1
        node.as_shape().get_shape_renderer().save(f"C:\\Temp\\shape{i}.png", aw.saving.ImageSaveOptions(aw.SaveFormat.PNG))

Thanks for the response, this seems to fix some of our problems however having the document ids accessible through the node objects would be a game changer. If you could come back to us with some more updates on this would be very appreciated.
Another issue we seem to have encountered is that adding a next page section break in the middle of the document is breaking one of the header shapes. I send the updated document attached.

Code

doc = aw.Document("sample_section_break.docx")

hf_types = [ aw.HeaderFooterType.HEADER_FIRST, aw.HeaderFooterType.HEADER_PRIMARY, aw.HeaderFooterType.HEADER_EVEN, aw.HeaderFooterType.FOOTER_FIRST, aw.HeaderFooterType.FOOTER_PRIMARY, aw.HeaderFooterType.FOOTER_EVEN ]

for s in doc.sections:
    s = s.as_section()

    # Render shapes in the section's body.
    for node in s.body.get_child_nodes(aw.NodeType.SHAPE, True):
        node = node.as_shape()
        i+=1
        node.get_shape_renderer().save(f"./output_folder_path/shape{i}.png", aw.saving.ImageSaveOptions(aw.SaveFormat.PNG))
    # Render shapes in headers/footers. Order of headers/footer is defined in the list above.
    for hf_type in hf_types:
        hf = s.headers_footers.get_by_header_footer_type(hf_type)
        if hf is not None:
            hf = hf.as_header_footer()
            for node in hf.get_child_nodes(aw.NodeType.SHAPE, True):
                node = node.as_shape()
                i+=1
                node.get_shape_renderer().save(f"./output_folder_path/shape{i}.png", aw.saving.ImageSaveOptions(aw.SaveFormat.PNG))

Attachments
sample_section_break.docx (31.5 KB)

@lbraguesdodoc In your document the second section does not have headers/footers. It inherits headers/footers from the previous section:

So it is expected, the shape in headers/footers are rendered only for the first section in your document.