/*
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License, version 2.1 as published by the Free Software
* Foundation.
*
* You should have received a copy of the GNU Lesser General Public License along with this
* program; if not, you can obtain a copy at http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html
* or from the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* Copyright (c) 2001 - 2013 Object Refinery Ltd, Pentaho Corporation and Contributors.. All rights reserved.
*/
package org.pentaho.reporting.libraries.pixie.wmf.records;
import org.pentaho.reporting.libraries.pixie.wmf.MfRecord;
import org.pentaho.reporting.libraries.pixie.wmf.WmfFile;
import java.awt.*;
/**
* This is the base class for all WMF-Records. A WMF record specifies a single command for drawing a element of the
* image.
*/
public abstract class MfCmd {
/**
* The X-Scale for the command.
*/
private float scaleX;
/**
* The Y-Scale for the command.
*/
private float scaleY;
/**
* The default constructor, adjusts the scale to 1.
*/
protected MfCmd() {
scaleX = 1;
scaleY = 1;
}
/**
* Creates a new record based on the data stored in the MfCommand.
*
* @return the created record.
* @throws RecordCreationException if an error occured while generating the record.
*/
public abstract MfRecord getRecord()
throws RecordCreationException;
/**
* Reads the command data from the given record and adjusts the internal parameters according to the data parsed.
* <p/>
* After the raw record was read from the datasource, the record is parsed by the concrete implementation.
*
* @param record the raw data that makes up the record.
*/
public abstract void setRecord( MfRecord record );
/**
* Reads the function identifier. Every record type is identified by a function number corresponding to one of the
* Windows GDI functions used.
*
* @return the function identifier.
*/
public abstract int getFunction();
/**
* Creates a empty unintialized copy of this command implementation.
*
* @return a new instance of the command.
*/
public abstract MfCmd getInstance();
/**
* Replays the command on the given WmfFile.
*
* @param metafile the meta file.
*/
public abstract void replay( WmfFile metafile );
/**
* Set the scale for the command.
*
* @param scaleX the horizontal scale
* @param scaleY the vertical scale
*/
public void setScale( final float scaleX, final float scaleY ) {
final float oldScaleX = this.scaleX;
final float oldScaleY = this.scaleY;
this.scaleX = scaleX;
this.scaleY = scaleY;
if ( oldScaleX != scaleX ) {
scaleXChanged();
}
if ( oldScaleY != scaleY ) {
scaleYChanged();
}
}
/**
* A callback function to inform the object, that the x scale has changed and the internal coordinate values have to
* be adjusted.
*/
protected abstract void scaleXChanged();
/**
* A callback function to inform the object, that the y scale has changed and the internal coordinate values have to
* be adjusted.
*/
protected abstract void scaleYChanged();
/**
* Scales the given rectangle.
*
* @param r the source rectangle.
* @return a new rectangle containing the scaled values.
*/
protected Rectangle scaleRect( final Rectangle r ) {
final Rectangle retval = new Rectangle();
retval.x = getScaledX( r.x );
retval.y = getScaledY( r.y );
retval.width = getScaledWidth( r.width );
retval.height = getScaledHeight( r.height );
return retval;
}
/**
* Scales the given horizontal length and makes sure that the lenght is at least 1.
*
* @param length the value that should be scaled.
* @return the scaled value.
*/
protected int getScaledWidth( int length ) {
if ( length == 0 ) {
return 1;
}
length = (int) ( length * scaleX + 0.5f );
return ( length == 0 ) ? 1 : length;
}
/**
* Scales the given vertical length and makes sure that the lenght is at least 1.
*
* @param length the value that should be scaled.
* @return the scaled value.
*/
protected int getScaledHeight( int length ) {
if ( length == 0 ) {
return 1;
}
length = (int) ( length * scaleY + 0.5f );
return ( length == 0 ) ? 1 : length;
}
/**
* Applies the new x-scaling to all values in the array n and places the values in the array dest. Additionally dest
* is also returned as return value.
*
* @param n the unscaled source values
* @param dest the array to store the scaled values
* @return dest.
*/
protected int[] applyScaleX( final int[] n, int[] dest ) {
if ( dest == null ) {
dest = new int[ n.length ];
} else if ( dest.length < n.length ) {
dest = new int[ n.length ];
}
for ( int i = 0; i < n.length; i++ ) {
dest[ i ] = (int) ( n[ i ] * scaleX + 0.5f );
}
return dest;
}
/**
* Applies the new y-scaling to all values in the array n and places the values in the array dest. Additionally dest
* is also returned as return value.
*
* @param n the unscaled source values
* @param dest the array to store the scaled values
* @return dest.
*/
protected int[] applyScaleY( final int[] n, int[] dest ) {
if ( dest == null ) {
dest = new int[ n.length ];
} else if ( dest.length < n.length ) {
dest = new int[ n.length ];
}
for ( int i = 0; i < n.length; i++ ) {
dest[ i ] = (int) ( n[ i ] * scaleY + 0.5f );
}
return dest;
}
/**
* Return integer scaled to output units.
*
* @param y the unscaled y
* @return the scaled y value
*/
public int getScaledY( final int y ) {
return (int) ( y * scaleY + 0.5f );
}
/**
* Return integer scaled to output units.
*
* @param x the unscaled x
* @return the scaled x value
*/
public int getScaledX( final int x ) {
return (int) ( x * scaleX + 0.5f );
}
}