/*
* 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.MfLogFont;
import org.pentaho.reporting.libraries.pixie.wmf.MfRecord;
import org.pentaho.reporting.libraries.pixie.wmf.MfType;
import org.pentaho.reporting.libraries.pixie.wmf.WmfFile;
import java.awt.*;
/**
* The CreateFontIndirect function creates a logical font that has the specified characteristics. The font can
* subsequently be selected as the current font for any device context.
* <p/>
* <code> typedef struct tagLOGFONT { LONG lfHeight; LONG lfWidth; LONG lfEscapement; LONG lfOrientation; LONG lfWeight;
* BYTE lfItalic; BYTE lfUnderline; BYTE lfStrikeOut; BYTE lfCharSet; BYTE lfOutPrecision; BYTE lfClipPrecision; BYTE
* lfQuality; BYTE lfPitchAndFamily; TCHAR lfFaceName[LF_FACESIZE]; } LOGFONT, *PLOGFONT; </code>
*/
public final class MfCmdCreateFont extends MfCmd {
public static final int CHARSET_ANSI = 0;
public static final int CHARSET_DEFAULT = 1;
public static final int CHARSET_SYMBOL = 2;
public static final int CHARSET_SHIFTJIS = 128;
public static final int CHARSET_OEM = 255;
private static final int FONT_FACE_MAX = 31;
private static final int FIXED_RECORD_SIZE = 9;
private static final int POS_HEIGHT = 0;
private static final int POS_WIDTH = 1;
private static final int POS_ESCAPEMENT = 2;
private static final int POS_ORIENTATION = 3;
private static final int POS_WEIGHT = 4;
private static final int POS_FLAGS1 = 5;
private static final int POS_FLAGS2 = 6;
private static final int POS_PRECISION = 7;
private static final int POS_QUALITY = 8;
private static final int POS_FONTFACE = 9;
private int height;
private int width;
private int scaled_height;
private int scaled_width;
private int escapement;
private int orientation;
private int weight;
private boolean italic;
private boolean underline;
private boolean strikeout;
private int charset;
private int outprecision;
private int clipprecision;
private int quality;
private int pitchAndFamily;
private String facename;
public MfCmdCreateFont() {
}
/**
* Replays the command on the given WmfFile.
*
* @param file the meta file.
*/
public void replay( final WmfFile file ) {
final MfLogFont lfont = new MfLogFont();
lfont.setFace( getFontFace() );
lfont.setSize( getScaledHeight() );
int style;
// should be bold ?
if ( getWeight() > 650 ) {
style = Font.BOLD;
} else {
style = Font.PLAIN;
}
if ( isItalic() ) {
style += Font.ITALIC;
}
lfont.setStyle( style );
lfont.setUnderline( isUnderline() );
lfont.setStrikeOut( isStrikeout() );
lfont.setRotation( getEscapement() / 10 );
file.getCurrentState().setLogFont( lfont );
file.storeObject( lfont );
}
/**
* Creates a empty unintialized copy of this command implementation.
*
* @return a new instance of the command.
*/
public MfCmd getInstance() {
return new MfCmdCreateFont();
}
/**
* Creates a new record based on the data stored in the MfCommand.
*
* @return the created record.
*/
public MfRecord getRecord() {
String fontFace = getFontFace();
if ( fontFace.length() > FONT_FACE_MAX ) {
fontFace = fontFace.substring( 0, FONT_FACE_MAX );
}
final MfRecord record = new MfRecord( FIXED_RECORD_SIZE + fontFace.length() );
record.setParam( POS_HEIGHT, getHeight() );
record.setParam( POS_WIDTH, getWidth() );
record.setParam( POS_ESCAPEMENT, getEscapement() );
record.setParam( POS_ORIENTATION, getOrientation() );
record.setParam( POS_WEIGHT, getWeight() );
record.setParam( POS_FLAGS1, formFlags( isUnderline(), isItalic() ) );
record.setParam( POS_FLAGS2, formFlags( isStrikeout(), false ) + getCharset() );
record.setParam( POS_PRECISION, getOutputPrecision() << 8 + getClipPrecision() );
record.setParam( POS_QUALITY, getQuality() << 8 + getPitchAndFamily() );
record.setStringParam( POS_FONTFACE, fontFace );
return record;
}
public void setRecord( final MfRecord record ) {
int height = record.getParam( POS_HEIGHT );
if ( height == 0 ) {
// a default height is requested, we use a default height of 10
height = 10;
}
if ( height < 0 ) {
// windows specifiy font mapper matching, ignored.
height *= -1;
}
final int width = record.getParam( POS_WIDTH );
final int escape = record.getParam( POS_ESCAPEMENT );
final int orientation = record.getParam( POS_ORIENTATION );
final int weight = record.getParam( POS_WEIGHT );
final int italic = record.getParam( POS_FLAGS1 ) & 0x00FF;
final int underline = record.getParam( POS_FLAGS1 ) & 0xFF00;
final int strikeout = record.getParam( POS_FLAGS2 ) & 0x00FF;
final int charset = record.getParam( POS_FLAGS2 ) & 0xFF00;
final int outprec = record.getParam( POS_PRECISION ) & 0x00FF;
final int clipprec = record.getParam( POS_PRECISION ) & 0xFF00;
final int quality = record.getParam( POS_QUALITY ) & 0x00FF;
final int pitch = record.getParam( POS_QUALITY ) & 0xFF00;
// A fontname must not exceed the length of 32 including the null-terminator
final String facename = record.getStringParam( POS_FONTFACE, 32 );
setCharset( charset );
setClipPrecision( clipprec );
setEscapement( escape );
setFontFace( facename );
setHeight( height );
setItalic( italic != 0 );
setOrientation( orientation );
setOutputPrecision( outprec );
setPitchAndFamily( pitch );
setQuality( quality );
setStrikeout( strikeout != 0 );
setUnderline( underline != 0 );
setWeight( weight );
setWidth( width );
}
private int formFlags( final boolean f1, final boolean f2 ) {
int retval = 0;
if ( f1 ) {
retval += 0x0100;
}
if ( f2 ) {
retval += 1;
}
return ( retval );
}
/**
* 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 int getFunction() {
return MfType.CREATE_FONT_INDIRECT;
}
public void setFontFace( final String facename ) {
this.facename = facename;
}
public String getFontFace() {
return facename;
}
public void setPitchAndFamily( final int pitchAndFamily ) {
this.pitchAndFamily = pitchAndFamily;
}
public int getPitchAndFamily() {
return pitchAndFamily;
}
public void setQuality( final int quality ) {
this.quality = quality;
}
public int getQuality() {
return quality;
}
public void setClipPrecision( final int clipprecision ) {
this.clipprecision = clipprecision;
}
public int getClipPrecision() {
return clipprecision;
}
public void setOutputPrecision( final int outprecision ) {
this.outprecision = outprecision;
}
public int getOutputPrecision() {
return outprecision;
}
public void setCharset( final int charset ) {
this.charset = charset;
}
public int getCharset() {
return charset;
}
public void setHeight( final int height ) {
this.height = height;
scaleYChanged();
}
public int getHeight() {
return height;
}
public int getScaledHeight() {
return scaled_height;
}
public void setWidth( final int width ) {
this.width = width;
scaleXChanged();
}
/**
* A callback function to inform the object, that the x scale has changed and the internal coordinate values have to
* be adjusted.
*/
protected void scaleXChanged() {
scaled_width = getScaledX( width );
}
/**
* A callback function to inform the object, that the y scale has changed and the internal coordinate values have to
* be adjusted.
*/
protected void scaleYChanged() {
scaled_height = getScaledY( height );
}
public int getWidth() {
return width;
}
public int getScaledWidth() {
return scaled_width;
}
// in 1/10 degrees
public void setEscapement( final int escapement ) {
this.escapement = escapement;
}
public int getEscapement() {
return escapement;
}
// in 1/10 degrees
public void setOrientation( final int orientation ) {
this.orientation = orientation;
}
public int getOrientation() {
return orientation;
}
// 200 = narrow
// 400 = normal
// 700 = bold
public void setWeight( final int weight ) {
this.weight = weight;
}
public int getWeight() {
return weight;
}
public void setItalic( final boolean italic ) {
this.italic = italic;
}
public boolean isItalic() {
return this.italic;
}
public void setUnderline( final boolean ul ) {
this.underline = ul;
}
public boolean isUnderline() {
return this.underline;
}
public void setStrikeout( final boolean so ) {
this.strikeout = so;
}
public boolean isStrikeout() {
return this.strikeout;
}
public String toString() {
final StringBuffer b = new StringBuffer();
b.append( "[CREATE_FONT] face=" );
b.append( getFontFace() );
b.append( " height=" );
b.append( getHeight() );
b.append( " width=" );
b.append( getWidth() );
b.append( " weight=" );
b.append( getWeight() );
b.append( " italic=" );
b.append( isItalic() );
b.append( " Strikeout=" );
b.append( isStrikeout() );
b.append( " Underline=" );
b.append( isUnderline() );
b.append( " outprecision=" );
b.append( getOutputPrecision() );
b.append( " escapement=" );
b.append( getEscapement() );
return b.toString();
}
}