Techblog

Tech Blog

Our latest geek adventures!

Archive for the ‘Development’ Category

22 October Printing & Big Bitmaps

Last week I started working on a new version of the print functionality in Floorplanner. The problem with the previous version was that it didn’t print shadows, it was impossible to rotate the plan to landscape and textures didn’t look very well. Overall it produced a very mediocre image compared to the visual quality of a plan on the screen. As can be seen below:

Old print output

Old print output

For printing we use the AS2 PrintJob class, which works really easy, with a small disadvantage: it doesn’t print Floorplans properly. I tried all kinds of settings for this class, with as input just a MovieClip with a drawing of the plan on it. I tried setting the printAsBitmap to true and false, both giving the exact same result. So although being stuck with it, the printAsBitmap boolean inspired me to investigate the Bitmap thing. We already had an image export utility, which produces images of a Floorplan with the same quality as it is shown in the FlashPlayer. The funny thing is that when I printed this exported image, the print quality was really good, at least a lot better than our own printing functionality. So for some reason, even if I used the printAsBitmap functionality, it still didn’t produce the same quality as using a real bitmap.
Of course we could have stopped here and just tell the users of Floorplanner to print the exported image. But since we are Floorplanner, we didn’t want to introduce another step requiring user action in the printing process, after all, we are the “easiest way” :-).
So I decided to use the same BitmapData created for the image export as basis for the printing. The first results where rather disappointing, I attached the created BitmapData to a MovieClip which in turn was given to the PrintJob. The produced print was of really low quality, you could easily see pixels all over the place. I tried using more pixels but now I bumped into the pixel limit of BitmapData (2880×2880 pixels). To work around this I invented the BigBitmapData class, this is a wrapper class that mimics the functionality of the BitmapData class, but which doesn’t have an upper limit of the number of pixels which can be used. When an instance of BitBitmapData is created which is bigger than 2880 by 2880, it creates additional BitmapDatas to store the additional pixels needed. So in fact the BigBitmapData internally stores an two dimensional array of BitmapDatas to bypass the pixel limit.
So with this new class I was able to scale up the created image to unprecedented sizes. I did a lot of printing experiments with scaling of the input, I tried scaling settings from 2 times to more than 10 times! This huge bitmap was attached to a MovieClip which in turn had to be scaled to fit on one single page of the printer. These values did give a better result, but still not good enough. It turned out that I had to take the DPI of the printer into account. The optimal scale factor turned out to be (1 / 72) * 300. The 72 is the DPI of the screen, and the 300 is the DPI of the printer. Furthermore a ‘point’ (print unit of measurement) is 1/72 inch, while the size of a pixel (screen unit of measurement) is dependent on the resolution of the screen.
So what this method actually does is creating a big image (which is resized to the paper contents) with enough quality to be printable on a 300 DPI printer.

New print output

New print output

So as you can see in the second image above, the new print looks a lot better, and since the new print uses bitmaps it is really easy to rotate it to always produce a print that tries to fill the entire paper.

A disadvantage of this method is that it takes quite some computational power to compute all the pixels for the bitmap that is created in memory, so as a result the FlashPlayer and sometimes even the browser freezes for a moment. Although this isn’t very good, we thought this behavior is acceptable since the quality of the prints is much better than the previous ones and the freeze time is actually really short. If you are not convinced by the images (which is understandable since the quality difference can only be seen on paper), just check it out!

No Comments - Tags: , ,

31 July Lighten up your development with Lighthouse

Posted by Gert-Jan in Development

Over the last year we’ve tried a lot of different applications to keep track of bugs and other issues, but none of those apps sticked with us. They were either not suited for the job (Basecamp) or to difficult and ugly (Trac, Bugzilla). But now I think that we finally have found a solution that just gets the job done: Lighthouse by activereload.

Lighthouse ticket scoreboardLighthouse’s tagline is “beautiful simple issue tracking” and that really sums it up perfectly. It tracks issues, not only a bugs, so you can use it for all the issues that need to be dealt with. It’s simple and it’s easy to use, it just does what it needs to do without loads of unneeded features. A great advantage for us is that our designers can (and want) to use it too. It’s also very nicely priced and it has a sweet API for us geeks to build your own scoreboard :-D (see picture).

There are some minor things that can be improved (for example, it’s somethings a little confusing to work with multiple projects) but it’s by far the best issue tracker I’ve ever worked with. To everybody at activereload, we really love your product and keep up the good work!

No Comments - Tags: , , ,

11 July Using git-svn

I personally am a fan of the git version control system. The best part of git is its speed, and the simplicity of using local branches.

Local branches are very helpful if you are working on different features at the same time but want to keep them apart. An example: it happens all the time that I am working on some feature and than I have to put my current work aside to work on a high priority issue. Once this issue is solved, I need to commit the changes and usually do a deploy of the web application so that the problem is solved as soon as possible. With Subversion, I sometimes commit files that were part of the unfinished feature I was working on before I started on the high priority issue. If I am not careful and deploy those files, unfinished work will be put into production and this can go horribly wrong, like every page request returning a 500-error of our high traffic site :(.

Using git, I can put my current work aside easily by using git stash. When I am finished with the high priority issue, I can revert to my previous work with git stash apply.

Another option: branching the project (using git branch feature) if the feature I am working on is invasive and than switch branches for high priority issues using git checkout master. I can go back to the feature branch with git checkout feature, followed by git merge master to merge back the changes I just made in the master branch. Branching and merging is very fast in git and merging is not the PITA like it is in Subversion.

However, our main code repository will probably remain in SVN for now. Luckily for me, I can use git-svn locally to profit from these advantages. I found an informative page on installing and getting started with git-svn on OSX. If you know Subversion, this page is helpful to translate Subversion commandos to their git alternatives.

No Comments - Tags: , , , ,

2 April Consume SOAP web service from Javascript

I wanted to get some data from a web service using Javascript. I looked at several Javascript classes (like this), but because the web service was running on another server it got a little troublesome. As a solution I tried to call the web service through a proxy, but that didn’t make it any easier.

Jaap suggested to take a look at NuSOAP, a -kinda old- SOAP toolkit for PHP. With an AJAX request I could call a PHP page that uses NuSOAP to consume the web service. It was actually easier then I thought it would be.

To make the AJAX call from Javascript I used Prototype and this script:

  function doRequest() {
    var url = "ajax/consume_webservice.php";
    var param1 = "value1";
    var param2 = "value2";
    var params = "param1="+ param1 +"&param2="+ param2;
 
    new Ajax.Request ( url, { method: 'POST', parameters: params,
      onComplete: onResult } );
  }
 
  function onResult( result ) {
    alert( result.responseText );
  }

The PHP file consume.php looks something like this:

< ?php
 
  $param1 = isset( $POST_['param1'] ) ? $POST_['param1'] : false;
  $param2 = isset( $POST_['param2'] ) ? $POST_['param2'] : false;
 
  // this is the only file I used from the NuSOAP project
  require_once( "nusoap.php" );
 
  $url = webserviceurl;
  $params = array( "param1" => $param1, "param2" => $param2 );
 
  $soap = new nusoap_client( $url, true, false, false, false, false, 0, 60 );
  $proxy = $soap->getProxy();
  $proxy->functionname( $params );
 
  echo $proxy->response;
 
?>

That’s all. Do a AJAX request from Javascript to a PHP page. Then the PHP page uses NuSOAP to consume the web service and returns the result. Back in Javascript you can do whatever you want with the given data.

No Comments - Tags: , , ,

28 March Rounding errors in practice

In college I followed a course in numerical analysis. The main point of the course was to be careful with floating point arithmetic, because it is vulnerable to rounding errors that can significantly influence the result of complex computations. Until yesterday I never had encountered such a problem. Now that I have lost my innocence in this matter, I would like to share my tale of nasty debugging and frustration.

After receiving some bug reports of Floorplanner designs that failed to save properly, we dove into the code to see what was going wrong. After some time, we found that the errors were caused by the script that loads the design after it has been saved with a unique name. This unique name is passed to the script to be able to find the design. We used the current timestamp as a unique name for the design. The current timestamp simply is the number of seconds passed since January 1, 1970 and looks something like this: 1206712028. As a design name, this number was passed to different scripts, both client-side and server-side. However, at some point in this chain of scripts, the number was changed slightly to 1206712030 and because of this the associated design could not be found, resulting in an error.

At first, we investigated the possibility that the stored timestamp was overwritten by a newer timestamp, as this could explain the slight increase in the number. However, we were not able to find this anywhere in the code and sometimes, the number was decreased a bit instead of being increased.

Finally, we monitored the data being sent between the different scripts, and we found that ActionScript automatically converted the numeric design name into a number in scientific notation. In our case, this would be 0.1206712028 x 10^10. Unfortunately, this number was rounded to 0.120671203 x 10^10 because computers use floating point arithmetic to store numbers in scientific notation. This number would eventually be converted back to normal notation, but it was now 1206712030 because of the rounding error.

We fixed it by putting an ‘a’ in front of the timestamp, preventing the automatic conversion to a number. Not very elegant, but it works!

No Comments -

24 October Source control and branching

Posted by Gert-Jan in Development

Today we changed our branching style of the Floorplanner code base. I had it in my head for a long time, but I actually changed it until I read this post.

In the old setup we used the style that is called Branch per Release.

Branch per Release
Every release is a new branch; common changes are merged between the releases. Branches are killed off only when the releases are no longer supported.branch per release

In the beginning we had a lot of custom projects running on one Floorplanner code base. We wanted to improve the Floorplanner itself but changes in the source could cripple the custom projects. That’s why we created a branch for every custom project. This way we had a stable codebase for every custom project and for the Floorplanner itself. When we fixed a global bug we merged the fix to all the branches.

Nowadays we don’t have any custom projects running on the same code base anymore. We do have one branch (not the trunk) in which we were working on the latest release. So today I decided that this had to change. We merged the branch to the trunk and new features (tasks) will be developed in a branch of their own. When the feature is done it will be merged back to the trunk.

This is called the Branch per Task.

Branch per Task
Every development task is a new, independent branch. Tasks are merged into the permanent main branch as they are completed.branch per task

If you want to know more about branching, read Jeff’s post Software Branching and Parallel Universes.

No Comments -

19 July Rethinking Design Patterns

Posted by Gert-Jan in Development

Jeff Atwood recently wrote a very interesting post about this topic. He states that:

  • Design patterns are a form of complexity. As with all complexity, I’d rather see developers focus on simpler solutions before going straight to a complex recipe of design patterns.
  • If you find yourself frequently writing a bunch of boilerplate design pattern code to deal with a “recurring design problem”, that’s not good engineering– it’s a sign that your language is fundamentally broken.

Check out the whole story here: Rethinking Design Patterns

No Comments - Tags: