Bugs in new LayoutEnumerator

I’ve just been trying out the new LayoutEnumerator functionality, which looks like it could be really useful for solving a whole range of problems, but I seem to have found a few bugs.

  1. When getting the bounding rectangle for a paragraph, the X location and the Width seem to be swapped, so that a paragraph that is wider but the same indent has a larger X and the same Width.

  2. When getting the bounding rectangle for a text Run, the page rectangle seems to come back instead.

Here’s my test code :

static void Main(string[] args)
{
    var doc = new Document("test.docx");
    DumpLocations(doc, NodeType.Paragraph);
    DumpLocations(doc, NodeType.Run);
}

static void DumpLocations(Document doc, NodeType nodeType)
{
    var nodes = doc.GetChildNodes(nodeType, true);

    LayoutEnumerator le = new LayoutEnumerator(doc);

    foreach(Node node in nodes)
    {
        le.MoveNode(node);
        Console.WriteLine("The text ‘{0}’ is on page {1} at position {2}", node.GetText().Trim(), le.PageIndex, le.Rectangle.ToString());
    }
}

It shows nicely in the attached document - all the paragraphs have the same indent but show increasing X values as the length of the text increases.

Hope that these are just teething troubles with what looks like a great new feature.

thanks,

Robin

Hi Robin,

Thanks for reporting these problems to us.

While using the latest version of Aspose.Words i.e. 13.1.0, I managed to reproduce these issues on my side. I have logged these issues in our bug tracking system. The ticket IDs of these issues are WORDSNET-7756 and WORDSNET-7757. Your request has also been linked to these issues and you will be notified as soon as these are resolved.

Sorry for the inconvenience.

Best regards,

Hi Robin,

Thanks for your patience.

It is to update you that our development team has finished working on your issues and has come to a conclusion that your issues and the behaviours you’re observing are actually not bugs in Aspose.Words. So, we’ve closed these issues with status as ‘Not a Bug’.

Regarding WORDSNET-7756, the problem occurs because the layout enumerator does not return rectangles of paragraphs and this behaviour is entirely by design. We will be sure to improve the documentation related to the use of layout enumerator in future.

Regarding WORDSNET-7757, please note that the layout enumerator can not move to Run nodes either. Please check for the return value of LayoutEnumerator.MoveNode method before getting the bounding rectangle of a layout entity. In your case, it always returns False and thus Rectangle gets coordinates of a current layout object which is a first page in the document. Please rework the code like below:

static void DumpLocations(Document doc, NodeType nodeType)
{
    DocumentBuilder builder = new DocumentBuilder();
    var nodes = doc.GetChildNodes(nodeType, true);
    LayoutEnumerator le = new LayoutEnumerator(doc);
    foreach (Node node in nodes)
    {
        if (!le.MoveNode(node))
        {
            builder.Writeln("Cannot move to '" + node.GetText().Trim() + "'");
        }
        else
        {
            builder.Writeln("The text '" + node.GetText().Trim() + "' is on page " + le.PageIndex + " at position " + le.Rectangle.ToString() + "");
            builder.Document.Save(fileName + " Out.docx");
        }
    }
}

If we can help you with anything else, please feel free to ask.

Best regards,

Hi,

what would the new api recommend me to do, if I want to get font information for a certain piece of text? While moveTo(Run) doesn’t work, I have no idea to achieve this.

Beste regards
Klemens Schrage

Hi Klemens,

Thanks for your inquiry.

Please note that all text of the document is stored in runs of text. These runs of text are represented by Run nodes in Aspose.Words’ DOM and you can access the Font information of Run by using Run.Font property. I would suggest you to please read the following article:
https://docs.aspose.com/words/net/applying-formatting/

I hope, this helps.

Best regards,

Hello,

don’ t get me wrong.I’ m quite familiar with the Aspose.Words api and I know how to retrieve and change font information on runs.

I thought I could use the LayoutEnumerator to do some kind of my own document rendering. Unfortunately the information provided are only text and rectangle. I have no clue to find out the font. Therefore this new feature has very limited usecases and obviously not the one I need.

Maybe I misunderstand the intention. What usescases do you see for this api?

Beste regards
Klemens Schrage

Hi,

Thanks for your inquiry.

I am afraid, you can not use the LayoutEnumerator class to implement your own document rendering engine. As the name suggests, the Aspose.Words.Layout namespace provides classes that allow to access layout information such as on what page and where on a page particular document elements are positioned, when the document is formatted into pages.

Best regards,

Hi,

maybe I misunderstand the term/namespace “layout”. But isn’t the font information essential in order to have any real world benefit of that feature.

Even if we wouldn’t try want to render by our own. Let’s say we want to preview pagination. Without any backlink to paragraphs / runs the pagenumbers and rectangles provided for a small chunk of layouted text is not enough. Especially when you have text with reoccuring words ;-).

I understand that your model might just don’t have this information when the LayoutEnumerator comes to the stage. But in fact I can’t believe that this information is missing since the use becomes very vague.

Nevertheless it’s the first version of the new api. Would it be possible to add features like that in the future?

Best regards
Klemens Schrage

PS: I want to thank you for the first class support you are providing. Even with such an asynchronous medium like a forum it’s almost immediately.

Hi Awais,

thanks for the reply - I’ve now started to understand how the layout enumerator really works and I have worked out how to do quite a lot of the things that I need to do.

It turns out that when you move to the paragraph node, the LayoutEnumerator ends up at the end of the paragraph pointing to a ‘span’. You can then do MoveParent on the LayoutEnumerator and you now have the last line of the paragraph. You can get the first line by doing a MoveNode on the previous para, then MoveParent, then MoveNext.

Once you have the first and last lines of the paragraph identified in the LayoutEnumerator, you can find the paragraph bounding box easily enough, or if you want you could walk all the lines and spans and match them up with the text of the paragraph node and it’s contained runs.

Overall great functionality, but some more examples and documentation would help

thanks,
Robin

Hi Robin,

nice explaination. I think my problems could be solved with this (I have to test it though).

Best regards
Klemens

Hi,

In addition, I would like to share a few bits of more information; yes, the layout enumerator can move to ‘span’ objects in layout model i.e. APS (Aspose Page Specification model). A span in most cases is just a ‘paragraph break’ character (span can also be a ‘end of a table cell’ or ‘end of a table row’ character). For example, you can move to a Cell in APS by moving to the last/first paragraph in a Cell and then ascend to the parent entity using enumerator.

Also, please note that for each paragraph in the document, MoveNode will always position to the last span of the paragraph (which is a paragraph break) and of-course you can move to parent of that span (which is line) and track all last lines of paragraph until last line of a previous paragraph.

Moreover, we have added a couple of example projects (see DocumentLayoutHelper and EnumerateLayoutElements projects) in the Aspose.Words for .NET Samples package. I hope, this helps in clarifying the concepts of this new API and of-course we will be sure to improve the documentation in future.

Please let me know if I can be of any further assistance.

Best regards,

The issues you have found earlier (filed as WORDSNET-7756;WORDSNET-7757) have been fixed in this .NET update and this Java update.

This message was posted using Notification2Forum from Downloads module by aspose.notifier.