Last week was Hackweek here at Novell, and I had a shot at improving svg support at two places inside OOo (I somehow keep returning to that topic):

  • made up my mind earlier that any attempt to convert svg to OOo’s internal vector format is a waste of time
  • made up my mind earlier that any attempt at implementing an own svg renderer on top of OOo’s graphic subsystem is of no practical value and a duplication of existing functionality
  • made up my mind earlier that plugging librsvg is the way to go:
    • added librsvg 2.26.3 and libcroco 0.6.2 to OOo source tree (mostly for windows builds), made it buildable inside OOo’s build system
    • hacked up a drawing layer primitive to render svg to a bitmap, everytime zoom or output device changes
    • made OOo treat svg as a ‘native’ graphics format, i.e. no longer converting it to internal vector representations, but keeping the original svg file inside the odf package (that actually took the longest time, due to several internal bugs I hit)
    • the final patch for the change is here – not yet 100% production ready, but feature complete
    • down the road, would be nice to use cairo’s ps, and especially pdf export, when detecting a suitable export operation
    • below is a screenshot of some awesome openclipart samples (from the always-brilliant Chrisdesign), both rendering fidelity and render speed are lightyears ahead of the internal import I once did, that maps to OOo’s internal vector format
      collection of inserted svg cliparts
    • The upstream feature request for the above is this issue, in which, after I had implemented this, an Oracle engineer announced something apparently similar – which, after several deleted cws, and a question about what’s going on remaining basically unanswered, was kind of a nasty surprise. If my interpretation of the (very sparse) information is accurate, this must have been developed in stealth mode – something inherently incompatible with FLOSS, I guess.
  • switched OOo’s internal svg:d parser from an ad-hoc old implementation to a slighty better ad-hoc shared new implementation, that is able to interpret elliptical arc segments (a somewhat longstanding feature request). Patch for this change (needs to be hoisted to dev300 code line, which is ~trivial) is here. It seems the corresponding issue got closed a bit prematurely…

Managed to squeeze two days of Libre Graphics Meeting in my schedule this year again, and it was again exceeding expectations. The creative mix of artists, designers and hackers is unique and extraordinary, the talks, covering both work of art & software, are mostly a revelation (to me). The organizers around Femke, Nicolas & Anne managed to grab a lofty, industrial-style old piano factory for the venue, a perfect match for the event, and with excellent infrastructure. Kudos to them!

From the talks I attended, I think I was most impressed by the nodebox folks, one of the rare moments of interdisciplinary innovation (albeit with prior art) that makes you feel very humble. I’d actually hang my walls with stuff like that.

Some random impressions:

(Lukas Tvrdy with Krita hairy brush stroke example – Jakub Steiner on his 100%-FLOSS-based icon workflow – Peter & Franz of Scribus fame demoing fancy mesh gradients – Eric Schrijver’s great ranting on design & “pixels are vectors, too” – ReJon’s Inkscape talk via Inkscape – the CloutComputing panel)

Was in Gelsenkirchen again this year, for what seems to be the rock festival hitting the sweet spot between band relevance (i.e. not entirely arcane or unknown), and size (i.e. you don’t need to walk one hour from your tent to the stages). What should I say – it was a blast. Rain stopped on Thursday, and sun was shining the whole weekend. My favourites this time: Bloodbath, Accept, Kreator, Nevermore, Orphaned Lands, Rage + orchestra. Honorable mention: Mambo Kurt, for doing a really funny gig on a home organ + C64, in front of a very demanding audience.

Impressions:

(dawn in the amphitheater – Kreator’s Miland „Mille“ Petrozza – 3 behind the mixing desk – shower, festival-style – part of the venue – Orphaned Land from Israel, surprisingly good – stunts in mid-air – Rage + strings)

This is in response to Martin’s posting about OOo product development, and my candidature for the OOo Community Council in particular:

The only candidate now for the non-code contributing projects for the next round of council elections will be Thorsten Behrens. he’s a well known great supporter of the hacker driven “Product Development”, from my perspective a good representative of the code contributors. But not for the non-code contributing PD projects of OOo as the charter of the CC states. It’s difficult to do a “no” vote against the only candidate for this seat, especially if the candidate does good things for the project and I consider him as a good friend of mine. But we need a general review of the PD part of the project, and therefore I want to see a person representing the classical school of product development and call for a no-vote and call for new candidates.

I wonder, does anyone really think someone capable of working on the strategic marketing plan will have more time doing so when being a member of the CC? ;-)

More seriously, and as I wrote in my introduction mail, I firmly believe that CC’s central function is arbitration – i.e. talking to people, convincing folks, finding compromise. It’s decidedly not the place to vote people into, because you need specific jobs A, B, or C done – that’s what the different projects are for, for the example at hand the marketing project. My selling point is surely not decades of marketing experience, but rather my ties into the wider community, for which I know very many people in person, and would call quite a few of them friends.

I’ve done QA work on CWS & sponsoring a tinderbox, I know a fair bit about the economies & strategies in FLOSS communities – and I do my legwork in advertising OOo, e.g. at CeBIT. As stated in my introduction mail, I’m explicitely running for this seat representing projects outside of raw code contribution in the council – in fact, I’ve always frowned upon the notion of being purely “code contributor”, “qa engineer”, or “marketer” – core to my motivation is my love for this project, that is OOo, and everything that’s necessary to further its success. Across all camps.

And finally, I find the act of lobbying for a “no” vote against a CC candidate quite without precedent, even more so since there was not even a single question, neither public nor privately, about my intentions or motivations, let alone a discussion. I can only ask everyone involved to check the facts objectively, and keep up with the tradition of having the CC be a place of collaboration & compromise, instead of exclusionism & camp mentality.

Note: I’d prefer to have the actual discussion on the dev list, rather than via blog. Please follow up there.

Introduction

Beside the problem of general polygon clipping, which has been thoroughly researched in the past twenty or so years, it is sometimes the case that only rectangular areas have to be clipped against each other. Two very prominent examples are the calculation of redraw areas in a GUI application – widget and application content areas are, because of performance and simplicity, often represented as rectangles, and quick, approximative spatial indexing, e.g. for GIS data.

It turns out that constraining clip calculations to axis-aligned bounding boxes (aka AABB) allows for noticeable simplifications in the algorithm – regarding code and time complexity, as well as numerical stability.

The algorithm

For clipping a set of AABBs against each other, the common sweep line algorithm is employed, in this case sweeping a vertical line from the leftmost box over to the rightmost. Therefore, each box B_i contributes two sweep line events E_l_i and E_r_i to the algorithm, one for its left and one for its right edge. After sorting those events in ascending order, a line is swept horizontally across all boxes:

Each time a box’s left edge is hit by the sweep line, two horizontal edges H_u_i and H_l_i are inserted into a list of currently-active horizontal segments. This list is kept sorted with ascending y values, and every vertical edge event is checked against intersection with all active horizontal edge segments.

At the core of every polygon clipping algorithm, mutual edge intersections need to be computed. Fortunately, as rectangles are convex polygons and free of self-intersections, a lot of the more complicated preprocessing steps involved for generic polygon clipping can be avoided. One of the most notable aspects is the fact that this algorithm is numericable stable also when performing intersection calculations with finite-precision floating-point math, because no precision-reducing operations need to be performed (this is in contrast to general polygon clipping, which gets notoriously instable under floating-point math, since the (sometimes repeated) calculation of intersection points introduces round-off errors – obvious for oblique edges).

For intersection calculations of AABBs, no calculations whatsoever are necessary on the coordinate elements, the resulting intersection vertices are just element-wise merged input coordinates.

Basically, four cases of edge intersections can be distinguished:

Note that, since the sweep line is vertical, it is always a right or a left edge of a rectangle, that needs to be intersected with either an upper or a lower edge. Degenerate cases, such as rectangles with zero height or width, or two exactly identical rectangles, are handled in a defined, but consistent way without affecting the general algorithm.

For each sweep line event (being either a left or a right rectangle edge), all currently active horizontal edge segments are processed, starting with the one with the smallest y value. Each left edge sweep line event creates a polygon, into which intersecting horizontal edges are merged. Therefore, when processing the horizontal edge segments, the sweep line will carry a current polygon P_c. The sweep line’s current polygon may change, naturally, as it intersects horizontal edges, taking up the associated polygon of the intersecting edge and in turn passing the current polygon to that horizontal edge:

For the sake of clarity, I have omitted symmetric cases here, which you get when polygon orientation is reversed (denoting reversed inside and outside areas). Those follow rather straight-forward. A version of the algorithm that handles those cases, and is thus able to perform the usual boolean operations on AABB-defined polygons, is implemented in c++, and used in OpenOffice.org’s graphic subsystem. A standalone version can be found here.

I'm going to FOSDEM, the Free and Open Source Software Developers' European Meeting

I’m actually even presenting!

Just uploaded ooo-build OOo 3.2 rc2 mac builds here.

Just a brief notice, took caff+tls, pulled changes up to latest debian version from svn, and hacked it into working state: script is here, suitable .caffrc is there.

Both power consumption and imminent cease of Debian security updates for the sparc32 platform (I was running a trusty SparcStation 10 still) made me look for a worthy replacement. Some requirements: three or more ethernet ports, very low power consumption, must run Linux (platform with all-open drivers gives extra points), and a RS232/RS485 jack for the solar power inverter read-outs.

I settled for GlobalScale’s openRD-client box, an ARM kirkwood-based design, which typically takes about 6 watts, has ample interface connectors, including two gigabit ethernet ports (yeah, I wanted three. well, turns out that brings you into a completely different price range – so I’ll simply use an USB-based NIC for my 3rd). Hardware arrived some 6 weeks ago, but there was no pressing need yet.

Well, while staying at the GSoC mentor summit, things suddenly went south, the SparcStation blew its scsi controller (and the attached disk’s interface as well), I lost ~3 days worth of email, and I had to hurry things a bit.

Here’s what I did to have stock Debian stable running on the box:

  • I upgraded u-boot to the latest version (it’s kind of the bios on those arm machines, first thing that gets run after a reset), as I needed support for booting off of sd cards:
    • grab latest image from the list at http://code.google.com/p/openrd/downloads/list (http://openrd.googlecode.com/files/openrd_uboot.zip currently)
    • put on toplevel dir of a random usb stick, insert into openrd-client, reset, then at the u-boot prompt:
      usbstart
      fatload usb 0:1 0x0800000 uboot.bin / ext2load usb 0:1 0x0800000 uboot.bin
      nand erase 0x0 0xa0000
      nand write 0x0800000 0x0 0xa0000
      

      If that turns out to be succesful, issue a reset.
      After that, you should see this:

       ** MARVELL BOARD: OpenRD-Client LE 
      
      U-Boot 1.1.4 (Oct 27 2009 - 21:57:24) Marvell version: 3.4.19
      
    • Ready to actually install now. I did it as outlined here
    • Most important difference: we’re not setting up a Sheevaplug (which is also quite nice), so in the above howto, issue a
      setenv arcNumber 2361
      

      instead. Memory setup, I/O register etc. are all hard-coded on arm, so picking the correct machine magic number is paramount for having a working setup (and not accidentally frying your hardware, because some I/O pins are mapped differently. You have been warned).

    • I then decided to build a custom kernel, as the existing lenny image was not supporting all the openrd-client features yet:
      • cloned repo
      • applied this patch on top of it
      • stripped down config (you want to select OpenRD client from the ARM Kirkwood section), make sure mmc drivers are built-in if you want to boot w/o initrd
      • make uImage doesn’t even take that long to build, on the actual machine (1.2GHz, FWIW)
    • You can then flash your kernel image to the internal rom, like this (assuming the image is less than 4MB in size):
      mmcinit
      ext2load mmc 0:1 0x00800000 uImage
      nand erase clean 0x00100000 0x00400000
      nand write 0x00800000 0x00100000 0x00400000
      

      This assumes the kernel image resides on the second partition of your sd card. Since u-boot’s mmc support is still a bit flaky, and sometimes fails to properly initialize the sd card after a reset, booting from internal flash comes in extremely handy – boots kernel from flash, kernel then sets up mmc nicely & grabs everything else from there). Which ends up with the following tweaked u-boot boot setup for me:

      setenv bootargs 'console=ttyS0,115200 root=/dev/mmcblk0p2 rw mtdparts=orion_nand:0x400000@0x100000(uImage)'
      setenv bootcmd 'nand read 0x800000 0x100000 0x400000; bootm 0x800000'
      saveenv
      

      (my root fs lives on the 2nd sd card partition)

    Really happy with it, now that it’s working:

Decided to put 11.2 on some spare HD bits of my MacBook last week. Here’s the log of things I did:

  • Grabbed newest refit, install docs here.
  • Wanted to install via the network install image (around 150MB) from a usb thumb drive, it’s such a hassle (and a waste) to go & and burn CDs for that. So I went for latest grub2 to make EFI/rEFIt boot from usb. More docs about grub2 efit booting:
    • usb boot on mac: german blog
    • grub background info
    • my grub2 setup (on a x86_64 system):
      • ./configure --with-platform=efi --enable-efiemu --enable-mm-debug --enable-grub-emu --enable-grub-fstest --enable-grub-emu-usb --prefix=place_you_have_write_permissions --target=i386
      • then make; make install
      • cd into place_you_have_write_permissions
      • cd into lib/i386-grub/i386-efi there
      • run ../../../bin/i386-grub-mkimage -v -d . -o grub.efi part_gpt hfsplus fat ext2 normal sh chain boot fixvideo appleldr loadbios loopback configfile fs_file fshelp halt handler help iso9660 linux ls minicmd probe reboot search video scsi msdospart bitmap blocklist fs_uuid kernel memrw part_msdos parttool ext2 extcmd hexdump minicmd read sfs xnu xnu_uuid 2>&1 | tail
        this should result in something like "grub-mkimage: info: writing 446 bytes of a fixup block starting at 0xa000"
        Note that in theory, you could just use ../../../bin/i386-grub-mkimage -d . -o grub.efi *.mod, only that this was simply hanging during boot for me – and I didn’t have the patience to bin-search those upteen modules to find the incriminating one. Thus the explicit list, which worked for me.
  • Prepare the usb stick:
    • you should be fine with using both ext2 or fat partitions on it
    • copy your openSUSE-11.2-NET-x86_64.iso into the toplevel dir of the stick
    • from place_you_have_write_permissions/lib/i386-grub/i386-efi, copy grub.efi and *.lst to a efi/grub/ dir on the stick (that’s where refit looks for bootable stuff)
    • put this into efi/grub/grub.cfg on the stick:
      menuentry "openSUSE install" {
       fix_video
       fakebios
       root (hd0,1)
       loopback loop /openSUSE-11.2-NET-x86_64.iso
       linux (loop)/boot/x86_64/loader/linux initrd=initrd splash=silent showopts install=file://openSUSE-11.2-NET-x86_64.iso?device=sdb*
       initrd (loop)/boot/x86_64/loader/initrd
      }
      
  • Put stick into macbook, select usb medium in refit boot screen, boot install image. For me, the installer was falling back to manual setup, so grab the next mirror to you from http://mirrors.opensuse.org/list/11.2.html, determine IP address for the host (“host <mirror_name>”), enter that into the field you get when selecting “http method” for the installation image. Path on that server usually is something like /pub/opensuse/distribution/11.2/repo/oss/ .
  • Proceed with normal installation. Easy as pie.
  • More general info for openSUSE on macbook:

Misc stuff I did:

  • most important first thing to do, to prevent 2nd degree burns on knees: echo -n 2400 > /sys/devices/platform/applesmc.768/fan1_min (you want to put that line into your boot.local script or something. and it’s nothing Linux is at fault, this is entirely broken on Apple’s side of things)
  • get headphones jack to actually output music: run alsamixer in terminal, press F6 and select “HDA intel”. Press F5 to show all mixer controls, un-mute “Speaker 1″.
  • for the iSight built-in camera: install isight-firmware-tools, mount your (hopefully still-existent) OSX partition (something like mount -t hfsplus /dev/sda2 /mnt, then extract the firmware via ift-extract -a /mnt/System/Library/Extensions/IOUSBFamily.kext/Contents/PlugIns/AppleUSBVideoSupport.kext/Contents/MacOS/AppleUSBVideoSupport. Reboot, and voila, camera is working.
  • everything else just worked out of the box.