[philiptellis] /bb|[^b]{2}/
Never stop Grokking

Sunday, April 24, 2011

pngtocss and getting back to basics

A couple of days ago Nicole tweeted about the absence of a tool to convert images to gradients. I didn't see the tweet right away because I was asleep at the time, but Sergey retweeted it later under the @perfplanet account and I caught that.

My first thought was that there really must be something like that. Why not just use the gimp's colour picker or something. My second thought was, "what the heck are CSS gradients?" followed closely by, "I've never read a PNG in C before".

Back to basics

All of this brought up a sense of déjà vu back to 1999, to the birth of my first opensource project. That started out with someone on the ilug-bom mailing list asking how he could find out which server was running on a given host. I started to type out an explanation and then figured that it would take me less time to hack up a solution in perl, so I did, and httptype was born.

Yesterday was very similar, the only real difference being that this time I knew how to use version control, so I jumped in with:
mkdir pngtocss
cd pngtocss
git init
mkdir src
And then started on a bit of research. First to find out how to read in a PNG.

Reading in a PNG

libpng.org has a great book on using the libpng library. It's a long book and I'm a lazy dev, so I didn't read the whole thing. Instead I found the Chapter that dealt specifically with reading a PNG into memory. It turned out to be Chapter 13. Now when I say "I found", I really mean that Yahoo! found it for me.

Anyway, I read the doc and it was pretty straightforward, so I jumped right into writing code, but guess what? My C programming skills were rusty. My Makefile skills more so. Having man at hand helped things move along and I was soon up to speed.

Once I had an in-memory array of the image's pixels, I had to figure out how to write out the CSS.

CSS gradients

There were a few sites that helped with this, in particular CSS tricks. A few printfs later and I had simple gradients done.

The code was simple, and handled a very specific case. It didn't work with all possible gradients, and wouldn't be able to handle a sprite, but this is how projects grow. You don't try to solve everything at the start. You solve a use case and push it out there to find out what people want.

The last time around I pushed it out to the mailing list and got a lot of feedback, patches and even a mentor. This time I announced it on twitter and got a bunch of feedback and a ton of retweets.

The physics of gradients

Today I decided to look at multi-colour gradients. Not because anyone had asked for it, but because I thought it might be interesting to figure out where a colour shows up.

Now there are various ways to look at a gradient. If you think about it from a physics background, it's essentially a particle moving with constant velocity. Each pixel position is a unit of time and the colour value is the particle's position at that point in time. The position at any point of time is calculated by the second equation of motion:
s = ut + ½at²
For a simple two colour gradient, there's no acceleration, and the velocity u is the difference in the two colours divided by the number of pixels in that direction. This is the same as the difference in colour of adjacent pixels (colour differential per unit pixel).

The cool thing is that for CSS, you only need to specify the end points and it will fill in everything else.

Multi-colour gradients

When dealing with multi-colour gradients, you need to figure out where the stop points are. Once you know what the colour velocity at the start of the gradient, you keep iterating through the image until the velocity is no longer what you expect it to be. This is a colour stop. Note down the new colour and its position and restart.

To speed things up, rather than look at every pixel along the way, I exponentially increase the pixel index that I look at until I hit a bump and then backtrack till I find what I was looking for. A sort of binary search.

Putting it all together, I ended up with this example page which has gradient images and the equivalent CSS gradient side by side. There are still limitations, but none that I care to fix at the moment.

Other tools

Also of note is Alex Sirota's Gradient Editor as part of Colorzilla. It's completely web-based and can also take in a file upload and generate a gradient from that. It doesn't handle the rainbow gradient yet, but I suppose it won't be too hard to get around that.


In any case, pngtocss is on github at https://github.com/bluesmoon/pngtocss, feel free to fork it and submit patches. The code isn't pretty and isn't really commented either.

Wednesday, April 13, 2011

How much do you trust third party widgets?

It's fairly common to find third party widgets installed on websites today. My own blog includes widgets from twitter, delicious, google analytics and google translate, and in the past I've included mybloglog and technorati as well. The facebook like button, facebook comments, disqus comments, badges from sharethis and more are all over the place. This is a great way to engage with your readers, get feedback from them, and let them get the word out about your site, but how secure is it? When we include a third party widget on our sites, what exactly do we trust the third party to do and not do?

In particular, this mostly refers to widgets that require you to add links to their JavaScript into your page using a <script> node. There are a few that work through iframes, and while there are still a few issues with that, the script nodes are the ones that can do you the most damage.

Not be evil

For starters, we trust the third party to not be evil. We trust that the JavaScript they serve us will:
  • not try to steal the data our users give us through the website,
  • not manipulate our page content in malicious ways,
  • not track our user's actions in any ways that we haven't authorised them to do,
  • probably more...
For the most part, the widget provider stakes their reputation on the quality and the chastity of the widgets they provide. Anything malicious found in their widgets would affect a large number of sites, but would cause terrible PR and contractual problems for the provider. For most of us small blog authors, dots on the long tail as it were, the widget provider has far more to lose than we do. For a large company, like say one of these widget providers themselves, though, there's much more at stake, so don't be surprised if you don't see third party widgets on Google, Yahoo!, Microsoft, Facebook, Twitter, Amazon, Ebay and any other large site you can think of. They probably have much more (or at the least an equal amount) to lose than the widget provider.

Not be careless

We're also trusting the widget provider to not be careless. We expect them to be diligent about the security of their own systems. If someone malicious were to break into a third party widget provider, they could then manipulate the JavaScript served out to our sites. Same problem as above, same repercussions, but slightly different entity responsible. It's possible for the widget owner in this case to claim that they were also the victim. That doesn't make it better for anyone, it just shifts the blame.

Not be too trusting

We don't just trust the widget provider, but also their hosting provider and their DNS registrar. This is a sub-topic under the don't be careless part above, but there may be another entity involved here. Running a whois lookup on the widget provider's hostname will tell you who their DNS registrar is. Do you trust them to not get compromised and have DNS redirected? Does the widget provider use SSL to guarantee that the host you're connecting to is in fact a host they own? Can you trust SSL?

Not go down

Let's face it... how many times have you had a twitter (or any other) widget on your page that showed nothing? Perhaps you're being rate limited, perhaps the service is down for maintenance, or something else. That huge blank space where your widget should be looks kinda bad. Not really a security issue, but it hurts your site's image.

There's little doubt why large companies won't trust a third party's JavaScript on their own sites. In exceptional cases, they may contract with the third party to get the JavaScript onto their own servers where they can guarantee that it doesn't change, and can pull the plug quickly if something goes wrong.

What about you? Do you run a website that includes third party widget JavaScript on your site? Are you big or small? Would you keep this up when you became big?

Saturday, April 09, 2011

overflow:hidden, border-radius and position:absolute

In my last post, I showed off some CSS fun with border-radius and overflow:hidden. Truth be told, that post started out about a bug with WebKit based browsers in relation to those attributes, but when I got down to writing the post, I couldn't reproduce the bug. Today, while trying to animate it, I managed to isolate the problem, and it turns out that I'm not the only one.

The problem in brief is that the contents of a container with overflow:hidden will still overflow its border if you have border-radius set and position set to anything other than static. Bug 50072 on WebKit describes a similar issue in more detail, and I've posted my comments at the bottom of that bug. I've created a minimal test case on JSFiddle.

The problem only shows up when you set the container's position style attribute to something other than static (which is the default).

I've tested in the latest versions of Firefox, Chrome, Safari and Opera, and Firefox is the only one that renders it correctly.

Now before you go asking me to test on the latest WebKit, rest assured that it's compiling as I write this. I'll try and submit a fix if it still exists and I can figure out what needs patching, but given that position:static works correctly, it may just be a matter of seeing what's different with those two flows.

Update 2016-10-28: This appears to be fixed on the latest versions of Chrome, Firefox, Safari and Opera:

Bug fixed version