diff options
author | Mehdi Houshmand <mehdi@apache.org> | 2012-03-16 11:44:09 +0000 |
---|---|---|
committer | Mehdi Houshmand <mehdi@apache.org> | 2012-03-16 11:44:09 +0000 |
commit | 0e6c4648996b5bfd38330129fcdfaaa72f86b09c (patch) | |
tree | 38dbbb164c5e355841f7c853e3986816f18bcbee | |
parent | 8661b3a84d3c71a10bba467d5575687c21da25ba (diff) | |
download | xmlgraphics-fop-0e6c4648996b5bfd38330129fcdfaaa72f86b09c.tar.gz xmlgraphics-fop-0e6c4648996b5bfd38330129fcdfaaa72f86b09c.zip |
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
-rw-r--r-- | src/java/org/apache/fop/events/LoggingEventListener.java | 21 | ||||
-rw-r--r-- | src/java/org/apache/fop/fonts/FontEventAdapter.java | 5 | ||||
-rw-r--r-- | src/java/org/apache/fop/fonts/FontEventListener.java | 7 | ||||
-rw-r--r-- | src/java/org/apache/fop/fonts/FontEventProducer.java | 9 | ||||
-rw-r--r-- | src/java/org/apache/fop/fonts/FontEventProducer.xml | 3 | ||||
-rw-r--r-- | src/java/org/apache/fop/fonts/FontInfo.java | 31 | ||||
-rw-r--r-- | src/java/org/apache/fop/svg/ACIUtils.java | 16 | ||||
-rw-r--r-- | src/java/org/apache/fop/tools/fontlist/FontListMain.java | 4 | ||||
-rw-r--r-- | status.xml | 4 | ||||
-rw-r--r-- | test/java/org/apache/fop/fonts/FontEventProcessingTestCase.java | 10 | ||||
-rw-r--r-- | test/java/org/apache/fop/fonts/svg-fonts.fo | 37 |
11 files changed, 118 insertions, 29 deletions
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<String> loggedMessages = new HashSet<String>(); + /** * 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 @@ <message key="fontSubstituted">Font "{requested}" not found. Substituting with "{effective}".</message> <message key="fontLoadingErrorAtAutoDetection">Unable to load font file: {fontURL}.[ Reason: {e}]</message> <message key="glyphNotAvailable">Glyph "{ch}" (0x{ch,hex}[, {ch,glyph-name}]) not available in font "{fontName}".</message> - <message key="fontDirectoryNotFound">'{dir}' does not exist or is not a directory.</message> + <message key="fontDirectoryNotFound">The font directory {dir} could not be found.</message> + <message key="svgTextStrokedAsShapes">The SVG text for font {fontFamily} will be stroked as shapes.</message> </catalogue> 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<String, Typeface> 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<FontTriplet> loggedFontKeys = null; - /** Cache for Font instances. */ private Map<FontTriplet, Map<Integer, Font>> fontInstanceCache = null; @@ -453,22 +445,19 @@ public class FontInfo { return fontTriplets; } - private Set<FontTriplet> getLoggedFontKeys() { - if (loggedFontKeys == null) { - loggedFontKeys = new HashSet<FontTriplet>(); + 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. --> <release version="FOP Trunk" date="TBD"> + <action context="Code" dev="MH" type="fix" fixes-bug="52849" due-to="Luis Bernardo"> + Fixed bug that caused a configured and installed SVG font to stroked, + also added an event indicating when fonts are stroked. + </action> <action context="Code" dev="PH" type="fix"> Fix of a bug introduced when merging ImproveAccessibility. </action> 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 @@ +<?xml version="1.0" standalone="no"?> +<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:svg="http://www.w3.org/2000/svg"> + <fo:layout-master-set> + <fo:simple-page-master master-name="page"> + <fo:region-body /> + </fo:simple-page-master> + </fo:layout-master-set> + <fo:page-sequence master-reference="page"> + <fo:flow flow-name="xsl-region-body"> + <fo:block> + <fo:instream-foreign-object> + <svg:svg width="250" height="50"> + <svg:font horiz-adv-x="1000"> + <svg:font-face font-family="Missing" units-per-em="1000" underline-position="-100" + underline-thickness="50" /> + <svg:glyph unicode="A" horiz-adv-x="686" d="M162,186l362,0l78,-186l84,0l-308,708l-70,0l-308,-708l84,0M343,624l153,-372l-307,0z" /> + <svg:glyph unicode="C" horiz-adv-x="704" d="M620,154C567,72 491,48 417,48C235,48 126,191 126,354C126,517 235,660 417,660C492,660 571,613 599,567l63,47C600,693 505,726 417,726C206,726 48,569 48,354C48,139 206,-18 417,-18C534,-18 632,39 679,112z" /> + <svg:glyph unicode="F" horiz-adv-x="556" d="M168,335l330,0l0,66l-330,0l0,241l355,0l0,66l-427,0l0,-708l72,0z" /> + <svg:glyph unicode="G" horiz-adv-x="778" d="M673,631C610,694 529,726 417,726C206,726 48,569 48,354C48,139 206,-18 417,-18C503,-18 606,7 685,54l0,347l-241,0l0,-66l169,0l0,-237C560,68 490,48 417,48C235,48 126,191 126,354C126,517 235,660 417,660C504,660 571,629 619,578z" /> + </svg:font> + <svg:font horiz-adv-x="1000"> + <!-- this is not Helvetica but it is here to increase coverage and show the code takes expected path --> + <svg:font-face font-family="Helvetica" units-per-em="1000" underline-position="-100" + underline-thickness="50" /> + <svg:glyph unicode="A" horiz-adv-x="686" d="M162,186l362,0l78,-186l84,0l-308,708l-70,0l-308,-708l84,0M343,624l153,-372l-307,0z" /> + <svg:glyph unicode="C" horiz-adv-x="704" d="M620,154C567,72 491,48 417,48C235,48 126,191 126,354C126,517 235,660 417,660C492,660 571,613 599,567l63,47C600,693 505,726 417,726C206,726 48,569 48,354C48,139 206,-18 417,-18C534,-18 632,39 679,112z" /> + <svg:glyph unicode="F" horiz-adv-x="556" d="M168,335l330,0l0,66l-330,0l0,241l355,0l0,66l-427,0l0,-708l72,0z" /> + <svg:glyph unicode="G" horiz-adv-x="778" d="M673,631C610,694 529,726 417,726C206,726 48,569 48,354C48,139 206,-18 417,-18C503,-18 606,7 685,54l0,347l-241,0l0,-66l169,0l0,-237C560,68 490,48 417,48C235,48 126,191 126,354C126,517 235,660 417,660C504,660 571,629 619,578z" /> + </svg:font> + <svg:text x="20" y="20" font-family="Missing" font-size="12">ACFG</svg:text> + <svg:text x="20" y="40" font-family="Helvetica" font-size="12">ACFG</svg:text> + </svg:svg> + </fo:instream-foreign-object> + </fo:block> + </fo:flow> + </fo:page-sequence> +</fo:root> |