Ludum Dare #01 – 8.5 hours in

So, as I’m getting ready to have some lunch, let’s reflect on what we have at the moment:

- map rendering works perfectly, I implemented a partial view of a map, so it will scroll along when the player moves.
- sprited animation, one slight bug in the sprite while moving, nothing to worry about at this time.
- collision detection, I only need to fix an offset on the collision map. As it is now, the collision map is offset by about half a map. But the upside is: it works.

Compared to last time, not taking art into account, HAH “art” he says, I’m about as far as I got last time in Ludum engine-wise.

On the TODO list until the next blog update:

- fix that collision bug
- movement to other maps, not sure how to do that just yet, but I will need to get that working before moving on
- generic display of text
- decide on genre. RPG or Action/Adventure.

That’s about what I’ll do until the next update. Now, until I wait for lunch to be served (yes served :awesomeface:) I’m going to clean my code a bit. It’s beginning to reek.

Ludum Dare 23 #00 – 3.5 hrs to go

Here we go again: Ludum Dare. Trying to complete a game within 48 hours of the theme announcement. I entered the previous contest (LD 22) and I finished a game. It’s not a triple A game, but I finished it nonetheless. I told myself this time is going to be different. This time I’ll be prepared.

That was 4 months ago. And now on the verge of the 10 year anniversary edition of Ludum I find myself more prepared, but not to say I’ll have a game that outshines my previous one by a multitude of a gazillion. I prepared a bit, but not as much as I wanted to. But I tried to prepare very efficiently. I looked at some of the parts I had some issues with during last Ludum:

- map creation
- map rendering
- music
- fonts

I guess I’ll just run into other issues while I avoid the above. But those issues will be more game-related annd less related to slick2D.

My set-up:

Code : Java 6 

- IntelliJ IDEA – somewhat fell in love with this IDE during the past month. Try it if you can.
- Slick2D – same as last time, solid choice
- VCS – svn @ google code

“Art”

- Paint.NET – seems like a solid choice once more
- might look into http://danikgames.com/stuff/pyxeledit/ if the need arises

Sound FX / Music

- SFXR, gooooood stuff
- otomata, cool output (thanks claus)
-audacity, IF I need it

Varia

- Chronolapse for those sexy timelapses
- A block of paper and a pen for those sexy brainstorm sessions
- Spotify, unbearable without
- Beer (got it covered)

 

So, that’s about the gist of it. Good luck to everyone and have fun.

I wrote a Google+ Library

Because of a project, I have been trying out several Google+ Libraries. The following libraries were the ones I tried:

The first being made by Google and the second by… Not Google.

I cannot say I was satisfied with any of those two. The first one required what seemed like a thousand dependencies while the second one refused to work due to a JSON exception that seemed to have no documentation on-line. So, I decided I’d do myself a favor and make something that works the way I want it to work: with as few dependencies as possible and very easy to use.

I used three dependencies:

I picked these three (well, two actually, commons-codec was required by scribe) because they are easy in use and do not require other dependencies.

And this is the result: My very own Google+ library

I designed it with a few guidelines in mind:

 1. Easy to get it working

GooglePlus gPlus = new GooglePlus(apiKey, secret);
 Desktop.getDesktop().browse(new URI(gPlus.getAuthorizationUrl()));
 gPlus.verifyUser(new Scanner(System.in).next()); 

Three lines and we’re connected to the G+ api.

 2. Cope with calls that weren’t predefined

 private static final String apiUrl = "https://www.googleapis.com/plus/v1/";

public Response getResponse(String apiCall) {
 OAuthRequest request = new OAuthRequest(Verb.GET, apiUrl + apiCall);
 oAuthService.signRequest(accessToken, request);
 Response response = request.send();
 return response;
}

The library provides predefined calls to the api, such as “findUser(String query)”. Normally the inner workings would be shielded from external use, but if you need to make your own calls to G+, you can call the above method in net.mymilkedeek.social.gplus.core.Manager with your custom api call.

This will come in handy if Google updates its G+ api and this library doesn’t get updated. No need to wait, just put in the new api calls and process the Json response.

3. Easy to expand

This is awesomely achieved. To add the functionality for Comments I needed to:

  1. Create a Comment class (with fields)
  2. Create CommentManager (extends Manager<Comment>)
  3. Create CommentJsonParser (implement JsonParser<Comment>)
  4. Parse the Json to the Comment object
  5. Write one line functions in the Manager

The to-do’s

  • Add optional parameters.
  • Write more comments.
  • Better exception handling.

Download it, browse the source code, don’t download it. Do with it as you please. As long as you report bugs/notify me of things that could have been better.

  Some Example

import java.awt.Desktop;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.List;
import java.util.Scanner;

import net.mymilkedeek.social.gplus.GooglePlus;
import net.mymilkedeek.social.gplus.activity.Activity;
import net.mymilkedeek.social.gplus.activity.ActivityManager;
import net.mymilkedeek.social.gplus.comment.Comment;
import net.mymilkedeek.social.gplus.comment.CommentManager;
import net.mymilkedeek.social.gplus.person.Person;
import net.mymilkedeek.social.gplus.person.PersonManager;

import org.json.JSONException;

public class Main {

private static final String apiKey = &quot;XXX&quot;;
private static final String secret = &quot;XXX&quot;;

 public static void main(String[] args) throws JSONException, IOException,
 URISyntaxException {
 GooglePlus gPlus = new GooglePlus(apiKey, secret);
 Desktop.getDesktop().browse(new URI(gPlus.getAuthorizationUrl()));
 gPlus.verifyUser(new Scanner(System.in).next());

 ActivityManager activityManager = gPlus.getActivityManager();
 List&lt;Activity&gt; activities = activityManager
.getActivitiesFromUser(&quot;111486046861792612952&quot;); // that's me!

 for (Activity a : activities) {
 System.out.println(a.getId());
 PersonManager personManager = gPlus.getPersonManager();
 List&lt;Person&gt; persons = personManager.findByActivityId(a.getId(),
 PersonManager.PLUSONERS);

 for (Person p : persons) {
 System.out.println(p);
 }

 persons = personManager.findByActivityId(a.getId(),
 PersonManager.RESHARERS);

 for (Person p : persons) {
 System.out.println(p);
 }
 }
 }
}

This piece of code gets all of my activities (or posts) and then gets all the users who +1′d my post or shared it. Easy peasy.

Spring Social Facebook Application on the Desktop

So, you want to access Facebook from your application from a non-web, non-mobile environment? I looked around for a bit and found Spring Social. There was “facebook-java-api”, but I didn’t get very far using it. Spring Social is exactly what it says on the tin: a module in Spring that allows you to easily access the (more popular) social networks. Documentation on how to use it in a non-web environment is pretty scarce, so I decided to throw my working Hello World online.

Things you need before we start:

There also maven support:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 <modelVersion>4.0.0</modelVersion>
<groupId>net.mymilkedeek</groupId>
 <artifactId>social</artifactId>
 <version>0.0.1-SNAPSHOT</version>
<name>MME Social</name>
<dependencies>
 <dependency>
 <groupId>org.springframework.social</groupId>
 <artifactId>spring-social-core</artifactId>
 <version>1.0.1.RELEASE</version>
 </dependency>
 <dependency>
 <groupId>org.springframework.social</groupId>
 <artifactId>spring-social-facebook</artifactId>
 <version>1.0.1.RELEASE</version>
 </dependency>
 <dependency>
 <groupId>org.springframework</groupId>
 <artifactId>spring-core</artifactId>
 <version>3.1.0.RELEASE</version>
 </dependency>
 </dependencies></project>

As you can see from the pom.xml: each social network is going to require an added dependency. For this example we’re going to stick with Facebook.

Now, onto the code:

FacebookConnectionFactory connectionFactory = new FacebookConnectionFactory(apiKey, secretKey);
OAuth2Operations oauthOperations = connectionFactory.getOAuthOperations();
 OAuth2Parameters params = new OAuth2Parameters();
 params.setRedirectUri("https://www.facebook.com/dialog/oauth?client_id=" + apiKey + "&amp;redirect_uri=" + redirectUri);
 params.setScope("user_about_me,user_birthday,user_likes,user_status,publish_stream");
String authorizeUrl = oauthOperations.buildAuthorizeUrl( GrantType.AUTHORIZATION_CODE, params);

In this first bit, we are configuring our application. We set our api and secret key and we add a redirect URI, which is provided to us by Facebook. We also set the scope of our program. The scope are the permissions our application will have and what the user will see when he has to allow our application access to his Facebook data.

As you can see, Facebook uses OAuth2. For more information on OAuth, check out various tutorials and articles online.

java.awt.Desktop desktop = java.awt.Desktop.getDesktop();
 if (!desktop.isSupported(java.awt.Desktop.Action.BROWSE)) {
 System.out.println("No browsing allowed...");
 System.exit(1);
 }

 try {
 java.net.URI uri = new java.net.URI(authorizeUrl);
 desktop.browse(uri);
 } catch (Exception e) {
 System.err.println(e.getMessage());
}

Because we have a desktop application, we have to either start a browser and point it to the authorization url or implement a browser into our application. The latter has the benefit of not relying on the user to provide you with the Token, but on the returned url. But, that’s beyond the scope of this application, so we’re just going to have the user copy paste the url into our console.

System.out.println("Token : ");
 Scanner scanner = new Scanner(System.in);
 String input = scanner.next();
 input = input.replace("https://www.facebook.com/connect/login_success.html?code=", "");
System.out.println(input);

If I have to explain this then you’re looking at the wrong tutorial.

AccessGrant accessGrant = oauthOperations.exchangeForAccess(input, redirectUri, null);
Connection<Facebook> connection = connectionFactory.createConnection(accessGrant);
Facebook facebook = connection.getApi();

This is the code of the Facebook application.  We request an Access Token from Facebook and use that to create a Facebook object. The Facebook object will allow you to utilize Facebook’s functions and data. And it will allow us to write “Hello World” to our wall by writing:

facebook.feedOperations().updateStatus("Hello World");

And that’s it. I wanted to post this because I could not find any resource that wasn’t out of date or incorrect.

Things to note:

  • Do not rely on your users to copy paste the authorization tokens. Implement a small browser into your application. This will make it that much more idiot-proof.
  • The Facebook redirect url is “https://www.facebook.com/connect/login_success.html”

Source Code

Now for the entire source code:

HelloWorld.java

package net.mymilkedeek.social;

import java.util.Scanner;

import org.springframework.social.connect.Connection;
import org.springframework.social.facebook.api.Facebook;
import org.springframework.social.facebook.connect.FacebookConnectionFactory;
import org.springframework.social.oauth2.AccessGrant;
import org.springframework.social.oauth2.GrantType;
import org.springframework.social.oauth2.OAuth2Operations;
import org.springframework.social.oauth2.OAuth2Parameters;

public class HelloWorld {
private static final String apiKey = "xxx";
private static final String secretKey = "xxx";
 private static final String redirectUri = "https://www.facebook.com/connect/login_success.html";

 public static void main(String[] args) {
 FacebookConnectionFactory connectionFactory = new FacebookConnectionFactory(apiKey, secretKey);
 OAuth2Operations oauthOperations = connectionFactory.getOAuthOperations();
 OAuth2Parameters params = new OAuth2Parameters();
 params.setRedirectUri("https://www.facebook.com/dialog/oauth?client_id=" + apiKey + "&amp;redirect_uri=" + redirectUri);
 params.setScope("user_about_me,user_birthday,user_likes,user_status,publish_stream");
 String authorizeUrl = oauthOperations.buildAuthorizeUrl(GrantType.AUTHORIZATION_CODE, params);

 java.awt.Desktop desktop = java.awt.Desktop.getDesktop();
 if (!desktop.isSupported(java.awt.Desktop.Action.BROWSE)) {
 System.out.println("No browsing allowed...");
 System.exit(1);
 }

 try {
 java.net.URI uri = new java.net.URI(authorizeUrl);
 desktop.browse(uri);
 } catch (Exception e) {
 System.err.println(e.getMessage());
 }

 System.out.println("Token : ");
 Scanner scanner = new Scanner(System.in);
 String input = scanner.next();
 input = input.replace("https://www.facebook.com/connect/login_success.html?code=", "");
 System.out.println(input);

 AccessGrant accessGrant = oauthOperations.exchangeForAccess(input, redirectUri, null);
 Connection<Facebook> connection = connectionFactory.createConnection(accessGrant);
 Facebook facebook = connection.getApi();

 facebook.feedOperations().updateStatus("Hello World");
 }
}

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 <modelVersion>4.0.0</modelVersion>
<groupId>net.mymilkedeek</groupId>
 <artifactId>social</artifactId>
 <version>0.0.1-SNAPSHOT</version>
<name>MME Social</name>
 <dependencies>
 <dependency>
 <groupId>org.springframework.social</groupId>
 <artifactId>spring-social-core</artifactId>
 <version>1.0.1.RELEASE</version>
 </dependency>
 <dependency>
 <groupId>org.springframework.social</groupId>
 <artifactId>spring-social-facebook</artifactId>
 <version>1.0.1.RELEASE</version>
 </dependency>
 <dependency>
 <groupId>org.springframework</groupId>
 <artifactId>spring-core</artifactId>
 <version>3.1.0.RELEASE</version>
 </dependency>
 </dependencies>
</project>

Comments, suggestion and/or corrections are always welcome.

iText on the JVM

Java Virtual Machine Languages

Since a few years Java got some company on the JVM. Languages like Jython, JRuby and Groovy have emerged and claimed their place in the spotlight on the JVM. The exciting advantage of this is that it enables other paradigms to use your Java jars. It’s almost no hassle to use a jar in e.g. Groovy. This allows a lot of interesting possibilities. One of the biggest disadvantages is that some ports of non-JVM languages turn out to be a bit slower than the original: I’ve found Jython to be a lot slower than Python. Nevertheless, I’m still in love with Python and a Java implementation is still awesome.

If you want to learn more about the Java Virtual Machine and its languages, feel free to continue reading on the respective wikipedia pages here and here.

Eclipse and JVM Languages

Integrating these languages into Eclipse, my IDE of choice, is a smoother process than expected. I chose to integrate the following languages:

Most languages had a plugin in the Eclipse Marketplace (Jython, Groovy, Clojure) and the other had very informative websites on how to install the plugins (JRuby, Scala). I also chose not to download modified Eclipse versions. Most installs went very smooth. A few clicks, a restart and I was off to coding in a new language.

There was only one conflict. It seems that JRuby and Jython can not coexist in the same Eclipse. I had to install JRuby in a seperate Eclipse instance for it to work. In the end I was able to install 4 plugins in the same Eclipse instance, which is amazing.

There’s one odd thing about those 4 plugins though: the Scala plugin somehow seems to reference a JRuby file or two and causes an error every time I start Eclipse. Eclipse doesn’t crash or anything, but it’s annoying. That same Scala plugin somehow turned the background color of the editor to black for everything Jython.

There’s also a highly noticeable slowdown of Eclipse. I haven’t pinpointed the exact reason, but it happened after installing either Scala or Clojure.

So, in conclusion about multiple language support in Eclipse: try to keep the amount of language plugins as low as possible per instance to keep performance up and to avoid any conflicts between the plugins.

Interoperability

The main purpose of this article is to find the answer to the question: “How easy is it to use a jar in a non-Java project?” As it turns out: it’s very easy. For most languages it was only a matter of including the jar to the build path.

iText 5.1.3

iText is most likely the best pdf library in the Java ecosystem and it’s being used by a lot of companies to create pdf’s on the fly. I used iText to make it clear that, unless you have some odd reason not to use Java jars in your project, iText is not only the best choice to create pdf’s in Java, but for the JVM as a whole.

Java

In this post I’ll repeat the same Hello World example taken from the book “iText in Action” in each language to show how easy it is to use iText. This is the original source in Java:

/*
 * This class is part of the book "iText in Action - 2nd Edition"
 * written by Bruno Lowagie (ISBN: 9781935182610)
* For more info, go to: http://itextpdf.com/examples/
 * This example only works with the AGPL version of iText.
 */

package part1.chapter01;

import java.io.FileOutputStream;
import java.io.IOException;

import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.pdf.PdfWriter;

/**
 * First iText example: Hello World.
 */
public class HelloWorld {

 /** Path to the resulting PDF file. */
 public static final String RESULT
 = "results/part1/chapter01/hello.pdf";

 /**
 * Creates a PDF file: hello.pdf
 * @param args no arguments needed
 */
 public static void main(String[] args)
 throws DocumentException, IOException {
 new HelloWorld().createPdf(RESULT);
 }

 /**
 * Creates a PDF document.
 * @param filename the path to the new PDF document
 * @throws DocumentException
 * @throws IOException
 */
 public void createPdf(String filename)
 throws DocumentException, IOException {
 // step 1
 Document document = new Document();
 // step 2
 PdfWriter.getInstance(document, new FileOutputStream(filename));
 // step 3
 document.open();
 // step 4
 document.add(new Paragraph("Hello World!"));
 // step 5
 document.close();
 }
}

Now, onto porting it to other languages!

Jython

Jython is the Java implementation of Python (really clever name guys) and it was the first plugin I installed. That was an easy process thanks to the Eclipse Marketplace. Importing iText is also very easy:

Project Properties > PyDev PYTHONPATH > External Libraries > Add zip/jar/egg  and navigate to your jar.

Hello World example:

'''
Created on 28-dec.-2011
Creating a simple Hello World pdf in Jython using iText 5.1.3
@author: iText
'''
from com.itextpdf.text import Document
from com.itextpdf.text import Paragraph
from com.itextpdf.text.pdf import PdfWriter
from java.io import FileOutputStream

# step 1
document = Document()
print "Document Created"

# step 2
PdfWriter.getInstance(document, FileOutputStream("document.pdf"))
print "PdfWriter Created"

# step 3
document.open()
print "Document Opened"

# step 4
document.add(Paragraph("Hello Jython!"))
print "Content Added"

# step 5
document.close()
print "Document Closed"

That went relatively easy, didn’t it?

Next up,

Groovy

I followed some Groovy talks during Devoxx 2011 and I was impressed by the language, but I haven’t been able to test it out, up until now. As with Jython, it was pretty easy to install and to import iText into a project. It’s actually the same process as you would import a jar into a Java project. Assuming that you’re able to do that without instructions, so here’s the Hello World code for Groovy:

/*
 * Created on 28-dec.-2011
 * Creating a simple Hello World pdf in Groovy using iText 5.1.3
 * @author: iText
 */
import com.itextpdf.text.Document
import com.itextpdf.text.Paragraph
import com.itextpdf.text.pdf.PdfWriter

// step 1
def document = new Document()
println("Document Created")

// step 2
PdfWriter.getInstance(document, new FileOutputStream("document.pdf"))
println("PdfWriter Created")

// step 3
document.open()
println("Document Opened")

// step 4
document.add(new Paragraph("Hello Groovy!"))
println("Content Added")

// step 5
document.close()
println("Document Closed")

As you can see, the code is straightforward and simple and it looks pretty much like Jython. I prefer Groovy over Jython because it’s much faster and actually feels like a JVM language and not like a port of another language. Still a lot of love for Python though.

Scala

I hadn’t heard of Scala until Devoxx 2011. The first talk I followed that year was a crash course into Scala. I wasn’t very impressed by the talk, but my colleague seemed to have some fun programming Scala, so I gave it a try. Installing the plugin wasn’t as easy as going to the Marketplace, instead I had to search the Scala website and find which link to use in the “Install new Software” function.

Importing iText is the same as in a Java project. This is the Scala Hello World example:

package com.itextpdf.scala

import com.itextpdf.text.Document
import com.itextpdf.text.pdf.PdfWriter
import java.io.FileOutputStream
import com.itextpdf.text.Paragraph

object ITextTest {
 def main(args: Array[String]): Unit = {
 val document = new Document()
 PdfWriter.getInstance(document, new FileOutputStream("document.pdf"))
 document.open()
 document.add(new Paragraph("Hello Scala!"))
 document.close()
 }
}

It works like a charm, but I’m still not convinced about Scala. It will probably never be one of my favorite languages.

(Clojure)

Seriously, what is up with those parenthesis? Clojure is most definitely the strangest of the new JVM languages, but according to an old proverb “unknown is unloved”.

Installing Clojure happens through the marketplace and importing the jar is as easy as it is in Java. So, without further ado, let’s take a look at the code:

(ns helloworld)

(defn makePdf []
 (def document (new com.itextpdf.text.Document))
 (println "Document Created")
 (com.itextpdf.text.pdf.PdfWriter/getInstance document, (new java.io.FileOutputStream "document.pdf"))
 (println "PdfWriter Created")
 (.open document)
 (println "Document Opened")
 (.add document (new com.itextpdf.text.Paragraph "Hello Clojure!"))
 (println "Content Added")
 (.close document)
 (println "Document Closed")
)

I told you it was strange. It took me several tries to get a working example and this is it. Pretty sure it’s not the best looking Clojure code around, but it somehow works.

JRuby

Having some minor experience with Ruby, I thought I’d have the most fun using JRuby. So, I set out to use a plugin for JRuby in Eclipse and found one. I followed a few simple Hello World example and they worked, but as soon as I tried to talk to the Java classes and jars, the magic disappeared. Looking a bit further I downloaded Aptana Studio 3. But, by default, Aptana Studio takes the ruby.exe declared on your path. I tried to change this to use jruby instead of ruby, but to no avail.

And that’s when I built this make-shift IDE:

MacGyver would be proud.

And it works!

Before we go over the Hello World example, it should be noted that the lack of IDE integration is probably my own fault. If anyone knows how to integrate JRuby, let me know. I’ll be more than happy to update this post with your corrections/suggestions.

Integrating Java into JRuby isn’t that hard. All it needs is the following line:

require 'java'

That line of code allows you to use all the standard Java classes. But we need more. We need to use iText in JRuby. The following will allow us to use iText classes in JRuby.

require 'itextpdf-5.1.3.jar'

Do note that I put the jar in the same folder as the Ruby file.

With all of that out of the way, let’s move on to the Hello World example:

 require 'java'
require 'itextpdf-5.1.3.jar'

document = com.itextpdf.text.Document.new
pdfWriter = com.itextpdf.text.pdf.PdfWriter.getInstance(document, java.io.FileOutputStream.new("document.pdf"))
document.open
document.add(com.itextpdf.text.Paragraph.new("Hello JRuby"))
document.close

And that code snippet produces the last of our Hello World PDFs.

And a more elaborate example

Hello World examples are nice and everything, but never very practical. For this section I took one language and I ported one random example from the iText in Action book. I picked Groovy as I love that language. The example is the NUp example. NUp scales the pages of a pdf to fit mulitple pages onto one page.

Ported to Groovy that gives us the following:

package com.itextpdf.groovy

import com.itextpdf.text.Document
import com.itextpdf.text.Rectangle
import com.itextpdf.text.pdf.PdfReader
import com.itextpdf.text.pdf.PdfWriter

class NUp {
 static main(args) {
 def nup = new NUp()
 nup.manipulatePdf("test.pdf", "result.pdf", 4)
 }

 def manipulatePdf(src, dest, pow) {
 def reader = new PdfReader(src)
 def pageSize = reader.getPageSize(1)

 def newSize = (pow % 2) == 0 ?
 new Rectangle(pageSize.getWidth(), pageSize.getHeight()) :
 new Rectangle(pageSize.getHeight(), pageSize.getWidth())

 def unitSize = new Rectangle(pageSize.getWidth(), pageSize.getHeight())
 for ( i in 0..pow) {
 unitSize = new Rectangle((float)unitSize.getHeight() / 2, unitSize.getWidth())
 }

 def n = 2**pow
 def r = 2**(pow/2)
 def c = n / r

 def document = new Document(newSize, 0, 0, 0, 0)
 def pdfWriter = PdfWriter.getInstance(document, new FileOutputStream(dest))

 document.open()

 def contentBytes = pdfWriter.getDirectContent()
 def total = reader.getNumberOfPages()
 def currentSize
 def factor
 def offsetX
 def offsetY
 def page
 def i = 0

 while ( i < total) {
 if ( i % n == 0 ) {
 document.newPage()
 }
 currentSize = reader.getPageSize(++i)

 factor = Math.min(
 unitSize.getWidth() / currentSize.getWidth(),
 unitSize.getHeight() / currentSize.getHeight())

 offsetX = unitSize.getWidth() * ((i % (int) n ) % (int) c) + (unitSize.getWidth() - (currentSize.getWidth() * factor)) / 2f
 offsetY = newSize.getHeight() - (unitSize.getHeight() * (((i % (int) n) / (int) c) + 1)) + (unitSize.getHeight() - (currentSize.getHeight() * factor)) / 2f

 page = pdfWriter.getImportedPage(reader, i)
 contentBytes.addTemplate(page, (float) factor, 0f, 0f, (float) factor, (float) offsetX, (float) offsetY)
 }
 document.close()
 }
}

There is one error left in this last code snippet: the pages are shifted along the Y-axis when they are added to the new pdf and I cannot find where the error is. If you find it, let me know. But the example works and should prove that iText is a viable choice for any JVM language around.

Conclusion

iText is one of the best choices for any JVM language, if not the best. Not many hoops need to be jumped to get a working example although I wouldn’t advise you to use Clojure to write PDFs.

Also, Groovy rocks.