All posts by Dominik

Dominik is a PhD student at the Control Theory and Robotics Lab, TU Darmstadt, as part of the Research Training Group GKMM (GRK1362). My research focuses on state estimation in distributed systems. As hobby, I contribute to the KDE project and work on the Kate application and editor component.

Akademy 2013

So Akademy 2013 is nearing and this time it takes place at Bilbao, Spain. As it happens, Bilbao is located quite near to the beach as well as very close to the mountains. So I stumbled over a page with several hiking trails starting in Bilbao ranging from easy to hard. For instance, this route starts in a nearby village and then goes from about 65 meters in height up to 1000 (this is the point where you stop to hack on KDE, of course), and then down to 30 in Bilbao again. Anyone? :-)

PS: Maybe there are any locals who know the place around and can recommend a hiking track?

 

How to convert pdf to svg

In a project I’m currently working on I need to display the result of TeX code. So I thought it would be nice and accurate to compile the TeX code to produce a pdf, and then use libpoppler-qt4 to draw the pdf. This works in principal, but there is a licensing problem: libpoppler is GPL, and I want to use it in a LGPL library.

So I searched the net and found dvipng, which converts a dvi file to png. It even supports transparent backgrounds. So I could convert the dvi file to png through QProcess+dvipng, and then display the png file. This works, but whenever you scale the canvas the result looks ugly since png is not a vector graphic.

Next, I found pdf2svg that converts a pdf file into the scalable vector graphics format svg. In theory, I then can use QSvgRenderer to load and render the SVG on-the-fly using QSvgRenderer::render(QPainter*, …). So I first tested to convert the pdf to svg with this tool and then view it in InkScape. The result was perfect: InkScape renders the svg file exactly like Okular renders the pdf file:

So I looked into the source code of pdf2svg and saw that it uses libpoppler with Cairo. This reflects an additional dependency on cairo, so I went ahead and converted the cairo based code to Qt, using libpopper-qt4. The code basically boils down to:

// create poppler pdf document
Poppler::Document *document = Poppler::Document::load(args[1]);
document->setRenderBackend(Poppler::Document::ArthurBackend);
document->setRenderHint(Poppler::Document::Antialiasing, true);
document->setRenderHint(Poppler::Document::TextAntialiasing, true);
document->setRenderHint(Poppler::Document::TextHinting, true);
document->setRenderHint(Poppler::Document::TextSlightHinting, true);
document->setPaperColor(Qt::transparent);
// prepare QSvgGenerator as QPaintDevice
QSvgGenerator svgGenerator;
svgGenerator.setResolution(72); // resolution in dpi
svgGenerator.setFileName("out.svg");
svgGenerator.setSize(document->page(0)->pageSize());

// perform painting
QPainter painter(&svgGenerator);
document->page(0)->renderToPainter(&painter);
painter.end();

This code does indeed generate the svg code for the pdf file. However, the result is surprisingly ugly and wrong:

First, the pen seems too thick, and second the character ‘d’ is wrong on the left. I’ve tried changing the resolution (setResolution()) and also the page size (setSize()) of QSvgGenerator, always getting the same result. Searching the net reveals that QSvgGenerator seems to have quite some glitches with respect to WYSIWYG rendering. I tried to use QSvgGenerator before in 2009 and came out with unusable results. Maybe I’m missing something?

Update 1: It’s not QSvgGenerator that is to blame here. It’s indeed the Arthur backend of libpoppler. I send a patch to the poppler developers that fixes the issue with too bold glyphs. The pahts are still too inaccurate, though.

Update2: Using dvisvgm with the option –no-fonts results in an SVG file that QSvgRenderer renders correctly. So this is the current solution to get a TeX document rendered via SVG in Qt.

Kate: Search & Replace Notifications in KDE 4.11

In KDE 4.10, the “Find All” and “Replace All” highlights all matches and at the same time shows a passive notification in a bar below the view. This bar is animated, and takes quite a lot of place in addition to the search & replace bar.

Since some days, Kate Part can also show passive notifications floating in the view. Hence, we’ve changed the passive notification to appear on the bottom right as a small info message, showing the number of matches. However, in order to make this passive notification as small as possible, we removed the “Close” button, since the notification is hidden after 3 seconds anyway. Further, we removed the “Keep Highlighting” button. If you want to keep the highlights, just do not close the search & replace bar. The following video demonstrates this behavior, first for KDE 4.10, then how it currently will be in KDE 4.11 (watch the video in 720p):

Kate: New contributors, Valgrind, and a fixed bug

In the recent months Kate saw quite some contributions from developers other than “the usual kate developers”. This is really cool, areas include more work on python plugins, a lot of bug fixing and fine tuning in the vi input mode, an improved python indenter, and more unit tests. Especially one unit test turned out to be immensely useful and resulted in a fix for the infamous “rangesForLine” crash (about 40 times reported). We even decided to backport this to KDE 4.10.2, so KDevelopers and Kile LaTeXers please keep an eye open on whether this has any side effects!

Basically, the unit test provided us with a valgrind trace. Since valgrind is a very useful tool for all developers, we’ll have a closer look at the valgrind trace:

==10276== Invalid read of size 4
==10276== at 0x62F2116: Kate::TextCursor::lineInternal() const (katetextcursor.h:134)
==10276== by 0x62F9035: Kate::TextBlock::updateRange(Kate::TextRange*) (katetextblock.cpp:572)
==10276== by 0x62F8C57: Kate::TextBlock::mergeBlock(Kate::TextBlock*) (katetextblock.cpp:522)
==10276== by 0x62EFAA1: Kate::TextBuffer::balanceBlock(int) (katetextbuffer.cpp:494)
==10276== by 0x62EF1B2: Kate::TextBuffer::unwrapLine(int) (katetextbuffer.cpp:298)
==10276== by 0x637BB9C: KateBuffer::unwrapLines(int, int) (katebuffer.cpp:292)
==10276== by 0x6359DE9: KateDocument::editRemoveLines(int, int) (katedocument.cpp:1321)
==10276== by 0x6359AD6: KateDocument::editRemoveLine(int) (katedocument.cpp:1293)
==10276== by 0x6357841: KateDocument::removeLine(int) (katedocument.cpp:732)
==10276== by 0x6394C6A: KateScriptDocument::removeLine(int) (katescriptdocument.cpp:513)
==10276== Address 0x14353470 is 96 bytes inside a block of size 152 free’d
==10276== at 0x4C2A44B: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==10276== by 0x62FDE4D: Kate::TextRange::~TextRange() (katetextrange.cpp:66)
==10276== by 0x6470B1E: KateOnTheFlyChecker::deleteMovingRange(KTextEditor::MovingRange*) (ontheflycheck.cpp:535)
==10276== by 0x6470657: KateOnTheFlyChecker::rangeEmpty(KTextEditor::MovingRange*) (ontheflycheck.cpp:489)
==10276== by 0x62FE641: Kate::TextRange::checkValidity(int, int, bool) (katetextrange.cpp:196)
==10276== by 0x62F6C84: Kate::TextBlock::wrapLine(KTextEditor::Cursor const&) (katetextblock.cpp:168)
==10276== by 0x62EEF1D: Kate::TextBuffer::wrapLine(KTextEditor::Cursor const&) (katetextbuffer.cpp:231)
==10276== by 0x637BA6D: KateBuffer::wrapLine(KTextEditor::Cursor const&) (katebuffer.cpp:275)
==10276== by 0x635972E: KateDocument::editInsertLine(int, QString const&) (katedocument.cpp:1246)
==10276== by 0x6357690: KateDocument::insertLine(int, QString const&) (katedocument.cpp:706)
==10276== by 0x6394C32: KateScriptDocument::insertLine(int, QString const&) (katescriptdocument.cpp:508)

The trace tells us that somewhere in TextCursor::lineIntern() we read a variable/address that is invalid. In fact, we are reading a pointer called m_block that should be valid. In this case, as we know the pointer should be valid, we can conclude that the entire TextCursor object is then corrupted/invalid. Since the cursor is part of a TextRange, it means the TextRange is already invalid. Interestingly, this is exactly what valgrind is telling us in the lower part: The TextRange destructor that lead to the invalid read above is called in the 2nd half of the valgrind trace. From this, we can conclude that the function KateTextBuffer::mergeBlock() accesses a dangling pointer to a TextRange.

That’s a good start, but in fact, this is where the hard work begins. I’ve invesed about 2 hours to find that probably the dangling pointer is in a cache that is supposed to make the access of the TextRanges (MovingRanges to be precise) faster. Christoph then looked into it and tried several attempts to fix the nasty bug, finally showing us that the cache was indeed wrong but due to a too-late fixup of the start/end text cursors with respect to the TextBlocks. In total, Christoph probably invested about 6 hours, and given that Gerald certainly took quite a lot of time too to write the unit test, we probably have more than 10 ours just to get this bug fixed. Still, the good news is that we got it! And if we are lucky, this was the last bug in  Kate’s text buffer. So on to the next crashes… Help welcome!