deweese 01/10/29 13:13:41 Modified: sources/org/apache/batik/ext/awt/image/codec PNGEncodeParam.java sources/org/apache/batik/gvt/font AWTFontFamily.java AWTGVTFont.java sources/org/apache/batik/gvt/renderer StrokingTextPainter.java sources/org/apache/batik/gvt/text ArabicTextHandler.java AttributedCharacterSpanIterator.java BidiAttributedCharacterIterator.java Log: 1) 7-10x improvement in PNG encoding time. 2) Improved arabic text handling interface to avoid needing to construct AttributedString. 3) Reindented some of the GVT Text stuff. Revision Changes Path 1.2 +103 -81 xml-batik/sources/org/apache/batik/ext/awt/image/codec/PNGEncodeParam.java Index: PNGEncodeParam.java =================================================================== RCS file: /home/cvs/xml-batik/sources/org/apache/batik/ext/awt/image/codec/PNGEncodeParam.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- PNGEncodeParam.java 2001/01/23 17:07:13 1.1 +++ PNGEncodeParam.java 2001/10/29 21:13:41 1.2 @@ -1362,96 +1362,118 @@ byte[][] scratchRows, int bytesPerRow, int bytesPerPixel) { - int[] filterBadness = new int[5]; - for (int i = 0; i < 5; i++) { - filterBadness[i] = Integer.MAX_VALUE; - } - - { - int badness = 0; - - for (int i = bytesPerPixel; i < bytesPerRow + bytesPerPixel; i++) { - int curr = currRow[i] & 0xff; - badness += curr; - } - - filterBadness[0] = badness; - } - - { - byte[] subFilteredRow = scratchRows[1]; - int badness = 0; - - for (int i = bytesPerPixel; i < bytesPerRow + bytesPerPixel; i++) { - int curr = currRow[i] & 0xff; - int left = currRow[i - bytesPerPixel] & 0xff; - int difference = curr - left; - subFilteredRow[i] = (byte)difference; - - badness += abs(difference); - } - - filterBadness[1] = badness; - } - - { - byte[] upFilteredRow = scratchRows[2]; - int badness = 0; - - for (int i = bytesPerPixel; i < bytesPerRow + bytesPerPixel; i++) { - int curr = currRow[i] & 0xff; - int up = prevRow[i] & 0xff; - int difference = curr - up; - upFilteredRow[i] = (byte)difference; + + int [] badness = {0, 0, 0, 0, 0}; + int curr, left, up, upleft, diff; + int pa, pb, pc; + for (int i = bytesPerPixel; i < bytesPerRow + bytesPerPixel; i++) { + curr = currRow[i] & 0xff; + left = currRow[i - bytesPerPixel] & 0xff; + up = prevRow[i] & 0xff; + upleft = prevRow[i - bytesPerPixel] & 0xff; - badness += abs(difference); - } - - filterBadness[2] = badness; - } - - { - byte[] averageFilteredRow = scratchRows[3]; - int badness = 0; + // no filter + badness[0] += curr; - for (int i = bytesPerPixel; i < bytesPerRow + bytesPerPixel; i++) { - int curr = currRow[i] & 0xff; - int left = currRow[i - bytesPerPixel] & 0xff; - int up = prevRow[i] & 0xff; - int difference = curr - (left + up)/2;; - averageFilteredRow[i] = (byte)difference; + // sub filter + diff = curr - left; + scratchRows[1][i] = (byte)diff; + badness [1] += (diff>0)?diff:-diff; + + // up filter + diff = curr - up; + scratchRows[2][i] = (byte)diff; + badness [2] += (diff>=0)?diff:-diff; - badness += abs(difference); - } - - filterBadness[3] = badness; - } - - { - byte[] paethFilteredRow = scratchRows[4]; - int badness = 0; - - for (int i = bytesPerPixel; i < bytesPerRow + bytesPerPixel; i++) { - int curr = currRow[i] & 0xff; - int left = currRow[i - bytesPerPixel] & 0xff; - int up = prevRow[i] & 0xff; - int upleft = prevRow[i - bytesPerPixel] & 0xff; - int predictor = paethPredictor(left, up, upleft); - int difference = curr - predictor; - paethFilteredRow[i] = (byte)difference; + // average filter + diff = curr - ((left+up)>>1); + scratchRows[3][i] = (byte)diff; + badness [3] += (diff>=0)?diff:-diff; - badness += abs(difference); + // paeth filter + + // Original code much simplier but doesn't take full + // advantage of relationship between pa/b/c and + // information gleaned in abs operations. + /// pa = up -upleft; + /// pb = left-upleft; + /// pc = pa+pb; + /// pa = abs(pa); + /// pb = abs(pb); + /// pc = abs(pc); + /// if ((pa <= pb) && (pa <= pc)) + /// diff = curr-left; + /// else if (pb <= pc) + /// diff = curr-up; + /// else + /// diff = curr-upleft; + + pa = up -upleft; + pb = left-upleft; + if (pa<0) { + if (pb<0) { + // both pa & pb neg so pc is always greater than or + // equal to pa or pb; + if (pa >= pb) // since pa & pb neg check sense is reversed. + diff = curr-left; + else + diff = curr-up; + } else { + // pa neg pb pos so we must compute pc... + pc = pa+pb; + pa=-pa; + if (pa <= pb) // pc is positive and less than pb + if (pa <= pc) + diff = curr-left; + else + diff = curr-upleft; + else + // pc is negative and less than or equal to pa, + // but since pa is greater than pb this isn't an issue... + if (pb <= -pc) + diff = curr-up; + else + diff = curr-upleft; + } + } else { + if (pb<0) { + pb =-pb; // make it positive... + if (pa <= pb) { + // pc would be negative and less than or equal to pb + pc = pb-pa; + if (pa <= pc) + diff = curr-left; + else if (pb == pc) + // if pa is zero then pc==pb otherwise + // pc must be less than pb. + diff = curr-up; + else + diff = curr-upleft; + } else { + // pc would be positive and less than pa. + pc = pa-pb; + if (pb <= pc) + diff = curr-up; + else + diff = curr-upleft; + } + } else { + // both pos so pa+pb is always greater than pa/pb + if (pa <= pb) + diff = curr-left; + else + diff = curr-up; + } } - - filterBadness[4] = badness; + scratchRows[4][i] = (byte)diff; + badness [4] += (diff>=0)?diff:-diff; } - int filterType = 0; - int minBadness = filterBadness[0]; + int minBadness = badness[0]; for (int i = 1; i < 5; i++) { - if (filterBadness[i] < minBadness) { - minBadness = filterBadness[i]; + if (badness[i] < minBadness) { + minBadness = badness[i]; filterType = i; } } 1.2 +3 -3 xml-batik/sources/org/apache/batik/gvt/font/AWTFontFamily.java Index: AWTFontFamily.java =================================================================== RCS file: /home/cvs/xml-batik/sources/org/apache/batik/gvt/font/AWTFontFamily.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- AWTFontFamily.java 2001/04/29 08:22:54 1.1 +++ AWTFontFamily.java 2001/10/29 21:13:41 1.2 @@ -18,7 +18,7 @@ * A font family class for AWT fonts. * * @author <a href="mailto:[EMAIL PROTECTED]">Bella Robinson</a> - * @version $Id: AWTFontFamily.java,v 1.1 2001/04/29 08:22:54 dino Exp $ + * @version $Id: AWTFontFamily.java,v 1.2 2001/10/29 21:13:41 deweese Exp $ */ public class AWTFontFamily implements GVTFontFamily { @@ -46,8 +46,8 @@ * Derives a GVTFont object of the correct size. * * @param size The required size of the derived font. - * @param aci The character iterator that will be rendered using the derived - * font. + * @param aci The character iterator that will be rendered using + * the derived font. */ public GVTFont deriveFont(float size, AttributedCharacterIterator aci) { HashMap fontAttributes = new HashMap(aci.getAttributes()); 1.8 +3 -4 xml-batik/sources/org/apache/batik/gvt/font/AWTGVTFont.java Index: AWTGVTFont.java =================================================================== RCS file: /home/cvs/xml-batik/sources/org/apache/batik/gvt/font/AWTGVTFont.java,v retrieving revision 1.7 retrieving revision 1.8 diff -u -r1.7 -r1.8 --- AWTGVTFont.java 2001/09/17 16:28:27 1.7 +++ AWTGVTFont.java 2001/10/29 21:13:41 1.8 @@ -34,7 +34,7 @@ * This is a wrapper class for a java.awt.Font instance. * * @author <a href="mailto:[EMAIL PROTECTED]">Bella Robinson</a> - * @version $Id: AWTGVTFont.java,v 1.7 2001/09/17 16:28:27 tkormann Exp $ + * @version $Id: AWTGVTFont.java,v 1.8 2001/10/29 21:13:41 deweese Exp $ */ public class AWTGVTFont implements GVTFont { @@ -160,10 +160,9 @@ if (ci instanceof AttributedCharacterIterator) { AttributedCharacterIterator aci = (AttributedCharacterIterator)ci; - AttributedString as = new AttributedString(aci); - if (ArabicTextHandler.containsArabic(as)) { + if (ArabicTextHandler.containsArabic(aci)) { String substString = - ArabicTextHandler.createSubstituteString(aci); + ArabicTextHandler.createSubstituteString(aci); return createGlyphVector(frc, substString); } 1.19 +23 -16 xml-batik/sources/org/apache/batik/gvt/renderer/StrokingTextPainter.java Index: StrokingTextPainter.java =================================================================== RCS file: /home/cvs/xml-batik/sources/org/apache/batik/gvt/renderer/StrokingTextPainter.java,v retrieving revision 1.18 retrieving revision 1.19 diff -u -r1.18 -r1.19 --- StrokingTextPainter.java 2001/10/23 13:42:29 1.18 +++ StrokingTextPainter.java 2001/10/29 21:13:41 1.19 @@ -60,7 +60,7 @@ * @see org.apache.batik.gvt.text.GVTAttributedCharacterIterator * * @author <a href="[EMAIL PROTECTED]>Bill Haneman</a> - * @version $Id: StrokingTextPainter.java,v 1.18 2001/10/23 13:42:29 deweese Exp $ + * @version $Id: StrokingTextPainter.java,v 1.19 2001/10/29 21:13:41 deweese Exp $ */ public class StrokingTextPainter extends BasicTextPainter { @@ -362,14 +362,17 @@ private AttributedCharacterIterator createModifiedACIForFontMatching (TextNode node, AttributedCharacterIterator aci) { + // This looks like vestigial code, but perhaps it works around + // a bug... + // aci.first(); + // AttributedCharacterSpanIterator acsi = + // new AttributedCharacterSpanIterator(aci, aci.getBeginIndex(), + // aci.getEndIndex()); + // + // AttributedString as = new AttributedString(acsi); + AttributedString as = new AttributedString(aci); aci.first(); - AttributedCharacterSpanIterator acsi = - new AttributedCharacterSpanIterator(aci, aci.getBeginIndex(), - aci.getEndIndex()); - AttributedString as = new AttributedString(acsi); - aci.first(); - boolean moreChunks = true; while (moreChunks) { int start = aci.getRunStart @@ -380,8 +383,8 @@ AttributedCharacterSpanIterator runaci = new AttributedCharacterSpanIterator(aci, start, end); - Vector fontFamilies = (Vector)runaci.getAttributes().get( - GVTAttributedCharacterIterator.TextAttribute.GVT_FONT_FAMILIES); + Vector fontFamilies = (Vector)runaci.getAttributes().get + (GVTAttributedCharacterIterator.TextAttribute.GVT_FONT_FAMILIES); if (fontFamilies == null) { // no font families set, just return the same aci @@ -404,8 +407,9 @@ resolvedFontFamilies.add(fontFamily); } } + // if could not resolve at least one of the fontFamilies then use - // the default faont + // the default font if (resolvedFontFamilies.size() == 0) { resolvedFontFamilies.add(FontFamilyResolver.defaultFont); } @@ -440,7 +444,8 @@ int currentRunIndex = runaci.getBeginIndex(); while (currentRunIndex < runaci.getEndIndex()) { - int displayUpToIndex = font.canDisplayUpTo(runaci, currentRunIndex, end); + int displayUpToIndex = + font.canDisplayUpTo(runaci, currentRunIndex, end); if (displayUpToIndex == -1) { // for each char, if not already assigned a font, @@ -454,9 +459,9 @@ currentRunIndex = runaci.getEndIndex(); } else if (displayUpToIndex > currentRunIndex) { - // could display some but not all - // for each char it can display, - // if not already assigned a font, assign this font to it + // could display some but not all, so for each + // char it can display, if char not already + // assigned a font, assign this font to it for (int j = currentRunIndex; j < displayUpToIndex; j++) { if (!fontAssigned[j - start]) { as.addAttribute(GVTAttributedCharacterIterator.TextAttribute.GVT_FONT, font, j, j+1); @@ -471,11 +476,13 @@ } } } + // assign the first font to any chars haven't alreay been assigned for (int i = 0; i < runaciLength; i++) { if (!fontAssigned[i]) { - GVTFontFamily fontFamily - = FontFamilyResolver.getFamilyThatCanDisplay(runaci.setIndex(start+i)); + GVTFontFamily fontFamily + = FontFamilyResolver.getFamilyThatCanDisplay + (runaci.setIndex(start+i)); if (fontFamily != null) { GVTFont font = fontFamily.deriveFont(fontSize, runaci); as.addAttribute(GVTAttributedCharacterIterator.TextAttribute.GVT_FONT, 1.2 +16 -6 xml-batik/sources/org/apache/batik/gvt/text/ArabicTextHandler.java Index: ArabicTextHandler.java =================================================================== RCS file: /home/cvs/xml-batik/sources/org/apache/batik/gvt/text/ArabicTextHandler.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- ArabicTextHandler.java 2001/07/05 06:26:22 1.1 +++ ArabicTextHandler.java 2001/10/29 21:13:41 1.2 @@ -21,7 +21,7 @@ * text is rendered using an AWT font. * * @author <a href="mailto:[EMAIL PROTECTED]">Bella Robinson</a> - * @version $Id: ArabicTextHandler.java,v 1.1 2001/07/05 06:26:22 bella Exp $ + * @version $Id: ArabicTextHandler.java,v 1.2 2001/10/29 21:13:41 deweese Exp $ */ public class ArabicTextHandler { @@ -31,11 +31,12 @@ private final static Map charMap = new HashMap(54); /** - * If the AttributedString contains any arabic chars, assigns an arabic form - * attribute, ie. initial|medial|terminal|isolated, to each arabic char. + * If the AttributedString contains any arabic chars, assigns an + * arabic form attribute, ie. initial|medial|terminal|isolated, to + * each arabic char. * * @param as The string to attach the arabic form attributes to. - * @return An attributed string with arabic form attributes. + * @return An attributed string with arabic form attributes. */ public static AttributedString assignArabicForms(AttributedString as) { @@ -227,8 +228,17 @@ * @return True if at least one char is arabic, false otherwise. */ public static boolean containsArabic(AttributedString as) { + return containsArabic(as.getIterator()); + } + + /** + * Returns true if the ACI contains any arabic characters. + * + * @param aci The AttributedCharacterIterator to test. + * @return True if at least one char is arabic, false otherwise. + */ + public static boolean containsArabic(AttributedCharacterIterator aci) { char c; - AttributedCharacterIterator aci = as.getIterator(); for (int i = aci.getBeginIndex(); i < aci.getEndIndex(); i++) { c = aci.setIndex(i); if (arabicChar(c)) { @@ -655,4 +665,4 @@ } -} \ No newline at end of file +} 1.5 +9 -7 xml-batik/sources/org/apache/batik/gvt/text/AttributedCharacterSpanIterator.java Index: AttributedCharacterSpanIterator.java =================================================================== RCS file: /home/cvs/xml-batik/sources/org/apache/batik/gvt/text/AttributedCharacterSpanIterator.java,v retrieving revision 1.4 retrieving revision 1.5 diff -u -r1.4 -r1.5 --- AttributedCharacterSpanIterator.java 2001/05/14 16:46:44 1.4 +++ AttributedCharacterSpanIterator.java 2001/10/29 21:13:41 1.5 @@ -26,7 +26,7 @@ * AttributedString. * * @author <a href="mailto:[EMAIL PROTECTED]">Bill Haneman</a> - * @version $Id: AttributedCharacterSpanIterator.java,v 1.4 2001/05/14 16:46:44 tkormann Exp $ + * @version $Id: AttributedCharacterSpanIterator.java,v 1.5 2001/10/29 21:13:41 deweese Exp $ */ public class AttributedCharacterSpanIterator implements @@ -43,8 +43,9 @@ * @param start the first index of the subinterval * @param stop the index of the first character after the subinterval */ - public AttributedCharacterSpanIterator(AttributedCharacterIterator aci, int start, int stop) { - this.aci = aci; + public AttributedCharacterSpanIterator(AttributedCharacterIterator aci, + int start, int stop) { + this.aci = aci; end = Math.min(aci.getEndIndex(), stop); begin = Math.max(aci.getBeginIndex(), start); this.aci.setIndex(begin); @@ -64,7 +65,7 @@ * Get the value of the named attribute for the current * character. */ - public Object getAttribute(AttributedCharacterIterator.Attribute attribute) { + public Object getAttribute(Attribute attribute) { return aci.getAttribute(attribute); } @@ -122,9 +123,10 @@ } /** - * Get the index of the first character of the run with - * respect to the given attributes containing the current character. - * @param attributes the Set of attributes which begins at the returned index. + * Get the index of the first character of the run with respect to + * the given attributes containing the current character. + * @param attributes the Set of attributes which begins at the + * returned index. */ public int getRunStart(Set attributes) { return Math.max(aci.getRunStart(attributes), begin); 1.3 +7 -5 xml-batik/sources/org/apache/batik/gvt/text/BidiAttributedCharacterIterator.java Index: BidiAttributedCharacterIterator.java =================================================================== RCS file: /home/cvs/xml-batik/sources/org/apache/batik/gvt/text/BidiAttributedCharacterIterator.java,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- BidiAttributedCharacterIterator.java 2001/07/05 06:29:21 1.2 +++ BidiAttributedCharacterIterator.java 2001/10/29 21:13:41 1.3 @@ -25,7 +25,7 @@ * in a text run will all have the same bidi level. * * @author <a href="mailto:[EMAIL PROTECTED]">Bella Robinson</a> - * @version $Id: BidiAttributedCharacterIterator.java,v 1.2 2001/07/05 06:29:21 bella Exp $ + * @version $Id: BidiAttributedCharacterIterator.java,v 1.3 2001/10/29 21:13:41 deweese Exp $ */ public class BidiAttributedCharacterIterator implements AttributedCharacterIterator { @@ -44,7 +44,8 @@ * order. * @param frc The current font render context */ - public BidiAttributedCharacterIterator(AttributedCharacterIterator aci, FontRenderContext frc) { + public BidiAttributedCharacterIterator(AttributedCharacterIterator aci, + FontRenderContext frc) { this.frc = frc; aci.first(); @@ -54,8 +55,9 @@ int numChars = tl.getCharacterCount(); AttributedString as = new AttributedString(aci); for (int i = 0; i < numChars; i++) { - as.addAttribute(GVTAttributedCharacterIterator.TextAttribute.BIDI_LEVEL, - new Integer(tl.getCharacterLevel(i)), i, i+1); + as.addAttribute + (GVTAttributedCharacterIterator.TextAttribute.BIDI_LEVEL, + new Integer(tl.getCharacterLevel(i)), i, i+1); } this.aci = as.getIterator(); @@ -481,4 +483,4 @@ } -} \ No newline at end of file +}
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]