From 0e6c4648996b5bfd38330129fcdfaaa72f86b09c Mon Sep 17 00:00:00 2001 From: Mehdi Houshmand Date: Fri, 16 Mar 2012 11:44:09 +0000 Subject: [PATCH] Bugzila#52849: SVG font being painted as shapes when font present in the system git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@1301445 13f79535-47bb-0310-9956-ffa450edef68 --- .../fop/events/LoggingEventListener.java | 21 ++++++++++- .../apache/fop/fonts/FontEventAdapter.java | 5 +++ .../apache/fop/fonts/FontEventListener.java | 7 ++++ .../apache/fop/fonts/FontEventProducer.java | 9 ++++- .../apache/fop/fonts/FontEventProducer.xml | 3 +- src/java/org/apache/fop/fonts/FontInfo.java | 31 +++++----------- src/java/org/apache/fop/svg/ACIUtils.java | 16 ++++++-- .../fop/tools/fontlist/FontListMain.java | 4 ++ status.xml | 4 ++ .../fonts/FontEventProcessingTestCase.java | 10 +++++ test/java/org/apache/fop/fonts/svg-fonts.fo | 37 +++++++++++++++++++ 11 files changed, 118 insertions(+), 29 deletions(-) create mode 100644 test/java/org/apache/fop/fonts/svg-fonts.fo diff --git a/src/java/org/apache/fop/events/LoggingEventListener.java b/src/java/org/apache/fop/events/LoggingEventListener.java index 58fbb7f97..7df05f6d3 100644 --- a/src/java/org/apache/fop/events/LoggingEventListener.java +++ b/src/java/org/apache/fop/events/LoggingEventListener.java @@ -19,6 +19,9 @@ package org.apache.fop.events; +import java.util.HashSet; +import java.util.Set; + import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -36,6 +39,8 @@ public class LoggingEventListener implements EventListener { private Log log; private boolean skipFatal; + private final Set loggedMessages = new HashSet(); + /** * Creates an instance logging to the default log category of this class. */ @@ -77,7 +82,20 @@ public class LoggingEventListener implements EventListener { if (severity == EventSeverity.INFO) { log.info(msg); } else if (severity == EventSeverity.WARN) { - log.warn(msg); + // we want to prevent logging of duplicate messages in situations where they are likely + // to occur; for instance, warning related to layout do not repeat (since line number + // will be different) and as such we do not try to filter them here; on the other hand, + // font related warnings are very likely to repeat and we try to filter them out here; + // the same may happen with missing images (but not implemented yet). + String eventGroupID = event.getEventGroupID(); + if (eventGroupID.equals("org.apache.fop.fonts.FontEventProducer")) { + if (!loggedMessages.contains(msg)) { + loggedMessages.add(msg); + log.warn(msg); + } + } else { + log.warn(msg); + } } else if (severity == EventSeverity.ERROR) { if (event.getParam("e") != null) { log.error(msg, (Throwable)event.getParam("e")); @@ -96,5 +114,4 @@ public class LoggingEventListener implements EventListener { assert false; } } - } diff --git a/src/java/org/apache/fop/fonts/FontEventAdapter.java b/src/java/org/apache/fop/fonts/FontEventAdapter.java index 85a43393e..e8078a796 100644 --- a/src/java/org/apache/fop/fonts/FontEventAdapter.java +++ b/src/java/org/apache/fop/fonts/FontEventAdapter.java @@ -66,4 +66,9 @@ public class FontEventAdapter implements FontEventListener { getEventProducer().fontDirectoryNotFound(source, dir); } + /** {@inheritDoc} */ + public void svgTextStrokedAsShapes(Object source, String fontFamily) { + getEventProducer().svgTextStrokedAsShapes(source, fontFamily); + } + } diff --git a/src/java/org/apache/fop/fonts/FontEventListener.java b/src/java/org/apache/fop/fonts/FontEventListener.java index 5f9e7b6c6..419a3fcd2 100644 --- a/src/java/org/apache/fop/fonts/FontEventListener.java +++ b/src/java/org/apache/fop/fonts/FontEventListener.java @@ -54,4 +54,11 @@ public interface FontEventListener { * @param dir the directory in the config file */ void fontDirectoryNotFound(Object source, String dir); + + /** + * The SVG text will be stroked as shapes. + * @param source the event source + * @param fontFamily the family name of the font that is being stroked + */ + void svgTextStrokedAsShapes(Object source, String fontFamily); } diff --git a/src/java/org/apache/fop/fonts/FontEventProducer.java b/src/java/org/apache/fop/fonts/FontEventProducer.java index 702d3efb6..60dbcc6ad 100644 --- a/src/java/org/apache/fop/fonts/FontEventProducer.java +++ b/src/java/org/apache/fop/fonts/FontEventProducer.java @@ -73,10 +73,17 @@ public interface FontEventProducer extends EventProducer { /** * An error occurred trying to find the font directory specified in the config file. - * @param source the event sourece + * @param source the event source * @param dir the directory in the config file * @event.severity WARN */ void fontDirectoryNotFound(Object source, String dir); + /** + * The SVG text will be stroked as shapes. + * @param source the event source + * @param fontFamily the family name of the font that is being stroked + * @event.severity WARN + */ + void svgTextStrokedAsShapes(Object source, String fontFamily); } diff --git a/src/java/org/apache/fop/fonts/FontEventProducer.xml b/src/java/org/apache/fop/fonts/FontEventProducer.xml index 27fd587b1..d7ce27e7a 100644 --- a/src/java/org/apache/fop/fonts/FontEventProducer.xml +++ b/src/java/org/apache/fop/fonts/FontEventProducer.xml @@ -20,5 +20,6 @@ Font "{requested}" not found. Substituting with "{effective}". Unable to load font file: {fontURL}.[ Reason: {e}] Glyph "{ch}" (0x{ch,hex}[, {ch,glyph-name}]) not available in font "{fontName}". - '{dir}' does not exist or is not a directory. + The font directory {dir} could not be found. + The SVG text for font {fontFamily} will be stroked as shapes. diff --git a/src/java/org/apache/fop/fonts/FontInfo.java b/src/java/org/apache/fop/fonts/FontInfo.java index 5c9c63a98..a38a5b480 100644 --- a/src/java/org/apache/fop/fonts/FontInfo.java +++ b/src/java/org/apache/fop/fonts/FontInfo.java @@ -22,10 +22,8 @@ package org.apache.fop.fonts; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; -import java.util.HashSet; import java.util.List; import java.util.Map; -import java.util.Set; import java.util.SortedSet; import java.util.TreeSet; @@ -59,12 +57,6 @@ public class FontInfo { /** look up a font-name to get a font (that implements FontMetrics at least) */ private Map fonts = null; //(String = font key) - /** - * a collection of missing fonts; used to make sure the user gets - * a warning for a missing font only once (not every time the font is used) - */ - private Set loggedFontKeys = null; - /** Cache for Font instances. */ private Map> fontInstanceCache = null; @@ -453,22 +445,19 @@ public class FontInfo { return fontTriplets; } - private Set getLoggedFontKeys() { - if (loggedFontKeys == null) { - loggedFontKeys = new HashSet(); + private void notifyFontReplacement(FontTriplet replacedKey, FontTriplet newKey) { + if (this.eventListener != null) { + this.eventListener.fontSubstituted(this, replacedKey, newKey); } - return loggedFontKeys; } - private void notifyFontReplacement(FontTriplet replacedKey, FontTriplet newKey) { - if (!getLoggedFontKeys().contains(replacedKey)) { - getLoggedFontKeys().add(replacedKey); - if (this.eventListener != null) { - this.eventListener.fontSubstituted(this, replacedKey, newKey); - } else { - log.warn("Font '" + replacedKey + "' not found. " - + "Substituting with '" + newKey + "'."); - } + /** + * Notify listeners that the SVG text for the given font will be stroked as shapes. + * @param fontFamily a SVG font family + */ + public void notifyStrokingSVGTextAsShapes(String fontFamily) { + if (this.eventListener != null) { + this.eventListener.svgTextStrokedAsShapes(this, fontFamily); } } diff --git a/src/java/org/apache/fop/svg/ACIUtils.java b/src/java/org/apache/fop/svg/ACIUtils.java index 64552b303..924ca1d51 100644 --- a/src/java/org/apache/fop/svg/ACIUtils.java +++ b/src/java/org/apache/fop/svg/ACIUtils.java @@ -28,13 +28,12 @@ import java.util.Map; import java.util.Map.Entry; import java.util.Set; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - import org.apache.batik.bridge.SVGFontFamily; import org.apache.batik.gvt.font.GVTFont; import org.apache.batik.gvt.font.GVTFontFamily; import org.apache.batik.gvt.text.GVTAttributedCharacterIterator; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.apache.fop.fonts.Font; import org.apache.fop.fonts.FontInfo; @@ -96,9 +95,10 @@ public final class ACIUtils { } if (gvtFonts != null) { + boolean haveInstanceOfSVGFontFamily = false; for (GVTFontFamily fam : gvtFonts) { if (fam instanceof SVGFontFamily) { - return null; //Let Batik paint this text! + haveInstanceOfSVGFontFamily = true; } String fontFamily = fam.getFamilyName(); if (fontInfo.hasFont(fontFamily, style, weight)) { @@ -116,6 +116,14 @@ public final class ACIUtils { firstFontFamily = fontFamily; } } + // SVG fonts are embedded fonts in the SVG document and are rarely used; however if they + // are used but the fonts also exists in the system and are known to FOP then FOP should + // use them; then the decision whether Batik should stroke the text should be made after + // no matching fonts are found + if (fonts.isEmpty() && haveInstanceOfSVGFontFamily) { + fontInfo.notifyStrokingSVGTextAsShapes(firstFontFamily); + return null; // Let Batik paint this text! + } } if (fonts.isEmpty()) { if (firstFontFamily == null) { diff --git a/src/java/org/apache/fop/tools/fontlist/FontListMain.java b/src/java/org/apache/fop/tools/fontlist/FontListMain.java index 92c2acffd..b9b01f706 100644 --- a/src/java/org/apache/fop/tools/fontlist/FontListMain.java +++ b/src/java/org/apache/fop/tools/fontlist/FontListMain.java @@ -147,6 +147,10 @@ public final class FontListMain { //ignore } + public void svgTextStrokedAsShapes(Object source, String fontFamily) { + // ignore + } + }; FontListGenerator listGenerator = new FontListGenerator(); diff --git a/status.xml b/status.xml index 4d6914e9f..52bf109c4 100644 --- a/status.xml +++ b/status.xml @@ -62,6 +62,10 @@ documents. Example: the fix of marks layering will be such a case when it's done. --> + + Fixed bug that caused a configured and installed SVG font to stroked, + also added an event indicating when fonts are stroked. + Fix of a bug introduced when merging ImproveAccessibility. diff --git a/test/java/org/apache/fop/fonts/FontEventProcessingTestCase.java b/test/java/org/apache/fop/fonts/FontEventProcessingTestCase.java index 898f83197..c17062e7b 100644 --- a/test/java/org/apache/fop/fonts/FontEventProcessingTestCase.java +++ b/test/java/org/apache/fop/fonts/FontEventProcessingTestCase.java @@ -57,4 +57,14 @@ public class FontEventProcessingTestCase { MimeConstants.MIME_PDF); } + @Test + public void testSVGFontStrokedAsShapes() throws FOPException, TransformerException, IOException, + SAXException { + // svg-fonts.fo embeds two fonts; one that is present in the system and the other is not; the + // missing font is stroked as shapes while the fonts that exists is stroked as text + InputStream inStream = getClass().getResourceAsStream("svg-fonts.fo"); + eventsTests.doTest(inStream, null, FontEventProducer.class.getName() + ".svgTextStrokedAsShapes", + MimeConstants.MIME_PDF); + } + } diff --git a/test/java/org/apache/fop/fonts/svg-fonts.fo b/test/java/org/apache/fop/fonts/svg-fonts.fo new file mode 100644 index 000000000..0c5f3f599 --- /dev/null +++ b/test/java/org/apache/fop/fonts/svg-fonts.fo @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + ACFG + ACFG + + + + + + -- 2.39.5