Skip to content

Commit

Permalink
restore extension fonts on virtualization
Browse files Browse the repository at this point in the history
closes gh-225
  • Loading branch information
dadza committed Dec 27, 2021
1 parent bcc8bf5 commit 0074da4
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
*/
package net.sf.jasperreports.engine.fill;

import java.awt.Font;
import java.io.IOException;
import java.io.ObjectInputStream.GetField;
import java.io.Serializable;
Expand Down Expand Up @@ -56,6 +57,7 @@
import net.sf.jasperreports.engine.base.JRVirtualPrintPage;
import net.sf.jasperreports.engine.base.VirtualElementsData;
import net.sf.jasperreports.engine.base.VirtualizableElementList;
import net.sf.jasperreports.engine.fonts.FontUtil;
import net.sf.jasperreports.engine.util.DeepPrintElementVisitor;
import net.sf.jasperreports.engine.util.UniformPrintElementVisitor;
import net.sf.jasperreports.renderers.Renderable;
Expand Down Expand Up @@ -599,6 +601,10 @@ else if (obj instanceof VirtualizationContextIdHolder)
}
resolve = context;
}
else if (obj instanceof Font)
{
resolve = FontUtil.getInstance(jasperReportsContext).resolveDeserializedFont((Font) obj);
}
return resolve;
}

Expand Down
21 changes: 21 additions & 0 deletions jasperreports/src/net/sf/jasperreports/engine/fonts/FontUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -657,6 +657,27 @@ public Font getAwtFont(JRFont font, Locale locale)
return awtFont;
}

public Font resolveDeserializedFont(Font font)
{
// We use the font.getName() method here because the name field in the java.awt.Font class is the only font name related information that gets serialized,
// along with the size and style. The font.getFontName() and font.getFamily() both return runtime calculated values, which are not accurate in case of AWT fonts
// created at runtime through font extensions (both seem to return 'Dialog').
// For AWT fonts created from font extensions using the Font.createFont(int, InputStream), the name field is set to the same value as the font.getFontName(),
// which is the recommended method to get the name of an AWT font.
String fontName = font.getName();
// We load an instance of an AWT font, even if the specified font name is not available (ignoreMissingFont=true),
// because only third-party visualization packages such as JFreeChart (chart themes) store serialized java.awt.Font objects,
// and they are responsible for the drawing as well.
// Here we rely on the utility method ability to find a font by face name, not only family name. This is because font.getName() above returns an AWT font name,
// not a font family name.
Font newFont = getAwtFontFromBundles(fontName, font.getStyle(), font.getSize2D(), null, true);
if (newFont != null)
{
return newFont.deriveFont(font.getAttributes());
}

return font;
}

private FontUtil()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,23 +122,7 @@ protected Object resolveObject(Object obj) throws IOException

if (font != null)
{
// We use the font.getName() method here because the name field in the java.awt.Font class is the only font name related information that gets serialized,
// along with the size and style. The font.getFontName() and font.getFamily() both return runtime calculated values, which are not accurate in case of AWT fonts
// created at runtime through font extensions (both seem to return 'Dialog').
// For AWT fonts created from font extensions using the Font.createFont(int, InputStream), the name field is set to the same value as the font.getFontName(),
// which is the recommended method to get the name of an AWT font.
String fontName = font.getName();
// We load an instance of an AWT font, even if the specified font name is not available (ignoreMissingFont=true),
// because only third-party visualization packages such as JFreeChart (chart themes) store serialized java.awt.Font objects,
// and they are responsible for the drawing as well.
// Here we rely on the utility method ability to find a font by face name, not only family name. This is because font.getName() above returns an AWT font name,
// not a font family name.
Font newFont = FontUtil.getInstance(jasperReportsContext).getAwtFontFromBundles(fontName, font.getStyle(), font.getSize2D(), null, true);

if (newFont != null)
{
return newFont.deriveFont(font.getAttributes());
}
return FontUtil.getInstance(jasperReportsContext).resolveDeserializedFont(font);
}

return obj;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
*/
package net.sf.jasperreports.engine.virtualization;

import java.awt.Font;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
Expand All @@ -31,6 +32,7 @@

import net.sf.jasperreports.engine.JRRuntimeException;
import net.sf.jasperreports.engine.fill.JRVirtualizationContext;
import net.sf.jasperreports.engine.fonts.FontUtil;

/**
* @author Lucian Chirita (lucianc@users.sourceforge.net)
Expand All @@ -52,6 +54,8 @@ public VirtualizationInput(InputStream in,
super(in);

this.virtualizationContext = virtualizationContext;

enableResolveObject(true);
}

public JRVirtualizationContext getVirtualizationContext()
Expand Down Expand Up @@ -129,4 +133,15 @@ protected void putReference(int typeValue, Object value)

objects.add(value);
}

@Override
protected Object resolveObject(Object obj) throws IOException
{
if (obj instanceof Font)
{
return FontUtil.getInstance(virtualizationContext.getJasperReportsContext()).resolveDeserializedFont((Font) obj);
}

return obj;
}
}

0 comments on commit 0074da4

Please sign in to comment.