/*
 * $Id: QualityMeter.js 84386 2009-10-01 11:47:48Z k.reimer $
 * Copyright (C) 2006 IP Labs GmbH <http://www.iplabs.de/>
 * All rights reserved.
 */
 
 
/**
 * @fileoverview
 *
 * Contains the QualityMeter class which is used to measure the quality
 * of a picture when rendered on a product.
 *
 * @author Klaus Reimer (k.reimer@iplabs.de)
 * @version $Revision: 84386 $
 */

 
/**
 * @class The QualityMeter class calculates the quality for a picture size
 * printed on a specific product.
 *
 * @constructor 
 *
 * @param printWidth
 *            The width of the print area in millimeter
 * @param printHeight
 *            The height of the print area in millimeter
 */
 
function QualityMeter(printWidth, printHeight)
{
    this.printWidth = printWidth;
    this.printHeight = printHeight;
}


/**
 * If the orientation of the picture can be rotated. For products like 
 * normal prints this parameter should be set to true. For products like 
 * Mousepads it may be set to false. Always depends on how the finisher handles
 * an orientation-mismatch.
 *
 * @type Boolean
 */
QualityMeter.prototype.rotatable = true;

/** The dots-per-meter setting of the product. @type Integer*/
QualityMeter.prototype.dpm = 10000;

/**
 * A factor with which the calculated "best size" is multiplied to allow 
 * quality level fine tuning.
 *
 * @type Integer
 */
QualityMeter.prototype.coefficient = 1.0;

/** The print area width in millimeters. @type Integer */
QualityMeter.prototype.printWidth = null;

/** The print area height in millimeters. @type Integer */
QualityMeter.prototype.printHeight = null;

/** If fill-in should be used instead of fit-in. @type Boolean */
QualityMeter.prototype.fillIn = false;


/**
 * Calculates the quality in percent.
 *
 * @param {Integer} pictureWidth
 *            The picture width in pixels
 * @param {Integer} pictureHeight
 *            The picture height in pixels
 * @param {Integer} printWidth
 *            The print width in millimeter
 * @param {Integer} printHeight
 *            The print height in millimeter
 * @param {Boolean} rotatable
 *            If the orientation of the picture can be rotated. Optional 
 *            parameter, defaults to true. For products like normal prints this
 *            parameter should be set to true. For products like Mousepads
 *            it may be set to false. Always depends on how the finisher handles
 *            an orientation-mismatch
 * @param {Integer} dpm
 *            The dots-per-meter setting of the product. Optional parameter,
 *            defaults to 10000
 * @param {Boolean} fillIn
 *            If fillIn should be used instead of fitIn. Optional parameter,
 *            defaults to false
 * @param {Float} coefficient
 *            A factor with which the calculated "best size" is multiplied
 *            to allow quality level fine tuning. Optional parameter, defaults
 *            to 1.0
 * @return {Integer}
 *            The quality in percent
 */
 
QualityMeter.getQualityPercent = function(pictureWidth, pictureHeight, 
    printWidth, printHeight, rotatable, dpm, fillIn, coefficient)
{
    var qualityMeter = new QualityMeter(printWidth, printHeight);
    if (rotatable !== undefined)
    {
        qualityMeter.rotatable = rotatable;
    }
    if (dpm !== undefined)
    {
        qualityMeter.dpm = dpm;
    }
    if (coefficient !== undefined)
    {
        qualityMeter.coefficient = coefficient;
    }
    if (fillIn !== undefined)
    {
        qualityMeter.fillIn = fillIn;
    }
    
    return qualityMeter.getQualityPercent(pictureWidth, pictureHeight);
};
 

/**
 * Calculates the quality in percent.
 *
 * @param {Integer} pictureWidth
 *            The picture width in pixels
 * @param {Integer} pictureHeight
 *            The picture height in pixels
 * @return {Integer}
 *            The quality in percent
 */
 
QualityMeter.prototype.getQualityPercent = function(pictureWidth, pictureHeight)
{
    var bestSize, currentSize;
    
    // Rotate picture if needed and allowed
    if (this.rotatable && (
        ((pictureWidth > pictureHeight) && (this.printWidth < this.printHeight))
        ||
        ((pictureWidth < pictureHeight) && (this.printWidth > this.printHeight))))
    {
        var tmp = pictureWidth;
        pictureWidth = pictureHeight;
        pictureHeight = tmp;
    }
    
    // Determine if width or height should be used for quality calculation
    // and also calculate the best width/height.
    if ((!this.fillIn &&
        ((pictureWidth / this.printWidth) > (pictureHeight / this.printHeight)))
        || (this.fillIn &&
        ((pictureWidth / this.printWidth) < (pictureHeight / this.printHeight))))
    {
        bestSize = this.printWidth * this.dpm / 1000;
        currentSize = pictureWidth;
    }
    else
    {
        bestSize = this.printHeight * this.dpm / 1000;
        currentSize = pictureHeight;
    }
    
    // Apply coefficient
    bestSize *= this.coefficient;
    
    // Return the quality percent (coverage of picture on optimal print area)
    return 100 * currentSize / bestSize;
};


/**
 * Calculates the quality level.
 *
 * @param {Integer} pictureWidth
 *            The picture width in pixels
 * @param {Integer} pictureHeight
 *            The picture height in pixels
 * @param {Integer} printWidth
 *            The print width in millimeter
 * @param {Integer} printHeight
 *            The print height in millimeter
 * @param {Boolean} rotatable
 *            If the orientation of the picture can be rotated. Optional 
 *            parameter, defaults to true. For products like normal prints this
 *            parameter should be set to true. For products like Mousepads
 *            it may be set to false. Always depends on how the finisher handles
 *            an orientation-mismatch
 * @param {Integer} dpm
 *            The dots-per-meter setting of the product. Optional parameter,
 *            defaults to 10000
 * @param {Boolean} fillIn
 *            If fillIn should be used instead of fitIn. Optional parameter,
 *            defaults to false
 * @param {Float} coefficient
 *            A factor with which the calculated "best size" is multiplied
 *            to allow quality level fine tuning. Optional parameter, defaults
 *            to 1.0
 * @return {Integer}
 *            The quality level
 */
 
QualityMeter.getQualityLevel = function(pictureWidth, pictureHeight, 
    printWidth, printHeight, rotatable, dpm, fillIn, coefficient)
{
    var qualityMeter = new QualityMeter(printWidth, printHeight);
    if (rotatable !== undefined)
    {
        qualityMeter.rotatable = rotatable;
    }
    if (dpm !== undefined)
    {
        qualityMeter.dpm = dpm;
    }
    if (coefficient !== undefined)
    {
        qualityMeter.coefficient = coefficient;
    }
    if (fillIn !== undefined)
    {
        qualityMeter.fillIn = fillIn;
    }
    
    return qualityMeter.getQualityLevel(pictureWidth, pictureHeight);
};
 

/**
 * Calculates the quality level. For this it needs the global array
 * qualityLevels which includes the border percent values between the
 * quality levels. "0" is always the worst quality. The maximum quality
 * level is defined by the qualityLevels table. So if the table includes
 * the percent values "50" and "100", then the quality model has three levels
 * (0-2).
 *
 * @param {Integer} pictureWidth
 *            The picture width in pixels
 * @param {Integer} pictureHeight
 *            The picture height in pixels
 * @return {Integer}
 *            The quality level
 */
 
QualityMeter.prototype.getQualityLevel = function(pictureWidth, pictureHeight)
{
    var level, max;
    var percent;
    
    percent = this.getQualityPercent(pictureWidth, pictureHeight);
    for (level = 0, max = qualityLevels.length; level < max; level++)
    {
        if (qualityLevels[level] > percent)
        {
            return level;
        }
    } 
    return level;
};
