You are viewing a plain text version of this content. The canonical link for it is here.
Posted to batik-commits@xmlgraphics.apache.org by ca...@apache.org on 2006/03/08 01:04:03 UTC
svn commit: r384062 [5/6] - in /xmlgraphics/batik/branches/anim: ./ lib/
resources/META-INF/services/
resources/org/apache/batik/apps/rasterizer/resources/
resources/org/apache/batik/apps/svgbrowser/resources/
resources/org/apache/batik/dom/svg/resourc...
Modified: xmlgraphics/batik/branches/anim/sources/org/apache/batik/ext/awt/image/spi/MagicNumberRegistryEntry.java
URL: http://svn.apache.org/viewcvs/xmlgraphics/batik/branches/anim/sources/org/apache/batik/ext/awt/image/spi/MagicNumberRegistryEntry.java?rev=384062&r1=384061&r2=384062&view=diff
==============================================================================
--- xmlgraphics/batik/branches/anim/sources/org/apache/batik/ext/awt/image/spi/MagicNumberRegistryEntry.java (original)
+++ xmlgraphics/batik/branches/anim/sources/org/apache/batik/ext/awt/image/spi/MagicNumberRegistryEntry.java Tue Mar 7 16:03:46 2006
@@ -1,6 +1,6 @@
/*
- Copyright 2001,2003 The Apache Software Foundation
+ Copyright 2001,2003,2006 The Apache Software Foundation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -114,63 +114,136 @@
* Constructor, simplifies construction of entry when only
* one extension and one magic number is required.
* @param name Format Name
+ * @param priority the priority of the RegistryEntry
* @param ext Standard extension
+ * @param mimeType the supported MIME type
* @param offset Offset of magic number
* @param magicNumber byte array to match.
*/
public MagicNumberRegistryEntry(String name,
+ float priority,
String ext,
String mimeType,
int offset, byte[]magicNumber) {
- super(name, PRIORITY, ext, mimeType);
+ super(name, priority, ext, mimeType);
magicNumbers = new MagicNumber[1];
magicNumbers[0] = new MagicNumber(offset, magicNumber);
}
/**
* Constructor, simplifies construction of entry when only
+ * one extension and one magic number is required.
+ * @param name Format Name
+ * @param ext Standard extension
+ * @param mimeType the supported MIME type
+ * @param offset Offset of magic number
+ * @param magicNumber byte array to match.
+ */
+ public MagicNumberRegistryEntry(String name,
+ String ext,
+ String mimeType,
+ int offset, byte[] magicNumber) {
+ this(name, PRIORITY, ext, mimeType, offset, magicNumber);
+ }
+
+ /**
+ * Constructor, simplifies construction of entry when only
* one extension is required.
* @param name Format Name
+ * @param priority the priority of the RegistryEntry
* @param ext Standard extension
+ * @param mimeType the supported MIME type
* @param magicNumbers Array of magic numbers any of which can match.
*/
public MagicNumberRegistryEntry(String name,
+ float priority,
String ext,
String mimeType,
- MagicNumber [] magicNumbers) {
- super(name, PRIORITY, ext, mimeType);
+ MagicNumber[] magicNumbers) {
+ super(name, priority, ext, mimeType);
this.magicNumbers = magicNumbers;
}
/**
* Constructor, simplifies construction of entry when only
+ * one extension is required.
+ * @param name Format Name
+ * @param ext Standard extension
+ * @param mimeType the supported MIME type
+ * @param magicNumbers Array of magic numbers any of which can match.
+ */
+ public MagicNumberRegistryEntry(String name,
+ String ext,
+ String mimeType,
+ MagicNumber[] magicNumbers) {
+ this(name, PRIORITY, ext, mimeType, magicNumbers);
+ }
+
+ /**
+ * Constructor, simplifies construction of entry when only
* one magic number is required.
* @param name Format Name
+ * @param priority the priority of the RegistryEntry
* @param exts Standard set of extensions
+ * @param mimeTypes array of supported MIME types
* @param offset Offset of magic number
* @param magicNumber byte array to match.
*/
public MagicNumberRegistryEntry(String name,
+ float priority,
String [] exts,
String [] mimeTypes,
int offset, byte[]magicNumber) {
- super(name, PRIORITY, exts, mimeTypes);
+ super(name, priority, exts, mimeTypes);
magicNumbers = new MagicNumber[1];
magicNumbers[0] = new MagicNumber(offset, magicNumber);
}
/**
+ * Constructor, simplifies construction of entry when only
+ * one magic number is required.
+ * @param name Format Name
+ * @param exts Standard set of extensions
+ * @param mimeTypes array of supported MIME types
+ * @param offset Offset of magic number
+ * @param magicNumber byte array to match.
+ */
+ public MagicNumberRegistryEntry(String name,
+ String [] exts,
+ String [] mimeTypes,
+ int offset, byte[] magicNumbers) {
+ this(name, PRIORITY, exts, mimeTypes, offset, magicNumbers);
+ }
+
+ /**
* Constructor
* @param name Format Name
+ * @param priority the priority of the RegistryEntry
* @param exts Standard set of extensions
+ * @param mimeTypes array of supported MIME types
* @param magicNumbers array of magic numbers any of which can match.
*/
public MagicNumberRegistryEntry(String name,
+ float priority,
String [] exts,
String [] mimeTypes,
MagicNumber [] magicNumbers) {
- super(name, PRIORITY, exts, mimeTypes);
+ super(name, priority, exts, mimeTypes);
this.magicNumbers = magicNumbers;
+ }
+
+ /**
+ * Constructor
+ * @param name Format Name
+ * @param exts Standard set of extensions
+ * @param mimeTypes array of supported MIME types
+ * @param magicNumbers array of magic numbers any of which can match.
+ */
+ public MagicNumberRegistryEntry(String name,
+ String [] exts,
+ String [] mimeTypes,
+ MagicNumber [] magicNumbers) {
+ this(name, PRIORITY, exts, mimeTypes, magicNumbers);
}
/**
Modified: xmlgraphics/batik/branches/anim/sources/org/apache/batik/extension/StylableExtensionElement.java
URL: http://svn.apache.org/viewcvs/xmlgraphics/batik/branches/anim/sources/org/apache/batik/extension/StylableExtensionElement.java?rev=384062&r1=384061&r2=384062&view=diff
==============================================================================
--- xmlgraphics/batik/branches/anim/sources/org/apache/batik/extension/StylableExtensionElement.java (original)
+++ xmlgraphics/batik/branches/anim/sources/org/apache/batik/extension/StylableExtensionElement.java Tue Mar 7 16:03:46 2006
@@ -1,6 +1,6 @@
/*
- Copyright 1999-2003 The Apache Software Foundation
+ Copyright 1999-2003,2006 The Apache Software Foundation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -22,6 +22,7 @@
import java.net.URL;
import org.apache.batik.css.engine.CSSStylableElement;
+import org.apache.batik.css.engine.StyleDeclarationProvider;
import org.apache.batik.css.engine.StyleMap;
import org.apache.batik.dom.AbstractDocument;
import org.w3c.dom.Node;
@@ -132,6 +133,15 @@
return n == null;
}
return false;
+ }
+
+ /**
+ * Returns the object that gives access to the underlying
+ * {@link org.apache.batik.css.engine.StyleDeclaration} for the override
+ * style of this element.
+ */
+ public StyleDeclarationProvider getOverrideStyleDeclarationProvider() {
+ return null;
}
// SVGStylable //////////////////////////////////////////////////
Modified: xmlgraphics/batik/branches/anim/sources/org/apache/batik/extension/svg/BatikFlowTextElementBridge.java
URL: http://svn.apache.org/viewcvs/xmlgraphics/batik/branches/anim/sources/org/apache/batik/extension/svg/BatikFlowTextElementBridge.java?rev=384062&r1=384061&r2=384062&view=diff
==============================================================================
--- xmlgraphics/batik/branches/anim/sources/org/apache/batik/extension/svg/BatikFlowTextElementBridge.java (original)
+++ xmlgraphics/batik/branches/anim/sources/org/apache/batik/extension/svg/BatikFlowTextElementBridge.java Tue Mar 7 16:03:46 2006
@@ -137,6 +137,8 @@
Element element) {
List rgns = getRegions(ctx, element);
AttributedString ret = getFlowDiv(ctx, element);
+ if (ret == null) return ret;
+
ret.addAttribute(FLOW_REGIONS, rgns, 0, 1);
return ret;
}
Modified: xmlgraphics/batik/branches/anim/sources/org/apache/batik/gvt/FillShapePainter.java
URL: http://svn.apache.org/viewcvs/xmlgraphics/batik/branches/anim/sources/org/apache/batik/gvt/FillShapePainter.java?rev=384062&r1=384061&r2=384062&view=diff
==============================================================================
--- xmlgraphics/batik/branches/anim/sources/org/apache/batik/gvt/FillShapePainter.java (original)
+++ xmlgraphics/batik/branches/anim/sources/org/apache/batik/gvt/FillShapePainter.java Tue Mar 7 16:03:46 2006
@@ -65,6 +65,13 @@
}
/**
+ * Gets the paint used to draw the outline of the shape.
+ */
+ public Paint getPaint() {
+ return paint;
+ }
+
+ /**
* Paints the specified shape using the specified Graphics2D.
*
* @param g2d the Graphics2D to use
Modified: xmlgraphics/batik/branches/anim/sources/org/apache/batik/gvt/StrokeShapePainter.java
URL: http://svn.apache.org/viewcvs/xmlgraphics/batik/branches/anim/sources/org/apache/batik/gvt/StrokeShapePainter.java?rev=384062&r1=384061&r2=384062&view=diff
==============================================================================
--- xmlgraphics/batik/branches/anim/sources/org/apache/batik/gvt/StrokeShapePainter.java (original)
+++ xmlgraphics/batik/branches/anim/sources/org/apache/batik/gvt/StrokeShapePainter.java Tue Mar 7 16:03:46 2006
@@ -77,12 +77,26 @@
}
/**
+ * Gets the stroke used to draw the outline of the shape.
+ */
+ public Stroke getStroke() {
+ return stroke;
+ }
+
+ /**
* Sets the paint used to fill a shape.
*
* @param newPaint the paint object used to draw the shape
*/
public void setPaint(Paint newPaint) {
this.paint = newPaint;
+ }
+
+ /**
+ * Gets the paint used to draw the outline of the shape.
+ */
+ public Paint getPaint() {
+ return paint;
}
/**
Modified: xmlgraphics/batik/branches/anim/sources/org/apache/batik/gvt/flow/FlowGlyphLayout.java
URL: http://svn.apache.org/viewcvs/xmlgraphics/batik/branches/anim/sources/org/apache/batik/gvt/flow/FlowGlyphLayout.java?rev=384062&r1=384061&r2=384062&view=diff
==============================================================================
--- xmlgraphics/batik/branches/anim/sources/org/apache/batik/gvt/flow/FlowGlyphLayout.java (original)
+++ xmlgraphics/batik/branches/anim/sources/org/apache/batik/gvt/flow/FlowGlyphLayout.java Tue Mar 7 16:03:46 2006
@@ -43,8 +43,10 @@
*/
public class FlowGlyphLayout extends GlyphLayout {
- public static final AttributedCharacterIterator.Attribute WORD_LIMIT
- = TextLineBreaks.WORD_LIMIT;
+ public static final char SOFT_HYPHEN = 0x00AD;
+ public static final char ZERO_WIDTH_SPACE = 0x200B;
+ public static final char ZERO_WIDTH_JOINER = 0x200D;
+ public static final char SPACE = ' ';
public FlowGlyphLayout(AttributedCharacterIterator aci,
@@ -55,396 +57,4 @@
}
- public static boolean textWrapTextChunk
- (AttributedCharacterIterator [] acis,
- List chunkLayouts,
- List flowRects,
- FontRenderContext frc) {
-
- int numChunks = acis.length;
- // System.out.println("Len: " + acis.length + " Size: " +
- // chunkLayouts.size());
-
- // Make a list of the GlyphVectors so we can construct a
- // multiGlyphVector that makes them all look like one big
- // glyphVector
- GVTGlyphVector [] gvs = new GVTGlyphVector[acis.length];
- WordInfo [][] wordInfos = new WordInfo[acis.length][];
- Iterator clIter = chunkLayouts.iterator();
-
- float prevBotMargin = 0;
- int numWords = 0;
- BlockInfo [] blockInfos = new BlockInfo[acis.length];
- float [] topSkip = new float[acis.length];
- for (int chunk=0; clIter.hasNext(); chunk++) {
- // System.err.print("Chunk: " + chunk + " Str: '");
- AttributedCharacterIterator aci = acis[chunk];
- List gvl = new LinkedList();
- List layouts = (List)clIter.next();
- Iterator iter = layouts.iterator();
- while (iter.hasNext()) {
- GlyphLayout gl = (GlyphLayout)iter.next();
- gvl.add(gl.getGlyphVector());
- }
- GVTGlyphVector gv = new MultiGlyphVector(gvl);
- gvs[chunk] = gv;
- wordInfos[chunk] = doWordAnalysis(gv, aci, numWords, frc);
- aci.first();
- BlockInfo bi = (BlockInfo)aci.getAttribute(FLOW_PARAGRAPH);
- bi.initLineInfo(frc);
- blockInfos[chunk] = bi;
- if (prevBotMargin > bi.getTopMargin())
- topSkip[chunk] = prevBotMargin;
- else
- topSkip[chunk] = bi.getTopMargin();
- prevBotMargin = bi.getBottomMargin();
- numWords += wordInfos[chunk].length;
- }
-
- Iterator frIter = flowRects.iterator();
- RegionInfo currentRegion = null;
- int currWord = 0;
- int chunk = 0;
- List lineInfos = new LinkedList();
- while(frIter.hasNext()) {
- currentRegion = (RegionInfo) frIter.next();
- FlowRegions fr = new FlowRegions(currentRegion.getShape());
-
- while (chunk < wordInfos.length) {
- WordInfo [] chunkInfo = wordInfos[chunk];
- BlockInfo bi = blockInfos[chunk];
- WordInfo wi = chunkInfo[currWord];
- Object flowLine = wi.getFlowLine();
- double lh = Math.max(wi.getLineHeight(),bi.getLineHeight());
- LineInfo li = new LineInfo(fr, bi, true);
- double newY = li.getCurrentY()+topSkip[chunk];
- topSkip[chunk] = 0;
- if (li.gotoY(newY)) break;
-
- while (!li.addWord(wi)) {
- // step down 1/10 of a line height and try again.
- newY = li.getCurrentY()+lh*.1;
- if (li.gotoY(newY)) break;
- }
- if (fr.done()) break;
-
- currWord++;
- for (;currWord < chunkInfo.length;currWord++) {
- wi = chunkInfo[currWord];
- if ((wi.getFlowLine() == flowLine) && (li.addWord(wi)))
- continue;
-
- // Word didn't fit or we hit end of flowLine elem,
- // go to a new line.
- li.layout();
- lineInfos.add(li);
- li = null;
-
- flowLine = wi.getFlowLine();
- lh = Math.max(wi.getLineHeight(),bi.getLineHeight());
- if (!fr.newLine(lh)) break; // region is done
-
- li = new LineInfo(fr, bi, false);
- while (!li.addWord(wi)) {
- newY =li.getCurrentY()+lh*.1;
- if (li.gotoY(newY)) break;
- }
- if (fr.done()) break;
- }
- if (li != null) {
- li.setParaEnd(true);
- li.layout();
- }
-
- if (fr.done()) break;
-
- chunk++;
- currWord = 0;
-
- if (bi.isFlowRegionBreak())
- break;
-
- if (!fr.newLine(lh)) // Region is done.
- break;
- }
- if (chunk == wordInfos.length)
- break;
- }
-
- boolean overflow = (chunk < wordInfos.length);
-
- while (chunk < wordInfos.length) {
- WordInfo [] chunkInfo = wordInfos[chunk];
- while (currWord < chunkInfo.length) {
- WordInfo wi = chunkInfo[currWord];
- int numGG = wi.getNumGlyphGroups();
- for (int gg=0; gg<numGG; gg++) {
- GlyphGroupInfo ggi = wi.getGlyphGroup(gg);
- GVTGlyphVector gv = ggi.getGlyphVector();
- int end = ggi.getEnd();
- for (int g=ggi.getStart(); g <= end; g++) {
- gv.setGlyphVisible(g, false);
- }
- }
- currWord++;
- }
- chunk++;
- currWord = 0;
- }
-
- return overflow;
- }
-
- static int [] allocWordMap(int [] wordMap, int sz) {
- if (wordMap != null) {
- if (sz <= wordMap.length)
- return wordMap;
- if (sz < wordMap.length*2)
- sz = wordMap.length*2;
- }
-
- int [] ret = new int[sz];
- int ext=0;
- if (wordMap != null)
- ext = wordMap.length;
- if (sz < ext) ext = sz;
- int i=0;
- for (; i<ext; i++) {
- ret[i] = wordMap[i];
- }
- for (; i<sz; i++) {
- ret[i] = -1;
- }
- return ret;
- }
-
- /**
- * This returns an array of glyphs numbers for each glyph
- * group in each word: ret[word][glyphGroup][glyphNum].
- */
- static WordInfo[] doWordAnalysis(GVTGlyphVector gv,
- AttributedCharacterIterator aci,
- int numWords,
- FontRenderContext frc) {
- int numGlyphs = gv.getNumGlyphs();
- int [] glyphWords = new int[numGlyphs];
- int [] wordMap = allocWordMap(null, 10);
- int maxWord = 0;
- int aciIdx = aci.getBeginIndex();
- // First we go through the glyphs seeing if any two ajacent
- // words need to be collapsed because of a ligature. This
- // would be an odd case. If it happens we consider the
- // two words to be one.
- for (int i=0; i<numGlyphs; i++) {
- int cnt = gv.getCharacterCount(i,i);
- aci.setIndex(aciIdx);
- Integer integer = (Integer)aci.getAttribute(WORD_LIMIT);
- int minWord = integer.intValue()-numWords;
- if (minWord > maxWord) {
- maxWord = minWord;
- wordMap = allocWordMap(wordMap, maxWord+1);
- }
- aciIdx++;
- for (int c=1; c<cnt; c++) {
- aci.setIndex(aciIdx);
- integer = (Integer)aci.getAttribute(WORD_LIMIT);
- int cWord = integer.intValue()-numWords;
- if (cWord > maxWord) {
- maxWord = cWord;
- wordMap = allocWordMap(wordMap, maxWord+1);
- }
- // We always want to use the min word as the main
- // index for the new composite word.
- if (cWord < minWord) {
- wordMap[minWord] = cWord;
- minWord = cWord;
- } else if (cWord > minWord) {
- wordMap[cWord] = minWord;
- }
- aciIdx++;
- }
- glyphWords[i] = minWord;
- }
- int words=0;
- WordInfo [] cWordMap = new WordInfo[maxWord+1];
- for (int i=0; i<=maxWord; i++) {
- int nw = wordMap[i];
- if (nw == -1) {
- // new word so give it a number.
- cWordMap[i] = new WordInfo(words++);
- } else {
- int word = nw;
- nw = wordMap[i];
- while (nw != -1) {
- word = nw;
- nw = wordMap[word];
- }
- wordMap[i] = word; // help the next guy out
- cWordMap[i] = cWordMap[word];
- }
- }
- wordMap = null;
- WordInfo [] wordInfos = new WordInfo[words];
- for (int i=0; i<=maxWord; i++) {
- WordInfo wi = cWordMap[i];
- wordInfos[wi.getIndex()] = cWordMap[i];
- }
-
- aciIdx = aci.getBeginIndex();
- int aciEnd = aci.getEndIndex();
- char ch = aci.setIndex(aciIdx);
-
- int aciWordStart = aciIdx;
- GVTFont gvtFont = (GVTFont)aci.getAttribute(GVT_FONT);
- float lineHeight = 1.f;
- Float lineHeightFloat = (Float)aci.getAttribute(LINE_HEIGHT);
- if (lineHeightFloat != null)
- lineHeight = lineHeightFloat.floatValue();
- int runLimit = aci.getRunLimit(szAtts);
- WordInfo prevWI = null;
- float [] lastAdvAdj = new float [numGlyphs];
- float [] advAdj = new float [numGlyphs];
- boolean [] hideLast = new boolean[numGlyphs];
- boolean [] hide = new boolean[numGlyphs];
- boolean [] space = new boolean[numGlyphs];
- float [] glyphPos = gv.getGlyphPositions(0, numGlyphs+1, null);
- for (int i=0; i<numGlyphs; i++) {
- char pch = ch;
- ch = aci.setIndex(aciIdx);
- Integer integer = (Integer)aci.getAttribute(WORD_LIMIT);
- WordInfo theWI = cWordMap[integer.intValue()-numWords];
- if (theWI.getFlowLine() == null)
- theWI.setFlowLine(aci.getAttribute(FLOW_LINE_BREAK));
-
- if (prevWI == null) {
- prevWI = theWI;
- } else if (prevWI != theWI) {
- GVTLineMetrics lm = gvtFont.getLineMetrics
- (aci, aciWordStart, aciIdx, frc);
- prevWI.addLineMetrics(gvtFont, lm);
- prevWI.addLineHeight(lineHeight);
- aciWordStart = aciIdx;
- prevWI = theWI;
- }
-
- int chCnt = gv.getCharacterCount(i,i);
- if (chCnt == 1) {
- char nch;
- float kern;
- switch(ch) {
- case SOFT_HYPHEN:
- hideLast[i] = true;
- nch = aci.next(); aci.previous();
- kern = gvtFont.getHKern(pch, nch);
- advAdj[i] = -(glyphPos[2*i+2]-glyphPos[2*i]+kern);
- break;
- case ZERO_WIDTH_JOINER:
- hide[i] = true;
- break;
- case ZERO_WIDTH_SPACE:
- hide[i] = true;
- break;
- case SPACE:
- space[i] = true;
- nch = aci.next(); aci.previous();
- kern = gvtFont.getHKern(pch, nch);
- lastAdvAdj[i] = -(glyphPos[2*i+2]-glyphPos[2*i]+kern);
- default:
- }
- }
-
- aciIdx += chCnt;
- if ((aciIdx > runLimit) && (aciIdx < aciEnd)) {
- // Possible font size/style change so record current
- // line metrics and start fresh.
- GVTLineMetrics lm = gvtFont.getLineMetrics
- (aci,aciWordStart, runLimit, frc);
- prevWI.addLineMetrics(gvtFont, lm);
- prevWI.addLineHeight(lineHeight);
- prevWI = null;
- aciWordStart = aciIdx;
- aci.setIndex(aciIdx);
- gvtFont = (GVTFont)aci.getAttribute(GVT_FONT);
- Float f = (Float)aci.getAttribute(LINE_HEIGHT);
- lineHeight = f.floatValue();
- runLimit = aci.getRunLimit(szAtts);
- }
- }
- GVTLineMetrics lm = gvtFont.getLineMetrics
- (aci,aciWordStart, runLimit, frc);
- prevWI.addLineMetrics(gvtFont, lm);
- prevWI.addLineHeight(lineHeight);
-
- int [] wordGlyphCounts = new int[words];
- // Build a mapping from words to glyphs.
- for (int i=0; i<numGlyphs; i++) {
- int word = glyphWords[i];
- int cWord = cWordMap[word].getIndex();
- glyphWords[i] = cWord;
- wordGlyphCounts[cWord]++;
- }
-
- cWordMap = null;
- int [][]wordGlyphs = new int [words][];
- int []wordGlyphGroupsCounts = new int [words];
- for (int i=0; i<numGlyphs; i++) {
- int cWord = glyphWords[i];
- // System.err.println("CW: " + cWord);
- int [] wgs = wordGlyphs[cWord];
- if (wgs == null) {
- wgs = wordGlyphs[cWord]
- = new int[wordGlyphCounts[cWord]];
- // We use this to track where the next
- // glyph should go in wordGlyphs
- // by the time we are done it should be correct again.
- wordGlyphCounts[cWord] =0;
- }
- int cnt = wordGlyphCounts[cWord];
- wgs[cnt] = i;
- // Track the number of glyph groups in this word.
- if (cnt==0) {
- wordGlyphGroupsCounts[cWord]++;
- } else {
- if (wgs[cnt-1] != i-1)
- wordGlyphGroupsCounts[cWord]++;
- }
- wordGlyphCounts[cWord]++;
- }
-
- for (int i=0; i<words; i++) {
- int cnt = wordGlyphGroupsCounts[i];
- // System.err.println("WGGC: " + cnt);
- GlyphGroupInfo []wordGlyphGroups = new GlyphGroupInfo[cnt];
- if (cnt == 1) {
- int [] glyphs = wordGlyphs[i];
- int start = glyphs[0];
- int end = glyphs[glyphs.length-1];
- wordGlyphGroups[0] = new GlyphGroupInfo
- (gv, start, end, hide, hideLast[end],
- glyphPos, advAdj, lastAdvAdj, space);
- } else {
- int glyphGroup = 0;
- int []glyphs = wordGlyphs[i];
- int prev = glyphs[0];
- int start = prev;
- for (int j=1; j<glyphs.length; j++) {
- if (prev+1 != glyphs[j]) {
- int end = glyphs[j-1];
- wordGlyphGroups[glyphGroup] = new GlyphGroupInfo
- (gv, start, end, hide, hideLast[end],
- glyphPos, advAdj, lastAdvAdj, space);
- start = glyphs[j];
- glyphGroup++;
- }
- prev = glyphs[j];
- }
- int end = glyphs[glyphs.length-1];
- wordGlyphGroups[glyphGroup] = new GlyphGroupInfo
- (gv, start, end, hide, hideLast[end],
- glyphPos, advAdj, lastAdvAdj, space);
- }
- wordInfos[i].setGlyphGroups(wordGlyphGroups);
- }
- return wordInfos;
- }
}
Modified: xmlgraphics/batik/branches/anim/sources/org/apache/batik/gvt/flow/FlowRegions.java
URL: http://svn.apache.org/viewcvs/xmlgraphics/batik/branches/anim/sources/org/apache/batik/gvt/flow/FlowRegions.java?rev=384062&r1=384061&r2=384062&view=diff
==============================================================================
--- xmlgraphics/batik/branches/anim/sources/org/apache/batik/gvt/flow/FlowRegions.java (original)
+++ xmlgraphics/batik/branches/anim/sources/org/apache/batik/gvt/flow/FlowRegions.java Tue Mar 7 16:03:46 2006
@@ -81,6 +81,7 @@
}
public int getNumRangeOnLine() {
+ if (validRanges == null) return 0;
return validRanges.size();
}
public void resetRange() {
Modified: xmlgraphics/batik/branches/anim/sources/org/apache/batik/gvt/flow/FlowTextNode.java
URL: http://svn.apache.org/viewcvs/xmlgraphics/batik/branches/anim/sources/org/apache/batik/gvt/flow/FlowTextNode.java?rev=384062&r1=384061&r2=384062&view=diff
==============================================================================
--- xmlgraphics/batik/branches/anim/sources/org/apache/batik/gvt/flow/FlowTextNode.java (original)
+++ xmlgraphics/batik/branches/anim/sources/org/apache/batik/gvt/flow/FlowTextNode.java Tue Mar 7 16:03:46 2006
@@ -23,6 +23,24 @@
import org.apache.batik.gvt.TextNode;
import org.apache.batik.gvt.TextPainter;
+import java.text.AttributedCharacterIterator;
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import java.awt.geom.Point2D;
+import java.awt.font.FontRenderContext;
+import java.awt.font.TextAttribute;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.Set;
+
+import org.apache.batik.gvt.font.GVTFont;
+import org.apache.batik.gvt.font.GVTGlyphVector;
+import org.apache.batik.gvt.font.GVTLineMetrics;
+import org.apache.batik.gvt.font.MultiGlyphVector;
+import org.apache.batik.gvt.text.GlyphLayout;
+import org.apache.batik.gvt.text.GVTAttributedCharacterIterator;
+import org.apache.batik.gvt.renderer.StrokingTextPainter.TextRun;
/**
* One line Class Desc
@@ -44,5 +62,4 @@
else
this.textPainter = textPainter;
}
-
};
Modified: xmlgraphics/batik/branches/anim/sources/org/apache/batik/gvt/flow/FlowTextPainter.java
URL: http://svn.apache.org/viewcvs/xmlgraphics/batik/branches/anim/sources/org/apache/batik/gvt/flow/FlowTextPainter.java?rev=384062&r1=384061&r2=384062&view=diff
==============================================================================
--- xmlgraphics/batik/branches/anim/sources/org/apache/batik/gvt/flow/FlowTextPainter.java (original)
+++ xmlgraphics/batik/branches/anim/sources/org/apache/batik/gvt/flow/FlowTextPainter.java Tue Mar 7 16:03:46 2006
@@ -27,6 +27,20 @@
import org.apache.batik.gvt.TextPainter;
import org.apache.batik.gvt.renderer.StrokingTextPainter;
+import java.awt.geom.Point2D;
+import java.awt.font.FontRenderContext;
+import java.awt.font.TextAttribute;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.Set;
+
+import org.apache.batik.gvt.font.GVTFont;
+import org.apache.batik.gvt.font.GVTGlyphVector;
+import org.apache.batik.gvt.font.GVTLineMetrics;
+import org.apache.batik.gvt.font.MultiGlyphVector;
+import org.apache.batik.gvt.text.GlyphLayout;
+import org.apache.batik.gvt.text.GVTAttributedCharacterIterator;
+
/**
* One line Class Desc
*
@@ -76,11 +90,431 @@
layouts.add(tr.getLayout());
}
- FlowGlyphLayout.textWrapTextChunk
- (chunkACIs, chunkLayouts, rgns, fontRenderContext);
+ textWrap(chunkACIs, chunkLayouts, rgns, fontRenderContext);
}
+
node.setTextRuns(textRuns);
- return textRuns;
+ return node.getTextRuns();
+ }
+
+ public static final char SOFT_HYPHEN = 0x00AD;
+ public static final char ZERO_WIDTH_SPACE = 0x200B;
+ public static final char ZERO_WIDTH_JOINER = 0x200D;
+ public static final char SPACE = ' ';
+
+ public static final AttributedCharacterIterator.Attribute WORD_LIMIT =
+ TextLineBreaks.WORD_LIMIT;
+
+ public static final AttributedCharacterIterator.Attribute FLOW_REGIONS =
+ GVTAttributedCharacterIterator.TextAttribute.FLOW_REGIONS;
+
+ public static final AttributedCharacterIterator.Attribute FLOW_LINE_BREAK
+ = GVTAttributedCharacterIterator.TextAttribute.FLOW_LINE_BREAK;
+ public static final AttributedCharacterIterator.Attribute LINE_HEIGHT
+ = GVTAttributedCharacterIterator.TextAttribute.LINE_HEIGHT;
+
+ public static final AttributedCharacterIterator.Attribute GVT_FONT
+ = GVTAttributedCharacterIterator.TextAttribute.GVT_FONT;
+
+ static protected Set szAtts = new HashSet();
+
+ static {
+ szAtts.add(TextAttribute.SIZE);
+ szAtts.add(GVT_FONT);
+ szAtts.add(LINE_HEIGHT);
+ }
+
+ public static boolean textWrap(AttributedCharacterIterator [] acis,
+ List chunkLayouts,
+ List flowRects,
+ FontRenderContext frc) {
+
+ int numChunks = acis.length;
+ // System.out.println("Len: " + acis.length + " Size: " +
+ // chunkLayouts.size());
+
+ // Make a list of the GlyphVectors so we can construct a
+ // multiGlyphVector that makes them all look like one big
+ // glyphVector
+ GVTGlyphVector [] gvs = new GVTGlyphVector[acis.length];
+ WordInfo [][] wordInfos = new WordInfo[acis.length][];
+ Iterator clIter = chunkLayouts.iterator();
+
+ float prevBotMargin = 0;
+ int numWords = 0;
+ BlockInfo [] blockInfos = new BlockInfo[acis.length];
+ float [] topSkip = new float[acis.length];
+ for (int chunk=0; clIter.hasNext(); chunk++) {
+ // System.err.print("Chunk: " + chunk + " Str: '");
+ AttributedCharacterIterator aci = acis[chunk];
+ List gvl = new LinkedList();
+ List layouts = (List)clIter.next();
+ Iterator iter = layouts.iterator();
+ while (iter.hasNext()) {
+ GlyphLayout gl = (GlyphLayout)iter.next();
+ gvl.add(gl.getGlyphVector());
+ }
+ GVTGlyphVector gv = new MultiGlyphVector(gvl);
+ gvs[chunk] = gv;
+ wordInfos[chunk] = doWordAnalysis(gv, aci, numWords, frc);
+ aci.first();
+ BlockInfo bi = (BlockInfo)aci.getAttribute(FLOW_PARAGRAPH);
+ bi.initLineInfo(frc);
+ blockInfos[chunk] = bi;
+ if (prevBotMargin > bi.getTopMargin())
+ topSkip[chunk] = prevBotMargin;
+ else
+ topSkip[chunk] = bi.getTopMargin();
+ prevBotMargin = bi.getBottomMargin();
+ numWords += wordInfos[chunk].length;
+ }
+
+ Iterator frIter = flowRects.iterator();
+ RegionInfo currentRegion = null;
+ int currWord = 0;
+ int chunk = 0;
+ List lineInfos = new LinkedList();
+ while(frIter.hasNext()) {
+ currentRegion = (RegionInfo) frIter.next();
+ FlowRegions fr = new FlowRegions(currentRegion.getShape());
+
+ while (chunk < wordInfos.length) {
+ WordInfo [] chunkInfo = wordInfos[chunk];
+ BlockInfo bi = blockInfos[chunk];
+ WordInfo wi = chunkInfo[currWord];
+ Object flowLine = wi.getFlowLine();
+ double lh = Math.max(wi.getLineHeight(),bi.getLineHeight());
+ LineInfo li = new LineInfo(fr, bi, true);
+ double newY = li.getCurrentY()+topSkip[chunk];
+ topSkip[chunk] = 0;
+ if (li.gotoY(newY)) break;
+
+ while (!li.addWord(wi)) {
+ // step down 1/10 of a line height and try again.
+ newY = li.getCurrentY()+lh*.1;
+ if (li.gotoY(newY)) break;
+ }
+ if (fr.done()) break;
+
+ currWord++;
+ for (;currWord < chunkInfo.length;currWord++) {
+ wi = chunkInfo[currWord];
+ if ((wi.getFlowLine() == flowLine) && (li.addWord(wi)))
+ continue;
+
+ // Word didn't fit or we hit end of flowLine elem,
+ // go to a new line.
+ li.layout();
+ lineInfos.add(li);
+ li = null;
+
+ flowLine = wi.getFlowLine();
+ lh = Math.max(wi.getLineHeight(),bi.getLineHeight());
+ if (!fr.newLine(lh)) break; // region is done
+
+ li = new LineInfo(fr, bi, false);
+ while (!li.addWord(wi)) {
+ newY =li.getCurrentY()+lh*.1;
+ if (li.gotoY(newY)) break;
+ }
+ if (fr.done()) break;
+ }
+ if (li != null) {
+ li.setParaEnd(true);
+ li.layout();
+ }
+
+ if (fr.done()) break;
+
+ chunk++;
+ currWord = 0;
+
+ if (bi.isFlowRegionBreak())
+ break;
+
+ if (!fr.newLine(lh)) // Region is done.
+ break;
+ }
+ if (chunk == wordInfos.length)
+ break;
+ }
+
+ boolean overflow = (chunk < wordInfos.length);
+
+ while (chunk < wordInfos.length) {
+ WordInfo [] chunkInfo = wordInfos[chunk];
+ while (currWord < chunkInfo.length) {
+ WordInfo wi = chunkInfo[currWord];
+ int numGG = wi.getNumGlyphGroups();
+ for (int gg=0; gg<numGG; gg++) {
+ GlyphGroupInfo ggi = wi.getGlyphGroup(gg);
+ GVTGlyphVector gv = ggi.getGlyphVector();
+ int end = ggi.getEnd();
+ for (int g=ggi.getStart(); g <= end; g++) {
+ gv.setGlyphVisible(g, false);
+ }
+ }
+ currWord++;
+ }
+ chunk++;
+ currWord = 0;
+ }
+
+ return overflow;
+ }
+
+ static int [] allocWordMap(int [] wordMap, int sz) {
+ if (wordMap != null) {
+ if (sz <= wordMap.length)
+ return wordMap;
+ if (sz < wordMap.length*2)
+ sz = wordMap.length*2;
+ }
+
+ int [] ret = new int[sz];
+ int ext=0;
+ if (wordMap != null)
+ ext = wordMap.length;
+ if (sz < ext) ext = sz;
+ int i=0;
+ for (; i<ext; i++) {
+ ret[i] = wordMap[i];
+ }
+ for (; i<sz; i++) {
+ ret[i] = -1;
+ }
+ return ret;
+ }
+
+ /**
+ * This returns an array of glyphs numbers for each glyph
+ * group in each word: ret[word][glyphGroup][glyphNum].
+ */
+ static WordInfo[] doWordAnalysis(GVTGlyphVector gv,
+ AttributedCharacterIterator aci,
+ int numWords,
+ FontRenderContext frc) {
+ int numGlyphs = gv.getNumGlyphs();
+ int [] glyphWords = new int[numGlyphs];
+ int [] wordMap = allocWordMap(null, 10);
+ int maxWord = 0;
+ int aciIdx = aci.getBeginIndex();
+ // First we go through the glyphs seeing if any two ajacent
+ // words need to be collapsed because of a ligature. This
+ // would be an odd case. If it happens we consider the
+ // two words to be one.
+ for (int i=0; i<numGlyphs; i++) {
+ int cnt = gv.getCharacterCount(i,i);
+ aci.setIndex(aciIdx);
+ Integer integer = (Integer)aci.getAttribute(WORD_LIMIT);
+ int minWord = integer.intValue()-numWords;
+ if (minWord > maxWord) {
+ maxWord = minWord;
+ wordMap = allocWordMap(wordMap, maxWord+1);
+ }
+ aciIdx++;
+ for (int c=1; c<cnt; c++) {
+ aci.setIndex(aciIdx);
+ integer = (Integer)aci.getAttribute(WORD_LIMIT);
+ int cWord = integer.intValue()-numWords;
+ if (cWord > maxWord) {
+ maxWord = cWord;
+ wordMap = allocWordMap(wordMap, maxWord+1);
+ }
+ // We always want to use the min word as the main
+ // index for the new composite word.
+ if (cWord < minWord) {
+ wordMap[minWord] = cWord;
+ minWord = cWord;
+ } else if (cWord > minWord) {
+ wordMap[cWord] = minWord;
+ }
+ aciIdx++;
+ }
+ glyphWords[i] = minWord;
+ }
+ int words=0;
+ WordInfo [] cWordMap = new WordInfo[maxWord+1];
+ for (int i=0; i<=maxWord; i++) {
+ int nw = wordMap[i];
+ if (nw == -1) {
+ // new word so give it a number.
+ cWordMap[i] = new WordInfo(words++);
+ } else {
+ int word = nw;
+ nw = wordMap[i];
+ while (nw != -1) {
+ word = nw;
+ nw = wordMap[word];
+ }
+ wordMap[i] = word; // help the next guy out
+ cWordMap[i] = cWordMap[word];
+ }
+ }
+ wordMap = null;
+ WordInfo [] wordInfos = new WordInfo[words];
+ for (int i=0; i<=maxWord; i++) {
+ WordInfo wi = cWordMap[i];
+ wordInfos[wi.getIndex()] = cWordMap[i];
+ }
+
+ aciIdx = aci.getBeginIndex();
+ int aciEnd = aci.getEndIndex();
+ char ch = aci.setIndex(aciIdx);
+
+ int aciWordStart = aciIdx;
+ GVTFont gvtFont = (GVTFont)aci.getAttribute(GVT_FONT);
+ float lineHeight = 1.f;
+ Float lineHeightFloat = (Float)aci.getAttribute(LINE_HEIGHT);
+ if (lineHeightFloat != null)
+ lineHeight = lineHeightFloat.floatValue();
+ int runLimit = aci.getRunLimit(szAtts);
+ WordInfo prevWI = null;
+ float [] lastAdvAdj = new float [numGlyphs];
+ float [] advAdj = new float [numGlyphs];
+ boolean [] hideLast = new boolean[numGlyphs];
+ boolean [] hide = new boolean[numGlyphs];
+ boolean [] space = new boolean[numGlyphs];
+ float [] glyphPos = gv.getGlyphPositions(0, numGlyphs+1, null);
+ for (int i=0; i<numGlyphs; i++) {
+ char pch = ch;
+ ch = aci.setIndex(aciIdx);
+ Integer integer = (Integer)aci.getAttribute(WORD_LIMIT);
+ WordInfo theWI = cWordMap[integer.intValue()-numWords];
+ if (theWI.getFlowLine() == null)
+ theWI.setFlowLine(aci.getAttribute(FLOW_LINE_BREAK));
+
+ if (prevWI == null) {
+ prevWI = theWI;
+ } else if (prevWI != theWI) {
+ GVTLineMetrics lm = gvtFont.getLineMetrics
+ (aci, aciWordStart, aciIdx, frc);
+ prevWI.addLineMetrics(gvtFont, lm);
+ prevWI.addLineHeight(lineHeight);
+ aciWordStart = aciIdx;
+ prevWI = theWI;
+ }
+
+ int chCnt = gv.getCharacterCount(i,i);
+ if (chCnt == 1) {
+ char nch;
+ float kern;
+ switch(ch) {
+ case SOFT_HYPHEN:
+ hideLast[i] = true;
+ nch = aci.next(); aci.previous();
+ kern = gvtFont.getHKern(pch, nch);
+ advAdj[i] = -(glyphPos[2*i+2]-glyphPos[2*i]+kern);
+ break;
+ case ZERO_WIDTH_JOINER:
+ hide[i] = true;
+ break;
+ case ZERO_WIDTH_SPACE:
+ hide[i] = true;
+ break;
+ case SPACE:
+ space[i] = true;
+ nch = aci.next(); aci.previous();
+ kern = gvtFont.getHKern(pch, nch);
+ lastAdvAdj[i] = -(glyphPos[2*i+2]-glyphPos[2*i]+kern);
+ default:
+ }
+ }
+
+ aciIdx += chCnt;
+ if ((aciIdx > runLimit) && (aciIdx < aciEnd)) {
+ // Possible font size/style change so record current
+ // line metrics and start fresh.
+ GVTLineMetrics lm = gvtFont.getLineMetrics
+ (aci,aciWordStart, runLimit, frc);
+ prevWI.addLineMetrics(gvtFont, lm);
+ prevWI.addLineHeight(lineHeight);
+ prevWI = null;
+ aciWordStart = aciIdx;
+ aci.setIndex(aciIdx);
+ gvtFont = (GVTFont)aci.getAttribute(GVT_FONT);
+ Float f = (Float)aci.getAttribute(LINE_HEIGHT);
+ lineHeight = f.floatValue();
+ runLimit = aci.getRunLimit(szAtts);
+ }
+ }
+ GVTLineMetrics lm = gvtFont.getLineMetrics
+ (aci,aciWordStart, runLimit, frc);
+ prevWI.addLineMetrics(gvtFont, lm);
+ prevWI.addLineHeight(lineHeight);
+
+ int [] wordGlyphCounts = new int[words];
+ // Build a mapping from words to glyphs.
+ for (int i=0; i<numGlyphs; i++) {
+ int word = glyphWords[i];
+ int cWord = cWordMap[word].getIndex();
+ glyphWords[i] = cWord;
+ wordGlyphCounts[cWord]++;
+ }
+
+ cWordMap = null;
+ int [][]wordGlyphs = new int [words][];
+ int []wordGlyphGroupsCounts = new int [words];
+ for (int i=0; i<numGlyphs; i++) {
+ int cWord = glyphWords[i];
+ // System.err.println("CW: " + cWord);
+ int [] wgs = wordGlyphs[cWord];
+ if (wgs == null) {
+ wgs = wordGlyphs[cWord]
+ = new int[wordGlyphCounts[cWord]];
+ // We use this to track where the next
+ // glyph should go in wordGlyphs
+ // by the time we are done it should be correct again.
+ wordGlyphCounts[cWord] =0;
+ }
+ int cnt = wordGlyphCounts[cWord];
+ wgs[cnt] = i;
+ // Track the number of glyph groups in this word.
+ if (cnt==0) {
+ wordGlyphGroupsCounts[cWord]++;
+ } else {
+ if (wgs[cnt-1] != i-1)
+ wordGlyphGroupsCounts[cWord]++;
+ }
+ wordGlyphCounts[cWord]++;
+ }
+
+ for (int i=0; i<words; i++) {
+ int cnt = wordGlyphGroupsCounts[i];
+ // System.err.println("WGGC: " + cnt);
+ GlyphGroupInfo []wordGlyphGroups = new GlyphGroupInfo[cnt];
+ if (cnt == 1) {
+ int [] glyphs = wordGlyphs[i];
+ int start = glyphs[0];
+ int end = glyphs[glyphs.length-1];
+ wordGlyphGroups[0] = new GlyphGroupInfo
+ (gv, start, end, hide, hideLast[end],
+ glyphPos, advAdj, lastAdvAdj, space);
+ } else {
+ int glyphGroup = 0;
+ int []glyphs = wordGlyphs[i];
+ int prev = glyphs[0];
+ int start = prev;
+ for (int j=1; j<glyphs.length; j++) {
+ if (prev+1 != glyphs[j]) {
+ int end = glyphs[j-1];
+ wordGlyphGroups[glyphGroup] = new GlyphGroupInfo
+ (gv, start, end, hide, hideLast[end],
+ glyphPos, advAdj, lastAdvAdj, space);
+ start = glyphs[j];
+ glyphGroup++;
+ }
+ prev = glyphs[j];
+ }
+ int end = glyphs[glyphs.length-1];
+ wordGlyphGroups[glyphGroup] = new GlyphGroupInfo
+ (gv, start, end, hide, hideLast[end],
+ glyphPos, advAdj, lastAdvAdj, space);
+ }
+ wordInfos[i].setGlyphGroups(wordGlyphGroups);
+ }
+ return wordInfos;
}
+
};
Modified: xmlgraphics/batik/branches/anim/sources/org/apache/batik/gvt/flow/TextLineBreaks.java
URL: http://svn.apache.org/viewcvs/xmlgraphics/batik/branches/anim/sources/org/apache/batik/gvt/flow/TextLineBreaks.java?rev=384062&r1=384061&r2=384062&view=diff
==============================================================================
--- xmlgraphics/batik/branches/anim/sources/org/apache/batik/gvt/flow/TextLineBreaks.java (original)
+++ xmlgraphics/batik/branches/anim/sources/org/apache/batik/gvt/flow/TextLineBreaks.java Tue Mar 7 16:03:46 2006
@@ -68,6 +68,7 @@
return;
char ch = aci.current(), prevCh = (char)-1;
byte cls = getCharCharClass(ch);
+ if (cls == CHAR_CLASS_LF) cls = CHAR_CLASS_BK;
byte curCls = cls;
byte prevCls = cls;
byte prevPrevCls = -1;
@@ -77,6 +78,7 @@
int ich = wordBegin+1;
int lineEnd = aci.getRunLimit(lineBrks);
+ // handle case where input starts with an LF
if (cls >= CHAR_CLASS_CM) cls = CHAR_CLASS_AL;
for (ch = aci.next();
@@ -97,7 +99,8 @@
lineEnd = aci.getRunLimit(lineBrks);
continue;
}
- // handle spaces
+
+ // handle spaces
curCls = getCharCharClass(ch);
if (curCls == CHAR_CLASS_SP) {
// pbrk[ich-1] = BREAK_ACTION_PROHIBITED;
@@ -121,6 +124,24 @@
if ((ch == CHAR_ZERO_WIDTH_JOINER) ||
(prevCh == CHAR_ZERO_WIDTH_JOINER))
continue; // Don't allow break around JOINER.
+
+ if ((curCls == CHAR_CLASS_BK) || (curCls == CHAR_CLASS_LF)) {
+ as.addAttribute(WORD_LIMIT, new Integer(wordCnt++),
+ wordBegin, ich);
+ wordBegin = ich;
+ cls = CHAR_CLASS_BK;
+ continue;
+ }
+ if (prevCls == CHAR_CLASS_CR) {
+ as.addAttribute(WORD_LIMIT, new Integer(wordCnt++),
+ wordBegin, ich-1);
+ wordBegin = ich-1;
+ cls = CHAR_CLASS_BK;
+ continue;
+ }
+ if (curCls == CHAR_CLASS_CR) {
+ continue;
+ }
// handle combining marks
if (curCls == CHAR_CLASS_CM) {
@@ -142,6 +163,11 @@
continue;
}
+ if (cls == CHAR_CLASS_BK) {
+ cls = curCls;
+ continue;
+ }
+
// lookup pair table information
byte brk = brkPairs[cls][curCls];
@@ -255,11 +281,11 @@
final public static byte CHAR_CLASS_SA = 20;
final public static byte CHAR_CLASS_SP = 21;
final public static byte CHAR_CLASS_BK = 22;
- final public static byte CHAR_CLASS_AI = 23;
- final public static byte CHAR_CLASS_CR = 24;
- final public static byte CHAR_CLASS_LF = 25;
- final public static byte CHAR_CLASS_SG = 26;
- final public static byte CHAR_CLASS_XX = 27;
+ final public static byte CHAR_CLASS_AI = CHAR_CLASS_AL; // 23;
+ final public static byte CHAR_CLASS_CR = 24; // Can't occur (space res)
+ final public static byte CHAR_CLASS_LF = 25; // Can't occur (space res)
+ final public static byte CHAR_CLASS_SG = CHAR_CLASS_AL; // 26;
+ final public static byte CHAR_CLASS_XX = CHAR_CLASS_AL; // 27;
final public static byte CHAR_CLASS_CB = 28;
final public static String [] clsStrs = {
Modified: xmlgraphics/batik/branches/anim/sources/org/apache/batik/gvt/font/AWTGVTGlyphVector.java
URL: http://svn.apache.org/viewcvs/xmlgraphics/batik/branches/anim/sources/org/apache/batik/gvt/font/AWTGVTGlyphVector.java?rev=384062&r1=384061&r2=384062&view=diff
==============================================================================
--- xmlgraphics/batik/branches/anim/sources/org/apache/batik/gvt/font/AWTGVTGlyphVector.java (original)
+++ xmlgraphics/batik/branches/anim/sources/org/apache/batik/gvt/font/AWTGVTGlyphVector.java Tue Mar 7 16:03:46 2006
@@ -799,11 +799,7 @@
int end = endGlyphIndex+ci.getBeginIndex();
for (char c = ci.setIndex(start); ci.getIndex() <= end; c=ci.next()) {
- if (ArabicTextHandler.isLigature(c)) {
- charCount += ArabicTextHandler.getNumChars(c);
- } else {
- charCount++;
- }
+ charCount += ArabicTextHandler.getNumChars(c);
}
return charCount;
Modified: xmlgraphics/batik/branches/anim/sources/org/apache/batik/gvt/renderer/StrokingTextPainter.java
URL: http://svn.apache.org/viewcvs/xmlgraphics/batik/branches/anim/sources/org/apache/batik/gvt/renderer/StrokingTextPainter.java?rev=384062&r1=384061&r2=384062&view=diff
==============================================================================
--- xmlgraphics/batik/branches/anim/sources/org/apache/batik/gvt/renderer/StrokingTextPainter.java (original)
+++ xmlgraphics/batik/branches/anim/sources/org/apache/batik/gvt/renderer/StrokingTextPainter.java Tue Mar 7 16:03:46 2006
@@ -204,7 +204,7 @@
// System.out.println("Reorder: " + reorderTime + " FontMatching: " + fontMatchingTime + " Layout: " + layoutTime);
// cache the textRuns so don't need to recalculate
node.setTextRuns(textRuns);
- return textRuns;
+ return node.getTextRuns();
}
public List computeTextRuns(TextNode node,
@@ -1673,7 +1673,7 @@
this.anchorType = TextNode.Anchor.ANCHOR_START;
TextNode.Anchor anchor = (TextNode.Anchor) aci.getAttribute
- (GVTAttributedCharacterIterator.TextAttribute.ANCHOR_TYPE);
+ (GVTAttributedCharacterIterator.TextAttribute.ANCHOR_TYPE);
if (anchor != null) {
this.anchorType = anchor.getType();
}
Modified: xmlgraphics/batik/branches/anim/sources/org/apache/batik/gvt/text/ArabicTextHandler.java
URL: http://svn.apache.org/viewcvs/xmlgraphics/batik/branches/anim/sources/org/apache/batik/gvt/text/ArabicTextHandler.java?rev=384062&r1=384061&r2=384062&view=diff
==============================================================================
--- xmlgraphics/batik/branches/anim/sources/org/apache/batik/gvt/text/ArabicTextHandler.java (original)
+++ xmlgraphics/batik/branches/anim/sources/org/apache/batik/gvt/text/ArabicTextHandler.java Tue Mar 7 16:03:46 2006
@@ -1,6 +1,6 @@
/*
- Copyright 2001,2003 The Apache Software Foundation
+ Copyright 2001,2003,2006 The Apache Software Foundation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -53,12 +53,19 @@
GVTAttributedCharacterIterator.TextAttribute.ARABIC_MEDIAL;
/**
+ * private ctor prevents unnecessary instantiation of this class.
+ */
+ private ArabicTextHandler() {
+
+ }
+
+ /*
* If the AttributedString contains any arabic chars, assigns an
* arabic form attribute, i.e. 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) {
@@ -73,47 +80,54 @@
// reorder that part of the string so that it becomes tAB
// construct the reordered ACI
AttributedCharacterIterator aci = as.getIterator();
- boolean didSomeReordering = false;
int numChars = aci.getEndIndex() - aci.getBeginIndex();
- int charOrder[] = new int[numChars];
- for (int i = 0; i < numChars; i++) {
- charOrder[i] = i + aci.getBeginIndex();
- }
- for (int i = 1; i < numChars-1; i++) {
- char c = aci.setIndex(aci.getBeginIndex() + i);
- if (arabicCharTransparent(c)) {
- char prevChar = aci.setIndex(aci.getBeginIndex() + i-1);
- char nextChar = aci.setIndex(aci.getBeginIndex() + i+1);
- if (charMap.get("" + prevChar + nextChar) != null) {
- // found a ligature, separated by a transparent char
- didSomeReordering = true;
- int temp = charOrder[i];
- charOrder[i] = charOrder[i-1];
- charOrder[i-1] = temp;
+ int charOrder[] = null;
+ if (numChars >= 3) {
+ char prevChar = aci.first();
+ char c = aci.next();
+ int i = 1;
+ for (char nextChar = aci.next();
+ nextChar != AttributedCharacterIterator.DONE;
+ prevChar = c, c = nextChar, nextChar = aci.next(), i++) {
+ if (arabicCharTransparent(c)) {
+ if (hasSubstitute(prevChar, nextChar)) {
+ // found a ligature, separated by a transparent char
+ if (charOrder == null) {
+ charOrder = new int[numChars];
+ for (int j = 0; j < numChars; i++) {
+ charOrder[i] = j + aci.getBeginIndex();
+ }
+ }
+ int temp = charOrder[i];
+ charOrder[i] = charOrder[i-1];
+ charOrder[i-1] = temp;
+ }
}
}
}
- if (didSomeReordering) {
+ if (charOrder != null) {
// need to reconstruct the reordered attributed string
- String reorderedString = "";
+ StringBuffer reorderedString = new StringBuffer(numChars);
char c;
for (int i = 0; i < numChars; i++) {
c = aci.setIndex(charOrder[i]);
- reorderedString += c;
+ reorderedString.append( c );
}
- AttributedString reorderedAS = new AttributedString(reorderedString);
+ AttributedString reorderedAS;
+ reorderedAS = new AttributedString(reorderedString.toString());
+
for (int i = 0; i < numChars; i++) {
aci.setIndex(charOrder[i]);
Map attributes = aci.getAttributes();
reorderedAS.addAttributes(attributes, i, i+1);
}
- if ((charOrder[0] == (aci.getBeginIndex()+1)) &&
- (charOrder[1] == aci.getBeginIndex())) {
- // have swapped the first 2 chars, may need to move
+
+ if (charOrder[0] != aci.getBeginIndex()) {
+ // have swapped the first char. Need to move
// any position attributes
- aci.first();
+ aci.setIndex(charOrder[0]);
Float x = (Float) aci.getAttribute(
GVTAttributedCharacterIterator.TextAttribute.X);
Float y = (Float) aci.getAttribute(
@@ -122,17 +136,17 @@
if (x != null && !x.isNaN()) {
reorderedAS.addAttribute
(GVTAttributedCharacterIterator.TextAttribute.X,
- new Float(Float.NaN), 1, 2);
+ new Float(Float.NaN), charOrder[0], charOrder[0]+1);
reorderedAS.addAttribute
- (GVTAttributedCharacterIterator.TextAttribute.X,
+ (GVTAttributedCharacterIterator.TextAttribute.X,
x, 0, 1);
}
if (y != null && !y.isNaN()) {
reorderedAS.addAttribute
(GVTAttributedCharacterIterator.TextAttribute.Y,
- new Float(Float.NaN), 1, 2);
+ new Float(Float.NaN), charOrder[0], charOrder[0]+1);
reorderedAS.addAttribute
- (GVTAttributedCharacterIterator.TextAttribute.Y,
+ (GVTAttributedCharacterIterator.TextAttribute.Y,
y, 0, 1);
}
}
@@ -140,15 +154,23 @@
}
// first assign none to all arabic letters
- int c;
aci = as.getIterator();
- for (int i = aci.getBeginIndex(); i < aci.getEndIndex(); i++) {
- c = aci.setIndex(i);
+ int runStart = -1;
+ int idx = aci.getBeginIndex();
+ for (int c = aci.first();
+ c != AttributedCharacterIterator.DONE;
+ c = aci.next(), idx++) {
if ((c >= arabicStart) && (c <= arabicEnd)) {
- as.addAttribute(ARABIC_FORM, ARABIC_NONE,i, i+1);
+ if (runStart == -1)
+ runStart = idx;
+ } else if (runStart != -1) {
+ as.addAttribute(ARABIC_FORM, ARABIC_NONE, runStart, idx);
+ runStart = -1;
}
}
-
+ if (runStart != -1)
+ as.addAttribute(ARABIC_FORM, ARABIC_NONE, runStart, idx);
+
aci = as.getIterator(); // Make sure ACI tracks ARABIC_FORM
int end = aci.getBeginIndex();
@@ -162,16 +184,16 @@
if (currentForm == null) {
// only modify if the chars in the run are arabic
- continue;
+ continue;
}
-
+
int currentIndex = start;
int prevCharIndex = start-1;
while (currentIndex < end) {
char prevChar = currentChar;
currentChar= aci.setIndex(currentIndex);
- while (arabicCharTransparent(currentChar) &&
+ while (arabicCharTransparent(currentChar) &&
(currentIndex < end)) {
currentIndex++;
currentChar = aci.setIndex(currentIndex);
@@ -188,7 +210,7 @@
&& arabicCharShapesLeft(currentChar)) {
// Increment the form of the previous char
prevForm = new Integer(prevForm.intValue()+1);
- as.addAttribute(ARABIC_FORM, prevForm,
+ as.addAttribute(ARABIC_FORM, prevForm,
prevCharIndex, prevCharIndex+1);
// and set the form of the current char to INITIAL
@@ -245,9 +267,9 @@
* @return True if at least one char is arabic, false otherwise.
*/
public static boolean containsArabic(AttributedCharacterIterator aci) {
- char c;
- for (int i = aci.getBeginIndex(); i < aci.getEndIndex(); i++) {
- c = aci.setIndex(i);
+ for (char c = aci.first();
+ c != AttributedCharacterIterator.DONE;
+ c = aci.next()) {
if (arabicChar(c)) {
return true;
}
@@ -263,11 +285,14 @@
*/
public static boolean arabicCharTransparent(char c) {
int charVal = c;
- if ((charVal >= 0x064B && charVal <= 0x0655) ||
+ if ((charVal < 0x064B) || (charVal > 0x06ED))
+ return false;
+
+ if ((charVal <= 0x0655) ||
(charVal == 0x0670) ||
(charVal >= 0x06D6 && charVal <= 0x06E4) ||
(charVal >= 0x06E7 && charVal <= 0x06E8) ||
- (charVal >= 0x06EA && charVal <= 0x06ED)) {
+ (charVal >= 0x06EA)) {
return true;
}
return false;
@@ -350,6 +375,17 @@
return arabicCharShapesRight(c);
}
+ public static boolean hasSubstitute(char ch1, char ch2) {
+ if ((ch1 < doubleCharFirst) || (ch1 > doubleCharLast)) return false;
+
+ int [][]remaps = doubleCharRemappings[ch1-doubleCharFirst];
+ if (remaps == null) return false;
+ for (int i=0; i<remaps.length; i++) {
+ if (remaps[i][0] == ch2)
+ return true;
+ }
+ return false;
+ }
/**
* Will try and find a substitute character of the specified form.
@@ -362,16 +398,29 @@
* @return The unicode value of the substutute char, or -1 if no susbtitue
* exists.
*/
- public static int getSubstituteChar(String unicode, int form) {
+ public static int getSubstituteChar(char ch1, char ch2, int form) {
if (form == 0) return -1;
- int chars[] = (int[])charMap.get(unicode);
- if (chars == null) return -1;
+ if ((ch1 < doubleCharFirst) || (ch1 > doubleCharLast)) return -1;
- if (chars[form-1] > 0)
- return chars[form-1];
+ int [][]remaps = doubleCharRemappings[ch1-doubleCharFirst];
+ if (remaps == null) return -1;
+ for (int i=0; i<remaps.length; i++) {
+ if (remaps[i][0] == ch2)
+ return remaps[i][form];
+ }
return -1;
}
+ public static int getSubstituteChar(char ch, int form) {
+ if (form == 0) return -1;
+ if ((ch < singleCharFirst) || (ch > singleCharLast)) return -1;
+
+ int chars[] = singleCharRemappings[ch-singleCharFirst];
+ if (chars == null) return -1;
+
+ return chars[form-1];
+ }
+
/**
* Where possible substitues plain arabic glyphs with their shaped
* forms. This is needed when the arabic text is rendered using
@@ -385,66 +434,68 @@
* @return A String containing the shaped versions of the arabic characters
*/
public static String createSubstituteString(AttributedCharacterIterator aci) {
-
- String substString = "";
- for (int i = aci.getBeginIndex(); i < aci.getEndIndex(); i++) {
+ int start = aci.getBeginIndex();
+ int end = aci.getEndIndex();
+ int numChar = end-start;
+ StringBuffer substString = new StringBuffer(numChar);
+ for (int i=start; i< end; i++) {
char c = aci.setIndex(i);
- if (arabicChar(c)) {
- Integer form = (Integer)aci.getAttribute(ARABIC_FORM);
- // see if the c is the start of a ligature
- if (charStartsLigature(c) && i < aci.getEndIndex()) {
- char nextChar = aci.setIndex(i+1);
- Integer nextForm = (Integer)aci.getAttribute(ARABIC_FORM);
- if (form != null && nextForm != null) {
- if (form.equals(ARABIC_TERMINAL)
- && nextForm.equals(ARABIC_INITIAL)) {
- // look for an isolated ligature
- int substChar = ArabicTextHandler.getSubstituteChar
- ("" + c + nextChar,ARABIC_ISOLATED.intValue());
- if (substChar > -1) {
- substString += (char)substChar;
- i++;
- continue;
- }
- } else if (form.equals(ARABIC_TERMINAL)) {
- // look for a terminal ligature
- int substChar = ArabicTextHandler.getSubstituteChar
- ("" + c + nextChar,ARABIC_TERMINAL.intValue());
- if (substChar > -1) {
- substString += (char)substChar;
- i++;
- continue;
- }
- } else if (form.equals(ARABIC_MEDIAL)
- && nextForm.equals(ARABIC_MEDIAL)) {
- // look for a medial ligature
- int substChar = ArabicTextHandler.getSubstituteChar
- ("" + c + nextChar,ARABIC_MEDIAL.intValue());
- if (substChar > -1) {
- substString += (char)substChar;
- i++;
- continue;
- }
+ if (!arabicChar(c)) {
+ substString.append(c);
+ continue;
+ }
+
+ Integer form = (Integer)aci.getAttribute(ARABIC_FORM);
+ // see if the c is the start of a ligature
+ if (charStartsLigature(c) && (i+1 < end)) {
+ char nextChar = aci.setIndex(i+1);
+ Integer nextForm = (Integer)aci.getAttribute(ARABIC_FORM);
+ if (form != null && nextForm != null) {
+ if (form.equals(ARABIC_TERMINAL)
+ && nextForm.equals(ARABIC_INITIAL)) {
+ // look for an isolated ligature
+ int substChar = ArabicTextHandler.getSubstituteChar
+ (c, nextChar,ARABIC_ISOLATED.intValue());
+ if (substChar > -1) {
+ substString.append((char)substChar);
+ i++;
+ continue;
+ }
+ } else if (form.equals(ARABIC_TERMINAL)) {
+ // look for a terminal ligature
+ int substChar = ArabicTextHandler.getSubstituteChar
+ (c, nextChar,ARABIC_TERMINAL.intValue());
+ if (substChar > -1) {
+ substString.append((char)substChar);
+ i++;
+ continue;
+ }
+ } else if (form.equals(ARABIC_MEDIAL)
+ && nextForm.equals(ARABIC_MEDIAL)) {
+ // look for a medial ligature
+ int substChar = ArabicTextHandler.getSubstituteChar
+ (c, nextChar,ARABIC_MEDIAL.intValue());
+ if (substChar > -1) {
+ substString.append((char)substChar);
+ i++;
+ continue;
}
}
}
+ }
- // couln't find a matching ligature so just look for a simple substitution
- if (form != null && form.intValue() > 0) {
- int substChar = ArabicTextHandler.getSubstituteChar(""+c, form.intValue());
- if (substChar > -1) {
- substString += (char)substChar;
- } else {
- substString += c;
- }
- } else {
- substString += c;
+ // couldn't find a matching ligature so just look for a
+ // simple substitution
+ if (form != null && form.intValue() > 0) {
+ int substChar = getSubstituteChar(c, form.intValue());
+ if (substChar > -1) {
+ c = (char)substChar;
}
- } else {
- substString += c;
}
+ substString.append(c);
}
- return substString;
+
+ return substString.toString();
}
/**
@@ -466,209 +517,151 @@
}
/**
- * Returns the number of characters the glyph for the specified character
- * represents. If the glyph represents a ligature this will be 2, otherwise 1.
+ * Returns the number of characters the glyph for the specified
+ * character represents. If the glyph represents a ligature this
+ * will be 2, otherwise 1.
*
* @param c The character to test.
* @return The number of characters the glyph for c represents.
*/
public static int getNumChars(char c) {
// if c is a ligature returns 2, else returns 1
- if (isLigature(c)) {
+ if (isLigature(c))
// at the moment only support ligatures with two chars
return 2;
- }
return 1;
}
/**
- * Returns true if the glyph for the specified character respresents a ligature.
+ * Returns true if the glyph for the specified character
+ * respresents a ligature.
*
* @param c The character to test.
* @return True if c is a ligature, false otherwise.
*/
public static boolean isLigature(char c) {
int charVal = c;
- if ((charVal >= 0xFE70 && charVal <= 0xFE72)
- || (charVal == 0xFE74)
- || (charVal >= 0xFE76 && charVal <= 0xFE7F)
- || (charVal >= 0xFEF5 && charVal <= 0xFEFC)) {
+ if ((charVal < 0xFE70) || (charVal > 0xFEFC))
+ return false;
+
+ if ((charVal <= 0xFE72) ||
+ (charVal == 0xFE74) ||
+ (charVal >= 0xFE76 && charVal <= 0xFE7F) ||
+ (charVal >= 0xFEF5)) {
return true;
}
return false;
}
- static {
-
- // constructs the character map that maps arabic characters and
- // ligature to their various forms
- // NOTE: the unicode values for ligatures are stored here in
- // visual order (not logical order)
-
- int chars1[] = {0xFE70, -1, -1, -1}; // isolated, final, initial, medial
- charMap.put(new String("" + (char)0x064B + (char)0x0020), chars1);
-
- int chars2[] = {-1, -1, -1, 0xFE71};
- charMap.put(new String("" + (char)0x064B + (char)0x0640), chars2);
-
- int chars3[] = {0xFE72, -1, -1, -1};
- charMap.put(new String("" + (char)0x064C + (char)0x0020), chars3);
-
- int chars4[] = {0xFE74, -1, -1, -1};
- charMap.put(new String("" + (char)0x064D + (char)0x0020), chars4);
-
- int chars5[] = {0xFE76, -1, -1, -1};
- charMap.put(new String("" + (char)0x064E + (char)0x0020), chars5);
-
- int chars6[] = {-1, -1, -1, 0xFE77};
- charMap.put(new String("" + (char)0x064E + (char)0x0640), chars6);
-
- int chars7[] = {0xFE78, -1, -1, -1};
- charMap.put(new String("" + (char)0x064F + (char)0x0020), chars7);
-
- int chars8[] = {-1, -1, -1, 0xFE79};
- charMap.put(new String("" + (char)0x064F + (char)0x0640), chars8);
-
- int chars9[] = {0xFE7A, -1, -1, -1};
- charMap.put(new String("" + (char)0x0650 + (char)0x0020), chars9);
-
- int chars10[] = {-1, -1, -1, 0xFE7B};
- charMap.put(new String("" + (char)0x0650 + (char)0x0640), chars10);
-
- int chars11[] = {0xFE7C, -1, -1, -1};
- charMap.put(new String("" + (char)0x0651 + (char)0x0020), chars11);
-
- int chars12[] = {-1, -1, -1, 0xFE7D};
- charMap.put(new String("" + (char)0x0651 + (char)0x0640), chars12);
-
- int chars13[] = {0xFE7E, -1, -1, -1};
- charMap.put(new String("" + (char)0x0652 + (char)0x0020), chars13);
-
- int chars14[] = {-1, -1, -1, 0xFE7F};
- charMap.put(new String("" + (char)0x0652 + (char)0x0640), chars14);
-
- int chars15[] = {0xFE80, -1, -1, -1};
- charMap.put(new String("" + (char)0x0621), chars15);
-
- int chars16[] = {0xFE81, 0xFE82, -1, -1};
- charMap.put(new String("" + (char)0x0622), chars16);
-
- int chars17[] = {0xFE83, 0xFE84, -1, -1};
- charMap.put(new String("" + (char)0x0623), chars17);
-
- int chars18[] = {0xFE85, 0xFE86, -1, -1};
- charMap.put(new String("" + (char)0x0624), chars18);
-
- int chars19[] = {0xFE87, 0xFE88, -1, -1};
- charMap.put(new String("" + (char)0x0625), chars19);
-
- int chars20[] = {0xFE89, 0xFE8A, 0xFE8B, 0xFE8C};
- charMap.put(new String("" + (char)0x0626), chars20);
-
- int chars21[] = {0xFE8D, 0xFE8E, -1, -1};
- charMap.put(new String("" + (char)0x0627), chars21);
-
- int chars22[] = {0xFE8F, 0xFE90, 0xFE91, 0xFE92};
- charMap.put(new String("" + (char)0x0628), chars22);
-
- int chars23[] = {0xFE93, 0xFE94, -1, -1};
- charMap.put(new String("" + (char)0x0629), chars23);
-
- int chars24[] = {0xFE95, 0xFE96, 0xFE97, 0xFE98};
- charMap.put(new String("" + (char)0x062A), chars24);
-
- int chars25[] = {0xFE99, 0xFE9A, 0xFE9B, 0xFE9C};
- charMap.put(new String("" + (char)0x062B), chars25);
-
- int chars26[] = {0xFE9D, 0xFE9E, 0xFE9F, 0xFEA0};
- charMap.put(new String("" + (char)0x062C), chars26);
-
- int chars27[] = {0xFEA1, 0xFEA2, 0xFEA3, 0xFEA4};
- charMap.put(new String("" + (char)0x062D), chars27);
-
- int chars28[] = {0xFEA5, 0xFEA6, 0xFEA7, 0xFEA8};
- charMap.put(new String("" + (char)0x062E), chars28);
-
- int chars29[] = {0xFEA9, 0xFEAA, -1, -1};
- charMap.put(new String("" + (char)0x062F), chars29);
-
- int chars30[] = {0xFEAB, 0xFEAC, -1, -1};
- charMap.put(new String("" + (char)0x0630), chars30);
-
- int chars31[] = {0xFEAD, 0xFEAE, -1, -1};
- charMap.put(new String("" + (char)0x0631), chars31);
-
- int chars32[] = {0xFEAF, 0xFEB0, -1, -1};
- charMap.put(new String("" + (char)0x0632), chars32);
-
- int chars33[] = {0xFEB1, 0xFEB2, 0xFEB3, 0xFEB4};
- charMap.put(new String("" + (char)0x0633), chars33);
-
- int chars34[] = {0xFEB5, 0xFEB6, 0xFEB7, 0xFEB8};
- charMap.put(new String("" + (char)0x0634), chars34);
-
- int chars35[] = {0xFEB9, 0xFEBA, 0xFEBB, 0xFEBC};
- charMap.put(new String("" + (char)0x0635), chars35);
-
- int chars36[] = {0xFEBD, 0xFEBE, 0xFEBF, 0xFEC0};
- charMap.put(new String("" + (char)0x0636), chars36);
-
- int chars37[] = {0xFEC1, 0xFEC2, 0xFEC3, 0xFEC4};
- charMap.put(new String("" + (char)0x0637), chars37);
-
- int chars38[] = {0xFEC5, 0xFEC6, 0xFEC7, 0xFEC8};
- charMap.put(new String("" + (char)0x0638), chars38);
-
- int chars39[] = {0xFEC9, 0xFECA, 0xFECB, 0xFECC};
- charMap.put(new String("" + (char)0x0639), chars39);
-
- int chars40[] = { 0xFECD, 0xFECE, 0xFECF, 0xFED0};
- charMap.put(new String("" + (char)0x063A), chars40);
-
- int chars41[] = {0xFED1, 0xFED2, 0xFED3, 0xFED4};
- charMap.put(new String("" + (char)0x0641), chars41);
-
- int chars42[] = {0xFED5, 0xFED6, 0xFED7, 0xFED8};
- charMap.put(new String("" + (char)0x0642), chars42);
-
- int chars43[] = {0xFED9, 0xFEDA, 0xFEDB, 0xFEDC};
- charMap.put(new String("" + (char)0x0643), chars43);
-
- int chars44[] = {0xFEDD, 0xFEDE, 0xFEDF, 0xFEE0};
- charMap.put(new String("" + (char)0x0644), chars44);
-
- int chars45[] = {0xFEE1, 0xFEE2, 0xFEE3, 0xFEE4};
- charMap.put(new String("" + (char)0x0645), chars45);
-
- int chars46[] = {0xFEE5, 0xFEE6, 0xFEE7, 0xFEE8};
- charMap.put(new String("" + (char)0x0646), chars46);
-
- int chars47[] = {0xFEE9, 0xFEEA, 0xFEEB, 0xFEEC};
- charMap.put(new String("" + (char)0x0647), chars47);
-
- int chars48[] = {0xFEED, 0xFEEE, -1, -1};
- charMap.put(new String("" + (char)0x0648), chars48);
-
- int chars49[] = {0xFEEF, 0xFEF0, -1, -1};
- charMap.put(new String("" + (char)0x0649), chars49);
-
- int chars50[] = {0xFEF1, 0xFEF2, 0xFEF3, 0xFEF4};
- charMap.put(new String("" + (char)0x064A), chars50);
-
- int chars51[] = {0xFEF5, 0xFEF6, -1, -1};
- charMap.put(new String("" + (char)0x0622 + (char)0x0644), chars51);
-
- int chars52[] = {0xFEF7, 0xFEF8, -1, -1};
- charMap.put(new String("" + (char)0x0623 + (char)0x0644), chars52);
-
- int chars53[] = {0xFEF9, 0xFEFA, -1, -1};
- charMap.put(new String("" + (char)0x0625 + (char)0x0644), chars53);
-
- int chars54[] = {0xFEFB, 0xFEFC, -1, -1};
- charMap.put(new String("" + (char)0x0627 + (char)0x0644), chars54);
-
- }
-
-
+ // constructs the character map that maps arabic characters and
+ // ligature to their various forms
+ // NOTE: the unicode values for ligatures are stored here in
+ // visual order (not logical order)
+
+ // Single char remappings:
+ static int singleCharFirst=0x0621;
+ static int singleCharLast =0x064A;
+ static int [][] singleCharRemappings = {
+ // isolated, final, initial, medial
+ {0xFE80, -1, -1, -1}, // 0x0621
+ {0xFE81, 0xFE82, -1, -1}, // 0x0622
+ {0xFE83, 0xFE84, -1, -1}, // 0x0623
+ {0xFE85, 0xFE86, -1, -1}, // 0x0624
+ {0xFE87, 0xFE88, -1, -1}, // 0x0625
+ {0xFE89, 0xFE8A, 0xFE8B, 0xFE8C}, // 0x0626
+ {0xFE8D, 0xFE8E, -1, -1}, // 0x0627
+ {0xFE8F, 0xFE90, 0xFE91, 0xFE92}, // 0x0628
+ {0xFE93, 0xFE94, -1, -1}, // 0x0629
+ {0xFE95, 0xFE96, 0xFE97, 0xFE98}, // 0x062A
+ {0xFE99, 0xFE9A, 0xFE9B, 0xFE9C}, // 0x062B
+ {0xFE9D, 0xFE9E, 0xFE9F, 0xFEA0}, // 0x062C
+ {0xFEA1, 0xFEA2, 0xFEA3, 0xFEA4}, // 0x062D
+ {0xFEA5, 0xFEA6, 0xFEA7, 0xFEA8}, // 0x062E
+ {0xFEA9, 0xFEAA, -1, -1}, // 0x062F
+ {0xFEAB, 0xFEAC, -1, -1}, // 0x0630
+ {0xFEAD, 0xFEAE, -1, -1}, // 0x0631
+ {0xFEAF, 0xFEB0, -1, -1}, // 0x0632
+ {0xFEB1, 0xFEB2, 0xFEB3, 0xFEB4}, // 0x0633
+ {0xFEB5, 0xFEB6, 0xFEB7, 0xFEB8}, // 0x0634
+ {0xFEB9, 0xFEBA, 0xFEBB, 0xFEBC}, // 0x0635
+ {0xFEBD, 0xFEBE, 0xFEBF, 0xFEC0}, // 0x0636
+ {0xFEC1, 0xFEC2, 0xFEC3, 0xFEC4}, // 0x0637
+ {0xFEC5, 0xFEC6, 0xFEC7, 0xFEC8}, // 0x0638
+ {0xFEC9, 0xFECA, 0xFECB, 0xFECC}, // 0x0639
+ {0xFECD, 0xFECE, 0xFECF, 0xFED0}, // 0x063A
+
+ null, // 0x063B
+ null, // 0x063C
+ null, // 0x063D
+ null, // 0x063E
+ null, // 0x063F
+ null, // 0x0640
+
+ {0xFED1, 0xFED2, 0xFED3, 0xFED4}, // 0x0641
+ {0xFED5, 0xFED6, 0xFED7, 0xFED8}, // 0x0642
+ {0xFED9, 0xFEDA, 0xFEDB, 0xFEDC}, // 0x0643
+ {0xFEDD, 0xFEDE, 0xFEDF, 0xFEE0}, // 0x0644
+ {0xFEE1, 0xFEE2, 0xFEE3, 0xFEE4}, // 0x0645
+ {0xFEE5, 0xFEE6, 0xFEE7, 0xFEE8}, // 0x0646
+ {0xFEE9, 0xFEEA, 0xFEEB, 0xFEEC}, // 0x0647
+ {0xFEED, 0xFEEE, -1, -1}, // 0x0648
+ {0xFEEF, 0xFEF0, -1, -1}, // 0x0649
+ {0xFEF1, 0xFEF2, 0xFEF3, 0xFEF4}}; // 0x064A
+
+ static int doubleCharFirst=0x0622;
+ static int doubleCharLast =0x0652;
+ static int [][][] doubleCharRemappings = {
+ // 2nd Char, isolated, final, initial, medial
+ {{0x0644, 0xFEF5, 0xFEF6, -1, -1}}, // 0x0622
+ {{0x0644, 0xFEF7, 0xFEF8, -1, -1}}, // 0x0623
+ null, // 0x0624
+ {{0x0644, 0xFEF9, 0xFEFA, -1, -1}}, // 0x0625
+ null, // 0x0626
+ {{0x0644, 0xFEFB, 0xFEFC, -1, -1}}, // 0x0627
+
+ null, // 0x0628
+ null, // 0x0629
+ null, // 0x0630
+ null, // 0x0631
+ null, // 0x0632
+ null, // 0x0633
+ null, // 0x0634
+ null, // 0x0635
+ null, // 0x0636
+ null, // 0x0637
+ null, // 0x0638
+ null, // 0x0639
+ null, // 0x063A
+ null, // 0x063B
+ null, // 0x063C
+ null, // 0x063D
+ null, // 0x063E
+ null, // 0x063F
+ null, // 0x0640
+ null, // 0x0641
+ null, // 0x0642
+ null, // 0x0643
+ null, // 0x0644
+ null, // 0x0645
+ null, // 0x0646
+ null, // 0x0647
+ null, // 0x0648
+ null, // 0x0649
+ null, // 0x064A
+
+ {{0x0020, 0xFE70, -1, -1, -1}, // 0x064B
+ {0x0640, -1, -1, -1, 0xFE71}},
+ {{0x0020, 0xFE72, -1, -1, -1}}, // 0x064C
+ {{0x0020, 0xFE74, -1, -1, -1}}, // 0x064D
+ {{0x0020, 0xFE76, -1, -1, -1}, // 0x064E
+ {0x0640, -1, -1, -1, 0xFE77}},
+ {{0x0020, 0xFE78, -1, -1, -1}, // 0x064F
+ {0x0640, -1, -1, -1, 0xFE79}},
+ {{0x0020, 0xFE7A, -1, -1, -1}, // 0x0650
+ {0x0640, -1, -1, -1, 0xFE7B}},
+ {{0x0020, 0xFE7C, -1, -1, -1}, // 0x0651
+ {0x0640, -1, -1, -1, 0xFE7D}},
+ {{0x0020, 0xFE7E, -1, -1, -1}, // 0x0652
+ {0x0640, -1, -1, -1, 0xFE7F}}};
}
Modified: xmlgraphics/batik/branches/anim/sources/org/apache/batik/gvt/text/GlyphLayout.java
URL: http://svn.apache.org/viewcvs/xmlgraphics/batik/branches/anim/sources/org/apache/batik/gvt/text/GlyphLayout.java?rev=384062&r1=384061&r2=384062&view=diff
==============================================================================
--- xmlgraphics/batik/branches/anim/sources/org/apache/batik/gvt/text/GlyphLayout.java (original)
+++ xmlgraphics/batik/branches/anim/sources/org/apache/batik/gvt/text/GlyphLayout.java Tue Mar 7 16:03:46 2006
@@ -55,11 +55,6 @@
*/
public class GlyphLayout implements TextSpanLayout {
- public static final char SOFT_HYPHEN = 0x00AD;
- public static final char ZERO_WIDTH_SPACE = 0x200B;
- public static final char ZERO_WIDTH_JOINER = 0x200D;
- public static final char SPACE = ' ';
-
private GVTGlyphVector gv;
private GVTFont font;
private GVTLineMetrics metrics;
Modified: xmlgraphics/batik/branches/anim/sources/org/apache/batik/script/rhino/RhinoClassLoader.java
URL: http://svn.apache.org/viewcvs/xmlgraphics/batik/branches/anim/sources/org/apache/batik/script/rhino/RhinoClassLoader.java?rev=384062&r1=384061&r2=384062&view=diff
==============================================================================
--- xmlgraphics/batik/branches/anim/sources/org/apache/batik/script/rhino/RhinoClassLoader.java (original)
+++ xmlgraphics/batik/branches/anim/sources/org/apache/batik/script/rhino/RhinoClassLoader.java Tue Mar 7 16:03:46 2006
@@ -164,4 +164,3 @@
return perms;
}
}
-