function createPaperShadow( name, width, height, params) {
    function interp( a,b, r) { return ( b*r + a*(1.0-r)); }

    function renderBorderImage( ctx, width, height, params) {
	var slice = params['slice'];
	var shadow = params['shadow'];
	var glow = params['glow'];
	var glowBlur = params['glowBlur'];
	var shadowWidth = params['shadowWidth'];
	var shadowBlur = params['shadowBlur'];
	var shadowVariation = params['variation'];

	if ( slice === undefined) slice = 8;
	if ( shadowBlur === undefined) shadowBlur = 3;
	if ( shadowWidth === undefined) shadowWidth = slice - shadowBlur;
	if ( shadowVariation === undefined) shadowVariation = 0.5;
	if ( shadow === undefined) shadow = 0.5;
	if ( glowBlur == undefined) glowBlur = 3;
	if ( glow == undefined) glow = 0.4;

	var leftEdge = slice;
	var topEdge = slice;
	var rightEdge = width - slice;
	var bottomEdge = height - slice;


	// First things first. Path winding is broken in some browsers
	// I'd like to set a clip so nothing ever draws in the center of 
	// the border image, but I can't, so I'll let it draw then
	// erase it later.



	// Draw the glow. Since this is largely related to the edge
	// being lit, I'll just use a shadow on a triangle.
	ctx.save();
	ctx.moveTo( leftEdge, bottomEdge);
	ctx.lineTo( leftEdge, topEdge);
	ctx.lineTo( rightEdge, topEdge);
	ctx.closePath();
	
	ctx.shadowBlur = glowBlur;
	ctx.shadowColor = 'hsla(0,0%,100%,'+(0+glow).toFixed(2)+')';
	ctx.fill();

	ctx.restore();

	// starting in the upper right, go around clockwise and 
	// make the shadow polygon. Cut the corner from the lower left to 
	// top right when done.
	ctx.save();
	ctx.beginPath();

	var dent4 = interp(shadowWidth, shadowWidth/4, shadowVariation);
	var dent2 = interp(shadowWidth, shadowWidth/2, shadowVariation);

	// as 'a' goes from 0 to 1.0, return the proportional position along the axis of the shadow
	function X(a) { return interp( leftEdge+shadowWidth, rightEdge+shadowWidth, a); }
	function Y(a) { return interp( topEdge+shadowWidth, bottomEdge+shadowWidth, a); }

	ctx.moveTo( rightEdge, Y(0));
	ctx.lineTo( rightEdge + shadowWidth, Y(0));                    // top corner
	ctx.bezierCurveTo(rightEdge + shadowWidth, Y(0.1), 
			  rightEdge + dent4, Y(0.2),
			  rightEdge + dent4, Y(0.3 ));
	ctx.bezierCurveTo(rightEdge + dent4, Y(0.4), 
			  rightEdge + dent2, Y(0.6),
			  rightEdge + dent2, Y(0.7 ));
	ctx.bezierCurveTo(rightEdge + dent2, Y(0.8), 
			  rightEdge + shadowWidth, Y(1.0),
			  rightEdge + shadowWidth, Y(1.0));           // bottom corner
	ctx.bezierCurveTo( X(1.0), Y(1.0),
			   X(0.5), bottomEdge + dent4,
			   X(0.3), bottomEdge + dent4);
	ctx.bezierCurveTo( X(0.2), bottomEdge + dent4,
			   X(0), bottomEdge + shadowWidth,
			   X(0), bottomEdge + shadowWidth);          // left corner

	ctx.lineTo( leftEdge + shadowWidth, bottomEdge);
	ctx.closePath();


	ctx.fillStyle = 'hsla(0,0%,0%,'+(0+shadow).toFixed(2)+')';
	ctx.shadowOffsetX = 0;
	ctx.shadowOffsetY = 0;
	ctx.shadowBlur = shadowBlur*2;
	ctx.shadowColor = 'hsla(0,0%,0%,1.0)';
	ctx.fill();
	ctx.restore();

	// cut out the center of the rectangle, since we couldn't set the clip
	ctx.save();
	ctx.clearRect( leftEdge, topEdge, rightEdge-leftEdge, bottomEdge-topEdge);
	ctx.restore();
    };

    ctx = document.getCSSCanvasContext( "2d", name, width, height);
    renderBorderImage( ctx, width, height, params);
};
