

var drawPreview = function (image, highresimage, compositeImage, fabricWidth, fabricHeight, imageWidth, imageHeight, repeat, compositeRepeats, fabricDpi) {
      
    var canvas = document.getElementById('design_preview');
    
    //
    // The canvasText code is released to the public domain by Jim Studt, 2007.
    // He may keep some sort of up to date copy at http://www.federated.com/~jim/canvastext/
    //
    
    // This code is what enables us to put numbers on the ruler... canvas does not come with a native text capability

    var CanvasTextFunctions = { };

    CanvasTextFunctions.letters = {
        ' ': { width: 16, points: [] },
        '|': { width: 20, points: [[19,20],[19,0]] },
        '!': { width: 20, points: [[19,12],[19,0]] },
        'i': { width: 8, points: [[3,21],[4,20],[5,21],[4,22],[3,21],[-1,-1],[4,14],[4,0]] },
        'n': { width: 19, points: [[4,14],[4,0],[-1,-1],[4,10],[7,13],[9,14],[12,14],[14,13],[15,10],[15,0]] },
        '.': { width: 10, points: [[5,2],[4,1],[5,0],[6,1],[5,2]] },
        '_': { width: 20, points: [[20,10],[0,10]] },
        '-': { width: 20, points: [[12,10],[0,10]] },
        '0': { width: 20, points: [[9,21],[6,20],[4,17],[3,12],[3,9],[4,4],[6,1],[9,0],[11,0],[14,1],[16,4],[17,9],[17,12],[16,17],[14,20],[11,21],[9,21]] },
        '1': { width: 20, points: [[6,17],[8,18],[11,21],[11,0]] },
        '2': { width: 20, points: [[4,16],[4,17],[5,19],[6,20],[8,21],[12,21],[14,20],[15,19],[16,17],[16,15],[15,13],[13,10],[3,0],[17,0]] },
        '3': { width: 20, points: [[5,21],[16,21],[10,13],[13,13],[15,12],[16,11],[17,8],[17,6],[16,3],[14,1],[11,0],[8,0],[5,1],[4,2],[3,4]] },
        '4': { width: 20, points: [[13,21],[3,7],[18,7],[-1,-1],[13,21],[13,0]] },
        '5': { width: 20, points: [[15,21],[5,21],[4,12],[5,13],[8,14],[11,14],[14,13],[16,11],[17,8],[17,6],[16,3],[14,1],[11,0],[8,0],[5,1],[4,2],[3,4]] },
        '6': { width: 20, points: [[16,18],[15,20],[12,21],[10,21],[7,20],[5,17],[4,12],[4,7],[5,3],[7,1],[10,0],[11,0],[14,1],[16,3],[17,6],[17,7],[16,10],[14,12],[11,13],[10,13],[7,12],[5,10],[4,7]] },
        '7': { width: 20, points: [[17,21],[7,0],[-1,-1],[3,21],[17,21]] },
        '8': { width: 20, points: [[8,21],[5,20],[4,18],[4,16],[5,14],[7,13],[11,12],[14,11],[16,9],[17,7],[17,4],[16,2],[15,1],[12,0],[8,0],[5,1],[4,2],[3,4],[3,7],[4,9],[6,11],[9,12],[13,13],[15,14],[16,16],[16,18],[15,20],[12,21],[8,21]] },
        '9': { width: 20, points: [[16,14],[15,11],[13,9],[10,8],[9,8],[6,9],[4,11],[3,14],[3,15],[4,18],[6,20],[9,21],[10,21],[13,20],[15,18],[16,14],[16,9],[15,4],[13,1],[10,0],[8,0],[5,1],[4,3]] }
    };

    CanvasTextFunctions.letter = function (ch)
    {
        return CanvasTextFunctions.letters[ch];
    }

    CanvasTextFunctions.ascent = function( font, size)
    {
        return size;
    }

    CanvasTextFunctions.descent = function( font, size)
    {
        return 7.0*size/25.0;
    }

    CanvasTextFunctions.measure = function( font, size, str)
    {
        var total = 0;
        var len = str.length;

        for ( i = 0; i < len; i++) {
    	var c = CanvasTextFunctions.letter( str.charAt(i));
    	if ( c) total += c.width * size / 25.0;
        }
        return total;
    }

    CanvasTextFunctions.draw = function(ctx,font,size,x,y,str)
    {
        var total = 0;
        var len = str.length;
        var mag = size / 25.0;

        ctx.save();
        ctx.lineCap = "round";
        ctx.lineWidth = 2.0 * mag;

        for ( i = 0; i < len; i++) {
    	var c = CanvasTextFunctions.letter( str.charAt(i));
    	if ( !c) continue;

    	ctx.beginPath();

    	var penUp = 1;
    	var needStroke = 0;
    	for ( j = 0; j < c.points.length; j++) {
    	    var a = c.points[j];
    	    if ( a[0] == -1 && a[1] == -1) {
    		penUp = 1;
    		continue;
    	    }
    	    if ( penUp) {
    		ctx.moveTo( x + a[0]*mag, y - a[1]*mag);
    		penUp = false;
    	    } else {
    		ctx.lineTo( x + a[0]*mag, y - a[1]*mag);
    	    }
    	}
    	ctx.stroke();
    	x += c.width*mag;
        }
        ctx.restore();
        return total;
    }

    CanvasTextFunctions.enable = function( ctx)
    {
        ctx.drawText = function(font,size,x,y,text) { return CanvasTextFunctions.draw( ctx, font,size,x,y,text); };
        ctx.measureText = function(font,size,text) { return CanvasTextFunctions.measure( font,size,text); };
        ctx.fontAscent = function(font,size) { return CanvasTextFunctions.ascent(font,size); }
        ctx.fontDescent = function(font,size) { return CanvasTextFunctions.descent(font,size); }

        ctx.drawTextRight = function(font,size,x,y,text) { 
    	var w = CanvasTextFunctions.measure(font,size,text);
    	return CanvasTextFunctions.draw( ctx, font,size,x-w,y,text); 
        };
        ctx.drawTextCenter = function(font,size,x,y,text) { 
    	var w = CanvasTextFunctions.measure(font,size,text);
    	return CanvasTextFunctions.draw( ctx, font,size,x-w/2,y,text); 
        };
    }
    
    // end of canvasText functions
    
    var rulerWidth = 15;
    var lineLength = 10;
    
    var displayWidth = function () {
        return canvas.width - rulerWidth;
    }

    var displayHeight = function () {
        return canvas.height - rulerWidth;
    }
    
    var calcDpi = function (inches) {
        return displayWidth() / inches;
    }

    var dpi = calcDpi(fabricWidth);
    
    var drawRulers = function (ctx, dpi) {
        CanvasTextFunctions.enable(ctx);
        
        // First, draw the yellow ruler boxes
        
        ctx.fillStyle = "rgb(237,228,11)";
        ctx.fillRect(rulerWidth, 0, displayWidth(), rulerWidth);
        ctx.fillRect(0, rulerWidth, rulerWidth, displayHeight());
        ctx.fillStyle = "rgb(255,255,255)";
        ctx.fillRect(0, 0, rulerWidth, rulerWidth);

        ctx.beginPath();
        ctx.moveTo(rulerWidth, 0);
        ctx.lineTo(rulerWidth, rulerWidth);
        {ctx.drawText("sans",8,3,rulerWidth -2,'in.');}

        var odd = true;
        var div_by_four = true
        num_inches = fabricWidth;
        
        // Second, iterate through the top Horizontal bar
        // displaying inch numbers or odd or even hash marks
         
        for (var i = 1; i <= fabricWidth; i += 1) {
          j=i*dpi;
          var inch = i+"";
          
          // We don't always display a number
          if ( (num_inches < 12) || ((num_inches < 28) && (!odd)) || ((!odd) && (div_by_four))) 
          {
            // some fussy formatting adjustments based on the number or number position
            if ((i < 10) && (i != num_inches))
              // move single digits just a bit to the right
              {ctx.drawText("sans",8,j+rulerWidth-4,rulerWidth -2,inch);}
            else if (i != num_inches)
              // move double digit numbers a little to the left
              {ctx.drawText("sans",8,j+rulerWidth-7,rulerWidth -2,inch);}
            else
              // move the last number quite a bit to the left so it isn't truncated by the edge of the canvas
              {ctx.drawText("sans",8,j+rulerWidth-12,rulerWidth -2,inch);}
          }
          else // when we don't display a number, put a hash mark
          {
            // I hacked the font so that the ! is a short hash, the | is a long hash
            ctx.drawText("sans",7,j+rulerWidth-6,rulerWidth -2,(odd ? '!' : '|'));
          }
          odd = !odd;
          if (!odd) {div_by_four = !div_by_four;}
        }
        ctx.stroke();

        ctx.beginPath();
        ctx.moveTo(0, rulerWidth);
        ctx.lineTo(rulerWidth, rulerWidth);

        // Third, iterate through the left Vertical ruler
        // displaying inch numbers or odd or even hash marks
        // very similar to above functionality...

        num_inches = fabricHeight;
        odd = true;
        var div_by_four = true
        for (var i = 1; i <= fabricHeight; i += 1) {
          j=i*dpi;
          var inch = i + "";
          if ( (num_inches < 12) || ((num_inches < 28) && (!odd)) || ((!odd) && (div_by_four))) 
          {
            if ((i<100) && (i != num_inches))
              {ctx.drawText("sans",7, 2, j+rulerWidth,inch);}
            else if (i>=100)
              // squeeze the font down to fit three digits
              {ctx.drawText("sans",6, 0, j+rulerWidth -4,inch);}
            else
              {ctx.drawText("sans",7, 2, j+rulerWidth -4,inch);}          }
          else 
          {
            // I hacked the font so that the - is a short horizontal hash, the _ is long
            ctx.drawText("sans", 7, 0, j+rulerWidth,(odd ? '-' : '_'));
          }
          
          odd = !odd;
          if (!odd) {div_by_four = !div_by_four;}
        }
        ctx.stroke();
    }

    var drawMirror = function (ctx, dpi, imageWidth, imageHeight) {
      var scaledImageWidth = Math.floor(imageWidth * 2 * dpi);
      var scaledImageHeight = Math.floor(imageHeight * 2 * dpi);
      for (var i = rulerWidth; i <= canvas.width - 3; i = i + scaledImageWidth - 1) {
          for (var j = canvas.height; j >= rulerWidth - scaledImageHeight + 3; j = j - scaledImageHeight + 1) {
              ctx.drawImage(image, i, j, scaledImageWidth, scaledImageHeight);
          }
      }
    }

    var drawImageWithMirrorSource = function (ctx, dpi, imageWidth, imageHeight) {
        var origWidth = image.width/2
        var origHeight = image.height/2
        var scaledImageWidth = Math.floor(imageWidth * dpi);
        var scaledImageHeight = Math.floor(imageHeight * dpi);
        
        
        // The -1's are to make IE render without lines between images.
        // The -3 and +3 is to eliminate slivers of repeat when the image is an exact fit to the fabric size
        for (var i = rulerWidth; i <= canvas.width - 3; i = i + scaledImageWidth - 1) {
            for (var j = canvas.height; j >= rulerWidth - scaledImageHeight + 3; j = j - scaledImageHeight + 1) {
                ctx.drawImage(image, 0, origHeight, origWidth, origHeight, i, j, scaledImageWidth, scaledImageHeight);
            }
        }
    }
    
    var drawStep = function (ctx, dpi, imageWidth, imageHeight) {
        var origWidth = image.width/2
        var origHeight = image.height/2      
        var scaledImageWidth = Math.floor(imageWidth * dpi);
        var scaledImageHeight = Math.floor(imageHeight * dpi);
        if (scaledImageHeight % 2 != 0) { scaledImageHeight =  scaledImageHeight + 1; }
        
        var step = ((scaledImageHeight)/2) ;
        var count = 1;
        var IEfix = 0
        
        if (BrowserDetect.browser == "Explorer") { IEfix=1 }
        
        // The -1 is are to make IE render without lines between images.
        
        // The -3 and +3 is to eliminate slivers of repeat when the image is an exact fit to the fabric size
        for (var i = rulerWidth; i <= canvas.width - 3; i = i + (scaledImageWidth - IEfix )) {
            count++;
            for (var j = canvas.height+1; j >= rulerWidth - (2*scaledImageHeight) + 3; j = j - (scaledImageHeight - IEfix )) {
                if ((count % 2) == 0) 
                {
                  ctx.drawImage(image, 0, origHeight, origWidth, origHeight, i, j, scaledImageWidth, scaledImageHeight);
                }
                else
                {
                  ctx.drawImage(image, 0, origHeight, origWidth, origHeight, i, j+step, scaledImageWidth, scaledImageHeight);
                }
            }
        }
    }
    
    var drawBrick = function (ctx, dpi, imageWidth, imageHeight) {
        // Note that we are working with a mirrored image, so it is twice the original height and width
        var origWidth = image.width/2
        var origHeight = image.height/2      
        var scaledImageWidth = Math.floor(imageWidth * dpi);
        var scaledImageHeight = Math.floor(imageHeight * dpi);
        // Step quantity - this must be an integer or a white gap shows, so force by using modulo
        if ((scaledImageWidth % 2) == 0) { var step = scaledImageWidth/2; } else { var step = (scaledImageWidth+1)/2; }                
        
        var count = 0;
        // The -1's are to make IE render without lines between images.
        // The -3 and +3 is to eliminate slivers of repeat when the image is an exact fit to the fabric size
        for (var x = rulerWidth; x < canvas.width + step; x = x + scaledImageWidth) {
          count = 0
            for (var y = canvas.height; y >= rulerWidth - scaledImageHeight + 3; y = y - scaledImageHeight + 1) {
                count++;
                if ((count % 2) == 0) { xpos = x; } else { xpos = x - step; }                
                widthRemaining = canvas.width - xpos;
                if (widthRemaining < scaledImageWidth)
                { 
                  if (widthRemaining >0 )
                  {
                    trimmedWidth = (origWidth * (widthRemaining/scaledImageWidth) ) + 1;
                    ctx.drawImage(image, 0, origHeight, trimmedWidth, origHeight, xpos, y, widthRemaining, scaledImageHeight); 
                  }
                }
                else
                { ctx.drawImage(image, 0, origHeight, origWidth, origHeight, xpos, y, scaledImageWidth, scaledImageHeight); }
            }
        }
    }
    
    var drawBigImage = function (ctx, dpi, imageWidth, imageHeight) {
      var scaledImageWidth = Math.floor(imageWidth * dpi);
      var scaledImageHeight = Math.floor(imageHeight * dpi);
      for (var i = rulerWidth; i <= canvas.width - 3; i = i + scaledImageWidth - 1) {
          for (var j = canvas.height; j >= rulerWidth - scaledImageHeight + 3; j = j - scaledImageHeight + 1) {
              ctx.drawImage(highresimage, i, j, scaledImageWidth, scaledImageHeight);
          }
      }
    }
    
    var drawCentered = function (ctx, dpi, imageWidth, imageHeight, composite_bool) {
        var scaledImageWidth = Math.floor(imageWidth * dpi);
        var scaledImageHeight = Math.floor(imageHeight * dpi);
        var origWidth = image.width/2
        var origHeight = image.height/2      
        i=(canvas.width - scaledImageWidth + rulerWidth)/2
        j=((canvas.height - scaledImageHeight + rulerWidth)/2)
        
        sx= 0;
        sy= origHeight;
        sw= origWidth
        sh= origHeight
        dx= i
        dy= j
        dw= scaledImageWidth
        dh= scaledImageHeight
        // alert('sx, sy, sw, sh, dx, dy, dw, dh: ' + sx + ', ' +sy + ', ' +sw + ', ' + sh + ', ' + dx + ', ' + dy + ', ' + dw + ', ' + dh)
        if (composite_bool>0)
        { 
          ctx.drawImage(compositeImage, dx, dy, dw, dh)
        }
        else
        {
          ctx.drawImage(image, sx, sy, sw, sh, dx, dy, dw, dh)
        }
    }
    
    var drawCenteredvbig = function (ctx, dpi, imageWidth, imageHeight, fabricWidth, fabricHeight) {
  
        
        var scaledImageWidth = Math.floor(imageWidth * dpi);
        var scaledImageHeight = Math.floor(imageHeight * dpi);
        var origWidth = highresimage.width
        var origHeight = highresimage.height      
        i=(canvas.width - scaledImageWidth + rulerWidth)/2
        j=((canvas.height - scaledImageHeight + rulerWidth)/2) 
        imageToCanvasRatio = scaledImageHeight/origHeight
        CanvasToImageRatio = origHeight/scaledImageHeight
        origdpi = CanvasToImageRatio * dpi
        dWidthReduction = 0
        dHeightReduction = 0
        sw = origdpi * fabricWidth
        if (sw > origWidth)
        {
          dWidthReduction = (sw-origWidth)*imageToCanvasRatio
          sw = origWidth
        }
        sh = origdpi * fabricHeight
        if (sh > origHeight)
        {
          dHeightReduction = (sh-origHeight)*imageToCanvasRatio
          sh=origHeight
        }
        sx = (origWidth - sw)/2
        sy = (origHeight - sh)/2

        // var alertmessage = 
        //   "source image height, source image width, " + 
        //   origHeight + ',  ' + origWidth + 
        //   ",\neach pixel in the source image is being stretched to cover " + 
        //    (scaledImageHeight/origHeight) + " pixels in the preview. \n" + 
        //   ", scaledImageHeight, scaledImageWidth " +  scaledImageHeight + ',  ' + scaledImageWidth + 
        //   "\ndpi: there are " + dpi + " pixels on the canvas for each inch marker on the ruler. \n" +
        //   "origdpi: there are " + origdpi + " pixels on the source image for each inch marker on the ruler. imagewidth: " + 
        //   imageWidth + " inches, imageHeight: " + imageHeight + " inches. \n" +
        //   "sx, sy, sw, sh: " + sx + ', ' + sy + ', ' + sw + ', ' + sh +
        //   "\nthe canvas space will be reduce by " + dWidthReduction + " pixels of Width \n" +
        //   "and " + dHeightReduction + " pixels of Height"
        //   alert(alertmessage);
          

        // drawImage(image, sx, sy, sw, sh, dx, dy, dw, dh) s=source image, d=destination on the canvas
        // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#the-canvas-element

        // this version overlays a huge image over a huge canvas, and lets the canvas trim off the stuff over the edges
        // it works, but it shows distortion in excanvas
        // ctx.drawImage(highresimage, 0, 0, origWidth, origHeight, i, j, scaledImageWidth, scaledImageHeight);

        // this version sets out precisely the piece of the source image to display on the full canvas
        ctx.drawImage(highresimage, sx, sy, sw, sh, (dWidthReduction/2)+rulerWidth, (dHeightReduction/2)+rulerWidth, canvas.width - dWidthReduction - rulerWidth, canvas.height - dHeightReduction - rulerWidth);

    }
    var drawComposite = function (ctx, canvasDpi, imageWidth, imageHeight, fabricWidth, compositeRepeats, fabricDpi) {
      

        var origWidth = image.width/compositeRepeats
        var origHeight = image.height/compositeRepeats
        var compositeDpi = (origWidth/(imageWidth * (fabricDpi/150)));
        // var alertmessage = 
        //   "canvasDpi, " + canvasDpi + 
        //   "\ncompositeDpi, " + compositeDpi + 
        //   "\nfabricDpi, " + fabricDpi
        //   
        //   alert(alertmessage);
        
        var scaledCompositeImageWidth = Math.floor((image.width/compositeDpi) * canvasDpi * (150/fabricDpi));
        var scaledCompositeImageHeight = Math.floor((image.height/compositeDpi) * canvasDpi * (150/fabricDpi));

        // var alertmessage = 
        //   "source image height, source image width, " + 
        //   image.height + ',  ' + image.width + 
        //   ", has " + compositeRepeats + ' repeats on the x and y axes. ' +
        //   "\nscaledImageHeight, scaledImageWidth " +  scaledCompositeImageHeight + ',  ' + scaledCompositeImageWidth + 
        //   "\nimagewidth: " + imageWidth + " inches, imageHeight: " + imageHeight + " inches. \n" 
        //   
        //   alert(alertmessage);
       
          sx= 0;
          sy= image.height-(image.height *((canvas.height-rulerWidth)/scaledCompositeImageHeight))
          sw= image.width * ((canvas.width-rulerWidth)/scaledCompositeImageWidth)
          sh= image.height *((canvas.height-rulerWidth)/scaledCompositeImageHeight)
          dx= rulerWidth
          dy= rulerWidth
          dw= canvas.width-rulerWidth
          dh= canvas.height-rulerWidth
          
          // IF THE COMPOSITE IMAGE IS LARGER THAN THE PREVIEW PAGE, THEN 
          // DRAW THE APPROPRIATE PART OF THE COMPOSITE IMAGE ONTO THE PREVIEW
        
          if (sw < image.width && sh < image.height)
          {
            // drawImage(image, sx, sy, sw, sh, dx, dy, dw, dh) s=source image, d=destination on the canvas
            // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#the-canvas-element
            
            // alert('sx, sy, sw, sh, dx, dy, dw, dh: ' + sx + ', ' +sy + ', ' +sw + ', ' + sh + ', ' + dx + ', ' + dy + ', ' + dw + ', ' + dh)
            ctx.drawImage(compositeImage, sx, sy, sw, sh, dx, dy, dw, dh)
          }
          else
          {
            // OTHERWISE LOOP THROUGH A BASIC REPEAT OF THE COMPOSITE AS FOLLOWS.
            // 0,0 ON CANVAS IS UPPER LEFT.  SPOONFLOWER REPEATS FROM LOWER LEFT
            // DRAWIMAGE USES THE UPPER LEFT POINT AS ORIGIN, AND DRAWS DOWN AND TO THE RIGHT
            // SO THE REPEAT LOOP STARTS WITH THE UPPER LEFT POINT OF THE BOTTOM DRAWING
            // AND REPEATS TO THE TOP (X VALUES GOING -DOWN-), AND THEN MOVES OVER ONE
            // AND GOES BOTTOM TO TOP AGAIN      
            for (var i = rulerWidth; i <= canvas.width; i = i + scaledCompositeImageWidth-1) {
                for (var j = canvas.height -scaledCompositeImageHeight ; 
                  j > rulerWidth - scaledCompositeImageHeight; j = j - scaledCompositeImageHeight+1) {
        
                  // var alertmessage = 
                  //      "source image height, source image width, " + 
                  //      image.height + ',  ' + image.width + 
                  //      "\nkeeping in mind this is the upper left corner of the image that will be put on the canvas, \n" +
                  //      "i and j are " + i +', ' + j
                  //      alert(alertmessage);
                    ctx.drawImage(compositeImage, 0, 0, image.width, image.height, i, j, scaledCompositeImageWidth, scaledCompositeImageHeight);
                }
            }
          }
    }
    
    canvas.height = (fabricHeight * dpi) + rulerWidth;
    
    var ctx = canvas.getContext("2d");
    
    //  This is the guts of the previewer...
    // imagewidth, imageheight, and fabricheight are all in inches
    // DPI is the converter; it is the number of pixels 
    // on the browser screen for each inch of fabric
    // represented in the preview.  
    
    // To see the arguments that are being sent to the repeat rendering functions, uncomment the following
    
    // var alertmessage = "dpi: there are " + dpi + " pixels on the canvas for each inch marker on the ruler. imagewidth: " + imageWidth + " inches, imageHeight: " + imageHeight + 
    //     " inches, fabricHeight: " +  fabricHeight + " inches";
    //     alert(alertmessage);    
        
    var origWidth = image.width/2
    var origHeight = image.height/2      
    var scaledImageWidth = Math.floor(imageWidth * dpi);
    var scaledImageHeight = Math.floor(imageHeight * dpi);
    
    // To see original and scaled image dimensions, uncomment the following: 
    
    // var alertmessage = "origHeight, origWidth, " + 
    // origHeight + ',  ' + origWidth + 
    // ", scaledImageHeight, scaledImageWidth " +  scaledImageHeight + ',  ' + scaledImageWidth + 
    // ", each pixel in the preview image is being stretched to cover " + 
    //  (scaledImageHeight/origHeight) + " pixels in the preview."
    // 
    // alert(alertmessage);
    
    // IN ORDER TO SPEED UP THE CANVAS BROWSE, THE PREVIEWER USES COMPOSITE REPEATS THAT ARE
    // GENERATED BY IMAGEMAGICK ON THE SERVER FOR ALL IMAGES SMALLER THAN 4"
    
    
    
    if ( compositeRepeats > 0 )
    { 
      if (repeat == 0)
      {
        drawCentered(ctx, dpi, imageWidth, imageHeight, 1);
        drawRulers(ctx, dpi);
      }
      else
      {
        drawComposite(ctx, dpi, imageWidth, imageHeight, fabricWidth, compositeRepeats, fabricDpi)
        drawRulers(ctx, dpi);
      }      
    }
    else
    {
      if ((scaledImageHeight/origHeight) <= 2)
      {
    
      if (repeat == 4) {drawMirror(ctx, dpi, imageWidth, imageHeight, fabricHeight);}
      if (repeat == 3) {drawBrick(ctx, dpi, imageWidth, imageHeight, fabricHeight);}
      if (repeat == 2) {drawStep(ctx, dpi, imageWidth, imageHeight, fabricHeight);}
      if (repeat == 1) {drawImageWithMirrorSource(ctx, dpi, imageWidth, imageHeight, fabricHeight);}
      if (repeat == 0) {drawCentered(ctx, dpi, imageWidth, imageHeight, 0);}
      drawRulers(ctx, dpi);
      }
      else
      {
        // WHEN WE ARE WORKING WITH A DESIGN OF LARGE DIMENSIONS, ANYTHING GREATER THAN 16", THE PREVIEW GETS 
        // FUZZY WHEN YOU ZOOM IN TO A SMALL FABRIC PIECE, LIKE A SWATCH.  TO AVERT THIS, WE SWITCH TO A HIGH
        // RESOLUTION PREVIEW.
                
        if ((repeat == 4) || (repeat == 3) || (repeat == 2) || (repeat == 1)) {drawBigImage(ctx, dpi, imageWidth, imageHeight, fabricHeight);}
        if (repeat == 0) {drawCenteredvbig (ctx, dpi, imageWidth, imageHeight, fabricWidth, fabricHeight);}
        drawRulers(ctx, dpi);
      }
    }

}