git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@1400890 13f79535-47bb-0310-9956-ffa450edef68tags/fop-2_0
@@ -19,6 +19,8 @@ | |||
package org.apache.fop.area; | |||
import java.util.Locale; | |||
// block areas hold either more block areas or line | |||
// areas can also be used as a block spacer | |||
@@ -63,8 +65,9 @@ public class Block extends BlockParent { | |||
/** if true, allow BPD update */ | |||
protected transient boolean allowBPDUpdate = true; | |||
// a block with may contain the dominant styling info in | |||
// terms of most lines or blocks with info | |||
private Locale locale; | |||
private String location; | |||
/** | |||
* Add the block to this block area. | |||
@@ -140,5 +143,37 @@ public class Block extends BlockParent { | |||
return (endIndent != null ? endIndent : 0); | |||
} | |||
/** | |||
* Sets the language information coming from the FO that generated this area. | |||
*/ | |||
public void setLocale(Locale locale) { | |||
this.locale = locale; | |||
} | |||
/** | |||
* Returns the language information for the FO that generated this area. | |||
*/ | |||
public Locale getLocale() { | |||
return locale; | |||
} | |||
/** | |||
* Sets the location in the source XML of the FO that generated this area. | |||
* | |||
* @location the line and column location | |||
*/ | |||
public void setLocation(String location) { | |||
this.location = location; | |||
} | |||
/** | |||
* Returns the location in the source XML of the FO that generated this area. | |||
* | |||
* @return the line and column location, {@code null} if that information is not available | |||
*/ | |||
public String getLocation() { | |||
return location; | |||
} | |||
} | |||
@@ -565,7 +565,7 @@ public abstract class FONode implements Cloneable { | |||
/** | |||
* Helper function to return "not supported child" exceptions. Note that the child is valid, just not | |||
* supported yet by FOP. | |||
* | |||
* | |||
* @param loc org.xml.sax.Locator object of the error (*not* parent node) | |||
* @param nsURI namespace URI of incoming invalid node | |||
* @param lName local name (i.e., no prefix) of incoming node | |||
@@ -663,7 +663,7 @@ public abstract class FONode implements Cloneable { | |||
if (loc == null) { | |||
return "Unknown location"; | |||
} else { | |||
return loc.getLineNumber() + "/" + loc.getColumnNumber(); | |||
return loc.getLineNumber() + ":" + loc.getColumnNumber(); | |||
} | |||
} | |||
@@ -31,6 +31,7 @@ import org.apache.fop.area.Area; | |||
import org.apache.fop.area.Block; | |||
import org.apache.fop.area.LineArea; | |||
import org.apache.fop.datatypes.Length; | |||
import org.apache.fop.fo.FONode; | |||
import org.apache.fop.fo.properties.KeepProperty; | |||
import org.apache.fop.fonts.Font; | |||
import org.apache.fop.fonts.FontInfo; | |||
@@ -381,6 +382,8 @@ public class BlockLayoutManager extends BlockStackingLayoutManager implements Co | |||
startIndent, endIndent, | |||
this); | |||
curBlockArea.setLocale(getBlockFO().getCommonHyphenation().getLocale()); | |||
curBlockArea.setLocation(FONode.getLocatorString(getBlockFO().getLocator())); | |||
setCurrentArea(curBlockArea); // ??? for generic operations | |||
} | |||
return curBlockArea; |
@@ -51,6 +51,8 @@ public class IFContext { | |||
private String id = ""; | |||
private String location; | |||
/** | |||
* Main constructor. | |||
* @param ua the user agent | |||
@@ -179,4 +181,23 @@ public class IFContext { | |||
return id; | |||
} | |||
/** | |||
* Sets the location of the object enclosing the current content. | |||
* | |||
* @location the line and column location of the object in the source FO file | |||
*/ | |||
public void setLocation(String location) { | |||
this.location = location; | |||
} | |||
/** | |||
* Returns the location of the object enclosing the current content. | |||
* | |||
* @return the line and column location of the object in the source FO file, | |||
* {@code null} if that information is not available | |||
*/ | |||
public String getLocation() { | |||
return location; | |||
} | |||
} |
@@ -965,7 +965,14 @@ public class IFRenderer extends AbstractPathOrientedRenderer { | |||
} | |||
saveBlockPosIfTargetable(block); | |||
pushdID(block); | |||
IFContext context = documentHandler.getContext(); | |||
Locale oldLocale = context.getLanguage(); | |||
context.setLanguage(block.getLocale()); | |||
String oldLocation = context.getLocation(); | |||
context.setLocation(block.getLocation()); | |||
super.renderBlock(block); | |||
context.setLocation(oldLocation); | |||
context.setLanguage(oldLocale); | |||
popID(block); | |||
} | |||
@@ -74,4 +74,13 @@ public interface PDFEventProducer extends EventProducer { | |||
* @event.severity WARN | |||
*/ | |||
void incorrectEncryptionLength(Object source, int originalValue, int correctedValue); | |||
/** | |||
* The language of a piece of text is unknown. | |||
* | |||
* @param source the event source | |||
* @param location location in the source FO file, if any | |||
*/ | |||
void unknownLanguage(Object source, String location); | |||
} |
@@ -3,4 +3,5 @@ | |||
<message key="nonFullyResolvedLinkTargets">{count} link target{count,equals,1,,s} could not be fully resolved and now point{count,equals,1,,s} to the top of the page or {count,equals,1,is,are} dysfunctional.</message> | |||
<message key="nonStandardStructureType">‘{type}’ is not a standard structure type defined by the PDF Reference. Falling back to ‘{fallback}’.</message> | |||
<message key="incorrectEncryptionLength">Encryption length must be a multiple of 8 between 40 and 128. Setting encryption length to {correctedValue} instead of {originalValue}.</message> | |||
<message key="unknownLanguage">A piece of text or an image’s alternate text is missing language information [(See position {location})|(No context info available)]</message> | |||
</catalogue> |
@@ -26,6 +26,9 @@ import java.awt.Point; | |||
import java.awt.Rectangle; | |||
import java.awt.geom.AffineTransform; | |||
import java.io.IOException; | |||
import java.util.HashSet; | |||
import java.util.Locale; | |||
import java.util.Set; | |||
import org.w3c.dom.Document; | |||
@@ -40,6 +43,7 @@ import org.apache.fop.pdf.PDFTextUtil; | |||
import org.apache.fop.pdf.PDFXObject; | |||
import org.apache.fop.render.RenderingContext; | |||
import org.apache.fop.render.intermediate.AbstractIFPainter; | |||
import org.apache.fop.render.intermediate.IFContext; | |||
import org.apache.fop.render.intermediate.IFException; | |||
import org.apache.fop.render.intermediate.IFState; | |||
import org.apache.fop.render.intermediate.IFUtil; | |||
@@ -65,6 +69,41 @@ public class PDFPainter extends AbstractIFPainter<PDFDocumentHandler> { | |||
private PDFLogicalStructureHandler logicalStructureHandler; | |||
private final LanguageAvailabilityChecker languageAvailabilityChecker; | |||
private static class LanguageAvailabilityChecker { | |||
private final IFContext context; | |||
private final Set<String> reportedLocations = new HashSet<String>(); | |||
LanguageAvailabilityChecker(IFContext context) { | |||
this.context = context; | |||
} | |||
private void checkLanguageAvailability(String text) { | |||
Locale locale = context.getLanguage(); | |||
if (locale == null && containsLettersOrDigits(text)) { | |||
String location = context.getLocation(); | |||
if (!reportedLocations.contains(location)) { | |||
PDFEventProducer.Provider.get(context.getUserAgent().getEventBroadcaster()) | |||
.unknownLanguage(this, location); | |||
reportedLocations.add(location); | |||
} | |||
} | |||
} | |||
private boolean containsLettersOrDigits(String text) { | |||
for (int i = 0; i < text.length(); i++) { | |||
if (Character.isLetterOrDigit(text.charAt(i))) { | |||
return true; | |||
} | |||
} | |||
return false; | |||
} | |||
} | |||
/** | |||
* Default constructor. | |||
* @param documentHandler the parent document handler | |||
@@ -78,6 +117,9 @@ public class PDFPainter extends AbstractIFPainter<PDFDocumentHandler> { | |||
this.borderPainter = new PDFBorderPainter(this.generator); | |||
this.state = IFState.create(); | |||
accessEnabled = this.getUserAgent().isAccessibilityEnabled(); | |||
languageAvailabilityChecker = accessEnabled | |||
? new LanguageAvailabilityChecker(documentHandler.getContext()) | |||
: null; | |||
} | |||
/** {@inheritDoc} */ | |||
@@ -130,6 +172,9 @@ public class PDFPainter extends AbstractIFPainter<PDFDocumentHandler> { | |||
private void prepareImageMCID(PDFStructElem structElem) { | |||
imageMCI = logicalStructureHandler.addImageContentItem(structElem); | |||
if (structElem != null) { | |||
languageAvailabilityChecker.checkLanguageAvailability((String) structElem.get("Alt")); | |||
} | |||
} | |||
/** {@inheritDoc} */ | |||
@@ -274,6 +319,7 @@ public class PDFPainter extends AbstractIFPainter<PDFDocumentHandler> { | |||
throws IFException { | |||
if (accessEnabled) { | |||
PDFStructElem structElem = (PDFStructElem) getContext().getStructureTreeElement(); | |||
languageAvailabilityChecker.checkLanguageAvailability(text); | |||
MarkedContentInfo mci = logicalStructureHandler.addTextContentItem(structElem); | |||
if (generator.getTextUtil().isInTextObject()) { | |||
generator.separateTextElements(mci.tag, mci.mcid); |
@@ -59,6 +59,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="Renderers" dev="VH" type="add" fixes-bug="54037"> | |||
PDF output: Issue a warning when accessibility is enabled and language information is | |||
missing. | |||
</action> | |||
<action context="Renderers" dev="VH" type="add" fixes-bug="53980"> | |||
PDF accessibility: Store language information coming from fo:block or fo:character in the | |||
structure tree. |