Skip to content

Commit

Permalink
Merge pull request #450 from danfickle/better_java2d
Browse files Browse the repository at this point in the history
Java2D - Ability to add fonts via code and manual test harness.
  • Loading branch information
danfickle authored Mar 4, 2020
2 parents 15cbfd4 + 8fe65e6 commit 9fa3322
Show file tree
Hide file tree
Showing 24 changed files with 827 additions and 391 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,7 @@

public interface FontResolver {
public FSFont resolveFont(SharedContext renderingContext, FontSpecification spec);

@Deprecated
public void flushCache();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package com.openhtmltopdf.outputdevice.helper;

import java.io.File;
import java.io.InputStream;

import com.openhtmltopdf.extend.FSSupplier;
import com.openhtmltopdf.outputdevice.helper.BaseRendererBuilder.FontStyle;

public class AddedFont {
public final FSSupplier<InputStream> supplier;
public final File fontFile;
public final Integer weight;
public final String family;
public final boolean subset;
public final FontStyle style;
public final Object pdfontSupplier; // Bit of a hack, not type-safe!

public AddedFont(FSSupplier<InputStream> supplier, File fontFile, Integer weight, String family, boolean subset,
FontStyle style) {
this.supplier = supplier;
this.fontFile = fontFile;
this.pdfontSupplier = null;
this.weight = weight;
this.family = family;
this.subset = subset;
this.style = style;
}

public AddedFont(Object pdfontSupplier, Integer weight, String family, boolean subset, FontStyle style) {
this.supplier = null;
this.fontFile = null;
this.pdfontSupplier = pdfontSupplier;
this.weight = weight;
this.family = family;
this.subset = subset;
this.style = style;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import org.w3c.dom.Document;

import java.io.File;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
Expand All @@ -29,8 +30,9 @@ public abstract class BaseRendererBuilder<TFinalClass extends BaseRendererBuilde
* This is internal, please don't use directly.
*/
public abstract static class BaseRendererBuilderState {
public final List<FSDOMMutator> _domMutators = new ArrayList<FSDOMMutator>();
public Map<String, FSStreamFactory> _streamFactoryMap = new HashMap<String, FSStreamFactory>();
public final List<AddedFont> _fonts = new ArrayList<>();
public final List<FSDOMMutator> _domMutators = new ArrayList<>();
public final Map<String, FSStreamFactory> _streamFactoryMap = new HashMap<>();
public FSUriResolver _resolver;
public String _html;
public String _baseUri;
Expand Down Expand Up @@ -433,6 +435,67 @@ public final TFinalClass useFastMode() {
state._useFastRenderer = true;
return (TFinalClass) this;
}

/**
* Like {@link #useFont(FSSupplier, String, Integer, FontStyle, boolean)}, but
* allows to supply a font file. If the font file is a .ttc file it is handled
* as TrueTypeCollection (PDF only). If you have the font in file form you should use this
* API.
*/
public TFinalClass useFont(File fontFile, String fontFamily, Integer fontWeight, FontStyle fontStyle,
boolean subset) {
state._fonts.add(new AddedFont(null, fontFile, fontWeight, fontFamily, subset, fontStyle));
return (TFinalClass) this;
}

/**
* Simpler overload for
* {@link #useFont(File, String, Integer, FontStyle, boolean)}
*
* @param fontFile
* @param fontFamily
* @return this for method chaining
*/
public TFinalClass useFont(File fontFile, String fontFamily) {
return this.useFont(fontFile, fontFamily, 400, FontStyle.NORMAL, true);
}

/**
* Add a font programmatically. If the font is NOT subset, it will be downloaded
* when the renderer is run, otherwise, assuming a font-metrics cache has been configured,
* the font will only be downloaded if required. Therefore, the user could add many fonts,
* confident that only those that are needed will be downloaded and processed.
*
* The InputStream returned by the supplier will be closed by the caller. Fonts
* should generally be subset (Java2D rendered ignores this argument),
* except when used in form controls. FSSupplier is a lambda compatible interface.
*
* Fonts can also be added using a font-face at-rule in the CSS.
*
* @param supplier
* @param fontFamily
* @param fontWeight
* @param fontStyle
* @param subset
* @return
*/
public TFinalClass useFont(FSSupplier<InputStream> supplier, String fontFamily, Integer fontWeight,
FontStyle fontStyle, boolean subset) {
state._fonts.add(new AddedFont(supplier, null, fontWeight, fontFamily, subset, fontStyle));
return (TFinalClass) this;
}

/**
* Simpler overload for
* {@link #useFont(FSSupplier, String, Integer, FontStyle, boolean)}
*
* @param supplier
* @param fontFamily
* @return
*/
public TFinalClass useFont(FSSupplier<InputStream> supplier, String fontFamily) {
return this.useFont(supplier, fontFamily, 400, FontStyle.NORMAL, true);
}

public enum TextDirection {
RTL, LTR
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ xr.text.scale=1.0
# at what font-size should AA kick in. for older JVMs AA is very expensive and slow--set this to
# a high value (like 25); for JDK 6, smoke tests show that AA is basically low-cost for Flying Saucer
# we set it to a high value for the benefit of users still on JDK 1.4
xr.text.aa-fontsize-threshhold=25
xr.text.aa-fontsize-threshhold=7

# when using Java2D for rendering, hint to renderer for AA algorithm to use
xr.text.aa-rendering-hint=RenderingHints.VALUE_TEXT_ANTIALIAS_HGRB
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,7 @@ private static void renderPNG(String html, final String filename) throws Excepti
BufferedImagePageProcessor bufferedImagePageProcessor = new BufferedImagePageProcessor(
BufferedImage.TYPE_INT_RGB, 2.0);
builder.useDefaultPageSize(210, 297, Java2DRendererBuilder.PageSizeUnits.MM);
builder.useEnvironmentFonts(true);

/*
* Render Single Page Image
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package com.openhtmltopdf.testcases.j2d;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import com.openhtmltopdf.visualtest.Java2DVisualTester;
import com.openhtmltopdf.visualtest.Java2DVisualTester.Java2DBuilderConfig;
import com.openhtmltopdf.visualtest.TestSupport;

public class Java2DVisualTest {
private final Java2DVisualTester vtester;
private final List<String> failed = new ArrayList<>();

private Java2DVisualTest() throws IOException {
File outputDirectory = new File("target/test/visual-tests/test-output/j2d");
TestSupport.makeFontFiles();
vtester = new Java2DVisualTester(
"/visualtest/j2d/html/", /* Resource path. */
"/visualtest/j2d/expected/", /* Expected resource path */
outputDirectory
);
}

private void run(String resource, Java2DBuilderConfig config) throws IOException {
if (!vtester.runTest(resource, config)) {
failed.add(resource);
}
}

private void run(String resource) throws IOException {
run(resource, (builder) -> {});
}

private void runAllTests() throws IOException {
run("simple-blocks");
run("simple-text");


// If you add a test here, please remember to also
// add it to runOneTest (commented out).
}

private void runOneTest() throws IOException {
// run("simple-blocks");
// run("simple-text");

// If you add a test here, please remember to also add
// it to runAllTests.
}

// These are not automated tests due to the slight differences between JDK versions
// for Java2D output. Rather they are manual tests meant to be run before a release.
public static void main(String[] args) throws Exception {
Java2DVisualTest test = new Java2DVisualTest();

test.runOneTest();
test.runAllTests();

System.out.println("The failed tests were:");
System.out.println(test.failed);
}
}
Loading

0 comments on commit 9fa3322

Please sign in to comment.