Added:
xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/font/ComplexGlyphVector.java
URL:
http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/font/ComplexGlyphVector.java?rev=1615385&view=auto
==============================================================================
---
xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/font/ComplexGlyphVector.java
(added)
+++
xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/font/ComplexGlyphVector.java
Sun Aug 3 04:40:34 2014
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.svg.font;
+
+import java.awt.font.FontRenderContext;
+import java.text.AttributedCharacterIterator;
+import java.text.CharacterIterator;
+
+import org.apache.batik.gvt.text.GVTAttributedCharacterIterator;
+
+import org.apache.fop.fonts.GlyphMapping;
+
+class ComplexGlyphVector extends FOPGVTGlyphVector {
+
+ public static final AttributedCharacterIterator.Attribute WRITING_MODE
+ = GVTAttributedCharacterIterator.TextAttribute.WRITING_MODE;
+
+ public static final Integer WRITING_MODE_RTL
+ = GVTAttributedCharacterIterator.TextAttribute.WRITING_MODE_RTL;
+
+ ComplexGlyphVector(FOPGVTFont font, final CharacterIterator iter,
FontRenderContext frc) {
+ super(font, iter, frc);
+ }
+
+ public void performDefaultLayout() {
+ super.performDefaultLayout();
+ }
+
+ protected void maybeReverse(GlyphMapping mapping) {
+ if (charIter instanceof AttributedCharacterIterator) {
+ AttributedCharacterIterator aci = (AttributedCharacterIterator)
charIter;
+ aci.first();
+ if (aci.getAttribute(WRITING_MODE) == WRITING_MODE_RTL) {
+ mapping.reverse();
+ }
+ }
+ }
+
+}
Propchange:
xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/font/ComplexGlyphVector.java
------------------------------------------------------------------------------
svn:eol-style = LF
Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/font/FOPGVTFont.java
URL:
http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/font/FOPGVTFont.java?rev=1615385&r1=1615384&r2=1615385&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/font/FOPGVTFont.java
(original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/font/FOPGVTFont.java Sun
Aug 3 04:40:34 2014
@@ -20,6 +20,7 @@
package org.apache.fop.svg.font;
import java.awt.font.FontRenderContext;
+import java.text.AttributedString;
import java.text.CharacterIterator;
import java.text.StringCharacterIterator;
@@ -27,6 +28,7 @@ import org.apache.batik.gvt.font.GVTFont
import org.apache.batik.gvt.font.GVTFontFamily;
import org.apache.batik.gvt.font.GVTGlyphVector;
import org.apache.batik.gvt.font.GVTLineMetrics;
+import org.apache.batik.gvt.text.GVTAttributedCharacterIterator;
import org.apache.fop.fonts.Font;
import org.apache.fop.fonts.FontMetrics;
@@ -83,8 +85,11 @@ public class FOPGVTFont implements GVTFo
}
public GVTGlyphVector createGlyphVector(FontRenderContext frc,
CharacterIterator ci) {
- // TODO Batik does manual glyph shaping for Arabic. Replace with
complex scripts implementation
- return new FOPGVTGlyphVector(this, ci, frc);
+ if (!font.performsSubstitution() && !font.performsPositioning()) {
+ return new FOPGVTGlyphVector(this, ci, frc);
+ } else {
+ return new ComplexGlyphVector(this, ci, frc);
+ }
}
public GVTGlyphVector createGlyphVector(FontRenderContext frc,
@@ -93,11 +98,26 @@ public class FOPGVTFont implements GVTFo
throw new UnsupportedOperationException("Not implemented");
}
- public GVTGlyphVector createGlyphVector(FontRenderContext frc, String str)
{
- StringCharacterIterator sci = new StringCharacterIterator(str);
+ public GVTGlyphVector createGlyphVector(FontRenderContext frc, String
text) {
+ StringCharacterIterator sci = new StringCharacterIterator(text);
return createGlyphVector(frc, sci);
}
+ public GVTGlyphVector createGlyphVector(FontRenderContext frc, String
text, String script, String language) {
+ if ((script != null) || (language != null)) {
+ AttributedString as = new AttributedString(text);
+ if (script != null) {
+
as.addAttribute(GVTAttributedCharacterIterator.TextAttribute.SCRIPT, script);
+ }
+ if (language != null) {
+
as.addAttribute(GVTAttributedCharacterIterator.TextAttribute.LANGUAGE,
language);
+ }
+ return createGlyphVector(frc, as.getIterator());
+ } else {
+ return createGlyphVector(frc, text);
+ }
+ }
+
public FOPGVTFont deriveFont(float size) {
throw new UnsupportedOperationException("Not implemented");
}
Modified:
xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/font/FOPGVTGlyphVector.java
URL:
http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/font/FOPGVTGlyphVector.java?rev=1615385&r1=1615384&r2=1615385&view=diff
==============================================================================
---
xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/font/FOPGVTGlyphVector.java
(original)
+++
xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/font/FOPGVTGlyphVector.java
Sun Aug 3 04:40:34 2014
@@ -33,11 +33,13 @@ import java.text.AttributedCharacterIter
import java.text.CharacterIterator;
import java.text.StringCharacterIterator;
import java.util.Arrays;
+import java.util.List;
import org.apache.batik.gvt.font.GVTFont;
import org.apache.batik.gvt.font.GVTGlyphMetrics;
import org.apache.batik.gvt.font.GVTGlyphVector;
import org.apache.batik.gvt.font.GVTLineMetrics;
+import org.apache.batik.gvt.text.GVTAttributedCharacterIterator;
import org.apache.fop.fonts.Font;
import org.apache.fop.fonts.FontMetrics;
@@ -47,7 +49,7 @@ import org.apache.fop.traits.MinOptMax;
class FOPGVTGlyphVector implements GVTGlyphVector {
- private final CharacterIterator charIter;
+ protected final CharacterIterator charIter;
private final FOPGVTFont font;
@@ -57,9 +59,11 @@ class FOPGVTGlyphVector implements GVTGl
private final FontRenderContext frc;
- private int[] glyphs;
+ protected int[] glyphs;
- private float[] positions;
+ protected List associations;
+
+ protected float[] positions;
private Rectangle2D[] boundingBoxes;
@@ -86,20 +90,37 @@ class FOPGVTGlyphVector implements GVTGl
MinOptMax letterSpaceIPD = MinOptMax.ZERO;
MinOptMax[] letterSpaceAdjustments = new
MinOptMax[charIter.getEndIndex() - charIter.getBeginIndex()];
GlyphMapping mapping = GlyphMapping.doGlyphMapping(text,
charIter.getBeginIndex(), charIter.getEndIndex(),
- f, letterSpaceIPD, letterSpaceAdjustments, '\0', '\0', false,
0 /* TODO */);
- glyphs = buildGlyphs(f, mapping.mapping != null ? new
StringCharacterIterator(mapping.mapping) : charIter);
- buildGlyphPositions(mapping, letterSpaceAdjustments);
+ f, letterSpaceIPD, letterSpaceAdjustments, '\0', '\0', false, 0,
true);
+ maybeReverse(mapping);
+ CharacterIterator glyphAsCharIter =
+ mapping.mapping != null ? new
StringCharacterIterator(mapping.mapping) : charIter;
+ this.glyphs = buildGlyphs(f, glyphAsCharIter);
+ this.associations = mapping.associations;
+ this.positions = buildGlyphPositions(glyphAsCharIter,
mapping.gposAdjustments, letterSpaceAdjustments);
this.glyphVisibilities = new boolean[this.glyphs.length];
Arrays.fill(glyphVisibilities, true);
this.glyphTransforms = new AffineTransform[this.glyphs.length];
}
+ protected void maybeReverse(GlyphMapping mapping) {
+ }
+
private static class SVGTextFragment implements TextFragment {
private final CharacterIterator charIter;
+ private String script;
+
+ private String language;
+
SVGTextFragment(CharacterIterator charIter) {
this.charIter = charIter;
+ if (charIter instanceof AttributedCharacterIterator) {
+ AttributedCharacterIterator aci =
(AttributedCharacterIterator) charIter;
+ aci.first();
+ this.script = (String)
aci.getAttribute(GVTAttributedCharacterIterator.TextAttribute.SCRIPT);
+ this.language = (String)
aci.getAttribute(GVTAttributedCharacterIterator.TextAttribute.LANGUAGE);
+ }
}
public CharSequence subSequence(int startIndex, int endIndex) {
@@ -111,11 +132,19 @@ class FOPGVTGlyphVector implements GVTGl
}
public String getScript() {
- return "DFLT"; // TODO pass on script value from SVG
+ if (script != null) {
+ return script;
+ } else {
+ return "auto";
+ }
}
public String getLanguage() {
- return "dflt"; // TODO pass on language value from SVG
+ if (language != null) {
+ return language;
+ } else {
+ return "none";
+ }
}
public char charAt(int index) {
@@ -123,42 +152,69 @@ class FOPGVTGlyphVector implements GVTGl
}
}
- private int[] buildGlyphs(Font font, final CharacterIterator charIter) {
- int[] glyphs = new int[charIter.getEndIndex() -
charIter.getBeginIndex()];
+ private int[] buildGlyphs(Font font, final CharacterIterator
glyphAsCharIter) {
+ int[] glyphs = new int[glyphAsCharIter.getEndIndex() -
glyphAsCharIter.getBeginIndex()];
int index = 0;
- for (char c = charIter.first(); c != CharacterIterator.DONE; c =
charIter.next()) {
+ for (char c = glyphAsCharIter.first(); c != CharacterIterator.DONE; c
= glyphAsCharIter.next()) {
glyphs[index] = font.mapChar(c);
index++;
}
return glyphs;
}
- private void buildGlyphPositions(GlyphMapping ai, MinOptMax[]
letterSpaceAdjustments) {
- positions = new float[2 * glyphs.length + 2];
- if (ai.gposAdjustments != null) {
- assert ai.gposAdjustments.length == glyphs.length;
- for (int glyphIndex = 0; glyphIndex < glyphs.length; glyphIndex++)
{
- int n = 2 * glyphIndex;
- if (ai.gposAdjustments[glyphIndex] != null) {
- for (int p = 0; p < 4; p++) {
- positions[n + p] += ai.gposAdjustments[glyphIndex][p]
/ 1000f;
- }
- }
- positions[n + 2] += positions[n] + getGlyphWidth(glyphIndex);
+ private static final int[] PA_ZERO = new int[4];
+
+ /**
+ * Build glyph position array.
+ * @param glyphAsCharIter iterator for mapped glyphs as char codes (not
glyph codes)
+ * @param dp optionally null glyph position adjustments array
+ * @param lsa optionally null letter space adjustments array
+ * @return array of floats that denote [X,Y] position pairs for each glyph
including
+ * including an implied subsequent glyph; i.e., returned array contains
one more pair
+ * than the numbers of glyphs, where the position denoted by this last
pair represents
+ * the position after the last glyph has incurred advancement
+ */
+ private float[] buildGlyphPositions(final CharacterIterator
glyphAsCharIter, int[][] dp, MinOptMax[] lsa) {
+ int numGlyphs = glyphAsCharIter.getEndIndex() -
glyphAsCharIter.getBeginIndex();
+ float[] positions = new float[2 * (numGlyphs + 1)];
+ float xc = 0f;
+ float yc = 0f;
+ if (dp != null) {
+ for (int i = 0; i < numGlyphs + 1; ++i) {
+ int[] pa = ((i >= dp.length) || (dp[i] == null)) ? PA_ZERO :
dp[i];
+ float xo = xc + ((float) pa[0]) / 1000f;
+ float yo = yc - ((float) pa[1]) / 1000f;
+ float xa = getGlyphWidth(i) + ((float) pa[2]) / 1000f;
+ float ya = ((float) pa[3]) / 1000f;
+ int k = 2 * i;
+ positions[k + 0] = xo;
+ positions[k + 1] = yo;
+ xc += xa;
+ yc += ya;
}
- } else {
- for (int i = 0, n = 2; i < glyphs.length; i++, n += 2) {
- int kern = i < glyphs.length - 1 && letterSpaceAdjustments[i +
1] != null
- ? letterSpaceAdjustments[i + 1].getOpt()
- : 0;
- positions[n] = positions[n - 2] + getGlyphWidth(i) + kern /
1000f;
- positions[n + 1] = 0;
+ } else if (lsa != null) {
+ for (int i = 0; i < numGlyphs + 1; ++i) {
+ MinOptMax sa = (((i + 1) >= lsa.length) || (lsa[i + 1] ==
null)) ? MinOptMax.ZERO : lsa[i + 1];
+ float xo = xc;
+ float yo = yc;
+ float xa = getGlyphWidth(i) + sa.getOpt() / 1000f;
+ float ya = 0;
+ int k = 2 * i;
+ positions[k + 0] = xo;
+ positions[k + 1] = yo;
+ xc += xa;
+ yc += ya;
}
}
+ return positions;
}
private float getGlyphWidth(int index) {
- return fontMetrics.getWidth(glyphs[index], fontSize) / 1000000f;
+ if (index < glyphs.length) {
+ return fontMetrics.getWidth(glyphs[index], fontSize) / 1000000f;
+ } else {
+ return 0f;
+ }
}
public GVTFont getFont() {
Added:
xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/text/ComplexGlyphLayout.java
URL:
http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/text/ComplexGlyphLayout.java?rev=1615385&view=auto
==============================================================================
---
xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/text/ComplexGlyphLayout.java
(added)
+++
xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/text/ComplexGlyphLayout.java
Sun Aug 3 04:40:34 2014
@@ -0,0 +1,78 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.svg.text;
+
+import java.awt.font.FontRenderContext;
+import java.awt.geom.Point2D;
+import java.text.AttributedCharacterIterator;
+
+import org.apache.batik.gvt.font.GVTFont;
+import org.apache.batik.gvt.font.GVTGlyphVector;
+import org.apache.batik.gvt.text.GVTAttributedCharacterIterator;
+import org.apache.batik.gvt.text.GlyphLayout;
+
+import org.apache.fop.fonts.Font;
+import org.apache.fop.svg.font.FOPGVTFont;
+
+public class ComplexGlyphLayout extends GlyphLayout {
+
+ public ComplexGlyphLayout(AttributedCharacterIterator aci,
+ int [] charMap, Point2D offset, FontRenderContext frc) {
+ super(aci, charMap, offset, frc);
+ }
+
+ @Override
+ protected void doExplicitGlyphLayout() {
+ GVTGlyphVector gv = this.gv;
+ gv.performDefaultLayout();
+ int ng = gv.getNumGlyphs();
+ if (ng > 0) {
+ this.advance = gv.getGlyphPosition(ng);
+ } else {
+ this.advance = new Point2D.Float(0, 0);
+ }
+ this.layoutApplied = true;
+ }
+
+ public static final boolean
mayRequireComplexLayout(AttributedCharacterIterator aci) {
+ boolean rv = false;
+ GVTAttributedCharacterIterator.TextAttribute attrFont =
GVTAttributedCharacterIterator.TextAttribute.GVT_FONT;
+ int indexSave = aci.getIndex();
+ aci.first();
+ do {
+ GVTFont gvtFont = (GVTFont) aci.getAttribute(attrFont);
+ if (gvtFont == null) {
+ continue;
+ } else {
+ if (gvtFont instanceof FOPGVTFont) {
+ Font f = ((FOPGVTFont) gvtFont).getFont();
+ if (f.performsSubstitution() || f.performsPositioning()) {
+ rv = true;
+ break;
+ }
+ }
+ aci.setIndex(aci.getRunLimit(attrFont));
+ }
+ } while (aci.next() != AttributedCharacterIterator.DONE);
+ aci.setIndex(indexSave);
+ return rv;
+ }
+
+}
Propchange:
xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/text/ComplexGlyphLayout.java
------------------------------------------------------------------------------
svn:eol-style = LF
Modified:
xmlgraphics/fop/trunk/test/java/org/apache/fop/svg/font/GlyphLayoutTestCase.java
URL:
http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/test/java/org/apache/fop/svg/font/GlyphLayoutTestCase.java?rev=1615385&r1=1615384&r2=1615385&view=diff
==============================================================================
---
xmlgraphics/fop/trunk/test/java/org/apache/fop/svg/font/GlyphLayoutTestCase.java
(original)
+++
xmlgraphics/fop/trunk/test/java/org/apache/fop/svg/font/GlyphLayoutTestCase.java
Sun Aug 3 04:40:34 2014
@@ -50,7 +50,7 @@ public class GlyphLayoutTestCase extends
private void testGlyphLayout(boolean useAdvanced) {
FOPGVTFont font = loadFont(useAdvanced);
- glyphVector = (FOPGVTGlyphVector) font.createGlyphVector(null,
"L\u201DP,V.F,A\u2019LT.");
+ glyphVector = (FOPGVTGlyphVector) font.createGlyphVector(null,
"L\u201DP,V.F,A\u2019LT.", "DFLT", "dflt");
glyphVector.performDefaultLayout();
// Values in font units (unitsPerEm = 2048), glyph width - kern
int[] widths = {
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]