Problems with curves in HTML5 using Chrome

Recently we encountered a bug with one of our converted HTML5 files that was specific to Google Chrome, specifically to do with the bezierCurveTo function for canvas.

The HTML file contains a rectangular box with two rounded corners, below is it’s appearance in most web browsers and Chrome:

Normal appearance outside of Chrome

Appearance outside of Chrome

Appearance in Chrome

Appearance in Chrome

Upon inspection we found the problem code to be one specific bezierCurveTo function call. So in an effort to understand the problem I made a small test page to replicate it which you can see here.

The following is a snippet of that code showing how the image is drawn:

var height = 400;
var width = 150;
var curvature = 8;
 
pdf.beginPath();
pdf.moveTo(0, 0);
pdf.lineTo(0, height);
pdf.lineTo(width - curvature, height);
pdf.bezierCurveTo(width - curvature, height, width, height, width, height - curvature);
pdf.lineTo(width, 0 + curvature);
pdf.bezierCurveTo(width, curvature, width, 0, width - curvature, 0);
pdf.fillStyle = 'rgb(0,0,0)';
pdf.fill();

For convenience sake I hard coded the values as variables so it was easier to modify. The variables height and width are self explanatory; curvature denotes how curved the two corners should be, lower values will create a smaller curve.

The lines begin at the top left hand side of the canvas and travel anticlockwise using normal lineTo commands until it reaches the bottom right hand side, whereupon we use a bézier curve to create a smooth corner.

This first bézier curve behaves normally and appearance stays consistent across all html5 supporting browsers we have tested on. After this bézier curve we use another simple lineTo command to traverse to the top right hand corner of the shape and then call a final bézier curve to finish the shape.

This is when the error in Chrome becomes apparent, up until this point all the browsers display the same. If the height is greater than the width (i.e. the box is a rectangle) the error occurs. In fact this can also happen with the first bezierCurveTo function if the width is greater than the height.

From a quick search I was able to find out that this issue was not present in previous version of Chrome and can also effect square shapes using bezier curves for all four corners.

One solution, as noted in that link, is to use the quadraticCurveTo function instead, however this affords less accuracy as it only takes one control point instead of two and because we are converting PDF files to HTML we cannot use quadratic curves as PDF files use bézier curves.

Another solution I found is to offset the bézier curves first control points y by a fractional amount: the smallest I have used is 0.000001

pdf.bezierCurveTo(width, 0.000001 + curvature, width, 0, width - curvature, 0);

Until there is a fix for the issue, offsetting the Y value seems like the likely workaround we will use in our PDF to HTML5 converter.

This post is part of our “HTML5 Article index” in these articles, we aim to help you understand the world of HTML5.

Related Posts:

The following two tabs change content below.
Lyndon is a Developer at IDR Solutions. He currently focuses mostly on the JavaScript in the Viewer and PDF to HTML5 Converter and also the Android PDF Viewer. He gave a short talk at the GlassFish UnConference before JavaOne 2012. Outside of IDR Solutions he has a keen interest in AI and Games Programming and runs a blog that he periodically updates.
lyndon

About Lyndon Armitage

Lyndon is a Developer at IDR Solutions. He currently focuses mostly on the JavaScript in the Viewer and PDF to HTML5 Converter and also the Android PDF Viewer. He gave a short talk at the GlassFish UnConference before JavaOne 2012.

Outside of IDR Solutions he has a keen interest in AI and Games Programming and runs a blog that he periodically updates.

One thought on “Problems with curves in HTML5 using Chrome

  1. Had a similar issue with Chrome 30 (IE 10, Opera 12 and previous Chrome all fine) rendering one extra pixel wide and tall for bezierCurveTo() created boxes using only fill(). Your fix above corrects that as well, really appreciate the post!

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes:

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>