Java tutorial
/* * 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) 2006 - 2017 Hitachi Vantara and Contributors. All rights reserved. */ package org.pentaho.reporting.libraries.fonts.itext; import com.lowagie.text.pdf.BaseFont; import org.pentaho.reporting.libraries.fonts.LibFontsDefaults; import org.pentaho.reporting.libraries.fonts.encoding.CodePointUtilities; import org.pentaho.reporting.libraries.fonts.registry.BaselineInfo; import org.pentaho.reporting.libraries.fonts.registry.FontMetrics; import org.pentaho.reporting.libraries.fonts.registry.FontNativeContext; import org.pentaho.reporting.libraries.fonts.tools.FontStrictGeomUtility; import java.util.Arrays; /** * Creation-Date: 22.07.2007, 19:04:00 * * @author Thomas Morgner */ public class BaseFontFontMetrics implements FontMetrics { private BaseFont baseFont; private float size; private long xHeight; private char[] cpBuffer; private long[] cachedWidths; private long ascent; private long descent; private long leading; private long sizeScaled; private long italicsAngle; private long maxAscent; private long maxDescent; private long maxCharAdvance; private boolean trueTypeFont; private transient BaselineInfo cachedBaselineInfo; private FontNativeContext record; public BaseFontFontMetrics(final FontNativeContext record, final BaseFont baseFont, final float size) { if (baseFont == null) { throw new NullPointerException("BaseFont is invalid."); } this.record = record; this.baseFont = baseFont; this.size = size; this.cpBuffer = new char[4]; this.cachedWidths = new long[256 - 32]; Arrays.fill(cachedWidths, -1); sizeScaled = FontStrictGeomUtility.toInternalValue(size); this.ascent = (long) baseFont.getFontDescriptor(BaseFont.AWT_ASCENT, sizeScaled); this.descent = (long) -baseFont.getFontDescriptor(BaseFont.AWT_DESCENT, sizeScaled); this.leading = (long) baseFont.getFontDescriptor(BaseFont.AWT_LEADING, sizeScaled); italicsAngle = FontStrictGeomUtility .toInternalValue(baseFont.getFontDescriptor(BaseFont.ITALICANGLE, size)); maxAscent = (long) baseFont.getFontDescriptor(BaseFont.BBOXURY, sizeScaled); maxDescent = (long) -baseFont.getFontDescriptor(BaseFont.BBOXLLY, sizeScaled); maxCharAdvance = (long) baseFont.getFontDescriptor(BaseFont.AWT_MAXADVANCE, sizeScaled); final int[] charBBox = this.baseFont.getCharBBox('x'); if (charBBox != null) { this.xHeight = (long) (charBBox[3] * size); } if (this.xHeight == 0) { this.xHeight = getAscent() / 2; } this.trueTypeFont = baseFont.getFontType() == BaseFont.FONT_TYPE_TT || baseFont.getFontType() == BaseFont.FONT_TYPE_TTUNI; } public boolean isTrueTypeFont() { return trueTypeFont; } public long getAscent() { return ascent; } public long getDescent() { return descent; } public long getLeading() { return leading; } public long getXHeight() { return xHeight; } public long getOverlinePosition() { return getLeading() - Math.max(1000, sizeScaled / 20); } public long getUnderlinePosition() { return (getLeading() + getMaxAscent()) + Math.max(1000, sizeScaled / 20); } public long getStrikeThroughPosition() { return getMaxAscent() - (long) (LibFontsDefaults.DEFAULT_STRIKETHROUGH_POSITION * getXHeight()); } public long getItalicAngle() { return italicsAngle; } public long getMaxAscent() { return maxAscent; } public long getMaxDescent() { return maxDescent; } public long getMaxHeight() { return getMaxAscent() + getMaxDescent() + getLeading(); } public long getMaxCharAdvance() { return maxCharAdvance; } public long getCharWidth(final int character) { if (character >= 32 && character < 256) { // can be cached .. final int index = character - 32; final long cachedWidth = cachedWidths[index]; if (cachedWidth >= 0) { return cachedWidth; } final int retval = CodePointUtilities.toChars(character, cpBuffer, 0); if (retval == 1) { final char char1 = cpBuffer[0]; if (char1 < 128 || (char1 >= 160 && char1 <= 255)) { final long width = (long) (baseFont.getWidth(char1) * size); cachedWidths[index] = width; return width; } } else if (retval < 1) { cachedWidths[index] = 0; return 0; } final long width = (long) (baseFont.getWidth(new String(cpBuffer, 0, retval)) * size); cachedWidths[index] = width; return width; } final int retval = CodePointUtilities.toChars(character, cpBuffer, 0); if (retval == 1) { final char char1 = cpBuffer[0]; if (char1 < 128 || (char1 >= 160 && char1 <= 255)) { return (long) (baseFont.getWidth(char1) * size); } } else if (retval < 1) { return 0; } return (long) (baseFont.getWidth(new String(cpBuffer, 0, retval)) * size); } public long getKerning(final int previous, final int codePoint) { return (long) (size * baseFont.getKerning((char) previous, (char) codePoint)); } /** * Is it guaranteed that the font always returns the same baseline info objct? * * @return true, if the baseline info in question is always the same, false otherwise. */ public boolean isUniformFontMetrics() { return true; } public BaselineInfo getBaselines(final int c, BaselineInfo info) { if (cachedBaselineInfo != null) { if (info == null) { info = new BaselineInfo(); } info.update(cachedBaselineInfo); return info; } if (info == null) { info = new BaselineInfo(); } // If we had more data, we could surely create something better. Well, this has to be enough .. final long maxAscent = getMaxAscent(); info.setBaseline(BaselineInfo.MATHEMATICAL, maxAscent - getXHeight()); info.setBaseline(BaselineInfo.IDEOGRAPHIC, getMaxHeight()); info.setBaseline(BaselineInfo.MIDDLE, maxAscent / 2); info.setBaseline(BaselineInfo.ALPHABETIC, maxAscent); info.setBaseline(BaselineInfo.CENTRAL, maxAscent / 2); info.setBaseline(BaselineInfo.HANGING, maxAscent - getXHeight()); info.setDominantBaseline(BaselineInfo.ALPHABETIC); final BaselineInfo cached = new BaselineInfo(); cached.update(info); cachedBaselineInfo = cached; return info; } public BaseFont getBaseFont() { return baseFont; } public FontNativeContext getNativeContext() { return record; } }