All posts by Kevin Newman

I'm the lead developer at adcSTUDIO located in Kingston NY (in Livingston Manor NY before that). I do all kinds of things there, from robust server side work to the much more enjoyable client side development in HTML/JavaScript/Flash (RIAs, HTML5, etc.) and all the other tech-buzz-phrases of the moment. My brother came up with the idea for unFocus.com which was originally meant be a place to discuss and blog about whatever topics we both found interesting, from politics to technology, to art and design. Time was scarce, and I need a place to host History Keeper, and unFocus Projects - a sub focus of unfocus.com was born, and eventually migrated to the font page. Oh, and I'm on Twitter (@Touvan) and Google+.

HiDPI/Retina for CreateJS (Flash Pro HTML5 Canvas)

Adding HiDPI and Retina screen support to a CreateJS (Flash HTML5 canvas publish with EaselJS) is easy enough. Just add this code after where the stage is defined in your published html file (either inside the generated init function, or handleComplete if there are external assets to load):

if (window.devicePixelRatio) {
	// grab the width and height from canvas
	var height = canvas.getAttribute('height');
	var width = canvas.getAttribute('width');
	// reset the canvas width and height with window.devicePixelRatio applied
	canvas.setAttribute('width', Math.round(width * window.devicePixelRatio));
	canvas.setAttribute('height', Math.round( height * window.devicePixelRatio));
	// force the canvas back to the original size using css
	canvas.style.width = width+"px";
	canvas.style.height = height+"px";
	// set CreateJS to render scaled
	stage.scaleX = stage.scaleY = window.devicePixelRatio;
}

IE 10 doesn’t support devicePixelRatio, but you can polyfill devicePixelRatio with this (include it before your CreateJS script):

/*! GetDevicePixelRatio | Author: Tyson Matanich, 2012 | License: MIT */
(function (window) {
	window.getDevicePixelRatio = function () {
		var ratio = 1;
		// To account for zoom, change to use deviceXDPI instead of systemXDPI
		if (window.screen.systemXDPI !== undefined && window.screen.logicalXDPI !== undefined && window.screen.systemXDPI > window.screen.logicalXDPI) {
			// Only allow for values > 1
			ratio = window.screen.systemXDPI / window.screen.logicalXDPI;
		}
		else if (window.devicePixelRatio !== undefined) {
			ratio = window.devicePixelRatio;
		}
		return ratio;
	};
})(this);

If you like to load your CreateJS based animation in an iframe (I do) and the canvas content is the only content, you may also want to add some styles to avoid scrollbars and extra padding:

body {
	margin:0;
	padding:0;
}
canvas {
	display: block;
}

Before making these edits, I recommend copying the main html page, so that you don’t have to worry about the publisher wiping out your changes when you publish again (if certain things change, you may need to reintegrate your changes).

Some Notes:

  • Some (slightly) older versions of Safari on OSX with Retina screens seemed to automatically apply a pixel doubling to canvas elements, so this might be redoubling again (I’m really not sure). It doesn’t seem to do this in the latest version though.
  • If you use “cacheAsBitmap” the content will be cached at the normal resolution. If you can find the place in code where that’s being set, you can actually apply the devicePixelRatio multiplier there by passing it in as a variable to the function that sets CAB, but CreateJS does not do this by default.

Relevant info for devicePixelRatio and supporting HiDPI / Retina displays

SVGView for Xamarin.Android

Instead of making dozens of PNG files for all the various screen sizes for icon assets, I wanted to use vector graphics (such as SVG) in an Android app I’m building with Xamarin.Android. There is a tool for generating images, and that’s better than nothing, but SVG is even easier, and I’m all about easier. I thought this would be relatively easy to do, but it turns out Android has no built in support for vector image formats.

Xamarin has a nice binding project and sample for using an SVG library (I think it wraps SVG-Android on GitHub) in Android apps, but it wasn’t clear how to use that, and there was an annoying gotcha I hit along the way, that I thought I’d document here.

There are two projects in the sample solution. One is the library project, and the other is a sample project, with sample art that you can build to see it working. What we want to do is build the library, and then copy the necessary components into our own Android app project. Here’s how to do that using Xamarin Studio.

  1. Download and unzip the project files from Xamarin (or fork it on GitHub). Open the Solution in Xamarin Studio. You should see something like this:
  2. Put the build mode into “Release” and then right click (or control click) on SvgAndroid (Highlighted in the screenshot above), and then click Build SvgAndroid (or highlight the project and press cmd+K). This will make a release .dll file (a .NET assembly) in the bin folder:
  3. You’ll need to copy two files into your own project. SvgAndroid.dll from bin/Release, and svg-android-1.1.jar from the Jars folder. I put SvgAndroid.dll file in the project/Assemblies folder in in my project hierarchy so that the dll could be managed in git with the rest of my project (the git rule of thumb – include what you need to build, and I need this dll to build the app). The jar file – svg-android-1.1.jar – went into the project/Jars folder.
  4. Add the assembly to the project: Right click on references in the Solution panel, and choose “Edit References.” In there, add the .dll under the “.Net Assemblies” tab.
  5. Add the jar file: Add the jar file to your project using add file or add folder (to add the entire Jars folder). Then right click the jar file, and choose “Build Action” -> “AndroidJavaLibrary” to make sure it gets packaged with your application.

That’s it! Those two files are all you need. Now you can create an SVGView class, and use that in your axml layouts. Here’s a quick and dirty example of the class:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Util;
using Android.Views;
using Android.Widget;
using Com.Larvalabs.Svgandroid;

namespace unFocus
{
	public class SVGView : ImageView
	{
		protected string svgSrc;
		public string SVGSrc {
			get {
				return svgSrc;
			}
			set {
				svgSrc = value;
				setupSVG ();
			}
		}

		public SVGView (Context context) :
			base (context)
		{
			Initialize ();
		}

		public SVGView (Context context, IAttributeSet attrs) :
			base (context, attrs)
		{
			Initialize (attrs);
		}

		public SVGView (Context context, IAttributeSet attrs, int defStyle) :
			base (context, attrs, defStyle)
		{
			Initialize (attrs);
		}

		void Initialize ()
		{
		}

		void Initialize (IAttributeSet attrs)
		{
			var a = Context.ObtainStyledAttributes(attrs, Resource.Styleable.SVGView);
			SVGSrc = a.GetString(Resource.Styleable.SVGView_svgSrc);
			a.Recycle ();
		}

		void setupSVG ()
		{
			// svg-android doesn't work in hardware mode, so set software
			SetLayerType (LayerType.Software, null);

			if (null == SVGSrc)
				return;
			SVG svg = SVGParser.GetSVGFromAsset (Context.Assets, SVGSrc);
			SetImageDrawable (svg.CreatePictureDrawable ());
			Invalidate ();
		}
	}
}

And in values/attrs.xml:

<?xml version="1.0" encoding="UTF-8" ?>
 <resources>
     <declare-styleable name="SVGView">
         <attr name="svgSrc" format="string"></attr>
     </declare>
 </resources>

Now you can create SVGViews in axml using:

<unFocus.SVGView
    android:svgSrc="svg/somesvgfile.svg"
    android:layout_width="58.0dp"
    android:layout_height="58.0dp"
    android:id="@+id/icon" />

SVG files go in the Assets folder, in whatever tree you want. In this example, they are in Assets/svg/. Build action for svg files is “AndroidAsset,” which should be the default.

There is an irritating gotcha, that’ll have you tearing your hair out if you don’t know about it.

SVG files MUST have width and height attributes on the root element to work with this library. If you don’t have them, and Adobe Illustrator CC doesn’t add them by default, the lib will fail with cryptic error messages. The fix is easy enough, just open the SVG in Xamarin and add width and height attributes. There will already be a viewBox attribute with the correct attributes (viewBox=”0 0 70 70″ <– the second two, width and height). You’ll need to add these: width=”70px” height=”70px”.

Update: One other thing I forgot to mention – this didn’t work on the Xamarin Alpha for some reason. The SVGAndroid binding was failing if I remember correctly (at least that’s where the runtime  errors seemed to originate). So if you are having trouble getting this to work, it might be something in the Alpha channel.

Update 2: What I’ve showed you here will work, but some folks on the Xamarin forums suggest there may be advantages to including third party code in alternative ways (like including an entire project, etc.). Have a read.

Update 3: SVG-Android won’t work under hardware acceleration, which is enabled by default in apps targetting Android 3.0 and newer. You just get a blank space. The easiest way around this is to set the Application, Activity, or the specific view you are working on to use software acceleration.

I modified the SVGView example above to do this automatically, but you can also do it yourself (using the code above) or by setting the android:layerType=”software” on the specific view (or somethings its parent).

This is worth knowing about because other types of drawables (such as animations) seem to display other types of incompatibilities with hardware acceleration (such as fuzzy low resolution renderings), and setting software mode can fix it.

Enjoy!

Compiling Mono (and PlayScript) on OSX Mountain Lion (10.8)

A while back, Zynga employees demonstrated a project they are working on called PlayScript, an implementation of AS3 and an ASNext wish-list language they named PlayScript on the Mono Platform. In order to play with it, it’s probably best to compile your own copy, since any binaries they post will quickly get out of date. Wanting to play around with it on my iPhone, I took a stab at compiling the Mono Project on OSX, for use in Xamarin Studio. I used a copy of PlayScript-mono for this post, but these instruction should really apply to any fork of Mono (I think).

The OSX compile instruction page on Mono-Project.com is a bit hard to follow if you are new to this stuff, so I thought I’d write up some more detailed instructions in the hope it would save someone some time.

First, the prerequisites. You’ll need Xcode, and the command line tools. Grab Xcode out of the Mac App Store, and run it. Then go to Preferences under the Xcode menu, then the Downloads Tab/button/icon (organizationally, it’s tab, but it looks like a button with an icon). In there, you should install “Command Line Tools”. This contains some of the stuff you’ll need to build Mono on OSX.

The build instructions on mono-project.com say you’ll need a version of mono installed before you can compile. I had Xamarin and Unity3D installed before I tried to build, and one of them seemed to cover my bases.

There are a couple of prereqs still missing. From various sources, it looks like the make and autoconf tools used to be included with Xcode’s command line package, but they aren’t anymore in OSX 10.8 (Mtn Lion). There are a couple of ways to install them, including building them yourself, but the easiest way I found is to use Brew. Installing Brew is easy enough – copy the ruby command from the brew website, and run it in a terminal.

I always recommend going to the primary source for the correct install method on these kinds of things, so go there, install, and then come back.

Next, use brew to install automake, autoconf, and libtool. You don’t need “sudo” – but don’t worry, brew will complain if you forget. You’ll get a message about libtool being prefixed with a g to avoid conflicts – this didn’t seem to have any unwanted effect for building Mono.

brew install autoconf libtool automake

Note: I had trouble with brew install and libtool on a new mac while writing this post. I didn’t have this problem when I built it on an older iMac. I’m not sure what caused it, but if you get any errors during the brew step (mine was about linking libtool) you can type “brew doctor” in the build directory, and it’ll give you some pointers. My specific problem was that /usr/local/lib wasn’t owned by my user account. The brew suggestion was to “chown” that dir, and rerun the link command for libtool (the step that failed during install), so this was the command I used to fix my brew libtool problem:

sudo chown $USER /usr/local/lib
brew link libtool

There were some other notes about rearranging things in your path for git, etc., but I didn’t bother with any of that.

Now we are ready to compile Mono. The first thing you need to do is download a copy of the Mono source from somewhere. A mainline mono archive or SVN checkout would work, or you could clone a local copy of PlayScript-mono from GitHub, then go inside the folder, which is what I did:

git clone https://github.com/playscript/playscript-mono.git
cd playscript-mono

Now we are up to the configure stage, which is where you will start to run into trouble if you don’t have the proper prerequisites setup. The instructions on mono-project say you can use ./configure from a tar, but I wasn’t able to get that to work from either git or tarball. ./autogen.sh seemed to work from both sources though. Note: the prefix flag is where Mono will be installed when you run “make install” and unless you know what you are doing, you probably don’t want to leave that as the default value. Here’s the bolded warning from mono-project, “It is strongly advised not to install Mono from source in /usr, /usr/local or any other “standard” directories unless you know what you are doing.” I put mine in a directory matching the repo name I’m building from my user directory.

./autogen.sh –prefix=/users/{kevin}/mono-playscript –enable-nls=no
make
make install

This can take a LONG time!

It’s been a while.

It’s a been a while since I posted. What’s up?

I’ve been working on a ton of stuff, and learning 10 new platforms it feels like. There’s a lot of excitement out there in both mobile development and HTML5 spaces. I’ve been deep diving into WordPress, learning CoffeeScript and TypeScript (I even started a Backbone.js implementation in TypeScript and called it CruddyMVC, but I didn’t get far, just the model, and I need to back port some ideas I implemented in a PHP/WordPress version of the same), node.js (even got my first bit of node.js code out in the wild just yesterday), and recently Xamarin, which looks like a great replacement for Flash and AIR for mobile apps (even without Playscript and Zynga’s AS3 language bindings, though those are pretty nice to have). I think I’ll even throw together a video sharing app using Xamarin, and a node.js server, cause that sounds like a great way to spend my nights and weekends. I might even dig back into unBrix (here’s the even less feature complete Android version). I have some ideas on how to keep the late game from getting boring, and it really could use some more features and, you know, levels.

I’ve got some fun things to post on WordPress dev (been doing a lot of WordPress and Backbone.js at work), and some tools I made like OnceForm (make sure to checkout the redux branch), that adcSTUDIO contributed to open source under GPL (I wrote a giant intro post for that a couple of weeks ago, but then Firefox crashed…).

Anywho, just wanted to post .. something. So here it is. I’ll try to post more often about some of this stuff, there’s a lot to talk about!

SignalsLite.js, Unit Testing, and Buggy IE

I decided to finally learn unit testing, so I downloaded QUnit (after looking at the 20,000 different unit testing options), and figured I’d give porting tiny SignalsLite to JavaScript a try, and see how the process goes.

While doing that, I found a crazy IE7/IE8 JS bug, that I’m sure has had me scratching my head in the past. Here is a quick unit test to show the problem:

test( "Basic Requirements", function testReqs() {
	expect(1);
	var T;
	(function makeT() {
		T=function T(){}
		T.prototype.test = 1;
	})();
	ok((new T).test, "Instance of exported T should have prototype methods");
});

If you run that IE7 or IE8 it’ll fail!

The cool thing is, without having created unit tests for SignalsLite.js, I would never have known that could be an issue, and instead would continue to scratch my head when stuff like that broke in IE7/8. I found this because I was trying to export SignalLite from within a closure (I try to always define my stuff inside of closures to avoid namespace pollution), with this:

(function() { "use strict"; // standard header

// naming inline functions makes the debug console easier to read.
window.SignalLite = function SignalLite() {
	// stuff
}
SignalLite.prototype = {
	// methods
};

// The fix is to use an anonymous function, or export elsewhere:
// window.SignalLite = SignalLite;

})();

For whatever reason, that doesn’t work in IE7 and IE8. Unit testing is crazy!

If you are interested, go fork SignalsLite.json GitHib.

P.S. You can run the SignalsLite.js unit tests here to see the fail for yourself! I disabled that test in the SignalsLite.js tests.