MetafileHelper.java
/*
** Module : MetafileHelper.java
** Abstract : Helper class to provide report generation from generic GUI metafile.
**
** Copyright (c) 2019-2024, Golden Code Development Corporation.
**
** -#- -I- --Date-- --------------------------------------Description---------------------------------------
** 001 EVL 20190510 Created initial version.
** 002 EVL 20190618 Removed printDoc and sendOptionalText from metafile extension set.
** 003 EVL 20201216 Added more clean up for metafile stop/interrupt processing.
** EVL 20210106 Added code to properly finalize the metafile recording.
** EVL 20210107 Added new helper methods to get current temporary directory and reset text styles.
** EVL 20210113 Added new helper method to calculate text scaling factor.
** EVL 20210114 Changed to use common constant from Xpr2PdfWorker.
** EVL 20210602 Added setPageOrientation(character) method.
** GES 20210610 Added setTextStyle(character) method.
** EVL 20211021 Making small improvement for text width calculation with Arial font.
** EVL 20211026 Changing text font size type to float.
** EVL 20211115 Improved handling of the ' ' char weight while text width calculation.
** EVL 20220126 Some fixes for text width calculation approach.
** EVL 20220127 Adding method to get current text underline attribute. Fix text width for certain very
** narrow chars.
** EVL 20220227 More separations for wide, extra wide and regular characters fro capital letters.
** EVL 20220228 Adding methods version with 4GL compatible input parameters types.
** EVL 20220302 Moving here the additional processing for bold and italic fonts.
** EVL 20220314 Adding two more characters to very narrow character set for weight calculation.
** EVL 20220315 Reviewed printable characters size based on general sample and changes some sets to
** increase match and precision.
** 004 DDF 20230620 Replaced static initialization of values from the directory configuration with
** a method called at server bootstrap.
** 005 EVL 20240730 Adding ability to have preview only instead of real file downloading.
*/
/*
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU Affero General Public License as
** published by the Free Software Foundation, either version 3 of the
** License, or (at your option) any later version.
**
** 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 Affero General Public License for more details.
**
** You may find a copy of the GNU Affero GPL version 3 at the following
** location: https://www.gnu.org/licenses/agpl-3.0.en.html
**
** Additional terms under GNU Affero GPL version 3 section 7:
**
** Under Section 7 of the GNU Affero GPL version 3, the following additional
** terms apply to the works covered under the License. These additional terms
** are non-permissive additional terms allowed under Section 7 of the GNU
** Affero GPL version 3 and may not be removed by you.
**
** 0. Attribution Requirement.
**
** You must preserve all legal notices or author attributions in the covered
** work or Appropriate Legal Notices displayed by works containing the covered
** work. You may not remove from the covered work any author or developer
** credit already included within the covered work.
**
** 1. No License To Use Trademarks.
**
** This license does not grant any license or rights to use the trademarks
** Golden Code, FWD, any Golden Code or FWD logo, or any other trademarks
** of Golden Code Development Corporation. You are not authorized to use the
** name Golden Code, FWD, or the names of any author or contributor, for
** publicity purposes without written authorization.
**
** 2. No Misrepresentation of Affiliation.
**
** You may not represent yourself as Golden Code Development Corporation or FWD.
**
** You may not represent yourself for publicity purposes as associated with
** Golden Code Development Corporation, FWD, or any author or contributor to
** the covered work, without written authorization.
**
** 3. No Misrepresentation of Source or Origin.
**
** You may not represent the covered work as solely your work. All modified
** versions of the covered work must be marked in a reasonable way to make it
** clear that the modified work is not originating from Golden Code Development
** Corporation or FWD. All modified versions must contain the notices of
** attribution required in this license.
*/
package com.goldencode.p2j.reporting;
import com.goldencode.p2j.security.*;
import com.goldencode.p2j.ui.client.*;
import com.goldencode.p2j.util.*;
import java.io.*;
/**
* A helper class to convert and show a generic GDI metafile as a PDF document. This replacement is platform
* neutral (not dependent upon WIN32).
*/
public class MetafileHelper
{
/** Base units is inches constant. */
private static final int UNITS_INCHES = 0;
/** Base units is cm constant. */
private static final int UNITS_CM = 1;
/** Base units is mm constant. */
private static final int UNITS_MM = 2;
/** Row modifier to convert XPR helper row coords to pixel. */
private static double pixPerRow = XprHelper.getRow2Pix(Xpr2PdfWorker.DPI_DEFAULT,
XprEntity.LPI_DEFAULT);
/** Column modifier to convert XPR helper character coords to pixel. */
private static double pixPerCol = XprHelper.getCol2Pix(Xpr2PdfWorker.DPI_DEFAULT,
XprEntity.CPI_DEFAULT);
/** Base units type, inches, cm or mm. */
private static int units = UNITS_CM;
/** Stores context-local state variables. */
private static ContextContainer work = new ContextContainer();
/** Flag to open real file or make preview. */
private static boolean openFile = true;
/**
* Method called at server bootstrap that initializes values from the directory
* configuration. Until this method is called, default values are used.
*/
public static void bootstrap()
{
// several options can be overridden in directory
// metafile units override
String unitsOverride = Utils.getDirectoryNodeString(null, "metafile-report/units", null,
Utils.DirScope.BOTH, null);
if (unitsOverride != null && !unitsOverride.isEmpty())
{
if(unitsOverride.equalsIgnoreCase("INCHES"))
{
units = UNITS_INCHES;
}
else if(unitsOverride.equalsIgnoreCase("MM"))
{
units = UNITS_MM;
}
else if(unitsOverride.equalsIgnoreCase("CM"))
{
units = UNITS_CM;
}
}
}
/**
* Sets new values for text alignment.
*
* @param horizAlign
* The new String value for horizontal text alignment. The valid alignment values:
* "left", "center", "right".
* @param vertAlign
* The new String value for vertical text alignment. The valid alignment values:
* "top", "baseline", "bottom".
*/
public static void setTextAlignment(String horizAlign, String vertAlign)
{
resolveCurrentMetafile().setTextAlignment(horizAlign, vertAlign);
}
/**
* Sets new values for text alignment.
*
* @param horizAlign
* The new String value for horizontal text alignment. The valid alignment values:
* "left", "center", "right".
* @param vertAlign
* The new String value for vertical text alignment. The valid alignment values:
* "top", "baseline", "bottom".
*/
public static void setTextAlignment(character horizAlign, String vertAlign)
{
if (isParameterValid(horizAlign))
{
setTextAlignment(horizAlign.getValue(), vertAlign);
}
}
/**
* Sets new values for text alignment.
*
* @param horizAlign
* The new String value for horizontal text alignment. The valid alignment values:
* "left", "center", "right".
* @param vertAlign
* The new String value for vertical text alignment. The valid alignment values:
* "top", "baseline", "bottom".
*/
public static void setTextAlignment(String horizAlign, character vertAlign)
{
if (isParameterValid(vertAlign))
{
setTextAlignment(horizAlign, vertAlign.getValue());
}
}
/**
* Sets new values for text alignment.
*
* @param horizAlign
* The new String value for horizontal text alignment. The valid alignment values:
* "left", "center", "right".
* @param vertAlign
* The new String value for vertical text alignment. The valid alignment values:
* "top", "baseline", "bottom".
*/
public static void setTextAlignment(character horizAlign, character vertAlign)
{
if (isParameterValid(horizAlign) && isParameterValid(vertAlign))
{
setTextAlignment(horizAlign.getValue(), vertAlign.getValue());
}
}
/**
* Sets new current color value to be used in text primitives.
*
* @param rgbColor
* The new 32-bit color value packed in int value.
*/
public static void setTextColor(int rgbColor)
{
resolveCurrentMetafile().setTextColor(rgbColor);
}
/**
* Sets new current color value to be used in text primitives.
*
* @param rgbColor
* The new 32-bit color value packed in int value.
*/
public static void setTextColor(integer rgbColor)
{
if (isParameterValid(rgbColor))
{
setTextColor(rgbColor.intValue());
}
}
/**
* Sets new value for text style.
*
* @param style
* The new String value for the current text style. The valid style values:
* "italic", "underline", "bold", "no-italic", "no-underline", "no-bold".
*/
public static void setTextStyle(String style)
{
resolveCurrentMetafile().setTextStyle(style);
}
/**
* Sets new value for text style.
*
* @param style
* The new String value for the current text style. The valid style values:
* "italic", "underline", "bold", "no-italic", "no-underline", "no-bold".
*/
public static void setTextStyle(character style)
{
if (style == null || style.isUnknown())
{
return;
}
setTextStyle(style.toStringMessage());
}
/**
* Gets flag meaning underlined text should be currently used.
*
* @return <code>TRUE</code> if text underlined, <code>FALSE</code> otherwise.
*/
public static boolean isUnderline()
{
return resolveCurrentMetafile().isUnderline();
}
/**
* Resets new value for text style to be off.
*/
public static void resetTextStyle()
{
resolveCurrentMetafile().resetTextStyle();
}
/**
* Starts the new page construction for the document that is currently processing.
*/
public static void startNewPage()
{
resolveCurrentMetafile().startNewPage();
}
/**
* Sets new value for current font.
*
* @param fontName
* The new String value for the current font name. Can be "default" for default
* font to use.
*/
public static void setFont(String fontName)
{
resolveCurrentMetafile().setFont(fontName);
}
/**
* Sets new value for current font.
*
* @param fontName
* The new String value for the current font name. Can be "default" for default
* font to use.
*/
public static void setFont(character fontName)
{
if (isParameterValid(fontName))
{
setFont(fontName.getValue());
}
}
/**
* Gets the current font value.
*
* @param fontName
* The value for the font name currently in use.
*/
public static void getFont(character fontName)
{
resolveCurrentMetafile().getFont(fontName);
}
/**
* Sets new value for current zoom factor.
*
* @param zoomType
* The new String value for the current zoom type.
*/
public static void setZoomFactor(String zoomType)
{
resolveCurrentMetafile().setZoomFactor(zoomType);
}
/**
* Sets new value for current zoom factor.
*
* @param zoomType
* The new String value for the current zoom type.
*/
public static void setZoomFactor(character zoomType)
{
if (isParameterValid(zoomType))
{
setZoomFactor(zoomType.getValue());
}
}
/**
* Gets the current zoom factor value.
*
* @param zoomType
* The value for the zoom type currently in use.
*/
public static void getZoomFactor(character zoomType)
{
resolveCurrentMetafile().getZoomFactor(zoomType);
}
/**
* Gets the current font height value.
*
* @param fontHeight
* The currently used font height value in metric units.
*/
public static void getFontHeight(decimal fontHeight)
{
resolveCurrentMetafile().getFontHeight(fontHeight);
}
/**
* Sets the current font height value.
*
* @param fontHeight
* The font height value in pics to use.
*/
public static void setFontHeight(float fontHeight)
{
resolveCurrentMetafile().setFontHeight(fontHeight);
}
/**
* Sets the current font height value.
*
* @param fontHeight
* The font height value in pics to use.
*/
public static void setFontHeight(integer fontHeight)
{
if (isParameterValid(fontHeight))
{
setFontHeight(fontHeight.intValue());
}
}
/**
* Gets the given text width value.
*
* @param textToMeasure
* The text to calculate width.
* @param textWidth
* The width of the text in metric units.
*/
public static void getTextWidth(String textToMeasure, decimal textWidth)
{
resolveCurrentMetafile().getTextWidth(textToMeasure, textWidth);
}
/**
* Gets the given text width value.
*
* @param textToMeasure
* The text to calculate width.
* @param textWidth
* The width of the text in metric units.
*/
public static void getTextWidth(character textToMeasure, decimal textWidth)
{
if (isParameterValid(textToMeasure))
{
getTextWidth(textToMeasure.getValue(), textWidth);
}
}
/**
* Sets the new current position for cursor. Can be used a starting point for text/line/image
* draw.
*
* @param x
* The new X position.
* @param y
* The new Y position.
*/
public static void setXY(double x, double y)
{
resolveCurrentMetafile().setXY(x, y);
}
/**
* Sets the new current position for cursor. Can be used a starting point for text/line/image
* draw.
*
* @param x
* The new X position.
* @param y
* The new Y position.
*/
public static void setXY(decimal x, decimal y)
{
if (isParameterValid(x) && isParameterValid(y))
{
setXY(x.doubleValue(), y.doubleValue());
}
}
/**
* Sets the new current position for cursor. Can be used a starting point for text/line/image
* draw.
*
* @param x
* The new X position.
* @param y
* The new Y position.
*/
public static void setXY(double x, decimal y)
{
if (isParameterValid(y))
{
setXY(x, y.doubleValue());
}
}
/**
* Sets the new current position for cursor. Can be used a starting point for text/line/image
* draw.
*
* @param x
* The new X position.
* @param y
* The new Y position.
*/
public static void setXY(decimal x, double y)
{
if (isParameterValid(x))
{
setXY(x.doubleValue(), y);
}
}
/**
* Sets the new value for document's left margin.
*
* @param leftMargin
* The new left margin value.
*/
public static void setLeftMargin(double leftMargin)
{
resolveCurrentMetafile().setLeftMargin(leftMargin);
}
/**
* Sets the new value for document's left margin.
*
* @param leftMargin
* The new left margin value.
*/
public static void setLeftMargin(decimal leftMargin)
{
if (isParameterValid(leftMargin))
{
setLeftMargin(leftMargin.doubleValue());
}
}
/**
* Gets the new current position for cursor. Can be used a starting point for text/line/image
* draw.
*
* @param x
* The returned X position.
* @param y
* The returned Y position.
*/
public static void getXY(decimal x, decimal y)
{
resolveCurrentMetafile().getXY(x, y);
}
/**
* Starts new line of the text. Y coord will be shifted by the text height and interleaving,
* X coored be set to leftmost point of the text.
*/
public static void startNewTextLine()
{
resolveCurrentMetafile().startNewTextLine();
}
/**
* Sets the extra vertical space between two sequential rows.
*
* @param extraYSpace
* The new extra Y distance between rows.
*/
public static void setInterleaving(double extraYSpace)
{
resolveCurrentMetafile().setInterleaving(extraYSpace);
}
/**
* Sets the extra vertical space between two sequential rows.
*
* @param extraYSpace
* The new extra Y distance between rows.
*/
public static void setInterleaving(decimal extraYSpace)
{
if (isParameterValid(extraYSpace))
{
setInterleaving(extraYSpace.doubleValue());
}
}
/**
* Gets the free space below the current Y position.
*
* @param freeSpaceDown
* The remaining vertical free space on the current page.
*/
public static void getFreeSpaceDown(decimal freeSpaceDown)
{
resolveCurrentMetafile().getFreeSpaceDown(freeSpaceDown);
}
/**
* Gets the free space to the right the current X position.
*
* @param freeSpaceRight
* The remaining horizontal free space on the current line(page).
*/
public static void getFreeSpaceRight(decimal freeSpaceRight)
{
resolveCurrentMetafile().getFreeSpaceRight(freeSpaceRight);
}
/**
* Draws the text at current position.
*
* @param text
* The new text to draw at current position.
*/
public static void drawText(String text)
{
resolveCurrentMetafile().drawText(text);
}
/**
* Draws the text at current position.
*
* @param text
* The new text to draw at current position.
*/
public static void drawText(character text)
{
if (isParameterValid(text))
{
drawText(text.getValue());
}
}
/**
* Draws the text at current position.
*
* @param x
* The X position to set after text drawing in device independent units.
* @param text
* The new text to draw at current position.
*/
public static void drawTextAndSetX(double x, String text)
{
resolveCurrentMetafile().drawTextAndSetX(x, text);
}
/**
* Draws the text at current position.
*
* @param x
* The X position to set after text drawing in device independent units.
* @param text
* The new text to draw at current position.
*/
public static void drawTextAndSetX(decimal x, character text)
{
if (isParameterValid(x) && isParameterValid(text))
{
drawTextAndSetX(x.doubleValue(), text.getValue());
}
}
/**
* Draws the text at the given X position and current Y position and given alignment.
*
* @param x
* The X position for text to draw in device independent units.
* @param text
* The new text to draw at the given position.
* @param align
* The alignment value, either left or right.
*/
public static void drawTextAtX(double x, String text, String align)
{
resolveCurrentMetafile().drawTextAtX(x, text, align);
}
/**
* Draws the text at the given X position and current Y position and left alignment.
*
* @param x
* The X position for text to draw in device independent units.
* @param text
* The new text to draw at the given position.
*/
public static void drawTextAtXLeft(double x, String text)
{
resolveCurrentMetafile().drawTextAtX(x, text, "left");
}
/**
* Draws the text at the given X position and current Y position and left alignment.
*
* @param x
* The X position for text to draw in device independent units.
* @param text
* The new text to draw at the given position.
*/
public static void drawTextAtXLeft(decimal x, character text)
{
if (isParameterValid(x) && isParameterValid(text))
{
drawTextAtXLeft(x.doubleValue(), text.getValue());
}
}
/**
* Draws the text at the given X position and current Y position and left alignment.
*
* @param x
* The X position for text to draw in device independent units.
* @param text
* The new text to draw at the given position.
*/
public static void drawTextAtXRight(double x, String text)
{
resolveCurrentMetafile().drawTextAtX(x, text, "right");
}
/**
* Draws the text at the given X position and current Y position and left alignment.
*
* @param x
* The X position for text to draw in device independent units.
* @param text
* The new text to draw at the given position.
*/
public static void drawTextAtXRight(decimal x, character text)
{
if (isParameterValid(x) && isParameterValid(text))
{
drawTextAtXRight(x.doubleValue(), text.getValue());
}
}
/**
* Draws the text between left and right X positions and current Y position with given
* alignment. If text does not fit the area it will be truncated until match.
*
* @param left
* The left X position for text to draw in device independent units.
* @param right
* The right X position for text to draw in device independent units.
* @param text
* The new text to fit and draw in the given positions.
* @param align
* The alignment value, either left or right.
*/
public static void drawTextBetween(double left, double right, String text, String align)
{
resolveCurrentMetafile().drawTextBetween(left, right, text, align);
}
/**
* Draws the text between left and right X positions and current Y position with given
* alignment. If text does not fit the area it will be truncated until match.
*
* @param left
* The left X position for text to draw in device independent units.
* @param right
* The right X position for text to draw in device independent units.
* @param text
* The new text to fit and draw in the given positions.
* @param align
* The alignment value, either left or right.
*/
public static void drawTextBetween(decimal left, decimal right, character text, String align)
{
if (isParameterValid(left) && isParameterValid(right) && isParameterValid(text))
{
drawTextBetween(left.doubleValue(), right.doubleValue(), text.getValue(), align);
}
}
/**
* Draws the text between left and right X positions and current Y position with left
* alignment. If text does not fit the area it will be truncated until match.
*
* @param left
* The left X position for text to draw in device independent units.
* @param right
* The right X position for text to draw in device independent units.
* @param text
* The new text to fit and draw in the given positions.
*/
public static void drawTextBetweenLeft(double left, double right, String text)
{
resolveCurrentMetafile().drawTextBetween(left, right, text, "left");
}
/**
* Draws the text between left and right X positions and current Y position with left
* alignment. If text does not fit the area it will be truncated until match.
*
* @param left
* The left X position for text to draw in device independent units.
* @param right
* The right X position for text to draw in device independent units.
* @param text
* The new text to fit and draw in the given positions.
*/
public static void drawTextBetweenLeft(decimal left, decimal right, character text)
{
if (isParameterValid(left) && isParameterValid(right) && isParameterValid(text))
{
drawTextBetweenLeft(left.doubleValue(), right.doubleValue(), text.getValue());
}
}
/**
* Draws the text between left and right X positions and current Y position with right
* alignment. If text does not fit the area it will be truncated until match.
*
* @param left
* The left X position for text to draw in device independent units.
* @param right
* The right X position for text to draw in device independent units.
* @param text
* The new text to fit and draw in the given positions.
*/
public static void drawTextBetweenRight(double left, double right, String text)
{
resolveCurrentMetafile().drawTextBetween(left, right, text, "right");
}
/**
* Draws the text between left and right X positions and current Y position with right
* alignment. If text does not fit the area it will be truncated until match.
*
* @param left
* The left X position for text to draw in device independent units.
* @param right
* The right X position for text to draw in device independent units.
* @param text
* The new text to fit and draw in the given positions.
*/
public static void drawTextBetweenRight(decimal left, decimal right, character text)
{
if (isParameterValid(left) && isParameterValid(right) && isParameterValid(text))
{
drawTextBetweenRight(left.doubleValue(), right.doubleValue(), text.getValue());
}
}
/**
* Sets new values for line attributes.
*
* @param style
* The new String value for the current line style. The valid style values:
* "solid", "dash", "dot", "dashdot", "dashdotdot", "null", "insideframe".
* @param thickness
* The thick of the line in device independent units.
* @param redColor
* The new red part of the color value.
* @param greenColor
* The new green part of the color value.
* @param blueColor
* The new blue part of the color value.
*/
public static void setLineAttributes(String style, double thickness,
int redColor, int greenColor, int blueColor)
{
resolveCurrentMetafile().setLineAttributes(style, thickness,
redColor, greenColor, blueColor);
}
/**
* Sets new values for line attributes.
*
* @param style
* The new String value for the current line style. The valid style values:
* "solid", "dash", "dot", "dashdot", "dashdotdot", "null", "insideframe".
* @param thickness
* The thick of the line in device independent units.
* @param redColor
* The new red part of the color value.
* @param greenColor
* The new green part of the color value.
* @param blueColor
* The new blue part of the color value.
*/
public static void setLineAttributes(String style, decimal thickness,
int redColor, int greenColor, int blueColor)
{
if (isParameterValid(thickness))
{
setLineAttributes(style, thickness.doubleValue(), redColor, greenColor, blueColor);
}
}
/**
* Sets new values for line attributes.
*
* @param style
* The new String value for the current line style. The valid style values:
* "solid", "dash", "dot", "dashdot", "dashdotdot", "null", "insideframe".
* @param thickness
* The thick of the line in device independent units.
* @param redColor
* The new red part of the color value.
* @param greenColor
* The new green part of the color value.
* @param blueColor
* The new blue part of the color value.
*/
public static void setLineAttributes(character style, decimal thickness,
integer redColor, integer greenColor, integer blueColor)
{
if (isParameterValid(style) && isParameterValid(thickness) && isParameterValid(redColor) &&
isParameterValid(greenColor) && isParameterValid(blueColor))
{
setLineAttributes(style.getValue(), thickness.doubleValue(), redColor.intValue(),
greenColor.intValue(), blueColor.intValue());
}
}
/**
* Sets new current color value to be used in line based primitives.
*
* @param rgbColor
* The new 32-bit color value packed in int value.
*/
public static void setLineColor(int rgbColor)
{
resolveCurrentMetafile().setLineColor(rgbColor);
}
/**
* Sets new current color value to be used in line based primitives.
*
* @param rgbColor
* The new 32-bit color value packed in int value.
*/
public static void setLineColor(integer rgbColor)
{
if (isParameterValid(rgbColor))
{
setLineColor(rgbColor.intValue());
}
}
/**
* Sets new values for line attributes.
*
* @param style
* The new String value for the current line style. The valid style values:
* "solid", "dash", "dot", "dashdot", "dashdotdot", "null", "insideframe".
* @param thickness
* The thick of the line in device independent units.
*/
public static void setLineStyle(String style, double thickness)
{
resolveCurrentMetafile().setLineStyle(style, thickness);
}
/**
* Sets new values for line attributes.
*
* @param style
* The new String value for the current line style. The valid style values:
* "solid", "dash", "dot", "dashdot", "dashdotdot", "null", "insideframe".
* @param thickness
* The thick of the line in device independent units.
*/
public static void setLineStyle(String style, decimal thickness)
{
if (isParameterValid(thickness))
{
setLineStyle(style, thickness.doubleValue());
}
}
/**
* Sets new values for line attributes.
*
* @param style
* The new String value for the current line style. The valid style values:
* "solid", "dash", "dot", "dashdot", "dashdotdot", "null", "insideframe".
* @param thickness
* The thick of the line in device independent units.
*/
public static void setLineStyle(character style, decimal thickness)
{
if (isParameterValid(style) && isParameterValid(thickness))
{
setLineStyle(style.getValue(), thickness.doubleValue());
}
}
/**
* Sets new current color value to be used in fill based primitives.
*
* @param rgbColor
* The new 32-bit color value packed in int value.
*/
public static void setFillColor(int rgbColor)
{
resolveCurrentMetafile().setFillColor(rgbColor);
}
/**
* Sets new current color value to be used in fill based primitives.
*
* @param rgbColor
* The new 32-bit color value packed in int value.
*/
public static void setFillColor(integer rgbColor)
{
if (isParameterValid(rgbColor))
{
setFillColor(rgbColor.intValue());
}
}
/**
* Draws the line from left-top point to right-bottom with current line attributes.
* The coordintes are in device independent units.
*
* @param left
* The left X position of the line start.
* @param top
* The top Y position of the line start.
* @param right
* The right X position of the line start.
* @param bottom
* The bottom Y position of the line start.
*/
public static void drawLine(double left, double top, double right, double bottom)
{
resolveCurrentMetafile().drawLine(left, top, right, bottom);
}
/**
* Draws the line from left-top point to right-bottom with current line attributes.
* The coordintes are in device independent units.
*
* @param left
* The left X position of the line start.
* @param top
* The top Y position of the line start.
* @param right
* The right X position of the line start.
* @param bottom
* The bottom Y position of the line start.
*/
public static void drawLine(decimal left, decimal top, decimal right, decimal bottom)
{
if (isParameterValid(left) && isParameterValid(top) &&
isParameterValid(right) && isParameterValid(bottom))
{
drawLine(left.doubleValue(), top.doubleValue(),
right.doubleValue(), bottom.doubleValue());
}
}
/**
* Draws the line from left-top point to right-bottom with current line attributes.
* The coordintes are in device independent units.
*
* @param left
* The left X position of the line start.
* @param top
* The top Y position of the line start.
* @param right
* The right X position of the line start.
* @param bottom
* The bottom Y position of the line start.
*/
public static void drawLine(double left, decimal top, decimal right, decimal bottom)
{
if (isParameterValid(top) && isParameterValid(right) && isParameterValid(bottom))
{
drawLine(left, top.doubleValue(), right.doubleValue(), bottom.doubleValue());
}
}
/**
* Draws the line from left-top point to right-bottom with current line attributes.
* The coordintes are in device independent units.
*
* @param left
* The left X position of the line start.
* @param top
* The top Y position of the line start.
* @param right
* The right X position of the line start.
* @param bottom
* The bottom Y position of the line start.
*/
public static void drawLine(decimal left, decimal top, double right, decimal bottom)
{
if (isParameterValid(left) && isParameterValid(top) && isParameterValid(bottom))
{
drawLine(left.doubleValue(), top.doubleValue(), right, bottom.doubleValue());
}
}
/**
* Draws the line from left-top point to right-bottom with current line attributes.
* The coordintes are in device independent units.
*
* @param left
* The left X position of the line start.
* @param top
* The top Y position of the line start.
* @param right
* The right X position of the line start.
* @param bottom
* The bottom Y position of the line start.
*/
public static void drawLine(double left, decimal top, double right, decimal bottom)
{
if (isParameterValid(top) && isParameterValid(bottom))
{
drawLine(left, top.doubleValue(), right, bottom.doubleValue());
}
}
/**
* Draws the line from left-top point to right-bottom with current line attributes.
* The coordintes are in device independent units.
*
* @param left
* The left X position of the line start.
* @param top
* The top Y position of the line start.
* @param right
* The right X position of the line start.
* @param bottom
* The bottom Y position of the line start.
*/
public static void drawLine(decimal left, double top, double right, double bottom)
{
if (isParameterValid(left))
{
drawLine(left.doubleValue(), top, right, bottom);
}
}
/**
* Draws the line from left-top point to right-bottom with current line attributes.
* The coordintes are in device independent units.
*
* @param left
* The left X position of the line start.
* @param top
* The top Y position of the line start.
* @param right
* The right X position of the line start.
* @param bottom
* The bottom Y position of the line start.
*/
public static void drawLine(decimal left, double top, decimal right, double bottom)
{
if (isParameterValid(left) && isParameterValid(right))
{
drawLine(left.doubleValue(), top, right.doubleValue(), bottom);
}
}
/**
* Draws the framed rectangle between left-top point and right-bottom with current line
* attributes. The coordintes are in device independent units.
*
* @param left
* The left X position of the rectangle.
* @param top
* The top Y position of the rectangle.
* @param right
* The right X position of the rectangle.
* @param bottom
* The bottom Y position of the rectangle.
*/
public static void drawRect(double left, double top, double right, double bottom)
{
resolveCurrentMetafile().drawRect(left, top, right, bottom);
}
/**
* Draws the framed rectangle between left-top point and right-bottom with current line
* attributes. The coordintes are in device independent units.
*
* @param left
* The left X position of the rectangle.
* @param top
* The top Y position of the rectangle.
* @param right
* The right X position of the rectangle.
* @param bottom
* The bottom Y position of the rectangle.
*/
public static void drawRect(decimal left, decimal top, decimal right, decimal bottom)
{
if (isParameterValid(left) && isParameterValid(top) &&
isParameterValid(right) && isParameterValid(bottom))
{
drawRect(left.doubleValue(), top.doubleValue(),
right.doubleValue(), bottom.doubleValue());
}
}
/**
* Draws the framed rectangle between left-top point and right-bottom with current line
* attributes. The coordintes are in device independent units.
*
* @param left
* The left X position of the rectangle.
* @param top
* The top Y position of the rectangle.
* @param right
* The right X position of the rectangle.
* @param bottom
* The bottom Y position of the rectangle.
*/
public static void drawRect(double left, decimal top, decimal right, decimal bottom)
{
if (isParameterValid(top) && isParameterValid(right) && isParameterValid(bottom))
{
drawRect(left, top.doubleValue(), right.doubleValue(), bottom.doubleValue());
}
}
/**
* Draws the rectangle between left-top point and right-bottom with current line and fill
* attributes. The coordintes are in device independent units.
*
* @param left
* The left X position of the rectangle.
* @param top
* The top Y position of the rectangle.
* @param right
* The right X position of the rectangle.
* @param bottom
* The bottom Y position of the rectangle.
*/
public static void drawFilledRect(double left, double top, double right, double bottom)
{
resolveCurrentMetafile().drawFilledRect(left, top, right, bottom);
}
/**
* Draws the rectangle between left-top point and right-bottom with current line and fill
* attributes. The coordintes are in device independent units.
*
* @param left
* The left X position of the rectangle.
* @param top
* The top Y position of the rectangle.
* @param right
* The right X position of the rectangle.
* @param bottom
* The bottom Y position of the rectangle.
*/
public static void drawFilledRect(decimal left, decimal top, decimal right, decimal bottom)
{
if (isParameterValid(left) && isParameterValid(top) &&
isParameterValid(right) && isParameterValid(bottom))
{
drawFilledRect(left.doubleValue(), top.doubleValue(),
right.doubleValue(), bottom.doubleValue());
}
}
/**
* Sets new values for image alignment.
*
* @param horizAlign
* The new String value for horizontal text alignment. The valid alignment values:
* "left", "center", "right".
* @param vertAlign
* The new String value for vertical text alignment. The valid alignment values:
* "top", "baseline", "bottom".
*/
public static void setImageAlign(String horizAlign, String vertAlign)
{
resolveCurrentMetafile().setImageAlign(horizAlign, vertAlign);
}
/**
* Draws the image.
*
* @param option
* The image painting option for example "origratio=yes".
* @param x
* The image X position.
* @param y
* The image Y position.
* @param width
* The image width in metric units.
* @param height
* The image height in metric units.
* @param filename
* The name of the file to use as image.
* @param imgWidth
* The final painted image width in metric units(return value).
* @param imgHeight
* The final painted image height in metric units(return value).
*/
public static void drawImage(String option, double x, double y, double width, double height,
String filename, decimal imgWidth, decimal imgHeight)
{
resolveCurrentMetafile().drawImage(option, x, y, width, height, filename,
imgWidth, imgHeight);
}
/**
* Draws the image.
*
* @param option
* The image painting option for example "origratio=yes".
* @param x
* The image X position.
* @param y
* The image Y position.
* @param width
* The image width in metric units.
* @param height
* The image height in metric units.
* @param filename
* The name of the file to use as image.
* @param imgWidth
* The final painted image width in metric units(return value).
* @param imgHeight
* The final painted image height in metric units(return value).
*/
public static void drawImage(String option, decimal x, decimal y, decimal width,
decimal height, character filename,
decimal imgWidth, decimal imgHeight)
{
if (isParameterValid(x) && isParameterValid(y) && isParameterValid(width) &&
isParameterValid(height) && isParameterValid(filename))
{
drawImage(option, x.doubleValue(), y.doubleValue(), width.doubleValue(),
height.doubleValue(), filename.getValue(), imgWidth, imgHeight);
}
}
/**
* Draws the image.
*
* @param option
* The image painting option for example "origratio=yes".
* @param x
* The image X position.
* @param y
* The image Y position.
* @param width
* The image width in metric units.
* @param height
* The image height in metric units.
* @param filename
* The name of the file to use as image.
* @param imgWidth
* The final painted image width in metric units(return value).
* @param imgHeight
* The final painted image height in metric units(return value).
*/
public static void drawImage(character option, decimal x, decimal y, decimal width,
decimal height, character filename,
decimal imgWidth, decimal imgHeight)
{
if (isParameterValid(option) && isParameterValid(x) && isParameterValid(y) &&
isParameterValid(width) && isParameterValid(height) && isParameterValid(filename))
{
drawImage(option.getValue(), x.doubleValue(), y.doubleValue(), width.doubleValue(),
height.doubleValue(), filename.getValue(), imgWidth, imgHeight);
}
}
/**
* Draws the image.
*
* @param option
* The image painting option for example "origratio=yes".
* @param x
* The image X position.
* @param y
* The image Y position.
* @param width
* The image width in metric units.
* @param height
* The image height in metric units.
* @param filename
* The name of the file to use as image.
* @param imgWidth
* The final painted image width in metric units(return value).
* @param imgHeight
* The final painted image height in metric units(return value).
*/
public static void drawImage(String option, decimal x, decimal y, double width, double height,
character filename, decimal imgWidth, decimal imgHeight)
{
if (isParameterValid(x) && isParameterValid(y) && isParameterValid(filename))
{
drawImage(option, x.doubleValue(), y.doubleValue(), width, height, filename.getValue(),
imgWidth, imgHeight);
}
}
/**
* Draws the part of the image.
*
* @param x
* The image X position.
* @param y
* The image Y position.
* @param widthPix
* The image width in pixels.
* @param heightPix
* The image height in pixels.
* @param maxWidthCm
* The image maximum right border not to exceed.
* @param filename
* The name of the file to use as image.
*/
public static void drawImagePart(double x, double y, int widthPix, int heightPix,
double maxWidthCm, String filename)
{
resolveCurrentMetafile().drawImagePart(x, y, widthPix, heightPix, maxWidthCm, filename);
}
/**
* Draws the part of the image.
*
* @param x
* The image X position.
* @param y
* The image Y position.
* @param widthPix
* The image width in pixels.
* @param heightPix
* The image height in pixels.
* @param maxWidthCm
* The image maximum right border not to exceed.
* @param filename
* The name of the file to use as image.
*/
public static void drawImagePart(decimal x, decimal y, integer widthPix, integer heightPix,
decimal maxWidthCm, character filename)
{
if (isParameterValid(x) && isParameterValid(y) && isParameterValid(widthPix) &&
isParameterValid(heightPix) && isParameterValid(maxWidthCm) &&
isParameterValid(filename))
{
drawImagePart(x.doubleValue(), y.doubleValue(), widthPix.intValue(),
heightPix.intValue(), maxWidthCm.doubleValue(), filename.getValue());
}
}
/**
* Sets new value for current page orientation.
*
* @param mode
* The new String value for page orientation. The valid alignment values:
* "standard", "portrait", "landscape".
*/
public static void setPageOrientation(character mode)
{
if (isParameterValid(mode))
{
resolveCurrentMetafile().setPageOrientation(mode.getValue());
}
}
/**
* Sets new value for current page orientation.
*
* @param mode
* The new String value for page orientation. The valid alignment values:
* "standard", "portrait", "landscape".
*/
public static void setPageOrientation(String mode)
{
resolveCurrentMetafile().setPageOrientation(mode);
}
/**
* Gets the current page width.
*
* @param pageWidth
* The current page width value in device independent units.
*/
public static void getPageWidth(decimal pageWidth)
{
resolveCurrentMetafile().getPageWidth(pageWidth);
}
/**
* Gets the current page height.
*
* @param pageHeight
* The current page height value in device independent units.
*/
public static void getPageHeight(decimal pageHeight)
{
resolveCurrentMetafile().getPageHeight(pageHeight);
}
/**
* Sets new value for current/maximum page number.
*
* @param mode
* The new String value for page mode. The valid values: "append", "new".
* @param newMaxPageNum
* The integer max page number value.
*/
public static void resetPage(String mode, int newMaxPageNum)
{
resolveCurrentMetafile().resetPage(mode, newMaxPageNum);
}
/**
* Sets new value for current/maximum page number.
*
* @param mode
* The new String value for page mode. The valid values: "append", "new".
* @param newMaxPageNum
* The integer max page number value.
*/
public static void resetPage(String mode, integer newMaxPageNum)
{
if (isParameterValid(newMaxPageNum))
{
resetPage(mode, newMaxPageNum.intValue());
}
}
/**
* Gets the current page number.
*
* @param pageNum
* The current integer page number value.
*/
public static void getPageNumber(integer pageNum)
{
resolveCurrentMetafile().getPageNumber(pageNum);
}
/**
* Sets new value for current page number.
*
* @param newPageNum
* The integer page number value.
*/
public static void setPageNumber(int newPageNum)
{
resolveCurrentMetafile().setPageNumber(newPageNum);
}
/**
* Sets the new current position for page number. Can be used to draw page number text for
* header and footer.
*
* @param x
* The new X position for page nummber.
* @param y
* The new Y position for page nummber.
*/
public static void setPageNumberPosition(double x, double y)
{
resolveCurrentMetafile().setPageNumberPosition(x, y);
}
/**
* Sets the new current position for page number. Can be used to draw page number text for
* header and footer.
*
* @param x
* The new X position for page nummber.
* @param y
* The new Y position for page nummber.
*/
public static void setPageNumberPosition(decimal x, decimal y)
{
if (isParameterValid(x) && isParameterValid(y))
{
setPageNumberPosition(x.doubleValue(), y.doubleValue());
}
}
/**
* Sets new value for current page number text.
*
* @param text
* The new text for page number.
* @param pgNumberNdx
* The index of new text for page number.
*/
public static void setPageNumberText(String text, int pgNumberNdx)
{
resolveCurrentMetafile().setPageNumberText(text, pgNumberNdx);
}
/**
* Sets new value for current page number text.
*
* @param text
* The new text for page number.
* @param pgNumberNdx
* The index of new text for page number.
*/
public static void setPageNumberText(character text, int pgNumberNdx)
{
if (isParameterValid(text))
{
setPageNumberText(text.getValue(), pgNumberNdx);
}
}
/**
* Sets new value for current page number text(alternative version).
*
* @param x
* The new X position for page nummber.
* @param y
* The new Y position for page nummber.
* @param text
* The new text for page number.
*/
public static void setPageNumberText(double x, double y, String text)
{
resolveCurrentMetafile().setPageNumberPosition(x, y);
resolveCurrentMetafile().setPageNumberText(text, 1);
}
/**
* Sets new value for current page number text(alternative version).
*
* @param x
* The new X position for page nummber.
* @param y
* The new Y position for page nummber.
* @param text
* The new text for page number.
*/
public static void setPageNumberText(decimal x, decimal y, character text)
{
if (isParameterValid(x) && isParameterValid(y) && isParameterValid(text))
{
setPageNumberText(x.doubleValue(), y.doubleValue(), text.getValue());
}
}
/**
* Sets to show page footer or not.
*
* @param show
* The <code>1</code> value means show footer, <code>0</code> means no footer.
*/
public static void showPageFooter(int show)
{
resolveCurrentMetafile().showPageFooter(show == 1);
}
/**
* Sets to show page footer or not.
*
* @param show
* The <code>1</code> value means show footer, <code>0</code> means no footer.
*/
public static void showPageFooter(integer show)
{
if (isParameterValid(show))
{
showPageFooter(show.intValue());
}
}
/**
* General metafile subsystem init procedure.
*
* @param footerTextHeight
* The height of the footed text in device independent units.
* @param tmpDir
* The temporary directory to use.
* @param ok
* The return value, meaning success init or not.
*/
public static void initialize(double footerTextHeight, String tmpDir, integer ok)
{
resolveCurrentMetafile().initialize(footerTextHeight, tmpDir, ok);
}
/**
* General metafile subsystem init procedure.
*
* @param footerTextHeight
* The height of the footed text in device independent units.
* @param tmpDir
* The temporary directory to use.
* @param ok
* The return value, meaning success init or not.
*/
public static void initialize(decimal footerTextHeight, character tmpDir, integer ok)
{
if (isParameterValid(footerTextHeight) && isParameterValid(tmpDir))
{
initialize(footerTextHeight.doubleValue(), tmpDir.getValue(), ok);
}
}
/**
* Gets optionally set temporary directory to store generated PDF temporary files.
*
* @return The currently used temporary directory.
*/
public static String getTmpDirectory()
{
return resolveCurrentMetafile().getTmpDirectory();
}
/**
* Makes PDF file from the currently recorded metafile.
*
* @param pdfFileName
* The name of the PDF file to create.
*/
public static void makePdf(String pdfFileName)
{
// get the metafile object
WorkArea wa = work.obtain();
// intercept Jasper related issues tp avoid client abend too
try
{
// ensure all pending objects are committed
wa.currentMf.stopRecording();
// time to create jasper related worker
Xpr2PdfWorker pdfOutput = new Xpr2PdfWorker(wa.currentMf, pdfFileName);
// export to PDF
if (!pdfOutput.export(false))
{
XprHelper.displayOrLogError(String.format("MetafileHelper export failed for %s.",
pdfFileName));
}
}
catch (Exception e)
{
XprHelper.displayOrLogError(String.format(
"MetafileHelper has faced unexpected problem with report generation for PDF file %s.",
pdfFileName), e);
}
// after pdf was made we need to clean up current session based metafile
wa.currentMf = null;
// as final step we load file into client context
if(openFile)
{
WebBrowserManager.openMimeResource(XprHelper.PDF_MIME,
XprHelper.FILE_PROTOCOL + pdfFileName, false);
}
}
/**
* Makes PDF file from the currently recorded metafile.
*
* @param pdfFileName
* The name of the PDF file to create.
*/
public static void makePdf(character pdfFileName)
{
if (isParameterValid(pdfFileName))
{
makePdf(pdfFileName.getValue());
}
}
/**
* Makes PDF file from the currently recorded metafile with preview mode or not.
*
* @param pdfFileName
* The name of the PDF file to create.
* @param openFilePDF
* preview prevents opening the PDF file instantly
*/
public static void makePdf(character pdfFileName, boolean openFilePDF)
{
if (isParameterValid(pdfFileName))
{
makePdf(pdfFileName.getValue(), openFilePDF);
}
}
/**
* Makes PDF file from the currently recorded metafile with preview mode or not.
*
* @param pdfFileName
* The name of the PDF file to create.
* @param openFilePDF
* preview prevents opening the PDF file instantly
*/
public static void makePdf(String pdfFileName, logical openFilePDF)
{
if (isParameterValid(openFilePDF))
{
makePdf(pdfFileName, openFilePDF.booleanValue());
}
}
/**
* Makes PDF file from the currently recorded metafile with preview mode or not.
*
* @param pdfFileName
* The name of the PDF file to create.
* @param openFilePDF
* preview prevents opening the PDF file instantly
*/
public static void makePdf(character pdfFileName, logical openFilePDF)
{
if (isParameterValid(pdfFileName) && isParameterValid(openFilePDF))
{
makePdf(pdfFileName.getValue(), openFilePDF.booleanValue());
}
}
/**
* Makes PDF file from the currently recorded metafile with preview mode or not.
*
* @param pdfFileName
* The name of the PDF file to create.
* @param openFilePDF
* preview prevents opening the PDF file instantly
*/
public static void makePdf(String pdfFileName, boolean openFilePDF)
{
try
{
openFile = openFilePDF;
makePdf(pdfFileName);
}
finally
{
openFile = true;
}
}
/**
* Stops all operation for the current metafile.
*/
public static void stopRecording()
{
resolveCurrentMetafile().stopRecording();
}
/**
* Interrupts all operation for the current metafile.
*/
public static void interruptRecording()
{
work.obtain().currentMf = null;
}
/**
* Converts X cm metafile coordinate to XPR column value.
*
* @param x
* The X coordinate to transform.
*
* @return The column value to use in JasperReports XPR objects handling.
*/
public static double x2Col(double x)
{
// gets the pixel value of the metafile coord and converts to XPR column
return (double)mfUnits2pix(x) / pixPerCol;
}
/**
* Converts Y cm metafile coordinate to XPR row value.
*
* @param y
* The Y coordinate to transform.
*
* @return The row value to use in JasperReports XPR objects handling.
*/
public static double y2Row(double y)
{
// gets the pixel value of the metafile coord and converts to XPR row
return (double)mfUnits2pix(y) / pixPerRow;
}
/**
* Converts pixel coordinate value into metafile device independent unit value.
*
* @param pixelValue
* The coordinate in pixels to transform.
* @param mfUnits
* The device independent unit, can be inch/cm/mm.
*/
public static void pix2MfUnits(int pixelValue, decimal mfUnits)
{
double val = pix2MfUnits(pixelValue);
mfUnits.assign(new decimal(val));
}
/**
* Converts pixel coordinate value into metafile device independent unit value.
*
* @param pixelValue
* The coordinate in pixels to transform.
* @param mfUnits
* The device independent unit, can be inch/cm/mm.
*/
public static void pix2MfUnits(integer pixelValue, decimal mfUnits)
{
if (isParameterValid(pixelValue))
{
pix2MfUnits(pixelValue.intValue(), mfUnits);
}
}
/**
* Converts pixel coordinate value into metafile device independent unit value.
*
* @param pixelValue
* The coordinate in pixels to transform.
*
* @return The device independent unit, can be inch/cm/mm.
*/
public static double pix2MfUnits(float pixelValue)
{
// defaulting to inches
double res = (double)pixelValue / (double) (Xpr2PdfWorker.DPI_DEFAULT);
// can be CM or MM as well
if (units == UNITS_MM)
{
res *= XprEntity.INCH_2_MM;
}
else if (units == UNITS_CM)
{
res *= XprEntity.INCH_2_MM / 10.0;
}
return res;
}
/**
* Converts metafile coordinate value into pixel based coordinate.
*
* @param mfValue
* The coordinate in metafile units to transform.
*
* @return The coordinale in pixels.
*/
public static int mfUnits2pix(double mfValue)
{
// defaulting to use inches
double res = (double)mfValue * (double) (Xpr2PdfWorker.DPI_DEFAULT);
// can be CM or MM as well
if (units == UNITS_MM)
{
res /= XprEntity.INCH_2_MM;
}
else if (units == UNITS_CM)
{
res /= XprEntity.INCH_2_MM / 10.0;
}
return (int)Math.round(res);
}
/**
* Checks if the given parameter is valid and can be used in Metafile api.
*
* @param op
* The parameter to test.
*
* @return <code>TRUE</code> if valid, <code>FALSE</code> otherwise.
*/
public static boolean isParameterValid(BaseDataType op)
{
return op != null && !op.isUnknown();
}
/**
* Calculates the scaling factor for given text. Different letters have different width for variable
* size fonts like Arial. We need to compensate this difference to get proper text width.
*
* @param textToTest
* The text to measure letters scale.
* @param fontName
* The font to be used to draw the text.
* @param isBold
* If the font to be used is bold or not.
* @param isItalic
* If the font to be used is italic or not.
*
* @return The scaling for given string to calculate text width.
*/
public static double getTextWeightScale(String textToTest, String fontName,
boolean isBold, boolean isItalic)
{
double res = 0.0;
// some simple NPE and errors protection
// fixed width font can also be exculded
if (textToTest == null || textToTest.isEmpty() || fontName.equals("Courier"))
{
return 1.0;
}
// text length
int length = textToTest.length();
for (int i = 0; i < length; i++)
{
char chNext = textToTest.charAt(i);
switch (chNext)
{
case ' ':
case ':':
case '.':
case ',':
case ';':
case '[':
case ']':
case '(':
case ')':
case '!':
case '\'':
case '|':
{
// very narrow letters
res += 0.555;
break;
}
case 'I':
case 'i':
case 'L':
case 'l':
case '/':
case '\\':
case '-':
case '*':
case 'f':
case 't':
case '{':
case '}':
{
// narrow letters
res += 0.75;
break;
}
case 'Z':
case 'M':
case 'G':
case 'E':
case 'R':
case 'O':
case 'D':
case 'N':
case 'S':
{
// very wide letters
res += 1.35;
break;
}
case 'W':
case '@':
case '%':
{
// extra wide letters
res += 1.55;
break;
}
case 'A':
case 'V':
case 'P':
case 'C':
case 'w':
case 'Q':
{
// wide letters
res += 1.15;
break;
}
default:
{
// all other letters are regular
res += 1.0;
break;
}
}
// bold and possibly italic fonts need additional corrections in certain cases
if (isBold && !Character.isDigit(chNext))
{
res += 0.1;
}
else if (isItalic)
{
res += 0.0;
}
}
// normalize the scale factor
res /= (double)length;
// the Arial font needs to be a bit smaller comparing to all others
return fontName.equals("Arial") ? res * 0.85 : res;
}
/**
* Gets the instance of the current metafile to process.
*
* @return The current metafile.
*/
private static Metafile resolveCurrentMetafile()
{
WorkArea wa = work.obtain();
if (wa.currentMf == null)
{
wa.currentMf = new Metafile();
}
return wa.currentMf;
}
/**
* Stores global data relating to the state of the current context.
*/
private static class WorkArea
{
/** Current per session context metafile instance. */
private Metafile currentMf = null;
}
/**
* Simple container that stores and returns a context-local instance of
* the global work area.
*/
private static class ContextContainer
extends ContextLocal<WorkArea>
{
/**
* Obtains the context-local instance of the contained global work
* area.
*
* @return The work area associated with this context.
*/
public WorkArea obtain()
{
return this.get();
}
/**
* Initializes the work area, the first time it is requested within a
* new context.
*
* @return The newly instantiated work area.
*/
protected synchronized WorkArea initialValue()
{
WorkArea wa = new WorkArea();
return wa;
}
}
}