Index ¦ Archives ¦ RSS > Category: libreoffice ¦ RSS

My hack week at Collabora: btLr text direction in Writer

Estimated read time: 4 minutes

As mentioned in my previous such report, a hack week is when we are allowed to hack on anything we want in LibreOffice for a few days at Collabora. I used this time to implement core support for the btLr text direction in Writer.

Motivation

If you work with tables in Word, it’s very easy to create this writing direction: the context menu in a table cell has a menu item to set the direction of the text, where you can rotate the text by 90 degrees counter-clockwise or clockwise. The counter-clockwise btLr direction is the problematic one. Support for tbRl was fine already, since that is needed typically for Chinese/Japanese scripts as well.

Results so far

Here is how the baseline, the current and the reference rendering of btLr text looks like:

https://lh3.googleusercontent.com/o5t6-JQeeNaZpx0YURMvS6xUJv7L4KbkbKnn6VPQ0yzULxHFI15ufkwaw_m0FVY7B2tv8gOnTw1CEY2Uxq6BFTgXHlcorXS52J8X1-mNjsyHKYDmoNG-MQ9X1LtdUWmrLl_W3b2ifQ=w640
Figure 1. btlr-cell.docx, baseline
https://lh3.googleusercontent.com/Y8jXvq7TFyNoKVjwWd_QvJNJaOySZdKZE_HqqBaTwGoi_rExCee3eDAHx4AS49E7d7bcjG8SEgxnXOmdKFXaJx0MzmadungQ7D0SVqdSqC2trMC9InsHdKUTq1iwu5p8bDwUfIizng=w640
Figure 2. btlr-cell.docx, current
https://lh3.googleusercontent.com/KYSBaOiAMdy_U8shsb4zoS8J5uyZzwkFPZY4qIKTrHKlo-M-pCdiHHBUxZ9OmQ-uv_QkBiktXeprTQD6gANDvzDVi8JWs4-Ng2RL-uoMcQCrQNL6Hk7tjXSJBaaqxc2skfZzmepkqA=w640
Figure 3. btlr-cell.docx, reference

You can see how the second paragraph in the cell was missing from the rendered result and now we basically pixel-by-pixel match the reference.

How is this implemented?

If you would like to know a bit more about how this works, continue reading… :-)

The document model and UNO API were reasonably straightforward to implement, but the layout was much more challenging. Writer already supported 3 writing directions:

  • typically used for Latin (left to right, top to bottom)

  • Chinese/Japanese (top to bottom, right to left)

  • Mongolian (top to bottom, left to right) text.

This new one is also a vertical direction, also left to right, but bottom to top. The initial layout contained code to read the new enumerator from doc model, extend the SwFrame class to handle this new bottom to top mode, some handling of switching between horizontal/vertical mode and at the end mapping from Writer layout’s direction to VCL’s "900" font orientation. There are more things to handle in layout, but this was good enough to look at other areas as well.

The ODF filter required updating, which was a bit challenging as it was necessary to write different attribute names depending on which enumerator is used from an emumeration, and we don’t have good support for this. Once the filter code was in place, I could write some layout-level tests as well.

Since we have .ui files for UI descriptions, adding UI support was really easy.

Time came to step away from coding for a moment and write up paperwork to propose this feature to be part of the next ODF version (thanks to Andras for the help there!).

Finally I went back to layout, and improved things a bit more: after fixing baseline offsets, the positioning of the text was exactly matching what Word does. How do I know? I used this little script:

gs -dNOPROMPT -dBATCH -sDEVICE=jpeg -r75 -dNOPAUSE -sOutputFile=btlr.jpg btlr.pdf
gs -dNOPROMPT -dBATCH -sDEVICE=jpeg -r75 -dNOPAUSE -sOutputFile=btlr-word.jpg btlr-word.pdf
composite -compose difference btlr-word.jpg btlr.jpg out.jpg

Which allows seeing the differences between our and Word’s PDF output. Additional work was needed to handle multiple paragraphs in a table cell. At this stage I was happy enough with the rendering result, so finally pulled the trigger and replaced the old DOCX filter hack (using character-level rotation) with simple DOCX filter mapping from OOXML’s btLr direction to Writer’s btLr direction — i.e. what was already done for the tbRl case.

Future work

The feature works good enough already so that this new core feature can be used by the DOCX filter by default, but there are still a few rough edges:

  • the shell code (cursor travelling, selection painting, etc) only has partial support for this new direction

  • RTF and DOC filters are not yet updated

  • the ODF proposal has a list of contexts other than table cells where the new writing direction could be used, which lack UI/filter support/etc at the moment.

All this is available in master (towards LibreOffice 6.3), so you can grab a daily build and try it out right now. :-)


Improving SmartArt import in Impress FOSDEM talk

Estimated read time: 1 minutes

(via cor4office)

The next step in the recent SmartArt story is my Improving SmartArt import in Impress talk at FOSDEM 2019, in the Open Document Editors devroom. The room was a bit far away from the popular places, but the livestream worked out nicely.

There was also a hackfest before the conference, I looked at RTF export of rotated Writer pictures.


SmartArt improvements in LibreOffice, part 3

Estimated read time: 2 minutes

I recently dived into the SmartArt support of LibreOffice, which is the component responsible for displaying complex diagrams from PPTX. I focus on the case when only the document model and the layout constraints are given, not a pre-rendered result.

First, thanks to our partner SUSE for working with Collabora to make this possible.

Continuous Block Process, Accent Process and Organization Chart

In this post I would like to present the progress done last month regarding the above mentioned diagram types — these are used in many documents.

The improvement (as always) come in small incremental steps:

  • Continuous Block Process now reads space width from constraints.

  • Accent Process now has the missing bullets and fixes an incorrect large paragraph-level indent.

  • Organization Chart now has an initial implementation of the hierRoot and hierChild algorithms.

  • Organization Chart now handles multiple employees for a manager.

With all these fixed, we reach a much better state for the mentioned diagram types.

Results so far

The SmartArt test documents from sd/qa/unit/data/pptx/ is what I used for testing this work.

Here is how the baseline, the current and the reference rendering of Accent Process looks like:

smartart-accent-process.pptx, baseline

smartart-accent-process.pptx, current

smartart-accent-process.pptx, reference

And here is how the baseline, the current and the reference rendering of Organization Chart looks like:

smartart-org-chart.pptx, baseline

smartart-org-chart.pptx, current

smartart-org-chart.pptx, reference

This is not not perfect yet, but it’s clearly a large improvement, all text is now readable from the diagrams and bullets are no longer missing!

All this is available in master (towards LibreOffice 6.3), so you can grab a daily build and try it out right now. :-)


SmartArt improvements in LibreOffice, part 2

Estimated read time: 2 minutes

I recently dived into the SmartArt support of LibreOffice, which is the component responsible for displaying complex diagrams from PPTX. I focused especially on the case when only document model and the layout constraints are given, not a pre-rendered result.

First, thanks to our partner SUSE for working with Collabora to make this possible.

Accent Process

In this post I would like to present the progress regarding the Accent Process preset, available in PowerPoint — which is used in many documents.

This exposed several shortcomings of the current diagram layout we have in LibreOffice:

  • Values are not read from constraints (there was a reason for this, they can be complex, given that depending on the context, the unit is points or millimeters and the unit is always implicit).

  • ZOrder offsets were ignored.

  • Linear algorithm did not take size from constraints when it came to recursing into child algorithms.

  • Data point assumed that all text for it is a single "run" (i.e. either all text is bold or nothing, not half of it).

  • followSib axis was not implemented for forEach, so when you have arrow shapes between objects, we created N arrows, not N - 1 ones.

  • Connectors were created as invisible shapes and had the wrong width/height aspect.

With all these fixed, we reach a much better state for handling accent process.

Results so far

smartart-accent-process.pptx is what I used for testing of this work.

Here is how the baseline, the current and the reference rendering of the test documents look like:

smartart-accent-process.pptx, baseline

smartart-accent-process.pptx, current

smartart-accent-process.pptx, reference

This is not not perfect yet, but it’s clearly a large improvement, all text is now readable from the diagram!

All this is available in master (towards LibreOffice 6.3), so you can grab a daily build and try it out right now. :-)


SmartArt improvements in LibreOffice

Estimated read time: 2 minutes

I recently dived into the SmartArt support of LibreOffice, which is the component responsible for displaying complex diagrams from PPTX, especially in case only document model and the layout constraints are given, not a pre-rendered result.

First, thanks to our partner SUSE for working with Collabora to make this possible.

The problem

There are several ones. :-) If you are just interested in high quality viewing of PPTX files, then your problem started with PowerPoint 2007 not writing a pre-rendered drawingML markup of the diagram to the files, only PowerPoint 2010 started behaving like this. Additionally, if a diagram is not edited, then re-saving with PowerPoint 2010 doesn’t seem to generate the drawingML markup, either. This means that data + constraints cases are quite frequent even today.

Also, one day Impress should be able to actually edit these SmartArts as well, so having the knowledge how to lay out SmartArt (even if it’s import-time-only at the moment) is a good thing.

Results so far

I always write cppunit tests when I work on filter code (in this case OOXML), so far all fixes were visible in just two test files: smartart-vertial-box-list.pptx and vertical-bracket-list.pptx.

Here is how the baseline, the current and the reference rendering of these test documents look like:

smartart-vertial-box-list.pptx, baseline

smartart-vertial-box-list.pptx, current

smartart-vertial-box-list.pptx, reference

vertical-bracket-list.pptx, baseline

vertical-bracket-list.pptx, current

vertical-bracket-list.pptx, reference

In terms of code commits, the fixes are split into several ones:

Clearly the results are not perfect yet, but in both cases nothing was visible, and now all text is readable, so we’re moving in the right direction!

All this is available in master (towards LibreOffice 6.2), so you can grab a daily build and try it out right now. :-)


Text layout performance in LibreOffice conference lightning talk

Estimated read time: 1 minutes

Last Friday I gave a Text layout performance lightning talk at LibreOffice Conference 2018. Click on the image to get the hybrid PDF slides!


ReqIF import/export in LibreOffice Writer conference talk

Estimated read time: 1 minutes

Earlier today I gave an Editing ReqIF-XHTML fragments with Writer talk at LibreOffice Conference 2018. The room was well-crowded — perhaps because the previous talk was about OOXML interoperability. ;-)

I expect quite some other slides will be available on Planet, don’t miss them.


API improvements in LibreOffice

Estimated read time: 3 minutes

https://farm2.staticflickr.com/1793/43859007612_ca207fed0f_o.png

I worked on two small features to extend the public (UNO) API of LibreOffice. First, thanks to Vector for funding Collabora to make this possible.

Aliased paths and text in the PNG export for Draw

The UNO API of Draw allows you to build quite complex and custom shapes, but you may want to export the rendered result to a bitmap for testing purposes, so you can assert that the actual result matches a reference one.

One problem in this area is anti-aliasing, which can easily differ between machines. Given that normally aliased rendering is ugly, there is now a way to enable AA, but disable it just during a single invocation of the PNG exporter.

The above picture shows how the AA result looks like. You could write a Basic macro like this to trigger the PNG export from Draw:

xExporter = createUnoService("com.sun.star.drawing.GraphicExportFilter")
xExporter.SetSourceDocument(ThisComponent.DrawPages(0))
Dim aArgs(1) As new com.sun.star.beans.PropertyValue
aArgs(0).Name  = "URL"
aArgs(0).Value = "file:///tmp/debug/aa.png"
aArgs(1).Name  = "MediaType"
aArgs(1).Value = "image/png"
xExporter.filter(aArgs())

Let’s see how it looks like if you turn AA off:

https://farm2.staticflickr.com/1832/43859007522_aeb4516f02_o.png

You just need to specify a new Antialiasing key under FilterData:

Dim aFilterData(0) As new com.sun.star.beans.PropertyValue
aFilterData(0).Name = "AntiAliasing"
aFilterData(0).Value = False
xExporter = createUnoService("com.sun.star.drawing.GraphicExportFilter")
xExporter.SetSourceDocument(ThisComponent.DrawPages(0))
Dim aArgs(2) As new com.sun.star.beans.PropertyValue
aArgs(0).Name  = "URL"
aArgs(0).Value = "file:///tmp/debug/non-aa.png"
aArgs(1).Name  = "FilterData"
aArgs(1).Value = aFilterData()
aArgs(2).Name  = "MediaType"
aArgs(2).Value = "image/png"
xExporter.filter(aArgs())

You can imagine which rendering result is easier to debug when the reference and the actual bitmap doesn’t match. ;-)

Note
This feature is available for other bitmap formats as well, PNG is only an example.

Default character style in Writer

In most cases you don’t really need a default character style: if you’re fine with a default, then the default paragraph style should be enough for your needs. In general, paragraph styles can contain character properties, so if the default is fine for you, you just don’t set a character style.

However, there is an exception to all rules. If you want to reset the current character style, it makes sense to just set the CharStyleName property to a default value, especially since this works with paragraph styles already.

Now you can write C++ code like this (see SwUnoWriter::testDefaultCharStyle() for a full example):

xCursorProps->setPropertyValue("CharStyleName", uno::makeAny(OUString("Standard")));

And it’ll be handled as Default Style in English builds, or their localized versions in a non-English UI.

All this is available in master (towards LibreOffice 6.2), or you can grab a daily build and try it out right now. :-)


Editing ReqIF-XHTML fragments in LibreOffice Writer

Estimated read time: 2 minutes

I worked on a small feature to use Writer as an editor for the XHTML fragments inside Requirements Interchange Format (ReqIF) files. First, thanks to Vector for funding Collabora to make this possible.

Writer already supported XHTML import and export before (see my previous post) as a special mode of the HTML filter, this work builds on top of that. The main speciality around XHTML as used for fragments inside a ReqIF file is embedded objects.

The special mode to opt-in for ReqIF-XHTML behavior can actived like this:

  • during import: --infilter="HTML (StarWriter):xhtmlns=reqif-xhtml"

  • during export: -convert-to "xhtml:HTML (StarWriter):xhtmlns=reqif-xhtml"

Three different cases are handled:

  1. Image with native data we don’t understand and just preserve.

  2. Image with OLE2 data, which we hand out to external applications (at least on Windows). On the above video this is an embedded PPSX file, handled by PowerPoint.

  3. Image with ODF data, which we handle internally. This is a Draw document on the above video.

Regarding how it works, the import is a series of unwrapping containers till you get to the real data and the export is the opposite of this. Here are the layers:

  • Larger ReqIF files have the .reqifz extension, and are ZIP files containing an XML file, having the XHTML fragments. This is not relevant for this post, as Writer assumes that extracting the XHTML fragment from ReqIF is done before you load the content into Writer.

  • XHTML always has a PNG image for the object, and optionally it has RTF as native data for the object.

  • The RTF file is a fragment, containing just an embedded OLE1 container.

  • The OLE1 container is just a wrapper around the real OLE2 container.

  • The OLE2 container either has the data directly or MSO has a convention on how to include OOXML files in it (see the PPSX example above), and we handle that.

On export we do the opposite: save the file, put it into OLE2, then into OLE1, then into RTF, finally into XHTML.

There is no specification on how to put ODF files into OLE2, so I extracted the relevant code from LibreOffice’s binary MSO filters and now the Writer HTML filter uses that as well. This avoids code duplication and also could avoid inventing some new markup this way.

All this is available in master (towards LibreOffice 6.2), or you can grab a daily build and try it out right now. :-)


Lazy reading images from Microsoft formats in LibreOffice

Estimated read time: 1 minutes

I worked on improving document load performance of Microsoft formats in general, and DOC/DOCX in particular in LibreOffice recently. First, thanks to TDF and users that support the foundation by providing donations for funding Collabora to make this possible.

I built on top of the great work of Tomaz, focusing on these secondary, but important formats.

The idea is that if you load an Microsoft binary or OOXML file, it should not be necessary to parse all images at load time, it’s enough to lazy read it when we first render e.g. a Writer page containing that image.

The focus here was documents containing large images. I tested with an Earth photo of size 8000x8000 pixels from NASA, making little modifications to it, so each picture has a different checksum, embedding them into a binary DOC file.

https://farm1.staticflickr.com/980/41838412652_c1cbefcfc1_o.png

I measured the time from the soffice process startup to rendering the first page. We defer the work of loading most images now, as you can see on the chart. In contrast, we used to decompress all images on file import in the past. This means the new cost for e.g. 4 images is 37% of the original.

All this is available in master (towards LibreOffice 6.1), or you can grab a daily build and try it out right now. :-)

© Miklos Vajna. Built using Pelican. Theme by Giulio Fidente on github.