Development/Aw080 documentation/Paradigm changes

Branch aw080
This page is part of the documentation for the aw080 branch for the Apache OpenOffice project (incubating). The main page can be found here

Paradigm changes
Changes that deeply influence relationships of objects between each other or principally different handling of model data, relationships of objects or processing of data.

New SdrObject/SdrModel paradigm

One of the most basic changes in aw080 is the relationship of SdrObject/SdrPage to SdrModel. Currently, SdrObjects can be created and exist without SdrModel. This is problematic and a source of many crashes, mainly because SdrObjects use a SfxItemSet to hold properties which itself relies on an SfxItemPool which is part of the SdrModel. No model, no SfxItemSet. In aw080, all SdrObjects need a SdrModel at construction time and it it is defined to not change during SdrObject's lifetime. This ensures much more stability in SdrObject and thus in DrawingLayer Model handling. It made migrating SdrObjects between SdrModels superfluous, too, so MigrateItemPool mechanisms could be removed. An objects instertion to a page is now completely decoupled from it's existance and always has a SdrModel and a Pool for it's PoolItems.

All usages were adapted to this, all SdrObject constructors, too. It is now safe to have helper SdrObjects vor varoius purposes; this was used in the past, but always was more than risky. It was neccessary to insert those SdrObjects somewhere (to a SdrPage or group) to have them get a SdrModel; existing hacks to make these invisible or similar were removed.

The old mechanism to insert an existing SdrObject to another model and thus really moving it was very dangerous and the source of many errors. It is now replaced with the SdrObject cloning mechanism; it now allows to clone an SdrObject to an alternative given new SdrModel or inside the current one (default). This makes removal/insertion of SdrObjects to SdrModels explicit and safe. All usages of this mechanism were adapted to the new ones, all SdrObject implementations of cloning adapted to do this safely and reliably.

The same is done for SdrPage and it's hierarchy, also complete with adaptions to all usages and all derivations. Constructors are reduced to a single one per class, members are adapted to hungarian notation and cleaned up. SdrPage has a method to also clone it to another model if it needs to be copied, completely implemented for all derivations.

SdrObject transformation changed to basegfx::B2DHomMatrix

This is a very basic paradigm change for SdrObjects. They now have a matrix-based definition for their basic object transformation, based on the basegfx::B2DHomMatrix class. Object size (scale), position (translate), shear and rotation are combined by linear combination as defined in Linear Algebra. This allows setting and getting these values back unchanged in double precision for the first time with SdrObjects.

The current implementation just applies geometrical changes to the object's geometry: When e.g. currently mirroring an object, it's geometry gets actively mirrored, but the state of the object – if it is mirrored or not – is lost. This is the reason why hor/ver mirroring cannot be switched on/off currently for SdrObjects or better controlled. This will change with aw080.

This is a very big change, adaption of all usages of all old changing methods is ongoing work. To support this, bridging helper classes are defined in svx/inc/svx/svdlegacy.hxx and used currently. These methods are defined as temporary helpers and will all be removed and replaced at the end of the adaptions. This is the main working point which is still ongoing with aw080 today. All usages of SdrObjects need to be adapted (all 14 users), the full Draw/Impress application with all modifers, Writer and Calc DrawingLayer usages, but also all import/export filters and UNO API implementations.

All SdrObjects are now constructed getting an initial transformation in the constructor, all constructors for SdrObject hierarchy are adapted to that. The object itself is always seen as being in a 'generic' state e.g. a rectangle object internally uses the unit rectangle from (0,0) to (1,1) and the transformation is thought to be adapted to it. This requires no geometry data any longer at most objects, it's implicit. All internal SdrObject handling can be unified in these unit coordinate system, e.g. glue points are now always relative in the ranges from 0 to 1 in X and Y. There are two exceptions for lines and measure objects (which have the generic form from (0,0) to (1,0)) and for polygons: the contained geometry is kept in world coordinates for practical reasons, but there is an interface supported to handle the contained geometry scaled to unit coordinates always being inside (0,0) to (1,1). This also means that principally all SdrObjects will be rotatable and shearable after aw080. This is already prepared in the working trunk, one of the reasons to allow this early for OLE and GraphicObjects.

Primitive creation paradigm change (also for 3D primitives)

Currently when the Primitves for an SdrObject are fetched using the ViewObjectContact a new Primitive representing the highest Primitive to represent the graphic representation of the object is generated. It is then compared to the existing one to reliably detect changes in visualisation (primitives contain all needed information for visualisation by definition). In most cases when nothing changed the old one is kept, preserving all it's buffered decompositions and reusing it. The reason for doing this was at the time when Primitives were implemented that the reset of the highest level Primitive was not reliable. In aw080 this is changed since the mechanisms to detect an object change are more reliable, so this is no longer needed. All operator== of all primitives were removed in aw080, they are no longer needed.

BoundRange definition view dependency

A very old problem is the correct BoundRange (bounding rectangle) calculation for graphic content. It is problematic since all older implementations did try to calculate this independent from a View, only based on model data. This is insufficient due to the fact that many graphic parts are view dependent. For example, each hairline is view dependent (and hairlines are the default in AOO); imagine zooming in and out, the lines defined to cover one pixel will cover various areas in logical coordinates. When zooming far out a hairline may have a corresponding logical width of some centimeters.

Thus, to calculate this correctly and to avoid refresh and repaint errors in the future which happen because the calculated range is too small, aw080 makes this calculation view-dependent as far as possible since the ViewTransformation is needed for correct calculation. As a consequence this means that objects have one BoundRange per view. Up to some rare occasions it was possible to change this. The last ocurrences use a fallback to an empty ViewTransformation and are marked for replacement in the future.

All NBC* methods removed

The old code has a NBC* method for nearly every method on SdrObjects which change object attributes or geometry on the DrawingLayer Model. NBC is short for NonBroadCasting. Broadcasting the changes of objects always was expensive, thus this possibilities were offered. It did not only lead to having always two calls for each function, but also forced the programmer using it to know enough about the DrawingLayer and the Application/User programming to decide if he could possibly call the non-NBC method. This led to what it had to lead, lot of notifications were missing and even after years of fixing bugs this conceptional error still causes errors. In aw080 all NBC-methods are removed for security reasons and the broadcasts are enhanced to happen less often and to be cheaper.

Many MapMode usages changed to getting ViewTransformation from OutputDevice

For quite some time now I had added methods at the OutputDevice to support the ongoing changes. These include getting the MapMode which is the ViewTransformaton as basegfx::B2DHomMatrix, and also it's inverse for back-transformations. I added for aw080 some more convenience methods at OutputDevice to directly convert MapModes to transformations and other handy stuff. I adapted most usages in DrawingLayer in aw080 to use these instead of the old LogicToPixel and others, thus complete geometries can be transformed with single calls and the ViewTransformation can easily be added to combined matrix stacks.

Page and List classes both based on one base class

The classe for pages (SdrPage) and group obejcts (SdrObjGroup) were derived from different base classes. This lead to many special handlings of traversing over object hierarchies and others, also a cause for many extra code and errors. Both are now based on SdrObjList. SdrObjList itself was adapted to support this using virtual methods for getting child and parent access. The derived page and group classes implement these accordingly. All places using page and group traversioning were adapted to this simplificaton. Insertion, removal and change of position/NavigationPosition are reimplemented and secured, STL classes are used to handle this.

One basic definition for the exchange of list of SdrObjects

A single basic definition SdrObjectVector is defined for this in SdrObject.hxx and used in all places/occurrences where lists of SdrObjects need to be exchanged (selection, travelling over hierarchies, etc.). Of couse this is using a STL vector class as base. All places in Drawinglayer where SdrObject lists were exchanged were adapted to this mechanism, many extra handlings and list conversions could be removed. All iterations can now use this base class. Even the SdrObjListIter is internally such a list created at construction time and could be used directly instead of using the iterator anymore.