Преглед изворни кода

Plugged fonts package into the event subsystem. Note: I did not follow the same pattern as for the rest as the font package is to be considered FOP-external, so I just added a manual adapter for the FontEventListener. This demonstrates how an external library can be integrated with the event system.

Missing warning for unknown formatting objects added. Warning is not issued by the ElementMappingRegistry anymore but by FOTreeBuilder which has access to more context information.

git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_ProcessingFeedback@642975 13f79535-47bb-0310-9956-ffa450edef68
Temp_ProcessingFeedback
Jeremias Maerki пре 16 година
родитељ
комит
0c96509fca

+ 2
- 0
src/java/META-INF/services/org.apache.fop.util.text.AdvancedMessageFormat$PartFactory Прегледај датотеку

@@ -1,4 +1,6 @@
org.apache.fop.util.text.IfFieldPart$Factory
org.apache.fop.util.text.EqualsFieldPart$Factory
org.apache.fop.util.text.ChoiceFieldPart$Factory
org.apache.fop.util.text.HexFieldPart$Factory
org.apache.fop.util.text.GlyphNameFieldPart$Factory
org.apache.fop.events.EventFormatter$LookupFieldPartFactory

+ 4
- 0
src/java/org/apache/fop/events/EventFormatter.xml Прегледај датотеку

@@ -51,6 +51,7 @@ Any reference to it will be considered a reference to the first occurrence in th
<message key="org.apache.fop.fo.FOValidationEventProducer.columnCountErrorOnRegionBodyOverflowScroll">If overflow property is set to "scroll" on {elementName}, a column-count other than "1" may not be specified.{{locator}}</message>
<message key="org.apache.fop.fo.FOValidationEventProducer.invalidFORoot">First element must be the fo:root formatting object. Found {elementName} instead. Please make sure you're producing a valid XSL-FO document.</message>
<message key="org.apache.fop.fo.FOValidationEventProducer.emptyDocument">Document is empty (something might be wrong with your XSLT stylesheet).</message>
<message key="org.apache.fop.fo.FOValidationEventProducer.unknownFormattingObject">Unknown formatting object "{offendingNode}" encountered (a child of {elementName}}.{{locator}}</message>
<message key="org.apache.fop.fo.flow.table.TableEventProducer.nonAutoBPDOnTable">Only a value of "auto" for block-progression-dimension has a well-specified behavior on fo:table. Falling back to "auto".{{locator}}</message>
<message key="org.apache.fop.fo.flow.table.TableEventProducer.noTablePaddingWithCollapsingBorderModel">In collapsing border model a table does not have padding (see http://www.w3.org/TR/REC-CSS2/tables.html#collapsing-borders), but a non-zero value for padding was found. The padding will be ignored.{{locator}}</message>
<message key="org.apache.fop.fo.flow.table.TableEventProducer.noMixRowsAndCells">Either fo:table-rows or fo:table-cells may be children of an {elementName} but not both.{{locator}}</message>
@@ -94,4 +95,7 @@ Any reference to it will be considered a reference to the first occurrence in th
<message key="org.apache.fop.area.AreaEventProducer.pageLoadError">Error while deserializing page {page}.[ Reason: {e}]</message>
<message key="org.apache.fop.area.AreaEventProducer.pageSaveError">Error while serializing page {page}.[ Reason: {e}]</message>
<message key="org.apache.fop.area.AreaEventProducer.pageRenderingError">Error while rendering page {page}.[ Reason: {e}]</message>
<message key="org.apache.fop.fonts.FontEventAdapter.fontSubstituted">Font "{requested}" not found. Substituting with "{effective}".</message>
<message key="org.apache.fop.fonts.FontEventAdapter.fontLoadingErrorAtAutoDetection">Unable to load font file: {fontURL}.[ Reason: {e}]</message>
<message key="org.apache.fop.fonts.FontEventAdapter.glyphNotAvailable">Glyph "{ch}" (0x{ch,hex}[, {ch,glyph-name}]) not available in font "{fontName}".</message>
</catalogue>

+ 1
- 1
src/java/org/apache/fop/fo/ElementMappingRegistry.java Прегледај датотеку

@@ -23,6 +23,7 @@ import java.util.Iterator;
import java.util.Map;

import org.w3c.dom.DOMImplementation;

import org.xml.sax.Locator;

import org.apache.commons.logging.Log;
@@ -144,7 +145,6 @@ public class ElementMappingRegistry {
+ "No element mapping definition found for "
+ FONode.getNodeString(namespaceURI, localName), locator);
} else {
log.warn("Unknown formatting object " + namespaceURI + "^" + localName);
fobjMaker = new UnknownXMLObj.Maker(namespaceURI);
}
}

+ 2
- 0
src/java/org/apache/fop/fo/FOEventHandler.java Прегледај датотеку

@@ -48,6 +48,7 @@ import org.apache.fop.fo.flow.table.TableColumn;
import org.apache.fop.fo.flow.table.TableRow;
import org.apache.fop.fo.pagination.Flow;
import org.apache.fop.fo.pagination.PageSequence;
import org.apache.fop.fonts.FontEventAdapter;
import org.apache.fop.fonts.FontInfo;

/**
@@ -101,6 +102,7 @@ public abstract class FOEventHandler {
public FOEventHandler(FOUserAgent foUserAgent) {
this.foUserAgent = foUserAgent;
this.fontInfo = new FontInfo();
this.fontInfo.setEventListener(new FontEventAdapter(foUserAgent.getEventBroadcaster()));
}

/**

+ 25
- 13
src/java/org/apache/fop/fo/FOTreeBuilder.java Прегледај датотеку

@@ -31,6 +31,8 @@ import org.xml.sax.helpers.DefaultHandler;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.apache.xmlgraphics.util.QName;

import org.apache.fop.apps.FOPException;
import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.apps.FormattingResults;
@@ -181,18 +183,6 @@ public class FOTreeBuilder extends DefaultHandler {
}
}

/**
* Finds the {@link Maker} used to create {@link FONode} objects of a particular type
*
* @param namespaceURI URI for the namespace of the element
* @param localName name of the Element
* @return the ElementMapping.Maker that can create an FO object for this element
* @throws FOPException if a Maker could not be found for a bound namespace.
*/
private Maker findFOMaker(String namespaceURI, String localName) throws FOPException {
return elementMappingRegistry.findFOMaker(namespaceURI, localName, locator);
}

/** {@inheritDoc} */
public void warning(SAXParseException e) {
log.warn(e.getLocalizedMessage());
@@ -374,7 +364,29 @@ public class FOTreeBuilder extends DefaultHandler {
/** {@inheritDoc} */
public void endDocument() throws SAXException {
currentFObj = null;
}
}
/**
* Finds the {@link Maker} used to create {@link FONode} objects of a particular type
*
* @param namespaceURI URI for the namespace of the element
* @param localName name of the Element
* @return the ElementMapping.Maker that can create an FO object for this element
* @throws FOPException if a Maker could not be found for a bound namespace.
*/
private Maker findFOMaker(String namespaceURI, String localName) throws FOPException {
Maker maker = elementMappingRegistry.findFOMaker(namespaceURI, localName, locator);
if (maker instanceof UnknownXMLObj.Maker) {
FOValidationEventProducer eventProducer
= FOValidationEventProducer.Factory.create(
foEventHandler.getUserAgent().getEventBroadcaster());
eventProducer.unknownFormattingObject(this, currentFObj.getName(),
new QName(namespaceURI, localName),
getEffectiveLocator());
}
return maker;
}

}
}


+ 11
- 0
src/java/org/apache/fop/fo/FOValidationEventProducer.java Прегледај датотеку

@@ -333,5 +333,16 @@ public interface FOValidationEventProducer extends EventProducer {
* @event.severity FATAL
*/
void emptyDocument(Object source) throws ValidationException;
/**
* An unknown/unsupported formatting object has been encountered.
* @param source the event source
* @param elementName the name of the context node
* @param offendingNode the offending node
* @param loc the location of the error or null
* @event.severity WARN
*/
void unknownFormattingObject(Object source, String elementName,
QName offendingNode, Locator loc);
}

+ 82
- 0
src/java/org/apache/fop/fonts/FontEventAdapter.java Прегледај датотеку

@@ -0,0 +1,82 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/* $Id$ */
package org.apache.fop.fonts;

import java.util.Map;

import org.apache.fop.events.Event;
import org.apache.fop.events.EventBroadcaster;
import org.apache.fop.events.model.EventSeverity;

/**
* Event listener interface for font-related events. This interface extends FontEventListener
* and EventProducer for integration into FOP's event subsystem.
*/
public class FontEventAdapter implements FontEventListener {

private EventBroadcaster eventBroadcaster;
/**
* Creates a new FontEventAdapter.
* @param broadcaster the event broadcaster to send the generated events to
*/
public FontEventAdapter(EventBroadcaster broadcaster) {
this.eventBroadcaster = broadcaster;
}
/**
* Returns the event group ID.
* @return the event group ID
*/
protected String getEventGroupID() {
return getClass().getName();
}
/** {@inheritDoc} */
public void fontSubstituted(Object source, FontTriplet requested, FontTriplet effective) {
Map params = new java.util.HashMap();
params.put("requested", requested);
params.put("effective", effective);
Event ev = new Event(source, getEventGroupID() + ".fontSubstituted",
EventSeverity.WARN, params);
this.eventBroadcaster.broadcastEvent(ev);
}

/** {@inheritDoc} */
public void fontLoadingErrorAtAutoDetection(Object source, String fontURL, Exception e) {
Map params = new java.util.HashMap();
params.put("fontURL", fontURL);
params.put("e", e);
Event ev = new Event(source, getEventGroupID() + ".fontLoadingErrorAtAutoDetection",
EventSeverity.WARN, params);
this.eventBroadcaster.broadcastEvent(ev);
}

/** {@inheritDoc} */
public void glyphNotAvailable(Object source, char ch, String fontName) {
Map params = new java.util.HashMap();
params.put("ch", new Character(ch));
params.put("fontName", fontName);
Event ev = new Event(source, getEventGroupID() + ".glyphNotAvailable",
EventSeverity.WARN, params);
this.eventBroadcaster.broadcastEvent(ev);
}
}

+ 52
- 0
src/java/org/apache/fop/fonts/FontEventListener.java Прегледај датотеку

@@ -0,0 +1,52 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/* $Id$ */
package org.apache.fop.fonts;


/**
* Event listener interface for font-related events.
*/
public interface FontEventListener {

/**
* Notifies about a font being substituted as the requested one isn't available.
* @param source the event source
* @param requested the requested font triplet
* @param effective the effective font triplet
*/
void fontSubstituted(Object source, FontTriplet requested, FontTriplet effective);

/**
* An error occurred while loading a font for auto-detection.
* @param source the event source
* @param fontURL the font URL
* @param e the original exception
*/
void fontLoadingErrorAtAutoDetection(Object source, String fontURL, Exception e);

/**
* A glyph has been requested that is not available in the font.
* @param source the event source
* @param ch the character for which the glyph isn't available
* @param fontName the name of the font
*/
void glyphNotAvailable(Object source, char ch, String fontName);
}

+ 20
- 2
src/java/org/apache/fop/fonts/FontInfo.java Прегледај датотеку

@@ -67,6 +67,8 @@ public class FontInfo {
/** Cache for Font instances. */
private Map fontInstanceCache = new java.util.HashMap();
private FontEventListener eventListener;
/**
* Main constructor
*/
@@ -77,6 +79,15 @@ public class FontInfo {
this.usedFonts = new java.util.HashMap();
}

/**
* Sets the font event listener that can be used to receive events about particular events
* in this class.
* @param listener the font event listener
*/
public void setEventListener(FontEventListener listener) {
this.eventListener = listener;
}
/**
* Checks if the font setup is valid (At least the ultimate fallback font
* must be registered.)
@@ -158,6 +169,9 @@ public class FontInfo {
public void addMetrics(String name, FontMetrics metrics) {
// add the given metrics as a font with the given name

if (metrics instanceof Typeface) {
((Typeface)metrics).setEventListener(this.eventListener);
}
this.fonts.put(name, metrics);
}

@@ -364,8 +378,12 @@ public class FontInfo {
}
if (!loggedFontKeys.contains(replacedKey)) {
loggedFontKeys.add(replacedKey);
log.warn("Font '" + replacedKey + "' not found. "
+ "Substituting with '" + newKey + "'.");
if (this.eventListener != null) {
this.eventListener.fontSubstituted(this, replacedKey, newKey);
} else {
log.warn("Font '" + replacedKey + "' not found. "
+ "Substituting with '" + newKey + "'.");
}
}
}

+ 1
- 0
src/java/org/apache/fop/fonts/LazyFont.java Прегледај датотеку

@@ -139,6 +139,7 @@ public class LazyFont extends Typeface implements FontDescriptor {
throw new RuntimeException(ioex.getMessage());
}
}
realFont.setEventListener(this.eventListener);
isMetricsLoaded = true;
}
}

+ 16
- 12
src/java/org/apache/fop/fonts/SingleByteFont.java Прегледај датотеку

@@ -117,18 +117,22 @@ public class SingleByteFont extends CustomFont {
}
//Give up, character is not available
Character ch = new Character(c);
if (warnedChars == null) {
warnedChars = new java.util.HashSet();
}
if (warnedChars.size() < 8 && !warnedChars.contains(ch)) {
warnedChars.add(ch);
if (warnedChars.size() == 8) {
log.warn("Many requested glyphs are not available in font " + getFontName());
} else {
log.warn("Glyph " + (int)c + " (0x" + Integer.toHexString(c)
+ ", " + Glyphs.charToGlyphName(c)
+ ") not available in font " + getFontName());
if (this.eventListener != null) {
this.eventListener.glyphNotAvailable(this, c, getFontName());
} else {
Character ch = new Character(c);
if (warnedChars == null) {
warnedChars = new java.util.HashSet();
}
if (warnedChars.size() < 8 && !warnedChars.contains(ch)) {
warnedChars.add(ch);
if (warnedChars.size() == 8) {
log.warn("Many requested glyphs are not available in font " + getFontName());
} else {
log.warn("Glyph " + (int)c + " (0x" + Integer.toHexString(c)
+ ", " + Glyphs.charToGlyphName(c)
+ ") not available in font " + getFontName());
}
}
}
return NOT_FOUND;

+ 12
- 0
src/java/org/apache/fop/fonts/Typeface.java Прегледај датотеку

@@ -30,6 +30,9 @@ public abstract class Typeface implements FontMetrics {
*/
private long charMapOps = 0;
/** An optional event listener that receives events such as missing glyphs etc. */
protected FontEventListener eventListener;
/**
* Get the encoding of the font.
* @return the encoding
@@ -80,5 +83,14 @@ public abstract class Typeface implements FontMetrics {
return getAscender(size);
}
/**
* Sets the font event listener that can be used to receive events about particular events
* in this class.
* @param listener the font event listener
*/
public void setEventListener(FontEventListener listener) {
this.eventListener = listener;
}
}


+ 17
- 3
src/java/org/apache/fop/fonts/autodetect/FontInfoFinder.java Прегледај датотеку

@@ -37,6 +37,7 @@ import org.apache.fop.fonts.CustomFont;
import org.apache.fop.fonts.EmbedFontInfo;
import org.apache.fop.fonts.Font;
import org.apache.fop.fonts.FontCache;
import org.apache.fop.fonts.FontEventListener;
import org.apache.fop.fonts.FontLoader;
import org.apache.fop.fonts.FontResolver;
import org.apache.fop.fonts.FontTriplet;
@@ -50,6 +51,17 @@ public class FontInfoFinder {
/** logging instance */
private Log log = LogFactory.getLog(FontInfoFinder.class);

private FontEventListener eventListener;
/**
* Sets the font event listener that can be used to receive events about particular events
* in this class.
* @param listener the font event listener
*/
public void setEventListener(FontEventListener listener) {
this.eventListener = listener;
}
/**
* Attempts to determine FontTriplets from a given CustomFont.
* It seems to be fairly accurate but will probably require some tweaking over time
@@ -189,15 +201,17 @@ public class FontInfoFinder {
try {
customFont = FontLoader.loadFont(fontUrl, resolver);
} catch (Exception e) {
//TODO Too verbose (it's an error but we don't care if some fonts can't be loaded)
if (log.isErrorEnabled()) {
log.error("Unable to load font file: " + embedUrl + ". Reason: " + e.getMessage());
if (this.eventListener != null) {
this.eventListener.fontLoadingErrorAtAutoDetection(this, embedUrl, e);
}
if (fontCache != null) {
fontCache.registerFailedFont(embedUrl, fileLastModified);
}
return null;
}
if (this.eventListener != null) {
customFont.setEventListener(this.eventListener);
}
return fontInfoFromCustomFont(fontUrl, customFont, fontCache);
}
}

+ 89
- 0
src/java/org/apache/fop/util/text/GlyphNameFieldPart.java Прегледај датотеку

@@ -0,0 +1,89 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/* $Id$ */

package org.apache.fop.util.text;

import java.util.Map;

import org.apache.xmlgraphics.fonts.Glyphs;

import org.apache.fop.util.text.AdvancedMessageFormat.Part;
import org.apache.fop.util.text.AdvancedMessageFormat.PartFactory;

/**
* Function formatting a character to a glyph name.
*/
public class GlyphNameFieldPart implements Part {

private String fieldName;
/**
* Creates a new glyph name field part
* @param fieldName the field name
*/
public GlyphNameFieldPart(String fieldName) {
this.fieldName = fieldName;
}
/** {@inheritDoc} */
public boolean isGenerated(Map params) {
Object obj = params.get(fieldName);
return obj != null && getGlyphName(obj).length() > 0;
}
private String getGlyphName(Object obj) {
if (obj instanceof Character) {
return Glyphs.charToGlyphName(((Character)obj).charValue());
} else {
throw new IllegalArgumentException(
"Value for glyph name part must be a Character but was: "
+ obj.getClass().getName());
}
}

/** {@inheritDoc} */
public void write(StringBuffer sb, Map params) {
if (!params.containsKey(fieldName)) {
throw new IllegalArgumentException(
"Message pattern contains unsupported field name: " + fieldName);
}
Object obj = params.get(fieldName);
sb.append(getGlyphName(obj));
}

/** {@inheritDoc} */
public String toString() {
return "{" + this.fieldName + ",glyph-name}";
}
/** Factory for {@link GlyphNameFieldPart}. */
public static class Factory implements PartFactory {

/** {@inheritDoc} */
public Part newPart(String fieldName, String values) {
return new GlyphNameFieldPart(fieldName);
}
/** {@inheritDoc} */
public String getFormat() {
return "glyph-name";
}
}
}

+ 84
- 0
src/java/org/apache/fop/util/text/HexFieldPart.java Прегледај датотеку

@@ -0,0 +1,84 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/* $Id$ */

package org.apache.fop.util.text;

import java.util.Map;

import org.apache.fop.util.text.AdvancedMessageFormat.Part;
import org.apache.fop.util.text.AdvancedMessageFormat.PartFactory;

/**
* Function formatting a number or character to a hex value.
*/
public class HexFieldPart implements Part {

private String fieldName;
/**
* Creates a new hex field part
* @param fieldName the field name
*/
public HexFieldPart(String fieldName) {
this.fieldName = fieldName;
}
/** {@inheritDoc} */
public boolean isGenerated(Map params) {
Object obj = params.get(fieldName);
return obj != null;
}

/** {@inheritDoc} */
public void write(StringBuffer sb, Map params) {
if (!params.containsKey(fieldName)) {
throw new IllegalArgumentException(
"Message pattern contains unsupported field name: " + fieldName);
}
Object obj = params.get(fieldName);
if (obj instanceof Character) {
sb.append(Integer.toHexString(((Character)obj).charValue()));
} else if (obj instanceof Number) {
sb.append(Integer.toHexString(((Number)obj).intValue()));
} else {
throw new IllegalArgumentException("Incompatible value for hex field part: "
+ obj.getClass().getName());
}
}

/** {@inheritDoc} */
public String toString() {
return "{" + this.fieldName + ",hex}";
}
/** Factory for {@link HexFieldPart}. */
public static class Factory implements PartFactory {

/** {@inheritDoc} */
public Part newPart(String fieldName, String values) {
return new HexFieldPart(fieldName);
}
/** {@inheritDoc} */
public String getFormat() {
return "hex";
}
}
}

Loading…
Откажи
Сачувај