[scribus-dev] Tables GSoC - Weekly Report #5

Elvis Stansvik elvstone at gmail.com
Tue Jul 5 16:56:32 UTC 2011


2011/7/5 Craig Bradney <cbradney at zip.com.au>:
> On 7/5/11 1:43 PM, Elvis Stansvik wrote:
>
> Hi Craig and everyone,
>
> A full two days late, but here's my fifth report [1].
>
> The reason it took such time is that I was scrambling to get my local
> branch with the painting refactor work ready to be pushed. I pushed it
> late last night (or early morning depending on how you see it :)
>
> No screencast this time, just an attached screenshot that shows some
> collapsed joined and non-joined borders in Scribus
> (scribus_table_joins.png).
>
> Cheers,
> Elvis
>
> [1] http://wiki.scribus.net/canvas/GSoC_2011_Tables_Weekly_Reports
>
> = Tables GSoC - Weekly Report #5 =
>
> == Work Report ==
> * Fixed the API docs of Scribus to work with Doxygen 1.7+.
> ** Some HTML elements had changed, so the CSS was updated to match.
> ** Updated Doxyfile with `doxygen -u'.
> ** Added *.js and *.repository to `clean' target as those are
> generated nowadays. No *.ttf seems to be generated anymore, but I kept
> them in to stay compatible with older Doxygen.
> ** Enabled JAVADOC_AUTOBRIEF (OK:ed by avox on IRC).
>
> The above is not directly related to my project, but as I try to
> document all code I'm writing I wanted to see what it looks like by
> generating it locally. Anyway, it was 15-20 min of work. Moving on, I
> also
>
> * Added class TableBorderLine which represents a single line in a
> table/cell border. Perhaps it can be scrapped in favor of the
> SingleLine class in scribusstructs.h as they are very similar, but I'm
> keeping it for now.
> * Added class TableBorder which represents a border along one side of
> a table/cell. It is essentially a list of TableBorderLine with a
> convenience function bool joinsWith(const TableBorder& other) const;
> to check if it can be joined with another border. A TableBorder with
> no TableBorderLines in it is considered a null border. These are used
> for convenience during painting to represent the absence of a border.
> * Updated the scripting API and table/cell styles to use the new
> border system instead of individually set border color/width/et.c.
> properties.
> * Added abstract base class TablePainter representing a painter that
> can paint a PageItem_Table. The class has a single pure virtual
> function void paintTable(ScPainter*) in which subclasses should do
> their work.
> * Added class CollapsedTablePainter, an implementation of TablePainter
> that can paint a table with borders collapsed and joined at
> intersections.
> * Modified PageItem_Table to hold a pointer to a TablePainter and
> paint itself using this painter in the DrawObj_Item(...) function.
> * Added three utility functions, kept in a new TableUtils namespace
> for easy unit testing. The functions are used by CollapsedTablePainter
> when collapsing and joining borders. They are
> ** collapseBorders(...) which given two borders returns them collapsed,
> ** joinHorizontal(...) which given a horizontal table border and its
> adjoining borders will return the adjustments necessary for joining
> the border,
> ** joinVertical(...) which given a vertical table border and its
> adjoining borders will return the adjustments necessary for joining
> the border,
> * Added columnPosition(int) and rowPosition(int) API to PageItem_Table.
> * Added an QString asString() const; to CellStyle for easy printing.
>
> In addition to just listing the changes like this, I feel I need to
> elaborate a bit on what has taken such time. I did explain it a little
> bit in an earlier mid-week report. The problem has been a hard one for
> mainly two reasons:
>
> * Each cell may have N neighboring cells along one of its edges. The
> objective of the painting algorithm is to iterate over all cell edges
> in the table, and for each cell edge, iterate over all shared border
> sections. It must then figure out all (possibly six) cells surrounding
> the border section to be painted, along with the collapsed borders
> between them (or between them and the table). When that is done, the
> border section (or rather, the coordinates at which to paint the
> border section) needs to be adjusted for joining. This is delegated to
> the joining algorithm.
>
> * There are 41 one possible join cases (that I've identified at
> least). They can be seen in the attached picture, which I finally had
> to draw to sort it out in my head. The objective of the joining
> algorithm is then to, given a border section along with the other
> border sections coming in to meet it at its start and end point,
> return adjusted start and end points as well as offsets for the
> individual border lines in order to make a proper join.
>
> On top of this is the question of painting order. The joining
> algorithm must be necessity make an assumption about painting order;
> either horizontal borders should be painted on top for the algorithm
> to work, or vertical should be painted on top.
>
> The joining algorithm I've written assumes that all horizontal borders
> in the table are painted on top of vertical ones, which means two
> iterations across the cells. I've been unable to find an algorithm
> which makes no assumption about the painting order. I don't think
> there is any actually, and iteration across the table cells should be
> fast enough. Perhaps in the future optimizations could be made, but
> then I think they should rather be done to the internal structures of
> the table to make cell accesses fast,
> rather than convoluting the joining algorithm.
>
> All in all, a tough nut to crack, and there are currently the
> following two small problems with the painting/joining left:
>
> 1) The joining algorithm does not handle some cases properly.
> 2) The painting algoritm sometimes mistakenly identifies a neighboring
> border as a null border.
>
> For 1), I feel that I need a break from this problem to not go insane,
> and will let it go for now. The code is completely isolated in
> TableUtils::joinHorizontal(...) and TableUtils::joinVertical(...) and
> can be improved on later. I welcome anyone who likes puzzles to look
> at the picture with the 41 join cases and see if they can find an
> optimal algorithm that covers all cases with a minimal amount of code.
>
> For 2) I know the reason and how to fix it, it's just that I haven't
> gotten around to it. In short, what happens is that instead of
> collapsing with the table border, it's requesting a cell outside the
> table, which will return an invalid cell with a null border, and
> collapses with that.
>
> As I've intentionally kept the collapsing and joining algorithms as
> separate functions in the TableUtils namespace, what remains is to
> write unit tests that cover all the 41 cases.
>
> == Project Status ==
> I'm still behind schedule by at least one week. The reason I decided
> to put all my efforts into getting this painting working correctly is
> I didn't want to leave it unfinished, or leave a design that would
> later come back and bite me when trying to paint complex borders.
>
> I had no idea it would be such much hard work. I think I've used up
> all my sketchbooks on this problem, and lost some sleep over it. I
> feel now that, to not lose my mind, I really need to get on with some
> of the other problems, such as UI and integration with text frames.
>
> I've looked ahead a bit on my schedule, and found that
>
> Week 6:
> * Wrapping up for mid-term evaluation.
> * Fix bugs/finish up what I have so far.
>
> Week 7:
> * Row and column spanning.
>
> Week 8:
> * Table/row/column/cell styles.
>
> Since row and column spanning is done, and the styles are in a pretty
> good shape (they are there, and new properties can be added removed
> easily), I feel that there's still a good opportunity for me to catch
> up.
>
> == Problems / Questions ==
> My biggest question right now is:
>
> * What should be the general approach for integration of text frames?
> The table will hold a set of text frames for its cells, but then? The
> user should be prohibited from doing certain things to the text
> frames, such as selecting and resizing them. This should be handled by
> the table. In a way they will be similar to locked text frames, until
> the user decides he wants to edit their content. Should I go for an
> approach where I add a bool isTableCellContent() or similar to
> PageItem_TextFrame? Or should PageItem_TextFrame even be inherited,
> creating a new item for cell content? I'm open to all ideas, so if you
> happen to have given this problem some thought, please share, because
> frankly I haven't (yet).
>
> == Next Week ==
> I'll yet again be working on catching up with my schedule, which means
> working on integration of text frames and basic UI. Since mid-term
> evaluation is next week, perhaps I should also write some kind of
> mid-term report. What do you think Craig, do you think its worthwhile
> or just a waste of coding time? Perhaps you feel up to date enough
> with my status. I also really should get around to making another blog
> post showing the new features, as I've only made one post so far.
>
>
>
> All in all, its very impressive. I'll catch up with you on IRC though.

Great.

> For frames.. remember we need to allow images (etc) in cells too.. so
> considering that is important when deciding on a method. I suspect a cell
> frame type is going to be required to inherit what is needed (only). You may
> even find (I suspect this to be the case) that you don't actually want all
> the mess/history that comes with text frames.

Right. For cell background images, I imagined these will be drawn by
the table painter, same as for cell fills. I could take a look at the
image frame for inspiration. With "(etc)", what did you have in mind
more specifically?

Regarding mess/history of text frames, do you mean to change tactic
and not use text frames at all? Or just that only parts of them should
be reused? How separate is the text layout engine of Scribus from the
text frame page item type? Is there an easy way of telling the text
layout engine "here, layout this text in this rect"? But then, I'd
lose a lot of text user interaction code that has gone into the text
frame page item and its associated canvas mode, wouldn't I? I feel I
really need to do some investigation of these parts of the code..

> I also think that it might be important to aim for the GUI controls of what
> you have working via the scripter as a higher priority than content - this
> will enable more of us to control and test the frames, borders and all that
> stuff.

I agree. Perhaps I should put my focus on getting basic UI support for
column/row/table resizing, editing of table properties and editing of
cell/table styles first, and then work on the text frame integration
(or whatever will be the solution).

> I'll review the timetable later tonight and see what that means for the
> above..

Good.

> I'll think about the mid-term review. Your reports have been detailed and
> well communicated, so I expect a summary would be nice but repeating all
> that has been written is not necessary.

Alright. I'll make a brief summary with the highlights from my reports.

> Talk to you soon in IRC I hope.

Yep. Will be there all day.

Thanks for the feedback!

Elvis



More information about the scribus-dev mailing list