]> source.dussan.org Git - xmlgraphics-fop.git/commitdiff
Bugzila#52849: SVG font being painted as shapes when font present in the system
authorMehdi Houshmand <mehdi@apache.org>
Fri, 16 Mar 2012 11:44:09 +0000 (11:44 +0000)
committerMehdi Houshmand <mehdi@apache.org>
Fri, 16 Mar 2012 11:44:09 +0000 (11:44 +0000)
git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@1301445 13f79535-47bb-0310-9956-ffa450edef68

src/java/org/apache/fop/events/LoggingEventListener.java
src/java/org/apache/fop/fonts/FontEventAdapter.java
src/java/org/apache/fop/fonts/FontEventListener.java
src/java/org/apache/fop/fonts/FontEventProducer.java
src/java/org/apache/fop/fonts/FontEventProducer.xml
src/java/org/apache/fop/fonts/FontInfo.java
src/java/org/apache/fop/svg/ACIUtils.java
src/java/org/apache/fop/tools/fontlist/FontListMain.java
status.xml
test/java/org/apache/fop/fonts/FontEventProcessingTestCase.java
test/java/org/apache/fop/fonts/svg-fonts.fo [new file with mode: 0644]

index 58fbb7f972af7943e26128de600f2e4a391b22c3..7df05f6d3a355d4d5399c9e20ec7dff09ce20ecb 100644 (file)
@@ -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;
         }
     }
-
 }
index 85a43393e8f52620639d38fc16dd56ddfcf8d771..e8078a7968a4ba90732114555e8ec33748abd5c5 100644 (file)
@@ -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);
+    }
+
 }
index 5f9e7b6c69b023f3391cc1f57bfbded38d81bb85..419a3fcd2c5fcf161c3feba643716a3f7f522147 100644 (file)
@@ -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);
 }
index 702d3efb6df47249af128dad4417a45c9b68544e..60dbcc6ad8e94a8730625b53ca22e614d12e6992 100644 (file)
@@ -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);
 }
index 27fd587b172a7ffd51bb24aae7a36298a7aac062..d7ce27e7aeb12e54cd5876b476237e2bb717b77b 100644 (file)
@@ -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>
index 5c9c63a98e7337fac55a5c988fe27f017af800c7..a38a5b4804ffc9c2aaaabdd7682a2b0154cc16e7 100644 (file)
@@ -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);
         }
     }
 
index 64552b303532f89e683916f0ce9685ad6892fdae..924ca1d51c7b0565ad2b799f118e6ad5fde6daa1 100644 (file)
@@ -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) {
index 92c2acffdb0fdd8b08cfe0299ad6fb88b0fae9f0..b9b01f70638960ab5c2b7a94a3d02cbb608c2b79 100644 (file)
@@ -147,6 +147,10 @@ public final class FontListMain {
                 //ignore
             }
 
+            public void svgTextStrokedAsShapes(Object source, String fontFamily) {
+                // ignore
+            }
+
         };
 
         FontListGenerator listGenerator = new FontListGenerator();
index 4d6914e9f1b636c9e52edba9b1e7666b5c19e09a..52bf109c436e196cd23962366bad935f6a4f5ecc 100644 (file)
       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>
index 898f83197ca63652fea1081476ad447d548b0dd7..c17062e7beb01ace6977ee6f96979967a5af74e1 100644 (file)
@@ -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 (file)
index 0000000..0c5f3f5
--- /dev/null
@@ -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>