xhtmlrenderer: DOCTYPE

Wenn man mit dem xhtmlrenderer ein PDF erzeugen möchte sollte man in der Quell-XHTML-Datei die DOCTYPE Definition weglassen. Bleibt diese nämlich drin wird die parse() Methode des DocumentBuilder versuchen die DTD zu laden. Und wenn das nicht möglich ist (zum Beispiel, weil keine Netzwerkverbindung aufgebaut werden kann/darf) bleibt das Programm an dieser Stelle einfach (und zunächst ohne Fehler) stehen.

File inputFile   = new File( "input.xhtml" );
String baseUrl = inputFile.toURI().toURL().toString().replace( inputFileName, "");

DocumentBuilder dBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document doc = dBuilder.parse( inputFile );

ITextRenderer renderer = new ITextRenderer();
renderer.setDocument( doc, baseUrl );
renderer.layout();

FileOutputStream pdfOutputStream = new FileOutputStream(outputFileName);

renderer.createPDF( pdfOutputStream );

pdfOutputStream.close();

xhtmlrenderer: PDFs mit Bookmarks / Inhaltsverzeichnis erstellen

Dass man mit dem xhtmlrenderer (The Flying Saucer Project) aus xhtml Dateien PDFs erzeugen kann ist weitläufig bekannt. Dass man über spezielle XML-Elemente zudem Lesezeichen (Bookmarks) im PDF erzeugen kann, weniger. Man kann sogar die <bookmark />-Tags verschachteln um so eine Hierarchie (wie zum Beispiel ein Inhaltsverzeichnis) abzubilden. Das Hauptelement <bookmarks> muss dabei im <head> platziert werden.

<html>
    <head>
        <bookmarks>
            <bookmark name="A bookmark" href="#bm" />
            <bookmark name="A bookmark 2" href="#bm2">
                <bookmark name="A bookmark 3" href="#bm3" />
            </bookmark>
            <bookmark name="A bookmark invalid" href="#bm99" />
        </bookmarks>
    </head>
    <body>
        <a name="bm1">Jumpmark 1</a>
        <a name="bm2">Jumpmark 2</a>
        <a name="bm3">Jumpmark 3</a>
    </body>
</html>

Im PDF sieht es dann so aus:

Blue spice for MediaWiki

Blue spice for Media Wiki

Jeder kennt Wikis. Jeder kennt zumindest die Wikipedia. Die Software hinter Wikipedia ist das inzwischen weit verbreitete MediaWiki. Und für genau diese Plattform gibt es nun die umfangreiche Erweiterung „Blue spice for MediaWiki“.

„Blue spice“ bietet Verbesserungen:

  • Moderne Oberfläche: Blue spice Skin
  • Hochentwickelte Bearbeitungswerkzeuge: RichText-Editor, Link-, Kategorie- und Bildassistenten
  • Schneller Zugriff auf Informationen: Artikel-Statusbar, Widgets, Persönliche Navigation
  • u.v.m.

Ihr könnt es euch hier herunterladen: http://sourceforge.net/projects/bluespice/

Über Feedback freuen wir uns sehr! Zögert bitte auch nicht Bugs zu melden. Ihr könnt sie direkt in unseren BugTracker eintragen.

Viel Spaß mit Blue spice for MediaWiki!

RaphaelJS: Text aus einem print()-Set rotieren


Wer schonmal mit RaphaelJS gearbeitet hat, dem ist sicher aufgefallen, dass beim Rotieren eines (normalen) Text-Objekts unschöne Effekte, wie zum Beispiel verschobene Buchstaben auftreten können.
Beispiel:

var Rdemo1 = Raphael( 'raphael-js-textrotate-demo1', 500, 200 );
Rdemo1.text( 250, 100, 'Hallo Welt! Medienwerkstadt GmbH' )
          .attr( { font: '25px Helvetica, Arial' } )
          .rotate( -15 );

Abhilfe schafft der Weg über die print()-Methode des Raphael-Objekts. Der Nachteil dabei ist, dass eine Cufon Schriftart erzeugt und geladen werden muss. Außerdem kann es bei viel Text zu Leistungseinbußen des Browsers kommen.
Das Problem beim Rotieren eines mit der print() Methode erzeugten Textes ist, dass es sich bei ihrem Rückgabewert leider nicht um ein Objekt handelt, sondern um ein set von Objekten (Jeder Buschstabe ist ein eigenes). Würde man auf diesem Set die rotate() Methode ausführen ohne den Rotationsmittelpunkt anzugeben würde jeder Buchstabe um sein jeweiliges Zentrum rotiert werden und nicht der Text als gesamtes. Daher muss man zunächst den gemeinsamen Rotationsmittelpunkt des sets finden.
Beispiel:

//Wurde vorher mit Cufon erzeugt
Raphael.registerFont( {
     "w":162,
     "face": {
     "font-family":"MyFont",
     "font-weight":500,
     //[...]
});

r   = new Raphael( "raphael-js-textrotate-demo2", 500, 200 );

//liefert ein set-Objekt zurück, welches die Pfade der Buchstaben enthält.
txt = r.print( 100, 100, "Hallo Welt! Medienwerkstatt GmbH", r.getFont( "MyFont" ), 25 );

txtXLeft = txt.getBBox().x;
txtYTop  = txt.getBBox().y;

txtXRight  = txt.getBBox().x + txt.getBBox().width;
txtYBottom = txt.getBBox().y + txt.getBBox().height;

txtXMiddle = txt.getBBox().x + txt.getBBox().width / 2;
txtYMiddle = txt.getBBox().y + txt.getBBox().height / 2;

txt.rotate(35, txtXMiddle, txtYMiddle); // 35 Grad um den Mittelpunkt
txt.rotate(20, txtXLeft,   txtYTop); // 20 Grad um die linke obere Ecke
txt.rotate(95, txtXRight,  txtYMiddle ); // 95 Grad um die rechte Seite (mittig in der Höhe)
txt.rotate(60, txtXLeft,   txtYBottom ); // 60 Grad um die linke untere Ecke

Natürlich lassen sich beliebige Punkte innerhalb, sowie außerhalb des BBox definieren. Einfach die width und height Eigenschaften mit Werten zwischen 0 und 1 (innerhalb der BBox) oder größer als 1 (außerhalb der BBox) multiplizieren.


Weblinks: