From cfa853d5b2a728fa90c12cd1a44ca1a3eec1a12e Mon Sep 17 00:00:00 2001 From: Simon Pepping Date: Wed, 17 Nov 2010 19:45:27 +0000 Subject: findbugs-reported bug squashing; 959 bugs left (findbugs 1.3.9) git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@1036179 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/render/bitmap/TIFFRenderer.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'src/java/org/apache/fop/render/bitmap') diff --git a/src/java/org/apache/fop/render/bitmap/TIFFRenderer.java b/src/java/org/apache/fop/render/bitmap/TIFFRenderer.java index 7dd3bcd95..5a9cfa21b 100644 --- a/src/java/org/apache/fop/render/bitmap/TIFFRenderer.java +++ b/src/java/org/apache/fop/render/bitmap/TIFFRenderer.java @@ -31,6 +31,7 @@ import java.awt.image.SinglePixelPackedSampleModel; import java.io.IOException; import java.io.OutputStream; import java.util.Iterator; +import java.util.NoSuchElementException; import org.apache.commons.logging.Log; @@ -133,7 +134,11 @@ public class TIFFRenderer extends Java2DRenderer implements TIFFConstants { multiWriter.close(); } } else { - writer.writeImage((RenderedImage) pageImagesItr.next(), outputStream, writerParams); + RenderedImage renderedImage = null; + if (pageImagesItr.hasNext()) { + renderedImage = (RenderedImage) pageImagesItr.next(); + } + writer.writeImage(renderedImage, outputStream, writerParams); if (pageImagesItr.hasNext()) { BitmapRendererEventProducer eventProducer = BitmapRendererEventProducer.Provider.get( @@ -186,8 +191,7 @@ public class TIFFRenderer extends Java2DRenderer implements TIFFConstants { try { pageImage = getPageImage(current++); } catch (FOPException e) { - log.error(e); - return null; + throw new NoSuchElementException(e.getMessage()); } if (COMPRESSION_CCITT_T4.equalsIgnoreCase(writerParams.getCompressionMethod()) -- cgit v1.2.3 From 355eb32c4afbdae66bf0e26c46ca19e4581ef94a Mon Sep 17 00:00:00 2001 From: Peter Hancock Date: Thu, 25 Aug 2011 15:48:26 +0000 Subject: Improved fix for bugzilla#48062 Bug relates to PCL painter thread safetly. Previous fix in rev 895012 worked by synchronizing methods of a static instance of Java2DFontMetrics. This fix uses a unique instance for per thread. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@1161612 13f79535-47bb-0310-9956-ffa450edef68 --- .../render/bitmap/BitmapRendererConfigurator.java | 10 +++---- .../fop/render/java2d/Base14FontCollection.java | 35 +++++++++++----------- .../fop/render/java2d/InstalledFontCollection.java | 15 +++++----- .../fop/render/java2d/Java2DFontMetrics.java | 28 ++++++++--------- .../apache/fop/render/java2d/Java2DRenderer.java | 6 ++-- .../org/apache/fop/render/java2d/Java2DUtil.java | 6 ++-- .../fop/render/java2d/SystemFontMetricsMapper.java | 31 ++++++++++--------- .../fop/render/pcl/PCLRendererConfigurator.java | 9 +++--- status.xml | 5 ++++ 9 files changed, 74 insertions(+), 71 deletions(-) (limited to 'src/java/org/apache/fop/render/bitmap') diff --git a/src/java/org/apache/fop/render/bitmap/BitmapRendererConfigurator.java b/src/java/org/apache/fop/render/bitmap/BitmapRendererConfigurator.java index 1b6c43700..2d78b53c6 100644 --- a/src/java/org/apache/fop/render/bitmap/BitmapRendererConfigurator.java +++ b/src/java/org/apache/fop/render/bitmap/BitmapRendererConfigurator.java @@ -115,13 +115,13 @@ public class BitmapRendererConfigurator extends Java2DRendererConfigurator /** {@inheritDoc} */ public void setupFontInfo(IFDocumentHandler documentHandler, FontInfo fontInfo) throws FOPException { - FontManager fontManager = userAgent.getFactory().getFontManager(); + final FontManager fontManager = userAgent.getFactory().getFontManager(); - Graphics2D graphics2D = Java2DFontMetrics.createFontMetricsGraphics2D(); + final Java2DFontMetrics java2DFontMetrics = new Java2DFontMetrics(); - List fontCollections = new java.util.ArrayList(); - fontCollections.add(new Base14FontCollection(graphics2D)); - fontCollections.add(new InstalledFontCollection(graphics2D)); + final List fontCollections = new java.util.ArrayList(); + fontCollections.add(new Base14FontCollection(java2DFontMetrics)); + fontCollections.add(new InstalledFontCollection(java2DFontMetrics)); Configuration cfg = super.getRendererConfig(documentHandler.getMimeType()); if (cfg != null) { diff --git a/src/java/org/apache/fop/render/java2d/Base14FontCollection.java b/src/java/org/apache/fop/render/java2d/Base14FontCollection.java index 29e80dc2f..578745281 100644 --- a/src/java/org/apache/fop/render/java2d/Base14FontCollection.java +++ b/src/java/org/apache/fop/render/java2d/Base14FontCollection.java @@ -30,14 +30,15 @@ import org.apache.fop.fonts.FontInfo; */ public class Base14FontCollection implements FontCollection { - private Graphics2D graphics2d = null; + /** required when creating new instances of SystemFontMetricsMapper */ + private final Java2DFontMetrics java2DFontMetrics; /** * Main constructor - * @param graphics2d a graphics 2D + * @param java2DFontMetrics required when creating new instances of SystemFontMetricsMapper */ - public Base14FontCollection(Graphics2D graphics2d) { - this.graphics2d = graphics2d; + public Base14FontCollection(Java2DFontMetrics java2DFontMetrics) { + this.java2DFontMetrics = java2DFontMetrics; } /** @@ -56,47 +57,47 @@ public class Base14FontCollection implements FontCollection { final int bolditalic = java.awt.Font.BOLD + java.awt.Font.ITALIC; FontMetricsMapper metric; - metric = new SystemFontMetricsMapper("SansSerif", normal, graphics2d); + metric = new SystemFontMetricsMapper("SansSerif", normal, java2DFontMetrics); // --> goes to F1 fontInfo.addMetrics("F1", metric); - metric = new SystemFontMetricsMapper("SansSerif", italic, graphics2d); + metric = new SystemFontMetricsMapper("SansSerif", italic, java2DFontMetrics); // --> goes to F2 fontInfo.addMetrics("F2", metric); - metric = new SystemFontMetricsMapper("SansSerif", bold, graphics2d); + metric = new SystemFontMetricsMapper("SansSerif", bold, java2DFontMetrics); // --> goes to F3 fontInfo.addMetrics("F3", metric); - metric = new SystemFontMetricsMapper("SansSerif", bolditalic, graphics2d); + metric = new SystemFontMetricsMapper("SansSerif", bolditalic, java2DFontMetrics); // --> goes to F4 fontInfo.addMetrics("F4", metric); - metric = new SystemFontMetricsMapper("Serif", normal, graphics2d); + metric = new SystemFontMetricsMapper("Serif", normal, java2DFontMetrics); // --> goes to F5 fontInfo.addMetrics("F5", metric); - metric = new SystemFontMetricsMapper("Serif", italic, graphics2d); + metric = new SystemFontMetricsMapper("Serif", italic, java2DFontMetrics); // --> goes to F6 fontInfo.addMetrics("F6", metric); - metric = new SystemFontMetricsMapper("Serif", bold, graphics2d); + metric = new SystemFontMetricsMapper("Serif", bold, java2DFontMetrics); // --> goes to F7 fontInfo.addMetrics("F7", metric); - metric = new SystemFontMetricsMapper("Serif", bolditalic, graphics2d); + metric = new SystemFontMetricsMapper("Serif", bolditalic, java2DFontMetrics); // --> goes to F8 fontInfo.addMetrics("F8", metric); - metric = new SystemFontMetricsMapper("MonoSpaced", normal, graphics2d); + metric = new SystemFontMetricsMapper("MonoSpaced", normal, java2DFontMetrics); // --> goes to F9 fontInfo.addMetrics("F9", metric); - metric = new SystemFontMetricsMapper("MonoSpaced", italic, graphics2d); + metric = new SystemFontMetricsMapper("MonoSpaced", italic, java2DFontMetrics); // --> goes to F10 fontInfo.addMetrics("F10", metric); - metric = new SystemFontMetricsMapper("MonoSpaced", bold, graphics2d); + metric = new SystemFontMetricsMapper("MonoSpaced", bold, java2DFontMetrics); // --> goes to F11 fontInfo.addMetrics("F11", metric); - metric = new SystemFontMetricsMapper("MonoSpaced", bolditalic, graphics2d); + metric = new SystemFontMetricsMapper("MonoSpaced", bolditalic, java2DFontMetrics); // --> goes to F12 fontInfo.addMetrics("F12", metric); - metric = new SystemFontMetricsMapper("Serif", normal, graphics2d); + metric = new SystemFontMetricsMapper("Serif", normal, java2DFontMetrics); //"Symbol" doesn't seem to work here, but "Serif" does the job just fine. *shrug* // --> goes to F13 and F14 fontInfo.addMetrics("F13", metric); diff --git a/src/java/org/apache/fop/render/java2d/InstalledFontCollection.java b/src/java/org/apache/fop/render/java2d/InstalledFontCollection.java index fe4e04766..7526c540d 100644 --- a/src/java/org/apache/fop/render/java2d/InstalledFontCollection.java +++ b/src/java/org/apache/fop/render/java2d/InstalledFontCollection.java @@ -57,15 +57,16 @@ public class InstalledFontCollection implements FontCollection { HARDCODED_FONT_NAMES.add("Computer-Modern-Typewriter"); } - private Graphics2D graphics2D = null; + /** Required by new instances of FontMetricsMapper */ + final private Java2DFontMetrics java2DFontMetrics; /** * Main constructor * - * @param graphics2D a graphics 2D + * @param java2DFontMetrics required by new instances of FontMetricsMapper */ - public InstalledFontCollection(Graphics2D graphics2D) { - this.graphics2D = graphics2D; + public InstalledFontCollection(Java2DFontMetrics java2DFontMetrics) { + this.java2DFontMetrics = java2DFontMetrics; } /** @@ -98,7 +99,7 @@ public class InstalledFontCollection implements FontCollection { num++; String fontKey = "F" + num; int style = convertToAWTFontStyle(guessedStyle, guessedWeight); - addFontMetricsMapper(fontInfo, f.getName(), fontKey, graphics2D, style); + addFontMetricsMapper(fontInfo, f.getName(), fontKey, java2DFontMetrics, style); //Register appropriate font triplets matching the font. Two different strategies: //Example: "Arial Bold", normal, normal @@ -120,8 +121,8 @@ public class InstalledFontCollection implements FontCollection { } private static void addFontMetricsMapper(FontInfo fontInfo, String family, String fontKey, - Graphics2D graphics, int style) { - FontMetricsMapper metric = new SystemFontMetricsMapper(family, style, graphics); + Java2DFontMetrics java2DFontMetrics, int style) { + FontMetricsMapper metric = new SystemFontMetricsMapper(family, style, java2DFontMetrics); fontInfo.addMetrics(fontKey, metric); } diff --git a/src/java/org/apache/fop/render/java2d/Java2DFontMetrics.java b/src/java/org/apache/fop/render/java2d/Java2DFontMetrics.java index 544f9c589..fc4af3574 100644 --- a/src/java/org/apache/fop/render/java2d/Java2DFontMetrics.java +++ b/src/java/org/apache/fop/render/java2d/Java2DFontMetrics.java @@ -109,13 +109,13 @@ public class Java2DFontMetrics { /** * Temp graphics object needed to get the font metrics */ - private Graphics2D graphics; + private final Graphics2D graphics; /** * Creates a Graphics2D object for the sole purpose of getting font metrics. * @return a Graphics2D object */ - public static Graphics2D createFontMetricsGraphics2D() { + private static Graphics2D createFontMetricsGraphics2D() { BufferedImage fontImage = new BufferedImage(100, 100, BufferedImage.TYPE_INT_RGB); Graphics2D graphics2D = fontImage.createGraphics(); @@ -127,11 +127,9 @@ public class Java2DFontMetrics { /** * Constructs a new Font-metrics. - * @param graphics a temp graphics object - this is needed so - * that we can get an instance of java.awt.FontMetrics */ - public Java2DFontMetrics(Graphics2D graphics) { - this.graphics = graphics; + public Java2DFontMetrics() { + this.graphics = createFontMetricsGraphics2D(); } /** @@ -142,7 +140,7 @@ public class Java2DFontMetrics { * @param size font size * @return ascent in milliponts */ - public synchronized int getMaxAscent(String family, int style, int size) { + public int getMaxAscent(String family, int style, int size) { setFont(family, style, size); return Math.round(lineMetrics.getAscent() * FONT_FACTOR); } @@ -155,7 +153,7 @@ public class Java2DFontMetrics { * @param size font size * @return ascent in milliponts */ - public synchronized int getAscender(String family, int style, int size) { + public int getAscender(String family, int style, int size) { setFont(family, style, size); return ascender * 1000; @@ -193,7 +191,7 @@ public class Java2DFontMetrics { * @param size font size * @return capital height in millipoints */ - public synchronized int getCapHeight(String family, int style, int size) { + public int getCapHeight(String family, int style, int size) { // currently just gets Ascent value but maybe should use // getMaxAcent() at some stage return getAscender(family, style, size); @@ -207,7 +205,7 @@ public class Java2DFontMetrics { * @param size font size * @return descent in milliponts */ - public synchronized int getDescender(String family, int style, int size) { + public int getDescender(String family, int style, int size) { setFont(family, style, size); return descender * 1000; } @@ -220,7 +218,7 @@ public class Java2DFontMetrics { * @param size font size * @return font height in milliponts */ - public synchronized int getXHeight(String family, int style, int size) { + public int getXHeight(String family, int style, int size) { setFont(family, style, size); return xHeight * 1000; } @@ -234,7 +232,7 @@ public class Java2DFontMetrics { * @param size font size * @return character width in millipoints */ - public synchronized int width(int i, String family, int style, int size) { + public int width(int i, String family, int style, int size) { int w; setFont(family, style, size); w = internalCharWidth(i) * 1000; @@ -256,7 +254,7 @@ public class Java2DFontMetrics { * @param size font size * @return array of character widths in millipoints */ - public synchronized int[] getWidths(String family, int style, int size) { + public int[] getWidths(String family, int style, int size) { int i; if (width == null) { @@ -351,7 +349,7 @@ public class Java2DFontMetrics { * @param size font size * @return font with the desired characeristics. */ - public synchronized java.awt.Font getFont(String family, int style, int size) { + public java.awt.Font getFont(String family, int style, int size) { setFont(family, style, size); return f1; /* @@ -372,7 +370,7 @@ public class Java2DFontMetrics { * @param c the glyph to check * @return true if the character is supported */ - public synchronized boolean hasChar(String family, int style, int size, char c) { + public boolean hasChar(String family, int style, int size, char c) { setFont(family, style, size); return f1.canDisplay(c); } diff --git a/src/java/org/apache/fop/render/java2d/Java2DRenderer.java b/src/java/org/apache/fop/render/java2d/Java2DRenderer.java index 26f98ddd1..766aa081f 100644 --- a/src/java/org/apache/fop/render/java2d/Java2DRenderer.java +++ b/src/java/org/apache/fop/render/java2d/Java2DRenderer.java @@ -171,11 +171,11 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem //Don't call super.setupFontInfo() here! Java2D needs a special font setup // create a temp Image to test font metrics on this.fontInfo = inFontInfo; - Graphics2D graphics2D = Java2DFontMetrics.createFontMetricsGraphics2D(); + final Java2DFontMetrics java2DFontMetrics = new Java2DFontMetrics(); FontCollection[] fontCollections = new FontCollection[] { - new Base14FontCollection(graphics2D), - new InstalledFontCollection(graphics2D), + new Base14FontCollection(java2DFontMetrics), + new InstalledFontCollection(java2DFontMetrics), new ConfiguredFontCollection(getFontResolver(), getFontList()) }; userAgent.getFactory().getFontManager().setup( diff --git a/src/java/org/apache/fop/render/java2d/Java2DUtil.java b/src/java/org/apache/fop/render/java2d/Java2DUtil.java index 7e11ab263..961d64ad2 100644 --- a/src/java/org/apache/fop/render/java2d/Java2DUtil.java +++ b/src/java/org/apache/fop/render/java2d/Java2DUtil.java @@ -44,12 +44,12 @@ public final class Java2DUtil { */ public static FontInfo buildDefaultJava2DBasedFontInfo( FontInfo fontInfo, FOUserAgent userAgent) { - Graphics2D graphics2D = Java2DFontMetrics.createFontMetricsGraphics2D(); + Java2DFontMetrics java2DFontMetrics = new Java2DFontMetrics(); FontManager fontManager = userAgent.getFactory().getFontManager(); FontCollection[] fontCollections = new FontCollection[] { - new org.apache.fop.render.java2d.Base14FontCollection(graphics2D), - new InstalledFontCollection(graphics2D) + new org.apache.fop.render.java2d.Base14FontCollection(java2DFontMetrics), + new InstalledFontCollection(java2DFontMetrics) }; FontInfo fi = (fontInfo != null ? fontInfo : new FontInfo()); diff --git a/src/java/org/apache/fop/render/java2d/SystemFontMetricsMapper.java b/src/java/org/apache/fop/render/java2d/SystemFontMetricsMapper.java index afcf088cc..fac436909 100644 --- a/src/java/org/apache/fop/render/java2d/SystemFontMetricsMapper.java +++ b/src/java/org/apache/fop/render/java2d/SystemFontMetricsMapper.java @@ -42,7 +42,7 @@ public class SystemFontMetricsMapper extends Typeface implements FontMetricsMapp * This is a Java2DFontMetrics that does the real calculation. * It is only one class that dynamically determines the font-size. */ - private static Java2DFontMetrics metric = null; + private final Java2DFontMetrics java2DFontMetrics; /** * The java name of the font. @@ -60,15 +60,14 @@ public class SystemFontMetricsMapper extends Typeface implements FontMetricsMapp * Constructs a new Font-metrics. * @param family the family name of the font (java value) * @param style the java type style value of the font - * @param graphics a Graphics2D object - this is needed so - * that we can get an instance of java.awt.FontMetrics + * @param java2DFontMetrics metric calculations delegated to this */ - public SystemFontMetricsMapper(String family, int style, Graphics2D graphics) { + public SystemFontMetricsMapper(String family, int style, Java2DFontMetrics java2DFontMetrics) { this.family = family; + this.style = style; - if (metric == null) { - metric = new Java2DFontMetrics(graphics); - } + + this.java2DFontMetrics = java2DFontMetrics; } /** {@inheritDoc} */ @@ -104,42 +103,42 @@ public class SystemFontMetricsMapper extends Typeface implements FontMetricsMapp * {@inheritDoc} */ public int getMaxAscent(int size) { - return metric.getMaxAscent(family, style, size); + return java2DFontMetrics.getMaxAscent(family, style, size); } /** * {@inheritDoc} */ public int getAscender(int size) { - return metric.getAscender(family, style, size); + return java2DFontMetrics.getAscender(family, style, size); } /** * {@inheritDoc} */ public int getCapHeight(int size) { - return metric.getCapHeight(family, style, size); + return java2DFontMetrics.getCapHeight(family, style, size); } /** * {@inheritDoc} */ public int getDescender(int size) { - return metric.getDescender(family, style, size); + return java2DFontMetrics.getDescender(family, style, size); } /** * {@inheritDoc} */ public int getXHeight(int size) { - return metric.getXHeight(family, style, size); + return java2DFontMetrics.getXHeight(family, style, size); } /** * {@inheritDoc} */ public int getWidth(int i, int size) { - return metric.width(i, family, style, size); + return java2DFontMetrics.width(i, family, style, size); } @@ -147,14 +146,14 @@ public class SystemFontMetricsMapper extends Typeface implements FontMetricsMapp * {@inheritDoc} */ public int[] getWidths() { - return metric.getWidths(family, style, Java2DFontMetrics.FONT_SIZE); + return java2DFontMetrics.getWidths(family, style, Java2DFontMetrics.FONT_SIZE); } /** * {@inheritDoc} */ public java.awt.Font getFont(int size) { - return metric.getFont(family, style, size); + return java2DFontMetrics.getFont(family, style, size); } /** @@ -183,7 +182,7 @@ public class SystemFontMetricsMapper extends Typeface implements FontMetricsMapp /** {@inheritDoc} */ public boolean hasChar(char c) { - return metric.hasChar(family, style, Java2DFontMetrics.FONT_SIZE, c); + return java2DFontMetrics.hasChar(family, style, Java2DFontMetrics.FONT_SIZE, c); } } diff --git a/src/java/org/apache/fop/render/pcl/PCLRendererConfigurator.java b/src/java/org/apache/fop/render/pcl/PCLRendererConfigurator.java index 339880b64..605220ee2 100644 --- a/src/java/org/apache/fop/render/pcl/PCLRendererConfigurator.java +++ b/src/java/org/apache/fop/render/pcl/PCLRendererConfigurator.java @@ -108,11 +108,10 @@ public class PCLRendererConfigurator extends PrintRendererConfigurator throws FOPException { FontManager fontManager = userAgent.getFactory().getFontManager(); - Graphics2D graphics2D = Java2DFontMetrics.createFontMetricsGraphics2D(); - - List fontCollections = new java.util.ArrayList(); - fontCollections.add(new Base14FontCollection(graphics2D)); - fontCollections.add(new InstalledFontCollection(graphics2D)); + final Java2DFontMetrics java2DFontMetrics = new Java2DFontMetrics(); + final List fontCollections = new java.util.ArrayList(); + fontCollections.add(new Base14FontCollection(java2DFontMetrics)); + fontCollections.add(new InstalledFontCollection(java2DFontMetrics)); Configuration cfg = super.getRendererConfig(documentHandler.getMimeType()); if (cfg != null) { diff --git a/status.xml b/status.xml index 340030f22..e077cdd52 100644 --- a/status.xml +++ b/status.xml @@ -60,6 +60,11 @@ documents. Example: the fix of marks layering will be such a case when it's done. --> + + Improved fix of a bug relating to PCL painter thread safetly. Previous fix in rev 895012 + worked by synchronizing methods of a static instance of Java2DFontMetrics. This fix uses a + unique instance for per thread. + Fixed a bug in AFP where an ArrayOutofBoundsException is throwqn when embedding a Page Segment. -- cgit v1.2.3 From fb20c15fa4aafcc71ddb7288d45d32db118a7d86 Mon Sep 17 00:00:00 2001 From: Mehdi Houshmand Date: Mon, 23 Jan 2012 16:15:23 +0000 Subject: Moved the FOUserAgent into the constructor of the Renderers This breaks the public API but for good reasons: 1) the user-agent is essential for configuring the renderers 2) instantiation of the constructor is always followed by call to "setUserAgent()" (in the examples) 3) simplifies the API and reduces mutability of the Renderers git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@1234877 13f79535-47bb-0310-9956-ffa450edef68 --- .../java/embedding/ExampleFO2JPSPrint.java | 3 +- .../java/embedding/atxml/ExampleConcat.java | 3 +- .../org/apache/fop/cli/CommandLineOptions.java | 7 +-- .../fop/render/AbstractPathOrientedRenderer.java | 5 ++ .../org/apache/fop/render/AbstractRenderer.java | 14 ++--- src/java/org/apache/fop/render/PrintRenderer.java | 5 ++ src/java/org/apache/fop/render/Renderer.java | 7 --- .../org/apache/fop/render/RendererFactory.java | 4 +- .../org/apache/fop/render/awt/AWTRenderer.java | 62 +++++++--------------- .../apache/fop/render/awt/AWTRendererMaker.java | 2 +- .../apache/fop/render/awt/viewer/PreviewPanel.java | 5 +- .../org/apache/fop/render/bitmap/PNGRenderer.java | 5 ++ .../apache/fop/render/bitmap/PNGRendererMaker.java | 2 +- .../org/apache/fop/render/bitmap/TIFFRenderer.java | 12 +---- .../fop/render/bitmap/TIFFRendererMaker.java | 2 +- .../apache/fop/render/intermediate/IFRenderer.java | 6 ++- .../apache/fop/render/java2d/Java2DRenderer.java | 10 ++-- .../apache/fop/render/print/PageableRenderer.java | 15 ++---- .../org/apache/fop/render/print/PrintRenderer.java | 23 ++------ .../fop/render/print/PrintRendererMaker.java | 2 +- .../org/apache/fop/render/txt/TXTRenderer.java | 4 +- .../apache/fop/render/txt/TXTRendererMaker.java | 2 +- .../apache/fop/render/xml/AbstractXMLRenderer.java | 19 ++++--- .../org/apache/fop/render/xml/XMLRenderer.java | 18 ++----- .../apache/fop/render/xml/XMLRendererMaker.java | 2 +- .../org/apache/fop/render/svg/SVGRenderer.java | 11 ++-- .../apache/fop/render/svg/SVGRendererMaker.java | 2 +- .../java/org/apache/fop/URIResolutionTestCase.java | 15 +++--- .../fop/intermediate/AreaTreeParserTestCase.java | 9 ++-- .../fop/layoutengine/LayoutEngineTestCase.java | 6 +-- 30 files changed, 113 insertions(+), 169 deletions(-) (limited to 'src/java/org/apache/fop/render/bitmap') diff --git a/examples/embedding/java/embedding/ExampleFO2JPSPrint.java b/examples/embedding/java/embedding/ExampleFO2JPSPrint.java index 4f18b71ab..1e0ec4853 100644 --- a/examples/embedding/java/embedding/ExampleFO2JPSPrint.java +++ b/examples/embedding/java/embedding/ExampleFO2JPSPrint.java @@ -85,8 +85,7 @@ public class ExampleFO2JPSPrint { //Set up a custom user agent so we can supply our own renderer instance FOUserAgent userAgent = fopFactory.newFOUserAgent(); - PageableRenderer renderer = new PageableRenderer(); - renderer.setUserAgent(userAgent); + PageableRenderer renderer = new PageableRenderer(userAgent); userAgent.setRendererOverride(renderer); // Construct FOP with desired output format diff --git a/examples/embedding/java/embedding/atxml/ExampleConcat.java b/examples/embedding/java/embedding/atxml/ExampleConcat.java index adec1b08c..289f7d074 100644 --- a/examples/embedding/java/embedding/atxml/ExampleConcat.java +++ b/examples/embedding/java/embedding/atxml/ExampleConcat.java @@ -93,8 +93,7 @@ public class ExampleConcat { userAgent, MimeConstants.MIME_PDF); //Create the XMLRenderer to create the area tree XML - XMLRenderer xmlRenderer = new XMLRenderer(); - xmlRenderer.setUserAgent(userAgent); + XMLRenderer xmlRenderer = new XMLRenderer(userAgent); //Tell the XMLRenderer to mimic the target renderer xmlRenderer.mimicRenderer(targetRenderer); diff --git a/src/java/org/apache/fop/cli/CommandLineOptions.java b/src/java/org/apache/fop/cli/CommandLineOptions.java index 0d4c3790c..845c11a0d 100644 --- a/src/java/org/apache/fop/cli/CommandLineOptions.java +++ b/src/java/org/apache/fop/cli/CommandLineOptions.java @@ -203,17 +203,14 @@ public class CommandLineOptions { System.err.println("Couldn't set system look & feel!"); } - AWTRenderer renderer = new AWTRenderer(true); - renderer.setRenderable(inputHandler); //set before user agent! - renderer.setUserAgent(foUserAgent); + AWTRenderer renderer = new AWTRenderer(foUserAgent, inputHandler, true, true); foUserAgent.setRendererOverride(renderer); } else if (MimeConstants.MIME_FOP_AREA_TREE.equals(outputmode) && mimicRenderer != null) { // render from FO to Intermediate Format Renderer targetRenderer = foUserAgent.getRendererFactory().createRenderer( foUserAgent, mimicRenderer); - XMLRenderer xmlRenderer = new XMLRenderer(); - xmlRenderer.setUserAgent(foUserAgent); + XMLRenderer xmlRenderer = new XMLRenderer(foUserAgent); //Tell the XMLRenderer to mimic the target renderer xmlRenderer.mimicRenderer(targetRenderer); diff --git a/src/java/org/apache/fop/render/AbstractPathOrientedRenderer.java b/src/java/org/apache/fop/render/AbstractPathOrientedRenderer.java index 45a02a977..83d3d84a2 100644 --- a/src/java/org/apache/fop/render/AbstractPathOrientedRenderer.java +++ b/src/java/org/apache/fop/render/AbstractPathOrientedRenderer.java @@ -34,6 +34,7 @@ import org.apache.xmlgraphics.image.loader.ImageSize; import org.apache.xmlgraphics.util.QName; import org.apache.xmlgraphics.util.UnitConv; +import org.apache.fop.apps.FOUserAgent; import org.apache.fop.area.Area; import org.apache.fop.area.Block; import org.apache.fop.area.BlockViewport; @@ -56,6 +57,10 @@ import org.apache.fop.traits.BorderProps; */ public abstract class AbstractPathOrientedRenderer extends PrintRenderer { + public AbstractPathOrientedRenderer(FOUserAgent userAgent) { + super(userAgent); + } + /** * Handle block traits. * The block could be any sort of block with any positioning diff --git a/src/java/org/apache/fop/render/AbstractRenderer.java b/src/java/org/apache/fop/render/AbstractRenderer.java index 7ff236d16..659748df9 100644 --- a/src/java/org/apache/fop/render/AbstractRenderer.java +++ b/src/java/org/apache/fop/render/AbstractRenderer.java @@ -61,11 +61,11 @@ import org.apache.fop.area.inline.Image; import org.apache.fop.area.inline.InlineArea; import org.apache.fop.area.inline.InlineBlockParent; import org.apache.fop.area.inline.InlineParent; +import org.apache.fop.area.inline.InlineViewport; import org.apache.fop.area.inline.Leader; import org.apache.fop.area.inline.Space; import org.apache.fop.area.inline.SpaceArea; import org.apache.fop.area.inline.TextArea; -import org.apache.fop.area.inline.InlineViewport; import org.apache.fop.area.inline.WordArea; import org.apache.fop.fo.Constants; import org.apache.fop.fonts.FontInfo; @@ -116,16 +116,16 @@ public abstract class AbstractRenderer /** {@inheritDoc} */ public abstract void setupFontInfo(FontInfo fontInfo) throws FOPException; - /** {@inheritDoc} */ - public void setUserAgent(FOUserAgent agent) { - userAgent = agent; + /** + * + * @param userAgent the user agent that contains configuration details. This cannot be null. + */ + public AbstractRenderer(FOUserAgent userAgent) { + this.userAgent = userAgent; } /** {@inheritDoc} */ public FOUserAgent getUserAgent() { - if (userAgent == null) { - throw new IllegalStateException("FOUserAgent has not been set on Renderer"); - } return userAgent; } diff --git a/src/java/org/apache/fop/render/PrintRenderer.java b/src/java/org/apache/fop/render/PrintRenderer.java index be3ace016..05e9cb7af 100644 --- a/src/java/org/apache/fop/render/PrintRenderer.java +++ b/src/java/org/apache/fop/render/PrintRenderer.java @@ -27,6 +27,7 @@ import java.util.Map; import org.w3c.dom.Document; import org.apache.fop.apps.FOPException; +import org.apache.fop.apps.FOUserAgent; import org.apache.fop.area.Area; import org.apache.fop.area.Trait; import org.apache.fop.fonts.CustomFontCollection; @@ -42,6 +43,10 @@ import org.apache.fop.fonts.base14.Base14FontCollection; /** Abstract base class of "Print" type renderers. */ public abstract class PrintRenderer extends AbstractRenderer { + public PrintRenderer(FOUserAgent userAgent) { + super(userAgent); + } + /** Font configuration */ protected FontInfo fontInfo; diff --git a/src/java/org/apache/fop/render/Renderer.java b/src/java/org/apache/fop/render/Renderer.java index 76f245251..5f5596dfb 100644 --- a/src/java/org/apache/fop/render/Renderer.java +++ b/src/java/org/apache/fop/render/Renderer.java @@ -81,13 +81,6 @@ public interface Renderer { void stopRenderer() throws IOException; - /** - * Set the User Agent. - * - * @param agent The User Agent - */ - void setUserAgent(FOUserAgent agent); - /** * Returns the associated user agent. * @return the user agent diff --git a/src/java/org/apache/fop/render/RendererFactory.java b/src/java/org/apache/fop/render/RendererFactory.java index bc598450f..3ceb27a8e 100644 --- a/src/java/org/apache/fop/render/RendererFactory.java +++ b/src/java/org/apache/fop/render/RendererFactory.java @@ -299,7 +299,6 @@ public class RendererFactory { AbstractRendererMaker maker = getRendererMaker(outputFormat); if (maker != null) { Renderer rend = maker.makeRenderer(userAgent); - rend.setUserAgent(userAgent); RendererConfigurator configurator = maker.getConfigurator(userAgent); if (configurator != null) { configurator.configure(rend); @@ -311,8 +310,7 @@ public class RendererFactory { } private Renderer createRendererForDocumentHandler(IFDocumentHandler documentHandler) { - IFRenderer rend = new IFRenderer(); - rend.setUserAgent(documentHandler.getContext().getUserAgent()); + IFRenderer rend = new IFRenderer(documentHandler.getContext().getUserAgent()); rend.setDocumentHandler(documentHandler); return rend; } diff --git a/src/java/org/apache/fop/render/awt/AWTRenderer.java b/src/java/org/apache/fop/render/awt/AWTRenderer.java index 99dece24a..c36655204 100644 --- a/src/java/org/apache/fop/render/awt/AWTRenderer.java +++ b/src/java/org/apache/fop/render/awt/AWTRenderer.java @@ -64,18 +64,6 @@ public class AWTRenderer extends Java2DRenderer implements Pageable { /** flag for debugging */ public boolean debug; // CSOK: VisibilityModifier - /** If true, preview dialog is shown. */ - public boolean dialogDisplay = true; // CSOK: VisibilityModifier - - /** true if the preview dialog should be the main window of the application */ - private boolean previewAsMainWindow; - - /** - * Renderable instance that can be used to reload and re-render a document after - * modifications. - */ - protected Renderable renderable; - /** * Will be notified when rendering progresses */ @@ -84,47 +72,35 @@ public class AWTRenderer extends Java2DRenderer implements Pageable { /** * Creates a new AWTRenderer instance. + * + * @param userAgent the user agent that contains configuration data */ - public AWTRenderer() { - this(false); + public AWTRenderer(FOUserAgent userAgent) { + this(userAgent, null, false, false); } /** * Creates a new AWTRenderer instance. + * + * @param userAgent the user agent that contains configuration data + * @param renderable a Renderable instance can be set so the Preview Dialog can enable the + * "Reload" button which causes the current document to be reprocessed and redisplayed. * @param previewAsMainWindow true if the preview dialog created by the renderer should be - * the main window of the application. + * the main window of the application. + * @param show sets whether the preview dialog should be created and displayed when the + * rendering has finished. */ - public AWTRenderer(boolean previewAsMainWindow) { - this.previewAsMainWindow = previewAsMainWindow; - } - - /** {@inheritDoc} */ - public void setUserAgent(FOUserAgent foUserAgent) { - super.setUserAgent(foUserAgent); - if (dialogDisplay) { - setStatusListener(PreviewDialog.createPreviewDialog(userAgent, this.renderable, - this.previewAsMainWindow)); + public AWTRenderer(FOUserAgent userAgent, Renderable renderable, boolean previewAsMainWindow, + boolean show) { + super(userAgent); + if (show) { + // MH: Not sure about this??? If show is false, there's no way for this class + // to create a preview dialog... Previously a "setUserAgent" could be called. + setStatusListener(PreviewDialog.createPreviewDialog(userAgent, renderable, + previewAsMainWindow)); } } - /** - * A Renderable instance can be set so the Preview Dialog can enable the "Reload" button - * which causes the current document to be reprocessed and redisplayed. - * @param renderable the Renderable instance. - */ - public void setRenderable(Renderable renderable) { - this.renderable = renderable; - } - - /** - * Sets whether the preview dialog should be created and displayed when - * the rendering is finished. - * @param show If false, preview dialog is not shown. True by default - */ - public void setPreviewDialogDisplayed(boolean show) { - dialogDisplay = show; - } - /** * {@inheritDoc} */ diff --git a/src/java/org/apache/fop/render/awt/AWTRendererMaker.java b/src/java/org/apache/fop/render/awt/AWTRendererMaker.java index 983b42e0c..d65a550d4 100644 --- a/src/java/org/apache/fop/render/awt/AWTRendererMaker.java +++ b/src/java/org/apache/fop/render/awt/AWTRendererMaker.java @@ -34,7 +34,7 @@ public class AWTRendererMaker extends AbstractRendererMaker { /** {@inheritDoc} */ public Renderer makeRenderer(FOUserAgent ua) { - return new AWTRenderer(); + return new AWTRenderer(ua); } /** {@inheritDoc} */ diff --git a/src/java/org/apache/fop/render/awt/viewer/PreviewPanel.java b/src/java/org/apache/fop/render/awt/viewer/PreviewPanel.java index 2303c0e8e..c850c35e7 100644 --- a/src/java/org/apache/fop/render/awt/viewer/PreviewPanel.java +++ b/src/java/org/apache/fop/render/awt/viewer/PreviewPanel.java @@ -67,12 +67,9 @@ import org.apache.fop.render.awt.AWTRenderer; *

*
  * FopFactory fopFactory = FopFactory.newInstance();
- * AWTRenderer renderer = new AWTRenderer();
  * FOUserAgent agent = fopFactory.newFOUserAgent();
+ * AWTRenderer renderer = new AWTRenderer(agent);
  * agent.setRendererOverride(renderer);
- * renderer.setPreviewDialogDisplayed(false);
- * renderer.setUserAgent(agent);
- * renderer.setUserAgent(agent);
  * previewPanel = new PreviewPanel(agent, null, renderer);
  * previewPanel = new PreviewPanel(ua);
  * myGui.add(previewPanel);
diff --git a/src/java/org/apache/fop/render/bitmap/PNGRenderer.java b/src/java/org/apache/fop/render/bitmap/PNGRenderer.java
index 3733bf2f2..1c6f2e33d 100644
--- a/src/java/org/apache/fop/render/bitmap/PNGRenderer.java
+++ b/src/java/org/apache/fop/render/bitmap/PNGRenderer.java
@@ -29,6 +29,7 @@ import org.apache.xmlgraphics.image.writer.ImageWriter;
 import org.apache.xmlgraphics.image.writer.ImageWriterParams;
 import org.apache.xmlgraphics.image.writer.ImageWriterRegistry;
 
+import org.apache.fop.apps.FOUserAgent;
 import org.apache.fop.apps.MimeConstants;
 import org.apache.fop.area.PageViewport;
 import org.apache.fop.render.java2d.Java2DRenderer;
@@ -40,6 +41,10 @@ import org.apache.fop.render.java2d.Java2DRenderer;
  */
 public class PNGRenderer extends Java2DRenderer {
 
+    public PNGRenderer(FOUserAgent userAgent) {
+        super(userAgent);
+    }
+
     /** The MIME type for png-Rendering */
     public static final String MIME_TYPE = MimeConstants.MIME_PNG;
 
diff --git a/src/java/org/apache/fop/render/bitmap/PNGRendererMaker.java b/src/java/org/apache/fop/render/bitmap/PNGRendererMaker.java
index 7d321791a..da19b2986 100644
--- a/src/java/org/apache/fop/render/bitmap/PNGRendererMaker.java
+++ b/src/java/org/apache/fop/render/bitmap/PNGRendererMaker.java
@@ -36,7 +36,7 @@ public class PNGRendererMaker extends AbstractRendererMaker {
 
     /** {@inheritDoc} */
     public Renderer makeRenderer(FOUserAgent ua) {
-        return new PNGRenderer();
+        return new PNGRenderer(ua);
     }
 
     /** {@inheritDoc} */
diff --git a/src/java/org/apache/fop/render/bitmap/TIFFRenderer.java b/src/java/org/apache/fop/render/bitmap/TIFFRenderer.java
index 5a9cfa21b..0e2364d35 100644
--- a/src/java/org/apache/fop/render/bitmap/TIFFRenderer.java
+++ b/src/java/org/apache/fop/render/bitmap/TIFFRenderer.java
@@ -83,19 +83,11 @@ public class TIFFRenderer extends Java2DRenderer implements TIFFConstants {
     }
 
     /** Creates TIFF renderer. */
-    public TIFFRenderer() {
+    public TIFFRenderer(FOUserAgent userAgent) {
+        super(userAgent);
         writerParams = new ImageWriterParams();
         writerParams.setCompressionMethod(COMPRESSION_PACKBITS);
-    }
-
-    /**
-     * {@inheritDoc}
-     *          org.apache.fop.apps.FOUserAgent)
-     */
-    public void setUserAgent(FOUserAgent foUserAgent) {
-        super.setUserAgent(foUserAgent);
 
-        //Set target resolution
         int dpi = Math.round(userAgent.getTargetResolution());
         writerParams.setResolution(dpi);
     }
diff --git a/src/java/org/apache/fop/render/bitmap/TIFFRendererMaker.java b/src/java/org/apache/fop/render/bitmap/TIFFRendererMaker.java
index e3c567995..852e6ba04 100644
--- a/src/java/org/apache/fop/render/bitmap/TIFFRendererMaker.java
+++ b/src/java/org/apache/fop/render/bitmap/TIFFRendererMaker.java
@@ -34,7 +34,7 @@ public class TIFFRendererMaker extends AbstractRendererMaker {
 
     /** {@inheritDoc} */
     public Renderer makeRenderer(FOUserAgent userAgent) {
-        return new TIFFRenderer();
+        return new TIFFRenderer(userAgent);
     }
 
     /** {@inheritDoc} */
diff --git a/src/java/org/apache/fop/render/intermediate/IFRenderer.java b/src/java/org/apache/fop/render/intermediate/IFRenderer.java
index 24a2e8a75..d5d5a154a 100644
--- a/src/java/org/apache/fop/render/intermediate/IFRenderer.java
+++ b/src/java/org/apache/fop/render/intermediate/IFRenderer.java
@@ -51,6 +51,7 @@ import org.apache.xmlgraphics.xmp.schemas.XMPBasicSchema;
 
 import org.apache.fop.Version;
 import org.apache.fop.apps.FOPException;
+import org.apache.fop.apps.FOUserAgent;
 import org.apache.fop.apps.MimeConstants;
 import org.apache.fop.area.Area;
 import org.apache.fop.area.AreaTreeObject;
@@ -70,10 +71,10 @@ import org.apache.fop.area.inline.ForeignObject;
 import org.apache.fop.area.inline.Image;
 import org.apache.fop.area.inline.InlineArea;
 import org.apache.fop.area.inline.InlineParent;
+import org.apache.fop.area.inline.InlineViewport;
 import org.apache.fop.area.inline.Leader;
 import org.apache.fop.area.inline.SpaceArea;
 import org.apache.fop.area.inline.TextArea;
-import org.apache.fop.area.inline.InlineViewport;
 import org.apache.fop.area.inline.WordArea;
 import org.apache.fop.datatypes.URISpecification;
 import org.apache.fop.fo.extensions.ExtensionAttachment;
@@ -158,7 +159,8 @@ public class IFRenderer extends AbstractPathOrientedRenderer {
     /**
      * Main constructor
      */
-    public IFRenderer() {
+    public IFRenderer(FOUserAgent userAgent) {
+        super(userAgent);
     }
 
     /** {@inheritDoc} */
diff --git a/src/java/org/apache/fop/render/java2d/Java2DRenderer.java b/src/java/org/apache/fop/render/java2d/Java2DRenderer.java
index 766aa081f..3c7006588 100644
--- a/src/java/org/apache/fop/render/java2d/Java2DRenderer.java
+++ b/src/java/org/apache/fop/render/java2d/Java2DRenderer.java
@@ -147,15 +147,13 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem
     private GeneralPath currentPath = null;
 
     /** Default constructor */
-    public Java2DRenderer() {
-    }
+    public Java2DRenderer(FOUserAgent userAgent) {
+        super(userAgent);
 
-    /** {@inheritDoc} */
-    public void setUserAgent(FOUserAgent foUserAgent) {
-        super.setUserAgent(foUserAgent);
+        // MH: necessary? the caller has access to FOUserAgent
         userAgent.setRendererOverride(this); // for document regeneration
 
-        String s = (String)userAgent.getRendererOptions().get(JAVA2D_TRANSPARENT_PAGE_BACKGROUND);
+        String s = (String) userAgent.getRendererOptions().get(JAVA2D_TRANSPARENT_PAGE_BACKGROUND);
         if (s != null) {
             this.transparentPageBackground = "true".equalsIgnoreCase(s);
         }
diff --git a/src/java/org/apache/fop/render/print/PageableRenderer.java b/src/java/org/apache/fop/render/print/PageableRenderer.java
index 89ab98071..08d5b0f04 100644
--- a/src/java/org/apache/fop/render/print/PageableRenderer.java
+++ b/src/java/org/apache/fop/render/print/PageableRenderer.java
@@ -73,7 +73,11 @@ public class PageableRenderer extends Java2DRenderer implements Pageable {
     /**
      * Creates a new PageableRenderer.
      */
-    public PageableRenderer() {
+    public PageableRenderer(FOUserAgent userAgent) {
+        super(userAgent);
+        Map rendererOptions = getUserAgent().getRendererOptions();
+        processOptions(rendererOptions);
+        this.pageFilter = new DefaultPageFilter();
     }
 
     /** {@inheritDoc} */
@@ -81,15 +85,6 @@ public class PageableRenderer extends Java2DRenderer implements Pageable {
         return MimeConstants.MIME_FOP_PRINT;
     }
 
-    /** {@inheritDoc} */
-    public void setUserAgent(FOUserAgent agent) {
-        super.setUserAgent(agent);
-
-        Map rendererOptions = agent.getRendererOptions();
-        processOptions(rendererOptions);
-        this.pageFilter = new DefaultPageFilter();
-    }
-
     private void processOptions(Map rendererOptions) {
         Object o = rendererOptions.get(PageableRenderer.PAGES_MODE);
         if (o != null) {
diff --git a/src/java/org/apache/fop/render/print/PrintRenderer.java b/src/java/org/apache/fop/render/print/PrintRenderer.java
index 2eb2b07a2..ea68bc9b2 100644
--- a/src/java/org/apache/fop/render/print/PrintRenderer.java
+++ b/src/java/org/apache/fop/render/print/PrintRenderer.java
@@ -55,19 +55,9 @@ public class PrintRenderer extends PageableRenderer {
      * Creates a new PrintRenderer with the options set through the renderer options if a custom
      * PrinterJob is not given in FOUserAgent's renderer options.
      */
-    public PrintRenderer() {
-    }
-
-    /**
-     * Creates a new PrintRenderer and allows you to pass in a specific PrinterJob instance
-     * that this renderer should work with.
-     * @param printerJob the PrinterJob instance
-     * @deprecated Please use the rendering options on the user agent to pass in the PrinterJob!
-     */
-    public PrintRenderer(PrinterJob printerJob) {
-        this();
-        this.printerJob = printerJob;
-        printerJob.setPageable(this);
+    public PrintRenderer(FOUserAgent userAgent) {
+        super(userAgent);
+        setRendererOptions();
     }
 
     private void initializePrinterJob() {
@@ -85,11 +75,8 @@ public class PrintRenderer extends PageableRenderer {
         }
     }
 
-    /** {@inheritDoc} */
-    public void setUserAgent(FOUserAgent agent) {
-        super.setUserAgent(agent);
-
-        Map rendererOptions = agent.getRendererOptions();
+    private void setRendererOptions() {
+        Map rendererOptions = getUserAgent().getRendererOptions();
 
         Object printerJobO = rendererOptions.get(PrintRenderer.PRINTER_JOB);
         if (printerJobO != null) {
diff --git a/src/java/org/apache/fop/render/print/PrintRendererMaker.java b/src/java/org/apache/fop/render/print/PrintRendererMaker.java
index 21eb4717a..63444a628 100644
--- a/src/java/org/apache/fop/render/print/PrintRendererMaker.java
+++ b/src/java/org/apache/fop/render/print/PrintRendererMaker.java
@@ -35,7 +35,7 @@ public class PrintRendererMaker extends AbstractRendererMaker {
 
     /**{@inheritDoc} */
     public Renderer makeRenderer(FOUserAgent userAgent) {
-        return new PrintRenderer();
+        return new PrintRenderer(userAgent);
     }
 
     /** {@inheritDoc} */
diff --git a/src/java/org/apache/fop/render/txt/TXTRenderer.java b/src/java/org/apache/fop/render/txt/TXTRenderer.java
index 386f95838..74c5b84a8 100644
--- a/src/java/org/apache/fop/render/txt/TXTRenderer.java
+++ b/src/java/org/apache/fop/render/txt/TXTRenderer.java
@@ -32,6 +32,7 @@ import java.util.Map;
 import org.apache.xmlgraphics.util.UnitConv;
 
 import org.apache.fop.apps.FOPException;
+import org.apache.fop.apps.FOUserAgent;
 import org.apache.fop.area.Area;
 import org.apache.fop.area.CTM;
 import org.apache.fop.area.PageViewport;
@@ -110,7 +111,8 @@ public class TXTRenderer extends AbstractPathOrientedRenderer {
     /**
      * Constructs a newly allocated TXTRenderer object.
      */
-    public TXTRenderer() {
+    public TXTRenderer(FOUserAgent userAgent) {
+        super(userAgent);
     }
 
     /** {@inheritDoc} */
diff --git a/src/java/org/apache/fop/render/txt/TXTRendererMaker.java b/src/java/org/apache/fop/render/txt/TXTRendererMaker.java
index 0db369ef2..740866e0c 100644
--- a/src/java/org/apache/fop/render/txt/TXTRendererMaker.java
+++ b/src/java/org/apache/fop/render/txt/TXTRendererMaker.java
@@ -34,7 +34,7 @@ public class TXTRendererMaker extends AbstractRendererMaker {
 
     /**{@inheritDoc} */
     public Renderer makeRenderer(FOUserAgent userAgent) {
-        return new TXTRenderer();
+        return new TXTRenderer(userAgent);
     }
 
     /**{@inheritDoc} */
diff --git a/src/java/org/apache/fop/render/xml/AbstractXMLRenderer.java b/src/java/org/apache/fop/render/xml/AbstractXMLRenderer.java
index 497e3c047..9c938199f 100644
--- a/src/java/org/apache/fop/render/xml/AbstractXMLRenderer.java
+++ b/src/java/org/apache/fop/render/xml/AbstractXMLRenderer.java
@@ -29,6 +29,15 @@ import javax.xml.transform.sax.SAXTransformerFactory;
 import javax.xml.transform.sax.TransformerHandler;
 import javax.xml.transform.stream.StreamResult;
 
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.ext.LexicalHandler;
+import org.xml.sax.helpers.AttributesImpl;
+
+import org.apache.xmlgraphics.util.QName;
+
+import org.apache.fop.apps.FOUserAgent;
 import org.apache.fop.area.BookmarkData;
 import org.apache.fop.area.OffDocumentExtensionAttachment;
 import org.apache.fop.area.OffDocumentItem;
@@ -36,16 +45,14 @@ import org.apache.fop.area.PageViewport;
 import org.apache.fop.fo.extensions.ExtensionAttachment;
 import org.apache.fop.render.PrintRenderer;
 import org.apache.fop.render.RendererContext;
-import org.apache.xmlgraphics.util.QName;
-import org.xml.sax.Attributes;
-import org.xml.sax.ContentHandler;
-import org.xml.sax.SAXException;
-import org.xml.sax.ext.LexicalHandler;
-import org.xml.sax.helpers.AttributesImpl;
 
 /** Abstract xml renderer base class. */
 public abstract class AbstractXMLRenderer extends PrintRenderer {
 
+    public AbstractXMLRenderer(FOUserAgent userAgent) {
+        super(userAgent);
+    }
+
     /** Main namespace in use. */
     public static final String NS = "";
 
diff --git a/src/java/org/apache/fop/render/xml/XMLRenderer.java b/src/java/org/apache/fop/render/xml/XMLRenderer.java
index 21d28042d..3ae49b121 100644
--- a/src/java/org/apache/fop/render/xml/XMLRenderer.java
+++ b/src/java/org/apache/fop/render/xml/XMLRenderer.java
@@ -37,7 +37,6 @@ import javax.xml.transform.stream.StreamResult;
 import org.w3c.dom.Document;
 import org.w3c.dom.Node;
 import org.w3c.dom.NodeList;
-
 import org.xml.sax.SAXException;
 
 import org.apache.xmlgraphics.util.QName;
@@ -75,11 +74,11 @@ import org.apache.fop.area.inline.Image;
 import org.apache.fop.area.inline.InlineArea;
 import org.apache.fop.area.inline.InlineBlockParent;
 import org.apache.fop.area.inline.InlineParent;
+import org.apache.fop.area.inline.InlineViewport;
 import org.apache.fop.area.inline.Leader;
 import org.apache.fop.area.inline.Space;
 import org.apache.fop.area.inline.SpaceArea;
 import org.apache.fop.area.inline.TextArea;
-import org.apache.fop.area.inline.InlineViewport;
 import org.apache.fop.area.inline.WordArea;
 import org.apache.fop.fo.Constants;
 import org.apache.fop.fo.extensions.ExtensionAttachment;
@@ -113,20 +112,9 @@ public class XMLRenderer extends AbstractXMLRenderer {
 
     private int pageSequenceIndex;
 
-    /**
-     * Creates a new XML renderer.
-     */
-    public XMLRenderer() {
+    public XMLRenderer(FOUserAgent userAgent) {
+        super(userAgent);
         context = new RendererContext(this, XML_MIME_TYPE);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public void setUserAgent(FOUserAgent agent) {
-        super.setUserAgent(agent);
-
         XMLHandler xmlHandler = new XMLXMLHandler();
         userAgent.getXMLHandlerRegistry().addXMLHandler(xmlHandler);
         Boolean b = (Boolean)userAgent.getRendererOptions().get("compact-format");
diff --git a/src/java/org/apache/fop/render/xml/XMLRendererMaker.java b/src/java/org/apache/fop/render/xml/XMLRendererMaker.java
index 8526daa2a..f54c74b32 100644
--- a/src/java/org/apache/fop/render/xml/XMLRendererMaker.java
+++ b/src/java/org/apache/fop/render/xml/XMLRendererMaker.java
@@ -35,7 +35,7 @@ public class XMLRendererMaker extends AbstractRendererMaker {
 
     /**{@inheritDoc} */
     public Renderer makeRenderer(FOUserAgent userAgent) {
-        return new XMLRenderer();
+        return new XMLRenderer(userAgent);
     }
 
     /**{@inheritDoc} */
diff --git a/src/sandbox/org/apache/fop/render/svg/SVGRenderer.java b/src/sandbox/org/apache/fop/render/svg/SVGRenderer.java
index 63f486c07..246062a32 100644
--- a/src/sandbox/org/apache/fop/render/svg/SVGRenderer.java
+++ b/src/sandbox/org/apache/fop/render/svg/SVGRenderer.java
@@ -26,19 +26,22 @@ import java.io.IOException;
 import java.io.OutputStream;
 import java.io.Writer;
 
+import org.w3c.dom.DOMImplementation;
+import org.w3c.dom.Document;
+
 import org.apache.batik.dom.GenericDOMImplementation;
 import org.apache.batik.svggen.SVGGeneratorContext;
 import org.apache.batik.svggen.SVGGraphics2D;
 import org.apache.commons.io.IOUtils;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
+
+import org.apache.fop.apps.FOUserAgent;
 import org.apache.fop.apps.MimeConstants;
 import org.apache.fop.area.PageViewport;
 import org.apache.fop.render.bitmap.MultiFileRenderingUtil;
 import org.apache.fop.render.java2d.Java2DGraphicsState;
 import org.apache.fop.render.java2d.Java2DRenderer;
-import org.w3c.dom.DOMImplementation;
-import org.w3c.dom.Document;
 
 /**
  * 

@@ -67,8 +70,8 @@ public class SVGRenderer extends Java2DRenderer { /** Helper class for generating multiple files */ private MultiFileRenderingUtil multiFileUtil; - /** Default constructor. */ - public SVGRenderer() { + public SVGRenderer(FOUserAgent userAgent) { + super(userAgent); } /** {@inheritDoc} */ diff --git a/src/sandbox/org/apache/fop/render/svg/SVGRendererMaker.java b/src/sandbox/org/apache/fop/render/svg/SVGRendererMaker.java index f0da974e6..892d01711 100644 --- a/src/sandbox/org/apache/fop/render/svg/SVGRendererMaker.java +++ b/src/sandbox/org/apache/fop/render/svg/SVGRendererMaker.java @@ -34,7 +34,7 @@ public class SVGRendererMaker extends AbstractRendererMaker { /** {@inheritDoc} */ public Renderer makeRenderer(FOUserAgent ua) { - return new SVGRenderer(); + return new SVGRenderer(ua); } /** {@inheritDoc} */ diff --git a/test/java/org/apache/fop/URIResolutionTestCase.java b/test/java/org/apache/fop/URIResolutionTestCase.java index 97d1c9c25..490486158 100644 --- a/test/java/org/apache/fop/URIResolutionTestCase.java +++ b/test/java/org/apache/fop/URIResolutionTestCase.java @@ -39,19 +39,21 @@ import javax.xml.transform.sax.TransformerHandler; import javax.xml.transform.stream.StreamResult; import javax.xml.transform.stream.StreamSource; +import org.junit.BeforeClass; +import org.junit.Test; +import org.w3c.dom.Document; + import org.apache.commons.io.IOUtils; import org.apache.commons.io.output.ByteArrayOutputStream; +import org.apache.xpath.XPathAPI; +import org.apache.xpath.objects.XObject; + import org.apache.fop.apps.FOPException; import org.apache.fop.apps.FOUserAgent; import org.apache.fop.apps.Fop; import org.apache.fop.apps.FopFactory; import org.apache.fop.apps.MimeConstants; import org.apache.fop.render.xml.XMLRenderer; -import org.apache.xpath.XPathAPI; -import org.apache.xpath.objects.XObject; -import org.junit.BeforeClass; -import org.junit.Test; -import org.w3c.dom.Document; /** * Tests URI resolution facilities. @@ -160,8 +162,7 @@ public class URIResolutionTestCase extends AbstractFOPTest { TransformerHandler athandler = tfactory.newTransformerHandler(); athandler.setResult(domres); - XMLRenderer atrenderer = new XMLRenderer(); - atrenderer.setUserAgent(ua); + XMLRenderer atrenderer = new XMLRenderer(ua); atrenderer.setContentHandler(athandler); ua.setRendererOverride(atrenderer); diff --git a/test/java/org/apache/fop/intermediate/AreaTreeParserTestCase.java b/test/java/org/apache/fop/intermediate/AreaTreeParserTestCase.java index a0de2e8ab..1f8abb9be 100644 --- a/test/java/org/apache/fop/intermediate/AreaTreeParserTestCase.java +++ b/test/java/org/apache/fop/intermediate/AreaTreeParserTestCase.java @@ -97,10 +97,9 @@ public class AreaTreeParserTestCase extends AbstractIntermediateTest { Renderer targetRenderer = userAgent.getRendererFactory().createRenderer( userAgent, getTargetMIME()); - XMLRenderer renderer = new XMLRenderer(); + XMLRenderer renderer = new XMLRenderer(userAgent); renderer.mimicRenderer(targetRenderer); renderer.setContentHandler(handler); - renderer.setUserAgent(userAgent); userAgent.setRendererOverride(renderer); @@ -131,12 +130,10 @@ public class AreaTreeParserTestCase extends AbstractIntermediateTest { TransformerHandler handler = testAssistant.getTransformerFactory().newTransformerHandler(); DOMResult domResult = new DOMResult(); handler.setResult(domResult); - XMLRenderer renderer = new XMLRenderer(); - renderer.setContentHandler(handler); - FOUserAgent userAgent = createUserAgent(); + XMLRenderer renderer = new XMLRenderer(userAgent); userAgent.setRendererOverride(renderer); - renderer.setUserAgent(userAgent); + renderer.setContentHandler(handler); FontInfo fontInfo = new FontInfo(); AreaTreeModel treeModel = new RenderPagesModel(userAgent, diff --git a/test/java/org/apache/fop/layoutengine/LayoutEngineTestCase.java b/test/java/org/apache/fop/layoutengine/LayoutEngineTestCase.java index 46908a448..6a0d424e9 100644 --- a/test/java/org/apache/fop/layoutengine/LayoutEngineTestCase.java +++ b/test/java/org/apache/fop/layoutengine/LayoutEngineTestCase.java @@ -150,8 +150,7 @@ public class LayoutEngineTestCase { ua.getEventBroadcaster().addEventListener( new ConsoleEventListenerForTests(testFile.getName(), EventSeverity.WARN)); - XMLRenderer atrenderer = new XMLRenderer(); - atrenderer.setUserAgent(ua); + XMLRenderer atrenderer = new XMLRenderer(ua); atrenderer.setContentHandler(athandler); ua.setRendererOverride(atrenderer); fop = effFactory.newFop(ua); @@ -208,8 +207,7 @@ public class LayoutEngineTestCase { ua.getEventBroadcaster().addEventListener( new ConsoleEventListenerForTests(testFile.getName(), EventSeverity.WARN)); - IFRenderer ifRenderer = new IFRenderer(); - ifRenderer.setUserAgent(ua); + IFRenderer ifRenderer = new IFRenderer(ua); IFSerializer serializer = new IFSerializer(); serializer.setContext(new IFContext(ua)); -- cgit v1.2.3 From f248634b7fcd300446c25275d89cf7e07f3757c3 Mon Sep 17 00:00:00 2001 From: Mehdi Houshmand Date: Tue, 24 Jan 2012 09:53:32 +0000 Subject: Reverted changes made in r1234877, see bugzilla#52513 git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@1235189 13f79535-47bb-0310-9956-ffa450edef68 --- .../java/embedding/ExampleFO2JPSPrint.java | 3 +- .../java/embedding/atxml/ExampleConcat.java | 3 +- .../org/apache/fop/cli/CommandLineOptions.java | 7 ++- .../fop/render/AbstractPathOrientedRenderer.java | 5 -- .../org/apache/fop/render/AbstractRenderer.java | 14 ++--- src/java/org/apache/fop/render/PrintRenderer.java | 5 -- src/java/org/apache/fop/render/Renderer.java | 7 +++ .../org/apache/fop/render/RendererFactory.java | 4 +- .../org/apache/fop/render/awt/AWTRenderer.java | 62 +++++++++++++++------- .../apache/fop/render/awt/AWTRendererMaker.java | 2 +- .../apache/fop/render/awt/viewer/PreviewPanel.java | 5 +- .../org/apache/fop/render/bitmap/PNGRenderer.java | 5 -- .../apache/fop/render/bitmap/PNGRendererMaker.java | 2 +- .../org/apache/fop/render/bitmap/TIFFRenderer.java | 12 ++++- .../fop/render/bitmap/TIFFRendererMaker.java | 2 +- .../apache/fop/render/intermediate/IFRenderer.java | 6 +-- .../apache/fop/render/java2d/Java2DRenderer.java | 10 ++-- .../apache/fop/render/print/PageableRenderer.java | 15 ++++-- .../org/apache/fop/render/print/PrintRenderer.java | 23 ++++++-- .../fop/render/print/PrintRendererMaker.java | 2 +- .../org/apache/fop/render/txt/TXTRenderer.java | 4 +- .../apache/fop/render/txt/TXTRendererMaker.java | 2 +- .../apache/fop/render/xml/AbstractXMLRenderer.java | 19 +++---- .../org/apache/fop/render/xml/XMLRenderer.java | 18 +++++-- .../apache/fop/render/xml/XMLRendererMaker.java | 2 +- .../org/apache/fop/render/svg/SVGRenderer.java | 11 ++-- .../apache/fop/render/svg/SVGRendererMaker.java | 2 +- .../java/org/apache/fop/URIResolutionTestCase.java | 15 +++--- .../fop/intermediate/AreaTreeParserTestCase.java | 9 ++-- .../fop/layoutengine/LayoutEngineTestCase.java | 6 ++- 30 files changed, 169 insertions(+), 113 deletions(-) (limited to 'src/java/org/apache/fop/render/bitmap') diff --git a/examples/embedding/java/embedding/ExampleFO2JPSPrint.java b/examples/embedding/java/embedding/ExampleFO2JPSPrint.java index 1e0ec4853..4f18b71ab 100644 --- a/examples/embedding/java/embedding/ExampleFO2JPSPrint.java +++ b/examples/embedding/java/embedding/ExampleFO2JPSPrint.java @@ -85,7 +85,8 @@ public class ExampleFO2JPSPrint { //Set up a custom user agent so we can supply our own renderer instance FOUserAgent userAgent = fopFactory.newFOUserAgent(); - PageableRenderer renderer = new PageableRenderer(userAgent); + PageableRenderer renderer = new PageableRenderer(); + renderer.setUserAgent(userAgent); userAgent.setRendererOverride(renderer); // Construct FOP with desired output format diff --git a/examples/embedding/java/embedding/atxml/ExampleConcat.java b/examples/embedding/java/embedding/atxml/ExampleConcat.java index 289f7d074..adec1b08c 100644 --- a/examples/embedding/java/embedding/atxml/ExampleConcat.java +++ b/examples/embedding/java/embedding/atxml/ExampleConcat.java @@ -93,7 +93,8 @@ public class ExampleConcat { userAgent, MimeConstants.MIME_PDF); //Create the XMLRenderer to create the area tree XML - XMLRenderer xmlRenderer = new XMLRenderer(userAgent); + XMLRenderer xmlRenderer = new XMLRenderer(); + xmlRenderer.setUserAgent(userAgent); //Tell the XMLRenderer to mimic the target renderer xmlRenderer.mimicRenderer(targetRenderer); diff --git a/src/java/org/apache/fop/cli/CommandLineOptions.java b/src/java/org/apache/fop/cli/CommandLineOptions.java index 845c11a0d..0d4c3790c 100644 --- a/src/java/org/apache/fop/cli/CommandLineOptions.java +++ b/src/java/org/apache/fop/cli/CommandLineOptions.java @@ -203,14 +203,17 @@ public class CommandLineOptions { System.err.println("Couldn't set system look & feel!"); } - AWTRenderer renderer = new AWTRenderer(foUserAgent, inputHandler, true, true); + AWTRenderer renderer = new AWTRenderer(true); + renderer.setRenderable(inputHandler); //set before user agent! + renderer.setUserAgent(foUserAgent); foUserAgent.setRendererOverride(renderer); } else if (MimeConstants.MIME_FOP_AREA_TREE.equals(outputmode) && mimicRenderer != null) { // render from FO to Intermediate Format Renderer targetRenderer = foUserAgent.getRendererFactory().createRenderer( foUserAgent, mimicRenderer); - XMLRenderer xmlRenderer = new XMLRenderer(foUserAgent); + XMLRenderer xmlRenderer = new XMLRenderer(); + xmlRenderer.setUserAgent(foUserAgent); //Tell the XMLRenderer to mimic the target renderer xmlRenderer.mimicRenderer(targetRenderer); diff --git a/src/java/org/apache/fop/render/AbstractPathOrientedRenderer.java b/src/java/org/apache/fop/render/AbstractPathOrientedRenderer.java index 83d3d84a2..45a02a977 100644 --- a/src/java/org/apache/fop/render/AbstractPathOrientedRenderer.java +++ b/src/java/org/apache/fop/render/AbstractPathOrientedRenderer.java @@ -34,7 +34,6 @@ import org.apache.xmlgraphics.image.loader.ImageSize; import org.apache.xmlgraphics.util.QName; import org.apache.xmlgraphics.util.UnitConv; -import org.apache.fop.apps.FOUserAgent; import org.apache.fop.area.Area; import org.apache.fop.area.Block; import org.apache.fop.area.BlockViewport; @@ -57,10 +56,6 @@ import org.apache.fop.traits.BorderProps; */ public abstract class AbstractPathOrientedRenderer extends PrintRenderer { - public AbstractPathOrientedRenderer(FOUserAgent userAgent) { - super(userAgent); - } - /** * Handle block traits. * The block could be any sort of block with any positioning diff --git a/src/java/org/apache/fop/render/AbstractRenderer.java b/src/java/org/apache/fop/render/AbstractRenderer.java index 659748df9..7ff236d16 100644 --- a/src/java/org/apache/fop/render/AbstractRenderer.java +++ b/src/java/org/apache/fop/render/AbstractRenderer.java @@ -61,11 +61,11 @@ import org.apache.fop.area.inline.Image; import org.apache.fop.area.inline.InlineArea; import org.apache.fop.area.inline.InlineBlockParent; import org.apache.fop.area.inline.InlineParent; -import org.apache.fop.area.inline.InlineViewport; import org.apache.fop.area.inline.Leader; import org.apache.fop.area.inline.Space; import org.apache.fop.area.inline.SpaceArea; import org.apache.fop.area.inline.TextArea; +import org.apache.fop.area.inline.InlineViewport; import org.apache.fop.area.inline.WordArea; import org.apache.fop.fo.Constants; import org.apache.fop.fonts.FontInfo; @@ -116,16 +116,16 @@ public abstract class AbstractRenderer /** {@inheritDoc} */ public abstract void setupFontInfo(FontInfo fontInfo) throws FOPException; - /** - * - * @param userAgent the user agent that contains configuration details. This cannot be null. - */ - public AbstractRenderer(FOUserAgent userAgent) { - this.userAgent = userAgent; + /** {@inheritDoc} */ + public void setUserAgent(FOUserAgent agent) { + userAgent = agent; } /** {@inheritDoc} */ public FOUserAgent getUserAgent() { + if (userAgent == null) { + throw new IllegalStateException("FOUserAgent has not been set on Renderer"); + } return userAgent; } diff --git a/src/java/org/apache/fop/render/PrintRenderer.java b/src/java/org/apache/fop/render/PrintRenderer.java index 05e9cb7af..be3ace016 100644 --- a/src/java/org/apache/fop/render/PrintRenderer.java +++ b/src/java/org/apache/fop/render/PrintRenderer.java @@ -27,7 +27,6 @@ import java.util.Map; import org.w3c.dom.Document; import org.apache.fop.apps.FOPException; -import org.apache.fop.apps.FOUserAgent; import org.apache.fop.area.Area; import org.apache.fop.area.Trait; import org.apache.fop.fonts.CustomFontCollection; @@ -43,10 +42,6 @@ import org.apache.fop.fonts.base14.Base14FontCollection; /** Abstract base class of "Print" type renderers. */ public abstract class PrintRenderer extends AbstractRenderer { - public PrintRenderer(FOUserAgent userAgent) { - super(userAgent); - } - /** Font configuration */ protected FontInfo fontInfo; diff --git a/src/java/org/apache/fop/render/Renderer.java b/src/java/org/apache/fop/render/Renderer.java index 5f5596dfb..76f245251 100644 --- a/src/java/org/apache/fop/render/Renderer.java +++ b/src/java/org/apache/fop/render/Renderer.java @@ -81,6 +81,13 @@ public interface Renderer { void stopRenderer() throws IOException; + /** + * Set the User Agent. + * + * @param agent The User Agent + */ + void setUserAgent(FOUserAgent agent); + /** * Returns the associated user agent. * @return the user agent diff --git a/src/java/org/apache/fop/render/RendererFactory.java b/src/java/org/apache/fop/render/RendererFactory.java index 3ceb27a8e..bc598450f 100644 --- a/src/java/org/apache/fop/render/RendererFactory.java +++ b/src/java/org/apache/fop/render/RendererFactory.java @@ -299,6 +299,7 @@ public class RendererFactory { AbstractRendererMaker maker = getRendererMaker(outputFormat); if (maker != null) { Renderer rend = maker.makeRenderer(userAgent); + rend.setUserAgent(userAgent); RendererConfigurator configurator = maker.getConfigurator(userAgent); if (configurator != null) { configurator.configure(rend); @@ -310,7 +311,8 @@ public class RendererFactory { } private Renderer createRendererForDocumentHandler(IFDocumentHandler documentHandler) { - IFRenderer rend = new IFRenderer(documentHandler.getContext().getUserAgent()); + IFRenderer rend = new IFRenderer(); + rend.setUserAgent(documentHandler.getContext().getUserAgent()); rend.setDocumentHandler(documentHandler); return rend; } diff --git a/src/java/org/apache/fop/render/awt/AWTRenderer.java b/src/java/org/apache/fop/render/awt/AWTRenderer.java index c36655204..99dece24a 100644 --- a/src/java/org/apache/fop/render/awt/AWTRenderer.java +++ b/src/java/org/apache/fop/render/awt/AWTRenderer.java @@ -64,6 +64,18 @@ public class AWTRenderer extends Java2DRenderer implements Pageable { /** flag for debugging */ public boolean debug; // CSOK: VisibilityModifier + /** If true, preview dialog is shown. */ + public boolean dialogDisplay = true; // CSOK: VisibilityModifier + + /** true if the preview dialog should be the main window of the application */ + private boolean previewAsMainWindow; + + /** + * Renderable instance that can be used to reload and re-render a document after + * modifications. + */ + protected Renderable renderable; + /** * Will be notified when rendering progresses */ @@ -72,35 +84,47 @@ public class AWTRenderer extends Java2DRenderer implements Pageable { /** * Creates a new AWTRenderer instance. - * - * @param userAgent the user agent that contains configuration data */ - public AWTRenderer(FOUserAgent userAgent) { - this(userAgent, null, false, false); + public AWTRenderer() { + this(false); } /** * Creates a new AWTRenderer instance. - * - * @param userAgent the user agent that contains configuration data - * @param renderable a Renderable instance can be set so the Preview Dialog can enable the - * "Reload" button which causes the current document to be reprocessed and redisplayed. * @param previewAsMainWindow true if the preview dialog created by the renderer should be - * the main window of the application. - * @param show sets whether the preview dialog should be created and displayed when the - * rendering has finished. + * the main window of the application. */ - public AWTRenderer(FOUserAgent userAgent, Renderable renderable, boolean previewAsMainWindow, - boolean show) { - super(userAgent); - if (show) { - // MH: Not sure about this??? If show is false, there's no way for this class - // to create a preview dialog... Previously a "setUserAgent" could be called. - setStatusListener(PreviewDialog.createPreviewDialog(userAgent, renderable, - previewAsMainWindow)); + public AWTRenderer(boolean previewAsMainWindow) { + this.previewAsMainWindow = previewAsMainWindow; + } + + /** {@inheritDoc} */ + public void setUserAgent(FOUserAgent foUserAgent) { + super.setUserAgent(foUserAgent); + if (dialogDisplay) { + setStatusListener(PreviewDialog.createPreviewDialog(userAgent, this.renderable, + this.previewAsMainWindow)); } } + /** + * A Renderable instance can be set so the Preview Dialog can enable the "Reload" button + * which causes the current document to be reprocessed and redisplayed. + * @param renderable the Renderable instance. + */ + public void setRenderable(Renderable renderable) { + this.renderable = renderable; + } + + /** + * Sets whether the preview dialog should be created and displayed when + * the rendering is finished. + * @param show If false, preview dialog is not shown. True by default + */ + public void setPreviewDialogDisplayed(boolean show) { + dialogDisplay = show; + } + /** * {@inheritDoc} */ diff --git a/src/java/org/apache/fop/render/awt/AWTRendererMaker.java b/src/java/org/apache/fop/render/awt/AWTRendererMaker.java index d65a550d4..983b42e0c 100644 --- a/src/java/org/apache/fop/render/awt/AWTRendererMaker.java +++ b/src/java/org/apache/fop/render/awt/AWTRendererMaker.java @@ -34,7 +34,7 @@ public class AWTRendererMaker extends AbstractRendererMaker { /** {@inheritDoc} */ public Renderer makeRenderer(FOUserAgent ua) { - return new AWTRenderer(ua); + return new AWTRenderer(); } /** {@inheritDoc} */ diff --git a/src/java/org/apache/fop/render/awt/viewer/PreviewPanel.java b/src/java/org/apache/fop/render/awt/viewer/PreviewPanel.java index c850c35e7..2303c0e8e 100644 --- a/src/java/org/apache/fop/render/awt/viewer/PreviewPanel.java +++ b/src/java/org/apache/fop/render/awt/viewer/PreviewPanel.java @@ -67,9 +67,12 @@ import org.apache.fop.render.awt.AWTRenderer; *

*
  * FopFactory fopFactory = FopFactory.newInstance();
+ * AWTRenderer renderer = new AWTRenderer();
  * FOUserAgent agent = fopFactory.newFOUserAgent();
- * AWTRenderer renderer = new AWTRenderer(agent);
  * agent.setRendererOverride(renderer);
+ * renderer.setPreviewDialogDisplayed(false);
+ * renderer.setUserAgent(agent);
+ * renderer.setUserAgent(agent);
  * previewPanel = new PreviewPanel(agent, null, renderer);
  * previewPanel = new PreviewPanel(ua);
  * myGui.add(previewPanel);
diff --git a/src/java/org/apache/fop/render/bitmap/PNGRenderer.java b/src/java/org/apache/fop/render/bitmap/PNGRenderer.java
index 1c6f2e33d..3733bf2f2 100644
--- a/src/java/org/apache/fop/render/bitmap/PNGRenderer.java
+++ b/src/java/org/apache/fop/render/bitmap/PNGRenderer.java
@@ -29,7 +29,6 @@ import org.apache.xmlgraphics.image.writer.ImageWriter;
 import org.apache.xmlgraphics.image.writer.ImageWriterParams;
 import org.apache.xmlgraphics.image.writer.ImageWriterRegistry;
 
-import org.apache.fop.apps.FOUserAgent;
 import org.apache.fop.apps.MimeConstants;
 import org.apache.fop.area.PageViewport;
 import org.apache.fop.render.java2d.Java2DRenderer;
@@ -41,10 +40,6 @@ import org.apache.fop.render.java2d.Java2DRenderer;
  */
 public class PNGRenderer extends Java2DRenderer {
 
-    public PNGRenderer(FOUserAgent userAgent) {
-        super(userAgent);
-    }
-
     /** The MIME type for png-Rendering */
     public static final String MIME_TYPE = MimeConstants.MIME_PNG;
 
diff --git a/src/java/org/apache/fop/render/bitmap/PNGRendererMaker.java b/src/java/org/apache/fop/render/bitmap/PNGRendererMaker.java
index da19b2986..7d321791a 100644
--- a/src/java/org/apache/fop/render/bitmap/PNGRendererMaker.java
+++ b/src/java/org/apache/fop/render/bitmap/PNGRendererMaker.java
@@ -36,7 +36,7 @@ public class PNGRendererMaker extends AbstractRendererMaker {
 
     /** {@inheritDoc} */
     public Renderer makeRenderer(FOUserAgent ua) {
-        return new PNGRenderer(ua);
+        return new PNGRenderer();
     }
 
     /** {@inheritDoc} */
diff --git a/src/java/org/apache/fop/render/bitmap/TIFFRenderer.java b/src/java/org/apache/fop/render/bitmap/TIFFRenderer.java
index 0e2364d35..5a9cfa21b 100644
--- a/src/java/org/apache/fop/render/bitmap/TIFFRenderer.java
+++ b/src/java/org/apache/fop/render/bitmap/TIFFRenderer.java
@@ -83,11 +83,19 @@ public class TIFFRenderer extends Java2DRenderer implements TIFFConstants {
     }
 
     /** Creates TIFF renderer. */
-    public TIFFRenderer(FOUserAgent userAgent) {
-        super(userAgent);
+    public TIFFRenderer() {
         writerParams = new ImageWriterParams();
         writerParams.setCompressionMethod(COMPRESSION_PACKBITS);
+    }
+
+    /**
+     * {@inheritDoc}
+     *          org.apache.fop.apps.FOUserAgent)
+     */
+    public void setUserAgent(FOUserAgent foUserAgent) {
+        super.setUserAgent(foUserAgent);
 
+        //Set target resolution
         int dpi = Math.round(userAgent.getTargetResolution());
         writerParams.setResolution(dpi);
     }
diff --git a/src/java/org/apache/fop/render/bitmap/TIFFRendererMaker.java b/src/java/org/apache/fop/render/bitmap/TIFFRendererMaker.java
index 852e6ba04..e3c567995 100644
--- a/src/java/org/apache/fop/render/bitmap/TIFFRendererMaker.java
+++ b/src/java/org/apache/fop/render/bitmap/TIFFRendererMaker.java
@@ -34,7 +34,7 @@ public class TIFFRendererMaker extends AbstractRendererMaker {
 
     /** {@inheritDoc} */
     public Renderer makeRenderer(FOUserAgent userAgent) {
-        return new TIFFRenderer(userAgent);
+        return new TIFFRenderer();
     }
 
     /** {@inheritDoc} */
diff --git a/src/java/org/apache/fop/render/intermediate/IFRenderer.java b/src/java/org/apache/fop/render/intermediate/IFRenderer.java
index d5d5a154a..24a2e8a75 100644
--- a/src/java/org/apache/fop/render/intermediate/IFRenderer.java
+++ b/src/java/org/apache/fop/render/intermediate/IFRenderer.java
@@ -51,7 +51,6 @@ import org.apache.xmlgraphics.xmp.schemas.XMPBasicSchema;
 
 import org.apache.fop.Version;
 import org.apache.fop.apps.FOPException;
-import org.apache.fop.apps.FOUserAgent;
 import org.apache.fop.apps.MimeConstants;
 import org.apache.fop.area.Area;
 import org.apache.fop.area.AreaTreeObject;
@@ -71,10 +70,10 @@ import org.apache.fop.area.inline.ForeignObject;
 import org.apache.fop.area.inline.Image;
 import org.apache.fop.area.inline.InlineArea;
 import org.apache.fop.area.inline.InlineParent;
-import org.apache.fop.area.inline.InlineViewport;
 import org.apache.fop.area.inline.Leader;
 import org.apache.fop.area.inline.SpaceArea;
 import org.apache.fop.area.inline.TextArea;
+import org.apache.fop.area.inline.InlineViewport;
 import org.apache.fop.area.inline.WordArea;
 import org.apache.fop.datatypes.URISpecification;
 import org.apache.fop.fo.extensions.ExtensionAttachment;
@@ -159,8 +158,7 @@ public class IFRenderer extends AbstractPathOrientedRenderer {
     /**
      * Main constructor
      */
-    public IFRenderer(FOUserAgent userAgent) {
-        super(userAgent);
+    public IFRenderer() {
     }
 
     /** {@inheritDoc} */
diff --git a/src/java/org/apache/fop/render/java2d/Java2DRenderer.java b/src/java/org/apache/fop/render/java2d/Java2DRenderer.java
index 3c7006588..766aa081f 100644
--- a/src/java/org/apache/fop/render/java2d/Java2DRenderer.java
+++ b/src/java/org/apache/fop/render/java2d/Java2DRenderer.java
@@ -147,13 +147,15 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem
     private GeneralPath currentPath = null;
 
     /** Default constructor */
-    public Java2DRenderer(FOUserAgent userAgent) {
-        super(userAgent);
+    public Java2DRenderer() {
+    }
 
-        // MH: necessary? the caller has access to FOUserAgent
+    /** {@inheritDoc} */
+    public void setUserAgent(FOUserAgent foUserAgent) {
+        super.setUserAgent(foUserAgent);
         userAgent.setRendererOverride(this); // for document regeneration
 
-        String s = (String) userAgent.getRendererOptions().get(JAVA2D_TRANSPARENT_PAGE_BACKGROUND);
+        String s = (String)userAgent.getRendererOptions().get(JAVA2D_TRANSPARENT_PAGE_BACKGROUND);
         if (s != null) {
             this.transparentPageBackground = "true".equalsIgnoreCase(s);
         }
diff --git a/src/java/org/apache/fop/render/print/PageableRenderer.java b/src/java/org/apache/fop/render/print/PageableRenderer.java
index 08d5b0f04..89ab98071 100644
--- a/src/java/org/apache/fop/render/print/PageableRenderer.java
+++ b/src/java/org/apache/fop/render/print/PageableRenderer.java
@@ -73,11 +73,7 @@ public class PageableRenderer extends Java2DRenderer implements Pageable {
     /**
      * Creates a new PageableRenderer.
      */
-    public PageableRenderer(FOUserAgent userAgent) {
-        super(userAgent);
-        Map rendererOptions = getUserAgent().getRendererOptions();
-        processOptions(rendererOptions);
-        this.pageFilter = new DefaultPageFilter();
+    public PageableRenderer() {
     }
 
     /** {@inheritDoc} */
@@ -85,6 +81,15 @@ public class PageableRenderer extends Java2DRenderer implements Pageable {
         return MimeConstants.MIME_FOP_PRINT;
     }
 
+    /** {@inheritDoc} */
+    public void setUserAgent(FOUserAgent agent) {
+        super.setUserAgent(agent);
+
+        Map rendererOptions = agent.getRendererOptions();
+        processOptions(rendererOptions);
+        this.pageFilter = new DefaultPageFilter();
+    }
+
     private void processOptions(Map rendererOptions) {
         Object o = rendererOptions.get(PageableRenderer.PAGES_MODE);
         if (o != null) {
diff --git a/src/java/org/apache/fop/render/print/PrintRenderer.java b/src/java/org/apache/fop/render/print/PrintRenderer.java
index ea68bc9b2..2eb2b07a2 100644
--- a/src/java/org/apache/fop/render/print/PrintRenderer.java
+++ b/src/java/org/apache/fop/render/print/PrintRenderer.java
@@ -55,9 +55,19 @@ public class PrintRenderer extends PageableRenderer {
      * Creates a new PrintRenderer with the options set through the renderer options if a custom
      * PrinterJob is not given in FOUserAgent's renderer options.
      */
-    public PrintRenderer(FOUserAgent userAgent) {
-        super(userAgent);
-        setRendererOptions();
+    public PrintRenderer() {
+    }
+
+    /**
+     * Creates a new PrintRenderer and allows you to pass in a specific PrinterJob instance
+     * that this renderer should work with.
+     * @param printerJob the PrinterJob instance
+     * @deprecated Please use the rendering options on the user agent to pass in the PrinterJob!
+     */
+    public PrintRenderer(PrinterJob printerJob) {
+        this();
+        this.printerJob = printerJob;
+        printerJob.setPageable(this);
     }
 
     private void initializePrinterJob() {
@@ -75,8 +85,11 @@ public class PrintRenderer extends PageableRenderer {
         }
     }
 
-    private void setRendererOptions() {
-        Map rendererOptions = getUserAgent().getRendererOptions();
+    /** {@inheritDoc} */
+    public void setUserAgent(FOUserAgent agent) {
+        super.setUserAgent(agent);
+
+        Map rendererOptions = agent.getRendererOptions();
 
         Object printerJobO = rendererOptions.get(PrintRenderer.PRINTER_JOB);
         if (printerJobO != null) {
diff --git a/src/java/org/apache/fop/render/print/PrintRendererMaker.java b/src/java/org/apache/fop/render/print/PrintRendererMaker.java
index 63444a628..21eb4717a 100644
--- a/src/java/org/apache/fop/render/print/PrintRendererMaker.java
+++ b/src/java/org/apache/fop/render/print/PrintRendererMaker.java
@@ -35,7 +35,7 @@ public class PrintRendererMaker extends AbstractRendererMaker {
 
     /**{@inheritDoc} */
     public Renderer makeRenderer(FOUserAgent userAgent) {
-        return new PrintRenderer(userAgent);
+        return new PrintRenderer();
     }
 
     /** {@inheritDoc} */
diff --git a/src/java/org/apache/fop/render/txt/TXTRenderer.java b/src/java/org/apache/fop/render/txt/TXTRenderer.java
index 74c5b84a8..386f95838 100644
--- a/src/java/org/apache/fop/render/txt/TXTRenderer.java
+++ b/src/java/org/apache/fop/render/txt/TXTRenderer.java
@@ -32,7 +32,6 @@ import java.util.Map;
 import org.apache.xmlgraphics.util.UnitConv;
 
 import org.apache.fop.apps.FOPException;
-import org.apache.fop.apps.FOUserAgent;
 import org.apache.fop.area.Area;
 import org.apache.fop.area.CTM;
 import org.apache.fop.area.PageViewport;
@@ -111,8 +110,7 @@ public class TXTRenderer extends AbstractPathOrientedRenderer {
     /**
      * Constructs a newly allocated TXTRenderer object.
      */
-    public TXTRenderer(FOUserAgent userAgent) {
-        super(userAgent);
+    public TXTRenderer() {
     }
 
     /** {@inheritDoc} */
diff --git a/src/java/org/apache/fop/render/txt/TXTRendererMaker.java b/src/java/org/apache/fop/render/txt/TXTRendererMaker.java
index 740866e0c..0db369ef2 100644
--- a/src/java/org/apache/fop/render/txt/TXTRendererMaker.java
+++ b/src/java/org/apache/fop/render/txt/TXTRendererMaker.java
@@ -34,7 +34,7 @@ public class TXTRendererMaker extends AbstractRendererMaker {
 
     /**{@inheritDoc} */
     public Renderer makeRenderer(FOUserAgent userAgent) {
-        return new TXTRenderer(userAgent);
+        return new TXTRenderer();
     }
 
     /**{@inheritDoc} */
diff --git a/src/java/org/apache/fop/render/xml/AbstractXMLRenderer.java b/src/java/org/apache/fop/render/xml/AbstractXMLRenderer.java
index 9c938199f..497e3c047 100644
--- a/src/java/org/apache/fop/render/xml/AbstractXMLRenderer.java
+++ b/src/java/org/apache/fop/render/xml/AbstractXMLRenderer.java
@@ -29,15 +29,6 @@ import javax.xml.transform.sax.SAXTransformerFactory;
 import javax.xml.transform.sax.TransformerHandler;
 import javax.xml.transform.stream.StreamResult;
 
-import org.xml.sax.Attributes;
-import org.xml.sax.ContentHandler;
-import org.xml.sax.SAXException;
-import org.xml.sax.ext.LexicalHandler;
-import org.xml.sax.helpers.AttributesImpl;
-
-import org.apache.xmlgraphics.util.QName;
-
-import org.apache.fop.apps.FOUserAgent;
 import org.apache.fop.area.BookmarkData;
 import org.apache.fop.area.OffDocumentExtensionAttachment;
 import org.apache.fop.area.OffDocumentItem;
@@ -45,14 +36,16 @@ import org.apache.fop.area.PageViewport;
 import org.apache.fop.fo.extensions.ExtensionAttachment;
 import org.apache.fop.render.PrintRenderer;
 import org.apache.fop.render.RendererContext;
+import org.apache.xmlgraphics.util.QName;
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.ext.LexicalHandler;
+import org.xml.sax.helpers.AttributesImpl;
 
 /** Abstract xml renderer base class. */
 public abstract class AbstractXMLRenderer extends PrintRenderer {
 
-    public AbstractXMLRenderer(FOUserAgent userAgent) {
-        super(userAgent);
-    }
-
     /** Main namespace in use. */
     public static final String NS = "";
 
diff --git a/src/java/org/apache/fop/render/xml/XMLRenderer.java b/src/java/org/apache/fop/render/xml/XMLRenderer.java
index 3ae49b121..21d28042d 100644
--- a/src/java/org/apache/fop/render/xml/XMLRenderer.java
+++ b/src/java/org/apache/fop/render/xml/XMLRenderer.java
@@ -37,6 +37,7 @@ import javax.xml.transform.stream.StreamResult;
 import org.w3c.dom.Document;
 import org.w3c.dom.Node;
 import org.w3c.dom.NodeList;
+
 import org.xml.sax.SAXException;
 
 import org.apache.xmlgraphics.util.QName;
@@ -74,11 +75,11 @@ import org.apache.fop.area.inline.Image;
 import org.apache.fop.area.inline.InlineArea;
 import org.apache.fop.area.inline.InlineBlockParent;
 import org.apache.fop.area.inline.InlineParent;
-import org.apache.fop.area.inline.InlineViewport;
 import org.apache.fop.area.inline.Leader;
 import org.apache.fop.area.inline.Space;
 import org.apache.fop.area.inline.SpaceArea;
 import org.apache.fop.area.inline.TextArea;
+import org.apache.fop.area.inline.InlineViewport;
 import org.apache.fop.area.inline.WordArea;
 import org.apache.fop.fo.Constants;
 import org.apache.fop.fo.extensions.ExtensionAttachment;
@@ -112,9 +113,20 @@ public class XMLRenderer extends AbstractXMLRenderer {
 
     private int pageSequenceIndex;
 
-    public XMLRenderer(FOUserAgent userAgent) {
-        super(userAgent);
+    /**
+     * Creates a new XML renderer.
+     */
+    public XMLRenderer() {
         context = new RendererContext(this, XML_MIME_TYPE);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void setUserAgent(FOUserAgent agent) {
+        super.setUserAgent(agent);
+
         XMLHandler xmlHandler = new XMLXMLHandler();
         userAgent.getXMLHandlerRegistry().addXMLHandler(xmlHandler);
         Boolean b = (Boolean)userAgent.getRendererOptions().get("compact-format");
diff --git a/src/java/org/apache/fop/render/xml/XMLRendererMaker.java b/src/java/org/apache/fop/render/xml/XMLRendererMaker.java
index f54c74b32..8526daa2a 100644
--- a/src/java/org/apache/fop/render/xml/XMLRendererMaker.java
+++ b/src/java/org/apache/fop/render/xml/XMLRendererMaker.java
@@ -35,7 +35,7 @@ public class XMLRendererMaker extends AbstractRendererMaker {
 
     /**{@inheritDoc} */
     public Renderer makeRenderer(FOUserAgent userAgent) {
-        return new XMLRenderer(userAgent);
+        return new XMLRenderer();
     }
 
     /**{@inheritDoc} */
diff --git a/src/sandbox/org/apache/fop/render/svg/SVGRenderer.java b/src/sandbox/org/apache/fop/render/svg/SVGRenderer.java
index 246062a32..63f486c07 100644
--- a/src/sandbox/org/apache/fop/render/svg/SVGRenderer.java
+++ b/src/sandbox/org/apache/fop/render/svg/SVGRenderer.java
@@ -26,22 +26,19 @@ import java.io.IOException;
 import java.io.OutputStream;
 import java.io.Writer;
 
-import org.w3c.dom.DOMImplementation;
-import org.w3c.dom.Document;
-
 import org.apache.batik.dom.GenericDOMImplementation;
 import org.apache.batik.svggen.SVGGeneratorContext;
 import org.apache.batik.svggen.SVGGraphics2D;
 import org.apache.commons.io.IOUtils;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
-
-import org.apache.fop.apps.FOUserAgent;
 import org.apache.fop.apps.MimeConstants;
 import org.apache.fop.area.PageViewport;
 import org.apache.fop.render.bitmap.MultiFileRenderingUtil;
 import org.apache.fop.render.java2d.Java2DGraphicsState;
 import org.apache.fop.render.java2d.Java2DRenderer;
+import org.w3c.dom.DOMImplementation;
+import org.w3c.dom.Document;
 
 /**
  * 

@@ -70,8 +67,8 @@ public class SVGRenderer extends Java2DRenderer { /** Helper class for generating multiple files */ private MultiFileRenderingUtil multiFileUtil; - public SVGRenderer(FOUserAgent userAgent) { - super(userAgent); + /** Default constructor. */ + public SVGRenderer() { } /** {@inheritDoc} */ diff --git a/src/sandbox/org/apache/fop/render/svg/SVGRendererMaker.java b/src/sandbox/org/apache/fop/render/svg/SVGRendererMaker.java index 892d01711..f0da974e6 100644 --- a/src/sandbox/org/apache/fop/render/svg/SVGRendererMaker.java +++ b/src/sandbox/org/apache/fop/render/svg/SVGRendererMaker.java @@ -34,7 +34,7 @@ public class SVGRendererMaker extends AbstractRendererMaker { /** {@inheritDoc} */ public Renderer makeRenderer(FOUserAgent ua) { - return new SVGRenderer(ua); + return new SVGRenderer(); } /** {@inheritDoc} */ diff --git a/test/java/org/apache/fop/URIResolutionTestCase.java b/test/java/org/apache/fop/URIResolutionTestCase.java index 490486158..97d1c9c25 100644 --- a/test/java/org/apache/fop/URIResolutionTestCase.java +++ b/test/java/org/apache/fop/URIResolutionTestCase.java @@ -39,21 +39,19 @@ import javax.xml.transform.sax.TransformerHandler; import javax.xml.transform.stream.StreamResult; import javax.xml.transform.stream.StreamSource; -import org.junit.BeforeClass; -import org.junit.Test; -import org.w3c.dom.Document; - import org.apache.commons.io.IOUtils; import org.apache.commons.io.output.ByteArrayOutputStream; -import org.apache.xpath.XPathAPI; -import org.apache.xpath.objects.XObject; - import org.apache.fop.apps.FOPException; import org.apache.fop.apps.FOUserAgent; import org.apache.fop.apps.Fop; import org.apache.fop.apps.FopFactory; import org.apache.fop.apps.MimeConstants; import org.apache.fop.render.xml.XMLRenderer; +import org.apache.xpath.XPathAPI; +import org.apache.xpath.objects.XObject; +import org.junit.BeforeClass; +import org.junit.Test; +import org.w3c.dom.Document; /** * Tests URI resolution facilities. @@ -162,7 +160,8 @@ public class URIResolutionTestCase extends AbstractFOPTest { TransformerHandler athandler = tfactory.newTransformerHandler(); athandler.setResult(domres); - XMLRenderer atrenderer = new XMLRenderer(ua); + XMLRenderer atrenderer = new XMLRenderer(); + atrenderer.setUserAgent(ua); atrenderer.setContentHandler(athandler); ua.setRendererOverride(atrenderer); diff --git a/test/java/org/apache/fop/intermediate/AreaTreeParserTestCase.java b/test/java/org/apache/fop/intermediate/AreaTreeParserTestCase.java index 1f8abb9be..a0de2e8ab 100644 --- a/test/java/org/apache/fop/intermediate/AreaTreeParserTestCase.java +++ b/test/java/org/apache/fop/intermediate/AreaTreeParserTestCase.java @@ -97,9 +97,10 @@ public class AreaTreeParserTestCase extends AbstractIntermediateTest { Renderer targetRenderer = userAgent.getRendererFactory().createRenderer( userAgent, getTargetMIME()); - XMLRenderer renderer = new XMLRenderer(userAgent); + XMLRenderer renderer = new XMLRenderer(); renderer.mimicRenderer(targetRenderer); renderer.setContentHandler(handler); + renderer.setUserAgent(userAgent); userAgent.setRendererOverride(renderer); @@ -130,10 +131,12 @@ public class AreaTreeParserTestCase extends AbstractIntermediateTest { TransformerHandler handler = testAssistant.getTransformerFactory().newTransformerHandler(); DOMResult domResult = new DOMResult(); handler.setResult(domResult); + XMLRenderer renderer = new XMLRenderer(); + renderer.setContentHandler(handler); + FOUserAgent userAgent = createUserAgent(); - XMLRenderer renderer = new XMLRenderer(userAgent); userAgent.setRendererOverride(renderer); - renderer.setContentHandler(handler); + renderer.setUserAgent(userAgent); FontInfo fontInfo = new FontInfo(); AreaTreeModel treeModel = new RenderPagesModel(userAgent, diff --git a/test/java/org/apache/fop/layoutengine/LayoutEngineTestCase.java b/test/java/org/apache/fop/layoutengine/LayoutEngineTestCase.java index 6a0d424e9..46908a448 100644 --- a/test/java/org/apache/fop/layoutengine/LayoutEngineTestCase.java +++ b/test/java/org/apache/fop/layoutengine/LayoutEngineTestCase.java @@ -150,7 +150,8 @@ public class LayoutEngineTestCase { ua.getEventBroadcaster().addEventListener( new ConsoleEventListenerForTests(testFile.getName(), EventSeverity.WARN)); - XMLRenderer atrenderer = new XMLRenderer(ua); + XMLRenderer atrenderer = new XMLRenderer(); + atrenderer.setUserAgent(ua); atrenderer.setContentHandler(athandler); ua.setRendererOverride(atrenderer); fop = effFactory.newFop(ua); @@ -207,7 +208,8 @@ public class LayoutEngineTestCase { ua.getEventBroadcaster().addEventListener( new ConsoleEventListenerForTests(testFile.getName(), EventSeverity.WARN)); - IFRenderer ifRenderer = new IFRenderer(ua); + IFRenderer ifRenderer = new IFRenderer(); + ifRenderer.setUserAgent(ua); IFSerializer serializer = new IFSerializer(); serializer.setContext(new IFContext(ua)); -- cgit v1.2.3 From c5c6ddef0cb6c90ea71e306f63474fd67ed46f6a Mon Sep 17 00:00:00 2001 From: Mehdi Houshmand Date: Mon, 30 Jan 2012 09:49:22 +0000 Subject: Bugzilla#52513: Moved FOUserAgent to the constructor of the Renderers git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@1237582 13f79535-47bb-0310-9956-ffa450edef68 --- .../java/embedding/ExampleFO2JPSPrint.java | 3 +- .../java/embedding/atxml/ExampleConcat.java | 3 +- .../org/apache/fop/cli/CommandLineOptions.java | 7 +-- .../fop/render/AbstractPathOrientedRenderer.java | 5 ++ .../org/apache/fop/render/AbstractRenderer.java | 14 ++--- src/java/org/apache/fop/render/PrintRenderer.java | 5 ++ src/java/org/apache/fop/render/Renderer.java | 7 --- .../org/apache/fop/render/RendererFactory.java | 4 +- .../org/apache/fop/render/awt/AWTRenderer.java | 62 +++++++--------------- .../apache/fop/render/awt/AWTRendererMaker.java | 2 +- .../apache/fop/render/awt/viewer/PreviewPanel.java | 5 +- .../org/apache/fop/render/bitmap/PNGRenderer.java | 5 ++ .../apache/fop/render/bitmap/PNGRendererMaker.java | 2 +- .../org/apache/fop/render/bitmap/TIFFRenderer.java | 12 +---- .../fop/render/bitmap/TIFFRendererMaker.java | 2 +- .../apache/fop/render/intermediate/IFRenderer.java | 6 ++- .../apache/fop/render/java2d/Java2DRenderer.java | 10 ++-- .../apache/fop/render/print/PageableRenderer.java | 15 ++---- .../org/apache/fop/render/print/PrintRenderer.java | 23 ++------ .../fop/render/print/PrintRendererMaker.java | 2 +- .../org/apache/fop/render/txt/TXTRenderer.java | 4 +- .../apache/fop/render/txt/TXTRendererMaker.java | 2 +- .../apache/fop/render/xml/AbstractXMLRenderer.java | 19 ++++--- .../org/apache/fop/render/xml/XMLRenderer.java | 18 ++----- .../apache/fop/render/xml/XMLRendererMaker.java | 2 +- .../org/apache/fop/render/svg/SVGRenderer.java | 11 ++-- .../apache/fop/render/svg/SVGRendererMaker.java | 2 +- .../java/org/apache/fop/URIResolutionTestCase.java | 15 +++--- .../fop/intermediate/AreaTreeParserTestCase.java | 9 ++-- .../fop/layoutengine/LayoutEngineTestCase.java | 6 +-- 30 files changed, 113 insertions(+), 169 deletions(-) (limited to 'src/java/org/apache/fop/render/bitmap') diff --git a/examples/embedding/java/embedding/ExampleFO2JPSPrint.java b/examples/embedding/java/embedding/ExampleFO2JPSPrint.java index 4f18b71ab..1e0ec4853 100644 --- a/examples/embedding/java/embedding/ExampleFO2JPSPrint.java +++ b/examples/embedding/java/embedding/ExampleFO2JPSPrint.java @@ -85,8 +85,7 @@ public class ExampleFO2JPSPrint { //Set up a custom user agent so we can supply our own renderer instance FOUserAgent userAgent = fopFactory.newFOUserAgent(); - PageableRenderer renderer = new PageableRenderer(); - renderer.setUserAgent(userAgent); + PageableRenderer renderer = new PageableRenderer(userAgent); userAgent.setRendererOverride(renderer); // Construct FOP with desired output format diff --git a/examples/embedding/java/embedding/atxml/ExampleConcat.java b/examples/embedding/java/embedding/atxml/ExampleConcat.java index adec1b08c..289f7d074 100644 --- a/examples/embedding/java/embedding/atxml/ExampleConcat.java +++ b/examples/embedding/java/embedding/atxml/ExampleConcat.java @@ -93,8 +93,7 @@ public class ExampleConcat { userAgent, MimeConstants.MIME_PDF); //Create the XMLRenderer to create the area tree XML - XMLRenderer xmlRenderer = new XMLRenderer(); - xmlRenderer.setUserAgent(userAgent); + XMLRenderer xmlRenderer = new XMLRenderer(userAgent); //Tell the XMLRenderer to mimic the target renderer xmlRenderer.mimicRenderer(targetRenderer); diff --git a/src/java/org/apache/fop/cli/CommandLineOptions.java b/src/java/org/apache/fop/cli/CommandLineOptions.java index 0d4c3790c..845c11a0d 100644 --- a/src/java/org/apache/fop/cli/CommandLineOptions.java +++ b/src/java/org/apache/fop/cli/CommandLineOptions.java @@ -203,17 +203,14 @@ public class CommandLineOptions { System.err.println("Couldn't set system look & feel!"); } - AWTRenderer renderer = new AWTRenderer(true); - renderer.setRenderable(inputHandler); //set before user agent! - renderer.setUserAgent(foUserAgent); + AWTRenderer renderer = new AWTRenderer(foUserAgent, inputHandler, true, true); foUserAgent.setRendererOverride(renderer); } else if (MimeConstants.MIME_FOP_AREA_TREE.equals(outputmode) && mimicRenderer != null) { // render from FO to Intermediate Format Renderer targetRenderer = foUserAgent.getRendererFactory().createRenderer( foUserAgent, mimicRenderer); - XMLRenderer xmlRenderer = new XMLRenderer(); - xmlRenderer.setUserAgent(foUserAgent); + XMLRenderer xmlRenderer = new XMLRenderer(foUserAgent); //Tell the XMLRenderer to mimic the target renderer xmlRenderer.mimicRenderer(targetRenderer); diff --git a/src/java/org/apache/fop/render/AbstractPathOrientedRenderer.java b/src/java/org/apache/fop/render/AbstractPathOrientedRenderer.java index 45a02a977..83d3d84a2 100644 --- a/src/java/org/apache/fop/render/AbstractPathOrientedRenderer.java +++ b/src/java/org/apache/fop/render/AbstractPathOrientedRenderer.java @@ -34,6 +34,7 @@ import org.apache.xmlgraphics.image.loader.ImageSize; import org.apache.xmlgraphics.util.QName; import org.apache.xmlgraphics.util.UnitConv; +import org.apache.fop.apps.FOUserAgent; import org.apache.fop.area.Area; import org.apache.fop.area.Block; import org.apache.fop.area.BlockViewport; @@ -56,6 +57,10 @@ import org.apache.fop.traits.BorderProps; */ public abstract class AbstractPathOrientedRenderer extends PrintRenderer { + public AbstractPathOrientedRenderer(FOUserAgent userAgent) { + super(userAgent); + } + /** * Handle block traits. * The block could be any sort of block with any positioning diff --git a/src/java/org/apache/fop/render/AbstractRenderer.java b/src/java/org/apache/fop/render/AbstractRenderer.java index 7ff236d16..659748df9 100644 --- a/src/java/org/apache/fop/render/AbstractRenderer.java +++ b/src/java/org/apache/fop/render/AbstractRenderer.java @@ -61,11 +61,11 @@ import org.apache.fop.area.inline.Image; import org.apache.fop.area.inline.InlineArea; import org.apache.fop.area.inline.InlineBlockParent; import org.apache.fop.area.inline.InlineParent; +import org.apache.fop.area.inline.InlineViewport; import org.apache.fop.area.inline.Leader; import org.apache.fop.area.inline.Space; import org.apache.fop.area.inline.SpaceArea; import org.apache.fop.area.inline.TextArea; -import org.apache.fop.area.inline.InlineViewport; import org.apache.fop.area.inline.WordArea; import org.apache.fop.fo.Constants; import org.apache.fop.fonts.FontInfo; @@ -116,16 +116,16 @@ public abstract class AbstractRenderer /** {@inheritDoc} */ public abstract void setupFontInfo(FontInfo fontInfo) throws FOPException; - /** {@inheritDoc} */ - public void setUserAgent(FOUserAgent agent) { - userAgent = agent; + /** + * + * @param userAgent the user agent that contains configuration details. This cannot be null. + */ + public AbstractRenderer(FOUserAgent userAgent) { + this.userAgent = userAgent; } /** {@inheritDoc} */ public FOUserAgent getUserAgent() { - if (userAgent == null) { - throw new IllegalStateException("FOUserAgent has not been set on Renderer"); - } return userAgent; } diff --git a/src/java/org/apache/fop/render/PrintRenderer.java b/src/java/org/apache/fop/render/PrintRenderer.java index be3ace016..05e9cb7af 100644 --- a/src/java/org/apache/fop/render/PrintRenderer.java +++ b/src/java/org/apache/fop/render/PrintRenderer.java @@ -27,6 +27,7 @@ import java.util.Map; import org.w3c.dom.Document; import org.apache.fop.apps.FOPException; +import org.apache.fop.apps.FOUserAgent; import org.apache.fop.area.Area; import org.apache.fop.area.Trait; import org.apache.fop.fonts.CustomFontCollection; @@ -42,6 +43,10 @@ import org.apache.fop.fonts.base14.Base14FontCollection; /** Abstract base class of "Print" type renderers. */ public abstract class PrintRenderer extends AbstractRenderer { + public PrintRenderer(FOUserAgent userAgent) { + super(userAgent); + } + /** Font configuration */ protected FontInfo fontInfo; diff --git a/src/java/org/apache/fop/render/Renderer.java b/src/java/org/apache/fop/render/Renderer.java index 76f245251..5f5596dfb 100644 --- a/src/java/org/apache/fop/render/Renderer.java +++ b/src/java/org/apache/fop/render/Renderer.java @@ -81,13 +81,6 @@ public interface Renderer { void stopRenderer() throws IOException; - /** - * Set the User Agent. - * - * @param agent The User Agent - */ - void setUserAgent(FOUserAgent agent); - /** * Returns the associated user agent. * @return the user agent diff --git a/src/java/org/apache/fop/render/RendererFactory.java b/src/java/org/apache/fop/render/RendererFactory.java index bc598450f..3ceb27a8e 100644 --- a/src/java/org/apache/fop/render/RendererFactory.java +++ b/src/java/org/apache/fop/render/RendererFactory.java @@ -299,7 +299,6 @@ public class RendererFactory { AbstractRendererMaker maker = getRendererMaker(outputFormat); if (maker != null) { Renderer rend = maker.makeRenderer(userAgent); - rend.setUserAgent(userAgent); RendererConfigurator configurator = maker.getConfigurator(userAgent); if (configurator != null) { configurator.configure(rend); @@ -311,8 +310,7 @@ public class RendererFactory { } private Renderer createRendererForDocumentHandler(IFDocumentHandler documentHandler) { - IFRenderer rend = new IFRenderer(); - rend.setUserAgent(documentHandler.getContext().getUserAgent()); + IFRenderer rend = new IFRenderer(documentHandler.getContext().getUserAgent()); rend.setDocumentHandler(documentHandler); return rend; } diff --git a/src/java/org/apache/fop/render/awt/AWTRenderer.java b/src/java/org/apache/fop/render/awt/AWTRenderer.java index 99dece24a..c36655204 100644 --- a/src/java/org/apache/fop/render/awt/AWTRenderer.java +++ b/src/java/org/apache/fop/render/awt/AWTRenderer.java @@ -64,18 +64,6 @@ public class AWTRenderer extends Java2DRenderer implements Pageable { /** flag for debugging */ public boolean debug; // CSOK: VisibilityModifier - /** If true, preview dialog is shown. */ - public boolean dialogDisplay = true; // CSOK: VisibilityModifier - - /** true if the preview dialog should be the main window of the application */ - private boolean previewAsMainWindow; - - /** - * Renderable instance that can be used to reload and re-render a document after - * modifications. - */ - protected Renderable renderable; - /** * Will be notified when rendering progresses */ @@ -84,47 +72,35 @@ public class AWTRenderer extends Java2DRenderer implements Pageable { /** * Creates a new AWTRenderer instance. + * + * @param userAgent the user agent that contains configuration data */ - public AWTRenderer() { - this(false); + public AWTRenderer(FOUserAgent userAgent) { + this(userAgent, null, false, false); } /** * Creates a new AWTRenderer instance. + * + * @param userAgent the user agent that contains configuration data + * @param renderable a Renderable instance can be set so the Preview Dialog can enable the + * "Reload" button which causes the current document to be reprocessed and redisplayed. * @param previewAsMainWindow true if the preview dialog created by the renderer should be - * the main window of the application. + * the main window of the application. + * @param show sets whether the preview dialog should be created and displayed when the + * rendering has finished. */ - public AWTRenderer(boolean previewAsMainWindow) { - this.previewAsMainWindow = previewAsMainWindow; - } - - /** {@inheritDoc} */ - public void setUserAgent(FOUserAgent foUserAgent) { - super.setUserAgent(foUserAgent); - if (dialogDisplay) { - setStatusListener(PreviewDialog.createPreviewDialog(userAgent, this.renderable, - this.previewAsMainWindow)); + public AWTRenderer(FOUserAgent userAgent, Renderable renderable, boolean previewAsMainWindow, + boolean show) { + super(userAgent); + if (show) { + // MH: Not sure about this??? If show is false, there's no way for this class + // to create a preview dialog... Previously a "setUserAgent" could be called. + setStatusListener(PreviewDialog.createPreviewDialog(userAgent, renderable, + previewAsMainWindow)); } } - /** - * A Renderable instance can be set so the Preview Dialog can enable the "Reload" button - * which causes the current document to be reprocessed and redisplayed. - * @param renderable the Renderable instance. - */ - public void setRenderable(Renderable renderable) { - this.renderable = renderable; - } - - /** - * Sets whether the preview dialog should be created and displayed when - * the rendering is finished. - * @param show If false, preview dialog is not shown. True by default - */ - public void setPreviewDialogDisplayed(boolean show) { - dialogDisplay = show; - } - /** * {@inheritDoc} */ diff --git a/src/java/org/apache/fop/render/awt/AWTRendererMaker.java b/src/java/org/apache/fop/render/awt/AWTRendererMaker.java index 983b42e0c..d65a550d4 100644 --- a/src/java/org/apache/fop/render/awt/AWTRendererMaker.java +++ b/src/java/org/apache/fop/render/awt/AWTRendererMaker.java @@ -34,7 +34,7 @@ public class AWTRendererMaker extends AbstractRendererMaker { /** {@inheritDoc} */ public Renderer makeRenderer(FOUserAgent ua) { - return new AWTRenderer(); + return new AWTRenderer(ua); } /** {@inheritDoc} */ diff --git a/src/java/org/apache/fop/render/awt/viewer/PreviewPanel.java b/src/java/org/apache/fop/render/awt/viewer/PreviewPanel.java index 2303c0e8e..c850c35e7 100644 --- a/src/java/org/apache/fop/render/awt/viewer/PreviewPanel.java +++ b/src/java/org/apache/fop/render/awt/viewer/PreviewPanel.java @@ -67,12 +67,9 @@ import org.apache.fop.render.awt.AWTRenderer; *

*
  * FopFactory fopFactory = FopFactory.newInstance();
- * AWTRenderer renderer = new AWTRenderer();
  * FOUserAgent agent = fopFactory.newFOUserAgent();
+ * AWTRenderer renderer = new AWTRenderer(agent);
  * agent.setRendererOverride(renderer);
- * renderer.setPreviewDialogDisplayed(false);
- * renderer.setUserAgent(agent);
- * renderer.setUserAgent(agent);
  * previewPanel = new PreviewPanel(agent, null, renderer);
  * previewPanel = new PreviewPanel(ua);
  * myGui.add(previewPanel);
diff --git a/src/java/org/apache/fop/render/bitmap/PNGRenderer.java b/src/java/org/apache/fop/render/bitmap/PNGRenderer.java
index 3733bf2f2..1c6f2e33d 100644
--- a/src/java/org/apache/fop/render/bitmap/PNGRenderer.java
+++ b/src/java/org/apache/fop/render/bitmap/PNGRenderer.java
@@ -29,6 +29,7 @@ import org.apache.xmlgraphics.image.writer.ImageWriter;
 import org.apache.xmlgraphics.image.writer.ImageWriterParams;
 import org.apache.xmlgraphics.image.writer.ImageWriterRegistry;
 
+import org.apache.fop.apps.FOUserAgent;
 import org.apache.fop.apps.MimeConstants;
 import org.apache.fop.area.PageViewport;
 import org.apache.fop.render.java2d.Java2DRenderer;
@@ -40,6 +41,10 @@ import org.apache.fop.render.java2d.Java2DRenderer;
  */
 public class PNGRenderer extends Java2DRenderer {
 
+    public PNGRenderer(FOUserAgent userAgent) {
+        super(userAgent);
+    }
+
     /** The MIME type for png-Rendering */
     public static final String MIME_TYPE = MimeConstants.MIME_PNG;
 
diff --git a/src/java/org/apache/fop/render/bitmap/PNGRendererMaker.java b/src/java/org/apache/fop/render/bitmap/PNGRendererMaker.java
index 7d321791a..da19b2986 100644
--- a/src/java/org/apache/fop/render/bitmap/PNGRendererMaker.java
+++ b/src/java/org/apache/fop/render/bitmap/PNGRendererMaker.java
@@ -36,7 +36,7 @@ public class PNGRendererMaker extends AbstractRendererMaker {
 
     /** {@inheritDoc} */
     public Renderer makeRenderer(FOUserAgent ua) {
-        return new PNGRenderer();
+        return new PNGRenderer(ua);
     }
 
     /** {@inheritDoc} */
diff --git a/src/java/org/apache/fop/render/bitmap/TIFFRenderer.java b/src/java/org/apache/fop/render/bitmap/TIFFRenderer.java
index 5a9cfa21b..0e2364d35 100644
--- a/src/java/org/apache/fop/render/bitmap/TIFFRenderer.java
+++ b/src/java/org/apache/fop/render/bitmap/TIFFRenderer.java
@@ -83,19 +83,11 @@ public class TIFFRenderer extends Java2DRenderer implements TIFFConstants {
     }
 
     /** Creates TIFF renderer. */
-    public TIFFRenderer() {
+    public TIFFRenderer(FOUserAgent userAgent) {
+        super(userAgent);
         writerParams = new ImageWriterParams();
         writerParams.setCompressionMethod(COMPRESSION_PACKBITS);
-    }
-
-    /**
-     * {@inheritDoc}
-     *          org.apache.fop.apps.FOUserAgent)
-     */
-    public void setUserAgent(FOUserAgent foUserAgent) {
-        super.setUserAgent(foUserAgent);
 
-        //Set target resolution
         int dpi = Math.round(userAgent.getTargetResolution());
         writerParams.setResolution(dpi);
     }
diff --git a/src/java/org/apache/fop/render/bitmap/TIFFRendererMaker.java b/src/java/org/apache/fop/render/bitmap/TIFFRendererMaker.java
index e3c567995..852e6ba04 100644
--- a/src/java/org/apache/fop/render/bitmap/TIFFRendererMaker.java
+++ b/src/java/org/apache/fop/render/bitmap/TIFFRendererMaker.java
@@ -34,7 +34,7 @@ public class TIFFRendererMaker extends AbstractRendererMaker {
 
     /** {@inheritDoc} */
     public Renderer makeRenderer(FOUserAgent userAgent) {
-        return new TIFFRenderer();
+        return new TIFFRenderer(userAgent);
     }
 
     /** {@inheritDoc} */
diff --git a/src/java/org/apache/fop/render/intermediate/IFRenderer.java b/src/java/org/apache/fop/render/intermediate/IFRenderer.java
index 24a2e8a75..d5d5a154a 100644
--- a/src/java/org/apache/fop/render/intermediate/IFRenderer.java
+++ b/src/java/org/apache/fop/render/intermediate/IFRenderer.java
@@ -51,6 +51,7 @@ import org.apache.xmlgraphics.xmp.schemas.XMPBasicSchema;
 
 import org.apache.fop.Version;
 import org.apache.fop.apps.FOPException;
+import org.apache.fop.apps.FOUserAgent;
 import org.apache.fop.apps.MimeConstants;
 import org.apache.fop.area.Area;
 import org.apache.fop.area.AreaTreeObject;
@@ -70,10 +71,10 @@ import org.apache.fop.area.inline.ForeignObject;
 import org.apache.fop.area.inline.Image;
 import org.apache.fop.area.inline.InlineArea;
 import org.apache.fop.area.inline.InlineParent;
+import org.apache.fop.area.inline.InlineViewport;
 import org.apache.fop.area.inline.Leader;
 import org.apache.fop.area.inline.SpaceArea;
 import org.apache.fop.area.inline.TextArea;
-import org.apache.fop.area.inline.InlineViewport;
 import org.apache.fop.area.inline.WordArea;
 import org.apache.fop.datatypes.URISpecification;
 import org.apache.fop.fo.extensions.ExtensionAttachment;
@@ -158,7 +159,8 @@ public class IFRenderer extends AbstractPathOrientedRenderer {
     /**
      * Main constructor
      */
-    public IFRenderer() {
+    public IFRenderer(FOUserAgent userAgent) {
+        super(userAgent);
     }
 
     /** {@inheritDoc} */
diff --git a/src/java/org/apache/fop/render/java2d/Java2DRenderer.java b/src/java/org/apache/fop/render/java2d/Java2DRenderer.java
index 766aa081f..3c7006588 100644
--- a/src/java/org/apache/fop/render/java2d/Java2DRenderer.java
+++ b/src/java/org/apache/fop/render/java2d/Java2DRenderer.java
@@ -147,15 +147,13 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem
     private GeneralPath currentPath = null;
 
     /** Default constructor */
-    public Java2DRenderer() {
-    }
+    public Java2DRenderer(FOUserAgent userAgent) {
+        super(userAgent);
 
-    /** {@inheritDoc} */
-    public void setUserAgent(FOUserAgent foUserAgent) {
-        super.setUserAgent(foUserAgent);
+        // MH: necessary? the caller has access to FOUserAgent
         userAgent.setRendererOverride(this); // for document regeneration
 
-        String s = (String)userAgent.getRendererOptions().get(JAVA2D_TRANSPARENT_PAGE_BACKGROUND);
+        String s = (String) userAgent.getRendererOptions().get(JAVA2D_TRANSPARENT_PAGE_BACKGROUND);
         if (s != null) {
             this.transparentPageBackground = "true".equalsIgnoreCase(s);
         }
diff --git a/src/java/org/apache/fop/render/print/PageableRenderer.java b/src/java/org/apache/fop/render/print/PageableRenderer.java
index 89ab98071..08d5b0f04 100644
--- a/src/java/org/apache/fop/render/print/PageableRenderer.java
+++ b/src/java/org/apache/fop/render/print/PageableRenderer.java
@@ -73,7 +73,11 @@ public class PageableRenderer extends Java2DRenderer implements Pageable {
     /**
      * Creates a new PageableRenderer.
      */
-    public PageableRenderer() {
+    public PageableRenderer(FOUserAgent userAgent) {
+        super(userAgent);
+        Map rendererOptions = getUserAgent().getRendererOptions();
+        processOptions(rendererOptions);
+        this.pageFilter = new DefaultPageFilter();
     }
 
     /** {@inheritDoc} */
@@ -81,15 +85,6 @@ public class PageableRenderer extends Java2DRenderer implements Pageable {
         return MimeConstants.MIME_FOP_PRINT;
     }
 
-    /** {@inheritDoc} */
-    public void setUserAgent(FOUserAgent agent) {
-        super.setUserAgent(agent);
-
-        Map rendererOptions = agent.getRendererOptions();
-        processOptions(rendererOptions);
-        this.pageFilter = new DefaultPageFilter();
-    }
-
     private void processOptions(Map rendererOptions) {
         Object o = rendererOptions.get(PageableRenderer.PAGES_MODE);
         if (o != null) {
diff --git a/src/java/org/apache/fop/render/print/PrintRenderer.java b/src/java/org/apache/fop/render/print/PrintRenderer.java
index 2eb2b07a2..ea68bc9b2 100644
--- a/src/java/org/apache/fop/render/print/PrintRenderer.java
+++ b/src/java/org/apache/fop/render/print/PrintRenderer.java
@@ -55,19 +55,9 @@ public class PrintRenderer extends PageableRenderer {
      * Creates a new PrintRenderer with the options set through the renderer options if a custom
      * PrinterJob is not given in FOUserAgent's renderer options.
      */
-    public PrintRenderer() {
-    }
-
-    /**
-     * Creates a new PrintRenderer and allows you to pass in a specific PrinterJob instance
-     * that this renderer should work with.
-     * @param printerJob the PrinterJob instance
-     * @deprecated Please use the rendering options on the user agent to pass in the PrinterJob!
-     */
-    public PrintRenderer(PrinterJob printerJob) {
-        this();
-        this.printerJob = printerJob;
-        printerJob.setPageable(this);
+    public PrintRenderer(FOUserAgent userAgent) {
+        super(userAgent);
+        setRendererOptions();
     }
 
     private void initializePrinterJob() {
@@ -85,11 +75,8 @@ public class PrintRenderer extends PageableRenderer {
         }
     }
 
-    /** {@inheritDoc} */
-    public void setUserAgent(FOUserAgent agent) {
-        super.setUserAgent(agent);
-
-        Map rendererOptions = agent.getRendererOptions();
+    private void setRendererOptions() {
+        Map rendererOptions = getUserAgent().getRendererOptions();
 
         Object printerJobO = rendererOptions.get(PrintRenderer.PRINTER_JOB);
         if (printerJobO != null) {
diff --git a/src/java/org/apache/fop/render/print/PrintRendererMaker.java b/src/java/org/apache/fop/render/print/PrintRendererMaker.java
index 21eb4717a..63444a628 100644
--- a/src/java/org/apache/fop/render/print/PrintRendererMaker.java
+++ b/src/java/org/apache/fop/render/print/PrintRendererMaker.java
@@ -35,7 +35,7 @@ public class PrintRendererMaker extends AbstractRendererMaker {
 
     /**{@inheritDoc} */
     public Renderer makeRenderer(FOUserAgent userAgent) {
-        return new PrintRenderer();
+        return new PrintRenderer(userAgent);
     }
 
     /** {@inheritDoc} */
diff --git a/src/java/org/apache/fop/render/txt/TXTRenderer.java b/src/java/org/apache/fop/render/txt/TXTRenderer.java
index 386f95838..74c5b84a8 100644
--- a/src/java/org/apache/fop/render/txt/TXTRenderer.java
+++ b/src/java/org/apache/fop/render/txt/TXTRenderer.java
@@ -32,6 +32,7 @@ import java.util.Map;
 import org.apache.xmlgraphics.util.UnitConv;
 
 import org.apache.fop.apps.FOPException;
+import org.apache.fop.apps.FOUserAgent;
 import org.apache.fop.area.Area;
 import org.apache.fop.area.CTM;
 import org.apache.fop.area.PageViewport;
@@ -110,7 +111,8 @@ public class TXTRenderer extends AbstractPathOrientedRenderer {
     /**
      * Constructs a newly allocated TXTRenderer object.
      */
-    public TXTRenderer() {
+    public TXTRenderer(FOUserAgent userAgent) {
+        super(userAgent);
     }
 
     /** {@inheritDoc} */
diff --git a/src/java/org/apache/fop/render/txt/TXTRendererMaker.java b/src/java/org/apache/fop/render/txt/TXTRendererMaker.java
index 0db369ef2..740866e0c 100644
--- a/src/java/org/apache/fop/render/txt/TXTRendererMaker.java
+++ b/src/java/org/apache/fop/render/txt/TXTRendererMaker.java
@@ -34,7 +34,7 @@ public class TXTRendererMaker extends AbstractRendererMaker {
 
     /**{@inheritDoc} */
     public Renderer makeRenderer(FOUserAgent userAgent) {
-        return new TXTRenderer();
+        return new TXTRenderer(userAgent);
     }
 
     /**{@inheritDoc} */
diff --git a/src/java/org/apache/fop/render/xml/AbstractXMLRenderer.java b/src/java/org/apache/fop/render/xml/AbstractXMLRenderer.java
index 497e3c047..9c938199f 100644
--- a/src/java/org/apache/fop/render/xml/AbstractXMLRenderer.java
+++ b/src/java/org/apache/fop/render/xml/AbstractXMLRenderer.java
@@ -29,6 +29,15 @@ import javax.xml.transform.sax.SAXTransformerFactory;
 import javax.xml.transform.sax.TransformerHandler;
 import javax.xml.transform.stream.StreamResult;
 
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.ext.LexicalHandler;
+import org.xml.sax.helpers.AttributesImpl;
+
+import org.apache.xmlgraphics.util.QName;
+
+import org.apache.fop.apps.FOUserAgent;
 import org.apache.fop.area.BookmarkData;
 import org.apache.fop.area.OffDocumentExtensionAttachment;
 import org.apache.fop.area.OffDocumentItem;
@@ -36,16 +45,14 @@ import org.apache.fop.area.PageViewport;
 import org.apache.fop.fo.extensions.ExtensionAttachment;
 import org.apache.fop.render.PrintRenderer;
 import org.apache.fop.render.RendererContext;
-import org.apache.xmlgraphics.util.QName;
-import org.xml.sax.Attributes;
-import org.xml.sax.ContentHandler;
-import org.xml.sax.SAXException;
-import org.xml.sax.ext.LexicalHandler;
-import org.xml.sax.helpers.AttributesImpl;
 
 /** Abstract xml renderer base class. */
 public abstract class AbstractXMLRenderer extends PrintRenderer {
 
+    public AbstractXMLRenderer(FOUserAgent userAgent) {
+        super(userAgent);
+    }
+
     /** Main namespace in use. */
     public static final String NS = "";
 
diff --git a/src/java/org/apache/fop/render/xml/XMLRenderer.java b/src/java/org/apache/fop/render/xml/XMLRenderer.java
index 21d28042d..3ae49b121 100644
--- a/src/java/org/apache/fop/render/xml/XMLRenderer.java
+++ b/src/java/org/apache/fop/render/xml/XMLRenderer.java
@@ -37,7 +37,6 @@ import javax.xml.transform.stream.StreamResult;
 import org.w3c.dom.Document;
 import org.w3c.dom.Node;
 import org.w3c.dom.NodeList;
-
 import org.xml.sax.SAXException;
 
 import org.apache.xmlgraphics.util.QName;
@@ -75,11 +74,11 @@ import org.apache.fop.area.inline.Image;
 import org.apache.fop.area.inline.InlineArea;
 import org.apache.fop.area.inline.InlineBlockParent;
 import org.apache.fop.area.inline.InlineParent;
+import org.apache.fop.area.inline.InlineViewport;
 import org.apache.fop.area.inline.Leader;
 import org.apache.fop.area.inline.Space;
 import org.apache.fop.area.inline.SpaceArea;
 import org.apache.fop.area.inline.TextArea;
-import org.apache.fop.area.inline.InlineViewport;
 import org.apache.fop.area.inline.WordArea;
 import org.apache.fop.fo.Constants;
 import org.apache.fop.fo.extensions.ExtensionAttachment;
@@ -113,20 +112,9 @@ public class XMLRenderer extends AbstractXMLRenderer {
 
     private int pageSequenceIndex;
 
-    /**
-     * Creates a new XML renderer.
-     */
-    public XMLRenderer() {
+    public XMLRenderer(FOUserAgent userAgent) {
+        super(userAgent);
         context = new RendererContext(this, XML_MIME_TYPE);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public void setUserAgent(FOUserAgent agent) {
-        super.setUserAgent(agent);
-
         XMLHandler xmlHandler = new XMLXMLHandler();
         userAgent.getXMLHandlerRegistry().addXMLHandler(xmlHandler);
         Boolean b = (Boolean)userAgent.getRendererOptions().get("compact-format");
diff --git a/src/java/org/apache/fop/render/xml/XMLRendererMaker.java b/src/java/org/apache/fop/render/xml/XMLRendererMaker.java
index 8526daa2a..f54c74b32 100644
--- a/src/java/org/apache/fop/render/xml/XMLRendererMaker.java
+++ b/src/java/org/apache/fop/render/xml/XMLRendererMaker.java
@@ -35,7 +35,7 @@ public class XMLRendererMaker extends AbstractRendererMaker {
 
     /**{@inheritDoc} */
     public Renderer makeRenderer(FOUserAgent userAgent) {
-        return new XMLRenderer();
+        return new XMLRenderer(userAgent);
     }
 
     /**{@inheritDoc} */
diff --git a/src/sandbox/org/apache/fop/render/svg/SVGRenderer.java b/src/sandbox/org/apache/fop/render/svg/SVGRenderer.java
index 63f486c07..246062a32 100644
--- a/src/sandbox/org/apache/fop/render/svg/SVGRenderer.java
+++ b/src/sandbox/org/apache/fop/render/svg/SVGRenderer.java
@@ -26,19 +26,22 @@ import java.io.IOException;
 import java.io.OutputStream;
 import java.io.Writer;
 
+import org.w3c.dom.DOMImplementation;
+import org.w3c.dom.Document;
+
 import org.apache.batik.dom.GenericDOMImplementation;
 import org.apache.batik.svggen.SVGGeneratorContext;
 import org.apache.batik.svggen.SVGGraphics2D;
 import org.apache.commons.io.IOUtils;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
+
+import org.apache.fop.apps.FOUserAgent;
 import org.apache.fop.apps.MimeConstants;
 import org.apache.fop.area.PageViewport;
 import org.apache.fop.render.bitmap.MultiFileRenderingUtil;
 import org.apache.fop.render.java2d.Java2DGraphicsState;
 import org.apache.fop.render.java2d.Java2DRenderer;
-import org.w3c.dom.DOMImplementation;
-import org.w3c.dom.Document;
 
 /**
  * 

@@ -67,8 +70,8 @@ public class SVGRenderer extends Java2DRenderer { /** Helper class for generating multiple files */ private MultiFileRenderingUtil multiFileUtil; - /** Default constructor. */ - public SVGRenderer() { + public SVGRenderer(FOUserAgent userAgent) { + super(userAgent); } /** {@inheritDoc} */ diff --git a/src/sandbox/org/apache/fop/render/svg/SVGRendererMaker.java b/src/sandbox/org/apache/fop/render/svg/SVGRendererMaker.java index f0da974e6..892d01711 100644 --- a/src/sandbox/org/apache/fop/render/svg/SVGRendererMaker.java +++ b/src/sandbox/org/apache/fop/render/svg/SVGRendererMaker.java @@ -34,7 +34,7 @@ public class SVGRendererMaker extends AbstractRendererMaker { /** {@inheritDoc} */ public Renderer makeRenderer(FOUserAgent ua) { - return new SVGRenderer(); + return new SVGRenderer(ua); } /** {@inheritDoc} */ diff --git a/test/java/org/apache/fop/URIResolutionTestCase.java b/test/java/org/apache/fop/URIResolutionTestCase.java index 97d1c9c25..490486158 100644 --- a/test/java/org/apache/fop/URIResolutionTestCase.java +++ b/test/java/org/apache/fop/URIResolutionTestCase.java @@ -39,19 +39,21 @@ import javax.xml.transform.sax.TransformerHandler; import javax.xml.transform.stream.StreamResult; import javax.xml.transform.stream.StreamSource; +import org.junit.BeforeClass; +import org.junit.Test; +import org.w3c.dom.Document; + import org.apache.commons.io.IOUtils; import org.apache.commons.io.output.ByteArrayOutputStream; +import org.apache.xpath.XPathAPI; +import org.apache.xpath.objects.XObject; + import org.apache.fop.apps.FOPException; import org.apache.fop.apps.FOUserAgent; import org.apache.fop.apps.Fop; import org.apache.fop.apps.FopFactory; import org.apache.fop.apps.MimeConstants; import org.apache.fop.render.xml.XMLRenderer; -import org.apache.xpath.XPathAPI; -import org.apache.xpath.objects.XObject; -import org.junit.BeforeClass; -import org.junit.Test; -import org.w3c.dom.Document; /** * Tests URI resolution facilities. @@ -160,8 +162,7 @@ public class URIResolutionTestCase extends AbstractFOPTest { TransformerHandler athandler = tfactory.newTransformerHandler(); athandler.setResult(domres); - XMLRenderer atrenderer = new XMLRenderer(); - atrenderer.setUserAgent(ua); + XMLRenderer atrenderer = new XMLRenderer(ua); atrenderer.setContentHandler(athandler); ua.setRendererOverride(atrenderer); diff --git a/test/java/org/apache/fop/intermediate/AreaTreeParserTestCase.java b/test/java/org/apache/fop/intermediate/AreaTreeParserTestCase.java index a0de2e8ab..1f8abb9be 100644 --- a/test/java/org/apache/fop/intermediate/AreaTreeParserTestCase.java +++ b/test/java/org/apache/fop/intermediate/AreaTreeParserTestCase.java @@ -97,10 +97,9 @@ public class AreaTreeParserTestCase extends AbstractIntermediateTest { Renderer targetRenderer = userAgent.getRendererFactory().createRenderer( userAgent, getTargetMIME()); - XMLRenderer renderer = new XMLRenderer(); + XMLRenderer renderer = new XMLRenderer(userAgent); renderer.mimicRenderer(targetRenderer); renderer.setContentHandler(handler); - renderer.setUserAgent(userAgent); userAgent.setRendererOverride(renderer); @@ -131,12 +130,10 @@ public class AreaTreeParserTestCase extends AbstractIntermediateTest { TransformerHandler handler = testAssistant.getTransformerFactory().newTransformerHandler(); DOMResult domResult = new DOMResult(); handler.setResult(domResult); - XMLRenderer renderer = new XMLRenderer(); - renderer.setContentHandler(handler); - FOUserAgent userAgent = createUserAgent(); + XMLRenderer renderer = new XMLRenderer(userAgent); userAgent.setRendererOverride(renderer); - renderer.setUserAgent(userAgent); + renderer.setContentHandler(handler); FontInfo fontInfo = new FontInfo(); AreaTreeModel treeModel = new RenderPagesModel(userAgent, diff --git a/test/java/org/apache/fop/layoutengine/LayoutEngineTestCase.java b/test/java/org/apache/fop/layoutengine/LayoutEngineTestCase.java index 46908a448..6a0d424e9 100644 --- a/test/java/org/apache/fop/layoutengine/LayoutEngineTestCase.java +++ b/test/java/org/apache/fop/layoutengine/LayoutEngineTestCase.java @@ -150,8 +150,7 @@ public class LayoutEngineTestCase { ua.getEventBroadcaster().addEventListener( new ConsoleEventListenerForTests(testFile.getName(), EventSeverity.WARN)); - XMLRenderer atrenderer = new XMLRenderer(); - atrenderer.setUserAgent(ua); + XMLRenderer atrenderer = new XMLRenderer(ua); atrenderer.setContentHandler(athandler); ua.setRendererOverride(atrenderer); fop = effFactory.newFop(ua); @@ -208,8 +207,7 @@ public class LayoutEngineTestCase { ua.getEventBroadcaster().addEventListener( new ConsoleEventListenerForTests(testFile.getName(), EventSeverity.WARN)); - IFRenderer ifRenderer = new IFRenderer(); - ifRenderer.setUserAgent(ua); + IFRenderer ifRenderer = new IFRenderer(ua); IFSerializer serializer = new IFSerializer(); serializer.setContext(new IFContext(ua)); -- cgit v1.2.3 From af35f0470875116ed42e407c05127f16272ec890 Mon Sep 17 00:00:00 2001 From: Mehdi Houshmand Date: Mon, 30 Jan 2012 11:46:13 +0000 Subject: Amended checkstyle errors and return carriages git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@1237610 13f79535-47bb-0310-9956-ffa450edef68 --- .../fop/afp/fonts/AFPBase12FontCollection.java | 3 + .../org/apache/fop/afp/modca/GraphicsObject.java | 1 + .../apache/fop/fonts/type1/Type1FontLoader.java | 2 +- .../fop/render/AbstractPathOrientedRenderer.java | 3 + src/java/org/apache/fop/render/PrintRenderer.java | 3 + .../fop/render/afp/AFPRendererConfigurator.java | 6 +- .../org/apache/fop/render/bitmap/PNGRenderer.java | 3 + .../org/apache/fop/render/bitmap/TIFFRenderer.java | 6 +- .../apache/fop/render/intermediate/IFRenderer.java | 2 + .../apache/fop/render/java2d/Java2DRenderer.java | 6 +- .../apache/fop/render/print/PageableRenderer.java | 2 + .../org/apache/fop/render/print/PrintRenderer.java | 2 + .../org/apache/fop/render/txt/TXTRenderer.java | 2 + .../apache/fop/render/xml/AbstractXMLRenderer.java | 3 + .../org/apache/fop/render/xml/XMLRenderer.java | 3 + .../org/apache/fop/render/svg/SVGRenderer.java | 3 + .../fop/fonts/truetype/TTFFontLoaderTestCase.java | 114 ++++++++++----------- .../java/org/apache/fop/pdf/PDFObjectTestCase.java | 10 +- 18 files changed, 109 insertions(+), 65 deletions(-) (limited to 'src/java/org/apache/fop/render/bitmap') diff --git a/src/java/org/apache/fop/afp/fonts/AFPBase12FontCollection.java b/src/java/org/apache/fop/afp/fonts/AFPBase12FontCollection.java index c872a08cc..244e6122c 100644 --- a/src/java/org/apache/fop/afp/fonts/AFPBase12FontCollection.java +++ b/src/java/org/apache/fop/afp/fonts/AFPBase12FontCollection.java @@ -43,6 +43,9 @@ public class AFPBase12FontCollection implements FontCollection { private final AFPEventProducer eventProducer; + /** + * @param eventProducer the AFP-specific event producer + */ public AFPBase12FontCollection(AFPEventProducer eventProducer) { this.eventProducer = eventProducer; } diff --git a/src/java/org/apache/fop/afp/modca/GraphicsObject.java b/src/java/org/apache/fop/afp/modca/GraphicsObject.java index 66876a5ac..19d4618be 100644 --- a/src/java/org/apache/fop/afp/modca/GraphicsObject.java +++ b/src/java/org/apache/fop/afp/modca/GraphicsObject.java @@ -325,6 +325,7 @@ public class GraphicsObject extends AbstractDataObject { * @param str the string * @param x the x coordinate * @param y the y coordinate + * @param charSet the character set associated with the string */ public void addString(String str, int x, int y, CharacterSet charSet) { addObject(new GraphicsCharacterString(str, x, y, charSet)); diff --git a/src/java/org/apache/fop/fonts/type1/Type1FontLoader.java b/src/java/org/apache/fop/fonts/type1/Type1FontLoader.java index b5b573eca..1e93763e8 100644 --- a/src/java/org/apache/fop/fonts/type1/Type1FontLoader.java +++ b/src/java/org/apache/fop/fonts/type1/Type1FontLoader.java @@ -62,7 +62,7 @@ public class Type1FontLoader extends FontLoader { return pfbURI.substring(0, pfbURI.length() - 4) + "." + pfmExt; } - private static final String[] AFM_EXTENSIONS = new String[] { ".AFM", ".afm", ".Afm" }; + private static final String[] AFM_EXTENSIONS = new String[] {".AFM", ".afm", ".Afm"}; /** {@inheritDoc} */ @Override diff --git a/src/java/org/apache/fop/render/AbstractPathOrientedRenderer.java b/src/java/org/apache/fop/render/AbstractPathOrientedRenderer.java index 83d3d84a2..333248f4d 100644 --- a/src/java/org/apache/fop/render/AbstractPathOrientedRenderer.java +++ b/src/java/org/apache/fop/render/AbstractPathOrientedRenderer.java @@ -57,6 +57,9 @@ import org.apache.fop.traits.BorderProps; */ public abstract class AbstractPathOrientedRenderer extends PrintRenderer { + /** + * @param userAgent the user agent that contains configuration details. This cannot be null. + */ public AbstractPathOrientedRenderer(FOUserAgent userAgent) { super(userAgent); } diff --git a/src/java/org/apache/fop/render/PrintRenderer.java b/src/java/org/apache/fop/render/PrintRenderer.java index 05e9cb7af..4e49adc25 100644 --- a/src/java/org/apache/fop/render/PrintRenderer.java +++ b/src/java/org/apache/fop/render/PrintRenderer.java @@ -43,6 +43,9 @@ import org.apache.fop.fonts.base14.Base14FontCollection; /** Abstract base class of "Print" type renderers. */ public abstract class PrintRenderer extends AbstractRenderer { + /** + * @param userAgent the user agent that contains configuration details. This cannot be null. + */ public PrintRenderer(FOUserAgent userAgent) { super(userAgent); } diff --git a/src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java b/src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java index bfef1b0cc..23449ce4e 100644 --- a/src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java +++ b/src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java @@ -204,8 +204,10 @@ public class AFPRendererConfigurator extends PrintRendererConfigurator "org.apache.fop.fonts.base14." + base14).asSubclass(Typeface.class); try { Typeface tf = clazz.newInstance(); - font.addCharacterSet(sizeMpt, CharacterSetBuilder.getSingleByteInstance() - .build(characterset, codepage, encoding, tf, eventProducer)); + font.addCharacterSet(sizeMpt, + CharacterSetBuilder.getSingleByteInstance() + .build(characterset, codepage, encoding, tf, + eventProducer)); } catch (Exception ie) { String msg = "The base 14 font class " + clazz.getName() + " could not be instantiated"; diff --git a/src/java/org/apache/fop/render/bitmap/PNGRenderer.java b/src/java/org/apache/fop/render/bitmap/PNGRenderer.java index 1c6f2e33d..6f45d18ca 100644 --- a/src/java/org/apache/fop/render/bitmap/PNGRenderer.java +++ b/src/java/org/apache/fop/render/bitmap/PNGRenderer.java @@ -41,6 +41,9 @@ import org.apache.fop.render.java2d.Java2DRenderer; */ public class PNGRenderer extends Java2DRenderer { + /** + * @param userAgent the user agent that contains configuration details. This cannot be null. + */ public PNGRenderer(FOUserAgent userAgent) { super(userAgent); } diff --git a/src/java/org/apache/fop/render/bitmap/TIFFRenderer.java b/src/java/org/apache/fop/render/bitmap/TIFFRenderer.java index 0e2364d35..3cdcf2cdc 100644 --- a/src/java/org/apache/fop/render/bitmap/TIFFRenderer.java +++ b/src/java/org/apache/fop/render/bitmap/TIFFRenderer.java @@ -82,7 +82,11 @@ public class TIFFRenderer extends Java2DRenderer implements TIFFConstants { return MIME_TYPE; } - /** Creates TIFF renderer. */ + /** + * Creates TIFF renderer. + * + * @param userAgent the user agent that contains configuration details. This cannot be null. + */ public TIFFRenderer(FOUserAgent userAgent) { super(userAgent); writerParams = new ImageWriterParams(); diff --git a/src/java/org/apache/fop/render/intermediate/IFRenderer.java b/src/java/org/apache/fop/render/intermediate/IFRenderer.java index d5d5a154a..9d8fb6e4b 100644 --- a/src/java/org/apache/fop/render/intermediate/IFRenderer.java +++ b/src/java/org/apache/fop/render/intermediate/IFRenderer.java @@ -158,6 +158,8 @@ public class IFRenderer extends AbstractPathOrientedRenderer { /** * Main constructor + * + * @param userAgent the user agent that contains configuration details. This cannot be null. */ public IFRenderer(FOUserAgent userAgent) { super(userAgent); diff --git a/src/java/org/apache/fop/render/java2d/Java2DRenderer.java b/src/java/org/apache/fop/render/java2d/Java2DRenderer.java index 3c7006588..1d1697607 100644 --- a/src/java/org/apache/fop/render/java2d/Java2DRenderer.java +++ b/src/java/org/apache/fop/render/java2d/Java2DRenderer.java @@ -146,7 +146,11 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem private GeneralPath currentPath = null; - /** Default constructor */ + /** + * Default constructor + * + * @param userAgent the user agent that contains configuration details. This cannot be null. + */ public Java2DRenderer(FOUserAgent userAgent) { super(userAgent); diff --git a/src/java/org/apache/fop/render/print/PageableRenderer.java b/src/java/org/apache/fop/render/print/PageableRenderer.java index 08d5b0f04..70a7f84a6 100644 --- a/src/java/org/apache/fop/render/print/PageableRenderer.java +++ b/src/java/org/apache/fop/render/print/PageableRenderer.java @@ -72,6 +72,8 @@ public class PageableRenderer extends Java2DRenderer implements Pageable { /** * Creates a new PageableRenderer. + * + * @param userAgent the user agent that contains configuration details. This cannot be null. */ public PageableRenderer(FOUserAgent userAgent) { super(userAgent); diff --git a/src/java/org/apache/fop/render/print/PrintRenderer.java b/src/java/org/apache/fop/render/print/PrintRenderer.java index ea68bc9b2..1540acd23 100644 --- a/src/java/org/apache/fop/render/print/PrintRenderer.java +++ b/src/java/org/apache/fop/render/print/PrintRenderer.java @@ -54,6 +54,8 @@ public class PrintRenderer extends PageableRenderer { /** * Creates a new PrintRenderer with the options set through the renderer options if a custom * PrinterJob is not given in FOUserAgent's renderer options. + * + * @param userAgent the user agent that contains configuration details. This cannot be null. */ public PrintRenderer(FOUserAgent userAgent) { super(userAgent); diff --git a/src/java/org/apache/fop/render/txt/TXTRenderer.java b/src/java/org/apache/fop/render/txt/TXTRenderer.java index 74c5b84a8..eecb6a623 100644 --- a/src/java/org/apache/fop/render/txt/TXTRenderer.java +++ b/src/java/org/apache/fop/render/txt/TXTRenderer.java @@ -110,6 +110,8 @@ public class TXTRenderer extends AbstractPathOrientedRenderer { /** * Constructs a newly allocated TXTRenderer object. + * + * @param userAgent the user agent that contains configuration details. This cannot be null. */ public TXTRenderer(FOUserAgent userAgent) { super(userAgent); diff --git a/src/java/org/apache/fop/render/xml/AbstractXMLRenderer.java b/src/java/org/apache/fop/render/xml/AbstractXMLRenderer.java index 9c938199f..149111e0d 100644 --- a/src/java/org/apache/fop/render/xml/AbstractXMLRenderer.java +++ b/src/java/org/apache/fop/render/xml/AbstractXMLRenderer.java @@ -49,6 +49,9 @@ import org.apache.fop.render.RendererContext; /** Abstract xml renderer base class. */ public abstract class AbstractXMLRenderer extends PrintRenderer { + /** + * @param userAgent the user agent that contains configuration details. This cannot be null. + */ public AbstractXMLRenderer(FOUserAgent userAgent) { super(userAgent); } diff --git a/src/java/org/apache/fop/render/xml/XMLRenderer.java b/src/java/org/apache/fop/render/xml/XMLRenderer.java index 3ae49b121..d2cd55abe 100644 --- a/src/java/org/apache/fop/render/xml/XMLRenderer.java +++ b/src/java/org/apache/fop/render/xml/XMLRenderer.java @@ -112,6 +112,9 @@ public class XMLRenderer extends AbstractXMLRenderer { private int pageSequenceIndex; + /** + * @param userAgent the user agent that contains configuration details. This cannot be null. + */ public XMLRenderer(FOUserAgent userAgent) { super(userAgent); context = new RendererContext(this, XML_MIME_TYPE); diff --git a/src/sandbox/org/apache/fop/render/svg/SVGRenderer.java b/src/sandbox/org/apache/fop/render/svg/SVGRenderer.java index 246062a32..0e575c736 100644 --- a/src/sandbox/org/apache/fop/render/svg/SVGRenderer.java +++ b/src/sandbox/org/apache/fop/render/svg/SVGRenderer.java @@ -70,6 +70,9 @@ public class SVGRenderer extends Java2DRenderer { /** Helper class for generating multiple files */ private MultiFileRenderingUtil multiFileUtil; + /** + * @param userAgent the user agent that contains configuration details. This cannot be null. + */ public SVGRenderer(FOUserAgent userAgent) { super(userAgent); } diff --git a/test/java/org/apache/fop/fonts/truetype/TTFFontLoaderTestCase.java b/test/java/org/apache/fop/fonts/truetype/TTFFontLoaderTestCase.java index 0d6fc1d48..aadf877e0 100644 --- a/test/java/org/apache/fop/fonts/truetype/TTFFontLoaderTestCase.java +++ b/test/java/org/apache/fop/fonts/truetype/TTFFontLoaderTestCase.java @@ -1,57 +1,57 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* $Id$ */ - -package org.apache.fop.fonts.truetype; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -import java.io.File; -import java.io.IOException; - -import org.junit.Test; - -import org.apache.fop.fonts.EncodingMode; -import org.apache.fop.fonts.FontManager; -import org.apache.fop.fonts.FontResolver; - -/** - * Test case for {@link TTFFontLoader}. - */ -public class TTFFontLoaderTestCase { - - @Test - public void testUseKerning() throws IOException { - File file = new File("test/resources/fonts/ttf/DejaVuLGCSerif.ttf"); - String absoluteFilePath = file.toURL().toExternalForm(); - FontResolver resolver = FontManager.createMinimalFontResolver(); - String fontName = "Deja Vu"; - boolean embedded = false; - boolean useKerning = true; - - TTFFontLoader fontLoader = new TTFFontLoader(absoluteFilePath, fontName, embedded, - EncodingMode.AUTO, useKerning, resolver); - assertTrue(fontLoader.getFont().hasKerningInfo()); - useKerning = false; - - fontLoader = new TTFFontLoader(absoluteFilePath, fontName, embedded, EncodingMode.AUTO, - useKerning, resolver); - assertFalse(fontLoader.getFont().hasKerningInfo()); - } -} +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* $Id$ */ + +package org.apache.fop.fonts.truetype; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.io.File; +import java.io.IOException; + +import org.junit.Test; + +import org.apache.fop.fonts.EncodingMode; +import org.apache.fop.fonts.FontManager; +import org.apache.fop.fonts.FontResolver; + +/** + * Test case for {@link TTFFontLoader}. + */ +public class TTFFontLoaderTestCase { + + @Test + public void testUseKerning() throws IOException { + File file = new File("test/resources/fonts/ttf/DejaVuLGCSerif.ttf"); + String absoluteFilePath = file.toURI().toURL().toExternalForm(); + FontResolver resolver = FontManager.createMinimalFontResolver(); + String fontName = "Deja Vu"; + boolean embedded = false; + boolean useKerning = true; + + TTFFontLoader fontLoader = new TTFFontLoader(absoluteFilePath, fontName, embedded, + EncodingMode.AUTO, useKerning, resolver); + assertTrue(fontLoader.getFont().hasKerningInfo()); + useKerning = false; + + fontLoader = new TTFFontLoader(absoluteFilePath, fontName, embedded, EncodingMode.AUTO, + useKerning, resolver); + assertFalse(fontLoader.getFont().hasKerningInfo()); + } +} diff --git a/test/java/org/apache/fop/pdf/PDFObjectTestCase.java b/test/java/org/apache/fop/pdf/PDFObjectTestCase.java index d4ad87d78..ee9512d88 100644 --- a/test/java/org/apache/fop/pdf/PDFObjectTestCase.java +++ b/test/java/org/apache/fop/pdf/PDFObjectTestCase.java @@ -19,13 +19,17 @@ package org.apache.fop.pdf; -import org.junit.Test; -import org.junit.Before; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; import java.io.ByteArrayOutputStream; import java.io.IOException; +import org.junit.Before; +import org.junit.Test; + /** * Tests the PDFObject class. */ -- cgit v1.2.3 From d6d8e57b17eb2e36631115517afa003ad3afa1a1 Mon Sep 17 00:00:00 2001 From: Glenn Adams Date: Sun, 26 Feb 2012 02:29:01 +0000 Subject: apply complex scripts patch git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@1293736 13f79535-47bb-0310-9956-ffa450edef68 --- build.xml | 169 +- checkstyle-suppressions.xml | 3 +- findbugs-exclude.xml | 385 + fop.cmd | 2 +- .../fop/tools/EventProducerCollectorTask.java | 4 +- .../fop/complexscripts/bidi/GenerateBidiClass.java | 571 + .../complexscripts/bidi/GenerateBidiTestData.java | 1269 + .../content/xdocs/trunk/configuration.xml | 15 + .../fop-intermediate-format-ng-content.xsd | 8 +- src/foschema/fop-configuration.xsd | 5 + src/java/org/apache/fop/apps/FOUserAgent.java | 18 + src/java/org/apache/fop/apps/FopFactory.java | 17 + .../apache/fop/apps/FopFactoryConfigurator.java | 10 + src/java/org/apache/fop/area/Area.java | 90 +- src/java/org/apache/fop/area/AreaTreeHandler.java | 14 + src/java/org/apache/fop/area/AreaTreeParser.java | 31 +- src/java/org/apache/fop/area/Block.java | 9 +- src/java/org/apache/fop/area/BodyRegion.java | 12 + src/java/org/apache/fop/area/CTM.java | 29 +- src/java/org/apache/fop/area/LineArea.java | 52 +- src/java/org/apache/fop/area/LinkResolver.java | 33 +- src/java/org/apache/fop/area/MainReference.java | 13 + src/java/org/apache/fop/area/Page.java | 24 + src/java/org/apache/fop/area/PageViewport.java | 12 + src/java/org/apache/fop/area/RegionViewport.java | 22 +- src/java/org/apache/fop/area/Span.java | 26 + src/java/org/apache/fop/area/Trait.java | 23 +- .../apache/fop/area/inline/AbstractTextArea.java | 2 +- .../org/apache/fop/area/inline/BasicLinkArea.java | 23 +- .../org/apache/fop/area/inline/FilledArea.java | 7 +- .../org/apache/fop/area/inline/InlineArea.java | 81 +- .../org/apache/fop/area/inline/InlineParent.java | 38 +- .../org/apache/fop/area/inline/InlineViewport.java | 15 +- src/java/org/apache/fop/area/inline/Space.java | 6 + src/java/org/apache/fop/area/inline/SpaceArea.java | 16 +- src/java/org/apache/fop/area/inline/TextArea.java | 94 +- .../fop/area/inline/UnresolvedPageNumber.java | 36 +- src/java/org/apache/fop/area/inline/WordArea.java | 278 +- .../org/apache/fop/cli/CommandLineOptions.java | 8 + .../apache/fop/complexscripts/bidi/BidiClass.java | 271 + .../fop/complexscripts/bidi/BidiConstants.java | 91 + .../fop/complexscripts/bidi/BidiResolver.java | 242 + .../complexscripts/bidi/DelimitedTextRange.java | 228 + .../apache/fop/complexscripts/bidi/InlineRun.java | 310 + .../fop/complexscripts/bidi/TextInterval.java | 143 + .../complexscripts/bidi/UnflattenProcessor.java | 361 + .../complexscripts/bidi/UnicodeBidiAlgorithm.java | 839 + .../AdvancedTypographicTableFormatException.java | 49 + .../complexscripts/fonts/GlyphClassMapping.java | 48 + .../fop/complexscripts/fonts/GlyphClassTable.java | 277 + .../complexscripts/fonts/GlyphCoverageMapping.java | 46 + .../complexscripts/fonts/GlyphCoverageTable.java | 233 + .../fop/complexscripts/fonts/GlyphDefinition.java | 38 + .../fonts/GlyphDefinitionSubtable.java | 76 + .../complexscripts/fonts/GlyphDefinitionTable.java | 451 + .../complexscripts/fonts/GlyphMappingTable.java | 322 + .../fop/complexscripts/fonts/GlyphPositioning.java | 43 + .../fonts/GlyphPositioningState.java | 208 + .../fonts/GlyphPositioningSubtable.java | 129 + .../fonts/GlyphPositioningTable.java | 2264 + .../complexscripts/fonts/GlyphProcessingState.java | 1135 + .../complexscripts/fonts/GlyphSubstitution.java | 41 + .../fonts/GlyphSubstitutionState.java | 230 + .../fonts/GlyphSubstitutionSubtable.java | 124 + .../fonts/GlyphSubstitutionTable.java | 1474 + .../fop/complexscripts/fonts/GlyphSubtable.java | 314 + .../fop/complexscripts/fonts/GlyphTable.java | 1300 + .../fonts/IncompatibleSubtableException.java | 41 + .../fonts/OTFAdvancedTypographicTableReader.java | 3797 + .../fop/complexscripts/fonts/Positionable.java | 58 + .../fop/complexscripts/fonts/Substitutable.java | 63 + .../scripts/ArabicScriptProcessor.java | 522 + .../scripts/DefaultScriptProcessor.java | 144 + .../scripts/DevanagariScriptProcessor.java | 537 + .../scripts/GujaratiScriptProcessor.java | 537 + .../scripts/GurmukhiScriptProcessor.java | 543 + .../scripts/IndicScriptProcessor.java | 589 + .../complexscripts/scripts/ScriptProcessor.java | 234 + .../apache/fop/complexscripts/util/CharMirror.java | 715 + .../apache/fop/complexscripts/util/CharScript.java | 930 + .../util/DiscontinuousAssociationException.java | 41 + .../complexscripts/util/GlyphContextTester.java | 42 + .../fop/complexscripts/util/GlyphSequence.java | 1075 + .../fop/complexscripts/util/GlyphTester.java | 36 + .../fop/complexscripts/util/NumberConverter.java | 1616 + .../complexscripts/util/ScriptContextTester.java | 35 + .../org/apache/fop/complexscripts/util/UTF32.java | 128 + src/java/org/apache/fop/fo/Constants.java | 22 +- src/java/org/apache/fop/fo/FONode.java | 119 + src/java/org/apache/fop/fo/FOPropertyMapping.java | 162 +- src/java/org/apache/fop/fo/FOText.java | 343 +- src/java/org/apache/fop/fo/FObj.java | 63 +- src/java/org/apache/fop/fo/PropertyList.java | 84 +- .../org/apache/fop/fo/flow/AbstractGraphics.java | 20 +- .../fop/fo/flow/AbstractPageNumberCitation.java | 16 + src/java/org/apache/fop/fo/flow/BidiOverride.java | 138 +- src/java/org/apache/fop/fo/flow/Block.java | 64 +- .../org/apache/fop/fo/flow/BlockContainer.java | 85 +- src/java/org/apache/fop/fo/flow/Character.java | 15 + .../org/apache/fop/fo/flow/InlineContainer.java | 89 +- src/java/org/apache/fop/fo/flow/InlineLevel.java | 17 +- src/java/org/apache/fop/fo/flow/Leader.java | 43 +- src/java/org/apache/fop/fo/flow/ListItem.java | 17 + src/java/org/apache/fop/fo/flow/PageNumber.java | 6 + src/java/org/apache/fop/fo/flow/Wrapper.java | 6 + src/java/org/apache/fop/fo/flow/table/Table.java | 34 +- .../fop/fo/pagination/AbstractPageSequence.java | 9 +- .../fop/fo/pagination/PageNumberGenerator.java | 152 +- .../org/apache/fop/fo/pagination/PageSequence.java | 132 +- src/java/org/apache/fop/fo/pagination/Region.java | 27 +- .../org/apache/fop/fo/pagination/RegionAfter.java | 14 +- .../org/apache/fop/fo/pagination/RegionBA.java | 7 +- .../org/apache/fop/fo/pagination/RegionBefore.java | 13 +- .../org/apache/fop/fo/pagination/RegionBody.java | 16 +- .../org/apache/fop/fo/pagination/RegionEnd.java | 18 +- .../org/apache/fop/fo/pagination/RegionSE.java | 7 +- .../org/apache/fop/fo/pagination/RegionStart.java | 17 +- .../apache/fop/fo/pagination/SimplePageMaster.java | 27 +- .../fo/properties/CorrespondingPropertyMaker.java | 19 +- .../fop/fo/properties/DimensionPropertyMaker.java | 23 +- .../fop/fo/properties/IndentPropertyMaker.java | 13 +- src/java/org/apache/fop/fonts/BFEntry.java | 12 +- src/java/org/apache/fop/fonts/CustomFont.java | 17 + .../org/apache/fop/fonts/CustomFontCollection.java | 5 +- src/java/org/apache/fop/fonts/EmbedFontInfo.java | 27 +- src/java/org/apache/fop/fonts/Font.java | 111 +- .../org/apache/fop/fonts/FontInfoConfigurator.java | 10 +- src/java/org/apache/fop/fonts/FontLoader.java | 29 +- src/java/org/apache/fop/fonts/FontManager.java | 36 +- .../apache/fop/fonts/FontManagerConfigurator.java | 12 + src/java/org/apache/fop/fonts/FontReader.java | 17 +- src/java/org/apache/fop/fonts/FontResolver.java | 6 + src/java/org/apache/fop/fonts/FontSetup.java | 52 +- src/java/org/apache/fop/fonts/LazyFont.java | 124 +- src/java/org/apache/fop/fonts/MultiByteFont.java | 351 +- src/java/org/apache/fop/fonts/MutableFont.java | 6 + src/java/org/apache/fop/fonts/Typeface.java | 6 +- .../apache/fop/fonts/apps/AbstractFontReader.java | 6 +- src/java/org/apache/fop/fonts/apps/TTFReader.java | 22 +- .../fop/fonts/autodetect/FontInfoFinder.java | 12 +- .../apache/fop/fonts/truetype/TTFDirTabEntry.java | 8 +- .../org/apache/fop/fonts/truetype/TTFFile.java | 214 +- .../apache/fop/fonts/truetype/TTFFontLoader.java | 25 +- .../apache/fop/fonts/truetype/TTFSubSetFile.java | 16 + .../apache/fop/fonts/type1/Type1FontLoader.java | 2 +- .../fop/layoutmgr/AbstractLayoutManager.java | 2 +- .../fop/layoutmgr/BlockContainerLayoutManager.java | 15 +- .../apache/fop/layoutmgr/BlockLayoutManager.java | 3 +- .../layoutmgr/ExternalDocumentLayoutManager.java | 8 +- .../org/apache/fop/layoutmgr/LayoutContext.java | 7 +- .../apache/fop/layoutmgr/LayoutManagerMapping.java | 24 +- .../org/apache/fop/layoutmgr/PageProvider.java | 1 + .../fop/layoutmgr/PageSequenceLayoutManager.java | 7 +- .../inline/AbstractGraphicsLayoutManager.java | 25 +- .../AbstractPageNumberCitationLayoutManager.java | 41 +- .../fop/layoutmgr/inline/AlignmentContext.java | 15 +- .../layoutmgr/inline/BasicLinkLayoutManager.java | 6 + .../fop/layoutmgr/inline/BidiLayoutManager.java | 45 +- .../layoutmgr/inline/CharacterLayoutManager.java | 13 +- .../fop/layoutmgr/inline/InlineLayoutManager.java | 6 +- .../inline/InlineStackingLayoutManager.java | 4 + .../fop/layoutmgr/inline/LeaderLayoutManager.java | 30 +- .../layoutmgr/inline/LeafNodeLayoutManager.java | 2 +- .../fop/layoutmgr/inline/LineLayoutManager.java | 63 +- .../PageNumberCitationLastLayoutManager.java | 8 +- .../inline/PageNumberCitationLayoutManager.java | 19 +- .../layoutmgr/inline/PageNumberLayoutManager.java | 2 +- .../fop/layoutmgr/inline/ScaledBaselineTable.java | 9 +- .../fop/layoutmgr/inline/TextLayoutManager.java | 607 +- .../fop/layoutmgr/list/ListBlockLayoutManager.java | 4 +- .../list/ListItemContentLayoutManager.java | 6 +- .../fop/layoutmgr/list/ListItemLayoutManager.java | 5 +- .../apache/fop/layoutmgr/table/ColumnSetup.java | 42 + src/java/org/apache/fop/pdf/PDFTextUtil.java | 57 +- .../fop/render/AbstractPathOrientedRenderer.java | 328 +- .../org/apache/fop/render/AbstractRenderer.java | 129 +- .../org/apache/fop/render/DefaultFontResolver.java | 5 + src/java/org/apache/fop/render/PrintRenderer.java | 3 +- .../fop/render/PrintRendererConfigurator.java | 7 +- src/java/org/apache/fop/render/afp/AFPPainter.java | 14 +- .../render/bitmap/BitmapRendererConfigurator.java | 3 +- .../fop/render/intermediate/AbstractIFPainter.java | 52 +- .../fop/render/intermediate/BorderPainter.java | 74 +- .../apache/fop/render/intermediate/IFPainter.java | 18 +- .../apache/fop/render/intermediate/IFParser.java | 10 +- .../apache/fop/render/intermediate/IFRenderer.java | 172 +- .../fop/render/intermediate/IFSerializer.java | 37 +- .../org/apache/fop/render/intermediate/IFUtil.java | 178 + .../render/java2d/ConfiguredFontCollection.java | 8 +- .../apache/fop/render/java2d/Java2DPainter.java | 12 +- .../apache/fop/render/java2d/Java2DRenderer.java | 7 +- src/java/org/apache/fop/render/pcl/PCLPainter.java | 31 +- .../fop/render/pcl/PCLRendererConfigurator.java | 3 +- src/java/org/apache/fop/render/pdf/PDFPainter.java | 89 +- .../apache/fop/render/ps/AbstractPSTranscoder.java | 3 +- .../apache/fop/render/ps/NativeTextHandler.java | 3 +- src/java/org/apache/fop/render/ps/PSPainter.java | 25 +- src/java/org/apache/fop/render/rtf/RTFHandler.java | 3 +- .../org/apache/fop/render/xml/XMLRenderer.java | 46 +- .../org/apache/fop/svg/PDFDocumentGraphics2D.java | 3 +- .../fop/svg/PDFDocumentGraphics2DConfigurator.java | 15 +- src/java/org/apache/fop/svg/PDFGraphics2D.java | 3 +- src/java/org/apache/fop/svg/PDFTranscoder.java | 3 +- .../apache/fop/text/linebreak/LineBreakUtils.java | 46 +- src/java/org/apache/fop/traits/Direction.java | 108 + src/java/org/apache/fop/traits/WritingMode.java | 166 + .../org/apache/fop/traits/WritingModeTraits.java | 157 + .../apache/fop/traits/WritingModeTraitsGetter.java | 58 + .../apache/fop/traits/WritingModeTraitsSetter.java | 70 + src/java/org/apache/fop/util/CharUtilities.java | 158 +- src/java/org/apache/fop/util/XMLUtil.java | 122 + .../org/apache/fop/render/mif/MIFHandler.java | 3 +- .../org/apache/fop/render/svg/SVGPainter.java | 6 +- .../complexscripts/ComplexScriptsTestSuite.java | 42 + .../complexscripts/bidi/BidiAlgorithmTestCase.java | 265 + .../fop/complexscripts/bidi/BidiClassTestCase.java | 58 + .../fop/complexscripts/bidi/BidiTestData$LD0.ser | Bin 0 -> 87 bytes .../fop/complexscripts/bidi/BidiTestData$LD1.ser | Bin 0 -> 119 bytes .../fop/complexscripts/bidi/BidiTestData$LD10.ser | Bin 0 -> 359 bytes .../fop/complexscripts/bidi/BidiTestData$LD100.ser | Bin 0 -> 11343 bytes .../fop/complexscripts/bidi/BidiTestData$LD101.ser | Bin 0 -> 5103 bytes .../fop/complexscripts/bidi/BidiTestData$LD102.ser | Bin 0 -> 1263 bytes .../fop/complexscripts/bidi/BidiTestData$LD103.ser | Bin 0 -> 16943 bytes .../fop/complexscripts/bidi/BidiTestData$LD104.ser | Bin 0 -> 22043 bytes .../fop/complexscripts/bidi/BidiTestData$LD105.ser | Bin 0 -> 10463 bytes .../fop/complexscripts/bidi/BidiTestData$LD106.ser | Bin 0 -> 12883 bytes .../fop/complexscripts/bidi/BidiTestData$LD107.ser | Bin 0 -> 12143 bytes .../fop/complexscripts/bidi/BidiTestData$LD108.ser | Bin 0 -> 9343 bytes .../fop/complexscripts/bidi/BidiTestData$LD109.ser | Bin 0 -> 6143 bytes .../fop/complexscripts/bidi/BidiTestData$LD11.ser | Bin 0 -> 275 bytes .../fop/complexscripts/bidi/BidiTestData$LD110.ser | Bin 0 -> 1903 bytes .../fop/complexscripts/bidi/BidiTestData$LD111.ser | Bin 0 -> 543 bytes .../fop/complexscripts/bidi/BidiTestData$LD112.ser | Bin 0 -> 13015 bytes .../fop/complexscripts/bidi/BidiTestData$LD113.ser | Bin 0 -> 2647 bytes .../fop/complexscripts/bidi/BidiTestData$LD114.ser | Bin 0 -> 1351 bytes .../fop/complexscripts/bidi/BidiTestData$LD115.ser | Bin 0 -> 58383 bytes .../fop/complexscripts/bidi/BidiTestData$LD116.ser | Bin 0 -> 2359 bytes .../fop/complexscripts/bidi/BidiTestData$LD117.ser | Bin 0 -> 919 bytes .../fop/complexscripts/bidi/BidiTestData$LD118.ser | Bin 0 -> 631 bytes .../fop/complexscripts/bidi/BidiTestData$LD119.ser | Bin 0 -> 13023 bytes .../fop/complexscripts/bidi/BidiTestData$LD12.ser | Bin 0 -> 95 bytes .../fop/complexscripts/bidi/BidiTestData$LD120.ser | Bin 0 -> 1351 bytes .../fop/complexscripts/bidi/BidiTestData$LD121.ser | Bin 0 -> 343 bytes .../fop/complexscripts/bidi/BidiTestData$LD122.ser | Bin 0 -> 343 bytes .../fop/complexscripts/bidi/BidiTestData$LD123.ser | Bin 0 -> 6543 bytes .../fop/complexscripts/bidi/BidiTestData$LD124.ser | Bin 0 -> 28143 bytes .../fop/complexscripts/bidi/BidiTestData$LD125.ser | Bin 0 -> 22743 bytes .../fop/complexscripts/bidi/BidiTestData$LD126.ser | Bin 0 -> 23823 bytes .../fop/complexscripts/bidi/BidiTestData$LD127.ser | Bin 0 -> 2223 bytes .../fop/complexscripts/bidi/BidiTestData$LD128.ser | Bin 0 -> 1143 bytes .../fop/complexscripts/bidi/BidiTestData$LD129.ser | Bin 0 -> 29583 bytes .../fop/complexscripts/bidi/BidiTestData$LD13.ser | Bin 0 -> 3511 bytes .../fop/complexscripts/bidi/BidiTestData$LD130.ser | Bin 0 -> 12123 bytes .../fop/complexscripts/bidi/BidiTestData$LD131.ser | Bin 0 -> 18423 bytes .../fop/complexscripts/bidi/BidiTestData$LD132.ser | Bin 0 -> 14103 bytes .../fop/complexscripts/bidi/BidiTestData$LD133.ser | Bin 0 -> 9243 bytes .../fop/complexscripts/bidi/BidiTestData$LD134.ser | Bin 0 -> 783 bytes .../fop/complexscripts/bidi/BidiTestData$LD135.ser | Bin 0 -> 423 bytes .../fop/complexscripts/bidi/BidiTestData$LD136.ser | Bin 0 -> 2103 bytes .../fop/complexscripts/bidi/BidiTestData$LD137.ser | Bin 0 -> 183 bytes .../fop/complexscripts/bidi/BidiTestData$LD138.ser | Bin 0 -> 151 bytes .../fop/complexscripts/bidi/BidiTestData$LD139.ser | Bin 0 -> 10143 bytes .../fop/complexscripts/bidi/BidiTestData$LD14.ser | Bin 0 -> 1127 bytes .../fop/complexscripts/bidi/BidiTestData$LD140.ser | Bin 0 -> 823 bytes .../fop/complexscripts/bidi/BidiTestData$LD141.ser | Bin 0 -> 13015 bytes .../fop/complexscripts/bidi/BidiTestData$LD142.ser | Bin 0 -> 3799 bytes .../fop/complexscripts/bidi/BidiTestData$LD143.ser | Bin 0 -> 58383 bytes .../fop/complexscripts/bidi/BidiTestData$LD144.ser | Bin 0 -> 551 bytes .../fop/complexscripts/bidi/BidiTestData$LD145.ser | Bin 0 -> 3687 bytes .../fop/complexscripts/bidi/BidiTestData$LD146.ser | Bin 0 -> 1943 bytes .../fop/complexscripts/bidi/BidiTestData$LD147.ser | Bin 0 -> 18783 bytes .../fop/complexscripts/bidi/BidiTestData$LD148.ser | Bin 0 -> 5343 bytes .../fop/complexscripts/bidi/BidiTestData$LD149.ser | Bin 0 -> 32223 bytes .../fop/complexscripts/bidi/BidiTestData$LD15.ser | Bin 0 -> 263 bytes .../fop/complexscripts/bidi/BidiTestData$LD150.ser | Bin 0 -> 25383 bytes .../fop/complexscripts/bidi/BidiTestData$LD151.ser | Bin 0 -> 20583 bytes .../fop/complexscripts/bidi/BidiTestData$LD152.ser | Bin 0 -> 4383 bytes .../fop/complexscripts/bidi/BidiTestData$LD153.ser | Bin 0 -> 5983 bytes .../fop/complexscripts/bidi/BidiTestData$LD154.ser | Bin 0 -> 31623 bytes .../fop/complexscripts/bidi/BidiTestData$LD155.ser | Bin 0 -> 15123 bytes .../fop/complexscripts/bidi/BidiTestData$LD156.ser | Bin 0 -> 17963 bytes .../fop/complexscripts/bidi/BidiTestData$LD157.ser | Bin 0 -> 15863 bytes .../fop/complexscripts/bidi/BidiTestData$LD158.ser | Bin 0 -> 7623 bytes .../fop/complexscripts/bidi/BidiTestData$LD159.ser | Bin 0 -> 1863 bytes .../fop/complexscripts/bidi/BidiTestData$LD16.ser | Bin 0 -> 155 bytes .../fop/complexscripts/bidi/BidiTestData$LD160.ser | Bin 0 -> 1335 bytes .../fop/complexscripts/bidi/BidiTestData$LD161.ser | Bin 0 -> 151 bytes .../fop/complexscripts/bidi/BidiTestData$LD162.ser | Bin 0 -> 103 bytes .../fop/complexscripts/bidi/BidiTestData$LD163.ser | Bin 0 -> 5823 bytes .../fop/complexscripts/bidi/BidiTestData$LD164.ser | Bin 0 -> 311 bytes .../fop/complexscripts/bidi/BidiTestData$LD165.ser | Bin 0 -> 3735 bytes .../fop/complexscripts/bidi/BidiTestData$LD166.ser | Bin 0 -> 935 bytes .../fop/complexscripts/bidi/BidiTestData$LD167.ser | Bin 0 -> 16623 bytes .../fop/complexscripts/bidi/BidiTestData$LD168.ser | Bin 0 -> 343 bytes .../fop/complexscripts/bidi/BidiTestData$LD169.ser | Bin 0 -> 1975 bytes .../fop/complexscripts/bidi/BidiTestData$LD17.ser | Bin 0 -> 5239 bytes .../fop/complexscripts/bidi/BidiTestData$LD170.ser | Bin 0 -> 1303 bytes .../fop/complexscripts/bidi/BidiTestData$LD171.ser | Bin 0 -> 10143 bytes .../fop/complexscripts/bidi/BidiTestData$LD172.ser | Bin 0 -> 2943 bytes .../fop/complexscripts/bidi/BidiTestData$LD173.ser | Bin 0 -> 10503 bytes .../fop/complexscripts/bidi/BidiTestData$LD174.ser | Bin 0 -> 9903 bytes .../fop/complexscripts/bidi/BidiTestData$LD175.ser | Bin 0 -> 6903 bytes .../fop/complexscripts/bidi/BidiTestData$LD176.ser | Bin 0 -> 1503 bytes .../fop/complexscripts/bidi/BidiTestData$LD177.ser | Bin 0 -> 3183 bytes .../fop/complexscripts/bidi/BidiTestData$LD178.ser | Bin 0 -> 10283 bytes .../fop/complexscripts/bidi/BidiTestData$LD179.ser | Bin 0 -> 6223 bytes .../fop/complexscripts/bidi/BidiTestData$LD18.ser | Bin 0 -> 239 bytes .../fop/complexscripts/bidi/BidiTestData$LD180.ser | Bin 0 -> 6283 bytes .../fop/complexscripts/bidi/BidiTestData$LD181.ser | Bin 0 -> 5383 bytes .../fop/complexscripts/bidi/BidiTestData$LD182.ser | Bin 0 -> 2583 bytes .../fop/complexscripts/bidi/BidiTestData$LD183.ser | Bin 0 -> 663 bytes .../fop/complexscripts/bidi/BidiTestData$LD184.ser | Bin 0 -> 21423 bytes .../fop/complexscripts/bidi/BidiTestData$LD185.ser | Bin 0 -> 6423 bytes .../fop/complexscripts/bidi/BidiTestData$LD186.ser | Bin 0 -> 4623 bytes .../fop/complexscripts/bidi/BidiTestData$LD187.ser | Bin 0 -> 303 bytes .../fop/complexscripts/bidi/BidiTestData$LD188.ser | Bin 0 -> 183 bytes .../fop/complexscripts/bidi/BidiTestData$LD189.ser | Bin 0 -> 14943 bytes .../fop/complexscripts/bidi/BidiTestData$LD19.ser | Bin 0 -> 1127 bytes .../fop/complexscripts/bidi/BidiTestData$LD190.ser | Bin 0 -> 8163 bytes .../fop/complexscripts/bidi/BidiTestData$LD191.ser | Bin 0 -> 9183 bytes .../fop/complexscripts/bidi/BidiTestData$LD192.ser | Bin 0 -> 2263 bytes .../fop/complexscripts/bidi/BidiTestData$LD193.ser | Bin 0 -> 1403 bytes .../fop/complexscripts/bidi/BidiTestData$LD194.ser | Bin 0 -> 143 bytes .../fop/complexscripts/bidi/BidiTestData$LD195.ser | Bin 0 -> 103 bytes .../fop/complexscripts/bidi/BidiTestData$LD196.ser | Bin 0 -> 7503 bytes .../fop/complexscripts/bidi/BidiTestData$LD197.ser | Bin 0 -> 41343 bytes .../fop/complexscripts/bidi/BidiTestData$LD198.ser | Bin 0 -> 11103 bytes .../fop/complexscripts/bidi/BidiTestData$LD199.ser | Bin 0 -> 2343 bytes .../fop/complexscripts/bidi/BidiTestData$LD2.ser | Bin 0 -> 119 bytes .../fop/complexscripts/bidi/BidiTestData$LD20.ser | Bin 0 -> 359 bytes .../fop/complexscripts/bidi/BidiTestData$LD200.ser | Bin 0 -> 543 bytes .../fop/complexscripts/bidi/BidiTestData$LD201.ser | Bin 0 -> 10323 bytes .../fop/complexscripts/bidi/BidiTestData$LD202.ser | Bin 0 -> 20803 bytes .../fop/complexscripts/bidi/BidiTestData$LD203.ser | Bin 0 -> 16803 bytes .../fop/complexscripts/bidi/BidiTestData$LD204.ser | Bin 0 -> 15183 bytes .../fop/complexscripts/bidi/BidiTestData$LD205.ser | Bin 0 -> 4583 bytes .../fop/complexscripts/bidi/BidiTestData$LD206.ser | Bin 0 -> 903 bytes .../fop/complexscripts/bidi/BidiTestData$LD207.ser | Bin 0 -> 263 bytes .../fop/complexscripts/bidi/BidiTestData$LD208.ser | Bin 0 -> 6783 bytes .../fop/complexscripts/bidi/BidiTestData$LD209.ser | Bin 0 -> 11703 bytes .../fop/complexscripts/bidi/BidiTestData$LD21.ser | Bin 0 -> 5239 bytes .../fop/complexscripts/bidi/BidiTestData$LD210.ser | Bin 0 -> 25023 bytes .../fop/complexscripts/bidi/BidiTestData$LD211.ser | Bin 0 -> 1983 bytes .../fop/complexscripts/bidi/BidiTestData$LD212.ser | Bin 0 -> 1023 bytes .../fop/complexscripts/bidi/BidiTestData$LD213.ser | Bin 0 -> 11423 bytes .../fop/complexscripts/bidi/BidiTestData$LD214.ser | Bin 0 -> 13183 bytes .../fop/complexscripts/bidi/BidiTestData$LD215.ser | Bin 0 -> 9603 bytes .../fop/complexscripts/bidi/BidiTestData$LD216.ser | Bin 0 -> 10263 bytes .../fop/complexscripts/bidi/BidiTestData$LD217.ser | Bin 0 -> 8543 bytes .../fop/complexscripts/bidi/BidiTestData$LD218.ser | Bin 0 -> 823 bytes .../fop/complexscripts/bidi/BidiTestData$LD219.ser | Bin 0 -> 443 bytes .../fop/complexscripts/bidi/BidiTestData$LD22.ser | Bin 0 -> 155 bytes .../fop/complexscripts/bidi/BidiTestData$LD220.ser | Bin 0 -> 543 bytes .../fop/complexscripts/bidi/BidiTestData$LD221.ser | Bin 0 -> 4623 bytes .../fop/complexscripts/bidi/BidiTestData$LD222.ser | Bin 0 -> 1263 bytes .../fop/complexscripts/bidi/BidiTestData$LD223.ser | Bin 0 -> 20703 bytes .../fop/complexscripts/bidi/BidiTestData$LD224.ser | Bin 0 -> 3303 bytes .../fop/complexscripts/bidi/BidiTestData$LD225.ser | Bin 0 -> 1063 bytes .../fop/complexscripts/bidi/BidiTestData$LD226.ser | Bin 0 -> 9803 bytes .../fop/complexscripts/bidi/BidiTestData$LD227.ser | Bin 0 -> 1563 bytes .../fop/complexscripts/bidi/BidiTestData$LD228.ser | Bin 0 -> 4183 bytes .../fop/complexscripts/bidi/BidiTestData$LD229.ser | Bin 0 -> 7863 bytes .../fop/complexscripts/bidi/BidiTestData$LD23.ser | Bin 0 -> 359 bytes .../fop/complexscripts/bidi/BidiTestData$LD230.ser | Bin 0 -> 7363 bytes .../fop/complexscripts/bidi/BidiTestData$LD231.ser | Bin 0 -> 1623 bytes .../fop/complexscripts/bidi/BidiTestData$LD232.ser | Bin 0 -> 303 bytes .../fop/complexscripts/bidi/BidiTestData$LD233.ser | Bin 0 -> 1023 bytes .../fop/complexscripts/bidi/BidiTestData$LD234.ser | Bin 0 -> 783 bytes .../fop/complexscripts/bidi/BidiTestData$LD235.ser | Bin 0 -> 2343 bytes .../fop/complexscripts/bidi/BidiTestData$LD236.ser | Bin 0 -> 1983 bytes .../fop/complexscripts/bidi/BidiTestData$LD237.ser | Bin 0 -> 563 bytes .../fop/complexscripts/bidi/BidiTestData$LD238.ser | Bin 0 -> 2043 bytes .../fop/complexscripts/bidi/BidiTestData$LD239.ser | Bin 0 -> 443 bytes .../fop/complexscripts/bidi/BidiTestData$LD24.ser | Bin 0 -> 215 bytes .../fop/complexscripts/bidi/BidiTestData$LD240.ser | Bin 0 -> 783 bytes .../fop/complexscripts/bidi/BidiTestData$LD241.ser | Bin 0 -> 1803 bytes .../fop/complexscripts/bidi/BidiTestData$LD242.ser | Bin 0 -> 1243 bytes .../fop/complexscripts/bidi/BidiTestData$LD243.ser | Bin 0 -> 323 bytes .../fop/complexscripts/bidi/BidiTestData$LD244.ser | Bin 0 -> 17823 bytes .../fop/complexscripts/bidi/BidiTestData$LD245.ser | Bin 0 -> 3963 bytes .../fop/complexscripts/bidi/BidiTestData$LD246.ser | Bin 0 -> 3383 bytes .../fop/complexscripts/bidi/BidiTestData$LD247.ser | Bin 0 -> 1623 bytes .../fop/complexscripts/bidi/BidiTestData$LD248.ser | Bin 0 -> 1083 bytes .../fop/complexscripts/bidi/BidiTestData$LD249.ser | Bin 0 -> 143 bytes .../fop/complexscripts/bidi/BidiTestData$LD25.ser | Bin 0 -> 1783 bytes .../fop/complexscripts/bidi/BidiTestData$LD250.ser | Bin 0 -> 103 bytes .../fop/complexscripts/bidi/BidiTestData$LD251.ser | Bin 0 -> 5683 bytes .../fop/complexscripts/bidi/BidiTestData$LD252.ser | Bin 0 -> 27783 bytes .../fop/complexscripts/bidi/BidiTestData$LD253.ser | Bin 0 -> 6623 bytes .../fop/complexscripts/bidi/BidiTestData$LD254.ser | Bin 0 -> 1883 bytes .../fop/complexscripts/bidi/BidiTestData$LD255.ser | Bin 0 -> 1783 bytes .../fop/complexscripts/bidi/BidiTestData$LD256.ser | Bin 0 -> 903 bytes .../fop/complexscripts/bidi/BidiTestData$LD257.ser | Bin 0 -> 263 bytes .../fop/complexscripts/bidi/BidiTestData$LD258.ser | Bin 0 -> 7143 bytes .../fop/complexscripts/bidi/BidiTestData$LD259.ser | Bin 0 -> 8303 bytes .../fop/complexscripts/bidi/BidiTestData$LD26.ser | Bin 0 -> 2551 bytes .../fop/complexscripts/bidi/BidiTestData$LD260.ser | Bin 0 -> 19743 bytes .../fop/complexscripts/bidi/BidiTestData$LD261.ser | Bin 0 -> 1663 bytes .../fop/complexscripts/bidi/BidiTestData$LD262.ser | Bin 0 -> 863 bytes .../fop/complexscripts/bidi/BidiTestData$LD263.ser | Bin 0 -> 4743 bytes .../fop/complexscripts/bidi/BidiTestData$LD264.ser | Bin 0 -> 5523 bytes .../fop/complexscripts/bidi/BidiTestData$LD265.ser | Bin 0 -> 1063 bytes .../fop/complexscripts/bidi/BidiTestData$LD266.ser | Bin 0 -> 23903 bytes .../fop/complexscripts/bidi/BidiTestData$LD267.ser | Bin 0 -> 3683 bytes .../fop/complexscripts/bidi/BidiTestData$LD268.ser | Bin 0 -> 3123 bytes .../fop/complexscripts/bidi/BidiTestData$LD269.ser | Bin 0 -> 5223 bytes .../fop/complexscripts/bidi/BidiTestData$LD27.ser | Bin 0 -> 4183 bytes .../fop/complexscripts/bidi/BidiTestData$LD270.ser | Bin 0 -> 663 bytes .../fop/complexscripts/bidi/BidiTestData$LD271.ser | Bin 0 -> 2643 bytes .../fop/complexscripts/bidi/BidiTestData$LD272.ser | Bin 0 -> 15503 bytes .../fop/complexscripts/bidi/BidiTestData$LD273.ser | Bin 0 -> 1343 bytes .../fop/complexscripts/bidi/BidiTestData$LD274.ser | Bin 0 -> 703 bytes .../fop/complexscripts/bidi/BidiTestData$LD275.ser | Bin 0 -> 303 bytes .../fop/complexscripts/bidi/BidiTestData$LD276.ser | Bin 0 -> 2583 bytes .../fop/complexscripts/bidi/BidiTestData$LD277.ser | Bin 0 -> 863 bytes .../fop/complexscripts/bidi/BidiTestData$LD278.ser | Bin 0 -> 7183 bytes .../fop/complexscripts/bidi/BidiTestData$LD279.ser | Bin 0 -> 1303 bytes .../fop/complexscripts/bidi/BidiTestData$LD28.ser | Bin 0 -> 2551 bytes .../fop/complexscripts/bidi/BidiTestData$LD280.ser | Bin 0 -> 183 bytes .../fop/complexscripts/bidi/BidiTestData$LD281.ser | Bin 0 -> 663 bytes .../fop/complexscripts/bidi/BidiTestData$LD282.ser | Bin 0 -> 543 bytes .../fop/complexscripts/bidi/BidiTestData$LD283.ser | Bin 0 -> 903 bytes .../fop/complexscripts/bidi/BidiTestData$LD284.ser | Bin 0 -> 783 bytes .../fop/complexscripts/bidi/BidiTestData$LD285.ser | Bin 0 -> 87543 bytes .../fop/complexscripts/bidi/BidiTestData$LD286.ser | Bin 0 -> 19503 bytes .../fop/complexscripts/bidi/BidiTestData$LD287.ser | Bin 0 -> 9783 bytes .../fop/complexscripts/bidi/BidiTestData$LD288.ser | Bin 0 -> 51903 bytes .../fop/complexscripts/bidi/BidiTestData$LD289.ser | Bin 0 -> 34083 bytes .../fop/complexscripts/bidi/BidiTestData$LD29.ser | Bin 0 -> 1879 bytes .../fop/complexscripts/bidi/BidiTestData$LD290.ser | Bin 0 -> 35703 bytes .../fop/complexscripts/bidi/BidiTestData$LD291.ser | Bin 0 -> 3303 bytes .../fop/complexscripts/bidi/BidiTestData$LD292.ser | Bin 0 -> 1683 bytes .../fop/complexscripts/bidi/BidiTestData$LD293.ser | Bin 0 -> 15183 bytes .../fop/complexscripts/bidi/BidiTestData$LD294.ser | Bin 0 -> 6543 bytes .../fop/complexscripts/bidi/BidiTestData$LD295.ser | Bin 0 -> 4383 bytes .../fop/complexscripts/bidi/BidiTestData$LD296.ser | Bin 0 -> 10143 bytes .../fop/complexscripts/bidi/BidiTestData$LD297.ser | Bin 0 -> 8343 bytes .../fop/complexscripts/bidi/BidiTestData$LD298.ser | Bin 0 -> 8703 bytes .../fop/complexscripts/bidi/BidiTestData$LD299.ser | Bin 0 -> 783 bytes .../fop/complexscripts/bidi/BidiTestData$LD3.ser | Bin 0 -> 63 bytes .../fop/complexscripts/bidi/BidiTestData$LD30.ser | Bin 0 -> 439 bytes .../fop/complexscripts/bidi/BidiTestData$LD300.ser | Bin 0 -> 423 bytes .../fop/complexscripts/bidi/BidiTestData$LD301.ser | Bin 0 -> 8703 bytes .../fop/complexscripts/bidi/BidiTestData$LD302.ser | Bin 0 -> 2223 bytes .../fop/complexscripts/bidi/BidiTestData$LD303.ser | Bin 0 -> 2223 bytes .../fop/complexscripts/bidi/BidiTestData$LD304.ser | Bin 0 -> 5463 bytes .../fop/complexscripts/bidi/BidiTestData$LD305.ser | Bin 0 -> 3843 bytes .../fop/complexscripts/bidi/BidiTestData$LD306.ser | Bin 0 -> 4383 bytes .../fop/complexscripts/bidi/BidiTestData$LD307.ser | Bin 0 -> 423 bytes .../fop/complexscripts/bidi/BidiTestData$LD308.ser | Bin 0 -> 243 bytes .../fop/complexscripts/bidi/BidiTestData$LD309.ser | Bin 0 -> 36783 bytes .../fop/complexscripts/bidi/BidiTestData$LD31.ser | Bin 0 -> 2679 bytes .../fop/complexscripts/bidi/BidiTestData$LD310.ser | Bin 0 -> 9603 bytes .../fop/complexscripts/bidi/BidiTestData$LD311.ser | Bin 0 -> 6903 bytes .../fop/complexscripts/bidi/BidiTestData$LD312.ser | Bin 0 -> 423 bytes .../fop/complexscripts/bidi/BidiTestData$LD313.ser | Bin 0 -> 243 bytes .../fop/complexscripts/bidi/BidiTestData$LD314.ser | Bin 0 -> 15003 bytes .../fop/complexscripts/bidi/BidiTestData$LD315.ser | Bin 0 -> 32103 bytes .../fop/complexscripts/bidi/BidiTestData$LD316.ser | Bin 0 -> 5643 bytes .../fop/complexscripts/bidi/BidiTestData$LD317.ser | Bin 0 -> 14103 bytes .../fop/complexscripts/bidi/BidiTestData$LD318.ser | Bin 0 -> 3843 bytes .../fop/complexscripts/bidi/BidiTestData$LD319.ser | Bin 0 -> 33183 bytes .../fop/complexscripts/bidi/BidiTestData$LD32.ser | Bin 0 -> 3495 bytes .../fop/complexscripts/bidi/BidiTestData$LD320.ser | Bin 0 -> 2943 bytes .../fop/complexscripts/bidi/BidiTestData$LD321.ser | Bin 0 -> 1503 bytes .../fop/complexscripts/bidi/BidiTestData$LD322.ser | Bin 0 -> 1143 bytes .../fop/complexscripts/bidi/BidiTestData$LD323.ser | Bin 0 -> 1863 bytes .../fop/complexscripts/bidi/BidiTestData$LD324.ser | Bin 0 -> 1143 bytes .../fop/complexscripts/bidi/BidiTestData$LD325.ser | Bin 0 -> 783 bytes .../fop/complexscripts/bidi/BidiTestData$LD326.ser | Bin 0 -> 603 bytes .../fop/complexscripts/bidi/BidiTestData$LD327.ser | Bin 0 -> 1143 bytes .../fop/complexscripts/bidi/BidiTestData$LD328.ser | Bin 0 -> 423 bytes .../fop/complexscripts/bidi/BidiTestData$LD329.ser | Bin 0 -> 423 bytes .../fop/complexscripts/bidi/BidiTestData$LD33.ser | Bin 0 -> 1943 bytes .../fop/complexscripts/bidi/BidiTestData$LD330.ser | Bin 0 -> 13743 bytes .../fop/complexscripts/bidi/BidiTestData$LD331.ser | Bin 0 -> 1023 bytes .../fop/complexscripts/bidi/BidiTestData$LD332.ser | Bin 0 -> 783 bytes .../fop/complexscripts/bidi/BidiTestData$LD333.ser | Bin 0 -> 7903 bytes .../fop/complexscripts/bidi/BidiTestData$LD334.ser | Bin 0 -> 1743 bytes .../fop/complexscripts/bidi/BidiTestData$LD335.ser | Bin 0 -> 5303 bytes .../fop/complexscripts/bidi/BidiTestData$LD336.ser | Bin 0 -> 623 bytes .../fop/complexscripts/bidi/BidiTestData$LD337.ser | Bin 0 -> 343 bytes .../fop/complexscripts/bidi/BidiTestData$LD338.ser | Bin 0 -> 5103 bytes .../fop/complexscripts/bidi/BidiTestData$LD339.ser | Bin 0 -> 87543 bytes .../fop/complexscripts/bidi/BidiTestData$LD34.ser | Bin 0 -> 2119 bytes .../fop/complexscripts/bidi/BidiTestData$LD340.ser | Bin 0 -> 28143 bytes .../fop/complexscripts/bidi/BidiTestData$LD341.ser | Bin 0 -> 4063 bytes .../fop/complexscripts/bidi/BidiTestData$LD342.ser | Bin 0 -> 57343 bytes .../fop/complexscripts/bidi/BidiTestData$LD343.ser | Bin 0 -> 37923 bytes .../fop/complexscripts/bidi/BidiTestData$LD344.ser | Bin 0 -> 30843 bytes .../fop/complexscripts/bidi/BidiTestData$LD345.ser | Bin 0 -> 6543 bytes .../fop/complexscripts/bidi/BidiTestData$LD346.ser | Bin 0 -> 3303 bytes .../fop/complexscripts/bidi/BidiTestData$LD347.ser | Bin 0 -> 24183 bytes .../fop/complexscripts/bidi/BidiTestData$LD348.ser | Bin 0 -> 14223 bytes .../fop/complexscripts/bidi/BidiTestData$LD349.ser | Bin 0 -> 2263 bytes .../fop/complexscripts/bidi/BidiTestData$LD35.ser | Bin 0 -> 1559 bytes .../fop/complexscripts/bidi/BidiTestData$LD350.ser | Bin 0 -> 16743 bytes .../fop/complexscripts/bidi/BidiTestData$LD351.ser | Bin 0 -> 13863 bytes .../fop/complexscripts/bidi/BidiTestData$LD352.ser | Bin 0 -> 9943 bytes .../fop/complexscripts/bidi/BidiTestData$LD353.ser | Bin 0 -> 2143 bytes .../fop/complexscripts/bidi/BidiTestData$LD354.ser | Bin 0 -> 6143 bytes .../fop/complexscripts/bidi/BidiTestData$LD355.ser | Bin 0 -> 1063 bytes .../fop/complexscripts/bidi/BidiTestData$LD356.ser | Bin 0 -> 1103 bytes .../fop/complexscripts/bidi/BidiTestData$LD357.ser | Bin 0 -> 143 bytes .../fop/complexscripts/bidi/BidiTestData$LD358.ser | Bin 0 -> 103 bytes .../fop/complexscripts/bidi/BidiTestData$LD359.ser | Bin 0 -> 4023 bytes .../fop/complexscripts/bidi/BidiTestData$LD36.ser | Bin 0 -> 727 bytes .../fop/complexscripts/bidi/BidiTestData$LD360.ser | Bin 0 -> 43423 bytes .../fop/complexscripts/bidi/BidiTestData$LD361.ser | Bin 0 -> 13403 bytes .../fop/complexscripts/bidi/BidiTestData$LD362.ser | Bin 0 -> 3483 bytes .../fop/complexscripts/bidi/BidiTestData$LD363.ser | Bin 0 -> 783 bytes .../fop/complexscripts/bidi/BidiTestData$LD364.ser | Bin 0 -> 3703 bytes .../fop/complexscripts/bidi/BidiTestData$LD365.ser | Bin 0 -> 19003 bytes .../fop/complexscripts/bidi/BidiTestData$LD366.ser | Bin 0 -> 35223 bytes .../fop/complexscripts/bidi/BidiTestData$LD367.ser | Bin 0 -> 2943 bytes .../fop/complexscripts/bidi/BidiTestData$LD368.ser | Bin 0 -> 1503 bytes .../fop/complexscripts/bidi/BidiTestData$LD369.ser | Bin 0 -> 303 bytes .../fop/complexscripts/bidi/BidiTestData$LD37.ser | Bin 0 -> 215 bytes .../fop/complexscripts/bidi/BidiTestData$LD370.ser | Bin 0 -> 10323 bytes .../fop/complexscripts/bidi/BidiTestData$LD371.ser | Bin 0 -> 1863 bytes .../fop/complexscripts/bidi/BidiTestData$LD372.ser | Bin 0 -> 31023 bytes .../fop/complexscripts/bidi/BidiTestData$LD373.ser | Bin 0 -> 4923 bytes .../fop/complexscripts/bidi/BidiTestData$LD374.ser | Bin 0 -> 183 bytes .../fop/complexscripts/bidi/BidiTestData$LD375.ser | Bin 0 -> 2223 bytes .../fop/complexscripts/bidi/BidiTestData$LD376.ser | Bin 0 -> 1143 bytes .../fop/complexscripts/bidi/BidiTestData$LD377.ser | Bin 0 -> 3483 bytes .../fop/complexscripts/bidi/BidiTestData$LD378.ser | Bin 0 -> 2943 bytes .../fop/complexscripts/bidi/BidiTestData$LD379.ser | Bin 0 -> 8703 bytes .../fop/complexscripts/bidi/BidiTestData$LD38.ser | Bin 0 -> 25983 bytes .../fop/complexscripts/bidi/BidiTestData$LD380.ser | Bin 0 -> 783 bytes .../fop/complexscripts/bidi/BidiTestData$LD381.ser | Bin 0 -> 423 bytes .../fop/complexscripts/bidi/BidiTestData$LD382.ser | Bin 0 -> 4863 bytes .../fop/complexscripts/bidi/BidiTestData$LD383.ser | Bin 0 -> 1323 bytes .../fop/complexscripts/bidi/BidiTestData$LD384.ser | Bin 0 -> 3083 bytes .../fop/complexscripts/bidi/BidiTestData$LD385.ser | Bin 0 -> 383 bytes .../fop/complexscripts/bidi/BidiTestData$LD386.ser | Bin 0 -> 223 bytes .../fop/complexscripts/bidi/BidiTestData$LD387.ser | Bin 0 -> 1743 bytes .../fop/complexscripts/bidi/BidiTestData$LD388.ser | Bin 0 -> 24903 bytes .../fop/complexscripts/bidi/BidiTestData$LD389.ser | Bin 0 -> 6663 bytes .../fop/complexscripts/bidi/BidiTestData$LD39.ser | Bin 0 -> 7831 bytes .../fop/complexscripts/bidi/BidiTestData$LD390.ser | Bin 0 -> 1503 bytes .../fop/complexscripts/bidi/BidiTestData$LD391.ser | Bin 0 -> 16843 bytes .../fop/complexscripts/bidi/BidiTestData$LD392.ser | Bin 0 -> 8803 bytes .../fop/complexscripts/bidi/BidiTestData$LD393.ser | Bin 0 -> 8603 bytes .../fop/complexscripts/bidi/BidiTestData$LD394.ser | Bin 0 -> 1803 bytes .../fop/complexscripts/bidi/BidiTestData$LD395.ser | Bin 0 -> 1983 bytes .../fop/complexscripts/bidi/BidiTestData$LD396.ser | Bin 0 -> 12783 bytes .../fop/complexscripts/bidi/BidiTestData$LD397.ser | Bin 0 -> 9423 bytes .../fop/complexscripts/bidi/BidiTestData$LD398.ser | Bin 0 -> 1263 bytes .../fop/complexscripts/bidi/BidiTestData$LD399.ser | Bin 0 -> 9223 bytes .../fop/complexscripts/bidi/BidiTestData$LD4.ser | Bin 0 -> 479 bytes .../fop/complexscripts/bidi/BidiTestData$LD40.ser | Bin 0 -> 1783 bytes .../fop/complexscripts/bidi/BidiTestData$LD400.ser | Bin 0 -> 9763 bytes .../fop/complexscripts/bidi/BidiTestData$LD401.ser | Bin 0 -> 5583 bytes .../fop/complexscripts/bidi/BidiTestData$LD402.ser | Bin 0 -> 1283 bytes .../fop/complexscripts/bidi/BidiTestData$LD403.ser | Bin 0 -> 3743 bytes .../fop/complexscripts/bidi/BidiTestData$LD404.ser | Bin 0 -> 643 bytes .../fop/complexscripts/bidi/BidiTestData$LD405.ser | Bin 0 -> 583 bytes .../fop/complexscripts/bidi/BidiTestData$LD406.ser | Bin 0 -> 103 bytes .../fop/complexscripts/bidi/BidiTestData$LD407.ser | Bin 0 -> 83 bytes .../fop/complexscripts/bidi/BidiTestData$LD408.ser | Bin 0 -> 1723 bytes .../fop/complexscripts/bidi/BidiTestData$LD409.ser | Bin 0 -> 14023 bytes .../fop/complexscripts/bidi/BidiTestData$LD41.ser | Bin 0 -> 919 bytes .../fop/complexscripts/bidi/BidiTestData$LD410.ser | Bin 0 -> 3743 bytes .../fop/complexscripts/bidi/BidiTestData$LD411.ser | Bin 0 -> 1203 bytes .../fop/complexscripts/bidi/BidiTestData$LD412.ser | Bin 0 -> 303 bytes .../fop/complexscripts/bidi/BidiTestData$LD413.ser | Bin 0 -> 1983 bytes .../fop/complexscripts/bidi/BidiTestData$LD414.ser | Bin 0 -> 8263 bytes .../fop/complexscripts/bidi/BidiTestData$LD415.ser | Bin 0 -> 13423 bytes .../fop/complexscripts/bidi/BidiTestData$LD416.ser | Bin 0 -> 1023 bytes .../fop/complexscripts/bidi/BidiTestData$LD417.ser | Bin 0 -> 543 bytes .../fop/complexscripts/bidi/BidiTestData$LD418.ser | Bin 0 -> 183 bytes .../fop/complexscripts/bidi/BidiTestData$LD419.ser | Bin 0 -> 3483 bytes .../fop/complexscripts/bidi/BidiTestData$LD42.ser | Bin 0 -> 4663 bytes .../fop/complexscripts/bidi/BidiTestData$LD420.ser | Bin 0 -> 663 bytes .../fop/complexscripts/bidi/BidiTestData$LD421.ser | Bin 0 -> 10383 bytes .../fop/complexscripts/bidi/BidiTestData$LD422.ser | Bin 0 -> 1683 bytes .../fop/complexscripts/bidi/BidiTestData$LD423.ser | Bin 0 -> 123 bytes .../fop/complexscripts/bidi/BidiTestData$LD424.ser | Bin 0 -> 783 bytes .../fop/complexscripts/bidi/BidiTestData$LD425.ser | Bin 0 -> 423 bytes .../fop/complexscripts/bidi/BidiTestData$LD426.ser | Bin 0 -> 1203 bytes .../fop/complexscripts/bidi/BidiTestData$LD427.ser | Bin 0 -> 1023 bytes .../fop/complexscripts/bidi/BidiTestData$LD428.ser | Bin 0 -> 33423 bytes .../fop/complexscripts/bidi/BidiTestData$LD429.ser | Bin 0 -> 7223 bytes .../fop/complexscripts/bidi/BidiTestData$LD43.ser | Bin 0 -> 3079 bytes .../fop/complexscripts/bidi/BidiTestData$LD430.ser | Bin 0 -> 4103 bytes .../fop/complexscripts/bidi/BidiTestData$LD431.ser | Bin 0 -> 143 bytes .../fop/complexscripts/bidi/BidiTestData$LD432.ser | Bin 0 -> 103 bytes .../fop/complexscripts/bidi/BidiTestData$LD433.ser | Bin 0 -> 6843 bytes .../fop/complexscripts/bidi/BidiTestData$LD434.ser | Bin 0 -> 5543 bytes .../fop/complexscripts/bidi/BidiTestData$LD435.ser | Bin 0 -> 1963 bytes .../fop/complexscripts/bidi/BidiTestData$LD436.ser | Bin 0 -> 4503 bytes .../fop/complexscripts/bidi/BidiTestData$LD437.ser | Bin 0 -> 1123 bytes .../fop/complexscripts/bidi/BidiTestData$LD438.ser | Bin 0 -> 4383 bytes .../fop/complexscripts/bidi/BidiTestData$LD439.ser | Bin 0 -> 383 bytes .../fop/complexscripts/bidi/BidiTestData$LD44.ser | Bin 0 -> 3223 bytes .../fop/complexscripts/bidi/BidiTestData$LD440.ser | Bin 0 -> 223 bytes .../fop/complexscripts/bidi/BidiTestData$LD441.ser | Bin 0 -> 183 bytes .../fop/complexscripts/bidi/BidiTestData$LD442.ser | Bin 0 -> 263 bytes .../fop/complexscripts/bidi/BidiTestData$LD443.ser | Bin 0 -> 183 bytes .../fop/complexscripts/bidi/BidiTestData$LD444.ser | Bin 0 -> 143 bytes .../fop/complexscripts/bidi/BidiTestData$LD445.ser | Bin 0 -> 123 bytes .../fop/complexscripts/bidi/BidiTestData$LD446.ser | Bin 0 -> 183 bytes .../fop/complexscripts/bidi/BidiTestData$LD447.ser | Bin 0 -> 103 bytes .../fop/complexscripts/bidi/BidiTestData$LD448.ser | Bin 0 -> 103 bytes .../fop/complexscripts/bidi/BidiTestData$LD449.ser | Bin 0 -> 7223 bytes .../fop/complexscripts/bidi/BidiTestData$LD45.ser | Bin 0 -> 343 bytes .../fop/complexscripts/bidi/BidiTestData$LD450.ser | Bin 0 -> 3363 bytes .../fop/complexscripts/bidi/BidiTestData$LD451.ser | Bin 0 -> 723 bytes .../fop/complexscripts/bidi/BidiTestData$LD452.ser | Bin 0 -> 11943 bytes .../fop/complexscripts/bidi/BidiTestData$LD453.ser | Bin 0 -> 66583 bytes .../fop/complexscripts/bidi/BidiTestData$LD454.ser | Bin 0 -> 13783 bytes .../fop/complexscripts/bidi/BidiTestData$LD455.ser | Bin 0 -> 823 bytes .../fop/complexscripts/bidi/BidiTestData$LD456.ser | Bin 0 -> 223 bytes .../fop/complexscripts/bidi/BidiTestData$LD457.ser | Bin 0 -> 2683 bytes .../fop/complexscripts/bidi/BidiTestData$LD458.ser | Bin 0 -> 12803 bytes .../fop/complexscripts/bidi/BidiTestData$LD459.ser | Bin 0 -> 10183 bytes .../fop/complexscripts/bidi/BidiTestData$LD46.ser | Bin 0 -> 199 bytes .../fop/complexscripts/bidi/BidiTestData$LD460.ser | Bin 0 -> 383 bytes .../fop/complexscripts/bidi/BidiTestData$LD461.ser | Bin 0 -> 223 bytes .../fop/complexscripts/bidi/BidiTestData$LD462.ser | Bin 0 -> 1203 bytes .../fop/complexscripts/bidi/BidiTestData$LD463.ser | Bin 0 -> 263 bytes .../fop/complexscripts/bidi/BidiTestData$LD464.ser | Bin 0 -> 3503 bytes .../fop/complexscripts/bidi/BidiTestData$LD465.ser | Bin 0 -> 603 bytes .../fop/complexscripts/bidi/BidiTestData$LD466.ser | Bin 0 -> 303 bytes .../fop/complexscripts/bidi/BidiTestData$LD467.ser | Bin 0 -> 183 bytes .../fop/complexscripts/bidi/BidiTestData$LD468.ser | Bin 0 -> 443 bytes .../fop/complexscripts/bidi/BidiTestData$LD469.ser | Bin 0 -> 383 bytes .../fop/complexscripts/bidi/BidiTestData$LD47.ser | Bin 0 -> 38943 bytes .../fop/complexscripts/bidi/BidiTestData$LD470.ser | Bin 0 -> 5663 bytes .../fop/complexscripts/bidi/BidiTestData$LD471.ser | Bin 0 -> 723 bytes .../fop/complexscripts/bidi/BidiTestData$LD472.ser | Bin 0 -> 3343 bytes .../fop/complexscripts/bidi/BidiTestData$LD473.ser | Bin 0 -> 343 bytes .../fop/complexscripts/bidi/BidiTestData$LD474.ser | Bin 0 -> 203 bytes .../fop/complexscripts/bidi/BidiTestData$LD475.ser | Bin 0 -> 1723 bytes .../fop/complexscripts/bidi/BidiTestData$LD476.ser | Bin 0 -> 14103 bytes .../fop/complexscripts/bidi/BidiTestData$LD477.ser | Bin 0 -> 6163 bytes .../fop/complexscripts/bidi/BidiTestData$LD478.ser | Bin 0 -> 343 bytes .../fop/complexscripts/bidi/BidiTestData$LD479.ser | Bin 0 -> 203 bytes .../fop/complexscripts/bidi/BidiTestData$LD48.ser | Bin 0 -> 1399 bytes .../fop/complexscripts/bidi/BidiTestData$LD480.ser | Bin 0 -> 11583 bytes .../fop/complexscripts/bidi/BidiTestData$LD481.ser | Bin 0 -> 16383 bytes .../fop/complexscripts/bidi/BidiTestData$LD482.ser | Bin 0 -> 37903 bytes .../fop/complexscripts/bidi/BidiTestData$LD483.ser | Bin 0 -> 2623 bytes .../fop/complexscripts/bidi/BidiTestData$LD484.ser | Bin 0 -> 1343 bytes .../fop/complexscripts/bidi/BidiTestData$LD485.ser | Bin 0 -> 1023 bytes .../fop/complexscripts/bidi/BidiTestData$LD486.ser | Bin 0 -> 1023 bytes .../fop/complexscripts/bidi/BidiTestData$LD487.ser | Bin 0 -> 1663 bytes .../fop/complexscripts/bidi/BidiTestData$LD488.ser | Bin 0 -> 1023 bytes .../fop/complexscripts/bidi/BidiTestData$LD489.ser | Bin 0 -> 703 bytes .../fop/complexscripts/bidi/BidiTestData$LD49.ser | Bin 0 -> 7831 bytes .../fop/complexscripts/bidi/BidiTestData$LD490.ser | Bin 0 -> 543 bytes .../fop/complexscripts/bidi/BidiTestData$LD491.ser | Bin 0 -> 543 bytes .../fop/complexscripts/bidi/BidiTestData$LD492.ser | Bin 0 -> 1023 bytes .../fop/complexscripts/bidi/BidiTestData$LD493.ser | Bin 0 -> 383 bytes .../fop/complexscripts/bidi/BidiTestData$LD494.ser | Bin 0 -> 383 bytes .../fop/complexscripts/bidi/BidiTestData$LD495.ser | Bin 0 -> 303 bytes .../fop/complexscripts/bidi/BidiTestData$LD496.ser | Bin 0 -> 303 bytes .../fop/complexscripts/bidi/BidiTestData$LD497.ser | Bin 0 -> 143 bytes .../fop/complexscripts/bidi/BidiTestData$LD498.ser | Bin 0 -> 143 bytes .../fop/complexscripts/bidi/BidiTestData$LD499.ser | Bin 0 -> 2343 bytes .../fop/complexscripts/bidi/BidiTestData$LD5.ser | Bin 0 -> 695 bytes .../fop/complexscripts/bidi/BidiTestData$LD50.ser | Bin 0 -> 2551 bytes .../fop/complexscripts/bidi/BidiTestData$LD500.ser | Bin 0 -> 303 bytes .../fop/complexscripts/bidi/BidiTestData$LD501.ser | Bin 0 -> 3123 bytes .../fop/complexscripts/bidi/BidiTestData$LD502.ser | Bin 0 -> 563 bytes .../fop/complexscripts/bidi/BidiTestData$LD503.ser | Bin 0 -> 663 bytes .../fop/complexscripts/bidi/BidiTestData$LD504.ser | Bin 0 -> 663 bytes .../fop/complexscripts/bidi/BidiTestData$LD505.ser | Bin 0 -> 1543 bytes .../fop/complexscripts/bidi/BidiTestData$LD506.ser | Bin 0 -> 143 bytes .../fop/complexscripts/bidi/BidiTestData$LD507.ser | Bin 0 -> 103 bytes .../fop/complexscripts/bidi/BidiTestData$LD508.ser | Bin 0 -> 423 bytes .../fop/complexscripts/bidi/BidiTestData$LD509.ser | Bin 0 -> 10383 bytes .../fop/complexscripts/bidi/BidiTestData$LD51.ser | Bin 0 -> 951 bytes .../fop/complexscripts/bidi/BidiTestData$LD510.ser | Bin 0 -> 663 bytes .../fop/complexscripts/bidi/BidiTestData$LD511.ser | Bin 0 -> 33983 bytes .../fop/complexscripts/bidi/BidiTestData$LD512.ser | Bin 0 -> 4363 bytes .../fop/complexscripts/bidi/BidiTestData$LD513.ser | Bin 0 -> 303 bytes .../fop/complexscripts/bidi/BidiTestData$LD514.ser | Bin 0 -> 1683 bytes .../fop/complexscripts/bidi/BidiTestData$LD515.ser | Bin 0 -> 443 bytes .../fop/complexscripts/bidi/BidiTestData$LD516.ser | Bin 0 -> 2863 bytes .../fop/complexscripts/bidi/BidiTestData$LD517.ser | Bin 0 -> 2423 bytes .../fop/complexscripts/bidi/BidiTestData$LD518.ser | Bin 0 -> 183 bytes .../fop/complexscripts/bidi/BidiTestData$LD519.ser | Bin 0 -> 203 bytes .../fop/complexscripts/bidi/BidiTestData$LD52.ser | Bin 0 -> 5207 bytes .../fop/complexscripts/bidi/BidiTestData$LD520.ser | Bin 0 -> 103 bytes .../fop/complexscripts/bidi/BidiTestData$LD521.ser | Bin 0 -> 83 bytes .../fop/complexscripts/bidi/BidiTestData$LD522.ser | Bin 0 -> 543 bytes .../fop/complexscripts/bidi/BidiTestData$LD523.ser | Bin 0 -> 203 bytes .../fop/complexscripts/bidi/BidiTestData$LD524.ser | Bin 0 -> 523 bytes .../fop/complexscripts/bidi/BidiTestData$LD525.ser | Bin 0 -> 263 bytes .../fop/complexscripts/bidi/BidiTestData$LD526.ser | Bin 0 -> 423 bytes .../fop/complexscripts/bidi/BidiTestData$LD527.ser | Bin 0 -> 423 bytes .../fop/complexscripts/bidi/BidiTestData$LD528.ser | Bin 0 -> 1043 bytes .../fop/complexscripts/bidi/BidiTestData$LD529.ser | Bin 0 -> 143 bytes .../fop/complexscripts/bidi/BidiTestData$LD53.ser | Bin 0 -> 3431 bytes .../fop/complexscripts/bidi/BidiTestData$LD530.ser | Bin 0 -> 103 bytes .../fop/complexscripts/bidi/BidiTestData$LD531.ser | Bin 0 -> 183 bytes .../fop/complexscripts/bidi/BidiTestData$LD532.ser | Bin 0 -> 1203 bytes .../fop/complexscripts/bidi/BidiTestData$LD533.ser | Bin 0 -> 263 bytes .../fop/complexscripts/bidi/BidiTestData$LD534.ser | Bin 0 -> 3183 bytes .../fop/complexscripts/bidi/BidiTestData$LD535.ser | Bin 0 -> 1143 bytes .../fop/complexscripts/bidi/BidiTestData$LD536.ser | Bin 0 -> 183 bytes .../fop/complexscripts/bidi/BidiTestData$LD537.ser | Bin 0 -> 1023 bytes .../fop/complexscripts/bidi/BidiTestData$LD538.ser | Bin 0 -> 303 bytes .../fop/complexscripts/bidi/BidiTestData$LD539.ser | Bin 0 -> 1703 bytes .../fop/complexscripts/bidi/BidiTestData$LD54.ser | Bin 0 -> 2791 bytes .../fop/complexscripts/bidi/BidiTestData$LD540.ser | Bin 0 -> 1723 bytes .../fop/complexscripts/bidi/BidiTestData$LD541.ser | Bin 0 -> 145863 bytes .../fop/complexscripts/bidi/BidiTestData$LD542.ser | Bin 0 -> 29223 bytes .../fop/complexscripts/bidi/BidiTestData$LD543.ser | Bin 0 -> 14643 bytes .../fop/complexscripts/bidi/BidiTestData$LD544.ser | Bin 0 -> 25983 bytes .../fop/complexscripts/bidi/BidiTestData$LD545.ser | Bin 0 -> 9783 bytes .../fop/complexscripts/bidi/BidiTestData$LD546.ser | Bin 0 -> 6543 bytes .../fop/complexscripts/bidi/BidiTestData$LD547.ser | Bin 0 -> 14643 bytes .../fop/complexscripts/bidi/BidiTestData$LD548.ser | Bin 0 -> 3303 bytes .../fop/complexscripts/bidi/BidiTestData$LD549.ser | Bin 0 -> 3303 bytes .../fop/complexscripts/bidi/BidiTestData$LD55.ser | Bin 0 -> 631 bytes .../fop/complexscripts/bidi/BidiTestData$LD550.ser | Bin 0 -> 23103 bytes .../fop/complexscripts/bidi/BidiTestData$LD551.ser | Bin 0 -> 1503 bytes .../fop/complexscripts/bidi/BidiTestData$LD552.ser | Bin 0 -> 1143 bytes .../fop/complexscripts/bidi/BidiTestData$LD553.ser | Bin 0 -> 8703 bytes .../fop/complexscripts/bidi/BidiTestData$LD554.ser | Bin 0 -> 6903 bytes .../fop/complexscripts/bidi/BidiTestData$LD555.ser | Bin 0 -> 5643 bytes .../fop/complexscripts/bidi/BidiTestData$LD556.ser | Bin 0 -> 5643 bytes .../fop/complexscripts/bidi/BidiTestData$LD557.ser | Bin 0 -> 1503 bytes .../fop/complexscripts/bidi/BidiTestData$LD558.ser | Bin 0 -> 2583 bytes .../fop/complexscripts/bidi/BidiTestData$LD559.ser | Bin 0 -> 14463 bytes .../fop/complexscripts/bidi/BidiTestData$LD56.ser | Bin 0 -> 38943 bytes .../fop/complexscripts/bidi/BidiTestData$LD560.ser | Bin 0 -> 1143 bytes .../fop/complexscripts/bidi/BidiTestData$LD561.ser | Bin 0 -> 603 bytes .../fop/complexscripts/bidi/BidiTestData$LD562.ser | Bin 0 -> 2943 bytes .../fop/complexscripts/bidi/BidiTestData$LD563.ser | Bin 0 -> 2943 bytes .../fop/complexscripts/bidi/BidiTestData$LD564.ser | Bin 0 -> 1503 bytes .../fop/complexscripts/bidi/BidiTestData$LD565.ser | Bin 0 -> 3303 bytes .../fop/complexscripts/bidi/BidiTestData$LD566.ser | Bin 0 -> 783 bytes .../fop/complexscripts/bidi/BidiTestData$LD567.ser | Bin 0 -> 963 bytes .../fop/complexscripts/bidi/BidiTestData$LD568.ser | Bin 0 -> 21183 bytes .../fop/complexscripts/bidi/BidiTestData$LD569.ser | Bin 0 -> 1423 bytes .../fop/complexscripts/bidi/BidiTestData$LD57.ser | Bin 0 -> 823 bytes .../fop/complexscripts/bidi/BidiTestData$LD570.ser | Bin 0 -> 823 bytes .../fop/complexscripts/bidi/BidiTestData$LD571.ser | Bin 0 -> 1343 bytes .../fop/complexscripts/bidi/BidiTestData$LD572.ser | Bin 0 -> 1023 bytes .../fop/complexscripts/bidi/BidiTestData$LD573.ser | Bin 0 -> 843 bytes .../fop/complexscripts/bidi/BidiTestData$LD574.ser | Bin 0 -> 1043 bytes .../fop/complexscripts/bidi/BidiTestData$LD575.ser | Bin 0 -> 303 bytes .../fop/complexscripts/bidi/BidiTestData$LD576.ser | Bin 0 -> 423 bytes .../fop/complexscripts/bidi/BidiTestData$LD577.ser | Bin 0 -> 7743 bytes .../fop/complexscripts/bidi/BidiTestData$LD578.ser | Bin 0 -> 863 bytes .../fop/complexscripts/bidi/BidiTestData$LD579.ser | Bin 0 -> 743 bytes .../fop/complexscripts/bidi/BidiTestData$LD58.ser | Bin 0 -> 2263 bytes .../fop/complexscripts/bidi/BidiTestData$LD580.ser | Bin 0 -> 6143 bytes .../fop/complexscripts/bidi/BidiTestData$LD581.ser | Bin 0 -> 145863 bytes .../fop/complexscripts/bidi/BidiTestData$LD582.ser | Bin 0 -> 42323 bytes .../fop/complexscripts/bidi/BidiTestData$LD583.ser | Bin 0 -> 4883 bytes .../fop/complexscripts/bidi/BidiTestData$LD584.ser | Bin 0 -> 41063 bytes .../fop/complexscripts/bidi/BidiTestData$LD585.ser | Bin 0 -> 21023 bytes .../fop/complexscripts/bidi/BidiTestData$LD586.ser | Bin 0 -> 5003 bytes .../fop/complexscripts/bidi/BidiTestData$LD587.ser | Bin 0 -> 383 bytes .../fop/complexscripts/bidi/BidiTestData$LD588.ser | Bin 0 -> 303 bytes .../fop/complexscripts/bidi/BidiTestData$LD589.ser | Bin 0 -> 1343 bytes .../fop/complexscripts/bidi/BidiTestData$LD59.ser | Bin 0 -> 1399 bytes .../fop/complexscripts/bidi/BidiTestData$LD590.ser | Bin 0 -> 40263 bytes .../fop/complexscripts/bidi/BidiTestData$LD591.ser | Bin 0 -> 9643 bytes .../fop/complexscripts/bidi/BidiTestData$LD592.ser | Bin 0 -> 2203 bytes .../fop/complexscripts/bidi/BidiTestData$LD593.ser | Bin 0 -> 20403 bytes .../fop/complexscripts/bidi/BidiTestData$LD594.ser | Bin 0 -> 13163 bytes .../fop/complexscripts/bidi/BidiTestData$LD595.ser | Bin 0 -> 14463 bytes .../fop/complexscripts/bidi/BidiTestData$LD596.ser | Bin 0 -> 1343 bytes .../fop/complexscripts/bidi/BidiTestData$LD597.ser | Bin 0 -> 703 bytes .../fop/complexscripts/bidi/BidiTestData$LD598.ser | Bin 0 -> 1023 bytes .../fop/complexscripts/bidi/BidiTestData$LD599.ser | Bin 0 -> 663 bytes .../fop/complexscripts/bidi/BidiTestData$LD6.ser | Bin 0 -> 695 bytes .../fop/complexscripts/bidi/BidiTestData$LD60.ser | Bin 0 -> 535 bytes .../fop/complexscripts/bidi/BidiTestData$LD600.ser | Bin 0 -> 423 bytes .../fop/complexscripts/bidi/BidiTestData$LD601.ser | Bin 0 -> 603 bytes .../fop/complexscripts/bidi/BidiTestData$LD602.ser | Bin 0 -> 183 bytes .../fop/complexscripts/bidi/BidiTestData$LD603.ser | Bin 0 -> 183 bytes .../fop/complexscripts/bidi/BidiTestData$LD604.ser | Bin 0 -> 2623 bytes .../fop/complexscripts/bidi/BidiTestData$LD605.ser | Bin 0 -> 383 bytes .../fop/complexscripts/bidi/BidiTestData$LD606.ser | Bin 0 -> 263 bytes .../fop/complexscripts/bidi/BidiTestData$LD607.ser | Bin 0 -> 2623 bytes .../fop/complexscripts/bidi/BidiTestData$LD608.ser | Bin 0 -> 41463 bytes .../fop/complexscripts/bidi/BidiTestData$LD609.ser | Bin 0 -> 10583 bytes .../fop/complexscripts/bidi/BidiTestData$LD61.ser | Bin 0 -> 1735 bytes .../fop/complexscripts/bidi/BidiTestData$LD610.ser | Bin 0 -> 1403 bytes .../fop/complexscripts/bidi/BidiTestData$LD611.ser | Bin 0 -> 9723 bytes .../fop/complexscripts/bidi/BidiTestData$LD612.ser | Bin 0 -> 5203 bytes .../fop/complexscripts/bidi/BidiTestData$LD613.ser | Bin 0 -> 3263 bytes .../fop/complexscripts/bidi/BidiTestData$LD614.ser | Bin 0 -> 303 bytes .../fop/complexscripts/bidi/BidiTestData$LD615.ser | Bin 0 -> 183 bytes .../fop/complexscripts/bidi/BidiTestData$LD616.ser | Bin 0 -> 703 bytes .../fop/complexscripts/bidi/BidiTestData$LD617.ser | Bin 0 -> 21263 bytes .../fop/complexscripts/bidi/BidiTestData$LD618.ser | Bin 0 -> 5303 bytes .../fop/complexscripts/bidi/BidiTestData$LD619.ser | Bin 0 -> 963 bytes .../fop/complexscripts/bidi/BidiTestData$LD62.ser | Bin 0 -> 1367 bytes .../fop/complexscripts/bidi/BidiTestData$LD620.ser | Bin 0 -> 13383 bytes .../fop/complexscripts/bidi/BidiTestData$LD621.ser | Bin 0 -> 9623 bytes .../fop/complexscripts/bidi/BidiTestData$LD63.ser | Bin 0 -> 967 bytes .../fop/complexscripts/bidi/BidiTestData$LD64.ser | Bin 0 -> 247 bytes .../fop/complexscripts/bidi/BidiTestData$LD65.ser | Bin 0 -> 13023 bytes .../fop/complexscripts/bidi/BidiTestData$LD66.ser | Bin 0 -> 3319 bytes .../fop/complexscripts/bidi/BidiTestData$LD67.ser | Bin 0 -> 903 bytes .../fop/complexscripts/bidi/BidiTestData$LD68.ser | Bin 0 -> 663 bytes .../fop/complexscripts/bidi/BidiTestData$LD69.ser | Bin 0 -> 87 bytes .../fop/complexscripts/bidi/BidiTestData$LD7.ser | Bin 0 -> 263 bytes .../fop/complexscripts/bidi/BidiTestData$LD70.ser | Bin 0 -> 71 bytes .../fop/complexscripts/bidi/BidiTestData$LD71.ser | Bin 0 -> 18783 bytes .../fop/complexscripts/bidi/BidiTestData$LD72.ser | Bin 0 -> 1383 bytes .../fop/complexscripts/bidi/BidiTestData$LD73.ser | Bin 0 -> 5975 bytes .../fop/complexscripts/bidi/BidiTestData$LD74.ser | Bin 0 -> 1527 bytes .../fop/complexscripts/bidi/BidiTestData$LD75.ser | Bin 0 -> 359 bytes .../fop/complexscripts/bidi/BidiTestData$LD76.ser | Bin 0 -> 119 bytes .../fop/complexscripts/bidi/BidiTestData$LD77.ser | Bin 0 -> 31023 bytes .../fop/complexscripts/bidi/BidiTestData$LD78.ser | Bin 0 -> 1303 bytes .../fop/complexscripts/bidi/BidiTestData$LD79.ser | Bin 0 -> 1975 bytes .../fop/complexscripts/bidi/BidiTestData$LD8.ser | Bin 0 -> 431 bytes .../fop/complexscripts/bidi/BidiTestData$LD80.ser | Bin 0 -> 3383 bytes .../fop/complexscripts/bidi/BidiTestData$LD81.ser | Bin 0 -> 311 bytes .../fop/complexscripts/bidi/BidiTestData$LD82.ser | Bin 0 -> 183 bytes .../fop/complexscripts/bidi/BidiTestData$LD83.ser | Bin 0 -> 18783 bytes .../fop/complexscripts/bidi/BidiTestData$LD84.ser | Bin 0 -> 151 bytes .../fop/complexscripts/bidi/BidiTestData$LD85.ser | Bin 0 -> 967 bytes .../fop/complexscripts/bidi/BidiTestData$LD86.ser | Bin 0 -> 215 bytes .../fop/complexscripts/bidi/BidiTestData$LD87.ser | Bin 0 -> 2807 bytes .../fop/complexscripts/bidi/BidiTestData$LD88.ser | Bin 0 -> 487 bytes .../fop/complexscripts/bidi/BidiTestData$LD89.ser | Bin 0 -> 13743 bytes .../fop/complexscripts/bidi/BidiTestData$LD9.ser | Bin 0 -> 635 bytes .../fop/complexscripts/bidi/BidiTestData$LD90.ser | Bin 0 -> 103 bytes .../fop/complexscripts/bidi/BidiTestData$LD91.ser | Bin 0 -> 247 bytes .../fop/complexscripts/bidi/BidiTestData$LD92.ser | Bin 0 -> 151 bytes .../fop/complexscripts/bidi/BidiTestData$LD93.ser | Bin 0 -> 359 bytes .../fop/complexscripts/bidi/BidiTestData$LD94.ser | Bin 0 -> 311 bytes .../fop/complexscripts/bidi/BidiTestData$LD95.ser | Bin 0 -> 2943 bytes .../fop/complexscripts/bidi/BidiTestData$LD96.ser | Bin 0 -> 15423 bytes .../fop/complexscripts/bidi/BidiTestData$LD97.ser | Bin 0 -> 21543 bytes .../fop/complexscripts/bidi/BidiTestData$LD98.ser | Bin 0 -> 14223 bytes .../fop/complexscripts/bidi/BidiTestData$LD99.ser | Bin 0 -> 15543 bytes .../fop/complexscripts/bidi/BidiTestData$TD0.ser | Bin 0 -> 4191 bytes .../fop/complexscripts/bidi/BidiTestData$TD1.ser | Bin 0 -> 39 bytes .../fop/complexscripts/bidi/BidiTestData$TD10.ser | Bin 0 -> 199 bytes .../fop/complexscripts/bidi/BidiTestData$TD11.ser | Bin 0 -> 79 bytes .../fop/complexscripts/bidi/BidiTestData$TD12.ser | Bin 0 -> 135 bytes .../fop/complexscripts/bidi/BidiTestData$TD13.ser | Bin 0 -> 1623 bytes .../fop/complexscripts/bidi/BidiTestData$TD14.ser | Bin 0 -> 127 bytes .../fop/complexscripts/bidi/BidiTestData$TD15.ser | Bin 0 -> 71 bytes .../fop/complexscripts/bidi/BidiTestData$TD16.ser | Bin 0 -> 55 bytes .../fop/complexscripts/bidi/BidiTestData$TD17.ser | Bin 0 -> 95 bytes .../fop/complexscripts/bidi/BidiTestData$TD18.ser | Bin 0 -> 1495 bytes .../fop/complexscripts/bidi/BidiTestData$TD2.ser | Bin 0 -> 39 bytes .../fop/complexscripts/bidi/BidiTestData$TD3.ser | Bin 0 -> 407 bytes .../fop/complexscripts/bidi/BidiTestData$TD4.ser | Bin 0 -> 199 bytes .../fop/complexscripts/bidi/BidiTestData$TD5.ser | Bin 0 -> 39 bytes .../fop/complexscripts/bidi/BidiTestData$TD6.ser | Bin 0 -> 39 bytes .../fop/complexscripts/bidi/BidiTestData$TD7.ser | Bin 0 -> 39 bytes .../fop/complexscripts/bidi/BidiTestData$TD8.ser | Bin 0 -> 119 bytes .../fop/complexscripts/bidi/BidiTestData$TD9.ser | Bin 0 -> 103 bytes .../fop/complexscripts/bidi/BidiTestData.java | 74 + .../fop/complexscripts/bidi/BidiTestSuite.java | 35 + .../fop/complexscripts/fonts/FontsTestSuite.java | 39 + .../fop/complexscripts/fonts/GDEFTestCase.java | 3177 + .../fop/complexscripts/fonts/GPOSTestCase.java | 475 + .../fop/complexscripts/fonts/GSUBTestCase.java | 2268 + .../fop/complexscripts/fonts/ttx/TTXFile.java | 3450 + .../complexscripts/fonts/ttx/TTXFileTestCase.java | 52 + .../complexscripts/scripts/ScriptsTestSuite.java | 36 + .../scripts/arabic/ArabicTestCase.java | 195 + .../scripts/arabic/ArabicTestConstants.java | 49 + .../scripts/arabic/GenerateArabicTestData.java | 179 + .../util/NumberConverterTestCase.java | 1564 + .../fop/complexscripts/util/UtilTestSuite.java | 34 + .../fop/config/FontsSubstitutionTestCase.java | 3 +- .../apache/fop/fonts/DejaVuLGCSerifTestCase.java | 2 +- .../fop/fonts/truetype/TTFFontLoaderTestCase.java | 7 +- test/layoutengine/disabled-testcases.xml | 6 + ...basic-link_background-image_writing-mode_rl.xml | 54 + ...c-link_external-destination_writing-mode_rl.xml | 48 + ...link_external-destination_writing-mode_rl_2.xml | 58 + .../basic-link_for_toc_writing-mode_rl.xml | 53 + ...-link_height_baseline-shift_writing-mode_rl.xml | 62 + ...ic-link_height_inline-child_writing-mode_rl.xml | 62 + ...sic-link_height_multi-child_writing-mode_rl.xml | 58 + ...asic-link_height_multi-line_writing-mode_rl.xml | 67 + .../basic-link_height_writing-mode_rl.xml | 53 + .../basic-link_internal-desination-next-page.xml | 48 + ...ternal-desination-next-page_writing-mode_rl.xml | 48 + ...ic-link_internal-desination-same-page-after.xml | 44 + ...-desination-same-page-after_writing-mode_rl.xml | 44 + ...c-link_internal-desination-same-page-before.xml | 44 + ...desination-same-page-before_writing-mode_rl.xml | 44 + .../standard-testcases/bidi_propagation_1.xml | 125 + .../block-container_start-indent.xml | 2 + ...lock-container_start-indent_writing-mode_rl.xml | 161 + .../standard-testcases/block_basic_2.xml | 2 +- .../standard-testcases/block_text-align_4.xml | 80 + .../standard-testcases/block_text-align_5.xml | 65 + .../character_writing-mode_rl.xml | 76 + .../inline_background-color_writing-mode_rl.xml | 133 + ...stream-foreign-object_basic_writing-mode_rl.xml | 57 + ...reign-object_border_padding_writing-mode_rl.xml | 96 + ...oreign-object_display-align_writing-mode_rl.xml | 121 + .../standard-testcases/kerning_1_off.xml | 4 +- .../standard-testcases/kerning_1_on.xml | 4 +- .../standard-testcases/leader-alignment.xml | 86 +- .../leader-alignment_writing-mode_rl.xml | 170 + .../leader_leader-pattern_dots_writing-mode_rl.xml | 213 + ...eader_leader-pattern_rule_writing-system_rl.xml | 331 + ...leader_leader-pattern_space_writing-mode_rl.xml | 95 + ..._leader-pattern_use-content_writing-mode_rl.xml | 317 + .../list-block_writing-mode_rl.xml | 207 + .../page-number-citation_writing-mode_rl.xml | 63 + .../region-body_column-count_1_writing-mode_rl.xml | 86 + .../region-body_column-count_2_writing-mode_rl.xml | 103 + ...writing-mode_rl_region-body_margin_relative.xml | 36 +- ...writing-mode_rl_region-body_margin_relative.xml | 40 +- ...writing-mode_rl_region-body_margin_relative.xml | 78 +- ...writing-mode_rl_region-body_margin_relative.xml | 78 +- .../table-column_column-progression-lr.xml | 82 + .../table-column_column-progression-rl.xml | 82 + .../complexscripts/arab/data/arab-001-f0.ser | Bin 0 -> 16639920 bytes .../complexscripts/arab/data/arab-001-f1.ser | Bin 0 -> 16257386 bytes .../complexscripts/arab/data/arab-001-f2.ser | Bin 0 -> 12193061 bytes .../complexscripts/arab/data/arab-001-f3.ser | Bin 0 -> 12190871 bytes .../complexscripts/arab/data/arab-001.txt | 85508 +++++++++++++++++++ .../resources/complexscripts/arab/ttx/arab-001.ttx | 1 + .../resources/complexscripts/arab/ttx/arab-002.ttx | 1 + .../resources/complexscripts/arab/ttx/arab-003.ttx | 1 + .../resources/complexscripts/arab/ttx/arab-004.ttx | 1 + 928 files changed, 132297 insertions(+), 1662 deletions(-) create mode 100644 src/codegen/unicode/java/org/apache/fop/complexscripts/bidi/GenerateBidiClass.java create mode 100644 src/codegen/unicode/java/org/apache/fop/complexscripts/bidi/GenerateBidiTestData.java create mode 100644 src/java/org/apache/fop/complexscripts/bidi/BidiClass.java create mode 100644 src/java/org/apache/fop/complexscripts/bidi/BidiConstants.java create mode 100644 src/java/org/apache/fop/complexscripts/bidi/BidiResolver.java create mode 100644 src/java/org/apache/fop/complexscripts/bidi/DelimitedTextRange.java create mode 100644 src/java/org/apache/fop/complexscripts/bidi/InlineRun.java create mode 100644 src/java/org/apache/fop/complexscripts/bidi/TextInterval.java create mode 100644 src/java/org/apache/fop/complexscripts/bidi/UnflattenProcessor.java create mode 100644 src/java/org/apache/fop/complexscripts/bidi/UnicodeBidiAlgorithm.java create mode 100644 src/java/org/apache/fop/complexscripts/fonts/AdvancedTypographicTableFormatException.java create mode 100644 src/java/org/apache/fop/complexscripts/fonts/GlyphClassMapping.java create mode 100644 src/java/org/apache/fop/complexscripts/fonts/GlyphClassTable.java create mode 100644 src/java/org/apache/fop/complexscripts/fonts/GlyphCoverageMapping.java create mode 100644 src/java/org/apache/fop/complexscripts/fonts/GlyphCoverageTable.java create mode 100644 src/java/org/apache/fop/complexscripts/fonts/GlyphDefinition.java create mode 100644 src/java/org/apache/fop/complexscripts/fonts/GlyphDefinitionSubtable.java create mode 100644 src/java/org/apache/fop/complexscripts/fonts/GlyphDefinitionTable.java create mode 100644 src/java/org/apache/fop/complexscripts/fonts/GlyphMappingTable.java create mode 100644 src/java/org/apache/fop/complexscripts/fonts/GlyphPositioning.java create mode 100644 src/java/org/apache/fop/complexscripts/fonts/GlyphPositioningState.java create mode 100644 src/java/org/apache/fop/complexscripts/fonts/GlyphPositioningSubtable.java create mode 100644 src/java/org/apache/fop/complexscripts/fonts/GlyphPositioningTable.java create mode 100644 src/java/org/apache/fop/complexscripts/fonts/GlyphProcessingState.java create mode 100644 src/java/org/apache/fop/complexscripts/fonts/GlyphSubstitution.java create mode 100644 src/java/org/apache/fop/complexscripts/fonts/GlyphSubstitutionState.java create mode 100644 src/java/org/apache/fop/complexscripts/fonts/GlyphSubstitutionSubtable.java create mode 100644 src/java/org/apache/fop/complexscripts/fonts/GlyphSubstitutionTable.java create mode 100644 src/java/org/apache/fop/complexscripts/fonts/GlyphSubtable.java create mode 100644 src/java/org/apache/fop/complexscripts/fonts/GlyphTable.java create mode 100644 src/java/org/apache/fop/complexscripts/fonts/IncompatibleSubtableException.java create mode 100644 src/java/org/apache/fop/complexscripts/fonts/OTFAdvancedTypographicTableReader.java create mode 100644 src/java/org/apache/fop/complexscripts/fonts/Positionable.java create mode 100644 src/java/org/apache/fop/complexscripts/fonts/Substitutable.java create mode 100644 src/java/org/apache/fop/complexscripts/scripts/ArabicScriptProcessor.java create mode 100644 src/java/org/apache/fop/complexscripts/scripts/DefaultScriptProcessor.java create mode 100644 src/java/org/apache/fop/complexscripts/scripts/DevanagariScriptProcessor.java create mode 100644 src/java/org/apache/fop/complexscripts/scripts/GujaratiScriptProcessor.java create mode 100644 src/java/org/apache/fop/complexscripts/scripts/GurmukhiScriptProcessor.java create mode 100644 src/java/org/apache/fop/complexscripts/scripts/IndicScriptProcessor.java create mode 100644 src/java/org/apache/fop/complexscripts/scripts/ScriptProcessor.java create mode 100644 src/java/org/apache/fop/complexscripts/util/CharMirror.java create mode 100644 src/java/org/apache/fop/complexscripts/util/CharScript.java create mode 100644 src/java/org/apache/fop/complexscripts/util/DiscontinuousAssociationException.java create mode 100644 src/java/org/apache/fop/complexscripts/util/GlyphContextTester.java create mode 100644 src/java/org/apache/fop/complexscripts/util/GlyphSequence.java create mode 100644 src/java/org/apache/fop/complexscripts/util/GlyphTester.java create mode 100644 src/java/org/apache/fop/complexscripts/util/NumberConverter.java create mode 100644 src/java/org/apache/fop/complexscripts/util/ScriptContextTester.java create mode 100644 src/java/org/apache/fop/complexscripts/util/UTF32.java create mode 100644 src/java/org/apache/fop/traits/Direction.java create mode 100644 src/java/org/apache/fop/traits/WritingMode.java create mode 100644 src/java/org/apache/fop/traits/WritingModeTraits.java create mode 100644 src/java/org/apache/fop/traits/WritingModeTraitsGetter.java create mode 100644 src/java/org/apache/fop/traits/WritingModeTraitsSetter.java create mode 100644 test/java/org/apache/fop/complexscripts/ComplexScriptsTestSuite.java create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiAlgorithmTestCase.java create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiClassTestCase.java create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD0.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD1.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD10.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD100.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD101.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD102.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD103.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD104.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD105.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD106.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD107.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD108.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD109.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD11.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD110.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD111.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD112.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD113.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD114.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD115.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD116.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD117.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD118.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD119.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD12.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD120.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD121.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD122.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD123.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD124.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD125.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD126.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD127.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD128.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD129.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD13.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD130.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD131.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD132.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD133.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD134.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD135.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD136.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD137.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD138.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD139.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD14.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD140.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD141.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD142.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD143.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD144.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD145.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD146.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD147.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD148.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD149.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD15.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD150.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD151.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD152.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD153.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD154.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD155.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD156.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD157.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD158.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD159.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD16.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD160.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD161.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD162.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD163.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD164.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD165.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD166.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD167.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD168.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD169.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD17.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD170.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD171.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD172.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD173.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD174.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD175.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD176.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD177.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD178.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD179.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD18.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD180.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD181.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD182.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD183.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD184.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD185.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD186.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD187.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD188.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD189.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD19.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD190.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD191.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD192.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD193.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD194.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD195.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD196.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD197.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD198.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD199.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD2.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD20.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD200.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD201.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD202.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD203.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD204.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD205.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD206.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD207.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD208.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD209.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD21.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD210.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD211.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD212.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD213.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD214.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD215.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD216.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD217.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD218.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD219.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD22.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD220.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD221.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD222.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD223.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD224.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD225.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD226.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD227.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD228.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD229.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD23.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD230.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD231.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD232.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD233.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD234.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD235.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD236.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD237.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD238.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD239.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD24.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD240.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD241.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD242.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD243.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD244.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD245.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD246.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD247.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD248.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD249.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD25.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD250.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD251.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD252.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD253.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD254.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD255.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD256.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD257.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD258.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD259.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD26.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD260.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD261.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD262.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD263.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD264.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD265.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD266.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD267.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD268.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD269.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD27.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD270.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD271.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD272.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD273.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD274.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD275.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD276.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD277.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD278.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD279.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD28.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD280.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD281.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD282.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD283.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD284.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD285.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD286.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD287.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD288.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD289.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD29.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD290.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD291.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD292.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD293.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD294.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD295.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD296.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD297.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD298.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD299.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD3.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD30.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD300.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD301.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD302.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD303.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD304.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD305.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD306.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD307.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD308.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD309.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD31.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD310.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD311.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD312.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD313.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD314.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD315.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD316.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD317.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD318.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD319.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD32.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD320.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD321.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD322.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD323.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD324.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD325.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD326.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD327.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD328.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD329.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD33.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD330.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD331.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD332.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD333.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD334.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD335.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD336.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD337.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD338.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD339.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD34.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD340.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD341.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD342.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD343.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD344.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD345.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD346.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD347.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD348.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD349.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD35.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD350.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD351.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD352.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD353.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD354.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD355.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD356.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD357.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD358.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD359.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD36.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD360.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD361.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD362.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD363.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD364.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD365.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD366.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD367.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD368.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD369.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD37.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD370.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD371.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD372.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD373.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD374.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD375.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD376.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD377.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD378.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD379.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD38.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD380.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD381.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD382.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD383.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD384.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD385.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD386.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD387.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD388.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD389.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD39.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD390.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD391.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD392.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD393.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD394.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD395.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD396.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD397.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD398.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD399.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD4.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD40.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD400.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD401.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD402.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD403.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD404.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD405.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD406.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD407.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD408.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD409.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD41.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD410.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD411.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD412.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD413.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD414.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD415.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD416.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD417.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD418.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD419.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD42.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD420.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD421.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD422.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD423.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD424.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD425.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD426.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD427.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD428.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD429.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD43.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD430.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD431.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD432.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD433.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD434.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD435.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD436.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD437.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD438.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD439.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD44.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD440.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD441.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD442.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD443.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD444.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD445.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD446.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD447.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD448.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD449.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD45.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD450.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD451.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD452.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD453.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD454.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD455.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD456.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD457.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD458.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD459.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD46.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD460.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD461.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD462.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD463.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD464.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD465.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD466.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD467.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD468.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD469.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD47.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD470.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD471.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD472.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD473.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD474.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD475.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD476.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD477.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD478.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD479.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD48.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD480.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD481.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD482.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD483.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD484.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD485.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD486.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD487.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD488.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD489.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD49.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD490.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD491.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD492.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD493.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD494.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD495.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD496.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD497.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD498.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD499.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD5.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD50.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD500.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD501.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD502.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD503.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD504.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD505.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD506.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD507.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD508.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD509.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD51.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD510.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD511.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD512.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD513.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD514.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD515.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD516.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD517.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD518.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD519.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD52.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD520.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD521.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD522.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD523.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD524.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD525.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD526.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD527.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD528.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD529.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD53.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD530.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD531.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD532.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD533.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD534.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD535.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD536.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD537.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD538.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD539.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD54.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD540.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD541.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD542.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD543.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD544.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD545.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD546.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD547.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD548.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD549.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD55.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD550.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD551.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD552.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD553.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD554.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD555.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD556.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD557.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD558.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD559.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD56.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD560.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD561.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD562.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD563.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD564.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD565.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD566.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD567.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD568.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD569.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD57.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD570.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD571.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD572.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD573.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD574.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD575.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD576.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD577.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD578.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD579.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD58.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD580.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD581.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD582.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD583.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD584.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD585.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD586.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD587.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD588.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD589.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD59.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD590.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD591.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD592.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD593.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD594.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD595.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD596.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD597.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD598.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD599.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD6.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD60.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD600.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD601.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD602.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD603.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD604.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD605.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD606.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD607.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD608.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD609.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD61.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD610.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD611.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD612.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD613.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD614.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD615.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD616.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD617.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD618.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD619.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD62.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD620.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD621.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD63.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD64.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD65.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD66.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD67.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD68.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD69.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD7.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD70.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD71.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD72.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD73.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD74.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD75.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD76.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD77.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD78.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD79.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD8.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD80.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD81.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD82.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD83.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD84.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD85.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD86.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD87.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD88.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD89.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD9.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD90.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD91.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD92.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD93.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD94.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD95.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD96.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD97.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD98.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD99.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$TD0.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$TD1.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$TD10.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$TD11.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$TD12.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$TD13.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$TD14.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$TD15.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$TD16.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$TD17.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$TD18.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$TD2.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$TD3.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$TD4.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$TD5.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$TD6.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$TD7.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$TD8.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData$TD9.ser create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestData.java create mode 100644 test/java/org/apache/fop/complexscripts/bidi/BidiTestSuite.java create mode 100644 test/java/org/apache/fop/complexscripts/fonts/FontsTestSuite.java create mode 100644 test/java/org/apache/fop/complexscripts/fonts/GDEFTestCase.java create mode 100644 test/java/org/apache/fop/complexscripts/fonts/GPOSTestCase.java create mode 100644 test/java/org/apache/fop/complexscripts/fonts/GSUBTestCase.java create mode 100644 test/java/org/apache/fop/complexscripts/fonts/ttx/TTXFile.java create mode 100644 test/java/org/apache/fop/complexscripts/fonts/ttx/TTXFileTestCase.java create mode 100644 test/java/org/apache/fop/complexscripts/scripts/ScriptsTestSuite.java create mode 100644 test/java/org/apache/fop/complexscripts/scripts/arabic/ArabicTestCase.java create mode 100644 test/java/org/apache/fop/complexscripts/scripts/arabic/ArabicTestConstants.java create mode 100644 test/java/org/apache/fop/complexscripts/scripts/arabic/GenerateArabicTestData.java create mode 100644 test/java/org/apache/fop/complexscripts/util/NumberConverterTestCase.java create mode 100644 test/java/org/apache/fop/complexscripts/util/UtilTestSuite.java create mode 100644 test/layoutengine/standard-testcases/basic-link_background-image_writing-mode_rl.xml create mode 100644 test/layoutengine/standard-testcases/basic-link_external-destination_writing-mode_rl.xml create mode 100644 test/layoutengine/standard-testcases/basic-link_external-destination_writing-mode_rl_2.xml create mode 100644 test/layoutengine/standard-testcases/basic-link_for_toc_writing-mode_rl.xml create mode 100644 test/layoutengine/standard-testcases/basic-link_height_baseline-shift_writing-mode_rl.xml create mode 100644 test/layoutengine/standard-testcases/basic-link_height_inline-child_writing-mode_rl.xml create mode 100644 test/layoutengine/standard-testcases/basic-link_height_multi-child_writing-mode_rl.xml create mode 100644 test/layoutengine/standard-testcases/basic-link_height_multi-line_writing-mode_rl.xml create mode 100644 test/layoutengine/standard-testcases/basic-link_height_writing-mode_rl.xml create mode 100644 test/layoutengine/standard-testcases/basic-link_internal-desination-next-page.xml create mode 100644 test/layoutengine/standard-testcases/basic-link_internal-desination-next-page_writing-mode_rl.xml create mode 100644 test/layoutengine/standard-testcases/basic-link_internal-desination-same-page-after.xml create mode 100644 test/layoutengine/standard-testcases/basic-link_internal-desination-same-page-after_writing-mode_rl.xml create mode 100644 test/layoutengine/standard-testcases/basic-link_internal-desination-same-page-before.xml create mode 100644 test/layoutengine/standard-testcases/basic-link_internal-desination-same-page-before_writing-mode_rl.xml create mode 100644 test/layoutengine/standard-testcases/bidi_propagation_1.xml create mode 100644 test/layoutengine/standard-testcases/block-container_start-indent_writing-mode_rl.xml create mode 100644 test/layoutengine/standard-testcases/block_text-align_4.xml create mode 100644 test/layoutengine/standard-testcases/block_text-align_5.xml create mode 100644 test/layoutengine/standard-testcases/character_writing-mode_rl.xml create mode 100644 test/layoutengine/standard-testcases/inline_background-color_writing-mode_rl.xml create mode 100644 test/layoutengine/standard-testcases/instream-foreign-object_basic_writing-mode_rl.xml create mode 100644 test/layoutengine/standard-testcases/instream-foreign-object_border_padding_writing-mode_rl.xml create mode 100644 test/layoutengine/standard-testcases/instream-foreign-object_display-align_writing-mode_rl.xml create mode 100644 test/layoutengine/standard-testcases/leader-alignment_writing-mode_rl.xml create mode 100644 test/layoutengine/standard-testcases/leader_leader-pattern_dots_writing-mode_rl.xml create mode 100644 test/layoutengine/standard-testcases/leader_leader-pattern_rule_writing-system_rl.xml create mode 100644 test/layoutengine/standard-testcases/leader_leader-pattern_space_writing-mode_rl.xml create mode 100644 test/layoutengine/standard-testcases/leader_leader-pattern_use-content_writing-mode_rl.xml create mode 100644 test/layoutengine/standard-testcases/list-block_writing-mode_rl.xml create mode 100644 test/layoutengine/standard-testcases/page-number-citation_writing-mode_rl.xml create mode 100644 test/layoutengine/standard-testcases/region-body_column-count_1_writing-mode_rl.xml create mode 100644 test/layoutengine/standard-testcases/region-body_column-count_2_writing-mode_rl.xml create mode 100644 test/layoutengine/standard-testcases/table-column_column-progression-lr.xml create mode 100644 test/layoutengine/standard-testcases/table-column_column-progression-rl.xml create mode 100644 test/resources/complexscripts/arab/data/arab-001-f0.ser create mode 100644 test/resources/complexscripts/arab/data/arab-001-f1.ser create mode 100644 test/resources/complexscripts/arab/data/arab-001-f2.ser create mode 100644 test/resources/complexscripts/arab/data/arab-001-f3.ser create mode 100644 test/resources/complexscripts/arab/data/arab-001.txt create mode 100644 test/resources/complexscripts/arab/ttx/arab-001.ttx create mode 100644 test/resources/complexscripts/arab/ttx/arab-002.ttx create mode 100644 test/resources/complexscripts/arab/ttx/arab-003.ttx create mode 100644 test/resources/complexscripts/arab/ttx/arab-004.ttx (limited to 'src/java/org/apache/fop/render/bitmap') diff --git a/build.xml b/build.xml index e8d522309..5c7bc0e39 100644 --- a/build.xml +++ b/build.xml @@ -85,12 +85,12 @@ list of possible build targets. - - - - - - + + + + + + @@ -98,7 +98,7 @@ list of possible build targets. - + @@ -153,6 +153,8 @@ list of possible build targets. + + @@ -214,7 +216,10 @@ list of possible build targets. - + @@ -396,18 +401,18 @@ list of possible build targets. - + - - - - - - - - - - + + + + + + + + + + @@ -418,20 +423,20 @@ list of possible build targets. - - - - - - - - - - - - - - + + + + + + + + + + + + + + @@ -551,6 +556,7 @@ list of possible build targets. + @@ -662,10 +668,15 @@ list of possible build targets. - + + + + + + - + @@ -705,6 +716,7 @@ list of possible build targets. + @@ -778,10 +790,10 @@ list of possible build targets. - + - + @@ -798,7 +810,7 @@ list of possible build targets. - + @@ -865,7 +877,10 @@ list of possible build targets. - + + + + @@ -1017,7 +1032,7 @@ NOTE: - + @@ -1252,11 +1267,11 @@ NOTE: - - - - - + + + + + NOTE: @@ -1330,21 +1345,71 @@ NOTE: - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -1361,7 +1426,7 @@ NOTE: All tests passed! - + @@ -1373,7 +1438,7 @@ NOTE: - + @@ -1409,4 +1474,10 @@ NOTE: + + + + + + diff --git a/checkstyle-suppressions.xml b/checkstyle-suppressions.xml index 217299870..76e282f61 100644 --- a/checkstyle-suppressions.xml +++ b/checkstyle-suppressions.xml @@ -2,6 +2,7 @@ - + + diff --git a/findbugs-exclude.xml b/findbugs-exclude.xml index e5aee4279..86471d609 100644 --- a/findbugs-exclude.xml +++ b/findbugs-exclude.xml @@ -4821,4 +4821,389 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fop.cmd b/fop.cmd index 33f164c53..8cf143e2f 100644 --- a/fop.cmd +++ b/fop.cmd @@ -27,5 +27,5 @@ goto setupArgs rem This label provides a place for the argument list loop to break out :doneStart -call %LOCAL_FOP_HOME%\fop.bat %FOP_CMD_LINE_ARGS% +call "%LOCAL_FOP_HOME%\fop.bat" %FOP_CMD_LINE_ARGS% diff --git a/src/codegen/java/org/apache/fop/tools/EventProducerCollectorTask.java b/src/codegen/java/org/apache/fop/tools/EventProducerCollectorTask.java index 6786e43f0..38867d87a 100644 --- a/src/codegen/java/org/apache/fop/tools/EventProducerCollectorTask.java +++ b/src/codegen/java/org/apache/fop/tools/EventProducerCollectorTask.java @@ -58,7 +58,7 @@ import org.apache.fop.events.model.EventProducerModel; */ public class EventProducerCollectorTask extends Task { - private List filesets = new java.util.ArrayList(); + private List filesets = new java.util.ArrayList(); private File destDir; private File translationFile; @@ -202,7 +202,7 @@ public class EventProducerCollectorTask extends Task { protected long processFileSets(EventProducerCollector collector) throws IOException, EventConventionException, ClassNotFoundException { long lastModified = 0; - Iterator iter = filesets.iterator(); + Iterator iter = filesets.iterator(); while (iter.hasNext()) { FileSet fs = (FileSet)iter.next(); DirectoryScanner ds = fs.getDirectoryScanner(getProject()); diff --git a/src/codegen/unicode/java/org/apache/fop/complexscripts/bidi/GenerateBidiClass.java b/src/codegen/unicode/java/org/apache/fop/complexscripts/bidi/GenerateBidiClass.java new file mode 100644 index 000000000..7b1a6bb5b --- /dev/null +++ b/src/codegen/unicode/java/org/apache/fop/complexscripts/bidi/GenerateBidiClass.java @@ -0,0 +1,571 @@ +/* + * 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.complexscripts.bidi; + +import java.io.BufferedReader; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.InputStreamReader; +import java.io.PrintWriter; +import java.net.URL; +import java.util.Arrays; +import java.util.Iterator; +import java.util.SortedSet; +import java.util.TreeSet; + +import org.apache.fop.complexscripts.bidi.BidiConstants; +import org.apache.fop.util.License; + +// CSOFF: LineLength +// CSOFF: NoWhitespaceAfter + +/** + *

Utility for generating a Java class representing bidirectional + * class properties from the Unicode property files.

+ * + *

This code is derived in part from GenerateLineBreakUtils.java.

+ * + * @author Glenn Adams + */ +public final class GenerateBidiClass { + + private GenerateBidiClass() { + } + + private static byte[] bcL1 = new byte[256]; // ascii and basic latin blocks ( 0x0000 - 0x00FF ) + private static byte[] bcR1 = new byte[368]; // hebrew and arabic blocks ( 0x0590 - 0x06FF ) + private static int[] bcS1; // interval start indices + private static int[] bcE1; // interval end indices + private static byte[] bcC1; // interval bid classes + + /** + * Generate a class managing bidi class properties for Unicode characters. + * + * @param bidiFileName name (as URL) of file containing bidi type data + * @param outFileName name of the output file + * @throws Exception + */ + private static void convertBidiClassProperties(String bidiFileName, String outFileName) throws Exception { + + readBidiClassProperties(bidiFileName); + + // generate class + PrintWriter out = new PrintWriter(new FileWriter(outFileName)); + License.writeJavaLicenseId(out); + out.println(); + out.println("package org.apache.fop.complexscripts.bidi;"); + out.println(); + out.println("import java.util.Arrays;"); + out.println("import org.apache.fop.complexscripts.bidi.BidiConstants;"); + out.println(); + out.println("// CSOFF: WhitespaceAfterCheck"); + out.println("// CSOFF: LineLengthCheck"); + out.println(); + out.println("/*"); + out.println(" * !!! THIS IS A GENERATED FILE !!!"); + out.println(" * If updates to the source are needed, then:"); + out.println(" * - apply the necessary modifications to"); + out.println(" * 'src/codegen/unicode/java/org/apache/fop/complexscripts/bidi/GenerateBidiClass.java'"); + out.println(" * - run 'ant codegen-unicode', which will generate a new BidiClass.java"); + out.println(" * in 'src/java/org/apache/fop/complexscripts/bidi'"); + out.println(" * - commit BOTH changed files"); + out.println(" */"); + out.println(); + out.println("/** Bidirectional class utilities. */"); + out.println("public final class BidiClass {"); + out.println(); + out.println("private BidiClass() {"); + out.println("}"); + out.println(); + dumpData(out); + out.println ("/**"); + out.println (" * Lookup bidi class for character expressed as unicode scalar value."); + out.println (" * @param ch a unicode scalar value"); + out.println (" * @return bidi class"); + out.println (" */"); + out.println("public static int getBidiClass ( int ch ) {"); + out.println(" if ( ch <= 0x00FF ) {"); + out.println(" return bcL1 [ ch - 0x0000 ];"); + out.println(" } else if ( ( ch >= 0x0590 ) && ( ch <= 0x06FF ) ) {"); + out.println(" return bcR1 [ ch - 0x0590 ];"); + out.println(" } else {"); + out.println(" return getBidiClass ( ch, bcS1, bcE1, bcC1 );"); + out.println(" }"); + out.println("}"); + out.println(); + out.println("private static int getBidiClass ( int ch, int[] sa, int[] ea, byte[] ca ) {"); + out.println(" int k = Arrays.binarySearch ( sa, ch );"); + out.println(" if ( k >= 0 ) {"); + out.println(" return ca [ k ];"); + out.println(" } else {"); + out.println(" k = - ( k + 1 );"); + out.println(" if ( k == 0 ) {"); + out.println(" return BidiConstants.L;"); + out.println(" } else if ( ch <= ea [ k - 1 ] ) {"); + out.println(" return ca [ k - 1 ];"); + out.println(" } else {"); + out.println(" return BidiConstants.L;"); + out.println(" }"); + out.println(" }"); + out.println("}"); + out.println(); + out.println("}"); + out.flush(); + out.close(); + } + + /** + * Read bidi class property data. + * + * @param bidiFileName name (as URL) of bidi type data + */ + private static void readBidiClassProperties(String bidiFileName) throws Exception { + // read property names + BufferedReader b = new BufferedReader(new InputStreamReader(new URL(bidiFileName).openStream())); + String line; + int lineNumber = 0; + TreeSet intervals = new TreeSet(); + while ( ( line = b.readLine() ) != null ) { + lineNumber++; + if ( line.startsWith("#") ) { + continue; + } else if ( line.length() == 0 ) { + continue; + } else { + if ( line.indexOf ( "#" ) != -1 ) { + line = ( line.split ( "#" ) ) [ 0 ]; + } + String[] fa = line.split ( ";" ); + if ( fa.length == 2 ) { + int[] interval = parseInterval ( fa[0].trim() ); + byte bidiClass = (byte) parseBidiClass ( fa[1].trim() ); + if ( interval[1] == interval[0] ) { // singleton + int c = interval[0]; + if ( c <= 0x00FF ) { + if ( bcL1 [ c - 0x0000 ] == 0 ) { + bcL1 [ c - 0x0000 ] = bidiClass; + } else { + throw new Exception ( "duplicate singleton entry: " + c ); + } + } else if ( ( c >= 0x0590 ) && ( c <= 0x06FF ) ) { + if ( bcR1 [ c - 0x0590 ] == 0 ) { + bcR1 [ c - 0x0590 ] = bidiClass; + } else { + throw new Exception ( "duplicate singleton entry: " + c ); + } + } else { + addInterval ( intervals, c, c, bidiClass ); + } + } else { // non-singleton + int s = interval[0]; + int e = interval[1]; // inclusive + if ( s <= 0x00FF ) { + for ( int i = s; i <= e; i++ ) { + if ( i <= 0x00FF ) { + if ( bcL1 [ i - 0x0000 ] == 0 ) { + bcL1 [ i - 0x0000 ] = bidiClass; + } else { + throw new Exception ( "duplicate singleton entry: " + i ); + } + } else { + addInterval ( intervals, i, e, bidiClass ); + break; + } + } + } else if ( ( s >= 0x0590 ) && ( s <= 0x06FF ) ) { + for ( int i = s; i <= e; i++ ) { + if ( i <= 0x06FF ) { + if ( bcR1 [ i - 0x0590 ] == 0 ) { + bcR1 [ i - 0x0590 ] = bidiClass; + } else { + throw new Exception ( "duplicate singleton entry: " + i ); + } + } else { + addInterval ( intervals, i, e, bidiClass ); + break; + } + } + } else { + addInterval ( intervals, s, e, bidiClass ); + } + } + } else { + throw new Exception ( "bad syntax, line(" + lineNumber + "): " + line ); + } + } + } + // compile interval search data + int ivIndex = 0, niv = intervals.size(); + bcS1 = new int [ niv ]; + bcE1 = new int [ niv ]; + bcC1 = new byte [ niv ]; + for ( Iterator it = intervals.iterator(); it.hasNext(); ivIndex++ ) { + Interval iv = (Interval) it.next(); + bcS1[ivIndex] = iv.start; + bcE1[ivIndex] = iv.end; + bcC1[ivIndex] = (byte) iv.bidiClass; + } + // test data + test(); + } + + private static int[] parseInterval ( String interval ) throws Exception { + int s, e; + String[] fa = interval.split("\\.\\."); + if ( fa.length == 1 ) { + s = Integer.parseInt ( fa[0], 16 ); + e = s; + } else if ( fa.length == 2 ) { + s = Integer.parseInt ( fa[0], 16 ); + e = Integer.parseInt ( fa[1], 16 ); + } else { + throw new Exception ( "bad interval syntax: " + interval ); + } + if ( e < s ) { + throw new Exception ( "bad interval, start must be less than or equal to end: " + interval ); + } + return new int[] {s, e}; + } + + private static int parseBidiClass ( String bidiClass ) { + int bc = 0; + if ( "L".equals ( bidiClass ) ) { + bc = BidiConstants.L; + } else if ( "LRE".equals ( bidiClass ) ) { + bc = BidiConstants.LRE; + } else if ( "LRO".equals ( bidiClass ) ) { + bc = BidiConstants.LRO; + } else if ( "R".equals ( bidiClass ) ) { + bc = BidiConstants.R; + } else if ( "AL".equals ( bidiClass ) ) { + bc = BidiConstants.AL; + } else if ( "RLE".equals ( bidiClass ) ) { + bc = BidiConstants.RLE; + } else if ( "RLO".equals ( bidiClass ) ) { + bc = BidiConstants.RLO; + } else if ( "PDF".equals ( bidiClass ) ) { + bc = BidiConstants.PDF; + } else if ( "EN".equals ( bidiClass ) ) { + bc = BidiConstants.EN; + } else if ( "ES".equals ( bidiClass ) ) { + bc = BidiConstants.ES; + } else if ( "ET".equals ( bidiClass ) ) { + bc = BidiConstants.ET; + } else if ( "AN".equals ( bidiClass ) ) { + bc = BidiConstants.AN; + } else if ( "CS".equals ( bidiClass ) ) { + bc = BidiConstants.CS; + } else if ( "NSM".equals ( bidiClass ) ) { + bc = BidiConstants.NSM; + } else if ( "BN".equals ( bidiClass ) ) { + bc = BidiConstants.BN; + } else if ( "B".equals ( bidiClass ) ) { + bc = BidiConstants.B; + } else if ( "S".equals ( bidiClass ) ) { + bc = BidiConstants.S; + } else if ( "WS".equals ( bidiClass ) ) { + bc = BidiConstants.WS; + } else if ( "ON".equals ( bidiClass ) ) { + bc = BidiConstants.ON; + } else { + throw new IllegalArgumentException ( "unknown bidi class: " + bidiClass ); + } + return bc; + } + + private static void addInterval ( SortedSet intervals, int start, int end, int bidiClass ) { + intervals.add ( new Interval ( start, end, bidiClass ) ); + } + + private static void dumpData ( PrintWriter out ) { + boolean first; + StringBuffer sb = new StringBuffer(); + + // bcL1 + first = true; + sb.setLength(0); + out.println ( "private static byte[] bcL1 = {" ); + for ( int i = 0; i < bcL1.length; i++ ) { + if ( ! first ) { + sb.append ( "," ); + } else { + first = false; + } + sb.append ( bcL1[i] ); + if ( sb.length() > 120 ) { + sb.append(','); + out.println(sb); + first = true; + sb.setLength(0); + } + } + if ( sb.length() > 0 ) { + out.println(sb); + } + out.println ( "};" ); + out.println(); + + // bcR1 + first = true; + sb.setLength(0); + out.println ( "private static byte[] bcR1 = {" ); + for ( int i = 0; i < bcR1.length; i++ ) { + if ( ! first ) { + sb.append ( "," ); + } else { + first = false; + } + sb.append ( bcR1[i] ); + if ( sb.length() > 120 ) { + sb.append(','); + out.println(sb); + first = true; + sb.setLength(0); + } + } + if ( sb.length() > 0 ) { + out.println(sb); + } + out.println ( "};" ); + out.println(); + + // bcS1 + first = true; + sb.setLength(0); + out.println ( "private static int[] bcS1 = {" ); + for ( int i = 0; i < bcS1.length; i++ ) { + if ( ! first ) { + sb.append ( "," ); + } else { + first = false; + } + sb.append ( bcS1[i] ); + if ( sb.length() > 120 ) { + sb.append(','); + out.println(sb); + first = true; + sb.setLength(0); + } + } + if ( sb.length() > 0 ) { + out.println(sb); + } + out.println ( "};" ); + out.println(); + + // bcE1 + first = true; + sb.setLength(0); + out.println ( "private static int[] bcE1 = {" ); + for ( int i = 0; i < bcE1.length; i++ ) { + if ( ! first ) { + sb.append ( "," ); + } else { + first = false; + } + sb.append ( bcE1[i] ); + if ( sb.length() > 120 ) { + sb.append(','); + out.println(sb); + first = true; + sb.setLength(0); + } + } + if ( sb.length() > 0 ) { + out.println(sb); + } + out.println ( "};" ); + out.println(); + + // bcC1 + first = true; + sb.setLength(0); + out.println ( "private static byte[] bcC1 = {" ); + for ( int i = 0; i < bcC1.length; i++ ) { + if ( ! first ) { + sb.append ( "," ); + } else { + first = false; + } + sb.append ( bcC1[i] ); + if ( sb.length() > 120 ) { + sb.append(','); + out.println(sb); + first = true; + sb.setLength(0); + } + } + if ( sb.length() > 0 ) { + out.println(sb); + } + out.println ( "};" ); + out.println(); + } + + private static int getBidiClass ( int ch ) { + if ( ch <= 0x00FF ) { + return bcL1 [ ch - 0x0000 ]; + } else if ( ( ch >= 0x0590 ) && ( ch <= 0x06FF ) ) { + return bcR1 [ ch - 0x0590 ]; + } else { + return getBidiClass ( ch, bcS1, bcE1, bcC1 ); + } + } + + private static int getBidiClass ( int ch, int[] sa, int[] ea, byte[] ca ) { + int k = Arrays.binarySearch ( sa, ch ); + if ( k >= 0 ) { + return ca [ k ]; + } else { + k = - ( k + 1 ); + if ( k == 0 ) { + return BidiConstants.L; + } else if ( ch <= ea [ k - 1 ] ) { + return ca [ k - 1 ]; + } else { + return BidiConstants.L; + } + } + } + + private static final int[] testData = // CSOK: ConstantName + { + 0x000000, BidiConstants.BN, + 0x000009, BidiConstants.S, + 0x00000A, BidiConstants.B, + 0x00000C, BidiConstants.WS, + 0x000020, BidiConstants.WS, + 0x000023, BidiConstants.ET, + 0x000028, BidiConstants.ON, + 0x00002B, BidiConstants.ES, + 0x00002C, BidiConstants.CS, + 0x000031, BidiConstants.EN, + 0x00003A, BidiConstants.CS, + 0x000041, BidiConstants.L, + 0x000300, BidiConstants.NSM, + 0x000374, BidiConstants.ON, + 0x0005BE, BidiConstants.R, + 0x000601, BidiConstants.AN, + 0x000608, BidiConstants.AL, + 0x000670, BidiConstants.NSM, + 0x000710, BidiConstants.AL, + 0x0007FA, BidiConstants.R, + 0x000970, BidiConstants.L, + 0x001392, BidiConstants.ON, + 0x002000, BidiConstants.WS, + 0x00200E, BidiConstants.L, + 0x00200F, BidiConstants.R, + 0x00202A, BidiConstants.LRE, + 0x00202B, BidiConstants.RLE, + 0x00202C, BidiConstants.PDF, + 0x00202D, BidiConstants.LRO, + 0x00202E, BidiConstants.RLO, + 0x0020E1, BidiConstants.NSM, + 0x002212, BidiConstants.ES, + 0x002070, BidiConstants.EN, + 0x003000, BidiConstants.WS, + 0x003009, BidiConstants.ON, + 0x00FBD4, BidiConstants.AL, + 0x00FE69, BidiConstants.ET, + 0x00FF0C, BidiConstants.CS, + 0x00FEFF, BidiConstants.BN, + 0x01034A, BidiConstants.L, + 0x010E60, BidiConstants.AN, + 0x01F100, BidiConstants.EN, + 0x0E0001, BidiConstants.BN, + 0x0E0100, BidiConstants.NSM, + 0x10FFFF, BidiConstants.BN + }; + + private static void test() throws Exception { + for ( int i = 0, n = testData.length / 2; i < n; i++ ) { + int ch = testData [ i * 2 + 0 ]; + int tc = testData [ i * 2 + 1 ]; + int bc = getBidiClass ( ch ); + if ( bc != tc ) { + throw new Exception ( "test mapping failed for character (0x" + Integer.toHexString(ch) + "): expected " + tc + ", got " + bc ); + } + } + } + + /** + * Main entry point for generator. + * @param args array of command line arguments + */ + public static void main(String[] args) { + String bidiFileName = "http://www.unicode.org/Public/UNIDATA/extracted/DerivedBidiClass.txt"; + String outFileName = "BidiClass.java"; + boolean ok = true; + for (int i = 0; i < args.length; i = i + 2) { + if (i + 1 == args.length) { + ok = false; + } else { + String opt = args[i]; + if ("-b".equals(opt)) { + bidiFileName = args [i + 1]; + } else if ("-o".equals(opt)) { + outFileName = args [i + 1]; + } else { + ok = false; + } + } + } + if (!ok) { + System.out.println("Usage: GenerateBidiClass [-b ] [-o ]"); + System.out.println(" defaults:"); + System.out.println(" : " + bidiFileName); + System.out.println(" : " + outFileName); + } else { + try { + convertBidiClassProperties(bidiFileName, outFileName); + System.out.println("Generated " + outFileName + " from"); + System.out.println(" : " + bidiFileName); + } catch (Exception e) { + System.out.println("An unexpected error occured"); + e.printStackTrace(); + } + } + } + + private static class Interval implements Comparable { + int start; // CSOK: VisibilityModifier + int end; // CSOK: VisibilityModifier + int bidiClass; // CSOK: VisibilityModifier + Interval ( int start, int end, int bidiClass ) { + this.start = start; + this.end = end; + this.bidiClass = bidiClass; + } + public int compareTo ( Object o ) { + Interval iv = (Interval) o; + if ( start < iv.start ) { + return -1; + } else if ( start > iv.start ) { + return 1; + } else if ( end < iv.end ) { + return -1; + } else if ( end > iv.end ) { + return 1; + } else { + return 0; + } + } + } +} diff --git a/src/codegen/unicode/java/org/apache/fop/complexscripts/bidi/GenerateBidiTestData.java b/src/codegen/unicode/java/org/apache/fop/complexscripts/bidi/GenerateBidiTestData.java new file mode 100644 index 000000000..e2fab1d94 --- /dev/null +++ b/src/codegen/unicode/java/org/apache/fop/complexscripts/bidi/GenerateBidiTestData.java @@ -0,0 +1,1269 @@ +/* + * 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.text.bidi; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileOutputStream; +import java.io.FileWriter; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.ObjectOutputStream; +import java.io.PrintWriter; + +import java.net.URL; +import java.text.CharacterIterator; +import java.text.StringCharacterIterator; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; + +import org.apache.fop.complexscripts.bidi.BidiConstants; +import org.apache.fop.util.License; + +// CSOFF: LineLengthCheck +// CSOFF: NoWhitespaceAfterCheck +// CSOFF: InnerAssignmentCheck +// CSOFF: SimplifyBooleanReturnCheck +// CSOFF: EmptyForIteratorPadCheck + +/** + *

Utility for generating a Java class and associated data files representing + * bidirectional confomance test data from the Unicode Character Database and + * Unicode BidiTest data files.

+ * + *

This code is derived in part from GenerateBidiClassUtils.java.

+ * + * @author Glenn Adams + */ +public final class GenerateBidiTestData { + + // local constants + private static final String PFX_TYPE = "@Type:"; + private static final String PFX_LEVELS = "@Levels:"; + private static final String PFX_REORDER = "@Reorder:"; + + // command line options + private static boolean ignoreDeprecatedTypeData; + private static boolean verbose; + + // instrumentation + private static int lineNumber; + private static int numTypeRanges; + private static int numLevelSpecs; + private static int numTestSpecs; + + // compiled data + private static int[][] td; // types data + private static int[][] ld; // levels data + + // ensure non-instantiation + private GenerateBidiTestData() { + } + + /** + * Generate a class managing bidi test data for Unicode characters. + * + * @param ucdFileName name (as URL) of file containing unicode character database data + * @param bidiFileName name (as URL) of file containing bidi test data + * @param outFileName name of the output class file + * @throws Exception + */ + private static void convertBidiTestData(String ucdFileName, String bidiFileName, String outFileName) throws Exception { + + // read type data from UCD if ignoring deprecated type data + if ( ignoreDeprecatedTypeData ) { + readBidiTypeData(ucdFileName); + } + + // read bidi test data + readBidiTestData(bidiFileName); + + // generate class + PrintWriter out = new PrintWriter(new FileWriter(outFileName)); + License.writeJavaLicenseId(out); + out.println(); + out.println("package org.apache.fop.complexscripts.bidi;"); + out.println(); + out.println("import java.io.IOException;"); + out.println("import java.io.InputStream;"); + out.println("import java.io.ObjectInputStream;"); + out.println(); + out.println("// CSOFF: WhitespaceAfterCheck"); + out.println(); + out.println("/*"); + out.println(" * !!! THIS IS A GENERATED FILE !!!"); + out.println(" * If updates to the source are needed, then:"); + out.println(" * - apply the necessary modifications to"); + out.println(" * 'src/codegen/unicode/java/org/apache/fop/text/bidi/GenerateBidiTestData.java'"); + out.println(" * - run 'ant codegen-unicode', which will generate a new BidiTestData.java"); + out.println(" * in 'test/java/org/apache/fop/complexscripts/bidi'"); + out.println(" * - commit BOTH changed files"); + out.println(" */"); + out.println(); + out.println("/** Bidirectional test data. */"); + out.println("public final class BidiTestData {"); + out.println(); + out.println(" private BidiTestData() {"); + out.println(" }"); + out.println(); + dumpData ( out, outFileName ); + out.println(" public static final int NUM_TEST_SEQUENCES = " + numTestSpecs + ";"); + out.println(); + out.println(" public static int[] readTestData ( String prefix, int index ) {"); + out.println(" int[] data = null;"); + out.println(" InputStream is = null;"); + out.println(" Class btc = BidiTestData.class;"); + out.println(" String name = btc.getSimpleName() + \"$\" + prefix + index + \".ser\";"); + out.println(" try {"); + out.println(" if ( ( is = btc.getResourceAsStream ( name ) ) != null ) {"); + out.println(" ObjectInputStream ois = new ObjectInputStream ( is );"); + out.println(" data = (int[]) ois.readObject();"); + out.println(" ois.close();"); + out.println(" }"); + out.println(" } catch ( IOException e ) {"); + out.println(" data = null;"); + out.println(" } catch ( ClassNotFoundException e ) {"); + out.println(" data = null;"); + out.println(" } finally {"); + out.println(" if ( is != null ) {"); + out.println(" try { is.close(); } catch ( Exception e ) {}"); + out.println(" }"); + out.println(" }"); + out.println(" return data;"); + out.println(" }"); + out.println("}"); + out.flush(); + out.close(); + + } + + /** + * Read bidi type data. + * + * @param ucdFileName name (as URL) of unicode character database data + */ + private static void readBidiTypeData(String ucdFileName) throws Exception { + BufferedReader b = new BufferedReader(new InputStreamReader(new URL(ucdFileName).openStream())); + String line; + int n; + // singleton map - derived from single char entry + Map/**/ sm = new HashMap/**/(); + // interval map - derived from pair of block endpoint entries + Map/**/ im = new HashMap/**/(); + if ( verbose ) { + System.out.print("Reading bidi type data..."); + } + for ( lineNumber = 0; ( line = b.readLine() ) != null; ) { + lineNumber++; + if ( line.length() == 0 ) { + continue; + } else if ( line.startsWith("#") ) { + continue; + } else { + parseTypeProperties ( line, sm, im ); + } + } + // extract type data list + List tdl = processTypeData ( sm, im, new ArrayList() ); + // dump instrumentation + if ( verbose ) { + System.out.println(); + System.out.println("Read type ranges : " + numTypeRanges ); + System.out.println("Read lines : " + lineNumber ); + } + td = (int[][]) tdl.toArray ( new int [ tdl.size() ] [] ); + } + + private static void parseTypeProperties ( String line, Map/**/ sm, Map/**/ im ) { + String[] sa = line.split(";"); + if ( sa.length >= 5 ) { + int uc = Integer.parseInt ( sa[0], 16 ); + int bc = parseBidiClassAny ( sa[4] ); + if ( bc >= 0 ) { + String ucName = sa[1]; + if ( isBlockStart ( ucName ) ) { + String ucBlock = getBlockName ( ucName ); + if ( ! im.containsKey ( ucBlock ) ) { + im.put ( ucBlock, new int[] { uc, -1, bc } ); + } else { + throw new IllegalArgumentException ( "duplicate start of block '" + ucBlock + "' at entry: " + line ); + } + } else if ( isBlockEnd ( ucName ) ) { + String ucBlock = getBlockName ( ucName ); + if ( im.containsKey ( ucBlock ) ) { + int[] ba = (int[]) im.get ( ucBlock ); + assert ba.length == 3; + if ( ba[1] < 0 ) { + ba[1] = uc; + } else { + throw new IllegalArgumentException ( "duplicate end of block '" + ucBlock + "' at entry: " + line ); + } + } else { + throw new IllegalArgumentException ( "missing start of block '" + ucBlock + "' at entry: " + line ); + } + } else { + Integer k = Integer.valueOf ( bc ); + List sl; + if ( ! sm.containsKey ( k ) ) { + sl = new ArrayList(); + sm.put ( k, sl ); + } else { + sl = (List) sm.get ( k ); + } + assert sl != null; + sl.add ( Integer.valueOf ( uc ) ); + } + } else { + throw new IllegalArgumentException ( "invalid bidi class '" + sa[4] + "' at entry: " + line ); + } + } else { + throw new IllegalArgumentException ( "invalid unicode character database entry: " + line ); + } + } + + private static boolean isBlockStart ( String s ) { + return s.startsWith("<") && s.endsWith("First>"); + } + + private static boolean isBlockEnd ( String s ) { + return s.startsWith("<") && s.endsWith("Last>"); + } + + private static String getBlockName ( String s ) { + String[] sa = s.substring ( 1, s.length() - 1 ).split(","); + assert ( sa != null ) && ( sa.length > 0 ); + return sa[0].trim(); + } + + private static List processTypeData ( Map/**/ sm, Map/**/ im, List tdl ) { + for ( int i = BidiConstants.FIRST, k = BidiConstants.LAST; i <= k; i++ ) { + Map/**/ rm = new TreeMap/**/(); + // populate intervals from singleton map + List sl = (List) sm.get ( Integer.valueOf ( i ) ); + if ( sl != null ) { + for ( Iterator it = sl.iterator(); it.hasNext(); ) { + Integer s = (Integer) it.next(); + int uc = s.intValue(); + rm.put ( Integer.valueOf ( uc ), Integer.valueOf ( uc + 1 ) ); + } + } + // populate intervals from (block) interval map + if ( ! im.isEmpty() ) { + for ( Iterator it = im.values().iterator(); it.hasNext(); ) { + int[] ba = (int[]) it.next(); + assert ( ba != null ) && ( ba.length > 2 ); + if ( ba[2] == i ) { + rm.put ( Integer.valueOf ( ba[0] ), Integer.valueOf ( ba[1] + 1 ) ); + } + } + } + tdl.add ( createTypeData ( i, extractRanges ( rm ) ) ); + } + return tdl; + } + + private static List extractRanges ( Map/**/ rm ) { + List ranges = new ArrayList(); + int sLast = 0; + int eLast = 0; + for ( Iterator it = rm.entrySet().iterator(); it.hasNext(); ) { + Map.Entry/**/ me = (Map.Entry/**/) it.next(); + int s = ((Integer) me.getKey()).intValue(); + int e = ((Integer) me.getValue()).intValue(); + if ( s > eLast ) { + if ( eLast > sLast ) { + ranges.add ( new int[] { sLast, eLast } ); + if ( verbose ) { + if ( ( ++numTypeRanges % 10 ) == 0 ) { + System.out.print("#"); + } + } + } + sLast = s; + eLast = e; + } else if ( ( s >= sLast ) && ( e >= eLast ) ) { + eLast = e; + } + } + if ( eLast > sLast ) { + ranges.add ( new int[] { sLast, eLast } ); + if ( verbose ) { + if ( ( ++numTypeRanges % 10 ) == 0 ) { + System.out.print("#"); + } + } + } + return ranges; + } + + /** + * Read biditest data. + * + * @param bidiFileName name (as URL) of bidi test data + */ + private static void readBidiTestData(String bidiFileName) throws Exception { + BufferedReader b = new BufferedReader(new InputStreamReader(new URL(bidiFileName).openStream())); + String line; + int n; + List tdl = new ArrayList(); + List ldl = new ArrayList(); + if ( verbose ) { + System.out.print("Reading bidi test data..."); + } + for ( lineNumber = 0; ( line = b.readLine() ) != null; ) { + lineNumber++; + if ( line.length() == 0 ) { + continue; + } else if ( line.startsWith("#") ) { + continue; + } else if ( line.startsWith(PFX_TYPE) && ! ignoreDeprecatedTypeData ) { + List lines = new ArrayList(); + if ( ( n = readType ( line, b, lines ) ) < 0 ) { + break; + } else { + lineNumber += n; + tdl.add ( parseType ( lines ) ); + } + } else if ( line.startsWith(PFX_LEVELS) ) { + List lines = new ArrayList(); + if ( ( n = readLevels ( line, b, lines ) ) < 0 ) { + break; + } else { + lineNumber += n; + ldl.add ( parseLevels ( lines ) ); + } + } + } + // dump instrumentation + if ( verbose ) { + System.out.println(); + if ( ! ignoreDeprecatedTypeData ) { + System.out.println("Read type ranges : " + numTypeRanges ); + } + System.out.println("Read level specs : " + numLevelSpecs ); + System.out.println("Read test specs : " + numTestSpecs ); + System.out.println("Read lines : " + lineNumber ); + } + if ( ! ignoreDeprecatedTypeData ) { + td = (int[][]) tdl.toArray ( new int [ tdl.size() ] [] ); + } + ld = (int[][]) ldl.toArray ( new int [ ldl.size() ] [] ); + } + + private static int readType ( String line, BufferedReader b, List lines ) throws IOException { + lines.add ( line ); + return 0; + } + + private static int readLevels ( String line, BufferedReader b, List lines ) throws IOException { + boolean done = false; + int n = 0; + lines.add ( line ); + while ( ! done ) { + switch ( testPrefix ( b, PFX_LEVELS ) ) { + case 0: // within current levels + if ( ( line = b.readLine() ) != null ) { + n++; + if ( ( line.length() > 0 ) && ! line.startsWith("#") ) { + lines.add ( line ); + } + } else { + done = true; + } + break; + case 1: // end of current levels + case -1: // eof + default: + done = true; + break; + } + } + return n; + } + + private static int testPrefix ( BufferedReader b, String pfx ) throws IOException { + int rv = 0; + int pfxLen = pfx.length(); + b.mark ( pfxLen ); + for ( int i = 0, n = pfxLen; i < n; i++ ) { + int c = b.read(); + if ( c < 0 ) { + rv = -1; + break; + } else if ( c != pfx.charAt ( i ) ) { + rv = 0; + break; + } else { + rv = 1; + } + } + b.reset(); + return rv; + } + + private static int[] parseType ( List lines ) { + if ( ( lines != null ) && ( lines.size() >= 1 ) ) { + String line = (String) lines.get(0); + if ( line.startsWith(PFX_TYPE) ) { + // @Type: BIDI_CLASS ':' LWSP CHARACTER_CLASS + String[] sa = line.split ( ":" ); + if ( sa.length == 3 ) { + String bcs = sa[1].trim(); + String crs = sa[2].trim(); + int bc = parseBidiClass ( bcs ); + List rl = parseCharacterRanges ( crs ); + return createTypeData ( bc, rl ); + } + } + } + return null; + } + + private static int[] createTypeData ( int bc, List ranges ) { + int[] data = new int [ 1 + ( 2 * ranges.size() ) ]; + int k = 0; + data [ k++ ] = bc; + for ( Iterator it = ranges.iterator(); it.hasNext(); ) { + int[] r = (int[]) it.next(); + data [ k++ ] = r [ 0 ]; + data [ k++ ] = r [ 1 ]; + } + return data; + } + + private static int parseBidiClass ( String bidiClass ) { + int bc = 0; + if ( "L".equals ( bidiClass ) ) { + bc = BidiConstants.L; + } else if ( "LRE".equals ( bidiClass ) ) { + bc = BidiConstants.LRE; + } else if ( "LRO".equals ( bidiClass ) ) { + bc = BidiConstants.LRO; + } else if ( "R".equals ( bidiClass ) ) { + bc = BidiConstants.R; + } else if ( "AL".equals ( bidiClass ) ) { + bc = BidiConstants.AL; + } else if ( "RLE".equals ( bidiClass ) ) { + bc = BidiConstants.RLE; + } else if ( "RLO".equals ( bidiClass ) ) { + bc = BidiConstants.RLO; + } else if ( "PDF".equals ( bidiClass ) ) { + bc = BidiConstants.PDF; + } else if ( "EN".equals ( bidiClass ) ) { + bc = BidiConstants.EN; + } else if ( "ES".equals ( bidiClass ) ) { + bc = BidiConstants.ES; + } else if ( "ET".equals ( bidiClass ) ) { + bc = BidiConstants.ET; + } else if ( "AN".equals ( bidiClass ) ) { + bc = BidiConstants.AN; + } else if ( "CS".equals ( bidiClass ) ) { + bc = BidiConstants.CS; + } else if ( "NSM".equals ( bidiClass ) ) { + bc = BidiConstants.NSM; + } else if ( "BN".equals ( bidiClass ) ) { + bc = BidiConstants.BN; + } else if ( "B".equals ( bidiClass ) ) { + bc = BidiConstants.B; + } else if ( "S".equals ( bidiClass ) ) { + bc = BidiConstants.S; + } else if ( "WS".equals ( bidiClass ) ) { + bc = BidiConstants.WS; + } else if ( "ON".equals ( bidiClass ) ) { + bc = BidiConstants.ON; + } else { + throw new IllegalArgumentException ( "unknown bidi class: " + bidiClass ); + } + return bc; + } + + private static int parseBidiClassAny ( String bidiClass ) { + try { + return parseBidiClass ( bidiClass ); + } catch ( IllegalArgumentException e ) { + return -1; + } + } + + private static List parseCharacterRanges ( String charRanges ) { + List ranges = new ArrayList(); + CharacterIterator ci = new StringCharacterIterator ( charRanges ); + // read initial list delimiter + skipSpace ( ci ); + if ( ! readStartOfList ( ci ) ) { + badRangeSpec ( "missing initial list delimiter", charRanges ); + } + // read negation token if present + boolean negated = false; + skipSpace ( ci ); + if ( maybeReadNext ( ci, '^' ) ) { + negated = true; + } + // read item + int[] r; + skipSpace ( ci ); + if ( ( r = maybeReadItem ( ci ) ) != null ) { + ranges.add ( r ); + if ( verbose ) { + if ( ( ++numTypeRanges % 10 ) == 0 ) { + System.out.print("#"); + } + } + } else { + badRangeSpec ( "must contain at least one item", charRanges ); + } + // read more items if present + boolean more = true; + while ( more ) { + // read separator if present + String s; + skipSpace ( ci ); + if ( ( s = maybeReadSeparator ( ci ) ) != null ) { + if ( ( s.length() != 0 ) && ! s.equals("||") ) { + badRangeSpec ( "invalid item separator \"" + s + "\"", charRanges ); + } + } + // read item + skipSpace ( ci ); + if ( ( r = maybeReadItem ( ci ) ) != null ) { + ranges.add ( r ); + if ( verbose ) { + if ( ( ++numTypeRanges % 10 ) == 0 ) { + System.out.print("#"); + } + } + } else { + more = false; + } + } + // read terminating list delimiter + skipSpace ( ci ); + if ( ! readEndOfList ( ci ) ) { + badRangeSpec ( "missing terminating list delimiter", charRanges ); + } + if ( ! atEnd ( ci ) ) { + badRangeSpec ( "extraneous content prior to end of line", ci ); + } + if ( negated ) { + ranges = complementRanges ( ranges ); + } + return removeSurrogates ( ranges ); + } + + private static boolean atEnd ( CharacterIterator ci ) { + return ci.getIndex() >= ci.getEndIndex(); + } + + private static boolean readStartOfList ( CharacterIterator ci ) { + return maybeReadNext ( ci, '[' ); + } + + private static void skipSpace ( CharacterIterator ci ) { + while ( ! atEnd ( ci ) ) { + char c = ci.current(); + if ( ! Character.isWhitespace ( c ) ) { + break; + } else { + ci.next(); + } + } + } + + private static boolean maybeReadNext ( CharacterIterator ci, char next ) { + while ( ! atEnd ( ci ) ) { + char c = ci.current(); + if ( c == next ) { + ci.next(); + return true; + } else { + break; + } + } + return false; + } + + private static int[] maybeReadItem ( CharacterIterator ci ) { + // read first code point + int p1 = -1; + skipSpace ( ci ); + if ( ( p1 = maybeReadCodePoint ( ci ) ) < 0 ) { + return null; + } + // read second code point if present + int p2 = -1; + skipSpace ( ci ); + if ( maybeReadNext ( ci, '-' ) ) { + skipSpace ( ci ); + if ( ( p2 = maybeReadCodePoint ( ci ) ) < 0 ) { + badRangeSpec ( "incomplete item range, requires second item", ci ); + } + } + if ( p2 < 0 ) { + return new int[] { p1, p1 + 1 }; // convert to half open interval [ P1, P1+1 ) + } else if ( p1 <= p2 ) { + return new int[] { p1, p2 + 1 }; // convert to half open interval [ P1, P2+2 ) + } else { + badRangeSpec ( "invalid item range, second item must be greater than or equal to first item", ci ); + return null; + } + } + + private static int maybeReadCodePoint ( CharacterIterator ci ) { + if ( maybeReadNext ( ci, '\\' ) ) { + if ( maybeReadNext ( ci, 'u' ) ) { + String s = maybeReadHexDigits ( ci, 4 ); + if ( s != null ) { + return Integer.parseInt ( s, 16 ); + } else { + badRangeSpec ( "incomplete escaped code point, requires 4 hex digits", ci ); + } + } else if ( maybeReadNext ( ci, 'U' ) ) { + String s = maybeReadHexDigits ( ci, 8 ); + if ( s != null ) { + return Integer.parseInt ( s, 16 ); + } else { + badRangeSpec ( "incomplete escaped code point, requires 8 hex digits", ci ); + } + } else { + char c = ci.current(); + if ( c == CharacterIterator.DONE ) { + badRangeSpec ( "incomplete escaped code point", ci ); + } else { + ci.next(); + return (int) c; + } + } + } else { + char c = ci.current(); + if ( ( c == CharacterIterator.DONE ) || ( c == ']' ) ) { + return -1; + } else { + ci.next(); + return (int) c; + } + } + return -1; + } + + private static String maybeReadHexDigits ( CharacterIterator ci, int numDigits ) { + StringBuffer sb = new StringBuffer(); + while ( ( numDigits < 0 ) || ( sb.length() < numDigits ) ) { + char c = ci.current(); + if ( c != CharacterIterator.DONE ) { + if ( isHexDigit ( c ) ) { + ci.next(); + sb.append ( c ); + } else { + break; + } + } else { + break; + } + } + if ( ( ( numDigits < 0 ) && ( sb.length() > 0 ) ) || ( sb.length() == numDigits ) ) { + return sb.toString(); + } else { + return null; + } + } + + private static boolean isHexDigit ( char c ) { + return ( ( c >= '0' ) && ( c <= '9' ) ) || ( ( c >= 'a' ) && ( c <= 'f' ) ) || ( ( c >= 'A' ) && ( c <= 'F' ) ); + } + + private static String maybeReadSeparator ( CharacterIterator ci ) { + if ( maybeReadNext ( ci, '|' ) ) { + if ( maybeReadNext ( ci, '|' ) ) { + return "||"; + } else { + return "|"; + } + } else { + return ""; + } + } + + private static boolean readEndOfList ( CharacterIterator ci ) { + return maybeReadNext ( ci, ']' ); + } + + private static List complementRanges ( List ranges ) { + Map/**/ rm = new TreeMap/**/(); + for ( Iterator it = ranges.iterator(); it.hasNext(); ) { + int[] r = (int[]) it.next(); + rm.put ( Integer.valueOf ( r[0] ), Integer.valueOf ( r[1] ) ); + } + // add complement ranges save last + int s, e, cs = 0; + List compRanges = new ArrayList ( rm.size() + 1 ); + for ( Iterator it = rm.entrySet().iterator(); it.hasNext(); ) { + Map.Entry/**/ me = (Map.Entry/**/) it.next(); + s = ( (Integer) me.getKey() ).intValue(); + e = ( (Integer) me.getValue() ).intValue(); + if ( s > cs ) { + compRanges.add ( new int[] { cs, s } ); + } + cs = e; + } + // add trailing complement range + if ( cs < 0x110000 ) { + compRanges.add ( new int[] { cs, 0x110000 } ); + } + return compRanges; + } + + private static final int[] SURROGATES = new int[] { 0xD800, 0xE000 }; + + private static List removeSurrogates ( List ranges ) { + List rsl = new ArrayList ( ranges.size() ); + for ( Iterator it = ranges.iterator(); it.hasNext(); ) { + int[] r = (int[]) it.next(); + if ( intersectsRange ( r, SURROGATES ) ) { + rsl.addAll ( removeRange ( r, SURROGATES ) ); + } else { + rsl.add ( r ); + } + } + return rsl; + } + + /** + * Determine if range r2 intersects with range r1. + */ + private static boolean intersectsRange ( int[] r1, int[] r2 ) { + if ( r1[1] <= r2[0] ) { // r1 precedes r2 or abuts r2 on right + return false; + } else if ( r1[0] >= r2[1] ) { // r2 precedes r1 or abuts r1 on left + return false; + } else if ( ( r1[0] < r2[0] ) && ( r1[1] > r2[1] ) ) { // r1 encloses r2 + return true; + } else if ( r1[0] < r2[0] ) { // r1 precedes and overlaps r2 + return true; + } else if ( r2[1] < r1[1] ) { // r2 precedes and overlaps r1 + return true; + } else { // r2 encloses r1 + return true; + } + } + + /** + * Remove range r2 from range r1, leaving zero, one, or two + * remaining ranges. + */ + private static List removeRange ( int[] r1, int[] r2 ) { + List rl = new ArrayList(); + if ( r1[1] <= r2[0] ) { // r1 precedes r2 or abuts r2 on right + rl.add ( r1 ); + } else if ( r1[0] >= r2[1] ) { // r2 precedes r1 or abuts r1 on left + rl.add ( r1 ); + } else if ( ( r1[0] < r2[0] ) && ( r1[1] > r2[1] ) ) { // r1 encloses r2 + rl.add ( new int[] { r1[0], r2[0] } ); + rl.add ( new int[] { r2[1], r1[1] } ); + } else if ( r1[0] < r2[0] ) { // r1 precedes and overlaps r2 + rl.add ( new int[] { r1[0], r2[0] } ); + } else if ( r2[1] < r1[1] ) { // r2 precedes and overlaps r1 + rl.add ( new int[] { r2[1], r1[1] } ); + } + return rl; + } + + private static void badRangeSpec ( String reason, String charRanges ) throws IllegalArgumentException { + if ( verbose ) { + System.out.println(); + } + throw new IllegalArgumentException ( "bad range specification: " + reason + ": \"" + charRanges + "\"" ); + } + + private static void badRangeSpec ( String reason, CharacterIterator ci ) throws IllegalArgumentException { + if ( verbose ) { + System.out.println(); + } + throw new IllegalArgumentException ( "bad range specification: " + reason + ": starting at \"" + remainder ( ci ) + "\"" ); + } + + private static String remainder ( CharacterIterator ci ) { + StringBuffer sb = new StringBuffer(); + for ( char c; ( c = ci.current() ) != CharacterIterator.DONE; ) { + ci.next(); + sb.append ( c ); + } + return sb.toString(); + } + + /** + * Parse levels segment, consisting of multiple lines as follows: + * + * LEVEL_SPEC \n + * REORDER_SPEC \n + * ( TEST_SPEC \n )+ + */ + private static int[] parseLevels ( List lines ) { + int[] la = null; // levels array + int[] ra = null; // reorder array + List tal = new ArrayList(); + if ( ( lines != null ) && ( lines.size() >= 3 ) ) { + for ( Iterator it = lines.iterator(); it.hasNext(); ) { + String line = (String) it.next(); + if ( line.startsWith(PFX_LEVELS) ) { + if ( la == null ) { + la = parseLevelSpec ( line ); + if ( verbose ) { + if ( ( ++numLevelSpecs % 10 ) == 0 ) { + System.out.print("&"); + } + } + } else { + throw new IllegalArgumentException ( "redundant levels array: \"" + line + "\"" ); + } + } else if ( line.startsWith(PFX_REORDER) ) { + if ( la == null ) { + throw new IllegalArgumentException ( "missing levels array before: \"" + line + "\"" ); + } else if ( ra == null ) { + ra = parseReorderSpec ( line, la ); + } else { + throw new IllegalArgumentException ( "redundant reorder array: \"" + line + "\"" ); + } + } else if ( ( la != null ) && ( ra != null ) ) { + int[] ta = parseTestSpec ( line, la ); + if ( ta != null ) { + if ( verbose ) { + if ( ( ++numTestSpecs % 100 ) == 0 ) { + System.out.print("!"); + } + } + tal.add ( ta ); + } + } else if ( la == null ) { + throw new IllegalArgumentException ( "missing levels array before: \"" + line + "\"" ); + } else if ( ra == null ) { + throw new IllegalArgumentException ( "missing reorder array before: \"" + line + "\"" ); + } + } + } + if ( ( la != null ) && ( ra != null ) ) { + return createLevelData ( la, ra, tal ); + } else { + return null; + } + } + + private static int[] createLevelData ( int[] la, int[] ra, List tal ) { + int nl = la.length; + int[] data = new int [ 1 + nl * 2 + ( ( nl + 1 ) * tal.size() ) ]; + int k = 0; + data [ k++ ] = nl; + for ( int i = 0, n = nl; i < n; i++ ) { + data [ k++ ] = la [ i ]; + } + int nr = ra.length; + for ( int i = 0, n = nr; i < n; i++ ) { + data [ k++ ] = ra [ i ]; + } + for ( Iterator it = tal.iterator(); it.hasNext(); ) { + int[] ta = (int[]) it.next(); + if ( ta == null ) { + throw new IllegalStateException ( "null test array" ); + } else if ( ta.length == ( nl + 1 ) ) { + for ( int i = 0, n = ta.length; i < n; i++ ) { + data [ k++ ] = ta [ i ]; + } + } else { + throw new IllegalStateException ( "test array length error, expected " + ( nl + 1 ) + " entries, got " + ta.length + " entries" ); + } + } + assert k == data.length; + return data; + } + + /** + * Parse level specification, which follows the following syntax: + * + * @Levels: ( LWSP ( NUMBER | 'x' ) )+ + */ + private static int[] parseLevelSpec ( String line ) { + CharacterIterator ci = new StringCharacterIterator ( line ); + List ll = new ArrayList(); + // read prefix + skipSpace ( ci ); + if ( ! maybeReadToken ( ci, PFX_LEVELS ) ) { + badLevelSpec ( "missing prefix \"" + PFX_LEVELS + "\"", ci ); + } + // read level values + boolean more = true; + while ( more ) { + Integer l; + skipSpace ( ci ); + if ( ( l = maybeReadInteger ( ci ) ) != null ) { + ll.add ( l ); + } else if ( maybeReadToken ( ci, "x" ) ) { + ll.add ( Integer.valueOf ( -1 ) ); + } else { + more = false; + } + } + // read to end of line + skipSpace ( ci ); + if ( ! atEnd ( ci ) ) { + badLevelSpec ( "extraneous content prior to end of line", ci ); + } + if ( ll.size() == 0 ) { + badLevelSpec ( "must have at least one level value", ci ); + } + return createLevelsArray ( ll ); + } + + private static Integer maybeReadInteger ( CharacterIterator ci ) { + // read optional minus sign if present + boolean negative; + if ( maybeReadNext ( ci, '-' ) ) { + negative = true; + } else { + negative = false; + } + // read digits + StringBuffer sb = new StringBuffer(); + while ( true ) { + char c = ci.current(); + if ( ( c != CharacterIterator.DONE ) && isDigit ( c ) ) { + ci.next(); + sb.append ( c ); + } else { + break; + } + } + if ( sb.length() == 0 ) { + return null; + } else { + int value = Integer.parseInt ( sb.toString() ); + if ( negative ) { + value = -value; + } + return Integer.valueOf ( value ); + } + } + + private static boolean isDigit ( char c ) { + return ( ( c >= '0' ) && ( c <= '9' ) ); + } + + private static boolean maybeReadToken ( CharacterIterator ci, String s ) { + int startIndex = ci.getIndex(); + for ( int i = 0, n = s.length(); i < n; i++ ) { + char c = s.charAt ( i ); + if ( ci.current() == c ) { + ci.next(); + } else { + ci.setIndex ( startIndex ); + return false; + } + } + return true; + } + + private static void badLevelSpec ( String reason, CharacterIterator ci ) throws IllegalArgumentException { + if ( verbose ) { + System.out.println(); + } + throw new IllegalArgumentException ( "bad level specification: " + reason + ": starting at \"" + remainder ( ci ) + "\"" ); + } + + private static int[] createLevelsArray ( List levels ) { + int[] la = new int [ levels.size() ]; + int k = 0; + for ( Iterator it = levels.iterator(); it.hasNext(); ) { + la [ k++ ] = ( (Integer) it.next() ).intValue(); + } + return la; + } + + /** + * Parse reorder specification, which follows the following syntax: + * + * @Reorder: ( LWSP NUMBER )* + */ + private static int[] parseReorderSpec ( String line, int[] levels ) { + CharacterIterator ci = new StringCharacterIterator ( line ); + List rl = new ArrayList(); + // read prefix + skipSpace ( ci ); + if ( ! maybeReadToken ( ci, PFX_REORDER ) ) { + badReorderSpec ( "missing prefix \"" + PFX_REORDER + "\"", ci ); + } + // read reorder values + boolean more = true; + while ( more ) { + skipSpace ( ci ); + Integer l; + if ( ( l = maybeReadInteger ( ci ) ) != null ) { + rl.add ( l ); + } else { + more = false; + } + } + // read to end of line + skipSpace ( ci ); + if ( ! atEnd ( ci ) ) { + badReorderSpec ( "extraneous content prior to end of line", ci ); + } + return createReorderArray ( rl, levels ); + } + + private static void badReorderSpec ( String reason, CharacterIterator ci ) throws IllegalArgumentException { + if ( verbose ) { + System.out.println(); + } + throw new IllegalArgumentException ( "bad reorder specification: " + reason + ": starting at \"" + remainder ( ci ) + "\"" ); + } + + private static int[] createReorderArray ( List reorders, int[] levels ) { + int nr = reorders.size(); + int nl = levels.length; + if ( nr <= nl ) { + int[] ra = new int [ nl ]; + Iterator it = reorders.iterator(); + for ( int i = 0, n = nl; i < n; i++ ) { + int r = -1; + if ( levels [ i ] >= 0 ) { + if ( it.hasNext() ) { + r = ( (Integer) it.next() ).intValue(); + } + } + ra [ i ] = r; + } + return ra; + } else { + throw new IllegalArgumentException ( "excessive number of reorder array entries, expected no more than " + nl + ", but got " + nr + " entries" ); + } + } + + /** + * Parse test specification, which follows the following syntax: + * + * BIDI_CLASS ( LWSP BIDI_CLASS )+ ';' LWSP NUMBER + */ + private static int[] parseTestSpec ( String line, int[] levels ) { + CharacterIterator ci = new StringCharacterIterator ( line ); + List cl = new ArrayList(); + // read bidi class identifier sequence + while ( ! atEnd ( ci ) && ! maybeReadNext ( ci, ';' ) ) { + skipSpace ( ci ); + int bc; + if ( ( bc = maybeReadBidiClass ( ci ) ) >= 0 ) { + cl.add ( Integer.valueOf ( bc ) ); + } else { + break; + } + } + // read bit set + skipSpace ( ci ); + String s; + int bs = 0; + if ( ( s = maybeReadHexDigits ( ci, -1 ) ) != null ) { + bs = Integer.parseInt ( s, 16 ); + } else { + badTestSpec ( "missing bit set", ci ); + } + // read to end of line + skipSpace ( ci ); + if ( ! atEnd ( ci ) ) { + badTestSpec ( "extraneous content prior to end of line", ci ); + } + return createTestArray ( cl, bs, levels ); + } + + private static String maybeReadIdentifier ( CharacterIterator ci ) { + // read keyword chars ([A-Z]) + StringBuffer sb = new StringBuffer(); + while ( true ) { + char c = ci.current(); + if ( c == CharacterIterator.DONE ) { + break; + } else if ( sb.length() == 0 ) { + if ( Character.isUnicodeIdentifierStart ( c ) ) { + ci.next(); + sb.append ( c ); + } else { + break; + } + } else { + if ( Character.isUnicodeIdentifierPart ( c ) ) { + ci.next(); + sb.append ( c ); + } else { + break; + } + } + } + if ( sb.length() == 0 ) { + return null; + } else { + return sb.toString(); + } + } + + private static int maybeReadBidiClass ( CharacterIterator ci ) { + int bc = -1; + int i = ci.getIndex(); + String s; + if ( ( s = maybeReadIdentifier ( ci ) ) != null ) { + try { + bc = parseBidiClass ( s ); + } catch ( IllegalArgumentException e ) { + throw e; + } + } + if ( bc < 0 ) { + ci.setIndex ( i ); + } + return bc; + } + + private static void badTestSpec ( String reason, CharacterIterator ci ) throws IllegalArgumentException { + if ( verbose ) { + System.out.println(); + } + throw new IllegalArgumentException ( "bad test specification: " + reason + ": starting at \"" + remainder ( ci ) + "\"" ); + } + + private static int[] createTestArray ( List classes, int bitset, int[] levels ) { + int nc = classes.size(); + if ( nc <= levels.length ) { + int[] ta = new int [ 1 + nc ]; + int k = 0; + ta [ k++ ] = bitset; + for ( Iterator it = classes.iterator(); it.hasNext(); ) { + ta [ k++ ] = ( (Integer) it.next() ).intValue(); + } + return ta; + } else { + throw new IllegalArgumentException ( "excessive number of test array entries, expected no more than " + levels.length + ", but got " + nc + " entries" ); + } + } + + /** + * Dump data arrays to output and resource files. + * @param out - bidi test data java class file print writer + * @param outFileName - (full path) name of bidi test data java class file + */ + private static void dumpData ( PrintWriter out, String outFileName ) throws IOException { + File f = new File ( outFileName ); + File p = f.getParentFile(); + if ( td != null ) { + String pfxTD = "TD"; + dumpResourcesDescriptor ( out, pfxTD, td.length ); + dumpResourcesData ( p, f.getName(), pfxTD, td ); + } + if ( ld != null ) { + String pfxTD = "LD"; + dumpResourcesDescriptor ( out, pfxTD, ld.length ); + dumpResourcesData ( p, f.getName(), pfxTD, ld ); + } + } + + private static void dumpResourcesDescriptor ( PrintWriter out, String prefix, int numResources ) { + out.println ( " public static final String " + prefix + "_PFX = \"" + prefix + "\";" ); + out.println ( " public static final int " + prefix + "_CNT = " + numResources + ";" ); + out.println(""); + } + + private static void dumpResourcesData ( File btcDir, String btcName, String prefix, int[][] data ) throws IOException { + String btdName = extractDataFileName ( btcName ); + for ( int i = 0, n = data.length; i < n; i++ ) { + File f = new File ( btcDir, btdName + "$" + prefix + i + ".ser" ); + ObjectOutputStream os = new ObjectOutputStream ( new FileOutputStream ( f ) ); + os.writeObject ( data[i] ); + os.close(); + } + } + + private static final String JAVA_EXT = ".java"; + + private static String extractDataFileName ( String btcName ) { + if ( btcName.endsWith ( JAVA_EXT ) ) { + return btcName.substring ( 0, btcName.length() - JAVA_EXT.length() ); + } else { + return btcName; + } + } + + /** + * Main entry point for generator. + * @param args array of command line arguments + */ + public static void main(String[] args) { + String bidiFileName = "http://www.unicode.org/Public/UNIDATA/BidiTest.txt"; + String ucdFileName = "http://www.unicode.org/Public/UNIDATA/BidiTest.txt"; + String outFileName = "BidiTestData.java"; + boolean ok = true; + for (int i = 0; ok && ( i < args.length ); i++) { + String opt = args[i]; + if ("-b".equals(opt)) { + if ( ( i + 1 ) <= args.length ) { + bidiFileName = args[++i]; + } else { + ok = false; + } + } else if ("-d".equals(opt)) { + if ( ( i + 1 ) <= args.length ) { + ucdFileName = args[++i]; + } else { + ok = false; + } + } else if ("-i".equals(opt)) { + ignoreDeprecatedTypeData = true; + } else if ("-o".equals(opt)) { + if ( ( i + 1 ) <= args.length ) { + outFileName = args[++i]; + } else { + ok = false; + } + } else if ("-v".equals(opt)) { + verbose = true; + } else { + ok = false; + } + } + if ( ! ok ) { + System.out.println("Usage: GenerateBidiTestData [-v] [-i] [-d ] [-b ] [-o ]"); + System.out.println(" defaults:"); + if ( ignoreDeprecatedTypeData ) { + System.out.println(" : " + ucdFileName); + } + System.out.println(" : " + bidiFileName); + System.out.println(" : " + outFileName); + } else { + try { + convertBidiTestData(ucdFileName, bidiFileName, outFileName); + System.out.println("Generated " + outFileName + " from"); + if ( ignoreDeprecatedTypeData ) { + System.out.println(" : " + ucdFileName); + } + System.out.println(" : " + bidiFileName); + } catch (Exception e) { + System.out.println("An unexpected error occured at line: " + lineNumber ); + e.printStackTrace(); + } + } + } +} diff --git a/src/documentation/content/xdocs/trunk/configuration.xml b/src/documentation/content/xdocs/trunk/configuration.xml index e5469d037..aae353922 100644 --- a/src/documentation/content/xdocs/trunk/configuration.xml +++ b/src/documentation/content/xdocs/trunk/configuration.xml @@ -151,6 +151,21 @@ specification describes. false + + complex-scripts + attribute disabled (optional) + + If present and if an attribute 'disabled' is specified with the value 'false', then + complex script features are disabled. The same result can be obtained on an FOP + per-invocation basis by specifying a '-nocs' command line option when invoking FOP. + When complex script features are disabled, all bidirectional processing and complex + character to glyph mapping processing is disabled; in addition, the loading of + GDEF, GSUB, and GPOS advanced typographic tables is disabled for OpenType and + TrueType fonts. Unless disabled by this mechanism or by use of the '-nocs' command + line option, complex script features will be enabled by default. + + n/a + default-page-settings n/a diff --git a/src/documentation/intermediate-format-ng/fop-intermediate-format-ng-content.xsd b/src/documentation/intermediate-format-ng/fop-intermediate-format-ng-content.xsd index ac7357f8c..695d724fe 100644 --- a/src/documentation/intermediate-format-ng/fop-intermediate-format-ng-content.xsd +++ b/src/documentation/intermediate-format-ng/fop-intermediate-format-ng-content.xsd @@ -100,10 +100,10 @@ - - - - + + + + diff --git a/src/foschema/fop-configuration.xsd b/src/foschema/fop-configuration.xsd index 9ceec1717..af85115b2 100644 --- a/src/foschema/fop-configuration.xsd +++ b/src/foschema/fop-configuration.xsd @@ -48,6 +48,11 @@ + + + + diff --git a/src/java/org/apache/fop/apps/FOUserAgent.java b/src/java/org/apache/fop/apps/FOUserAgent.java index 7d1736586..c13a624cf 100644 --- a/src/java/org/apache/fop/apps/FOUserAgent.java +++ b/src/java/org/apache/fop/apps/FOUserAgent.java @@ -653,6 +653,24 @@ public class FOUserAgent { this.conserveMemoryPolicy = conserveMemoryPolicy; } + /** + * Check whether complex script features are enabled. + * + * @return true if FOP is to use complex script features + */ + public boolean isComplexScriptFeaturesEnabled() { + return factory.isComplexScriptFeaturesEnabled(); + } + + /** + * Control whether complex script features should be enabled + * + * @param useComplexScriptFeatures true if FOP is to use complex script features + */ + public void setComplexScriptFeaturesEnabled(boolean useComplexScriptFeatures) { + factory.setComplexScriptFeaturesEnabled ( useComplexScriptFeatures ); + } + /** * Activates accessibility (for output formats that support it). * diff --git a/src/java/org/apache/fop/apps/FopFactory.java b/src/java/org/apache/fop/apps/FopFactory.java index 2aca8bf99..18c84a036 100644 --- a/src/java/org/apache/fop/apps/FopFactory.java +++ b/src/java/org/apache/fop/apps/FopFactory.java @@ -143,6 +143,10 @@ public class FopFactory implements ImageContext { /** Page width */ private String pageWidth = FopFactoryConfigurator.DEFAULT_PAGE_WIDTH; + /** Complex scripts support enabled */ + private boolean useComplexScriptFeatures + = FopFactoryConfigurator.DEFAULT_COMPLEX_SCRIPT_FEATURES; + /** @see #setBreakIndentInheritanceOnReferenceAreaBoundary(boolean) */ private boolean breakIndentInheritanceOnReferenceAreaBoundary = FopFactoryConfigurator.DEFAULT_BREAK_INDENT_INHERITANCE; @@ -211,6 +215,19 @@ public class FopFactory implements ImageContext { return accessibility; } + /** + * Sets complex script support. + * @param value true to enable complex script features, + * false otherwise + */ + void setComplexScriptFeaturesEnabled(boolean value) { + this.useComplexScriptFeatures = value; + } + + boolean isComplexScriptFeaturesEnabled() { + return useComplexScriptFeatures; + } + /** * Returns a new {@link Fop} instance. FOP will be configured with a default user agent * instance. diff --git a/src/java/org/apache/fop/apps/FopFactoryConfigurator.java b/src/java/org/apache/fop/apps/FopFactoryConfigurator.java index 9097f23e3..4ed59d0fe 100644 --- a/src/java/org/apache/fop/apps/FopFactoryConfigurator.java +++ b/src/java/org/apache/fop/apps/FopFactoryConfigurator.java @@ -69,6 +69,9 @@ public class FopFactoryConfigurator { /** Defines the default target resolution (72dpi) for FOP */ public static final float DEFAULT_TARGET_RESOLUTION = GraphicsConstants.DEFAULT_DPI; //dpi + /** Defines the default complex script support */ + public static final boolean DEFAULT_COMPLEX_SCRIPT_FEATURES = true; + private static final String PREFER_RENDERER = "prefer-renderer"; /** logger instance */ @@ -269,6 +272,13 @@ public class FopFactoryConfigurator { } } + // configure complex script support + Configuration csConfig = cfg.getChild("complex-scripts"); + if (csConfig != null) { + this.factory.setComplexScriptFeaturesEnabled + (!csConfig.getAttributeAsBoolean ( "disabled", false )); + } + // configure font manager new FontManagerConfigurator(cfg, baseURI).configure(factory.getFontManager(), strict); diff --git a/src/java/org/apache/fop/area/Area.java b/src/java/org/apache/fop/area/Area.java index 1f14ed740..435876d65 100644 --- a/src/java/org/apache/fop/area/Area.java +++ b/src/java/org/apache/fop/area/Area.java @@ -25,6 +25,7 @@ import java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.fop.traits.BorderProps; +import org.apache.fop.traits.WritingModeTraitsGetter; // If the area appears more than once in the output // or if the area has external data it is cached @@ -41,27 +42,6 @@ public class Area extends AreaTreeObject implements Serializable { private static final long serialVersionUID = 6342888466142626492L; - // stacking directions - /** - * Stacking left to right - */ - public static final int LR = 0; - - /** - * Stacking right to left - */ - public static final int RL = 1; - - /** - * Stacking top to bottom - */ - public static final int TB = 2; - - /** - * Stacking bottom to top - */ - public static final int BT = 3; - // orientations for reference areas /** * Normal orientation @@ -129,17 +109,21 @@ public class Area extends AreaTreeObject implements Serializable { /** the area's block-progression-dimension */ protected int bpd; + /** + * Resolved bidirectional level for area. + */ + protected int bidiLevel = -1; + /** * Traits for this area stored in a HashMap */ - protected Map props = null; + protected transient Map traits = null; /** * logging instance */ protected static final Log log = LogFactory.getLog(Area.class); - /** * Get the area class of this area. * @@ -225,6 +209,32 @@ public class Area extends AreaTreeObject implements Serializable { + getBorderAndPaddingWidthAfter() + getSpaceAfter(); } + /** + * Set the bidirectional embedding level. + * + * @param bidiLevel the bidirectional embedding level + */ + public void setBidiLevel ( int bidiLevel ) { + this.bidiLevel = bidiLevel; + } + + /** + * Reset the bidirectional embedding level to default + * value (-1). + */ + public void resetBidiLevel() { + setBidiLevel(-1); + } + + /** + * Get the bidirectional embedding level. + * + * @return the bidirectional embedding level + */ + public int getBidiLevel() { + return bidiLevel; + } + /** * Return the sum of region border- and padding-before * @@ -379,10 +389,23 @@ public class Area extends AreaTreeObject implements Serializable { * @param prop the value of the trait */ public void addTrait(Integer traitCode, Object prop) { - if (props == null) { - props = new java.util.HashMap(20); + if (traits == null) { + traits = new java.util.HashMap(20); + } + traits.put(traitCode, prop); + } + + /** + * Set traits on this area, copying from an existing traits map. + * + * @param traits the map of traits + */ + public void setTraits ( Map traits ) { + if ( traits != null ) { + this.traits = new java.util.HashMap ( traits ); + } else { + this.traits = null; } - props.put(traitCode, prop); } /** @@ -391,12 +414,12 @@ public class Area extends AreaTreeObject implements Serializable { * @return the map of traits */ public Map getTraits() { - return this.props; + return this.traits; } /** @return true if the area has traits */ public boolean hasTraits() { - return (this.props != null); + return (this.traits != null); } /** @@ -406,7 +429,7 @@ public class Area extends AreaTreeObject implements Serializable { * @return the trait value */ public Object getTrait(Integer traitCode) { - return (props != null ? props.get(traitCode) : null); + return (traits != null ? traits.get(traitCode) : null); } /** @@ -444,6 +467,14 @@ public class Area extends AreaTreeObject implements Serializable { } } + /** + * Sets the writing mode traits for this area. Default implementation + * does nothing. + * @param wmtg a WM traits getter + */ + public void setWritingModeTraits(WritingModeTraitsGetter wmtg) { + } + /** * {@inheritDoc} * @return ipd and bpd of area @@ -457,4 +488,3 @@ public class Area extends AreaTreeObject implements Serializable { return sb.toString(); } } - diff --git a/src/java/org/apache/fop/area/AreaTreeHandler.java b/src/java/org/apache/fop/area/AreaTreeHandler.java index 6448e7c5d..c87a728e6 100644 --- a/src/java/org/apache/fop/area/AreaTreeHandler.java +++ b/src/java/org/apache/fop/area/AreaTreeHandler.java @@ -73,6 +73,9 @@ public class AreaTreeHandler extends FOEventHandler { /** The AreaTreeModel in use */ protected AreaTreeModel model; + // Flag for controlling complex script features (default: true). + private boolean useComplexScriptFeatures = true; + // Keeps track of all meaningful id references private IDTracker idTracker; @@ -108,6 +111,8 @@ public class AreaTreeHandler extends FOEventHandler { this.idTracker = new IDTracker(); + this.useComplexScriptFeatures = userAgent.isComplexScriptFeaturesEnabled(); + if (log.isDebugEnabled()) { statistics = new Statistics(); } @@ -168,6 +173,15 @@ public class AreaTreeHandler extends FOEventHandler { return this.results; } + /** + * Check whether complex script features are enabled. + * + * @return true if using complex script features + */ + public boolean isComplexScriptFeaturesEnabled() { + return useComplexScriptFeatures; + } + /** * Prepare AreaTreeHandler for document processing This is called from * FOTreeBuilder.startDocument() diff --git a/src/java/org/apache/fop/area/AreaTreeParser.java b/src/java/org/apache/fop/area/AreaTreeParser.java index d8c22f2e8..961160a55 100644 --- a/src/java/org/apache/fop/area/AreaTreeParser.java +++ b/src/java/org/apache/fop/area/AreaTreeParser.java @@ -700,7 +700,7 @@ public class AreaTreeParser { public void startElement(Attributes attributes) { InlineArea inl = new InlineArea(); transferForeignObjects(attributes, inl); - inl.setOffset(XMLUtil.getAttributeAsInt(attributes, "offset", 0)); + inl.setBlockProgressionOffset(XMLUtil.getAttributeAsInt(attributes, "offset", 0)); setAreaAttributes(attributes, inl); setTraits(attributes, inl, SUBSET_COMMON); setTraits(attributes, inl, SUBSET_BOX); @@ -720,7 +720,7 @@ public class AreaTreeParser { public void startElement(Attributes attributes) { InlineParent ip = new InlineParent(); transferForeignObjects(attributes, ip); - ip.setOffset(XMLUtil.getAttributeAsInt(attributes, "offset", 0)); + ip.setBlockProgressionOffset(XMLUtil.getAttributeAsInt(attributes, "offset", 0)); setAreaAttributes(attributes, ip); setTraits(attributes, ip, SUBSET_COMMON); setTraits(attributes, ip, SUBSET_BOX); @@ -741,7 +741,7 @@ public class AreaTreeParser { public void startElement(Attributes attributes) { InlineBlockParent ibp = new InlineBlockParent(); transferForeignObjects(attributes, ibp); - ibp.setOffset(XMLUtil.getAttributeAsInt(attributes, "offset", 0)); + ibp.setBlockProgressionOffset(XMLUtil.getAttributeAsInt(attributes, "offset", 0)); setAreaAttributes(attributes, ibp); setTraits(attributes, ibp, SUBSET_COMMON); setTraits(attributes, ibp, SUBSET_BOX); @@ -769,7 +769,7 @@ public class AreaTreeParser { setTraits(attributes, text, SUBSET_COLOR); setTraits(attributes, text, SUBSET_FONT); text.setBaselineOffset(XMLUtil.getAttributeAsInt(attributes, "baseline", 0)); - text.setOffset(XMLUtil.getAttributeAsInt(attributes, "offset", 0)); + text.setBlockProgressionOffset(XMLUtil.getAttributeAsInt(attributes, "offset", 0)); text.setTextLetterSpaceAdjust(XMLUtil.getAttributeAsInt(attributes, "tlsadjust", 0)); text.setTextWordSpaceAdjust(XMLUtil.getAttributeAsInt(attributes, @@ -791,8 +791,14 @@ public class AreaTreeParser { int[] letterAdjust = ConversionUtils.toIntArray( lastAttributes.getValue("letter-adjust"), "\\s"); + int level = XMLUtil.getAttributeAsInt(lastAttributes, "level", -1); + boolean reversed = XMLUtil.getAttributeAsBoolean(lastAttributes, "reversed", false); + int[][] gposAdjustments + = XMLUtil.getAttributeAsPositionAdjustments(lastAttributes, "position-adjust"); content.flip(); - WordArea word = new WordArea(content.toString().trim(), offset, letterAdjust); + WordArea word = new WordArea + ( offset, level, content.toString().trim(), letterAdjust, + null, gposAdjustments, reversed ); AbstractTextArea text = getCurrentText(); word.setParentArea(text); text.addChildArea(word); @@ -811,7 +817,8 @@ public class AreaTreeParser { if (content.position() > 0) { content.flip(); boolean adjustable = XMLUtil.getAttributeAsBoolean(lastAttributes, "adj", true); - SpaceArea space = new SpaceArea(content.charAt(0), offset, adjustable); + int level = XMLUtil.getAttributeAsInt(lastAttributes, "level", -1); + SpaceArea space = new SpaceArea(offset, level, content.charAt(0), adjustable); AbstractTextArea text = getCurrentText(); space.setParentArea(text); text.addChildArea(space); @@ -821,7 +828,7 @@ public class AreaTreeParser { setTraits(lastAttributes, space, SUBSET_COMMON); setTraits(lastAttributes, space, SUBSET_BOX); setTraits(lastAttributes, space, SUBSET_COLOR); - space.setOffset(offset); + space.setBlockProgressionOffset(offset); Area parent = (Area)areaStack.peek(); parent.addChildArea(space); } @@ -842,7 +849,8 @@ public class AreaTreeParser { setTraits(attributes, leader, SUBSET_BOX); setTraits(attributes, leader, SUBSET_COLOR); setTraits(attributes, leader, SUBSET_FONT); - leader.setOffset(XMLUtil.getAttributeAsInt(attributes, "offset", 0)); + leader.setBlockProgressionOffset + ( XMLUtil.getAttributeAsInt(attributes, "offset", 0) ); String ruleStyle = attributes.getValue("ruleStyle"); if (ruleStyle != null) { leader.setRuleStyle(ruleStyle); @@ -857,7 +865,8 @@ public class AreaTreeParser { private class InlineViewportMaker extends AbstractMaker { public void startElement(Attributes attributes) { - InlineViewport viewport = new InlineViewport(null); + int level = XMLUtil.getAttributeAsInt(attributes, "level", -1); + InlineViewport viewport = new InlineViewport(null, level); transferForeignObjects(attributes, viewport); setAreaAttributes(attributes, viewport); setTraits(attributes, viewport, SUBSET_COMMON); @@ -865,7 +874,8 @@ public class AreaTreeParser { setTraits(attributes, viewport, SUBSET_COLOR); viewport.setContentPosition(XMLUtil.getAttributeAsRectangle2D(attributes, "pos")); viewport.setClip(XMLUtil.getAttributeAsBoolean(attributes, "clip", false)); - viewport.setOffset(XMLUtil.getAttributeAsInt(attributes, "offset", 0)); + viewport.setBlockProgressionOffset + ( XMLUtil.getAttributeAsInt(attributes, "offset", 0) ); Area parent = (Area)areaStack.peek(); parent.addChildArea(viewport); areaStack.push(viewport); @@ -1025,6 +1035,7 @@ public class AreaTreeParser { private void setAreaAttributes(Attributes attributes, Area area) { area.setIPD(Integer.parseInt(attributes.getValue("ipd"))); area.setBPD(Integer.parseInt(attributes.getValue("bpd"))); + area.setBidiLevel(XMLUtil.getAttributeAsInt(attributes, "level", -1)); } private static final Object[] SUBSET_COMMON = new Object[] { diff --git a/src/java/org/apache/fop/area/Block.java b/src/java/org/apache/fop/area/Block.java index 423dcfafa..c6e31f71d 100644 --- a/src/java/org/apache/fop/area/Block.java +++ b/src/java/org/apache/fop/area/Block.java @@ -58,7 +58,6 @@ public class Block extends BlockParent { */ public static final int FIXED = 3; - private int stacking = TB; private int positioning = STACK; /** if true, allow BPD update */ @@ -133,5 +132,13 @@ public class Block extends BlockParent { return (startIndent != null ? startIndent : 0); } + /** + * @return the end-indent trait + */ + public int getEndIndent() { + Integer endIndent = (Integer)getTrait(Trait.END_INDENT); + return (endIndent != null ? endIndent : 0); + } + } diff --git a/src/java/org/apache/fop/area/BodyRegion.java b/src/java/org/apache/fop/area/BodyRegion.java index 2dd8a9a7c..2fd0b014b 100644 --- a/src/java/org/apache/fop/area/BodyRegion.java +++ b/src/java/org/apache/fop/area/BodyRegion.java @@ -22,6 +22,7 @@ package org.apache.fop.area; import java.util.List; import org.apache.fop.fo.pagination.RegionBody; +import org.apache.fop.traits.WritingModeTraitsGetter; /** * This class is a container for the areas that may be generated by @@ -139,6 +140,17 @@ public class BodyRegion extends RegionReference { return getBPD() - usedBPD; } + /** + * Sets the writing mode traits for the main reference area of + * this body region area. + * @param wmtg a WM traits getter + */ + public void setWritingModeTraits(WritingModeTraitsGetter wmtg) { + if ( getMainReference() != null ) { + getMainReference().setWritingModeTraits ( wmtg ); + } + } + /** * Clone this object. * diff --git a/src/java/org/apache/fop/area/CTM.java b/src/java/org/apache/fop/area/CTM.java index 07c3bbc02..73943ed65 100644 --- a/src/java/org/apache/fop/area/CTM.java +++ b/src/java/org/apache/fop/area/CTM.java @@ -25,10 +25,12 @@ import java.awt.geom.Rectangle2D; import java.io.Serializable; import org.apache.fop.datatypes.FODimension; +import org.apache.fop.traits.WritingMode; import static org.apache.fop.fo.Constants.EN_LR_TB; import static org.apache.fop.fo.Constants.EN_RL_TB; import static org.apache.fop.fo.Constants.EN_TB_RL; +import static org.apache.fop.fo.Constants.EN_TB_LR; /** * Describe a PDF or PostScript style coordinate transformation matrix (CTM). @@ -42,7 +44,7 @@ public class CTM implements Serializable { private double a, b, c, d, e, f; private static final CTM CTM_LRTB = new CTM(1, 0, 0, 1, 0, 0); - private static final CTM CTM_RLTB = new CTM(-1, 0, 0, 1, 0, 0); + private static final CTM CTM_RLTB = new CTM(1, 0, 0, 1, 0, 0); private static final CTM CTM_TBRL = new CTM(0, 1, -1, 0, 0, 0); /** @@ -126,28 +128,25 @@ public class CTM implements Serializable { * Return a CTM which will transform coordinates for a particular writing-mode * into normalized first quandrant coordinates. * @param wm A writing mode constant from fo.properties.WritingMode, ie. - * one of LR_TB, RL_TB, TB_RL. + * one of LR_TB, RL_TB, TB_RL, TB_LR. * @param ipd The inline-progression dimension of the reference area whose * CTM is being set.. * @param bpd The block-progression dimension of the reference area whose * CTM is being set. * @return a new CTM with the required transform */ - public static CTM getWMctm(int wm, int ipd, int bpd) { + public static CTM getWMctm(WritingMode wm, int ipd, int bpd) { CTM wmctm; - switch (wm) { + switch (wm.getEnumValue()) { case EN_LR_TB: return new CTM(CTM_LRTB); case EN_RL_TB: - wmctm = new CTM(CTM_RLTB); - wmctm.e = ipd; - return wmctm; - //return CTM_RLTB.translate(ipd, 0); + return new CTM(CTM_RLTB); case EN_TB_RL: // CJK + case EN_TB_LR: // CJK wmctm = new CTM(CTM_TBRL); wmctm.e = bpd; return wmctm; - //return CTM_TBRL.translate(0, ipd); default: return null; } @@ -284,7 +283,7 @@ public class CTM implements Serializable { * @return CTM the coordinate transformation matrix (CTM) */ public static CTM getCTMandRelDims(int absRefOrient, - int writingMode, + WritingMode writingMode, Rectangle2D absVPrect, FODimension reldims) { int width, height; @@ -335,12 +334,18 @@ public class CTM implements Serializable { * can set ipd and bpd appropriately based on the writing mode. */ - if (writingMode == EN_LR_TB || writingMode == EN_RL_TB) { + switch ( writingMode.getEnumValue() ) { + default: + case EN_LR_TB: + case EN_RL_TB: reldims.ipd = width; reldims.bpd = height; - } else { + break; + case EN_TB_LR: + case EN_TB_RL: reldims.ipd = height; reldims.bpd = width; + break; } // Set a rectangle to be the writing-mode relative version??? // Now transform for writing mode diff --git a/src/java/org/apache/fop/area/LineArea.java b/src/java/org/apache/fop/area/LineArea.java index edf60578a..1d3262487 100644 --- a/src/java/org/apache/fop/area/LineArea.java +++ b/src/java/org/apache/fop/area/LineArea.java @@ -21,6 +21,7 @@ package org.apache.fop.area; import java.io.Serializable; import java.util.ArrayList; +import java.util.Iterator; import java.util.List; import org.apache.fop.area.inline.InlineArea; @@ -124,6 +125,24 @@ public class LineArea extends Area { inlineAreas.add(area); } + /** + *

Set (en masse) the inline child areas of this line area.

+ *

Used by bidirectional processing after line area consituent reordering.

+ * @param inlineAreas the list of inline areas + */ + public void setInlineAreas ( List inlineAreas ) { + for ( Iterator it = inlineAreas.iterator(); it.hasNext();) { + InlineArea ia = it.next(); + Area pa = ia.getParentArea(); + if ( pa == null ) { + ia.setParentArea ( this ); + } else { + assert pa == this; + } + } + this.inlineAreas = inlineAreas; + } + /** * Get the inline child areas of this line area. * @@ -148,6 +167,21 @@ public class LineArea extends Area { } } + /** + * Get the end indent of this line area. + * The end indent is used for offsetting the end of + * the inline areas for alignment or other indents. + * + * @return the end indent value + */ + public int getEndIndent() { + if (hasTrait(Trait.END_INDENT)) { + return getTraitAsInteger(Trait.END_INDENT); + } else { + return 0; + } + } + /** * Updates the extents of the line area from its children. */ @@ -178,17 +212,21 @@ public class LineArea extends Area { * @param ipdVariation the difference between old and new ipd */ public void handleIPDVariation(int ipdVariation) { + int si = getStartIndent(); + int ei = getEndIndent(); switch (adjustingInfo.lineAlignment) { case EN_START: - // nothing to do in this case + // adjust end indent + addTrait(Trait.END_INDENT, ei - ipdVariation); break; case EN_CENTER: - // re-compute indent - addTrait(Trait.START_INDENT, getStartIndent() - ipdVariation / 2); + // adjust start and end indents + addTrait(Trait.START_INDENT, si - ipdVariation / 2); + addTrait(Trait.END_INDENT, ei - ipdVariation / 2); break; case EN_END: - // re-compute indent - addTrait(Trait.START_INDENT, getStartIndent() - ipdVariation); + // adjust start indent + addTrait(Trait.START_INDENT, si - ipdVariation); break; case EN_JUSTIFY: // compute variation factor @@ -198,7 +236,7 @@ public class LineArea extends Area { // if the LineArea has already been added to the area tree, // call finalize(); otherwise, wait for the LineLM to call it if (adjustingInfo.bAddedToAreaTree) { - finalise(); + finish(); } break; default: @@ -211,7 +249,7 @@ public class LineArea extends Area { * and destroy the AdjustingInfo object if there are * no UnresolvedAreas left */ - public void finalise() { + public void finish() { if (adjustingInfo.lineAlignment == EN_JUSTIFY) { if (log.isTraceEnabled()) { log.trace("Applying variation factor to justified line: " + adjustingInfo); diff --git a/src/java/org/apache/fop/area/LinkResolver.java b/src/java/org/apache/fop/area/LinkResolver.java index 1e135701f..b458a1baf 100644 --- a/src/java/org/apache/fop/area/LinkResolver.java +++ b/src/java/org/apache/fop/area/LinkResolver.java @@ -20,6 +20,7 @@ package org.apache.fop.area; // Java +import java.util.ArrayList; import java.util.List; import java.io.Serializable; @@ -33,6 +34,7 @@ public class LinkResolver implements Resolvable, Serializable { private boolean resolved = false; private String idRef; private Area area; + private transient List dependents = null; /** * Create a new link resolver. @@ -79,8 +81,35 @@ public class LinkResolver implements Resolvable, Serializable { public void resolveIDRef(String id, PageViewport pv) { if (idRef.equals(id) && pv != null) { resolved = true; - Trait.InternalLink iLink = new Trait.InternalLink(pv.getKey(), idRef); - area.addTrait(Trait.INTERNAL_LINK, iLink); + if ( area != null ) { + Trait.InternalLink iLink = new Trait.InternalLink(pv.getKey(), idRef); + area.addTrait(Trait.INTERNAL_LINK, iLink); + area = null; // break circular reference from basic link area to this resolver + } + resolveDependents(id, pv); } } + + /** + * Add dependent resolvable. Used to resolve second-order resolvables that + * depend on resolution of this resolver. + * @param dependent resolvable + */ + public void addDependent(Resolvable dependent) { + if ( dependents == null ) { + dependents = new ArrayList(); + } + dependents.add(dependent); + } + + private void resolveDependents(String id, PageViewport pv) { + if ( dependents != null ) { + List pages = new ArrayList(); + pages.add(pv); + for ( Resolvable r : dependents ) { + r.resolveIDRef(id, pages); + } + } + } + } diff --git a/src/java/org/apache/fop/area/MainReference.java b/src/java/org/apache/fop/area/MainReference.java index a6112011d..44f4cc8c8 100644 --- a/src/java/org/apache/fop/area/MainReference.java +++ b/src/java/org/apache/fop/area/MainReference.java @@ -19,6 +19,8 @@ package org.apache.fop.area; +import org.apache.fop.traits.WritingModeTraitsGetter; + import java.util.ArrayList; import java.util.Iterator; import java.util.List; @@ -124,5 +126,16 @@ public class MainReference extends Area { return parent.getColumnGap(); } + /** + * Sets the writing mode traits for the spans of this main + * reference area. + * @param wmtg a WM traits getter + */ + public void setWritingModeTraits(WritingModeTraitsGetter wmtg) { + for ( Span s : (List) getSpans() ) { + s.setWritingModeTraits ( wmtg ); + } + } + } diff --git a/src/java/org/apache/fop/area/Page.java b/src/java/org/apache/fop/area/Page.java index a1d9e389f..3a08809dc 100644 --- a/src/java/org/apache/fop/area/Page.java +++ b/src/java/org/apache/fop/area/Page.java @@ -33,6 +33,7 @@ import org.apache.fop.fo.pagination.RegionBody; import org.apache.fop.fo.pagination.SimplePageMaster; import org.apache.fop.fo.properties.CommonMarginBlock; import org.apache.fop.layoutmgr.TraitSetter; +import org.apache.fop.traits.WritingModeTraitsGetter; import static org.apache.fop.fo.Constants.FO_REGION_AFTER; import static org.apache.fop.fo.Constants.FO_REGION_BEFORE; @@ -304,6 +305,29 @@ public class Page extends AreaTreeObject implements Serializable, Cloneable { return unresolved; } + /** + * Sets the writing mode traits for the region viewports of + * this page. + * @param wmtg a WM traits getter + */ + public void setWritingModeTraits(WritingModeTraitsGetter wmtg) { + if (regionBefore != null) { + regionBefore.setWritingModeTraits(wmtg); + } + if (regionStart != null) { + regionStart.setWritingModeTraits(wmtg); + } + if (regionBody != null) { + regionBody.setWritingModeTraits(wmtg); + } + if (regionEnd != null) { + regionEnd.setWritingModeTraits(wmtg); + } + if (regionAfter != null) { + regionAfter.setWritingModeTraits(wmtg); + } + } + } diff --git a/src/java/org/apache/fop/area/PageViewport.java b/src/java/org/apache/fop/area/PageViewport.java index ff4b2fdaa..f335fa128 100644 --- a/src/java/org/apache/fop/area/PageViewport.java +++ b/src/java/org/apache/fop/area/PageViewport.java @@ -34,6 +34,7 @@ import org.apache.commons.logging.LogFactory; import org.apache.fop.fo.flow.Marker; import org.apache.fop.fo.pagination.SimplePageMaster; +import org.apache.fop.traits.WritingModeTraitsGetter; import static org.apache.fop.fo.Constants.FO_REGION_BODY; import static org.apache.fop.fo.Constants.EN_FSWP; @@ -654,4 +655,15 @@ public class PageViewport extends AreaTreeObject implements Resolvable, Cloneabl public RegionReference getRegionReference(int id) { return getPage().getRegionViewport(id).getRegionReference(); } + + /** + * Sets the writing mode traits for the page associated with this viewport. + * @param wmtg a WM traits getter + */ + public void setWritingModeTraits(WritingModeTraitsGetter wmtg) { + if ( page != null ) { + page.setWritingModeTraits(wmtg); + } + } + } diff --git a/src/java/org/apache/fop/area/RegionViewport.java b/src/java/org/apache/fop/area/RegionViewport.java index 6cc700a7b..0104b53ad 100644 --- a/src/java/org/apache/fop/area/RegionViewport.java +++ b/src/java/org/apache/fop/area/RegionViewport.java @@ -19,6 +19,8 @@ package org.apache.fop.area; +import org.apache.fop.traits.WritingModeTraitsGetter; + import java.awt.Rectangle; import java.awt.geom.Rectangle2D; import java.io.IOException; @@ -106,7 +108,7 @@ public class RegionViewport extends Area implements Cloneable, Viewport { out.writeFloat((float) viewArea.getWidth()); out.writeFloat((float) viewArea.getHeight()); out.writeBoolean(clip); - out.writeObject(props); + out.writeObject(traits); out.writeObject(regionReference); } @@ -115,7 +117,7 @@ public class RegionViewport extends Area implements Cloneable, Viewport { viewArea = new Rectangle2D.Float(in.readFloat(), in.readFloat(), in.readFloat(), in.readFloat()); clip = in.readBoolean(); - props = (HashMap)in.readObject(); + traits = (HashMap)in.readObject(); setRegionReference((RegionReference) in.readObject()); } @@ -128,13 +130,25 @@ public class RegionViewport extends Area implements Cloneable, Viewport { public Object clone() { RegionViewport rv = new RegionViewport((Rectangle2D)viewArea.clone()); rv.regionReference = (RegionReference)regionReference.clone(); - if (props != null) { - rv.props = new HashMap(props); + if (traits != null) { + rv.traits = new HashMap(traits); } if (foreignAttributes != null) { rv.foreignAttributes = new HashMap(foreignAttributes); } return rv; } + + /** + * Sets the writing mode traits for the region reference of + * this region viewport + * @param wmtg a WM traits getter + */ + public void setWritingModeTraits(WritingModeTraitsGetter wmtg) { + if (regionReference != null) { + regionReference.setWritingModeTraits(wmtg); + } + } + } diff --git a/src/java/org/apache/fop/area/Span.java b/src/java/org/apache/fop/area/Span.java index c2fd4679c..f25140097 100644 --- a/src/java/org/apache/fop/area/Span.java +++ b/src/java/org/apache/fop/area/Span.java @@ -19,8 +19,12 @@ package org.apache.fop.area; +import java.util.Iterator; import java.util.List; +import org.apache.fop.fo.Constants; +import org.apache.fop.traits.WritingModeTraitsGetter; + /** * The span-reference-area. * This is a block-area with 0 border and padding that is stacked @@ -183,6 +187,28 @@ public class Span extends Area { return (areaCount == 0); } + /** + * Sets the writing mode traits for the main reference area of + * this span area. + * @param wmtg a WM traits getter + */ + public void setWritingModeTraits(WritingModeTraitsGetter wmtg) { + switch ( wmtg.getColumnProgressionDirection().getEnumValue() ) { + case Constants.EN_RL: + setBidiLevel(1); + for ( Iterator it = flowAreas.iterator(); it.hasNext();) { + it.next().setBidiLevel(1); + } + break; + default: + resetBidiLevel(); + for ( Iterator it = flowAreas.iterator(); it.hasNext();) { + it.next().resetBidiLevel(); + } + break; + } + } + /** {@inheritDoc} */ @Override public String toString() { diff --git a/src/java/org/apache/fop/area/Trait.java b/src/java/org/apache/fop/area/Trait.java index d9194559d..9942a1370 100644 --- a/src/java/org/apache/fop/area/Trait.java +++ b/src/java/org/apache/fop/area/Trait.java @@ -26,6 +26,8 @@ import org.apache.xmlgraphics.image.loader.ImageInfo; import org.apache.fop.fonts.FontTriplet; import org.apache.fop.traits.BorderProps; +import org.apache.fop.traits.Direction; +import org.apache.fop.traits.WritingMode; import org.apache.fop.util.ColorUtil; import static org.apache.fop.fo.Constants.EN_REPEAT; @@ -156,8 +158,19 @@ public final class Trait implements Serializable { /** For navigation in the document structure. */ public static final Integer STRUCTURE_TREE_ELEMENT = 37; + /** writing mode trait */ + public static final Integer WRITING_MODE = 38; + /** inline progression direction trait */ + public static final Integer INLINE_PROGRESSION_DIRECTION = 39; + /** block progression direction trait */ + public static final Integer BLOCK_PROGRESSION_DIRECTION = 40; + /** column progression direction trait */ + public static final Integer COLUMN_PROGRESSION_DIRECTION = 41; + /** shift direction trait */ + public static final Integer SHIFT_DIRECTION = 42; + /** Maximum value used by trait keys */ - public static final int MAX_TRAIT_KEY = 37; + public static final int MAX_TRAIT_KEY = 42; private static final TraitInfo[] TRAIT_INFO = new TraitInfo[MAX_TRAIT_KEY + 1]; @@ -221,6 +234,14 @@ public final class Trait implements Serializable { put(SPACE_AFTER, new TraitInfo("space-after", Integer.class)); put(IS_REFERENCE_AREA, new TraitInfo("is-reference-area", Boolean.class)); put(IS_VIEWPORT_AREA, new TraitInfo("is-viewport-area", Boolean.class)); + put(WRITING_MODE, + new TraitInfo("writing-mode", WritingMode.class)); + put(INLINE_PROGRESSION_DIRECTION, + new TraitInfo("inline-progression-direction", Direction.class)); + put(BLOCK_PROGRESSION_DIRECTION, + new TraitInfo("block-progression-direction", Direction.class)); + put(SHIFT_DIRECTION, + new TraitInfo("shift-direction", Direction.class)); } diff --git a/src/java/org/apache/fop/area/inline/AbstractTextArea.java b/src/java/org/apache/fop/area/inline/AbstractTextArea.java index 1558e8160..348820939 100644 --- a/src/java/org/apache/fop/area/inline/AbstractTextArea.java +++ b/src/java/org/apache/fop/area/inline/AbstractTextArea.java @@ -188,7 +188,7 @@ public abstract class AbstractTextArea extends InlineParent { @Override int getVirtualOffset() { - return getOffset(); + return getBlockProgressionOffset(); } @Override diff --git a/src/java/org/apache/fop/area/inline/BasicLinkArea.java b/src/java/org/apache/fop/area/inline/BasicLinkArea.java index fce913944..c91181946 100644 --- a/src/java/org/apache/fop/area/inline/BasicLinkArea.java +++ b/src/java/org/apache/fop/area/inline/BasicLinkArea.java @@ -20,6 +20,7 @@ package org.apache.fop.area.inline; import org.apache.fop.area.Area; +import org.apache.fop.area.LinkResolver; /** * An inline area produced by an fo:basic-link element. This class implements a different @@ -33,6 +34,8 @@ public class BasicLinkArea extends InlineParent { private static final long serialVersionUID = 5183753430412208151L; + private LinkResolver resolver; + @Override public void setParentArea(Area parentArea) { super.setParentArea(parentArea); @@ -42,12 +45,28 @@ public class BasicLinkArea extends InlineParent { * called after all of the children areas have been added to this area. */ /* Make this area start at its beforest child. */ - setOffset(getOffset() + minChildOffset); + setBlockProgressionOffset(getBlockProgressionOffset() + minChildOffset); /* Update children offsets accordingly. */ for (InlineArea inline : inlines) { - inline.setOffset(inline.getOffset() - minChildOffset); + inline.setBlockProgressionOffset(inline.getBlockProgressionOffset() - minChildOffset); } setBPD(getVirtualBPD()); } + /** + * Establish (or remove) back-pointer to link resolver. + * @param resolver the link resolver that will resolve this basic link or null + */ + public void setResolver(LinkResolver resolver) { + assert ( resolver == null ) || ( this.resolver == null ); + this.resolver = resolver; + } + + /** + * Obtain back-pointer to link resolver. + * @return resolver the link resolver that will resolve this basic link or null + */ + public LinkResolver getResolver() { + return this.resolver; + } } diff --git a/src/java/org/apache/fop/area/inline/FilledArea.java b/src/java/org/apache/fop/area/inline/FilledArea.java index e0207ada6..dfb3af58b 100644 --- a/src/java/org/apache/fop/area/inline/FilledArea.java +++ b/src/java/org/apache/fop/area/inline/FilledArea.java @@ -50,10 +50,9 @@ public class FilledArea extends InlineParent { * @param v the offset */ /* - public void setOffset(int v) { + public void setBlockProgressionOffset(int v) { setChildOffset(inlines.listIterator(), v); } - */ private void setChildOffset(ListIterator childrenIterator, int v) { while (childrenIterator.hasNext()) { @@ -63,10 +62,11 @@ public class FilledArea extends InlineParent { } else if (child instanceof InlineViewport) { // nothing } else { - child.setOffset(v); + child.setBlockProgressionOffset(v); } } } + */ /** * Set the unit width for the areas to fill the full width. @@ -129,5 +129,6 @@ public class FilledArea extends InlineParent { setIPD(getIPD() + adjustingInfo.applyVariationFactor(variationFactor)); return false; } + } diff --git a/src/java/org/apache/fop/area/inline/InlineArea.java b/src/java/org/apache/fop/area/inline/InlineArea.java index d62e6f721..5fa156ac8 100644 --- a/src/java/org/apache/fop/area/inline/InlineArea.java +++ b/src/java/org/apache/fop/area/inline/InlineArea.java @@ -20,10 +20,12 @@ package org.apache.fop.area.inline; import java.io.Serializable; +import java.util.List; import org.apache.fop.area.Area; import org.apache.fop.area.LineArea; import org.apache.fop.area.Trait; +import org.apache.fop.complexscripts.bidi.InlineRun; /** * Inline Area @@ -79,7 +81,7 @@ public class InlineArea extends Area { /** * offset position from before edge of parent area */ - protected int offset = 0; + protected int blockProgressionOffset = 0; /** * parent area @@ -100,6 +102,23 @@ public class InlineArea extends Area { */ protected InlineAdjustingInfo adjustingInfo = null; + /** + * Default constructor for inline area. + */ + public InlineArea() { + this ( 0, -1 ); + } + + /** + * Instantiate inline area. + * @param blockProgressionOffset a block progression offset or zero + * @param bidiLevel a resolved bidi level or -1 + */ + protected InlineArea ( int blockProgressionOffset, int bidiLevel ) { + this.blockProgressionOffset = blockProgressionOffset; + setBidiLevel(bidiLevel); + } + /** * @return the adjustment information object */ @@ -138,25 +157,25 @@ public class InlineArea extends Area { } /** - * Set the offset of this inline area. + * Set the block progression offset of this inline area. * This is used to set the offset of the inline area * which is relative to the before edge of the parent area. * - * @param offset the offset + * @param blockProgressionOffset the offset */ - public void setOffset(int offset) { - this.offset = offset; + public void setBlockProgressionOffset(int blockProgressionOffset) { + this.blockProgressionOffset = blockProgressionOffset; } /** - * Get the offset of this inline area. + * Get the block progression offset of this inline area. * This returns the offset of the inline area - * which is relative to the before edge of the parent area. + * relative to the before edge of the parent area. * - * @return the offset + * @return the blockProgressionOffset */ - public int getOffset() { - return offset; + public int getBlockProgressionOffset() { + return blockProgressionOffset; } /** @@ -266,7 +285,7 @@ public class InlineArea extends Area { * @see BasicLinkArea */ int getVirtualOffset() { - return getOffset(); + return getBlockProgressionOffset(); } /** @@ -278,5 +297,43 @@ public class InlineArea extends Area { int getVirtualBPD() { return getBPD(); } -} + /** + * Collection bidi inline runs. + * @param runs current list of inline runs + * @return modified list of inline runs, having appended new run + */ + public List collectInlineRuns ( List runs ) { + assert runs != null; + runs.add ( new InlineRun ( this, new int[] {getBidiLevel()}) ); + return runs; + } + + /** + * Determine if inline area IA is an ancestor inline area or same as this area. + * @param ia inline area to test + * @return true if specified inline area is an ancestor or same as this area + */ + public boolean isAncestorOrSelf ( InlineArea ia ) { + return ( ia == this ) || isAncestor ( ia ); + } + + /** + * Determine if inline area IA is an ancestor inline area of this area. + * @param ia inline area to test + * @return true if specified inline area is an ancestor of this area + */ + public boolean isAncestor ( InlineArea ia ) { + for ( Area p = getParentArea(); p != null;) { + if ( p == ia ) { + return true; + } else if ( p instanceof InlineArea ) { + p = ( (InlineArea) p ).getParentArea(); + } else { + p = null; + } + } + return false; + } + +} diff --git a/src/java/org/apache/fop/area/inline/InlineParent.java b/src/java/org/apache/fop/area/inline/InlineParent.java index 521080469..0e1f32dff 100644 --- a/src/java/org/apache/fop/area/inline/InlineParent.java +++ b/src/java/org/apache/fop/area/inline/InlineParent.java @@ -20,6 +20,7 @@ package org.apache.fop.area.inline; import java.util.List; +import java.util.Iterator; import org.apache.fop.area.Area; @@ -62,6 +63,7 @@ public class InlineParent extends InlineArea { if (autoSize) { increaseIPD(childArea.getAllocIPD()); } + updateLevel ( childArea.getBidiLevel() ); int childOffset = childArea.getVirtualOffset(); minChildOffset = Math.min(minChildOffset, childOffset); maxAfterEdge = Math.max(maxAfterEdge, childOffset + childArea.getVirtualBPD()); @@ -69,7 +71,7 @@ public class InlineParent extends InlineArea { @Override int getVirtualOffset() { - return getOffset() + minChildOffset; + return getBlockProgressionOffset() + minChildOffset; } @Override @@ -110,5 +112,37 @@ public class InlineParent extends InlineArea { return hasUnresolvedAreas; } -} + @Override + public List collectInlineRuns ( List runs ) { + for ( Iterator it = getChildAreas().iterator(); it.hasNext();) { + InlineArea ia = it.next(); + runs = ia.collectInlineRuns ( runs ); + } + return runs; + } + + /** + * Reset bidirectionality level of all children to default (-1), + * signalling that they will inherit the level of their parent text area. + */ + public void resetChildrenLevel() { + for ( Iterator it = inlines.iterator(); it.hasNext();) { + ( (InlineArea) it.next() ) .resetBidiLevel(); + } + } + private void updateLevel ( int newLevel ) { + if ( newLevel >= 0 ) { + int curLevel = getBidiLevel(); + if ( curLevel >= 0 ) { + if ( newLevel < curLevel ) { + setBidiLevel ( newLevel ); + } + } else { + setBidiLevel ( newLevel ); + } + } + } + + +} diff --git a/src/java/org/apache/fop/area/inline/InlineViewport.java b/src/java/org/apache/fop/area/inline/InlineViewport.java index 68cc9a797..202a7dad4 100644 --- a/src/java/org/apache/fop/area/inline/InlineViewport.java +++ b/src/java/org/apache/fop/area/inline/InlineViewport.java @@ -50,6 +50,17 @@ public class InlineViewport extends InlineArea implements Viewport { * @param child the child content area of this viewport */ public InlineViewport(Area child) { + this(child, -1); + } + + /** + * Create a new viewport area with the content area. + * + * @param child the child content area of this viewport + * @param bidiLevel the bidirectional embedding level (or -1 if not defined) + */ + public InlineViewport(Area child, int bidiLevel) { + super(0, bidiLevel); this.content = child; } @@ -121,7 +132,7 @@ public class InlineViewport extends InlineArea implements Viewport { out.writeFloat((float) contentPosition.getHeight()); } out.writeBoolean(clip); - out.writeObject(props); + out.writeObject(traits); out.writeObject(content); } @@ -134,7 +145,7 @@ public class InlineViewport extends InlineArea implements Viewport { in.readFloat()); } this.clip = in.readBoolean(); - this.props = (HashMap) in.readObject(); + this.traits = (HashMap) in.readObject(); this.content = (Area) in.readObject(); } diff --git a/src/java/org/apache/fop/area/inline/Space.java b/src/java/org/apache/fop/area/inline/Space.java index bf683bb22..b097e4349 100644 --- a/src/java/org/apache/fop/area/inline/Space.java +++ b/src/java/org/apache/fop/area/inline/Space.java @@ -27,4 +27,10 @@ public class Space extends InlineArea { private static final long serialVersionUID = -8748265505356839796L; + /** + * Default constructor. + */ + public Space() { + } + } diff --git a/src/java/org/apache/fop/area/inline/SpaceArea.java b/src/java/org/apache/fop/area/inline/SpaceArea.java index ebfcc5ec8..c3786ec0d 100644 --- a/src/java/org/apache/fop/area/inline/SpaceArea.java +++ b/src/java/org/apache/fop/area/inline/SpaceArea.java @@ -38,14 +38,15 @@ public class SpaceArea extends InlineArea { /** * Create a space area - * @param s the space character - * @param o the offset for the next area - * @param a is this space adjustable? + * @param space the space character + * @param blockProgressionOffset the offset for the next area + * @param adjustable is this space adjustable? + * @param bidiLevel the bidirectional embedding level (or -1 if not defined) */ - public SpaceArea(char s, int o, boolean a) { - space = s; - offset = o; - isAdjustable = a; + public SpaceArea(int blockProgressionOffset, int bidiLevel, char space, boolean adjustable) { + super ( blockProgressionOffset, bidiLevel ); + this.space = space; + this.isAdjustable = adjustable; } /** @return Returns the space. */ @@ -57,4 +58,5 @@ public class SpaceArea extends InlineArea { public boolean isAdjustable() { return this.isAdjustable; } + } diff --git a/src/java/org/apache/fop/area/inline/TextArea.java b/src/java/org/apache/fop/area/inline/TextArea.java index 15d005025..1d27827f7 100644 --- a/src/java/org/apache/fop/area/inline/TextArea.java +++ b/src/java/org/apache/fop/area/inline/TextArea.java @@ -19,6 +19,10 @@ package org.apache.fop.area.inline; +import java.util.Arrays; + +import org.apache.fop.util.CharUtilities; + /** * A text inline area. */ @@ -57,7 +61,7 @@ public class TextArea extends AbstractTextArea { * @param offset the offset for the next area */ public void addWord(String word, int offset) { - addWord(word, offset, null); + addWord(word, 0, null, null, null, offset); } /** @@ -65,25 +69,51 @@ public class TextArea extends AbstractTextArea { * * @param word the word string * @param offset the offset for the next area + * @param level bidirectional level that applies to entire word + */ + public void addWord(String word, int offset, int level) { + addWord(word, 0, null, makeLevels(level, word.length()), null, offset); + } + + /** + * Create and add a WordArea child to this TextArea. + * + * @param word the word string + * @param ipd the word's ipd * @param letterAdjust the letter adjustment array (may be null) + * @param levels array of resolved bidirectional levels of word characters, + * or null if default level + * @param gposAdjustments array of general position adjustments or null if none apply + * @param blockProgressionOffset the offset for the next area */ - public void addWord(String word, int offset, int[] letterAdjust) { - WordArea wordArea = new WordArea(word, offset, letterAdjust); + public void addWord + ( String word, int ipd, int[] letterAdjust, int[] levels, + int[][] gposAdjustments, int blockProgressionOffset ) { + int minWordLevel = findMinLevel ( levels ); + WordArea wordArea = new WordArea + ( blockProgressionOffset, minWordLevel, word, letterAdjust, levels, gposAdjustments ); + wordArea.setIPD ( ipd ); addChildArea(wordArea); wordArea.setParentArea(this); + updateLevel(minWordLevel); } /** * Create and add a SpaceArea child to this TextArea * - * @param space the space character - * @param offset the offset for the next area + * @param space the space character + * @param ipd the space's ipd + * @param blockProgressionOffset the offset for the next area * @param adjustable is this space adjustable? + * @param level resolved bidirection level of space character */ - public void addSpace(char space, int offset, boolean adjustable) { - SpaceArea spaceArea = new SpaceArea(space, offset, adjustable); + public void addSpace + ( char space, int ipd, boolean adjustable, int blockProgressionOffset, int level ) { + SpaceArea spaceArea = new SpaceArea(blockProgressionOffset, level, space, adjustable); + spaceArea.setIPD ( ipd ); addChildArea(spaceArea); spaceArea.setParentArea(this); + updateLevel(level); } /** @@ -113,7 +143,55 @@ public class TextArea extends AbstractTextArea { /** {@inheritDoc} */ @Override public String toString() { - return "TextArea{text=" + getText() + "}"; + StringBuffer sb = new StringBuffer(super.toString()); + sb.append(" {text=\""); + sb.append(CharUtilities.toNCRefs(getText())); + sb.append("\""); + sb.append("}"); + return sb.toString(); } + + private void updateLevel ( int newLevel ) { + if ( newLevel >= 0 ) { + int curLevel = getBidiLevel(); + if ( curLevel >= 0 ) { + if ( newLevel < curLevel ) { + setBidiLevel ( newLevel ); + } + } else { + setBidiLevel ( newLevel ); + } + } + } + + private static int findMinLevel ( int[] levels ) { + if ( levels != null ) { + int lMin = Integer.MAX_VALUE; + for ( int i = 0, n = levels.length; i < n; i++ ) { + int l = levels [ i ]; + if ( ( l >= 0 ) && ( l < lMin ) ) { + lMin = l; + } + } + if ( lMin == Integer.MAX_VALUE ) { + return -1; + } else { + return lMin; + } + } else { + return -1; + } + } + + private int[] makeLevels ( int level, int count ) { + if ( level >= 0 ) { + int[] levels = new int [ count ]; + Arrays.fill ( levels, level ); + return levels; + } else { + return null; + } + } + } diff --git a/src/java/org/apache/fop/area/inline/UnresolvedPageNumber.java b/src/java/org/apache/fop/area/inline/UnresolvedPageNumber.java index d3bb91045..71a3dfa62 100644 --- a/src/java/org/apache/fop/area/inline/UnresolvedPageNumber.java +++ b/src/java/org/apache/fop/area/inline/UnresolvedPageNumber.java @@ -19,12 +19,13 @@ package org.apache.fop.area.inline; +import java.util.List; + import org.apache.fop.area.PageViewport; import org.apache.fop.area.Resolvable; +import org.apache.fop.complexscripts.bidi.InlineRun; import org.apache.fop.fonts.Font; -import java.util.List; - /** * Unresolvable page number area. * This is a word area that resolves itself to a page number @@ -82,6 +83,15 @@ public class UnresolvedPageNumber extends TextArea implements Resolvable { return new String[] {pageIDRef}; } + /** + * Get the (resolved or unresolved) text. + * + * @return the text + */ + public String getText() { + return text; + } + /** * Resolve the page number idref * This resolves the idref for this object by getting the page number @@ -89,6 +99,9 @@ public class UnresolvedPageNumber extends TextArea implements Resolvable { * for this ID. The page number text is then set to the String value * of the page number. * + * TODO: [GA] May need to run bidi algorithm and script processor + * on resolved page number. + * * @param id an id whose PageViewports have been determined * @param pages the list of PageViewports associated with this ID */ @@ -103,7 +116,7 @@ public class UnresolvedPageNumber extends TextArea implements Resolvable { // replace the text removeText(); text = page.getPageNumberString(); - addWord(text, 0); + addWord(text, 0, getBidiLevel()); // update ipd if (font != null) { handleIPDVariation(font.getWordWidth(text) - getIPD()); @@ -137,4 +150,21 @@ public class UnresolvedPageNumber extends TextArea implements Resolvable { int lineStretch, int lineShrink) { return true; } + + /** + * Collection bidi inline runs. + * Override of @{link InlineParent} implementation. + * + * N.B. [GA] without this override, the page-number-citation_writing_mode_rl + * layout engine test will fail. It may be that the test needs to + * be updated rather than using this override. + * @param runs current list of inline runs + * @return modified list of inline runs, having appended new run + */ + @Override + public List collectInlineRuns ( List runs ) { + assert runs != null; + runs.add ( new InlineRun ( this, new int[] {getBidiLevel()}) ); + return runs; + } } diff --git a/src/java/org/apache/fop/area/inline/WordArea.java b/src/java/org/apache/fop/area/inline/WordArea.java index 7f62fe8d7..00ddc9e1d 100644 --- a/src/java/org/apache/fop/area/inline/WordArea.java +++ b/src/java/org/apache/fop/area/inline/WordArea.java @@ -19,6 +19,12 @@ package org.apache.fop.area.inline; +import java.util.Arrays; +import java.util.List; + +import org.apache.fop.complexscripts.bidi.InlineRun; +import org.apache.fop.complexscripts.util.CharMirror; + /** * A string of characters without spaces */ @@ -29,22 +35,63 @@ public class WordArea extends InlineArea { /** The text for this word area */ protected String word; - /** The correction offset for the next area */ - protected int offset = 0; - /** An array of width for adjusting the individual letters (optional) */ protected int[] letterAdjust; + /** + * An array of resolved bidirectional levels corresponding to each character + * in word (optional) + */ + protected int[] levels; + + /** + * An array of glyph positioning adjustments to apply to each glyph 'char' in word (optional) + */ + protected int[][] gposAdjustments; + + /** + * A flag indicating whether the content of word is reversed in relation to + * its original logical order. + */ + protected boolean reversed; + + /** + * Create a word area + * @param blockProgressionOffset the offset for this area + * @param level the bidirectional embedding level (or -1 if not defined) for word as a group + * @param word the word string + * @param letterAdjust the letter adjust array (may be null) + * @param levels array of per-character (glyph) bidirectional levels, + * in case word area is heterogenously leveled + * @param gposAdjustments array of general position adjustments or null if none apply + * @param reversed true if word is known to be reversed at construction time + */ + public WordArea + ( int blockProgressionOffset, int level, String word, int[] letterAdjust, int[] levels, + int[][] gposAdjustments, boolean reversed ) { + super ( blockProgressionOffset, level ); + int length = ( word != null ) ? word.length() : 0; + this.word = word; + this.letterAdjust = maybeAdjustLength ( letterAdjust, length ); + this.levels = maybePopulateLevels ( levels, level, length ); + this.gposAdjustments = maybeAdjustLength ( gposAdjustments, length ); + this.reversed = reversed; + } + /** * Create a word area - * @param w the word string - * @param o the offset for the next area - * @param la the letter adjust array (may be null) + * @param blockProgressionOffset the offset for this area + * @param level the bidirectional embedding level (or -1 if not defined) for word as a group + * @param word the word string + * @param letterAdjust the letter adjust array (may be null) + * @param levels array of per-character (glyph) bidirectional levels, + * in case word area is heterogenously leveled + * @param gposAdjustments array of general position adjustments or null if none apply */ - public WordArea(String w, int o, int[] la) { - word = w; - offset = o; - this.letterAdjust = la; + public WordArea + ( int blockProgressionOffset, int level, String word, int[] letterAdjust, int[] levels, + int[][] gposAdjustments ) { + this ( blockProgressionOffset, level, word, letterAdjust, levels, gposAdjustments, false ); } /** @return Returns the word. */ @@ -52,20 +99,211 @@ public class WordArea extends InlineArea { return word; } - /** @return Returns the offset. */ - @Override - public int getOffset() { - return offset; + /** @return the array of letter adjust widths */ + public int[] getLetterAdjustArray() { + return this.letterAdjust; } - /** @param o The offset to set. */ + + /** + * Obtain per-character (glyph) bidi levels. + * @return a (possibly empty) array of levels or null (if none resolved) + */ + public int[] getBidiLevels() { + return levels; + } + + /** + *

Obtain per-character (glyph) bidi levels over a specified subsequence.

+ *

If word has been reversed, then the subsequence is over the reversed word.

+ * @param start starting (inclusive) index of subsequence + * @param end ending (exclusive) index of subsequence + * @return a (possibly null) array of per-character (glyph) levels over the specified + * sequence + */ + public int[] getBidiLevels ( int start, int end ) { + assert start <= end; + if ( this.levels != null ) { + int n = end - start; + int[] levels = new int [ n ]; + for ( int i = 0; i < n; i++ ) { + levels[i] = this.levels [ start + i ]; + } + return levels; + } else { + return null; + } + } + + /** + *

Obtain per-character (glyph) level at a specified index position.

+ *

If word has been reversed, then the position is relative to the reversed word.

+ * @param position the index of the (possibly reversed) character from which to obtain the + * level + * @return a resolved bidirectional level or, if not specified, then -1 + */ + public int bidiLevelAt ( int position ) { + if ( position > word.length() ) { + throw new IndexOutOfBoundsException(); + } else if ( levels != null ) { + return levels [ position ]; + } else { + return -1; + } + } + @Override - public void setOffset(int o) { - offset = o; + public List collectInlineRuns ( List runs ) { + assert runs != null; + InlineRun r; + if ( getBidiLevels() != null ) { + r = new InlineRun ( this, getBidiLevels() ); + } else { + r = new InlineRun ( this, -1, word.length() ); + } + runs.add ( r ); + return runs; } - /** @return the array of letter adjust widths */ - public int[] getLetterAdjustArray() { - return this.letterAdjust; + /** + * Obtain per-character (glyph) position adjustments. + * @return a (possibly empty) array of adjustments, each having four elements, or null + * if no adjustments apply + */ + public int[][] getGlyphPositionAdjustments() { + return gposAdjustments; + } + + /** + *

Obtain per-character (glyph) position adjustments at a specified index position.

+ *

If word has been reversed, then the position is relative to the reversed word.

+ * @param position the index of the (possibly reversed) character from which to obtain the + * level + * @return an array of adjustments or null if none applies + */ + public int[] glyphPositionAdjustmentsAt ( int position ) { + if ( position > word.length() ) { + throw new IndexOutOfBoundsException(); + } else if ( gposAdjustments != null ) { + return gposAdjustments [ position ]; + } else { + return null; + } + } + + /** + *

Reverse characters and corresponding per-character levels and glyph position + * adjustments.

+ * @param mirror if true, then perform mirroring if mirrorred characters + */ + public void reverse ( boolean mirror ) { + if ( word.length() > 0 ) { + word = ( ( new StringBuffer ( word ) ) .reverse() ) .toString(); + if ( levels != null ) { + reverse ( levels ); + } + if ( gposAdjustments != null ) { + reverse ( gposAdjustments ); + } + reversed = !reversed; + if ( mirror ) { + word = CharMirror.mirror ( word ); + } + } + } + + /** + *

Perform mirroring on mirrorable characters.

+ */ + public void mirror() { + if ( word.length() > 0 ) { + word = CharMirror.mirror ( word ); + } + } + + /** + *

Determined if word has been reversed (in relation to original logical order).

+ *

If a word is reversed, then both its characters (glyphs) and corresponding per-character + * levels are in reverse order.

+ *

Note: this information is used in order to process non-spacing marks during rendering as + * well as provide hints for caret direction.

+ * @return true if word is reversed + */ + public boolean isReversed() { + return reversed; + } + + /* + * If int[] array is not of specified length, then create + * a new copy of the first length entries. + */ + private static int[] maybeAdjustLength ( int[] ia, int length ) { + if ( ia != null ) { + if ( ia.length == length ) { + return ia; + } else { + int[] iaNew = new int [ length ]; + for ( int i = 0, n = ia.length; i < n; i++ ) { + if ( i < length ) { + iaNew [ i ] = ia [ i ]; + } else { + break; + } + } + return iaNew; + } + } else { + return ia; + } + } + + /* + * If int[][] matrix is not of specified length, then create + * a new shallow copy of the first length entries. + */ + private static int[][] maybeAdjustLength ( int[][] im, int length ) { + if ( im != null ) { + if ( im.length == length ) { + return im; + } else { + int[][] imNew = new int [ length ][]; + for ( int i = 0, n = im.length; i < n; i++ ) { + if ( i < length ) { + imNew [ i ] = im [ i ]; + } else { + break; + } + } + return imNew; + } + } else { + return im; + } + } + + private static int[] maybePopulateLevels ( int[] levels, int level, int count ) { + if ( ( levels == null ) && ( level >= 0 ) ) { + levels = new int[count]; + Arrays.fill ( levels, level ); + } + return maybeAdjustLength ( levels, count ); + } + + private static void reverse ( int[] a ) { + for ( int i = 0, n = a.length, m = n / 2; i < m; i++ ) { + int k = n - i - 1; + int t = a [ k ]; + a [ k ] = a [ i ]; + a [ i ] = t; + } + } + + private static void reverse ( int[][] aa ) { + for ( int i = 0, n = aa.length, m = n / 2; i < m; i++ ) { + int k = n - i - 1; + int[] t = aa [ k ]; + aa [ k ] = aa [ i ]; + aa [ i ] = t; + } } } diff --git a/src/java/org/apache/fop/cli/CommandLineOptions.java b/src/java/org/apache/fop/cli/CommandLineOptions.java index 845c11a0d..bfcdb163e 100644 --- a/src/java/org/apache/fop/cli/CommandLineOptions.java +++ b/src/java/org/apache/fop/cli/CommandLineOptions.java @@ -118,6 +118,8 @@ public class CommandLineOptions { private int targetResolution = 0; /* control memory-conservation policy */ private boolean conserveMemoryPolicy = false; + /* true if a complex script features are enabled */ + private boolean useComplexScriptFeatures = true; private FopFactory factory = FopFactory.newInstance(); private FOUserAgent foUserAgent; @@ -181,6 +183,9 @@ public class CommandLineOptions { addXSLTParameter("fop-output-format", getOutputFormat()); addXSLTParameter("fop-version", Version.getVersion()); foUserAgent.setConserveMemoryPolicy(conserveMemoryPolicy); + if (!useComplexScriptFeatures) { + foUserAgent.setComplexScriptFeaturesEnabled(false); + } } else { return false; } @@ -378,6 +383,8 @@ public class CommandLineOptions { getPDFEncryptionParams().setAllowEditContent(false); } else if (args[i].equals("-noannotations")) { getPDFEncryptionParams().setAllowEditAnnotations(false); + } else if (args[i].equals("-nocs")) { + useComplexScriptFeatures = false; } else if (args[i].equals("-nofillinforms")) { getPDFEncryptionParams().setAllowFillInForms(false); } else if (args[i].equals("-noaccesscontent")) { @@ -1175,6 +1182,7 @@ public class CommandLineOptions { + " -q quiet mode \n" + " -c cfg.xml use additional configuration file cfg.xml\n" + " -l lang the language to use for user information \n" + + " -nocs disable complex script features\n" + " -r relaxed/less strict validation (where available)\n" + " -dpi xxx target resolution in dots per inch (dpi) where xxx is a number\n" + " -s for area tree XML, down to block areas only\n" diff --git a/src/java/org/apache/fop/complexscripts/bidi/BidiClass.java b/src/java/org/apache/fop/complexscripts/bidi/BidiClass.java new file mode 100644 index 000000000..6e462eadc --- /dev/null +++ b/src/java/org/apache/fop/complexscripts/bidi/BidiClass.java @@ -0,0 +1,271 @@ +/* + * 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: License.java 1039179 2010-11-25 21:04:09Z vhennebert $ */ + +package org.apache.fop.complexscripts.bidi; + +import java.util.Arrays; +import org.apache.fop.complexscripts.bidi.BidiConstants; + +// CSOFF: WhitespaceAfterCheck +// CSOFF: LineLengthCheck + +/* + * !!! THIS IS A GENERATED FILE !!! + * If updates to the source are needed, then: + * - apply the necessary modifications to + * 'src/codegen/unicode/java/org/apache/fop/complexscripts/bidi/GenerateBidiClass.java' + * - run 'ant codegen-unicode', which will generate a new BidiClass.java + * in 'src/java/org/apache/fop/complexscripts/bidi' + * - commit BOTH changed files + */ + +/** Bidirectional class utilities. */ +public final class BidiClass { + +private BidiClass() { +} + +private static byte[] bcL1 = { +15,15,15,15,15,15,15,15,15,17,16,17,18,16,15,15,15,15,15,15,15,15,15,15,15,15,15,15,16,16,16,17,18,19,19,11,11,11,19,19,19, +19,19,10,13,10,13,13,9,9,9,9,9,9,9,9,9,9,13,19,19,19,19,19,19,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,19,19,19, +19,19,19,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,19,19,19,19,15,15,15,15,15,15,16,15,15,15,15,15,15,15,15,15,15, +15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,13,19,11,11,11,11,19,19,19,19,1,19,19,15,19,19,11,11,9,9,19,1,19,19,19,9,1, +19,19,19,19,19,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,19,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,19,1,1,1,1,1,1,1,1 +}; + +private static byte[] bcR1 = { +4,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14, +14,14,14,14,14,4,14,4,14,14,4,14,14,4,14,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, +4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,12,12,12,12,5,5,19,19,5,11,11,5,13,5,19,19,14,14,14,14,14,14,14,14,14,14,14,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,14,14,14,14,14,14,14,14,14,14,14,14,14,14, +14,14,14,14,14,14,14,12,12,12,12,12,12,12,12,12,12,11,12,12,5,5,5,14,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,5,14,14,14,14,14,14,14,12,19,14,14,14,14,14,14,5,5,14,14,19,14,14,14,14,5,5,9,9,9,9,9,9,9,9,9,9,5, +5,5,5,5,5 +}; + +private static int[] bcS1 = { +256,443,444,448,452,660,661,688,697,699,706,710,720,722,736,741,748,749,750,751,768,880,884,885,886,890,891,894,900,902,903, +904,908,910,931,1014,1015,1154,1155,1160,1162,1329,1369,1370,1377,1417,1418,1792,1806,1807,1808,1809,1810,1840,1867,1869,1958, +1969,1970,1984,1994,2027,2036,2038,2039,2042,2043,2048,2070,2074,2075,2084,2085,2088,2089,2094,2096,2111,2112,2137,2140,2142, +2143,2304,2307,2308,2362,2363,2364,2365,2366,2369,2377,2381,2382,2384,2385,2392,2402,2404,2406,2416,2417,2418,2425,2433,2434, +2437,2447,2451,2474,2482,2486,2492,2493,2494,2497,2503,2507,2509,2510,2519,2524,2527,2530,2534,2544,2546,2548,2554,2555,2561, +2563,2565,2575,2579,2602,2610,2613,2616,2620,2622,2625,2631,2635,2641,2649,2654,2662,2672,2674,2677,2689,2691,2693,2703,2707, +2730,2738,2741,2748,2749,2750,2753,2759,2761,2763,2765,2768,2784,2786,2790,2801,2817,2818,2821,2831,2835,2858,2866,2869,2876, +2877,2878,2879,2880,2881,2887,2891,2893,2902,2903,2908,2911,2914,2918,2928,2929,2930,2946,2947,2949,2958,2962,2969,2972,2974, +2979,2984,2990,3006,3008,3009,3014,3018,3021,3024,3031,3046,3056,3059,3065,3066,3073,3077,3086,3090,3114,3125,3133,3134,3137, +3142,3146,3157,3160,3168,3170,3174,3192,3199,3202,3205,3214,3218,3242,3253,3260,3261,3262,3263,3264,3270,3271,3274,3276,3285, +3294,3296,3298,3302,3313,3330,3333,3342,3346,3389,3390,3393,3398,3402,3405,3406,3415,3424,3426,3430,3440,3449,3450,3458,3461, +3482,3507,3517,3520,3530,3535,3538,3542,3544,3570,3572,3585,3633,3634,3636,3647,3648,3654,3655,3663,3664,3674,3713,3716,3719, +3722,3725,3732,3737,3745,3749,3751,3754,3757,3761,3762,3764,3771,3773,3776,3782,3784,3792,3804,3840,3841,3844,3859,3864,3866, +3872,3882,3892,3893,3894,3895,3896,3897,3898,3899,3900,3901,3902,3904,3913,3953,3967,3968,3973,3974,3976,3981,3993,4030,4038, +4039,4046,4048,4053,4057,4096,4139,4141,4145,4146,4152,4153,4155,4157,4159,4160,4170,4176,4182,4184,4186,4190,4193,4194,4197, +4199,4206,4209,4213,4226,4227,4229,4231,4237,4238,4239,4240,4250,4253,4254,4256,4304,4347,4348,4352,4682,4688,4696,4698,4704, +4746,4752,4786,4792,4800,4802,4808,4824,4882,4888,4957,4960,4961,4969,4992,5008,5024,5120,5121,5741,5743,5760,5761,5787,5788, +5792,5867,5870,5888,5902,5906,5920,5938,5941,5952,5970,5984,5998,6002,6016,6068,6070,6071,6078,6086,6087,6089,6100,6103,6104, +6107,6108,6109,6112,6128,6144,6150,6151,6155,6158,6160,6176,6211,6212,6272,6313,6314,6320,6400,6432,6435,6439,6441,6448,6450, +6451,6457,6464,6468,6470,6480,6512,6528,6576,6593,6600,6608,6618,6622,6656,6679,6681,6686,6688,6741,6742,6743,6744,6752,6753, +6754,6755,6757,6765,6771,6783,6784,6800,6816,6823,6824,6912,6916,6917,6964,6965,6966,6971,6972,6973,6978,6979,6981,6992,7002, +7009,7019,7028,7040,7042,7043,7073,7074,7078,7080,7082,7086,7088,7104,7142,7143,7144,7146,7149,7150,7151,7154,7164,7168,7204, +7212,7220,7222,7227,7232,7245,7248,7258,7288,7294,7376,7379,7380,7393,7394,7401,7405,7406,7410,7424,7468,7522,7544,7545,7579, +7616,7676,7680,7960,7968,8008,8016,8025,8027,8029,8031,8064,8118,8125,8126,8127,8130,8134,8141,8144,8150,8157,8160,8173,8178, +8182,8189,8192,8203,8206,8207,8208,8214,8216,8217,8218,8219,8221,8222,8223,8224,8232,8233,8234,8235,8236,8237,8238,8239,8240, +8245,8249,8250,8251,8255,8257,8260,8261,8262,8263,8274,8275,8276,8277,8287,8288,8293,8298,8304,8305,8308,8314,8316,8317,8318, +8319,8320,8330,8332,8333,8334,8336,8352,8400,8413,8417,8418,8421,8448,8450,8451,8455,8456,8458,8468,8469,8470,8472,8473,8478, +8484,8485,8486,8487,8488,8489,8490,8494,8495,8501,8505,8506,8508,8512,8517,8522,8523,8524,8526,8527,8528,8544,8579,8581,8585, +8592,8597,8602,8604,8608,8609,8611,8612,8614,8615,8622,8623,8654,8656,8658,8659,8660,8661,8692,8722,8723,8724,8960,8968,8972, +8992,8994,9001,9002,9003,9014,9083,9084,9085,9109,9110,9115,9140,9180,9186,9216,9280,9312,9352,9372,9450,9472,9655,9656,9665, +9666,9720,9728,9839,9840,9900,9901,9985,10088,10089,10090,10091,10092,10093,10094,10095,10096,10097,10098,10099,10100,10101, +10102,10132,10176,10181,10182,10183,10188,10190,10214,10215,10216,10217,10218,10219,10220,10221,10222,10223,10224,10240,10496, +10627,10628,10629,10630,10631,10632,10633,10634,10635,10636,10637,10638,10639,10640,10641,10642,10643,10644,10645,10646,10647, +10648,10649,10712,10713,10714,10715,10716,10748,10749,10750,11008,11056,11077,11079,11088,11264,11312,11360,11389,11390,11493, +11499,11503,11513,11517,11518,11520,11568,11631,11632,11647,11648,11680,11688,11696,11704,11712,11720,11728,11736,11744,11776, +11778,11779,11780,11781,11782,11785,11786,11787,11788,11789,11790,11799,11800,11802,11803,11804,11805,11806,11808,11809,11810, +11811,11812,11813,11814,11815,11816,11817,11818,11823,11824,11904,11931,12032,12272,12288,12289,12292,12293,12294,12295,12296, +12297,12298,12299,12300,12301,12302,12303,12304,12305,12306,12308,12309,12310,12311,12312,12313,12314,12315,12316,12317,12318, +12320,12321,12330,12336,12337,12342,12344,12347,12348,12349,12350,12353,12441,12443,12445,12447,12448,12449,12539,12540,12543, +12549,12593,12688,12690,12694,12704,12736,12784,12800,12829,12832,12842,12880,12881,12896,12924,12927,12928,12938,12977,12992, +13004,13008,13056,13175,13179,13278,13280,13311,13312,19904,19968,40960,40981,40982,42128,42192,42232,42238,42240,42508,42509, +42512,42528,42538,42560,42606,42607,42608,42611,42620,42622,42623,42624,42656,42726,42736,42738,42752,42775,42784,42786,42864, +42865,42888,42889,42891,42896,42912,43002,43003,43010,43011,43014,43015,43019,43020,43043,43045,43047,43048,43056,43062,43064, +43065,43072,43124,43136,43138,43188,43204,43214,43216,43232,43250,43256,43259,43264,43274,43302,43310,43312,43335,43346,43359, +43360,43392,43395,43396,43443,43444,43446,43450,43452,43453,43457,43471,43472,43486,43520,43561,43567,43569,43571,43573,43584, +43587,43588,43596,43597,43600,43612,43616,43632,43633,43639,43642,43643,43648,43696,43697,43698,43701,43703,43705,43710,43712, +43713,43714,43739,43741,43742,43777,43785,43793,43808,43816,43968,44003,44005,44006,44008,44009,44011,44012,44013,44016,44032, +55216,55243,57344,63744,64048,64112,64256,64275,64285,64286,64287,64297,64298,64311,64312,64317,64318,64319,64320,64322,64323, +64325,64326,64336,64434,64450,64467,64830,64831,64832,64848,64912,64914,64968,64976,65008,65020,65021,65022,65024,65040,65047, +65048,65049,65056,65072,65073,65075,65077,65078,65079,65080,65081,65082,65083,65084,65085,65086,65087,65088,65089,65090,65091, +65092,65093,65095,65096,65097,65101,65104,65105,65106,65108,65109,65110,65112,65113,65114,65115,65116,65117,65118,65119,65120, +65122,65123,65124,65128,65129,65130,65131,65136,65141,65142,65277,65279,65281,65283,65284,65285,65286,65288,65289,65290,65291, +65292,65293,65294,65296,65306,65307,65308,65311,65313,65339,65340,65341,65342,65343,65344,65345,65371,65372,65373,65374,65375, +65376,65377,65378,65379,65380,65382,65392,65393,65438,65440,65474,65482,65490,65498,65504,65506,65507,65508,65509,65512,65513, +65517,65520,65529,65532,65534,65536,65549,65576,65596,65599,65616,65664,65792,65793,65794,65799,65847,65856,65909,65913,65930, +65936,66000,66045,66176,66208,66304,66336,66352,66369,66370,66378,66432,66463,66464,66504,66512,66513,66560,66640,66720,67584, +67590,67592,67593,67594,67638,67639,67641,67644,67645,67647,67670,67671,67672,67680,67840,67862,67868,67871,67872,67898,67903, +67904,68096,68097,68100,68101,68103,68108,68112,68116,68117,68120,68121,68148,68152,68155,68159,68160,68168,68176,68185,68192, +68221,68223,68224,68352,68406,68409,68416,68438,68440,68448,68467,68472,68480,68608,68681,69216,69247,69632,69633,69634,69635, +69688,69703,69714,69734,69760,69762,69763,69808,69811,69815,69817,69819,69821,69822,73728,74752,74864,77824,92160,110592,118784, +119040,119081,119141,119143,119146,119149,119155,119163,119171,119173,119180,119210,119214,119296,119362,119365,119552,119648, +119808,119894,119966,119970,119973,119977,119982,119995,119997,120005,120071,120077,120086,120094,120123,120128,120134,120138, +120146,120488,120513,120514,120539,120540,120571,120572,120597,120598,120629,120630,120655,120656,120687,120688,120713,120714, +120745,120746,120771,120772,120782,124928,126976,127024,127136,127153,127169,127185,127232,127248,127280,127344,127462,127504, +127552,127568,127744,127792,127799,127872,127904,127942,127968,128000,128064,128066,128140,128141,128249,128256,128292,128293, +128336,128507,128513,128530,128534,128536,128538,128540,128544,128552,128557,128560,128565,128581,128640,128768,131070,131072, +173824,177984,194560,196606,262142,327678,393214,458750,524286,589822,655358,720894,786430,851966,917502,917505,917506,917536, +917632,917760,918000,983038,983040,1048574,1048576,1114110 +}; + +private static int[] bcE1 = { +442,443,447,451,659,660,687,696,698,705,709,719,721,735,740,747,748,749,750,767,879,883,884,885,887,890,893,894,901,902,903, +906,908,929,1013,1014,1153,1154,1159,1161,1319,1366,1369,1375,1415,1417,1418,1805,1806,1807,1808,1809,1839,1866,1868,1957, +1968,1969,1983,1993,2026,2035,2037,2038,2041,2042,2047,2069,2073,2074,2083,2084,2087,2088,2093,2095,2110,2111,2136,2139,2141, +2142,2303,2306,2307,2361,2362,2363,2364,2365,2368,2376,2380,2381,2383,2384,2391,2401,2403,2405,2415,2416,2417,2423,2431,2433, +2435,2444,2448,2472,2480,2482,2489,2492,2493,2496,2500,2504,2508,2509,2510,2519,2525,2529,2531,2543,2545,2547,2553,2554,2555, +2562,2563,2570,2576,2600,2608,2611,2614,2617,2620,2624,2626,2632,2637,2641,2652,2654,2671,2673,2676,2677,2690,2691,2701,2705, +2728,2736,2739,2745,2748,2749,2752,2757,2760,2761,2764,2765,2768,2785,2787,2799,2801,2817,2819,2828,2832,2856,2864,2867,2873, +2876,2877,2878,2879,2880,2884,2888,2892,2893,2902,2903,2909,2913,2915,2927,2928,2929,2935,2946,2947,2954,2960,2965,2970,2972, +2975,2980,2986,3001,3007,3008,3010,3016,3020,3021,3024,3031,3055,3058,3064,3065,3066,3075,3084,3088,3112,3123,3129,3133,3136, +3140,3144,3149,3158,3161,3169,3171,3183,3198,3199,3203,3212,3216,3240,3251,3257,3260,3261,3262,3263,3268,3270,3272,3275,3277, +3286,3294,3297,3299,3311,3314,3331,3340,3344,3386,3389,3392,3396,3400,3404,3405,3406,3415,3425,3427,3439,3445,3449,3455,3459, +3478,3505,3515,3517,3526,3530,3537,3540,3542,3551,3571,3572,3632,3633,3635,3642,3647,3653,3654,3662,3663,3673,3675,3714,3716, +3720,3722,3725,3735,3743,3747,3749,3751,3755,3760,3761,3763,3769,3772,3773,3780,3782,3789,3801,3805,3840,3843,3858,3863,3865, +3871,3881,3891,3892,3893,3894,3895,3896,3897,3898,3899,3900,3901,3903,3911,3948,3966,3967,3972,3973,3975,3980,3991,4028,4037, +4038,4044,4047,4052,4056,4058,4138,4140,4144,4145,4151,4152,4154,4156,4158,4159,4169,4175,4181,4183,4185,4189,4192,4193,4196, +4198,4205,4208,4212,4225,4226,4228,4230,4236,4237,4238,4239,4249,4252,4253,4255,4293,4346,4347,4348,4680,4685,4694,4696,4701, +4744,4749,4784,4789,4798,4800,4805,4822,4880,4885,4954,4959,4960,4968,4988,5007,5017,5108,5120,5740,5742,5759,5760,5786,5787, +5788,5866,5869,5872,5900,5905,5908,5937,5940,5942,5969,5971,5996,6000,6003,6067,6069,6070,6077,6085,6086,6088,6099,6102,6103, +6106,6107,6108,6109,6121,6137,6149,6150,6154,6157,6158,6169,6210,6211,6263,6312,6313,6314,6389,6428,6434,6438,6440,6443,6449, +6450,6456,6459,6464,6469,6479,6509,6516,6571,6592,6599,6601,6617,6618,6655,6678,6680,6683,6687,6740,6741,6742,6743,6750,6752, +6753,6754,6756,6764,6770,6780,6783,6793,6809,6822,6823,6829,6915,6916,6963,6964,6965,6970,6971,6972,6977,6978,6980,6987,7001, +7008,7018,7027,7036,7041,7042,7072,7073,7077,7079,7081,7082,7087,7097,7141,7142,7143,7145,7148,7149,7150,7153,7155,7167,7203, +7211,7219,7221,7223,7231,7241,7247,7257,7287,7293,7295,7378,7379,7392,7393,7400,7404,7405,7409,7410,7467,7521,7543,7544,7578, +7615,7654,7679,7957,7965,8005,8013,8023,8025,8027,8029,8061,8116,8124,8125,8126,8129,8132,8140,8143,8147,8155,8159,8172,8175, +8180,8188,8190,8202,8205,8206,8207,8213,8215,8216,8217,8218,8220,8221,8222,8223,8231,8232,8233,8234,8235,8236,8237,8238,8239, +8244,8248,8249,8250,8254,8256,8259,8260,8261,8262,8273,8274,8275,8276,8286,8287,8292,8297,8303,8304,8305,8313,8315,8316,8317, +8318,8319,8329,8331,8332,8333,8334,8348,8377,8412,8416,8417,8420,8432,8449,8450,8454,8455,8457,8467,8468,8469,8471,8472,8477, +8483,8484,8485,8486,8487,8488,8489,8493,8494,8500,8504,8505,8507,8511,8516,8521,8522,8523,8525,8526,8527,8543,8578,8580,8584, +8585,8596,8601,8603,8607,8608,8610,8611,8613,8614,8621,8622,8653,8655,8657,8658,8659,8660,8691,8721,8722,8723,8959,8967,8971, +8991,8993,9000,9001,9002,9013,9082,9083,9084,9108,9109,9114,9139,9179,9185,9203,9254,9290,9351,9371,9449,9471,9654,9655,9664, +9665,9719,9727,9838,9839,9899,9900,9983,10087,10088,10089,10090,10091,10092,10093,10094,10095,10096,10097,10098,10099,10100, +10101,10131,10175,10180,10181,10182,10186,10188,10213,10214,10215,10216,10217,10218,10219,10220,10221,10222,10223,10239,10495, +10626,10627,10628,10629,10630,10631,10632,10633,10634,10635,10636,10637,10638,10639,10640,10641,10642,10643,10644,10645,10646, +10647,10648,10711,10712,10713,10714,10715,10747,10748,10749,11007,11055,11076,11078,11084,11097,11310,11358,11388,11389,11492, +11498,11502,11505,11516,11517,11519,11557,11621,11631,11632,11647,11670,11686,11694,11702,11710,11718,11726,11734,11742,11775, +11777,11778,11779,11780,11781,11784,11785,11786,11787,11788,11789,11798,11799,11801,11802,11803,11804,11805,11807,11808,11809, +11810,11811,11812,11813,11814,11815,11816,11817,11822,11823,11825,11929,12019,12245,12283,12288,12291,12292,12293,12294,12295, +12296,12297,12298,12299,12300,12301,12302,12303,12304,12305,12307,12308,12309,12310,12311,12312,12313,12314,12315,12316,12317, +12319,12320,12329,12335,12336,12341,12343,12346,12347,12348,12349,12351,12438,12442,12444,12446,12447,12448,12538,12539,12542, +12543,12589,12686,12689,12693,12703,12730,12771,12799,12828,12830,12841,12879,12880,12895,12923,12926,12927,12937,12976,12991, +13003,13007,13054,13174,13178,13277,13279,13310,13311,19893,19967,40907,40980,40981,42124,42182,42231,42237,42239,42507,42508, +42511,42527,42537,42539,42605,42606,42607,42610,42611,42621,42622,42623,42647,42725,42735,42737,42743,42774,42783,42785,42863, +42864,42887,42888,42890,42894,42897,42921,43002,43009,43010,43013,43014,43018,43019,43042,43044,43046,43047,43051,43061,43063, +43064,43065,43123,43127,43137,43187,43203,43204,43215,43225,43249,43255,43258,43259,43273,43301,43309,43311,43334,43345,43347, +43359,43388,43394,43395,43442,43443,43445,43449,43451,43452,43456,43469,43471,43481,43487,43560,43566,43568,43570,43572,43574, +43586,43587,43595,43596,43597,43609,43615,43631,43632,43638,43641,43642,43643,43695,43696,43697,43700,43702,43704,43709,43711, +43712,43713,43714,43740,43741,43743,43782,43790,43798,43814,43822,44002,44004,44005,44007,44008,44010,44011,44012,44013,44025, +55203,55238,55291,63743,64045,64109,64217,64262,64279,64285,64286,64296,64297,64310,64311,64316,64317,64318,64319,64321,64322, +64324,64325,64335,64433,64449,64466,64829,64830,64831,64847,64911,64913,64967,64975,65007,65019,65020,65021,65023,65039,65046, +65047,65048,65049,65062,65072,65074,65076,65077,65078,65079,65080,65081,65082,65083,65084,65085,65086,65087,65088,65089,65090, +65091,65092,65094,65095,65096,65100,65103,65104,65105,65106,65108,65109,65111,65112,65113,65114,65115,65116,65117,65118,65119, +65121,65122,65123,65126,65128,65129,65130,65131,65140,65141,65276,65278,65279,65282,65283,65284,65285,65287,65288,65289,65290, +65291,65292,65293,65295,65305,65306,65307,65310,65312,65338,65339,65340,65341,65342,65343,65344,65370,65371,65372,65373,65374, +65375,65376,65377,65378,65379,65381,65391,65392,65437,65439,65470,65479,65487,65495,65500,65505,65506,65507,65508,65510,65512, +65516,65518,65528,65531,65533,65535,65547,65574,65594,65597,65613,65629,65786,65792,65793,65794,65843,65855,65908,65912,65929, +65930,65947,66044,66045,66204,66256,66334,66339,66368,66369,66377,66378,66461,66463,66499,66511,66512,66517,66639,66717,66729, +67589,67591,67592,67593,67637,67638,67640,67643,67644,67646,67669,67670,67671,67679,67839,67861,67867,67870,67871,67897,67902, +67903,68095,68096,68099,68100,68102,68107,68111,68115,68116,68119,68120,68147,68151,68154,68158,68159,68167,68175,68184,68191, +68220,68222,68223,68351,68405,68408,68415,68437,68439,68447,68466,68471,68479,68607,68680,69215,69246,69631,69632,69633,69634, +69687,69702,69709,69733,69743,69761,69762,69807,69810,69814,69816,69818,69820,69821,69825,74606,74850,74867,78894,92728,110593, +119029,119078,119140,119142,119145,119148,119154,119162,119170,119172,119179,119209,119213,119261,119361,119364,119365,119638, +119665,119892,119964,119967,119970,119974,119980,119993,119995,120003,120069,120074,120084,120092,120121,120126,120132,120134, +120144,120485,120512,120513,120538,120539,120570,120571,120596,120597,120628,120629,120654,120655,120686,120687,120712,120713, +120744,120745,120770,120771,120779,120831,126975,127019,127123,127150,127166,127183,127199,127242,127278,127337,127386,127490, +127546,127560,127569,127776,127797,127868,127891,127940,127946,127984,128062,128064,128139,128140,128247,128252,128291,128292, +128317,128359,128511,128528,128532,128534,128536,128538,128542,128549,128555,128557,128563,128576,128591,128709,128883,131071, +173782,177972,178205,195101,196607,262143,327679,393215,458751,524287,589823,655359,720895,786431,851967,917504,917505,917535, +917631,917759,917999,921599,983039,1048573,1048575,1114109,1114111 +}; + +private static byte[] bcC1 = { +1,1,1,1,1,1,1,1,19,1,19,19,1,19,1,19,19,19,1,19,14,1,19,19,1,1,1,19,19,1,19,1,1,1,1,19,1,1,14,14,1,1,1,1,1,1,19,5,5,12,5,14, +5,14,5,5,14,5,5,4,4,14,4,19,19,4,4,4,14,4,14,4,14,4,14,4,4,4,4,14,4,4,4,14,1,1,14,1,14,1,1,14,1,14,1,1,14,1,14,1,1,1,1,1,1, +14,1,1,1,1,1,1,1,14,1,1,14,1,1,14,1,1,1,1,14,1,1,11,1,1,11,14,1,1,1,1,1,1,1,1,14,1,14,14,14,14,1,1,1,14,1,14,14,1,1,1,1,1, +1,1,14,1,1,14,14,1,1,14,1,1,14,1,11,14,1,1,1,1,1,1,1,14,1,1,14,1,14,1,1,14,14,1,1,1,14,1,1,1,1,14,1,1,1,1,1,1,1,1,1,1,1,14, +1,1,1,14,1,1,1,1,19,11,19,1,1,1,1,1,1,1,14,1,14,14,14,1,1,14,1,19,1,1,1,1,1,1,1,14,1,1,1,1,1,1,1,14,1,1,1,14,1,1,1,1,1,1,1, +1,14,1,1,14,1,1,1,14,1,1,1,1,1,1,1,1,1,1,14,1,14,14,1,1,1,1,14,1,14,11,1,1,14,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,14,1,14,14,1,1, +1,14,1,1,1,1,1,1,14,1,1,1,1,14,1,14,1,14,19,19,19,19,1,1,1,14,1,14,1,14,1,14,14,1,14,1,1,1,1,1,1,1,14,1,14,1,14,1,14,1,1,1, +1,1,14,1,14,1,1,1,1,1,14,1,14,1,14,1,14,1,1,1,1,14,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,14,1,1,1,1,19,1,19,1,1,1,18,1, +19,19,1,1,1,1,1,14,1,14,1,1,14,1,1,14,1,1,1,14,1,14,1,14,1,1,1,11,1,14,1,19,19,19,19,14,18,1,1,1,1,1,14,1,1,1,14,1,14,1,1, +14,1,14,19,19,1,1,1,1,1,1,1,1,1,19,1,14,1,1,1,1,14,1,14,14,1,14,1,14,1,14,14,1,1,1,1,1,14,1,1,14,1,14,1,14,1,14,1,1,1,1,1, +14,1,14,1,1,1,14,1,14,1,1,1,1,14,1,14,1,14,1,14,1,1,1,1,14,1,14,1,1,1,1,1,1,1,14,1,14,1,14,1,14,1,1,1,1,1,1,1,1,14,14,1,1, +1,1,1,1,1,1,1,1,1,19,1,19,1,1,19,1,1,19,1,19,1,1,19,18,15,1,4,19,19,19,19,19,19,19,19,19,19,18,16,2,6,8,3,7,13,11,19,19,19, +19,19,19,13,19,19,19,19,19,19,19,18,15,15,15,9,1,9,10,19,19,19,1,9,10,19,19,19,1,11,14,14,14,14,14,19,1,19,1,19,1,19,1,19, +19,1,19,1,19,1,19,1,19,1,11,1,1,1,19,1,19,1,19,19,19,1,1,19,1,1,1,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, +19,10,11,19,19,19,19,19,19,19,19,19,1,19,19,19,1,19,19,19,19,19,19,19,19,9,1,19,19,19,19,19,19,19,19,19,19,1,19,19,19,19,19, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,19,19,19,19,19,19,19,19,19,19, +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,1,1,1,1,19,1,14,19,19,19,1,1,1,1,14,1,1, +1,1,1,1,1,1,1,14,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, +19,18,19,19,1,1,1,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,1,14,19,1,19,1,1,1,19,19,1,14,19,1, +1,19,1,19,1,1,1,1,1,1,1,1,19,1,1,19,1,1,19,19,1,19,1,1,1,19,1,19,1,1,19,1,19,1,19,1,19,1,1,1,1,19,1,1,1,1,1,19,1,1,1,1,1,14, +14,19,14,19,19,1,1,1,14,1,19,19,19,1,1,1,19,1,1,1,1,1,1,14,1,14,1,14,1,1,14,1,19,1,1,11,11,1,19,1,1,1,14,1,1,14,1,1,1,1,1, +14,1,1,14,1,1,1,14,1,1,14,1,14,1,14,1,1,1,1,1,1,14,1,14,1,14,1,14,1,14,1,1,1,1,1,1,1,1,1,1,14,1,14,1,14,1,14,1,14,1,1,1,1, +1,1,1,1,1,1,1,14,1,14,1,1,1,14,1,1,1,1,1,1,1,1,1,1,4,14,4,10,4,4,4,4,4,4,4,4,4,4,4,5,5,5,5,19,19,5,5,5,5,5,15,5,5,19,5,14, +19,19,19,19,14,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,13,19,13,19,13,19,19,19,19,19,19,19, +19,11,19,10,10,19,19,11,11,19,5,5,5,5,15,19,11,11,11,19,19,19,19,10,13,10,13,9,13,19,19,19,1,19,19,19,19,19,19,1,19,19,19, +19,19,19,19,19,19,19,1,1,1,1,1,1,1,1,1,11,19,19,19,11,19,19,19,15,19,19,15,1,1,1,1,1,1,1,1,19,1,1,1,19,19,19,19,19,1,14,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,19,4,4,4,4,4,14,4,14,4,14,4,4,4,4,4,4,14,4,14,4,4,4,4, +4,4,4,4,4,4,19,4,4,4,4,4,4,4,4,4,12,4,1,14,1,1,14,1,19,1,14,1,1,1,14,1,14,1,1,1,1,1,1,1,1,1,1,1,1,1,14,1,1,15,14,1,14,1,14, +1,19,14,19,19,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,19,1,1,1,19,1,1,1,19,1,1,1,19,1,1,1,19,1,9,4,19,19,19,19,19,19, +9,1,1,1,1,1,1,1,19,19,19,19,19,19,19,19,19,19,1,19,19,19,1,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,15,1,1,1,1,15, +15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,14,15,15,1,15,1,15 +}; + +/** + * Lookup bidi class for character expressed as unicode scalar value. + * @param ch a unicode scalar value + * @return bidi class + */ +public static int getBidiClass ( int ch ) { + if ( ch <= 0x00FF ) { + return bcL1 [ ch - 0x0000 ]; + } else if ( ( ch >= 0x0590 ) && ( ch <= 0x06FF ) ) { + return bcR1 [ ch - 0x0590 ]; + } else { + return getBidiClass ( ch, bcS1, bcE1, bcC1 ); + } +} + +private static int getBidiClass ( int ch, int[] sa, int[] ea, byte[] ca ) { + int k = Arrays.binarySearch ( sa, ch ); + if ( k >= 0 ) { + return ca [ k ]; + } else { + k = - ( k + 1 ); + if ( k == 0 ) { + return BidiConstants.L; + } else if ( ch <= ea [ k - 1 ] ) { + return ca [ k - 1 ]; + } else { + return BidiConstants.L; + } + } +} + +} diff --git a/src/java/org/apache/fop/complexscripts/bidi/BidiConstants.java b/src/java/org/apache/fop/complexscripts/bidi/BidiConstants.java new file mode 100644 index 000000000..ef29223be --- /dev/null +++ b/src/java/org/apache/fop/complexscripts/bidi/BidiConstants.java @@ -0,0 +1,91 @@ +/* + * 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.complexscripts.bidi; + + +/** + * Constants used for bidirectional processing. + * @author Glenn Adams + */ +public interface BidiConstants { + + // bidi character class + + /** first external (official) category */ + int FIRST = 1; + + // strong category + /** left-to-right class */ + int L = 1; + /** left-to-right embedding class */ + int LRE = 2; + /** left-to-right override class */ + int LRO = 3; + /** right-to-left class */ + int R = 4; + /** right-to-left arabic class */ + int AL = 5; + /** right-to-left embedding class */ + int RLE = 6; + /** right-to-left override class */ + int RLO = 7; + + // weak category + /** pop directional formatting class */ + int PDF = 8; + /** european number class */ + int EN = 9; + /** european number separator class */ + int ES = 10; + /** european number terminator class */ + int ET = 11; + /** arabic number class */ + int AN = 12; + /** common number separator class */ + int CS = 13; + /** non-spacing mark class */ + int NSM = 14; + /** boundary neutral class */ + int BN = 15; + + // neutral category + /** paragraph separator class */ + int B = 16; + /** segment separator class */ + int S = 17; + /** whitespace class */ + int WS = 18; + /** other neutrals class */ + int ON = 19; + + /** last external (official) category */ + int LAST = 19; + + // implementation specific categories + /** placeholder for low surrogate */ + int SURROGATE = 20; + + // other constants + /** last + /** maximum bidirectional levels */ + int MAX_LEVELS = 61; + /** override flag */ + int OVERRIDE = 128; +} diff --git a/src/java/org/apache/fop/complexscripts/bidi/BidiResolver.java b/src/java/org/apache/fop/complexscripts/bidi/BidiResolver.java new file mode 100644 index 000000000..70bbe857a --- /dev/null +++ b/src/java/org/apache/fop/complexscripts/bidi/BidiResolver.java @@ -0,0 +1,242 @@ +/* + * 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.complexscripts.bidi; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Stack; +import java.util.Vector; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.apache.fop.area.LineArea; +import org.apache.fop.area.inline.InlineArea; +import org.apache.fop.fo.pagination.PageSequence; + +// CSOFF: EmptyForIteratorPadCheck +// CSOFF: InnerAssignmentCheck +// CSOFF: LineLengthCheck +// CSOFF: NoWhitespaceAfterCheck +// CSOFF: SimplifyBooleanReturnCheck + +/** + *

A utility class for performing bidirectional resolution processing.

+ * + * @author Glenn Adams + */ +public final class BidiResolver { + + /** + * logging instance + */ + private static final Log log = LogFactory.getLog(BidiResolver.class); // CSOK: ConstantNameCheck + + private BidiResolver() { + } + + /** + * Resolve inline directionality. + * @param ps a page sequence FO instance + */ + public static void resolveInlineDirectionality ( PageSequence ps ) { + if (log.isDebugEnabled()) { + log.debug ( "BD: RESOLVE: " + ps ); + } + List ranges = pruneEmptyRanges ( ps.collectDelimitedTextRanges ( new Stack() ) ); + resolveInlineDirectionality ( ranges ); + } + + /** + * Reorder line area. + * @param la a line area instance + */ + public static void reorder ( LineArea la ) { + + // 1. collect inline levels + List runs = collectRuns ( la.getInlineAreas(), new Vector() ); + if (log.isDebugEnabled()) { + dumpRuns ( "BD: REORDER: INPUT:", runs ); + } + + // 2. split heterogeneous inlines + runs = splitRuns ( runs ); + if (log.isDebugEnabled()) { + dumpRuns ( "BD: REORDER: SPLIT INLINES:", runs ); + } + + // 3. determine minimum and maximum levels + int[] mm = computeMinMaxLevel ( runs, null ); + if (log.isDebugEnabled()) { + log.debug( "BD: REORDER: { min = " + mm[0] + ", max = " + mm[1] + "}" ); + } + + // 4. reorder from maximum level to minimum odd level + int mn = mm[0]; + int mx = mm[1]; + if ( mx > 0 ) { + for ( int l1 = mx, l2 = ( ( mn & 1 ) == 0 ) ? ( mn + 1 ) : mn; l1 >= l2; l1-- ) { + runs = reorderRuns ( runs, l1 ); + } + } + if (log.isDebugEnabled()) { + dumpRuns ( "BD: REORDER: REORDERED RUNS:", runs ); + } + + // 5. reverse word consituents (characters and glyphs) while mirroring + boolean mirror = true; + reverseWords ( runs, mirror ); + if (log.isDebugEnabled()) { + dumpRuns ( "BD: REORDER: REORDERED WORDS:", runs ); + } + + // 6. replace line area's inline areas with reordered runs' inline areas + replaceInlines ( la, replicateSplitWords ( runs ) ); + } + + private static void resolveInlineDirectionality ( List ranges ) { + for ( Iterator it = ranges.iterator(); it.hasNext(); ) { + DelimitedTextRange r = (DelimitedTextRange) it.next(); + r.resolve(); + if (log.isDebugEnabled()) { + log.debug ( r ); + } + } + } + + private static List collectRuns ( List inlines, List runs ) { + for ( Iterator it = inlines.iterator(); it.hasNext(); ) { + InlineArea ia = (InlineArea) it.next(); + runs = ia.collectInlineRuns ( runs ); + } + return runs; + } + + private static List splitRuns ( List runs ) { + List runsNew = new Vector(); + for ( Iterator it = runs.iterator(); it.hasNext(); ) { + InlineRun ir = (InlineRun) it.next(); + if ( ir.isHomogenous() ) { + runsNew.add ( ir ); + } else { + runsNew.addAll ( ir.split() ); + } + } + if ( ! runsNew.equals ( runs ) ) { + runs = runsNew; + } + return runs; + } + + private static int[] computeMinMaxLevel ( List runs, int[] mm ) { + if ( mm == null ) { + mm = new int[] {Integer.MAX_VALUE, Integer.MIN_VALUE}; + } + for ( Iterator it = runs.iterator(); it.hasNext(); ) { + InlineRun ir = (InlineRun) it.next(); + ir.updateMinMax ( mm ); + } + return mm; + } + private static List reorderRuns ( List runs, int level ) { + assert level >= 0; + List runsNew = new Vector(); + for ( int i = 0, n = runs.size(); i < n; i++ ) { + InlineRun iri = (InlineRun) runs.get(i); + if ( iri.getMinLevel() < level ) { + runsNew.add ( iri ); + } else { + int s = i; + int e = s; + while ( e < n ) { + InlineRun ire = (InlineRun) runs.get(e); + if ( ire.getMinLevel() < level ) { + break; + } else { + e++; + } + } + if ( s < e ) { + runsNew.addAll ( reverseRuns ( runs, s, e ) ); + } + i = e - 1; + } + } + if ( ! runsNew.equals ( runs ) ) { + runs = runsNew; + } + return runs; + } + private static List reverseRuns ( List runs, int s, int e ) { + int n = e - s; + Vector runsNew = new Vector ( n ); + if ( n > 0 ) { + for ( int i = 0; i < n; i++ ) { + int k = ( n - i - 1 ); + InlineRun ir = (InlineRun) runs.get(s + k); + ir.reverse(); + runsNew.add ( ir ); + } + } + return runsNew; + } + private static void reverseWords ( List runs, boolean mirror ) { + for ( Iterator it = runs.iterator(); it.hasNext(); ) { + InlineRun ir = (InlineRun) it.next(); + ir.maybeReverseWord ( mirror ); + } + } + private static List replicateSplitWords ( List runs ) { + // [TBD] for each run which inline word area appears multiple times in + // runs, replicate that word + return runs; + } + private static void replaceInlines ( LineArea la, List runs ) { + List inlines = new ArrayList(); + for ( Iterator it = runs.iterator(); it.hasNext(); ) { + InlineRun ir = (InlineRun) it.next(); + inlines.add ( ir.getInline() ); + } + la.setInlineAreas ( unflattenInlines ( inlines ) ); + } + private static List unflattenInlines ( List inlines ) { + return new UnflattenProcessor ( inlines ) .unflatten(); + } + private static void dumpRuns ( String header, List runs ) { + log.debug ( header ); + for ( Iterator it = runs.iterator(); it.hasNext(); ) { + InlineRun ir = (InlineRun) it.next(); + log.debug ( ir ); + } + } + + private static List pruneEmptyRanges ( Stack ranges ) { + Vector rv = new Vector(); + for ( Iterator it = ranges.iterator(); it.hasNext(); ) { + DelimitedTextRange r = (DelimitedTextRange) it.next(); + if ( ! r.isEmpty() ) { + rv.add ( r ); + } + } + return rv; + } + +} diff --git a/src/java/org/apache/fop/complexscripts/bidi/DelimitedTextRange.java b/src/java/org/apache/fop/complexscripts/bidi/DelimitedTextRange.java new file mode 100644 index 000000000..9939db971 --- /dev/null +++ b/src/java/org/apache/fop/complexscripts/bidi/DelimitedTextRange.java @@ -0,0 +1,228 @@ +/* + * 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.complexscripts.bidi; + +import java.util.Iterator; +import java.util.List; +import java.util.Vector; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.apache.fop.fo.CharIterator; +import org.apache.fop.fo.FONode; +import org.apache.fop.fo.FObj; +import org.apache.fop.traits.Direction; +import org.apache.fop.traits.WritingModeTraits; +import org.apache.fop.traits.WritingModeTraitsGetter; +import org.apache.fop.util.CharUtilities; + +// CSOFF: EmptyForIteratorPadCheck +// CSOFF: InnerAssignmentCheck +// CSOFF: LineLengthCheck +// CSOFF: NoWhitespaceAfterCheck + +/** + * The DelimitedTextRange class implements the "delimited text range" as described + * by XML-FO 1.1 §5.8, which contains a flattened sequence of characters. Any FO that generates + * block areas serves as a delimiter. + * + * @author Glenn Adams + */ +public class DelimitedTextRange { + private FONode fn; // node that generates this text range + private StringBuffer buffer; // flattened character sequence of generating FO nodes + private List intervals; // list of intervals over buffer of generating FO nodes + /** + * Primary constructor. + * @param fn node that generates this text range + */ + public DelimitedTextRange ( FONode fn ) { + this.fn = fn; + this.buffer = new StringBuffer(); + this.intervals = new Vector(); + } + /** + * Obtain node that generated this text range. + * @return node that generated this text range + */ + public FONode getNode() { + return fn; + } + /** + * Append interval using characters from character iterator IT. + * @param it character iterator + * @param fn node that generates interval being appended + */ + public void append ( CharIterator it, FONode fn ) { + if ( it != null ) { + int s = buffer.length(); + int e = s; + while ( it.hasNext() ) { + char c = it.nextChar(); + buffer.append ( c ); + e++; + } + intervals.add ( new TextInterval ( fn, s, e ) ); + } + } + /** + * Append interval using character C. + * @param c character + * @param fn node that generates interval being appended + */ + public void append ( char c, FONode fn ) { + if ( c != 0 ) { + int s = buffer.length(); + int e = s + 1; + buffer.append ( c ); + intervals.add ( new TextInterval ( fn, s, e ) ); + } + } + /** + * Determine if range is empty. + * @return true if range is empty + */ + public boolean isEmpty() { + return buffer.length() == 0; + } + /** + * Resolve bidirectional levels for this range. + */ + public void resolve() { + WritingModeTraitsGetter tg; + if ( ( tg = WritingModeTraits.getWritingModeTraitsGetter ( getNode() ) ) != null ) { + resolve ( tg.getInlineProgressionDirection() ); + } + } + @Override + public String toString() { + StringBuffer sb = new StringBuffer ( "DR: " + fn.getLocalName() + " { <" + CharUtilities.toNCRefs ( buffer.toString() ) + ">" ); + sb.append ( ", intervals <" ); + boolean first = true; + for ( Iterator it = intervals.iterator(); it.hasNext(); ) { + TextInterval ti = (TextInterval) it.next(); + if ( first ) { + first = false; + } else { + sb.append(','); + } + sb.append ( ti.toString() ); + } + sb.append("> }"); + return sb.toString(); + } + private void resolve ( Direction paragraphEmbeddingLevel ) { + int [] levels; + if ( ( levels = UnicodeBidiAlgorithm.resolveLevels ( buffer, paragraphEmbeddingLevel ) ) != null ) { + assignLevels ( levels ); + assignBlockLevel ( paragraphEmbeddingLevel ); + assignTextLevels(); + } + } + /** + *

Assign resolved levels to all text intervals of this delimited text range.

+ *

Has a possible side effect of replacing the intervals array with a new array + * containing new text intervals, such that each text interval is associated with + * a single level run.

+ * @param levels array of levels each corresponding to each index of the delimited + * text range + */ + private void assignLevels ( int[] levels ) { + Vector intervalsNew = new Vector ( intervals.size() ); + for ( Iterator it = intervals.iterator(); it.hasNext(); ) { + TextInterval ti = (TextInterval) it.next(); + intervalsNew.addAll ( assignLevels ( ti, levels ) ); + } + if ( ! intervalsNew.equals ( intervals ) ) { + intervals = intervalsNew; + } + } + /** + *

Assign resolved levels to a specified text interval over this delimited text + * range.

+ *

Returns a list of text intervals containing either (1) the single, input text + * interval or (2) two or more new text intervals obtained from sub-dividing the input + * text range into level runs, i.e., runs of text assigned to a single level.

+ * @param ti a text interval to which levels are to be assigned + * @param levels array of levels each corresponding to each index of the delimited + * text range + * @return a list of text intervals as described above + */ + private static final Log log = LogFactory.getLog(BidiResolver.class); // CSOK: ConstantNameCheck + private List assignLevels ( TextInterval ti, int[] levels ) { + Vector tiv = new Vector(); + FONode fn = ti.getNode(); + int fnStart = ti.getStart(); // start of node's text in delimited text range + for ( int i = fnStart, n = ti.getEnd(); i < n; ) { + int s = i; // inclusive start index of interval in delimited text range + int e = s; // exclusive end index of interval in delimited text range + int l = levels [ s ]; // current run level + while ( e < n ) { // skip to end of run level or end of interval + if ( levels [ e ] != l ) { + break; + } else { + e++; + } + } + if ( ( ti.getStart() == s ) && ( ti.getEnd() == e ) ) { + ti.setLevel ( l ); // reuse interval, assigning it single level + } else { + ti = new TextInterval ( fn, fnStart, s, e, l ); // subdivide interval + } + if (log.isDebugEnabled()) { + log.debug ( "AL(" + l + "): " + ti ); + } + tiv.add ( ti ); + i = e; + } + return tiv; + } + /** + *

Assign resolved levels for each interval to source #PCDATA in the associated FOText.

+ */ + private void assignTextLevels() { + for ( Iterator it = intervals.iterator(); it.hasNext(); ) { + TextInterval ti = (TextInterval) it.next(); + ti.assignTextLevels(); + } + } + private void assignBlockLevel ( Direction paragraphEmbeddingLevel ) { + int defaultLevel = ( paragraphEmbeddingLevel == Direction.RL ) ? 1 : 0; + for ( Iterator it = intervals.iterator(); it.hasNext(); ) { + TextInterval ti = (TextInterval) it.next(); + assignBlockLevel ( ti.getNode(), defaultLevel ); + } + } + private void assignBlockLevel ( FONode node, int defaultLevel ) { + for ( FONode fn = node; fn != null; fn = fn.getParent() ) { + if ( fn instanceof FObj ) { + FObj fo = (FObj) fn; + if ( fo.isBidiRangeBlockItem() ) { + if ( fo.getBidiLevel() < 0 ) { + fo.setBidiLevel ( defaultLevel ); + } + break; + } + } + } + } +} + diff --git a/src/java/org/apache/fop/complexscripts/bidi/InlineRun.java b/src/java/org/apache/fop/complexscripts/bidi/InlineRun.java new file mode 100644 index 000000000..6ea62494a --- /dev/null +++ b/src/java/org/apache/fop/complexscripts/bidi/InlineRun.java @@ -0,0 +1,310 @@ +/* + * 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.complexscripts.bidi; + +import java.util.Arrays; +import java.util.List; +import java.util.Vector; + +import org.apache.fop.area.inline.Anchor; +import org.apache.fop.area.inline.InlineArea; +import org.apache.fop.area.inline.InlineBlockParent; +import org.apache.fop.area.inline.InlineParent; +import org.apache.fop.area.inline.InlineViewport; +import org.apache.fop.area.inline.Leader; +import org.apache.fop.area.inline.Space; +import org.apache.fop.area.inline.SpaceArea; +import org.apache.fop.area.inline.TextArea; +import org.apache.fop.area.inline.UnresolvedPageNumber; +import org.apache.fop.area.inline.WordArea; +import org.apache.fop.traits.Direction; +import org.apache.fop.util.CharUtilities; + +// CSOFF: EmptyForIteratorPadCheck +// CSOFF: InnerAssignmentCheck +// CSOFF: NoWhitespaceAfterCheck +// CSOFF: SimplifyBooleanReturnCheck + +/** + * The InlineRun class is a utility class, the instances of which are used + * to capture a sequence of reordering levels associated with an inline area. + * + * @author Glenn Adams + */ +public class InlineRun { + private InlineArea inline; + private int[] levels; + private int minLevel; + private int maxLevel; + private int reversals; + /** + * Primary constructor. + * @param inline which generated this inline run + * @param levels levels array + */ + public InlineRun ( InlineArea inline, int[] levels ) { + assert inline != null; + assert levels != null; + this.inline = inline; + this.levels = levels; + setMinMax ( levels ); + } + /** + * Alternate constructor. + * @param inline which generated this inline run + * @param level for each index + * @param count of indices + */ + public InlineRun ( InlineArea inline, int level, int count ) { + this ( inline, makeLevels ( level, count ) ); + } + /** + * Obtain inline area that generated this inline run. + * @return inline area that generated this inline run. + */ + public InlineArea getInline() { + return inline; + } + /** + * Obtain minimum bidi level for this run. + * @return minimum bidi level + */ + public int getMinLevel() { + return minLevel; + } + /** + * Obtain maximum bidi level for this run. + * @return maximum bidi level + */ + public int getMaxLevel() { + return maxLevel; + } + private void setMinMax ( int[] levels ) { + int mn = Integer.MAX_VALUE; + int mx = Integer.MIN_VALUE; + if ( ( levels != null ) && ( levels.length > 0 ) ) { + for ( int i = 0, n = levels.length; i < n; i++ ) { + int l = levels [ i ]; + if ( l < mn ) { + mn = l; + } + if ( l > mx ) { + mx = l; + } + } + } else { + mn = mx = -1; + } + this.minLevel = mn; + this.maxLevel = mx; + } + /** + * Determine if this run has homogenous (same valued) bidi levels. + * @return true if homogenous + */ + public boolean isHomogenous() { + return minLevel == maxLevel; + } + /** + * Split this inline run into homogenous runs. + * @return list of new runs + */ + public List split() { + List runs = new Vector(); + for ( int i = 0, n = levels.length; i < n; ) { + int l = levels [ i ]; + int s = i; + int e = s; + while ( e < n ) { + if ( levels [ e ] != l ) { + break; + } else { + e++; + } + } + if ( s < e ) { + runs.add ( new InlineRun ( inline, l, e - s ) ); + } + i = e; + } + assert runs.size() < 2 : "heterogeneous inlines not yet supported!!"; + return runs; + } + /** + * Update a min/max array to correspond with this run's min/max values. + * @param mm reference to min/max array + */ + public void updateMinMax ( int[] mm ) { + if ( minLevel < mm[0] ) { + mm[0] = minLevel; + } + if ( maxLevel > mm[1] ) { + mm[1] = maxLevel; + } + } + /** + * Determine if run needs mirroring. + * @return true if run is homogenous and odd (i.e., right to left) + */ + public boolean maybeNeedsMirroring() { + return ( minLevel == maxLevel ) && ( ( minLevel & 1 ) != 0 ); + } + /** + * Reverse run (by incrementing reversal count, not actually reversing). + */ + public void reverse() { + reversals++; + } + /** + * Reverse inline area if it is a word area and it requires + * reversal. + * @param mirror if true then also mirror characters + */ + public void maybeReverseWord ( boolean mirror ) { + if ( inline instanceof WordArea ) { + WordArea w = (WordArea) inline; + // if not already reversed, then reverse now + if ( ! w.isReversed() ) { + if ( ( reversals & 1 ) != 0 ) { + w.reverse ( mirror ); + } else if ( mirror && maybeNeedsMirroring() ) { + w.mirror(); + } + } + } + } + @Override + public boolean equals ( Object o ) { + if ( o instanceof InlineRun ) { + InlineRun ir = (InlineRun) o; + if ( ir.inline != inline ) { + return false; + } else if ( ir.minLevel != minLevel ) { + return false; + } else if ( ir.maxLevel != maxLevel ) { + return false; + } else if ( ( ir.levels != null ) && ( levels != null ) ) { + if ( ir.levels.length != levels.length ) { + return false; + } else { + for ( int i = 0, n = levels.length; i < n; i++ ) { + if ( ir.levels[i] != levels[i] ) { + return false; + } + } + return true; + } + } else if ( ( ir.levels == null ) && ( levels == null ) ) { + return true; + } else { + return false; + } + } else { + return false; + } + } + @Override + public int hashCode() { + int l = ( inline != null ) ? inline.hashCode() : 0; + l = ( l ^ minLevel ) + ( l << 19 ); + l = ( l ^ maxLevel ) + ( l << 11 ); + return l; + } + @Override + public String toString() { + StringBuffer sb = new StringBuffer( "RR: { type = \'" ); + char c; + String content = null; + if ( inline instanceof WordArea ) { + c = 'W'; + content = ( (WordArea) inline ) .getWord(); + } else if ( inline instanceof SpaceArea ) { + c = 'S'; + content = ( (SpaceArea) inline ) .getSpace(); + } else if ( inline instanceof Anchor ) { + c = 'A'; + } else if ( inline instanceof Leader ) { + c = 'L'; + } else if ( inline instanceof Space ) { + c = 'S'; + } else if ( inline instanceof UnresolvedPageNumber ) { + c = '#'; + content = ( (UnresolvedPageNumber) inline ) .getText(); + } else if ( inline instanceof InlineBlockParent ) { + c = 'B'; + } else if ( inline instanceof InlineViewport ) { + c = 'V'; + } else if ( inline instanceof InlineParent ) { + c = 'I'; + } else { + c = '?'; + } + sb.append ( c ); + sb.append ( "\', levels = \'" ); + sb.append ( generateLevels ( levels ) ); + sb.append ( "\', min = " ); + sb.append ( minLevel ); + sb.append ( ", max = " ); + sb.append ( maxLevel ); + sb.append ( ", reversals = " ); + sb.append ( reversals ); + sb.append ( ", content = <" ); + sb.append ( CharUtilities.toNCRefs ( content ) ); + sb.append ( "> }" ); + return sb.toString(); + } + private String generateLevels ( int[] levels ) { + StringBuffer lb = new StringBuffer(); + int maxLevel = -1; + int numLevels = levels.length; + for ( int i = 0; i < numLevels; i++ ) { + int l = levels [ i ]; + if ( l > maxLevel ) { + maxLevel = l; + } + } + if ( maxLevel < 0 ) { + // leave level buffer empty + } else if ( maxLevel < 10 ) { + // use string of decimal digits + for ( int i = 0; i < numLevels; i++ ) { + lb.append ( (char) ( '0' + levels [ i ] ) ); + } + } else { + // use comma separated list + boolean first = true; + for ( int i = 0; i < numLevels; i++ ) { + if ( first ) { + first = false; + } else { + lb.append(','); + } + lb.append ( levels [ i ] ); + } + } + return lb.toString(); + } + private static int[] makeLevels ( int level, int count ) { + int[] levels = new int [ count ]; + Arrays.fill ( levels, level ); + return levels; + } +} + diff --git a/src/java/org/apache/fop/complexscripts/bidi/TextInterval.java b/src/java/org/apache/fop/complexscripts/bidi/TextInterval.java new file mode 100644 index 000000000..7d4ab105b --- /dev/null +++ b/src/java/org/apache/fop/complexscripts/bidi/TextInterval.java @@ -0,0 +1,143 @@ +/* + * 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.complexscripts.bidi; + +import org.apache.fop.fo.FONode; +import org.apache.fop.fo.FOText; +import org.apache.fop.fo.flow.AbstractPageNumberCitation; +import org.apache.fop.fo.flow.AbstractGraphics; +import org.apache.fop.fo.flow.BidiOverride; +import org.apache.fop.fo.flow.Character; +import org.apache.fop.fo.flow.Leader; + +// CSOFF: LineLengthCheck +// CSOFF: SimplifyBooleanReturnCheck + +/** + * The TextInterval class is a utility class, the instances of which are used + * to record backpointers to associated nodes over sub-intervals of a delimited text range. + * + * @author Glenn Adams + */ +class TextInterval { + private FONode fn; // associated node + private int textStart; // starting index within delimited text range of associated node's text + private int start; // starting index within delimited text range + private int end; // ending index within delimited text range + private int level; // resolved level or default (-1) + TextInterval ( FONode fn, int start, int end ) { + this ( fn, start, start, end, -1 ); + } + TextInterval ( FONode fn, int textStart, int start, int end, int level ) { + this.fn = fn; + this.textStart = textStart; + this.start = start; + this.end = end; + this.level = level; + } + FONode getNode() { + return fn; + } + int getTextStart() { + return textStart; + } + int getStart() { + return start; + } + int getEnd() { + return end; + } + int getLevel() { + return level; + } + void setLevel ( int level ) { + this.level = level; + } + public int length() { + return end - start; + } + public String getText() { + if ( fn instanceof FOText ) { + return ( (FOText) fn ) .getCharSequence() .toString(); + } else if ( fn instanceof Character ) { + return new String ( new char[] {( (Character) fn ) .getCharacter()} ); + } else { + return null; + } + } + public void assignTextLevels() { + if ( fn instanceof FOText ) { + ( (FOText) fn ) .setBidiLevel ( level, start - textStart, end - textStart ); + } else if ( fn instanceof Character ) { + ( (Character) fn ) .setBidiLevel ( level ); + } else if ( fn instanceof AbstractPageNumberCitation ) { + ( (AbstractPageNumberCitation) fn ) .setBidiLevel ( level ); + } else if ( fn instanceof AbstractGraphics ) { + ( (AbstractGraphics) fn ) .setBidiLevel ( level ); + } else if ( fn instanceof Leader ) { + ( (Leader) fn ) .setBidiLevel ( level ); + } + } + public boolean equals ( Object o ) { + if ( o instanceof TextInterval ) { + TextInterval ti = (TextInterval) o; + if ( ti.getNode() != fn ) { + return false; + } else if ( ti.getStart() != start ) { + return false; + } else if ( ti.getEnd() != end ) { + return false; + } else { + return true; + } + } else { + return false; + } + } + public int hashCode() { + int l = ( fn != null ) ? fn.hashCode() : 0; + l = ( l ^ start ) + ( l << 19 ); + l = ( l ^ end ) + ( l << 11 ); + return l; + } + public String toString() { + StringBuffer sb = new StringBuffer(); + char c; + if ( fn instanceof FOText ) { + c = 'T'; + } else if ( fn instanceof Character ) { + c = 'C'; + } else if ( fn instanceof BidiOverride ) { + c = 'B'; + } else if ( fn instanceof AbstractPageNumberCitation ) { + c = '#'; + } else if ( fn instanceof AbstractGraphics ) { + c = 'G'; + } else if ( fn instanceof Leader ) { + c = 'L'; + } else { + c = '?'; + } + sb.append ( c ); + sb.append ( "[" + start + "," + end + "][" + textStart + "](" + level + ")" ); + return sb.toString(); + } +} + diff --git a/src/java/org/apache/fop/complexscripts/bidi/UnflattenProcessor.java b/src/java/org/apache/fop/complexscripts/bidi/UnflattenProcessor.java new file mode 100644 index 000000000..d91bed572 --- /dev/null +++ b/src/java/org/apache/fop/complexscripts/bidi/UnflattenProcessor.java @@ -0,0 +1,361 @@ +/* + * 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.complexscripts.bidi; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Stack; + +import org.apache.fop.area.Area; +import org.apache.fop.area.LinkResolver; +import org.apache.fop.area.inline.BasicLinkArea; +import org.apache.fop.area.inline.FilledArea; +import org.apache.fop.area.inline.InlineArea; +import org.apache.fop.area.inline.InlineParent; +import org.apache.fop.area.inline.SpaceArea; +import org.apache.fop.area.inline.TextArea; +import org.apache.fop.area.inline.UnresolvedPageNumber; + +// CSOFF: EmptyForIteratorPadCheck +// CSOFF: LineLengthCheck +// CSOFF: NoWhitespaceAfterCheck +// CSOFF: SimplifyBooleanReturnCheck + +/** + * The UnflattenProcessor class is used to reconstruct (by unflattening) a line + * area's internal area hierarachy after leaf inline area reordering is completed. + * + * @author Glenn Adams + */ +class UnflattenProcessor { + private List il; // list of flattened inline areas being unflattened + private List ilNew; // list of unflattened inline areas being constructed + private int iaLevelLast; // last (previous) level of current inline area (if applicable) or -1 + private TextArea tcOrig; // original text area container + private TextArea tcNew; // new text area container being constructed + private Stack icOrig; // stack of original inline parent containers + private Stack icNew; // stack of new inline parent containers being constructed + UnflattenProcessor ( List inlines ) { + this.il = inlines; + this.ilNew = new ArrayList(); + this.iaLevelLast = -1; + this.icOrig = new Stack(); + this.icNew = new Stack(); + } + List unflatten() { + if ( il != null ) { + for ( Iterator it = il.iterator(); it.hasNext(); ) { + process ( it.next() ); + } + } + finishAll(); + return ilNew; + } + private void process ( InlineArea ia ) { + process ( findInlineContainers ( ia ), findTextContainer ( ia ), ia ); + } + private void process ( List ich, TextArea tc, InlineArea ia ) { + if ( ( tcNew == null ) || ( tc != tcNew ) ) { + maybeFinishTextContainer ( tc, ia ); + maybeFinishInlineContainers ( ich, tc, ia ); + update ( ich, tc, ia ); + } else { + // skip inline area whose text container is the current new text container, + // which occurs in the context of the inline runs produced by a filled area + } + } + private boolean shouldFinishTextContainer ( TextArea tc, InlineArea ia ) { + if ( ( tcOrig != null ) && ( tc != tcOrig ) ) { + return true; + } else if ( ( iaLevelLast != -1 ) && ( ia.getBidiLevel() != iaLevelLast ) ) { + return true; + } else { + return false; + } + } + private void finishTextContainer() { + finishTextContainer ( null, null ); + } + private void finishTextContainer ( TextArea tc, InlineArea ia ) { + if ( tcNew != null ) { + updateIPD ( tcNew ); + if ( ! icNew.empty() ) { + icNew.peek().addChildArea ( tcNew ); + } else { + ilNew.add ( tcNew ); + } + } + tcNew = null; + } + private void maybeFinishTextContainer ( TextArea tc, InlineArea ia ) { + if ( shouldFinishTextContainer ( tc, ia ) ) { + finishTextContainer ( tc, ia ); + } + } + private boolean shouldFinishInlineContainer ( List ich, TextArea tc, InlineArea ia ) { + if ( ( ich == null ) || ich.isEmpty() ) { + return ! icOrig.empty(); + } else { + if ( ! icOrig.empty() ) { + InlineParent ic = ich.get(0); + InlineParent ic0 = icOrig.peek(); + return ( ic != ic0 ) && ! isInlineParentOf ( ic, ic0 ); + } else { + return false; + } + } + } + private void finishInlineContainer() { + finishInlineContainer ( null, null, null ); + } + private void finishInlineContainer ( List ich, TextArea tc, InlineArea ia ) { + if ( ( ich != null ) && ! ich.isEmpty() ) { // finish non-matching inner inline container(s) + for ( Iterator it = ich.iterator(); it.hasNext(); ) { + InlineParent ic = it.next(); + InlineParent ic0 = icOrig.empty() ? null : icOrig.peek(); + if ( ic0 == null ) { + assert icNew.empty(); + } else if ( ic != ic0 ) { + assert ! icNew.empty(); + InlineParent icO0 = icOrig.pop(); + InlineParent icN0 = icNew.pop(); + assert icO0 != null; + assert icN0 != null; + if ( icNew.empty() ) { + ilNew.add ( icN0 ); + } else { + icNew.peek().addChildArea ( icN0 ); + } + if ( ! icOrig.empty() && ( icOrig.peek() == ic ) ) { + break; + } + } else { + break; + } + } + } else { // finish all inline containers + while ( ! icNew.empty() ) { + InlineParent icO0 = icOrig.pop(); + InlineParent icN0 = icNew.pop(); + assert icO0 != null; + assert icN0 != null; + if ( icNew.empty() ) { + ilNew.add ( icN0 ); + } else { + icNew.peek().addChildArea ( icN0 ); + } + } + } + } + private void maybeFinishInlineContainers ( List ich, TextArea tc, InlineArea ia ) { + if ( shouldFinishInlineContainer ( ich, tc, ia ) ) { + finishInlineContainer ( ich, tc, ia ); + } + } + private void finishAll() { + finishTextContainer(); + finishInlineContainer(); + } + private void update ( List ich, TextArea tc, InlineArea ia ) { + if ( ! alreadyUnflattened ( ia ) ) { + if ( ( ich != null ) && ! ich.isEmpty() ) { + pushInlineContainers ( ich ); + } + if ( tc != null ) { + pushTextContainer ( tc, ia ); + } else { + pushNonTextInline ( ia ); + } + iaLevelLast = ia.getBidiLevel(); + tcOrig = tc; + } else if ( tcNew != null ) { + finishTextContainer(); + tcOrig = null; + } else { + tcOrig = null; + } + } + private boolean alreadyUnflattened ( InlineArea ia ) { + for ( Iterator it = ilNew.iterator(); it.hasNext(); ) { + if ( ia.isAncestorOrSelf ( it.next() ) ) { + return true; + } + } + return false; + } + private void pushInlineContainers ( List ich ) { + LinkedList icl = new LinkedList(); + for ( Iterator it = ich.iterator(); it.hasNext(); ) { + InlineParent ic = it.next(); + if ( icOrig.search ( ic ) >= 0 ) { + break; + } else { + icl.addFirst ( ic ); + } + } + for ( Iterator it = icl.iterator(); it.hasNext(); ) { + InlineParent ic = it.next(); + icOrig.push ( ic ); + icNew.push ( generateInlineContainer ( ic ) ); + } + } + private void pushTextContainer ( TextArea tc, InlineArea ia ) { + if ( tc instanceof UnresolvedPageNumber ) { + tcNew = tc; + } else { + if ( tcNew == null ) { + tcNew = generateTextContainer ( tc ); + } + tcNew.addChildArea ( ia ); + } + } + private void pushNonTextInline ( InlineArea ia ) { + if ( icNew.empty() ) { + ilNew.add ( ia ); + } else { + icNew.peek().addChildArea ( ia ); + } + } + private InlineParent generateInlineContainer ( InlineParent i ) { + if ( i instanceof BasicLinkArea ) { + return generateBasicLinkArea ( (BasicLinkArea) i ); + } else if ( i instanceof FilledArea ) { + return generateFilledArea ( (FilledArea) i ); + } else { + return generateInlineContainer0 ( i ); + } + } + private InlineParent generateBasicLinkArea ( BasicLinkArea l ) { + BasicLinkArea lc = new BasicLinkArea(); + if ( l != null ) { + initializeInlineContainer ( lc, l ); + initializeLinkArea ( lc, l ); + } + return lc; + } + private void initializeLinkArea ( BasicLinkArea lc, BasicLinkArea l ) { + assert lc != null; + assert l != null; + LinkResolver r = l.getResolver(); + if ( r != null ) { + String[] idrefs = r.getIDRefs(); + if ( idrefs.length > 0 ) { + String idref = idrefs[0]; + LinkResolver lr = new LinkResolver ( idref, lc ); + lc.setResolver ( lr ); + r.addDependent ( lr ); + } + } + } + private InlineParent generateFilledArea ( FilledArea f ) { + FilledArea fc = new FilledArea(); + if ( f != null ) { + initializeInlineContainer ( fc, f ); + initializeFilledArea ( fc, f ); + } + return fc; + } + private void initializeFilledArea ( FilledArea fc, FilledArea f ) { + assert fc != null; + assert f != null; + fc.setIPD ( f.getIPD() ); + fc.setUnitWidth ( f.getUnitWidth() ); + } + private InlineParent generateInlineContainer0 ( InlineParent i ) { + InlineParent ic = new InlineParent(); + if ( i != null ) { + initializeInlineContainer ( ic, i ); + } + return ic; + } + private void initializeInlineContainer ( InlineParent ic, InlineParent i ) { + assert ic != null; + assert i != null; + ic.setTraits ( i.getTraits() ); + ic.setBPD ( i.getBPD() ); + ic.setBlockProgressionOffset ( i.getBlockProgressionOffset() ); + } + private TextArea generateTextContainer ( TextArea t ) { + TextArea tc = new TextArea(); + if ( t != null ) { + tc.setTraits ( t.getTraits() ); + tc.setBPD ( t.getBPD() ); + tc.setBlockProgressionOffset ( t.getBlockProgressionOffset() ); + tc.setBaselineOffset ( t.getBaselineOffset() ); + tc.setTextWordSpaceAdjust ( t.getTextWordSpaceAdjust() ); + tc.setTextLetterSpaceAdjust ( t.getTextLetterSpaceAdjust() ); + } + return tc; + } + private void updateIPD ( TextArea tc ) { + int numAdjustable = 0; + for ( Iterator it = tc.getChildAreas().iterator(); it.hasNext(); ) { + InlineArea ia = (InlineArea) it.next(); + if ( ia instanceof SpaceArea ) { + SpaceArea sa = (SpaceArea) ia; + if ( sa.isAdjustable() ) { + numAdjustable++; + } + } + } + if ( numAdjustable > 0 ) { + tc.setIPD ( tc.getIPD() + ( numAdjustable * tc.getTextWordSpaceAdjust() ) ); + } + } + private TextArea findTextContainer ( InlineArea ia ) { + assert ia != null; + TextArea t = null; + while ( t == null ) { + if ( ia instanceof TextArea ) { + t = (TextArea) ia; + } else { + Area p = ia.getParentArea(); + if ( p instanceof InlineArea ) { + ia = (InlineArea) p; + } else { + break; + } + } + } + return t; + } + private List findInlineContainers ( InlineArea ia ) { + assert ia != null; + List ich = new ArrayList(); + Area a = ia.getParentArea(); + while ( a != null ) { + if ( a instanceof InlineArea ) { + if ( ( a instanceof InlineParent ) && ! ( a instanceof TextArea ) ) { + ich.add ( (InlineParent) a ); + } + a = ( (InlineArea) a ) .getParentArea(); + } else { + a = null; + } + } + return ich; + } + private boolean isInlineParentOf ( InlineParent ic0, InlineParent ic1 ) { + assert ic0 != null; + return ic0.getParentArea() == ic1; + } +} diff --git a/src/java/org/apache/fop/complexscripts/bidi/UnicodeBidiAlgorithm.java b/src/java/org/apache/fop/complexscripts/bidi/UnicodeBidiAlgorithm.java new file mode 100644 index 000000000..0f24cba9d --- /dev/null +++ b/src/java/org/apache/fop/complexscripts/bidi/UnicodeBidiAlgorithm.java @@ -0,0 +1,839 @@ +/* + * 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.complexscripts.bidi; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.apache.fop.traits.Direction; +import org.apache.fop.util.CharUtilities; + +// CSOFF: AvoidNestedBlocksCheck +// CSOFF: EmptyForIteratorPadCheck +// CSOFF: InnerAssignmentCheck +// CSOFF: LineLengthCheck +// CSOFF: NoWhitespaceAfterCheck +// CSOFF: ParameterNumberCheck + +/** + * The UnicodeBidiAlgorithm class implements functionality prescribed by + * the Unicode Bidirectional Algorithm, Unicode Standard Annex #9. + * + * @author Glenn Adams + */ +public final class UnicodeBidiAlgorithm implements BidiConstants { + + /** + * logging instance + */ + private static final Log log = LogFactory.getLog(BidiResolver.class); // CSOK: ConstantNameCheck + + private UnicodeBidiAlgorithm() { + } + + /** + * Resolve the directionality levels of each character in a character seqeunce. + * If some character is encoded in the character sequence as a Unicode Surrogate Pair, + * then the directionality level of each of the two members of the pair will be identical. + * @return null if bidirectional processing is not required; otherwise, returns an array + * of integers, where each integer corresponds to exactly one UTF-16 + * encoding element present in the input character sequence, and where each integer denotes + * the directionality level of the corresponding encoding element + * @param cs input character sequence representing a UTF-16 encoded string + * @param defaultLevel the default paragraph level, which must be zero (LR) or one (RL) + */ + public static int[] resolveLevels ( CharSequence cs, Direction defaultLevel ) { + int[] chars = new int [ cs.length() ]; + if ( convertToScalar ( cs, chars ) || ( defaultLevel == Direction.RL ) ) { + return resolveLevels ( chars, ( defaultLevel == Direction.RL ) ? 1 : 0, new int [ chars.length ] ); + } else { + return null; + } + } + + /** + * Resolve the directionality levels of each character in a character seqeunce. + * @return null if bidirectional processing is not required; otherwise, returns an array + * of integers, where each integer corresponds to exactly one UTF-16 + * encoding element present in the input character sequence, and where each integer denotes + * the directionality level of the corresponding encoding element + * @param chars array of input characters represented as unicode scalar values + * @param defaultLevel the default paragraph level, which must be zero (LR) or one (RL) + * @param levels array to receive levels, one for each character in chars array + */ + public static int[] resolveLevels ( int[] chars, int defaultLevel, int[] levels ) { + return resolveLevels ( chars, getClasses ( chars ), defaultLevel, levels, false ); + } + + /** + * Resolve the directionality levels of each character in a character seqeunce. + * @return null if bidirectional processing is not required; otherwise, returns an array + * of integers, where each integer corresponds to exactly one UTF-16 + * encoding element present in the input character sequence, and where each integer denotes + * the directionality level of the corresponding encoding element + * @param chars array of input characters represented as unicode scalar values + * @param classes array containing one bidi class per character in chars array + * @param defaultLevel the default paragraph level, which must be zero (LR) or one (RL) + * @param levels array to receive levels, one for each character in chars array + * @param useRuleL1 true if rule L1 should be used + */ + public static int[] resolveLevels ( int[] chars, int[] classes, int defaultLevel, int[] levels, boolean useRuleL1 ) { + int[] ica = classes; + int[] wca = copySequence ( ica ); + int[] ea = new int [ levels.length ]; + resolveExplicit ( wca, defaultLevel, ea ); + resolveRuns ( wca, defaultLevel, ea, levelsFromEmbeddings ( ea, levels ) ); + if ( useRuleL1 ) { + resolveSeparators ( ica, wca, defaultLevel, levels ); + } + dump ( "RL: CC(" + ( ( chars != null ) ? chars.length : -1 ) + ")", chars, classes, defaultLevel, levels ); + return levels; + } + + private static int[] copySequence ( int[] ta ) { + int[] na = new int [ ta.length ]; + System.arraycopy ( ta, 0, na, 0, na.length ); + return na; + } + + private static void resolveExplicit ( int[] wca, int defaultLevel, int[] ea ) { + int[] es = new int [ MAX_LEVELS ]; /* embeddings stack */ + int ei = 0; /* embeddings stack index */ + int ec = defaultLevel; /* current embedding level */ + for ( int i = 0, n = wca.length; i < n; i++ ) { + int bc = wca [ i ]; /* bidi class of current char */ + int el; /* embedding level to assign to current char */ + switch ( bc ) { + case LRE: // start left-to-right embedding + case RLE: // start right-to-left embedding + case LRO: // start left-to-right override + case RLO: // start right-to-left override + { + int en; /* new embedding level */ + if ( ( bc == RLE ) || ( bc == RLO ) ) { + en = ( ( ec & ~OVERRIDE ) + 1 ) | 1; + } else { + en = ( ( ec & ~OVERRIDE ) + 2 ) & ~1; + } + if ( en < ( MAX_LEVELS + 1 ) ) { + es [ ei++ ] = ec; + if ( ( bc == LRO ) || ( bc == RLO ) ) { + ec = en | OVERRIDE; + } else { + ec = en & ~OVERRIDE; + } + } else { + // max levels exceeded, so don't change level or override + } + el = ec; + break; + } + case PDF: // pop directional formatting + { + el = ec; + if ( ei > 0 ) { + ec = es [ --ei ]; + } else { + // ignore isolated PDF + } + break; + } + case B: // paragraph separator + { + el = ec = defaultLevel; + ei = 0; + break; + } + default: + { + el = ec; + break; + } + } + switch ( bc ) { + case BN: + break; + case LRE: case RLE: case LRO: case RLO: case PDF: + wca [ i ] = BN; + break; + default: + if ( ( el & OVERRIDE ) != 0 ) { + wca [ i ] = directionOfLevel ( el ); + } + break; + } + ea [ i ] = el; + } + } + + private static int directionOfLevel ( int level ) { + return ( ( level & 1 ) != 0 ) ? R : L; + } + + private static int levelOfEmbedding ( int embedding ) { + return embedding & ~OVERRIDE; + } + + private static int[] levelsFromEmbeddings ( int[] ea, int[] la ) { + assert ea != null; + assert la != null; + assert la.length == ea.length; + for ( int i = 0, n = la.length; i < n; i++ ) { + la [ i ] = levelOfEmbedding ( ea [ i ] ); + } + return la; + } + + private static void resolveRuns ( int[] wca, int defaultLevel, int[] ea, int[] la ) { + if ( la.length != wca.length ) { + throw new IllegalArgumentException ( "levels sequence length must match classes sequence length" ); + } else if ( la.length != ea.length ) { + throw new IllegalArgumentException ( "levels sequence length must match embeddings sequence length" ); + } else { + for ( int i = 0, n = ea.length, lPrev = defaultLevel; i < n; ) { + int s = i; + int e = s; + int l = findNextNonRetainedFormattingLevel ( wca, ea, s, lPrev ); + while ( e < n ) { + if ( la [ e ] != l ) { + if ( startsWithRetainedFormattingRun ( wca, ea, e ) ) { + e += getLevelRunLength ( ea, e ); + } else { + break; + } + } else { + e++; + } + } + lPrev = resolveRun ( wca, defaultLevel, ea, la, s, e, l, lPrev ); + i = e; + } + } + } + + private static int findNextNonRetainedFormattingLevel ( int[] wca, int[] ea, int start, int lPrev ) { + int s = start; + int e = wca.length; + while ( s < e ) { + if ( startsWithRetainedFormattingRun ( wca, ea, s ) ) { + s += getLevelRunLength ( ea, s ); + } else { + break; + } + } + if ( s < e ) { + return levelOfEmbedding ( ea [ s ] ); + } else { + return lPrev; + } + } + + private static int getLevelRunLength ( int[] ea, int start ) { + assert start < ea.length; + int nl = 0; + for ( int s = start, e = ea.length, l0 = levelOfEmbedding ( ea [ start ] ); s < e; s++ ) { + if ( levelOfEmbedding ( ea [ s ] ) == l0 ) { + nl++; + } else { + break; + } + } + return nl; + } + + private static boolean startsWithRetainedFormattingRun ( int[] wca, int[] ea, int start ) { + int nl = getLevelRunLength ( ea, start ); + if ( nl > 0 ) { + int nc = getRetainedFormattingRunLength ( wca, start ); + return ( nc >= nl ); + } else { + return false; + } + } + + private static int getRetainedFormattingRunLength ( int[] wca, int start ) { + assert start < wca.length; + int nc = 0; + for ( int s = start, e = wca.length; s < e; s++ ) { + if ( wca [ s ] == BidiConstants.BN ) { + nc++; + } else { + break; + } + } + return nc; + } + + private static int resolveRun ( int[] wca, int defaultLevel, int[] ea, int[] la, int start, int end, int level, int levelPrev ) { + + // determine start of run direction + int sor = directionOfLevel ( max ( levelPrev, level ) ); + + // determine end of run direction + int le = -1; + if ( end == wca.length ) { + le = max ( level, defaultLevel ); + } else { + for ( int i = end; i < wca.length; i++ ) { + if ( wca [ i ] != BidiConstants.BN ) { + le = max ( level, la [ i ] ); + break; + } + } + if ( le < 0 ) { + le = max ( level, defaultLevel ); + } + } + int eor = directionOfLevel ( le ); + + if (log.isDebugEnabled()) { + log.debug ( "BR[" + padLeft ( start, 3 ) + "," + padLeft ( end, 3 ) + "] :" + padLeft ( level, 2 ) + ": SOR(" + getClassName(sor) + "), EOR(" + getClassName(eor) + ")" ); + } + + resolveWeak ( wca, defaultLevel, ea, la, start, end, level, sor, eor ); + resolveNeutrals ( wca, defaultLevel, ea, la, start, end, level, sor, eor ); + resolveImplicit ( wca, defaultLevel, ea, la, start, end, level, sor, eor ); + + // if this run is all retained formatting, then return prior level, otherwise this run's level + return isRetainedFormatting ( wca, start, end ) ? levelPrev : level; + } + + private static void resolveWeak ( int[] wca, int defaultLevel, int[] ea, int[] la, int start, int end, int level, int sor, int eor ) { + + // W1 - X BN* NSM -> X BN* X + for ( int i = start, n = end, bcPrev = sor; i < n; i++ ) { + int bc = wca [ i ]; + if ( bc == NSM ) { + wca [ i ] = bcPrev; + } else if ( bc != BN ) { + bcPrev = bc; + } + } + + // W2 - AL ... EN -> AL ... AN + for ( int i = start, n = end, bcPrev = sor; i < n; i++ ) { + int bc = wca [ i ]; + if ( bc == EN ) { + if ( bcPrev == AL ) { + wca [ i ] = AN; + } + } else if ( isStrong ( bc ) ) { + bcPrev = bc; + } + } + + // W3 - AL -> R + for ( int i = start, n = end; i < n; i++ ) { + int bc = wca [ i ]; + if ( bc == AL ) { + wca [ i ] = R; + } + } + + // W4 - EN BN* ES BN* EN -> EN BN* EN BN* EN; XN BN* CS BN* XN -> XN BN* XN BN* XN + for ( int i = start, n = end, bcPrev = sor; i < n; i++ ) { + int bc = wca [ i ]; + if ( bc == ES ) { + int bcNext = eor; + for ( int j = i + 1; j < n; j++ ) { + if ( ( bc = wca [ j ] ) != BN ) { + bcNext = bc; + break; + } + } + if ( ( bcPrev == EN ) && ( bcNext == EN ) ) { + wca [ i ] = EN; + } + } else if ( bc == CS ) { + int bcNext = eor; + for ( int j = i + 1; j < n; j++ ) { + if ( ( bc = wca [ j ] ) != BN ) { + bcNext = bc; + break; + } + } + if ( ( bcPrev == EN ) && ( bcNext == EN ) ) { + wca [ i ] = EN; + } else if ( ( bcPrev == AN ) && ( bcNext == AN ) ) { + wca [ i ] = AN; + } + } + if ( bc != BN ) { + bcPrev = bc; + } + } + + // W5 - EN (ET|BN)* -> EN (EN|BN)*; (ET|BN)* EN -> (EN|BN)* EN + for ( int i = start, n = end, bcPrev = sor; i < n; i++ ) { + int bc = wca [ i ]; + if ( bc == ET ) { + int bcNext = eor; + for ( int j = i + 1; j < n; j++ ) { + bc = wca [ j ]; + if ( ( bc != BN ) && ( bc != ET ) ) { + bcNext = bc; + break; + } + } + if ( ( bcPrev == EN ) || ( bcNext == EN ) ) { + wca [ i ] = EN; + } + } else if ( ( bc != BN ) && ( bc != ET ) ) { + bcPrev = bc; + } + } + + // W6 - BN* (ET|ES|CS) BN* -> ON* ON ON* + for ( int i = start, n = end; i < n; i++ ) { + int bc = wca [ i ]; + if ( ( bc == ET ) || ( bc == ES ) || ( bc == CS ) ) { + wca [ i ] = ON; + resolveAdjacentBoundaryNeutrals ( wca, start, end, i, ON ); + } + } + + // W7 - L ... EN -> L ... L + for ( int i = start, n = end, bcPrev = sor; i < n; i++ ) { + int bc = wca [ i ]; + if ( bc == EN ) { + if ( bcPrev == L ) { + wca [ i ] = L; + } + } else if ( ( bc == L ) || ( bc == R ) ) { + bcPrev = bc; + } + } + + } + + private static void resolveNeutrals ( int[] wca, int defaultLevel, int[] ea, int[] la, int start, int end, int level, int sor, int eor ) { + + // N1 - (L|R) N+ (L|R) -> L L+ L | R R+ R; (AN|EN) N+ R -> (AN|EN) R+ R; R N+ (AN|EN) -> R R+ (AN|EN) + for ( int i = start, n = end, bcPrev = sor; i < n; i++ ) { + int bc = wca [ i ]; + if ( isNeutral ( bc ) ) { + int bcNext = eor; + for ( int j = i + 1; j < n; j++ ) { + bc = wca [ j ]; + if ( ( bc == L ) || ( bc == R ) ) { + bcNext = bc; + break; + } else if ( ( bc == AN ) || ( bc == EN ) ) { + bcNext = R; + break; + } else if ( isNeutral ( bc ) ) { + continue; + } else if ( isRetainedFormatting ( bc ) ) { + continue; + } else { + break; + } + } + if ( bcPrev == bcNext ) { + wca [ i ] = bcPrev; + resolveAdjacentBoundaryNeutrals ( wca, start, end, i, bcPrev ); + } + } else if ( ( bc == L ) || ( bc == R ) ) { + bcPrev = bc; + } else if ( ( bc == AN ) || ( bc == EN ) ) { + bcPrev = R; + } + } + + // N2 - N -> embedding level + for ( int i = start, n = end; i < n; i++ ) { + int bc = wca [ i ]; + if ( isNeutral ( bc ) ) { + int bcEmbedding = directionOfLevel ( levelOfEmbedding ( ea [ i ] ) ); + wca [ i ] = bcEmbedding; + resolveAdjacentBoundaryNeutrals ( wca, start, end, i, bcEmbedding ); + } + } + + } + + private static void resolveAdjacentBoundaryNeutrals ( int[] wca, int start, int end, int index, int bcNew ) { + if ( ( index < start ) || ( index >= end ) ) { + throw new IllegalArgumentException(); + } else { + for ( int i = index - 1; i >= start; i-- ) { + int bc = wca [ i ]; + if ( bc == BN ) { + wca [ i ] = bcNew; + } else { + break; + } + } + for ( int i = index + 1; i < end; i++ ) { + int bc = wca [ i ]; + if ( bc == BN ) { + wca [ i ] = bcNew; + } else { + break; + } + } + } + } + + private static void resolveImplicit ( int[] wca, int defaultLevel, int[] ea, int[] la, int start, int end, int level, int sor, int eor ) { + for ( int i = start, n = end; i < n; i++ ) { + int bc = wca [ i ]; // bidi class + int el = la [ i ]; // embedding level + int ed = 0; // embedding level delta + if ( ( el & 1 ) == 0 ) { // even + if ( bc == R ) { + ed = 1; + } else if ( bc == AN ) { + ed = 2; + } else if ( bc == EN ) { + ed = 2; + } + } else { // odd + if ( bc == L ) { + ed = 1; + } else if ( bc == EN ) { + ed = 1; + } else if ( bc == AN ) { + ed = 1; + } + } + la [ i ] = el + ed; + } + } + + /** + * Resolve separators and boundary neutral levels to account for UAX#9 3.4 L1 while taking into + * account retention of formatting codes (5.2). + * @param ica original input class array (sequence) + * @param wca working copy of original intput class array (sequence), as modified by prior steps + * @param dl default paragraph level + * @param la array of output levels to be adjusted, as produced by bidi algorithm + */ + private static void resolveSeparators ( int[] ica, int[] wca, int dl, int[] la ) { + // steps (1) through (3) + for ( int i = 0, n = ica.length; i < n; i++ ) { + int ic = ica[i]; + if ( ( ic == BidiConstants.S ) || ( ic == BidiConstants.B ) ) { + la[i] = dl; + for ( int k = i - 1; k >= 0; k-- ) { + int pc = ica[k]; + if ( isRetainedFormatting ( pc ) ) { + continue; + } if ( pc == BidiConstants.WS ) { + la[k] = dl; + } else { + break; + } + } + } + } + // step (4) - consider end of input sequence to be end of line, but skip any trailing boundary neutrals and retained formatting codes + for ( int i = ica.length; i > 0; i-- ) { + int k = i - 1; + int ic = ica[k]; + if ( isRetainedFormatting ( ic ) ) { + continue; + } else if ( ic == BidiConstants.WS ) { + la[k] = dl; + } else { + break; + } + } + // step (5) - per section 5.2 + for ( int i = 0, n = ica.length; i < n; i++ ) { + int ic = ica[i]; + if ( isRetainedFormatting ( ic ) ) { + if ( i == 0 ) { + la[i] = dl; + } else { + la[i] = la [ i - 1 ]; + } + } + } + } + + private static boolean isStrong ( int bc ) { + switch ( bc ) { + case L: + case R: + case AL: + return true; + default: + return false; + } + } + + private static boolean isNeutral ( int bc ) { + switch ( bc ) { + case WS: + case ON: + case S: + case B: + return true; + default: + return false; + } + } + + private static boolean isRetainedFormatting ( int bc ) { + switch ( bc ) { + case LRE: + case LRO: + case RLE: + case RLO: + case PDF: + case BN: + return true; + default: + return false; + } + } + + private static boolean isRetainedFormatting ( int[] ca, int s, int e ) { + for ( int i = s; i < e; i++ ) { + if ( ! isRetainedFormatting ( ca[i] ) ) { + return false; + } + } + return true; + } + + private static int max ( int x, int y ) { + if ( x > y ) { + return x; + } else { + return y; + } + } + + private static int[] getClasses ( int[] chars ) { + int[] classes = new int [ chars.length ]; + int bc; + for ( int i = 0, n = chars.length; i < n; i++ ) { + int ch = chars [ i ]; + if ( ch >= 0 ) { + bc = BidiClass.getBidiClass ( chars [ i ] ); + } else { + bc = SURROGATE; + } + classes [ i ] = bc; + } + return classes; + } + + /** + * Convert character sequence (a UTF-16 encoded string) to an array of unicode scalar values + * expressed as integers. If a valid UTF-16 surrogate pair is encountered, it is converted to + * two integers, the first being the equivalent unicode scalar value, and the second being + * negative one (-1). This special mechanism is used to track the use of surrogate pairs while + * working with unicode scalar values, and permits maintaining indices that apply both to the + * input UTF-16 and out scalar value sequences. + * @return a boolean indicating that content is present that triggers bidirectional processing + * @param cs a UTF-16 encoded character sequence + * @param chars an integer array to accept the converted scalar values, where the length of the + * array must be the same as the length of the input character sequence + * @throws IllegalArgumentException if the input sequence is not a valid UTF-16 string, e.g., + * if it contains an isolated UTF-16 surrogate + */ + private static boolean convertToScalar ( CharSequence cs, int[] chars ) throws IllegalArgumentException { + boolean triggered = false; + if ( chars.length != cs.length() ) { + throw new IllegalArgumentException ( "characters array length must match input sequence length" ); + } + for ( int i = 0, n = chars.length; i < n; ) { + int chIn = cs.charAt ( i ); + int chOut; + if ( chIn < 0xD800 ) { + chOut = chIn; + } else if ( chIn < 0xDC00 ) { + int chHi = chIn; + int chLo; + if ( ( i + 1 ) < n ) { + chLo = cs.charAt ( i + 1 ); + if ( ( chLo >= 0xDC00 ) && ( chLo <= 0xDFFF ) ) { + chOut = convertToScalar ( chHi, chLo ); + } else { + throw new IllegalArgumentException ( "isolated high surrogate" ); + } + } else { + throw new IllegalArgumentException ( "truncated surrogate pair" ); + } + } else if ( chIn < 0xE000 ) { + throw new IllegalArgumentException ( "isolated low surrogate" ); + } else { + chOut = chIn; + } + if ( ! triggered && triggersBidi ( chOut ) ) { + triggered = true; + } + if ( ( chOut & 0xFF0000 ) == 0 ) { + chars [ i++ ] = chOut; + } else { + chars [ i++ ] = chOut; + chars [ i++ ] = -1; + } + } + return triggered; + } + + /** + * Convert UTF-16 surrogate pair to unicode scalar valuee. + * @return a unicode scalar value + * @param chHi high (most significant or first) surrogate + * @param chLo low (least significant or second) surrogate + * @throws IllegalArgumentException if one of the input surrogates is not valid + */ + private static int convertToScalar ( int chHi, int chLo ) { + if ( ( chHi < 0xD800 ) || ( chHi > 0xDBFF ) ) { + throw new IllegalArgumentException ( "bad high surrogate" ); + } else if ( ( chLo < 0xDC00 ) || ( chLo > 0xDFFF ) ) { + throw new IllegalArgumentException ( "bad low surrogate" ); + } else { + return ( ( ( chHi & 0x03FF ) << 10 ) | ( chLo & 0x03FF ) ) + 0x10000; + } + } + + /** + * Determine of character CH triggers bidirectional processing. Bidirectional + * processing is deemed triggerable if CH is a strong right-to-left character, + * an arabic letter or number, or is a right-to-left embedding or override + * character. + * @return true if character triggers bidirectional processing + * @param ch a unicode scalar value + */ + private static boolean triggersBidi ( int ch ) { + switch ( BidiClass.getBidiClass ( ch ) ) { + case R: + case AL: + case AN: + case RLE: + case RLO: + return true; + default: + return false; + } + } + + private static void dump ( String header, int[] chars, int[] classes, int defaultLevel, int[] levels ) { + log.debug ( header ); + log.debug ( "BD: default level(" + defaultLevel + ")" ); + StringBuffer sb = new StringBuffer(); + if ( chars != null ) { + for ( int i = 0, n = chars.length; i < n; i++ ) { + int ch = chars [ i ]; + sb.setLength(0); + if ( ( ch > 0x20 ) && ( ch < 0x7F ) ) { + sb.append ( (char) ch ); + } else { + sb.append ( CharUtilities.charToNCRef ( ch ) ); + } + for ( int k = sb.length(); k < 12; k++ ) { + sb.append ( ' ' ); + } + sb.append ( ": " + padRight ( getClassName ( classes[i] ), 4 ) + " " + levels[i] ); + log.debug ( sb ); + } + } else { + for ( int i = 0, n = classes.length; i < n; i++ ) { + sb.setLength(0); + for ( int k = sb.length(); k < 12; k++ ) { + sb.append ( ' ' ); + } + sb.append ( ": " + padRight ( getClassName ( classes[i] ), 4 ) + " " + levels[i] ); + log.debug ( sb ); + } + } + } + + private static String getClassName ( int bc ) { + switch ( bc ) { + case L: // left-to-right + return "L"; + case LRE: // left-to-right embedding + return "LRE"; + case LRO: // left-to-right override + return "LRO"; + case R: // right-to-left + return "R"; + case AL: // right-to-left arabic + return "AL"; + case RLE: // right-to-left embedding + return "RLE"; + case RLO: // right-to-left override + return "RLO"; + case PDF: // pop directional formatting + return "PDF"; + case EN: // european number + return "EN"; + case ES: // european number separator + return "ES"; + case ET: // european number terminator + return "ET"; + case AN: // arabic number + return "AN"; + case CS: // common number separator + return "CS"; + case NSM: // non-spacing mark + return "NSM"; + case BN: // boundary neutral + return "BN"; + case B: // paragraph separator + return "B"; + case S: // segment separator + return "S"; + case WS: // whitespace + return "WS"; + case ON: // other neutrals + return "ON"; + case SURROGATE: // placeholder for low surrogate + return "SUR"; + default: + return "?"; + } + } + + private static String padLeft ( int n, int width ) { + return padLeft ( Integer.toString ( n ), width ); + } + + private static String padLeft ( String s, int width ) { + StringBuffer sb = new StringBuffer(); + for ( int i = s.length(); i < width; i++ ) { + sb.append(' '); + } + sb.append ( s ); + return sb.toString(); + } + + /* not used yet + private static String padRight ( int n, int width ) { + return padRight ( Integer.toString ( n ), width ); + } + */ + + private static String padRight ( String s, int width ) { + StringBuffer sb = new StringBuffer ( s ); + for ( int i = sb.length(); i < width; i++ ) { + sb.append(' '); + } + return sb.toString(); + } + +} diff --git a/src/java/org/apache/fop/complexscripts/fonts/AdvancedTypographicTableFormatException.java b/src/java/org/apache/fop/complexscripts/fonts/AdvancedTypographicTableFormatException.java new file mode 100644 index 000000000..4f3e341d6 --- /dev/null +++ b/src/java/org/apache/fop/complexscripts/fonts/AdvancedTypographicTableFormatException.java @@ -0,0 +1,49 @@ +/* + * 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.complexscripts.fonts; + +/** + * Exception thrown when attempting to decode a truetype font file and a format + * constraint is violated. + * @author Glenn Adams + */ +public class AdvancedTypographicTableFormatException extends RuntimeException { + /** + * Instantiate ATT format exception. + */ + public AdvancedTypographicTableFormatException() { + super(); + } + /** + * Instantiate ATT format exception. + * @param message a message string + */ + public AdvancedTypographicTableFormatException(String message) { + super(message); + } + /** + * Instantiate ATT format exception. + * @param message a message string + * @param cause a Throwable that caused this exception + */ + public AdvancedTypographicTableFormatException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/src/java/org/apache/fop/complexscripts/fonts/GlyphClassMapping.java b/src/java/org/apache/fop/complexscripts/fonts/GlyphClassMapping.java new file mode 100644 index 000000000..4afc747a2 --- /dev/null +++ b/src/java/org/apache/fop/complexscripts/fonts/GlyphClassMapping.java @@ -0,0 +1,48 @@ +/* + * 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.complexscripts.fonts; + +// CSOFF: LineLengthCheck + +/** + * The GlyphClassMapping interface provides glyph identifier to class + * index mapping support. + * @author Glenn Adams + */ +public interface GlyphClassMapping { + + /** + * Obtain size of class table, i.e., ciMax + 1, where ciMax is the maximum + * class index. + * @param set for coverage set based class mappings, indicates set index, otherwise ignored + * @return size of class table + */ + int getClassSize ( int set ); + + /** + * Map glyph identifier (code) to coverge index. Returns -1 if glyph identifier is not in the domain of + * the class table. + * @param gid glyph identifier (code) + * @param set for coverage set based class mappings, indicates set index, otherwise ignored + * @return non-negative glyph class index or -1 if glyph identifiers is not mapped by table + */ + int getClassIndex ( int gid, int set ); + +} diff --git a/src/java/org/apache/fop/complexscripts/fonts/GlyphClassTable.java b/src/java/org/apache/fop/complexscripts/fonts/GlyphClassTable.java new file mode 100644 index 000000000..88478531e --- /dev/null +++ b/src/java/org/apache/fop/complexscripts/fonts/GlyphClassTable.java @@ -0,0 +1,277 @@ +/* + * 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.complexscripts.fonts; + +import java.util.Arrays; +import java.util.List; +import java.util.Iterator; + +// CSOFF: LineLengthCheck +// CSOFF: NoWhitespaceAfterCheck + +/** + * Base class implementation of glyph class table. + * @author Glenn Adams + */ +public final class GlyphClassTable extends GlyphMappingTable implements GlyphClassMapping { + + /** empty mapping table */ + public static final int GLYPH_CLASS_TYPE_EMPTY = GLYPH_MAPPING_TYPE_EMPTY; + + /** mapped mapping table */ + public static final int GLYPH_CLASS_TYPE_MAPPED = GLYPH_MAPPING_TYPE_MAPPED; + + /** range based mapping table */ + public static final int GLYPH_CLASS_TYPE_RANGE = GLYPH_MAPPING_TYPE_RANGE; + + /** empty mapping table */ + public static final int GLYPH_CLASS_TYPE_COVERAGE_SET = 3; + + private GlyphClassMapping cm; + + private GlyphClassTable ( GlyphClassMapping cm ) { + assert cm != null; + assert cm instanceof GlyphMappingTable; + this.cm = cm; + } + + /** {@inheritDoc} */ + public int getType() { + return ( (GlyphMappingTable) cm ) .getType(); + } + + /** {@inheritDoc} */ + public List getEntries() { + return ( (GlyphMappingTable) cm ) .getEntries(); + } + + /** {@inheritDoc} */ + public int getClassSize ( int set ) { + return cm.getClassSize ( set ); + } + + /** {@inheritDoc} */ + public int getClassIndex ( int gid, int set ) { + return cm.getClassIndex ( gid, set ); + } + + /** + * Create glyph class table. + * @param entries list of mapped or ranged class entries, or null or empty list + * @return a new covera table instance + */ + public static GlyphClassTable createClassTable ( List entries ) { + GlyphClassMapping cm; + if ( ( entries == null ) || ( entries.size() == 0 ) ) { + cm = new EmptyClassTable ( entries ); + } else if ( isMappedClass ( entries ) ) { + cm = new MappedClassTable ( entries ); + } else if ( isRangeClass ( entries ) ) { + cm = new RangeClassTable ( entries ); + } else if ( isCoverageSetClass ( entries ) ) { + cm = new CoverageSetClassTable ( entries ); + } else { + cm = null; + } + assert cm != null : "unknown class type"; + return new GlyphClassTable ( cm ); + } + + private static boolean isMappedClass ( List entries ) { + if ( ( entries == null ) || ( entries.size() == 0 ) ) { + return false; + } else { + for ( Iterator it = entries.iterator(); it.hasNext();) { + Object o = it.next(); + if ( ! ( o instanceof Integer ) ) { + return false; + } + } + return true; + } + } + + private static boolean isRangeClass ( List entries ) { + if ( ( entries == null ) || ( entries.size() == 0 ) ) { + return false; + } else { + for ( Iterator it = entries.iterator(); it.hasNext();) { + Object o = it.next(); + if ( ! ( o instanceof MappingRange ) ) { + return false; + } + } + return true; + } + } + + private static boolean isCoverageSetClass ( List entries ) { + if ( ( entries == null ) || ( entries.size() == 0 ) ) { + return false; + } else { + for ( Iterator it = entries.iterator(); it.hasNext();) { + Object o = it.next(); + if ( ! ( o instanceof GlyphCoverageTable ) ) { + return false; + } + } + return true; + } + } + + private static class EmptyClassTable extends GlyphMappingTable.EmptyMappingTable implements GlyphClassMapping { + public EmptyClassTable ( List entries ) { + super ( entries ); + } + /** {@inheritDoc} */ + public int getClassSize ( int set ) { + return 0; + } + /** {@inheritDoc} */ + public int getClassIndex ( int gid, int set ) { + return -1; + } + } + + private static class MappedClassTable extends GlyphMappingTable.MappedMappingTable implements GlyphClassMapping { + private int firstGlyph; + private int[] gca; + private int gcMax = -1; + public MappedClassTable ( List entries ) { + populate ( entries ); + } + /** {@inheritDoc} */ + public List getEntries() { + List entries = new java.util.ArrayList(); + entries.add ( Integer.valueOf ( firstGlyph ) ); + if ( gca != null ) { + for ( int i = 0, n = gca.length; i < n; i++ ) { + entries.add ( Integer.valueOf ( gca [ i ] ) ); + } + } + return entries; + } + /** {@inheritDoc} */ + public int getMappingSize() { + return gcMax + 1; + } + /** {@inheritDoc} */ + public int getMappedIndex ( int gid ) { + int i = gid - firstGlyph; + if ( ( i >= 0 ) && ( i < gca.length ) ) { + return gca [ i ]; + } else { + return -1; + } + } + /** {@inheritDoc} */ + public int getClassSize ( int set ) { + return getMappingSize(); + } + /** {@inheritDoc} */ + public int getClassIndex ( int gid, int set ) { + return getMappedIndex ( gid ); + } + private void populate ( List entries ) { + // obtain entries iterator + Iterator it = entries.iterator(); + // extract first glyph + int firstGlyph = 0; + if ( it.hasNext() ) { + Object o = it.next(); + if ( o instanceof Integer ) { + firstGlyph = ( (Integer) o ) . intValue(); + } else { + throw new AdvancedTypographicTableFormatException ( "illegal entry, first entry must be Integer denoting first glyph value, but is: " + o ); + } + } + // extract glyph class array + int i = 0, n = entries.size() - 1, gcMax = -1; + int[] gca = new int [ n ]; + while ( it.hasNext() ) { + Object o = it.next(); + if ( o instanceof Integer ) { + int gc = ( (Integer) o ) . intValue(); + gca [ i++ ] = gc; + if ( gc > gcMax ) { + gcMax = gc; + } + } else { + throw new AdvancedTypographicTableFormatException ( "illegal mapping entry, must be Integer: " + o ); + } + } + assert i == n; + assert this.gca == null; + this.firstGlyph = firstGlyph; + this.gca = gca; + this.gcMax = gcMax; + } + /** {@inheritDoc} */ + public String toString() { + StringBuffer sb = new StringBuffer(); + sb.append("{ firstGlyph = " + firstGlyph + ", classes = {"); + for ( int i = 0, n = gca.length; i < n; i++ ) { + if ( i > 0 ) { + sb.append(','); + } + sb.append ( Integer.toString ( gca [ i ] ) ); + } + sb.append("} }"); + return sb.toString(); + } + } + + private static class RangeClassTable extends GlyphMappingTable.RangeMappingTable implements GlyphClassMapping { + public RangeClassTable ( List entries ) { + super ( entries ); + } + /** {@inheritDoc} */ + public int getMappedIndex ( int gid, int s, int m ) { + return m; + } + /** {@inheritDoc} */ + public int getClassSize ( int set ) { + return getMappingSize(); + } + /** {@inheritDoc} */ + public int getClassIndex ( int gid, int set ) { + return getMappedIndex ( gid ); + } + } + + private static class CoverageSetClassTable extends GlyphMappingTable.EmptyMappingTable implements GlyphClassMapping { + public CoverageSetClassTable ( List entries ) { + throw new UnsupportedOperationException ( "coverage set class table not yet supported" ); + } + /** {@inheritDoc} */ + public int getType() { + return GLYPH_CLASS_TYPE_COVERAGE_SET; + } + /** {@inheritDoc} */ + public int getClassSize ( int set ) { + return 0; + } + /** {@inheritDoc} */ + public int getClassIndex ( int gid, int set ) { + return -1; + } + } + +} diff --git a/src/java/org/apache/fop/complexscripts/fonts/GlyphCoverageMapping.java b/src/java/org/apache/fop/complexscripts/fonts/GlyphCoverageMapping.java new file mode 100644 index 000000000..e8fde9474 --- /dev/null +++ b/src/java/org/apache/fop/complexscripts/fonts/GlyphCoverageMapping.java @@ -0,0 +1,46 @@ +/* + * 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.complexscripts.fonts; + +// CSOFF: LineLengthCheck + +/** + * The GlyphCoverageMapping interface provides glyph identifier to coverage + * index mapping support. + * @author Glenn Adams + */ +public interface GlyphCoverageMapping { + + /** + * Obtain size of coverage table, i.e., ciMax + 1, where ciMax is the maximum + * coverage index. + * @return size of coverage table + */ + int getCoverageSize(); + + /** + * Map glyph identifier (code) to coverge index. Returns -1 if glyph identifier is not in the domain of + * the coverage table. + * @param gid glyph identifier (code) + * @return non-negative glyph coverage index or -1 if glyph identifiers is not mapped by table + */ + int getCoverageIndex ( int gid ); + +} diff --git a/src/java/org/apache/fop/complexscripts/fonts/GlyphCoverageTable.java b/src/java/org/apache/fop/complexscripts/fonts/GlyphCoverageTable.java new file mode 100644 index 000000000..a9b0fc2b5 --- /dev/null +++ b/src/java/org/apache/fop/complexscripts/fonts/GlyphCoverageTable.java @@ -0,0 +1,233 @@ +/* + * 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.complexscripts.fonts; + +import java.util.Arrays; +import java.util.List; +import java.util.Iterator; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +// CSOFF: LineLengthCheck +// CSOFF: InnerAssignmentCheck +// CSOFF: NoWhitespaceAfterCheck + +/** + * Base class implementation of glyph coverage table. + * @author Glenn Adams + */ +public final class GlyphCoverageTable extends GlyphMappingTable implements GlyphCoverageMapping { + + /* logging instance */ + private static final Log log = LogFactory.getLog(GlyphCoverageTable.class); // CSOK: ConstantNameCheck + + /** empty mapping table */ + public static final int GLYPH_COVERAGE_TYPE_EMPTY = GLYPH_MAPPING_TYPE_EMPTY; + + /** mapped mapping table */ + public static final int GLYPH_COVERAGE_TYPE_MAPPED = GLYPH_MAPPING_TYPE_MAPPED; + + /** range based mapping table */ + public static final int GLYPH_COVERAGE_TYPE_RANGE = GLYPH_MAPPING_TYPE_RANGE; + + private GlyphCoverageMapping cm; + + private GlyphCoverageTable ( GlyphCoverageMapping cm ) { + assert cm != null; + assert cm instanceof GlyphMappingTable; + this.cm = cm; + } + + /** {@inheritDoc} */ + public int getType() { + return ( (GlyphMappingTable) cm ) .getType(); + } + + /** {@inheritDoc} */ + public List getEntries() { + return ( (GlyphMappingTable) cm ) .getEntries(); + } + + /** {@inheritDoc} */ + public int getCoverageSize() { + return cm.getCoverageSize(); + } + + /** {@inheritDoc} */ + public int getCoverageIndex ( int gid ) { + return cm.getCoverageIndex ( gid ); + } + + /** + * Create glyph coverage table. + * @param entries list of mapped or ranged coverage entries, or null or empty list + * @return a new covera table instance + */ + public static GlyphCoverageTable createCoverageTable ( List entries ) { + GlyphCoverageMapping cm; + if ( ( entries == null ) || ( entries.size() == 0 ) ) { + cm = new EmptyCoverageTable ( entries ); + } else if ( isMappedCoverage ( entries ) ) { + cm = new MappedCoverageTable ( entries ); + } else if ( isRangeCoverage ( entries ) ) { + cm = new RangeCoverageTable ( entries ); + } else { + cm = null; + } + assert cm != null : "unknown coverage type"; + return new GlyphCoverageTable ( cm ); + } + + private static boolean isMappedCoverage ( List entries ) { + if ( ( entries == null ) || ( entries.size() == 0 ) ) { + return false; + } else { + for ( Iterator it = entries.iterator(); it.hasNext();) { + Object o = it.next(); + if ( ! ( o instanceof Integer ) ) { + return false; + } + } + return true; + } + } + + private static boolean isRangeCoverage ( List entries ) { + if ( ( entries == null ) || ( entries.size() == 0 ) ) { + return false; + } else { + for ( Iterator it = entries.iterator(); it.hasNext();) { + Object o = it.next(); + if ( ! ( o instanceof MappingRange ) ) { + return false; + } + } + return true; + } + } + + private static class EmptyCoverageTable extends GlyphMappingTable.EmptyMappingTable implements GlyphCoverageMapping { + public EmptyCoverageTable ( List entries ) { + super ( entries ); + } + /** {@inheritDoc} */ + public int getCoverageSize() { + return 0; + } + /** {@inheritDoc} */ + public int getCoverageIndex ( int gid ) { + return -1; + } + } + + private static class MappedCoverageTable extends GlyphMappingTable.MappedMappingTable implements GlyphCoverageMapping { + private int[] map; + public MappedCoverageTable ( List entries ) { + populate ( entries ); + } + /** {@inheritDoc} */ + public List getEntries() { + List entries = new java.util.ArrayList(); + if ( map != null ) { + for ( int i = 0, n = map.length; i < n; i++ ) { + entries.add ( Integer.valueOf ( map [ i ] ) ); + } + } + return entries; + } + /** {@inheritDoc} */ + public int getMappingSize() { + return ( map != null ) ? map.length : 0; + } + public int getMappedIndex ( int gid ) { + int i; + if ( ( i = Arrays.binarySearch ( map, gid ) ) >= 0 ) { + return i; + } else { + return -1; + } + } + /** {@inheritDoc} */ + public int getCoverageSize() { + return getMappingSize(); + } + /** {@inheritDoc} */ + public int getCoverageIndex ( int gid ) { + return getMappedIndex ( gid ); + } + private void populate ( List entries ) { + int i = 0, n = entries.size(), gidMax = -1; + int[] map = new int [ n ]; + for ( Iterator it = entries.iterator(); it.hasNext();) { + Object o = it.next(); + if ( o instanceof Integer ) { + int gid = ( (Integer) o ) . intValue(); + if ( ( gid >= 0 ) && ( gid < 65536 ) ) { + if ( gid > gidMax ) { + map [ i++ ] = gidMax = gid; + } else { + log.info ( "ignoring out of order or duplicate glyph index: " + gid ); + } + } else { + throw new AdvancedTypographicTableFormatException ( "illegal glyph index: " + gid ); + } + } else { + throw new AdvancedTypographicTableFormatException ( "illegal coverage entry, must be Integer: " + o ); + } + } + assert i == n; + assert this.map == null; + this.map = map; + } + /** {@inheritDoc} */ + public String toString() { + StringBuffer sb = new StringBuffer(); + sb.append('{'); + for ( int i = 0, n = map.length; i < n; i++ ) { + if ( i > 0 ) { + sb.append(','); + } + sb.append ( Integer.toString ( map [ i ] ) ); + } + sb.append('}'); + return sb.toString(); + } + } + + private static class RangeCoverageTable extends GlyphMappingTable.RangeMappingTable implements GlyphCoverageMapping { + public RangeCoverageTable ( List entries ) { + super ( entries ); + } + /** {@inheritDoc} */ + public int getMappedIndex ( int gid, int s, int m ) { + return m + gid - s; + } + /** {@inheritDoc} */ + public int getCoverageSize() { + return getMappingSize(); + } + /** {@inheritDoc} */ + public int getCoverageIndex ( int gid ) { + return getMappedIndex ( gid ); + } + } + +} diff --git a/src/java/org/apache/fop/complexscripts/fonts/GlyphDefinition.java b/src/java/org/apache/fop/complexscripts/fonts/GlyphDefinition.java new file mode 100644 index 000000000..a3d511dce --- /dev/null +++ b/src/java/org/apache/fop/complexscripts/fonts/GlyphDefinition.java @@ -0,0 +1,38 @@ +/* + * 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.complexscripts.fonts; + +// CSOFF: LineLengthCheck + +/** + * The GlyphDefinition interface is a marker interface implemented by a glyph definition + * subtable. + * @author Glenn Adams + */ +public interface GlyphDefinition { + + /** + * Determine if some definition is available for a specific glyph. + * @param gi a glyph index + * @return true if some (unspecified) definition is available for the specified glyph + */ + boolean hasDefinition ( int gi ); + +} diff --git a/src/java/org/apache/fop/complexscripts/fonts/GlyphDefinitionSubtable.java b/src/java/org/apache/fop/complexscripts/fonts/GlyphDefinitionSubtable.java new file mode 100644 index 000000000..ec7e1e3d2 --- /dev/null +++ b/src/java/org/apache/fop/complexscripts/fonts/GlyphDefinitionSubtable.java @@ -0,0 +1,76 @@ +/* + * 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.complexscripts.fonts; + +// CSOFF: LineLengthCheck +// CSOFF: InnerAssignmentCheck + +/** + * The GlyphDefinitionSubtable implements an abstract base of a glyph definition subtable, + * providing a default implementation of the GlyphDefinition interface. + * @author Glenn Adams + */ +public abstract class GlyphDefinitionSubtable extends GlyphSubtable implements GlyphDefinition { + + /** + * Instantiate a GlyphDefinitionSubtable. + * @param id subtable identifier + * @param sequence subtable sequence + * @param flags subtable flags + * @param format subtable format + * @param mapping subtable coverage table + */ + protected GlyphDefinitionSubtable ( String id, int sequence, int flags, int format, GlyphMappingTable mapping ) { + super ( id, sequence, flags, format, mapping ); + } + + /** {@inheritDoc} */ + public int getTableType() { + return GlyphTable.GLYPH_TABLE_TYPE_DEFINITION; + } + + /** {@inheritDoc} */ + public String getTypeName() { + return GlyphDefinitionTable.getLookupTypeName ( getType() ); + } + + /** {@inheritDoc} */ + public boolean usesReverseScan() { + return false; + } + + /** {@inheritDoc} */ + public boolean hasDefinition ( int gi ) { + GlyphCoverageMapping cvm; + if ( ( cvm = getCoverage() ) != null ) { + if ( cvm.getCoverageIndex ( gi ) >= 0 ) { + return true; + } + } + GlyphClassMapping clm; + if ( ( clm = getClasses() ) != null ) { + if ( clm.getClassIndex ( gi, 0 ) >= 0 ) { + return true; + } + } + return false; + } + +} diff --git a/src/java/org/apache/fop/complexscripts/fonts/GlyphDefinitionTable.java b/src/java/org/apache/fop/complexscripts/fonts/GlyphDefinitionTable.java new file mode 100644 index 000000000..d5cd04615 --- /dev/null +++ b/src/java/org/apache/fop/complexscripts/fonts/GlyphDefinitionTable.java @@ -0,0 +1,451 @@ +/* + * 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.complexscripts.fonts; + +import java.nio.CharBuffer; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.apache.fop.complexscripts.scripts.ScriptProcessor; +import org.apache.fop.complexscripts.util.GlyphSequence; + +// CSOFF: InnerAssignmentCheck +// CSOFF: LineLengthCheck + +/** + * The GlyphDefinitionTable class is a glyph table that implements + * glyph definition functionality according to the OpenType GDEF table. + * @author Glenn Adams + */ +public class GlyphDefinitionTable extends GlyphTable { + + /** logging instance */ + private static final Log log = LogFactory.getLog(GlyphDefinitionTable.class); // CSOK: ConstantNameCheck + + /** glyph class subtable type */ + public static final int GDEF_LOOKUP_TYPE_GLYPH_CLASS = 1; + /** attachment point subtable type */ + public static final int GDEF_LOOKUP_TYPE_ATTACHMENT_POINT = 2; + /** ligature caret subtable type */ + public static final int GDEF_LOOKUP_TYPE_LIGATURE_CARET = 3; + /** mark attachment subtable type */ + public static final int GDEF_LOOKUP_TYPE_MARK_ATTACHMENT = 4; + + /** pre-defined glyph class - base glyph */ + public static final int GLYPH_CLASS_BASE = 1; + /** pre-defined glyph class - ligature glyph */ + public static final int GLYPH_CLASS_LIGATURE = 2; + /** pre-defined glyph class - mark glyph */ + public static final int GLYPH_CLASS_MARK = 3; + /** pre-defined glyph class - component glyph */ + public static final int GLYPH_CLASS_COMPONENT = 4; + + /** singleton glyph class table */ + private GlyphClassSubtable gct; + /** singleton attachment point table */ + // private AttachmentPointSubtable apt; // NOT YET USED + /** singleton ligature caret table */ + // private LigatureCaretSubtable lct; // NOT YET USED + /** singleton mark attachment table */ + private MarkAttachmentSubtable mat; + + /** + * Instantiate a GlyphDefinitionTable object using the specified subtables. + * @param subtables a list of identified subtables + */ + public GlyphDefinitionTable ( List subtables ) { + super ( null, new HashMap(0) ); + if ( ( subtables == null ) || ( subtables.size() == 0 ) ) { + throw new AdvancedTypographicTableFormatException ( "subtables must be non-empty" ); + } else { + for ( Iterator it = subtables.iterator(); it.hasNext();) { + Object o = it.next(); + if ( o instanceof GlyphDefinitionSubtable ) { + addSubtable ( (GlyphSubtable) o ); + } else { + throw new AdvancedTypographicTableFormatException ( "subtable must be a glyph definition subtable" ); + } + } + freezeSubtables(); + } + } + + /** + * Reorder combining marks in glyph sequence so that they precede (within the sequence) the base + * character to which they are applied. N.B. In the case of LTR segments, marks are not reordered by this, + * method since when the segment is reversed by BIDI processing, marks are automatically reordered to precede + * their base glyph. + * @param gs an input glyph sequence + * @param gpa associated glyph position adjustments (also reordered) + * @param script a script identifier + * @param language a language identifier + * @return the reordered (output) glyph sequence + */ + public GlyphSequence reorderCombiningMarks ( GlyphSequence gs, int[][] gpa, String script, String language ) { + ScriptProcessor sp = ScriptProcessor.getInstance ( script ); + return sp.reorderCombiningMarks ( this, gs, gpa, script, language ); + } + + /** {@inheritDoc} */ + protected void addSubtable ( GlyphSubtable subtable ) { + if ( subtable instanceof GlyphClassSubtable ) { + this.gct = (GlyphClassSubtable) subtable; + } else if ( subtable instanceof AttachmentPointSubtable ) { + // TODO - not yet used + // this.apt = (AttachmentPointSubtable) subtable; + } else if ( subtable instanceof LigatureCaretSubtable ) { + // TODO - not yet used + // this.lct = (LigatureCaretSubtable) subtable; + } else if ( subtable instanceof MarkAttachmentSubtable ) { + this.mat = (MarkAttachmentSubtable) subtable; + } else { + throw new UnsupportedOperationException ( "unsupported glyph definition subtable type: " + subtable ); + } + } + + /** + * Determine if glyph belongs to pre-defined glyph class. + * @param gid a glyph identifier (index) + * @param gc a pre-defined glyph class (GLYPH_CLASS_BASE|GLYPH_CLASS_LIGATURE|GLYPH_CLASS_MARK|GLYPH_CLASS_COMPONENT). + * @return true if glyph belongs to specified glyph class + */ + public boolean isGlyphClass ( int gid, int gc ) { + if ( gct != null ) { + return gct.isGlyphClass ( gid, gc ); + } else { + return false; + } + } + + /** + * Determine glyph class. + * @param gid a glyph identifier (index) + * @return a pre-defined glyph class (GLYPH_CLASS_BASE|GLYPH_CLASS_LIGATURE|GLYPH_CLASS_MARK|GLYPH_CLASS_COMPONENT). + */ + public int getGlyphClass ( int gid ) { + if ( gct != null ) { + return gct.getGlyphClass ( gid ); + } else { + return -1; + } + } + + /** + * Determine if glyph belongs to (font specific) mark attachment class. + * @param gid a glyph identifier (index) + * @param mac a (font specific) mark attachment class + * @return true if glyph belongs to specified mark attachment class + */ + public boolean isMarkAttachClass ( int gid, int mac ) { + if ( mat != null ) { + return mat.isMarkAttachClass ( gid, mac ); + } else { + return false; + } + } + + /** + * Determine mark attachment class. + * @param gid a glyph identifier (index) + * @return a non-negative mark attachment class, or -1 if no class defined + */ + public int getMarkAttachClass ( int gid ) { + if ( mat != null ) { + return mat.getMarkAttachClass ( gid ); + } else { + return -1; + } + } + + /** + * Map a lookup type name to its constant (integer) value. + * @param name lookup type name + * @return lookup type + */ + public static int getLookupTypeFromName ( String name ) { + int t; + String s = name.toLowerCase(); + if ( "glyphclass".equals ( s ) ) { + t = GDEF_LOOKUP_TYPE_GLYPH_CLASS; + } else if ( "attachmentpoint".equals ( s ) ) { + t = GDEF_LOOKUP_TYPE_ATTACHMENT_POINT; + } else if ( "ligaturecaret".equals ( s ) ) { + t = GDEF_LOOKUP_TYPE_LIGATURE_CARET; + } else if ( "markattachment".equals ( s ) ) { + t = GDEF_LOOKUP_TYPE_MARK_ATTACHMENT; + } else { + t = -1; + } + return t; + } + + /** + * Map a lookup type constant (integer) value to its name. + * @param type lookup type + * @return lookup type name + */ + public static String getLookupTypeName ( int type ) { + String tn = null; + switch ( type ) { + case GDEF_LOOKUP_TYPE_GLYPH_CLASS: + tn = "glyphclass"; + break; + case GDEF_LOOKUP_TYPE_ATTACHMENT_POINT: + tn = "attachmentpoint"; + break; + case GDEF_LOOKUP_TYPE_LIGATURE_CARET: + tn = "ligaturecaret"; + break; + case GDEF_LOOKUP_TYPE_MARK_ATTACHMENT: + tn = "markattachment"; + break; + default: + tn = "unknown"; + break; + } + return tn; + } + + /** + * Create a definition subtable according to the specified arguments. + * @param type subtable type + * @param id subtable identifier + * @param sequence subtable sequence + * @param flags subtable flags (must be zero) + * @param format subtable format + * @param mapping subtable mapping table + * @param entries subtable entries + * @return a glyph subtable instance + */ + public static GlyphSubtable createSubtable ( int type, String id, int sequence, int flags, int format, GlyphMappingTable mapping, List entries ) { + GlyphSubtable st = null; + switch ( type ) { + case GDEF_LOOKUP_TYPE_GLYPH_CLASS: + st = GlyphClassSubtable.create ( id, sequence, flags, format, mapping, entries ); + break; + case GDEF_LOOKUP_TYPE_ATTACHMENT_POINT: + st = AttachmentPointSubtable.create ( id, sequence, flags, format, mapping, entries ); + break; + case GDEF_LOOKUP_TYPE_LIGATURE_CARET: + st = LigatureCaretSubtable.create ( id, sequence, flags, format, mapping, entries ); + break; + case GDEF_LOOKUP_TYPE_MARK_ATTACHMENT: + st = MarkAttachmentSubtable.create ( id, sequence, flags, format, mapping, entries ); + break; + default: + break; + } + return st; + } + + private abstract static class GlyphClassSubtable extends GlyphDefinitionSubtable { + GlyphClassSubtable ( String id, int sequence, int flags, int format, GlyphMappingTable mapping, List entries ) { + super ( id, sequence, flags, format, mapping ); + } + /** {@inheritDoc} */ + public int getType() { + return GDEF_LOOKUP_TYPE_GLYPH_CLASS; + } + /** + * Determine if glyph belongs to pre-defined glyph class. + * @param gid a glyph identifier (index) + * @param gc a pre-defined glyph class (GLYPH_CLASS_BASE|GLYPH_CLASS_LIGATURE|GLYPH_CLASS_MARK|GLYPH_CLASS_COMPONENT). + * @return true if glyph belongs to specified glyph class + */ + public abstract boolean isGlyphClass ( int gid, int gc ); + /** + * Determine glyph class. + * @param gid a glyph identifier (index) + * @return a pre-defined glyph class (GLYPH_CLASS_BASE|GLYPH_CLASS_LIGATURE|GLYPH_CLASS_MARK|GLYPH_CLASS_COMPONENT). + */ + public abstract int getGlyphClass ( int gid ); + static GlyphDefinitionSubtable create ( String id, int sequence, int flags, int format, GlyphMappingTable mapping, List entries ) { + if ( format == 1 ) { + return new GlyphClassSubtableFormat1 ( id, sequence, flags, format, mapping, entries ); + } else { + throw new UnsupportedOperationException(); + } + } + } + + private static class GlyphClassSubtableFormat1 extends GlyphClassSubtable { + GlyphClassSubtableFormat1 ( String id, int sequence, int flags, int format, GlyphMappingTable mapping, List entries ) { + super ( id, sequence, flags, format, mapping, entries ); + } + /** {@inheritDoc} */ + public List getEntries() { + return null; + } + /** {@inheritDoc} */ + public boolean isCompatible ( GlyphSubtable subtable ) { + return subtable instanceof GlyphClassSubtable; + } + /** {@inheritDoc} */ + public boolean isGlyphClass ( int gid, int gc ) { + GlyphClassMapping cm = getClasses(); + if ( cm != null ) { + return cm.getClassIndex ( gid, 0 ) == gc; + } else { + return false; + } + } + /** {@inheritDoc} */ + public int getGlyphClass ( int gid ) { + GlyphClassMapping cm = getClasses(); + if ( cm != null ) { + return cm.getClassIndex ( gid, 0 ); + } else { + return -1; + } + } + } + + private abstract static class AttachmentPointSubtable extends GlyphDefinitionSubtable { + AttachmentPointSubtable ( String id, int sequence, int flags, int format, GlyphMappingTable mapping, List entries ) { + super ( id, sequence, flags, format, mapping ); + } + /** {@inheritDoc} */ + public int getType() { + return GDEF_LOOKUP_TYPE_ATTACHMENT_POINT; + } + static GlyphDefinitionSubtable create ( String id, int sequence, int flags, int format, GlyphMappingTable mapping, List entries ) { + if ( format == 1 ) { + return new AttachmentPointSubtableFormat1 ( id, sequence, flags, format, mapping, entries ); + } else { + throw new UnsupportedOperationException(); + } + } + } + + private static class AttachmentPointSubtableFormat1 extends AttachmentPointSubtable { + AttachmentPointSubtableFormat1 ( String id, int sequence, int flags, int format, GlyphMappingTable mapping, List entries ) { + super ( id, sequence, flags, format, mapping, entries ); + } + /** {@inheritDoc} */ + public List getEntries() { + return null; + } + /** {@inheritDoc} */ + public boolean isCompatible ( GlyphSubtable subtable ) { + return subtable instanceof AttachmentPointSubtable; + } + } + + private abstract static class LigatureCaretSubtable extends GlyphDefinitionSubtable { + LigatureCaretSubtable ( String id, int sequence, int flags, int format, GlyphMappingTable mapping, List entries ) { + super ( id, sequence, flags, format, mapping ); + } + /** {@inheritDoc} */ + public int getType() { + return GDEF_LOOKUP_TYPE_LIGATURE_CARET; + } + static GlyphDefinitionSubtable create ( String id, int sequence, int flags, int format, GlyphMappingTable mapping, List entries ) { + if ( format == 1 ) { + return new LigatureCaretSubtableFormat1 ( id, sequence, flags, format, mapping, entries ); + } else { + throw new UnsupportedOperationException(); + } + } + } + + private static class LigatureCaretSubtableFormat1 extends LigatureCaretSubtable { + LigatureCaretSubtableFormat1 ( String id, int sequence, int flags, int format, GlyphMappingTable mapping, List entries ) { + super ( id, sequence, flags, format, mapping, entries ); + } + /** {@inheritDoc} */ + public List getEntries() { + return null; + } + /** {@inheritDoc} */ + public boolean isCompatible ( GlyphSubtable subtable ) { + return subtable instanceof LigatureCaretSubtable; + } + } + + private abstract static class MarkAttachmentSubtable extends GlyphDefinitionSubtable { + MarkAttachmentSubtable ( String id, int sequence, int flags, int format, GlyphMappingTable mapping, List entries ) { + super ( id, sequence, flags, format, mapping ); + } + /** {@inheritDoc} */ + public int getType() { + return GDEF_LOOKUP_TYPE_MARK_ATTACHMENT; + } + /** + * Determine if glyph belongs to (font specific) mark attachment class. + * @param gid a glyph identifier (index) + * @param mac a (font specific) mark attachment class + * @return true if glyph belongs to specified mark attachment class + */ + public abstract boolean isMarkAttachClass ( int gid, int mac ); + /** + * Determine mark attachment class. + * @param gid a glyph identifier (index) + * @return a non-negative mark attachment class, or -1 if no class defined + */ + public abstract int getMarkAttachClass ( int gid ); + static GlyphDefinitionSubtable create ( String id, int sequence, int flags, int format, GlyphMappingTable mapping, List entries ) { + if ( format == 1 ) { + return new MarkAttachmentSubtableFormat1 ( id, sequence, flags, format, mapping, entries ); + } else { + throw new UnsupportedOperationException(); + } + } + } + + private static class MarkAttachmentSubtableFormat1 extends MarkAttachmentSubtable { + MarkAttachmentSubtableFormat1 ( String id, int sequence, int flags, int format, GlyphMappingTable mapping, List entries ) { + super ( id, sequence, flags, format, mapping, entries ); + } + /** {@inheritDoc} */ + public List getEntries() { + return null; + } + /** {@inheritDoc} */ + public boolean isCompatible ( GlyphSubtable subtable ) { + return subtable instanceof MarkAttachmentSubtable; + } + /** {@inheritDoc} */ + public boolean isMarkAttachClass ( int gid, int mac ) { + GlyphClassMapping cm = getClasses(); + if ( cm != null ) { + return cm.getClassIndex ( gid, 0 ) == mac; + } else { + return false; + } + } + /** {@inheritDoc} */ + public int getMarkAttachClass ( int gid ) { + GlyphClassMapping cm = getClasses(); + if ( cm != null ) { + return cm.getClassIndex ( gid, 0 ); + } else { + return -1; + } + } + } + +} diff --git a/src/java/org/apache/fop/complexscripts/fonts/GlyphMappingTable.java b/src/java/org/apache/fop/complexscripts/fonts/GlyphMappingTable.java new file mode 100644 index 000000000..a0791e8f6 --- /dev/null +++ b/src/java/org/apache/fop/complexscripts/fonts/GlyphMappingTable.java @@ -0,0 +1,322 @@ +/* + * 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.complexscripts.fonts; + +import java.util.Arrays; +import java.util.List; +import java.util.Iterator; + +// CSOFF: NoWhitespaceAfterCheck +// CSOFF: InnerAssignmentCheck +// CSOFF: LineLengthCheck + +/** + * Base class implementation of glyph mapping table. This base + * class maps glyph indices to arbitrary integers (mappping indices), and + * is used to implement both glyph coverage and glyph class maps. + * @author Glenn Adams + */ +public class GlyphMappingTable { + + /** empty mapping table */ + public static final int GLYPH_MAPPING_TYPE_EMPTY = 0; + + /** mapped mapping table */ + public static final int GLYPH_MAPPING_TYPE_MAPPED = 1; + + /** range based mapping table */ + public static final int GLYPH_MAPPING_TYPE_RANGE = 2; + + /** + * Obtain mapping type. + * @return mapping format type + */ + public int getType() { + return -1; + } + + /** + * Obtain mapping entries. + * @return list of mapping entries + */ + public List getEntries() { + return null; + } + + /** + * Obtain size of mapping table, i.e., ciMax + 1, where ciMax is the maximum + * mapping index. + * @return size of mapping table + */ + public int getMappingSize() { + return 0; + } + + /** + * Map glyph identifier (code) to coverge index. Returns -1 if glyph identifier is not in the domain of + * the mapping table. + * @param gid glyph identifier (code) + * @return non-negative glyph mapping index or -1 if glyph identifiers is not mapped by table + */ + public int getMappedIndex ( int gid ) { + return -1; + } + + /** empty mapping table base class */ + protected static class EmptyMappingTable extends GlyphMappingTable { + /** + * Construct empty mapping table. + */ + public EmptyMappingTable() { + this ( (List) null ); + } + /** + * Construct empty mapping table with entries (ignored). + * @param entries list of entries (ignored) + */ + public EmptyMappingTable ( List entries ) { + } + /** {@inheritDoc} */ + public int getType() { + return GLYPH_MAPPING_TYPE_EMPTY; + } + /** {@inheritDoc} */ + public List getEntries() { + return new java.util.ArrayList(); + } + /** {@inheritDoc} */ + public int getMappingSize() { + return 0; + } + /** {@inheritDoc} */ + public int getMappedIndex ( int gid ) { + return -1; + } + } + + /** mapped mapping table base class */ + protected static class MappedMappingTable extends GlyphMappingTable { + /** + * Construct mapped mapping table. + */ + public MappedMappingTable() { + } + /** {@inheritDoc} */ + public int getType() { + return GLYPH_MAPPING_TYPE_MAPPED; + } + } + + /** range mapping table base class */ + protected abstract static class RangeMappingTable extends GlyphMappingTable { + private int[] sa = null; // array of range (inclusive) starts + private int[] ea = null; // array of range (inclusive) ends + private int[] ma = null; // array of range mapped values + private int miMax = -1; + /** + * Construct range mapping table. + * @param entries of mapping ranges + */ + public RangeMappingTable ( List entries ) { + populate ( entries ); + } + /** {@inheritDoc} */ + public int getType() { + return GLYPH_MAPPING_TYPE_RANGE; + } + /** {@inheritDoc} */ + public List getEntries() { + List entries = new java.util.ArrayList(); + if ( sa != null ) { + for ( int i = 0, n = sa.length; i < n; i++ ) { + entries.add ( new MappingRange ( sa [ i ], ea [ i ], ma [ i ] ) ); + } + } + return entries; + } + /** {@inheritDoc} */ + public int getMappingSize() { + return miMax + 1; + } + /** {@inheritDoc} */ + public int getMappedIndex ( int gid ) { + int i, mi; + if ( ( i = Arrays.binarySearch ( sa, gid ) ) >= 0 ) { + mi = getMappedIndex ( gid, sa [ i ], ma [ i ] ); // matches start of (some) range + } else if ( ( i = - ( i + 1 ) ) == 0 ) { + mi = -1; // precedes first range + } else if ( gid > ea [ --i ] ) { + mi = -1; // follows preceding (or last) range + } else { + mi = getMappedIndex ( gid, sa [ i ], ma [ i ] ); // intersects (some) range + } + return mi; + } + /** + * Map glyph identifier (code) to coverge index. Returns -1 if glyph identifier is not in the domain of + * the mapping table. + * @param gid glyph identifier (code) + * @param s start of range + * @param m mapping value + * @return non-negative glyph mapping index or -1 if glyph identifiers is not mapped by table + */ + public abstract int getMappedIndex ( int gid, int s, int m ); + private void populate ( List entries ) { + int i = 0, n = entries.size(), gidMax = -1, miMax = -1; + int[] sa = new int [ n ]; + int[] ea = new int [ n ]; + int[] ma = new int [ n ]; + for ( Iterator it = entries.iterator(); it.hasNext();) { + Object o = it.next(); + if ( o instanceof MappingRange ) { + MappingRange r = (MappingRange) o; + int gs = r.getStart(); + int ge = r.getEnd(); + int mi = r.getIndex(); + if ( ( gs < 0 ) || ( gs > 65535 ) ) { + throw new AdvancedTypographicTableFormatException ( "illegal glyph range: [" + gs + "," + ge + "]: bad start index" ); + } else if ( ( ge < 0 ) || ( ge > 65535 ) ) { + throw new AdvancedTypographicTableFormatException ( "illegal glyph range: [" + gs + "," + ge + "]: bad end index" ); + } else if ( gs > ge ) { + throw new AdvancedTypographicTableFormatException ( "illegal glyph range: [" + gs + "," + ge + "]: start index exceeds end index" ); + } else if ( gs < gidMax ) { + throw new AdvancedTypographicTableFormatException ( "out of order glyph range: [" + gs + "," + ge + "]" ); + } else if ( mi < 0 ) { + throw new AdvancedTypographicTableFormatException ( "illegal mapping index: " + mi ); + } else { + int miLast; + sa [ i ] = gs; + ea [ i ] = gidMax = ge; + ma [ i ] = mi; + if ( ( miLast = mi + ( ge - gs ) ) > miMax ) { + miMax = miLast; + } + i++; + } + } else { + throw new AdvancedTypographicTableFormatException ( "illegal mapping entry, must be Integer: " + o ); + } + } + assert i == n; + assert this.sa == null; + assert this.ea == null; + assert this.ma == null; + this.sa = sa; + this.ea = ea; + this.ma = ma; + this.miMax = miMax; + } + /** {@inheritDoc} */ + public String toString() { + StringBuffer sb = new StringBuffer(); + sb.append('{'); + for ( int i = 0, n = sa.length; i < n; i++ ) { + if ( i > 0 ) { + sb.append(','); + } + sb.append ( '[' ); + sb.append ( Integer.toString ( sa [ i ] ) ); + sb.append ( Integer.toString ( ea [ i ] ) ); + sb.append ( "]:" ); + sb.append ( Integer.toString ( ma [ i ] ) ); + } + sb.append('}'); + return sb.toString(); + } + } + + /** + * The MappingRange class encapsulates a glyph [start,end] range and + * a mapping index. + */ + public static class MappingRange { + + private final int gidStart; // first glyph in range (inclusive) + private final int gidEnd; // last glyph in range (inclusive) + private final int index; // mapping index; + + /** + * Instantiate a mapping range. + */ + public MappingRange() { + this ( 0, 0, 0 ); + } + + /** + * Instantiate a specific mapping range. + * @param gidStart start of range + * @param gidEnd end of range + * @param index mapping index + */ + public MappingRange ( int gidStart, int gidEnd, int index ) { + if ( ( gidStart < 0 ) || ( gidEnd < 0 ) || ( index < 0 ) ) { + throw new AdvancedTypographicTableFormatException(); + } else if ( gidStart > gidEnd ) { + throw new AdvancedTypographicTableFormatException(); + } else { + this.gidStart = gidStart; + this.gidEnd = gidEnd; + this.index = index; + } + } + + /** @return start of range */ + public int getStart() { + return gidStart; + } + + /** @return end of range */ + public int getEnd() { + return gidEnd; + } + + /** @return mapping index */ + public int getIndex() { + return index; + } + + /** @return interval as a pair of integers */ + public int[] getInterval() { + return new int[] { gidStart, gidEnd }; + } + + /** + * Obtain interval, filled into first two elements of specified array, or returning new array. + * @param interval an array of length two or greater or null + * @return interval as a pair of integers, filled into specified array + */ + public int[] getInterval ( int[] interval ) { + if ( ( interval == null ) || ( interval.length != 2 ) ) { + throw new IllegalArgumentException(); + } else { + interval[0] = gidStart; + interval[1] = gidEnd; + } + return interval; + } + + /** @return length of interval */ + public int getLength() { + return gidStart - gidEnd; + } + + } + +} diff --git a/src/java/org/apache/fop/complexscripts/fonts/GlyphPositioning.java b/src/java/org/apache/fop/complexscripts/fonts/GlyphPositioning.java new file mode 100644 index 000000000..92fae7506 --- /dev/null +++ b/src/java/org/apache/fop/complexscripts/fonts/GlyphPositioning.java @@ -0,0 +1,43 @@ +/* + * 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.complexscripts.fonts; + +// CSOFF: LineLengthCheck + +/** + * The GlyphPositioning interface is implemented by a glyph positioning subtable + * that supports the determination of glyph positioning information based on script and + * language of the corresponding character content. + * @author Glenn Adams + */ +public interface GlyphPositioning { + + /** + * Perform glyph positioning at the current index, mutating the positioning state object as required. + * Only the context associated with the current index is processed. + * @param ps glyph positioning state object + * @return true if the glyph subtable applies, meaning that the current context matches the + * associated input context glyph coverage table; note that returning true does not mean any position + * adjustment occurred; it only means that no further glyph subtables for the current lookup table + * should be applied. + */ + boolean position ( GlyphPositioningState ps ); + +} diff --git a/src/java/org/apache/fop/complexscripts/fonts/GlyphPositioningState.java b/src/java/org/apache/fop/complexscripts/fonts/GlyphPositioningState.java new file mode 100644 index 000000000..ea62a7239 --- /dev/null +++ b/src/java/org/apache/fop/complexscripts/fonts/GlyphPositioningState.java @@ -0,0 +1,208 @@ +/* + * 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.complexscripts.fonts; + +import org.apache.fop.complexscripts.util.GlyphSequence; +import org.apache.fop.complexscripts.util.ScriptContextTester; + +// CSOFF: LineLengthCheck +// CSOFF: ParameterNumberCheck + +/** + * The GlyphPositioningState implements an state object used during glyph positioning + * processing. + * @author Glenn Adams + */ + +public class GlyphPositioningState extends GlyphProcessingState { + + /** font size */ + private int fontSize; + /** default advancements */ + private int[] widths; + /** current adjustments */ + private int[][] adjustments; + /** if true, then some adjustment was applied */ + private boolean adjusted; + + /** + * Construct glyph positioning state. + * @param gs input glyph sequence + * @param script script identifier + * @param language language identifier + * @param feature feature identifier + * @param fontSize font size (in micropoints) + * @param widths array of design advancements (in glyph index order) + * @param adjustments positioning adjustments to which positioning is applied + * @param sct script context tester (or null) + */ + public GlyphPositioningState ( GlyphSequence gs, String script, String language, String feature, int fontSize, int[] widths, int[][] adjustments, ScriptContextTester sct ) { + super ( gs, script, language, feature, sct ); + this.fontSize = fontSize; + this.widths = widths; + this.adjustments = adjustments; + } + + /** + * Construct glyph positioning state using an existing state object using shallow copy + * except as follows: input glyph sequence is copied deep except for its characters array. + * @param ps existing positioning state to copy from + */ + public GlyphPositioningState ( GlyphPositioningState ps ) { + super ( ps ); + this.fontSize = ps.fontSize; + this.widths = ps.widths; + this.adjustments = ps.adjustments; + } + + /** + * Obtain design advancement (width) of glyph at specified index. + * @param gi glyph index + * @return design advancement, or zero if glyph index is not present + */ + public int getWidth ( int gi ) { + if ( ( widths != null ) && ( gi < widths.length ) ) { + return widths [ gi ]; + } else { + return 0; + } + } + + /** + * Perform adjustments at current position index. + * @param v value containing adjustments + * @return true if a non-zero adjustment was made + */ + public boolean adjust ( GlyphPositioningTable.Value v ) { + return adjust ( v, 0 ); + } + + /** + * Perform adjustments at specified offset from current position index. + * @param v value containing adjustments + * @param offset from current position index + * @return true if a non-zero adjustment was made + */ + public boolean adjust ( GlyphPositioningTable.Value v, int offset ) { + assert v != null; + if ( ( index + offset ) < indexLast ) { + return v.adjust ( adjustments [ index + offset ], fontSize ); + } else { + throw new IndexOutOfBoundsException(); + } + } + + /** + * Obtain current adjustments at current position index. + * @return array of adjustments (int[4]) at current position + */ + public int[] getAdjustment() { + return getAdjustment ( 0 ); + } + + /** + * Obtain current adjustments at specified offset from current position index. + * @param offset from current position index + * @return array of adjustments (int[4]) at specified offset + * @throws IndexOutOfBoundsException if offset is invalid + */ + public int[] getAdjustment ( int offset ) throws IndexOutOfBoundsException { + if ( ( index + offset ) < indexLast ) { + return adjustments [ index + offset ]; + } else { + throw new IndexOutOfBoundsException(); + } + } + + /** + * Apply positioning subtable to current state at current position (only), + * resulting in the consumption of zero or more input glyphs. + * @param st the glyph positioning subtable to apply + * @return true if subtable applied, or false if it did not (e.g., its + * input coverage table did not match current input context) + */ + public boolean apply ( GlyphPositioningSubtable st ) { + assert st != null; + updateSubtableState ( st ); + boolean applied = st.position ( this ); + resetSubtableState(); + return applied; + } + + /** + * Apply a sequence of matched rule lookups to the nig input glyphs + * starting at the current position. If lookups are non-null and non-empty, then + * all input glyphs specified by nig are consumed irregardless of + * whether any specified lookup applied. + * @param lookups array of matched lookups (or null) + * @param nig number of glyphs in input sequence, starting at current position, to which + * the lookups are to apply, and to be consumed once the application has finished + * @return true if lookups are non-null and non-empty; otherwise, false + */ + public boolean apply ( GlyphTable.RuleLookup[] lookups, int nig ) { + if ( ( lookups != null ) && ( lookups.length > 0 ) ) { + // apply each rule lookup to extracted input glyph array + for ( int i = 0, n = lookups.length; i < n; i++ ) { + GlyphTable.RuleLookup l = lookups [ i ]; + if ( l != null ) { + GlyphTable.LookupTable lt = l.getLookup(); + if ( lt != null ) { + // perform positioning on a copy of previous state + GlyphPositioningState ps = new GlyphPositioningState ( this ); + // apply lookup table positioning + if ( lt.position ( ps, l.getSequenceIndex() ) ) { + setAdjusted ( true ); + } + } + } + } + consume ( nig ); + return true; + } else { + return false; + } + } + + /** + * Apply default application semantices; namely, consume one input glyph. + */ + public void applyDefault() { + super.applyDefault(); + } + + /** + * Set adjusted state, used to record effect of non-zero adjustment. + * @param adjusted true if to set adjusted state, otherwise false to + * clear adjusted state + */ + public void setAdjusted ( boolean adjusted ) { + this.adjusted = adjusted; + } + + /** + * Get adjusted state. + * @return adjusted true if some non-zero adjustment occurred and + * was recorded by {@link #setAdjusted}; otherwise, false. + */ + public boolean getAdjusted() { + return adjusted; + } + +} diff --git a/src/java/org/apache/fop/complexscripts/fonts/GlyphPositioningSubtable.java b/src/java/org/apache/fop/complexscripts/fonts/GlyphPositioningSubtable.java new file mode 100644 index 000000000..4325a3547 --- /dev/null +++ b/src/java/org/apache/fop/complexscripts/fonts/GlyphPositioningSubtable.java @@ -0,0 +1,129 @@ +/* + * 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.complexscripts.fonts; + +import java.util.List; + +import org.apache.fop.complexscripts.util.GlyphSequence; +import org.apache.fop.complexscripts.util.ScriptContextTester; + +// CSOFF: LineLengthCheck +// CSOFF: NoWhitespaceAfterCheck +// CSOFF: ParameterNumberCheck + +/** + * The GlyphPositioningSubtable implements an abstract base of a glyph subtable, + * providing a default implementation of the GlyphPositioning interface. + * @author Glenn Adams + */ +public abstract class GlyphPositioningSubtable extends GlyphSubtable implements GlyphPositioning { + + /** + * Instantiate a GlyphPositioningSubtable. + * @param id subtable identifier + * @param sequence subtable sequence + * @param flags subtable flags + * @param format subtable format + * @param coverage subtable coverage table + */ + protected GlyphPositioningSubtable ( String id, int sequence, int flags, int format, GlyphCoverageTable coverage ) { + super ( id, sequence, flags, format, coverage ); + } + + /** {@inheritDoc} */ + public int getTableType() { + return GlyphTable.GLYPH_TABLE_TYPE_POSITIONING; + } + + /** {@inheritDoc} */ + public String getTypeName() { + return GlyphPositioningTable.getLookupTypeName ( getType() ); + } + + /** {@inheritDoc} */ + public boolean isCompatible ( GlyphSubtable subtable ) { + return subtable instanceof GlyphPositioningSubtable; + } + + /** {@inheritDoc} */ + public boolean usesReverseScan() { + return false; + } + + /** {@inheritDoc} */ + public boolean position ( GlyphPositioningState ps ) { + return false; + } + + /** + * Apply positioning using specified state and subtable array. For each position in input sequence, + * apply subtables in order until some subtable applies or none remain. If no subtable applied or no + * input was consumed for a given position, then apply default action (no adjustments and advance). + * If sequenceIndex is non-negative, then apply subtables only when current position + * matches sequenceIndex in relation to the starting position. Furthermore, upon + * successful application at sequenceIndex, then discontinue processing the remaining + * @param ps positioning state + * @param sta array of subtables to apply + * @param sequenceIndex if non negative, then apply subtables only at specified sequence index + * @return true if a non-zero adjustment occurred + */ + public static final boolean position ( GlyphPositioningState ps, GlyphPositioningSubtable[] sta, int sequenceIndex ) { + int sequenceStart = ps.getPosition(); + boolean appliedOneShot = false; + while ( ps.hasNext() ) { + boolean applied = false; + if ( ! appliedOneShot && ps.maybeApplicable() ) { + for ( int i = 0, n = sta.length; ! applied && ( i < n ); i++ ) { + if ( sequenceIndex < 0 ) { + applied = ps.apply ( sta [ i ] ); + } else if ( ps.getPosition() == ( sequenceStart + sequenceIndex ) ) { + applied = ps.apply ( sta [ i ] ); + if ( applied ) { + appliedOneShot = true; + } + } + } + } + if ( ! applied || ! ps.didConsume() ) { + ps.applyDefault(); + } + ps.next(); + } + return ps.getAdjusted(); + } + + /** + * Apply positioning. + * @param gs input glyph sequence + * @param script tag + * @param language tag + * @param feature tag + * @param fontSize the font size + * @param sta subtable array + * @param widths array + * @param adjustments array (receives output adjustments) + * @param sct script context tester + * @return true if a non-zero adjustment occurred + */ + public static final boolean position ( GlyphSequence gs, String script, String language, String feature, int fontSize, GlyphPositioningSubtable[] sta, int[] widths, int[][] adjustments, ScriptContextTester sct ) { + return position ( new GlyphPositioningState ( gs, script, language, feature, fontSize, widths, adjustments, sct ), sta, -1 ); + } + +} diff --git a/src/java/org/apache/fop/complexscripts/fonts/GlyphPositioningTable.java b/src/java/org/apache/fop/complexscripts/fonts/GlyphPositioningTable.java new file mode 100644 index 000000000..f8ac4e504 --- /dev/null +++ b/src/java/org/apache/fop/complexscripts/fonts/GlyphPositioningTable.java @@ -0,0 +1,2264 @@ +/* + * 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.complexscripts.fonts; + +import java.util.Arrays; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.apache.fop.complexscripts.scripts.ScriptProcessor; +import org.apache.fop.complexscripts.util.GlyphSequence; +import org.apache.fop.complexscripts.util.GlyphTester; + +// CSOFF: LineLengthCheck +// CSOFF: InnerAssignmentCheck +// CSOFF: NoWhitespaceAfterCheck +// CSOFF: ParameterNumberCheck + +/** + * The GlyphPositioningTable class is a glyph table that implements + * GlyphPositioning functionality. + * @author Glenn Adams + */ +public class GlyphPositioningTable extends GlyphTable { + + /** logging instance */ + private static final Log log = LogFactory.getLog(GlyphPositioningTable.class); // CSOK: ConstantNameCheck + + /** single positioning subtable type */ + public static final int GPOS_LOOKUP_TYPE_SINGLE = 1; + /** multiple positioning subtable type */ + public static final int GPOS_LOOKUP_TYPE_PAIR = 2; + /** cursive positioning subtable type */ + public static final int GPOS_LOOKUP_TYPE_CURSIVE = 3; + /** mark to base positioning subtable type */ + public static final int GPOS_LOOKUP_TYPE_MARK_TO_BASE = 4; + /** mark to ligature positioning subtable type */ + public static final int GPOS_LOOKUP_TYPE_MARK_TO_LIGATURE = 5; + /** mark to mark positioning subtable type */ + public static final int GPOS_LOOKUP_TYPE_MARK_TO_MARK = 6; + /** contextual positioning subtable type */ + public static final int GPOS_LOOKUP_TYPE_CONTEXTUAL = 7; + /** chained contextual positioning subtable type */ + public static final int GPOS_LOOKUP_TYPE_CHAINED_CONTEXTUAL = 8; + /** extension positioning subtable type */ + public static final int GPOS_LOOKUP_TYPE_EXTENSION_POSITIONING = 9; + + /** + * Instantiate a GlyphPositioningTable object using the specified lookups + * and subtables. + * @param gdef glyph definition table that applies + * @param lookups a map of lookup specifications to subtable identifier strings + * @param subtables a list of identified subtables + */ + public GlyphPositioningTable ( GlyphDefinitionTable gdef, Map lookups, List subtables ) { + super ( gdef, lookups ); + if ( ( subtables == null ) || ( subtables.size() == 0 ) ) { + throw new AdvancedTypographicTableFormatException ( "subtables must be non-empty" ); + } else { + for ( Iterator it = subtables.iterator(); it.hasNext();) { + Object o = it.next(); + if ( o instanceof GlyphPositioningSubtable ) { + addSubtable ( (GlyphSubtable) o ); + } else { + throw new AdvancedTypographicTableFormatException ( "subtable must be a glyph positioning subtable" ); + } + } + freezeSubtables(); + } + } + + /** + * Map a lookup type name to its constant (integer) value. + * @param name lookup type name + * @return lookup type + */ + public static int getLookupTypeFromName ( String name ) { + int t; + String s = name.toLowerCase(); + if ( "single".equals ( s ) ) { + t = GPOS_LOOKUP_TYPE_SINGLE; + } else if ( "pair".equals ( s ) ) { + t = GPOS_LOOKUP_TYPE_PAIR; + } else if ( "cursive".equals ( s ) ) { + t = GPOS_LOOKUP_TYPE_CURSIVE; + } else if ( "marktobase".equals ( s ) ) { + t = GPOS_LOOKUP_TYPE_MARK_TO_BASE; + } else if ( "marktoligature".equals ( s ) ) { + t = GPOS_LOOKUP_TYPE_MARK_TO_LIGATURE; + } else if ( "marktomark".equals ( s ) ) { + t = GPOS_LOOKUP_TYPE_MARK_TO_MARK; + } else if ( "contextual".equals ( s ) ) { + t = GPOS_LOOKUP_TYPE_CONTEXTUAL; + } else if ( "chainedcontextual".equals ( s ) ) { + t = GPOS_LOOKUP_TYPE_CHAINED_CONTEXTUAL; + } else if ( "extensionpositioning".equals ( s ) ) { + t = GPOS_LOOKUP_TYPE_EXTENSION_POSITIONING; + } else { + t = -1; + } + return t; + } + + /** + * Map a lookup type constant (integer) value to its name. + * @param type lookup type + * @return lookup type name + */ + public static String getLookupTypeName ( int type ) { + String tn; + switch ( type ) { + case GPOS_LOOKUP_TYPE_SINGLE: + tn = "single"; + break; + case GPOS_LOOKUP_TYPE_PAIR: + tn = "pair"; + break; + case GPOS_LOOKUP_TYPE_CURSIVE: + tn = "cursive"; + break; + case GPOS_LOOKUP_TYPE_MARK_TO_BASE: + tn = "marktobase"; + break; + case GPOS_LOOKUP_TYPE_MARK_TO_LIGATURE: + tn = "marktoligature"; + break; + case GPOS_LOOKUP_TYPE_MARK_TO_MARK: + tn = "marktomark"; + break; + case GPOS_LOOKUP_TYPE_CONTEXTUAL: + tn = "contextual"; + break; + case GPOS_LOOKUP_TYPE_CHAINED_CONTEXTUAL: + tn = "chainedcontextual"; + break; + case GPOS_LOOKUP_TYPE_EXTENSION_POSITIONING: + tn = "extensionpositioning"; + break; + default: + tn = "unknown"; + break; + } + return tn; + } + + /** + * Create a positioning subtable according to the specified arguments. + * @param type subtable type + * @param id subtable identifier + * @param sequence subtable sequence + * @param flags subtable flags + * @param format subtable format + * @param coverage subtable coverage table + * @param entries subtable entries + * @return a glyph subtable instance + */ + public static GlyphSubtable createSubtable ( int type, String id, int sequence, int flags, int format, GlyphCoverageTable coverage, List entries ) { + GlyphSubtable st = null; + switch ( type ) { + case GPOS_LOOKUP_TYPE_SINGLE: + st = SingleSubtable.create ( id, sequence, flags, format, coverage, entries ); + break; + case GPOS_LOOKUP_TYPE_PAIR: + st = PairSubtable.create ( id, sequence, flags, format, coverage, entries ); + break; + case GPOS_LOOKUP_TYPE_CURSIVE: + st = CursiveSubtable.create ( id, sequence, flags, format, coverage, entries ); + break; + case GPOS_LOOKUP_TYPE_MARK_TO_BASE: + st = MarkToBaseSubtable.create ( id, sequence, flags, format, coverage, entries ); + break; + case GPOS_LOOKUP_TYPE_MARK_TO_LIGATURE: + st = MarkToLigatureSubtable.create ( id, sequence, flags, format, coverage, entries ); + break; + case GPOS_LOOKUP_TYPE_MARK_TO_MARK: + st = MarkToMarkSubtable.create ( id, sequence, flags, format, coverage, entries ); + break; + case GPOS_LOOKUP_TYPE_CONTEXTUAL: + st = ContextualSubtable.create ( id, sequence, flags, format, coverage, entries ); + break; + case GPOS_LOOKUP_TYPE_CHAINED_CONTEXTUAL: + st = ChainedContextualSubtable.create ( id, sequence, flags, format, coverage, entries ); + break; + default: + break; + } + return st; + } + + /** + * Create a positioning subtable according to the specified arguments. + * @param type subtable type + * @param id subtable identifier + * @param sequence subtable sequence + * @param flags subtable flags + * @param format subtable format + * @param coverage list of coverage table entries + * @param entries subtable entries + * @return a glyph subtable instance + */ + public static GlyphSubtable createSubtable ( int type, String id, int sequence, int flags, int format, List coverage, List entries ) { + return createSubtable ( type, id, sequence, flags, format, GlyphCoverageTable.createCoverageTable ( coverage ), entries ); + } + + /** + * Perform positioning processing using all matching lookups. + * @param gs an input glyph sequence + * @param script a script identifier + * @param language a language identifier + * @param fontSize size in device units + * @param widths array of default advancements for each glyph + * @param adjustments accumulated adjustments array (sequence) of 4-tuples of placement [PX,PY] and advance [AX,AY] adjustments, in that order, + * with one 4-tuple for each element of glyph sequence + * @return true if some adjustment is not zero; otherwise, false + */ + public boolean position ( GlyphSequence gs, String script, String language, int fontSize, int[] widths, int[][] adjustments ) { + Map/*>*/ lookups = matchLookups ( script, language, "*" ); + if ( ( lookups != null ) && ( lookups.size() > 0 ) ) { + ScriptProcessor sp = ScriptProcessor.getInstance ( script ); + return sp.position ( this, gs, script, language, fontSize, lookups, widths, adjustments ); + } else { + return false; + } + } + + private abstract static class SingleSubtable extends GlyphPositioningSubtable { + SingleSubtable ( String id, int sequence, int flags, int format, GlyphCoverageTable coverage, List entries ) { + super ( id, sequence, flags, format, coverage ); + } + /** {@inheritDoc} */ + public int getType() { + return GPOS_LOOKUP_TYPE_SINGLE; + } + /** {@inheritDoc} */ + public boolean isCompatible ( GlyphSubtable subtable ) { + return subtable instanceof SingleSubtable; + } + /** {@inheritDoc} */ + public boolean position ( GlyphPositioningState ps ) { + int gi = ps.getGlyph(), ci; + if ( ( ci = getCoverageIndex ( gi ) ) < 0 ) { + return false; + } else { + Value v = getValue ( ci, gi ); + if ( v != null ) { + if ( ps.adjust(v) ) { + ps.setAdjusted ( true ); + } + ps.consume(1); + } + return true; + } + } + /** + * Obtain positioning value for coverage index. + * @param ci coverage index + * @param gi input glyph index + * @return positioning value or null if none applies + */ + public abstract Value getValue ( int ci, int gi ); + static GlyphPositioningSubtable create ( String id, int sequence, int flags, int format, GlyphCoverageTable coverage, List entries ) { + if ( format == 1 ) { + return new SingleSubtableFormat1 ( id, sequence, flags, format, coverage, entries ); + } else if ( format == 2 ) { + return new SingleSubtableFormat2 ( id, sequence, flags, format, coverage, entries ); + } else { + throw new UnsupportedOperationException(); + } + } + } + + private static class SingleSubtableFormat1 extends SingleSubtable { + private Value value; + private int ciMax; + SingleSubtableFormat1 ( String id, int sequence, int flags, int format, GlyphCoverageTable coverage, List entries ) { + super ( id, sequence, flags, format, coverage, entries ); + populate ( entries ); + } + /** {@inheritDoc} */ + public List getEntries() { + if ( value != null ) { + List entries = new ArrayList ( 1 ); + entries.add ( value ); + return entries; + } else { + return null; + } + } + /** {@inheritDoc} */ + public Value getValue ( int ci, int gi ) { + if ( ( value != null ) && ( ci <= ciMax ) ) { + return value; + } else { + return null; + } + } + private void populate ( List entries ) { + if ( ( entries == null ) || ( entries.size() != 1 ) ) { + throw new AdvancedTypographicTableFormatException ( "illegal entries, must be non-null and contain exactly one entry" ); + } else { + Value v; + Object o = entries.get(0); + if ( o instanceof Value ) { + v = (Value) o; + } else { + throw new AdvancedTypographicTableFormatException ( "illegal entries entry, must be Value, but is: " + ( ( o != null ) ? o.getClass() : null ) ); + } + assert this.value == null; + this.value = v; + this.ciMax = getCoverageSize() - 1; + } + } + } + + private static class SingleSubtableFormat2 extends SingleSubtable { + private Value[] values; + SingleSubtableFormat2 ( String id, int sequence, int flags, int format, GlyphCoverageTable coverage, List entries ) { + super ( id, sequence, flags, format, coverage, entries ); + populate ( entries ); + } + /** {@inheritDoc} */ + public List getEntries() { + if ( values != null ) { + List entries = new ArrayList ( values.length ); + for ( int i = 0, n = values.length; i < n; i++ ) { + entries.add ( values[i] ); + } + return entries; + } else { + return null; + } + } + /** {@inheritDoc} */ + public Value getValue ( int ci, int gi ) { + if ( ( values != null ) && ( ci < values.length ) ) { + return values [ ci ]; + } else { + return null; + } + } + private void populate ( List entries ) { + if ( entries == null ) { + throw new AdvancedTypographicTableFormatException ( "illegal entries, must be non-null" ); + } else if ( entries.size() != 1 ) { + throw new AdvancedTypographicTableFormatException ( "illegal entries, " + entries.size() + " entries present, but requires 1 entry" ); + } else { + Object o; + if ( ( ( o = entries.get(0) ) == null ) || ! ( o instanceof Value[] ) ) { + throw new AdvancedTypographicTableFormatException ( "illegal entries, single entry must be a Value[], but is: " + ( ( o != null ) ? o.getClass() : null ) ); + } else { + Value[] va = (Value[]) o; + if ( va.length != getCoverageSize() ) { + throw new AdvancedTypographicTableFormatException ( "illegal values array, " + entries.size() + " values present, but requires " + getCoverageSize() + " values" ); + } else { + assert this.values == null; + this.values = va; + } + } + } + } + } + + private abstract static class PairSubtable extends GlyphPositioningSubtable { + PairSubtable ( String id, int sequence, int flags, int format, GlyphCoverageTable coverage, List entries ) { + super ( id, sequence, flags, format, coverage ); + } + /** {@inheritDoc} */ + public int getType() { + return GPOS_LOOKUP_TYPE_PAIR; + } + /** {@inheritDoc} */ + public boolean isCompatible ( GlyphSubtable subtable ) { + return subtable instanceof PairSubtable; + } + /** {@inheritDoc} */ + public boolean position ( GlyphPositioningState ps ) { + boolean applied = false; + int gi = ps.getGlyph(0), ci; + if ( ( ci = getCoverageIndex ( gi ) ) >= 0 ) { + int[] counts = ps.getGlyphsAvailable ( 0 ); + int nga = counts[0]; + if ( nga > 1 ) { + int[] iga = ps.getGlyphs ( 0, 2, null, counts ); + if ( ( iga != null ) && ( iga.length == 2 ) ) { + PairValues pv = getPairValues ( ci, iga[0], iga[1] ); + if ( pv != null ) { + Value v1 = pv.getValue1(); + if ( v1 != null ) { + if ( ps.adjust(v1, 0) ) { + ps.setAdjusted ( true ); + } + } + Value v2 = pv.getValue2(); + if ( v2 != null ) { + if ( ps.adjust(v2, 1) ) { + ps.setAdjusted ( true ); + } + } + ps.consume ( counts[0] + counts[1] ); + applied = true; + } + } + } + } + return applied; + } + /** + * Obtain associated pair values. + * @param ci coverage index + * @param gi1 first input glyph index + * @param gi2 second input glyph index + * @return pair values or null if none applies + */ + public abstract PairValues getPairValues ( int ci, int gi1, int gi2 ); + static GlyphPositioningSubtable create ( String id, int sequence, int flags, int format, GlyphCoverageTable coverage, List entries ) { + if ( format == 1 ) { + return new PairSubtableFormat1 ( id, sequence, flags, format, coverage, entries ); + } else if ( format == 2 ) { + return new PairSubtableFormat2 ( id, sequence, flags, format, coverage, entries ); + } else { + throw new UnsupportedOperationException(); + } + } + } + + private static class PairSubtableFormat1 extends PairSubtable { + private PairValues[][] pvm; // pair values matrix + PairSubtableFormat1 ( String id, int sequence, int flags, int format, GlyphCoverageTable coverage, List entries ) { + super ( id, sequence, flags, format, coverage, entries ); + populate ( entries ); + } + /** {@inheritDoc} */ + public List getEntries() { + if ( pvm != null ) { + List entries = new ArrayList ( 1 ); + entries.add ( pvm ); + return entries; + } else { + return null; + } + } + /** {@inheritDoc} */ + public PairValues getPairValues ( int ci, int gi1, int gi2 ) { + if ( ( pvm != null ) && ( ci < pvm.length ) ) { + PairValues[] pvt = pvm [ ci ]; + for ( int i = 0, n = pvt.length; i < n; i++ ) { + PairValues pv = pvt [ i ]; + if ( pv != null ) { + int g = pv.getGlyph(); + if ( g < gi2 ) { + continue; + } else if ( g == gi2 ) { + return pv; + } else { + break; + } + } + } + } + return null; + } + private void populate ( List entries ) { + if ( entries == null ) { + throw new AdvancedTypographicTableFormatException ( "illegal entries, must be non-null" ); + } else if ( entries.size() != 1 ) { + throw new AdvancedTypographicTableFormatException ( "illegal entries, " + entries.size() + " entries present, but requires 1 entry" ); + } else { + Object o; + if ( ( ( o = entries.get(0) ) == null ) || ! ( o instanceof PairValues[][] ) ) { + throw new AdvancedTypographicTableFormatException ( "illegal entries, first (and only) entry must be a PairValues[][], but is: " + ( ( o != null ) ? o.getClass() : null ) ); + } else { + pvm = (PairValues[][]) o; + } + } + } + } + + private static class PairSubtableFormat2 extends PairSubtable { + private GlyphClassTable cdt1; // class def table 1 + private GlyphClassTable cdt2; // class def table 2 + private int nc1; // class 1 count + private int nc2; // class 2 count + private PairValues[][] pvm; // pair values matrix + PairSubtableFormat2 ( String id, int sequence, int flags, int format, GlyphCoverageTable coverage, List entries ) { + super ( id, sequence, flags, format, coverage, entries ); + populate ( entries ); + } + /** {@inheritDoc} */ + public List getEntries() { + if ( pvm != null ) { + List entries = new ArrayList ( 5 ); + entries.add ( cdt1 ); + entries.add ( cdt2 ); + entries.add ( Integer.valueOf ( nc1 ) ); + entries.add ( Integer.valueOf ( nc2 ) ); + entries.add ( pvm ); + return entries; + } else { + return null; + } + } + /** {@inheritDoc} */ + public PairValues getPairValues ( int ci, int gi1, int gi2 ) { + if ( pvm != null ) { + int c1 = cdt1.getClassIndex ( gi1, 0 ); + if ( ( c1 >= 0 ) && ( c1 < nc1 ) && ( c1 < pvm.length ) ) { + PairValues[] pvt = pvm [ c1 ]; + if ( pvt != null ) { + int c2 = cdt2.getClassIndex ( gi2, 0 ); + if ( ( c2 >= 0 ) && ( c2 < nc2 ) && ( c2 < pvt.length ) ) { + return pvt [ c2 ]; + } + } + } + } + return null; + } + private void populate ( List entries ) { + if ( entries == null ) { + throw new AdvancedTypographicTableFormatException ( "illegal entries, must be non-null" ); + } else if ( entries.size() != 5 ) { + throw new AdvancedTypographicTableFormatException ( "illegal entries, " + entries.size() + " entries present, but requires 5 entries" ); + } else { + Object o; + if ( ( ( o = entries.get(0) ) == null ) || ! ( o instanceof GlyphClassTable ) ) { + throw new AdvancedTypographicTableFormatException ( "illegal entries, first entry must be an GlyphClassTable, but is: " + ( ( o != null ) ? o.getClass() : null ) ); + } else { + cdt1 = (GlyphClassTable) o; + } + if ( ( ( o = entries.get(1) ) == null ) || ! ( o instanceof GlyphClassTable ) ) { + throw new AdvancedTypographicTableFormatException ( "illegal entries, second entry must be an GlyphClassTable, but is: " + ( ( o != null ) ? o.getClass() : null ) ); + } else { + cdt2 = (GlyphClassTable) o; + } + if ( ( ( o = entries.get(2) ) == null ) || ! ( o instanceof Integer ) ) { + throw new AdvancedTypographicTableFormatException ( "illegal entries, third entry must be an Integer, but is: " + ( ( o != null ) ? o.getClass() : null ) ); + } else { + nc1 = ((Integer)(o)).intValue(); + } + if ( ( ( o = entries.get(3) ) == null ) || ! ( o instanceof Integer ) ) { + throw new AdvancedTypographicTableFormatException ( "illegal entries, fourth entry must be an Integer, but is: " + ( ( o != null ) ? o.getClass() : null ) ); + } else { + nc2 = ((Integer)(o)).intValue(); + } + if ( ( ( o = entries.get(4) ) == null ) || ! ( o instanceof PairValues[][] ) ) { + throw new AdvancedTypographicTableFormatException ( "illegal entries, fifth entry must be a PairValues[][], but is: " + ( ( o != null ) ? o.getClass() : null ) ); + } else { + pvm = (PairValues[][]) o; + } + } + } + } + + private abstract static class CursiveSubtable extends GlyphPositioningSubtable { + CursiveSubtable ( String id, int sequence, int flags, int format, GlyphCoverageTable coverage, List entries ) { + super ( id, sequence, flags, format, coverage ); + } + /** {@inheritDoc} */ + public int getType() { + return GPOS_LOOKUP_TYPE_CURSIVE; + } + /** {@inheritDoc} */ + public boolean isCompatible ( GlyphSubtable subtable ) { + return subtable instanceof CursiveSubtable; + } + /** {@inheritDoc} */ + public boolean position ( GlyphPositioningState ps ) { + boolean applied = false; + int gi = ps.getGlyph(0), ci; + if ( ( ci = getCoverageIndex ( gi ) ) >= 0 ) { + int[] counts = ps.getGlyphsAvailable ( 0 ); + int nga = counts[0]; + if ( nga > 1 ) { + int[] iga = ps.getGlyphs ( 0, 2, null, counts ); + if ( ( iga != null ) && ( iga.length == 2 ) ) { + // int gi1 = gi; + int ci1 = ci; + int gi2 = iga [ 1 ]; + int ci2 = getCoverageIndex ( gi2 ); + Anchor[] aa = getExitEntryAnchors ( ci1, ci2 ); + if ( aa != null ) { + Anchor exa = aa [ 0 ]; + Anchor ena = aa [ 1 ]; + // int exw = ps.getWidth ( gi1 ); + int enw = ps.getWidth ( gi2 ); + if ( ( exa != null ) && ( ena != null ) ) { + Value v = ena.getAlignmentAdjustment ( exa ); + v.adjust ( - enw, 0, 0, 0 ); + if ( ps.adjust ( v ) ) { + ps.setAdjusted ( true ); + } + } + // consume only first glyph of exit/entry glyph pair + ps.consume ( 1 ); + applied = true; + } + } + } + } + return applied; + } + /** + * Obtain exit anchor for first glyph with coverage index ci1 and entry anchor for second + * glyph with coverage index ci2. + * @param ci1 coverage index of first glyph (may be negative) + * @param ci2 coverage index of second glyph (may be negative) + * @return array of two anchors or null if either coverage index is negative or corresponding anchor is + * missing, where the first entry is the exit anchor of the first glyph and the second entry is the + * entry anchor of the second glyph + */ + public abstract Anchor[] getExitEntryAnchors ( int ci1, int ci2 ); + static GlyphPositioningSubtable create ( String id, int sequence, int flags, int format, GlyphCoverageTable coverage, List entries ) { + if ( format == 1 ) { + return new CursiveSubtableFormat1 ( id, sequence, flags, format, coverage, entries ); + } else { + throw new UnsupportedOperationException(); + } + } + } + + private static class CursiveSubtableFormat1 extends CursiveSubtable { + private Anchor[] aa; // anchor array, where even entries are entry anchors, and odd entries are exit anchors + CursiveSubtableFormat1 ( String id, int sequence, int flags, int format, GlyphCoverageTable coverage, List entries ) { + super ( id, sequence, flags, format, coverage, entries ); + populate ( entries ); + } + /** {@inheritDoc} */ + public List getEntries() { + if ( aa != null ) { + List entries = new ArrayList ( 1 ); + entries.add ( aa ); + return entries; + } else { + return null; + } + } + /** {@inheritDoc} */ + public Anchor[] getExitEntryAnchors ( int ci1, int ci2 ) { + if ( ( ci1 >= 0 ) && ( ci2 >= 0 ) ) { + int ai1 = ( ci1 * 2 ) + 1; // ci1 denotes glyph with exit anchor + int ai2 = ( ci2 * 2 ) + 0; // ci2 denotes glyph with entry anchor + if ( ( aa != null ) && ( ai1 < aa.length ) && ( ai2 < aa.length ) ) { + Anchor exa = aa [ ai1 ]; + Anchor ena = aa [ ai2 ]; + if ( ( exa != null ) && ( ena != null ) ) { + return new Anchor[] { exa, ena }; + } + } + } + return null; + } + private void populate ( List entries ) { + if ( entries == null ) { + throw new AdvancedTypographicTableFormatException ( "illegal entries, must be non-null" ); + } else if ( entries.size() != 1 ) { + throw new AdvancedTypographicTableFormatException ( "illegal entries, " + entries.size() + " entries present, but requires 1 entry" ); + } else { + Object o; + if ( ( ( o = entries.get(0) ) == null ) || ! ( o instanceof Anchor[] ) ) { + throw new AdvancedTypographicTableFormatException ( "illegal entries, first (and only) entry must be a Anchor[], but is: " + ( ( o != null ) ? o.getClass() : null ) ); + } else if ( ( ( (Anchor[]) o ) . length % 2 ) != 0 ) { + throw new AdvancedTypographicTableFormatException ( "illegal entries, Anchor[] array must have an even number of entries, but has: " + ( (Anchor[]) o ) . length ); + } else { + aa = (Anchor[]) o; + } + } + } + } + + private abstract static class MarkToBaseSubtable extends GlyphPositioningSubtable { + MarkToBaseSubtable ( String id, int sequence, int flags, int format, GlyphCoverageTable coverage, List entries ) { + super ( id, sequence, flags, format, coverage ); + } + /** {@inheritDoc} */ + public int getType() { + return GPOS_LOOKUP_TYPE_MARK_TO_BASE; + } + /** {@inheritDoc} */ + public boolean isCompatible ( GlyphSubtable subtable ) { + return subtable instanceof MarkToBaseSubtable; + } + /** {@inheritDoc} */ + public boolean position ( GlyphPositioningState ps ) { + boolean applied = false; + int giMark = ps.getGlyph(), ciMark; + if ( ( ciMark = getCoverageIndex ( giMark ) ) >= 0 ) { + MarkAnchor ma = getMarkAnchor ( ciMark, giMark ); + if ( ma != null ) { + for ( int i = 0, n = ps.getPosition(); i < n; i++ ) { + int gi = ps.getGlyph ( - ( i + 1 ) ); + if ( ps.isMark ( gi ) ) { + continue; + } else { + Anchor a = getBaseAnchor ( gi, ma.getMarkClass() ); + if ( a != null ) { + Value v = a.getAlignmentAdjustment ( ma ); + // start experimental fix for END OF AYAH in Lateef/Scheherazade + int[] aa = ps.getAdjustment(); + if ( aa[2] == 0 ) { + v.adjust ( 0, 0, - ps.getWidth ( giMark ), 0 ); + } + // end experimental fix for END OF AYAH in Lateef/Scheherazade + if ( ps.adjust ( v ) ) { + ps.setAdjusted ( true ); + } + } + ps.consume(1); + applied = true; + break; + } + } + } + } + return applied; + } + /** + * Obtain mark anchor associated with mark coverage index. + * @param ciMark coverage index + * @param giMark input glyph index of mark glyph + * @return mark anchor or null if none applies + */ + public abstract MarkAnchor getMarkAnchor ( int ciMark, int giMark ); + /** + * Obtain anchor associated with base glyph index and mark class. + * @param giBase input glyph index of base glyph + * @param markClass class number of mark glyph + * @return anchor or null if none applies + */ + public abstract Anchor getBaseAnchor ( int giBase, int markClass ); + static GlyphPositioningSubtable create ( String id, int sequence, int flags, int format, GlyphCoverageTable coverage, List entries ) { + if ( format == 1 ) { + return new MarkToBaseSubtableFormat1 ( id, sequence, flags, format, coverage, entries ); + } else { + throw new UnsupportedOperationException(); + } + } + } + + private static class MarkToBaseSubtableFormat1 extends MarkToBaseSubtable { + private GlyphCoverageTable bct; // base coverage table + private int nmc; // mark class count + private MarkAnchor[] maa; // mark anchor array, ordered by mark coverage index + private Anchor[][] bam; // base anchor matrix, ordered by base coverage index, then by mark class + MarkToBaseSubtableFormat1 ( String id, int sequence, int flags, int format, GlyphCoverageTable coverage, List entries ) { + super ( id, sequence, flags, format, coverage, entries ); + populate ( entries ); + } + /** {@inheritDoc} */ + public List getEntries() { + if ( ( bct != null ) && ( maa != null ) && ( nmc > 0 ) && ( bam != null ) ) { + List entries = new ArrayList ( 4 ); + entries.add ( bct ); + entries.add ( Integer.valueOf ( nmc ) ); + entries.add ( maa ); + entries.add ( bam ); + return entries; + } else { + return null; + } + } + /** {@inheritDoc} */ + public MarkAnchor getMarkAnchor ( int ciMark, int giMark ) { + if ( ( maa != null ) && ( ciMark < maa.length ) ) { + return maa [ ciMark ]; + } else { + return null; + } + } + /** {@inheritDoc} */ + public Anchor getBaseAnchor ( int giBase, int markClass ) { + int ciBase; + if ( ( bct != null ) && ( ( ciBase = bct.getCoverageIndex ( giBase ) ) >= 0 ) ) { + if ( ( bam != null ) && ( ciBase < bam.length ) ) { + Anchor[] ba = bam [ ciBase ]; + if ( ( ba != null ) && ( markClass < ba.length ) ) { + return ba [ markClass ]; + } + } + } + return null; + } + private void populate ( List entries ) { + if ( entries == null ) { + throw new AdvancedTypographicTableFormatException ( "illegal entries, must be non-null" ); + } else if ( entries.size() != 4 ) { + throw new AdvancedTypographicTableFormatException ( "illegal entries, " + entries.size() + " entries present, but requires 4 entries" ); + } else { + Object o; + if ( ( ( o = entries.get(0) ) == null ) || ! ( o instanceof GlyphCoverageTable ) ) { + throw new AdvancedTypographicTableFormatException ( "illegal entries, first entry must be an GlyphCoverageTable, but is: " + ( ( o != null ) ? o.getClass() : null ) ); + } else { + bct = (GlyphCoverageTable) o; + } + if ( ( ( o = entries.get(1) ) == null ) || ! ( o instanceof Integer ) ) { + throw new AdvancedTypographicTableFormatException ( "illegal entries, second entry must be an Integer, but is: " + ( ( o != null ) ? o.getClass() : null ) ); + } else { + nmc = ((Integer)(o)).intValue(); + } + if ( ( ( o = entries.get(2) ) == null ) || ! ( o instanceof MarkAnchor[] ) ) { + throw new AdvancedTypographicTableFormatException ( "illegal entries, third entry must be a MarkAnchor[], but is: " + ( ( o != null ) ? o.getClass() : null ) ); + } else { + maa = (MarkAnchor[]) o; + } + if ( ( ( o = entries.get(3) ) == null ) || ! ( o instanceof Anchor[][] ) ) { + throw new AdvancedTypographicTableFormatException ( "illegal entries, fourth entry must be a Anchor[][], but is: " + ( ( o != null ) ? o.getClass() : null ) ); + } else { + bam = (Anchor[][]) o; + } + } + } + } + + private abstract static class MarkToLigatureSubtable extends GlyphPositioningSubtable { + MarkToLigatureSubtable ( String id, int sequence, int flags, int format, GlyphCoverageTable coverage, List entries ) { + super ( id, sequence, flags, format, coverage ); + } + /** {@inheritDoc} */ + public int getType() { + return GPOS_LOOKUP_TYPE_MARK_TO_LIGATURE; + } + /** {@inheritDoc} */ + public boolean isCompatible ( GlyphSubtable subtable ) { + return subtable instanceof MarkToLigatureSubtable; + } + /** {@inheritDoc} */ + public boolean position ( GlyphPositioningState ps ) { + boolean applied = false; + int giMark = ps.getGlyph(), ciMark; + if ( ( ciMark = getCoverageIndex ( giMark ) ) >= 0 ) { + MarkAnchor ma = getMarkAnchor ( ciMark, giMark ); + int mxc = getMaxComponentCount(); + if ( ma != null ) { + for ( int i = 0, n = ps.getPosition(); i < n; i++ ) { + int gi = ps.getGlyph ( - ( i + 1 ) ); + if ( ps.isMark ( gi ) ) { + continue; + } else { + Anchor a = getLigatureAnchor ( gi, mxc, i, ma.getMarkClass() ); + if ( a != null ) { + if ( ps.adjust ( a.getAlignmentAdjustment ( ma ) ) ) { + ps.setAdjusted ( true ); + } + } + ps.consume(1); + applied = true; + break; + } + } + } + } + return applied; + } + /** + * Obtain mark anchor associated with mark coverage index. + * @param ciMark coverage index + * @param giMark input glyph index of mark glyph + * @return mark anchor or null if none applies + */ + public abstract MarkAnchor getMarkAnchor ( int ciMark, int giMark ); + /** + * Obtain maximum component count. + * @return maximum component count (>=0) + */ + public abstract int getMaxComponentCount(); + /** + * Obtain anchor associated with ligature glyph index and mark class. + * @param giLig input glyph index of ligature glyph + * @param maxComponents maximum component count + * @param component component number (0...maxComponents-1) + * @param markClass class number of mark glyph + * @return anchor or null if none applies + */ + public abstract Anchor getLigatureAnchor ( int giLig, int maxComponents, int component, int markClass ); + static GlyphPositioningSubtable create ( String id, int sequence, int flags, int format, GlyphCoverageTable coverage, List entries ) { + if ( format == 1 ) { + return new MarkToLigatureSubtableFormat1 ( id, sequence, flags, format, coverage, entries ); + } else { + throw new UnsupportedOperationException(); + } + } + } + + private static class MarkToLigatureSubtableFormat1 extends MarkToLigatureSubtable { + private GlyphCoverageTable lct; // ligature coverage table + private int nmc; // mark class count + private int mxc; // maximum ligature component count + private MarkAnchor[] maa; // mark anchor array, ordered by mark coverage index + private Anchor[][][] lam; // ligature anchor matrix, ordered by ligature coverage index, then ligature component, then mark class + MarkToLigatureSubtableFormat1 ( String id, int sequence, int flags, int format, GlyphCoverageTable coverage, List entries ) { + super ( id, sequence, flags, format, coverage, entries ); + populate ( entries ); + } + /** {@inheritDoc} */ + public List getEntries() { + if ( lam != null ) { + List entries = new ArrayList ( 5 ); + entries.add ( lct ); + entries.add ( Integer.valueOf ( nmc ) ); + entries.add ( Integer.valueOf ( mxc ) ); + entries.add ( maa ); + entries.add ( lam ); + return entries; + } else { + return null; + } + } + /** {@inheritDoc} */ + public MarkAnchor getMarkAnchor ( int ciMark, int giMark ) { + if ( ( maa != null ) && ( ciMark < maa.length ) ) { + return maa [ ciMark ]; + } else { + return null; + } + } + /** {@inheritDoc} */ + public int getMaxComponentCount() { + return mxc; + } + /** {@inheritDoc} */ + public Anchor getLigatureAnchor ( int giLig, int maxComponents, int component, int markClass ) { + int ciLig; + if ( ( lct != null ) && ( ( ciLig = lct.getCoverageIndex ( giLig ) ) >= 0 ) ) { + if ( ( lam != null ) && ( ciLig < lam.length ) ) { + Anchor[][] lcm = lam [ ciLig ]; + if ( component < maxComponents ) { + Anchor[] la = lcm [ component ]; + if ( ( la != null ) && ( markClass < la.length ) ) { + return la [ markClass ]; + } + } + } + } + return null; + } + private void populate ( List entries ) { + if ( entries == null ) { + throw new AdvancedTypographicTableFormatException ( "illegal entries, must be non-null" ); + } else if ( entries.size() != 5 ) { + throw new AdvancedTypographicTableFormatException ( "illegal entries, " + entries.size() + " entries present, but requires 5 entries" ); + } else { + Object o; + if ( ( ( o = entries.get(0) ) == null ) || ! ( o instanceof GlyphCoverageTable ) ) { + throw new AdvancedTypographicTableFormatException ( "illegal entries, first entry must be an GlyphCoverageTable, but is: " + ( ( o != null ) ? o.getClass() : null ) ); + } else { + lct = (GlyphCoverageTable) o; + } + if ( ( ( o = entries.get(1) ) == null ) || ! ( o instanceof Integer ) ) { + throw new AdvancedTypographicTableFormatException ( "illegal entries, second entry must be an Integer, but is: " + ( ( o != null ) ? o.getClass() : null ) ); + } else { + nmc = ((Integer)(o)).intValue(); + } + if ( ( ( o = entries.get(2) ) == null ) || ! ( o instanceof Integer ) ) { + throw new AdvancedTypographicTableFormatException ( "illegal entries, third entry must be an Integer, but is: " + ( ( o != null ) ? o.getClass() : null ) ); + } else { + mxc = ((Integer)(o)).intValue(); + } + if ( ( ( o = entries.get(3) ) == null ) || ! ( o instanceof MarkAnchor[] ) ) { + throw new AdvancedTypographicTableFormatException ( "illegal entries, fourth entry must be a MarkAnchor[], but is: " + ( ( o != null ) ? o.getClass() : null ) ); + } else { + maa = (MarkAnchor[]) o; + } + if ( ( ( o = entries.get(4) ) == null ) || ! ( o instanceof Anchor[][][] ) ) { + throw new AdvancedTypographicTableFormatException ( "illegal entries, fifth entry must be a Anchor[][][], but is: " + ( ( o != null ) ? o.getClass() : null ) ); + } else { + lam = (Anchor[][][]) o; + } + } + } + } + + private abstract static class MarkToMarkSubtable extends GlyphPositioningSubtable { + MarkToMarkSubtable ( String id, int sequence, int flags, int format, GlyphCoverageTable coverage, List entries ) { + super ( id, sequence, flags, format, coverage ); + } + /** {@inheritDoc} */ + public int getType() { + return GPOS_LOOKUP_TYPE_MARK_TO_MARK; + } + /** {@inheritDoc} */ + public boolean isCompatible ( GlyphSubtable subtable ) { + return subtable instanceof MarkToMarkSubtable; + } + /** {@inheritDoc} */ + public boolean position ( GlyphPositioningState ps ) { + boolean applied = false; + int giMark1 = ps.getGlyph(), ciMark1; + if ( ( ciMark1 = getCoverageIndex ( giMark1 ) ) >= 0 ) { + MarkAnchor ma = getMark1Anchor ( ciMark1, giMark1 ); + if ( ma != null ) { + if ( ps.hasPrev() ) { + Anchor a = getMark2Anchor ( ps.getGlyph(-1), ma.getMarkClass() ); + if ( a != null ) { + if ( ps.adjust ( a.getAlignmentAdjustment ( ma ) ) ) { + ps.setAdjusted ( true ); + } + } + ps.consume(1); + applied = true; + } + } + } + return applied; + } + /** + * Obtain mark 1 anchor associated with mark 1 coverage index. + * @param ciMark1 mark 1 coverage index + * @param giMark1 input glyph index of mark 1 glyph + * @return mark 1 anchor or null if none applies + */ + public abstract MarkAnchor getMark1Anchor ( int ciMark1, int giMark1 ); + /** + * Obtain anchor associated with mark 2 glyph index and mark 1 class. + * @param giMark2 input glyph index of mark 2 glyph + * @param markClass class number of mark 1 glyph + * @return anchor or null if none applies + */ + public abstract Anchor getMark2Anchor ( int giBase, int markClass ); + static GlyphPositioningSubtable create ( String id, int sequence, int flags, int format, GlyphCoverageTable coverage, List entries ) { + if ( format == 1 ) { + return new MarkToMarkSubtableFormat1 ( id, sequence, flags, format, coverage, entries ); + } else { + throw new UnsupportedOperationException(); + } + } + } + + private static class MarkToMarkSubtableFormat1 extends MarkToMarkSubtable { + private GlyphCoverageTable mct2; // mark 2 coverage table + private int nmc; // mark class count + private MarkAnchor[] maa; // mark1 anchor array, ordered by mark1 coverage index + private Anchor[][] mam; // mark2 anchor matrix, ordered by mark2 coverage index, then by mark1 class + MarkToMarkSubtableFormat1 ( String id, int sequence, int flags, int format, GlyphCoverageTable coverage, List entries ) { + super ( id, sequence, flags, format, coverage, entries ); + populate ( entries ); + } + /** {@inheritDoc} */ + public List getEntries() { + if ( ( mct2 != null ) && ( maa != null ) && ( nmc > 0 ) && ( mam != null ) ) { + List entries = new ArrayList ( 4 ); + entries.add ( mct2 ); + entries.add ( Integer.valueOf ( nmc ) ); + entries.add ( maa ); + entries.add ( mam ); + return entries; + } else { + return null; + } + } + /** {@inheritDoc} */ + public MarkAnchor getMark1Anchor ( int ciMark1, int giMark1 ) { + if ( ( maa != null ) && ( ciMark1 < maa.length ) ) { + return maa [ ciMark1 ]; + } else { + return null; + } + } + /** {@inheritDoc} */ + public Anchor getMark2Anchor ( int giMark2, int markClass ) { + int ciMark2; + if ( ( mct2 != null ) && ( ( ciMark2 = mct2.getCoverageIndex ( giMark2 ) ) >= 0 ) ) { + if ( ( mam != null ) && ( ciMark2 < mam.length ) ) { + Anchor[] ma = mam [ ciMark2 ]; + if ( ( ma != null ) && ( markClass < ma.length ) ) { + return ma [ markClass ]; + } + } + } + return null; + } + private void populate ( List entries ) { + if ( entries == null ) { + throw new AdvancedTypographicTableFormatException ( "illegal entries, must be non-null" ); + } else if ( entries.size() != 4 ) { + throw new AdvancedTypographicTableFormatException ( "illegal entries, " + entries.size() + " entries present, but requires 4 entries" ); + } else { + Object o; + if ( ( ( o = entries.get(0) ) == null ) || ! ( o instanceof GlyphCoverageTable ) ) { + throw new AdvancedTypographicTableFormatException ( "illegal entries, first entry must be an GlyphCoverageTable, but is: " + ( ( o != null ) ? o.getClass() : null ) ); + } else { + mct2 = (GlyphCoverageTable) o; + } + if ( ( ( o = entries.get(1) ) == null ) || ! ( o instanceof Integer ) ) { + throw new AdvancedTypographicTableFormatException ( "illegal entries, second entry must be an Integer, but is: " + ( ( o != null ) ? o.getClass() : null ) ); + } else { + nmc = ((Integer)(o)).intValue(); + } + if ( ( ( o = entries.get(2) ) == null ) || ! ( o instanceof MarkAnchor[] ) ) { + throw new AdvancedTypographicTableFormatException ( "illegal entries, third entry must be a MarkAnchor[], but is: " + ( ( o != null ) ? o.getClass() : null ) ); + } else { + maa = (MarkAnchor[]) o; + } + if ( ( ( o = entries.get(3) ) == null ) || ! ( o instanceof Anchor[][] ) ) { + throw new AdvancedTypographicTableFormatException ( "illegal entries, fourth entry must be a Anchor[][], but is: " + ( ( o != null ) ? o.getClass() : null ) ); + } else { + mam = (Anchor[][]) o; + } + } + } + } + + private abstract static class ContextualSubtable extends GlyphPositioningSubtable { + ContextualSubtable ( String id, int sequence, int flags, int format, GlyphCoverageTable coverage, List entries ) { + super ( id, sequence, flags, format, coverage ); + } + /** {@inheritDoc} */ + public int getType() { + return GPOS_LOOKUP_TYPE_CONTEXTUAL; + } + /** {@inheritDoc} */ + public boolean isCompatible ( GlyphSubtable subtable ) { + return subtable instanceof ContextualSubtable; + } + /** {@inheritDoc} */ + public boolean position ( GlyphPositioningState ps ) { + boolean applied = false; + int gi = ps.getGlyph(), ci; + if ( ( ci = getCoverageIndex ( gi ) ) >= 0 ) { + int[] rv = new int[1]; + RuleLookup[] la = getLookups ( ci, gi, ps, rv ); + if ( la != null ) { + ps.apply ( la, rv[0] ); + applied = true; + } + } + return applied; + } + /** + * Obtain rule lookups set associated current input glyph context. + * @param ci coverage index of glyph at current position + * @param gi glyph index of glyph at current position + * @param ps glyph positioning state + * @param rv array of ints used to receive multiple return values, must be of length 1 or greater, + * where the first entry is used to return the input sequence length of the matched rule + * @return array of rule lookups or null if none applies + */ + public abstract RuleLookup[] getLookups ( int ci, int gi, GlyphPositioningState ps, int[] rv ); + static GlyphPositioningSubtable create ( String id, int sequence, int flags, int format, GlyphCoverageTable coverage, List entries ) { + if ( format == 1 ) { + return new ContextualSubtableFormat1 ( id, sequence, flags, format, coverage, entries ); + } else if ( format == 2 ) { + return new ContextualSubtableFormat2 ( id, sequence, flags, format, coverage, entries ); + } else if ( format == 3 ) { + return new ContextualSubtableFormat3 ( id, sequence, flags, format, coverage, entries ); + } else { + throw new UnsupportedOperationException(); + } + } + } + + private static class ContextualSubtableFormat1 extends ContextualSubtable { + private RuleSet[] rsa; // rule set array, ordered by glyph coverage index + ContextualSubtableFormat1 ( String id, int sequence, int flags, int format, GlyphCoverageTable coverage, List entries ) { + super ( id, sequence, flags, format, coverage, entries ); + populate ( entries ); + } + /** {@inheritDoc} */ + public List getEntries() { + if ( rsa != null ) { + List entries = new ArrayList ( 1 ); + entries.add ( rsa ); + return entries; + } else { + return null; + } + } + /** {@inheritDoc} */ + public void resolveLookupReferences ( Map/**/ lookupTables ) { + GlyphTable.resolveLookupReferences ( rsa, lookupTables ); + } + /** {@inheritDoc} */ + public RuleLookup[] getLookups ( int ci, int gi, GlyphPositioningState ps, int[] rv ) { + assert ps != null; + assert ( rv != null ) && ( rv.length > 0 ); + assert rsa != null; + if ( rsa.length > 0 ) { + RuleSet rs = rsa [ 0 ]; + if ( rs != null ) { + Rule[] ra = rs.getRules(); + for ( int i = 0, n = ra.length; i < n; i++ ) { + Rule r = ra [ i ]; + if ( ( r != null ) && ( r instanceof ChainedGlyphSequenceRule ) ) { + ChainedGlyphSequenceRule cr = (ChainedGlyphSequenceRule) r; + int[] iga = cr.getGlyphs ( gi ); + if ( matches ( ps, iga, 0, rv ) ) { + return r.getLookups(); + } + } + } + } + } + return null; + } + static boolean matches ( GlyphPositioningState ps, int[] glyphs, int offset, int[] rv ) { + if ( ( glyphs == null ) || ( glyphs.length == 0 ) ) { + return true; // match null or empty glyph sequence + } else { + boolean reverse = offset < 0; + GlyphTester ignores = ps.getIgnoreDefault(); + int[] counts = ps.getGlyphsAvailable ( offset, reverse, ignores ); + int nga = counts[0]; + int ngm = glyphs.length; + if ( nga < ngm ) { + return false; // insufficient glyphs available to match + } else { + int[] ga = ps.getGlyphs ( offset, ngm, reverse, ignores, null, counts ); + for ( int k = 0; k < ngm; k++ ) { + if ( ga [ k ] != glyphs [ k ] ) { + return false; // match fails at ga [ k ] + } + } + if ( rv != null ) { + rv[0] = counts[0] + counts[1]; + } + return true; // all glyphs match + } + } + } + private void populate ( List entries ) { + if ( entries == null ) { + throw new AdvancedTypographicTableFormatException ( "illegal entries, must be non-null" ); + } else if ( entries.size() != 1 ) { + throw new AdvancedTypographicTableFormatException ( "illegal entries, " + entries.size() + " entries present, but requires 1 entry" ); + } else { + Object o; + if ( ( ( o = entries.get(0) ) == null ) || ! ( o instanceof RuleSet[] ) ) { + throw new AdvancedTypographicTableFormatException ( "illegal entries, first entry must be an RuleSet[], but is: " + ( ( o != null ) ? o.getClass() : null ) ); + } else { + rsa = (RuleSet[]) o; + } + } + } + } + + private static class ContextualSubtableFormat2 extends ContextualSubtable { + private GlyphClassTable cdt; // class def table + private int ngc; // class set count + private RuleSet[] rsa; // rule set array, ordered by class number [0...ngc - 1] + ContextualSubtableFormat2 ( String id, int sequence, int flags, int format, GlyphCoverageTable coverage, List entries ) { + super ( id, sequence, flags, format, coverage, entries ); + populate ( entries ); + } + /** {@inheritDoc} */ + public List getEntries() { + if ( rsa != null ) { + List entries = new ArrayList ( 3 ); + entries.add ( cdt ); + entries.add ( Integer.valueOf ( ngc ) ); + entries.add ( rsa ); + return entries; + } else { + return null; + } + } + /** {@inheritDoc} */ + public void resolveLookupReferences ( Map/**/ lookupTables ) { + GlyphTable.resolveLookupReferences ( rsa, lookupTables ); + } + /** {@inheritDoc} */ + public RuleLookup[] getLookups ( int ci, int gi, GlyphPositioningState ps, int[] rv ) { + assert ps != null; + assert ( rv != null ) && ( rv.length > 0 ); + assert rsa != null; + if ( rsa.length > 0 ) { + RuleSet rs = rsa [ 0 ]; + if ( rs != null ) { + Rule[] ra = rs.getRules(); + for ( int i = 0, n = ra.length; i < n; i++ ) { + Rule r = ra [ i ]; + if ( ( r != null ) && ( r instanceof ChainedClassSequenceRule ) ) { + ChainedClassSequenceRule cr = (ChainedClassSequenceRule) r; + int[] ca = cr.getClasses ( cdt.getClassIndex ( gi, ps.getClassMatchSet ( gi ) ) ); + if ( matches ( ps, cdt, ca, 0, rv ) ) { + return r.getLookups(); + } + } + } + } + } + return null; + } + static boolean matches ( GlyphPositioningState ps, GlyphClassTable cdt, int[] classes, int offset, int[] rv ) { + if ( ( cdt == null ) || ( classes == null ) || ( classes.length == 0 ) ) { + return true; // match null class definitions, null or empty class sequence + } else { + boolean reverse = offset < 0; + GlyphTester ignores = ps.getIgnoreDefault(); + int[] counts = ps.getGlyphsAvailable ( offset, reverse, ignores ); + int nga = counts[0]; + int ngm = classes.length; + if ( nga < ngm ) { + return false; // insufficient glyphs available to match + } else { + int[] ga = ps.getGlyphs ( offset, ngm, reverse, ignores, null, counts ); + for ( int k = 0; k < ngm; k++ ) { + int gi = ga [ k ]; + int ms = ps.getClassMatchSet ( gi ); + int gc = cdt.getClassIndex ( gi, ms ); + if ( ( gc < 0 ) || ( gc >= cdt.getClassSize ( ms ) ) ) { + return false; // none or invalid class fails mat ch + } else if ( gc != classes [ k ] ) { + return false; // match fails at ga [ k ] + } + } + if ( rv != null ) { + rv[0] = counts[0] + counts[1]; + } + return true; // all glyphs match + } + } + } + private void populate ( List entries ) { + if ( entries == null ) { + throw new AdvancedTypographicTableFormatException ( "illegal entries, must be non-null" ); + } else if ( entries.size() != 3 ) { + throw new AdvancedTypographicTableFormatException ( "illegal entries, " + entries.size() + " entries present, but requires 3 entries" ); + } else { + Object o; + if ( ( ( o = entries.get(0) ) == null ) || ! ( o instanceof GlyphClassTable ) ) { + throw new AdvancedTypographicTableFormatException ( "illegal entries, first entry must be an GlyphClassTable, but is: " + ( ( o != null ) ? o.getClass() : null ) ); + } else { + cdt = (GlyphClassTable) o; + } + if ( ( ( o = entries.get(1) ) == null ) || ! ( o instanceof Integer ) ) { + throw new AdvancedTypographicTableFormatException ( "illegal entries, second entry must be an Integer, but is: " + ( ( o != null ) ? o.getClass() : null ) ); + } else { + ngc = ((Integer)(o)).intValue(); + } + if ( ( ( o = entries.get(2) ) == null ) || ! ( o instanceof RuleSet[] ) ) { + throw new AdvancedTypographicTableFormatException ( "illegal entries, third entry must be an RuleSet[], but is: " + ( ( o != null ) ? o.getClass() : null ) ); + } else { + rsa = (RuleSet[]) o; + if ( rsa.length != ngc ) { + throw new AdvancedTypographicTableFormatException ( "illegal entries, RuleSet[] length is " + rsa.length + ", but expected " + ngc + " glyph classes" ); + } + } + } + } + } + + private static class ContextualSubtableFormat3 extends ContextualSubtable { + private RuleSet[] rsa; // rule set array, containing a single rule set + ContextualSubtableFormat3 ( String id, int sequence, int flags, int format, GlyphCoverageTable coverage, List entries ) { + super ( id, sequence, flags, format, coverage, entries ); + populate ( entries ); + } + /** {@inheritDoc} */ + public List getEntries() { + if ( rsa != null ) { + List entries = new ArrayList ( 1 ); + entries.add ( rsa ); + return entries; + } else { + return null; + } + } + /** {@inheritDoc} */ + public void resolveLookupReferences ( Map/**/ lookupTables ) { + GlyphTable.resolveLookupReferences ( rsa, lookupTables ); + } + /** {@inheritDoc} */ + public RuleLookup[] getLookups ( int ci, int gi, GlyphPositioningState ps, int[] rv ) { + assert ps != null; + assert ( rv != null ) && ( rv.length > 0 ); + assert rsa != null; + if ( rsa.length > 0 ) { + RuleSet rs = rsa [ 0 ]; + if ( rs != null ) { + Rule[] ra = rs.getRules(); + for ( int i = 0, n = ra.length; i < n; i++ ) { + Rule r = ra [ i ]; + if ( ( r != null ) && ( r instanceof ChainedCoverageSequenceRule ) ) { + ChainedCoverageSequenceRule cr = (ChainedCoverageSequenceRule) r; + GlyphCoverageTable[] gca = cr.getCoverages(); + if ( matches ( ps, gca, 0, rv ) ) { + return r.getLookups(); + } + } + } + } + } + return null; + } + static boolean matches ( GlyphPositioningState ps, GlyphCoverageTable[] gca, int offset, int[] rv ) { + if ( ( gca == null ) || ( gca.length == 0 ) ) { + return true; // match null or empty coverage array + } else { + boolean reverse = offset < 0; + GlyphTester ignores = ps.getIgnoreDefault(); + int[] counts = ps.getGlyphsAvailable ( offset, reverse, ignores ); + int nga = counts[0]; + int ngm = gca.length; + if ( nga < ngm ) { + return false; // insufficient glyphs available to match + } else { + int[] ga = ps.getGlyphs ( offset, ngm, reverse, ignores, null, counts ); + for ( int k = 0; k < ngm; k++ ) { + GlyphCoverageTable ct = gca [ k ]; + if ( ct != null ) { + if ( ct.getCoverageIndex ( ga [ k ] ) < 0 ) { + return false; // match fails at ga [ k ] + } + } + } + if ( rv != null ) { + rv[0] = counts[0] + counts[1]; + } + return true; // all glyphs match + } + } + } + private void populate ( List entries ) { + if ( entries == null ) { + throw new AdvancedTypographicTableFormatException ( "illegal entries, must be non-null" ); + } else if ( entries.size() != 1 ) { + throw new AdvancedTypographicTableFormatException ( "illegal entries, " + entries.size() + " entries present, but requires 1 entry" ); + } else { + Object o; + if ( ( ( o = entries.get(0) ) == null ) || ! ( o instanceof RuleSet[] ) ) { + throw new AdvancedTypographicTableFormatException ( "illegal entries, first entry must be an RuleSet[], but is: " + ( ( o != null ) ? o.getClass() : null ) ); + } else { + rsa = (RuleSet[]) o; + } + } + } + } + + private abstract static class ChainedContextualSubtable extends GlyphPositioningSubtable { + ChainedContextualSubtable ( String id, int sequence, int flags, int format, GlyphCoverageTable coverage, List entries ) { + super ( id, sequence, flags, format, coverage ); + } + /** {@inheritDoc} */ + public int getType() { + return GPOS_LOOKUP_TYPE_CHAINED_CONTEXTUAL; + } + /** {@inheritDoc} */ + public boolean isCompatible ( GlyphSubtable subtable ) { + return subtable instanceof ChainedContextualSubtable; + } + /** {@inheritDoc} */ + public boolean position ( GlyphPositioningState ps ) { + boolean applied = false; + int gi = ps.getGlyph(), ci; + if ( ( ci = getCoverageIndex ( gi ) ) >= 0 ) { + int[] rv = new int[1]; + RuleLookup[] la = getLookups ( ci, gi, ps, rv ); + if ( la != null ) { + ps.apply ( la, rv[0] ); + applied = true; + } + } + return applied; + } + /** + * Obtain rule lookups set associated current input glyph context. + * @param ci coverage index of glyph at current position + * @param gi glyph index of glyph at current position + * @param ps glyph positioning state + * @param rv array of ints used to receive multiple return values, must be of length 1 or greater, + * where the first entry is used to return the input sequence length of the matched rule + * @return array of rule lookups or null if none applies + */ + public abstract RuleLookup[] getLookups ( int ci, int gi, GlyphPositioningState ps, int[] rv ); + static GlyphPositioningSubtable create ( String id, int sequence, int flags, int format, GlyphCoverageTable coverage, List entries ) { + if ( format == 1 ) { + return new ChainedContextualSubtableFormat1 ( id, sequence, flags, format, coverage, entries ); + } else if ( format == 2 ) { + return new ChainedContextualSubtableFormat2 ( id, sequence, flags, format, coverage, entries ); + } else if ( format == 3 ) { + return new ChainedContextualSubtableFormat3 ( id, sequence, flags, format, coverage, entries ); + } else { + throw new UnsupportedOperationException(); + } + } + } + + private static class ChainedContextualSubtableFormat1 extends ChainedContextualSubtable { + private RuleSet[] rsa; // rule set array, ordered by glyph coverage index + ChainedContextualSubtableFormat1 ( String id, int sequence, int flags, int format, GlyphCoverageTable coverage, List entries ) { + super ( id, sequence, flags, format, coverage, entries ); + populate ( entries ); + } + /** {@inheritDoc} */ + public List getEntries() { + if ( rsa != null ) { + List entries = new ArrayList ( 1 ); + entries.add ( rsa ); + return entries; + } else { + return null; + } + } + /** {@inheritDoc} */ + public void resolveLookupReferences ( Map/**/ lookupTables ) { + GlyphTable.resolveLookupReferences ( rsa, lookupTables ); + } + /** {@inheritDoc} */ + public RuleLookup[] getLookups ( int ci, int gi, GlyphPositioningState ps, int[] rv ) { + assert ps != null; + assert ( rv != null ) && ( rv.length > 0 ); + assert rsa != null; + if ( rsa.length > 0 ) { + RuleSet rs = rsa [ 0 ]; + if ( rs != null ) { + Rule[] ra = rs.getRules(); + for ( int i = 0, n = ra.length; i < n; i++ ) { + Rule r = ra [ i ]; + if ( ( r != null ) && ( r instanceof ChainedGlyphSequenceRule ) ) { + ChainedGlyphSequenceRule cr = (ChainedGlyphSequenceRule) r; + int[] iga = cr.getGlyphs ( gi ); + if ( matches ( ps, iga, 0, rv ) ) { + int[] bga = cr.getBacktrackGlyphs(); + if ( matches ( ps, bga, -1, null ) ) { + int[] lga = cr.getLookaheadGlyphs(); + if ( matches ( ps, lga, rv[0], null ) ) { + return r.getLookups(); + } + } + } + } + } + } + } + return null; + } + private boolean matches ( GlyphPositioningState ps, int[] glyphs, int offset, int[] rv ) { + return ContextualSubtableFormat1.matches ( ps, glyphs, offset, rv ); + } + private void populate ( List entries ) { + if ( entries == null ) { + throw new AdvancedTypographicTableFormatException ( "illegal entries, must be non-null" ); + } else if ( entries.size() != 1 ) { + throw new AdvancedTypographicTableFormatException ( "illegal entries, " + entries.size() + " entries present, but requires 1 entry" ); + } else { + Object o; + if ( ( ( o = entries.get(0) ) == null ) || ! ( o instanceof RuleSet[] ) ) { + throw new AdvancedTypographicTableFormatException ( "illegal entries, first entry must be an RuleSet[], but is: " + ( ( o != null ) ? o.getClass() : null ) ); + } else { + rsa = (RuleSet[]) o; + } + } + } + } + + private static class ChainedContextualSubtableFormat2 extends ChainedContextualSubtable { + private GlyphClassTable icdt; // input class def table + private GlyphClassTable bcdt; // backtrack class def table + private GlyphClassTable lcdt; // lookahead class def table + private int ngc; // class set count + private RuleSet[] rsa; // rule set array, ordered by class number [0...ngc - 1] + ChainedContextualSubtableFormat2 ( String id, int sequence, int flags, int format, GlyphCoverageTable coverage, List entries ) { + super ( id, sequence, flags, format, coverage, entries ); + populate ( entries ); + } + /** {@inheritDoc} */ + public List getEntries() { + if ( rsa != null ) { + List entries = new ArrayList ( 5 ); + entries.add ( icdt ); + entries.add ( bcdt ); + entries.add ( lcdt ); + entries.add ( Integer.valueOf ( ngc ) ); + entries.add ( rsa ); + return entries; + } else { + return null; + } + } + /** {@inheritDoc} */ + public void resolveLookupReferences ( Map/**/ lookupTables ) { + GlyphTable.resolveLookupReferences ( rsa, lookupTables ); + } + /** {@inheritDoc} */ + public RuleLookup[] getLookups ( int ci, int gi, GlyphPositioningState ps, int[] rv ) { + assert ps != null; + assert ( rv != null ) && ( rv.length > 0 ); + assert rsa != null; + if ( rsa.length > 0 ) { + RuleSet rs = rsa [ 0 ]; + if ( rs != null ) { + Rule[] ra = rs.getRules(); + for ( int i = 0, n = ra.length; i < n; i++ ) { + Rule r = ra [ i ]; + if ( ( r != null ) && ( r instanceof ChainedClassSequenceRule ) ) { + ChainedClassSequenceRule cr = (ChainedClassSequenceRule) r; + int[] ica = cr.getClasses ( icdt.getClassIndex ( gi, ps.getClassMatchSet ( gi ) ) ); + if ( matches ( ps, icdt, ica, 0, rv ) ) { + int[] bca = cr.getBacktrackClasses(); + if ( matches ( ps, bcdt, bca, -1, null ) ) { + int[] lca = cr.getLookaheadClasses(); + if ( matches ( ps, lcdt, lca, rv[0], null ) ) { + return r.getLookups(); + } + } + } + } + } + } + } + return null; + } + private boolean matches ( GlyphPositioningState ps, GlyphClassTable cdt, int[] classes, int offset, int[] rv ) { + return ContextualSubtableFormat2.matches ( ps, cdt, classes, offset, rv ); + } + private void populate ( List entries ) { + if ( entries == null ) { + throw new AdvancedTypographicTableFormatException ( "illegal entries, must be non-null" ); + } else if ( entries.size() != 5 ) { + throw new AdvancedTypographicTableFormatException ( "illegal entries, " + entries.size() + " entries present, but requires 5 entries" ); + } else { + Object o; + if ( ( ( o = entries.get(0) ) == null ) || ! ( o instanceof GlyphClassTable ) ) { + throw new AdvancedTypographicTableFormatException ( "illegal entries, first entry must be an GlyphClassTable, but is: " + ( ( o != null ) ? o.getClass() : null ) ); + } else { + icdt = (GlyphClassTable) o; + } + if ( ( ( o = entries.get(1) ) != null ) && ! ( o instanceof GlyphClassTable ) ) { + throw new AdvancedTypographicTableFormatException ( "illegal entries, second entry must be an GlyphClassTable, but is: " + o.getClass() ); + } else { + bcdt = (GlyphClassTable) o; + } + if ( ( ( o = entries.get(2) ) != null ) && ! ( o instanceof GlyphClassTable ) ) { + throw new AdvancedTypographicTableFormatException ( "illegal entries, third entry must be an GlyphClassTable, but is: " + o.getClass() ); + } else { + lcdt = (GlyphClassTable) o; + } + if ( ( ( o = entries.get(3) ) == null ) || ! ( o instanceof Integer ) ) { + throw new AdvancedTypographicTableFormatException ( "illegal entries, fourth entry must be an Integer, but is: " + ( ( o != null ) ? o.getClass() : null ) ); + } else { + ngc = ((Integer)(o)).intValue(); + } + if ( ( ( o = entries.get(4) ) == null ) || ! ( o instanceof RuleSet[] ) ) { + throw new AdvancedTypographicTableFormatException ( "illegal entries, fifth entry must be an RuleSet[], but is: " + ( ( o != null ) ? o.getClass() : null ) ); + } else { + rsa = (RuleSet[]) o; + if ( rsa.length != ngc ) { + throw new AdvancedTypographicTableFormatException ( "illegal entries, RuleSet[] length is " + rsa.length + ", but expected " + ngc + " glyph classes" ); + } + } + } + } + } + + private static class ChainedContextualSubtableFormat3 extends ChainedContextualSubtable { + private RuleSet[] rsa; // rule set array, containing a single rule set + ChainedContextualSubtableFormat3 ( String id, int sequence, int flags, int format, GlyphCoverageTable coverage, List entries ) { + super ( id, sequence, flags, format, coverage, entries ); + populate ( entries ); + } + /** {@inheritDoc} */ + public List getEntries() { + if ( rsa != null ) { + List entries = new ArrayList ( 1 ); + entries.add ( rsa ); + return entries; + } else { + return null; + } + } + /** {@inheritDoc} */ + public void resolveLookupReferences ( Map/**/ lookupTables ) { + GlyphTable.resolveLookupReferences ( rsa, lookupTables ); + } + /** {@inheritDoc} */ + public RuleLookup[] getLookups ( int ci, int gi, GlyphPositioningState ps, int[] rv ) { + assert ps != null; + assert ( rv != null ) && ( rv.length > 0 ); + assert rsa != null; + if ( rsa.length > 0 ) { + RuleSet rs = rsa [ 0 ]; + if ( rs != null ) { + Rule[] ra = rs.getRules(); + for ( int i = 0, n = ra.length; i < n; i++ ) { + Rule r = ra [ i ]; + if ( ( r != null ) && ( r instanceof ChainedCoverageSequenceRule ) ) { + ChainedCoverageSequenceRule cr = (ChainedCoverageSequenceRule) r; + GlyphCoverageTable[] igca = cr.getCoverages(); + if ( matches ( ps, igca, 0, rv ) ) { + GlyphCoverageTable[] bgca = cr.getBacktrackCoverages(); + if ( matches ( ps, bgca, -1, null ) ) { + GlyphCoverageTable[] lgca = cr.getLookaheadCoverages(); + if ( matches ( ps, lgca, rv[0], null ) ) { + return r.getLookups(); + } + } + } + } + } + } + } + return null; + } + private boolean matches ( GlyphPositioningState ps, GlyphCoverageTable[] gca, int offset, int[] rv ) { + return ContextualSubtableFormat3.matches ( ps, gca, offset, rv ); + } + private void populate ( List entries ) { + if ( entries == null ) { + throw new AdvancedTypographicTableFormatException ( "illegal entries, must be non-null" ); + } else if ( entries.size() != 1 ) { + throw new AdvancedTypographicTableFormatException ( "illegal entries, " + entries.size() + " entries present, but requires 1 entry" ); + } else { + Object o; + if ( ( ( o = entries.get(0) ) == null ) || ! ( o instanceof RuleSet[] ) ) { + throw new AdvancedTypographicTableFormatException ( "illegal entries, first entry must be an RuleSet[], but is: " + ( ( o != null ) ? o.getClass() : null ) ); + } else { + rsa = (RuleSet[]) o; + } + } + } + } + + /** + * The DeviceTable class implements a positioning device table record, comprising + * adjustments to be made to scaled design units according to the scaled size. + */ + public static class DeviceTable { + + private final int startSize; + private final int endSize; + private final int[] deltas; + + /** + * Instantiate a DeviceTable. + * @param startSize the + * @param endSize the ending (scaled) size + * @param deltas adjustments for each scaled size + */ + public DeviceTable ( int startSize, int endSize, int[] deltas ) { + assert startSize >= 0; + assert startSize <= endSize; + assert deltas != null; + assert deltas.length == ( endSize - startSize ) + 1; + this.startSize = startSize; + this.endSize = endSize; + this.deltas = deltas; + } + + /** @return the start size */ + public int getStartSize() { + return startSize; + } + + /** @return the end size */ + public int getEndSize() { + return endSize; + } + + /** @return the deltas */ + public int[] getDeltas() { + return deltas; + } + + /** + * Find device adjustment. + * @param fontSize the font size to search for + * @return an adjustment if font size matches an entry + * @asf.todo at present, assumes that 1 device unit equals one point + */ + public int findAdjustment ( int fontSize ) { + int fs = fontSize / 1000; + if ( fs < startSize ) { + return 0; + } else if ( fs <= endSize ) { + return deltas [ fs - startSize ] * 1000; + } else { + return 0; + } + } + + /** {@inheritDoc} */ + public String toString() { + return "{ start = " + startSize + ", end = " + endSize + ", deltas = " + Arrays.toString ( deltas ) + "}"; + } + + } + + /** + * The Value class implements a positioning value record, comprising placement + * and advancement information in X and Y axes, and optionally including device data used to + * perform device (grid-fitted) specific fine grain adjustments. + */ + public static class Value { + + /** X_PLACEMENT value format flag */ + public static final int X_PLACEMENT = 0x0001; + /** Y_PLACEMENT value format flag */ + public static final int Y_PLACEMENT = 0x0002; + /** X_ADVANCE value format flag */ + public static final int X_ADVANCE = 0x0004; + /** Y_ADVANCE value format flag */ + public static final int Y_ADVANCE = 0x0008; + /** X_PLACEMENT_DEVICE value format flag */ + public static final int X_PLACEMENT_DEVICE = 0x0010; + /** Y_PLACEMENT_DEVICE value format flag */ + public static final int Y_PLACEMENT_DEVICE = 0x0020; + /** X_ADVANCE_DEVICE value format flag */ + public static final int X_ADVANCE_DEVICE = 0x0040; + /** Y_ADVANCE_DEVICE value format flag */ + public static final int Y_ADVANCE_DEVICE = 0x0080; + + /** X_PLACEMENT value index (within adjustments arrays) */ + public static final int IDX_X_PLACEMENT = 0; + /** Y_PLACEMENT value index (within adjustments arrays) */ + public static final int IDX_Y_PLACEMENT = 1; + /** X_ADVANCE value index (within adjustments arrays) */ + public static final int IDX_X_ADVANCE = 2; + /** Y_ADVANCE value index (within adjustments arrays) */ + public static final int IDX_Y_ADVANCE = 3; + + private int xPlacement; // x placement + private int yPlacement; // y placement + private int xAdvance; // x advance + private int yAdvance; // y advance + private final DeviceTable xPlaDevice; // x placement device table + private final DeviceTable yPlaDevice; // y placement device table + private final DeviceTable xAdvDevice; // x advance device table + private final DeviceTable yAdvDevice; // x advance device table + + /** + * Instantiate a Value. + * @param xPlacement the x placement or zero + * @param yPlacement the y placement or zero + * @param xAdvance the x advance or zero + * @param yAdvance the y advance or zero + * @param xPlaDevice the x placement device table or null + * @param yPlaDevice the y placement device table or null + * @param xAdvDevice the x advance device table or null + * @param yAdvDevice the y advance device table or null + */ + public Value ( int xPlacement, int yPlacement, int xAdvance, int yAdvance, DeviceTable xPlaDevice, DeviceTable yPlaDevice, DeviceTable xAdvDevice, DeviceTable yAdvDevice ) { + this.xPlacement = xPlacement; + this.yPlacement = yPlacement; + this.xAdvance = xAdvance; + this.yAdvance = yAdvance; + this.xPlaDevice = xPlaDevice; + this.yPlaDevice = yPlaDevice; + this.xAdvDevice = xAdvDevice; + this.yAdvDevice = yAdvDevice; + } + + /** @return the x placement */ + public int getXPlacement() { + return xPlacement; + } + + /** @return the y placement */ + public int getYPlacement() { + return yPlacement; + } + + /** @return the x advance */ + public int getXAdvance() { + return xAdvance; + } + + /** @return the y advance */ + public int getYAdvance() { + return yAdvance; + } + + /** @return the x placement device table */ + public DeviceTable getXPlaDevice() { + return xPlaDevice; + } + + /** @return the y placement device table */ + public DeviceTable getYPlaDevice() { + return yPlaDevice; + } + + /** @return the x advance device table */ + public DeviceTable getXAdvDevice() { + return xAdvDevice; + } + + /** @return the y advance device table */ + public DeviceTable getYAdvDevice() { + return yAdvDevice; + } + + /** + * Apply value to specific adjustments to without use of device table adjustments. + * @param xPlacement the x placement or zero + * @param yPlacement the y placement or zero + * @param xAdvance the x advance or zero + * @param yAdvance the y advance or zero + */ + public void adjust ( int xPlacement, int yPlacement, int xAdvance, int yAdvance ) { + this.xPlacement += xPlacement; + this.yPlacement += yPlacement; + this.xAdvance += xAdvance; + this.yAdvance += yAdvance; + } + + /** + * Apply value to adjustments using font size for device table adjustments. + * @param adjustments array of four integers containing X,Y placement and X,Y advance adjustments + * @param fontSize font size for device table adjustments + * @return true if some adjustment was made + */ + public boolean adjust ( int[] adjustments, int fontSize ) { + boolean adjust = false; + int dv; + if ( ( dv = xPlacement ) != 0 ) { + adjustments [ IDX_X_PLACEMENT ] += dv; + adjust = true; + } + if ( ( dv = yPlacement ) != 0 ) { + adjustments [ IDX_Y_PLACEMENT ] += dv; + adjust = true; + } + if ( ( dv = xAdvance ) != 0 ) { + adjustments [ IDX_X_ADVANCE ] += dv; + adjust = true; + } + if ( ( dv = yAdvance ) != 0 ) { + adjustments [ IDX_Y_ADVANCE ] += dv; + adjust = true; + } + if ( fontSize != 0 ) { + DeviceTable dt; + if ( ( dt = xPlaDevice ) != null ) { + if ( ( dv = dt.findAdjustment ( fontSize ) ) != 0 ) { + adjustments [ IDX_X_PLACEMENT ] += dv; + adjust = true; + } + } + if ( ( dt = yPlaDevice ) != null ) { + if ( ( dv = dt.findAdjustment ( fontSize ) ) != 0 ) { + adjustments [ IDX_Y_PLACEMENT ] += dv; + adjust = true; + } + } + if ( ( dt = xAdvDevice ) != null ) { + if ( ( dv = dt.findAdjustment ( fontSize ) ) != 0 ) { + adjustments [ IDX_X_ADVANCE ] += dv; + adjust = true; + } + } + if ( ( dt = yAdvDevice ) != null ) { + if ( ( dv = dt.findAdjustment ( fontSize ) ) != 0 ) { + adjustments [ IDX_Y_ADVANCE ] += dv; + adjust = true; + } + } + } + return adjust; + } + + /** {@inheritDoc} */ + public String toString() { + StringBuffer sb = new StringBuffer(); + boolean first = true; + sb.append ( "{ " ); + if ( xPlacement != 0 ) { + if ( ! first ) { + sb.append ( ", " ); + } else { + first = false; + } + sb.append ( "xPlacement = " + xPlacement ); + } + if ( yPlacement != 0 ) { + if ( ! first ) { + sb.append ( ", " ); + } else { + first = false; + } + sb.append ( "yPlacement = " + yPlacement ); + } + if ( xAdvance != 0 ) { + if ( ! first ) { + sb.append ( ", " ); + } else { + first = false; + } + sb.append ( "xAdvance = " + xAdvance ); + } + if ( yAdvance != 0 ) { + if ( ! first ) { + sb.append ( ", " ); + } else { + first = false; + } + sb.append ( "yAdvance = " + yAdvance ); + } + if ( xPlaDevice != null ) { + if ( ! first ) { + sb.append ( ", " ); + } else { + first = false; + } + sb.append ( "xPlaDevice = " + xPlaDevice ); + } + if ( yPlaDevice != null ) { + if ( ! first ) { + sb.append ( ", " ); + } else { + first = false; + } + sb.append ( "xPlaDevice = " + yPlaDevice ); + } + if ( xAdvDevice != null ) { + if ( ! first ) { + sb.append ( ", " ); + } else { + first = false; + } + sb.append ( "xAdvDevice = " + xAdvDevice ); + } + if ( yAdvDevice != null ) { + if ( ! first ) { + sb.append ( ", " ); + } else { + first = false; + } + sb.append ( "xAdvDevice = " + yAdvDevice ); + } + sb.append(" }"); + return sb.toString(); + } + + } + + /** + * The PairValues class implements a pair value record, comprising a glyph id (or zero) + * and two optional positioning values. + */ + public static class PairValues { + + private final int glyph; // glyph id (or 0) + private final Value value1; // value for first glyph in pair (or null) + private final Value value2; // value for second glyph in pair (or null) + + /** + * Instantiate a PairValues. + * @param glyph the glyph id (or zero) + * @param value1 the value of the first glyph in pair (or null) + * @param value2 the value of the second glyph in pair (or null) + */ + public PairValues ( int glyph, Value value1, Value value2 ) { + assert glyph >= 0; + this.glyph = glyph; + this.value1 = value1; + this.value2 = value2; + } + + /** @return the glyph id */ + public int getGlyph() { + return glyph; + } + + /** @return the first value */ + public Value getValue1() { + return value1; + } + + /** @return the second value */ + public Value getValue2() { + return value2; + } + + /** {@inheritDoc} */ + public String toString() { + StringBuffer sb = new StringBuffer(); + boolean first = true; + sb.append ( "{ " ); + if ( glyph != 0 ) { + if ( ! first ) { + sb.append ( ", " ); + } else { + first = false; + } + sb.append ( "glyph = " + glyph ); + } + if ( value1 != null ) { + if ( ! first ) { + sb.append ( ", " ); + } else { + first = false; + } + sb.append ( "value1 = " + value1 ); + } + if ( value2 != null ) { + if ( ! first ) { + sb.append ( ", " ); + } else { + first = false; + } + sb.append ( "value2 = " + value2 ); + } + sb.append(" }"); + return sb.toString(); + } + + } + + /** + * The Anchor class implements a anchor record, comprising an X,Y coordinate pair, + * an optional anchor point index (or -1), and optional X or Y device tables (or null if absent). + */ + public static class Anchor { + + private final int x; // xCoordinate (in design units) + private final int y; // yCoordinate (in design units) + private final int anchorPoint; // anchor point index (or -1) + private final DeviceTable xDevice; // x device table + private final DeviceTable yDevice; // y device table + + /** + * Instantiate an Anchor (format 1). + * @param x the x coordinate + * @param y the y coordinate + */ + public Anchor ( int x, int y ) { + this ( x, y, -1, null, null ); + } + + /** + * Instantiate an Anchor (format 2). + * @param x the x coordinate + * @param y the y coordinate + * @param anchorPoint anchor index (or -1) + */ + public Anchor ( int x, int y, int anchorPoint ) { + this ( x, y, anchorPoint, null, null ); + } + + /** + * Instantiate an Anchor (format 3). + * @param x the x coordinate + * @param y the y coordinate + * @param xDevice the x device table (or null if not present) + * @param yDevice the y device table (or null if not present) + */ + public Anchor ( int x, int y, DeviceTable xDevice, DeviceTable yDevice ) { + this ( x, y, -1, xDevice, yDevice ); + } + + /** + * Instantiate an Anchor based on an existing anchor. + * @param a the existing anchor + */ + protected Anchor ( Anchor a ) { + this ( a.x, a.y, a.anchorPoint, a.xDevice, a.yDevice ); + } + + private Anchor ( int x, int y, int anchorPoint, DeviceTable xDevice, DeviceTable yDevice ) { + assert ( anchorPoint >= 0 ) || ( anchorPoint == -1 ); + this.x = x; + this.y = y; + this.anchorPoint = anchorPoint; + this.xDevice = xDevice; + this.yDevice = yDevice; + } + + /** @return the x coordinate */ + public int getX() { + return x; + } + + /** @return the y coordinate */ + public int getY() { + return y; + } + + /** @return the anchor point index (or -1 if not specified) */ + public int getAnchorPoint() { + return anchorPoint; + } + + /** @return the x device table (or null if not specified) */ + public DeviceTable getXDevice() { + return xDevice; + } + + /** @return the y device table (or null if not specified) */ + public DeviceTable getYDevice() { + return yDevice; + } + + /** + * Obtain adjustment value required to align the specified anchor + * with this anchor. + * @param a the anchor to align + * @return the adjustment value needed to effect alignment + */ + public Value getAlignmentAdjustment ( Anchor a ) { + assert a != null; + // TODO - handle anchor point + // TODO - handle device tables + return new Value ( x - a.x, y - a.y, 0, 0, null, null, null, null ); + } + + /** {@inheritDoc} */ + public String toString() { + StringBuffer sb = new StringBuffer(); + sb.append ( "{ [" + x + "," + y + "]" ); + if ( anchorPoint != -1 ) { + sb.append ( ", anchorPoint = " + anchorPoint ); + } + if ( xDevice != null ) { + sb.append ( ", xDevice = " + xDevice ); + } + if ( yDevice != null ) { + sb.append ( ", yDevice = " + yDevice ); + } + sb.append(" }"); + return sb.toString(); + } + + } + + /** + * The MarkAnchor class is a subclass of the Anchor class, adding a mark + * class designation. + */ + public static class MarkAnchor extends Anchor { + + private final int markClass; // mark class + + /** + * Instantiate a MarkAnchor + * @param markClass the mark class + * @param a the underlying anchor (whose fields are copied) + */ + public MarkAnchor ( int markClass, Anchor a ) { + super ( a ); + this.markClass = markClass; + } + + /** @return the mark class */ + public int getMarkClass() { + return markClass; + } + + /** {@inheritDoc} */ + public String toString() { + return "{ markClass = " + markClass + ", anchor = " + super.toString() + " }"; + } + + } + +} diff --git a/src/java/org/apache/fop/complexscripts/fonts/GlyphProcessingState.java b/src/java/org/apache/fop/complexscripts/fonts/GlyphProcessingState.java new file mode 100644 index 000000000..acccdc86c --- /dev/null +++ b/src/java/org/apache/fop/complexscripts/fonts/GlyphProcessingState.java @@ -0,0 +1,1135 @@ +/* + * 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.complexscripts.fonts; + +import java.nio.IntBuffer; +import java.util.ArrayList; +import java.util.List; + +import org.apache.fop.complexscripts.util.GlyphSequence; +import org.apache.fop.complexscripts.util.GlyphContextTester; +import org.apache.fop.complexscripts.util.GlyphTester; +import org.apache.fop.complexscripts.util.ScriptContextTester; + +// CSOFF: LineLengthCheck +// CSOFF: NoWhitespaceAfterCheck + +/** + * The GlyphProcessingState implements a common, base state object used during glyph substitution + * and positioning processing. + * @author Glenn Adams + */ + +public class GlyphProcessingState { + + /** governing glyph definition table */ + protected GlyphDefinitionTable gdef; + /** governing script */ + protected String script; + /** governing language */ + protected String language; + /** governing feature */ + protected String feature; + /** current input glyph sequence */ + protected GlyphSequence igs; + /** current index in input sequence */ + protected int index; + /** last (maximum) index of input sequence (exclusive) */ + protected int indexLast; + /** consumed, updated after each successful subtable application */ + protected int consumed; + /** lookup flags */ + protected int lookupFlags; + /** class match set */ + protected int classMatchSet; + /** script specific context tester or null */ + protected ScriptContextTester sct; + /** glyph context tester or null */ + protected GlyphContextTester gct; + /** ignore base glyph tester */ + protected GlyphTester ignoreBase; + /** ignore ligature glyph tester */ + protected GlyphTester ignoreLigature; + /** ignore mark glyph tester */ + protected GlyphTester ignoreMark; + /** default ignore glyph tester */ + protected GlyphTester ignoreDefault; + + /** + * Construct glyph processing state. + * @param gs input glyph sequence + * @param script script identifier + * @param language language identifier + * @param feature feature identifier + * @param sct script context tester (or null) + */ + protected GlyphProcessingState ( GlyphSequence gs, String script, String language, String feature, ScriptContextTester sct ) { + this.script = script; + this.language = language; + this.feature = feature; + this.igs = gs; + this.indexLast = gs.getGlyphCount(); + this.sct = sct; + this.gct = ( sct != null ) ? sct.getTester ( feature ) : null; + this.ignoreBase = new GlyphTester() { public boolean test(int gi, int flags) { return isIgnoredBase(gi, flags); } }; + this.ignoreLigature = new GlyphTester() { public boolean test(int gi, int flags) { return isIgnoredLigature(gi, flags); } }; + this.ignoreMark = new GlyphTester() { public boolean test(int gi, int flags) { return isIgnoredMark(gi, flags); } }; + } + + /** + * Construct glyph processing state using an existing state object using shallow copy + * except as follows: input glyph sequence is copied deep except for its characters array. + * @param s existing processing state to copy from + */ + protected GlyphProcessingState ( GlyphProcessingState s ) { + this ( new GlyphSequence ( s.igs ), s.script, s.language, s.feature, s.sct ); + setPosition ( s.index ); + } + + /** + * Set governing glyph definition table. + * @param gdef glyph definition table (or null, to unset) + */ + public void setGDEF ( GlyphDefinitionTable gdef ) { + if ( this.gdef == null ) { + this.gdef = gdef; + } else if ( gdef == null ) { + this.gdef = null; + } + } + + /** + * Obtain governing glyph definition table. + * @return glyph definition table (or null, to not set) + */ + public GlyphDefinitionTable getGDEF() { + return gdef; + } + + /** + * Set governing lookup flags + * @param flags lookup flags (or zero, to unset) + */ + public void setLookupFlags ( int flags ) { + if ( this.lookupFlags == 0 ) { + this.lookupFlags = flags; + } else if ( flags == 0 ) { + this.lookupFlags = 0; + } + } + + /** + * Obtain governing lookup flags. + * @return lookup flags (zero may indicate unset or no flags) + */ + public int getLookupFlags() { + return lookupFlags; + } + + /** + * Obtain governing class match set. + * @param gi glyph index that may be used to determine which match set applies + * @return class match set (zero may indicate unset or no set) + */ + public int getClassMatchSet ( int gi ) { + return 0; + } + + /** + * Set default ignore tester. + * @param ignoreDefault glyph tester (or null, to unset) + */ + public void setIgnoreDefault ( GlyphTester ignoreDefault ) { + if ( this.ignoreDefault == null ) { + this.ignoreDefault = ignoreDefault; + } else if ( ignoreDefault == null ) { + this.ignoreDefault = null; + } + } + + /** + * Obtain governing default ignores tester. + * @return default ignores tester + */ + public GlyphTester getIgnoreDefault() { + return ignoreDefault; + } + + /** + * Update glyph subtable specific state. Each time a + * different glyph subtable is to be applied, it is used + * to update this state prior to application, after which + * this state is to be reset. + * @param st glyph subtable to use for update + */ + public void updateSubtableState ( GlyphSubtable st ) { + setGDEF ( st.getGDEF() ); + setLookupFlags ( st.getFlags() ); + setIgnoreDefault ( getIgnoreTester ( getLookupFlags() ) ); + } + + /** + * Reset glyph subtable specific state. + */ + public void resetSubtableState() { + setGDEF ( null ); + setLookupFlags ( 0 ); + setIgnoreDefault ( null ); + } + + /** + * Obtain current position index in input glyph sequence. + * @return current index + */ + public int getPosition() { + return index; + } + + /** + * Set (seek to) position index in input glyph sequence. + * @param index to seek to + * @throws IndexOutOfBoundsException if index is less than zero + * or exceeds last valid position + */ + public void setPosition ( int index ) throws IndexOutOfBoundsException { + if ( ( index >= 0 ) && ( index <= indexLast ) ) { + this.index = index; + } else { + throw new IndexOutOfBoundsException(); + } + } + + /** + * Obtain last valid position index in input glyph sequence. + * @return current last index + */ + public int getLastPosition() { + return indexLast; + } + + /** + * Determine if at least one glyph remains in + * input sequence. + * @return true if one or more glyph remains + */ + public boolean hasNext() { + return hasNext ( 1 ); + } + + /** + * Determine if at least count glyphs remain in + * input sequence. + * @param count of glyphs to test + * @return true if at least count glyphs are available + */ + public boolean hasNext ( int count ) { + return ( index + count ) <= indexLast; + } + + /** + * Update the current position index based upon previously consumed + * glyphs, i.e., add the consuemd count to the current position index. + * If no glyphs were previously consumed, then forces exactly one + * glyph to be consumed. + * @return the new (updated) position index + */ + public int next() { + if ( index < indexLast ) { + // force consumption of at least one input glyph + if ( consumed == 0 ) { + consumed = 1; + } + index += consumed; consumed = 0; + if ( index > indexLast ) { + index = indexLast; + } + } + return index; + } + + /** + * Determine if at least one backtrack (previous) glyph is present + * in input sequence. + * @return true if one or more glyph remains + */ + public boolean hasPrev() { + return hasPrev ( 1 ); + } + + /** + * Determine if at least count backtrack (previous) glyphs + * are present in input sequence. + * @param count of glyphs to test + * @return true if at least count glyphs are available + */ + public boolean hasPrev ( int count ) { + return ( index - count ) >= 0; + } + + /** + * Update the current position index based upon previously consumed + * glyphs, i.e., subtract the consuemd count from the current position index. + * If no glyphs were previously consumed, then forces exactly one + * glyph to be consumed. This method is used to traverse an input + * glyph sequence in reverse order. + * @return the new (updated) position index + */ + public int prev() { + if ( index > 0 ) { + // force consumption of at least one input glyph + if ( consumed == 0 ) { + consumed = 1; + } + index -= consumed; consumed = 0; + if ( index < 0 ) { + index = 0; + } + } + return index; + } + + /** + * Record the consumption of count glyphs such that + * this consumption never exceeds the number of glyphs in the input glyph + * sequence. + * @param count of glyphs to consume + * @return newly adjusted consumption count + * @throws IndexOutOfBoundsException if count would cause consumption + * to exceed count of glyphs in input glyph sequence + */ + public int consume ( int count ) throws IndexOutOfBoundsException { + if ( ( consumed + count ) <= indexLast ) { + consumed += count; + return consumed; + } else { + throw new IndexOutOfBoundsException(); + } + } + + /** + * Determine if any consumption has occurred. + * @return true if consumption count is greater than zero + */ + public boolean didConsume() { + return consumed > 0; + } + + /** + * Obtain reference to input glyph sequence, which must not be modified. + * @return input glyph sequence + */ + public GlyphSequence getInput() { + return igs; + } + + /** + * Obtain glyph at specified offset from current position. + * @param offset from current position + * @return glyph at specified offset from current position + * @throws IndexOutOfBoundsException if no glyph available at offset + */ + public int getGlyph ( int offset ) throws IndexOutOfBoundsException { + int i = index + offset; + if ( ( i >= 0 ) && ( i < indexLast ) ) { + return igs.getGlyph ( i ); + } else { + throw new IndexOutOfBoundsException ( "attempting index at " + i ); + } + } + + /** + * Obtain glyph at current position. + * @return glyph at current position + * @throws IndexOutOfBoundsException if no glyph available + */ + public int getGlyph() throws IndexOutOfBoundsException { + return getGlyph ( 0 ); + } + + /** + * Set (replace) glyph at specified offset from current position. + * @param offset from current position + * @param glyph to set at specified offset from current position + * @throws IndexOutOfBoundsException if specified offset is not valid position + */ + public void setGlyph ( int offset, int glyph ) throws IndexOutOfBoundsException { + int i = index + offset; + if ( ( i >= 0 ) && ( i < indexLast ) ) { + igs.setGlyph ( i, glyph ); + } else { + throw new IndexOutOfBoundsException ( "attempting index at " + i ); + } + } + + /** + * Obtain character association of glyph at specified offset from current position. + * @param offset from current position + * @return character association of glyph at current position + * @throws IndexOutOfBoundsException if offset results in an invalid index into input glyph sequence + */ + public GlyphSequence.CharAssociation getAssociation ( int offset ) throws IndexOutOfBoundsException { + int i = index + offset; + if ( ( i >= 0 ) && ( i < indexLast ) ) { + return igs.getAssociation ( i ); + } else { + throw new IndexOutOfBoundsException ( "attempting index at " + i ); + } + } + + /** + * Obtain character association of glyph at current position. + * @return character association of glyph at current position + * @throws IndexOutOfBoundsException if no glyph available + */ + public GlyphSequence.CharAssociation getAssociation() throws IndexOutOfBoundsException { + return getAssociation ( 0 ); + } + + /** + * Obtain count glyphs starting at specified offset from current position. If + * reverseOrder is true, then glyphs are returned in reverse order starting at specified offset + * and going in reverse towards beginning of input glyph sequence. + * @param offset from current position + * @param count number of glyphs to obtain + * @param reverseOrder true if to obtain in reverse order + * @param ignoreTester glyph tester to use to determine which glyphs are ignored (or null, in which case none are ignored) + * @param glyphs array to use to fetch glyphs + * @param counts int[2] array to receive fetched glyph counts, where counts[0] will + * receive the number of glyphs obtained, and counts[1] will receive the number of glyphs + * ignored + * @return array of glyphs + * @throws IndexOutOfBoundsException if offset or count results in an + * invalid index into input glyph sequence + */ + public int[] getGlyphs ( int offset, int count, boolean reverseOrder, GlyphTester ignoreTester, int[] glyphs, int[] counts ) throws IndexOutOfBoundsException { + if ( count < 0 ) { + count = getGlyphsAvailable ( offset, reverseOrder, ignoreTester ) [ 0 ]; + } + int start = index + offset; + if ( start < 0 ) { + throw new IndexOutOfBoundsException ( "will attempt index at " + start ); + } else if ( ! reverseOrder && ( ( start + count ) > indexLast ) ) { + throw new IndexOutOfBoundsException ( "will attempt index at " + ( start + count ) ); + } else if ( reverseOrder && ( ( start + 1 ) < count ) ) { + throw new IndexOutOfBoundsException ( "will attempt index at " + ( start - count ) ); + } + if ( glyphs == null ) { + glyphs = new int [ count ]; + } else if ( glyphs.length != count ) { + throw new IllegalArgumentException ( "glyphs array is non-null, but its length (" + glyphs.length + "), is not equal to count (" + count + ")" ); + } + if ( ! reverseOrder ) { + return getGlyphsForward ( start, count, ignoreTester, glyphs, counts ); + } else { + return getGlyphsReverse ( start, count, ignoreTester, glyphs, counts ); + } + } + + private int[] getGlyphsForward ( int start, int count, GlyphTester ignoreTester, int[] glyphs, int[] counts ) throws IndexOutOfBoundsException { + int counted = 0; + int ignored = 0; + for ( int i = start, n = indexLast, k = 0; i < n; i++ ) { + int gi = getGlyph ( i - index ); + if ( gi == 65535 ) { + ignored++; + } else { + if ( ( ignoreTester == null ) || ! ignoreTester.test ( gi, getLookupFlags() ) ) { + if ( k < count ) { + glyphs [ k++ ] = gi; counted++; + } else { + break; + } + } else { + ignored++; + } + } + } + if ( ( counts != null ) && ( counts.length > 1 ) ) { + counts[0] = counted; + counts[1] = ignored; + } + return glyphs; + } + + private int[] getGlyphsReverse ( int start, int count, GlyphTester ignoreTester, int[] glyphs, int[] counts ) throws IndexOutOfBoundsException { + int counted = 0; + int ignored = 0; + for ( int i = start, k = 0; i >= 0; i-- ) { + int gi = getGlyph ( i - index ); + if ( gi == 65535 ) { + ignored++; + } else { + if ( ( ignoreTester == null ) || ! ignoreTester.test ( gi, getLookupFlags() ) ) { + if ( k < count ) { + glyphs [ k++ ] = gi; counted++; + } else { + break; + } + } else { + ignored++; + } + } + } + if ( ( counts != null ) && ( counts.length > 1 ) ) { + counts[0] = counted; + counts[1] = ignored; + } + return glyphs; + } + + /** + * Obtain count glyphs starting at specified offset from current position. If + * offset is negative, then glyphs are returned in reverse order starting at specified offset + * and going in reverse towards beginning of input glyph sequence. + * @param offset from current position + * @param count number of glyphs to obtain + * @param glyphs array to use to fetch glyphs + * @param counts int[2] array to receive fetched glyph counts, where counts[0] will + * receive the number of glyphs obtained, and counts[1] will receive the number of glyphs + * ignored + * @return array of glyphs + * @throws IndexOutOfBoundsException if offset or count results in an + * invalid index into input glyph sequence + */ + public int[] getGlyphs ( int offset, int count, int[] glyphs, int[] counts ) throws IndexOutOfBoundsException { + return getGlyphs ( offset, count, offset < 0, ignoreDefault, glyphs, counts ); + } + + /** + * Obtain all glyphs starting from current position to end of input glyph sequence. + * @return array of available glyphs + * @throws IndexOutOfBoundsException if no glyph available + */ + public int[] getGlyphs() throws IndexOutOfBoundsException { + return getGlyphs ( 0, indexLast - index, false, null, null, null ); + } + + /** + * Obtain count ignored glyphs starting at specified offset from current position. If + * reverseOrder is true, then glyphs are returned in reverse order starting at specified offset + * and going in reverse towards beginning of input glyph sequence. + * @param offset from current position + * @param count number of glyphs to obtain + * @param reverseOrder true if to obtain in reverse order + * @param ignoreTester glyph tester to use to determine which glyphs are ignored (or null, in which case none are ignored) + * @param glyphs array to use to fetch glyphs + * @param counts int[2] array to receive fetched glyph counts, where counts[0] will + * receive the number of glyphs obtained, and counts[1] will receive the number of glyphs + * ignored + * @return array of glyphs + * @throws IndexOutOfBoundsException if offset or count results in an + * invalid index into input glyph sequence + */ + public int[] getIgnoredGlyphs ( int offset, int count, boolean reverseOrder, GlyphTester ignoreTester, int[] glyphs, int[] counts ) throws IndexOutOfBoundsException { + return getGlyphs ( offset, count, reverseOrder, new NotGlyphTester ( ignoreTester ), glyphs, counts ); + } + + /** + * Obtain count ignored glyphs starting at specified offset from current position. If offset is + * negative, then fetch in reverse order. + * @param offset from current position + * @param count number of glyphs to obtain + * @return array of glyphs + * @throws IndexOutOfBoundsException if offset or count results in an + * invalid index into input glyph sequence + */ + public int[] getIgnoredGlyphs ( int offset, int count ) throws IndexOutOfBoundsException { + return getIgnoredGlyphs ( offset, count, offset < 0, ignoreDefault, null, null ); + } + + /** + * Determine number of glyphs available starting at specified offset from current position. If + * reverseOrder is true, then search backwards in input glyph sequence. + * @param offset from current position + * @param reverseOrder true if to obtain in reverse order + * @param ignoreTester glyph tester to use to determine which glyphs to count (or null, in which case none are ignored) + * @return an int[2] array where counts[0] is the number of glyphs available, and counts[1] is the number of glyphs ignored + * @throws IndexOutOfBoundsException if offset or count results in an + * invalid index into input glyph sequence + */ + public int[] getGlyphsAvailable ( int offset, boolean reverseOrder, GlyphTester ignoreTester ) throws IndexOutOfBoundsException { + int start = index + offset; + if ( ( start < 0 ) || ( start > indexLast ) ) { + return new int[] { 0, 0 }; + } else if ( ! reverseOrder ) { + return getGlyphsAvailableForward ( start, ignoreTester ); + } else { + return getGlyphsAvailableReverse ( start, ignoreTester ); + } + } + + private int[] getGlyphsAvailableForward ( int start, GlyphTester ignoreTester ) throws IndexOutOfBoundsException { + int counted = 0; + int ignored = 0; + if ( ignoreTester == null ) { + counted = indexLast - start; + } else { + for ( int i = start, n = indexLast; i < n; i++ ) { + int gi = getGlyph ( i - index ); + if ( gi == 65535 ) { + ignored++; + } else { + if ( ignoreTester.test ( gi, getLookupFlags() ) ) { + ignored++; + } else { + counted++; + } + } + } + } + return new int[] { counted, ignored }; + } + + private int[] getGlyphsAvailableReverse ( int start, GlyphTester ignoreTester ) throws IndexOutOfBoundsException { + int counted = 0; + int ignored = 0; + if ( ignoreTester == null ) { + counted = start + 1; + } else { + for ( int i = start; i >= 0; i-- ) { + int gi = getGlyph ( i - index ); + if ( gi == 65535 ) { + ignored++; + } else { + if ( ignoreTester.test ( gi, getLookupFlags() ) ) { + ignored++; + } else { + counted++; + } + } + } + } + return new int[] { counted, ignored }; + } + + /** + * Determine number of glyphs available starting at specified offset from current position. If + * reverseOrder is true, then search backwards in input glyph sequence. Uses the + * default ignores tester. + * @param offset from current position + * @param reverseOrder true if to obtain in reverse order + * @return an int[2] array where counts[0] is the number of glyphs available, and counts[1] is the number of glyphs ignored + * @throws IndexOutOfBoundsException if offset or count results in an + * invalid index into input glyph sequence + */ + public int[] getGlyphsAvailable ( int offset, boolean reverseOrder ) throws IndexOutOfBoundsException { + return getGlyphsAvailable ( offset, reverseOrder, ignoreDefault ); + } + + /** + * Determine number of glyphs available starting at specified offset from current position. If + * offset is negative, then search backwards in input glyph sequence. Uses the + * default ignores tester. + * @param offset from current position + * @return an int[2] array where counts[0] is the number of glyphs available, and counts[1] is the number of glyphs ignored + * @throws IndexOutOfBoundsException if offset or count results in an + * invalid index into input glyph sequence + */ + public int[] getGlyphsAvailable ( int offset ) throws IndexOutOfBoundsException { + return getGlyphsAvailable ( offset, offset < 0 ); + } + + /** + * Obtain count character associations of glyphs starting at specified offset from current position. If + * reverseOrder is true, then associations are returned in reverse order starting at specified offset + * and going in reverse towards beginning of input glyph sequence. + * @param offset from current position + * @param count number of associations to obtain + * @param reverseOrder true if to obtain in reverse order + * @param ignoreTester glyph tester to use to determine which glyphs are ignored (or null, in which case none are ignored) + * @param associations array to use to fetch associations + * @param counts int[2] array to receive fetched association counts, where counts[0] will + * receive the number of associations obtained, and counts[1] will receive the number of glyphs whose + * associations were ignored + * @return array of associations + * @throws IndexOutOfBoundsException if offset or count results in an + * invalid index into input glyph sequence + */ + public GlyphSequence.CharAssociation[] getAssociations ( int offset, int count, boolean reverseOrder, GlyphTester ignoreTester, GlyphSequence.CharAssociation[] associations, int[] counts ) + throws IndexOutOfBoundsException { + if ( count < 0 ) { + count = getGlyphsAvailable ( offset, reverseOrder, ignoreTester ) [ 0 ]; + } + int start = index + offset; + if ( start < 0 ) { + throw new IndexOutOfBoundsException ( "will attempt index at " + start ); + } else if ( ! reverseOrder && ( ( start + count ) > indexLast ) ) { + throw new IndexOutOfBoundsException ( "will attempt index at " + ( start + count ) ); + } else if ( reverseOrder && ( ( start + 1 ) < count ) ) { + throw new IndexOutOfBoundsException ( "will attempt index at " + ( start - count ) ); + } + if ( associations == null ) { + associations = new GlyphSequence.CharAssociation [ count ]; + } else if ( associations.length != count ) { + throw new IllegalArgumentException ( "associations array is non-null, but its length (" + associations.length + "), is not equal to count (" + count + ")" ); + } + if ( ! reverseOrder ) { + return getAssociationsForward ( start, count, ignoreTester, associations, counts ); + } else { + return getAssociationsReverse ( start, count, ignoreTester, associations, counts ); + } + } + + private GlyphSequence.CharAssociation[] getAssociationsForward ( int start, int count, GlyphTester ignoreTester, GlyphSequence.CharAssociation[] associations, int[] counts ) + throws IndexOutOfBoundsException { + int counted = 0; + int ignored = 0; + for ( int i = start, n = indexLast, k = 0; i < n; i++ ) { + int gi = getGlyph ( i - index ); + if ( gi == 65535 ) { + ignored++; + } else { + if ( ( ignoreTester == null ) || ! ignoreTester.test ( gi, getLookupFlags() ) ) { + if ( k < count ) { + associations [ k++ ] = getAssociation ( i - index ); counted++; + } else { + break; + } + } else { + ignored++; + } + } + } + if ( ( counts != null ) && ( counts.length > 1 ) ) { + counts[0] = counted; + counts[1] = ignored; + } + return associations; + } + + private GlyphSequence.CharAssociation[] getAssociationsReverse ( int start, int count, GlyphTester ignoreTester, GlyphSequence.CharAssociation[] associations, int[] counts ) + throws IndexOutOfBoundsException { + int counted = 0; + int ignored = 0; + for ( int i = start, k = 0; i >= 0; i-- ) { + int gi = getGlyph ( i - index ); + if ( gi == 65535 ) { + ignored++; + } else { + if ( ( ignoreTester == null ) || ! ignoreTester.test ( gi, getLookupFlags() ) ) { + if ( k < count ) { + associations [ k++ ] = getAssociation ( i - index ); counted++; + } else { + break; + } + } else { + ignored++; + } + } + } + if ( ( counts != null ) && ( counts.length > 1 ) ) { + counts[0] = counted; + counts[1] = ignored; + } + return associations; + } + + /** + * Obtain count character associations of glyphs starting at specified offset from current position. If + * offset is negative, then search backwards in input glyph sequence. Uses the + * default ignores tester. + * @param offset from current position + * @param count number of associations to obtain + * @return array of associations + * @throws IndexOutOfBoundsException if offset or count results in an + * invalid index into input glyph sequence + */ + public GlyphSequence.CharAssociation[] getAssociations ( int offset, int count ) throws IndexOutOfBoundsException { + return getAssociations ( offset, count, offset < 0, ignoreDefault, null, null ); + } + + /** + * Obtain count character associations of ignored glyphs starting at specified offset from current position. If + * reverseOrder is true, then glyphs are returned in reverse order starting at specified offset + * and going in reverse towards beginning of input glyph sequence. + * @param offset from current position + * @param count number of character associations to obtain + * @param reverseOrder true if to obtain in reverse order + * @param ignoreTester glyph tester to use to determine which glyphs are ignored (or null, in which case none are ignored) + * @param associations array to use to fetch associations + * @param counts int[2] array to receive fetched association counts, where counts[0] will + * receive the number of associations obtained, and counts[1] will receive the number of glyphs whose + * associations were ignored + * @return array of associations + * @throws IndexOutOfBoundsException if offset or count results in an + * invalid index into input glyph sequence + */ + public GlyphSequence.CharAssociation[] getIgnoredAssociations ( int offset, int count, boolean reverseOrder, GlyphTester ignoreTester, GlyphSequence.CharAssociation[] associations, int[] counts ) + throws IndexOutOfBoundsException { + return getAssociations ( offset, count, reverseOrder, new NotGlyphTester ( ignoreTester ), associations, counts ); + } + + /** + * Obtain count character associations of ignored glyphs starting at specified offset from current position. If + * offset is negative, then search backwards in input glyph sequence. Uses the + * default ignores tester. + * @param offset from current position + * @param count number of character associations to obtain + * @return array of associations + * @throws IndexOutOfBoundsException if offset or count results in an + * invalid index into input glyph sequence + */ + public GlyphSequence.CharAssociation[] getIgnoredAssociations ( int offset, int count ) throws IndexOutOfBoundsException { + return getIgnoredAssociations ( offset, count, offset < 0, ignoreDefault, null, null ); + } + + /** + * Replace subsequence of input glyph sequence starting at specified offset from current position and of + * length count glyphs with a subsequence of the sequence gs starting from the specified + * offset gsOffset of length gsCount glyphs. + * @param offset from current position + * @param count number of glyphs to replace, which, if negative means all glyphs from offset to end of input sequence + * @param gs glyph sequence from which to obtain replacement glyphs + * @param gsOffset offset of first glyph in replacement sequence + * @param gsCount count of glyphs in replacement sequence starting at gsOffset + * @return true if replacement occurred, or false if replacement would result in no change to input glyph sequence + * @throws IndexOutOfBoundsException if offset or count results in an + * invalid index into input glyph sequence + */ + public boolean replaceInput ( int offset, int count, GlyphSequence gs, int gsOffset, int gsCount ) throws IndexOutOfBoundsException { + int nig = ( igs != null ) ? igs.getGlyphCount() : 0; + int position = getPosition() + offset; + if ( position < 0 ) { + position = 0; + } else if ( position > nig ) { + position = nig; + } + if ( ( count < 0 ) || ( ( position + count ) > nig ) ) { + count = nig - position; + } + int nrg = ( gs != null ) ? gs.getGlyphCount() : 0; + if ( gsOffset < 0 ) { + gsOffset = 0; + } else if ( gsOffset > nrg ) { + gsOffset = nrg; + } + if ( ( gsCount < 0 ) || ( ( gsOffset + gsCount ) > nrg ) ) { + gsCount = nrg - gsOffset; + } + int ng = nig + gsCount - count; + IntBuffer gb = IntBuffer.allocate ( ng ); + List al = new ArrayList ( ng ); + for ( int i = 0, n = position; i < n; i++ ) { + gb.put ( igs.getGlyph ( i ) ); + al.add ( igs.getAssociation ( i ) ); + } + for ( int i = gsOffset, n = gsOffset + gsCount; i < n; i++ ) { + gb.put ( gs.getGlyph ( i ) ); + al.add ( gs.getAssociation ( i ) ); + } + for ( int i = position + count, n = nig; i < n; i++ ) { + gb.put ( igs.getGlyph ( i ) ); + al.add ( igs.getAssociation ( i ) ); + } + gb.flip(); + if ( igs.compareGlyphs ( gb ) != 0 ) { + this.igs = new GlyphSequence ( igs.getCharacters(), gb, al ); + this.indexLast = gb.limit(); + return true; + } else { + return false; + } + } + + /** + * Replace subsequence of input glyph sequence starting at specified offset from current position and of + * length count glyphs with all glyphs in the replacement sequence gs. + * @param offset from current position + * @param count number of glyphs to replace, which, if negative means all glyphs from offset to end of input sequence + * @param gs glyph sequence from which to obtain replacement glyphs + * @return true if replacement occurred, or false if replacement would result in no change to input glyph sequence + * @throws IndexOutOfBoundsException if offset or count results in an + * invalid index into input glyph sequence + */ + public boolean replaceInput ( int offset, int count, GlyphSequence gs ) throws IndexOutOfBoundsException { + return replaceInput ( offset, count, gs, 0, gs.getGlyphCount() ); + } + + /** + * Erase glyphs in input glyph sequence starting at specified offset from current position, where each glyph + * in the specified glyphs array is matched, one at a time, and when a (forward searching) match is found + * in the input glyph sequence, the matching glyph is replaced with the glyph index 65535. + * @param offset from current position + * @param glyphs array of glyphs to erase + * @return the number of glyphs erased, which may be less than the number of specified glyphs + * @throws IndexOutOfBoundsException if offset or count results in an + * invalid index into input glyph sequence + */ + public int erase ( int offset, int[] glyphs ) throws IndexOutOfBoundsException { + int start = index + offset; + if ( ( start < 0 ) || ( start > indexLast ) ) { + throw new IndexOutOfBoundsException ( "will attempt index at " + start ); + } else { + int erased = 0; + for ( int i = start - index, n = indexLast - start; i < n; i++ ) { + int gi = getGlyph ( i ); + if ( gi == glyphs [ erased ] ) { + setGlyph ( i, 65535 ); + erased++; + } + } + return erased; + } + } + + /** + * Determine if is possible that the current input sequence satisfies a script specific + * context testing predicate. If no predicate applies, then application is always possible. + * @return true if no script specific context tester applies or if a specified tester returns + * true for the current input sequence context + */ + public boolean maybeApplicable() { + if ( gct == null ) { + return true; + } else { + return gct.test ( script, language, feature, igs, index, getLookupFlags() ); + } + } + + /** + * Apply default application semantices; namely, consume one glyph. + */ + public void applyDefault() { + consumed += 1; + } + + /** + * Determine if specified glyph is a base glyph according to the governing + * glyph definition table. + * @param gi glyph index to test + * @return true if glyph definition table records glyph as a base glyph; otherwise, false + */ + public boolean isBase ( int gi ) { + if ( gdef != null ) { + return gdef.isGlyphClass ( gi, GlyphDefinitionTable.GLYPH_CLASS_BASE ); + } else { + return false; + } + } + + /** + * Determine if specified glyph is an ignored base glyph according to the governing + * glyph definition table. + * @param gi glyph index to test + * @param flags that apply to lookup in scope + * @return true if glyph definition table records glyph as a base glyph; otherwise, false + */ + public boolean isIgnoredBase ( int gi, int flags ) { + return ( ( flags & GlyphSubtable.LF_IGNORE_BASE ) != 0 ) && isBase ( gi ); + } + + /** + * Determine if specified glyph is an ligature glyph according to the governing + * glyph definition table. + * @param gi glyph index to test + * @return true if glyph definition table records glyph as a ligature glyph; otherwise, false + */ + public boolean isLigature ( int gi ) { + if ( gdef != null ) { + return gdef.isGlyphClass ( gi, GlyphDefinitionTable.GLYPH_CLASS_LIGATURE ); + } else { + return false; + } + } + + /** + * Determine if specified glyph is an ignored ligature glyph according to the governing + * glyph definition table. + * @param gi glyph index to test + * @param flags that apply to lookup in scope + * @return true if glyph definition table records glyph as a ligature glyph; otherwise, false + */ + public boolean isIgnoredLigature ( int gi, int flags ) { + return ( ( flags & GlyphSubtable.LF_IGNORE_LIGATURE ) != 0 ) && isLigature ( gi ); + } + + /** + * Determine if specified glyph is a mark glyph according to the governing + * glyph definition table. + * @param gi glyph index to test + * @return true if glyph definition table records glyph as a mark glyph; otherwise, false + */ + public boolean isMark ( int gi ) { + if ( gdef != null ) { + return gdef.isGlyphClass ( gi, GlyphDefinitionTable.GLYPH_CLASS_MARK ); + } else { + return false; + } + } + + /** + * Determine if specified glyph is an ignored ligature glyph according to the governing + * glyph definition table. + * @param gi glyph index to test + * @param flags that apply to lookup in scope + * @return true if glyph definition table records glyph as a ligature glyph; otherwise, false + */ + public boolean isIgnoredMark ( int gi, int flags ) { + if ( ( flags & GlyphSubtable.LF_IGNORE_MARK ) != 0 ) { + return isMark ( gi ); + } else if ( ( flags & GlyphSubtable.LF_MARK_ATTACHMENT_TYPE ) != 0 ) { + int lac = ( flags & GlyphSubtable.LF_MARK_ATTACHMENT_TYPE ) >> 8; + int gac = gdef.getMarkAttachClass ( gi ); + return ( gac != lac ); + } else { + return false; + } + } + + /** + * Obtain an ignored glyph tester that corresponds to the specified lookup flags. + * @param flags lookup flags + * @return a glyph tester + */ + public GlyphTester getIgnoreTester ( int flags ) { + if ( ( flags & GlyphSubtable.LF_IGNORE_BASE ) != 0 ) { + if ( ( flags & (GlyphSubtable.LF_IGNORE_LIGATURE | GlyphSubtable.LF_IGNORE_MARK) ) == 0 ) { + return ignoreBase; + } else { + return getCombinedIgnoreTester ( flags ); + } + } + if ( ( flags & GlyphSubtable.LF_IGNORE_LIGATURE ) != 0 ) { + if ( ( flags & (GlyphSubtable.LF_IGNORE_BASE | GlyphSubtable.LF_IGNORE_MARK) ) == 0 ) { + return ignoreLigature; + } else { + return getCombinedIgnoreTester ( flags ); + } + } + if ( ( flags & GlyphSubtable.LF_IGNORE_MARK ) != 0 ) { + if ( ( flags & (GlyphSubtable.LF_IGNORE_BASE | GlyphSubtable.LF_IGNORE_LIGATURE) ) == 0 ) { + return ignoreMark; + } else { + return getCombinedIgnoreTester ( flags ); + } + } + return null; + } + + /** + * Obtain an ignored glyph tester that corresponds to the specified multiple (combined) lookup flags. + * @param flags lookup flags + * @return a glyph tester + */ + public GlyphTester getCombinedIgnoreTester ( int flags ) { + GlyphTester[] gta = new GlyphTester [ 3 ]; + int ngt = 0; + if ( ( flags & GlyphSubtable.LF_IGNORE_BASE ) != 0 ) { + gta [ ngt++ ] = ignoreBase; + } + if ( ( flags & GlyphSubtable.LF_IGNORE_LIGATURE ) != 0 ) { + gta [ ngt++ ] = ignoreLigature; + } + if ( ( flags & GlyphSubtable.LF_IGNORE_MARK ) != 0 ) { + gta [ ngt++ ] = ignoreMark; + } + return getCombinedOrTester ( gta, ngt ); + } + + /** + * Obtain an combined OR glyph tester. + * @param gta an array of glyph testers + * @param ngt number of glyph testers present in specified array + * @return a combined OR glyph tester + */ + public GlyphTester getCombinedOrTester ( GlyphTester[] gta, int ngt ) { + if ( ngt > 0 ) { + return new CombinedOrGlyphTester ( gta, ngt ); + } else { + return null; + } + } + + /** + * Obtain an combined AND glyph tester. + * @param gta an array of glyph testers + * @param ngt number of glyph testers present in specified array + * @return a combined AND glyph tester + */ + public GlyphTester getCombinedAndTester ( GlyphTester[] gta, int ngt ) { + if ( ngt > 0 ) { + return new CombinedAndGlyphTester ( gta, ngt ); + } else { + return null; + } + } + + /** combined OR glyph tester */ + private static class CombinedOrGlyphTester implements GlyphTester { + private GlyphTester[] gta; + private int ngt; + CombinedOrGlyphTester ( GlyphTester[] gta, int ngt ) { + this.gta = gta; + this.ngt = ngt; + } + /** {@inheritDoc} */ + public boolean test ( int gi, int flags ) { + for ( int i = 0, n = ngt; i < n; i++ ) { + GlyphTester gt = gta [ i ]; + if ( gt != null ) { + if ( gt.test ( gi, flags ) ) { + return true; + } + } + } + return false; + } + } + + /** combined AND glyph tester */ + private static class CombinedAndGlyphTester implements GlyphTester { + private GlyphTester[] gta; + private int ngt; + CombinedAndGlyphTester ( GlyphTester[] gta, int ngt ) { + this.gta = gta; + this.ngt = ngt; + } + /** {@inheritDoc} */ + public boolean test ( int gi, int flags ) { + for ( int i = 0, n = ngt; i < n; i++ ) { + GlyphTester gt = gta [ i ]; + if ( gt != null ) { + if ( ! gt.test ( gi, flags ) ) { + return false; + } + } + } + return true; + } + } + + /** NOT glyph tester */ + private static class NotGlyphTester implements GlyphTester { + private GlyphTester gt; + NotGlyphTester ( GlyphTester gt ) { + this.gt = gt; + } + /** {@inheritDoc} */ + public boolean test ( int gi, int flags ) { + if ( gt != null ) { + if ( gt.test ( gi, flags ) ) { + return false; + } + } + return true; + } + } + +} diff --git a/src/java/org/apache/fop/complexscripts/fonts/GlyphSubstitution.java b/src/java/org/apache/fop/complexscripts/fonts/GlyphSubstitution.java new file mode 100644 index 000000000..b8f9d02bf --- /dev/null +++ b/src/java/org/apache/fop/complexscripts/fonts/GlyphSubstitution.java @@ -0,0 +1,41 @@ +/* + * 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.complexscripts.fonts; + +// CSOFF: LineLengthCheck + +/** + * The GlyphSubstitution interface is implemented by a glyph substitution subtable + * that supports the determination of glyph substitution information based on script and + * language of the corresponding character content. + * @author Glenn Adams + */ +public interface GlyphSubstitution { + + /** + * Perform glyph substitution at the current index, mutating the substitution state object as required. + * Only the context associated with the current index is processed. + * @param ss glyph substitution state object + * @return true if the glyph subtable was applied, meaning that the current context matches the + * associated input context glyph coverage table + */ + boolean substitute ( GlyphSubstitutionState ss ); + +} diff --git a/src/java/org/apache/fop/complexscripts/fonts/GlyphSubstitutionState.java b/src/java/org/apache/fop/complexscripts/fonts/GlyphSubstitutionState.java new file mode 100644 index 000000000..4af8c371e --- /dev/null +++ b/src/java/org/apache/fop/complexscripts/fonts/GlyphSubstitutionState.java @@ -0,0 +1,230 @@ +/* + * 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.complexscripts.fonts; + +import java.nio.IntBuffer; +import java.util.ArrayList; +import java.util.List; + +import org.apache.fop.complexscripts.util.GlyphSequence; +import org.apache.fop.complexscripts.util.ScriptContextTester; + +// CSOFF: LineLengthCheck +// CSOFF: NoWhitespaceAfterCheck + +/** + * The GlyphSubstitutionState implements an state object used during glyph substitution + * processing. + * @author Glenn Adams + */ + +public class GlyphSubstitutionState extends GlyphProcessingState { + + /** alternates index */ + private int[] alternatesIndex; + /** current output glyph sequence */ + private IntBuffer ogb; + /** current output glyph to character associations */ + private List oal; + /** character association predications */ + private boolean predications; + + /** + * Construct glyph substitution state. + * @param gs input glyph sequence + * @param script script identifier + * @param language language identifier + * @param feature feature identifier + * @param sct script context tester (or null) + */ + public GlyphSubstitutionState ( GlyphSequence gs, String script, String language, String feature, ScriptContextTester sct ) { + super ( gs, script, language, feature, sct ); + this.ogb = IntBuffer.allocate ( gs.getGlyphCount() ); + this.oal = new ArrayList ( gs.getGlyphCount() ); + this.predications = gs.getPredications(); + } + + /** + * Construct glyph substitution state using an existing state object using shallow copy + * except as follows: input glyph sequence is copied deep except for its characters array. + * @param ss existing positioning state to copy from + */ + public GlyphSubstitutionState ( GlyphSubstitutionState ss ) { + super ( ss ); + this.ogb = IntBuffer.allocate ( indexLast ); + this.oal = new ArrayList ( indexLast ); + } + + /** + * Set alternates indices. + * @param alternates array of alternates indices ordered by coverage index + */ + public void setAlternates ( int[] alternates ) { + this.alternatesIndex = alternates; + } + + /** + * Obtain alternates index associated with specified coverage index. An alternates + * index is used to select among stylistic alternates of a glyph at a particular + * coverage index. This information must be provided by the document itself (in the + * form of an extension attribute value), since a font has no way to determine which + * alternate the user desires. + * @param ci coverage index + * @return an alternates index + */ + public int getAlternatesIndex ( int ci ) { + if ( alternatesIndex == null ) { + return 0; + } else if ( ( ci < 0 ) || ( ci > alternatesIndex.length ) ) { + return 0; + } else { + return alternatesIndex [ ci ]; + } + } + + /** + * Put (write) glyph into glyph output buffer. + * @param glyph to write + * @param a character association that applies to glyph + * @param predication a predication value to add to association A if predications enabled + */ + public void putGlyph ( int glyph, GlyphSequence.CharAssociation a, Object predication ) { + if ( ! ogb.hasRemaining() ) { + ogb = growBuffer ( ogb ); + } + ogb.put ( glyph ); + if ( predications && ( predication != null ) ) { + a.setPredication ( feature, predication ); + } + oal.add ( a ); + } + + /** + * Put (write) array of glyphs into glyph output buffer. + * @param glyphs to write + * @param associations array of character associations that apply to glyphs + * @param predication optional predicaion object to be associated with glyphs' associations + */ + public void putGlyphs ( int[] glyphs, GlyphSequence.CharAssociation[] associations, Object predication ) { + assert glyphs != null; + assert associations != null; + assert associations.length >= glyphs.length; + for ( int i = 0, n = glyphs.length; i < n; i++ ) { + putGlyph ( glyphs [ i ], associations [ i ], predication ); + } + } + + /** + * Obtain output glyph sequence. + * @return newly constructed glyph sequence comprised of original + * characters, output glyphs, and output associations + */ + public GlyphSequence getOutput() { + int position = ogb.position(); + if ( position > 0 ) { + ogb.limit ( position ); + ogb.rewind(); + return new GlyphSequence ( igs.getCharacters(), ogb, oal ); + } else { + return igs; + } + } + + /** + * Apply substitution subtable to current state at current position (only), + * resulting in the consumption of zero or more input glyphs, and possibly + * replacing the current input glyphs starting at the current position, in + * which case it is possible that indexLast is altered to be either less than + * or greater than its value prior to this application. + * @param st the glyph substitution subtable to apply + * @return true if subtable applied, or false if it did not (e.g., its + * input coverage table did not match current input context) + */ + public boolean apply ( GlyphSubstitutionSubtable st ) { + assert st != null; + updateSubtableState ( st ); + boolean applied = st.substitute ( this ); + resetSubtableState(); + return applied; + } + + /** + * Apply a sequence of matched rule lookups to the nig input glyphs + * starting at the current position. If lookups are non-null and non-empty, then + * all input glyphs specified by nig are consumed irregardless of + * whether any specified lookup applied. + * @param lookups array of matched lookups (or null) + * @param nig number of glyphs in input sequence, starting at current position, to which + * the lookups are to apply, and to be consumed once the application has finished + * @return true if lookups are non-null and non-empty; otherwise, false + */ + public boolean apply ( GlyphTable.RuleLookup[] lookups, int nig ) { + // int nbg = index; + int nlg = indexLast - ( index + nig ); + int nog = 0; + if ( ( lookups != null ) && ( lookups.length > 0 ) ) { + // apply each rule lookup to extracted input glyph array + for ( int i = 0, n = lookups.length; i < n; i++ ) { + GlyphTable.RuleLookup l = lookups [ i ]; + if ( l != null ) { + GlyphTable.LookupTable lt = l.getLookup(); + if ( lt != null ) { + // perform substitution on a copy of previous state + GlyphSubstitutionState ss = new GlyphSubstitutionState ( this ); + // apply lookup table substitutions + GlyphSequence gs = lt.substitute ( ss, l.getSequenceIndex() ); + // replace current input sequence starting at current position with result + if ( replaceInput ( 0, -1, gs ) ) { + nog = gs.getGlyphCount() - nlg; + } + } + } + } + // output glyphs and associations + putGlyphs ( getGlyphs ( 0, nog, false, null, null, null ), getAssociations ( 0, nog, false, null, null, null ), null ); + // consume replaced input glyphs + consume ( nog ); + return true; + } else { + return false; + } + } + + /** + * Apply default application semantices; namely, consume one input glyph, + * writing that glyph (and its association) to the output glyphs (and associations). + */ + public void applyDefault() { + super.applyDefault(); + int gi = getGlyph(); + if ( gi != 65535 ) { + putGlyph ( gi, getAssociation(), null ); + } + } + + private static IntBuffer growBuffer ( IntBuffer ib ) { + int capacity = ib.capacity(); + int capacityNew = capacity * 2; + IntBuffer ibNew = IntBuffer.allocate ( capacityNew ); + ib.rewind(); + return ibNew.put ( ib ); + } + +} diff --git a/src/java/org/apache/fop/complexscripts/fonts/GlyphSubstitutionSubtable.java b/src/java/org/apache/fop/complexscripts/fonts/GlyphSubstitutionSubtable.java new file mode 100644 index 000000000..d111b465f --- /dev/null +++ b/src/java/org/apache/fop/complexscripts/fonts/GlyphSubstitutionSubtable.java @@ -0,0 +1,124 @@ +/* + * 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.complexscripts.fonts; + +import org.apache.fop.complexscripts.util.GlyphSequence; +import org.apache.fop.complexscripts.util.ScriptContextTester; + +// CSOFF: LineLengthCheck +// CSOFF: NoWhitespaceAfterCheck + +/** + * The GlyphSubstitutionSubtable implements an abstract base of a glyph substitution subtable, + * providing a default implementation of the GlyphSubstitution interface. + * @author Glenn Adams + */ +public abstract class GlyphSubstitutionSubtable extends GlyphSubtable implements GlyphSubstitution { + + /** + * Instantiate a GlyphSubstitutionSubtable. + * @param id subtable identifier + * @param sequence subtable sequence + * @param flags subtable flags + * @param format subtable format + * @param coverage subtable coverage table + */ + protected GlyphSubstitutionSubtable ( String id, int sequence, int flags, int format, GlyphCoverageTable coverage ) { + super ( id, sequence, flags, format, coverage ); + } + + /** {@inheritDoc} */ + public int getTableType() { + return GlyphTable.GLYPH_TABLE_TYPE_SUBSTITUTION; + } + + /** {@inheritDoc} */ + public String getTypeName() { + return GlyphSubstitutionTable.getLookupTypeName ( getType() ); + } + + /** {@inheritDoc} */ + public boolean isCompatible ( GlyphSubtable subtable ) { + return subtable instanceof GlyphSubstitutionSubtable; + } + + /** {@inheritDoc} */ + public boolean usesReverseScan() { + return false; + } + + /** {@inheritDoc} */ + public boolean substitute ( GlyphSubstitutionState ss ) { + return false; + } + + /** + * Apply substitutions using specified state and subtable array. For each position in input sequence, + * apply subtables in order until some subtable applies or none remain. If no subtable applied or no + * input was consumed for a given position, then apply default action (copy input glyph and advance). + * If sequenceIndex is non-negative, then apply subtables only when current position + * matches sequenceIndex in relation to the starting position. Furthermore, upon + * successful application at sequenceIndex, then apply default action for all remaining + * glyphs in input sequence. + * @param ss substitution state + * @param sta array of subtables to apply + * @param sequenceIndex if non negative, then apply subtables only at specified sequence index + * @return output glyph sequence + */ + public static final GlyphSequence substitute ( GlyphSubstitutionState ss, GlyphSubstitutionSubtable[] sta, int sequenceIndex ) { + int sequenceStart = ss.getPosition(); + boolean appliedOneShot = false; + while ( ss.hasNext() ) { + boolean applied = false; + if ( ! appliedOneShot && ss.maybeApplicable() ) { + for ( int i = 0, n = sta.length; ! applied && ( i < n ); i++ ) { + if ( sequenceIndex < 0 ) { + applied = ss.apply ( sta [ i ] ); + } else if ( ss.getPosition() == ( sequenceStart + sequenceIndex ) ) { + applied = ss.apply ( sta [ i ] ); + if ( applied ) { + appliedOneShot = true; + } + } + } + } + if ( ! applied || ! ss.didConsume() ) { + ss.applyDefault(); + } + ss.next(); + } + return ss.getOutput(); + } + + /** + * Apply substitutions. + * @param gs input glyph sequence + * @param script tag + * @param language tag + * @param feature tag + * @param sta subtable array + * @param sct script context tester + * @return output glyph sequence + */ + public static final GlyphSequence substitute ( GlyphSequence gs, String script, String language, String feature, GlyphSubstitutionSubtable[] sta, ScriptContextTester sct ) { + return substitute ( new GlyphSubstitutionState ( gs, script, language, feature, sct ), sta, -1 ); + } + +} diff --git a/src/java/org/apache/fop/complexscripts/fonts/GlyphSubstitutionTable.java b/src/java/org/apache/fop/complexscripts/fonts/GlyphSubstitutionTable.java new file mode 100644 index 000000000..1b724a63b --- /dev/null +++ b/src/java/org/apache/fop/complexscripts/fonts/GlyphSubstitutionTable.java @@ -0,0 +1,1474 @@ +/* + * 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.complexscripts.fonts; + +import java.nio.CharBuffer; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.apache.fop.complexscripts.scripts.ScriptProcessor; +import org.apache.fop.complexscripts.util.GlyphSequence; +import org.apache.fop.complexscripts.util.GlyphTester; + +// CSOFF: InnerAssignmentCheck +// CSOFF: LineLengthCheck +// CSOFF: NoWhitespaceAfterCheck + +/** + * The GlyphSubstitutionTable class is a glyph table that implements + * GlyphSubstitution functionality. + * @author Glenn Adams + */ +public class GlyphSubstitutionTable extends GlyphTable { + + /** logging instance */ + private static final Log log = LogFactory.getLog(GlyphSubstitutionTable.class); // CSOK: ConstantNameCheck + + /** single substitution subtable type */ + public static final int GSUB_LOOKUP_TYPE_SINGLE = 1; + /** multiple substitution subtable type */ + public static final int GSUB_LOOKUP_TYPE_MULTIPLE = 2; + /** alternate substitution subtable type */ + public static final int GSUB_LOOKUP_TYPE_ALTERNATE = 3; + /** ligature substitution subtable type */ + public static final int GSUB_LOOKUP_TYPE_LIGATURE = 4; + /** contextual substitution subtable type */ + public static final int GSUB_LOOKUP_TYPE_CONTEXTUAL = 5; + /** chained contextual substitution subtable type */ + public static final int GSUB_LOOKUP_TYPE_CHAINED_CONTEXTUAL = 6; + /** extension substitution substitution subtable type */ + public static final int GSUB_LOOKUP_TYPE_EXTENSION_SUBSTITUTION = 7; + /** reverse chained contextual single substitution subtable type */ + public static final int GSUB_LOOKUP_TYPE_REVERSE_CHAINED_SINGLE = 8; + + /** + * Instantiate a GlyphSubstitutionTable object using the specified lookups + * and subtables. + * @param gdef glyph definition table that applies + * @param lookups a map of lookup specifications to subtable identifier strings + * @param subtables a list of identified subtables + */ + public GlyphSubstitutionTable ( GlyphDefinitionTable gdef, Map lookups, List subtables ) { + super ( gdef, lookups ); + if ( ( subtables == null ) || ( subtables.size() == 0 ) ) { + throw new AdvancedTypographicTableFormatException ( "subtables must be non-empty" ); + } else { + for ( Iterator it = subtables.iterator(); it.hasNext();) { + Object o = it.next(); + if ( o instanceof GlyphSubstitutionSubtable ) { + addSubtable ( (GlyphSubtable) o ); + } else { + throw new AdvancedTypographicTableFormatException ( "subtable must be a glyph substitution subtable" ); + } + } + freezeSubtables(); + } + } + + /** + * Perform substitution processing using all matching lookups. + * @param gs an input glyph sequence + * @param script a script identifier + * @param language a language identifier + * @return the substituted (output) glyph sequence + */ + public GlyphSequence substitute ( GlyphSequence gs, String script, String language ) { + GlyphSequence ogs; + Map/*>*/ lookups = matchLookups ( script, language, "*" ); + if ( ( lookups != null ) && ( lookups.size() > 0 ) ) { + ScriptProcessor sp = ScriptProcessor.getInstance ( script ); + ogs = sp.substitute ( this, gs, script, language, lookups ); + } else { + ogs = gs; + } + return ogs; + } + + /** + * Map a lookup type name to its constant (integer) value. + * @param name lookup type name + * @return lookup type + */ + public static int getLookupTypeFromName ( String name ) { + int t; + String s = name.toLowerCase(); + if ( "single".equals ( s ) ) { + t = GSUB_LOOKUP_TYPE_SINGLE; + } else if ( "multiple".equals ( s ) ) { + t = GSUB_LOOKUP_TYPE_MULTIPLE; + } else if ( "alternate".equals ( s ) ) { + t = GSUB_LOOKUP_TYPE_ALTERNATE; + } else if ( "ligature".equals ( s ) ) { + t = GSUB_LOOKUP_TYPE_LIGATURE; + } else if ( "contextual".equals ( s ) ) { + t = GSUB_LOOKUP_TYPE_CONTEXTUAL; + } else if ( "chainedcontextual".equals ( s ) ) { + t = GSUB_LOOKUP_TYPE_CHAINED_CONTEXTUAL; + } else if ( "extensionsubstitution".equals ( s ) ) { + t = GSUB_LOOKUP_TYPE_EXTENSION_SUBSTITUTION; + } else if ( "reversechainiingcontextualsingle".equals ( s ) ) { + t = GSUB_LOOKUP_TYPE_REVERSE_CHAINED_SINGLE; + } else { + t = -1; + } + return t; + } + + /** + * Map a lookup type constant (integer) value to its name. + * @param type lookup type + * @return lookup type name + */ + public static String getLookupTypeName ( int type ) { + String tn = null; + switch ( type ) { + case GSUB_LOOKUP_TYPE_SINGLE: + tn = "single"; + break; + case GSUB_LOOKUP_TYPE_MULTIPLE: + tn = "multiple"; + break; + case GSUB_LOOKUP_TYPE_ALTERNATE: + tn = "alternate"; + break; + case GSUB_LOOKUP_TYPE_LIGATURE: + tn = "ligature"; + break; + case GSUB_LOOKUP_TYPE_CONTEXTUAL: + tn = "contextual"; + break; + case GSUB_LOOKUP_TYPE_CHAINED_CONTEXTUAL: + tn = "chainedcontextual"; + break; + case GSUB_LOOKUP_TYPE_EXTENSION_SUBSTITUTION: + tn = "extensionsubstitution"; + break; + case GSUB_LOOKUP_TYPE_REVERSE_CHAINED_SINGLE: + tn = "reversechainiingcontextualsingle"; + break; + default: + tn = "unknown"; + break; + } + return tn; + } + + /** + * Create a substitution subtable according to the specified arguments. + * @param type subtable type + * @param id subtable identifier + * @param sequence subtable sequence + * @param flags subtable flags + * @param format subtable format + * @param coverage subtable coverage table + * @param entries subtable entries + * @return a glyph subtable instance + */ + public static GlyphSubtable createSubtable ( int type, String id, int sequence, int flags, int format, GlyphCoverageTable coverage, List entries ) { + GlyphSubtable st = null; + switch ( type ) { + case GSUB_LOOKUP_TYPE_SINGLE: + st = SingleSubtable.create ( id, sequence, flags, format, coverage, entries ); + break; + case GSUB_LOOKUP_TYPE_MULTIPLE: + st = MultipleSubtable.create ( id, sequence, flags, format, coverage, entries ); + break; + case GSUB_LOOKUP_TYPE_ALTERNATE: + st = AlternateSubtable.create ( id, sequence, flags, format, coverage, entries ); + break; + case GSUB_LOOKUP_TYPE_LIGATURE: + st = LigatureSubtable.create ( id, sequence, flags, format, coverage, entries ); + break; + case GSUB_LOOKUP_TYPE_CONTEXTUAL: + st = ContextualSubtable.create ( id, sequence, flags, format, coverage, entries ); + break; + case GSUB_LOOKUP_TYPE_CHAINED_CONTEXTUAL: + st = ChainedContextualSubtable.create ( id, sequence, flags, format, coverage, entries ); + break; + case GSUB_LOOKUP_TYPE_REVERSE_CHAINED_SINGLE: + st = ReverseChainedSingleSubtable.create ( id, sequence, flags, format, coverage, entries ); + break; + default: + break; + } + return st; + } + + /** + * Create a substitution subtable according to the specified arguments. + * @param type subtable type + * @param id subtable identifier + * @param sequence subtable sequence + * @param flags subtable flags + * @param format subtable format + * @param coverage list of coverage table entries + * @param entries subtable entries + * @return a glyph subtable instance + */ + public static GlyphSubtable createSubtable ( int type, String id, int sequence, int flags, int format, List coverage, List entries ) { + return createSubtable ( type, id, sequence, flags, format, GlyphCoverageTable.createCoverageTable ( coverage ), entries ); + } + + private abstract static class SingleSubtable extends GlyphSubstitutionSubtable { + SingleSubtable ( String id, int sequence, int flags, int format, GlyphCoverageTable coverage, List entries ) { + super ( id, sequence, flags, format, coverage ); + } + /** {@inheritDoc} */ + public int getType() { + return GSUB_LOOKUP_TYPE_SINGLE; + } + /** {@inheritDoc} */ + public boolean isCompatible ( GlyphSubtable subtable ) { + return subtable instanceof SingleSubtable; + } + /** {@inheritDoc} */ + public boolean substitute ( GlyphSubstitutionState ss ) { + int gi = ss.getGlyph(), ci; + if ( ( ci = getCoverageIndex ( gi ) ) < 0 ) { + return false; + } else { + int go = getGlyphForCoverageIndex ( ci, gi ); + if ( ( go < 0 ) || ( go > 65535 ) ) { + go = 65535; + } + ss.putGlyph ( go, ss.getAssociation(), Boolean.TRUE ); + ss.consume(1); + return true; + } + } + /** + * Obtain glyph for coverage index. + * @param ci coverage index + * @param gi original glyph index + * @return substituted glyph value + * @throws IllegalArgumentException if coverage index is not valid + */ + public abstract int getGlyphForCoverageIndex ( int ci, int gi ) throws IllegalArgumentException; + static GlyphSubstitutionSubtable create ( String id, int sequence, int flags, int format, GlyphCoverageTable coverage, List entries ) { + if ( format == 1 ) { + return new SingleSubtableFormat1 ( id, sequence, flags, format, coverage, entries ); + } else if ( format == 2 ) { + return new SingleSubtableFormat2 ( id, sequence, flags, format, coverage, entries ); + } else { + throw new UnsupportedOperationException(); + } + } + } + + private static class SingleSubtableFormat1 extends SingleSubtable { + private int delta; + private int ciMax; + SingleSubtableFormat1 ( String id, int sequence, int flags, int format, GlyphCoverageTable coverage, List entries ) { + super ( id, sequence, flags, format, coverage, entries ); + populate ( entries ); + } + /** {@inheritDoc} */ + public List getEntries() { + List entries = new ArrayList ( 1 ); + entries.add ( Integer.valueOf ( delta ) ); + return entries; + } + /** {@inheritDoc} */ + public int getGlyphForCoverageIndex ( int ci, int gi ) throws IllegalArgumentException { + if ( ci <= ciMax ) { + return gi + delta; + } else { + throw new IllegalArgumentException ( "coverage index " + ci + " out of range, maximum coverage index is " + ciMax ); + } + } + private void populate ( List entries ) { + if ( ( entries == null ) || ( entries.size() != 1 ) ) { + throw new AdvancedTypographicTableFormatException ( "illegal entries, must be non-null and contain exactly one entry" ); + } else { + Object o = entries.get(0); + int delta = 0; + if ( o instanceof Integer ) { + delta = ( (Integer) o ) . intValue(); + } else { + throw new AdvancedTypographicTableFormatException ( "illegal entries entry, must be Integer, but is: " + o ); + } + this.delta = delta; + this.ciMax = getCoverageSize() - 1; + } + } + } + + private static class SingleSubtableFormat2 extends SingleSubtable { + private int[] glyphs; + SingleSubtableFormat2 ( String id, int sequence, int flags, int format, GlyphCoverageTable coverage, List entries ) { + super ( id, sequence, flags, format, coverage, entries ); + populate ( entries ); + } + /** {@inheritDoc} */ + public List getEntries() { + List entries = new ArrayList ( glyphs.length ); + for ( int i = 0, n = glyphs.length; i < n; i++ ) { + entries.add ( Integer.valueOf ( glyphs[i] ) ); + } + return entries; + } + /** {@inheritDoc} */ + public int getGlyphForCoverageIndex ( int ci, int gi ) throws IllegalArgumentException { + if ( glyphs == null ) { + return -1; + } else if ( ci >= glyphs.length ) { + throw new IllegalArgumentException ( "coverage index " + ci + " out of range, maximum coverage index is " + glyphs.length ); + } else { + return glyphs [ ci ]; + } + } + private void populate ( List entries ) { + int i = 0, n = entries.size(); + int[] glyphs = new int [ n ]; + for ( Iterator it = entries.iterator(); it.hasNext();) { + Object o = it.next(); + if ( o instanceof Integer ) { + int gid = ( (Integer) o ) .intValue(); + if ( ( gid >= 0 ) && ( gid < 65536 ) ) { + glyphs [ i++ ] = gid; + } else { + throw new AdvancedTypographicTableFormatException ( "illegal glyph index: " + gid ); + } + } else { + throw new AdvancedTypographicTableFormatException ( "illegal entries entry, must be Integer: " + o ); + } + } + assert i == n; + assert this.glyphs == null; + this.glyphs = glyphs; + } + } + + private abstract static class MultipleSubtable extends GlyphSubstitutionSubtable { + public MultipleSubtable ( String id, int sequence, int flags, int format, GlyphCoverageTable coverage, List entries ) { + super ( id, sequence, flags, format, coverage ); + } + /** {@inheritDoc} */ + public int getType() { + return GSUB_LOOKUP_TYPE_MULTIPLE; + } + /** {@inheritDoc} */ + public boolean isCompatible ( GlyphSubtable subtable ) { + return subtable instanceof MultipleSubtable; + } + /** {@inheritDoc} */ + public boolean substitute ( GlyphSubstitutionState ss ) { + int gi = ss.getGlyph(), ci; + if ( ( ci = getCoverageIndex ( gi ) ) < 0 ) { + return false; + } else { + int[] ga = getGlyphsForCoverageIndex ( ci, gi ); + if ( ga != null ) { + ss.putGlyphs ( ga, GlyphSequence.CharAssociation.replicate ( ss.getAssociation(), ga.length ), Boolean.TRUE ); + ss.consume(1); + } + return true; + } + } + /** + * Obtain glyph sequence for coverage index. + * @param ci coverage index + * @param gi original glyph index + * @return sequence of glyphs to substitute for input glyph + * @throws IllegalArgumentException if coverage index is not valid + */ + public abstract int[] getGlyphsForCoverageIndex ( int ci, int gi ) throws IllegalArgumentException; + static GlyphSubstitutionSubtable create ( String id, int sequence, int flags, int format, GlyphCoverageTable coverage, List entries ) { + if ( format == 1 ) { + return new MultipleSubtableFormat1 ( id, sequence, flags, format, coverage, entries ); + } else { + throw new UnsupportedOperationException(); + } + } + } + + private static class MultipleSubtableFormat1 extends MultipleSubtable { + private int[][] gsa; // glyph sequence array, ordered by coverage index + MultipleSubtableFormat1 ( String id, int sequence, int flags, int format, GlyphCoverageTable coverage, List entries ) { + super ( id, sequence, flags, format, coverage, entries ); + populate ( entries ); + } + /** {@inheritDoc} */ + public List getEntries() { + if ( gsa != null ) { + List entries = new ArrayList ( 1 ); + entries.add ( gsa ); + return entries; + } else { + return null; + } + } + /** {@inheritDoc} */ + public int[] getGlyphsForCoverageIndex ( int ci, int gi ) throws IllegalArgumentException { + if ( gsa == null ) { + return null; + } else if ( ci >= gsa.length ) { + throw new IllegalArgumentException ( "coverage index " + ci + " out of range, maximum coverage index is " + gsa.length ); + } else { + return gsa [ ci ]; + } + } + private void populate ( List entries ) { + if ( entries == null ) { + throw new AdvancedTypographicTableFormatException ( "illegal entries, must be non-null" ); + } else if ( entries.size() != 1 ) { + throw new AdvancedTypographicTableFormatException ( "illegal entries, " + entries.size() + " entries present, but requires 1 entry" ); + } else { + Object o; + if ( ( ( o = entries.get(0) ) == null ) || ! ( o instanceof int[][] ) ) { + throw new AdvancedTypographicTableFormatException ( "illegal entries, first entry must be an int[][], but is: " + ( ( o != null ) ? o.getClass() : null ) ); + } else { + gsa = (int[][]) o; + } + } + } + } + + private abstract static class AlternateSubtable extends GlyphSubstitutionSubtable { + public AlternateSubtable ( String id, int sequence, int flags, int format, GlyphCoverageTable coverage, List entries ) { + super ( id, sequence, flags, format, coverage ); + } + /** {@inheritDoc} */ + public int getType() { + return GSUB_LOOKUP_TYPE_ALTERNATE; + } + /** {@inheritDoc} */ + public boolean isCompatible ( GlyphSubtable subtable ) { + return subtable instanceof AlternateSubtable; + } + /** {@inheritDoc} */ + public boolean substitute ( GlyphSubstitutionState ss ) { + int gi = ss.getGlyph(), ci; + if ( ( ci = getCoverageIndex ( gi ) ) < 0 ) { + return false; + } else { + int[] ga = getAlternatesForCoverageIndex ( ci, gi ); + int ai = ss.getAlternatesIndex ( ci ); + int go; + if ( ( ai < 0 ) || ( ai >= ga.length ) ) { + go = gi; + } else { + go = ga [ ai ]; + } + if ( ( go < 0 ) || ( go > 65535 ) ) { + go = 65535; + } + ss.putGlyph ( go, ss.getAssociation(), Boolean.TRUE ); + ss.consume(1); + return true; + } + } + /** + * Obtain glyph alternates for coverage index. + * @param ci coverage index + * @param gi original glyph index + * @return sequence of glyphs to substitute for input glyph + * @throws IllegalArgumentException if coverage index is not valid + */ + public abstract int[] getAlternatesForCoverageIndex ( int ci, int gi ) throws IllegalArgumentException; + static GlyphSubstitutionSubtable create ( String id, int sequence, int flags, int format, GlyphCoverageTable coverage, List entries ) { + if ( format == 1 ) { + return new AlternateSubtableFormat1 ( id, sequence, flags, format, coverage, entries ); + } else { + throw new UnsupportedOperationException(); + } + } + } + + private static class AlternateSubtableFormat1 extends AlternateSubtable { + private int[][] gaa; // glyph alternates array, ordered by coverage index + AlternateSubtableFormat1 ( String id, int sequence, int flags, int format, GlyphCoverageTable coverage, List entries ) { + super ( id, sequence, flags, format, coverage, entries ); + populate ( entries ); + } + /** {@inheritDoc} */ + public List getEntries() { + List entries = new ArrayList ( gaa.length ); + for ( int i = 0, n = gaa.length; i < n; i++ ) { + entries.add ( gaa[i] ); + } + return entries; + } + /** {@inheritDoc} */ + public int[] getAlternatesForCoverageIndex ( int ci, int gi ) throws IllegalArgumentException { + if ( gaa == null ) { + return null; + } else if ( ci >= gaa.length ) { + throw new IllegalArgumentException ( "coverage index " + ci + " out of range, maximum coverage index is " + gaa.length ); + } else { + return gaa [ ci ]; + } + } + private void populate ( List entries ) { + int i = 0, n = entries.size(); + int[][] gaa = new int [ n ][]; + for ( Iterator it = entries.iterator(); it.hasNext();) { + Object o = it.next(); + if ( o instanceof int[] ) { + gaa [ i++ ] = (int[]) o; + } else { + throw new AdvancedTypographicTableFormatException ( "illegal entries entry, must be int[]: " + o ); + } + } + assert i == n; + assert this.gaa == null; + this.gaa = gaa; + } + } + + private abstract static class LigatureSubtable extends GlyphSubstitutionSubtable { + public LigatureSubtable ( String id, int sequence, int flags, int format, GlyphCoverageTable coverage, List entries ) { + super ( id, sequence, flags, format, coverage ); + } + /** {@inheritDoc} */ + public int getType() { + return GSUB_LOOKUP_TYPE_LIGATURE; + } + /** {@inheritDoc} */ + public boolean isCompatible ( GlyphSubtable subtable ) { + return subtable instanceof LigatureSubtable; + } + /** {@inheritDoc} */ + public boolean substitute ( GlyphSubstitutionState ss ) { + int gi = ss.getGlyph(), ci; + if ( ( ci = getCoverageIndex ( gi ) ) < 0 ) { + return false; + } else { + LigatureSet ls = getLigatureSetForCoverageIndex ( ci, gi ); + if ( ls != null ) { + boolean reverse = false; + GlyphTester ignores = ss.getIgnoreDefault(); + int[] counts = ss.getGlyphsAvailable ( 0, reverse, ignores ); + int nga = counts[0], ngi; + if ( nga > 1 ) { + int[] iga = ss.getGlyphs ( 0, nga, reverse, ignores, null, counts ); + Ligature l = findLigature ( ls, iga ); + if ( l != null ) { + int go = l.getLigature(); + if ( ( go < 0 ) || ( go > 65535 ) ) { + go = 65535; + } + int nmg = 1 + l.getNumComponents(); + // fetch matched number of component glyphs to determine matched and ignored count + ss.getGlyphs ( 0, nmg, reverse, ignores, null, counts ); + nga = counts[0]; + ngi = counts[1]; + // fetch associations of matched component glyphs + GlyphSequence.CharAssociation[] laa = ss.getAssociations ( 0, nga ); + // output ligature glyph and its association + ss.putGlyph ( go, GlyphSequence.CharAssociation.join ( laa ), Boolean.TRUE ); + // fetch and output ignored glyphs (if necessary) + if ( ngi > 0 ) { + ss.putGlyphs ( ss.getIgnoredGlyphs ( 0, ngi ), ss.getIgnoredAssociations ( 0, ngi ), null ); + } + ss.consume ( nga + ngi ); + } + } + } + return true; + } + } + private Ligature findLigature ( LigatureSet ls, int[] glyphs ) { + Ligature[] la = ls.getLigatures(); + int k = -1; + int maxComponents = -1; + for ( int i = 0, n = la.length; i < n; i++ ) { + Ligature l = la [ i ]; + if ( l.matchesComponents ( glyphs ) ) { + int nc = l.getNumComponents(); + if ( nc > maxComponents ) { + maxComponents = nc; + k = i; + } + } + } + if ( k >= 0 ) { + return la [ k ]; + } else { + return null; + } + } + /** + * Obtain ligature set for coverage index. + * @param ci coverage index + * @param gi original glyph index + * @return ligature set (or null if none defined) + * @throws IllegalArgumentException if coverage index is not valid + */ + public abstract LigatureSet getLigatureSetForCoverageIndex ( int ci, int gi ) throws IllegalArgumentException; + static GlyphSubstitutionSubtable create ( String id, int sequence, int flags, int format, GlyphCoverageTable coverage, List entries ) { + if ( format == 1 ) { + return new LigatureSubtableFormat1 ( id, sequence, flags, format, coverage, entries ); + } else { + throw new UnsupportedOperationException(); + } + } + } + + private static class LigatureSubtableFormat1 extends LigatureSubtable { + private LigatureSet[] ligatureSets; + public LigatureSubtableFormat1 ( String id, int sequence, int flags, int format, GlyphCoverageTable coverage, List entries ) { + super ( id, sequence, flags, format, coverage, entries ); + populate ( entries ); + } + /** {@inheritDoc} */ + public List getEntries() { + List entries = new ArrayList ( ligatureSets.length ); + for ( int i = 0, n = ligatureSets.length; i < n; i++ ) { + entries.add ( ligatureSets[i] ); + } + return entries; + } + /** {@inheritDoc} */ + public LigatureSet getLigatureSetForCoverageIndex ( int ci, int gi ) throws IllegalArgumentException { + if ( ligatureSets == null ) { + return null; + } else if ( ci >= ligatureSets.length ) { + throw new IllegalArgumentException ( "coverage index " + ci + " out of range, maximum coverage index is " + ligatureSets.length ); + } else { + return ligatureSets [ ci ]; + } + } + private void populate ( List entries ) { + int i = 0, n = entries.size(); + LigatureSet[] ligatureSets = new LigatureSet [ n ]; + for ( Iterator it = entries.iterator(); it.hasNext();) { + Object o = it.next(); + if ( o instanceof LigatureSet ) { + ligatureSets [ i++ ] = (LigatureSet) o; + } else { + throw new AdvancedTypographicTableFormatException ( "illegal ligatures entry, must be LigatureSet: " + o ); + } + } + assert i == n; + assert this.ligatureSets == null; + this.ligatureSets = ligatureSets; + } + } + + private abstract static class ContextualSubtable extends GlyphSubstitutionSubtable { + public ContextualSubtable ( String id, int sequence, int flags, int format, GlyphCoverageTable coverage, List entries ) { + super ( id, sequence, flags, format, coverage ); + } + /** {@inheritDoc} */ + public int getType() { + return GSUB_LOOKUP_TYPE_CONTEXTUAL; + } + /** {@inheritDoc} */ + public boolean isCompatible ( GlyphSubtable subtable ) { + return subtable instanceof ContextualSubtable; + } + /** {@inheritDoc} */ + public boolean substitute ( GlyphSubstitutionState ss ) { + int gi = ss.getGlyph(), ci; + if ( ( ci = getCoverageIndex ( gi ) ) < 0 ) { + return false; + } else { + int[] rv = new int[1]; + RuleLookup[] la = getLookups ( ci, gi, ss, rv ); + if ( la != null ) { + ss.apply ( la, rv[0] ); + } + return true; + } + } + /** + * Obtain rule lookups set associated current input glyph context. + * @param ci coverage index of glyph at current position + * @param gi glyph index of glyph at current position + * @param ss glyph substitution state + * @param rv array of ints used to receive multiple return values, must be of length 1 or greater, + * where the first entry is used to return the input sequence length of the matched rule + * @return array of rule lookups or null if none applies + */ + public abstract RuleLookup[] getLookups ( int ci, int gi, GlyphSubstitutionState ss, int[] rv ); + static GlyphSubstitutionSubtable create ( String id, int sequence, int flags, int format, GlyphCoverageTable coverage, List entries ) { + if ( format == 1 ) { + return new ContextualSubtableFormat1 ( id, sequence, flags, format, coverage, entries ); + } else if ( format == 2 ) { + return new ContextualSubtableFormat2 ( id, sequence, flags, format, coverage, entries ); + } else if ( format == 3 ) { + return new ContextualSubtableFormat3 ( id, sequence, flags, format, coverage, entries ); + } else { + throw new UnsupportedOperationException(); + } + } + } + + private static class ContextualSubtableFormat1 extends ContextualSubtable { + private RuleSet[] rsa; // rule set array, ordered by glyph coverage index + ContextualSubtableFormat1 ( String id, int sequence, int flags, int format, GlyphCoverageTable coverage, List entries ) { + super ( id, sequence, flags, format, coverage, entries ); + populate ( entries ); + } + /** {@inheritDoc} */ + public List getEntries() { + if ( rsa != null ) { + List entries = new ArrayList ( 1 ); + entries.add ( rsa ); + return entries; + } else { + return null; + } + } + /** {@inheritDoc} */ + public void resolveLookupReferences ( Map/**/ lookupTables ) { + GlyphTable.resolveLookupReferences ( rsa, lookupTables ); + } + /** {@inheritDoc} */ + public RuleLookup[] getLookups ( int ci, int gi, GlyphSubstitutionState ss, int[] rv ) { + assert ss != null; + assert ( rv != null ) && ( rv.length > 0 ); + assert rsa != null; + if ( rsa.length > 0 ) { + RuleSet rs = rsa [ 0 ]; + if ( rs != null ) { + Rule[] ra = rs.getRules(); + for ( int i = 0, n = ra.length; i < n; i++ ) { + Rule r = ra [ i ]; + if ( ( r != null ) && ( r instanceof ChainedGlyphSequenceRule ) ) { + ChainedGlyphSequenceRule cr = (ChainedGlyphSequenceRule) r; + int[] iga = cr.getGlyphs ( gi ); + if ( matches ( ss, iga, 0, rv ) ) { + return r.getLookups(); + } + } + } + } + } + return null; + } + static boolean matches ( GlyphSubstitutionState ss, int[] glyphs, int offset, int[] rv ) { + if ( ( glyphs == null ) || ( glyphs.length == 0 ) ) { + return true; // match null or empty glyph sequence + } else { + boolean reverse = offset < 0; + GlyphTester ignores = ss.getIgnoreDefault(); + int[] counts = ss.getGlyphsAvailable ( offset, reverse, ignores ); + int nga = counts[0]; + int ngm = glyphs.length; + if ( nga < ngm ) { + return false; // insufficient glyphs available to match + } else { + int[] ga = ss.getGlyphs ( offset, ngm, reverse, ignores, null, counts ); + for ( int k = 0; k < ngm; k++ ) { + if ( ga [ k ] != glyphs [ k ] ) { + return false; // match fails at ga [ k ] + } + } + if ( rv != null ) { + rv[0] = counts[0] + counts[1]; + } + return true; // all glyphs match + } + } + } + private void populate ( List entries ) { + if ( entries == null ) { + throw new AdvancedTypographicTableFormatException ( "illegal entries, must be non-null" ); + } else if ( entries.size() != 1 ) { + throw new AdvancedTypographicTableFormatException ( "illegal entries, " + entries.size() + " entries present, but requires 1 entry" ); + } else { + Object o; + if ( ( ( o = entries.get(0) ) == null ) || ! ( o instanceof RuleSet[] ) ) { + throw new AdvancedTypographicTableFormatException ( "illegal entries, first entry must be an RuleSet[], but is: " + ( ( o != null ) ? o.getClass() : null ) ); + } else { + rsa = (RuleSet[]) o; + } + } + } + } + + private static class ContextualSubtableFormat2 extends ContextualSubtable { + private GlyphClassTable cdt; // class def table + private int ngc; // class set count + private RuleSet[] rsa; // rule set array, ordered by class number [0...ngc - 1] + ContextualSubtableFormat2 ( String id, int sequence, int flags, int format, GlyphCoverageTable coverage, List entries ) { + super ( id, sequence, flags, format, coverage, entries ); + populate ( entries ); + } + /** {@inheritDoc} */ + public List getEntries() { + if ( rsa != null ) { + List entries = new ArrayList ( 3 ); + entries.add ( cdt ); + entries.add ( Integer.valueOf ( ngc ) ); + entries.add ( rsa ); + return entries; + } else { + return null; + } + } + /** {@inheritDoc} */ + public void resolveLookupReferences ( Map/**/ lookupTables ) { + GlyphTable.resolveLookupReferences ( rsa, lookupTables ); + } + /** {@inheritDoc} */ + public RuleLookup[] getLookups ( int ci, int gi, GlyphSubstitutionState ss, int[] rv ) { + assert ss != null; + assert ( rv != null ) && ( rv.length > 0 ); + assert rsa != null; + if ( rsa.length > 0 ) { + RuleSet rs = rsa [ 0 ]; + if ( rs != null ) { + Rule[] ra = rs.getRules(); + for ( int i = 0, n = ra.length; i < n; i++ ) { + Rule r = ra [ i ]; + if ( ( r != null ) && ( r instanceof ChainedClassSequenceRule ) ) { + ChainedClassSequenceRule cr = (ChainedClassSequenceRule) r; + int[] ca = cr.getClasses ( cdt.getClassIndex ( gi, ss.getClassMatchSet ( gi ) ) ); + if ( matches ( ss, cdt, ca, 0, rv ) ) { + return r.getLookups(); + } + } + } + } + } + return null; + } + static boolean matches ( GlyphSubstitutionState ss, GlyphClassTable cdt, int[] classes, int offset, int[] rv ) { + if ( ( cdt == null ) || ( classes == null ) || ( classes.length == 0 ) ) { + return true; // match null class definitions, null or empty class sequence + } else { + boolean reverse = offset < 0; + GlyphTester ignores = ss.getIgnoreDefault(); + int[] counts = ss.getGlyphsAvailable ( offset, reverse, ignores ); + int nga = counts[0]; + int ngm = classes.length; + if ( nga < ngm ) { + return false; // insufficient glyphs available to match + } else { + int[] ga = ss.getGlyphs ( offset, ngm, reverse, ignores, null, counts ); + for ( int k = 0; k < ngm; k++ ) { + int gi = ga [ k ]; + int ms = ss.getClassMatchSet ( gi ); + int gc = cdt.getClassIndex ( gi, ms ); + if ( ( gc < 0 ) || ( gc >= cdt.getClassSize ( ms ) ) ) { + return false; // none or invalid class fails mat ch + } else if ( gc != classes [ k ] ) { + return false; // match fails at ga [ k ] + } + } + if ( rv != null ) { + rv[0] = counts[0] + counts[1]; + } + return true; // all glyphs match + } + } + } + private void populate ( List entries ) { + if ( entries == null ) { + throw new AdvancedTypographicTableFormatException ( "illegal entries, must be non-null" ); + } else if ( entries.size() != 3 ) { + throw new AdvancedTypographicTableFormatException ( "illegal entries, " + entries.size() + " entries present, but requires 3 entries" ); + } else { + Object o; + if ( ( ( o = entries.get(0) ) == null ) || ! ( o instanceof GlyphClassTable ) ) { + throw new AdvancedTypographicTableFormatException ( "illegal entries, first entry must be an GlyphClassTable, but is: " + ( ( o != null ) ? o.getClass() : null ) ); + } else { + cdt = (GlyphClassTable) o; + } + if ( ( ( o = entries.get(1) ) == null ) || ! ( o instanceof Integer ) ) { + throw new AdvancedTypographicTableFormatException ( "illegal entries, second entry must be an Integer, but is: " + ( ( o != null ) ? o.getClass() : null ) ); + } else { + ngc = ((Integer)(o)).intValue(); + } + if ( ( ( o = entries.get(2) ) == null ) || ! ( o instanceof RuleSet[] ) ) { + throw new AdvancedTypographicTableFormatException ( "illegal entries, third entry must be an RuleSet[], but is: " + ( ( o != null ) ? o.getClass() : null ) ); + } else { + rsa = (RuleSet[]) o; + if ( rsa.length != ngc ) { + throw new AdvancedTypographicTableFormatException ( "illegal entries, RuleSet[] length is " + rsa.length + ", but expected " + ngc + " glyph classes" ); + } + } + } + } + } + + private static class ContextualSubtableFormat3 extends ContextualSubtable { + private RuleSet[] rsa; // rule set array, containing a single rule set + ContextualSubtableFormat3 ( String id, int sequence, int flags, int format, GlyphCoverageTable coverage, List entries ) { + super ( id, sequence, flags, format, coverage, entries ); + populate ( entries ); + } + /** {@inheritDoc} */ + public List getEntries() { + if ( rsa != null ) { + List entries = new ArrayList ( 1 ); + entries.add ( rsa ); + return entries; + } else { + return null; + } + } + /** {@inheritDoc} */ + public void resolveLookupReferences ( Map/**/ lookupTables ) { + GlyphTable.resolveLookupReferences ( rsa, lookupTables ); + } + /** {@inheritDoc} */ + public RuleLookup[] getLookups ( int ci, int gi, GlyphSubstitutionState ss, int[] rv ) { + assert ss != null; + assert ( rv != null ) && ( rv.length > 0 ); + assert rsa != null; + if ( rsa.length > 0 ) { + RuleSet rs = rsa [ 0 ]; + if ( rs != null ) { + Rule[] ra = rs.getRules(); + for ( int i = 0, n = ra.length; i < n; i++ ) { + Rule r = ra [ i ]; + if ( ( r != null ) && ( r instanceof ChainedCoverageSequenceRule ) ) { + ChainedCoverageSequenceRule cr = (ChainedCoverageSequenceRule) r; + GlyphCoverageTable[] gca = cr.getCoverages(); + if ( matches ( ss, gca, 0, rv ) ) { + return r.getLookups(); + } + } + } + } + } + return null; + } + static boolean matches ( GlyphSubstitutionState ss, GlyphCoverageTable[] gca, int offset, int[] rv ) { + if ( ( gca == null ) || ( gca.length == 0 ) ) { + return true; // match null or empty coverage array + } else { + boolean reverse = offset < 0; + GlyphTester ignores = ss.getIgnoreDefault(); + int[] counts = ss.getGlyphsAvailable ( offset, reverse, ignores ); + int nga = counts[0]; + int ngm = gca.length; + if ( nga < ngm ) { + return false; // insufficient glyphs available to match + } else { + int[] ga = ss.getGlyphs ( offset, ngm, reverse, ignores, null, counts ); + for ( int k = 0; k < ngm; k++ ) { + GlyphCoverageTable ct = gca [ k ]; + if ( ct != null ) { + if ( ct.getCoverageIndex ( ga [ k ] ) < 0 ) { + return false; // match fails at ga [ k ] + } + } + } + if ( rv != null ) { + rv[0] = counts[0] + counts[1]; + } + return true; // all glyphs match + } + } + } + private void populate ( List entries ) { + if ( entries == null ) { + throw new AdvancedTypographicTableFormatException ( "illegal entries, must be non-null" ); + } else if ( entries.size() != 1 ) { + throw new AdvancedTypographicTableFormatException ( "illegal entries, " + entries.size() + " entries present, but requires 1 entry" ); + } else { + Object o; + if ( ( ( o = entries.get(0) ) == null ) || ! ( o instanceof RuleSet[] ) ) { + throw new AdvancedTypographicTableFormatException ( "illegal entries, first entry must be an RuleSet[], but is: " + ( ( o != null ) ? o.getClass() : null ) ); + } else { + rsa = (RuleSet[]) o; + } + } + } + } + + private abstract static class ChainedContextualSubtable extends GlyphSubstitutionSubtable { + public ChainedContextualSubtable ( String id, int sequence, int flags, int format, GlyphCoverageTable coverage, List entries ) { + super ( id, sequence, flags, format, coverage ); + } + /** {@inheritDoc} */ + public int getType() { + return GSUB_LOOKUP_TYPE_CHAINED_CONTEXTUAL; + } + /** {@inheritDoc} */ + public boolean isCompatible ( GlyphSubtable subtable ) { + return subtable instanceof ChainedContextualSubtable; + } + /** {@inheritDoc} */ + public boolean substitute ( GlyphSubstitutionState ss ) { + int gi = ss.getGlyph(), ci; + if ( ( ci = getCoverageIndex ( gi ) ) < 0 ) { + return false; + } else { + int[] rv = new int[1]; + RuleLookup[] la = getLookups ( ci, gi, ss, rv ); + if ( la != null ) { + ss.apply ( la, rv[0] ); + return true; + } else { + return false; + } + } + } + /** + * Obtain rule lookups set associated current input glyph context. + * @param ci coverage index of glyph at current position + * @param gi glyph index of glyph at current position + * @param ss glyph substitution state + * @param rv array of ints used to receive multiple return values, must be of length 1 or greater + * @return array of rule lookups or null if none applies + */ + public abstract RuleLookup[] getLookups ( int ci, int gi, GlyphSubstitutionState ss, int[] rv ); + static GlyphSubstitutionSubtable create ( String id, int sequence, int flags, int format, GlyphCoverageTable coverage, List entries ) { + if ( format == 1 ) { + return new ChainedContextualSubtableFormat1 ( id, sequence, flags, format, coverage, entries ); + } else if ( format == 2 ) { + return new ChainedContextualSubtableFormat2 ( id, sequence, flags, format, coverage, entries ); + } else if ( format == 3 ) { + return new ChainedContextualSubtableFormat3 ( id, sequence, flags, format, coverage, entries ); + } else { + throw new UnsupportedOperationException(); + } + } + } + + private static class ChainedContextualSubtableFormat1 extends ChainedContextualSubtable { + private RuleSet[] rsa; // rule set array, ordered by glyph coverage index + ChainedContextualSubtableFormat1 ( String id, int sequence, int flags, int format, GlyphCoverageTable coverage, List entries ) { + super ( id, sequence, flags, format, coverage, entries ); + populate ( entries ); + } + /** {@inheritDoc} */ + public List getEntries() { + if ( rsa != null ) { + List entries = new ArrayList ( 1 ); + entries.add ( rsa ); + return entries; + } else { + return null; + } + } + /** {@inheritDoc} */ + public void resolveLookupReferences ( Map/**/ lookupTables ) { + GlyphTable.resolveLookupReferences ( rsa, lookupTables ); + } + /** {@inheritDoc} */ + public RuleLookup[] getLookups ( int ci, int gi, GlyphSubstitutionState ss, int[] rv ) { + assert ss != null; + assert ( rv != null ) && ( rv.length > 0 ); + assert rsa != null; + if ( rsa.length > 0 ) { + RuleSet rs = rsa [ 0 ]; + if ( rs != null ) { + Rule[] ra = rs.getRules(); + for ( int i = 0, n = ra.length; i < n; i++ ) { + Rule r = ra [ i ]; + if ( ( r != null ) && ( r instanceof ChainedGlyphSequenceRule ) ) { + ChainedGlyphSequenceRule cr = (ChainedGlyphSequenceRule) r; + int[] iga = cr.getGlyphs ( gi ); + if ( matches ( ss, iga, 0, rv ) ) { + int[] bga = cr.getBacktrackGlyphs(); + if ( matches ( ss, bga, -1, null ) ) { + int[] lga = cr.getLookaheadGlyphs(); + if ( matches ( ss, lga, rv[0], null ) ) { + return r.getLookups(); + } + } + } + } + } + } + } + return null; + } + private boolean matches ( GlyphSubstitutionState ss, int[] glyphs, int offset, int[] rv ) { + return ContextualSubtableFormat1.matches ( ss, glyphs, offset, rv ); + } + private void populate ( List entries ) { + if ( entries == null ) { + throw new AdvancedTypographicTableFormatException ( "illegal entries, must be non-null" ); + } else if ( entries.size() != 1 ) { + throw new AdvancedTypographicTableFormatException ( "illegal entries, " + entries.size() + " entries present, but requires 1 entry" ); + } else { + Object o; + if ( ( ( o = entries.get(0) ) == null ) || ! ( o instanceof RuleSet[] ) ) { + throw new AdvancedTypographicTableFormatException ( "illegal entries, first entry must be an RuleSet[], but is: " + ( ( o != null ) ? o.getClass() : null ) ); + } else { + rsa = (RuleSet[]) o; + } + } + } + } + + private static class ChainedContextualSubtableFormat2 extends ChainedContextualSubtable { + private GlyphClassTable icdt; // input class def table + private GlyphClassTable bcdt; // backtrack class def table + private GlyphClassTable lcdt; // lookahead class def table + private int ngc; // class set count + private RuleSet[] rsa; // rule set array, ordered by class number [0...ngc - 1] + ChainedContextualSubtableFormat2 ( String id, int sequence, int flags, int format, GlyphCoverageTable coverage, List entries ) { + super ( id, sequence, flags, format, coverage, entries ); + populate ( entries ); + } + /** {@inheritDoc} */ + public List getEntries() { + if ( rsa != null ) { + List entries = new ArrayList ( 5 ); + entries.add ( icdt ); + entries.add ( bcdt ); + entries.add ( lcdt ); + entries.add ( Integer.valueOf ( ngc ) ); + entries.add ( rsa ); + return entries; + } else { + return null; + } + } + /** {@inheritDoc} */ + public RuleLookup[] getLookups ( int ci, int gi, GlyphSubstitutionState ss, int[] rv ) { + assert ss != null; + assert ( rv != null ) && ( rv.length > 0 ); + assert rsa != null; + if ( rsa.length > 0 ) { + RuleSet rs = rsa [ 0 ]; + if ( rs != null ) { + Rule[] ra = rs.getRules(); + for ( int i = 0, n = ra.length; i < n; i++ ) { + Rule r = ra [ i ]; + if ( ( r != null ) && ( r instanceof ChainedClassSequenceRule ) ) { + ChainedClassSequenceRule cr = (ChainedClassSequenceRule) r; + int[] ica = cr.getClasses ( icdt.getClassIndex ( gi, ss.getClassMatchSet ( gi ) ) ); + if ( matches ( ss, icdt, ica, 0, rv ) ) { + int[] bca = cr.getBacktrackClasses(); + if ( matches ( ss, bcdt, bca, -1, null ) ) { + int[] lca = cr.getLookaheadClasses(); + if ( matches ( ss, lcdt, lca, rv[0], null ) ) { + return r.getLookups(); + } + } + } + } + } + } + } + return null; + } + private boolean matches ( GlyphSubstitutionState ss, GlyphClassTable cdt, int[] classes, int offset, int[] rv ) { + return ContextualSubtableFormat2.matches ( ss, cdt, classes, offset, rv ); + } + /** {@inheritDoc} */ + public void resolveLookupReferences ( Map/**/ lookupTables ) { + GlyphTable.resolveLookupReferences ( rsa, lookupTables ); + } + private void populate ( List entries ) { + if ( entries == null ) { + throw new AdvancedTypographicTableFormatException ( "illegal entries, must be non-null" ); + } else if ( entries.size() != 5 ) { + throw new AdvancedTypographicTableFormatException ( "illegal entries, " + entries.size() + " entries present, but requires 5 entries" ); + } else { + Object o; + if ( ( ( o = entries.get(0) ) == null ) || ! ( o instanceof GlyphClassTable ) ) { + throw new AdvancedTypographicTableFormatException ( "illegal entries, first entry must be an GlyphClassTable, but is: " + ( ( o != null ) ? o.getClass() : null ) ); + } else { + icdt = (GlyphClassTable) o; + } + if ( ( ( o = entries.get(1) ) != null ) && ! ( o instanceof GlyphClassTable ) ) { + throw new AdvancedTypographicTableFormatException ( "illegal entries, second entry must be an GlyphClassTable, but is: " + o.getClass() ); + } else { + bcdt = (GlyphClassTable) o; + } + if ( ( ( o = entries.get(2) ) != null ) && ! ( o instanceof GlyphClassTable ) ) { + throw new AdvancedTypographicTableFormatException ( "illegal entries, third entry must be an GlyphClassTable, but is: " + o.getClass() ); + } else { + lcdt = (GlyphClassTable) o; + } + if ( ( ( o = entries.get(3) ) == null ) || ! ( o instanceof Integer ) ) { + throw new AdvancedTypographicTableFormatException ( "illegal entries, fourth entry must be an Integer, but is: " + ( ( o != null ) ? o.getClass() : null ) ); + } else { + ngc = ((Integer)(o)).intValue(); + } + if ( ( ( o = entries.get(4) ) == null ) || ! ( o instanceof RuleSet[] ) ) { + throw new AdvancedTypographicTableFormatException ( "illegal entries, fifth entry must be an RuleSet[], but is: " + ( ( o != null ) ? o.getClass() : null ) ); + } else { + rsa = (RuleSet[]) o; + if ( rsa.length != ngc ) { + throw new AdvancedTypographicTableFormatException ( "illegal entries, RuleSet[] length is " + rsa.length + ", but expected " + ngc + " glyph classes" ); + } + } + } + } + } + + private static class ChainedContextualSubtableFormat3 extends ChainedContextualSubtable { + private RuleSet[] rsa; // rule set array, containing a single rule set + ChainedContextualSubtableFormat3 ( String id, int sequence, int flags, int format, GlyphCoverageTable coverage, List entries ) { + super ( id, sequence, flags, format, coverage, entries ); + populate ( entries ); + } + /** {@inheritDoc} */ + public List getEntries() { + if ( rsa != null ) { + List entries = new ArrayList ( 1 ); + entries.add ( rsa ); + return entries; + } else { + return null; + } + } + /** {@inheritDoc} */ + public void resolveLookupReferences ( Map/**/ lookupTables ) { + GlyphTable.resolveLookupReferences ( rsa, lookupTables ); + } + /** {@inheritDoc} */ + public RuleLookup[] getLookups ( int ci, int gi, GlyphSubstitutionState ss, int[] rv ) { + assert ss != null; + assert ( rv != null ) && ( rv.length > 0 ); + assert rsa != null; + if ( rsa.length > 0 ) { + RuleSet rs = rsa [ 0 ]; + if ( rs != null ) { + Rule[] ra = rs.getRules(); + for ( int i = 0, n = ra.length; i < n; i++ ) { + Rule r = ra [ i ]; + if ( ( r != null ) && ( r instanceof ChainedCoverageSequenceRule ) ) { + ChainedCoverageSequenceRule cr = (ChainedCoverageSequenceRule) r; + GlyphCoverageTable[] igca = cr.getCoverages(); + if ( matches ( ss, igca, 0, rv ) ) { + GlyphCoverageTable[] bgca = cr.getBacktrackCoverages(); + if ( matches ( ss, bgca, -1, null ) ) { + GlyphCoverageTable[] lgca = cr.getLookaheadCoverages(); + if ( matches ( ss, lgca, rv[0], null ) ) { + return r.getLookups(); + } + } + } + } + } + } + } + return null; + } + private boolean matches ( GlyphSubstitutionState ss, GlyphCoverageTable[] gca, int offset, int[] rv ) { + return ContextualSubtableFormat3.matches ( ss, gca, offset, rv ); + } + private void populate ( List entries ) { + if ( entries == null ) { + throw new AdvancedTypographicTableFormatException ( "illegal entries, must be non-null" ); + } else if ( entries.size() != 1 ) { + throw new AdvancedTypographicTableFormatException ( "illegal entries, " + entries.size() + " entries present, but requires 1 entry" ); + } else { + Object o; + if ( ( ( o = entries.get(0) ) == null ) || ! ( o instanceof RuleSet[] ) ) { + throw new AdvancedTypographicTableFormatException ( "illegal entries, first entry must be an RuleSet[], but is: " + ( ( o != null ) ? o.getClass() : null ) ); + } else { + rsa = (RuleSet[]) o; + } + } + } + } + + private abstract static class ReverseChainedSingleSubtable extends GlyphSubstitutionSubtable { + public ReverseChainedSingleSubtable ( String id, int sequence, int flags, int format, GlyphCoverageTable coverage, List entries ) { + super ( id, sequence, flags, format, coverage ); + } + /** {@inheritDoc} */ + public int getType() { + return GSUB_LOOKUP_TYPE_REVERSE_CHAINED_SINGLE; + } + /** {@inheritDoc} */ + public boolean isCompatible ( GlyphSubtable subtable ) { + return subtable instanceof ReverseChainedSingleSubtable; + } + /** {@inheritDoc} */ + public boolean usesReverseScan() { + return true; + } + static GlyphSubstitutionSubtable create ( String id, int sequence, int flags, int format, GlyphCoverageTable coverage, List entries ) { + if ( format == 1 ) { + return new ReverseChainedSingleSubtableFormat1 ( id, sequence, flags, format, coverage, entries ); + } else { + throw new UnsupportedOperationException(); + } + } + } + + private static class ReverseChainedSingleSubtableFormat1 extends ReverseChainedSingleSubtable { + ReverseChainedSingleSubtableFormat1 ( String id, int sequence, int flags, int format, GlyphCoverageTable coverage, List entries ) { + super ( id, sequence, flags, format, coverage, entries ); + populate ( entries ); + } + /** {@inheritDoc} */ + public List getEntries() { + return null; + } + private void populate ( List entries ) { + } + } + + /** + * The Ligature class implements a ligature lookup result in terms of + * a ligature glyph (code) and the N+1... components that comprise the ligature, + * where the Nth component was consumed in the coverage table lookup mapping to + * this ligature instance. + */ + public static class Ligature { + + private final int ligature; // (resulting) ligature glyph + private final int[] components; // component glyph codes (note that first component is implied) + + /** + * Instantiate a ligature. + * @param ligature glyph id + * @param components sequence of N+1... component glyph (or character) identifiers + */ + public Ligature ( int ligature, int[] components ) { + if ( ( ligature < 0 ) || ( ligature > 65535 ) ) { + throw new AdvancedTypographicTableFormatException ( "invalid ligature glyph index: " + ligature ); + } else if ( components == null ) { + throw new AdvancedTypographicTableFormatException ( "invalid ligature components, must be non-null array" ); + } else { + for ( int i = 0, n = components.length; i < n; i++ ) { + int gc = components [ i ]; + if ( ( gc < 0 ) || ( gc > 65535 ) ) { + throw new AdvancedTypographicTableFormatException ( "invalid component glyph index: " + gc ); + } + } + this.ligature = ligature; + this.components = components; + } + } + + /** @return ligature glyph id */ + public int getLigature() { + return ligature; + } + + /** @return array of N+1... components */ + public int[] getComponents() { + return components; + } + + /** @return components count */ + public int getNumComponents() { + return components.length; + } + + /** + * Determine if input sequence at offset matches ligature's components. + * @param glyphs array of glyph components to match (including first, implied glyph) + * @return true if matches + */ + public boolean matchesComponents ( int[] glyphs ) { + if ( glyphs.length < ( components.length + 1 ) ) { + return false; + } else { + for ( int i = 0, n = components.length; i < n; i++ ) { + if ( glyphs [ i + 1 ] != components [ i ] ) { + return false; + } + } + return true; + } + } + + /** {@inheritDoc} */ + public String toString() { + StringBuffer sb = new StringBuffer(); + sb.append("{components={"); + for ( int i = 0, n = components.length; i < n; i++ ) { + if ( i > 0 ) { + sb.append(','); + } + sb.append(Integer.toString(components[i])); + } + sb.append("},ligature="); + sb.append(Integer.toString(ligature)); + sb.append("}"); + return sb.toString(); + } + + } + + /** + * The LigatureSet class implements a set of ligatures. + */ + public static class LigatureSet { + + private final Ligature[] ligatures; // set of ligatures all of which share the first (implied) component + private final int maxComponents; // maximum number of components (including first) + + /** + * Instantiate a set of ligatures. + * @param ligatures collection of ligatures + */ + public LigatureSet ( List ligatures ) { + this ( (Ligature[]) ligatures.toArray ( new Ligature [ ligatures.size() ] ) ); + } + + /** + * Instantiate a set of ligatures. + * @param ligatures array of ligatures + */ + public LigatureSet ( Ligature[] ligatures ) { + if ( ligatures == null ) { + throw new AdvancedTypographicTableFormatException ( "invalid ligatures, must be non-null array" ); + } else { + this.ligatures = ligatures; + int ncMax = -1; + for ( int i = 0, n = ligatures.length; i < n; i++ ) { + Ligature l = ligatures [ i ]; + int nc = l.getNumComponents() + 1; + if ( nc > ncMax ) { + ncMax = nc; + } + } + maxComponents = ncMax; + } + } + + /** @return array of ligatures in this ligature set */ + public Ligature[] getLigatures() { + return ligatures; + } + + /** @return count of ligatures in this ligature set */ + public int getNumLigatures() { + return ligatures.length; + } + + /** @return maximum number of components in one ligature (including first component) */ + public int getMaxComponents() { + return maxComponents; + } + + /** {@inheritDoc} */ + public String toString() { + StringBuffer sb = new StringBuffer(); + sb.append("{ligs={"); + for ( int i = 0, n = ligatures.length; i < n; i++ ) { + if ( i > 0 ) { + sb.append(','); + } + sb.append(ligatures[i]); + } + sb.append("}}"); + return sb.toString(); + } + + } + +} + diff --git a/src/java/org/apache/fop/complexscripts/fonts/GlyphSubtable.java b/src/java/org/apache/fop/complexscripts/fonts/GlyphSubtable.java new file mode 100644 index 000000000..ba0141e44 --- /dev/null +++ b/src/java/org/apache/fop/complexscripts/fonts/GlyphSubtable.java @@ -0,0 +1,314 @@ +/* + * 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.complexscripts.fonts; + +import java.lang.ref.WeakReference; + +import java.util.List; +import java.util.Map; + +// CSOFF: InnerAssignmentCheck +// CSOFF: LineLengthCheck + +/** + * The GlyphSubtable implements an abstract glyph subtable that + * encapsulates identification, type, format, and coverage information. + * @author Glenn Adams + */ +public abstract class GlyphSubtable implements Comparable { + + /** lookup flag - right to left */ + public static final int LF_RIGHT_TO_LEFT = 0x0001; + /** lookup flag - ignore base glyphs */ + public static final int LF_IGNORE_BASE = 0x0002; + /** lookup flag - ignore ligatures */ + public static final int LF_IGNORE_LIGATURE = 0x0004; + /** lookup flag - ignore marks */ + public static final int LF_IGNORE_MARK = 0x0008; + /** lookup flag - use mark filtering set */ + public static final int LF_USE_MARK_FILTERING_SET = 0x0010; + /** lookup flag - reserved */ + public static final int LF_RESERVED = 0x0E00; + /** lookup flag - mark attachment type */ + public static final int LF_MARK_ATTACHMENT_TYPE = 0xFF00; + /** internal flag - use reverse scan */ + public static final int LF_INTERNAL_USE_REVERSE_SCAN = 0x10000; + + /** lookup identifier, having form of "lu%d" where %d is index of lookup in lookup list; shared by multiple subtables in a single lookup */ + private String lookupId; + /** subtable sequence (index) number in lookup, zero based */ + private int sequence; + /** subtable flags */ + private int flags; + /** subtable format */ + private int format; + /** subtable mapping table */ + private GlyphMappingTable mapping; + /** weak reference to parent (gsub or gpos) table */ + private WeakReference table; + + /** + * Instantiate this glyph subtable. + * @param lookupId lookup identifier, having form of "lu%d" where %d is index of lookup in lookup list + * @param sequence subtable sequence (within lookup), starting with zero + * @param flags subtable flags + * @param format subtable format + * @param mapping subtable mapping table + */ + protected GlyphSubtable ( String lookupId, int sequence, int flags, int format, GlyphMappingTable mapping ) + { + if ( ( lookupId == null ) || ( lookupId.length() == 0 ) ) { + throw new AdvancedTypographicTableFormatException ( "invalid lookup identifier, must be non-empty string" ); + } else if ( mapping == null ) { + throw new AdvancedTypographicTableFormatException ( "invalid mapping table, must not be null" ); + } else { + this.lookupId = lookupId; + this.sequence = sequence; + this.flags = flags; + this.format = format; + this.mapping = mapping; + } + } + + /** @return this subtable's lookup identifer */ + public String getLookupId() { + return lookupId; + } + + /** @return this subtable's table type */ + public abstract int getTableType(); + + /** @return this subtable's type */ + public abstract int getType(); + + /** @return this subtable's type name */ + public abstract String getTypeName(); + + /** + * Determine if a glyph subtable is compatible with this glyph subtable. Two glyph subtables are + * compatible if the both may appear in a single lookup table. + * @param subtable a glyph subtable to determine compatibility + * @return true if specified subtable is compatible with this glyph subtable, where by compatible + * is meant that they share the same lookup type + */ + public abstract boolean isCompatible ( GlyphSubtable subtable ); + + /** @return true if subtable uses reverse scanning of glyph sequence, meaning from the last glyph + * in a glyph sequence to the first glyph + */ + public abstract boolean usesReverseScan(); + + /** @return this subtable's sequence (index) within lookup */ + public int getSequence() { + return sequence; + } + + /** @return this subtable's flags */ + public int getFlags() { + return flags; + } + + /** @return this subtable's format */ + public int getFormat() { + return format; + } + + /** @return this subtable's governing glyph definition table or null if none available */ + public GlyphDefinitionTable getGDEF() { + GlyphTable gt = getTable(); + if ( gt != null ) { + return gt.getGlyphDefinitions(); + } else { + return null; + } + } + + /** @return this subtable's coverage mapping or null if mapping is not a coverage mapping */ + public GlyphCoverageMapping getCoverage() { + if ( mapping instanceof GlyphCoverageMapping ) { + return (GlyphCoverageMapping) mapping; + } else { + return null; + } + } + + /** @return this subtable's class mapping or null if mapping is not a class mapping */ + public GlyphClassMapping getClasses() { + if ( mapping instanceof GlyphClassMapping ) { + return (GlyphClassMapping) mapping; + } else { + return null; + } + } + + /** @return this subtable's lookup entries */ + public abstract List getEntries(); + + /** @return this subtable's parent table (or null if undefined) */ + public synchronized GlyphTable getTable() { + WeakReference r = this.table; + return ( r != null ) ? (GlyphTable) r.get() : null; + } + + /** + * Establish a weak reference from this subtable to its parent + * table. If table parameter is specified as null, then + * clear and remove weak reference. + * @param table the table or null + * @throws IllegalStateException if table is already set to non-null + */ + public synchronized void setTable ( GlyphTable table ) throws IllegalStateException { + WeakReference r = this.table; + if ( table == null ) { + this.table = null; + if ( r != null ) { + r.clear(); + } + } else if ( r == null ) { + this.table = new WeakReference ( table ); + } else { + throw new IllegalStateException ( "table already set" ); + } + } + + /** + * Resolve references to lookup tables, e.g., in RuleLookup, to the lookup tables themselves. + * @param lookupTables map from lookup table identifers, e.g. "lu4", to lookup tables + */ + public void resolveLookupReferences ( Map/**/ lookupTables ) { + } + + /** + * Map glyph id to coverage index. + * @param gid glyph id + * @return the corresponding coverage index of the specified glyph id + */ + public int getCoverageIndex ( int gid ) { + if ( mapping instanceof GlyphCoverageMapping ) { + return ( (GlyphCoverageMapping) mapping ) .getCoverageIndex ( gid ); + } else { + return -1; + } + } + + /** + * Map glyph id to coverage index. + * @return the corresponding coverage index of the specified glyph id + */ + public int getCoverageSize() { + if ( mapping instanceof GlyphCoverageMapping ) { + return ( (GlyphCoverageMapping) mapping ) .getCoverageSize(); + } else { + return 0; + } + } + + /** {@inheritDoc} */ + public int hashCode() { + int hc = sequence; + hc = ( hc * 3 ) + ( lookupId.hashCode() ^ hc ); + return hc; + } + + /** + * {@inheritDoc} + * @return true if the lookup identifier and the sequence number of the specified subtable is the same + * as the lookup identifier and sequence number of this subtable + */ + public boolean equals ( Object o ) { + if ( o instanceof GlyphSubtable ) { + GlyphSubtable st = (GlyphSubtable) o; + return lookupId.equals ( st.lookupId ) && ( sequence == st.sequence ); + } else { + return false; + } + } + + /** + * {@inheritDoc} + * @return the result of comparing the lookup identifier and the sequence number of the specified subtable with + * the lookup identifier and sequence number of this subtable + */ + public int compareTo ( Object o ) { + int d; + if ( o instanceof GlyphSubtable ) { + GlyphSubtable st = (GlyphSubtable) o; + if ( ( d = lookupId.compareTo ( st.lookupId ) ) == 0 ) { + if ( sequence < st.sequence ) { + d = -1; + } else if ( sequence > st.sequence ) { + d = 1; + } + } + } else { + d = -1; + } + return d; + } + + /** + * Determine if any of the specified subtables uses reverse scanning. + * @param subtables array of glyph subtables + * @return true if any of the specified subtables uses reverse scanning. + */ + public static boolean usesReverseScan ( GlyphSubtable[] subtables ) { + if ( ( subtables == null ) || ( subtables.length == 0 ) ) { + return false; + } else { + for ( int i = 0, n = subtables.length; i < n; i++ ) { + if ( subtables[i].usesReverseScan() ) { + return true; + } + } + return false; + } + } + + /** + * Determine consistent flags for a set of subtables. + * @param subtables array of glyph subtables + * @return consistent flags + * @throws IllegalStateException if inconsistent flags + */ + public static int getFlags ( GlyphSubtable[] subtables ) throws IllegalStateException { + if ( ( subtables == null ) || ( subtables.length == 0 ) ) { + return 0; + } else { + int flags = 0; + // obtain first non-zero value of flags in array of subtables + for ( int i = 0, n = subtables.length; i < n; i++ ) { + int f = subtables[i].getFlags(); + if ( flags == 0 ) { + flags = f; + break; + } + } + // enforce flag consistency + for ( int i = 0, n = subtables.length; i < n; i++ ) { + int f = subtables[i].getFlags(); + if ( f != flags ) { + throw new IllegalStateException ( "inconsistent lookup flags " + f + ", expected " + flags ); + } + } + return flags | ( usesReverseScan ( subtables ) ? LF_INTERNAL_USE_REVERSE_SCAN : 0 ); + } + } + +} diff --git a/src/java/org/apache/fop/complexscripts/fonts/GlyphTable.java b/src/java/org/apache/fop/complexscripts/fonts/GlyphTable.java new file mode 100644 index 000000000..91f8d4924 --- /dev/null +++ b/src/java/org/apache/fop/complexscripts/fonts/GlyphTable.java @@ -0,0 +1,1300 @@ +/* + * 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.complexscripts.fonts; + +import java.util.Arrays; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.ListIterator; +import java.util.Map; +import java.util.Set; +import java.util.TreeSet; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.apache.fop.complexscripts.util.GlyphSequence; +import org.apache.fop.complexscripts.util.ScriptContextTester; + +// CSOFF: EmptyForIteratorPadCheck +// CSOFF: InnerAssignmentCheck +// CSOFF: LineLengthCheck +// CSOFF: NoWhitespaceAfterCheck +// CSOFF: ParameterNumberCheck +// CSOFF: SimplifyBooleanReturnCheck + +/** + * Base class for all advanced typographic glyph tables. + * @author Glenn Adams + */ +public class GlyphTable { + + /** logging instance */ + private static final Log log = LogFactory.getLog(GlyphTable.class); // CSOK: ConstantNameCheck + + /** substitution glyph table type */ + public static final int GLYPH_TABLE_TYPE_SUBSTITUTION = 1; + /** positioning glyph table type */ + public static final int GLYPH_TABLE_TYPE_POSITIONING = 2; + /** justification glyph table type */ + public static final int GLYPH_TABLE_TYPE_JUSTIFICATION = 3; + /** baseline glyph table type */ + public static final int GLYPH_TABLE_TYPE_BASELINE = 4; + /** definition glyph table type */ + public static final int GLYPH_TABLE_TYPE_DEFINITION = 5; + + // (optional) glyph definition table in table types other than glyph definition table + private GlyphTable gdef; + + // map from lookup specs to lists of strings, each of which identifies a lookup table (consisting of one or more subtables) + private Map/*>*/ lookups; + + // map from lookup identifiers to lookup tables + private Map/**/ lookupTables; + + // if true, then prevent further subtable addition + private boolean frozen; + + /** + * Instantiate glyph table with specified lookups. + * @param gdef glyph definition table that applies + * @param lookups map from lookup specs to lookup tables + */ + public GlyphTable ( GlyphTable gdef, Map/*>*/ lookups ) { + if ( ( gdef != null ) && ! ( gdef instanceof GlyphDefinitionTable ) ) { + throw new AdvancedTypographicTableFormatException ( "bad glyph definition table" ); + } else if ( lookups == null ) { + throw new AdvancedTypographicTableFormatException ( "lookups must be non-null map" ); + } else { + this.gdef = gdef; + this.lookups = lookups; + this.lookupTables = new LinkedHashMap/*>*/(); + } + } + + /** + * Obtain glyph definition table. + * @return (possibly null) glyph definition table + */ + public GlyphDefinitionTable getGlyphDefinitions() { + return (GlyphDefinitionTable) gdef; + } + + /** + * Obtain list of all lookup specifications. + * @return (possibly empty) list of all lookup specifications + */ + public List/**/ getLookups() { + return matchLookupSpecs ( "*", "*", "*" ); + } + + /** + * Obtain ordered list of all lookup tables, where order is by lookup identifier, which + * lexicographic ordering follows the lookup list order. + * @return (possibly empty) ordered list of all lookup tables + */ + public List/**/ getLookupTables() { + TreeSet/**/ lids = new TreeSet/**/ ( lookupTables.keySet() ); + List/**/ ltl = new ArrayList/**/ ( lids.size() ); + for ( Iterator it = lids.iterator(); it.hasNext(); ) { + String lid = (String) it.next(); + ltl.add ( lookupTables.get ( lid ) ); + } + return ltl; + } + + /** + * Obtain lookup table by lookup id. This method is used by test code, and provides + * access to embedded lookups not normally accessed by {script, language, feature} lookup spec. + * @param lid lookup id + * @return table associated with lookup id or null if none + */ + public LookupTable getLookupTable ( String lid ) { + return (LookupTable) lookupTables.get ( lid ); + } + + /** + * Add a subtable. + * @param subtable a (non-null) glyph subtable + */ + protected void addSubtable ( GlyphSubtable subtable ) { + // ensure table is not frozen + if ( frozen ) { + throw new IllegalStateException ( "glyph table is frozen, subtable addition prohibited" ); + } + // set subtable's table reference to this table + subtable.setTable ( this ); + // add subtable to this table's subtable collection + String lid = subtable.getLookupId(); + if ( lookupTables.containsKey ( lid ) ) { + LookupTable lt = (LookupTable) lookupTables.get ( lid ); + lt.addSubtable ( subtable ); + } else { + LookupTable lt = new LookupTable ( lid, subtable ); + lookupTables.put ( lid, lt ); + } + } + + /** + * Freeze subtables, i.e., do not allow further subtable addition, and + * create resulting cached state. + */ + protected void freezeSubtables() { + if ( ! frozen ) { + for ( Iterator it = lookupTables.values().iterator(); it.hasNext(); ) { + LookupTable lt = (LookupTable) it.next(); + lt.freezeSubtables ( lookupTables ); + } + frozen = true; + } + } + + /** + * Match lookup specifications according to tuple, where + * '*' is a wildcard for a tuple component. + * @param script a script identifier + * @param language a language identifier + * @param feature a feature identifier + * @return a (possibly empty) array of matching lookup specifications + */ + public List/**/ matchLookupSpecs ( String script, String language, String feature ) { + Set/**/ keys = lookups.keySet(); + List/**/ matches = new ArrayList/**/(); + for ( Iterator it = keys.iterator(); it.hasNext();) { + LookupSpec ls = (LookupSpec) it.next(); + if ( ! "*".equals(script) ) { + if ( ! ls.getScript().equals ( script ) ) { + continue; + } + } + if ( ! "*".equals(language) ) { + if ( ! ls.getLanguage().equals ( language ) ) { + continue; + } + } + if ( ! "*".equals(feature) ) { + if ( ! ls.getFeature().equals ( feature ) ) { + continue; + } + } + matches.add ( ls ); + } + return matches; + } + + /** + * Match lookup specifications according to tuple, where + * '*' is a wildcard for a tuple component. + * @param script a script identifier + * @param language a language identifier + * @param feature a feature identifier + * @return a (possibly empty) map from matching lookup specifications to lists of corresponding lookup tables + */ + public Map/*>*/ matchLookups ( String script, String language, String feature ) { + List/**/ lsl = matchLookupSpecs ( script, language, feature ); + Map lm = new LinkedHashMap(); + for ( Iterator it = lsl.iterator(); it.hasNext(); ) { + LookupSpec ls = (LookupSpec) it.next(); + lm.put ( ls, findLookupTables ( ls ) ); + } + return lm; + } + + /** + * Obtain ordered list of glyph lookup tables that match a specific lookup specification. + * @param ls a (non-null) lookup specification + * @return a (possibly empty) ordered list of lookup tables whose corresponding lookup specifications match the specified lookup spec + */ + public List/**/ findLookupTables ( LookupSpec ls ) { + TreeSet/**/ lts = new TreeSet/**/(); + List/**/ ids; + if ( ( ids = (List/**/) lookups.get ( ls ) ) != null ) { + for ( Iterator it = ids.iterator(); it.hasNext();) { + String lid = (String) it.next(); + LookupTable lt; + if ( ( lt = (LookupTable) lookupTables.get ( lid ) ) != null ) { + lts.add ( lt ); + } + } + } + return new ArrayList/**/ ( lts ); + } + + /** + * Assemble ordered array of lookup table use specifications according to the specified features and candidate lookups, + * where the order of the array is in accordance to the order of the applicable lookup list. + * @param features array of feature identifiers to apply + * @param lookups a mapping from lookup specifications to lists of look tables from which to select lookup tables according to the specified features + * @return ordered array of assembled lookup table use specifications + */ + public UseSpec[] assembleLookups ( String[] features, Map/*>*/ lookups ) { + TreeSet/**/ uss = new TreeSet/**/(); + for ( int i = 0, n = features.length; i < n; i++ ) { + String feature = features[i]; + for ( Iterator it = lookups.entrySet().iterator(); it.hasNext(); ) { + Map.Entry/*>*/ e = (Map.Entry/*>*/) it.next(); + LookupSpec ls = (LookupSpec) e.getKey(); + if ( ls.getFeature().equals ( feature ) ) { + List/**/ ltl = (List/**/) e.getValue(); + if ( ltl != null ) { + for ( Iterator ltit = ltl.iterator(); ltit.hasNext(); ) { + LookupTable lt = (LookupTable) ltit.next(); + uss.add ( new UseSpec ( lt, feature ) ); + } + } + } + } + } + return (UseSpec[]) uss.toArray ( new UseSpec [ uss.size() ] ); + } + + /** {@inheritDoc} */ + public String toString() { + StringBuffer sb = new StringBuffer(super.toString()); + sb.append("{"); + sb.append("lookups={"); + sb.append(lookups.toString()); + sb.append("},lookupTables={"); + sb.append(lookupTables.toString()); + sb.append("}}"); + return sb.toString(); + } + + /** + * Obtain glyph table type from name. + * @param name of table type to map to type value + * @return glyph table type (as an integer constant) + */ + public static int getTableTypeFromName ( String name ) { + int t; + String s = name.toLowerCase(); + if ( "gsub".equals ( s ) ) { + t = GLYPH_TABLE_TYPE_SUBSTITUTION; + } else if ( "gpos".equals ( s ) ) { + t = GLYPH_TABLE_TYPE_POSITIONING; + } else if ( "jstf".equals ( s ) ) { + t = GLYPH_TABLE_TYPE_JUSTIFICATION; + } else if ( "base".equals ( s ) ) { + t = GLYPH_TABLE_TYPE_BASELINE; + } else if ( "gdef".equals ( s ) ) { + t = GLYPH_TABLE_TYPE_DEFINITION; + } else { + t = -1; + } + return t; + } + + /** + * Resolve references to lookup tables in a collection of rules sets. + * @param rsa array of rule sets + * @param lookupTables map from lookup table identifers, e.g. "lu4", to lookup tables + */ + public static void resolveLookupReferences ( RuleSet[] rsa, Map/**/ lookupTables ) { + if ( ( rsa != null ) && ( lookupTables != null ) ) { + for ( int i = 0, n = rsa.length; i < n; i++ ) { + RuleSet rs = rsa [ i ]; + if ( rs != null ) { + rs.resolveLookupReferences ( lookupTables ); + } + } + } + } + + /** + * A structure class encapsulating a lookup specification as a tuple. + */ + public static class LookupSpec implements Comparable { + + private final String script; + private final String language; + private final String feature; + + /** + * Instantiate lookup spec. + * @param script a script identifier + * @param language a language identifier + * @param feature a feature identifier + */ + public LookupSpec ( String script, String language, String feature ) { + if ( ( script == null ) || ( script.length() == 0 ) ) { + throw new AdvancedTypographicTableFormatException ( "script must be non-empty string" ); + } else if ( ( language == null ) || ( language.length() == 0 ) ) { + throw new AdvancedTypographicTableFormatException ( "language must be non-empty string" ); + } else if ( ( feature == null ) || ( feature.length() == 0 ) ) { + throw new AdvancedTypographicTableFormatException ( "feature must be non-empty string" ); + } else if ( script.equals("*") ) { + throw new AdvancedTypographicTableFormatException ( "script must not be wildcard" ); + } else if ( language.equals("*") ) { + throw new AdvancedTypographicTableFormatException ( "language must not be wildcard" ); + } else if ( feature.equals("*") ) { + throw new AdvancedTypographicTableFormatException ( "feature must not be wildcard" ); + } else { + this.script = script.trim(); + this.language = language.trim(); + this.feature = feature.trim(); + } + } + + /** @return script identifier */ + public String getScript() { + return script; + } + + /** @return language identifier */ + public String getLanguage() { + return language; + } + + /** @return feature identifier */ + public String getFeature() { + return feature; + } + + /** {@inheritDoc} */ + public int hashCode() { + int hc = 0; + hc = 7 * hc + ( hc ^ script.hashCode() ); + hc = 11 * hc + ( hc ^ language.hashCode() ); + hc = 17 * hc + ( hc ^ feature.hashCode() ); + return hc; + } + + /** {@inheritDoc} */ + public boolean equals ( Object o ) { + if ( o instanceof LookupSpec ) { + LookupSpec l = (LookupSpec) o; + if ( ! l.script.equals ( script ) ) { + return false; + } else if ( ! l.language.equals ( language ) ) { + return false; + } else if ( ! l.feature.equals ( feature ) ) { + return false; + } else { + return true; + } + } else { + return false; + } + } + + /** {@inheritDoc} */ + public int compareTo ( Object o ) { + int d; + if ( o instanceof LookupSpec ) { + LookupSpec ls = (LookupSpec) o; + if ( ( d = script.compareTo ( ls.script ) ) == 0 ) { + if ( ( d = language.compareTo ( ls.language ) ) == 0 ) { + if ( ( d = feature.compareTo ( ls.feature ) ) == 0 ) { + d = 0; + } + } + } + } else { + d = -1; + } + return d; + } + + /** {@inheritDoc} */ + public String toString() { + StringBuffer sb = new StringBuffer(super.toString()); + sb.append("{"); + sb.append("<'" + script + "'"); + sb.append(",'" + language + "'"); + sb.append(",'" + feature + "'"); + sb.append(">}"); + return sb.toString(); + } + + } + + /** + * The LookupTable class comprising an identifier and an ordered list + * of glyph subtables, each of which employ the same lookup identifier. + */ + public static class LookupTable implements Comparable { + + private final String id; // lookup identifiers + private final List/**/ subtables; // list of subtables + private boolean doesSub; // performs substitutions + private boolean doesPos; // performs positioning + private boolean frozen; // if true, then don't permit further subtable additions + // frozen state + private GlyphSubtable[] subtablesArray; + private static GlyphSubtable[] subtablesArrayEmpty = new GlyphSubtable[0]; + + /** + * Instantiate a LookupTable. + * @param id the lookup table's identifier + * @param subtable an initial subtable (or null) + */ + public LookupTable ( String id, GlyphSubtable subtable ) { + this ( id, makeSingleton ( subtable ) ); + } + + /** + * Instantiate a LookupTable. + * @param id the lookup table's identifier + * @param subtables a pre-poplated list of subtables or null + */ + public LookupTable ( String id, List/**/ subtables ) { + assert id != null; + assert id.length() != 0; + this.id = id; + this.subtables = new LinkedList/**/(); + if ( subtables != null ) { + for ( Iterator it = subtables.iterator(); it.hasNext(); ) { + GlyphSubtable st = (GlyphSubtable) it.next(); + addSubtable ( st ); + } + } + } + + /** @return the identifier */ + public String getId() { + return id; + } + + /** @return the subtables as an array */ + public GlyphSubtable[] getSubtables() { + if ( frozen ) { + return ( subtablesArray != null ) ? subtablesArray : subtablesArrayEmpty; + } else { + if ( doesSub ) { + return (GlyphSubtable[]) subtables.toArray ( new GlyphSubstitutionSubtable [ subtables.size() ] ); + } else if ( doesPos ) { + return (GlyphSubtable[]) subtables.toArray ( new GlyphPositioningSubtable [ subtables.size() ] ); + } else { + return null; + } + } + } + + /** + * Add a subtable into this lookup table's collecion of subtables according to its + * natural order. + * @param subtable to add + * @return true if subtable was not already present, otherwise false + */ + public boolean addSubtable ( GlyphSubtable subtable ) { + boolean added = false; + // ensure table is not frozen + if ( frozen ) { + throw new IllegalStateException ( "glyph table is frozen, subtable addition prohibited" ); + } + // validate subtable to ensure consistency with current subtables + validateSubtable ( subtable ); + // insert subtable into ordered list + for ( ListIterator/**/ lit = subtables.listIterator(0); lit.hasNext(); ) { + GlyphSubtable st = (GlyphSubtable) lit.next(); + int d; + if ( ( d = subtable.compareTo ( st ) ) < 0 ) { + // insert within list + lit.set ( subtable ); + lit.add ( st ); + added = true; + } else if ( d == 0 ) { + // duplicate entry is ignored + added = false; subtable = null; + } + } + // append at end of list + if ( ! added && ( subtable != null ) ) { + subtables.add ( subtable ); + added = true; + } + return added; + } + + private void validateSubtable ( GlyphSubtable subtable ) { + if ( subtable == null ) { + throw new AdvancedTypographicTableFormatException ( "subtable must be non-null" ); + } + if ( subtable instanceof GlyphSubstitutionSubtable ) { + if ( doesPos ) { + throw new AdvancedTypographicTableFormatException ( "subtable must be positioning subtable, but is: " + subtable ); + } else { + doesSub = true; + } + } + if ( subtable instanceof GlyphPositioningSubtable ) { + if ( doesSub ) { + throw new AdvancedTypographicTableFormatException ( "subtable must be substitution subtable, but is: " + subtable ); + } else { + doesPos = true; + } + } + if ( subtables.size() > 0 ) { + GlyphSubtable st = (GlyphSubtable) subtables.get(0); + if ( ! st.isCompatible ( subtable ) ) { + throw new AdvancedTypographicTableFormatException ( "subtable " + subtable + " is not compatible with subtable " + st ); + } + } + } + + /** + * Freeze subtables, i.e., do not allow further subtable addition, and + * create resulting cached state. In addition, resolve any references to + * lookup tables that appear in this lookup table's subtables. + * @param lookupTables map from lookup table identifers, e.g. "lu4", to lookup tables + */ + public void freezeSubtables ( Map/**/ lookupTables ) { + if ( ! frozen ) { + GlyphSubtable[] sta = getSubtables(); + resolveLookupReferences ( sta, lookupTables ); + this.subtablesArray = sta; + this.frozen = true; + } + } + + private void resolveLookupReferences ( GlyphSubtable[] subtables, Map/**/ lookupTables ) { + if ( subtables != null ) { + for ( int i = 0, n = subtables.length; i < n; i++ ) { + GlyphSubtable st = subtables [ i ]; + if ( st != null ) { + st.resolveLookupReferences ( lookupTables ); + } + } + } + } + + /** + * Determine if this glyph table performs substitution. + * @return true if it performs substitution + */ + public boolean performsSubstitution() { + return doesSub; + } + + /** + * Perform substitution processing using this lookup table's subtables. + * @param gs an input glyph sequence + * @param script a script identifier + * @param language a language identifier + * @param feature a feature identifier + * @param sct a script specific context tester (or null) + * @return the substituted (output) glyph sequence + */ + public GlyphSequence substitute ( GlyphSequence gs, String script, String language, String feature, ScriptContextTester sct ) { + if ( performsSubstitution() ) { + return GlyphSubstitutionSubtable.substitute ( gs, script, language, feature, (GlyphSubstitutionSubtable[]) subtablesArray, sct ); + } else { + return gs; + } + } + + /** + * Perform substitution processing on an existing glyph substitution state object using this lookup table's subtables. + * @param ss a glyph substitution state object + * @param sequenceIndex if non negative, then apply subtables only at specified sequence index + * @return the substituted (output) glyph sequence + */ + public GlyphSequence substitute ( GlyphSubstitutionState ss, int sequenceIndex ) { + if ( performsSubstitution() ) { + return GlyphSubstitutionSubtable.substitute ( ss, (GlyphSubstitutionSubtable[]) subtablesArray, sequenceIndex ); + } else { + return ss.getInput(); + } + } + + /** + * Determine if this glyph table performs positioning. + * @return true if it performs positioning + */ + public boolean performsPositioning() { + return doesPos; + } + + /** + * Perform positioning processing using this lookup table's subtables. + * @param gs an input glyph sequence + * @param script a script identifier + * @param language a language identifier + * @param feature a feature identifier + * @param fontSize size in device units + * @param widths array of default advancements for each glyph in font + * @param adjustments accumulated adjustments array (sequence) of 4-tuples of placement [PX,PY] and advance [AX,AY] adjustments, in that order, + * with one 4-tuple for each element of glyph sequence + * @param sct a script specific context tester (or null) + * @return true if some adjustment is not zero; otherwise, false + */ + public boolean position ( GlyphSequence gs, String script, String language, String feature, int fontSize, int[] widths, int[][] adjustments, ScriptContextTester sct ) { + if ( performsPositioning() ) { + return GlyphPositioningSubtable.position ( gs, script, language, feature, fontSize, (GlyphPositioningSubtable[]) subtablesArray, widths, adjustments, sct ); + } else { + return false; + } + } + + /** + * Perform positioning processing on an existing glyph positioning state object using this lookup table's subtables. + * @param ps a glyph positioning state object + * @param sequenceIndex if non negative, then apply subtables only at specified sequence index + * @return true if some adjustment is not zero; otherwise, false + */ + public boolean position ( GlyphPositioningState ps, int sequenceIndex ) { + if ( performsPositioning() ) { + return GlyphPositioningSubtable.position ( ps, (GlyphPositioningSubtable[]) subtablesArray, sequenceIndex ); + } else { + return false; + } + } + + /** {@inheritDoc} */ + public int hashCode() { + return id.hashCode(); + } + + /** + * {@inheritDoc} + * @return true if identifier of the specified lookup table is the same + * as the identifier of this lookup table + */ + public boolean equals ( Object o ) { + if ( o instanceof LookupTable ) { + LookupTable lt = (LookupTable) o; + return id.equals ( lt.id ); + } else { + return false; + } + } + + /** + * {@inheritDoc} + * @return the result of comparing the identifier of the specified lookup table with + * the identifier of this lookup table; lookup table identifiers take the form + * "lu(DIGIT)+", with comparison based on numerical ordering of numbers expressed by + * (DIGIT)+. + */ + public int compareTo ( Object o ) { + if ( o instanceof LookupTable ) { + LookupTable lt = (LookupTable) o; + assert id.startsWith ( "lu" ); + int i = Integer.parseInt ( id.substring ( 2 ) ); + assert lt.id.startsWith ( "lu" ); + int j = Integer.parseInt ( lt.id.substring ( 2 ) ); + if ( i < j ) { + return -1; + } else if ( i > j ) { + return 1; + } else { + return 0; + } + } else { + return -1; + } + } + + /** {@inheritDoc} */ + public String toString() { + StringBuffer sb = new StringBuffer(); + sb.append ( "{ " ); + sb.append ( "id = " + id ); + sb.append ( ", subtables = " + subtables ); + sb.append ( " }" ); + return sb.toString(); + } + + private static List/**/ makeSingleton ( GlyphSubtable subtable ) { + if ( subtable == null ) { + return null; + } else { + List/**/ stl = new ArrayList/**/ ( 1 ); + stl.add ( subtable ); + return stl; + } + } + + } + + /** + * The UseSpec class comprises a lookup table reference + * and the feature that selected the lookup table. + */ + public static class UseSpec implements Comparable { + + /** lookup table to apply */ + private final LookupTable lookupTable; + /** feature that caused selection of the lookup table */ + private final String feature; + + /** + * Construct a glyph lookup table use specification. + * @param lookupTable a glyph lookup table + * @param feature a feature that caused lookup table selection + */ + public UseSpec ( LookupTable lookupTable, String feature ) { + this.lookupTable = lookupTable; + this.feature = feature; + } + + /** @return the lookup table */ + public LookupTable getLookupTable() { + return lookupTable; + } + + /** @return the feature that selected this lookup table */ + public String getFeature() { + return feature; + } + + /** + * Perform substitution processing using this use specification's lookup table. + * @param gs an input glyph sequence + * @param script a script identifier + * @param language a language identifier + * @param sct a script specific context tester (or null) + * @return the substituted (output) glyph sequence + */ + public GlyphSequence substitute ( GlyphSequence gs, String script, String language, ScriptContextTester sct ) { + return lookupTable.substitute ( gs, script, language, feature, sct ); + } + + /** + * Perform positioning processing using this use specification's lookup table. + * @param gs an input glyph sequence + * @param script a script identifier + * @param language a language identifier + * @param fontSize size in device units + * @param widths array of default advancements for each glyph in font + * @param adjustments accumulated adjustments array (sequence) of 4-tuples of placement [PX,PY] and advance [AX,AY] adjustments, in that order, + * with one 4-tuple for each element of glyph sequence + * @param sct a script specific context tester (or null) + * @return true if some adjustment is not zero; otherwise, false + */ + public boolean position ( GlyphSequence gs, String script, String language, int fontSize, int[] widths, int[][] adjustments, ScriptContextTester sct ) { + return lookupTable.position ( gs, script, language, feature, fontSize, widths, adjustments, sct ); + } + + /** {@inheritDoc} */ + public int hashCode() { + return lookupTable.hashCode(); + } + + /** {@inheritDoc} */ + public boolean equals ( Object o ) { + if ( o instanceof UseSpec ) { + UseSpec u = (UseSpec) o; + return lookupTable.equals ( u.lookupTable ); + } else { + return false; + } + } + + /** {@inheritDoc} */ + public int compareTo ( Object o ) { + if ( o instanceof UseSpec ) { + UseSpec u = (UseSpec) o; + return lookupTable.compareTo ( u.lookupTable ); + } else { + return -1; + } + } + + } + + /** + * The RuleLookup class implements a rule lookup record, comprising + * a glyph sequence index and a lookup table index (in an applicable lookup list). + */ + public static class RuleLookup { + + private final int sequenceIndex; // index into input glyph sequence + private final int lookupIndex; // lookup list index + private LookupTable lookup; // resolved lookup table + + /** + * Instantiate a RuleLookup. + * @param sequenceIndex the index into the input sequence + * @param lookupIndex the lookup table index + */ + public RuleLookup ( int sequenceIndex, int lookupIndex ) { + this.sequenceIndex = sequenceIndex; + this.lookupIndex = lookupIndex; + this.lookup = null; + } + + /** @return the sequence index */ + public int getSequenceIndex() { + return sequenceIndex; + } + + /** @return the lookup index */ + public int getLookupIndex() { + return lookupIndex; + } + + /** @return the lookup table */ + public LookupTable getLookup() { + return lookup; + } + + /** + * Resolve references to lookup tables. + * @param lookupTables map from lookup table identifers, e.g. "lu4", to lookup tables + */ + public void resolveLookupReferences ( Map/**/ lookupTables ) { + if ( lookupTables != null ) { + String lid = "lu" + Integer.toString ( lookupIndex ); + LookupTable lt = (LookupTable) lookupTables.get ( lid ); + if ( lt != null ) { + this.lookup = lt; + } else { + log.warn ( "unable to resolve glyph lookup table reference '" + lid + "' amongst lookup tables: " + lookupTables.values() ); + } + } + } + + /** {@inheritDoc} */ + public String toString() { + return "{ sequenceIndex = " + sequenceIndex + ", lookupIndex = " + lookupIndex + " }"; + } + + } + + /** + * The Rule class implements an array of rule lookup records. + */ + public abstract static class Rule { + + private final RuleLookup[] lookups; // rule lookups + private final int inputSequenceLength; // input sequence length + + /** + * Instantiate a Rule. + * @param lookups the rule's lookups + * @param inputSequenceLength the number of glyphs in the input sequence for this rule + */ + protected Rule ( RuleLookup[] lookups, int inputSequenceLength ) { + assert lookups != null; + this.lookups = lookups; + this.inputSequenceLength = inputSequenceLength; + } + + /** @return the lookups */ + public RuleLookup[] getLookups() { + return lookups; + } + + /** @return the input sequence length */ + public int getInputSequenceLength() { + return inputSequenceLength; + } + + /** + * Resolve references to lookup tables, e.g., in RuleLookup, to the lookup tables themselves. + * @param lookupTables map from lookup table identifers, e.g. "lu4", to lookup tables + */ + public void resolveLookupReferences ( Map/**/ lookupTables ) { + if ( lookups != null ) { + for ( int i = 0, n = lookups.length; i < n; i++ ) { + RuleLookup l = lookups [ i ]; + if ( l != null ) { + l.resolveLookupReferences ( lookupTables ); + } + } + } + } + + /** {@inheritDoc} */ + public String toString() { + return "{ lookups = " + Arrays.toString ( lookups ) + ", inputSequenceLength = " + inputSequenceLength + " }"; + } + + } + + /** + * The GlyphSequenceRule class implements a subclass of Rule + * that supports matching on a specific glyph sequence. + */ + public static class GlyphSequenceRule extends Rule { + + private final int[] glyphs; // glyphs + + /** + * Instantiate a GlyphSequenceRule. + * @param lookups the rule's lookups + * @param inputSequenceLength number of glyphs constituting input sequence (to be consumed) + * @param glyphs the rule's glyph sequence to match, starting with second glyph in sequence + */ + public GlyphSequenceRule ( RuleLookup[] lookups, int inputSequenceLength, int[] glyphs ) { + super ( lookups, inputSequenceLength ); + assert glyphs != null; + this.glyphs = glyphs; + } + + /** + * Obtain glyphs. N.B. that this array starts with the second + * glyph of the input sequence. + * @return the glyphs + */ + public int[] getGlyphs() { + return glyphs; + } + + /** + * Obtain glyphs augmented by specified first glyph entry. + * @param firstGlyph to fill in first glyph entry + * @return the glyphs augmented by first glyph + */ + public int[] getGlyphs ( int firstGlyph ) { + int[] ga = new int [ glyphs.length + 1 ]; + ga [ 0 ] = firstGlyph; + System.arraycopy ( glyphs, 0, ga, 1, glyphs.length ); + return ga; + } + + /** {@inheritDoc} */ + public String toString() { + StringBuffer sb = new StringBuffer(); + sb.append ( "{ " ); + sb.append ( "lookups = " + Arrays.toString ( getLookups() ) ); + sb.append ( ", glyphs = " + Arrays.toString ( glyphs ) ); + sb.append ( " }" ); + return sb.toString(); + } + + } + + /** + * The ClassSequenceRule class implements a subclass of Rule + * that supports matching on a specific glyph class sequence. + */ + public static class ClassSequenceRule extends Rule { + + private final int[] classes; // glyph classes + + /** + * Instantiate a ClassSequenceRule. + * @param lookups the rule's lookups + * @param inputSequenceLength number of glyphs constituting input sequence (to be consumed) + * @param classes the rule's glyph class sequence to match, starting with second glyph in sequence + */ + public ClassSequenceRule ( RuleLookup[] lookups, int inputSequenceLength, int[] classes ) { + super ( lookups, inputSequenceLength ); + assert classes != null; + this.classes = classes; + } + + /** + * Obtain glyph classes. N.B. that this array starts with the class of the second + * glyph of the input sequence. + * @return the classes + */ + public int[] getClasses() { + return classes; + } + + /** + * Obtain glyph classes augmented by specified first class entry. + * @param firstClass to fill in first class entry + * @return the classes augmented by first class + */ + public int[] getClasses ( int firstClass ) { + int[] ca = new int [ classes.length + 1 ]; + ca [ 0 ] = firstClass; + System.arraycopy ( classes, 0, ca, 1, classes.length ); + return ca; + } + + /** {@inheritDoc} */ + public String toString() { + StringBuffer sb = new StringBuffer(); + sb.append ( "{ " ); + sb.append ( "lookups = " + Arrays.toString ( getLookups() ) ); + sb.append ( ", classes = " + Arrays.toString( classes ) ); + sb.append ( " }" ); + return sb.toString(); + } + + } + + /** + * The CoverageSequenceRule class implements a subclass of Rule + * that supports matching on a specific glyph coverage sequence. + */ + public static class CoverageSequenceRule extends Rule { + + private final GlyphCoverageTable[] coverages; // glyph coverages + + /** + * Instantiate a ClassSequenceRule. + * @param lookups the rule's lookups + * @param inputSequenceLength number of glyphs constituting input sequence (to be consumed) + * @param coverages the rule's glyph coverage sequence to match, starting with first glyph in sequence + */ + public CoverageSequenceRule ( RuleLookup[] lookups, int inputSequenceLength, GlyphCoverageTable[] coverages ) { + super ( lookups, inputSequenceLength ); + assert coverages != null; + this.coverages = coverages; + } + + /** @return the coverages */ + public GlyphCoverageTable[] getCoverages() { + return coverages; + } + + /** {@inheritDoc} */ + public String toString() { + StringBuffer sb = new StringBuffer(); + sb.append ( "{ " ); + sb.append ( "lookups = " + Arrays.toString ( getLookups() ) ); + sb.append ( ", coverages = " + Arrays.toString( coverages ) ); + sb.append ( " }" ); + return sb.toString(); + } + + } + + /** + * The ChainedGlyphSequenceRule class implements a subclass of GlyphSequenceRule + * that supports matching on a specific glyph sequence in a specific chained contextual. + */ + public static class ChainedGlyphSequenceRule extends GlyphSequenceRule { + + private final int[] backtrackGlyphs; // backtrack glyphs + private final int[] lookaheadGlyphs; // lookahead glyphs + + /** + * Instantiate a ChainedGlyphSequenceRule. + * @param lookups the rule's lookups + * @param inputSequenceLength number of glyphs constituting input sequence (to be consumed) + * @param glyphs the rule's input glyph sequence to match, starting with second glyph in sequence + * @param backtrackGlyphs the rule's backtrack glyph sequence to match, starting with first glyph in sequence + * @param lookaheadGlyphs the rule's lookahead glyph sequence to match, starting with first glyph in sequence + */ + public ChainedGlyphSequenceRule ( RuleLookup[] lookups, int inputSequenceLength, int[] glyphs, int[] backtrackGlyphs, int[] lookaheadGlyphs ) { + super ( lookups, inputSequenceLength, glyphs ); + assert backtrackGlyphs != null; + assert lookaheadGlyphs != null; + this.backtrackGlyphs = backtrackGlyphs; + this.lookaheadGlyphs = lookaheadGlyphs; + } + + /** @return the backtrack glyphs */ + public int[] getBacktrackGlyphs() { + return backtrackGlyphs; + } + + /** @return the lookahead glyphs */ + public int[] getLookaheadGlyphs() { + return lookaheadGlyphs; + } + + /** {@inheritDoc} */ + public String toString() { + StringBuffer sb = new StringBuffer(); + sb.append ( "{ " ); + sb.append ( "lookups = " + Arrays.toString ( getLookups() ) ); + sb.append ( ", glyphs = " + Arrays.toString ( getGlyphs() ) ); + sb.append ( ", backtrackGlyphs = " + Arrays.toString ( backtrackGlyphs ) ); + sb.append ( ", lookaheadGlyphs = " + Arrays.toString ( lookaheadGlyphs ) ); + sb.append ( " }" ); + return sb.toString(); + } + + } + + /** + * The ChainedClassSequenceRule class implements a subclass of ClassSequenceRule + * that supports matching on a specific glyph class sequence in a specific chained contextual. + */ + public static class ChainedClassSequenceRule extends ClassSequenceRule { + + private final int[] backtrackClasses; // backtrack classes + private final int[] lookaheadClasses; // lookahead classes + + /** + * Instantiate a ChainedClassSequenceRule. + * @param lookups the rule's lookups + * @param inputSequenceLength number of glyphs constituting input sequence (to be consumed) + * @param classes the rule's input glyph class sequence to match, starting with second glyph in sequence + * @param backtrackClasses the rule's backtrack glyph class sequence to match, starting with first glyph in sequence + * @param lookaheadClasses the rule's lookahead glyph class sequence to match, starting with first glyph in sequence + */ + public ChainedClassSequenceRule ( RuleLookup[] lookups, int inputSequenceLength, int[] classes, int[] backtrackClasses, int[] lookaheadClasses ) { + super ( lookups, inputSequenceLength, classes ); + assert backtrackClasses != null; + assert lookaheadClasses != null; + this.backtrackClasses = backtrackClasses; + this.lookaheadClasses = lookaheadClasses; + } + + /** @return the backtrack classes */ + public int[] getBacktrackClasses() { + return backtrackClasses; + } + + /** @return the lookahead classes */ + public int[] getLookaheadClasses() { + return lookaheadClasses; + } + + /** {@inheritDoc} */ + public String toString() { + StringBuffer sb = new StringBuffer(); + sb.append ( "{ " ); + sb.append ( "lookups = " + Arrays.toString ( getLookups() ) ); + sb.append ( ", classes = " + Arrays.toString ( getClasses() ) ); + sb.append ( ", backtrackClasses = " + Arrays.toString ( backtrackClasses ) ); + sb.append ( ", lookaheadClasses = " + Arrays.toString ( lookaheadClasses ) ); + sb.append ( " }" ); + return sb.toString(); + } + + } + + /** + * The ChainedCoverageSequenceRule class implements a subclass of CoverageSequenceRule + * that supports matching on a specific glyph class sequence in a specific chained contextual. + */ + public static class ChainedCoverageSequenceRule extends CoverageSequenceRule { + + private final GlyphCoverageTable[] backtrackCoverages; // backtrack coverages + private final GlyphCoverageTable[] lookaheadCoverages; // lookahead coverages + + /** + * Instantiate a ChainedCoverageSequenceRule. + * @param lookups the rule's lookups + * @param inputSequenceLength number of glyphs constituting input sequence (to be consumed) + * @param coverages the rule's input glyph class sequence to match, starting with first glyph in sequence + * @param backtrackCoverages the rule's backtrack glyph class sequence to match, starting with first glyph in sequence + * @param lookaheadCoverages the rule's lookahead glyph class sequence to match, starting with first glyph in sequence + */ + public ChainedCoverageSequenceRule ( RuleLookup[] lookups, int inputSequenceLength, GlyphCoverageTable[] coverages, GlyphCoverageTable[] backtrackCoverages, GlyphCoverageTable[] lookaheadCoverages ) { + super ( lookups, inputSequenceLength, coverages ); + assert backtrackCoverages != null; + assert lookaheadCoverages != null; + this.backtrackCoverages = backtrackCoverages; + this.lookaheadCoverages = lookaheadCoverages; + } + + /** @return the backtrack coverages */ + public GlyphCoverageTable[] getBacktrackCoverages() { + return backtrackCoverages; + } + + /** @return the lookahead coverages */ + public GlyphCoverageTable[] getLookaheadCoverages() { + return lookaheadCoverages; + } + + /** {@inheritDoc} */ + public String toString() { + StringBuffer sb = new StringBuffer(); + sb.append ( "{ " ); + sb.append ( "lookups = " + Arrays.toString ( getLookups() ) ); + sb.append ( ", coverages = " + Arrays.toString ( getCoverages() ) ); + sb.append ( ", backtrackCoverages = " + Arrays.toString ( backtrackCoverages ) ); + sb.append ( ", lookaheadCoverages = " + Arrays.toString ( lookaheadCoverages ) ); + sb.append ( " }" ); + return sb.toString(); + } + + } + + /** + * The RuleSet class implements a collection of rules, which + * may or may not be the same rule type. + */ + public static class RuleSet { + + private final Rule[] rules; // set of rules + + /** + * Instantiate a Rule Set. + * @param rules the rules + * @throws AdvancedTypographicTableFormatException if rules or some element of rules is null + */ + public RuleSet ( Rule[] rules ) throws AdvancedTypographicTableFormatException { + // enforce rules array instance + if ( rules == null ) { + throw new AdvancedTypographicTableFormatException ( "rules[] is null" ); + } + this.rules = rules; + } + + /** @return the rules */ + public Rule[] getRules() { + return rules; + } + + /** + * Resolve references to lookup tables, e.g., in RuleLookup, to the lookup tables themselves. + * @param lookupTables map from lookup table identifers, e.g. "lu4", to lookup tables + */ + public void resolveLookupReferences ( Map/**/ lookupTables ) { + if ( rules != null ) { + for ( int i = 0, n = rules.length; i < n; i++ ) { + Rule r = rules [ i ]; + if ( r != null ) { + r.resolveLookupReferences ( lookupTables ); + } + } + } + } + + /** {@inheritDoc} */ + public String toString() { + return "{ rules = " + Arrays.toString ( rules ) + " }"; + } + + } + + /** + * The HomogenousRuleSet class implements a collection of rules, which + * must be the same rule type (i.e., same concrete rule class) or null. + */ + public static class HomogeneousRuleSet extends RuleSet { + + /** + * Instantiate a Homogeneous Rule Set. + * @param rules the rules + * @throws AdvancedTypographicTableFormatException if some rule[i] is not an instance of rule[0] + */ + public HomogeneousRuleSet ( Rule[] rules ) throws AdvancedTypographicTableFormatException { + super ( rules ); + // find first non-null rule + Rule r0 = null; + for ( int i = 1, n = rules.length; ( r0 == null ) && ( i < n ); i++ ) { + if ( rules[i] != null ) { + r0 = rules[i]; + } + } + // enforce rule instance homogeneity + if ( r0 != null ) { + Class c = r0.getClass(); + for ( int i = 1, n = rules.length; i < n; i++ ) { + Rule r = rules[i]; + if ( ( r != null ) && ! c.isInstance ( r ) ) { + throw new AdvancedTypographicTableFormatException ( "rules[" + i + "] is not an instance of " + c.getName() ); + } + } + } + + } + + } + +} diff --git a/src/java/org/apache/fop/complexscripts/fonts/IncompatibleSubtableException.java b/src/java/org/apache/fop/complexscripts/fonts/IncompatibleSubtableException.java new file mode 100644 index 000000000..0ad8fc105 --- /dev/null +++ b/src/java/org/apache/fop/complexscripts/fonts/IncompatibleSubtableException.java @@ -0,0 +1,41 @@ +/* + * 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.complexscripts.fonts; + +/** + * Exception thrown during when attempting to map glyphs to associated characters + * in the case that the associated characters do not represent a compact interval. + * @author Glenn Adams + */ +public class IncompatibleSubtableException extends RuntimeException { + /** + * Instantiate incompatible subtable exception + */ + public IncompatibleSubtableException() { + super(); + } + /** + * Instantiate incompatible subtable exception + * @param message a message string + */ + public IncompatibleSubtableException(String message) { + super(message); + } +} diff --git a/src/java/org/apache/fop/complexscripts/fonts/OTFAdvancedTypographicTableReader.java b/src/java/org/apache/fop/complexscripts/fonts/OTFAdvancedTypographicTableReader.java new file mode 100644 index 000000000..539f9af30 --- /dev/null +++ b/src/java/org/apache/fop/complexscripts/fonts/OTFAdvancedTypographicTableReader.java @@ -0,0 +1,3797 @@ +/* + * 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.complexscripts.fonts; + +import java.io.IOException; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.apache.fop.complexscripts.fonts.AdvancedTypographicTableFormatException; +import org.apache.fop.complexscripts.fonts.GlyphClassTable; +import org.apache.fop.complexscripts.fonts.GlyphCoverageTable; +import org.apache.fop.complexscripts.fonts.GlyphDefinitionSubtable; +import org.apache.fop.complexscripts.fonts.GlyphDefinitionTable; +import org.apache.fop.complexscripts.fonts.GlyphMappingTable; +import org.apache.fop.complexscripts.fonts.GlyphPositioningSubtable; +import org.apache.fop.complexscripts.fonts.GlyphPositioningTable; +import org.apache.fop.complexscripts.fonts.GlyphSubstitutionSubtable; +import org.apache.fop.complexscripts.fonts.GlyphSubstitutionTable; +import org.apache.fop.complexscripts.fonts.GlyphSubtable; +import org.apache.fop.complexscripts.fonts.GlyphTable; +import org.apache.fop.fonts.truetype.FontFileReader; +import org.apache.fop.fonts.truetype.TTFDirTabEntry; +import org.apache.fop.fonts.truetype.TTFFile; + +// CSOFF: AvoidNestedBlocksCheck +// CSOFF: NoWhitespaceAfterCheck +// CSOFF: InnerAssignmentCheck +// CSOFF: SimplifyBooleanReturnCheck +// CSOFF: LineLengthCheck + +/** + * OpenType Font (OTF) advanced typographic table reader. Used by @{Link org.apache.fop.fonts.truetype.TTFFile} + * to read advanced typographic tables (GDEF, GSUB, GPOS). + * + * @author Glenn Adams + */ +public final class OTFAdvancedTypographicTableReader { + + // logging state + private static Log log = LogFactory.getLog(OTFAdvancedTypographicTableReader.class); + // instance state + private TTFFile ttf; // parent font file reader + private FontFileReader in; // input reader + private GlyphDefinitionTable gdef; // glyph definition table + private GlyphSubstitutionTable gsub; // glyph substitution table + private GlyphPositioningTable gpos; // glyph positioning table + // transient parsing state + private transient Map/**/ seScripts; // script-tag => Object[3] : { default-language-tag, List(language-tag), seLanguages } + private transient Map/**/ seLanguages; // language-tag => Object[2] : { "f", List("f") + private transient Map/*>*/ seFeatures; // "f" => Object[2] : { feature-tag, List("lu") } + private transient GlyphMappingTable seMapping; // subtable entry mappings + private transient List seEntries; // subtable entry entries + private transient List seSubtables; // subtable entry subtables + + /** + * Construct an OTFAdvancedTypographicTableReader instance. + * @param ttf parent font file reader (must be non-null) + * @param in font file reader (must be non-null) + */ + public OTFAdvancedTypographicTableReader ( TTFFile ttf, FontFileReader in ) { + assert ttf != null; + assert in != null; + this.ttf = ttf; + this.in = in; + } + + /** + * Read all advanced typographic tables. + * @throws AdvancedTypographicTableFormatException if ATT table has invalid format + */ + public void readAll() throws AdvancedTypographicTableFormatException { + try { + readGDEF(); + readGSUB(); + readGPOS(); + } catch ( AdvancedTypographicTableFormatException e ) { + resetATStateAll(); + throw e; + } catch ( IOException e ) { + resetATStateAll(); + throw new AdvancedTypographicTableFormatException ( e.getMessage(), e ); + } finally { + resetATState(); + } + } + + /** + * Determine if advanced (typographic) table is present. + * @return true if advanced (typographic) table is present + */ + public boolean hasAdvancedTable() { + return ( gdef != null ) || ( gsub != null ) || ( gpos != null ); + } + + /** + * Returns the GDEF table or null if none present. + * @return the GDEF table + */ + public GlyphDefinitionTable getGDEF() { + return gdef; + } + + /** + * Returns the GSUB table or null if none present. + * @return the GSUB table + */ + public GlyphSubstitutionTable getGSUB() { + return gsub; + } + + /** + * Returns the GPOS table or null if none present. + * @return the GPOS table + */ + public GlyphPositioningTable getGPOS() { + return gpos; + } + + private void readLangSysTable(String tableTag, long langSysTable, String langSysTag) throws IOException { + in.seekSet(langSysTable); + if (log.isDebugEnabled()) { + log.debug(tableTag + " lang sys table: " + langSysTag ); + } + // read lookup order (reorder) table offset + int lo = in.readTTFUShort(); + // read required feature index + int rf = in.readTTFUShort(); + String rfi; + if ( rf != 65535 ) { + rfi = "f" + rf; + } else { + rfi = null; + } + // read (non-required) feature count + int nf = in.readTTFUShort(); + // dump info if debugging + if (log.isDebugEnabled()) { + log.debug(tableTag + " lang sys table reorder table: " + lo ); + log.debug(tableTag + " lang sys table required feature index: " + rf ); + log.debug(tableTag + " lang sys table non-required feature count: " + nf ); + } + // read (non-required) feature indices + int[] fia = new int[nf]; + List fl = new java.util.ArrayList(); + for ( int i = 0; i < nf; i++ ) { + int fi = in.readTTFUShort(); + if (log.isDebugEnabled()) { + log.debug(tableTag + " lang sys table non-required feature index: " + fi ); + } + fia[i] = fi; + fl.add ( "f" + fi ); + } + if ( seLanguages == null ) { + seLanguages = new java.util.LinkedHashMap(); + } + seLanguages.put ( langSysTag, new Object[] { rfi, fl } ); + } + + private static String defaultTag = "dflt"; + + private void readScriptTable(String tableTag, long scriptTable, String scriptTag) throws IOException { + in.seekSet(scriptTable); + if (log.isDebugEnabled()) { + log.debug(tableTag + " script table: " + scriptTag ); + } + // read default language system table offset + int dl = in.readTTFUShort(); + String dt = defaultTag; + if ( dl > 0 ) { + if (log.isDebugEnabled()) { + log.debug(tableTag + " default lang sys tag: " + dt ); + log.debug(tableTag + " default lang sys table offset: " + dl ); + } + } + // read language system record count + int nl = in.readTTFUShort(); + List ll = new java.util.ArrayList(); + if ( nl > 0 ) { + String[] lta = new String[nl]; + int[] loa = new int[nl]; + // read language system records + for ( int i = 0, n = nl; i < n; i++ ) { + String lt = in.readTTFString(4); + int lo = in.readTTFUShort(); + if (log.isDebugEnabled()) { + log.debug(tableTag + " lang sys tag: " + lt ); + log.debug(tableTag + " lang sys table offset: " + lo ); + } + lta[i] = lt; + loa[i] = lo; + if ( dl == lo ) { + dl = 0; + dt = lt; + } + ll.add ( lt ); + } + // read non-default language system tables + for ( int i = 0, n = nl; i < n; i++ ) { + readLangSysTable ( tableTag, scriptTable + loa [ i ], lta [ i ] ); + } + } + // read default language system table (if specified) + if ( dl > 0 ) { + readLangSysTable ( tableTag, scriptTable + dl, dt ); + } else if ( dt != null ) { + if (log.isDebugEnabled()) { + log.debug(tableTag + " lang sys default: " + dt ); + } + } + seScripts.put ( scriptTag, new Object[] { dt, ll, seLanguages } ); + seLanguages = null; + } + + private void readScriptList(String tableTag, long scriptList) throws IOException { + in.seekSet(scriptList); + // read script record count + int ns = in.readTTFUShort(); + if (log.isDebugEnabled()) { + log.debug(tableTag + " script list record count: " + ns ); + } + if ( ns > 0 ) { + String[] sta = new String[ns]; + int[] soa = new int[ns]; + // read script records + for ( int i = 0, n = ns; i < n; i++ ) { + String st = in.readTTFString(4); + int so = in.readTTFUShort(); + if (log.isDebugEnabled()) { + log.debug(tableTag + " script tag: " + st ); + log.debug(tableTag + " script table offset: " + so ); + } + sta[i] = st; + soa[i] = so; + } + // read script tables + for ( int i = 0, n = ns; i < n; i++ ) { + seLanguages = null; + readScriptTable ( tableTag, scriptList + soa [ i ], sta [ i ] ); + } + } + } + + private void readFeatureTable(String tableTag, long featureTable, String featureTag, int featureIndex) throws IOException { + in.seekSet(featureTable); + if (log.isDebugEnabled()) { + log.debug(tableTag + " feature table: " + featureTag ); + } + // read feature params offset + int po = in.readTTFUShort(); + // read lookup list indices count + int nl = in.readTTFUShort(); + // dump info if debugging + if (log.isDebugEnabled()) { + log.debug(tableTag + " feature table parameters offset: " + po ); + log.debug(tableTag + " feature table lookup list index count: " + nl ); + } + // read lookup table indices + int[] lia = new int[nl]; + List lul = new java.util.ArrayList(); + for ( int i = 0; i < nl; i++ ) { + int li = in.readTTFUShort(); + if (log.isDebugEnabled()) { + log.debug(tableTag + " feature table lookup index: " + li ); + } + lia[i] = li; + lul.add ( "lu" + li ); + } + seFeatures.put ( "f" + featureIndex, new Object[] { featureTag, lul } ); + } + + private void readFeatureList(String tableTag, long featureList) throws IOException { + in.seekSet(featureList); + // read feature record count + int nf = in.readTTFUShort(); + if (log.isDebugEnabled()) { + log.debug(tableTag + " feature list record count: " + nf ); + } + if ( nf > 0 ) { + String[] fta = new String[nf]; + int[] foa = new int[nf]; + // read feature records + for ( int i = 0, n = nf; i < n; i++ ) { + String ft = in.readTTFString(4); + int fo = in.readTTFUShort(); + if (log.isDebugEnabled()) { + log.debug(tableTag + " feature tag: " + ft ); + log.debug(tableTag + " feature table offset: " + fo ); + } + fta[i] = ft; + foa[i] = fo; + } + // read feature tables + for ( int i = 0, n = nf; i < n; i++ ) { + if (log.isDebugEnabled()) { + log.debug(tableTag + " feature index: " + i ); + } + readFeatureTable ( tableTag, featureList + foa [ i ], fta [ i ], i ); + } + } + } + + static final class GDEFLookupType { + static final int GLYPH_CLASS = 1; + static final int ATTACHMENT_POINT = 2; + static final int LIGATURE_CARET = 3; + static final int MARK_ATTACHMENT = 4; + private GDEFLookupType() { + } + public static int getSubtableType ( int lt ) { + int st; + switch ( lt ) { + case GDEFLookupType.GLYPH_CLASS: + st = GlyphDefinitionTable.GDEF_LOOKUP_TYPE_GLYPH_CLASS; + break; + case GDEFLookupType.ATTACHMENT_POINT: + st = GlyphDefinitionTable.GDEF_LOOKUP_TYPE_ATTACHMENT_POINT; + break; + case GDEFLookupType.LIGATURE_CARET: + st = GlyphDefinitionTable.GDEF_LOOKUP_TYPE_LIGATURE_CARET; + break; + case GDEFLookupType.MARK_ATTACHMENT: + st = GlyphDefinitionTable.GDEF_LOOKUP_TYPE_MARK_ATTACHMENT; + break; + default: + st = -1; + break; + } + return st; + } + public static String toString(int type) { + String s; + switch ( type ) { + case GLYPH_CLASS: + s = "GlyphClass"; + break; + case ATTACHMENT_POINT: + s = "AttachmentPoint"; + break; + case LIGATURE_CARET: + s = "LigatureCaret"; + break; + case MARK_ATTACHMENT: + s = "MarkAttachment"; + break; + default: + s = "?"; + break; + } + return s; + } + } + + static final class GSUBLookupType { + static final int SINGLE = 1; + static final int MULTIPLE = 2; + static final int ALTERNATE = 3; + static final int LIGATURE = 4; + static final int CONTEXTUAL = 5; + static final int CHAINED_CONTEXTUAL = 6; + static final int EXTENSION = 7; + static final int REVERSE_CHAINED_SINGLE = 8; + private GSUBLookupType() { + } + public static int getSubtableType ( int lt ) { + int st; + switch ( lt ) { + case GSUBLookupType.SINGLE: + st = GlyphSubstitutionTable.GSUB_LOOKUP_TYPE_SINGLE; + break; + case GSUBLookupType.MULTIPLE: + st = GlyphSubstitutionTable.GSUB_LOOKUP_TYPE_MULTIPLE; + break; + case GSUBLookupType.ALTERNATE: + st = GlyphSubstitutionTable.GSUB_LOOKUP_TYPE_ALTERNATE; + break; + case GSUBLookupType.LIGATURE: + st = GlyphSubstitutionTable.GSUB_LOOKUP_TYPE_LIGATURE; + break; + case GSUBLookupType.CONTEXTUAL: + st = GlyphSubstitutionTable.GSUB_LOOKUP_TYPE_CONTEXTUAL; + break; + case GSUBLookupType.CHAINED_CONTEXTUAL: + st = GlyphSubstitutionTable.GSUB_LOOKUP_TYPE_CHAINED_CONTEXTUAL; + break; + case GSUBLookupType.EXTENSION: + st = GlyphSubstitutionTable.GSUB_LOOKUP_TYPE_EXTENSION_SUBSTITUTION; + break; + case GSUBLookupType.REVERSE_CHAINED_SINGLE: + st = GlyphSubstitutionTable.GSUB_LOOKUP_TYPE_REVERSE_CHAINED_SINGLE; + break; + default: + st = -1; + break; + } + return st; + } + public static String toString(int type) { + String s; + switch ( type ) { + case SINGLE: + s = "Single"; + break; + case MULTIPLE: + s = "Multiple"; + break; + case ALTERNATE: + s = "Alternate"; + break; + case LIGATURE: + s = "Ligature"; + break; + case CONTEXTUAL: + s = "Contextual"; + break; + case CHAINED_CONTEXTUAL: + s = "ChainedContextual"; + break; + case EXTENSION: + s = "Extension"; + break; + case REVERSE_CHAINED_SINGLE: + s = "ReverseChainedSingle"; + break; + default: + s = "?"; + break; + } + return s; + } + } + + static final class GPOSLookupType { + static final int SINGLE = 1; + static final int PAIR = 2; + static final int CURSIVE = 3; + static final int MARK_TO_BASE = 4; + static final int MARK_TO_LIGATURE = 5; + static final int MARK_TO_MARK = 6; + static final int CONTEXTUAL = 7; + static final int CHAINED_CONTEXTUAL = 8; + static final int EXTENSION = 9; + private GPOSLookupType() { + } + public static String toString(int type) { + String s; + switch ( type ) { + case SINGLE: + s = "Single"; + break; + case PAIR: + s = "Pair"; + break; + case CURSIVE: + s = "Cursive"; + break; + case MARK_TO_BASE: + s = "MarkToBase"; + break; + case MARK_TO_LIGATURE: + s = "MarkToLigature"; + break; + case MARK_TO_MARK: + s = "MarkToMark"; + break; + case CONTEXTUAL: + s = "Contextual"; + break; + case CHAINED_CONTEXTUAL: + s = "ChainedContextual"; + break; + case EXTENSION: + s = "Extension"; + break; + default: + s = "?"; + break; + } + return s; + } + } + + static final class LookupFlag { + static final int RIGHT_TO_LEFT = 0x0001; + static final int IGNORE_BASE_GLYPHS = 0x0002; + static final int IGNORE_LIGATURE = 0x0004; + static final int IGNORE_MARKS = 0x0008; + static final int USE_MARK_FILTERING_SET = 0x0010; + static final int MARK_ATTACHMENT_TYPE = 0xFF00; + private LookupFlag() { + } + public static String toString(int flags) { + StringBuffer sb = new StringBuffer(); + boolean first = true; + if ( ( flags & RIGHT_TO_LEFT ) != 0 ) { + if ( first ) { + first = false; + } else { + sb.append ( '|' ); + } + sb.append ( "RightToLeft" ); + } + if ( ( flags & IGNORE_BASE_GLYPHS ) != 0 ) { + if ( first ) { + first = false; + } else { + sb.append ( '|' ); + } + sb.append ( "IgnoreBaseGlyphs" ); + } + if ( ( flags & IGNORE_LIGATURE ) != 0 ) { + if ( first ) { + first = false; + } else { + sb.append ( '|' ); + } + sb.append ( "IgnoreLigature" ); + } + if ( ( flags & IGNORE_MARKS ) != 0 ) { + if ( first ) { + first = false; + } else { + sb.append ( '|' ); + } + sb.append ( "IgnoreMarks" ); + } + if ( ( flags & USE_MARK_FILTERING_SET ) != 0 ) { + if ( first ) { + first = false; + } else { + sb.append ( '|' ); + } + sb.append ( "UseMarkFilteringSet" ); + } + if ( sb.length() == 0 ) { + sb.append ( '-' ); + } + return sb.toString(); + } + } + + private GlyphCoverageTable readCoverageTableFormat1(String label, long tableOffset, int coverageFormat) throws IOException { + List entries = new java.util.ArrayList(); + in.seekSet(tableOffset); + // skip over format (already known) + in.skip ( 2 ); + // read glyph count + int ng = in.readTTFUShort(); + int[] ga = new int[ng]; + for ( int i = 0, n = ng; i < n; i++ ) { + int g = in.readTTFUShort(); + ga[i] = g; + entries.add ( Integer.valueOf(g) ); + } + // dump info if debugging + if (log.isDebugEnabled()) { + log.debug(label + " glyphs: " + toString(ga) ); + } + return GlyphCoverageTable.createCoverageTable ( entries ); + } + + private GlyphCoverageTable readCoverageTableFormat2(String label, long tableOffset, int coverageFormat) throws IOException { + List entries = new java.util.ArrayList(); + in.seekSet(tableOffset); + // skip over format (already known) + in.skip ( 2 ); + // read range record count + int nr = in.readTTFUShort(); + for ( int i = 0, n = nr; i < n; i++ ) { + // read range start + int s = in.readTTFUShort(); + // read range end + int e = in.readTTFUShort(); + // read range coverage (mapping) index + int m = in.readTTFUShort(); + // dump info if debugging + if (log.isDebugEnabled()) { + log.debug(label + " range[" + i + "]: [" + s + "," + e + "]: " + m ); + } + entries.add ( new GlyphCoverageTable.MappingRange ( s, e, m ) ); + } + return GlyphCoverageTable.createCoverageTable ( entries ); + } + + private GlyphCoverageTable readCoverageTable(String label, long tableOffset) throws IOException { + GlyphCoverageTable gct; + long cp = in.getCurrentPos(); + in.seekSet(tableOffset); + // read coverage table format + int cf = in.readTTFUShort(); + if ( cf == 1 ) { + gct = readCoverageTableFormat1 ( label, tableOffset, cf ); + } else if ( cf == 2 ) { + gct = readCoverageTableFormat2 ( label, tableOffset, cf ); + } else { + throw new AdvancedTypographicTableFormatException ( "unsupported coverage table format: " + cf ); + } + in.seekSet ( cp ); + return gct; + } + + private GlyphClassTable readClassDefTableFormat1(String label, long tableOffset, int classFormat) throws IOException { + List entries = new java.util.ArrayList(); + in.seekSet(tableOffset); + // skip over format (already known) + in.skip ( 2 ); + // read start glyph + int sg = in.readTTFUShort(); + entries.add ( Integer.valueOf(sg) ); + // read glyph count + int ng = in.readTTFUShort(); + // read glyph classes + int[] ca = new int[ng]; + for ( int i = 0, n = ng; i < n; i++ ) { + int gc = in.readTTFUShort(); + ca[i] = gc; + entries.add ( Integer.valueOf(gc) ); + } + // dump info if debugging + if (log.isDebugEnabled()) { + log.debug(label + " glyph classes: " + toString(ca) ); + } + return GlyphClassTable.createClassTable ( entries ); + } + + private GlyphClassTable readClassDefTableFormat2(String label, long tableOffset, int classFormat) throws IOException { + List entries = new java.util.ArrayList(); + in.seekSet(tableOffset); + // skip over format (already known) + in.skip ( 2 ); + // read range record count + int nr = in.readTTFUShort(); + for ( int i = 0, n = nr; i < n; i++ ) { + // read range start + int s = in.readTTFUShort(); + // read range end + int e = in.readTTFUShort(); + // read range glyph class (mapping) index + int m = in.readTTFUShort(); + // dump info if debugging + if (log.isDebugEnabled()) { + log.debug(label + " range[" + i + "]: [" + s + "," + e + "]: " + m ); + } + entries.add ( new GlyphClassTable.MappingRange ( s, e, m ) ); + } + return GlyphClassTable.createClassTable ( entries ); + } + + private GlyphClassTable readClassDefTable(String label, long tableOffset) throws IOException { + GlyphClassTable gct; + long cp = in.getCurrentPos(); + in.seekSet(tableOffset); + // read class table format + int cf = in.readTTFUShort(); + if ( cf == 1 ) { + gct = readClassDefTableFormat1 ( label, tableOffset, cf ); + } else if ( cf == 2 ) { + gct = readClassDefTableFormat2 ( label, tableOffset, cf ); + } else { + throw new AdvancedTypographicTableFormatException ( "unsupported class definition table format: " + cf ); + } + in.seekSet ( cp ); + return gct; + } + + private void readSingleSubTableFormat1(int lookupType, int lookupFlags, long subtableOffset, int subtableFormat) throws IOException { + String tableTag = "GSUB"; + in.seekSet(subtableOffset); + // skip over format (already known) + in.skip ( 2 ); + // read coverage offset + int co = in.readTTFUShort(); + // read delta glyph + int dg = in.readTTFShort(); + // dump info if debugging + if (log.isDebugEnabled()) { + log.debug(tableTag + " single substitution subtable format: " + subtableFormat + " (delta)" ); + log.debug(tableTag + " single substitution coverage table offset: " + co ); + log.debug(tableTag + " single substitution delta: " + dg ); + } + // read coverage table + seMapping = readCoverageTable ( tableTag + " single substitution coverage", subtableOffset + co ); + seEntries.add ( Integer.valueOf ( dg ) ); + } + + private void readSingleSubTableFormat2(int lookupType, int lookupFlags, long subtableOffset, int subtableFormat) throws IOException { + String tableTag = "GSUB"; + in.seekSet(subtableOffset); + // skip over format (already known) + in.skip ( 2 ); + // read coverage offset + int co = in.readTTFUShort(); + // read glyph count + int ng = in.readTTFUShort(); + // dump info if debugging + if (log.isDebugEnabled()) { + log.debug(tableTag + " single substitution subtable format: " + subtableFormat + " (mapped)" ); + log.debug(tableTag + " single substitution coverage table offset: " + co ); + log.debug(tableTag + " single substitution glyph count: " + ng ); + } + // read coverage table + seMapping = readCoverageTable ( tableTag + " single substitution coverage", subtableOffset + co ); + // read glyph substitutions + int[] gsa = new int[ng]; + for ( int i = 0, n = ng; i < n; i++ ) { + int gs = in.readTTFUShort(); + if (log.isDebugEnabled()) { + log.debug(tableTag + " single substitution glyph[" + i + "]: " + gs ); + } + gsa[i] = gs; + seEntries.add ( Integer.valueOf ( gs ) ); + } + } + + private int readSingleSubTable(int lookupType, int lookupFlags, long subtableOffset) throws IOException { + in.seekSet(subtableOffset); + // read substitution subtable format + int sf = in.readTTFUShort(); + if ( sf == 1 ) { + readSingleSubTableFormat1 ( lookupType, lookupFlags, subtableOffset, sf ); + } else if ( sf == 2 ) { + readSingleSubTableFormat2 ( lookupType, lookupFlags, subtableOffset, sf ); + } else { + throw new AdvancedTypographicTableFormatException ( "unsupported single substitution subtable format: " + sf ); + } + return sf; + } + + private void readMultipleSubTableFormat1(int lookupType, int lookupFlags, long subtableOffset, int subtableFormat) throws IOException { + String tableTag = "GSUB"; + in.seekSet(subtableOffset); + // skip over format (already known) + in.skip ( 2 ); + // read coverage offset + int co = in.readTTFUShort(); + // read sequence count + int ns = in.readTTFUShort(); + // dump info if debugging + if (log.isDebugEnabled()) { + log.debug(tableTag + " multiple substitution subtable format: " + subtableFormat + " (mapped)" ); + log.debug(tableTag + " multiple substitution coverage table offset: " + co ); + log.debug(tableTag + " multiple substitution sequence count: " + ns ); + } + // read coverage table + seMapping = readCoverageTable ( tableTag + " multiple substitution coverage", subtableOffset + co ); + // read sequence table offsets + int[] soa = new int[ns]; + for ( int i = 0, n = ns; i < n; i++ ) { + soa[i] = in.readTTFUShort(); + } + // read sequence tables + int[][] gsa = new int [ ns ] []; + for ( int i = 0, n = ns; i < n; i++ ) { + int so = soa[i]; + int[] ga; + if ( so > 0 ) { + in.seekSet(subtableOffset + so); + // read glyph count + int ng = in.readTTFUShort(); + ga = new int[ng]; + for ( int j = 0; j < ng; j++ ) { + ga[j] = in.readTTFUShort(); + } + } else { + ga = null; + } + if (log.isDebugEnabled()) { + log.debug(tableTag + " multiple substitution sequence[" + i + "]: " + toString ( ga ) ); + } + gsa [ i ] = ga; + } + seEntries.add ( gsa ); + } + + private int readMultipleSubTable(int lookupType, int lookupFlags, long subtableOffset) throws IOException { + in.seekSet(subtableOffset); + // read substitution subtable format + int sf = in.readTTFUShort(); + if ( sf == 1 ) { + readMultipleSubTableFormat1 ( lookupType, lookupFlags, subtableOffset, sf ); + } else { + throw new AdvancedTypographicTableFormatException ( "unsupported multiple substitution subtable format: " + sf ); + } + return sf; + } + + private void readAlternateSubTableFormat1(int lookupType, int lookupFlags, long subtableOffset, int subtableFormat) throws IOException { + String tableTag = "GSUB"; + in.seekSet(subtableOffset); + // skip over format (already known) + in.skip ( 2 ); + // read coverage offset + int co = in.readTTFUShort(); + // read alternate set count + int ns = in.readTTFUShort(); + // dump info if debugging + if (log.isDebugEnabled()) { + log.debug(tableTag + " alternate substitution subtable format: " + subtableFormat + " (mapped)" ); + log.debug(tableTag + " alternate substitution coverage table offset: " + co ); + log.debug(tableTag + " alternate substitution alternate set count: " + ns ); + } + // read coverage table + seMapping = readCoverageTable ( tableTag + " alternate substitution coverage", subtableOffset + co ); + // read alternate set table offsets + int[] soa = new int[ns]; + for ( int i = 0, n = ns; i < n; i++ ) { + soa[i] = in.readTTFUShort(); + } + // read alternate set tables + for ( int i = 0, n = ns; i < n; i++ ) { + int so = soa[i]; + in.seekSet(subtableOffset + so); + // read glyph count + int ng = in.readTTFUShort(); + int[] ga = new int[ng]; + for ( int j = 0; j < ng; j++ ) { + int gs = in.readTTFUShort(); + ga[j] = gs; + } + if (log.isDebugEnabled()) { + log.debug(tableTag + " alternate substitution alternate set[" + i + "]: " + toString ( ga ) ); + } + seEntries.add ( ga ); + } + } + + private int readAlternateSubTable(int lookupType, int lookupFlags, long subtableOffset) throws IOException { + in.seekSet(subtableOffset); + // read substitution subtable format + int sf = in.readTTFUShort(); + if ( sf == 1 ) { + readAlternateSubTableFormat1 ( lookupType, lookupFlags, subtableOffset, sf ); + } else { + throw new AdvancedTypographicTableFormatException ( "unsupported alternate substitution subtable format: " + sf ); + } + return sf; + } + + private void readLigatureSubTableFormat1(int lookupType, int lookupFlags, long subtableOffset, int subtableFormat) throws IOException { + String tableTag = "GSUB"; + in.seekSet(subtableOffset); + // skip over format (already known) + in.skip ( 2 ); + // read coverage offset + int co = in.readTTFUShort(); + // read ligature set count + int ns = in.readTTFUShort(); + // dump info if debugging + if (log.isDebugEnabled()) { + log.debug(tableTag + " ligature substitution subtable format: " + subtableFormat + " (mapped)" ); + log.debug(tableTag + " ligature substitution coverage table offset: " + co ); + log.debug(tableTag + " ligature substitution ligature set count: " + ns ); + } + // read coverage table + seMapping = readCoverageTable ( tableTag + " ligature substitution coverage", subtableOffset + co ); + // read ligature set table offsets + int[] soa = new int[ns]; + for ( int i = 0, n = ns; i < n; i++ ) { + soa[i] = in.readTTFUShort(); + } + // read ligature set tables + for ( int i = 0, n = ns; i < n; i++ ) { + int so = soa[i]; + in.seekSet(subtableOffset + so); + // read ligature table count + int nl = in.readTTFUShort(); + int[] loa = new int[nl]; + for ( int j = 0; j < nl; j++ ) { + loa[j] = in.readTTFUShort(); + } + List ligs = new java.util.ArrayList(); + for ( int j = 0; j < nl; j++ ) { + int lo = loa[j]; + in.seekSet(subtableOffset + so + lo); + // read ligature glyph id + int lg = in.readTTFUShort(); + // read ligature (input) component count + int nc = in.readTTFUShort(); + int[] ca = new int [ nc - 1 ]; + // read ligature (input) component glyph ids + for ( int k = 0; k < nc - 1; k++ ) { + ca[k] = in.readTTFUShort(); + } + if (log.isDebugEnabled()) { + log.debug(tableTag + " ligature substitution ligature set[" + i + "]: ligature(" + lg + "), components: " + toString ( ca ) ); + } + ligs.add ( new GlyphSubstitutionTable.Ligature ( lg, ca ) ); + } + seEntries.add ( new GlyphSubstitutionTable.LigatureSet ( ligs ) ); + } + } + + private int readLigatureSubTable(int lookupType, int lookupFlags, long subtableOffset) throws IOException { + in.seekSet(subtableOffset); + // read substitution subtable format + int sf = in.readTTFUShort(); + if ( sf == 1 ) { + readLigatureSubTableFormat1 ( lookupType, lookupFlags, subtableOffset, sf ); + } else { + throw new AdvancedTypographicTableFormatException ( "unsupported ligature substitution subtable format: " + sf ); + } + return sf; + } + + private GlyphTable.RuleLookup[] readRuleLookups(int numLookups, String header) throws IOException { + GlyphTable.RuleLookup[] la = new GlyphTable.RuleLookup [ numLookups ]; + for ( int i = 0, n = numLookups; i < n; i++ ) { + int sequenceIndex = in.readTTFUShort(); + int lookupIndex = in.readTTFUShort(); + la [ i ] = new GlyphTable.RuleLookup ( sequenceIndex, lookupIndex ); + // dump info if debugging and header is non-null + if ( log.isDebugEnabled() && ( header != null ) ) { + log.debug(header + "lookup[" + i + "]: " + la[i]); + } + } + return la; + } + + private void readContextualSubTableFormat1(int lookupType, int lookupFlags, long subtableOffset, int subtableFormat) throws IOException { + String tableTag = "GSUB"; + in.seekSet(subtableOffset); + // skip over format (already known) + in.skip ( 2 ); + // read coverage offset + int co = in.readTTFUShort(); + // read rule set count + int nrs = in.readTTFUShort(); + // read rule set offsets + int[] rsoa = new int [ nrs ]; + for ( int i = 0; i < nrs; i++ ) { + rsoa [ i ] = in.readTTFUShort(); + } + // dump info if debugging + if (log.isDebugEnabled()) { + log.debug(tableTag + " contextual substitution format: " + subtableFormat + " (glyphs)" ); + log.debug(tableTag + " contextual substitution coverage table offset: " + co ); + log.debug(tableTag + " contextual substitution rule set count: " + nrs ); + for ( int i = 0; i < nrs; i++ ) { + log.debug(tableTag + " contextual substitution rule set offset[" + i + "]: " + rsoa[i] ); + } + } + // read coverage table + GlyphCoverageTable ct; + if ( co > 0 ) { + ct = readCoverageTable ( tableTag + " contextual substitution coverage", subtableOffset + co ); + } else { + ct = null; + } + // read rule sets + GlyphTable.RuleSet[] rsa = new GlyphTable.RuleSet [ nrs ]; + String header = null; + for ( int i = 0; i < nrs; i++ ) { + GlyphTable.RuleSet rs; + int rso = rsoa [ i ]; + if ( rso > 0 ) { + // seek to rule set [ i ] + in.seekSet ( subtableOffset + rso ); + // read rule count + int nr = in.readTTFUShort(); + // read rule offsets + int[] roa = new int [ nr ]; + GlyphTable.Rule[] ra = new GlyphTable.Rule [ nr ]; + for ( int j = 0; j < nr; j++ ) { + roa [ j ] = in.readTTFUShort(); + } + // read glyph sequence rules + for ( int j = 0; j < nr; j++ ) { + GlyphTable.GlyphSequenceRule r; + int ro = roa [ j ]; + if ( ro > 0 ) { + // seek to rule [ j ] + in.seekSet ( subtableOffset + rso + ro ); + // read glyph count + int ng = in.readTTFUShort(); + // read rule lookup count + int nl = in.readTTFUShort(); + // read glyphs + int[] glyphs = new int [ ng - 1 ]; + for ( int k = 0, nk = glyphs.length; k < nk; k++ ) { + glyphs [ k ] = in.readTTFUShort(); + } + // read rule lookups + if (log.isDebugEnabled()) { + header = tableTag + " contextual substitution lookups @rule[" + i + "][" + j + "]: "; + } + GlyphTable.RuleLookup[] lookups = readRuleLookups ( nl, header ); + r = new GlyphTable.GlyphSequenceRule ( lookups, ng, glyphs ); + } else { + r = null; + } + ra [ j ] = r; + } + rs = new GlyphTable.HomogeneousRuleSet ( ra ); + } else { + rs = null; + } + rsa [ i ] = rs; + } + // store results + seMapping = ct; + seEntries.add ( rsa ); + } + + private void readContextualSubTableFormat2(int lookupType, int lookupFlags, long subtableOffset, int subtableFormat) throws IOException { + String tableTag = "GSUB"; + in.seekSet(subtableOffset); + // skip over format (already known) + in.skip ( 2 ); + // read coverage offset + int co = in.readTTFUShort(); + // read class def table offset + int cdo = in.readTTFUShort(); + // read class rule set count + int ngc = in.readTTFUShort(); + // read class rule set offsets + int[] csoa = new int [ ngc ]; + for ( int i = 0; i < ngc; i++ ) { + csoa [ i ] = in.readTTFUShort(); + } + // dump info if debugging + if (log.isDebugEnabled()) { + log.debug(tableTag + " contextual substitution format: " + subtableFormat + " (glyph classes)" ); + log.debug(tableTag + " contextual substitution coverage table offset: " + co ); + log.debug(tableTag + " contextual substitution class set count: " + ngc ); + for ( int i = 0; i < ngc; i++ ) { + log.debug(tableTag + " contextual substitution class set offset[" + i + "]: " + csoa[i] ); + } + } + // read coverage table + GlyphCoverageTable ct; + if ( co > 0 ) { + ct = readCoverageTable ( tableTag + " contextual substitution coverage", subtableOffset + co ); + } else { + ct = null; + } + // read class definition table + GlyphClassTable cdt; + if ( cdo > 0 ) { + cdt = readClassDefTable ( tableTag + " contextual substitution class definition", subtableOffset + cdo ); + } else { + cdt = null; + } + // read rule sets + GlyphTable.RuleSet[] rsa = new GlyphTable.RuleSet [ ngc ]; + String header = null; + for ( int i = 0; i < ngc; i++ ) { + int cso = csoa [ i ]; + GlyphTable.RuleSet rs; + if ( cso > 0 ) { + // seek to rule set [ i ] + in.seekSet ( subtableOffset + cso ); + // read rule count + int nr = in.readTTFUShort(); + // read rule offsets + int[] roa = new int [ nr ]; + GlyphTable.Rule[] ra = new GlyphTable.Rule [ nr ]; + for ( int j = 0; j < nr; j++ ) { + roa [ j ] = in.readTTFUShort(); + } + // read glyph sequence rules + for ( int j = 0; j < nr; j++ ) { + int ro = roa [ j ]; + GlyphTable.ClassSequenceRule r; + if ( ro > 0 ) { + // seek to rule [ j ] + in.seekSet ( subtableOffset + cso + ro ); + // read glyph count + int ng = in.readTTFUShort(); + // read rule lookup count + int nl = in.readTTFUShort(); + // read classes + int[] classes = new int [ ng - 1 ]; + for ( int k = 0, nk = classes.length; k < nk; k++ ) { + classes [ k ] = in.readTTFUShort(); + } + // read rule lookups + if (log.isDebugEnabled()) { + header = tableTag + " contextual substitution lookups @rule[" + i + "][" + j + "]: "; + } + GlyphTable.RuleLookup[] lookups = readRuleLookups ( nl, header ); + r = new GlyphTable.ClassSequenceRule ( lookups, ng, classes ); + } else { + assert ro > 0 : "unexpected null subclass rule offset"; + r = null; + } + ra [ j ] = r; + } + rs = new GlyphTable.HomogeneousRuleSet ( ra ); + } else { + rs = null; + } + rsa [ i ] = rs; + } + // store results + seMapping = ct; + seEntries.add ( cdt ); + seEntries.add ( Integer.valueOf ( ngc ) ); + seEntries.add ( rsa ); + } + + private void readContextualSubTableFormat3(int lookupType, int lookupFlags, long subtableOffset, int subtableFormat) throws IOException { + String tableTag = "GSUB"; + in.seekSet(subtableOffset); + // skip over format (already known) + in.skip ( 2 ); + // read glyph (input sequence length) count + int ng = in.readTTFUShort(); + // read substitution lookup count + int nl = in.readTTFUShort(); + // read glyph coverage offsets, one per glyph input sequence length count + int[] gcoa = new int [ ng ]; + for ( int i = 0; i < ng; i++ ) { + gcoa [ i ] = in.readTTFUShort(); + } + // dump info if debugging + if (log.isDebugEnabled()) { + log.debug(tableTag + " contextual substitution format: " + subtableFormat + " (glyph sets)" ); + log.debug(tableTag + " contextual substitution glyph input sequence length count: " + ng ); + log.debug(tableTag + " contextual substitution lookup count: " + nl ); + for ( int i = 0; i < ng; i++ ) { + log.debug(tableTag + " contextual substitution coverage table offset[" + i + "]: " + gcoa[i] ); + } + } + // read coverage tables + GlyphCoverageTable[] gca = new GlyphCoverageTable [ ng ]; + for ( int i = 0; i < ng; i++ ) { + int gco = gcoa [ i ]; + GlyphCoverageTable gct; + if ( gco > 0 ) { + gct = readCoverageTable ( tableTag + " contextual substitution coverage[" + i + "]", subtableOffset + gco ); + } else { + gct = null; + } + gca [ i ] = gct; + } + // read rule lookups + String header = null; + if (log.isDebugEnabled()) { + header = tableTag + " contextual substitution lookups: "; + } + GlyphTable.RuleLookup[] lookups = readRuleLookups ( nl, header ); + // construct rule, rule set, and rule set array + GlyphTable.Rule r = new GlyphTable.CoverageSequenceRule ( lookups, ng, gca ); + GlyphTable.RuleSet rs = new GlyphTable.HomogeneousRuleSet ( new GlyphTable.Rule[] {r} ); + GlyphTable.RuleSet[] rsa = new GlyphTable.RuleSet[] {rs}; + // store results + assert ( gca != null ) && ( gca.length > 0 ); + seMapping = gca[0]; + seEntries.add ( rsa ); + } + + private int readContextualSubTable(int lookupType, int lookupFlags, long subtableOffset) throws IOException { + in.seekSet(subtableOffset); + // read substitution subtable format + int sf = in.readTTFUShort(); + if ( sf == 1 ) { + readContextualSubTableFormat1 ( lookupType, lookupFlags, subtableOffset, sf ); + } else if ( sf == 2 ) { + readContextualSubTableFormat2 ( lookupType, lookupFlags, subtableOffset, sf ); + } else if ( sf == 3 ) { + readContextualSubTableFormat3 ( lookupType, lookupFlags, subtableOffset, sf ); + } else { + throw new AdvancedTypographicTableFormatException ( "unsupported contextual substitution subtable format: " + sf ); + } + return sf; + } + + private void readChainedContextualSubTableFormat1(int lookupType, int lookupFlags, long subtableOffset, int subtableFormat) throws IOException { + String tableTag = "GSUB"; + in.seekSet(subtableOffset); + // skip over format (already known) + in.skip ( 2 ); + // read coverage offset + int co = in.readTTFUShort(); + // read rule set count + int nrs = in.readTTFUShort(); + // read rule set offsets + int[] rsoa = new int [ nrs ]; + for ( int i = 0; i < nrs; i++ ) { + rsoa [ i ] = in.readTTFUShort(); + } + // dump info if debugging + if (log.isDebugEnabled()) { + log.debug(tableTag + " chained contextual substitution format: " + subtableFormat + " (glyphs)" ); + log.debug(tableTag + " chained contextual substitution coverage table offset: " + co ); + log.debug(tableTag + " chained contextual substitution rule set count: " + nrs ); + for ( int i = 0; i < nrs; i++ ) { + log.debug(tableTag + " chained contextual substitution rule set offset[" + i + "]: " + rsoa[i] ); + } + } + // read coverage table + GlyphCoverageTable ct; + if ( co > 0 ) { + ct = readCoverageTable ( tableTag + " chained contextual substitution coverage", subtableOffset + co ); + } else { + ct = null; + } + // read rule sets + GlyphTable.RuleSet[] rsa = new GlyphTable.RuleSet [ nrs ]; + String header = null; + for ( int i = 0; i < nrs; i++ ) { + GlyphTable.RuleSet rs; + int rso = rsoa [ i ]; + if ( rso > 0 ) { + // seek to rule set [ i ] + in.seekSet ( subtableOffset + rso ); + // read rule count + int nr = in.readTTFUShort(); + // read rule offsets + int[] roa = new int [ nr ]; + GlyphTable.Rule[] ra = new GlyphTable.Rule [ nr ]; + for ( int j = 0; j < nr; j++ ) { + roa [ j ] = in.readTTFUShort(); + } + // read glyph sequence rules + for ( int j = 0; j < nr; j++ ) { + GlyphTable.ChainedGlyphSequenceRule r; + int ro = roa [ j ]; + if ( ro > 0 ) { + // seek to rule [ j ] + in.seekSet ( subtableOffset + rso + ro ); + // read backtrack glyph count + int nbg = in.readTTFUShort(); + // read backtrack glyphs + int[] backtrackGlyphs = new int [ nbg ]; + for ( int k = 0, nk = backtrackGlyphs.length; k < nk; k++ ) { + backtrackGlyphs [ k ] = in.readTTFUShort(); + } + // read input glyph count + int nig = in.readTTFUShort(); + // read glyphs + int[] glyphs = new int [ nig - 1 ]; + for ( int k = 0, nk = glyphs.length; k < nk; k++ ) { + glyphs [ k ] = in.readTTFUShort(); + } + // read lookahead glyph count + int nlg = in.readTTFUShort(); + // read lookahead glyphs + int[] lookaheadGlyphs = new int [ nlg ]; + for ( int k = 0, nk = lookaheadGlyphs.length; k < nk; k++ ) { + lookaheadGlyphs [ k ] = in.readTTFUShort(); + } + // read rule lookup count + int nl = in.readTTFUShort(); + // read rule lookups + if (log.isDebugEnabled()) { + header = tableTag + " contextual substitution lookups @rule[" + i + "][" + j + "]: "; + } + GlyphTable.RuleLookup[] lookups = readRuleLookups ( nl, header ); + r = new GlyphTable.ChainedGlyphSequenceRule ( lookups, nig, glyphs, backtrackGlyphs, lookaheadGlyphs ); + } else { + r = null; + } + ra [ j ] = r; + } + rs = new GlyphTable.HomogeneousRuleSet ( ra ); + } else { + rs = null; + } + rsa [ i ] = rs; + } + // store results + seMapping = ct; + seEntries.add ( rsa ); + } + + private void readChainedContextualSubTableFormat2(int lookupType, int lookupFlags, long subtableOffset, int subtableFormat) throws IOException { + String tableTag = "GSUB"; + in.seekSet(subtableOffset); + // skip over format (already known) + in.skip ( 2 ); + // read coverage offset + int co = in.readTTFUShort(); + // read backtrack class def table offset + int bcdo = in.readTTFUShort(); + // read input class def table offset + int icdo = in.readTTFUShort(); + // read lookahead class def table offset + int lcdo = in.readTTFUShort(); + // read class set count + int ngc = in.readTTFUShort(); + // read class set offsets + int[] csoa = new int [ ngc ]; + for ( int i = 0; i < ngc; i++ ) { + csoa [ i ] = in.readTTFUShort(); + } + // dump info if debugging + if (log.isDebugEnabled()) { + log.debug(tableTag + " chained contextual substitution format: " + subtableFormat + " (glyph classes)" ); + log.debug(tableTag + " chained contextual substitution coverage table offset: " + co ); + log.debug(tableTag + " chained contextual substitution class set count: " + ngc ); + for ( int i = 0; i < ngc; i++ ) { + log.debug(tableTag + " chained contextual substitution class set offset[" + i + "]: " + csoa[i] ); + } + } + // read coverage table + GlyphCoverageTable ct; + if ( co > 0 ) { + ct = readCoverageTable ( tableTag + " chained contextual substitution coverage", subtableOffset + co ); + } else { + ct = null; + } + // read backtrack class definition table + GlyphClassTable bcdt; + if ( bcdo > 0 ) { + bcdt = readClassDefTable ( tableTag + " contextual substitution backtrack class definition", subtableOffset + bcdo ); + } else { + bcdt = null; + } + // read input class definition table + GlyphClassTable icdt; + if ( icdo > 0 ) { + icdt = readClassDefTable ( tableTag + " contextual substitution input class definition", subtableOffset + icdo ); + } else { + icdt = null; + } + // read lookahead class definition table + GlyphClassTable lcdt; + if ( lcdo > 0 ) { + lcdt = readClassDefTable ( tableTag + " contextual substitution lookahead class definition", subtableOffset + lcdo ); + } else { + lcdt = null; + } + // read rule sets + GlyphTable.RuleSet[] rsa = new GlyphTable.RuleSet [ ngc ]; + String header = null; + for ( int i = 0; i < ngc; i++ ) { + int cso = csoa [ i ]; + GlyphTable.RuleSet rs; + if ( cso > 0 ) { + // seek to rule set [ i ] + in.seekSet ( subtableOffset + cso ); + // read rule count + int nr = in.readTTFUShort(); + // read rule offsets + int[] roa = new int [ nr ]; + GlyphTable.Rule[] ra = new GlyphTable.Rule [ nr ]; + for ( int j = 0; j < nr; j++ ) { + roa [ j ] = in.readTTFUShort(); + } + // read glyph sequence rules + for ( int j = 0; j < nr; j++ ) { + int ro = roa [ j ]; + GlyphTable.ChainedClassSequenceRule r; + if ( ro > 0 ) { + // seek to rule [ j ] + in.seekSet ( subtableOffset + cso + ro ); + // read backtrack glyph class count + int nbc = in.readTTFUShort(); + // read backtrack glyph classes + int[] backtrackClasses = new int [ nbc ]; + for ( int k = 0, nk = backtrackClasses.length; k < nk; k++ ) { + backtrackClasses [ k ] = in.readTTFUShort(); + } + // read input glyph class count + int nic = in.readTTFUShort(); + // read input glyph classes + int[] classes = new int [ nic - 1 ]; + for ( int k = 0, nk = classes.length; k < nk; k++ ) { + classes [ k ] = in.readTTFUShort(); + } + // read lookahead glyph class count + int nlc = in.readTTFUShort(); + // read lookahead glyph classes + int[] lookaheadClasses = new int [ nlc ]; + for ( int k = 0, nk = lookaheadClasses.length; k < nk; k++ ) { + lookaheadClasses [ k ] = in.readTTFUShort(); + } + // read rule lookup count + int nl = in.readTTFUShort(); + // read rule lookups + if (log.isDebugEnabled()) { + header = tableTag + " contextual substitution lookups @rule[" + i + "][" + j + "]: "; + } + GlyphTable.RuleLookup[] lookups = readRuleLookups ( nl, header ); + r = new GlyphTable.ChainedClassSequenceRule ( lookups, nic, classes, backtrackClasses, lookaheadClasses ); + } else { + r = null; + } + ra [ j ] = r; + } + rs = new GlyphTable.HomogeneousRuleSet ( ra ); + } else { + rs = null; + } + rsa [ i ] = rs; + } + // store results + seMapping = ct; + seEntries.add ( icdt ); + seEntries.add ( bcdt ); + seEntries.add ( lcdt ); + seEntries.add ( Integer.valueOf ( ngc ) ); + seEntries.add ( rsa ); + } + + private void readChainedContextualSubTableFormat3(int lookupType, int lookupFlags, long subtableOffset, int subtableFormat) throws IOException { + String tableTag = "GSUB"; + in.seekSet(subtableOffset); + // skip over format (already known) + in.skip ( 2 ); + // read backtrack glyph count + int nbg = in.readTTFUShort(); + // read backtrack glyph coverage offsets + int[] bgcoa = new int [ nbg ]; + for ( int i = 0; i < nbg; i++ ) { + bgcoa [ i ] = in.readTTFUShort(); + } + // read input glyph count + int nig = in.readTTFUShort(); + // read input glyph coverage offsets + int[] igcoa = new int [ nig ]; + for ( int i = 0; i < nig; i++ ) { + igcoa [ i ] = in.readTTFUShort(); + } + // read lookahead glyph count + int nlg = in.readTTFUShort(); + // read lookahead glyph coverage offsets + int[] lgcoa = new int [ nlg ]; + for ( int i = 0; i < nlg; i++ ) { + lgcoa [ i ] = in.readTTFUShort(); + } + // read substitution lookup count + int nl = in.readTTFUShort(); + // dump info if debugging + if (log.isDebugEnabled()) { + log.debug(tableTag + " chained contextual substitution format: " + subtableFormat + " (glyph sets)" ); + log.debug(tableTag + " chained contextual substitution backtrack glyph count: " + nbg ); + for ( int i = 0; i < nbg; i++ ) { + log.debug(tableTag + " chained contextual substitution backtrack coverage table offset[" + i + "]: " + bgcoa[i] ); + } + log.debug(tableTag + " chained contextual substitution input glyph count: " + nig ); + for ( int i = 0; i < nig; i++ ) { + log.debug(tableTag + " chained contextual substitution input coverage table offset[" + i + "]: " + igcoa[i] ); + } + log.debug(tableTag + " chained contextual substitution lookahead glyph count: " + nlg ); + for ( int i = 0; i < nlg; i++ ) { + log.debug(tableTag + " chained contextual substitution lookahead coverage table offset[" + i + "]: " + lgcoa[i] ); + } + log.debug(tableTag + " chained contextual substitution lookup count: " + nl ); + } + // read backtrack coverage tables + GlyphCoverageTable[] bgca = new GlyphCoverageTable[nbg]; + for ( int i = 0; i < nbg; i++ ) { + int bgco = bgcoa [ i ]; + GlyphCoverageTable bgct; + if ( bgco > 0 ) { + bgct = readCoverageTable ( tableTag + " chained contextual substitution backtrack coverage[" + i + "]", subtableOffset + bgco ); + } else { + bgct = null; + } + bgca[i] = bgct; + } + // read input coverage tables + GlyphCoverageTable[] igca = new GlyphCoverageTable[nig]; + for ( int i = 0; i < nig; i++ ) { + int igco = igcoa [ i ]; + GlyphCoverageTable igct; + if ( igco > 0 ) { + igct = readCoverageTable ( tableTag + " chained contextual substitution input coverage[" + i + "]", subtableOffset + igco ); + } else { + igct = null; + } + igca[i] = igct; + } + // read lookahead coverage tables + GlyphCoverageTable[] lgca = new GlyphCoverageTable[nlg]; + for ( int i = 0; i < nlg; i++ ) { + int lgco = lgcoa [ i ]; + GlyphCoverageTable lgct; + if ( lgco > 0 ) { + lgct = readCoverageTable ( tableTag + " chained contextual substitution lookahead coverage[" + i + "]", subtableOffset + lgco ); + } else { + lgct = null; + } + lgca[i] = lgct; + } + // read rule lookups + String header = null; + if (log.isDebugEnabled()) { + header = tableTag + " chained contextual substitution lookups: "; + } + GlyphTable.RuleLookup[] lookups = readRuleLookups ( nl, header ); + // construct rule, rule set, and rule set array + GlyphTable.Rule r = new GlyphTable.ChainedCoverageSequenceRule ( lookups, nig, igca, bgca, lgca ); + GlyphTable.RuleSet rs = new GlyphTable.HomogeneousRuleSet ( new GlyphTable.Rule[] {r} ); + GlyphTable.RuleSet[] rsa = new GlyphTable.RuleSet[] {rs}; + // store results + assert ( igca != null ) && ( igca.length > 0 ); + seMapping = igca[0]; + seEntries.add ( rsa ); + } + + private int readChainedContextualSubTable(int lookupType, int lookupFlags, long subtableOffset) throws IOException { + in.seekSet(subtableOffset); + // read substitution subtable format + int sf = in.readTTFUShort(); + if ( sf == 1 ) { + readChainedContextualSubTableFormat1 ( lookupType, lookupFlags, subtableOffset, sf ); + } else if ( sf == 2 ) { + readChainedContextualSubTableFormat2 ( lookupType, lookupFlags, subtableOffset, sf ); + } else if ( sf == 3 ) { + readChainedContextualSubTableFormat3 ( lookupType, lookupFlags, subtableOffset, sf ); + } else { + throw new AdvancedTypographicTableFormatException ( "unsupported chained contextual substitution subtable format: " + sf ); + } + return sf; + } + + private void readExtensionSubTableFormat1(int lookupType, int lookupFlags, int lookupSequence, int subtableSequence, long subtableOffset, int subtableFormat) throws IOException { + String tableTag = "GSUB"; + in.seekSet(subtableOffset); + // skip over format (already known) + in.skip ( 2 ); + // read extension lookup type + int lt = in.readTTFUShort(); + // read extension offset + long eo = in.readTTFULong(); + // dump info if debugging + if (log.isDebugEnabled()) { + log.debug(tableTag + " extension substitution subtable format: " + subtableFormat ); + log.debug(tableTag + " extension substitution lookup type: " + lt ); + log.debug(tableTag + " extension substitution lookup table offset: " + eo ); + } + // read referenced subtable from extended offset + readGSUBSubtable ( lt, lookupFlags, lookupSequence, subtableSequence, subtableOffset + eo ); + } + + private int readExtensionSubTable(int lookupType, int lookupFlags, int lookupSequence, int subtableSequence, long subtableOffset) throws IOException { + in.seekSet(subtableOffset); + // read substitution subtable format + int sf = in.readTTFUShort(); + if ( sf == 1 ) { + readExtensionSubTableFormat1 ( lookupType, lookupFlags, lookupSequence, subtableSequence, subtableOffset, sf ); + } else { + throw new AdvancedTypographicTableFormatException ( "unsupported extension substitution subtable format: " + sf ); + } + return sf; + } + + private void readReverseChainedSingleSubTableFormat1(int lookupType, int lookupFlags, long subtableOffset, int subtableFormat) throws IOException { + String tableTag = "GSUB"; + in.seekSet(subtableOffset); + // skip over format (already known) + in.skip ( 2 ); + // read coverage offset + int co = in.readTTFUShort(); + // read backtrack glyph count + int nbg = in.readTTFUShort(); + // read backtrack glyph coverage offsets + int[] bgcoa = new int [ nbg ]; + for ( int i = 0; i < nbg; i++ ) { + bgcoa [ i ] = in.readTTFUShort(); + } + // read lookahead glyph count + int nlg = in.readTTFUShort(); + // read backtrack glyph coverage offsets + int[] lgcoa = new int [ nlg ]; + for ( int i = 0; i < nlg; i++ ) { + lgcoa [ i ] = in.readTTFUShort(); + } + // read substitution (output) glyph count + int ng = in.readTTFUShort(); + // read substitution (output) glyphs + int[] glyphs = new int [ ng ]; + for ( int i = 0, n = ng; i < n; i++ ) { + glyphs [ i ] = in.readTTFUShort(); + } + // dump info if debugging + if (log.isDebugEnabled()) { + log.debug(tableTag + " reverse chained contextual substitution format: " + subtableFormat ); + log.debug(tableTag + " reverse chained contextual substitution coverage table offset: " + co ); + log.debug(tableTag + " reverse chained contextual substitution backtrack glyph count: " + nbg ); + for ( int i = 0; i < nbg; i++ ) { + log.debug(tableTag + " reverse chained contextual substitution backtrack coverage table offset[" + i + "]: " + bgcoa[i] ); + } + log.debug(tableTag + " reverse chained contextual substitution lookahead glyph count: " + nlg ); + for ( int i = 0; i < nlg; i++ ) { + log.debug(tableTag + " reverse chained contextual substitution lookahead coverage table offset[" + i + "]: " + lgcoa[i] ); + } + log.debug(tableTag + " reverse chained contextual substitution glyphs: " + toString(glyphs) ); + } + // read coverage table + GlyphCoverageTable ct = readCoverageTable ( tableTag + " reverse chained contextual substitution coverage", subtableOffset + co ); + // read backtrack coverage tables + GlyphCoverageTable[] bgca = new GlyphCoverageTable[nbg]; + for ( int i = 0; i < nbg; i++ ) { + int bgco = bgcoa[i]; + GlyphCoverageTable bgct; + if ( bgco > 0 ) { + bgct = readCoverageTable ( tableTag + " reverse chained contextual substitution backtrack coverage[" + i + "]", subtableOffset + bgco ); + } else { + bgct = null; + } + bgca[i] = bgct; + } + // read lookahead coverage tables + GlyphCoverageTable[] lgca = new GlyphCoverageTable[nlg]; + for ( int i = 0; i < nlg; i++ ) { + int lgco = lgcoa[i]; + GlyphCoverageTable lgct; + if ( lgco > 0 ) { + lgct = readCoverageTable ( tableTag + " reverse chained contextual substitution lookahead coverage[" + i + "]", subtableOffset + lgco ); + } else { + lgct = null; + } + lgca[i] = lgct; + } + // store results + seMapping = ct; + seEntries.add ( bgca ); + seEntries.add ( lgca ); + seEntries.add ( glyphs ); + } + + private int readReverseChainedSingleSubTable(int lookupType, int lookupFlags, long subtableOffset) throws IOException { + in.seekSet(subtableOffset); + // read substitution subtable format + int sf = in.readTTFUShort(); + if ( sf == 1 ) { + readReverseChainedSingleSubTableFormat1 ( lookupType, lookupFlags, subtableOffset, sf ); + } else { + throw new AdvancedTypographicTableFormatException ( "unsupported reverse chained single substitution subtable format: " + sf ); + } + return sf; + } + + private void readGSUBSubtable(int lookupType, int lookupFlags, int lookupSequence, int subtableSequence, long subtableOffset) throws IOException { + initATSubState(); + int subtableFormat = -1; + switch ( lookupType ) { + case GSUBLookupType.SINGLE: + subtableFormat = readSingleSubTable ( lookupType, lookupFlags, subtableOffset ); + break; + case GSUBLookupType.MULTIPLE: + subtableFormat = readMultipleSubTable ( lookupType, lookupFlags, subtableOffset ); + break; + case GSUBLookupType.ALTERNATE: + subtableFormat = readAlternateSubTable ( lookupType, lookupFlags, subtableOffset ); + break; + case GSUBLookupType.LIGATURE: + subtableFormat = readLigatureSubTable ( lookupType, lookupFlags, subtableOffset ); + break; + case GSUBLookupType.CONTEXTUAL: + subtableFormat = readContextualSubTable ( lookupType, lookupFlags, subtableOffset ); + break; + case GSUBLookupType.CHAINED_CONTEXTUAL: + subtableFormat = readChainedContextualSubTable ( lookupType, lookupFlags, subtableOffset ); + break; + case GSUBLookupType.REVERSE_CHAINED_SINGLE: + subtableFormat = readReverseChainedSingleSubTable ( lookupType, lookupFlags, subtableOffset ); + break; + case GSUBLookupType.EXTENSION: + subtableFormat = readExtensionSubTable ( lookupType, lookupFlags, lookupSequence, subtableSequence, subtableOffset ); + break; + default: + break; + } + extractSESubState ( GlyphTable.GLYPH_TABLE_TYPE_SUBSTITUTION, lookupType, lookupFlags, lookupSequence, subtableSequence, subtableFormat ); + resetATSubState(); + } + + private GlyphPositioningTable.DeviceTable readPosDeviceTable(long subtableOffset, long deviceTableOffset) throws IOException { + long cp = in.getCurrentPos(); + in.seekSet(subtableOffset + deviceTableOffset); + // read start size + int ss = in.readTTFUShort(); + // read end size + int es = in.readTTFUShort(); + // read delta format + int df = in.readTTFUShort(); + int s1, m1, dm, dd, s2; + if ( df == 1 ) { + s1 = 14; m1 = 0x3; dm = 1; dd = 4; s2 = 2; + } else if ( df == 2 ) { + s1 = 12; m1 = 0xF; dm = 7; dd = 16; s2 = 4; + } else if ( df == 3 ) { + s1 = 8; m1 = 0xFF; dm = 127; dd = 256; s2 = 8; + } else { + log.debug ( "unsupported device table delta format: " + df + ", ignoring device table" ); + return null; + } + // read deltas + int n = ( es - ss ) + 1; + if ( n < 0 ) { + log.debug ( "invalid device table delta count: " + n + ", ignoring device table" ); + return null; + } + int[] da = new int [ n ]; + for ( int i = 0; ( i < n ) && ( s2 > 0 );) { + int p = in.readTTFUShort(); + for ( int j = 0, k = 16 / s2; j < k; j++ ) { + int d = ( p >> s1 ) & m1; + if ( d > dm ) { + d -= dd; + } + if ( i < n ) { + da [ i++ ] = d; + } else { + break; + } + p <<= s2; + } + } + in.seekSet(cp); + return new GlyphPositioningTable.DeviceTable ( ss, es, da ); + } + + private GlyphPositioningTable.Value readPosValue(long subtableOffset, int valueFormat) throws IOException { + // XPlacement + int xp; + if ( ( valueFormat & GlyphPositioningTable.Value.X_PLACEMENT ) != 0 ) { + xp = ttf.convertTTFUnit2PDFUnit ( in.readTTFShort() ); + } else { + xp = 0; + } + // YPlacement + int yp; + if ( ( valueFormat & GlyphPositioningTable.Value.Y_PLACEMENT ) != 0 ) { + yp = ttf.convertTTFUnit2PDFUnit ( in.readTTFShort() ); + } else { + yp = 0; + } + // XAdvance + int xa; + if ( ( valueFormat & GlyphPositioningTable.Value.X_ADVANCE ) != 0 ) { + xa = ttf.convertTTFUnit2PDFUnit ( in.readTTFShort() ); + } else { + xa = 0; + } + // YAdvance + int ya; + if ( ( valueFormat & GlyphPositioningTable.Value.Y_ADVANCE ) != 0 ) { + ya = ttf.convertTTFUnit2PDFUnit ( in.readTTFShort() ); + } else { + ya = 0; + } + // XPlaDevice + GlyphPositioningTable.DeviceTable xpd; + if ( ( valueFormat & GlyphPositioningTable.Value.X_PLACEMENT_DEVICE ) != 0 ) { + int xpdo = in.readTTFUShort(); + xpd = readPosDeviceTable ( subtableOffset, xpdo ); + } else { + xpd = null; + } + // YPlaDevice + GlyphPositioningTable.DeviceTable ypd; + if ( ( valueFormat & GlyphPositioningTable.Value.Y_PLACEMENT_DEVICE ) != 0 ) { + int ypdo = in.readTTFUShort(); + ypd = readPosDeviceTable ( subtableOffset, ypdo ); + } else { + ypd = null; + } + // XAdvDevice + GlyphPositioningTable.DeviceTable xad; + if ( ( valueFormat & GlyphPositioningTable.Value.X_ADVANCE_DEVICE ) != 0 ) { + int xado = in.readTTFUShort(); + xad = readPosDeviceTable ( subtableOffset, xado ); + } else { + xad = null; + } + // YAdvDevice + GlyphPositioningTable.DeviceTable yad; + if ( ( valueFormat & GlyphPositioningTable.Value.Y_ADVANCE_DEVICE ) != 0 ) { + int yado = in.readTTFUShort(); + yad = readPosDeviceTable ( subtableOffset, yado ); + } else { + yad = null; + } + return new GlyphPositioningTable.Value ( xp, yp, xa, ya, xpd, ypd, xad, yad ); + } + + private void readSinglePosTableFormat1(int lookupType, int lookupFlags, long subtableOffset, int subtableFormat) throws IOException { + String tableTag = "GPOS"; + in.seekSet(subtableOffset); + // skip over format (already known) + in.skip ( 2 ); + // read coverage offset + int co = in.readTTFUShort(); + // read value format + int vf = in.readTTFUShort(); + // read value + GlyphPositioningTable.Value v = readPosValue ( subtableOffset, vf ); + // dump info if debugging + if (log.isDebugEnabled()) { + log.debug(tableTag + " single positioning subtable format: " + subtableFormat + " (delta)" ); + log.debug(tableTag + " single positioning coverage table offset: " + co ); + log.debug(tableTag + " single positioning value: " + v ); + } + // read coverage table + GlyphCoverageTable ct = readCoverageTable ( tableTag + " single positioning coverage", subtableOffset + co ); + // store results + seMapping = ct; + seEntries.add ( v ); + } + + private void readSinglePosTableFormat2(int lookupType, int lookupFlags, long subtableOffset, int subtableFormat) throws IOException { + String tableTag = "GPOS"; + in.seekSet(subtableOffset); + // skip over format (already known) + in.skip ( 2 ); + // read coverage offset + int co = in.readTTFUShort(); + // read value format + int vf = in.readTTFUShort(); + // read value count + int nv = in.readTTFUShort(); + // dump info if debugging + if (log.isDebugEnabled()) { + log.debug(tableTag + " single positioning subtable format: " + subtableFormat + " (mapped)" ); + log.debug(tableTag + " single positioning coverage table offset: " + co ); + log.debug(tableTag + " single positioning value count: " + nv ); + } + // read coverage table + GlyphCoverageTable ct = readCoverageTable ( tableTag + " single positioning coverage", subtableOffset + co ); + // read positioning values + GlyphPositioningTable.Value[] pva = new GlyphPositioningTable.Value[nv]; + for ( int i = 0, n = nv; i < n; i++ ) { + GlyphPositioningTable.Value pv = readPosValue ( subtableOffset, vf ); + if (log.isDebugEnabled()) { + log.debug(tableTag + " single positioning value[" + i + "]: " + pv ); + } + pva[i] = pv; + } + // store results + seMapping = ct; + seEntries.add ( pva ); + } + + private int readSinglePosTable(int lookupType, int lookupFlags, long subtableOffset) throws IOException { + in.seekSet(subtableOffset); + // read positionining subtable format + int sf = in.readTTFUShort(); + if ( sf == 1 ) { + readSinglePosTableFormat1 ( lookupType, lookupFlags, subtableOffset, sf ); + } else if ( sf == 2 ) { + readSinglePosTableFormat2 ( lookupType, lookupFlags, subtableOffset, sf ); + } else { + throw new AdvancedTypographicTableFormatException ( "unsupported single positioning subtable format: " + sf ); + } + return sf; + } + + private GlyphPositioningTable.PairValues readPosPairValues(long subtableOffset, boolean hasGlyph, int vf1, int vf2) throws IOException { + // read glyph (if present) + int glyph; + if ( hasGlyph ) { + glyph = in.readTTFUShort(); + } else { + glyph = 0; + } + // read first value (if present) + GlyphPositioningTable.Value v1; + if ( vf1 != 0 ) { + v1 = readPosValue ( subtableOffset, vf1 ); + } else { + v1 = null; + } + // read second value (if present) + GlyphPositioningTable.Value v2; + if ( vf2 != 0 ) { + v2 = readPosValue ( subtableOffset, vf2 ); + } else { + v2 = null; + } + return new GlyphPositioningTable.PairValues ( glyph, v1, v2 ); + } + + private GlyphPositioningTable.PairValues[] readPosPairSetTable(long subtableOffset, int pairSetTableOffset, int vf1, int vf2) throws IOException { + String tableTag = "GPOS"; + long cp = in.getCurrentPos(); + in.seekSet(subtableOffset + pairSetTableOffset); + // read pair values count + int npv = in.readTTFUShort(); + // dump info if debugging + if (log.isDebugEnabled()) { + log.debug(tableTag + " pair set table offset: " + pairSetTableOffset ); + log.debug(tableTag + " pair set table values count: " + npv ); + } + // read pair values + GlyphPositioningTable.PairValues[] pva = new GlyphPositioningTable.PairValues [ npv ]; + for ( int i = 0, n = npv; i < n; i++ ) { + GlyphPositioningTable.PairValues pv = readPosPairValues ( subtableOffset, true, vf1, vf2 ); + pva [ i ] = pv; + if (log.isDebugEnabled()) { + log.debug(tableTag + " pair set table value[" + i + "]: " + pv); + } + } + in.seekSet(cp); + return pva; + } + + private void readPairPosTableFormat1(int lookupType, int lookupFlags, long subtableOffset, int subtableFormat) throws IOException { + String tableTag = "GPOS"; + in.seekSet(subtableOffset); + // skip over format (already known) + in.skip ( 2 ); + // read coverage offset + int co = in.readTTFUShort(); + // read value format for first glyph + int vf1 = in.readTTFUShort(); + // read value format for second glyph + int vf2 = in.readTTFUShort(); + // read number (count) of pair sets + int nps = in.readTTFUShort(); + // dump info if debugging + if (log.isDebugEnabled()) { + log.debug(tableTag + " pair positioning subtable format: " + subtableFormat + " (glyphs)" ); + log.debug(tableTag + " pair positioning coverage table offset: " + co ); + log.debug(tableTag + " pair positioning value format #1: " + vf1 ); + log.debug(tableTag + " pair positioning value format #2: " + vf2 ); + } + // read coverage table + GlyphCoverageTable ct = readCoverageTable ( tableTag + " pair positioning coverage", subtableOffset + co ); + // read pair value matrix + GlyphPositioningTable.PairValues[][] pvm = new GlyphPositioningTable.PairValues [ nps ][]; + for ( int i = 0, n = nps; i < n; i++ ) { + // read pair set offset + int pso = in.readTTFUShort(); + // read pair set table at offset + pvm [ i ] = readPosPairSetTable ( subtableOffset, pso, vf1, vf2 ); + } + // store results + seMapping = ct; + seEntries.add ( pvm ); + } + + private void readPairPosTableFormat2(int lookupType, int lookupFlags, long subtableOffset, int subtableFormat) throws IOException { + String tableTag = "GPOS"; + in.seekSet(subtableOffset); + // skip over format (already known) + in.skip ( 2 ); + // read coverage offset + int co = in.readTTFUShort(); + // read value format for first glyph + int vf1 = in.readTTFUShort(); + // read value format for second glyph + int vf2 = in.readTTFUShort(); + // read class def 1 offset + int cd1o = in.readTTFUShort(); + // read class def 2 offset + int cd2o = in.readTTFUShort(); + // read number (count) of classes in class def 1 table + int nc1 = in.readTTFUShort(); + // read number (count) of classes in class def 2 table + int nc2 = in.readTTFUShort(); + // dump info if debugging + if (log.isDebugEnabled()) { + log.debug(tableTag + " pair positioning subtable format: " + subtableFormat + " (glyph classes)" ); + log.debug(tableTag + " pair positioning coverage table offset: " + co ); + log.debug(tableTag + " pair positioning value format #1: " + vf1 ); + log.debug(tableTag + " pair positioning value format #2: " + vf2 ); + log.debug(tableTag + " pair positioning class def table #1 offset: " + cd1o ); + log.debug(tableTag + " pair positioning class def table #2 offset: " + cd2o ); + log.debug(tableTag + " pair positioning class #1 count: " + nc1 ); + log.debug(tableTag + " pair positioning class #2 count: " + nc2 ); + } + // read coverage table + GlyphCoverageTable ct = readCoverageTable ( tableTag + " pair positioning coverage", subtableOffset + co ); + // read class definition table #1 + GlyphClassTable cdt1 = readClassDefTable ( tableTag + " pair positioning class definition #1", subtableOffset + cd1o ); + // read class definition table #2 + GlyphClassTable cdt2 = readClassDefTable ( tableTag + " pair positioning class definition #2", subtableOffset + cd2o ); + // read pair value matrix + GlyphPositioningTable.PairValues[][] pvm = new GlyphPositioningTable.PairValues [ nc1 ] [ nc2 ]; + for ( int i = 0; i < nc1; i++ ) { + for ( int j = 0; j < nc2; j++ ) { + GlyphPositioningTable.PairValues pv = readPosPairValues ( subtableOffset, false, vf1, vf2 ); + pvm [ i ] [ j ] = pv; + if (log.isDebugEnabled()) { + log.debug(tableTag + " pair set table value[" + i + "][" + j + "]: " + pv); + } + } + } + // store results + seMapping = ct; + seEntries.add ( cdt1 ); + seEntries.add ( cdt2 ); + seEntries.add ( Integer.valueOf ( nc1 ) ); + seEntries.add ( Integer.valueOf ( nc2 ) ); + seEntries.add ( pvm ); + } + + private int readPairPosTable(int lookupType, int lookupFlags, long subtableOffset) throws IOException { + in.seekSet(subtableOffset); + // read positioning subtable format + int sf = in.readTTFUShort(); + if ( sf == 1 ) { + readPairPosTableFormat1 ( lookupType, lookupFlags, subtableOffset, sf ); + } else if ( sf == 2 ) { + readPairPosTableFormat2 ( lookupType, lookupFlags, subtableOffset, sf ); + } else { + throw new AdvancedTypographicTableFormatException ( "unsupported pair positioning subtable format: " + sf ); + } + return sf; + } + + private GlyphPositioningTable.Anchor readPosAnchor(long anchorTableOffset) throws IOException { + GlyphPositioningTable.Anchor a; + long cp = in.getCurrentPos(); + in.seekSet(anchorTableOffset); + // read anchor table format + int af = in.readTTFUShort(); + if ( af == 1 ) { + // read x coordinate + int x = ttf.convertTTFUnit2PDFUnit ( in.readTTFShort() ); + // read y coordinate + int y = ttf.convertTTFUnit2PDFUnit ( in.readTTFShort() ); + a = new GlyphPositioningTable.Anchor ( x, y ); + } else if ( af == 2 ) { + // read x coordinate + int x = ttf.convertTTFUnit2PDFUnit ( in.readTTFShort() ); + // read y coordinate + int y = ttf.convertTTFUnit2PDFUnit ( in.readTTFShort() ); + // read anchor point index + int ap = in.readTTFUShort(); + a = new GlyphPositioningTable.Anchor ( x, y, ap ); + } else if ( af == 3 ) { + // read x coordinate + int x = ttf.convertTTFUnit2PDFUnit ( in.readTTFShort() ); + // read y coordinate + int y = ttf.convertTTFUnit2PDFUnit ( in.readTTFShort() ); + // read x device table offset + int xdo = in.readTTFUShort(); + // read y device table offset + int ydo = in.readTTFUShort(); + // read x device table (if present) + GlyphPositioningTable.DeviceTable xd; + if ( xdo != 0 ) { + xd = readPosDeviceTable ( cp, xdo ); + } else { + xd = null; + } + // read y device table (if present) + GlyphPositioningTable.DeviceTable yd; + if ( ydo != 0 ) { + yd = readPosDeviceTable ( cp, ydo ); + } else { + yd = null; + } + a = new GlyphPositioningTable.Anchor ( x, y, xd, yd ); + } else { + throw new AdvancedTypographicTableFormatException ( "unsupported positioning anchor format: " + af ); + } + in.seekSet(cp); + return a; + } + + private void readCursivePosTableFormat1(int lookupType, int lookupFlags, long subtableOffset, int subtableFormat) throws IOException { + String tableTag = "GPOS"; + in.seekSet(subtableOffset); + // skip over format (already known) + in.skip ( 2 ); + // read coverage offset + int co = in.readTTFUShort(); + // read entry/exit count + int ec = in.readTTFUShort(); + // dump info if debugging + if (log.isDebugEnabled()) { + log.debug(tableTag + " cursive positioning subtable format: " + subtableFormat ); + log.debug(tableTag + " cursive positioning coverage table offset: " + co ); + log.debug(tableTag + " cursive positioning entry/exit count: " + ec ); + } + // read coverage table + GlyphCoverageTable ct = readCoverageTable ( tableTag + " cursive positioning coverage", subtableOffset + co ); + // read entry/exit records + GlyphPositioningTable.Anchor[] aa = new GlyphPositioningTable.Anchor [ ec * 2 ]; + for ( int i = 0, n = ec; i < n; i++ ) { + // read entry anchor offset + int eno = in.readTTFUShort(); + // read exit anchor offset + int exo = in.readTTFUShort(); + // read entry anchor + GlyphPositioningTable.Anchor ena; + if ( eno > 0 ) { + ena = readPosAnchor ( subtableOffset + eno ); + } else { + ena = null; + } + // read exit anchor + GlyphPositioningTable.Anchor exa; + if ( exo > 0 ) { + exa = readPosAnchor ( subtableOffset + exo ); + } else { + exa = null; + } + aa [ ( i * 2 ) + 0 ] = ena; + aa [ ( i * 2 ) + 1 ] = exa; + if (log.isDebugEnabled()) { + if ( ena != null ) { + log.debug(tableTag + " cursive entry anchor [" + i + "]: " + ena ); + } + if ( exa != null ) { + log.debug(tableTag + " cursive exit anchor [" + i + "]: " + exa ); + } + } + } + // store results + seMapping = ct; + seEntries.add ( aa ); + } + + private int readCursivePosTable(int lookupType, int lookupFlags, long subtableOffset) throws IOException { + in.seekSet(subtableOffset); + // read positioning subtable format + int sf = in.readTTFUShort(); + if ( sf == 1 ) { + readCursivePosTableFormat1 ( lookupType, lookupFlags, subtableOffset, sf ); + } else { + throw new AdvancedTypographicTableFormatException ( "unsupported cursive positioning subtable format: " + sf ); + } + return sf; + } + + private void readMarkToBasePosTableFormat1(int lookupType, int lookupFlags, long subtableOffset, int subtableFormat) throws IOException { + String tableTag = "GPOS"; + in.seekSet(subtableOffset); + // skip over format (already known) + in.skip ( 2 ); + // read mark coverage offset + int mco = in.readTTFUShort(); + // read base coverage offset + int bco = in.readTTFUShort(); + // read mark class count + int nmc = in.readTTFUShort(); + // read mark array offset + int mao = in.readTTFUShort(); + // read base array offset + int bao = in.readTTFUShort(); + // dump info if debugging + if (log.isDebugEnabled()) { + log.debug(tableTag + " mark-to-base positioning subtable format: " + subtableFormat ); + log.debug(tableTag + " mark-to-base positioning mark coverage table offset: " + mco ); + log.debug(tableTag + " mark-to-base positioning base coverage table offset: " + bco ); + log.debug(tableTag + " mark-to-base positioning mark class count: " + nmc ); + log.debug(tableTag + " mark-to-base positioning mark array offset: " + mao ); + log.debug(tableTag + " mark-to-base positioning base array offset: " + bao ); + } + // read mark coverage table + GlyphCoverageTable mct = readCoverageTable ( tableTag + " mark-to-base positioning mark coverage", subtableOffset + mco ); + // read base coverage table + GlyphCoverageTable bct = readCoverageTable ( tableTag + " mark-to-base positioning base coverage", subtableOffset + bco ); + // read mark anchor array + // seek to mark array + in.seekSet(subtableOffset + mao); + // read mark count + int nm = in.readTTFUShort(); + if (log.isDebugEnabled()) { + log.debug(tableTag + " mark-to-base positioning mark count: " + nm ); + } + // read mark anchor array, where i:{0...markCount} + GlyphPositioningTable.MarkAnchor[] maa = new GlyphPositioningTable.MarkAnchor [ nm ]; + for ( int i = 0; i < nm; i++ ) { + // read mark class + int mc = in.readTTFUShort(); + // read mark anchor offset + int ao = in.readTTFUShort(); + GlyphPositioningTable.Anchor a; + if ( ao > 0 ) { + a = readPosAnchor ( subtableOffset + mao + ao ); + } else { + a = null; + } + GlyphPositioningTable.MarkAnchor ma; + if ( a != null ) { + ma = new GlyphPositioningTable.MarkAnchor ( mc, a ); + } else { + ma = null; + } + maa [ i ] = ma; + if (log.isDebugEnabled()) { + log.debug(tableTag + " mark-to-base positioning mark anchor[" + i + "]: " + ma); + } + + } + // read base anchor matrix + // seek to base array + in.seekSet(subtableOffset + bao); + // read base count + int nb = in.readTTFUShort(); + if (log.isDebugEnabled()) { + log.debug(tableTag + " mark-to-base positioning base count: " + nb ); + } + // read anchor matrix, where i:{0...baseCount - 1}, j:{0...markClassCount - 1} + GlyphPositioningTable.Anchor[][] bam = new GlyphPositioningTable.Anchor [ nb ] [ nmc ]; + for ( int i = 0; i < nb; i++ ) { + for ( int j = 0; j < nmc; j++ ) { + // read base anchor offset + int ao = in.readTTFUShort(); + GlyphPositioningTable.Anchor a; + if ( ao > 0 ) { + a = readPosAnchor ( subtableOffset + bao + ao ); + } else { + a = null; + } + bam [ i ] [ j ] = a; + if (log.isDebugEnabled()) { + log.debug(tableTag + " mark-to-base positioning base anchor[" + i + "][" + j + "]: " + a); + } + } + } + // store results + seMapping = mct; + seEntries.add ( bct ); + seEntries.add ( Integer.valueOf ( nmc ) ); + seEntries.add ( maa ); + seEntries.add ( bam ); + } + + private int readMarkToBasePosTable(int lookupType, int lookupFlags, long subtableOffset) throws IOException { + in.seekSet(subtableOffset); + // read positioning subtable format + int sf = in.readTTFUShort(); + if ( sf == 1 ) { + readMarkToBasePosTableFormat1 ( lookupType, lookupFlags, subtableOffset, sf ); + } else { + throw new AdvancedTypographicTableFormatException ( "unsupported mark-to-base positioning subtable format: " + sf ); + } + return sf; + } + + private void readMarkToLigaturePosTableFormat1(int lookupType, int lookupFlags, long subtableOffset, int subtableFormat) throws IOException { + String tableTag = "GPOS"; + in.seekSet(subtableOffset); + // skip over format (already known) + in.skip ( 2 ); + // read mark coverage offset + int mco = in.readTTFUShort(); + // read ligature coverage offset + int lco = in.readTTFUShort(); + // read mark class count + int nmc = in.readTTFUShort(); + // read mark array offset + int mao = in.readTTFUShort(); + // read ligature array offset + int lao = in.readTTFUShort(); + // dump info if debugging + if (log.isDebugEnabled()) { + log.debug(tableTag + " mark-to-ligature positioning subtable format: " + subtableFormat ); + log.debug(tableTag + " mark-to-ligature positioning mark coverage table offset: " + mco ); + log.debug(tableTag + " mark-to-ligature positioning ligature coverage table offset: " + lco ); + log.debug(tableTag + " mark-to-ligature positioning mark class count: " + nmc ); + log.debug(tableTag + " mark-to-ligature positioning mark array offset: " + mao ); + log.debug(tableTag + " mark-to-ligature positioning ligature array offset: " + lao ); + } + // read mark coverage table + GlyphCoverageTable mct = readCoverageTable ( tableTag + " mark-to-ligature positioning mark coverage", subtableOffset + mco ); + // read ligature coverage table + GlyphCoverageTable lct = readCoverageTable ( tableTag + " mark-to-ligature positioning ligature coverage", subtableOffset + lco ); + // read mark anchor array + // seek to mark array + in.seekSet(subtableOffset + mao); + // read mark count + int nm = in.readTTFUShort(); + if (log.isDebugEnabled()) { + log.debug(tableTag + " mark-to-ligature positioning mark count: " + nm ); + } + // read mark anchor array, where i:{0...markCount} + GlyphPositioningTable.MarkAnchor[] maa = new GlyphPositioningTable.MarkAnchor [ nm ]; + for ( int i = 0; i < nm; i++ ) { + // read mark class + int mc = in.readTTFUShort(); + // read mark anchor offset + int ao = in.readTTFUShort(); + GlyphPositioningTable.Anchor a; + if ( ao > 0 ) { + a = readPosAnchor ( subtableOffset + mao + ao ); + } else { + a = null; + } + GlyphPositioningTable.MarkAnchor ma; + if ( a != null ) { + ma = new GlyphPositioningTable.MarkAnchor ( mc, a ); + } else { + ma = null; + } + maa [ i ] = ma; + if (log.isDebugEnabled()) { + log.debug(tableTag + " mark-to-ligature positioning mark anchor[" + i + "]: " + ma); + } + } + // read ligature anchor matrix + // seek to ligature array + in.seekSet(subtableOffset + lao); + // read ligature count + int nl = in.readTTFUShort(); + if (log.isDebugEnabled()) { + log.debug(tableTag + " mark-to-ligature positioning ligature count: " + nl ); + } + // read ligature attach table offsets + int[] laoa = new int [ nl ]; + for ( int i = 0; i < nl; i++ ) { + laoa [ i ] = in.readTTFUShort(); + } + // iterate over ligature attach tables, recording maximum component count + int mxc = 0; + for ( int i = 0; i < nl; i++ ) { + int lato = laoa [ i ]; + in.seekSet ( subtableOffset + lao + lato ); + // read component count + int cc = in.readTTFUShort(); + if ( cc > mxc ) { + mxc = cc; + } + } + if (log.isDebugEnabled()) { + log.debug(tableTag + " mark-to-ligature positioning maximum component count: " + mxc ); + } + // read anchor matrix, where i:{0...ligatureCount - 1}, j:{0...maxComponentCount - 1}, k:{0...markClassCount - 1} + GlyphPositioningTable.Anchor[][][] lam = new GlyphPositioningTable.Anchor [ nl ][][]; + for ( int i = 0; i < nl; i++ ) { + int lato = laoa [ i ]; + // seek to ligature attach table for ligature[i] + in.seekSet ( subtableOffset + lao + lato ); + // read component count + int cc = in.readTTFUShort(); + GlyphPositioningTable.Anchor[][] lcm = new GlyphPositioningTable.Anchor [ cc ] [ nmc ]; + for ( int j = 0; j < cc; j++ ) { + for ( int k = 0; k < nmc; k++ ) { + // read ligature anchor offset + int ao = in.readTTFUShort(); + GlyphPositioningTable.Anchor a; + if ( ao > 0 ) { + a = readPosAnchor ( subtableOffset + lao + lato + ao ); + } else { + a = null; + } + lcm [ j ] [ k ] = a; + if (log.isDebugEnabled()) { + log.debug(tableTag + " mark-to-ligature positioning ligature anchor[" + i + "][" + j + "][" + k + "]: " + a); + } + } + } + lam [ i ] = lcm; + } + // store results + seMapping = mct; + seEntries.add ( lct ); + seEntries.add ( Integer.valueOf ( nmc ) ); + seEntries.add ( Integer.valueOf ( mxc ) ); + seEntries.add ( maa ); + seEntries.add ( lam ); + } + + private int readMarkToLigaturePosTable(int lookupType, int lookupFlags, long subtableOffset) throws IOException { + in.seekSet(subtableOffset); + // read positioning subtable format + int sf = in.readTTFUShort(); + if ( sf == 1 ) { + readMarkToLigaturePosTableFormat1 ( lookupType, lookupFlags, subtableOffset, sf ); + } else { + throw new AdvancedTypographicTableFormatException ( "unsupported mark-to-ligature positioning subtable format: " + sf ); + } + return sf; + } + + private void readMarkToMarkPosTableFormat1(int lookupType, int lookupFlags, long subtableOffset, int subtableFormat) throws IOException { + String tableTag = "GPOS"; + in.seekSet(subtableOffset); + // skip over format (already known) + in.skip ( 2 ); + // read mark #1 coverage offset + int m1co = in.readTTFUShort(); + // read mark #2 coverage offset + int m2co = in.readTTFUShort(); + // read mark class count + int nmc = in.readTTFUShort(); + // read mark #1 array offset + int m1ao = in.readTTFUShort(); + // read mark #2 array offset + int m2ao = in.readTTFUShort(); + // dump info if debugging + if (log.isDebugEnabled()) { + log.debug(tableTag + " mark-to-mark positioning subtable format: " + subtableFormat ); + log.debug(tableTag + " mark-to-mark positioning mark #1 coverage table offset: " + m1co ); + log.debug(tableTag + " mark-to-mark positioning mark #2 coverage table offset: " + m2co ); + log.debug(tableTag + " mark-to-mark positioning mark class count: " + nmc ); + log.debug(tableTag + " mark-to-mark positioning mark #1 array offset: " + m1ao ); + log.debug(tableTag + " mark-to-mark positioning mark #2 array offset: " + m2ao ); + } + // read mark #1 coverage table + GlyphCoverageTable mct1 = readCoverageTable ( tableTag + " mark-to-mark positioning mark #1 coverage", subtableOffset + m1co ); + // read mark #2 coverage table + GlyphCoverageTable mct2 = readCoverageTable ( tableTag + " mark-to-mark positioning mark #2 coverage", subtableOffset + m2co ); + // read mark #1 anchor array + // seek to mark array + in.seekSet(subtableOffset + m1ao); + // read mark count + int nm1 = in.readTTFUShort(); + if (log.isDebugEnabled()) { + log.debug(tableTag + " mark-to-mark positioning mark #1 count: " + nm1 ); + } + // read mark anchor array, where i:{0...mark1Count} + GlyphPositioningTable.MarkAnchor[] maa = new GlyphPositioningTable.MarkAnchor [ nm1 ]; + for ( int i = 0; i < nm1; i++ ) { + // read mark class + int mc = in.readTTFUShort(); + // read mark anchor offset + int ao = in.readTTFUShort(); + GlyphPositioningTable.Anchor a; + if ( ao > 0 ) { + a = readPosAnchor ( subtableOffset + m1ao + ao ); + } else { + a = null; + } + GlyphPositioningTable.MarkAnchor ma; + if ( a != null ) { + ma = new GlyphPositioningTable.MarkAnchor ( mc, a ); + } else { + ma = null; + } + maa [ i ] = ma; + if (log.isDebugEnabled()) { + log.debug(tableTag + " mark-to-mark positioning mark #1 anchor[" + i + "]: " + ma); + } + } + // read mark #2 anchor matrix + // seek to mark #2 array + in.seekSet(subtableOffset + m2ao); + // read mark #2 count + int nm2 = in.readTTFUShort(); + if (log.isDebugEnabled()) { + log.debug(tableTag + " mark-to-mark positioning mark #2 count: " + nm2 ); + } + // read anchor matrix, where i:{0...mark2Count - 1}, j:{0...markClassCount - 1} + GlyphPositioningTable.Anchor[][] mam = new GlyphPositioningTable.Anchor [ nm2 ] [ nmc ]; + for ( int i = 0; i < nm2; i++ ) { + for ( int j = 0; j < nmc; j++ ) { + // read mark anchor offset + int ao = in.readTTFUShort(); + GlyphPositioningTable.Anchor a; + if ( ao > 0 ) { + a = readPosAnchor ( subtableOffset + m2ao + ao ); + } else { + a = null; + } + mam [ i ] [ j ] = a; + if (log.isDebugEnabled()) { + log.debug(tableTag + " mark-to-mark positioning mark #2 anchor[" + i + "][" + j + "]: " + a); + } + } + } + // store results + seMapping = mct1; + seEntries.add ( mct2 ); + seEntries.add ( Integer.valueOf ( nmc ) ); + seEntries.add ( maa ); + seEntries.add ( mam ); + } + + private int readMarkToMarkPosTable(int lookupType, int lookupFlags, long subtableOffset) throws IOException { + in.seekSet(subtableOffset); + // read positioning subtable format + int sf = in.readTTFUShort(); + if ( sf == 1 ) { + readMarkToMarkPosTableFormat1 ( lookupType, lookupFlags, subtableOffset, sf ); + } else { + throw new AdvancedTypographicTableFormatException ( "unsupported mark-to-mark positioning subtable format: " + sf ); + } + return sf; + } + + private void readContextualPosTableFormat1(int lookupType, int lookupFlags, long subtableOffset, int subtableFormat) throws IOException { + String tableTag = "GPOS"; + in.seekSet(subtableOffset); + // skip over format (already known) + in.skip ( 2 ); + // read coverage offset + int co = in.readTTFUShort(); + // read rule set count + int nrs = in.readTTFUShort(); + // read rule set offsets + int[] rsoa = new int [ nrs ]; + for ( int i = 0; i < nrs; i++ ) { + rsoa [ i ] = in.readTTFUShort(); + } + // dump info if debugging + if (log.isDebugEnabled()) { + log.debug(tableTag + " contextual positioning subtable format: " + subtableFormat + " (glyphs)" ); + log.debug(tableTag + " contextual positioning coverage table offset: " + co ); + log.debug(tableTag + " contextual positioning rule set count: " + nrs ); + for ( int i = 0; i < nrs; i++ ) { + log.debug(tableTag + " contextual positioning rule set offset[" + i + "]: " + rsoa[i] ); + } + } + // read coverage table + GlyphCoverageTable ct; + if ( co > 0 ) { + ct = readCoverageTable ( tableTag + " contextual positioning coverage", subtableOffset + co ); + } else { + ct = null; + } + // read rule sets + GlyphTable.RuleSet[] rsa = new GlyphTable.RuleSet [ nrs ]; + String header = null; + for ( int i = 0; i < nrs; i++ ) { + GlyphTable.RuleSet rs; + int rso = rsoa [ i ]; + if ( rso > 0 ) { + // seek to rule set [ i ] + in.seekSet ( subtableOffset + rso ); + // read rule count + int nr = in.readTTFUShort(); + // read rule offsets + int[] roa = new int [ nr ]; + GlyphTable.Rule[] ra = new GlyphTable.Rule [ nr ]; + for ( int j = 0; j < nr; j++ ) { + roa [ j ] = in.readTTFUShort(); + } + // read glyph sequence rules + for ( int j = 0; j < nr; j++ ) { + GlyphTable.GlyphSequenceRule r; + int ro = roa [ j ]; + if ( ro > 0 ) { + // seek to rule [ j ] + in.seekSet ( subtableOffset + rso + ro ); + // read glyph count + int ng = in.readTTFUShort(); + // read rule lookup count + int nl = in.readTTFUShort(); + // read glyphs + int[] glyphs = new int [ ng - 1 ]; + for ( int k = 0, nk = glyphs.length; k < nk; k++ ) { + glyphs [ k ] = in.readTTFUShort(); + } + // read rule lookups + if (log.isDebugEnabled()) { + header = tableTag + " contextual positioning lookups @rule[" + i + "][" + j + "]: "; + } + GlyphTable.RuleLookup[] lookups = readRuleLookups ( nl, header ); + r = new GlyphTable.GlyphSequenceRule ( lookups, ng, glyphs ); + } else { + r = null; + } + ra [ j ] = r; + } + rs = new GlyphTable.HomogeneousRuleSet ( ra ); + } else { + rs = null; + } + rsa [ i ] = rs; + } + // store results + seMapping = ct; + seEntries.add ( rsa ); + } + + private void readContextualPosTableFormat2(int lookupType, int lookupFlags, long subtableOffset, int subtableFormat) throws IOException { + String tableTag = "GPOS"; + in.seekSet(subtableOffset); + // skip over format (already known) + in.skip ( 2 ); + // read coverage offset + int co = in.readTTFUShort(); + // read class def table offset + int cdo = in.readTTFUShort(); + // read class rule set count + int ngc = in.readTTFUShort(); + // read class rule set offsets + int[] csoa = new int [ ngc ]; + for ( int i = 0; i < ngc; i++ ) { + csoa [ i ] = in.readTTFUShort(); + } + // dump info if debugging + if (log.isDebugEnabled()) { + log.debug(tableTag + " contextual positioning subtable format: " + subtableFormat + " (glyph classes)" ); + log.debug(tableTag + " contextual positioning coverage table offset: " + co ); + log.debug(tableTag + " contextual positioning class set count: " + ngc ); + for ( int i = 0; i < ngc; i++ ) { + log.debug(tableTag + " contextual positioning class set offset[" + i + "]: " + csoa[i] ); + } + } + // read coverage table + GlyphCoverageTable ct; + if ( co > 0 ) { + ct = readCoverageTable ( tableTag + " contextual positioning coverage", subtableOffset + co ); + } else { + ct = null; + } + // read class definition table + GlyphClassTable cdt; + if ( cdo > 0 ) { + cdt = readClassDefTable ( tableTag + " contextual positioning class definition", subtableOffset + cdo ); + } else { + cdt = null; + } + // read rule sets + GlyphTable.RuleSet[] rsa = new GlyphTable.RuleSet [ ngc ]; + String header = null; + for ( int i = 0; i < ngc; i++ ) { + int cso = csoa [ i ]; + GlyphTable.RuleSet rs; + if ( cso > 0 ) { + // seek to rule set [ i ] + in.seekSet ( subtableOffset + cso ); + // read rule count + int nr = in.readTTFUShort(); + // read rule offsets + int[] roa = new int [ nr ]; + GlyphTable.Rule[] ra = new GlyphTable.Rule [ nr ]; + for ( int j = 0; j < nr; j++ ) { + roa [ j ] = in.readTTFUShort(); + } + // read glyph sequence rules + for ( int j = 0; j < nr; j++ ) { + int ro = roa [ j ]; + GlyphTable.ClassSequenceRule r; + if ( ro > 0 ) { + // seek to rule [ j ] + in.seekSet ( subtableOffset + cso + ro ); + // read glyph count + int ng = in.readTTFUShort(); + // read rule lookup count + int nl = in.readTTFUShort(); + // read classes + int[] classes = new int [ ng - 1 ]; + for ( int k = 0, nk = classes.length; k < nk; k++ ) { + classes [ k ] = in.readTTFUShort(); + } + // read rule lookups + if (log.isDebugEnabled()) { + header = tableTag + " contextual positioning lookups @rule[" + i + "][" + j + "]: "; + } + GlyphTable.RuleLookup[] lookups = readRuleLookups ( nl, header ); + r = new GlyphTable.ClassSequenceRule ( lookups, ng, classes ); + } else { + r = null; + } + ra [ j ] = r; + } + rs = new GlyphTable.HomogeneousRuleSet ( ra ); + } else { + rs = null; + } + rsa [ i ] = rs; + } + // store results + seMapping = ct; + seEntries.add ( cdt ); + seEntries.add ( Integer.valueOf ( ngc ) ); + seEntries.add ( rsa ); + } + + private void readContextualPosTableFormat3(int lookupType, int lookupFlags, long subtableOffset, int subtableFormat) throws IOException { + String tableTag = "GPOS"; + in.seekSet(subtableOffset); + // skip over format (already known) + in.skip ( 2 ); + // read glyph (input sequence length) count + int ng = in.readTTFUShort(); + // read positioning lookup count + int nl = in.readTTFUShort(); + // read glyph coverage offsets, one per glyph input sequence length count + int[] gcoa = new int [ ng ]; + for ( int i = 0; i < ng; i++ ) { + gcoa [ i ] = in.readTTFUShort(); + } + // dump info if debugging + if (log.isDebugEnabled()) { + log.debug(tableTag + " contextual positioning subtable format: " + subtableFormat + " (glyph sets)" ); + log.debug(tableTag + " contextual positioning glyph input sequence length count: " + ng ); + log.debug(tableTag + " contextual positioning lookup count: " + nl ); + for ( int i = 0; i < ng; i++ ) { + log.debug(tableTag + " contextual positioning coverage table offset[" + i + "]: " + gcoa[i] ); + } + } + // read coverage tables + GlyphCoverageTable[] gca = new GlyphCoverageTable [ ng ]; + for ( int i = 0; i < ng; i++ ) { + int gco = gcoa [ i ]; + GlyphCoverageTable gct; + if ( gco > 0 ) { + gct = readCoverageTable ( tableTag + " contextual positioning coverage[" + i + "]", subtableOffset + gcoa[i] ); + } else { + gct = null; + } + gca [ i ] = gct; + } + // read rule lookups + String header = null; + if (log.isDebugEnabled()) { + header = tableTag + " contextual positioning lookups: "; + } + GlyphTable.RuleLookup[] lookups = readRuleLookups ( nl, header ); + // construct rule, rule set, and rule set array + GlyphTable.Rule r = new GlyphTable.CoverageSequenceRule ( lookups, ng, gca ); + GlyphTable.RuleSet rs = new GlyphTable.HomogeneousRuleSet ( new GlyphTable.Rule[] {r} ); + GlyphTable.RuleSet[] rsa = new GlyphTable.RuleSet[] {rs}; + // store results + assert ( gca != null ) && ( gca.length > 0 ); + seMapping = gca[0]; + seEntries.add ( rsa ); + } + + private int readContextualPosTable(int lookupType, int lookupFlags, long subtableOffset) throws IOException { + in.seekSet(subtableOffset); + // read positioning subtable format + int sf = in.readTTFUShort(); + if ( sf == 1 ) { + readContextualPosTableFormat1 ( lookupType, lookupFlags, subtableOffset, sf ); + } else if ( sf == 2 ) { + readContextualPosTableFormat2 ( lookupType, lookupFlags, subtableOffset, sf ); + } else if ( sf == 3 ) { + readContextualPosTableFormat3 ( lookupType, lookupFlags, subtableOffset, sf ); + } else { + throw new AdvancedTypographicTableFormatException ( "unsupported contextual positioning subtable format: " + sf ); + } + return sf; + } + + private void readChainedContextualPosTableFormat1(int lookupType, int lookupFlags, long subtableOffset, int subtableFormat) throws IOException { + String tableTag = "GPOS"; + in.seekSet(subtableOffset); + // skip over format (already known) + in.skip ( 2 ); + // read coverage offset + int co = in.readTTFUShort(); + // read rule set count + int nrs = in.readTTFUShort(); + // read rule set offsets + int[] rsoa = new int [ nrs ]; + for ( int i = 0; i < nrs; i++ ) { + rsoa [ i ] = in.readTTFUShort(); + } + // dump info if debugging + if (log.isDebugEnabled()) { + log.debug(tableTag + " chained contextual positioning subtable format: " + subtableFormat + " (glyphs)" ); + log.debug(tableTag + " chained contextual positioning coverage table offset: " + co ); + log.debug(tableTag + " chained contextual positioning rule set count: " + nrs ); + for ( int i = 0; i < nrs; i++ ) { + log.debug(tableTag + " chained contextual positioning rule set offset[" + i + "]: " + rsoa[i] ); + } + } + // read coverage table + GlyphCoverageTable ct; + if ( co > 0 ) { + ct = readCoverageTable ( tableTag + " chained contextual positioning coverage", subtableOffset + co ); + } else { + ct = null; + } + // read rule sets + GlyphTable.RuleSet[] rsa = new GlyphTable.RuleSet [ nrs ]; + String header = null; + for ( int i = 0; i < nrs; i++ ) { + GlyphTable.RuleSet rs; + int rso = rsoa [ i ]; + if ( rso > 0 ) { + // seek to rule set [ i ] + in.seekSet ( subtableOffset + rso ); + // read rule count + int nr = in.readTTFUShort(); + // read rule offsets + int[] roa = new int [ nr ]; + GlyphTable.Rule[] ra = new GlyphTable.Rule [ nr ]; + for ( int j = 0; j < nr; j++ ) { + roa [ j ] = in.readTTFUShort(); + } + // read glyph sequence rules + for ( int j = 0; j < nr; j++ ) { + GlyphTable.ChainedGlyphSequenceRule r; + int ro = roa [ j ]; + if ( ro > 0 ) { + // seek to rule [ j ] + in.seekSet ( subtableOffset + rso + ro ); + // read backtrack glyph count + int nbg = in.readTTFUShort(); + // read backtrack glyphs + int[] backtrackGlyphs = new int [ nbg ]; + for ( int k = 0, nk = backtrackGlyphs.length; k < nk; k++ ) { + backtrackGlyphs [ k ] = in.readTTFUShort(); + } + // read input glyph count + int nig = in.readTTFUShort(); + // read glyphs + int[] glyphs = new int [ nig - 1 ]; + for ( int k = 0, nk = glyphs.length; k < nk; k++ ) { + glyphs [ k ] = in.readTTFUShort(); + } + // read lookahead glyph count + int nlg = in.readTTFUShort(); + // read lookahead glyphs + int[] lookaheadGlyphs = new int [ nlg ]; + for ( int k = 0, nk = lookaheadGlyphs.length; k < nk; k++ ) { + lookaheadGlyphs [ k ] = in.readTTFUShort(); + } + // read rule lookup count + int nl = in.readTTFUShort(); + // read rule lookups + if (log.isDebugEnabled()) { + header = tableTag + " contextual positioning lookups @rule[" + i + "][" + j + "]: "; + } + GlyphTable.RuleLookup[] lookups = readRuleLookups ( nl, header ); + r = new GlyphTable.ChainedGlyphSequenceRule ( lookups, nig, glyphs, backtrackGlyphs, lookaheadGlyphs ); + } else { + r = null; + } + ra [ j ] = r; + } + rs = new GlyphTable.HomogeneousRuleSet ( ra ); + } else { + rs = null; + } + rsa [ i ] = rs; + } + // store results + seMapping = ct; + seEntries.add ( rsa ); + } + + private void readChainedContextualPosTableFormat2(int lookupType, int lookupFlags, long subtableOffset, int subtableFormat) throws IOException { + String tableTag = "GPOS"; + in.seekSet(subtableOffset); + // skip over format (already known) + in.skip ( 2 ); + // read coverage offset + int co = in.readTTFUShort(); + // read backtrack class def table offset + int bcdo = in.readTTFUShort(); + // read input class def table offset + int icdo = in.readTTFUShort(); + // read lookahead class def table offset + int lcdo = in.readTTFUShort(); + // read class set count + int ngc = in.readTTFUShort(); + // read class set offsets + int[] csoa = new int [ ngc ]; + for ( int i = 0; i < ngc; i++ ) { + csoa [ i ] = in.readTTFUShort(); + } + // dump info if debugging + if (log.isDebugEnabled()) { + log.debug(tableTag + " chained contextual positioning subtable format: " + subtableFormat + " (glyph classes)" ); + log.debug(tableTag + " chained contextual positioning coverage table offset: " + co ); + log.debug(tableTag + " chained contextual positioning class set count: " + ngc ); + for ( int i = 0; i < ngc; i++ ) { + log.debug(tableTag + " chained contextual positioning class set offset[" + i + "]: " + csoa[i] ); + } + } + // read coverage table + GlyphCoverageTable ct; + if ( co > 0 ) { + ct = readCoverageTable ( tableTag + " chained contextual positioning coverage", subtableOffset + co ); + } else { + ct = null; + } + // read backtrack class definition table + GlyphClassTable bcdt; + if ( bcdo > 0 ) { + bcdt = readClassDefTable ( tableTag + " contextual positioning backtrack class definition", subtableOffset + bcdo ); + } else { + bcdt = null; + } + // read input class definition table + GlyphClassTable icdt; + if ( icdo > 0 ) { + icdt = readClassDefTable ( tableTag + " contextual positioning input class definition", subtableOffset + icdo ); + } else { + icdt = null; + } + // read lookahead class definition table + GlyphClassTable lcdt; + if ( lcdo > 0 ) { + lcdt = readClassDefTable ( tableTag + " contextual positioning lookahead class definition", subtableOffset + lcdo ); + } else { + lcdt = null; + } + // read rule sets + GlyphTable.RuleSet[] rsa = new GlyphTable.RuleSet [ ngc ]; + String header = null; + for ( int i = 0; i < ngc; i++ ) { + int cso = csoa [ i ]; + GlyphTable.RuleSet rs; + if ( cso > 0 ) { + // seek to rule set [ i ] + in.seekSet ( subtableOffset + cso ); + // read rule count + int nr = in.readTTFUShort(); + // read rule offsets + int[] roa = new int [ nr ]; + GlyphTable.Rule[] ra = new GlyphTable.Rule [ nr ]; + for ( int j = 0; j < nr; j++ ) { + roa [ j ] = in.readTTFUShort(); + } + // read glyph sequence rules + for ( int j = 0; j < nr; j++ ) { + GlyphTable.ChainedClassSequenceRule r; + int ro = roa [ j ]; + if ( ro > 0 ) { + // seek to rule [ j ] + in.seekSet ( subtableOffset + cso + ro ); + // read backtrack glyph class count + int nbc = in.readTTFUShort(); + // read backtrack glyph classes + int[] backtrackClasses = new int [ nbc ]; + for ( int k = 0, nk = backtrackClasses.length; k < nk; k++ ) { + backtrackClasses [ k ] = in.readTTFUShort(); + } + // read input glyph class count + int nic = in.readTTFUShort(); + // read input glyph classes + int[] classes = new int [ nic - 1 ]; + for ( int k = 0, nk = classes.length; k < nk; k++ ) { + classes [ k ] = in.readTTFUShort(); + } + // read lookahead glyph class count + int nlc = in.readTTFUShort(); + // read lookahead glyph classes + int[] lookaheadClasses = new int [ nlc ]; + for ( int k = 0, nk = lookaheadClasses.length; k < nk; k++ ) { + lookaheadClasses [ k ] = in.readTTFUShort(); + } + // read rule lookup count + int nl = in.readTTFUShort(); + // read rule lookups + if (log.isDebugEnabled()) { + header = tableTag + " contextual positioning lookups @rule[" + i + "][" + j + "]: "; + } + GlyphTable.RuleLookup[] lookups = readRuleLookups ( nl, header ); + r = new GlyphTable.ChainedClassSequenceRule ( lookups, nic, classes, backtrackClasses, lookaheadClasses ); + } else { + r = null; + } + ra [ j ] = r; + } + rs = new GlyphTable.HomogeneousRuleSet ( ra ); + } else { + rs = null; + } + rsa [ i ] = rs; + } + // store results + seMapping = ct; + seEntries.add ( icdt ); + seEntries.add ( bcdt ); + seEntries.add ( lcdt ); + seEntries.add ( Integer.valueOf ( ngc ) ); + seEntries.add ( rsa ); + } + + private void readChainedContextualPosTableFormat3(int lookupType, int lookupFlags, long subtableOffset, int subtableFormat) throws IOException { + String tableTag = "GPOS"; + in.seekSet(subtableOffset); + // skip over format (already known) + in.skip ( 2 ); + // read backtrack glyph count + int nbg = in.readTTFUShort(); + // read backtrack glyph coverage offsets + int[] bgcoa = new int [ nbg ]; + for ( int i = 0; i < nbg; i++ ) { + bgcoa [ i ] = in.readTTFUShort(); + } + // read input glyph count + int nig = in.readTTFUShort(); + // read backtrack glyph coverage offsets + int[] igcoa = new int [ nig ]; + for ( int i = 0; i < nig; i++ ) { + igcoa [ i ] = in.readTTFUShort(); + } + // read lookahead glyph count + int nlg = in.readTTFUShort(); + // read backtrack glyph coverage offsets + int[] lgcoa = new int [ nlg ]; + for ( int i = 0; i < nlg; i++ ) { + lgcoa [ i ] = in.readTTFUShort(); + } + // read positioning lookup count + int nl = in.readTTFUShort(); + // dump info if debugging + if (log.isDebugEnabled()) { + log.debug(tableTag + " chained contextual positioning subtable format: " + subtableFormat + " (glyph sets)" ); + log.debug(tableTag + " chained contextual positioning backtrack glyph count: " + nbg ); + for ( int i = 0; i < nbg; i++ ) { + log.debug(tableTag + " chained contextual positioning backtrack coverage table offset[" + i + "]: " + bgcoa[i] ); + } + log.debug(tableTag + " chained contextual positioning input glyph count: " + nig ); + for ( int i = 0; i < nig; i++ ) { + log.debug(tableTag + " chained contextual positioning input coverage table offset[" + i + "]: " + igcoa[i] ); + } + log.debug(tableTag + " chained contextual positioning lookahead glyph count: " + nlg ); + for ( int i = 0; i < nlg; i++ ) { + log.debug(tableTag + " chained contextual positioning lookahead coverage table offset[" + i + "]: " + lgcoa[i] ); + } + log.debug(tableTag + " chained contextual positioning lookup count: " + nl ); + } + // read backtrack coverage tables + GlyphCoverageTable[] bgca = new GlyphCoverageTable[nbg]; + for ( int i = 0; i < nbg; i++ ) { + int bgco = bgcoa [ i ]; + GlyphCoverageTable bgct; + if ( bgco > 0 ) { + bgct = readCoverageTable ( tableTag + " chained contextual positioning backtrack coverage[" + i + "]", subtableOffset + bgco ); + } else { + bgct = null; + } + bgca[i] = bgct; + } + // read input coverage tables + GlyphCoverageTable[] igca = new GlyphCoverageTable[nig]; + for ( int i = 0; i < nig; i++ ) { + int igco = igcoa [ i ]; + GlyphCoverageTable igct; + if ( igco > 0 ) { + igct = readCoverageTable ( tableTag + " chained contextual positioning input coverage[" + i + "]", subtableOffset + igco ); + } else { + igct = null; + } + igca[i] = igct; + } + // read lookahead coverage tables + GlyphCoverageTable[] lgca = new GlyphCoverageTable[nlg]; + for ( int i = 0; i < nlg; i++ ) { + int lgco = lgcoa [ i ]; + GlyphCoverageTable lgct; + if ( lgco > 0 ) { + lgct = readCoverageTable ( tableTag + " chained contextual positioning lookahead coverage[" + i + "]", subtableOffset + lgco ); + } else { + lgct = null; + } + lgca[i] = lgct; + } + // read rule lookups + String header = null; + if (log.isDebugEnabled()) { + header = tableTag + " chained contextual positioning lookups: "; + } + GlyphTable.RuleLookup[] lookups = readRuleLookups ( nl, header ); + // construct rule, rule set, and rule set array + GlyphTable.Rule r = new GlyphTable.ChainedCoverageSequenceRule ( lookups, nig, igca, bgca, lgca ); + GlyphTable.RuleSet rs = new GlyphTable.HomogeneousRuleSet ( new GlyphTable.Rule[] {r} ); + GlyphTable.RuleSet[] rsa = new GlyphTable.RuleSet[] {rs}; + // store results + assert ( igca != null ) && ( igca.length > 0 ); + seMapping = igca[0]; + seEntries.add ( rsa ); + } + + private int readChainedContextualPosTable(int lookupType, int lookupFlags, long subtableOffset) throws IOException { + in.seekSet(subtableOffset); + // read positioning subtable format + int sf = in.readTTFUShort(); + if ( sf == 1 ) { + readChainedContextualPosTableFormat1 ( lookupType, lookupFlags, subtableOffset, sf ); + } else if ( sf == 2 ) { + readChainedContextualPosTableFormat2 ( lookupType, lookupFlags, subtableOffset, sf ); + } else if ( sf == 3 ) { + readChainedContextualPosTableFormat3 ( lookupType, lookupFlags, subtableOffset, sf ); + } else { + throw new AdvancedTypographicTableFormatException ( "unsupported chained contextual positioning subtable format: " + sf ); + } + return sf; + } + + private void readExtensionPosTableFormat1(int lookupType, int lookupFlags, int lookupSequence, int subtableSequence, long subtableOffset, int subtableFormat) throws IOException { + String tableTag = "GPOS"; + in.seekSet(subtableOffset); + // skip over format (already known) + in.skip ( 2 ); + // read extension lookup type + int lt = in.readTTFUShort(); + // read extension offset + long eo = in.readTTFULong(); + // dump info if debugging + if (log.isDebugEnabled()) { + log.debug(tableTag + " extension positioning subtable format: " + subtableFormat ); + log.debug(tableTag + " extension positioning lookup type: " + lt ); + log.debug(tableTag + " extension positioning lookup table offset: " + eo ); + } + // read referenced subtable from extended offset + readGPOSSubtable ( lt, lookupFlags, lookupSequence, subtableSequence, subtableOffset + eo ); + } + + private int readExtensionPosTable(int lookupType, int lookupFlags, int lookupSequence, int subtableSequence, long subtableOffset) throws IOException { + in.seekSet(subtableOffset); + // read positioning subtable format + int sf = in.readTTFUShort(); + if ( sf == 1 ) { + readExtensionPosTableFormat1 ( lookupType, lookupFlags, lookupSequence, subtableSequence, subtableOffset, sf ); + } else { + throw new AdvancedTypographicTableFormatException ( "unsupported extension positioning subtable format: " + sf ); + } + return sf; + } + + private void readGPOSSubtable(int lookupType, int lookupFlags, int lookupSequence, int subtableSequence, long subtableOffset) throws IOException { + initATSubState(); + int subtableFormat = -1; + switch ( lookupType ) { + case GPOSLookupType.SINGLE: + subtableFormat = readSinglePosTable ( lookupType, lookupFlags, subtableOffset ); + break; + case GPOSLookupType.PAIR: + subtableFormat = readPairPosTable ( lookupType, lookupFlags, subtableOffset ); + break; + case GPOSLookupType.CURSIVE: + subtableFormat = readCursivePosTable ( lookupType, lookupFlags, subtableOffset ); + break; + case GPOSLookupType.MARK_TO_BASE: + subtableFormat = readMarkToBasePosTable ( lookupType, lookupFlags, subtableOffset ); + break; + case GPOSLookupType.MARK_TO_LIGATURE: + subtableFormat = readMarkToLigaturePosTable ( lookupType, lookupFlags, subtableOffset ); + break; + case GPOSLookupType.MARK_TO_MARK: + subtableFormat = readMarkToMarkPosTable ( lookupType, lookupFlags, subtableOffset ); + break; + case GPOSLookupType.CONTEXTUAL: + subtableFormat = readContextualPosTable ( lookupType, lookupFlags, subtableOffset ); + break; + case GPOSLookupType.CHAINED_CONTEXTUAL: + subtableFormat = readChainedContextualPosTable ( lookupType, lookupFlags, subtableOffset ); + break; + case GPOSLookupType.EXTENSION: + subtableFormat = readExtensionPosTable ( lookupType, lookupFlags, lookupSequence, subtableSequence, subtableOffset ); + break; + default: + break; + } + extractSESubState ( GlyphTable.GLYPH_TABLE_TYPE_POSITIONING, lookupType, lookupFlags, lookupSequence, subtableSequence, subtableFormat ); + resetATSubState(); + } + + private void readLookupTable(String tableTag, int lookupSequence, long lookupTable) throws IOException { + boolean isGSUB = tableTag.equals ( "GSUB" ); + boolean isGPOS = tableTag.equals ( "GPOS" ); + in.seekSet(lookupTable); + // read lookup type + int lt = in.readTTFUShort(); + // read lookup flags + int lf = in.readTTFUShort(); + // read sub-table count + int ns = in.readTTFUShort(); + // dump info if debugging + if (log.isDebugEnabled()) { + String lts; + if ( isGSUB ) { + lts = GSUBLookupType.toString ( lt ); + } else if ( isGPOS ) { + lts = GPOSLookupType.toString ( lt ); + } else { + lts = "?"; + } + log.debug(tableTag + " lookup table type: " + lt + " (" + lts + ")" ); + log.debug(tableTag + " lookup table flags: " + lf + " (" + LookupFlag.toString ( lf ) + ")" ); + log.debug(tableTag + " lookup table subtable count: " + ns ); + } + // read subtable offsets + int[] soa = new int[ns]; + for ( int i = 0; i < ns; i++ ) { + int so = in.readTTFUShort(); + if (log.isDebugEnabled()) { + log.debug(tableTag + " lookup table subtable offset: " + so ); + } + soa[i] = so; + } + // read mark filtering set + if ( ( lf & LookupFlag.USE_MARK_FILTERING_SET ) != 0 ) { + // read mark filtering set + int fs = in.readTTFUShort(); + // dump info if debugging + if (log.isDebugEnabled()) { + log.debug(tableTag + " lookup table mark filter set: " + fs ); + } + } + // read subtables + for ( int i = 0; i < ns; i++ ) { + int so = soa[i]; + if ( isGSUB ) { + readGSUBSubtable ( lt, lf, lookupSequence, i, lookupTable + so ); + } else if ( isGPOS ) { + readGPOSSubtable ( lt, lf, lookupSequence, i, lookupTable + so ); + } + } + } + + private void readLookupList(String tableTag, long lookupList) throws IOException { + in.seekSet(lookupList); + // read lookup record count + int nl = in.readTTFUShort(); + if (log.isDebugEnabled()) { + log.debug(tableTag + " lookup list record count: " + nl ); + } + if ( nl > 0 ) { + int[] loa = new int[nl]; + // read lookup records + for ( int i = 0, n = nl; i < n; i++ ) { + int lo = in.readTTFUShort(); + if (log.isDebugEnabled()) { + log.debug(tableTag + " lookup table offset: " + lo ); + } + loa[i] = lo; + } + // read lookup tables + for ( int i = 0, n = nl; i < n; i++ ) { + if (log.isDebugEnabled()) { + log.debug(tableTag + " lookup index: " + i ); + } + readLookupTable ( tableTag, i, lookupList + loa [ i ] ); + } + } + } + + /** + * Read the common layout tables (used by GSUB and GPOS). + * @param tableTag tag of table being read + * @param scriptList offset to script list from beginning of font file + * @param featureList offset to feature list from beginning of font file + * @param lookupList offset to lookup list from beginning of font file + * @throws IOException In case of a I/O problem + */ + private void readCommonLayoutTables(String tableTag, long scriptList, long featureList, long lookupList) throws IOException { + if ( scriptList > 0 ) { + readScriptList ( tableTag, scriptList ); + } + if ( featureList > 0 ) { + readFeatureList ( tableTag, featureList ); + } + if ( lookupList > 0 ) { + readLookupList ( tableTag, lookupList ); + } + } + + private void readGDEFClassDefTable(String tableTag, int lookupSequence, long subtableOffset) throws IOException { + initATSubState(); + in.seekSet(subtableOffset); + // subtable is a bare class definition table + GlyphClassTable ct = readClassDefTable ( tableTag + " glyph class definition table", subtableOffset ); + // store results + seMapping = ct; + // extract subtable + extractSESubState ( GlyphTable.GLYPH_TABLE_TYPE_DEFINITION, GDEFLookupType.GLYPH_CLASS, 0, lookupSequence, 0, 1 ); + resetATSubState(); + } + + private void readGDEFAttachmentTable(String tableTag, int lookupSequence, long subtableOffset) throws IOException { + initATSubState(); + in.seekSet(subtableOffset); + // read coverage offset + int co = in.readTTFUShort(); + // dump info if debugging + if (log.isDebugEnabled()) { + log.debug(tableTag + " attachment point coverage table offset: " + co ); + } + // read coverage table + GlyphCoverageTable ct = readCoverageTable ( tableTag + " attachment point coverage", subtableOffset + co ); + // store results + seMapping = ct; + // extract subtable + extractSESubState ( GlyphTable.GLYPH_TABLE_TYPE_DEFINITION, GDEFLookupType.ATTACHMENT_POINT, 0, lookupSequence, 0, 1 ); + resetATSubState(); + } + + private void readGDEFLigatureCaretTable(String tableTag, int lookupSequence, long subtableOffset) throws IOException { + initATSubState(); + in.seekSet(subtableOffset); + // read coverage offset + int co = in.readTTFUShort(); + // read ligature glyph count + int nl = in.readTTFUShort(); + // read ligature glyph table offsets + int[] lgto = new int [ nl ]; + for ( int i = 0; i < nl; i++ ) { + lgto [ i ] = in.readTTFUShort(); + } + + // dump info if debugging + if (log.isDebugEnabled()) { + log.debug(tableTag + " ligature caret coverage table offset: " + co ); + log.debug(tableTag + " ligature caret ligature glyph count: " + nl ); + for ( int i = 0; i < nl; i++ ) { + log.debug(tableTag + " ligature glyph table offset[" + i + "]: " + lgto[i] ); + } + } + // read coverage table + GlyphCoverageTable ct = readCoverageTable ( tableTag + " ligature caret coverage", subtableOffset + co ); + // store results + seMapping = ct; + // extract subtable + extractSESubState ( GlyphTable.GLYPH_TABLE_TYPE_DEFINITION, GDEFLookupType.LIGATURE_CARET, 0, lookupSequence, 0, 1 ); + resetATSubState(); + } + + private void readGDEFMarkAttachmentTable(String tableTag, int lookupSequence, long subtableOffset) throws IOException { + initATSubState(); + in.seekSet(subtableOffset); + // subtable is a bare class definition table + GlyphClassTable ct = readClassDefTable ( tableTag + " glyph class definition table", subtableOffset ); + // store results + seMapping = ct; + // extract subtable + extractSESubState ( GlyphTable.GLYPH_TABLE_TYPE_DEFINITION, GDEFLookupType.MARK_ATTACHMENT, 0, lookupSequence, 0, 1 ); + resetATSubState(); + } + + private void readGDEFMarkGlyphsTableFormat1(String tableTag, int lookupSequence, long subtableOffset, int subtableFormat) throws IOException { + initATSubState(); + in.seekSet(subtableOffset); + // skip over format (already known) + in.skip ( 2 ); + // read mark set class count + int nmc = in.readTTFUShort(); + long[] mso = new long [ nmc ]; + // read mark set coverage offsets + for ( int i = 0; i < nmc; i++ ) { + mso [ i ] = in.readTTFULong(); + } + // dump info if debugging + if (log.isDebugEnabled()) { + log.debug(tableTag + " mark set subtable format: " + subtableFormat + " (glyph sets)" ); + log.debug(tableTag + " mark set class count: " + nmc ); + for ( int i = 0; i < nmc; i++ ) { + log.debug(tableTag + " mark set coverage table offset[" + i + "]: " + mso[i] ); + } + } + // read mark set coverage tables, one per class + GlyphCoverageTable[] msca = new GlyphCoverageTable[nmc]; + for ( int i = 0; i < nmc; i++ ) { + msca[i] = readCoverageTable ( tableTag + " mark set coverage[" + i + "]", subtableOffset + mso[i] ); + } + // create combined class table from per-class coverage tables + GlyphClassTable ct = GlyphClassTable.createClassTable ( Arrays.asList ( msca ) ); + // store results + seMapping = ct; + // extract subtable + extractSESubState ( GlyphTable.GLYPH_TABLE_TYPE_DEFINITION, GDEFLookupType.MARK_ATTACHMENT, 0, lookupSequence, 0, 1 ); + resetATSubState(); + } + + private void readGDEFMarkGlyphsTable(String tableTag, int lookupSequence, long subtableOffset) throws IOException { + in.seekSet(subtableOffset); + // read mark set subtable format + int sf = in.readTTFUShort(); + if ( sf == 1 ) { + readGDEFMarkGlyphsTableFormat1 ( tableTag, lookupSequence, subtableOffset, sf ); + } else { + throw new AdvancedTypographicTableFormatException ( "unsupported mark glyph sets subtable format: " + sf ); + } + } + + /** + * Read the GDEF table. + * @throws IOException In case of a I/O problem + */ + private void readGDEF() throws IOException { + String tableTag = "GDEF"; + // Initialize temporary state + initATState(); + // Read glyph definition (GDEF) table + TTFDirTabEntry dirTab = ttf.getDirectoryEntry ( tableTag ); + if ( gdef != null ) { + if (log.isDebugEnabled()) { + log.debug(tableTag + ": ignoring duplicate table"); + } + } else if (dirTab != null) { + ttf.seekTab(in, tableTag, 0); + long version = in.readTTFULong(); + if (log.isDebugEnabled()) { + log.debug(tableTag + " version: " + ( version / 65536 ) + "." + ( version % 65536 )); + } + // glyph class definition table offset (may be null) + int cdo = in.readTTFUShort(); + // attach point list offset (may be null) + int apo = in.readTTFUShort(); + // ligature caret list offset (may be null) + int lco = in.readTTFUShort(); + // mark attach class definition table offset (may be null) + int mao = in.readTTFUShort(); + // mark glyph sets definition table offset (may be null) + int mgo; + if ( version >= 0x00010002 ) { + mgo = in.readTTFUShort(); + } else { + mgo = 0; + } + if (log.isDebugEnabled()) { + log.debug(tableTag + " glyph class definition table offset: " + cdo ); + log.debug(tableTag + " attachment point list offset: " + apo ); + log.debug(tableTag + " ligature caret list offset: " + lco ); + log.debug(tableTag + " mark attachment class definition table offset: " + mao ); + log.debug(tableTag + " mark glyph set definitions table offset: " + mgo ); + } + // initialize subtable sequence number + int seqno = 0; + // obtain offset to start of gdef table + long to = dirTab.getOffset(); + // (optionally) read glyph class definition subtable + if ( cdo != 0 ) { + readGDEFClassDefTable ( tableTag, seqno++, to + cdo ); + } + // (optionally) read glyph attachment point subtable + if ( apo != 0 ) { + readGDEFAttachmentTable ( tableTag, seqno++, to + apo ); + } + // (optionally) read ligature caret subtable + if ( lco != 0 ) { + readGDEFLigatureCaretTable ( tableTag, seqno++, to + lco ); + } + // (optionally) read mark attachment class subtable + if ( mao != 0 ) { + readGDEFMarkAttachmentTable ( tableTag, seqno++, to + mao ); + } + // (optionally) read mark glyph sets subtable + if ( mgo != 0 ) { + readGDEFMarkGlyphsTable ( tableTag, seqno++, to + mgo ); + } + GlyphDefinitionTable gdef; + if ( ( gdef = constructGDEF() ) != null ) { + this.gdef = gdef; + } + } + } + + /** + * Read the GSUB table. + * @throws IOException In case of a I/O problem + */ + private void readGSUB() throws IOException { + String tableTag = "GSUB"; + // Initialize temporary state + initATState(); + // Read glyph substitution (GSUB) table + TTFDirTabEntry dirTab = ttf.getDirectoryEntry ( tableTag ); + if ( gpos != null ) { + if (log.isDebugEnabled()) { + log.debug(tableTag + ": ignoring duplicate table"); + } + } else if (dirTab != null) { + ttf.seekTab(in, tableTag, 0); + int version = in.readTTFLong(); + if (log.isDebugEnabled()) { + log.debug(tableTag + " version: " + ( version / 65536 ) + "." + ( version % 65536 )); + } + int slo = in.readTTFUShort(); + int flo = in.readTTFUShort(); + int llo = in.readTTFUShort(); + if (log.isDebugEnabled()) { + log.debug(tableTag + " script list offset: " + slo ); + log.debug(tableTag + " feature list offset: " + flo ); + log.debug(tableTag + " lookup list offset: " + llo ); + } + long to = dirTab.getOffset(); + readCommonLayoutTables ( tableTag, to + slo, to + flo, to + llo ); + GlyphSubstitutionTable gsub; + if ( ( gsub = constructGSUB() ) != null ) { + this.gsub = gsub; + } + } + } + + /** + * Read the GPOS table. + * @throws IOException In case of a I/O problem + */ + private void readGPOS() throws IOException { + String tableTag = "GPOS"; + // Initialize temporary state + initATState(); + // Read glyph positioning (GPOS) table + TTFDirTabEntry dirTab = ttf.getDirectoryEntry ( tableTag ); + if ( gpos != null ) { + if (log.isDebugEnabled()) { + log.debug(tableTag + ": ignoring duplicate table"); + } + } else if (dirTab != null) { + ttf.seekTab(in, tableTag, 0); + int version = in.readTTFLong(); + if (log.isDebugEnabled()) { + log.debug(tableTag + " version: " + ( version / 65536 ) + "." + ( version % 65536 )); + } + int slo = in.readTTFUShort(); + int flo = in.readTTFUShort(); + int llo = in.readTTFUShort(); + if (log.isDebugEnabled()) { + log.debug(tableTag + " script list offset: " + slo ); + log.debug(tableTag + " feature list offset: " + flo ); + log.debug(tableTag + " lookup list offset: " + llo ); + } + long to = dirTab.getOffset(); + readCommonLayoutTables ( tableTag, to + slo, to + flo, to + llo ); + GlyphPositioningTable gpos; + if ( ( gpos = constructGPOS() ) != null ) { + this.gpos = gpos; + } + } + } + + /** + * Construct the (internal representation of the) GDEF table based on previously + * parsed state. + * @returns glyph definition table or null if insufficient or invalid state + */ + private GlyphDefinitionTable constructGDEF() { + GlyphDefinitionTable gdef = null; + List subtables; + if ( ( subtables = constructGDEFSubtables() ) != null ) { + if ( subtables.size() > 0 ) { + gdef = new GlyphDefinitionTable ( subtables ); + } + } + resetATState(); + return gdef; + } + + /** + * Construct the (internal representation of the) GSUB table based on previously + * parsed state. + * @returns glyph substitution table or null if insufficient or invalid state + */ + private GlyphSubstitutionTable constructGSUB() { + GlyphSubstitutionTable gsub = null; + Map lookups; + if ( ( lookups = constructLookups() ) != null ) { + List subtables; + if ( ( subtables = constructGSUBSubtables() ) != null ) { + if ( ( lookups.size() > 0 ) && ( subtables.size() > 0 ) ) { + gsub = new GlyphSubstitutionTable ( gdef, lookups, subtables ); + } + } + } + resetATState(); + return gsub; + } + + /** + * Construct the (internal representation of the) GPOS table based on previously + * parsed state. + * @returns glyph positioning table or null if insufficient or invalid state + */ + private GlyphPositioningTable constructGPOS() { + GlyphPositioningTable gpos = null; + Map lookups; + if ( ( lookups = constructLookups() ) != null ) { + List subtables; + if ( ( subtables = constructGPOSSubtables() ) != null ) { + if ( ( lookups.size() > 0 ) && ( subtables.size() > 0 ) ) { + gpos = new GlyphPositioningTable ( gdef, lookups, subtables ); + } + } + } + resetATState(); + return gpos; + } + + private void constructLookupsFeature ( Map lookups, String st, String lt, String fid ) { + Object[] fp = (Object[]) seFeatures.get ( fid ); + if ( fp != null ) { + assert fp.length == 2; + String ft = (String) fp[0]; // feature tag + List/**/ lul = (List) fp[1]; // list of lookup table ids + if ( ( ft != null ) && ( lul != null ) && ( lul.size() > 0 ) ) { + GlyphTable.LookupSpec ls = new GlyphTable.LookupSpec ( st, lt, ft ); + lookups.put ( ls, lul ); + } + } + } + + private void constructLookupsFeatures ( Map lookups, String st, String lt, List/**/ fids ) { + for ( Iterator fit = fids.iterator(); fit.hasNext();) { + String fid = (String) fit.next(); + constructLookupsFeature ( lookups, st, lt, fid ); + } + } + + private void constructLookupsLanguage ( Map lookups, String st, String lt, Map/**/ languages ) { + Object[] lp = (Object[]) languages.get ( lt ); + if ( lp != null ) { + assert lp.length == 2; + if ( lp[0] != null ) { // required feature id + constructLookupsFeature ( lookups, st, lt, (String) lp[0] ); + } + if ( lp[1] != null ) { // non-required features ids + constructLookupsFeatures ( lookups, st, lt, (List) lp[1] ); + } + } + } + + private void constructLookupsLanguages ( Map lookups, String st, List/**/ ll, Map/**/ languages ) { + for ( Iterator lit = ll.iterator(); lit.hasNext();) { + String lt = (String) lit.next(); + constructLookupsLanguage ( lookups, st, lt, languages ); + } + } + + private Map constructLookups() { + Map/*>*/ lookups = new java.util.LinkedHashMap(); + for ( Iterator sit = seScripts.keySet().iterator(); sit.hasNext();) { + String st = (String) sit.next(); + Object[] sp = (Object[]) seScripts.get ( st ); + if ( sp != null ) { + assert sp.length == 3; + Map/**/ languages = (Map) sp[2]; + if ( sp[0] != null ) { // default language + constructLookupsLanguage ( lookups, st, (String) sp[0], languages ); + } + if ( sp[1] != null ) { // non-default languages + constructLookupsLanguages ( lookups, st, (List) sp[1], languages ); + } + } + } + return lookups; + } + + private List constructGDEFSubtables() { + List/**/ subtables = new java.util.ArrayList(); + if ( seSubtables != null ) { + for ( Iterator it = seSubtables.iterator(); it.hasNext();) { + Object[] stp = (Object[]) it.next(); + GlyphSubtable st; + if ( ( st = constructGDEFSubtable ( stp ) ) != null ) { + subtables.add ( st ); + } + } + } + return subtables; + } + + private GlyphSubtable constructGDEFSubtable ( Object[] stp ) { + GlyphSubtable st = null; + assert ( stp != null ) && ( stp.length == 8 ); + Integer tt = (Integer) stp[0]; // table type + Integer lt = (Integer) stp[1]; // lookup type + Integer ln = (Integer) stp[2]; // lookup sequence number + Integer lf = (Integer) stp[3]; // lookup flags + Integer sn = (Integer) stp[4]; // subtable sequence number + Integer sf = (Integer) stp[5]; // subtable format + GlyphMappingTable mapping = (GlyphMappingTable) stp[6]; + List entries = (List) stp[7]; + if ( tt.intValue() == GlyphTable.GLYPH_TABLE_TYPE_DEFINITION ) { + int type = GDEFLookupType.getSubtableType ( lt.intValue() ); + String lid = "lu" + ln.intValue(); + int sequence = sn.intValue(); + int flags = lf.intValue(); + int format = sf.intValue(); + st = GlyphDefinitionTable.createSubtable ( type, lid, sequence, flags, format, mapping, entries ); + } + return st; + } + + private List constructGSUBSubtables() { + List/**/ subtables = new java.util.ArrayList(); + if ( seSubtables != null ) { + for ( Iterator it = seSubtables.iterator(); it.hasNext();) { + Object[] stp = (Object[]) it.next(); + GlyphSubtable st; + if ( ( st = constructGSUBSubtable ( stp ) ) != null ) { + subtables.add ( st ); + } + } + } + return subtables; + } + + private GlyphSubtable constructGSUBSubtable ( Object[] stp ) { + GlyphSubtable st = null; + assert ( stp != null ) && ( stp.length == 8 ); + Integer tt = (Integer) stp[0]; // table type + Integer lt = (Integer) stp[1]; // lookup type + Integer ln = (Integer) stp[2]; // lookup sequence number + Integer lf = (Integer) stp[3]; // lookup flags + Integer sn = (Integer) stp[4]; // subtable sequence number + Integer sf = (Integer) stp[5]; // subtable format + GlyphCoverageTable coverage = (GlyphCoverageTable) stp[6]; + List entries = (List) stp[7]; + if ( tt.intValue() == GlyphTable.GLYPH_TABLE_TYPE_SUBSTITUTION ) { + int type = GSUBLookupType.getSubtableType ( lt.intValue() ); + String lid = "lu" + ln.intValue(); + int sequence = sn.intValue(); + int flags = lf.intValue(); + int format = sf.intValue(); + st = GlyphSubstitutionTable.createSubtable ( type, lid, sequence, flags, format, coverage, entries ); + } + return st; + } + + private List constructGPOSSubtables() { + List/**/ subtables = new java.util.ArrayList(); + if ( seSubtables != null ) { + for ( Iterator it = seSubtables.iterator(); it.hasNext();) { + Object[] stp = (Object[]) it.next(); + GlyphSubtable st; + if ( ( st = constructGPOSSubtable ( stp ) ) != null ) { + subtables.add ( st ); + } + } + } + return subtables; + } + + private GlyphSubtable constructGPOSSubtable ( Object[] stp ) { + GlyphSubtable st = null; + assert ( stp != null ) && ( stp.length == 8 ); + Integer tt = (Integer) stp[0]; // table type + Integer lt = (Integer) stp[1]; // lookup type + Integer ln = (Integer) stp[2]; // lookup sequence number + Integer lf = (Integer) stp[3]; // lookup flags + Integer sn = (Integer) stp[4]; // subtable sequence number + Integer sf = (Integer) stp[5]; // subtable format + GlyphCoverageTable coverage = (GlyphCoverageTable) stp[6]; + List entries = (List) stp[7]; + if ( tt.intValue() == GlyphTable.GLYPH_TABLE_TYPE_POSITIONING ) { + int type = GSUBLookupType.getSubtableType ( lt.intValue() ); + String lid = "lu" + ln.intValue(); + int sequence = sn.intValue(); + int flags = lf.intValue(); + int format = sf.intValue(); + st = GlyphPositioningTable.createSubtable ( type, lid, sequence, flags, format, coverage, entries ); + } + return st; + } + + private void initATState() { + seScripts = new java.util.LinkedHashMap(); + seLanguages = new java.util.LinkedHashMap(); + seFeatures = new java.util.LinkedHashMap(); + seSubtables = new java.util.ArrayList(); + resetATSubState(); + } + + private void resetATState() { + seScripts = null; + seLanguages = null; + seFeatures = null; + seSubtables = null; + resetATSubState(); + } + + private void initATSubState() { + seMapping = null; + seEntries = new java.util.ArrayList(); + } + + private void extractSESubState ( int tableType, int lookupType, int lookupFlags, int lookupSequence, int subtableSequence, int subtableFormat ) { + if ( seEntries != null ) { + if ( ( tableType == GlyphTable.GLYPH_TABLE_TYPE_DEFINITION ) || ( seEntries.size() > 0 ) ) { + if ( seSubtables != null ) { + Integer tt = Integer.valueOf ( tableType ); + Integer lt = Integer.valueOf ( lookupType ); + Integer ln = Integer.valueOf ( lookupSequence ); + Integer lf = Integer.valueOf ( lookupFlags ); + Integer sn = Integer.valueOf ( subtableSequence ); + Integer sf = Integer.valueOf ( subtableFormat ); + seSubtables.add ( new Object[] { tt, lt, ln, lf, sn, sf, seMapping, seEntries } ); + } + } + } + } + + private void resetATSubState() { + seMapping = null; + seEntries = null; + } + + private void resetATStateAll() { + resetATState(); + gdef = null; gsub = null; gpos = null; + } + + /** helper method for formatting an integer array for output */ + private String toString ( int[] ia ) { + StringBuffer sb = new StringBuffer(); + if ( ( ia == null ) || ( ia.length == 0 ) ) { + sb.append ( '-' ); + } else { + boolean first = true; + for ( int i = 0; i < ia.length; i++ ) { + if ( ! first ) { + sb.append ( ' ' ); + } else { + first = false; + } + sb.append ( ia[i] ); + } + } + return sb.toString(); + } + +} diff --git a/src/java/org/apache/fop/complexscripts/fonts/Positionable.java b/src/java/org/apache/fop/complexscripts/fonts/Positionable.java new file mode 100644 index 000000000..ce2da38c6 --- /dev/null +++ b/src/java/org/apache/fop/complexscripts/fonts/Positionable.java @@ -0,0 +1,58 @@ +/* + * 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.complexscripts.fonts; + +// CSOFF: LineLengthCheck + +/** + * Optional interface which indicates that glyph positioning is supported and, if supported, + * can perform positioning. + * @author Glenn Adams + */ +public interface Positionable { + + /** + * Determines if font performs glyph positioning. + * @return true if performs positioning + */ + boolean performsPositioning(); + + /** + * Perform glyph positioning. + * @param cs character sequence to map to position offsets (advancement adjustments) + * @param script a script identifier + * @param language a language identifier + * @param fontSize font size + * @return array (sequence) of 4-tuples of placement [PX,PY] and advance [AX,AY] adjustments, in that order, + * with one 4-tuple for each element of glyph sequence, or null if no non-zero adjustment applies + */ + int[][] performPositioning ( CharSequence cs, String script, String language, int fontSize ); + + /** + * Perform glyph positioning using an implied font size. + * @param cs character sequence to map to position offsets (advancement adjustments) + * @param script a script identifier + * @param language a language identifier + * @return array (sequence) of 4-tuples of placement [PX,PY] and advance [AX,AY] adjustments, in that order, + * with one 4-tuple for each element of glyph sequence, or null if no non-zero adjustment applies + */ + int[][] performPositioning ( CharSequence cs, String script, String language ); + +} diff --git a/src/java/org/apache/fop/complexscripts/fonts/Substitutable.java b/src/java/org/apache/fop/complexscripts/fonts/Substitutable.java new file mode 100644 index 000000000..1ff970a5e --- /dev/null +++ b/src/java/org/apache/fop/complexscripts/fonts/Substitutable.java @@ -0,0 +1,63 @@ +/* + * 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.complexscripts.fonts; + +// CSOFF: LineLengthCheck + +/** + * Optional interface which indicates that glyph substitution is supported and, if supported, + * can perform substitution. + * @author Glenn Adams + */ +public interface Substitutable { + + /** + * Determines if font performs glyph substitution. + * @return true if performs substitution. + */ + boolean performsSubstitution(); + + /** + * Perform substitutions on characters to effect glyph substitution. If some substitution is performed, it + * entails mapping from one or more input characters denoting textual character information to one or more + * output character codes denoting glyphs in this font, where the output character codes may make use of + * private character code values that have significance only for this font. + * @param cs character sequence to map to output font encoding character sequence + * @param script a script identifier + * @param language a language identifier + * @return output sequence (represented as a character sequence, where each character in the returned sequence + * denotes "font characters", i.e., character codes that map directly (1-1) to their associated glyphs + */ + CharSequence performSubstitution ( CharSequence cs, String script, String language ); + + /** + * Reorder combining marks in character sequence so that they precede (within the sequence) the base + * character to which they are applied. N.B. In the case of LTR segments, marks are not reordered by this, + * method since when the segment is reversed by BIDI processing, marks are automatically reordered to precede + * their base character. + * @param cs character sequence within which combining marks to be reordered + * @param gpa associated glyph position adjustments (also reordered) + * @param script a script identifier + * @param language a language identifier + * @return output sequence containing reordered "font characters" + */ + CharSequence reorderCombiningMarks ( CharSequence cs, int[][] gpa, String script, String language ); + +} diff --git a/src/java/org/apache/fop/complexscripts/scripts/ArabicScriptProcessor.java b/src/java/org/apache/fop/complexscripts/scripts/ArabicScriptProcessor.java new file mode 100644 index 000000000..503ee2705 --- /dev/null +++ b/src/java/org/apache/fop/complexscripts/scripts/ArabicScriptProcessor.java @@ -0,0 +1,522 @@ +/* + * 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.complexscripts.scripts; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.apache.fop.complexscripts.bidi.BidiClass; +import org.apache.fop.complexscripts.bidi.BidiConstants; +import org.apache.fop.complexscripts.fonts.GlyphDefinitionTable; +import org.apache.fop.complexscripts.util.GlyphContextTester; +import org.apache.fop.complexscripts.util.GlyphSequence; +import org.apache.fop.complexscripts.util.ScriptContextTester; + +// CSOFF: AvoidNestedBlocksCheck +// CSOFF: NoWhitespaceAfterCheck +// CSOFF: InnerAssignmentCheck +// CSOFF: SimplifyBooleanReturnCheck +// CSOFF: LineLengthCheck + +/** + *

The ArabicScriptProcessor class implements a script processor for + * performing glyph substitution and positioning operations on content associated with the Arabic script.

+ * @author Glenn Adams + */ +public class ArabicScriptProcessor extends DefaultScriptProcessor { + + /** logging instance */ + private static final Log log = LogFactory.getLog(ArabicScriptProcessor.class); // CSOK: ConstantNameCheck + + /** features to use for substitutions */ + private static final String[] gsubFeatures = // CSOK: ConstantNameCheck + { + "calt", // contextual alternates + "ccmp", // glyph composition/decomposition + "fina", // final (terminal) forms + "init", // initial forms + "isol", // isolated formas + "liga", // standard ligatures + "medi", // medial forms + "rlig" // required ligatures + }; + + /** features to use for positioning */ + private static final String[] gposFeatures = // CSOK: ConstantNameCheck + { + "curs", // cursive positioning + "kern", // kerning + "mark", // mark to base or ligature positioning + "mkmk" // mark to mark positioning + }; + + private static class SubstitutionScriptContextTester implements ScriptContextTester { + private static Map/**/ testerMap = new HashMap/**/(); + static { + testerMap.put ( "fina", new GlyphContextTester() { + public boolean test ( String script, String language, String feature, GlyphSequence gs, int index, int flags ) { + return inFinalContext ( script, language, feature, gs, index, flags ); + } + } ); + testerMap.put ( "init", new GlyphContextTester() { + public boolean test ( String script, String language, String feature, GlyphSequence gs, int index, int flags ) { + return inInitialContext ( script, language, feature, gs, index, flags ); + } + } ); + testerMap.put ( "isol", new GlyphContextTester() { + public boolean test ( String script, String language, String feature, GlyphSequence gs, int index, int flags ) { + return inIsolateContext ( script, language, feature, gs, index, flags ); + } + } ); + testerMap.put ( "liga", new GlyphContextTester() { + public boolean test ( String script, String language, String feature, GlyphSequence gs, int index, int flags ) { + return inLigatureContext ( script, language, feature, gs, index, flags ); + } + } ); + testerMap.put ( "medi", new GlyphContextTester() { + public boolean test ( String script, String language, String feature, GlyphSequence gs, int index, int flags ) { + return inMedialContext ( script, language, feature, gs, index, flags ); + } + } ); + } + public GlyphContextTester getTester ( String feature ) { + return (GlyphContextTester) testerMap.get ( feature ); + } + } + + private static class PositioningScriptContextTester implements ScriptContextTester { + private static Map/**/ testerMap = new HashMap/**/(); + public GlyphContextTester getTester ( String feature ) { + return (GlyphContextTester) testerMap.get ( feature ); + } + } + + private final ScriptContextTester subContextTester; + private final ScriptContextTester posContextTester; + + ArabicScriptProcessor ( String script ) { + super ( script ); + this.subContextTester = new SubstitutionScriptContextTester(); + this.posContextTester = new PositioningScriptContextTester(); + } + + /** {@inheritDoc} */ + public String[] getSubstitutionFeatures() { + return gsubFeatures; + } + + /** {@inheritDoc} */ + public ScriptContextTester getSubstitutionContextTester() { + return subContextTester; + } + + /** {@inheritDoc} */ + public String[] getPositioningFeatures() { + return gposFeatures; + } + + /** {@inheritDoc} */ + public ScriptContextTester getPositioningContextTester() { + return posContextTester; + } + + /** {@inheritDoc} */ + @Override + public GlyphSequence reorderCombiningMarks ( GlyphDefinitionTable gdef, GlyphSequence gs, int[][] gpa, String script, String language ) { + // a side effect of BIDI reordering is to order combining marks before their base, so we need to override the default here to + // prevent double reordering + return gs; + } + + private static boolean inFinalContext ( String script, String language, String feature, GlyphSequence gs, int index, int flags ) { + GlyphSequence.CharAssociation a = gs.getAssociation ( index ); + int[] ca = gs.getCharacterArray ( false ); + int nc = gs.getCharacterCount(); + if ( nc == 0 ) { + return false; + } else { + int s = a.getStart(); + int e = a.getEnd(); + if ( ! hasFinalPrecedingContext ( ca, nc, s, e ) ) { + return false; + } else if ( forcesFinalThisContext ( ca, nc, s, e ) ) { + return true; + } else if ( ! hasFinalFollowingContext ( ca, nc, s, e ) ) { + return false; + } else { + return true; + } + } + } + + private static boolean inInitialContext ( String script, String language, String feature, GlyphSequence gs, int index, int flags ) { + GlyphSequence.CharAssociation a = gs.getAssociation ( index ); + int[] ca = gs.getCharacterArray ( false ); + int nc = gs.getCharacterCount(); + if ( nc == 0 ) { + return false; + } else { + int s = a.getStart(); + int e = a.getEnd(); + if ( ! hasInitialPrecedingContext ( ca, nc, s, e ) ) { + return false; + } else if ( ! hasInitialFollowingContext ( ca, nc, s, e ) ) { + return false; + } else { + return true; + } + } + } + + private static boolean inIsolateContext ( String script, String language, String feature, GlyphSequence gs, int index, int flags ) { + GlyphSequence.CharAssociation a = gs.getAssociation ( index ); + int nc = gs.getCharacterCount(); + if ( nc == 0 ) { + return false; + } else if ( ( a.getStart() == 0 ) && ( a.getEnd() == nc ) ) { + return true; + } else { + return false; + } + } + + private static boolean inLigatureContext ( String script, String language, String feature, GlyphSequence gs, int index, int flags ) { + GlyphSequence.CharAssociation a = gs.getAssociation ( index ); + int[] ca = gs.getCharacterArray ( false ); + int nc = gs.getCharacterCount(); + if ( nc == 0 ) { + return false; + } else { + int s = a.getStart(); + int e = a.getEnd(); + if ( ! hasLigaturePrecedingContext ( ca, nc, s, e ) ) { + return false; + } else if ( ! hasLigatureFollowingContext ( ca, nc, s, e ) ) { + return false; + } else { + return true; + } + } + } + + private static boolean inMedialContext ( String script, String language, String feature, GlyphSequence gs, int index, int flags ) { + GlyphSequence.CharAssociation a = gs.getAssociation ( index ); + int[] ca = gs.getCharacterArray ( false ); + int nc = gs.getCharacterCount(); + if ( nc == 0 ) { + return false; + } else { + int s = a.getStart(); + int e = a.getEnd(); + if ( ! hasMedialPrecedingContext ( ca, nc, s, e ) ) { + return false; + } else if ( ! hasMedialThisContext ( ca, nc, s, e ) ) { + return false; + } else if ( ! hasMedialFollowingContext ( ca, nc, s, e ) ) { + return false; + } else { + return true; + } + } + } + + private static boolean hasFinalPrecedingContext ( int[] ca, int nc, int s, int e ) { + int chp = 0; + int clp = 0; + for ( int i = s; i > 0; i-- ) { + int k = i - 1; + if ( ( k >= 0 ) && ( k < nc ) ) { + chp = ca [ k ]; + clp = BidiClass.getBidiClass ( chp ); + if ( clp != BidiConstants.NSM ) { + break; + } + } + } + if ( clp != BidiConstants.AL ) { + return false; + } else if ( hasIsolateInitial ( chp ) ) { + return false; + } else { + return true; + } + } + + private static boolean forcesFinalThisContext ( int[] ca, int nc, int s, int e ) { + int chl = 0; + int cll = 0; + for ( int i = 0, n = e - s; i < n; i++ ) { + int k = n - i - 1; + int j = s + k; + if ( ( j >= 0 ) && ( j < nc ) ) { + chl = ca [ j ]; + cll = BidiClass.getBidiClass ( chl ); + if ( cll != BidiConstants.NSM ) { + break; + } + } + } + if ( cll != BidiConstants.AL ) { + return false; + } + if ( hasIsolateInitial ( chl ) ) { + return true; + } else { + return false; + } + } + + private static boolean hasFinalFollowingContext ( int[] ca, int nc, int s, int e ) { + int chf = 0; + int clf = 0; + for ( int i = e, n = nc; i < n; i++ ) { + chf = ca [ i ]; + clf = BidiClass.getBidiClass ( chf ); + if ( clf != BidiConstants.NSM ) { + break; + } + } + if ( clf != BidiConstants.AL ) { + return true; + } else if ( hasIsolateFinal ( chf ) ) { + return true; + } else { + return false; + } + } + + private static boolean hasInitialPrecedingContext ( int[] ca, int nc, int s, int e ) { + int chp = 0; + int clp = 0; + for ( int i = s; i > 0; i-- ) { + int k = i - 1; + if ( ( k >= 0 ) && ( k < nc ) ) { + chp = ca [ k ]; + clp = BidiClass.getBidiClass ( chp ); + if ( clp != BidiConstants.NSM ) { + break; + } + } + } + if ( clp != BidiConstants.AL ) { + return true; + } else if ( hasIsolateInitial ( chp ) ) { + return true; + } else { + return false; + } + } + + private static boolean hasInitialFollowingContext ( int[] ca, int nc, int s, int e ) { + int chf = 0; + int clf = 0; + for ( int i = e, n = nc; i < n; i++ ) { + chf = ca [ i ]; + clf = BidiClass.getBidiClass ( chf ); + if ( clf != BidiConstants.NSM ) { + break; + } + } + if ( clf != BidiConstants.AL ) { + return false; + } else if ( hasIsolateFinal ( chf ) ) { + return false; + } else { + return true; + } + } + + private static boolean hasMedialPrecedingContext ( int[] ca, int nc, int s, int e ) { + int chp = 0; + int clp = 0; + for ( int i = s; i > 0; i-- ) { + int k = i - 1; + if ( ( k >= 0 ) && ( k < nc ) ) { + chp = ca [ k ]; + clp = BidiClass.getBidiClass ( chp ); + if ( clp != BidiConstants.NSM ) { + break; + } + } + } + if ( clp != BidiConstants.AL ) { + return false; + } else if ( hasIsolateInitial ( chp ) ) { + return false; + } else { + return true; + } + } + + private static boolean hasMedialThisContext ( int[] ca, int nc, int s, int e ) { + int chf = 0; // first non-NSM char in [s,e) + int clf = 0; + for ( int i = 0, n = e - s; i < n; i++ ) { + int k = s + i; + if ( ( k >= 0 ) && ( k < nc ) ) { + chf = ca [ s + i ]; + clf = BidiClass.getBidiClass ( chf ); + if ( clf != BidiConstants.NSM ) { + break; + } + } + } + if ( clf != BidiConstants.AL ) { + return false; + } + int chl = 0; // last non-NSM char in [s,e) + int cll = 0; + for ( int i = 0, n = e - s; i < n; i++ ) { + int k = n - i - 1; + int j = s + k; + if ( ( j >= 0 ) && ( j < nc ) ) { + chl = ca [ j ]; + cll = BidiClass.getBidiClass ( chl ); + if ( cll != BidiConstants.NSM ) { + break; + } + } + } + if ( cll != BidiConstants.AL ) { + return false; + } + if ( hasIsolateFinal ( chf ) ) { + return false; + } else if ( hasIsolateInitial ( chl ) ) { + return false; + } else { + return true; + } + } + + private static boolean hasMedialFollowingContext ( int[] ca, int nc, int s, int e ) { + int chf = 0; + int clf = 0; + for ( int i = e, n = nc; i < n; i++ ) { + chf = ca [ i ]; + clf = BidiClass.getBidiClass ( chf ); + if ( clf != BidiConstants.NSM ) { + break; + } + } + if ( clf != BidiConstants.AL ) { + return false; + } else if ( hasIsolateFinal ( chf ) ) { + return false; + } else { + return true; + } + } + + private static boolean hasLigaturePrecedingContext ( int[] ca, int nc, int s, int e ) { + return true; + } + + private static boolean hasLigatureFollowingContext ( int[] ca, int nc, int s, int e ) { + int chf = 0; + int clf = 0; + for ( int i = e, n = nc; i < n; i++ ) { + chf = ca [ i ]; + clf = BidiClass.getBidiClass ( chf ); + if ( clf != BidiConstants.NSM ) { + break; + } + } + if ( clf == BidiConstants.AL ) { + return true; + } else { + return false; + } + } + + /** + * Ordered array of Unicode scalars designating those Arabic (Script) Letters + * which exhibit an isolated form in word initial position. + */ + private static int[] isolatedInitials = { + 0x0621, // HAMZA + 0x0622, // ALEF WITH MADDA ABOVE + 0x0623, // ALEF WITH HAMZA ABOVE + 0x0624, // WAW WITH HAMZA ABOVE + 0x0625, // ALEF WITH HAMZA BELOWW + 0x0627, // ALEF + 0x062F, // DAL + 0x0630, // THAL + 0x0631, // REH + 0x0632, // ZAIN + 0x0648, // WAW + 0x0671, // ALEF WASLA + 0x0672, // ALEF WITH WAVY HAMZA ABOVE + 0x0673, // ALEF WITH WAVY HAMZA BELOW + 0x0675, // HIGH HAMZA ALEF + 0x0676, // HIGH HAMZA WAW + 0x0677, // U WITH HAMZA ABOVE + 0x0688, // DDAL + 0x0689, // DAL WITH RING + 0x068A, // DAL WITH DOT BELOW + 0x068B, // DAL WITH DOT BELOW AND SMALL TAH + 0x068C, // DAHAL + 0x068D, // DDAHAL + 0x068E, // DUL + 0x068F, // DUL WITH THREE DOTS ABOVE DOWNWARDS + 0x0690, // DUL WITH FOUR DOTS ABOVE + 0x0691, // RREH + 0x0692, // REH WITH SMALL V + 0x0693, // REH WITH RING + 0x0694, // REH WITH DOT BELOW + 0x0695, // REH WITH SMALL V BELOW + 0x0696, // REH WITH DOT BELOW AND DOT ABOVE + 0x0697, // REH WITH TWO DOTS ABOVE + 0x0698, // JEH + 0x0699, // REH WITH FOUR DOTS ABOVE + 0x06C4, // WAW WITH RING + 0x06C5, // KIRGHIZ OE + 0x06C6, // OE + 0x06C7, // U + 0x06C8, // YU + 0x06C9, // KIRGHIZ YU + 0x06CA, // WAW WITH TWO DOTS ABOVE + 0x06CB, // VE + 0x06CF, // WAW WITH DOT ABOVE + 0x06EE, // DAL WITH INVERTED V + 0x06EF // REH WITH INVERTED V + }; + + private static boolean hasIsolateInitial ( int ch ) { + return Arrays.binarySearch ( isolatedInitials, ch ) >= 0; + } + + /** + * Ordered array of Unicode scalars designating those Arabic (Script) Letters + * which exhibit an isolated form in word final position. + */ + private static int[] isolatedFinals = { + 0x0621 // HAMZA + }; + + private static boolean hasIsolateFinal ( int ch ) { + return Arrays.binarySearch ( isolatedFinals, ch ) >= 0; + } + +} diff --git a/src/java/org/apache/fop/complexscripts/scripts/DefaultScriptProcessor.java b/src/java/org/apache/fop/complexscripts/scripts/DefaultScriptProcessor.java new file mode 100644 index 000000000..ff70e6a67 --- /dev/null +++ b/src/java/org/apache/fop/complexscripts/scripts/DefaultScriptProcessor.java @@ -0,0 +1,144 @@ +/* + * 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.complexscripts.scripts; + +import org.apache.fop.complexscripts.fonts.GlyphDefinitionTable; +import org.apache.fop.complexscripts.util.GlyphSequence; +import org.apache.fop.complexscripts.util.ScriptContextTester; + +// CSOFF: LineLengthCheck + +/** + * Default script processor, which enables default glyph composition/decomposition, common ligatures, localized forms + * and kerning. + * + * @author Glenn Adams + */ +public class DefaultScriptProcessor extends ScriptProcessor { + + /** features to use for substitutions */ + private static final String[] gsubFeatures = // CSOK: ConstantNameCheck + { + "ccmp", // glyph composition/decomposition + "liga", // common ligatures + "locl" // localized forms + }; + + /** features to use for positioning */ + private static final String[] gposFeatures = // CSOK: ConstantNameCheck + { + "kern", // kerning + "mark", // mark to base or ligature positioning + "mkmk" // mark to mark positioning + }; + + DefaultScriptProcessor ( String script ) { + super ( script ); + } + + @Override + /** {@inheritDoc} */ + public String[] getSubstitutionFeatures() { + return gsubFeatures; + } + + @Override + /** {@inheritDoc} */ + public ScriptContextTester getSubstitutionContextTester() { + return null; + } + + @Override + /** {@inheritDoc} */ + public String[] getPositioningFeatures() { + return gposFeatures; + } + + @Override + /** {@inheritDoc} */ + public ScriptContextTester getPositioningContextTester() { + return null; + } + + @Override + /** {@inheritDoc} */ + public GlyphSequence reorderCombiningMarks ( GlyphDefinitionTable gdef, GlyphSequence gs, int[][] gpa, String script, String language ) { + int ng = gs.getGlyphCount(); + int[] ga = gs.getGlyphArray ( false ); + int nm = 0; + // count combining marks + for ( int i = 0; i < ng; i++ ) { + int gid = ga [ i ]; + if ( gdef.isGlyphClass ( gid, GlyphDefinitionTable.GLYPH_CLASS_MARK ) ) { + nm++; + } + } + // only reorder if there is at least one mark and at least one non-mark glyph + if ( ( nm > 0 ) && ( ( ng - nm ) > 0 ) ) { + GlyphSequence.CharAssociation[] aa = gs.getAssociations ( 0, -1 ); + int[] nga = new int [ ng ]; + int[][] npa = ( gpa != null ) ? new int [ ng ][] : null; + GlyphSequence.CharAssociation[] naa = new GlyphSequence.CharAssociation [ ng ]; + int k = 0; + GlyphSequence.CharAssociation ba = null; + int bg = -1; + int[] bpa = null; + for ( int i = 0; i < ng; i++ ) { + int gid = ga [ i ]; + int[] pa = ( gpa != null ) ? gpa [ i ] : null; + GlyphSequence.CharAssociation ca = aa [ i ]; + if ( gdef.isGlyphClass ( gid, GlyphDefinitionTable.GLYPH_CLASS_MARK ) ) { + nga [ k ] = gid; naa [ k ] = ca; + if ( npa != null ) { + npa [ k ] = pa; + } + k++; + } else { + if ( bg != -1 ) { + nga [ k ] = bg; naa [ k ] = ba; + if ( npa != null ) { + npa [ k ] = bpa; + } + k++; + bg = -1; ba = null; bpa = null; + } + if ( bg == -1 ) { + bg = gid; ba = ca; bpa = pa; + } + } + } + if ( bg != -1 ) { + nga [ k ] = bg; naa [ k ] = ba; + if ( npa != null ) { + npa [ k ] = bpa; + } + k++; + } + assert k == ng; + if ( npa != null ) { + System.arraycopy ( npa, 0, gpa, 0, ng ); + } + return new GlyphSequence ( gs, null, nga, null, null, naa, null ); + } else { + return gs; + } + } + +} diff --git a/src/java/org/apache/fop/complexscripts/scripts/DevanagariScriptProcessor.java b/src/java/org/apache/fop/complexscripts/scripts/DevanagariScriptProcessor.java new file mode 100644 index 000000000..52f1d7284 --- /dev/null +++ b/src/java/org/apache/fop/complexscripts/scripts/DevanagariScriptProcessor.java @@ -0,0 +1,537 @@ +/* + * 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.complexscripts.scripts; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.apache.fop.complexscripts.util.GlyphSequence; +import org.apache.fop.complexscripts.util.ScriptContextTester; + +// CSOFF: AvoidNestedBlocksCheck +// CSOFF: NoWhitespaceAfterCheck +// CSOFF: WhitespaceAfter +// CSOFF: InnerAssignmentCheck +// CSOFF: SimplifyBooleanReturnCheck +// CSOFF: LineLengthCheck + +/** + *

The DevanagariScriptProcessor class implements a script processor for + * performing glyph substitution and positioning operations on content associated with the Devanagari script.

+ * @author Glenn Adams + */ +public class DevanagariScriptProcessor extends IndicScriptProcessor { + + /** logging instance */ + private static final Log log = LogFactory.getLog(DevanagariScriptProcessor.class); // CSOK: ConstantNameCheck + + DevanagariScriptProcessor ( String script ) { + super ( script ); + } + + @Override + protected Class getSyllabizerClass() { + return DevanagariSyllabizer.class; + } + + @Override + // find rightmost pre-base matra + protected int findPreBaseMatra ( GlyphSequence gs ) { + int ng = gs.getGlyphCount(); + int lk = -1; + for ( int i = ng; i > 0; i-- ) { + int k = i - 1; + if ( containsPreBaseMatra ( gs, k ) ) { + lk = k; + break; + } + } + return lk; + } + + @Override + // find leftmost pre-base matra target, starting from source + protected int findPreBaseMatraTarget ( GlyphSequence gs, int source ) { + int ng = gs.getGlyphCount(); + int lk = -1; + for ( int i = ( source < ng ) ? source : ng; i > 0; i-- ) { + int k = i - 1; + if ( containsConsonant ( gs, k ) ) { + if ( containsHalfConsonant ( gs, k ) ) { + lk = k; + } else if ( lk == -1 ) { + lk = k; + } else { + break; + } + } + } + return lk; + } + + private static boolean containsPreBaseMatra ( GlyphSequence gs, int k ) { + GlyphSequence.CharAssociation a = gs.getAssociation ( k ); + int[] ca = gs.getCharacterArray ( false ); + for ( int i = a.getStart(), e = a.getEnd(); i < e; i++ ) { + if ( isPreM ( ca [ i ] ) ) { + return true; + } + } + return false; + } + + private static boolean containsConsonant ( GlyphSequence gs, int k ) { + GlyphSequence.CharAssociation a = gs.getAssociation ( k ); + int[] ca = gs.getCharacterArray ( false ); + for ( int i = a.getStart(), e = a.getEnd(); i < e; i++ ) { + if ( isC ( ca [ i ] ) ) { + return true; + } + } + return false; + } + + private static boolean containsHalfConsonant ( GlyphSequence gs, int k ) { + Boolean half = (Boolean) gs.getAssociation ( k ) . getPredication ( "half" ); + return ( half != null ) ? half.booleanValue() : false; + } + + @Override + protected int findReph ( GlyphSequence gs ) { + int ng = gs.getGlyphCount(); + int li = -1; + for ( int i = 0; i < ng; i++ ) { + if ( containsReph ( gs, i ) ) { + li = i; + break; + } + } + return li; + } + + @Override + protected int findRephTarget ( GlyphSequence gs, int source ) { + int ng = gs.getGlyphCount(); + int c1 = -1; + int c2 = -1; + // first candidate target is after first non-half consonant + for ( int i = 0; i < ng; i++ ) { + if ( ( i != source ) && containsConsonant ( gs, i ) ) { + if ( ! containsHalfConsonant ( gs, i ) ) { + c1 = i + 1; + break; + } + } + } + // second candidate target is after last non-prebase matra after first candidate or before first syllable or vedic mark + for ( int i = ( c1 >= 0 ) ? c1 : 0; i < ng; i++ ) { + if ( containsMatra ( gs, i ) && ! containsPreBaseMatra ( gs, i ) ) { + c2 = i + 1; + } else if ( containsOtherMark ( gs, i ) ) { + c2 = i; + break; + } + } + if ( c2 >= 0 ) { + return c2; + } else if ( c1 >= 0 ) { + return c1; + } else { + return source; + } + } + + private static boolean containsReph ( GlyphSequence gs, int k ) { + Boolean rphf = (Boolean) gs.getAssociation ( k ) . getPredication ( "rphf" ); + return ( rphf != null ) ? rphf.booleanValue() : false; + } + + private static boolean containsMatra ( GlyphSequence gs, int k ) { + GlyphSequence.CharAssociation a = gs.getAssociation ( k ); + int[] ca = gs.getCharacterArray ( false ); + for ( int i = a.getStart(), e = a.getEnd(); i < e; i++ ) { + if ( isM ( ca [ i ] ) ) { + return true; + } + } + return false; + } + + private static boolean containsOtherMark ( GlyphSequence gs, int k ) { + GlyphSequence.CharAssociation a = gs.getAssociation ( k ); + int[] ca = gs.getCharacterArray ( false ); + for ( int i = a.getStart(), e = a.getEnd(); i < e; i++ ) { + switch ( typeOf ( ca [ i ] ) ) { + case C_T: // tone (e.g., udatta, anudatta) + case C_A: // accent (e.g., acute, grave) + case C_O: // other (e.g., candrabindu, anusvara, visarga, etc) + return true; + default: + break; + } + } + return false; + } + + private static class DevanagariSyllabizer extends DefaultSyllabizer { + DevanagariSyllabizer ( String script, String language ) { + super ( script, language ); + } + @Override + // | C ... + protected int findStartOfSyllable ( int[] ca, int s, int e ) { + if ( ( s < 0 ) || ( s >= e ) ) { + return -1; + } else { + while ( s < e ) { + int c = ca [ s ]; + if ( isC ( c ) ) { + break; + } else { + s++; + } + } + return s; + } + } + @Override + // D* L? | ... + protected int findEndOfSyllable ( int[] ca, int s, int e ) { + if ( ( s < 0 ) || ( s >= e ) ) { + return -1; + } else { + int nd = 0; + int nl = 0; + int i; + // consume dead consonants + while ( ( i = isDeadConsonant ( ca, s, e ) ) > s ) { + s = i; nd++; + } + // consume zero or one live consonant + if ( ( i = isLiveConsonant ( ca, s, e ) ) > s ) { + s = i; nl++; + } + return ( ( nd > 0 ) || ( nl > 0 ) ) ? s : -1; + } + } + // D := ( C N? H )? + private int isDeadConsonant ( int[] ca, int s, int e ) { + if ( s < 0 ) { + return -1; + } else { + int c, i = 0; + int nc = 0, nh = 0; + do { + // C + if ( ( s + i ) < e ) { + c = ca [ s + i ]; + if ( isC ( c ) ) { + i++; + nc++; + } else { + break; + } + } + // N? + if ( ( s + i ) < e ) { + c = ca [ s + 1 ]; + if ( isN ( c ) ) { + i++; + } + } + // H + if ( ( s + i ) < e ) { + c = ca [ s + i ]; + if ( isH ( c ) ) { + i++; + nh++; + } else { + break; + } + } + } while ( false ); + return ( nc > 0 ) && ( nh > 0 ) ? s + i : -1; + } + } + // L := ( (C|V) N? X* )?; where X = ( MATRA | ACCENT MARK | TONE MARK | OTHER MARK ) + private int isLiveConsonant ( int[] ca, int s, int e ) { + if ( s < 0 ) { + return -1; + } else { + int c, i = 0; + int nc = 0, nv = 0, nx = 0; + do { + // C + if ( ( s + i ) < e ) { + c = ca [ s + i ]; + if ( isC ( c ) ) { + i++; + nc++; + } else if ( isV ( c ) ) { + i++; + nv++; + } else { + break; + } + } + // N? + if ( ( s + i ) < e ) { + c = ca [ s + i ]; + if ( isN ( c ) ) { + i++; + } + } + // X* + while ( ( s + i ) < e ) { + c = ca [ s + i ]; + if ( isX ( c ) ) { + i++; + nx++; + } else { + break; + } + } + } while ( false ); + // if no X but has H, then ignore C|I + if ( nx == 0 ) { + if ( ( s + i ) < e ) { + c = ca [ s + i ]; + if ( isH ( c ) ) { + if ( nc > 0 ) { + nc--; + } else if ( nv > 0 ) { + nv--; + } + } + } + } + return ( ( nc > 0 ) || ( nv > 0 ) ) ? s + i : -1; + } + } + } + + // devanagari character types + static final short C_U = 0; // unassigned + static final short C_C = 1; // consonant + static final short C_V = 2; // vowel + static final short C_M = 3; // vowel sign (matra) + static final short C_S = 4; // symbol or sign + static final short C_T = 5; // tone mark + static final short C_A = 6; // accent mark + static final short C_P = 7; // punctuation + static final short C_D = 8; // digit + static final short C_H = 9; // halant (virama) + static final short C_O = 10; // other signs + static final short C_N = 0x0100; // nukta(ized) + static final short C_R = 0x0200; // reph(ized) + static final short C_PRE = 0x0400; // pre-base + static final short C_M_TYPE = 0x00FF; // type mask + static final short C_M_FLAGS = 0x7F00; // flag mask + // devanagari block range + static final int ccaStart = 0x0900; // first code point mapped by cca // CSOK: ConstantNameCheck + static final int ccaEnd = 0x0980; // last code point + 1 mapped by cca // CSOK: ConstantNameCheck + // devanagari character type lookups + static final short[] cca = { // CSOK: ConstantNameCheck + C_O, // 0x0900 // INVERTED CANDRABINDU + C_O, // 0x0901 // CANDRABINDU + C_O, // 0x0902 // ANUSVARA + C_O, // 0x0903 // VISARGA + C_V, // 0x0904 // SHORT A + C_V, // 0x0905 // A + C_V, // 0x0906 // AA + C_V, // 0x0907 // I + C_V, // 0x0908 // II + C_V, // 0x0909 // U + C_V, // 0x090A // UU + C_V, // 0x090B // VOCALIC R + C_V, // 0x090C // VOCALIC L + C_V, // 0x090D // CANDRA E + C_V, // 0x090E // SHORT E + C_V, // 0x090F // E + C_V, // 0x0910 // AI + C_V, // 0x0911 // CANDRA O + C_V, // 0x0912 // SHORT O + C_V, // 0x0913 // O + C_V, // 0x0914 // AU + C_C, // 0x0915 // KA + C_C, // 0x0916 // KHA + C_C, // 0x0917 // GA + C_C, // 0x0918 // GHA + C_C, // 0x0919 // NGA + C_C, // 0x091A // CA + C_C, // 0x091B // CHA + C_C, // 0x091C // JA + C_C, // 0x091D // JHA + C_C, // 0x091E // NYA + C_C, // 0x091F // TTA + C_C, // 0x0920 // TTHA + C_C, // 0x0921 // DDA + C_C, // 0x0922 // DDHA + C_C, // 0x0923 // NNA + C_C, // 0x0924 // TA + C_C, // 0x0925 // THA + C_C, // 0x0926 // DA + C_C, // 0x0927 // DHA + C_C, // 0x0928 // NA + C_C, // 0x0929 // NNNA + C_C, // 0x092A // PA + C_C, // 0x092B // PHA + C_C, // 0x092C // BA + C_C, // 0x092D // BHA + C_C, // 0x092E // MA + C_C, // 0x092F // YA + C_C|C_R, // 0x0930 // RA // CSOK: WhitespaceAround + C_C|C_R|C_N, // 0x0931 // RRA = 0930+093C // CSOK: WhitespaceAround + C_C, // 0x0932 // LA + C_C, // 0x0933 // LLA + C_C, // 0x0934 // LLLA + C_C, // 0x0935 // VA + C_C, // 0x0936 // SHA + C_C, // 0x0937 // SSA + C_C, // 0x0938 // SA + C_C, // 0x0939 // HA + C_M, // 0x093A // OE (KASHMIRI) + C_M, // 0x093B // OOE (KASHMIRI) + C_N, // 0x093C // NUKTA + C_S, // 0x093D // AVAGRAHA + C_M, // 0x093E // AA + C_M|C_PRE, // 0x093F // I // CSOK: WhitespaceAround + C_M, // 0x0940 // II + C_M, // 0x0941 // U + C_M, // 0x0942 // UU + C_M, // 0x0943 // VOCALIC R + C_M, // 0x0944 // VOCALIC RR + C_M, // 0x0945 // CANDRA E + C_M, // 0x0946 // SHORT E + C_M, // 0x0947 // E + C_M, // 0x0948 // AI + C_M, // 0x0949 // CANDRA O + C_M, // 0x094A // SHORT O + C_M, // 0x094B // O + C_M, // 0x094C // AU + C_H, // 0x094D // VIRAMA (HALANT) + C_M, // 0x094E // PRISHTHAMATRA E + C_M, // 0x094F // AW + C_S, // 0x0950 // OM + C_T, // 0x0951 // UDATTA + C_T, // 0x0952 // ANUDATTA + C_A, // 0x0953 // GRAVE + C_A, // 0x0954 // ACUTE + C_M, // 0x0955 // CANDRA LONG E + C_M, // 0x0956 // UE + C_M, // 0x0957 // UUE + C_C|C_N, // 0x0958 // QA // CSOK: WhitespaceAround + C_C|C_N, // 0x0959 // KHHA // CSOK: WhitespaceAround + C_C|C_N, // 0x095A // GHHA // CSOK: WhitespaceAround + C_C|C_N, // 0x095B // ZA // CSOK: WhitespaceAround + C_C|C_N, // 0x095C // DDDHA // CSOK: WhitespaceAround + C_C|C_N, // 0x095D // RHA // CSOK: WhitespaceAround + C_C|C_N, // 0x095E // FA // CSOK: WhitespaceAround + C_C|C_N, // 0x095F // YYA // CSOK: WhitespaceAround + C_V, // 0x0960 // VOCALIC RR + C_V, // 0x0961 // VOCALIC LL + C_M, // 0x0962 // VOCALIC RR + C_M, // 0x0963 // VOCALIC LL + C_P, // 0x0964 // DANDA + C_P, // 0x0965 // DOUBLE DANDA + C_D, // 0x0966 // ZERO + C_D, // 0x0967 // ONE + C_D, // 0x0968 // TWO + C_D, // 0x0969 // THREE + C_D, // 0x096A // FOUR + C_D, // 0x096B // FIVE + C_D, // 0x096C // SIX + C_D, // 0x096D // SEVEN + C_D, // 0x096E // EIGHT + C_D, // 0x096F // NINE + C_S, // 0x0970 // ABBREVIATION SIGN + C_S, // 0x0971 // HIGH SPACING DOT + C_V, // 0x0972 // CANDRA A (MARATHI) + C_V, // 0x0973 // OE (KASHMIRI) + C_V, // 0x0974 // OOE (KASHMIRI) + C_V, // 0x0975 // AW (KASHMIRI) + C_V, // 0x0976 // UE (KASHMIRI) + C_V, // 0x0977 // UUE (KASHMIRI) + C_U, // 0x0978 // UNASSIGNED + C_C, // 0x0979 // ZHA + C_C, // 0x097A // HEAVY YA + C_C, // 0x097B // GGAA (SINDHI) + C_C, // 0x097C // JJA (SINDHI) + C_C, // 0x097D // GLOTTAL STOP (LIMBU) + C_C, // 0x097E // DDDA (SINDHI) + C_C // 0x097F // BBA (SINDHI) + }; + static int typeOf(int c) { + if ( ( c >= ccaStart ) && ( c < ccaEnd ) ) { + return cca [ c - ccaStart ] & C_M_TYPE; + } else { + return C_U; + } + } + static boolean isType(int c, int t) { + return typeOf ( c ) == t; + } + static boolean hasFlag(int c, int f) { + if ( ( c >= ccaStart ) && ( c < ccaEnd ) ) { + return ( cca [ c - ccaStart ] & f ) == f; + } else { + return false; + } + } + static boolean isC(int c) { + return isType(c,C_C); + } + static boolean isR(int c) { + return isType(c,C_C) && hasR(c); + } + static boolean isV(int c) { + return isType(c,C_V); + } + static boolean isN(int c) { + return c == 0x093C; + } + static boolean isH(int c) { + return c == 0x094D; + } + static boolean isM(int c) { + return isType(c,C_M); + } + static boolean isPreM(int c) { + return isType(c,C_M) && hasFlag(c,C_PRE); + } + static boolean isX(int c) { + switch ( typeOf ( c ) ) { + case C_M: // matra (combining vowel) + case C_A: // accent mark + case C_T: // tone mark + case C_O: // other (modifying) mark + return true; + default: + return false; + } + } + static boolean hasR(int c) { + return hasFlag(c,C_R); + } + static boolean hasN(int c) { + return hasFlag(c,C_N); + } + +} diff --git a/src/java/org/apache/fop/complexscripts/scripts/GujaratiScriptProcessor.java b/src/java/org/apache/fop/complexscripts/scripts/GujaratiScriptProcessor.java new file mode 100644 index 000000000..4aec56a65 --- /dev/null +++ b/src/java/org/apache/fop/complexscripts/scripts/GujaratiScriptProcessor.java @@ -0,0 +1,537 @@ +/* + * 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.complexscripts.scripts; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.apache.fop.complexscripts.util.GlyphSequence; +import org.apache.fop.complexscripts.util.ScriptContextTester; + +// CSOFF: AvoidNestedBlocksCheck +// CSOFF: NoWhitespaceAfterCheck +// CSOFF: WhitespaceAfter +// CSOFF: InnerAssignmentCheck +// CSOFF: SimplifyBooleanReturnCheck +// CSOFF: LineLengthCheck + +/** + *

The GujaratiScriptProcessor class implements a script processor for + * performing glyph substitution and positioning operations on content associated with the Gujarati script.

+ * @author Glenn Adams + */ +public class GujaratiScriptProcessor extends IndicScriptProcessor { + + /** logging instance */ + private static final Log log = LogFactory.getLog(GujaratiScriptProcessor.class); // CSOK: ConstantNameCheck + + GujaratiScriptProcessor ( String script ) { + super ( script ); + } + + @Override + protected Class getSyllabizerClass() { + return GujaratiSyllabizer.class; + } + + @Override + // find rightmost pre-base matra + protected int findPreBaseMatra ( GlyphSequence gs ) { + int ng = gs.getGlyphCount(); + int lk = -1; + for ( int i = ng; i > 0; i-- ) { + int k = i - 1; + if ( containsPreBaseMatra ( gs, k ) ) { + lk = k; + break; + } + } + return lk; + } + + @Override + // find leftmost pre-base matra target, starting from source + protected int findPreBaseMatraTarget ( GlyphSequence gs, int source ) { + int ng = gs.getGlyphCount(); + int lk = -1; + for ( int i = ( source < ng ) ? source : ng; i > 0; i-- ) { + int k = i - 1; + if ( containsConsonant ( gs, k ) ) { + if ( containsHalfConsonant ( gs, k ) ) { + lk = k; + } else if ( lk == -1 ) { + lk = k; + } else { + break; + } + } + } + return lk; + } + + private static boolean containsPreBaseMatra ( GlyphSequence gs, int k ) { + GlyphSequence.CharAssociation a = gs.getAssociation ( k ); + int[] ca = gs.getCharacterArray ( false ); + for ( int i = a.getStart(), e = a.getEnd(); i < e; i++ ) { + if ( isPreM ( ca [ i ] ) ) { + return true; + } + } + return false; + } + + private static boolean containsConsonant ( GlyphSequence gs, int k ) { + GlyphSequence.CharAssociation a = gs.getAssociation ( k ); + int[] ca = gs.getCharacterArray ( false ); + for ( int i = a.getStart(), e = a.getEnd(); i < e; i++ ) { + if ( isC ( ca [ i ] ) ) { + return true; + } + } + return false; + } + + private static boolean containsHalfConsonant ( GlyphSequence gs, int k ) { + Boolean half = (Boolean) gs.getAssociation ( k ) . getPredication ( "half" ); + return ( half != null ) ? half.booleanValue() : false; + } + + @Override + protected int findReph ( GlyphSequence gs ) { + int ng = gs.getGlyphCount(); + int li = -1; + for ( int i = 0; i < ng; i++ ) { + if ( containsReph ( gs, i ) ) { + li = i; + break; + } + } + return li; + } + + @Override + protected int findRephTarget ( GlyphSequence gs, int source ) { + int ng = gs.getGlyphCount(); + int c1 = -1; + int c2 = -1; + // first candidate target is after first non-half consonant + for ( int i = 0; i < ng; i++ ) { + if ( ( i != source ) && containsConsonant ( gs, i ) ) { + if ( ! containsHalfConsonant ( gs, i ) ) { + c1 = i + 1; + break; + } + } + } + // second candidate target is after last non-prebase matra after first candidate or before first syllable or vedic mark + for ( int i = ( c1 >= 0 ) ? c1 : 0; i < ng; i++ ) { + if ( containsMatra ( gs, i ) && ! containsPreBaseMatra ( gs, i ) ) { + c2 = i + 1; + } else if ( containsOtherMark ( gs, i ) ) { + c2 = i; + break; + } + } + if ( c2 >= 0 ) { + return c2; + } else if ( c1 >= 0 ) { + return c1; + } else { + return source; + } + } + + private static boolean containsReph ( GlyphSequence gs, int k ) { + Boolean rphf = (Boolean) gs.getAssociation ( k ) . getPredication ( "rphf" ); + return ( rphf != null ) ? rphf.booleanValue() : false; + } + + private static boolean containsMatra ( GlyphSequence gs, int k ) { + GlyphSequence.CharAssociation a = gs.getAssociation ( k ); + int[] ca = gs.getCharacterArray ( false ); + for ( int i = a.getStart(), e = a.getEnd(); i < e; i++ ) { + if ( isM ( ca [ i ] ) ) { + return true; + } + } + return false; + } + + private static boolean containsOtherMark ( GlyphSequence gs, int k ) { + GlyphSequence.CharAssociation a = gs.getAssociation ( k ); + int[] ca = gs.getCharacterArray ( false ); + for ( int i = a.getStart(), e = a.getEnd(); i < e; i++ ) { + switch ( typeOf ( ca [ i ] ) ) { + case C_T: // tone (e.g., udatta, anudatta) + case C_A: // accent (e.g., acute, grave) + case C_O: // other (e.g., candrabindu, anusvara, visarga, etc) + return true; + default: + break; + } + } + return false; + } + + private static class GujaratiSyllabizer extends DefaultSyllabizer { + GujaratiSyllabizer ( String script, String language ) { + super ( script, language ); + } + @Override + // | C ... + protected int findStartOfSyllable ( int[] ca, int s, int e ) { + if ( ( s < 0 ) || ( s >= e ) ) { + return -1; + } else { + while ( s < e ) { + int c = ca [ s ]; + if ( isC ( c ) ) { + break; + } else { + s++; + } + } + return s; + } + } + @Override + // D* L? | ... + protected int findEndOfSyllable ( int[] ca, int s, int e ) { + if ( ( s < 0 ) || ( s >= e ) ) { + return -1; + } else { + int nd = 0; + int nl = 0; + int i; + // consume dead consonants + while ( ( i = isDeadConsonant ( ca, s, e ) ) > s ) { + s = i; nd++; + } + // consume zero or one live consonant + if ( ( i = isLiveConsonant ( ca, s, e ) ) > s ) { + s = i; nl++; + } + return ( ( nd > 0 ) || ( nl > 0 ) ) ? s : -1; + } + } + // D := ( C N? H )? + private int isDeadConsonant ( int[] ca, int s, int e ) { + if ( s < 0 ) { + return -1; + } else { + int c, i = 0; + int nc = 0, nh = 0; + do { + // C + if ( ( s + i ) < e ) { + c = ca [ s + i ]; + if ( isC ( c ) ) { + i++; + nc++; + } else { + break; + } + } + // N? + if ( ( s + i ) < e ) { + c = ca [ s + 1 ]; + if ( isN ( c ) ) { + i++; + } + } + // H + if ( ( s + i ) < e ) { + c = ca [ s + i ]; + if ( isH ( c ) ) { + i++; + nh++; + } else { + break; + } + } + } while ( false ); + return ( nc > 0 ) && ( nh > 0 ) ? s + i : -1; + } + } + // L := ( (C|V) N? X* )?; where X = ( MATRA | ACCENT MARK | TONE MARK | OTHER MARK ) + private int isLiveConsonant ( int[] ca, int s, int e ) { + if ( s < 0 ) { + return -1; + } else { + int c, i = 0; + int nc = 0, nv = 0, nx = 0; + do { + // C + if ( ( s + i ) < e ) { + c = ca [ s + i ]; + if ( isC ( c ) ) { + i++; + nc++; + } else if ( isV ( c ) ) { + i++; + nv++; + } else { + break; + } + } + // N? + if ( ( s + i ) < e ) { + c = ca [ s + i ]; + if ( isN ( c ) ) { + i++; + } + } + // X* + while ( ( s + i ) < e ) { + c = ca [ s + i ]; + if ( isX ( c ) ) { + i++; + nx++; + } else { + break; + } + } + } while ( false ); + // if no X but has H, then ignore C|I + if ( nx == 0 ) { + if ( ( s + i ) < e ) { + c = ca [ s + i ]; + if ( isH ( c ) ) { + if ( nc > 0 ) { + nc--; + } else if ( nv > 0 ) { + nv--; + } + } + } + } + return ( ( nc > 0 ) || ( nv > 0 ) ) ? s + i : -1; + } + } + } + + // gujarati character types + static final short C_U = 0; // unassigned + static final short C_C = 1; // consonant + static final short C_V = 2; // vowel + static final short C_M = 3; // vowel sign (matra) + static final short C_S = 4; // symbol or sign + static final short C_T = 5; // tone mark + static final short C_A = 6; // accent mark + static final short C_P = 7; // punctuation + static final short C_D = 8; // digit + static final short C_H = 9; // halant (virama) + static final short C_O = 10; // other signs + static final short C_N = 0x0100; // nukta(ized) + static final short C_R = 0x0200; // reph(ized) + static final short C_PRE = 0x0400; // pre-base + static final short C_M_TYPE = 0x00FF; // type mask + static final short C_M_FLAGS = 0x7F00; // flag mask + // gujarati block range + static final int ccaStart = 0x0A80; // first code point mapped by cca // CSOK: ConstantNameCheck + static final int ccaEnd = 0x0B00; // last code point + 1 mapped by cca // CSOK: ConstantNameCheck + // gujarati character type lookups + static final short[] cca = { // CSOK: ConstantNameCheck + C_U, // 0x0A80 // UNASSIGNED + C_O, // 0x0A81 // CANDRABINDU + C_O, // 0x0A82 // ANUSVARA + C_O, // 0x0A83 // VISARGA + C_U, // 0x0A84 // UNASSIGNED + C_V, // 0x0A85 // A + C_V, // 0x0A86 // AA + C_V, // 0x0A87 // I + C_V, // 0x0A88 // II + C_V, // 0x0A89 // U + C_V, // 0x0A8A // UU + C_V, // 0x0A8B // VOCALIC R + C_V, // 0x0A8C // VOCALIC L + C_V, // 0x0A8D // CANDRA E + C_U, // 0x0A8E // UNASSIGNED + C_V, // 0x0A8F // E + C_V, // 0x0A90 // AI + C_V, // 0x0A91 // CANDRA O + C_U, // 0x0A92 // UNASSIGNED + C_V, // 0x0A93 // O + C_V, // 0x0A94 // AU + C_C, // 0x0A95 // KA + C_C, // 0x0A96 // KHA + C_C, // 0x0A97 // GA + C_C, // 0x0A98 // GHA + C_C, // 0x0A99 // NGA + C_C, // 0x0A9A // CA + C_C, // 0x0A9B // CHA + C_C, // 0x0A9C // JA + C_C, // 0x0A9D // JHA + C_C, // 0x0A9E // NYA + C_C, // 0x0A9F // TTA + C_C, // 0x0AA0 // TTHA + C_C, // 0x0AA1 // DDA + C_C, // 0x0AA2 // DDHA + C_C, // 0x0AA3 // NNA + C_C, // 0x0AA4 // TA + C_C, // 0x0AA5 // THA + C_C, // 0x0AA6 // DA + C_C, // 0x0AA7 // DHA + C_C, // 0x0AA8 // NA + C_U, // 0x0AA9 // UNASSIGNED + C_C, // 0x0AAA // PA + C_C, // 0x0AAB // PHA + C_C, // 0x0AAC // BA + C_C, // 0x0AAD // BHA + C_C, // 0x0AAE // MA + C_C, // 0x0AAF // YA + C_C|C_R, // 0x0AB0 // RA // CSOK: WhitespaceAround + C_U, // 0x0AB1 // UNASSIGNED + C_C, // 0x0AB2 // LA + C_C, // 0x0AB3 // LLA + C_U, // 0x0AB4 // UNASSIGNED + C_C, // 0x0AB5 // VA + C_C, // 0x0AB6 // SHA + C_C, // 0x0AB7 // SSA + C_C, // 0x0AB8 // SA + C_C, // 0x0AB9 // HA + C_U, // 0x0ABA // UNASSIGNED + C_U, // 0x0ABB // UNASSIGNED + C_N, // 0x0ABC // NUKTA + C_S, // 0x0ABD // AVAGRAHA + C_M, // 0x0ABE // AA + C_M|C_PRE, // 0x0ABF // I // CSOK: WhitespaceAround + C_M, // 0x0AC0 // II + C_M, // 0x0AC1 // U + C_M, // 0x0AC2 // UU + C_M, // 0x0AC3 // VOCALIC R + C_M, // 0x0AC4 // VOCALIC RR + C_M, // 0x0AC5 // CANDRA E + C_U, // 0x0AC6 // UNASSIGNED + C_M, // 0x0AC7 // E + C_M, // 0x0AC8 // AI + C_M, // 0x0AC9 // CANDRA O + C_U, // 0x0ACA // UNASSIGNED + C_M, // 0x0ACB // O + C_M, // 0x0ACC // AU + C_H, // 0x0ACD // VIRAMA (HALANT) + C_U, // 0x0ACE // UNASSIGNED + C_U, // 0x0ACF // UNASSIGNED + C_S, // 0x0AD0 // OM + C_U, // 0x0AD1 // UNASSIGNED + C_U, // 0x0AD2 // UNASSIGNED + C_U, // 0x0AD3 // UNASSIGNED + C_U, // 0x0AD4 // UNASSIGNED + C_U, // 0x0AD5 // UNASSIGNED + C_U, // 0x0AD6 // UNASSIGNED + C_U, // 0x0AD7 // UNASSIGNED + C_U, // 0x0AD8 // UNASSIGNED + C_U, // 0x0AD9 // UNASSIGNED + C_U, // 0x0ADA // UNASSIGNED + C_U, // 0x0ADB // UNASSIGNED + C_U, // 0x0ADC // UNASSIGNED + C_U, // 0x0ADD // UNASSIGNED + C_U, // 0x0ADE // UNASSIGNED + C_U, // 0x0ADF // UNASSIGNED + C_V, // 0x0AE0 // VOCALIC RR + C_V, // 0x0AE1 // VOCALIC LL + C_M, // 0x0AE2 // VOCALIC L + C_M, // 0x0AE3 // VOCALIC LL + C_U, // 0x0AE4 // UNASSIGNED + C_U, // 0x0AE5 // UNASSIGNED + C_D, // 0x0AE6 // ZERO + C_D, // 0x0AE7 // ONE + C_D, // 0x0AE8 // TWO + C_D, // 0x0AE9 // THREE + C_D, // 0x0AEA // FOUR + C_D, // 0x0AEB // FIVE + C_D, // 0x0AEC // SIX + C_D, // 0x0AED // SEVEN + C_D, // 0x0AEE // EIGHT + C_D, // 0x0AEF // NINE + C_U, // 0x0AF0 // UNASSIGNED + C_S, // 0x0AF1 // RUPEE SIGN + C_U, // 0x0AF2 // UNASSIGNED + C_U, // 0x0AF3 // UNASSIGNED + C_U, // 0x0AF4 // UNASSIGNED + C_U, // 0x0AF5 // UNASSIGNED + C_U, // 0x0AF6 // UNASSIGNED + C_U, // 0x0AF7 // UNASSIGNED + C_U, // 0x0AF8 // UNASSIGNED + C_U, // 0x0AF9 // UNASSIGNED + C_U, // 0x0AFA // UNASSIGNED + C_U, // 0x0AFB // UNASSIGNED + C_U, // 0x0AFC // UNASSIGNED + C_U, // 0x0AFD // UNASSIGNED + C_U, // 0x0AFE // UNASSIGNED + C_U // 0x0AFF // UNASSIGNED + }; + static int typeOf(int c) { + if ( ( c >= ccaStart ) && ( c < ccaEnd ) ) { + return cca [ c - ccaStart ] & C_M_TYPE; + } else { + return C_U; + } + } + static boolean isType(int c, int t) { + return typeOf ( c ) == t; + } + static boolean hasFlag(int c, int f) { + if ( ( c >= ccaStart ) && ( c < ccaEnd ) ) { + return ( cca [ c - ccaStart ] & f ) == f; + } else { + return false; + } + } + static boolean isC(int c) { + return isType(c,C_C); + } + static boolean isR(int c) { + return isType(c,C_C) && hasR(c); + } + static boolean isV(int c) { + return isType(c,C_V); + } + static boolean isN(int c) { + return c == 0x0ABC; + } + static boolean isH(int c) { + return c == 0x0ACD; + } + static boolean isM(int c) { + return isType(c,C_M); + } + static boolean isPreM(int c) { + return isType(c,C_M) && hasFlag(c,C_PRE); + } + static boolean isX(int c) { + switch ( typeOf ( c ) ) { + case C_M: // matra (combining vowel) + case C_A: // accent mark + case C_T: // tone mark + case C_O: // other (modifying) mark + return true; + default: + return false; + } + } + static boolean hasR(int c) { + return hasFlag(c,C_R); + } + static boolean hasN(int c) { + return hasFlag(c,C_N); + } + +} diff --git a/src/java/org/apache/fop/complexscripts/scripts/GurmukhiScriptProcessor.java b/src/java/org/apache/fop/complexscripts/scripts/GurmukhiScriptProcessor.java new file mode 100644 index 000000000..1f1b56738 --- /dev/null +++ b/src/java/org/apache/fop/complexscripts/scripts/GurmukhiScriptProcessor.java @@ -0,0 +1,543 @@ +/* + * 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.complexscripts.scripts; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.apache.fop.complexscripts.fonts.GlyphDefinitionTable; +import org.apache.fop.complexscripts.util.GlyphSequence; +import org.apache.fop.complexscripts.util.ScriptContextTester; + +// CSOFF: AvoidNestedBlocksCheck +// CSOFF: NoWhitespaceAfterCheck +// CSOFF: WhitespaceAfter +// CSOFF: InnerAssignmentCheck +// CSOFF: SimplifyBooleanReturnCheck +// CSOFF: LineLengthCheck + +/** + *

The GurmukhiScriptProcessor class implements a script processor for + * performing glyph substitution and positioning operations on content associated with the Gurmukhi script.

+ * @author Glenn Adams + */ +public class GurmukhiScriptProcessor extends IndicScriptProcessor { + + /** logging instance */ + private static final Log log = LogFactory.getLog(GurmukhiScriptProcessor.class); // CSOK: ConstantNameCheck + + GurmukhiScriptProcessor ( String script ) { + super ( script ); + } + + @Override + protected Class getSyllabizerClass() { + return GurmukhiSyllabizer.class; + } + + @Override + // find rightmost pre-base matra + protected int findPreBaseMatra ( GlyphSequence gs ) { + int ng = gs.getGlyphCount(); + int lk = -1; + for ( int i = ng; i > 0; i-- ) { + int k = i - 1; + if ( containsPreBaseMatra ( gs, k ) ) { + lk = k; + break; + } + } + return lk; + } + + @Override + // find leftmost pre-base matra target, starting from source + protected int findPreBaseMatraTarget ( GlyphSequence gs, int source ) { + int ng = gs.getGlyphCount(); + int lk = -1; + for ( int i = ( source < ng ) ? source : ng; i > 0; i-- ) { + int k = i - 1; + if ( containsConsonant ( gs, k ) ) { + if ( containsHalfConsonant ( gs, k ) ) { + lk = k; + } else if ( lk == -1 ) { + lk = k; + } else { + break; + } + } + } + return lk; + } + + private static boolean containsPreBaseMatra ( GlyphSequence gs, int k ) { + GlyphSequence.CharAssociation a = gs.getAssociation ( k ); + int[] ca = gs.getCharacterArray ( false ); + for ( int i = a.getStart(), e = a.getEnd(); i < e; i++ ) { + if ( isPreM ( ca [ i ] ) ) { + return true; + } + } + return false; + } + + private static boolean containsConsonant ( GlyphSequence gs, int k ) { + GlyphSequence.CharAssociation a = gs.getAssociation ( k ); + int[] ca = gs.getCharacterArray ( false ); + for ( int i = a.getStart(), e = a.getEnd(); i < e; i++ ) { + if ( isC ( ca [ i ] ) ) { + return true; + } + } + return false; + } + + private static boolean containsHalfConsonant ( GlyphSequence gs, int k ) { + Boolean half = (Boolean) gs.getAssociation ( k ) . getPredication ( "half" ); + return ( half != null ) ? half.booleanValue() : false; + } + + @Override + protected int findReph ( GlyphSequence gs ) { + int ng = gs.getGlyphCount(); + int li = -1; + for ( int i = 0; i < ng; i++ ) { + if ( containsReph ( gs, i ) ) { + li = i; + break; + } + } + return li; + } + + @Override + protected int findRephTarget ( GlyphSequence gs, int source ) { + int ng = gs.getGlyphCount(); + int c1 = -1; + int c2 = -1; + // first candidate target is after first non-half consonant + for ( int i = 0; i < ng; i++ ) { + if ( ( i != source ) && containsConsonant ( gs, i ) ) { + if ( ! containsHalfConsonant ( gs, i ) ) { + c1 = i + 1; + break; + } + } + } + // second candidate target is after last non-prebase matra after first candidate or before first syllable or vedic mark + for ( int i = ( c1 >= 0 ) ? c1 : 0; i < ng; i++ ) { + if ( containsMatra ( gs, i ) && ! containsPreBaseMatra ( gs, i ) ) { + c2 = i + 1; + } else if ( containsOtherMark ( gs, i ) ) { + c2 = i; + break; + } + } + if ( c2 >= 0 ) { + return c2; + } else if ( c1 >= 0 ) { + return c1; + } else { + return source; + } + } + + private static boolean containsReph ( GlyphSequence gs, int k ) { + Boolean rphf = (Boolean) gs.getAssociation ( k ) . getPredication ( "rphf" ); + return ( rphf != null ) ? rphf.booleanValue() : false; + } + + private static boolean containsMatra ( GlyphSequence gs, int k ) { + GlyphSequence.CharAssociation a = gs.getAssociation ( k ); + int[] ca = gs.getCharacterArray ( false ); + for ( int i = a.getStart(), e = a.getEnd(); i < e; i++ ) { + if ( isM ( ca [ i ] ) ) { + return true; + } + } + return false; + } + + private static boolean containsOtherMark ( GlyphSequence gs, int k ) { + GlyphSequence.CharAssociation a = gs.getAssociation ( k ); + int[] ca = gs.getCharacterArray ( false ); + for ( int i = a.getStart(), e = a.getEnd(); i < e; i++ ) { + switch ( typeOf ( ca [ i ] ) ) { + case C_T: // tone (e.g., udatta, anudatta) + case C_A: // accent (e.g., acute, grave) + case C_O: // other (e.g., candrabindu, anusvara, visarga, etc) + return true; + default: + break; + } + } + return false; + } + + private static class GurmukhiSyllabizer extends DefaultSyllabizer { + GurmukhiSyllabizer ( String script, String language ) { + super ( script, language ); + } + @Override + // | C ... + protected int findStartOfSyllable ( int[] ca, int s, int e ) { + if ( ( s < 0 ) || ( s >= e ) ) { + return -1; + } else { + while ( s < e ) { + int c = ca [ s ]; + if ( isC ( c ) ) { + break; + } else { + s++; + } + } + return s; + } + } + @Override + // D* L? | ... + protected int findEndOfSyllable ( int[] ca, int s, int e ) { + if ( ( s < 0 ) || ( s >= e ) ) { + return -1; + } else { + int nd = 0; + int nl = 0; + int i; + // consume dead consonants + while ( ( i = isDeadConsonant ( ca, s, e ) ) > s ) { + s = i; nd++; + } + // consume zero or one live consonant + if ( ( i = isLiveConsonant ( ca, s, e ) ) > s ) { + s = i; nl++; + } + return ( ( nd > 0 ) || ( nl > 0 ) ) ? s : -1; + } + } + // D := ( C N? H )? + private int isDeadConsonant ( int[] ca, int s, int e ) { + if ( s < 0 ) { + return -1; + } else { + int c, i = 0; + int nc = 0, nh = 0; + do { + // C + if ( ( s + i ) < e ) { + c = ca [ s + i ]; + if ( isC ( c ) ) { + i++; + nc++; + } else { + break; + } + } + // N? + if ( ( s + i ) < e ) { + c = ca [ s + 1 ]; + if ( isN ( c ) ) { + i++; + } + } + // H + if ( ( s + i ) < e ) { + c = ca [ s + i ]; + if ( isH ( c ) ) { + i++; + nh++; + } else { + break; + } + } + } while ( false ); + return ( nc > 0 ) && ( nh > 0 ) ? s + i : -1; + } + } + // L := ( (C|V) N? X* )?; where X = ( MATRA | ACCENT MARK | TONE MARK | OTHER MARK ) + private int isLiveConsonant ( int[] ca, int s, int e ) { + if ( s < 0 ) { + return -1; + } else { + int c, i = 0; + int nc = 0, nv = 0, nx = 0; + do { + // C + if ( ( s + i ) < e ) { + c = ca [ s + i ]; + if ( isC ( c ) ) { + i++; + nc++; + } else if ( isV ( c ) ) { + i++; + nv++; + } else { + break; + } + } + // N? + if ( ( s + i ) < e ) { + c = ca [ s + i ]; + if ( isN ( c ) ) { + i++; + } + } + // X* + while ( ( s + i ) < e ) { + c = ca [ s + i ]; + if ( isX ( c ) ) { + i++; + nx++; + } else { + break; + } + } + } while ( false ); + // if no X but has H, then ignore C|I + if ( nx == 0 ) { + if ( ( s + i ) < e ) { + c = ca [ s + i ]; + if ( isH ( c ) ) { + if ( nc > 0 ) { + nc--; + } else if ( nv > 0 ) { + nv--; + } + } + } + } + return ( ( nc > 0 ) || ( nv > 0 ) ) ? s + i : -1; + } + } + } + + // gurmukhi character types + static final short C_U = 0; // unassigned + static final short C_C = 1; // consonant + static final short C_V = 2; // vowel + static final short C_M = 3; // vowel sign (matra) + static final short C_S = 4; // symbol or sign + static final short C_T = 5; // tone mark + static final short C_A = 6; // accent mark + static final short C_P = 7; // punctuation + static final short C_D = 8; // digit + static final short C_H = 9; // halant (virama) + static final short C_O = 10; // other signs + static final short C_N = 0x0100; // nukta(ized) + static final short C_R = 0x0200; // reph(ized) + static final short C_PRE = 0x0400; // pre-base + static final short C_M_TYPE = 0x00FF; // type mask + static final short C_M_FLAGS = 0x7F00; // flag mask + // gurmukhi block range + static final int ccaStart = 0x0A00; // first code point mapped by cca // CSOK: ConstantNameCheck + static final int ccaEnd = 0x0A80; // last code point + 1 mapped by cca // CSOK: ConstantNameCheck + // gurmukhi character type lookups + static final short[] cca = { // CSOK: ConstantNameCheck + C_U, // 0x0A00 // UNASSIGNED + C_O, // 0x0A01 // ADAK BINDI + C_O, // 0x0A02 // BINDI + C_O, // 0x0A03 // VISARGA + C_U, // 0x0A04 // UNASSIGNED + C_V, // 0x0A05 // A + C_V, // 0x0A06 // AA + C_V, // 0x0A07 // I + C_V, // 0x0A08 // II + C_V, // 0x0A09 // U + C_V, // 0x0A0A // UU + C_U, // 0x0A0B // UNASSIGNED + C_U, // 0x0A0C // UNASSIGNED + C_U, // 0x0A0D // UNASSIGNED + C_U, // 0x0A0E // UNASSIGNED + C_V, // 0x0A0F // E + C_V, // 0x0A10 // AI + C_U, // 0x0A11 // UNASSIGNED + C_U, // 0x0A12 // UNASSIGNED + C_V, // 0x0A13 // O + C_V, // 0x0A14 // AU + C_C, // 0x0A15 // KA + C_C, // 0x0A16 // KHA + C_C, // 0x0A17 // GA + C_C, // 0x0A18 // GHA + C_C, // 0x0A19 // NGA + C_C, // 0x0A1A // CA + C_C, // 0x0A1B // CHA + C_C, // 0x0A1C // JA + C_C, // 0x0A1D // JHA + C_C, // 0x0A1E // NYA + C_C, // 0x0A1F // TTA + C_C, // 0x0A20 // TTHA + C_C, // 0x0A21 // DDA + C_C, // 0x0A22 // DDHA + C_C, // 0x0A23 // NNA + C_C, // 0x0A24 // TA + C_C, // 0x0A25 // THA + C_C, // 0x0A26 // DA + C_C, // 0x0A27 // DHA + C_C, // 0x0A28 // NA + C_U, // 0x0A29 // UNASSIGNED + C_C, // 0x0A2A // PA + C_C, // 0x0A2B // PHA + C_C, // 0x0A2C // BA + C_C, // 0x0A2D // BHA + C_C, // 0x0A2E // MA + C_C, // 0x0A2F // YA + C_C|C_R, // 0x0A30 // RA // CSOK: WhitespaceAround + C_U, // 0x0A31 // UNASSIGNED + C_C, // 0x0A32 // LA + C_C, // 0x0A33 // LLA + C_U, // 0x0A34 // UNASSIGNED + C_C, // 0x0A35 // VA + C_C, // 0x0A36 // SHA + C_U, // 0x0A37 // UNASSIGNED + C_C, // 0x0A38 // SA + C_C, // 0x0A39 // HA + C_U, // 0x0A3A // UNASSIGNED + C_U, // 0x0A3B // UNASSIGNED + C_N, // 0x0A3C // NUKTA + C_U, // 0x0A3D // UNASSIGNED + C_M, // 0x0A3E // AA + C_M|C_PRE, // 0x0A3F // I // CSOK: WhitespaceAround + C_M, // 0x0A40 // II + C_M, // 0x0A41 // U + C_M, // 0x0A42 // UU + C_U, // 0x0A43 // UNASSIGNED + C_U, // 0x0A44 // UNASSIGNED + C_U, // 0x0A45 // UNASSIGNED + C_U, // 0x0A46 // UNASSIGNED + C_M, // 0x0A47 // EE + C_M, // 0x0A48 // AI + C_U, // 0x0A49 // UNASSIGNED + C_U, // 0x0A4A // UNASSIGNED + C_M, // 0x0A4B // OO + C_M, // 0x0A4C // AU + C_H, // 0x0A4D // VIRAMA (HALANT) + C_U, // 0x0A4E // UNASSIGNED + C_U, // 0x0A4F // UNASSIGNED + C_U, // 0x0A50 // UNASSIGNED + C_T, // 0x0A51 // UDATTA + C_U, // 0x0A52 // UNASSIGNED + C_U, // 0x0A53 // UNASSIGNED + C_U, // 0x0A54 // UNASSIGNED + C_U, // 0x0A55 // UNASSIGNED + C_U, // 0x0A56 // UNASSIGNED + C_U, // 0x0A57 // UNASSIGNED + C_U, // 0x0A58 // UNASSIGNED + C_C|C_N, // 0x0A59 // KHHA // CSOK: WhitespaceAround + C_C|C_N, // 0x0A5A // GHHA // CSOK: WhitespaceAround + C_C|C_N, // 0x0A5B // ZA // CSOK: WhitespaceAround + C_C|C_N, // 0x0A5C // RRA // CSOK: WhitespaceAround + C_U, // 0x0A5D // UNASSIGNED + C_C|C_N, // 0x0A5E // FA // CSOK: WhitespaceAround + C_U, // 0x0A5F // UNASSIGNED + C_U, // 0x0A60 // UNASSIGNED + C_U, // 0x0A61 // UNASSIGNED + C_U, // 0x0A62 // UNASSIGNED + C_U, // 0x0A63 // UNASSIGNED + C_U, // 0x0A64 // UNASSIGNED + C_U, // 0x0A65 // UNASSIGNED + C_D, // 0x0A66 // ZERO + C_D, // 0x0A67 // ONE + C_D, // 0x0A68 // TWO + C_D, // 0x0A69 // THREE + C_D, // 0x0A6A // FOUR + C_D, // 0x0A6B // FIVE + C_D, // 0x0A6C // SIX + C_D, // 0x0A6D // SEVEN + C_D, // 0x0A6E // EIGHT + C_D, // 0x0A6F // NINE + C_O, // 0x0A70 // TIPPI + C_O, // 0x0A71 // ADDAK + C_V, // 0x0A72 // IRI + C_V, // 0x0A73 // URA + C_S, // 0x0A74 // EK ONKAR + C_O, // 0x0A75 // YAKASH + C_U, // 0x0A76 // UNASSIGNED + C_U, // 0x0A77 // UNASSIGNED + C_U, // 0x0A78 // UNASSIGNED + C_U, // 0x0A79 // UNASSIGNED + C_U, // 0x0A7A // UNASSIGNED + C_U, // 0x0A7B // UNASSIGNED + C_U, // 0x0A7C // UNASSIGNED + C_U, // 0x0A7D // UNASSIGNED + C_U, // 0x0A7E // UNASSIGNED + C_U // 0x0A7F // UNASSIGNED + }; + static int typeOf(int c) { + if ( ( c >= ccaStart ) && ( c < ccaEnd ) ) { + return cca [ c - ccaStart ] & C_M_TYPE; + } else { + return C_U; + } + } + static boolean isType(int c, int t) { + return typeOf ( c ) == t; + } + static boolean hasFlag(int c, int f) { + if ( ( c >= ccaStart ) && ( c < ccaEnd ) ) { + return ( cca [ c - ccaStart ] & f ) == f; + } else { + return false; + } + } + static boolean isC(int c) { + return isType(c,C_C); + } + static boolean isR(int c) { + return isType(c,C_C) && hasR(c); + } + static boolean isV(int c) { + return isType(c,C_V); + } + static boolean isN(int c) { + return c == 0x0A3C; + } + static boolean isH(int c) { + return c == 0x0A4D; + } + static boolean isM(int c) { + return isType(c,C_M); + } + static boolean isPreM(int c) { + return isType(c,C_M) && hasFlag(c,C_PRE); + } + static boolean isX(int c) { + switch ( typeOf ( c ) ) { + case C_M: // matra (combining vowel) + case C_A: // accent mark + case C_T: // tone mark + case C_O: // other (modifying) mark + return true; + default: + return false; + } + } + static boolean hasR(int c) { + return hasFlag(c,C_R); + } + static boolean hasN(int c) { + return hasFlag(c,C_N); + } + + @Override + public GlyphSequence reorderCombiningMarks ( GlyphDefinitionTable gdef, GlyphSequence gs, int[][] gpa, String script, String language ) { + return super.reorderCombiningMarks ( gdef, gs, gpa, script, language ); + } + +} diff --git a/src/java/org/apache/fop/complexscripts/scripts/IndicScriptProcessor.java b/src/java/org/apache/fop/complexscripts/scripts/IndicScriptProcessor.java new file mode 100644 index 000000000..92ed31501 --- /dev/null +++ b/src/java/org/apache/fop/complexscripts/scripts/IndicScriptProcessor.java @@ -0,0 +1,589 @@ +/* + * 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.complexscripts.scripts; + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.Vector; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.apache.fop.complexscripts.fonts.GlyphTable; +import org.apache.fop.complexscripts.util.CharScript; +import org.apache.fop.complexscripts.util.GlyphContextTester; +import org.apache.fop.complexscripts.util.GlyphSequence; +import org.apache.fop.complexscripts.util.ScriptContextTester; + +// CSOFF: AvoidNestedBlocksCheck +// CSOFF: NoWhitespaceAfterCheck +// CSOFF: InnerAssignmentCheck +// CSOFF: SimplifyBooleanReturnCheck +// CSOFF: EmptyForIteratorPadCheck +// CSOFF: WhitespaceAfterCheck +// CSOFF: ParameterNumberCheck +// CSOFF: LineLengthCheck + +/** + *

The IndicScriptProcessor class implements a script processor for + * performing glyph substitution and positioning operations on content associated with the Indic script.

+ * @author Glenn Adams + */ +public class IndicScriptProcessor extends DefaultScriptProcessor { + + /** logging instance */ + private static final Log log = LogFactory.getLog(IndicScriptProcessor.class); // CSOK: ConstantNameCheck + + /** required features to use for substitutions */ + private static final String[] gsubReqFeatures = // CSOK: ConstantNameCheck + { + "abvf", // above base forms + "abvs", // above base substitutions + "akhn", // akhand + "blwf", // below base forms + "blws", // below base substitutions + "ccmp", // glyph composition/decomposition + "cjct", // conjunct forms + "clig", // contextual ligatures + "half", // half forms + "haln", // halant forms + "locl", // localized forms + "nukt", // nukta forms + "pref", // pre-base forms + "pres", // pre-base substitutions + "pstf", // post-base forms + "psts", // post-base substitutions + "rkrf", // rakar forms + "rphf", // reph form + "vatu" // vattu variants + }; + + /** optional features to use for substitutions */ + private static final String[] gsubOptFeatures = // CSOK: ConstantNameCheck + { + "afrc", // alternative fractions + "calt", // contextual alternatives + "dlig" // discretionary ligatures + }; + + /** required features to use for positioning */ + private static final String[] gposReqFeatures = // CSOK: ConstantNameCheck + { + "abvm", // above base marks + "blwm", // below base marks + "dist", // distance (adjustment) + "kern" // kerning + }; + + /** required features to use for positioning */ + private static final String[] gposOptFeatures = // CSOK: ConstantNameCheck + { + }; + + private static class SubstitutionScriptContextTester implements ScriptContextTester { + private static Map/**/ testerMap = new HashMap/**/(); + public GlyphContextTester getTester ( String feature ) { + return (GlyphContextTester) testerMap.get ( feature ); + } + } + + private static class PositioningScriptContextTester implements ScriptContextTester { + private static Map/**/ testerMap = new HashMap/**/(); + public GlyphContextTester getTester ( String feature ) { + return (GlyphContextTester) testerMap.get ( feature ); + } + } + + /** + * Make script specific flavor of Indic script processor. + * @param script tag + * @return script processor instance + */ + public static ScriptProcessor makeProcessor ( String script ) { + switch ( CharScript.scriptCodeFromTag ( script ) ) { + case CharScript.SCRIPT_DEVANAGARI: + case CharScript.SCRIPT_DEVANAGARI_2: + return new DevanagariScriptProcessor ( script ); + case CharScript.SCRIPT_GUJARATI: + case CharScript.SCRIPT_GUJARATI_2: + return new GujaratiScriptProcessor ( script ); + case CharScript.SCRIPT_GURMUKHI: + case CharScript.SCRIPT_GURMUKHI_2: + return new GurmukhiScriptProcessor ( script ); + // [TBD] implement other script processors + default: + return new IndicScriptProcessor ( script ); + } + } + + private final ScriptContextTester subContextTester; + private final ScriptContextTester posContextTester; + + IndicScriptProcessor ( String script ) { + super ( script ); + this.subContextTester = new SubstitutionScriptContextTester(); + this.posContextTester = new PositioningScriptContextTester(); + } + + /** {@inheritDoc} */ + public String[] getSubstitutionFeatures() { + return gsubReqFeatures; + } + + /** {@inheritDoc} */ + public String[] getOptionalSubstitutionFeatures() { + return gsubOptFeatures; + } + + /** {@inheritDoc} */ + public ScriptContextTester getSubstitutionContextTester() { + return subContextTester; + } + + /** {@inheritDoc} */ + public String[] getPositioningFeatures() { + return gposReqFeatures; + } + + /** {@inheritDoc} */ + public String[] getOptionalPositioningFeatures() { + return gposOptFeatures; + } + + /** {@inheritDoc} */ + public ScriptContextTester getPositioningContextTester() { + return posContextTester; + } + + /** {@inheritDoc} */ + @Override + public GlyphSequence substitute ( GlyphSequence gs, String script, String language, GlyphTable.UseSpec[] usa, ScriptContextTester sct ) { + assert usa != null; + // 1. syllabize + GlyphSequence[] sa = syllabize ( gs, script, language ); + // 2. process each syllable + for ( int i = 0, n = sa.length; i < n; i++ ) { + GlyphSequence s = sa [ i ]; + // apply basic shaping subs + for ( int j = 0, m = usa.length; j < m; j++ ) { + GlyphTable.UseSpec us = usa [ j ]; + if ( isBasicShapingUse ( us ) ) { + s.setPredications ( true ); + s = us.substitute ( s, script, language, sct ); + } + } + // reorder pre-base matra + s = reorderPreBaseMatra ( s ); + // reorder reph + s = reorderReph ( s ); + // apply presentation subs + for ( int j = 0, m = usa.length; j < m; j++ ) { + GlyphTable.UseSpec us = usa [ j ]; + if ( isPresentationUse ( us ) ) { + s.setPredications ( true ); + s = us.substitute ( s, script, language, sct ); + } + } + // record result + sa [ i ] = s; + } + // 3. return reassembled substituted syllables + return unsyllabize ( gs, sa ); + } + + /** + * Get script specific syllabizer class. + * @return a syllabizer class object or null + */ + protected Class getSyllabizerClass() { + return null; + } + + private GlyphSequence[] syllabize ( GlyphSequence gs, String script, String language ) { + return Syllabizer.getSyllabizer ( script, language, getSyllabizerClass() ) . syllabize ( gs ); + } + + private GlyphSequence unsyllabize ( GlyphSequence gs, GlyphSequence[] sa ) { + return GlyphSequence.join ( gs, sa ); + } + + private static Set basicShapingFeatures; + private static final String[] basicShapingFeatureStrings = { // CSOK: ConstantNameCheck + "abvf", + "akhn", + "blwf", + "cjct", + "half", + "locl", + "nukt", + "pref", + "pstf", + "rkrf", + "rphf", + "vatu", + }; + static { + basicShapingFeatures = new HashSet(); + for ( String s : basicShapingFeatureStrings ) { + basicShapingFeatures.add ( s ); + } + } + private boolean isBasicShapingUse ( GlyphTable.UseSpec us ) { + assert us != null; + if ( basicShapingFeatures != null ) { + return basicShapingFeatures.contains ( us.getFeature() ); + } else { + return false; + } + } + + private static Set presentationFeatures; + private static final String[] presentationFeatureStrings = { // CSOK: ConstantNameCheck + "abvs", + "blws", + "calt", + "haln", + "pres", + "psts", + }; + static { + presentationFeatures = new HashSet(); + for ( String s : presentationFeatureStrings ) { + presentationFeatures.add ( s ); + } + } + private boolean isPresentationUse ( GlyphTable.UseSpec us ) { + assert us != null; + if ( presentationFeatures != null ) { + return presentationFeatures.contains ( us.getFeature() ); + } else { + return false; + } + } + + private GlyphSequence reorderPreBaseMatra ( GlyphSequence gs ) { + int source; + if ( ( source = findPreBaseMatra ( gs ) ) >= 0 ) { + int target; + if ( ( target = findPreBaseMatraTarget ( gs, source ) ) >= 0 ) { + if ( target != source ) { + gs = reorder ( gs, source, target ); + } + } + } + return gs; + } + + /** + * Find pre-base matra in sequence. + * @param gs input sequence + * @return index of pre-base matra or -1 if not found + */ + protected int findPreBaseMatra ( GlyphSequence gs ) { + return -1; + } + + /** + * Find pre-base matra target in sequence. + * @param gs input sequence + * @param source index of pre-base matra + * @return index of pre-base matra target or -1 + */ + protected int findPreBaseMatraTarget ( GlyphSequence gs, int source ) { + return -1; + } + + private GlyphSequence reorderReph ( GlyphSequence gs ) { + int source; + if ( ( source = findReph ( gs ) ) >= 0 ) { + int target; + if ( ( target = findRephTarget ( gs, source ) ) >= 0 ) { + if ( target != source ) { + gs = reorder ( gs, source, target ); + } + } + } + return gs; + } + + /** + * Find reph in sequence. + * @param gs input sequence + * @return index of reph or -1 if not found + */ + protected int findReph ( GlyphSequence gs ) { + return -1; + } + + /** + * Find reph target in sequence. + * @param gs input sequence + * @param source index of reph + * @return index of reph target or -1 + */ + protected int findRephTarget ( GlyphSequence gs, int source ) { + return -1; + } + + private GlyphSequence reorder ( GlyphSequence gs, int source, int target ) { + return GlyphSequence.reorder ( gs, source, 1, target ); + } + + /** {@inheritDoc} */ + @Override + public boolean position ( GlyphSequence gs, String script, String language, int fontSize, GlyphTable.UseSpec[] usa, int[] widths, int[][] adjustments, ScriptContextTester sct ) { + boolean adjusted = super.position ( gs, script, language, fontSize, usa, widths, adjustments, sct ); + return adjusted; + } + + /** Abstract syllabizer. */ + protected abstract static class Syllabizer { + private String script; + private String language; + Syllabizer ( String script, String language ) { + this.script = script; + this.language = language; + } + /** + * Subdivide glyph sequence GS into syllabic segments each represented by a distinct + * output glyph sequence. + * @param gs input glyph sequence + * @return segmented syllabic glyph sequences + */ + abstract GlyphSequence[] syllabize ( GlyphSequence gs ); + /** {@inheritDoc} */ + public int hashCode() { + int hc = 0; + hc = 7 * hc + ( hc ^ script.hashCode() ); + hc = 11 * hc + ( hc ^ language.hashCode() ); + return hc; + } + /** {@inheritDoc} */ + public boolean equals ( Object o ) { + if ( o instanceof Syllabizer ) { + Syllabizer s = (Syllabizer) o; + if ( ! s.script.equals ( script ) ) { + return false; + } else if ( ! s.language.equals ( language ) ) { + return false; + } else { + return true; + } + } else { + return false; + } + } + /** {@inheritDoc} */ + public int compareTo ( Object o ) { + int d; + if ( o instanceof Syllabizer ) { + Syllabizer s = (Syllabizer) o; + if ( ( d = script.compareTo ( s.script ) ) == 0 ) { + d = language.compareTo ( s.language ); + } + } else { + d = -1; + } + return d; + } + private static Map syllabizers = new HashMap(); + static Syllabizer getSyllabizer ( String script, String language, Class syllabizerClass ) { + String sid = makeSyllabizerId ( script, language ); + Syllabizer s = syllabizers.get ( sid ); + if ( s == null ) { + if ( ( s = makeSyllabizer ( script, language, syllabizerClass ) ) == null ) { + s = new DefaultSyllabizer ( script, language ); + } + syllabizers.put ( sid, s ); + } + return s; + } + static String makeSyllabizerId ( String script, String language ) { + return script + ":" + language; + } + static Syllabizer makeSyllabizer ( String script, String language, Class syllabizerClass ) { + Syllabizer s; + try { + Constructor cf = syllabizerClass.getDeclaredConstructor ( new Class[] { String.class, String.class } ); + s = (Syllabizer) cf.newInstance ( script, language ); + } catch ( NoSuchMethodException e ) { + s = null; + } catch ( InstantiationException e ) { + s = null; + } catch ( IllegalAccessException e ) { + s = null; + } catch ( InvocationTargetException e ) { + s = null; + } + return s; + } + } + + /** Default syllabizer. */ + protected static class DefaultSyllabizer extends Syllabizer { + DefaultSyllabizer ( String script, String language ) { + super ( script, language ); + } + /** {@inheritDoc} */ + @Override + GlyphSequence[] syllabize ( GlyphSequence gs ) { + int[] ca = gs.getCharacterArray ( false ); + int nc = gs.getCharacterCount(); + if ( nc == 0 ) { + return new GlyphSequence[] { gs }; + } else { + return segmentize ( gs, segmentize ( ca, nc ) ); + } + } + /** + * Construct array of segements from original character array (associated with original glyph sequence) + * @param ca input character sequence + * @param nc number of characters in sequence + * @return array of syllable segments + */ + protected Segment[] segmentize ( int[] ca, int nc ) { + Vector sv = new Vector ( nc ); + for ( int s = 0, e = nc; s < e; ) { + int i; + if ( ( i = findStartOfSyllable ( ca, s, e ) ) > s ) { + // from s to i is non-syllable segment + sv.add ( new Segment ( s, i, Segment.OTHER ) ); + s = i; // move s to start of syllable + } else if ( i > s ) { + // from s to e is non-syllable segment + sv.add ( new Segment ( s, e, Segment.OTHER ) ); + s = e; // move s to end of input sequence + } + if ( ( i = findEndOfSyllable ( ca, s, e ) ) > s ) { + // from s to i is syllable segment + sv.add ( new Segment ( s, i, Segment.SYLLABLE ) ); + s = i; // move s to end of syllable + } else { + // from s to e is non-syllable segment + sv.add ( new Segment ( s, e, Segment.OTHER ) ); + s = e; // move s to end of input sequence + } + } + return sv.toArray ( new Segment [ sv.size() ] ); + } + /** + * Construct array of glyph sequences from original glyph sequence and segment array. + * @param gs original input glyph sequence + * @param sa segment array + * @return array of glyph sequences each belonging to an (ordered) segment in SA + */ + protected GlyphSequence[] segmentize ( GlyphSequence gs, Segment[] sa ) { + int ng = gs.getGlyphCount(); + int[] ga = gs.getGlyphArray ( false ); + GlyphSequence.CharAssociation[] aa = gs.getAssociations ( 0, -1 ); + Vector nsv = new Vector(); + for ( int i = 0, ns = sa.length; i < ns; i++ ) { + Segment s = sa [ i ]; + Vector ngv = new Vector ( ng ); + Vector nav = new Vector ( ng ); + for ( int j = 0; j < ng; j++ ) { + GlyphSequence.CharAssociation ca = aa [ j ]; + if ( ca.contained ( s.getOffset(), s.getCount() ) ) { + ngv.add ( ga [ j ] ); + nav.add ( ca ); + } + } + if ( ngv.size() > 0 ) { + nsv.add ( new GlyphSequence ( gs, null, toIntArray ( ngv ), null, null, nav.toArray ( new GlyphSequence.CharAssociation [ nav.size() ] ), null ) ); + } + } + if ( nsv.size() > 0 ) { + return nsv.toArray ( new GlyphSequence [ nsv.size() ] ); + } else { + return new GlyphSequence[] { gs }; + } + } + /** + * Find start of syllable in character array, starting at S, ending at E. + * @param ca character array + * @param s start index + * @param e end index + * @return index of start or E if no start found + */ + protected int findStartOfSyllable ( int[] ca, int s, int e ) { + return e; + } + /** + * Find end of syllable in character array, starting at S, ending at E. + * @param ca character array + * @param s start index + * @param e end index + * @return index of start or S if no end found + */ + protected int findEndOfSyllable ( int[] ca, int s, int e ) { + return s; + } + private static int[] toIntArray ( Vector iv ) { + int ni = iv.size(); + int[] ia = new int [ iv.size() ]; + for ( int i = 0, n = ni; i < n; i++ ) { + ia [ i ] = (int) iv.get ( i ); + } + return ia; + } + } + + /** Syllabic segment. */ + protected static class Segment { + + static final int OTHER = 0; // other (non-syllable) characters + static final int SYLLABLE = 1; // (orthographic) syllable + + private int start; + private int end; + private int type; + + Segment ( int start, int end, int type ) { + this.start = start; + this.end = end; + this.type = type; + } + + int getStart() { + return start; + } + + int getEnd() { + return end; + } + + int getOffset() { + return start; + } + + int getCount() { + return end - start; + } + + int getType() { + return type; + } + } +} diff --git a/src/java/org/apache/fop/complexscripts/scripts/ScriptProcessor.java b/src/java/org/apache/fop/complexscripts/scripts/ScriptProcessor.java new file mode 100644 index 000000000..4f6feffee --- /dev/null +++ b/src/java/org/apache/fop/complexscripts/scripts/ScriptProcessor.java @@ -0,0 +1,234 @@ +/* + * 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.complexscripts.scripts; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.fop.complexscripts.fonts.GlyphDefinitionTable; +import org.apache.fop.complexscripts.fonts.GlyphPositioningTable; +import org.apache.fop.complexscripts.fonts.GlyphSubstitutionTable; +import org.apache.fop.complexscripts.fonts.GlyphTable; +import org.apache.fop.complexscripts.util.CharScript; +import org.apache.fop.complexscripts.util.GlyphSequence; +import org.apache.fop.complexscripts.util.ScriptContextTester; + +// CSOFF: InnerAssignmentCheck +// CSOFF: LineLengthCheck +// CSOFF: ParameterNumberCheck + +/** + * Abstract script processor base class for which an implementation of the substitution and positioning methods + * must be supplied. + * @author Glenn Adams + */ +public abstract class ScriptProcessor { + + private final String script; + + private static Map processors = new HashMap(); + + /** + * Instantiate a script processor. + * @param script a script identifier + */ + protected ScriptProcessor ( String script ) { + if ( ( script == null ) || ( script.length() == 0 ) ) { + throw new IllegalArgumentException ( "script must be non-empty string" ); + } else { + this.script = script; + } + } + + /** @return script identifier */ + public final String getScript() { + return script; + } + + /** + * Obtain script specific required substitution features. + * @return array of suppported substitution features or null + */ + public abstract String[] getSubstitutionFeatures(); + + /** + * Obtain script specific optional substitution features. + * @return array of suppported substitution features or null + */ + public String[] getOptionalSubstitutionFeatures() { + return new String[0]; + } + + /** + * Obtain script specific substitution context tester. + * @return substitution context tester or null + */ + public abstract ScriptContextTester getSubstitutionContextTester(); + + /** + * Perform substitution processing using a specific set of lookup tables. + * @param gsub the glyph substitution table that applies + * @param gs an input glyph sequence + * @param script a script identifier + * @param language a language identifier + * @param lookups a mapping from lookup specifications to glyph subtables to use for substitution processing + * @return the substituted (output) glyph sequence + */ + public final GlyphSequence substitute ( GlyphSubstitutionTable gsub, GlyphSequence gs, String script, String language, Map/*>>*/ lookups ) { + return substitute ( gs, script, language, assembleLookups ( gsub, getSubstitutionFeatures(), lookups ), getSubstitutionContextTester() ); + } + + /** + * Perform substitution processing using a specific set of ordered glyph table use specifications. + * @param gs an input glyph sequence + * @param script a script identifier + * @param language a language identifier + * @param usa an ordered array of glyph table use specs + * @param sct a script specific context tester (or null) + * @return the substituted (output) glyph sequence + */ + public GlyphSequence substitute ( GlyphSequence gs, String script, String language, GlyphTable.UseSpec[] usa, ScriptContextTester sct ) { + assert usa != null; + for ( int i = 0, n = usa.length; i < n; i++ ) { + GlyphTable.UseSpec us = usa [ i ]; + gs = us.substitute ( gs, script, language, sct ); + } + return gs; + } + + /** + * Reorder combining marks in glyph sequence so that they precede (within the sequence) the base + * character to which they are applied. N.B. In the case of RTL segments, marks are not reordered by this, + * method since when the segment is reversed by BIDI processing, marks are automatically reordered to precede + * their base glyph. + * @param gdef the glyph definition table that applies + * @param gs an input glyph sequence + * @param gpa associated glyph position adjustments (also reordered) + * @param script a script identifier + * @param language a language identifier + * @return the reordered (output) glyph sequence + */ + public GlyphSequence reorderCombiningMarks ( GlyphDefinitionTable gdef, GlyphSequence gs, int[][] gpa, String script, String language ) { + return gs; + } + + /** + * Obtain script specific required positioning features. + * @return array of suppported positioning features or null + */ + public abstract String[] getPositioningFeatures(); + + /** + * Obtain script specific optional positioning features. + * @return array of suppported positioning features or null + */ + public String[] getOptionalPositioningFeatures() { + return new String[0]; + } + + /** + * Obtain script specific positioning context tester. + * @return positioning context tester or null + */ + public abstract ScriptContextTester getPositioningContextTester(); + + /** + * Perform positioning processing using a specific set of lookup tables. + * @param gpos the glyph positioning table that applies + * @param gs an input glyph sequence + * @param script a script identifier + * @param language a language identifier + * @param fontSize size in device units + * @param lookups a mapping from lookup specifications to glyph subtables to use for positioning processing + * @param widths array of default advancements for each glyph + * @param adjustments accumulated adjustments array (sequence) of 4-tuples of placement [PX,PY] and advance [AX,AY] adjustments, in that order, + * with one 4-tuple for each element of glyph sequence + * @return true if some adjustment is not zero; otherwise, false + */ + public final boolean position ( GlyphPositioningTable gpos, GlyphSequence gs, String script, String language, int fontSize, Map/*>*/ lookups, int[] widths, int[][] adjustments ) { + return position ( gs, script, language, fontSize, assembleLookups ( gpos, getPositioningFeatures(), lookups ), widths, adjustments, getPositioningContextTester() ); + } + + /** + * Perform positioning processing using a specific set of ordered glyph table use specifications. + * @param gs an input glyph sequence + * @param script a script identifier + * @param language a language identifier + * @param fontSize size in device units + * @param usa an ordered array of glyph table use specs + * @param widths array of default advancements for each glyph in font + * @param adjustments accumulated adjustments array (sequence) of 4-tuples of placement [PX,PY] and advance [AX,AY] adjustments, in that order, + * with one 4-tuple for each element of glyph sequence + * @param sct a script specific context tester (or null) + * @return true if some adjustment is not zero; otherwise, false + */ + public boolean position ( GlyphSequence gs, String script, String language, int fontSize, GlyphTable.UseSpec[] usa, int[] widths, int[][] adjustments, ScriptContextTester sct ) { + assert usa != null; + boolean adjusted = false; + for ( int i = 0, n = usa.length; i < n; i++ ) { + GlyphTable.UseSpec us = usa [ i ]; + if ( us.position ( gs, script, language, fontSize, widths, adjustments, sct ) ) { + adjusted = true; + } + } + return adjusted; + } + + /** + * Assemble ordered array of lookup table use specifications according to the specified features and candidate lookups, + * where the order of the array is in accordance to the order of the applicable lookup list. + * @param table the governing glyph table + * @param features array of feature identifiers to apply + * @param lookups a mapping from lookup specifications to lists of look tables from which to select lookup tables according to the specified features + * @return ordered array of assembled lookup table use specifications + */ + public final GlyphTable.UseSpec[] assembleLookups ( GlyphTable table, String[] features, Map/*>*/ lookups ) { + return table.assembleLookups ( features, lookups ); + } + + /** + * Obtain script processor instance associated with specified script. + * @param script a script identifier + * @return a script processor instance or null if none found + */ + public static synchronized ScriptProcessor getInstance ( String script ) { + ScriptProcessor sp = null; + assert processors != null; + if ( ( sp = processors.get ( script ) ) == null ) { + processors.put ( script, sp = createProcessor ( script ) ); + } + return sp; + } + + // [TBD] - rework to provide more configurable binding between script name and script processor constructor + private static ScriptProcessor createProcessor ( String script ) { + ScriptProcessor sp = null; + int sc = CharScript.scriptCodeFromTag ( script ); + if ( sc == CharScript.SCRIPT_ARABIC ) { + sp = new ArabicScriptProcessor ( script ); + } else if ( CharScript.isIndicScript ( sc ) ) { + sp = IndicScriptProcessor.makeProcessor ( script ); + } else { + sp = new DefaultScriptProcessor ( script ); + } + return sp; + } + +} diff --git a/src/java/org/apache/fop/complexscripts/util/CharMirror.java b/src/java/org/apache/fop/complexscripts/util/CharMirror.java new file mode 100644 index 000000000..bb1d1587f --- /dev/null +++ b/src/java/org/apache/fop/complexscripts/util/CharMirror.java @@ -0,0 +1,715 @@ +/* + * 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.complexscripts.util; + +import java.util.Arrays; + +/** + * Mirror related utilities. + * @author Glenn Adams + */ +public final class CharMirror { + + private CharMirror() { + } + + /** + * Mirror characters that are designated as having the bidi mirrorred property. + * @param s a string whose characters are to be mirrored + * @return the resulting string + */ + public static String mirror ( String s ) { + StringBuffer sb = new StringBuffer ( s ); + for ( int i = 0, n = sb.length(); i < n; i++ ) { + sb.setCharAt ( i, (char) mirror ( sb.charAt ( i ) ) ); + } + return sb.toString(); + } + + private static int[] mirroredCharacters = { + 0x0028, + 0x0029, + 0x003C, + 0x003E, + 0x005B, + 0x005D, + 0x007B, + 0x007D, + 0x00AB, + 0x00BB, + 0x0F3A, + 0x0F3B, + 0x0F3C, + 0x0F3D, + 0x169B, + 0x169C, + 0x2039, + 0x203A, + 0x2045, + 0x2046, + 0x207D, + 0x207E, + 0x208D, + 0x208E, + 0x2208, + 0x2209, + 0x220A, + 0x220B, + 0x220C, + 0x220D, + 0x2215, + 0x223C, + 0x223D, + 0x2243, + 0x2252, + 0x2253, + 0x2254, + 0x2255, + 0x2264, + 0x2265, + 0x2266, + 0x2267, + 0x2268, + 0x2269, + 0x226A, + 0x226B, + 0x226E, + 0x226F, + 0x2270, + 0x2271, + 0x2272, + 0x2273, + 0x2274, + 0x2275, + 0x2276, + 0x2277, + 0x2278, + 0x2279, + 0x227A, + 0x227B, + 0x227C, + 0x227D, + 0x227E, + 0x227F, + 0x2280, + 0x2281, + 0x2282, + 0x2283, + 0x2284, + 0x2285, + 0x2286, + 0x2287, + 0x2288, + 0x2289, + 0x228A, + 0x228B, + 0x228F, + 0x2290, + 0x2291, + 0x2292, + 0x2298, + 0x22A2, + 0x22A3, + 0x22A6, + 0x22A8, + 0x22A9, + 0x22AB, + 0x22B0, + 0x22B1, + 0x22B2, + 0x22B3, + 0x22B4, + 0x22B5, + 0x22B6, + 0x22B7, + 0x22C9, + 0x22CA, + 0x22CB, + 0x22CC, + 0x22CD, + 0x22D0, + 0x22D1, + 0x22D6, + 0x22D7, + 0x22D8, + 0x22D9, + 0x22DA, + 0x22DB, + 0x22DC, + 0x22DD, + 0x22DE, + 0x22DF, + 0x22E0, + 0x22E1, + 0x22E2, + 0x22E3, + 0x22E4, + 0x22E5, + 0x22E6, + 0x22E7, + 0x22E8, + 0x22E9, + 0x22EA, + 0x22EB, + 0x22EC, + 0x22ED, + 0x22F0, + 0x22F1, + 0x22F2, + 0x22F3, + 0x22F4, + 0x22F6, + 0x22F7, + 0x22FA, + 0x22FB, + 0x22FC, + 0x22FD, + 0x22FE, + 0x2308, + 0x2309, + 0x230A, + 0x230B, + 0x2329, + 0x232A, + 0x2768, + 0x2769, + 0x276A, + 0x276B, + 0x276C, + 0x276D, + 0x276E, + 0x276F, + 0x2770, + 0x2771, + 0x2772, + 0x2773, + 0x2774, + 0x2775, + 0x27C3, + 0x27C4, + 0x27C5, + 0x27C6, + 0x27C8, + 0x27C9, + 0x27D5, + 0x27D6, + 0x27DD, + 0x27DE, + 0x27E2, + 0x27E3, + 0x27E4, + 0x27E5, + 0x27E6, + 0x27E7, + 0x27E8, + 0x27E9, + 0x27EA, + 0x27EB, + 0x27EC, + 0x27ED, + 0x27EE, + 0x27EF, + 0x2983, + 0x2984, + 0x2985, + 0x2986, + 0x2987, + 0x2988, + 0x2989, + 0x298A, + 0x298B, + 0x298C, + 0x298D, + 0x298E, + 0x298F, + 0x2990, + 0x2991, + 0x2992, + 0x2993, + 0x2994, + 0x2995, + 0x2996, + 0x2997, + 0x2998, + 0x29B8, + 0x29C0, + 0x29C1, + 0x29C4, + 0x29C5, + 0x29CF, + 0x29D0, + 0x29D1, + 0x29D2, + 0x29D4, + 0x29D5, + 0x29D8, + 0x29D9, + 0x29DA, + 0x29DB, + 0x29F5, + 0x29F8, + 0x29F9, + 0x29FC, + 0x29FD, + 0x2A2B, + 0x2A2C, + 0x2A2D, + 0x2A2E, + 0x2A34, + 0x2A35, + 0x2A3C, + 0x2A3D, + 0x2A64, + 0x2A65, + 0x2A79, + 0x2A7A, + 0x2A7D, + 0x2A7E, + 0x2A7F, + 0x2A80, + 0x2A81, + 0x2A82, + 0x2A83, + 0x2A84, + 0x2A8B, + 0x2A8C, + 0x2A91, + 0x2A92, + 0x2A93, + 0x2A94, + 0x2A95, + 0x2A96, + 0x2A97, + 0x2A98, + 0x2A99, + 0x2A9A, + 0x2A9B, + 0x2A9C, + 0x2AA1, + 0x2AA2, + 0x2AA6, + 0x2AA7, + 0x2AA8, + 0x2AA9, + 0x2AAA, + 0x2AAB, + 0x2AAC, + 0x2AAD, + 0x2AAF, + 0x2AB0, + 0x2AB3, + 0x2AB4, + 0x2AC3, + 0x2AC4, + 0x2AC5, + 0x2AC6, + 0x2ACD, + 0x2ACE, + 0x2ACF, + 0x2AD0, + 0x2AD1, + 0x2AD2, + 0x2AD3, + 0x2AD4, + 0x2AD5, + 0x2AD6, + 0x2ADE, + 0x2AE3, + 0x2E02, + 0x2E03, + 0x2E04, + 0x2E05, + 0x2E09, + 0x2E0A, + 0x2E0C, + 0x2E0D, + 0x2E1C, + 0x2E1D, + 0x2E20, + 0x2E21, + 0x2E22, + 0x2E23, + 0x2E24, + 0x2E25, + 0x2E26, + 0x300E, + 0x300F, + 0x3010, + 0x3011, + 0x3014, + 0x3015, + 0x3016, + 0x3017, + 0x3018, + 0x3019, + 0x301A, + 0x301B, + 0xFE59, + 0xFE5A, + 0xFF3B, + 0xFF3D, + 0xFF5B, + 0xFF5D, + 0xFF5F, + 0xFF60, + 0xFF62, + 0xFF63 + }; + + private static int[] mirroredCharactersMapping = { + 0x0029, + 0x0028, + 0x003E, + 0x003C, + 0x005D, + 0x005B, + 0x007D, + 0x007B, + 0x00BB, + 0x00AB, + 0x0F3B, + 0x0F3A, + 0x0F3D, + 0x0F3C, + 0x169C, + 0x169B, + 0x203A, + 0x2039, + 0x2046, + 0x2045, + 0x207E, + 0x207D, + 0x208E, + 0x208D, + 0x220B, + 0x220C, + 0x220D, + 0x2208, + 0x2209, + 0x220A, + 0x29F5, + 0x223D, + 0x223C, + 0x22CD, + 0x2253, + 0x2252, + 0x2255, + 0x2254, + 0x2265, + 0x2264, + 0x2267, + 0x2266, + 0x2269, + 0x2268, + 0x226B, + 0x226A, + 0x226F, + 0x226E, + 0x2271, + 0x2270, + 0x2273, + 0x2272, + 0x2275, + 0x2274, + 0x2277, + 0x2276, + 0x2279, + 0x2278, + 0x227B, + 0x227A, + 0x227D, + 0x227C, + 0x227F, + 0x227E, + 0x2281, + 0x2280, + 0x2283, + 0x2282, + 0x2285, + 0x2284, + 0x2287, + 0x2286, + 0x2289, + 0x2288, + 0x228B, + 0x228A, + 0x2290, + 0x228F, + 0x2292, + 0x2291, + 0x29B8, + 0x22A3, + 0x22A2, + 0x2ADE, + 0x2AE4, + 0x2AE3, + 0x2AE5, + 0x22B1, + 0x22B0, + 0x22B3, + 0x22B2, + 0x22B5, + 0x22B4, + 0x22B7, + 0x22B6, + 0x22CA, + 0x22C9, + 0x22CC, + 0x22CB, + 0x2243, + 0x22D1, + 0x22D0, + 0x22D7, + 0x22D6, + 0x22D9, + 0x22D8, + 0x22DB, + 0x22DA, + 0x22DD, + 0x22DC, + 0x22DF, + 0x22DE, + 0x22E1, + 0x22E0, + 0x22E3, + 0x22E2, + 0x22E5, + 0x22E4, + 0x22E7, + 0x22E6, + 0x22E9, + 0x22E8, + 0x22EB, + 0x22EA, + 0x22ED, + 0x22EC, + 0x22F1, + 0x22F0, + 0x22FA, + 0x22FB, + 0x22FC, + 0x22FD, + 0x22FE, + 0x22F2, + 0x22F3, + 0x22F4, + 0x22F6, + 0x22F7, + 0x2309, + 0x2308, + 0x230B, + 0x230A, + 0x232A, + 0x2329, + 0x2769, + 0x2768, + 0x276B, + 0x276A, + 0x276D, + 0x276C, + 0x276F, + 0x276E, + 0x2771, + 0x2770, + 0x2773, + 0x2772, + 0x2775, + 0x2774, + 0x27C4, + 0x27C3, + 0x27C6, + 0x27C5, + 0x27C9, + 0x27C8, + 0x27D6, + 0x27D5, + 0x27DE, + 0x27DD, + 0x27E3, + 0x27E2, + 0x27E5, + 0x27E4, + 0x27E7, + 0x27E6, + 0x27E9, + 0x27E8, + 0x27EB, + 0x27EA, + 0x27ED, + 0x27EC, + 0x27EF, + 0x27EE, + 0x2984, + 0x2983, + 0x2986, + 0x2985, + 0x2988, + 0x2987, + 0x298A, + 0x2989, + 0x298C, + 0x298B, + 0x2990, + 0x298F, + 0x298E, + 0x298D, + 0x2992, + 0x2991, + 0x2994, + 0x2993, + 0x2996, + 0x2995, + 0x2998, + 0x2997, + 0x2298, + 0x29C1, + 0x29C0, + 0x29C5, + 0x29C4, + 0x29D0, + 0x29CF, + 0x29D2, + 0x29D1, + 0x29D5, + 0x29D4, + 0x29D9, + 0x29D8, + 0x29DB, + 0x29DA, + 0x2215, + 0x29F9, + 0x29F8, + 0x29FD, + 0x29FC, + 0x2A2C, + 0x2A2B, + 0x2A2E, + 0x2A2D, + 0x2A35, + 0x2A34, + 0x2A3D, + 0x2A3C, + 0x2A65, + 0x2A64, + 0x2A7A, + 0x2A79, + 0x2A7E, + 0x2A7D, + 0x2A80, + 0x2A7F, + 0x2A82, + 0x2A81, + 0x2A84, + 0x2A83, + 0x2A8C, + 0x2A8B, + 0x2A92, + 0x2A91, + 0x2A94, + 0x2A93, + 0x2A96, + 0x2A95, + 0x2A98, + 0x2A97, + 0x2A9A, + 0x2A99, + 0x2A9C, + 0x2A9B, + 0x2AA2, + 0x2AA1, + 0x2AA7, + 0x2AA6, + 0x2AA9, + 0x2AA8, + 0x2AAB, + 0x2AAA, + 0x2AAD, + 0x2AAC, + 0x2AB0, + 0x2AAF, + 0x2AB4, + 0x2AB3, + 0x2AC4, + 0x2AC3, + 0x2AC6, + 0x2AC5, + 0x2ACE, + 0x2ACD, + 0x2AD0, + 0x2ACF, + 0x2AD2, + 0x2AD1, + 0x2AD4, + 0x2AD3, + 0x2AD6, + 0x2AD5, + 0x22A6, + 0x22A9, + 0x2E03, + 0x2E02, + 0x2E05, + 0x2E04, + 0x2E0A, + 0x2E09, + 0x2E0D, + 0x2E0C, + 0x2E1D, + 0x2E1C, + 0x2E21, + 0x2E20, + 0x2E23, + 0x2E22, + 0x2E25, + 0x2E24, + 0x2E27, + 0x300F, + 0x300E, + 0x3011, + 0x3010, + 0x3015, + 0x3014, + 0x3017, + 0x3016, + 0x3019, + 0x3018, + 0x301B, + 0x301A, + 0xFE5A, + 0xFE59, + 0xFF3D, + 0xFF3B, + 0xFF5D, + 0xFF5B, + 0xFF60, + 0xFF5F, + 0xFF63, + 0xFF62 + }; + + private static int mirror ( int c ) { + int i = Arrays.binarySearch ( mirroredCharacters, c ); + if ( i < 0 ) { + return c; + } else { + return mirroredCharactersMapping [ i ]; + } + } + +} diff --git a/src/java/org/apache/fop/complexscripts/util/CharScript.java b/src/java/org/apache/fop/complexscripts/util/CharScript.java new file mode 100644 index 000000000..bcce31327 --- /dev/null +++ b/src/java/org/apache/fop/complexscripts/util/CharScript.java @@ -0,0 +1,930 @@ +/* + * 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.complexscripts.util; + +import java.util.Arrays; +import java.util.Iterator; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import org.apache.fop.util.CharUtilities; + +// CSOFF: AvoidNestedBlocksCheck +// CSOFF: InnerAssignmentCheck +// CSOFF: LineLengthCheck +// CSOFF: SimplifyBooleanReturnCheck +// CSOFF: WhitespaceAfterCheck + +/** + * Script related utilities. + * @author Glenn Adams + */ +public final class CharScript { + + // + // The following script codes are based on ISO 15924. Codes less than 1000 are + // official assignments from 15924; those equal to or greater than 1000 are FOP + // implementation specific. + // + /** hebrew script constant */ + public static final int SCRIPT_HEBREW = 125; // 'hebr' + /** mongolian script constant */ + public static final int SCRIPT_MONGOLIAN = 145; // 'mong' + /** arabic script constant */ + public static final int SCRIPT_ARABIC = 160; // 'arab' + /** greek script constant */ + public static final int SCRIPT_GREEK = 200; // 'grek' + /** latin script constant */ + public static final int SCRIPT_LATIN = 215; // 'latn' + /** cyrillic script constant */ + public static final int SCRIPT_CYRILLIC = 220; // 'cyrl' + /** georgian script constant */ + public static final int SCRIPT_GEORGIAN = 240; // 'geor' + /** bopomofo script constant */ + public static final int SCRIPT_BOPOMOFO = 285; // 'bopo' + /** hangul script constant */ + public static final int SCRIPT_HANGUL = 286; // 'hang' + /** gurmukhi script constant */ + public static final int SCRIPT_GURMUKHI = 310; // 'guru' + /** gurmukhi 2 script constant */ + public static final int SCRIPT_GURMUKHI_2 = 1310; // 'gur2' -- MSFT (pseudo) script tag for variant shaping semantics + /** devanagari script constant */ + public static final int SCRIPT_DEVANAGARI = 315; // 'deva' + /** devanagari 2 script constant */ + public static final int SCRIPT_DEVANAGARI_2 = 1315; // 'dev2' -- MSFT (pseudo) script tag for variant shaping semantics + /** gujarati script constant */ + public static final int SCRIPT_GUJARATI = 320; // 'gujr' + /** gujarati 2 script constant */ + public static final int SCRIPT_GUJARATI_2 = 1320; // 'gjr2' -- MSFT (pseudo) script tag for variant shaping semantics + /** bengali script constant */ + public static final int SCRIPT_BENGALI = 326; // 'beng' + /** bengali 2 script constant */ + public static final int SCRIPT_BENGALI_2 = 1326; // 'bng2' -- MSFT (pseudo) script tag for variant shaping semantics + /** oriya script constant */ + public static final int SCRIPT_ORIYA = 327; // 'orya' + /** oriya 2 script constant */ + public static final int SCRIPT_ORIYA_2 = 1327; // 'ory2' -- MSFT (pseudo) script tag for variant shaping semantics + /** tibetan script constant */ + public static final int SCRIPT_TIBETAN = 330; // 'tibt' + /** telugu script constant */ + public static final int SCRIPT_TELUGU = 340; // 'telu' + /** telugu 2 script constant */ + public static final int SCRIPT_TELUGU_2 = 1340; // 'tel2' -- MSFT (pseudo) script tag for variant shaping semantics + /** kannada script constant */ + public static final int SCRIPT_KANNADA = 345; // 'knda' + /** kannada 2 script constant */ + public static final int SCRIPT_KANNADA_2 = 1345; // 'knd2' -- MSFT (pseudo) script tag for variant shaping semantics + /** tamil script constant */ + public static final int SCRIPT_TAMIL = 346; // 'taml' + /** tamil 2 script constant */ + public static final int SCRIPT_TAMIL_2 = 1346; // 'tml2' -- MSFT (pseudo) script tag for variant shaping semantics + /** malayalam script constant */ + public static final int SCRIPT_MALAYALAM = 347; // 'mlym' + /** malayalam 2 script constant */ + public static final int SCRIPT_MALAYALAM_2 = 1347; // 'mlm2' -- MSFT (pseudo) script tag for variant shaping semantics + /** sinhalese script constant */ + public static final int SCRIPT_SINHALESE = 348; // 'sinh' + /** burmese script constant */ + public static final int SCRIPT_BURMESE = 350; // 'mymr' + /** thai script constant */ + public static final int SCRIPT_THAI = 352; // 'thai' + /** khmer script constant */ + public static final int SCRIPT_KHMER = 355; // 'khmr' + /** lao script constant */ + public static final int SCRIPT_LAO = 356; // 'laoo' + /** hiragana script constant */ + public static final int SCRIPT_HIRAGANA = 410; // 'hira' + /** ethiopic script constant */ + public static final int SCRIPT_ETHIOPIC = 430; // 'ethi' + /** han script constant */ + public static final int SCRIPT_HAN = 500; // 'hani' + /** katakana script constant */ + public static final int SCRIPT_KATAKANA = 410; // 'kana' + /** math script constant */ + public static final int SCRIPT_MATH = 995; // 'zmth' + /** symbol script constant */ + public static final int SCRIPT_SYMBOL = 996; // 'zsym' + /** undetermined script constant */ + public static final int SCRIPT_UNDETERMINED = 998; // 'zyyy' + /** uncoded script constant */ + public static final int SCRIPT_UNCODED = 999; // 'zzzz' + + /** + * A static (class) parameter indicating whether V2 indic shaping + * rules apply or not, with default being true. + */ + private static final boolean useV2Indic = true; // CSOK: ConstantNameCheck + + private CharScript() { + } + + /** + * Determine if character c is punctuation. + * @param c a character represented as a unicode scalar value + * @return true if character is punctuation + */ + public static boolean isPunctuation ( int c ) { + if ( ( c >= 0x0021 ) && ( c <= 0x002F ) ) { // basic latin punctuation + return true; + } else if ( ( c >= 0x003A ) && ( c <= 0x0040 ) ) { // basic latin punctuation + return true; + } else if ( ( c >= 0x005F ) && ( c <= 0x0060 ) ) { // basic latin punctuation + return true; + } else if ( ( c >= 0x007E ) && ( c <= 0x007E ) ) { // basic latin punctuation + return true; + } else if ( ( c >= 0x007E ) && ( c <= 0x007E ) ) { // basic latin punctuation + return true; + } else if ( ( c >= 0x00A1 ) && ( c <= 0x00BF ) ) { // latin supplement punctuation + return true; + } else if ( ( c >= 0x00D7 ) && ( c <= 0x00D7 ) ) { // latin supplement punctuation + return true; + } else if ( ( c >= 0x00F7 ) && ( c <= 0x00F7 ) ) { // latin supplement punctuation + return true; + } else if ( ( c >= 0x2000 ) && ( c <= 0x206F ) ) { // general punctuation + return true; + } else { // [TBD] - not complete + return false; + } + } + + /** + * Determine if character c is a digit. + * @param c a character represented as a unicode scalar value + * @return true if character is a digit + */ + public static boolean isDigit ( int c ) { + if ( ( c >= 0x0030 ) && ( c <= 0x0039 ) ) { // basic latin digits + return true; + } else { // [TBD] - not complete + return false; + } + } + + /** + * Determine if character c belong to the hebrew script. + * @param c a character represented as a unicode scalar value + * @return true if character belongs to hebrew script + */ + public static boolean isHebrew ( int c ) { + if ( ( c >= 0x0590 ) && ( c <= 0x05FF ) ) { // hebrew block + return true; + } else if ( ( c >= 0xFB00 ) && ( c <= 0xFB4F ) ) { // hebrew presentation forms block + return true; + } else { + return false; + } + } + + /** + * Determine if character c belong to the mongolian script. + * @param c a character represented as a unicode scalar value + * @return true if character belongs to mongolian script + */ + public static boolean isMongolian ( int c ) { + if ( ( c >= 0x1800 ) && ( c <= 0x18AF ) ) { // mongolian block + return true; + } else { + return false; + } + } + + /** + * Determine if character c belong to the arabic script. + * @param c a character represented as a unicode scalar value + * @return true if character belongs to arabic script + */ + public static boolean isArabic ( int c ) { + if ( ( c >= 0x0600 ) && ( c <= 0x06FF ) ) { // arabic block + return true; + } else if ( ( c >= 0x0750 ) && ( c <= 0x077F ) ) { // arabic supplement block + return true; + } else if ( ( c >= 0xFB50 ) && ( c <= 0xFDFF ) ) { // arabic presentation forms a block + return true; + } else if ( ( c >= 0xFE70 ) && ( c <= 0xFEFF ) ) { // arabic presentation forms b block + return true; + } else { + return false; + } + } + + /** + * Determine if character c belong to the greek script. + * @param c a character represented as a unicode scalar value + * @return true if character belongs to greek script + */ + public static boolean isGreek ( int c ) { + if ( ( c >= 0x0370 ) && ( c <= 0x03FF ) ) { // greek (and coptic) block + return true; + } else if ( ( c >= 0x1F00 ) && ( c <= 0x1FFF ) ) { // greek extended block + return true; + } else { + return false; + } + } + + /** + * Determine if character c belong to the latin script. + * @param c a character represented as a unicode scalar value + * @return true if character belongs to latin script + */ + public static boolean isLatin ( int c ) { + if ( ( c >= 0x0041 ) && ( c <= 0x005A ) ) { // basic latin upper case + return true; + } else if ( ( c >= 0x0061 ) && ( c <= 0x007A ) ) { // basic latin lower case + return true; + } else if ( ( c >= 0x00C0 ) && ( c <= 0x00D6 ) ) { // latin supplement upper case + return true; + } else if ( ( c >= 0x00D8 ) && ( c <= 0x00DF ) ) { // latin supplement upper case + return true; + } else if ( ( c >= 0x00E0 ) && ( c <= 0x00F6 ) ) { // latin supplement lower case + return true; + } else if ( ( c >= 0x00F8 ) && ( c <= 0x00FF ) ) { // latin supplement lower case + return true; + } else if ( ( c >= 0x0100 ) && ( c <= 0x017F ) ) { // latin extended a + return true; + } else if ( ( c >= 0x0180 ) && ( c <= 0x024F ) ) { // latin extended b + return true; + } else if ( ( c >= 0x1E00 ) && ( c <= 0x1EFF ) ) { // latin extended additional + return true; + } else if ( ( c >= 0x2C60 ) && ( c <= 0x2C7F ) ) { // latin extended c + return true; + } else if ( ( c >= 0xA720 ) && ( c <= 0xA7FF ) ) { // latin extended d + return true; + } else if ( ( c >= 0xFB00 ) && ( c <= 0xFB0F ) ) { // latin ligatures + return true; + } else { + return false; + } + } + + /** + * Determine if character c belong to the cyrillic script. + * @param c a character represented as a unicode scalar value + * @return true if character belongs to cyrillic script + */ + public static boolean isCyrillic ( int c ) { + if ( ( c >= 0x0400 ) && ( c <= 0x04FF ) ) { // cyrillic block + return true; + } else if ( ( c >= 0x0500 ) && ( c <= 0x052F ) ) { // cyrillic supplement block + return true; + } else if ( ( c >= 0x2DE0 ) && ( c <= 0x2DFF ) ) { // cyrillic extended-a block + return true; + } else if ( ( c >= 0xA640 ) && ( c <= 0xA69F ) ) { // cyrillic extended-b block + return true; + } else { + return false; + } + } + + /** + * Determine if character c belong to the georgian script. + * @param c a character represented as a unicode scalar value + * @return true if character belongs to georgian script + */ + public static boolean isGeorgian ( int c ) { + if ( ( c >= 0x10A0 ) && ( c <= 0x10FF ) ) { // georgian block + return true; + } else if ( ( c >= 0x2D00 ) && ( c <= 0x2D2F ) ) { // georgian supplement block + return true; + } else { + return false; + } + } + + /** + * Determine if character c belong to the hangul script. + * @param c a character represented as a unicode scalar value + * @return true if character belongs to hangul script + */ + public static boolean isHangul ( int c ) { + if ( ( c >= 0x1100 ) && ( c <= 0x11FF ) ) { // hangul jamo + return true; + } else if ( ( c >= 0x3130 ) && ( c <= 0x318F ) ) { // hangul compatibility jamo + return true; + } else if ( ( c >= 0xA960 ) && ( c <= 0xA97F ) ) { // hangul jamo extended a + return true; + } else if ( ( c >= 0xAC00 ) && ( c <= 0xD7A3 ) ) { // hangul syllables + return true; + } else if ( ( c >= 0xD7B0 ) && ( c <= 0xD7FF ) ) { // hangul jamo extended a + return true; + } else { + return false; + } + } + + /** + * Determine if character c belong to the gurmukhi script. + * @param c a character represented as a unicode scalar value + * @return true if character belongs to gurmukhi script + */ + public static boolean isGurmukhi ( int c ) { + if ( ( c >= 0x0A00 ) && ( c <= 0x0A7F ) ) { // gurmukhi block + return true; + } else { + return false; + } + } + + /** + * Determine if character c belong to the devanagari script. + * @param c a character represented as a unicode scalar value + * @return true if character belongs to devanagari script + */ + public static boolean isDevanagari ( int c ) { + if ( ( c >= 0x0900 ) && ( c <= 0x097F ) ) { // devangari block + return true; + } else if ( ( c >= 0xA8E0 ) && ( c <= 0xA8FF ) ) { // devangari extended block + return true; + } else { + return false; + } + } + + /** + * Determine if character c belong to the gujarati script. + * @param c a character represented as a unicode scalar value + * @return true if character belongs to gujarati script + */ + public static boolean isGujarati ( int c ) { + if ( ( c >= 0x0A80 ) && ( c <= 0x0AFF ) ) { // gujarati block + return true; + } else { + return false; + } + } + + /** + * Determine if character c belong to the bengali script. + * @param c a character represented as a unicode scalar value + * @return true if character belongs to bengali script + */ + public static boolean isBengali ( int c ) { + if ( ( c >= 0x0980 ) && ( c <= 0x09FF ) ) { // bengali block + return true; + } else { + return false; + } + } + + /** + * Determine if character c belong to the oriya script. + * @param c a character represented as a unicode scalar value + * @return true if character belongs to oriya script + */ + public static boolean isOriya ( int c ) { + if ( ( c >= 0x0B00 ) && ( c <= 0x0B7F ) ) { // oriya block + return true; + } else { + return false; + } + } + + /** + * Determine if character c belong to the tibetan script. + * @param c a character represented as a unicode scalar value + * @return true if character belongs to tibetan script + */ + public static boolean isTibetan ( int c ) { + if ( ( c >= 0x0F00 ) && ( c <= 0x0FFF ) ) { // tibetan block + return true; + } else { + return false; + } + } + + /** + * Determine if character c belong to the telugu script. + * @param c a character represented as a unicode scalar value + * @return true if character belongs to telugu script + */ + public static boolean isTelugu ( int c ) { + if ( ( c >= 0x0C00 ) && ( c <= 0x0C7F ) ) { // telugu block + return true; + } else { + return false; + } + } + + /** + * Determine if character c belong to the kannada script. + * @param c a character represented as a unicode scalar value + * @return true if character belongs to kannada script + */ + public static boolean isKannada ( int c ) { + if ( ( c >= 0x0C00 ) && ( c <= 0x0C7F ) ) { // kannada block + return true; + } else { + return false; + } + } + + /** + * Determine if character c belong to the tamil script. + * @param c a character represented as a unicode scalar value + * @return true if character belongs to tamil script + */ + public static boolean isTamil ( int c ) { + if ( ( c >= 0x0B80 ) && ( c <= 0x0BFF ) ) { // tamil block + return true; + } else { + return false; + } + } + + /** + * Determine if character c belong to the malayalam script. + * @param c a character represented as a unicode scalar value + * @return true if character belongs to malayalam script + */ + public static boolean isMalayalam ( int c ) { + if ( ( c >= 0x0D00 ) && ( c <= 0x0D7F ) ) { // malayalam block + return true; + } else { + return false; + } + } + + /** + * Determine if character c belong to the sinhalese script. + * @param c a character represented as a unicode scalar value + * @return true if character belongs to sinhalese script + */ + public static boolean isSinhalese ( int c ) { + if ( ( c >= 0x0D80 ) && ( c <= 0x0DFF ) ) { // sinhala block + return true; + } else { + return false; + } + } + + /** + * Determine if character c belong to the burmese script. + * @param c a character represented as a unicode scalar value + * @return true if character belongs to burmese script + */ + public static boolean isBurmese ( int c ) { + if ( ( c >= 0x1000 ) && ( c <= 0x109F ) ) { // burmese (myanmar) block + return true; + } else if ( ( c >= 0xAA60 ) && ( c <= 0xAA7F ) ) { // burmese (myanmar) extended block + return true; + } else { + return false; + } + } + + /** + * Determine if character c belong to the thai script. + * @param c a character represented as a unicode scalar value + * @return true if character belongs to thai script + */ + public static boolean isThai ( int c ) { + if ( ( c >= 0x0E00 ) && ( c <= 0x0E7F ) ) { // thai block + return true; + } else { + return false; + } + } + + /** + * Determine if character c belong to the khmer script. + * @param c a character represented as a unicode scalar value + * @return true if character belongs to khmer script + */ + public static boolean isKhmer ( int c ) { + if ( ( c >= 0x1780 ) && ( c <= 0x17FF ) ) { // khmer block + return true; + } else if ( ( c >= 0x19E0 ) && ( c <= 0x19FF ) ) { // khmer symbols block + return true; + } else { + return false; + } + } + + /** + * Determine if character c belong to the lao script. + * @param c a character represented as a unicode scalar value + * @return true if character belongs to lao script + */ + public static boolean isLao ( int c ) { + if ( ( c >= 0x0E80 ) && ( c <= 0x0EFF ) ) { // lao block + return true; + } else { + return false; + } + } + + /** + * Determine if character c belong to the ethiopic (amharic) script. + * @param c a character represented as a unicode scalar value + * @return true if character belongs to ethiopic (amharic) script + */ + public static boolean isEthiopic ( int c ) { + if ( ( c >= 0x1200 ) && ( c <= 0x137F ) ) { // ethiopic block + return true; + } else if ( ( c >= 0x1380 ) && ( c <= 0x139F ) ) { // ethoipic supplement block + return true; + } else if ( ( c >= 0x2D80 ) && ( c <= 0x2DDF ) ) { // ethoipic extended block + return true; + } else if ( ( c >= 0xAB00 ) && ( c <= 0xAB2F ) ) { // ethoipic extended-a block + return true; + } else { + return false; + } + } + + /** + * Determine if character c belong to the han (unified cjk) script. + * @param c a character represented as a unicode scalar value + * @return true if character belongs to han (unified cjk) script + */ + public static boolean isHan ( int c ) { + if ( ( c >= 0x3400 ) && ( c <= 0x4DBF ) ) { + return true; // cjk unified ideographs extension a + } else if ( ( c >= 0x4E00 ) && ( c <= 0x9FFF ) ) { + return true; // cjk unified ideographs + } else if ( ( c >= 0xF900 ) && ( c <= 0xFAFF ) ) { + return true; // cjk compatibility ideographs + } else if ( ( c >= 0x20000 ) && ( c <= 0x2A6DF ) ) { + return true; // cjk unified ideographs extension b + } else if ( ( c >= 0x2A700 ) && ( c <= 0x2B73F ) ) { + return true; // cjk unified ideographs extension c + } else if ( ( c >= 0x2F800 ) && ( c <= 0x2FA1F ) ) { + return true; // cjk compatibility ideographs supplement + } else { + return false; + } + } + + /** + * Determine if character c belong to the bopomofo script. + * @param c a character represented as a unicode scalar value + * @return true if character belongs to bopomofo script + */ + public static boolean isBopomofo ( int c ) { + if ( ( c >= 0x3100 ) && ( c <= 0x312F ) ) { + return true; + } else { + return false; + } + } + + /** + * Determine if character c belong to the hiragana script. + * @param c a character represented as a unicode scalar value + * @return true if character belongs to hiragana script + */ + public static boolean isHiragana ( int c ) { + if ( ( c >= 0x3040 ) && ( c <= 0x309F ) ) { + return true; + } else { + return false; + } + } + + /** + * Determine if character c belong to the katakana script. + * @param c a character represented as a unicode scalar value + * @return true if character belongs to katakana script + */ + public static boolean isKatakana ( int c ) { + if ( ( c >= 0x30A0 ) && ( c <= 0x30FF ) ) { + return true; + } else if ( ( c >= 0x31F0 ) && ( c <= 0x31FF ) ) { + return true; + } else { + return false; + } + } + + /** + * Obtain ISO15924 numeric script code of character. If script is not or cannot be determined, + * then the script code 998 ('zyyy') is returned. + * @param c the character to obtain script + * @return an ISO15924 script code + */ + public static int scriptOf ( int c ) { // [TBD] - needs optimization!!! + if ( CharUtilities.isAnySpace ( c ) ) { + return SCRIPT_UNDETERMINED; + } else if ( isPunctuation ( c ) ) { + return SCRIPT_UNDETERMINED; + } else if ( isDigit ( c ) ) { + return SCRIPT_UNDETERMINED; + } else if ( isLatin ( c ) ) { + return SCRIPT_LATIN; + } else if ( isCyrillic ( c ) ) { + return SCRIPT_CYRILLIC; + } else if ( isGreek ( c ) ) { + return SCRIPT_GREEK; + } else if ( isHan ( c ) ) { + return SCRIPT_HAN; + } else if ( isBopomofo ( c ) ) { + return SCRIPT_BOPOMOFO; + } else if ( isKatakana ( c ) ) { + return SCRIPT_KATAKANA; + } else if ( isHiragana ( c ) ) { + return SCRIPT_HIRAGANA; + } else if ( isHangul ( c ) ) { + return SCRIPT_HANGUL; + } else if ( isArabic ( c ) ) { + return SCRIPT_ARABIC; + } else if ( isHebrew ( c ) ) { + return SCRIPT_HEBREW; + } else if ( isMongolian ( c ) ) { + return SCRIPT_MONGOLIAN; + } else if ( isGeorgian ( c ) ) { + return SCRIPT_GEORGIAN; + } else if ( isGurmukhi ( c ) ) { + return useV2IndicRules ( SCRIPT_GURMUKHI ); + } else if ( isDevanagari ( c ) ) { + return useV2IndicRules ( SCRIPT_DEVANAGARI ); + } else if ( isGujarati ( c ) ) { + return useV2IndicRules ( SCRIPT_GUJARATI ); + } else if ( isBengali ( c ) ) { + return useV2IndicRules ( SCRIPT_BENGALI ); + } else if ( isOriya ( c ) ) { + return useV2IndicRules ( SCRIPT_ORIYA ); + } else if ( isTibetan ( c ) ) { + return SCRIPT_TIBETAN; + } else if ( isTelugu ( c ) ) { + return useV2IndicRules ( SCRIPT_TELUGU ); + } else if ( isKannada ( c ) ) { + return useV2IndicRules ( SCRIPT_KANNADA ); + } else if ( isTamil ( c ) ) { + return useV2IndicRules ( SCRIPT_TAMIL ); + } else if ( isMalayalam ( c ) ) { + return useV2IndicRules ( SCRIPT_MALAYALAM ); + } else if ( isSinhalese ( c ) ) { + return SCRIPT_SINHALESE; + } else if ( isBurmese ( c ) ) { + return SCRIPT_BURMESE; + } else if ( isThai ( c ) ) { + return SCRIPT_THAI; + } else if ( isKhmer ( c ) ) { + return SCRIPT_KHMER; + } else if ( isLao ( c ) ) { + return SCRIPT_LAO; + } else if ( isEthiopic ( c ) ) { + return SCRIPT_ETHIOPIC; + } else { + return SCRIPT_UNDETERMINED; + } + } + + /** + * Obtain the V2 indic script code corresponding to V1 indic script code SC if + * and only iff V2 indic rules apply; otherwise return SC. + * @param sc a V1 indic script code + * @return either SC or the V2 flavor of SC if V2 indic rules apply + */ + public static int useV2IndicRules ( int sc ) { + if ( useV2Indic ) { + return ( sc < 1000 ) ? ( sc + 1000 ) : sc; + } else { + return sc; + } + } + + /** + * Obtain the script codes of each character in a character sequence. If script + * is not or cannot be determined for some character, then the script code 998 + * ('zyyy') is returned. + * @param cs the character sequence + * @return a (possibly empty) array of script codes + */ + public static int[] scriptsOf ( CharSequence cs ) { + Set s = new HashSet(); + for ( int i = 0, n = cs.length(); i < n; i++ ) { + s.add ( Integer.valueOf ( scriptOf ( cs.charAt ( i ) ) ) ); + } + int[] sa = new int [ s.size() ]; + int ns = 0; + for ( Iterator it = s.iterator(); it.hasNext();) { + sa [ ns++ ] = ( (Integer) it.next() ) .intValue(); + } + Arrays.sort ( sa ); + return sa; + } + + /** + * Determine the dominant script of a character sequence. + * @param cs the character sequence + * @return the dominant script or SCRIPT_UNDETERMINED + */ + public static int dominantScript ( CharSequence cs ) { + Map m = new HashMap(); + for ( int i = 0, n = cs.length(); i < n; i++ ) { + int c = cs.charAt ( i ); + int s = scriptOf ( c ); + Integer k = Integer.valueOf ( s ); + Integer v = (Integer) m.get ( k ); + if ( v != null ) { + m.put ( k, Integer.valueOf ( v.intValue() + 1 ) ); + } else { + m.put ( k, Integer.valueOf ( 0 ) ); + } + } + int sMax = -1; + int cMax = -1; + for ( Iterator it = m.entrySet().iterator(); it.hasNext();) { + Map.Entry e = (Map.Entry) it.next(); + Integer k = (Integer) e.getKey(); + int s = k.intValue(); + switch ( s ) { + case SCRIPT_UNDETERMINED: + case SCRIPT_UNCODED: + break; + default: + { + Integer v = (Integer) e.getValue(); + assert v != null; + int c = v.intValue(); + if ( c > cMax ) { + cMax = c; sMax = s; + } + break; + } + } + } + if ( sMax < 0 ) { + sMax = SCRIPT_UNDETERMINED; + } + return sMax; + } + + /** + * Determine if script tag denotes an 'Indic' script, where a + * script is an 'Indic' script if it is intended to be processed by + * the generic 'Indic' Script Processor. + * @param script a script tag + * @return true if script tag is a designated 'Indic' script + */ + public static boolean isIndicScript ( String script ) { + return isIndicScript ( scriptCodeFromTag ( script ) ); + } + + /** + * Determine if script tag denotes an 'Indic' script, where a + * script is an 'Indic' script if it is intended to be processed by + * the generic 'Indic' Script Processor. + * @param script a script code + * @return true if script code is a designated 'Indic' script + */ + public static boolean isIndicScript ( int script ) { + switch ( script ) { + case SCRIPT_BENGALI: + case SCRIPT_BENGALI_2: + case SCRIPT_BURMESE: + case SCRIPT_DEVANAGARI: + case SCRIPT_DEVANAGARI_2: + case SCRIPT_GUJARATI: + case SCRIPT_GUJARATI_2: + case SCRIPT_GURMUKHI: + case SCRIPT_GURMUKHI_2: + case SCRIPT_KANNADA: + case SCRIPT_KANNADA_2: + case SCRIPT_MALAYALAM: + case SCRIPT_MALAYALAM_2: + case SCRIPT_ORIYA: + case SCRIPT_ORIYA_2: + case SCRIPT_TAMIL: + case SCRIPT_TAMIL_2: + case SCRIPT_TELUGU: + case SCRIPT_TELUGU_2: + return true; + default: + return false; + } + } + + /** + * Determine the script tag associated with an internal script code. + * @param code the script code + * @return a script tag + */ + public static String scriptTagFromCode ( int code ) { + Map m = getScriptTagsMap(); + if ( m != null ) { + String tag; + if ( ( tag = m.get ( Integer.valueOf ( code ) ) ) != null ) { + return tag; + } else { + return ""; + } + } else { + return ""; + } + } + + /** + * Determine the internal script code associated with a script tag. + * @param tag the script tag + * @return a script code + */ + public static int scriptCodeFromTag ( String tag ) { + Map m = getScriptCodeMap(); + if ( m != null ) { + Integer c; + if ( ( c = m.get ( tag ) ) != null ) { + return (int) c; + } else { + return SCRIPT_UNDETERMINED; + } + } else { + return SCRIPT_UNDETERMINED; + } + } + + private static Map scriptTagsMap = null; + private static Map scriptCodeMap = null; + + private static void putScriptTag ( Map tm, Map cm, int code, String tag ) { + assert tag != null; + assert tag.length() != 0; + assert code >= 0; + assert code < 2000; + tm.put ( Integer.valueOf ( code ), tag ); + cm.put ( tag, Integer.valueOf ( code ) ); + } + + private static void makeScriptMaps() { + HashMap tm = new HashMap(); + HashMap cm = new HashMap(); + putScriptTag ( tm, cm, SCRIPT_HEBREW, "hebr" ); + putScriptTag ( tm, cm, SCRIPT_MONGOLIAN, "mong" ); + putScriptTag ( tm, cm, SCRIPT_ARABIC, "arab" ); + putScriptTag ( tm, cm, SCRIPT_GREEK, "grek" ); + putScriptTag ( tm, cm, SCRIPT_LATIN, "latn" ); + putScriptTag ( tm, cm, SCRIPT_CYRILLIC, "cyrl" ); + putScriptTag ( tm, cm, SCRIPT_GEORGIAN, "geor" ); + putScriptTag ( tm, cm, SCRIPT_BOPOMOFO, "bopo" ); + putScriptTag ( tm, cm, SCRIPT_HANGUL, "hang" ); + putScriptTag ( tm, cm, SCRIPT_GURMUKHI, "guru" ); + putScriptTag ( tm, cm, SCRIPT_GURMUKHI_2, "gur2" ); + putScriptTag ( tm, cm, SCRIPT_DEVANAGARI, "deva" ); + putScriptTag ( tm, cm, SCRIPT_DEVANAGARI_2, "dev2" ); + putScriptTag ( tm, cm, SCRIPT_GUJARATI, "gujr" ); + putScriptTag ( tm, cm, SCRIPT_GUJARATI_2, "gjr2" ); + putScriptTag ( tm, cm, SCRIPT_BENGALI, "beng" ); + putScriptTag ( tm, cm, SCRIPT_BENGALI_2, "bng2" ); + putScriptTag ( tm, cm, SCRIPT_ORIYA, "orya" ); + putScriptTag ( tm, cm, SCRIPT_ORIYA_2, "ory2" ); + putScriptTag ( tm, cm, SCRIPT_TIBETAN, "tibt" ); + putScriptTag ( tm, cm, SCRIPT_TELUGU, "telu" ); + putScriptTag ( tm, cm, SCRIPT_TELUGU_2, "tel2" ); + putScriptTag ( tm, cm, SCRIPT_KANNADA, "knda" ); + putScriptTag ( tm, cm, SCRIPT_KANNADA_2, "knd2" ); + putScriptTag ( tm, cm, SCRIPT_TAMIL, "taml" ); + putScriptTag ( tm, cm, SCRIPT_TAMIL_2, "tml2" ); + putScriptTag ( tm, cm, SCRIPT_MALAYALAM, "mlym" ); + putScriptTag ( tm, cm, SCRIPT_MALAYALAM_2, "mlm2" ); + putScriptTag ( tm, cm, SCRIPT_SINHALESE, "sinh" ); + putScriptTag ( tm, cm, SCRIPT_BURMESE, "mymr" ); + putScriptTag ( tm, cm, SCRIPT_THAI, "thai" ); + putScriptTag ( tm, cm, SCRIPT_KHMER, "khmr" ); + putScriptTag ( tm, cm, SCRIPT_LAO, "laoo" ); + putScriptTag ( tm, cm, SCRIPT_HIRAGANA, "hira" ); + putScriptTag ( tm, cm, SCRIPT_ETHIOPIC, "ethi" ); + putScriptTag ( tm, cm, SCRIPT_HAN, "hani" ); + putScriptTag ( tm, cm, SCRIPT_KATAKANA, "kana" ); + putScriptTag ( tm, cm, SCRIPT_MATH, "zmth" ); + putScriptTag ( tm, cm, SCRIPT_SYMBOL, "zsym" ); + putScriptTag ( tm, cm, SCRIPT_UNDETERMINED, "zyyy" ); + putScriptTag ( tm, cm, SCRIPT_UNCODED, "zzzz" ); + scriptTagsMap = tm; + scriptCodeMap = cm; + } + + private static Map getScriptTagsMap() { + if ( scriptTagsMap == null ) { + makeScriptMaps(); + } + return scriptTagsMap; + } + + private static Map getScriptCodeMap() { + if ( scriptCodeMap == null ) { + makeScriptMaps(); + } + return scriptCodeMap; + } + +} diff --git a/src/java/org/apache/fop/complexscripts/util/DiscontinuousAssociationException.java b/src/java/org/apache/fop/complexscripts/util/DiscontinuousAssociationException.java new file mode 100644 index 000000000..daade8ca6 --- /dev/null +++ b/src/java/org/apache/fop/complexscripts/util/DiscontinuousAssociationException.java @@ -0,0 +1,41 @@ +/* + * 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.complexscripts.util; + +/** + * Exception thrown during when attempting to map glyphs to associated characters + * in the case that the associated characters do not represent a compact interval. + * @author Glenn Adams + */ +public class DiscontinuousAssociationException extends RuntimeException { + /** + * Instantiate discontinuous association exception + */ + public DiscontinuousAssociationException() { + super(); + } + /** + * Instantiate discontinuous association exception + * @param message a message string + */ + public DiscontinuousAssociationException(String message) { + super(message); + } +} diff --git a/src/java/org/apache/fop/complexscripts/util/GlyphContextTester.java b/src/java/org/apache/fop/complexscripts/util/GlyphContextTester.java new file mode 100644 index 000000000..6bdeb2298 --- /dev/null +++ b/src/java/org/apache/fop/complexscripts/util/GlyphContextTester.java @@ -0,0 +1,42 @@ +/* + * 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.complexscripts.util; + +// CSOFF: LineLengthCheck + +/** + * Interface for testing the originating (source) character context of a glyph sequence. + * @author Glenn Adams + */ +public interface GlyphContextTester { + + /** + * Perform a test on a glyph sequence in a specific (originating) character context. + * @param script governing script + * @param language governing language + * @param feature governing feature + * @param gs glyph sequence to test + * @param index index into glyph sequence to test + * @param flags that apply to lookup in scope + * @return true if test is satisfied + */ + boolean test ( String script, String language, String feature, GlyphSequence gs, int index, int flags ); + +} diff --git a/src/java/org/apache/fop/complexscripts/util/GlyphSequence.java b/src/java/org/apache/fop/complexscripts/util/GlyphSequence.java new file mode 100644 index 000000000..0e256241d --- /dev/null +++ b/src/java/org/apache/fop/complexscripts/util/GlyphSequence.java @@ -0,0 +1,1075 @@ +/* + * 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.complexscripts.util; + +import java.nio.IntBuffer; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.fop.util.CharUtilities; + +// CSOFF: InnerAssignmentCheck +// CSOFF: LineLengthCheck +// CSOFF: WhitespaceAfterCheck +// CSOFF: NoWhitespaceAfterCheck + +/** + * A GlyphSequence encapsulates a sequence of character codes, a sequence of glyph codes, + * and a sequence of character associations, where, for each glyph in the sequence of glyph + * codes, there is a corresponding character association. Character associations server to + * relate the glyph codes in a glyph sequence to the specific characters in an original + * character code sequence with which the glyph codes are associated. + * @author Glenn Adams + */ +public class GlyphSequence implements Cloneable { + + /** default character buffer capacity in case new character buffer is created */ + private static final int DEFAULT_CHARS_CAPACITY = 8; + + /** character buffer */ + private IntBuffer characters; + /** glyph buffer */ + private IntBuffer glyphs; + /** association list */ + private List associations; + /** predications flag */ + private boolean predications; + + /** + * Instantiate a glyph sequence, reusing (i.e., not copying) the referenced + * character and glyph buffers and associations. If characters is null, then + * an empty character buffer is created. If glyphs is null, then a glyph buffer + * is created whose capacity is that of the character buffer. If associations is + * null, then identity associations are created. + * @param characters a (possibly null) buffer of associated (originating) characters + * @param glyphs a (possibly null) buffer of glyphs + * @param associations a (possibly null) array of glyph to character associations + * @param predications true if predications are enabled + */ + public GlyphSequence ( IntBuffer characters, IntBuffer glyphs, List associations, boolean predications ) { + if ( characters == null ) { + characters = IntBuffer.allocate ( DEFAULT_CHARS_CAPACITY ); + } + if ( glyphs == null ) { + glyphs = IntBuffer.allocate ( characters.capacity() ); + } + if ( associations == null ) { + associations = makeIdentityAssociations ( characters.limit(), glyphs.limit() ); + } + this.characters = characters; + this.glyphs = glyphs; + this.associations = associations; + this.predications = predications; + } + + /** + * Instantiate a glyph sequence, reusing (i.e., not copying) the referenced + * character and glyph buffers and associations. If characters is null, then + * an empty character buffer is created. If glyphs is null, then a glyph buffer + * is created whose capacity is that of the character buffer. If associations is + * null, then identity associations are created. + * @param characters a (possibly null) buffer of associated (originating) characters + * @param glyphs a (possibly null) buffer of glyphs + * @param associations a (possibly null) array of glyph to character associations + */ + public GlyphSequence ( IntBuffer characters, IntBuffer glyphs, List associations ) { + this ( characters, glyphs, associations, false ); + } + + /** + * Instantiate a glyph sequence using an existing glyph sequence, where the new glyph sequence shares + * the character array of the existing sequence (but not the buffer object), and creates new copies + * of glyphs buffer and association list. + * @param gs an existing glyph sequence + */ + public GlyphSequence ( GlyphSequence gs ) { + this ( gs.characters.duplicate(), copyBuffer ( gs.glyphs ), copyAssociations ( gs.associations ), gs.predications ); + } + + /** + * Instantiate a glyph sequence using an existing glyph sequence, where the new glyph sequence shares + * the character array of the existing sequence (but not the buffer object), but uses the specified + * backtrack, input, and lookahead glyph arrays to populate the glyphs, and uses the specified + * of glyphs buffer and association list. + * backtrack, input, and lookahead association arrays to populate the associations. + * @param gs an existing glyph sequence + * @param bga backtrack glyph array + * @param iga input glyph array + * @param lga lookahead glyph array + * @param bal backtrack association list + * @param ial input association list + * @param lal lookahead association list + */ + public GlyphSequence ( GlyphSequence gs, int[] bga, int[] iga, int[] lga, CharAssociation[] bal, CharAssociation[] ial, CharAssociation[] lal ) { + this ( gs.characters.duplicate(), concatGlyphs ( bga, iga, lga ), concatAssociations ( bal, ial, lal ), gs.predications ); + } + + /** + * Obtain reference to underlying character buffer. + * @return character buffer reference + */ + public IntBuffer getCharacters() { + return characters; + } + + /** + * Obtain array of characters. If copy is true, then + * a newly instantiated array is returned, otherwise a reference to + * the underlying buffer's array is returned. N.B. in case a reference + * to the undelying buffer's array is returned, the length + * of the array is not necessarily the number of characters in array. + * To determine the number of characters, use {@link #getCharacterCount}. + * @param copy true if to return a newly instantiated array of characters + * @return array of characters + */ + public int[] getCharacterArray ( boolean copy ) { + if ( copy ) { + return toArray ( characters ); + } else { + return characters.array(); + } + } + + /** + * Obtain the number of characters in character array, where + * each character constitutes a unicode scalar value. + * @return number of characters available in character array + */ + public int getCharacterCount() { + return characters.limit(); + } + + /** + * Obtain glyph id at specified index. + * @param index to obtain glyph + * @return the glyph identifier of glyph at specified index + * @throws IndexOutOfBoundsException if index is less than zero + * or exceeds last valid position + */ + public int getGlyph ( int index ) throws IndexOutOfBoundsException { + return glyphs.get ( index ); + } + + /** + * Set glyph id at specified index. + * @param index to set glyph + * @param gi glyph index + * @throws IndexOutOfBoundsException if index is greater or equal to + * the limit of the underlying glyph buffer + */ + public void setGlyph ( int index, int gi ) throws IndexOutOfBoundsException { + if ( gi > 65535 ) { + gi = 65535; + } + glyphs.put ( index, gi ); + } + + /** + * Obtain reference to underlying glyph buffer. + * @return glyph buffer reference + */ + public IntBuffer getGlyphs() { + return glyphs; + } + + /** + * Obtain count glyphs starting at offset. If count is + * negative, then it is treated as if the number of available glyphs + * were specified. + * @param offset into glyph sequence + * @param count of glyphs to obtain starting at offset, or negative, + * indicating all avaialble glyphs starting at offset + * @return glyph array + */ + public int[] getGlyphs ( int offset, int count ) { + int ng = getGlyphCount(); + if ( offset < 0 ) { + offset = 0; + } else if ( offset > ng ) { + offset = ng; + } + if ( count < 0 ) { + count = ng - offset; + } + int[] ga = new int [ count ]; + for ( int i = offset, n = offset + count, k = 0; i < n; i++ ) { + if ( k < ga.length ) { + ga [ k++ ] = glyphs.get ( i ); + } + } + return ga; + } + + /** + * Obtain array of glyphs. If copy is true, then + * a newly instantiated array is returned, otherwise a reference to + * the underlying buffer's array is returned. N.B. in case a reference + * to the undelying buffer's array is returned, the length + * of the array is not necessarily the number of glyphs in array. + * To determine the number of glyphs, use {@link #getGlyphCount}. + * @param copy true if to return a newly instantiated array of glyphs + * @return array of glyphs + */ + public int[] getGlyphArray ( boolean copy ) { + if ( copy ) { + return toArray ( glyphs ); + } else { + return glyphs.array(); + } + } + + /** + * Obtain the number of glyphs in glyphs array, where + * each glyph constitutes a font specific glyph index. + * @return number of glyphs available in character array + */ + public int getGlyphCount() { + return glyphs.limit(); + } + + /** + * Obtain association at specified index. + * @param index into associations array + * @return glyph to character associations at specified index + * @throws IndexOutOfBoundsException if index is less than zero + * or exceeds last valid position + */ + public CharAssociation getAssociation ( int index ) throws IndexOutOfBoundsException { + return (CharAssociation) associations.get ( index ); + } + + /** + * Obtain reference to underlying associations list. + * @return associations list + */ + public List getAssociations() { + return associations; + } + + /** + * Obtain count associations starting at offset. + * @param offset into glyph sequence + * @param count of associations to obtain starting at offset, or negative, + * indicating all avaialble associations starting at offset + * @return associations + */ + public CharAssociation[] getAssociations ( int offset, int count ) { + int ng = getGlyphCount(); + if ( offset < 0 ) { + offset = 0; + } else if ( offset > ng ) { + offset = ng; + } + if ( count < 0 ) { + count = ng - offset; + } + CharAssociation[] aa = new CharAssociation [ count ]; + for ( int i = offset, n = offset + count, k = 0; i < n; i++ ) { + if ( k < aa.length ) { + aa [ k++ ] = (CharAssociation) associations.get ( i ); + } + } + return aa; + } + + /** + * Enable or disable predications. + * @param enable true if predications are to be enabled; otherwise false to disable + */ + public void setPredications ( boolean enable ) { + this.predications = enable; + } + + /** + * Obtain predications state. + * @return true if predications are enabled + */ + public boolean getPredications() { + return this.predications; + } + + /** + * Set predication at glyph sequence OFFSET. + * @param offset offset (index) into glyph sequence + * @param key predication key + * @param value predication value + */ + public void setPredication ( int offset, String key, Object value ) { + if ( predications ) { + CharAssociation[] aa = getAssociations ( offset, 1 ); + CharAssociation ca = aa[0]; + ca.setPredication ( key, value ); + } + } + + /** + * Get predication KEY at glyph sequence OFFSET. + * @param offset offset (index) into glyph sequence + * @param key predication key + * @return predication KEY at OFFSET or null if none exists + */ + public Object getPredication ( int offset, String key ) { + if ( predications ) { + CharAssociation[] aa = getAssociations ( offset, 1 ); + CharAssociation ca = aa[0]; + return ca.getPredication ( key ); + } else { + return null; + } + } + + /** + * Compare glyphs. + * @param gb buffer containing glyph indices with which this glyph sequence's glyphs are to be compared + * @return zero if glyphs are the same, otherwise returns 1 or -1 according to whether this glyph sequence's + * glyphs are lexicographically greater or lesser than the glyphs in the specified string buffer + */ + public int compareGlyphs ( IntBuffer gb ) { + int ng = getGlyphCount(); + for ( int i = 0, n = gb.limit(); i < n; i++ ) { + if ( i < ng ) { + int g1 = glyphs.get ( i ); + int g2 = gb.get ( i ); + if ( g1 > g2 ) { + return 1; + } else if ( g1 < g2 ) { + return -1; + } + } else { + return -1; // this gb is a proper prefix of specified gb + } + } + return 0; // same lengths with no difference + } + + /** {@inheritDoc} */ + public Object clone() { + try { + GlyphSequence gs = (GlyphSequence) super.clone(); + gs.characters = copyBuffer ( characters ); + gs.glyphs = copyBuffer ( glyphs ); + gs.associations = copyAssociations ( associations ); + return gs; + } catch ( CloneNotSupportedException e ) { + return null; + } + } + + /** {@inheritDoc} */ + public String toString() { + StringBuffer sb = new StringBuffer(); + sb.append ( '{' ); + sb.append ( "chars = [" ); + sb.append ( characters ); + sb.append ( "], glyphs = [" ); + sb.append ( glyphs ); + sb.append ( "], associations = [" ); + sb.append ( associations ); + sb.append ( "]" ); + sb.append ( '}' ); + return sb.toString(); + } + + /** + * Determine if two arrays of glyphs are identical. + * @param ga1 first glyph array + * @param ga2 second glyph array + * @return true if arrays are botth null or both non-null and have identical elements + */ + public static boolean sameGlyphs ( int[] ga1, int[] ga2 ) { + if ( ga1 == ga2 ) { + return true; + } else if ( ( ga1 == null ) || ( ga2 == null ) ) { + return false; + } else if ( ga1.length != ga2.length ) { + return false; + } else { + for ( int i = 0, n = ga1.length; i < n; i++ ) { + if ( ga1[i] != ga2[i] ) { + return false; + } + } + return true; + } + } + + /** + * Concatenante glyph arrays. + * @param bga backtrack glyph array + * @param iga input glyph array + * @param lga lookahead glyph array + * @return new integer buffer containing concatenated glyphs + */ + public static IntBuffer concatGlyphs ( int[] bga, int[] iga, int[] lga ) { + int ng = 0; + if ( bga != null ) { + ng += bga.length; + } + if ( iga != null ) { + ng += iga.length; + } + if ( lga != null ) { + ng += lga.length; + } + IntBuffer gb = IntBuffer.allocate ( ng ); + if ( bga != null ) { + gb.put ( bga ); + } + if ( iga != null ) { + gb.put ( iga ); + } + if ( lga != null ) { + gb.put ( lga ); + } + gb.flip(); + return gb; + } + + /** + * Concatenante association arrays. + * @param baa backtrack association array + * @param iaa input association array + * @param laa lookahead association array + * @return new list containing concatenated associations + */ + public static List concatAssociations ( CharAssociation[] baa, CharAssociation[] iaa, CharAssociation[] laa ) { + int na = 0; + if ( baa != null ) { + na += baa.length; + } + if ( iaa != null ) { + na += iaa.length; + } + if ( laa != null ) { + na += laa.length; + } + if ( na > 0 ) { + List gl = new ArrayList ( na ); + if ( baa != null ) { + for ( int i = 0; i < baa.length; i++ ) { + gl.add ( baa[i] ); + } + } + if ( iaa != null ) { + for ( int i = 0; i < iaa.length; i++ ) { + gl.add ( iaa[i] ); + } + } + if ( laa != null ) { + for ( int i = 0; i < laa.length; i++ ) { + gl.add ( laa[i] ); + } + } + return gl; + } else { + return null; + } + } + + /** + * Join (concatenate) glyph sequences. + * @param gs original glyph sequence from which to reuse character array reference + * @param sa array of glyph sequences, whose glyph arrays and association lists are to be concatenated + * @return new glyph sequence referring to character array of GS and concatenated glyphs and associations of SA + */ + public static GlyphSequence join ( GlyphSequence gs, GlyphSequence[] sa ) { + assert sa != null; + int tg = 0; + int ta = 0; + for ( int i = 0, n = sa.length; i < n; i++ ) { + GlyphSequence s = sa [ i ]; + IntBuffer ga = s.getGlyphs(); + assert ga != null; + int ng = ga.limit(); + List al = s.getAssociations(); + assert al != null; + int na = al.size(); + assert na == ng; + tg += ng; + ta += na; + } + IntBuffer uga = IntBuffer.allocate ( tg ); + ArrayList ual = new ArrayList ( ta ); + for ( int i = 0, n = sa.length; i < n; i++ ) { + GlyphSequence s = sa [ i ]; + uga.put ( s.getGlyphs() ); + ual.addAll ( s.getAssociations() ); + } + return new GlyphSequence ( gs.getCharacters(), uga, ual, gs.getPredications() ); + } + + /** + * Reorder sequence such that [SOURCE,SOURCE+COUNT) is moved just prior to TARGET. + * @param gs input sequence + * @param source index of sub-sequence to reorder + * @param count length of sub-sequence to reorder + * @param target index to which source sub-sequence is to be moved + * @return reordered sequence (or original if no reordering performed) + */ + public static GlyphSequence reorder ( GlyphSequence gs, int source, int count, int target ) { + if ( source != target ) { + int ng = gs.getGlyphCount(); + int[] ga = gs.getGlyphArray ( false ); + int[] nga = new int [ ng ]; + GlyphSequence.CharAssociation[] aa = gs.getAssociations ( 0, ng ); + GlyphSequence.CharAssociation[] naa = new GlyphSequence.CharAssociation [ ng ]; + if ( source < target ) { + int t = 0; + for ( int s = 0, e = source; s < e; s++, t++ ) { + nga[t] = ga[s]; + naa[t] = aa[s]; + } + for ( int s = source + count, e = target; s < e; s++, t++ ) { + nga[t] = ga[s]; + naa[t] = aa[s]; + } + for ( int s = source, e = source + count; s < e; s++, t++ ) { + nga[t] = ga[s]; + naa[t] = aa[s]; + } + for ( int s = target, e = ng; s < e; s++, t++ ) { + nga[t] = ga[s]; + naa[t] = aa[s]; + } + } else { + int t = 0; + for ( int s = 0, e = target; s < e; s++, t++ ) { + nga[t] = ga[s]; + naa[t] = aa[s]; + } + for ( int s = source, e = source + count; s < e; s++, t++ ) { + nga[t] = ga[s]; + naa[t] = aa[s]; + } + for ( int s = target, e = source; s < e; s++, t++ ) { + nga[t] = ga[s]; + naa[t] = aa[s]; + } + for ( int s = source + count, e = ng; s < e; s++, t++ ) { + nga[t] = ga[s]; + naa[t] = aa[s]; + } + } + return new GlyphSequence ( gs, null, nga, null, null, naa, null ); + } else { + return gs; + } + } + + private static int[] toArray ( IntBuffer ib ) { + if ( ib != null ) { + int n = ib.limit(); + int[] ia = new int[n]; + ib.get ( ia, 0, n ); + return ia; + } else { + return new int[0]; + } + } + + private static List makeIdentityAssociations ( int numChars, int numGlyphs ) { + int nc = numChars; + int ng = numGlyphs; + List av = new ArrayList ( ng ); + for ( int i = 0, n = ng; i < n; i++ ) { + int k = ( i > nc ) ? nc : i; + av.add ( new CharAssociation ( i, ( k == nc ) ? 0 : 1 ) ); + } + return av; + } + + private static IntBuffer copyBuffer ( IntBuffer ib ) { + if ( ib != null ) { + int[] ia = new int [ ib.capacity() ]; + int p = ib.position(); + int l = ib.limit(); + System.arraycopy ( ib.array(), 0, ia, 0, ia.length ); + return IntBuffer.wrap ( ia, p, l - p ); + } else { + return null; + } + } + + private static List copyAssociations ( List ca ) { + if ( ca != null ) { + return new ArrayList ( ca ); + } else { + return ca; + } + } + + /** + * A structure class encapsulating an interval of characters + * expressed as an offset and count of Unicode scalar values (in + * an IntBuffer). A CharAssociation is used to + * maintain a backpointer from a glyph to one or more character + * intervals from which the glyph was derived. + * + * Each glyph in a glyph sequence is associated with a single + * CharAssociation instance. + * + * A CharAssociation instance is additionally (and + * optionally) used to record predication information about the + * glyph, such as whether the glyph was produced by the + * application of a specific substitution table or whether its + * position was adjusted by a specific poisitioning table. + */ + public static class CharAssociation implements Cloneable { + + // instance state + private final int offset; + private final int count; + private final int[] subIntervals; + private Map predications; + + // class state + private static volatile Map predicationMergers; + + interface PredicationMerger { + Object merge ( String key, Object v1, Object v2 ); + } + + /** + * Instantiate a character association. + * @param offset into array of Unicode scalar values (in associated IntBuffer) + * @param count of Unicode scalar values (in associated IntBuffer) + * @param subIntervals if disjoint, then array of sub-intervals, otherwise null; even + * members of array are sub-interval starts, and odd members are sub-interval + * ends (exclusive) + */ + public CharAssociation ( int offset, int count, int[] subIntervals ) { + this.offset = offset; + this.count = count; + this.subIntervals = ( ( subIntervals != null ) && ( subIntervals.length > 2 ) ) ? subIntervals : null; + } + + /** + * Instantiate a non-disjoint character association. + * @param offset into array of UTF-16 code elements (in associated CharSequence) + * @param count of UTF-16 character code elements (in associated CharSequence) + */ + public CharAssociation ( int offset, int count ) { + this ( offset, count, null ); + } + + /** + * Instantiate a non-disjoint character association. + * @param subIntervals if disjoint, then array of sub-intervals, otherwise null; even + * members of array are sub-interval starts, and odd members are sub-interval + * ends (exclusive) + */ + public CharAssociation ( int[] subIntervals ) { + this ( getSubIntervalsStart ( subIntervals ), getSubIntervalsLength ( subIntervals ), subIntervals ); + } + + /** @return offset (start of association interval) */ + public int getOffset() { + return offset; + } + + /** @return count (number of characer codes in association) */ + public int getCount() { + return count; + } + + /** @return start of association interval */ + public int getStart() { + return getOffset(); + } + + /** @return end of association interval */ + public int getEnd() { + return getOffset() + getCount(); + } + + /** @return true if association is disjoint */ + public boolean isDisjoint() { + return subIntervals != null; + } + + /** @return subintervals of disjoint association */ + public int[] getSubIntervals() { + return subIntervals; + } + + /** @return count of subintervals of disjoint association */ + public int getSubIntervalCount() { + return ( subIntervals != null ) ? ( subIntervals.length / 2 ) : 0; + } + + /** + * @param offset of interval in sequence + * @param count length of interval + * @return true if this association is contained within [offset,offset+count) + */ + public boolean contained ( int offset, int count ) { + int s = offset; + int e = offset + count; + if ( ! isDisjoint() ) { + int s0 = getStart(); + int e0 = getEnd(); + return ( s0 >= s ) && ( e0 <= e ); + } else { + int ns = getSubIntervalCount(); + for ( int i = 0; i < ns; i++ ) { + int s0 = subIntervals [ 2 * i + 0 ]; + int e0 = subIntervals [ 2 * i + 1 ]; + if ( ( s0 >= s ) && ( e0 <= e ) ) { + return true; + } + } + return false; + } + } + + /** + * Set predication . + * @param key predication key + * @param value predication value + */ + public void setPredication ( String key, Object value ) { + if ( predications == null ) { + predications = new HashMap(); + } + if ( predications != null ) { + predications.put ( key, value ); + } + } + + /** + * Get predication KEY. + * @param key predication key + * @return predication KEY at OFFSET or null if none exists + */ + public Object getPredication ( String key ) { + if ( predications != null ) { + return predications.get ( key ); + } else { + return null; + } + } + + /** + * Merge predication . + * @param key predication key + * @param value predication value + */ + public void mergePredication ( String key, Object value ) { + if ( predications == null ) { + predications = new HashMap(); + } + if ( predications != null ) { + if ( predications.containsKey ( key ) ) { + Object v1 = predications.get ( key ); + Object v2 = value; + predications.put ( key, mergePredicationValues ( key, v1, v2 ) ); + } else { + predications.put ( key, value ); + } + } + } + + /** + * Merge predication values V1 and V2 on KEY. Uses registered PredicationMerger + * if one exists, otherwise uses V2 if non-null, otherwise uses V1. + * @param key predication key + * @param v1 first (original) predication value + * @param v2 second (to be merged) predication value + * @return merged value + */ + public static Object mergePredicationValues ( String key, Object v1, Object v2 ) { + PredicationMerger pm = getPredicationMerger ( key ); + if ( pm != null ) { + return pm.merge ( key, v1, v2 ); + } else if ( v2 != null ) { + return v2; + } else { + return v1; + } + } + + /** + * Merge predications from another CA. + * @param ca from which to merge + */ + public void mergePredications ( CharAssociation ca ) { + if ( ca.predications != null ) { + for ( Map.Entry e : ca.predications.entrySet() ) { + mergePredication ( e.getKey(), e.getValue() ); + } + } + } + + /** {@inheritDoc} */ + public Object clone() { + try { + CharAssociation ca = (CharAssociation) super.clone(); + if ( predications != null ) { + ca.predications = new HashMap ( predications ); + } + return ca; + } catch ( CloneNotSupportedException e ) { + return null; + } + } + + /** + * Register predication merger PM for KEY. + * @param key for predication merger + * @param pm predication merger + */ + public static void setPredicationMerger ( String key, PredicationMerger pm ) { + if ( predicationMergers == null ) { + predicationMergers = new HashMap(); + } + if ( predicationMergers != null ) { + predicationMergers.put ( key, pm ); + } + } + + /** + * Obtain predication merger for KEY. + * @param key for predication merger + * @return predication merger or null if none exists + */ + public static PredicationMerger getPredicationMerger ( String key ) { + if ( predicationMergers != null ) { + return predicationMergers.get ( key ); + } else { + return null; + } + } + + /** + * Replicate association to form repeat new associations. + * @param a association to replicate + * @param repeat count + * @return array of replicated associations + */ + public static CharAssociation[] replicate ( CharAssociation a, int repeat ) { + CharAssociation[] aa = new CharAssociation [ repeat ]; + for ( int i = 0, n = aa.length; i < n; i++ ) { + aa [ i ] = (CharAssociation) a.clone(); + } + return aa; + } + + /** + * Join (merge) multiple associations into a single, potentially disjoint + * association. + * @param aa array of associations to join + * @return (possibly disjoint) association containing joined associations + */ + public static CharAssociation join ( CharAssociation[] aa ) { + CharAssociation ca; + // extract sorted intervals + int[] ia = extractIntervals ( aa ); + if ( ( ia == null ) || ( ia.length == 0 ) ) { + ca = new CharAssociation ( 0, 0 ); + } else if ( ia.length == 2 ) { + int s = ia[0]; + int e = ia[1]; + ca = new CharAssociation ( s, e - s ); + } else { + ca = new CharAssociation ( mergeIntervals ( ia ) ); + } + return mergePredicates ( ca, aa ); + } + + private static CharAssociation mergePredicates ( CharAssociation ca, CharAssociation[] aa ) { + for ( CharAssociation a : aa ) { + ca.mergePredications ( a ); + } + return ca; + } + + private static int getSubIntervalsStart ( int[] ia ) { + int us = Integer.MAX_VALUE; + int ue = Integer.MIN_VALUE; + if ( ia != null ) { + for ( int i = 0, n = ia.length; i < n; i += 2 ) { + int s = ia [ i + 0 ]; + int e = ia [ i + 1 ]; + if ( s < us ) { + us = s; + } + if ( e > ue ) { + ue = e; + } + } + if ( ue < 0 ) { + ue = 0; + } + if ( us > ue ) { + us = ue; + } + } + return us; + } + + private static int getSubIntervalsLength ( int[] ia ) { + int us = Integer.MAX_VALUE; + int ue = Integer.MIN_VALUE; + if ( ia != null ) { + for ( int i = 0, n = ia.length; i < n; i += 2 ) { + int s = ia [ i + 0 ]; + int e = ia [ i + 1 ]; + if ( s < us ) { + us = s; + } + if ( e > ue ) { + ue = e; + } + } + if ( ue < 0 ) { + ue = 0; + } + if ( us > ue ) { + us = ue; + } + } + return ue - us; + } + + /** + * Extract sorted sub-intervals. + */ + private static int[] extractIntervals ( CharAssociation[] aa ) { + int ni = 0; + for ( int i = 0, n = aa.length; i < n; i++ ) { + CharAssociation a = aa [ i ]; + if ( a.isDisjoint() ) { + ni += a.getSubIntervalCount(); + } else { + ni += 1; + } + } + int[] sa = new int [ ni ]; + int[] ea = new int [ ni ]; + for ( int i = 0, k = 0; i < aa.length; i++ ) { + CharAssociation a = aa [ i ]; + if ( a.isDisjoint() ) { + int[] da = a.getSubIntervals(); + for ( int j = 0; j < da.length; j += 2 ) { + sa [ k ] = da [ j + 0 ]; + ea [ k ] = da [ j + 1 ]; + k++; + } + } else { + sa [ k ] = a.getStart(); + ea [ k ] = a.getEnd(); + k++; + } + } + return sortIntervals ( sa, ea ); + } + + private static final int[] sortIncrements16 // CSOK: ConstantNameCheck + = { 1391376, 463792, 198768, 86961, 33936, 13776, 4592, 1968, 861, 336, 112, 48, 21, 7, 3, 1 }; + + private static final int[] sortIncrements03 // CSOK: ConstantNameCheck + = { 7, 3, 1 }; + + /** + * Sort sub-intervals using modified Shell Sort. + */ + private static int[] sortIntervals ( int[] sa, int[] ea ) { + assert sa != null; + assert ea != null; + assert sa.length == ea.length; + int ni = sa.length; + int[] incr = ( ni < 21 ) ? sortIncrements03 : sortIncrements16; + for ( int k = 0; k < incr.length; k++ ) { + for ( int h = incr [ k ], i = h, n = ni, j; i < n; i++ ) { + int s1 = sa [ i ]; + int e1 = ea [ i ]; + for ( j = i; j >= h; j -= h) { + int s2 = sa [ j - h ]; + int e2 = ea [ j - h ]; + if ( s2 > s1 ) { + sa [ j ] = s2; + ea [ j ] = e2; + } else if ( ( s2 == s1 ) && ( e2 > e1 ) ) { + sa [ j ] = s2; + ea [ j ] = e2; + } else { + break; + } + } + sa [ j ] = s1; + ea [ j ] = e1; + } + } + int[] ia = new int [ ni * 2 ]; + for ( int i = 0; i < ni; i++ ) { + ia [ ( i * 2 ) + 0 ] = sa [ i ]; + ia [ ( i * 2 ) + 1 ] = ea [ i ]; + } + return ia; + } + + /** + * Merge overlapping and abutting sub-intervals. + */ + private static int[] mergeIntervals ( int[] ia ) { + int ni = ia.length; + int i, n, nm, is, ie; + // count merged sub-intervals + for ( i = 0, n = ni, nm = 0, is = ie = -1; i < n; i += 2 ) { + int s = ia [ i + 0 ]; + int e = ia [ i + 1 ]; + if ( ( ie < 0 ) || ( s > ie ) ) { + is = s; + ie = e; + nm++; + } else if ( s >= is ) { + if ( e > ie ) { + ie = e; + } + } + } + int[] mi = new int [ nm * 2 ]; + // populate merged sub-intervals + for ( i = 0, n = ni, nm = 0, is = ie = -1; i < n; i += 2 ) { + int s = ia [ i + 0 ]; + int e = ia [ i + 1 ]; + int k = nm * 2; + if ( ( ie < 0 ) || ( s > ie ) ) { + is = s; + ie = e; + mi [ k + 0 ] = is; + mi [ k + 1 ] = ie; + nm++; + } else if ( s >= is ) { + if ( e > ie ) { + ie = e; + } + mi [ k - 1 ] = ie; + } + } + return mi; + } + + } + +} diff --git a/src/java/org/apache/fop/complexscripts/util/GlyphTester.java b/src/java/org/apache/fop/complexscripts/util/GlyphTester.java new file mode 100644 index 000000000..48d0444a0 --- /dev/null +++ b/src/java/org/apache/fop/complexscripts/util/GlyphTester.java @@ -0,0 +1,36 @@ +/* + * 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.complexscripts.util; + +/** + * Interface for testing glyph properties according to glyph identifier. + * @author Glenn Adams + */ +public interface GlyphTester { + + /** + * Perform a test on a glyph identifier. + * @param gi glyph identififer + * @param flags that apply to lookup in scope + * @return true if test is satisfied + */ + boolean test ( int gi, int flags ); + +} diff --git a/src/java/org/apache/fop/complexscripts/util/NumberConverter.java b/src/java/org/apache/fop/complexscripts/util/NumberConverter.java new file mode 100644 index 000000000..6d9831249 --- /dev/null +++ b/src/java/org/apache/fop/complexscripts/util/NumberConverter.java @@ -0,0 +1,1616 @@ +/* + * 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.complexscripts.util; + +import java.util.ArrayList; +import java.util.List; + +// CSOFF: LineLengthCheck +// CSOFF: InnerAssignmentCheck +// CSOFF: NoWhitespaceAfterCheck +// CSOFF: AvoidNestedBlocksCheck + +/** + * Implementation of Number to String Conversion algorithm specified by + * XSL Transformations (XSLT) Version 2.0, W3C Recommendation, 23 January 2007. + * + * This algorithm differs from that specified in XSLT 1.0 in the following + * ways: + *
    + *
  • input numbers are greater than or equal to zero rather than greater than zero;
  • + *
  • introduces format tokens { w, W, Ww };
  • + *
  • introduces ordinal parameter to generate ordinal numbers;
  • + *
+ * + * Implementation Defaults and Limitations + *
    + *
  • If language parameter is unspecified (null or empty string), then the value + * of DEFAULT_LANGUAGE is used, which is defined below as "eng" (English).
  • + *
  • Only English, French, and Spanish word numerals are supported, and only if less than one trillion (1,000,000,000,000).
  • + *
  • Ordinal word numerals are supported for French and Spanish only when less than or equal to ten (10).
  • + *
+ * + * Implementation Notes + *
    + *
  • In order to handle format tokens outside the Unicode BMP, all processing is + * done in Unicode Scalar Values represented with Integer and Integer[] + * types. Without affecting behavior, this may be subsequently optimized to + * use int and int[] types.
  • + *
  • In order to communicate various sub-parameters, including ordinalization, a features + * is employed, which consists of comma separated name and optional value tokens, where name and value + * are separated by an equals '=' sign.
  • + *
  • Ordinal numbers are selected by specifying a word based format token in combination with a 'ordinal' feature with no value, in which case + * the features 'male' and 'female' may be used to specify gender for gender sensitive languages. For example, the feature string "ordinal,female" + * selects female ordinals.
  • + *
+ * + * @author Glenn Adams + */ +public class NumberConverter { + + /** alphabetical */ + public static final int LETTER_VALUE_ALPHABETIC = 1; + /** traditional */ + public static final int LETTER_VALUE_TRADITIONAL = 2; + + /** no token type */ + private static final int TOKEN_NONE = 0; + /** alhphanumeric token type */ + private static final int TOKEN_ALPHANUMERIC = 1; + /** nonalphanumeric token type */ + private static final int TOKEN_NONALPHANUMERIC = 2; + /** default token */ + private static final Integer[] DEFAULT_TOKEN = new Integer[] { (int) '1' }; + /** default separator */ + private static final Integer[] DEFAULT_SEPARATOR = new Integer[] { (int) '.' }; + /** default language */ + private static final String DEFAULT_LANGUAGE = "eng"; + + /** prefix token */ + private Integer[] prefix; + /** suffix token */ + private Integer[] suffix; + /** sequence of tokens, as parsed from format */ + private Integer[][] tokens; + /** sequence of separators, as parsed from format */ + private Integer[][] separators; + /** grouping separator */ + private int groupingSeparator; + /** grouping size */ + private int groupingSize; + /** letter value */ + private int letterValue; + /** letter value system */ + private String features; + /** language */ + private String language; + /** country */ + private String country; + + /** + * Construct parameterized number converter. + * @param format format for the page number (may be null or empty, which is treated as null) + * @param groupingSeparator grouping separator (if zero, then no grouping separator applies) + * @param groupingSize grouping size (if zero or negative, then no grouping size applies) + * @param letterValue letter value (must be one of the above letter value enumeration values) + * @param features features (feature sub-parameters) + * @param language (may be null or empty, which is treated as null) + * @param country (may be null or empty, which is treated as null) + * @throws IllegalArgumentException if format is not a valid UTF-16 string (e.g., has unpaired surrogate) + */ + public NumberConverter ( String format, int groupingSeparator, int groupingSize, int letterValue, String features, String language, String country ) + throws IllegalArgumentException { + this.groupingSeparator = groupingSeparator; + this.groupingSize = groupingSize; + this.letterValue = letterValue; + this.features = features; + this.language = ( language != null ) ? language.toLowerCase() : null; + this.country = ( country != null ) ? country.toLowerCase() : null; + parseFormatTokens ( format ); + } + + /** + * Convert a number to string according to conversion parameters. + * @param number number to conver + * @return string representing converted number + */ + public String convert ( long number ) { + List numbers = new ArrayList(); + numbers.add ( number ); + return convert ( numbers ); + } + + /** + * Convert list of numbers to string according to conversion parameters. + * @param numbers list of numbers to convert + * @return string representing converted list of numbers + */ + public String convert ( List numbers ) { + List scalars = new ArrayList(); + if ( prefix != null ) { + appendScalars ( scalars, prefix ); + } + convertNumbers ( scalars, numbers ); + if ( suffix != null ) { + appendScalars ( scalars, suffix ); + } + return scalarsToString ( scalars ); + } + + private void parseFormatTokens ( String format ) throws IllegalArgumentException { + List tokens = new ArrayList(); + List separators = new ArrayList(); + if ( ( format == null ) || ( format.length() == 0 ) ) { + format = "1"; + } + int tokenType = TOKEN_NONE; + List token = new ArrayList(); + Integer[] ca = UTF32.toUTF32 ( format, 0, true ); + for ( int i = 0, n = ca.length; i < n; i++ ) { + int c = ca[i]; + int tokenTypeNew = isAlphaNumeric ( c ) ? TOKEN_ALPHANUMERIC : TOKEN_NONALPHANUMERIC; + if ( tokenTypeNew != tokenType ) { + if ( token.size() > 0 ) { + if ( tokenType == TOKEN_ALPHANUMERIC ) { + tokens.add ( token.toArray ( new Integer [ token.size() ] ) ); + } else { + separators.add ( token.toArray ( new Integer [ token.size() ] ) ); + } + token.clear(); + } + tokenType = tokenTypeNew; + } + token.add ( c ); + } + if ( token.size() > 0 ) { + if ( tokenType == TOKEN_ALPHANUMERIC ) { + tokens.add ( token.toArray ( new Integer [ token.size() ] ) ); + } else { + separators.add ( token.toArray ( new Integer [ token.size() ] ) ); + } + } + if ( ! separators.isEmpty() ) { + this.prefix = separators.remove ( 0 ); + } + if ( ! separators.isEmpty() ) { + this.suffix = separators.remove ( separators.size() - 1 ); + } + this.separators = separators.toArray ( new Integer [ separators.size() ] [] ); + this.tokens = tokens.toArray ( new Integer [ tokens.size() ] [] ); + } + + private static boolean isAlphaNumeric ( int c ) { + switch ( Character.getType ( c ) ) { + case Character.DECIMAL_DIGIT_NUMBER: // Nd + case Character.LETTER_NUMBER: // Nl + case Character.OTHER_NUMBER: // No + case Character.UPPERCASE_LETTER: // Lu + case Character.LOWERCASE_LETTER: // Ll + case Character.TITLECASE_LETTER: // Lt + case Character.MODIFIER_LETTER: // Lm + case Character.OTHER_LETTER: // Lo + return true; + default: + return false; + } + } + + private void convertNumbers ( List scalars, List numbers ) { + Integer[] tknLast = DEFAULT_TOKEN; + int tknIndex = 0; + int tknCount = tokens.length; + int sepIndex = 0; + int sepCount = separators.length; + int numIndex = 0; + for ( Long number : numbers ) { + Integer[] sep = null; + Integer[] tkn; + if ( tknIndex < tknCount ) { + if ( numIndex > 0 ) { + if ( sepIndex < sepCount ) { + sep = separators [ sepIndex++ ]; + } else { + sep = DEFAULT_SEPARATOR; + } + } + tkn = tokens [ tknIndex++ ]; + } else { + tkn = tknLast; + } + appendScalars ( scalars, convertNumber ( number, sep, tkn ) ); + tknLast = tkn; + numIndex++; + } + } + + private Integer[] convertNumber ( long number, Integer[] separator, Integer[] token ) { + List sl = new ArrayList(); + if ( separator != null ) { + appendScalars ( sl, separator ); + } + if ( token != null ) { + appendScalars ( sl, formatNumber ( number, token ) ); + } + return sl.toArray ( new Integer [ sl.size() ] ); + } + + private Integer[] formatNumber ( long number, Integer[] token ) { + Integer[] fn = null; + assert token.length > 0; + if ( number < 0 ) { + throw new IllegalArgumentException ( "number must be non-negative" ); + } else if ( token.length == 1 ) { + int s = token[0].intValue(); + switch ( s ) { + case (int) '1': + { + fn = formatNumberAsDecimal ( number, (int) '1', 1 ); + break; + } + case (int) 'W': + case (int) 'w': + { + fn = formatNumberAsWord ( number, ( s == (int) 'W' ) ? Character.UPPERCASE_LETTER : Character.LOWERCASE_LETTER ); + break; + } + case (int) 'A': // handled as numeric sequence + case (int) 'a': // handled as numeric sequence + case (int) 'I': // handled as numeric special + case (int) 'i': // handled as numeric special + default: + { + if ( isStartOfDecimalSequence ( s ) ) { + fn = formatNumberAsDecimal ( number, s, 1 ); + } else if ( isStartOfAlphabeticSequence ( s ) ) { + fn = formatNumberAsSequence ( number, s, getSequenceBase ( s ), null ); + } else if ( isStartOfNumericSpecial ( s ) ) { + fn = formatNumberAsSpecial ( number, s ); + } else { + fn = null; + } + break; + } + } + } else if ( ( token.length == 2 ) && ( token[0] == (int) 'W' ) && ( token[1] == (int) 'w' ) ) { + fn = formatNumberAsWord ( number, Character.TITLECASE_LETTER ); + } else if ( isPaddedOne ( token ) ) { + int s = token [ token.length - 1 ].intValue(); + fn = formatNumberAsDecimal ( number, s, token.length ); + } else { + throw new IllegalArgumentException ( "invalid format token: \"" + UTF32.fromUTF32 ( token ) + "\"" ); + } + if ( fn == null ) { + fn = formatNumber ( number, DEFAULT_TOKEN ); + } + assert fn != null; + return fn; + } + + /** + * Format NUMBER as decimal using characters denoting digits that start at ONE, + * adding one or more (zero) padding characters as needed to fill out field WIDTH. + * @param number to be formatted + * @param one unicode scalar value denoting numeric value 1 + * @param width non-negative integer denoting field width of number, possible including padding + * @return formatted number as array of unicode scalars + */ + private Integer[] formatNumberAsDecimal ( long number, int one, int width ) { + assert Character.getNumericValue ( one ) == 1; + assert Character.getNumericValue ( one - 1 ) == 0; + assert Character.getNumericValue ( one + 8 ) == 9; + List sl = new ArrayList(); + int zero = one - 1; + while ( number > 0 ) { + long digit = number % 10; + sl.add ( 0, zero + (int) digit ); + number = number / 10; + } + while ( width > sl.size() ) { + sl.add ( 0, zero ); + } + if ( ( groupingSize != 0 ) && ( groupingSeparator != 0 ) ) { + sl = performGrouping ( sl, groupingSize, groupingSeparator ); + } + return sl.toArray ( new Integer [ sl.size() ] ); + } + + private static List performGrouping ( List sl, int groupingSize, int groupingSeparator ) { + assert groupingSize > 0; + assert groupingSeparator != 0; + if ( sl.size() > groupingSize ) { + List gl = new ArrayList(); + for ( int i = 0, n = sl.size(), g = 0; i < n; i++ ) { + int k = n - i - 1; + if ( g == groupingSize ) { + gl.add ( 0, groupingSeparator ); + g = 1; + } else { + g++; + } + gl.add ( 0, sl.get ( k ) ); + } + return gl; + } else { + return sl; + } + } + + + /** + * Format NUMBER as using sequence of characters that start at ONE, and + * having BASE radix. + * @param number to be formatted + * @param one unicode scalar value denoting start of sequence (numeric value 1) + * @param base number of elements in sequence + * @param map if non-null, then maps sequences indices to unicode scalars + * @return formatted number as array of unicode scalars + */ + private Integer[] formatNumberAsSequence ( long number, int one, int base, int[] map ) { + assert base > 1; + assert ( map == null ) || ( map.length >= base ); + List sl = new ArrayList(); + if ( number == 0 ) { + return null; + } else { + long n = number; + while ( n > 0 ) { + int d = (int) ( ( n - 1 ) % (long) base ); + int s = ( map != null ) ? map [ d ] : ( one + d ); + sl.add ( 0, s ); + n = ( n - 1 ) / base; + } + return sl.toArray ( new Integer [ sl.size() ] ); + } + } + + /** + * Format NUMBER as using special system that starts at ONE. + * @param number to be formatted + * @param one unicode scalar value denoting start of system (numeric value 1) + * @return formatted number as array of unicode scalars + */ + private Integer[] formatNumberAsSpecial ( long number, int one ) { + SpecialNumberFormatter f = getSpecialFormatter ( one, letterValue, features, language, country ); + if ( f != null ) { + return f.format ( number, one, letterValue, features, language, country ); + } else { + return null; + } + } + + /** + * Format NUMBER as word according to TYPE, which must be either + * Character.UPPERCASE_LETTER, Character.LOWERCASE_LETTER, or + * Character.TITLECASE_LETTER. Makes use of this.language to + * determine language of word. + * @param number to be formatted + * @param caseType unicode character type for case conversion + * @return formatted number as array of unicode scalars + */ + private Integer[] formatNumberAsWord ( long number, int caseType ) { + SpecialNumberFormatter f = null; + if ( isLanguage ( "eng" ) ) { + f = new EnglishNumberAsWordFormatter ( caseType ); + } else if ( isLanguage ( "spa" ) ) { + f = new SpanishNumberAsWordFormatter ( caseType ); + } else if ( isLanguage ( "fra" ) ) { + f = new FrenchNumberAsWordFormatter ( caseType ); + } else { + f = new EnglishNumberAsWordFormatter ( caseType ); + } + return f.format ( number, 0, letterValue, features, language, country ); + } + + private boolean isLanguage ( String iso3Code ) { + if ( language == null ) { + return false; + } else if ( language.equals ( iso3Code ) ) { + return true; + } else { + return isSameLanguage ( iso3Code, language ); + } + } + + private static String[][] equivalentLanguages = { + { "eng", "en" }, + { "fra", "fre", "fr" }, + { "spa", "es" }, + }; + + private static boolean isSameLanguage ( String i3c, String lc ) { + for ( String[] el : equivalentLanguages ) { + assert el.length >= 2; + if ( el[0].equals ( i3c ) ) { + for ( int i = 0, n = el.length; i < n; i++ ) { + if ( el[i].equals ( lc ) ) { + return true; + } + } + return false; + } + } + return false; + } + + private static boolean hasFeature ( String features, String feature ) { + if ( features != null ) { + assert feature != null; + assert feature.length() != 0; + String[] fa = features.split(","); + for ( String f : fa ) { + String[] fp = f.split("="); + assert fp.length > 0; + String fn = fp[0]; + String fv = ( fp.length > 1 ) ? fp[1] : ""; + if ( fn.equals ( feature ) ) { + return true; + } + } + } + return false; + } + + /* not yet used + private static String getFeatureValue ( String features, String feature ) { + if ( features != null ) { + assert feature != null; + assert feature.length() != 0; + String[] fa = features.split(","); + for ( String f : fa ) { + String[] fp = f.split("="); + assert fp.length > 0; + String fn = fp[0]; + String fv = ( fp.length > 1 ) ? fp[1] : ""; + if ( fn.equals ( feature ) ) { + return fv; + } + } + } + return ""; + } + */ + + private static void appendScalars ( List scalars, Integer[] sa ) { + for ( Integer s : sa ) { + scalars.add ( s ); + } + } + + private static String scalarsToString ( List scalars ) { + Integer[] sa = scalars.toArray ( new Integer [ scalars.size() ] ); + return UTF32.fromUTF32 ( sa ); + } + + private static boolean isPaddedOne ( Integer[] token ) { + if ( getDecimalValue ( token [ token.length - 1 ] ) != 1 ) { + return false; + } else { + for ( int i = 0, n = token.length - 1; i < n; i++ ) { + if ( getDecimalValue ( token [ i ] ) != 0 ) { + return false; + } + } + return true; + } + } + + private static int getDecimalValue ( Integer scalar ) { + int s = scalar.intValue(); + if ( Character.getType ( s ) == Character.DECIMAL_DIGIT_NUMBER ) { + return Character.getNumericValue ( s ); + } else { + return -1; + } + } + + private static boolean isStartOfDecimalSequence ( int s ) { + return ( Character.getNumericValue ( s ) == 1 ) + && ( Character.getNumericValue ( s - 1 ) == 0 ) + && ( Character.getNumericValue ( s + 8 ) == 9 ); + } + + private static int[][] supportedAlphabeticSequences = { + { 'A', 26 }, // A...Z + { 'a', 26 }, // a...z + }; + + private static boolean isStartOfAlphabeticSequence ( int s ) { + for ( int[] ss : supportedAlphabeticSequences ) { + assert ss.length >= 2; + if ( ss[0] == s ) { + return true; + } + } + return false; + } + + private static int getSequenceBase ( int s ) { + for ( int[] ss : supportedAlphabeticSequences ) { + assert ss.length >= 2; + if ( ss[0] == s ) { + return ss[1]; + } + } + return 0; + } + + private static int[][] supportedSpecials = { + { 'I' }, // latin - uppercase roman numerals + { 'i' }, // latin - lowercase roman numerals + { '\u0391' }, // greek - uppercase isopsephry numerals + { '\u03B1' }, // greek - lowercase isopsephry numerals + { '\u05D0' }, // hebrew - gematria numerals + { '\u0623' }, // arabic - abjadi numberals + { '\u0627' }, // arabic - either abjadi or hijai alphabetic sequence + { '\u0E01' }, // thai - default alphabetic sequence + { '\u3042' }, // kana - hiragana (gojuon) - default alphabetic sequence + { '\u3044' }, // kana - hiragana (iroha) + { '\u30A2' }, // kana - katakana (gojuon) - default alphabetic sequence + { '\u30A4' }, // kana - katakana (iroha) + }; + + private static boolean isStartOfNumericSpecial ( int s ) { + for ( int[] ss : supportedSpecials ) { + assert ss.length >= 1; + if ( ss[0] == s ) { + return true; + } + } + return false; + } + + private SpecialNumberFormatter getSpecialFormatter ( int one, int letterValue, String features, String language, String country ) { + if ( one == (int) 'I' ) { + return new RomanNumeralsFormatter(); + } else if ( one == (int) 'i' ) { + return new RomanNumeralsFormatter(); + } else if ( one == (int) '\u0391' ) { + return new IsopsephryNumeralsFormatter(); + } else if ( one == (int) '\u03B1' ) { + return new IsopsephryNumeralsFormatter(); + } else if ( one == (int) '\u05D0' ) { + return new GematriaNumeralsFormatter(); + } else if ( one == (int) '\u0623' ) { + return new ArabicNumeralsFormatter(); + } else if ( one == (int) '\u0627' ) { + return new ArabicNumeralsFormatter(); + } else if ( one == (int) '\u0E01' ) { + return new ThaiNumeralsFormatter(); + } else if ( one == (int) '\u3042' ) { + return new KanaNumeralsFormatter(); + } else if ( one == (int) '\u3044' ) { + return new KanaNumeralsFormatter(); + } else if ( one == (int) '\u30A2' ) { + return new KanaNumeralsFormatter(); + } else if ( one == (int) '\u30A4' ) { + return new KanaNumeralsFormatter(); + } else { + return null; + } + } + + private static Integer[] toUpperCase ( Integer[] sa ) { + assert sa != null; + for ( int i = 0, n = sa.length; i < n; i++ ) { + Integer s = sa [ i ]; + sa [ i ] = Character.toUpperCase ( s ); + } + return sa; + } + + private static Integer[] toLowerCase ( Integer[] sa ) { + assert sa != null; + for ( int i = 0, n = sa.length; i < n; i++ ) { + Integer s = sa [ i ]; + sa [ i ] = Character.toLowerCase ( s ); + } + return sa; + } + + /* not yet used + private static Integer[] toTitleCase ( Integer[] sa ) { + assert sa != null; + if ( sa.length > 0 ) { + sa [ 0 ] = Character.toTitleCase ( sa [ 0 ] ); + } + return sa; + } + */ + + private static List convertWordCase ( List words, int caseType ) { + List wl = new ArrayList(); + for ( String w : words ) { + wl.add ( convertWordCase ( w, caseType ) ); + } + return wl; + } + + private static String convertWordCase ( String word, int caseType ) { + if ( caseType == Character.UPPERCASE_LETTER ) { + return word.toUpperCase(); + } else if ( caseType == Character.LOWERCASE_LETTER ) { + return word.toLowerCase(); + } else if ( caseType == Character.TITLECASE_LETTER ) { + StringBuffer sb = new StringBuffer(); + for ( int i = 0, n = word.length(); i < n; i++ ) { + String s = word.substring ( i, i + 1 ); + if ( i == 0 ) { + sb.append ( s.toUpperCase() ); + } else { + sb.append ( s.toLowerCase() ); + } + } + return sb.toString(); + } else { + return word; + } + } + + private static String joinWords ( List words, String separator ) { + StringBuffer sb = new StringBuffer(); + for ( String w : words ) { + if ( sb.length() > 0 ) { + sb.append ( separator ); + } + sb.append ( w ); + } + return sb.toString(); + } + + /** + * Special number formatter. + */ + interface SpecialNumberFormatter { + /** + * Format number with special numeral system. + * @param number to be formatted + * @param one unicode scalar value denoting numeric value 1 + * @param letterValue letter value (must be one of the above letter value enumeration values) + * @param features features (feature sub-parameters) + * @param language denotes applicable language + * @param country denotes applicable country + * @return formatted number as array of unicode scalars + */ + Integer[] format ( long number, int one, int letterValue, String features, String language, String country ); + } + + /** + * English Word Numerals + */ + private static String[] englishWordOnes = { "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine" }; + private static String[] englishWordTeens = { "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen" }; + private static String[] englishWordTens = { "", "ten", "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety" }; + private static String[] englishWordOthers = { "hundred", "thousand", "million", "billion" }; + private static String[] englishWordOnesOrd = { "none", "first", "second", "third", "fourth", "fifth", "sixth", "seventh", "eighth", "ninth" }; + private static String[] englishWordTeensOrd = { "tenth", "eleventh", "twelfth", "thirteenth", "fourteenth", "fifteenth", "sixteenth", "seventeenth", "eighteenth", "nineteenth" }; + private static String[] englishWordTensOrd = { "", "tenth", "twentieth", "thirtieth", "fortieth", "fiftieth", "sixtieth", "seventieth", "eightieth", "ninetith" }; + private static String[] englishWordOthersOrd = { "hundredth", "thousandth", "millionth", "billionth" }; + private static class EnglishNumberAsWordFormatter implements SpecialNumberFormatter { + private int caseType = Character.UPPERCASE_LETTER; + EnglishNumberAsWordFormatter ( int caseType ) { + this.caseType = caseType; + } + @Override + public Integer[] format ( long number, int one, int letterValue, String features, String language, String country ) { + List wl = new ArrayList(); + if ( number >= 1000000000000L ) { + return null; + } else { + boolean ordinal = hasFeature ( features, "ordinal" ); + if ( number == 0 ) { + wl.add ( englishWordOnes [ 0 ] ); + } else if ( ordinal && ( number < 10 ) ) { + wl.add ( englishWordOnesOrd [ (int) number ] ); + } else { + int ones = (int) ( number % 1000 ); + int thousands = (int) ( ( number / 1000 ) % 1000 ); + int millions = (int) ( ( number / 1000000 ) % 1000 ); + int billions = (int) ( ( number / 1000000000 ) % 1000 ); + if ( billions > 0 ) { + wl = formatOnesInThousand ( wl, billions ); + if ( ordinal && ( ( number % 1000000000 ) == 0 ) ) { + wl.add ( englishWordOthersOrd[3] ); + } else { + wl.add ( englishWordOthers[3] ); + } + } + if ( millions > 0 ) { + wl = formatOnesInThousand ( wl, millions ); + if ( ordinal && ( ( number % 1000000 ) == 0 ) ) { + wl.add ( englishWordOthersOrd[2] ); + } else { + wl.add ( englishWordOthers[2] ); + } + } + if ( thousands > 0 ) { + wl = formatOnesInThousand ( wl, thousands ); + if ( ordinal && ( ( number % 1000 ) == 0 ) ) { + wl.add ( englishWordOthersOrd[1] ); + } else { + wl.add ( englishWordOthers[1] ); + } + } + if ( ones > 0 ) { + wl = formatOnesInThousand ( wl, ones, ordinal ); + } + } + wl = convertWordCase ( wl, caseType ); + return UTF32.toUTF32 ( joinWords ( wl, " " ), 0, true ); + } + } + private List formatOnesInThousand ( List wl, int number ) { + return formatOnesInThousand ( wl, number, false ); + } + private List formatOnesInThousand ( List wl, int number, boolean ordinal ) { + assert number < 1000; + int ones = number % 10; + int tens = ( number / 10 ) % 10; + int hundreds = ( number / 100 ) % 10; + if ( hundreds > 0 ) { + wl.add ( englishWordOnes [ hundreds ] ); + if ( ordinal && ( ( number % 100 ) == 0 ) ) { + wl.add ( englishWordOthersOrd[0] ); + } else { + wl.add ( englishWordOthers[0] ); + } + } + if ( tens > 0 ) { + if ( tens == 1 ) { + if ( ordinal ) { + wl.add ( englishWordTeensOrd [ ones ] ); + } else { + wl.add ( englishWordTeens [ ones ] ); + } + } else { + if ( ordinal && ( ones == 0 ) ) { + wl.add ( englishWordTensOrd [ tens ] ); + } else { + wl.add ( englishWordTens [ tens ] ); + } + if ( ones > 0 ) { + if ( ordinal ) { + wl.add ( englishWordOnesOrd [ ones ] ); + } else { + wl.add ( englishWordOnes [ ones ] ); + } + } + } + } else if ( ones > 0 ) { + if ( ordinal ) { + wl.add ( englishWordOnesOrd [ ones ] ); + } else { + wl.add ( englishWordOnes [ ones ] ); + } + } + return wl; + } + } + + /** + * French Word Numerals + */ + private static String[] frenchWordOnes = { "z\u00e9ro", "un", "deux", "trois", "quatre", "cinq", "six", "sept", "huit", "neuf" }; + private static String[] frenchWordTeens = { "dix", "onze", "douze", "treize", "quatorze", "quinze", "seize", "dix-sept", "dix-huit", "dix-neuf" }; + private static String[] frenchWordTens = { "", "dix", "vingt", "trente", "quarante", "cinquante", "soixante", "soixante-dix", "quatre-vingt", "quatre-vingt-dix" }; + private static String[] frenchWordOthers = { "cent", "cents", "mille", "million", "millions", "milliard", "milliards" }; + private static String[] frenchWordOnesOrdMale = { "premier", "deuxi\u00e8me", "troisi\u00e8me", "quatri\u00e8me", "cinqui\u00e8me", "sixi\u00e8me", "septi\u00e8me", "huiti\u00e8me", "neuvi\u00e8me", "dixi\u00e8me" }; + private static String[] frenchWordOnesOrdFemale = { "premi\u00e8re", "deuxi\u00e8me", "troisi\u00e8me", "quatri\u00e8me", "cinqui\u00e8me", "sixi\u00e8me", "septi\u00e8me", "huiti\u00e8me", "neuvi\u00e8me", "dixi\u00e8me" }; + private static class FrenchNumberAsWordFormatter implements SpecialNumberFormatter { + private int caseType = Character.UPPERCASE_LETTER; + FrenchNumberAsWordFormatter ( int caseType ) { + this.caseType = caseType; + } + @Override + public Integer[] format ( long number, int one, int letterValue, String features, String language, String country ) { + List wl = new ArrayList(); + if ( number >= 1000000000000L ) { + return null; + } else { + boolean ordinal = hasFeature ( features, "ordinal" ); + if ( number == 0 ) { + wl.add ( frenchWordOnes [ 0 ] ); + } else if ( ordinal && ( number <= 10 ) ) { + boolean female = hasFeature ( features, "female" ); + if ( female ) { + wl.add ( frenchWordOnesOrdFemale [ (int) number ] ); + } else { + wl.add ( frenchWordOnesOrdMale [ (int) number ] ); + } + } else { + int ones = (int) ( number % 1000 ); + int thousands = (int) ( ( number / 1000 ) % 1000 ); + int millions = (int) ( ( number / 1000000 ) % 1000 ); + int billions = (int) ( ( number / 1000000000 ) % 1000 ); + if ( billions > 0 ) { + wl = formatOnesInThousand ( wl, billions ); + if ( billions == 1 ) { + wl.add ( frenchWordOthers[5] ); + } else { + wl.add ( frenchWordOthers[6] ); + } + } + if ( millions > 0 ) { + wl = formatOnesInThousand ( wl, millions ); + if ( millions == 1 ) { + wl.add ( frenchWordOthers[3] ); + } else { + wl.add ( frenchWordOthers[4] ); + } + } + if ( thousands > 0 ) { + if ( thousands > 1 ) { + wl = formatOnesInThousand ( wl, thousands ); + } + wl.add ( frenchWordOthers[2] ); + } + if ( ones > 0 ) { + wl = formatOnesInThousand ( wl, ones ); + } + } + wl = convertWordCase ( wl, caseType ); + return UTF32.toUTF32 ( joinWords ( wl, " " ), 0, true ); + } + } + private List formatOnesInThousand ( List wl, int number ) { + assert number < 1000; + int ones = number % 10; + int tens = ( number / 10 ) % 10; + int hundreds = ( number / 100 ) % 10; + if ( hundreds > 0 ) { + if ( hundreds > 1 ) { + wl.add ( frenchWordOnes [ hundreds ] ); + } + if ( ( hundreds > 1 ) && ( tens == 0 ) && ( ones == 0 ) ) { + wl.add ( frenchWordOthers[1] ); + } else { + wl.add ( frenchWordOthers[0] ); + } + } + if ( tens > 0 ) { + if ( tens == 1 ) { + wl.add ( frenchWordTeens [ ones ] ); + } else if ( tens < 7 ) { + if ( ones == 1 ) { + wl.add ( frenchWordTens [ tens ] ); + wl.add ( "et" ); + wl.add ( frenchWordOnes [ ones ] ); + } else { + StringBuffer sb = new StringBuffer(); + sb.append ( frenchWordTens [ tens ] ); + if ( ones > 0 ) { + sb.append ( '-' ); + sb.append ( frenchWordOnes [ ones ] ); + } + wl.add ( sb.toString() ); + } + } else if ( tens == 7 ) { + if ( ones == 1 ) { + wl.add ( frenchWordTens [ 6 ] ); + wl.add ( "et" ); + wl.add ( frenchWordTeens [ ones ] ); + } else { + StringBuffer sb = new StringBuffer(); + sb.append ( frenchWordTens [ 6 ] ); + sb.append ( '-' ); + sb.append ( frenchWordTeens [ ones ] ); + wl.add ( sb.toString() ); + } + } else if ( tens == 8 ) { + StringBuffer sb = new StringBuffer(); + sb.append ( frenchWordTens [ tens ] ); + if ( ones > 0 ) { + sb.append ( '-' ); + sb.append ( frenchWordOnes [ ones ] ); + } else { + sb.append ( 's' ); + } + wl.add ( sb.toString() ); + } else if ( tens == 9 ) { + StringBuffer sb = new StringBuffer(); + sb.append ( frenchWordTens [ 8 ] ); + sb.append ( '-' ); + sb.append ( frenchWordTeens [ ones ] ); + wl.add ( sb.toString() ); + } + } else if ( ones > 0 ) { + wl.add ( frenchWordOnes [ ones ] ); + } + return wl; + } + } + + /** + * Spanish Word Numerals + */ + private static String[] spanishWordOnes = { "cero", "uno", "dos", "tres", "cuatro", "cinco", "seise", "siete", "ocho", "nueve" }; + private static String[] spanishWordTeens = { "diez", "once", "doce", "trece", "catorce", "quince", "diecis\u00e9is", "diecisiete", "dieciocho", "diecinueve" }; + private static String[] spanishWordTweens = { "veinte", "veintiuno", "veintid\u00f3s", "veintitr\u00e9s", "veinticuatro", "veinticinco", "veintis\u00e9is", "veintisiete", "veintiocho", "veintinueve" }; + private static String[] spanishWordTens = { "", "diez", "veinte", "treinta", "cuarenta", "cincuenta", "sesenta", "setenta", "ochenta", "noventa" }; + private static String[] spanishWordHundreds = { "", "ciento", "doscientos", "trescientos", "cuatrocientos", "quinientos", "seiscientos", "setecientos", "ochocientos", "novecientos" }; + private static String[] spanishWordOthers = { "un", "cien", "mil", "mill\u00f3n", "millones" }; + private static String[] spanishWordOnesOrdMale = { "ninguno", "primero", "segundo", "tercero", "cuarto", "quinto", "sexto", "s\u00e9ptimo", "octavo", "novento", "d\u00e9cimo" }; + private static String[] spanishWordOnesOrdFemale = { "ninguna", "primera", "segunda", "tercera", "cuarta", "quinta", "sexta", "s\u00e9ptima", "octava", "noventa", "d\u00e9cima" }; + private static class SpanishNumberAsWordFormatter implements SpecialNumberFormatter { + private int caseType = Character.UPPERCASE_LETTER; + SpanishNumberAsWordFormatter ( int caseType ) { + this.caseType = caseType; + } + @Override + public Integer[] format ( long number, int one, int letterValue, String features, String language, String country ) { + List wl = new ArrayList(); + if ( number >= 1000000000000L ) { + return null; + } else { + boolean ordinal = hasFeature ( features, "ordinal" ); + if ( number == 0 ) { + wl.add ( spanishWordOnes [ 0 ] ); + } else if ( ordinal && ( number <= 10 ) ) { + boolean female = hasFeature ( features, "female" ); + if ( female ) { + wl.add ( spanishWordOnesOrdFemale [ (int) number ] ); + } else { + wl.add ( spanishWordOnesOrdMale [ (int) number ] ); + } + } else { + int ones = (int) ( number % 1000 ); + int thousands = (int) ( ( number / 1000 ) % 1000 ); + int millions = (int) ( ( number / 1000000 ) % 1000 ); + int billions = (int) ( ( number / 1000000000 ) % 1000 ); + if ( billions > 0 ) { + if ( billions > 1 ) { + wl = formatOnesInThousand ( wl, billions ); + } + wl.add ( spanishWordOthers[2] ); + wl.add ( spanishWordOthers[4] ); + } + if ( millions > 0 ) { + if ( millions == 1 ) { + wl.add ( spanishWordOthers[0] ); + } else { + wl = formatOnesInThousand ( wl, millions ); + } + if ( millions > 1 ) { + wl.add ( spanishWordOthers[4] ); + } else { + wl.add ( spanishWordOthers[3] ); + } + } + if ( thousands > 0 ) { + if ( thousands > 1 ) { + wl = formatOnesInThousand ( wl, thousands ); + } + wl.add ( spanishWordOthers[2] ); + } + if ( ones > 0 ) { + wl = formatOnesInThousand ( wl, ones ); + } + } + wl = convertWordCase ( wl, caseType ); + return UTF32.toUTF32 ( joinWords ( wl, " " ), 0, true ); + } + } + private List formatOnesInThousand ( List wl, int number ) { + assert number < 1000; + int ones = number % 10; + int tens = ( number / 10 ) % 10; + int hundreds = ( number / 100 ) % 10; + if ( hundreds > 0 ) { + if ( ( hundreds == 1 ) && ( tens == 0 ) && ( ones == 0 ) ) { + wl.add ( spanishWordOthers[1] ); + } else { + wl.add ( spanishWordHundreds [ hundreds ] ); + } + } + if ( tens > 0 ) { + if ( tens == 1 ) { + wl.add ( spanishWordTeens [ ones ] ); + } else if ( tens == 2 ) { + wl.add ( spanishWordTweens [ ones ] ); + } else { + wl.add ( spanishWordTens [ tens ] ); + if ( ones > 0 ) { + wl.add ( "y" ); + wl.add ( spanishWordOnes [ ones ] ); + } + } + } else if ( ones > 0 ) { + wl.add ( spanishWordOnes [ ones ] ); + } + return wl; + } + } + + /** + * Roman (Latin) Numerals + */ + private static int[] romanMapping = { + 100000, + 90000, + 50000, + 40000, + 10000, + 9000, + 5000, + 4000, + 1000, + 900, + 500, + 400, + 100, + 90, + 50, + 40, + 10, + 9, + 8, + 7, + 6, + 5, + 4, + 3, + 2, + 1 + }; + private static String[] romanStandardForms = { + null, + null, + null, + null, + null, + null, + null, + null, + "m", + "cm", + "d", + "cd", + "c", + "xc", + "l", + "xl", + "x", + "ix", + null, + null, + null, + "v", + "iv", + null, + null, + "i" + }; + private static String[] romanLargeForms = { + "\u2188", + "\u2182\u2188", + "\u2187", + "\u2182\u2187", + "\u2182", + "\u2180\u2182", + "\u2181", + "\u2180\u2181", + "m", + "cm", + "d", + "cd", + "c", + "xc", + "l", + "xl", + "x", + "ix", + null, + null, + null, + "v", + "iv", + null, + null, + "i" + }; + private static String[] romanNumberForms = { + "\u2188", + "\u2182\u2188", + "\u2187", + "\u2182\u2187", + "\u2182", + "\u2180\u2182", + "\u2181", + "\u2180\u2181", + "\u216F", + "\u216D\u216F", + "\u216E", + "\u216D\u216E", + "\u216D", + "\u2169\u216D", + "\u216C", + "\u2169\u216C", + "\u2169", + "\u2168", + "\u2167", + "\u2166", + "\u2165", + "\u2164", + "\u2163", + "\u2162", + "\u2161", + "\u2160" + }; + private static class RomanNumeralsFormatter implements SpecialNumberFormatter { + @Override + public Integer[] format ( long number, int one, int letterValue, String features, String language, String country ) { + List sl = new ArrayList(); + if ( number == 0 ) { + return null; + } else { + String[] forms; + int maxNumber; + if ( hasFeature ( features, "unicode-number-forms" ) ) { + forms = romanNumberForms; + maxNumber = 199999; + } else if ( hasFeature ( features, "large" ) ) { + forms = romanLargeForms; + maxNumber = 199999; + } else { + forms = romanStandardForms; + maxNumber = 4999; + } + if ( number > maxNumber ) { + return null; + } else { + while ( number > 0 ) { + for ( int i = 0, n = romanMapping.length; i < n; i++ ) { + int d = romanMapping [ i ]; + if ( ( number >= d ) && ( forms [ i ] != null ) ) { + appendScalars ( sl, UTF32.toUTF32 ( forms [ i ], 0, true ) ); + number = number - d; + break; + } + } + } + if ( one == (int) 'I' ) { + return toUpperCase ( sl.toArray ( new Integer [ sl.size() ] ) ); + } else if ( one == (int) 'i' ) { + return toLowerCase ( sl.toArray ( new Integer [ sl.size() ] ) ); + } else { + return null; + } + } + } + } + } + + /** + * Isopsephry (Greek) Numerals + */ + private static class IsopsephryNumeralsFormatter implements SpecialNumberFormatter { + @Override + public Integer[] format ( long number, int one, int letterValue, String features, String language, String country ) { + return null; + } + } + + /** + * Gematria (Hebrew) Numerals + */ + private static int[] hebrewGematriaAlphabeticMap = { + // ones + 0x05D0, // ALEF + 0x05D1, // BET + 0x05D2, // GIMEL + 0x05D3, // DALET + 0x05D4, // HE + 0x05D5, // VAV + 0x05D6, // ZAYIN + 0x05D7, // HET + 0x05D8, // TET + // tens + 0x05D9, // YOD + 0x05DB, // KAF + 0x05DC, // LAMED + 0x05DE, // MEM + 0x05E0, // NUN + 0x05E1, // SAMEKH + 0x05E2, // AYIN + 0x05E4, // PE + 0x05E6, // TSADHI + // hundreds + 0x05E7, // QOF + 0x05E8, // RESH + 0x05E9, // SHIN + 0x05EA, // TAV + 0x05DA, // FINAL KAF + 0x05DD, // FINAL MEM + 0x05DF, // FINAL NUN + 0x05E3, // FINAL PE + 0x05E5, // FINAL TSADHI + }; + private class GematriaNumeralsFormatter implements SpecialNumberFormatter { + @Override + public Integer[] format ( long number, int one, int letterValue, String features, String language, String country ) { + if ( one == 0x05D0 ) { + if ( letterValue == LETTER_VALUE_ALPHABETIC ) { + return formatNumberAsSequence ( number, one, hebrewGematriaAlphabeticMap.length, hebrewGematriaAlphabeticMap ); + } else if ( letterValue == LETTER_VALUE_TRADITIONAL ) { + if ( ( number == 0 ) || ( number > 1999 ) ) { + return null; + } else { + return formatAsGematriaNumber ( number, features, language, country ); + } + } else { + return null; + } + } else { + return null; + } + } + private Integer[] formatAsGematriaNumber ( long number, String features, String language, String country ) { + List sl = new ArrayList(); + assert hebrewGematriaAlphabeticMap.length == 27; + assert hebrewGematriaAlphabeticMap[0] == 0x05D0; // ALEF + assert hebrewGematriaAlphabeticMap[21] == 0x05EA; // TAV + assert number != 0; + assert number < 2000; + int[] map = hebrewGematriaAlphabeticMap; + int thousands = (int) ( ( number / 1000 ) % 10 ); + int hundreds = (int) ( ( number / 100 ) % 10 ); + int tens = (int) ( ( number / 10 ) % 10 ); + int ones = (int) ( ( number / 1 ) % 10 ); + if ( thousands > 0 ) { + sl.add ( map [ 0 + ( thousands - 1 ) ] ); + sl.add ( 0x05F3 ); + } + if ( hundreds > 0 ) { + assert hundreds < 10; + if ( hundreds < 5 ) { + sl.add ( map [ 18 + ( hundreds - 1 ) ] ); + } else if ( hundreds < 9 ) { + sl.add ( map [ 18 + ( 4 - 1 ) ] ); + sl.add ( 0x05F4 ); + sl.add ( map [ 18 + ( hundreds - 5 ) ] ); + } else if ( hundreds == 9 ) { + sl.add ( map [ 18 + ( 4 - 1 ) ] ); + sl.add ( map [ 18 + ( 4 - 1 ) ] ); + sl.add ( 0x05F4 ); + sl.add ( map [ 18 + ( hundreds - 9 ) ] ); + } + } + if ( number == 15 ) { + sl.add ( map [ 9 - 1] ); + sl.add ( 0x05F4 ); + sl.add ( map [ 6 - 1] ); + } else if ( number == 16 ) { + sl.add ( map [ 9 - 1 ] ); + sl.add ( 0x05F4 ); + sl.add ( map [ 7 - 1 ] ); + } else { + if ( tens > 0 ) { + assert tens < 10; + sl.add ( map [ 9 + ( tens - 1 ) ] ); + } + if ( ones > 0 ) { + assert ones < 10; + sl.add ( map [ 0 + ( ones - 1 ) ] ); + } + } + return sl.toArray ( new Integer [ sl.size() ] ); + } + } + + /** + * Arabic Numerals + */ + private static int[] arabicAbjadiAlphabeticMap = { + // ones + 0x0623, // ALEF WITH HAMZA ABOVE + 0x0628, // BEH + 0x062C, // JEEM + 0x062F, // DAL + 0x0647, // HEH + 0x0648, // WAW + 0x0632, // ZAIN + 0x062D, // HAH + 0x0637, // TAH + // tens + 0x0649, // ALEF MAQSURA + 0x0643, // KAF + 0x0644, // LAM + 0x0645, // MEEM + 0x0646, // NOON + 0x0633, // SEEN + 0x0639, // AIN + 0x0641, // FEH + 0x0635, // SAD + // hundreds + 0x0642, // QAF + 0x0631, // REH + 0x0634, // SHEEN + 0x062A, // TEH + 0x062B, // THEH + 0x062E, // KHAH + 0x0630, // THAL + 0x0636, // DAD + 0x0638, // ZAH + // thousands + 0x063A, // GHAIN + }; + private static int[] arabicHijaiAlphabeticMap = { + 0x0623, // ALEF WITH HAMZA ABOVE + 0x0628, // BEH + 0x062A, // TEH + 0x062B, // THEH + 0x062C, // JEEM + 0x062D, // HAH + 0x062E, // KHAH + 0x062F, // DAL + 0x0630, // THAL + 0x0631, // REH + 0x0632, // ZAIN + 0x0633, // SEEN + 0x0634, // SHEEN + 0x0635, // SAD + 0x0636, // DAD + 0x0637, // TAH + 0x0638, // ZAH + 0x0639, // AIN + 0x063A, // GHAIN + 0x0641, // FEH + 0x0642, // QAF + 0x0643, // KAF + 0x0644, // LAM + 0x0645, // MEEM + 0x0646, // NOON + 0x0647, // HEH + 0x0648, // WAW + 0x0649, // ALEF MAQSURA + }; + private class ArabicNumeralsFormatter implements SpecialNumberFormatter { + @Override + public Integer[] format ( long number, int one, int letterValue, String features, String language, String country ) { + if ( one == 0x0627 ) { + int[] map; + if ( letterValue == LETTER_VALUE_TRADITIONAL ) { + map = arabicAbjadiAlphabeticMap; + } else if ( letterValue == LETTER_VALUE_ALPHABETIC ) { + map = arabicHijaiAlphabeticMap; + } else { + map = arabicAbjadiAlphabeticMap; + } + return formatNumberAsSequence ( number, one, map.length, map ); + } else if ( one == 0x0623 ) { + if ( ( number == 0 ) || ( number > 1999 ) ) { + return null; + } else { + return formatAsAbjadiNumber ( number, features, language, country ); + } + } else { + return null; + } + } + private Integer[] formatAsAbjadiNumber ( long number, String features, String language, String country ) { + List sl = new ArrayList(); + assert arabicAbjadiAlphabeticMap.length == 28; + assert arabicAbjadiAlphabeticMap[0] == 0x0623; // ALEF WITH HAMZA ABOVE + assert arabicAbjadiAlphabeticMap[27] == 0x063A; // GHAIN + assert number != 0; + assert number < 2000; + int[] map = arabicAbjadiAlphabeticMap; + int thousands = (int) ( ( number / 1000 ) % 10 ); + int hundreds = (int) ( ( number / 100 ) % 10 ); + int tens = (int) ( ( number / 10 ) % 10 ); + int ones = (int) ( ( number / 1 ) % 10 ); + if ( thousands > 0 ) { + assert thousands < 2; + sl.add ( map [ 27 + ( thousands - 1 ) ] ); + } + if ( hundreds > 0 ) { + assert thousands < 10; + sl.add ( map [ 18 + ( hundreds - 1 ) ] ); + } + if ( tens > 0 ) { + assert tens < 10; + sl.add ( map [ 9 + ( tens - 1 ) ] ); + } + if ( ones > 0 ) { + assert ones < 10; + sl.add ( map [ 0 + ( ones - 1 ) ] ); + } + return sl.toArray ( new Integer [ sl.size() ] ); + } + } + + /** + * Kana (Japanese) Numerals + */ + private static int[] hiraganaGojuonAlphabeticMap = { + 0x3042, // A + 0x3044, // I + 0x3046, // U + 0x3048, // E + 0x304A, // O + 0x304B, // KA + 0x304D, // KI + 0x304F, // KU + 0x3051, // KE + 0x3053, // KO + 0x3055, // SA + 0x3057, // SI + 0x3059, // SU + 0x305B, // SE + 0x305D, // SO + 0x305F, // TA + 0x3061, // TI + 0x3064, // TU + 0x3066, // TE + 0x3068, // TO + 0x306A, // NA + 0x306B, // NI + 0x306C, // NU + 0x306D, // NE + 0x306E, // NO + 0x306F, // HA + 0x3072, // HI + 0x3075, // HU + 0x3078, // HE + 0x307B, // HO + 0x307E, // MA + 0x307F, // MI + 0x3080, // MU + 0x3081, // ME + 0x3082, // MO + 0x3084, // YA + 0x3086, // YU + 0x3088, // YO + 0x3089, // RA + 0x308A, // RI + 0x308B, // RU + 0x308C, // RE + 0x308D, // RO + 0x308F, // WA + 0x3090, // WI + 0x3091, // WE + 0x3092, // WO + 0x3093, // N + }; + private static int[] katakanaGojuonAlphabeticMap = { + 0x30A2, // A + 0x30A4, // I + 0x30A6, // U + 0x30A8, // E + 0x30AA, // O + 0x30AB, // KA + 0x30AD, // KI + 0x30AF, // KU + 0x30B1, // KE + 0x30B3, // KO + 0x30B5, // SA + 0x30B7, // SI + 0x30B9, // SU + 0x30BB, // SE + 0x30BD, // SO + 0x30BF, // TA + 0x30C1, // TI + 0x30C4, // TU + 0x30C6, // TE + 0x30C8, // TO + 0x30CA, // NA + 0x30CB, // NI + 0x30CC, // NU + 0x30CD, // NE + 0x30CE, // NO + 0x30CF, // HA + 0x30D2, // HI + 0x30D5, // HU + 0x30D8, // HE + 0x30DB, // HO + 0x30DE, // MA + 0x30DF, // MI + 0x30E0, // MU + 0x30E1, // ME + 0x30E2, // MO + 0x30E4, // YA + 0x30E6, // YU + 0x30E8, // YO + 0x30E9, // RA + 0x30EA, // RI + 0x30EB, // RU + 0x30EC, // RE + 0x30ED, // RO + 0x30EF, // WA + 0x30F0, // WI + 0x30F1, // WE + 0x30F2, // WO + 0x30F3, // N + }; + private class KanaNumeralsFormatter implements SpecialNumberFormatter { + @Override + public Integer[] format ( long number, int one, int letterValue, String features, String language, String country ) { + if ( ( one == 0x3042 ) && ( letterValue == LETTER_VALUE_ALPHABETIC ) ) { + return formatNumberAsSequence ( number, one, hiraganaGojuonAlphabeticMap.length, hiraganaGojuonAlphabeticMap ); + } else if ( ( one == 0x30A2 ) && ( letterValue == LETTER_VALUE_ALPHABETIC ) ) { + return formatNumberAsSequence ( number, one, katakanaGojuonAlphabeticMap.length, katakanaGojuonAlphabeticMap ); + } else { + return null; + } + } + } + + /** + * Thai Numerals + */ + private static int[] thaiAlphabeticMap = { + 0x0E01, + 0x0E02, + 0x0E03, + 0x0E04, + 0x0E05, + 0x0E06, + 0x0E07, + 0x0E08, + 0x0E09, + 0x0E0A, + 0x0E0B, + 0x0E0C, + 0x0E0D, + 0x0E0E, + 0x0E0F, + 0x0E10, + 0x0E11, + 0x0E12, + 0x0E13, + 0x0E14, + 0x0E15, + 0x0E16, + 0x0E17, + 0x0E18, + 0x0E19, + 0x0E1A, + 0x0E1B, + 0x0E1C, + 0x0E1D, + 0x0E1E, + 0x0E1F, + 0x0E20, + 0x0E21, + 0x0E22, + 0x0E23, + // 0x0E24, // RU - not used in modern sequence + 0x0E25, + // 0x0E26, // LU - not used in modern sequence + 0x0E27, + 0x0E28, + 0x0E29, + 0x0E2A, + 0x0E2B, + 0x0E2C, + 0x0E2D, + 0x0E2E, + }; + private class ThaiNumeralsFormatter implements SpecialNumberFormatter { + @Override + public Integer[] format ( long number, int one, int letterValue, String features, String language, String country ) { + if ( ( one == 0x0E01 ) && ( letterValue == LETTER_VALUE_ALPHABETIC ) ) { + return formatNumberAsSequence ( number, one, thaiAlphabeticMap.length, thaiAlphabeticMap ); + } else { + return null; + } + } + } + +} diff --git a/src/java/org/apache/fop/complexscripts/util/ScriptContextTester.java b/src/java/org/apache/fop/complexscripts/util/ScriptContextTester.java new file mode 100644 index 000000000..3f68b00e2 --- /dev/null +++ b/src/java/org/apache/fop/complexscripts/util/ScriptContextTester.java @@ -0,0 +1,35 @@ +/* + * 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.complexscripts.util; + +/** + * Interface for providing script specific context testers. + * @author Glenn Adams + */ +public interface ScriptContextTester { + + /** + * Obtain a glyph context tester for the specified feature. + * @param feature a feature identifier + * @return a glyph context tester or null if none available for the specified feature + */ + GlyphContextTester getTester ( String feature ); + +} diff --git a/src/java/org/apache/fop/complexscripts/util/UTF32.java b/src/java/org/apache/fop/complexscripts/util/UTF32.java new file mode 100644 index 000000000..9df2020f0 --- /dev/null +++ b/src/java/org/apache/fop/complexscripts/util/UTF32.java @@ -0,0 +1,128 @@ +/* + * 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.complexscripts.util; + +import org.apache.fop.util.CharUtilities; + +// CSOFF: InnerAssignmentCheck + +/** + * UTF32 related utilities. + * @author Glenn Adams + */ +public final class UTF32 { + + private UTF32() { + } + + /** + * Convert Java string (UTF-16) to a Unicode scalar array (UTF-32). + * Note that if there are any non-BMP encoded characters present in the + * input, then the number of entries in the output array will be less + * than the number of elements in the input string. Any + * @param s input string + * @param substitution value to substitute for ill-formed surrogate + * @param errorOnSubstitution throw runtime exception (IllegalArgumentException) in + * case this argument is true and a substitution would be attempted + * @return output scalar array + * @throws IllegalArgumentException if substitution required and errorOnSubstitution + * is not false + */ + public static Integer[] toUTF32 ( String s, int substitution, boolean errorOnSubstitution ) + throws IllegalArgumentException { + int n; + if ( ( n = s.length() ) == 0 ) { + return new Integer[0]; + } else { + Integer[] sa = new Integer [ n ]; + int k = 0; + for ( int i = 0; i < n; i++ ) { + int c = (int) s.charAt(i); + if ( ( c >= 0xD800 ) && ( c < 0xE000 ) ) { + int s1 = c; + int s2 = ( ( i + 1 ) < n ) ? (int) s.charAt ( i + 1 ) : 0; + if ( s1 < 0xDC00 ) { + if ( ( s2 >= 0xDC00 ) && ( s2 < 0xE000 ) ) { + c = ( ( s1 - 0xD800 ) << 10 ) + ( s2 - 0xDC00 ) + 65536; + i++; + } else { + if ( errorOnSubstitution ) { + throw new IllegalArgumentException + ( "isolated high (leading) surrogate" ); + } else { + c = substitution; + } + } + } else { + if ( errorOnSubstitution ) { + throw new IllegalArgumentException + ( "isolated low (trailing) surrogate" ); + } else { + c = substitution; + } + } + } + sa[k++] = c; + } + if ( k == n ) { + return sa; + } else { + Integer[] na = new Integer [ k ]; + System.arraycopy ( sa, 0, na, 0, k ); + return na; + } + } + } + + /** + * Convert a Unicode scalar array (UTF-32) a Java string (UTF-16). + * @param sa input scalar array + * @return output (UTF-16) string + * @throws IllegalArgumentException if an input scalar value is illegal, + * e.g., a surrogate or out of range + */ + public static String fromUTF32 ( Integer[] sa ) throws IllegalArgumentException { + StringBuffer sb = new StringBuffer(); + for ( int s : sa ) { + if ( s < 65535 ) { + if ( ( s < 0xD800 ) || ( s > 0xDFFF ) ) { + sb.append ( (char) s ); + } else { + String ncr = CharUtilities.charToNCRef(s); + throw new IllegalArgumentException + ( "illegal scalar value 0x" + ncr.substring(2, ncr.length() - 1) + + "; cannot be UTF-16 surrogate" ); + } + } else if ( s < 1114112 ) { + int s1 = ( ( ( s - 65536 ) >> 10 ) & 0x3FF ) + 0xD800; + int s2 = ( ( ( s - 65536 ) >> 0 ) & 0x3FF ) + 0xDC00; + sb.append ( (char) s1 ); + sb.append ( (char) s2 ); + } else { + String ncr = CharUtilities.charToNCRef(s); + throw new IllegalArgumentException + ( "illegal scalar value 0x" + ncr.substring(2, ncr.length() - 1) + + "; out of range for UTF-16" ); + } + } + return sb.toString(); + } + +} diff --git a/src/java/org/apache/fop/fo/Constants.java b/src/java/org/apache/fop/fo/Constants.java index a2b982269..2d10dcdd9 100644 --- a/src/java/org/apache/fop/fo/Constants.java +++ b/src/java/org/apache/fop/fo/Constants.java @@ -26,7 +26,7 @@ package org.apache.fop.fo; *
  • Input and output formats
  • *
  • Formatting objects (FO_XXX)
  • *
  • Formatting properties (PR_XXX)
  • - *
  • Enumerated values used in formatting properties (EN_XXX)
  • + *
  • Enumerated values used in formatting properties and traits (EN_XXX)
  • * */ public interface Constants { @@ -778,9 +778,15 @@ public interface Constants { int PR_X_ALT_TEXT = 274; /** Property constant - FOP proprietary prototype (in XSL-FO 2.0 Requirements) */ int PR_X_XML_BASE = 275; + /** + * Property constant - FOP proprietary extension (see NumberConverter) used + * to perform additional control over number conversion when generating page + * numbers. + */ + int PR_X_NUMBER_CONVERSION_FEATURES = 276; /** Number of property constants defined */ - int PROPERTY_COUNT = 275; + int PROPERTY_COUNT = 276; // compound property constants @@ -1208,6 +1214,16 @@ public interface Constants { int EN_NO_LINK = 199; /** Enumeration constant -- XSL 1.1 */ int EN_ALTERNATE = 200; + /** Enumeration constant -- for *-direction traits */ + int EN_LR = 201; // left to right + /** Enumeration constant -- for *-direction traits */ + int EN_RL = 202; // right to left + /** Enumeration constant -- for *-direction traits */ + int EN_TB = 203; // top to bottom + /** Enumeration constant -- for *-direction traits */ + int EN_BT = 204; // bottom to top + /** Enumeration constant */ + int EN_TB_LR = 205; // for top-to-bottom, left-to-right writing mode /** Number of enumeration constants defined */ - int ENUM_COUNT = 200; + int ENUM_COUNT = 205; } diff --git a/src/java/org/apache/fop/fo/FONode.java b/src/java/org/apache/fop/fo/FONode.java index b63c49ae2..99d133f16 100644 --- a/src/java/org/apache/fop/fo/FONode.java +++ b/src/java/org/apache/fop/fo/FONode.java @@ -20,8 +20,10 @@ package org.apache.fop.fo; // Java +import java.util.Iterator; import java.util.ListIterator; import java.util.Map; +import java.util.Stack; import org.xml.sax.Attributes; import org.xml.sax.Locator; @@ -35,6 +37,7 @@ import org.apache.xmlgraphics.util.QName; import org.apache.fop.accessibility.StructureTreeElement; import org.apache.fop.apps.FOPException; import org.apache.fop.apps.FOUserAgent; +import org.apache.fop.complexscripts.bidi.DelimitedTextRange; import org.apache.fop.fo.extensions.ExtensionAttachment; import org.apache.fop.fo.extensions.ExtensionElementMapping; import org.apache.fop.fo.extensions.InternalElementMapping; @@ -864,6 +867,122 @@ public abstract class FONode implements Cloneable { followingSibling.siblings[0] = precedingSibling; } + /** + * Determine if node has a delimited text range boundary. N.B. that we report + * this to be true by default, while specific subclasses override this method to report false. + * @param boundary one of {EN_BEFORE, EN_AFTER, or EN_BOTH} enumeration constants + * @return true if indicated boundary (or boundaries) constitute a delimited text range + * boundary. + */ + public boolean isDelimitedTextRangeBoundary ( int boundary ) { + return true; + } + + /** + * Collect the sequence of delimited text ranges, where each new + * range is pushed onto RANGES. + * @param ranges a stack of delimited text ranges + * @return the (possibly) updated stack of delimited text ranges + */ + public Stack collectDelimitedTextRanges ( Stack ranges ) { + // if boundary before, then push new range + if ( isRangeBoundaryBefore() ) { + maybeNewRange ( ranges ); + } + // get current range, if one exists + DelimitedTextRange currentRange; + if ( ranges.size() > 0 ) { + currentRange = (DelimitedTextRange) ranges.peek(); + } else { + currentRange = null; + } + // proceses this node + ranges = collectDelimitedTextRanges ( ranges, currentRange ); + // if boundary after, then push new range + if ( isRangeBoundaryAfter() ) { + maybeNewRange ( ranges ); + } + return ranges; + } + + /** + * Collect the sequence of delimited text ranges, where each new + * range is pushed onto RANGES, where default implementation collects ranges + * of child nodes. + * @param ranges a stack of delimited text ranges + * @param currentRange the current range or null (if none) + * @return the (possibly) updated stack of delimited text ranges + */ + protected Stack collectDelimitedTextRanges ( Stack ranges, DelimitedTextRange currentRange ) { + for ( Iterator it = getChildNodes(); ( it != null ) && it.hasNext();) { + ranges = ( (FONode) it.next() ).collectDelimitedTextRanges ( ranges ); + } + return ranges; + } + + /** + * Determine if this node is a new bidi RANGE block item. + * @return true if this node is a new bidi RANGE block item + */ + public boolean isBidiRangeBlockItem() { + return false; + } + + /** + * Conditionally add a new delimited text range to RANGES, where new range is + * associated with current FONode. A new text range is added unless all of the following are + * true: + *
      + *
    • there exists a current range RCUR in RANGES
    • + *
    • RCUR is empty
    • + *
    • the node of the RCUR is the same node as FN or a descendent node of FN
    • + *
    + * @param ranges stack of delimited text ranges + * @return new range (if constructed and pushed onto stack) or current range (if any) or null + */ + private DelimitedTextRange maybeNewRange ( Stack ranges ) { + DelimitedTextRange rCur = null; // current range (top of range stack) + DelimitedTextRange rNew = null; // new range to be pushed onto range stack + if ( ranges.empty() ) { + if ( isBidiRangeBlockItem() ) { + rNew = new DelimitedTextRange(this); + } + } else { + rCur = (DelimitedTextRange) ranges.peek(); + if ( rCur != null ) { + if ( !rCur.isEmpty() || !isSelfOrDescendent ( rCur.getNode(), this ) ) { + rNew = new DelimitedTextRange(this); + } + } + } + if ( rNew != null ) { + ranges.push ( rNew ); + } else { + rNew = rCur; + } + return rNew; + } + + private boolean isRangeBoundaryBefore() { + return isDelimitedTextRangeBoundary ( Constants.EN_BEFORE ); + } + + private boolean isRangeBoundaryAfter() { + return isDelimitedTextRangeBoundary ( Constants.EN_AFTER ); + } + + /** + * Determine if node N2 is the same or a descendent of node N1. + */ + private static boolean isSelfOrDescendent ( FONode n1, FONode n2 ) { + for ( FONode n = n2; n != null; n = n.getParent() ) { + if ( n == n1 ) { + return true; + } + } + return false; + } + /** * Base iterator interface over a FO's children */ diff --git a/src/java/org/apache/fop/fo/FOPropertyMapping.java b/src/java/org/apache/fop/fo/FOPropertyMapping.java index 172aa5329..b29571b09 100644 --- a/src/java/org/apache/fop/fo/FOPropertyMapping.java +++ b/src/java/org/apache/fop/fo/FOPropertyMapping.java @@ -632,7 +632,7 @@ public final class FOPropertyMapping implements Constants { m.setDefault("black"); corr = new CorrespondingPropertyMaker(m); corr.setCorresponding(PR_BORDER_TOP_COLOR, PR_BORDER_TOP_COLOR, - PR_BORDER_RIGHT_COLOR); + PR_BORDER_RIGHT_COLOR, PR_BORDER_LEFT_COLOR); corr.setRelative(true); addPropertyMaker("border-before-color", m); @@ -641,7 +641,7 @@ public final class FOPropertyMapping implements Constants { m.useGeneric(genericBorderStyle); corr = new CorrespondingPropertyMaker(m); corr.setCorresponding(PR_BORDER_TOP_STYLE, PR_BORDER_TOP_STYLE, - PR_BORDER_RIGHT_STYLE); + PR_BORDER_RIGHT_STYLE, PR_BORDER_LEFT_STYLE); corr.setRelative(true); addPropertyMaker("border-before-style", m); @@ -651,7 +651,7 @@ public final class FOPropertyMapping implements Constants { m.getSubpropMaker(CP_CONDITIONALITY).setDefault("discard"); corr = new CorrespondingPropertyMaker(m); corr.setCorresponding(PR_BORDER_TOP_WIDTH, PR_BORDER_TOP_WIDTH, - PR_BORDER_RIGHT_WIDTH); + PR_BORDER_RIGHT_WIDTH, PR_BORDER_LEFT_WIDTH); corr.setRelative(true); addPropertyMaker("border-before-width", m); @@ -662,7 +662,7 @@ public final class FOPropertyMapping implements Constants { m.setDefault("black"); corr = new CorrespondingPropertyMaker(m); corr.setCorresponding(PR_BORDER_BOTTOM_COLOR, PR_BORDER_BOTTOM_COLOR, - PR_BORDER_LEFT_COLOR); + PR_BORDER_LEFT_COLOR, PR_BORDER_RIGHT_COLOR); corr.setRelative(true); addPropertyMaker("border-after-color", m); @@ -671,7 +671,7 @@ public final class FOPropertyMapping implements Constants { m.useGeneric(genericBorderStyle); corr = new CorrespondingPropertyMaker(m); corr.setCorresponding(PR_BORDER_BOTTOM_STYLE, PR_BORDER_BOTTOM_STYLE, - PR_BORDER_LEFT_STYLE); + PR_BORDER_LEFT_STYLE, PR_BORDER_RIGHT_STYLE); corr.setRelative(true); addPropertyMaker("border-after-style", m); @@ -681,7 +681,7 @@ public final class FOPropertyMapping implements Constants { m.getSubpropMaker(CP_CONDITIONALITY).setDefault("discard"); corr = new CorrespondingPropertyMaker(m); corr.setCorresponding(PR_BORDER_BOTTOM_WIDTH, PR_BORDER_BOTTOM_WIDTH, - PR_BORDER_LEFT_WIDTH); + PR_BORDER_LEFT_WIDTH, PR_BORDER_LEFT_WIDTH); corr.setRelative(true); addPropertyMaker("border-after-width", m); @@ -692,7 +692,7 @@ public final class FOPropertyMapping implements Constants { m.setDefault("black"); corr = new CorrespondingPropertyMaker(m); corr.setCorresponding(PR_BORDER_LEFT_COLOR, PR_BORDER_RIGHT_COLOR, - PR_BORDER_TOP_COLOR); + PR_BORDER_TOP_COLOR, PR_BORDER_TOP_COLOR); corr.setRelative(true); addPropertyMaker("border-start-color", m); @@ -701,7 +701,7 @@ public final class FOPropertyMapping implements Constants { m.useGeneric(genericBorderStyle); corr = new CorrespondingPropertyMaker(m); corr.setCorresponding(PR_BORDER_LEFT_STYLE, PR_BORDER_RIGHT_STYLE, - PR_BORDER_TOP_STYLE); + PR_BORDER_TOP_STYLE, PR_BORDER_TOP_STYLE); corr.setRelative(true); addPropertyMaker("border-start-style", m); @@ -711,7 +711,7 @@ public final class FOPropertyMapping implements Constants { m.getSubpropMaker(CP_CONDITIONALITY).setDefault("discard"); corr = new CorrespondingPropertyMaker(m); corr.setCorresponding(PR_BORDER_LEFT_WIDTH, PR_BORDER_RIGHT_WIDTH, - PR_BORDER_TOP_WIDTH); + PR_BORDER_TOP_WIDTH, PR_BORDER_TOP_WIDTH); corr.setRelative(true); addPropertyMaker("border-start-width", m); @@ -722,7 +722,7 @@ public final class FOPropertyMapping implements Constants { m.setDefault("black"); corr = new CorrespondingPropertyMaker(m); corr.setCorresponding(PR_BORDER_RIGHT_COLOR, PR_BORDER_LEFT_COLOR, - PR_BORDER_BOTTOM_COLOR); + PR_BORDER_BOTTOM_COLOR, PR_BORDER_BOTTOM_COLOR); corr.setRelative(true); addPropertyMaker("border-end-color", m); @@ -731,7 +731,7 @@ public final class FOPropertyMapping implements Constants { m.useGeneric(genericBorderStyle); corr = new CorrespondingPropertyMaker(m); corr.setCorresponding(PR_BORDER_RIGHT_STYLE, PR_BORDER_LEFT_STYLE, - PR_BORDER_BOTTOM_STYLE); + PR_BORDER_BOTTOM_STYLE, PR_BORDER_BOTTOM_STYLE); corr.setRelative(true); addPropertyMaker("border-end-style", m); @@ -741,7 +741,7 @@ public final class FOPropertyMapping implements Constants { m.getSubpropMaker(CP_CONDITIONALITY).setDefault("discard"); corr = new CorrespondingPropertyMaker(m); corr.setCorresponding(PR_BORDER_RIGHT_WIDTH, PR_BORDER_LEFT_WIDTH, - PR_BORDER_BOTTOM_WIDTH); + PR_BORDER_BOTTOM_WIDTH, PR_BORDER_BOTTOM_WIDTH); corr.setRelative(true); addPropertyMaker("border-end-width", m); @@ -755,7 +755,7 @@ public final class FOPropertyMapping implements Constants { m.addShorthand(generics[PR_BORDER]); corr = new CorrespondingPropertyMaker(m); corr.setCorresponding(PR_BORDER_BEFORE_COLOR, PR_BORDER_BEFORE_COLOR, - PR_BORDER_START_COLOR); + PR_BORDER_START_COLOR, PR_BORDER_START_COLOR); addPropertyMaker("border-top-color", m); // border-top-style @@ -766,7 +766,7 @@ public final class FOPropertyMapping implements Constants { m.addShorthand(generics[PR_BORDER]); corr = new CorrespondingPropertyMaker(m); corr.setCorresponding(PR_BORDER_BEFORE_STYLE, PR_BORDER_BEFORE_STYLE, - PR_BORDER_START_STYLE); + PR_BORDER_START_STYLE, PR_BORDER_START_STYLE); addPropertyMaker("border-top-style", m); // border-top-width @@ -778,7 +778,7 @@ public final class FOPropertyMapping implements Constants { bwm.addShorthand(generics[PR_BORDER]); corr = new CorrespondingPropertyMaker(bwm); corr.setCorresponding(PR_BORDER_BEFORE_WIDTH, PR_BORDER_BEFORE_WIDTH, - PR_BORDER_START_WIDTH); + PR_BORDER_START_WIDTH, PR_BORDER_START_WIDTH); addPropertyMaker("border-top-width", bwm); // border-bottom-color @@ -791,7 +791,7 @@ public final class FOPropertyMapping implements Constants { m.addShorthand(generics[PR_BORDER]); corr = new CorrespondingPropertyMaker(m); corr.setCorresponding(PR_BORDER_AFTER_COLOR, PR_BORDER_AFTER_COLOR, - PR_BORDER_END_COLOR); + PR_BORDER_END_COLOR, PR_BORDER_END_COLOR); addPropertyMaker("border-bottom-color", m); // border-bottom-style @@ -802,7 +802,7 @@ public final class FOPropertyMapping implements Constants { m.addShorthand(generics[PR_BORDER]); corr = new CorrespondingPropertyMaker(m); corr.setCorresponding(PR_BORDER_AFTER_STYLE, PR_BORDER_AFTER_STYLE, - PR_BORDER_END_STYLE); + PR_BORDER_END_STYLE, PR_BORDER_END_STYLE); addPropertyMaker("border-bottom-style", m); // border-bottom-width @@ -814,7 +814,7 @@ public final class FOPropertyMapping implements Constants { bwm.addShorthand(generics[PR_BORDER]); corr = new CorrespondingPropertyMaker(bwm); corr.setCorresponding(PR_BORDER_AFTER_WIDTH, PR_BORDER_AFTER_WIDTH, - PR_BORDER_END_WIDTH); + PR_BORDER_END_WIDTH, PR_BORDER_END_WIDTH); addPropertyMaker("border-bottom-width", bwm); // border-left-color @@ -827,7 +827,7 @@ public final class FOPropertyMapping implements Constants { m.addShorthand(generics[PR_BORDER]); corr = new CorrespondingPropertyMaker(m); corr.setCorresponding(PR_BORDER_START_COLOR, PR_BORDER_END_COLOR, - PR_BORDER_AFTER_COLOR); + PR_BORDER_AFTER_COLOR, PR_BORDER_BEFORE_COLOR); addPropertyMaker("border-left-color", m); // border-left-style @@ -838,7 +838,7 @@ public final class FOPropertyMapping implements Constants { m.addShorthand(generics[PR_BORDER]); corr = new CorrespondingPropertyMaker(m); corr.setCorresponding(PR_BORDER_START_STYLE, PR_BORDER_END_STYLE, - PR_BORDER_AFTER_STYLE); + PR_BORDER_AFTER_STYLE, PR_BORDER_BEFORE_STYLE); addPropertyMaker("border-left-style", m); // border-left-width @@ -850,7 +850,7 @@ public final class FOPropertyMapping implements Constants { bwm.addShorthand(generics[PR_BORDER]); corr = new CorrespondingPropertyMaker(bwm); corr.setCorresponding(PR_BORDER_START_WIDTH, PR_BORDER_END_WIDTH, - PR_BORDER_AFTER_WIDTH); + PR_BORDER_AFTER_WIDTH, PR_BORDER_BEFORE_WIDTH); addPropertyMaker("border-left-width", bwm); // border-right-color @@ -863,7 +863,7 @@ public final class FOPropertyMapping implements Constants { m.addShorthand(generics[PR_BORDER]); corr = new CorrespondingPropertyMaker(m); corr.setCorresponding(PR_BORDER_END_COLOR, PR_BORDER_START_COLOR, - PR_BORDER_BEFORE_COLOR); + PR_BORDER_BEFORE_COLOR, PR_BORDER_AFTER_COLOR); addPropertyMaker("border-right-color", m); // border-right-style @@ -874,7 +874,7 @@ public final class FOPropertyMapping implements Constants { m.addShorthand(generics[PR_BORDER]); corr = new CorrespondingPropertyMaker(m); corr.setCorresponding(PR_BORDER_END_STYLE, PR_BORDER_START_STYLE, - PR_BORDER_BEFORE_STYLE); + PR_BORDER_BEFORE_STYLE, PR_BORDER_AFTER_STYLE); addPropertyMaker("border-right-style", m); // border-right-width @@ -886,7 +886,7 @@ public final class FOPropertyMapping implements Constants { bwm.addShorthand(generics[PR_BORDER]); corr = new CorrespondingPropertyMaker(bwm); corr.setCorresponding(PR_BORDER_END_WIDTH, PR_BORDER_START_WIDTH, - PR_BORDER_BEFORE_WIDTH); + PR_BORDER_BEFORE_WIDTH, PR_BORDER_AFTER_WIDTH); addPropertyMaker("border-right-width", bwm); // padding-before @@ -895,7 +895,7 @@ public final class FOPropertyMapping implements Constants { m.getSubpropMaker(CP_CONDITIONALITY).setDefault("discard"); corr = new CorrespondingPropertyMaker(m); corr.setCorresponding(PR_PADDING_TOP, PR_PADDING_TOP, - PR_PADDING_RIGHT); + PR_PADDING_RIGHT, PR_PADDING_LEFT); corr.setRelative(true); addPropertyMaker("padding-before", m); @@ -905,7 +905,7 @@ public final class FOPropertyMapping implements Constants { m.getSubpropMaker(CP_CONDITIONALITY).setDefault("discard"); corr = new CorrespondingPropertyMaker(m); corr.setCorresponding(PR_PADDING_BOTTOM, PR_PADDING_BOTTOM, - PR_PADDING_LEFT); + PR_PADDING_LEFT, PR_PADDING_RIGHT); corr.setRelative(true); addPropertyMaker("padding-after", m); @@ -915,7 +915,7 @@ public final class FOPropertyMapping implements Constants { m.getSubpropMaker(CP_CONDITIONALITY).setDefault("discard"); corr = new CorrespondingPropertyMaker(m); corr.setCorresponding(PR_PADDING_LEFT, PR_PADDING_RIGHT, - PR_PADDING_TOP); + PR_PADDING_TOP, PR_PADDING_TOP); corr.setRelative(true); addPropertyMaker("padding-start", m); @@ -925,7 +925,7 @@ public final class FOPropertyMapping implements Constants { m.getSubpropMaker(CP_CONDITIONALITY).setDefault("discard"); corr = new CorrespondingPropertyMaker(m); corr.setCorresponding(PR_PADDING_RIGHT, PR_PADDING_LEFT, - PR_PADDING_BOTTOM); + PR_PADDING_BOTTOM, PR_PADDING_BOTTOM); corr.setRelative(true); addPropertyMaker("padding-end", m); @@ -934,7 +934,7 @@ public final class FOPropertyMapping implements Constants { m.useGeneric(genericPadding); corr = new CorrespondingPropertyMaker(m); corr.setCorresponding(PR_PADDING_BEFORE, PR_PADDING_BEFORE, - PR_PADDING_START); + PR_PADDING_START, PR_PADDING_START); addPropertyMaker("padding-top", m); // padding-bottom @@ -942,7 +942,7 @@ public final class FOPropertyMapping implements Constants { m.useGeneric(genericPadding); corr = new CorrespondingPropertyMaker(m); corr.setCorresponding(PR_PADDING_AFTER, PR_PADDING_AFTER, - PR_PADDING_END); + PR_PADDING_END, PR_PADDING_END); addPropertyMaker("padding-bottom", m); // padding-left @@ -950,7 +950,7 @@ public final class FOPropertyMapping implements Constants { m.useGeneric(genericPadding); corr = new CorrespondingPropertyMaker(m); corr.setCorresponding(PR_PADDING_START, PR_PADDING_END, - PR_PADDING_AFTER); + PR_PADDING_AFTER, PR_PADDING_BEFORE); addPropertyMaker("padding-left", m); // padding-right @@ -958,7 +958,7 @@ public final class FOPropertyMapping implements Constants { m.useGeneric(genericPadding); corr = new CorrespondingPropertyMaker(m); corr.setCorresponding(PR_PADDING_END, PR_PADDING_START, - PR_PADDING_BEFORE); + PR_PADDING_BEFORE, PR_PADDING_AFTER); addPropertyMaker("padding-right", m); } @@ -1151,7 +1151,7 @@ public final class FOPropertyMapping implements Constants { m = new SpaceProperty.Maker(PR_SPACE_BEFORE); m.useGeneric(genericSpace); corr = new SpacePropertyMaker(m); - corr.setCorresponding(PR_MARGIN_TOP, PR_MARGIN_TOP, PR_MARGIN_RIGHT); + corr.setCorresponding(PR_MARGIN_TOP, PR_MARGIN_TOP, PR_MARGIN_RIGHT, PR_MARGIN_LEFT); corr.setUseParent(false); corr.setRelative(true); addPropertyMaker("space-before", m); @@ -1160,7 +1160,7 @@ public final class FOPropertyMapping implements Constants { m = new SpaceProperty.Maker(PR_SPACE_AFTER); m.useGeneric(genericSpace); corr = new SpacePropertyMaker(m); - corr.setCorresponding(PR_MARGIN_BOTTOM, PR_MARGIN_BOTTOM, PR_MARGIN_LEFT); + corr.setCorresponding(PR_MARGIN_BOTTOM, PR_MARGIN_BOTTOM, PR_MARGIN_LEFT, PR_MARGIN_RIGHT); corr.setUseParent(false); corr.setRelative(true); addPropertyMaker("space-after", m); @@ -1171,14 +1171,14 @@ public final class FOPropertyMapping implements Constants { m.setDefault("0pt"); m.setPercentBase(LengthBase.CONTAINING_REFAREA_WIDTH); IndentPropertyMaker sCorr = new IndentPropertyMaker(m); - sCorr.setCorresponding(PR_MARGIN_LEFT, PR_MARGIN_RIGHT, PR_MARGIN_TOP); + sCorr.setCorresponding(PR_MARGIN_LEFT, PR_MARGIN_RIGHT, PR_MARGIN_TOP, PR_MARGIN_TOP); sCorr.setUseParent(false); sCorr.setRelative(true); sCorr.setPaddingCorresponding(new int[] { - PR_PADDING_LEFT, PR_PADDING_RIGHT, PR_PADDING_TOP + PR_PADDING_LEFT, PR_PADDING_RIGHT, PR_PADDING_TOP, PR_PADDING_TOP }); sCorr.setBorderWidthCorresponding(new int[] { - PR_BORDER_LEFT_WIDTH, PR_BORDER_RIGHT_WIDTH, PR_BORDER_TOP_WIDTH + PR_BORDER_LEFT_WIDTH, PR_BORDER_RIGHT_WIDTH, PR_BORDER_TOP_WIDTH, PR_BORDER_TOP_WIDTH }); addPropertyMaker("start-indent", m); @@ -1188,14 +1188,16 @@ public final class FOPropertyMapping implements Constants { m.setDefault("0pt"); m.setPercentBase(LengthBase.CONTAINING_REFAREA_WIDTH); IndentPropertyMaker eCorr = new IndentPropertyMaker(m); - eCorr.setCorresponding(PR_MARGIN_RIGHT, PR_MARGIN_LEFT, PR_MARGIN_BOTTOM); + eCorr.setCorresponding(PR_MARGIN_RIGHT, PR_MARGIN_LEFT, + PR_MARGIN_BOTTOM, PR_MARGIN_BOTTOM); eCorr.setUseParent(false); eCorr.setRelative(true); eCorr.setPaddingCorresponding(new int[] { - PR_PADDING_RIGHT, PR_PADDING_LEFT, PR_PADDING_BOTTOM + PR_PADDING_RIGHT, PR_PADDING_LEFT, PR_PADDING_BOTTOM, PR_PADDING_BOTTOM }); eCorr.setBorderWidthCorresponding(new int[] { - PR_BORDER_RIGHT_WIDTH, PR_BORDER_LEFT_WIDTH, PR_BORDER_BOTTOM_WIDTH + PR_BORDER_RIGHT_WIDTH, PR_BORDER_LEFT_WIDTH, + PR_BORDER_BOTTOM_WIDTH, PR_BORDER_BOTTOM_WIDTH }); addPropertyMaker("end-indent", m); } @@ -1352,10 +1354,10 @@ public final class FOPropertyMapping implements Constants { m.addSubpropMaker(l); pdim = new DimensionPropertyMaker(m); - pdim.setCorresponding(PR_HEIGHT, PR_HEIGHT, PR_WIDTH); + pdim.setCorresponding(PR_HEIGHT, PR_HEIGHT, PR_WIDTH, PR_WIDTH); pdim.setExtraCorresponding(new int[][] { - {PR_MIN_HEIGHT, PR_MIN_HEIGHT, PR_MIN_WIDTH, }, - {PR_MAX_HEIGHT, PR_MAX_HEIGHT, PR_MAX_WIDTH, } + {PR_MIN_HEIGHT, PR_MIN_HEIGHT, PR_MIN_WIDTH, PR_MIN_WIDTH}, + {PR_MAX_HEIGHT, PR_MAX_HEIGHT, PR_MAX_WIDTH, PR_MAX_WIDTH} }); pdim.setRelative(true); m.setCorresponding(pdim); @@ -1419,10 +1421,10 @@ public final class FOPropertyMapping implements Constants { pdim = new DimensionPropertyMaker(m); pdim.setRelative(true); - pdim.setCorresponding(PR_WIDTH, PR_WIDTH, PR_HEIGHT); + pdim.setCorresponding(PR_WIDTH, PR_WIDTH, PR_HEIGHT, PR_HEIGHT); pdim.setExtraCorresponding(new int[][] { - {PR_MIN_WIDTH, PR_MIN_WIDTH, PR_MIN_HEIGHT, }, - {PR_MAX_WIDTH, PR_MAX_WIDTH, PR_MAX_HEIGHT, } + {PR_MIN_WIDTH, PR_MIN_WIDTH, PR_MIN_HEIGHT, PR_MIN_HEIGHT }, + {PR_MAX_WIDTH, PR_MAX_WIDTH, PR_MAX_HEIGHT, PR_MIN_HEIGHT } }); m.setCorresponding(pdim); addPropertyMaker("inline-progression-dimension", m); @@ -1491,6 +1493,37 @@ public final class FOPropertyMapping implements Constants { addPropertyMaker("fox:block-progression-unit", l); } + private Property calcWritingModeDependent ( int pv, int wm ) { + if ( pv == EN_LEFT ) { + if ( wm == Constants.EN_LR_TB ) { + pv = EN_START; + } else if ( wm == Constants.EN_RL_TB ) { + pv = EN_END; + } else { + pv = EN_START; + } + } else if ( pv == EN_RIGHT ) { + if ( wm == Constants.EN_LR_TB ) { + pv = EN_END; + } else if ( wm == Constants.EN_RL_TB ) { + pv = EN_START; + } else { + pv = EN_END; + } + } + return makeWritingModeDependentEnum ( pv ); + } + + private Property makeWritingModeDependentEnum ( int pv ) { + if ( pv == EN_START ) { + return getEnumProperty ( EN_START, "START" ); + } else if ( pv == EN_END ) { + return getEnumProperty ( EN_END, "END" ); + } else { + return null; + } + } + private void createBlockAndLineProperties() { // CSOK: MethodLength PropertyMaker m; @@ -1576,16 +1609,29 @@ public final class FOPropertyMapping implements Constants { addPropertyMaker("white-space-treatment", m); // text-align TODO: make it a StringProperty with enums. - m = new EnumProperty.Maker(PR_TEXT_ALIGN); + m = new EnumProperty.Maker(PR_TEXT_ALIGN) { + public Property get(int subpropId, PropertyList propertyList, + boolean bTryInherit, boolean bTryDefault) throws PropertyException { + Property p = super.get(subpropId, propertyList, bTryInherit, bTryDefault); + if ( p != null ) { + int pv = p.getEnum(); + if ( ( pv == EN_LEFT ) || ( pv == EN_RIGHT ) ) { + p = calcWritingModeDependent + ( pv, propertyList.get(Constants.PR_WRITING_MODE).getEnum() ); + } + } + return p; + } + }; m.setInherited(true); - // Note: both 'end', 'right' and 'outside' are mapped to END - // both 'start', 'left' and 'inside' are mapped to START m.addEnum("center", getEnumProperty(EN_CENTER, "CENTER")); m.addEnum("end", getEnumProperty(EN_END, "END")); - m.addEnum("right", getEnumProperty(EN_END, "END")); m.addEnum("start", getEnumProperty(EN_START, "START")); - m.addEnum("left", getEnumProperty(EN_START, "START")); m.addEnum("justify", getEnumProperty(EN_JUSTIFY, "JUSTIFY")); + // [GA] must defer writing-mode relative mapping of left/right + m.addEnum("left", getEnumProperty(EN_LEFT, "LEFT")); + m.addEnum("right", getEnumProperty(EN_RIGHT, "RIGHT")); + // [GA] inside and outside are not correctly implemented by the following mapping m.addEnum("inside", getEnumProperty(EN_START, "START")); m.addEnum("outside", getEnumProperty(EN_END, "END")); m.setDefault("start"); @@ -1605,7 +1651,6 @@ public final class FOPropertyMapping implements Constants { } return p; } - private Property calcRelative(PropertyList propertyList) throws PropertyException { Property corresponding = propertyList.get(PR_TEXT_ALIGN); if (corresponding == null) { @@ -1620,6 +1665,12 @@ public final class FOPropertyMapping implements Constants { return getEnumProperty(EN_START, "START"); } else if (correspondingValue == EN_CENTER) { return getEnumProperty(EN_CENTER, "CENTER"); + } else if (correspondingValue == EN_LEFT) { + return calcWritingModeDependent + ( EN_LEFT, propertyList.get(Constants.PR_WRITING_MODE).getEnum() ); + } else if (correspondingValue == EN_RIGHT) { + return calcWritingModeDependent + ( EN_RIGHT, propertyList.get(Constants.PR_WRITING_MODE).getEnum() ); } else { return null; } @@ -2171,6 +2222,12 @@ public final class FOPropertyMapping implements Constants { m.addEnum("auto", getEnumProperty(EN_AUTO, "AUTO")); m.setDefault("auto"); addPropertyMaker("letter-value", m); + + // fox:alt-text, used for accessibility + m = new StringProperty.Maker(PR_X_NUMBER_CONVERSION_FEATURES); + m.setInherited(false); + m.setDefault(""); + addPropertyMaker("fox:number-conversion-features", m); } private void createPaginationAndLayoutProperties() { @@ -2512,6 +2569,7 @@ public final class FOPropertyMapping implements Constants { m.addEnum("lr-tb", getEnumProperty(EN_LR_TB, "LR_TB")); m.addEnum("rl-tb", getEnumProperty(EN_RL_TB, "RL_TB")); m.addEnum("tb-rl", getEnumProperty(EN_TB_RL, "TB_RL")); + m.addEnum("tb-lr", getEnumProperty(EN_TB_LR, "TB_LR")); m.addKeyword("lr", "lr-tb"); m.addKeyword("rl", "rl-tb"); m.addKeyword("tb", "tb-rl"); diff --git a/src/java/org/apache/fop/fo/FOText.java b/src/java/org/apache/fop/fo/FOText.java index 43b58685f..5dfe0766b 100644 --- a/src/java/org/apache/fop/fo/FOText.java +++ b/src/java/org/apache/fop/fo/FOText.java @@ -21,12 +21,15 @@ package org.apache.fop.fo; import java.awt.Color; import java.nio.CharBuffer; +import java.util.Map; import java.util.NoSuchElementException; +import java.util.Stack; import org.xml.sax.Locator; import org.apache.fop.accessibility.StructureTreeElement; import org.apache.fop.apps.FOPException; +import org.apache.fop.complexscripts.bidi.DelimitedTextRange; import org.apache.fop.datatypes.Length; import org.apache.fop.fo.flow.Block; import org.apache.fop.fo.properties.CommonFont; @@ -45,7 +48,8 @@ public class FOText extends FONode implements CharSequence { /** the CharBuffer containing the text */ private CharBuffer charBuffer; - /** properties relevant for #PCDATA */ + // The value of FO traits (refined properties) that apply to #PCDATA + // (aka implicit sequence of fo:character) private CommonFont commonFont; private CommonHyphenation commonHyphenation; private Color color; @@ -58,6 +62,10 @@ public class FOText extends FONode implements CharSequence { private Property wordSpacing; private int wrapOption; private Length baselineShift; + private String country; + private String language; + private String script; + // End of trait values /** * Points to the previous FOText object created within the current @@ -82,6 +90,12 @@ public class FOText extends FONode implements CharSequence { private StructureTreeElement structureTreeElement; + /* bidi levels */ + private int[] bidiLevels; + + /* advanced script processing state */ + private Map/**/ mappings; + private static final int IS_WORD_CHAR_FALSE = 0; private static final int IS_WORD_CHAR_TRUE = 1; private static final int IS_WORD_CHAR_MAYBE = 2; @@ -98,21 +112,31 @@ public class FOText extends FONode implements CharSequence { /** {@inheritDoc} */ protected void characters(char[] data, int start, int length, PropertyList list, Locator locator) throws FOPException { - - if (this.charBuffer == null) { + if (charBuffer == null) { // buffer not yet initialized, do so now - this.charBuffer = CharBuffer.allocate(length); + int newLength = ( length < 16 ) ? 16 : length; + charBuffer = CharBuffer.allocate(newLength); } else { // allocate a larger buffer, and transfer contents - int newLength = this.charBuffer.limit() + length; - CharBuffer newBuffer = CharBuffer.allocate(newLength); - this.charBuffer.rewind(); - newBuffer.put(this.charBuffer); - this.charBuffer = newBuffer; + int requires = charBuffer.position() + length; + int capacity = charBuffer.capacity(); + if ( requires > capacity ) { + int newCapacity = capacity * 2; + if ( requires > newCapacity ) { + newCapacity = requires; + } + CharBuffer newBuffer = CharBuffer.allocate(newCapacity); + charBuffer.rewind(); + newBuffer.put(charBuffer); + charBuffer = newBuffer; + } } + // extend limit to capacity + charBuffer.limit(charBuffer.capacity()); // append characters - this.charBuffer.put(data, start, length); - + charBuffer.put(data, start, length); + // shrink limit to position + charBuffer.limit(charBuffer.position()); } /** @@ -135,10 +159,10 @@ public class FOText extends FONode implements CharSequence { if (removeChildren) { // not really removing, just make sure the char buffer // pointed to is really a different one - if (this.charBuffer != null) { - ft.charBuffer = CharBuffer.allocate(this.charBuffer.limit()); - this.charBuffer.rewind(); - ft.charBuffer.put(this.charBuffer); + if (charBuffer != null) { + ft.charBuffer = CharBuffer.allocate(charBuffer.limit()); + charBuffer.rewind(); + ft.charBuffer.put(charBuffer); ft.charBuffer.rewind(); } } @@ -163,10 +187,16 @@ public class FOText extends FONode implements CharSequence { this.wrapOption = pList.get(Constants.PR_WRAP_OPTION).getEnum(); this.textDecoration = pList.getTextDecorationProps(); this.baselineShift = pList.get(Constants.PR_BASELINE_SHIFT).getLength(); + this.country = pList.get(Constants.PR_COUNTRY).getString(); + this.language = pList.get(Constants.PR_LANGUAGE).getString(); + this.script = pList.get(Constants.PR_SCRIPT).getString(); } /** {@inheritDoc} */ protected void endOfNode() throws FOPException { + if ( charBuffer != null ) { + charBuffer.rewind(); + } super.endOfNode(); getFOEventHandler().characters(this); } @@ -187,20 +217,20 @@ public class FOText extends FONode implements CharSequence { */ public boolean willCreateArea() { if (whiteSpaceCollapse == Constants.EN_FALSE - && this.charBuffer.limit() > 0) { + && charBuffer.limit() > 0) { return true; } char ch; - this.charBuffer.rewind(); - while (this.charBuffer.hasRemaining()) { - ch = this.charBuffer.get(); + charBuffer.rewind(); + while (charBuffer.hasRemaining()) { + ch = charBuffer.get(); if (!((ch == CharUtilities.SPACE) || (ch == CharUtilities.LINEFEED_CHAR) || (ch == CharUtilities.CARRIAGE_RETURN) || (ch == CharUtilities.TAB))) { // not whitespace - this.charBuffer.rewind(); + charBuffer.rewind(); return true; } } @@ -243,13 +273,13 @@ public class FOText extends FONode implements CharSequence { return; } - this.charBuffer.rewind(); - CharBuffer tmp = this.charBuffer.slice(); + charBuffer.rewind(); + CharBuffer tmp = charBuffer.slice(); char c; - int lim = this.charBuffer.limit(); + int lim = charBuffer.limit(); int pos = -1; while (++pos < lim) { - c = this.charBuffer.get(); + c = charBuffer.get(); switch (textTransform) { case Constants.EN_UPPERCASE: tmp.put(Character.toUpperCase(c)); @@ -374,25 +404,25 @@ public class FOText extends FONode implements CharSequence { * @return The previous FOText node in this Block; null, if this is the * first FOText in this Block. */ - public FOText getPrevFOTextThisBlock () { - return prevFOTextThisBlock; - } + //public FOText getPrevFOTextThisBlock () { + // return prevFOTextThisBlock; + //} /** * @return The next FOText node in this Block; null if this is the last * FOText in this Block; null if subsequent FOText nodes have not yet been * processed. */ - public FOText getNextFOTextThisBlock () { - return nextFOTextThisBlock; - } + //public FOText getNextFOTextThisBlock () { + // return nextFOTextThisBlock; + //} /** * @return The nearest ancestor block object which contains this FOText. */ - public Block getAncestorBlock () { - return ancestorBlock; - } + //public Block getAncestorBlock () { + // return ancestorBlock; + //} /** * Determines whether the input char should be considered part of a @@ -485,6 +515,9 @@ public class FOText extends FONode implements CharSequence { private boolean canRemove = false; private boolean canReplace = false; + public TextCharIterator() { + } + /** {@inheritDoc} */ public boolean hasNext() { return (this.currentPosition < charBuffer.limit()); @@ -556,67 +589,88 @@ public class FOText extends FONode implements CharSequence { } /** - * @return the "color" property. + * @return the "color" trait. */ public Color getColor() { return color; } /** - * @return the "keep-together" property. + * @return the "keep-together" trait. */ public KeepProperty getKeepTogether() { return keepTogether; } /** - * @return the "letter-spacing" property. + * @return the "letter-spacing" trait. */ public Property getLetterSpacing() { return letterSpacing; } /** - * @return the "line-height" property. + * @return the "line-height" trait. */ public SpaceProperty getLineHeight() { return lineHeight; } /** - * @return the "white-space-treatment" property + * @return the "white-space-treatment" trait */ public int getWhitespaceTreatment() { return whiteSpaceTreatment; } /** - * @return the "word-spacing" property. + * @return the "word-spacing" trait. */ public Property getWordSpacing() { return wordSpacing; } /** - * @return the "wrap-option" property. + * @return the "wrap-option" trait. */ public int getWrapOption() { return wrapOption; } - /** @return the "text-decoration" property. */ + /** @return the "text-decoration" trait. */ public CommonTextDecoration getTextDecoration() { return textDecoration; } - /** @return the baseline-shift property */ + /** @return the baseline-shift trait */ public Length getBaseLineShift() { return baselineShift; } + /** @return the country trait */ + public String getCountry() { + return country; + } + + /** @return the language trait */ + public String getLanguage() { + return language; + } + + /** @return the script trait */ + public String getScript() { + return script; + } + /** {@inheritDoc} */ public String toString() { - return (this.charBuffer == null) ? "" : this.charBuffer.toString(); + if ( charBuffer == null ) { + return ""; + } else { + CharBuffer cb = charBuffer.duplicate(); + cb.rewind(); + return cb.toString(); + } } /** {@inheritDoc} */ @@ -640,28 +694,33 @@ public class FOText extends FONode implements CharSequence { /** {@inheritDoc} */ public char charAt(int position) { - return this.charBuffer.get(position); + return charBuffer.get(position); } /** {@inheritDoc} */ public CharSequence subSequence(int start, int end) { - return this.charBuffer.subSequence(start, end); + return charBuffer.subSequence(start, end); } /** {@inheritDoc} */ public int length() { - return this.charBuffer.limit(); + return charBuffer.limit(); } /** * Resets the backing java.nio.CharBuffer */ public void resetBuffer() { - if (this.charBuffer != null) { - this.charBuffer.rewind(); + if (charBuffer != null) { + charBuffer.rewind(); } } + @Override + public boolean isDelimitedTextRangeBoundary ( int boundary ) { + return false; + } + @Override public void setStructureTreeElement(StructureTreeElement structureTreeElement) { this.structureTreeElement = structureTreeElement; @@ -672,4 +731,192 @@ public class FOText extends FONode implements CharSequence { return structureTreeElement; } + /** + * Set bidirectional level over interval [start,end). + * @param level the resolved level + * @param start the starting index of interval + * @param end the ending index of interval + */ + public void setBidiLevel ( int level, int start, int end ) { + if ( start < end ) { + if ( bidiLevels == null ) { + bidiLevels = new int [ length() ]; + } + for ( int i = start, n = end; i < n; i++ ) { + bidiLevels [ i ] = level; + } + if ( parent != null ) { + ( (FObj) parent ).setBidiLevel ( level ); + } + } else { + assert start < end; + } + } + + /** + * Obtain bidirectional level of each character + * represented by this FOText. + * @return a (possibly empty) array of bidi levels or null + * in case no bidi levels have been assigned + */ + public int[] getBidiLevels() { + return bidiLevels; + } + + /** + * Obtain bidirectional level of each character over + * interval [start,end). + * @param start the starting index of interval + * @param end the ending index of interval + * @return a (possibly empty) array of bidi levels or null + * in case no bidi levels have been assigned + */ + public int[] getBidiLevels ( int start, int end ) { + if ( this.bidiLevels != null ) { + assert start <= end; + int n = end - start; + int[] bidiLevels = new int [ n ]; + for ( int i = 0; i < n; i++ ) { + bidiLevels[i] = this.bidiLevels [ start + i ]; + } + return bidiLevels; + } else { + return null; + } + } + + /** + * Obtain bidirectional level of character at + * specified position, which must be a non-negative integer + * less than the length of this FO. + * @param position an offset position into FO's characters + * @return a resolved bidi level or -1 if default + * @throws IndexOutOfBoundsException if position is not non-negative integer + * or is greater than or equal to length + */ + public int bidiLevelAt ( int position ) throws IndexOutOfBoundsException { + if ( ( position < 0 ) || ( position >= length() ) ) { + throw new IndexOutOfBoundsException(); + } else if ( bidiLevels != null ) { + return bidiLevels [ position ]; + } else { + return -1; + } + } + + /** + * Add characters mapped by script substitution processing. + * @param start index in character buffer + * @param end index in character buffer + * @param mappedChars sequence of character codes denoting substituted characters + */ + public void addMapping ( int start, int end, CharSequence mappedChars ) { + if ( mappings == null ) { + mappings = new java.util.HashMap(); + } + mappings.put ( new MapRange ( start, end ), mappedChars.toString() ); + } + + /** + * Determine if characters over specific interval have a mapping. + * @param start index in character buffer + * @param end index in character buffer + * @return true if a mapping exist such that the mapping's interval is coincident to + * [start,end) + */ + public boolean hasMapping ( int start, int end ) { + return ( mappings != null ) && ( mappings.containsKey ( new MapRange ( start, end ) ) ); + } + + /** + * Obtain mapping of characters over specific interval. + * @param start index in character buffer + * @param end index in character buffer + * @return a string of characters representing the mapping over the interval + * [start,end) + */ + public String getMapping ( int start, int end ) { + if ( mappings != null ) { + return (String) mappings.get ( new MapRange ( start, end ) ); + } else { + return null; + } + } + + /** + * Obtain length of mapping of characters over specific interval. + * @param start index in character buffer + * @param end index in character buffer + * @return the length of the mapping (if present) or zero + */ + public int getMappingLength ( int start, int end ) { + if ( mappings != null ) { + return ( (String) mappings.get ( new MapRange ( start, end ) ) ) .length(); + } else { + return 0; + } + } + + /** + * Obtain bidirectional levels of mapping of characters over specific interval. + * @param start index in character buffer + * @param end index in character buffer + * @return a (possibly empty) array of bidi levels or null + * in case no bidi levels have been assigned + */ + public int[] getMappingBidiLevels ( int start, int end ) { + if ( hasMapping ( start, end ) ) { + int nc = end - start; + int nm = getMappingLength ( start, end ); + int[] la = getBidiLevels ( start, end ); + if ( la == null ) { + return null; + } else if ( nm == nc ) { // mapping is same length as mapped range + return la; + } else if ( nm > nc ) { // mapping is longer than mapped range + int[] ma = new int [ nm ]; + System.arraycopy ( la, 0, ma, 0, la.length ); + for ( int i = la.length, + n = ma.length, l = ( i > 0 ) ? la [ i - 1 ] : 0; i < n; i++ ) { + ma [ i ] = l; + } + return ma; + } else { // mapping is shorter than mapped range + int[] ma = new int [ nm ]; + System.arraycopy ( la, 0, ma, 0, ma.length ); + return ma; + } + } else { + return getBidiLevels ( start, end ); + } + } + + @Override + protected Stack collectDelimitedTextRanges ( Stack ranges, DelimitedTextRange currentRange ) { + if ( currentRange != null ) { + currentRange.append ( charIterator(), this ); + } + return ranges; + } + + private static class MapRange { + private int start; + private int end; + MapRange(int start, int end) { + this.start = start; + this.end = end; + } + public int hashCode() { + return ( start * 31 ) + end; + } + public boolean equals ( Object o ) { + if ( o instanceof MapRange ) { + MapRange r = (MapRange) o; + return ( r.start == start ) && ( r.end == end ); + } else { + return false; + } + } + } + } diff --git a/src/java/org/apache/fop/fo/FObj.java b/src/java/org/apache/fop/fo/FObj.java index 27d0711f2..f1d78acf1 100644 --- a/src/java/org/apache/fop/fo/FObj.java +++ b/src/java/org/apache/fop/fo/FObj.java @@ -67,6 +67,8 @@ public abstract class FObj extends FONode implements Constants { /** Markers added to this element. */ private Map markers = null; + private int bidiLevel = -1; + // The value of properties relevant for all fo objects private String id = null; // End of property values @@ -118,9 +120,7 @@ public abstract class FObj extends FONode implements Constants { throws FOPException { setLocator(locator); pList.addAttributesToList(attlist); - if (!inMarker() - || "marker".equals(elementName)) { - pList.setWritingMode(); + if (!inMarker() || "marker".equals(elementName)) { bind(pList); } } @@ -558,6 +558,63 @@ public abstract class FObj extends FONode implements Constants { return "fo"; } + /** {@inheritDoc} */ + public boolean isBidiRangeBlockItem() { + String ns = getNamespaceURI(); + String ln = getLocalName(); + return !isNeutralItem(ns, ln) && isBlockItem(ns, ln); + } + + /** + * Recursively set resolved bidirectional level of FO (and its ancestors) if + * and only if it is non-negative and if either the current value is reset (-1) + * or the new value is less than the current value. + * @param bidiLevel a non-negative bidi embedding level + */ + public void setBidiLevel(int bidiLevel) { + assert bidiLevel >= 0; + if ( bidiLevel >= 0 ) { + if ( ( this.bidiLevel < 0 ) || ( bidiLevel < this.bidiLevel ) ) { + this.bidiLevel = bidiLevel; + if ( parent != null ) { + FObj foParent = (FObj) parent; + int parentBidiLevel = foParent.getBidiLevel(); + if ( ( parentBidiLevel < 0 ) || ( bidiLevel < parentBidiLevel ) ) { + foParent.setBidiLevel ( bidiLevel ); + } + } + } + } + } + + /** + * Obtain resolved bidirectional level of FO. + * @return either a non-negative bidi embedding level or -1 + * in case no bidi levels have been assigned + */ + public int getBidiLevel() { + return bidiLevel; + } + + /** + * Obtain resolved bidirectional level of FO or nearest FO + * ancestor that has a resolved level. + * @return either a non-negative bidi embedding level or -1 + * in case no bidi levels have been assigned to this FO or + * any ancestor + */ + public int getBidiLevelRecursive() { + for ( FONode fn = this; fn != null; fn = fn.getParent() ) { + if ( fn instanceof FObj ) { + int level = ( (FObj) fn).getBidiLevel(); + if ( level >= 0 ) { + return level; + } + } + } + return -1; + } + /** * Add a new extension attachment to this FObj. * (see org.apache.fop.fo.FONode for details) diff --git a/src/java/org/apache/fop/fo/PropertyList.java b/src/java/org/apache/fop/fo/PropertyList.java index 65ebd40a2..0852c6e29 100644 --- a/src/java/org/apache/fop/fo/PropertyList.java +++ b/src/java/org/apache/fop/fo/PropertyList.java @@ -46,8 +46,6 @@ import org.apache.fop.fo.properties.PropertyMaker; */ public abstract class PropertyList { - // writing-mode index - private int writingMode; private static boolean[] inheritableProperty; @@ -220,58 +218,60 @@ public abstract class PropertyList { } /** - * Set writing mode for this FO. - * Use that from the nearest ancestor, including self, which generates - * reference areas, or from root FO if no ancestor found. - * @throws PropertyException ... - */ - public void setWritingMode() throws PropertyException { - FObj p = fobj.findNearestAncestorFObj(); - // If this is a reference area or the root, use the property value. - if (fobj.generatesReferenceAreas() || p == null) { - writingMode = get(Constants.PR_WRITING_MODE).getEnum(); - } else { - // Otherwise get the writing mode value from the parent. - writingMode = getParentPropertyList().getWritingMode(); - } - } - - /** - * Return the "writing-mode" property value. - * @return the "writing-mode" property value. - */ - public int getWritingMode() { - return writingMode; - } - - - /** - * Uses the stored writingMode. + * Select a writing mode dependent property ID based on value of writing mode property. * @param lrtb the property ID to return under lrtb writingmode. * @param rltb the property ID to return under rltb writingmode. * @param tbrl the property ID to return under tbrl writingmode. + * @param tblr the property ID to return under tblr writingmode. * @return one of the property IDs, depending on the writing mode. */ - public int getWritingMode(int lrtb, int rltb, int tbrl) { - switch (writingMode) { - case Constants.EN_LR_TB: return lrtb; - case Constants.EN_RL_TB: return rltb; - case Constants.EN_TB_RL: return tbrl; + public int selectFromWritingMode(int lrtb, int rltb, int tbrl, int tblr) { + int propID; + try { + switch (get(Constants.PR_WRITING_MODE).getEnum()) { + case Constants.EN_LR_TB: + propID = lrtb; + break; + case Constants.EN_RL_TB: + propID = rltb; + break; + case Constants.EN_TB_RL: + propID = tbrl; + break; + case Constants.EN_TB_LR: + propID = tblr; + break; default: - //nop + propID = -1; + break; + } + } catch ( PropertyException e ) { + propID = -1; } - return -1; + return propID; } private String addAttributeToList(Attributes attributes, String attributeName) throws ValidationException { String attributeValue = attributes.getValue(attributeName); - convertAttributeToProperty(attributes, attributeName, attributeValue); + if ( attributeValue != null ) { + convertAttributeToProperty(attributes, attributeName, attributeValue); + } return attributeValue; } /** - * Adds the attributes, passed in by the parser to the PropertyList + *

    Adds the attributes, passed in by the parser to the PropertyList.

    + *

    Note that certain attributes are given priority in terms of order of + * processing due to conversion dependencies, where the order is as follows:

    + *
      + *
    1. writing-mode
    2. + *
    3. column-number
    4. + *
    5. number-columns-spanned
    6. + *
    7. font
    8. + *
    9. font-size
    10. + *
    11. all others in order of appearance
    12. + *
    * * @param attributes Collection of attributes passed to us from the parser. * @throws ValidationException if there is an attribute that does not @@ -279,6 +279,11 @@ public abstract class PropertyList { */ public void addAttributesToList(Attributes attributes) throws ValidationException { + /* + * Give writing-mode highest conversion priority. + */ + addAttributeToList(attributes, "writing-mode"); + /* * If column-number/number-columns-spanned are specified, then we * need them before all others (possible from-table-column() on any @@ -300,9 +305,9 @@ public abstract class PropertyList { addAttributeToList(attributes, "font-size"); } + String attributeNS; String attributeName; String attributeValue; - String attributeNS; FopFactory factory = getFObj().getUserAgent().getFactory(); for (int i = 0; i < attributes.getLength(); i++) { /* convert all attributes with the same namespace as the fo element @@ -646,4 +651,3 @@ public abstract class PropertyList { return CommonTextDecoration.createFromPropertyList(this); } } - diff --git a/src/java/org/apache/fop/fo/flow/AbstractGraphics.java b/src/java/org/apache/fop/fo/flow/AbstractGraphics.java index d5fe2b500..3d93eaa8f 100644 --- a/src/java/org/apache/fop/fo/flow/AbstractGraphics.java +++ b/src/java/org/apache/fop/fo/flow/AbstractGraphics.java @@ -19,8 +19,11 @@ package org.apache.fop.fo.flow; +import java.util.Stack; + import org.apache.fop.accessibility.StructureTreeElement; import org.apache.fop.apps.FOPException; +import org.apache.fop.complexscripts.bidi.DelimitedTextRange; import org.apache.fop.datatypes.Length; import org.apache.fop.fo.FONode; import org.apache.fop.fo.FObj; @@ -33,6 +36,7 @@ import org.apache.fop.fo.properties.KeepProperty; import org.apache.fop.fo.properties.LengthRangeProperty; import org.apache.fop.fo.properties.SpaceProperty; import org.apache.fop.fo.properties.StructureTreeElementHolder; +import org.apache.fop.util.CharUtilities; /** * Common base class for the @@ -77,8 +81,6 @@ public abstract class AbstractGraphics extends FObj // private int scalingMethod; // End of property values - - /** * constructs an instream-foreign-object object (called by Maker). * @@ -250,4 +252,18 @@ public abstract class AbstractGraphics extends FObj /** @return the graphic's intrinsic alignment-adjust */ public abstract Length getIntrinsicAlignmentAdjust(); + + @Override + public boolean isDelimitedTextRangeBoundary ( int boundary ) { + return false; + } + + @Override + protected Stack collectDelimitedTextRanges ( Stack ranges, DelimitedTextRange currentRange ) { + if ( currentRange != null ) { + currentRange.append ( CharUtilities.OBJECT_REPLACEMENT_CHARACTER, this ); + } + return ranges; + } + } diff --git a/src/java/org/apache/fop/fo/flow/AbstractPageNumberCitation.java b/src/java/org/apache/fop/fo/flow/AbstractPageNumberCitation.java index 5a6893b55..ec3891632 100644 --- a/src/java/org/apache/fop/fo/flow/AbstractPageNumberCitation.java +++ b/src/java/org/apache/fop/fo/flow/AbstractPageNumberCitation.java @@ -20,12 +20,14 @@ package org.apache.fop.fo.flow; import java.awt.Color; +import java.util.Stack; import org.xml.sax.Attributes; import org.xml.sax.Locator; import org.apache.fop.accessibility.StructureTreeElement; import org.apache.fop.apps.FOPException; +import org.apache.fop.complexscripts.bidi.DelimitedTextRange; import org.apache.fop.datatypes.Length; import org.apache.fop.fo.Constants; import org.apache.fop.fo.FONode; @@ -39,6 +41,7 @@ import org.apache.fop.fo.properties.CommonFont; import org.apache.fop.fo.properties.CommonTextDecoration; import org.apache.fop.fo.properties.SpaceProperty; import org.apache.fop.fo.properties.StructureTreeElementHolder; +import org.apache.fop.util.CharUtilities; /** * Common base class for the @@ -197,4 +200,17 @@ public abstract class AbstractPageNumberCitation extends FObj return refId; } + @Override + public boolean isDelimitedTextRangeBoundary ( int boundary ) { + return false; + } + + @Override + protected Stack collectDelimitedTextRanges ( Stack ranges, DelimitedTextRange currentRange ) { + if ( currentRange != null ) { + currentRange.append ( CharUtilities.OBJECT_REPLACEMENT_CHARACTER, this ); + } + return ranges; + } + } diff --git a/src/java/org/apache/fop/fo/flow/BidiOverride.java b/src/java/org/apache/fop/fo/flow/BidiOverride.java index 6e4a74379..d38df90c7 100644 --- a/src/java/org/apache/fop/fo/flow/BidiOverride.java +++ b/src/java/org/apache/fop/fo/flow/BidiOverride.java @@ -19,38 +19,37 @@ package org.apache.fop.fo.flow; +import java.util.Iterator; +import java.util.Stack; + import org.xml.sax.Locator; import org.apache.fop.apps.FOPException; +import org.apache.fop.complexscripts.bidi.DelimitedTextRange; +import org.apache.fop.datatypes.Length; +import org.apache.fop.fo.Constants; import org.apache.fop.fo.FONode; import org.apache.fop.fo.FObjMixed; import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.ValidationException; +import org.apache.fop.fo.properties.Property; import org.apache.fop.fo.properties.SpaceProperty; +import org.apache.fop.util.CharUtilities; /** * Class modelling the * fo:bidi-override object. */ -public class BidiOverride extends FObjMixed { - - // used for FO validation - private boolean blockOrInlineItemFound = false; - private boolean canHaveBlockLevelChildren = true; - // The value of properties relevant for fo:bidi-override. - // private ToBeImplementedProperty prDirection; - // private ToBeImplementedProperty prLetterSpacing; - private SpaceProperty lineHeight; - // private ToBeImplementedProperty prScoreSpaces; - // private ToBeImplementedProperty prUnicodeBidi; - - // Unused but valid items, commented out for performance: - // private CommonAural commonAural; - // private CommonFont commonFont; - // private CommonRelativePosition commonRelativePosition; - // private Color prColor; - // private SpaceProperty prWordSpacing; - // End of property values +public class BidiOverride extends Inline { + + // The value of FO traits (refined properties) that apply to fo:bidi-override + // (that are not implemented by InlineLevel). + private Property letterSpacing; + private Property wordSpacing; + private int direction; + private int unicodeBidi; + // private int scoreSpaces; + // End of trait values /** * Base constructor @@ -59,66 +58,35 @@ public class BidiOverride extends FObjMixed { */ public BidiOverride(FONode parent) { super(parent); - - /* Check to see if this node can have block-level children. - * See validateChildNode() below. - */ - int lvlLeader = findAncestor(FO_LEADER); - int lvlInCntr = findAncestor(FO_INLINE_CONTAINER); - int lvlInline = findAncestor(FO_INLINE); - int lvlFootnote = findAncestor(FO_FOOTNOTE); - - if (lvlLeader > 0) { - if (lvlInCntr < 0 || (lvlInCntr > 0 && lvlInCntr > lvlLeader)) { - canHaveBlockLevelChildren = false; - } - } else if (lvlInline > 0 && lvlFootnote == (lvlInline + 1)) { - if (lvlInCntr < 0 || (lvlInCntr > 0 && lvlInCntr > lvlInline)) { - canHaveBlockLevelChildren = false; - } - } - } /** {@inheritDoc} */ public void bind(PropertyList pList) throws FOPException { - // prDirection = pList.get(PR_DIRECTION); - // prLetterSpacing = pList.get(PR_LETTER_SPACING); - lineHeight = pList.get(PR_LINE_HEIGHT).getSpace(); - // prScoreSpaces = pList.get(PR_SCORE_SPACES); - // prUnicodeBidi = pList.get(PR_UNICODE_BIDI); + super.bind(pList); + letterSpacing = pList.get(PR_LETTER_SPACING); + wordSpacing = pList.get(PR_WORD_SPACING); + direction = pList.get(PR_DIRECTION).getEnum(); + unicodeBidi = pList.get(PR_UNICODE_BIDI).getEnum(); } - /** - * {@inheritDoc} - *
    XSL Content Model: marker* (#PCDATA|%inline;|%block;)* - *
    Additionally: "An fo:bidi-override that is a descendant of an fo:leader - * or of the fo:inline child of an fo:footnote may not have block-level - * children, unless it has a nearer ancestor that is an - * fo:inline-container." - */ - protected void validateChildNode(Locator loc, String nsURI, String localName) - throws ValidationException { - if (FO_URI.equals(nsURI)) { - if (localName.equals("marker")) { - if (blockOrInlineItemFound) { - nodesOutOfOrderError(loc, "fo:marker", - "(#PCDATA|%inline;|%block;)"); - } - } else if (!isBlockOrInlineItem(nsURI, localName)) { - invalidChildError(loc, nsURI, localName); - } else if (!canHaveBlockLevelChildren && isBlockItem(nsURI, localName)) { - invalidChildError(loc, getParent().getName(), nsURI, getName(), - "rule.bidiOverrideContent"); - } else { - blockOrInlineItemFound = true; - } - } + /** @return the "letter-spacing" trait */ + public Property getLetterSpacing() { + return letterSpacing; + } + + /** @return the "word-spacing" trait */ + public Property getWordSpacing() { + return wordSpacing; } - /** @return the "line-height" property */ - public SpaceProperty getLineHeight() { - return lineHeight; + /** @return the "direction" trait */ + public int getDirection() { + return direction; + } + + /** @return the "unicodeBidi" trait */ + public int getUnicodeBidi() { + return unicodeBidi; } /** {@inheritDoc} */ @@ -133,4 +101,32 @@ public class BidiOverride extends FObjMixed { public int getNameId() { return FO_BIDI_OVERRIDE; } + + @Override + protected Stack collectDelimitedTextRanges ( Stack ranges, DelimitedTextRange currentRange ) { + char pfx = 0; + char sfx = 0; + int unicodeBidi = getUnicodeBidi(); + int direction = getDirection(); + if ( unicodeBidi == Constants.EN_BIDI_OVERRIDE ) { + pfx = ( direction == Constants.EN_RTL ) ? CharUtilities.RLO : CharUtilities.LRO; + sfx = CharUtilities.PDF; + } else if ( unicodeBidi == Constants.EN_EMBED ) { + pfx = ( direction == Constants.EN_RTL ) ? CharUtilities.RLE : CharUtilities.LRE; + sfx = CharUtilities.PDF; + } + if ( currentRange != null ) { + if ( pfx != 0 ) { + currentRange.append ( pfx, this ); + } + for ( Iterator it = getChildNodes(); ( it != null ) && it.hasNext();) { + ranges = ( (FONode) it.next() ).collectDelimitedTextRanges ( ranges ); + } + if ( sfx != 0 ) { + currentRange.append ( sfx, this ); + } + } + return ranges; + } + } diff --git a/src/java/org/apache/fop/fo/flow/Block.java b/src/java/org/apache/fop/fo/flow/Block.java index 84f1abc1b..d93821ca6 100644 --- a/src/java/org/apache/fop/fo/flow/Block.java +++ b/src/java/org/apache/fop/fo/flow/Block.java @@ -54,7 +54,7 @@ public class Block extends FObjMixed implements BreakPropertySet, private boolean blockOrInlineItemFound = false; private boolean initialPropertySetFound = false; - // The value of properties relevant for fo:block. + // The value of FO traits (refined properties) that apply to fo:block. private CommonAccessibility commonAccessibility; private CommonBorderPaddingBackground commonBorderPaddingBackground; private CommonFont commonFont; @@ -91,7 +91,7 @@ public class Block extends FObjMixed implements BreakPropertySet, // private Length textDepth; // private Length textAltitude; // private int visibility; - // End of property values + // End of FO trait values /** * Base constructor @@ -177,87 +177,87 @@ public class Block extends FObjMixed implements BreakPropertySet, return commonHyphenation; } - /** @return the "break-after" property. */ + /** @return the "break-after" trait. */ public int getBreakAfter() { return breakAfter; } - /** @return the "break-before" property. */ + /** @return the "break-before" trait. */ public int getBreakBefore() { return breakBefore; } - /** @return the "hyphenation-ladder-count" property. */ + /** @return the "hyphenation-ladder-count" trait. */ public Numeric getHyphenationLadderCount() { return hyphenationLadderCount; } - /** @return the "keep-with-next" property. */ + /** @return the "keep-with-next" trait. */ public KeepProperty getKeepWithNext() { return keepWithNext; } - /** @return the "keep-with-previous" property. */ + /** @return the "keep-with-previous" trait. */ public KeepProperty getKeepWithPrevious() { return keepWithPrevious; } - /** @return the "keep-together" property. */ + /** @return the "keep-together" trait. */ public KeepProperty getKeepTogether() { return keepTogether; } - /** @return the "orphans" property. */ + /** @return the "orphans" trait. */ public int getOrphans() { return orphans.getValue(); } - /** @return the "widows" property. */ + /** @return the "widows" trait. */ public int getWidows() { return widows.getValue(); } - /** @return the "line-stacking-strategy" property. */ + /** @return the "line-stacking-strategy" trait. */ public int getLineStackingStrategy() { return lineStackingStrategy; } - /** @return the "color" property */ + /** @return the "color" trait */ public Color getColor() { return color; } - /** @return the "line-height" property */ + /** @return the "line-height" trait */ public SpaceProperty getLineHeight() { return lineHeight; } - /** @return the "span" property */ + /** @return the "span" trait */ public int getSpan() { return this.span; } - /** @return the "text-align" property */ + /** @return the "text-align" trait */ public int getTextAlign() { return textAlign; } - /** @return the "text-align-last" property */ + /** @return the "text-align-last" trait */ public int getTextAlignLast() { return textAlignLast; } - /** @return the "text-indent" property */ + /** @return the "text-indent" trait */ public Length getTextIndent() { return textIndent; } - /** @return the "last-line-end-indent" property */ + /** @return the "last-line-end-indent" trait */ public Length getLastLineEndIndent() { return lastLineEndIndent; } - /** @return the "wrap-option" property */ + /** @return the "wrap-option" trait */ public int getWrapOption() { return wrapOption; } @@ -295,17 +295,17 @@ public class Block extends FObjMixed implements BreakPropertySet, } } - /** @return the "linefeed-treatment" property */ + /** @return the "linefeed-treatment" trait */ public int getLinefeedTreatment() { return linefeedTreatment; } - /** @return the "white-space-treatment" property */ + /** @return the "white-space-treatment" trait */ public int getWhitespaceTreatment() { return whiteSpaceTreatment; } - /** @return the "white-space-collapse" property */ + /** @return the "white-space-collapse" trait */ public int getWhitespaceCollapse() { return whiteSpaceCollapse; } @@ -315,17 +315,17 @@ public class Block extends FObjMixed implements BreakPropertySet, return this.commonRelativePosition; } - /** @return the "hyphenation-keep" property */ + /** @return the "hyphenation-keep" trait */ public int getHyphenationKeep() { return this.hyphenationKeep; } - /** @return the "intrusion-displace" property */ + /** @return the "intrusion-displace" trait */ public int getIntrusionDisplace() { return this.intrusionDisplace; } - /** @return the "line-height-shift-adjustment" property */ + /** @return the "line-height-shift-adjustment" trait */ public int getLineHeightShiftAdjustment() { return this.lineHeightShiftAdjustment; } @@ -335,9 +335,9 @@ public class Block extends FObjMixed implements BreakPropertySet, * {@link org.apache.fop.fo.Constants#EN_TRUE}, * {@link org.apache.fop.fo.Constants#EN_FALSE} */ - public int getDisableColumnBalancing() { - return disableColumnBalancing; - } + public int getDisableColumnBalancing() { + return disableColumnBalancing; + } /** {@inheritDoc} */ @@ -350,10 +350,10 @@ public class Block extends FObjMixed implements BreakPropertySet, return "block"; } - /** - * {@inheritDoc} - * @return {@link org.apache.fop.fo.Constants#FO_BLOCK} - */ + /** + * {@inheritDoc} + * @return {@link org.apache.fop.fo.Constants#FO_BLOCK} + */ public int getNameId() { return FO_BLOCK; } diff --git a/src/java/org/apache/fop/fo/flow/BlockContainer.java b/src/java/org/apache/fop/fo/flow/BlockContainer.java index 57cb6e5c6..1dc43fd36 100644 --- a/src/java/org/apache/fop/fo/flow/BlockContainer.java +++ b/src/java/org/apache/fop/fo/flow/BlockContainer.java @@ -31,14 +31,18 @@ import org.apache.fop.fo.properties.CommonBorderPaddingBackground; import org.apache.fop.fo.properties.CommonMarginBlock; import org.apache.fop.fo.properties.KeepProperty; import org.apache.fop.fo.properties.LengthRangeProperty; +import org.apache.fop.traits.Direction; +import org.apache.fop.traits.WritingMode; +import org.apache.fop.traits.WritingModeTraits; +import org.apache.fop.traits.WritingModeTraitsGetter; import org.xml.sax.Locator; /** * Class modelling the * fo:block-container object. */ -public class BlockContainer extends FObj implements BreakPropertySet { - // The value of properties relevant for fo:block-container. +public class BlockContainer extends FObj implements BreakPropertySet, WritingModeTraitsGetter { + // The value of FO traits (refined properties) that apply to fo:block-container. private CommonAbsolutePosition commonAbsolutePosition; private CommonBorderPaddingBackground commonBorderPaddingBackground; private CommonMarginBlock commonMarginBlock; @@ -55,11 +59,11 @@ public class BlockContainer extends FObj implements BreakPropertySet { private Numeric referenceOrientation; private int span; private int disableColumnBalancing; - private int writingMode; + private WritingModeTraits writingModeTraits; // Unused but valid items, commented out for performance: // private int intrusionDisplace; // private Numeric zIndex; - // End of property values + // End of FO trait values /** used for FO validation */ private boolean blockItemFound = false; @@ -92,7 +96,8 @@ public class BlockContainer extends FObj implements BreakPropertySet { overflow = pList.get(PR_OVERFLOW).getEnum(); referenceOrientation = pList.get(PR_REFERENCE_ORIENTATION).getNumeric(); span = pList.get(PR_SPAN).getEnum(); - writingMode = pList.get(PR_WRITING_MODE).getEnum(); + writingModeTraits = new WritingModeTraits + ( WritingMode.valueOf(pList.get(PR_WRITING_MODE).getEnum()) ); disableColumnBalancing = pList.get(PR_X_DISABLE_COLUMN_BALANCING).getEnum(); } @@ -161,58 +166,58 @@ public class BlockContainer extends FObj implements BreakPropertySet { } /** - * @return the "block-progression-dimension" property. + * @return the "block-progression-dimension" FO trait. */ public LengthRangeProperty getBlockProgressionDimension() { return blockProgressionDimension; } - /** @return the "display-align" property. */ + /** @return the "display-align" FO trait. */ public int getDisplayAlign() { return displayAlign; } - /** @return the "break-after" property. */ + /** @return the "break-after" FO trait. */ public int getBreakAfter() { return breakAfter; } - /** @return the "break-before" property. */ + /** @return the "break-before" FO trait. */ public int getBreakBefore() { return breakBefore; } - /** @return the "keep-with-next" property. */ + /** @return the "keep-with-next" FO trait. */ public KeepProperty getKeepWithNext() { return keepWithNext; } - /** @return the "keep-with-previous" property. */ + /** @return the "keep-with-previous" FO trait. */ public KeepProperty getKeepWithPrevious() { return keepWithPrevious; } - /** @return the "keep-together" property. */ + /** @return the "keep-together" FO trait. */ public KeepProperty getKeepTogether() { return keepTogether; } - /** @return the "inline-progression-dimension" property */ + /** @return the "inline-progression-dimension" FO trait */ public LengthRangeProperty getInlineProgressionDimension() { return inlineProgressionDimension; } - /** @return the "overflow" property */ + /** @return the "overflow" FO trait */ public int getOverflow() { return overflow; } - /** @return the "reference-orientation" property */ + /** @return the "reference-orientation" FO trait */ public int getReferenceOrientation() { return referenceOrientation.getValue(); } - /** @return the "span" property */ + /** @return the "span" FO trait */ public int getSpan() { return this.span; } @@ -226,10 +231,52 @@ public class BlockContainer extends FObj implements BreakPropertySet { return disableColumnBalancing; } + /** + * Obtain inline progression direction. + * @return the inline progression direction + */ + public Direction getInlineProgressionDirection() { + return writingModeTraits.getInlineProgressionDirection(); + } + + /** + * Obtain block progression direction. + * @return the block progression direction + */ + public Direction getBlockProgressionDirection() { + return writingModeTraits.getBlockProgressionDirection(); + } + + /** + * Obtain column progression direction. + * @return the column progression direction + */ + public Direction getColumnProgressionDirection() { + return writingModeTraits.getColumnProgressionDirection(); + } - /** @return the "writing-mode" property */ - public int getWritingMode() { - return writingMode; + /** + * Obtain row progression direction. + * @return the row progression direction + */ + public Direction getRowProgressionDirection() { + return writingModeTraits.getRowProgressionDirection(); + } + + /** + * Obtain (baseline) shift direction. + * @return the (baseline) shift direction + */ + public Direction getShiftDirection() { + return writingModeTraits.getShiftDirection(); + } + + /** + * Obtain writing mode. + * @return the writing mode + */ + public WritingMode getWritingMode() { + return writingModeTraits.getWritingMode(); } /** {@inheritDoc} */ diff --git a/src/java/org/apache/fop/fo/flow/Character.java b/src/java/org/apache/fop/fo/flow/Character.java index c4de9fb72..f48ff289e 100644 --- a/src/java/org/apache/fop/fo/flow/Character.java +++ b/src/java/org/apache/fop/fo/flow/Character.java @@ -21,11 +21,13 @@ package org.apache.fop.fo.flow; import java.awt.Color; import java.util.NoSuchElementException; +import java.util.Stack; import org.xml.sax.Locator; import org.apache.fop.accessibility.StructureTreeElement; import org.apache.fop.apps.FOPException; +import org.apache.fop.complexscripts.bidi.DelimitedTextRange; import org.apache.fop.datatypes.Length; import org.apache.fop.fo.CharIterator; import org.apache.fop.fo.FONode; @@ -233,6 +235,19 @@ public class Character extends FObj implements StructureTreeElementHolder { return FO_CHARACTER; } + @Override + public boolean isDelimitedTextRangeBoundary ( int boundary ) { + return false; + } + + @Override + protected Stack collectDelimitedTextRanges ( Stack ranges, DelimitedTextRange currentRange ) { + if ( currentRange != null ) { + currentRange.append ( charIterator(), this ); + } + return ranges; + } + private class FOCharIterator extends CharIterator { private boolean bFirst = true; diff --git a/src/java/org/apache/fop/fo/flow/InlineContainer.java b/src/java/org/apache/fop/fo/flow/InlineContainer.java index d2422a24b..a52801c3f 100644 --- a/src/java/org/apache/fop/fo/flow/InlineContainer.java +++ b/src/java/org/apache/fop/fo/flow/InlineContainer.java @@ -33,6 +33,10 @@ import org.apache.fop.fo.properties.CommonMarginInline; import org.apache.fop.fo.properties.KeepProperty; import org.apache.fop.fo.properties.LengthRangeProperty; import org.apache.fop.fo.properties.SpaceProperty; +import org.apache.fop.traits.Direction; +import org.apache.fop.traits.WritingMode; +import org.apache.fop.traits.WritingModeTraits; +import org.apache.fop.traits.WritingModeTraitsGetter; /** * Class modelling the @@ -40,7 +44,7 @@ import org.apache.fop.fo.properties.SpaceProperty; */ public class InlineContainer extends FObj { - // The value of properties relevant for fo:inline-container. + // The value of FO traits (refined properties) that apply to fo:inline-container. private Length alignmentAdjust; private int alignmentBaseline; private Length baselineShift; @@ -54,7 +58,7 @@ public class InlineContainer extends FObj { private SpaceProperty lineHeight; private int overflow; private Numeric referenceOrientation; - private int writingMode; + private WritingModeTraits writingModeTraits; // Unused but valid items, commented out for performance: // private CommonRelativePosition commonRelativePosition; // private int displayAlign; @@ -62,7 +66,7 @@ public class InlineContainer extends FObj { // private KeepProperty keepWithNext; // private KeepProperty keepWithPrevious; // private Length width; - // End of property values + // End of FO trait values /** used for FO validation */ private boolean blockItemFound = false; @@ -92,7 +96,8 @@ public class InlineContainer extends FObj { lineHeight = pList.get(PR_LINE_HEIGHT).getSpace(); overflow = pList.get(PR_OVERFLOW).getEnum(); referenceOrientation = pList.get(PR_REFERENCE_ORIENTATION).getNumeric(); - writingMode = pList.get(PR_WRITING_MODE).getEnum(); + writingModeTraits = new WritingModeTraits + ( WritingMode.valueOf(pList.get(PR_WRITING_MODE).getEnum()) ); } /** @@ -121,27 +126,27 @@ public class InlineContainer extends FObj { } } - /** @return the "alignment-adjust" property */ + /** @return the "alignment-adjust" FO trait */ public Length getAlignmentAdjust() { return alignmentAdjust; } - /** @return the "alignment-baseline" property */ + /** @return the "alignment-baseline" FO trait */ public int getAlignmentBaseline() { return alignmentBaseline; } - /** @return the "baseline-shift" property */ + /** @return the "baseline-shift" FO trait */ public Length getBaselineShift() { return baselineShift; } - /** @return the "block-progression-dimension" property */ + /** @return the "block-progression-dimension" FO trait */ public LengthRangeProperty getBlockProgressionDimension() { return blockProgressionDimension; } - /** @return the "clip" property */ + /** @return the "clip" FO trait */ public int getClip() { return clip; } @@ -156,39 +161,82 @@ public class InlineContainer extends FObj { return this.commonMarginInline; } - /** @return the "dominant-baseline" property */ + /** @return the "dominant-baseline" FO trait */ public int getDominantBaseline() { return dominantBaseline; } - /** @return the "keep-together" property */ + /** @return the "keep-together" FO trait */ public KeepProperty getKeepTogether() { return keepTogether; } - /** @return the "inline-progression-dimension" property */ + /** @return the "inline-progression-dimension" FO trait */ public LengthRangeProperty getInlineProgressionDimension() { return inlineProgressionDimension; } - /** @return the "line-height" property */ + /** @return the "line-height" FO trait */ public SpaceProperty getLineHeight() { return lineHeight; } - /** @return the "overflow" property */ + /** @return the "overflow" FO trait */ public int getOverflow() { return overflow; } - /** @return the "reference-orientation" property */ + /** @return the "reference-orientation" FO trait */ public int getReferenceOrientation() { return referenceOrientation.getValue(); } - /** @return the "writing-mode" property */ - public int getWritingMode() { - return writingMode; + /** + * Obtain inline progression direction. + * @return the inline progression direction + */ + public Direction getInlineProgressionDirection() { + return writingModeTraits.getInlineProgressionDirection(); + } + + /** + * Obtain block progression direction. + * @return the block progression direction + */ + public Direction getBlockProgressionDirection() { + return writingModeTraits.getBlockProgressionDirection(); + } + + /** + * Obtain column progression direction. + * @return the column progression direction + */ + public Direction getColumnProgressionDirection() { + return writingModeTraits.getColumnProgressionDirection(); + } + + /** + * Obtain row progression direction. + * @return the row progression direction + */ + public Direction getRowProgressionDirection() { + return writingModeTraits.getRowProgressionDirection(); + } + + /** + * Obtain (baseline) shift direction. + * @return the (baseline) shift direction + */ + public Direction getShiftDirection() { + return writingModeTraits.getShiftDirection(); + } + + /** + * Obtain writing mode. + * @return the writing mode + */ + public WritingMode getWritingMode() { + return writingModeTraits.getWritingMode(); } /** {@inheritDoc} */ @@ -204,4 +252,9 @@ public class InlineContainer extends FObj { return FO_INLINE_CONTAINER; } + @Override + public boolean isDelimitedTextRangeBoundary ( int boundary ) { + return false; + } + } diff --git a/src/java/org/apache/fop/fo/flow/InlineLevel.java b/src/java/org/apache/fop/fo/flow/InlineLevel.java index 0da769080..b0531f859 100644 --- a/src/java/org/apache/fop/fo/flow/InlineLevel.java +++ b/src/java/org/apache/fop/fo/flow/InlineLevel.java @@ -39,7 +39,7 @@ import org.apache.fop.fo.properties.SpaceProperty; */ public abstract class InlineLevel extends FObjMixed implements CommonAccessibilityHolder { - // The value of properties relevant for inline-level FOs. + // The value of FO traits (refined properties) that apply to inline level FOs. private CommonAccessibility commonAccessibility; private CommonBorderPaddingBackground commonBorderPaddingBackground; private CommonMarginInline commonMarginInline; @@ -48,7 +48,7 @@ public abstract class InlineLevel extends FObjMixed implements CommonAccessibili private KeepProperty keepWithNext; private KeepProperty keepWithPrevious; private SpaceProperty lineHeight; - // End of property values + // End of trait values /** * Base constructor @@ -92,24 +92,29 @@ public abstract class InlineLevel extends FObjMixed implements CommonAccessibili return commonFont; } - /** @return the "color" property */ + /** @return the "color" trait */ public Color getColor() { return color; } - /** @return the "line-height" property */ + /** @return the "line-height" trait */ public SpaceProperty getLineHeight() { return lineHeight; } - /** @return the "keep-with-next" property */ + /** @return the "keep-with-next" trait */ public KeepProperty getKeepWithNext() { return keepWithNext; } - /** @return the "keep-with-previous" property */ + /** @return the "keep-with-previous" trait */ public KeepProperty getKeepWithPrevious() { return keepWithPrevious; } + @Override + public boolean isDelimitedTextRangeBoundary ( int boundary ) { + return false; + } + } diff --git a/src/java/org/apache/fop/fo/flow/Leader.java b/src/java/org/apache/fop/fo/flow/Leader.java index f12930dde..ce166b114 100644 --- a/src/java/org/apache/fop/fo/flow/Leader.java +++ b/src/java/org/apache/fop/fo/flow/Leader.java @@ -19,18 +19,24 @@ package org.apache.fop.fo.flow; +import java.util.Stack; + +import org.xml.sax.Locator; + import org.apache.fop.apps.FOPException; +import org.apache.fop.complexscripts.bidi.DelimitedTextRange; import org.apache.fop.datatypes.Length; import org.apache.fop.fo.FONode; import org.apache.fop.fo.PropertyList; +import org.apache.fop.fo.ValidationException; import org.apache.fop.fo.properties.LengthRangeProperty; +import org.apache.fop.util.CharUtilities; /** * Class modelling the * fo:leader object. * The main property of fo:leader is leader-pattern. * The following patterns are treated: rule, space, dots and use-content. - * TODO implement validateChildNode() */ public class Leader extends InlineLevel { // The value of properties relevant for fo:leader. @@ -96,6 +102,28 @@ public class Leader extends InlineLevel { // textShadow = pList.get(PR_TEXT_SHADOW); } + /** + * {@inheritDoc} + *
    XSL Content Model: (#PCDATA|%inline;)* + *
    Additionally: "The content must not contain an + * fo:leader, fo:inline-container, fo:block-container, fo:float, + * fo:footnote, or fo:marker either as a direct child or as a + * descendant." + */ + protected void validateChildNode(Locator loc, String nsURI, String localName) + throws ValidationException { + if (FO_URI.equals(nsURI)) { + if ( localName.equals("leader") + || localName.equals("inline-container") + || localName.equals("block-container") + || localName.equals("float") + || localName.equals("marker") + || !isInlineItem(nsURI, localName) ) { + invalidChildError(loc, nsURI, localName); + } + } + } + /** @return the "rule-style" property */ public int getRuleStyle() { return ruleStyle; @@ -170,4 +198,17 @@ public class Leader extends InlineLevel { super.endOfNode(); getFOEventHandler().endLeader(this); } + + @Override + protected Stack collectDelimitedTextRanges ( Stack ranges, DelimitedTextRange currentRange ) { + if ( currentRange != null ) { + if ( leaderPattern == EN_USECONTENT ) { + ranges = super.collectDelimitedTextRanges ( ranges, currentRange ); + } else { + currentRange.append ( CharUtilities.OBJECT_REPLACEMENT_CHARACTER, this ); + } + } + return ranges; + } + } diff --git a/src/java/org/apache/fop/fo/flow/ListItem.java b/src/java/org/apache/fop/fo/flow/ListItem.java index aa177777c..f61254874 100644 --- a/src/java/org/apache/fop/fo/flow/ListItem.java +++ b/src/java/org/apache/fop/fo/flow/ListItem.java @@ -19,9 +19,12 @@ package org.apache.fop.fo.flow; +import java.util.Stack; + import org.xml.sax.Locator; import org.apache.fop.apps.FOPException; +import org.apache.fop.complexscripts.bidi.DelimitedTextRange; import org.apache.fop.fo.FONode; import org.apache.fop.fo.FObj; import org.apache.fop.fo.PropertyList; @@ -201,5 +204,19 @@ public class ListItem extends FObj implements BreakPropertySet, CommonAccessibil public int getNameId() { return FO_LIST_ITEM; } + + @Override + protected Stack collectDelimitedTextRanges ( Stack ranges, DelimitedTextRange currentRange ) { + ListItemLabel label = getLabel(); + if ( label != null ) { + ranges = label.collectDelimitedTextRanges ( ranges ); + } + ListItemBody body = getBody(); + if ( body != null ) { + ranges = body.collectDelimitedTextRanges ( ranges ); + } + return ranges; + } + } diff --git a/src/java/org/apache/fop/fo/flow/PageNumber.java b/src/java/org/apache/fop/fo/flow/PageNumber.java index 59169c2d3..fe3e80a75 100644 --- a/src/java/org/apache/fop/fo/flow/PageNumber.java +++ b/src/java/org/apache/fop/fo/flow/PageNumber.java @@ -199,4 +199,10 @@ public class PageNumber extends FObj public int getNameId() { return FO_PAGE_NUMBER; } + + @Override + public boolean isDelimitedTextRangeBoundary ( int boundary ) { + return false; + } + } diff --git a/src/java/org/apache/fop/fo/flow/Wrapper.java b/src/java/org/apache/fop/fo/flow/Wrapper.java index 6c5619252..1302e3134 100644 --- a/src/java/org/apache/fop/fo/flow/Wrapper.java +++ b/src/java/org/apache/fop/fo/flow/Wrapper.java @@ -135,5 +135,11 @@ public class Wrapper extends FObjMixed { public int getNameId() { return FO_WRAPPER; } + + @Override + public boolean isDelimitedTextRangeBoundary ( int boundary ) { + return false; + } + } diff --git a/src/java/org/apache/fop/fo/flow/table/Table.java b/src/java/org/apache/fop/fo/flow/table/Table.java index c78f9f959..b14326af5 100644 --- a/src/java/org/apache/fop/fo/flow/table/Table.java +++ b/src/java/org/apache/fop/fo/flow/table/Table.java @@ -48,7 +48,7 @@ import org.apache.fop.fo.properties.TableColLength; public class Table extends TableFObj implements ColumnNumberManagerHolder, BreakPropertySet, CommonAccessibilityHolder { - /** properties */ + // The value of FO traits (refined properties) that apply to fo:table. private CommonAccessibility commonAccessibility; private CommonBorderPaddingBackground commonBorderPaddingBackground; private CommonMarginBlock commonMarginBlock; @@ -64,11 +64,12 @@ public class Table extends TableFObj implements ColumnNumberManagerHolder, Break private int tableLayout; private int tableOmitFooterAtBreak; private int tableOmitHeaderAtBreak; + private int writingMode; // Unused but valid items, commented out for performance: // private CommonAural commonAural; // private CommonRelativePosition commonRelativePosition; // private int intrusionDisplace; - // private int writingMode; + // End of FO trait values /** extension properties */ private Length widowContentLimit; @@ -130,6 +131,7 @@ public class Table extends TableFObj implements ColumnNumberManagerHolder, Break tableLayout = pList.get(PR_TABLE_LAYOUT).getEnum(); tableOmitFooterAtBreak = pList.get(PR_TABLE_OMIT_FOOTER_AT_BREAK).getEnum(); tableOmitHeaderAtBreak = pList.get(PR_TABLE_OMIT_HEADER_AT_BREAK).getEnum(); + writingMode = pList.get(PR_WRITING_MODE).getEnum(); //Bind extension properties widowContentLimit = pList.get(PR_X_WIDOW_CONTENT_LIMIT).getLength(); @@ -336,7 +338,6 @@ public class Table extends TableFObj implements ColumnNumberManagerHolder, Break TableColumn implicitColumn = new TableColumn(this, true); PropertyList pList = new StaticPropertyList( implicitColumn, this.propList); - pList.setWritingMode(); implicitColumn.bind(pList); implicitColumn.setColumnWidth(new TableColLength(1.0, implicitColumn)); implicitColumn.setColumnNumber(colNumber); @@ -433,14 +434,14 @@ public class Table extends TableFObj implements ColumnNumberManagerHolder, Break } /** - * @return the "inline-progression-dimension" property. + * @return the "inline-progression-dimension" FO trait. */ public LengthRangeProperty getInlineProgressionDimension() { return inlineProgressionDimension; } /** - * @return the "block-progression-dimension" property. + * @return the "block-progression-dimension" FO trait. */ public LengthRangeProperty getBlockProgressionDimension() { return blockProgressionDimension; @@ -460,27 +461,27 @@ public class Table extends TableFObj implements ColumnNumberManagerHolder, Break return commonBorderPaddingBackground; } - /** @return the "break-after" property. */ + /** @return the "break-after" FO trait. */ public int getBreakAfter() { return breakAfter; } - /** @return the "break-before" property. */ + /** @return the "break-before" FO trait. */ public int getBreakBefore() { return breakBefore; } - /** @return the "keep-with-next" property. */ + /** @return the "keep-with-next" FO trait. */ public KeepProperty getKeepWithNext() { return keepWithNext; } - /** @return the "keep-with-previous" property. */ + /** @return the "keep-with-previous" FO trait. */ public KeepProperty getKeepWithPrevious() { return keepWithPrevious; } - /** @return the "keep-together" property. */ + /** @return the "keep-together" FO trait. */ public KeepProperty getKeepTogether() { return keepTogether; } @@ -494,7 +495,7 @@ public class Table extends TableFObj implements ColumnNumberManagerHolder, Break || !getKeepTogether().getWithinColumn().isAuto(); } - /** @return the "border-collapse" property. */ + /** @return the "border-collapse" FO trait. */ public int getBorderCollapse() { return borderCollapse; } @@ -504,17 +505,22 @@ public class Table extends TableFObj implements ColumnNumberManagerHolder, Break return (getBorderCollapse() == EN_SEPARATE); } - /** @return the "border-separation" property. */ + /** @return the "border-separation" FO trait. */ public LengthPairProperty getBorderSeparation() { return borderSeparation; } - /** @return the "fox:widow-content-limit" extension property */ + /** @return the "writing-mode" FO trait */ + public int getWritingMode() { + return writingMode; + } + + /** @return the "fox:widow-content-limit" extension FO trait */ public Length getWidowContentLimit() { return widowContentLimit; } - /** @return the "fox:orphan-content-limit" extension property */ + /** @return the "fox:orphan-content-limit" extension FO trait */ public Length getOrphanContentLimit() { return orphanContentLimit; } diff --git a/src/java/org/apache/fop/fo/pagination/AbstractPageSequence.java b/src/java/org/apache/fop/fo/pagination/AbstractPageSequence.java index 51b24b314..8640ab19b 100644 --- a/src/java/org/apache/fop/fo/pagination/AbstractPageSequence.java +++ b/src/java/org/apache/fop/fo/pagination/AbstractPageSequence.java @@ -43,6 +43,9 @@ public abstract class AbstractPageSequence extends FObj { private char groupingSeparator; private int groupingSize; private Numeric referenceOrientation; //XSL 1.1 + private String language; + private String country; + private String numberConversionFeatures; // End of property values private PageNumberGenerator pageNumberGenerator; @@ -70,12 +73,16 @@ public abstract class AbstractPageSequence extends FObj { groupingSeparator = pList.get(PR_GROUPING_SEPARATOR).getCharacter(); groupingSize = pList.get(PR_GROUPING_SIZE).getNumber().intValue(); referenceOrientation = pList.get(PR_REFERENCE_ORIENTATION).getNumeric(); + language = pList.get(PR_LANGUAGE).getString(); + country = pList.get(PR_COUNTRY).getString(); + numberConversionFeatures = pList.get(PR_X_NUMBER_CONVERSION_FEATURES).getString(); } /** {@inheritDoc} */ protected void startOfNode() throws FOPException { this.pageNumberGenerator = new PageNumberGenerator( - format, groupingSeparator, groupingSize, letterValue); + format, groupingSeparator, groupingSize, letterValue, + numberConversionFeatures, language, country); } diff --git a/src/java/org/apache/fop/fo/pagination/PageNumberGenerator.java b/src/java/org/apache/fop/fo/pagination/PageNumberGenerator.java index 485fb67cc..ebd1919c4 100644 --- a/src/java/org/apache/fop/fo/pagination/PageNumberGenerator.java +++ b/src/java/org/apache/fop/fo/pagination/PageNumberGenerator.java @@ -19,84 +19,37 @@ package org.apache.fop.fo.pagination; +import org.apache.fop.complexscripts.util.NumberConverter; + +// CSOFF: LineLengthCheck + /** * This class uses the 'format', 'groupingSeparator', 'groupingSize', * and 'letterValue' properties on fo:page-sequence to return a String * corresponding to the supplied integer page number. + * + * In addition, (now) uses 'language' parameter and new 'fox:page-number-features' + * parameter to express applicable language and number conversion features. + * + * @author Glenn Adams (rewrite to use new NumberConverter utility) + * @see NumberConverter */ public class PageNumberGenerator { - private String format; - private char groupingSeparator; - private int groupingSize; - private int letterValue; - - // constants - private static final int DECIMAL = 1; // '0*1' - private static final int LOWERALPHA = 2; // 'a' - private static final int UPPERALPHA = 3; // 'A' - private static final int LOWERROMAN = 4; // 'i' - private static final int UPPERROMAN = 5; // 'I' - - // flags - private int formatType = DECIMAL; - private int minPadding = 0; // for decimal formats - - // preloaded strings of zeros - private String[] zeros = { - "", "0", "00", "000", "0000", "00000" - }; + private NumberConverter converter; /** - * Main constructor. For further information on the parameters see the XSLT - * specs (Number to String Conversion Attributes). - * @param format format for the page number - * @param groupingSeparator grouping separator - * @param groupingSize grouping size + * Main constructor. For further information on the parameters see {@link NumberConverter}. + * @param format format for the page number (may be null or empty, which is treated as null) + * @param groupingSeparator grouping separator (if zero, then no grouping separator applies) + * @param groupingSize grouping size (if zero or negative, then no grouping size applies) * @param letterValue letter value + * @param features features (feature sub-parameters) + * @param language (may be null or empty, which is treated as null) + * @param country (may be null or empty, which is treated as null) */ - public PageNumberGenerator(String format, char groupingSeparator, - int groupingSize, int letterValue) { - this.format = format; - this.groupingSeparator = groupingSeparator; - this.groupingSize = groupingSize; - this.letterValue = letterValue; - - // the only accepted format strings are currently '0*1' 'a', 'A', 'i' - // and 'I' - int fmtLen = format.length(); - if (fmtLen == 1) { - if (format.equals("1")) { - formatType = DECIMAL; - minPadding = 0; - } else if (format.equals("a")) { - formatType = LOWERALPHA; - } else if (format.equals("A")) { - formatType = UPPERALPHA; - } else if (format.equals("i")) { - formatType = LOWERROMAN; - } else if (format.equals("I")) { - formatType = UPPERROMAN; - } else { - // token not handled - //getLogger().debug("'format' token not recognized; using '1'"); - formatType = DECIMAL; - minPadding = 0; - } - } else { - // only accepted token is '0+1'at this stage. Because of the - // wonderful regular expression support in Java, we will resort to a - // loop - for (int i = 0; i < fmtLen - 1; i++) { - if (format.charAt(i) != '0') { - //getLogger().debug("'format' token not recognized; using '1'"); - formatType = DECIMAL; - minPadding = 0; - } else { - minPadding = fmtLen - 1; - } - } - } + public PageNumberGenerator ( String format, int groupingSeparator, int groupingSize, int letterValue, String features, String language, String country ) { + this.converter = new NumberConverter ( format, groupingSeparator, groupingSize, letterValue, features, language, country ); } /** @@ -104,70 +57,9 @@ public class PageNumberGenerator { * @param number page number to format * @return the formatted page number as a String */ - public String makeFormattedPageNumber(int number) { - String pn = null; - if (formatType == DECIMAL) { - pn = Integer.toString(number); - if (minPadding >= pn.length()) { - int nz = minPadding - pn.length() + 1; - pn = zeros[nz] + pn; - } - } else if ((formatType == LOWERROMAN) || (formatType == UPPERROMAN)) { - pn = makeRoman(number); - if (formatType == UPPERROMAN) { - pn = pn.toUpperCase(); - } - } else { - // alphabetic - pn = makeAlpha(number); - if (formatType == UPPERALPHA) { - pn = pn.toUpperCase(); - } - } - return pn; + public String makeFormattedPageNumber ( int number ) { + return converter.convert ( number ); } - private String makeRoman(int num) { - int[] arabic = { - 1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1 - }; - String[] roman = { - "m", "cm", "d", "cd", "c", "xc", "l", "xl", "x", "ix", "v", "iv", - "i" - }; - - int i = 0; - StringBuffer romanNumber = new StringBuffer(); - - while (num > 0) { - while (num >= arabic[i]) { - num = num - arabic[i]; - romanNumber.append(roman[i]); - } - i = i + 1; - } - return romanNumber.toString(); - } - - private String makeAlpha(int num) { - String letters = "abcdefghijklmnopqrstuvwxyz"; - StringBuffer alphaNumber = new StringBuffer(); - - int base = 26; - int rem = 0; - - num--; - if (num < base) { - alphaNumber.append(letters.charAt(num)); - } else { - while (num >= base) { - rem = num % base; - alphaNumber.append(letters.charAt(rem)); - num = num / base; - } - alphaNumber.append(letters.charAt(num - 1)); - } - return alphaNumber.reverse().toString(); - } } diff --git a/src/java/org/apache/fop/fo/pagination/PageSequence.java b/src/java/org/apache/fop/fo/pagination/PageSequence.java index 1c3b33fa7..63114b507 100644 --- a/src/java/org/apache/fop/fo/pagination/PageSequence.java +++ b/src/java/org/apache/fop/fo/pagination/PageSequence.java @@ -19,28 +19,35 @@ package org.apache.fop.fo.pagination; -// Java import java.util.Map; +import java.util.Stack; import org.xml.sax.Locator; import org.apache.fop.apps.FOPException; +import org.apache.fop.complexscripts.bidi.DelimitedTextRange; +import org.apache.fop.datatypes.Numeric; import org.apache.fop.fo.FONode; import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.ValidationException; +import org.apache.fop.traits.Direction; +import org.apache.fop.traits.WritingMode; +import org.apache.fop.traits.WritingModeTraits; +import org.apache.fop.traits.WritingModeTraitsGetter; /** * Class modelling the * fo:page-sequence object. */ -public class PageSequence extends AbstractPageSequence { +public class PageSequence extends AbstractPageSequence implements WritingModeTraitsGetter { - // The value of properties relevant for fo:page-sequence. + // The value of FO traits (refined properties) that apply to fo:page-sequence. private String country; private String language; private String masterReference; - //private int writingMode; //XSL 1.1 - // End of property values + private Numeric referenceOrientation; + private WritingModeTraits writingModeTraits; + // End of trait values // There doesn't seem to be anything in the spec requiring flows // to be in the order given, only that they map to the regions @@ -86,8 +93,9 @@ public class PageSequence extends AbstractPageSequence { country = pList.get(PR_COUNTRY).getString(); language = pList.get(PR_LANGUAGE).getString(); masterReference = pList.get(PR_MASTER_REFERENCE).getString(); - //writingMode = pList.getWritingMode(); - + referenceOrientation = pList.get(PR_REFERENCE_ORIENTATION).getNumeric(); + writingModeTraits = new WritingModeTraits + ( WritingMode.valueOf(pList.get(PR_WRITING_MODE).getEnum()) ); if (masterReference == null || masterReference.equals("")) { missingPropertyError("master-reference"); } @@ -292,8 +300,8 @@ public class PageSequence extends AbstractPageSequence { } /** - * Get the value of the master-reference property. - * @return the "master-reference" property + * Get the value of the master-reference trait. + * @return the "master-reference" trait */ public String getMasterReference() { return masterReference; @@ -313,21 +321,119 @@ public class PageSequence extends AbstractPageSequence { } /** - * Get the value of the country property. - * @return the country property value + * Get the value of the country trait. + * @return the country trait value */ public String getCountry() { return this.country; } /** - * Get the value of the language property. - * @return the language property value + * Get the value of the language trait. + * @return the language trait value */ public String getLanguage() { return this.language; } + /** + * Get the value of the reference-orientation trait. + * @return the reference orientation trait value + */ + public int getReferenceOrientation() { + if ( referenceOrientation != null ) { + return referenceOrientation.getValue(); + } else { + return 0; + } + } + + /** + * {@inheritDoc} + */ + public Direction getInlineProgressionDirection() { + if ( writingModeTraits != null ) { + return writingModeTraits.getInlineProgressionDirection(); + } else { + return Direction.LR; + } + } + + /** + * {@inheritDoc} + */ + public Direction getBlockProgressionDirection() { + if ( writingModeTraits != null ) { + return writingModeTraits.getBlockProgressionDirection(); + } else { + return Direction.TB; + } + } + + /** + * {@inheritDoc} + */ + public Direction getColumnProgressionDirection() { + if ( writingModeTraits != null ) { + return writingModeTraits.getColumnProgressionDirection(); + } else { + return Direction.LR; + } + } + + /** + * {@inheritDoc} + */ + public Direction getRowProgressionDirection() { + if ( writingModeTraits != null ) { + return writingModeTraits.getRowProgressionDirection(); + } else { + return Direction.TB; + } + } + + /** + * {@inheritDoc} + */ + public Direction getShiftDirection() { + if ( writingModeTraits != null ) { + return writingModeTraits.getShiftDirection(); + } else { + return Direction.TB; + } + } + + /** + * {@inheritDoc} + */ + public WritingMode getWritingMode() { + if ( writingModeTraits != null ) { + return writingModeTraits.getWritingMode(); + } else { + return WritingMode.LR_TB; + } + } + + + @Override + protected Stack collectDelimitedTextRanges ( Stack ranges, DelimitedTextRange currentRange ) { + // collect ranges from static content flows + Map flows = getFlowMap(); + if ( flows != null ) { + for ( FONode fn : flows.values() ) { + if ( fn instanceof StaticContent ) { + ranges = ( (StaticContent) fn ).collectDelimitedTextRanges ( ranges ); + } + } + } + // collect ranges in main flow + Flow main = getMainFlow(); + if ( main != null ) { + ranges = main.collectDelimitedTextRanges ( ranges ); + } + return ranges; + } + /** * Releases a page-sequence's children after the page-sequence has been fully processed. */ diff --git a/src/java/org/apache/fop/fo/pagination/Region.java b/src/java/org/apache/fop/fo/pagination/Region.java index a3c259aa7..16956b6dd 100644 --- a/src/java/org/apache/fop/fo/pagination/Region.java +++ b/src/java/org/apache/fop/fo/pagination/Region.java @@ -32,20 +32,21 @@ import org.apache.fop.fo.FObj; import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.ValidationException; import org.apache.fop.fo.properties.CommonBorderPaddingBackground; +import org.apache.fop.traits.WritingMode; /** * This is an abstract base class for pagination regions. */ public abstract class Region extends FObj { - // The value of properties relevant for fo:region + // The value of FO traits (refined properties) that apply to fo:region private CommonBorderPaddingBackground commonBorderPaddingBackground; // private ToBeImplementedProperty clip private int displayAlign; private int overflow; private String regionName; private Numeric referenceOrientation; - private int writingMode; - // End of property values + private WritingMode writingMode; + // End of FO trait values /** the parent {@link SimplePageMaster} */ protected final SimplePageMaster layoutMaster; @@ -68,7 +69,7 @@ public abstract class Region extends FObj { overflow = pList.get(PR_OVERFLOW).getEnum(); regionName = pList.get(PR_REGION_NAME).getString(); referenceOrientation = pList.get(PR_REFERENCE_ORIENTATION).getNumeric(); - writingMode = pList.getWritingMode(); + writingMode = WritingMode.valueOf(pList.get(PR_WRITING_MODE).getEnum()); // regions may have name, or default if (regionName.equals("")) { @@ -169,28 +170,28 @@ public abstract class Region extends FObj { return commonBorderPaddingBackground; } - /** @return the "region-name" property. */ + /** @return the "region-name" FO trait. */ public String getRegionName() { return regionName; } - /** @return the "writing-mode" property. */ - public int getWritingMode() { - return writingMode; - } - - /** @return the "overflow" property. */ + /** @return the "overflow" FO trait. */ public int getOverflow() { return overflow; } - /** @return the display-align property. */ + /** @return the display-align FO trait. */ public int getDisplayAlign() { return displayAlign; } - /** @return the "reference-orientation" property. */ + /** @return the "reference-orientation" FO trait. */ public int getReferenceOrientation() { return referenceOrientation.getValue(); } + + /** @return the "writing-mode" FO trait. */ + public WritingMode getWritingMode() { + return writingMode; + } } diff --git a/src/java/org/apache/fop/fo/pagination/RegionAfter.java b/src/java/org/apache/fop/fo/pagination/RegionAfter.java index bab5d46b8..3541c54be 100644 --- a/src/java/org/apache/fop/fo/pagination/RegionAfter.java +++ b/src/java/org/apache/fop/fo/pagination/RegionAfter.java @@ -23,6 +23,7 @@ package org.apache.fop.fo.pagination; import java.awt.Rectangle; // FOP +import org.apache.fop.fo.Constants; import org.apache.fop.fo.FONode; import org.apache.fop.datatypes.FODimension; import org.apache.fop.datatypes.LengthBase; @@ -52,15 +53,22 @@ public class RegionAfter extends RegionBA { PercentBaseContext pageHeightContext = getPageHeightContext(LengthBase.CUSTOM_BASE); PercentBaseContext neighbourContext; Rectangle vpRect; - if (layoutMaster.getWritingMode() == EN_LR_TB - || layoutMaster.getWritingMode() == EN_RL_TB) { + + // [TBD] WRITING MODE ALERT + switch ( getWritingMode().getEnumValue() ) { + default: + case Constants.EN_LR_TB: + case Constants.EN_RL_TB: neighbourContext = pageWidthContext; vpRect = new Rectangle(0, reldims.bpd - getExtent().getValue(pageHeightContext) , reldims.ipd, getExtent().getValue(pageHeightContext)); - } else { + break; + case Constants.EN_TB_LR: + case Constants.EN_TB_RL: neighbourContext = pageHeightContext; vpRect = new Rectangle(0, reldims.bpd - getExtent().getValue(pageWidthContext) , getExtent().getValue(pageWidthContext), reldims.ipd); + break; } if (getPrecedence() == EN_FALSE) { adjustIPD(vpRect, layoutMaster.getWritingMode(), neighbourContext); diff --git a/src/java/org/apache/fop/fo/pagination/RegionBA.java b/src/java/org/apache/fop/fo/pagination/RegionBA.java index 149e470cf..eac7723f5 100644 --- a/src/java/org/apache/fop/fo/pagination/RegionBA.java +++ b/src/java/org/apache/fop/fo/pagination/RegionBA.java @@ -26,6 +26,7 @@ import org.apache.fop.apps.FOPException; import org.apache.fop.datatypes.PercentBaseContext; import org.apache.fop.fo.FONode; import org.apache.fop.fo.PropertyList; +import org.apache.fop.traits.WritingMode; /** * Abstract base class for @@ -70,7 +71,8 @@ public abstract class RegionBA extends SideRegion { * @param wm writing mode * @param siblingContext the context to use to resolve extent on siblings */ - protected void adjustIPD(Rectangle vpRefRect, int wm, PercentBaseContext siblingContext) { + protected void adjustIPD + ( Rectangle vpRefRect, WritingMode wm, PercentBaseContext siblingContext ) { int offset = 0; RegionStart start = (RegionStart) getSiblingRegion(FO_REGION_START); if (start != null) { @@ -81,8 +83,9 @@ public abstract class RegionBA extends SideRegion { if (end != null) { offset += end.getExtent().getValue(siblingContext); } + // [TBD] WRITING MODE ALERT if (offset > 0) { - if (wm == EN_LR_TB || wm == EN_RL_TB) { + if (wm == WritingMode.LR_TB || wm == WritingMode.RL_TB) { vpRefRect.width -= offset; } else { vpRefRect.height -= offset; diff --git a/src/java/org/apache/fop/fo/pagination/RegionBefore.java b/src/java/org/apache/fop/fo/pagination/RegionBefore.java index 4aa29ec90..295f6dc1c 100644 --- a/src/java/org/apache/fop/fo/pagination/RegionBefore.java +++ b/src/java/org/apache/fop/fo/pagination/RegionBefore.java @@ -23,6 +23,7 @@ package org.apache.fop.fo.pagination; import java.awt.Rectangle; // FOP +import org.apache.fop.fo.Constants; import org.apache.fop.datatypes.FODimension; import org.apache.fop.datatypes.LengthBase; import org.apache.fop.datatypes.PercentBaseContext; @@ -57,13 +58,19 @@ public class RegionBefore extends RegionBA { PercentBaseContext pageHeightContext = getPageHeightContext(LengthBase.CUSTOM_BASE); PercentBaseContext neighbourContext; Rectangle vpRect; - if (layoutMaster.getWritingMode() == EN_LR_TB - || layoutMaster.getWritingMode() == EN_RL_TB) { + // [TBD] WRITING MODE ALERT + switch ( getWritingMode().getEnumValue() ) { + default: + case Constants.EN_LR_TB: + case Constants.EN_RL_TB: neighbourContext = pageWidthContext; vpRect = new Rectangle(0, 0, reldims.ipd, getExtent().getValue(pageHeightContext)); - } else { + break; + case Constants.EN_TB_LR: + case Constants.EN_TB_RL: neighbourContext = pageHeightContext; vpRect = new Rectangle(0, 0, getExtent().getValue(pageWidthContext), reldims.ipd); + break; } if (getPrecedence() == EN_FALSE) { adjustIPD(vpRect, layoutMaster.getWritingMode(), neighbourContext); diff --git a/src/java/org/apache/fop/fo/pagination/RegionBody.java b/src/java/org/apache/fop/fo/pagination/RegionBody.java index 5eed36061..9e6392337 100644 --- a/src/java/org/apache/fop/fo/pagination/RegionBody.java +++ b/src/java/org/apache/fop/fo/pagination/RegionBody.java @@ -28,9 +28,11 @@ import org.apache.fop.datatypes.Length; import org.apache.fop.datatypes.LengthBase; import org.apache.fop.datatypes.Numeric; import org.apache.fop.datatypes.PercentBaseContext; +import org.apache.fop.fo.Constants; import org.apache.fop.fo.FONode; import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.properties.CommonMarginBlock; +import org.apache.fop.traits.WritingMode; /** * Class modelling the @@ -113,12 +115,22 @@ public class RegionBody extends Region { int start; int end; - if (layoutMaster.getWritingMode() == EN_LR_TB) { // Left-to-right + // [TBD] WRITING MODE ALERT + switch ( getWritingMode().getEnumValue() ) { + default: + case Constants.EN_LR_TB: start = commonMarginBlock.marginLeft.getValue(pageWidthContext); end = commonMarginBlock.marginRight.getValue(pageWidthContext); - } else { // all other supported modes are right-to-left + break; + case Constants.EN_RL_TB: start = commonMarginBlock.marginRight.getValue(pageWidthContext); end = commonMarginBlock.marginLeft.getValue(pageWidthContext); + break; + case Constants.EN_TB_LR: + case Constants.EN_TB_RL: + start = commonMarginBlock.marginTop.getValue(pageWidthContext); + end = commonMarginBlock.marginBottom.getValue(pageWidthContext); + break; } int before = commonMarginBlock.spaceBefore.getOptimum(pageHeightContext) .getLength().getValue(pageHeightContext); diff --git a/src/java/org/apache/fop/fo/pagination/RegionEnd.java b/src/java/org/apache/fop/fo/pagination/RegionEnd.java index 2533763a5..ce0258524 100644 --- a/src/java/org/apache/fop/fo/pagination/RegionEnd.java +++ b/src/java/org/apache/fop/fo/pagination/RegionEnd.java @@ -23,6 +23,7 @@ package org.apache.fop.fo.pagination; import java.awt.Rectangle; // FOP +import org.apache.fop.fo.Constants; import org.apache.fop.fo.FONode; import org.apache.fop.datatypes.FODimension; import org.apache.fop.datatypes.LengthBase; @@ -52,18 +53,27 @@ public class RegionEnd extends RegionSE { PercentBaseContext pageHeightContext = getPageHeightContext(LengthBase.CUSTOM_BASE); PercentBaseContext neighbourContext; Rectangle vpRect; - if (layoutMaster.getWritingMode() == EN_LR_TB - || layoutMaster.getWritingMode() == EN_RL_TB) { + // [TBD] WRITING MODE ALERT + switch ( getWritingMode().getEnumValue() ) { + default: + case Constants.EN_LR_TB: neighbourContext = pageHeightContext; vpRect = new Rectangle(reldims.ipd - getExtent().getValue(pageWidthContext), 0, getExtent().getValue(pageWidthContext), reldims.bpd); - } else { + break; + case Constants.EN_RL_TB: + neighbourContext = pageHeightContext; + vpRect = new Rectangle(0, 0, getExtent().getValue(pageWidthContext), reldims.bpd); + break; + case Constants.EN_TB_LR: + case Constants.EN_TB_RL: // Rectangle: x , y (of top left point), width, height neighbourContext = pageWidthContext; vpRect = new Rectangle(reldims.ipd - getExtent().getValue(pageHeightContext), 0, reldims.bpd, getExtent().getValue(pageHeightContext)); + break; } - adjustIPD(vpRect, layoutMaster.getWritingMode(), neighbourContext); + adjustIPD(vpRect, getWritingMode(), neighbourContext); return vpRect; } diff --git a/src/java/org/apache/fop/fo/pagination/RegionSE.java b/src/java/org/apache/fop/fo/pagination/RegionSE.java index f106e8a36..9fc2bdc27 100644 --- a/src/java/org/apache/fop/fo/pagination/RegionSE.java +++ b/src/java/org/apache/fop/fo/pagination/RegionSE.java @@ -26,6 +26,7 @@ import org.apache.fop.apps.FOPException; import org.apache.fop.datatypes.PercentBaseContext; import org.apache.fop.fo.FONode; import org.apache.fop.fo.PropertyList; +import org.apache.fop.traits.WritingMode; /** * Abstract base class for @@ -61,7 +62,8 @@ public abstract class RegionSE extends SideRegion { * @param wm writing mode * @param siblingContext the context to use to resolve extent on siblings */ - protected void adjustIPD(Rectangle vpRefRect, int wm, PercentBaseContext siblingContext) { + protected void adjustIPD + ( Rectangle vpRefRect, WritingMode wm, PercentBaseContext siblingContext ) { int offset = 0; RegionBefore before = (RegionBefore) getSiblingRegion(FO_REGION_BEFORE); if (before != null && before.getPrecedence() == EN_TRUE) { @@ -72,8 +74,9 @@ public abstract class RegionSE extends SideRegion { if (after != null && after.getPrecedence() == EN_TRUE) { offset += after.getExtent().getValue(siblingContext); } + // [TBD] WRITING MODE ALERT if (offset > 0) { - if (wm == EN_LR_TB || wm == EN_RL_TB) { + if (wm == WritingMode.LR_TB || wm == WritingMode.RL_TB) { vpRefRect.height -= offset; } else { vpRefRect.width -= offset; diff --git a/src/java/org/apache/fop/fo/pagination/RegionStart.java b/src/java/org/apache/fop/fo/pagination/RegionStart.java index fdb423c51..c2fc3fe17 100644 --- a/src/java/org/apache/fop/fo/pagination/RegionStart.java +++ b/src/java/org/apache/fop/fo/pagination/RegionStart.java @@ -23,6 +23,7 @@ package org.apache.fop.fo.pagination; import java.awt.Rectangle; // FOP +import org.apache.fop.fo.Constants; import org.apache.fop.fo.FONode; import org.apache.fop.datatypes.FODimension; import org.apache.fop.datatypes.LengthBase; @@ -52,13 +53,23 @@ public class RegionStart extends RegionSE { PercentBaseContext pageHeightContext = getPageHeightContext(LengthBase.CUSTOM_BASE); PercentBaseContext neighbourContext; Rectangle vpRect; - if (layoutMaster.getWritingMode() == EN_LR_TB - || layoutMaster.getWritingMode() == EN_RL_TB) { + // [TBD] WRITING MODE ALERT + switch ( getWritingMode().getEnumValue() ) { + default: + case Constants.EN_LR_TB: neighbourContext = pageHeightContext; vpRect = new Rectangle(0, 0, getExtent().getValue(pageWidthContext), reldims.bpd); - } else { + break; + case Constants.EN_RL_TB: + neighbourContext = pageHeightContext; + vpRect = new Rectangle(reldims.ipd - getExtent().getValue(pageWidthContext), 0, + getExtent().getValue(pageWidthContext), reldims.bpd); + break; + case Constants.EN_TB_LR: + case Constants.EN_TB_RL: neighbourContext = pageWidthContext; vpRect = new Rectangle(0, 0, reldims.bpd, getExtent().getValue(pageHeightContext)); + break; } adjustIPD(vpRect, layoutMaster.getWritingMode(), neighbourContext); return vpRect; diff --git a/src/java/org/apache/fop/fo/pagination/SimplePageMaster.java b/src/java/org/apache/fop/fo/pagination/SimplePageMaster.java index e38993487..79c8c3358 100644 --- a/src/java/org/apache/fop/fo/pagination/SimplePageMaster.java +++ b/src/java/org/apache/fop/fo/pagination/SimplePageMaster.java @@ -35,6 +35,7 @@ import org.apache.fop.fo.FObj; import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.ValidationException; import org.apache.fop.fo.properties.CommonMarginBlock; +import org.apache.fop.traits.WritingMode; /** * Class modelling the @@ -43,14 +44,14 @@ import org.apache.fop.fo.properties.CommonMarginBlock; * and attributes. */ public class SimplePageMaster extends FObj { - // The value of properties relevant for fo:simple-page-master. + // The value of FO traits (refined properties) that apply to fo:simple-page-master. private CommonMarginBlock commonMarginBlock; private String masterName; private Length pageHeight; private Length pageWidth; private Numeric referenceOrientation; - private int writingMode; - // End of property values + private WritingMode writingMode; + // End of FO trait values /** * Page regions (regionClass, Region) @@ -80,7 +81,7 @@ public class SimplePageMaster extends FObj { pageHeight = pList.get(PR_PAGE_HEIGHT).getLength(); pageWidth = pList.get(PR_PAGE_WIDTH).getLength(); referenceOrientation = pList.get(PR_REFERENCE_ORIENTATION).getNumeric(); - writingMode = pList.getWritingMode(); + writingMode = WritingMode.valueOf(pList.get(PR_WRITING_MODE).getEnum()); if (masterName == null || masterName.equals("")) { missingPropertyError("master-name"); @@ -269,31 +270,31 @@ public class SimplePageMaster extends FObj { return commonMarginBlock; } - /** @return "master-name" property. */ + /** @return "master-name" FO trait. */ public String getMasterName() { return masterName; } - /** @return the "page-width" property. */ + /** @return the "page-width" FO trait. */ public Length getPageWidth() { return pageWidth; } - /** @return the "page-height" property. */ + /** @return the "page-height" FO trait. */ public Length getPageHeight() { return pageHeight; } - /** @return the "writing-mode" property. */ - public int getWritingMode() { - return writingMode; - } - - /** @return the "reference-orientation" property. */ + /** @return the "reference-orientation" FO trait. */ public int getReferenceOrientation() { return referenceOrientation.getValue(); } + /** @return the "writing-mode" FO trait. */ + public WritingMode getWritingMode() { + return writingMode; + } + /** {@inheritDoc} */ public String getLocalName() { return "simple-page-master"; diff --git a/src/java/org/apache/fop/fo/properties/CorrespondingPropertyMaker.java b/src/java/org/apache/fop/fo/properties/CorrespondingPropertyMaker.java index 6183b9e56..b74c9dcfb 100644 --- a/src/java/org/apache/fop/fo/properties/CorrespondingPropertyMaker.java +++ b/src/java/org/apache/fop/fo/properties/CorrespondingPropertyMaker.java @@ -35,6 +35,8 @@ public class CorrespondingPropertyMaker { protected int rltb; /** corresponding property for tb-rl writing mode */ protected int tbrl; + /** corresponding property for tb-lr writing mode */ + protected int tblr; /** user parent property list */ protected boolean useParent; private boolean relative; @@ -48,17 +50,26 @@ public class CorrespondingPropertyMaker { baseMaker.setCorresponding(this); } + /** + * Set corresponding property values. + * @param lrtb a corresponding value + * @param rltb a corresponding value + * @param tbrl a corresponding value + * @param tblr a corresponding value + */ /** * Set corresponding property identifiers. * @param lrtb the property that corresponds with lr-tb writing mode * @param rltb the property that corresponds with rl-tb writing mode * @param tbrl the property that corresponds with tb-lr writing mode + * @param tblr the property that corresponds with tb-lr writing mode */ - public void setCorresponding(int lrtb, int rltb, int tbrl) { + public void setCorresponding(int lrtb, int rltb, int tbrl, int tblr) { this.lrtb = lrtb; this.rltb = rltb; this.tbrl = tbrl; + this.tblr = tblr; } /** @@ -72,7 +83,7 @@ public class CorrespondingPropertyMaker { /** * Set relative flag. - * @param relative true if relative direction + * @param relative true if properties operate on a relative direction */ public void setRelative(boolean relative) { this.relative = relative; @@ -102,7 +113,7 @@ public class CorrespondingPropertyMaker { PropertyList pList = getWMPropertyList(propertyList); if (pList != null) { - int correspondingId = pList.getWritingMode(lrtb, rltb, tbrl); + int correspondingId = pList.selectFromWritingMode(lrtb, rltb, tbrl, tblr); if (pList.getExplicit(correspondingId) != null) { return true; @@ -126,7 +137,7 @@ public class CorrespondingPropertyMaker { if (pList == null) { return null; } - int correspondingId = pList.getWritingMode(lrtb, rltb, tbrl); + int correspondingId = pList.selectFromWritingMode(lrtb, rltb, tbrl, tblr); Property p = propertyList.getExplicitOrShorthand(correspondingId); if (p != null) { diff --git a/src/java/org/apache/fop/fo/properties/DimensionPropertyMaker.java b/src/java/org/apache/fop/fo/properties/DimensionPropertyMaker.java index 0bef5e916..13efa6f30 100644 --- a/src/java/org/apache/fop/fo/properties/DimensionPropertyMaker.java +++ b/src/java/org/apache/fop/fo/properties/DimensionPropertyMaker.java @@ -34,7 +34,7 @@ public class DimensionPropertyMaker extends CorrespondingPropertyMaker { private int[][] extraCorresponding = null; /** - * Construct a dimension property maker. + * Instantiate a dimension property maker. * @param baseMaker the base property maker */ public DimensionPropertyMaker(PropertyMaker baseMaker) { @@ -43,9 +43,18 @@ public class DimensionPropertyMaker extends CorrespondingPropertyMaker { /** * Set extra correspondences. - * @param extraCorresponding the extra correspondences + * @param extraCorresponding an array of four element integer arrays */ public void setExtraCorresponding(int[][] extraCorresponding) { + if ( extraCorresponding == null ) { + throw new NullPointerException(); + } + for ( int i = 0; i < extraCorresponding.length; i++ ) { + int[] eca = extraCorresponding[i]; + if ( ( eca == null ) || ( eca.length != 4 ) ) { + throw new IllegalArgumentException ( "bad sub-array @ [" + i + "]" ); + } + } this.extraCorresponding = extraCorresponding; } @@ -76,18 +85,20 @@ public class DimensionPropertyMaker extends CorrespondingPropertyMaker { } // Based on min-[width|height] - int wmcorr = propertyList.getWritingMode(extraCorresponding[0][0], + int wmcorr = propertyList.selectFromWritingMode(extraCorresponding[0][0], extraCorresponding[0][1], - extraCorresponding[0][2]); + extraCorresponding[0][2], + extraCorresponding[0][3]); Property subprop = propertyList.getExplicitOrShorthand(wmcorr); if (subprop != null) { baseMaker.setSubprop(p, Constants.CP_MINIMUM, subprop); } // Based on max-[width|height] - wmcorr = propertyList.getWritingMode(extraCorresponding[1][0], + wmcorr = propertyList.selectFromWritingMode(extraCorresponding[1][0], extraCorresponding[1][1], - extraCorresponding[1][2]); + extraCorresponding[1][2], + extraCorresponding[1][3]); subprop = propertyList.getExplicitOrShorthand(wmcorr); // TODO: Don't set when NONE. if (subprop != null) { diff --git a/src/java/org/apache/fop/fo/properties/IndentPropertyMaker.java b/src/java/org/apache/fop/fo/properties/IndentPropertyMaker.java index 19c4675ed..6b7c58a62 100644 --- a/src/java/org/apache/fop/fo/properties/IndentPropertyMaker.java +++ b/src/java/org/apache/fop/fo/properties/IndentPropertyMaker.java @@ -55,6 +55,9 @@ public class IndentPropertyMaker extends CorrespondingPropertyMaker { * @param paddingCorresponding the corresping propids. */ public void setPaddingCorresponding(int[] paddingCorresponding) { + if ( ( paddingCorresponding == null ) || ( paddingCorresponding.length != 4 ) ) { + throw new IllegalArgumentException(); + } this.paddingCorresponding = paddingCorresponding; } @@ -63,6 +66,9 @@ public class IndentPropertyMaker extends CorrespondingPropertyMaker { * @param borderWidthCorresponding the corresping propids. */ public void setBorderWidthCorresponding(int[] borderWidthCorresponding) { + if ( ( borderWidthCorresponding == null ) || ( borderWidthCorresponding.length != 4 ) ) { + throw new IllegalArgumentException(); + } this.borderWidthCorresponding = borderWidthCorresponding; } @@ -99,7 +105,7 @@ public class IndentPropertyMaker extends CorrespondingPropertyMaker { Numeric padding = getCorresponding(paddingCorresponding, propertyList).getNumeric(); Numeric border = getCorresponding(borderWidthCorresponding, propertyList).getNumeric(); - int marginProp = pList.getWritingMode(lrtb, rltb, tbrl); + int marginProp = pList.selectFromWritingMode(lrtb, rltb, tbrl, tblr); // Calculate the absolute margin. if (propertyList.getExplicitOrShorthand(marginProp) == null) { Property indent = propertyList.getExplicit(baseMaker.propId); @@ -158,7 +164,7 @@ public class IndentPropertyMaker extends CorrespondingPropertyMaker { Numeric padding = getCorresponding(paddingCorresponding, propertyList).getNumeric(); Numeric border = getCorresponding(borderWidthCorresponding, propertyList).getNumeric(); - int marginProp = pList.getWritingMode(lrtb, rltb, tbrl); + int marginProp = pList.selectFromWritingMode(lrtb, rltb, tbrl, tblr); //Determine whether the nearest anscestor indent was specified through //start-indent|end-indent or through a margin property. @@ -208,7 +214,8 @@ public class IndentPropertyMaker extends CorrespondingPropertyMaker { throws PropertyException { PropertyList pList = getWMPropertyList(propertyList); if (pList != null) { - int wmcorr = pList.getWritingMode(corresponding[0], corresponding[1], corresponding[2]); + int wmcorr = pList.selectFromWritingMode + ( corresponding[0], corresponding[1], corresponding[2], corresponding[3] ); return propertyList.get(wmcorr); } else { return null; diff --git a/src/java/org/apache/fop/fonts/BFEntry.java b/src/java/org/apache/fop/fonts/BFEntry.java index e04b021e4..d3c7956ba 100644 --- a/src/java/org/apache/fop/fonts/BFEntry.java +++ b/src/java/org/apache/fop/fonts/BFEntry.java @@ -68,9 +68,15 @@ public class BFEntry { @Override public String toString() { StringBuilder sb = new StringBuilder("BFEntry: "); - sb.append("Unicode ").append(getUnicodeStart()).append("..").append(getUnicodeEnd()); - sb.append(" --> ").append(getGlyphStartIndex()).append(".."); - sb.append(getGlyphStartIndex() + getUnicodeEnd() - getUnicodeStart()); + sb.append ( "{ UC[" ); + sb.append ( unicodeStart ); + sb.append ( ',' ); + sb.append ( unicodeEnd ); + sb.append ( "]: GC[" ); + sb.append ( glyphStartIndex ); + sb.append ( ',' ); + sb.append ( glyphStartIndex + ( unicodeEnd - unicodeStart ) ); + sb.append ( "] }" ); return sb.toString(); } diff --git a/src/java/org/apache/fop/fonts/CustomFont.java b/src/java/org/apache/fop/fonts/CustomFont.java index 4432fccef..c6b43fe98 100644 --- a/src/java/org/apache/fop/fonts/CustomFont.java +++ b/src/java/org/apache/fop/fonts/CustomFont.java @@ -60,6 +60,7 @@ public abstract class CustomFont extends Typeface private Map> kerning; private boolean useKerning = true; + private boolean useAdvanced = true; /** {@inheritDoc} */ public String getFontName() { @@ -285,6 +286,15 @@ public abstract class CustomFont extends Typeface } } + /** + * Used to determine if advanced typographic features are enabled. + * By default, this is false, but may be overridden by subclasses. + * @return true if enabled. + */ + public boolean isAdvancedEnabled() { + return useAdvanced; + } + /* ---- MutableFont interface ---- */ /** {@inheritDoc} */ @@ -427,6 +437,13 @@ public abstract class CustomFont extends Typeface this.useKerning = enabled; } + /** + * {@inheritDoc} + */ + public void setAdvancedEnabled(boolean enabled) { + this.useAdvanced = enabled; + } + /** * Sets the font resolver. Needed for URI resolution. * @param resolver the font resolver diff --git a/src/java/org/apache/fop/fonts/CustomFontCollection.java b/src/java/org/apache/fop/fonts/CustomFontCollection.java index 9f98814a3..6e798a8f7 100644 --- a/src/java/org/apache/fop/fonts/CustomFontCollection.java +++ b/src/java/org/apache/fop/fonts/CustomFontCollection.java @@ -33,13 +33,14 @@ public class CustomFontCollection implements FontCollection { * Main constructor. * @param fontResolver a font resolver * @param customFonts the list of custom fonts + * @param useComplexScriptFeatures true if complex script features enabled */ public CustomFontCollection(FontResolver fontResolver, - List customFonts) { + List customFonts, boolean useComplexScriptFeatures) { this.fontResolver = fontResolver; if (this.fontResolver == null) { //Ensure that we have minimal font resolution capabilities - this.fontResolver = FontManager.createMinimalFontResolver(); + this.fontResolver = FontManager.createMinimalFontResolver(useComplexScriptFeatures); } this.embedFontInfoList = customFonts; } diff --git a/src/java/org/apache/fop/fonts/EmbedFontInfo.java b/src/java/org/apache/fop/fonts/EmbedFontInfo.java index b53cdfdd6..8848c0a87 100644 --- a/src/java/org/apache/fop/fonts/EmbedFontInfo.java +++ b/src/java/org/apache/fop/fonts/EmbedFontInfo.java @@ -29,7 +29,7 @@ import java.util.List; public class EmbedFontInfo implements Serializable { /** Serialization Version UID */ - private static final long serialVersionUID = 8755432068669997368L; + private static final long serialVersionUID = 8755432068669997369L; /** filename of the metrics file */ protected String metricsFile; @@ -37,6 +37,8 @@ public class EmbedFontInfo implements Serializable { protected String embedFile; /** false, to disable kerning */ protected boolean kerning; + /** false, to disable advanced typographic features */ + protected boolean advanced; /** the requested encoding mode for the font */ protected EncodingMode encodingMode = EncodingMode.AUTO; @@ -52,17 +54,19 @@ public class EmbedFontInfo implements Serializable { /** * Main constructor - * @param metricsFile Path to the xml file containing font metrics - * @param kerning True if kerning should be enabled - * @param fontTriplets List of font triplets to associate with this font - * @param embedFile Path to the embeddable font file (may be null) + * @param metricsFile path to the xml file containing font metrics + * @param kerning true if kerning should be enabled + * @param advanced true if advanced typography features should be enabled + * @param fontTriplets list of font triplets to associate with this font + * @param embedFile path to the embeddable font file (may be null) * @param subFontName the sub-fontname used for TrueType Collections (null otherwise) */ - public EmbedFontInfo(String metricsFile, boolean kerning, + public EmbedFontInfo(String metricsFile, boolean kerning, boolean advanced, List fontTriplets, String embedFile, String subFontName) { this.metricsFile = metricsFile; this.embedFile = embedFile; this.kerning = kerning; + this.advanced = advanced; this.fontTriplets = fontTriplets; this.subFontName = subFontName; } @@ -85,12 +89,20 @@ public class EmbedFontInfo implements Serializable { /** * Determines if kerning is enabled - * @return True if enabled + * @return true if enabled */ public boolean getKerning() { return kerning; } + /** + * Determines if advanced typographic features are enabled + * @return true if enabled + */ + public boolean getAdvanced() { + return advanced; + } + /** * Returns the sub-font name of the font. This is primarily used for TrueType Collections * to select one of the sub-fonts. For all other fonts, this is always null. @@ -173,6 +185,7 @@ public class EmbedFontInfo implements Serializable { public String toString() { return "metrics-url=" + metricsFile + ", embed-url=" + embedFile + ", kerning=" + kerning + + ", advanced=" + advanced + ", enc-mode=" + encodingMode + ", font-triplet=" + fontTriplets + (getSubFontName() != null ? ", sub-font=" + getSubFontName() : "") diff --git a/src/java/org/apache/fop/fonts/Font.java b/src/java/org/apache/fop/fonts/Font.java index 8ca802234..ca387840a 100644 --- a/src/java/org/apache/fop/fonts/Font.java +++ b/src/java/org/apache/fop/fonts/Font.java @@ -25,11 +25,16 @@ import java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.apache.fop.complexscripts.fonts.Positionable; +import org.apache.fop.complexscripts.fonts.Substitutable; + +// CSOFF: LineLengthCheck + /** * This class holds font state information and provides access to the font * metrics. */ -public class Font { +public class Font implements Substitutable, Positionable { /** Extra Bold font weight */ public static final int WEIGHT_EXTRA_BOLD = 800; @@ -188,6 +193,30 @@ public class Font { return 0; } + /** + * Returns the amount of kerning between two characters. + * + * The value returned measures in pt. So it is already adjusted for font size. + * + * @param ch1 first character + * @param ch2 second character + * @return the distance to adjust for kerning, 0 if there's no kerning + */ + public int getKernValue(int ch1, int ch2) { + // TODO !BMP + if ( ch1 > 0x10000 ) { + return 0; + } else if ( ( ch1 >= 0xD800 ) && ( ch1 <= 0xE000 ) ) { + return 0; + } else if ( ch2 > 0x10000 ) { + return 0; + } else if ( ( ch2 >= 0xD800 ) && ( ch2 <= 0xE000 ) ) { + return 0; + } else { + return getKernValue ( (char) ch1, (char) ch2 ); + } + } + /** * Returns the width of a character * @param charnum character to look up @@ -241,8 +270,8 @@ public class Font { */ @Override public String toString() { - StringBuffer sbuf = new StringBuffer(); - sbuf.append('('); + StringBuffer sbuf = new StringBuffer(super.toString()); + sbuf.append('{'); /* sbuf.append(fontFamily); sbuf.append(',');*/ @@ -254,7 +283,7 @@ public class Font { sbuf.append(fontStyle); sbuf.append(','); sbuf.append(fontWeight);*/ - sbuf.append(')'); + sbuf.append('}'); return sbuf.toString(); } @@ -264,7 +293,7 @@ public class Font { * This also performs some guessing on widths on various * versions of space that might not exists in the font. * @param c character to inspect - * @return the width of the character + * @return the width of the character or -1 if no width available */ public int getCharWidth(char c) { int width; @@ -328,6 +357,23 @@ public class Font { return width; } + /** + * Helper method for getting the width of a unicode char + * from the current fontstate. + * This also performs some guessing on widths on various + * versions of space that might not exists in the font. + * @param c character to inspect + * @return the width of the character or -1 if no width available + */ + public int getCharWidth(int c) { + if ( c < 0x10000 ) { + return getCharWidth ( (char) c ); + } else { + // TODO !BMP + return -1; + } + } + /** * Calculates the word width. * @param word text to get width for @@ -347,6 +393,59 @@ public class Font { return width; } -} + /** {@inheritDoc} */ + public boolean performsSubstitution() { + if ( metric instanceof Substitutable ) { + Substitutable s = (Substitutable) metric; + return s.performsSubstitution(); + } else { + return false; + } + } + + /** {@inheritDoc} */ + public CharSequence performSubstitution ( CharSequence cs, String script, String language ) { + if ( metric instanceof Substitutable ) { + Substitutable s = (Substitutable) metric; + return s.performSubstitution ( cs, script, language ); + } else { + throw new UnsupportedOperationException(); + } + } + + /** {@inheritDoc} */ + public CharSequence reorderCombiningMarks ( CharSequence cs, int[][] gpa, String script, String language ) { + if ( metric instanceof Substitutable ) { + Substitutable s = (Substitutable) metric; + return s.reorderCombiningMarks ( cs, gpa, script, language ); + } else { + throw new UnsupportedOperationException(); + } + } + /** {@inheritDoc} */ + public boolean performsPositioning() { + if ( metric instanceof Positionable ) { + Positionable p = (Positionable) metric; + return p.performsPositioning(); + } else { + return false; + } + } + /** {@inheritDoc} */ + public int[][] performPositioning ( CharSequence cs, String script, String language, int fontSize ) { + if ( metric instanceof Positionable ) { + Positionable p = (Positionable) metric; + return p.performPositioning ( cs, script, language, fontSize ); + } else { + throw new UnsupportedOperationException(); + } + } + + /** {@inheritDoc} */ + public int[][] performPositioning ( CharSequence cs, String script, String language ) { + return performPositioning ( cs, script, language, fontSize ); + } + +} diff --git a/src/java/org/apache/fop/fonts/FontInfoConfigurator.java b/src/java/org/apache/fop/fonts/FontInfoConfigurator.java index 1f1116990..34b6ed1d0 100644 --- a/src/java/org/apache/fop/fonts/FontInfoConfigurator.java +++ b/src/java/org/apache/fop/fonts/FontInfoConfigurator.java @@ -253,20 +253,26 @@ public class FontInfoConfigurator { } boolean useKerning = fontCfg.getAttributeAsBoolean("kerning", true); + boolean useAdvanced = fontCfg.getAttributeAsBoolean("advanced", true); EncodingMode encodingMode = EncodingMode.getEncodingMode( fontCfg.getAttribute("encoding-mode", EncodingMode.AUTO.getName())); EmbedFontInfo embedFontInfo - = new EmbedFontInfo(metricsUrl, useKerning, tripletList, embedUrl, subFont); + = new EmbedFontInfo(metricsUrl, useKerning, useAdvanced, tripletList, embedUrl, + subFont); embedFontInfo.setEncodingMode(encodingMode); + boolean skipCachedFont = false; if (fontCache != null) { if (!fontCache.containsFont(embedFontInfo)) { fontCache.addFont(embedFontInfo); + } else { + skipCachedFont = true; } } if (log.isDebugEnabled()) { String embedFile = embedFontInfo.getEmbedFile(); - log.debug("Adding font " + (embedFile != null ? embedFile + ", " : "") + log.debug( ( skipCachedFont ? "Skipping (cached) font " : "Adding font " ) + + (embedFile != null ? embedFile + ", " : "") + "metric file " + embedFontInfo.getMetricsFile()); for (int j = 0; j < tripletList.size(); ++j) { FontTriplet triplet = tripletList.get(j); diff --git a/src/java/org/apache/fop/fonts/FontLoader.java b/src/java/org/apache/fop/fonts/FontLoader.java index 02c09a1a1..91b763939 100644 --- a/src/java/org/apache/fop/fonts/FontLoader.java +++ b/src/java/org/apache/fop/fonts/FontLoader.java @@ -43,31 +43,36 @@ public abstract class FontLoader { protected static final Log log = LogFactory.getLog(FontLoader.class); /** URI representing the font file */ - protected String fontFileURI = null; + protected String fontFileURI; /** the FontResolver to use for font URI resolution */ - protected FontResolver resolver = null; + protected FontResolver resolver; /** the loaded font */ - protected CustomFont returnFont = null; + protected CustomFont returnFont; /** true if the font has been loaded */ - protected boolean loaded = false; + protected boolean loaded; /** true if the font will be embedded, false if it will be referenced only. */ - protected boolean embedded = true; - /** true if kerning information shall be loaded if available. */ - protected boolean useKerning = true; + protected boolean embedded; + /** true if kerning information false be loaded if available. */ + protected boolean useKerning; + /** true if advanced typographic information shall be loaded if available. */ + protected boolean useAdvanced; /** * Default constructor. * @param fontFileURI the URI to the PFB file of a Type 1 font * @param embedded indicates whether the font is embedded or referenced * @param useKerning indicates whether kerning information shall be loaded if available + * @param useAdvanced indicates whether advanced typographic information shall be loaded if + * available * @param resolver the font resolver used to resolve URIs */ public FontLoader(String fontFileURI, boolean embedded, boolean useKerning, - FontResolver resolver) { + boolean useAdvanced, FontResolver resolver) { this.fontFileURI = fontFileURI; this.embedded = embedded; this.useKerning = useKerning; + this.useAdvanced = useAdvanced; this.resolver = resolver; } @@ -105,7 +110,7 @@ public abstract class FontLoader { boolean embedded, EncodingMode encodingMode, FontResolver resolver) throws IOException { return loadFont(fontUrl.toExternalForm(), subFontName, - embedded, encodingMode, true, + embedded, encodingMode, true, true, resolver); } @@ -116,13 +121,15 @@ public abstract class FontLoader { * @param embedded indicates whether the font is embedded or referenced * @param encodingMode the requested encoding mode * @param useKerning indicates whether kerning information should be loaded if available + * @param useAdvanced indicates whether advanced typographic information shall be loaded if + * available * @param resolver the font resolver to use when resolving URIs * @return the newly loaded font * @throws IOException In case of an I/O error */ public static CustomFont loadFont(String fontFileURI, String subFontName, boolean embedded, EncodingMode encodingMode, boolean useKerning, - FontResolver resolver) throws IOException { + boolean useAdvanced, FontResolver resolver) throws IOException { fontFileURI = fontFileURI.trim(); boolean type1 = isType1(fontFileURI); FontLoader loader; @@ -134,7 +141,7 @@ public abstract class FontLoader { loader = new Type1FontLoader(fontFileURI, embedded, useKerning, resolver); } else { loader = new TTFFontLoader(fontFileURI, subFontName, - embedded, encodingMode, useKerning, resolver); + embedded, encodingMode, useKerning, useAdvanced, resolver); } return loader.getFont(); } diff --git a/src/java/org/apache/fop/fonts/FontManager.java b/src/java/org/apache/fop/fonts/FontManager.java index 51516e231..9285c94be 100644 --- a/src/java/org/apache/fop/fonts/FontManager.java +++ b/src/java/org/apache/fop/fonts/FontManager.java @@ -224,16 +224,32 @@ public class FontManager { getFontSubstitutions().adjustFontInfo(fontInfo); } - /** @return a new FontResolver to be used by the font subsystem */ - public static FontResolver createMinimalFontResolver() { - return new FontResolver() { - - /** {@inheritDoc} */ - public Source resolve(String href) { - //Minimal functionality here - return new StreamSource(href); - } - }; + /** + * Minimum implemenation of FontResolver. + */ + public static class MinimalFontResolver implements FontResolver { + private boolean useComplexScriptFeatures; + MinimalFontResolver(boolean useComplexScriptFeatures) { + this.useComplexScriptFeatures = useComplexScriptFeatures; + } + /** {@inheritDoc} */ + public Source resolve(String href) { + //Minimal functionality here + return new StreamSource(href); + } + /** {@inheritDoc} */ + public boolean isComplexScriptFeaturesEnabled() { + return useComplexScriptFeatures; + } + } + + /** + * Create minimal font resolver. + * @param useComplexScriptFeatures true if complex script features enabled + * @return a new FontResolver to be used by the font subsystem + */ + public static FontResolver createMinimalFontResolver(boolean useComplexScriptFeatures) { + return new MinimalFontResolver ( useComplexScriptFeatures ); } /** diff --git a/src/java/org/apache/fop/fonts/FontManagerConfigurator.java b/src/java/org/apache/fop/fonts/FontManagerConfigurator.java index 6935df7e3..40e163d42 100644 --- a/src/java/org/apache/fop/fonts/FontManagerConfigurator.java +++ b/src/java/org/apache/fop/fonts/FontManagerConfigurator.java @@ -98,6 +98,18 @@ public class FontManagerConfigurator { } } + // [GA] permit configuration control over base14 kerning; without this, + // there is no way for a user to enable base14 kerning other than by + // programmatic API; + if (cfg.getChild("base14-kerning", false) != null) { + try { + fontManager + .setBase14KerningEnabled(cfg.getChild("base14-kerning").getValueAsBoolean()); + } catch (ConfigurationException e) { + LogUtil.handleException(log, e, true); + } + } + // global font configuration Configuration fontsCfg = cfg.getChild("fonts", false); if (fontsCfg != null) { diff --git a/src/java/org/apache/fop/fonts/FontReader.java b/src/java/org/apache/fop/fonts/FontReader.java index e9b88ec16..0f0348fc1 100644 --- a/src/java/org/apache/fop/fonts/FontReader.java +++ b/src/java/org/apache/fop/fonts/FontReader.java @@ -34,6 +34,7 @@ import org.xml.sax.Attributes; import org.xml.sax.InputSource; import org.xml.sax.Locator; import org.xml.sax.SAXException; +import org.xml.sax.SAXParseException; import org.xml.sax.XMLReader; import org.xml.sax.helpers.DefaultHandler; @@ -52,7 +53,7 @@ import org.apache.fop.fonts.apps.TTFReader; */ public class FontReader extends DefaultHandler { - private Locator locator = null; + // private Locator locator = null; // not used at present private boolean isCID = false; private CustomFont returnFont = null; private MultiByteFont multiFont = null; @@ -116,6 +117,14 @@ public class FontReader extends DefaultHandler { returnFont.setKerningEnabled(enabled); } + /** + * Enable/disable use of advanced typographic features for the font + * @param enabled true to enable, false to disable + */ + public void setAdvancedEnabled(boolean enabled) { + returnFont.setAdvancedEnabled(enabled); + } + /** * Sets the font resolver. Needed for URI resolution. * @param resolver the font resolver @@ -153,7 +162,7 @@ public class FontReader extends DefaultHandler { * {@inheritDoc} */ public void setDocumentLocator(Locator locator) { - this.locator = locator; + // this.locator = locator; // not used at present } /** @@ -212,6 +221,7 @@ public class FontReader extends DefaultHandler { currentKerning.put(new Integer(attributes.getValue("kpx2")), new Integer(attributes.getValue("kern"))); } + } private int getInt(String str) throws SAXException { @@ -305,6 +315,5 @@ public class FontReader extends DefaultHandler { public void characters(char[] ch, int start, int length) { text.append(ch, start, length); } -} - +} diff --git a/src/java/org/apache/fop/fonts/FontResolver.java b/src/java/org/apache/fop/fonts/FontResolver.java index 1da2339f7..bd155482e 100644 --- a/src/java/org/apache/fop/fonts/FontResolver.java +++ b/src/java/org/apache/fop/fonts/FontResolver.java @@ -36,4 +36,10 @@ public interface FontResolver { */ Source resolve(String href); + /** + * Check whether complex script features are enabled. + * @return true if FOP is to use complex script features + */ + boolean isComplexScriptFeaturesEnabled(); + } diff --git a/src/java/org/apache/fop/fonts/FontSetup.java b/src/java/org/apache/fop/fonts/FontSetup.java index 935f695b1..ba31b2d50 100644 --- a/src/java/org/apache/fop/fonts/FontSetup.java +++ b/src/java/org/apache/fop/fonts/FontSetup.java @@ -57,9 +57,10 @@ public final class FontSetup { /** * Sets up a font info * @param fontInfo font info + * @param base14Kerning true if base14 kerning applies */ - public static void setup(FontInfo fontInfo) { - setup(fontInfo, null, null); + public static void setup(FontInfo fontInfo, boolean base14Kerning) { + setup(fontInfo, null, null, base14Kerning); } /** @@ -71,10 +72,10 @@ public final class FontSetup { * @param fontInfo the font info object to set up * @param embedFontInfoList a list of EmbedFontInfo objects * @param resolver the font resolver + * @param base14Kerning true if base14 kerning applies */ public static void setup(FontInfo fontInfo, List embedFontInfoList, - FontResolver resolver) { - final boolean base14Kerning = false; + FontResolver resolver, boolean base14Kerning) { fontInfo.addMetrics("F1", new Helvetica(base14Kerning)); fontInfo.addMetrics("F2", new HelveticaOblique(base14Kerning)); fontInfo.addMetrics("F3", new HelveticaBold(base14Kerning)); @@ -180,7 +181,7 @@ public final class FontSetup { final int startNum = 15; /* Add configured fonts */ - addConfiguredFonts(fontInfo, embedFontInfoList, startNum, resolver); + addConfiguredFonts(fontInfo, embedFontInfoList, startNum, resolver, base14Kerning); } /** @@ -191,14 +192,17 @@ public final class FontSetup { * @param resolver the font resolver */ private static void addConfiguredFonts(FontInfo fontInfo, - List embedFontInfoList, int num, FontResolver resolver) { + List embedFontInfoList, int num, FontResolver resolver, + boolean base14Kerning) { if (embedFontInfoList == null) { return; //No fonts to process } if (resolver == null) { //Ensure that we have minimal font resolution capabilities - resolver = createMinimalFontResolver(); + //None of the built-in base14 fonts have advanced typographic data + boolean useAdvanced = false; + resolver = createMinimalFontResolver(useAdvanced); } String internalName = null; @@ -218,15 +222,31 @@ public final class FontSetup { } } - /** @return a new FontResolver to be used by the font subsystem */ - public static FontResolver createMinimalFontResolver() { - return new FontResolver() { + /** + * Minimum implemenation of FontResolver. + */ + public static class MinimalFontResolver implements FontResolver { + private boolean useComplexScriptFeatures; + MinimalFontResolver(boolean useComplexScriptFeatures) { + this.useComplexScriptFeatures = useComplexScriptFeatures; + } + /** {@inheritDoc} */ + public Source resolve(String href) { + //Minimal functionality here + return new StreamSource(href); + } + /** {@inheritDoc} */ + public boolean isComplexScriptFeaturesEnabled() { + return useComplexScriptFeatures; + } + } - /** {@inheritDoc} */ - public Source resolve(String href) { - //Minimal functionality here - return new StreamSource(href); - } - }; + /** + * Create minimal font resolver. + * @param useComplexScriptFeatures true if complex script features enabled + * @return a new FontResolver to be used by the font subsystem + */ + public static FontResolver createMinimalFontResolver(boolean useComplexScriptFeatures) { + return new MinimalFontResolver ( useComplexScriptFeatures ); } } diff --git a/src/java/org/apache/fop/fonts/LazyFont.java b/src/java/org/apache/fop/fonts/LazyFont.java index f331a331e..dfd2367b2 100644 --- a/src/java/org/apache/fop/fonts/LazyFont.java +++ b/src/java/org/apache/fop/fonts/LazyFont.java @@ -29,28 +29,34 @@ import javax.xml.transform.stream.StreamSource; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + import org.apache.fop.apps.FOPException; +import org.apache.fop.complexscripts.fonts.Positionable; +import org.apache.fop.complexscripts.fonts.Substitutable; + + import org.xml.sax.InputSource; /** * This class is used to defer the loading of a font until it is really used. */ -public class LazyFont extends Typeface implements FontDescriptor { +public class LazyFont extends Typeface implements FontDescriptor, Substitutable, Positionable { private static Log log = LogFactory.getLog(LazyFont.class); - private String metricsFileName = null; - private String fontEmbedPath = null; - private boolean useKerning = false; + private String metricsFileName; + private String fontEmbedPath; + private boolean useKerning; + private boolean useAdvanced; private EncodingMode encodingMode = EncodingMode.AUTO; - private boolean embedded = true; - private String subFontName = null; + private boolean embedded; + private String subFontName; - private boolean isMetricsLoaded = false; - private Typeface realFont = null; - private FontDescriptor realFontDescriptor = null; + private boolean isMetricsLoaded; + private Typeface realFont; + private FontDescriptor realFontDescriptor; - private FontResolver resolver = null; + private FontResolver resolver; /** * Main constructor @@ -62,6 +68,11 @@ public class LazyFont extends Typeface implements FontDescriptor { this.metricsFileName = fontInfo.getMetricsFile(); this.fontEmbedPath = fontInfo.getEmbedFile(); this.useKerning = fontInfo.getKerning(); + if ( resolver != null ) { + this.useAdvanced = resolver.isComplexScriptFeaturesEnabled(); + } else { + this.useAdvanced = fontInfo.getAdvanced(); + } this.encodingMode = fontInfo.getEncodingMode(); this.subFontName = fontInfo.getSubFontName(); this.embedded = fontInfo.isEmbedded(); @@ -70,9 +81,15 @@ public class LazyFont extends Typeface implements FontDescriptor { /** {@inheritDoc} */ public String toString() { - return ( "metrics-url=" + metricsFileName + ", embed-url=" + fontEmbedPath - + ", kerning=" + useKerning ); - } + StringBuffer sbuf = new StringBuffer(super.toString()); + sbuf.append('{'); + sbuf.append("metrics-url=" + metricsFileName); + sbuf.append(",embed-url=" + fontEmbedPath); + sbuf.append(",kerning=" + useKerning); + sbuf.append(",advanced=" + useAdvanced); + sbuf.append('}'); + return sbuf.toString(); + } private void load(boolean fail) { if (!isMetricsLoaded) { @@ -120,6 +137,7 @@ public class LazyFont extends Typeface implements FontDescriptor { new URL(metricsFileName).openStream())); } reader.setKerningEnabled(useKerning); + reader.setAdvancedEnabled(useAdvanced); if (this.embedded) { reader.setFontEmbedPath(fontEmbedPath); } @@ -130,7 +148,7 @@ public class LazyFont extends Typeface implements FontDescriptor { throw new RuntimeException("Cannot load font. No font URIs available."); } realFont = FontLoader.loadFont(fontEmbedPath, this.subFontName, - this.embedded, this.encodingMode, useKerning, resolver); + this.embedded, this.encodingMode, useKerning, useAdvanced, resolver); } if (realFont instanceof FontDescriptor) { realFontDescriptor = (FontDescriptor) realFont; @@ -373,6 +391,84 @@ public class LazyFont extends Typeface implements FontDescriptor { return realFontDescriptor.isEmbeddable(); } + /** + * {@inheritDoc} + */ + public boolean performsSubstitution() { + load(true); + if ( realFontDescriptor instanceof Substitutable ) { + return ((Substitutable)realFontDescriptor).performsSubstitution(); + } else { + return false; + } + } + + /** + * {@inheritDoc} + */ + public CharSequence performSubstitution ( CharSequence cs, String script, String language ) { + load(true); + if ( realFontDescriptor instanceof Substitutable ) { + return ((Substitutable)realFontDescriptor).performSubstitution(cs, script, language); + } else { + return cs; + } + } + + /** + * {@inheritDoc} + */ + public CharSequence reorderCombiningMarks + ( CharSequence cs, int[][] gpa, String script, String language ) { + load(true); + if ( realFontDescriptor instanceof Substitutable ) { + return ((Substitutable)realFontDescriptor). + reorderCombiningMarks(cs, gpa, script, language); + } else { + return cs; + } + } + + /** + * {@inheritDoc} + */ + public boolean performsPositioning() { + load(true); + if ( realFontDescriptor instanceof Positionable ) { + return ((Positionable)realFontDescriptor).performsPositioning(); + } else { + return false; + } + } + + /** + * {@inheritDoc} + */ + public int[][] + performPositioning ( CharSequence cs, String script, String language, int fontSize ) { + load(true); + if ( realFontDescriptor instanceof Positionable ) { + return ((Positionable)realFontDescriptor) + .performPositioning(cs, script, language, fontSize); + } else { + return null; + } + } + + /** + * {@inheritDoc} + */ + public int[][] + performPositioning ( CharSequence cs, String script, String language ) { + load(true); + if ( realFontDescriptor instanceof Positionable ) { + return ((Positionable)realFontDescriptor) + .performPositioning(cs, script, language); + } else { + return null; + } + } + /** * {@inheritDoc} */ diff --git a/src/java/org/apache/fop/fonts/MultiByteFont.java b/src/java/org/apache/fop/fonts/MultiByteFont.java index 0d9897268..3b15662dc 100644 --- a/src/java/org/apache/fop/fonts/MultiByteFont.java +++ b/src/java/org/apache/fop/fonts/MultiByteFont.java @@ -19,14 +19,29 @@ package org.apache.fop.fonts; -//Java +import java.nio.CharBuffer; +import java.nio.IntBuffer; import java.util.Map; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.apache.fop.complexscripts.fonts.GlyphDefinitionTable; +import org.apache.fop.complexscripts.fonts.GlyphPositioningTable; +import org.apache.fop.complexscripts.fonts.GlyphSubstitutionTable; +import org.apache.fop.complexscripts.fonts.Positionable; +import org.apache.fop.complexscripts.fonts.Substitutable; +import org.apache.fop.complexscripts.util.GlyphSequence; +import org.apache.fop.util.CharUtilities; /** * Generic MultiByte (CID) font */ -public class MultiByteFont extends CIDFont { +public class MultiByteFont extends CIDFont implements Substitutable, Positionable { + + /** logging instance */ + private static final Log log // CSOK: ConstantNameCheck + = LogFactory.getLog(MultiByteFont.class); private String ttcName = null; private String encoding = "Identity-H"; @@ -36,9 +51,28 @@ public class MultiByteFont extends CIDFont { private CIDSubset subset = new CIDSubset(); - /** A map from Unicode indices to glyph indices */ + /** + * A map from Unicode indices to glyph indices. No assumption + * about ordering is made below. If lookup is changed to a binary + * search (from the current linear search), then addPrivateUseMapping() + * needs to be changed to perform ordered inserts. + */ private BFEntry[] bfentries = null; + /* advanced typographic support */ + private GlyphDefinitionTable gdef; + private GlyphSubstitutionTable gsub; + private GlyphPositioningTable gpos; + + /* dynamic private use (character) mappings */ + private int numMapped; + private int numUnmapped; + private int nextPrivateUse = 0xE000; + private int firstPrivate; + private int lastPrivate; + private int firstUnmapped; + private int lastUnmapped; + /** * Default constructor */ @@ -132,13 +166,14 @@ public class MultiByteFont extends CIDFont { * @param c the Unicode character index * @return the glyph index (or 0 if the glyph is not available) */ - private int findGlyphIndex(char c) { - int idx = (int)c; + // [TBD] - needs optimization, i.e., change from linear search to binary search + private int findGlyphIndex(int c) { + int idx = c; int retIdx = SingleByteEncoding.NOT_FOUND_CODE_POINT; for (int i = 0; (i < bfentries.length) && retIdx == 0; i++) { if (bfentries[i].getUnicodeStart() <= idx - && bfentries[i].getUnicodeEnd() >= idx) { + && bfentries[i].getUnicodeEnd() >= idx) { retIdx = bfentries[i].getGlyphStartIndex() + idx @@ -148,6 +183,95 @@ public class MultiByteFont extends CIDFont { return retIdx; } + /** + * Add a private use mapping {PU,GI} to the existing BFENTRIES map. + * N.B. Does not insert in order, merely appends to end of existing map. + */ + private synchronized void addPrivateUseMapping ( int pu, int gi ) { + assert findGlyphIndex ( pu ) == SingleByteEncoding.NOT_FOUND_CODE_POINT; + BFEntry[] bfeOld = bfentries; + int bfeCnt = bfeOld.length; + BFEntry[] bfeNew = new BFEntry [ bfeCnt + 1 ]; + System.arraycopy ( bfeOld, 0, bfeNew, 0, bfeCnt ); + bfeNew [ bfeCnt ] = new BFEntry ( pu, pu, gi ); + bfentries = bfeNew; + } + + /** + * Given a glyph index, create a new private use mapping, augmenting the bfentries + * table. This is needed to accommodate the presence of an (output) glyph index in a + * complex script glyph substitution that does not correspond to a character in the + * font's CMAP. The creation of such private use mappings is deferred until an + * attempt is actually made to perform the reverse lookup from the glyph index. This + * is necessary in order to avoid exhausting the private use space on fonts containing + * many such non-mapped glyph indices, if these mappings had been created statically + * at font load time. + * @param gi glyph index + * @returns unicode scalar value + */ + private int createPrivateUseMapping ( int gi ) { + while ( ( nextPrivateUse < 0xF900 ) + && ( findGlyphIndex(nextPrivateUse) != SingleByteEncoding.NOT_FOUND_CODE_POINT ) ) { + nextPrivateUse++; + } + if ( nextPrivateUse < 0xF900 ) { + int pu = nextPrivateUse; + addPrivateUseMapping ( pu, gi ); + if ( firstPrivate == 0 ) { + firstPrivate = pu; + } + lastPrivate = pu; + numMapped++; + if (log.isDebugEnabled()) { + log.debug ( "Create private use mapping from " + + CharUtilities.format ( pu ) + + " to glyph index " + gi + + " in font '" + getFullName() + "'" ); + } + return pu; + } else { + if ( firstUnmapped == 0 ) { + firstUnmapped = gi; + } + lastUnmapped = gi; + numUnmapped++; + log.warn ( "Exhausted private use area: unable to map " + + numUnmapped + " glyphs in glyph index range [" + + firstUnmapped + "," + lastUnmapped + + "] (inclusive) of font '" + getFullName() + "'" ); + return 0; + } + } + + /** + * Returns the Unicode scalar value that corresponds to the glyph index. If more than + * one correspondence exists, then the first one is returned (ordered by bfentries[]). + * @param gi glyph index + * @returns unicode scalar value + */ + // [TBD] - needs optimization, i.e., change from linear search to binary search + private int findCharacterFromGlyphIndex ( int gi, boolean augment ) { + int cc = 0; + for ( int i = 0, n = bfentries.length; i < n; i++ ) { + BFEntry be = bfentries [ i ]; + int s = be.getGlyphStartIndex(); + int e = s + ( be.getUnicodeEnd() - be.getUnicodeStart() ); + if ( ( gi >= s ) && ( gi <= e ) ) { + cc = be.getUnicodeStart() + ( gi - s ); + break; + } + } + if ( ( cc == 0 ) && augment ) { + cc = createPrivateUseMapping ( gi ); + } + return cc; + } + + private int findCharacterFromGlyphIndex ( int gi ) { + return findCharacterFromGlyphIndex ( gi, true ); + } + + /** {@inheritDoc} */ public char mapChar(char c) { notifyMapOperation(); @@ -223,5 +347,220 @@ public class MultiByteFont extends CIDFont { } return subset.getSubsetChars(); } + + /** + * Establishes the glyph definition table. + * @param gdef the glyph definition table to be used by this font + */ + public void setGDEF ( GlyphDefinitionTable gdef ) { + if ( ( this.gdef == null ) || ( gdef == null ) ) { + this.gdef = gdef; + } else { + throw new IllegalStateException ( "font already associated with GDEF table" ); + } + } + + /** + * Obtain glyph definition table. + * @return glyph definition table or null if none is associated with font + */ + public GlyphDefinitionTable getGDEF() { + return gdef; + } + + /** + * Establishes the glyph substitution table. + * @param gsub the glyph substitution table to be used by this font + */ + public void setGSUB ( GlyphSubstitutionTable gsub ) { + if ( ( this.gsub == null ) || ( gsub == null ) ) { + this.gsub = gsub; + } else { + throw new IllegalStateException ( "font already associated with GSUB table" ); + } + } + + /** + * Obtain glyph substitution table. + * @return glyph substitution table or null if none is associated with font + */ + public GlyphSubstitutionTable getGSUB() { + return gsub; + } + + /** + * Establishes the glyph positioning table. + * @param gpos the glyph positioning table to be used by this font + */ + public void setGPOS ( GlyphPositioningTable gpos ) { + if ( ( this.gpos == null ) || ( gpos == null ) ) { + this.gpos = gpos; + } else { + throw new IllegalStateException ( "font already associated with GPOS table" ); + } + } + + /** + * Obtain glyph positioning table. + * @return glyph positioning table or null if none is associated with font + */ + public GlyphPositioningTable getGPOS() { + return gpos; + } + + /** {@inheritDoc} */ + public boolean performsSubstitution() { + return gsub != null; + } + + /** {@inheritDoc} */ + public CharSequence performSubstitution ( CharSequence cs, String script, String language ) { + if ( gsub != null ) { + GlyphSequence igs = mapCharsToGlyphs ( cs ); + GlyphSequence ogs = gsub.substitute ( igs, script, language ); + CharSequence ocs = mapGlyphsToChars ( ogs ); + return ocs; + } else { + return cs; + } + } + + /** {@inheritDoc} */ + public CharSequence reorderCombiningMarks + ( CharSequence cs, int[][] gpa, String script, String language ) { + if ( gdef != null ) { + GlyphSequence igs = mapCharsToGlyphs ( cs ); + GlyphSequence ogs = gdef.reorderCombiningMarks ( igs, gpa, script, language ); + CharSequence ocs = mapGlyphsToChars ( ogs ); + return ocs; + } else { + return cs; + } + } + + /** {@inheritDoc} */ + public boolean performsPositioning() { + return gpos != null; + } + + /** {@inheritDoc} */ + public int[][] + performPositioning ( CharSequence cs, String script, String language, int fontSize ) { + if ( gpos != null ) { + GlyphSequence gs = mapCharsToGlyphs ( cs ); + int[][] adjustments = new int [ gs.getGlyphCount() ] [ 4 ]; + if ( gpos.position ( gs, script, language, fontSize, this.width, adjustments ) ) { + return scaleAdjustments ( adjustments, fontSize ); + } else { + return null; + } + } else { + return null; + } + } + + /** {@inheritDoc} */ + public int[][] performPositioning ( CharSequence cs, String script, String language ) { + throw new UnsupportedOperationException(); + } + + + private int[][] scaleAdjustments ( int[][] adjustments, int fontSize ) { + if ( adjustments != null ) { + for ( int i = 0, n = adjustments.length; i < n; i++ ) { + int[] gpa = adjustments [ i ]; + for ( int k = 0; k < 4; k++ ) { + gpa [ k ] = ( gpa [ k ] * fontSize ) / 1000; + } + } + return adjustments; + } else { + return null; + } + } + + /** + * Map sequence CS, comprising a sequence of UTF-16 encoded Unicode Code Points, to + * an output character sequence GS, comprising a sequence of Glyph Indices. N.B. Unlike + * mapChar(), this method does not make use of embedded subset encodings. + * @param cs a CharSequence containing UTF-16 encoded Unicode characters + * @returns a CharSequence containing glyph indices + */ + private GlyphSequence mapCharsToGlyphs ( CharSequence cs ) { + IntBuffer cb = IntBuffer.allocate ( cs.length() ); + IntBuffer gb = IntBuffer.allocate ( cs.length() ); + int gi, giMissing = findGlyphIndex ( Typeface.NOT_FOUND ); + for ( int i = 0, n = cs.length(); i < n; i++ ) { + int cc = cs.charAt ( i ); + if ( ( cc >= 0xD800 ) && ( cc < 0xDC00 ) ) { + if ( ( i + 1 ) < n ) { + int sh = cc; + int sl = cs.charAt ( ++i ); + if ( ( sl >= 0xDC00 ) && ( sl < 0xE000 ) ) { + cc = 0x10000 + ( ( sh - 0xD800 ) << 10 ) + ( ( sl - 0xDC00 ) << 0 ); + } else { + throw new IllegalArgumentException + ( "ill-formed UTF-16 sequence, " + + "contains isolated high surrogate at index " + i ); + } + } else { + throw new IllegalArgumentException + ( "ill-formed UTF-16 sequence, " + + "contains isolated high surrogate at end of sequence" ); + } + } else if ( ( cc >= 0xDC00 ) && ( cc < 0xE000 ) ) { + throw new IllegalArgumentException + ( "ill-formed UTF-16 sequence, " + + "contains isolated low surrogate at index " + i ); + } + notifyMapOperation(); + gi = findGlyphIndex ( cc ); + if ( gi == SingleByteEncoding.NOT_FOUND_CODE_POINT ) { + warnMissingGlyph ( (char) cc ); + gi = giMissing; + } + cb.put ( cc ); + gb.put ( gi ); + } + cb.flip(); + gb.flip(); + return new GlyphSequence ( cb, gb, null ); + } + + /** + * Map sequence GS, comprising a sequence of Glyph Indices, to output sequence CS, + * comprising a sequence of UTF-16 encoded Unicode Code Points. + * @param gs a GlyphSequence containing glyph indices + * @returns a CharSequence containing UTF-16 encoded Unicode characters + */ + private CharSequence mapGlyphsToChars ( GlyphSequence gs ) { + int ng = gs.getGlyphCount(); + CharBuffer cb = CharBuffer.allocate ( ng ); + int ccMissing = Typeface.NOT_FOUND; + for ( int i = 0, n = ng; i < n; i++ ) { + int gi = gs.getGlyph ( i ); + int cc = findCharacterFromGlyphIndex ( gi ); + if ( ( cc == 0 ) || ( cc > 0x10FFFF ) ) { + cc = ccMissing; + log.warn("Unable to map glyph index " + gi + + " to Unicode scalar in font '" + + getFullName() + "', substituting missing character '" + + (char) cc + "'"); + } + if ( cc > 0x00FFFF ) { + int sh, sl; + cc -= 0x10000; + sh = ( ( cc >> 10 ) & 0x3FF ) + 0xD800; + sl = ( ( cc >> 0 ) & 0x3FF ) + 0xDC00; + cb.put ( (char) sh ); + cb.put ( (char) sl ); + } else { + cb.put ( (char) cc ); + } + } + cb.flip(); + return (CharSequence) cb; + } + } diff --git a/src/java/org/apache/fop/fonts/MutableFont.java b/src/java/org/apache/fop/fonts/MutableFont.java index bcbcadbdc..41c552a0b 100644 --- a/src/java/org/apache/fop/fonts/MutableFont.java +++ b/src/java/org/apache/fop/fonts/MutableFont.java @@ -132,6 +132,12 @@ public interface MutableFont { */ void setKerningEnabled(boolean enabled); + /** + * Enables/disabled advanced typographic features. + * @param enabled true if advanced typographic features should be enabled if available + */ + void setAdvancedEnabled(boolean enabled); + /** * Adds an entry to the kerning table. * @param key Kerning key diff --git a/src/java/org/apache/fop/fonts/Typeface.java b/src/java/org/apache/fop/fonts/Typeface.java index a0c1d99ec..e933781cd 100644 --- a/src/java/org/apache/fop/fonts/Typeface.java +++ b/src/java/org/apache/fop/fonts/Typeface.java @@ -143,6 +143,10 @@ public abstract class Typeface implements FontMetrics { /** {@inheritDoc} */ public String toString() { - return getFullName(); + StringBuffer sbuf = new StringBuffer(super.toString()); + sbuf.append('{'); + sbuf.append(getFullName()); + sbuf.append('}'); + return sbuf.toString(); } } diff --git a/src/java/org/apache/fop/fonts/apps/AbstractFontReader.java b/src/java/org/apache/fop/fonts/apps/AbstractFontReader.java index 1c973cd51..89c7890af 100644 --- a/src/java/org/apache/fop/fonts/apps/AbstractFontReader.java +++ b/src/java/org/apache/fop/fonts/apps/AbstractFontReader.java @@ -67,7 +67,7 @@ public abstract class AbstractFontReader { List arguments = new java.util.ArrayList(); for (int i = 0; i < args.length; i++) { if (args[i].startsWith("-")) { - if ("-d".equals(args[i]) || "-q".equals(args[i])) { + if ("-t".equals(args[i]) || "-d".equals(args[i]) || "-q".equals(args[i])) { options.put(args[i], ""); } else if ((i + 1) < args.length && !args[i + 1].startsWith("-")) { options.put(args[i], args[i + 1]); @@ -101,7 +101,9 @@ public abstract class AbstractFontReader { */ protected static void determineLogLevel(Map options) { //Determine log level - if (options.get("-d") != null) { + if (options.get("-t") != null) { + setLogLevel("trace"); + } else if (options.get("-d") != null) { setLogLevel("debug"); } else if (options.get("-q") != null) { setLogLevel("error"); diff --git a/src/java/org/apache/fop/fonts/apps/TTFReader.java b/src/java/org/apache/fop/fonts/apps/TTFReader.java index 6e64f9144..1804a8dd9 100644 --- a/src/java/org/apache/fop/fonts/apps/TTFReader.java +++ b/src/java/org/apache/fop/fonts/apps/TTFReader.java @@ -21,6 +21,7 @@ package org.apache.fop.fonts.apps; import java.io.IOException; import java.util.Iterator; +import java.util.List; import java.util.Map; import java.util.Set; @@ -38,6 +39,9 @@ import org.w3c.dom.Element; import org.xml.sax.Attributes; import org.xml.sax.SAXException; +// CSOFF: InnerAssignmentCheck +// CSOFF: LineLengthCheck + /** * A tool which reads TTF files and generates * XML font metrics file for use in FOP. @@ -61,6 +65,7 @@ public class TTFReader extends AbstractFontReader { "java " + TTFReader.class.getName() + " [options] fontfile.ttf xmlfile.xml"); System.out.println(); System.out.println("where options can be:"); + System.out.println("-t Trace mode"); System.out.println("-d Debug mode"); System.out.println("-q Quiet mode"); System.out.println("-enc ansi"); @@ -102,6 +107,8 @@ public class TTFReader extends AbstractFontReader { * you can also include the fontfile in the fop.jar file when building fop. * You can use both -ef and -er. The file specified in -ef will be searched first, * then the -er file. + * -nocs + * if complex script features are disabled */ public static void main(String[] args) { String embFile = null; @@ -155,13 +162,19 @@ public class TTFReader extends AbstractFontReader { className = (String)options.get("-cn"); } + boolean useKerning = true; + boolean useAdvanced = true; + if (options.get("-nocs") != null) { + useAdvanced = false; + } + if (arguments.length != 2 || options.get("-h") != null || options.get("-help") != null || options.get("--help") != null) { displayUsage(); } else { try { log.info("Parsing font..."); - TTFFile ttf = app.loadTTF(arguments[0], ttcName); + TTFFile ttf = app.loadTTF(arguments[0], ttcName, useKerning, useAdvanced); if (ttf != null) { org.w3c.dom.Document doc = app.constructFontXML(ttf, fontName, className, embResource, embFile, isCid, @@ -198,11 +211,13 @@ public class TTFReader extends AbstractFontReader { * * @param fileName The filename of the TTF file. * @param fontName The name of the font + * @param useKerning true if should load kerning data + * @param useAdvanced true if should load advanced typographic table data * @return The TTF as an object, null if the font is incompatible. * @throws IOException In case of an I/O problem */ - public TTFFile loadTTF(String fileName, String fontName) throws IOException { - TTFFile ttfFile = new TTFFile(); + public TTFFile loadTTF(String fileName, String fontName, boolean useKerning, boolean useAdvanced) throws IOException { + TTFFile ttfFile = new TTFFile(useKerning, useAdvanced); log.info("Reading " + fileName + "..."); FontFileReader reader = new FontFileReader(fileName); @@ -463,7 +478,6 @@ public class TTFReader extends AbstractFontReader { } } - /** * Bugzilla 40739, check that attr has a metrics-version attribute * compatible with ours. diff --git a/src/java/org/apache/fop/fonts/autodetect/FontInfoFinder.java b/src/java/org/apache/fop/fonts/autodetect/FontInfoFinder.java index 714af0e57..bf6f493cf 100644 --- a/src/java/org/apache/fop/fonts/autodetect/FontInfoFinder.java +++ b/src/java/org/apache/fop/fonts/autodetect/FontInfoFinder.java @@ -148,7 +148,7 @@ public class FontInfoFinder { subFontName = ((MultiByteFont)customFont).getTTCName(); } EmbedFontInfo fontInfo = new EmbedFontInfo(null, customFont.isKerningEnabled(), - fontTripletList, embedUrl, subFontName); + customFont.isAdvancedEnabled(), fontTripletList, embedUrl, subFontName); fontInfo.setPostScriptName(customFont.getFontName()); if (fontCache != null) { fontCache.addFont(fontInfo); @@ -168,6 +168,9 @@ public class FontInfoFinder { public EmbedFontInfo[] find(URL fontURL, FontResolver resolver, FontCache fontCache) { String embedURL = null; embedURL = fontURL.toExternalForm(); + boolean useKerning = true; + boolean useAdvanced = ( resolver != null ) + ? resolver.isComplexScriptFeaturesEnabled() : true; long fileLastModified = -1; if (fontCache != null) { @@ -190,14 +193,14 @@ public class FontInfoFinder { // try to determine triplet information from font file CustomFont customFont = null; - if (fontURL.toExternalForm().endsWith(".ttc")) { + if (fontURL.toExternalForm().toLowerCase().endsWith(".ttc")) { // Get a list of the TTC Font names List ttcNames = null; String fontFileURL = fontURL.toExternalForm().trim(); InputStream in = null; try { in = FontLoader.openFontUri(resolver, fontFileURL); - TTFFile ttf = new TTFFile(); + TTFFile ttf = new TTFFile(false, false); FontFileReader reader = new FontFileReader(in); ttcNames = ttf.getTTCnames(reader); } catch (Exception e) { @@ -218,7 +221,8 @@ public class FontInfoFinder { } try { TTFFontLoader ttfLoader = new TTFFontLoader( - fontFileURL, fontName, true, EncodingMode.AUTO, true, resolver); + fontFileURL, fontName, true, EncodingMode.AUTO, + useKerning, useAdvanced, resolver); customFont = ttfLoader.getFont(); if (this.eventListener != null) { customFont.setEventListener(this.eventListener); diff --git a/src/java/org/apache/fop/fonts/truetype/TTFDirTabEntry.java b/src/java/org/apache/fop/fonts/truetype/TTFDirTabEntry.java index 405a71395..1f05ebfa1 100644 --- a/src/java/org/apache/fop/fonts/truetype/TTFDirTabEntry.java +++ b/src/java/org/apache/fop/fonts/truetype/TTFDirTabEntry.java @@ -26,7 +26,7 @@ import java.io.UnsupportedEncodingException; /** * This class represents an entry to a TrueType font's Dir Tab. */ -class TTFDirTabEntry { +public class TTFDirTabEntry { private byte[] tag = new byte[4]; private int checksum; @@ -34,7 +34,10 @@ class TTFDirTabEntry { private long length; /** - * Read Dir Tab, return tag name + * Read Dir Tab. + * @param in font file reader + * @return tag name + * @throws IOException upon I/O exception */ public String read(FontFileReader in) throws IOException { tag[0] = in.readTTFByte(); @@ -52,6 +55,7 @@ class TTFDirTabEntry { } + @Override public String toString() { return "Read dir tab [" + tag[0] + " " + tag[1] + " " + tag[2] + " " + tag[3] + "]" diff --git a/src/java/org/apache/fop/fonts/truetype/TTFFile.java b/src/java/org/apache/fop/fonts/truetype/TTFFile.java index f4806d95e..33d608540 100644 --- a/src/java/org/apache/fop/fonts/truetype/TTFFile.java +++ b/src/java/org/apache/fop/fonts/truetype/TTFFile.java @@ -28,9 +28,15 @@ import java.util.Set; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.apache.fop.fonts.FontUtil; import org.apache.xmlgraphics.fonts.Glyphs; +import org.apache.fop.complexscripts.fonts.AdvancedTypographicTableFormatException; +import org.apache.fop.complexscripts.fonts.GlyphDefinitionTable; +import org.apache.fop.complexscripts.fonts.GlyphPositioningTable; +import org.apache.fop.complexscripts.fonts.GlyphSubstitutionTable; +import org.apache.fop.complexscripts.fonts.OTFAdvancedTypographicTableReader; +import org.apache.fop.fonts.FontUtil; + /** * Reads a TrueType file or a TrueType Collection. * The TrueType spec can be found at the Microsoft. @@ -43,12 +49,12 @@ public class TTFFile { static final int MAX_CHAR_CODE = 255; static final int ENC_BUF_SIZE = 1024; - /** Set to true to get even more debug output than with level DEBUG */ - public static final boolean TRACE_ENABLED = false; - private final String encoding = "WinAnsiEncoding"; // Default encoding private final short firstChar = 0; + + private boolean useKerning = false; + private boolean isEmbeddable = true; private boolean hasSerifs = true; /** @@ -58,7 +64,7 @@ public class TTFFile { private Map> kerningTab; // for CIDs private Map> ansiKerningTab; // For winAnsiEncoding private List cmaps; - private List unicodeMapping; + private Set unicodeMappings; private int upem; // unitsPerEm from "head" table private int nhmtx; // Number of horizontal metrics @@ -120,15 +126,29 @@ public class TTFFile { private boolean isCFF; + // advanced typographic table support + private boolean useAdvanced = false; + private OTFAdvancedTypographicTableReader advancedTableReader; + /** * logging instance */ protected Log log = LogFactory.getLog(TTFFile.class); + /** + * Constructor + * @param useKerning true if kerning data should be loaded + * @param useAdvanced true if advanced typographic tables should be loaded + */ + public TTFFile ( boolean useKerning, boolean useAdvanced ) { + this.useKerning = useKerning; + this.useAdvanced = useAdvanced; + } + /** * Key-value helper class */ - class UnicodeMapping { + class UnicodeMapping implements Comparable { private final int unicodeIndex; private final int glyphIndex; @@ -155,15 +175,67 @@ public class TTFFile { public int getUnicodeIndex() { return unicodeIndex; } + + + /** {@inheritDoc} */ + public int hashCode() { + int hc = unicodeIndex; + hc = 19 * hc + ( hc ^ glyphIndex ); + return hc; + } + + /** {@inheritDoc} */ + public boolean equals ( Object o ) { + if ( o instanceof UnicodeMapping ) { + UnicodeMapping m = (UnicodeMapping) o; + if ( unicodeIndex != m.unicodeIndex ) { + return false; + } else { + return ( glyphIndex == m.glyphIndex ); + } + } else { + return false; + } + } + + /** {@inheritDoc} */ + public int compareTo ( Object o ) { + if ( o instanceof UnicodeMapping ) { + UnicodeMapping m = (UnicodeMapping) o; + if ( unicodeIndex > m.unicodeIndex ) { + return 1; + } else if ( unicodeIndex < m.unicodeIndex ) { + return -1; + } else { + return 0; + } + } else { + return -1; + } + } + } + + /** + * Obtain directory table entry. + * @param name (tag) of entry + * @return a directory table entry or null if none found + */ + public TTFDirTabEntry getDirectoryEntry ( String name ) { + return (TTFDirTabEntry) dirTabs.get ( name ); } /** * Position inputstream to position indicated * in the dirtab offset + offset + * @param in font file reader + * @param name (tag) of table + * @param offset from start of table + * @return true if seek succeeded + * @throws IOException if I/O exception occurs during seek */ - boolean seekTab(FontFileReader in, String name, + public boolean seekTab(FontFileReader in, String name, long offset) throws IOException { - TTFDirTabEntry dt = (TTFDirTabEntry)dirTabs.get(name); + TTFDirTabEntry dt = getDirectoryEntry ( name ); if (dt == null) { log.error("Dirtab " + name + " not found."); return false; @@ -203,7 +275,7 @@ public class TTFFile { */ private boolean readCMAP(FontFileReader in) throws IOException { - unicodeMapping = new java.util.ArrayList(); + unicodeMappings = new java.util.TreeSet(); seekTab(in, "cmap", 2); int numCMap = in.readTTFUShort(); // Number of cmap subtables @@ -344,7 +416,7 @@ public class TTFFile { glyphIdx = (in.readTTFUShort() + cmapDeltas[i]) & 0xffff; - unicodeMapping.add(new UnicodeMapping(glyphIdx, j)); + unicodeMappings.add(new UnicodeMapping(glyphIdx, j)); mtxTab[glyphIdx].getUnicodeIndex().add(new Integer(j)); if (encodingID == 0 && j >= 0xF020 && j <= 0xF0FF) { @@ -354,7 +426,7 @@ public class TTFFile { int mapped = j - 0xF000; if (!eightBitGlyphs.get(mapped)) { //Only map if Unicode code point hasn't been mapped before - unicodeMapping.add(new UnicodeMapping(glyphIdx, mapped)); + unicodeMappings.add(new UnicodeMapping(glyphIdx, mapped)); mtxTab[glyphIdx].getUnicodeIndex().add(new Integer(mapped)); } } @@ -395,7 +467,7 @@ public class TTFFile { + mtxTab.length); } - unicodeMapping.add(new UnicodeMapping(glyphIdx, j)); + unicodeMappings.add(new UnicodeMapping(glyphIdx, j)); if (glyphIdx < mtxTab.length) { mtxTab[glyphIdx].getUnicodeIndex().add(new Integer(j)); } else { @@ -554,9 +626,27 @@ public class TTFFile { } // Create cmaps for bfentries createCMaps(); - // print_max_min(); - readKerning(in); + if ( useKerning ) { + readKerning(in); + } + + // Read advanced typographic tables. + if ( useAdvanced ) { + try { + OTFAdvancedTypographicTableReader atr + = new OTFAdvancedTypographicTableReader ( this, in ); + atr.readAll(); + this.advancedTableReader = atr; + } catch ( AdvancedTypographicTableFormatException e ) { + log.warn ( + "Encountered format constraint violation in advanced (typographic) table (AT) " + + "in font '" + getFullName() + "', ignoring AT data: " + + e.getMessage() + ); + } + } + guessVerticalMetricsFromGlyphBBox(); return true; } @@ -565,7 +655,7 @@ public class TTFFile { cmaps = new java.util.ArrayList(); TTFCmapEntry tce = new TTFCmapEntry(); - Iterator e = unicodeMapping.listIterator(); + Iterator e = unicodeMappings.iterator(); UnicodeMapping um = (UnicodeMapping)e.next(); UnicodeMapping lastMapping = um; @@ -927,8 +1017,8 @@ public class TTFFile { int mtxSize = Math.max(numberOfGlyphs, nhmtx); mtxTab = new TTFMtxEntry[mtxSize]; - if (TRACE_ENABLED) { - log.debug("*** Widths array: \n"); + if (log.isTraceEnabled()) { + log.trace("*** Widths array: \n"); } for (int i = 0; i < mtxSize; i++) { mtxTab[i] = new TTFMtxEntry(); @@ -937,11 +1027,9 @@ public class TTFFile { mtxTab[i].setWx(in.readTTFUShort()); mtxTab[i].setLsb(in.readTTFUShort()); - if (TRACE_ENABLED) { - if (log.isDebugEnabled()) { - log.debug(" width[" + i + "] = " - + convertTTFUnit2PDFUnit(mtxTab[i].getWx()) + ";"); - } + if (log.isTraceEnabled()) { + log.trace(" width[" + i + "] = " + + convertTTFUnit2PDFUnit(mtxTab[i].getWx()) + ";"); } } @@ -1045,7 +1133,7 @@ public class TTFFile { */ private void readOS2(FontFileReader in) throws IOException { // Check if font is embeddable - TTFDirTabEntry os2Entry = (TTFDirTabEntry)dirTabs.get("OS/2"); + TTFDirTabEntry os2Entry = getDirectoryEntry ( "OS/2" ); if (os2Entry != null) { seekTab(in, "OS/2", 0); int version = in.readTTFUShort(); @@ -1133,7 +1221,7 @@ public class TTFFile { * @throws IOException In case of a I/O problem */ private void readGlyf(FontFileReader in) throws IOException { - TTFDirTabEntry dirTab = (TTFDirTabEntry)dirTabs.get("glyf"); + TTFDirTabEntry dirTab = getDirectoryEntry ( "glyf" ); if (dirTab == null) { throw new IOException("glyf table not found, cannot continue"); } @@ -1153,7 +1241,7 @@ public class TTFFile { } - long n = ((TTFDirTabEntry)dirTabs.get("glyf")).getOffset(); + long n = dirTab.getOffset(); for (int i = 0; i < numberOfGlyphs; i++) { if ((i + 1) >= mtxTab.length || mtxTab[i].getOffset() != mtxTab[i + 1].getOffset()) { @@ -1259,7 +1347,7 @@ public class TTFFile { * @throws IOException In case of a I/O problem */ private boolean readPCLT(FontFileReader in) throws IOException { - TTFDirTabEntry dirTab = (TTFDirTabEntry)dirTabs.get("PCLT"); + TTFDirTabEntry dirTab = getDirectoryEntry ( "PCLT" ); if (dirTab != null) { in.seekSet(dirTab.getOffset() + 4 + 4 + 2); xHeight = in.readTTFUShort(); @@ -1380,7 +1468,7 @@ public class TTFFile { capHeight = os2CapHeight; } if (capHeight == 0) { - log.warn("capHeight value could not be determined." + log.debug("capHeight value could not be determined." + " The font may not work as expected."); } } @@ -1390,7 +1478,7 @@ public class TTFFile { xHeight = os2xHeight; } if (xHeight == 0) { - log.warn("xHeight value could not be determined." + log.debug("xHeight value could not be determined." + " The font may not work as expected."); } } @@ -1406,7 +1494,7 @@ public class TTFFile { // Read kerning kerningTab = new java.util.HashMap(); ansiKerningTab = new java.util.HashMap(); - TTFDirTabEntry dirTab = (TTFDirTabEntry)dirTabs.get("kern"); + TTFDirTabEntry dirTab = getDirectoryEntry ( "kern" ); if (dirTab != null) { seekTab(in, "kern", 2); for (int n = in.readTTFUShort(); n > 0; n--) { @@ -1584,11 +1672,9 @@ public class TTFFile { dirOffsets[i] = in.readTTFULong(); } - if (log.isDebugEnabled()) { - log.debug("This is a TrueType collection file with " - + numDirectories + " fonts"); - log.debug("Containing the following fonts: "); - } + log.info("This is a TrueType collection file with " + + numDirectories + " fonts"); + log.info("Containing the following fonts: "); for (int i = 0; (i < numDirectories); i++) { in.seekSet(dirOffsets[i]); @@ -1596,7 +1682,7 @@ public class TTFFile { readName(in); - log.debug(fullName); + log.info(fullName); fontNames.add(fullName); // Reset names @@ -1667,9 +1753,8 @@ public class TTFFile { * * @param glyphIndex * @return unicode code point - * @throws IOException if glyphIndex not found */ - private Integer glyphToUnicode(int glyphIndex) throws IOException { + private Integer glyphToUnicode(int glyphIndex) { return (Integer) glyphToUnicodeMap.get(new Integer(glyphIndex)); } @@ -1678,7 +1763,6 @@ public class TTFFile { * * @param unicodeIndex unicode code point * @return glyph index - * @throws IOException if unicodeIndex not found */ private Integer unicodeToGlyph(int unicodeIndex) throws IOException { final Integer result @@ -1690,13 +1774,63 @@ public class TTFFile { return result; } + /** + * Determine if advanced (typographic) table is present. + * @return true if advanced (typographic) table is present + */ + public boolean hasAdvancedTable() { + if ( advancedTableReader != null ) { + return advancedTableReader.hasAdvancedTable(); + } else { + return false; + } + } + + /** + * Returns the GDEF table or null if none present. + * @return the GDEF table + */ + public GlyphDefinitionTable getGDEF() { + if ( advancedTableReader != null ) { + return advancedTableReader.getGDEF(); + } else { + return null; + } + } + + /** + * Returns the GSUB table or null if none present. + * @return the GSUB table + */ + public GlyphSubstitutionTable getGSUB() { + if ( advancedTableReader != null ) { + return advancedTableReader.getGSUB(); + } else { + return null; + } + } + + /** + * Returns the GPOS table or null if none present. + * @return the GPOS table + */ + public GlyphPositioningTable getGPOS() { + if ( advancedTableReader != null ) { + return advancedTableReader.getGPOS(); + } else { + return null; + } + } + /** * Static main method to get info about a TrueType font. * @param args The command line arguments */ public static void main(String[] args) { try { - TTFFile ttfFile = new TTFFile(); + boolean useKerning = true; + boolean useAdvanced = true; + TTFFile ttfFile = new TTFFile(useKerning, useAdvanced); FontFileReader reader = new FontFileReader(args[0]); @@ -1713,4 +1847,4 @@ public class TTFFile { ioe.printStackTrace(System.err); } } -} \ No newline at end of file +} diff --git a/src/java/org/apache/fop/fonts/truetype/TTFFontLoader.java b/src/java/org/apache/fop/fonts/truetype/TTFFontLoader.java index f9be8e010..54324be52 100644 --- a/src/java/org/apache/fop/fonts/truetype/TTFFontLoader.java +++ b/src/java/org/apache/fop/fonts/truetype/TTFFontLoader.java @@ -54,7 +54,7 @@ public class TTFFontLoader extends FontLoader { * @param resolver the FontResolver for font URI resolution */ public TTFFontLoader(String fontFileURI, FontResolver resolver) { - this(fontFileURI, null, true, EncodingMode.AUTO, true, resolver); + this(fontFileURI, null, true, EncodingMode.AUTO, true, true, resolver); } /** @@ -65,12 +65,13 @@ public class TTFFontLoader extends FontLoader { * @param embedded indicates whether the font is embedded or referenced * @param encodingMode the requested encoding mode * @param useKerning true to enable loading kerning info if available, false to disable + * @param useAdvanced true to enable loading advanced info if available, false to disable * @param resolver the FontResolver for font URI resolution */ public TTFFontLoader(String fontFileURI, String subFontName, boolean embedded, EncodingMode encodingMode, boolean useKerning, - FontResolver resolver) { - super(fontFileURI, embedded, useKerning, resolver); + boolean useAdvanced, FontResolver resolver) { + super(fontFileURI, embedded, useKerning, useAdvanced, resolver); this.subFontName = subFontName; this.encodingMode = encodingMode; if (this.encodingMode == EncodingMode.AUTO) { @@ -93,7 +94,7 @@ public class TTFFontLoader extends FontLoader { private void read(String ttcFontName) throws IOException { InputStream in = openFontUri(resolver, this.fontFileURI); try { - TTFFile ttf = new TTFFile(); + TTFFile ttf = new TTFFile(useKerning, useAdvanced); FontFileReader reader = new FontFileReader(in); boolean supported = ttf.readFont(reader, ttcFontName); if (!supported) { @@ -169,6 +170,9 @@ public class TTFFontLoader extends FontLoader { if (useKerning) { copyKerning(ttf, isCid); } + if (useAdvanced) { + copyAdvanced(ttf); + } if (this.embedded) { if (ttf.isEmbeddable()) { returnFont.setEmbedFileName(this.fontFileURI); @@ -229,4 +233,17 @@ public class TTFFontLoader extends FontLoader { returnFont.putKerningEntry(kpx1, h2); } } + + /** + * Copy advanced typographic information. + */ + private void copyAdvanced ( TTFFile ttf ) { + if ( returnFont instanceof MultiByteFont ) { + MultiByteFont mbf = (MultiByteFont) returnFont; + mbf.setGDEF ( ttf.getGDEF() ); + mbf.setGSUB ( ttf.getGSUB() ); + mbf.setGPOS ( ttf.getGPOS() ); + } + } + } diff --git a/src/java/org/apache/fop/fonts/truetype/TTFSubSetFile.java b/src/java/org/apache/fop/fonts/truetype/TTFSubSetFile.java index 665cf289d..e081734be 100644 --- a/src/java/org/apache/fop/fonts/truetype/TTFSubSetFile.java +++ b/src/java/org/apache/fop/fonts/truetype/TTFSubSetFile.java @@ -56,6 +56,22 @@ public class TTFSubSetFile extends TTFFile { private int checkSumAdjustmentOffset = 0; private int locaOffset = 0; + /** + * Default Constructor + */ + public TTFSubSetFile() { + this(false, false); + } + + /** + * Constructor + * @param useKerning true if kerning data should be loaded + * @param useAdvanced true if advanced typographic tables should be loaded + */ + public TTFSubSetFile ( boolean useKerning, boolean useAdvanced ) { + super(useKerning, useAdvanced); + } + /** * Initalize the output array */ diff --git a/src/java/org/apache/fop/fonts/type1/Type1FontLoader.java b/src/java/org/apache/fop/fonts/type1/Type1FontLoader.java index 1e93763e8..924f7b0b8 100644 --- a/src/java/org/apache/fop/fonts/type1/Type1FontLoader.java +++ b/src/java/org/apache/fop/fonts/type1/Type1FontLoader.java @@ -52,7 +52,7 @@ public class Type1FontLoader extends FontLoader { */ public Type1FontLoader(String fontFileURI, boolean embedded, boolean useKerning, FontResolver resolver) throws IOException { - super(fontFileURI, embedded, useKerning, resolver); + super(fontFileURI, embedded, useKerning, true, resolver); } private String getPFMURI(String pfbURI) { diff --git a/src/java/org/apache/fop/layoutmgr/AbstractLayoutManager.java b/src/java/org/apache/fop/layoutmgr/AbstractLayoutManager.java index 8e96f3eb1..dd9c34149 100644 --- a/src/java/org/apache/fop/layoutmgr/AbstractLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/AbstractLayoutManager.java @@ -448,7 +448,7 @@ public abstract class AbstractLayoutManager extends AbstractBaseLayoutManager /** {@inheritDoc} */ @Override public String toString() { - return (super.toString() + (fobj != null ? "[fobj=" + fobj.toString() + "]" : "")); + return (super.toString() + (fobj != null ? "{fobj = " + fobj.toString() + "}" : "")); } /** {@inheritDoc} */ diff --git a/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java b/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java index 95b7f8a39..205fac0f2 100644 --- a/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java @@ -349,7 +349,12 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager contentRectOffsetX = 0; contentRectOffsetY = 0; - contentRectOffsetX += fo.getCommonMarginBlock().startIndent.getValue(this); + int level = fo.getBidiLevel(); + if ( ( level < 0 ) || ( ( level & 1 ) == 0 ) ) { + contentRectOffsetX += fo.getCommonMarginBlock().startIndent.getValue(this); + } else { + contentRectOffsetX += fo.getCommonMarginBlock().endIndent.getValue(this); + } contentRectOffsetY += fo.getCommonBorderPaddingBackground().getBorderBeforeWidth(false); contentRectOffsetY += fo.getCommonBorderPaddingBackground().getPaddingBefore(false, this); @@ -834,10 +839,13 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager if (referenceArea == null) { boolean switchedProgressionDirection = blockProgressionDirectionChanges(); boolean allowBPDUpdate = autoHeight && !switchedProgressionDirection; + int level = getBlockContainerFO().getBidiLevel(); viewportBlockArea = new BlockViewport(allowBPDUpdate); viewportBlockArea.addTrait(Trait.IS_VIEWPORT_AREA, Boolean.TRUE); - + if ( level >= 0 ) { + viewportBlockArea.setBidiLevel ( level ); + } viewportBlockArea.setIPD(getContentAreaIPD()); if (allowBPDUpdate) { viewportBlockArea.setBPD(0); @@ -872,6 +880,9 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager referenceArea = new Block(); referenceArea.addTrait(Trait.IS_REFERENCE_AREA, Boolean.TRUE); + if ( level >= 0 ) { + referenceArea.setBidiLevel ( level ); + } TraitSetter.setProducerID(referenceArea, getBlockContainerFO().getId()); if (abProps.absolutePosition == EN_ABSOLUTE) { diff --git a/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java b/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java index ed2ea4ee9..9c3639f93 100644 --- a/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java @@ -359,6 +359,8 @@ public class BlockLayoutManager extends BlockStackingLayoutManager curBlockArea.setIPD(super.getContentAreaIPD()); + curBlockArea.setBidiLevel ( getBlockFO().getBidiLevel() ); + TraitSetter.addBreaks(curBlockArea, getBlockFO().getBreakBefore(), getBlockFO().getBreakAfter()); @@ -503,4 +505,3 @@ public class BlockLayoutManager extends BlockStackingLayoutManager } } - diff --git a/src/java/org/apache/fop/layoutmgr/ExternalDocumentLayoutManager.java b/src/java/org/apache/fop/layoutmgr/ExternalDocumentLayoutManager.java index c4aa1a39b..a46b74e1a 100644 --- a/src/java/org/apache/fop/layoutmgr/ExternalDocumentLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/ExternalDocumentLayoutManager.java @@ -51,6 +51,7 @@ import org.apache.fop.datatypes.URISpecification; import org.apache.fop.fo.Constants; import org.apache.fop.fo.extensions.ExternalDocument; import org.apache.fop.layoutmgr.inline.ImageLayout; +import org.apache.fop.traits.WritingMode; /** * LayoutManager for an external-document extension element. This class is instantiated by @@ -184,12 +185,12 @@ public class ExternalDocumentLayoutManager extends AbstractPageSequenceLayoutMan TraitSetter.setProducerID(imageArea, fobj.getId()); transferForeignAttributes(imageArea); - InlineViewport vp = new InlineViewport(imageArea); + InlineViewport vp = new InlineViewport(imageArea, fobj.getBidiLevel()); TraitSetter.setProducerID(vp, fobj.getId()); vp.setIPD(imageSize.width); vp.setBPD(imageSize.height); vp.setContentPosition(imageLayout.getPlacement()); - vp.setOffset(0); + vp.setBlockProgressionOffset(0); //Link them all together... lineArea.addInlineArea(vp); @@ -230,8 +231,9 @@ public class ExternalDocumentLayoutManager extends AbstractPageSequenceLayoutMan referenceRect = new Rectangle(0, 0, imageSize.height, imageSize.width); } FODimension reldims = new FODimension(0, 0); + // [TBD] BIDI ALERT CTM pageCTM = CTM.getCTMandRelDims(pageSeq.getReferenceOrientation(), - Constants.EN_LR_TB, referenceRect, reldims); + WritingMode.LR_TB, referenceRect, reldims); Page page = new Page(referenceRect, pageNumber, pageNumberString, isBlank); diff --git a/src/java/org/apache/fop/layoutmgr/LayoutContext.java b/src/java/org/apache/fop/layoutmgr/LayoutContext.java index 18059c5ca..a2512c50b 100644 --- a/src/java/org/apache/fop/layoutmgr/LayoutContext.java +++ b/src/java/org/apache/fop/layoutmgr/LayoutContext.java @@ -26,6 +26,7 @@ import org.apache.fop.fo.Constants; import org.apache.fop.layoutmgr.inline.AlignmentContext; import org.apache.fop.layoutmgr.inline.HyphContext; import org.apache.fop.traits.MinOptMax; +import org.apache.fop.traits.WritingMode; /** @@ -92,7 +93,7 @@ public class LayoutContext { //overlap with refIPD. Need to investigate how best to refactor that. /** the writing mode established by the nearest ancestor reference area */ - private int writingMode = Constants.EN_LR_TB; + private WritingMode writingMode = WritingMode.LR_TB; /** Current pending space-after or space-end from preceding area */ private SpaceSpecifier trailingSpace; @@ -564,7 +565,7 @@ public class LayoutContext { * Get the writing mode of the relevant reference area. * @return the applicable writing mode */ - public int getWritingMode() { + public WritingMode getWritingMode() { return writingMode; } @@ -572,7 +573,7 @@ public class LayoutContext { * Set the writing mode. * @param writingMode the writing mode */ - public void setWritingMode(int writingMode) { + public void setWritingMode(WritingMode writingMode) { this.writingMode = writingMode; } diff --git a/src/java/org/apache/fop/layoutmgr/LayoutManagerMapping.java b/src/java/org/apache/fop/layoutmgr/LayoutManagerMapping.java index 2acf67c1f..76a1cb9e4 100644 --- a/src/java/org/apache/fop/layoutmgr/LayoutManagerMapping.java +++ b/src/java/org/apache/fop/layoutmgr/LayoutManagerMapping.java @@ -67,6 +67,7 @@ import org.apache.fop.fo.pagination.SideRegion; import org.apache.fop.fo.pagination.StaticContent; import org.apache.fop.fo.pagination.Title; import org.apache.fop.layoutmgr.inline.BasicLinkLayoutManager; +import org.apache.fop.layoutmgr.inline.BidiLayoutManager; import org.apache.fop.layoutmgr.inline.CharacterLayoutManager; import org.apache.fop.layoutmgr.inline.ContentLayoutManager; import org.apache.fop.layoutmgr.inline.ExternalGraphicLayoutManager; @@ -246,28 +247,9 @@ public class LayoutManagerMapping implements LayoutManagerMaker { public static class BidiOverrideLayoutManagerMaker extends Maker { /** {@inheritDoc} */ public void make(FONode node, List lms) { - /* [GA] remove broken code - if (false) { - // this is broken; it does nothing - // it should make something like an InlineStackingLM - super.make(node, lms); - } else { - ArrayList childList = new ArrayList(); - // this is broken; it does nothing - // it should make something like an InlineStackingLM - super.make(node, childList); - for (int count = childList.size() - 1; count >= 0; count--) { - LayoutManager lm = (LayoutManager) childList.get(count); - if (lm instanceof InlineLevelLayoutManager) { - LayoutManager blm = new BidiLayoutManager - ((BidiOverride) node, (InlineLayoutManager) lm); - lms.add(blm); - } else { - lms.add(lm); - } - } + if ( node instanceof BidiOverride ) { + lms.add(new BidiLayoutManager((BidiOverride) node)); } - */ } } diff --git a/src/java/org/apache/fop/layoutmgr/PageProvider.java b/src/java/org/apache/fop/layoutmgr/PageProvider.java index 364839f8a..a668b044b 100644 --- a/src/java/org/apache/fop/layoutmgr/PageProvider.java +++ b/src/java/org/apache/fop/layoutmgr/PageProvider.java @@ -335,6 +335,7 @@ public class PageProvider implements Constants { //Set unique key obtained from the AreaTreeHandler page.getPageViewport().setKey(areaTreeHandler.generatePageViewportKey()); page.getPageViewport().setForeignAttributes(spm.getForeignAttributes()); + page.getPageViewport().setWritingModeTraits(pageSeq); cachedPages.add(page); return page; } diff --git a/src/java/org/apache/fop/layoutmgr/PageSequenceLayoutManager.java b/src/java/org/apache/fop/layoutmgr/PageSequenceLayoutManager.java index 1b2b5d7c5..8ad124c27 100644 --- a/src/java/org/apache/fop/layoutmgr/PageSequenceLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/PageSequenceLayoutManager.java @@ -25,6 +25,7 @@ import org.apache.commons.logging.LogFactory; import org.apache.fop.area.AreaTreeHandler; import org.apache.fop.area.AreaTreeModel; import org.apache.fop.area.LineArea; +import org.apache.fop.complexscripts.bidi.BidiResolver; import org.apache.fop.fo.Constants; import org.apache.fop.fo.pagination.PageSequence; import org.apache.fop.fo.pagination.PageSequenceMaster; @@ -78,8 +79,12 @@ public class PageSequenceLayoutManager extends AbstractPageSequenceLayoutManager public void activateLayout() { initialize(); - LineArea title = null; + // perform step 5.8 of refinement process (Unicode BIDI Processing) + if ( areaTreeHandler.isComplexScriptFeaturesEnabled() ) { + BidiResolver.resolveInlineDirectionality(getPageSequence()); + } + LineArea title = null; if (getPageSequence().getTitleFO() != null) { try { ContentLayoutManager clm = getLayoutManagerMaker(). diff --git a/src/java/org/apache/fop/layoutmgr/inline/AbstractGraphicsLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/AbstractGraphicsLayoutManager.java index 8c797a48c..a7bc78be8 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/AbstractGraphicsLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/AbstractGraphicsLayoutManager.java @@ -59,6 +59,7 @@ public abstract class AbstractGraphicsLayoutManager extends LeafNodeLayoutManage Dimension intrinsicSize = new Dimension( fobj.getIntrinsicWidth(), fobj.getIntrinsicHeight()); + int bidiLevel = fobj.getBidiLevel(); //TODO Investigate if the line-height property has to be taken into the calculation //somehow. There was some code here that hints in this direction but it was disabled. @@ -67,6 +68,7 @@ public abstract class AbstractGraphicsLayoutManager extends LeafNodeLayoutManage Rectangle placement = imageLayout.getPlacement(); CommonBorderPaddingBackground borderProps = fobj.getCommonBorderPaddingBackground(); + setCommonBorderPaddingBackground(borderProps); //Determine extra BPD from borders and padding int beforeBPD = borderProps.getPadding(CommonBorderPaddingBackground.BEFORE, false, this); @@ -75,30 +77,35 @@ public abstract class AbstractGraphicsLayoutManager extends LeafNodeLayoutManage placement.y += beforeBPD; //Determine extra IPD from borders and padding - int startIPD = borderProps.getPadding(CommonBorderPaddingBackground.START, false, this); - startIPD += borderProps.getBorderWidth(CommonBorderPaddingBackground.START, false); - - placement.x += startIPD; + if ( ( bidiLevel == -1 ) || ( ( bidiLevel & 1 ) == 0 ) ) { + int startIPD = borderProps.getPadding(CommonBorderPaddingBackground.START, false, this); + startIPD += borderProps.getBorderWidth(CommonBorderPaddingBackground.START, false); + placement.x += startIPD; + } else { + int endIPD = borderProps.getPadding(CommonBorderPaddingBackground.END, false, this); + endIPD += borderProps.getBorderWidth(CommonBorderPaddingBackground.END, false); + placement.x += endIPD; + } Area viewportArea = getChildArea(); TraitSetter.setProducerID(viewportArea, fobj.getId()); transferForeignAttributes(viewportArea); - InlineViewport vp = new InlineViewport(viewportArea); + InlineViewport vp = new InlineViewport(viewportArea, bidiLevel); TraitSetter.addStructureTreeElement(vp, fobj.getStructureTreeElement()); TraitSetter.setProducerID(vp, fobj.getId()); vp.setIPD(imageLayout.getViewportSize().width); vp.setBPD(imageLayout.getViewportSize().height); vp.setContentPosition(placement); vp.setClip(imageLayout.isClipped()); - vp.setOffset(0); + vp.setBlockProgressionOffset(0); // Common Border, Padding, and Background Properties - TraitSetter.addBorders(vp, fobj.getCommonBorderPaddingBackground() + TraitSetter.addBorders(vp, borderProps , false, false, false, false, this); - TraitSetter.addPadding(vp, fobj.getCommonBorderPaddingBackground() + TraitSetter.addPadding(vp, borderProps , false, false, false, false, this); - TraitSetter.addBackground(vp, fobj.getCommonBorderPaddingBackground(), this); + TraitSetter.addBackground(vp, borderProps, this); return vp; } diff --git a/src/java/org/apache/fop/layoutmgr/inline/AbstractPageNumberCitationLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/AbstractPageNumberCitationLayoutManager.java index 8c769924a..aba137115 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/AbstractPageNumberCitationLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/AbstractPageNumberCitationLayoutManager.java @@ -81,10 +81,7 @@ public abstract class AbstractPageNumberCitationLayoutManager extends LeafNodeLa } /** {@inheritDoc} */ - public InlineArea get(LayoutContext context) { - curArea = getPageNumberCitationInlineArea(); - return curArea; - } + public abstract InlineArea get(LayoutContext context); /** * {@inheritDoc} @@ -97,35 +94,6 @@ public abstract class AbstractPageNumberCitationLayoutManager extends LeafNodeLa } } - /** - * If id can be resolved then simply return a text area, otherwise - * return a resolvable area - * - * @return a corresponding InlineArea - */ - private InlineArea getPageNumberCitationInlineArea() { - PageViewport page = getPSLM().getFirstPVWithID(fobj.getRefId()); - TextArea text; - if (page != null) { - String str = page.getPageNumberString(); - // get page string from parent, build area - text = new TextArea(); - int width = getStringWidth(str); - text.addWord(str, 0); - text.setIPD(width); - resolved = true; - } else { - resolved = false; - text = new UnresolvedPageNumber(fobj.getRefId(), font); - String str = "MMM"; // reserve three spaces for page number - int width = getStringWidth(str); - text.setIPD(width); - } - updateTextAreaTraits(text); - - return text; - } - /** * Updates the traits for the generated text area. * @param text the text area @@ -152,5 +120,12 @@ public abstract class AbstractPageNumberCitationLayoutManager extends LeafNodeLa return width; } + /** + * @return bidi level governing abstract page number citation + */ + protected int getBidiLevel() { + return fobj.getBidiLevel(); + } + } diff --git a/src/java/org/apache/fop/layoutmgr/inline/AlignmentContext.java b/src/java/org/apache/fop/layoutmgr/inline/AlignmentContext.java index daf7ce01d..eb199da9d 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/AlignmentContext.java +++ b/src/java/org/apache/fop/layoutmgr/inline/AlignmentContext.java @@ -24,6 +24,7 @@ import org.apache.fop.datatypes.LengthBase; import org.apache.fop.datatypes.SimplePercentBaseContext; import org.apache.fop.fo.Constants; import org.apache.fop.fonts.Font; +import org.apache.fop.traits.WritingMode; /** * The alignment context is carried within a LayoutContext and as @@ -173,7 +174,7 @@ public class AlignmentContext implements Constants { * @param lineHeight the computed value of the lineHeight property * @param writingMode the current writing mode */ - AlignmentContext(Font font, int lineHeight, int writingMode) { + AlignmentContext(Font font, int lineHeight, WritingMode writingMode) { this.areaHeight = font.getAscender() - font.getDescender(); this.lineHeight = lineHeight; this.xHeight = font.getXHeight(); @@ -298,6 +299,14 @@ public class AlignmentContext implements Constants { return actualBaselineTable.getDominantBaselineIdentifier(); } + /** + * Return the writing mode. + * @return the writing mode + */ +/* public WritingMode getWritingMode() { + return scaledBaselineTable.getWritingMode(); + }*/ + /** * Calculates the baseline shift value based on the baseline-shift * property value. @@ -504,6 +513,10 @@ public class AlignmentContext implements Constants { && parentAlignmentContext.usesInitialBaselineTable()); } + /* private boolean isHorizontalWritingMode() { + return (getWritingMode() == WritingMode.LR_TB || getWritingMode() == WritingMode.RL_TB); + }*/ + /** {@inheritDoc} */ public String toString() { StringBuffer sb = new StringBuffer(64); diff --git a/src/java/org/apache/fop/layoutmgr/inline/BasicLinkLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/BasicLinkLayoutManager.java index 1390c04d8..593003d55 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/BasicLinkLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/BasicLinkLayoutManager.java @@ -69,6 +69,12 @@ public class BasicLinkLayoutManager extends InlineLayoutManager { res.resolveIDRef(idref, pslm.getFirstPVWithID(idref)); if (!res.isResolved()) { pslm.addUnresolvedArea(idref, res); + if ( area instanceof BasicLinkArea ) { + // establish back-pointer from BasicLinkArea to LinkResolver to + // handle inline area unflattening during line bidi reordering; + // needed to create internal link trait on synthesized basic link area + ((BasicLinkArea)area).setResolver(res); + } } } else if (fobj.hasExternalDestination()) { String url = URISpecification.getURL(fobj.getExternalDestination()); diff --git a/src/java/org/apache/fop/layoutmgr/inline/BidiLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/BidiLayoutManager.java index f342399fc..b6145f025 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/BidiLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/BidiLayoutManager.java @@ -19,56 +19,19 @@ package org.apache.fop.layoutmgr.inline; -import java.util.ArrayList; -import java.util.List; - -import org.apache.fop.area.inline.InlineArea; import org.apache.fop.fo.flow.BidiOverride; - /** - * If this bidi has a different writing mode direction - * ltr or rtl than its parent writing mode then this - * reverses the inline areas (at the character level). + * Layout manager for fo:bidi-override. */ -public class BidiLayoutManager extends LeafNodeLayoutManager { - - private List children; +public class BidiLayoutManager extends InlineLayoutManager { /** * Construct bidi layout manager. - * @param node bidi override FO - * @param cLM parent layout manager + * @param node an BidiOverride FONode */ - public BidiLayoutManager(BidiOverride node, InlineLayoutManager cLM) { + public BidiLayoutManager(BidiOverride node) { super(node); - setParent(cLM); - children = new ArrayList(); -/* - for (int count = cLM.size() - 1; count >= 0; count--) { - InlineArea ia = cLM.get(count); - if (ia instanceof Word) { - // reverse word - Word word = (Word) ia; - StringBuffer sb = new StringBuffer(word.getWord()); - word.setWord(sb.reverse().toString()); - } - children.add(ia); - } -*/ - } - - /** @return number of children */ - public int size() { - return children.size(); - } - - /** - * @param index of child inline area - * @return a child inline area - */ - public InlineArea get(int index) { - return (InlineArea) children.get(index); } } diff --git a/src/java/org/apache/fop/layoutmgr/inline/CharacterLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/CharacterLayoutManager.java index 4877ff9bd..32d4d1004 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/CharacterLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/CharacterLayoutManager.java @@ -77,13 +77,18 @@ public class CharacterLayoutManager extends LeafNodeLayoutManager { private TextArea getCharacterInlineArea(Character node) { TextArea text = new TextArea(); char ch = node.getCharacter(); + int ipd = font.getCharWidth(ch); + int blockProgressionOffset = 0; + int level = node.getBidiLevel(); if (CharUtilities.isAnySpace(ch)) { // add space unless it's zero-width: if (!CharUtilities.isZeroWidthSpace(ch)) { - text.addSpace(ch, 0, CharUtilities.isAdjustableSpace(ch)); + text.addSpace(ch, ipd, CharUtilities.isAdjustableSpace(ch), + blockProgressionOffset, level); } } else { - text.addWord(String.valueOf(ch), 0); + int[] levels = ( level >= 0 ) ? new int[] {level} : null; + text.addWord(String.valueOf(ch), ipd, null, levels, null, blockProgressionOffset); } TraitSetter.setProducerID(text, node.getId()); TraitSetter.addTextDecoration(text, node.getTextDecoration()); @@ -105,9 +110,8 @@ public class CharacterLayoutManager extends LeafNodeLayoutManager { Character fobj = (Character)this.fobj; - ipd = MinOptMax.getInstance(font.getCharWidth(fobj.getCharacter())); + ipd = MinOptMax.getInstance(curArea.getIPD()); - curArea.setIPD(ipd.getOpt()); curArea.setBPD(font.getAscender() - font.getDescender()); TraitSetter.addFontTraits(curArea, font); @@ -227,4 +231,3 @@ public class CharacterLayoutManager extends LeafNodeLayoutManager { } } - diff --git a/src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java index ede078066..1eb91e0ab 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java @@ -207,7 +207,7 @@ public class InlineLayoutManager extends InlineStackingLayoutManager { InlineArea area; if (isInline) { area = createInlineParent(); - area.setOffset(0); + area.setBlockProgressionOffset(0); } else { area = new InlineBlockParent(); } @@ -482,12 +482,12 @@ public class InlineLayoutManager extends InlineStackingLayoutManager { || lastLM instanceof InlineLevelLayoutManager); parent.setBPD(alignmentContext.getHeight()); if (parent instanceof InlineParent) { - parent.setOffset(alignmentContext.getOffset()); + parent.setBlockProgressionOffset(alignmentContext.getOffset()); } else if (parent instanceof InlineBlockParent) { // All inline elements are positioned by the renderers relative to // the before edge of their content rectangle if (borderProps != null) { - parent.setOffset(borderProps.getPaddingBefore(false, this) + parent.setBlockProgressionOffset(borderProps.getPaddingBefore(false, this) + borderProps.getBorderBeforeWidth(false)); } } diff --git a/src/java/org/apache/fop/layoutmgr/inline/InlineStackingLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/InlineStackingLayoutManager.java index b15f0f8db..4a203d55e 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/InlineStackingLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/InlineStackingLayoutManager.java @@ -180,6 +180,10 @@ public abstract class InlineStackingLayoutManager extends AbstractLayoutManager //getLogger().debug("Add leading space: " + iAdjust); Space ls = new Space(); ls.setIPD(iAdjust); + int level = parentArea.getBidiLevel(); + if ( level >= 0 ) { + ls.setBidiLevel ( level ); + } parentArea.addChildArea(ls); } } diff --git a/src/java/org/apache/fop/layoutmgr/inline/LeaderLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/LeaderLayoutManager.java index 2a58b2018..b3d3218ab 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/LeaderLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/LeaderLayoutManager.java @@ -115,7 +115,7 @@ public class LeaderLayoutManager extends LeafNodeLayoutManager { private InlineArea getLeaderInlineArea(LayoutContext context) { InlineArea leaderArea = null; - + int level = fobj.getBidiLevel(); if (fobj.getLeaderPattern() == EN_RULE) { if (fobj.getRuleStyle() != EN_NONE) { org.apache.fop.area.inline.Leader leader @@ -125,28 +125,41 @@ public class LeaderLayoutManager extends LeafNodeLayoutManager { leaderArea = leader; } else { leaderArea = new Space(); + if ( level >= 0 ) { + leaderArea.setBidiLevel ( level ); + } } leaderArea.setBPD(fobj.getRuleThickness().getValue(this)); leaderArea.addTrait(Trait.COLOR, fobj.getColor()); + if ( level >= 0 ) { + leaderArea.setBidiLevel ( level ); + } } else if (fobj.getLeaderPattern() == EN_SPACE) { leaderArea = new Space(); leaderArea.setBPD(fobj.getRuleThickness().getValue(this)); + if ( level >= 0 ) { + leaderArea.setBidiLevel ( level ); + } } else if (fobj.getLeaderPattern() == EN_DOTS) { TextArea t = new TextArea(); char dot = '.'; // userAgent.getLeaderDotCharacter(); - int width = font.getCharWidth(dot); - t.addWord("" + dot, 0); + int[] levels = ( level < 0 ) ? null : new int[] {level}; + t.addWord("" + dot, width, null, levels, null, 0); t.setIPD(width); t.setBPD(width); t.setBaselineOffset(width); TraitSetter.addFontTraits(t, font); t.addTrait(Trait.COLOR, fobj.getColor()); Space spacer = null; - if (fobj.getLeaderPatternWidth().getValue(this) > width) { + int widthLeaderPattern = fobj.getLeaderPatternWidth().getValue(this); + if (widthLeaderPattern > width) { spacer = new Space(); - spacer.setIPD(fobj.getLeaderPatternWidth().getValue(this) - width); - width = fobj.getLeaderPatternWidth().getValue(this); + spacer.setIPD(widthLeaderPattern - width); + if ( level >= 0 ) { + spacer.setBidiLevel ( level ); + } + width = widthLeaderPattern; } FilledArea fa = new FilledArea(); fa.setUnitWidth(width); @@ -155,7 +168,6 @@ public class LeaderLayoutManager extends LeafNodeLayoutManager { fa.addChildArea(spacer); } fa.setBPD(t.getBPD()); - leaderArea = fa; } else if (fobj.getLeaderPattern() == EN_USECONTENT) { if (fobj.getChildNodes() == null) { @@ -188,6 +200,9 @@ public class LeaderLayoutManager extends LeafNodeLayoutManager { if (fobj.getLeaderPatternWidth().getValue(this) > width) { spacer = new Space(); spacer.setIPD(fobj.getLeaderPatternWidth().getValue(this) - width); + if ( level >= 0 ) { + spacer.setBidiLevel ( level ); + } width = fobj.getLeaderPatternWidth().getValue(this); } fa.setUnitWidth(width); @@ -199,6 +214,7 @@ public class LeaderLayoutManager extends LeafNodeLayoutManager { //Content collapsed to nothing, so use a space leaderArea = new Space(); leaderArea.setBPD(fobj.getRuleThickness().getValue(this)); + leaderArea.setBidiLevel ( fobj.getBidiLevelRecursive() ); } } TraitSetter.setProducerID(leaderArea, fobj.getId()); diff --git a/src/java/org/apache/fop/layoutmgr/inline/LeafNodeLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/LeafNodeLayoutManager.java index 5e3464da7..c7205905b 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/LeafNodeLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/LeafNodeLayoutManager.java @@ -224,7 +224,7 @@ public abstract class LeafNodeLayoutManager extends AbstractLayoutManager * @param context the layout context used for adding the area */ protected void offsetArea(InlineArea area, LayoutContext context) { - area.setOffset(alignmentContext.getOffset()); + area.setBlockProgressionOffset(alignmentContext.getOffset()); } /** diff --git a/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java index db7d1edc8..f57b9367a 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java @@ -32,6 +32,7 @@ import org.apache.fop.area.Area; import org.apache.fop.area.LineArea; import org.apache.fop.area.Trait; import org.apache.fop.area.inline.InlineArea; +import org.apache.fop.complexscripts.bidi.BidiResolver; import org.apache.fop.datatypes.Length; import org.apache.fop.datatypes.Numeric; import org.apache.fop.fo.Constants; @@ -111,6 +112,7 @@ public class LineLayoutManager extends InlineStackingLayoutManager private final double dAdjust; // Percentage to adjust (stretch or shrink) private final double ipdAdjust; // Percentage to adjust (stretch or shrink) private final int startIndent; + private final int endIndent; private final int lineHeight; private final int lineWidth; private final int spaceBefore; @@ -119,8 +121,8 @@ public class LineLayoutManager extends InlineStackingLayoutManager LineBreakPosition( // CSOK: ParameterNumber LayoutManager lm, int index, int startIndex, int breakIndex, - int shrink, int stretch, int diff, double ipdA, double adjust, int ind, - int lh, int lw, int sb, int sa, int bl) { + int shrink, int stretch, int diff, double ipdA, double adjust, int si, + int ei, int lh, int lw, int sb, int sa, int bl) { super(lm, breakIndex); availableShrink = shrink; availableStretch = stretch; @@ -129,7 +131,8 @@ public class LineLayoutManager extends InlineStackingLayoutManager this.startIndex = startIndex; ipdAdjust = ipdA; dAdjust = adjust; - startIndent = ind; + startIndent = si; + endIndent = ei; lineHeight = lh; lineWidth = lw; spaceBefore = sb; @@ -140,6 +143,7 @@ public class LineLayoutManager extends InlineStackingLayoutManager } + private int bidiLevel = -1; private int textAlignment = EN_JUSTIFY; private int textAlignmentLast; private int effectiveAlignment; @@ -333,13 +337,38 @@ public class LineLayoutManager extends InlineStackingLayoutManager int total) { // compute indent and adjustment ratio, according to // the value of text-align and text-align-last - int indent = 0; + int startIndent; + int endIndent; int difference = bestActiveNode.difference; int textAlign = (bestActiveNode.line < total) ? alignment : alignmentLast; - indent += (textAlign == Constants.EN_CENTER) + + switch ( textAlign ) { + case Constants.EN_START: + startIndent = 0; + endIndent = difference > 0 ? difference : 0; + break; + case Constants.EN_END: + startIndent = difference > 0 ? difference : 0; + endIndent = 0; + break; + case Constants.EN_CENTER: + startIndent = difference / 2; + endIndent = startIndent; + break; + default: + case Constants.EN_JUSTIFY: + startIndent = 0; + endIndent = 0; + break; + } + + /* + startIndent += (textAlign == Constants.EN_CENTER) ? difference / 2 : (textAlign == Constants.EN_END) ? difference : 0; - indent += (bestActiveNode.line == 1 && indentFirstPart && isFirstInBlock) + */ + startIndent += (bestActiveNode.line == 1 && indentFirstPart && isFirstInBlock) ? textIndent : 0; + double ratio = (textAlign == Constants.EN_JUSTIFY || difference < 0 && -difference <= bestActiveNode.availableShrink) ? bestActiveNode.adjustRatio : 0; @@ -377,7 +406,7 @@ public class LineLayoutManager extends InlineStackingLayoutManager bestActiveNode.availableShrink - (addedPositions > 0 ? 0 : ((Paragraph) par).lineFiller.getShrink()), bestActiveNode.availableStretch, - difference, ratio, indent), activePossibility); + difference, ratio, startIndent, endIndent), activePossibility); addedPositions++; } @@ -389,7 +418,8 @@ public class LineLayoutManager extends InlineStackingLayoutManager private LineBreakPosition makeLineBreakPosition( // CSOK: ParameterNumber KnuthSequence par, int firstElementIndex, int lastElementIndex, int availableShrink, - int availableStretch, int difference, double ratio, int indent) { + int availableStretch, int difference, double ratio, int startIndent, + int endIndent) { // line height calculation - spaceBefore may differ from spaceAfter // by 1mpt due to rounding int spaceBefore = (lineHeight - lead - follow) / 2; @@ -456,14 +486,14 @@ public class LineLayoutManager extends InlineStackingLayoutManager knuthParagraphs.indexOf(par), firstElementIndex, lastElementIndex, availableShrink, availableStretch, - difference, ratio, 0, indent, + difference, ratio, 0, startIndent, endIndent, 0, ipd, 0, 0, 0); } else { return new LineBreakPosition(thisLLM, knuthParagraphs.indexOf(par), firstElementIndex, lastElementIndex, availableShrink, availableStretch, - difference, ratio, 0, indent, + difference, ratio, 0, startIndent, endIndent, lineLead + lineFollow, ipd, spaceBefore, spaceAfter, lineLead); @@ -544,6 +574,7 @@ public class LineLayoutManager extends InlineStackingLayoutManager /** {@inheritDoc} */ @Override public void initialize() { + bidiLevel = fobj.getBidiLevel(); textAlignment = fobj.getTextAlign(); textAlignmentLast = fobj.getTextAlignLast(); textIndent = fobj.getTextIndent(); @@ -1429,8 +1460,12 @@ public class LineLayoutManager extends InlineStackingLayoutManager if (lbp.startIndent != 0) { lineArea.addTrait(Trait.START_INDENT, lbp.startIndent); } + if (lbp.endIndent != 0) { + lineArea.addTrait(Trait.END_INDENT, new Integer(lbp.endIndent)); + } lineArea.setBPD(lbp.lineHeight); lineArea.setIPD(lbp.lineWidth); + lineArea.setBidiLevel(bidiLevel); lineArea.addTrait(Trait.SPACE_BEFORE, lbp.spaceBefore); lineArea.addTrait(Trait.SPACE_AFTER, lbp.spaceAfter); alignmentContext.resizeLine(lbp.lineHeight, lbp.baseline); @@ -1506,7 +1541,10 @@ public class LineLayoutManager extends InlineStackingLayoutManager && (!context.isLastArea() || !isLastPosition)) { lineArea.setBPD(lineArea.getBPD() + context.getSpaceAfter()); } - lineArea.finalise(); + lineArea.finish(); + if ( lineArea.getBidiLevel() >= 0 ) { + BidiResolver.reorder ( lineArea ); + } parentLayoutManager.addChildArea(lineArea); } @@ -1556,6 +1594,9 @@ public class LineLayoutManager extends InlineStackingLayoutManager blocklc.setTrailingSpace(new SpaceSpecifier(false)); } lineArea.updateExtentsFromChildren(); + if ( lineArea.getBidiLevel() >= 0 ) { + BidiResolver.reorder ( lineArea ); + } parentLayoutManager.addChildArea(lineArea); } diff --git a/src/java/org/apache/fop/layoutmgr/inline/PageNumberCitationLastLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/PageNumberCitationLastLayoutManager.java index 56bcdaa3b..b1ba38565 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/PageNumberCitationLastLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/PageNumberCitationLastLayoutManager.java @@ -56,22 +56,24 @@ public class PageNumberCitationLastLayoutManager extends AbstractPageNumberCitat */ private InlineArea getPageNumberCitationLastInlineArea(LayoutManager parentLM) { TextArea text = null; - resolved = false; + int level = getBidiLevel(); if (!getPSLM().associateLayoutManagerID(fobj.getRefId())) { text = new UnresolvedPageNumber(fobj.getRefId(), font, UnresolvedPageNumber.LAST); getPSLM().addUnresolvedArea(fobj.getRefId(), (Resolvable)text); String str = "MMM"; // reserve three spaces for page number int width = getStringWidth(str); + text.setBidiLevel(level); text.setIPD(width); + resolved = false; } else { PageViewport page = getPSLM().getLastPVWithID(fobj.getRefId()); String str = page.getPageNumberString(); // get page string from parent, build area text = new TextArea(); int width = getStringWidth(str); - text.addWord(str, 0); + text.setBidiLevel(level); + text.addWord(str, 0, level); text.setIPD(width); - resolved = true; } diff --git a/src/java/org/apache/fop/layoutmgr/inline/PageNumberCitationLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/PageNumberCitationLayoutManager.java index 958a854ac..16ce09ec5 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/PageNumberCitationLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/PageNumberCitationLayoutManager.java @@ -50,27 +50,32 @@ public class PageNumberCitationLayoutManager extends AbstractPageNumberCitationL /** * if id can be resolved then simply return a word, otherwise * return a resolvable area + * + * TODO: [GA] May need to run bidi algorithm and script processor + * on resolved page number. */ private InlineArea getPageNumberCitationInlineArea() { PageViewport page = getPSLM().getFirstPVWithID(fobj.getRefId()); TextArea text = null; + int level = getBidiLevel(); if (page != null) { String str = page.getPageNumberString(); // get page string from parent, build area text = new TextArea(); - int width = getStringWidth(str); - text.addWord(str, 0); - text.setIPD(width); + int width = getStringWidth(str); // TODO: [GA] !I18N! + text.setBidiLevel(level); + text.addWord(str, 0, level); + text.setIPD(width); // TODO: [GA] !I18N! resolved = true; } else { - resolved = false; text = new UnresolvedPageNumber(fobj.getRefId(), font); String str = "MMM"; // reserve three spaces for page number - int width = getStringWidth(str); - text.setIPD(width); + int width = getStringWidth(str); // TODO: [GA] !I18N! + text.setBidiLevel(level); + text.setIPD(width); // TODO: [GA] !I18N! + resolved = false; } updateTextAreaTraits(text); - return text; } diff --git a/src/java/org/apache/fop/layoutmgr/inline/PageNumberLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/PageNumberLayoutManager.java index 4b7289b37..c3ee5af32 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/PageNumberLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/PageNumberLayoutManager.java @@ -101,7 +101,7 @@ public class PageNumberLayoutManager extends LeafNodeLayoutManager { TraitSetter.setProducerID(ta, fobj.getId()); ta.setIPD(baseArea.getIPD()); ta.setBPD(baseArea.getBPD()); - ta.setOffset(baseArea.getOffset()); + ta.setBlockProgressionOffset(baseArea.getBlockProgressionOffset()); ta.setBaselineOffset(baseArea.getBaselineOffset()); ta.addTrait(Trait.COLOR, fobj.getColor()); //only to initialize the trait map ta.getTraits().putAll(baseArea.getTraits()); diff --git a/src/java/org/apache/fop/layoutmgr/inline/ScaledBaselineTable.java b/src/java/org/apache/fop/layoutmgr/inline/ScaledBaselineTable.java index d5d3e5edb..1ccba23d7 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/ScaledBaselineTable.java +++ b/src/java/org/apache/fop/layoutmgr/inline/ScaledBaselineTable.java @@ -20,6 +20,7 @@ package org.apache.fop.layoutmgr.inline; import org.apache.fop.fo.Constants; +import org.apache.fop.traits.WritingMode; /** @@ -43,7 +44,7 @@ final class ScaledBaselineTable { private final int dominantBaselineIdentifier; - private final int writingMode; + private final WritingMode writingMode; private final int dominantBaselineOffset; @@ -66,7 +67,7 @@ final class ScaledBaselineTable { int depth, int xHeight, int dominantBaselineIdentifier, - int writingMode) { + WritingMode writingMode) { this.altitude = altitude; this.depth = depth; this.xHeight = xHeight; @@ -89,7 +90,7 @@ final class ScaledBaselineTable { * Return the writing mode for this baseline table. * @return the writing mode */ - int getWritingMode() { + WritingMode getWritingMode() { return this.writingMode; } @@ -139,7 +140,7 @@ final class ScaledBaselineTable { } private boolean isHorizontalWritingMode() { - return writingMode == Constants.EN_LR_TB || writingMode == Constants.EN_RL_TB; + return writingMode.isHorizontal(); } /** diff --git a/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java index 8767fe296..c63c65277 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java @@ -19,6 +19,7 @@ package org.apache.fop.layoutmgr.inline; +import java.util.Arrays; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; @@ -29,6 +30,8 @@ import org.apache.commons.logging.LogFactory; import org.apache.fop.area.Trait; import org.apache.fop.area.inline.TextArea; +import org.apache.fop.complexscripts.fonts.GlyphPositioningTable; +import org.apache.fop.complexscripts.util.CharScript; import org.apache.fop.fo.Constants; import org.apache.fop.fo.FOText; import org.apache.fop.fonts.Font; @@ -71,6 +74,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { private final int startIndex; private final int breakIndex; + private int wordCharLength; private final int wordSpaceCount; private int letterSpaceCount; private MinOptMax areaIPD; @@ -78,14 +82,17 @@ public class TextLayoutManager extends LeafNodeLayoutManager { private final boolean isSpace; private boolean breakOppAfter; private final Font font; + private final int level; + private final int[][] gposAdjustments; - AreaInfo( // CSOK: ParameterNumber - int startIndex, int breakIndex, int wordSpaceCount, int letterSpaceCount, - MinOptMax areaIPD, boolean isHyphenated, boolean isSpace, boolean breakOppAfter, - Font font) { + AreaInfo // CSOK: ParameterNumber + (int startIndex, int breakIndex, int wordSpaceCount, int letterSpaceCount, + MinOptMax areaIPD, boolean isHyphenated, boolean isSpace, boolean breakOppAfter, + Font font, int level, int[][] gposAdjustments) { assert startIndex <= breakIndex; this.startIndex = startIndex; this.breakIndex = breakIndex; + this.wordCharLength = -1; this.wordSpaceCount = wordSpaceCount; this.letterSpaceCount = letterSpaceCount; this.areaIPD = areaIPD; @@ -93,10 +100,26 @@ public class TextLayoutManager extends LeafNodeLayoutManager { this.isSpace = isSpace; this.breakOppAfter = breakOppAfter; this.font = font; + this.level = level; + this.gposAdjustments = gposAdjustments; } - private int getCharLength() { - return breakIndex - startIndex; + /** + * Obtain number of 'characters' contained in word. If word + * is mapped, then this number may be less than or greater than the + * original length (breakIndex - startIndex). We compute and + * memoize thius length upon first invocation of this method. + */ + private int getWordLength() { + if ( wordCharLength == -1 ) { + if ( foText.hasMapping ( startIndex, breakIndex ) ) { + wordCharLength = foText.getMapping ( startIndex, breakIndex ).length(); + } else { + assert breakIndex >= startIndex; + wordCharLength = breakIndex - startIndex; + } + } + return wordCharLength; } private void addToAreaIPD(MinOptMax idp) { @@ -104,16 +127,16 @@ public class TextLayoutManager extends LeafNodeLayoutManager { } public String toString() { - return "AreaInfo[" - + "letterSpaceCount = " + letterSpaceCount - + ", wordSpaceCount = " + wordSpaceCount + return super.toString() + "{" + + "interval = [" + startIndex + "," + breakIndex + "]" + + ", isSpace = " + isSpace + + ", level = " + level + ", areaIPD = " + areaIPD - + ", startIndex = " + startIndex - + ", breakIndex = " + breakIndex + + ", letterSpaceCount = " + letterSpaceCount + + ", wordSpaceCount = " + wordSpaceCount + ", isHyphenated = " + isHyphenated - + ", isSpace = " + isSpace + ", font = " + font - + "]"; + + "}"; } } @@ -149,7 +172,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { * be used to influence the start position of the first letter. The entry i+1 defines the * cursor advancement after the character i. A null entry means no special advancement. */ - private final MinOptMax[] letterAdjustArray; //size = textArray.length + 1 + private final MinOptMax[] letterSpaceAdjustArray; //size = textArray.length + 1 /** Font used for the space between words. */ private Font spaceFont = null; @@ -192,7 +215,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { */ public TextLayoutManager(FOText node) { foText = node; - letterAdjustArray = new MinOptMax[node.length() + 1]; + letterSpaceAdjustArray = new MinOptMax[node.length() + 1]; areaInfos = new ArrayList(); } @@ -269,7 +292,9 @@ public class TextLayoutManager extends LeafNodeLayoutManager { } if (tbpNext.getLeafPos() != -1) { areaInfo = (AreaInfo) areaInfos.get(tbpNext.getLeafPos()); - if (lastAreaInfo == null || areaInfo.font != lastAreaInfo.font) { + if (lastAreaInfo == null + || ( areaInfo.font != lastAreaInfo.font ) + || ( areaInfo.level != lastAreaInfo.level ) ) { if (lastAreaInfo != null) { addAreaInfoAreas(lastAreaInfo, wordSpaceCount, letterSpaceCount, firstAreaInfoIndex, @@ -291,6 +316,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { addAreaInfoAreas(lastAreaInfo, wordSpaceCount, letterSpaceCount, firstAreaInfoIndex, lastAreaInfoIndex, realWidth, context); } + } private void addAreaInfoAreas(AreaInfo areaInfo, int wordSpaceCount, int letterSpaceCount, @@ -301,7 +327,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { // changes. However, it seems as if they should use the AreaInfo from // firstAreaInfoIndex.. lastAreaInfoIndex rather than just the last areaInfo. // This needs to be checked. - int textLength = areaInfo.getCharLength(); + int textLength = areaInfo.getWordLength(); if (areaInfo.letterSpaceCount == textLength && !areaInfo.isHyphenated && context.isLastArea()) { // the line ends at a character like "/" or "-"; @@ -311,8 +337,8 @@ public class TextLayoutManager extends LeafNodeLayoutManager { } for (int i = areaInfo.startIndex; i < areaInfo.breakIndex; i++) { - MinOptMax letterAdjustment = letterAdjustArray[i + 1]; - if (letterAdjustment != null && letterAdjustment.isElastic()) { + MinOptMax letterSpaceAdjustment = letterSpaceAdjustArray[i + 1]; + if (letterSpaceAdjustment != null && letterSpaceAdjustment.isElastic()) { letterSpaceCount++; } } @@ -387,21 +413,27 @@ public class TextLayoutManager extends LeafNodeLayoutManager { private final class TextAreaBuilder { - private final MinOptMax width; - private final int adjust; - private final LayoutContext context; - private final int firstIndex; - private final int lastIndex; - private final boolean isLastArea; - private final Font font; - - private int blockProgressionDimension; - private AreaInfo areaInfo; - private StringBuffer wordChars; - private int[] letterAdjust; - private int letterAdjustIndex; - - private TextArea textArea; + // constructor initialized state + private final MinOptMax width; // content ipd + private final int adjust; // content ipd adjustment + private final LayoutContext context; // layout context + private final int firstIndex; // index of first AreaInfo + private final int lastIndex; // index of last AreaInfo + private final boolean isLastArea; // true if last inline area in line area + private final Font font; // applicable font + + // other, non-constructor state + private TextArea textArea; // text area being constructed + private int blockProgressionDimension; // calculated bpd + private AreaInfo areaInfo; // current area info when iterating over words + private StringBuffer wordChars; // current word's character buffer + private int[] letterSpaceAdjust; // current word's letter space adjustments + private int letterSpaceAdjustIndex; // last written letter space adjustment index + private int[] wordLevels; // current word's bidi levels + private int wordLevelsIndex; // last written bidi level index + private int wordIPD; // accumulated ipd of current word + private int[][] gposAdjustments; // current word's glyph position adjustments + private int gposAdjustmentsIndex; // last written glyph position adjustment index /** * Creates a new TextAreaBuilder which itself builds an inline word area. This @@ -432,7 +464,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { calcBlockProgressionDimension(); setBlockProgressionDimension(); setBaselineOffset(); - setOffset(); + setBlockProgressionOffset(); setText(); TraitSetter.addFontTraits(textArea, font); textArea.addTrait(Trait.COLOR, foText.getColor()); @@ -471,11 +503,11 @@ public class TextLayoutManager extends LeafNodeLayoutManager { textArea.setBaselineOffset(font.getAscender()); } - private void setOffset() { + private void setBlockProgressionOffset() { if (blockProgressionDimension == alignmentContext.getHeight()) { - textArea.setOffset(0); + textArea.setBlockProgressionOffset(0); } else { - textArea.setOffset(alignmentContext.getOffset()); + textArea.setBlockProgressionOffset(alignmentContext.getOffset()); } } @@ -483,7 +515,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { * Sets the text of the TextArea, split into words and spaces. */ private void setText() { - int wordStartIndex = -1; + int areaInfoIndex = -1; int wordCharLength = 0; for (int wordIndex = firstIndex; wordIndex <= lastIndex; wordIndex++) { areaInfo = getAreaInfo(wordIndex); @@ -491,15 +523,15 @@ public class TextLayoutManager extends LeafNodeLayoutManager { addSpaces(); } else { // areaInfo stores information about a word fragment - if (wordStartIndex == -1) { + if (areaInfoIndex == -1) { // here starts a new word - wordStartIndex = wordIndex; + areaInfoIndex = wordIndex; wordCharLength = 0; } - wordCharLength += areaInfo.getCharLength(); + wordCharLength += areaInfo.getWordLength(); if (isWordEnd(wordIndex)) { - addWord(wordStartIndex, wordIndex, wordCharLength); - wordStartIndex = -1; + addWord(areaInfoIndex, wordIndex, wordCharLength); + areaInfoIndex = -1; } } } @@ -509,26 +541,78 @@ public class TextLayoutManager extends LeafNodeLayoutManager { return areaInfoIndex == lastIndex || getAreaInfo(areaInfoIndex + 1).isSpace; } - private void addWord(int startIndex, int endIndex, int charLength) { + /** + * Add word with fragments from STARTINDEX to ENDINDEX, where + * total length of (possibly mapped) word is CHARLENGTH. + * A word is composed from one or more word fragments, where each + * fragment corresponds to distinct instance in a sequence of + * area info instances starting at STARTINDEX continuing through (and + * including) ENDINDEX. + * @param startIndex index of first area info of word to add + * @param endIndex index of last area info of word to add + * @param wordLength number of (mapped) characters in word + */ + private void addWord(int startIndex, int endIndex, int wordLength) { + int blockProgressionOffset = 0; + boolean gposAdjusted = false; if (isHyphenated(endIndex)) { - charLength++; + // TODO may be problematic in some I18N contexts [GA] + wordLength++; } - initWord(charLength); + initWord(wordLength); + // iterate over word's fragments, adding word chars (with bidi + // levels), letter space adjustments, and glyph position adjustments for (int i = startIndex; i <= endIndex; i++) { AreaInfo wordAreaInfo = getAreaInfo(i); addWordChars(wordAreaInfo); addLetterAdjust(wordAreaInfo); + if ( addGlyphPositionAdjustments(wordAreaInfo) ) { + gposAdjusted = true; + } } if (isHyphenated(endIndex)) { + // TODO may be problematic in some I18N contexts [GA] addHyphenationChar(); } - textArea.addWord(wordChars.toString(), 0, letterAdjust); + if ( !gposAdjusted ) { + gposAdjustments = null; + } + textArea.addWord(wordChars.toString(), wordIPD, letterSpaceAdjust, + getNonEmptyLevels(), gposAdjustments, blockProgressionOffset); } - private void initWord(int charLength) { - wordChars = new StringBuffer(charLength); - letterAdjust = new int[charLength]; - letterAdjustIndex = 0; + private int[] getNonEmptyLevels() { + if ( wordLevels != null ) { + assert wordLevelsIndex <= wordLevels.length; + boolean empty = true; + for ( int i = 0, n = wordLevelsIndex; i < n; i++ ) { + if ( wordLevels [ i ] >= 0 ) { + empty = false; + break; + } + } + return empty ? null : wordLevels; + } else { + return null; + } + } + + /** + * Fully allocate word character buffer, letter space adjustments + * array, bidi levels array, and glyph position adjustments array. + * based on full word length, including all (possibly mapped) fragments. + * @param wordLength length of word including all (possibly mapped) fragments + */ + private void initWord(int wordLength) { + wordChars = new StringBuffer(wordLength); + letterSpaceAdjust = new int[wordLength]; + letterSpaceAdjustIndex = 0; + wordLevels = new int[wordLength]; + wordLevelsIndex = 0; + Arrays.fill ( wordLevels, -1 ); + gposAdjustments = new int[wordLength][4]; + gposAdjustmentsIndex = 0; + wordIPD = 0; } private boolean isHyphenated(int endIndex) { @@ -537,27 +621,112 @@ public class TextLayoutManager extends LeafNodeLayoutManager { private void addHyphenationChar() { wordChars.append(foText.getCommonHyphenation().getHyphChar(font)); + // [TBD] expand bidi word levels, letter space adjusts, gpos adjusts + // [TBD] [GA] problematic in bidi context... what is level of hyphen? } + /** + * Given a word area info associated with a word fragment, + * (1) concatenate (possibly mapped) word characters to word character buffer; + * (2) concatenante (possibly mapped) word bidi levels to levels buffer; + * (3) update word's IPD with optimal IPD of fragment. + * @param wordAreaInfo fragment info + */ private void addWordChars(AreaInfo wordAreaInfo) { - for (int i = wordAreaInfo.startIndex; i < wordAreaInfo.breakIndex; i++) { - wordChars.append(foText.charAt(i)); + int s = wordAreaInfo.startIndex; + int e = wordAreaInfo.breakIndex; + if ( foText.hasMapping ( s, e ) ) { + wordChars.append ( foText.getMapping ( s, e ) ); + addWordLevels ( foText.getMappingBidiLevels ( s, e ) ); + } else { + for (int i = s; i < e; i++) { + wordChars.append(foText.charAt(i)); + } + addWordLevels ( foText.getBidiLevels ( s, e ) ); + } + wordIPD += wordAreaInfo.areaIPD.getOpt(); + } + + /** + * Given a (possibly null) bidi levels array associated with a word fragment, + * concatenante (possibly mapped) word bidi levels to levels buffer. + * @param levels bidi levels array or null + */ + private void addWordLevels ( int[] levels ) { + int numLevels = ( levels != null ) ? levels.length : 0; + if ( numLevels > 0 ) { + int need = wordLevelsIndex + numLevels; + if ( need <= wordLevels.length ) { + System.arraycopy ( levels, 0, wordLevels, wordLevelsIndex, numLevels ); + } else { + throw new IllegalStateException + ( "word levels array too short: expect at least " + + need + " entries, but has only " + wordLevels.length + " entries" ); + } } + wordLevelsIndex += numLevels; } + /** + * Given a word area info associated with a word fragment, + * concatenate letter space adjustments for each (possibly mapped) character. + * @param wordAreaInfo fragment info + */ private void addLetterAdjust(AreaInfo wordAreaInfo) { int letterSpaceCount = wordAreaInfo.letterSpaceCount; - for (int i = wordAreaInfo.startIndex; i < wordAreaInfo.breakIndex; i++) { - if (letterAdjustIndex > 0) { - MinOptMax adj = letterAdjustArray[i]; - letterAdjust[letterAdjustIndex] = adj == null ? 0 : adj.getOpt(); + int wordLength = wordAreaInfo.getWordLength(); + int taAdjust = textArea.getTextLetterSpaceAdjust(); + for ( int i = 0, n = wordLength; i < n; i++ ) { + int j = letterSpaceAdjustIndex + i; + if ( j > 0 ) { + int k = wordAreaInfo.startIndex + i; + MinOptMax adj = ( k < letterSpaceAdjustArray.length ) + ? letterSpaceAdjustArray [ k ] : null; + letterSpaceAdjust [ j ] = ( adj == null ) ? 0 : adj.getOpt(); } - if (letterSpaceCount > 0) { - letterAdjust[letterAdjustIndex] += textArea.getTextLetterSpaceAdjust(); + if ( letterSpaceCount > 0 ) { + letterSpaceAdjust [ j ] += taAdjust; letterSpaceCount--; } - letterAdjustIndex++; } + letterSpaceAdjustIndex += wordLength; + } + + /** + * Given a word area info associated with a word fragment, + * concatenate glyph position adjustments for each (possibly mapped) character. + * @param wordAreaInfo fragment info + * @return true if an adjustment was non-zero + */ + private boolean addGlyphPositionAdjustments(AreaInfo wordAreaInfo) { + boolean adjusted = false; + int[][] gpa = wordAreaInfo.gposAdjustments; + int numAdjusts = ( gpa != null ) ? gpa.length : 0; + int wordLength = wordAreaInfo.getWordLength(); + if ( numAdjusts > 0 ) { + int need = gposAdjustmentsIndex + numAdjusts; + if ( need <= gposAdjustments.length ) { + for ( int i = 0, n = wordLength, j = 0; i < n; i++ ) { + if ( i < numAdjusts ) { + int[] wpa1 = gposAdjustments [ gposAdjustmentsIndex + i ]; + int[] wpa2 = gpa [ j++ ]; + for ( int k = 0; k < 4; k++ ) { + int a = wpa2 [ k ]; + if ( a != 0 ) { + wpa1 [ k ] += a; adjusted = true; + } + } + } + } + } else { + throw new IllegalStateException + ( "gpos adjustments array too short: expect at least " + + need + " entries, but has only " + gposAdjustments.length + + " entries" ); + } + } + gposAdjustmentsIndex += wordLength; + return adjusted; } /** @@ -566,13 +735,44 @@ public class TextLayoutManager extends LeafNodeLayoutManager { * Add the spaces - except zero-width spaces - to the TextArea. */ private void addSpaces() { + int blockProgressionOffset = 0; + // [TBD] need to better handling of spaceIPD assignment, for now, + // divide the area info's allocated IPD evenly among the + // non-zero-width space characters + int numZeroWidthSpaces = 0; for (int i = areaInfo.startIndex; i < areaInfo.breakIndex; i++) { char spaceChar = foText.charAt(i); + if (CharUtilities.isZeroWidthSpace(spaceChar)) { + numZeroWidthSpaces++; + } + } + int numSpaces = areaInfo.breakIndex - areaInfo.startIndex - numZeroWidthSpaces; + int spaceIPD = areaInfo.areaIPD.getOpt() / ( ( numSpaces > 0 ) ? numSpaces : 1 ); + // add space area children, one for each non-zero-width space character + for (int i = areaInfo.startIndex; i < areaInfo.breakIndex; i++) { + char spaceChar = foText.charAt(i); + int level = foText.bidiLevelAt(i); if (!CharUtilities.isZeroWidthSpace(spaceChar)) { - textArea.addSpace(spaceChar, 0, CharUtilities.isAdjustableSpace(spaceChar)); + textArea.addSpace + ( spaceChar, spaceIPD, + CharUtilities.isAdjustableSpace(spaceChar), + blockProgressionOffset, level ); } } } + + } + + private void addAreaInfo ( AreaInfo ai ) { + addAreaInfo ( areaInfos.size(), ai ); + } + + private void addAreaInfo ( int index, AreaInfo ai ) { + areaInfos.add ( index, ai ); + } + + private void removeAreaInfo ( int index ) { + areaInfos.remove ( index ); } private AreaInfo getAreaInfo(int index) { @@ -580,10 +780,10 @@ public class TextLayoutManager extends LeafNodeLayoutManager { } private void addToLetterAdjust(int index, int width) { - if (letterAdjustArray[index] == null) { - letterAdjustArray[index] = MinOptMax.getInstance(width); + if (letterSpaceAdjustArray[index] == null) { + letterSpaceAdjustArray[index] = MinOptMax.getInstance(width); } else { - letterAdjustArray[index] = letterAdjustArray[index].plus(width); + letterSpaceAdjustArray[index] = letterSpaceAdjustArray[index].plus(width); } } @@ -600,6 +800,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { /** {@inheritDoc} */ public List getNextKnuthElements(final LayoutContext context, final int alignment) { + lineStartBAP = context.getLineStartBorderAndPaddingWidth(); lineEndBAP = context.getLineEndBorderAndPaddingWidth(); alignmentContext = context.getAlignmentContext(); @@ -610,13 +811,19 @@ public class TextLayoutManager extends LeafNodeLayoutManager { AreaInfo prevAreaInfo = null; returnList.add(sequence); + if (LOG.isDebugEnabled()) { + LOG.debug ( "GK: [" + nextStart + "," + foText.length() + "]" ); + } LineBreakStatus lineBreakStatus = new LineBreakStatus(); thisStart = nextStart; boolean inWord = false; boolean inWhitespace = false; char ch = 0; + int level = -1; + int prevLevel = -1; while (nextStart < foText.length()) { ch = foText.charAt(nextStart); + level = foText.bidiLevelAt(nextStart); boolean breakOpportunity = false; byte breakAction = keepTogether ? LineBreakStatus.PROHIBITED_BREAK @@ -635,17 +842,29 @@ public class TextLayoutManager extends LeafNodeLayoutManager { default: TextLayoutManager.LOG.error("Unexpected breakAction: " + breakAction); } + if (LOG.isDebugEnabled()) { + LOG.debug ( "GK: {" + + " index = " + nextStart + + ", char = " + CharUtilities.charToNCRef ( ch ) + + ", level = " + level + + ", levelPrev = " + prevLevel + + ", inWord = " + inWord + + ", inSpace = " + inWhitespace + + "}" ); + } if (inWord) { - if (breakOpportunity - || TextLayoutManager.isSpace(ch) - || CharUtilities.isExplicitBreak(ch)) { + if ( breakOpportunity + || TextLayoutManager.isSpace(ch) + || CharUtilities.isExplicitBreak(ch) + || ( ( prevLevel != -1 ) && ( level != prevLevel ) ) ) { // this.foText.charAt(lastIndex) == CharUtilities.SOFT_HYPHEN prevAreaInfo = processWord(alignment, sequence, prevAreaInfo, ch, - breakOpportunity, true); + breakOpportunity, true, prevLevel); } } else if (inWhitespace) { if (ch != CharUtilities.SPACE || breakOpportunity) { - prevAreaInfo = processWhitespace(alignment, sequence, breakOpportunity); + prevAreaInfo = processWhitespace(alignment, sequence, + breakOpportunity, prevLevel); } } else { if (areaInfo != null) { @@ -665,14 +884,14 @@ public class TextLayoutManager extends LeafNodeLayoutManager { // preserved space or non-breaking space: // create the AreaInfo object areaInfo = new AreaInfo(nextStart, nextStart + 1, 1, 0, wordSpaceIPD, false, true, - breakOpportunity, spaceFont); + breakOpportunity, spaceFont, level, null); thisStart = nextStart + 1; } else if (CharUtilities.isFixedWidthSpace(ch) || CharUtilities.isZeroWidthSpace(ch)) { // create the AreaInfo object Font font = FontSelector.selectFontForCharacterInText(ch, foText, this); MinOptMax ipd = MinOptMax.getInstance(font.getCharWidth(ch)); areaInfo = new AreaInfo(nextStart, nextStart + 1, 0, 0, ipd, false, true, - breakOpportunity, font); + breakOpportunity, font, level, null); thisStart = nextStart + 1; } else if (CharUtilities.isExplicitBreak(ch)) { //mandatory break-character: only advance index @@ -682,14 +901,15 @@ public class TextLayoutManager extends LeafNodeLayoutManager { inWord = !TextLayoutManager.isSpace(ch) && !CharUtilities.isExplicitBreak(ch); inWhitespace = ch == CharUtilities.SPACE && foText.getWhitespaceTreatment() != Constants.EN_PRESERVE; + prevLevel = level; nextStart++; } // Process any last elements if (inWord) { - processWord(alignment, sequence, prevAreaInfo, ch, false, false); + processWord(alignment, sequence, prevAreaInfo, ch, false, false, prevLevel); } else if (inWhitespace) { - processWhitespace(alignment, sequence, !keepTogether); + processWhitespace(alignment, sequence, !keepTogether, prevLevel); } else if (areaInfo != null) { processLeftoverAreaInfo(alignment, sequence, areaInfo, ch == CharUtilities.ZERO_WIDTH_SPACE); @@ -708,6 +928,8 @@ public class TextLayoutManager extends LeafNodeLayoutManager { } else { return returnList; } + + } private KnuthSequence processLinebreak(List returnList, KnuthSequence sequence) { @@ -723,20 +945,27 @@ public class TextLayoutManager extends LeafNodeLayoutManager { private void processLeftoverAreaInfo(int alignment, KnuthSequence sequence, AreaInfo areaInfo, boolean breakOpportunityAfter) { - areaInfos.add(areaInfo); + addAreaInfo(areaInfo); areaInfo.breakOppAfter = breakOpportunityAfter; addElementsForASpace(sequence, alignment, areaInfo, areaInfos.size() - 1); } private AreaInfo processWhitespace(final int alignment, - final KnuthSequence sequence, final boolean breakOpportunity) { + final KnuthSequence sequence, final boolean breakOpportunity, int level) { + + if (LOG.isDebugEnabled()) { + LOG.debug ( "PS: [" + thisStart + "," + nextStart + "]" ); + } + // End of whitespace // create the AreaInfo object assert nextStart >= thisStart; - AreaInfo areaInfo = new AreaInfo(thisStart, nextStart, nextStart - thisStart, 0, - wordSpaceIPD.mult(nextStart - thisStart), false, true, breakOpportunity, spaceFont); + AreaInfo areaInfo = new AreaInfo + ( thisStart, nextStart, nextStart - thisStart, 0, + wordSpaceIPD.mult(nextStart - thisStart), + false, true, breakOpportunity, spaceFont, level, null ); - areaInfos.add(areaInfo); + addAreaInfo(areaInfo); // create the elements addElementsForASpace(sequence, alignment, areaInfo, areaInfos.size() - 1); @@ -745,22 +974,136 @@ public class TextLayoutManager extends LeafNodeLayoutManager { return areaInfo; } - private AreaInfo processWord(final int alignment, final KnuthSequence sequence, - AreaInfo prevAreaInfo, final char ch, final boolean breakOpportunity, - final boolean checkEndsWithHyphen) { + private AreaInfo processWordMapping + ( int lastIndex, final Font font, AreaInfo prevAreaInfo, final char breakOpportunityChar, + final boolean endsWithHyphen, int level ) { + int s = this.thisStart; // start index of word in FOText character buffer + int e = lastIndex; // end index of word in FOText character buffer + int nLS = 0; // # of letter spaces + String script = foText.getScript(); + String language = foText.getLanguage(); + + if (LOG.isDebugEnabled()) { + LOG.debug ( "PW: [" + thisStart + "," + lastIndex + "]: {" + + " +M" + + ", level = " + level + + " }" ); + } - //Word boundary found, process widths and kerning - int lastIndex = nextStart; - while (lastIndex > 0 && foText.charAt(lastIndex - 1) == CharUtilities.SOFT_HYPHEN) { - lastIndex--; + // 1. extract unmapped character sequence + CharSequence ics = foText.subSequence ( s, e ); + + // 2. if script is not specified (by FO property) or it is specified as 'auto', + // then compute dominant script + if ( ( script == null ) || "auto".equals(script) ) { + script = CharScript.scriptTagFromCode ( CharScript.dominantScript ( ics ) ); + } + if ( ( language == null ) || "none".equals(language) ) { + language = "dflt"; } - Font font = FontSelector - .selectFontForCharactersInText(foText, thisStart, lastIndex, foText, this); + + // 3. perform mapping of chars to glyphs ... to glyphs ... to chars + CharSequence mcs = font.performSubstitution ( ics, script, language ); + + // 4. compute glyph position adjustments on (substituted) characters + int[][] gpa; + if ( font.performsPositioning() ) { + // handle GPOS adjustments + gpa = font.performPositioning ( mcs, script, language ); + } else if ( font.hasKerning() ) { + // handle standard (non-GPOS) kerning adjustments + gpa = getKerningAdjustments ( mcs, font ); + } else { + gpa = null; + } + + // 5. reorder combining marks so that they precede (within the mapped char sequence) the + // base to which they are applied; N.B. position adjustments (gpa) are reordered in place + mcs = font.reorderCombiningMarks ( mcs, gpa, script, language ); + + // 6. if mapped sequence differs from input sequence, then memoize mapped sequence + if ( !CharUtilities.isSameSequence ( mcs, ics ) ) { + foText.addMapping ( s, e, mcs ); + } + + // 7. compute word ipd based on final position adjustments + MinOptMax ipd = MinOptMax.ZERO; + for ( int i = 0, n = mcs.length(); i < n; i++ ) { + int c = mcs.charAt ( i ); + // TODO !BMP + int w = font.getCharWidth ( c ); + if ( w < 0 ) { + w = 0; + } + if ( gpa != null ) { + w += gpa [ i ] [ GlyphPositioningTable.Value.IDX_X_ADVANCE ]; + } + ipd = ipd.plus ( w ); + } + + // [TBD] - handle letter spacing + + return new AreaInfo + ( s, e, 0, nLS, ipd, endsWithHyphen, false, + breakOpportunityChar != 0, font, level, gpa ); + } + + /** + * Given a mapped character sequence MCS, obtain glyph position adjustments + * from the font's kerning data. + * @param mcs mapped character sequence + * @param font applicable font + * @return glyph position adjustments (or null if no kerning) + */ + private int[][] getKerningAdjustments ( CharSequence mcs, final Font font ) { + int nc = mcs.length(); + // extract kerning array + int[] ka = new int [ nc ]; // kerning array + for ( int i = 0, n = nc, cPrev = -1; i < n; i++ ) { + int c = mcs.charAt ( i ); + // TODO !BMP + if ( cPrev >= 0 ) { + ka[i] = font.getKernValue ( cPrev, c ); + } + cPrev = c; + } + // was there a non-zero kerning? + boolean hasKerning = false; + for ( int i = 0, n = nc; i < n; i++ ) { + if ( ka[i] != 0 ) { + hasKerning = true; + break; + } + } + // if non-zero kerning, then create and return glyph position adjustment array + if ( hasKerning ) { + int[][] gpa = new int [ nc ] [ 4 ]; + for ( int i = 0, n = nc; i < n; i++ ) { + if ( i > 0 ) { + gpa [ i - 1 ] [ GlyphPositioningTable.Value.IDX_X_ADVANCE ] = ka [ i ]; + } + } + return gpa; + } else { + return null; + } + } + + private AreaInfo processWordNoMapping(int lastIndex, final Font font, AreaInfo prevAreaInfo, + final char breakOpportunityChar, final boolean endsWithHyphen, int level) { boolean kerning = font.hasKerning(); MinOptMax wordIPD = MinOptMax.ZERO; + + if (LOG.isDebugEnabled()) { + LOG.debug ( "PW: [" + thisStart + "," + lastIndex + "]: {" + + " -M" + + ", level = " + level + + " }" ); + } + for (int i = thisStart; i < lastIndex; i++) { char currentChar = foText.charAt(i); - + //character width int charWidth = font.getCharWidth(currentChar); wordIPD = wordIPD.plus(charWidth); @@ -782,14 +1125,12 @@ public class TextLayoutManager extends LeafNodeLayoutManager { } } } - boolean endsWithHyphen = checkEndsWithHyphen - && foText.charAt(lastIndex) == CharUtilities.SOFT_HYPHEN; if (kerning - && breakOpportunity - && !TextLayoutManager.isSpace(ch) + && ( breakOpportunityChar != 0 ) + && !TextLayoutManager.isSpace(breakOpportunityChar) && lastIndex > 0 && endsWithHyphen) { - int kern = font.getKernValue(foText.charAt(lastIndex - 1), ch); + int kern = font.getKernValue(foText.charAt(lastIndex - 1), breakOpportunityChar); if (kern != 0) { addToLetterAdjust(lastIndex, kern); //TODO: add kern to wordIPD? @@ -801,23 +1142,46 @@ public class TextLayoutManager extends LeafNodeLayoutManager { int letterSpaces = 0; if (wordLength != 0) { letterSpaces = wordLength - 1; - // if there is a break opportunity and the next one + // if there is a break opportunity and the next one (break character) // is not a space, it could be used as a line end; // add one more letter space, in case other text follows - if (breakOpportunity && !TextLayoutManager.isSpace(ch)) { - letterSpaces++; + if (( breakOpportunityChar != 0 ) && !TextLayoutManager.isSpace(breakOpportunityChar)) { + letterSpaces++; } } assert letterSpaces >= 0; wordIPD = wordIPD.plus(letterSpaceIPD.mult(letterSpaces)); - // create the AreaInfo object - AreaInfo areaInfo = new AreaInfo(thisStart, lastIndex, 0, - letterSpaces, wordIPD, - endsWithHyphen, - false, breakOpportunity, font); + // create and return the AreaInfo object + return new AreaInfo(thisStart, lastIndex, 0, + letterSpaces, wordIPD, + endsWithHyphen, + false, breakOpportunityChar != 0, font, level, null); + } + + private AreaInfo processWord(final int alignment, final KnuthSequence sequence, + AreaInfo prevAreaInfo, final char ch, final boolean breakOpportunity, + final boolean checkEndsWithHyphen, int level) { + + //Word boundary found, process widths and kerning + int lastIndex = nextStart; + while (lastIndex > 0 && foText.charAt(lastIndex - 1) == CharUtilities.SOFT_HYPHEN) { + lastIndex--; + } + final boolean endsWithHyphen = checkEndsWithHyphen + && foText.charAt(lastIndex) == CharUtilities.SOFT_HYPHEN; + Font font = FontSelector.selectFontForCharactersInText + ( foText, thisStart, lastIndex, foText, this ); + AreaInfo areaInfo; + if ( font.performsSubstitution() || font.performsPositioning() ) { + areaInfo = processWordMapping + ( lastIndex, font, prevAreaInfo, breakOpportunity ? ch : 0, endsWithHyphen, level ); + } else { + areaInfo = processWordNoMapping + ( lastIndex, font, prevAreaInfo, breakOpportunity ? ch : 0, endsWithHyphen, level ); + } prevAreaInfo = areaInfo; - areaInfos.add(areaInfo); + addAreaInfo(areaInfo); tempStart = nextStart; //add the elements @@ -902,22 +1266,22 @@ public class TextLayoutManager extends LeafNodeLayoutManager { newIPD = newIPD.plus(font.getCharWidth(ch)); //if (i > startIndex) { if (i < stopIndex) { - MinOptMax letterAdjust = letterAdjustArray[i + 1]; + MinOptMax letterSpaceAdjust = letterSpaceAdjustArray[i + 1]; if (i == stopIndex - 1 && hyphenFollows) { //the letter adjust here needs to be handled further down during //element generation because it depends on hyph/no-hyph condition - letterAdjust = null; + letterSpaceAdjust = null; } - if (letterAdjust != null) { - newIPD = newIPD.plus(letterAdjust); + if (letterSpaceAdjust != null) { + newIPD = newIPD.plus(letterSpaceAdjust); } } } // add letter spaces boolean isWordEnd - = stopIndex == areaInfo.breakIndex - && areaInfo.letterSpaceCount < areaInfo.getCharLength(); + = (stopIndex == areaInfo.breakIndex) + && (areaInfo.letterSpaceCount < areaInfo.getWordLength()); int letterSpaceCount = isWordEnd ? stopIndex - startIndex - 1 : stopIndex - startIndex; assert letterSpaceCount >= 0; @@ -925,8 +1289,11 @@ public class TextLayoutManager extends LeafNodeLayoutManager { if (!(nothingChanged && stopIndex == areaInfo.breakIndex && !hyphenFollows)) { // the new AreaInfo object is not equal to the old one - changeList.add(new PendingChange(new AreaInfo(startIndex, stopIndex, 0, - letterSpaceCount, newIPD, hyphenFollows, false, false, font), + changeList.add + ( new PendingChange + ( new AreaInfo(startIndex, stopIndex, 0, + letterSpaceCount, newIPD, hyphenFollows, + false, false, font, -1, null), ((LeafPosition) pos).getLeafPos() + changeOffset)); nothingChanged = false; } @@ -992,9 +1359,9 @@ public class TextLayoutManager extends LeafNodeLayoutManager { areaInfosAdded++; oldIndex = currChange.index; changeIndex = currChange.index + areaInfosAdded - areaInfosRemoved; - areaInfos.remove(changeIndex); + removeAreaInfo(changeIndex); } - areaInfos.add(changeIndex, currChange.areaInfo); + addAreaInfo(changeIndex, currChange.areaInfo); } changeList.clear(); } @@ -1035,7 +1402,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { int leafValue = ((LeafPosition) pos).getLeafPos() + changeOffset; if (leafValue != -1) { AreaInfo areaInfo = getAreaInfo(leafValue); - StringBuffer buffer = new StringBuffer(areaInfo.getCharLength()); + StringBuffer buffer = new StringBuffer(areaInfo.getWordLength()); for (int i = areaInfo.startIndex; i < areaInfo.breakIndex; i++) { buffer.append(foText.charAt(i)); } @@ -1209,7 +1576,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { MinOptMax widthIfNoBreakOccurs = null; if (areaInfo.breakIndex < foText.length()) { //Add in kerning in no-break condition - widthIfNoBreakOccurs = letterAdjustArray[areaInfo.breakIndex]; + widthIfNoBreakOccurs = letterSpaceAdjustArray[areaInfo.breakIndex]; } //if (areaInfo.breakIndex) @@ -1325,4 +1692,14 @@ public class TextLayoutManager extends LeafNodeLayoutManager { } + /** {@inheritDoc} */ + public String toString() { + return super.toString() + "{" + + "chars = \'" + + CharUtilities.toNCRefs ( foText.getCharSequence().toString() ) + + "\'" + + ", len = " + foText.length() + + "}"; + } + } diff --git a/src/java/org/apache/fop/layoutmgr/list/ListBlockLayoutManager.java b/src/java/org/apache/fop/layoutmgr/list/ListBlockLayoutManager.java index 5772c33ff..5bd451ffb 100644 --- a/src/java/org/apache/fop/layoutmgr/list/ListBlockLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/list/ListBlockLayoutManager.java @@ -120,8 +120,8 @@ public class ListBlockLayoutManager extends BlockStackingLayoutManager } /** - * The table area is a reference area that contains areas for - * columns, bodies, rows and the contents are in cells. + * A list block generates one or more normal block areas whose child areas are + * normal block areas returned by the children of fo:list-block. See XSL-FO 1.1 6.8.2. * * @param parentIter the position iterator * @param layoutContext the layout context for adding areas diff --git a/src/java/org/apache/fop/layoutmgr/list/ListItemContentLayoutManager.java b/src/java/org/apache/fop/layoutmgr/list/ListItemContentLayoutManager.java index 8ef0f62cf..72e4e227a 100644 --- a/src/java/org/apache/fop/layoutmgr/list/ListItemContentLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/list/ListItemContentLayoutManager.java @@ -45,7 +45,7 @@ public class ListItemContentLayoutManager extends BlockStackingLayoutManager { private Block curBlockArea; - private int xoffset; + private int xOffset; private int itemIPD; /** @@ -80,7 +80,7 @@ public class ListItemContentLayoutManager extends BlockStackingLayoutManager { * @param off the x offset */ public void setXOffset(int off) { - xoffset = off; + xOffset = off; } /** @@ -175,7 +175,7 @@ public class ListItemContentLayoutManager extends BlockStackingLayoutManager { curBlockArea = new Block(); curBlockArea.setPositioning(Block.ABSOLUTE); // set position - curBlockArea.setXOffset(xoffset); + curBlockArea.setXOffset(xOffset); //TODO: Check - itemIPD never set? curBlockArea.setIPD(itemIPD); //curBlockArea.setHeight(); diff --git a/src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java b/src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java index 8b9282aea..bc7daa24f 100644 --- a/src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java @@ -465,7 +465,6 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager /** * Add the areas for the break points. - * This sets the offset of each cell as it is added. * * @param parentIter the position iterator * @param layoutContext the layout context for adding areas @@ -507,12 +506,12 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager int bodyFirstIndex = ((ListItemPosition) positionList.getFirst()).getBodyFirstIndex(); int bodyLastIndex = ((ListItemPosition) positionList.getLast()).getBodyLastIndex(); - //Determine previous break if any + //Determine previous break if any (in item label list) int previousBreak = ElementListUtils.determinePreviousBreak(labelList, labelFirstIndex); SpaceResolver.performConditionalsNotification(labelList, labelFirstIndex, labelLastIndex, previousBreak); - //Determine previous break if any + //Determine previous break if any (in item body list) previousBreak = ElementListUtils.determinePreviousBreak(bodyList, bodyFirstIndex); SpaceResolver.performConditionalsNotification(bodyList, bodyFirstIndex, bodyLastIndex, previousBreak); diff --git a/src/java/org/apache/fop/layoutmgr/table/ColumnSetup.java b/src/java/org/apache/fop/layoutmgr/table/ColumnSetup.java index c1fc19050..aaccbd0d3 100644 --- a/src/java/org/apache/fop/layoutmgr/table/ColumnSetup.java +++ b/src/java/org/apache/fop/layoutmgr/table/ColumnSetup.java @@ -33,6 +33,9 @@ import org.apache.fop.fo.expr.RelativeNumericProperty; import org.apache.fop.fo.flow.table.Table; import org.apache.fop.fo.flow.table.TableColumn; import org.apache.fop.fo.properties.TableColLength; +import org.apache.fop.traits.Direction; +import org.apache.fop.traits.WritingModeTraits; +import org.apache.fop.traits.WritingModeTraitsGetter; /** * Class holding a number of columns making up the column setup of a row. @@ -43,6 +46,7 @@ public class ColumnSetup { private static Log log = LogFactory.getLog(ColumnSetup.class); private Table table; + private WritingModeTraitsGetter wmTraits; private List columns = new java.util.ArrayList(); private List colWidths = new java.util.ArrayList(); @@ -53,7 +57,9 @@ public class ColumnSetup { * @param table the table to construct this column setup for */ public ColumnSetup(Table table) { + assert table != null; this.table = table; + this.wmTraits = WritingModeTraits.getWritingModeTraitsGetter ( table ); prepareColumns(); initializeColumnWidths(); } @@ -232,11 +238,47 @@ public class ColumnSetup { } /** + * Determine the X offset of the indicated column, where this + * offset denotes the left edge of the column irrespective of writing + * mode. If writing mode's column progression direction is right-to-left, + * then the first column is the right-most column and the last column is + * the left-most column; otherwise, the first column is the left-most + * column. * @param col column index (1 is first column) * @param context the context for percentage based calculations * @return the X offset of the requested column */ public int getXOffset(int col, PercentBaseContext context) { + // TODO handle vertical WMs [GA] + if ( (wmTraits != null) && (wmTraits.getColumnProgressionDirection() == Direction.RL) ) { + return getXOffsetRTL(col, context); + } else { + return getXOffsetLTR(col, context); + } + } + + /* + * Determine x offset by summing widths of columns to left of specified + * column; i.e., those columns whose column numbers are greater than the + * specified column number. + */ + private int getXOffsetRTL(int col, PercentBaseContext context) { + int xoffset = 0; + for (int i = col, nc = colWidths.size(); ++i < nc;) { + int effCol = i; + if (colWidths.get(effCol) != null) { + xoffset += ((Length) colWidths.get(effCol)).getValue(context); + } + } + return xoffset; + } + + /* + * Determine x offset by summing widths of columns to left of specified + * column; i.e., those columns whose column numbers are less than the + * specified column number. + */ + private int getXOffsetLTR(int col, PercentBaseContext context) { int xoffset = 0; for (int i = col; --i >= 0;) { int effCol; diff --git a/src/java/org/apache/fop/pdf/PDFTextUtil.java b/src/java/org/apache/fop/pdf/PDFTextUtil.java index 3768bb6ce..ed475fcb8 100644 --- a/src/java/org/apache/fop/pdf/PDFTextUtil.java +++ b/src/java/org/apache/fop/pdf/PDFTextUtil.java @@ -81,8 +81,8 @@ public abstract class PDFTextUtil { sb.append(PDFNumber.doubleOut(lt[5], DEC)); } - private void writeChar(char ch, StringBuffer sb) { - if (!useMultiByte) { + private static void writeChar(char ch, StringBuffer sb, boolean multibyte) { + if (!multibyte) { if (ch < 32 || ch > 127) { sb.append("\\").append(Integer.toOctalString(ch)); } else { @@ -101,6 +101,10 @@ public abstract class PDFTextUtil { } } + private void writeChar(char ch, StringBuffer sb) { + writeChar ( ch, sb, useMultiByte ); + } + private void checkInTextObject() { if (!inTextObject) { throw new IllegalStateException("Not in text object"); @@ -245,24 +249,38 @@ public abstract class PDFTextUtil { bufTJ = new StringBuffer(); } if (bufTJ.length() == 0) { - bufTJ.append("[").append(startText); + bufTJ.append("["); + bufTJ.append(startText); } writeChar(codepoint, bufTJ); } /** * Writes a glyph adjust value to the "TJ-Buffer". + + *

    Assumes the following:

    + *
      + *
    1. if buffer is currently empty, then this is the start of the array object + * that encodes the adjustment and character values, and, therfore, a LEFT + * SQUARE BRACKET '[' must be prepended; and + *
    2. + *
    3. otherwise (the buffer is + * not empty), then the last element written to the buffer was a mapped + * character, and, therefore, a terminating '>' or ')' followed by a space + * must be appended to the buffer prior to appending the adjustment value. + *
    4. + *
    * @param adjust the glyph adjust value in thousands of text unit space. */ public void adjustGlyphTJ(double adjust) { if (bufTJ == null) { bufTJ = new StringBuffer(); } - if (bufTJ.length() > 0) { - bufTJ.append(endText).append(" "); - } if (bufTJ.length() == 0) { bufTJ.append("["); + } else { + bufTJ.append(endText); + bufTJ.append(" "); } bufTJ.append(PDFNumber.doubleOut(adjust, DEC - 4)); bufTJ.append(" "); @@ -285,4 +303,31 @@ public abstract class PDFTextUtil { return bufTJ != null && bufTJ.length() > 0; } + /** + * Writes a "Td" command with specified x and y coordinates. + * @param x coordinate + * @param y coordinate + */ + public void writeTd ( double x, double y ) { + StringBuffer sb = new StringBuffer(); + sb.append(PDFNumber.doubleOut(x, DEC)); + sb.append(' '); + sb.append(PDFNumber.doubleOut(y, DEC)); + sb.append ( " Td\n" ); + write ( sb.toString() ); + } + + /** + * Writes a "Tj" command with specified character code. + * @param ch character code to write + */ + public void writeTj ( char ch ) { + StringBuffer sb = new StringBuffer(); + sb.append ( '<' ); + writeChar ( ch, sb, true ); + sb.append ( '>' ); + sb.append ( " Tj\n" ); + write ( sb.toString() ); + } + } diff --git a/src/java/org/apache/fop/render/AbstractPathOrientedRenderer.java b/src/java/org/apache/fop/render/AbstractPathOrientedRenderer.java index 333248f4d..7930e62ab 100644 --- a/src/java/org/apache/fop/render/AbstractPathOrientedRenderer.java +++ b/src/java/org/apache/fop/render/AbstractPathOrientedRenderer.java @@ -73,29 +73,31 @@ public abstract class AbstractPathOrientedRenderer extends PrintRenderer { * @param block the block to render the traits */ protected void handleBlockTraits(Block block) { - int borderPaddingStart = block.getBorderAndPaddingWidthStart(); - int borderPaddingBefore = block.getBorderAndPaddingWidthBefore(); + float borderPaddingStart = block.getBorderAndPaddingWidthStart() / 1000f; + float borderPaddingEnd = block.getBorderAndPaddingWidthEnd() / 1000f; + float borderPaddingBefore = block.getBorderAndPaddingWidthBefore() / 1000f; + float borderPaddingAfter = block.getBorderAndPaddingWidthAfter() / 1000f; float startx = currentIPPosition / 1000f; float starty = currentBPPosition / 1000f; float width = block.getIPD() / 1000f; float height = block.getBPD() / 1000f; - /* using start-indent now - Integer spaceStart = (Integer) block.getTrait(Trait.SPACE_START); - if (spaceStart != null) { - startx += spaceStart.floatValue() / 1000f; - }*/ - startx += block.getStartIndent() / 1000f; - startx -= block.getBorderAndPaddingWidthStart() / 1000f; - - width += borderPaddingStart / 1000f; - width += block.getBorderAndPaddingWidthEnd() / 1000f; - height += borderPaddingBefore / 1000f; - height += block.getBorderAndPaddingWidthAfter() / 1000f; - - drawBackAndBorders(block, startx, starty, - width, height); + int level = block.getBidiLevel(); + if ( ( level == -1 ) || ( ( level & 1 ) == 0 ) ) { + startx += block.getStartIndent() / 1000f; + startx -= borderPaddingStart; + } else { + startx += block.getEndIndent() / 1000f; + startx -= borderPaddingEnd; + } + + width += borderPaddingStart; + width += borderPaddingEnd; + height += borderPaddingBefore; + height += borderPaddingAfter; + + drawBackAndBorders(block, startx, starty, width, height); } /** @@ -114,7 +116,12 @@ public abstract class AbstractPathOrientedRenderer extends PrintRenderer { // adjust the current position according to region borders and padding currentBPPosition = referenceArea.getBorderAndPaddingWidthBefore(); - currentIPPosition = referenceArea.getBorderAndPaddingWidthStart(); + int level = region.getBidiLevel(); + if ( ( level == -1 ) || ( ( level & 1 ) == 0 ) ) { + currentIPPosition = referenceArea.getBorderAndPaddingWidthStart(); + } else { + currentIPPosition = referenceArea.getBorderAndPaddingWidthEnd(); + } // draw background (traits are in the RegionViewport) // and borders (traits are in the RegionReference) drawBackAndBorders(region, referenceArea, startx, starty, width, height); @@ -161,9 +168,9 @@ public abstract class AbstractPathOrientedRenderer extends PrintRenderer { drawBackground(startx, starty, width, height, (Trait.Background) backgroundArea.getTrait(Trait.BACKGROUND), - bpsBefore, bpsAfter, bpsStart, bpsEnd); + bpsBefore, bpsAfter, bpsStart, bpsEnd, backgroundArea.getBidiLevel()); drawBorders(startx, starty, width, height, - bpsBefore, bpsAfter, bpsStart, bpsEnd); + bpsBefore, bpsAfter, bpsStart, bpsEnd, borderArea.getBidiLevel()); } /** @@ -179,11 +186,44 @@ public abstract class AbstractPathOrientedRenderer extends PrintRenderer { * @param bpsAfter the border-after traits * @param bpsStart the border-start traits * @param bpsEnd the border-end traits + * @param level of bidirectional embedding */ protected void drawBackground( // CSOK: ParameterNumber float startx, float starty, float width, float height, Trait.Background back, BorderProps bpsBefore, BorderProps bpsAfter, - BorderProps bpsStart, BorderProps bpsEnd) { + BorderProps bpsStart, BorderProps bpsEnd, int level) { + BorderProps bpsTop = bpsBefore; + BorderProps bpsBottom = bpsAfter; + BorderProps bpsLeft; + BorderProps bpsRight; + if ( ( level == -1 ) || ( ( level & 1 ) == 0 ) ) { + bpsLeft = bpsStart; + bpsRight = bpsEnd; + } else { + bpsLeft = bpsEnd; + bpsRight = bpsStart; + } + drawBackground(startx, starty, width, height, back, bpsTop, bpsBottom, bpsLeft, bpsRight); + } + + /** + * Draw the background. + * This draws the background given the position and the traits. + * + * @param startx the start x position + * @param starty the start y position + * @param width the width of the area + * @param height the height of the area + * @param back the background traits + * @param bpsTop the border specification on the top edge + * @param bpsBottom the border traits associated with bottom edge + * @param bpsLeft the border specification on the left edge + * @param bpsRight the border specification on the right edge + */ + protected void drawBackground( // CSOK: ParameterNumber + float startx, float starty, float width, float height, Trait.Background back, + BorderProps bpsTop, BorderProps bpsBottom, + BorderProps bpsLeft, BorderProps bpsRight) { if (back != null) { endTextObject(); @@ -192,19 +232,19 @@ public abstract class AbstractPathOrientedRenderer extends PrintRenderer { float sy = starty; float paddRectWidth = width; float paddRectHeight = height; - if (bpsStart != null) { - sx += bpsStart.width / 1000f; - paddRectWidth -= bpsStart.width / 1000f; + if (bpsLeft != null) { + sx += bpsLeft.width / 1000f; + paddRectWidth -= bpsLeft.width / 1000f; } - if (bpsBefore != null) { - sy += bpsBefore.width / 1000f; - paddRectHeight -= bpsBefore.width / 1000f; + if (bpsTop != null) { + sy += bpsTop.width / 1000f; + paddRectHeight -= bpsTop.width / 1000f; } - if (bpsEnd != null) { - paddRectWidth -= bpsEnd.width / 1000f; + if (bpsRight != null) { + paddRectWidth -= bpsRight.width / 1000f; } - if (bpsAfter != null) { - paddRectHeight -= bpsAfter.width / 1000f; + if (bpsBottom != null) { + paddRectHeight -= bpsBottom.width / 1000f; } if (back.getColor() != null) { @@ -264,86 +304,99 @@ public abstract class AbstractPathOrientedRenderer extends PrintRenderer { * @param starty the start y position * @param width the width of the area * @param height the height of the area - * @param bpsBefore the border-before traits - * @param bpsAfter the border-after traits - * @param bpsStart the border-start traits - * @param bpsEnd the border-end traits + * @param bpsBefore the border traits associated with before edge + * @param bpsAfter the border traits associated with after edge + * @param bpsStart the border traits associated with start edge + * @param bpsEnd the border traits associated with end edge + * @param level of bidirectional embedding */ protected void drawBorders( // CSOK: ParameterNumber float startx, float starty, float width, float height, BorderProps bpsBefore, BorderProps bpsAfter, - BorderProps bpsStart, BorderProps bpsEnd) { + BorderProps bpsStart, BorderProps bpsEnd, int level) { Rectangle2D.Float borderRect = new Rectangle2D.Float(startx, starty, width, height); - drawBorders(borderRect, bpsBefore, bpsAfter, bpsStart, bpsEnd); + BorderProps bpsTop = bpsBefore; + BorderProps bpsBottom = bpsAfter; + BorderProps bpsLeft; + BorderProps bpsRight; + if ( ( level == -1 ) || ( ( level & 1 ) == 0 ) ) { + bpsLeft = bpsStart; + bpsRight = bpsEnd; + } else { + bpsLeft = bpsEnd; + bpsRight = bpsStart; + } + drawBorders(borderRect, bpsTop, bpsBottom, bpsLeft, bpsRight); } - private static final int BEFORE = 0; - private static final int END = 1; - private static final int AFTER = 2; - private static final int START = 3; + private static final int TOP = 0; + private static final int RIGHT = 1; + private static final int BOTTOM = 2; + private static final int LEFT = 3; /** * Draws borders. * @param borderRect the border rectangle - * @param bpsBefore the border specification on the before side - * @param bpsAfter the border specification on the after side - * @param bpsStart the border specification on the start side - * @param bpsEnd the border specification on the end side + * @param bpsTop the border specification on the top edge + * @param bpsBottom the border traits associated with bottom edge + * @param bpsLeft the border specification on the left edge + * @param bpsRight the border specification on the right edge */ protected void drawBorders( // CSOK: MethodLength Rectangle2D.Float borderRect, - BorderProps bpsBefore, BorderProps bpsAfter, BorderProps bpsStart, BorderProps bpsEnd) { + BorderProps bpsTop, BorderProps bpsBottom, BorderProps bpsLeft, BorderProps bpsRight) { //TODO generalize each of the four conditions into using a parameterized drawBorder() boolean[] border = new boolean[] { - (bpsBefore != null), (bpsEnd != null), - (bpsAfter != null), (bpsStart != null)}; + (bpsTop != null), (bpsRight != null), + (bpsBottom != null), (bpsLeft != null)}; float startx = borderRect.x; float starty = borderRect.y; float width = borderRect.width; float height = borderRect.height; float[] borderWidth = new float[] { - (border[BEFORE] ? bpsBefore.width / 1000f : 0.0f), - (border[END] ? bpsEnd.width / 1000f : 0.0f), - (border[AFTER] ? bpsAfter.width / 1000f : 0.0f), - (border[START] ? bpsStart.width / 1000f : 0.0f)}; + (border[TOP] ? bpsTop.width / 1000f : 0.0f), + (border[RIGHT] ? bpsRight.width / 1000f : 0.0f), + (border[BOTTOM] ? bpsBottom.width / 1000f : 0.0f), + (border[LEFT] ? bpsLeft.width / 1000f : 0.0f)}; float[] clipw = new float[] { - BorderProps.getClippedWidth(bpsBefore) / 1000f, - BorderProps.getClippedWidth(bpsEnd) / 1000f, - BorderProps.getClippedWidth(bpsAfter) / 1000f, - BorderProps.getClippedWidth(bpsStart) / 1000f}; - starty += clipw[BEFORE]; - height -= clipw[BEFORE]; - height -= clipw[AFTER]; - startx += clipw[START]; - width -= clipw[START]; - width -= clipw[END]; + BorderProps.getClippedWidth(bpsTop) / 1000f, + BorderProps.getClippedWidth(bpsRight) / 1000f, + BorderProps.getClippedWidth(bpsBottom) / 1000f, + BorderProps.getClippedWidth(bpsLeft) / 1000f}; + + starty += clipw[TOP]; + height -= clipw[TOP]; + height -= clipw[BOTTOM]; + startx += clipw[LEFT]; + width -= clipw[LEFT]; + width -= clipw[RIGHT]; boolean[] slant = new boolean[] { - (border[START] && border[BEFORE]), - (border[BEFORE] && border[END]), - (border[END] && border[AFTER]), - (border[AFTER] && border[START])}; - if (bpsBefore != null) { + (border[LEFT] && border[TOP]), + (border[TOP] && border[RIGHT]), + (border[RIGHT] && border[BOTTOM]), + (border[BOTTOM] && border[LEFT])}; + if (bpsTop != null) { endTextObject(); float sx1 = startx; - float sx2 = (slant[BEFORE] ? sx1 + borderWidth[START] - clipw[START] : sx1); + float sx2 = (slant[TOP] ? sx1 + borderWidth[LEFT] - clipw[LEFT] : sx1); float ex1 = startx + width; - float ex2 = (slant[END] ? ex1 - borderWidth[END] + clipw[END] : ex1); - float outery = starty - clipw[BEFORE]; - float clipy = outery + clipw[BEFORE]; - float innery = outery + borderWidth[BEFORE]; + float ex2 = (slant[RIGHT] ? ex1 - borderWidth[RIGHT] + clipw[RIGHT] : ex1); + float outery = starty - clipw[TOP]; + float clipy = outery + clipw[TOP]; + float innery = outery + borderWidth[TOP]; saveGraphicsState(); moveTo(sx1, clipy); float sx1a = sx1; float ex1a = ex1; - if (bpsBefore.mode == BorderProps.COLLAPSE_OUTER) { - if (bpsStart != null && bpsStart.mode == BorderProps.COLLAPSE_OUTER) { - sx1a -= clipw[START]; + if (bpsTop.mode == BorderProps.COLLAPSE_OUTER) { + if (bpsLeft != null && bpsLeft.mode == BorderProps.COLLAPSE_OUTER) { + sx1a -= clipw[LEFT]; } - if (bpsEnd != null && bpsEnd.mode == BorderProps.COLLAPSE_OUTER) { - ex1a += clipw[END]; + if (bpsRight != null && bpsRight.mode == BorderProps.COLLAPSE_OUTER) { + ex1a += clipw[RIGHT]; } lineTo(sx1a, outery); lineTo(ex1a, outery); @@ -354,30 +407,30 @@ public abstract class AbstractPathOrientedRenderer extends PrintRenderer { closePath(); clip(); drawBorderLine(sx1a, outery, ex1a, innery, true, true, - bpsBefore.style, bpsBefore.color); + bpsTop.style, bpsTop.color); restoreGraphicsState(); } - if (bpsEnd != null) { + if (bpsRight != null) { endTextObject(); float sy1 = starty; - float sy2 = (slant[END] ? sy1 + borderWidth[BEFORE] - clipw[BEFORE] : sy1); + float sy2 = (slant[RIGHT] ? sy1 + borderWidth[TOP] - clipw[TOP] : sy1); float ey1 = starty + height; - float ey2 = (slant[AFTER] ? ey1 - borderWidth[AFTER] + clipw[AFTER] : ey1); - float outerx = startx + width + clipw[END]; - float clipx = outerx - clipw[END]; - float innerx = outerx - borderWidth[END]; + float ey2 = (slant[BOTTOM] ? ey1 - borderWidth[BOTTOM] + clipw[BOTTOM] : ey1); + float outerx = startx + width + clipw[RIGHT]; + float clipx = outerx - clipw[RIGHT]; + float innerx = outerx - borderWidth[RIGHT]; saveGraphicsState(); moveTo(clipx, sy1); float sy1a = sy1; float ey1a = ey1; - if (bpsEnd.mode == BorderProps.COLLAPSE_OUTER) { - if (bpsBefore != null && bpsBefore.mode == BorderProps.COLLAPSE_OUTER) { - sy1a -= clipw[BEFORE]; + if (bpsRight.mode == BorderProps.COLLAPSE_OUTER) { + if (bpsTop != null && bpsTop.mode == BorderProps.COLLAPSE_OUTER) { + sy1a -= clipw[TOP]; } - if (bpsAfter != null && bpsAfter.mode == BorderProps.COLLAPSE_OUTER) { - ey1a += clipw[AFTER]; + if (bpsBottom != null && bpsBottom.mode == BorderProps.COLLAPSE_OUTER) { + ey1a += clipw[BOTTOM]; } lineTo(outerx, sy1a); lineTo(outerx, ey1a); @@ -387,30 +440,31 @@ public abstract class AbstractPathOrientedRenderer extends PrintRenderer { lineTo(innerx, sy2); closePath(); clip(); - drawBorderLine(innerx, sy1a, outerx, ey1a, false, false, bpsEnd.style, bpsEnd.color); + drawBorderLine(innerx, sy1a, outerx, ey1a, false, false, + bpsRight.style, bpsRight.color); restoreGraphicsState(); } - if (bpsAfter != null) { + if (bpsBottom != null) { endTextObject(); float sx1 = startx; - float sx2 = (slant[START] ? sx1 + borderWidth[START] - clipw[START] : sx1); + float sx2 = (slant[LEFT] ? sx1 + borderWidth[LEFT] - clipw[LEFT] : sx1); float ex1 = startx + width; - float ex2 = (slant[AFTER] ? ex1 - borderWidth[END] + clipw[END] : ex1); - float outery = starty + height + clipw[AFTER]; - float clipy = outery - clipw[AFTER]; - float innery = outery - borderWidth[AFTER]; + float ex2 = (slant[BOTTOM] ? ex1 - borderWidth[RIGHT] + clipw[RIGHT] : ex1); + float outery = starty + height + clipw[BOTTOM]; + float clipy = outery - clipw[BOTTOM]; + float innery = outery - borderWidth[BOTTOM]; saveGraphicsState(); moveTo(ex1, clipy); float sx1a = sx1; float ex1a = ex1; - if (bpsAfter.mode == BorderProps.COLLAPSE_OUTER) { - if (bpsStart != null && bpsStart.mode == BorderProps.COLLAPSE_OUTER) { - sx1a -= clipw[START]; + if (bpsBottom.mode == BorderProps.COLLAPSE_OUTER) { + if (bpsLeft != null && bpsLeft.mode == BorderProps.COLLAPSE_OUTER) { + sx1a -= clipw[LEFT]; } - if (bpsEnd != null && bpsEnd.mode == BorderProps.COLLAPSE_OUTER) { - ex1a += clipw[END]; + if (bpsRight != null && bpsRight.mode == BorderProps.COLLAPSE_OUTER) { + ex1a += clipw[RIGHT]; } lineTo(ex1a, outery); lineTo(sx1a, outery); @@ -420,30 +474,31 @@ public abstract class AbstractPathOrientedRenderer extends PrintRenderer { lineTo(ex2, innery); closePath(); clip(); - drawBorderLine(sx1a, innery, ex1a, outery, true, false, bpsAfter.style, bpsAfter.color); + drawBorderLine(sx1a, innery, ex1a, outery, true, false, + bpsBottom.style, bpsBottom.color); restoreGraphicsState(); } - if (bpsStart != null) { + if (bpsLeft != null) { endTextObject(); float sy1 = starty; - float sy2 = (slant[BEFORE] ? sy1 + borderWidth[BEFORE] - clipw[BEFORE] : sy1); + float sy2 = (slant[TOP] ? sy1 + borderWidth[TOP] - clipw[TOP] : sy1); float ey1 = sy1 + height; - float ey2 = (slant[START] ? ey1 - borderWidth[AFTER] + clipw[AFTER] : ey1); - float outerx = startx - clipw[START]; - float clipx = outerx + clipw[START]; - float innerx = outerx + borderWidth[START]; + float ey2 = (slant[LEFT] ? ey1 - borderWidth[BOTTOM] + clipw[BOTTOM] : ey1); + float outerx = startx - clipw[LEFT]; + float clipx = outerx + clipw[LEFT]; + float innerx = outerx + borderWidth[LEFT]; saveGraphicsState(); moveTo(clipx, ey1); float sy1a = sy1; float ey1a = ey1; - if (bpsStart.mode == BorderProps.COLLAPSE_OUTER) { - if (bpsBefore != null && bpsBefore.mode == BorderProps.COLLAPSE_OUTER) { - sy1a -= clipw[BEFORE]; + if (bpsLeft.mode == BorderProps.COLLAPSE_OUTER) { + if (bpsTop != null && bpsTop.mode == BorderProps.COLLAPSE_OUTER) { + sy1a -= clipw[TOP]; } - if (bpsAfter != null && bpsAfter.mode == BorderProps.COLLAPSE_OUTER) { - ey1a += clipw[AFTER]; + if (bpsBottom != null && bpsBottom.mode == BorderProps.COLLAPSE_OUTER) { + ey1a += clipw[BOTTOM]; } lineTo(outerx, ey1a); lineTo(outerx, sy1a); @@ -453,7 +508,7 @@ public abstract class AbstractPathOrientedRenderer extends PrintRenderer { lineTo(innerx, ey2); closePath(); clip(); - drawBorderLine(outerx, sy1a, innerx, ey1a, false, true, bpsStart.style, bpsStart.color); + drawBorderLine(outerx, sy1a, innerx, ey1a, false, true, bpsLeft.style, bpsLeft.color); restoreGraphicsState(); } } @@ -466,16 +521,16 @@ public abstract class AbstractPathOrientedRenderer extends PrintRenderer { */ protected void renderInlineAreaBackAndBorders(InlineArea area) { float borderPaddingStart = area.getBorderAndPaddingWidthStart() / 1000f; + float borderPaddingEnd = area.getBorderAndPaddingWidthEnd() / 1000f; float borderPaddingBefore = area.getBorderAndPaddingWidthBefore() / 1000f; - float bpwidth = borderPaddingStart - + (area.getBorderAndPaddingWidthEnd() / 1000f); - float bpheight = borderPaddingBefore - + (area.getBorderAndPaddingWidthAfter() / 1000f); + float borderPaddingAfter = area.getBorderAndPaddingWidthAfter() / 1000f; + float bpwidth = borderPaddingStart + borderPaddingEnd; + float bpheight = borderPaddingBefore + borderPaddingAfter; float height = area.getBPD() / 1000f; if (height != 0.0f || bpheight != 0.0f && bpwidth != 0.0f) { float x = currentIPPosition / 1000f; - float y = (currentBPPosition + area.getOffset()) / 1000f; + float y = (currentBPPosition + area.getBlockProgressionOffset()) / 1000f; float width = area.getIPD() / 1000f; drawBackAndBorders(area, x, y - borderPaddingBefore , width + bpwidth @@ -512,10 +567,16 @@ public abstract class AbstractPathOrientedRenderer extends PrintRenderer { AffineTransform positionTransform = new AffineTransform(); positionTransform.translate(bv.getXOffset(), bv.getYOffset()); + int level = bv.getBidiLevel(); int borderPaddingStart = bv.getBorderAndPaddingWidthStart(); + int borderPaddingEnd = bv.getBorderAndPaddingWidthEnd(); //"left/"top" (bv.getX/YOffset()) specify the position of the content rectangle - positionTransform.translate(-borderPaddingStart, -borderPaddingBefore); + if ( ( level == -1 ) || ( ( level & 1 ) == 0 ) ) { + positionTransform.translate(-borderPaddingStart, -borderPaddingBefore); + } else { + positionTransform.translate(-borderPaddingEnd, -borderPaddingBefore); + } //Free transformation for the block-container viewport String transf; @@ -536,14 +597,18 @@ public abstract class AbstractPathOrientedRenderer extends PrintRenderer { //Background and borders float borderPaddingWidth - = (borderPaddingStart + bv.getBorderAndPaddingWidthEnd()) / 1000f; + = (borderPaddingStart + borderPaddingEnd) / 1000f; float borderPaddingHeight = (borderPaddingBefore + bv.getBorderAndPaddingWidthAfter()) / 1000f; drawBackAndBorders(bv, 0, 0, width + borderPaddingWidth, height + borderPaddingHeight); //Shift to content rectangle after border painting AffineTransform contentRectTransform = new AffineTransform(); - contentRectTransform.translate(borderPaddingStart, borderPaddingBefore); + if ( ( level == -1 ) || ( ( level & 1 ) == 0 ) ) { + contentRectTransform.translate(borderPaddingStart, borderPaddingBefore); + } else { + contentRectTransform.translate(borderPaddingEnd, borderPaddingBefore); + } if (!contentRectTransform.isIdentity()) { establishTransformationMatrix(contentRectTransform); @@ -694,25 +759,28 @@ public abstract class AbstractPathOrientedRenderer extends PrintRenderer { * @param viewport the viewport to handle */ public void renderInlineViewport(InlineViewport viewport) { - + int level = viewport.getBidiLevel(); float x = currentIPPosition / 1000f; - float y = (currentBPPosition + viewport.getOffset()) / 1000f; + float y = (currentBPPosition + viewport.getBlockProgressionOffset()) / 1000f; float width = viewport.getIPD() / 1000f; float height = viewport.getBPD() / 1000f; // TODO: Calculate the border rect correctly. float borderPaddingStart = viewport.getBorderAndPaddingWidthStart() / 1000f; + float borderPaddingEnd = viewport.getBorderAndPaddingWidthEnd() / 1000f; float borderPaddingBefore = viewport.getBorderAndPaddingWidthBefore() / 1000f; - float bpwidth = borderPaddingStart - + (viewport.getBorderAndPaddingWidthEnd() / 1000f); - float bpheight = borderPaddingBefore - + (viewport.getBorderAndPaddingWidthAfter() / 1000f); + float borderPaddingAfter = viewport.getBorderAndPaddingWidthAfter() / 1000f; + float bpwidth = borderPaddingStart + borderPaddingEnd; + float bpheight = borderPaddingBefore + borderPaddingAfter; drawBackAndBorders(viewport, x, y, width + bpwidth, height + bpheight); if (viewport.hasClip()) { saveGraphicsState(); - - clipRect(x + borderPaddingStart, y + borderPaddingBefore, width, height); + if ( ( level == -1 ) || ( ( level & 1 ) == 0 ) ) { + clipRect(x + borderPaddingStart, y + borderPaddingBefore, width, height); + } else { + clipRect(x + borderPaddingEnd, y + borderPaddingBefore, width, height); + } } super.renderInlineViewport(viewport); diff --git a/src/java/org/apache/fop/render/AbstractRenderer.java b/src/java/org/apache/fop/render/AbstractRenderer.java index 3c07c0006..639f8590b 100644 --- a/src/java/org/apache/fop/render/AbstractRenderer.java +++ b/src/java/org/apache/fop/render/AbstractRenderer.java @@ -57,6 +57,7 @@ import org.apache.fop.area.RegionViewport; import org.apache.fop.area.Span; import org.apache.fop.area.Trait; import org.apache.fop.area.inline.Container; +import org.apache.fop.area.inline.FilledArea; import org.apache.fop.area.inline.ForeignObject; import org.apache.fop.area.inline.Image; import org.apache.fop.area.inline.InlineArea; @@ -402,22 +403,34 @@ public abstract class AbstractRenderer * @param mr The main reference area */ protected void renderMainReference(MainReference mr) { - int saveIPPos = currentIPPosition; - Span span = null; List spans = mr.getSpans(); int saveBPPos = currentBPPosition; int saveSpanBPPos = saveBPPos; + int saveIPPos = currentIPPosition; for (int count = 0; count < spans.size(); count++) { span = (Span) spans.get(count); + int level = span.getBidiLevel(); + if ( level < 0 ) { + level = 0; + } + if ( ( level & 1 ) == 1 ) { + currentIPPosition += span.getIPD(); + currentIPPosition += mr.getColumnGap(); + } for (int c = 0; c < span.getColumnCount(); c++) { NormalFlow flow = span.getNormalFlow(c); - if (flow != null) { currentBPPosition = saveSpanBPPos; + if ( ( level & 1 ) == 1 ) { + currentIPPosition -= flow.getIPD(); + currentIPPosition -= mr.getColumnGap(); + } renderFlow(flow); - currentIPPosition += flow.getIPD(); - currentIPPosition += mr.getColumnGap(); + if ( ( level & 1 ) == 0 ) { + currentIPPosition += flow.getIPD(); + currentIPPosition += mr.getColumnGap(); + } } } currentIPPosition = saveIPPos; @@ -512,17 +525,10 @@ public abstract class AbstractRenderer */ protected void renderBlocks(Block parent, List blocks) { int saveIP = currentIPPosition; -// int saveBP = currentBPPosition; // Calculate the position of the content rectangle. if (parent != null && !parent.getTraitAsBoolean(Trait.IS_VIEWPORT_AREA)) { currentBPPosition += parent.getBorderAndPaddingWidthBefore(); - /* This is unnecessary now as we're going to use the *-indent traits - currentIPPosition += parent.getBorderAndPaddingWidthStart(); - Integer spaceStart = (Integer) parent.getTrait(Trait.SPACE_START); - if (spaceStart != null) { - currentIPPosition += spaceStart.intValue(); - }*/ } // the position of the containing block is used for @@ -541,15 +547,19 @@ public abstract class AbstractRenderer renderBlock((Block) obj); containingBPPosition = contBP; containingIPPosition = contIP; - } else { + } else if (obj instanceof LineArea) { // a line area is rendered from the top left position // of the line, each inline object is offset from there LineArea line = (LineArea) obj; - currentIPPosition = contIP - + parent.getStartIndent() - + line.getStartIndent(); + if ( parent != null ) { + int level = parent.getBidiLevel(); + if ( ( level == -1 ) || ( ( level & 1 ) == 0 ) ) { + currentIPPosition += parent.getStartIndent(); + } else { + currentIPPosition += parent.getEndIndent(); + } + } renderLineArea(line); - //InlineArea child = (InlineArea) line.getInlineAreas().get(0); currentBPPosition += line.getAllocBPD(); } currentIPPosition = saveIP; @@ -562,6 +572,7 @@ public abstract class AbstractRenderer * @param block The block area */ protected void renderBlock(Block block) { + assert block != null; List children = block.getChildAreas(); if (block instanceof BlockViewport) { if (children != null) { @@ -611,13 +622,40 @@ public abstract class AbstractRenderer List children = line.getInlineAreas(); int saveBP = currentBPPosition; currentBPPosition += line.getSpaceBefore(); - for (int count = 0; count < children.size(); count++) { - InlineArea inline = (InlineArea) children.get(count); + int bl = line.getBidiLevel(); + if ( bl >= 0 ) { + if ( ( bl & 1 ) == 0 ) { + currentIPPosition += line.getStartIndent(); + } else { + currentIPPosition += line.getEndIndent(); + // if line's content overflows line area, then + // ensure that overflow is drawn (extends) + // outside of left side of line area + int overflow = computeInlinesOverflow ( line ); + if ( overflow > 0 ) { + currentIPPosition -= overflow; + } + } + } else { + currentIPPosition += line.getStartIndent(); + } + for (int i = 0, l = children.size(); i < l; i++) { + InlineArea inline = (InlineArea) children.get(i); renderInlineArea(inline); } currentBPPosition = saveBP; } + private int computeInlinesOverflow ( LineArea line ) { + List children = line.getInlineAreas(); + int ipdConsumed = 0; + for (int i = 0, l = children.size(); i < l; i++) { + InlineArea inline = (InlineArea) children.get(i); + ipdConsumed += inline.getIPD(); + } + return ipdConsumed - line.getIPD(); + } + /** * Render the given InlineArea. * @param inlineArea inline area text to render @@ -678,11 +716,12 @@ public abstract class AbstractRenderer * @param text the text to render */ protected void renderText(TextArea text) { + List children = text.getChildAreas(); int saveIP = currentIPPosition; int saveBP = currentBPPosition; - Iterator iter = text.getChildAreas().iterator(); - while (iter.hasNext()) { - renderInlineArea((InlineArea) iter.next()); + for (int i = 0, l = children.size(); i < l; i++) { + InlineArea inline = (InlineArea) children.get(i); + renderInlineArea(inline); } currentIPPosition = saveIP + text.getAllocIPD(); } @@ -708,14 +747,39 @@ public abstract class AbstractRenderer * @param ip the inline parent to render */ protected void renderInlineParent(InlineParent ip) { + int level = ip.getBidiLevel(); + List children = ip.getChildAreas(); renderInlineAreaBackAndBorders(ip); int saveIP = currentIPPosition; int saveBP = currentBPPosition; - currentIPPosition += ip.getBorderAndPaddingWidthStart(); - currentBPPosition += ip.getOffset(); - Iterator iter = ip.getChildAreas().iterator(); - while (iter.hasNext()) { - renderInlineArea((InlineArea) iter.next()); + // if inline parent is a filled area (generated by Leader), and if + // it is right-to-left, then adjust starting ip position in order to + // align children to starting (right) edge of filled area + int ipAdjust; + if ( ( ip instanceof FilledArea ) && ( ( level & 1 ) != 0 ) ) { + int ipdChildren = 0; + for (int i = 0, l = children.size(); i < l; i++) { + InlineArea inline = (InlineArea) children.get(i); + ipdChildren += inline.getAllocIPD(); + } + ipAdjust = ip.getAllocIPD() - ipdChildren; + } else { + ipAdjust = 0; + } + // perform inline position adjustments + if ( ( level == -1 ) || ( ( level & 1 ) == 0 ) ) { + currentIPPosition += ip.getBorderAndPaddingWidthStart(); + } else { + currentIPPosition += ip.getBorderAndPaddingWidthEnd(); + if ( ipAdjust > 0 ) { + currentIPPosition += ipAdjust; + } + } + currentBPPosition += ip.getBlockProgressionOffset(); + // render children inlines + for (int i = 0, l = children.size(); i < l; i++) { + InlineArea inline = (InlineArea) children.get(i); + renderInlineArea(inline); } currentIPPosition = saveIP + ip.getAllocIPD(); currentBPPosition = saveBP; @@ -726,11 +790,16 @@ public abstract class AbstractRenderer * @param ibp the inline block parent to render */ protected void renderInlineBlockParent(InlineBlockParent ibp) { + int level = ibp.getBidiLevel(); renderInlineAreaBackAndBorders(ibp); - currentIPPosition += ibp.getBorderAndPaddingWidthStart(); + if ( ( level == -1 ) || ( ( level & 1 ) == 0 ) ) { + currentIPPosition += ibp.getBorderAndPaddingWidthStart(); + } else { + currentIPPosition += ibp.getBorderAndPaddingWidthEnd(); + } // For inline content the BP position is updated by the enclosing line area int saveBP = currentBPPosition; - currentBPPosition += ibp.getOffset(); + currentBPPosition += ibp.getBlockProgressionOffset(); renderBlock(ibp.getChildArea()); currentBPPosition = saveBP; } @@ -742,7 +811,7 @@ public abstract class AbstractRenderer protected void renderInlineViewport(InlineViewport viewport) { Area content = viewport.getContent(); int saveBP = currentBPPosition; - currentBPPosition += viewport.getOffset(); + currentBPPosition += viewport.getBlockProgressionOffset(); Rectangle2D contpos = viewport.getContentPosition(); if (content instanceof Image) { renderImage((Image) content, contpos); diff --git a/src/java/org/apache/fop/render/DefaultFontResolver.java b/src/java/org/apache/fop/render/DefaultFontResolver.java index a4960c665..0642537c4 100644 --- a/src/java/org/apache/fop/render/DefaultFontResolver.java +++ b/src/java/org/apache/fop/render/DefaultFontResolver.java @@ -44,4 +44,9 @@ public class DefaultFontResolver implements FontResolver { return userAgent.resolveURI(href, userAgent.getFactory().getFontManager().getFontBaseURL()); } + /** {@inheritDoc} */ + public boolean isComplexScriptFeaturesEnabled() { + return userAgent.isComplexScriptFeaturesEnabled(); + } + } diff --git a/src/java/org/apache/fop/render/PrintRenderer.java b/src/java/org/apache/fop/render/PrintRenderer.java index 4e49adc25..96a62cb11 100644 --- a/src/java/org/apache/fop/render/PrintRenderer.java +++ b/src/java/org/apache/fop/render/PrintRenderer.java @@ -91,7 +91,8 @@ public abstract class PrintRenderer extends AbstractRenderer { FontManager fontManager = userAgent.getFactory().getFontManager(); FontCollection[] fontCollections = new FontCollection[] { new Base14FontCollection(fontManager.isBase14KerningEnabled()), - new CustomFontCollection(getFontResolver(), getFontList()) + new CustomFontCollection(getFontResolver(), getFontList(), + userAgent.isComplexScriptFeaturesEnabled()) }; fontManager.setup(getFontInfo(), fontCollections); } diff --git a/src/java/org/apache/fop/render/PrintRendererConfigurator.java b/src/java/org/apache/fop/render/PrintRendererConfigurator.java index 90305ae03..93678b4f8 100644 --- a/src/java/org/apache/fop/render/PrintRendererConfigurator.java +++ b/src/java/org/apache/fop/render/PrintRendererConfigurator.java @@ -95,7 +95,9 @@ public class PrintRendererConfigurator extends AbstractRendererConfigurator FontManager fontManager = factory.getFontManager(); if (fontResolver == null) { //Ensure that we have minimal font resolution capabilities - fontResolver = FontManager.createMinimalFontResolver(); + fontResolver + = FontManager.createMinimalFontResolver + ( userAgent.isComplexScriptFeaturesEnabled() ); } boolean strict = factory.validateUserConfigStrictly(); @@ -128,7 +130,8 @@ public class PrintRendererConfigurator extends AbstractRendererConfigurator FontEventListener listener = new FontEventAdapter( userAgent.getEventBroadcaster()); List fontList = buildFontList(cfg, fontResolver, listener); - fontCollections.add(new CustomFontCollection(fontResolver, fontList)); + fontCollections.add(new CustomFontCollection(fontResolver, fontList, + userAgent.isComplexScriptFeaturesEnabled())); } fontManager.setup(fontInfo, diff --git a/src/java/org/apache/fop/render/afp/AFPPainter.java b/src/java/org/apache/fop/render/afp/AFPPainter.java index 28ca6c67f..30e4e7693 100644 --- a/src/java/org/apache/fop/render/afp/AFPPainter.java +++ b/src/java/org/apache/fop/render/afp/AFPPainter.java @@ -57,6 +57,7 @@ import org.apache.fop.render.intermediate.BorderPainter; import org.apache.fop.render.intermediate.IFContext; import org.apache.fop.render.intermediate.IFException; import org.apache.fop.render.intermediate.IFState; +import org.apache.fop.render.intermediate.IFUtil; import org.apache.fop.traits.BorderProps; import org.apache.fop.traits.RuleStyle; import org.apache.fop.util.CharUtilities; @@ -259,11 +260,11 @@ public class AFPPainter extends AbstractIFPainter { /** {@inheritDoc} */ @Override - public void drawBorderRect(Rectangle rect, BorderProps before, BorderProps after, - BorderProps start, BorderProps end) throws IFException { - if (before != null || after != null || start != null || end != null) { + public void drawBorderRect(Rectangle rect, BorderProps top, BorderProps bottom, + BorderProps left, BorderProps right) throws IFException { + if (top != null || bottom != null || left != null || right != null) { try { - this.borderPainter.drawBorders(rect, before, after, start, end); + this.borderPainter.drawBorders(rect, top, bottom, left, right); } catch (IOException ife) { throw new IFException("IO error while painting borders", ife); } @@ -354,8 +355,8 @@ public class AFPPainter extends AbstractIFPainter { /** {@inheritDoc} */ public void drawText( // CSOK: MethodLength - int x, int y, final int letterSpacing, final int wordSpacing, final int[] dx, - final String text) throws IFException { + int x, int y, final int letterSpacing, final int wordSpacing, + final int[][] dp, final String text) throws IFException { final int fontSize = this.state.getFontSize(); getPaintingState().setFontSize(fontSize); @@ -404,6 +405,7 @@ public class AFPPainter extends AbstractIFPainter { builder.setCodedFont((byte)fontReference); int l = text.length(); + int[] dx = IFUtil.convertDPToDX ( dp ); int dxl = (dx != null ? dx.length : 0); StringBuffer sb = new StringBuffer(); diff --git a/src/java/org/apache/fop/render/bitmap/BitmapRendererConfigurator.java b/src/java/org/apache/fop/render/bitmap/BitmapRendererConfigurator.java index 2d78b53c6..296d4628a 100644 --- a/src/java/org/apache/fop/render/bitmap/BitmapRendererConfigurator.java +++ b/src/java/org/apache/fop/render/bitmap/BitmapRendererConfigurator.java @@ -129,7 +129,8 @@ public class BitmapRendererConfigurator extends Java2DRendererConfigurator FontEventListener listener = new FontEventAdapter( userAgent.getEventBroadcaster()); List fontList = buildFontList(cfg, fontResolver, listener); - fontCollections.add(new ConfiguredFontCollection(fontResolver, fontList)); + fontCollections.add(new ConfiguredFontCollection(fontResolver, fontList, + userAgent.isComplexScriptFeaturesEnabled())); } fontManager.setup(fontInfo, diff --git a/src/java/org/apache/fop/render/intermediate/AbstractIFPainter.java b/src/java/org/apache/fop/render/intermediate/AbstractIFPainter.java index 2226274ab..c696e552d 100644 --- a/src/java/org/apache/fop/render/intermediate/AbstractIFPainter.java +++ b/src/java/org/apache/fop/render/intermediate/AbstractIFPainter.java @@ -315,55 +315,55 @@ public abstract class AbstractIFPainter implements IFPainter { } /** {@inheritDoc} */ - public void drawBorderRect(Rectangle rect, BorderProps before, BorderProps after, - BorderProps start, BorderProps end) throws IFException { - if (before != null) { + public void drawBorderRect(Rectangle rect, BorderProps top, BorderProps bottom, + BorderProps left, BorderProps right) throws IFException { + if (top != null) { Rectangle b = new Rectangle( rect.x, rect.y, - rect.width, before.width); - fillRect(b, before.color); + rect.width, top.width); + fillRect(b, top.color); } - if (end != null) { + if (right != null) { Rectangle b = new Rectangle( - rect.x + rect.width - end.width, rect.y, - end.width, rect.height); - fillRect(b, end.color); + rect.x + rect.width - right.width, rect.y, + right.width, rect.height); + fillRect(b, right.color); } - if (after != null) { + if (bottom != null) { Rectangle b = new Rectangle( - rect.x, rect.y + rect.height - after.width, - rect.width, after.width); - fillRect(b, after.color); + rect.x, rect.y + rect.height - bottom.width, + rect.width, bottom.width); + fillRect(b, bottom.color); } - if (start != null) { + if (left != null) { Rectangle b = new Rectangle( rect.x, rect.y, - start.width, rect.height); - fillRect(b, start.color); + left.width, rect.height); + fillRect(b, left.color); } } /** * Indicates whether the given border segments (if present) have only solid borders, i.e. * could be painted in a simplified fashion keeping the output file smaller. - * @param before the border segment on the before-side (top) - * @param after the border segment on the after-side (bottom) - * @param start the border segment on the start-side (left) - * @param end the border segment on the end-side (right) + * @param top the border segment on the top edge + * @param bottom the border segment on the bottom edge + * @param left the border segment on the left edge + * @param right the border segment on the right edge * @return true if any border segment has a non-solid border style */ - protected boolean hasOnlySolidBorders(BorderProps before, BorderProps after, - BorderProps start, BorderProps end) { - if (before != null && before.style != Constants.EN_SOLID) { + protected boolean hasOnlySolidBorders(BorderProps top, BorderProps bottom, + BorderProps left, BorderProps right) { + if (top != null && top.style != Constants.EN_SOLID) { return false; } - if (after != null && after.style != Constants.EN_SOLID) { + if (bottom != null && bottom.style != Constants.EN_SOLID) { return false; } - if (start != null && start.style != Constants.EN_SOLID) { + if (left != null && left.style != Constants.EN_SOLID) { return false; } - if (end != null && end.style != Constants.EN_SOLID) { + if (right != null && right.style != Constants.EN_SOLID) { return false; } return true; diff --git a/src/java/org/apache/fop/render/intermediate/BorderPainter.java b/src/java/org/apache/fop/render/intermediate/BorderPainter.java index 20402369a..cc28028ef 100644 --- a/src/java/org/apache/fop/render/intermediate/BorderPainter.java +++ b/src/java/org/apache/fop/render/intermediate/BorderPainter.java @@ -35,35 +35,35 @@ public abstract class BorderPainter { /** * Draws borders. * @param borderRect the border rectangle - * @param bpsBefore the border specification on the before side - * @param bpsAfter the border specification on the after side - * @param bpsStart the border specification on the start side - * @param bpsEnd the border specification on the end side + * @param bpsTop the border specification on the top side + * @param bpsBottom the border specification on the bottom side + * @param bpsLeft the border specification on the left side + * @param bpsRight the border specification on the end side * @throws IOException if an I/O error occurs while creating the borders */ public void drawBorders(Rectangle borderRect, // CSOK: MethodLength - BorderProps bpsBefore, BorderProps bpsAfter, - BorderProps bpsStart, BorderProps bpsEnd) throws IOException { + BorderProps bpsTop, BorderProps bpsBottom, + BorderProps bpsLeft, BorderProps bpsRight) throws IOException { int startx = borderRect.x; int starty = borderRect.y; int width = borderRect.width; int height = borderRect.height; boolean[] b = new boolean[] { - (bpsBefore != null), (bpsEnd != null), - (bpsAfter != null), (bpsStart != null)}; + (bpsTop != null), (bpsRight != null), + (bpsBottom != null), (bpsLeft != null)}; if (!b[0] && !b[1] && !b[2] && !b[3]) { return; } int[] bw = new int[] { - (b[0] ? bpsBefore.width : 0), - (b[1] ? bpsEnd.width : 0), - (b[2] ? bpsAfter.width : 0), - (b[3] ? bpsStart.width : 0)}; + (b[0] ? bpsTop.width : 0), + (b[1] ? bpsRight.width : 0), + (b[2] ? bpsBottom.width : 0), + (b[3] ? bpsLeft.width : 0)}; int[] clipw = new int[] { - BorderProps.getClippedWidth(bpsBefore), - BorderProps.getClippedWidth(bpsEnd), - BorderProps.getClippedWidth(bpsAfter), - BorderProps.getClippedWidth(bpsStart)}; + BorderProps.getClippedWidth(bpsTop), + BorderProps.getClippedWidth(bpsRight), + BorderProps.getClippedWidth(bpsBottom), + BorderProps.getClippedWidth(bpsLeft)}; starty += clipw[0]; height -= clipw[0]; height -= clipw[2]; @@ -73,7 +73,7 @@ public abstract class BorderPainter { boolean[] slant = new boolean[] { (b[3] && b[0]), (b[0] && b[1]), (b[1] && b[2]), (b[2] && b[3])}; - if (bpsBefore != null) { + if (bpsTop != null) { int sx1 = startx; int sx2 = (slant[0] ? sx1 + bw[3] - clipw[3] : sx1); int ex1 = startx + width; @@ -86,11 +86,11 @@ public abstract class BorderPainter { moveTo(sx1, clipy); int sx1a = sx1; int ex1a = ex1; - if (bpsBefore.mode == BorderProps.COLLAPSE_OUTER) { - if (bpsStart != null && bpsStart.mode == BorderProps.COLLAPSE_OUTER) { + if (bpsTop.mode == BorderProps.COLLAPSE_OUTER) { + if (bpsLeft != null && bpsLeft.mode == BorderProps.COLLAPSE_OUTER) { sx1a -= clipw[3]; } - if (bpsEnd != null && bpsEnd.mode == BorderProps.COLLAPSE_OUTER) { + if (bpsRight != null && bpsRight.mode == BorderProps.COLLAPSE_OUTER) { ex1a += clipw[1]; } lineTo(sx1a, outery); @@ -102,10 +102,10 @@ public abstract class BorderPainter { closePath(); clip(); drawBorderLine(sx1a, outery, ex1a, innery, true, true, - bpsBefore.style, bpsBefore.color); + bpsTop.style, bpsTop.color); restoreGraphicsState(); } - if (bpsEnd != null) { + if (bpsRight != null) { int sy1 = starty; int sy2 = (slant[1] ? sy1 + bw[0] - clipw[0] : sy1); int ey1 = starty + height; @@ -118,11 +118,11 @@ public abstract class BorderPainter { moveTo(clipx, sy1); int sy1a = sy1; int ey1a = ey1; - if (bpsEnd.mode == BorderProps.COLLAPSE_OUTER) { - if (bpsBefore != null && bpsBefore.mode == BorderProps.COLLAPSE_OUTER) { + if (bpsRight.mode == BorderProps.COLLAPSE_OUTER) { + if (bpsTop != null && bpsTop.mode == BorderProps.COLLAPSE_OUTER) { sy1a -= clipw[0]; } - if (bpsAfter != null && bpsAfter.mode == BorderProps.COLLAPSE_OUTER) { + if (bpsBottom != null && bpsBottom.mode == BorderProps.COLLAPSE_OUTER) { ey1a += clipw[2]; } lineTo(outerx, sy1a); @@ -133,10 +133,11 @@ public abstract class BorderPainter { lineTo(innerx, sy2); closePath(); clip(); - drawBorderLine(innerx, sy1a, outerx, ey1a, false, false, bpsEnd.style, bpsEnd.color); + drawBorderLine(innerx, sy1a, outerx, ey1a, false, false, + bpsRight.style, bpsRight.color); restoreGraphicsState(); } - if (bpsAfter != null) { + if (bpsBottom != null) { int sx1 = startx; int sx2 = (slant[3] ? sx1 + bw[3] - clipw[3] : sx1); int ex1 = startx + width; @@ -149,11 +150,11 @@ public abstract class BorderPainter { moveTo(ex1, clipy); int sx1a = sx1; int ex1a = ex1; - if (bpsAfter.mode == BorderProps.COLLAPSE_OUTER) { - if (bpsStart != null && bpsStart.mode == BorderProps.COLLAPSE_OUTER) { + if (bpsBottom.mode == BorderProps.COLLAPSE_OUTER) { + if (bpsLeft != null && bpsLeft.mode == BorderProps.COLLAPSE_OUTER) { sx1a -= clipw[3]; } - if (bpsEnd != null && bpsEnd.mode == BorderProps.COLLAPSE_OUTER) { + if (bpsRight != null && bpsRight.mode == BorderProps.COLLAPSE_OUTER) { ex1a += clipw[1]; } lineTo(ex1a, outery); @@ -164,10 +165,11 @@ public abstract class BorderPainter { lineTo(ex2, innery); closePath(); clip(); - drawBorderLine(sx1a, innery, ex1a, outery, true, false, bpsAfter.style, bpsAfter.color); + drawBorderLine(sx1a, innery, ex1a, outery, true, false, + bpsBottom.style, bpsBottom.color); restoreGraphicsState(); } - if (bpsStart != null) { + if (bpsLeft != null) { int sy1 = starty; int sy2 = (slant[0] ? sy1 + bw[0] - clipw[0] : sy1); int ey1 = sy1 + height; @@ -180,11 +182,11 @@ public abstract class BorderPainter { moveTo(clipx, ey1); int sy1a = sy1; int ey1a = ey1; - if (bpsStart.mode == BorderProps.COLLAPSE_OUTER) { - if (bpsBefore != null && bpsBefore.mode == BorderProps.COLLAPSE_OUTER) { + if (bpsLeft.mode == BorderProps.COLLAPSE_OUTER) { + if (bpsTop != null && bpsTop.mode == BorderProps.COLLAPSE_OUTER) { sy1a -= clipw[0]; } - if (bpsAfter != null && bpsAfter.mode == BorderProps.COLLAPSE_OUTER) { + if (bpsBottom != null && bpsBottom.mode == BorderProps.COLLAPSE_OUTER) { ey1a += clipw[2]; } lineTo(outerx, ey1a); @@ -195,7 +197,7 @@ public abstract class BorderPainter { lineTo(innerx, ey2); closePath(); clip(); - drawBorderLine(outerx, sy1a, innerx, ey1a, false, true, bpsStart.style, bpsStart.color); + drawBorderLine(outerx, sy1a, innerx, ey1a, false, true, bpsLeft.style, bpsLeft.color); restoreGraphicsState(); } } diff --git a/src/java/org/apache/fop/render/intermediate/IFPainter.java b/src/java/org/apache/fop/render/intermediate/IFPainter.java index 00fd74209..06dfbd181 100644 --- a/src/java/org/apache/fop/render/intermediate/IFPainter.java +++ b/src/java/org/apache/fop/render/intermediate/IFPainter.java @@ -151,12 +151,14 @@ public interface IFPainter { * @param y Y-coordinate of the starting point of the text * @param letterSpacing additional spacing between characters (may be 0) * @param wordSpacing additional spacing between words (may be 0) - * @param dx an array of adjustment values for each character in X-direction (may be null) + * @param dp an array of 4-tuples, expressing [X,Y] placment + * adjustments and [X,Y] advancement adjustments, in that order (may be null); if + * not null, then adjustments.length must be the same as text.length() * @param text the text * @throws IFException if an error occurs while handling this event */ void drawText(int x, int y, int letterSpacing, int wordSpacing, - int[] dx, String text) throws IFException; + int[][] dp, String text) throws IFException; /** * Restricts the current clipping region with the given rectangle. @@ -178,15 +180,15 @@ public interface IFPainter { * Draws a border rectangle. The border segments are specified through {@link BorderProps} * instances. * @param rect the rectangle's coordinates and extent - * @param before the border segment on the before-side (top) - * @param after the border segment on the after-side (bottom) - * @param start the border segment on the start-side (left) - * @param end the border segment on the end-side (right) + * @param top the border segment on the top edge + * @param bottom the border segment on the bottom edge + * @param left the border segment on the left edge + * @param right the border segment on the right edge * @throws IFException if an error occurs while handling this event */ void drawBorderRect(Rectangle rect, - BorderProps before, BorderProps after, - BorderProps start, BorderProps end) throws IFException; + BorderProps top, BorderProps bottom, + BorderProps left, BorderProps right) throws IFException; /** * Draws a line. NOTE: Currently, only horizontal lines are implemented! diff --git a/src/java/org/apache/fop/render/intermediate/IFParser.java b/src/java/org/apache/fop/render/intermediate/IFParser.java index 36f1fd841..26d1b62ed 100644 --- a/src/java/org/apache/fop/render/intermediate/IFParser.java +++ b/src/java/org/apache/fop/render/intermediate/IFParser.java @@ -618,8 +618,14 @@ public class IFParser implements IFConstants { s = lastAttributes.getValue("word-spacing"); int wordSpacing = (s != null ? Integer.parseInt(s) : 0); int[] dx = XMLUtil.getAttributeAsIntArray(lastAttributes, "dx"); + int[][] dp = XMLUtil.getAttributeAsPositionAdjustments(lastAttributes, "dp"); + // if only DX present, then convert DX to DP; otherwise use only DP, + // effectively ignoring DX + if ( ( dp == null ) && ( dx != null ) ) { + dp = IFUtil.convertDXToDP ( dx ); + } establishStructureTreeElement(lastAttributes); - painter.drawText(x, y, letterSpacing, wordSpacing, dx, content.toString()); + painter.drawText(x, y, letterSpacing, wordSpacing, dp, content.toString()); resetStructureTreeElement(); } @@ -679,7 +685,7 @@ public class IFParser implements IFConstants { } - private static final String[] SIDES = new String[] {"before", "after", "start", "end"}; + private static final String[] SIDES = new String[] {"top", "bottom", "left", "right"}; private class BorderRectHandler extends AbstractElementHandler { diff --git a/src/java/org/apache/fop/render/intermediate/IFRenderer.java b/src/java/org/apache/fop/render/intermediate/IFRenderer.java index 4fec6c623..2987a4be8 100644 --- a/src/java/org/apache/fop/render/intermediate/IFRenderer.java +++ b/src/java/org/apache/fop/render/intermediate/IFRenderer.java @@ -61,6 +61,7 @@ import org.apache.fop.area.BlockViewport; import org.apache.fop.area.BookmarkData; import org.apache.fop.area.CTM; import org.apache.fop.area.DestinationData; +import org.apache.fop.area.LineArea; import org.apache.fop.area.OffDocumentExtensionAttachment; import org.apache.fop.area.OffDocumentItem; import org.apache.fop.area.PageSequence; @@ -488,7 +489,8 @@ public class IFRenderer extends AbstractPathOrientedRenderer { if (hasDocumentNavigation() && id != null) { int extraMarginBefore = 5000; // millipoints int ipp = currentIPPosition; - int bpp = currentBPPosition + inlineArea.getOffset() - extraMarginBefore; + int bpp = currentBPPosition + + inlineArea.getBlockProgressionOffset() - extraMarginBefore; saveAbsolutePosition(id, ipp, bpp); } } @@ -919,7 +921,7 @@ public class IFRenderer extends AbstractPathOrientedRenderer { AbstractAction action = null; // make sure the rect is determined *before* calling super! int ipp = currentIPPosition; - int bpp = currentBPPosition + ip.getOffset(); + int bpp = currentBPPosition + ip.getBlockProgressionOffset(); ipRect = new Rectangle(ipp, bpp, ip.getIPD(), ip.getBPD()); AffineTransform transform = graphicContext.getTransform(); ipRect = transform.createTransformedShape(ipRect).getBounds(); @@ -1031,7 +1033,7 @@ public class IFRenderer extends AbstractPathOrientedRenderer { } int rx = currentIPPosition + text.getBorderAndPaddingWidthStart(); - int bl = currentBPPosition + text.getOffset() + text.getBaselineOffset(); + int bl = currentBPPosition + text.getBlockProgressionOffset() + text.getBaselineOffset(); textUtil.flush(); textUtil.setStartPosition(rx, bl); textUtil.setSpacing(text.getTextLetterSpaceAdjust(), text.getTextWordSpaceAdjust()); @@ -1047,7 +1049,12 @@ public class IFRenderer extends AbstractPathOrientedRenderer { Font font = getFontFromArea(word.getParentArea()); String s = word.getWord(); - renderText(s, word.getLetterAdjustArray(), + int[][] dp = word.getGlyphPositionAdjustments(); + if ( dp == null ) { + dp = IFUtil.convertDXToDP ( word.getLetterAdjustArray() ); + } + + renderText(s, dp, word.isReversed(), font, (AbstractTextArea)word.getParentArea()); super.renderWord(word); @@ -1059,7 +1066,7 @@ public class IFRenderer extends AbstractPathOrientedRenderer { String s = space.getSpace(); AbstractTextArea textArea = (AbstractTextArea)space.getParentArea(); - renderText(s, null, font, textArea); + renderText(s, null, false, font, textArea); if (textUtil.combined && space.isAdjustable()) { //Used for justified text, for example @@ -1072,24 +1079,32 @@ public class IFRenderer extends AbstractPathOrientedRenderer { super.renderSpace(space); } + private void renderText(String s, + int[][] dp, boolean reversed, + Font font, AbstractTextArea parentArea) { + if ( ( dp == null ) || IFUtil.isDPOnlyDX ( dp ) ) { + int[] dx = IFUtil.convertDPToDX ( dp ); + renderTextWithAdjustments ( s, dx, reversed, font, parentArea ); + } else { + renderTextWithAdjustments ( s, dp, reversed, font, parentArea ); + } + } + /** - * Does low-level rendering of text. + * Does low-level rendering of text using DX only position adjustments. * @param s text to render - * @param letterAdjust an array of widths for letter adjustment (may be null) + * @param dx an array of widths for letter adjustment (may be null) + * @param reversed if true then text has been reversed (from logical order) * @param font to font in use * @param parentArea the parent text area to retrieve certain traits from */ - protected void renderText(String s, - int[] letterAdjust, - Font font, AbstractTextArea parentArea) { + private void renderTextWithAdjustments(String s, + int[] dx, boolean reversed, + Font font, AbstractTextArea parentArea) { int l = s.length(); if (l == 0) { return; } - - if (letterAdjust != null) { - textUtil.adjust(letterAdjust[0]); - } for (int i = 0; i < l; i++) { char ch = s.charAt(i); textUtil.addChar(ch); @@ -1098,18 +1113,38 @@ public class IFRenderer extends AbstractPathOrientedRenderer { int tls = (i < l - 1 ? parentArea.getTextLetterSpaceAdjust() : 0); glyphAdjust += tls; } - if (letterAdjust != null && i < l - 1) { - glyphAdjust += letterAdjust[i + 1]; + if (dx != null && i < l) { + glyphAdjust += dx[i]; } - textUtil.adjust(glyphAdjust); } } + /** + * Does low-level rendering of text using generalized position adjustments. + * @param s text to render + * @param dp an array of 4-tuples, expressing [X,Y] placment + * adjustments and [X,Y] advancement adjustments, in that order (may be null) + * @param reversed if true then text has been reversed (from logical order) + * @param font to font in use + * @param parentArea the parent text area to retrieve certain traits from + */ + private void renderTextWithAdjustments(String s, + int[][] dp, boolean reversed, + Font font, AbstractTextArea parentArea) { + assert !textUtil.combined; + for ( int i = 0, n = s.length(); i < n; i++ ) { + textUtil.addChar ( s.charAt ( i ) ); + if ( dp != null ) { + textUtil.adjust ( dp[i] ); + } + } + } + private class TextUtil { private static final int INITIAL_BUFFER_SIZE = 16; - private int[] dx = new int[INITIAL_BUFFER_SIZE]; - private int lastDXPos = 0; + private int[][] dp = new int[INITIAL_BUFFER_SIZE][4]; + // private int lastDPPos = 0; // TBD - not yet used private final StringBuffer text = new StringBuffer(); private int startx, starty; private int tls, tws; @@ -1119,25 +1154,41 @@ public class IFRenderer extends AbstractPathOrientedRenderer { text.append(ch); } - void adjust(int adjust) { - if (adjust != 0) { + void adjust(int dx) { + adjust ( new int[] { + dx, // xPlaAdjust + 0, // yPlaAdjust + dx, // xAdvAdjust + 0 // yAdvAdjust + } ); + } + + void adjust(int[] pa) { + if ( !IFUtil.isPAIdentity ( pa ) ) { int idx = text.length(); - if (idx > dx.length - 1) { - int newSize = Math.max(dx.length, idx + 1) + INITIAL_BUFFER_SIZE; - int[] newDX = new int[newSize]; - System.arraycopy(dx, 0, newDX, 0, dx.length); - dx = newDX; + if (idx > dp.length - 1) { + int newSize = Math.max(dp.length, idx + 1) + INITIAL_BUFFER_SIZE; + int[][] newDP = new int[newSize][]; + // reuse prior PA[0]...PA[dp.length-1] + System.arraycopy(dp, 0, newDP, 0, dp.length); + // populate new PA[dp.length]...PA[newDP.length-1] + for ( int i = dp.length, n = newDP.length; i < n; i++ ) { + newDP[i] = new int[4]; + } + dp = newDP; } - dx[idx] += adjust; - lastDXPos = idx; + IFUtil.adjustPA ( dp[idx - 1], pa ); + // lastDPPos = idx; } } void reset() { if (text.length() > 0) { text.setLength(0); - Arrays.fill(dx, 0); - lastDXPos = 0; + for ( int i = 0, n = dp.length; i < n; i++ ) { + Arrays.fill(dp[i], 0); + } + // lastDPPos = 0; } } @@ -1154,16 +1205,12 @@ public class IFRenderer extends AbstractPathOrientedRenderer { void flush() { if (text.length() > 0) { try { - int[] effDX = null; - if (lastDXPos > 0) { - int size = lastDXPos + 1; - effDX = new int[size]; - System.arraycopy(dx, 0, effDX, 0, size); - } if (combined) { - painter.drawText(startx, starty, 0, 0, effDX, text.toString()); + painter.drawText(startx, starty, 0, 0, + trimAdjustments ( dp, text.length() ), text.toString()); } else { - painter.drawText(startx, starty, tls, tws, effDX, text.toString()); + painter.drawText(startx, starty, tls, tws, + trimAdjustments ( dp, text.length() ), text.toString()); } } catch (IFException e) { handleIFException(e); @@ -1171,6 +1218,38 @@ public class IFRenderer extends AbstractPathOrientedRenderer { reset(); } } + + /** + * Trim adjustments array dp to be no greater length than + * text length, and where trailing all-zero entries are removed. + * @param dp a position adjustments array (or null) + * @param textLength the length of the associated text + * @return either the original value of dp or a copy + * of its first N significant adjustment entries, such that N is + * no greater than text length, and the last entry has a non-zero + * adjustment. + */ + private int[][] trimAdjustments ( int[][] dp, int textLength ) { + if ( dp != null ) { + int tl = textLength; + int pl = dp.length; + int i = ( tl < pl ) ? tl : pl; + while ( i > 0 ) { + int[] pa = dp [ i - 1 ]; + if ( !IFUtil.isPAIdentity ( pa ) ) { + break; + } else { + i--; + } + } + if ( i == 0 ) { + dp = null; + } else if ( i < pl ) { + dp = IFUtil.copyDP ( dp, 0, i ); + } + } + return dp; + } } /** {@inheritDoc} */ @@ -1220,7 +1299,7 @@ public class IFRenderer extends AbstractPathOrientedRenderer { int style = area.getRuleStyle(); int ruleThickness = area.getRuleThickness(); int startx = currentIPPosition + area.getBorderAndPaddingWidthStart(); - int starty = currentBPPosition + area.getOffset() + (ruleThickness / 2); + int starty = currentBPPosition + area.getBlockProgressionOffset() + (ruleThickness / 2); int endx = currentIPPosition + area.getBorderAndPaddingWidthStart() + area.getIPD(); @@ -1262,10 +1341,21 @@ public class IFRenderer extends AbstractPathOrientedRenderer { float startx, float starty, float width, float height, BorderProps bpsBefore, BorderProps bpsAfter, - BorderProps bpsStart, BorderProps bpsEnd) { + BorderProps bpsStart, BorderProps bpsEnd, int level) { Rectangle rect = toMillipointRectangle(startx, starty, width, height); try { - painter.drawBorderRect(rect, bpsBefore, bpsAfter, bpsStart, bpsEnd); + BorderProps bpsTop = bpsBefore; + BorderProps bpsBottom = bpsAfter; + BorderProps bpsLeft; + BorderProps bpsRight; + if ( ( level == -1 ) || ( ( level & 1 ) == 0 ) ) { + bpsLeft = bpsStart; + bpsRight = bpsEnd; + } else { + bpsLeft = bpsEnd; + bpsRight = bpsStart; + } + painter.drawBorderRect(rect, bpsTop, bpsBottom, bpsLeft, bpsRight); } catch (IFException ife) { handleIFException(ife); } diff --git a/src/java/org/apache/fop/render/intermediate/IFSerializer.java b/src/java/org/apache/fop/render/intermediate/IFSerializer.java index 7b9d95849..f8f286cb3 100644 --- a/src/java/org/apache/fop/render/intermediate/IFSerializer.java +++ b/src/java/org/apache/fop/render/intermediate/IFSerializer.java @@ -521,9 +521,9 @@ public class IFSerializer extends AbstractXMLWritingIFDocumentHandler } /** {@inheritDoc} */ - public void drawBorderRect(Rectangle rect, BorderProps before, BorderProps after, - BorderProps start, BorderProps end) throws IFException { - if (before == null && after == null && start == null && end == null) { + public void drawBorderRect(Rectangle rect, BorderProps top, BorderProps bottom, + BorderProps left, BorderProps right) throws IFException { + if (top == null && bottom == null && left == null && right == null) { return; } try { @@ -532,17 +532,17 @@ public class IFSerializer extends AbstractXMLWritingIFDocumentHandler addAttribute(atts, "y", Integer.toString(rect.y)); addAttribute(atts, "width", Integer.toString(rect.width)); addAttribute(atts, "height", Integer.toString(rect.height)); - if (before != null) { - addAttribute(atts, "before", before.toString()); + if (top != null) { + addAttribute(atts, "top", top.toString()); } - if (after != null) { - addAttribute(atts, "after", after.toString()); + if (bottom != null) { + addAttribute(atts, "bottom", bottom.toString()); } - if (start != null) { - addAttribute(atts, "start", start.toString()); + if (left != null) { + addAttribute(atts, "left", left.toString()); } - if (end != null) { - addAttribute(atts, "end", end.toString()); + if (right != null) { + addAttribute(atts, "right", right.toString()); } handler.element(EL_BORDER_RECT, atts); } catch (SAXException e) { @@ -571,7 +571,7 @@ public class IFSerializer extends AbstractXMLWritingIFDocumentHandler /** {@inheritDoc} */ public void drawText(int x, int y, int letterSpacing, int wordSpacing, - int[] dx, String text) throws IFException { + int[][] dp, String text) throws IFException { try { addID(); AttributesImpl atts = new AttributesImpl(); @@ -583,8 +583,17 @@ public class IFSerializer extends AbstractXMLWritingIFDocumentHandler if (wordSpacing != 0) { addAttribute(atts, "word-spacing", Integer.toString(wordSpacing)); } - if (dx != null) { - addAttribute(atts, "dx", IFUtil.toString(dx)); + if (dp != null) { + if ( IFUtil.isDPIdentity(dp) ) { + // don't add dx or dp attribute + } else if ( IFUtil.isDPOnlyDX(dp) ) { + // add dx attribute only + int[] dx = IFUtil.convertDPToDX(dp); + addAttribute(atts, "dx", IFUtil.toString(dx)); + } else { + // add dp attribute only + addAttribute(atts, "dp", XMLUtil.encodePositionAdjustments(dp)); + } } addStructureReference(atts); handler.startElement(EL_TEXT, atts); diff --git a/src/java/org/apache/fop/render/intermediate/IFUtil.java b/src/java/org/apache/fop/render/intermediate/IFUtil.java index 1867b0294..86991ecb1 100644 --- a/src/java/org/apache/fop/render/intermediate/IFUtil.java +++ b/src/java/org/apache/fop/render/intermediate/IFUtil.java @@ -199,4 +199,182 @@ public final class IFUtil { return documentHandler.getMimeType(); } + /** + * Convert the general gpos 'dp' adjustments to the older 'dx' adjustments. + * This utility method is used to provide backward compatibility in implementations + * of IFPainter that have not yet been upgraded to the general position adjustments format. + * @param dp an array of 4-tuples, expressing [X,Y] placment + * adjustments and [X,Y] advancement adjustments, in that order (may be null) + * @param count if dp is not null, then a count of dp values to convert + * @return if dp is not null, then an array of adjustments to the current + * x position prior to rendering individual glyphs; otherwise, null + */ + public static int[] convertDPToDX ( int[][] dp, int count ) { + int[] dx; + if ( dp != null ) { + dx = new int [ count ]; + for ( int i = 0, n = count; i < n; i++ ) { + dx [ i ] = dp [ i ] [ 0 ]; // xPlaAdjust[i] + } + } else { + dx = null; + } + return dx; + } + + /** + * Convert the general gpos 'dp' adjustments to the older 'dx' adjustments. + * This utility method is used to provide backward compatibility in implementations + * of IFPainter that have not yet been upgraded to the general position adjustments format. + * @param dp an array of 4-tuples, expressing [X,Y] placment + * adjustments and [X,Y] advancement adjustments, in that order (may be null) + * @return if dp is not null, then an array of adjustments to the current + * x position prior to rendering individual glyphs; otherwise, null + */ + public static int[] convertDPToDX ( int[][] dp ) { + return convertDPToDX ( dp, ( dp != null ) ? dp.length : 0 ); + } + + /** + * Convert the general gpos 'dp' adjustments to the older 'dx' adjustments. + * This utility method is used to provide backward compatibility in implementations + * of IFPainter that have not yet been upgraded to the general position adjustments format. + * @param dx an array of adjustments to the current x position prior to rendering + * individual glyphs or null + * @param count if dx is not null, then a count of dx values to convert + * @return if dx is not null, then an array of 4-tuples, expressing [X,Y] + * placment adjustments and [X,Y] advancement adjustments, in that order; otherwise, null + */ + public static int[][] convertDXToDP ( int[] dx, int count ) { + int[][] dp; + if ( dx != null ) { + dp = new int [ count ] [ 4 ]; + for ( int i = 0, n = count; i < n; i++ ) { + int[] pa = dp [ i ]; + int d = dx [ i ]; + pa [ 0 ] = d; // xPlaAdjust[i] + pa [ 2 ] = d; // xAdvAdjust[i] + } + } else { + dp = null; + } + return dp; + } + + /** + * Convert the general gpos 'dp' adjustments to the older 'dx' adjustments. + * This utility method is used to provide backward compatibility in implementations + * of IFPainter that have not yet been upgraded to the general position adjustments format. + * @param dx an array of adjustments to the current x position prior to rendering + * individual glyphs or null + * @return if dx is not null, then an array of 4-tuples, expressing [X,Y] + * placment adjustments and [X,Y] advancement adjustments, in that order; otherwise, null + */ + public static int[][] convertDXToDP ( int[] dx ) { + return convertDXToDP ( dx, ( dx != null ) ? dx.length : 0 ); + } + + /** + * Determine if position adjustment is the identity adjustment, i.e., no non-zero adjustment. + * @param pa a 4-tuple, expressing [X,Y] placment and [X,Y] advance adjuustments (may be null) + * @return true if dp is null or contains no non-zero adjustment + */ + public static boolean isPAIdentity ( int[] pa ) { + if ( pa == null ) { + return true; + } else { + for ( int k = 0; k < 4; k++ ) { + if ( pa[k] != 0 ) { + return false; + } + } + return true; + } + } + + /** + * Determine if position adjustments is the identity adjustment, i.e., no non-zero adjustment. + * @param dp an array of 4-tuples, expressing [X,Y] placment + * adjustments and [X,Y] advancement adjustments, in that order (may be null) + * @return true if dp is null or contains no non-zero adjustment + */ + public static boolean isDPIdentity ( int[][] dp ) { + if ( dp == null ) { + return true; + } else { + for ( int i = 0, n = dp.length; i < n; i++ ) { + if ( !isPAIdentity ( dp[i] ) ) { + return false; + } + } + return true; + } + } + + /** + * Determine if position adjustments comprises only DX adjustments as encoded by + * {@link #convertDPToDX}. Note that if given a set of all all zero position + * adjustments, both this method and {@link #isDPIdentity} will return true; + * however, this method may return true when {@link #isDPIdentity} returns false. + * @param dp an array of 4-tuples, expressing [X,Y] placment + * adjustments and [X,Y] advancement adjustments, in that order (may be null) + * @return true if dp is not null and contains only xPlaAdjust + * and xAdvAdjust values consistent with the output of {@link #convertDPToDX}. + */ + public static boolean isDPOnlyDX ( int[][] dp ) { + if ( dp == null ) { + return false; + } else { + for ( int i = 0, n = dp.length; i < n; i++ ) { + int[] pa = dp[i]; + if ( pa[0] != pa[2] ) { + return false; + } + } + return true; + } + } + + /** + * Adjust a position adjustments array. If both paDst and paSrc are + * non-null, then paSrc[i] is added to paDst[i]. + * @param paDst a 4-tuple, expressing [X,Y] placment + * and [X,Y] advance adjuustments (may be null) + * @param paSrc a 4-tuple, expressing [X,Y] placment + * and [X,Y] advance adjuustments (may be null) + */ + public static void adjustPA ( int[] paDst, int[] paSrc ) { + if ( ( paDst != null ) && ( paSrc != null ) ) { + assert paDst.length == 4; assert paSrc.length == 4; + for ( int i = 0; i < 4; i++ ) { + paDst[i] += paSrc[i]; + } + } + } + + /** + * Copy entries from position adjustments. + * @param dp an array of 4-tuples, expressing [X,Y] placment + * adjustments and [X,Y] advancement adjustments, in that order + * @param offset starting offset from which to copy + * @param count number of entries to copy + * @return a deep copy of the count position adjustment entries start at + * offset + */ + public static int[][] copyDP ( int[][] dp, int offset, int count ) { + if ( ( dp == null ) || ( offset > dp.length ) || ( ( offset + count ) > dp.length ) ) { + throw new IllegalArgumentException(); + } else { + int[][] dpNew = new int [ count ] [ 4 ]; + for ( int i = 0, n = count; i < n; i++ ) { + int[] paDst = dpNew [ i ]; + int[] paSrc = dp [ i + offset ]; + for ( int k = 0; k < 4; k++ ) { + paDst [ k ] = paSrc [ k ]; + } + } + return dpNew; + } + } + } diff --git a/src/java/org/apache/fop/render/java2d/ConfiguredFontCollection.java b/src/java/org/apache/fop/render/java2d/ConfiguredFontCollection.java index fb88b8bce..7ac350d5d 100644 --- a/src/java/org/apache/fop/render/java2d/ConfiguredFontCollection.java +++ b/src/java/org/apache/fop/render/java2d/ConfiguredFontCollection.java @@ -51,13 +51,14 @@ public class ConfiguredFontCollection implements FontCollection { * Main constructor * @param fontResolver a font resolver * @param customFonts the list of custom fonts + * @param useComplexScriptFeatures true if complex script features enabled */ public ConfiguredFontCollection(FontResolver fontResolver, - List/**/ customFonts) { + List/**/ customFonts, boolean useComplexScriptFeatures) { this.fontResolver = fontResolver; if (this.fontResolver == null) { //Ensure that we have minimal font resolution capabilities - this.fontResolver = FontManager.createMinimalFontResolver(); + this.fontResolver = FontManager.createMinimalFontResolver(useComplexScriptFeatures); } this.embedFontInfoList = customFonts; } @@ -89,7 +90,8 @@ public class ConfiguredFontCollection implements FontCollection { } else { CustomFont fontMetrics = FontLoader.loadFont( fontFile, null, true, EncodingMode.AUTO, - configFontInfo.getKerning(), fontResolver); + configFontInfo.getKerning(), + configFontInfo.getAdvanced(), fontResolver); font = new CustomFontMetricsMapper(fontMetrics); } diff --git a/src/java/org/apache/fop/render/java2d/Java2DPainter.java b/src/java/org/apache/fop/render/java2d/Java2DPainter.java index 396645768..c7fa1adc5 100644 --- a/src/java/org/apache/fop/render/java2d/Java2DPainter.java +++ b/src/java/org/apache/fop/render/java2d/Java2DPainter.java @@ -42,6 +42,7 @@ import org.apache.fop.render.intermediate.IFContext; import org.apache.fop.render.intermediate.IFException; import org.apache.fop.render.intermediate.IFPainter; import org.apache.fop.render.intermediate.IFState; +import org.apache.fop.render.intermediate.IFUtil; import org.apache.fop.traits.BorderProps; import org.apache.fop.traits.RuleStyle; import org.apache.fop.util.CharUtilities; @@ -184,11 +185,11 @@ public class Java2DPainter extends AbstractIFPainter { } /** {@inheritDoc} */ - public void drawBorderRect(Rectangle rect, BorderProps before, BorderProps after, - BorderProps start, BorderProps end) throws IFException { - if (before != null || after != null || start != null || end != null) { + public void drawBorderRect(Rectangle rect, BorderProps top, BorderProps bottom, + BorderProps left, BorderProps right) throws IFException { + if (top != null || bottom != null || left != null || right != null) { try { - this.borderPainter.drawBorders(rect, before, after, start, end); + this.borderPainter.drawBorders(rect, top, bottom, left, right); } catch (IOException e) { //Won't happen with Java2D throw new IllegalStateException("Unexpected I/O error"); @@ -203,7 +204,7 @@ public class Java2DPainter extends AbstractIFPainter { } /** {@inheritDoc} */ - public void drawText(int x, int y, int letterSpacing, int wordSpacing, int[] dx, String text) + public void drawText(int x, int y, int letterSpacing, int wordSpacing, int[][] dp, String text) throws IFException { g2dState.updateColor(state.getTextColor()); FontTriplet triplet = new FontTriplet( @@ -220,6 +221,7 @@ public class Java2DPainter extends AbstractIFPainter { Point2D cursor = new Point2D.Float(0, 0); int l = text.length(); + int[] dx = IFUtil.convertDPToDX ( dp ); int dxl = (dx != null ? dx.length : 0); if (dx != null && dxl > 0 && dx[0] != 0) { diff --git a/src/java/org/apache/fop/render/java2d/Java2DRenderer.java b/src/java/org/apache/fop/render/java2d/Java2DRenderer.java index 1d1697607..45c91b2ee 100644 --- a/src/java/org/apache/fop/render/java2d/Java2DRenderer.java +++ b/src/java/org/apache/fop/render/java2d/Java2DRenderer.java @@ -178,7 +178,8 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem FontCollection[] fontCollections = new FontCollection[] { new Base14FontCollection(java2DFontMetrics), new InstalledFontCollection(java2DFontMetrics), - new ConfiguredFontCollection(getFontResolver(), getFontList()) + new ConfiguredFontCollection(getFontResolver(), getFontList(), + userAgent.isComplexScriptFeaturesEnabled()) }; userAgent.getFactory().getFontManager().setup( getFontInfo(), fontCollections); @@ -715,7 +716,7 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem renderInlineAreaBackAndBorders(text); int rx = currentIPPosition + text.getBorderAndPaddingWidthStart(); - int bl = currentBPPosition + text.getOffset() + text.getBaselineOffset(); + int bl = currentBPPosition + text.getBlockProgressionOffset() + text.getBaselineOffset(); int saveIP = currentIPPosition; Font font = getFontFromArea(text); @@ -827,7 +828,7 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem // TODO Colors do not work on Leaders yet float startx = (currentIPPosition + area.getBorderAndPaddingWidthStart()) / 1000f; - float starty = ((currentBPPosition + area.getOffset()) / 1000f); + float starty = ((currentBPPosition + area.getBlockProgressionOffset()) / 1000f); float endx = (currentIPPosition + area.getBorderAndPaddingWidthStart() + area.getIPD()) / 1000f; diff --git a/src/java/org/apache/fop/render/pcl/PCLPainter.java b/src/java/org/apache/fop/render/pcl/PCLPainter.java index afae8ac27..53e3d77da 100644 --- a/src/java/org/apache/fop/render/pcl/PCLPainter.java +++ b/src/java/org/apache/fop/render/pcl/PCLPainter.java @@ -51,6 +51,7 @@ import org.apache.fop.render.intermediate.IFContext; import org.apache.fop.render.intermediate.IFException; import org.apache.fop.render.intermediate.IFPainter; import org.apache.fop.render.intermediate.IFState; +import org.apache.fop.render.intermediate.IFUtil; import org.apache.fop.render.java2d.FontMetricsMapper; import org.apache.fop.render.java2d.Java2DPainter; import org.apache.fop.traits.BorderProps; @@ -206,13 +207,13 @@ public class PCLPainter extends AbstractIFPainter implements PCLConstants { /** {@inheritDoc} */ public void drawBorderRect(final Rectangle rect, - final BorderProps before, final BorderProps after, - final BorderProps start, final BorderProps end) throws IFException { + final BorderProps top, final BorderProps bottom, + final BorderProps left, final BorderProps right) throws IFException { if (isSpeedOptimized()) { - super.drawBorderRect(rect, before, after, start, end); + super.drawBorderRect(rect, top, bottom, left, right); return; } - if (before != null || after != null || start != null || end != null) { + if (top != null || bottom != null || left != null || right != null) { final Rectangle boundingBox = rect; final Dimension dim = boundingBox.getSize(); @@ -224,7 +225,7 @@ public class PCLPainter extends AbstractIFPainter implements PCLConstants { Java2DPainter painter = new Java2DPainter(g2d, getContext(), parent.getFontInfo(), state); try { - painter.drawBorderRect(rect, before, after, start, end); + painter.drawBorderRect(rect, top, bottom, left, right); } catch (IFException e) { //This should never happen with the Java2DPainter throw new RuntimeException("Unexpected error while painting borders", e); @@ -307,7 +308,7 @@ public class PCLPainter extends AbstractIFPainter implements PCLConstants { } /** {@inheritDoc} */ - public void drawText(int x, int y, int letterSpacing, int wordSpacing, int[] dx, String text) + public void drawText(int x, int y, int letterSpacing, int wordSpacing, int[][] dp, String text) throws IFException { try { FontTriplet triplet = new FontTriplet( @@ -319,13 +320,13 @@ public class PCLPainter extends AbstractIFPainter implements PCLConstants { ? false : HardcodedFonts.setFont(gen, fontKey, state.getFontSize(), text); if (pclFont) { - drawTextNative(x, y, letterSpacing, wordSpacing, dx, text, triplet); + drawTextNative(x, y, letterSpacing, wordSpacing, dp, text, triplet); } else { - drawTextAsBitmap(x, y, letterSpacing, wordSpacing, dx, text, triplet); + drawTextAsBitmap(x, y, letterSpacing, wordSpacing, dp, text, triplet); if (DEBUG) { state.setTextColor(Color.GRAY); HardcodedFonts.setFont(gen, "F1", state.getFontSize(), text); - drawTextNative(x, y, letterSpacing, wordSpacing, dx, text, triplet); + drawTextNative(x, y, letterSpacing, wordSpacing, dp, text, triplet); } } } catch (IOException ioe) { @@ -333,7 +334,7 @@ public class PCLPainter extends AbstractIFPainter implements PCLConstants { } } - private void drawTextNative(int x, int y, int letterSpacing, int wordSpacing, int[] dx, + private void drawTextNative(int x, int y, int letterSpacing, int wordSpacing, int[][] dp, String text, FontTriplet triplet) throws IOException { Color textColor = state.getTextColor(); if (textColor != null) { @@ -347,6 +348,7 @@ public class PCLPainter extends AbstractIFPainter implements PCLConstants { float fontSize = state.getFontSize() / 1000f; Font font = parent.getFontInfo().getFontInstance(triplet, state.getFontSize()); int l = text.length(); + int[] dx = IFUtil.convertDPToDX ( dp ); int dxl = (dx != null ? dx.length : 0); StringBuffer sb = new StringBuffer(Math.max(16, l)); @@ -392,7 +394,7 @@ public class PCLPainter extends AbstractIFPainter implements PCLConstants { private Rectangle getTextBoundingBox( // CSOK: ParameterNumber int x, int y, - int letterSpacing, int wordSpacing, int[] dx, + int letterSpacing, int wordSpacing, int[][] dp, String text, Font font, FontMetricsMapper metrics) { int maxAscent = metrics.getMaxAscent(font.getFontSize()) / 1000; @@ -403,6 +405,7 @@ public class PCLPainter extends AbstractIFPainter implements PCLConstants { 0, maxAscent - descent + 2 * safetyMargin); int l = text.length(); + int[] dx = IFUtil.convertDPToDX ( dp ); int dxl = (dx != null ? dx.length : 0); if (dx != null && dxl > 0 && dx[0] != 0) { @@ -432,7 +435,7 @@ public class PCLPainter extends AbstractIFPainter implements PCLConstants { } private void drawTextAsBitmap(final int x, final int y, - final int letterSpacing, final int wordSpacing, final int[] dx, + final int letterSpacing, final int wordSpacing, final int[][] dp, final String text, FontTriplet triplet) throws IFException { //Use Java2D to paint different fonts via bitmap final Font font = parent.getFontInfo().getFontInstance(triplet, state.getFontSize()); @@ -447,7 +450,7 @@ public class PCLPainter extends AbstractIFPainter implements PCLConstants { final int baselineOffset = maxAscent + safetyMargin; final Rectangle boundingBox = getTextBoundingBox(x, y, - letterSpacing, wordSpacing, dx, text, font, mapper); + letterSpacing, wordSpacing, dp, text, font, mapper); final Dimension dim = boundingBox.getSize(); Graphics2DImagePainter painter = new Graphics2DImagePainter() { @@ -470,7 +473,7 @@ public class PCLPainter extends AbstractIFPainter implements PCLConstants { Java2DPainter painter = new Java2DPainter(g2d, getContext(), parent.getFontInfo(), state); try { - painter.drawText(x, y, letterSpacing, wordSpacing, dx, text); + painter.drawText(x, y, letterSpacing, wordSpacing, dp, text); } catch (IFException e) { //This should never happen with the Java2DPainter throw new RuntimeException("Unexpected error while painting text", e); diff --git a/src/java/org/apache/fop/render/pcl/PCLRendererConfigurator.java b/src/java/org/apache/fop/render/pcl/PCLRendererConfigurator.java index 605220ee2..84608b685 100644 --- a/src/java/org/apache/fop/render/pcl/PCLRendererConfigurator.java +++ b/src/java/org/apache/fop/render/pcl/PCLRendererConfigurator.java @@ -119,7 +119,8 @@ public class PCLRendererConfigurator extends PrintRendererConfigurator FontEventListener listener = new FontEventAdapter( userAgent.getEventBroadcaster()); List fontList = buildFontList(cfg, fontResolver, listener); - fontCollections.add(new ConfiguredFontCollection(fontResolver, fontList)); + fontCollections.add(new ConfiguredFontCollection(fontResolver, fontList, + userAgent.isComplexScriptFeaturesEnabled())); } fontManager.setup(fontInfo, diff --git a/src/java/org/apache/fop/render/pdf/PDFPainter.java b/src/java/org/apache/fop/render/pdf/PDFPainter.java index f2fbfd014..4928e7251 100644 --- a/src/java/org/apache/fop/render/pdf/PDFPainter.java +++ b/src/java/org/apache/fop/render/pdf/PDFPainter.java @@ -45,8 +45,10 @@ import org.apache.fop.render.intermediate.AbstractIFPainter; import org.apache.fop.render.intermediate.IFContext; import org.apache.fop.render.intermediate.IFException; import org.apache.fop.render.intermediate.IFState; +import org.apache.fop.render.intermediate.IFUtil; import org.apache.fop.render.pdf.PDFLogicalStructureHandler.MarkedContentInfo; import org.apache.fop.traits.BorderProps; +import org.apache.fop.traits.Direction; import org.apache.fop.traits.RuleStyle; import org.apache.fop.util.CharUtilities; @@ -259,12 +261,12 @@ public class PDFPainter extends AbstractIFPainter { /** {@inheritDoc} */ @Override - public void drawBorderRect(Rectangle rect, BorderProps before, BorderProps after, - BorderProps start, BorderProps end) throws IFException { - if (before != null || after != null || start != null || end != null) { + public void drawBorderRect(Rectangle rect, BorderProps top, BorderProps bottom, + BorderProps left, BorderProps right) throws IFException { + if (top != null || bottom != null || left != null || right != null) { generator.endTextObject(); try { - this.borderPainter.drawBorders(rect, before, after, start, end); + this.borderPainter.drawBorders(rect, top, bottom, left, right); } catch (IOException ioe) { throw new IFException("I/O error while drawing borders", ioe); } @@ -291,7 +293,7 @@ public class PDFPainter extends AbstractIFPainter { } /** {@inheritDoc} */ - public void drawText(int x, int y, int letterSpacing, int wordSpacing, int[] dx, + public void drawText(int x, int y, int letterSpacing, int wordSpacing, int[][] dp, String text) throws IFException { if (accessEnabled) { @@ -309,6 +311,19 @@ public class PDFPainter extends AbstractIFPainter { FontTriplet triplet = new FontTriplet( state.getFontFamily(), state.getFontStyle(), state.getFontWeight()); + + if ( ( dp == null ) || IFUtil.isDPOnlyDX ( dp ) ) { + drawTextWithDX ( x, y, text, triplet, letterSpacing, + wordSpacing, IFUtil.convertDPToDX ( dp ) ); + } else { + drawTextWithDP ( x, y, text, triplet, letterSpacing, + wordSpacing, dp ); + } + } + + private void drawTextWithDX ( int x, int y, String text, FontTriplet triplet, + int letterSpacing, int wordSpacing, int[] dx ) { + //TODO Ignored: state.getFontVariant() //TODO Opportunity for font caching if font state is more heavily used String fontKey = getFontInfo().getInternalFontKey(triplet); @@ -375,6 +390,70 @@ public class PDFPainter extends AbstractIFPainter { textutil.writeTJ(); } + private static int[] paZero = new int[4]; + + private void drawTextWithDP ( int x, int y, String text, FontTriplet triplet, + int letterSpacing, int wordSpacing, int[][] dp ) { + assert text != null; + assert triplet != null; + assert dp != null; + String fk = getFontInfo().getInternalFontKey(triplet); + Typeface tf = getTypeface(fk); + if ( tf.isMultiByte() ) { + int fs = state.getFontSize(); + float fsPoints = fs / 1000f; + Font f = getFontInfo().getFontInstance(triplet, fs); + // String fn = f.getFontName(); + PDFTextUtil tu = generator.getTextUtil(); + double xc = 0f; + double yc = 0f; + double xoLast = 0f; + double yoLast = 0f; + double wox = wordSpacing; + tu.writeTextMatrix ( new AffineTransform ( 1, 0, 0, -1, x / 1000f, y / 1000f ) ); + tu.updateTf ( fk, fsPoints, true ); + generator.updateCharacterSpacing ( letterSpacing / 1000f ); + for ( int i = 0, n = text.length(); i < n; i++ ) { + char ch = text.charAt ( i ); + int[] pa = ( i < dp.length ) ? dp [ i ] : paZero; + double xo = xc + pa[0]; + double yo = yc + pa[1]; + double xa = f.getCharWidth(ch) + maybeWordOffsetX ( wox, ch, null ); + double ya = 0; + double xd = ( xo - xoLast ) / 1000f; + double yd = ( yo - yoLast ) / 1000f; + tu.writeTd ( xd, yd ); + tu.writeTj ( f.mapChar ( ch ) ); + xc += xa + pa[2]; + yc += ya + pa[3]; + xoLast = xo; + yoLast = yo; + } + } + } + + private double maybeWordOffsetX ( double wox, char ch, Direction dir ) { + if ( ( wox != 0 ) + && CharUtilities.isAdjustableSpace ( ch ) + && ( ( dir == null ) || dir.isHorizontal() ) ) { + return wox; + } else { + return 0; + } + } + + /* + private double maybeWordOffsetY ( double woy, char ch, Direction dir ) { + if ( ( woy != 0 ) + && CharUtilities.isAdjustableSpace ( ch ) && dir.isVertical() + && ( ( dir != null ) && dir.isVertical() ) ) { + return woy; + } else { + return 0; + } + } + */ + private char selectAndMapSingleByteFont(SingleByteFont singleByteFont, String fontName, float fontSize, PDFTextUtil textutil, char ch) { if (singleByteFont != null && singleByteFont.hasAdditionalEncodings()) { diff --git a/src/java/org/apache/fop/render/ps/AbstractPSTranscoder.java b/src/java/org/apache/fop/render/ps/AbstractPSTranscoder.java index 766c939f1..ad5090686 100644 --- a/src/java/org/apache/fop/render/ps/AbstractPSTranscoder.java +++ b/src/java/org/apache/fop/render/ps/AbstractPSTranscoder.java @@ -112,8 +112,9 @@ public abstract class AbstractPSTranscoder extends AbstractFOPTranscoder { graphics = createDocumentGraphics2D(); if (!isTextStroked()) { try { + boolean useComplexScriptFeatures = false; //TODO - FIX ME this.fontInfo = PDFDocumentGraphics2DConfigurator.createFontInfo( - getEffectiveConfiguration()); + getEffectiveConfiguration(), useComplexScriptFeatures); graphics.setCustomTextHandler(new NativeTextHandler(graphics, fontInfo)); } catch (FOPException fe) { throw new TranscoderException(fe); diff --git a/src/java/org/apache/fop/render/ps/NativeTextHandler.java b/src/java/org/apache/fop/render/ps/NativeTextHandler.java index 7cf59d519..e1171b3e1 100644 --- a/src/java/org/apache/fop/render/ps/NativeTextHandler.java +++ b/src/java/org/apache/fop/render/ps/NativeTextHandler.java @@ -73,7 +73,8 @@ public class NativeTextHandler implements PSTextHandler { private void setupFontInfo() { //Sets up a FontInfo with default fonts fontInfo = new FontInfo(); - FontSetup.setup(fontInfo); + boolean base14Kerning = false; + FontSetup.setup(fontInfo, base14Kerning); } /** diff --git a/src/java/org/apache/fop/render/ps/PSPainter.java b/src/java/org/apache/fop/render/ps/PSPainter.java index ef9239c2a..370472457 100644 --- a/src/java/org/apache/fop/render/ps/PSPainter.java +++ b/src/java/org/apache/fop/render/ps/PSPainter.java @@ -51,6 +51,7 @@ import org.apache.fop.render.intermediate.AbstractIFPainter; import org.apache.fop.render.intermediate.IFContext; import org.apache.fop.render.intermediate.IFException; import org.apache.fop.render.intermediate.IFState; +import org.apache.fop.render.intermediate.IFUtil; import org.apache.fop.traits.BorderProps; import org.apache.fop.traits.RuleStyle; import org.apache.fop.util.CharUtilities; @@ -234,16 +235,16 @@ public class PSPainter extends AbstractIFPainter { } /** {@inheritDoc} */ - public void drawBorderRect(Rectangle rect, BorderProps before, BorderProps after, - BorderProps start, BorderProps end) throws IFException { - if (before != null || after != null || start != null || end != null) { + public void drawBorderRect(Rectangle rect, BorderProps top, BorderProps bottom, + BorderProps left, BorderProps right) throws IFException { + if (top != null || bottom != null || left != null || right != null) { try { endTextObject(); if (getPSUtil().getRenderingMode() == PSRenderingMode.SIZE - && hasOnlySolidBorders(before, after, start, end)) { - super.drawBorderRect(rect, before, after, start, end); + && hasOnlySolidBorders(top, bottom, left, right)) { + super.drawBorderRect(rect, top, bottom, left, right); } else { - this.borderPainter.drawBorders(rect, before, after, start, end); + this.borderPainter.drawBorders(rect, top, bottom, left, right); } } catch (IOException ioe) { throw new IFException("I/O error in drawBorderRect()", ioe); @@ -343,9 +344,8 @@ public class PSPainter extends AbstractIFPainter { /** {@inheritDoc} */ public void drawText(int x, int y, int letterSpacing, int wordSpacing, - int[] dx, String text) throws IFException { + int[][] dp, String text) throws IFException { try { - //Note: dy is currently ignored PSGenerator generator = getGenerator(); generator.useColor(state.getTextColor()); beginTextObject(); @@ -383,8 +383,8 @@ public class PSPainter extends AbstractIFPainter { int encoding = mapped / 256; if (currentEncoding != encoding) { if (i > 0) { - writeText(text, start, i - start, letterSpacing, wordSpacing, dx, - font, tf); + writeText(text, start, i - start, + letterSpacing, wordSpacing, dp, font, tf); } if (encoding == 0) { useFont(fontKey, sizeMillipoints); @@ -399,7 +399,7 @@ public class PSPainter extends AbstractIFPainter { //Simple single-font painting useFont(fontKey, sizeMillipoints); } - writeText(text, start, textLen - start, letterSpacing, wordSpacing, dx, font, tf); + writeText(text, start, textLen - start, letterSpacing, wordSpacing, dp, font, tf); } catch (IOException ioe) { throw new IFException("I/O error in drawText()", ioe); } @@ -407,7 +407,7 @@ public class PSPainter extends AbstractIFPainter { private void writeText( // CSOK: ParameterNumber String text, int start, int len, - int letterSpacing, int wordSpacing, int[] dx, + int letterSpacing, int wordSpacing, int[][] dp, Font font, Typeface tf) throws IOException { PSGenerator generator = getGenerator(); int end = start + len; @@ -420,6 +420,7 @@ public class PSPainter extends AbstractIFPainter { int lineStart = 0; StringBuffer accText = new StringBuffer(initialSize); StringBuffer sb = new StringBuffer(initialSize); + int[] dx = IFUtil.convertDPToDX ( dp ); int dxl = (dx != null ? dx.length : 0); for (int i = start; i < end; i++) { char orgChar = text.charAt(i); diff --git a/src/java/org/apache/fop/render/rtf/RTFHandler.java b/src/java/org/apache/fop/render/rtf/RTFHandler.java index 22c0c8b76..95c4fec12 100644 --- a/src/java/org/apache/fop/render/rtf/RTFHandler.java +++ b/src/java/org/apache/fop/render/rtf/RTFHandler.java @@ -167,7 +167,8 @@ public class RTFHandler extends FOEventHandler { this.os = os; bDefer = true; - FontSetup.setup(fontInfo, null, new DefaultFontResolver(userAgent)); + boolean base14Kerning = false; + FontSetup.setup(fontInfo, null, new DefaultFontResolver(userAgent), base14Kerning); } /** diff --git a/src/java/org/apache/fop/render/xml/XMLRenderer.java b/src/java/org/apache/fop/render/xml/XMLRenderer.java index 504133c09..4ac650269 100644 --- a/src/java/org/apache/fop/render/xml/XMLRenderer.java +++ b/src/java/org/apache/fop/render/xml/XMLRenderer.java @@ -86,6 +86,7 @@ import org.apache.fop.render.Renderer; import org.apache.fop.render.RendererContext; import org.apache.fop.render.XMLHandler; import org.apache.fop.util.ColorUtil; +import org.apache.fop.util.XMLUtil; /** * Renderer that renders areas to XML for debugging purposes. @@ -157,6 +158,7 @@ public class XMLRenderer extends AbstractXMLRenderer { protected void addAreaAttributes(Area area) { addAttribute("ipd", area.getIPD()); addAttribute("bpd", area.getBPD()); + maybeAddLevelAttribute(area); if (isDetailedFormat()) { if (area.getIPD() != 0) { addAttribute("ipda", area.getAllocIPD()); @@ -708,7 +710,7 @@ public class XMLRenderer extends AbstractXMLRenderer { atts.clear(); addAreaAttributes(viewport); addTraitAttributes(viewport); - addAttribute("offset", viewport.getOffset()); + addAttribute("offset", viewport.getBlockProgressionOffset()); addAttribute("pos", viewport.getContentPosition()); if (viewport.hasClip()) { addAttribute("clip", "true"); @@ -770,7 +772,7 @@ public class XMLRenderer extends AbstractXMLRenderer { atts.clear(); addAreaAttributes(space); addTraitAttributes(space); - addAttribute("offset", space.getOffset()); + addAttribute("offset", space.getBlockProgressionOffset()); startElement("space", atts); endElement("space"); } @@ -787,7 +789,7 @@ public class XMLRenderer extends AbstractXMLRenderer { if (text.getTextLetterSpaceAdjust() != 0) { addAttribute("tlsadjust", text.getTextLetterSpaceAdjust()); } - addAttribute("offset", text.getOffset()); + addAttribute("offset", text.getBlockProgressionOffset()); addAttribute("baseline", text.getBaselineOffset()); addAreaAttributes(text); addTraitAttributes(text); @@ -802,7 +804,10 @@ public class XMLRenderer extends AbstractXMLRenderer { @Override protected void renderWord(WordArea word) { atts.clear(); - addAttribute("offset", word.getOffset()); + int offset = word.getBlockProgressionOffset(); + if ( offset != 0 ) { + addAttribute("offset", offset); + } int[] letterAdjust = word.getLetterAdjustArray(); if (letterAdjust != null) { StringBuffer sb = new StringBuffer(64); @@ -818,6 +823,11 @@ public class XMLRenderer extends AbstractXMLRenderer { addAttribute("letter-adjust", sb.toString()); } } + maybeAddLevelAttribute(word); + maybeAddPositionAdjustAttribute(word); + if ( word.isReversed() ) { + addAttribute("reversed", "true"); + } startElement("word", atts); characters(word.getWord()); endElement("word"); @@ -830,7 +840,11 @@ public class XMLRenderer extends AbstractXMLRenderer { @Override protected void renderSpace(SpaceArea space) { atts.clear(); - addAttribute("offset", space.getOffset()); + int offset = space.getBlockProgressionOffset(); + if ( offset != 0 ) { + addAttribute("offset", offset); + } + maybeAddLevelAttribute(space); if (!space.isAdjustable()) { addAttribute("adj", "false"); //default is true } @@ -848,7 +862,7 @@ public class XMLRenderer extends AbstractXMLRenderer { atts.clear(); addAreaAttributes(ip); addTraitAttributes(ip); - addAttribute("offset", ip.getOffset()); + addAttribute("offset", ip.getBlockProgressionOffset()); startElement("inlineparent", atts); super.renderInlineParent(ip); endElement("inlineparent"); @@ -862,7 +876,7 @@ public class XMLRenderer extends AbstractXMLRenderer { atts.clear(); addAreaAttributes(ibp); addTraitAttributes(ibp); - addAttribute("offset", ibp.getOffset()); + addAttribute("offset", ibp.getBlockProgressionOffset()); startElement("inlineblockparent", atts); super.renderInlineBlockParent(ibp); endElement("inlineblockparent"); @@ -876,7 +890,7 @@ public class XMLRenderer extends AbstractXMLRenderer { atts.clear(); addAreaAttributes(area); addTraitAttributes(area); - addAttribute("offset", area.getOffset()); + addAttribute("offset", area.getBlockProgressionOffset()); addAttribute("ruleStyle", area.getRuleStyleAsString()); addAttribute("ruleThickness", area.getRuleThickness()); startElement("leader", atts); @@ -889,5 +903,19 @@ public class XMLRenderer extends AbstractXMLRenderer { return XML_MIME_TYPE; } -} + private void maybeAddLevelAttribute ( Area a ) { + int level = a.getBidiLevel(); + if ( level >= 0 ) { + addAttribute ( "level", level ); + } + } + private void maybeAddPositionAdjustAttribute ( WordArea w ) { + int[][] adjustments = w.getGlyphPositionAdjustments(); + if ( adjustments != null ) { + addAttribute ( "position-adjust", XMLUtil.encodePositionAdjustments ( adjustments ) ); + } + } + + +} diff --git a/src/java/org/apache/fop/svg/PDFDocumentGraphics2D.java b/src/java/org/apache/fop/svg/PDFDocumentGraphics2D.java index 7ec9d7f2b..e91e2231c 100644 --- a/src/java/org/apache/fop/svg/PDFDocumentGraphics2D.java +++ b/src/java/org/apache/fop/svg/PDFDocumentGraphics2D.java @@ -159,7 +159,8 @@ public class PDFDocumentGraphics2D extends PDFGraphics2D { if (fontInfo == null) { //Default minimal fonts FontInfo fontInfo = new FontInfo(); - FontSetup.setup(fontInfo); + boolean base14Kerning = false; + FontSetup.setup(fontInfo, base14Kerning); setFontInfo(fontInfo); } } diff --git a/src/java/org/apache/fop/svg/PDFDocumentGraphics2DConfigurator.java b/src/java/org/apache/fop/svg/PDFDocumentGraphics2DConfigurator.java index 24974b01a..954291a57 100644 --- a/src/java/org/apache/fop/svg/PDFDocumentGraphics2DConfigurator.java +++ b/src/java/org/apache/fop/svg/PDFDocumentGraphics2DConfigurator.java @@ -46,9 +46,11 @@ public class PDFDocumentGraphics2DConfigurator { * Configures a PDFDocumentGraphics2D instance using an Avalon Configuration object. * @param graphics the PDFDocumentGraphics2D instance * @param cfg the configuration + * @param useComplexScriptFeatures true if complex script features enabled * @throws ConfigurationException if an error occurs while configuring the object */ - public void configure(PDFDocumentGraphics2D graphics, Configuration cfg) + public void configure(PDFDocumentGraphics2D graphics, Configuration cfg, + boolean useComplexScriptFeatures ) throws ConfigurationException { PDFDocument pdfDoc = graphics.getPDFDocument(); @@ -58,7 +60,7 @@ public class PDFDocumentGraphics2DConfigurator { //Fonts try { - FontInfo fontInfo = createFontInfo(cfg); + FontInfo fontInfo = createFontInfo(cfg, useComplexScriptFeatures); graphics.setFontInfo(fontInfo); } catch (FOPException e) { throw new ConfigurationException("Error while setting up fonts", e); @@ -68,13 +70,15 @@ public class PDFDocumentGraphics2DConfigurator { /** * Creates the {@link FontInfo} instance for the given configuration. * @param cfg the configuration + * @param useComplexScriptFeatures true if complex script features enabled * @return the font collection * @throws FOPException if an error occurs while setting up the fonts */ - public static FontInfo createFontInfo(Configuration cfg) throws FOPException { + public static FontInfo createFontInfo(Configuration cfg, boolean useComplexScriptFeatures) + throws FOPException { FontInfo fontInfo = new FontInfo(); final boolean strict = false; - FontResolver fontResolver = FontManager.createMinimalFontResolver(); + FontResolver fontResolver = FontManager.createMinimalFontResolver(useComplexScriptFeatures); //TODO The following could be optimized by retaining the FontManager somewhere FontManager fontManager = new FontManager(); if (cfg != null) { @@ -92,7 +96,8 @@ public class PDFDocumentGraphics2DConfigurator { = new FontInfoConfigurator(cfg, fontManager, fontResolver, listener, strict); List/**/ fontInfoList = new java.util.ArrayList/**/(); fontInfoConfigurator.configure(fontInfoList); - fontCollections.add(new CustomFontCollection(fontResolver, fontInfoList)); + fontCollections.add(new CustomFontCollection(fontResolver, fontInfoList, + fontResolver.isComplexScriptFeaturesEnabled())); } fontManager.setup(fontInfo, (FontCollection[])fontCollections.toArray( diff --git a/src/java/org/apache/fop/svg/PDFGraphics2D.java b/src/java/org/apache/fop/svg/PDFGraphics2D.java index 0d25e166c..429a1ea35 100644 --- a/src/java/org/apache/fop/svg/PDFGraphics2D.java +++ b/src/java/org/apache/fop/svg/PDFGraphics2D.java @@ -965,7 +965,8 @@ public class PDFGraphics2D extends AbstractGraphics2D implements NativeImageHand preparePainting(); FontInfo specialFontInfo = new FontInfo(); - FontSetup.setup(specialFontInfo); + boolean base14Kerning = false; + FontSetup.setup(specialFontInfo, base14Kerning); PDFResources res = pdfDoc.getFactory().makeResources(); PDFResourceContext context = new PDFResourceContext(res); diff --git a/src/java/org/apache/fop/svg/PDFTranscoder.java b/src/java/org/apache/fop/svg/PDFTranscoder.java index bf08b2fcf..8cf396ae5 100644 --- a/src/java/org/apache/fop/svg/PDFTranscoder.java +++ b/src/java/org/apache/fop/svg/PDFTranscoder.java @@ -126,7 +126,8 @@ public class PDFTranscoder extends AbstractFOPTranscoder { if (effCfg != null) { PDFDocumentGraphics2DConfigurator configurator = new PDFDocumentGraphics2DConfigurator(); - configurator.configure(graphics, effCfg); + boolean useComplexScriptFeatures = false; //TODO - FIX ME + configurator.configure(graphics, effCfg, useComplexScriptFeatures); } else { graphics.setupDefaultFontInfo(); } diff --git a/src/java/org/apache/fop/text/linebreak/LineBreakUtils.java b/src/java/org/apache/fop/text/linebreak/LineBreakUtils.java index 343191eea..d6e19a97a 100644 --- a/src/java/org/apache/fop/text/linebreak/LineBreakUtils.java +++ b/src/java/org/apache/fop/text/linebreak/LineBreakUtils.java @@ -100,35 +100,35 @@ public final class LineBreakUtils { lineBreakProperties[6] = new byte[] { 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 13, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 13, 13, 13, 13, 13, 13, 13, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 19, 0}; lineBreakProperties[7] = new byte[] { 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 0, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; lineBreakProperties[9] = new byte[] { 2, 2, 2, 9, 9, 9, 9, 9, 9, 9, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; - lineBreakProperties[10] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; + lineBreakProperties[10] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; lineBreakProperties[11] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 0, 19, 4, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 4, 9, 2, 9, 9, 2, 9, 9, 12, 9, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - lineBreakProperties[12] = new byte[] { 2, 2, 2, 2, 0, 0, 2, 2, 2, 28, 28, 28, 19, 19, 2, 2, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 12, 0, 0, 12, 12, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 28, 26, 26, 2, 2, 2, 9, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; - lineBreakProperties[13] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 12, 2, 9, 9, 9, 9, 9, 9, 9, 2, 9, 9, 9, 9, 9, 9, 9, 2, 2, 9, 9, 2, 9, 9, 9, 9, 2, 2, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 2, 2, 2, 2, 2, 2}; + lineBreakProperties[12] = new byte[] { 2, 2, 2, 2, 0, 0, 2, 2, 2, 28, 28, 28, 19, 19, 2, 2, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 12, 0, 0, 12, 12, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 28, 26, 26, 2, 2, 2, 9, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; + lineBreakProperties[13] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 12, 2, 9, 9, 9, 9, 9, 9, 9, 2, 2, 9, 9, 9, 9, 9, 9, 2, 2, 9, 9, 2, 9, 9, 9, 9, 2, 2, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 2, 2, 2, 2, 2, 2}; lineBreakProperties[14] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 9, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; lineBreakProperties[15] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, 9, 9, 9, 9, 9, 9, 9, 9, 2, 2, 2, 2, 19, 12, 2, 0, 0, 0, 0, 0}; - lineBreakProperties[16] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, 9, 9, 9, 2, 9, 9, 9, 9, 9, 9, 9, 9, 9, 2, 9, 9, 9, 2, 9, 9, 9, 9, 9, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + lineBreakProperties[16] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, 9, 9, 9, 2, 9, 9, 9, 9, 9, 9, 9, 9, 9, 2, 9, 9, 9, 2, 9, 9, 9, 9, 9, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, 9, 9, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; lineBreakProperties[17] = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - lineBreakProperties[18] = new byte[] { 9, 9, 9, 9, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 9, 2, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 2, 9, 9, 9, 9, 9, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, 9, 4, 4, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 2, 2, 2, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2}; + lineBreakProperties[18] = new byte[] { 9, 9, 9, 9, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, 9, 9, 2, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 2, 9, 9, 9, 9, 9, 9, 9, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, 9, 4, 4, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2}; lineBreakProperties[19] = new byte[] { 0, 9, 9, 9, 0, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 0, 2, 0, 0, 0, 2, 2, 2, 2, 0, 0, 9, 2, 9, 9, 9, 9, 9, 9, 9, 0, 0, 9, 9, 0, 0, 9, 9, 9, 2, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 2, 2, 0, 2, 2, 2, 9, 9, 0, 0, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 2, 2, 28, 28, 2, 2, 2, 2, 2, 28, 2, 29, 0, 0, 0, 0}; lineBreakProperties[20] = new byte[] { 0, 9, 9, 9, 0, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 0, 2, 2, 0, 2, 2, 0, 0, 9, 0, 9, 9, 9, 9, 9, 0, 0, 0, 0, 9, 9, 0, 0, 9, 9, 9, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 9, 9, 2, 2, 2, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; lineBreakProperties[21] = new byte[] { 0, 9, 9, 9, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 0, 2, 2, 2, 2, 2, 0, 0, 9, 2, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 0, 9, 9, 9, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 9, 9, 0, 0, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 0, 29, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - lineBreakProperties[22] = new byte[] { 0, 9, 9, 9, 0, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 0, 2, 2, 2, 2, 2, 0, 0, 9, 2, 9, 9, 9, 9, 9, 9, 9, 0, 0, 9, 9, 0, 0, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 2, 2, 0, 2, 2, 2, 9, 9, 0, 0, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + lineBreakProperties[22] = new byte[] { 0, 9, 9, 9, 0, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 0, 2, 2, 2, 2, 2, 0, 0, 9, 2, 9, 9, 9, 9, 9, 9, 9, 0, 0, 9, 9, 0, 0, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 2, 2, 0, 2, 2, 2, 9, 9, 0, 0, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0}; lineBreakProperties[23] = new byte[] { 0, 0, 9, 2, 0, 2, 2, 2, 2, 2, 2, 0, 0, 0, 2, 2, 2, 0, 2, 2, 2, 2, 0, 0, 0, 2, 2, 0, 2, 0, 2, 2, 0, 0, 0, 2, 2, 0, 0, 0, 2, 2, 2, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 9, 9, 9, 9, 9, 0, 0, 0, 9, 9, 9, 0, 9, 9, 9, 9, 0, 0, 2, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 2, 2, 2, 2, 2, 2, 2, 2, 2, 29, 2, 0, 0, 0, 0, 0}; lineBreakProperties[24] = new byte[] { 0, 9, 9, 9, 0, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 0, 0, 0, 2, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 0, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 2, 2, 0, 0, 0, 0, 0, 0, 2, 2, 9, 9, 0, 0, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2}; lineBreakProperties[25] = new byte[] { 0, 0, 9, 9, 0, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 0, 0, 9, 2, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 0, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 2, 9, 9, 0, 0, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - lineBreakProperties[26] = new byte[] { 0, 0, 9, 9, 0, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 2, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 0, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 9, 9, 0, 0, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 2, 2, 2, 2, 2, 2, 0, 0, 0, 28, 2, 2, 2, 2, 2, 2}; + lineBreakProperties[26] = new byte[] { 0, 0, 9, 9, 0, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 2, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 0, 9, 9, 9, 9, 2, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 9, 9, 0, 0, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 2, 2, 2, 2, 2, 2, 0, 0, 0, 28, 2, 2, 2, 2, 2, 2}; lineBreakProperties[27] = new byte[] { 0, 0, 9, 9, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 9, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 0, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; lineBreakProperties[28] = new byte[] { 0, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 0, 0, 0, 0, 29, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 2, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; lineBreakProperties[29] = new byte[] { 0, 31, 31, 0, 31, 0, 0, 31, 31, 0, 31, 0, 0, 31, 0, 0, 0, 0, 0, 0, 31, 31, 31, 31, 0, 31, 31, 31, 31, 31, 31, 31, 0, 31, 31, 31, 0, 31, 0, 31, 0, 0, 31, 31, 0, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 0, 31, 31, 31, 0, 0, 31, 31, 31, 31, 31, 0, 31, 0, 31, 31, 31, 31, 31, 31, 0, 0, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 0, 0, 31, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; lineBreakProperties[30] = new byte[] { 2, 5, 5, 5, 5, 2, 5, 5, 13, 5, 5, 4, 13, 12, 12, 12, 12, 12, 13, 2, 12, 2, 2, 2, 9, 9, 2, 2, 2, 2, 2, 2, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 4, 9, 2, 9, 2, 9, 27, 8, 27, 8, 9, 9, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 4}; - lineBreakProperties[31] = new byte[] { 9, 9, 9, 9, 9, 4, 9, 9, 2, 2, 2, 2, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 4, 4, 2, 2, 2, 2, 2, 2, 9, 2, 2, 2, 2, 2, 2, 0, 2, 2, 5, 5, 4, 5, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + lineBreakProperties[31] = new byte[] { 9, 9, 9, 9, 9, 4, 9, 9, 2, 2, 2, 2, 2, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 4, 4, 2, 2, 2, 2, 2, 2, 9, 2, 2, 2, 2, 2, 2, 0, 2, 2, 5, 5, 4, 5, 2, 2, 2, 2, 2, 13, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; lineBreakProperties[32] = new byte[] { 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 4, 4, 2, 2, 2, 2, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31}; lineBreakProperties[33] = new byte[] { 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 31, 31, 31, 31, 31, 31, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0}; lineBreakProperties[34] = new byte[] { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22}; lineBreakProperties[35] = new byte[] { 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21}; lineBreakProperties[36] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 0, 2, 0, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; lineBreakProperties[37] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 0, 2, 0, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; - lineBreakProperties[38] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 9, 2, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0}; + lineBreakProperties[38] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 9, 9, 9, 2, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0}; lineBreakProperties[39] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; lineBreakProperties[40] = new byte[] { 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; lineBreakProperties[45] = new byte[] { 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 27, 8, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 4, 4, 4, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; @@ -137,24 +137,24 @@ public final class LineBreakUtils { lineBreakProperties[48] = new byte[] { 2, 2, 12, 12, 4, 4, 5, 2, 12, 12, 2, 9, 9, 9, 13, 0, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0}; lineBreakProperties[49] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, 2, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; lineBreakProperties[50] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 2, 0, 0, 0, 12, 12, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 0, 0, 31, 31, 31, 31, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - lineBreakProperties[51] = new byte[] { 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 0, 0, 0, 0, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 0, 0, 0, 0, 0, 0, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 0, 0, 0, 31, 31, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; + lineBreakProperties[51] = new byte[] { 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 0, 0, 0, 0, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 0, 0, 0, 0, 0, 0, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 31, 0, 0, 0, 31, 31, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; lineBreakProperties[52] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, 9, 9, 9, 9, 0, 0, 2, 2, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 0, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 0, 0, 9}; lineBreakProperties[53] = new byte[] { 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 0, 0, 0, 0, 0, 0, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 0, 0, 0, 0, 0, 0, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; lineBreakProperties[54] = new byte[] { 9, 9, 9, 9, 9, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 4, 4, 2, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, 9, 9, 9, 9, 9, 9, 9, 9, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0}; - lineBreakProperties[55] = new byte[] { 9, 9, 9, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 2, 2, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + lineBreakProperties[55] = new byte[] { 9, 9, 9, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 2, 2, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2}; lineBreakProperties[56] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 4, 4, 4, 4, 4, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 0, 0, 0, 2, 2, 2, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 4, 4}; lineBreakProperties[57] = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 2, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 2, 2, 2, 2, 9, 2, 2, 2, 2, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - lineBreakProperties[59] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9}; + lineBreakProperties[59] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9}; lineBreakProperties[62] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 0, 2, 0, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0}; lineBreakProperties[63] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 5, 2, 0}; lineBreakProperties[64] = new byte[] { 4, 4, 4, 4, 4, 4, 4, 13, 4, 4, 4, 37, 9, 9, 9, 9, 4, 13, 4, 4, 3, 1, 1, 2, 30, 30, 27, 30, 30, 30, 27, 30, 1, 1, 2, 2, 18, 18, 18, 4, 6, 6, 9, 9, 9, 9, 9, 13, 28, 28, 28, 28, 28, 28, 28, 28, 2, 30, 30, 1, 25, 25, 2, 2, 2, 2, 2, 2, 19, 27, 8, 25, 25, 25, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 4, 2, 4, 4, 4, 4, 2, 4, 4, 4, 35, 2, 2, 2, 2, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 2, 2, 0, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 27, 8, 1}; - lineBreakProperties[65] = new byte[] { 2, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 27, 8, 0, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 29, 29, 29, 29, 29, 29, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 28, 29, 29, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + lineBreakProperties[65] = new byte[] { 2, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 27, 8, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 29, 29, 29, 29, 29, 29, 29, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 28, 29, 29, 29, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; lineBreakProperties[66] = new byte[] { 2, 2, 2, 28, 2, 1, 2, 2, 2, 28, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 29, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2, 2, 1, 2, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2}; lineBreakProperties[67] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; lineBreakProperties[68] = new byte[] { 1, 2, 1, 1, 2, 2, 2, 1, 1, 2, 2, 1, 2, 2, 2, 1, 2, 1, 29, 29, 2, 1, 2, 2, 2, 2, 1, 2, 2, 1, 1, 1, 1, 2, 2, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 2, 1, 2, 2, 2, 2, 2, 1, 1, 1, 1, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 1, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 2, 2, 1, 1, 1, 1, 2, 2, 1, 1, 2, 2, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; lineBreakProperties[69] = new byte[] { 2, 2, 1, 1, 2, 2, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; lineBreakProperties[70] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 27, 8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; - lineBreakProperties[71] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + lineBreakProperties[71] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; lineBreakProperties[72] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; lineBreakProperties[73] = new byte[] { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2}; } @@ -163,14 +163,14 @@ public final class LineBreakUtils { lineBreakProperties[74] = new byte[] { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; lineBreakProperties[75] = new byte[] { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 2, 2, 1, 1, 2, 2, 2, 2, 1, 1, 2, 2, 1, 1, 2, 2, 2, 2, 1, 1, 1, 2, 2, 1, 2, 2, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; lineBreakProperties[76] = new byte[] { 2, 2, 2, 2, 2, 1, 1, 2, 2, 1, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2, 1, 1, 1, 1, 2, 2, 2, 2, 1, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 2, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; - lineBreakProperties[77] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; - lineBreakProperties[78] = new byte[] { 0, 2, 2, 2, 2, 0, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 0, 2, 2, 2, 2, 0, 0, 0, 2, 1, 2, 2, 2, 30, 30, 30, 30, 0, 0, 2, 12, 12, 2, 2, 2, 2, 27, 8, 27, 8, 27, 8, 27, 8, 27, 8, 27, 8, 27, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; - lineBreakProperties[79] = new byte[] { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 27, 8, 2, 2, 2, 2, 0, 2, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 27, 8, 27, 8, 27, 8, 27, 8, 27, 8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; + lineBreakProperties[77] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; + lineBreakProperties[78] = new byte[] { 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 30, 30, 30, 30, 2, 2, 2, 12, 12, 2, 2, 2, 2, 27, 8, 27, 8, 27, 8, 27, 8, 27, 8, 27, 8, 27, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; + lineBreakProperties[79] = new byte[] { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 27, 8, 2, 2, 2, 2, 0, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 27, 8, 27, 8, 27, 8, 27, 8, 27, 8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; lineBreakProperties[83] = new byte[] { 2, 2, 2, 27, 8, 27, 8, 27, 8, 27, 8, 27, 8, 27, 8, 27, 8, 27, 8, 27, 8, 27, 8, 27, 8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 27, 8, 27, 8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 27, 8, 2, 2}; lineBreakProperties[86] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; lineBreakProperties[88] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; lineBreakProperties[89] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 12, 4, 4, 4, 2, 12, 4}; - lineBreakProperties[90] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + lineBreakProperties[90] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9}; lineBreakProperties[91] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9}; lineBreakProperties[92] = new byte[] { 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 4, 4, 4, 4, 4, 4, 4, 4, 2, 4, 27, 4, 2, 2, 30, 30, 2, 2, 30, 30, 27, 8, 27, 8, 27, 8, 27, 8, 4, 4, 4, 4, 12, 2, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; lineBreakProperties[93] = new byte[] { 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; @@ -179,21 +179,22 @@ public final class LineBreakUtils { lineBreakProperties[96] = new byte[] { 17, 8, 8, 17, 17, 25, 17, 17, 27, 8, 27, 8, 27, 8, 27, 8, 27, 8, 17, 17, 27, 8, 27, 8, 27, 8, 27, 8, 25, 27, 8, 8, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 9, 9, 9, 9, 9, 9, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 25, 25, 17, 17, 17, 0, 25, 17, 25, 17, 25, 17, 25, 17, 25, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 25, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17}; lineBreakProperties[97] = new byte[] { 17, 17, 17, 25, 17, 25, 17, 25, 17, 17, 17, 17, 17, 17, 25, 17, 17, 17, 17, 17, 17, 25, 25, 0, 0, 9, 9, 25, 25, 25, 25, 17, 25, 25, 17, 25, 17, 25, 17, 25, 17, 25, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 25, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 25, 17, 25, 17, 25, 17, 17, 17, 17, 17, 17, 25, 17, 17, 17, 17, 17, 17, 25, 25, 17, 17, 17, 17, 25, 25, 25, 25, 17}; lineBreakProperties[98] = new byte[] { 0, 0, 0, 0, 0, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, 0, 0, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17}; - lineBreakProperties[99] = new byte[] { 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, 0, 0, 0, 0, 0, 0, 0, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25}; + lineBreakProperties[99] = new byte[] { 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, 0, 0, 0, 0, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25}; lineBreakProperties[100] = new byte[] { 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 1, 1, 1, 1, 1, 1, 1, 1, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17}; lineBreakProperties[101] = new byte[] { 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 0}; lineBreakProperties[155] = new byte[] { 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; lineBreakProperties[320] = new byte[] { 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 25, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17}; lineBreakProperties[329] = new byte[] { 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, 0, 0, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 4, 4}; - lineBreakProperties[332] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 4, 12, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, 9, 9, 9, 2, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 2, 2}; + lineBreakProperties[332] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 4, 12, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, 9, 9, 9, 2, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 2, 2}; lineBreakProperties[333] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, 9, 2, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0}; - lineBreakProperties[335] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2}; + lineBreakProperties[335] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2}; lineBreakProperties[336] = new byte[] { 2, 2, 9, 2, 2, 2, 9, 2, 2, 2, 2, 9, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, 9, 9, 9, 9, 2, 2, 2, 2, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 28, 2, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 5, 12, 12, 0, 0, 0, 0, 0, 0, 0, 0}; lineBreakProperties[337] = new byte[] { 9, 9, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0}; lineBreakProperties[338] = new byte[] { 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, 9, 9, 9, 9, 9, 9, 9, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0}; lineBreakProperties[339] = new byte[] { 9, 9, 9, 9, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 2, 2, 2, 2, 2, 2, 4, 4, 4, 2, 2, 2, 2, 0, 2, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; lineBreakProperties[340] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 9, 2, 2, 2, 2, 2, 2, 2, 2, 9, 9, 0, 0, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 0, 0, 2, 4, 4, 4, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 0, 0, 0, 0}; lineBreakProperties[341] = new byte[] { 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 31, 31, 31, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + lineBreakProperties[342] = new byte[] { 0, 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; lineBreakProperties[343] = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, 9, 9, 9, 9, 9, 9, 9, 4, 9, 9, 0, 0, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 0, 0, 0, 0, 0, 0}; lineBreakProperties[344] = new byte[] { 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15}; lineBreakProperties[345] = new byte[] { 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 14, 15, 15, 15}; @@ -206,7 +207,7 @@ public final class LineBreakUtils { lineBreakProperties[432] = new byte[] { 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32}; lineBreakProperties[448] = new byte[] { 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36}; lineBreakProperties[502] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 2, 9, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 0, 2, 0, 2, 2, 0, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; - lineBreakProperties[503] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; + lineBreakProperties[503] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; lineBreakProperties[506] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 27, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; lineBreakProperties[507] = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 28, 2, 0, 0}; lineBreakProperties[508] = new byte[] { 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 19, 8, 8, 19, 19, 12, 12, 27, 8, 18, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 17, 17, 17, 17, 27, 8, 27, 8, 27, 8, 27, 8, 27, 8, 27, 8, 27, 8, 27, 8, 17, 17, 27, 8, 17, 17, 17, 17, 17, 17, 17, 8, 17, 8, 0, 25, 25, 12, 12, 17, 27, 8, 27, 8, 27, 8, 17, 17, 17, 17, 17, 17, 17, 17, 0, 17, 29, 28, 17, 0, 0, 0, 0, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; @@ -462,7 +463,6 @@ public final class LineBreakUtils { lineBreakProperties[330] = lineBreakProperties[2]; lineBreakProperties[331] = lineBreakProperties[2]; lineBreakProperties[334] = lineBreakProperties[2]; - lineBreakProperties[342] = lineBreakProperties[17]; lineBreakProperties[351] = lineBreakProperties[344]; lineBreakProperties[352] = lineBreakProperties[345]; lineBreakProperties[353] = lineBreakProperties[346]; diff --git a/src/java/org/apache/fop/traits/Direction.java b/src/java/org/apache/fop/traits/Direction.java new file mode 100644 index 000000000..5eb36058e --- /dev/null +++ b/src/java/org/apache/fop/traits/Direction.java @@ -0,0 +1,108 @@ +/* + * 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.traits; + +import java.io.ObjectStreamException; + +import org.apache.fop.fo.Constants; + +/** + * Enumeration class for direction traits, namely {inline,block}-progression-direction + * and shift-direction. + */ +public final class Direction extends TraitEnum { + + private static final long serialVersionUID = 1L; + + private static final String[] DIRECTION_NAMES = new String[] + {"lr", "rl", "tb", "bt"}; + + private static final int[] DIRECTION_VALUES = new int[] + {Constants.EN_LR, Constants.EN_RL, Constants.EN_TB, Constants.EN_BT}; + + /** direction: left-to-right */ + public static final Direction LR = new Direction(0); + /** direction: right-to-left */ + public static final Direction RL = new Direction(1); + /** direction: top-to-bottom */ + public static final Direction TB = new Direction(2); + /** direction: bottom-to-top */ + public static final Direction BT = new Direction(3); + + private static final Direction[] DIRECTIONS = new Direction[] {LR, RL, TB, BT}; + + private Direction(int index) { + super(DIRECTION_NAMES[index], DIRECTION_VALUES[index]); + } + + /** + * Determine if direction is vertical or not. + * @return true if vertical + */ + public boolean isVertical() { + return ( getEnumValue() == Constants.EN_TB ) || ( getEnumValue() == Constants.EN_BT ); + } + + /** + * Determine if direction is horizontal or not. + * @return true if horizontal + */ + public boolean isHorizontal() { + return ( getEnumValue() == Constants.EN_LR ) || ( getEnumValue() == Constants.EN_RL ); + } + + /** + * Returns the enumeration/singleton object based on its name. + * @param name the name of the enumeration value + * @return the enumeration object + */ + public static Direction valueOf(String name) { + for (int i = 0; i < DIRECTIONS.length; i++) { + if (DIRECTIONS[i].getName().equalsIgnoreCase(name)) { + return DIRECTIONS[i]; + } + } + throw new IllegalArgumentException("Illegal direction: " + name); + } + + /** + * Returns the enumeration/singleton object based on its name. + * @param enumValue the enumeration value + * @return the enumeration object + */ + public static Direction valueOf(int enumValue) { + for (int i = 0; i < DIRECTIONS.length; i++) { + if (DIRECTIONS[i].getEnumValue() == enumValue) { + return DIRECTIONS[i]; + } + } + throw new IllegalArgumentException("Illegal direction: " + enumValue); + } + + private Object readResolve() throws ObjectStreamException { + return valueOf(getName()); + } + + /** {@inheritDoc} */ + public String toString() { + return getName(); + } + +} diff --git a/src/java/org/apache/fop/traits/WritingMode.java b/src/java/org/apache/fop/traits/WritingMode.java new file mode 100644 index 000000000..5b12bb127 --- /dev/null +++ b/src/java/org/apache/fop/traits/WritingMode.java @@ -0,0 +1,166 @@ +/* + * 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.traits; + +import java.io.ObjectStreamException; + +import org.apache.fop.fo.Constants; + +/** Enumeration class for writing mode trait. */ +public final class WritingMode extends TraitEnum { + + private static final long serialVersionUID = 1L; + + private static final String[] WRITING_MODE_NAMES = new String[] + {"lr-tb", "rl-tb", "tb-lr", "tb-rl"}; + + private static final int[] WRITING_MODE_VALUES = new int[] + {Constants.EN_LR_TB, Constants.EN_RL_TB, Constants.EN_TB_LR, Constants.EN_TB_RL}; + + /** writing mode: lr-tb */ + public static final WritingMode LR_TB = new WritingMode(0); + /** writing mode: rl-tb */ + public static final WritingMode RL_TB = new WritingMode(1); + /** writing mode: tb-lr */ + public static final WritingMode TB_LR = new WritingMode(2); + /** writing mode: tb-rl */ + public static final WritingMode TB_RL = new WritingMode(3); + + private static final WritingMode[] WRITING_MODES + = new WritingMode[] {LR_TB, RL_TB, TB_LR, TB_RL}; + + private WritingMode(int index) { + super(WRITING_MODE_NAMES[index], WRITING_MODE_VALUES[index]); + } + + /** + * Assign writing mode traits from this trait to the specified + * writing mode traits setter. + * @param wms a writing mode traits setter + */ + public void assignWritingModeTraits ( WritingModeTraitsSetter wms ) { + Direction inlineProgressionDirection; + Direction blockProgressionDirection; + Direction columnProgressionDirection; + Direction rowProgressionDirection; + Direction shiftDirection; + switch ( getEnumValue() ) { + default: + case Constants.EN_LR_TB: + inlineProgressionDirection = Direction.LR; + blockProgressionDirection = Direction.TB; + columnProgressionDirection = Direction.LR; + rowProgressionDirection = Direction.TB; + shiftDirection = Direction.BT; + break; + case Constants.EN_RL_TB: + inlineProgressionDirection = Direction.RL; + blockProgressionDirection = Direction.TB; + columnProgressionDirection = Direction.RL; + rowProgressionDirection = Direction.TB; + shiftDirection = Direction.BT; + break; + case Constants.EN_TB_LR: + inlineProgressionDirection = Direction.TB; + blockProgressionDirection = Direction.LR; + columnProgressionDirection = Direction.TB; + rowProgressionDirection = Direction.LR; + shiftDirection = Direction.RL; + break; + case Constants.EN_TB_RL: + inlineProgressionDirection = Direction.TB; + blockProgressionDirection = Direction.RL; + columnProgressionDirection = Direction.TB; + rowProgressionDirection = Direction.RL; + shiftDirection = Direction.LR; + break; + } + wms.setInlineProgressionDirection ( inlineProgressionDirection ); + wms.setBlockProgressionDirection ( blockProgressionDirection ); + wms.setColumnProgressionDirection ( columnProgressionDirection ); + wms.setRowProgressionDirection ( rowProgressionDirection ); + wms.setShiftDirection ( shiftDirection ); + wms.setWritingMode ( this ); + } + + /** + * Determine if WM is horizontal or not. + * @return true if horizontal + */ + public boolean isHorizontal() { + switch ( getEnumValue() ) { + case Constants.EN_LR_TB: + case Constants.EN_RL_TB: + return true; + case Constants.EN_TB_LR: + case Constants.EN_TB_RL: + return false; + default: + assert false; + return true; + } + } + + /** + * Determine if WM is vertical or not. + * @return true if vertical + */ + public boolean isVertical() { + return !isHorizontal(); + } + + /** + * Returns the enumeration/singleton object based on its name. + * @param name the name of the enumeration value + * @return the enumeration object + */ + public static WritingMode valueOf(String name) { + for (int i = 0; i < WRITING_MODES.length; i++) { + if (WRITING_MODES[i].getName().equalsIgnoreCase(name)) { + return WRITING_MODES[i]; + } + } + throw new IllegalArgumentException("Illegal writing mode: " + name); + } + + /** + * Returns the enumeration/singleton object based on its name. + * @param enumValue the enumeration value + * @return the enumeration object + */ + public static WritingMode valueOf(int enumValue) { + for (int i = 0; i < WRITING_MODES.length; i++) { + if (WRITING_MODES[i].getEnumValue() == enumValue) { + return WRITING_MODES[i]; + } + } + throw new IllegalArgumentException("Illegal writing mode: " + enumValue); + } + + private Object readResolve() throws ObjectStreamException { + return valueOf(getName()); + } + + /** {@inheritDoc} */ + public String toString() { + return getName(); + } + +} diff --git a/src/java/org/apache/fop/traits/WritingModeTraits.java b/src/java/org/apache/fop/traits/WritingModeTraits.java new file mode 100644 index 000000000..c96cd73c3 --- /dev/null +++ b/src/java/org/apache/fop/traits/WritingModeTraits.java @@ -0,0 +1,157 @@ +/* + * 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.traits; + +/** + * This class provides a reusable implementation of the WritingModeTraitsSetter + * interface. + */ +public class WritingModeTraits implements WritingModeTraitsSetter { + + private Direction inlineProgressionDirection; + private Direction blockProgressionDirection; + private Direction columnProgressionDirection; + private Direction rowProgressionDirection; + private Direction shiftDirection; + private WritingMode writingMode; + + /** + * Default writing mode traits constructor. + */ + public WritingModeTraits() { + this ( WritingMode.LR_TB ); + } + + /** + * Construct writing mode traits using the specified writing mode. + * @param writingMode a writing mode traits object + */ + public WritingModeTraits ( WritingMode writingMode ) { + assignWritingModeTraits ( writingMode ); + } + + /** + * @return the "inline-progression-direction" trait. + */ + public Direction getInlineProgressionDirection() { + return inlineProgressionDirection; + } + + /** + * @param direction the "inline-progression-direction" trait. + */ + public void setInlineProgressionDirection ( Direction direction ) { + this.inlineProgressionDirection = direction; + } + + /** + * @return the "block-progression-direction" trait. + */ + public Direction getBlockProgressionDirection() { + return blockProgressionDirection; + } + + /** + * @param direction the "block-progression-direction" trait. + */ + public void setBlockProgressionDirection ( Direction direction ) { + this.blockProgressionDirection = direction; + } + + /** + * @return the "column-progression-direction" trait. + */ + public Direction getColumnProgressionDirection() { + return columnProgressionDirection; + } + + /** + * @param direction the "column-progression-direction" trait. + */ + public void setColumnProgressionDirection ( Direction direction ) { + this.columnProgressionDirection = direction; + } + + /** + * @return the "row-progression-direction" trait. + */ + public Direction getRowProgressionDirection() { + return rowProgressionDirection; + } + + /** + * @param direction the "row-progression-direction" trait. + */ + public void setRowProgressionDirection ( Direction direction ) { + this.rowProgressionDirection = direction; + } + + /** + * @return the "shift-direction" trait. + */ + public Direction getShiftDirection() { + return shiftDirection; + } + + /** + * @param direction the "shift-direction" trait. + */ + public void setShiftDirection ( Direction direction ) { + this.shiftDirection = direction; + } + + /** + * @return the "writing-mode" trait. + */ + public WritingMode getWritingMode() { + return writingMode; + } + + /** + * @param writingMode the "writing-mode" trait. + */ + public void setWritingMode ( WritingMode writingMode ) { + this.writingMode = writingMode; + } + + /** + * @param writingMode the "writing-mode" trait. + */ + public void assignWritingModeTraits ( WritingMode writingMode ) { + writingMode.assignWritingModeTraits ( this ); + } + + /** + * Helper function to find the writing mode traits getter (if any) that applies for + * a given FO node. + * @param fn the node to start searching from + * @return the applicable writing mode traits getter, or null if none applies + */ + public static WritingModeTraitsGetter + getWritingModeTraitsGetter ( org.apache.fop.fo.FONode fn ) { + for ( org.apache.fop.fo.FONode n = fn; n != null; n = n.getParent() ) { + if ( n instanceof WritingModeTraitsGetter ) { + return (WritingModeTraitsGetter) n; + } + } + return null; + } + +} diff --git a/src/java/org/apache/fop/traits/WritingModeTraitsGetter.java b/src/java/org/apache/fop/traits/WritingModeTraitsGetter.java new file mode 100644 index 000000000..a67e437c9 --- /dev/null +++ b/src/java/org/apache/fop/traits/WritingModeTraitsGetter.java @@ -0,0 +1,58 @@ +/* + * 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.traits; + +/** + * This interface provides read access to FO traits related to writing mode. + */ +public interface WritingModeTraitsGetter { + + /** + * @return the "inline-progression-direction" trait + */ + Direction getInlineProgressionDirection(); + + /** + * @return the "block-progression-direction" trait + */ + Direction getBlockProgressionDirection(); + + /** + * @return the "column-progression-direction" trait + */ + Direction getColumnProgressionDirection(); + + /** + * @return the "row-progression-direction" trait + */ + + Direction getRowProgressionDirection(); + + /** + * @return the "shift-direction" trait + */ + Direction getShiftDirection(); + + /** + * @return the "writing-mode" trait + */ + WritingMode getWritingMode(); + +} diff --git a/src/java/org/apache/fop/traits/WritingModeTraitsSetter.java b/src/java/org/apache/fop/traits/WritingModeTraitsSetter.java new file mode 100644 index 000000000..1b94e22de --- /dev/null +++ b/src/java/org/apache/fop/traits/WritingModeTraitsSetter.java @@ -0,0 +1,70 @@ +/* + * 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.traits; + +/** + * This interface provides read and assignment access to FO traits related to writing mode. + */ +public interface WritingModeTraitsSetter extends WritingModeTraitsGetter { + + /** + * Set value of inline-progression-direction trait. + * @param direction the "inline-progression-direction" trait + */ + void setInlineProgressionDirection ( Direction direction ); + + /** + * Set value of block-progression-direction trait. + * @param direction the "block-progression-direction" trait + */ + void setBlockProgressionDirection ( Direction direction ); + + /** + * Set value of column-progression-direction trait. + * @param direction the "column-progression-direction" trait + */ + void setColumnProgressionDirection ( Direction direction ); + + /** + * Set value of row-progression-direction trait. + * @param direction the "row-progression-direction" trait + */ + void setRowProgressionDirection ( Direction direction ); + + /** + * Set value of shift-direction trait. + * @param direction the "shift-direction" trait + */ + void setShiftDirection ( Direction direction ); + + /** + * Set value of writing-mode trait. + * @param writingMode the "writing-mode" trait + */ + void setWritingMode ( WritingMode writingMode ); + + /** + * Collectivelly assign values to all writing mode traits based upon a specific + * writing mode. + * @param writingMode the "writing-mode" trait + */ + void assignWritingModeTraits ( WritingMode writingMode ); + +} diff --git a/src/java/org/apache/fop/util/CharUtilities.java b/src/java/org/apache/fop/util/CharUtilities.java index 7786552ff..8b90e3d25 100644 --- a/src/java/org/apache/fop/util/CharUtilities.java +++ b/src/java/org/apache/fop/util/CharUtilities.java @@ -74,6 +74,20 @@ public class CharUtilities { public static final char WORD_JOINER = '\u2060'; /** zero-width joiner */ public static final char ZERO_WIDTH_JOINER = '\u200D'; + /** left-to-right mark */ + public static final char LRM = '\u200E'; + /** right-to-left mark */ + public static final char RLM = '\u202F'; + /** left-to-right embedding */ + public static final char LRE = '\u202A'; + /** right-to-left embedding */ + public static final char RLE = '\u202B'; + /** pop directional formatting */ + public static final char PDF = '\u202C'; + /** left-to-right override */ + public static final char LRO = '\u202D'; + /** right-to-left override */ + public static final char RLO = '\u202E'; /** zero-width no-break space (= byte order mark) */ public static final char ZERO_WIDTH_NOBREAK_SPACE = '\uFEFF'; /** soft hyphen */ @@ -86,10 +100,11 @@ public class CharUtilities { public static final char MISSING_IDEOGRAPH = '\u25A1'; /** Ideogreaphic space */ public static final char IDEOGRAPHIC_SPACE = '\u3000'; + /** Object replacement character */ + public static final char OBJECT_REPLACEMENT_CHARACTER = '\uFFFC'; /** Unicode value indicating the the character is "not a character". */ public static final char NOT_A_CHARACTER = '\uFFFF'; - /** * Utility class: Constructor prevents instantiating when subclassed. */ @@ -103,7 +118,7 @@ public class CharUtilities { * @param c character to inspect * @return the determined character class */ - public static int classOf(char c) { + public static int classOf ( int c ) { switch (c) { case CODE_EOT: return EOT; @@ -126,7 +141,7 @@ public class CharUtilities { * @param c character to inspect * @return True if the character is a normal space */ - public static boolean isBreakableSpace(char c) { + public static boolean isBreakableSpace ( int c ) { return (c == SPACE || isFixedWidthSpace(c)); } @@ -135,7 +150,7 @@ public class CharUtilities { * @param c the character to check * @return true if the character is a zero-width space */ - public static boolean isZeroWidthSpace(char c) { + public static boolean isZeroWidthSpace ( int c ) { return c == ZERO_WIDTH_SPACE // 200Bh || c == WORD_JOINER // 2060h || c == ZERO_WIDTH_NOBREAK_SPACE; // FEFFh (also used as BOM) @@ -146,7 +161,7 @@ public class CharUtilities { * @param c the character to check * @return true if the character has a fixed-width */ - public static boolean isFixedWidthSpace(char c) { + public static boolean isFixedWidthSpace ( int c ) { return (c >= '\u2000' && c <= '\u200B') || c == '\u3000'; // c == '\u2000' // en quad @@ -170,7 +185,7 @@ public class CharUtilities { * @param c character to check * @return True if the character is a nbsp */ - public static boolean isNonBreakableSpace(char c) { + public static boolean isNonBreakableSpace ( int c ) { return (c == NBSPACE // no-break space || c == '\u202F' // narrow no-break space @@ -185,7 +200,7 @@ public class CharUtilities { * @param c character to check * @return True if the character is adjustable */ - public static boolean isAdjustableSpace(char c) { + public static boolean isAdjustableSpace ( int c ) { //TODO: are there other kinds of adjustable spaces? return (c == '\u0020' // normal space @@ -197,19 +212,19 @@ public class CharUtilities { * @param c character to check * @return True if the character represents any kind of space */ - public static boolean isAnySpace(char c) { + public static boolean isAnySpace ( int c ) { return (isBreakableSpace(c) || isNonBreakableSpace(c)); } /** * Indicates whether a character is classified as "Alphabetic" by the Unicode standard. - * @param ch the character + * @param c the character * @return true if the character is "Alphabetic" */ - public static boolean isAlphabetic(char ch) { + public static boolean isAlphabetic ( int c ) { //http://www.unicode.org/Public/UNIDATA/UCD.html#Alphabetic //Generated from: Other_Alphabetic + Lu + Ll + Lt + Lm + Lo + Nl - int generalCategory = Character.getType(ch); + int generalCategory = Character.getType((char)c); switch (generalCategory) { case Character.UPPERCASE_LETTER: //Lu case Character.LOWERCASE_LETTER: //Ll @@ -227,15 +242,120 @@ public class CharUtilities { /** * Indicates whether the given character is an explicit break-character - * @param ch the character to check + * @param c the character to check * @return true if the character represents an explicit break */ - public static boolean isExplicitBreak(char ch) { - return (ch == LINEFEED_CHAR - || ch == CARRIAGE_RETURN - || ch == NEXT_LINE - || ch == LINE_SEPARATOR - || ch == PARAGRAPH_SEPARATOR); + public static boolean isExplicitBreak ( int c ) { + return (c == LINEFEED_CHAR + || c == CARRIAGE_RETURN + || c == NEXT_LINE + || c == LINE_SEPARATOR + || c == PARAGRAPH_SEPARATOR); + } + + /** + * Convert a single unicode scalar value to an XML numeric character + * reference. If in the BMP, four digits are used, otherwise 6 digits are used. + * @param c a unicode scalar value + * @return a string representing a numeric character reference + */ + public static String charToNCRef ( int c ) { + StringBuffer sb = new StringBuffer(); + for ( int i = 0, nDigits = ( c > 0xFFFF ) ? 6 : 4; i < nDigits; i++, c >>= 4 ) { + int d = c & 0xF; + char hd; + if ( d < 10 ) { + hd = (char) ( (int) '0' + d ); + } else { + hd = (char) ( (int) 'A' + ( d - 10 ) ); + } + sb.append ( hd ); + } + return "&#x" + sb.reverse() + ";"; + } + + /** + * Convert a string to a sequence of ASCII or XML numeric character references. + * @param s a java string (encoded in UTF-16) + * @return a string representing a sequence of numeric character reference or + * ASCII characters + * @author Glenn Adams + */ + public static String toNCRefs ( String s ) { + StringBuffer sb = new StringBuffer(); + if ( s != null ) { + for ( int i = 0; i < s.length(); i++ ) { + char c = s.charAt(i); + if ( ( c >= 32 ) && ( c < 127 ) ) { + if ( c == '<' ) { + sb.append ( "<" ); + } else if ( c == '>' ) { + sb.append ( ">" ); + } else if ( c == '&' ) { + sb.append ( "&" ); + } else { + sb.append ( c ); + } + } else { + sb.append ( charToNCRef ( c ) ); + } + } + } + return sb.toString(); + } + + /** + * Pad a string S on left out to width W using padding character PAD. + * @param s string to pad + * @param width width of field to add padding + * @param pad character to use for padding + * @return padded string + * @author Glenn Adams + */ + public static String padLeft ( String s, int width, char pad ) { + StringBuffer sb = new StringBuffer(); + for ( int i = s.length(); i < width; i++ ) { + sb.append(pad); + } + sb.append ( s ); + return sb.toString(); + } + + /** + * Format character for debugging output, which it is prefixed with "0x", padded left with '0' + * and either 4 or 6 hex characters in width according to whether it is in the BMP or not. + * @param c character code + * @return formatted character string + * @author Glenn Adams + */ + public static String format ( int c ) { + if ( c < 1114112 ) { + return "0x" + padLeft ( Integer.toString ( c, 16 ), ( c < 65536 ) ? 4 : 6, '0' ); + } else { + return "!NOT A CHARACTER!"; + } } -} + /** + * Determine if two character sequences contain the same characters. + * @param cs1 first character sequence + * @param cs2 second character sequence + * @return true if both sequences have same length and same character sequence + * @author Glenn Adams + */ + public static boolean isSameSequence ( CharSequence cs1, CharSequence cs2 ) { + assert cs1 != null; + assert cs2 != null; + if ( cs1.length() != cs2.length() ) { + return false; + } else { + for ( int i = 0, n = cs1.length(); i < n; i++ ) { + if ( cs1.charAt(i) != cs2.charAt(i) ) { + return false; + } + } + return true; + } + } + +} diff --git a/src/java/org/apache/fop/util/XMLUtil.java b/src/java/org/apache/fop/util/XMLUtil.java index d4397c2c7..e91b6eb5d 100644 --- a/src/java/org/apache/fop/util/XMLUtil.java +++ b/src/java/org/apache/fop/util/XMLUtil.java @@ -173,4 +173,126 @@ public final class XMLUtil implements XMLConstants { atts.addAttribute("", localName, localName, XMLUtil.CDATA, value); } + /** + * Encode a glyph position adjustments array as a string, where the string value + * adheres to the following syntax: + * + * count ( 'Z' repeat | number ) + * + * where each token is separated by whitespace, except that 'Z' followed by repeat + * are considered to be a single token with no intervening whitespace, and where + * 'Z' repeat encodes repeated zeroes. + * @param dp the adjustments array + * @param paCount the number of entries to encode from adjustments array + * @return the encoded value + */ + public static String encodePositionAdjustments ( int[][] dp, int paCount ) { + assert dp != null; + StringBuffer sb = new StringBuffer(); + int na = paCount; + int nz = 0; + sb.append ( na ); + for ( int i = 0; i < na; i++ ) { + int[] pa = dp [ i ]; + for ( int k = 0; k < 4; k++ ) { + int a = pa [ k ]; + if ( a != 0 ) { + encodeNextAdjustment ( sb, nz, a ); nz = 0; + } else { + nz++; + } + } + } + encodeNextAdjustment ( sb, nz, 0 ); + return sb.toString(); + } + + /** + * Encode a glyph position adjustments array as a string, where the string value + * adheres to the following syntax: + * + * count ( 'Z' repeat | number ) + * + * where each token is separated by whitespace, except that 'Z' followed by repeat + * are considered to be a single token with no intervening whitespace. + * @param dp the adjustments array + * @return the encoded value + */ + public static String encodePositionAdjustments ( int[][] dp ) { + assert dp != null; + return encodePositionAdjustments ( dp, dp.length ); + } + + private static void encodeNextAdjustment ( StringBuffer sb, int nz, int a ) { + encodeZeroes ( sb, nz ); + encodeAdjustment ( sb, a ); + } + + private static void encodeZeroes ( StringBuffer sb, int nz ) { + if ( nz > 0 ) { + sb.append ( ' ' ); + if ( nz == 1 ) { + sb.append ( '0' ); + } else { + sb.append ( 'Z' ); + sb.append ( nz ); + } + } + } + + private static void encodeAdjustment ( StringBuffer sb, int a ) { + if ( a != 0 ) { + sb.append ( ' ' ); + sb.append ( a ); + } + } + + /** + * Decode a string as a glyph position adjustments array, where the string + * shall adhere to the syntax specified by {@link #encodePositionAdjustments}. + * @param value the encoded value + * @return the position adjustments array + */ + public static int[][] decodePositionAdjustments ( String value ) { + int[][] dp = null; + if ( value != null ) { + String[] sa = value.split ( "\\s" ); + if ( sa != null ) { + if ( sa.length > 0 ) { + int na = Integer.parseInt ( sa[0] ); + dp = new int [ na ] [ 4 ]; + for ( int i = 1, n = sa.length, k = 0; i < n; i++ ) { + String s = sa [ i ]; + if ( s.charAt(0) == 'Z' ) { + int nz = Integer.parseInt ( s.substring ( 1 ) ); + k += nz; + } else { + dp [ k / 4 ] [ k % 4 ] = Integer.parseInt ( s ); + k += 1; + } + } + } + } + } + return dp; + } + + /** + * Returns an attribute value as a glyph position adjustments array. The string value + * is expected to be a non-empty sequence of either Z or , where the + * former encodes a repeat count (of zeroes) and the latter encodes a integer number, + * and where each item is separated by whitespace. + * @param attributes the Attributes object + * @param name the name of the attribute + * @return the position adjustments array + */ + public static int[][] getAttributeAsPositionAdjustments(Attributes attributes, String name) { + String s = attributes.getValue(name); + if (s == null) { + return null; + } else { + return decodePositionAdjustments(s.trim()); + } + } + } diff --git a/src/sandbox/org/apache/fop/render/mif/MIFHandler.java b/src/sandbox/org/apache/fop/render/mif/MIFHandler.java index 0adf8bf5b..34eb7dc8d 100644 --- a/src/sandbox/org/apache/fop/render/mif/MIFHandler.java +++ b/src/sandbox/org/apache/fop/render/mif/MIFHandler.java @@ -84,7 +84,8 @@ public class MIFHandler extends FOEventHandler { public MIFHandler(FOUserAgent ua, OutputStream os) { super(ua); outStream = os; - FontSetup.setup(fontInfo, null, new DefaultFontResolver(ua)); + boolean base14Kerning = false; //TODO - FIXME + FontSetup.setup(fontInfo, null, new DefaultFontResolver(ua), base14Kerning); } /** {@inheritDoc} */ diff --git a/src/sandbox/org/apache/fop/render/svg/SVGPainter.java b/src/sandbox/org/apache/fop/render/svg/SVGPainter.java index bcc3a6913..3eba51097 100644 --- a/src/sandbox/org/apache/fop/render/svg/SVGPainter.java +++ b/src/sandbox/org/apache/fop/render/svg/SVGPainter.java @@ -49,6 +49,7 @@ import org.apache.fop.render.intermediate.IFConstants; import org.apache.fop.render.intermediate.IFContext; import org.apache.fop.render.intermediate.IFException; import org.apache.fop.render.intermediate.IFState; +import org.apache.fop.render.intermediate.IFUtil; import org.apache.fop.traits.BorderProps; import org.apache.fop.traits.RuleStyle; import org.apache.fop.util.ColorUtil; @@ -319,7 +320,7 @@ public class SVGPainter extends AbstractIFPainter implements SVGConstants { /** {@inheritDoc} */ - public void drawText(int x, int y, int letterSpacing, int wordSpacing, int[] dx, + public void drawText(int x, int y, int letterSpacing, int wordSpacing, int[][] dp, String text) throws IFException { try { establish(MODE_TEXT); @@ -333,7 +334,8 @@ public class SVGPainter extends AbstractIFPainter implements SVGConstants { if (wordSpacing != 0) { XMLUtil.addAttribute(atts, "word-spacing", SVGUtil.formatMptToPt(wordSpacing)); } - if (dx != null) { + if (dp != null) { + int[] dx = IFUtil.convertDPToDX(dp); XMLUtil.addAttribute(atts, "dx", SVGUtil.formatMptArrayToPt(dx)); } handler.startElement("text", atts); diff --git a/test/java/org/apache/fop/complexscripts/ComplexScriptsTestSuite.java b/test/java/org/apache/fop/complexscripts/ComplexScriptsTestSuite.java new file mode 100644 index 000000000..1dc0610b9 --- /dev/null +++ b/test/java/org/apache/fop/complexscripts/ComplexScriptsTestSuite.java @@ -0,0 +1,42 @@ +/* + * 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.complexscripts; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; +import org.junit.runners.Suite.SuiteClasses; + +import org.apache.fop.complexscripts.bidi.BidiTestSuite; +import org.apache.fop.complexscripts.fonts.FontsTestSuite; +import org.apache.fop.complexscripts.scripts.ScriptsTestSuite; +import org.apache.fop.complexscripts.util.UtilTestSuite; + +/** + * Test suite for complex scripts functionality. + */ +@RunWith(Suite.class) +@SuiteClasses({ + BidiTestSuite.class, + FontsTestSuite.class, + ScriptsTestSuite.class, + UtilTestSuite.class +}) +public class ComplexScriptsTestSuite { +} diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiAlgorithmTestCase.java b/test/java/org/apache/fop/complexscripts/bidi/BidiAlgorithmTestCase.java new file mode 100644 index 000000000..41115df98 --- /dev/null +++ b/test/java/org/apache/fop/complexscripts/bidi/BidiAlgorithmTestCase.java @@ -0,0 +1,265 @@ +/* + * 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.complexscripts.bidi; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.apache.fop.complexscripts.bidi.UnicodeBidiAlgorithm; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + +/** + *

    Test case for Unicode Bidi Algorithm.

    + * @author Glenn Adams + */ +public class BidiAlgorithmTestCase { + + /** + * logging instance + */ + private static final Log log = LogFactory.getLog(BidiAlgorithmTestCase.class); // CSOK: ConstantNameCheck + + /** + * Concatenated array of tuples + * specifying which sequences are to be excluded from testing, + * where -1 for either component is a wildcard. + */ + private static final int[] EXCLUSIONS = { + // no exclusions + }; + + /** + * Concatenated array of tuples + * specifying which sequences are to be included in testing, where + * -1 for either component is a wildcard. + */ + private static final int[] INCLUSIONS = { + -1, -1 // all sequences + }; + + /** + * Concatenated array of tuples expressing ranges of + * test sets to be tested, where -1 in the end position signifies + * all remaining test sets. + */ + private static final int[] TEST_SET_RANGES = { + 0, -1 // all test sets + }; + + // instrumentation + private int includedSequences; + private int excludedSequences; + private int passedSequences; + + @Test + public void testBidiAlgorithm() throws Exception { + String ldPfx = BidiTestData.LD_PFX; + int ldCount = BidiTestData.LD_CNT; + for ( int i = 0; i < ldCount; i++ ) { + int[] da = BidiTestData.readTestData ( ldPfx, i ); + if ( da != null ) { + testBidiAlgorithm ( i, da ); + } else { + fail ( "unable to read bidi test data for resource at index " + i ); + } + } + // ensure we passed all test sequences + assertEquals ( "did not pass all test sequences", BidiTestData.NUM_TEST_SEQUENCES, passedSequences ); + if ( log.isDebugEnabled() ) { + log.debug ( "Included Sequences : " + includedSequences ); + log.debug ( "Excluded Sequences : " + excludedSequences ); + log.debug( "Passed Sequences : " + passedSequences ); + } + } + + private void testBidiAlgorithm ( int testSet, int[] da ) throws Exception { + if ( da.length < 1 ) { + fail ( "test data is empty" ); + } else if ( da.length < ( ( da[0] * 2 ) + 1 ) ) { + fail ( "test data is truncated" ); + } else { + int k = 0; + // extract level count + int n = da[k++]; + // extract level array + int[] la = new int [ n ]; + for ( int i = 0; i < n; i++ ) { + la[i] = da[k++]; + } + // extract reorder array + int[] ra = new int [ n ]; + for ( int i = 0; i < n; i++ ) { + ra[i] = da[k++]; + } + // extract and test each test sequence + int testSequence = 0; + int[] ta = new int [ n ]; + while ( ( k + ( 1 + n ) ) <= da.length ) { + int bs = da[k++]; + for ( int i = 0; i < n; i++ ) { + ta[i] = da[k++]; + } + if ( includeSequence ( testSet, testSequence ) ) { + includedSequences++; + if ( ! excludeSequence ( testSet, testSequence ) ) { + if ( testBidiAlgorithm ( testSet, testSequence, la, ra, ta, bs ) ) { + passedSequences++; + } + } else { + excludedSequences++; + } + } + testSequence++; + } + // ensure we exhausted test data + assertEquals ( "extraneous test data", da.length, k ); + } + } + + private boolean includeTestSet ( int testSet ) { + for ( int i = 0, n = TEST_SET_RANGES.length / 2; i < n; i++ ) { + int s = TEST_SET_RANGES [ ( i * 2 ) + 0 ]; + int e = TEST_SET_RANGES [ ( i * 2 ) + 1 ]; + if ( testSet >= s ) { + if ( ( e < 0 ) || ( testSet <= e ) ) { + return true; + } + } + } + return false; + } + + private boolean includeSequence ( int testSet, int testSequence ) { + if ( ! includeTestSet ( testSet ) ) { + return false; + } else { + for ( int i = 0, n = INCLUSIONS.length / 2; i < n; i++ ) { + int setno = INCLUSIONS [ ( i * 2 ) + 0 ]; + int seqno = INCLUSIONS [ ( i * 2 ) + 1 ]; + if ( setno < 0 ) { + if ( seqno < 0 ) { + return true; + } else if ( seqno == testSequence ) { + return true; + } + } else if ( setno == testSet ) { + if ( seqno < 0 ) { + return true; + } else if ( seqno == testSequence ) { + return true; + } + } + } + return false; + } + } + + private boolean excludeSequence ( int testSet, int testSequence ) { + for ( int i = 0, n = EXCLUSIONS.length / 2; i < n; i++ ) { + int setno = EXCLUSIONS [ ( i * 2 ) + 0 ]; + int seqno = EXCLUSIONS [ ( i * 2 ) + 1 ]; + if ( setno < 0 ) { + if ( seqno < 0 ) { + return true; + } else if ( seqno == testSequence ) { + return true; + } + } else if ( setno == testSet ) { + if ( seqno < 0 ) { + return true; + } else if ( seqno == testSequence ) { + return true; + } + } + } + return false; + } + + private boolean testBidiAlgorithm ( int testSet, int testSequence, int[] la, int[] ra, int[] ta, int bs ) throws Exception { + boolean passed = true; + int n = la.length; + if ( ra.length != n ) { + fail ( "bad reorder array length, expected " + n + ", got " + ra.length ); + } else if ( ta.length != n ) { + fail ( "bad test array length, expected " + n + ", got " + ta.length ); + } else { + // auto-LTR + if ( ( bs & 1 ) != 0 ) { + // auto-LTR is performed at higher level + } + // LTR + if ( ( bs & 2 ) != 0 ) { + int[] levels = UnicodeBidiAlgorithm.resolveLevels ( null, ta, 0, new int [ n ], true ); + if ( ! verifyResults ( la, levels, ta, 0, testSet, testSequence ) ) { + passed = false; + } + } + // RTL + if ( ( bs & 4 ) != 0 ) { + int[] levels = UnicodeBidiAlgorithm.resolveLevels ( null, ta, 1, new int [ n ], true ); + if ( ! verifyResults ( la, levels, ta, 1, testSet, testSequence ) ) { + passed = false; + } + } + } + return passed; + } + + private boolean verifyResults ( int[] laExp, int[] laOut, int[] ta, int dl, int testSet, int testSequence ) { + if ( laOut.length != laExp.length ) { + fail ( "output levels array length mismatch, expected " + laExp.length + ", got " + laOut.length ); + return false; + } else { + int numMatch = 0; + for ( int i = 0, n = laExp.length; i < n; i++ ) { + if ( laExp[i] >= 0 ) { + int lo = laOut[i]; + int le = laExp[i]; + if ( lo != le ) { + assertEquals ( getMismatchMessage ( testSet, testSequence, i, dl ), le, lo ); + } else { + numMatch++; + } + } else { + numMatch++; + } + } + return numMatch == laExp.length; + } + } + + private String getMismatchMessage ( int testSet, int testSequence, int seqIndex, int defaultLevel ) { + StringBuffer sb = new StringBuffer(); + sb.append ( "level mismatch for default level " ); + sb.append ( defaultLevel ); + sb.append ( " at sequence index " ); + sb.append ( seqIndex ); + sb.append ( " in test sequence " ); + sb.append ( testSequence ); + sb.append ( " of test set " ); + sb.append ( testSet ); + return sb.toString(); + } + +} diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiClassTestCase.java b/test/java/org/apache/fop/complexscripts/bidi/BidiClassTestCase.java new file mode 100644 index 000000000..0ea9017bc --- /dev/null +++ b/test/java/org/apache/fop/complexscripts/bidi/BidiClassTestCase.java @@ -0,0 +1,58 @@ +/* + * 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.complexscripts.bidi; + +import org.apache.fop.complexscripts.bidi.BidiClass; +import org.apache.fop.util.CharUtilities; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + +public class BidiClassTestCase { + + @Test + public void testBidiClasses() throws Exception { + String tdPfx = BidiTestData.TD_PFX; + int tdCount = BidiTestData.TD_CNT; + for ( int i = 0; i < tdCount; i++ ) { + int[] da = BidiTestData.readTestData ( tdPfx, i ); + if ( da != null ) { + testBidiClass ( da ); + } else { + fail ( "unable to read bidi test data for resource at index " + i ); + } + } + } + + private void testBidiClass ( int[] da ) throws Exception { + int bc = da[0]; + for ( int i = 1, n = da.length; i < n; i += 2 ) { + int s = da[i+0]; + int e = da[i+1]; + for ( int c = s; c < e; c++ ) { + int cbc = BidiClass.getBidiClass ( c ); + assertEquals ( "bad bidi class for CH(" + CharUtilities.format ( c ) + ")", bc, cbc ); + } + } + } + +} diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD0.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD0.ser new file mode 100644 index 000000000..6eccb4b6f Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD0.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD1.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD1.ser new file mode 100644 index 000000000..8a7a802d2 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD1.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD10.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD10.ser new file mode 100644 index 000000000..74a52f212 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD10.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD100.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD100.ser new file mode 100644 index 000000000..4058da121 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD100.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD101.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD101.ser new file mode 100644 index 000000000..321ed2682 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD101.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD102.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD102.ser new file mode 100644 index 000000000..f5e3973dd Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD102.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD103.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD103.ser new file mode 100644 index 000000000..0235952c9 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD103.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD104.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD104.ser new file mode 100644 index 000000000..00d9ff6b4 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD104.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD105.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD105.ser new file mode 100644 index 000000000..b924c8d19 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD105.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD106.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD106.ser new file mode 100644 index 000000000..2cdabbf17 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD106.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD107.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD107.ser new file mode 100644 index 000000000..24e41ceab Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD107.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD108.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD108.ser new file mode 100644 index 000000000..8c9d014f2 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD108.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD109.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD109.ser new file mode 100644 index 000000000..fc2fc255e Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD109.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD11.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD11.ser new file mode 100644 index 000000000..2a40fe758 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD11.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD110.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD110.ser new file mode 100644 index 000000000..89ef3a341 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD110.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD111.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD111.ser new file mode 100644 index 000000000..0691f5f96 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD111.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD112.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD112.ser new file mode 100644 index 000000000..c3bd6103e Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD112.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD113.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD113.ser new file mode 100644 index 000000000..54d27e213 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD113.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD114.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD114.ser new file mode 100644 index 000000000..0ba52993a Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD114.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD115.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD115.ser new file mode 100644 index 000000000..0b95e6283 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD115.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD116.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD116.ser new file mode 100644 index 000000000..ca1111447 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD116.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD117.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD117.ser new file mode 100644 index 000000000..fbce0f949 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD117.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD118.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD118.ser new file mode 100644 index 000000000..c7bee5162 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD118.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD119.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD119.ser new file mode 100644 index 000000000..83ad166ef Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD119.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD12.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD12.ser new file mode 100644 index 000000000..81ff5dcbd Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD12.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD120.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD120.ser new file mode 100644 index 000000000..2a84369ef Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD120.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD121.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD121.ser new file mode 100644 index 000000000..3c3f08edf Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD121.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD122.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD122.ser new file mode 100644 index 000000000..81a342bc0 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD122.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD123.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD123.ser new file mode 100644 index 000000000..f2fdba316 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD123.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD124.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD124.ser new file mode 100644 index 000000000..5bebb054f Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD124.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD125.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD125.ser new file mode 100644 index 000000000..1292a8a01 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD125.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD126.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD126.ser new file mode 100644 index 000000000..f7c910fb0 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD126.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD127.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD127.ser new file mode 100644 index 000000000..bb2d2353a Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD127.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD128.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD128.ser new file mode 100644 index 000000000..4ef886527 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD128.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD129.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD129.ser new file mode 100644 index 000000000..7538307f8 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD129.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD13.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD13.ser new file mode 100644 index 000000000..5a81f8f76 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD13.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD130.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD130.ser new file mode 100644 index 000000000..dfa56bb42 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD130.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD131.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD131.ser new file mode 100644 index 000000000..04c0e6b02 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD131.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD132.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD132.ser new file mode 100644 index 000000000..5389ec53c Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD132.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD133.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD133.ser new file mode 100644 index 000000000..6ec49f1c7 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD133.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD134.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD134.ser new file mode 100644 index 000000000..381b6b741 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD134.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD135.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD135.ser new file mode 100644 index 000000000..e991a278f Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD135.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD136.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD136.ser new file mode 100644 index 000000000..84eb27fa3 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD136.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD137.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD137.ser new file mode 100644 index 000000000..3e3ceb4f0 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD137.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD138.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD138.ser new file mode 100644 index 000000000..52f01ebbf Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD138.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD139.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD139.ser new file mode 100644 index 000000000..54a66ac43 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD139.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD14.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD14.ser new file mode 100644 index 000000000..5bad9fe23 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD14.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD140.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD140.ser new file mode 100644 index 000000000..7e58aea97 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD140.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD141.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD141.ser new file mode 100644 index 000000000..60811580c Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD141.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD142.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD142.ser new file mode 100644 index 000000000..bfa39bf75 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD142.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD143.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD143.ser new file mode 100644 index 000000000..5df598aa7 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD143.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD144.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD144.ser new file mode 100644 index 000000000..f46f6a289 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD144.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD145.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD145.ser new file mode 100644 index 000000000..825930ea8 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD145.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD146.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD146.ser new file mode 100644 index 000000000..3d2efe600 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD146.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD147.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD147.ser new file mode 100644 index 000000000..5e3667df8 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD147.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD148.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD148.ser new file mode 100644 index 000000000..4a04343a5 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD148.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD149.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD149.ser new file mode 100644 index 000000000..85260e0f8 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD149.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD15.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD15.ser new file mode 100644 index 000000000..c1cb2878d Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD15.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD150.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD150.ser new file mode 100644 index 000000000..ab5dd0c00 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD150.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD151.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD151.ser new file mode 100644 index 000000000..df304a84b Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD151.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD152.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD152.ser new file mode 100644 index 000000000..887699163 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD152.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD153.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD153.ser new file mode 100644 index 000000000..fa70ead76 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD153.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD154.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD154.ser new file mode 100644 index 000000000..73402d898 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD154.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD155.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD155.ser new file mode 100644 index 000000000..c611d952e Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD155.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD156.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD156.ser new file mode 100644 index 000000000..a5a70cf81 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD156.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD157.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD157.ser new file mode 100644 index 000000000..736576c15 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD157.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD158.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD158.ser new file mode 100644 index 000000000..4667a5a4a Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD158.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD159.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD159.ser new file mode 100644 index 000000000..9a07236c3 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD159.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD16.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD16.ser new file mode 100644 index 000000000..6a8e667fb Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD16.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD160.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD160.ser new file mode 100644 index 000000000..abfeac3ec Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD160.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD161.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD161.ser new file mode 100644 index 000000000..1b225c825 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD161.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD162.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD162.ser new file mode 100644 index 000000000..36aab1fd1 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD162.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD163.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD163.ser new file mode 100644 index 000000000..77a744263 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD163.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD164.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD164.ser new file mode 100644 index 000000000..6f340e971 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD164.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD165.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD165.ser new file mode 100644 index 000000000..92ab48e50 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD165.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD166.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD166.ser new file mode 100644 index 000000000..412885433 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD166.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD167.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD167.ser new file mode 100644 index 000000000..3b4b83607 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD167.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD168.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD168.ser new file mode 100644 index 000000000..3e04f60f7 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD168.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD169.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD169.ser new file mode 100644 index 000000000..5e58d00f8 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD169.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD17.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD17.ser new file mode 100644 index 000000000..290d0e5b4 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD17.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD170.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD170.ser new file mode 100644 index 000000000..fb1f6b7ae Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD170.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD171.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD171.ser new file mode 100644 index 000000000..7ba80984d Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD171.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD172.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD172.ser new file mode 100644 index 000000000..594645bdc Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD172.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD173.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD173.ser new file mode 100644 index 000000000..5d995d076 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD173.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD174.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD174.ser new file mode 100644 index 000000000..e57c46d8e Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD174.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD175.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD175.ser new file mode 100644 index 000000000..ad4317529 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD175.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD176.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD176.ser new file mode 100644 index 000000000..52cdcd567 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD176.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD177.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD177.ser new file mode 100644 index 000000000..e786ab17e Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD177.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD178.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD178.ser new file mode 100644 index 000000000..2f9e41f08 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD178.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD179.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD179.ser new file mode 100644 index 000000000..94f739223 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD179.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD18.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD18.ser new file mode 100644 index 000000000..53073211e Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD18.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD180.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD180.ser new file mode 100644 index 000000000..172498f80 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD180.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD181.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD181.ser new file mode 100644 index 000000000..c5a9b434d Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD181.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD182.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD182.ser new file mode 100644 index 000000000..1c98e34a4 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD182.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD183.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD183.ser new file mode 100644 index 000000000..4e8c8e30c Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD183.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD184.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD184.ser new file mode 100644 index 000000000..824fad23d Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD184.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD185.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD185.ser new file mode 100644 index 000000000..969e34a37 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD185.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD186.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD186.ser new file mode 100644 index 000000000..0867d2e55 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD186.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD187.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD187.ser new file mode 100644 index 000000000..dd052d7a1 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD187.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD188.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD188.ser new file mode 100644 index 000000000..d52c97d1d Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD188.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD189.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD189.ser new file mode 100644 index 000000000..2bdb9dab4 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD189.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD19.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD19.ser new file mode 100644 index 000000000..21128bf86 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD19.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD190.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD190.ser new file mode 100644 index 000000000..d153d3442 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD190.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD191.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD191.ser new file mode 100644 index 000000000..5019d6fea Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD191.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD192.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD192.ser new file mode 100644 index 000000000..e726e2651 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD192.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD193.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD193.ser new file mode 100644 index 000000000..c37e1cdd0 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD193.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD194.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD194.ser new file mode 100644 index 000000000..1ba7b2877 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD194.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD195.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD195.ser new file mode 100644 index 000000000..62215ed07 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD195.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD196.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD196.ser new file mode 100644 index 000000000..709279994 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD196.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD197.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD197.ser new file mode 100644 index 000000000..788ac372f Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD197.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD198.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD198.ser new file mode 100644 index 000000000..9d4a14249 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD198.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD199.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD199.ser new file mode 100644 index 000000000..6cbb79535 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD199.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD2.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD2.ser new file mode 100644 index 000000000..05cf07859 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD2.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD20.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD20.ser new file mode 100644 index 000000000..9c10e367c Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD20.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD200.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD200.ser new file mode 100644 index 000000000..583084f0b Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD200.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD201.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD201.ser new file mode 100644 index 000000000..d8ed032c6 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD201.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD202.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD202.ser new file mode 100644 index 000000000..21e97fff0 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD202.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD203.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD203.ser new file mode 100644 index 000000000..5e3e01293 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD203.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD204.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD204.ser new file mode 100644 index 000000000..eba9874c5 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD204.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD205.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD205.ser new file mode 100644 index 000000000..182c5fc35 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD205.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD206.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD206.ser new file mode 100644 index 000000000..47ed04ba6 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD206.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD207.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD207.ser new file mode 100644 index 000000000..b56f3ee7c Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD207.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD208.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD208.ser new file mode 100644 index 000000000..302b20c39 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD208.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD209.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD209.ser new file mode 100644 index 000000000..c97cbbe12 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD209.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD21.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD21.ser new file mode 100644 index 000000000..e7eb886be Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD21.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD210.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD210.ser new file mode 100644 index 000000000..4da33f6c0 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD210.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD211.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD211.ser new file mode 100644 index 000000000..46f29b71a Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD211.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD212.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD212.ser new file mode 100644 index 000000000..b84d2efaa Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD212.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD213.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD213.ser new file mode 100644 index 000000000..2d0995a6f Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD213.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD214.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD214.ser new file mode 100644 index 000000000..66a505aae Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD214.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD215.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD215.ser new file mode 100644 index 000000000..cbd99924e Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD215.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD216.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD216.ser new file mode 100644 index 000000000..46b5315a0 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD216.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD217.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD217.ser new file mode 100644 index 000000000..4afc67dbc Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD217.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD218.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD218.ser new file mode 100644 index 000000000..992177ded Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD218.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD219.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD219.ser new file mode 100644 index 000000000..e75b1d344 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD219.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD22.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD22.ser new file mode 100644 index 000000000..ca7478b6c Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD22.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD220.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD220.ser new file mode 100644 index 000000000..3f754847c Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD220.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD221.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD221.ser new file mode 100644 index 000000000..02efa8786 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD221.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD222.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD222.ser new file mode 100644 index 000000000..1897b09f8 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD222.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD223.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD223.ser new file mode 100644 index 000000000..cd24d1101 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD223.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD224.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD224.ser new file mode 100644 index 000000000..aba011dba Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD224.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD225.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD225.ser new file mode 100644 index 000000000..dad463960 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD225.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD226.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD226.ser new file mode 100644 index 000000000..6430967e4 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD226.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD227.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD227.ser new file mode 100644 index 000000000..4f2bde014 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD227.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD228.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD228.ser new file mode 100644 index 000000000..7be09ec92 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD228.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD229.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD229.ser new file mode 100644 index 000000000..6ffa285db Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD229.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD23.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD23.ser new file mode 100644 index 000000000..d6c532596 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD23.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD230.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD230.ser new file mode 100644 index 000000000..3519adb5e Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD230.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD231.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD231.ser new file mode 100644 index 000000000..7540663aa Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD231.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD232.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD232.ser new file mode 100644 index 000000000..788e4c7e1 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD232.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD233.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD233.ser new file mode 100644 index 000000000..c36265614 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD233.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD234.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD234.ser new file mode 100644 index 000000000..772b72aef Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD234.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD235.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD235.ser new file mode 100644 index 000000000..e5fa50b85 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD235.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD236.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD236.ser new file mode 100644 index 000000000..13fdb364c Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD236.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD237.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD237.ser new file mode 100644 index 000000000..c600524d6 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD237.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD238.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD238.ser new file mode 100644 index 000000000..6043e0155 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD238.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD239.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD239.ser new file mode 100644 index 000000000..14250a315 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD239.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD24.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD24.ser new file mode 100644 index 000000000..209e8179e Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD24.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD240.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD240.ser new file mode 100644 index 000000000..bdbc02f69 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD240.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD241.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD241.ser new file mode 100644 index 000000000..d3f40a8de Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD241.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD242.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD242.ser new file mode 100644 index 000000000..03b94bc76 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD242.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD243.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD243.ser new file mode 100644 index 000000000..cb0321933 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD243.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD244.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD244.ser new file mode 100644 index 000000000..3cdc87c9c Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD244.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD245.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD245.ser new file mode 100644 index 000000000..7c50f1284 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD245.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD246.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD246.ser new file mode 100644 index 000000000..b04164e4c Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD246.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD247.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD247.ser new file mode 100644 index 000000000..bdce40f9c Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD247.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD248.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD248.ser new file mode 100644 index 000000000..e50ed7988 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD248.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD249.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD249.ser new file mode 100644 index 000000000..14ac62043 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD249.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD25.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD25.ser new file mode 100644 index 000000000..c1b31fcce Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD25.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD250.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD250.ser new file mode 100644 index 000000000..d96343972 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD250.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD251.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD251.ser new file mode 100644 index 000000000..7b3168b23 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD251.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD252.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD252.ser new file mode 100644 index 000000000..7f9b9056d Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD252.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD253.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD253.ser new file mode 100644 index 000000000..d5849ec9d Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD253.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD254.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD254.ser new file mode 100644 index 000000000..00a2b4a0e Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD254.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD255.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD255.ser new file mode 100644 index 000000000..5cc330f12 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD255.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD256.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD256.ser new file mode 100644 index 000000000..23e032ac9 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD256.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD257.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD257.ser new file mode 100644 index 000000000..7ba16c21a Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD257.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD258.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD258.ser new file mode 100644 index 000000000..334737ecd Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD258.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD259.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD259.ser new file mode 100644 index 000000000..26defabff Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD259.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD26.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD26.ser new file mode 100644 index 000000000..09dc4ca08 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD26.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD260.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD260.ser new file mode 100644 index 000000000..03cb82426 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD260.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD261.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD261.ser new file mode 100644 index 000000000..6d00960cf Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD261.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD262.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD262.ser new file mode 100644 index 000000000..920e4c5b1 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD262.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD263.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD263.ser new file mode 100644 index 000000000..dbbee5d7f Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD263.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD264.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD264.ser new file mode 100644 index 000000000..716661a75 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD264.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD265.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD265.ser new file mode 100644 index 000000000..b418d9b9f Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD265.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD266.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD266.ser new file mode 100644 index 000000000..bc16ddcff Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD266.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD267.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD267.ser new file mode 100644 index 000000000..a105347f0 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD267.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD268.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD268.ser new file mode 100644 index 000000000..f75552dc3 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD268.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD269.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD269.ser new file mode 100644 index 000000000..a3f6eab8f Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD269.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD27.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD27.ser new file mode 100644 index 000000000..604170dcc Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD27.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD270.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD270.ser new file mode 100644 index 000000000..755d6cd60 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD270.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD271.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD271.ser new file mode 100644 index 000000000..9b29a7d1e Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD271.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD272.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD272.ser new file mode 100644 index 000000000..5685e40b8 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD272.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD273.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD273.ser new file mode 100644 index 000000000..49a7c0739 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD273.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD274.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD274.ser new file mode 100644 index 000000000..1697a421b Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD274.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD275.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD275.ser new file mode 100644 index 000000000..ea0d9adf1 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD275.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD276.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD276.ser new file mode 100644 index 000000000..067dca228 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD276.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD277.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD277.ser new file mode 100644 index 000000000..9f9078678 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD277.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD278.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD278.ser new file mode 100644 index 000000000..9cd498c3c Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD278.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD279.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD279.ser new file mode 100644 index 000000000..c5c4c6ab0 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD279.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD28.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD28.ser new file mode 100644 index 000000000..890ce30bb Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD28.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD280.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD280.ser new file mode 100644 index 000000000..fac475452 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD280.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD281.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD281.ser new file mode 100644 index 000000000..4711e4586 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD281.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD282.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD282.ser new file mode 100644 index 000000000..1fcea5dbf Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD282.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD283.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD283.ser new file mode 100644 index 000000000..bf2a0bcc5 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD283.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD284.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD284.ser new file mode 100644 index 000000000..29a3c23d4 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD284.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD285.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD285.ser new file mode 100644 index 000000000..fea28c7d2 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD285.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD286.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD286.ser new file mode 100644 index 000000000..48663053e Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD286.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD287.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD287.ser new file mode 100644 index 000000000..43f440cf7 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD287.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD288.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD288.ser new file mode 100644 index 000000000..385ac7184 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD288.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD289.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD289.ser new file mode 100644 index 000000000..8a032f261 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD289.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD29.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD29.ser new file mode 100644 index 000000000..fdc27290b Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD29.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD290.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD290.ser new file mode 100644 index 000000000..264c28e08 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD290.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD291.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD291.ser new file mode 100644 index 000000000..daf236abf Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD291.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD292.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD292.ser new file mode 100644 index 000000000..8f972bf5a Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD292.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD293.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD293.ser new file mode 100644 index 000000000..647424ee0 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD293.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD294.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD294.ser new file mode 100644 index 000000000..9e8b99773 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD294.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD295.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD295.ser new file mode 100644 index 000000000..486bcf475 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD295.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD296.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD296.ser new file mode 100644 index 000000000..856d72fd1 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD296.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD297.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD297.ser new file mode 100644 index 000000000..ce0b5bf4c Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD297.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD298.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD298.ser new file mode 100644 index 000000000..cad0d5049 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD298.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD299.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD299.ser new file mode 100644 index 000000000..b14aa4597 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD299.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD3.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD3.ser new file mode 100644 index 000000000..6657a3593 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD3.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD30.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD30.ser new file mode 100644 index 000000000..b30faf809 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD30.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD300.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD300.ser new file mode 100644 index 000000000..4baca2704 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD300.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD301.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD301.ser new file mode 100644 index 000000000..630a13467 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD301.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD302.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD302.ser new file mode 100644 index 000000000..0f8e3d7d8 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD302.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD303.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD303.ser new file mode 100644 index 000000000..42a05ced7 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD303.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD304.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD304.ser new file mode 100644 index 000000000..13ba94a7e Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD304.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD305.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD305.ser new file mode 100644 index 000000000..e5a3a925e Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD305.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD306.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD306.ser new file mode 100644 index 000000000..1ada57413 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD306.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD307.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD307.ser new file mode 100644 index 000000000..a14a0bebf Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD307.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD308.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD308.ser new file mode 100644 index 000000000..c66ae933f Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD308.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD309.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD309.ser new file mode 100644 index 000000000..fd1e62ca8 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD309.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD31.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD31.ser new file mode 100644 index 000000000..4914c3b65 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD31.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD310.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD310.ser new file mode 100644 index 000000000..e8aad8cad Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD310.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD311.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD311.ser new file mode 100644 index 000000000..0d8f4cf1e Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD311.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD312.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD312.ser new file mode 100644 index 000000000..54d856156 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD312.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD313.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD313.ser new file mode 100644 index 000000000..5bd0e8286 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD313.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD314.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD314.ser new file mode 100644 index 000000000..37a4d8c68 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD314.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD315.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD315.ser new file mode 100644 index 000000000..a16a7b8f9 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD315.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD316.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD316.ser new file mode 100644 index 000000000..6e5747ed9 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD316.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD317.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD317.ser new file mode 100644 index 000000000..3ee6650ed Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD317.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD318.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD318.ser new file mode 100644 index 000000000..8c6f200a2 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD318.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD319.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD319.ser new file mode 100644 index 000000000..4774611b5 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD319.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD32.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD32.ser new file mode 100644 index 000000000..09332a05e Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD32.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD320.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD320.ser new file mode 100644 index 000000000..88327e077 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD320.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD321.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD321.ser new file mode 100644 index 000000000..600eb2ac3 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD321.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD322.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD322.ser new file mode 100644 index 000000000..eed01d875 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD322.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD323.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD323.ser new file mode 100644 index 000000000..cc2db9896 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD323.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD324.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD324.ser new file mode 100644 index 000000000..d0ae70999 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD324.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD325.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD325.ser new file mode 100644 index 000000000..eb2a30d19 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD325.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD326.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD326.ser new file mode 100644 index 000000000..5825c9571 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD326.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD327.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD327.ser new file mode 100644 index 000000000..c1b927a19 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD327.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD328.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD328.ser new file mode 100644 index 000000000..5d7eb7f7e Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD328.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD329.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD329.ser new file mode 100644 index 000000000..a78094615 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD329.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD33.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD33.ser new file mode 100644 index 000000000..efb28b562 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD33.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD330.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD330.ser new file mode 100644 index 000000000..686c66e20 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD330.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD331.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD331.ser new file mode 100644 index 000000000..b210f7896 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD331.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD332.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD332.ser new file mode 100644 index 000000000..da93f81fc Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD332.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD333.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD333.ser new file mode 100644 index 000000000..8a0f567f1 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD333.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD334.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD334.ser new file mode 100644 index 000000000..622bdd1e1 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD334.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD335.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD335.ser new file mode 100644 index 000000000..4baa13941 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD335.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD336.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD336.ser new file mode 100644 index 000000000..1d40b0818 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD336.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD337.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD337.ser new file mode 100644 index 000000000..ef0b76e42 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD337.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD338.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD338.ser new file mode 100644 index 000000000..bd0a0456f Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD338.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD339.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD339.ser new file mode 100644 index 000000000..73ee20cbe Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD339.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD34.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD34.ser new file mode 100644 index 000000000..9e33d39e9 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD34.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD340.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD340.ser new file mode 100644 index 000000000..6afa6bf7c Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD340.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD341.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD341.ser new file mode 100644 index 000000000..84782b980 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD341.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD342.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD342.ser new file mode 100644 index 000000000..fdde6d7a5 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD342.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD343.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD343.ser new file mode 100644 index 000000000..2654a884a Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD343.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD344.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD344.ser new file mode 100644 index 000000000..b24a2a444 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD344.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD345.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD345.ser new file mode 100644 index 000000000..613d80bee Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD345.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD346.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD346.ser new file mode 100644 index 000000000..df1df5fbf Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD346.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD347.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD347.ser new file mode 100644 index 000000000..3f68bd344 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD347.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD348.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD348.ser new file mode 100644 index 000000000..361734a3c Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD348.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD349.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD349.ser new file mode 100644 index 000000000..009e2419c Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD349.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD35.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD35.ser new file mode 100644 index 000000000..7c142c3e3 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD35.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD350.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD350.ser new file mode 100644 index 000000000..6e14a51a4 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD350.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD351.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD351.ser new file mode 100644 index 000000000..ed8f2450d Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD351.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD352.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD352.ser new file mode 100644 index 000000000..80489aa41 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD352.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD353.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD353.ser new file mode 100644 index 000000000..ede61bef1 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD353.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD354.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD354.ser new file mode 100644 index 000000000..e837ec5a6 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD354.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD355.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD355.ser new file mode 100644 index 000000000..0dbeb4a18 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD355.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD356.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD356.ser new file mode 100644 index 000000000..fdbc6a8f2 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD356.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD357.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD357.ser new file mode 100644 index 000000000..47665da0c Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD357.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD358.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD358.ser new file mode 100644 index 000000000..aae718782 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD358.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD359.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD359.ser new file mode 100644 index 000000000..5bc6e4083 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD359.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD36.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD36.ser new file mode 100644 index 000000000..07d3b8d15 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD36.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD360.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD360.ser new file mode 100644 index 000000000..81af1c964 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD360.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD361.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD361.ser new file mode 100644 index 000000000..4abfa7c14 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD361.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD362.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD362.ser new file mode 100644 index 000000000..aec3af860 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD362.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD363.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD363.ser new file mode 100644 index 000000000..ac1eecb96 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD363.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD364.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD364.ser new file mode 100644 index 000000000..1f1367be6 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD364.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD365.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD365.ser new file mode 100644 index 000000000..3cf337cda Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD365.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD366.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD366.ser new file mode 100644 index 000000000..19f7fd9e9 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD366.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD367.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD367.ser new file mode 100644 index 000000000..8c92df043 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD367.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD368.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD368.ser new file mode 100644 index 000000000..dad7f014b Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD368.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD369.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD369.ser new file mode 100644 index 000000000..b0022c672 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD369.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD37.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD37.ser new file mode 100644 index 000000000..bfbb586fb Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD37.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD370.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD370.ser new file mode 100644 index 000000000..b435feea0 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD370.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD371.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD371.ser new file mode 100644 index 000000000..dafe64d04 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD371.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD372.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD372.ser new file mode 100644 index 000000000..973fcdc92 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD372.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD373.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD373.ser new file mode 100644 index 000000000..a49d73cfe Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD373.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD374.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD374.ser new file mode 100644 index 000000000..892a50d1b Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD374.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD375.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD375.ser new file mode 100644 index 000000000..0fa29c84b Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD375.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD376.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD376.ser new file mode 100644 index 000000000..a29b52179 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD376.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD377.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD377.ser new file mode 100644 index 000000000..e7c2a5a36 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD377.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD378.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD378.ser new file mode 100644 index 000000000..0ec361014 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD378.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD379.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD379.ser new file mode 100644 index 000000000..bca795879 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD379.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD38.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD38.ser new file mode 100644 index 000000000..49ca3d106 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD38.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD380.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD380.ser new file mode 100644 index 000000000..0a340e65e Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD380.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD381.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD381.ser new file mode 100644 index 000000000..2e73aff87 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD381.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD382.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD382.ser new file mode 100644 index 000000000..d3a437077 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD382.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD383.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD383.ser new file mode 100644 index 000000000..963e0a877 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD383.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD384.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD384.ser new file mode 100644 index 000000000..092300f46 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD384.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD385.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD385.ser new file mode 100644 index 000000000..0c4c00312 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD385.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD386.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD386.ser new file mode 100644 index 000000000..9abf70ed9 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD386.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD387.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD387.ser new file mode 100644 index 000000000..7e518db09 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD387.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD388.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD388.ser new file mode 100644 index 000000000..797d08f9c Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD388.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD389.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD389.ser new file mode 100644 index 000000000..672e36e4a Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD389.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD39.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD39.ser new file mode 100644 index 000000000..de9d5aadb Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD39.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD390.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD390.ser new file mode 100644 index 000000000..44c076196 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD390.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD391.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD391.ser new file mode 100644 index 000000000..2706725f7 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD391.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD392.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD392.ser new file mode 100644 index 000000000..1cc61a4ed Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD392.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD393.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD393.ser new file mode 100644 index 000000000..33305fe62 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD393.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD394.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD394.ser new file mode 100644 index 000000000..278fb38d7 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD394.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD395.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD395.ser new file mode 100644 index 000000000..3d2ff817c Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD395.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD396.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD396.ser new file mode 100644 index 000000000..45833bacc Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD396.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD397.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD397.ser new file mode 100644 index 000000000..54e88ffc0 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD397.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD398.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD398.ser new file mode 100644 index 000000000..751b118a7 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD398.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD399.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD399.ser new file mode 100644 index 000000000..4acd804ca Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD399.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD4.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD4.ser new file mode 100644 index 000000000..c65761df1 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD4.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD40.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD40.ser new file mode 100644 index 000000000..d6759145b Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD40.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD400.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD400.ser new file mode 100644 index 000000000..4c9b21368 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD400.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD401.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD401.ser new file mode 100644 index 000000000..e3e6c6ec2 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD401.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD402.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD402.ser new file mode 100644 index 000000000..92e5a6187 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD402.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD403.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD403.ser new file mode 100644 index 000000000..873595ead Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD403.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD404.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD404.ser new file mode 100644 index 000000000..1709012da Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD404.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD405.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD405.ser new file mode 100644 index 000000000..5ad6315e3 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD405.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD406.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD406.ser new file mode 100644 index 000000000..aa04c95e2 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD406.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD407.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD407.ser new file mode 100644 index 000000000..12edd65ab Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD407.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD408.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD408.ser new file mode 100644 index 000000000..40290ec4c Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD408.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD409.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD409.ser new file mode 100644 index 000000000..b59671610 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD409.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD41.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD41.ser new file mode 100644 index 000000000..5d664e82c Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD41.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD410.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD410.ser new file mode 100644 index 000000000..9c5866504 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD410.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD411.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD411.ser new file mode 100644 index 000000000..01fe69955 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD411.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD412.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD412.ser new file mode 100644 index 000000000..b71d6c546 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD412.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD413.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD413.ser new file mode 100644 index 000000000..5ad3f0613 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD413.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD414.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD414.ser new file mode 100644 index 000000000..b89491a41 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD414.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD415.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD415.ser new file mode 100644 index 000000000..289f9b48d Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD415.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD416.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD416.ser new file mode 100644 index 000000000..24d1e1cbe Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD416.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD417.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD417.ser new file mode 100644 index 000000000..927349572 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD417.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD418.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD418.ser new file mode 100644 index 000000000..8208a5005 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD418.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD419.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD419.ser new file mode 100644 index 000000000..346fb131d Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD419.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD42.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD42.ser new file mode 100644 index 000000000..28c0e15e1 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD42.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD420.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD420.ser new file mode 100644 index 000000000..53d6b158d Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD420.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD421.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD421.ser new file mode 100644 index 000000000..c324000e4 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD421.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD422.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD422.ser new file mode 100644 index 000000000..d99423cbb Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD422.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD423.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD423.ser new file mode 100644 index 000000000..d78b800db Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD423.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD424.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD424.ser new file mode 100644 index 000000000..eabb33cc3 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD424.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD425.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD425.ser new file mode 100644 index 000000000..571728da3 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD425.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD426.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD426.ser new file mode 100644 index 000000000..25d9cb0aa Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD426.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD427.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD427.ser new file mode 100644 index 000000000..d493f3859 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD427.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD428.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD428.ser new file mode 100644 index 000000000..06b90d501 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD428.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD429.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD429.ser new file mode 100644 index 000000000..5b97f90ca Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD429.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD43.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD43.ser new file mode 100644 index 000000000..22b1b8d9b Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD43.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD430.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD430.ser new file mode 100644 index 000000000..db3749949 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD430.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD431.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD431.ser new file mode 100644 index 000000000..272364c6f Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD431.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD432.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD432.ser new file mode 100644 index 000000000..078a31f84 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD432.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD433.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD433.ser new file mode 100644 index 000000000..b4aaf015b Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD433.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD434.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD434.ser new file mode 100644 index 000000000..52c01f7e9 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD434.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD435.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD435.ser new file mode 100644 index 000000000..626e52df0 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD435.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD436.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD436.ser new file mode 100644 index 000000000..2de03dae5 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD436.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD437.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD437.ser new file mode 100644 index 000000000..041c1a4cf Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD437.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD438.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD438.ser new file mode 100644 index 000000000..c8da3b083 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD438.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD439.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD439.ser new file mode 100644 index 000000000..74f71d784 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD439.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD44.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD44.ser new file mode 100644 index 000000000..d1321181b Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD44.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD440.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD440.ser new file mode 100644 index 000000000..bcf11b73c Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD440.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD441.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD441.ser new file mode 100644 index 000000000..a9ba2dea1 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD441.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD442.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD442.ser new file mode 100644 index 000000000..fe728d89c Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD442.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD443.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD443.ser new file mode 100644 index 000000000..23d7eb22b Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD443.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD444.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD444.ser new file mode 100644 index 000000000..58f06cbce Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD444.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD445.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD445.ser new file mode 100644 index 000000000..bd56f8524 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD445.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD446.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD446.ser new file mode 100644 index 000000000..54d14da06 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD446.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD447.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD447.ser new file mode 100644 index 000000000..ee6f83422 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD447.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD448.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD448.ser new file mode 100644 index 000000000..f94d24f69 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD448.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD449.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD449.ser new file mode 100644 index 000000000..feef36694 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD449.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD45.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD45.ser new file mode 100644 index 000000000..93720aeac Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD45.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD450.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD450.ser new file mode 100644 index 000000000..d1a58aaa5 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD450.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD451.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD451.ser new file mode 100644 index 000000000..11f0d14b3 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD451.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD452.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD452.ser new file mode 100644 index 000000000..2aef6789e Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD452.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD453.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD453.ser new file mode 100644 index 000000000..e60e00a75 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD453.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD454.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD454.ser new file mode 100644 index 000000000..e7ed6f17e Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD454.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD455.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD455.ser new file mode 100644 index 000000000..49062bd27 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD455.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD456.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD456.ser new file mode 100644 index 000000000..5b4049240 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD456.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD457.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD457.ser new file mode 100644 index 000000000..c051bb336 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD457.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD458.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD458.ser new file mode 100644 index 000000000..bb781c485 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD458.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD459.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD459.ser new file mode 100644 index 000000000..289e7e587 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD459.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD46.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD46.ser new file mode 100644 index 000000000..c4b5db34b Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD46.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD460.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD460.ser new file mode 100644 index 000000000..bacc29cf6 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD460.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD461.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD461.ser new file mode 100644 index 000000000..d791c7d59 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD461.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD462.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD462.ser new file mode 100644 index 000000000..eac181fa5 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD462.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD463.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD463.ser new file mode 100644 index 000000000..4d4c36621 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD463.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD464.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD464.ser new file mode 100644 index 000000000..ab10d3c9d Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD464.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD465.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD465.ser new file mode 100644 index 000000000..ada0cfb53 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD465.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD466.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD466.ser new file mode 100644 index 000000000..b2f924cb4 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD466.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD467.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD467.ser new file mode 100644 index 000000000..4965ccab3 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD467.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD468.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD468.ser new file mode 100644 index 000000000..f04ae6182 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD468.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD469.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD469.ser new file mode 100644 index 000000000..27fc5e31f Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD469.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD47.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD47.ser new file mode 100644 index 000000000..dd2f2f73d Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD47.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD470.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD470.ser new file mode 100644 index 000000000..868c0718f Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD470.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD471.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD471.ser new file mode 100644 index 000000000..95ba064e9 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD471.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD472.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD472.ser new file mode 100644 index 000000000..ec1bcb735 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD472.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD473.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD473.ser new file mode 100644 index 000000000..d4bfab753 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD473.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD474.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD474.ser new file mode 100644 index 000000000..bf4de5393 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD474.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD475.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD475.ser new file mode 100644 index 000000000..b01e493df Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD475.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD476.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD476.ser new file mode 100644 index 000000000..247977216 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD476.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD477.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD477.ser new file mode 100644 index 000000000..0a4655675 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD477.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD478.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD478.ser new file mode 100644 index 000000000..7847c8b34 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD478.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD479.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD479.ser new file mode 100644 index 000000000..6ac093714 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD479.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD48.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD48.ser new file mode 100644 index 000000000..1fb8a568a Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD48.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD480.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD480.ser new file mode 100644 index 000000000..4f5ce8e37 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD480.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD481.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD481.ser new file mode 100644 index 000000000..b9cf2310e Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD481.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD482.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD482.ser new file mode 100644 index 000000000..d8cc78a39 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD482.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD483.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD483.ser new file mode 100644 index 000000000..44438e065 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD483.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD484.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD484.ser new file mode 100644 index 000000000..a6227255a Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD484.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD485.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD485.ser new file mode 100644 index 000000000..415f6c049 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD485.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD486.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD486.ser new file mode 100644 index 000000000..8ea2f93ad Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD486.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD487.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD487.ser new file mode 100644 index 000000000..ca7f77129 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD487.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD488.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD488.ser new file mode 100644 index 000000000..5aaf07824 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD488.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD489.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD489.ser new file mode 100644 index 000000000..655516191 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD489.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD49.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD49.ser new file mode 100644 index 000000000..3cc2d4a75 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD49.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD490.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD490.ser new file mode 100644 index 000000000..94f1d83fd Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD490.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD491.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD491.ser new file mode 100644 index 000000000..14b49f0a4 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD491.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD492.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD492.ser new file mode 100644 index 000000000..adb3d3737 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD492.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD493.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD493.ser new file mode 100644 index 000000000..b2c4902eb Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD493.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD494.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD494.ser new file mode 100644 index 000000000..8b28deac8 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD494.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD495.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD495.ser new file mode 100644 index 000000000..5d238271b Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD495.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD496.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD496.ser new file mode 100644 index 000000000..ab8f4d6d1 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD496.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD497.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD497.ser new file mode 100644 index 000000000..901e4173d Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD497.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD498.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD498.ser new file mode 100644 index 000000000..d6fd495bb Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD498.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD499.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD499.ser new file mode 100644 index 000000000..52400b507 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD499.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD5.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD5.ser new file mode 100644 index 000000000..4d03b7211 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD5.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD50.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD50.ser new file mode 100644 index 000000000..975618522 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD50.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD500.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD500.ser new file mode 100644 index 000000000..33e7b0c7d Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD500.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD501.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD501.ser new file mode 100644 index 000000000..8e101db57 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD501.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD502.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD502.ser new file mode 100644 index 000000000..f8246c2d2 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD502.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD503.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD503.ser new file mode 100644 index 000000000..c8707cd48 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD503.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD504.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD504.ser new file mode 100644 index 000000000..41e6c694a Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD504.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD505.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD505.ser new file mode 100644 index 000000000..595e24ff2 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD505.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD506.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD506.ser new file mode 100644 index 000000000..731b47fd2 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD506.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD507.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD507.ser new file mode 100644 index 000000000..8bf1d99fa Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD507.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD508.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD508.ser new file mode 100644 index 000000000..bc63d7e97 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD508.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD509.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD509.ser new file mode 100644 index 000000000..d7415c13a Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD509.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD51.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD51.ser new file mode 100644 index 000000000..e8d28148e Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD51.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD510.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD510.ser new file mode 100644 index 000000000..b94811af6 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD510.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD511.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD511.ser new file mode 100644 index 000000000..91a3bd4ea Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD511.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD512.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD512.ser new file mode 100644 index 000000000..2e31b49d8 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD512.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD513.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD513.ser new file mode 100644 index 000000000..2cef55911 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD513.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD514.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD514.ser new file mode 100644 index 000000000..84c1bdeb8 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD514.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD515.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD515.ser new file mode 100644 index 000000000..431fe2dd8 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD515.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD516.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD516.ser new file mode 100644 index 000000000..37c17f168 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD516.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD517.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD517.ser new file mode 100644 index 000000000..087847d57 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD517.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD518.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD518.ser new file mode 100644 index 000000000..8bd76318d Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD518.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD519.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD519.ser new file mode 100644 index 000000000..318fc84a7 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD519.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD52.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD52.ser new file mode 100644 index 000000000..5e853ec29 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD52.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD520.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD520.ser new file mode 100644 index 000000000..e72f8d30e Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD520.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD521.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD521.ser new file mode 100644 index 000000000..cbd161b83 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD521.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD522.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD522.ser new file mode 100644 index 000000000..a2c4ccff7 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD522.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD523.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD523.ser new file mode 100644 index 000000000..cbd7fa3b8 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD523.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD524.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD524.ser new file mode 100644 index 000000000..b876b1b27 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD524.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD525.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD525.ser new file mode 100644 index 000000000..64e50de82 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD525.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD526.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD526.ser new file mode 100644 index 000000000..e5f094eeb Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD526.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD527.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD527.ser new file mode 100644 index 000000000..537459e7f Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD527.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD528.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD528.ser new file mode 100644 index 000000000..577b66158 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD528.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD529.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD529.ser new file mode 100644 index 000000000..4679568f4 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD529.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD53.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD53.ser new file mode 100644 index 000000000..389261a05 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD53.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD530.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD530.ser new file mode 100644 index 000000000..635151fa9 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD530.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD531.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD531.ser new file mode 100644 index 000000000..69e85f02b Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD531.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD532.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD532.ser new file mode 100644 index 000000000..c28ba450a Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD532.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD533.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD533.ser new file mode 100644 index 000000000..fe26705e5 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD533.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD534.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD534.ser new file mode 100644 index 000000000..19595d9e3 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD534.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD535.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD535.ser new file mode 100644 index 000000000..95e9836b4 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD535.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD536.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD536.ser new file mode 100644 index 000000000..d179f7c8c Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD536.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD537.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD537.ser new file mode 100644 index 000000000..1b91641ad Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD537.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD538.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD538.ser new file mode 100644 index 000000000..fc83f4562 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD538.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD539.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD539.ser new file mode 100644 index 000000000..ea2af6364 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD539.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD54.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD54.ser new file mode 100644 index 000000000..0f76396bb Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD54.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD540.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD540.ser new file mode 100644 index 000000000..143d5894a Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD540.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD541.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD541.ser new file mode 100644 index 000000000..671cf26d1 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD541.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD542.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD542.ser new file mode 100644 index 000000000..1a7fda27b Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD542.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD543.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD543.ser new file mode 100644 index 000000000..5aee466d8 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD543.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD544.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD544.ser new file mode 100644 index 000000000..37f124113 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD544.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD545.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD545.ser new file mode 100644 index 000000000..8bc00e144 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD545.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD546.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD546.ser new file mode 100644 index 000000000..9d9b9c119 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD546.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD547.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD547.ser new file mode 100644 index 000000000..88411a216 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD547.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD548.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD548.ser new file mode 100644 index 000000000..f8324788b Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD548.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD549.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD549.ser new file mode 100644 index 000000000..2d3118a56 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD549.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD55.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD55.ser new file mode 100644 index 000000000..51a8b7095 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD55.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD550.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD550.ser new file mode 100644 index 000000000..e939d4754 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD550.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD551.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD551.ser new file mode 100644 index 000000000..61e5e3f3c Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD551.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD552.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD552.ser new file mode 100644 index 000000000..496e6912a Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD552.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD553.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD553.ser new file mode 100644 index 000000000..0fc2f1a23 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD553.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD554.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD554.ser new file mode 100644 index 000000000..dc5183342 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD554.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD555.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD555.ser new file mode 100644 index 000000000..de477db15 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD555.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD556.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD556.ser new file mode 100644 index 000000000..6a4e51c29 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD556.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD557.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD557.ser new file mode 100644 index 000000000..fccb593ae Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD557.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD558.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD558.ser new file mode 100644 index 000000000..828b3a72e Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD558.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD559.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD559.ser new file mode 100644 index 000000000..3b14d4a8f Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD559.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD56.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD56.ser new file mode 100644 index 000000000..373392279 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD56.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD560.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD560.ser new file mode 100644 index 000000000..a91b8512a Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD560.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD561.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD561.ser new file mode 100644 index 000000000..639a7be49 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD561.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD562.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD562.ser new file mode 100644 index 000000000..68dd4089b Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD562.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD563.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD563.ser new file mode 100644 index 000000000..2908e3f63 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD563.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD564.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD564.ser new file mode 100644 index 000000000..391e3e14a Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD564.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD565.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD565.ser new file mode 100644 index 000000000..5bd9c1e71 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD565.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD566.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD566.ser new file mode 100644 index 000000000..d4ecb3a88 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD566.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD567.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD567.ser new file mode 100644 index 000000000..d68ca24ac Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD567.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD568.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD568.ser new file mode 100644 index 000000000..73cd97bf6 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD568.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD569.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD569.ser new file mode 100644 index 000000000..a6d766289 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD569.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD57.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD57.ser new file mode 100644 index 000000000..d0af60722 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD57.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD570.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD570.ser new file mode 100644 index 000000000..231290df6 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD570.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD571.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD571.ser new file mode 100644 index 000000000..21e85e747 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD571.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD572.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD572.ser new file mode 100644 index 000000000..e99365766 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD572.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD573.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD573.ser new file mode 100644 index 000000000..4f844be2e Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD573.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD574.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD574.ser new file mode 100644 index 000000000..ccb6d70f1 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD574.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD575.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD575.ser new file mode 100644 index 000000000..aa3909601 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD575.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD576.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD576.ser new file mode 100644 index 000000000..5d1bb4981 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD576.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD577.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD577.ser new file mode 100644 index 000000000..64823ec47 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD577.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD578.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD578.ser new file mode 100644 index 000000000..09d6843e8 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD578.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD579.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD579.ser new file mode 100644 index 000000000..59f2572ad Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD579.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD58.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD58.ser new file mode 100644 index 000000000..cb600cfca Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD58.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD580.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD580.ser new file mode 100644 index 000000000..b1faa848b Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD580.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD581.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD581.ser new file mode 100644 index 000000000..1e057fdf4 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD581.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD582.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD582.ser new file mode 100644 index 000000000..cdd3cbec1 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD582.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD583.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD583.ser new file mode 100644 index 000000000..84eed41fe Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD583.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD584.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD584.ser new file mode 100644 index 000000000..7b91077fc Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD584.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD585.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD585.ser new file mode 100644 index 000000000..259194e4e Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD585.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD586.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD586.ser new file mode 100644 index 000000000..0616c3c12 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD586.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD587.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD587.ser new file mode 100644 index 000000000..22430bd97 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD587.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD588.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD588.ser new file mode 100644 index 000000000..b583a1a1b Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD588.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD589.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD589.ser new file mode 100644 index 000000000..841747bdf Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD589.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD59.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD59.ser new file mode 100644 index 000000000..23521f3cd Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD59.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD590.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD590.ser new file mode 100644 index 000000000..168552d3c Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD590.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD591.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD591.ser new file mode 100644 index 000000000..c0da95a76 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD591.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD592.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD592.ser new file mode 100644 index 000000000..276e0ffed Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD592.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD593.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD593.ser new file mode 100644 index 000000000..363f4f695 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD593.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD594.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD594.ser new file mode 100644 index 000000000..a0f6639ba Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD594.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD595.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD595.ser new file mode 100644 index 000000000..cdc9eb94a Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD595.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD596.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD596.ser new file mode 100644 index 000000000..c6223a7ce Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD596.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD597.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD597.ser new file mode 100644 index 000000000..74f023e83 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD597.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD598.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD598.ser new file mode 100644 index 000000000..9755e4a3c Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD598.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD599.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD599.ser new file mode 100644 index 000000000..986a332f3 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD599.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD6.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD6.ser new file mode 100644 index 000000000..edc35abdc Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD6.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD60.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD60.ser new file mode 100644 index 000000000..6ed639c5e Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD60.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD600.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD600.ser new file mode 100644 index 000000000..d2c52eba1 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD600.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD601.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD601.ser new file mode 100644 index 000000000..f34830970 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD601.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD602.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD602.ser new file mode 100644 index 000000000..7cea4a6c6 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD602.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD603.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD603.ser new file mode 100644 index 000000000..e2c08df91 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD603.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD604.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD604.ser new file mode 100644 index 000000000..7a37cd019 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD604.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD605.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD605.ser new file mode 100644 index 000000000..85f679da2 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD605.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD606.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD606.ser new file mode 100644 index 000000000..8f1d6966d Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD606.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD607.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD607.ser new file mode 100644 index 000000000..f82e37287 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD607.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD608.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD608.ser new file mode 100644 index 000000000..f22902dd5 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD608.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD609.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD609.ser new file mode 100644 index 000000000..bb7f98e41 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD609.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD61.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD61.ser new file mode 100644 index 000000000..d25cb04c7 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD61.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD610.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD610.ser new file mode 100644 index 000000000..8ddaeb744 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD610.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD611.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD611.ser new file mode 100644 index 000000000..b11de6c32 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD611.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD612.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD612.ser new file mode 100644 index 000000000..2b1ea8898 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD612.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD613.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD613.ser new file mode 100644 index 000000000..1d2ea017c Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD613.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD614.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD614.ser new file mode 100644 index 000000000..ae74ca063 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD614.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD615.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD615.ser new file mode 100644 index 000000000..fed68df6e Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD615.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD616.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD616.ser new file mode 100644 index 000000000..94b09c1e1 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD616.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD617.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD617.ser new file mode 100644 index 000000000..0af062be1 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD617.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD618.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD618.ser new file mode 100644 index 000000000..bd93b288c Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD618.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD619.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD619.ser new file mode 100644 index 000000000..ea7a544bf Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD619.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD62.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD62.ser new file mode 100644 index 000000000..c3510ec9e Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD62.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD620.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD620.ser new file mode 100644 index 000000000..c02164344 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD620.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD621.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD621.ser new file mode 100644 index 000000000..16cf973f2 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD621.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD63.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD63.ser new file mode 100644 index 000000000..f827db274 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD63.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD64.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD64.ser new file mode 100644 index 000000000..c079752d6 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD64.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD65.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD65.ser new file mode 100644 index 000000000..18d091c4a Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD65.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD66.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD66.ser new file mode 100644 index 000000000..2628ac645 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD66.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD67.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD67.ser new file mode 100644 index 000000000..e0a656874 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD67.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD68.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD68.ser new file mode 100644 index 000000000..cd908264a Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD68.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD69.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD69.ser new file mode 100644 index 000000000..da9a56794 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD69.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD7.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD7.ser new file mode 100644 index 000000000..1eec94eeb Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD7.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD70.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD70.ser new file mode 100644 index 000000000..1458485b6 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD70.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD71.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD71.ser new file mode 100644 index 000000000..0bb894af9 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD71.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD72.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD72.ser new file mode 100644 index 000000000..596af011c Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD72.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD73.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD73.ser new file mode 100644 index 000000000..adac3305c Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD73.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD74.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD74.ser new file mode 100644 index 000000000..1440bb78a Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD74.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD75.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD75.ser new file mode 100644 index 000000000..2a1091e9c Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD75.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD76.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD76.ser new file mode 100644 index 000000000..a519dc078 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD76.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD77.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD77.ser new file mode 100644 index 000000000..533579a8f Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD77.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD78.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD78.ser new file mode 100644 index 000000000..cd8bea1c7 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD78.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD79.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD79.ser new file mode 100644 index 000000000..16635b605 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD79.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD8.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD8.ser new file mode 100644 index 000000000..05616a937 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD8.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD80.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD80.ser new file mode 100644 index 000000000..44ce6375e Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD80.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD81.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD81.ser new file mode 100644 index 000000000..cfd698d7d Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD81.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD82.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD82.ser new file mode 100644 index 000000000..415f1bf8e Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD82.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD83.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD83.ser new file mode 100644 index 000000000..2fc94de93 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD83.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD84.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD84.ser new file mode 100644 index 000000000..a7e226ec1 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD84.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD85.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD85.ser new file mode 100644 index 000000000..573c8ce87 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD85.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD86.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD86.ser new file mode 100644 index 000000000..e8df233a5 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD86.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD87.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD87.ser new file mode 100644 index 000000000..abcad78d0 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD87.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD88.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD88.ser new file mode 100644 index 000000000..e702881e7 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD88.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD89.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD89.ser new file mode 100644 index 000000000..1b76a8499 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD89.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD9.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD9.ser new file mode 100644 index 000000000..13edb5406 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD9.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD90.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD90.ser new file mode 100644 index 000000000..da2ee39ec Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD90.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD91.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD91.ser new file mode 100644 index 000000000..7f9f0a3fd Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD91.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD92.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD92.ser new file mode 100644 index 000000000..6cbe89840 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD92.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD93.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD93.ser new file mode 100644 index 000000000..423f92310 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD93.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD94.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD94.ser new file mode 100644 index 000000000..331ba261f Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD94.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD95.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD95.ser new file mode 100644 index 000000000..0c4e54135 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD95.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD96.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD96.ser new file mode 100644 index 000000000..20afc295a Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD96.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD97.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD97.ser new file mode 100644 index 000000000..e801916f4 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD97.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD98.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD98.ser new file mode 100644 index 000000000..7fc398de9 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD98.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD99.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD99.ser new file mode 100644 index 000000000..5c7a0de21 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$LD99.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$TD0.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$TD0.ser new file mode 100644 index 000000000..f7b1fbed1 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$TD0.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$TD1.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$TD1.ser new file mode 100644 index 000000000..dc3634dec Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$TD1.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$TD10.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$TD10.ser new file mode 100644 index 000000000..a3108b43e Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$TD10.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$TD11.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$TD11.ser new file mode 100644 index 000000000..f561c2d2f Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$TD11.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$TD12.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$TD12.ser new file mode 100644 index 000000000..1dc99e434 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$TD12.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$TD13.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$TD13.ser new file mode 100644 index 000000000..e1b97d053 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$TD13.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$TD14.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$TD14.ser new file mode 100644 index 000000000..5600cbfa2 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$TD14.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$TD15.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$TD15.ser new file mode 100644 index 000000000..fe4068c42 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$TD15.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$TD16.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$TD16.ser new file mode 100644 index 000000000..59ad5e462 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$TD16.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$TD17.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$TD17.ser new file mode 100644 index 000000000..b11600cd0 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$TD17.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$TD18.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$TD18.ser new file mode 100644 index 000000000..5abc2b1b6 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$TD18.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$TD2.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$TD2.ser new file mode 100644 index 000000000..37814223f Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$TD2.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$TD3.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$TD3.ser new file mode 100644 index 000000000..58bb75a7f Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$TD3.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$TD4.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$TD4.ser new file mode 100644 index 000000000..f905fc364 Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$TD4.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$TD5.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$TD5.ser new file mode 100644 index 000000000..0c1e74beb Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$TD5.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$TD6.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$TD6.ser new file mode 100644 index 000000000..1032043be Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$TD6.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$TD7.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$TD7.ser new file mode 100644 index 000000000..d0e34603a Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$TD7.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$TD8.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$TD8.ser new file mode 100644 index 000000000..4d47ada2d Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$TD8.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$TD9.ser b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$TD9.ser new file mode 100644 index 000000000..eb522634d Binary files /dev/null and b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData$TD9.ser differ diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestData.java b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData.java new file mode 100644 index 000000000..273240a27 --- /dev/null +++ b/test/java/org/apache/fop/complexscripts/bidi/BidiTestData.java @@ -0,0 +1,74 @@ +/* + * 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: License.java 1039179 2010-11-25 21:04:09Z vhennebert $ */ + +package org.apache.fop.complexscripts.bidi; + +import java.io.IOException; +import java.io.InputStream; +import java.io.ObjectInputStream; + +// CSOFF: WhitespaceAfterCheck + +/* + * !!! THIS IS A GENERATED FILE !!! + * If updates to the source are needed, then: + * - apply the necessary modifications to + * 'src/codegen/unicode/java/org/apache/fop/text/bidi/GenerateBidiTestData.java' + * - run 'ant codegen-unicode', which will generate a new BidiTestData.java + * in 'test/java/org/apache/fop/complexscripts/bidi' + * - commit BOTH changed files + */ + +/** Bidirectional test data. */ +public final class BidiTestData { + + private BidiTestData() { + } + + public static final String TD_PFX = "TD"; + public static final int TD_CNT = 19; + + public static final String LD_PFX = "LD"; + public static final int LD_CNT = 622; + + public static final int NUM_TEST_SEQUENCES = 216357; + + public static int[] readTestData ( String prefix, int index ) { + int[] data = null; + InputStream is = null; + Class btc = BidiTestData.class; + String name = btc.getSimpleName() + "$" + prefix + index + ".ser"; + try { + if ( ( is = btc.getResourceAsStream ( name ) ) != null ) { + ObjectInputStream ois = new ObjectInputStream ( is ); + data = (int[]) ois.readObject(); + ois.close(); + } + } catch ( IOException e ) { + data = null; + } catch ( ClassNotFoundException e ) { + data = null; + } finally { + if ( is != null ) { + try { is.close(); } catch ( Exception e ) {} + } + } + return data; + } +} diff --git a/test/java/org/apache/fop/complexscripts/bidi/BidiTestSuite.java b/test/java/org/apache/fop/complexscripts/bidi/BidiTestSuite.java new file mode 100644 index 000000000..7a6a095c6 --- /dev/null +++ b/test/java/org/apache/fop/complexscripts/bidi/BidiTestSuite.java @@ -0,0 +1,35 @@ +/* + * 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.complexscripts.bidi; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; +import org.junit.runners.Suite.SuiteClasses; + +/** + * Test suite for bidirectional functionality. + */ +@RunWith(Suite.class) +@SuiteClasses({ + BidiClassTestCase.class, + BidiAlgorithmTestCase.class +}) +public class BidiTestSuite { +} diff --git a/test/java/org/apache/fop/complexscripts/fonts/FontsTestSuite.java b/test/java/org/apache/fop/complexscripts/fonts/FontsTestSuite.java new file mode 100644 index 000000000..a7e4b0615 --- /dev/null +++ b/test/java/org/apache/fop/complexscripts/fonts/FontsTestSuite.java @@ -0,0 +1,39 @@ +/* + * 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.complexscripts.fonts; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; +import org.junit.runners.Suite.SuiteClasses; + +import org.apache.fop.complexscripts.fonts.ttx.TTXFileTestCase; + +/** + * Test suite for fonts functionality related to complex scripts. + */ +@RunWith(Suite.class) +@SuiteClasses({ + TTXFileTestCase.class, + GDEFTestCase.class, + GSUBTestCase.class, + GPOSTestCase.class +}) +public class FontsTestSuite { +} diff --git a/test/java/org/apache/fop/complexscripts/fonts/GDEFTestCase.java b/test/java/org/apache/fop/complexscripts/fonts/GDEFTestCase.java new file mode 100644 index 000000000..162b5d241 --- /dev/null +++ b/test/java/org/apache/fop/complexscripts/fonts/GDEFTestCase.java @@ -0,0 +1,3177 @@ +/* + * 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.complexscripts.fonts; + +import java.io.File; + +import org.apache.fop.complexscripts.fonts.GlyphSubtable; +import org.apache.fop.complexscripts.fonts.GlyphDefinitionSubtable; +import org.apache.fop.complexscripts.fonts.GlyphDefinitionTable; +import org.apache.fop.complexscripts.fonts.GlyphTable.LookupSpec; +import org.apache.fop.complexscripts.fonts.GlyphTable.LookupTable; +import org.apache.fop.complexscripts.fonts.ttx.TTXFile; +import org.apache.fop.complexscripts.util.GlyphContextTester; +import org.apache.fop.complexscripts.util.GlyphSequence; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +public class GDEFTestCase { + + private static String ttxFilesRoot = "test/resources/complexscripts"; + + private static String[][] ttxFonts = { + { "f0", "arab/ttx/arab-001.ttx" }, // simplified arabic + { "f1", "arab/ttx/arab-002.ttx" }, // traditional arabic + { "f2", "arab/ttx/arab-003.ttx" }, // lateef + { "f3", "arab/ttx/arab-004.ttx" }, // scheherazade + }; + + private static Object[][] ltGlyphClass = { + { GlyphDefinitionTable.GDEF_LOOKUP_TYPE_GLYPH_CLASS }, + // arab-001.ttx + { "f0", "lu0", + new String[][] { + { "a", "1" }, + { "aacute", "1" }, + { "acircumflex", "1" }, + { "acute", "1" }, + { "adieresis", "1" }, + { "ae", "1" }, + { "agrave", "1" }, + { "ain", "1" }, + { "ainfinal", "1" }, + { "aininitial", "1" }, + { "ainisolated", "1" }, + { "ainmedial", "1" }, + { "aleffinal", "1" }, + { "alefisolated", "1" }, + { "alefmaksura", "1" }, + { "alefmaksurafinal", "1" }, + { "alefmaksuraisolated", "1" }, + { "alefwasla", "1" }, + { "alefwaslafinal", "1" }, + { "alefwaslaisolated", "1" }, + { "alefwithfathatanfinal", "1" }, + { "alefwithfathatanisolated", "1" }, + { "alefwithhamzaabove", "1" }, + { "alefwithhamzaabovefinal", "1" }, + { "alefwithhamzaaboveisolated", "1" }, + { "alefwithhamzabelow", "1" }, + { "alefwithhamzabelowfinal", "1" }, + { "alefwithhamzabelowisolated", "1" }, + { "alefwithmaddaabove", "1" }, + { "alefwithmaddaabovefinal", "1" }, + { "alefwithmaddaaboveisolated", "1" }, + { "allahisolated", "2" }, + { "ampersand", "1" }, + { "arabicae", "1" }, + { "arabicalef", "1" }, + { "arabiccomma", "1" }, + { "arabicfivepointedstar", "1" }, + { "arabicindicdigiteight", "1" }, + { "arabicindicdigitfive", "1" }, + { "arabicindicdigitfour", "1" }, + { "arabicindicdigitnine", "1" }, + { "arabicindicdigitone", "1" }, + { "arabicindicdigitseven", "1" }, + { "arabicindicdigitsix", "1" }, + { "arabicindicdigitthree", "1" }, + { "arabicindicdigittwo", "1" }, + { "arabicindicdigitzero", "1" }, + { "arabickaf", "1" }, + { "arabicpercentsign", "1" }, + { "arabicquestionmark", "1" }, + { "arabicsemicolon", "1" }, + { "aring", "1" }, + { "asciicircum", "1" }, + { "asciitilde", "1" }, + { "asterisk", "1" }, + { "at", "1" }, + { "atilde", "1" }, + { "b", "1" }, + { "backslash", "1" }, + { "bar", "1" }, + { "beh", "1" }, + { "behisolated", "1" }, + { "behmedial", "1" }, + { "braceleft", "1" }, + { "braceright", "1" }, + { "bracketleft", "1" }, + { "bracketright", "1" }, + { "brokenbar", "1" }, + { "bullet", "1" }, + { "c", "1" }, + { "caron", "1" }, + { "ccedilla", "1" }, + { "cedilla", "1" }, + { "cent", "1" }, + { "circumflex", "1" }, + { "colon", "1" }, + { "comma", "1" }, + { "copyright", "1" }, + { "currency", "1" }, + { "d", "1" }, + { "dad", "1" }, + { "dadisolated", "1" }, + { "dadmedial", "1" }, + { "dagger", "1" }, + { "daggerdbl", "1" }, + { "dal", "1" }, + { "dalisolated", "1" }, + { "damma", "3" }, + { "dammahontatweel", "3" }, + { "dammaisolated", "3" }, + { "dammalow", "1" }, + { "dammaonhamza", "3" }, + { "dammatan", "3" }, + { "dammatanisolated", "3" }, + { "dammatanlow", "1" }, + { "dammatanonhamza", "3" }, + { "degree", "1" }, + { "delete", "1" }, + { "dieresis", "1" }, + { "divide", "1" }, + { "dollar", "1" }, + { "dotlessi", "1" }, + { "e", "1" }, + { "eacute", "1" }, + { "ecircumflex", "1" }, + { "edieresis", "1" }, + { "egrave", "1" }, + { "eight", "1" }, + { "ellipsis", "1" }, + { "endash", "1" }, + { "equal", "1" }, + { "eth", "1" }, + { "exclam", "1" }, + { "exclamdown", "1" }, + { "extendedarabicindicdigiteight", "1" }, + { "extendedarabicindicdigitfive", "1" }, + { "extendedarabicindicdigitfour", "1" }, + { "extendedarabicindicdigitnine", "1" }, + { "extendedarabicindicdigitone", "1" }, + { "extendedarabicindicdigitseven", "1" }, + { "extendedarabicindicdigitsix", "1" }, + { "extendedarabicindicdigitthree", "1" }, + { "extendedarabicindicdigittwo", "1" }, + { "extendedarabicindicdigitzero", "1" }, + { "f", "1" }, + { "farsiyeh", "1" }, + { "farsiyehfinal", "1" }, + { "farsiyehisolated", "1" }, + { "fatha", "3" }, + { "fathahontatweel", "3" }, + { "fathaisolated", "3" }, + { "fathalow", "1" }, + { "fathaonhamza", "3" }, + { "fathatan", "3" }, + { "fathatanisolated", "3" }, + { "fathatanlow", "1" }, + { "fathatanonhamza", "3" }, + { "fathatanontatweel", "1" }, + { "feh", "1" }, + { "fehinitial", "1" }, + { "fehisolated", "1" }, + { "fehmedial", "1" }, + { "five", "1" }, + { "florin", "1" }, + { "four", "1" }, + { "g", "1" }, + { "gaf", "1" }, + { "gaffinal", "1" }, + { "gafinitial", "1" }, + { "gafisolated", "1" }, + { "gafmedial", "1" }, + { "germandbls", "1" }, + { "ghain", "1" }, + { "ghainfinal", "1" }, + { "ghaininitial", "1" }, + { "ghainisolated", "1" }, + { "ghainmedial", "1" }, + { "glyph1", "1" }, + { "glyph2", "1" }, + { "glyph99", "1" }, + { "grave", "1" }, + { "greater", "1" }, + { "guillemotleft", "1" }, + { "guillemotright", "1" }, + { "guilsinglleft", "1" }, + { "guilsinglright", "1" }, + { "h", "1" }, + { "hah", "1" }, + { "hahfinal", "1" }, + { "hahisolated", "1" }, + { "hahmedial", "1" }, + { "hamza", "1" }, + { "hamzaisolated", "3" }, + { "heh", "1" }, + { "hehfinal", "1" }, + { "hehinitial", "1" }, + { "hehisolated", "1" }, + { "hehmedial", "1" }, + { "highhamza", "1" }, + { "hyphenminus", "1" }, + { "i", "1" }, + { "iacute", "1" }, + { "icircumflex", "1" }, + { "idieresis", "1" }, + { "igrave", "1" }, + { "j", "1" }, + { "jeem", "1" }, + { "jeemfinal", "1" }, + { "jeemisolated", "1" }, + { "jeemmedial", "1" }, + { "jeh", "1" }, + { "jehisolated", "1" }, + { "k", "1" }, + { "kafisolated", "1" }, + { "kafmedial", "1" }, + { "kasra", "3" }, + { "kasrahontatweel", "3" }, + { "kasraisolated", "3" }, + { "kasralow", "1" }, + { "kasratan", "3" }, + { "kasratanisolated", "3" }, + { "kasratanlow", "1" }, + { "keheh", "1" }, + { "kehehfinal", "1" }, + { "kehehinitial", "1" }, + { "kehehisolated", "1" }, + { "kehehmedial", "1" }, + { "khah", "1" }, + { "khahfinal", "1" }, + { "khahisolated", "1" }, + { "khahmedial", "1" }, + { "l", "1" }, + { "lam", "1" }, + { "lamisolated", "1" }, + { "lammedial", "1" }, + { "lamwithaleffinal", "2" }, + { "lamwithalefhamzaabovefinal", "2" }, + { "lamwithalefhamzaaboveisolatedd", "2" }, + { "lamwithalefhamzabelowfinal", "2" }, + { "lamwithalefhamzabelowisolated", "2" }, + { "lamwithalefisolated", "2" }, + { "lamwithalefmaddaabovefinal", "2" }, + { "lamwithalefmaddaaboveisolatedd", "2" }, + { "lamwithmeemwithjeeminitial", "1" }, + { "lefttoright", "1" }, + { "less", "1" }, + { "logicalnot", "1" }, + { "m", "1" }, + { "macron", "1" }, + { "meem", "1" }, + { "meemisolated", "1" }, + { "meemmedial", "1" }, + { "micro", "1" }, + { "multiply", "1" }, + { "n", "1" }, + { "nbspace", "1" }, + { "nine", "1" }, + { "noon", "1" }, + { "noonisolated", "1" }, + { "noonmedial", "1" }, + { "ntilde", "1" }, + { "numbersign", "1" }, + { "o", "1" }, + { "oacute", "1" }, + { "ocircumflex", "1" }, + { "odieresis", "1" }, + { "oe", "1" }, + { "ograve", "1" }, + { "one", "1" }, + { "onehalf", "1" }, + { "onequarter", "1" }, + { "onesuperior", "1" }, + { "ordfeminine", "1" }, + { "ordmasculine", "1" }, + { "ornateleftparenthesis", "1" }, + { "ornaterightparenthesis", "1" }, + { "oslash", "1" }, + { "otilde", "1" }, + { "p", "1" }, + { "paragraph", "1" }, + { "parenleft", "1" }, + { "parenright", "1" }, + { "peh", "1" }, + { "pehisolated", "1" }, + { "pehmedial", "1" }, + { "percent", "1" }, + { "period", "1" }, + { "periodcentered", "1" }, + { "perthousand", "1" }, + { "plus", "1" }, + { "plusminus", "1" }, + { "q", "1" }, + { "qaf", "1" }, + { "qafinitial", "1" }, + { "qafisolated", "1" }, + { "qafmedial", "1" }, + { "question", "1" }, + { "questiondown", "1" }, + { "quotedash", "1" }, + { "quotedbl", "1" }, + { "quotedblbase", "1" }, + { "quotedblleft", "1" }, + { "quotedblright", "1" }, + { "quoteleft", "1" }, + { "quoteright", "1" }, + { "quotesinglbase", "1" }, + { "quotesingle", "1" }, + { "r", "1" }, + { "rayaleflam", "2" }, + { "registered", "1" }, + { "reh", "1" }, + { "rehisolated", "1" }, + { "righttoleft", "1" }, + { "s", "1" }, + { "sad", "1" }, + { "sadisolated", "1" }, + { "sadmedial", "1" }, + { "scaron", "1" }, + { "section", "1" }, + { "seen", "1" }, + { "seenisolated", "1" }, + { "seenmedial", "1" }, + { "semicolon", "1" }, + { "seven", "1" }, + { "sfthyphen", "1" }, + { "shadda", "3" }, + { "shaddahontatweel", "3" }, + { "shaddaisolated", "3" }, + { "shaddalow", "1" }, + { "shaddawithdammaisolated", "3" }, + { "shaddawithdammalow", "3" }, + { "shaddawithdammamedial", "1" }, + { "shaddawithdammatanisolated", "1" }, + { "shaddawithdammatanlow", "3" }, + { "shaddawithfathaisolated", "3" }, + { "shaddawithfathalow", "3" }, + { "shaddawithfathamedial", "1" }, + { "shaddawithfathatanisolated", "1" }, + { "shaddawithfathatanlow", "3" }, + { "shaddawithkasraisolated", "3" }, + { "shaddawithkasralow", "3" }, + { "shaddawithkasramedial", "1" }, + { "shaddawithkasratanisolated", "1" }, + { "shaddawithkasratanlow", "3" }, + { "sheen", "1" }, + { "sheenisolated", "1" }, + { "sheenmedial", "1" }, + { "six", "1" }, + { "slash", "1" }, + { "smallhighmadda", "3" }, + { "space", "1" }, + { "sterling", "1" }, + { "sukun", "3" }, + { "sukunisolated", "3" }, + { "sukunlow", "1" }, + { "sukunonhamza", "3" }, + { "sukunontatweel", "3" }, + { "superscriptalef", "3" }, + { "t", "1" }, + { "tah", "1" }, + { "tahisolated", "1" }, + { "tatweel", "1" }, + { "tcheh", "1" }, + { "tchehfinal", "1" }, + { "tchehisolated", "1" }, + { "tchehmedial", "1" }, + { "teh", "1" }, + { "tehisolated", "1" }, + { "tehmarbuta", "1" }, + { "tehmarbutafinal", "1" }, + { "tehmarbutaisolated", "1" }, + { "tehmedial", "1" }, + { "thal", "1" }, + { "thalisolated", "1" }, + { "theh", "1" }, + { "thehisolated", "1" }, + { "thehmedial", "1" }, + { "thorn", "1" }, + { "three", "1" }, + { "threequarters", "1" }, + { "threesuperior", "1" }, + { "tilde", "1" }, + { "trademark", "1" }, + { "two", "1" }, + { "twosuperior", "1" }, + { "u", "1" }, + { "uacute", "1" }, + { "ucircumflex", "1" }, + { "udieresis", "1" }, + { "ugrave", "1" }, + { "underscore", "1" }, + { "uni000D", "1" }, + { "uni0649.init", "1" }, + { "uni0654", "3" }, + { "uni0655", "3" }, + { "uni0655064D", "3" }, + { "uni06550650", "3" }, + { "uni06A5.init", "1" }, + { "uni25CC", "1" }, + { "v", "1" }, + { "veh", "1" }, + { "vehisolated", "1" }, + { "vehmedial", "1" }, + { "w", "1" }, + { "waw", "1" }, + { "wawisolated", "1" }, + { "wawwithhamzaabove", "1" }, + { "wawwithhamzaaboveisolated", "1" }, + { "x", "1" }, + { "y", "1" }, + { "yacute", "1" }, + { "ydieresis", "1" }, + { "yeh", "1" }, + { "yehfinal", "1" }, + { "yehisolated", "1" }, + { "yehmedial", "1" }, + { "yehwithhamzaabove", "1" }, + { "yehwithhamzaabovefinal", "1" }, + { "yehwithhamzaaboveisolated", "1" }, + { "yehwithhamzaabovemedial", "1" }, + { "yen", "1" }, + { "z", "1" }, + { "zah", "1" }, + { "zahisolated", "1" }, + { "zain", "1" }, + { "zainisolated", "1" }, + { "zcaron", "1" }, + { "zero", "1" }, + { "zerojoin", "1" }, + { "zeronojoin", "1" }, + { "zerowidthnobreakspace", "1" }, + }, + }, + // arab-002.ttx + { "f1", "lu0", + new String[][] { + { "a", "1" }, + { "aacute", "1" }, + { "acircumflex", "1" }, + { "acute", "1" }, + { "adieresis", "1" }, + { "ae", "1" }, + { "agrave", "1" }, + { "ain", "1" }, + { "ainfinal", "1" }, + { "aininitial", "1" }, + { "ainisolated", "1" }, + { "ainmedial", "1" }, + { "aleffinal", "1" }, + { "alefisolated", "1" }, + { "alefmaksura", "1" }, + { "alefmaksurafinal", "1" }, + { "alefmaksuraisolated", "1" }, + { "alefwasla", "1" }, + { "alefwaslafinal", "1" }, + { "alefwaslaisolated", "1" }, + { "alefwithfathatanfinal", "1" }, + { "alefwithfathatanisolated", "1" }, + { "alefwithhamzaabove", "1" }, + { "alefwithhamzaabovefinal", "1" }, + { "alefwithhamzaaboveisolated", "1" }, + { "alefwithhamzabelow", "1" }, + { "alefwithhamzabelowfinal", "1" }, + { "alefwithhamzabelowisolated", "1" }, + { "alefwithmaddaabove", "1" }, + { "alefwithmaddaabovefinal", "1" }, + { "alefwithmaddaaboveisolated", "1" }, + { "allahisolated", "2" }, + { "ampersand", "1" }, + { "arabicae", "1" }, + { "arabicalef", "1" }, + { "arabiccomma", "1" }, + { "arabicfivepointedstar", "3" }, + { "arabicindicdigiteight", "1" }, + { "arabicindicdigitfive", "1" }, + { "arabicindicdigitfour", "1" }, + { "arabicindicdigitnine", "1" }, + { "arabicindicdigitone", "1" }, + { "arabicindicdigitseven", "1" }, + { "arabicindicdigitsix", "1" }, + { "arabicindicdigitthree", "1" }, + { "arabicindicdigittwo", "1" }, + { "arabicindicdigitzero", "1" }, + { "arabickaf", "1" }, + { "arabickaffinal", "1" }, + { "arabicpercentsign", "1" }, + { "arabicquestionmark", "1" }, + { "arabicsemicolon", "1" }, + { "aring", "1" }, + { "asciicircum", "1" }, + { "asciitilde", "1" }, + { "asterisk", "1" }, + { "at", "1" }, + { "atilde", "1" }, + { "b", "1" }, + { "backslash", "1" }, + { "bar", "1" }, + { "beh", "1" }, + { "behfinal", "1" }, + { "behinitial", "1" }, + { "behisolated", "1" }, + { "behmedial", "1" }, + { "behwithalefmaksurafinal", "2" }, + { "behwithalefmaksuraisolated", "2" }, + { "behwithhahinitial", "2" }, + { "behwithhehinitial", "2" }, + { "behwithjeeminitial", "2" }, + { "behwithkhahinitial", "2" }, + { "behwithmeeminitial", "2" }, + { "behwithmeemisolated", "2" }, + { "behwithnoonfinal", "2" }, + { "behwithrehfinal", "2" }, + { "behwithyehfinal", "2" }, + { "behwithyehisolated", "2" }, + { "braceleft", "1" }, + { "braceright", "1" }, + { "bracketleft", "1" }, + { "bracketright", "1" }, + { "brokenbar", "1" }, + { "bullet", "1" }, + { "c", "1" }, + { "caron", "1" }, + { "ccedilla", "1" }, + { "cedilla", "1" }, + { "cent", "1" }, + { "circumflex", "1" }, + { "colon", "1" }, + { "comma", "1" }, + { "copyright", "1" }, + { "currency", "1" }, + { "d", "1" }, + { "dad", "1" }, + { "dadfinal", "1" }, + { "dadinitial", "1" }, + { "dadisolated", "1" }, + { "dadmedial", "1" }, + { "dagger", "1" }, + { "daggerdbl", "1" }, + { "dal", "1" }, + { "dalfinal", "1" }, + { "dalisolated", "1" }, + { "damma", "3" }, + { "dammahontatweel", "1" }, + { "dammaisolated", "1" }, + { "dammalow", "1" }, + { "dammaonhamza", "3" }, + { "dammatan", "3" }, + { "dammatanisolated", "1" }, + { "dammatanlow", "1" }, + { "dammatanonhamza", "3" }, + { "degree", "1" }, + { "delete", "1" }, + { "dieresis", "1" }, + { "divide", "1" }, + { "dollar", "1" }, + { "dotlessi", "1" }, + { "e", "1" }, + { "eacute", "1" }, + { "ecircumflex", "1" }, + { "edieresis", "1" }, + { "egrave", "1" }, + { "eight", "1" }, + { "ellipsis", "1" }, + { "endash", "1" }, + { "equal", "1" }, + { "eth", "1" }, + { "exclam", "1" }, + { "exclamdown", "1" }, + { "extendedarabicindicdigiteight", "1" }, + { "extendedarabicindicdigitfive", "1" }, + { "extendedarabicindicdigitfour", "1" }, + { "extendedarabicindicdigitnine", "1" }, + { "extendedarabicindicdigitone", "1" }, + { "extendedarabicindicdigitseven", "1" }, + { "extendedarabicindicdigitsix", "1" }, + { "extendedarabicindicdigitthree", "1" }, + { "extendedarabicindicdigittwo", "1" }, + { "extendedarabicindicdigitzero", "1" }, + { "f", "1" }, + { "farsiyeh", "1" }, + { "farsiyehfinal", "1" }, + { "farsiyehisolated", "1" }, + { "fatha", "3" }, + { "fathahontatweel", "1" }, + { "fathaisolated", "1" }, + { "fathalow", "1" }, + { "fathaonhamza", "3" }, + { "fathatan", "3" }, + { "fathatanisolated", "1" }, + { "fathatanlow", "1" }, + { "fathatanonhamza", "3" }, + { "fathatanontatweel", "1" }, + { "feh", "1" }, + { "fehfinal", "1" }, + { "fehinitial", "1" }, + { "fehisolated", "1" }, + { "fehmedial", "1" }, + { "fehwithalefmaksuraisolated", "2" }, + { "fehwithyehisolated", "2" }, + { "five", "1" }, + { "florin", "1" }, + { "four", "1" }, + { "g", "1" }, + { "gaf", "1" }, + { "gaffinal", "1" }, + { "gafinitial", "1" }, + { "gafisolated", "1" }, + { "gafmedial", "1" }, + { "germandbls", "1" }, + { "ghain", "1" }, + { "ghainfinal", "1" }, + { "ghaininitial", "1" }, + { "ghainisolated", "1" }, + { "ghainmedial", "1" }, + { "grave", "1" }, + { "greater", "1" }, + { "guillemotleft", "1" }, + { "guillemotright", "1" }, + { "guilsinglleft", "1" }, + { "guilsinglright", "1" }, + { "h", "1" }, + { "hah", "1" }, + { "hahfinal", "1" }, + { "hahinitial", "1" }, + { "hahisolated", "1" }, + { "hahmedial", "1" }, + { "hahwithmeeminitial", "2" }, + { "hamza", "1" }, + { "hamzaisolated", "1" }, + { "heh", "1" }, + { "hehfinal", "1" }, + { "hehinitial", "1" }, + { "hehisolated", "1" }, + { "hehmedial", "1" }, + { "hehwithmeeminitial", "2" }, + { "highhamza", "1" }, + { "hyphenminus", "1" }, + { "i", "1" }, + { "iacute", "1" }, + { "icircumflex", "1" }, + { "idieresis", "1" }, + { "igrave", "1" }, + { "j", "1" }, + { "jeem", "1" }, + { "jeemfinal", "1" }, + { "jeeminitial", "1" }, + { "jeemisolated", "1" }, + { "jeemmedial", "1" }, + { "jeemwithmeeminitial", "2" }, + { "jeh", "1" }, + { "jehfinal", "1" }, + { "jehisolated", "1" }, + { "k", "1" }, + { "kafinitial", "1" }, + { "kafisolated", "1" }, + { "kafmedial", "1" }, + { "kasra", "3" }, + { "kasrahontatweel", "1" }, + { "kasraisolated", "1" }, + { "kasralow", "1" }, + { "kasratan", "3" }, + { "kasratanisolated", "1" }, + { "kasratanlow", "1" }, + { "keheh", "1" }, + { "kehehfinal", "1" }, + { "kehehinitial", "1" }, + { "kehehisolated", "1" }, + { "kehehmedial", "1" }, + { "khah", "1" }, + { "khahfinal", "1" }, + { "khahinitial", "1" }, + { "khahisolated", "1" }, + { "khahmedial", "1" }, + { "khahwithmeeminitial", "2" }, + { "l", "1" }, + { "lam", "1" }, + { "lamfinal", "1" }, + { "laminitial", "1" }, + { "lamisolated", "1" }, + { "lammedial", "1" }, + { "lamwithaleffinal", "2" }, + { "lamwithalefhamzaabovefinal", "2" }, + { "lamwithalefhamzaaboveisolatedd", "2" }, + { "lamwithalefhamzabelowfinal", "2" }, + { "lamwithalefhamzabelowisolated", "2" }, + { "lamwithalefisolated", "2" }, + { "lamwithalefmaddaabovefinal", "2" }, + { "lamwithalefmaddaaboveisolatedd", "2" }, + { "lamwithalefmaksuraisolated", "2" }, + { "lamwithhahinitial", "2" }, + { "lamwithhahisolated", "2" }, + { "lamwithhehinitial", "2" }, + { "lamwithjeeminitial", "2" }, + { "lamwithjeemisolated", "2" }, + { "lamwithkhahinitial", "2" }, + { "lamwithkhahisolated", "2" }, + { "lamwithmeeminitial", "2" }, + { "lamwithmeemisolated", "2" }, + { "lamwithmeemwithhahinitial", "2" }, + { "lamwithmeemwithjeeminitial", "2" }, + { "lamwithyehisolated", "2" }, + { "lefttoright", "1" }, + { "less", "1" }, + { "logicalnot", "1" }, + { "m", "1" }, + { "macron", "1" }, + { "meem", "1" }, + { "meemfinal", "1" }, + { "meeminitial", "1" }, + { "meemisolated", "1" }, + { "meemmedial", "1" }, + { "meemwithhahinitial", "2" }, + { "meemwithjeeminitial", "2" }, + { "meemwithkhahinitial", "2" }, + { "meemwithmeeminitial", "2" }, + { "micro", "1" }, + { "multiply", "1" }, + { "n", "1" }, + { "nine", "1" }, + { "nonbreakingspace", "1" }, + { "nonmarkingreturn", "1" }, + { "noon", "1" }, + { "noonfinal", "1" }, + { "nooninitial", "1" }, + { "noonisolated", "1" }, + { "noonmedial", "1" }, + { "noonwithalefmaksurafinal", "2" }, + { "noonwithalefmaksuraisolated", "2" }, + { "noonwithhahinitial", "2" }, + { "noonwithhehinitial", "2" }, + { "noonwithjeeminitial", "2" }, + { "noonwithkhahinitial", "2" }, + { "noonwithmeeminitial", "2" }, + { "noonwithmeemisolated", "2" }, + { "noonwithyehfinal", "2" }, + { "noonwithyehisolated", "2" }, + { "noonwithzainfinal", "2" }, + { "ntilde", "1" }, + { "numbersign", "1" }, + { "o", "1" }, + { "oacute", "1" }, + { "ocircumflex", "1" }, + { "odieresis", "1" }, + { "oe", "1" }, + { "ograve", "1" }, + { "one", "1" }, + { "onehalf", "1" }, + { "onequarter", "1" }, + { "onesuperior", "1" }, + { "ordfeminine", "1" }, + { "ordmasculine", "1" }, + { "ornateleftparenthesis", "1" }, + { "ornaterightparenthesis", "1" }, + { "oslash", "1" }, + { "otilde", "1" }, + { "p", "1" }, + { "paragraph", "1" }, + { "parenleft", "1" }, + { "parenright", "1" }, + { "peh", "1" }, + { "pehfinal", "1" }, + { "pehinitial", "1" }, + { "pehisolated", "1" }, + { "pehmedial", "1" }, + { "pehwithhehinitial", "2" }, + { "percent", "1" }, + { "period", "1" }, + { "periodcentered", "1" }, + { "perthousand", "1" }, + { "plus", "1" }, + { "plusminus", "1" }, + { "q", "1" }, + { "qaf", "1" }, + { "qaffinal", "1" }, + { "qafinitial", "1" }, + { "qafisolated", "1" }, + { "qafmedial", "1" }, + { "question", "1" }, + { "questiondown", "1" }, + { "quotedash", "1" }, + { "quotedbl", "1" }, + { "quotedblbase", "1" }, + { "quotedblleft", "1" }, + { "quotedblright", "1" }, + { "quoteleft", "1" }, + { "quoteright", "1" }, + { "quotesinglbase", "1" }, + { "quotesingle", "1" }, + { "r", "1" }, + { "rayaleflam", "2" }, + { "registered", "1" }, + { "reh", "1" }, + { "rehfinal", "1" }, + { "rehisolated", "1" }, + { "righttoleft", "1" }, + { "s", "1" }, + { "sad", "1" }, + { "sadfinal", "1" }, + { "sadinitial", "1" }, + { "sadisolated", "1" }, + { "sadmedial", "1" }, + { "scaron", "1" }, + { "section", "1" }, + { "seen", "1" }, + { "seenfinal", "1" }, + { "seeninitial", "1" }, + { "seenisolated", "1" }, + { "seenmedial", "1" }, + { "seenwithmeeminitial", "2" }, + { "semicolon", "1" }, + { "seven", "1" }, + { "sfthyphen", "1" }, + { "shadda", "3" }, + { "shaddahontatweel", "1" }, + { "shaddaisolated", "1" }, + { "shaddalow", "1" }, + { "shaddawithdammaisolated", "1" }, + { "shaddawithdammaisolatedlow", "3" }, + { "shaddawithdammamedial", "1" }, + { "shaddawithdammatanisolated", "1" }, + { "shaddawithdammatanisolatedlow", "3" }, + { "shaddawithfathaisolated", "1" }, + { "shaddawithfathaisolatedlow", "3" }, + { "shaddawithfathamedial", "1" }, + { "shaddawithfathatanisolated", "3" }, + { "shaddawithfathatanisolatedlow", "3" }, + { "shaddawithkasraisolated", "1" }, + { "shaddawithkasraisolatedlow", "3" }, + { "shaddawithkasramedial", "1" }, + { "shaddawithkasratanisolated", "1" }, + { "shaddawithkasratanisolatedlow", "3" }, + { "sheen", "1" }, + { "sheenfinal", "1" }, + { "sheeninitial", "1" }, + { "sheenisolated", "1" }, + { "sheenmedial", "1" }, + { "sheenwithmeeminitial", "2" }, + { "six", "1" }, + { "slash", "1" }, + { "smallhighmadda", "3" }, + { "space", "1" }, + { "sterling", "1" }, + { "sukun", "3" }, + { "sukunisolated", "1" }, + { "sukunlow", "1" }, + { "sukunonhamza", "3" }, + { "sukunontatweel", "1" }, + { "superscriptalef", "3" }, + { "t", "1" }, + { "tah", "1" }, + { "tahfinal", "1" }, + { "tahinitial", "1" }, + { "tahisolated", "1" }, + { "tahmedial", "1" }, + { "tatweel", "1" }, + { "tcheh", "1" }, + { "tchehfinal", "1" }, + { "tchehinitial", "1" }, + { "tchehisolated", "1" }, + { "tchehmedial", "1" }, + { "teh", "1" }, + { "tehfinal", "1" }, + { "tehinitial", "1" }, + { "tehisolated", "1" }, + { "tehmarbuta", "1" }, + { "tehmarbutafinal", "1" }, + { "tehmarbutaisolated", "1" }, + { "tehmedial", "1" }, + { "tehwithalefmaksurafinal", "2" }, + { "tehwithhahinitial", "2" }, + { "tehwithhehinitial", "2" }, + { "tehwithjeeminitial", "2" }, + { "tehwithkhahinitial", "2" }, + { "tehwithmeeminitial", "2" }, + { "tehwithmeemisolated", "2" }, + { "tehwithnoonfinal", "2" }, + { "tehwithyehfinal", "2" }, + { "tehwithyehisolated", "2" }, + { "thal", "1" }, + { "thalfinal", "1" }, + { "thalisolated", "1" }, + { "theh", "1" }, + { "thehfinal", "1" }, + { "thehinitial", "1" }, + { "thehisolated", "1" }, + { "thehmedial", "1" }, + { "thehwithmeeminitial", "2" }, + { "thehwithmeemisolated", "2" }, + { "thorn", "1" }, + { "three", "1" }, + { "threequarters", "1" }, + { "threesuperior", "1" }, + { "tilde", "1" }, + { "trademark", "1" }, + { "two", "1" }, + { "twosuperior", "1" }, + { "u", "1" }, + { "uacute", "1" }, + { "ucircumflex", "1" }, + { "udieresis", "1" }, + { "ugrave", "1" }, + { "underscore", "1" }, + { "uni000D", "1" }, + { "uni0649.init", "1" }, + { "uni0649.medi", "1" }, + { "uni0654", "3" }, + { "uni0655", "3" }, + { "uni0655064D", "3" }, + { "uni06550650", "3" }, + { "uni25CC", "1" }, + { "uniE817", "2" }, + { "v", "1" }, + { "veh", "1" }, + { "vehfinal", "1" }, + { "vehinitial", "1" }, + { "vehisolated", "1" }, + { "vehmedial", "1" }, + { "w", "1" }, + { "waw", "1" }, + { "wawfinal", "1" }, + { "wawisolated", "1" }, + { "wawwithhamzaabove", "1" }, + { "wawwithhamzaabovefinal", "1" }, + { "wawwithhamzaaboveisolated", "1" }, + { "x", "1" }, + { "y", "1" }, + { "yacute", "1" }, + { "ydieresis", "1" }, + { "yeh", "1" }, + { "yehfinal", "1" }, + { "yehinitial", "1" }, + { "yehisolated", "1" }, + { "yehmedial", "1" }, + { "yehwithalefmaksurafinal", "2" }, + { "yehwithalefmaksuraisolated", "2" }, + { "yehwithhahinitial", "2" }, + { "yehwithhamzaabove", "1" }, + { "yehwithhamzaabovefinal", "1" }, + { "yehwithhamzaaboveinitial", "1" }, + { "yehwithhamzaaboveisolated", "1" }, + { "yehwithhamzaabovemedial", "1" }, + { "yehwithjeeminitial", "2" }, + { "yehwithkhahinitial", "2" }, + { "yehwithmeeminitial", "2" }, + { "yehwithmeemisolated", "2" }, + { "yehwithnoonfinal", "2" }, + { "yehwithrehfinal", "2" }, + { "yen", "1" }, + { "z", "1" }, + { "zah", "1" }, + { "zahfinal", "1" }, + { "zahinitial", "1" }, + { "zahisolated", "1" }, + { "zahmedial", "1" }, + { "zain", "1" }, + { "zainfinal", "1" }, + { "zainisolated", "1" }, + { "zcaron", "1" }, + { "zero", "1" }, + { "zerojoin", "1" }, + { "zeronojoin", "1" }, + { "zerowidthnobreakspace", "1" }, + }, + }, + // arab-003.ttx + { "f2", "lu0", + new String[][] { + { "_bar", "1" }, + { "_damma", "1" }, + { "_dot1", "1" }, + { "_dot1_hat", "1" }, + { "_dot1_smallV", "1" }, + { "_dot1_tah", "1" }, + { "_dot2h", "1" }, + { "_dot2h_tah", "1" }, + { "_dot2v", "1" }, + { "_dot3d", "1" }, + { "_dot3h", "1" }, + { "_dot3u", "1" }, + { "_dot3u_tah", "1" }, + { "_dot4", "1" }, + { "_gafBar", "1" }, + { "_gafBar_dot2h", "1" }, + { "_gafBar_dot3u", "1" }, + { "_hamza", "1" }, + { "_hamzaDamma", "1" }, + { "_hat", "1" }, + { "_highHamza", "1" }, + { "_hook", "1" }, + { "_invSmallV", "1" }, + { "_lines", "1" }, + { "_madda", "1" }, + { "_ring", "1" }, + { "_smallV", "1" }, + { "_tah", "1" }, + { "_vline", "1" }, + { "_wasla", "1" }, + { "_wavyHamza", "1" }, + { "_wavyHamza.b", "1" }, + { "a", "1" }, + { "absAutoKashida", "1" }, + { "absJeemRetro1", "1" }, + { "absJeemRetro1Fin", "1" }, + { "absJeemRetro1Ini", "1" }, + { "absJeemRetro1Med", "1" }, + { "absJeemRetro2", "1" }, + { "absJeemRetro2Fin", "1" }, + { "absJeemRetro2Ini", "1" }, + { "absJeemRetro2Med", "1" }, + { "absJeemRetro3", "1" }, + { "absJeemRetro3Fin", "1" }, + { "absJeemRetro3Ini", "1" }, + { "absJeemRetro3Med", "1" }, + { "absJehRetro1", "1" }, + { "absJehRetro1Fin", "1" }, + { "absJehRetro2", "1" }, + { "absJehRetro2Fin", "1" }, + { "absLamRetro", "1" }, + { "absLamRetroAlef", "2" }, + { "absLamRetroAlefFin", "2" }, + { "absLamRetroFin", "1" }, + { "absLamRetroIni", "1" }, + { "absLamRetroIni.preAlef", "1" }, + { "absLamRetroMed", "1" }, + { "absLamRetroMed.preAlef", "1" }, + { "absShaddaAlef", "3" }, + { "absSheenRetro1", "1" }, + { "absSheenRetro1Fin", "1" }, + { "absSheenRetro1Ini", "1" }, + { "absSheenRetro1Med", "1" }, + { "absSheenRetro2", "1" }, + { "absSheenRetro2Fin", "1" }, + { "absSheenRetro2Ini", "1" }, + { "absSheenRetro2Med", "1" }, + { "absTchehRetro1", "1" }, + { "absTchehRetro1Fin", "1" }, + { "absTchehRetro1Ini", "1" }, + { "absTchehRetro1Med", "1" }, + { "absTchehRetro2", "1" }, + { "absTchehRetro2Fin", "1" }, + { "absTchehRetro2Ini", "1" }, + { "absTchehRetro2Med", "1" }, + { "absWawDotBelow", "1" }, + { "absWawDotBelowFin", "1" }, + { "ampersand", "1" }, + { "asciicircum", "1" }, + { "asciitilde", "1" }, + { "asterisk", "1" }, + { "asterisk.arab", "1" }, + { "at", "1" }, + { "b", "1" }, + { "backslash", "1" }, + { "bar", "1" }, + { "braceleft", "1" }, + { "braceright", "1" }, + { "bracketleft", "1" }, + { "bracketright", "1" }, + { "c", "1" }, + { "colon", "1" }, + { "colon.arab", "1" }, + { "comma", "1" }, + { "d", "1" }, + { "dollar", "1" }, + { "e", "1" }, + { "eight", "1" }, + { "eightMedium", "3" }, + { "eightSmall", "3" }, + { "equal", "1" }, + { "exclam", "1" }, + { "exclam.arab", "1" }, + { "f", "1" }, + { "five", "1" }, + { "fiveMedium", "3" }, + { "fiveSmall", "3" }, + { "four", "1" }, + { "fourMedium", "3" }, + { "fourSmall", "3" }, + { "g", "1" }, + { "grave", "1" }, + { "greater", "1" }, + { "h", "1" }, + { "hyphen", "1" }, + { "i", "1" }, + { "j", "1" }, + { "k", "1" }, + { "l", "1" }, + { "less", "1" }, + { "m", "1" }, + { "n", "1" }, + { "nine", "1" }, + { "nineMedium", "3" }, + { "nineSmall", "3" }, + { "nonmarkingreturn", "1" }, + { "numbersign", "1" }, + { "o", "1" }, + { "one", "1" }, + { "oneMedium", "3" }, + { "oneSmall", "3" }, + { "p", "1" }, + { "parenleft", "1" }, + { "parenleft.arab", "1" }, + { "parenright", "1" }, + { "parenright.arab", "1" }, + { "percent", "1" }, + { "period", "1" }, + { "plus", "1" }, + { "q", "1" }, + { "question", "1" }, + { "quotedbl", "1" }, + { "quotedblleft.arab", "1" }, + { "quotedblright.arab", "1" }, + { "quoteleft.arab", "1" }, + { "quoteright.arab", "1" }, + { "quotesingle", "1" }, + { "r", "1" }, + { "s", "1" }, + { "semicolon", "1" }, + { "seven", "1" }, + { "sevenMedium", "3" }, + { "sevenSmall", "3" }, + { "six", "1" }, + { "sixMedium", "3" }, + { "sixSmall", "3" }, + { "slash", "1" }, + { "space", "1" }, + { "t", "1" }, + { "three", "1" }, + { "threeMedium", "3" }, + { "threeSmall", "3" }, + { "two", "1" }, + { "twoMedium", "3" }, + { "twoSmall", "3" }, + { "u", "1" }, + { "underscore", "1" }, + { "uni060C", "1" }, + { "uni060C.downward", "1" }, + { "uni0614", "3" }, + { "uni061B", "1" }, + { "uni061B.downward", "1" }, + { "uni061E", "1" }, + { "uni061F", "1" }, + { "uni0621", "1" }, + { "uni0622", "1" }, + { "uni0622.fina", "1" }, + { "uni0622.fina.postLamIni", "1" }, + { "uni0622.fina.postLamMed", "1" }, + { "uni0623", "1" }, + { "uni0623.fina", "1" }, + { "uni0623.fina.postLamIni", "1" }, + { "uni0623.fina.postLamMed", "1" }, + { "uni0624", "1" }, + { "uni0624.fina", "1" }, + { "uni0625", "1" }, + { "uni0625.fina", "1" }, + { "uni0625.fina.postLamIni", "1" }, + { "uni0625.fina.postLamMed", "1" }, + { "uni0626", "1" }, + { "uni0626.fina", "1" }, + { "uni0626.init", "1" }, + { "uni0626.medi", "1" }, + { "uni0627", "1" }, + { "uni0627.fina", "1" }, + { "uni0627.fina.postLamIni", "1" }, + { "uni0627.fina.postLamMed", "1" }, + { "uni0628", "1" }, + { "uni0628.fina", "1" }, + { "uni0628.init", "1" }, + { "uni0628.medi", "1" }, + { "uni0629", "1" }, + { "uni0629.fina", "1" }, + { "uni062A", "1" }, + { "uni062A.fina", "1" }, + { "uni062A.init", "1" }, + { "uni062A.medi", "1" }, + { "uni062B", "1" }, + { "uni062B.fina", "1" }, + { "uni062B.init", "1" }, + { "uni062B.medi", "1" }, + { "uni062C", "1" }, + { "uni062C.fina", "1" }, + { "uni062C.init", "1" }, + { "uni062C.medi", "1" }, + { "uni062D", "1" }, + { "uni062D.fina", "1" }, + { "uni062D.init", "1" }, + { "uni062D.medi", "1" }, + { "uni062E", "1" }, + { "uni062E.fina", "1" }, + { "uni062E.init", "1" }, + { "uni062E.medi", "1" }, + { "uni062F", "1" }, + { "uni062F.fina", "1" }, + { "uni0630", "1" }, + { "uni0630.fina", "1" }, + { "uni0631", "1" }, + { "uni0631.fina", "1" }, + { "uni0632", "1" }, + { "uni0632.fina", "1" }, + { "uni0633", "1" }, + { "uni0633.fina", "1" }, + { "uni0633.init", "1" }, + { "uni0633.medi", "1" }, + { "uni0634", "1" }, + { "uni0634.fina", "1" }, + { "uni0634.init", "1" }, + { "uni0634.medi", "1" }, + { "uni0635", "1" }, + { "uni0635.fina", "1" }, + { "uni0635.init", "1" }, + { "uni0635.medi", "1" }, + { "uni0636", "1" }, + { "uni0636.fina", "1" }, + { "uni0636.init", "1" }, + { "uni0636.medi", "1" }, + { "uni0637", "1" }, + { "uni0637.fina", "1" }, + { "uni0637.init", "1" }, + { "uni0637.medi", "1" }, + { "uni0638", "1" }, + { "uni0638.fina", "1" }, + { "uni0638.init", "1" }, + { "uni0638.medi", "1" }, + { "uni0639", "1" }, + { "uni0639.fina", "1" }, + { "uni0639.init", "1" }, + { "uni0639.medi", "1" }, + { "uni063A", "1" }, + { "uni063A.fina", "1" }, + { "uni063A.init", "1" }, + { "uni063A.medi", "1" }, + { "uni0640", "1" }, + { "uni0641", "1" }, + { "uni0641.fina", "1" }, + { "uni0641.init", "1" }, + { "uni0641.medi", "1" }, + { "uni0642", "1" }, + { "uni0642.fina", "1" }, + { "uni0642.init", "1" }, + { "uni0642.medi", "1" }, + { "uni0643", "1" }, + { "uni0643.fina", "1" }, + { "uni0643.init", "1" }, + { "uni0643.medi", "1" }, + { "uni0644", "1" }, + { "uni0644.fina", "1" }, + { "uni0644.init", "1" }, + { "uni0644.init.preAlef", "1" }, + { "uni0644.medi", "1" }, + { "uni0644.medi.preAlef", "1" }, + { "uni06440627", "2" }, + { "uni06440627.fina", "2" }, + { "uni0645", "1" }, + { "uni0645.fina", "1" }, + { "uni0645.fina.sindhi", "1" }, + { "uni0645.init", "1" }, + { "uni0645.medi", "1" }, + { "uni0645.sindhi", "1" }, + { "uni0646", "1" }, + { "uni0646.fina", "1" }, + { "uni0646.init", "1" }, + { "uni0646.medi", "1" }, + { "uni0647", "1" }, + { "uni0647.fina", "1" }, + { "uni0647.fina.hooked", "1" }, + { "uni0647.fina.knottedFlat", "1" }, + { "uni0647.fina.knottedHigh", "1" }, + { "uni0647.init", "1" }, + { "uni0647.init.hooked", "1" }, + { "uni0647.knotted", "1" }, + { "uni0647.medi", "1" }, + { "uni0647.medi.hooked", "1" }, + { "uni0647.medi.knottedHigh", "1" }, + { "uni0648", "1" }, + { "uni0648.fina", "1" }, + { "uni0649", "1" }, + { "uni0649.fina", "1" }, + { "uni0649.init", "1" }, + { "uni0649.medi", "1" }, + { "uni064A", "1" }, + { "uni064A.fina", "1" }, + { "uni064A.fina.noDots", "1" }, + { "uni064A.init", "1" }, + { "uni064A.init.noDots", "1" }, + { "uni064A.medi", "1" }, + { "uni064A.medi.noDots", "1" }, + { "uni064A.noDots", "1" }, + { "uni064B", "3" }, + { "uni064C", "3" }, + { "uni064C.sixNine", "3" }, + { "uni064D", "3" }, + { "uni064E", "3" }, + { "uni064F", "3" }, + { "uni0650", "3" }, + { "uni0651", "3" }, + { "uni0651064B", "3" }, + { "uni0651064C", "3" }, + { "uni0651064D", "3" }, + { "uni0651064E", "3" }, + { "uni0651064F", "3" }, + { "uni06510650", "3" }, + { "uni0652", "3" }, + { "uni0652.downOpen", "3" }, + { "uni0652.leftOpen", "3" }, + { "uni0653", "3" }, + { "uni0654", "3" }, + { "uni0654064E", "3" }, + { "uni0654064F", "3" }, + { "uni0655", "3" }, + { "uni0656", "3" }, + { "uni0657", "3" }, + { "uni0658", "3" }, + { "uni0659", "3" }, + { "uni065A", "3" }, + { "uni065B", "3" }, + { "uni065C", "3" }, + { "uni065D", "3" }, + { "uni065E", "3" }, + { "uni0660", "1" }, + { "uni0660.Medium", "3" }, + { "uni0660.Small", "3" }, + { "uni0661", "1" }, + { "uni0661.Medium", "3" }, + { "uni0661.Small", "3" }, + { "uni0662", "1" }, + { "uni0662.Medium", "3" }, + { "uni0662.Small", "3" }, + { "uni0663", "1" }, + { "uni0663.Medium", "3" }, + { "uni0663.Small", "3" }, + { "uni0664", "1" }, + { "uni0664.Medium", "3" }, + { "uni0664.Small", "3" }, + { "uni0665", "1" }, + { "uni0665.Medium", "3" }, + { "uni0665.Small", "3" }, + { "uni0666", "1" }, + { "uni0666.Medium", "3" }, + { "uni0666.Small", "3" }, + { "uni0667", "1" }, + { "uni0667.Medium", "3" }, + { "uni0667.Small", "3" }, + { "uni0668", "1" }, + { "uni0668.Medium", "3" }, + { "uni0668.Small", "3" }, + { "uni0669", "1" }, + { "uni0669.Medium", "3" }, + { "uni0669.Small", "3" }, + { "uni066A", "1" }, + { "uni066B", "1" }, + { "uni066C", "1" }, + { "uni066D", "1" }, + { "uni066E", "1" }, + { "uni066E.fina", "1" }, + { "uni066E.init", "1" }, + { "uni066E.medi", "1" }, + { "uni066F", "1" }, + { "uni066F.fina", "1" }, + { "uni066F.init", "1" }, + { "uni066F.medi", "1" }, + { "uni0670", "3" }, + { "uni0670.large", "3" }, + { "uni0671", "1" }, + { "uni0671.fina", "1" }, + { "uni0671.fina.postLamIni", "1" }, + { "uni0671.fina.postLamMed", "1" }, + { "uni0672", "1" }, + { "uni0672.fina", "1" }, + { "uni0672.fina.postLamIni", "1" }, + { "uni0672.fina.postLamMed", "1" }, + { "uni0673", "1" }, + { "uni0673.fina", "1" }, + { "uni0673.fina.postLamIni", "1" }, + { "uni0673.fina.postLamMed", "1" }, + { "uni0674", "3" }, + { "uni0675", "1" }, + { "uni0675.fina", "1" }, + { "uni0675.fina.postLamIni", "1" }, + { "uni0675.fina.postLamMed", "1" }, + { "uni0676", "1" }, + { "uni0676.fina", "1" }, + { "uni0677", "1" }, + { "uni0677.fina", "1" }, + { "uni0678", "1" }, + { "uni0678.fina", "1" }, + { "uni0678.init", "1" }, + { "uni0678.medi", "1" }, + { "uni0679", "1" }, + { "uni0679.fina", "1" }, + { "uni0679.init", "1" }, + { "uni0679.medi", "1" }, + { "uni067A", "1" }, + { "uni067A.fina", "1" }, + { "uni067A.init", "1" }, + { "uni067A.medi", "1" }, + { "uni067B", "1" }, + { "uni067B.fina", "1" }, + { "uni067B.init", "1" }, + { "uni067B.medi", "1" }, + { "uni067C", "1" }, + { "uni067C.fina", "1" }, + { "uni067C.init", "1" }, + { "uni067C.medi", "1" }, + { "uni067D", "1" }, + { "uni067D.fina", "1" }, + { "uni067D.init", "1" }, + { "uni067D.medi", "1" }, + { "uni067E", "1" }, + { "uni067E.fina", "1" }, + { "uni067E.init", "1" }, + { "uni067E.medi", "1" }, + { "uni067F", "1" }, + { "uni067F.fina", "1" }, + { "uni067F.init", "1" }, + { "uni067F.medi", "1" }, + { "uni0680", "1" }, + { "uni0680.fina", "1" }, + { "uni0680.init", "1" }, + { "uni0680.medi", "1" }, + { "uni0681", "1" }, + { "uni0681.fina", "1" }, + { "uni0681.init", "1" }, + { "uni0681.medi", "1" }, + { "uni0682", "1" }, + { "uni0682.fina", "1" }, + { "uni0682.init", "1" }, + { "uni0682.medi", "1" }, + { "uni0683", "1" }, + { "uni0683.fina", "1" }, + { "uni0683.init", "1" }, + { "uni0683.medi", "1" }, + { "uni0684", "1" }, + { "uni0684.fina", "1" }, + { "uni0684.init", "1" }, + { "uni0684.medi", "1" }, + { "uni0685", "1" }, + { "uni0685.fina", "1" }, + { "uni0685.init", "1" }, + { "uni0685.medi", "1" }, + { "uni0686", "1" }, + { "uni0686.fina", "1" }, + { "uni0686.init", "1" }, + { "uni0686.medi", "1" }, + { "uni0687", "1" }, + { "uni0687.fina", "1" }, + { "uni0687.init", "1" }, + { "uni0687.medi", "1" }, + { "uni0688", "1" }, + { "uni0688.fina", "1" }, + { "uni0689", "1" }, + { "uni0689.fina", "1" }, + { "uni068A", "1" }, + { "uni068A.fina", "1" }, + { "uni068B", "1" }, + { "uni068B.fina", "1" }, + { "uni068C", "1" }, + { "uni068C.fina", "1" }, + { "uni068D", "1" }, + { "uni068D.fina", "1" }, + { "uni068E", "1" }, + { "uni068E.fina", "1" }, + { "uni068F", "1" }, + { "uni068F.fina", "1" }, + { "uni0690", "1" }, + { "uni0690.fina", "1" }, + { "uni0691", "1" }, + { "uni0691.fina", "1" }, + { "uni0692", "1" }, + { "uni0692.fina", "1" }, + { "uni0693", "1" }, + { "uni0693.fina", "1" }, + { "uni0694", "1" }, + { "uni0694.fina", "1" }, + { "uni0695", "1" }, + { "uni0695.fina", "1" }, + { "uni0696", "1" }, + { "uni0696.fina", "1" }, + { "uni0697", "1" }, + { "uni0697.fina", "1" }, + { "uni0698", "1" }, + { "uni0698.dotHat", "1" }, + { "uni0698.fina", "1" }, + { "uni0698.fina.dotHat", "1" }, + { "uni0699", "1" }, + { "uni0699.fina", "1" }, + { "uni069A", "1" }, + { "uni069A.fina", "1" }, + { "uni069A.init", "1" }, + { "uni069A.medi", "1" }, + { "uni069B", "1" }, + { "uni069B.fina", "1" }, + { "uni069B.init", "1" }, + { "uni069B.medi", "1" }, + { "uni069C", "1" }, + { "uni069C.fina", "1" }, + { "uni069C.init", "1" }, + { "uni069C.medi", "1" }, + { "uni069D", "1" }, + { "uni069D.fina", "1" }, + { "uni069D.init", "1" }, + { "uni069D.medi", "1" }, + { "uni069E", "1" }, + { "uni069E.fina", "1" }, + { "uni069E.init", "1" }, + { "uni069E.medi", "1" }, + { "uni069F", "1" }, + { "uni069F.fina", "1" }, + { "uni069F.init", "1" }, + { "uni069F.medi", "1" }, + { "uni06A0", "1" }, + { "uni06A0.fina", "1" }, + { "uni06A0.init", "1" }, + { "uni06A0.medi", "1" }, + { "uni06A1", "1" }, + { "uni06A1.fina", "1" }, + { "uni06A1.init", "1" }, + { "uni06A1.medi", "1" }, + { "uni06A2", "1" }, + { "uni06A2.fina", "1" }, + { "uni06A2.init", "1" }, + { "uni06A2.medi", "1" }, + { "uni06A3", "1" }, + { "uni06A3.fina", "1" }, + { "uni06A3.init", "1" }, + { "uni06A3.medi", "1" }, + { "uni06A4", "1" }, + { "uni06A4.fina", "1" }, + { "uni06A4.init", "1" }, + { "uni06A4.medi", "1" }, + { "uni06A5", "1" }, + { "uni06A5.fina", "1" }, + { "uni06A5.init", "1" }, + { "uni06A5.medi", "1" }, + { "uni06A6", "1" }, + { "uni06A6.fina", "1" }, + { "uni06A6.init", "1" }, + { "uni06A6.medi", "1" }, + { "uni06A7", "1" }, + { "uni06A7.fina", "1" }, + { "uni06A7.init", "1" }, + { "uni06A7.medi", "1" }, + { "uni06A8", "1" }, + { "uni06A8.fina", "1" }, + { "uni06A8.init", "1" }, + { "uni06A8.medi", "1" }, + { "uni06A9", "1" }, + { "uni06A9.fina", "1" }, + { "uni06A9.init", "1" }, + { "uni06A9.medi", "1" }, + { "uni06AA", "1" }, + { "uni06AA.fina", "1" }, + { "uni06AA.init", "1" }, + { "uni06AA.medi", "1" }, + { "uni06AB", "1" }, + { "uni06AB.fina", "1" }, + { "uni06AB.init", "1" }, + { "uni06AB.medi", "1" }, + { "uni06AC", "1" }, + { "uni06AC.fina", "1" }, + { "uni06AC.init", "1" }, + { "uni06AC.medi", "1" }, + { "uni06AD", "1" }, + { "uni06AD.fina", "1" }, + { "uni06AD.init", "1" }, + { "uni06AD.medi", "1" }, + { "uni06AE", "1" }, + { "uni06AE.fina", "1" }, + { "uni06AE.init", "1" }, + { "uni06AE.medi", "1" }, + { "uni06AF", "1" }, + { "uni06AF.fina", "1" }, + { "uni06AF.init", "1" }, + { "uni06AF.medi", "1" }, + { "uni06B0", "1" }, + { "uni06B0.fina", "1" }, + { "uni06B0.init", "1" }, + { "uni06B0.medi", "1" }, + { "uni06B1", "1" }, + { "uni06B1.fina", "1" }, + { "uni06B1.init", "1" }, + { "uni06B1.medi", "1" }, + { "uni06B2", "1" }, + { "uni06B2.fina", "1" }, + { "uni06B2.init", "1" }, + { "uni06B2.medi", "1" }, + { "uni06B3", "1" }, + { "uni06B3.fina", "1" }, + { "uni06B3.init", "1" }, + { "uni06B3.medi", "1" }, + { "uni06B4", "1" }, + { "uni06B4.fina", "1" }, + { "uni06B4.init", "1" }, + { "uni06B4.medi", "1" }, + { "uni06B5", "1" }, + { "uni06B5.fina", "1" }, + { "uni06B5.init", "1" }, + { "uni06B5.init.preAlef", "1" }, + { "uni06B5.medi", "1" }, + { "uni06B5.medi.preAlef", "1" }, + { "uni06B50627", "2" }, + { "uni06B50627.fina", "2" }, + { "uni06B6", "1" }, + { "uni06B6.fina", "1" }, + { "uni06B6.init", "1" }, + { "uni06B6.init.preAlef", "1" }, + { "uni06B6.medi", "1" }, + { "uni06B6.medi.preAlef", "1" }, + { "uni06B60627", "2" }, + { "uni06B60627.fina", "2" }, + { "uni06B7", "1" }, + { "uni06B7.fina", "1" }, + { "uni06B7.init", "1" }, + { "uni06B7.init.preAlef", "1" }, + { "uni06B7.medi", "1" }, + { "uni06B7.medi.preAlef", "1" }, + { "uni06B70627", "2" }, + { "uni06B70627.fina", "2" }, + { "uni06B8", "1" }, + { "uni06B8.fina", "1" }, + { "uni06B8.init", "1" }, + { "uni06B8.init.preAlef", "1" }, + { "uni06B8.medi", "1" }, + { "uni06B8.medi.preAlef", "1" }, + { "uni06B80627", "2" }, + { "uni06B80627.fina", "2" }, + { "uni06B9", "1" }, + { "uni06B9.fina", "1" }, + { "uni06B9.init", "1" }, + { "uni06B9.medi", "1" }, + { "uni06BA", "1" }, + { "uni06BA.fina", "1" }, + { "uni06BA.init", "1" }, + { "uni06BA.medi", "1" }, + { "uni06BB", "1" }, + { "uni06BB.fina", "1" }, + { "uni06BB.init", "1" }, + { "uni06BB.medi", "1" }, + { "uni06BC", "1" }, + { "uni06BC.fina", "1" }, + { "uni06BC.init", "1" }, + { "uni06BC.medi", "1" }, + { "uni06BD", "1" }, + { "uni06BD.fina", "1" }, + { "uni06BD.init", "1" }, + { "uni06BD.medi", "1" }, + { "uni06BE", "1" }, + { "uni06BE.fina", "1" }, + { "uni06BE.init", "1" }, + { "uni06BE.medi", "1" }, + { "uni06BF", "1" }, + { "uni06BF.fina", "1" }, + { "uni06BF.init", "1" }, + { "uni06BF.medi", "1" }, + { "uni06C0", "1" }, + { "uni06C0.fina", "1" }, + { "uni06C0.init", "1" }, + { "uni06C0.medi", "1" }, + { "uni06C1", "1" }, + { "uni06C1.fina", "1" }, + { "uni06C1.init", "1" }, + { "uni06C1.medi", "1" }, + { "uni06C2", "1" }, + { "uni06C2.fina", "1" }, + { "uni06C2.init", "1" }, + { "uni06C2.medi", "1" }, + { "uni06C3", "1" }, + { "uni06C3.fina", "1" }, + { "uni06C4", "1" }, + { "uni06C4.fina", "1" }, + { "uni06C5", "1" }, + { "uni06C5.fina", "1" }, + { "uni06C6", "1" }, + { "uni06C6.fina", "1" }, + { "uni06C7", "1" }, + { "uni06C7.fina", "1" }, + { "uni06C8", "1" }, + { "uni06C8.fina", "1" }, + { "uni06C9", "1" }, + { "uni06C9.fina", "1" }, + { "uni06CA", "1" }, + { "uni06CA.fina", "1" }, + { "uni06CB", "1" }, + { "uni06CB.fina", "1" }, + { "uni06CC", "1" }, + { "uni06CC.fina", "1" }, + { "uni06CC.init", "1" }, + { "uni06CC.medi", "1" }, + { "uni06CD", "1" }, + { "uni06CD.fina", "1" }, + { "uni06CE", "1" }, + { "uni06CE.fina", "1" }, + { "uni06CE.init", "1" }, + { "uni06CE.medi", "1" }, + { "uni06CF", "1" }, + { "uni06CF.fina", "1" }, + { "uni06D0", "1" }, + { "uni06D0.fina", "1" }, + { "uni06D0.init", "1" }, + { "uni06D0.medi", "1" }, + { "uni06D1", "1" }, + { "uni06D1.fina", "1" }, + { "uni06D1.init", "1" }, + { "uni06D1.medi", "1" }, + { "uni06D2", "1" }, + { "uni06D2.fina", "1" }, + { "uni06D3", "1" }, + { "uni06D3.fina", "1" }, + { "uni06D4", "1" }, + { "uni06D5", "1" }, + { "uni06D6", "3" }, + { "uni06D7", "3" }, + { "uni06D8", "3" }, + { "uni06D9", "3" }, + { "uni06DA", "3" }, + { "uni06DB", "3" }, + { "uni06DC", "3" }, + { "uni06DD", "1" }, + { "uni06DD.2", "1" }, + { "uni06DD.3", "1" }, + { "uni06DD.aat1", "1" }, + { "uni06DD.aat2", "1" }, + { "uni06DD.aat3", "1" }, + { "uni06DD.sp1", "1" }, + { "uni06DD.sp2", "1" }, + { "uni06DD.sp3", "1" }, + { "uni06DE", "1" }, + { "uni06DF", "3" }, + { "uni06E0", "3" }, + { "uni06E1", "3" }, + { "uni06E2", "3" }, + { "uni06E3", "3" }, + { "uni06E4", "3" }, + { "uni06E5", "3" }, + { "uni06E6", "3" }, + { "uni06E7", "3" }, + { "uni06E8", "3" }, + { "uni06E9", "1" }, + { "uni06EA", "3" }, + { "uni06EB", "3" }, + { "uni06EC", "3" }, + { "uni06ED", "3" }, + { "uni06EE", "1" }, + { "uni06EE.fina", "1" }, + { "uni06EF", "1" }, + { "uni06EF.fina", "1" }, + { "uni06F0", "1" }, + { "uni06F0.Medium", "3" }, + { "uni06F0.Small", "3" }, + { "uni06F1", "1" }, + { "uni06F1.Medium", "3" }, + { "uni06F1.Small", "3" }, + { "uni06F2", "1" }, + { "uni06F2.Medium", "3" }, + { "uni06F2.Small", "3" }, + { "uni06F3", "1" }, + { "uni06F3.Medium", "3" }, + { "uni06F3.Small", "3" }, + { "uni06F4", "1" }, + { "uni06F4.Medium", "3" }, + { "uni06F4.Medium.urdu", "3" }, + { "uni06F4.Small", "3" }, + { "uni06F4.Small.urdu", "3" }, + { "uni06F4.urdu", "1" }, + { "uni06F5", "1" }, + { "uni06F5.Medium", "3" }, + { "uni06F5.Small", "3" }, + { "uni06F6", "1" }, + { "uni06F6.Medium", "3" }, + { "uni06F6.Medium.urdu", "3" }, + { "uni06F6.Small", "3" }, + { "uni06F6.Small.urdu", "3" }, + { "uni06F6.urdu", "1" }, + { "uni06F7", "1" }, + { "uni06F7.Medium", "3" }, + { "uni06F7.Medium.urdu", "3" }, + { "uni06F7.Small", "3" }, + { "uni06F7.Small.urdu", "3" }, + { "uni06F7.urdu", "1" }, + { "uni06F8", "1" }, + { "uni06F8.Medium", "3" }, + { "uni06F8.Small", "3" }, + { "uni06F9", "1" }, + { "uni06F9.Medium", "3" }, + { "uni06F9.Small", "3" }, + { "uni06FA", "1" }, + { "uni06FA.fina", "1" }, + { "uni06FA.init", "1" }, + { "uni06FA.medi", "1" }, + { "uni06FB", "1" }, + { "uni06FB.fina", "1" }, + { "uni06FB.init", "1" }, + { "uni06FB.medi", "1" }, + { "uni06FC", "1" }, + { "uni06FC.fina", "1" }, + { "uni06FC.init", "1" }, + { "uni06FC.medi", "1" }, + { "uni06FD", "1" }, + { "uni06FE", "1" }, + { "uni06FF", "1" }, + { "uni06FF.fina", "1" }, + { "uni06FF.init", "1" }, + { "uni06FF.medi", "1" }, + { "uni0750", "1" }, + { "uni0750.fina", "1" }, + { "uni0750.init", "1" }, + { "uni0750.medi", "1" }, + { "uni0751", "1" }, + { "uni0751.fina", "1" }, + { "uni0751.init", "1" }, + { "uni0751.medi", "1" }, + { "uni0752", "1" }, + { "uni0752.fina", "1" }, + { "uni0752.init", "1" }, + { "uni0752.medi", "1" }, + { "uni0753", "1" }, + { "uni0753.fina", "1" }, + { "uni0753.init", "1" }, + { "uni0753.medi", "1" }, + { "uni0754", "1" }, + { "uni0754.fina", "1" }, + { "uni0754.init", "1" }, + { "uni0754.medi", "1" }, + { "uni0755", "1" }, + { "uni0755.fina", "1" }, + { "uni0755.init", "1" }, + { "uni0755.medi", "1" }, + { "uni0756", "1" }, + { "uni0756.fina", "1" }, + { "uni0756.init", "1" }, + { "uni0756.medi", "1" }, + { "uni0757", "1" }, + { "uni0757.fina", "1" }, + { "uni0757.init", "1" }, + { "uni0757.medi", "1" }, + { "uni0758", "1" }, + { "uni0758.fina", "1" }, + { "uni0758.init", "1" }, + { "uni0758.medi", "1" }, + { "uni0759", "1" }, + { "uni0759.fina", "1" }, + { "uni075A", "1" }, + { "uni075A.fina", "1" }, + { "uni075B", "1" }, + { "uni075B.fina", "1" }, + { "uni075C", "1" }, + { "uni075C.fina", "1" }, + { "uni075C.init", "1" }, + { "uni075C.medi", "1" }, + { "uni075D", "1" }, + { "uni075D.fina", "1" }, + { "uni075D.init", "1" }, + { "uni075D.medi", "1" }, + { "uni075E", "1" }, + { "uni075E.fina", "1" }, + { "uni075E.init", "1" }, + { "uni075E.medi", "1" }, + { "uni075F", "1" }, + { "uni075F.fina", "1" }, + { "uni075F.init", "1" }, + { "uni075F.medi", "1" }, + { "uni0760", "1" }, + { "uni0760.fina", "1" }, + { "uni0760.init", "1" }, + { "uni0760.medi", "1" }, + { "uni0761", "1" }, + { "uni0761.fina", "1" }, + { "uni0761.init", "1" }, + { "uni0761.medi", "1" }, + { "uni0762", "1" }, + { "uni0762.fina", "1" }, + { "uni0762.init", "1" }, + { "uni0762.medi", "1" }, + { "uni0763", "1" }, + { "uni0763.fina", "1" }, + { "uni0763.init", "1" }, + { "uni0763.medi", "1" }, + { "uni0764", "1" }, + { "uni0764.fina", "1" }, + { "uni0764.init", "1" }, + { "uni0764.medi", "1" }, + { "uni0765", "1" }, + { "uni0765.fina", "1" }, + { "uni0765.init", "1" }, + { "uni0765.medi", "1" }, + { "uni0766", "1" }, + { "uni0766.fina", "1" }, + { "uni0766.init", "1" }, + { "uni0766.medi", "1" }, + { "uni0767", "1" }, + { "uni0767.fina", "1" }, + { "uni0767.init", "1" }, + { "uni0767.medi", "1" }, + { "uni0768", "1" }, + { "uni0768.fina", "1" }, + { "uni0768.init", "1" }, + { "uni0768.medi", "1" }, + { "uni0769", "1" }, + { "uni0769.fina", "1" }, + { "uni0769.init", "1" }, + { "uni0769.medi", "1" }, + { "uni076A", "1" }, + { "uni076A.fina", "1" }, + { "uni076A.init", "1" }, + { "uni076A.init.preAlef", "1" }, + { "uni076A.medi", "1" }, + { "uni076A.medi.preAlef", "1" }, + { "uni076A0627", "2" }, + { "uni076A0627.fina", "2" }, + { "uni076B", "1" }, + { "uni076B.fina", "1" }, + { "uni076C", "1" }, + { "uni076C.fina", "1" }, + { "uni076D", "1" }, + { "uni076D.fina", "1" }, + { "uni076D.init", "1" }, + { "uni076D.medi", "1" }, + { "uni2000", "1" }, + { "uni2001", "1" }, + { "uni2002", "1" }, + { "uni2003", "1" }, + { "uni2004", "1" }, + { "uni2005", "1" }, + { "uni2006", "1" }, + { "uni2007", "1" }, + { "uni2008", "1" }, + { "uni2009", "1" }, + { "uni200A", "1" }, + { "uni200B", "1" }, + { "uni200C", "1" }, + { "uni200D", "1" }, + { "uni200E", "1" }, + { "uni200F", "1" }, + { "uni202A", "1" }, + { "uni202B", "1" }, + { "uni202C", "1" }, + { "uni202D", "1" }, + { "uni202E", "1" }, + { "uni2060", "1" }, + { "uni206C", "1" }, + { "uni206D", "1" }, + { "uni25CC", "1" }, + { "uniFD3E", "1" }, + { "uniFD3F", "1" }, + { "uniFDF2", "1" }, + { "uniFDFC", "1" }, + { "uniFEFF", "1" }, + { "v", "1" }, + { "w", "1" }, + { "x", "1" }, + { "y", "1" }, + { "z", "1" }, + { "zero", "1" }, + { "zeroMedium", "3" }, + { "zeroSmall", "3" }, + }, + }, + // arab-004.ttx + { "f3", "lu0", + new String[][] { + { "_bar", "1" }, + { "_damma", "1" }, + { "_dot1", "1" }, + { "_dot1_hat", "1" }, + { "_dot1_smallV", "1" }, + { "_dot1_tah", "1" }, + { "_dot2h", "1" }, + { "_dot2h_tah", "1" }, + { "_dot2v", "1" }, + { "_dot3d", "1" }, + { "_dot3h", "1" }, + { "_dot3u", "1" }, + { "_dot3u_tah", "1" }, + { "_dot4", "1" }, + { "_gafBar", "1" }, + { "_gafBarShort", "1" }, + { "_gafBarShort_dot2h", "1" }, + { "_gafBarShort_dot3u", "1" }, + { "_gafBar_dot2h", "1" }, + { "_gafBar_dot3u", "1" }, + { "_hamza", "1" }, + { "_hamzaDamma", "1" }, + { "_hat", "1" }, + { "_highHamza", "1" }, + { "_invSmallV", "1" }, + { "_lines", "1" }, + { "_madda", "1" }, + { "_ring", "1" }, + { "_smallV", "1" }, + { "_tah", "1" }, + { "_vline", "1" }, + { "_wasla", "1" }, + { "_wavyHamza", "1" }, + { "_wavyHamza.b", "1" }, + { "a", "1" }, + { "absAutoKashida", "1" }, + { "absJeemRetro1", "1" }, + { "absJeemRetro1Fin", "1" }, + { "absJeemRetro1Ini", "1" }, + { "absJeemRetro1Med", "1" }, + { "absJeemRetro2", "1" }, + { "absJeemRetro2Fin", "1" }, + { "absJeemRetro2Ini", "1" }, + { "absJeemRetro2Med", "1" }, + { "absJeemRetro3", "1" }, + { "absJeemRetro3Fin", "1" }, + { "absJeemRetro3Ini", "1" }, + { "absJeemRetro3Med", "1" }, + { "absJehRetro1", "1" }, + { "absJehRetro1Fin", "1" }, + { "absJehRetro2", "1" }, + { "absJehRetro2Fin", "1" }, + { "absLamRetro", "1" }, + { "absLamRetroAlef", "2" }, + { "absLamRetroAlefFin", "2" }, + { "absLamRetroFin", "1" }, + { "absLamRetroIni", "1" }, + { "absLamRetroIni.preAlef", "1" }, + { "absLamRetroMed", "1" }, + { "absLamRetroMed.preAlef", "1" }, + { "absShaddaAlef", "3" }, + { "absSheenRetro1", "1" }, + { "absSheenRetro1Fin", "1" }, + { "absSheenRetro1Ini", "1" }, + { "absSheenRetro1Med", "1" }, + { "absSheenRetro2", "1" }, + { "absSheenRetro2Fin", "1" }, + { "absSheenRetro2Ini", "1" }, + { "absSheenRetro2Med", "1" }, + { "absTchehRetro1", "1" }, + { "absTchehRetro1Fin", "1" }, + { "absTchehRetro1Ini", "1" }, + { "absTchehRetro1Med", "1" }, + { "absTchehRetro2", "1" }, + { "absTchehRetro2Fin", "1" }, + { "absTchehRetro2Ini", "1" }, + { "absTchehRetro2Med", "1" }, + { "absWawDotBelow", "1" }, + { "absWawDotBelowFin", "1" }, + { "ampersand", "1" }, + { "asciicircum", "1" }, + { "asciitilde", "1" }, + { "asterisk", "1" }, + { "at", "1" }, + { "b", "1" }, + { "backslash", "1" }, + { "bar", "1" }, + { "braceleft", "1" }, + { "braceright", "1" }, + { "bracketleft", "1" }, + { "bracketright", "1" }, + { "c", "1" }, + { "colon", "1" }, + { "comma", "1" }, + { "d", "1" }, + { "dollar", "1" }, + { "e", "1" }, + { "eight", "1" }, + { "eightMedium", "3" }, + { "eightSmall", "3" }, + { "equal", "1" }, + { "exclam", "1" }, + { "f", "1" }, + { "five", "1" }, + { "fiveMedium", "3" }, + { "fiveSmall", "3" }, + { "four", "1" }, + { "fourMedium", "3" }, + { "fourSmall", "3" }, + { "g", "1" }, + { "grave", "1" }, + { "greater", "1" }, + { "h", "1" }, + { "hyphen", "1" }, + { "i", "1" }, + { "j", "1" }, + { "k", "1" }, + { "l", "1" }, + { "less", "1" }, + { "m", "1" }, + { "n", "1" }, + { "nine", "1" }, + { "nineMedium", "3" }, + { "nineSmall", "3" }, + { "nonmarkingreturn", "1" }, + { "numbersign", "1" }, + { "o", "1" }, + { "one", "1" }, + { "oneMedium", "3" }, + { "oneSmall", "3" }, + { "p", "1" }, + { "parenleft", "1" }, + { "parenright", "1" }, + { "percent", "1" }, + { "period", "1" }, + { "plus", "1" }, + { "q", "1" }, + { "question", "1" }, + { "quotedbl", "1" }, + { "quotesingle", "1" }, + { "r", "1" }, + { "s", "1" }, + { "semicolon", "1" }, + { "seven", "1" }, + { "sevenMedium", "3" }, + { "sevenSmall", "3" }, + { "six", "1" }, + { "sixMedium", "3" }, + { "sixSmall", "3" }, + { "slash", "1" }, + { "space", "1" }, + { "t", "1" }, + { "three", "1" }, + { "threeMedium", "3" }, + { "threeSmall", "3" }, + { "two", "1" }, + { "twoMedium", "3" }, + { "twoSmall", "3" }, + { "u", "1" }, + { "underscore", "1" }, + { "uni0600", "1" }, + { "uni0600.2", "1" }, + { "uni0600.3", "1" }, + { "uni0600.aat1", "1" }, + { "uni0600.aat2", "1" }, + { "uni0600.aat3", "1" }, + { "uni0600.sp1", "1" }, + { "uni0600.sp2", "1" }, + { "uni0600.sp3", "1" }, + { "uni0601", "1" }, + { "uni0601.2", "1" }, + { "uni0601.3", "1" }, + { "uni0601.4", "1" }, + { "uni0601.aat1", "1" }, + { "uni0601.aat2", "1" }, + { "uni0601.aat3", "1" }, + { "uni0601.aat4", "1" }, + { "uni0601.sp1", "1" }, + { "uni0601.sp2", "1" }, + { "uni0601.sp3", "1" }, + { "uni0601.sp4", "1" }, + { "uni0602", "1" }, + { "uni0602.2", "1" }, + { "uni0602.aat1", "1" }, + { "uni0602.aat2", "1" }, + { "uni0602.sp1", "1" }, + { "uni0602.sp2", "1" }, + { "uni0603", "1" }, + { "uni0603.2", "1" }, + { "uni0603.3", "1" }, + { "uni0603.aat1", "1" }, + { "uni0603.aat2", "1" }, + { "uni0603.aat3", "1" }, + { "uni0603.sp1", "1" }, + { "uni0603.sp2", "1" }, + { "uni0603.sp3", "1" }, + { "uni060B", "1" }, + { "uni060C", "1" }, + { "uni060C.downward", "1" }, + { "uni060D", "1" }, + { "uni060E", "1" }, + { "uni060F", "1" }, + { "uni0610", "3" }, + { "uni0611", "3" }, + { "uni0612", "3" }, + { "uni0613", "3" }, + { "uni0614", "3" }, + { "uni0615", "3" }, + { "uni061B", "1" }, + { "uni061B.downward", "1" }, + { "uni061E", "1" }, + { "uni061F", "1" }, + { "uni0621", "1" }, + { "uni0622", "1" }, + { "uni0622.fina", "1" }, + { "uni0622.fina.postLamIni", "1" }, + { "uni0622.fina.postLamMed", "1" }, + { "uni0623", "1" }, + { "uni0623.fina", "1" }, + { "uni0623.fina.postLamIni", "1" }, + { "uni0623.fina.postLamMed", "1" }, + { "uni0624", "1" }, + { "uni0624.fina", "1" }, + { "uni0625", "1" }, + { "uni0625.fina", "1" }, + { "uni0625.fina.postLamIni", "1" }, + { "uni0625.fina.postLamMed", "1" }, + { "uni0626", "1" }, + { "uni0626.fina", "1" }, + { "uni0626.init", "1" }, + { "uni0626.medi", "1" }, + { "uni0627", "1" }, + { "uni0627.fina", "1" }, + { "uni0627.fina.postLamIni", "1" }, + { "uni0627.fina.postLamMed", "1" }, + { "uni0628", "1" }, + { "uni0628.fina", "1" }, + { "uni0628.init", "1" }, + { "uni0628.medi", "1" }, + { "uni0629", "1" }, + { "uni0629.fina", "1" }, + { "uni062A", "1" }, + { "uni062A.fina", "1" }, + { "uni062A.init", "1" }, + { "uni062A.medi", "1" }, + { "uni062B", "1" }, + { "uni062B.fina", "1" }, + { "uni062B.init", "1" }, + { "uni062B.medi", "1" }, + { "uni062C", "1" }, + { "uni062C.fina", "1" }, + { "uni062C.init", "1" }, + { "uni062C.medi", "1" }, + { "uni062D", "1" }, + { "uni062D.fina", "1" }, + { "uni062D.init", "1" }, + { "uni062D.medi", "1" }, + { "uni062E", "1" }, + { "uni062E.fina", "1" }, + { "uni062E.init", "1" }, + { "uni062E.medi", "1" }, + { "uni062F", "1" }, + { "uni062F.fina", "1" }, + { "uni0630", "1" }, + { "uni0630.fina", "1" }, + { "uni0631", "1" }, + { "uni0631.fina", "1" }, + { "uni0632", "1" }, + { "uni0632.fina", "1" }, + { "uni0633", "1" }, + { "uni0633.fina", "1" }, + { "uni0633.init", "1" }, + { "uni0633.medi", "1" }, + { "uni0634", "1" }, + { "uni0634.fina", "1" }, + { "uni0634.init", "1" }, + { "uni0634.medi", "1" }, + { "uni0635", "1" }, + { "uni0635.fina", "1" }, + { "uni0635.init", "1" }, + { "uni0635.medi", "1" }, + { "uni0636", "1" }, + { "uni0636.fina", "1" }, + { "uni0636.init", "1" }, + { "uni0636.medi", "1" }, + { "uni0637", "1" }, + { "uni0637.fina", "1" }, + { "uni0637.init", "1" }, + { "uni0637.medi", "1" }, + { "uni0638", "1" }, + { "uni0638.fina", "1" }, + { "uni0638.init", "1" }, + { "uni0638.medi", "1" }, + { "uni0639", "1" }, + { "uni0639.fina", "1" }, + { "uni0639.init", "1" }, + { "uni0639.medi", "1" }, + { "uni063A", "1" }, + { "uni063A.fina", "1" }, + { "uni063A.init", "1" }, + { "uni063A.medi", "1" }, + { "uni0640", "1" }, + { "uni0641", "1" }, + { "uni0641.fina", "1" }, + { "uni0641.init", "1" }, + { "uni0641.medi", "1" }, + { "uni0642", "1" }, + { "uni0642.fina", "1" }, + { "uni0642.init", "1" }, + { "uni0642.medi", "1" }, + { "uni0643", "1" }, + { "uni0643.fina", "1" }, + { "uni0643.init", "1" }, + { "uni0643.medi", "1" }, + { "uni0644", "1" }, + { "uni0644.fina", "1" }, + { "uni0644.init", "1" }, + { "uni0644.init.preAlef", "1" }, + { "uni0644.medi", "1" }, + { "uni0644.medi.preAlef", "1" }, + { "uni06440627", "2" }, + { "uni06440627.fina", "2" }, + { "uni0645", "1" }, + { "uni0645.fina", "1" }, + { "uni0645.fina.sindhi", "1" }, + { "uni0645.init", "1" }, + { "uni0645.medi", "1" }, + { "uni0645.sindhi", "1" }, + { "uni0646", "1" }, + { "uni0646.fina", "1" }, + { "uni0646.init", "1" }, + { "uni0646.medi", "1" }, + { "uni0647", "1" }, + { "uni0647.fina", "1" }, + { "uni0647.fina.hooked", "1" }, + { "uni0647.fina.knottedFlat", "1" }, + { "uni0647.fina.knottedHigh", "1" }, + { "uni0647.init", "1" }, + { "uni0647.init.hooked", "1" }, + { "uni0647.knotted", "1" }, + { "uni0647.medi", "1" }, + { "uni0647.medi.hooked", "1" }, + { "uni0647.medi.knottedHigh", "1" }, + { "uni0648", "1" }, + { "uni0648.fina", "1" }, + { "uni0649", "1" }, + { "uni0649.fina", "1" }, + { "uni0649.init", "1" }, + { "uni0649.medi", "1" }, + { "uni064A", "1" }, + { "uni064A.fina", "1" }, + { "uni064A.fina.noDots", "1" }, + { "uni064A.init", "1" }, + { "uni064A.init.noDots", "1" }, + { "uni064A.medi", "1" }, + { "uni064A.medi.noDots", "1" }, + { "uni064A.noDots", "1" }, + { "uni064B", "3" }, + { "uni064C", "3" }, + { "uni064C.sixNine", "3" }, + { "uni064D", "3" }, + { "uni064E", "3" }, + { "uni064F", "3" }, + { "uni0650", "3" }, + { "uni0651", "3" }, + { "uni0651064B", "3" }, + { "uni0651064C", "3" }, + { "uni0651064D", "3" }, + { "uni0651064E", "3" }, + { "uni0651064F", "3" }, + { "uni06510650", "3" }, + { "uni0652", "3" }, + { "uni0652.downOpen", "3" }, + { "uni0652.leftOpen", "3" }, + { "uni0653", "3" }, + { "uni0654", "3" }, + { "uni0654064E", "3" }, + { "uni0654064F", "3" }, + { "uni0655", "3" }, + { "uni0656", "3" }, + { "uni0657", "3" }, + { "uni0658", "3" }, + { "uni0659", "3" }, + { "uni065A", "3" }, + { "uni065B", "3" }, + { "uni065C", "3" }, + { "uni065D", "3" }, + { "uni065E", "3" }, + { "uni0660", "1" }, + { "uni0660.Medium", "3" }, + { "uni0660.Small", "3" }, + { "uni0661", "1" }, + { "uni0661.Medium", "3" }, + { "uni0661.Small", "3" }, + { "uni0662", "1" }, + { "uni0662.Medium", "3" }, + { "uni0662.Small", "3" }, + { "uni0663", "1" }, + { "uni0663.Medium", "3" }, + { "uni0663.Small", "3" }, + { "uni0664", "1" }, + { "uni0664.Medium", "3" }, + { "uni0664.Small", "3" }, + { "uni0665", "1" }, + { "uni0665.Medium", "3" }, + { "uni0665.Small", "3" }, + { "uni0666", "1" }, + { "uni0666.Medium", "3" }, + { "uni0666.Small", "3" }, + { "uni0667", "1" }, + { "uni0667.Medium", "3" }, + { "uni0667.Small", "3" }, + { "uni0668", "1" }, + { "uni0668.Medium", "3" }, + { "uni0668.Small", "3" }, + { "uni0669", "1" }, + { "uni0669.Medium", "3" }, + { "uni0669.Small", "3" }, + { "uni066A", "1" }, + { "uni066B", "1" }, + { "uni066C", "1" }, + { "uni066D", "1" }, + { "uni066E", "1" }, + { "uni066E.fina", "1" }, + { "uni066E.init", "1" }, + { "uni066E.medi", "1" }, + { "uni066F", "1" }, + { "uni066F.fina", "1" }, + { "uni066F.init", "1" }, + { "uni066F.medi", "1" }, + { "uni0670", "3" }, + { "uni0670.large", "3" }, + { "uni0671", "1" }, + { "uni0671.fina", "1" }, + { "uni0671.fina.postLamIni", "1" }, + { "uni0671.fina.postLamMed", "1" }, + { "uni0672", "1" }, + { "uni0672.fina", "1" }, + { "uni0672.fina.postLamIni", "1" }, + { "uni0672.fina.postLamMed", "1" }, + { "uni0673", "1" }, + { "uni0673.fina", "1" }, + { "uni0673.fina.postLamIni", "1" }, + { "uni0673.fina.postLamMed", "1" }, + { "uni0674", "3" }, + { "uni0675", "1" }, + { "uni0675.fina", "1" }, + { "uni0675.fina.postLamIni", "1" }, + { "uni0675.fina.postLamMed", "1" }, + { "uni0676", "1" }, + { "uni0676.fina", "1" }, + { "uni0677", "1" }, + { "uni0677.fina", "1" }, + { "uni0678", "1" }, + { "uni0678.fina", "1" }, + { "uni0678.init", "1" }, + { "uni0678.medi", "1" }, + { "uni0679", "1" }, + { "uni0679.fina", "1" }, + { "uni0679.init", "1" }, + { "uni0679.medi", "1" }, + { "uni067A", "1" }, + { "uni067A.fina", "1" }, + { "uni067A.init", "1" }, + { "uni067A.medi", "1" }, + { "uni067B", "1" }, + { "uni067B.fina", "1" }, + { "uni067B.init", "1" }, + { "uni067B.medi", "1" }, + { "uni067C", "1" }, + { "uni067C.fina", "1" }, + { "uni067C.init", "1" }, + { "uni067C.medi", "1" }, + { "uni067D", "1" }, + { "uni067D.fina", "1" }, + { "uni067D.init", "1" }, + { "uni067D.medi", "1" }, + { "uni067E", "1" }, + { "uni067E.fina", "1" }, + { "uni067E.init", "1" }, + { "uni067E.medi", "1" }, + { "uni067F", "1" }, + { "uni067F.fina", "1" }, + { "uni067F.init", "1" }, + { "uni067F.medi", "1" }, + { "uni0680", "1" }, + { "uni0680.fina", "1" }, + { "uni0680.init", "1" }, + { "uni0680.medi", "1" }, + { "uni0681", "1" }, + { "uni0681.fina", "1" }, + { "uni0681.init", "1" }, + { "uni0681.medi", "1" }, + { "uni0682", "1" }, + { "uni0682.fina", "1" }, + { "uni0682.init", "1" }, + { "uni0682.medi", "1" }, + { "uni0683", "1" }, + { "uni0683.fina", "1" }, + { "uni0683.init", "1" }, + { "uni0683.medi", "1" }, + { "uni0684", "1" }, + { "uni0684.fina", "1" }, + { "uni0684.init", "1" }, + { "uni0684.medi", "1" }, + { "uni0685", "1" }, + { "uni0685.fina", "1" }, + { "uni0685.init", "1" }, + { "uni0685.medi", "1" }, + { "uni0686", "1" }, + { "uni0686.fina", "1" }, + { "uni0686.init", "1" }, + { "uni0686.medi", "1" }, + { "uni0687", "1" }, + { "uni0687.fina", "1" }, + { "uni0687.init", "1" }, + { "uni0687.medi", "1" }, + { "uni0688", "1" }, + { "uni0688.fina", "1" }, + { "uni0689", "1" }, + { "uni0689.fina", "1" }, + { "uni068A", "1" }, + { "uni068A.fina", "1" }, + { "uni068B", "1" }, + { "uni068B.fina", "1" }, + { "uni068C", "1" }, + { "uni068C.fina", "1" }, + { "uni068D", "1" }, + { "uni068D.fina", "1" }, + { "uni068E", "1" }, + { "uni068E.fina", "1" }, + { "uni068F", "1" }, + { "uni068F.fina", "1" }, + { "uni0690", "1" }, + { "uni0690.fina", "1" }, + { "uni0691", "1" }, + { "uni0691.fina", "1" }, + { "uni0692", "1" }, + { "uni0692.fina", "1" }, + { "uni0693", "1" }, + { "uni0693.fina", "1" }, + { "uni0694", "1" }, + { "uni0694.fina", "1" }, + { "uni0695", "1" }, + { "uni0695.fina", "1" }, + { "uni0696", "1" }, + { "uni0696.fina", "1" }, + { "uni0697", "1" }, + { "uni0697.fina", "1" }, + { "uni0698", "1" }, + { "uni0698.dotHat", "1" }, + { "uni0698.fina", "1" }, + { "uni0698.fina.dotHat", "1" }, + { "uni0699", "1" }, + { "uni0699.fina", "1" }, + { "uni069A", "1" }, + { "uni069A.fina", "1" }, + { "uni069A.init", "1" }, + { "uni069A.medi", "1" }, + { "uni069B", "1" }, + { "uni069B.fina", "1" }, + { "uni069B.init", "1" }, + { "uni069B.medi", "1" }, + { "uni069C", "1" }, + { "uni069C.fina", "1" }, + { "uni069C.init", "1" }, + { "uni069C.medi", "1" }, + { "uni069D", "1" }, + { "uni069D.fina", "1" }, + { "uni069D.init", "1" }, + { "uni069D.medi", "1" }, + { "uni069E", "1" }, + { "uni069E.fina", "1" }, + { "uni069E.init", "1" }, + { "uni069E.medi", "1" }, + { "uni069F", "1" }, + { "uni069F.fina", "1" }, + { "uni069F.init", "1" }, + { "uni069F.medi", "1" }, + { "uni06A0", "1" }, + { "uni06A0.fina", "1" }, + { "uni06A0.init", "1" }, + { "uni06A0.medi", "1" }, + { "uni06A1", "1" }, + { "uni06A1.fina", "1" }, + { "uni06A1.init", "1" }, + { "uni06A1.medi", "1" }, + { "uni06A2", "1" }, + { "uni06A2.fina", "1" }, + { "uni06A2.init", "1" }, + { "uni06A2.medi", "1" }, + { "uni06A3", "1" }, + { "uni06A3.fina", "1" }, + { "uni06A3.init", "1" }, + { "uni06A3.medi", "1" }, + { "uni06A4", "1" }, + { "uni06A4.fina", "1" }, + { "uni06A4.init", "1" }, + { "uni06A4.medi", "1" }, + { "uni06A5", "1" }, + { "uni06A5.fina", "1" }, + { "uni06A5.init", "1" }, + { "uni06A5.medi", "1" }, + { "uni06A6", "1" }, + { "uni06A6.fina", "1" }, + { "uni06A6.init", "1" }, + { "uni06A6.medi", "1" }, + { "uni06A7", "1" }, + { "uni06A7.fina", "1" }, + { "uni06A7.init", "1" }, + { "uni06A7.medi", "1" }, + { "uni06A8", "1" }, + { "uni06A8.fina", "1" }, + { "uni06A8.init", "1" }, + { "uni06A8.medi", "1" }, + { "uni06A9", "1" }, + { "uni06A9.fina", "1" }, + { "uni06A9.init", "1" }, + { "uni06A9.medi", "1" }, + { "uni06AA", "1" }, + { "uni06AA.fina", "1" }, + { "uni06AA.init", "1" }, + { "uni06AA.medi", "1" }, + { "uni06AB", "1" }, + { "uni06AB.fina", "1" }, + { "uni06AB.init", "1" }, + { "uni06AB.medi", "1" }, + { "uni06AC", "1" }, + { "uni06AC.fina", "1" }, + { "uni06AC.init", "1" }, + { "uni06AC.medi", "1" }, + { "uni06AD", "1" }, + { "uni06AD.fina", "1" }, + { "uni06AD.init", "1" }, + { "uni06AD.medi", "1" }, + { "uni06AE", "1" }, + { "uni06AE.fina", "1" }, + { "uni06AE.init", "1" }, + { "uni06AE.medi", "1" }, + { "uni06AF", "1" }, + { "uni06AF.fina", "1" }, + { "uni06AF.init", "1" }, + { "uni06AF.medi", "1" }, + { "uni06B0", "1" }, + { "uni06B0.fina", "1" }, + { "uni06B0.init", "1" }, + { "uni06B0.medi", "1" }, + { "uni06B1", "1" }, + { "uni06B1.fina", "1" }, + { "uni06B1.init", "1" }, + { "uni06B1.medi", "1" }, + { "uni06B2", "1" }, + { "uni06B2.fina", "1" }, + { "uni06B2.init", "1" }, + { "uni06B2.medi", "1" }, + { "uni06B3", "1" }, + { "uni06B3.fina", "1" }, + { "uni06B3.init", "1" }, + { "uni06B3.medi", "1" }, + { "uni06B4", "1" }, + { "uni06B4.fina", "1" }, + { "uni06B4.init", "1" }, + { "uni06B4.medi", "1" }, + { "uni06B5", "1" }, + { "uni06B5.fina", "1" }, + { "uni06B5.init", "1" }, + { "uni06B5.init.preAlef", "1" }, + { "uni06B5.medi", "1" }, + { "uni06B5.medi.preAlef", "1" }, + { "uni06B50627", "2" }, + { "uni06B50627.fina", "2" }, + { "uni06B6", "1" }, + { "uni06B6.fina", "1" }, + { "uni06B6.init", "1" }, + { "uni06B6.init.preAlef", "1" }, + { "uni06B6.medi", "1" }, + { "uni06B6.medi.preAlef", "1" }, + { "uni06B60627", "2" }, + { "uni06B60627.fina", "2" }, + { "uni06B7", "1" }, + { "uni06B7.fina", "1" }, + { "uni06B7.init", "1" }, + { "uni06B7.init.preAlef", "1" }, + { "uni06B7.medi", "1" }, + { "uni06B7.medi.preAlef", "1" }, + { "uni06B70627", "2" }, + { "uni06B70627.fina", "2" }, + { "uni06B8", "1" }, + { "uni06B8.fina", "1" }, + { "uni06B8.init", "1" }, + { "uni06B8.init.preAlef", "1" }, + { "uni06B8.medi", "1" }, + { "uni06B8.medi.preAlef", "1" }, + { "uni06B80627", "2" }, + { "uni06B80627.fina", "2" }, + { "uni06B9", "1" }, + { "uni06B9.fina", "1" }, + { "uni06B9.init", "1" }, + { "uni06B9.medi", "1" }, + { "uni06BA", "1" }, + { "uni06BA.fina", "1" }, + { "uni06BA.init", "1" }, + { "uni06BA.medi", "1" }, + { "uni06BB", "1" }, + { "uni06BB.fina", "1" }, + { "uni06BB.init", "1" }, + { "uni06BB.medi", "1" }, + { "uni06BC", "1" }, + { "uni06BC.fina", "1" }, + { "uni06BC.init", "1" }, + { "uni06BC.medi", "1" }, + { "uni06BD", "1" }, + { "uni06BD.fina", "1" }, + { "uni06BD.init", "1" }, + { "uni06BD.medi", "1" }, + { "uni06BE", "1" }, + { "uni06BE.fina", "1" }, + { "uni06BE.init", "1" }, + { "uni06BE.medi", "1" }, + { "uni06BF", "1" }, + { "uni06BF.fina", "1" }, + { "uni06BF.init", "1" }, + { "uni06BF.medi", "1" }, + { "uni06C0", "1" }, + { "uni06C0.fina", "1" }, + { "uni06C0.init", "1" }, + { "uni06C0.medi", "1" }, + { "uni06C1", "1" }, + { "uni06C1.fina", "1" }, + { "uni06C1.init", "1" }, + { "uni06C1.medi", "1" }, + { "uni06C2", "1" }, + { "uni06C2.fina", "1" }, + { "uni06C2.init", "1" }, + { "uni06C2.medi", "1" }, + { "uni06C3", "1" }, + { "uni06C3.fina", "1" }, + { "uni06C4", "1" }, + { "uni06C4.fina", "1" }, + { "uni06C5", "1" }, + { "uni06C5.fina", "1" }, + { "uni06C6", "1" }, + { "uni06C6.fina", "1" }, + { "uni06C7", "1" }, + { "uni06C7.fina", "1" }, + { "uni06C8", "1" }, + { "uni06C8.fina", "1" }, + { "uni06C9", "1" }, + { "uni06C9.fina", "1" }, + { "uni06CA", "1" }, + { "uni06CA.fina", "1" }, + { "uni06CB", "1" }, + { "uni06CB.fina", "1" }, + { "uni06CC", "1" }, + { "uni06CC.fina", "1" }, + { "uni06CC.init", "1" }, + { "uni06CC.medi", "1" }, + { "uni06CD", "1" }, + { "uni06CD.fina", "1" }, + { "uni06CE", "1" }, + { "uni06CE.fina", "1" }, + { "uni06CE.init", "1" }, + { "uni06CE.medi", "1" }, + { "uni06CF", "1" }, + { "uni06CF.fina", "1" }, + { "uni06D0", "1" }, + { "uni06D0.fina", "1" }, + { "uni06D0.init", "1" }, + { "uni06D0.medi", "1" }, + { "uni06D1", "1" }, + { "uni06D1.fina", "1" }, + { "uni06D1.init", "1" }, + { "uni06D1.medi", "1" }, + { "uni06D2", "1" }, + { "uni06D2.fina", "1" }, + { "uni06D3", "1" }, + { "uni06D3.fina", "1" }, + { "uni06D4", "1" }, + { "uni06D5", "1" }, + { "uni06D6", "3" }, + { "uni06D7", "3" }, + { "uni06D8", "3" }, + { "uni06D9", "3" }, + { "uni06DA", "3" }, + { "uni06DB", "3" }, + { "uni06DC", "3" }, + { "uni06DD", "1" }, + { "uni06DD.2", "1" }, + { "uni06DD.3", "1" }, + { "uni06DD.aat1", "1" }, + { "uni06DD.aat2", "1" }, + { "uni06DD.aat3", "1" }, + { "uni06DD.alt", "1" }, + { "uni06DD.alt.2", "1" }, + { "uni06DD.alt.3", "1" }, + { "uni06DD.alt.aat1", "1" }, + { "uni06DD.alt.aat2", "1" }, + { "uni06DD.alt.aat3", "1" }, + { "uni06DD.altB", "1" }, + { "uni06DD.altB.2", "1" }, + { "uni06DD.altB.3", "1" }, + { "uni06DD.altB.aat1", "1" }, + { "uni06DD.altB.aat2", "1" }, + { "uni06DD.altB.aat3", "1" }, + { "uni06DD.sp1", "1" }, + { "uni06DD.sp2", "1" }, + { "uni06DD.sp3", "1" }, + { "uni06DE", "1" }, + { "uni06DF", "3" }, + { "uni06E0", "3" }, + { "uni06E1", "3" }, + { "uni06E2", "3" }, + { "uni06E3", "3" }, + { "uni06E4", "3" }, + { "uni06E5", "3" }, + { "uni06E6", "3" }, + { "uni06E7", "3" }, + { "uni06E8", "3" }, + { "uni06E9", "1" }, + { "uni06EA", "3" }, + { "uni06EB", "3" }, + { "uni06EC", "3" }, + { "uni06ED", "3" }, + { "uni06EE", "1" }, + { "uni06EE.fina", "1" }, + { "uni06EF", "1" }, + { "uni06EF.fina", "1" }, + { "uni06F0", "1" }, + { "uni06F0.Medium", "3" }, + { "uni06F0.Small", "3" }, + { "uni06F1", "1" }, + { "uni06F1.Medium", "3" }, + { "uni06F1.Small", "3" }, + { "uni06F2", "1" }, + { "uni06F2.Medium", "3" }, + { "uni06F2.Small", "3" }, + { "uni06F3", "1" }, + { "uni06F3.Medium", "3" }, + { "uni06F3.Small", "3" }, + { "uni06F4", "1" }, + { "uni06F4.Medium", "3" }, + { "uni06F4.Medium.urdu", "3" }, + { "uni06F4.Small", "3" }, + { "uni06F4.Small.urdu", "3" }, + { "uni06F4.urdu", "1" }, + { "uni06F5", "1" }, + { "uni06F5.Medium", "3" }, + { "uni06F5.Small", "3" }, + { "uni06F6", "1" }, + { "uni06F6.Medium", "3" }, + { "uni06F6.Medium.urdu", "3" }, + { "uni06F6.Small", "3" }, + { "uni06F6.Small.urdu", "3" }, + { "uni06F6.urdu", "1" }, + { "uni06F7", "1" }, + { "uni06F7.Medium", "3" }, + { "uni06F7.Medium.urdu", "3" }, + { "uni06F7.Small", "3" }, + { "uni06F7.Small.urdu", "3" }, + { "uni06F7.urdu", "1" }, + { "uni06F8", "1" }, + { "uni06F8.Medium", "3" }, + { "uni06F8.Small", "3" }, + { "uni06F9", "1" }, + { "uni06F9.Medium", "3" }, + { "uni06F9.Small", "3" }, + { "uni06FA", "1" }, + { "uni06FA.fina", "1" }, + { "uni06FA.init", "1" }, + { "uni06FA.medi", "1" }, + { "uni06FB", "1" }, + { "uni06FB.fina", "1" }, + { "uni06FB.init", "1" }, + { "uni06FB.medi", "1" }, + { "uni06FC", "1" }, + { "uni06FC.fina", "1" }, + { "uni06FC.init", "1" }, + { "uni06FC.medi", "1" }, + { "uni06FD", "1" }, + { "uni06FE", "1" }, + { "uni06FF", "1" }, + { "uni06FF.fina", "1" }, + { "uni06FF.init", "1" }, + { "uni06FF.medi", "1" }, + { "uni0750", "1" }, + { "uni0750.fina", "1" }, + { "uni0750.init", "1" }, + { "uni0750.medi", "1" }, + { "uni0751", "1" }, + { "uni0751.fina", "1" }, + { "uni0751.init", "1" }, + { "uni0751.medi", "1" }, + { "uni0752", "1" }, + { "uni0752.fina", "1" }, + { "uni0752.init", "1" }, + { "uni0752.medi", "1" }, + { "uni0753", "1" }, + { "uni0753.fina", "1" }, + { "uni0753.init", "1" }, + { "uni0753.medi", "1" }, + { "uni0754", "1" }, + { "uni0754.fina", "1" }, + { "uni0754.init", "1" }, + { "uni0754.medi", "1" }, + { "uni0755", "1" }, + { "uni0755.fina", "1" }, + { "uni0755.init", "1" }, + { "uni0755.medi", "1" }, + { "uni0756", "1" }, + { "uni0756.fina", "1" }, + { "uni0756.init", "1" }, + { "uni0756.medi", "1" }, + { "uni0757", "1" }, + { "uni0757.fina", "1" }, + { "uni0757.init", "1" }, + { "uni0757.medi", "1" }, + { "uni0758", "1" }, + { "uni0758.fina", "1" }, + { "uni0758.init", "1" }, + { "uni0758.medi", "1" }, + { "uni0759", "1" }, + { "uni0759.fina", "1" }, + { "uni075A", "1" }, + { "uni075A.fina", "1" }, + { "uni075B", "1" }, + { "uni075B.fina", "1" }, + { "uni075C", "1" }, + { "uni075C.fina", "1" }, + { "uni075C.init", "1" }, + { "uni075C.medi", "1" }, + { "uni075D", "1" }, + { "uni075D.fina", "1" }, + { "uni075D.init", "1" }, + { "uni075D.medi", "1" }, + { "uni075E", "1" }, + { "uni075E.fina", "1" }, + { "uni075E.init", "1" }, + { "uni075E.medi", "1" }, + { "uni075F", "1" }, + { "uni075F.fina", "1" }, + { "uni075F.init", "1" }, + { "uni075F.medi", "1" }, + { "uni0760", "1" }, + { "uni0760.fina", "1" }, + { "uni0760.init", "1" }, + { "uni0760.medi", "1" }, + { "uni0761", "1" }, + { "uni0761.fina", "1" }, + { "uni0761.init", "1" }, + { "uni0761.medi", "1" }, + { "uni0762", "1" }, + { "uni0762.fina", "1" }, + { "uni0762.init", "1" }, + { "uni0762.medi", "1" }, + { "uni0763", "1" }, + { "uni0763.fina", "1" }, + { "uni0763.init", "1" }, + { "uni0763.medi", "1" }, + { "uni0764", "1" }, + { "uni0764.fina", "1" }, + { "uni0764.init", "1" }, + { "uni0764.medi", "1" }, + { "uni0765", "1" }, + { "uni0765.fina", "1" }, + { "uni0765.init", "1" }, + { "uni0765.medi", "1" }, + { "uni0766", "1" }, + { "uni0766.fina", "1" }, + { "uni0766.init", "1" }, + { "uni0766.medi", "1" }, + { "uni0767", "1" }, + { "uni0767.fina", "1" }, + { "uni0767.init", "1" }, + { "uni0767.medi", "1" }, + { "uni0768", "1" }, + { "uni0768.fina", "1" }, + { "uni0768.init", "1" }, + { "uni0768.medi", "1" }, + { "uni0769", "1" }, + { "uni0769.fina", "1" }, + { "uni0769.init", "1" }, + { "uni0769.medi", "1" }, + { "uni076A", "1" }, + { "uni076A.fina", "1" }, + { "uni076A.init", "1" }, + { "uni076A.init.preAlef", "1" }, + { "uni076A.medi", "1" }, + { "uni076A.medi.preAlef", "1" }, + { "uni076A0627", "2" }, + { "uni076A0627.fina", "2" }, + { "uni076B", "1" }, + { "uni076B.fina", "1" }, + { "uni076C", "1" }, + { "uni076C.fina", "1" }, + { "uni076D", "1" }, + { "uni076D.fina", "1" }, + { "uni076D.init", "1" }, + { "uni076D.medi", "1" }, + { "uni2000", "1" }, + { "uni2001", "1" }, + { "uni2002", "1" }, + { "uni2003", "1" }, + { "uni2004", "1" }, + { "uni2005", "1" }, + { "uni2006", "1" }, + { "uni2007", "1" }, + { "uni2008", "1" }, + { "uni2009", "1" }, + { "uni200A", "1" }, + { "uni200B", "1" }, + { "uni200C", "1" }, + { "uni200D", "1" }, + { "uni200E", "1" }, + { "uni200F", "1" }, + { "uni202A", "1" }, + { "uni202B", "1" }, + { "uni202C", "1" }, + { "uni202D", "1" }, + { "uni202E", "1" }, + { "uni2060", "1" }, + { "uni206C", "1" }, + { "uni206D", "1" }, + { "uni25CC", "1" }, + { "uniFD3E", "1" }, + { "uniFD3F", "1" }, + { "uniFDF2", "1" }, + { "uniFDFC", "1" }, + { "uniFEFF", "1" }, + { "v", "1" }, + { "w", "1" }, + { "x", "1" }, + { "y", "1" }, + { "z", "1" }, + { "zero", "1" }, + { "zeroMedium", "3" }, + { "zeroSmall", "3" }, + }, + }, + }; + + private static Object[][] ltAttachmentPoint = { + { GlyphDefinitionTable.GDEF_LOOKUP_TYPE_ATTACHMENT_POINT }, + // arab-001.ttx - not present + // arab-002.ttx - maybe add tests + // arab-003.ttx - maybe add tests + // arab-004.ttx - maybe add tests + }; + + private static Object[][] ltLigatureCaret = { + { GlyphDefinitionTable.GDEF_LOOKUP_TYPE_LIGATURE_CARET }, + // arab-001.ttx - not present + // arab-002.ttx - maybe add tests + // arab-003.ttx - maybe add tests + // arab-004.ttx - maybe add tests + }; + + private static Object[][] ltMarkAttachment = { + { GlyphDefinitionTable.GDEF_LOOKUP_TYPE_MARK_ATTACHMENT }, + // arab-001.ttx - not present + // arab-002.ttx - maybe add tests + // arab-003.ttx - maybe add tests + // arab-004.ttx - maybe add tests + }; + + @Test + public void testGDEFGlyphClass() throws Exception { + performLookups ( ltGlyphClass ); + } + + @Test + public void testGDEFAttachmentPoint() throws Exception { + performLookups ( ltAttachmentPoint ); + } + + @Test + public void testGDEFLigatureCaret() throws Exception { + performLookups ( ltLigatureCaret ); + } + + @Test + public void testGDEFMarkAttachment() throws Exception { + performLookups ( ltMarkAttachment ); + } + + /** + * Perform lookups on all test data in test specification TS. + * @param ts test specification + */ + private void performLookups ( Object[][] ts ) { + assert ts.length > 0; + Object[] tp = ts[0]; + for ( int i = 1; i < ts.length; i++ ) { + performLookups ( tp, ts[i] ); + } + } + + /** + * Perform lookups on all test data TD using test parameters TP. + * @param tp test parameters + * @param td test data + */ + private void performLookups ( Object[] tp, Object[] td ) { + assert tp.length > 0; + if ( td.length > 1 ) { + String fid = (String) td[0]; + String lid = (String) td[1]; + TTXFile tf = findTTX ( fid ); + assertTrue ( tf != null ); + GlyphDefinitionTable gdef = tf.getGDEF(); + assertTrue ( gdef != null ); + String[][] tia = (String[][]) td[2]; + switch ( (int) ( (Integer) tp[0] ) ) { + case GlyphDefinitionTable.GDEF_LOOKUP_TYPE_GLYPH_CLASS: + performGlyphClassLookups ( tf, lid, tia ); + break; + case GlyphDefinitionTable.GDEF_LOOKUP_TYPE_ATTACHMENT_POINT: + performAttachmentPointLookups ( tf, lid, tia ); + break; + case GlyphDefinitionTable.GDEF_LOOKUP_TYPE_LIGATURE_CARET: + performLigatureCaretLookups ( tf, lid, tia ); + break; + case GlyphDefinitionTable.GDEF_LOOKUP_TYPE_MARK_ATTACHMENT: + performMarkAttachmentLookups ( tf, lid, tia ); + break; + default: + assertTrue ( "bad lookup type", false ); + break; + } + } + } + + private void performGlyphClassLookups ( TTXFile tf, String lid, String[][] tia ) { + GlyphDefinitionTable gdef = tf.getGDEF(); + assert gdef != null; + for ( String[] ti : tia ) { + assert ti != null; + assert ti.length > 1; + String gn = ti[0]; + assert gn != null; + String cn = ti[1]; + assert cn != null; + int g = tf.getGlyph ( gn ); + assertTrue ( g >= 0 ); + int oc = Integer.parseInt ( cn ); + int tc = gdef.getGlyphClass ( g ); + assertEquals ( "bad glyph class for glyph \'" + gn + "\', gid(" + g + ")", oc, tc ); + } + } + + private void performAttachmentPointLookups ( TTXFile tf, String lid, String[][] tia ) { + // not yet supported by GDEF or test TTX files + } + + private void performLigatureCaretLookups ( TTXFile tf, String lid, String[][] tia ) { + // not yet supported by GDEF or test TTX files + } + + private void performMarkAttachmentLookups ( TTXFile tf, String lid, String[][] tia ) { + // not yet supported by GDEF or test TTX files + } + + private String findTTXPath ( String fid ) { + for ( String[] fs : ttxFonts ) { + if ( ( fs != null ) && ( fs.length > 1 ) ) { + if ( fs[0].equals ( fid ) ) { + return ttxFilesRoot + File.separator + fs[1]; + } + } + } + return null; + } + + private TTXFile findTTX ( String fid ) { + String pn = findTTXPath ( fid ); + assertTrue ( pn != null ); + try { + TTXFile tf = TTXFile.getFromCache ( pn ); + return tf; + } catch ( Exception e ) { + fail ( e.getMessage() ); + return null; + } + } + +} \ No newline at end of file diff --git a/test/java/org/apache/fop/complexscripts/fonts/GPOSTestCase.java b/test/java/org/apache/fop/complexscripts/fonts/GPOSTestCase.java new file mode 100644 index 000000000..28e364c43 --- /dev/null +++ b/test/java/org/apache/fop/complexscripts/fonts/GPOSTestCase.java @@ -0,0 +1,475 @@ +/* + * 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.complexscripts.fonts; + +import java.io.File; +import java.util.List; +import java.util.Map; + +import org.apache.fop.complexscripts.fonts.GlyphSubtable; +import org.apache.fop.complexscripts.fonts.GlyphPositioningSubtable; +import org.apache.fop.complexscripts.fonts.GlyphPositioningTable; +import org.apache.fop.complexscripts.fonts.GlyphTable.LookupSpec; +import org.apache.fop.complexscripts.fonts.GlyphTable.LookupTable; +import org.apache.fop.complexscripts.fonts.ttx.TTXFile; +import org.apache.fop.complexscripts.util.GlyphContextTester; +import org.apache.fop.complexscripts.util.GlyphSequence; +import org.apache.fop.complexscripts.util.ScriptContextTester; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +public class GPOSTestCase implements ScriptContextTester, GlyphContextTester { + + private static String ttxFilesRoot = "test/resources/complexscripts"; + + private static String[][] ttxFonts = { + { "f0", "arab/ttx/arab-001.ttx" }, // simplified arabic + { "f1", "arab/ttx/arab-002.ttx" }, // traditional arabic + { "f2", "arab/ttx/arab-003.ttx" }, // lateef + { "f3", "arab/ttx/arab-004.ttx" }, // scheherazade + }; + + private static Object[][] ltSingle = { + { GlyphPositioningTable.GPOS_LOOKUP_TYPE_SINGLE }, + // arab-001.ttx + { "f0", "lu1", "arab", "dflt", "mark", + new Object[][] { + { + new String[] { "fathatan" }, + new int[][] { + { 0, 0, -412, 0 } + } + }, + { + new String[] { "fatha" }, + new int[][] { + { 0, 0, -410, 0 } + } + }, + }, + }, + { "f0", "lu9", "arab", "*", "*", + new Object[][] { + { + new String[] { "fathatan" }, + new int[][] { + { 50, 0, 0, 0 } + } + }, + { + new String[] { "fatha" }, + new int[][] { + { 50, 0, 0, 0 } + } + }, + }, + }, + { "f0", "lu10", "arab", "*", "*", + new Object[][] { + { + new String[] { "kasratan" }, + new int[][] { + { 0, -200, 0, 0 } + } + }, + { + new String[] { "kasra" }, + new int[][] { + { 0, -200, 0, 0 } + } + }, + }, + }, + { "f0", "lu11", "arab", "*", "*", + new Object[][] { + { + new String[] { "kasratan" }, + new int[][] { + { 0, -300, 0, 0 } + } + }, + { + new String[] { "kasra" }, + new int[][] { + { 0, -300, 0, 0 } + } + }, + { + new String[] { "uni0655" }, + new int[][] { + { 0, -250, 0, 0 } + } + }, + }, + }, + // arab-002.ttx - maybe add tests + // arab-003.ttx - maybe add tests + // arab-004.ttx - maybe add tests + }; + + private static Object[][] ltPair = { + { GlyphPositioningTable.GPOS_LOOKUP_TYPE_PAIR }, + // arab-001.ttx + { "f0", "lu0", "arab", "dflt", "kern", + new Object[][] { + { + new String[] { "wawwithhamzaabove", "hamza" }, + new int[][] { + { -300, 0, -300, 0 }, { 0, 0, 0, 0 } + } + }, + { + new String[] { "reh", "alefwithmaddaabove" }, + new int[][] { + { -500, 0, -500, 0 }, { 0, 0, 0, 0 } + } + }, + { + new String[] { "zain", "zain" }, + new int[][] { + { -190, 0, -190, 0 }, { 0, 0, 0, 0 } + } + }, + { + new String[] { "waw", "uni0649.init" }, + new int[][] { + { -145, 0, -145, 0 }, { 0, 0, 0, 0 } + } + }, + { + new String[] { "jeh", "uni06A5.init" }, + new int[][] { + { -345, 0, -345, 0 }, { 0, 0, 0, 0 } + } + }, + }, + }, + // arab-002.ttx - maybe add tests + // arab-003.ttx - maybe add tests + // arab-004.ttx - maybe add tests + }; + + private static Object[][] ltCursive = { + { GlyphPositioningTable.GPOS_LOOKUP_TYPE_CURSIVE }, + // arab-001.ttx - none used + // arab-002.ttx - none used + // arab-003.ttx - maybe add tests + { "f2", "lu0", "arab", "dflt", "curs", + new Object[][] { + { + new String[] { "uni0644.init.preAlef", "uni0622.fina.postLamIni" }, + new int[][] { + // { 576, 0, 0, 0 }, { 0, 0, 0, 0 } - with zero widths + { 295, 0, 0, 0 }, { 0, 0, 0, 0 } + } + }, + { + new String[] { "uni0644.medi.preAlef", "uni0622.fina.postLamMed" }, + new int[][] { + // { 550, 0, 0, 0 }, { 0, 0, 0, 0 } - with zero widths + { 282, 0, 0, 0 }, { 0, 0, 0, 0 } + } + }, + }, + }, + // arab-004.ttx - none used + }; + + private static Object[][] ltMarkToBase = { + { GlyphPositioningTable.GPOS_LOOKUP_TYPE_MARK_TO_BASE }, + // arab-001.ttx - maybe add tests + // arab-002.ttx + { "f1", "lu4", "arab", "dflt", "mark", + new Object[][] { + { + new String[] { "beh", "fatha" }, + new int[][] { + // { 0, 0, 0, 0 }, { 266, -672, 0, 0 } - with zero widths + { 0, 0, 0, 0 }, { 266, -672, -199, 0 } + } + }, + { + new String[] { "alefwithhamzabelow", "kasra" }, + new int[][] { + // { 0, 0, 0, 0 }, { -48, 344, 0, 0 } - with zero widths + { 0, 0, 0, 0 }, { -48, 344, -199, 0 } + } + }, + }, + }, + // arab-003.ttx - maybe add tests + // arab-004.ttx - maybe add tests + }; + + private static Object[][] ltMarkToLigature = { + { GlyphPositioningTable.GPOS_LOOKUP_TYPE_MARK_TO_LIGATURE }, + // arab-001.ttx + { "f0", "lu4", "arab", "dflt", "mark", + new Object[][] { + { + new String[] { "rayaleflam", "fatha", "fatha", "fatha", "fatha" }, + new int[][] { + { 0, 0, 0, 0 }, { 1260, -1150, 0, 0 }, { 910, -1020, 0, 0 }, { 590, -630, 0, 0 }, { 110, -720, 0, 0 } + } + }, + { + new String[] { "rayaleflam", "kasra", "kasra", "kasra", "kasra" }, + new int[][] { + { 0, 0, 0, 0 }, { 1110 , 225, 0, 0 }, { 760, 275, 0, 0 }, { 520, 475, 0, 0 }, { 110, 425, 0, 0 } + } + }, + }, + }, + // arab-002.ttx - maybe add tests + // arab-003.ttx - maybe add tests + // arab-004.ttx - maybe add tests + }; + + private static Object[][] ltMarkToMark = { + { GlyphPositioningTable.GPOS_LOOKUP_TYPE_MARK_TO_MARK }, + // arab-001.ttx - maybe add tests + // arab-002.ttx - maybe add tests + // arab-003.ttx - maybe add tests + // arab-004.ttx + { "f3", "lu3", "arab", "dflt", "mkmk", + new Object[][] { + { + new String[] { "uni064F", "uni064E" }, + new int[][] { + { 0, 0, 0, 0 }, { -15, 495, 0, 0 } + } + }, + { + new String[] { "uni0651", "uni0670" }, + new int[][] { + { 0, 0, 0, 0 }, { -30, 705, 0, 0 } + } + }, + }, + }, + }; + + private static Object[][] ltContextual = { + { GlyphPositioningTable.GPOS_LOOKUP_TYPE_CONTEXTUAL }, + // arab-001.ttx - none used + // arab-002.ttx - none used + // arab-003.ttx - none used + // arab-004.ttx - none used + }; + + private static Object[][] ltChainedContextual = { + { GlyphPositioningTable.GPOS_LOOKUP_TYPE_CHAINED_CONTEXTUAL }, + // arab-001.ttx + { "f0", "lu3", "arab", "dflt", "mark", + new Object[][] { + { + new String[] { "behmedial", "fatha", "lam" }, + new int[][] { + { 0, 0, 0, 0 }, { 50, 0, 0, 0 }, { 0, 0, 0, 0 } + } + }, + }, + }, + // arab-002.ttx + { "f1", "lu6", "arab", "dflt", "mark", + new Object[][] { + { + new String[] { "zain", "fatha", "kafinitial" }, + new int[][] { + { 0, 0, 0, 0 }, { 0, 250, 0, 0 }, { 0, 0, 0, 0 } + } + }, + }, + }, + // arab-003.ttx - none used + // arab-004.ttx + { "f3", "lu5", "arab", "dflt", "mark", + new Object[][] { + { + new String[] { "uni064D", "uni0622.fina.postLamIni", "uni0650" }, + new int[][] { + { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 55, 424, 0, 0 } + } + }, + }, + }, + }; + + @Test + public void testGPOSSingle() throws Exception { + performPositioning ( ltSingle ); + } + + @Test + public void testGPOSPair() throws Exception { + performPositioning ( ltPair ); + } + + @Test + public void testGPOSCursive() throws Exception { + performPositioning ( ltCursive ); + } + + @Test + public void testGPOSMarkToBase() throws Exception { + performPositioning ( ltMarkToBase ); + } + + @Test + public void testGPOSMarkToLigature() throws Exception { + performPositioning ( ltMarkToLigature ); + } + + @Test + public void testGPOSMarkToMark() throws Exception { + performPositioning ( ltMarkToMark ); + } + + @Test + public void testGPOSContextual() throws Exception { + performPositioning ( ltContextual ); + } + + @Test + public void testGPOSChainedContextual() throws Exception { + performPositioning ( ltChainedContextual ); + } + + /** + * Perform positioning on all test data in test specification TS. + * @param ts test specification + */ + private void performPositioning ( Object[][] ts ) { + assert ts.length > 0; + Object[] tp = ts[0]; + for ( int i = 1; i < ts.length; i++ ) { + performPositioning ( tp, ts[i] ); + } + } + + /** + * Perform positioning on all test data TD using test parameters TP. + * @param tp test parameters + * @param td test data + */ + private void performPositioning ( Object[] tp, Object[] td ) { + assert tp.length > 0; + if ( td.length > 5 ) { + String fid = (String) td[0]; + String lid = (String) td[1]; + String script = (String) td[2]; + String language = (String) td[3]; + String feature = (String) td[4]; + TTXFile tf = findTTX ( fid ); + assertTrue ( tf != null ); + GlyphPositioningTable gpos = tf.getGPOS(); + assertTrue ( gpos != null ); + GlyphPositioningSubtable[] sta = findGPOSSubtables ( gpos, script, language, feature, lid ); + assertTrue ( sta != null ); + assertTrue ( sta.length > 0 ); + ScriptContextTester sct = findScriptContextTester ( script, language, feature ); + Object[][] tia = (Object[][]) td[5]; // test instance array + for ( Object[] ti : tia ) { // test instance + if ( ti != null ) { + if ( ti.length > 0 ) { // must have at least input glyphs + String[] igia = (String[]) ti[0]; // input glyph id array + int[][] ogpa = (int[][]) ti[1]; // output glyph positioning array + GlyphSequence igs = tf.getGlyphSequence ( igia ); + int[] widths = tf.getWidths(); + int[][] tgpa = new int [ igia.length ] [ 4 ]; + boolean adjusted = GlyphPositioningSubtable.position ( igs, script, language, feature, 1000, sta, widths, tgpa, sct ); + assertTrue ( adjusted ); + assertSamePositions ( ogpa, tgpa ); + } + } + } + } + } + + private String findTTXPath ( String fid ) { + for ( String[] fs : ttxFonts ) { + if ( ( fs != null ) && ( fs.length > 1 ) ) { + if ( fs[0].equals ( fid ) ) { + return ttxFilesRoot + File.separator + fs[1]; + } + } + } + return null; + } + + private TTXFile findTTX ( String fid ) { + String pn = findTTXPath ( fid ); + assertTrue ( pn != null ); + try { + TTXFile tf = TTXFile.getFromCache ( pn ); + return tf; + } catch ( Exception e ) { + fail ( e.getMessage() ); + return null; + } + } + + private GlyphPositioningSubtable[] findGPOSSubtables ( GlyphPositioningTable gpos, String script, String language, String feature, String lid ) { + LookupTable lt = gpos.getLookupTable ( lid ); + if ( lt != null ) { + return (GlyphPositioningSubtable[]) lt.getSubtables(); + } else { + return null; + } + } + + private ScriptContextTester findScriptContextTester ( String script, String language, String feature ) { + return this; + } + + @Override + public GlyphContextTester getTester ( String feature ) { + return this; + } + + @Override + public boolean test ( String script, String language, String feature, GlyphSequence gs, int index, int flags ) { + return true; + } + + private void assertSamePositions ( int[][] pa1, int[][] pa2 ) { + assertNotNull ( pa1 ); + assertNotNull ( pa2 ); + assertEquals ( "unequal adjustment count", pa1.length, pa2.length ); + for ( int i = 0; i < pa1.length; i++ ) { + int[] a1 = pa1 [ i ]; + int[] a2 = pa2 [ i ]; + assertNotNull ( a1 ); + assertNotNull ( a2 ); + assertEquals ( "bad adjustment array length", 4, a1.length ); + assertEquals ( "bad adjustment array length", 4, a2.length ); + for ( int k = 0; k < a1.length; k++ ) { + int p1 = a1[k]; + int p2 = a2[k]; + assertEquals ( "bad adjustment", p1, p2 ); + } + } + } +} diff --git a/test/java/org/apache/fop/complexscripts/fonts/GSUBTestCase.java b/test/java/org/apache/fop/complexscripts/fonts/GSUBTestCase.java new file mode 100644 index 000000000..d969222df --- /dev/null +++ b/test/java/org/apache/fop/complexscripts/fonts/GSUBTestCase.java @@ -0,0 +1,2268 @@ +/* + * 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.complexscripts.fonts; + +import java.io.File; +import java.nio.IntBuffer; +import java.util.List; +import java.util.Map; + +import org.apache.fop.complexscripts.fonts.GlyphSubtable; +import org.apache.fop.complexscripts.fonts.GlyphSubstitutionSubtable; +import org.apache.fop.complexscripts.fonts.GlyphSubstitutionTable; +import org.apache.fop.complexscripts.fonts.GlyphTable.LookupSpec; +import org.apache.fop.complexscripts.fonts.GlyphTable.LookupTable; +import org.apache.fop.complexscripts.fonts.ttx.TTXFile; +import org.apache.fop.complexscripts.util.GlyphContextTester; +import org.apache.fop.complexscripts.util.GlyphSequence; +import org.apache.fop.complexscripts.util.ScriptContextTester; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +public class GSUBTestCase implements ScriptContextTester, GlyphContextTester { + + private static String ttxFilesRoot = "test/resources/complexscripts"; + + private static String[][] ttxFonts = { + { "f0", "arab/ttx/arab-001.ttx" }, // simplified arabic + { "f1", "arab/ttx/arab-002.ttx" }, // traditional arabic + { "f2", "arab/ttx/arab-003.ttx" }, // lateef + { "f3", "arab/ttx/arab-004.ttx" }, // scheherazade + }; + + private static Object[][] ltSingle = { + { GlyphSubstitutionTable.GSUB_LOOKUP_TYPE_SINGLE }, + // arab-001.ttx + { "f0", "lu2", "arab", "dflt", "isol", + new String[][][] { + { { "ainisolated" }, { "ain" } }, + { { "alefmaksuraisolated" }, { "alefmaksura" } }, + { { "behisolated" }, { "beh" } }, + { { "dadisolated" }, { "dad" } }, + { { "dalisolated" }, { "dal" } }, + { { "farsiyehisolated" }, { "farsiyeh" } }, + { { "fehisolated" }, { "feh" } }, + { { "gafisolated" }, { "gaf" } }, + { { "ghainisolated" }, { "ghain" } }, + { { "hahisolated" }, { "hah" } }, + { { "jeemisolated" }, { "jeem" } }, + { { "jehisolated" }, { "jeh" } }, + { { "kafisolated" }, { "arabickaf" } }, + { { "kehehisolated" }, { "keheh" } }, + { { "khahisolated" }, { "khah" } }, + { { "meemisolated" }, { "meem" } }, + { { "noonisolated" }, { "noon" } }, + { { "pehisolated" }, { "peh" } }, + { { "qafisolated" }, { "qaf" } }, + { { "rehisolated" }, { "reh" } }, + { { "sadisolated" }, { "sad" } }, + { { "seenisolated" }, { "seen" } }, + { { "sheenisolated" }, { "sheen" } }, + { { "tahisolated" }, { "tah" } }, + { { "tchehisolated" }, { "tcheh" } }, + { { "tehisolated" }, { "teh" } }, + { { "tehmarbutaisolated" }, { "tehmarbuta" } }, + { { "thalisolated" }, { "thal" } }, + { { "thehisolated" }, { "theh" } }, + { { "vehisolated" }, { "veh" } }, + { { "wawisolated" }, { "waw" } }, + { { "yehisolated" }, { "yeh" } }, + { { "yehwithhamzaaboveisolated" }, { "yehwithhamzaabove" } }, + { { "zahisolated" }, { "zah" } }, + { { "zainisolated" }, { "zain" } }, + }, + }, + { "f0", "lu4", "arab", "dflt", "fina", + new String[][][] { + { { "ain" }, { "ainfinal" } }, + { { "alefmaksura" }, { "alefmaksurafinal" } }, + { { "alefwasla" }, { "alefwaslafinal" } }, + { { "alefwithhamzaabove" }, { "alefwithhamzaabovefinal" } }, + { { "alefwithhamzabelow" }, { "alefwithhamzabelowfinal" } }, + { { "alefwithmaddaabove" }, { "alefwithmaddaabovefinal" } }, + { { "arabicae" }, { "hehfinal" } }, + { { "arabicalef" }, { "aleffinal" } }, + { { "arabickaf" }, { "arabickaf" } }, + { { "beh" }, { "beh" } }, + { { "dad" }, { "dad" } }, + { { "dal" }, { "dal" } }, + { { "farsiyeh" }, { "farsiyehfinal" } }, + { { "feh" }, { "feh" } }, + { { "gaf" }, { "gaffinal" } }, + { { "ghain" }, { "ghainfinal" } }, + { { "hah" }, { "hahfinal" } }, + { { "heh" }, { "hehfinal" } }, + { { "jeem" }, { "jeemfinal" } }, + { { "jeh" }, { "jeh" } }, + { { "keheh" }, { "kehehfinal" } }, + { { "khah" }, { "khahfinal" } }, + { { "lam" }, { "lam" } }, + { { "meem" }, { "meem" } }, + { { "noon" }, { "noon" } }, + { { "peh" }, { "peh" } }, + { { "qaf" }, { "qaf" } }, + { { "reh" }, { "reh" } }, + { { "sad" }, { "sad" } }, + { { "seen" }, { "seen" } }, + { { "sheen" }, { "sheen" } }, + { { "tah" }, { "tah" } }, + { { "tcheh" }, { "tchehfinal" } }, + { { "teh" }, { "teh" } }, + { { "tehmarbuta" }, { "tehmarbutafinal" } }, + { { "thal" }, { "thal" } }, + { { "theh" }, { "theh" } }, + { { "veh" }, { "veh" } }, + { { "waw" }, { "waw" } }, + { { "wawwithhamzaabove" }, { "wawwithhamzaabove" } }, + { { "yeh" }, { "yehfinal" } }, + { { "yehwithhamzaabove" }, { "yehwithhamzaabovefinal" } }, + { { "zah" }, { "zah" } }, + { { "zain" }, { "zain" } }, + } + }, + { "f0", "lu5", "arab", "dflt", "init", + new String[][][] { + { { "ain" }, { "aininitial" } }, + { { "alefmaksura" }, { "uni0649.init" } }, + { { "arabickaf" }, { "kafmedial" } }, + { { "beh" }, { "behmedial" } }, + { { "dad" }, { "dadmedial" } }, + { { "farsiyeh" }, { "yehmedial" } }, + { { "feh" }, { "fehinitial" } }, + { { "gaf" }, { "gafinitial" } }, + { { "ghain" }, { "ghaininitial" } }, + { { "hah" }, { "hahmedial" } }, + { { "heh" }, { "hehinitial" } }, + { { "jeem" }, { "jeemmedial" } }, + { { "keheh" }, { "kehehinitial" } }, + { { "khah" }, { "khahmedial" } }, + { { "lam" }, { "lamisolated" } }, + { { "meem" }, { "meemmedial" } }, + { { "noon" }, { "noonmedial" } }, + { { "peh" }, { "pehmedial" } }, + { { "qaf" }, { "qafinitial" } }, + { { "sad" }, { "sadmedial" } }, + { { "seen" }, { "seenmedial" } }, + { { "sheen" }, { "sheenmedial" } }, + { { "tah" }, { "tah" } }, + { { "tcheh" }, { "tchehmedial" } }, + { { "teh" }, { "tehmedial" } }, + { { "theh" }, { "thehmedial" } }, + { { "veh" }, { "uni06A5.init" } }, + { { "yeh" }, { "yehmedial" } }, + { { "yehwithhamzaabove" }, { "yehwithhamzaabovemedial" } }, + { { "zah" }, { "zah" } }, + } + }, + { "f0", "lu6", "arab", "dflt", "medi", + new String[][][] { + { { "ain" }, { "ainmedial" } }, + { { "alefmaksura" }, { "uni0649.init" } }, + { { "arabickaf" }, { "kafmedial" } }, + { { "beh" }, { "behmedial" } }, + { { "dad" }, { "dadmedial" } }, + { { "farsiyeh" }, { "yehmedial" } }, + { { "feh" }, { "fehmedial" } }, + { { "gaf" }, { "gafmedial" } }, + { { "ghain" }, { "ghainmedial" } }, + { { "hah" }, { "hahmedial" } }, + { { "heh" }, { "hehmedial" } }, + { { "jeem" }, { "jeemmedial" } }, + { { "keheh" }, { "kehehmedial" } }, + { { "khah" }, { "khahmedial" } }, + { { "lam" }, { "lammedial" } }, + { { "meem" }, { "meemmedial" } }, + { { "noon" }, { "noonmedial" } }, + { { "peh" }, { "pehmedial" } }, + { { "qaf" }, { "qafmedial" } }, + { { "sad" }, { "sadmedial" } }, + { { "seen" }, { "seenmedial" } }, + { { "sheen" }, { "sheenmedial" } }, + { { "tah" }, { "tah" } }, + { { "tcheh" }, { "tchehmedial" } }, + { { "teh" }, { "tehmedial" } }, + { { "theh" }, { "thehmedial" } }, + { { "veh" }, { "vehmedial" } }, + { { "yeh" }, { "yehmedial" } }, + { { "yehwithhamzaabove" }, { "yehwithhamzaabovemedial" } }, + { { "zah" }, { "zah" } }, + } + }, + // arab-002.ttx + { "f1", "lu1", "arab", "*", "isol", + new String[][][] { + { { "ainisolated" }, { "ain" } }, + { { "alefmaksuraisolated" }, { "alefmaksura" } }, + { { "behisolated" }, { "beh" } }, + { { "dadisolated" }, { "dad" } }, + { { "dalisolated" }, { "dal" } }, + { { "farsiyehisolated" }, { "farsiyeh" } }, + { { "fehisolated" }, { "feh" } }, + { { "gafisolated" }, { "gaf" } }, + { { "ghainisolated" }, { "ghain" } }, + { { "hahisolated" }, { "hah" } }, + { { "jeemisolated" }, { "jeem" } }, + { { "jehisolated" }, { "jeh" } }, + { { "kafisolated" }, { "arabickaf" } }, + { { "kehehisolated" }, { "keheh" } }, + { { "khahisolated" }, { "khah" } }, + { { "meemisolated" }, { "meem" } }, + { { "noonisolated" }, { "noon" } }, + { { "pehisolated" }, { "peh" } }, + { { "qafisolated" }, { "qaf" } }, + { { "rehisolated" }, { "reh" } }, + { { "sadisolated" }, { "sad" } }, + { { "seenisolated" }, { "seen" } }, + { { "sheenisolated" }, { "sheen" } }, + { { "tahisolated" }, { "tah" } }, + { { "tchehisolated" }, { "tcheh" } }, + { { "tehisolated" }, { "teh" } }, + { { "tehmarbutaisolated" }, { "tehmarbuta" } }, + { { "thalisolated" }, { "thal" } }, + { { "thehisolated" }, { "theh" } }, + { { "vehisolated" }, { "veh" } }, + { { "wawisolated" }, { "waw" } }, + { { "yehisolated" }, { "yeh" } }, + { { "yehwithhamzaaboveisolated" }, { "yehwithhamzaabove" } }, + { { "zahisolated" }, { "zah" } }, + { { "zainisolated" }, { "zain" } }, + } + }, + { "f1", "lu3", "arab", "*", "fina", + new String[][][] { + { { "ain" }, { "ainfinal" } }, + { { "alefmaksura" }, { "alefmaksurafinal" } }, + { { "alefwasla" }, { "alefwaslafinal" } }, + { { "alefwithhamzaabove" }, { "alefwithhamzaabovefinal" } }, + { { "alefwithhamzabelow" }, { "alefwithhamzabelowfinal" } }, + { { "alefwithmaddaabove" }, { "alefwithmaddaabovefinal" } }, + { { "arabicae" }, { "hehfinal" } }, + { { "arabicalef" }, { "aleffinal" } }, + { { "arabickaf" }, { "arabickaffinal" } }, + { { "beh" }, { "behfinal" } }, + { { "dad" }, { "dadfinal" } }, + { { "dal" }, { "dalfinal" } }, + { { "farsiyeh" }, { "farsiyehfinal" } }, + { { "feh" }, { "fehfinal" } }, + { { "gaf" }, { "gaffinal" } }, + { { "ghain" }, { "ghainfinal" } }, + { { "hah" }, { "hahfinal" } }, + { { "heh" }, { "hehfinal" } }, + { { "jeem" }, { "jeemfinal" } }, + { { "jeh" }, { "jehfinal" } }, + { { "keheh" }, { "kehehfinal" } }, + { { "khah" }, { "khahfinal" } }, + { { "lam" }, { "lamfinal" } }, + { { "meem" }, { "meemfinal" } }, + { { "noon" }, { "noonfinal" } }, + { { "peh" }, { "pehfinal" } }, + { { "qaf" }, { "qaffinal" } }, + { { "reh" }, { "rehfinal" } }, + { { "sad" }, { "sadfinal" } }, + { { "seen" }, { "seenfinal" } }, + { { "sheen" }, { "sheenfinal" } }, + { { "tah" }, { "tahfinal" } }, + { { "tcheh" }, { "tchehfinal" } }, + { { "teh" }, { "tehfinal" } }, + { { "tehmarbuta" }, { "tehmarbutafinal" } }, + { { "thal" }, { "thalfinal" } }, + { { "theh" }, { "thehfinal" } }, + { { "veh" }, { "vehfinal" } }, + { { "waw" }, { "wawfinal" } }, + { { "wawwithhamzaabove" }, { "wawwithhamzaabovefinal" } }, + { { "yeh" }, { "yehfinal" } }, + { { "yehwithhamzaabove" }, { "yehwithhamzaabovefinal" } }, + { { "zah" }, { "zahfinal" } }, + { { "zain" }, { "zainfinal" } }, + } + }, + { "f1", "lu4", "arab", "*", "init", + new String[][][] { + { { "ain" }, { "aininitial" } }, + { { "alefmaksura" }, { "uni0649.init" } }, + { { "arabickaf" }, { "kafinitial" } }, + { { "beh" }, { "behinitial" } }, + { { "dad" }, { "dadinitial" } }, + { { "farsiyeh" }, { "yehinitial" } }, + { { "feh" }, { "fehinitial" } }, + { { "gaf" }, { "gafinitial" } }, + { { "ghain" }, { "ghaininitial" } }, + { { "hah" }, { "hahinitial" } }, + { { "heh" }, { "hehinitial" } }, + { { "jeem" }, { "jeeminitial" } }, + { { "keheh" }, { "kehehinitial" } }, + { { "khah" }, { "khahinitial" } }, + { { "lam" }, { "laminitial" } }, + { { "meem" }, { "meeminitial" } }, + { { "noon" }, { "nooninitial" } }, + { { "peh" }, { "pehinitial" } }, + { { "qaf" }, { "qafinitial" } }, + { { "sad" }, { "sadinitial" } }, + { { "seen" }, { "seeninitial" } }, + { { "sheen" }, { "sheeninitial" } }, + { { "tah" }, { "tahinitial" } }, + { { "tcheh" }, { "tchehinitial" } }, + { { "teh" }, { "tehinitial" } }, + { { "theh" }, { "thehinitial" } }, + { { "veh" }, { "vehinitial" } }, + { { "yeh" }, { "yehinitial" } }, + { { "yehwithhamzaabove" }, { "yehwithhamzaaboveinitial" } }, + { { "zah" }, { "zahinitial" } }, + } + }, + { "f1", "lu5", "arab", "*", "medi", + new String[][][] { + { { "ain" }, { "ainmedial" } }, + { { "alefmaksura" }, { "uni0649.medi" } }, + { { "arabickaf" }, { "kafmedial" } }, + { { "beh" }, { "behmedial" } }, + { { "dad" }, { "dadmedial" } }, + { { "farsiyeh" }, { "yehmedial" } }, + { { "feh" }, { "fehmedial" } }, + { { "gaf" }, { "gafmedial" } }, + { { "ghain" }, { "ghainmedial" } }, + { { "hah" }, { "hahmedial" } }, + { { "heh" }, { "hehmedial" } }, + { { "jeem" }, { "jeemmedial" } }, + { { "keheh" }, { "kehehmedial" } }, + { { "khah" }, { "khahmedial" } }, + { { "lam" }, { "lammedial" } }, + { { "meem" }, { "meemmedial" } }, + { { "noon" }, { "noonmedial" } }, + { { "peh" }, { "pehmedial" } }, + { { "qaf" }, { "qafmedial" } }, + { { "sad" }, { "sadmedial" } }, + { { "seen" }, { "seenmedial" } }, + { { "sheen" }, { "sheenmedial" } }, + { { "tah" }, { "tahmedial" } }, + { { "tcheh" }, { "tchehmedial" } }, + { { "teh" }, { "tehmedial" } }, + { { "theh" }, { "thehmedial" } }, + { { "veh" }, { "vehmedial" } }, + { { "yeh" }, { "yehmedial" } }, + { { "yehwithhamzaabove" }, { "yehwithhamzaabovemedial" } }, + { { "zah" }, { "zahmedial" } }, + } + }, + { "f1", "lu13", "arab", "*", "*", + new String[][][] { + { { "heh" }, { "hehisolated" } }, + } + }, + // arab-003.ttx + { "f2", "lu1", "arab", "dflt", "init", + new String[][][] { + { { "absJeemRetro1" }, { "absJeemRetro1Ini" } }, + { { "absJeemRetro2" }, { "absJeemRetro2Ini" } }, + { { "absJeemRetro3" }, { "absJeemRetro3Ini" } }, + { { "absLamRetro" }, { "absLamRetroIni" } }, + { { "absSheenRetro1" }, { "absSheenRetro1Ini" } }, + { { "absSheenRetro2" }, { "absSheenRetro2Ini" } }, + { { "absTchehRetro1" }, { "absTchehRetro1Ini" } }, + { { "absTchehRetro2" }, { "absTchehRetro2Ini" } }, + { { "uni0626" }, { "uni0626.init" } }, + { { "uni0628" }, { "uni0628.init" } }, + { { "uni062A" }, { "uni062A.init" } }, + { { "uni062B" }, { "uni062B.init" } }, + { { "uni062C" }, { "uni062C.init" } }, + { { "uni062D" }, { "uni062D.init" } }, + { { "uni062E" }, { "uni062E.init" } }, + { { "uni0633" }, { "uni0633.init" } }, + { { "uni0634" }, { "uni0634.init" } }, + { { "uni0635" }, { "uni0635.init" } }, + { { "uni0636" }, { "uni0636.init" } }, + { { "uni0637" }, { "uni0637.init" } }, + { { "uni0638" }, { "uni0638.init" } }, + { { "uni0639" }, { "uni0639.init" } }, + { { "uni063A" }, { "uni063A.init" } }, + { { "uni0641" }, { "uni0641.init" } }, + { { "uni0642" }, { "uni0642.init" } }, + { { "uni0643" }, { "uni0643.init" } }, + { { "uni0644" }, { "uni0644.init" } }, + { { "uni0645" }, { "uni0645.init" } }, + { { "uni0646" }, { "uni0646.init" } }, + { { "uni0647" }, { "uni0647.init" } }, + { { "uni0649" }, { "uni0649.init" } }, + { { "uni064A" }, { "uni064A.init" } }, + { { "uni064A.noDots" }, { "uni064A.init.noDots" } }, + { { "uni066E" }, { "uni066E.init" } }, + { { "uni066F" }, { "uni066F.init" } }, + { { "uni0678" }, { "uni0678.init" } }, + { { "uni0679" }, { "uni0679.init" } }, + { { "uni067A" }, { "uni067A.init" } }, + { { "uni067B" }, { "uni067B.init" } }, + { { "uni067C" }, { "uni067C.init" } }, + { { "uni067D" }, { "uni067D.init" } }, + { { "uni067E" }, { "uni067E.init" } }, + { { "uni067F" }, { "uni067F.init" } }, + { { "uni0680" }, { "uni0680.init" } }, + { { "uni0681" }, { "uni0681.init" } }, + { { "uni0682" }, { "uni0682.init" } }, + { { "uni0683" }, { "uni0683.init" } }, + { { "uni0684" }, { "uni0684.init" } }, + { { "uni0685" }, { "uni0685.init" } }, + { { "uni0686" }, { "uni0686.init" } }, + { { "uni0687" }, { "uni0687.init" } }, + { { "uni069A" }, { "uni069A.init" } }, + { { "uni069B" }, { "uni069B.init" } }, + { { "uni069C" }, { "uni069C.init" } }, + { { "uni069D" }, { "uni069D.init" } }, + { { "uni069E" }, { "uni069E.init" } }, + { { "uni069F" }, { "uni069F.init" } }, + { { "uni06A0" }, { "uni06A0.init" } }, + { { "uni06A1" }, { "uni06A1.init" } }, + { { "uni06A2" }, { "uni06A2.init" } }, + { { "uni06A3" }, { "uni06A3.init" } }, + { { "uni06A4" }, { "uni06A4.init" } }, + { { "uni06A5" }, { "uni06A5.init" } }, + { { "uni06A6" }, { "uni06A6.init" } }, + { { "uni06A7" }, { "uni06A7.init" } }, + { { "uni06A8" }, { "uni06A8.init" } }, + { { "uni06A9" }, { "uni06A9.init" } }, + { { "uni06AA" }, { "uni06AA.init" } }, + { { "uni06AB" }, { "uni06AB.init" } }, + { { "uni06AC" }, { "uni06AC.init" } }, + { { "uni06AD" }, { "uni06AD.init" } }, + { { "uni06AE" }, { "uni06AE.init" } }, + { { "uni06AF" }, { "uni06AF.init" } }, + { { "uni06B0" }, { "uni06B0.init" } }, + { { "uni06B1" }, { "uni06B1.init" } }, + { { "uni06B2" }, { "uni06B2.init" } }, + { { "uni06B3" }, { "uni06B3.init" } }, + { { "uni06B4" }, { "uni06B4.init" } }, + { { "uni06B5" }, { "uni06B5.init" } }, + { { "uni06B6" }, { "uni06B6.init" } }, + { { "uni06B7" }, { "uni06B7.init" } }, + { { "uni06B8" }, { "uni06B8.init" } }, + { { "uni06B9" }, { "uni06B9.init" } }, + { { "uni06BA" }, { "uni06BA.init" } }, + { { "uni06BB" }, { "uni06BB.init" } }, + { { "uni06BC" }, { "uni06BC.init" } }, + { { "uni06BD" }, { "uni06BD.init" } }, + { { "uni06BE" }, { "uni06BE.init" } }, + { { "uni06BF" }, { "uni06BF.init" } }, + { { "uni06C1" }, { "uni06C1.init" } }, + { { "uni06C2" }, { "uni06C2.init" } }, + { { "uni06CC" }, { "uni06CC.init" } }, + { { "uni06CE" }, { "uni06CE.init" } }, + { { "uni06D0" }, { "uni06D0.init" } }, + { { "uni06D1" }, { "uni06D1.init" } }, + { { "uni06FA" }, { "uni06FA.init" } }, + { { "uni06FB" }, { "uni06FB.init" } }, + { { "uni06FC" }, { "uni06FC.init" } }, + { { "uni06FF" }, { "uni06FF.init" } }, + { { "uni0750" }, { "uni0750.init" } }, + { { "uni0751" }, { "uni0751.init" } }, + { { "uni0752" }, { "uni0752.init" } }, + { { "uni0753" }, { "uni0753.init" } }, + { { "uni0754" }, { "uni0754.init" } }, + { { "uni0755" }, { "uni0755.init" } }, + { { "uni0756" }, { "uni0756.init" } }, + { { "uni0757" }, { "uni0757.init" } }, + { { "uni0758" }, { "uni0758.init" } }, + { { "uni075C" }, { "uni075C.init" } }, + { { "uni075D" }, { "uni075D.init" } }, + { { "uni075E" }, { "uni075E.init" } }, + { { "uni075F" }, { "uni075F.init" } }, + { { "uni0760" }, { "uni0760.init" } }, + { { "uni0761" }, { "uni0761.init" } }, + { { "uni0762" }, { "uni0762.init" } }, + { { "uni0763" }, { "uni0763.init" } }, + { { "uni0764" }, { "uni0764.init" } }, + { { "uni0765" }, { "uni0765.init" } }, + { { "uni0766" }, { "uni0766.init" } }, + { { "uni0767" }, { "uni0767.init" } }, + { { "uni0768" }, { "uni0768.init" } }, + { { "uni0769" }, { "uni0769.init" } }, + { { "uni076A" }, { "uni076A.init" } }, + { { "uni076D" }, { "uni076D.init" } }, + } + }, + { "f2", "lu2", "arab", "dflt", "fina", + new String[][][] { + { { "absJeemRetro1" }, { "absJeemRetro1Fin" } }, + { { "absJeemRetro2" }, { "absJeemRetro2Fin" } }, + { { "absJeemRetro3" }, { "absJeemRetro3Fin" } }, + { { "absJehRetro1" }, { "absJehRetro1Fin" } }, + { { "absJehRetro2" }, { "absJehRetro2Fin" } }, + { { "absLamRetro" }, { "absLamRetroFin" } }, + { { "absSheenRetro1" }, { "absSheenRetro1Fin" } }, + { { "absSheenRetro2" }, { "absSheenRetro2Fin" } }, + { { "absTchehRetro1" }, { "absTchehRetro1Fin" } }, + { { "absTchehRetro2" }, { "absTchehRetro2Fin" } }, + { { "absWawDotBelow" }, { "absWawDotBelowFin" } }, + { { "uni0622" }, { "uni0622.fina" } }, + { { "uni0623" }, { "uni0623.fina" } }, + { { "uni0624" }, { "uni0624.fina" } }, + { { "uni0625" }, { "uni0625.fina" } }, + { { "uni0626" }, { "uni0626.fina" } }, + { { "uni0627" }, { "uni0627.fina" } }, + { { "uni0628" }, { "uni0628.fina" } }, + { { "uni0629" }, { "uni0629.fina" } }, + { { "uni062A" }, { "uni062A.fina" } }, + { { "uni062B" }, { "uni062B.fina" } }, + { { "uni062C" }, { "uni062C.fina" } }, + { { "uni062D" }, { "uni062D.fina" } }, + { { "uni062E" }, { "uni062E.fina" } }, + { { "uni062F" }, { "uni062F.fina" } }, + { { "uni0630" }, { "uni0630.fina" } }, + { { "uni0631" }, { "uni0631.fina" } }, + { { "uni0632" }, { "uni0632.fina" } }, + { { "uni0633" }, { "uni0633.fina" } }, + { { "uni0634" }, { "uni0634.fina" } }, + { { "uni0635" }, { "uni0635.fina" } }, + { { "uni0636" }, { "uni0636.fina" } }, + { { "uni0637" }, { "uni0637.fina" } }, + { { "uni0638" }, { "uni0638.fina" } }, + { { "uni0639" }, { "uni0639.fina" } }, + { { "uni063A" }, { "uni063A.fina" } }, + { { "uni0641" }, { "uni0641.fina" } }, + { { "uni0642" }, { "uni0642.fina" } }, + { { "uni0643" }, { "uni0643.fina" } }, + { { "uni0644" }, { "uni0644.fina" } }, + { { "uni0645" }, { "uni0645.fina" } }, + { { "uni0646" }, { "uni0646.fina" } }, + { { "uni0647" }, { "uni0647.fina" } }, + { { "uni0648" }, { "uni0648.fina" } }, + { { "uni0649" }, { "uni0649.fina" } }, + { { "uni064A" }, { "uni064A.fina" } }, + { { "uni064A.noDots" }, { "uni064A.fina.noDots" } }, + { { "uni066E" }, { "uni066E.fina" } }, + { { "uni066F" }, { "uni066F.fina" } }, + { { "uni0671" }, { "uni0671.fina" } }, + { { "uni0672" }, { "uni0672.fina" } }, + { { "uni0673" }, { "uni0673.fina" } }, + { { "uni0675" }, { "uni0675.fina" } }, + { { "uni0676" }, { "uni0676.fina" } }, + { { "uni0677" }, { "uni0677.fina" } }, + { { "uni0678" }, { "uni0678.fina" } }, + { { "uni0679" }, { "uni0679.fina" } }, + { { "uni067A" }, { "uni067A.fina" } }, + { { "uni067B" }, { "uni067B.fina" } }, + { { "uni067C" }, { "uni067C.fina" } }, + { { "uni067D" }, { "uni067D.fina" } }, + { { "uni067E" }, { "uni067E.fina" } }, + { { "uni067F" }, { "uni067F.fina" } }, + { { "uni0680" }, { "uni0680.fina" } }, + { { "uni0681" }, { "uni0681.fina" } }, + { { "uni0682" }, { "uni0682.fina" } }, + { { "uni0683" }, { "uni0683.fina" } }, + { { "uni0684" }, { "uni0684.fina" } }, + { { "uni0685" }, { "uni0685.fina" } }, + { { "uni0686" }, { "uni0686.fina" } }, + { { "uni0687" }, { "uni0687.fina" } }, + { { "uni0688" }, { "uni0688.fina" } }, + { { "uni0689" }, { "uni0689.fina" } }, + { { "uni068A" }, { "uni068A.fina" } }, + { { "uni068B" }, { "uni068B.fina" } }, + { { "uni068C" }, { "uni068C.fina" } }, + { { "uni068D" }, { "uni068D.fina" } }, + { { "uni068E" }, { "uni068E.fina" } }, + { { "uni068F" }, { "uni068F.fina" } }, + { { "uni0690" }, { "uni0690.fina" } }, + { { "uni0691" }, { "uni0691.fina" } }, + { { "uni0692" }, { "uni0692.fina" } }, + { { "uni0693" }, { "uni0693.fina" } }, + { { "uni0694" }, { "uni0694.fina" } }, + { { "uni0695" }, { "uni0695.fina" } }, + { { "uni0696" }, { "uni0696.fina" } }, + { { "uni0697" }, { "uni0697.fina" } }, + { { "uni0698" }, { "uni0698.fina" } }, + { { "uni0698.dotHat" }, { "uni0698.fina.dotHat" } }, + { { "uni0699" }, { "uni0699.fina" } }, + { { "uni069A" }, { "uni069A.fina" } }, + { { "uni069B" }, { "uni069B.fina" } }, + { { "uni069C" }, { "uni069C.fina" } }, + { { "uni069D" }, { "uni069D.fina" } }, + { { "uni069E" }, { "uni069E.fina" } }, + { { "uni069F" }, { "uni069F.fina" } }, + { { "uni06A0" }, { "uni06A0.fina" } }, + { { "uni06A1" }, { "uni06A1.fina" } }, + { { "uni06A2" }, { "uni06A2.fina" } }, + { { "uni06A3" }, { "uni06A3.fina" } }, + { { "uni06A4" }, { "uni06A4.fina" } }, + { { "uni06A5" }, { "uni06A5.fina" } }, + { { "uni06A6" }, { "uni06A6.fina" } }, + { { "uni06A7" }, { "uni06A7.fina" } }, + { { "uni06A8" }, { "uni06A8.fina" } }, + { { "uni06A9" }, { "uni06A9.fina" } }, + { { "uni06AA" }, { "uni06AA.fina" } }, + { { "uni06AB" }, { "uni06AB.fina" } }, + { { "uni06AC" }, { "uni06AC.fina" } }, + { { "uni06AD" }, { "uni06AD.fina" } }, + { { "uni06AE" }, { "uni06AE.fina" } }, + { { "uni06AF" }, { "uni06AF.fina" } }, + { { "uni06B0" }, { "uni06B0.fina" } }, + { { "uni06B1" }, { "uni06B1.fina" } }, + { { "uni06B2" }, { "uni06B2.fina" } }, + { { "uni06B3" }, { "uni06B3.fina" } }, + { { "uni06B4" }, { "uni06B4.fina" } }, + { { "uni06B5" }, { "uni06B5.fina" } }, + { { "uni06B6" }, { "uni06B6.fina" } }, + { { "uni06B7" }, { "uni06B7.fina" } }, + { { "uni06B8" }, { "uni06B8.fina" } }, + { { "uni06B9" }, { "uni06B9.fina" } }, + { { "uni06BA" }, { "uni06BA.fina" } }, + { { "uni06BB" }, { "uni06BB.fina" } }, + { { "uni06BC" }, { "uni06BC.fina" } }, + { { "uni06BD" }, { "uni06BD.fina" } }, + { { "uni06BE" }, { "uni06BE.fina" } }, + { { "uni06BF" }, { "uni06BF.fina" } }, + { { "uni06C0" }, { "uni06C0.fina" } }, + { { "uni06C1" }, { "uni06C1.fina" } }, + { { "uni06C2" }, { "uni06C2.fina" } }, + { { "uni06C3" }, { "uni06C3.fina" } }, + { { "uni06C4" }, { "uni06C4.fina" } }, + { { "uni06C5" }, { "uni06C5.fina" } }, + { { "uni06C6" }, { "uni06C6.fina" } }, + { { "uni06C7" }, { "uni06C7.fina" } }, + { { "uni06C8" }, { "uni06C8.fina" } }, + { { "uni06C9" }, { "uni06C9.fina" } }, + { { "uni06CA" }, { "uni06CA.fina" } }, + { { "uni06CB" }, { "uni06CB.fina" } }, + { { "uni06CC" }, { "uni06CC.fina" } }, + { { "uni06CD" }, { "uni06CD.fina" } }, + { { "uni06CE" }, { "uni06CE.fina" } }, + { { "uni06CF" }, { "uni06CF.fina" } }, + { { "uni06D0" }, { "uni06D0.fina" } }, + { { "uni06D1" }, { "uni06D1.fina" } }, + { { "uni06D2" }, { "uni06D2.fina" } }, + { { "uni06D3" }, { "uni06D3.fina" } }, + { { "uni06D5" }, { "uni06D5.fina" } }, + { { "uni06EE" }, { "uni06EE.fina" } }, + { { "uni06EF" }, { "uni06EF.fina" } }, + { { "uni06FA" }, { "uni06FA.fina" } }, + { { "uni06FB" }, { "uni06FB.fina" } }, + { { "uni06FC" }, { "uni06FC.fina" } }, + { { "uni06FF" }, { "uni06FF.fina" } }, + { { "uni0750" }, { "uni0750.fina" } }, + { { "uni0751" }, { "uni0751.fina" } }, + { { "uni0752" }, { "uni0752.fina" } }, + { { "uni0753" }, { "uni0753.fina" } }, + { { "uni0754" }, { "uni0754.fina" } }, + { { "uni0755" }, { "uni0755.fina" } }, + { { "uni0756" }, { "uni0756.fina" } }, + { { "uni0757" }, { "uni0757.fina" } }, + { { "uni0758" }, { "uni0758.fina" } }, + { { "uni0759" }, { "uni0759.fina" } }, + { { "uni075A" }, { "uni075A.fina" } }, + { { "uni075B" }, { "uni075B.fina" } }, + { { "uni075C" }, { "uni075C.fina" } }, + { { "uni075D" }, { "uni075D.fina" } }, + { { "uni075E" }, { "uni075E.fina" } }, + { { "uni075F" }, { "uni075F.fina" } }, + { { "uni0760" }, { "uni0760.fina" } }, + { { "uni0761" }, { "uni0761.fina" } }, + { { "uni0762" }, { "uni0762.fina" } }, + { { "uni0763" }, { "uni0763.fina" } }, + { { "uni0764" }, { "uni0764.fina" } }, + { { "uni0765" }, { "uni0765.fina" } }, + { { "uni0766" }, { "uni0766.fina" } }, + { { "uni0767" }, { "uni0767.fina" } }, + { { "uni0768" }, { "uni0768.fina" } }, + { { "uni0769" }, { "uni0769.fina" } }, + { { "uni076A" }, { "uni076A.fina" } }, + { { "uni076B" }, { "uni076B.fina" } }, + { { "uni076C" }, { "uni076C.fina" } }, + { { "uni076D" }, { "uni076D.fina" } }, + } + }, + { "f2", "lu3", "arab", "dflt", "medi", + new String[][][] { + { { "absJeemRetro1" }, { "absJeemRetro1Med" } }, + { { "absJeemRetro2" }, { "absJeemRetro2Med" } }, + { { "absJeemRetro3" }, { "absJeemRetro3Med" } }, + { { "absLamRetro" }, { "absLamRetroMed" } }, + { { "absSheenRetro1" }, { "absSheenRetro1Med" } }, + { { "absSheenRetro2" }, { "absSheenRetro2Med" } }, + { { "absTchehRetro1" }, { "absTchehRetro1Med" } }, + { { "absTchehRetro2" }, { "absTchehRetro2Med" } }, + { { "uni0626" }, { "uni0626.medi" } }, + { { "uni0628" }, { "uni0628.medi" } }, + { { "uni062A" }, { "uni062A.medi" } }, + { { "uni062B" }, { "uni062B.medi" } }, + { { "uni062C" }, { "uni062C.medi" } }, + { { "uni062D" }, { "uni062D.medi" } }, + { { "uni062E" }, { "uni062E.medi" } }, + { { "uni0633" }, { "uni0633.medi" } }, + { { "uni0634" }, { "uni0634.medi" } }, + { { "uni0635" }, { "uni0635.medi" } }, + { { "uni0636" }, { "uni0636.medi" } }, + { { "uni0637" }, { "uni0637.medi" } }, + { { "uni0638" }, { "uni0638.medi" } }, + { { "uni0639" }, { "uni0639.medi" } }, + { { "uni063A" }, { "uni063A.medi" } }, + { { "uni0641" }, { "uni0641.medi" } }, + { { "uni0642" }, { "uni0642.medi" } }, + { { "uni0643" }, { "uni0643.medi" } }, + { { "uni0644" }, { "uni0644.medi" } }, + { { "uni0645" }, { "uni0645.medi" } }, + { { "uni0646" }, { "uni0646.medi" } }, + { { "uni0647" }, { "uni0647.medi" } }, + { { "uni0649" }, { "uni0649.medi" } }, + { { "uni064A" }, { "uni064A.medi" } }, + { { "uni064A.noDots" }, { "uni064A.medi.noDots" } }, + { { "uni066E" }, { "uni066E.medi" } }, + { { "uni066F" }, { "uni066F.medi" } }, + { { "uni0678" }, { "uni0678.medi" } }, + { { "uni0679" }, { "uni0679.medi" } }, + { { "uni067A" }, { "uni067A.medi" } }, + { { "uni067B" }, { "uni067B.medi" } }, + { { "uni067C" }, { "uni067C.medi" } }, + { { "uni067D" }, { "uni067D.medi" } }, + { { "uni067E" }, { "uni067E.medi" } }, + { { "uni067F" }, { "uni067F.medi" } }, + { { "uni0680" }, { "uni0680.medi" } }, + { { "uni0681" }, { "uni0681.medi" } }, + { { "uni0682" }, { "uni0682.medi" } }, + { { "uni0683" }, { "uni0683.medi" } }, + { { "uni0684" }, { "uni0684.medi" } }, + { { "uni0685" }, { "uni0685.medi" } }, + { { "uni0686" }, { "uni0686.medi" } }, + { { "uni0687" }, { "uni0687.medi" } }, + { { "uni069A" }, { "uni069A.medi" } }, + { { "uni069B" }, { "uni069B.medi" } }, + { { "uni069C" }, { "uni069C.medi" } }, + { { "uni069D" }, { "uni069D.medi" } }, + { { "uni069E" }, { "uni069E.medi" } }, + { { "uni069F" }, { "uni069F.medi" } }, + { { "uni06A0" }, { "uni06A0.medi" } }, + { { "uni06A1" }, { "uni06A1.medi" } }, + { { "uni06A2" }, { "uni06A2.medi" } }, + { { "uni06A3" }, { "uni06A3.medi" } }, + { { "uni06A4" }, { "uni06A4.medi" } }, + { { "uni06A5" }, { "uni06A5.medi" } }, + { { "uni06A6" }, { "uni06A6.medi" } }, + { { "uni06A7" }, { "uni06A7.medi" } }, + { { "uni06A8" }, { "uni06A8.medi" } }, + { { "uni06A9" }, { "uni06A9.medi" } }, + { { "uni06AA" }, { "uni06AA.medi" } }, + { { "uni06AB" }, { "uni06AB.medi" } }, + { { "uni06AC" }, { "uni06AC.medi" } }, + { { "uni06AD" }, { "uni06AD.medi" } }, + { { "uni06AE" }, { "uni06AE.medi" } }, + { { "uni06AF" }, { "uni06AF.medi" } }, + { { "uni06B0" }, { "uni06B0.medi" } }, + { { "uni06B1" }, { "uni06B1.medi" } }, + { { "uni06B2" }, { "uni06B2.medi" } }, + { { "uni06B3" }, { "uni06B3.medi" } }, + { { "uni06B4" }, { "uni06B4.medi" } }, + { { "uni06B5" }, { "uni06B5.medi" } }, + { { "uni06B6" }, { "uni06B6.medi" } }, + { { "uni06B7" }, { "uni06B7.medi" } }, + { { "uni06B8" }, { "uni06B8.medi" } }, + { { "uni06B9" }, { "uni06B9.medi" } }, + { { "uni06BA" }, { "uni06BA.medi" } }, + { { "uni06BB" }, { "uni06BB.medi" } }, + { { "uni06BC" }, { "uni06BC.medi" } }, + { { "uni06BD" }, { "uni06BD.medi" } }, + { { "uni06BE" }, { "uni06BE.medi" } }, + { { "uni06BF" }, { "uni06BF.medi" } }, + { { "uni06C1" }, { "uni06C1.medi" } }, + { { "uni06C2" }, { "uni06C2.medi" } }, + { { "uni06CC" }, { "uni06CC.medi" } }, + { { "uni06CE" }, { "uni06CE.medi" } }, + { { "uni06D0" }, { "uni06D0.medi" } }, + { { "uni06D1" }, { "uni06D1.medi" } }, + { { "uni06FA" }, { "uni06FA.medi" } }, + { { "uni06FB" }, { "uni06FB.medi" } }, + { { "uni06FC" }, { "uni06FC.medi" } }, + { { "uni06FF" }, { "uni06FF.medi" } }, + { { "uni0750" }, { "uni0750.medi" } }, + { { "uni0751" }, { "uni0751.medi" } }, + { { "uni0752" }, { "uni0752.medi" } }, + { { "uni0753" }, { "uni0753.medi" } }, + { { "uni0754" }, { "uni0754.medi" } }, + { { "uni0755" }, { "uni0755.medi" } }, + { { "uni0756" }, { "uni0756.medi" } }, + { { "uni0757" }, { "uni0757.medi" } }, + { { "uni0758" }, { "uni0758.medi" } }, + { { "uni075C" }, { "uni075C.medi" } }, + { { "uni075D" }, { "uni075D.medi" } }, + { { "uni075E" }, { "uni075E.medi" } }, + { { "uni075F" }, { "uni075F.medi" } }, + { { "uni0760" }, { "uni0760.medi" } }, + { { "uni0761" }, { "uni0761.medi" } }, + { { "uni0762" }, { "uni0762.medi" } }, + { { "uni0763" }, { "uni0763.medi" } }, + { { "uni0764" }, { "uni0764.medi" } }, + { { "uni0765" }, { "uni0765.medi" } }, + { { "uni0766" }, { "uni0766.medi" } }, + { { "uni0767" }, { "uni0767.medi" } }, + { { "uni0768" }, { "uni0768.medi" } }, + { { "uni0769" }, { "uni0769.medi" } }, + { { "uni076A" }, { "uni076A.medi" } }, + { { "uni076D" }, { "uni076D.medi" } }, + } + }, + { "f2", "lu9", "arab", "SND ", "calt", + new String[][][] { + { { "uni060C" }, { "uni060C.downward" } }, + { { "uni061B" }, { "uni061B.downward" } }, + { { "uni0645" }, { "uni0645.sindhi" } }, + { { "uni0645.fina" }, { "uni0645.fina.sindhi" } }, + { { "uni0647" }, { "uni0647.knotted" } }, + { { "uni0647.fina" }, { "uni0647.fina.knottedHigh" } }, + { { "uni0647.medi" }, { "uni0647.medi.knottedHigh" } }, + { { "uni064C" }, { "uni064C.sixNine" } }, + { { "uni06F6" }, { "uni06F6.urdu" } }, + { { "uni06F7" }, { "uni06F7.urdu" } }, + } + }, + { "f2", "lu10", "arab", "URD ", "calt", + new String[][][] { + { { "uni0647.fina" }, { "uni0647.fina.hooked" } }, + { { "uni0647.init" }, { "uni0647.init.hooked" } }, + { { "uni0647.medi" }, { "uni0647.medi.hooked" } }, + { { "uni06F4" }, { "uni06F4.urdu" } }, + { { "uni06F6" }, { "uni06F6.urdu" } }, + { { "uni06F7" }, { "uni06F7.urdu" } }, + } + }, + { "f2", "lu11", "arab", "KUR ", "calt", + new String[][][] { + { { "uni0647" }, { "uni0647.knotted" } }, + { { "uni0647.fina" }, { "uni0647.fina.knottedHigh" } }, + } + }, + { "f2", "lu12", "latn", "dflt", "ccmp", + new String[][][] { + { { "asterisk.arab" }, { "asterisk" } }, + { { "colon.arab" }, { "colon" } }, + { { "exclam.arab" }, { "exclam" } }, + { { "parenleft.arab" }, { "parenleft" } }, + { { "parenright.arab" }, { "parenright" } }, + { { "quotedblleft.arab" }, { "quotedblleft" } }, + { { "quotedblright.arab" }, { "quotedblright" } }, + { { "quoteleft.arab" }, { "quoteleft" } }, + { { "quoteright.arab" }, { "quoteright" } }, + } + }, + { "f2", "lu14", "arab", "*", "*", + new String[][][] { + { { "absLamRetroIni" }, { "absLamRetroIni.preAlef" } }, + { { "absLamRetroMed" }, { "absLamRetroMed.preAlef" } }, + { { "uni0644.init" }, { "uni0644.init.preAlef" } }, + { { "uni0644.medi" }, { "uni0644.medi.preAlef" } }, + { { "uni06B5.init" }, { "uni06B5.init.preAlef" } }, + { { "uni06B5.medi" }, { "uni06B5.medi.preAlef" } }, + { { "uni06B6.init" }, { "uni06B6.init.preAlef" } }, + { { "uni06B6.medi" }, { "uni06B6.medi.preAlef" } }, + { { "uni06B7.init" }, { "uni06B7.init.preAlef" } }, + { { "uni06B7.medi" }, { "uni06B7.medi.preAlef" } }, + { { "uni06B8.init" }, { "uni06B8.init.preAlef" } }, + { { "uni06B8.medi" }, { "uni06B8.medi.preAlef" } }, + { { "uni076A.init" }, { "uni076A.init.preAlef" } }, + { { "uni076A.medi" }, { "uni076A.medi.preAlef" } }, + } + }, + { "f2", "lu15", "arab", "*", "*", + new String[][][] { + { { "uni0622.fina" }, { "uni0622.fina.postLamIni" } }, + { { "uni0623.fina" }, { "uni0623.fina.postLamIni" } }, + { { "uni0625.fina" }, { "uni0625.fina.postLamIni" } }, + { { "uni0627.fina" }, { "uni0627.fina.postLamIni" } }, + { { "uni0671.fina" }, { "uni0671.fina.postLamIni" } }, + { { "uni0672.fina" }, { "uni0672.fina.postLamIni" } }, + { { "uni0673.fina" }, { "uni0673.fina.postLamIni" } }, + { { "uni0675.fina" }, { "uni0675.fina.postLamIni" } }, + } + }, + { "f2", "lu16", "arab", "*", "*", + new String[][][] { + { { "uni0622.fina" }, { "uni0622.fina.postLamMed" } }, + { { "uni0623.fina" }, { "uni0623.fina.postLamMed" } }, + { { "uni0625.fina" }, { "uni0625.fina.postLamMed" } }, + { { "uni0627.fina" }, { "uni0627.fina.postLamMed" } }, + { { "uni0671.fina" }, { "uni0671.fina.postLamMed" } }, + { { "uni0672.fina" }, { "uni0672.fina.postLamMed" } }, + { { "uni0673.fina" }, { "uni0673.fina.postLamMed" } }, + { { "uni0675.fina" }, { "uni0675.fina.postLamMed" } }, + } + }, + { "f2", "lu17", "arab", "*", "*", + new String[][][] { + { { "uni0670" }, { "uni0670.large" } }, + } + }, + { "f2", "lu18", "arab", "*", "*", + new String[][][] { + { { "uni06DD" }, { "uni06DD.3" } }, + } + }, + { "f2", "lu19", "arab", "*", "*", + new String[][][] { + { { "uni06DD" }, { "uni06DD.2" } }, + } + }, + { "f2", "lu20", "arab", "*", "*", + new String[][][] { + { { "eight" }, { "eightMedium" } }, + { { "five" }, { "fiveMedium" } }, + { { "four" }, { "fourMedium" } }, + { { "nine" }, { "nineMedium" } }, + { { "one" }, { "oneMedium" } }, + { { "seven" }, { "sevenMedium" } }, + { { "six" }, { "sixMedium" } }, + { { "three" }, { "threeMedium" } }, + { { "two" }, { "twoMedium" } }, + { { "uni0660" }, { "uni0660.Medium" } }, + { { "uni0661" }, { "uni0661.Medium" } }, + { { "uni0662" }, { "uni0662.Medium" } }, + { { "uni0663" }, { "uni0663.Medium" } }, + { { "uni0664" }, { "uni0664.Medium" } }, + { { "uni0665" }, { "uni0665.Medium" } }, + { { "uni0666" }, { "uni0666.Medium" } }, + { { "uni0667" }, { "uni0667.Medium" } }, + { { "uni0668" }, { "uni0668.Medium" } }, + { { "uni0669" }, { "uni0669.Medium" } }, + { { "uni06F0" }, { "uni06F0.Medium" } }, + { { "uni06F1" }, { "uni06F1.Medium" } }, + { { "uni06F2" }, { "uni06F2.Medium" } }, + { { "uni06F3" }, { "uni06F3.Medium" } }, + { { "uni06F4" }, { "uni06F4.Medium" } }, + { { "uni06F4.urdu" }, { "uni06F4.Medium.urdu" } }, + { { "uni06F5" }, { "uni06F5.Medium" } }, + { { "uni06F6" }, { "uni06F6.Medium" } }, + { { "uni06F6.urdu" }, { "uni06F6.Medium.urdu" } }, + { { "uni06F7" }, { "uni06F7.Medium" } }, + { { "uni06F7.urdu" }, { "uni06F7.Medium.urdu" } }, + { { "uni06F8" }, { "uni06F8.Medium" } }, + { { "uni06F9" }, { "uni06F9.Medium" } }, + { { "zero" }, { "zeroMedium" } }, + } + }, + { "f2", "lu21", "arab", "*", "*", + new String[][][] { + { { "eight" }, { "eightSmall" } }, + { { "five" }, { "fiveSmall" } }, + { { "four" }, { "fourSmall" } }, + { { "nine" }, { "nineSmall" } }, + { { "one" }, { "oneSmall" } }, + { { "seven" }, { "sevenSmall" } }, + { { "six" }, { "sixSmall" } }, + { { "three" }, { "threeSmall" } }, + { { "two" }, { "twoSmall" } }, + { { "uni0660" }, { "uni0660.Small" } }, + { { "uni0661" }, { "uni0661.Small" } }, + { { "uni0662" }, { "uni0662.Small" } }, + { { "uni0663" }, { "uni0663.Small" } }, + { { "uni0664" }, { "uni0664.Small" } }, + { { "uni0665" }, { "uni0665.Small" } }, + { { "uni0666" }, { "uni0666.Small" } }, + { { "uni0667" }, { "uni0667.Small" } }, + { { "uni0668" }, { "uni0668.Small" } }, + { { "uni0669" }, { "uni0669.Small" } }, + { { "uni06F0" }, { "uni06F0.Small" } }, + { { "uni06F1" }, { "uni06F1.Small" } }, + { { "uni06F2" }, { "uni06F2.Small" } }, + { { "uni06F3" }, { "uni06F3.Small" } }, + { { "uni06F4" }, { "uni06F4.Small" } }, + { { "uni06F4.urdu" }, { "uni06F4.Small.urdu" } }, + { { "uni06F5" }, { "uni06F5.Small" } }, + { { "uni06F6" }, { "uni06F6.Small" } }, + { { "uni06F6.urdu" }, { "uni06F6.Small.urdu" } }, + { { "uni06F7" }, { "uni06F7.Small" } }, + { { "uni06F7.urdu" }, { "uni06F7.Small.urdu" } }, + { { "uni06F8" }, { "uni06F8.Small" } }, + { { "uni06F9" }, { "uni06F9.Small" } }, + { { "zero" }, { "zeroSmall" } }, + } + }, + // arab-004.ttx + { "f3", "lu1", "arab", "dflt", "init", + new String[][][] { + { { "absJeemRetro1" }, { "absJeemRetro1Ini" } }, + { { "absJeemRetro2" }, { "absJeemRetro2Ini" } }, + { { "absJeemRetro3" }, { "absJeemRetro3Ini" } }, + { { "absLamRetro" }, { "absLamRetroIni" } }, + { { "absSheenRetro1" }, { "absSheenRetro1Ini" } }, + { { "absSheenRetro2" }, { "absSheenRetro2Ini" } }, + { { "absTchehRetro1" }, { "absTchehRetro1Ini" } }, + { { "absTchehRetro2" }, { "absTchehRetro2Ini" } }, + { { "uni0626" }, { "uni0626.init" } }, + { { "uni0628" }, { "uni0628.init" } }, + { { "uni062A" }, { "uni062A.init" } }, + { { "uni062B" }, { "uni062B.init" } }, + { { "uni062C" }, { "uni062C.init" } }, + { { "uni062D" }, { "uni062D.init" } }, + { { "uni062E" }, { "uni062E.init" } }, + { { "uni0633" }, { "uni0633.init" } }, + { { "uni0634" }, { "uni0634.init" } }, + { { "uni0635" }, { "uni0635.init" } }, + { { "uni0636" }, { "uni0636.init" } }, + { { "uni0637" }, { "uni0637.init" } }, + { { "uni0638" }, { "uni0638.init" } }, + { { "uni0639" }, { "uni0639.init" } }, + { { "uni063A" }, { "uni063A.init" } }, + { { "uni0641" }, { "uni0641.init" } }, + { { "uni0642" }, { "uni0642.init" } }, + { { "uni0643" }, { "uni0643.init" } }, + { { "uni0644" }, { "uni0644.init" } }, + { { "uni0645" }, { "uni0645.init" } }, + { { "uni0646" }, { "uni0646.init" } }, + { { "uni0647" }, { "uni0647.init" } }, + { { "uni0649" }, { "uni0649.init" } }, + { { "uni064A" }, { "uni064A.init" } }, + { { "uni064A.noDots" }, { "uni064A.init.noDots" } }, + { { "uni066E" }, { "uni066E.init" } }, + { { "uni066F" }, { "uni066F.init" } }, + { { "uni0678" }, { "uni0678.init" } }, + { { "uni0679" }, { "uni0679.init" } }, + { { "uni067A" }, { "uni067A.init" } }, + { { "uni067B" }, { "uni067B.init" } }, + { { "uni067C" }, { "uni067C.init" } }, + { { "uni067D" }, { "uni067D.init" } }, + { { "uni067E" }, { "uni067E.init" } }, + { { "uni067F" }, { "uni067F.init" } }, + { { "uni0680" }, { "uni0680.init" } }, + { { "uni0681" }, { "uni0681.init" } }, + { { "uni0682" }, { "uni0682.init" } }, + { { "uni0683" }, { "uni0683.init" } }, + { { "uni0684" }, { "uni0684.init" } }, + { { "uni0685" }, { "uni0685.init" } }, + { { "uni0686" }, { "uni0686.init" } }, + { { "uni0687" }, { "uni0687.init" } }, + { { "uni069A" }, { "uni069A.init" } }, + { { "uni069B" }, { "uni069B.init" } }, + { { "uni069C" }, { "uni069C.init" } }, + { { "uni069D" }, { "uni069D.init" } }, + { { "uni069E" }, { "uni069E.init" } }, + { { "uni069F" }, { "uni069F.init" } }, + { { "uni06A0" }, { "uni06A0.init" } }, + { { "uni06A1" }, { "uni06A1.init" } }, + { { "uni06A2" }, { "uni06A2.init" } }, + { { "uni06A3" }, { "uni06A3.init" } }, + { { "uni06A4" }, { "uni06A4.init" } }, + { { "uni06A5" }, { "uni06A5.init" } }, + { { "uni06A6" }, { "uni06A6.init" } }, + { { "uni06A7" }, { "uni06A7.init" } }, + { { "uni06A8" }, { "uni06A8.init" } }, + { { "uni06A9" }, { "uni06A9.init" } }, + { { "uni06AA" }, { "uni06AA.init" } }, + { { "uni06AB" }, { "uni06AB.init" } }, + { { "uni06AC" }, { "uni06AC.init" } }, + { { "uni06AD" }, { "uni06AD.init" } }, + { { "uni06AE" }, { "uni06AE.init" } }, + { { "uni06AF" }, { "uni06AF.init" } }, + { { "uni06B0" }, { "uni06B0.init" } }, + { { "uni06B1" }, { "uni06B1.init" } }, + { { "uni06B2" }, { "uni06B2.init" } }, + { { "uni06B3" }, { "uni06B3.init" } }, + { { "uni06B4" }, { "uni06B4.init" } }, + { { "uni06B5" }, { "uni06B5.init" } }, + { { "uni06B6" }, { "uni06B6.init" } }, + { { "uni06B7" }, { "uni06B7.init" } }, + { { "uni06B8" }, { "uni06B8.init" } }, + { { "uni06B9" }, { "uni06B9.init" } }, + { { "uni06BA" }, { "uni06BA.init" } }, + { { "uni06BB" }, { "uni06BB.init" } }, + { { "uni06BC" }, { "uni06BC.init" } }, + { { "uni06BD" }, { "uni06BD.init" } }, + { { "uni06BE" }, { "uni06BE.init" } }, + { { "uni06BF" }, { "uni06BF.init" } }, + { { "uni06C1" }, { "uni06C1.init" } }, + { { "uni06CC" }, { "uni06CC.init" } }, + { { "uni06CE" }, { "uni06CE.init" } }, + { { "uni06D0" }, { "uni06D0.init" } }, + { { "uni06D1" }, { "uni06D1.init" } }, + { { "uni06FA" }, { "uni06FA.init" } }, + { { "uni06FB" }, { "uni06FB.init" } }, + { { "uni06FC" }, { "uni06FC.init" } }, + { { "uni06FF" }, { "uni06FF.init" } }, + { { "uni0750" }, { "uni0750.init" } }, + { { "uni0751" }, { "uni0751.init" } }, + { { "uni0752" }, { "uni0752.init" } }, + { { "uni0753" }, { "uni0753.init" } }, + { { "uni0754" }, { "uni0754.init" } }, + { { "uni0755" }, { "uni0755.init" } }, + { { "uni0756" }, { "uni0756.init" } }, + { { "uni0757" }, { "uni0757.init" } }, + { { "uni0758" }, { "uni0758.init" } }, + { { "uni075C" }, { "uni075C.init" } }, + { { "uni075D" }, { "uni075D.init" } }, + { { "uni075E" }, { "uni075E.init" } }, + { { "uni075F" }, { "uni075F.init" } }, + { { "uni0760" }, { "uni0760.init" } }, + { { "uni0761" }, { "uni0761.init" } }, + { { "uni0762" }, { "uni0762.init" } }, + { { "uni0763" }, { "uni0763.init" } }, + { { "uni0764" }, { "uni0764.init" } }, + { { "uni0765" }, { "uni0765.init" } }, + { { "uni0766" }, { "uni0766.init" } }, + { { "uni0767" }, { "uni0767.init" } }, + { { "uni0768" }, { "uni0768.init" } }, + { { "uni0769" }, { "uni0769.init" } }, + { { "uni076A" }, { "uni076A.init" } }, + { { "uni076D" }, { "uni076D.init" } }, + } + }, + { "f3", "lu2", "arab", "dflt", "fina", + new String[][][] { + { { "absJeemRetro1" }, { "absJeemRetro1Fin" } }, + { { "absJeemRetro2" }, { "absJeemRetro2Fin" } }, + { { "absJeemRetro3" }, { "absJeemRetro3Fin" } }, + { { "absJehRetro1" }, { "absJehRetro1Fin" } }, + { { "absJehRetro2" }, { "absJehRetro2Fin" } }, + { { "absLamRetro" }, { "absLamRetroFin" } }, + { { "absSheenRetro1" }, { "absSheenRetro1Fin" } }, + { { "absSheenRetro2" }, { "absSheenRetro2Fin" } }, + { { "absTchehRetro1" }, { "absTchehRetro1Fin" } }, + { { "absTchehRetro2" }, { "absTchehRetro2Fin" } }, + { { "absWawDotBelow" }, { "absWawDotBelowFin" } }, + { { "uni0622" }, { "uni0622.fina" } }, + { { "uni0623" }, { "uni0623.fina" } }, + { { "uni0624" }, { "uni0624.fina" } }, + { { "uni0625" }, { "uni0625.fina" } }, + { { "uni0626" }, { "uni0626.fina" } }, + { { "uni0627" }, { "uni0627.fina" } }, + { { "uni0628" }, { "uni0628.fina" } }, + { { "uni0629" }, { "uni0629.fina" } }, + { { "uni062A" }, { "uni062A.fina" } }, + { { "uni062B" }, { "uni062B.fina" } }, + { { "uni062C" }, { "uni062C.fina" } }, + { { "uni062D" }, { "uni062D.fina" } }, + { { "uni062E" }, { "uni062E.fina" } }, + { { "uni062F" }, { "uni062F.fina" } }, + { { "uni0630" }, { "uni0630.fina" } }, + { { "uni0631" }, { "uni0631.fina" } }, + { { "uni0632" }, { "uni0632.fina" } }, + { { "uni0633" }, { "uni0633.fina" } }, + { { "uni0634" }, { "uni0634.fina" } }, + { { "uni0635" }, { "uni0635.fina" } }, + { { "uni0636" }, { "uni0636.fina" } }, + { { "uni0637" }, { "uni0637.fina" } }, + { { "uni0638" }, { "uni0638.fina" } }, + { { "uni0639" }, { "uni0639.fina" } }, + { { "uni063A" }, { "uni063A.fina" } }, + { { "uni0641" }, { "uni0641.fina" } }, + { { "uni0642" }, { "uni0642.fina" } }, + { { "uni0643" }, { "uni0643.fina" } }, + { { "uni0644" }, { "uni0644.fina" } }, + { { "uni0645" }, { "uni0645.fina" } }, + { { "uni0646" }, { "uni0646.fina" } }, + { { "uni0647" }, { "uni0647.fina" } }, + { { "uni0648" }, { "uni0648.fina" } }, + { { "uni0649" }, { "uni0649.fina" } }, + { { "uni064A" }, { "uni064A.fina" } }, + { { "uni064A.noDots" }, { "uni064A.fina.noDots" } }, + { { "uni066E" }, { "uni066E.fina" } }, + { { "uni066F" }, { "uni066F.fina" } }, + { { "uni0671" }, { "uni0671.fina" } }, + { { "uni0672" }, { "uni0672.fina" } }, + { { "uni0673" }, { "uni0673.fina" } }, + { { "uni0675" }, { "uni0675.fina" } }, + { { "uni0676" }, { "uni0676.fina" } }, + { { "uni0677" }, { "uni0677.fina" } }, + { { "uni0678" }, { "uni0678.fina" } }, + { { "uni0679" }, { "uni0679.fina" } }, + { { "uni067A" }, { "uni067A.fina" } }, + { { "uni067B" }, { "uni067B.fina" } }, + { { "uni067C" }, { "uni067C.fina" } }, + { { "uni067D" }, { "uni067D.fina" } }, + { { "uni067E" }, { "uni067E.fina" } }, + { { "uni067F" }, { "uni067F.fina" } }, + { { "uni0680" }, { "uni0680.fina" } }, + { { "uni0681" }, { "uni0681.fina" } }, + { { "uni0682" }, { "uni0682.fina" } }, + { { "uni0683" }, { "uni0683.fina" } }, + { { "uni0684" }, { "uni0684.fina" } }, + { { "uni0685" }, { "uni0685.fina" } }, + { { "uni0686" }, { "uni0686.fina" } }, + { { "uni0687" }, { "uni0687.fina" } }, + { { "uni0688" }, { "uni0688.fina" } }, + { { "uni0689" }, { "uni0689.fina" } }, + { { "uni068A" }, { "uni068A.fina" } }, + { { "uni068B" }, { "uni068B.fina" } }, + { { "uni068C" }, { "uni068C.fina" } }, + { { "uni068D" }, { "uni068D.fina" } }, + { { "uni068E" }, { "uni068E.fina" } }, + { { "uni068F" }, { "uni068F.fina" } }, + { { "uni0690" }, { "uni0690.fina" } }, + { { "uni0691" }, { "uni0691.fina" } }, + { { "uni0692" }, { "uni0692.fina" } }, + { { "uni0693" }, { "uni0693.fina" } }, + { { "uni0694" }, { "uni0694.fina" } }, + { { "uni0695" }, { "uni0695.fina" } }, + { { "uni0696" }, { "uni0696.fina" } }, + { { "uni0697" }, { "uni0697.fina" } }, + { { "uni0698" }, { "uni0698.fina" } }, + { { "uni0698.dotHat" }, { "uni0698.fina.dotHat" } }, + { { "uni0699" }, { "uni0699.fina" } }, + { { "uni069A" }, { "uni069A.fina" } }, + { { "uni069B" }, { "uni069B.fina" } }, + { { "uni069C" }, { "uni069C.fina" } }, + { { "uni069D" }, { "uni069D.fina" } }, + { { "uni069E" }, { "uni069E.fina" } }, + { { "uni069F" }, { "uni069F.fina" } }, + { { "uni06A0" }, { "uni06A0.fina" } }, + { { "uni06A1" }, { "uni06A1.fina" } }, + { { "uni06A2" }, { "uni06A2.fina" } }, + { { "uni06A3" }, { "uni06A3.fina" } }, + { { "uni06A4" }, { "uni06A4.fina" } }, + { { "uni06A5" }, { "uni06A5.fina" } }, + { { "uni06A6" }, { "uni06A6.fina" } }, + { { "uni06A7" }, { "uni06A7.fina" } }, + { { "uni06A8" }, { "uni06A8.fina" } }, + { { "uni06A9" }, { "uni06A9.fina" } }, + { { "uni06AA" }, { "uni06AA.fina" } }, + { { "uni06AB" }, { "uni06AB.fina" } }, + { { "uni06AC" }, { "uni06AC.fina" } }, + { { "uni06AD" }, { "uni06AD.fina" } }, + { { "uni06AE" }, { "uni06AE.fina" } }, + { { "uni06AF" }, { "uni06AF.fina" } }, + { { "uni06B0" }, { "uni06B0.fina" } }, + { { "uni06B1" }, { "uni06B1.fina" } }, + { { "uni06B2" }, { "uni06B2.fina" } }, + { { "uni06B3" }, { "uni06B3.fina" } }, + { { "uni06B4" }, { "uni06B4.fina" } }, + { { "uni06B5" }, { "uni06B5.fina" } }, + { { "uni06B6" }, { "uni06B6.fina" } }, + { { "uni06B7" }, { "uni06B7.fina" } }, + { { "uni06B8" }, { "uni06B8.fina" } }, + { { "uni06B9" }, { "uni06B9.fina" } }, + { { "uni06BA" }, { "uni06BA.fina" } }, + { { "uni06BB" }, { "uni06BB.fina" } }, + { { "uni06BC" }, { "uni06BC.fina" } }, + { { "uni06BD" }, { "uni06BD.fina" } }, + { { "uni06BE" }, { "uni06BE.fina" } }, + { { "uni06BF" }, { "uni06BF.fina" } }, + { { "uni06C0" }, { "uni06C0.fina" } }, + { { "uni06C1" }, { "uni06C1.fina" } }, + { { "uni06C2" }, { "uni06C2.fina" } }, + { { "uni06C3" }, { "uni06C3.fina" } }, + { { "uni06C4" }, { "uni06C4.fina" } }, + { { "uni06C5" }, { "uni06C5.fina" } }, + { { "uni06C6" }, { "uni06C6.fina" } }, + { { "uni06C7" }, { "uni06C7.fina" } }, + { { "uni06C8" }, { "uni06C8.fina" } }, + { { "uni06C9" }, { "uni06C9.fina" } }, + { { "uni06CA" }, { "uni06CA.fina" } }, + { { "uni06CB" }, { "uni06CB.fina" } }, + { { "uni06CC" }, { "uni06CC.fina" } }, + { { "uni06CD" }, { "uni06CD.fina" } }, + { { "uni06CE" }, { "uni06CE.fina" } }, + { { "uni06CF" }, { "uni06CF.fina" } }, + { { "uni06D0" }, { "uni06D0.fina" } }, + { { "uni06D1" }, { "uni06D1.fina" } }, + { { "uni06D2" }, { "uni06D2.fina" } }, + { { "uni06D3" }, { "uni06D3.fina" } }, + { { "uni06D5" }, { "uni06D5.fina" } }, + { { "uni06EE" }, { "uni06EE.fina" } }, + { { "uni06EF" }, { "uni06EF.fina" } }, + { { "uni06FA" }, { "uni06FA.fina" } }, + { { "uni06FB" }, { "uni06FB.fina" } }, + { { "uni06FC" }, { "uni06FC.fina" } }, + { { "uni06FF" }, { "uni06FF.fina" } }, + { { "uni0750" }, { "uni0750.fina" } }, + { { "uni0751" }, { "uni0751.fina" } }, + { { "uni0752" }, { "uni0752.fina" } }, + { { "uni0753" }, { "uni0753.fina" } }, + { { "uni0754" }, { "uni0754.fina" } }, + { { "uni0755" }, { "uni0755.fina" } }, + { { "uni0756" }, { "uni0756.fina" } }, + { { "uni0757" }, { "uni0757.fina" } }, + { { "uni0758" }, { "uni0758.fina" } }, + { { "uni0759" }, { "uni0759.fina" } }, + { { "uni075A" }, { "uni075A.fina" } }, + { { "uni075B" }, { "uni075B.fina" } }, + { { "uni075C" }, { "uni075C.fina" } }, + { { "uni075D" }, { "uni075D.fina" } }, + { { "uni075E" }, { "uni075E.fina" } }, + { { "uni075F" }, { "uni075F.fina" } }, + { { "uni0760" }, { "uni0760.fina" } }, + { { "uni0761" }, { "uni0761.fina" } }, + { { "uni0762" }, { "uni0762.fina" } }, + { { "uni0763" }, { "uni0763.fina" } }, + { { "uni0764" }, { "uni0764.fina" } }, + { { "uni0765" }, { "uni0765.fina" } }, + { { "uni0766" }, { "uni0766.fina" } }, + { { "uni0767" }, { "uni0767.fina" } }, + { { "uni0768" }, { "uni0768.fina" } }, + { { "uni0769" }, { "uni0769.fina" } }, + { { "uni076A" }, { "uni076A.fina" } }, + { { "uni076B" }, { "uni076B.fina" } }, + { { "uni076C" }, { "uni076C.fina" } }, + { { "uni076D" }, { "uni076D.fina" } }, + } + }, + { "f3", "lu3", "arab", "dflt", "medi", + new String[][][] { + { { "absJeemRetro1" }, { "absJeemRetro1Med" } }, + { { "absJeemRetro2" }, { "absJeemRetro2Med" } }, + { { "absJeemRetro3" }, { "absJeemRetro3Med" } }, + { { "absLamRetro" }, { "absLamRetroMed" } }, + { { "absSheenRetro1" }, { "absSheenRetro1Med" } }, + { { "absSheenRetro2" }, { "absSheenRetro2Med" } }, + { { "absTchehRetro1" }, { "absTchehRetro1Med" } }, + { { "absTchehRetro2" }, { "absTchehRetro2Med" } }, + { { "uni0626" }, { "uni0626.medi" } }, + { { "uni0628" }, { "uni0628.medi" } }, + { { "uni062A" }, { "uni062A.medi" } }, + { { "uni062B" }, { "uni062B.medi" } }, + { { "uni062C" }, { "uni062C.medi" } }, + { { "uni062D" }, { "uni062D.medi" } }, + { { "uni062E" }, { "uni062E.medi" } }, + { { "uni0633" }, { "uni0633.medi" } }, + { { "uni0634" }, { "uni0634.medi" } }, + { { "uni0635" }, { "uni0635.medi" } }, + { { "uni0636" }, { "uni0636.medi" } }, + { { "uni0637" }, { "uni0637.medi" } }, + { { "uni0638" }, { "uni0638.medi" } }, + { { "uni0639" }, { "uni0639.medi" } }, + { { "uni063A" }, { "uni063A.medi" } }, + { { "uni0641" }, { "uni0641.medi" } }, + { { "uni0642" }, { "uni0642.medi" } }, + { { "uni0643" }, { "uni0643.medi" } }, + { { "uni0644" }, { "uni0644.medi" } }, + { { "uni0645" }, { "uni0645.medi" } }, + { { "uni0646" }, { "uni0646.medi" } }, + { { "uni0647" }, { "uni0647.medi" } }, + { { "uni0649" }, { "uni0649.medi" } }, + { { "uni064A" }, { "uni064A.medi" } }, + { { "uni064A.noDots" }, { "uni064A.medi.noDots" } }, + { { "uni066E" }, { "uni066E.medi" } }, + { { "uni066F" }, { "uni066F.medi" } }, + { { "uni0678" }, { "uni0678.medi" } }, + { { "uni0679" }, { "uni0679.medi" } }, + { { "uni067A" }, { "uni067A.medi" } }, + { { "uni067B" }, { "uni067B.medi" } }, + { { "uni067C" }, { "uni067C.medi" } }, + { { "uni067D" }, { "uni067D.medi" } }, + { { "uni067E" }, { "uni067E.medi" } }, + { { "uni067F" }, { "uni067F.medi" } }, + { { "uni0680" }, { "uni0680.medi" } }, + { { "uni0681" }, { "uni0681.medi" } }, + { { "uni0682" }, { "uni0682.medi" } }, + { { "uni0683" }, { "uni0683.medi" } }, + { { "uni0684" }, { "uni0684.medi" } }, + { { "uni0685" }, { "uni0685.medi" } }, + { { "uni0686" }, { "uni0686.medi" } }, + { { "uni0687" }, { "uni0687.medi" } }, + { { "uni069A" }, { "uni069A.medi" } }, + { { "uni069B" }, { "uni069B.medi" } }, + { { "uni069C" }, { "uni069C.medi" } }, + { { "uni069D" }, { "uni069D.medi" } }, + { { "uni069E" }, { "uni069E.medi" } }, + { { "uni069F" }, { "uni069F.medi" } }, + { { "uni06A0" }, { "uni06A0.medi" } }, + { { "uni06A1" }, { "uni06A1.medi" } }, + { { "uni06A2" }, { "uni06A2.medi" } }, + { { "uni06A3" }, { "uni06A3.medi" } }, + { { "uni06A4" }, { "uni06A4.medi" } }, + { { "uni06A5" }, { "uni06A5.medi" } }, + { { "uni06A6" }, { "uni06A6.medi" } }, + { { "uni06A7" }, { "uni06A7.medi" } }, + { { "uni06A8" }, { "uni06A8.medi" } }, + { { "uni06A9" }, { "uni06A9.medi" } }, + { { "uni06AA" }, { "uni06AA.medi" } }, + { { "uni06AB" }, { "uni06AB.medi" } }, + { { "uni06AC" }, { "uni06AC.medi" } }, + { { "uni06AD" }, { "uni06AD.medi" } }, + { { "uni06AE" }, { "uni06AE.medi" } }, + { { "uni06AF" }, { "uni06AF.medi" } }, + { { "uni06B0" }, { "uni06B0.medi" } }, + { { "uni06B1" }, { "uni06B1.medi" } }, + { { "uni06B2" }, { "uni06B2.medi" } }, + { { "uni06B3" }, { "uni06B3.medi" } }, + { { "uni06B4" }, { "uni06B4.medi" } }, + { { "uni06B5" }, { "uni06B5.medi" } }, + { { "uni06B6" }, { "uni06B6.medi" } }, + { { "uni06B7" }, { "uni06B7.medi" } }, + { { "uni06B8" }, { "uni06B8.medi" } }, + { { "uni06B9" }, { "uni06B9.medi" } }, + { { "uni06BA" }, { "uni06BA.medi" } }, + { { "uni06BB" }, { "uni06BB.medi" } }, + { { "uni06BC" }, { "uni06BC.medi" } }, + { { "uni06BD" }, { "uni06BD.medi" } }, + { { "uni06BE" }, { "uni06BE.medi" } }, + { { "uni06BF" }, { "uni06BF.medi" } }, + { { "uni06C1" }, { "uni06C1.medi" } }, + { { "uni06CC" }, { "uni06CC.medi" } }, + { { "uni06CE" }, { "uni06CE.medi" } }, + { { "uni06D0" }, { "uni06D0.medi" } }, + { { "uni06D1" }, { "uni06D1.medi" } }, + { { "uni06FA" }, { "uni06FA.medi" } }, + { { "uni06FB" }, { "uni06FB.medi" } }, + { { "uni06FC" }, { "uni06FC.medi" } }, + { { "uni06FF" }, { "uni06FF.medi" } }, + { { "uni0750" }, { "uni0750.medi" } }, + { { "uni0751" }, { "uni0751.medi" } }, + { { "uni0752" }, { "uni0752.medi" } }, + { { "uni0753" }, { "uni0753.medi" } }, + { { "uni0754" }, { "uni0754.medi" } }, + { { "uni0755" }, { "uni0755.medi" } }, + { { "uni0756" }, { "uni0756.medi" } }, + { { "uni0757" }, { "uni0757.medi" } }, + { { "uni0758" }, { "uni0758.medi" } }, + { { "uni075C" }, { "uni075C.medi" } }, + { { "uni075D" }, { "uni075D.medi" } }, + { { "uni075E" }, { "uni075E.medi" } }, + { { "uni075F" }, { "uni075F.medi" } }, + { { "uni0760" }, { "uni0760.medi" } }, + { { "uni0761" }, { "uni0761.medi" } }, + { { "uni0762" }, { "uni0762.medi" } }, + { { "uni0763" }, { "uni0763.medi" } }, + { { "uni0764" }, { "uni0764.medi" } }, + { { "uni0765" }, { "uni0765.medi" } }, + { { "uni0766" }, { "uni0766.medi" } }, + { { "uni0767" }, { "uni0767.medi" } }, + { { "uni0768" }, { "uni0768.medi" } }, + { { "uni0769" }, { "uni0769.medi" } }, + { { "uni076A" }, { "uni076A.medi" } }, + { { "uni076D" }, { "uni076D.medi" } }, + } + }, + { "f3", "lu11", "arab", "SND ", "calt", + new String[][][] { + { { "uni0645" }, { "uni0645.sindhi" } }, + { { "uni0645.fina" }, { "uni0645.fina.sindhi" } }, + { { "uni0647" }, { "uni0647.knotted" } }, + { { "uni0647.fina" }, { "uni0647.fina.knottedHigh" } }, + { { "uni0647.medi" }, { "uni0647.medi.knottedHigh" } }, + { { "uni06F6" }, { "uni06F6.urdu" } }, + { { "uni06F7" }, { "uni06F7.urdu" } }, + } + }, + { "f3", "lu12", "arab", "KUR ", "calt", + new String[][][] { + { { "uni0647" }, { "uni0647.knotted" } }, + { { "uni0647.fina" }, { "uni0647.fina.knottedHigh" } }, + } + }, + { "f3", "lu13", "arab", "URD ", "calt", + new String[][][] { + { { "uni0647.fina" }, { "uni0647.fina.hooked" } }, + { { "uni0647.init" }, { "uni0647.init.hooked" } }, + { { "uni0647.medi" }, { "uni0647.medi.hooked" } }, + { { "uni06F4" }, { "uni06F4.urdu" } }, + { { "uni06F6" }, { "uni06F6.urdu" } }, + { { "uni06F7" }, { "uni06F7.urdu" } }, + } + }, + { "f3", "lu15", "arab", "*", "*", + new String[][][] { + { { "absLamRetroIni" }, { "absLamRetroIni.preAlef" } }, + { { "absLamRetroMed" }, { "absLamRetroMed.preAlef" } }, + { { "uni0644.init" }, { "uni0644.init.preAlef" } }, + { { "uni0644.medi" }, { "uni0644.medi.preAlef" } }, + { { "uni06B5.init" }, { "uni06B5.init.preAlef" } }, + { { "uni06B5.medi" }, { "uni06B5.medi.preAlef" } }, + { { "uni06B6.init" }, { "uni06B6.init.preAlef" } }, + { { "uni06B6.medi" }, { "uni06B6.medi.preAlef" } }, + { { "uni06B7.init" }, { "uni06B7.init.preAlef" } }, + { { "uni06B7.medi" }, { "uni06B7.medi.preAlef" } }, + { { "uni06B8.init" }, { "uni06B8.init.preAlef" } }, + { { "uni06B8.medi" }, { "uni06B8.medi.preAlef" } }, + { { "uni076A.init" }, { "uni076A.init.preAlef" } }, + { { "uni076A.medi" }, { "uni076A.medi.preAlef" } }, + } + }, + { "f3", "lu16", "arab", "*", "*", + new String[][][] { + { { "uni0622.fina" }, { "uni0622.fina.postLamIni" } }, + { { "uni0623.fina" }, { "uni0623.fina.postLamIni" } }, + { { "uni0625.fina" }, { "uni0625.fina.postLamIni" } }, + { { "uni0627.fina" }, { "uni0627.fina.postLamIni" } }, + { { "uni0671.fina" }, { "uni0671.fina.postLamIni" } }, + { { "uni0672.fina" }, { "uni0672.fina.postLamIni" } }, + { { "uni0673.fina" }, { "uni0673.fina.postLamIni" } }, + { { "uni0675.fina" }, { "uni0675.fina.postLamIni" } }, + } + }, + { "f3", "lu17", "arab", "*", "*", + new String[][][] { + { { "uni0622.fina" }, { "uni0622.fina.postLamMed" } }, + { { "uni0623.fina" }, { "uni0623.fina.postLamMed" } }, + { { "uni0625.fina" }, { "uni0625.fina.postLamMed" } }, + { { "uni0627.fina" }, { "uni0627.fina.postLamMed" } }, + { { "uni0671.fina" }, { "uni0671.fina.postLamMed" } }, + { { "uni0672.fina" }, { "uni0672.fina.postLamMed" } }, + { { "uni0673.fina" }, { "uni0673.fina.postLamMed" } }, + { { "uni0675.fina" }, { "uni0675.fina.postLamMed" } }, + } + }, + { "f3", "lu18", "arab", "*", "*", + new String[][][] { + { { "uni0601" }, { "uni0601.4" } }, + } + }, + { "f3", "lu19", "arab", "*", "*", + new String[][][] { + { { "uni0600" }, { "uni0600.3" } }, + { { "uni0601" }, { "uni0601.3" } }, + { { "uni0603" }, { "uni0603.3" } }, + { { "uni06DD" }, { "uni06DD.3" } }, + { { "uni06DD.alt" }, { "uni06DD.alt.3" } }, + { { "uni06DD.altB" }, { "uni06DD.altB.3" } }, + } + }, + { "f3", "lu20", "arab", "*", "*", + new String[][][] { + { { "uni0600" }, { "uni0600.2" } }, + { { "uni0601" }, { "uni0601.2" } }, + { { "uni0602" }, { "uni0602.2" } }, + { { "uni0603" }, { "uni0603.2" } }, + { { "uni06DD" }, { "uni06DD.2" } }, + { { "uni06DD.alt" }, { "uni06DD.alt.2" } }, + { { "uni06DD.altB" }, { "uni06DD.altB.2" } }, + } + }, + { "f3", "lu21", "arab", "*", "*", + new String[][][] { + { { "eight" }, { "eightMedium" } }, + { { "five" }, { "fiveMedium" } }, + { { "four" }, { "fourMedium" } }, + { { "nine" }, { "nineMedium" } }, + { { "one" }, { "oneMedium" } }, + { { "seven" }, { "sevenMedium" } }, + { { "six" }, { "sixMedium" } }, + { { "three" }, { "threeMedium" } }, + { { "two" }, { "twoMedium" } }, + { { "uni0660" }, { "uni0660.Medium" } }, + { { "uni0661" }, { "uni0661.Medium" } }, + { { "uni0662" }, { "uni0662.Medium" } }, + { { "uni0663" }, { "uni0663.Medium" } }, + { { "uni0664" }, { "uni0664.Medium" } }, + { { "uni0665" }, { "uni0665.Medium" } }, + { { "uni0666" }, { "uni0666.Medium" } }, + { { "uni0667" }, { "uni0667.Medium" } }, + { { "uni0668" }, { "uni0668.Medium" } }, + { { "uni0669" }, { "uni0669.Medium" } }, + { { "uni06F0" }, { "uni06F0.Medium" } }, + { { "uni06F1" }, { "uni06F1.Medium" } }, + { { "uni06F2" }, { "uni06F2.Medium" } }, + { { "uni06F3" }, { "uni06F3.Medium" } }, + { { "uni06F4" }, { "uni06F4.Medium" } }, + { { "uni06F4.urdu" }, { "uni06F4.Medium.urdu" } }, + { { "uni06F5" }, { "uni06F5.Medium" } }, + { { "uni06F6" }, { "uni06F6.Medium" } }, + { { "uni06F6.urdu" }, { "uni06F6.Medium.urdu" } }, + { { "uni06F7" }, { "uni06F7.Medium" } }, + { { "uni06F7.urdu" }, { "uni06F7.Medium.urdu" } }, + { { "uni06F8" }, { "uni06F8.Medium" } }, + { { "uni06F9" }, { "uni06F9.Medium" } }, + { { "zero" }, { "zeroMedium" } }, + } + }, + { "f3", "lu22", "arab", "*", "*", + new String[][][] { + { { "eight" }, { "eightSmall" } }, + { { "five" }, { "fiveSmall" } }, + { { "four" }, { "fourSmall" } }, + { { "nine" }, { "nineSmall" } }, + { { "one" }, { "oneSmall" } }, + { { "seven" }, { "sevenSmall" } }, + { { "six" }, { "sixSmall" } }, + { { "three" }, { "threeSmall" } }, + { { "two" }, { "twoSmall" } }, + { { "uni0660" }, { "uni0660.Small" } }, + { { "uni0661" }, { "uni0661.Small" } }, + { { "uni0662" }, { "uni0662.Small" } }, + { { "uni0663" }, { "uni0663.Small" } }, + { { "uni0664" }, { "uni0664.Small" } }, + { { "uni0665" }, { "uni0665.Small" } }, + { { "uni0666" }, { "uni0666.Small" } }, + { { "uni0667" }, { "uni0667.Small" } }, + { { "uni0668" }, { "uni0668.Small" } }, + { { "uni0669" }, { "uni0669.Small" } }, + { { "uni06F0" }, { "uni06F0.Small" } }, + { { "uni06F1" }, { "uni06F1.Small" } }, + { { "uni06F2" }, { "uni06F2.Small" } }, + { { "uni06F3" }, { "uni06F3.Small" } }, + { { "uni06F4" }, { "uni06F4.Small" } }, + { { "uni06F4.urdu" }, { "uni06F4.Small.urdu" } }, + { { "uni06F5" }, { "uni06F5.Small" } }, + { { "uni06F6" }, { "uni06F6.Small" } }, + { { "uni06F6.urdu" }, { "uni06F6.Small.urdu" } }, + { { "uni06F7" }, { "uni06F7.Small" } }, + { { "uni06F7.urdu" }, { "uni06F7.Small.urdu" } }, + { { "uni06F8" }, { "uni06F8.Small" } }, + { { "uni06F9" }, { "uni06F9.Small" } }, + { { "zero" }, { "zeroSmall" } }, + } + }, + { "f3", "lu23", "arab", "*", "*", + new String[][][] { + { { "uni0670" }, { "uni0670.large" } }, + } + }, + }; + + private static Object[][] ltMultiple = { + { GlyphSubstitutionTable.GSUB_LOOKUP_TYPE_MULTIPLE }, + // arab-001.ttx + { "f0", "lu9", "arab", "*", "*", + new String[][][] { + { { "alefwithhamzabelow" }, { "arabicalef", "uni0655" } }, + } + }, + // arab-002.ttx + { "f1", "lu14", "arab", "*", "*", + new String[][][] { + { { "pehinitial" }, { "pehinitial", "tatweel" } }, + { { "yehwithhamzaaboveinitial" }, { "yehwithhamzaaboveinitial", "tatweel" } }, + { { "behinitial" }, { "behinitial", "tatweel" } }, + { { "tehinitial" }, { "tehinitial", "tatweel" } }, + { { "thehinitial" }, { "thehinitial", "tatweel" } }, + { { "fehinitial" }, { "fehinitial", "tatweel" } }, + { { "qafinitial" }, { "qafinitial", "tatweel" } }, + { { "nooninitial" }, { "nooninitial", "tatweel" } }, + { { "yehinitial" }, { "yehinitial", "tatweel" } }, + { { "uni0649.init" }, { "uni0649.init", "tatweel" } }, + } + }, + { "f1", "lu15", "arab", "*", "*", + new String[][][] { + { { "pehmedial" }, { "pehmedial", "tatweel" } }, + { { "yehwithhamzaabovemedial" }, { "yehwithhamzaabovemedial", "tatweel" } }, + { { "behmedial" }, { "behmedial", "tatweel" } }, + { { "tehmedial" }, { "tehmedial", "tatweel" } }, + { { "thehmedial" }, { "thehmedial", "tatweel" } }, + { { "noonmedial" }, { "noonmedial", "tatweel" } }, + { { "yehmedial" }, { "yehmedial", "tatweel" } }, + { { "uni0649.medi" }, { "uni0649.medi", "tatweel" } }, + } + }, + // arab-003.ttx + { "f2", "lu0", "arab", "dflt", "ccmp", + new String[][][] { + { { "uni0622" }, { "uni0627", "uni0653" } }, + { { "uni0623" }, { "uni0627", "uni0654" } }, + { { "uni0625" }, { "uni0627", "uni0655" } }, + { { "uni0626" }, { "uni064A", "uni0654" } }, + } + }, + // arab-004.ttx + { "f3", "lu0", "arab", "dflt", "ccmp", + new String[][][] { + { { "uni0622" }, { "uni0627", "uni0653" } }, + { { "uni0623" }, { "uni0627", "uni0654" } }, + { { "uni0625" }, { "uni0627", "uni0655" } }, + } + }, + }; + + private static Object[][] ltAlternate = { + { GlyphSubstitutionTable.GSUB_LOOKUP_TYPE_ALTERNATE }, + // arab-001.ttx - none used + // arab-002.ttx - none used + // arab-003.ttx - none used + // arab-004.ttx - add tests + { "f3", "lu14", "arab", "dflt", "salt" }, + }; + + private static Object[][] ltLigature = { + { GlyphSubstitutionTable.GSUB_LOOKUP_TYPE_LIGATURE }, + // arab-001.ttx + { "f0", "lu0", "arab", "dflt", "ccmp", + new String[][][] { + { { "damma", "shadda" }, { "shaddawithdammalow" } }, + { { "damma", "highhamza" }, { "dammaonhamza" } }, + { { "dammatan", "shadda" }, { "shaddawithdammatanlow" } }, + { { "dammatan", "highhamza" }, { "dammatanonhamza" } }, + { { "fatha", "shadda" }, { "shaddawithfathalow" } }, + { { "fatha", "highhamza" }, { "fathaonhamza" } }, + { { "fathatan", "shadda" }, { "shaddawithfathatanlow" } }, + { { "fathatan", "highhamza" }, { "fathatanonhamza" } }, + { { "highhamza", "fatha" }, { "fathaonhamza" } }, + { { "highhamza", "fathatan" }, { "fathatanonhamza" } }, + { { "highhamza", "sukun" }, { "sukunonhamza" } }, + { { "highhamza", "damma" }, { "dammaonhamza" } }, + { { "highhamza", "dammatan" }, { "dammatanonhamza" } }, + { { "kasra", "shadda" }, { "shaddawithkasralow" } }, + { { "kasra", "uni0655" }, { "uni06550650" } }, + { { "kasratan", "shadda" }, { "shaddawithkasratanlow" } }, + { { "kasratan", "uni0655" }, { "uni0655064D" } }, + { { "shadda", "dammatan" }, { "shaddawithdammatanlow" } }, + { { "shadda", "fatha" }, { "shaddawithfathalow" } }, + { { "shadda", "damma" }, { "shaddawithdammalow" } }, + { { "shadda", "fathatan" }, { "shaddawithfathatanlow" } }, + { { "shadda", "kasratan" }, { "shaddawithkasratanlow" } }, + { { "shadda", "kasra" }, { "shaddawithkasralow" } }, + { { "sukun", "highhamza" }, { "sukunonhamza" } }, + { { "uni0655", "kasratan" }, { "uni0655064D" } }, + { { "uni0655", "kasra" }, { "uni06550650" } }, + } + }, + { "f0", "lu7", "arab", "dflt", "rlig", + new String[][][] { + { { "lamisolated", "alefwithmaddaabovefinal" }, { "lamwithalefmaddaaboveisolatedd" } }, + { { "lamisolated", "alefwithhamzaabovefinal" }, { "lamwithalefhamzaaboveisolatedd" } }, + { { "lamisolated", "alefwithhamzabelowfinal" }, { "lamwithalefhamzabelowisolated" } }, + { { "lamisolated", "aleffinal" }, { "lamwithalefisolated" } }, + { { "lammedial", "alefwithmaddaabovefinal" }, { "lamwithalefmaddaabovefinal" } }, + { { "lammedial", "alefwithhamzaabovefinal" }, { "lamwithalefhamzaabovefinal" } }, + { { "lammedial", "alefwithhamzabelowfinal" }, { "lamwithalefhamzabelowfinal" } }, + { { "lammedial", "aleffinal" }, { "lamwithaleffinal" } }, + } + }, + { "f0", "lu8", "arab", "dflt", "liga", + new String[][][] { + { { "lamisolated", "lammedial", "hehfinal" }, { "allahisolated" } }, + { { "reh", "yehmedial", "aleffinal", "lam" }, { "rayaleflam" } }, + } + }, + // arab-002.ttx + { "f1", "lu0", "arab", "dflt", "ccmp", + new String[][][] { + { { "damma", "shadda" }, { "shaddawithdammaisolatedlow" } }, + { { "damma", "highhamza" }, { "dammaonhamza" } }, + { { "dammatan", "shadda" }, { "shaddawithdammatanisolatedlow" } }, + { { "dammatan", "highhamza" }, { "dammatanonhamza" } }, + { { "fatha", "shadda" }, { "shaddawithfathaisolatedlow" } }, + { { "fatha", "highhamza" }, { "fathaonhamza" } }, + { { "fathatan", "shadda" }, { "shaddawithfathatanisolatedlow" } }, + { { "fathatan", "highhamza" }, { "fathatanonhamza" } }, + { { "highhamza", "fatha" }, { "fathaonhamza" } }, + { { "highhamza", "fathatan" }, { "fathatanonhamza" } }, + { { "highhamza", "sukun" }, { "sukunonhamza" } }, + { { "highhamza", "damma" }, { "dammaonhamza" } }, + { { "highhamza", "dammatan" }, { "dammatanonhamza" } }, + { { "kasra", "shadda" }, { "shaddawithkasraisolatedlow" } }, + { { "kasra", "uni0655" }, { "uni06550650" } }, + { { "kasratan", "shadda" }, { "shaddawithkasratanisolatedlow" } }, + { { "kasratan", "uni0655" }, { "uni0655064D" } }, + { { "shadda", "dammatan" }, { "shaddawithdammatanisolatedlow" } }, + { { "shadda", "fatha" }, { "shaddawithfathaisolatedlow" } }, + { { "shadda", "damma" }, { "shaddawithdammaisolatedlow" } }, + { { "shadda", "fathatan" }, { "shaddawithfathatanisolatedlow" } }, + { { "shadda", "kasratan" }, { "shaddawithkasratanisolatedlow" } }, + { { "shadda", "kasra" }, { "shaddawithkasraisolatedlow" } }, + { { "sukun", "highhamza" }, { "sukunonhamza" } }, + { { "uni0655", "kasratan" }, { "uni0655064D" } }, + { { "uni0655", "kasra" }, { "uni06550650" } }, + } + }, + { "f1", "lu6", "arab", "dflt", "liga", + new String[][][] { + { { "behinitial", "hehmedial" }, { "behwithhehinitial" } }, + { { "behinitial", "meemfinal" }, { "behwithmeemisolated" } }, + { { "behinitial", "meemmedial" }, { "behwithmeeminitial" } }, + { { "behinitial", "alefmaksurafinal" }, { "behwithalefmaksuraisolated" } }, + { { "behinitial", "yehfinal" }, { "behwithyehisolated" } }, + { { "behinitial", "jeemmedial" }, { "behwithjeeminitial" } }, + { { "behinitial", "hahmedial" }, { "behwithhahinitial" } }, + { { "behinitial", "khahmedial" }, { "behwithkhahinitial" } }, + { { "behmedial", "alefmaksurafinal" }, { "behwithalefmaksurafinal" } }, + { { "behmedial", "yehfinal" }, { "behwithyehfinal" } }, + { { "behmedial", "rehfinal" }, { "behwithrehfinal" } }, + { { "behmedial", "noonfinal" }, { "behwithnoonfinal" } }, + { { "fehinitial", "alefmaksurafinal" }, { "fehwithalefmaksuraisolated" } }, + { { "fehinitial", "yehfinal" }, { "fehwithyehisolated" } }, + { { "hahinitial", "meemmedial" }, { "hahwithmeeminitial" } }, + { { "hehinitial", "meemmedial" }, { "hehwithmeeminitial" } }, + { { "jeeminitial", "meemmedial" }, { "jeemwithmeeminitial" } }, + { { "khahinitial", "meemmedial" }, { "khahwithmeeminitial" } }, + { { "laminitial", "jeemmedial" }, { "lamwithjeeminitial" } }, + { { "laminitial", "hahmedial" }, { "lamwithhahinitial" } }, + { { "laminitial", "khahmedial" }, { "lamwithkhahinitial" } }, + { { "laminitial", "hehmedial" }, { "lamwithhehinitial" } }, + { { "laminitial", "meemfinal" }, { "lamwithmeemisolated" } }, + { { "laminitial", "alefmaksurafinal" }, { "lamwithalefmaksuraisolated" } }, + { { "laminitial", "yehfinal" }, { "lamwithyehisolated" } }, + { { "meeminitial", "jeemmedial" }, { "meemwithjeeminitial" } }, + { { "meeminitial", "hahmedial" }, { "meemwithhahinitial" } }, + { { "meeminitial", "khahmedial" }, { "meemwithkhahinitial" } }, + { { "meeminitial", "meemmedial" }, { "meemwithmeeminitial" } }, + { { "nooninitial", "hehmedial" }, { "noonwithhehinitial" } }, + { { "nooninitial", "meemfinal" }, { "noonwithmeemisolated" } }, + { { "nooninitial", "meemmedial" }, { "noonwithmeeminitial" } }, + { { "nooninitial", "alefmaksurafinal" }, { "noonwithalefmaksuraisolated" } }, + { { "nooninitial", "yehfinal" }, { "noonwithyehisolated" } }, + { { "nooninitial", "jeemmedial" }, { "noonwithjeeminitial" } }, + { { "nooninitial", "hahmedial" }, { "noonwithhahinitial" } }, + { { "nooninitial", "khahmedial" }, { "noonwithkhahinitial" } }, + { { "noonmedial", "alefmaksurafinal" }, { "noonwithalefmaksurafinal" } }, + { { "noonmedial", "yehfinal" }, { "noonwithyehfinal" } }, + { { "pehinitial", "hehmedial" }, { "pehwithhehinitial" } }, + { { "seeninitial", "meemmedial" }, { "seenwithmeeminitial" } }, + { { "sheeninitial", "meemmedial" }, { "sheenwithmeeminitial" } }, + { { "tchehinitial", "meemmedial" }, { "uniE817" } }, + { { "tehinitial", "hehmedial" }, { "tehwithhehinitial" } }, + { { "tehinitial", "meemfinal" }, { "tehwithmeemisolated" } }, + { { "tehinitial", "meemmedial" }, { "tehwithmeeminitial" } }, + { { "tehinitial", "yehfinal" }, { "tehwithyehisolated" } }, + { { "tehinitial", "jeemmedial" }, { "tehwithjeeminitial" } }, + { { "tehinitial", "hahmedial" }, { "tehwithhahinitial" } }, + { { "tehinitial", "khahmedial" }, { "tehwithkhahinitial" } }, + { { "tehmedial", "alefmaksurafinal" }, { "tehwithalefmaksurafinal" } }, + { { "tehmedial", "yehfinal" }, { "tehwithyehfinal" } }, + { { "tehmedial", "rehfinal" }, { "noonwithzainfinal" } }, + { { "tehmedial", "noonfinal" }, { "tehwithnoonfinal" } }, + { { "thehinitial", "meemfinal" }, { "thehwithmeemisolated" } }, + { { "thehinitial", "meemmedial" }, { "thehwithmeeminitial" } }, + { { "yehinitial", "meemfinal" }, { "yehwithmeemisolated" } }, + { { "yehinitial", "meemmedial" }, { "yehwithmeeminitial" } }, + { { "yehinitial", "alefmaksurafinal" }, { "yehwithalefmaksuraisolated" } }, + { { "yehinitial", "jeemmedial" }, { "yehwithjeeminitial" } }, + { { "yehinitial", "hahmedial" }, { "yehwithhahinitial" } }, + { { "yehinitial", "khahmedial" }, { "yehwithkhahinitial" } }, + { { "yehmedial", "alefmaksurafinal" }, { "yehwithalefmaksurafinal" } }, + { { "yehmedial", "rehfinal" }, { "yehwithrehfinal" } }, + { { "yehmedial", "noonfinal" }, { "yehwithnoonfinal" } }, + } + }, + { "f1", "lu7", "arab", "dflt", "liga", + new String[][][] { + { { "laminitial", "meemmedial", "jeemmedial" }, { "lamwithmeemwithjeeminitial" } }, + { { "laminitial", "meemmedial", "hahmedial" }, { "lamwithmeemwithhahinitial" } }, + { { "laminitial", "meemmedial" }, { "lamwithmeeminitial" } }, + } + }, + { "f1", "lu8", "arab", "dflt", "liga", + new String[][][] { + { { "laminitial", "jeemfinal" }, { "lamwithjeemisolated" } }, + { { "laminitial", "hahfinal" }, { "lamwithhahisolated" } }, + { { "laminitial", "khahfinal" }, { "lamwithkhahisolated" } }, + } + }, + { "f1", "lu9", "arab", "dflt", "rlig", + new String[][][] { + { { "laminitial", "alefwithmaddaabovefinal" }, { "lamwithalefmaddaaboveisolatedd" } }, + { { "laminitial", "alefwithhamzaabovefinal" }, { "lamwithalefhamzaaboveisolatedd" } }, + { { "laminitial", "alefwithhamzabelowfinal" }, { "lamwithalefhamzabelowisolated" } }, + { { "laminitial", "aleffinal" }, { "lamwithalefisolated" } }, + { { "lammedial", "alefwithmaddaabovefinal" }, { "lamwithalefmaddaabovefinal" } }, + { { "lammedial", "alefwithhamzaabovefinal" }, { "lamwithalefhamzaabovefinal" } }, + { { "lammedial", "alefwithhamzabelowfinal" }, { "lamwithalefhamzabelowfinal" } }, + { { "lammedial", "aleffinal" }, { "lamwithaleffinal" } }, + } + }, + { "f1", "lu10", "arab", "dflt", "liga", + new String[][][] { + { { "laminitial", "lammedial", "hehfinal" }, { "allahisolated" } }, + { { "reh", "yehinitial", "aleffinal", "lam" }, { "rayaleflam" } }, + } + }, + // arab-003.ttx + { "f2", "lu5", "arab", "dflt", "rlig", + new String[][][] { + { { "uni064B", "uni0651" }, { "uni0651064B" } }, + { { "uni064C", "uni0651" }, { "uni0651064C" } }, + { { "uni064E", "uni0651" }, { "uni0651064E" } }, + { { "uni064F", "uni0651" }, { "uni0651064F" } }, + { { "uni0651", "uni064B" }, { "uni0651064B" } }, + { { "uni0651", "uni064C" }, { "uni0651064C" } }, + { { "uni0651", "uni064E" }, { "uni0651064E" } }, + { { "uni0651", "uni064F" }, { "uni0651064F" } }, + { { "uni0651", "uni0670" }, { "absShaddaAlef" } }, + { { "uni0670", "uni0651" }, { "absShaddaAlef" } }, + } + }, + { "f2", "lu6", "arab", "dflt", "rlig", + new String[][][] { + { { "uni064D", "uni0651" }, { "uni0651064D" } }, + { { "uni0650", "uni0651" }, { "uni06510650" } }, + { { "uni0651", "uni0650" }, { "uni06510650" } }, + { { "uni0651", "uni064D" }, { "uni0651064D" } }, + } + }, + { "f2", "lu7", "arab", "dflt", "rlig", + new String[][][] { + { { "uni0647", "uni0654" }, { "uni06C0" } }, + { { "uni0647.fina", "uni0654" }, { "uni06C0.fina" } }, + { { "uni0647.init", "uni0654" }, { "uni06C0.init" } }, + { { "uni0647.medi", "uni0654" }, { "uni06C0.medi" } }, + { { "uni0648", "uni0654" }, { "uni0624" } }, + { { "uni0648.fina", "uni0654" }, { "uni0624.fina" } }, + { { "uni064A", "uni0654" }, { "uni0626" } }, + { { "uni064A.fina", "uni0654" }, { "uni0626.fina" } }, + { { "uni064A.init", "uni0654" }, { "uni0626.init" } }, + { { "uni064A.medi", "uni0654" }, { "uni0626.medi" } }, + { { "uni06C1", "uni0654" }, { "uni06C2" } }, + { { "uni06C1.fina", "uni0654" }, { "uni06C2.fina" } }, + { { "uni06C1.init", "uni0654" }, { "uni06C2.init" } }, + { { "uni06C1.medi", "uni0654" }, { "uni06C2.medi" } }, + } + }, + // arab-004.ttx + { "f3", "lu5", "arab", "dflt", "rlig", + new String[][][] { + { { "uni064B", "uni0651" }, { "uni0651064B" } }, + { { "uni064C", "uni0651" }, { "uni0651064C" } }, + { { "uni064E", "uni0651" }, { "uni0651064E" } }, + { { "uni064F", "uni0651" }, { "uni0651064F" } }, + { { "uni0651", "uni064B" }, { "uni0651064B" } }, + { { "uni0651", "uni064C" }, { "uni0651064C" } }, + { { "uni0651", "uni064E" }, { "uni0651064E" } }, + { { "uni0651", "uni064F" }, { "uni0651064F" } }, + { { "uni0651", "uni0670" }, { "absShaddaAlef" } }, + { { "uni0670", "uni0651" }, { "absShaddaAlef" } }, + } + }, + { "f3", "lu6", "arab", "dflt", "rlig", + new String[][][] { + { { "uni064D", "uni0651" }, { "uni0651064D" } }, + { { "uni0650", "uni0651" }, { "uni06510650" } }, + { { "uni0651", "uni0650" }, { "uni06510650" } }, + { { "uni0651", "uni064D" }, { "uni0651064D" } }, + } + }, + { "f3", "lu7", "arab", "dflt", "rlig", + new String[][][] { + { { "uni0647", "uni0654" }, { "uni06C0" } }, + { { "uni0647.fina", "uni0654" }, { "uni06C0.fina" } }, + { { "uni0647.init", "uni0654" }, { "uni06C0.init" } }, + { { "uni0647.medi", "uni0654" }, { "uni06C0.medi" } }, + { { "uni0648", "uni0654" }, { "uni0624" } }, + { { "uni0648.fina", "uni0654" }, { "uni0624.fina" } }, + { { "uni064A", "uni0654" }, { "uni0626" } }, + { { "uni064A.fina", "uni0654" }, { "uni0626.fina" } }, + { { "uni064A.init", "uni0654" }, { "uni0626.init" } }, + { { "uni064A.medi", "uni0654" }, { "uni0626.medi" } }, + { { "uni06C1", "uni0654" }, { "uni06C2" } }, + { { "uni06C1.fina", "uni0654" }, { "uni06C2.fina" } }, + { { "uni06C1.init", "uni0654" }, { "uni06C2.init" } }, + { { "uni06C1.medi", "uni0654" }, { "uni06C2.medi" } }, + } + }, + { "f3", "lu8", "arab", "dflt", "rlig", + new String[][][] { + { { "uni064E", "uni0654" }, { "uni0654064E" } }, + { { "uni064F", "uni0654" }, { "uni0654064F" } }, + { { "uni0654", "uni064E" }, { "uni0654064E" } }, + { { "uni0654", "uni064F" }, { "uni0654064F" } }, + } + }, + }; + + private static Object[][] ltContextual = { + { GlyphSubstitutionTable.GSUB_LOOKUP_TYPE_CONTEXTUAL }, + // arab-001.ttx - none used + // arab-002.ttx - none used + // arab-003.ttx - none used + // arab-004.ttx - none used + }; + + private static Object[][] ltChainedContextual = { + { GlyphSubstitutionTable.GSUB_LOOKUP_TYPE_CHAINED_CONTEXTUAL }, + // arab-001.ttx + { "f0", "lu1", "arab", "dflt", "ccmp", + new String[][][] { + { { "wawwithhamzaabove", "alefwithhamzabelow" }, { "wawwithhamzaabove", "arabicalef", "uni0655" } }, + { { "reh", "alefwithhamzabelow" }, { "reh", "arabicalef", "uni0655" } }, + { { "zain", "alefwithhamzabelow" }, { "zain", "arabicalef", "uni0655" } }, + { { "waw", "alefwithhamzabelow" }, { "waw", "arabicalef", "uni0655" } }, + { { "jeh", "alefwithhamzabelow" }, { "jeh", "arabicalef", "uni0655" } }, + } + }, + { "f0", "lu3", "arab", "dflt", "isol", + new String[][][] { + { { "hamza", "heh" }, { "hamza", "hehisolated" } }, + { { "alefwithmaddaabove", "heh" }, { "alefwithmaddaabove", "hehisolated" } }, + { { "alefwithhamzaabove", "heh" }, { "alefwithhamzaabove", "hehisolated" } }, + { { "wawwithhamzaabove", "heh" }, { "wawwithhamzaabove", "hehisolated" } }, + { { "alefwithhamzabelow", "heh" }, { "alefwithhamzabelow", "hehisolated" } }, + { { "arabicalef", "heh" }, { "arabicalef", "hehisolated" } }, + { { "tehmarbuta", "heh" }, { "tehmarbuta", "hehisolated" } }, + { { "dal", "heh" }, { "dal", "hehisolated" } }, + { { "thal", "heh" }, { "thal", "hehisolated" } }, + { { "reh", "heh" }, { "reh", "hehisolated" } }, + { { "zain", "heh" }, { "zain", "hehisolated" } }, + { { "waw", "heh" }, { "waw", "hehisolated" } }, + { { "alefwasla", "heh" }, { "alefwasla", "hehisolated" } }, + { { "jeh", "heh" }, { "jeh", "hehisolated" } }, + { { "arabicae", "heh" }, { "arabicae", "hehisolated" } }, + { { "alefwaslafinal", "heh" }, { "alefwaslafinal", "hehisolated" } }, + { { "alefwithmaddaabovefinal", "heh" }, { "alefwithmaddaabovefinal", "hehisolated" } }, + { { "alefwithhamzaabovefinal", "heh" }, { "alefwithhamzaabovefinal", "hehisolated" } }, + { { "alefwithhamzabelowfinal", "heh" }, { "alefwithhamzabelowfinal", "hehisolated" } }, + { { "aleffinal", "heh" }, { "aleffinal", "hehisolated" } }, + { { "tehmarbutafinal", "heh" }, { "tehmarbutafinal", "hehisolated" } }, + { { "lamwithalefmaddaaboveisolatedd", "heh" }, { "lamwithalefmaddaaboveisolatedd", "hehisolated" } }, + { { "lamwithalefmaddaabovefinal", "heh" }, { "lamwithalefmaddaabovefinal", "hehisolated" } }, + { { "lamwithalefhamzaaboveisolatedd", "heh" }, { "lamwithalefhamzaaboveisolatedd", "hehisolated" } }, + { { "lamwithalefhamzaabovefinal", "heh" }, { "lamwithalefhamzaabovefinal", "hehisolated" } }, + { { "lamwithalefhamzabelowisolated", "heh" }, { "lamwithalefhamzabelowisolated", "hehisolated" } }, + { { "lamwithalefhamzabelowfinal", "heh" }, { "lamwithalefhamzabelowfinal", "hehisolated" } }, + { { "lamwithalefisolated", "heh" }, { "lamwithalefisolated", "hehisolated" } }, + { { "lamwithaleffinal", "heh" }, { "lamwithaleffinal", "hehisolated" } }, + } + }, + // arab-002.ttx + { "f1", "lu2", "arab", "dflt", "isol", + new String[][][] { + { { "hamza", "heh" }, { "hamza", "hehisolated" } }, + { { "alefwithmaddaabove", "heh" }, { "alefwithmaddaabove", "hehisolated" } }, + { { "alefwithhamzaabove", "heh" }, { "alefwithhamzaabove", "hehisolated" } }, + { { "wawwithhamzaabove", "heh" }, { "wawwithhamzaabove", "hehisolated" } }, + { { "alefwithhamzabelow", "heh" }, { "alefwithhamzabelow", "hehisolated" } }, + { { "arabicalef", "heh" }, { "arabicalef", "hehisolated" } }, + { { "tehmarbuta", "heh" }, { "tehmarbuta", "hehisolated" } }, + { { "dal", "heh" }, { "dal", "hehisolated" } }, + { { "thal", "heh" }, { "thal", "hehisolated" } }, + { { "reh", "heh" }, { "reh", "hehisolated" } }, + { { "zain", "heh" }, { "zain", "hehisolated" } }, + { { "waw", "heh" }, { "waw", "hehisolated" } }, + { { "alefwasla", "heh" }, { "alefwasla", "hehisolated" } }, + { { "jeh", "heh" }, { "jeh", "hehisolated" } }, + { { "arabicae", "heh" }, { "arabicae", "hehisolated" } }, + { { "alefwaslafinal", "heh" }, { "alefwaslafinal", "hehisolated" } }, + { { "alefwithmaddaabovefinal", "heh" }, { "alefwithmaddaabovefinal", "hehisolated" } }, + { { "alefwithhamzaabovefinal", "heh" }, { "alefwithhamzaabovefinal", "hehisolated" } }, + { { "alefwithhamzabelowfinal", "heh" }, { "alefwithhamzabelowfinal", "hehisolated" } }, + { { "aleffinal", "heh" }, { "aleffinal", "hehisolated" } }, + { { "tehmarbutafinal", "heh" }, { "tehmarbutafinal", "hehisolated" } }, + { { "lamwithalefmaddaaboveisolatedd", "heh" }, { "lamwithalefmaddaaboveisolatedd", "hehisolated" } }, + { { "lamwithalefmaddaabovefinal", "heh" }, { "lamwithalefmaddaabovefinal", "hehisolated" } }, + { { "lamwithalefhamzaaboveisolatedd", "heh" }, { "lamwithalefhamzaaboveisolatedd", "hehisolated" } }, + { { "lamwithalefhamzaabovefinal", "heh" }, { "lamwithalefhamzaabovefinal", "hehisolated" } }, + { { "lamwithalefhamzabelowisolated", "heh" }, { "lamwithalefhamzabelowisolated", "hehisolated" } }, + { { "lamwithalefhamzabelowfinal", "heh" }, { "lamwithalefhamzabelowfinal", "hehisolated" } }, + { { "lamwithalefisolated", "heh" }, { "lamwithalefisolated", "hehisolated" } }, + { { "lamwithaleffinal", "heh" }, { "lamwithaleffinal", "hehisolated" } }, + } + }, + { "f1", "lu11", "arab", "dflt", "calt", + new String[][][] { + { { "pehinitial", "fatha", "pehmedial", "fatha" }, { "pehinitial", "tatweel", "fatha", "pehmedial", "fatha" } }, + { { "yehwithhamzaaboveinitial", "damma", "vehmedial", "damma" }, { "yehwithhamzaaboveinitial", "tatweel", "damma", "vehmedial", "damma" } }, + { { "behinitial", "shadda", "jehfinal", "shadda" }, { "behinitial", "tatweel", "shadda", "jehfinal", "shadda" } }, + { { "tehinitial", "sukun", "behmedial", "sukun" }, { "tehinitial", "tatweel", "sukun", "behmedial", "sukun" } }, + { { "thehinitial", "smallhighmadda", "tehmedial", "smallhighmadda" }, { "thehinitial", "tatweel", "smallhighmadda", "tehmedial", "smallhighmadda" } }, + { { "fehinitial", "fathaonhamza", "ainmedial", "fathaonhamza" }, { "fehinitial", "tatweel", "fathaonhamza", "ainmedial", "fathaonhamza" } }, + { { "qafinitial", "dammaonhamza", "qafmedial", "dammaonhamza" }, { "qafinitial", "tatweel", "dammaonhamza", "qafmedial", "dammaonhamza" } }, + { { "nooninitial", "superscriptalef", "wawfinal", "superscriptalef" }, { "nooninitial", "tatweel", "superscriptalef", "wawfinal", "superscriptalef" } }, + { { "yehinitial", "dammatanonhamza", "rehfinal", "dammatanonhamza" }, { "yehinitial", "tatweel", "dammatanonhamza", "rehfinal", "dammatanonhamza" } }, + { { "uni0649.init", "uni0654", "wawwithhamzaabovefinal", "uni0654" }, { "uni0649.init", "tatweel", "uni0654", "wawwithhamzaabovefinal", "uni0654" } }, + } + }, + { "f1", "lu12", "arab", "dflt", "calt", + new String[][][] { + { { "pehmedial", "fatha", "pehmedial", "fatha" }, { "pehmedial", "tatweel", "fatha", "pehmedial", "fatha" } }, + { { "yehwithhamzaabovemedial", "damma", "vehmedial", "damma" }, { "yehwithhamzaabovemedial", "tatweel", "damma", "vehmedial", "damma" } }, + { { "behmedial", "shadda", "wawwithhamzaabovefinal", "shadda" }, { "behmedial", "tatweel", "shadda", "wawwithhamzaabovefinal", "shadda" } }, + { { "tehmedial", "sukun", "rehfinal", "sukun" }, { "tehmedial", "tatweel", "sukun", "rehfinal", "sukun" } }, + { { "thehmedial", "smallhighmadda", "zainfinal", "smallhighmadda" }, { "thehmedial", "tatweel", "smallhighmadda", "zainfinal", "smallhighmadda" } }, + { { "noonmedial", "superscriptalef", "ainmedial", "superscriptalef" }, { "noonmedial", "tatweel", "superscriptalef", "ainmedial", "superscriptalef" } }, + { { "yehmedial", "dammatanonhamza", "wawfinal", "dammatanonhamza" }, { "yehmedial", "tatweel", "dammatanonhamza", "wawfinal", "dammatanonhamza" } }, + { { "uni0649.medi", "uni0654", "yehmedial", "uni0654" }, { "uni0649.medi", "tatweel", "uni0654", "yehmedial", "uni0654" } }, + } + }, + // arab-003.ttx + { "f2", "lu4", "arab", "dflt", "rlig", + new String[][][] { + { { "uni0644.medi", "uni0622.fina" }, { "uni0644.medi.preAlef", "uni0622.fina.postLamMed" } }, + { { "uni06B5.medi", "uni0622.fina" }, { "uni06B5.medi.preAlef", "uni0622.fina.postLamMed" } }, + { { "uni06B6.medi", "uni0622.fina" }, { "uni06B6.medi.preAlef", "uni0622.fina.postLamMed" } }, + { { "uni06B7.medi", "uni0622.fina" }, { "uni06B7.medi.preAlef", "uni0622.fina.postLamMed" } }, + { { "uni06B8.medi", "uni0622.fina" }, { "uni06B8.medi.preAlef", "uni0622.fina.postLamMed" } }, + { { "absLamRetroMed", "uni0622.fina" }, { "absLamRetroMed.preAlef", "uni0622.fina.postLamMed" } }, + { { "uni076A.medi", "uni0622.fina" }, { "uni076A.medi.preAlef", "uni0622.fina.postLamMed" } }, + { { "uni0644.init", "uni0622.fina" }, { "uni0644.init.preAlef", "uni0622.fina.postLamIni" } }, + { { "uni06B5.init", "uni0622.fina" }, { "uni06B5.init.preAlef", "uni0622.fina.postLamIni" } }, + { { "uni06B6.init", "uni0622.fina" }, { "uni06B6.init.preAlef", "uni0622.fina.postLamIni" } }, + { { "uni06B7.init", "uni0622.fina" }, { "uni06B7.init.preAlef", "uni0622.fina.postLamIni" } }, + { { "uni06B8.init", "uni0622.fina" }, { "uni06B8.init.preAlef", "uni0622.fina.postLamIni" } }, + { { "absLamRetroIni", "uni0622.fina" }, { "absLamRetroIni.preAlef", "uni0622.fina.postLamIni" } }, + { { "uni076A.init", "uni0622.fina" }, { "uni076A.init.preAlef", "uni0622.fina.postLamIni" } }, + } + }, + { "f2", "lu8", "arab", "dflt", "calt", + new String[][][] { + { { "uni064A", "uni0670" }, { "uni064A", "uni0670.large" } }, + } + }, + { "f2", "lu13", "arab", "dflt", "calt", + new String[][][] { + { { "uni06DD", "one" }, { "uni06DD", "oneMedium" } }, + { { "uni06DD", "one", "two" }, { "uni06DD.2", "oneMedium", "twoMedium" } }, + { { "uni06DD", "one", "two", "three" }, { "uni06DD.3", "oneSmall", "twoSmall", "threeSmall" } }, + } + }, + // arab-004.ttx + { "f3", "lu4", "arab", "dflt", "rlig", + new String[][][] { + { { "uni0644.medi", "uni0622.fina" }, { "uni0644.medi.preAlef", "uni0622.fina.postLamMed" } }, + { { "uni06B5.medi", "uni0622.fina" }, { "uni06B5.medi.preAlef", "uni0622.fina.postLamMed" } }, + { { "uni06B6.medi", "uni0622.fina" }, { "uni06B6.medi.preAlef", "uni0622.fina.postLamMed" } }, + { { "uni06B7.medi", "uni0622.fina" }, { "uni06B7.medi.preAlef", "uni0622.fina.postLamMed" } }, + { { "uni06B8.medi", "uni0622.fina" }, { "uni06B8.medi.preAlef", "uni0622.fina.postLamMed" } }, + { { "absLamRetroMed", "uni0622.fina" }, { "absLamRetroMed.preAlef", "uni0622.fina.postLamMed" } }, + { { "uni076A.medi", "uni0622.fina" }, { "uni076A.medi.preAlef", "uni0622.fina.postLamMed" } }, + { { "uni0644.init", "uni0622.fina" }, { "uni0644.init.preAlef", "uni0622.fina.postLamIni" } }, + { { "uni06B5.init", "uni0622.fina" }, { "uni06B5.init.preAlef", "uni0622.fina.postLamIni" } }, + { { "uni06B6.init", "uni0622.fina" }, { "uni06B6.init.preAlef", "uni0622.fina.postLamIni" } }, + { { "uni06B7.init", "uni0622.fina" }, { "uni06B7.init.preAlef", "uni0622.fina.postLamIni" } }, + { { "uni06B8.init", "uni0622.fina" }, { "uni06B8.init.preAlef", "uni0622.fina.postLamIni" } }, + { { "absLamRetroIni", "uni0622.fina" }, { "absLamRetroIni.preAlef", "uni0622.fina.postLamIni" } }, + { { "uni076A.init", "uni0622.fina" }, { "uni076A.init.preAlef", "uni0622.fina.postLamIni" } }, + } + }, + { "f3", "lu9", "arab", "dflt", "calt", + new String[][][] { + { { "uni0601", "uni0661" }, { "uni0601", "uni0661.Medium" } }, + { { "uni0601", "uni0661", "uni0662" }, { "uni0601.2", "uni0661.Medium", "uni0662.Medium" } }, + { { "uni0601", "uni0661", "uni0662", "uni0663" }, { "uni0601.3", "uni0661.Medium", "uni0662.Medium", "uni0663.Medium", } }, + { { "uni0601", "uni0661", "uni0662", "uni0663", "uni0664" }, { "uni0601.4", "uni0661.Medium", "uni0662.Medium", "uni0663.Medium", "uni0664.Medium" } }, + } + }, + { "f3", "lu10", "arab", "dflt", "calt", + new String[][][] { + { { "uni064A", "uni0670" }, { "uni064A", "uni0670.large" } }, + } + }, + }; + + @Test + public void testGSUBSingle() throws Exception { + performSubstitutions ( ltSingle ); + } + + @Test + public void testGSUBMultiple() throws Exception { + performSubstitutions ( ltMultiple ); + } + + @Test + public void testGSUBAlternate() throws Exception { + performSubstitutions ( ltAlternate ); + } + + @Test + public void testGSUBLigature() throws Exception { + performSubstitutions ( ltLigature ); + } + + @Test + public void testGSUBContextual() throws Exception { + performSubstitutions ( ltContextual ); + } + + @Test + public void testGSUBChainedContextual() throws Exception { + performSubstitutions ( ltChainedContextual ); + } + + /** + * Perform substitutions on all test data in test specification TS. + * @param ts test specification + */ + private void performSubstitutions ( Object[][] ts ) { + assert ts.length > 0; + Object[] tp = ts[0]; + for ( int i = 1; i < ts.length; i++ ) { + performSubstitutions ( tp, ts[i] ); + } + } + + /** + * Perform substitutions on all test data TD using test parameters TP. + * @param tp test parameters + * @param td test data + */ + private void performSubstitutions ( Object[] tp, Object[] td ) { + assert tp.length > 0; + if ( td.length > 5 ) { + String fid = (String) td[0]; + String lid = (String) td[1]; + String script = (String) td[2]; + String language = (String) td[3]; + String feature = (String) td[4]; + TTXFile tf = findTTX ( fid ); + assertTrue ( tf != null ); + GlyphSubstitutionTable gsub = tf.getGSUB(); + assertTrue ( gsub != null ); + GlyphSubstitutionSubtable[] sta = findGSUBSubtables ( gsub, script, language, feature, lid ); + assertTrue ( sta != null ); + assertTrue ( sta.length > 0 ); + ScriptContextTester sct = findScriptContextTester ( script, language, feature ); + String[][][] tia = (String[][][]) td[5]; // test instance array + for ( String[][] ti : tia ) { // test instance + if ( ti != null ) { + if ( ti.length > 1 ) { // must have at least input and output glyph id arrays + String[] igia = ti[0]; // input glyph id array + String[] ogia = ti[1]; // output glyph id array + GlyphSequence igs = tf.getGlyphSequence ( igia ); + GlyphSequence ogs = tf.getGlyphSequence ( ogia ); + GlyphSequence tgs = GlyphSubstitutionSubtable.substitute ( igs, script, language, feature, sta, sct ); + assertSameGlyphs ( ogs, tgs ); + } + } + } + } + } + + private String findTTXPath ( String fid ) { + for ( String[] fs : ttxFonts ) { + if ( ( fs != null ) && ( fs.length > 1 ) ) { + if ( fs[0].equals ( fid ) ) { + return ttxFilesRoot + File.separator + fs[1]; + } + } + } + return null; + } + + private TTXFile findTTX ( String fid ) { + String pn = findTTXPath ( fid ); + assertTrue ( pn != null ); + try { + TTXFile tf = TTXFile.getFromCache ( pn ); + return tf; + } catch ( Exception e ) { + fail ( e.getMessage() ); + return null; + } + } + + private GlyphSubstitutionSubtable[] findGSUBSubtables ( GlyphSubstitutionTable gsub, String script, String language, String feature, String lid ) { + LookupTable lt = gsub.getLookupTable ( lid ); + if ( lt != null ) { + return (GlyphSubstitutionSubtable[]) lt.getSubtables(); + } else { + return null; + } + } + + private ScriptContextTester findScriptContextTester ( String script, String language, String feature ) { + return this; + } + + @Override + public GlyphContextTester getTester ( String feature ) { + return this; + } + + @Override + public boolean test ( String script, String language, String feature, GlyphSequence gs, int index, int flags ) { + return true; + } + + private void assertSameGlyphs ( GlyphSequence gs1, GlyphSequence gs2 ) { + assertNotNull ( gs1 ); + assertNotNull ( gs2 ); + IntBuffer gb1 = gs1.getGlyphs(); + IntBuffer gb2 = gs2.getGlyphs(); + assertEquals ( "unequal glyph count", gb1.limit(), gb2.limit() ); + for ( int i = 0; i < gb1.limit(); i++ ) { + int g1 = gb1.get(i); + int g2 = gb2.get(i); + assertEquals ( "unequal glyph code", g1, g2 ); + } + } + +} diff --git a/test/java/org/apache/fop/complexscripts/fonts/ttx/TTXFile.java b/test/java/org/apache/fop/complexscripts/fonts/ttx/TTXFile.java new file mode 100644 index 000000000..4be0fedd8 --- /dev/null +++ b/test/java/org/apache/fop/complexscripts/fonts/ttx/TTXFile.java @@ -0,0 +1,3450 @@ +/* + * 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.complexscripts.fonts.ttx; + +import java.io.File; +import java.io.IOException; + +import java.nio.IntBuffer; + +import java.util.Arrays; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.Stack; +import java.util.TreeMap; +import java.util.Vector; + +import javax.xml.parsers.FactoryConfigurationError; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.apache.fop.complexscripts.fonts.GlyphClassTable; +import org.apache.fop.complexscripts.fonts.GlyphCoverageTable; +import org.apache.fop.complexscripts.fonts.GlyphDefinitionSubtable; +import org.apache.fop.complexscripts.fonts.GlyphDefinitionTable; +import org.apache.fop.complexscripts.fonts.GlyphMappingTable; +import org.apache.fop.complexscripts.fonts.GlyphPositioningSubtable; +import org.apache.fop.complexscripts.fonts.GlyphPositioningTable; +import org.apache.fop.complexscripts.fonts.GlyphPositioningTable.Anchor; +import org.apache.fop.complexscripts.fonts.GlyphPositioningTable.MarkAnchor; +import org.apache.fop.complexscripts.fonts.GlyphPositioningTable.PairValues; +import org.apache.fop.complexscripts.fonts.GlyphPositioningTable.Value; +import org.apache.fop.complexscripts.fonts.GlyphSubstitutionSubtable; +import org.apache.fop.complexscripts.fonts.GlyphSubstitutionTable; +import org.apache.fop.complexscripts.fonts.GlyphSubstitutionTable.Ligature; +import org.apache.fop.complexscripts.fonts.GlyphSubstitutionTable.LigatureSet; +import org.apache.fop.complexscripts.fonts.GlyphSubtable; +import org.apache.fop.complexscripts.fonts.GlyphTable; +import org.apache.fop.complexscripts.fonts.GlyphTable.RuleLookup; +import org.apache.fop.complexscripts.util.GlyphSequence; +import org.apache.fop.complexscripts.util.UTF32; +import org.apache.fop.util.CharUtilities; + +import org.xml.sax.Attributes; +import org.xml.sax.Locator; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; + + +// CSOFF: InnerAssignmentCheck +// CSOFF: LineLengthCheck +// CSOFF: NoWhitespaceAfterCheck + +/** + * This class supports a subset of the TTX file as produced by the Adobe FLEX + * SDK (AFDKO). In particular, it is used to parse a TTX file in order to + * extract character to glyph code mapping data, glyph definition data, glyph substitution + * data, and glyph positioning data. + * + * TTX files are used in FOP for testing and debugging purposes only. Such + * files are used to represent font data employed by complex script processing, and + * normally extracted directly from an opentype (or truetype) file. However, due to + * copyright restrictions, it is not possible to include most opentype (or truetype) font + * files directly in the FOP distribution. In such cases, TTX files are used + * to distribute a subset of the complex script advanced table information contained in + * certain font files to facilitate testing. + * + * @author Glenn Adams + */ +public class TTXFile { + + /** logging instance */ + private static final Log log = LogFactory.getLog(TTXFile.class); // CSOK: ConstantNameCheck + /** default script tag */ + private static final String DEFAULT_SCRIPT_TAG = "dflt"; + /** default language tag */ + private static final String DEFAULT_LANGUAGE_TAG = "dflt"; + + /** ttxfile cache */ + private static Map cache = new HashMap(); + + // transient parsing state + private Locator locator; // current document locator + private Stack elements; // stack of ttx elements being parsed + private Map glyphIds; // map of glyph names to glyph identifiers + private List cmapEntries; // list of pairs + private Vector hmtxEntries; // vector of pairs + private Map glyphClasses; // map of glyph names to glyph classes + private Map>> scripts; // map of script tag to Map>> + private Map> languages; // map of language tag to List + private Map features; // map of feature id to Object[2] : { feature-tag, List } + private List languageFeatures; // list of language system feature ids, where first is (possibly null) required feature id + private List featureLookups; // list of lookup ids for feature being constructed + private List coverageEntries; // list of entries for coverage table being constructed + private Map coverages; // map of coverage table keys to coverage tables + private List subtableEntries; // list of lookup subtable entries + private List subtables; // list of constructed subtables + private List alternates; // list of alternates in alternate set being constructed + private List ligatures; // list of ligatures in ligature set being constructed + private List substitutes; // list of substitutes in (multiple substitution) sequence being constructed + private List pairs; // list of pair value records being constructed + private List pairSets; // list of pair value sets (as arrays) being constructed + private List anchors; // list of anchors of base|mark|component record being constructed + private List components; // list of ligature component anchors being constructed + private List markAnchors; // list of mark anchors being constructed + private List baseOrMarkAnchors; // list of base|mark2 anchors being constructed + private List ligatureAnchors; // list of ligature anchors being constructed + private List attachmentAnchors; // list of entry|exit attachment anchors being constructed + private List ruleLookups; // list of rule lookups being constructed + private int glyphIdMax; // maximum glyph id + private int cmPlatform; // plaform id of cmap being constructed + private int cmEncoding; // plaform id of cmap being constructed + private int cmLanguage; // plaform id of cmap being constructed + private int flIndex; // index of feature being constructed + private int flSequence; // feature sequence within feature list + private int ltIndex; // index of lookup table being constructed + private int ltSequence; // lookup sequence within table + private int ltFlags; // flags of current lookup being constructed + private int stSequence; // subtable sequence number within lookup + private int stFormat; // format of current subtable being constructed + private int ctFormat; // format of coverage table being constructed + private int ctIndex; // index of coverage table being constructed + private int rlSequence; // rule lookup sequence index + private int rlLookup; // rule lookup lookup index + private int psIndex; // pair set index + private int vf1; // value format 1 (used with pair pos and single pos) + private int vf2; // value format 2 (used with pair pos) + private int g2; // glyph id 2 (used with pair pos) + private int xCoord; // x coordinate of anchor being constructed + private int yCoord; // y coordinate of anchor being constructed + private int markClass; // mark class of mark anchor being constructed + private String defaultScriptTag; // tag of default script + private String scriptTag; // tag of script being constructed + private String defaultLanguageTag; // tag of default language system + private String languageTag; // tag of language system being constructed + private String featureTag; // tag of feature being constructed + private Value v1; // positioining value 1 + private Value v2; // positioining value 2 + + // resultant state + private int upem; // units per em + private Map cmap; // constructed character map + private Map gmap; // constructed glyph map + private int[][] hmtx; // constructed horizontal metrics - array of design { width, lsb } pairs, indexed by glyph code + private int[] widths; // pdf normalized widths (millipoints) + private GlyphDefinitionTable gdef; // constructed glyph definition table + private GlyphSubstitutionTable gsub; // constructed glyph substitution table + private GlyphPositioningTable gpos; // constructed glyph positioning table + + public TTXFile() { + elements = new Stack(); + glyphIds = new HashMap(); + cmapEntries = new ArrayList(); + hmtxEntries = new Vector(); + glyphClasses = new HashMap(); + scripts = new HashMap>>(); + languages = new HashMap>(); + features = new HashMap(); + languageFeatures = new ArrayList(); + featureLookups = new ArrayList(); + coverageEntries = new ArrayList(); + coverages = new HashMap(); + subtableEntries = new ArrayList(); + subtables = new ArrayList(); + alternates = new ArrayList(); + ligatures = new ArrayList(); + substitutes = new ArrayList(); + pairs = new ArrayList(); + pairSets = new ArrayList(); + anchors = new ArrayList(); + markAnchors = new ArrayList(); + baseOrMarkAnchors = new ArrayList(); + ligatureAnchors = new ArrayList(); + components = new ArrayList(); + attachmentAnchors = new ArrayList(); + ruleLookups = new ArrayList(); + glyphIdMax = -1; + cmPlatform = -1; + cmEncoding = -1; + cmLanguage = -1; + flIndex = -1; + flSequence = 0; + ltIndex = -1; + ltSequence = 0; + ltFlags = 0; + stSequence = 0; + stFormat = 0; + ctFormat = -1; + ctIndex = -1; + rlSequence = -1; + rlLookup = -1; + psIndex = -1; + vf1 = -1; + vf2 = -1; + g2 = -1; + xCoord = Integer.MIN_VALUE; + yCoord = Integer.MIN_VALUE; + markClass = -1; + defaultScriptTag = DEFAULT_SCRIPT_TAG; + scriptTag = null; + defaultLanguageTag = DEFAULT_LANGUAGE_TAG; + languageTag = null; + featureTag = null; + v1 = null; + v2 = null; + upem = -1; + } + public void parse ( String filename ) { + parse ( new File ( filename ) ); + } + public void parse ( File f ) { + assert f != null; + try { + SAXParserFactory spf = SAXParserFactory.newInstance(); + SAXParser sp = spf.newSAXParser(); + sp.parse ( f, new Handler() ); + } catch ( FactoryConfigurationError e ) { + throw new RuntimeException ( e.getMessage() ); + } catch ( ParserConfigurationException e ) { + throw new RuntimeException ( e.getMessage() ); + } catch ( SAXException e ) { + throw new RuntimeException ( e.getMessage() ); + } catch ( IOException e ) { + throw new RuntimeException ( e.getMessage() ); + } + } + public GlyphSequence mapCharsToGlyphs ( String s ) { + Integer[] ca = UTF32.toUTF32 ( s, 0, true ); + int ng = ca.length; + IntBuffer cb = IntBuffer.allocate ( ng ); + IntBuffer gb = IntBuffer.allocate ( ng ); + for ( Integer c : ca ) { + int g = mapCharToGlyph ( (int) c ); + if ( g >= 0 ) { + cb.put ( c ); + gb.put ( g ); + } else { + throw new IllegalArgumentException ( "character " + CharUtilities.format ( c ) + " has no corresponding glyph" ); + } + } + cb.rewind(); + gb.rewind(); + return new GlyphSequence ( cb, gb, null ); + } + public int mapCharToGlyph ( int c ) { + if ( cmap != null ) { + Integer g = cmap.get ( Integer.valueOf ( c ) ); + if ( g != null ) { + return (int) g; + } else { + return -1; + } + } else { + return -1; + } + } + public int getGlyph ( String gid ) { + return mapGlyphId0 ( gid ); + } + public GlyphSequence getGlyphSequence ( String[] gids ) { + assert gids != null; + int ng = gids.length; + IntBuffer cb = IntBuffer.allocate ( ng ); + IntBuffer gb = IntBuffer.allocate ( ng ); + for ( String gid : gids ) { + int g = mapGlyphId0 ( gid ); + if ( g >= 0 ) { + int c = mapGlyphIdToChar ( gid ); + if ( c < 0 ) { + c = CharUtilities.NOT_A_CHARACTER; + } + cb.put ( c ); + gb.put ( g ); + } else { + throw new IllegalArgumentException ( "unmapped glyph id \"" + gid + "\"" ); + } + } + cb.rewind(); + gb.rewind(); + return new GlyphSequence ( cb, gb, null ); + } + public int[] getWidths ( String[] gids ) { + assert gids != null; + int ng = gids.length; + int[] widths = new int [ ng ]; + int i = 0; + for ( String gid : gids ) { + int g = mapGlyphId0 ( gid ); + int w = 0; + if ( g >= 0 ) { + if ( ( hmtx != null ) && ( g < hmtx.length ) ) { + int[] mtx = hmtx [ g ]; + assert mtx != null; + assert mtx.length > 0; + w = mtx[0]; + } + } + widths [ i++ ] = w; + } + assert i == ng; + return widths; + } + public int[] getWidths() { + if ( this.widths == null ) { + if ( ( hmtx != null ) && ( upem > 0 ) ) { + int[] widths = new int [ hmtx.length ]; + for ( int i = 0, n = widths.length; i < n; i++ ) { + widths [ i ] = getPDFWidth ( hmtx [ i ] [ 0 ], upem ); + } + this.widths = widths; + } + } + return this.widths; + } + public static int getPDFWidth ( int tw, int upem ) { + // N.B. The following is copied (with minor edits) from TTFFile to insure same results + int pw; + if ( tw < 0 ) { + long rest1 = tw % upem; + long storrest = 1000 * rest1; + long ledd2 = ( storrest != 0 ) ? ( rest1 / storrest ) : 0; + pw = - ( ( -1000 * tw ) / upem - (int) ledd2 ); + } else { + pw = ( tw / upem ) * 1000 + ( ( tw % upem ) * 1000 ) / upem; + } + return pw; + } + public GlyphDefinitionTable getGDEF() { + return gdef; + } + public GlyphSubstitutionTable getGSUB() { + return gsub; + } + public GlyphPositioningTable getGPOS() { + return gpos; + } + public static synchronized TTXFile getFromCache ( String filename ) { + assert cache != null; + TTXFile f; + if ( ( f = (TTXFile) cache.get ( filename ) ) == null ) { + f = new TTXFile(); + f.parse ( filename ); + cache.put ( filename, f ); + } + return f; + } + public static synchronized void clearCache() { + cache.clear(); + } + private class Handler extends DefaultHandler { + private Handler() { + } + @Override + public void startDocument() { + } + @Override + public void endDocument() { + } + @Override + public void setDocumentLocator ( Locator locator ) { + TTXFile.this.locator = locator; + } + @Override + public void startElement ( String uri, String localName, String qName, Attributes attrs ) throws SAXException { + String[] en = makeExpandedName ( uri, localName, qName ); + if ( en[0] != null ) { + unsupportedElement ( en ); + } else if ( en[1].equals ( "Alternate" ) ) { + String[] pn = new String[] { null, "AlternateSet" }; + if ( isParent ( pn ) ) { + String glyph = attrs.getValue ( "glyph" ); + if ( glyph == null ) { + missingRequiredAttribute ( en, "glyph" ); + } + int gid = mapGlyphId ( glyph, en ); + alternates.add ( Integer.valueOf ( gid ) ); + } else { + notPermittedInElementContext ( en, getParent(), pn ); + } + } else if ( en[1].equals ( "AlternateSet" ) ) { + String[] pn = new String[] { null, "AlternateSubst" }; + if ( isParent ( pn ) ) { + String glyph = attrs.getValue ( "glyph" ); + if ( glyph == null ) { + missingRequiredAttribute ( en, "glyph" ); + } + int gid = mapGlyphId ( glyph, en ); + coverageEntries.add ( Integer.valueOf ( gid ) ); + } else { + notPermittedInElementContext ( en, getParent(), pn ); + } + } else if ( en[1].equals ( "AlternateSubst" ) ) { + String[] pn = new String[] { null, "Lookup" }; + if ( isParent ( pn ) ) { + String index = attrs.getValue ( "index" ); + if ( index == null ) { + missingRequiredAttribute ( en, "index" ); + } + String format = attrs.getValue ( "Format" ); + int sf = -1; + if ( format == null ) { + missingRequiredAttribute ( en, "Format" ); + } else { + sf = Integer.parseInt ( format ); + switch ( sf ) { + case 1: + break; + default: + unsupportedFormat ( en, sf ); + break; + } + } + assertCoverageClear(); + ctIndex = 0; + ctFormat = 1; + assertSubtableClear(); + assert sf >= 0; + stFormat = sf; + } else { + notPermittedInElementContext ( en, getParent(), pn ); + } + } else if ( en[1].equals ( "BacktrackCoverage" ) ) { + String[] pn1 = new String[] { null, "ChainContextSubst" }; + String[] pn2 = new String[] { null, "ChainContextPos" }; + String[][] pnx = new String[][] { pn1, pn2 }; + if ( isParent ( pnx ) ) { + String index = attrs.getValue ( "index" ); + int ci = -1; + if ( index == null ) { + missingRequiredAttribute ( en, "index" ); + } else { + ci = Integer.parseInt ( index ); + } + String format = attrs.getValue ( "Format" ); + int cf = -1; + if ( format == null ) { + missingRequiredAttribute ( en, "Format" ); + } else { + cf = Integer.parseInt ( format ); + switch ( cf ) { + case 1: + case 2: + break; + default: + unsupportedFormat ( en, cf ); + break; + } + } + assertCoverageClear(); + ctIndex = ci; + ctFormat = cf; + } else { + notPermittedInElementContext ( en, getParent(), pnx ); + } + } else if ( en[1].equals ( "BaseAnchor" ) ) { + String[] pn = new String[] { null, "BaseRecord" }; + if ( isParent ( pn ) ) { + String index = attrs.getValue ( "index" ); + if ( index == null ) { + missingRequiredAttribute ( en, "index" ); + } + String format = attrs.getValue ( "Format" ); + if ( format == null ) { + missingRequiredAttribute ( en, "Format" ); + } + assert xCoord == Integer.MIN_VALUE; + assert yCoord == Integer.MIN_VALUE; + } else { + notPermittedInElementContext ( en, getParent(), pn ); + } + } else if ( en[1].equals ( "BaseArray" ) ) { + String[] pn = new String[] { null, "MarkBasePos" }; + if ( ! isParent ( pn ) ) { + notPermittedInElementContext ( en, getParent(), pn ); + } + } else if ( en[1].equals ( "BaseCoverage" ) ) { + String[] pn = new String[] { null, "MarkBasePos" }; + if ( isParent ( pn ) ) { + String format = attrs.getValue ( "Format" ); + int cf = -1; + if ( format == null ) { + missingRequiredAttribute ( en, "Format" ); + } else { + cf = Integer.parseInt ( format ); + switch ( cf ) { + case 1: + case 2: + break; + default: + unsupportedFormat ( en, cf ); + break; + } + } + assertCoverageClear(); + ctIndex = 0; + ctFormat = cf; + } else { + notPermittedInElementContext ( en, getParent(), pn ); + } + } else if ( en[1].equals ( "BaseRecord" ) ) { + String[] pn = new String[] { null, "BaseArray" }; + if ( isParent ( pn ) ) { + String index = attrs.getValue ( "index" ); + if ( index == null ) { + missingRequiredAttribute ( en, "index" ); + } + } else { + notPermittedInElementContext ( en, getParent(), pn ); + } + } else if ( en[1].equals ( "ChainContextPos" ) || en[1].equals ( "ChainContextSubst" ) ) { + String[] pn = new String[] { null, "Lookup" }; + if ( isParent ( pn ) ) { + String index = attrs.getValue ( "index" ); + if ( index == null ) { + missingRequiredAttribute ( en, "index" ); + } + String format = attrs.getValue ( "Format" ); + int sf = -1; + if ( format == null ) { + missingRequiredAttribute ( en, "Format" ); + } else { + sf = Integer.parseInt ( format ); + switch ( sf ) { + case 1: + case 2: + case 3: + break; + default: + unsupportedFormat ( en, sf ); + break; + } + } + assertSubtableClear(); + assert sf >= 0; + stFormat = sf; + } else { + notPermittedInElementContext ( en, getParent(), pn ); + } + } else if ( en[1].equals ( "Class" ) ) { + String[] pn = new String[] { null, "MarkRecord" }; + if ( isParent ( pn ) ) { + String value = attrs.getValue ( "value" ); + int v = -1; + if ( value == null ) { + missingRequiredAttribute ( en, "value" ); + } else { + v = Integer.parseInt ( value ); + } + assert markClass == -1; + markClass = v; + } else { + notPermittedInElementContext ( en, getParent(), pn ); + } + } else if ( en[1].equals ( "ClassDef" ) ) { + String[] pn1 = new String[] { null, "GlyphClassDef" }; + String[] pn2 = new String[] { null, "MarkAttachClassDef" }; + String[][] pnx = new String[][] { pn1, pn2 }; + if ( isParent ( pnx ) ) { + String glyph = attrs.getValue ( "glyph" ); + if ( glyph == null ) { + missingRequiredAttribute ( en, "glyph" ); + } + String glyphClass = attrs.getValue ( "class" ); + if ( glyphClass == null ) { + missingRequiredAttribute ( en, "class" ); + } + if ( ! glyphIds.containsKey ( glyph ) ) { + unsupportedGlyph ( en, glyph ); + } else if ( isParent ( pn1 ) ) { + if ( glyphClasses.containsKey ( glyph ) ) { + duplicateGlyphClass ( en, glyph, glyphClass ); + } else { + glyphClasses.put ( glyph, Integer.parseInt(glyphClass) ); + } + } else if ( isParent ( pn2 ) ) { + if ( glyphClasses.containsKey ( glyph ) ) { + duplicateGlyphClass ( en, glyph, glyphClass ); + } else { + glyphClasses.put ( glyph, Integer.parseInt(glyphClass) ); + } + } + } else { + notPermittedInElementContext ( en, getParent(), pnx ); + } + } else if ( en[1].equals ( "ComponentRecord" ) ) { + String[] pn = new String[] { null, "LigatureAttach" }; + if ( isParent ( pn ) ) { + String index = attrs.getValue ( "index" ); + if ( index == null ) { + missingRequiredAttribute ( en, "index" ); + } + assert anchors.size() == 0; + } else { + notPermittedInElementContext ( en, getParent(), pn ); + } + } else if ( en[1].equals ( "Coverage" ) ) { + String[] pn1 = new String[] { null, "CursivePos" }; + String[] pn2 = new String[] { null, "LigCaretList" }; + String[] pn3 = new String[] { null, "MultipleSubst" }; + String[] pn4 = new String[] { null, "PairPos" }; + String[] pn5 = new String[] { null, "SinglePos" }; + String[][] pnx = new String[][] { pn1, pn2, pn3, pn4, pn5 }; + if ( isParent ( pnx ) ) { + String format = attrs.getValue ( "Format" ); + int cf = -1; + if ( format == null ) { + missingRequiredAttribute ( en, "Format" ); + } else { + cf = Integer.parseInt ( format ); + switch ( cf ) { + case 1: + case 2: + break; + default: + unsupportedFormat ( en, cf ); + break; + } + } + assertCoverageClear(); + ctIndex = 0; + ctFormat = cf; + } else { + notPermittedInElementContext ( en, getParent(), pnx ); + } + } else if ( en[1].equals ( "CursivePos" ) ) { + String[] pn = new String[] { null, "Lookup" }; + if ( isParent ( pn ) ) { + String index = attrs.getValue ( "index" ); + if ( index == null ) { + missingRequiredAttribute ( en, "index" ); + } + String format = attrs.getValue ( "Format" ); + int sf = -1; + if ( format == null ) { + missingRequiredAttribute ( en, "Format" ); + } else { + sf = Integer.parseInt ( format ); + switch ( sf ) { + case 1: + break; + default: + unsupportedFormat ( en, sf ); + break; + } + } + assertSubtableClear(); + assert sf >= 0; + stFormat = sf; + assert attachmentAnchors.size() == 0; + } else { + notPermittedInElementContext ( en, getParent(), pn ); + } + } else if ( en[1].equals ( "DefaultLangSys" ) ) { + String[] pn = new String[] { null, "Script" }; + if ( ! isParent ( pn ) ) { + notPermittedInElementContext ( en, getParent(), pn ); + } else { + assertLanguageFeaturesClear(); + assert languageTag == null; + languageTag = defaultLanguageTag; + } + } else if ( en[1].equals ( "EntryAnchor" ) ) { + String[] pn = new String[] { null, "EntryExitRecord" }; + if ( isParent ( pn ) ) { + String format = attrs.getValue ( "Format" ); + if ( format == null ) { + missingRequiredAttribute ( en, "Format" ); + } + assert xCoord == Integer.MIN_VALUE; + assert yCoord == Integer.MIN_VALUE; + } else { + notPermittedInElementContext ( en, getParent(), pn ); + } + } else if ( en[1].equals ( "EntryExitRecord" ) ) { + String[] pn = new String[] { null, "CursivePos" }; + if ( isParent ( pn ) ) { + String index = attrs.getValue ( "index" ); + if ( index == null ) { + missingRequiredAttribute ( en, "index" ); + } + } else { + notPermittedInElementContext ( en, getParent(), pn ); + } + } else if ( en[1].equals ( "ExitAnchor" ) ) { + String[] pn = new String[] { null, "EntryExitRecord" }; + if ( isParent ( pn ) ) { + String format = attrs.getValue ( "Format" ); + if ( format == null ) { + missingRequiredAttribute ( en, "Format" ); + } + assert xCoord == Integer.MIN_VALUE; + assert yCoord == Integer.MIN_VALUE; + } else { + notPermittedInElementContext ( en, getParent(), pn ); + } + } else if ( en[1].equals ( "Feature" ) ) { + String[] pn = new String[] { null, "FeatureRecord" }; + if ( ! isParent ( pn ) ) { + notPermittedInElementContext ( en, getParent(), pn ); + } else { + assertFeatureLookupsClear(); + } + } else if ( en[1].equals ( "FeatureIndex" ) ) { + String[] pn1 = new String[] { null, "DefaultLangSys" }; + String[] pn2 = new String[] { null, "LangSys" }; + String[][] pnx = new String[][] { pn1, pn2 }; + if ( isParent ( pnx ) ) { + String index = attrs.getValue ( "index" ); + if ( index == null ) { + missingRequiredAttribute ( en, "index" ); + } + String value = attrs.getValue ( "value" ); + int v = -1; + if ( value == null ) { + missingRequiredAttribute ( en, "value" ); + } else { + v = Integer.parseInt ( value ); + } + if ( languageFeatures.size() == 0 ) { + languageFeatures.add ( null ); + } + if ( ( v >= 0 ) && ( v < 65535 ) ) { + languageFeatures.add ( makeFeatureId ( v ) ); + } + } else { + notPermittedInElementContext ( en, getParent(), pnx ); + } + } else if ( en[1].equals ( "FeatureList" ) ) { + String[] pn1 = new String[] { null, "GSUB" }; + String[] pn2 = new String[] { null, "GPOS" }; + String[][] pnx = new String[][] { pn1, pn2 }; + if ( ! isParent ( pnx ) ) { + notPermittedInElementContext ( en, getParent(), pnx ); + } + } else if ( en[1].equals ( "FeatureRecord" ) ) { + String[] pn = new String[] { null, "FeatureList" }; + if ( isParent ( pn ) ) { + String index = attrs.getValue ( "index" ); + int fi = -1; + if ( index == null ) { + missingRequiredAttribute ( en, "index" ); + } else { + fi = Integer.parseInt ( index ); + } + assertFeatureClear(); + assert flIndex == -1; + flIndex = fi; + } else { + notPermittedInElementContext ( en, getParent(), pn ); + } + } else if ( en[1].equals ( "FeatureTag" ) ) { + String[] pn = new String[] { null, "FeatureRecord" }; + if ( isParent ( pn ) ) { + String value = attrs.getValue ( "value" ); + if ( value == null ) { + missingRequiredAttribute ( en, "value" ); + } else { + assert featureTag == null; + featureTag = value; + } + } else { + notPermittedInElementContext ( en, getParent(), pn ); + } + } else if ( en[1].equals ( "GDEF" ) ) { + String[] pn = new String[] { null, "ttFont" }; + if ( isParent ( pn ) ) { + assertSubtablesClear(); + } else { + notPermittedInElementContext ( en, getParent(), pn ); + } + } else if ( en[1].equals ( "GPOS" ) ) { + String[] pn = new String[] { null, "ttFont" }; + if ( isParent ( pn ) ) { + assertCoveragesClear(); + assertSubtablesClear(); + } else { + notPermittedInElementContext ( en, getParent(), pn ); + } + } else if ( en[1].equals ( "GSUB" ) ) { + String[] pn = new String[] { null, "ttFont" }; + if ( isParent ( pn ) ) { + assertCoveragesClear(); + assertSubtablesClear(); + } else { + notPermittedInElementContext ( en, getParent(), pn ); + } + } else if ( en[1].equals ( "Glyph" ) ) { + String[] pn1 = new String[] { null, "Coverage" }; + String[] pn2 = new String[] { null, "InputCoverage" }; + String[] pn3 = new String[] { null, "LookAheadCoverage" }; + String[] pn4 = new String[] { null, "BacktrackCoverage" }; + String[] pn5 = new String[] { null, "MarkCoverage" }; + String[] pn6 = new String[] { null, "Mark1Coverage" }; + String[] pn7 = new String[] { null, "Mark2Coverage" }; + String[] pn8 = new String[] { null, "BaseCoverage" }; + String[] pn9 = new String[] { null, "LigatureCoverage" }; + String[][] pnx = new String[][] { pn1, pn2, pn3, pn4, pn5, pn6, pn7, pn8, pn9 }; + if ( isParent ( pnx ) ) { + String value = attrs.getValue ( "value" ); + if ( value == null ) { + missingRequiredAttribute ( en, "value" ); + } else { + int gid = mapGlyphId ( value, en ); + coverageEntries.add ( Integer.valueOf ( gid ) ); + } + } else { + notPermittedInElementContext ( en, getParent(), pnx ); + } + } else if ( en[1].equals ( "GlyphClassDef" ) ) { + String[] pn = new String[] { null, "GDEF" }; + if ( isParent ( pn ) ) { + String format = attrs.getValue ( "Format" ); + int sf = -1; + if ( format == null ) { + missingRequiredAttribute ( en, "Format" ); + } else { + sf = Integer.parseInt ( format ); + switch ( sf ) { + case 1: + case 2: + break; + default: + unsupportedFormat ( en, sf ); + break; + } + } + assertSubtableClear(); + assert sf >= 0; + // force format 1 since TTX always writes entries as non-range entries + if ( sf != 1 ) { + sf = 1; + } + stFormat = sf; + assert glyphClasses.isEmpty(); + } else { + notPermittedInElementContext ( en, getParent(), pn ); + } + } else if ( en[1].equals ( "GlyphID" ) ) { + String[] pn = new String[] { null, "GlyphOrder" }; + if ( isParent ( pn ) ) { + String id = attrs.getValue ( "id" ); + int gid = -1; + if ( id == null ) { + missingRequiredAttribute ( en, "id" ); + } else { + gid = Integer.parseInt ( id ); + } + String name = attrs.getValue ( "name" ); + if ( name == null ) { + missingRequiredAttribute ( en, "name" ); + } + if ( glyphIds.containsKey ( name ) ) { + duplicateGlyph ( en, name, gid ); + } else { + if ( gid > glyphIdMax ) { + glyphIdMax = gid; + } + glyphIds.put ( name, gid ); + } + } else { + notPermittedInElementContext ( en, getParent(), pn ); + } + } else if ( en[1].equals ( "GlyphOrder" ) ) { + String[] pn = new String[] { null, "ttFont" }; + if ( ! isParent ( pn ) ) { + notPermittedInElementContext ( en, getParent(), pn ); + } + } else if ( en[1].equals ( "InputCoverage" ) ) { + String[] pn1 = new String[] { null, "ChainContextSubst" }; + String[] pn2 = new String[] { null, "ChainContextPos" }; + String[][] pnx = new String[][] { pn1, pn2 }; + if ( isParent ( pnx ) ) { + String index = attrs.getValue ( "index" ); + int ci = -1; + if ( index == null ) { + missingRequiredAttribute ( en, "index" ); + } else { + ci = Integer.parseInt ( index ); + } + String format = attrs.getValue ( "Format" ); + int cf = -1; + if ( format == null ) { + missingRequiredAttribute ( en, "Format" ); + } else { + cf = Integer.parseInt ( format ); + switch ( cf ) { + case 1: + case 2: + break; + default: + unsupportedFormat ( en, cf ); + break; + } + } + assertCoverageClear(); + ctIndex = ci; + ctFormat = cf; + } else { + notPermittedInElementContext ( en, getParent(), pnx ); + } + } else if ( en[1].equals ( "LangSys" ) ) { + String[] pn = new String[] { null, "LangSysRecord" }; + if ( ! isParent ( pn ) ) { + notPermittedInElementContext ( en, getParent(), pn ); + } else { + assertLanguageFeaturesClear(); + } + } else if ( en[1].equals ( "LangSysRecord" ) ) { + String[] pn = new String[] { null, "Script" }; + if ( isParent ( pn ) ) { + String index = attrs.getValue ( "index" ); + if ( index == null ) { + missingRequiredAttribute ( en, "index" ); + } + } else { + notPermittedInElementContext ( en, getParent(), pn ); + } + } else if ( en[1].equals ( "LangSysTag" ) ) { + String[] pn = new String[] { null, "LangSysRecord" }; + if ( isParent ( pn ) ) { + String value = attrs.getValue ( "value" ); + if ( value == null ) { + missingRequiredAttribute ( en, "value" ); + } else { + assert languageTag == null; + languageTag = value; + } + } else { + notPermittedInElementContext ( en, getParent(), pn ); + } + } else if ( en[1].equals ( "LigCaretList" ) ) { + String[] pn = new String[] { null, "GDEF" }; + if ( ! isParent ( pn ) ) { + notPermittedInElementContext ( en, getParent(), pn ); + } + } else if ( en[1].equals ( "Ligature" ) ) { + String[] pn = new String[] { null, "LigatureSet" }; + if ( isParent ( pn ) ) { + String components = attrs.getValue ( "components" ); + if ( components == null ) { + missingRequiredAttribute ( en, "components" ); + } + int[] cids = mapGlyphIds ( components, en ); + String glyph = attrs.getValue ( "glyph" ); + if ( glyph == null ) { + missingRequiredAttribute ( en, "glyph" ); + } + int gid = mapGlyphId ( glyph, en ); + ligatures.add ( new Ligature ( gid, cids ) ); + } else { + notPermittedInElementContext ( en, getParent(), pn ); + } + } else if ( en[1].equals ( "LigatureAnchor" ) ) { + String[] pn = new String[] { null, "ComponentRecord" }; + if ( isParent ( pn ) ) { + String index = attrs.getValue ( "index" ); + if ( index == null ) { + missingRequiredAttribute ( en, "index" ); + } + String format = attrs.getValue ( "Format" ); + if ( format == null ) { + missingRequiredAttribute ( en, "Format" ); + } + assert xCoord == Integer.MIN_VALUE; + assert yCoord == Integer.MIN_VALUE; + } else { + notPermittedInElementContext ( en, getParent(), pn ); + } + } else if ( en[1].equals ( "LigatureArray" ) ) { + String[] pn = new String[] { null, "MarkLigPos" }; + if ( ! isParent ( pn ) ) { + notPermittedInElementContext ( en, getParent(), pn ); + } + } else if ( en[1].equals ( "LigatureAttach" ) ) { + String[] pn = new String[] { null, "LigatureArray" }; + if ( isParent ( pn ) ) { + String index = attrs.getValue ( "index" ); + if ( index == null ) { + missingRequiredAttribute ( en, "index" ); + } + assert components.size() == 0; + } else { + notPermittedInElementContext ( en, getParent(), pn ); + } + } else if ( en[1].equals ( "LigatureCoverage" ) ) { + String[] pn = new String[] { null, "MarkLigPos" }; + if ( isParent ( pn ) ) { + String format = attrs.getValue ( "Format" ); + int cf = -1; + if ( format == null ) { + missingRequiredAttribute ( en, "Format" ); + } else { + cf = Integer.parseInt ( format ); + switch ( cf ) { + case 1: + case 2: + break; + default: + unsupportedFormat ( en, cf ); + break; + } + } + assertCoverageClear(); + ctIndex = 0; + ctFormat = cf; + } else { + notPermittedInElementContext ( en, getParent(), pn ); + } + } else if ( en[1].equals ( "LigatureSet" ) ) { + String[] pn = new String[] { null, "LigatureSubst" }; + if ( isParent ( pn ) ) { + String glyph = attrs.getValue ( "glyph" ); + if ( glyph == null ) { + missingRequiredAttribute ( en, "glyph" ); + } + int gid = mapGlyphId ( glyph, en ); + coverageEntries.add ( Integer.valueOf ( gid ) ); + } else { + notPermittedInElementContext ( en, getParent(), pn ); + } + } else if ( en[1].equals ( "LigatureSubst" ) ) { + String[] pn = new String[] { null, "Lookup" }; + if ( isParent ( pn ) ) { + String index = attrs.getValue ( "index" ); + if ( index == null ) { + missingRequiredAttribute ( en, "index" ); + } + String format = attrs.getValue ( "Format" ); + int sf = -1; + if ( format == null ) { + missingRequiredAttribute ( en, "Format" ); + } else { + sf = Integer.parseInt ( format ); + switch ( sf ) { + case 1: + break; + default: + unsupportedFormat ( en, sf ); + break; + } + } + assertCoverageClear(); + ctIndex = 0; + ctFormat = 1; + assertSubtableClear(); + assert sf >= 0; + stFormat = sf; + } else { + notPermittedInElementContext ( en, getParent(), pn ); + } + } else if ( en[1].equals ( "LookAheadCoverage" ) ) { + String[] pn1 = new String[] { null, "ChainContextSubst" }; + String[] pn2 = new String[] { null, "ChainContextPos" }; + String[][] pnx = new String[][] { pn1, pn2 }; + if ( isParent ( pnx ) ) { + String index = attrs.getValue ( "index" ); + int ci = -1; + if ( index == null ) { + missingRequiredAttribute ( en, "index" ); + } else { + ci = Integer.parseInt ( index ); + } + String format = attrs.getValue ( "Format" ); + int cf = -1; + if ( format == null ) { + missingRequiredAttribute ( en, "Format" ); + } else { + cf = Integer.parseInt ( format ); + switch ( cf ) { + case 1: + case 2: + break; + default: + unsupportedFormat ( en, cf ); + break; + } + } + assertCoverageClear(); + ctIndex = ci; + ctFormat = cf; + } else { + notPermittedInElementContext ( en, getParent(), pnx ); + } + } else if ( en[1].equals ( "Lookup" ) ) { + String[] pn = new String[] { null, "LookupList" }; + if ( isParent ( pn ) ) { + String index = attrs.getValue ( "index" ); + int li = -1; + if ( index == null ) { + missingRequiredAttribute ( en, "index" ); + } else { + li = Integer.parseInt ( index ); + } + assertLookupClear(); + assert ltIndex == -1; + ltIndex = li; + } else { + notPermittedInElementContext ( en, getParent(), pn ); + } + } else if ( en[1].equals ( "LookupFlag" ) ) { + String[] pn = new String[] { null, "Lookup" }; + if ( isParent ( pn ) ) { + String value = attrs.getValue ( "value" ); + int lf = 0; + if ( value == null ) { + missingRequiredAttribute ( en, "value" ); + } else { + lf = Integer.parseInt ( value ); + } + assert ltFlags == 0; + ltFlags = lf; + } else { + notPermittedInElementContext ( en, getParent(), pn ); + } + } else if ( en[1].equals ( "LookupList" ) ) { + String[] pn1 = new String[] { null, "GSUB" }; + String[] pn2 = new String[] { null, "GPOS" }; + String[][] pnx = new String[][] { pn1, pn2 }; + if ( ! isParent ( pnx ) ) { + notPermittedInElementContext ( en, getParent(), pnx ); + } + } else if ( en[1].equals ( "LookupListIndex" ) ) { + String[] pn1 = new String[] { null, "Feature" }; + String[] pn2 = new String[] { null, "SubstLookupRecord" }; + String[] pn3 = new String[] { null, "PosLookupRecord" }; + String[][] pnx = new String[][] { pn1, pn2, pn3 }; + if ( isParent ( pnx ) ) { + String index = attrs.getValue ( "index" ); + String value = attrs.getValue ( "value" ); + int v = -1; + if ( value == null ) { + missingRequiredAttribute ( en, "value" ); + } else { + v = Integer.parseInt ( value ); + } + String[][] pny = new String[][] { pn2, pn3 }; + if ( isParent ( pny ) ) { + assert rlLookup == -1; + assert v != -1; + rlLookup = v; + } else { + featureLookups.add ( makeLookupId ( v ) ); + } + } else { + notPermittedInElementContext ( en, getParent(), pnx ); + } + } else if ( en[1].equals ( "LookupType" ) ) { + String[] pn = new String[] { null, "Lookup" }; + if ( isParent ( pn ) ) { + String value = attrs.getValue ( "value" ); + if ( value == null ) { + missingRequiredAttribute ( en, "value" ); + } + } else { + notPermittedInElementContext ( en, getParent(), pn ); + } + } else if ( en[1].equals ( "Mark1Array" ) ) { + String[] pn = new String[] { null, "MarkMarkPos" }; + if ( ! isParent ( pn ) ) { + notPermittedInElementContext ( en, getParent(), pn ); + } + } else if ( en[1].equals ( "Mark1Coverage" ) ) { + String[] pn = new String[] { null, "MarkMarkPos" }; + if ( isParent ( pn ) ) { + String format = attrs.getValue ( "Format" ); + int cf = -1; + if ( format == null ) { + missingRequiredAttribute ( en, "Format" ); + } else { + cf = Integer.parseInt ( format ); + switch ( cf ) { + case 1: + case 2: + break; + default: + unsupportedFormat ( en, cf ); + break; + } + } + assertCoverageClear(); + ctIndex = 0; + ctFormat = cf; + } else { + notPermittedInElementContext ( en, getParent(), pn ); + } + } else if ( en[1].equals ( "Mark2Anchor" ) ) { + String[] pn = new String[] { null, "Mark2Record" }; + if ( isParent ( pn ) ) { + String format = attrs.getValue ( "Format" ); + if ( format == null ) { + missingRequiredAttribute ( en, "Format" ); + } + assert xCoord == Integer.MIN_VALUE; + assert yCoord == Integer.MIN_VALUE; + } else { + notPermittedInElementContext ( en, getParent(), pn ); + } + } else if ( en[1].equals ( "Mark2Array" ) ) { + String[] pn = new String[] { null, "MarkMarkPos" }; + if ( ! isParent ( pn ) ) { + notPermittedInElementContext ( en, getParent(), pn ); + } + } else if ( en[1].equals ( "Mark2Coverage" ) ) { + String[] pn = new String[] { null, "MarkMarkPos" }; + if ( isParent ( pn ) ) { + String format = attrs.getValue ( "Format" ); + int cf = -1; + if ( format == null ) { + missingRequiredAttribute ( en, "Format" ); + } else { + cf = Integer.parseInt ( format ); + switch ( cf ) { + case 1: + case 2: + break; + default: + unsupportedFormat ( en, cf ); + break; + } + } + assertCoverageClear(); + ctIndex = 0; + ctFormat = cf; + } else { + notPermittedInElementContext ( en, getParent(), pn ); + } + } else if ( en[1].equals ( "Mark2Record" ) ) { + String[] pn = new String[] { null, "Mark2Array" }; + if ( isParent ( pn ) ) { + String index = attrs.getValue ( "index" ); + if ( index == null ) { + missingRequiredAttribute ( en, "index" ); + } + } else { + notPermittedInElementContext ( en, getParent(), pn ); + } + } else if ( en[1].equals ( "MarkAnchor" ) ) { + String[] pn = new String[] { null, "MarkRecord" }; + if ( isParent ( pn ) ) { + String format = attrs.getValue ( "Format" ); + if ( format == null ) { + missingRequiredAttribute ( en, "Format" ); + } + assert xCoord == Integer.MIN_VALUE; + assert yCoord == Integer.MIN_VALUE; + } else { + notPermittedInElementContext ( en, getParent(), pn ); + } + } else if ( en[1].equals ( "MarkArray" ) ) { + String[] pn1 = new String[] { null, "MarkBasePos" }; + String[] pn2 = new String[] { null, "MarkLigPos" }; + String[][] pnx = new String[][] { pn1, pn2 }; + if ( ! isParent ( pnx ) ) { + notPermittedInElementContext ( en, getParent(), pnx ); + } + } else if ( en[1].equals ( "MarkAttachClassDef" ) ) { + String[] pn = new String[] { null, "GDEF" }; + if ( isParent ( pn ) ) { + String format = attrs.getValue ( "Format" ); + int sf = -1; + if ( format == null ) { + missingRequiredAttribute ( en, "Format" ); + } else { + sf = Integer.parseInt ( format ); + switch ( sf ) { + case 1: + case 2: + break; + default: + unsupportedFormat ( en, sf ); + break; + } + } + assertSubtableClear(); + assert sf >= 0; + // force format 1 since TTX always writes entries as non-range entries + if ( sf != 1 ) { + sf = 1; + } + stFormat = sf; + assert glyphClasses.isEmpty(); + } else { + notPermittedInElementContext ( en, getParent(), pn ); + } + } else if ( en[1].equals ( "MarkBasePos" ) ) { + String[] pn = new String[] { null, "Lookup" }; + if ( isParent ( pn ) ) { + String index = attrs.getValue ( "index" ); + if ( index == null ) { + missingRequiredAttribute ( en, "index" ); + } + String format = attrs.getValue ( "Format" ); + int sf = -1; + if ( format == null ) { + missingRequiredAttribute ( en, "Format" ); + } else { + sf = Integer.parseInt ( format ); + switch ( sf ) { + case 1: + break; + default: + unsupportedFormat ( en, sf ); + break; + } + } + assertSubtableClear(); + assert sf >= 0; + stFormat = sf; + assert markAnchors.size() == 0; + assert baseOrMarkAnchors.size() == 0; + } else { + notPermittedInElementContext ( en, getParent(), pn ); + } + } else if ( en[1].equals ( "MarkCoverage" ) ) { + String[] pn1 = new String[] { null, "MarkBasePos" }; + String[] pn2 = new String[] { null, "MarkLigPos" }; + String[][] pnx = new String[][] { pn1, pn2 }; + if ( isParent ( pnx ) ) { + String format = attrs.getValue ( "Format" ); + int cf = -1; + if ( format == null ) { + missingRequiredAttribute ( en, "Format" ); + } else { + cf = Integer.parseInt ( format ); + switch ( cf ) { + case 1: + case 2: + break; + default: + unsupportedFormat ( en, cf ); + break; + } + } + assertCoverageClear(); + ctIndex = 0; + ctFormat = cf; + } else { + notPermittedInElementContext ( en, getParent(), pnx ); + } + } else if ( en[1].equals ( "MarkLigPos" ) ) { + String[] pn = new String[] { null, "Lookup" }; + if ( isParent ( pn ) ) { + String index = attrs.getValue ( "index" ); + if ( index == null ) { + missingRequiredAttribute ( en, "index" ); + } + String format = attrs.getValue ( "Format" ); + int sf = -1; + if ( format == null ) { + missingRequiredAttribute ( en, "Format" ); + } else { + sf = Integer.parseInt ( format ); + switch ( sf ) { + case 1: + break; + default: + unsupportedFormat ( en, sf ); + break; + } + } + assertSubtableClear(); + assert sf >= 0; + stFormat = sf; + assert markAnchors.size() == 0; + assert ligatureAnchors.size() == 0; + } else { + notPermittedInElementContext ( en, getParent(), pn ); + } + } else if ( en[1].equals ( "MarkMarkPos" ) ) { + String[] pn = new String[] { null, "Lookup" }; + if ( isParent ( pn ) ) { + String index = attrs.getValue ( "index" ); + if ( index == null ) { + missingRequiredAttribute ( en, "index" ); + } + String format = attrs.getValue ( "Format" ); + int sf = -1; + if ( format == null ) { + missingRequiredAttribute ( en, "Format" ); + } else { + sf = Integer.parseInt ( format ); + switch ( sf ) { + case 1: + break; + default: + unsupportedFormat ( en, sf ); + break; + } + } + assertSubtableClear(); + assert sf >= 0; + stFormat = sf; + assert markAnchors.size() == 0; + assert baseOrMarkAnchors.size() == 0; + } else { + notPermittedInElementContext ( en, getParent(), pn ); + } + } else if ( en[1].equals ( "MarkRecord" ) ) { + String[] pn1 = new String[] { null, "MarkArray" }; + String[] pn2 = new String[] { null, "Mark1Array" }; + String[][] pnx = new String[][] { pn1, pn2 }; + if ( isParent ( pnx ) ) { + String index = attrs.getValue ( "index" ); + if ( index == null ) { + missingRequiredAttribute ( en, "index" ); + } + } else { + notPermittedInElementContext ( en, getParent(), pnx ); + } + } else if ( en[1].equals ( "MultipleSubst" ) ) { + String[] pn = new String[] { null, "Lookup" }; + if ( isParent ( pn ) ) { + String index = attrs.getValue ( "index" ); + if ( index == null ) { + missingRequiredAttribute ( en, "index" ); + } + String format = attrs.getValue ( "Format" ); + int sf = -1; + if ( format == null ) { + missingRequiredAttribute ( en, "Format" ); + } else { + sf = Integer.parseInt ( format ); + switch ( sf ) { + case 1: + break; + default: + unsupportedFormat ( en, sf ); + break; + } + } + assertSubtableClear(); + assert sf >= 0; + stFormat = sf; + } else { + notPermittedInElementContext ( en, getParent(), pn ); + } + } else if ( en[1].equals ( "PairPos" ) ) { + String[] pn = new String[] { null, "Lookup" }; + if ( isParent ( pn ) ) { + String index = attrs.getValue ( "index" ); + if ( index == null ) { + missingRequiredAttribute ( en, "index" ); + } + String format = attrs.getValue ( "Format" ); + int sf = -1; + if ( format == null ) { + missingRequiredAttribute ( en, "Format" ); + } else { + sf = Integer.parseInt ( format ); + switch ( sf ) { + case 1: + case 2: + break; + default: + unsupportedFormat ( en, sf ); + break; + } + } + assertSubtableClear(); + assert sf >= 0; + stFormat = sf; + } else { + notPermittedInElementContext ( en, getParent(), pn ); + } + } else if ( en[1].equals ( "PairSet" ) ) { + String[] pn = new String[] { null, "PairPos" }; + if ( isParent ( pn ) ) { + String index = attrs.getValue ( "index" ); + int psi = -1; + if ( index == null ) { + missingRequiredAttribute ( en, "index" ); + } else { + psi = Integer.parseInt ( index ); + } + assert psIndex == -1; + psIndex = psi; + } else { + notPermittedInElementContext ( en, getParent(), pn ); + } + } else if ( en[1].equals ( "PairValueRecord" ) ) { + String[] pn = new String[] { null, "PairSet" }; + if ( isParent ( pn ) ) { + String index = attrs.getValue ( "index" ); + if ( index == null ) { + missingRequiredAttribute ( en, "index" ); + } else { + assertPairClear(); + } + } else { + notPermittedInElementContext ( en, getParent(), pn ); + } + } else if ( en[1].equals ( "PosLookupRecord" ) ) { + String[] pn1 = new String[] { null, "ChainContextSubst" }; + String[] pn2 = new String[] { null, "ChainContextPos" }; + String[][] pnx = new String[][] { pn1, pn2 }; + if ( isParent ( pnx ) ) { + String index = attrs.getValue ( "index" ); + if ( index == null ) { + missingRequiredAttribute ( en, "index" ); + } + } else { + notPermittedInElementContext ( en, getParent(), pnx ); + } + } else if ( en[1].equals ( "ReqFeatureIndex" ) ) { + String[] pn1 = new String[] { null, "DefaultLangSys" }; + String[] pn2 = new String[] { null, "LangSys" }; + String[][] pnx = new String[][] { pn1, pn2 }; + if ( isParent ( pnx ) ) { + String value = attrs.getValue ( "value" ); + int v = -1; + if ( value == null ) { + missingRequiredAttribute ( en, "value" ); + } else { + v = Integer.parseInt ( value ); + } + String fid; + if ( ( v >= 0 ) && ( v < 65535 ) ) { + fid = makeFeatureId ( v ); + } else { + fid = null; + } + assertLanguageFeaturesClear(); + languageFeatures.add ( fid ); + } else { + notPermittedInElementContext ( en, getParent(), pnx ); + } + } else if ( en[1].equals ( "Script" ) ) { + String[] pn = new String[] { null, "ScriptRecord" }; + if ( ! isParent ( pn ) ) { + notPermittedInElementContext ( en, getParent(), pn ); + } + } else if ( en[1].equals ( "ScriptList" ) ) { + String[] pn1 = new String[] { null, "GSUB" }; + String[] pn2 = new String[] { null, "GPOS" }; + String[][] pnx = new String[][] { pn1, pn2 }; + if ( ! isParent ( pnx ) ) { + notPermittedInElementContext ( en, getParent(), pnx ); + } + } else if ( en[1].equals ( "ScriptRecord" ) ) { + String[] pn = new String[] { null, "ScriptList" }; + if ( isParent ( pn ) ) { + String index = attrs.getValue ( "index" ); + if ( index == null ) { + missingRequiredAttribute ( en, "index" ); + } + } else { + notPermittedInElementContext ( en, getParent(), pn ); + } + } else if ( en[1].equals ( "ScriptTag" ) ) { + String[] pn = new String[] { null, "ScriptRecord" }; + if ( isParent ( pn ) ) { + String value = attrs.getValue ( "value" ); + if ( value == null ) { + missingRequiredAttribute ( en, "value" ); + } else { + assert scriptTag == null; + scriptTag = value; + } + } else { + notPermittedInElementContext ( en, getParent(), pn ); + } + } else if ( en[1].equals ( "SecondGlyph" ) ) { + String[] pn = new String[] { null, "PairValueRecord" }; + if ( isParent ( pn ) ) { + String value = attrs.getValue ( "value" ); + if ( value == null ) { + missingRequiredAttribute ( en, "value" ); + } else { + int gid = mapGlyphId ( value, en ); + assert g2 == -1; + g2 = gid; + } + } else { + notPermittedInElementContext ( en, getParent(), pn ); + } + } else if ( en[1].equals ( "Sequence" ) ) { + String[] pn = new String[] { null, "MultipleSubst" }; + if ( isParent ( pn ) ) { + String index = attrs.getValue ( "index" ); + if ( index == null ) { + missingRequiredAttribute ( en, "index" ); + } else { + int i = Integer.parseInt ( index ); + if ( i != subtableEntries.size() ) { + invalidIndex ( en, i, subtableEntries.size() ); + } + } + } else { + notPermittedInElementContext ( en, getParent(), pn ); + } + } else if ( en[1].equals ( "SequenceIndex" ) ) { + String[] pn1 = new String[] { null, "PosLookupRecord" }; + String[] pn2 = new String[] { null, "SubstLookupRecord" }; + String[][] pnx = new String[][] { pn1, pn2 }; + if ( isParent ( pnx ) ) { + String value = attrs.getValue ( "value" ); + int v = -1; + if ( value == null ) { + missingRequiredAttribute ( en, "value" ); + } else { + v = Integer.parseInt ( value ); + } + assert rlSequence == -1; + assert v != -1; + rlSequence = v; + } else { + notPermittedInElementContext ( en, getParent(), pnx ); + } + } else if ( en[1].equals ( "SinglePos" ) ) { + String[] pn = new String[] { null, "Lookup" }; + if ( isParent ( pn ) ) { + String index = attrs.getValue ( "index" ); + if ( index == null ) { + missingRequiredAttribute ( en, "index" ); + } + String format = attrs.getValue ( "Format" ); + int sf = -1; + if ( format == null ) { + missingRequiredAttribute ( en, "Format" ); + } else { + sf = Integer.parseInt ( format ); + switch ( sf ) { + case 1: + case 2: + break; + default: + unsupportedFormat ( en, sf ); + break; + } + } + assertSubtableClear(); + assert sf >= 0; + stFormat = sf; + } else { + notPermittedInElementContext ( en, getParent(), pn ); + } + } else if ( en[1].equals ( "SingleSubst" ) ) { + String[] pn = new String[] { null, "Lookup" }; + if ( isParent ( pn ) ) { + String index = attrs.getValue ( "index" ); + if ( index == null ) { + missingRequiredAttribute ( en, "index" ); + } + String format = attrs.getValue ( "Format" ); + int sf = -1; + if ( format == null ) { + missingRequiredAttribute ( en, "Format" ); + } else { + sf = Integer.parseInt ( format ); + switch ( sf ) { + case 1: + case 2: + break; + default: + unsupportedFormat ( en, sf ); + break; + } + } + assertCoverageClear(); + ctIndex = 0; + ctFormat = 1; + assertSubtableClear(); + assert sf >= 0; + stFormat = sf; + } else { + notPermittedInElementContext ( en, getParent(), pn ); + } + } else if ( en[1].equals ( "SubstLookupRecord" ) ) { + String[] pn = new String[] { null, "ChainContextSubst" }; + if ( isParent ( pn ) ) { + String index = attrs.getValue ( "index" ); + if ( index == null ) { + missingRequiredAttribute ( en, "index" ); + } + } else { + notPermittedInElementContext ( en, getParent(), pn ); + } + } else if ( en[1].equals ( "Substitute" ) ) { + String[] pn = new String[] { null, "Sequence" }; + if ( isParent ( pn ) ) { + String index = attrs.getValue ( "index" ); + if ( index == null ) { + missingRequiredAttribute ( en, "index" ); + } else { + int i = Integer.parseInt ( index ); + if ( i != substitutes.size() ) { + invalidIndex ( en, i, substitutes.size() ); + } + } + String value = attrs.getValue ( "value" ); + if ( value == null ) { + missingRequiredAttribute ( en, "value" ); + } else { + int gid = mapGlyphId ( value, en ); + substitutes.add ( Integer.valueOf ( gid ) ); + } + } else { + notPermittedInElementContext ( en, getParent(), pn ); + } + } else if ( en[1].equals ( "Substitution" ) ) { + String[] pn = new String[] { null, "SingleSubst" }; + if ( isParent ( pn ) ) { + String in = attrs.getValue ( "in" ); + int igid = -1; + int ogid = -1; + if ( in == null ) { + missingRequiredAttribute ( en, "in" ); + } else { + igid = mapGlyphId ( in, en ); + } + String out = attrs.getValue ( "out" ); + if ( out == null ) { + missingRequiredAttribute ( en, "out" ); + } else { + ogid = mapGlyphId ( out, en ); + } + coverageEntries.add ( Integer.valueOf ( igid ) ); + subtableEntries.add ( Integer.valueOf ( ogid ) ); + } else { + notPermittedInElementContext ( en, getParent(), pn ); + } + } else if ( en[1].equals ( "Value" ) ) { + String[] pn = new String[] { null, "SinglePos" }; + if ( isParent ( pn ) ) { + String index = attrs.getValue ( "index" ); + if ( vf1 < 0 ) { + missingParameter ( en, "value format" ); + } else { + subtableEntries.add ( parseValue ( en, attrs, vf1 ) ); + } + } else { + notPermittedInElementContext ( en, getParent(), pn ); + } + } else if ( en[1].equals ( "Value1" ) ) { + String[] pn = new String[] { null, "PairValueRecord" }; + if ( isParent ( pn ) ) { + if ( vf1 < 0 ) { + missingParameter ( en, "value format 1" ); + } else { + assert v1 == null; + v1 = parseValue ( en, attrs, vf1 ); + } + } else { + notPermittedInElementContext ( en, getParent(), pn ); + } + } else if ( en[1].equals ( "Value2" ) ) { + String[] pn = new String[] { null, "PairValueRecord" }; + if ( isParent ( pn ) ) { + if ( vf2 < 0 ) { + missingParameter ( en, "value format 2" ); + } else { + assert v2 == null; + v2 = parseValue ( en, attrs, vf2 ); + } + } else { + notPermittedInElementContext ( en, getParent(), pn ); + } + } else if ( en[1].equals ( "ValueFormat" ) ) { + String[] pn = new String[] { null, "SinglePos" }; + if ( isParent ( pn ) ) { + String value = attrs.getValue ( "value" ); + int vf = -1; + if ( value == null ) { + missingRequiredAttribute ( en, "value" ); + } else { + vf = Integer.parseInt ( value ); + } + assert vf1 == -1; + vf1 = vf; + } else { + notPermittedInElementContext ( en, getParent(), pn ); + } + } else if ( en[1].equals ( "ValueFormat1" ) ) { + String[] pn = new String[] { null, "PairPos" }; + if ( isParent ( pn ) ) { + String value = attrs.getValue ( "value" ); + int vf = -1; + if ( value == null ) { + missingRequiredAttribute ( en, "value" ); + } else { + vf = Integer.parseInt ( value ); + } + assert vf1 == -1; + vf1 = vf; + } else { + notPermittedInElementContext ( en, getParent(), pn ); + } + } else if ( en[1].equals ( "ValueFormat2" ) ) { + String[] pn = new String[] { null, "PairPos" }; + if ( isParent ( pn ) ) { + String value = attrs.getValue ( "value" ); + int vf = -1; + if ( value == null ) { + missingRequiredAttribute ( en, "value" ); + } else { + vf = Integer.parseInt ( value ); + } + assert vf2 == -1; + vf2 = vf; + } else { + notPermittedInElementContext ( en, getParent(), pn ); + } + } else if ( en[1].equals ( "Version" ) ) { + String[] pn1 = new String[] { null, "GDEF" }; + String[] pn2 = new String[] { null, "GPOS" }; + String[] pn3 = new String[] { null, "GSUB" }; + String[][] pnx = new String[][] { pn1, pn2, pn3 }; + if ( isParent ( pnx ) ) { + String value = attrs.getValue ( "value" ); + if ( value == null ) { + missingRequiredAttribute ( en, "value" ); + } + } else { + notPermittedInElementContext ( en, getParent(), pnx ); + } + } else if ( en[1].equals ( "XCoordinate" ) ) { + String[] pn1 = new String[] { null, "BaseAnchor" }; + String[] pn2 = new String[] { null, "EntryAnchor" }; + String[] pn3 = new String[] { null, "ExitAnchor" }; + String[] pn4 = new String[] { null, "LigatureAnchor" }; + String[] pn5 = new String[] { null, "MarkAnchor" }; + String[] pn6 = new String[] { null, "Mark2Anchor" }; + String[][] pnx = new String[][] { pn1, pn2, pn3, pn4, pn5, pn6 }; + if ( isParent ( pnx ) ) { + String value = attrs.getValue ( "value" ); + int x = 0; + if ( value == null ) { + missingRequiredAttribute ( en, "value" ); + } else { + x = Integer.parseInt ( value ); + } + assert xCoord == Integer.MIN_VALUE; + xCoord = x; + } else { + notPermittedInElementContext ( en, getParent(), pnx ); + } + } else if ( en[1].equals ( "YCoordinate" ) ) { + String[] pn1 = new String[] { null, "BaseAnchor" }; + String[] pn2 = new String[] { null, "EntryAnchor" }; + String[] pn3 = new String[] { null, "ExitAnchor" }; + String[] pn4 = new String[] { null, "LigatureAnchor" }; + String[] pn5 = new String[] { null, "MarkAnchor" }; + String[] pn6 = new String[] { null, "Mark2Anchor" }; + String[][] pnx = new String[][] { pn1, pn2, pn3, pn4, pn5, pn6 }; + if ( isParent ( pnx ) ) { + String value = attrs.getValue ( "value" ); + int y = 0; + if ( value == null ) { + missingRequiredAttribute ( en, "value" ); + } else { + y = Integer.parseInt ( value ); + } + assert yCoord == Integer.MIN_VALUE; + yCoord = y; + } else { + notPermittedInElementContext ( en, getParent(), pnx ); + } + } else if ( en[1].equals ( "checkSumAdjustment" ) ) { + String[] pn = new String[] { null, "head" }; + if ( isParent ( pn ) ) { + String value = attrs.getValue ( "value" ); + if ( value == null ) { + missingRequiredAttribute ( en, "value" ); + } + } else { + notPermittedInElementContext ( en, getParent(), pn ); + } + } else if ( en[1].equals ( "cmap" ) ) { + String[] pn = new String[] { null, "ttFont" }; + if ( ! isParent ( pn ) ) { + notPermittedInElementContext ( en, getParent(), pn ); + } + } else if ( en[1].equals ( "cmap_format_0" ) ) { + String[] pn = new String[] { null, "cmap" }; + if ( isParent ( pn ) ) { + String platformID = attrs.getValue ( "platformID" ); + if ( platformID == null ) { + missingRequiredAttribute ( en, "platformID" ); + } + String platEncID = attrs.getValue ( "platEncID" ); + if ( platEncID == null ) { + missingRequiredAttribute ( en, "platEncID" ); + } + String language = attrs.getValue ( "language" ); + if ( language == null ) { + missingRequiredAttribute ( en, "language" ); + } + } else { + notPermittedInElementContext ( en, getParent(), pn ); + } + } else if ( en[1].equals ( "cmap_format_4" ) ) { + String[] pn = new String[] { null, "cmap" }; + if ( isParent ( pn ) ) { + String platformID = attrs.getValue ( "platformID" ); + int pid = -1; + if ( platformID == null ) { + missingRequiredAttribute ( en, "platformID" ); + } else { + pid = Integer.parseInt ( platformID ); + } + String platEncID = attrs.getValue ( "platEncID" ); + int eid = -1; + if ( platEncID == null ) { + missingRequiredAttribute ( en, "platEncID" ); + } else { + eid = Integer.parseInt ( platEncID ); + } + String language = attrs.getValue ( "language" ); + int lid = -1; + if ( language == null ) { + missingRequiredAttribute ( en, "language" ); + } else { + lid = Integer.parseInt ( language ); + } + assert cmapEntries.size() == 0; + assert cmPlatform == -1; + assert cmEncoding == -1; + assert cmLanguage == -1; + cmPlatform = pid; + cmEncoding = eid; + cmLanguage = lid; + } else { + notPermittedInElementContext ( en, getParent(), pn ); + } + } else if ( en[1].equals ( "created" ) ) { + String[] pn = new String[] { null, "head" }; + if ( isParent ( pn ) ) { + String value = attrs.getValue ( "value" ); + if ( value == null ) { + missingRequiredAttribute ( en, "value" ); + } + } else { + notPermittedInElementContext ( en, getParent(), pn ); + } + } else if ( en[1].equals ( "flags" ) ) { + String[] pn = new String[] { null, "head" }; + if ( isParent ( pn ) ) { + String value = attrs.getValue ( "value" ); + if ( value == null ) { + missingRequiredAttribute ( en, "value" ); + } + } else { + notPermittedInElementContext ( en, getParent(), pn ); + } + } else if ( en[1].equals ( "fontDirectionHint" ) ) { + String[] pn = new String[] { null, "head" }; + if ( isParent ( pn ) ) { + String value = attrs.getValue ( "value" ); + if ( value == null ) { + missingRequiredAttribute ( en, "value" ); + } + } else { + notPermittedInElementContext ( en, getParent(), pn ); + } + } else if ( en[1].equals ( "fontRevision" ) ) { + String[] pn = new String[] { null, "head" }; + if ( isParent ( pn ) ) { + String value = attrs.getValue ( "value" ); + if ( value == null ) { + missingRequiredAttribute ( en, "value" ); + } + } else { + notPermittedInElementContext ( en, getParent(), pn ); + } + } else if ( en[1].equals ( "glyphDataFormat" ) ) { + String[] pn = new String[] { null, "head" }; + if ( isParent ( pn ) ) { + String value = attrs.getValue ( "value" ); + if ( value == null ) { + missingRequiredAttribute ( en, "value" ); + } + } else { + notPermittedInElementContext ( en, getParent(), pn ); + } + } else if ( en[1].equals ( "head" ) ) { + String[] pn = new String[] { null, "ttFont" }; + if ( ! isParent ( pn ) ) { + notPermittedInElementContext ( en, getParent(), pn ); + } + } else if ( en[1].equals ( "hmtx" ) ) { + String[] pn = new String[] { null, "ttFont" }; + if ( ! isParent ( pn ) ) { + notPermittedInElementContext ( en, getParent(), pn ); + } else if ( glyphIdMax > 0 ) { + hmtxEntries.setSize ( glyphIdMax + 1 ); + } + } else if ( en[1].equals ( "indexToLocFormat" ) ) { + String[] pn = new String[] { null, "head" }; + if ( isParent ( pn ) ) { + String value = attrs.getValue ( "value" ); + if ( value == null ) { + missingRequiredAttribute ( en, "value" ); + } + } else { + notPermittedInElementContext ( en, getParent(), pn ); + } + } else if ( en[1].equals ( "lowestRecPPEM" ) ) { + String[] pn = new String[] { null, "head" }; + if ( isParent ( pn ) ) { + String value = attrs.getValue ( "value" ); + if ( value == null ) { + missingRequiredAttribute ( en, "value" ); + } + } else { + notPermittedInElementContext ( en, getParent(), pn ); + } + } else if ( en[1].equals ( "macStyle" ) ) { + String[] pn = new String[] { null, "head" }; + if ( isParent ( pn ) ) { + String value = attrs.getValue ( "value" ); + if ( value == null ) { + missingRequiredAttribute ( en, "value" ); + } + } else { + notPermittedInElementContext ( en, getParent(), pn ); + } + } else if ( en[1].equals ( "magicNumber" ) ) { + String[] pn = new String[] { null, "head" }; + if ( isParent ( pn ) ) { + String value = attrs.getValue ( "value" ); + if ( value == null ) { + missingRequiredAttribute ( en, "value" ); + } + } else { + notPermittedInElementContext ( en, getParent(), pn ); + } + } else if ( en[1].equals ( "map" ) ) { + String[] pn1 = new String[] { null, "cmap_format_0" }; + String[] pn2 = new String[] { null, "cmap_format_4" }; + String[][] pnx = new String[][] { pn1, pn2 }; + if ( isParent ( pnx ) ) { + String code = attrs.getValue ( "code" ); + int cid = -1; + if ( code == null ) { + missingRequiredAttribute ( en, "code" ); + } else { + code = code.toLowerCase(); + if ( code.startsWith ( "0x" ) ) { + cid = Integer.parseInt ( code.substring ( 2 ), 16 ); + } else { + cid = Integer.parseInt ( code, 10 ); + } + } + String name = attrs.getValue ( "name" ); + int gid = -1; + if ( name == null ) { + missingRequiredAttribute ( en, "name" ); + } else { + gid = mapGlyphId ( name, en ); + } + if ( ( cmPlatform == 3 ) && ( cmEncoding == 1 ) ) { + cmapEntries.add ( new int[] { cid, gid } ); + } + } else { + notPermittedInElementContext ( en, getParent(), pnx ); + } + } else if ( en[1].equals ( "modified" ) ) { + String[] pn = new String[] { null, "head" }; + if ( isParent ( pn ) ) { + String value = attrs.getValue ( "value" ); + if ( value == null ) { + missingRequiredAttribute ( en, "value" ); + } + } else { + notPermittedInElementContext ( en, getParent(), pn ); + } + } else if ( en[1].equals ( "mtx" ) ) { + String[] pn = new String[] { null, "hmtx" }; + if ( isParent ( pn ) ) { + String name = attrs.getValue ( "name" ); + int gid = -1; + if ( name == null ) { + missingRequiredAttribute ( en, "name" ); + } else { + gid = mapGlyphId ( name, en ); + } + String width = attrs.getValue ( "width" ); + int w = -1; + if ( width == null ) { + missingRequiredAttribute ( en, "width" ); + } else { + w = Integer.parseInt ( width ); + } + String lsb = attrs.getValue ( "lsb" ); + int l = -1; + if ( lsb == null ) { + missingRequiredAttribute ( en, "lsb" ); + } else { + l = Integer.parseInt ( lsb ); + } + hmtxEntries.set ( gid, new int[] { w, l } ); + } else { + notPermittedInElementContext ( en, getParent(), pn ); + } + } else if ( en[1].equals ( "tableVersion" ) ) { + String[] pn1 = new String[] { null, "cmap" }; + String[] pn2 = new String[] { null, "head" }; + String[][] pnx = new String[][] { pn1, pn2 }; + if ( isParent ( pn1 ) ) { // child of cmap + String version = attrs.getValue ( "version" ); + if ( version == null ) { + missingRequiredAttribute ( en, "version" ); + } + } else if ( isParent ( pn2 ) ) { // child of head + String value = attrs.getValue ( "value" ); + if ( value == null ) { + missingRequiredAttribute ( en, "value" ); + } + } else { + notPermittedInElementContext ( en, getParent(), pnx ); + } + } else if ( en[1].equals ( "ttFont" ) ) { + String[] pn = new String[] { null, null }; + if ( isParent ( pn ) ) { + String sfntVersion = attrs.getValue ( "sfntVersion" ); + if ( sfntVersion == null ) { + missingRequiredAttribute ( en, "sfntVersion" ); + } + String ttLibVersion = attrs.getValue ( "ttLibVersion" ); + if ( ttLibVersion == null ) { + missingRequiredAttribute ( en, "ttLibVersion" ); + } + } else { + notPermittedInElementContext ( en, getParent(), null ); + } + } else if ( en[1].equals ( "unitsPerEm" ) ) { + String[] pn = new String[] { null, "head" }; + if ( isParent ( pn ) ) { + String value = attrs.getValue ( "value" ); + int v = -1; + if ( value == null ) { + missingRequiredAttribute ( en, "value" ); + } else { + v = Integer.parseInt ( value ); + } + assert upem == -1; + upem = v; + } else { + notPermittedInElementContext ( en, getParent(), pn ); + } + } else if ( en[1].equals ( "xMax" ) ) { + String[] pn = new String[] { null, "head" }; + if ( isParent ( pn ) ) { + String value = attrs.getValue ( "value" ); + if ( value == null ) { + missingRequiredAttribute ( en, "value" ); + } + } else { + notPermittedInElementContext ( en, getParent(), pn ); + } + } else if ( en[1].equals ( "xMin" ) ) { + String[] pn = new String[] { null, "head" }; + if ( isParent ( pn ) ) { + String value = attrs.getValue ( "value" ); + if ( value == null ) { + missingRequiredAttribute ( en, "value" ); + } + } else { + notPermittedInElementContext ( en, getParent(), pn ); + } + } else if ( en[1].equals ( "yMax" ) ) { + String[] pn = new String[] { null, "head" }; + if ( isParent ( pn ) ) { + String value = attrs.getValue ( "value" ); + if ( value == null ) { + missingRequiredAttribute ( en, "value" ); + } + } else { + notPermittedInElementContext ( en, getParent(), pn ); + } + } else if ( en[1].equals ( "yMin" ) ) { + String[] pn = new String[] { null, "head" }; + if ( isParent ( pn ) ) { + String value = attrs.getValue ( "value" ); + if ( value == null ) { + missingRequiredAttribute ( en, "value" ); + } + } else { + notPermittedInElementContext ( en, getParent(), pn ); + } + } else { + unsupportedElement ( en ); + } + elements.push ( en ); + } + @Override + public void endElement ( String uri, String localName, String qName ) throws SAXException { + if ( elements.empty() ) { + throw new SAXException ( "element stack is unbalanced, no elements on stack!" ); + } + String[] enParent = elements.peek(); + if ( enParent == null ) { + throw new SAXException ( "element stack is empty, elements are not balanced" ); + } + String[] en = makeExpandedName ( uri, localName, qName ); + if ( ! sameExpandedName ( enParent, en ) ) { + throw new SAXException ( "element stack is unbalanced, expanded name mismatch" ); + } + if ( en[0] != null ) { + unsupportedElement ( en ); + } else if ( isAnchorElement ( en[1] ) ) { + if ( xCoord == Integer.MIN_VALUE ) { + missingParameter ( en, "x coordinate" ); + } else if ( yCoord == Integer.MIN_VALUE ) { + missingParameter ( en, "y coordinate" ); + } else { + if ( en[1].equals ( "EntryAnchor" ) ) { + if ( anchors.size() > 0 ) { + duplicateParameter ( en, "entry anchor" ); + } + } else if ( en[1].equals ( "ExitAnchor" ) ) { + if ( anchors.size() > 1 ) { + duplicateParameter ( en, "exit anchor" ); + } else if ( anchors.size() == 0 ) { + anchors.add ( null ); + } + } + anchors.add ( new GlyphPositioningTable.Anchor ( xCoord, yCoord ) ); + xCoord = yCoord = Integer.MIN_VALUE; + } + } else if ( en[1].equals ( "AlternateSet" ) ) { + subtableEntries.add ( extractAlternates() ); + } else if ( en[1].equals ( "AlternateSubst" ) ) { + if ( ! sortEntries ( coverageEntries, subtableEntries ) ) { + mismatchedEntries ( en, coverageEntries.size(), subtableEntries.size() ); + } + addGSUBSubtable ( GlyphSubstitutionTable.GSUB_LOOKUP_TYPE_ALTERNATE, extractCoverage() ); + } else if ( en[1].equals ( "BacktrackCoverage" ) ) { + String ck = makeCoverageKey ( "bk", ctIndex ); + if ( coverages.containsKey ( ck ) ) { + duplicateCoverageIndex ( en, ctIndex ); + } else { + coverages.put ( ck, extractCoverage() ); + } + } else if ( en[1].equals ( "BaseCoverage" ) ) { + coverages.put ( "base", extractCoverage() ); + } else if ( en[1].equals ( "BaseRecord" ) ) { + baseOrMarkAnchors.add ( extractAnchors() ); + } else if ( en[1].equals ( "ChainContextPos" ) || en[1].equals ( "ChainContextSubst" ) ) { + GlyphCoverageTable coverage = null; + if ( stFormat == 3 ) { + GlyphCoverageTable igca[] = getCoveragesWithPrefix ( "in" ); + GlyphCoverageTable bgca[] = getCoveragesWithPrefix ( "bk" ); + GlyphCoverageTable lgca[] = getCoveragesWithPrefix ( "la" ); + if ( ( igca.length == 0 ) || hasMissingCoverage ( igca ) ) { + missingCoverage ( en, "input", igca.length ); + } else if ( hasMissingCoverage ( bgca ) ) { + missingCoverage ( en, "backtrack", bgca.length ); + } else if ( hasMissingCoverage ( lgca ) ) { + missingCoverage ( en, "lookahead", lgca.length ); + } else { + GlyphTable.Rule r = new GlyphTable.ChainedCoverageSequenceRule ( extractRuleLookups(), igca.length, igca, bgca, lgca ); + GlyphTable.RuleSet rs = new GlyphTable.HomogeneousRuleSet ( new GlyphTable.Rule[] {r} ); + GlyphTable.RuleSet[] rsa = new GlyphTable.RuleSet[] {rs}; + coverage = igca [ 0 ]; + subtableEntries.add ( rsa ); + } + } else { + unsupportedFormat ( en, stFormat ); + } + if ( en[1].equals ( "ChainContextPos" ) ) { + addGPOSSubtable ( GlyphPositioningTable.GPOS_LOOKUP_TYPE_CHAINED_CONTEXTUAL, coverage ); + } else if ( en[1].equals ( "ChainContextSubst" ) ) { + addGSUBSubtable ( GlyphSubstitutionTable.GSUB_LOOKUP_TYPE_CHAINED_CONTEXTUAL, coverage ); + } + } else if ( en[1].equals ( "ComponentRecord" ) ) { + components.add ( extractAnchors() ); + } else if ( en[1].equals ( "Coverage" ) ) { + coverages.put ( "main", extractCoverage() ); + } else if ( en[1].equals ( "DefaultLangSys" ) || en[1].equals ( "LangSysRecord" ) ) { + if ( languageTag == null ) { + missingTag ( en, "language" ); + } else if ( languages.containsKey ( languageTag ) ) { + duplicateTag ( en, "language", languageTag ); + } else { + languages.put ( languageTag, extractLanguageFeatures() ); + languageTag = null; + } + } else if ( en[1].equals ( "CursivePos" ) ) { + GlyphCoverageTable ct = coverages.get ( "main" ); + if ( ct == null ) { + missingParameter ( en, "coverages" ); + } else if ( stFormat == 1 ) { + subtableEntries.add ( extractAttachmentAnchors() ); + } else { + unsupportedFormat ( en, stFormat ); + } + addGPOSSubtable ( GlyphPositioningTable.GPOS_LOOKUP_TYPE_CURSIVE, ct ); + } else if ( en[1].equals ( "EntryExitRecord" ) ) { + int na = anchors.size(); + if ( na == 0 ) { + missingParameter ( en, "entry or exit anchor" ); + } else if ( na == 1 ) { + anchors.add ( null ); + } else if ( na > 2 ) { + duplicateParameter ( en, "entry or exit anchor" ); + } + attachmentAnchors.add ( extractAnchors() ); + } else if ( en[1].equals ( "BaseRecord" ) ) { + baseOrMarkAnchors.add ( extractAnchors() ); + } else if ( en[1].equals ( "FeatureRecord" ) ) { + if ( flIndex != flSequence ) { + mismatchedIndex ( en, "feature", flIndex, flSequence ); + } else if ( featureTag == null ) { + missingTag ( en, "feature" ); + } else { + String fid = makeFeatureId ( flIndex ); + features.put ( fid, extractFeature() ); + nextFeature(); + } + } else if ( en[1].equals ( "GDEF" ) ) { + if ( subtables.size() > 0 ) { + gdef = new GlyphDefinitionTable ( subtables ); + } + clearTable(); + } else if ( en[1].equals ( "GPOS" ) ) { + if ( subtables.size() > 0 ) { + gpos = new GlyphPositioningTable ( gdef, extractLookups(), subtables ); + } + clearTable(); + } else if ( en[1].equals ( "GSUB" ) ) { + if ( subtables.size() > 0 ) { + gsub = new GlyphSubstitutionTable ( gdef, extractLookups(), subtables ); + } + clearTable(); + } else if ( en[1].equals ( "GlyphClassDef" ) ) { + GlyphMappingTable mapping = extractClassDefMapping ( glyphClasses, stFormat, true ); + addGDEFSubtable ( GlyphDefinitionTable.GDEF_LOOKUP_TYPE_GLYPH_CLASS, mapping ); + } else if ( en[1].equals ( "InputCoverage" ) ) { + String ck = makeCoverageKey ( "in", ctIndex ); + if ( coverages.containsKey ( ck ) ) { + duplicateCoverageIndex ( en, ctIndex ); + } else { + coverages.put ( ck, extractCoverage() ); + } + } else if ( en[1].equals ( "LigatureAttach" ) ) { + ligatureAnchors.add ( extractComponents() ); + } else if ( en[1].equals ( "LigatureCoverage" ) ) { + coverages.put ( "liga", extractCoverage() ); + } else if ( en[1].equals ( "LigatureSet" ) ) { + subtableEntries.add ( extractLigatures() ); + } else if ( en[1].equals ( "LigatureSubst" ) ) { + if ( ! sortEntries ( coverageEntries, subtableEntries ) ) { + mismatchedEntries ( en, coverageEntries.size(), subtableEntries.size() ); + } + GlyphCoverageTable coverage = extractCoverage(); + addGSUBSubtable ( GlyphSubstitutionTable.GSUB_LOOKUP_TYPE_LIGATURE, coverage ); + } else if ( en[1].equals ( "LookAheadCoverage" ) ) { + String ck = makeCoverageKey ( "la", ctIndex ); + if ( coverages.containsKey ( ck ) ) { + duplicateCoverageIndex ( en, ctIndex ); + } else { + coverages.put ( ck, extractCoverage() ); + } + } else if ( en[1].equals ( "Lookup" ) ) { + if ( ltIndex != ltSequence ) { + mismatchedIndex ( en, "lookup", ltIndex, ltSequence ); + } else { + nextLookup(); + } + } else if ( en[1].equals ( "MarkAttachClassDef" ) ) { + GlyphMappingTable mapping = extractClassDefMapping ( glyphClasses, stFormat, true ); + addGDEFSubtable ( GlyphDefinitionTable.GDEF_LOOKUP_TYPE_MARK_ATTACHMENT, mapping ); + } else if ( en[1].equals ( "MarkCoverage" ) ) { + coverages.put ( "mark", extractCoverage() ); + } else if ( en[1].equals ( "Mark1Coverage" ) ) { + coverages.put ( "mrk1", extractCoverage() ); + } else if ( en[1].equals ( "Mark2Coverage" ) ) { + coverages.put ( "mrk2", extractCoverage() ); + } else if ( en[1].equals ( "MarkBasePos" ) ) { + GlyphCoverageTable mct = coverages.get ( "mark" ); + GlyphCoverageTable bct = coverages.get ( "base" ); + if ( mct == null ) { + missingParameter ( en, "mark coverages" ); + } else if ( bct == null ) { + missingParameter ( en, "base coverages" ); + } else if ( stFormat == 1 ) { + MarkAnchor[] maa = extractMarkAnchors(); + Anchor[][] bam = extractBaseOrMarkAnchors(); + subtableEntries.add ( bct ); + subtableEntries.add ( computeClassCount ( bam ) ); + subtableEntries.add ( maa ); + subtableEntries.add ( bam ); + } else { + unsupportedFormat ( en, stFormat ); + } + addGPOSSubtable ( GlyphPositioningTable.GPOS_LOOKUP_TYPE_MARK_TO_BASE, mct ); + } else if ( en[1].equals ( "MarkLigPos" ) ) { + GlyphCoverageTable mct = coverages.get ( "mark" ); + GlyphCoverageTable lct = coverages.get ( "liga" ); + if ( mct == null ) { + missingParameter ( en, "mark coverages" ); + } else if ( lct == null ) { + missingParameter ( en, "ligature coverages" ); + } else if ( stFormat == 1 ) { + MarkAnchor[] maa = extractMarkAnchors(); + Anchor[][][] lam = extractLigatureAnchors(); + subtableEntries.add ( lct ); + subtableEntries.add ( computeLigaturesClassCount ( lam ) ); + subtableEntries.add ( computeLigaturesComponentCount ( lam ) ); + subtableEntries.add ( maa ); + subtableEntries.add ( lam ); + } else { + unsupportedFormat ( en, stFormat ); + } + addGPOSSubtable ( GlyphPositioningTable.GPOS_LOOKUP_TYPE_MARK_TO_LIGATURE, mct ); + } else if ( en[1].equals ( "MarkMarkPos" ) ) { + GlyphCoverageTable mct1 = coverages.get ( "mrk1" ); + GlyphCoverageTable mct2 = coverages.get ( "mrk2" ); + if ( mct1 == null ) { + missingParameter ( en, "mark coverages 1" ); + } else if ( mct2 == null ) { + missingParameter ( en, "mark coverages 2" ); + } else if ( stFormat == 1 ) { + MarkAnchor[] maa = extractMarkAnchors(); + Anchor[][] mam = extractBaseOrMarkAnchors(); + subtableEntries.add ( mct2 ); + subtableEntries.add ( computeClassCount ( mam ) ); + subtableEntries.add ( maa ); + subtableEntries.add ( mam ); + } else { + unsupportedFormat ( en, stFormat ); + } + addGPOSSubtable ( GlyphPositioningTable.GPOS_LOOKUP_TYPE_MARK_TO_MARK, mct1 ); + } else if ( en[1].equals ( "MarkRecord" ) ) { + if ( markClass == -1 ) { + missingParameter ( en, "mark class" ); + } else if ( anchors.size() == 0 ) { + missingParameter ( en, "mark anchor" ); + } else if ( anchors.size() > 1 ) { + duplicateParameter ( en, "mark anchor" ); + } else { + markAnchors.add ( new GlyphPositioningTable.MarkAnchor ( markClass, anchors.get(0) ) ); + markClass = -1; + anchors.clear(); + } + } else if ( en[1].equals ( "Mark2Record" ) ) { + baseOrMarkAnchors.add ( extractAnchors() ); + } else if ( en[1].equals ( "MultipleSubst" ) ) { + GlyphCoverageTable coverage = coverages.get ( "main" ); + addGSUBSubtable ( GlyphSubstitutionTable.GSUB_LOOKUP_TYPE_MULTIPLE, coverage, extractSequenceEntries() ); + } else if ( en[1].equals ( "PairPos" ) ) { + assertSubtableEntriesClear(); + if ( stFormat == 1 ) { + if ( pairSets.size() == 0 ) { + missingParameter ( en, "pair set" ); + } else { + subtableEntries.add ( extractPairSets() ); + } + } else if ( stFormat == 2 ) { + unsupportedFormat ( en, stFormat ); + } + GlyphCoverageTable coverage = coverages.get ( "main" ); + addGPOSSubtable ( GlyphPositioningTable.GPOS_LOOKUP_TYPE_PAIR, coverage ); + vf1 = vf2 = -1; psIndex = -1; + } else if ( en[1].equals ( "PairSet" ) ) { + if ( psIndex != pairSets.size() ) { + invalidIndex ( en, psIndex, pairSets.size() ); + } else { + pairSets.add ( extractPairs() ); + } + } else if ( en[1].equals ( "PairValueRecord" ) ) { + if ( g2 == -1 ) { + missingParameter ( en, "second glyph" ); + } else if ( ( v1 == null ) && ( v2 == null ) ) { + missingParameter ( en, "first or second value" ); + } else { + pairs.add ( new PairValues ( g2, v1, v2 ) ); + clearPair(); + } + } else if ( en[1].equals ( "PosLookupRecord" ) || en[1].equals ( "SubstLookupRecord" ) ) { + if ( rlSequence < 0 ) { + missingParameter ( en, "sequence index" ); + } else if ( rlLookup < 0 ) { + missingParameter ( en, "lookup index" ); + } else { + ruleLookups.add ( new GlyphTable.RuleLookup ( rlSequence, rlLookup ) ); + rlSequence = rlLookup = -1; + } + } else if ( en[1].equals ( "Script" ) ) { + if ( scriptTag == null ) { + missingTag ( en, "script" ); + } else if ( scripts.containsKey ( scriptTag ) ) { + duplicateTag ( en, "script", scriptTag ); + } else { + scripts.put ( scriptTag, extractLanguages() ); + scriptTag = null; + } + } else if ( en[1].equals ( "Sequence" ) ) { + subtableEntries.add ( extractSubstitutes() ); + } else if ( en[1].equals ( "SinglePos" ) ) { + int nv = subtableEntries.size(); + if ( stFormat == 1 ) { + if ( nv < 0 ) { + missingParameter ( en, "value" ); + } else if ( nv > 1 ) { + duplicateParameter ( en, "value" ); + } + } else if ( stFormat == 2 ) { + GlyphPositioningTable.Value[] pva = (GlyphPositioningTable.Value[]) subtableEntries.toArray ( new GlyphPositioningTable.Value [ nv ] ); + subtableEntries.clear(); + subtableEntries.add ( pva ); + } + GlyphCoverageTable coverage = coverages.get ( "main" ); + addGPOSSubtable ( GlyphPositioningTable.GPOS_LOOKUP_TYPE_SINGLE, coverage ); + vf1 = -1; + } else if ( en[1].equals ( "SingleSubst" ) ) { + if ( ! sortEntries ( coverageEntries, subtableEntries ) ) { + mismatchedEntries ( en, coverageEntries.size(), subtableEntries.size() ); + } + GlyphCoverageTable coverage = extractCoverage(); + addGSUBSubtable ( GlyphSubstitutionTable.GSUB_LOOKUP_TYPE_SINGLE, coverage ); + } else if ( en[1].equals ( "cmap" ) ) { + cmap = getCMAP(); + gmap = getGMAP(); + cmapEntries.clear(); + } else if ( en[1].equals ( "cmap_format_4" ) ) { + cmPlatform = cmEncoding = cmLanguage = -1; + } else if ( en[1].equals ( "hmtx" ) ) { + hmtx = getHMTX(); + hmtxEntries.clear(); + } else if ( en[1].equals ( "ttFont" ) ) { + if ( cmap == null ) { + missingParameter ( en, "cmap" ); + } + if ( hmtx == null ) { + missingParameter ( en, "hmtx" ); + } + } + elements.pop(); + } + @Override + public void characters ( char[] chars, int start, int length ) { + } + private String[] getParent() { + if ( ! elements.empty() ) { + return elements.peek(); + } else { + return new String[] { null, null }; + } + } + private boolean isParent ( Object enx ) { + if ( enx instanceof String[][] ) { + for ( String[] en : (String[][]) enx ) { + if ( isParent ( en ) ) { + return true; + } + } + return false; + } else if ( enx instanceof String[] ) { + String[] en = (String[]) enx; + if ( ! elements.empty() ) { + String[] pn = elements.peek(); + return ( pn != null ) && sameExpandedName ( en, pn ); + } else if ( ( en[0] == null ) && ( en[1] == null ) ) { + return true; + } else { + return false; + } + } else { + return false; + } + } + private boolean isAnchorElement ( String ln ) { + if ( ln.equals ( "BaseAnchor" ) ) { + return true; + } else if ( ln.equals ( "EntryAnchor" ) ) { + return true; + } else if ( ln.equals ( "ExitAnchor" ) ) { + return true; + } else if ( ln.equals ( "LigatureAnchor" ) ) { + return true; + } else if ( ln.equals ( "MarkAnchor" ) ) { + return true; + } else if ( ln.equals ( "Mark2Anchor" ) ) { + return true; + } else { + return false; + } + } + private Map getCMAP() { + Map cmap = new TreeMap(); + for ( int[] cme : cmapEntries ) { + Integer c = Integer.valueOf ( cme[0] ); + Integer g = Integer.valueOf ( cme[1] ); + cmap.put ( c, g ); + } + return cmap; + } + private Map getGMAP() { + Map gmap = new TreeMap(); + for ( int[] cme : cmapEntries ) { + Integer c = Integer.valueOf ( cme[0] ); + Integer g = Integer.valueOf ( cme[1] ); + gmap.put ( g, c ); + } + return gmap; + } + private int[][] getHMTX() { + int ne = hmtxEntries.size(); + int[][] hmtx = new int [ ne ] [ 2 ]; + for ( int i = 0; i < ne; i++ ) { + int[] ea = hmtxEntries.get(i); + if ( ea != null ) { + hmtx [ i ] [ 0 ] = ea[0]; + hmtx [ i ] [ 1 ] = ea[1]; + } + } + return hmtx; + } + private GlyphClassTable extractClassDefMapping ( Map glyphClasses, int format, boolean clearSourceMap ) { + GlyphClassTable ct; + if ( format == 1 ) { + ct = extractClassDefMapping1 ( extractClassMappings ( glyphClasses, clearSourceMap ) ); + } else if ( format == 2 ) { + ct = extractClassDefMapping2 ( extractClassMappings ( glyphClasses, clearSourceMap ) ); + } else { + ct = null; + } + return ct; + } + private GlyphClassTable extractClassDefMapping1 ( int[][] cma ) { + List entries = new ArrayList(); + int s = -1; + int l = -1; + Integer zero = Integer.valueOf(0); + for ( int[] m : cma ) { + int g = m[0]; + int c = m[1]; + if ( s < 0 ) { + s = g; + l = g - 1; + entries.add ( Integer.valueOf ( s ) ); + } + while ( g > ( l + 1 ) ) { + entries.add ( zero ); + l++; + } + assert l == ( g - 1 ); + entries.add ( Integer.valueOf ( c ) ); + l = g; + } + return GlyphClassTable.createClassTable ( entries ); + } + private GlyphClassTable extractClassDefMapping2 ( int[][] cma ) { + List entries = new ArrayList(); + int s = -1; + int e = s; + int l = -1; + for ( int[] m : cma ) { + int g = m[0]; + int c = m[1]; + if ( c != l ) { + if ( s >= 0 ) { + entries.add ( new GlyphClassTable.MappingRange ( s, e, l ) ); + } + s = e = g; + } else { + e = g; + } + l = c; + } + return GlyphClassTable.createClassTable ( entries ); + } + private int[][] extractClassMappings ( Map glyphClasses, boolean clearSourceMap ) { + int nc = glyphClasses.size(); + int i = 0; + int[][] cma = new int [ nc ] [ 2 ]; + for ( Map.Entry e : glyphClasses.entrySet() ) { + Integer gid = glyphIds.get ( e.getKey() ); + assert gid != null; + int[] m = cma [ i ]; + m [ 0 ] = (int) gid; + m [ 1 ] = (int) e.getValue(); + i++; + } + if ( clearSourceMap ) { + glyphClasses.clear(); + } + return sortClassMappings ( cma ); + } + private int[][] sortClassMappings ( int[][] cma ) { + Arrays.sort ( cma, new Comparator() { + public int compare ( int[] m1, int[] m2 ) { + assert m1.length > 0; + assert m2.length > 0; + if ( m1[0] < m2[0] ) { + return -1; + } else if ( m1[0] > m2[0] ) { + return 1; + } else { + return 0; + } + } + } + ); + return cma; + } + // sort coverage entries and subtable entries together + private boolean sortEntries ( List cel, List sel ) { + assert cel != null; + assert sel != null; + if ( cel.size() == sel.size() ) { + int np = cel.size(); + Object[][] pa = new Object [ np ] [ 2 ]; + for ( int i = 0; i < np; i++ ) { + pa [ i ] [ 0 ] = cel.get ( i ); + pa [ i ] [ 1 ] = sel.get ( i ); + } + Arrays.sort ( pa, new Comparator() { + public int compare ( Object[] p1, Object[] p2 ) { + assert p1.length == 2; + assert p2.length == 2; + int c1 = (Integer) p1[0]; + int c2 = (Integer) p2[0]; + if ( c1 < c2 ) { + return -1; + } else if ( c1 > c2 ) { + return 1; + } else { + return 0; + } + } + } + ); + cel.clear(); + sel.clear(); + for ( int i = 0; i < np; i++ ) { + cel.add ( pa [ i ] [ 0 ] ); + sel.add ( pa [ i ] [ 1 ] ); + } + assert cel.size() == sel.size(); + return true; + } else { + return false; + } + } + private String makeCoverageKey ( String prefix, int index ) { + assert prefix != null; + assert prefix.length() == 2; + assert index < 100; + return prefix + CharUtilities.padLeft ( Integer.toString ( index, 10 ), 2, '0' ); + } + private List extractCoverageEntries() { + List entries = new ArrayList ( coverageEntries ); + clearCoverage(); + return entries; + } + private void clearCoverageEntries() { + coverageEntries.clear(); + ctFormat = -1; + ctIndex = -1; + } + private void assertCoverageEntriesClear() { + assert coverageEntries.size() == 0; + } + private GlyphCoverageTable extractCoverage() { + assert ( ctFormat == 1 ) || ( ctFormat == 2 ); + assert ctIndex >= 0; + GlyphCoverageTable coverage = GlyphCoverageTable.createCoverageTable ( extractCoverageEntries() ); + clearCoverage(); + return coverage; + } + private void clearCoverages() { + coverages.clear(); + } + private void assertCoverageClear() { + assert ctFormat == -1; + assert ctIndex == -1; + assertCoverageEntriesClear(); + } + private void clearCoverage() { + ctFormat = -1; + ctIndex = -1; + clearCoverageEntries(); + } + private void assertCoveragesClear() { + assert coverages.size() == 0; + } + private GlyphCoverageTable[] getCoveragesWithPrefix ( String prefix ) { + assert prefix != null; + int prefixLength = prefix.length(); + Set keys = coverages.keySet(); + int mi = -1; // maximum coverage table index + for ( String k : keys ) { + if ( k.startsWith ( prefix ) ) { + int i = Integer.parseInt ( k.substring ( prefixLength ) ); + if ( i > mi ) { + mi = i; + } + } + } + GlyphCoverageTable[] gca = new GlyphCoverageTable [ mi + 1 ]; + for ( String k : keys ) { + if ( k.startsWith ( prefix ) ) { + int i = Integer.parseInt ( k.substring ( prefixLength ) ); + if ( i >= 0 ) { + gca [ i ] = coverages.get ( k ); + } + } + } + return gca; + } + private boolean hasMissingCoverage ( GlyphCoverageTable[] gca ) { + assert gca != null; + int nc = 0; + for ( int i = 0, n = gca.length; i < n; i++ ) { + if ( gca [ i ] != null ) { + nc++; + } + } + return nc != gca.length; + } + private String makeFeatureId ( int fid ) { + assert fid >= 0; + return "f" + fid; + } + private String makeLookupId ( int lid ) { + assert lid >= 0; + return "lu" + lid; + } + private void clearScripts() { + scripts.clear(); + } + private List extractLanguageFeatures() { + List lfl = new ArrayList(languageFeatures); + clearLanguageFeatures(); + return lfl; + } + private void assertLanguageFeaturesClear() { + assert languageFeatures.size() == 0; + } + private void clearLanguageFeatures() { + languageFeatures.clear(); + } + private Map> extractLanguages() { + Map> lm = new HashMap ( languages ); + clearLanguages(); + return lm; + } + private void clearLanguages() { + languages.clear(); + } + private void assertFeatureLookupsClear() { + assert featureLookups.size() == 0; + } + private List extractFeatureLookups() { + List lookups = new ArrayList ( featureLookups ); + clearFeatureLookups(); + return lookups; + } + private void clearFeatureLookups() { + featureLookups.clear(); + } + private void assertFeatureClear() { + assert flIndex == -1; + assert featureTag == null; + assertFeatureLookupsClear(); + } + private Object[] extractFeature() { + Object[] fa = new Object [ 2 ]; + fa[0] = featureTag; + fa[1] = extractFeatureLookups(); + clearFeature(); + return fa; + } + private void clearFeature() { + flIndex = -1; + featureTag = null; + clearFeatureLookups(); + } + private void nextFeature() { + flSequence++; + } + private void clearFeatures() { + features.clear(); + } + private void clearSubtableInLookup() { + stFormat = 0; + clearCoverages(); + } + private void clearSubtablesInLookup() { + clearSubtableInLookup(); + stSequence = 0; + } + private void clearSubtablesInTable() { + clearSubtablesInLookup(); + subtables.clear(); + } + private void nextSubtableInLookup() { + stSequence++; + clearSubtableInLookup(); + } + private void assertLookupClear() { + assert ltIndex == -1; + assert ltFlags == 0; + } + private void clearLookup() { + ltIndex = -1; + ltFlags = 0; + clearSubtablesInLookup(); + } + private Map> extractLookups() { + Map> lookups = new LinkedHashMap>(); + for ( String st : scripts.keySet() ) { + Map> lm = scripts.get ( st ); + if ( lm != null ) { + for ( String lt : lm.keySet() ) { + List fids = lm.get ( lt ); + if ( fids != null ) { + for ( String fid : fids ) { + if ( fid != null ) { + Object[] fa = features.get ( fid ); + if ( fa != null ) { + assert fa.length == 2; + String ft = (String) fa[0]; + List lids = (List) fa[1]; + if ( ( lids != null ) && ( lids.size() > 0 ) ) { + GlyphTable.LookupSpec ls = new GlyphTable.LookupSpec ( st, lt, ft ); + lookups.put ( ls, lids ); + } + } + } + } + } + } + } + } + clearScripts(); + clearLanguages(); + clearFeatures(); + return lookups; + } + private void clearLookups() { + clearLookup(); + clearSubtablesInTable(); + ltSequence = 0; + flSequence = 0; + } + private void nextLookup() { + ltSequence++; + clearLookup(); + } + private void clearTable() { + clearLookups(); + } + private void assertSubtableClear() { + assert stFormat == 0; + assertCoverageEntriesClear(); + } + private void assertSubtablesClear() { + assertSubtableClear(); + assert subtables.size() == 0; + } + private void clearSubtableEntries() { + subtableEntries.clear(); + } + private void assertSubtableEntriesClear() { + assert subtableEntries.size() == 0; + } + private List extractSubtableEntries() { + List entries = new ArrayList ( subtableEntries ); + clearSubtableEntries(); + return entries; + } + private int[] extractAlternates() { + int[] aa = new int [ alternates.size() ]; + int i = 0; + for ( Integer a : alternates ) { + aa[i++] = (int) a; + } + clearAlternates(); + return aa; + } + private void clearAlternates() { + alternates.clear(); + } + private LigatureSet extractLigatures() { + LigatureSet ls = new LigatureSet ( ligatures ); + clearLigatures(); + return ls; + } + private void clearLigatures() { + ligatures.clear(); + } + private int[] extractSubstitutes() { + int[] aa = new int [ substitutes.size() ]; + int i = 0; + for ( Integer a : substitutes ) { + aa[i++] = (int) a; + } + clearSubstitutes(); + return aa; + } + private void clearSubstitutes() { + substitutes.clear(); + } + private List extractSequenceEntries() { + List sequences = extractSubtableEntries(); + int[][] sa = new int [ sequences.size() ] []; + int i = 0; + for ( Object s : sequences ) { + if ( s instanceof int[] ) { + sa[i++] = (int[]) s; + } + } + List entries = new ArrayList(); + entries.add ( sa ); + return entries; + } + private RuleLookup[] extractRuleLookups() { + RuleLookup[] lookups = (RuleLookup[]) ruleLookups.toArray ( new RuleLookup [ ruleLookups.size() ] ); + clearRuleLookups(); + return lookups; + } + private void clearRuleLookups() { + ruleLookups.clear(); + } + private GlyphPositioningTable.Value parseValue ( String[] en, Attributes attrs, int format ) throws SAXException { + String xPlacement = attrs.getValue ( "XPlacement" ); + int xp = 0; + if ( xPlacement != null ) { + xp = Integer.parseInt ( xPlacement ); + } else if ( ( format & GlyphPositioningTable.Value.X_PLACEMENT ) != 0 ) { + missingParameter ( en, "xPlacement" ); + } + String yPlacement = attrs.getValue ( "YPlacement" ); + int yp = 0; + if ( yPlacement != null ) { + yp = Integer.parseInt ( yPlacement ); + } else if ( ( format & GlyphPositioningTable.Value.Y_PLACEMENT ) != 0 ) { + missingParameter ( en, "yPlacement" ); + } + String xAdvance = attrs.getValue ( "XAdvance" ); + int xa = 0; + if ( xAdvance != null ) { + xa = Integer.parseInt ( xAdvance ); + } else if ( ( format & GlyphPositioningTable.Value.X_ADVANCE ) != 0 ) { + missingParameter ( en, "xAdvance" ); + } + String yAdvance = attrs.getValue ( "YAdvance" ); + int ya = 0;; + if ( yAdvance != null ) { + ya = Integer.parseInt ( yAdvance ); + } else if ( ( format & GlyphPositioningTable.Value.Y_ADVANCE ) != 0 ) { + missingParameter ( en, "yAdvance" ); + } + return new GlyphPositioningTable.Value ( xp, yp, xa, ya, null, null, null, null ); + } + private void assertPairClear() { + assert g2 == -1; + assert v1 == null; + assert v2 == null; + } + private void clearPair() { + g2 = -1; + v1 = null; + v2 = null; + } + private void assertPairsClear() { + assert pairs.size() == 0; + } + private void clearPairs() { + pairs.clear(); + psIndex = -1; + } + private PairValues[] extractPairs() { + PairValues[] pva = (PairValues[]) pairs.toArray ( new PairValues [ pairs.size() ] ); + clearPairs(); + return pva; + } + private void assertPairSetsClear() { + assert pairSets.size() == 0; + } + private void clearPairSets() { + pairSets.clear(); + } + private PairValues[][] extractPairSets() { + PairValues[][] pvm = (PairValues[][]) pairSets.toArray ( new PairValues [ pairSets.size() ][] ); + clearPairSets(); + return pvm; + } + private Anchor[] extractAnchors() { + Anchor[] aa = (Anchor[]) anchors.toArray ( new Anchor [ anchors.size() ] ); + anchors.clear(); + return aa; + } + private MarkAnchor[] extractMarkAnchors() { + MarkAnchor[] maa = new MarkAnchor [ markAnchors.size() ]; + maa = (MarkAnchor[]) markAnchors.toArray ( new MarkAnchor [ maa.length ] ); + markAnchors.clear(); + return maa; + } + private Anchor[][] extractBaseOrMarkAnchors() { + int na = baseOrMarkAnchors.size(); + int ncMax = 0; + for ( Anchor[] aa : baseOrMarkAnchors ) { + if ( aa != null ) { + int nc = aa.length; + if ( nc > ncMax ) { + ncMax = nc; + } + } + } + Anchor[][] am = new Anchor [ na ][ ncMax ]; + for ( int i = 0; i < na; i++ ) { + Anchor[] aa = baseOrMarkAnchors.get(i); + if ( aa != null ) { + for ( int j = 0; j < ncMax; j++ ) { + if ( j < aa.length ) { + am [ i ] [ j ] = aa [ j ]; + } + } + } + } + baseOrMarkAnchors.clear(); + return am; + } + private Integer computeClassCount ( Anchor[][] am ) { + int ncMax = 0; + for ( int i = 0, n = am.length; i < n; i++ ) { + Anchor[] aa = am [ i ]; + if ( aa != null ) { + int nc = aa.length; + if ( nc > ncMax ) { + ncMax = nc; + } + } + } + return Integer.valueOf ( ncMax ); + } + private Anchor[][] extractComponents() { + Anchor[][] cam = new Anchor [ components.size() ][]; + cam = (Anchor[][]) components.toArray ( new Anchor [ cam.length ][] ); + components.clear(); + return cam; + } + private Anchor[][][] extractLigatureAnchors() { + int na = ligatureAnchors.size(); + int ncMax = 0; + int nxMax = 0; + for ( Anchor[][] cm : ligatureAnchors ) { + if ( cm != null ) { + int nx = cm.length; + if ( nx > nxMax ) { + nxMax = nx; + } + for ( Anchor[] aa : cm ) { + if ( aa != null ) { + int nc = aa.length; + if ( nc > ncMax ) { + ncMax = nc; + } + } + } + + } + } + Anchor[][][] lam = new Anchor [ na ] [ nxMax ] [ ncMax ]; + for ( int i = 0; i < na; i++ ) { + Anchor[][] cm = ligatureAnchors.get(i); + if ( cm != null ) { + for ( int j = 0; j < nxMax; j++ ) { + if ( j < cm.length ) { + Anchor[] aa = cm [ j ]; + if ( aa != null ) { + for ( int k = 0; k < ncMax; k++ ) { + if ( k < aa.length ) { + lam [ i ] [ j ] [ k ] = aa [ k ]; + } + } + } + } + } + } + } + ligatureAnchors.clear(); + return lam; + } + private Integer computeLigaturesClassCount ( Anchor[][][] lam ) { + int ncMax = 0; + if ( lam != null ) { + for ( Anchor[][] cm : lam ) { + if ( cm != null ) { + for ( Anchor[] aa : cm ) { + if ( aa != null ) { + int nc = aa.length;; + if ( nc > ncMax ) { + ncMax = nc; + } + } + } + } + } + } + return Integer.valueOf ( ncMax ); + } + private Integer computeLigaturesComponentCount ( Anchor[][][] lam ) { + int nxMax = 0; + if ( lam != null ) { + for ( Anchor[][] cm : lam ) { + if ( cm != null ) { + int nx = cm.length;; + if ( nx > nxMax ) { + nxMax = nx; + } + } + } + } + return Integer.valueOf ( nxMax ); + } + private Anchor[] extractAttachmentAnchors() { + int na = attachmentAnchors.size(); + Anchor[] aa = new Anchor [ na * 2 ]; + for ( int i = 0; i < na; i++ ) { + Anchor[] ea = attachmentAnchors.get(i); + int ne = ea.length; + if ( ne > 0 ) { + aa [ ( i * 2 ) + 0 ] = ea[0]; + } + if ( ne > 1 ) { + aa [ ( i * 2 ) + 1 ] = ea[1]; + } + } + attachmentAnchors.clear(); + return aa; + } + private void addGDEFSubtable ( int stType, GlyphMappingTable mapping ) { + subtables.add ( GlyphDefinitionTable.createSubtable ( stType, makeLookupId ( ltSequence ), stSequence, ltFlags, stFormat, mapping, extractSubtableEntries() ) ); + nextSubtableInLookup(); + } + private void addGSUBSubtable ( int stType, GlyphCoverageTable coverage, List entries ) { + subtables.add ( GlyphSubstitutionTable.createSubtable ( stType, makeLookupId ( ltSequence ), stSequence, ltFlags, stFormat, coverage, entries ) ); + nextSubtableInLookup(); + } + private void addGSUBSubtable ( int stType, GlyphCoverageTable coverage ) { + addGSUBSubtable ( stType, coverage, extractSubtableEntries() ); + } + private void addGPOSSubtable ( int stType, GlyphCoverageTable coverage, List entries ) { + subtables.add ( GlyphPositioningTable.createSubtable ( stType, makeLookupId ( ltSequence ), stSequence, ltFlags, stFormat, coverage, entries ) ); + nextSubtableInLookup(); + } + private void addGPOSSubtable ( int stType, GlyphCoverageTable coverage ) { + addGPOSSubtable ( stType, coverage, extractSubtableEntries() ); + } + } + private int mapGlyphId0 ( String glyph ) { + assert glyphIds != null; + Integer gid = glyphIds.get ( glyph ); + if ( gid != null ) { + return (int) gid; + } else { + return -1; + } + } + private int mapGlyphId ( String glyph, String[] currentElement ) throws SAXException { + int g = mapGlyphId0 ( glyph ); + if ( g < 0 ) { + unsupportedGlyph ( currentElement, glyph ); + return -1; + } else { + return g; + } + } + private int[] mapGlyphIds ( String glyphs, String[] currentElement ) throws SAXException { + String[] ga = glyphs.split(","); + int[] gids = new int [ ga.length ]; + int i = 0; + for ( String glyph : ga ) { + gids[i++] = mapGlyphId ( glyph, currentElement ); + } + return gids; + } + private int mapGlyphIdToChar ( String glyph ) { + assert glyphIds != null; + Integer gid = glyphIds.get ( glyph ); + if ( gid != null ) { + if ( gmap != null ) { + Integer cid = gmap.get ( gid ); + if ( cid != null ) { + return cid.intValue(); + } + } + } + return -1; + } + private String formatLocator() { + if ( locator == null ) { + return "{null}"; + } else { + return "{" + locator.getSystemId() + ":" + locator.getLineNumber() + ":" + locator.getColumnNumber() + "}"; + } + } + private void unsupportedElement ( String[] en ) throws SAXException { + throw new SAXException ( formatLocator() + ": unsupported element " + formatExpandedName ( en ) ); + } + private void notPermittedInElementContext ( String[] en, String[] cn, Object xns ) throws SAXException { + assert en != null; + assert cn != null; + String s = "element " + formatExpandedName(en) + " not permitted in current element context " + formatExpandedName(cn); + if ( xns == null ) { + s += ", expected root context"; + } else if ( xns instanceof String[][] ) { + int nxn = 0; + s += ", expected one of { "; + for ( String[] xn : (String[][]) xns ) { + if ( nxn++ > 0 ) { + s += ", "; + } + s += formatExpandedName ( xn ); + } + s += " }"; + } else if ( xns instanceof String[] ) { + s += ", expected " + formatExpandedName ( (String[]) xns ); + } + throw new SAXException ( formatLocator() + ": " + s ); + } + private void missingRequiredAttribute ( String[] en, String name ) throws SAXException { + throw new SAXException ( formatLocator() + ": element " + formatExpandedName(en) + " missing required attribute " + name ); + } + private void duplicateGlyph ( String[] en, String name, int gid ) throws SAXException { + throw new SAXException ( formatLocator() + ": element " + formatExpandedName(en) + " contains duplicate name \"" + name + "\", with identifier value " + gid ); + } + private void unsupportedGlyph ( String[] en, String name ) throws SAXException { + throw new SAXException ( formatLocator() + ": element " + formatExpandedName(en) + " refers to unsupported glyph id \"" + name + "\"" ); + } + private void duplicateCMAPCharacter ( String[] en, int cid ) throws SAXException { + throw new SAXException ( formatLocator() + ": element " + formatExpandedName(en) + " contains duplicate cmap character code: " + CharUtilities.format ( cid ) ); + } + private void duplicateCMAPGlyph ( String[] en, int gid ) throws SAXException { + throw new SAXException ( formatLocator() + ": element " + formatExpandedName(en) + " contains duplicate cmap glyph code: " + gid ); + } + private void duplicateGlyphClass ( String[] en, String name, String glyphClass ) throws SAXException { + throw new SAXException ( formatLocator() + ": element " + formatExpandedName(en) + " contains duplicate glyph class for \"" + name + "\", with class value " + glyphClass ); + } + private void unsupportedFormat ( String[] en, int format ) throws SAXException { + throw new SAXException ( formatLocator() + ": element " + formatExpandedName(en) + " refers to unsupported table format \"" + format + "\"" ); + } + private void invalidIndex ( String[] en, int actual, int expected ) throws SAXException { + throw new SAXException ( formatLocator() + ": element " + formatExpandedName(en) + " specifies invalid index " + actual + ", expected " + expected ); + } + private void mismatchedIndex ( String[] en, String label, int actual, int expected ) throws SAXException { + throw new SAXException ( formatLocator() + ": element " + formatExpandedName(en) + " mismatched " + label + " index: got " + actual + ", expected " + expected ); + } + private void mismatchedEntries ( String[] en, int nce, int nse ) throws SAXException { + throw new SAXException ( formatLocator() + ": element " + formatExpandedName(en) + " mismatched coverage and subtable entry counts, # coverages " + nce + ", # entries " + nse ); + } + private void missingParameter ( String[] en, String label ) throws SAXException { + throw new SAXException ( formatLocator() + ": element " + formatExpandedName(en) + " missing " + label + " parameter" ); + } + private void duplicateParameter ( String[] en, String label ) throws SAXException { + throw new SAXException ( formatLocator() + ": element " + formatExpandedName(en) + " duplicate " + label + " parameter" ); + } + private void duplicateCoverageIndex ( String[] en, int index ) throws SAXException { + throw new SAXException ( formatLocator() + ": element " + formatExpandedName(en) + " duplicate coverage table index " + index ); + } + private void missingCoverage ( String[] en, String type, int expected ) throws SAXException { + throw new SAXException ( formatLocator() + ": element " + formatExpandedName(en) + " missing " + type + " coverage table, expected " + ( ( expected > 0 ) ? expected : 1 ) + " table(s)" ); + } + private void missingTag ( String[] en, String label ) throws SAXException { + throw new SAXException ( formatLocator() + ": element " + formatExpandedName(en) + " missing " + label + " tag" ); + } + private void duplicateTag ( String[] en, String label, String tag ) throws SAXException { + throw new SAXException ( formatLocator() + ": element " + formatExpandedName(en) + " duplicate " + label + " tag: " + tag ); + } + private static String[] makeExpandedName ( String uri, String localName, String qName ) { + if ( ( uri != null ) && ( uri.length() == 0 ) ) { + uri = null; + } + if ( ( localName != null ) && ( localName.length() == 0 ) ) { + localName = null; + } + if ( ( uri == null ) && ( localName == null ) ) { + uri = extractPrefix ( qName ); + localName = extractLocalName ( qName ); + } + return new String[] { uri, localName }; + } + private static String extractPrefix ( String qName ) { + String[] sa = qName.split(":"); + if ( sa.length == 2 ) { + return sa[0]; + } else { + return null; + } + } + private static String extractLocalName ( String qName ) { + String[] sa = qName.split(":"); + if ( sa.length == 2 ) { + return sa[1]; + } else if ( sa.length == 1 ) { + return sa[0]; + } else { + return null; + } + } + private static boolean sameExpandedName ( String[] n1, String[] n2 ) { + String u1 = n1[0]; + String u2 = n2[0]; + if ( ( u1 == null ) ^ ( u2 == null ) ) { + return false; + } + if ( ( u1 != null ) && ( u2 != null ) ) { + if ( ! u1.equals ( u2 ) ) { + return false; + } + } + String l1 = n1[1]; + String l2 = n2[1]; + if ( ( l1 == null ) ^ ( l2 == null ) ) { + return false; + } + if ( ( l1 != null ) && ( l2 != null ) ) { + if ( ! l1.equals ( l2 ) ) { + return false; + } + } + return true; + } + private static String formatExpandedName ( String[] n ) { + String u = ( n[0] != null ) ? n[0] : "null"; + String l = ( n[1] != null ) ? n[1] : "null"; + return "{" + u + "}" + l; + } +} diff --git a/test/java/org/apache/fop/complexscripts/fonts/ttx/TTXFileTestCase.java b/test/java/org/apache/fop/complexscripts/fonts/ttx/TTXFileTestCase.java new file mode 100644 index 000000000..b28eb49c1 --- /dev/null +++ b/test/java/org/apache/fop/complexscripts/fonts/ttx/TTXFileTestCase.java @@ -0,0 +1,52 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* $Id$ */ + +package org.apache.fop.complexscripts.fonts.ttx; + +import java.io.File; + +import org.junit.Test; + +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +public class TTXFileTestCase { + + private static String ttxFilesRoot = "test/resources/complexscripts"; + + private static String[] ttxFiles = { + "arab/ttx/arab-001.ttx", + "arab/ttx/arab-002.ttx", + "arab/ttx/arab-003.ttx", + "arab/ttx/arab-004.ttx", + }; + + @Test + public void testTTXFiles() throws Exception { + for ( String tfn : ttxFiles ) { + try { + TTXFile tf = TTXFile.getFromCache ( ttxFilesRoot + File.separator + tfn ); + assertTrue ( tf != null ); + } catch ( Exception e ) { + fail ( e.getMessage() ); + } + } + } + +} diff --git a/test/java/org/apache/fop/complexscripts/scripts/ScriptsTestSuite.java b/test/java/org/apache/fop/complexscripts/scripts/ScriptsTestSuite.java new file mode 100644 index 000000000..cf5d846b4 --- /dev/null +++ b/test/java/org/apache/fop/complexscripts/scripts/ScriptsTestSuite.java @@ -0,0 +1,36 @@ +/* + * 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.complexscripts.scripts; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; +import org.junit.runners.Suite.SuiteClasses; + +import org.apache.fop.complexscripts.scripts.arabic.ArabicTestCase; + +/** + * Test suite for script specific functionality related to complex scripts. + */ +@RunWith(Suite.class) +@SuiteClasses({ + ArabicTestCase.class +}) +public class ScriptsTestSuite { +} diff --git a/test/java/org/apache/fop/complexscripts/scripts/arabic/ArabicTestCase.java b/test/java/org/apache/fop/complexscripts/scripts/arabic/ArabicTestCase.java new file mode 100644 index 000000000..ef1ea37bf --- /dev/null +++ b/test/java/org/apache/fop/complexscripts/scripts/arabic/ArabicTestCase.java @@ -0,0 +1,195 @@ +/* + * 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.complexscripts.scripts.arabic; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FilenameFilter; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.LineNumberReader; +import java.io.ObjectInputStream; +import java.nio.IntBuffer; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.List; + +import org.apache.fop.complexscripts.fonts.GlyphPositioningTable; +import org.apache.fop.complexscripts.fonts.GlyphSubstitutionTable; +import org.apache.fop.complexscripts.fonts.ttx.TTXFile; +import org.apache.fop.complexscripts.util.GlyphSequence; + +import org.junit.BeforeClass; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +/** + * Tests for functionality related to the arabic script. + */ +public class ArabicTestCase implements ArabicTestConstants { + + @Test + public void testArabicWordForms() { + for ( String sfn : srcFiles ) { + try { + processWordForms ( new File ( datFilesDir ) ); + } catch ( Exception e ) { + fail ( e.getMessage() ); + } + } + } + + private void processWordForms ( File dfd ) { + String[] files = listWordFormFiles ( dfd ); + for ( String fn : files ) { + File dff = new File ( dfd, fn ); + processWordForms ( dff.getAbsolutePath() ); + } + } + + private String[] listWordFormFiles ( File dfd ) { + return dfd.list ( new FilenameFilter() { + public boolean accept ( File f, String name ) { + return hasPrefixFrom ( name, srcFiles ) && hasExtension ( name, WF_FILE_DAT_EXT ); + } + private boolean hasPrefixFrom ( String name, String[] prefixes ) { + for ( String p : prefixes ) { + if ( name.startsWith ( p ) ) { + return true; + } + } + return false; + } + private boolean hasExtension ( String name, String extension ) { + return name.endsWith ( "." + extension ); + } + } ); + } + + private void processWordForms ( String dpn ) { + FileInputStream fis = null; + try { + fis = new FileInputStream ( dpn ); + if ( fis != null ) { + ObjectInputStream ois = new ObjectInputStream ( fis ); + List data = (List) ois.readObject(); + if ( data != null ) { + processWordForms ( data ); + } + ois.close(); + } + } catch ( FileNotFoundException e ) { + throw new RuntimeException ( e.getMessage(), e ); + } catch ( IOException e ) { + throw new RuntimeException ( e.getMessage(), e ); + } catch ( Exception e ) { + throw new RuntimeException ( e.getMessage(), e ); + } finally { + if ( fis != null ) { + try { fis.close(); } catch ( Exception e ) {} + } + } + } + + private void processWordForms ( List data ) { + assert data != null; + assert data.size() > 0; + String script = null; + String language = null; + String tfn = null; + TTXFile tf = null; + GlyphSubstitutionTable gsub = null; + GlyphPositioningTable gpos = null; + int[] widths = null; + for ( Object[] d : data ) { + if ( script == null ) { + assert d.length >= 4; + script = (String) d[0]; + language = (String) d[1]; + tfn = (String) d[3]; + tf = TTXFile.getFromCache ( ttxFontsDir + File.separator + tfn ); + assertTrue ( tf != null ); + gsub = tf.getGSUB(); + assertTrue ( gsub != null ); + gpos = tf.getGPOS(); + assertTrue ( gpos != null ); + widths = tf.getWidths(); + assertTrue ( widths != null ); + } else { + assert tf != null; + assert gsub != null; + assert gpos != null; + assert tfn != null; + assert d.length >= 4; + String wf = (String) d[0]; + int[] iga = (int[]) d[1]; + int[] oga = (int[]) d[2]; + int[][] paa = (int[][]) d[3]; + GlyphSequence tigs = tf.mapCharsToGlyphs ( wf ); + assertSameGlyphs ( iga, getGlyphs ( tigs ), "input glyphs", wf, tfn ); + GlyphSequence togs = gsub.substitute ( tigs, script, language ); + assertSameGlyphs ( oga, getGlyphs ( togs ), "output glyphs", wf, tfn ); + int[][] tpaa = new int [ togs.getGlyphCount() ] [ 4 ]; + if ( gpos.position ( togs, script, language, 1000, widths, tpaa ) ) { + assertSameAdjustments ( paa, tpaa, wf, tfn ); + } else if ( paa != null ) { + assertEquals ( "unequal adjustment count, word form(" + wf + "), font (" + tfn + ")", paa.length, 0 ); + } + } + } + } + + private void assertSameGlyphs ( int[] expected, int[] actual, String label, String wf, String tfn ) { + assertEquals ( label + ": unequal glyph count, word form(" + wf + "), font (" + tfn + ")", expected.length, actual.length ); + for ( int i = 0, n = expected.length; i < n; i++ ) { + int e = expected[i]; + int a = actual[i]; + assertEquals ( label + ": unequal glyphs[" + i + "], word form(" + wf + "), font (" + tfn + ")", e, a ); + } + } + + private void assertSameAdjustments ( int[][] expected, int[][] actual, String wf, String tfn ) { + assertEquals ( "unequal adjustment count, word form(" + wf + "), font (" + tfn + ")", expected.length, actual.length ); + for ( int i = 0, n = expected.length; i < n; i++ ) { + int[] ea = expected[i]; + int[] aa = actual[i]; + assertEquals ( "bad adjustments length, word form(" + wf + "), font (" + tfn + ")", ea.length, aa.length ); + for ( int k = 0; k < 4; k++ ) { + int e = ea[k]; + int a = aa[k]; + assertEquals ( "unequal adjustment[" + i + "][" + k + "], word form(" + wf + "), font (" + tfn + ")", e, a ); + } + } + } + + private static int[] getGlyphs ( GlyphSequence gs ) { + IntBuffer gb = gs.getGlyphs(); + int[] ga = new int [ gb.limit() ]; + gb.rewind(); + gb.get ( ga ); + return ga; + } + +} diff --git a/test/java/org/apache/fop/complexscripts/scripts/arabic/ArabicTestConstants.java b/test/java/org/apache/fop/complexscripts/scripts/arabic/ArabicTestConstants.java new file mode 100644 index 000000000..0669ff137 --- /dev/null +++ b/test/java/org/apache/fop/complexscripts/scripts/arabic/ArabicTestConstants.java @@ -0,0 +1,49 @@ +/* + * 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.complexscripts.scripts.arabic; + +/** + * Constants for test functionality related to the arabic script. + */ +public interface ArabicTestConstants { + + final String WF_FILE_SCRIPT = "arab"; + final String WF_FILE_LANGUAGE = "dflt"; + + String srcFilesDir = "test/resources/complexscripts/arab/data"; + String datFilesDir = "test/resources/complexscripts/arab/data"; + + String[] srcFiles = { + "arab-001", // unpointed word forms + }; + + final String WF_FILE_SRC_EXT = "txt"; + final String WF_FILE_DAT_EXT = "ser"; + + String ttxFontsDir = "test/resources/complexscripts/arab/ttx"; + + String[] ttxFonts = { + "arab-001.ttx", // simplified arabic + "arab-002.ttx", // traditional arabic + "arab-003.ttx", // lateef + "arab-004.ttx", // scheherazade + }; + +} diff --git a/test/java/org/apache/fop/complexscripts/scripts/arabic/GenerateArabicTestData.java b/test/java/org/apache/fop/complexscripts/scripts/arabic/GenerateArabicTestData.java new file mode 100644 index 000000000..4ae551344 --- /dev/null +++ b/test/java/org/apache/fop/complexscripts/scripts/arabic/GenerateArabicTestData.java @@ -0,0 +1,179 @@ +/* + * 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.complexscripts.scripts.arabic; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.LineNumberReader; +import java.io.ObjectOutputStream; +import java.nio.IntBuffer; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.List; + +import org.apache.fop.complexscripts.fonts.GlyphPositioningTable; +import org.apache.fop.complexscripts.fonts.GlyphSubstitutionTable; +import org.apache.fop.complexscripts.fonts.ttx.TTXFile; +import org.apache.fop.complexscripts.util.GlyphSequence; + +/** + * Tests for functionality related to the arabic script. + */ +public class GenerateArabicTestData implements ArabicTestConstants { + + public static void main ( String[] args ) { + boolean compile = false; + boolean help = false; + for ( String a : args ) { + if ( a.equals("-c") ) { + compile = true; + } + if ( a.equals("-?") ) { + help = true; + } + } + if ( help ) { + help(); + } else if ( compile ) { + compile(); + } + } + + private static void help() { + StringBuffer sb = new StringBuffer(); + sb.append ( "org.apache.fop.complexscripts.arabic.ArabicTestCase" ); + sb.append ( " [-compile]" ); + sb.append ( " [-?]" ); + System.out.println ( sb.toString() ); + } + + private static void compile() { + for ( String sfn : srcFiles ) { + try { + String spn = srcFilesDir + File.separator + sfn + "." + WF_FILE_SRC_EXT; + compile ( WF_FILE_SCRIPT, WF_FILE_LANGUAGE, spn ); + } catch ( Exception e ) { + System.err.println ( e.getMessage() ); + } + } + } + + private static void compile ( String script, String language, String spn ) { + int fno = 0; + for ( String tfn : ttxFonts ) { + TTXFile tf = TTXFile.getFromCache ( ttxFontsDir + File.separator + tfn ); + assert tf != null; + List data = compile ( script, language, spn, tfn, tf ); + output ( makeDataPathName ( spn, fno++ ), data ); + } + } + + private static List compile ( String script, String language, String spn, String tfn, TTXFile tf ) { + List data = new ArrayList(); + data.add ( new Object[] { script, language, spn, tfn } ); + GlyphSubstitutionTable gsub = tf.getGSUB(); + GlyphPositioningTable gpos = tf.getGPOS(); + int[] widths = tf.getWidths(); + if ( ( gsub != null ) && ( gpos != null ) ) { + FileInputStream fis = null; + try { + fis = new FileInputStream ( spn ); + if ( fis != null ) { + LineNumberReader lr = new LineNumberReader ( new InputStreamReader ( fis, Charset.forName ( "UTF-8" ) ) ); + String wf; + while ( ( wf = lr.readLine() ) != null ) { + GlyphSequence igs = tf.mapCharsToGlyphs ( wf ); + GlyphSequence ogs = gsub.substitute ( igs, script, language ); + int[][] paa = new int [ ogs.getGlyphCount() ] [ 4 ]; + if ( ! gpos.position ( ogs, script, language, 1000, widths, paa ) ) { + paa = null; + } + data.add ( new Object[] { wf, getGlyphs ( igs ), getGlyphs ( ogs ), paa } ); + } + lr.close(); + } + } catch ( FileNotFoundException e ) { + throw new RuntimeException ( e.getMessage(), e ); + } catch ( IOException e ) { + throw new RuntimeException ( e.getMessage(), e ); + } catch ( Exception e ) { + throw new RuntimeException ( e.getMessage(), e ); + } finally { + if ( fis != null ) { + try { fis.close(); } catch ( Exception e ) {} + } + } + } else { + assert gsub != null; + assert gpos != null; + } + System.err.println ( "compiled " + ( data.size() - 1 ) + " word forms using font " + tfn ); + return data; + } + + private static int[] getGlyphs ( GlyphSequence gs ) { + IntBuffer gb = gs.getGlyphs(); + int[] ga = new int [ gb.limit() ]; + gb.rewind(); + gb.get ( ga ); + return ga; + } + + private static String makeDataPathName ( String spn, int fno ) { + File f = new File ( spn ); + return datFilesDir + File.separator + stripExtension ( f.getName() ) + "-f" + fno + "." + WF_FILE_DAT_EXT; + } + + private static String stripExtension ( String s ) { + int i = s.lastIndexOf ( '.' ); + if ( i >= 0 ) { + return s.substring ( 0, i ); + } else { + return s; + } + } + + private static void output ( String dpn, List data ) { + FileOutputStream fos = null; + try { + fos = new FileOutputStream ( dpn ); + if ( fos != null ) { + ObjectOutputStream oos = new ObjectOutputStream ( fos ); + oos.writeObject ( data ); + oos.close(); + } + } catch ( FileNotFoundException e ) { + throw new RuntimeException ( e.getMessage(), e ); + } catch ( IOException e ) { + throw new RuntimeException ( e.getMessage(), e ); + } catch ( Exception e ) { + throw new RuntimeException ( e.getMessage(), e ); + } finally { + if ( fos != null ) { + try { fos.close(); } catch ( Exception e ) {} + } + } + } + +} diff --git a/test/java/org/apache/fop/complexscripts/util/NumberConverterTestCase.java b/test/java/org/apache/fop/complexscripts/util/NumberConverterTestCase.java new file mode 100644 index 000000000..55506b550 --- /dev/null +++ b/test/java/org/apache/fop/complexscripts/util/NumberConverterTestCase.java @@ -0,0 +1,1564 @@ +/* + * 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.complexscripts.util; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +// CSOFF: LineLengthCheck + +/** + * Test number converter functionality. + * + * @author Glenn Adams + */ +public class NumberConverterTestCase { + + static private String[][] formatDecimal = + { + { "1" }, + { "0", "0" }, + { "1", "1" }, + { "1000", "1000" }, + { "1000000", "1000000" }, + { "1000000000", "1000000000" }, + }; + + static private String[][] formatDecimalPadded = + { + { "001" }, + { "0", "000" }, + { "1", "001" }, + { "9", "009" }, + { "10", "010" }, + { "99", "099" }, + { "100", "100" }, + { "999", "999" }, + { "1000", "1000" }, + }; + + static private String[][] formatDecimalGrouped = + { + { "1", ",", "1" }, + { "0", "0" }, + { "1", "1" }, + { "1000", "1,0,0,0" }, + { "1000000", "1,0,0,0,0,0,0" }, + { "1000000000", "1,0,0,0,0,0,0,0,0,0" }, + }; + + static private String[][] formatDecimalGroupedPadded = + { + { "001", ",", "2" }, + { "0", "0,00" }, + { "1", "0,01" }, + { "9", "0,09" }, + { "10", "0,10" }, + { "99", "0,99" }, + { "100", "1,00" }, + { "999", "9,99" }, + { "1000", "10,00" }, + }; + + static private String[][] formatDecimalArabic = + { + { "\u0661" }, + { "0", "\u0660" }, + { "1", "\u0661" }, + { "2", "\u0662" }, + { "3", "\u0663" }, + { "4", "\u0664" }, + { "5", "\u0665" }, + { "6", "\u0666" }, + { "7", "\u0667" }, + { "8", "\u0668" }, + { "9", "\u0669" }, + { "10", "\u0661\u0660" }, + { "1000", "\u0661\u0660\u0660\u0660" }, + { "1000000", "\u0661\u0660\u0660\u0660\u0660\u0660\u0660" }, + { "1000000000", "\u0661\u0660\u0660\u0660\u0660\u0660\u0660\u0660\u0660\u0660" }, + }; + + static private String[][] formatDecimalArabicPadded = + { + { "\u0660\u0660\u0661" }, + { "0", "\u0660\u0660\u0660" }, + { "1", "\u0660\u0660\u0661" }, + { "9", "\u0660\u0660\u0669" }, + { "10", "\u0660\u0661\u0660" }, + { "99", "\u0660\u0669\u0669" }, + { "100", "\u0661\u0660\u0660" }, + { "999", "\u0669\u0669\u0669" }, + { "1000", "\u0661\u0660\u0660\u0660" }, + }; + + static private String[][] formatDecimalArabicGrouped = + { + { "\u0661", "\u066c", "1" }, + { "0", "\u0660" }, + { "1", "\u0661" }, + { "1000", "\u0661\u066c\u0660\u066c\u0660\u066c\u0660" }, + { "1000000", "\u0661\u066c\u0660\u066c\u0660\u066c\u0660\u066c\u0660\u066c\u0660\u066c\u0660" }, + { "1000000000", "\u0661\u066c\u0660\u066c\u0660\u066c\u0660\u066c\u0660\u066c\u0660\u066c\u0660\u066c\u0660\u066c\u0660\u066c\u0660" }, + }; + + static private String[][] formatDecimalArabicGroupedPadded = + { + { "\u0660\u0660\u0661", "\u066c", "2" }, + { "0", "\u0660\u066c\u0660\u0660" }, + { "1", "\u0660\u066c\u0660\u0661" }, + { "9", "\u0660\u066c\u0660\u0669" }, + { "10", "\u0660\u066c\u0661\u0660" }, + { "99", "\u0660\u066c\u0669\u0669" }, + { "100", "\u0661\u066c\u0660\u0660" }, + { "999", "\u0669\u066c\u0669\u0669" }, + { "1000", "\u0661\u0660\u066c\u0660\u0660" }, + }; + + static private String[][] formatDecimalThai = + { + { "\u0E51" }, + { "0", "\u0E50" }, + { "1", "\u0E51" }, + { "2", "\u0E52" }, + { "3", "\u0E53" }, + { "4", "\u0E54" }, + { "5", "\u0E55" }, + { "6", "\u0E56" }, + { "7", "\u0E57" }, + { "8", "\u0E58" }, + { "9", "\u0E59" }, + { "10", "\u0E51\u0E50" }, + { "1000", "\u0E51\u0E50\u0E50\u0E50" }, + { "1000000", "\u0E51\u0E50\u0E50\u0E50\u0E50\u0E50\u0E50" }, + { "1000000000", "\u0E51\u0E50\u0E50\u0E50\u0E50\u0E50\u0E50\u0E50\u0E50\u0E50" }, + }; + + static private String[][] formatDecimalThaiPadded = + { + { "\u0E50\u0E50\u0E51" }, + { "0", "\u0E50\u0E50\u0E50" }, + { "1", "\u0E50\u0E50\u0E51" }, + { "9", "\u0E50\u0E50\u0E59" }, + { "10", "\u0E50\u0E51\u0E50" }, + { "99", "\u0E50\u0E59\u0E59" }, + { "100", "\u0E51\u0E50\u0E50" }, + { "999", "\u0E59\u0E59\u0E59" }, + { "1000", "\u0E51\u0E50\u0E50\u0E50" }, + }; + + static private String[][] formatRomanLower = + { + { "i" }, + { "0", "0" }, + { "1", "i" }, + { "2", "ii" }, + { "3", "iii" }, + { "4", "iv" }, + { "5", "v" }, + { "6", "vi" }, + { "7", "vii" }, + { "8", "viii" }, + { "9", "ix" }, + { "10", "x" }, + { "20", "xx" }, + { "30", "xxx" }, + { "40", "xl" }, + { "50", "l" }, + { "60", "lx" }, + { "70", "lxx" }, + { "80", "lxxx" }, + { "90", "xc" }, + { "100", "c" }, + { "200", "cc" }, + { "300", "ccc" }, + { "400", "cd" }, + { "500", "d" }, + { "600", "dc" }, + { "700", "dcc" }, + { "800", "dccc" }, + { "900", "cm" }, + { "1000", "m" }, + { "2000", "mm" }, + { "2011", "mmxi" }, + { "4999", "mmmmcmxcix" }, + { "5000", "5000" }, + }; + + static private String[][] formatRomanUpper = + { + + { "I" }, + { "0", "0" }, + { "1", "I" }, + { "2", "II" }, + { "3", "III" }, + { "4", "IV" }, + { "5", "V" }, + { "6", "VI" }, + { "7", "VII" }, + { "8", "VIII" }, + { "9", "IX" }, + { "10", "X" }, + { "20", "XX" }, + { "30", "XXX" }, + { "40", "XL" }, + { "50", "L" }, + { "60", "LX" }, + { "70", "LXX" }, + { "80", "LXXX" }, + { "90", "XC" }, + { "100", "C" }, + { "200", "CC" }, + { "300", "CCC" }, + { "400", "CD" }, + { "500", "D" }, + { "600", "DC" }, + { "700", "DCC" }, + { "800", "DCCC" }, + { "900", "CM" }, + { "1000", "M" }, + { "2000", "MM" }, + { "2011", "MMXI" }, + { "4999", "MMMMCMXCIX" }, + { "5000", "5000" }, + }; + + static private String[][] formatRomanLargeLower = + { + { "i", null, null, null, "large" }, + { "0", "0" }, + { "1", "i" }, + { "2", "ii" }, + { "3", "iii" }, + { "4", "iv" }, + { "5", "v" }, + { "6", "vi" }, + { "7", "vii" }, + { "8", "viii" }, + { "9", "ix" }, + { "10", "x" }, + { "20", "xx" }, + { "30", "xxx" }, + { "40", "xl" }, + { "50", "l" }, + { "60", "lx" }, + { "70", "lxx" }, + { "80", "lxxx" }, + { "90", "xc" }, + { "100", "c" }, + { "200", "cc" }, + { "300", "ccc" }, + { "400", "cd" }, + { "500", "d" }, + { "600", "dc" }, + { "700", "dcc" }, + { "800", "dccc" }, + { "900", "cm" }, + { "1000", "m" }, + { "2000", "mm" }, + { "2011", "mmxi" }, + { "4999", "\u2180\u2181cmxcix" }, + { "5000", "\u2181" }, + { "5001", "\u2181i" }, + { "9999", "\u2180\u2182cmxcix" }, + { "10000", "\u2182" }, + { "10001", "\u2182i" }, + { "49999", "\u2182\u2187\u2180\u2182cmxcix" }, + { "99999", "\u2182\u2188\u2180\u2182cmxcix" }, + { "100000", "\u2188" }, + { "100001", "\u2188i" }, + { "199999", "\u2188\u2182\u2188\u2180\u2182cmxcix" }, + { "200000", "200000" }, + }; + + static private String[][] formatRomanLargeUpper = + { + { "I", null, null, null, "large" }, + { "0", "0" }, + { "1", "I" }, + { "2", "II" }, + { "3", "III" }, + { "4", "IV" }, + { "5", "V" }, + { "6", "VI" }, + { "7", "VII" }, + { "8", "VIII" }, + { "9", "IX" }, + { "10", "X" }, + { "20", "XX" }, + { "30", "XXX" }, + { "40", "XL" }, + { "50", "L" }, + { "60", "LX" }, + { "70", "LXX" }, + { "80", "LXXX" }, + { "90", "XC" }, + { "100", "C" }, + { "200", "CC" }, + { "300", "CCC" }, + { "400", "CD" }, + { "500", "D" }, + { "600", "DC" }, + { "700", "DCC" }, + { "800", "DCCC" }, + { "900", "CM" }, + { "1000", "M" }, + { "2000", "MM" }, + { "2011", "MMXI" }, + { "4999", "\u2180\u2181CMXCIX" }, + { "5000", "\u2181" }, + { "5001", "\u2181I" }, + { "9999", "\u2180\u2182CMXCIX" }, + { "10000", "\u2182" }, + { "10001", "\u2182I" }, + { "49999", "\u2182\u2187\u2180\u2182CMXCIX" }, + { "99999", "\u2182\u2188\u2180\u2182CMXCIX" }, + { "100000", "\u2188" }, + { "100001", "\u2188I" }, + { "199999", "\u2188\u2182\u2188\u2180\u2182CMXCIX" }, + { "200000", "200000" }, + }; + + static private String[][] formatRomanNumberFormsLower = + { + { "i", null, null, null, "unicode-number-forms" }, + { "0", "0" }, + { "1", "\u2170" }, + { "2", "\u2171" }, + { "3", "\u2172" }, + { "4", "\u2173" }, + { "5", "\u2174" }, + { "6", "\u2175" }, + { "7", "\u2176" }, + { "8", "\u2177" }, + { "9", "\u2178" }, + { "10", "\u2179" }, + { "11", "\u2179\u2170" }, + { "12", "\u2179\u2171" }, + { "13", "\u2179\u2172" }, + { "14", "\u2179\u2173" }, + { "15", "\u2179\u2174" }, + { "16", "\u2179\u2175" }, + { "17", "\u2179\u2176" }, + { "18", "\u2179\u2177" }, + { "19", "\u2179\u2178" }, + { "20", "\u2179\u2179" }, + { "30", "\u2179\u2179\u2179" }, + { "40", "\u2179\u217C" }, + { "50", "\u217C" }, + { "60", "\u217C\u2179" }, + { "70", "\u217C\u2179\u2179" }, + { "80", "\u217C\u2179\u2179\u2179" }, + { "90", "\u2179\u217D" }, + { "100", "\u217D" }, + { "200", "\u217D\u217D" }, + { "300", "\u217D\u217D\u217D" }, + { "400", "\u217D\u217E" }, + { "500", "\u217E" }, + { "600", "\u217E\u217D" }, + { "700", "\u217E\u217D\u217D" }, + { "800", "\u217E\u217D\u217D\u217D" }, + { "900", "\u217D\u217F" }, + { "999", "\u217D\u217F\u2179\u217D\u2178" }, + { "1000", "\u217F" }, + { "2000", "\u217F\u217F" }, + { "2011", "\u217F\u217F\u2179\u2170" }, + { "4999", "\u2180\u2181\u217D\u217F\u2179\u217D\u2178" }, + { "5000", "\u2181" }, + { "5001", "\u2181\u2170" }, + { "9999", "\u2180\u2182\u217D\u217F\u2179\u217D\u2178" }, + { "10000", "\u2182" }, + { "10001", "\u2182\u2170" }, + { "49999", "\u2182\u2187\u2180\u2182\u217D\u217F\u2179\u217D\u2178" }, + { "99999", "\u2182\u2188\u2180\u2182\u217D\u217F\u2179\u217D\u2178" }, + { "100000", "\u2188" }, + { "100001", "\u2188\u2170" }, + { "199999", "\u2188\u2182\u2188\u2180\u2182\u217D\u217F\u2179\u217D\u2178" }, + { "200000", "200000" }, + }; + + static private String[][] formatRomanNumberFormsUpper = + { + { "I", null, null, null, "unicode-number-forms" }, + { "0", "0" }, + { "1", "\u2160" }, + { "2", "\u2161" }, + { "3", "\u2162" }, + { "4", "\u2163" }, + { "5", "\u2164" }, + { "6", "\u2165" }, + { "7", "\u2166" }, + { "8", "\u2167" }, + { "9", "\u2168" }, + { "10", "\u2169" }, + { "11", "\u2169\u2160" }, + { "12", "\u2169\u2161" }, + { "13", "\u2169\u2162" }, + { "14", "\u2169\u2163" }, + { "15", "\u2169\u2164" }, + { "16", "\u2169\u2165" }, + { "17", "\u2169\u2166" }, + { "18", "\u2169\u2167" }, + { "19", "\u2169\u2168" }, + { "20", "\u2169\u2169" }, + { "30", "\u2169\u2169\u2169" }, + { "40", "\u2169\u216C" }, + { "50", "\u216C" }, + { "60", "\u216C\u2169" }, + { "70", "\u216C\u2169\u2169" }, + { "80", "\u216C\u2169\u2169\u2169" }, + { "90", "\u2169\u216D" }, + { "100", "\u216D" }, + { "200", "\u216D\u216D" }, + { "300", "\u216D\u216D\u216D" }, + { "400", "\u216D\u216E" }, + { "500", "\u216E" }, + { "600", "\u216E\u216D" }, + { "700", "\u216E\u216D\u216D" }, + { "800", "\u216E\u216D\u216D\u216D" }, + { "900", "\u216D\u216F" }, + { "999", "\u216D\u216F\u2169\u216D\u2168" }, + { "1000", "\u216F" }, + { "2000", "\u216F\u216F" }, + { "2011", "\u216F\u216F\u2169\u2160" }, + { "4999", "\u2180\u2181\u216D\u216F\u2169\u216D\u2168" }, + { "5000", "\u2181" }, + { "5001", "\u2181\u2160" }, + { "9999", "\u2180\u2182\u216D\u216F\u2169\u216D\u2168" }, + { "10000", "\u2182" }, + { "10001", "\u2182\u2160" }, + { "49999", "\u2182\u2187\u2180\u2182\u216D\u216F\u2169\u216D\u2168" }, + { "99999", "\u2182\u2188\u2180\u2182\u216D\u216F\u2169\u216D\u2168" }, + { "100000", "\u2188" }, + { "100001", "\u2188\u2160" }, + { "199999", "\u2188\u2182\u2188\u2180\u2182\u216D\u216F\u2169\u216D\u2168" }, + { "200000", "200000" }, + }; + + static private String[][] formatAlphabeticLatinLower = + { + { "a" }, + { "0", "0" }, + { "1", "a" }, + { "2", "b" }, + { "3", "c" }, + { "10", "j" }, + { "20", "t" }, + { "26", "z" }, + { "27", "aa" }, + { "28", "ab" }, + { "29", "ac" }, + { "52", "az" }, + { "53", "ba" }, + { "702", "zz" }, + { "703", "aaa" }, + { "999999", "bdwgm" }, + { "1000000", "bdwgn" }, + }; + + static private String[][] formatAlphabeticLatinUpper = + { + { "A" }, + { "0", "0" }, + { "1", "A" }, + { "2", "B" }, + { "3", "C" }, + { "10", "J" }, + { "20", "T" }, + { "26", "Z" }, + { "27", "AA" }, + { "28", "AB" }, + { "29", "AC" }, + { "52", "AZ" }, + { "53", "BA" }, + { "702", "ZZ" }, + { "703", "AAA" }, + { "999999", "BDWGM" }, + { "1000000", "BDWGN" }, + }; + + static private String[][] formatAlphabeticArabicHijai = + { + { "\u0627", null, null, "alphabetic" }, + { "0", "0" }, + { "1", "\u0623" }, + { "2", "\u0628" }, + { "3", "\u062A" }, + { "4", "\u062B" }, + { "5", "\u062C" }, + { "6", "\u062D" }, + { "7", "\u062E" }, + { "8", "\u062F" }, + { "9", "\u0630" }, + { "10", "\u0631" }, + { "11", "\u0632" }, + { "12", "\u0633" }, + { "13", "\u0634" }, + { "14", "\u0635" }, + { "15", "\u0636" }, + { "16", "\u0637" }, + { "17", "\u0638" }, + { "18", "\u0639" }, + { "19", "\u063A" }, + { "20", "\u0641" }, + { "21", "\u0642" }, + { "22", "\u0643" }, + { "23", "\u0644" }, + { "24", "\u0645" }, + { "25", "\u0646" }, + { "26", "\u0647" }, + { "27", "\u0648" }, + { "28", "\u0649" }, + { "29", "\u0623\u0623" }, + { "56", "\u0623\u0649" }, + { "57", "\u0628\u0623" }, + { "812", "\u0649\u0649" }, + { "813", "\u0623\u0623\u0623" }, + { "999999", "\u0623\u0638\u0636\u0635\u062E" }, + { "1000000", "\u0623\u0638\u0636\u0635\u062F" }, + }; + + static private String[][] formatAlphabeticArabicAbjadi = + { + { "\u0627", null, null, "traditional" }, + { "0", "0" }, + { "1", "\u0623" }, + { "2", "\u0628" }, + { "3", "\u062C" }, + { "4", "\u062F" }, + { "5", "\u0647" }, + { "6", "\u0648" }, + { "7", "\u0632" }, + { "8", "\u062D" }, + { "9", "\u0637" }, + { "10", "\u0649" }, + { "11", "\u0643" }, + { "12", "\u0644" }, + { "13", "\u0645" }, + { "14", "\u0646" }, + { "15", "\u0633" }, + { "16", "\u0639" }, + { "17", "\u0641" }, + { "18", "\u0635" }, + { "19", "\u0642" }, + { "20", "\u0631" }, + { "21", "\u0634" }, + { "22", "\u062A" }, + { "23", "\u062B" }, + { "24", "\u062E" }, + { "25", "\u0630" }, + { "26", "\u0636" }, + { "27", "\u0638" }, + { "28", "\u063A" }, + { "29", "\u0623\u0623" }, + { "56", "\u0623\u063A" }, + { "57", "\u0628\u0623" }, + { "812", "\u063A\u063A" }, + { "813", "\u0623\u0623\u0623" }, + { "999999", "\u0623\u0641\u0633\u0646\u0632" }, + { "1000000", "\u0623\u0641\u0633\u0646\u062D" }, + }; + + static private String[][] formatNumeralArabicAbjadi = + { + { "\u0623", null, null, "traditional" }, + { "0", "0" }, + { "1", "\u0623" }, + { "2", "\u0628" }, + { "3", "\u062C" }, + { "4", "\u062F" }, + { "5", "\u0647" }, + { "6", "\u0648" }, + { "7", "\u0632" }, + { "8", "\u062D" }, + { "9", "\u0637" }, + { "10", "\u0649" }, + { "11", "\u0649\u0623" }, + { "12", "\u0649\u0628" }, + { "13", "\u0649\u062C" }, + { "14", "\u0649\u062F" }, + { "15", "\u0649\u0647" }, + { "16", "\u0649\u0648" }, + { "17", "\u0649\u0632" }, + { "18", "\u0649\u062D" }, + { "19", "\u0649\u0637" }, + { "20", "\u0643" }, + { "30", "\u0644" }, + { "40", "\u0645" }, + { "50", "\u0646" }, + { "60", "\u0633" }, + { "70", "\u0639" }, + { "80", "\u0641" }, + { "90", "\u0635" }, + { "99", "\u0635\u0637" }, + { "100", "\u0642" }, + { "101", "\u0642\u0623" }, + { "200", "\u0631" }, + { "300", "\u0634" }, + { "400", "\u062A" }, + { "500", "\u062B" }, + { "600", "\u062E" }, + { "700", "\u0630" }, + { "800", "\u0636" }, + { "900", "\u0638" }, + { "999", "\u0638\u0635\u0637" }, + { "1000", "\u063A" }, + { "1999", "\u063A\u0638\u0635\u0637" }, + { "2000", "2000" }, + }; + + static private String[][] formatAlphabeticHebrew = + { + { "\u05D0", null, null, "alphabetic" }, + { "0", "0" }, + { "1", "\u05D0" }, + { "2", "\u05D1" }, + { "3", "\u05D2" }, + { "4", "\u05D3" }, + { "5", "\u05D4" }, + { "6", "\u05D5" }, + { "7", "\u05D6" }, + { "8", "\u05D7" }, + { "9", "\u05D8" }, + { "10", "\u05D9" }, + { "11", "\u05DB" }, + { "12", "\u05DC" }, + { "13", "\u05DE" }, + { "14", "\u05E0" }, + { "15", "\u05E1" }, + { "16", "\u05E2" }, + { "17", "\u05E4" }, + { "18", "\u05E6" }, + { "19", "\u05E7" }, + { "20", "\u05E8" }, + { "21", "\u05E9" }, + { "22", "\u05EA" }, + { "23", "\u05DA" }, + { "24", "\u05DD" }, + { "25", "\u05DF" }, + { "26", "\u05E3" }, + { "27", "\u05E5" }, + { "28", "\u05D0\u05D0" }, + { "54", "\u05D0\u05E5" }, + { "55", "\u05D1\u05D0" }, + { "756", "\u05E5\u05E5" }, + { "757", "\u05D0\u05D0\u05D0" }, + { "999999", "\u05D0\u05DA\u05E9\u05E7\u05E5" }, + { "1000000", "\u05D0\u05DA\u05E9\u05E8\u05D0" }, + }; + + static private String[][] formatNumeralHebrewGematria = + { + { "\u05D0", null, null, "traditional" }, + { "0", "0" }, + { "1", "\u05D0" }, + { "2", "\u05D1" }, + { "3", "\u05D2" }, + { "4", "\u05D3" }, + { "5", "\u05D4" }, + { "6", "\u05D5" }, + { "7", "\u05D6" }, + { "8", "\u05D7" }, + { "9", "\u05D8" }, + { "10", "\u05D9" }, + { "11", "\u05D9\u05D0" }, + { "12", "\u05D9\u05D1" }, + { "13", "\u05D9\u05D2" }, + { "14", "\u05D9\u05D3" }, + { "15", "\u05D8\u05F4\u05D5" }, + { "16", "\u05D8\u05F4\u05D6" }, + { "17", "\u05D9\u05D6" }, + { "18", "\u05D9\u05D7" }, + { "19", "\u05D9\u05D8" }, + { "20", "\u05DB" }, + { "30", "\u05DC" }, + { "40", "\u05DE" }, + { "50", "\u05E0" }, + { "60", "\u05E1" }, + { "70", "\u05E2" }, + { "80", "\u05E4" }, + { "90", "\u05E6" }, + { "99", "\u05E6\u05D8" }, + { "100", "\u05E7" }, + { "101", "\u05E7\u05D0" }, + { "200", "\u05E8" }, + { "300", "\u05E9" }, + { "400", "\u05EA" }, + { "500", "\u05EA\u05F4\u05E7" }, + { "600", "\u05EA\u05F4\u05E8" }, + { "700", "\u05EA\u05F4\u05E9" }, + { "800", "\u05EA\u05F4\u05EA" }, + { "900", "\u05EA\u05EA\u05F4\u05E7" }, + { "999", "\u05EA\u05EA\u05F4\u05E7\u05E6\u05D8" }, + { "1000", "\u05D0\u05F3" }, + { "1999", "\u05D0\u05F3\u05EA\u05EA\u05F4\u05E7\u05E6\u05D8" }, + { "2000", "2000" }, + }; + + static private String[][] formatAlphabeticThai = + { + { "\u0E01", null, null, "alphabetic" }, + { "0", "0" }, + { "1", "\u0E01" }, + { "2", "\u0E02" }, + { "3", "\u0E03" }, + { "10", "\u0E0A" }, + { "20", "\u0E14" }, + { "30", "\u0E1E" }, + { "40", "\u0E2A" }, + { "44", "\u0E2E" }, + { "45", "\u0E01\u0E01" }, + { "88", "\u0E01\u0E2E" }, + { "89", "\u0E02\u0E01" }, + { "1980", "\u0E2E\u0E2E" }, + { "1981", "\u0E01\u0E01\u0E01" }, + { "999999", "\u0E0B\u0E20\u0E17\u0E0B" }, + { "1000000", "\u0E0B\u0E20\u0E17\u0E0C" }, + }; + + static private String[][] formatWordEnglishLower = + { + { "w", null, null, null, null, "eng" }, + { "0", "zero" }, + { "1", "one" }, + { "2", "two" }, + { "3", "three" }, + { "4", "four" }, + { "5", "five" }, + { "6", "six" }, + { "7", "seven" }, + { "8", "eight" }, + { "9", "nine" }, + { "10", "ten" }, + { "99", "ninety nine" }, + { "100", "one hundred" }, + { "999", "nine hundred ninety nine" }, + { "1000", "one thousand" }, + { "999999", "nine hundred ninety nine thousand nine hundred ninety nine" }, + { "1000000", "one million" }, + { "999999999", "nine hundred ninety nine million nine hundred ninety nine thousand nine hundred ninety nine" }, + { "1000000000", "one billion" } + }; + + static private String[][] formatWordEnglishUpper = + { + { "W", null, null, null, null, "eng" }, + { "0", "ZERO" }, + { "1", "ONE" }, + { "2", "TWO" }, + { "3", "THREE" }, + { "4", "FOUR" }, + { "5", "FIVE" }, + { "6", "SIX" }, + { "7", "SEVEN" }, + { "8", "EIGHT" }, + { "9", "NINE" }, + { "10", "TEN" }, + { "99", "NINETY NINE" }, + { "100", "ONE HUNDRED" }, + { "999", "NINE HUNDRED NINETY NINE" }, + { "1000", "ONE THOUSAND" }, + { "999999", "NINE HUNDRED NINETY NINE THOUSAND NINE HUNDRED NINETY NINE" }, + { "1000000", "ONE MILLION" }, + { "999999999", "NINE HUNDRED NINETY NINE MILLION NINE HUNDRED NINETY NINE THOUSAND NINE HUNDRED NINETY NINE" }, + { "1000000000", "ONE BILLION" } + }; + + static private String[][] formatWordEnglishTitle = + { + { "Ww", null, null, null, null, "eng" }, + { "0", "Zero" }, + { "1", "One" }, + { "2", "Two" }, + { "3", "Three" }, + { "4", "Four" }, + { "5", "Five" }, + { "6", "Six" }, + { "7", "Seven" }, + { "8", "Eight" }, + { "9", "Nine" }, + { "10", "Ten" }, + { "99", "Ninety Nine" }, + { "100", "One Hundred" }, + { "999", "Nine Hundred Ninety Nine" }, + { "1000", "One Thousand" }, + { "999999", "Nine Hundred Ninety Nine Thousand Nine Hundred Ninety Nine" }, + { "1000000", "One Million" }, + { "999999999", "Nine Hundred Ninety Nine Million Nine Hundred Ninety Nine Thousand Nine Hundred Ninety Nine" }, + { "1000000000", "One Billion" } + }; + + static private String[][] formatWordSpanishLower = + { + { "w", null, null, null, null, "spa" }, + { "0", "cero" }, + { "1", "uno" }, + { "2", "dos" }, + { "3", "tres" }, + { "4", "cuatro" }, + { "5", "cinco" }, + { "6", "seise" }, + { "7", "siete" }, + { "8", "ocho" }, + { "9", "nueve" }, + { "10", "diez" }, + { "11", "once" }, + { "12", "doce" }, + { "13", "trece" }, + { "14", "catorce" }, + { "15", "quince" }, + { "16", "diecis\u00e9is" }, + { "17", "diecisiete" }, + { "18", "dieciocho" }, + { "19", "diecinueve" }, + { "20", "veinte" }, + { "21", "veintiuno" }, + { "22", "veintid\u00f3s" }, + { "23", "veintitr\u00e9s" }, + { "24", "veinticuatro" }, + { "25", "veinticinco" }, + { "26", "veintis\u00e9is" }, + { "27", "veintisiete" }, + { "28", "veintiocho" }, + { "29", "veintinueve" }, + { "30", "treinta" }, + { "31", "treinta y uno" }, + { "32", "treinta y dos" }, + { "40", "cuarenta" }, + { "41", "cuarenta y uno" }, + { "42", "cuarenta y dos" }, + { "50", "cincuenta" }, + { "51", "cincuenta y uno" }, + { "52", "cincuenta y dos" }, + { "60", "sesenta" }, + { "61", "sesenta y uno" }, + { "62", "sesenta y dos" }, + { "70", "setenta" }, + { "71", "setenta y uno" }, + { "72", "setenta y dos" }, + { "80", "ochenta" }, + { "81", "ochenta y uno" }, + { "82", "ochenta y dos" }, + { "90", "noventa" }, + { "91", "noventa y uno" }, + { "92", "noventa y dos" }, + { "99", "noventa y nueve" }, + { "100", "cien" }, + { "101", "ciento uno" }, + { "102", "ciento dos" }, + { "200", "doscientos" }, + { "300", "trescientos" }, + { "400", "cuatrocientos" }, + { "500", "quinientos" }, + { "600", "seiscientos" }, + { "700", "setecientos" }, + { "800", "ochocientos" }, + { "900", "novecientos" }, + { "999", "novecientos noventa y nueve" }, + { "1000", "mil" }, + { "1001", "mil uno" }, + { "1002", "mil dos" }, + { "2000", "dos mil" }, + { "2001", "dos mil uno" }, + { "100000", "cien mil" }, + { "100001", "cien mil uno" }, + { "999999", "novecientos noventa y nueve mil novecientos noventa y nueve" }, + { "1000000", "un mill\u00f3n" }, + { "999999999", "novecientos noventa y nueve millones novecientos noventa y nueve mil novecientos noventa y nueve" }, + { "1000000000", "mil millones" } + }; + + static private String[][] formatWordSpanishUpper = + { + { "W", null, null, null, null, "spa" }, + { "0", "CERO" }, + { "1", "UNO" }, + { "2", "DOS" }, + { "3", "TRES" }, + { "4", "CUATRO" }, + { "5", "CINCO" }, + { "6", "SEISE" }, + { "7", "SIETE" }, + { "8", "OCHO" }, + { "9", "NUEVE" }, + { "10", "DIEZ" }, + { "11", "ONCE" }, + { "12", "DOCE" }, + { "13", "TRECE" }, + { "14", "CATORCE" }, + { "15", "QUINCE" }, + { "16", "DIECIS\u00c9IS" }, + { "17", "DIECISIETE" }, + { "18", "DIECIOCHO" }, + { "19", "DIECINUEVE" }, + { "20", "VEINTE" }, + { "21", "VEINTIUNO" }, + { "22", "VEINTID\u00d3S" }, + { "23", "VEINTITR\u00c9S" }, + { "24", "VEINTICUATRO" }, + { "25", "VEINTICINCO" }, + { "26", "VEINTIS\u00c9IS" }, + { "27", "VEINTISIETE" }, + { "28", "VEINTIOCHO" }, + { "29", "VEINTINUEVE" }, + { "30", "TREINTA" }, + { "31", "TREINTA Y UNO" }, + { "32", "TREINTA Y DOS" }, + { "40", "CUARENTA" }, + { "41", "CUARENTA Y UNO" }, + { "42", "CUARENTA Y DOS" }, + { "50", "CINCUENTA" }, + { "51", "CINCUENTA Y UNO" }, + { "52", "CINCUENTA Y DOS" }, + { "60", "SESENTA" }, + { "61", "SESENTA Y UNO" }, + { "62", "SESENTA Y DOS" }, + { "70", "SETENTA" }, + { "71", "SETENTA Y UNO" }, + { "72", "SETENTA Y DOS" }, + { "80", "OCHENTA" }, + { "81", "OCHENTA Y UNO" }, + { "82", "OCHENTA Y DOS" }, + { "90", "NOVENTA" }, + { "91", "NOVENTA Y UNO" }, + { "92", "NOVENTA Y DOS" }, + { "99", "NOVENTA Y NUEVE" }, + { "100", "CIEN" }, + { "101", "CIENTO UNO" }, + { "102", "CIENTO DOS" }, + { "200", "DOSCIENTOS" }, + { "300", "TRESCIENTOS" }, + { "400", "CUATROCIENTOS" }, + { "500", "QUINIENTOS" }, + { "600", "SEISCIENTOS" }, + { "700", "SETECIENTOS" }, + { "800", "OCHOCIENTOS" }, + { "900", "NOVECIENTOS" }, + { "999", "NOVECIENTOS NOVENTA Y NUEVE" }, + { "1000", "MIL" }, + { "1001", "MIL UNO" }, + { "1002", "MIL DOS" }, + { "2000", "DOS MIL" }, + { "2001", "DOS MIL UNO" }, + { "100000", "CIEN MIL" }, + { "100001", "CIEN MIL UNO" }, + { "999999", "NOVECIENTOS NOVENTA Y NUEVE MIL NOVECIENTOS NOVENTA Y NUEVE" }, + { "1000000", "UN MILL\u00d3N" }, + { "999999999", "NOVECIENTOS NOVENTA Y NUEVE MILLONES NOVECIENTOS NOVENTA Y NUEVE MIL NOVECIENTOS NOVENTA Y NUEVE" }, + { "1000000000", "MIL MILLONES" } + }; + + static private String[][] formatWordSpanishTitle = + { + { "Ww", null, null, null, null, "spa" }, + { "0", "Cero" }, + { "1", "Uno" }, + { "2", "Dos" }, + { "3", "Tres" }, + { "4", "Cuatro" }, + { "5", "Cinco" }, + { "6", "Seise" }, + { "7", "Siete" }, + { "8", "Ocho" }, + { "9", "Nueve" }, + { "10", "Diez" }, + { "11", "Once" }, + { "12", "Doce" }, + { "13", "Trece" }, + { "14", "Catorce" }, + { "15", "Quince" }, + { "16", "Diecis\u00e9is" }, + { "17", "Diecisiete" }, + { "18", "Dieciocho" }, + { "19", "Diecinueve" }, + { "20", "Veinte" }, + { "21", "Veintiuno" }, + { "22", "Veintid\u00f3s" }, + { "23", "Veintitr\u00e9s" }, + { "24", "Veinticuatro" }, + { "25", "Veinticinco" }, + { "26", "Veintis\u00e9is" }, + { "27", "Veintisiete" }, + { "28", "Veintiocho" }, + { "29", "Veintinueve" }, + { "30", "Treinta" }, + { "31", "Treinta Y Uno" }, + { "32", "Treinta Y Dos" }, + { "40", "Cuarenta" }, + { "41", "Cuarenta Y Uno" }, + { "42", "Cuarenta Y Dos" }, + { "50", "Cincuenta" }, + { "51", "Cincuenta Y Uno" }, + { "52", "Cincuenta Y Dos" }, + { "60", "Sesenta" }, + { "61", "Sesenta Y Uno" }, + { "62", "Sesenta Y Dos" }, + { "70", "Setenta" }, + { "71", "Setenta Y Uno" }, + { "72", "Setenta Y Dos" }, + { "80", "Ochenta" }, + { "81", "Ochenta Y Uno" }, + { "82", "Ochenta Y Dos" }, + { "90", "Noventa" }, + { "91", "Noventa Y Uno" }, + { "92", "Noventa Y Dos" }, + { "99", "Noventa Y Nueve" }, + { "100", "Cien" }, + { "101", "Ciento Uno" }, + { "102", "Ciento Dos" }, + { "200", "Doscientos" }, + { "300", "Trescientos" }, + { "400", "Cuatrocientos" }, + { "500", "Quinientos" }, + { "600", "Seiscientos" }, + { "700", "Setecientos" }, + { "800", "Ochocientos" }, + { "900", "Novecientos" }, + { "999", "Novecientos Noventa Y Nueve" }, + { "1000", "Mil" }, + { "1001", "Mil Uno" }, + { "1002", "Mil Dos" }, + { "2000", "Dos Mil" }, + { "2001", "Dos Mil Uno" }, + { "100000", "Cien Mil" }, + { "100001", "Cien Mil Uno" }, + { "999999", "Novecientos Noventa Y Nueve Mil Novecientos Noventa Y Nueve" }, + { "1000000", "Un Mill\u00f3n" }, + { "999999999", "Novecientos Noventa Y Nueve Millones Novecientos Noventa Y Nueve Mil Novecientos Noventa Y Nueve" }, + { "1000000000", "Mil Millones" } + }; + + static private String[][] formatWordFrenchLower = + { + { "w", null, null, null, null, "fra" }, + { "0", "z\u00e9ro" }, + { "1", "un" }, + { "2", "deux" }, + { "3", "trois" }, + { "4", "quatre" }, + { "5", "cinq" }, + { "6", "six" }, + { "7", "sept" }, + { "8", "huit" }, + { "9", "neuf" }, + { "10", "dix" }, + { "11", "onze" }, + { "12", "douze" }, + { "13", "treize" }, + { "14", "quatorze" }, + { "15", "quinze" }, + { "16", "seize" }, + { "17", "dix-sept" }, + { "18", "dix-huit" }, + { "19", "dix-neuf" }, + { "20", "vingt" }, + { "21", "vingt et un" }, + { "22", "vingt-deux" }, + { "23", "vingt-trois" }, + { "24", "vingt-quatre" }, + { "25", "vingt-cinq" }, + { "26", "vingt-six" }, + { "27", "vingt-sept" }, + { "28", "vingt-huit" }, + { "29", "vingt-neuf" }, + { "30", "trente" }, + { "31", "trente et un" }, + { "32", "trente-deux" }, + { "40", "quarante" }, + { "41", "quarante et un" }, + { "42", "quarante-deux" }, + { "50", "cinquante" }, + { "51", "cinquante et un" }, + { "52", "cinquante-deux" }, + { "60", "soixante" }, + { "61", "soixante et un" }, + { "62", "soixante-deux" }, + { "70", "soixante-dix" }, + { "71", "soixante et onze" }, + { "72", "soixante-douze" }, + { "79", "soixante-dix-neuf" }, + { "80", "quatre-vingts" }, + { "81", "quatre-vingt-un" }, + { "82", "quatre-vingt-deux" }, + { "89", "quatre-vingt-neuf" }, + { "90", "quatre-vingt-dix" }, + { "91", "quatre-vingt-onze" }, + { "92", "quatre-vingt-douze" }, + { "99", "quatre-vingt-dix-neuf" }, + { "100", "cent" }, + { "101", "cent un" }, + { "102", "cent deux" }, + { "200", "deux cents" }, + { "201", "deux cent un" }, + { "202", "deux cent deux" }, + { "300", "trois cents" }, + { "301", "trois cent un" }, + { "400", "quatre cents" }, + { "401", "quatre cent un" }, + { "500", "cinq cents" }, + { "501", "cinq cent un" }, + { "600", "six cents" }, + { "601", "six cent un" }, + { "700", "sept cents" }, + { "701", "sept cent un" }, + { "800", "huit cents" }, + { "801", "huit cent un" }, + { "900", "neuf cents" }, + { "901", "neuf cent un" }, + { "999", "neuf cent quatre-vingt-dix-neuf" }, + { "1000", "mille" }, + { "1001", "mille un" }, + { "1002", "mille deux" }, + { "2000", "deux mille" }, + { "2001", "deux mille un" }, + { "100000", "cent mille" }, + { "100001", "cent mille un" }, + { "999999", "neuf cent quatre-vingt-dix-neuf mille neuf cent quatre-vingt-dix-neuf" }, + { "1000000", "un million" }, + { "999999999", "neuf cent quatre-vingt-dix-neuf millions neuf cent quatre-vingt-dix-neuf mille neuf cent quatre-vingt-dix-neuf" }, + { "1000000000", "un milliard" } + }; + + static private String[][] formatWordFrenchUpper = + { + { "W", null, null, null, null, "fra" }, + { "0", "Z\u00c9RO" }, + { "1", "UN" }, + { "2", "DEUX" }, + { "3", "TROIS" }, + { "4", "QUATRE" }, + { "5", "CINQ" }, + { "6", "SIX" }, + { "7", "SEPT" }, + { "8", "HUIT" }, + { "9", "NEUF" }, + { "10", "DIX" }, + { "11", "ONZE" }, + { "12", "DOUZE" }, + { "13", "TREIZE" }, + { "14", "QUATORZE" }, + { "15", "QUINZE" }, + { "16", "SEIZE" }, + { "17", "DIX-SEPT" }, + { "18", "DIX-HUIT" }, + { "19", "DIX-NEUF" }, + { "20", "VINGT" }, + { "21", "VINGT ET UN" }, + { "22", "VINGT-DEUX" }, + { "23", "VINGT-TROIS" }, + { "24", "VINGT-QUATRE" }, + { "25", "VINGT-CINQ" }, + { "26", "VINGT-SIX" }, + { "27", "VINGT-SEPT" }, + { "28", "VINGT-HUIT" }, + { "29", "VINGT-NEUF" }, + { "30", "TRENTE" }, + { "31", "TRENTE ET UN" }, + { "32", "TRENTE-DEUX" }, + { "40", "QUARANTE" }, + { "41", "QUARANTE ET UN" }, + { "42", "QUARANTE-DEUX" }, + { "50", "CINQUANTE" }, + { "51", "CINQUANTE ET UN" }, + { "52", "CINQUANTE-DEUX" }, + { "60", "SOIXANTE" }, + { "61", "SOIXANTE ET UN" }, + { "62", "SOIXANTE-DEUX" }, + { "70", "SOIXANTE-DIX" }, + { "71", "SOIXANTE ET ONZE" }, + { "72", "SOIXANTE-DOUZE" }, + { "79", "SOIXANTE-DIX-NEUF" }, + { "80", "QUATRE-VINGTS" }, + { "81", "QUATRE-VINGT-UN" }, + { "82", "QUATRE-VINGT-DEUX" }, + { "89", "QUATRE-VINGT-NEUF" }, + { "90", "QUATRE-VINGT-DIX" }, + { "91", "QUATRE-VINGT-ONZE" }, + { "92", "QUATRE-VINGT-DOUZE" }, + { "99", "QUATRE-VINGT-DIX-NEUF" }, + { "100", "CENT" }, + { "101", "CENT UN" }, + { "102", "CENT DEUX" }, + { "200", "DEUX CENTS" }, + { "201", "DEUX CENT UN" }, + { "202", "DEUX CENT DEUX" }, + { "300", "TROIS CENTS" }, + { "301", "TROIS CENT UN" }, + { "400", "QUATRE CENTS" }, + { "401", "QUATRE CENT UN" }, + { "500", "CINQ CENTS" }, + { "501", "CINQ CENT UN" }, + { "600", "SIX CENTS" }, + { "601", "SIX CENT UN" }, + { "700", "SEPT CENTS" }, + { "701", "SEPT CENT UN" }, + { "800", "HUIT CENTS" }, + { "801", "HUIT CENT UN" }, + { "900", "NEUF CENTS" }, + { "901", "NEUF CENT UN" }, + { "999", "NEUF CENT QUATRE-VINGT-DIX-NEUF" }, + { "1000", "MILLE" }, + { "1001", "MILLE UN" }, + { "1002", "MILLE DEUX" }, + { "2000", "DEUX MILLE" }, + { "2001", "DEUX MILLE UN" }, + { "100000", "CENT MILLE" }, + { "100001", "CENT MILLE UN" }, + { "999999", "NEUF CENT QUATRE-VINGT-DIX-NEUF MILLE NEUF CENT QUATRE-VINGT-DIX-NEUF" }, + { "1000000", "UN MILLION" }, + { "999999999", "NEUF CENT QUATRE-VINGT-DIX-NEUF MILLIONS NEUF CENT QUATRE-VINGT-DIX-NEUF MILLE NEUF CENT QUATRE-VINGT-DIX-NEUF" }, + { "1000000000", "UN MILLIARD" } + }; + + static private String[][] formatWordFrenchTitle = + { + { "Ww", null, null, null, null, "fra" }, + { "0", "Z\u00e9ro" }, + { "1", "Un" }, + { "2", "Deux" }, + { "3", "Trois" }, + { "4", "Quatre" }, + { "5", "Cinq" }, + { "6", "Six" }, + { "7", "Sept" }, + { "8", "Huit" }, + { "9", "Neuf" }, + { "10", "Dix" }, + { "11", "Onze" }, + { "12", "Douze" }, + { "13", "Treize" }, + { "14", "Quatorze" }, + { "15", "Quinze" }, + { "16", "Seize" }, + { "17", "Dix-sept" }, + { "18", "Dix-huit" }, + { "19", "Dix-neuf" }, + { "20", "Vingt" }, + { "21", "Vingt Et Un" }, + { "22", "Vingt-deux" }, + { "23", "Vingt-trois" }, + { "24", "Vingt-quatre" }, + { "25", "Vingt-cinq" }, + { "26", "Vingt-six" }, + { "27", "Vingt-sept" }, + { "28", "Vingt-huit" }, + { "29", "Vingt-neuf" }, + { "30", "Trente" }, + { "31", "Trente Et Un" }, + { "32", "Trente-deux" }, + { "40", "Quarante" }, + { "41", "Quarante Et Un" }, + { "42", "Quarante-deux" }, + { "50", "Cinquante" }, + { "51", "Cinquante Et Un" }, + { "52", "Cinquante-deux" }, + { "60", "Soixante" }, + { "61", "Soixante Et Un" }, + { "62", "Soixante-deux" }, + { "70", "Soixante-dix" }, + { "71", "Soixante Et Onze" }, + { "72", "Soixante-douze" }, + { "79", "Soixante-dix-neuf" }, + { "80", "Quatre-vingts" }, + { "81", "Quatre-vingt-un" }, + { "82", "Quatre-vingt-deux" }, + { "89", "Quatre-vingt-neuf" }, + { "90", "Quatre-vingt-dix" }, + { "91", "Quatre-vingt-onze" }, + { "92", "Quatre-vingt-douze" }, + { "99", "Quatre-vingt-dix-neuf" }, + { "100", "Cent" }, + { "101", "Cent Un" }, + { "102", "Cent Deux" }, + { "200", "Deux Cents" }, + { "201", "Deux Cent Un" }, + { "202", "Deux Cent Deux" }, + { "300", "Trois Cents" }, + { "301", "Trois Cent Un" }, + { "400", "Quatre Cents" }, + { "401", "Quatre Cent Un" }, + { "500", "Cinq Cents" }, + { "501", "Cinq Cent Un" }, + { "600", "Six Cents" }, + { "601", "Six Cent Un" }, + { "700", "Sept Cents" }, + { "701", "Sept Cent Un" }, + { "800", "Huit Cents" }, + { "801", "Huit Cent Un" }, + { "900", "Neuf Cents" }, + { "901", "Neuf Cent Un" }, + { "999", "Neuf Cent Quatre-vingt-dix-neuf" }, + { "1000", "Mille" }, + { "1001", "Mille Un" }, + { "1002", "Mille Deux" }, + { "2000", "Deux Mille" }, + { "2001", "Deux Mille Un" }, + { "100000", "Cent Mille" }, + { "100001", "Cent Mille Un" }, + { "999999", "Neuf Cent Quatre-vingt-dix-neuf Mille Neuf Cent Quatre-vingt-dix-neuf" }, + { "1000000", "Un Million" }, + { "999999999", "Neuf Cent Quatre-vingt-dix-neuf Millions Neuf Cent Quatre-vingt-dix-neuf Mille Neuf Cent Quatre-vingt-dix-neuf" }, + { "1000000000", "Un Milliard" } + }; + + /** + * Tests decimal from latin script. + * @throws Exception if the test fails + */ + @Test + public void testFormatDecimal() throws Exception { + performConversions ( formatDecimal ); + performConversions ( formatDecimalPadded ); + performConversions ( formatDecimalGrouped ); + performConversions ( formatDecimalGroupedPadded ); + } + + /** + * Tests decimal from arabic script. + * @throws Exception if the test fails + */ + @Test + public void testFormatDecimalArabic() throws Exception { + performConversions ( formatDecimalArabic ); + performConversions ( formatDecimalArabicPadded ); + performConversions ( formatDecimalArabicGrouped ); + performConversions ( formatDecimalArabicGroupedPadded ); + } + + /** + * Tests decimal from thai script. + * @throws Exception if the test fails + */ + @Test + public void testFormatDecimalThai() throws Exception { + performConversions ( formatDecimalThai ); + performConversions ( formatDecimalThaiPadded ); + } + + /** + * Tests roman numbers. + * @throws Exception if the test fails + */ + @Test + public void testFormatRoman() throws Exception { + performConversions ( formatRomanLower ); + performConversions ( formatRomanUpper ); + performConversions ( formatRomanLargeLower ); + performConversions ( formatRomanLargeUpper ); + performConversions ( formatRomanNumberFormsLower ); + performConversions ( formatRomanNumberFormsUpper ); + } + + /** + * Tests latin alphabetic sequence numerals. + * @throws Exception if the test fails + */ + @Test + public void testAlphabeticLatin() throws Exception { + performConversions ( formatAlphabeticLatinLower ); + performConversions ( formatAlphabeticLatinUpper ); + } + + /** + * Tests arabic alphabetic sequence numerals. + * @throws Exception if the test fails + */ + @Test + public void testAlphabeticArabic() throws Exception { + performConversions ( formatAlphabeticArabicHijai ); + performConversions ( formatAlphabeticArabicAbjadi ); + } + + /** + * Tests hebrew alphabetic sequence numerals. + * @throws Exception if the test fails + */ + @Test + public void testAlphabeticHebrew() throws Exception { + performConversions ( formatAlphabeticHebrew ); + } + + /** + * Tests latin alphabetic sequence numerals. + * @throws Exception if the test fails + */ + @Test + public void testAlphabeticThai() throws Exception { + performConversions ( formatAlphabeticThai ); + } + + /** + * Tests arabic numerals.. + * @throws Exception if the test fails + */ + @Test + public void testNumeralArabic() throws Exception { + performConversions ( formatNumeralArabicAbjadi ); + } + + /** + * Tests hebrew numerals. + * @throws Exception if the test fails + */ + @Test + public void testNumeralHebrew() throws Exception { + performConversions ( formatNumeralHebrewGematria ); + } + + /** + * Tests english word numerals. + * @throws Exception if the test fails + */ + @Test + public void testWordEnglish() throws Exception { + performConversions ( formatWordEnglishLower ); + performConversions ( formatWordEnglishUpper ); + performConversions ( formatWordEnglishTitle ); + } + + /** + * Tests spanish word numerals. + * @throws Exception if the test fails + */ + @Test + public void testWordSpanish() throws Exception { + performConversions ( formatWordSpanishLower ); + performConversions ( formatWordSpanishUpper ); + performConversions ( formatWordSpanishTitle ); + } + + /** + * Tests french word numerals. + * @throws Exception if the test fails + */ + @Test + public void testWordFrench() throws Exception { + performConversions ( formatWordFrenchLower ); + performConversions ( formatWordFrenchUpper ); + performConversions ( formatWordFrenchTitle ); + } + + /** + * Perform conversions according to test specification. + * @param ts test specification + */ + private void performConversions ( String[][] ts ) { + assert ts != null; + assert ts.length >= 2; + String[] args = ts[0]; + assert args != null; + assert args.length > 0; + String format = args[0]; + assert format.length() > 0; + char groupingSeparator; + if ( args.length > 1 ) { + String s = args[1]; + if ( ( s != null ) && ( s.length() > 0 ) ) { + groupingSeparator = s.charAt(0); + } else { + groupingSeparator = 0; + } + } else { + groupingSeparator = 0; + } + int groupingSize; + if ( args.length > 2 ) { + String s = args[2]; + if ( ( s != null ) && ( s.length() > 0 ) ) { + groupingSize = Integer.parseInt ( s ); + } else { + groupingSize = 0; + } + } else { + groupingSize = 0; + } + int letterValue; + if ( args.length > 3 ) { + String s = args[3]; + if ( ( s != null ) && ( s.length() > 0 ) ) { + s = s.toLowerCase(); + if ( s.equals("alphabetic") ) { + letterValue = NumberConverter.LETTER_VALUE_ALPHABETIC; + } else if ( s.equals("traditional") ) { + letterValue = NumberConverter.LETTER_VALUE_TRADITIONAL; + } else { + letterValue = 0; + } + } else { + letterValue = 0; + } + } else { + letterValue = 0; + } + String features; + if ( args.length > 4 ) { + String s = args[4]; + if ( ( s != null ) && ( s.length() > 0 ) ) { + features = s; + } else { + features = null; + } + } else { + features = null; + } + String language; + if ( args.length > 5 ) { + String s = args[5]; + if ( ( s != null ) && ( s.length() > 0 ) ) { + language = s; + } else { + language = null; + } + } else { + language = null; + } + String country; + if ( args.length > 6 ) { + String s = args[6]; + if ( ( s != null ) && ( s.length() > 0 ) ) { + country = s; + } else { + country = null; + } + } else { + country = null; + } + NumberConverter nc = new NumberConverter ( format, groupingSeparator, groupingSize, letterValue, features, language, country ); + for ( int i = 1, nt = ts.length; i < nt; i++ ) { + String[] sa = ts[i]; + assert sa != null; + assert sa.length >= 2; + List numbers = new ArrayList(); + for ( int k = 0, nn = sa.length - 1; k < nn; k++ ) { + String s = sa[k]; + numbers.add ( Long.valueOf ( s ) ); + } + String expected = sa [ sa.length - 1 ]; + String actual = nc.convert ( numbers ); + assertEquals ( expected, actual ); + } + } + +} diff --git a/test/java/org/apache/fop/complexscripts/util/UtilTestSuite.java b/test/java/org/apache/fop/complexscripts/util/UtilTestSuite.java new file mode 100644 index 000000000..70bd568af --- /dev/null +++ b/test/java/org/apache/fop/complexscripts/util/UtilTestSuite.java @@ -0,0 +1,34 @@ +/* + * 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.complexscripts.util; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; +import org.junit.runners.Suite.SuiteClasses; + +/** + * Test suite for bidirectional functionality. + */ +@RunWith(Suite.class) +@SuiteClasses({ + NumberConverterTestCase.class +}) +public class UtilTestSuite { +} diff --git a/test/java/org/apache/fop/config/FontsSubstitutionTestCase.java b/test/java/org/apache/fop/config/FontsSubstitutionTestCase.java index 0918d5867..1499c9186 100644 --- a/test/java/org/apache/fop/config/FontsSubstitutionTestCase.java +++ b/test/java/org/apache/fop/config/FontsSubstitutionTestCase.java @@ -48,7 +48,8 @@ public class FontsSubstitutionTestCase extends FontManager fontManager = ua.getFactory().getFontManager(); FontCollection[] fontCollections = new FontCollection[] { new Base14FontCollection(fontManager.isBase14KerningEnabled()), - new CustomFontCollection(renderer.getFontResolver(), renderer.getFontList()) + new CustomFontCollection(renderer.getFontResolver(), renderer.getFontList(), + ua.isComplexScriptFeaturesEnabled()) }; fontManager.setup(fontInfo, fontCollections); FontTriplet triplet = new FontTriplet("Times", "italic", diff --git a/test/java/org/apache/fop/fonts/DejaVuLGCSerifTestCase.java b/test/java/org/apache/fop/fonts/DejaVuLGCSerifTestCase.java index 322d5f622..4ac61d893 100644 --- a/test/java/org/apache/fop/fonts/DejaVuLGCSerifTestCase.java +++ b/test/java/org/apache/fop/fonts/DejaVuLGCSerifTestCase.java @@ -31,7 +31,7 @@ import org.junit.Test; */ public class DejaVuLGCSerifTestCase { - private FontResolver fontResolver = FontManager.createMinimalFontResolver(); + private FontResolver fontResolver = FontManager.createMinimalFontResolver(false); private CustomFont font; /** diff --git a/test/java/org/apache/fop/fonts/truetype/TTFFontLoaderTestCase.java b/test/java/org/apache/fop/fonts/truetype/TTFFontLoaderTestCase.java index aadf877e0..35c865cd7 100644 --- a/test/java/org/apache/fop/fonts/truetype/TTFFontLoaderTestCase.java +++ b/test/java/org/apache/fop/fonts/truetype/TTFFontLoaderTestCase.java @@ -38,20 +38,21 @@ public class TTFFontLoaderTestCase { @Test public void testUseKerning() throws IOException { + boolean useComplexScriptFeatures = false; File file = new File("test/resources/fonts/ttf/DejaVuLGCSerif.ttf"); String absoluteFilePath = file.toURI().toURL().toExternalForm(); - FontResolver resolver = FontManager.createMinimalFontResolver(); + FontResolver resolver = FontManager.createMinimalFontResolver(useComplexScriptFeatures); String fontName = "Deja Vu"; boolean embedded = false; boolean useKerning = true; TTFFontLoader fontLoader = new TTFFontLoader(absoluteFilePath, fontName, embedded, - EncodingMode.AUTO, useKerning, resolver); + EncodingMode.AUTO, useKerning, useComplexScriptFeatures, resolver); assertTrue(fontLoader.getFont().hasKerningInfo()); useKerning = false; fontLoader = new TTFFontLoader(absoluteFilePath, fontName, embedded, EncodingMode.AUTO, - useKerning, resolver); + useKerning, useComplexScriptFeatures, resolver); assertFalse(fontLoader.getFont().hasKerningInfo()); } } diff --git a/test/layoutengine/disabled-testcases.xml b/test/layoutengine/disabled-testcases.xml index a14ae6bea..5208fa91d 100644 --- a/test/layoutengine/disabled-testcases.xml +++ b/test/layoutengine/disabled-testcases.xml @@ -214,4 +214,10 @@ block-container_reference-orientation_bug36391.xml An assert is failing + + Writing mode problems + simple-page-master_writing-mode_rl_region-body_writing-mode-lr.xml + Test erroneously depends upon incorrect implementation of writing-mode trait + derivation on fo:region-*. + diff --git a/test/layoutengine/standard-testcases/basic-link_background-image_writing-mode_rl.xml b/test/layoutengine/standard-testcases/basic-link_background-image_writing-mode_rl.xml new file mode 100644 index 000000000..8aa5480ec --- /dev/null +++ b/test/layoutengine/standard-testcases/basic-link_background-image_writing-mode_rl.xml @@ -0,0 +1,54 @@ + + + + + +

    + This test checks background image on a fo:basic-link. +

    +
    + + ../../resources/images/bgimg300dpi.jpg + + + + + + + + + + + + Why is FOP so cool? + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/basic-link_external-destination_writing-mode_rl.xml b/test/layoutengine/standard-testcases/basic-link_external-destination_writing-mode_rl.xml new file mode 100644 index 000000000..879cead01 --- /dev/null +++ b/test/layoutengine/standard-testcases/basic-link_external-destination_writing-mode_rl.xml @@ -0,0 +1,48 @@ + + + + + +

    + This test checks external-destination on a fo:basic-link. +

    +
    + + + + + + + + + + FOP + FOP + FOP + FOP + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/basic-link_external-destination_writing-mode_rl_2.xml b/test/layoutengine/standard-testcases/basic-link_external-destination_writing-mode_rl_2.xml new file mode 100644 index 000000000..6812dd7ae --- /dev/null +++ b/test/layoutengine/standard-testcases/basic-link_external-destination_writing-mode_rl_2.xml @@ -0,0 +1,58 @@ + + + + + +

    + This test checks a fo:basic-link with an external-destination wrapping an SVG graphic. +

    +
    + + + + + + + + + + before before before + + start + + + + + + end + + after after after + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/basic-link_for_toc_writing-mode_rl.xml b/test/layoutengine/standard-testcases/basic-link_for_toc_writing-mode_rl.xml new file mode 100644 index 000000000..9966c54b1 --- /dev/null +++ b/test/layoutengine/standard-testcases/basic-link_for_toc_writing-mode_rl.xml @@ -0,0 +1,53 @@ + + + + + +

    + This test checks fo:basic-link in conjunction with text-align="justify" and an + fo:page-number-citation. +

    +
    + + + + + + + + + + + You can read about Apache FOP in + chapter 1 on page . + Apache FOP is open source, BTW. + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/basic-link_height_baseline-shift_writing-mode_rl.xml b/test/layoutengine/standard-testcases/basic-link_height_baseline-shift_writing-mode_rl.xml new file mode 100644 index 000000000..2eef7c8f0 --- /dev/null +++ b/test/layoutengine/standard-testcases/basic-link_height_baseline-shift_writing-mode_rl.xml @@ -0,0 +1,62 @@ + + + + + +

    + This test checks the height of an fo:basic-link with baseline-shift. +

    +
    + + + + + + + + + + Lorem ipsum dolor sit amet, consectetur + adipiscingelit. + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/basic-link_height_inline-child_writing-mode_rl.xml b/test/layoutengine/standard-testcases/basic-link_height_inline-child_writing-mode_rl.xml new file mode 100644 index 000000000..6f0a893a0 --- /dev/null +++ b/test/layoutengine/standard-testcases/basic-link_height_inline-child_writing-mode_rl.xml @@ -0,0 +1,62 @@ + + + + + +

    + This test checks the height of an fo:basic-link having several child elements wrapped into a + single fo:inline element. +

    +
    + + + + + + + + + + Lorem ipsum dolor sit amet, consectetur adipiscing elit. In + in egestas nisi. Etiam + at ante eget velit placerat ullamcorper. + + + + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/basic-link_height_multi-child_writing-mode_rl.xml b/test/layoutengine/standard-testcases/basic-link_height_multi-child_writing-mode_rl.xml new file mode 100644 index 000000000..ab7befaa0 --- /dev/null +++ b/test/layoutengine/standard-testcases/basic-link_height_multi-child_writing-mode_rl.xml @@ -0,0 +1,58 @@ + + + + + +

    + This test checks the height of an fo:basic-link having several child elements. +

    +
    + + + + + + + + + + Lorem ipsum dolor sit amet, consectetur adipiscing elit. In in egestas nisi. Etiam at ante eget + velit placerat ullamcorper. + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/basic-link_height_multi-line_writing-mode_rl.xml b/test/layoutengine/standard-testcases/basic-link_height_multi-line_writing-mode_rl.xml new file mode 100644 index 000000000..cee76ff67 --- /dev/null +++ b/test/layoutengine/standard-testcases/basic-link_height_multi-line_writing-mode_rl.xml @@ -0,0 +1,67 @@ + + + + + +

    + This test checks the height of an fo:basic-link spanning over several lines. +

    +
    + + + + + + + + + + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer quis neque + vitae lectus condimentum. In in egestas nisi. Etiam at ante eget + velit placerat ullamcorper. + + + + + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/basic-link_height_writing-mode_rl.xml b/test/layoutengine/standard-testcases/basic-link_height_writing-mode_rl.xml new file mode 100644 index 000000000..26a882fa8 --- /dev/null +++ b/test/layoutengine/standard-testcases/basic-link_height_writing-mode_rl.xml @@ -0,0 +1,53 @@ + + + + + +

    + This test checks the height of an fo:basic-link wrapping a bigger element. +

    +
    + + + + + + + + + + Lorem ipsum dolor sit amet, consectetur adipiscing elit. In in egestas nisi. + Etiam at ante eget velit placerat ullamcorper. + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/basic-link_internal-desination-next-page.xml b/test/layoutengine/standard-testcases/basic-link_internal-desination-next-page.xml new file mode 100644 index 000000000..c97b8ab01 --- /dev/null +++ b/test/layoutengine/standard-testcases/basic-link_internal-desination-next-page.xml @@ -0,0 +1,48 @@ + + + + + +

    + This test checks a next page internal-destination on a fo:basic-link. +

    +
    + + + + + + + + + + Internal Link + + + + + Link Target + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/basic-link_internal-desination-next-page_writing-mode_rl.xml b/test/layoutengine/standard-testcases/basic-link_internal-desination-next-page_writing-mode_rl.xml new file mode 100644 index 000000000..6f6ed37ae --- /dev/null +++ b/test/layoutengine/standard-testcases/basic-link_internal-desination-next-page_writing-mode_rl.xml @@ -0,0 +1,48 @@ + + + + + +

    + This test checks a next page internal-destination on a fo:basic-link. +

    +
    + + + + + + + + + + Internal Link + + + + + Link Target + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/basic-link_internal-desination-same-page-after.xml b/test/layoutengine/standard-testcases/basic-link_internal-desination-same-page-after.xml new file mode 100644 index 000000000..f83f4f418 --- /dev/null +++ b/test/layoutengine/standard-testcases/basic-link_internal-desination-same-page-after.xml @@ -0,0 +1,44 @@ + + + + + +

    + This test checks a same page internal-destination on a fo:basic-link which references a subsequent block. +

    +
    + + + + + + + + + + Internal Link + Link Target + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/basic-link_internal-desination-same-page-after_writing-mode_rl.xml b/test/layoutengine/standard-testcases/basic-link_internal-desination-same-page-after_writing-mode_rl.xml new file mode 100644 index 000000000..624dc43f2 --- /dev/null +++ b/test/layoutengine/standard-testcases/basic-link_internal-desination-same-page-after_writing-mode_rl.xml @@ -0,0 +1,44 @@ + + + + + +

    + This test checks a same page internal-destination on a fo:basic-link which references a subsequent block. +

    +
    + + + + + + + + + + Internal Link + Link Target + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/basic-link_internal-desination-same-page-before.xml b/test/layoutengine/standard-testcases/basic-link_internal-desination-same-page-before.xml new file mode 100644 index 000000000..541c95dbf --- /dev/null +++ b/test/layoutengine/standard-testcases/basic-link_internal-desination-same-page-before.xml @@ -0,0 +1,44 @@ + + + + + +

    + This test checks a same page internal-destination on a fo:basic-link which references a prior block. +

    +
    + + + + + + + + + + Link Target + Internal Link + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/basic-link_internal-desination-same-page-before_writing-mode_rl.xml b/test/layoutengine/standard-testcases/basic-link_internal-desination-same-page-before_writing-mode_rl.xml new file mode 100644 index 000000000..89d07ce50 --- /dev/null +++ b/test/layoutengine/standard-testcases/basic-link_internal-desination-same-page-before_writing-mode_rl.xml @@ -0,0 +1,44 @@ + + + + + +

    + This test checks a same page internal-destination on a fo:basic-link which references a prior block. +

    +
    + + + + + + + + + + Link Target + Internal Link + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/bidi_propagation_1.xml b/test/layoutengine/standard-testcases/bidi_propagation_1.xml new file mode 100644 index 000000000..947d9dac5 --- /dev/null +++ b/test/layoutengine/standard-testcases/bidi_propagation_1.xml @@ -0,0 +1,125 @@ + + + + + +

    + This test verifies correct propagation of bidi resolution. It is based upon skynav/fop + ticket #78. + [TBD] The test input file could be further simplified. + [TBD] Add fop bug corresponding to above ticket then change the above reference. +

    +
    + + + + + + + + + + + + + + + + + + + + + + + + + • + + + + + + Test + + + + + + + + + + + X + + + + + + + + + + + + • + + + + + Test + + + + + + + + + + X + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + diff --git a/test/layoutengine/standard-testcases/block-container_start-indent.xml b/test/layoutengine/standard-testcases/block-container_start-indent.xml index b21d332a3..9137515d0 100644 --- a/test/layoutengine/standard-testcases/block-container_start-indent.xml +++ b/test/layoutengine/standard-testcases/block-container_start-indent.xml @@ -78,6 +78,7 @@ + @@ -119,6 +120,7 @@ + diff --git a/test/layoutengine/standard-testcases/block-container_start-indent_writing-mode_rl.xml b/test/layoutengine/standard-testcases/block-container_start-indent_writing-mode_rl.xml new file mode 100644 index 000000000..bee1d1d05 --- /dev/null +++ b/test/layoutengine/standard-testcases/block-container_start-indent_writing-mode_rl.xml @@ -0,0 +1,161 @@ + + + + + +

    + This test checks indents on block-containers in a right-to-left writing mode context. +

    +

    + Since block-container generates a reference-area and no margin is specified the block-container as well as its + nested block inherit the start-indent of the top-most block. Since block-container also creates a viewport + the orange block is effectively indented two times by 10 pt. (See 5.3.2 in XSL 1.0) +

    +
    + + + + + + + + + + Outer block with start-indent="10pt" + + fo:block|fo:block + + fo:block|fo:block-container|fo:block + + + fo:block|fo:block-container|fo:block + fo:block|fo:block-container|fo:block start-indent="0pt" + + + Outer block with margin-right="10pt" + + fo:block|fo:block + + fo:block|fo:block-container|fo:block + + + fo:block|fo:block-container|fo:block + fo:block|fo:block-container|fo:block start-indent="0pt" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/block_basic_2.xml b/test/layoutengine/standard-testcases/block_basic_2.xml index 25e30c731..813be6c95 100644 --- a/test/layoutengine/standard-testcases/block_basic_2.xml +++ b/test/layoutengine/standard-testcases/block_basic_2.xml @@ -75,7 +75,7 @@ - + diff --git a/test/layoutengine/standard-testcases/block_text-align_4.xml b/test/layoutengine/standard-testcases/block_text-align_4.xml new file mode 100644 index 000000000..eb83c151d --- /dev/null +++ b/test/layoutengine/standard-testcases/block_text-align_4.xml @@ -0,0 +1,80 @@ + + + + + +

    + This test checks text-align (except for justify) when writing-mode is right-to-left, + in which case start is right and end is left. +

    +
    + + + + + + + + + + Lorem ipsum dolor sit amet, consectetuer adipiscing elit. + Lorem ipsum dolor sit amet, consectetuer adipiscing elit. + Lorem ipsum dolor sit amet, consectetuer adipiscing elit. + Lorem ipsum dolor sit amet, consectetuer adipiscing elit. + Lorem ipsum dolor sit amet, consectetuer adipiscing elit. + Lorem ipsum dolor sit amet, consectetuer adipiscing elit. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/block_text-align_5.xml b/test/layoutengine/standard-testcases/block_text-align_5.xml new file mode 100644 index 000000000..757bf2eb5 --- /dev/null +++ b/test/layoutengine/standard-testcases/block_text-align_5.xml @@ -0,0 +1,65 @@ + + + + + +

    + This test checks text-align="justify" when writing-mode is right-to-left. +

    +
    + + + + + + + + + + Lorem ipsum dolor sit amet, consectetuer adipiscing elit. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/character_writing-mode_rl.xml b/test/layoutengine/standard-testcases/character_writing-mode_rl.xml new file mode 100644 index 000000000..adc126ec8 --- /dev/null +++ b/test/layoutengine/standard-testcases/character_writing-mode_rl.xml @@ -0,0 +1,76 @@ + + + + + +

    + This test checks fo:character in a RTL writing-mode context. +

    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/inline_background-color_writing-mode_rl.xml b/test/layoutengine/standard-testcases/inline_background-color_writing-mode_rl.xml new file mode 100644 index 000000000..b4e656407 --- /dev/null +++ b/test/layoutengine/standard-testcases/inline_background-color_writing-mode_rl.xml @@ -0,0 +1,133 @@ + + + + + +

    + This test checks fo:inline with background-color properties. +

    +
    + + + + + + + + + + + To emphasize a phrase highlight it. + + + To emphasize a phrase highlight it with text-align="end". + + + To emphasize a phrase highlight it with text-align="justify". + + + To emphasize a phrase highlight it with text-align="center". + + + This demonstrates a long inline + which stretches over multiple lines to + show how the highlight extends from line to line while + correctly honouring the text-align (not specified) property + back to normal + + + This demonstrates a long inline + which stretches over multiple lines to + show how the highlight extends from line to line while + correctly honouring the text-align="end" property + back to normal + + + This demonstrates a long inline + which stretches over multiple lines to + show how the highlight extends from line to line while + correctly honouring the text-align="justify" property + back to normal + + + This demonstrates a long inline + which stretches over multiple lines to + show how the highlight extends from line to line while + correctly honouring the text-align="center" property + back to normal + + + Nested inline highlights + this is 10pt text + nested within is 14pt text + followed by 10pt text + back to normal + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/instream-foreign-object_basic_writing-mode_rl.xml b/test/layoutengine/standard-testcases/instream-foreign-object_basic_writing-mode_rl.xml new file mode 100644 index 000000000..9d090d5fd --- /dev/null +++ b/test/layoutengine/standard-testcases/instream-foreign-object_basic_writing-mode_rl.xml @@ -0,0 +1,57 @@ + + + + + +

    + This test checks the basics for instream-foreign-object. +

    +
    + + + + + + + + + + start + + + + + + + + + end + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/instream-foreign-object_border_padding_writing-mode_rl.xml b/test/layoutengine/standard-testcases/instream-foreign-object_border_padding_writing-mode_rl.xml new file mode 100644 index 000000000..ad27bb298 --- /dev/null +++ b/test/layoutengine/standard-testcases/instream-foreign-object_border_padding_writing-mode_rl.xml @@ -0,0 +1,96 @@ + + + + + +

    + This test checks the borders and the like for instream-foreign-object. +

    +
    + + + + + + + + + + + + + + + + + + Normal font + + + + + + + + + + FOP + + + In both blocks we have a setting of border-width="5pt 10pt 20pt 15pt" padding="15pt 20pt 10pt 5pt" on the i-f-o. + In the first block the i-f-o determines the height of the line in the 2nd block the font is bigger than the i-f-o. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/instream-foreign-object_display-align_writing-mode_rl.xml b/test/layoutengine/standard-testcases/instream-foreign-object_display-align_writing-mode_rl.xml new file mode 100644 index 000000000..4478d6a2a --- /dev/null +++ b/test/layoutengine/standard-testcases/instream-foreign-object_display-align_writing-mode_rl.xml @@ -0,0 +1,121 @@ + + + + + +

    + This test checks instream-foreign-object with display-align. +

    +
    + + + + + + + + + + plain instream-foreign-object + + + + + + + + + End + + instream-foreign-object with display-align="auto" + + + + + + + + + End + + instream-foreign-object with display-align="before" + + + + + + + + + End + + instream-foreign-object with display-align="center" + + + + + + + + + End + + instream-foreign-object with display-align="after" + + + + + + + + + End + + EOF + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/kerning_1_off.xml b/test/layoutengine/standard-testcases/kerning_1_off.xml index 569d98238..a4fa3712b 100644 --- a/test/layoutengine/standard-testcases/kerning_1_off.xml +++ b/test/layoutengine/standard-testcases/kerning_1_off.xml @@ -47,12 +47,12 @@ - + - + diff --git a/test/layoutengine/standard-testcases/kerning_1_on.xml b/test/layoutengine/standard-testcases/kerning_1_on.xml index b7410bab1..17852c127 100644 --- a/test/layoutengine/standard-testcases/kerning_1_on.xml +++ b/test/layoutengine/standard-testcases/kerning_1_on.xml @@ -52,12 +52,12 @@ - + - + diff --git a/test/layoutengine/standard-testcases/leader-alignment.xml b/test/layoutengine/standard-testcases/leader-alignment.xml index abc354150..d18adc4a2 100644 --- a/test/layoutengine/standard-testcases/leader-alignment.xml +++ b/test/layoutengine/standard-testcases/leader-alignment.xml @@ -31,11 +31,11 @@ - - margin="0pt" padding-left="10mm" + + margin="0pt" padding-start="10mm" - - padding-left="10mm" + + padding-start="10mm" leader-alignment="page" - + leader-alignment="page" - + @@ -64,5 +64,79 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/layoutengine/standard-testcases/leader-alignment_writing-mode_rl.xml b/test/layoutengine/standard-testcases/leader-alignment_writing-mode_rl.xml new file mode 100644 index 000000000..941c7320a --- /dev/null +++ b/test/layoutengine/standard-testcases/leader-alignment_writing-mode_rl.xml @@ -0,0 +1,170 @@ + + + + + +

    + This test checks leaders +

    +
    + + + + + + + + + + + margin="0pt" padding-start="10mm" + + + padding-start="10mm" + + + + leader-alignment="page" + + + + leader-alignment="page" + + + + + leader-alignment="reference-area" + + + + leader-alignment="reference-area" Leader-pattern is aligned as if it began on the current reference-area's content-rectangle start-edge. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/leader_leader-pattern_dots_writing-mode_rl.xml b/test/layoutengine/standard-testcases/leader_leader-pattern_dots_writing-mode_rl.xml new file mode 100644 index 000000000..c3d4e7f5e --- /dev/null +++ b/test/layoutengine/standard-testcases/leader_leader-pattern_dots_writing-mode_rl.xml @@ -0,0 +1,213 @@ + + + + + +

    + This test checks leaders with leader-pattern="dots" +

    +
    + + + + + + + + + + + + Default dots pattern + + + + leader-pattern-width="use-font-metrics" + + + + leader-length="20mm" leader-pattern-width="5mm" + + + + leader-length="20%" leader-pattern-width="5mm" + + + + leader-pattern-width="1pt" + + + + leader-length="20%" leader-pattern-width="5%" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/leader_leader-pattern_rule_writing-system_rl.xml b/test/layoutengine/standard-testcases/leader_leader-pattern_rule_writing-system_rl.xml new file mode 100644 index 000000000..3d836d27c --- /dev/null +++ b/test/layoutengine/standard-testcases/leader_leader-pattern_rule_writing-system_rl.xml @@ -0,0 +1,331 @@ + + + + + +

    + This test checks leaders with leader-patter="rule" +

    +
    + + + + + + + + + + + + No rule-style given + + + + rule-style="none" + + + + rule-style="dotted" + + + + rule-style="dashed" + + + + rule-style="solid" + + + + rule-style="double" + + + + rule-style="groove" + + + + rule-style="ridge" + + + + rule-style="dotted" rule-thickness="3pt" + + + + rule-style="dashed" rule-thickness="3pt" + + + + rule-style="solid" rule-thickness="3pt" + + + + rule-style="double" rule-thickness="3pt" + + + + rule-style="groove" rule-thickness="3pt" + + + + rule-style="ridge" rule-thickness="3pt" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/leader_leader-pattern_space_writing-mode_rl.xml b/test/layoutengine/standard-testcases/leader_leader-pattern_space_writing-mode_rl.xml new file mode 100644 index 000000000..040df72dc --- /dev/null +++ b/test/layoutengine/standard-testcases/leader_leader-pattern_space_writing-mode_rl.xml @@ -0,0 +1,95 @@ + + + + + +

    + This test checks leaders with leader-pattern="space" +

    +
    + + + + + + + + + + + + Default space pattern + + + + leader-length="0.5in" + + + + leader-length="5%" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/leader_leader-pattern_use-content_writing-mode_rl.xml b/test/layoutengine/standard-testcases/leader_leader-pattern_use-content_writing-mode_rl.xml new file mode 100644 index 000000000..d83e6e3a2 --- /dev/null +++ b/test/layoutengine/standard-testcases/leader_leader-pattern_use-content_writing-mode_rl.xml @@ -0,0 +1,317 @@ + + + + + +

    + This test checks leaders with leader-pattern="use-content" +

    +
    + + + + + + + + + + + x + Content is "x" + + + => + Content is "=>" with background + + + ~ + Content is "~" with leader-pattern-width="12pt" + + + * + Content is "*" with leader-pattern-width="12pt" and border + + + ++ + Content is "++" with l-p-w="12pt" and border small font + + + + + + + + + Content is svg 10 x 10 + + + + + + + + + Content is svg 20 x 10 which is wider than the leader-length + + + + Content is " " + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/list-block_writing-mode_rl.xml b/test/layoutengine/standard-testcases/list-block_writing-mode_rl.xml new file mode 100644 index 000000000..ecd27cf04 --- /dev/null +++ b/test/layoutengine/standard-testcases/list-block_writing-mode_rl.xml @@ -0,0 +1,207 @@ + + + + + +

    + This test checks lists in a RTL WM context. +

    +
    + + + + + + + + + + + + + label + + + value + + + + + label + + + value + + + + + label + + + value + + + + + + + label + + + value + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/page-number-citation_writing-mode_rl.xml b/test/layoutengine/standard-testcases/page-number-citation_writing-mode_rl.xml new file mode 100644 index 000000000..8137ff8de --- /dev/null +++ b/test/layoutengine/standard-testcases/page-number-citation_writing-mode_rl.xml @@ -0,0 +1,63 @@ + + + + + +

    + This test checks fo:page-number-citation in a RTL writing-mode context. +

    +
    + + + + + + + + + + Page + + + + + Page 2 + + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/region-body_column-count_1_writing-mode_rl.xml b/test/layoutengine/standard-testcases/region-body_column-count_1_writing-mode_rl.xml new file mode 100644 index 000000000..8207702f2 --- /dev/null +++ b/test/layoutengine/standard-testcases/region-body_column-count_1_writing-mode_rl.xml @@ -0,0 +1,86 @@ + + + + + +

    + This test checks multi-column documents with right-to-left writing mode. +

    +
    + + + + + + + + + + line1 + line2 + line3 + line4 + line5 + line6 + line7 + line8 + line9 + line10 + line11 + line12 + line13 + line14 + line15 + line16 + line17 + line18 + line19 + line20 + line21 + line22 + line23 + line24 + line25 + line26 + line27 + line28 + line29 + line30 + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/region-body_column-count_2_writing-mode_rl.xml b/test/layoutengine/standard-testcases/region-body_column-count_2_writing-mode_rl.xml new file mode 100644 index 000000000..b6ac19553 --- /dev/null +++ b/test/layoutengine/standard-testcases/region-body_column-count_2_writing-mode_rl.xml @@ -0,0 +1,103 @@ + + + + + +

    + This test checks multi-column documents with right-to-left writing mode. Normal multi-column document breaking over more than one page. +

    +
    + + + + + + + + + + line1 + line2 + line3 + line4 + line5 + line6 + line7 + line8 + line9 + line10 + line11 + line12 + line13 + line14 + line15 + line16 + line17 + line18 + line19 + line20 + line21 + line22 + line23 + line24 + line25 + line26 + line27 + line28 + line29 + line30 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/simple-page-master_reference-orientation_0_writing-mode_rl_region-body_margin_relative.xml b/test/layoutengine/standard-testcases/simple-page-master_reference-orientation_0_writing-mode_rl_region-body_margin_relative.xml index e594a211e..bfbc90565 100644 --- a/test/layoutengine/standard-testcases/simple-page-master_reference-orientation_0_writing-mode_rl_region-body_margin_relative.xml +++ b/test/layoutengine/standard-testcases/simple-page-master_reference-orientation_0_writing-mode_rl_region-body_margin_relative.xml @@ -19,12 +19,10 @@

    - This test checks relative margin on region (region-body). + This test checks relative margin on regions when writing mode is right to left, + with reference orientation 0.

    - - ../../resources/images/bgimg300dpi.jpg - @@ -32,8 +30,8 @@ - - + + @@ -60,7 +58,7 @@ Demonstrates relative 5% margin on the page master, 10% margin on regions before - and end and 5% margin on regions start and after. Corresponding margins are set + and start and 5% margin on regions end and after. Corresponding margins are set on the region body. The page size is 5in x 3in with the page reference not rotated and a rl writing-mode. @@ -76,23 +74,23 @@ - + - + - - + + - + - + - - + + - + @@ -100,14 +98,14 @@ - + - + - +
    diff --git a/test/layoutengine/standard-testcases/simple-page-master_reference-orientation_180_writing-mode_rl_region-body_margin_relative.xml b/test/layoutengine/standard-testcases/simple-page-master_reference-orientation_180_writing-mode_rl_region-body_margin_relative.xml index b9a26ce7c..284fdf02c 100644 --- a/test/layoutengine/standard-testcases/simple-page-master_reference-orientation_180_writing-mode_rl_region-body_margin_relative.xml +++ b/test/layoutengine/standard-testcases/simple-page-master_reference-orientation_180_writing-mode_rl_region-body_margin_relative.xml @@ -19,12 +19,10 @@

    - This test checks relative margin on region (region-body). + This test checks relative margin on regions when writing mode is right to left, + with reference orientation 180.

    - - ../../resources/images/bgimg300dpi.jpg - @@ -32,8 +30,8 @@ - - + + @@ -60,9 +58,9 @@ Demonstrates relative 5% margin on the page master, 10% margin on regions before - and end and 5% margin on regions start and after. Corresponding margins are set - on the region body. The page size is 5in x 3in with the page reference rotated by - 180 degrees and a rl writing-mode. + and start and 5% margin on regions end and after. Corresponding margins are set + on the region body. The page size is 5in x 3in with the page reference rotated + by 180 degrees and a rl writing-mode. @@ -76,23 +74,23 @@ - + - + - - + + - + - + - - + + - + @@ -100,14 +98,14 @@ - + - + - +
    diff --git a/test/layoutengine/standard-testcases/simple-page-master_reference-orientation_270_writing-mode_rl_region-body_margin_relative.xml b/test/layoutengine/standard-testcases/simple-page-master_reference-orientation_270_writing-mode_rl_region-body_margin_relative.xml index 93b37467b..550785af6 100644 --- a/test/layoutengine/standard-testcases/simple-page-master_reference-orientation_270_writing-mode_rl_region-body_margin_relative.xml +++ b/test/layoutengine/standard-testcases/simple-page-master_reference-orientation_270_writing-mode_rl_region-body_margin_relative.xml @@ -19,21 +19,19 @@

    - This test checks relative margin on region (region-body). + This test checks relative margin on regions when writing mode is right to left, + with reference orientation 270.

    - - ../../resources/images/bgimg300dpi.jpg - - + - - + + @@ -60,9 +58,9 @@ Demonstrates relative 5% margin on the page master, 10% margin on regions before - and end and 5% margin on regions start and after. Corresponding margins are set - on the region body. The page size is 5in x 3in with the page reference rotated by - 270 degrees and a rl writing-mode. + and start and 5% margin on regions end and after. Corresponding margins are set + on the region body. The page size is 5in x 3in with the page reference rotated + by 270 degrees and a rl writing-mode. @@ -71,43 +69,43 @@ - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + +
    diff --git a/test/layoutengine/standard-testcases/simple-page-master_reference-orientation_90_writing-mode_rl_region-body_margin_relative.xml b/test/layoutengine/standard-testcases/simple-page-master_reference-orientation_90_writing-mode_rl_region-body_margin_relative.xml index 8c98329f7..cdb3140d1 100644 --- a/test/layoutengine/standard-testcases/simple-page-master_reference-orientation_90_writing-mode_rl_region-body_margin_relative.xml +++ b/test/layoutengine/standard-testcases/simple-page-master_reference-orientation_90_writing-mode_rl_region-body_margin_relative.xml @@ -19,21 +19,19 @@

    - This test checks relative margin on region (region-body). + This test checks relative margin on regions when writing mode is right to left, + with reference orientation 90.

    - - ../../resources/images/bgimg300dpi.jpg - - + - - + + @@ -60,9 +58,9 @@ Demonstrates relative 5% margin on the page master, 10% margin on regions before - and end and 5% margin on regions start and after. Corresponding margins are set - on the region body. The page size is 5in x 3in with the page reference rotated by - 90 degrees and a rl writing-mode. + and start and 5% margin on regions end and after. Corresponding margins are set + on the region body. The page size is 5in x 3in with the page reference rotated + by 90 degrees and a rl writing-mode. @@ -71,43 +69,43 @@ - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + +
    diff --git a/test/layoutengine/standard-testcases/table-column_column-progression-lr.xml b/test/layoutengine/standard-testcases/table-column_column-progression-lr.xml new file mode 100644 index 000000000..f7bf8f949 --- /dev/null +++ b/test/layoutengine/standard-testcases/table-column_column-progression-lr.xml @@ -0,0 +1,82 @@ + + + + + +

    + This test checks table column progression with left-to-right writing mode. The first column + should be to the left of the second column; the second column should be to the left of the + third column. The columns should be colored red, yellow, orange from left to right. +

    +
    + + + + + + + + + + + + + + + + + cell1 + + + cell2 + + + cell3 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/test/layoutengine/standard-testcases/table-column_column-progression-rl.xml b/test/layoutengine/standard-testcases/table-column_column-progression-rl.xml new file mode 100644 index 000000000..4f6b3d53a --- /dev/null +++ b/test/layoutengine/standard-testcases/table-column_column-progression-rl.xml @@ -0,0 +1,82 @@ + + + + + +

    + This test checks table column progression with right-to-left writing mode. The first column + should be to the right of the second column; the second column should be to the right of the + third column. The columns should be colored red, yellow, orange from right to left. +

    +
    + + + + + + + + + + + + + + + + + cell1 + + + cell2 + + + cell3 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/test/resources/complexscripts/arab/data/arab-001-f0.ser b/test/resources/complexscripts/arab/data/arab-001-f0.ser new file mode 100644 index 000000000..4394ccbe4 Binary files /dev/null and b/test/resources/complexscripts/arab/data/arab-001-f0.ser differ diff --git a/test/resources/complexscripts/arab/data/arab-001-f1.ser b/test/resources/complexscripts/arab/data/arab-001-f1.ser new file mode 100644 index 000000000..ce626a9f9 Binary files /dev/null and b/test/resources/complexscripts/arab/data/arab-001-f1.ser differ diff --git a/test/resources/complexscripts/arab/data/arab-001-f2.ser b/test/resources/complexscripts/arab/data/arab-001-f2.ser new file mode 100644 index 000000000..ea2d1796a Binary files /dev/null and b/test/resources/complexscripts/arab/data/arab-001-f2.ser differ diff --git a/test/resources/complexscripts/arab/data/arab-001-f3.ser b/test/resources/complexscripts/arab/data/arab-001-f3.ser new file mode 100644 index 000000000..a0b49825f Binary files /dev/null and b/test/resources/complexscripts/arab/data/arab-001-f3.ser differ diff --git a/test/resources/complexscripts/arab/data/arab-001.txt b/test/resources/complexscripts/arab/data/arab-001.txt new file mode 100644 index 000000000..78772c68a --- /dev/null +++ b/test/resources/complexscripts/arab/data/arab-001.txt @@ -0,0 +1,85508 @@ +ءامنوا +آ +آب +آباء +آباءها +آباؤها +آباؤهم +آبائنا +آبائهم +آباد +آبار +آباراً +آبه +آتاك +آتاكم +آتت +آتي +آتية +آتيتم +آتيك +آثار +آثارا +آثاراً +آثارك +آثارمقلدة +آثاره +آثارها +آثارهم +آثاري +آثارًا +آثر +آثرت +آثـــار +آجلاً +آجلة +آحينية +آخذ +آخذا +آخذة +آخذه +آخذها +آخذين +آخر +آخرا +آخران +آخراً +آخرة +آخرمسرحيات +آخره +آخرها +آخرهم +آخرهما +آخرهن +آخرون +آخرى +آخرين +آخـر +آداب +آدابا +آدابنا +آدابه +آدامز +آدب +آدم +آدمية +آدمين +آذان +آذاناً +آذاننا +آذانها +آذانهم +آر +آراء +آراءهم +آراؤه +آراؤهم +آرائه +آرائها +آرائهم +آرائي +آراب +آرثر +آرمسترونج +آرنست +آريوس +آزوا +آسرا +آسرتين +آسرين +آسريه +آسف +آسفا +آسي +آسيا +آسيوي +آسيوية +آشلى +آشلي +آشور +آفات +آفاق +آفاقاً +آفاقه +آفاقًا +آفة +آقسنقر +آكد +آكل +آكلاً +آل +آلائه +آلات +آلاسكا +آلاف +آلافًا +آلام +آلامه +آلامها +آلان +آلة +آلت +آلته +آلف +آلمته +آلنسباخ +آله +آلهة +آلهتي +آلون +آلى +آلي +آليا +آليات +آلياته +آلياً +آلية +آليسندرو +آليَّة +آمال +آمالنا +آماله +آمالها +آمالهم +آمالي +آمر +آمرة +آمـن +آمل +آملاً +آملين +آمن +آمنا +آمناً +آمنة +آمنت +آمنوا +آمنًا +آمون +آمين +آمَنُوا +آمِنوا +آن +آنئذ +آنا +آناء +آند +آنذاك +آنس +آنفا +آنفاً +آنفة +آنه +آنيٌّ +آنّا +آه +آهٍ +آهْ +آوانا +آي +آيات +آياتا +آياته +آيار +آية +آيت +آيرس +آيزو +آيس +آيل +آيلة +آيللي +آينشتين +أ +أأ +أأعيد +أأنت +أؤكد +أؤمن +أؤمُّ +أئمة +أب +أبا +أبابا +أبابيل +أباد +أبادئها +أبادت +أبادله +أبادي +أبادير +أباريق +أباطيل +أباع +أباك +أبان +أبانا +أباه +أباها +أباً +أبت +أبتدع +أبتسم +أبتعد +أبتكر +أبتلع +أبجد +أبجديات +أبجدية +أبجديتهم +أبجديًا +أبحاث +أبحاثا +أبحاثك +أبحاثه +أبحاثها +أبحاثهم +أبحاثي +أبحث +أبحر +أبحرت +أبحرنا +أبخرة +أبدأ +أبدا +أبدانهن +أبداها +أبداً +أبدت +أبدد +أبدع +أبدعت +أبدعتها +أبدعنا +أبدلها +أبدو +أبدى +أبدي +أبديته +أبدًا +أبذل +أبذلها +أبراج +أبراجها +أبراجهم +أبراص +أبراهام +أبرد +أبرز +أبرزت +أبرزها +أبرزهم +أبرع +أبرم +أبرمت +أبرهة +أبرهن +أبريل +أبرّر +أبسط +أبسطها +أبشع +أبصر +أبصرنا +أبطأ +أبطال +أبطالك +أبطاله +أبطالها +أبطالهم +أبطل +أبعاد +أبعادا +أبعاده +أبعادها +أبعث +أبعد +أبعدت +أبعدتها +أبقار +أبقراط +أبقى +أبكتني +أبكر +أبكم +أبكوت +أبكي +أبلر +أبلوا +أبن +أبناء +أبناءنا +أبناءه +أبناءها +أبناءهم +أبناءهما +أبناءهن +أبناءِ +أبناؤكم +أبناؤنا +أبناؤه +أبناؤها +أبناؤهم +أبنائك +أبنائنا +أبنائه +أبنائها +أبنائهم +أبنائهما +أبنائي +أبنية +أبنيته +أبنيتها +أبها +أبهة +أبهى +أبو +أبوا +أبواب +أبوابا +أبواباً +أبوابه +أبوابها +أبواق +أبواه +أبواي +أبوبكر +أبوته +أبوح +أبورتي +أبورشدي +أبوسالم +أبوسيف +أبوشنب +أبوظبي +أبوعبدالرحمن +أبوعبدالله +أبوعمر +أبوك +أبوللو +أبولو +أبولّلو +أبولُّلو +أبونا +أبوه +أبوها +أبوي +أبويه +أبويّ +أبى +أبي +أبيات +أبياتا +أبياتها +أبيب +أبيت +أبيض +أبيع +أبيك +أبين +أبينا +أبيه +أبيها +أبيهم +أبيْتِ +أبًا +أبَى +أتأثر +أتأرجح +أتألم +أتأمل +أتابع +أتابك +أتاتوركية +أتاح +أتاحت +أتاحها +أتاني +أتاه +أتباع +أتباعه +أتباعها +أتبع +أتبعه +أتبناها +أتبنّ +أتبين +أتبينه +أتبينها +أتت +أتتبع +أتتبعها +أتجاسر +أتجاوزها +أتجه +أتجول +أتحبون +أتحتاجان +أتحداها +أتحدث +أتحدى +أتحدّث +أتحرر +أتحرق +أتحرك +أتحلى +أتحمل +أتحمّله +أتحول +أتحين +أتخذ +أتخفي +أتخلص +أتخيل +أتدخل +أتدرج +أتدرون +أتذكر +أتذكره +أتذكرها +أترابه +أتراجع +أتراحاسيس +أتراك +أترالكييو +أتراني +أتراهما +أترجم +أترجمه +أترجمها +أتردد +أتردّد +أترقب +أترك +أتركه +أتركها +أتريد +أتريدني +أتزعزع +أتزوج +أتساءل +أتسمع +أتش +أتشبث +أتشرّد +أتصدق +أتصدقين +أتصرف +أتصـرّف +أتصفح +أتصنعها +أتصور +أتصوّر +أتطلع +أتطلَّع +أتظن +أتعامل +أتعب +أتعبت +أتعذب +أتعرض +أتعرف +أتعرفين +أتعس +أتعسني +أتعـفّن +أتعلق +أتعلم +أتعلمها +أتعلمين +أتعود +أتعودها +أتفرج +أتفرّس +أتفهم +أتفوه +أتقاضي +أتقاكم +أتقدم +أتقصى +أتقصّى +أتقمّص +أتقن +أتقنوا +أتقول +أتقولين +أتقيأ +أتقياء +أتكأ +أتكاسل +أتكلم +أتلانتا +أتلانتيك +أتلصص +أتلفت +أتلق +أتلقى +أتم +أتمت +أتمثل +أتمرن +أتمرّس +أتمزق +أتمسك +أتمشى +أتمـــناها +أتمكن +أتمنى +أتمهل +أتناول +أتنزه +أتنصت +أتنفس +أتنقل +أتنهد +أتوا +أتواصل +أتوبيسات +أتوجه +أتوسل +أتوق +أتوقع +أتوقعه +أتوقعها +أتوقف +أتونها +أتوه +أتوهمها +أتى +أتيت +أتيتك +أتيته +أتيح +أتيحت +أتيليه +أتينا +أتُراها +أتْبعْت +أثابر +أثاث +أثاثها +أثاثًا +أثار +أثارا +أثارت +أثارتا +أثارته +أثارتها +أثاره +أثارها +أثبت +أثبتت +أثبتن +أثبتنا +أثبته +أثبتو +أثبتوا +أثبـتت +أثداء +أثر +أثرا +أثراً +أثرت +أثره +أثرها +أثرهم +أثروا +أثرى +أثري +أثريا +أثرياء +أثرياؤه +أثرية +أثريتها +أثريون +أثريين +أثريًا +أثرٌ +أثقال +أثقالا +أثقل +أثقلته +أثكلني +أثمانها +أثمر +أثمرت +أثمرته +أثمن +أثناء +أثناءها +أثنى +أثواباً +أثوابها +أثوابهم +أثير +أثيرت +أثينا +أثيوب +أثيوبيا +أثّرا +أثَّر +أجاب +أجابا +أجابت +أجابتها +أجابني +أجابه +أجابها +أجابهم +أجاثا +أجاد +أجادلهم +أجادها +أجازاتهم +أجازت +أجازته +أجانب +أجب +أجبت +أجبته +أجبر +أجبرت +أجبرتني +أجبرته +أجبها +أجتر +أجترحه +أجج +أجحدني +أجد +أجداد +أجدادنا +أجداده +أجدادهم +أجدادي +أجدت +أجدد +أجدر +أجدني +أجده +أجدها +أجدهم +أجدى +أجدُني +أجر +أجرؤ +أجرا +أجراء +أجراس +أجراه +أجراها +أجراً +أجرة +أجرت +أجرتك +أجرته +أجرتها +أجره +أجرهم +أجروها +أجرى +أجري +أجريت +أجريته +أجريتها +أجرينا +أجريناها +أجزئ +أجزاء +أجزاءها +أجزاءً +أجزائه +أجزائها +أجس +أجساد +أجسادنا +أجسادها +أجسادهم +أجسادهن +أجسام +أجسامنا +أجسامها +أجسامهم +أجسّدها +أجعل +أجعله +أجعلها +أجفان +أجفاننا +أجفانهم +أجفف +أجفلت +أجل +أجلب +أجلبه +أجلس +أجلسني +أجلك +أجله +أجلها +أجلهم +أجلى +أجلي +أجمع +أجمعت +أجمعين +أجمل +أجمله +أجملها +أجملِ +أجناس +أجناسهم +أجنبي +أجنبيا +أجنبية +أجنة +أجنحة +أجنحتها +أجنحـة +أجندة +أجندتهما +أجهدت +أجهز +أجهزة +أجهزتنا +أجهزته +أجهزتها +أجهزتهم +أجهضت +أجهضته +أجواء +أجوائه +أجوبة +أجودهما +أجور +أجوف +أجيء +أجيال +أجيالا +أجيالنا +أجيالهم +أجيب +أجيبي +أجيد +أجير +أجيراً +أجينور +أجّجتها +أجّل +أجَّلت +أحا +أحابي +أحادي +أحادية +أحاديث +أحاديثه +أحاديثي +أحاديّ +أحاذر +أحاسيس +أحاسيسه +أحاسيسها +أحاسيسي +أحاط +أحاطت +أحافظ +أحافير +أحاكم +أحال +أحالت +أحالته +أحاول +أحب +أحبائه +أحبابي +أحبالي +أحباناً +أحببت +أحببته +أحببتها +أحببتهم +أحببنا +أحبت +أحبتني +أحبكم +أحبه +أحبها +أحبوا +أحبّ +أحبَّ +أحتاج +أحتال +أحتراماً +أحترق +أحترم +أحتضن +أحتفظ +أحتويها +أحثكم +أحجار +أحجارها +أحجام +أحجامها +أحجبة +أحجمت +أحد +أحدا +أحداث +أحداثه +أحداثها +أحداثهما +أحداً +أحدث +أحدثت +أحدثته +أحدثك +أحدثن +أحدثه +أحدثها +أحدثوا +أحدده +أحددها +أحدق +أحدكم +أحدنا +أحدها +أحدهم +أحدهما +أحدًا +أحدٌ +أحدٍ +أحدَ +أحدِ +أحذرهم +أحذية +أحذيتهما +أحراج +أحرار +أحرارا +أحراش +أحرجتني +أحرز +أحرزت +أحرزته +أحرزناها +أحرزه +أحرص +أحرف +أحرفاً +أحرق +أحرقت +أحرك +أحرونوت +أحزابا +أحزان +أحزمة +أحزن +أحزنتني +أحس +أحسا +أحساسي +أحسب +أحست +أحسد +أحسست +أحسسته +أحسسنا +أحسن +أحسنت +أحسنتَ +أحسنها +أحسنوا +أحسنّا +أحسها +أحسّ +أحسَّت +أحشاء +أحشاءه +أحشائه +أحشائها +أحصاها +أحصر +أحصل +أحصنة +أحصي +أحضان +أحضانه +أحضانها +أحضر +أحضرت +أحضره +أحضرها +أحضرهم +أحضروا +أحط +أحطاب +أحطابها +أحطم +أحظى +أحـد +أحفاد +أحفاده +أحفادها +أحفادهم +أحفظ +أحفظه +أحفل +أحفورة +أحق +أحقاب +أحقق +أحقية +أحقيه +أحكام +أحكاما +أحكامه +أحكامها +أحكامًا +أحكم +أحكمت +أحكي +أحكيها +أحلام +أحلاماً +أحلامك +أحلامه +أحلامهم +أحلامي +أحلاميه +أحلاها +أحلت +أحلم +أحلمُ +أحلى +أحلي +أحماض +أحماله +أحمد +أحمر +أحمس +أحمـّل +أحمق +أحمل +أحمله +أحملها +أحملهم +أحميها +أحنافا +أحنه +أحنُّ +أحواض +أحواضهم +أحوال +أحوالنا +أحواله +أحوالها +أحوالهم +أحوالي +أحوج +أحولها +أحيا +أحياء +أحيائها +أحيان +أحيانا +أحياناً +أحيانًا +أحياه +أحيد +أحيدوس +أحيرام +أحيط +أحيل +أحيلكم +أحييت +أخ +أخا +أخاديدا +أخاذ +أخاطب +أخاطبها +أخاف +أخافني +أخافه +أخاك +أخال +أخالف +أخاه +أخاها +أخبار +أخباراً +أخبارنا +أخباره +أخبارها +أخبارهم +أخبارًا +أخبر +أخبرت +أخبرتك +أخبرتني +أخبرته +أخبرتها +أخبرنا +أخبرني +أخبره +أخبرها +أخبرهم +أخبروني +أخبريني +أخت +أختا +أختار +أختارها +أختام +أختبر +أخترنا +أختزل +أختزنه +أختصر +أختصرها +أختفى +أختفي +أختك +أختم +أختنق +أخته +أختي +أخدش +أخذ +أخذاه +أخذت +أخذتموهن +أخذتني +أخذته +أخذتها +أخذتْ +أخذن +أخذنا +أخذناها +أخذني +أخذه +أخذها +أخذهم +أخذوا +أخذوك +أخذوه +أخذوها +أخر +أخرج +أخرجت +أخرجته +أخرجنا +أخرجه +أخرجها +أخرق +أخره +أخرون +أخرى +أخري +أخريات +أخريين +أخرُجُ +أخسر +أخش +أخشاب +أخشاه +أخشى +أخص +أخصائى +أخصائية +أخصائيي +أخصب +أخضر +أخضرا +أخضعت +أخطأ +أخطأت +أخطأته +أخطأنا +أخطئ +أخطاء +أخطاؤنا +أخطائنا +أخطائها +أخطائي +أخطار +أخطارها +أخطارًا +أخطر +أخطط +أخطّه +أخــــطار +أخف +أخفاه +أخفتها +أخفتهما +أخفض +أخفضت +أخفف +أخفق +أخفقت +أخفى +أخفي +أخفيت +أخفيها +أخلاق +أخلاقه +أخلاقهم +أخلاقي +أخلاقيا +أخلاقيات +أخلاقياً +أخلاقية +أخلاّء +أخلد +أخلص +أخلع +أخليك +أخلّ +أخلّص +أخماج +أخماس +أخمص +أخمصي +أخناتون +أخواتها +أخواتي +أخواني +أخوة +أخوته +أخوتي +أخوك +أخوه +أخوها +أخوي +أخى +أخي +أخية +أخير +أخيرا +أخيراً +أخيرة +أخيرًا +أخيه +أخيها +أخّاذة +أداء +أداءه +أداءها +أدائه +أدائها +أدائهم +أداة +أداته +أداتي +أدار +أداري +أداعبه +أدافع +أداه +أداها +أدب +أدبا +أدباء +أدباءه +أدباؤه +أدبائها +أدباً +أدبنا +أدبه +أدبي +أدبيا +أدبيات +أدبياً +أدبية +أدبيًا +أدت +أدخر +أدخره +أدخل +أدخلت +أدخلته +أدخله +أدخلها +أدخلوا +أدراج +أدراجه +أدراجي +أدران +أدرانه +أدرانها +أدراني +أدرت +أدرج +أدرجت +أدرجه +أدرس +أدرك +أدركت +أدركته +أدركتها +أدركتهم +أدركنا +أدركناه +أدركها +أدركوا +أدركْتُ +أدرى +أدري +أدريان +أدريه +أدرّس +أدرِّس +أدش +أدع +أدعه +أدعوك +أدعوه +أدعوها +أدعوهم +أدعي +أدعية +أدفع +أدق +أدقق +أدقّ +أدل +أدلة +أدلى +أدناه +أدناها +أدنبره +أدنى +أدني +أدهشت +أدهشنا +أدهشني +أدهى +أدواء +أدواة +أدوات +أدواته +أدواتي +أدوار +أدوارا +أدواراً +أدواره +أدوارها +أدواري +أدور +أدورمات +أدون +أدونيس +أدوية +أدويتها +أدى +أديب +أديبا +أديبات +أديباً +أديبة +أديبًا +أدير +أديرت +أديس +أديسون +أديمَ +أدين +أدينوفيرس +أدّت +أدّعي +أدّى +أدَّت +أذا +أذابت +أذاة +أذاسا +أذاعت +أذان +أذانهم +أذبحه +أذرعه +أذق +أذقه +أذكر +أذكره +أذكّر +أذن +أذنان +أذناً +أذنه +أذني +أذنيه +أذنيها +أذنِ +أذنِها +أذهان +أذهاننا +أذهانهم +أذهب +أذهل +أذواق +أذى +أذيات +أذيب +أذية +أذيعت +أذيل +أر +أرأسه +أرأيت +أراء +أرائك +أراجع +أراجون +أراجيحها +أراد +أرادت +أراده +أرادها +أرادوا +أرادَ +أراض +أراضي +أراضينا +أراضيه +أراضيها +أراضٍ +أراعي +أراقب +أراقبك +أراقبها +أراقبهم +أراك +أراكِ +أرامكو +أرامل +أرانب +أراني +أراه +أراها +أراهم +أرباب +أربابه +أرباح +أرباحاً +أرباحها +أرباحي +أرباع +أرباعها +أرباني +أربض +أربطتها +أربع +أربعا +أربعاً +أربعاًمن +أربعة +أربعمائة +أربعون +أربعين +أربعينيات +أربكان +أرتاح +أرتب +أرتبط +أرتدي +أرتديه +أرتضيها +أرتنا +أرتّب +أرث +أرثها +أرثوذكسيًا +أرثي +أرجئ +أرجاء +أرجائها +أرجح +أرجع +أرجعنا +أرجعه +أرجعوا +أرجل +أرجله +أرجو +أرجوانية +أرجوك +أرجوكم +أرجوكِ +أرجوه +أرحام +أرحب +أرحل +أرخبيل +أرخص +أرخي +أرد +أردت +أردتم +أردد +أردف +أردفت +أردنا +أردية +أرذل +أرز +أرزاً +أرسطو +أرسطوطالية +أرسف +أرسل +أرسلان +أرسلت +أرسلته +أرسلن +أرسلني +أرسله +أرسلوها +أرسم +أرسمه +أرسمها +أرسوز +أرسى +أرسين +أرشاك +أرشدني +أرشف +أرشميدس +أرشيف +أرشّ +أرصد +أرصدة +أرصدها +أرصفة +أرض +أرضا +أرضاً +أرضعه +أرضنا +أرضه +أرضها +أرضهم +أرضى +أرضي +أرضيات +أرضية +أرضيت +أرضيتها +أرضًا +أرطاس +أرطال +أرعبني +أرفض +أرفع +أرفف +أرق +أرقا +أرقاء +أرقام +أرقاما +أرقاماً +أرقاً +أرقب +أرقبه +أرقبهما +أرقته +أرقط +أرقى +أرقي +أركان +أركز +أركض +أركّز +أرماس +أرمسترونج +أرملة +أرمنية +أرنب +أرنبا +أرنبة +أرنست +أرنستو +أرنو +أرنولد +أره +أرها +أرهبت +أرهفت +أرهقتَني +أرهقه +أرهم +أرواح +أرواحهم +أرواد +أروح +أروع +أروقة +أرونا +أروي +أرى +أري +أريتريا +أريحا +أريحية +أريحيته +أريد +أريدك +أريدكم +أريده +أريدها +أريسطوطال +أريك +أريكة +أريكته +أريكسون +أرييل +أرّخ +أرّخوا +أزاح +أزاحت +أزاد +أزار +أزال +أزالت +أزالوها +أزحت +أزحنا +أزرار +أزرق +أزره +أزري +أزعجت +أزعل +أزفها +أزقة +أزقتها +أزكمتها +أزل +أزلي +أزلية +أزمات +أزماتنا +أزماته +أزمان +أزماناً +أزمة +أزمتنا +أزمنة +أزهار +أزهارها +أزهاها +أزهرت +أزهري +أزهرية +أزهقت +أزهى +أزواج +أزواجنا +أزواجًا +أزور +أزوره +أزورها +أزياء +أزيحي +أزيد +أزيلت +أس +أسأل +أسألك +أسألكم +أسأله +أسألها +أسألهم +أسئلة +أسئلتك +أسئلتنا +أسئلته +أسئلتهم +أسئلتي +أسابقه +أسابيع +أساتذة +أساتذتك +أساتذته +أساتذتها +أساتذتي +أسارير +أساس +أساسا +أساسات +أساساً +أساسه +أساسها +أساسىين +أساسي +أساسيا +أساسيات +أساسيان +أساسياً +أساسية +أساسيتان +أساسيتين +أساسيين +أساسًا +أساطير +أساطيره +أساطيرها +أساطيل +أساطيلها +أساطيلهم +أساعد +أساعدكما +أسافر +أساليب +أساليبه +أساليبهم +أسامة +أسانوي +أسانيد +أساوم +أسباب +أسبابا +أسباباً +أسبابه +أسبابها +أسبابيه +أسبارجين +أسبانيا +أسبح +أسبر +أسبق +أسبوع +أسبوعا +أسبوعاً +أسبوعه +أسبوعي +أسبوعيا +أسبوعياً +أسبوعية +أسبوعيتين +أسبوعين +أسبوعيًا +أسبوعًا +أستأجر +أستأذنك +أستأذنكم +أستأنس +أستاذ +أستاذا +أستاذاً +أستاذة +أستاذتنا +أستاذتي +أستاذنا +أستاذه +أستاذها +أستاذي +أستاذية +أستاذًا +أستار +أستحضر +أستحقه +أستخدم +أستخلصه +أستدرك +أستدير +أستذكر +أستراليا +أسترجع +أسترحم +أسترسل +أسترق +أستريح +أستسلم +أستشهد +أستطاع +أستطع +أستطلع +أستطيع +أستطيعه +أستعجله +أستعد +أستعملها +أستعيد +أستعيده +أستعير +أستعين +أستفد +أستفسر +أستفيد +أستفيق +أستقر +أستقيها +أستمتع +أستمد +أستمر +أستمع +أستنجد +أستوعب +أستوعبها +أستوكهولم +أستون +أستونيا +أستيقظ +أستينوف +أسجل +أسخن +أسد +أسدا +أسدلت +أسدي +أسر +أسراب +أسرابه +أسرابٌ +أسراتٍ +أسرار +أسراراً +أسرارك +أسرارنا +أسراره +أسرارها +أسراري +أسرارِ +أسرانا +أسرة +أسرت +أسرتني +أسرته +أسرتها +أسرتي +أسرج +أسرح +أسرد +أسررت +أسرع +أسرعت +أسرعنا +أسرفنا +أسرق +أسرهم +أسرى +أسري +أسرياً +أسرّت +أسس +أسست +أسستها +أسسنا +أسسه +أسسها +أسطح +أسطحها +أسطر +أسطـح +أسطوانات +أسطوانة +أسطوانتي +أسطواني +أسطوانية +أسطورة +أسطوري +أسطوريا +أسطورية +أسطول +أسطولا +أسطولها +أسطى +أسع +أسعار +أسعارالعسل +أسعاراً +أسعاره +أسعارها +أسعد +أسعدتني +أسعدني +أسعده +أسعفتنا +أسعفته +أسعى +أسـئلة +أسف +أسفا +أسفار +أسفاره +أسفارها +أسفارهم +أسفارًا +أسفر +أسفرت +أسفل +أسفلت +أسفلتية +أسفله +أسفلها +أسفه +أسقط +أسقطها +أسقطوا +أسقطوها +أسقف +أسكت +أسكتلندا +أسكن +أسكنه +أسلافنا +أسلافه +أسلاك +أسلةً +أسلح +أسلحة +أسلحتنا +أسلحته +أسلحتها +أسلحتهم +أسلفت +أسلفنا +أسلك +أسلم +أسلمة +أسلمت +أسلوب +أسلوبا +أسلوباً +أسلوبك +أسلوبنا +أسلوبه +أسلوبها +أسلوبية +أسلوبين +أسلوبًا +أسلّي +أسماء +أسماءهم +أسماءً +أسماؤها +أسماؤهم +أسماؤهن +أسمائه +أسمائها +أسماع +أسماعنا +أسماك +أسماكها +أسماه +أسماها +أسمته +أسمح +أسمدة +أسمدتها +أسمر +أسمرة +أسمع +أسمعتم +أسمعني +أسمعه +أسمعيني +أسمك +أسمنتي +أسمنتية +أسموه +أسموها +أسمى +أسمياها +أسميته +أسمينا +أسميناه +أسميه +أسنان +أسنانه +أسنانها +أسنانهم +أسناني +أسندت +أسهر +أسهل +أسهم +أسهمت +أسهمه +أسهمها +أسهموا +أسوأ +أسوار +أسواراً +أسوارها +أسواق +أسواقا +أسواقنا +أسواقها +أسوان +أسوة +أسود +أسودا +أسوداً +أسوق +أسى +أسي +أسيء +أسيئ +أسيا +أسياخ +أسيادنا +أسيتيل +أسيجة +أسير +أسيرا +أسيراً +أسيرة +أسيرةً +أسيوط +أسّسها +أشاء +أشاح +أشاحت +أشاد +أشادت +أشار +أشارت +أشارك +أشاركهم +أشاروا +أشاطره +أشاطرهم +أشاع +أشاعت +أشاعه +أشاعها +أشاعوا +أشاهد +أشاهدها +أشباح +أشباحاً +أشبال +أشباه +أشباهه +أشباههم +أشبه +أشترك +أشتهي +أشجار +أشجارا +أشجاره +أشجارها +أشجانا +أشجع +أشجعهم +أشخاص +أشخاصاً +أشخبر +أشد +أشداء +أشداق +أشداقها +أشده +أشدها +أشدّ +أشدّها +أشرار +أشراف +أشرت +أشرح +أشرطة +أشرعة +أشرعتها +أشرف +أشرقت +أشركتهم +أشركنا +أشرنا +أشطر +أشعات +أشعار +أشعاره +أشعارها +أشعارهم +أشعاري +أشعب +أشعة +أشعتها +أشعث +أشعر +أشعل +أشعلت +أشعيا +أشعّة +أشعّت +أشفق +أشق +أشقاء +أشقائه +أشقوردة +أشك +أشكال +أشكالا +أشكالاً +أشكاله +أشكالها +أشكرك +أشكل +أشكو +أشكّل +أشلاء +أشم +أشمل +أشهد +أشهر +أشهرت +أشهرها +أشهى +أشواطاً +أشواق +أشوفج +أشياء +أشياءه +أشياؤه +أشير +أشيك +أصاب +أصابة +أصابت +أصابتنا +أصابتني +أصابته +أصابع +أصابعك +أصابعنا +أصابعه +أصابعها +أصابعهم +أصابعي +أصابنا +أصابني +أصابه +أصابها +أصابهم +أصابهما +أصابوني +أصارحكم +أصاف +أصافح +أصالة +أصالته +أصالتها +أصبت +أصبح +أصبحا +أصبحت +أصبحتا +أصبحتْ +أصبحـت +أصبحن +أصبحنا +أصبحوا +أصبع +أصبعه +أصبه +أصبو +أصحاب +أصحابه +أصحابها +أصحابي +أصحو +أصداء +أصداؤه +أصدائه +أصدر +أصدرالأمين +أصدرت +أصدرتم +أصدرته +أصدرتها +أصدره +أصدرها +أصدرْتُ +أصدق +أصدقاء +أصدقاؤك +أصدقاؤه +أصدقائك +أصدقائنا +أصدقائه +أصدقائها +أصدقائي +أصدقه +أصدكم +أصدّر +أصدّق +أصر +أصرت +أصرخ +أصرخي +أصرف +أصرفه +أصروا +أصرّ +أصص +أصطحبكم +أصطدم +أصعب +أصعبها +أصعد +أصعده +أصعّد +أصف +أصفر +أصفه +أصفهان +أصقاع +أصل +أصلا +أصلاب +أصلاً +أصلع +أصله +أصلها +أصلي +أصلية +أصم +أصمت +أصناف +أصنافاً +أصنافه +أصنافها +أصنع +أصنف +أصواب +أصوات +أصواتا +أصواتاً +أصواتنا +أصواتها +أصواتهم +أصور +أصول +أصوله +أصولها +أصولهم +أصولية +أصياف +أصيب +أصيبا +أصيبت +أصيبعة +أصيبوا +أصير +أصيل +أصيلا +أصيلاً +أصيلة +أضاءت +أضاع +أضاعف +أضاف +أضافت +أضافر +أضحت +أضحك +أضحكتنا +أضحى +أضحي +أضحية +أضخم +أضخمها +أضر +أضرار +أضرارا +أضراره +أضرارها +أضراس +أضراسه +أضرب +أضربُ +أضرت +أضرحة +أضرمت +أضرّت +أضطر +أضطررنا +أضع +أضعاف +أضعت +أضعته +أضعف +أضعفتها +أضعفني +أضعها +أضف +أضفت +أضفنا +أضفى +أضلاع +أضلاعه +أضلَّت +أضم +أضمن +أضمنه +أضمه +أضنتهما +أضواء +أضيء +أضيع +أضيف +أضيفت +أضيق +أطاع +أطال +أطالب +أطباء +أطباق +أطبعه +أطبق +أطحن +أطر +أطرا +أطراف +أطرافا +أطرافاً +أطرافه +أطرافها +أطرح +أطرف +أطرها +أطروحاتها +أطروحة +أطروحته +أطروحتي +أطعمة +أطعمتهم +أطعمه +أطفأ +أطفال +أطفالا +أطفالنا +أطفاله +أطفالها +أطفالهم +أطفالهما +أطفالهن +أطفالي +أطقم +أطل +أطلال +أطلالا +أطلانطا +أطلب +أطلبه +أطلت +أطلس +أطلع +أطلعت +أطلعتني +أطلعوا +أطلق +أطلقا +أطلقت +أطلقته +أطلقتها +أطلقنا +أطلقه +أطلقها +أطلقوا +أطلقي +أطلّق +أطمح +أطمع +أطنان +أطنانًا +أطهر +أطوار +أطواره +أطوارها +أطوالها +أطول +أطياف +أطيب +أطير +أطيق +أطيل +أظافره +أظفاري +أظل +أظلت +أظن +أظنك +أظننا +أظنه +أظنها +أظنّه +أظهر +أظهرت +أظهرتها +أعاجيب +أعاد +أعادا +أعادت +أعادته +أعادني +أعادوا +أعادوه +أعاق +أعالج +أعالجها +أعالى +أعالي +أعامل +أعانته +أعانق +أعانه +أعانهم +أعاني +أعانيه +أعانيها +أعبأ +أعباء +أعباءه +أعباءً +أعباؤه +أعبائها +أعبر +أعبـر +أعبّر +أعتاب +أعتبر +أعتبره +أعتبرها +أعتدي +أعتذر +أعترف +أعتز +أعتزم +أعتقد +أعتقدت +أعتمد +أعتني +أعتى +أعثر +أعجب +أعجبت +أعجبتنا +أعجبتني +أعجبته +أعجبني +أعجز +أعجف +أعجمه +أعجمي +أعجوبة +أعد +أعداء +أعداءك +أعداءها +أعداءهم +أعداؤه +أعداؤها +أعدائه +أعدائهم +أعداد +أعدادا +أعداداً +أعداده +أعدادها +أعدادهم +أعدادًا +أعدت +أعدتم +أعدته +أعدتها +أعدتُ +أعدد +أعددت +أعدم +أعده +أعدها +أعدوا +أعدوه +أعدّ +أعدّل +أعدّه +أعدَّت +أعذب +أعذبها +أعرابي +أعرابيّ +أعراس +أعراض +أعراضا +أعراضه +أعراف +أعراق +أعراقهم +أعرب +أعربت +أعربوا +أعرض +أعرضت +أعرضه +أعرف +أعرفك +أعرفكم +أعرفه +أعرفها +أعرفهم +أعرفُ +أعرق +أعز +أعزائي +أعزف +أعزّ +أعشاب +أعشاباً +أعشابها +أعشاش +أعشاشا +أعشاشاً +أعشاشه +أعشاشها +أعشق +أعشقه +أعصاب +أعصابك +أعصابه +أعصابي +أعضاء +أعضاءها +أعضاؤها +أعضاؤهم +أعضائه +أعضائها +أعطاف +أعطاك +أعطال +أعطاني +أعطاه +أعطاها +أعطاهم +أعطت +أعطتني +أعطته +أعطني +أعطه +أعطوا +أعطونا +أعطى +أعطي +أعطيت +أعطيتها +أعطيك +أعطيناكم +أعطِ +أعظم +أعظمها +أعـود +أعقاب +أعقابها +أعقبت +أعقبتها +أعقبها +أعقد +أعلا +أعلام +أعلامه +أعلاه +أعلاها +أعلت +أعلم +أعلمك +أعلمني +أعلمه +أعلمونا +أعلن +أعلنت +أعلنه +أعلى +أعلي +أعليه +أعمار +أعماركم +أعمارهم +أعماق +أعماقك +أعماقه +أعماقها +أعماقهم +أعماقهن +أعماقي +أعماقِ +أعمال +أعمالا +أعمالاً +أعمالك +أعماله +أعمالها +أعمالهم +أعمالي +أعمامي +أعمدة +أعمق +أعمل +أعمى +أعناقها +أعنف +أعني +أعنيه +أعنّة +أعهده +أعواد +أعوام +أعوامي +أعود +أعوذ +أعور +أعوض +أعوم +أعوّدها +أعوّض +أعي +أعياد +أعيادهم +أعيان +أعيانها +أعياه +أعيد +أعيده +أعيدي +أعيره +أعيش +أعيشه +أعيشها +أعين +أعيننا +أعينها +أعينهم +أف +أفئدة +أفئدتهم +أفاد +أفادت +أفادتني +أفادوا +أفاضت +أفاضل +أفاق +أفاقا +أفاقاً +أفاقت +أفاويه +أفتتح +أفتح +أفتحه +أفتخر +أفتراحها +أفترض +أفتش +أفتقده +أفتِّش +أفجع +أفجي +أفحص +أفخر +أفخم +أفدت +أفدح +أفدنة +أفراح +أفراحهم +أفراد +أفرادا +أفراده +أفرادها +أفرادَ +أفراس +أفرام +أفرج +أفرح +أفرخت +أفردت +أفرزها +أفرض +أفرط +أفرطت +أفرع +أفركهما +أفريقي +أفريقيا +أفريقية +أفريك +أفرّق +أفزع +أفزعتنا +أفزعني +أفسح +أفسحت +أفسد +أفسدت +أفسدته +أفسده +أفسدوا +أفسّر +أفشل +أفصحت +أفضت +أفضحك +أفضل +أفضلها +أفضّل +أفضِّل +أفطن +أفظع +أفظعني +أفعال +أفعل +أفعله +أفعى +أفق +أفقاً +أفقد +أفقده +أفقر +أفقيا +أفقياً +أفقية +أفكار +أفكارا +أفكاراً +أفكاره +أفكارها +أفكارهم +أفكارهما +أفكاري +أفكر +أفكّر +أفل +أفلا +أفلاج +أفلاطون +أفلام +أفلاما +أفلامك +أفلامه +أفلامها +أفلامي +أفلت +أفلح +أفلحت +أفلس +أفنت +أفهم +أفهمها +أفواج +أفواه +أفواها +أفواهها +أفواههم +أفولها +أفيائها +أفيد +أفيشاته +أفينيو +أقابل +أقابله +أقارب +أقاربك +أقاربنا +أقاربه +أقاربها +أقاربهم +أقاربي +أقارعهم +أقاصي +أقال +أقاليم +أقام +أقامت +أقامته +أقامتها +أقامر +أقامه +أقامها +أقاموا +أقاويل +أقاويلهم +أقبض +أقبل +أقبلها +أقبلوا +أقبية +أقتحم +أقتحمها +أقترب +أقترح +أقتل +أقتله +أقتلهم +أقحاح +أقحوان +أقداح +أقداحه +أقدام +أقدامنا +أقدامه +أقدامها +أقدامهم +أقدامَهما +أقدر +أقدره +أقدرها +أقدس +أقدم +أقدمت +أقدمه +أقدمها +أقدّرهم +أقر +أقرأ +أقرأه +أقرأها +أقراص +أقراط +أقران +أقرانه +أقرانها +أقرانهم +أقرب +أقرباءها +أقرباؤنا +أقربائنا +أقربائها +أقربائهما +أقربائي +أقرت +أقرتها +أقرفص +أقرن +أقره +أقرها +أقرّه +أقساط +أقسام +أقساما +أقسامها +أقسم +أقسنقر +أقسو +أقسى +أقسّم +أقصاب +أقصاها +أقصد +أقصده +أقصر +أقصى +أقصي +أقصيت +أقضت +أقضي +أقطاب +أقطار +أقطارنا +أقطاره +أقطارهم +أقطان +أقطع +أقطفه +أقطن +أقع +أقعدته +أقعده +أقعدها +أقف +أقفاص +أقفرت +أقل +أقلام +أقلامهم +أقلت +أقلتنا +أقلع +أقلعت +أقلق +أقلقت +أقلقنا +أقله +أقلها +أقلية +أقليدس +أقلّ +أقلّب +أقلُّ +أقم +أقمار +أقماش +أقمت +أقمشة +أقمنا +أقمناه +أقنع +أقنعة +أقنعت +أقنعه +أقواس +أقواسا +أقوال +أقوالهم +أقوام +أقول +أقوله +أقولها +أقوم +أقوى +أقوياء +أقيس +أقيل +أقيم +أقيمت +أكاد +أكاديمي +أكاديميا +أكاديمياً +أكاديمية +أكاسيد +أكاكوس +أكان +أكانت +أكبر +أكبرها +أكبرهم +أكبرَ +أكتاف +أكتافنا +أكتافه +أكتب +أكتبه +أكتبها +أكترث +أكتسب +أكتشف +أكتفي +أكتوبر +أكتوس +أكثر +أكثرأهمية +أكثرالكتب +أكثرمن +أكثره +أكثرها +أكثرهم +أكثرهن +أكثرية +أكثفها +أكد +أكدت +أكدته +أكده +أكدها +أكذب +أكذوبة +أكر +أكراد +أكرر +أكرم +أكرمكم +أكره +أكرهك +أكرهه +أكزيما +أكزيمائية +أكسب +أكسبته +أكسبها +أكسجة +أكسجين +أكسدة +أكسر +أكسفورد +أكسوبري +أكسي +أكسيد +أكسيدنتال +أكفاء +أكفاننا +أكفهم +أكفيك +أكل +أكلات +أكلة +أكلت +أكلنا +أكله +أكلها +أكمات +أكمامه +أكمد +أكمل +أكملنا +أكملوا +أكن +أكواب +أكواخ +أكواخهم +أكواريوس +أكوام +أكوره +أكولة +أكون +أكونه +أكويلا +أكياس +أكياساً +أكياسهم +أكيبوس +أكيد +أكيدا +أكيدة +أكُفٍّ +أكّد +أكّدته +أكَّد +ألا +ألاباما +ألاحظ +ألاحظه +ألاحظها +ألازمه +ألاسكا +ألاعيبه +ألان +ألاين +ألاّ +ألاَّ +ألب +ألبا +ألبانها +ألباني +ألبانيا +ألبتة +ألبرت +ألبرتي +ألبس +ألبسة +ألبسه +ألبسوه +ألبـــير +ألبوماته +ألبومًا +ألبي +ألبير +ألتدبير +ألتفت +ألتقط +ألتقي +ألتمس +ألتهب +ألجأ +ألحان +ألحانه +ألححنا +ألحظ +ألحـق +ألحق +ألحقت +ألحقه +ألحّت +ألخص +ألخصها +ألدس +ألدو +ألدوس +ألزمته +ألزهايمر +ألست +ألستُ +ألستِ +ألسن +ألسنا +ألسنة +ألسنةٍ +ألسنتكم +ألسنتها +ألصق +ألطف +ألعاب +ألعابا +ألعب +ألعن +ألعنها +ألف +ألفا +ألفاظ +ألفاظا +ألفاظه +ألفاظها +ألفان +ألفاً +ألفة +ألفت +ألفته +ألفتها +ألفرد +ألفريد +ألفناه +ألفه +ألفها +ألفي +ألفية +ألفين +ألفًا +ألفَ +ألفّ +ألقاب +ألقاه +ألقاها +ألقت +ألقتها +ألقها +ألقوا +ألقى +ألقي +ألقيت +ألقيتُ +ألقيتُها +ألقينا +ألقيها +ألقَى +ألكاليجينس +ألكترونيا +ألكسندر +ألم +ألمان +ألماني +ألمانيا +ألمانية +ألمانًا +ألماً +ألمحت +ألمس +ألمع +ألملم +ألمنيوم +ألمها +ألميكادو +ألمّ +ألمّت +ألن +ألهب +ألهبت +ألهته +ألهذا +ألهمته +ألهمني +ألهمه +ألهوه +ألواح +ألوان +ألوانا +ألوانك +ألوانه +ألوانها +ألوث +ألوذ +ألوف +ألوم +ألوية +ألياف +أليس +أليست +أليف +أليفاً +أليفة +أليمة +ألين +ألينوى +ألِدْهُ +ألّف +ألّفت +ألَّف +ألْصقت +أم +أما +أمارات +أمارس +أمازلت +أمازون +أماسي +أمافي +أماكن +أماكننا +أماكنها +أمالي +أمام +أمامك +أمامنا +أمامه +أمامها +أمامهم +أمامهما +أمامي +أمان +أمانا +أمانة +أمانتك +أمانها +أمانًا +أماً +أمبوس +أمبيسيلين +أمة +أمتار +أمتاراً +أمتعة +أمتعتنا +أمتعته +أمتعتهم +أمتعض +أمتعنا +أمتلك +أمتنا +أمته +أمتها +أمتهم +أمتهن +أمتي +أمثال +أمثالك +أمثالنا +أمثاله +أمثالها +أمثالي +أمثل +أمثلة +أمجاد +أمجاده +أمجادهم +أمجد +أمد +أمدا +أمداً +أمدح +أمدد +أمده +أمر +أمرا +أمراء +أمرائها +أمراض +أمراضا +أمراضنا +أمراضه +أمراضهم +أمران +أمراً +أمرت +أمرتني +أمرتِ +أمرك +أمرنا +أمره +أمرها +أمري +أمريكا +أمريكان +أمريكى +أمريكي +أمريكيا +أمريكيات +أمريكياً +أمريكية +أمريكيون +أمريكيين +أمريكيًا +أمرين +أمرًا +أمرٌ +أمرٍ +أمس +أمسافر +أمستردام +أمسك +أمسكا +أمسكت +أمسكتْ +أمسكنا +أمسكناه +أمسكوا +أمسيات +أمسياته +أمسية +أمسيت +أمشي +أمضاها +أمضوا +أمضى +أمضي +أمضيت +أمضيتم +أمضيته +أمضيتها +أمطرت +أمعاء +أمعن +أمعنت +أمـا +أمـل +أمك +أمكث +أمكن +أمكنة +أمكنتهم +أمكنك +أمكننا +أمل +أملا +أملاح +أملاك +أملاً +أملت +أملس +أملك +أملكه +أمله +أملها +أملوها +أملى +أملي +أمم +أممي +أممية +أممًا +أمن +أمنا +أمناء +أمناً +أمنت +أمنحتب +أمنحه +أمنحها +أمنع +أمنعك +أمنعه +أمنه +أمنوا +أمني +أمنيا +أمنياته +أمنياتهم +أمنياً +أمنية +أمنيته +أمنيتها +أمنيتي +أمه +أمها +أمهات +أمهاتها +أمهاتهم +أمهد +أمهرِ +أمهم +أموات +أمواج +أمواجا +أمواجه +أموال +أموالا +أموالاً +أمواله +أموالها +أموالهم +أموت +أمور +أمورا +أموراً +أمورك +أموركم +أمورنا +أموره +أمورها +أمورهم +أمورًا +أمويين +أمي +أميال +أمية +أمير +أميرا +أميراتها +أميرال +أميرة +أميركا +أميركية +أميرها +أميري +أميرًا +أميز +أميل +أمين +أمينا +أميناً +أمينة +أمينه +أميين +أميّ +أميّاً +أميّز +أميّون +أمَةَ +أمّ +أمّا +أمّة +أمّنوا +أمَّا +أمَّاً +أن +أنا +أنابيب +أناجيها +أناديك +أناديه +أنارت +أنازلهم +أناس +أناسا +أناساً +أناشيد +أناشيدي +أنام +أنامل +أناملنا +أنامهم +أناني +أناهيت +أناهيد +أنباء +أنبتتهم +أنبله +أنبه +أنبوب +أنت +أنتج +أنتجت +أنتجته +أنتجتها +أنتجرال +أنتجنا +أنتجه +أنتجوا +أنتجوه +أنتخب +أنتزاع +أنتسب +أنتشي +أنتصاري +أنتظر +أنتظرها +أنتقل +أنتقم +أنتقي +أنتم +أنتما +أنتمي +أنتهي +أنتي +أنتَ +أنتِ +أنثاه +أنثوي +أنثوية +أنثى +أنثيين +أنج +أنجب +أنجبت +أنجبهم +أنجح +أنجز +أنجزت +أنجزته +أنجزتها +أنجزنا +أنجزه +أنجزها +أنجزوا +أنجع +أنجلوس +أنحاء +أنحـاء +أند +أندر +أندرسون +أندره +أندرو +أندريا +أندريه +أندهش +أندي +أندية +أنر +أنزل +أنزلت +أنزلونا +أنزور +أنزيماته +أنزيماً +أنس +أنساب +أنساق +أنساقها +أنساقًا +أنسام +أنسانا +أنساني +أنساه +أنساها +أنساهما +أنسب +أنسته +أنستهم +أنسج +أنسجة +أنسجته +أنسجتها +أنسجم +أنسحب +أنسخ +أنسكِ +أنسلمو +أنسلُّ +أنسى +أنشأ +أنشأت +أنشأته +أنشأتها +أنشأها +أنشأوا +أنشئ +أنشئت +أنشاها +أنشد +أنشدتها +أنشر +أنشره +أنشرها +أنشطة +أنشطتنا +أنشطته +أنشطتها +أنشطتهم +أنشودة +أنصار +أنصاره +أنصارها +أنصاف +أنصت +أنصتت +أنصح +أنصع +أنصفوا +أنضج +أنضجته +أنضجه +أنطاكية +أنطوان +أنطون +أنطونين +أنطونيوس +أنظار +أنظارنا +أنظارهم +أنظاري +أنظر +أنظف +أنظمة +أنظمتها +أنعشت +أنعشتني +أنعم +أنعيها +أنف +أنفاس +أنفاسنا +أنفاسه +أنفاسها +أنفاسهم +أنفاسي +أنفاقا +أنفجر +أنفس +أنفسا +أنفسكم +أنفسنا +أنفسهم +أنفسهن +أنفع +أنفـاسـُه +أنفق +أنفقت +أنفقته +أنفقوا +أنفك +أنفه +أنفها +أنفي +أنفيليكا +أنقاض +أنقاضه +أنقذت +أنقذتني +أنقذني +أنقذونا +أنقر +أنقرة +أنقصه +أنقض +أنقل +أنقله +أنقلها +أنقى +أنك +أنكر +أنكره +أنكروا +أنكم +أنم +أنما +أنماط +أنماطا +أنماطه +أنموذج +أنموذجا +أنموذجاً +أنموذجًا +أننا +أننى +أنني +أنه +أنها +أنهار +أنهت +أنهر +أنهض +أنهكت +أنهكتها +أنهكه +أنهم +أنهما +أنهن +أنهى +أنهيت +أنهيتُ +أنوء +أنوا +أنوار +أنوارها +أنواع +أنواعا +أنواعاً +أنواعه +أنواعها +أنوال +أنوثة +أنوثتها +أنور +أنوسنت +أنوفنا +أنوي +أنوية +أنى +أني +أنياب +أنياباً +أنيابه +أنيابها +أنير +أنيردد +أنيس +أنيسة +أنيسفيلد +أنيطت +أنيق +أنيقة +أنيقًا +أنيميا +أنين +أنينا +أنّ +أنّا +أنّنا +أنّني +أنّه +أنّها +أنّى +أنَّ +أنَّبته +أنَّه +أنَّها +أهاب +أهابه +أهاجر +أهالي +أهبة +أهتف +أهتم +أهتماماتك +أهجم +أهدأ +أهدئ +أهداب +أهدابه +أهداف +أهدافه +أهدافها +أهداني +أهداه +أهداها +أهدتني +أهدتها +أهدف +أهدم +أهدى +أهدي +أهذا +أهذي +أهرامات +أهرب +أهكذا +أهل +أهلا +أهلاً +أهلة +أهلته +أهلك +أهلم +أهلنا +أهله +أهلها +أهلي +أهلية +أهليتهم +أهم +أهمس +أهمل +أهملت +أهملناه +أهمها +أهمهم +أهمهما +أهمية +أهميته +أهميتها +أهمّ +أهمّها +أهنئك +أهنئكم +أهنيك +أهو +أهوائها +أهوادو +أهوار +أهوال +أهون +أهوى +أهي +أهيئ +أهيب +أهينت +أهّلنا +أهّلني +أهَّله +أو +أوأخالفهم +أوأي +أوائل +أواثنين +أواجه +أواخر +أواخره +أوارا +أوارد +أواره +أوارها +أواسط +أواصر +أواصل +أواظب +أوافق +أوافقهم +أوالطعام +أوامر +أوامره +أوامرها +أوان +أواني +أوانٍ +أواه +أواي +أوبئة +أوبرا +أوبريت +أوبك +أوبنهايمر +أوبيك +أوتاد +أوتاوا +أوتوا +أوتوشيلي +أوتوماتيكي +أوتي +أوج +أوجار +أوجاع +أوجاعه +أوجاعها +أوجب +أوجد +أوجدت +أوجدتها +أوجز +أوجست +أوجه +أوجها +أوجهاً +أوجهها +أوجين +أوحال +أوحالا +أوحت +أوحش +أوحوا +أوحى +أود +أودت +أودع +أودعه +أودعها +أودعونا +أودى +أودية +أوديتها +أور +أوراق +أوراقه +أوراقها +أوراقهم +أوراقي +أوراقٌ +أورام +أوراني +أوربا +أورباني +أوربي +أوربياً +أوربية +أوربيين +أورثتْني +أورثه +أورد +أوردت +أوردته +أوردنا +أوردناه +أورده +أوردها +أوردوا +أورطة +أوركتسراليا +أوركسترا +أوركسترالي +أورلاندو +أورلي +أورليانز +أورنك +أورو +أوروبا +أوروبية +أوروك +أورومجي +أورويل +أوريكس +أوزار +أوزاره +أوزارها +أوزانها +أوزانهم +أوزانهن +أوزع +أوزفالدو +أوزن +أوزنك +أوزو +أوزيبيو +أوس +أوساط +أوساطهم +أوسبنسكي +أوسترهولم +أوستلر +أوستن +أوستيند +أوسط +أوسطتين +أوسطها +أوسطي +أوسطية +أوسطيين +أوسع +أوسكار +أوسكارات +أوسلو +أوسمات +أوسمته +أوشك +أوشكت +أوشين +أوصاف +أوصال +أوصالها +أوصاليه +أوصانا +أوصاني +أوصت +أوصتني +أوصعوبة +أوصل +أوصلت +أوصلتها +أوصلها +أوصى +أوصياءهم +أوضاع +أوضاعنا +أوضاعه +أوضاعها +أوضاعهم +أوضح +أوضحت +أوضحهم +أوضحوا +أوطان +أوطانها +أوطانهم +أوطويت +أوظف +أوعرائس +أوعز +أوعية +أوعيته +أوفاتا +أوفد +أوفدوا +أوفى +أوقات +أوقاتكم +أوقاتنا +أوقاته +أوقاتها +أوقاتهم +أوقاتًا +أوقبله +أوقد +أوقع +أوقعت +أوقعتني +أوقعنا +أوقعها +أوقف +أوقفت +أوقفته +أوقفه +أوقفها +أوقفوا +أوقفوه +أوقلو +أوقّع +أوكتايل +أوكراني +أوكرانيا +أوكسجين +أوكسفورد +أوكسوس +أوكسي +أوكل +أوكلاهوما +أوكلت +أول +أولئك +أولا +أولاد +أولاداً +أولادنا +أولاده +أولادها +أولادهم +أولادهما +أولادي +أولاك +أولاه +أولاها +أولاهما +أولاً +أولبرايت +أولت +أولتها +أولد +أوللرسم +أوله +أولها +أولهما +أولو +أولويات +أولوياتها +أولوية +أولى +أولي +أولياء +أوليات +أولياً +أولية +أوليفر +أوليفينات +أوليمبيا +أومان +أومدن +أومن +أوموافقة +أون +أونا +أونتاريو +أونثاريو +أونجاريتي +أونفور +أونوفروي +أونيل +أوه +أوهام +أوهامي +أوهايو +أوهم +أوهمني +أوهَب +أوو +أوي +أويت +أوّل +أوّلاً +أى +أىضا +أي +أيا +أيابا +أيادي +أياديهم +أيادٍ +أيام +أياما +أياماً +أيامنا +أيامه +أيامها +أيامي +أيامًا +أياً +أيبرز +أيبس +أيبك +أية +أيتام +أيتها +أيجوز +أيد +أيدت +أيدتها +أيدى +أيدي +أيدينا +أيديهم +أيديهما +أيديولوجيا +أيديولوجيات +أيديولوجياتهم +أيديولوجية +أيرلندي +أيروبيكس +أيزو +أيسر +أيسلاند +أيسلندا +أيسلندة +أيضا +أيضاً +أيضاَ +أيضًا +أيقظه +أيقظوني +أيقن +أيقنت +أيقونات +أيقوناتها +أيقونة +أيقونتها +أيلول +أيما +أيمكن +أيمن +أين +أينشتاين +أينشتين +أينشين +أينعت +أينما +أيها +أيهـــــا +أيهما +أيوب +أيونيدس +أيّ +أيّا +أيّام +أيّامه +أيّدها +أيّما +أيّهم +أيّهما +أيًّا +أيَّ +أيِّ +أَتْقَاكُمْ +أَحسَّ +أَسره +أَكْرَمَكُمْ +أَن +أَنهِ +أَنِّي +أَوْ +أَوْلِيَاءُ +أَيُّهَا +أُبتت +أُتيح +أُجري +أُجريت +أُجرِيَت +أُحب +أُحبُّ +أُحسن +أُخذت +أُخرج +أُخضعت +أُدخلت +أُدْخِلَ +أُذن +أُرسلت +أُريد +أُزيلت +أُضِيعُ +أُطيق +أُعدت +أُعدَّت +أُعفي +أُعلن +أُعيد +أُعْلنَ +أُفرج +أُفقدت +أُفلت +أُقيمت +أُلحق +أُلقي +أُلَملِم +أُلْهَم +أُمَّها +أُنشئ +أُنشئت +أُنْثَى +أُنْشِئَ +أُهدي +أُهين +أُوتُوا +أُوصي +أُولئك +أُولَئِكَ +إ +إإ +إإإ +إباحيا +إباحية +إبادة +إبان +إبتعد +إبحار +إبحارا +إبداء +إبداع +إبداعا +إبداعات +إبداعاته +إبداعاتها +إبداعاتهم +إبداعاتي +إبداعاً +إبداعه +إبداعها +إبداعي +إبداعيا +إبداعياً +إبداعية +إبر +إبراز +إبرازا +إبرازها +إبرامه +إبراهام +إبراهيم +إبرة +إبرهيم +إبريق +إبريل +إبصار +إبصارهم +إبطاء +إبطائها +إبطالها +إبعاد +إبعاداً +إبعاده +إبعادي +إبقاء +إبليس +إبن +إبناه +إبنة +إبهار +إبو +إبّان +إتاحة +إتاحتها +إتاحـة +إتجاه +إتحاد +إتخاذ +إتش +إتصال +إتصاله +إتصل +إتضح +إتفاقية +إتقان +إتقانه +إتقانها +إتلاف +إتلافها +إتمام +إتمامه +إتيل +إثارة +إثبات +إثباته +إثر +إثراء +إثرها +إثقال +إثنين +إثير +إثيلين +إجابات +إجابة +إجابته +إجابتي +إجادة +إجازاتهم +إجازة +إجازته +إجبار +إجباراً +إجبارى +إجباريا +إجتجاجا +إجر +إجراء +إجراءات +إجراءاتها +إجراؤها +إجرائهم +إجري +إجلاء +إجلالاً +إجماع +إجماعاً +إجمالا +إجمالاً +إجمالى +إجمالي +إجماليا +إجهاض +إجهاضات +إحاطة +إحالتها +إحالتي +إحباط +إحباطات +إحباطاته +إحتمال +إحداث +إحداثه +إحداثها +إحداثياته +إحداها +إحداهما +إحداهن +إحدى +إحدي +إحذري +إحراز +إحرازه +إحراق +إحساس +إحساسا +إحساساتي +إحساساً +إحساسه +إحساسهم +إحساسي +إحسان +إحصاء +إحصاءات +إحصاءاتنا +إحصائي +إحصائيات +إحصائية +إحضار +إحضارها +إحـدي +إحقاق +إحقاقاً +إحكام +إحلال +إحليل +إحنا +إحناإحنا +إحياء +إحيائه +إخافة +إخافته +إخافتهم +إخبار +إخباره +إخبارهم +إخبارية +إخراج +إخراجه +إخراجها +إخصائي +إخصائيا +إخصائيين +إخصاب +إخضاع +إخضاعه +إخضاعها +إخطار +إخطاره +إخفاء +إخفاءها +إخفائها +إخفاق +إخفاقاتها +إخفاقنا +إخلاء +إخلاصه +إخماد +إخوان +إخوانا +إخواننا +إخوانه +إخوانهم +إخواني +إخوة +إخوتنا +إخوته +إخوتهم +إدارات +إداراته +إدارة +إدارته +إدارتها +إداري +إداريا +إدارية +إداريّة +إدانة +إدانتك +إدانته +إدانتها +إدجار +إدخال +إدخاله +إدراج +إدراجه +إدراجها +إدراك +إدراكاً +إدراكه +إدريس +إدسا +إدعاء +إدعاءً +إدفو +إدماج +إدماجه +إدمان +إدموند +إدن +إدوار +إدوارالخراط +إدوارد +إذ +إذا +إذاعات +إذاعة +إذاعي +إذاعياً +إذاعية +إذاً +إذعان +إذكاء +إذلال +إذلالاً +إذلاله +إذن +إذنا +إذناً +إذنك +إذنه +إذهب +إذًا +إذْ +إرادة +إرادتك +إرادتي +إرادياً +إرباك +إرباكا +إربي +إرتاح +إرتاخ +إرث +إرثي +إرجاء +إرجاؤه +إرجاع +إرخاء +إرساء +إرسال +إرسالا +إرساله +إرسالها +إرسالهم +إرشاد +إرشادات +إرشاداتهم +إرشادية +إرضاء +إرضاءً +إرفنج +إرل +إرهاب +إرهابي +إرهابية +إرهاصات +إرهاق +إريتريا +إريل +إزاء +إزاءه +إزاءها +إزاحة +إزار +إزارلة +إزاري +إزالة +إزالتها +إزداد +إزعاج +إزعاجا +إزعاجهم +إزهار +إزهاقه +إس +إسا +إساءة +إسالة +إسباس +إسباني +إسبانيا +إسبانيتنا +إستاد +إستانب +إستانبول +إستثمار +إستجاب +إستدرجتها +إستر +إستراتيجيات +إستراتيجية +إسترازينيكا +إسترحمهما +إسترليني +إستطلاع +إستعداد +إستعدادا +إستعمال +إستمرار +إستون +إسرائيل +إسرائيلي +إسرائيلياً +إسرائيلية +إسرائيليين +إسرافا +إسطرلاب +إسطرلابًا +إسعاد +إسعافا +إسقاط +إسقاطات +إسقاطاته +إسقاطاتهم +إسقاطه +إسكاته +إسكندراني +إسكواش +إسكيتش +إسكيتشًا +إسلام +إسلاماً +إسلامه +إسلامها +إسلامي +إسلاميا +إسلامياً +إسلامية +إسلاميتين +إسلاميًا +إسلاميًّا +إسماع +إسماعيل +إسمج +إسمح +إسمحوا +إسمع +إسمه +إسمي +إسنا +إسناد +إسنادها +إسهال +إسهام +إسهاما +إسهامات +إسهاماته +إسهاماتها +إسهاماً +إسهامه +إسهامي +إسهروا +إشادة +إشارات +إشاراته +إشاراتها +إشارة +إشارته +إشارتهم +إشاعات +إشاعة +إشباع +إشباعها +إشرابا +إشراف +إشرافه +إشرافها +إشراقة +إشراك +إشعار +إشعاع +إشعاعات +إشعاعاتها +إشعاعها +إشعاعي +إشعاله +إشفاق +إشفيك +إشكالات +إشكالي +إشكاليات +إشكالية +إشهار +إصابات +إصابة +إصابته +إصابتها +إصابتهم +إصبر +إصبع +إصبعه +إصبعها +إصبعي +إصحاح +إصحاحها +إصدار +إصدارا +إصدارات +إصداراتها +إصداره +إصدارها +إصدارًا +إصرار +إصرارا +إصراره +إصراري +إصعدي +إصلاح +إصلاحا +إصلاحات +إصلاحه +إصلاحها +إصلاحي +إصلاحية +إضاءات +إضاءة +إضاءتها +إضاعة +إضافات +إضافة +إضافته +إضافتها +إضافي +إضافيا +إضافياً +إضافية +إضحاكا +إضحكاك +إضراب +إضعاف +إضفاء +إطار +إطارا +إطارات +إطاره +إطارها +إطارًا +إطاعة +إطالة +إطباقية +إطعام +إطلاع +إطلاق +إطلاقا +إطلاقاً +إطلاقه +إطلاقها +إطلاقًا +إطلالة +إطلالها +إطلع +إطماء +إظهار +إعادة +إعادته +إعادتها +إعاقات +إعاقة +إعاقتهم +إعالة +إعتقال +إعتقالات +إعجاب +إعجابا +إعجاباً +إعجابنا +إعجابه +إعجابهم +إعجابي +إعجاز +إعجازه +إعجازًا +إعداد +إعدادا +إعداداً +إعدادنا +إعداده +إعدادها +إعدادي +إعدادية +إعدام +إعراضا +إعصار +إعطاء +إعطاءه +إعطاؤها +إعطائه +إعطائها +إعطائي +إعلام +إعلاما +إعلامي +إعلاميا +إعلامياً +إعلامية +إعلان +إعلانا +إعلانات +إعلاناتها +إعلاناً +إعلانحالة +إعلانه +إعلانها +إعلانية +إعمار +إعوام +إف +إفادة +إفادتنا +إفتراضية +إفراديا +إفرادية +إفراز +إفرازا +إفرازات +إفرازاتها +إفرازه +إفراط +إفريقي +إفريقيا +إفريقية +إفساح +إفساد +إفشال +إفضاءً +إفطار +إفطارها +إفطارهم +إفلاس +إفهامكِ +إقالة +إقامة +إقامةٍ +إقامتنا +إقامته +إقامتها +إقامتهم +إقامتي +إقبال +إقبالا +إقبالاً +إقباله +إقتحم +إقتناء +إقحام +إقحامها +إقدام +إقرأ +إقرأها +إقرار +إقرارات +إقراره +إقصاء +إقطاعك +إقطاعي +إقفال +إقفل +إقلاع +إقلاعها +إقليدس +إقليم +إقليمنا +إقليمه +إقليمي +إقليمية +إقليميًا +إقناع +إقناعه +إقناعها +إقناعي +إقناعًا +إكبار +إكبارنا +إكرام +إكس +إكسفورد +إكسون +إكسير +إكليلاً +إكمال +إكماله +إكوداتاس +إكوفيول +إلا +إلاسلام +إلاك +إلاً +إلاّ +إلاَّ +إلبي +إلتزام +إلحاح +إلحاق +إلحاقه +إلحاقهم +إلخ +إلزام +إلزامي +إلزاميا +إلزامية +إلصاق +إلـي +إلقاء +إلقائها +إلكترون +إلكتروني +إلكترونيا +إلكترونياً +إلكترونية +إلكتريك +إلمام +إلماما +إلماماً +إلمامه +إله +إلها +إلهاب +إلهام +إلهامه +إلهامي +إلهي +إلهية +إلهًا +إلويار +إلى +إلىموقع +إلىه +إلي +إلياذة +إلياس +إليجا +إليجانز +إليزابيث +إليش +إليك +إليكم +إليكِ +إلينا +إلينوي +إليه +إليها +إليهم +إليهما +إليهن +إليوت +إليّ +إليّا +إليَّ +إم +إما +إماتة +إمارات +إماراتهم +إمارة +إماطة +إمالة +إمام +إماما +إماماً +إمبابي +إمبراطور +إمبراطورا +إمبراطوراً +إمبراطورية +إمتاعاً +إمداد +إمدادات +إمرأة +إمراضية +إمرة +إمرتها +إمرسون +إمساك +إمساكها +إمعانا +إمكان +إمكانات +إمكاناته +إمكاناتها +إمكاناتي +إمكانه +إمكانيات +إمكانياتك +إمكانياتها +إمكانياتي +إمكانية +إملاءاته +إمناء +إمنيد +إميل +إميلشيل +إميلي +إمّا +إن +إنا +إناء +إناث +إناثها +إناس +إنبات +إنباتية +إنت +إنتاج +إنتاجا +إنتاجاً +إنتاجنا +إنتاجه +إنتاجها +إنتاجهم +إنتاجي +إنتاجية +إنتاجيتهم +إنتاجيًّا +إنتانات +إنتانه +إنتركونتيننتال +إنتركونتيننتنال +إنترنت +إنتلاقى +إنتهى +إنتو +إنتوا +إنثاريو +إنج +إنجاب +إنجابه +إنجاح +إنجاز +إنجازا +إنجازات +إنجازاته +إنجازاتها +إنجازاً +إنجازك +إنجازه +إنجازها +إنجازًا +إنجلترا +إنجليز +إنجليزي +إنجليزية +إنجنيت +إنجيل +إنجيلية +إنخفاض +إنخفضت +إندس +إندونيسيا +إندونيسياً +إنديرا +إنذار +إنذارات +إنذاراً +إنروح +إنزال +إنزيم +إنساكيويو +إنسان +إنسانا +إنساناً +إنسانة +إنساننا +إنساني +إنسانيا +إنسانية +إنسانيته +إنسانيتها +إنسانيتهم +إنسانيتي +إنسانيّ +إنسانًا +إنشاء +إنشاءات +إنشاءها +إنشاؤها +إنشائه +إنشائها +إنشائية +إنشادها +إنضاجه +إنطاق +إنطلاقه +إنطلق +إنعاش +إنـه +إنفاق +إنفاقهم +إنفاقهما +إنفاقي +إنفو +إنقاذ +إنقاذهم +إنقاص +إنك +إنكار +إنكاره +إنكارها +إنكلترا +إنكم +إنما +إنماء +إنمائي +إنمائية +إننا +إننى +إنني +إنه +إنها +إنهاء +إنهائه +إنهاض +إنهم +إنهما +إنهن +إنوسنت +إنوما +إني +إنيرجي +إنّ +إنّما +إنّنا +إنّها +إنّي +إنَّ +إنَّه +إنَّها +إهانات +إهانة +إهتمامها +إهدأ +إهداء +إهدائه +إهدار +إهدارا +إهلاك +إهلرس +إهمال +إهمالاً +إهمالنا +إهماله +إهمالها +إهمالهما +إهمالي +إهي +إي +إياد +إياك +إياكم +إياه +إياها +إيبا +إيبرت +إيبــرت +إيتش +إيثيل +إيجابا +إيجاباً +إيجابي +إيجابيا +إيجابيات +إيجابياته +إيجابياً +إيجابية +إيجاد +إيجار +إيجارا +إيجاراتها +إيجاز +إيجبتومانيا +إيجور +إيجيبت +إيحاء +إيحاءات +إيداعها +إيديولوجيا +إيديولوجية +إيذاء +إيذائي +إيذان +إيذانا +إيذاناً +إيرادات +إيراداته +إيراداتها +إيراده +إيران +إيراني +إيرانيا +إيرانية +إيرباص +إيربيل +إيرفورت +إيرل +إيرلاينز +إيرنست +إيروس +إيزابيلا +إيسلي +إيش +إيشلون +إيصال +إيصالها +إيضاح +إيضاحا +إيطالي +إيطاليا +إيطالية +إيفان +إيفانز +إيفرن +إيقاظنا +إيقاظه +إيقاع +إيقاعاتها +إيقاعه +إيقاف +إيقافه +إيقافها +إيقافهم +إيكونوميا +إيلات +إيلاج +إيلاماً +إيلوارد +إيليا +إيلينوي +إيماءة +إيمائي +إيمان +إيمانا +إيماناً +إيماننا +إيمانه +إيمانها +إيمانهم +إيماني +إيمانية +إيملي +إيميت +إيميل +إيندهوفن +إينشتاين +إينوزين +إيني +إيه +إيها +إيوا +إيوان +إيوتروفاس +إيوجين +إِلاَّ +إِنَّ +إِنَّا +ئروتنا +ئز +ا +اآسيوية +اؤلئك +ائتلاف +ااقواسم +االتي +االخاصة +ابتدأ +ابتداء +ابتداءً +ابتدائية +ابتداع +ابتدع +ابتدعتها +ابتدعه +ابتسامة +ابتسامتكِ +ابتسامته +ابتسم +ابتسمت +ابتسمنا +ابتعاث +ابتعاد +ابتعاده +ابتعادها +ابتعث +ابتعثت +ابتعثوا +ابتعد +ابتعدت +ابتعدتِ +ابتكار +ابتكاراً +ابتكر +ابتكرت +ابتكرته +ابتكرتها +ابتلاع +ابتلاعها +ابتلع +ابتلعت +ابتلعتها +ابتلعه +ابتلعها +ابتلَّت +ابتنى +ابتهج +ابتهجت +ابحث +ابحثْ +ابدت +ابدى +ابذلوا +ابراهيم +ابريق +ابق +ابقى +ابل +ابن +ابنا +ابناً +ابنة +ابنتان +ابنتك +ابنتنا +ابنته +ابنتها +ابنتهما +ابنتي +ابنك +ابنه +ابنها +ابنى +ابني +ابنٌ +ابوالعتاهية +ابيب +ابيض +ابيضاض +اة +ات +اتباع +اتباعه +اتباعها +اتبع +اتبعت +اتبعتُها +اتبعنا +اتبعني +اتبعه +اتبعها +اتجاه +اتجاها +اتجاهات +اتجاهاتها +اتجاهاتهم +اتجاهه +اتجاهها +اتجاهين +اتجه +اتجهت +اتجهنا +اتجهوا +اتحاد +اتحدت +اتحدوا +اتخ +اتخاذ +اتخاذه +اتخاذها +اتخذ +اتخذت +اتخذته +اتخذتها +اتخذتْ +اتخذه +اتخذها +اتخذوا +اتخذوه +اتخيل +اتركها +اتركوا +اتركونا +اتركوني +اتركيني +اتزان +اتزانه +اتزانها +اتساخ +اتساع +اتساعا +اتساعاً +اتساعه +اتساعهما +اتساق +اتسخ +اتسع +اتسعت +اتسم +اتسمت +اتصاري +اتصال +اتصالا +اتصالات +اتصالاته +اتصالنا +اتصاله +اتصالها +اتصالين +اتصل +اتصلت +اتصلوا +اتضح +اتضحت +اتعيش +اتفاق +اتفاقا +اتفاقات +اتفاقاً +اتفاقيات +اتفاقية +اتفاقيه +اتفق +اتفقا +اتفقت +اتفقنا +اتفقوا +اتقائها +اتقوا +اتكأت +اتكأنا +اتكاءة +اتمختري +اتمنى +اتهام +اتهامات +اتهامنا +اتهامه +اتهم +اتهمت +اتهمه +اتهمها +اتهموا +اتهموه +اتيامبل +اتّجاه +اتّحاد +اتّخذت +اتّسع +اتّصال +اتَّجه +اتِّزانه +اثارتني +اثباتات +اثبت +اثنا +اثناء +اثنان +اثنتان +اثنتي +اثنتين +اثنى +اثني +اثنين +اثير +اجابات +اجت +اجتاح +اجتاحت +اجتاحها +اجتازت +اجتازتا +اجتذاب +اجتذبت +اجتذبك +اجترأ +اجتزنا +اجتماع +اجتماعا +اجتماعات +اجتماعاته +اجتماعاً +اجتماعنا +اجتماعهم +اجتماعي +اجتماعيا +اجتماعياً +اجتماعية +اجتماعيًا +اجتماعيًّا +اجتمع +اجتمعا +اجتمعت +اجتمعوا +اجتهاد +اجتهادات +اجتهاداته +اجتهاداتهم +اجتهادي +اجتهادية +اجتهادًا +اجتهد +اجتهدت +اجتياح +اجتياحا +اجتياحه +اجتياحها +اجتياز +اجر +اجراء +اجراءات +اجريت +اجل +اجلس +اجلستني +اجمعهما +اجهزة +اح +احبك +احبهم +احتاج +احتاجت +احتار +احتاروا +احتاط +احتباس +احتج +احتجاج +احتجاجا +احتجاجات +احتجاجي +احتجبت +احتجت +احتجزنا +احتجنا +احتدام +احتدّ +احتذوا +احتذيا +احترار +احتراف +احتراق +احتراقها +احترام +احتراما +احتراماً +احترامها +احترامًا +احترفت +احترقت +احترم +احتساء +احتسبت +احتشاء +احتشائية +احتشام +احتشد +احتضان +احتضانهم +احتضن +احتضنت +احتضنه +احتضنونا +احتفاء +احتفاظ +احتفاظه +احتفال +احتفالا +احتفالات +احتفالي +احتفاليا +احتفالية +احتفالين +احتفظ +احتفظت +احتفظوا +احتفل +احتفلت +احتفلوا +احتفى +احتقار +احتقان +احتكار +احتكاك +احتكاكه +احتكاكهم +احتل +احتلال +احتلالها +احتلالهم +احتلالية +احتلت +احتلتها +احتله +احتلها +احتمال +احتمالات +احتمالاته +احتمالاً +احتمل +احتواء +احتواءً +احتوائه +احتواه +احتواها +احتوت +احتياجات +احتياجاتنا +احتياجاته +احتياجاتها +احتياجاتهم +احتياجاتي +احتياجاً +احتياجهم +احتياطات +احتياطي +احتياطياً +احتياطيها +احجارها +احجية +احد +احداث +احداثاً +احداهما +احدث +احدق +احدهم +احدهما +احدى +احزر +احساس +احضار +احضر +احضرت +احضري +احـتياجات +احفظ +احمد +احمر +احمرار +احمرارا +احمرّت +احمل +احيانا +احيي +اخ +اخباره +اخبريني +اختار +اختارت +اختارتني +اختارته +اختارني +اختاره +اختارها +اختارهم +اختاروا +اختاروني +اختاري +اختبآ +اختبأ +اختباء +اختبار +اختبارا +اختبارات +اختباران +اختبارها +اختبرت +اختتم +اختر +اختراع +اختراعا +اختراعات +اختراعاته +اختراعاتها +اختراعاتهم +اختراعاً +اختراعه +اختراعي +اختراعًا +اختراق +اختراقات +اختراقاً +اختراقه +اختراقها +اخترت +اخترتُ +اخترتُها +اخترع +اخترعته +اخترعه +اخترق +اخترقت +اخترقتُ +اخترنا +اخترناها +اختزال +اختزالية +اختزان +اختزل +اختزنت +اختزنتها +اختصار +اختصارا +اختصاراً +اختصارها +اختصارهم +اختصاص +اختصاصاته +اختصاصاتها +اختصاصه +اختصاصها +اختصاصهم +اختصاصي +اختصاصيين +اختصتهم +اختصر +اختصرت +اختصرنا +اختضَّ +اختط +اختطفته +اختطفه +اختطفهم +اختطه +اختطها +اختفاء +اختفاءها +اختفت +اختفى +اختك +اختلاء +اختلاجات +اختلاط +اختلاطات +اختلاطاته +اختلاطاتها +اختلاف +اختلافا +اختلافات +اختلافها +اختلافهم +اختلال +اختلالات +اختلت +اختلط +اختلطت +اختلف +اختلفا +اختلفت +اختلفنا +اختلفوا +اختمرت +اختناق +اختناقاً +اختناقي +اختيار +اختيارا +اختيارات +اختياراته +اختياره +اختيارها +اختيارهم +اختياري +اختياريا +اختيارين +اختير +اختيرت +اخذتموهما +اخذته +اخراجها +اخرج +اخرى +اخصم +اخضرارًا +اخطأ +اخطر +اخطف +اخطفهم +اخفاء +اخماد +اخوتي +اخيرا +اد +ادار +ادارة +ادارتها +ادخرته +ادخرك +ادخل +ادركتهم +ادري +ادع +ادعاء +ادعاءات +ادعاءاتها +ادعاءاتهم +ادعائه +ادعم +ادعى +ادفع +اذ +اذا +اذاً +اذنا +اذهاننا +اذهب +اذهبوا +اذهبي +ار +ارابيس +ارادت +ارادتها +ارادتي +اراديا +اربطه +ارة +ارتأينا +ارتباط +ارتباطا +ارتباطات +ارتباطاته +ارتباطاً +ارتباطه +ارتباطها +ارتباطًا +ارتباك +ارتباكا +ارتبط +ارتبطت +ارتبكت +ارتجاعاته +ارتجفت +ارتحالي +ارتحت +ارتحل +ارتحلت +ارتحلنا +ارتخاء +ارتد +ارتداء +ارتداءالقفّازات +ارتداءه +ارتدائه +ارتدائها +ارتدادا +ارتدته +ارتدوا +ارتسمت +ارتشاحات +ارتضوا +ارتضى +ارتطام +ارتطامه +ارتطمت +ارتعاشات +ارتعبنا +ارتعش +ارتعشت +ارتفاع +ارتفاعا +ارتفاعات +ارتفاعاتها +ارتفاعاً +ارتفاعه +ارتفاعها +ارتفاعًا +ارتفع +ارتفعت +ارتقاء +ارتقت +ارتكاب +ارتكاز +ارتكازه +ارتكاس +ارتكاسات +ارتكب +ارتكبت +ارتكبتها +ارتكبناها +ارتكبه +ارتكبها +ارتكبوا +ارتكبوه +ارتكبوها +ارتكز +ارتكزت +ارتوازية +ارتويا +ارتياب +ارتيابا +ارتيابه +ارتياح +ارتياد +ارتيادها +ارحم +اردت +ارسم +ارضاً +ارضى +ارفع +ارفعي +اركيتكتشر +ارماند +ارنست +ارهاب +ارى +اريد +اريه +اريو +ازاحتها +ازداد +ازدادت +ازدادوا +ازدحام +ازدحاما +ازدحمت +ازددت +ازدهار +ازدهارا +ازدهاراً +ازدهارها +ازدهارهم +ازدهر +ازدهرت +ازدواج +ازدواجية +ازدياد +ازديادا +ازدياداً +ازرق +ازور +ازيل +اس +اسأل +اسألوا +اسألي +اسئلة +اسابيع +اساسات +اسبريتوس +استأثرت +استأجر +استأجرت +استأذنا +استأذنت +استأذنتها +استأنف +استئجار +استئذان +استئصال +استئصالها +استئصلت +استئناف +استاذ +استاذنتني +استانبول +استباحة +استباق +استبدال +استبدالها +استبدل +استبدلوا +استبطان +استبعاد +استبعادنا +استبعاده +استبعادهم +استبعد +استبعدتها +استبيانات +استثار +استثارة +استثمار +استثمارات +استثماراتها +استثماراً +استثمارياً +استثمارية +استثناء +استثناءات +استثنائي +استثنائية +استثنينا +استثير +استجاب +استجاباته +استجابة +استجابت +استجابته +استجابتها +استجار +استجداء +استجلاء +استجماع +استجمعت +استجوابهم +استجوب +استجوبت +استحال +استحالة +استحث +استحداث +استحدث +استحدثت +استحدثنا +استحدثوا +استحسان +استحسنت +استحسنتها +استحصال +استحضاراً +استحق +استحقاق +استحقاقاً +استحقاقًا +استحمام +استحمامه +استحوذ +استخدام +استخداما +استخدامات +استخدامه +استخدامها +استخدامهم +استخدامي +استخدامًا +استخدم +استخدما +استخدمت +استخدمته +استخدمتها +استخدمنا +استخدمه +استخدمها +استخدموا +استخدموها +استخذم +استخراج +استخراجه +استخرج +استخرجتها +استخلاص +استخلاصه +استخلصته +استخلصتها +استخلصوا +استدار +استدارة +استدارت +استدراجه +استدراكية +استدرج +استدرك +استدرّ +استدعاء +استدعاني +استدعاه +استدعت +استدعته +استدعوني +استدعى +استدعيت +استدلالات +استديو +استذكار +استراتيجي +استراتيجيا +استراتيجيات +استراتيجياً +استراتيجية +استراحات +استراحة +استراليا +استرجاع +استرجاعات +استرجاعها +استرجع +استرجعت +استرحام +استرحتم +استرحنا +استرخاء +استرخائه +استرخت +استرخى +استرخي +استرد +استرداد +استرداده +استرداف +استردته +استرده +استردّوا +استرشدت +استرعاهم +استرعت +استرعى +استرعيا +استرق +استرليني +استزادة +استزراع +استزلامياً +استسلام +استسلامهم +استسلم +استسلمت +استسهال +استشارات +استشارة +استشارت +استشارته +استشارى +استشاري +استشراف +استشراقي +استشراقية +استشرت +استشعرت +استشفاء +استشفاف +استشهاد +استشهادي +استشهادية +استشهد +استشهدنا +استشهدوا +استصدارها +استصلاح +استصناع +استضاف +استضافة +استضافت +استضافته +استضافنا +استضافه +استضافهم +استطاع +استطاعا +استطاعت +استطاعتي +استطاعوا +استطباب +استطعت +استطعن +استطعنا +استطلاع +استطلاعات +استطلاعنا +استطلاعية +استطلع +استطيع +استعاد +استعادة +استعادتها +استعادوا +استعار +استعارة +استعارها +استعان +استعانت +استعانوا +استعد +استعداد +استعدادا +استعدادات +استعداداتكم +استعداداتنا +استعداده +استعدادها +استعدادي +استعدادًا +استعدت +استعذت +استعراب +استعراض +استعراضها +استعرض +استعصائي +استعصيت +استعمار +استعمارا +استعمارياً +استعمارية +استعمال +استعماله +استعمالها +استعمالهما +استعمل +استعملت +استعملوا +استعنا +استعنت +استفاد +استفادة +استفادت +استفاده +استفادوا +استفاق +استفاقة +استفتاء +استفتائه +استفحالها +استفدت +استفرد +استفزازي +استفزه +استفسار +استفسارات +استفهام +استقاء +استقال +استقالة +استقالت +استقالته +استقامة +استقبال +استقبالنا +استقبالهم +استقبالهما +استقبل +استقبلت +استقبلتنا +استقبلنا +استقبله +استقبلها +استقبلوا +استقدام +استقدم +استقر +استقراء +استقرائهم +استقرار +استقرارها +استقرت +استقروا +استقرّ +استقصاءات +استقصائية +استقصى +استقطاب +استقلابية +استقلال +استقلاله +استقلالها +استقلالية +استقى +استكشاف +استكشافها +استكشافية +استكشف +استكمال +استكمالا +استكمالاً +استكماله +استكمالها +استكمله +استكهولم +استلاب +استلام +استلقاء +استلقت +استلقى +استلهام +استلهم +استماع +استمالة +استمالتهم +استمتاع +استمتع +استمتعنا +استمد +استمدت +استمدها +استمر +استمرءوا +استمرار +استمرارا +استمراره +استمرارها +استمرارية +استمرارًا +استمرت +استمررت +استمرَّ +استمع +استمعت +استمعنا +استمعوا +استملاك +استناد +استنادا +استناداً +استنادها +استنارة +استنبات +استنباط +استنباطا +استنبول +استنتاج +استنتاجات +استنتاجاتهم +استنتاجاً +استنتاجية +استنتجها +استنجدت +استند +استندت +استندوا +استنزاف +استنساخ +استنساخها +استنشاق +استنشاقها +استنفاذ +استنفدت +استنفدوا +استنقاذ +استنكار +استنهضه +استهداف +استهدف +استهدفت +استهدفته +استهل +استهلاك +استهلاكه +استهلاكها +استهلاكهم +استهلاكية +استهلاله +استهلك +استهلكت +استهلكها +استهلها +استهوت +استهوتني +استواء +استوائية +استوحاه +استوحى +استوحيت +استودع +استودعتكم +استوديو +استوردت +استوطنوا +استوعبا +استوعبت +استوعبوا +استوقفت +استوقفتني +استوقفتها +استوقفه +استوكهولم +استولت +استولوا +استولى +استولينا +استيراد +استيرادها +استيطان +استيطانه +استيطانياً +استيعاب +استيعابا +استيعابه +استيعابها +استيفاء +استيفائها +استيفن +استيقاظه +استيقظ +استيقظت +استيكو +استينوف +استيهاماته +استُخرج +استُشهد +اسجدوا +اسحق +اسطبل +اسطبله +اسطنبول +اسطوانات +اسطوانة +اسع +اسفل +اسفلتي +اسكتلندي +اسكتي +اسكندرونة +اسكوتلانديارد +اسكوتوس +اسلام +اسم +اسما +اسماء +اسماءها +اسماعيل +اسمان +اسماه +اسماً +اسمتر +اسمحي +اسمع +اسمعني +اسمعي +اسمعيني +اسمك +اسمكِ +اسمنت +اسمنتية +اسمه +اسمها +اسمي +اسميها +اسمٌ +اسمٍ +اسندتها +اسودّت +اسيتات +اسيد +اسيرى +اش +اشار +اشارة +اشتاق +اشتباه +اشتد +اشتداد +اشتدت +اشتدّ +اشتدّت +اشتراك +اشتراكا +اشتراكها +اشتراكهم +اشتراكي +اشتراكياً +اشتراه +اشتراها +اشترت +اشترتها +اشترك +اشتركت +اشتركوا +اشتروها +اشترى +اشتريت +اشتريتها +اشتعالا +اشتعالاً +اشتعل +اشتق +اشتقاق +اشتقوا +اشتكى +اشتمت +اشتمل +اشتملت +اشتهر +اشتهرت +اشتهروا +اشتهيت +اشتياق +اشجار +اشخاص +اشعار +اشعر +اشعل +اشكاليات +اشكول +اشمأزت +اشياء +اصابة +اصابتهم +اصابع +اصابعى +اصبح +اصبحت +اصداراتها +اصرف +اصطاد +اصطاده +اصطحابه +اصطحابها +اصطحب +اصطحباه +اصطحبته +اصطحبتها +اصطحبه +اصطدام +اصطدامك +اصطدامنا +اصطدتها +اصطدم +اصطدمت +اصطفاك +اصطلاح +اصطلاحا +اصطلاحات +اصطلاحيا +اصطلاحية +اصطلح +اصطناع +اصطناعي +اصطناعية +اصطياد +اصعب +اصعدي +اضافة +اضخمه +اضطر +اضطراب +اضطرابا +اضطرابات +اضطرار +اضطرارا +اضطراري +اضطرت +اضطرتها +اضطررت +اضطرني +اضطرها +اضطروا +اضطلاع +اضطهاد +اضطهاداً +اضطهد +اضطُرَّ +اضعافها +اضمحل +اضمحلال +اطراد +اطرد +اطردوا +اطلاع +اطلاعا +اطلاعكم +اطلاعه +اطلاعهم +اطلاعي +اطلب +اطلع +اطلعت +اطلعنا +اطلعوا +اطلق +اطمأن +اطمأنت +اطمأنوا +اطمئن +اطمئنان +اطماعاً +اطنان +اظهار +اعادت +اعتاد +اعتادت +اعتادها +اعتادوا +اعتادوه +اعتاض +اعتبار +اعتبارا +اعتبارات +اعتباراً +اعتبارنا +اعتباره +اعتبارها +اعتبارهم +اعتبارهما +اعتباري +اعتبارياً +اعتبارية +اعتبارًا +اعتبر +اعتبرت +اعتبرته +اعتبرتُ +اعتبرنا +اعتبرناه +اعتبره +اعتبرها +اعتبروها +اعتداءاتهم +اعتدال +اعتدت +اعتدلت +اعتدن +اعتدنا +اعتذار +اعتذارهم +اعتذر +اعتذرت +اعتذروا +اعتراض +اعتراضات +اعتراضاته +اعتراضه +اعتراف +اعترافا +اعترافات +اعترافاتهم +اعترافاً +اعترافهم +اعتراني +اعتراها +اعترت +اعترته +اعترض +اعترضت +اعترضتهم +اعترضوا +اعترف +اعترفا +اعترفت +اعترفن +اعتزازا +اعتزل +اعتصامات +اعتصمت +اعتقاد +اعتقادا +اعتقادنا +اعتقاده +اعتقادها +اعتقادي +اعتقادًا +اعتقال +اعتقالات +اعتقالاً +اعتقاله +اعتقالها +اعتقد +اعتقدا +اعتقدت +اعتقدوا +اعتقل +اعتقلت +اعتقله +اعتقلوا +اعتقلوني +اعتكاف +اعتلال +اعتلت +اعتلى +اعتليت +اعتلينا +اعتماد +اعتمادا +اعتماداً +اعتمادك +اعتماده +اعتمادها +اعتمادي +اعتمادًا +اعتمت +اعتمد +اعتمدت +اعتمدته +اعتمدها +اعتناء +اعتناقها +اعتنق +اعتنقوا +اعتنوا +اعتورنا +اعتيادي +اعتيادية +اعتَدْ +اعتُقل +اعجابه +اعداد +اعذرني +اعذروا +اعراض +اعرض +اعرفي +اعزائي +اعش +اعطهم +اعـتباراً +اعلق +اعلى +اعمالنا +اعمل +اعملها +اعوجاج +اعوجَّ +اعياد +اعية +افتاي +افتتاح +افتتاحه +افتتاحها +افتتاحيات +افتتاحية +افتتاحيتها +افتتح +افتتحت +افتتحها +افتتحوها +افتح +افتخاري +افتراء +افتراسي +افتراض +افترشوها +افترض +افترضنا +افتضاح +افتقاد +افتقاده +افتقار +افتقاره +افتقدت +افتقده +افتقر +افتيح +افتُعلتْ +افرنج +افصلوا +اق +اقاليم +اقامته +اقبر +اقتباسها +اقتبس +اقتبست +اقتبسها +اقتحام +اقتحم +اقتحما +اقتحمت +اقتحمه +اقتحموا +اقتحموها +اقتراب +اقترابا +اقترابه +اقترابي +اقترابًا +اقتراح +اقتراحات +اقتراحه +اقتراحي +اقتراحًا +اقترانه +اقترانها +اقترب +اقتربت +اقتربنا +اقترح +اقترحت +اقترحنا +اقترحه +اقترفنا +اقترن +اقترنت +اقتسار +اقتسمتا +اقتسموا +اقتصاد +اقتصادات +اقتصاداتها +اقتصاداً +اقتصادنا +اقتصاده +اقتصادى +اقتصادي +اقتصاديا +اقتصاديات +اقتصادياته +اقتصادياتها +اقتصادياً +اقتصادية +اقتصاديون +اقتصاديين +اقتصاديًا +اقتصار +اقتصارها +اقتصاي +اقتصر +اقتصرت +اقتضب +اقتضت +اقتضته +اقتضى +اقتطاع +اقتفاء +اقتفيت +اقتلاع +اقتلع +اقتناء +اقتنائه +اقتناع +اقتناه +اقتناها +اقتنص +اقتنصنا +اقتنع +اقتنعنا +اقتنى +اقتنيته +اقرأ +اقرب +اقصد +اقصدها +اقعد +اقفز +اقل +اقليم +اقناعه +اقنعت +اكبر +اكتئابه +اكتراث +اكتساب +اكتسابها +اكتسب +اكتسبت +اكتسبته +اكتسبتها +اكتسبه +اكتسبها +اكتسبوا +اكتسحها +اكتسى +اكتشاف +اكتشافات +اكتشافه +اكتشافها +اكتشافهم +اكتشافي +اكتشف +اكتشفت +اكتشفتها +اكتشفنا +اكتشفه +اكتشفها +اكتشفوا +اكتظاظها +اكتظت +اكتف +اكتفت +اكتفوا +اكتفى +اكتفي +اكتمال +اكتماله +اكتمل +اكتنف +اكتوى +اكتُشف +اكثر +اكزيما +اكس +اكسبريس +اكسبيرينس +اكستر +اكليل +اكنس +اكوره +ال +الآباء +الآبار +الآبدة +الآتون +الآتي +الآتية +الآتين +الآتيه +الآثار +الآثاريون +الآثر +الآثرية +الآجال +الآجر +الآجل +الآحاد +الآخاذ +الآخذ +الآخذة +الآخر +الآخران +الآخرة +الآخرون +الآخرين +الآداب +الآدمي +الآدميات +الآدمية +الآدميين +الآذان +الآذن +الآراء +الآرامية +الآراميين +الآزوت +الآستانة +الآسر +الآسرة +الآسن +الآسيا +الآسيوي +الآسيوية +الآسيويين +الآشوري +الآشورية +الآشوريين +الآف +الآفات +الآفاق +الآفة +الآفل +الآفلة +الآكشن +الآلات +الآلاف +الآلام +الآلة +الآلهة +الآلي +الآليات +الآلية +الآمال +الآمان +الآمرة +الآمن +الآمنة +الآن +الآنسة +الآنف +الآنفة +الآني +الآنية +الآنْ +الآه +الآهلة +الآونة +الآي +الآيات +الآياتا +الآية +الآيس +الأئمة +الأب +الأباتشي +الأباجورات +الأباطرة +الأبجدي +الأبجدية +الأبجورات +الأبحاث +الأبخرة +الأبخس +الأبد +الأبداعية +الأبدي +الأبدية +الأبراج +الأبراح +الأبرار +الأبراص +الأبرياء +الأبستان +الأبسطة +الأبسيسيك +الأبصار +الأبطال +الأبعاد +الأبعد +الأبقار +الأبناء +الأبنية +الأبهة +الأبهى +الأبواب +الأبوة +الأبوي +الأبوية +الأبوين +الأبيات +الأبيض +الأتابك +الأتابكة +الأتاري +الأتراك +الأتربة +الأتو +الأتوبيس +الأتوبيسات +الأتوجرافات +الأثاث +الأثر +الأثري +الأثرياء +الأثرية +الأثريون +الأثريين +الأثقال +الأثمان +الأثناء +الأثواب +الأثير +الأثيرة +الأثيني +الأجانب +الأجبان +الأجداد +الأجدر +الأجدى +الأجراس +الأجرام +الأجرة +الأجزاء +الأجساد +الأجسام +الأجش +الأجفان +الأجل +الأجلين +الأجمل +الأجناس +الأجنبى +الأجنبي +الأجنبية +الأجنة +الأجنحة +الأجندة +الأجهزة +الأجواء +الأجوبة +الأجور +الأجيال +الأجير +الأحادي +الأحاديث +الأحاسيس +الأحافير +الأحايين +الأحباس +الأحبة +الأحجار +الأحجام +الأحجبة +الأحد +الأحداث +الأحداق +الأحدث +الأحذية +الأحرار +الأحراش +الأحرف +الأحرى +الأحزاب +الأحزان +الأحساء +الأحشاء +الأحطاب +الأحـجام +الأحـمر +الأحفاد +الأحفورة +الأحفوري +الأحفورية +الأحق +الأحقاد +الأحكام +الأحلام +الأحماض +الأحمد +الأحمر +الأحناف +الأحواش +الأحواض +الأحوال +الأحياء +الأحيائي +الأحيان +الأحيدوس +الأخ +الأخاذ +الأخبار +الأخت +الأخدود +الأخذ +الأخر +الأخرس +الأخروية +الأخرى +الأخري +الأخريات +الأخشاب +الأخص +الأخضر +الأخطاء +الأخطار +الأخطبوطات +الأخلاف +الأخلاق +الأخلاقي +الأخلاقية +الأخماج +الأخوات +الأخوة +الأخوي +الأخوين +الأخيار +الأخير +الأخيرة +الأخيرين +الأخّاذ +الأداء +الأداب +الأداة +الأدب +الأدباء +الأدبار +الأدبي +الأدبية +الأدبين +الأدراج +الأدرم +الأدرياتيكي +الأدعي +الأدعياء +الأدعية +الأدلة +الأدمة +الأدن +الأدنى +الأدوات +الأدوار +الأدونيسية +الأدوية +الأديان +الأديب +الأديبات +الأديبان +الأديبة +الأديرة +الأذان +الأذكار +الأذكى +الأذكياء +الأذن +الأذنين +الأذهان +الأذواق +الأذى +الأذيات +الأذية +الأرائك +الأرابيسك +الأراجيح +الأراضى +الأراضي +الأرانب +الأرباح +الأربع +الأربعا +الأربعاء +الأربعة +الأربعمائة +الأربعون +الأربعين +الأربعينات +الأربعينيات +الأربلي +الأرثوذكسية +الأرجاء +الأرجح +الأرجل +الأرجنتين +الأرجنتينية +الأرجوان +الأرجي +الأرجية +الأرحام +الأرخبيل +الأرخص +الأردن +الأردني +الأردنيين +الأردية +الأرز +الأرزاق +الأرستقراطي +الأرستقراطية +الأرستقراطيين +الأرشيف +الأرصاد +الأرصدة +الأرصفة +الأرض +الأرضة +الأرضى +الأرضي +الأرضيات +الأرضية +الأرضين +الأرفف +الأرق +الأرقام +الأرقط +الأرقم +الأركان +الأرمن +الأرمني +الأرمنية +الأرميني +الأرمينية +الأرنب +الأرنونا +الأرواح +الأروعا +الأروقة +الأرياف +الأريبُ +الأريحية +الأريكة +الأزبكية +الأزد +الأزدي +الأزرار +الأزرق +الأزرقين +الأزقة +الأزل +الأزلية +الأزمات +الأزمان +الأزمة +الأزمنة +الأزهار +الأزهر +الأزهري +الأزهرية +الأزهريين +الأزواج +الأزياء +الأزيز +الأسئلة +الأسابيع +الأساتذة +الأساس +الأساسي +الأساسيات +الأساسيان +الأساسية +الأساسيون +الأساسيين +الأساسيّة +الأساطير +الأساطيل +الأساقفة +الأساليب +الأسانيد +الأسباب +الأسباط +الأسباني +الأسبرجيليس +الأسبرين +الأسبق +الأسبقية +الأسبوع +الأسبوعي +الأسبوعية +الأسبوعين +الأستاذ +الأستاذان +الأستاذة +الأستاذية +الأستار +الأستخدام +الأسترالي +الأسترالية +الأستراليين +الأستوديو +الأسد +الأسدي +الأسر +الأسرار +الأسرارِ +الأسرة +الأسرتين +الأسرع +الأسرى +الأسري +الأسرية +الأسس +الأسطح +الأسطر +الأسطرِ +الأسطوات +الأسطوانات +الأسطوانة +الأسطواني +الأسطوانية +الأسطورة +الأسطورية +الأسطول +الأسطى +الأسعار +الأسعد +الأسف +الأسفار +الأسفل +الأسفلت +الأسفلتية +الأسفوني +الأسقف +الأسكتلندي +الأسكوريال +الأسلاف +الأسلاك +الأسلحة +الأسلم +الأسلوب +الأسلوبي +الأسلوبية +الأسماء +الأسماع +الأسماك +الأسمدة +الأسمر +الأسمك +الأسمنت +الأسمنتي +الأسمنتية +الأسمى +الأسنان +الأسهم +الأسوأ +الأسوار +الأسواق +الأسود +الأسيتون +الأسيرة +الأسيسكو +الأسينيين +الأسيوي +الأشاعرة +الأشاوش +الأشباح +الأشبه +الأشجار +الأشخاص +الأشد +الأشدّاء +الأشرار +الأشراف +الأشرف +الأشرفية +الأشرم +الأشعار +الأشعة +الأشعث +الأشقاء +الأشقياء +الأشكال +الأشهاد +الأشهر +الأشواق +الأشواك +الأشوريون +الأشياء +الأشيب +الأصابع +الأصالة +الأصبحي +الأصبع +الأصح +الأصحاء +الأصحاب +الأصدقاء +الأصص +الأصعب +الأصعدة +الأصفاد +الأصفار +الأصفر +الأصقاع +الأصل +الأصلي +الأصلية +الأصليون +الأصليين +الأصليّة +الأصمعي +الأصمعيات +الأصناف +الأصنام +الأصوات +الأصوب +الأصول +الأصولي +الأصولية +الأصيل +الأصيلة +الأضاحي +الأضحى +الأضحية +الأضخم +الأضداد +الأضرار +الأضلاع +الأضواء +الأطباء +الأطباءَ +الأطباق +الأطر +الأطراف +الأطرش +الأطروحة +الأطعمة +الأطفال +الأطلال +الأطلس +الأطلسي +الأطلسية +الأطلنطي +الأطماع +الأطنان +الأطواء +الأطوار +الأطوال +الأطول +الأطومات +الأطياف +الأظافر +الأعاجيب +الأعاصير +الأعالي +الأعباء +الأعجمي +الأعداء +الأعداد +الأعذار +الأعرابي +الأعراس +الأعراض +الأعراف +الأعراق +الأعرج +الأعرجي +الأعسال +الأعشاب +الأعشاش +الأعشى +الأعصاب +الأعضاء +الأعطيات +الأعظم +الأعلاف +الأعلام +الأعلى +الأعم +الأعمار +الأعماق +الأعمال +الأعمدة +الأعمق +الأعمى +الأعمّ +الأعناب +الأعناق +الأعواد +الأعوام +الأعور +الأعياء +الأعياد +الأعيان +الأعين +الأفئدة +الأفارقة +الأفاعي +الأفذاذ +الأفراح +الأفراخ +الأفراد +الأفران +الأفرقة +الأفرو +الأفريقي +الأفريقية +الأفضل +الأفعال +الأفق +الأفقا +الأفقي +الأفكار +الأفلاج +الأفلاك +الأفلام +الأفنان +الأفواج +الأفواه +الأفول +الأفيال +الأفيون +الأفّاقين +الأقارب +الأقاليم +الأقاويل +الأقحوانة +الأقدار +الأقداس +الأقدام +الأقدر +الأقدمون +الأقدميات +الأقراص +الأقران +الأقرب +الأقرع +الأقسام +الأقصاب +الأقصر +الأقصورة +الأقصى +الأقطاب +الأقطار +الأقفاص +الأقفال +الأقل +الأقلام +الأقليات +الأقلية +الأقلّ +الأقمار +الأقمر +الأقمشة +الأقنعة +الأقوال +الأقوى +الأقوياء +الأكادية +الأكاديمي +الأكاديميات +الأكاديمية +الأكاديين +الأكاذيب +الأكارم +الأكبر +الأكبرُ +الأكبـر +الأكتاف +الأكثر +الأكثرون +الأكثرية +الأكر +الأكريلامايد +الأكزيما +الأكسجة +الأكسجين +الأكسدة +الأكسية +الأكسير +الأكفاء +الأكل +الأكلات +الأكلة +الأكمل +الأكواب +الأكواخ +الأكواريوم +الأكوان +الأكوع +الأكياس +الأكيدة +الألب +الألباب +الألباستر +الألبان +الألباني +الألبسة +الألبومات +الألبومين +الألحان +الألسنة +الألسنية +الألعاب +الألف +الألفاظ +الألفة +الألفي +الألفية +الألفين +الألقاب +الألم +الألماس +الألمان +الألماني +الألمانية +الألمانيتين +الألمنيوم +الألمي +الألمية +الألواح +الألوان +الألوف +الألومنيوم +الألوية +الألياف +الأليف +الأليفة +الأليق +الأليم +الأم +الأماجد +الأماسي +الأماكن +الأمام +الأمامي +الأمامية +الأمان +الأمانات +الأمانة +الأماني +الأمة +الأمتار +الأمتعة +الأمثال +الأمثل +الأمثلة +الأمجاد +الأمد +الأمر +الأمراء +الأمراض +الأمرالذي +الأمركة +الأمريكان +الأمريكتين +الأمريكى +الأمريكي +الأمريكية +الأمريكيتين +الأمريكيون +الأمريكيين +الأمرين +الأمرُ +الأمرّين +الأمس +الأمسيات +الأمسية +الأمشاط +الأمصار +الأمطار +الأمعاء +الأمكنة +الأمل +الأملاح +الأملس +الأملَ +الأمم +الأممي +الأممية +الأمن +الأمناء +الأمنى +الأمني +الأمنيات +الأمنية +الأمهات +الأموات +الأمواج +الأموال +الأمور +الأمومة +الأمونيا +الأمونياك +الأموي +الأموية +الأمويون +الأمويين +الأميال +الأميانت +الأمية +الأمير +الأميرات +الأميرة +الأميركي +الأميركية +الأميري +الأميرية +الأميل +الأمين +الأمينات +الأمينة +الأمينية +الأميون +الأميين +الأميّة +الأمّارة +الأمّة +الأمّي +الأن +الأنا +الأنابيب +الأناجيل +الأناشيد +الأناضول +الأناضولي +الأناقة +الأنامل +الأناناس +الأناني +الأنانية +الأنباء +الأنبار +الأنبوب +الأنبوبي +الأنبوبية +الأنبيا +الأنبياء +الأنتاركتيكا +الأنترنت +الأنثراكس +الأنثوي +الأنثوية +الأنثى +الأنجلو +الأنجيوتنسين +الأنحاء +الأنداد +الأندر +الأندلس +الأندلسي +الأندلسية +الأندلسيين +الأندية +الأنزيم +الأنزيمات +الأنساب +الأنساق +الأنسام +الأنسب +الأنسجة +الأنسنة +الأنسولين +الأنسي +الأنشطة +الأنشوجة +الأنصار +الأنصاري +الأنصارية +الأنظار +الأنظمة +الأنف +الأنفا +الأنفاس +الأنفاق +الأنفس +الأنفلونزا +الأنفي +الأنفية +الأنقى +الأنماط +الأنهار +الأنواء +الأنواع +الأنوال +الأنوثة +الأنوف +الأنوفيليس +الأنياب +الأنيق +الأنيقة +الأنين +الأنيوليتي +الأنْهَارُ +الأهالى +الأهالي +الأهبل +الأهداف +الأهرام +الأهل +الأهلى +الأهلي +الأهلية +الأهم +الأهمية +الأهمّ +الأهواء +الأهوار +الأوائل +الأوابد +الأوامر +الأوان +الأواني +الأوبئة +الأوبرا +الأوبرتات +الأوبك +الأوتوستراد +الأوثان +الأوجاع +الأوجه +الأوحال +الأوحد +الأود +الأوراق +الأورام +الأوربــــية +الأوربي +الأوربيات +الأوربية +الأوربيون +الأوربيين +الأورج +الأوردية +الأوركسترا +الأوركسترالي +الأوركسترالية +الأوروبي +الأوروبية +الأوروبيون +الأوروبيين +الأوزان +الأوزبكية +الأوزون +الأوس +الأوساخ +الأوساط +الأوسط +الأوسع +الأوسكار +الأوسمة +الأوصاف +الأوصياء +الأوضاع +الأوطان +الأوعية +الأوفاتا +الأوفر +الأوفشور +الأوقات +الأوقاف +الأوكتيل +الأوكتينول +الأوكراني +الأوكرانية +الأوكرانيين +الأوكسجين +الأول +الأولاد +الأولـى +الأولمبية +الأولومبي +الأولومبية +الأولويات +الأولوية +الأولى +الأولي +الأولياء +الأوليات +الأولية +الأولين +الأولَ +الأوهام +الأوّل +الأوّلي +الأيادي +الأياس +الأيام +الأيامُ +الأيتام +الأيدروجين +الأيدروجينية +الأيدى +الأيدي +الأيديولوجي +الأيديولوجيا +الأيديولوجيات +الأيديولوجيان +الأيديولوجية +الأيسر +الأيقونات +الأيل +الأيمن +الأيوبي +الأيوبية +الأيوبيين +الأيّام +الإ +الإئتلافية +الإباء +الإباحية +الإباضة +الإبانة +الإبتعاد +الإبحار +الإبداع +الإبداعات +الإبداعي +الإبداعية +الإبر +الإبراهيم +الإبراهيمي +الإبرة +الإبصار +الإبط +الإبعاد +الإبقاء +الإبل +الإبنة +الإبهار +الإبهام +الإتجاه +الإتجاهات +الإتصال +الإتفاقيتين +الإتهام +الإثارات +الإثارة +الإثبات +الإثنان +الإثني +الإثنية +الإثنين +الإثيلي +الإثيلين +الإثيوبية +الإجابات +الإجابة +الإجازات +الإجازة +الإجبار +الإجباري +الإجبارية +الإجتماع +الإجتماعات +الإجتماعية +الإجحاف +الإجراء +الإجراءات +الإجرائي +الإجرام +الإجماع +الإجمالي +الإجمالية +الإجماية +الإجهاد +الإجهاض +الإحاطة +الإحالة +الإحباط +الإحتراق +الإحتياط +الإحتياطات +الإحداثيات +الإحدى +الإحساس +الإحسان +الإحصاء +الإحصاءات +الإحصائيات +الإحصائية +الإحـساس +الإحـصاءات +الإحياء +الإحيائي +الإخاء +الإخبارية +الإختبار +الإختبارات +الإختلاجات +الإختلاطات +الإخراج +الإخصائي +الإخصاب +الإخفاء +الإخفاق +الإخلاء +الإخلاص +الإخلال +الإخوان +الإخوة +الإدارات +الإدارة +الإدارى +الإداري +الإدارية +الإدانة +الإدخار +الإدراك +الإدريسي +الإدلاء +الإدماج +الإدمان +الإدهاش +الإدّعاء +الإذاعات +الإذاعة +الإذاعتين +الإذاعي +الإذاعية +الإذلال +الإذن +الإذهال +الإرادة +الإرباك +الإربي +الإربية +الإرتقاء +الإرث +الإرسال +الإرسالية +الإرشاد +الإرشادات +الإرشادي +الإرشادية +الإرضاع +الإرقاء +الإرهاب +الإرهابي +الإرهابية +الإرهابيين +الإرهاق +الإزالة +الإزدحام +الإزعاج +الإزعاجات +الإساءة +الإسبان +الإسباني +الإسبانية +الإسبانيين +الإستثنائي +الإستراتيجيات +الإستراتيجية +الإستعانة +الإستعداد +الإستفادة +الإستقرار +الإستهلاك +الإستيراتيجية +الإسراء +الإسرائيلي +الإسرائيليات +الإسرائيلية +الإسرائيليون +الإسرائيليين +الإسراع +الإسراف +الإسطرلاب +الإسطوانية +الإسعافات +الإسعافية +الإسفلت +الإسفنج +الإسفنجي +الإسكان +الإسكانية +الإسكندر +الإسكندرون +الإسكندرية +الإسكندريون +الإسكندريين +الإسلام +الإسلامبولى +الإسلاموفوبيا +الإسلامى +الإسلامي +الإسلامية +الإسلاميون +الإسلاميين +الإسماعيلية +الإسمنت +الإسناد +الإسهاب +الإسهال +الإسهالات +الإسهام +الإسهامات +الإشادة +الإشارات +الإشاراتلكن +الإشارة +الإشاعات +الإشباع +الإشتراك +الإشراف +الإشراقات +الإشعاع +الإشعاعات +الإشعاعي +الإشعاعية +الإشكال +الإشكالات +الإشكاليات +الإشكالية +الإشهار +الإصابات +الإصابة +الإصبع +الإصدار +الإصدارات +الإصرار +الإصطناعي +الإصلاح +الإصلاحات +الإصلاحي +الإصلاحية +الإصلاحيون +الإصلاحيين +الإضاء +الإضاءة +الإضافات +الإضافة +الإضافي +الإضافية +الإضحاك +الإضرار +الإضطراب +الإضطرابات +الإطاحة +الإطار +الإطارات +الإطراء +الإطفاء +الإطلاع +الإطلاق +الإطلالة +الإعادة +الإعاقات +الإعاقة +الإعتبار +الإعتقاد +الإعتماد +الإعجاب +الإعجاز +الإعجازي +الإعداد +الإعدادي +الإعدادية +الإعدام +الإعزاز +الإعشاب +الإعصار +الإعلام +الإعلامي +الإعلامية +الإعلاميون +الإعلاميين +الإعلان +الإعلانات +الإعلانية +الإعمار +الإعياء +الإفادة +الإفتاء +الإفتتاح +الإفراج +الإفراز +الإفرازات +الإفراط +الإفرنج +الإفرنجي +الإفريقي +الإفريقيات +الإفريقية +الإفريقيون +الإفريقيين +الإفريي +الإفساد +الإفصاح +الإفطار +الإفلات +الإفلاس +الإقامة +الإقبال +الإقتصادي +الإقتصادية +الإقراء +الإقرار +الإقصاء +الإقصورة +الإقطاع +الإقطاعي +الإقطاعية +الإقطاعيين +الإقفار +الإقفاري +الإقلاع +الإقلال +الإقليدية +الإقليم +الإقليمي +الإقليمية +الإقناع +الإقياء +الإكتأب +الإكتشافات +الإكثار +الإكزيما +الإكليلية +الإكلينيكي +الإكوادور +الإلبية +الإلتزام +الإلتهاب +الإلتهابات +الإلحاح +الإلحاد +الإلحاديين +الإلزام +الإلزامي +الإلزامية +الإلعاب +الإلــتهاب +الإلقاح +الإلكترون +الإلكترونى +الإلكتروني +الإلكترونيات +الإلكترونية +الإلماح +الإلمام +الإله +الإلهام +الإلهة +الإلهي +الإلهية +الإلهيين +الإلياذة +الإلية +الإماء +الإمارات +الإماراتي +الإماراتيون +الإماراتيين +الإمارة +الإمارتين +الإمام +الإمامين +الإمبراطور +الإمبراطورية +الإمبريالي +الإمبريالية +الإمراضية +الإمساك +الإمعان +الإمكان +الإمكانات +الإمكانيات +الإمكانية +الإناء +الإنابة +الإناث +الإنارة +الإنباتية +الإنبوب +الإنتاج +الإنتاجية +الإنتانات +الإنتباه +الإنتربول +الإنتركونتيننتال +الإنترناشونال +الإنترناشيونال +الإنترنت +الإنتشار +الإنتفاخ +الإنتفاضة +الإنتقال +الإنثراكس +الإنثناء +الإنجاب +الإنجابية +الإنجاز +الإنجازات +الإنجليز +الإنجليزي +الإنجليزيات +الإنجليزية +الإنجيل +الإنجيلية +الإنجيليكانية +الإنحشار +الإندبندنت +الإندونيسية +الإنديز +الإنذار +الإنذارات +الإنزيم +الإنزيمات +الإنزيمية +الإنسان +الإنسانة +الإنسانى +الإنساني +الإنسانيات +الإنسانية +الإنسانيين +الإنسانَ +الإنسانِ +الإنسداد +الإنشاء +الإنشاءات +الإنشائية +الإنشاد +الإنصاف +الإنعاش +الإنـسان +الإنفاق +الإنفتاق +الإنفلونزا +الإنقاذ +الإنكار +الإنكشارية +الإنكشاريين +الإنماء +الإنمائية +الإنهاك +الإهانة +الإهتمام +الإهداء +الإهمال +الإوز +الإيابا +الإيبولا +الإيثان +الإيثايل +الإيثر +الإيثيلي +الإيجاب +الإيجابى +الإيجابي +الإيجابيات +الإيجابية +الإيحاء +الإيحائية +الإيداع +الإيدز +الإيديولوجيا +الإيذاء +الإيرادات +الإيرادي +الإيراني +الإيرانية +الإيرباص +الإيرلندي +الإيض +الإيطالى +الإيطالي +الإيطالية +الإيطاليون +الإيطاليين +الإيــدز +الإيقاع +الإيقاعات +الإيقاعي +الإيكولوجية +الإيماء +الإيمان +الإيماني +الإيمانية +الا +الائتلافية +الائتمان +الائتماني +الائتمانية +الابتدائي +الابتدائية +الابتداع +الابتذال +الابتسام +الابتسامة +الابتعاث +الابتعاد +الابتكار +الابتكارات +الابتكارية +الابتلاء +الابتهال +الابتهالات +الابداعية +الابن +الات +الاتباع +الاتجار +الاتجاه +الاتجاهات +الاتجاهين +الاتحاد +الاتحادات +الاتحادية +الاتروبين +الاتزان +الاتساع +الاتساق +الاتصال +الاتصالات +الاتصالية +الاتفاق +الاتفاقية +الاتكاء +الاتهام +الاتهامات +الاتهاماتِ +الاتيل +الاتّحاد +الاتّزان +الاتّصال +الاثنا +الاثنان +الاثنتان +الاثنتين +الاثنى +الاثنين +الاثنينية +الاجتماع +الاجتماعات +الاجتماعى +الاجتماعي +الاجتماعيات +الاجتماعية +الاجتهاد +الاجتهادات +الاجتهادين +الاجتياح +الاجراءات +الاجرة +الاجزاء +الاجهزة +الاحتباس +الاحتجاب +الاحتجاج +الاحتراف +الاحترافى +الاحترام +الاحتشاء +الاحتشائية +الاحتضار +الاحتفاء +الاحتفاظ +الاحتفال +الاحتفالات +الاحتفالي +الاحتفالية +الاحتقار +الاحتكاك +الاحتكاكات +الاحتكام +الاحتلال +الاحتلالي +الاحتلاليّ +الاحتمال +الاحتمالات +الاحتواء +الاحتياج +الاحتياجات +الاحتياط +الاحتياطات +الاحتياطي +الاحتياطيات +الاحتياطية +الاحداث +الاحزاب +الاحساء +الاحصائيات +الاحمرار +الاحوال +الاحياء +الاختبار +الاختبارات +الاختراع +الاختراق +الاختراقات +الاختزالية +الاختصاص +الاختصاصات +الاختصاصي +الاختفاء +الاختلاء +الاختلاج +الاختلاجات +الاختلاجية +الاختلاط +الاختلاف +الاختلافات +الاختلالات +الاختناق +الاختيار +الاختيارات +الاختيارية +الاخر +الاخرى +الاخرين +الاخضرار +الاخيرة +الادعاء +الادعاءات +الادوية +الاذاعي +الاراده +الاراضي +الاربع +الاربعاء +الاربعة +الارتباط +الارتباك +الارتجاجات +الارتجال +الارتجالي +الارتداد +الارتطام +الارتفاع +الارتقاء +الارتكاز +الارتواء +الارتوازية +الارتياح +الارتياد +الارض +الازدحام +الازدراء +الازدهار +الازدواج +الازدواجية +الازدياد +الازرق +الازعاج +الازهار +الاسئلة +الاساسية +الاسباب +الاسبوع +الاستئثنار +الاستئجار +الاستئصال +الاستاذ +الاستبانة +الاستبداد +الاستبيان +الاستبيانات +الاستثارة +الاستثمار +الاستثمارات +الاستثماري +الاستثمارية +الاستثناء +الاستثناءات +الاستثنائي +الاستثنائية +الاستجابات +الاستجابة +الاستجمام +الاستجمامية +الاستجواب +الاستحضار +الاستحقاق +الاستحقاقات +الاستحقاقين +الاستحكامات +الاستحمام +الاستخبارات +الاستخدام +الاستخدامات +الاستخلاف +الاستدارة +الاستدامة +الاستدراك +الاستدعاء +الاستراتيجي +الاستراتيجيات +الاستراتيجية +الاستراحة +الاسترالي +الاسترالية +الاستراليون +الاسترايجيات +الاسترخاء +الاسترليني +الاستروجين +الاستروجينات +الاستزادة +الاستزراع +الاستسلام +الاستسهال +الاستشارات +الاستشارة +الاستشاري +الاستشارية +الاستشراف +الاستشراق +الاستشراقي +الاستشراقية +الاستشعار +الاستشفاء +الاستشهاد +الاستشهادية +الاستصباح +الاستضافة +الاستطالات +الاستطباب +الاستطلاع +الاستطلاعية +الاستظهار +الاستعارات +الاستعاضة +الاستعانة +الاستعجال +الاستعداد +الاستعدادات +الاستعراب +الاستعراض +الاستعراضات +الاستعلاء +الاستعلائية +الاستعلامات +الاستعمار +الاستعماري +الاستعمارية +الاستعمال +الاستفادة +الاستفتاء +الاستفتاءات +الاستفزاز +الاستفسار +الاستفهام +الاستقالة +الاستقامة +الاستقبال +الاستقرار +الاستقصائية +الاستقطاب +الاستقلاب +الاستقلابية +الاستقلال +الاستقلالية +الاستكشاف +الاستكشافي +الاستكشافية +الاستلاب +الاستلام +الاستلقاء +الاستمارات +الاستماع +الاستمتاع +الاستمرار +الاستمرارية +الاستنباطية +الاستنتاج +الاستنتاجات +الاستنساخ +الاستنفار +الاستهداف +الاستهزاء +الاستهلاك +الاستهلاكي +الاستهلاكية +الاستواء +الاستوائي +الاستوائية +الاستيراد +الاستيطان +الاستيطاني +الاستيطانية +الاستيعاب +الاستيعابية +الاستيقاظ +الاستيلاء +الاسراع +الاسشتراقية +الاسطبل +الاسطر +الاسكندرونة +الاسكندرية +الاسكندنافيين +الاسلامية +الاسلمة +الاسم +الاسماعيلية +الاسمنت +الاسمية +الاسمين +الاسود +الاش +الاشارة +الاشتباك +الاشتباه +الاشتراط +الاشتراك +الاشتراكي +الاشتراكية +الاشتراكيين +الاشتعال +الاشتياق +الاشخاص +الاشراف +الاشياء +الاصابة +الاصدقاء +الاصرار +الاصطدام +الاصطفاف +الاصطلاح +الاصطلاحية +الاصطناعي +الاصطناعية +الاصطياف +الاصلية +الاضاءة +الاضحاك +الاضحكاك +الاضرابات +الاضطراب +الاضطرابات +الاضطراري +الاضطلاع +الاضطهاد +الاضمحلال +الاطاحة +الاطار +الاطراء +الاطفال +الاطلاع +الاطلنطي +الاطمئنان +الاطماع +الاعادة +الاعتبار +الاعتبارات +الاعتباري +الاعتداء +الاعتداءات +الاعتداد +الاعتدال +الاعتذار +الاعتراض +الاعتراضات +الاعتراف +الاعترافات +الاعتزاز +الاعتزال +الاعتصام +الاعتقاد +الاعتقال +الاعتكاف +الاعتلال +الاعتماد +الاعتمادات +الاعتناء +الاعتياد +الاعتيادي +الاعتيادية +الاعلام +الاعلانات +الاعوجاج +الاف +الافتاحية +الافتتاح +الافتتاحي +الافتتاحيات +الافتراءات +الافتراس +الافتراض +الافتراضات +الافتراضي +الافتراضية +الافتقار +الافتنان +الافراز +الافرازات +الافرنجي +الافكار +الاقتباس +الاقتباسات +الاقتتال +الاقتحام +الاقتحامي +الاقتداء +الاقتراب +الاقتراح +الاقتراحات +الاقتراض +الاقتصاد +الاقتصادات +الاقتصادى +الاقتصادي +الاقتصادية +الاقتصاديون +الاقتصاديين +الاقتصاية +الاقتفائيين +الاقتلاعين +الاقتناء +الاقتناع +الاقسام +الاقصورة +الاقصى +الاقطاعية +الاقل +الاقلية +الاقياء +الاكبر +الاكتئاب +الاكتتاب +الاكتشاف +الاكتشافات +الاكتفاء +الاكتمال +الاكزيمات +الاكزيمرليزر +الالاف +الالتباسات +الالتجاء +الالتحاق +الالتحام +الالتزام +الالتزامات +الالتصاق +الالتفات +الالتقاء +الالتهاب +الالتهابات +الالتهابي +الالف +الالكترونى +الالكتروني +الالم +الالوف +الالي +الامام +الامامي +الامان +الامبراطور +الامتحان +الامتحانات +الامتداد +الامتصاص +الامتعاض +الامتلاء +الامتياز +الامتيازات +الامر +الامريكية +الامكانات +الامم +الامنى +الامنية +الاميال +الان +الانبتات +الانبساط +الانبساطي +الانبعاث +الانبعاثات +الانبهار +الانتاج +الانتان +الانتانات +الانتاني +الانتباه +الانتحار +الانتخاب +الانتخابات +الانتخابي +الانتخابية +الانتداب +الانتدابية +الانترنت +الانتساب +الانتشار +الانتصار +الانتصارات +الانتظار +الانتظام +الانتعاش +الانتفاضات +الانتفاضة +الانتفاع +الانتقاء +الانتقائي +الانتقائية +الانتقادي +الانتقاص +الانتقال +الانتقالات +الانتقالة +الانتقالية +الانتماء +الانتماءات +الانتهاء +الانتهائية +الانثناء +الانجراف +الانجليز +الانجليزى +الانجليزي +الانجليزية +الانحباس +الانحدار +الانحراف +الانحرافات +الانحطاط +الانحلال +الانحناء +الانحياز +الانحيازات +الانخراط +الانخفاض +الاندفاع +الاندهاش +الانزعاج +الانسان +الانسانية +الانسحاب +الانسحاق +الانسيابي +الانشطار +الانشقاقات +الانصراف +الانصهار +الانصياع +الانضباط +الانضباطية +الانضمام +الانضواء +الانطباع +الانطباعات +الانطباعيين +الانطلاق +الانطلاقة +الانطواء +الانطوائي +الانعزال +الانعقال +الانعكاس +الانفتاح +الانفجار +الانفجارية +الانفراد +الانفرادي +الانفصال +الانفصاليين +الانفصام +الانفعال +الانفعالات +الانفعالي +الانفعالية +الانفلات +الانقباضي +الانقراض +الانقسام +الانقسامات +الانقضاض +الانقطاع +الانقلاب +الانقلابات +الانكسار +الانكساري +الانكسارية +الانكشارية +الانكشاف +الانكفاء +الانهيار +الانيلين +الاهانة +الاهتداء +الاهتزاز +الاهتزازات +الاهتزازية +الاهتمام +الاهتمامات +الاهم +الاهمامات +الاوركسترا +الاوقاف +الاولى +الاياتا +الايام +الايتافليين +الايجابي +الايرانية +الايزوينازيد +الايسلندية +الايصال +الايفننج +الايقاع +الايقاعات +الايمن +الاّ +البؤجة +البؤر +البؤرة +البؤرية +البؤس +البؤساء +البئر +البا +البائدة +البائس +البائسة +البائسين +البائع +الباب +البابا +البابايا +البابطين +البابلي +البابليون +البابليين +البابوات +البابونج +البابوي +البابوية +البابويين +البابي +البابين +البابَ +الباتر +الباحة +الباحث +الباحثات +الباحثان +الباحثة +الباحثون +الباحثين +الباحـة +الباخرة +البادئة +البادرات +البادية +الباذخة +البار +البارات +الباربكيو +البارحة +البارد +الباردة +الباردتين +البارز +البارزة +البارزين +البارع +البارعون +البارود +البارودي +البارون +الباري +الباريسي +الباريسية +الباز +البازار +البازلت +البازيليك +البازين +الباستيل +الباسق +الباسقة +الباسلة +الباسمة +الباشا +الباشة +الباشتو +الباص +الباصات +الباطشة +الباطل +الباطلة +الباطن +الباطنة +الباطنية +الباطونية +الباع +الباعة +الباعث +البافلو +الباقلاني +الباقوري +الباقى +الباقي +الباقية +الباقين +الباكر +الباكرة +الباكستان +الباكستانى +الباكستاني +الباكستانية +الباكستانيون +الباكستانيين +الباكية +البال +البالون +البالية +الباليستية +الباليه +البامبو +البان +الباندا +الباهت +الباهتة +الباهر +الباهرة +الباهظة +الباهلي +البايا +البايلو +البايلوسيد +الباين +الببليوثيرابيا +البتانوني +البتة +البتراء +البتروكيماويات +البتروكيماوية +البترول +البترولية +البترون +البتّة +البث +البثور +البجلي +البحار +البحارة +البحت +البحتة +البحتية +البحث +البحثي +البحثية +البحر +البحرة +البحرى +البحري +البحرية +البحرين +البحريني +البحرِ +البحـث +البحـر +البحلقة +البحوث +البحوه +البحيرات +البحيرة +البحّار +البخار +البخاري +البخارية +البخر +البخل +البخور +البخيل +البدء +البدئي +البدئية +البدائل +البدائي +البدائية +البدائيين +البدانة +البداوة +البدايات +البداية +البدايــة +البدر +البدع +البدلات +البدلة +البدن +البدني +البدنية +البدهي +البدهية +البدو +البدوي +البدوية +البديع +البديعة +البديل +البديلة +البدين +البدينة +البدينين +البديهية +البذار +البذل +البذلة +البذور +البر +البراءة +البرابرة +البراثن +البرادو +البراري +البراز +البرازيل +البرازيلي +البرازيلية +البرازيليين +البرازين +البراعم +البراق +البرامج +البرامجي +البراهيم +البراهين +البربر +البربري +البربرية +البرتا +البرتقال +البرج +البرجواتة +البرجوازيون +البرجين +البرد +البردنلس +البردي +البرديات +البرز +البرزخ +البرسيم +البرص +البرفسور +البرق +البرقعاوي +البرك +البركان +البركانية +البركة +البرلما +البرلمان +البرلمانية +البرمجة +البرمجيات +البرميل +البرناسي +البرناسية +البرنامج +البرنامجين +البرهان +البرهنة +البرواقية +البروبلس +البروبليس +البروة +البروتستانت +البروتونات +البروتيز +البروتين +البروتينات +البروتيني +البرودة +البروز +البروستاتة +البروفات +البروفة +البروفسور +البروفيسر +البروفيسور +البروفيسورة +البروفيه +البرونزي +البرونزية +البرى +البري +البريء +البريئة +البرية +البريد +البريدي +البريدية +البريشي +البريطانى +البريطاني +البريطانية +البريطانيون +البريطانيين +البريك +البريلوي +البريلوية +البرين +البريّة +البرّ +البزار +البزر +البزورية +البساتين +البساط +البساطة +البساطي +البسام +البستان +البستاني +البستنة +البسط +البسطا +البسطاء +البسطات +البسمة +البسيط +البسيطة +البشارة +البشاشة +البشتون +البشتونى +البشر +البشرة +البشرى +البشري +البشرية +البشريون +البشريين +البشريّة +البشع +البشعة +البشير +البصارة +البصر +البصرة +البصري +البصرية +البصل +البصلة +البصمات +البصيرة +البصيرية +البضائع +البضاعة +البط +البطء +البطئ +البطاريات +البطاطا +البطاطس +البطاقات +البطاقة +البطالة +البطالمة +البطانة +البطريرك +البطريق +البطش +البطل +البطلة +البطلمي +البطن +البطنية +البطنيتين +البطولات +البطولة +البطيء +البطيئة +البطيخ +البطين +البعث +البعثات +البعثة +البعثية +البعد +البعض +البعل +البعوث +البعوض +البعوضة +البعيد +البعيدة +البعيدتين +البعير +البـريئة +البقاء +البقايا +البقدونس +البقر +البقرة +البقطرياني +البقع +البقعة +البقعتين +البقعي +البقعية +البقية +البكاء +البكار +البكارة +البكالوريا +البكالوريوس +البكباشي +البكتري +البكتريا +البكترية +البكتيري +البكتيريا +البكتيرية +البكر +البكرية +البل +البلا +البلاء +البلابلْ +البلاد +البلادة +البلاذري +البلازا +البلازما +البلازموديوم +البلازمي +البلاستيك +البلاستيكى +البلاستيكي +البلاستيكية +البلاط +البلاطات +البلاعة +البلايا +البلايين +البلبل +البلجيكية +البلح +البلد +البلدالذى +البلدان +البلدة +البلدي +البلديات +البلدية +البلدين +البلطيق +البلع +البلعوم +البلعومي +البلقاء +البلقان +البلل +البلهارسيا +البلوز +البلياتشو +البلياردو +البلية +البليدة +البليون +البنا +البناء +البناءون +البنائين +البنات +البنادق +البناني +البنايات +البنت +البنتوكسيفيللين +البنجاب +البنجر +البنجلاديش +البنجلاديشية +البند +البندازول +البندر +البندق +البندقية +البندى +البندير +البنزايل +البنزين +البنسلين +البنسيون +البنطال +البنفسجية +البنك +البنكرياس +البنكي +البنكية +البنود +البنوك +البنوّة +البنى +البني +البنيات +البنيان +البنية +البنين +البنيوي +البنيوية +البنّاءة +البهائم +البهار +البهارات +البهجة +البهلوان +البهي +البهية +البهيم +البواب +البوابات +البوابة +البوادر +البوارُ +البواكي +البوالب +البوالص +البوبلين +البوتاسيوم +البوتوكس +البوح +البوحسن +البوذية +البور +البورجوازية +البورصات +البورنو +البوزجاني +البوسنة +البوصة +البوفيرا +البوفيه +البوق +البوقلمون +البوكر +البوكيرك +البول +البولب +البولشوي +البولندي +البولنديون +البولى +البولي +البولية +البوليتكنيك +البوليس +البوليستر +البوليسي +البوليسية +البوليسيةِ +البوليوليتي +البومة +البون +البوهيميون +البويضات +البوينج +البويهي +البيئات +البيئة +البيئي +البيئية +البيئيون +البيئيين +البيات +البيارق +البياض +البياضات +البيان +البيانات +البيانو +البياني +البيانية +البيبرازين +البيت +البيتا +البيتز +البيتزا +البيتية +البيتين +البيج +البير +البيرانتيل +البيرة +البيرتا +البيرفينيوم +البيروتية +البيروقراطية +البيروم +البيريت +البيزنطي +البيزنطية +البيزنطيون +البيزنطيين +البيزو +البيسبول +البيسين +البيض +البيضاء +البيضات +البيضة +البيطرة +البيطري +البيطرية +البيطريين +البيع +البيعة +البيـئة +البيك +البيكو +البيلساني +البين +البينات +البينية +البيه +البيوت +البيوتايل +البيوتين +البيورك +البيوض +البيولوجي +البيولوجيا +البيولوجية +البيولوجيّ +البيّنات +البيّنة +البَضّ +البَلَه +البَلُّوطة +الت +التآكل +التآكلي +التآلف +التآليف +التأتي +التأثر +التأثيث +التأثير +التأثيرات +التأخر +التأخير +التأديبية +التأرجح +التأريخ +التأسيس +التأسيسي +التأسيسية +التأشيرات +التأصيل +التأقلم +التأكد +التأكيد +التأليف +التأليفي +التأمت +التأمل +التأملات +التأمين +التأنق +التأني +التأنيب +التأهب +التأهل +التأهيل +التأهيلية +التأوه +التأويل +التأويلات +التأويلي +التئام +التا +التائب +التائبات +التائبون +التائهة +التائهون +التابع +التابعة +التابعون +التابعي +التابلوهات +التابوت +التاج +التاجر +التاريخ +التاريخي +التاريخية +التاريخين +التاريخيين +التاسع +التاسعة +التاطت +التافهة +التاكسي +التالفة +التالى +التالي +التالية +التاليتين +التام +التامات +التامة +التامي +التاني +التايلاندية +التايمز +التايواني +التايوانية +التبادل +التبادلات +التبادلية +التباس +التباعد +التباين +التباينات +التبت +التبجيل +التبدل +التبدلات +التبذير +التبرج +التبرع +التبرعات +التبريد +التبرير +التبست +التبسيط +التبشير +التبشيرية +التبعة +التبلدي +التبني +التبول +التبيين +التتابع +التتابعي +التتار +التتالي +التتر +التتراسكلين +التترية +التتويج +التثاقف +التثاقلي +التثاقلية +التثبيت +التثفل +التثقالية +التثقيفي +التثقيفية +التجادل +التجاذبات +التجار +التجارب +التجارة +التجارى +التجاري +التجارية +التجاريين +التجاعيد +التجانس +التجاوب +التجاوز +التجدد +التجديد +التجديدية +التجديديين +التجذر +التجربة +التجريب +التجريبي +التجريبية +التجريد +التجريدية +التجزئة +التجسس +التجسسيين +التجسيد +التجفيف +التجلي +التجمع +التجمعات +التجميع +التجميعية +التجميل +التجميلي +التجميلية +التجني +التجهيز +التجهيزات +التجهيل +التجوال +التجويد +التجويف +التحاشي +التحاق +التحاقه +التحاقهم +التحالف +التحالفات +التحاليل +التحام +التحامهما +التحاور +التحايل +التحبب +التحتى +التحتية +التحجب +التحجر +التحدث +التحدى +التحدي +التحديات +التحديث +التحديثات +التحديثي +التحديثية +التحديد +التحديدات +التحديق +التحذيرية +التحرر +التحرري +التحررية +التحرش +التحرك +التحرير +التحريري +التحريرية +التحريض +التحريضية +التحريفات +التحريم +التحرّر +التحرّري +التحسس +التحسسي +التحسسية +التحسن +التحسين +التحسينات +التحصيل +التحضير +التحضيرية +التحضيريتين +التحضُّر +التحطيب +التحـويلية +التحف +التحفة +التحفظات +التحفيظ +التحفّظات +التحق +التحقت +التحقق +التحقوا +التحقيق +التحقيقات +التحكم +التحكيم +التحلل +التحليق +التحليل +التحليلات +التحليلي +التحليلية +التحمل +التحميل +التحنيط +التحورات +التحول +التحولات +التحويرات +التحويل +التحويلية +التحوّل +التحوّلات +التحيات +التحية +التحيز +التحيّز +التخاذل +التخالف +التخت +التخثر +التخثرات +التخدير +التخرج +التخريب +التخريبي +التخريبية +التخريج +التخريشية +التخزين +التخزينية +التخصص +التخصصات +التخصصي +التخصصية +التخصيب +التخصيص +التخصّص +التخضب +التخطي +التخطيط +التخطيطية +التخفي +التخفيض +التخفيف +التخلخل +التخلص +التخلف +التخلي +التخليقية +التخلّي +التخلُّص +التخمة +التخمين +التخوف +التخوم +التخيل +التخيّل +التخيُّل +التدابير +التداخل +التداعي +التدافع +التداول +التداوي +التدبير +التدخل +التدخين +التدرج +التدرجات +التدرن +التدريب +التدريبات +التدريبي +التدريبية +التدريجي +التدريس +التدريسية +التدفئة +التدفق +التدفقات +التدقيق +التدقيقات +التدليل +التدمير +التدميرية +التدهور +التدوير +التدوين +التدين +التذاكر +التذبذب +التذكارات +التذكاري +التذكارية +التذكرة +التذكير +التذكّر +التذوق +التراب +الترابط +الترابية +التراتبية +التراتيل +التراث +التراثي +التراثية +التراثين +التراجع +التراجم +التراجيدية +التراحم +التراخيص +الترادف +التراكب +التراكم +التراكمات +التراكيب +الترامواي +الترانزستورات +الترانزيت +التراويح +التربانتين +التربة +التربتوفان +التربنة +التربوي +التربوية +التربويون +التربويين +التربية +التربيعي +الترتيب +الترتيبات +الترجمات +الترجمان +الترجمة +الترجي +الترحال +الترحيب +الترخيص +التردد +الترددات +الترددية +الترديد +التردّي +الترسانة +الترسيبي +الترشيح +الترصد +الترع +الترعة +الترف +الترفتاليك +الترفع +الترفيه +الترفيهى +الترفيهي +الترفيهية +الترقق +الترقي +الترقية +الترقيع +الترقّي +الترك +التركماني +التركى +التركي +التركيب +التركيبات +التركيبة +التركيبي +التركيبية +التركية +التركيز +الترمذي +الترميز +الترميم +الترميمية +الترهات +الترهل +الترهلات +التروك +التروي +التروية +الترويج +الترويجي +الترويجية +الترويس +التزام +التزاما +التزامات +التزامنا +التزامه +التزامها +التزامهم +التزاوج +التزايد +التزجيج +التزحزح +التزلج +التزم +التزمت +التزمّت +التزواج +التزود +التزويج +التزوير +التزوّد +التزين +التزينية +التزييف +التساؤل +التساؤلات +التسارة +التسارع +التسامح +التسامي +التساهل +التسبب +التستر +التسجيل +التسجيلات +التسجيلي +التسجيلية +التسخير +التسخيري +التسخين +التسرب +التسربات +التسريب +التسرية +التسرّبات +التسرُّب +التسع +التسعة +التسعون +التسعين +التسعينات +التسعينيات +التسكع +التسلح +التسلسل +التسلط +التسلل +التسلية +التسليح +التسليحية +التسليخ +التسليم +التسليمي +التسلّط +التسلُّق +التسمم +التسميات +التسمية +التسمّم +التسمُّم +التسنيد +التسهيلات +التسوق +التسول +التسونامي +التسوىقي +التسوية +التسويق +التسويقية +التسييس +التشاؤم +التشاؤمية +التشابك +التشابه +التشابهات +التشبث +التشبع +التشبيهية +التشبُّه +التشجير +التشجيع +التشجيعية +التشخيص +التشخيصية +التشدد +التشديد +التشرد +التشريح +التشريحية +التشريع +التشريعات +التشريعي +التشريعية +التشريفة +التشرّدية +التشفي +التشكك +التشكيك +التشكيل +التشكيلي +التشكيليات +التشكيلية +التشكيليين +التشكّل +التشنجات +التشنُّج +التشوه +التشوهات +التشويش +التشويه +التشويهات +التشوّش +التشيع +التشيكي +التصادم +التصاق +التصاقا +التصاقاً +التصاميم +التصانيف +التصحر +التصحيح +التصحيحية +التصحيف +التصحُّر +التصدعات +التصدي +التصدير +التصديق +التصدّي +التصدِّي +التصرف +التصرفات +التصريح +التصريحات +التصريف +التصرُّف +التصفية +التصفيق +التصق +التصقت +التصلب +التصميم +التصميمات +التصنيع +التصنيعية +التصنيف +التصور +التصورات +التصوف +التصويت +التصوير +التصوّر +التصوّرات +التضاد +التضاريس +التضامن +التضحية +التضخم +التضرعات +التطابق +التطاول +التطبيب +التطبيع +التطبيق +التطبيقات +التطبيقي +التطبيقية +التطرف +التطريز +التطريش +التطعيم +التطعيمات +التطلع +التطلعات +التطهريين +التطهير +التطور +التطورات +التطوع +التطوعي +التطوعية +التطوير +التطوّر +التطوُّح +التطيب +التطير +التظاهر +التظاهرة +التظرف +التظهرن +التعابير +التعارض +التعارف +التعاسة +التعاضد +التعاطف +التعاطي +التعاقدي +التعالي +التعاليم +التعامل +التعاون +التعاونى +التعاوني +التعاونية +التعاويذ +التعايش +التعب +التعبئة +التعبير +التعبيرات +التعبيرية +التعبّدي +التعتعة +التعتيم +التعجب +التعجرف +التعجيز +التعجيل +التعجُّب +التعداد +التعددية +التعدي +التعديلات +التعديلاتِ +التعدين +التعدينية +التعدّدي +التعدّدية +التعذيب +التعرض +التعرف +التعريب +التعرية +التعريف +التعريفات +التعرّض +التعرّف +التعرّي +التعرُّض +التعس +التعسة +التعسّف +التعصب +التعصّب +التعطّر +التعظيم +التعفن +التعقد +التعقيد +التعقيدات +التعقيم +التعلق +التعلم +التعليب +التعليقات +التعليم +التعليمات +التعليمي +التعليمية +التعمير +التعميم +التعميمية +التعنت +التعهدات +التعويض +التعيسة +التعيين +التـــي +التفاؤل +التفاتة +التفاح +التفاحة +التفاصيل +التفاعل +التفاعلات +التفاني +التفاهم +التفاوت +التفاوتِ +التفاوض +التفت +التفتا +التفتت +التفتح +التفتنا +التفتيش +التفتَ +التفتُ +التفتُّ +التفجير +التفرد +التفردية +التفرس +التفرعات +التفرقة +التفريط +التفريعات +التفريق +التفرّس +التفسير +التفسيرات +التفصيل +التفصيلات +التفصيلية +التفعيلة +التفكجي +التفكي +التفكير +التفكيك +التفكيكية +التفكّر +التفلسف +التفوق +التفوه +التفوّق +التفّاح +التقاء +التقاءه +التقائه +التقائهم +التقارب +التقارير +التقاسيم +التقاصر +التقاط +التقاطع +التقاطعات +التقاطه +التقاطها +التقاعد +التقاليد +التقانات +التقانة +التقانيات +التقاوي +التقبل +التقت +التقدم +التقدمية +التقدميين +التقدير +التقديرات +التقديرية +التقديس +التقديم +التقدّم +التقرب +التقريب +التقريبيون +التقرير +التقرّب +التقسيم +التقشف +التقشير +التقصير +التقصّي +التقصِّي +التقط +التقطت +التقطته +التقطتها +التقطتهما +التقطناه +التقطها +التقعر +التقـانة +التقلبات +التقلدية +التقلص +التقليد +التقليدي +التقليديان +التقليدية +التقليدين +التقليديون +التقليديين +التقليل +التقني +التقنيات +التقنية +التقنين +التقهقر +التقوا +التقوقع +التقوى +التقوي +التقويم +التقى +التقىيم +التقية +التقيت +التقيتها +التقيتُ +التقيحات +التقيد +التقينا +التقيناه +التقييم +التكاثر +التكاسل +التكافؤ +التكافل +التكافلية +التكاليف +التكامل +التكبير +التكتل +التكتلات +التكتيكية +التكرار +التكرير +التكريم +التكلس +التكلفة +التكلم +التكلور +التكليف +التكنولوجي +التكنولوجيا +التكنولوجية +التكون +التكوين +التكوينات +التكىيف +التكية +التكيف +التل +التلاؤم +التلاحم +التلازم +التلاعب +التلاقي +التلال +التلاميذ +التلبية +التلحين +التلفاز +التلفازي +التلفت +التلفريك +التلفريون +التلفزة +التلفزيون +التلفزيونات +التلفزيوني +التلفزيونية +التلفون +التلفّت +التلقائي +التلقائية +التلقيح +التلقين +التلقّي +التلمساني +التلموذات +التلميح +التلميذ +التلوث +التلوّث +التلوُّث +التليد +التليفزيون +التليفزيوني +التليفزيونية +التليفون +التليفونية +التليمير +التليميرات +التليميريز +التماثل +التماثيل +التمارين +التماس +التماسك +التماعات +التماعاته +التمام +التمامية +التماهي +التمايز +التمايزات +التمتع +التمتمة +التمثال +التمثيل +التمثيلي +التمثيلية +التمحيص +التمدد +التمديدات +التمدّن +التمذهب +التمر +التمرد +التمركز +التمريضية +التمرين +التمرّد +التمزقات +التمزيق +التمس +التمساح +التمسك +التمعدن +التمعن +التمكن +التمكين +التمكينية +التملك +التمني +التموجية +التمور +التمويل +التمويلي +التمويلية +التموين +التموينية +التمويه +التميز +التمييز +التمييزي +التميّز +التنازل +التنازلات +التناسق +التناسلي +التناسلية +التناص +التناضح +التناظر +التنافس +التنافسية +التناقص +التناقض +التناقضات +التناول +التنبؤ +التنبؤية +التنبيه +التنجيم +التندب +التنزيلات +التنس +التنسيب +التنسيق +التنشيط +التنشيف +التنصل +التنصي +التنصير +التنصيري +التنصيرية +التنضير +التنظــيف +التنظير +التنظيري +التنظيف +التنظيم +التنظيمات +التنفس +التنفسي +التنفسية +التنفيذ +التنفيذى +التنفيذي +التنفيذية +التنفيذيين +التنقل +التنقلات +التنقيب +التنقيبات +التنقيبية +التنكر +التنكس +التنكيزية +التنموي +التنموية +التنمية +التنهد +التنوخي +التنور +التنورة +التنوع +التنوير +التنويعات +التنويه +التنوّع +التنوُّع +التنين +التهاب +التهابات +التهابية +التهام +التهامها +التهامي +التهاني +التهاون +التهاوي +التهب +التهبت +التهجد +التهجير +التهجين +التهديد +التهديدات +التهذيب +التهرؤ +التهريب +التهشم +التهكم +التهم +التهمة +التهمت +التهنئة +التهور +التهوية +التهويم +التهوين +التوأم +التواء +التواؤم +التواب +التوابل +التواجد +التواريخ +التوازن +التوازنات +التوازني +التوازي +التواشيح +التواصل +التواضع +التواطؤ +التوافد +التوافق +التوالد +التوالدية +التوالي +التواليت +التوبة +التوبيخ +التوت +التوتاليتاري +التوتاليتارية +التوتر +التوترات +التوترية +التوتنجي +التوتياء +التوثيق +التوثيقي +التوجه +التوجهات +التوجيه +التوجيهات +التوحد +التوحيد +التوحيدي +التوحّش +التوراة +التوراتي +التوراتية +التورط +التورية +التوزيع +التوسع +التوسعة +التوسعي +التوسعية +التوسل +التوسلات +التوصل +التوصيات +التوصية +التوصيف +التوصيل +التوصيلات +التوضع +التوضيب +التوضيح +التوطين +التوظيف +التوظيفي +التوعوي +التوعوية +التوعية +التوفل +التوفير +التوفيق +التوق +التوقع +التوقعات +التوقف +التوقيت +التوقيع +التوكل +التولوين +التوليف +التوليفة +التون +التونة +التونسي +التونسية +التوهج +التويج +التى +التي +التيار +التيارات +التياران +التيارين +التيبر +التيبس +التيتانيك +التيجان +التيسير +التيليفريك +التين +التينة +التيه +التّجمّعات +التّذْويت +التّشارك +التّنظيف +التّنفّس +التّنفّسية +التّهوية +التّواليت +التّوصيات +التَّالية +التَّقْوَى +التَّليد +التِّـبْر +الث +الثائر +الثائرات +الثائرة +الثابت +الثابتة +الثاقبة +الثالث +الثالثة +الثالثةُ +الثالوث +الثامن +الثامنة +الثانوي +الثانوية +الثانى +الثاني +الثانية +الثانيةُ +الثبات +الثبيتي +الثدي +الثدييات +الثديين +الثراء +الثرثرة +الثروة +الثرى +الثري +الثريات +الثرية +الثعابين +الثعالب +الثعبان +الثعلب +الثـالـث +الثقاب +الثقات +الثقافات +الثقافة +الثقافى +الثقافي +الثقافية +الثقب +الثقة +الثقل +الثقلاء +الثقوب +الثقيل +الثقيلة +الثكلى +الثكنات +الثلاث +الثلاثاء +الثلاثة +الثلاثمائة +الثلاثي +الثلاثية +الثلاثين +الثلاثينات +الثلاثيني +الثلاثينيات +الثلاثُ +الثلاثِ +الثلاجة +الثلث +الثلثين +الثلج +الثلجي +الثلجية +الثلم +الثلمة +الثلوج +الثمار +الثمالة +الثمانون +الثماني +الثمانية +الثمانين +الثمانينات +الثمانينيات +الثمر +الثمرات +الثمرة +الثمن +الثمين +الثمينة +الثناء +الثنائى +الثنائي +الثنائية +الثنايا +الثنيات +الثواب +الثوابت +الثوار +الثواني +الثوب +الثور +الثورات +الثورة +الثوري +الثورية +الثوم +الثياب +الثيران +الثَّوَابِ +الجأش +الجائر +الجائرة +الجائز +الجائزة +الجائع +الجائعة +الجائعين +الجائلين +الجابر +الجابري +الجابون +الجابية +الجات +الجاثوم +الجاحظ +الجاحظتين +الجاد +الجادة +الجادر +الجادون +الجادين +الجاذب +الجاذبة +الجاذبية +الجار +الجارات +الجارالله +الجارة +الجارح +الجارحي +الجارديان +الجارف +الجاروف +الجارى +الجاري +الجارية +الجازم +الجاسر +الجاف +الجافة +الجافّ +الجاكارد +الجاكيت +الجالب +الجالس +الجالسين +الجالية +الجاليريهات +الجامح +الجامحة +الجامدة +الجامع +الجامعات +الجامعة +الجامعي +الجامعية +الجامعيين +الجان +الجانب +الجانبي +الجانبية +الجانبين +الجانبَ +الجانتسيان +الجانج +الجانجا +الجاهز +الجاهزة +الجاهلون +الجاهلي +الجاهلية +الجاهليين +الجاوي +الجبار +الجبال +الجبان +الجبر +الجبري +الجبس +الجبل +الجبلي +الجبلية +الجبن +الجبناء +الجبهات +الجبهة +الجبهي +الجبيل +الجبين +الجبّار +الجبّارة +الجثة +الجثث +الجثمانية +الجحر +الجحش +الجحور +الجحيم +الجد +الجدات +الجدار +الجدارة +الجداري +الجدارية +الجدالات +الجدانوفية +الجداول +الجداوي +الجدب +الجدة +الجدد +الجدرات +الجدران +الجدرة +الجدري +الجدل +الجدليات +الجدول +الجدوى +الجدوي +الجديان +الجدية +الجديد +الجديدة +الجدير +الجديرة +الجديـدة +الجدّ +الجدّة +الجدّي +الجذاب +الجذابة +الجذام +الجذب +الجذبوي +الجذبوية +الجذر +الجذري +الجذرية +الجذع +الجذعية +الجذوة +الجذور +الجذوع +الجر +الجرأة +الجرائد +الجرائم +الجراثيم +الجراح +الجراحات +الجراحة +الجراحون +الجراحي +الجراحية +الجراحين +الجراد +الجرار +الجرافات +الجرافة +الجرام +الجراند +الجرانيت +الجرثومية +الجرجاوي +الجرح +الجرحى +الجرد +الجرداء +الجرذان +الجرس +الجرعات +الجرعة +الجرف +الجرمان +الجروح +الجري +الجريء +الجريئة +الجريان +الجريح +الجريحة +الجريد +الجريدة +الجريمة +الجرّتين +الجزء +الجزأين +الجزئي +الجزئيات +الجزئية +الجزائر +الجزائرمحطته +الجزائري +الجزائرية +الجزائريون +الجزائريين +الجزار +الجزايرلي +الجزر +الجزرية +الجزم +الجزيء +الجزيئات +الجزيئية +الجزيرة +الجزيل +الجسد +الجسدي +الجسدية +الجسر +الجسرالضيّق +الجسم +الجسماني +الجسمي +الجسمية +الجسور +الجسورة +الجسيم +الجسيمات +الجسيمة +الجسيمية +الجص +الجعة +الجـوية +الجـينـات +الجفاف +الجفن +الجفوة +الجلاء +الجلابة +الجلابيب +الجلاد +الجلال +الجلالة +الجلالي +الجلالين +الجلاميد +الجلباب +الجلبة +الجلبي +الجلجلة +الجلد +الجلدشوكيات +الجلدي +الجلدية +الجلسات +الجلسة +الجلطات +الجلل +الجلود +الجلوس +الجلوكوز +الجلية +الجليد +الجليدي +الجليدية +الجليل +الجليلة +الجم +الجماجم +الجماح +الجماد +الجمارك +الجماعات +الجماعة +الجماعي +الجماعية +الجمال +الجمالى +الجمالي +الجمالية +الجماهير +الجماهيري +الجماهيرية +الجمبري +الجمجمة +الجمحي +الجمر +الجمرات +الجمرة +الجمركية +الجمع +الجمعة +الجمعي +الجمعيات +الجمعية +الجمل +الجملة +الجمهرة +الجمهور +الجمهوري +الجمهوريات +الجمهورية +الجمود +الجموع +الجميع +الجميل +الجميلات +الجميلة +الجميلتين +الجميّل +الجمّة +الجن +الجنائز +الجنائزي +الجنائزية +الجنائي +الجنائية +الجناة +الجناح +الجناحية +الجنادرية +الجنازات +الجنازة +الجنان +الجنبات +الجنبية +الجنة +الجند +الجندب +الجندر +الجندرة +الجندول +الجندي +الجندية +الجنرال +الجنس +الجنسي +الجنسيات +الجنسية +الجنسين +الجنوب +الجنوبى +الجنوبي +الجنوبية +الجنوبيين +الجنوبيّة +الجنوح +الجنود +الجنون +الجنوني +الجني +الجنية +الجنين +الجنينية +الجنيه +الجنيهات +الجنّ +الجهات +الجهاد +الجهادي +الجهادية +الجهاز +الجهازية +الجهة +الجهتين +الجهد +الجهراء +الجهل +الجهلاء +الجهنمي +الجهني +الجهود +الجهوري +الجهوي +الجهوية +الجو +الجوائز +الجواب +الجوابون +الجوار +الجوارح +الجواري +الجواريش +الجواز +الجوازات +الجوازي +الجواسيس +الجوامع +الجوانب +الجواني +الجواهر +الجود +الجودة +الجور +الجورشي +الجوز +الجوزي +الجوع +الجوعى +الجوفاء +الجوفية +الجوقة +الجول +الجولات +الجولان +الجولة +الجولف +الجونة +الجونكور +الجوهر +الجوهري +الجوهرية +الجوهريين +الجوى +الجوي +الجوية +الجويين +الجوّاني +الجياد +الجيب +الجيتار +الجيتو +الجيد +الجيدة +الجيدين +الجير +الجيران +الجيري +الجيرية +الجيزة +الجيش +الجيـنيون +الجيل +الجيلادا +الجيلاني +الجيم +الجين +الجينات +الجينز +الجينوكولوجي +الجينى +الجيني +الجينية +الجيوب +الجيوسي +الجيوش +الجيوفيزيائي +الجيوكندا +الجيولوجي +الجيولوجيا +الجيولوجية +الجيّد +الجيّدة +الجَدْب +الحائرين +الحائط +الحاج +الحاجات +الحاجبين +الحاجة +الحاجز +الحاحظ +الحاخامية +الحاد +الحادة +الحادث +الحادثة +الحادى +الحادي +الحادية +الحار +الحارة +الحارث +الحارثي +الحارس +الحارق +الحارقة +الحازم +الحازمة +الحاسب +الحاسبات +الحاسة +الحاسرات +الحاسم +الحاسمة +الحاسوب +الحاشد +الحاشية +الحاصل +الحاصلات +الحاصلة +الحاصلين +الحاضر +الحاضرات +الحاضرة +الحاضرون +الحاضرين +الحافة +الحافظ +الحافظة +الحافل +الحافلات +الحافلة +الحافي +الحافية +الحاقد +الحاقدة +الحاقدون +الحاقدين +الحاكم +الحاكمة +الحاكمية +الحاكمين +الحاكي +الحال +الحالات +الحالة +الحالتين +الحالك +الحالم +الحالمة +الحالمُ +الحالى +الحالي +الحالية +الحالين +الحاليين +الحامدي +الحامدية +الحامض +الحامضة +الحاملة +الحاملون +الحاملين +الحامى +الحامي +الحامية +الحانوت +الحانية +الحاوي +الحاوية +الحب +الحبات +الحباك +الحبة +الحبر +الحبس +الحبشة +الحبشي +الحبك +الحبكة +الحبل +الحبلية +الحبوب +الحبيب +الحبيبات +الحبيبة +الحبيبية +الحبيبين +الحتمي +الحتمية +الحثيث +الحثيثة +الحج +الحجاب +الحجاج +الحجارة +الحجاز +الحجازي +الحجازية +الحجازيين +الحجب +الحجة +الحجج +الحجر +الحجرات +الحجرالصحي +الحجرة +الحجري +الحجرية +الحجز +الحجلة +الحجم +الحجمُ +الحجمِ +الحجوزات +الحجي +الحجيج +الحد +الحدائق +الحداثة +الحداثي +الحداثيون +الحداد +الحدادة +الحدادين +الحدباء +الحدبة +الحدة +الحدث +الحدس +الحدقات +الحدقتين +الحدوات +الحدوة +الحدوث +الحدود +الحديث +الحديثة +الحديثين +الحديد +الحديدة +الحديدى +الحديدي +الحديدية +الحديديتين +الحديديين +الحديقة +الحدّ +الحدّية +الحدَّ +الحذاء +الحذاءين +الحذر +الحذف +الحر +الحرائق +الحراب +الحرارة +الحراري +الحرارية +الحراس +الحراسة +الحراسيس +الحراك +الحرام +الحرب +الحرباء +الحرباوات +الحربي +الحربية +الحربين +الحرة +الحرث +الحرج +الحرجة +الحرجلة +الحرجي +الحرس +الحرص +الحرف +الحرفة +الحرفي +الحرفية +الحرفيين +الحرق +الحرقة +الحرقية +الحركات +الحركة +الحركةِ +الحركتين +الحركي +الحركية +الحرم +الحرمات +الحرمان +الحرمون +الحرمين +الحروب +الحروري +الحرورية +الحروف +الحروق +الحريات +الحرية +الحرير +الحريرات +الحريرة +الحريرى +الحريري +الحريص +الحريصة +الحريصون +الحريق +الحريقة +الحرّ +الحرّة +الحزازات +الحزام +الحزب +الحزبان +الحزبي +الحزبية +الحزبين +الحزم +الحزن +الحزين +الحزينة +الحس +الحساب +الحسابات +الحسابية +الحساس +الحساسة +الحساسية +الحساسين +الحسب +الحسبان +الحسد +الحسم +الحسن +الحسنات +الحسنة +الحسنى +الحسنية +الحسي +الحسية +الحسين +الحسيني +الحسينية +الحسينيون +الحسّاسة +الحسّي +الحسّية +الحشائش +الحشاشين +الحشد +الحشرات +الحشرة +الحشرية +الحشف +الحشفي +الحشفية +الحشمة +الحشو +الحصاة +الحصاد +الحصار +الحصارات +الحصان +الحصانة +الحصباء +الحصة +الحصر +الحصص +الحصن +الحصول +الحصولَ +الحصون +الحصى +الحصيات +الحصير +الحصيرة +الحصيفة +الحصيلة +الحصين +الحصينة +الحض +الحضارات +الحضارة +الحضارتين +الحضاري +الحضارية +الحضانة +الحضرات +الحضري +الحضرية +الحضور +الحضيض +الحطاب +الحطام +الحظ +الحظر +الحظوظ +الحـالى +الحـج +الحـجز +الحـد +الحـدود +الحـديث +الحـديثة +الحـديقة +الحـركة +الحـسابية +الحـضارات +الحـــضـــــارة +الحــــالات +الحــية +الحـقيبة +الحـقيقة +الحـكومة +الحـكومية +الحـياة +الحـية +الحف +الحفائر +الحفاظ +الحفافي +الحفاوة +الحفر +الحفرة +الحفريات +الحفرية +الحفظ +الحفظية +الحفل +الحفلات +الحفلة +الحفلى +الحق +الحقائب +الحقائق +الحقانية +الحقب +الحقبة +الحقد +الحقل +الحقن +الحقوق +الحقوقي +الحقوقية +الحقوقيين +الحقول +الحقيبة +الحقير +الحقيرة +الحقيقة +الحقيقي +الحقيقية +الحقيقيين +الحقّ +الحكام +الحكايات +الحكاية +الحكة +الحكم +الحكماء +الحكمة +الحكواتي +الحكومات +الحكومة +الحكومتان +الحكومتين +الحكومى +الحكومي +الحكومية +الحكوميين +الحكي +الحكيم +الحكيمة +الحل +الحلاج +الحلاق +الحلاقة +الحلاقين +الحلال +الحلاوة +الحلاويين +الحلبة +الحلبي +الحلفاء +الحلق +الحلقات +الحلقة +الحلقية +الحلل +الحلم +الحلمية +الحلمُ +الحلو +الحلول +الحلوى +الحلي +الحليب +الحلية +الحليلي +الحليم +الحلّ +الحلّي +الحماد +الحمادي +الحمار +الحماس +الحماسة +الحماسية +الحماقات +الحماقة +الحمالون +الحمام +الحمامات +الحمامة +الحماية +الحمد +الحمداني +الحمدلله +الحمر +الحمراء +الحمص +الحمصي +الحمض +الحمضات +الحمضي +الحمضيات +الحمضية +الحمل +الحملات +الحملة +الحملي +الحموض +الحموضة +الحمولة +الحموي +الحمى +الحميد +الحميدي +الحمير +الحميري +الحميضي +الحميم +الحميمة +الحميمي +الحميمية +الحميمين +الحمّاد +الحمّام +الحمّى +الحمَّام +الحمَّامات +الحناء +الحنان +الحنة +الحنجرة +الحنجرية +الحنطة +الحنطور +الحنظل +الحنفي +الحنفية +الحنق +الحنك +الحنون +الحنية +الحنيف +الحنين +الحوائط +الحواة +الحواجب +الحواجز +الحواجزبين +الحوادث +الحوار +الحوارات +الحواري +الحوارية +الحواس +الحواضر +الحواف +الحوافز +الحوامل +الحوانيت +الحوت +الحور +الحوراني +الحورية +الحوسني +الحوشية +الحوض +الحوضين +الحوطي +الحول +الحوليات +الحىة +الحي +الحياء +الحياة +الحياتي +الحياتية +الحياد +الحيازة +الحياكة +الحية +الحيتان +الحيرة +الحيز +الحيض +الحيف +الحيل +الحيلة +الحين +الحيوات +الحيوان +الحيوانات +الحيواني +الحيوانية +الحيوي +الحيوية +الحيويّة +الحيّ +الحيّة +الحيّز +الحَجب +الحُبُور +الحُرَّة +الحِكَم +الخ +الخا +الخائب +الخائرة +الخائف +الخائفة +الخائن +الخابور +الخاتمة +الخادعة +الخادم +الخادمات +الخادمة +الخارج +الخارجة +الخارجون +الخارجى +الخارجي +الخارجية +الخارجين +الخارجيين +الخارطة +الخارق +الخارقة +الخارقين +الخازن +الخازندار +الخاسر +الخاسرين +الخاشعين +الخاص +الخاصة +الخاصية +الخاصّة +الخاضعة +الخاطئ +الخاطئة +الخاطبين +الخاطر +الخافت +الخافتة +الخافض +الخافضة +الخال +الخالة +الخالد +الخالدة +الخالدون +الخالدي +الخالدية +الخالص +الخالصة +الخالق +الخالقية +الخالى +الخالي +الخالية +الخام +الخامات +الخامد +الخامس +الخامسة +الخامل +الخان +الخانة +الخانقاه +الخانقة +الخبائث +الخبازين +الخبب +الخبر +الخبراء +الخبرات +الخبرة +الخبرية +الخبز +الخبيئة +الخبيث +الخبيثة +الخبير +الخبيرة +الختام +الختامي +الختامية +الختم +الختمة +الختمية +الخجل +الخجول +الخداع +الخدج +الخدر +الخدري +الخدم +الخدمات +الخدمة +الخدمية +الخدود +الخدور +الخدي +الخديعة +الخدين +الخديو +الخديوي +الخذلان +الخرائب +الخرائط +الخراب +الخرابة +الخراجات +الخراساني +الخراط +الخراطيم +الخراف +الخرافات +الخرافة +الخرافية +الخربة +الخرج +الخرجة +الخرجي +الخرسانة +الخرساني +الخرسانية +الخرطوم +الخرف +الخرم +الخرنفش +الخروج +الخروف +الخريجون +الخريجين +الخرير +الخريطة +الخريطتين +الخريف +الخزافين +الخزانات +الخزانة +الخزرج +الخزعة +الخزف +الخزفية +الخزينة +الخزّافين +الخس +الخسائر +الخسارة +الخشابين +الخشب +الخشبي +الخشبية +الخشبيّ +الخشخاش +الخشكريشة +الخشنة +الخشونة +الخشية +الخصائص +الخصال +الخصام +الخصب +الخصبة +الخصر +الخصلات +الخصلة +الخصم +الخصمين +الخصوبة +الخصوص +الخصوصية +الخصومات +الخصومة +الخصوي +الخصيب +الخصية +الخضار +الخضر +الخضراء +الخضراوات +الخضرة +الخضروات +الخضوع +الخط +الخطأ +الخطاب +الخطابات +الخطايا +الخطب +الخطبة +الخطبِ +الخطة +الخطر +الخطرة +الخطط +الخطف +الخطوات +الخطوبة +الخطوة +الخطورة +الخطوط +الخطى +الخطي +الخطيب +الخطيبان +الخطيبين +الخطية +الخطير +الخطيرة +الخطين +الخـدمـة +الخفاء +الخفاش +الخفايا +الخفض +الخفوت +الخفي +الخفية +الخفيض +الخفيضة +الخفيف +الخفيفة +الخفّة +الخل +الخلائق +الخلاب +الخلابة +الخلاص +الخلاصة +الخلاط +الخلاف +الخلافات +الخلافة +الخلافية +الخلاق +الخلايا +الخلاّق +الخلجات +الخلجان +الخلخلة +الخلدوني +الخلص +الخلط +الخلطاء +الخلطة +الخلعيين +الخلف +الخلفاء +الخلفي +الخلفيات +الخلفية +الخلفيتين +الخلفيين +الخلق +الخلقي +الخلقية +الخلل +الخلوات +الخلود +الخلوي +الخلوية +الخلية +الخليتان +الخليج +الخليجى +الخليجي +الخليجيات +الخليجية +الخليجيين +الخليط +الخليفة +الخليقة +الخليل +الخليلي +الخمار +الخمج +الخمر +الخمرة +الخمس +الخمسة +الخمسمائة +الخمسون +الخمسين +الخمسينات +الخمسينيات +الخمور +الخميرة +الخميس +الخميسات +الخميسي +الخميسية +الخميني +الخناجر +الخنادق +الخنافس +الخناق +الخنثى +الخنجر +الخندق +الخنزير +الخنساء +الخنق +الخواء +الخواتم +الخوادم +الخوارزمي +الخوارزمية +الخوارق +الخواص +الخواطر +الخوالي +الخوان +الخوتاني +الخوخ +الخور +الخوري +الخوض +الخوف +الخولي +الخونة +الخيار +الخيارات +الخياشيم +الخياط +الخياطة +الخياطين +الخيال +الخيالات +الخيالة +الخيالي +الخيالية +الخيام +الخيامية +الخياميون +الخيانة +الخيبة +الخير +الخيرات +الخيرة +الخيري +الخيرية +الخيرين +الخيش +الخيشومي +الخيط +الخيل +الخيلُ +الخيمة +الخيمي +الخيوط +الخيول +الخيّام +الخيّرة +الخَطَابة +الخُلْف +الدءوب +الدءوبة +الدأب +الدؤوب +الداء +الدائب +الدائر +الدائرة +الدائرية +الدائم +الدائمة +الدائمين +الدائن +الدائنون +الدابة +الداجنة +الداجنين +الداخل +الداخلة +الداخلون +الداخلى +الداخلي +الداخلية +الداخليين +الداخية +الدار +الدارج +الدارجة +الدارس +الدارسات +الدارسين +الدارية +الداع +الداعم +الداعمة +الداعي +الداعيات +الداعية +الداعين +الدافئ +الدافئة +الدافع +الدافعة +الدافعية +الدافق +الدافقة +الداكن +الداكنة +الداكوتا +الدال +الدالاتي +الدالة +الدامس +الدانتيلا +الدانماركيين +الدانوب +الداهية +الداوردي +الداوودي +الدب +الدبابات +الدبابة +الدبان +الدببة +الدببةِ +الدبق +الدبلجة +الدبلوم +الدبلوماسي +الدبلوماسية +الدبور +الدبوس +الدبين +الدبُّ +الدجاج +الدجاجين +الدجال +الدجالين +الدجاني +الدخان +الدخل +الدخلاء +الدخول +الدخيل +الدخيلة +الدراجات +الدراجة +الدراجي +الدراسات +الدراسة +الدراستين +الدراسي +الدراسية +الدراما +الدرامية +الدراويش +الدراية +الدرب +الدربكة +الدرة +الدرج +الدرجات +الدرجة +الدرحة +الدرداء +الدرر +الدرس +الدرع +الدرعية +الدرق +الدرقة +الدرقية +الدروس +الدرويشية +الدرَّاجات +الدسائس +الدساتير +الدستور +الدستورية +الدستوريين +الدسم +الدسمة +الدشاش +الدشداشة +الدشكة +الدعاء +الدعائم +الدعائية +الدعابة +الدعاة +الدعارة +الدعامات +الدعاوى +الدعاية +الدعة +الدعم +الدعوات +الدعوة +الدعوى +الدعوي +الدعوية +الدفء +الدفاتر +الدفاع +الدفاعات +الدفاعي +الدفاعية +الدفة +الدفتر +الدفع +الدفعات +الدفنات +الدفوف +الدفيئة +الدفين +الدفينة +الدقائق +الدقة +الدقهلية +الدقيق +الدقيقة +الدك +الدكاكين +الدكان +الدكتاتوريات +الدكتاتورية +الدكتور +الدكتوراة +الدكتوراه +الدكتورة +الدكن +الدلائل +الدلافين +الدلال +الدلالات +الدلالة +الدلالي +الدلتا +الدلو +الدليل +الدم +الدماء +الدمار +الدمام +الدمامل +الدمج +الدمشقي +الدمشقية +الدمع +الدمعة +الدمعي +الدمعية +الدموع +الدموي +الدموية +الدمى +الدمية +الدميةُ +الدميري +الدميني +الدنا +الدنانير +الدنايا +الدنسة +الدنمارك +الدنماركي +الدنيئة +الدنيا +الدنيوي +الدنيوية +الدهان +الدهب +الدهر +الدهشة +الدهليز +الدهن +الدهنية +الدهون +الدواء +الدواءين +الدواءُ +الدوائر +الدوائي +الدوائية +الدواب +الدواة +الدواجن +الدوار +الدوافع +الدوام +الدواوين +الدوبلر +الدوحة +الدوخة +الدود +الدودة +الدودي +الدودية +الدور +الدورات +الدوران +الدورة +الدوري +الدوريات +الدورية +الدورين +الدوسري +الدوش +الدوق +الدول +الدولار +الدولارات +الدولة +الدولتين +الدولفين +الدولى +الدولىين +الدولي +الدولية +الدوليين +الدومينة +الدومينو +الدومينيكان +الدونية +الدويس +الدويّ +الدوّارة +الدوّارين +الدي +الديار +الديانات +الديانة +الديانتين +الديحان +الديدان +الدير +الديسك +الديسكو +الديك +الديكة +الديكور +الديكي +الديمقراطي +الديمقراطية +الديموقراطية +الديمومة +الدين +الدينار +الدينامية +الديناميت +الديناميكي +الديناميكية +الدينى +الديني +الدينية +الديوان +الديوبندية +الديوبنديين +الديوك +الديون +الدّك +الدّوليّ +الدَّاكن +الدَّعَة +الدُّخان +الدِّين +الذأبي +الذؤابات +الذئاب +الذئب +الذئبة +الذائب +الذائبة +الذابلات +الذابلة +الذابلتان +الذات +الذاتي +الذاتية +الذاكرة +الذبائح +الذباب +الذبابات +الذبابة +الذبح +الذبول +الذبياني +الذخيرة +الذرات +الذراري +الذراع +الذراعين +الذرة +الذروة +الذري +الذرية +الذعر +الذقن +الذكاء +الذكر +الذكرى +الذكريات +الذكرية +الذكور +الذكورة +الذكوري +الذكورية +الذكوريين +الذكي +الذكية +الذل +الذنوب +الذهاب +الذهب +الذهبي +الذهبية +الذهن +الذهني +الذهنية +الذهول +الذوات +الذوبان +الذود +الذوق +الذوقي +الذى +الذىن +الذي +الذيل +الذين +الذيوع +الذَّارية +الذُّخْر +الر +الرءوس +الرأ +الرأس +الرأسمالي +الرأسمالية +الرأسي +الرأسية +الرأفة +الرأي +الرأيين +الرؤساء +الرؤى +الرؤيا +الرؤية +الرئاسة +الرئاسية +الرئة +الرئتين +الرئوي +الرئوية +الرئيس +الرئيسات +الرئيسة +الرئيسى +الرئيسي +الرئيسيان +الرئيسية +الرئيسين +الرئيسيون +الرئيسيين +الراء +الرائحة +الرائد +الرائدات +الرائدة +الرائع +الرائعة +الرائق +الرائقة +الرائي +الرابض +الرابضة +الرابط +الرابطة +الرابع +الرابعة +الرابية +الراتب +الراثية +الراج +الراجح +الراجف +الراحة +الراحـة +الراحل +الراحلة +الراحلين +الراحي +الراديكالي +الراديكالية +الراديكاليون +الراديكاليين +الراديو +الراديوم +الرازق +الرازي +الراسخ +الراسخة +الراسيات +الراشد +الراشدة +الراشدين +الراصدة +الراضي +الراعي +الرافدين +الرافض +الرافضات +الرافضة +الرافعي +الراقص +الراقصة +الراقى +الراقي +الراقية +الراكب +الرامزين +الرامي +الرامية +الراهب +الراهن +الراهنة +الراوي +الراوية +الراية +الراين +الرب +الربا +الربابة +الرباط +الرباعي +الرباعيات +الربان +الرباني +الربانية +الربح +الربحية +الربط +الربع +الربعي +الربو +الربوات +الربوة +الربوي +الربوية +الربيان +الربيع +الربيعي +الربيعية +الرتابة +الرتاج +الرتب +الرتج +الرتل +الرتم +الرتوش +الرتيبة +الرث +الرثاء +الرثة +الرثواني +الرثوية +الرجاء +الرجات +الرجال +الرجالَ +الرجالُ +الرجل +الرجلان +الرجلين +الرجم +الرجوع +الرجولة +الرجولي +الرجيب +الرجيم +الرحال +الرحالة +الرحالون +الرحب +الرحبانى +الرحبة +الرحـال +الرحـلات +الرحـلة +الرحل +الرحلات +الرحلة +الرحم +الرحمة +الرحمن +الرحى +الرحيب +الرحيبة +الرحيق +الرحيل +الرحيم +الرحيمي +الرحّالة +الرخاء +الرخام +الرخامية +الرخاوي +الرخصة +الرخو +الرخوة +الرخويات +الرخيص +الرخيصة +الرخيم +الرد +الردئ +الرداء +الرداءة +الردة +الردم +الرديء +الرديم +الردّ +الرذاذ +الرذيلة +الرز +الرزاق +الرزق +الرزمة +الرزنامة +الرزيزاء +الرزين +الرسائل +الرسالات +الرسالة +الرسالتين +الرسام +الرسامين +الرسل +الرسم +الرسمة +الرسمى +الرسمي +الرسمية +الرسميين +الرسو +الرسوب +الرسوبي +الرسوبيات +الرسوبية +الرسوخ +الرسول +الرسولي +الرسوم +الرسومات +الرشاد +الرشاش +الرشاوى +الرشايدة +الرشح +الرشدان +الرشود +الرشيد +الرشيدة +الرشيدية +الرشيق +الرشيقة +الرصاص +الرصاصات +الرصاصة +الرصاصي +الرصافي +الرصد +الرصيد +الرصيص +الرصيف +الرصيفة +الرض +الرضا +الرضاعة +الرضع +الرضوانية +الرضوض +الرضي +الرضية +الرضيع +الرضيعة +الرطب +الرطبة +الرطل +الرطوبة +الرطيب +الرعاة +الرعاش +الرعاع +الرعاف +الرعاية +الرعب +الرعد +الرعشة +الرعي +الرعية +الرعيل +الرف +الرفا +الرفاة +الرفات +الرفادات +الرفاعي +الرفاه +الرفاهية +الرفض +الرفع +الرفعة +الرفق +الرفوف +الرفيع +الرفيعة +الرفيف +الرق +الرقائق +الرقاب +الرقابة +الرقاقة +الرقبة +الرقبية +الرقة +الرقراق +الرقص +الرقصات +الرقعة +الرقم +الرقمي +الرقمية +الرقن +الرقى +الرقي +الرقيب +الرقية +الرقيق +الرقيقة +الرقّة +الركائز +الركاب +الركابي +الركب +الركبة +الركض +الركن +الركنين +الركوب +الركود +الركون +الركيزة +الركيكة +الركين +الركّاب +الرماحي +الرماد +الرمادي +الرمال +الرماية +الرمة +الرمح +الرمز +الرمزي +الرمزية +الرمضاء +الرمعي +الرمعية +الرمل +الرملة +الرملية +الرموز +الرموش +الرمي +الرنانة +الرنين +الرنّانة +الرها +الرهان +الرهبان +الرهبانية +الرهبة +الرهبنة +الرهيب +الرهيبة +الرهيف +الروائع +الروائي +الروائية +الروائيين +الروابط +الروابي +الرواة +الرواتب +الرواج +الرواح +الرواد +الروايات +الرواية +الروبيان +الروتين +الروتيني +الروتينية +الروح +الروحاني +الروحانيات +الروحانية +الروحي +الروحية +الروس +الروسي +الروسية +الروشتة +الروضات +الروضة +الروعة +الروك +الروم +الروماتيزم +الرومان +الرومانتيكيون +الرومانسي +الرومانسية +الرومانسيون +الرومانسيين +الروماني +الرومانية +الرومانيين +الرومي +الرومية +الرون +الروّاد +الري +الريا +الرياح +الريادة +الرياض +الرياضات +الرياضة +الرياضى +الرياضي +الرياضيات +الرياضية +الرياضيين +الريال +الريالات +الريبافرين +الريبة +الريح +الريحان +الريحاني +الريحانية +الريحُ +الريش +الريشة +الريف +الريفي +الريفية +الريفييرا +الريفيين +الرين +الرينيسانس +الرُها +الرّئويّ +الرّئيسيّة +الرّعاية +الرّقعة +الرَّأي +الرَّابحة +الرَّابض +الرَّاجية +الرَّشيد +الرَّفيع +الرَّفيعة +الرَّمقُ +الرَّيَّانة +الز +الزئبق +الزائد +الزائدة +الزائدون +الزائر +الزائرون +الزائرين +الزائف +الزائفة +الزائلة +الزاحف +الزاحفة +الزاحفين +الزاخر +الزاخرة +الزاد +الزامبيزي +الزاهد +الزاهر +الزاهرة +الزاهية +الزاوية +الزبائن +الزبادي +الزبالة +الزبد +الزبدة +الزبل +الزبون +الزبى +الزبير +الزبيري +الزجاج +الزجاجات +الزجاجة +الزجاجي +الزجاجية +الزحام +الزحف +الزحمة +الزخات +الزخارف +الزخرفة +الزخرفي +الزخرفية +الزخم +الزر +الزرابي +الزرازير +الزراعات +الزراعة +الزراعى +الزراعي +الزراعيات +الزراعية +الزراعيين +الزراية +الزردة +الزرزور +الزرع +الزرق +الزرقا +الزرقاء +الزرقاءْ +الزرقة +الزركشة +الزركلي +الزرنيخ +الزروع +الزرَّاع +الزعامة +الزعتر +الزعراء +الزعم +الزعماء +الزعنفة +الزعيم +الزعيمة +الزفاف +الزفان +الزفرات +الزفير +الزقاق +الزكاة +الزكام +الزكرتاوي +الزكرتي +الزكوات +الزلة +الزلزال +الزلل +الزليزلي +الزليّج +الزمالة +الزمالك +الزمام +الزمان +الزمانية +الزمر +الزمكان +الزمكاني +الزملاء +الزمن +الزمني +الزمنية +الزميل +الزناتي +الزنازين +الزنجي +الزنجيات +الزنجية +الزنخ +الزنزانة +الزنك +الزنكي +الزنوج +الزنى +الزهايمر +الزهد +الزهر +الزهراء +الزهراني +الزهرة +الزهرية +الزهو +الزهور +الزهيدة +الزوائد +الزوابع +الزواج +الزواحف +الزوار +الزوارق +الزوال +الزواوي +الزوايا +الزوج +الزوجات +الزوجة +الزوجية +الزوجين +الزودربلاس +الزور +الزوراء +الزوزانثللي +الزوفا +الزولو +الزوي +الزويك +الزى +الزي +الزيات +الزيادات +الزيادة +الزيارات +الزيارة +الزيبق +الزيت +الزيتون +الزيتونة +الزيتونية +الزيتى +الزيتية +الزيج +الزيجات +الزيجة +الزيدوفودين +الزيدي +الزيز +الزيف +الزيلزلي +الزينة +الزيوت +الزَّاكي +الزَّاكيات +الزَّاكية +الزَّبَدُ +الزَّكَاةَ +الزَّوج +السأم +السؤال +السؤالان +السؤالين +السائب +السائح +السائحـين +السائحون +السائحين +السائد +السائدة +السائرون +السائرين +السائق +السائقين +السائل +السائلة +السائلين +السابحات +السابحة +السابع +السابعة +السابق +السابقان +السابقة +السابقتين +السابقون +السابقين +الساتر +الساحات +الساحة +الساحةِ +الساحر +الساحرة +الساحرتين +الساحق +الساحقة +الساحل +الساحلي +الساحلية +الساحلين +الساخر +الساخرة +الساخطة +الساخن +الساخنة +الساد +السادات +الساداتي +الساداتية +السادة +السادس +السادسة +الساذج +الساذجة +السارد +السارس +السارع +السارق +الساري +السارية +السارّة +الساس +الساسانية +الساسانيين +الساسي +الساطع +الساطعة +الساعات +الساعة +الساعتين +الساعـة +الساعي +الساعية +الساعين +الساق +الساقزلي +الساقطة +الساقين +الساكن +الساكنة +السالامي +السالب +السالبة +السالفة +السالم +السالمون +السالمية +السالين +السام +السامة +السامر +السامرائي +السامريين +السامقة +السامي +السامية +السامين +الساميّة +السامّة +الساندويتشات +الساهرة +الساهرين +الساهي +السايلة +السبا +السبائك +السباحة +السباحون +السباحين +السباعي +السباق +السباقات +السباقون +السبانخ +السبب +السببي +السببَ +السبت +السبحة +السبخة +السبع +السبعة +السبعين +السبعينات +السبعيني +السبعينيات +السبق +السبل +السبورة +السبيطة +السبيعي +السبيل +الست +الستائر +الستار +الستارة +الستة +الستر +السترونتيوم +الستمائة +الستيروئيدات +الستيروئيدية +الستيرويدات +الستيرويدية +الستين +الستينات +الستينيات +الستّ +السجائر +السجات +السجاجيد +السجاد +السجادة +السجع +السجل +السجلات +السجن +السجناء +السجود +السجون +السجين +السجينى +السح +السحاب +السحالي +السحايا +السحب +السحر +السحرة +السحري +السحرية +السحلية +السحنة +السحور +السحيق +السحيقة +السخافات +السخان +السخرية +السخط +السخف +السخية +السخيف +السخيفة +السد +السداد +السدادة +السداسية +السدر +السدو +السدود +السديري +السديس +السذاجة +السر +السراء +السراب +السراة +السراج +السرادق +السراديب +السراي +السرب +السرة +السرتفيكا +السرد +السردية +السردين +السرطان +السرطانات +السرطاني +السرعات +السرعة +السرقات +السرقة +السروات +السروجيون +السرور +السري +السريالية +السريان +السريانية +السرية +السرير +السريري +السريرية +السريع +السريعة +السريين +السرّاء +السرّة +السطان +السطح +السطحي +السطحية +السطر +السطل +السطو +السطوح +السطور +السطوع +السعادة +السعادةَ +السعادةُ +السعادةِ +السعال +السعة +السعداوي +السعدية +السعر +السعرات +السعفة +السعود +السعودة +السعودى +السعودىة +السعودىين +السعودي +السعوديات +السعودية +السعوديةوالتعرف +السعوديون +السعوديين +السعوية +السعى +السعي +السعيد +السعيدة +السعيدية +الســـببية +السفارات +السفارة +السفح +السفر +السفراء +السفلس +السفلي +السفلية +السفن +السفير +السفيرة +السفينة +السقائين +السقف +السقفِ +السقم +السقوط +السقيم +السقيمة +السكارى +السكاكر +السكان +السكانى +السكاني +السكانية +السكة +السكتة +السكر +السكرتير +السكرى +السكري +السكريات +السكرية +السكريد +السكريين +السكك +السكن +السكندري +السكنى +السكني +السكنية +السكوت +السكوتر +السكون +السكين +السكينة +السكَّر +السل +السلاجقة +السلاح +السلاسة +السلاسل +السلاطين +السلافية +السلال +السلالات +السلالة +السلالم +السلام +السلامة +السلب +السلبى +السلبي +السلبيات +السلبية +السلة +السلجوقي +السلجوقية +السلحفاة +السلسا +السلسبيلات +السلسلة +السلطات +السلطان +السلطانية +السلطة +السلطتين +السلطنة +السلطوي +السلع +السلعة +السلعتين +السلعي +السلعية +السلف +السلفي +السلفية +السلفيين +السلك +السلم +السلمي +السلمية +السلو +السلودحا +السلوفان +السلوك +السلوكات +السلوكي +السلوكيات +السلوكية +السليب +السليبة +السليسيوم +السليكون +السليلوز +السليم +السليماني +السليمانية +السليمة +السليمين +السلّة +السلَّم +السم +السماء +السمات +السماح +السماحة +السماد +السماسرة +السماع +السماعات +السماعة +السمان +السمانة +السماوات +السماوي +السماوية +السمة +السمح +السمحاء +السمحة +السمر +السمراء +السمرة +السمسم +السمع +السمعاني +السمعة +السمعي +السمعية +السمك +السمكات +السمكة +السمكي +السمكية +السمن +السمنة +السمو +السموات +السموم +السمية +السمير +السميط +السميع +السميك +السميكة +السمينات +السمينة +السميّة +السمّ +السمّية +السن +السناجب +السنامين +السنباطي +السنبلاوين +السنبلة +السنة +السنتين +السنجاب +السنجق +السند +السندان +السندباد +السنعوسي +السنن +السنهوري +السنوات +السنوسي +السنوسية +السنون +السنونو +السنوى +السنوي +السنوية +السنية +السنين +السنيون +السنّة +السهام +السهد +السهر +السهرات +السهرة +السهل +السهلة +السهول +السهولة +السوء +السواء +السوائل +السواتر +السواح +السواحل +السواحيلية +السواد +السوار +السواعد +السواقي +السوانى +السواني +السود +السوداء +السودان +السوداني +السودانية +السودانيون +السودانيين +السوداوي +السودة +السودية +السور +السوربون +السوري +السوريالية +السورية +السوريين +السوس +السوسرية +السوسيولوجية +السوطي +السوفياتي +السوفيتي +السوفييت +السوفييتي +السوفييتية +السوق +السوقية +السولاريم +السومرية +السومريين +السون +السونا +السوهاجية +السوي +السوية +السويد +السويدي +السويدية +السويديين +السويرة +السويس +السويسري +السويسريات +السويسرية +السويسي +السي +السيئة +السيئين +السيا +السياب +السياح +السياحات +السياحة +السياحـة +السياحـى +السياحـية +السياحى +السياحي +السياحية +السياحيين +السيادة +السيارات +السيارة +السياسات +السياسة +السياسي +السياسية +السياسيون +السياسيين +السياط +السياق +السياقة +السيانيد +السيب +السيتو +السيتوكينات +السيتووراثية +السيجار +السيجارة +السيجواي +السيخ +السيد +السيدات +السيدان +السيدة +السيدين +السير +السيراميك +السيرة +السيرتين +السيرك +السيركليزم +السيرورة +السيزيوم +السيطرة +السيـّاب +السيف +السيكا +السيل +السيلان +السيليكون +السيليكونية +السيلينيوم +السيلُ +السيمانتيكي +السيمفوني +السيمفونية +السيمفونيين +السين +السينائية +السيناريو +السيناريوهات +السينما +السينمائي +السينمائية +السينمائيين +السينمات +السينوباه +السيوطي +السيوف +السيوفي +السيول +السيولة +السيوي +السييء +السيّئ +السيّاب +السيّاح +السُحُب +السُمِّية +السّاخن +السّبب +السّر +السّرير +السّعال +السّفر +السّهل +السّيلان +السَّحاب +السَّلطة +السَّنِيَّة +السَّيدة +السَّير +السُّؤدد +السُّعداء +السُّمَحاء +الشأن +الشؤون +الشئ +الشئون +الشائخة +الشائع +الشائعات +الشائعة +الشائق +الشائقة +الشائك +الشائكة +الشاب +الشابة +الشابي +الشابين +الشابّ +الشابّة +الشابَّ +الشاة +الشاحب +الشاحبة +الشاحبين +الشاحنين +الشاذة +الشاذلي +الشارات +الشارد +الشاردة +الشارع +الشارقة +الشاروني +الشاسع +الشاسعة +الشاسيه +الشاش +الشاشات +الشاشة +الشاطئ +الشاطئية +الشاعر +الشاعران +الشاعرة +الشافعي +الشافعية +الشافعين +الشافي +الشاق +الشاقة +الشال +الشاليهات +الشالَ +الشام +الشامان +الشامة +الشامخ +الشامخة +الشامل +الشاملة +الشامي +الشامية +الشاه +الشاهد +الشاهق +الشاهقة +الشاهين +الشاى +الشاي +الشايب +الشايع +الشباب +الشبابية +الشباك +الشباكية +الشبان +الشبح +الشبكات +الشبكة +الشبكي +الشبكية +الشبه +الشبهات +الشبهة +الشبيلي +الشبيه +الشبيهة +الشتاء +الشتائم +الشتلات +الشتور +الشتوي +الشتوية +الشجار +الشجاع +الشجاعة +الشجاعية +الشجر +الشجرة +الشجرةِ +الشجري +الشجعان +الشجن +الشجو +الشجى +الشجي +الشجية +الشجيرات +الشجيّ +الشح +الشحات +الشحادة +الشحاذين +الشحمي +الشحمية +الشحن +الشحنات +الشحنة +الشحوب +الشحوم +الشحيحة +الشخص +الشخصانية +الشخصى +الشخصي +الشخصيات +الشخصية +الشخوص +الشخير +الشد +الشدائد +الشدة +الشدياق +الشديد +الشديدة +الشديدين +الشذوذ +الشر +الشراء +الشرائح +الشرائط +الشرائية +الشراب +الشرارات +الشراسة +الشراشف +الشراك +الشراكة +الشرايين +الشرب +الشرج +الشرجية +الشرح +الشرخ +الشرر +الشرس +الشرسة +الشرشرة +الشرط +الشرطة +الشرطةِ +الشرطي +الشرطيان +الشرطين +الشرع +الشرعي +الشرعية +الشرعيين +الشرف +الشرفة +الشرق +الشرقاوي +الشرقى +الشرقي +الشرقيات +الشرقية +الشرقيين +الشركاء +الشركات +الشركة +الشركسي +الشره +الشرهان +الشرهين +الشروخ +الشرود +الشرور +الشروط +الشروع +الشروق +الشريان +الشرياني +الشريانية +الشريحة +الشريدة +الشرير +الشريرة +الشريط +الشريعة +الشريف +الشريفات +الشريفة +الشريفية +الشريفين +الشريك +الشريم +الشطر +الشطرنج +الشطرين +الشطط +الشطي +الشظايا +الشظف +الشعائر +الشعاب +الشعار +الشعارات +الشعارين +الشعاعي +الشعاعية +الشعب +الشعبى +الشعبي +الشعبيات +الشعبية +الشعبين +الشعبيين +الشعر +الشعراء +الشعراني +الشعراوي +الشعرة +الشعروالنحو +الشعرواي +الشعري +الشعرية +الشعـري +الشعلة +الشعوب +الشعور +الشعورية +الشعير +الشعيرة +الشـفّاف +الشفاء +الشفاعة +الشفاف +الشفافة +الشفافية +الشفاه +الشفة +الشفتان +الشفتين +الشفر +الشفرة +الشفروليت +الشفط +الشفق +الشفقة +الشفهي +الشفهية +الشفوية +الشفيف +الشق +الشقاء +الشقة +الشقر +الشقعة +الشقق +الشقوق +الشقي +الشقيري +الشقيق +الشقيقات +الشقيقة +الشقيقتين +الشقيقُ +الشقين +الشقّ +الشك +الشكاوى +الشكر +الشكل +الشكلانية +الشكلي +الشكلية +الشكليون +الشكوك +الشكوى +الشكي +الشكّ +الشلابي +الشلاّل +الشلل +الشللي +الشللية +الشم +الشماتة +الشماعين +الشمال +الشمالى +الشمالي +الشمالية +الشماليون +الشماليين +الشمس +الشمسي +الشمسية +الشمسيين +الشمع +الشمعة +الشمعي +الشمعية +الشمل +الشموخ +الشموس +الشمول +الشمولية +الشمي +الشمية +الشناوي +الشنتريني +الشنفرى +الشنقيطي +الشنيعة +الشهادات +الشهادة +الشهد +الشهداء +الشهر +الشهرة +الشهرستاني +الشهري +الشهرية +الشهرين +الشهم +الشهوات +الشهود +الشهور +الشهي +الشهية +الشهيد +الشهير +الشهيرة +الشهيرين +الشهيق +الشوائب +الشواذ +الشوارد +الشوارع +الشواطئ +الشوال +الشواهد +الشور +الشورى +الشوط +الشوف +الشوق +الشوك +الشوكة +الشوكولاتة +الشوكي +الشوكية +الشيء +الشياطين +الشيب +الشيباني +الشيبة +الشيخ +الشيخان +الشيخة +الشيخوخة +الشيراتون +الشيرازية +الشيشة +الشيطان +الشيطانية +الشيعي +الشيف +الشيفرة +الشيقة +الشيكات +الشيوخ +الشيوع +الشيوعى +الشيوعي +الشيوعية +الشيوعيون +الشُعب +الشّبيهة +الشّخصيّة +الشّرق +الشّرقيّة +الشّطف +الشّهيّة +الشَّرف +الشَّعر +الشَّهامة +الصائب +الصائم +الصائمون +الصائمين +الصابر +الصابرة +الصابورة +الصابون +الصابوني +الصاحب +الصاخب +الصاخبة +الصادات +الصادر +الصادرات +الصادران +الصادرة +الصادق +الصادقة +الصادقين +الصارخ +الصارخة +الصارم +الصارمة +الصاروج +الصاروخ +الصاروخية +الصاعد +الصاعقة +الصافي +الصافية +الصافيتان +الصالات +الصالة +الصالح +الصالحات +الصالحة +الصالحين +الصالون +الصامت +الصامتة +الصامدة +الصانع +الصبا +الصباح +الصباحى +الصباحية +الصبار +الصبايا +الصبح +الصبحُ +الصبر +الصبور +الصبورة +الصبي +الصبيان +الصبيانية +الصبيانْ +الصبية +الصبيين +الصبّاح +الصبّار +الصح +الصحابة +الصحابي +الصحابية +الصحارى +الصحاري +الصحاف +الصحافة +الصحافي +الصحافيين +الصحبة +الصحة +الصحراء +الصحراوي +الصحراوية +الصحـراء +الصحف +الصحفى +الصحفي +الصحفيات +الصحفية +الصحفيين +الصحن +الصحو +الصحوة +الصحون +الصحي +الصحية +الصحيح +الصحيحة +الصحيحين +الصحيفة +الصحيّة +الصحيّون +الصحّة +الصخب +الصخر +الصخرة +الصخرةِ +الصخري +الصخرية +الصخور +الصد +الصدأ +الصدارة +الصداع +الصداق +الصداقات +الصداقة +الصدام +الصدامي +الصدامية +الصدد +الصدر +الصدري +الصدرية +الصدع +الصدف +الصدفة +الصدق +الصدقات +الصدمات +الصدمة +الصدور +الصدوق +الصدى +الصديد +الصديق +الصديقة +الصديقين +الصراحة +الصراخ +الصراصير +الصراط +الصراع +الصراعات +الصراف +الصرافة +الصرامة +الصرب +الصربية +الصرة +الصرح +الصرخة +الصرصر +الصرع +الصرف +الصروح +الصريح +الصريحة +الصرّة +الصعاب +الصعاليك +الصعب +الصعبة +الصعداء +الصعلوك +الصعوبات +الصعوبة +الصعود +الصعيد +الصعيدي +الصعيدين +الصــحـــة +الصـــحــــيح +الصف +الصفا +الصفاء +الصفات +الصفار +الصفاق +الصفة +الصفتان +الصفح +الصفحات +الصفحة +الصفر +الصفراء +الصفرة +الصفرية +الصفصاف +الصفعة +الصفقات +الصفن +الصفوة +الصفوف +الصفيح +الصفيحات +الصقر +الصقعبي +الصقلي +الصقلية +الصقليين +الصقلّي +الصقور +الصقيع +الصقيل +الصقيلة +الصلابة +الصلاة +الصلات +الصلاح +الصلاحيات +الصلاحية +الصلب +الصلبة +الصلة +الصلح +الصلصال +الصلصالية +الصلوات +الصليب +الصليبي +الصليبية +الصليبين +الصليبيون +الصليبيين +الصمامات +الصمت +الصملاخ +الصملاخية +الصمم +الصمود +الصميم +الصميمة +الصنابير +الصناديقيين +الصنارة +الصناع +الصناعات +الصناعة +الصناعى +الصناعي +الصناعية +الصناعيين +الصنبور +الصندل +الصندوق +الصنع +الصنعاني +الصنعية +الصنم +الصنوبر +الصنوبرية +الصنيع +الصهاينة +الصهبجية +الصهريج +الصهيوني +الصهيونية +الصهيونيين +الصواب +الصواريخ +الصوان +الصوانة +الصوت +الصوتي +الصوتية +الصوديوم +الصور +الصورة +الصورتين +الصوري +الصورية +الصوف +الصوفي +الصوفية +الصوفيين +الصولات +الصولو +الصوم +الصويا +الصياح +الصياد +الصيادلة +الصيادون +الصيادين +الصيارفة +الصيام +الصيان +الصيانة +الصيت +الصيحة +الصيد +الصيداوي +الصيدلاني +الصيدلانية +الصيدلة +الصيدلي +الصيدليات +الصيدلية +الصيرة +الصيف +الصيفى +الصيفي +الصيفية +الصين +الصيني +الصينية +الصينيتين +الصينيون +الصينيين +الصينييين +الصيوان +الصيّاح +الصّبيحة +الصّحي +الصّحّة +الصّحّيّة +الصّدر +الصّين +الصَّالحات +الصَّالحة +الصَّالحين +الصَّبر +الصَّلاَةَ +الصِّنْعة +الضأن +الضئيل +الضئيلة +الضائع +الضائعة +الضابط +الضاجة +الضاجّة +الضاحك +الضاحكة +الضاد +الضار +الضاربات +الضاربة +الضارة +الضارية +الضالة +الضالعين +الضام +الضامة +الضاوية +الضباب +الضباط +الضبب +الضبط +الضجة +الضجيج +الضحايا +الضحك +الضحكات +الضحل +الضحلة +الضحى +الضحية +الضحيّة +الضخامة +الضخم +الضخمة +الضد +الضدية +الضر +الضرائب +الضراعة +الضرب +الضربة +الضرر +الضرورات +الضرورة +الضروري +الضروريات +الضرورية +الضريبة +الضريبي +الضريح +الضرير +الضعاف +الضعف +الضعفاء +الضعيف +الضعيفة +الضفادع +الضفاف +الضفة +الضفتين +الضفدعة +الضلال +الضلع +الضماد +الضمادات +الضمان +الضمانات +الضمنية +الضموري +الضمير +الضنك +الضنى +الضوء +الضوئي +الضوئية +الضوابط +الضواحي +الضوضاء +الضياء +الضياع +الضيافة +الضيف +الضيق +الضيقة +الضيوف +الضيّق +الضَّعيف +الط +الطائر +الطائرات +الطائرة +الطائعون +الطائف +الطائفة +الطائفتين +الطائفي +الطائفية +الطائلة +الطابع +الطابق +الطابور +الطابوقات +الطاحونة +الطار +الطارئة +الطارئين +الطارقون +الطازجة +الطاسة +الطاعات +الطاعة +الطاعن +الطاعنون +الطاعون +الطافح +الطافي +الطافية +الطاقات +الطاقة +الطاقةالعالمية +الطاقم +الطاقي +الطاقية +الطالب +الطالبات +الطالبان +الطالبانيين +الطالبة +الطالبـان +الطالبية +الطالع +الطالعة +الطامة +الطامعين +الطاهر +الطاهرات +الطاهرة +الطاهرتين +الطاهيين +الطاولات +الطاولة +الطاووس +الطب +الطبائع +الطباخ +الطباشير +الطباع +الطباعة +الطبخ +الطبري +الطبع +الطبعات +الطبعة +الطبق +الطبقات +الطبقة +الطبقي +الطبقية +الطبل +الطبول +الطبولوجيا +الطبي +الطبيب +الطبية +الطبيةالفوريّة +الطبيعة +الطبيعى +الطبيعي +الطبيعيأن +الطبيعيات +الطبيعية +الطبيعيين +الطبّيّة +الطحالب +الطحلب +الطحين +الطرائق +الطرابيش +الطراز +الطرازين +الطرب +الطرح +الطرد +الطرز +الطرزي +الطرف +الطرفان +الطرفة +الطرفين +الطرق +الطرقات +الطرقية +الطروحات +الطرود +الطري +الطرية +الطريحي +الطريف +الطريفة +الطريق +الطريقة +الطريقتين +الطريقِ +الطعام +الطعم +الطعوم +الطفح +الطفرات +الطفرة +الطفل +الطفلان +الطفلة +الطفلية +الطفو +الطفولة +الطفولية +الطفيف +الطفيل +الطفيلي +الطفيليات +الطفيلية +الطفّ +الطقس +الطقوس +الطقوسي +الطلاء +الطلاءات +الطلاب +الطلابي +الطلابية +الطلاسم +الطلاق +الطلب +الطلبات +الطلبة +الطلبية +الطلسم +الطلعة +الطلق +الطلقاتُ +الطلوعين +الطليان +الطليعة +الطليعي +الطليق +الطليقة +الطلّ +الطمأنينة +الطماطم +الطمع +الطموح +الطموحات +الطموحة +الطموحين +الطمي +الطمّاعين +الطناحي +الطنطاوي +الطهاة +الطهطاوي +الطهي +الطوائف +الطوابع +الطوابق +الطوابير +الطواجن +الطوارئ +الطواف +الطوافة +الطوباسي +الطوباوية +الطود +الطور +الطوعي +الطوعية +الطوفان +الطول +الطولونية +الطولية +الطوى +الطويل +الطويلة +الطويلتين +الطيات +الطيارين +الطيب +الطيبة +الطيبين +الطير +الطيران +الطيرة +الطيفي +الطين +الطيني +الطيور +الطّالب +الطّبّيّة +الطّفح +الطّلبة +الظالم +الظالمة +الظامئة +الظاهر +الظاهرة +الظاهرتين +الظاهري +الظاهرية +الظباء +الظرف +الظرفاء +الظرفي +الظرفية +الظروف +الظريفة +الظفر +الظل +الظلال +الظلام +الظلامات +الظلامية +الظلف +الظلم +الظلمات +الظلمة +الظليل +الظليلة +الظلّ +الظمأ +الظمأى +الظن +الظهارية +الظهر +الظهران +الظهرية +الظهور +الظهيرة +الظواهر +الع +العائد +العائدات +العائدة +العائدين +العائق +العائل +العائلات +العائلة +العائلةِ +العائلي +العائلية +العائمة +العابثين +العابد +العابدين +العابر +العابرة +العابرين +العاتية +العاج +العاجز +العاجزين +العاجل +العاجلة +العاجية +العاجيّة +العادات +العادة +العادل +العادلة +العادم +العادي +العادية +العاديون +العاديين +العار +العاربة +العارض +العارف +العارفية +العارفين +العارم +العارمة +العاري +العارية +العازف +العازفون +العازفين +العاشر +العاشرة +العاشق +العاشقين +العاص +العاصف +العاصفة +العاصمة +العاصي +العاطفة +العاطفي +العاطفية +العاطل +العاطلين +العافية +العاق +العاقل +العاقلة +العاكسة +العالق +العالقة +العالم +العالمة +العالمى +العالمي +العالمية +العالميتين +العالمين +العالميون +العالميين +العالي +العاليات +العالية +العالِم +العام +العامة +العامةِ +العامر +العامرات +العامرة +العامري +العامل +العاملات +العاملان +العاملة +العاملون +العاملي +العاملين +العامليين +العامود +العامي +العامية +العامين +العامّة +العاهرة +العاهل +العبء +العباءات +العباءة +العبابي +العباد +العبادات +العبادة +العبار +العبارات +العبارة +العباس +العباسي +العباسية +العباسيين +العبث +العبثي +العبد +العبدالذي +العبداللطيف +العبر +العبرات +العبرانيين +العبري +العبرية +العبسي +العبق +العبقة +العبقري +العبقريات +العبقرية +العبقريتين +العبوات +العبوة +العبودية +العبور +العبيد +العبيدلي +العبيدى +العتاد +العتاهية +العتب +العتبات +العتبة +العتمة +العته +العتيدة +العتيق +العتيقة +العثرات +العثرة +العثمان +العثماني +العثمانية +العثمانيين +العثور +العجائب +العجاب +العجالة +العجب +العجز +العجزة +العجلات +العجلة +العجوز +العجول +العجيب +العجيبة +العجيري +العد +العداء +العدائية +العداد +العدالة +العداوة +العداوي +العدة +العدد +العددى +العددي +العددية +العدس +العدسات +العدسة +العدل +العدم +العدنانية +العدنانيين +العدو +العدوان +العدواني +العدوانية +العدول +العدوى +العدوية +العديد +العديدة +العديدين +العذاب +العذارى +العذب +العذبة +العذر +العذراء +العذريين +العذل +العذوبة +العراء +العراءِ +العرائض +العرابي +العرابية +العرافة +العراق +العراقة +العراقي +العراقية +العراقيل +العراقين +العراقيون +العراقيين +العراك +العرب +العربات +العربان +العربة +العربى +العربي +العربيان +العربية +العربيين +العرج +العرس +العرش +العرض +العرضات +العرضاني +العرضي +العرضيين +العرعر +العرف +العرفاني +العرفي +العرفية +العرق +العرقسوس +العرقي +العرقية +العرن +العروبة +العروبية +العروبيون +العروبيين +العروس +العروسان +العروسة +العروسين +العروض +العروق +العريبي +العريس +العريضة +العريف +العريق +العريقة +العريقةِ +العرَق +العز +العزاء +العزائم +العزباء +العزبي +العزة +العزف +العزل +العزلة +العزم +العزوف +العزيز +العزيزة +العزيزية +العزيمة +العساف +العساكر +العسف +العسكر +العسكرى +العسكري +العسكرية +العسكريين +العسل +العسلية +العسليتين +العسير +العش +العشاء +العشائر +العشائري +العشابين +العشاق +العشاقْ +العشب +العشبي +العشبية +العشة +العشر +العشرات +العشرة +العشرون +العشرين +العشرينيات +العشش +العشــــرين +العشق +العشماوي +العشوائي +العشوائية +العشّاق +العصا +العصابات +العصابة +العصارة +العصاري +العصافير +العصامي +العصامية +العصاميين +العصب +العصبان +العصبة +العصبونات +العصبي +العصبية +العصر +العصرى +العصرية +العصرين +العصفور +العصفوران +العصفورة +العصماء +العصور +العصيان +العصيبة +العصير +العض +العضال +العضب +العضدي +العضلات +العضلة +العضلي +العضلية +العضو +العضوات +العضوة +العضوية +العطاء +العطاءَ +العطار +العطارة +العطارون +العطارين +العطاس +العطايا +العطب +العطر +العطرة +العطرية +العطس +العطش +العطشان +العطشى +العطف +العطل +العطلات +العطلة +العطور +العطورات +العظاءات +العظام +العظم +العظماء +العظمة +العظمى +العظمي +العظمية +العظميين +العظيم +العظيمة +العـثور +العـفش +العفاف +العفة +العفريت +العفش +العفو +العفولة +العفوي +العفوية +العفيف +العقا +العقائد +العقائدي +العقائدية +العقاب +العقاد +العقار +العقارات +العقارب +العقاري +العقارية +العقاقير +العقب +العقبات +العقبان +العقبة +العقبي +العقد +العقدالتي +العقدة +العقدي +العقديات +العقدية +العقدين +العقرب +العقل +العقلاء +العقلاني +العقلانية +العقلانيين +العقلــــية +العقلي +العقلية +العقم +العقوبات +العقوبة +العقود +العقول +العقيد +العقيدة +العقيق +العقيلي +العقيم +العقّاد +العكاز +العكر +العكرماوي +العكس +العكسي +العكسية +العكيلي +العلا +العلاء +العلاج +العلاجات +العلاجي +العلاجية +العلاقات +العلاقة +العلامات +العلامة +العلان +العلاني +العلاوي +العلايلي +العلاّمة +العلب +العلبة +العلة +العلـــمـــاء +العلــم +العلف +العلم +العلماء +العلماني +العلمانية +العلمانيون +العلمانيين +العلمنة +العلمى +العلمي +العلمية +العلمين +العلميين +العلني +العلو +العلوج +العلوم +العلوي +العلوية +العلويين +العلوّ +العلى +العلي +العليا +العلية +العليل +العليلة +العم +العمائر +العمائم +العماد +العمادة +العمارات +العمارة +العمارنة +العمال +العمالة +العمالقة +العمالية +العمامة +العماني +العمانية +العمانيون +العمانيين +العمة +العمد +العمدة +العمدي +العمر +العمران +العمراني +العمرانية +العمرة +العمري +العمرية +العمرِ +العمق +العمل +العملاء +العملات +العملاق +العملاقة +العملاقين +العملة +العملي +العمليات +العملية +العملين +العمود +العمودي +العمولة +العموم +العمومي +العمومية +العمى +العمياء +العميد +العمير +العميق +العميقة +العميل +العناء +العنابي +العناصر +العناق +العنان +العناوين +العناية +العنايةالمناسبة +العنب +العنبر +العنجهية +العند +العندليب +العنصر +العنصري +العنصرية +العنصرين +العنف +العنق +العنقوديات +العنقودية +العنكبوت +العنكبوتي +العنكبوتية +العنوان +العنود +العنيد +العنيدة +العنيف +العنيفة +العهد +العهدة +العهدين +العهود +العوا +العوائد +العوائق +العوائل +العوادم +العوار +العوارض +العواصف +العواصم +العواطف +العواقب +العوالق +العوامات +العوامل +العود +العودة +العودُ +العوز +العولمة +العولمي +العولمية +العون +العويد +العويص +العيادات +العيادة +العيادي +العيار +العيارات +العيال +العيب +العيبين +العيد +العيسائى +العيسائي +العيسى +العيش +العين +العينات +العينان +العينة +العيني +العينية +العينيتين +العينين +العيوب +العيون +العيِّنات +العَشاء +العُجْب +العُرْس +العُظمى +العِليَّات +الـ +الـخَلْق +الـخُلُق +الـذين +الـشئون +الــتــســعــون +الـمأمـون +الـمأمون +الـمؤمنين +الـماجدة +الـمال +الـمتزوِّدة +الـمدرسة +الـمرأة +الـمرافق +الـمسبُوك +الـمصيبة +الـمصُونة +الـمعروف +الـمفاخر +الـمكارم +الـمكنُونة +الـمكْرُمة +الـملهوفين +الـملهُوف +الـمنزلة +الـمنصور +الـمهيب +الـمياه +الـمُوقنة +الـمَّرات +الـهمَّة +الف +الفأر +الفأس +الفؤاد +الفئات +الفئة +الفئران +الفئوي +الفئوية +الفاء +الفائت +الفائدة +الفائز +الفائزة +الفائزين +الفائض +الفائق +الفائقة +الفاتح +الفاتحة +الفاتحون +الفاتحين +الفاترينة +الفاتك +الفاتنة +الفاتيكان +الفاجع +الفاجعة +الفاحش +الفاحشة +الفاحص +الفاحم +الفاخر +الفاخرة +الفادح +الفادحة +الفارابي +الفارس +الفارسي +الفارسية +الفارض +الفارعة +الفارق +الفارقة +الفاروا +الفاروق +الفاروقية +الفاسد +الفاسدة +الفاسي +الفاشل +الفاشلين +الفاشيون +الفاشيين +الفاصل +الفاصلة +الفاضل +الفاضلة +الفاطمي +الفاطمية +الفاطميون +الفاطميين +الفاعل +الفاعلة +الفاعلية +الفاعلين +الفاقد +الفاكس +الفاكسات +الفاكهة +الفاكو +الفالق +الفانتوم +الفانية +الفاو +الفايكينك +الفتاة +الفتات +الفتاتان +الفتاح +الفتاكة +الفتاوى +الفتح +الفتحات +الفتحة +الفترات +الفترة +الفتق +الفتن +الفتنة +الفتوحات +الفتوق +الفتوى +الفتى +الفتي +الفتيا +الفتيات +الفتيان +الفتية +الفتّاك +الفتّان +الفجة +الفجر +الفجل +الفجوات +الفجوة +الفحام +الفحشاء +الفحص +الفحل +الفحم +الفحمية +الفحوص +الفحوصات +الفحول +الفخ +الفخاخ +الفخار +الفخارية +الفخامة +الفخذ +الفخذين +الفخر +الفخرانية +الفخرية +الفخم +الفخمة +الفخِّ +الفداء +الفدائية +الفدائيين +الفدرالي +الفدرالية +الفذ +الفذة +الفذلكة +الفذّة +الفراء +الفرائس +الفرائين +الفرات +الفرادة +الفرار +الفراز +الفراسة +الفراش +الفراشات +الفراشة +الفراعنة +الفرافير +الفراق +الفرانكفونيين +الفرانكوفونية +الفرج +الفرجة +الفرح +الفرحة +الفرخ +الفرد +الفردانية +الفردوس +الفردوسي +الفردوسية +الفردي +الفردية +الفرس +الفرسان +الفرش +الفرشاة +الفرص +الفرصة +الفرضية +الفرع +الفرعون +الفرعوني +الفرعونية +الفرعية +الفرفرية +الفرفور +الفرق +الفرقاء +الفرقة +الفرما +الفرن +الفرنة +الفرنج +الفرنجة +الفرنجي +الفرنجية +الفرنس +الفرنسي +الفرنسية +الفرنسيون +الفرنسيين +الفروسية +الفروض +الفروع +الفروق +الفروقات +الفريد +الفريدة +الفريدو +الفرير +الفريسة +الفريضة +الفريق +الفريقان +الفريقين +الفريكة +الفزع +الفزعات +الفساد +الفستق +الفسطاط +الفسيح +الفسيحة +الفسيفساء +الفشل +الفصائل +الفصام +الفصحى +الفصل +الفصلي +الفصلية +الفصلين +الفصول +الفصيح +الفصيحة +الفصيلة +الفضاء +الفضاءات +الفضائل +الفضائى +الفضائي +الفضائيات +الفضائية +الفضة +الفضفاضة +الفضل +الفضلاء +الفضلات +الفضلي +الفضول +الفضولية +الفضوليين +الفضي +الفضية +الفضيحة +الفضيل +الفضيلة +الفطر +الفطرة +الفطري +الفطريات +الفطرية +الفطور +الفطينُ +الفظ +الفظيع +الفعال +الفعالة +الفعاليات +الفعالية +الفعل +الفعلة +الفعلي +الفعلية +الفعليين +الفعّال +الفعّالة +الفعَّال +الفعَّالة +الفــــهم +الفقار +الفقارية +الفقاعي +الفقد +الفقر +الفقراء +الفقرات +الفقرة +الفقري +الفقرية +الفقمة +الفقه +الفقهاء +الفقهي +الفقهية +الفقير +الفقيرة +الفقيه +الفك +الفكاهة +الفكاهي +الفكر +الفكرة +الفكري +الفكرية +الفل +الفلاح +الفلاحون +الفلاحية +الفلاحين +الفلاسفة +الفلاش +الفلامنجو +الفلاني +الفلبين +الفلج +الفلجين +الفلس +الفلسطيني +الفلسطينية +الفلسطينين +الفلسطينيون +الفلسطينيين +الفلسفات +الفلسفة +الفلسفي +الفلسفية +الفلفل +الفلقة +الفلك +الفلكلور +الفلكلوري +الفلكلورية +الفلكي +الفلكيات +الفلكية +الفلل +الفلوجة +الفلوس +الفليبين +الفليفلة +الفليم +الفم +الفمتو +الفموي +الفموية +الفن +الفناء +الفنادق +الفنار +الفنان +الفنانات +الفنانة +الفنانتين +الفنانون +الفنانين +الفنانيين +الفنجان +الفندق +الفندقة +الفندقى +الفندقية +الفندقين +الفنون +الفنى +الفني +الفنية +الفنين +الفنيون +الفنيين +الفهارس +الفهد +الفهرس +الفهرسة +الفهرست +الفهم +الفهمي +الفوائد +الفوائض +الفواح +الفواخير +الفوارق +الفواصل +الفواكه +الفوج +الفور +الفوران +الفورمول +الفوري +الفوز +الفوسفات +الفوسفور +الفوسفورية +الفوضوي +الفوضويون +الفوضى +الفوط +الفوقا +الفوقية +الفول +الفولاذ +الفولتاج +الفولكلوري +الفولكلورية +الفونسو +الفوّاحة +الفياجرا +الفياض +الفيبرينوجينات +الفيتاميرات +الفيتامين +الفيتامينات +الفيتاينات +الفيحاء +الفيدرالي +الفيدرالية +الفيديو +الفيرمونات +الفيروزي +الفيروس +الفيروسات +الفيروسي +الفيروسية +الفيروسين +الفيزا +الفيزوف +الفيزياء +الفيزيائي +الفيزيائية +الفيزيائيين +الفيزيقي +الفيزيقية +الفيزيولوجي +الفيزيولوجية +الفيسيولوجيا +الفيشاوي +الفيصل +الفيصلية +الفيض +الفيضان +الفيضانات +الفيل +الفيلاريا +الفيلة +الفيلسوف +الفيلم +الفيمتوثانية +الفين +الفينايل +الفينة +الفينقية +الفينيقي +الفينيقية +الفينيقيون +الفينيقيين +الفيوري +الفيوم +الفَنَاء +الفُسَح +الفِعَال +القائد +القائدة +القائل +القائلة +القائلين +القائم +القائمة +القائمون +القائمين +القابع +القابعات +القابعة +القابعين +القابل +القابلة +القابليات +القابلية +القات +القاتل +القاتلة +القاتمة +القاحلة +القادة +القادر +القادرة +القادرون +القادرين +القادسية +القادم +القادمة +القادمون +القادمين +القاديانية +القاذفات +القاذورات +القارئ +القارئات +القارئة +القارات +القارب +القارة +القارس +القاسم +القاسي +القاسية +القاش +القاشان +القاصرة +القاصرين +القاضي +القاضية +القاطرات +القاطع +القاطعة +القاطن +القاطنة +القاع +القاعات +القاعة +القاعدة +القاعدية +القافلة +القالب +القامة +القانون +القانوني +القانونية +القانية +القاهرة +القب +القبائل +القباب +القبب +القبة +القبح +القبر +القبرصى +القبرصية +القبض +القبضة +القبطان +القبطي +القبطية +القبعات +القبعة +القبل +القبلة +القبلتين +القبلي +القبلية +القبور +القبول +القبيح +القبيحة +القبيل +القبيلة +القبّة +القتال +القتل +القتلة +القتلى +القتيل +القتيلُ +القحط +القحطانى +القحطاني +القحطانية +القحطانيين +القد +القداسة +القدامى +القدر +القدرات +القدرة +القدرثم +القدرية +القدس +القدسي +القدسية +القدم +القدماء +القدمين +القدوة +القدية +القدير +القديس +القديسة +القديسين +القديم +القديمة +القديمين +القذائف +القذارة +القذافي +القذرة +القذرون +القذى +القذيفة +القر +القرآن +القرآني +القرآنية +القراء +القراءات +القراءة +القراءةَ +القرائية +القرابة +القرابين +القراد +القرار +القرارات +القرارت +القرارين +القراصنة +القراض +القراقوز +القران +القرب +القربى +القرحات +القرحة +القرد +القردة +القردوح +القرش +القرشي +القرشيين +القرص +القرصي +القرض +القرضاوي +القرطاجي +القرطبي +القرع +القرعان +القرعة +القرعون +القرفة +القرفصاء +القرفصة +القرم +القرن +القرنة +القرنفلة +القرني +القرنية +القرنين +القرنيّة +القره +القروش +القروض +القرون +القروي +القروية +القرويون +القرى +القريب +القريبة +القريبون +القريبين +القرية +القريشى +القرين +القرينات +القرّاء +القرَّاء +القز +القزم +القس +القسام +القسري +القسطنطينية +القسم +القسمين +القسوة +القسَّام +القش +القشة +القشرة +القشريات +القشور +القص +القصائد +القصاب +القصابين +القصار +القصاص +القصاصات +القصب +القصبات +القصبة +القصبجي +القصبي +القصة +القصتين +القصد +القصدير +القصديري +القصديرية +القصر +القصرين +القصص +القصصي +القصصية +القصف +القصور +القصوى +القصيبي +القصيد +القصيدة +القصير +القصيرة +القصيم +القصّ +القصّة +القضاء +القضائية +القضاة +القضايا +القضبان +القضية +القضيتين +القط +القطائع +القطار +القطارات +القطارين +القطاع +القطاعات +القطاعين +القطان +القطانين +القطب +القطبي +القطبية +القطبيتين +القطبين +القطة +القطر +القطرات +القطران +القطرة +القطري +القطرية +القطط +القطع +القطعة +القطعي +القطن +القطني +القطنية +القطيع +القطيعة +القعدة +القــرن +القــمر +القفر +القفز +القفزة +القفص +القفطي +القفل +القفّازات +القلائل +القلادة +القلاع +القلاعية +القلاقل +القلانسي +القلب +القلبية +القلة +القلت +القلطقجي +القلعة +القلعتان +القلعتين +القلق +القلقة +القلقشندي +القلقلة +القلم +القلماوي +القلنسوة +القلوب +القلوي +القلي +القليل +القليلات +القليلة +القليلون +القمارى +القماش +القماشي +القماشية +القمامة +القمة +القمح +القمر +القمري +القمريات +القمرية +القمع +القمعي +القمقم +القمم +القميص +القمّة +القنابل +القناة +القناتين +القناديل +القناص +القناصلة +القناطر +القناع +القناعات +القناعة +القنافذ +القنال +القنبلة +القنصل +القنصلية +القنفذ +القنن +القنوات +القنواتي +القنينات +القنّاصة +القهر +القهري +القهوة +القوابل +القوات +القوارب +القوارض +القواسم +القواسمي +القواعد +القوافل +القواقع +القوالب +القوام +القوامة +القوانين +القوة +القوت +القوتلي +القوتين +القورساوي +القوس +القوصي +القوطية +القوقاز +القوقازية +القوقعة +القوقعين +القول +القولون +القولين +القوم +القومى +القومي +القوميات +القومية +القوميون +القوميين +القوني +القوى +القوي +القوية +القويم +القويين +القيادات +القيادة +القيادية +القياس +القياسات +القياسي +القياسية +القيام +القيامة +القيثارة +القيد +القيس +القيسي +القيصري +القيصرية +القيظ +القيعان +القيقب +القيلات +القيلة +القيم +القيمة +القيمري +القيمرية +القيمي +القيمية +القيود +القيوم +القيّمون +القيِّم +القَسَم +القَصَّار +القَطان +القَلْت +القَيْد +القُبلة +القِصَر +الك +الكآبة +الكأس +الكئوس +الكئيبة +الكائن +الكائنات +الكائنة +الكائنين +الكابتة +الكابوس +الكابوسية +الكابيتوليو +الكاتب +الكاتبة +الكاتدرائية +الكاثارية +الكاثاريين +الكاثرة +الكاثودية +الكاثوليك +الكاثوليكي +الكاثوليكية +الكادحين +الكادر +الكاديلاك +الكاذب +الكاذبة +الكارت +الكارتون +الكارتيزية +الكارثة +الكاردينال +الكارهون +الكارهين +الكاريبى +الكاريبي +الكاريكاتير +الكاسر +الكاسيت +الكاشف +الكافور +الكافي +الكافية +الكاكاو +الكالسيوم +الكامل +الكاملة +الكامن +الكامنة +الكامنَ +الكامي +الكاميرا +الكاميرات +الكانجارو +الكانديدا +الكانولا +الكاهنات +الكبائر +الكبار +الكبت +الكبد +الكبدية +الكبر +الكبرى +الكبري +الكبرياء +الكبريت +الكبريتية +الكبريين +الكبير +الكبيرات +الكبيران +الكبيرة +الكبيرتين +الكبيرين +الكبيسي +الكتاب +الكتابات +الكتابة +الكتابتين +الكتابية +الكتابين +الكتان +الكتانية +الكتب +الكتبة +الكتبي +الكتبُ +الكترونية +الكتف +الكتفين +الكتل +الكتلة +الكتيب +الكتيبات +الكتيبة +الكتّاب +الكتَّاب +الكثافة +الكثبان +الكثة +الكثر +الكثرة +الكثيب +الكثير +الكثيرات +الكثيرة +الكثيرمن +الكثيرون +الكثيرين +الكثيف +الكثيفة +الكثّ +الكثّة +الكحل +الكحلاوى +الكحلاوي +الكحلي +الكحول +الكحولي +الكحوليات +الكحّة +الكدمات +الكذب +الكرابينابي +الكراسي +الكرام +الكرامة +الكراهية +الكربلائي +الكربون +الكرة +الكرتون +الكرتين +الكردية +الكرز +الكرسي +الكرش +الكرم +الكرمل +الكرنفالية +الكرنك +الكروان +الكروز +الكروم +الكروموسومات +الكروي +الكريات +الكريب +الكريم +الكريمات +الكريمة +الكرينيولي +الكريهة +الكرّ +الكساح +الكسار +الكسالى +الكساند +الكساوي +الكسكسي +الكسل +الكسوة +الكسور +الكسول +الكسولة +الكسيرة +الكسيس +الكشافة +الكشط +الكشف +الكشفية +الكشك +الكشميري +الكشميرية +الكشميريين +الكشوف +الكعبة +الكعبي +الكعك +الكعكيين +الكــــائنات +الكـندية +الكف +الكفؤة +الكفاءات +الكفاءة +الكفاح +الكفار +الكفاف +الكفالة +الكفاوين +الكفايات +الكفاية +الكفتيين +الكفر +الكفراوي +الكفيف +الكفيلة +الكفين +الكل +الكلاب +الكلاسيكي +الكلاسيكية +الكلاسيكيون +الكلاسيين +الكلام +الكلامي +الكلامية +الكلاّبات +الكلب +الكلبي +الكلبيّ +الكلدانيين +الكلس +الكلسمية +الكلفة +الكلم +الكلمات +الكلمة +الكلوب +الكلور +الكلوروإيثين +الكلوروكينين +الكلوي +الكلوية +الكلى +الكلي +الكليات +الكليانية +الكلية +الكليم +الكلّي +الكلِّي +الكم +الكمادات +الكمال +الكمامة +الكمان +الكمبيوتر +الكمبيوترات +الكمبيوترز +الكمبيوترلساعات +الكمبيوترية +الكميات +الكمية +الكميت +الكميّ +الكمّ +الكنائس +الكناري +الكنانات +الكنانة +الكناني +الكنتربري +الكندي +الكندية +الكنديين +الكنز +الكنسي +الكنسية +الكنعانية +الكنعانيون +الكنعانيين +الكنوز +الكنيسة +الكنيست +الكهرب +الكهرباء +الكهربائي +الكهربائية +الكهربائيين +الكهربية +الكهرلة +الكهروبصريات +الكهروضوئي +الكهروكيميائي +الكهف +الكهل +الكهلة +الكهنة +الكهنوتية +الكهوف +الكهول +الكهولة +الكوات +الكوادر +الكوارث +الكواري +الكواسر +الكوافي +الكوافيرة +الكواكب +الكواكبي +الكواليس +الكوب +الكوبالت +الكوبرا +الكوبونات +الكوبي +الكوبيا +الكوبية +الكوبيون +الكوبيين +الكوت +الكوثر +الكود +الكورتيزول +الكورتيزون +الكورتيزونات +الكورتيزونية +الكورس +الكورنيش +الكورونا +الكورونافيرس +الكوفة +الكوكائين +الكوكاكولا +الكوكايين +الكوكب +الكوكبة +الكولاجين +الكولدج +الكولسترول +الكولونيالي +الكولونيل +الكوليج +الكوليرا +الكوم +الكومبيوتر +الكومبيوترات +الكوميدي +الكوميديا +الكوميدية +الكون +الكونت +الكونجرس +الكونكورد +الكوني +الكونية +الكوهيبا +الكوى +الكويت +الكويتي +الكويتيات +الكويتية +الكويتيين +الكيان +الكيانات +الكيبور +الكيس +الكيسي +الكيف +الكيفية +الكيفيّ +الكيلاني +الكيلومترات +الكيما +الكيمائي +الكيمائية +الكيماويات +الكيماوية +الكيمياء +الكيميائي +الكيميائية +الكيميائيون +الكيميائيين +الكينا +الكينين +الكَومة +الكُتلة +الكُتّاب +الكُرَماء +الكِبر +اللآلئ +اللؤلؤ +اللإنساني +اللا +اللاإرادية +اللاإقليدية +اللائبة +اللائحة +اللائق +اللائقة +اللائكية +اللائي +اللاتكافؤ +اللاتي +اللاتيني +اللاتينية +اللاجئ +اللاجئين +اللاجنسي +اللاحق +اللاحقة +اللاذع +اللاذقية +اللازم +اللازمة +اللازمةللقيام +اللازمن +اللازمين +اللاستيعاب +اللاسلكي +اللاسلكية +اللاشعور +اللاشيء +اللاصق +اللاصقة +اللاعب +اللاعبين +اللاعلمية +اللاعنصري +اللاعنف +اللاعودة +اللافت +اللافتات +اللافتة +اللافقاريات +اللافي +اللامبالاة +اللامتناهية +اللامجدية +اللامحدودة +اللامركزي +اللامسمى +اللامع +اللامعة +اللامعقول +اللامنتهية +اللامنطق +اللامنهجية +اللانمطي +اللانموذجي +اللانموذجية +اللانهائية +اللاهب +اللاهبة +اللاهثة +اللاهثتين +اللاهوت +اللاهوتيون +اللاواعي +اللاواقعي +اللاوعي +اللبائن +اللباس +اللبــــناني +اللبن +اللبنات +اللبناني +اللبنانية +اللبنانيون +اللبنانيين +اللبنة +اللبنية +اللبوس +اللبونة +اللبونيات +اللبيبة +اللتان +اللتر +اللتين +اللثام +اللثة +اللجاة +اللجان +اللجة +اللجج +اللجنة +اللجنتين +اللجنين +اللجوء +اللحاف +اللحاق +اللحامين +اللحظات +اللحظة +اللحم +اللحمة +اللحن +اللحوم +اللحى +اللحية +اللدائن +اللدائنية +اللدائنيين +اللدودة +اللذان +اللذة +اللذيذ +اللذيذة +اللذين +اللزج +اللزجة +اللزوجة +اللسان +اللسانيات +اللسانية +اللسع +اللسعات +اللص +اللصوص +اللصيق +اللصيقة +اللصين +اللطافة +اللطخة +اللطيف +اللعاب +اللعب +اللعبة +اللعبي +اللعن +اللعنات +اللعنة +اللعوب +اللعين +اللعينة +اللـــوحة +اللـه +اللف +اللفائف +اللفائفي +اللفظ +اللفظتين +اللفظين +اللقاء +اللقاءات +اللقاح +اللقاحات +اللقب +اللقطات +اللقمة +اللقى +اللماذا +اللماع +اللمحة +اللمس +اللمسات +اللمسة +اللمعان +اللمفاوية +اللمّاع +اللندني +اللندنية +اللنشات +الله +اللهاة +اللهاث +اللهاية +اللهب +اللهجات +اللهجة +اللهفة +اللهم +اللهو +اللهوب +اللهَ +اللهُ +اللهِ +اللواء +اللوائح +اللواتي +اللواط +اللوتس +اللوثة +اللوثرية +اللوح +اللوحات +اللوحة +اللوحــة +اللورد +اللوز +اللوزات +اللوزتين +اللوسيونات +اللوم +اللوموند +اللون +اللونان +اللوني +اللونية +اللويزة +اللي +اللياقة +الليالى +الليالي +الليبرالي +الليبرالية +الليبي +الليبيات +الليبية +الليبيدات +الليبيون +الليبيين +الليث +الليثي +الليدي +الليزر +الليزرية +الليسانس +الليطاني +الليفي +الليل +الليلة +الليلى +الليلي +الليلية +الليمفاوية +الليمون +الليمونادة +الليموند +الليونة +اللّهَ +اللَّبيبة +اللَّهو +اللَّهُ +اللَّهِ +الم +المآتة +المآذن +المآسي +المآقي +المآكل +المآل +المأتم +المأتى +المأثور +المأجورين +المأخوذة +المأدبة +المأزق +المأساة +المأساوي +المأساوية +المأكل +المأكولات +المألوف +المألوفة +المأمول +المأمون +المأمونة +المأهولة +المأوى +المؤاخاة +المؤاخذة +المؤامرة +المؤبد +المؤتلفة +المؤتمر +المؤتمرات +المؤثر +المؤثرات +المؤثرة +المؤثِّر +المؤجر +المؤجل +المؤجلة +المؤجّجة +المؤدلج +المؤدنين +المؤدي +المؤدية +المؤذن +المؤذنين +المؤذي +المؤذية +المؤرجات +المؤرخ +المؤرخون +المؤرخين +المؤسس +المؤسسات +المؤسسة +المؤسسي +المؤسسين +المؤسف +المؤسفة +المؤسّسات +المؤشر +المؤشرات +المؤطر +المؤقت +المؤقتة +المؤكد +المؤكسجة +المؤكسد +المؤلف +المؤلفات +المؤلفة +المؤلفون +المؤلفين +المؤلم +المؤلمة +المؤمثلة +المؤمل +المؤمن +المؤمنات +المؤمنة +المؤمنين +المؤهبة +المؤهل +المؤهلات +المؤهلة +المؤهلين +المؤول +المؤيد +المؤيدة +المئات +المئة +المئتين +المئذنة +المئوية +الما +الماء +المائة +المائتي +المائجة +المائدة +المائى +المائي +المائية +الماثل +الماثلة +الماجستير +الماحق +المادة +المادتين +المادي +المادية +الماديّة +المار +الماراثون +المارة +المارد +المارشال +المارق +الماركات +الماركة +الماركسي +الماركسية +المازندراني +المازني +الماسة +الماشية +الماضى +الماضي +الماضية +الماضيتين +الماضين +الماضيين +الماعز +المافيا +الماكدونالد +الماكر +الماكرة +الماكرو +الماكياج +الماكينات +الماكينة +المال +المالح +المالحة +المالطية +المالك +المالكة +المالي +المالية +الماليزي +الماليين +المانجو +المانح +المانحة +الماندرين +المانع +المانعة +المانوي +الماهر +الماهرة +الماهية +الماوراء +الماورائي +المايسترو +المباحث +المباحثات +المباحثية +المبادئ +المبادرات +المبادرة +المبادىء +المباراة +المبارك +المباركة +المباركية +المباريات +المباشر +المباشرة +المباعة +المبالاة +المبانى +المباني +المباهج +المبايض +المبتدئون +المبتدعة +المبتدعين +المبتذلات +المبتذلة +المبتسم +المبتعثون +المبتعثين +المبتعد +المبتعدة +المبتكر +المبتكرات +المبتكرة +المبتل +المبتلاة +المبتلة +المبثوثة +المبجل +المبجلة +المبحرين +المبخرة +المبدأ +المبدأين +المبدئي +المبدئية +المبدع +المبدعة +المبدعين +المبذول +المبرد +المبرر +المبررات +المبرمج +المبرّحة +المبسط +المبسطة +المبشر +المبشرات +المبشرة +المبشرين +المبشور +المبصرون +المبصرين +المبضع +المبطلين +المبطنة +المبعثرة +المبعوث +المبعوثة +المبكر +المبكرة +المبكى +المبكّرة +المبلل +المبللة +المبنى +المبني +المبنية +المبهجة +المبهرة +المبهمة +المبهورين +المبيت +المبيد +المبيدات +المبيض +المبيضات +المبيعات +المبيعة +المبين +المبيّضة +المتآكل +المتآلفة +المتآمرين +المتأثر +المتأثرة +المتأثّرة +المتأخر +المتأخرة +المتأصلين +المتألمة +المتأمل +المتأملين +المتأنية +المتأين +المتابع +المتابعة +المتاجر +المتاجرة +المتاح +المتاحة +المتاحـة +المتاحف +المتاخم +المتاخمة +المتاعب +المتانة +المتاهة +المتبادل +المتبادلة +المتباعدة +المتباينة +المتبرع +المتبرعين +المتبصر +المتبصرين +المتبع +المتبعة +المتبـــقـية +المتبقي +المتبقية +المتبني +المتتابع +المتتابعات +المتتابعة +المتتالية +المتتبع +المتجانس +المتجانسة +المتجاهلون +المتجاوبة +المتجاورة +المتجدد +المتجددة +المتجذر +المتجر +المتجسد +المتجسس +المتجعد +المتجمد +المتجمدة +المتجمعة +المتجه +المتجهم +المتجهمة +المتجولين +المتحاربة +المتحالفة +المتحالفين +المتحامل +المتحجبات +المتحجبة +المتحدة +المتحدث +المتحدثة +المتحدثين +المتحدرين +المتحررات +المتحررة +المتحرقة +المتحرك +المتحركة +المتحسسين +المتحصنين +المتحضر +المتحضِّرة +المتحـدة +المتحف +المتحفر +المتحفية +المتحفّزة +المتحققة +المتحكمين +المتحلل +المتحللة +المتحمس +المتحمسين +المتحول +المتحوّل +المتخاذلة +المتخاصمين +المتخصص +المتخصصة +المتخصصون +المتخصصين +المتخصّص +المتخلفة +المتخلفين +المتخم +المتخمين +المتخوفة +المتخيل +المتخيلة +المتداخل +المتداخلان +المتداخلة +المتداعي +المتداعية +المتدافعة +المتداول +المتدرب +المتدربات +المتدربون +المتدربين +المتدرج +المتدرجة +المتدفق +المتدفقة +المتدنية +المتدينة +المتدينين +المتديّن +المتر +المترابطة +المتراجعة +المترادفة +المتراصّة +المترافق +المترافقة +المتراكبة +المتراكضتين +المتراكم +المتراكمة +المترامي +المترامية +المتربة +المتربص +المتربصين +المتربّصين +المترتبة +المترجم +المترجمات +المترجمة +المترجمين +المتردد +المترددين +المتردي +المتردية +المترع +المترعة +المترعتين +المترفعين +المترفون +المترو +المتروبوليتان +المترين +المتزاحمين +المتزامنة +المتزايد +المتزايدة +المتزلجين +المتزمتات +المتزمّتة +المتزن +المتزوجة +المتزوجين +المتزيدين +المتزيِّنة +المتسابقة +المتسابقون +المتسابقين +المتسارع +المتسارعة +المتساقط +المتسامية +المتسبب +المتسربة +المتسربين +المتسرع +المتسرِّب +المتسرِّبة +المتسعة +المتسكر +المتسلطة +المتسللة +المتسللين +المتسوقين +المتسول +المتشائل +المتشائم +المتشائمة +المتشائمين +المتشابهة +المتشابهتين +المتشابهين +المتشبث +المتشبّع +المتشدد +المتشددة +المتشددين +المتشردين +المتشعب +المتشعّبة +المتشققة +المتشككين +المتشكلة +المتصارعة +المتصارعين +المتصاهرتين +المتصدئه +المتصدرين +المتصدع +المتصل +المتصلة +المتصلين +المتصوف +المتصوفة +المتصوّفة +المتضافرة +المتضامن +المتضرر +المتضررة +المتضررين +المتضلعين +المتضمخات +المتضمنة +المتضمَّنَة +المتطاير +المتطايرة +المتطرف +المتطرفة +المتطرفين +المتطفلين +المتطفِّلة +المتطلبات +المتطلعين +المتطلّعين +المتطور +المتطورة +المتطوعة +المتطوعين +المتطوِّرة +المتطوِّعين +المتظاهرين +المتع +المتعارف +المتعاركين +المتعاطفين +المتعاطين +المتعاقبة +المتعاقدين +المتعالية +المتعاملين +المتعاونة +المتعاونين +المتعايش +المتعب +المتعبان +المتعبة +المتعبدات +المتعة +المتعثر +المتعثرة +المتعددة +المتعرضين +المتعصبة +المتعصبين +المتعطرين +المتعطش +المتعففات +المتعففة +المتعلق +المتعلقة +المتعلم +المتعلمين +المتعلّم +المتعمد +المتعمقة +المتعهّرة +المتفائل +المتفاقمة +المتفاوضين +المتفتحة +المتفجر +المتفجرات +المتفجرة +المتفحص +المتفرج +المتفرجون +المتفرد +المتفرعة +المتفرّدة +المتفشي +المتفشية +المتفشيين +المتفطرات +المتفق +المتفوقين +المتقابلة +المتقاتلين +المتقاربة +المتقاربين +المتقاطعة +المتقاعدين +المتقدة +المتقدم +المتقدمة +المتقدمين +المتقطع +المتقطعة +المتقلب +المتقلبة +المتقن +المتقنة +المتقنين +المتكئ +المتكئة +المتكاسلون +المتكافئ +المتكامل +المتكاملة +المتكرر +المتكررة +المتكرّر +المتكسر +المتكسرة +المتكسّر +المتكلم +المتكلمين +المتكملة +المتكوم +المتكونة +المتكيف +المتلألئة +المتلاحقة +المتلازمة +المتلاطمة +المتلجلج +المتلصصين +المتلقاة +المتلقي +المتلقّي +المتلكئ +المتمادية +المتماسك +المتماوت +المتماوج +المتمثل +المتمثلان +المتمثلة +المتمحورة +المتمدد +المتمرد +المتمردون +المتمردين +المتمرسة +المتمرسين +المتمكن +المتمكنة +المتمم +المتموجة +المتمورة +المتميز +المتميزة +المتميزين +المتناثرة +المتناحرين +المتناسخ +المتنافرة +المتناقض +المتناقضات +المتناقضة +المتنامى +المتنامي +المتنامية +المتناهي +المتناهية +المتنبى +المتنبي +المتنبّهين +المتنخرة +المتنزهات +المتنسكين +المتنصلات +المتنكرة +المتنورة +المتنورين +المتنوع +المتنوعة +المتنوّع +المتهافت +المتهالكة +المتهاونة +المتهدجة +المتهدم +المتهم +المتهمة +المتهمون +المتهمين +المتهور +المتواتر +المتواجدين +المتوارثة +المتواريات +المتوازنة +المتوازية +المتواصل +المتواصلة +المتواضع +المتواضعة +المتواعدون +المتوافر +المتوافرة +المتوافقة +المتوالية +المتوترة +المتوجه +المتوجّه +المتوحش +المتوحشة +المتوحّد +المتورطة +المتورطين +المتورم +المتوسط +المتوسطة +المتوسطةـ +المتوسطية +المتوضعة +المتوفرة +المتوفى +المتوقع +المتوقعة +المتوقف +المتوقَّعَة +المتوكل +المتولد +المتولدة +المتوهج +المتوهجة +المتوهّج +المتوّجة +المتيسرة +المتين +المتينة +المتّحدة +المتّقد +المثابر +المثابرة +المثارة +المثاعيب +المثال +المثالي +المثالية +المثالين +المثانة +المثبت +المثبتة +المثبط +المثبطة +المثقب +المثقبة +المثقف +المثقفة +المثقفين +المثقل +المثقوب +المثكنه +المثل +المثلث +المثلثات +المثلجة +المثلى +المثلية +المثمر +المثمرة +المثمن +المثوبة +المثير +المثيرة +المثيل +المجادلة +المجادلين +المجاذيف +المجاري +المجاز +المجازر +المجازفة +المجازي +المجازية +المجاعات +المجاعة +المجال +المجالات +المجالس +المجالين +المجامع +المجاملات +المجاملة +المجامِع +المجانى +المجاني +المجانية +المجانين +المجاهد +المجاهدون +المجاهدين +المجاهل +المجاور +المجاورة +المجبول +المجبولة +المجتمع +المجتمعات +المجتمعة +المجتمعي +المجتمعية +المجتمعين +المجد +المجدبة +المجدد +المجددة +المجدولة +المجدي +المجدين +المجدّ +المجراة +المجرات +المجرة +المجرد +المجردة +المجرم +المجرمة +المجرمين +المجرى +المجريات +المجرَّدة +المجزي +المجسدة +المجسم +المجسمات +المجعّد +المجلات +المجلة +المجلتان +المجلتين +المجلد +المجلدات +المجلس +المجمدة +المجمع +المجمعات +المجموعات +المجموعة +المجموعتان +المجموعتين +المجنحة +المجنون +المجنونة +المجهر +المجهرية +المجهزة +المجهود +المجهول +المجهولة +المجوس +المجونية +المجيء +المجيب +المجيبين +المجيد +المجين +المجّاني +المحاجاة +المحاذية +المحار +المحارب +المحاربون +المحاربين +المحاسبي +المحاسيب +المحاصر +المحاصرات +المحاصرة +المحاصيل +المحاضر +المحاضرات +المحاضرة +المحاضرين +المحاضن +المحاطة +المحافظ +المحافظات +المحافظة +المحافظين +المحافل +المحاق +المحاكاة +المحاكم +المحاكمات +المحاكمة +المحال +المحاماة +المحامي +المحاميات +المحامين +المحاور +المحاورة +المحاولات +المحاولة +المحايد +المحببة +المحبة +المحبوس +المحبين +المحبّان +المحتاج +المحتاجة +المحتاجين +المحتدم +المحتدمة +المحترفة +المحترفون +المحترفين +المحترقة +المحتشد +المحتفى +المحتقنة +المحتكين +المحتل +المحتلة +المحتلين +المحتمل +المحتملة +المحتملين +المحتوى +المحتويات +المحتوية +المحتَمَل +المحجر +المحجوب +المحجوز +المحدثة +المحدثون +المحدثين +المحدد +المحددات +المحددة +المحدق +المحدود +المحدودة +المحدودين +المحدَّد +المحذوفة +المحراب +المحراث +المحررة +المحرق +المحرقة +المحرك +المحركات +المحركة +المحرم +المحرمات +المحرمين +المحروسة +المحروقات +المحروقة +المحرومة +المحرّض +المحرّضة +المحرّكة +المحزن +المحسن +المحسنات +المحسنة +المحسوب +المحسوبة +المحسّنات +المحسّنة +المحشر +المحشية +المحصلة +المحصورة +المحصول +المحصولي +المحصولين +المحض +المحضة +المحضرة +المحطات +المحطة +المحطم +المحظور +المحظورات +المحظوظين +المحـلى +المحـلية +المحفزة +المحفور +المحفورة +المحفوظ +المحفوظة +المحفوف +المحقق +المحققة +المحققين +المحك +المحكم +المحكمة +المحكمين +المحكوم +المحكي +المحكية +المحل +المحلاة +المحلات +المحلة +المحلقة +المحلل +المحللين +المحلول +المحلى +المحلي +المحلية +المحليون +المحليين +المحلّ +المحلّيّ +المحلّيّون +المحلّيّين +المحمدية +المحمرّ +المحمل +المحملة +المحمودة +المحمول +المحمولة +المحمومة +المحميات +المحمية +المحمّل +المحمَّرة +المحن +المحنة +المحنية +المحو +المحور +المحوري +المحورية +المحوسب +المحوَّرَة +المحير +المحيرة +المحيط +المحيطات +المحيطة +المحيطين +المحيّرة +المخ +المخابرات +المخاتلة +المخاريط +المخازن +المخاض +المخاط +المخاطب +المخاطبة +المخاطر +المخاطرة +المخاطي +المخاطية +المخاطَب +المخاطِب +المخالف +المخالفة +المخالفين +المخاوف +المخبر +المخبري +المخبرية +المخبرين +المخبوءة +المخبول +المختار +المختارات +المختارة +المختبر +المختبرات +المختبرية +المخترق +المخترقين +المختزلة +المختزنة +المختص +المختصة +المختصر +المختصرة +المختصين +المختفين +المختلط +المختلطة +المختلف +المختلفة +المختلفين +المختنق +المختنقة +المختوم +المختومة +المختَبَرات +المخثر +المخجل +المخدرات +المخربة +المخربين +المخرج +المخرجة +المخرجين +المخرشة +المخروطية +المخرِّب +المخرِّبة +المخزن +المخزومي +المخزون +المخزونة +المخزية +المخصب +المخصبات +المخصبة +المخصص +المخصصات +المخصصة +المخصصتين +المخصيون +المخصّصة +المخصِّبات +المخضر +المخضرة +المخضرم +المخضرمين +المخضرّ +المخطط +المخططات +المخطوط +المخطوطات +المخطوطة +المخفضة +المخفف +المخففة +المخفية +المخفّف +المخل +المخلب +المخلبية +المخلص +المخلصة +المخلصون +المخلصين +المخلفات +المخلوطة +المخلوع +المخلوق +المخلوقات +المخلوقين +المخلَّفات +المخملي +المخملية +المخموجة +المخول +المخولة +المخيال +المخية +المخيف +المخيفة +المخيفتان +المخيم +المخيمات +المخيّلة +المد +المداخل +المداد +المدادة +المدار +المداراة +المدارات +المدارس +المدافع +المدافعون +المدافعين +المدافن +المداهم +المداوي +المدببة +المدة +المدجّن +المدجّنة +المدخر +المدخرات +المدخرون +المدخل +المدخلات +المدخنين +المدر +المدرات +المدرارة +المدرب +المدربة +المدربةُ +المدربون +المدرجات +المدرجة +المدرحي +المدرحية +المدرس +المدرسات +المدرسة +المدرسون +المدرسي +المدرسية +المدرسين +المدركة +المدروسة +المدسوسة +المدعو +المدعوة +المدعوم +المدعومة +المدعوين +المدعي +المدفأة +المدفعا +المدفعية +المدفوعات +المدفون +المدفونة +المدقق +المدققة +المدقوق +المدلاة +المدلل +المدللة +المدلولات +المدمجة +المدمر +المدمرة +المدمنين +المدمّر +المدمِّر +المدمِّرة +المدن +المدنى +المدني +المدنية +المدنيين +المدهش +المدهشة +المدهونة +المدور +المدورة +المدوى +المدوي +المدوية +المدوّن +المدوّي +المدوّية +المدى +المدي +المديد +المديدة +المدير +المديرات +المديرة +المديرية +المديـنة +المدين +المدينات +المدينة +المدينتين +المدّ +المدّاح +المدِّية +المذاب +المذابح +المذاق +المذاقات +المذاكرة +المذاهب +المذبوحين +المذكرات +المذكرة +المذكور +المذكورة +المذكِّر +المذنبين +المذهب +المذهبة +المذهبية +المذهبين +المذهل +المذهلة +المذياع +المذيب +المذيع +المذيعة +المر +المرء +المرآة +المرأة +المرئي +المرئيات +المرئية +المرابط +المرابطون +المرابي +المرابيع +المرات +المراتب +المراجع +المراجعة +المراجعين +المراجل +المراجين +المراحل +المراد +المرادة +المرادفة +المرارة +المرازيق +المراسلات +المراصد +المراطم +المراعي +المرافئ +المرافق +المرافقة +المرافقين +المراقب +المراقبة +المراقبون +المراقبين +المراكب +المراكز +المراكمة +المرام +المراهقة +المراهقون +المراهقين +المراهم +المرايا +المربد +المربع +المربعات +المربعة +المربوط +المربوطة +المربي +المربين +المرة +المرتاحة +المرتبات +المرتبة +المرتبط +المرتبطة +المرتجعة +المرتجف +المرتجلة +المرتجلين +المرتحل +المرتحلون +المرتخية +المرتديات +المرتدين +المرتزقة +المرتعب +المرتفع +المرتفعات +المرتفعة +المرتفعتين +المرتقب +المرتقبة +المرتكز +المرتكزات +المرتين +المرج +المرجان +المرجاني +المرجانيات +المرجانية +المرجة +المرجح +المرجع +المرجعي +المرجعيات +المرجعية +المرجعَ +المرجل +المرجو +المرجوة +المرجوّة +المرح +المرحاض +المرحة +المرحلة +المرحلتين +المرحلي +المرحوم +المرحومين +المرحّلين +المرخص +المردلي +المردود +المردودات +المرزوقي +المرزوقية +المرسل +المرسلة +المرسلين +المرسم +المرسيدس +المرشح +المرشحة +المرشحـة +المرشحين +المرشد +المرشدين +المرشوشة +المرصد +المرصع +المرصفي +المرصود +المرصوف +المرصوفة +المرض +المرضى +المرضي +المرضية +المرطبات +المرعب +المرعبة +المرعى +المرعية +المرفأ +المرفق +المرفه +المرفوع +المرفوعة +المرقص +المرقم +المركب +المركبات +المركبة +المركبين +المركز +المركزة +المركزي +المركزية +المركزين +المركونة +المركّب +المركّبات +المركَّب +المرمر +المرموقة +المرموقين +المرميين +المرميّة +المرن +المرنة +المرهف +المرهم +المرواس +المروج +المروجون +المروحية +المرور +المرورية +المروضة +المروع +المرونة +المرويات +المري +المريب +المريح +المريحة +المريخ +المريدون +المريدين +المرير +المريرة +المريض +المريضة +المريعة +المرينية +المرينيين +المرّة +المرَّة +المرُّ +المزابل +المزاج +المزاح +المزاحمين +المزاد +المزار +المزارع +المزارعون +المزارعين +المزامير +المزايا +المزايدة +المزايدين +المزبد +المزبلة +المزج +المزجاة +المزخرف +المزدحم +المزدحمة +المزدحمين +المزدهرة +المزدوج +المزدوجات +المزدوجة +المزرعة +المزركشة +المزروع +المزروعات +المزروعة +المزري +المزرية +المزعج +المزعجة +المزعوم +المزكي +المزمار +المزمع +المزمن +المزمنة +المزهوين +المزود +المزودة +المزورون +المزية +المزيج +المزيد +المزيف +المزيفة +المزين +المزينة +المزيّفة +المسألة +المسؤول +المسؤولة +المسؤولون +المسؤوليات +المسؤولية +المسؤولين +المسئول +المسئولة +المسئولون +المسئوليات +المسئولية +المسئولين +المسا +المساء +المساءات +المسائل +المسائية +المسابقات +المساجات +المساجد +المساجين +المساحات +المساحة +المسار +المسارات +المسارح +المساري +المسارين +المساس +المساعد +المساعدات +المساعدة +المساعدين +المساعي +المسافات +المسافة +المسافر +المسافرة +المسافرون +المسافرين +المساكن +المساكنة +المساكين +المسالك +المسالم +المسالمين +المسامات +المسامحة +المسامرات +المسامير +المساندة +المساهمات +المساهمة +المساهمين +المساوئ +المساواة +المساومة +المساوية +المسبب +المسببات +المسببة +المسبحة +المسبق +المسبقة +المسبوكة +المسبّب +المسبّبة +المستأثرة +المستأجرة +المستأصلة +المستبد +المستبصرة +المستبطن +المستبطنة +المستبعد +المستتر +المستترة +المستترين +المستثمر +المستثمرة +المستثمرون +المستثمرين +المستجدات +المستجدة +المستجديات +المستحب +المستحبة +المستحدث +المستحدثة +المستحدَثة +المستحدَثَة +المستحسن +المستحضرات +المستحـق +المستحق +المستحقة +المستحقين +المستحيل +المستحيلات +المستحيلة +المستخدم +المستخدمان +المستخدمة +المستخدمين +المستخرج +المستخرجة +المستخلص +المستدامة +المستدرك +المستدقه +المستديرة +المستديرتين +المستديم +المستديمة +المستر +المسترخية +المستردة +المستردفين +المستردِفة +المستسلمة +المستشار +المستشرق +المستشرقة +المستشرقون +المستشرقين +المستشري +المستشعرة +المستشفى +المستشفيات +المستضعفة +المستضعفين +المستطاع +المستطيلة +المستعارة +المستعدين +المستعرب +المستعربين +المستعصية +المستعمر +المستعمرات +المستعمرة +المستعمرون +المستعمرين +المستعمل +المستعملة +المستعيد +المستفحلة +المستفز +المستفيد +المستفيدون +المستفيدين +المستفيضة +المستقبل +المستقبلات +المستقبلي +المستقبليات +المستقبلية +المستقر +المستقرة +المستقرَّة +المستقل +المستقلة +المستقلين +المستقيم +المستكبرة +المستكشفين +المستلزمات +المستلقين +المستلهم +المستلهمة +المستمد +المستمدة +المستمر +المستمرة +المستمع +المستمعون +المستمعين +المستميتة +المستنبتات +المستنبطة +المستند +المستندة +المستنصر +المستنصرية +المستنقع +المستنقعات +المستنيرة +المستنيرون +المستنيرين +المستهدف +المستهدفة +المستهلك +المستهلكة +المستهلكون +المستهلكين +المستوحدة +المستودع +المستورد +المستوردة +المستوطنات +المستوطنة +المستوطنون +المستوطنين +المستوى +المستوي +المستويات +المستوية +المستويين +المسجد +المسجدية +المسجل +المسجلة +المسجلين +المسجى +المسجّى +المسح +المسحوبة +المسحور +المسحورة +المسحوق +المسحوقين +المسحّرين +المسخ +المسدة +المسرجة +المسرح +المسرحي +المسرحيات +المسرحية +المسرحيين +المسرطنة +المسرعة +المسرفين +المسروق +المسروقات +المسروقة +المسطح +المسطحات +المسطحة +المسعودي +المسعورين +المسعى +المسفوكة +المسقط +المسقفات +المسقوف +المسقوفة +المسك +المسكن +المسكنات +المسكوب +المسكوت +المسكون +المسكونة +المسكونية +المسكين +المسكينة +المسلح +المسلحة +المسلسل +المسلسلات +المسلسلين +المسلط +المسلطة +المسلك +المسلكيات +المسلم +المسلمات +المسلمة +المسلمون +المسلمين +المسلوب +المسلية +المسلّم +المسلَّحة +المسماة +المسمارية +المسماع +المسمم +المسممة +المسموح +المسموع +المسموعة +المسموم +المسمى +المسميات +المسميان +المسمّمة +المسن +المسنات +المسند +المسننة +المسنين +المسوحات +المسودة +المسوقة +المسيار +المسيح +المسيحي +المسيحية +المسيحيون +المسيحيين +المسير +المسيرة +المسيسبي +المسيسيبي +المسيطرة +المشئوم +المشئومة +المشابك +المشابهة +المشاة +المشاحنات +المشادات +المشادة +المشار +المشارف +المشارقة +المشارك +المشاركات +المشاركة +المشاركون +المشاركين +المشارى +المشاري +المشاريع +المشاعر +المشاعل +المشافي +المشاق +المشاكل +المشاهد +المشاهدات +المشاهدة +المشاهدين +المشاهير +المشايخ +المشبع +المشبعة +المشبوب +المشبوبة +المشبوه +المشبوهة +المشتاق +المشتبه +المشتراة +المشترك +المشتركة +المشتركين +المشترون +المشتري +المشتريات +المشترية +المشترين +المشتعل +المشتعلة +المشتق +المشتقات +المشتقة +المشتل +المشجرة +المشجعة +المشجعين +المشحون +المشحونة +المشخص +المشدد +المشددة +المشدود +المشردة +المشرع +المشرف +المشرفة +المشرفون +المشرفين +المشرق +المشرقة +المشرقي +المشرقية +المشركون +المشروبات +المشروبة +المشروط +المشروع +المشروعات +المشروعة +المشروعية +المشرّف +المشط +المشطية +المشع +المشعة +المشعر +المشعّة +المشـافي +المشفقة +المشفى +المشقوق +المشكلات +المشكلة +المشكورة +المشكوك +المشلولة +المشنقة +المشهد +المشهود +المشهودة +المشهور +المشهورة +المشهورين +المشوار +المشورة +المشوقة +المشوهة +المشوّهة +المشي +المشية +المشير +المشيعين +المص +المصائب +المصائر +المصاب +المصابات +المصابة +المصابيح +المصابين +المصاحب +المصاحبة +المصادر +المصادرات +المصادرة +المصادف +المصادفات +المصادفة +المصادقة +المصارحة +المصارعين +المصارف +المصاريف +المصاعب +المصاعد +المصالح +المصالحة +المصانع +المصاهرة +المصايد +المصايف +المصباح +المصبّات +المصحف +المصداقية +المصدر +المصدران +المصدرة +المصدرون +المصدرين +المصدّرة +المصدِّرة +المصرارة +المصرة +المصرف +المصرفي +المصرفية +المصروف +المصروفات +المصرى +المصري +المصريات +المصرية +المصريون +المصريين +المصطافون +المصطبة +المصطفة +المصطفون +المصطفى +المصطفي +المصطلح +المصطلحات +المصعد +المصفف +المصفى +المصقولة +المصل +المصلحة +المصلحون +المصلحين +المصلين +المصمـمون +المصمم +المصممة +المصنع +المصنعة +المصنعين +المصنفات +المصنوع +المصنوعات +المصنوعة +المصنّع +المصنِّع +المصهور +المصهورة +المصور +المصورة +المصورين +المصون +المصونة +المصيد +المصيدة +المصير +المصيري +المصيرية +المصيف +المضاءة +المضاجع +المضاجعات +المضاجعون +المضاد +المضادات +المضادة +المضادّات +المضادّة +المضاربات +المضارين +المضاعفات +المضاف +المضافة +المضامين +المضاهية +المضايقات +المضبوط +المضبوطات +المضبوطة +المضحكاتي +المضحكة +المضحكون +المضحكين +المضحي +المضخة +المضرة +المضطر +المضطرب +المضطربة +المضللة +المضلّع +المضمار +المضمارين +المضمنة +المضمون +المضمونة +المضموني +المضمونية +المضني +المضنية +المضى +المضي +المضيئة +المضيف +المضيفة +المضيق +المضيّ +المطابخ +المطابع +المطابقة +المطار +المطارات +المطارح +المطارد +المطاردات +المطاردة +المطاط +المطاعم +المطاف +المطالب +المطالبات +المطالبة +المطالع +المطالعة +المطامح +المطامع +المطبخ +المطبعة +المطبقة +المطبوخ +المطبوع +المطبوعات +المطبوعة +المطبّقة +المطر +المطرب +المطربة +المطربين +المطرد +المطردة +المطرزة +المطرق +المطرقة +المطرقية +المطروح +المطروحة +المطرودين +المطروق +المطرية +المطرَّز +المطعم +المطعمة +المطعون +المطــــلق +المطل +المطلب +المطلة +المطلع +المطلق +المطلقات +المطلقة +المطلقين +المطلوب +المطلوبة +المطلوبين +المطلية +المطمع +المطهرة +المطهرون +المطهم +المطورة +المطوع +المطولة +المطوّلة +المطير +المطيرة +المطّرد +المظالم +المظاهر +المظاهرات +المظروف +المظفر +المظلم +المظلمة +المظلوم +المظلومين +المظلّة +المظهر +المظهري +المعابد +المعاجم +المعاداة +المعادلات +المعادلة +المعادن +المعادي +المعادية +المعارض +المعارضة +المعارضون +المعارضين +المعارف +المعارك +المعاش +المعاشرة +المعاصر +المعاصرة +المعاصرين +المعاصي +المعاطي +المعاقون +المعاقين +المعاكس +المعاكسة +المعالج +المعالجات +المعالجة +المعالجين +المعالفة +المعالم +المعامل +المعاملات +المعاملة +المعاناة +المعاني +المعاهد +المعاهدات +المعاهدة +المعاونة +المعاىير +المعايشة +المعاينة +المعايير +المعبأة +المعبد +المعبدة +المعبر +المعبرة +المعبود +المعبّدة +المعبّرة +المعبَّأة +المعتاد +المعتادة +المعتبرة +المعتدل +المعتدلة +المعتدلين +المعتدون +المعتدية +المعتدين +المعترض +المعترف +المعترك +المعتز +المعتزلة +المعتصمين +المعتق +المعتقد +المعتقدات +المعتقل +المعتقلات +المعتلة +المعتم +المعتمة +المعتمد +المعتمدة +المعتمدين +المعتمر +المعتمرين +المعتنى +المعتورة +المعتوهة +المعتّق +المعجب +المعجبين +المعجز +المعجزات +المعجزة +المعجم +المعجمات +المعجمي +المعجمية +المعجَبة +المعدات +المعدة +المعدل +المعدلات +المعدلة +المعدن +المعدنية +المعدودين +المعدي +المعدية +المعدّة +المعدّل +المعدَّل +المعدَّلات +المعذب +المعرس +المعرض +المعرضة +المعرفة +المعرفي +المعرفية +المعركة +المعروض +المعروضات +المعروضة +المعروف +المعروفة +المعروفين +المعروقة +المعري +المعرّض +المعرّضون +المعرّي +المعرَّضة +المعز +المعزوفة +المعزولة +المعزين +المعسكر +المعسكرات +المعسول +المعشر +المعشوشبة +المعشوقة +المعصرة +المعصم +المعصوب +المعصية +المعضلة +المعطاة +المعطر +المعطشة +المعطوبة +المعطي +المعطيات +المعظم +المعـدّلة +المعـروف +المعقاف +المعقد +المعقدة +المعقل +المعقم +المعقمات +المعقوف +المعقول +المعقولة +المعقّدة +المعقّمة +المعكوسة +المعلب +المعلبات +المعلق +المعلقات +المعلقة +المعلقين +المعلم +المعلمات +المعلمة +المعلمون +المعلمين +المعلن +المعلنة +المعلوف +المعلوفية +المعلول +المعلومات +المعلوماتي +المعلوماتية +المعلومة +المعلّم +المعلَّقة +المعمار +المعمارى +المعماري +المعمارية +المعماريون +المعماريين +المعمد +المعمدانية +المعمر +المعمعة +المعمقة +المعمل +المعملي +المعممة +المعمور +المعمورة +المعمول +المعمّرة +المعمّقة +المعنوي +المعنوية +المعنى +المعني +المعنية +المعنيون +المعنيين +المعهد +المعهود +المعهودة +المعوزين +المعوق +المعوقات +المعوقون +المعوقين +المعول +المعولي +المعونات +المعونة +المعوية +المعوّقات +المعوَّلُ +المعيار +المعياران +المعياري +المعيارية +المعيبة +المعيش +المعيشة +المعيشية +المعين +المعيّن +المـــتحدة +المفاتن +المفاتيح +المفاجآت +المفاجأة +المفاجئ +المفاجئة +المفاجىء +المفاجيء +المفارش +المفارقات +المفارقة +المفاسد +المفاصل +المفاعل +المفاعلات +المفاهيم +المفاهيمية +المفاوضات +المفتئتين +المفتاح +المفترس +المفترسة +المفترسين +المفترض +المفترضة +المفترضين +المفتش +المفتشون +المفتشين +المفتعل +المفتقد +المفتوح +المفتوحة +المفجر +المفجعة +المفخور +المفدى +المفرح +المفرخة +المفردات +المفردة +المفرزات +المفرط +المفرطة +المفرطين +المفرقعات +المفروش +المفروشات +المفروشة +المفروض +المفروضة +المفروم +المفزع +المفزعات +المفزعة +المفسدين +المفسر +المفسرين +المفصلة +المفصلي +المفصلية +المفضل +المفضلة +المفضَّل +المفعم +المفعمة +المفعول +المفعولية +المفـقود +المفقود +المفقودات +المفقودة +المفقودين +المفكر +المفكرة +المفكرون +المفكرين +المفهرسين +المفهوم +المفهومين +المفوضية +المفيد +المفيدة +المقابر +المقابض +المقابل +المقابلات +المقابلة +المقاتل +المقاتلين +المقادير +المقاربة +المقارن +المقارنات +المقارنة +المقاريب +المقاصد +المقاطع +المقاطعات +المقاطعة +المقاعد +المقال +المقالات +المقالب +المقالة +المقالح +المقام +المقامات +المقامة +المقامين +المقاهي +المقاولات +المقاومة +المقاومين +المقايضة +المقاييس +المقبرة +المقبضة +المقبـرة +المقبل +المقبلات +المقبلة +المقبلين +المقبول +المقبولة +المقبولين +المقتبسة +المقتحمة +المقتدر +المقتدرة +المقتربة +المقترح +المقترحات +المقترحة +المقتضب +المقتضيات +المقتطف +المقتنيات +المقددات +المقدر +المقدرة +المقدس +المقدسات +المقدسة +المقدستين +المقدسون +المقدسي +المقدسية +المقدسين +المقدسيون +المقدسيين +المقدم +المقدمات +المقدمة +المقدوني +المقدونيين +المقدّس +المقدّمة +المقدَّم +المقدِّم +المقر +المقرئين +المقراب +المقربون +المقربين +المقرر +المقررة +المقرض +المقرنات +المقروءات +المقرون +المقريزي +المقريزية +المقرّبين +المقرّرات +المقزز +المقسم +المقسوم +المقصود +المقصودة +المقصورة +المقطع +المقطعة +المقطعي +المقطم +المقطوع +المقطوعات +المقطوعة +المقعد +المقعدية +المقفر +المقفع +المقفل +المقل +المقلاة +المقلد +المقلدة +المقلدين +المقلق +المقلوبة +المقلية +المقليَّة +المقلّدين +المقنع +المقنعة +المقنن +المقهور +المقهورة +المقهى +المقود +المقولات +المقولة +المقومات +المقوي +المقوية +المقوّى +المقياس +المقيتة +المقيدة +المقيل +المقيم +المقيمة +المقيمون +المقيمين +المكائن +المكاتب +المكاتبات +المكارم +المكاشفة +المكافآت +المكافأة +المكافحة +المكالمات +المكان +المكانة +المكاني +المكانية +المكاوي +المكبر +المكبوتة +المكتب +المكتبات +المكتبة +المكتبية +المكتبيون +المكتبيين +المكتسب +المكتسبات +المكتسبة +المكتشفة +المكتشفون +المكتشَف +المكتظ +المكتظة +المكتفي +المكتنزة +المكتوب +المكتوبة +المكتَشَف +المكثف +المكثّفة +المكثَّف +المكر +المكرسة +المكرسين +المكرمة +المكروه +المكسوة +المكسيك +المكسيكي +المكشوف +المكشوفة +المكعبات +المكفت +المكفهر +المكفهرة +المكفوف +المكفوفين +المكلف +المكلفة +المكلفين +المكلومة +المكملات +المكملة +المكننة +المكوث +المكوك +المكون +المكونات +المكونة +المكوّنة +المكي +المكياج +المكية +المكيفات +المكين +المكينة +المكيين +المكيّف +الملئ +الملا +الملائكة +الملائم +الملائمة +الملابس +الملابسات +الملاح +الملاحة +الملاحظ +الملاحظات +الملاحظة +الملاحقة +الملاحم +الملاحون +الملاحية +الملاذ +الملاريا +الملازم +الملازمة +الملازمين +الملاعب +الملاعين +الملاك +الملامح +الملامسة +الملاهي +الملاىين +الملايين +الملاّح +الملاّحين +الملبس +الملة +الملتئمة +الملتاع +الملتبسة +الملتحق +الملتحقين +الملتحمة +الملتحي +الملتزم +الملتزمة +الملتزمين +الملتصق +الملتصقون +الملتقى +الملتقي +الملتقيات +الملتهب +الملتهبة +الملجأ +الملح +الملحد +الملحدين +الملحق +الملحقة +الملحمة +الملحمي +الملحن +الملحوظ +الملحوظة +الملحون +الملحي +الملحّة +الملحَّة +الملزم +الملزمة +الملساء +الملطخ +الملطخة +الملعب +الملف +الملفات +الملفقة +الملفوف +الملفّح +الملقاة +الملقب +الملقبة +الملقح +الملقم +الملقى +الملك +الملكات +الملكانية +الملكة +الملكي +الملكية +الملكين +الملكَ +الملكُ +الملل +الملليمتر +الملمح +الملمس +الملموس +الملموسة +الملهوف +الملهوفين +الملوث +الملوثات +الملوثة +الملوحة +الملوك +الملوكِ +الملون +الملونة +الملونتين +الملوّث +الملوّثة +الملوّن +الملوّنة +الملوَّث +الملوِّثات +المليء +المليئة +المليار +المليارات +الملياري +الملية +المليشيات +المليون +المليونى +المليوني +المليونين +المماثلة +الممارس +الممارسات +الممارسة +المماكبات +الممالك +المماليك +الممايزة +الممتاز +الممتازة +الممتحنين +الممتد +الممتدة +الممتدتان +الممتزج +الممتص +الممتطون +الممتطين +الممتع +الممتعة +الممتلئة +الممتلكات +الممثل +الممثلة +الممثلون +الممثليات +الممثلين +الممدة +الممدد +الممر +الممرات +الممرض +الممرضات +الممرضة +الممرَّات +الممزق +الممسوحَين +الممضة +الممكن +الممكنات +الممكنة +الممل +المملة +المملحة +المملكة +المملكةالعربية +المملوءة +المملوك +المملوكة +المملوكي +الممنوحة +الممنوحـة +الممنوعات +الممهدة +الممول +المميت +المميتة +المميز +المميزات +المميزة +المميّزة +المميِّزة +المنابر +المنابع +المناجم +المناحل +المناخ +المناخات +المناخلية +المناخية +المنادون +المنادي +المنادية +المنارة +المنازعات +المنازل +المناسب +المناسبات +المناسباتِ +المناسبة +المناسترلى +المناسك +المناشط +المناشف +المناصب +المناصر +المناصرة +المناضل +المناضلة +المناضلون +المناضلين +المناطـق +المناطق +المناطيد +المناظر +المناظرات +المناعات +المناعة +المناعي +المناعية +المنافذ +المنافس +المنافسات +المنافسة +المنافسون +المنافع +المنافي +المناقب +المناقش +المناقشات +المناقشة +المنال +المنام +المنامة +المنامية +المناهج +المناهض +المناهضة +المناوئة +المناوئين +المناورة +المنبثقة +المنبر +المنبسط +المنبع +المنبعث +المنبعثة +المنبه +المنبهات +المنبوذة +المنبوذين +المنة +المنتأى +المنتج +المنتجات +المنتجة +المنتجع +المنتجعات +المنتجين +المنتخبات +المنتخبة +المنتدب +المنتدى +المنتديات +المنتزه +المنتزهات +المنتسبين +المنتشر +المنتشرة +المنتشية +المنتصر +المنتصرين +المنتظر +المنتظرات +المنتظرة +المنتظرين +المنتظم +المنتظمين +المنتفخ +المنتفعين +المنتقاة +المنتقلة +المنتمين +المنتهي +المنتوج +المنتوجات +المنثور +المنثورة +المنجد +المنجزات +المنجي +المنح +المنحة +المنحدر +المنحدرات +المنحدرة +المنحرف +المنحلة +المنحنى +المنحني +المنحنية +المنحوتات +المنحى +المنخفض +المنخفضات +المنخفضة +المنخورة +المندب +المندد +المنددة +المندفع +المندلعة +المندلق +المندمجة +المندوب +المندوبين +المنديل +المنذرة +المنزل +المنزلة +المنزلقات +المنزلي +المنزلية +المنزليةعلى +المنزليّ +المنزهة +المنسق +المنسوب +المنسوجات +المنسوجة +المنسية +المنسيين +المنشآت +المنشأ +المنشأة +المنشد +المنشدين +المنشفة +المنشق +المنشود +المنشودة +المنشودين +المنشور +المنشورات +المنشورة +المنشية +المنشِّطة +المنصب +المنصة +المنصتة +المنصرف +المنصرم +المنصرين +المنصفة +المنصوب +المنصور +المنصوري +المنصَّة +المنضبط +المنضبطة +المنضج +المنضوية +المنطبعتان +المنطق +المنطقة +المنطقتين +المنطقي +المنطقية +المنطلق +المنطلقات +المنطلقة +المنطوق +المنطوقة +المنطوي +المنطوية +المنظار +المنظر +المنظرين +المنظف +المنظفات +المنظم +المنظمات +المنظمة +المنظور +المنظورة +المنظومة +المنظّم +المنظِّفات +المنظِّمة +المنع +المنعة +المنعزلة +المنعش +المنعطف +المنعقد +المنعقدة +المنعكس +المنعكسة +المنفحة +المنفذة +المنفرد +المنفردة +المنفصل +المنفصلة +المنفعة +المنفقة +المنفلت +المنفلتة +المنفلوطي +المنفى +المنفي +المنفيون +المنقار +المنقبضة +المنقبين +المنقذ +المنقرضة +المنقلب +المنقورة +المنقوش +المنقوشة +المنقوص +المنقوصة +المنقول +المنقولات +المنقولة +المنقولين +المنكبين +المنكر +المنكرين +المنكوب +المنكوبة +المنكوبين +المنمق +المنمنمات +المنمنمة +المنهاج +المنهار +المنهارة +المنهج +المنهجي +المنهجية +المنهك +المنهكة +المنهمر +المنوال +المنوالية +المنورة +المنوطة +المنوعة +المنوفية +المنولوجات +المنومات +المنومة +المنون +المنوي +المنوية +المنوّرة +المنوّمة +المني +المنيا +المنية +المنيع +المنيعة +المنيف +المنيّة +المنّة +المها +المهاة +المهاتما +المهاجر +المهاجرة +المهاجرون +المهاجرين +المهاجمين +المهادنة +المهارات +المهارة +المهاري +المهام +المهبطية +المهبلي +المهتاج +المهتدي +المهترأة +المهترىء +المهتم +المهتمة +المهتمون +المهتمين +المهجر +المهجري +المهجورة +المهد +المهدئات +المهدئة +المهداة +المهدد +المهددة +المهدمة +المهدور +المهدورة +المهدومة +المهدي +المهدية +المهذب +المهرب +المهرة +المهرجان +المهرجانات +المهرجين +المهرطق +المهرطقون +المهرطقين +المهري +المهزوزة +المهسهس +المهضومة +المهلك +المهلكة +المهم +المهمات +المهماز +المهمازيون +المهمة +المهمشين +المهملات +المهملة +المهملين +المهمّ +المهمّة +المهن +المهنة +المهندس +المهندسة +المهندسون +المهندسين +المهني +المهنية +المهور +المهولة +المهيأة +المهيئة +المهيب +المهيري +المهيمن +المهيمنة +المهيمنون +المهيمنين +المهين +الموئل +الموا +الموائد +الموائل +المواتية +المواجد +المواجه +المواجهات +المواجهة +المواد +المواربة +الموارد +الموازنة +الموازي +المواسم +المواسير +المواشي +المواصفات +المواصلات +المواصلة +المواضع +المواضيع +المواطن +المواطنات +المواطنة +المواطنون +المواطنية +المواطنين +المواعظ +المواعيد +الموافق +الموافقة +المواقع +المواقف +المواقيت +المواكب +الموال +الموالد +الموالية +المواليد +الموانئ +المواهب +الموبؤة +الموبوء +الموبوءة +الموت +الموتى +الموتيف +الموتيفات +الموثقة +الموثوقة +الموج +الموجات +الموجب +الموجبة +الموجة +الموجز +الموجع +الموجه +الموجهة +الموجود +الموجودات +الموجودة +الموجودين +الموجي +الموجية +الموجيتو +الموجِ +الموجّه +الموجّهة +الموحدة +الموحدون +الموحدين +الموحش +الموحولة +الموحية +الموحّدة +المودة +المودودي +المودوي +الموديل +المورثات +المورثة +المورثية +المورقة +الموروث +الموروثات +الموروثة +الموريا +الموريكينري +الموزعة +الموساد +الموسم +الموسمي +الموسمية +الموسنيور +الموسوعات +الموسوعة +الموسوعي +الموسوم +الموسومة +الموسى +الموسيقا +الموسيقار +الموسيقــــى +الموسيقى +الموسيقي +الموسيقية +الموسيقيين +الموشاة +الموشح +الموشومة +الموصدة +الموصل +الموصلة +الموصلي +الموصوفة +الموصول +الموصى +الموصّاة +الموضات +الموضة +الموضع +الموضعة +الموضعي +الموضعية +الموضوع +الموضوعات +الموضوعة +الموضوعي +الموضوعية +الموطأ +الموطن +الموطِّدة +الموظف +الموظفة +الموظفون +الموظفين +الموظِّف +الموعد +الموعود +الموعودة +الموفد +الموفدين +الموفق +الموفين +الموقد +الموقع +الموقعة +الموقف +الموقفين +الموقوتة +الموكب +الموكلة +الموكولة +المول +المولد +المولدة +المولعين +المولود +المولودون +المولى +المومياء +المومياوات +المومياوين +المونولوجست +المونولوجي +الموهبة +الموهوب +الموهوبون +الموهوبين +المويجات +المياة +الميادين +المياه +المية +الميت +الميتافيزيقي +الميتة +الميثان +الميثانول +الميثانولي +الميثايل +الميثايلين +الميداليات +الميدالية +الميدان +الميداني +الميدانية +الميدي +الميديا +الميراث +الميراني +الميرمية +الميز +الميزاب +الميزات +الميزان +الميزانيات +الميزانية +الميزة +الميسرة +الميعاد +الميكادو +الميكانيكا +الميكانيكي +الميكانيكية +الميكانيكيّ +الميكرو +الميكروب +الميكروبات +الميكروسكوب +الميكروسكوبي +الميكروسكوبية +الميل +الميلاد +الميلادي +الميلادية +الميلاديين +الميلانات +الميلانين +الميلودراما +الميمني +الميناء +الميوزي +الميوسيني +المَتاهة +المَرَاح +المَيز +المُؤخّرة +المُبكِّر +المُحال +المُختَبَر +المُكتظَّة +المُهدى +الن +النأى +النائب +النائحات +النائحة +النائم +النائمات +النائمة +النائمون +النائمين +النائية +النابذات +النابذة +النابض +النابضة +النابع +النابعة +النابهين +النابودة +النابية +الناتئة +الناتج +الناتجة +الناجح +الناجحة +الناجحين +الناجرا +الناجزة +الناجع +الناجعة +الناجم +الناجمة +الناجون +الناجين +الناحل +الناحية +الناحيتين +الناخبين +النادر +النادرة +النادل +النادلات +النادى +النادي +النار +النارجيل +الناري +النارية +النازحون +النازحين +النازفة +النازل +النازي +النازية +الناس +الناسَ +الناسُ +الناشئ +الناشئة +الناشبة +الناشر +الناشرات +الناشرون +الناشرين +الناشطات +الناشطة +الناشطين +الناشف +الناصر +الناصرة +الناصري +الناصرية +الناصع +الناضبة +الناضجة +الناضجين +الناطق +الناطقة +الناطقون +الناطقين +الناظر +الناظرة +الناظرين +الناعم +الناعمة +الناعمتان +الناعمتين +النافذ +النافذة +النافع +النافعة +الناقة +الناقد +الناقدة +الناقدين +الناقص +الناقصة +الناقل +الناقلة +النامي +النامية +النانو +النانوبيوتك +النانوتوي +النانونبيوتك +النانوية +الناهض +الناهضة +الناي +النبأ +النبات +النباتات +النباتى +النباتي +النباتية +النباتين +النبتة +النبرة +النبض +النبضات +النبطية +النبع +النبل +النبلة +النبهان +النبهاني +النبوءات +النبوءة +النبوة +النبوى +النبوي +النبوية +النبي +النبيل +النبيلة +النبيين +النتائج +النتاج +النتاسق +النتفس +النتن +النتنة +النتوءات +النتيجة +النثار +النثر +النثري +النثرية +النجا +النجابة +النجاة +النجاح +النجاحات +النجار +النجارة +النجارين +النجديّة +النجلاوان +النجم +النجمات +النجمية +النجوم +النجومية +النجيبة +النجيع +النحاس +النحاسية +النحاسين +النحافة +النحال +النحالون +النحالين +النحت +النحر +النحس +النحـو +النحل +النحلات +النحلاوي +النحلة +النحو +النحوية +النحيفة +النحيل +النحيلة +النخاس +النخاسة +النخاع +النخب +النخبة +النخل +النخلة +النخوة +النخيل +الند +النداء +الندب +الندبات +الندبة +الندرة +الندل +الندم +الندوات +الندوة +الندوي +الندى +الندية +النديم +النديّة +النذر +النذري +النذور +النرجسية +النرجيلة +النرد +النرويج +النرويجي +النرويجية +النزاع +النزاعات +النزاهة +النزر +النزعة +النزف +النزقة +النزل +النزلاء +النزهة +النزوح +النزوع +النزوف +النزول +النسا +النساء +النساءَ +النسائم +النسائي +النسائية +النساجين +النساطرة +النساك +النسانيس +النسب +النسبة +النسبي +النسبية +النسج +النسخ +النسخة +النسر +النسق +النسل +النسمات +النسوة +النسوي +النسويات +النسوية +النسويين +النسيء +النسيان +النسيج +النسيجي +النسيم +النسيمات +النشأة +النشا +النشاء +النشادرية +النشاط +النشاطات +النشر +النشرات +النشرة +النشط +النشطة +النشطين +النشـيط +النشوء +النشوان +النشوة +النشويات +النشيد +النص +النصائح +النصاب +النصارى +النصال +النصب +النصح +النصر +النصرانية +النصف +النصفي +النصوص +النصية +النصيحة +النصيّة +النصّ +النضال +النضالات +النضالي +النضالية +النضج +النضرة +النضوج +النضوية +النطاح +النطاق +النطح +النطق +النظائر +النظارات +النظارة +النظافة +النظام +النظامي +النظامية +النظامين +النظر +النظرات +النظرة +النظري +النظريات +النظرية +النظم +النظير +النظيرية +النظيف +النظيفة +النعاج +النعاس +النعام +النعرات +النعم +النعمان +النعماني +النعمة +النعناع +النعوت +النعيم +النعيمى +النعيمي +النفائس +النفاثة +النفاخ +النفاذ +النفايات +النفخية +النفر +النفري +النفس +النفساني +النفسبدني +النفسي +النفسية +النفسيين +النفط +النفطى +النفطي +النفطية +النفع +النفعية +النفق +النفقات +النفقة +النفوذ +النفوس +النفي +النفيس +النفيسة +النقائص +النقائض +النقاب +النقابات +النقابة +النقابون +النقابية +النقاد +النقاش +النقاشات +النقاشية +النقاط +النقال +النقالة +النقاهة +النقب +النقد +النقدان +النقدي +النقدية +النقديتين +النقراشي +النقرة +النقش +النقشبندي +النقشبندية +النقشة +النقص +النقطة +النقل +النقلات +النقلة +النقليات +النقمة +النقود +النقوش +النقي +النقية +النقيض +النقيضين +النقّاد +النكات +النكبات +النكبة +النكتة +النكس +النكسة +النكفية +النكهة +النكوتين +النكوص +النمائية +النماذج +النمر +النمسا +النمط +النمطان +النمطية +النمطين +النمل +النملة +النملية +النمو +النموات +النموذج +النموذجي +النموذجية +النموذجين +النمور +النميري +النميمة +النهائي +النهائية +النهار +النهارات +النهامون +النهايات +النهاية +النهب +النهج +النهدين +النهر +النهرية +النهرين +النهرُ +النهضة +النهضوي +النهضوية +النهم +النهمة +النهود +النهوض +النهي +النوء +النواب +النواة +النواحي +النوادر +النوادي +النوارس +النوافذ +النواقل +النوايا +النوب +النوبات +النوبة +النوبيات +النوت +النوتة +النور +النورس +النورمان +النوري +النورين +النوطات +النوع +النوعان +النوعي +النوعيات +النوعية +النوعين +النوفرة +النوق +النوم +النون +النووى +النووي +النووية +النوويد +النوويين +النويهي +النيابة +النيابي +النياندرتالي +النيباليات +النية +النيترات +النيتروجليسرين +النيتروجين +النيتروجينية +النيتريك +النيجر +النيجيريين +النيران +النيفر +النيكل +النيل +النيلية +النيوترونات +النيوتوني +النيوتونية +النيوليتي +النيون +النيوي +النيّة +النيّر +النَفَس +النّاس +النّسق +النّفس +النَّاس +النَّاسُ +النَّبيل +النَّجيبة +النَّحل +النَّدى +النَّفس +الهائل +الهائلة +الهائمات +الهابطة +الهاتف +الهاتفية +الهاجاناة +الهاجس +الهاجعة +الهادئ +الهادئة +الهادر +الهادرة +الهادف +الهادفة +الهادي +الهاديء +الهاربات +الهاربة +الهاربون +الهارموني +الهارمونيكا +الهاشمي +الهاشميات +الهاشمية +الهاضمة +الهافية +الهالة +الهالك +الهام +الهامات +الهامة +الهامدة +الهامش +الهامشي +الهامشية +الهانئون +الهانئين +الهاون +الهبات +الهبة +الهبوط +الهتمي +الهجاء +الهجائية +الهجرات +الهجرة +الهجري +الهجمات +الهجمة +الهجن +الهجوم +الهجين +الهدا +الهدايا +الهداية +الهدف +الهدفين +الهدم +الهدنة +الهدوء +الهدى +الهدي +الهدية +الهدّابي +الهراطقة +الهرب +الهرج +الهرطقات +الهرطقة +الهرم +الهرمة +الهرمون +الهرمونات +الهرموني +الهرمونية +الهروب +الهرولة +الهري +الهزائم +الهزات +الهزاز +الهزة +الهزلية +الهزيع +الهزيلة +الهزيمة +الهستيريا +الهشاشة +الهشة +الهشيم +الهضاب +الهضبة +الهضم +الهضمى +الهضمي +الهضمية +الهكتار +الهكسانول +الهكسوس +الهلا +الهلاك +الهلال +الهلام +الهلامي +الهلاميات +الهلامية +الهلفوت +الهليكوبتر +الهم +الهمالايا +الهمام +الهمبورجر +الهمة +الهمذاني +الهمز +الهمس +الهمم +الهمهمات +الهموم +الهنا +الهناءة +الهنتنجتونية +الهند +الهندسة +الهندسي +الهندسية +الهندوس +الهندي +الهندية +الهنكرة +الهنود +الهواء +الهوائي +الهوائية +الهوائيتان +الهوائيتين +الهواة +الهواتف +الهواجس +الهوامش +الهوايات +الهواية +الهوة +الهودج +الهورمونات +الهوس +الهوكي +الهول +الهولندي +الهولندية +الهولنديين +الهوليوودي +الهوليوودية +الهوهنشتاوفن +الهوى +الهويات +الهوية +الهويّة +الهوّة +الهي +الهيئات +الهيئة +الهياج +الهيبة +الهيبز +الهيثم +الهيدرازين +الهيدروجين +الهيدروجيني +الهيدروجينية +الهيدروكربونات +الهيدروكربونية +الهيدرولية +الهيراطيقية +الهيروئين +الهيستامين +الهيكل +الهيكلة +الهيكلية +الهيلينستي +الهيلينستية +الهيليني +الهيلينية +الهيمالايا +الهيمنة +الهيموجلوبين +الهِرَم +الو +الوأد +الوئيد +الوا +الواب +الواثق +الواجب +الواجبات +الواجهات +الواجهة +الواجهتين +الواحات +الواحة +الواحد +الواحدة +الواحدي +الواحـد +الواد +الوادي +الوارد +الواردات +الواردة +الوازعة +الواسطة +الواسع +الواسعة +الواسعتين +الواصفون +الواصل +الواصلة +الواصلين +الواضح +الواضحة +الواضع +الواعد +الواعدة +الواعي +الواعية +الوافد +الوافدات +الوافدة +الوافدون +الوافدين +الوافر +الوافرة +الوافي +الوافية +الواقع +الواقعة +الواقعي +الواقعية +الواقف +الواقفة +الواقفين +الواقي +الواقيات +الوالد +الوالدان +الوالدين +الوالديين +الوالي +الواهم +الواهنة +الوباء +الوبائي +الوبائية +الوتر +الوترة +الوتيرة +الوثائق +الوثائقية +الوثنية +الوثي +الوثيق +الوثيقة +الوجازة +الوجبات +الوجبة +الوجد +الوجدان +الوجداني +الوجدانية +الوجدي +الوجه +الوجهات +الوجهان +الوجهة +الوجهتين +الوجهية +الوجهين +الوجود +الوجودي +الوجودية +الوجوه +الوجيب +الوجيز +الوجيهة +الوحدات +الوحدانية +الوحدة +الوحدوي +الوحدوية +الوحش +الوحشة +الوحشي +الوحشية +الوحشين +الوحـدة +الوحل +الوحول +الوحي +الوحيد +الوحيدة +الوحيدون +الوحيدين +الوحيدَ +الوخز +الوخيمة +الود +الودائع +الوداع +الوداعة +الوديان +الودية +الوديع +الوذمة +الوراء +الوراثة +الوراثي +الوراثية +الوراق +الورد +الوردة +الوردية +الورع +الورق +الورقة +الورقي +الورقية +الورك +الوركاء +الوركين +الورم +الورمية +الوروار +الورود +الوريد +الوريدي +الوريدية +الوريقات +الوزارات +الوزارة +الوزاري +الوزان +الوزراء +الوزن +الوزير +الوزيرة +الوسائط +الوسائل +الوسادتان +الوسادتين +الوسامة +الوسط +الوسطى +الوسطي +الوسوسة +الوسيط +الوسيطة +الوسيلة +الوسيم +الوشاحي +الوشى +الوشيك +الوصائية +الوصال +الوصايا +الوصاية +الوصف +الوصفات +الوصفة +الوصل +الوصلات +الوصول +الوصولي +الوصية +الوصيفة +الوضع +الوضعية +الوضوء +الوضوح +الوطأة +الوطن +الوطنى +الوطني +الوطنية +الوطنيين +الوطنيّات +الوطيء +الوظائف +الوظيـفة +الوظيفة +الوظيفي +الوظيفية +الوعاء +الوعائي +الوعائية +الوعاظ +الوعر +الوعرة +الوعظ +الوعكة +الوعود +الوعورة +الوعى +الوعي +الوفا +الوفاء +الوفاة +الوفاض +الوفاق +الوفد +الوفدية +الوفرة +الوفود +الوفي +الوفيات +الوفية +الوقائع +الوقائية +الوقار +الوقاية +الوقت +الوقع +الوقف +الوقفات +الوقفة +الوقفيات +الوقود +الوقودات +الوقودية +الوقور +الوقورة +الوقوع +الوقوف +الوقية +الوكالات +الوكالة +الوكالتان +الوكيل +الولاء +الولاءات +الولاة +الولادات +الولادة +الولادي +الولادية +الولايات +الولاية +الولد +الولدان +الولدين +الولع +الولهان +الولهانة +الولهى +الولوج +الولولة +الولي +الوليد +الوليدة +الوليمة +الومضاني +الونكا +الوهاب +الوهاد +الوهج +الوهلة +الوهم +الوهميين +الوهَّاب +الويب +الويل +الوَهَن +الى +الي +اليأس +الياء +اليائس +اليائسة +اليائسين +اليابان +الياباني +اليابانية +اليابانيون +اليابانيين +اليابس +اليابسة +اليازجي +الياسمين +اليافع +اليافعة +اليافعين +الياقات +الياقوت +اليانع +اليباب +اليباس +اليبوسيون +اليتامى +اليتم +اليتيم +اليتيمة +اليحيا +اليد +اليدوي +اليدوية +اليدين +اليرقات +اليرقة +اليرموك +اليسار +اليساري +اليسارية +اليساريين +اليسر +اليسرى +اليسوعية +اليسير +اليسيرة +اليشع +اليعاقبة +اليعقوبية +اليعيزر +اليفاع +اليقظ +اليقظة +اليقين +اليقينية +اليلاتوتين +اليمام +اليمامة +اليماني +اليمانية +اليمن +اليمنى +اليمني +اليمنية +اليمنيين +اليمين +اليمينية +الينا +الينابيع +الينبوع +اليه +اليها +اليهود +اليهودي +اليهودية +اليوجينية +اليود +اليورانيوم +اليورنكو +اليورهارت +اليوريا +اليوسف +اليوسين +اليولكران +اليوم +اليومى +اليومي +اليوميات +اليومية +اليوميةعن +اليومين +اليونان +اليوناني +اليونانية +اليونانيون +اليونانيين +اليونسكو +اليونسيف +اليونيسكو +اليونيسيف +اليونيني +الَّذِينَ +الْتقطت +الْعِلْمَ +الْمُؤْمِنِينَ +الْمُنْكَرِ +الْيُتْم +ام +اما +اماراتيا +امام +امامه +امامي +امبابي +امتاز +امتحان +امتحانات +امتحاناته +امتد +امتداحهم +امتداد +امتدادا +امتداداتها +امتداداً +امتداده +امتدادها +امتدادًا +امتدت +امتدح +امتدحناها +امتدَّ +امتزج +امتزجت +امتصاص +امتصاصاً +امتصاصه +امتصاصها +امتصته +امتطى +امتلأ +امتلأت +امتلاء +امتلاك +امتلاكه +امتلاكها +امتلك +امتلكت +امتناع +امتنع +امتنعت +امتنعوا +امتهانها +امتياز +امتيازات +امتيازاتها +امتيازاً +امتيازه +امتُهن +امحت +امرأة +امرأتك +امرأته +امرأتي +امرأتين +امرئ +امراضية +امريكياً +امسح +امفوراس +امكانية +امنة +امنحهم +امورا +اميل +ان +انا +اناملي +انبثاق +انبثاقا +انبثاقة +انبثق +انبثقت +انبرت +انبعاث +انبعاثها +انبعثت +انبهار +انبهارهم +انبهاري +انبهروا +انت +انتاب +انتابت +انتابتني +انتابته +انتابني +انتابه +انتاجهما +انتاجي +انتان +انتانية +انتباه +انتباهنا +انتباهه +انتباههم +انتباهي +انتبه +انتبهت +انتبهوا +انتبهي +انتج +انتحار +انتحارية +انتحب +انتحرت +انتخاب +انتخابات +انتخاباتهم +انتخابه +انتخابية +انتخب +انتخبت +انتدب +انتركونتيننتال +انترناشيونال +انتزاع +انتزاعها +انتزع +انتزعت +انتزعها +انتساب +انتسابك +انتسبت +انتسبتُ +انتشار +انتشارا +انتشاراً +انتشارسارس +انتشاره +انتشارها +انتشارًا +انتشال +انتشر +انتشرت +انتشروا +انتشلت +انتشله +انتشى +انتصاب +انتصابه +انتصار +انتصارا +انتصارات +انتصاراته +انتصاره +انتصارها +انتصر +انتصروا +انتظار +انتظارا +انتظاراً +انتظارك +انتظارنا +انتظاره +انتظارها +انتظارهم +انتظاري +انتظارًا +انتظام +انتظاما +انتظامه +انتظامها +انتظر +انتظرت +انتظرني +انتظره +انتظروا +انتظري +انتظريني +انتظم +انتعاش +انتعاشاً +انتعشت +انتفاء +انتفاخ +انتفاضات +انتفاضة +انتفت +انتفخ +انتفض +انتفضت +انتفع +انتقاء +انتقاؤها +انتقائي +انتقائيا +انتقاد +انتقادات +انتقادها +انتقاديا +انتقاص +انتقاصاً +انتقال +انتقاله +انتقالها +انتقالي +انتقالية +انتقام +انتقاما +انتقت +انتقد +انتقدتها +انتقدنا +انتقـال +انتقل +انتقلت +انتقلنا +انتقم +انتقى +انتماء +انتماءات +انتماءاتنا +انتماؤه +انتمائه +انتمائهم +انتمي +انتمينا +انتهاء +انتهاءها +انتهاءً +انتهائكم +انتهائه +انتهائها +انتهائي +انتهازي +انتهازية +انتهاك +انتهاكا +انتهاكاً +انتهاكها +انتهت +انتهز +انتهوا +انتهى +انتهي +انتهيت +انتهيتُ +انتهينا +انثقاب +انجذبت +انجزته +انجلاء +انجلترا +انحاء +انحازت +انحدر +انحدرت +انحراف +انحرافا +انحرافاً +انحرافها +انحرافًا +انحرف +انحسار +انحسارا +انحساراً +انحساره +انحسر +انحشار +انحصر +انحطاط +انحطاطنا +انحفر +انحل +انحناء +انحناءات +انحناءة +انحنت +انحياز +انحيازنا +انحيازه +انخرطت +انخرطتُ +انخرطوا +انخفاض +انخفاضا +انخفاضاً +انخفاضًا +انخفض +انخفضت +انخناقه +اند +اندثار +اندثارها +اندثرت +اندثروا +اندرج +اندريه +اندفاع +اندفاعاته +اندفاعه +اندفاعها +اندفاعهم +اندفع +اندفعت +اندفعنا +اندفعوا +اندلاع +اندلاعها +اندلع +اندلعت +اندماج +اندماجه +اندمج +اندمجت +اندهاشهم +اندهش +اندهشت +انزعاج +انزعج +انزعجوا +انزل +انزلاق +انزوت +انساب +انسان +انسباط +انسجام +انسجاماً +انسجامي +انسحاب +انسحابه +انسحب +انسحقت +انسداد +انسداداً +انسداده +انسقت +انسل +انسلاخ +انسلاخهم +انسلال +انسى +انسيابه +انسيابياً +انشاء +انشاؤها +انشقّتْ +انصب +انصباب +انصبت +انصراف +انصرافه +انصرافهم +انصرافي +انصرف +انصرفت +انصهار +انصهرت +انضم +انضمام +انضمامكم +انضمت +انضممت +انضوائها +انطباعاته +انطباعاً +انطباعك +انطباعي +انطباعية +انطبع +انطبعت +انطبق +انطراحه +انطفأت +انطفاء +انطلاق +انطلاقا +انطلاقاً +انطلاقة +انطلاقتها +انطلاقتي +انطلاقًا +انطلق +انطلقت +انطلقنا +انطلقوا +انطوت +انظافة +انظر +انظري +انظمة +انعتاق +انعتاقه +انعدام +انعدمت +انعزال +انعزالهم +انعطف +انعطفنا +انعقاد +انعقادها +انعقد +انعقدت +انعكاس +انعكاسا +انعكاسات +انعكاساتها +انعكاساً +انعكس +انعكست +انفتاح +انفتاحي +انفتح +انفتحت +انفتحتْ +انفجار +انفجارات +انفجاراتها +انفجاره +انفجارها +انفجاري +انفجر +انفجرت +انفراج +انفراجاً +انفراداته +انفراديا +انفراط +انفرد +انفردت +انفصال +انفصالا +انفصام +انفصل +انفض +انفضاض +انفعال +انفعالات +انفعالاته +انفعالاتي +انفعاله +انفعالي +انفعالية +انفكوا +انفلت +انقاذ +انقباض +انقر +انقراض +انقرض +انقرضت +انقسام +انقسامات +انقساماً +انقسمت +انقسموا +انقضائها +انقضاضه +انقضت +انقضوا +انقضى +انقطاع +انقطاعه +انقطاعها +انقطع +انقطعت +انقلاب +انقلابا +انقلابات +انقلاباً +انقلبت +انكبت +انكبّ +انكبَّ +انكتب +انكسار +انكشافه +انكشف +انكشفت +انكفأت +انكفاء +انكم +انكمش +انما +اننا +انني +انه +انها +انهالت +انهت +انهضي +انهم +انهماك +انهمك +انهن +انهى +انهي +انهيار +انهيارات +انهياره +انهيارها +انهيال +اني +اهتدوا +اهتدى +اهتديت +اهتز +اهتزاز +اهتزازات +اهتزازه +اهتزت +اهتم +اهتمام +اهتماما +اهتمامات +اهتماماتك +اهتماماتنا +اهتماماته +اهتماماتها +اهتماماتهم +اهتماماتي +اهتماماً +اهتمامكم +اهتمامنا +اهتمامه +اهتمامها +اهتمامهم +اهتمامي +اهتمامًا +اهتمت +اهتممت +اهتممتم +اهتموا +اهدأ +اهدئي +اهديه +اهريتش +اهلنه +اهمال +اهمها +اهمية +اهميتها +او +اور +اوربا +اوربينا +اورشاليم +اوستن +اوسلو +اولئك +اولمرت +اوما +اى +اي +ايام +ايان +اياها +اية +ايتان +ايجال +ايران +ايزوب +ايسلندا +ايضا +ايطاليا +ايطالية +ايقاعاتها +ايقظ +اين +اينما +ايها +ايهود +ايودين +اَلْمُسْتَشْفَى +اِسْتِخْدَامها +ب +بآثار +بآثارنا +بآثارها +بآثامه +بآخر +بآداب +بآدابهما +بآراء +بآرائه +بآسيا +بآفات +بآفاق +بآلات +بآلاف +بآلام +بآلة +بآلية +بآن +بآهات +بأبجديات +بأبحاثه +بأبدان +بأبرز +بأبشع +بأبعاد +بأبعاده +بأبناء +بأبنائه +بأبنيتها +بأبها +بأبهى +بأبو +بأبي +بأبيات +بأبياته +بأتلانتا +بأتيلييه +بأثر +بأثمان +بأثواب +بأجزائه +بأجسامنا +بأجسامها +بأجسامهم +بأجمل +بأجنحة +بأجنحته +بأجنحتها +بأجهزة +بأحاديثه +بأحاديثهم +بأحد +بأحداث +بأحداثه +بأحدث +بأحدكم +بأحذية +بأحرف +بأحزان +بأحزانك +بأحزمة +بأحسن +بأحشاء +بأحكام +بأحلام +بأحوال +بأخبار +بأخته +بأخذ +بأخرى +بأخلاق +بأخلاقيات +بأخواتها +بأخوة +بأخي +بأداء +بأدائها +بأدب +بأدبية +بأدوات +بأدواتها +بأدوارها +بأدونيس +بأدوية +بأديان +بأذن +بأذني +بأذنيه +بأذى +بأربع +بأربعة +بأرشاك +بأرض +بأرضيته +بأرفف +بأرقي +بأرواحنا +بأريج +بأريحية +بأزمات +بأزمة +بأس +بأسئلة +بأسئلته +بأسئلتها +بأسئلتي +بأسا +بأسابيع +بأساتذة +بأساسياته +بأساليب +بأساليبها +بأسباب +بأسبابها +بأسبوعين +بأستاذه +بأستوكهولم +بأسد +بأسرار +بأسراره +بأسرارها +بأسرارهم +بأسرته +بأسرع +بأسره +بأسرها +بأسطح +بأسطوانات +بأسطورة +بأسعار +بأسعاره +بأسعارها +بأسلحة +بأسلحته +بأسلوب +بأسلوبه +بأسلوبها +بأسلوبين +بأسماء +بأسمائها +بأسمى +بأسنانهم +بأسهل +بأسهم +بأسواق +بأسى +بأشجار +بأشد +بأشعارها +بأشعة +بأشق +بأشكال +بأشكالها +بأشهى +بأشياء +بأصابع +بأصابعها +بأصابعي +بأصبعه +بأصحاب +بأصحابه +بأصدقاء +بأصدقائه +بأصناف +بأصوات +بأصول +بأصولها +بأضرار +بأضراره +بأضعاف +بأطراف +بأطروحة +بأطوار +بأطوال +بأطياف +بأعجوبة +بأعداد +بأعراض +بأعصاب +بأعضائه +بأعلام +بأعلى +بأعمار +بأعماق +بأعمال +بأعماله +بأعمدة +بأعوام +بأعيادهم +بأعينهم +بأفراحها +بأفرازات +بأفريقيا +بأفضل +بأفعالنا +بأفكار +بأفكاره +بأفكارهم +بأفواههم +بأقاربها +بأقدار +بأقدامهم +بأقدامي +بأقرب +بأقصاب +بأقصى +بأقل +بأقلام +بأقلمة +بأكاديمية +بأكبر +بأكثر +بأكداس +بأكسدة +بأكسفورد +بأكمله +بأكملها +بأكوام +بأكياس +بألا +بألاعيب +بألاَّ +بألحان +بألحانه +بألعاب +بألعابه +بألعابها +بألعابهم +بألفي +بألم +بألمانيا +بألواح +بألوان +بألوانه +بألوانها +بألواني +بألياف +بأم +بأماكن +بأمان +بأمانة +بأمتار +بأمتها +بأمر +بأمراض +بأمره +بأمرها +بأمريكا +بأمرين +بأمطارها +بأمكا +بأمل +بأممية +بأمن +بأمه +بأمها +بأمواج +بأمور +بأمي +بأمير +بأمّته +بأن +بأنسابهم +بأنشطة +بأنطاكية +بأنظارها +بأنظمة +بأنــني +بأنفسنا +بأنفسهم +بأنك +بأننا +بأنني +بأنه +بأنها +بأنهم +بأنهما +بأنهن +بأنوار +بأنواع +بأنواعه +بأنواعها +بأنواعهـا +بأنور +بأني +بأنّ +بأهداف +بأهرام +بأهل +بأهله +بأهم +بأهمية +بأهميتها +بأهواء +بأواصر +بأوامر +بأوراد +بأوراق +بأورام +بأوربا +بأوسكار +بأوضح +بأوقات +بأوقاتهم +بأول +بأى +بأي +بأيام +بأيامنا +بأية +بأيد +بأيدى +بأيدي +بأيدينا +بأيديهم +بأيديهما +بأيسر +بؤبؤ +بؤر +بؤرة +بؤرية +بؤس +بؤسا +بؤسها +بإ +بإبداء +بإبداع +بإبداعية +بإبراز +بإبقاء +بإبقائه +بإبقائها +بإتاحة +بإتاحته +بإتاوات +بإتخاذ +بإتقان +بإتلافه +بإجازته +بإجراء +بإجراءات +بإجماع +بإجمالي +بإجهاد +بإحالة +بإحباط +بإحداث +بإحداثها +بإحدى +بإحراقها +بإحصائيات +بإحضار +بإحضارها +بإحكام +بإحيائهم +بإخراج +بإخفاء +بإخلاص +بإخواننا +بإخوانها +بإداراتها +بإدارة +بإدانتها +بإدخال +بإدخالها +بإدخالِ +بإذابة +بإذلال +بإذن +بإرادة +بإرادته +بإرجاعها +بإرسال +بإرشاده +بإزاء +بإزالة +بإزعاج +بإستانبول +بإسرائيل +بإسقاط +بإسقاطاتها +بإسمي +بإسهاب +بإسهال +بإشارات +بإشارة +بإشباع +بإشراف +بإشرافه +بإشفاق +بإصابة +بإصبعه +بإصبعها +بإصدار +بإصدارات +بإصرار +بإضاءة +بإضافة +بإضافتها +بإطار +بإطلاق +بإعادة +بإعادته +بإعاقة +بإعجاب +بإعجابهم +بإعجاز +بإعداد +بإعدادها +بإعدامه +بإعطاء +بإعطائه +بإعلان +بإعمار +بإعياء +بإفراز +بإفراط +بإفريقيا +بإقامة +بإقبال +بإقصاء +بإقليم +بإكسير +بإلحاح +بإلزام +بإلقاء +بإلقائها +بإله +بإليجا +بإمارة +بإمبراطوره +بإمعانٍ +بإمكان +بإمكانك +بإمكاننا +بإمكانها +بإمكانهم +بإمكاني +بإمكانية +بإميلشيل +بإنارة +بإنتاج +بإنتاجي +بإنجاب +بإنجاح +بإنجاحها +بإنجاز +بإنجازه +بإنجلترا +بإنجليزيته +بإنذار +بإنزاله +بإنسان +بإنسانية +بإنشاء +بإنفاقهم +بإنقاذ +بإنكار +بإهانة +بإهدار +بإهلاكه +بإيجاد +بإيجاز +بإيحاءات +بإيذاء +بإيراد +بإيران +بإيصال +بإيعازها +بإيقاع +بإيقاعها +بإيقاف +بإيواء +بئر +بئرا +با +باء +باءت +باأقول +بائتة +بائس +بائسة +بائع +بائعا +بائعاً +بائعة +باب +بابا +باباياناكيس +باباً +بابة +بابتسامة +بابتكار +بابتكاره +بابتلاعها +بابل +بابليون +بابن +بابنته +بابنه +بابه +بابها +بابور +بابوية +بابي +بابين +بابٍ +بات +باتا +باتاً +باتباع +باتباعه +باتت +باتجاه +باتجاهنا +باتجاههما +باتحاد +باتخاذ +باترك +باتريا +باتريس +باتريك +باتساع +باتصالات +باتصاله +باتفاقيات +باتهامات +باتهامها +باتي +باثا +باثاك +باثنى +باجتثاث +باجتذاب +باجترار +باجتهاد +باجر +باحة +باحترام +باحترامها +باحتفال +باحتقار +باحتلال +باحتمال +باحتمالاته +باحتياجاتهم +باحث +باحثا +باحثان +باحثاً +باحثة +باحثون +باحثي +باحثين +باحثًا +باخت +باختباره +باختراع +باختراعه +باختراق +باختصار +باختصاص +باختفاء +باختلاجات +باختلاف +باختلافنا +باختلافها +باختناق +باختيار +باختيارها +باختياري +باخرة +بادئ +بادئا +بادرات +بادرة +بادرت +بادرنا +بادره +بادروا +بادش +بادل +بادلته +بادوا +بادوك +بادىء +بادياً +بادية +باديس +بادٍ +باذخة +باذلة +باذله +باذلين +باذنجان +بار +باراك +باراكس +بارانا +باراي +باراً +باربارة +بارباروسا +باربر +بارت +بارتاجاس +بارتعاشٍ +بارتفاع +بارتلز +بارتليه +بارتوتشيل +بارتون +بارتي +بارتياب +بارتياح +بارحام +بارد +باردة +باردين +باردًا +بارز +بارزا +بارزاً +بارزة +بارزتين +بارزون +بارزين +بارزًا +بارسيمان +بارع +بارعا +بارعات +بارعاً +بارعة +بارعًا +بارقة +بارك +باركر +باركي +باروح +بارود +بارون +باريس +باريسية +باريمور +بارين +باريه +باز +بازدحام +بازدهار +بازدهاره +بازدياد +بازية +بازيل +باس +باستئجار +باستئصال +باستئناف +باستا +باستباب +باستبدال +باستثارة +باستثمار +باستثمارها +باستثناء +باستجلاء +باستحسان +باستحضار +باستحقاقاتها +باستخدام +باستخدامات +باستخداماته +باستخدامها +باستخراج +باستخفاف +باستخلاص +باستدعائنا +باسترداد +باستشراف +باستشهاد +باستصلاح +باستطاعة +باستطاعته +باستطاعتها +باستطاعتهم +باستطاعتي +باستطلاع +باستعادة +باستعارات +باستعراض +باستعمال +باستعمالها +باستقالتها +باستقالتي +باستقبال +باستقطاع +باستقلال +باستكمالها +باستلام +باستماتة +باستمرار +باستمراره +باستنشاق +باستهتارك +باستهلاك +باستوكهولم +باستير +باستيراد +باستيطانات +باسر +باسـتمرار +باسكندرونة +باسم +باسما +باسمائهم +باسماً +باسمك +باسمنا +باسمه +باسمها +باسمهم +باسمي +باسيلوس +باسيو +باشا +باشتراكيتها +باشر +باشراقات +باشمئزاز +باصابتهم +باصدقي +باصطحاب +باصقة +باضطراب +باضطرابات +باطراد +باطلا +باطلاق +باطن +باطنها +باع +باعة +باعت +باعتبار +باعتبارك +باعتباره +باعتبارها +باعتبارهم +باعتبارهما +باعتباري +باعتراف +باعتزاز +باعتزال +باعتقال +باعتقالها +باعتماد +باعتماده +باعتمادها +باعته +باعث +باعثة +باعوا +بافاريا +بافتتانه +بافتراض +بافتقادها +بافقيه +باق +باقادر +باقة +باقتحام +باقتراب +باقتراح +باقتصاديات +باقتضاب +باقتفاء +باقتناء +باقر +باقول +باقى +باقي +باقية +باك +باكتساب +باكتشاف +باكتشافِ +باكتظاظ +باكثير +باكرا +باكراً +باكستان +باكستاني +باكستانية +باكورة +باكورتي +باكوف +باكيات +باكياً +باكيًا +بال +بالآباء +بالآتي +بالآثار +بالآثام +بالآخر +بالآخرين +بالآداب +بالآراء +بالآلاف +بالآلة +بالآلية +بالآمال +بالأب +بالأباخس +بالأبجدية +بالأبحاث +بالأبخرة +بالأبدية +بالأبراج +بالأبصار +بالأبنية +بالأبواب +بالأبيات +بالأبيض +بالأتابك +بالأثاث +بالأجساد +بالأجسام +بالأجنة +بالأجهزة +بالأجيال +بالأحجار +بالأحداث +بالأحرف +بالأحرى +بالأحزان +بالأحقاد +بالأحكام +بالأحلام +بالأحمر +بالأحياء +بالأخبار +بالأخذ +بالأخص +بالأخضر +بالأخلاق +بالأخيرة +بالأداء +بالأدب +بالأدباء +بالأدعية +بالأدلة +بالأدوات +بالأدوار +بالأديان +بالأذرة +بالأذى +بالأذية +بالأراضي +بالأربعين +بالأردن +بالأرز +بالأرض +بالأرق +بالأرمن +بالأزرق +بالأزهر +بالأسئلة +بالأساس +بالأساليب +بالأسباب +بالأسبقية +بالأسبوع +بالأسر +بالأسرة +بالأسطورة +بالأسع +بالأسعار +بالأسف +بالأسلحة +بالأسلوب +بالأسماء +بالأسمنت +بالأسنان +بالأسهم +بالأسوار +بالأسواق +بالأسى +بالأشجار +بالأشعة +بالأشكال +بالأشواك +بالأشياء +بالأصقاع +بالأصل +بالأصنام +بالأضلاع +بالأضواء +بالأطعمة +بالأطفال +بالأظافر +بالأعباء +بالأعداء +بالأعراض +بالأعصاب +بالأعمال +بالأعين +بالأفاعي +بالأفاقية +بالأفاويه +بالأفضل +بالأفضلِ +بالأفعال +بالأفق +بالأفلاج +بالأفلام +بالأقدام +بالأقراط +بالأقران +بالأقصر +بالأقطار +بالأقمار +بالأقنعة +بالأكاديمية +بالأكثر +بالأكثرية +بالأكسجين +بالأكسدة +بالأكل +بالألباني +بالألبوم +بالألفية +بالألم +بالألمان +بالألماني +بالألمانية +بالألوان +بالألياف +بالأماكن +بالأمان +بالأمر +بالأمراض +بالأمريكيين +بالأمس +بالأمشاج +بالأمطار +بالأمعاء +بالأمل +بالأملاح +بالأمم +بالأمن +بالأمواج +بالأمور +بالأمير +بالأميرات +بالأنا +بالأناشيد +بالأناناس +بالأنبياء +بالأندلس +بالأنشطة +بالأنفلونزا +بالأنماط +بالأنواع +بالأوتار +بالأوحال +بالأوراق +بالأوربيين +بالأوضاع +بالأوقات +بالأوكسجين +بالإبحار +بالإبداع +بالإبرة +بالإبصار +بالإثارة +بالإجابة +بالإجماع +بالإحاطة +بالإحباط +بالإحساس +بالإخاء +بالإختناق +بالإدراك +بالإذعان +بالإرث +بالإرشادات +بالإرهاب +بالإرهاق +بالإستزادة +بالإستشفاء +بالإسكندرية +بالإسلام +بالإسهال +بالإشارة +بالإشاعات +بالإشعاع +بالإشعاعات +بالإشكاليات +بالإصدار +بالإضاءة +بالإضافة +بالإضافةإلى +بالإطار +بالإطلاع +بالإطلالة +بالإعاقة +بالإعجاب +بالإعداد +بالإعدام +بالإعراض +بالإعلام +بالإعلان +بالإفراج +بالإفراط +بالإقامة +بالإقلاع +بالإقليم +بالإلحاح +بالإمارات +بالإمام +بالإمعان +بالإمكان +بالإنتاج +بالإنترنت +بالإنجازات +بالإنجليزية +بالإنجيل +بالإنزيمات +بالإنسان +بالإنسانية +بالإنعام +بالإهانة +بالإهداء +بالإهدار +بالإهمال +بالإيجاب +بالإيدز +بالإيقاع +بالإيمان +بالابتسام +بالابتعاد +بالابتلاع +بالاتجاه +بالاتجاهات +بالاتحاد +بالاتصال +بالاتفاق +بالاثنين +بالاجتهاد +بالاحبال +بالاحترام +بالاحتفاء +بالاحتفاظ +بالاحتفال +بالاحتفالية +بالاحتلال +بالاحرى +بالاختبارات +بالاختزال +بالاختصاصات +بالاختلاج +بالاختلاجات +بالاختلاسات +بالاختلاف +بالاختلالات +بالاختناق +بالاختيار +بالاخر +بالادخار +بالارتباط +بالارتجال +بالارتفاع +بالارتياح +بالارد +بالاس +بالاستثمار +بالاستحمام +بالاسترخاء +بالاستروجين +بالاستطلاع +بالاستعانة +بالاستعمار +بالاستفادة +بالاستقلال +بالاستلقاء +بالاستماع +بالاستمرار +بالاستنشاق +بالاستيطان +بالاستيقاظ +بالاسم +بالاشتراك +بالاشتمال +بالاضافة +بالاضمحلال +بالاعتبار +بالاعتبارين +بالاعتداء +بالاعتقاد +بالاعتلال +بالاعتماد +بالاعمال +بالافتراق +بالاقتباس +بالاقتداء +بالاقتراب +بالاقتصاد +بالاقتصاص +بالاكتئاب +بالالتحاق +بالالتزام +بالالتصاق +بالالتفات +بالالتهاب +بالامتحان +بالامتلاء +بالامر +بالانتان +بالانتباه +بالانترنت +بالانتشار +بالانتصار +بالانتفاع +بالانتماء +بالانجليزية +بالانحدار +بالانحناء +بالانخراط +بالانخفاض +بالانزواء +بالانسحاب +بالانصاف +بالانصراف +بالانضباط +بالانضمام +بالانطباعية +بالانعكاس +بالانفجار +بالانفصال +بالانفلونزا +بالانقراض +بالانقلاب +بالانكفاء +بالاهتزاز +بالاهتمام +بالاً +بالباب +بالبابوية +بالباص +بالباطل +بالباعة +بالباكستان +بالبامبو +بالبترول +بالبث +بالبثور +بالبحث +بالبحر +بالبحرين +بالبحيرة +بالبدء +بالبدانة +بالبدن +بالبذرة +بالبراءة +بالبرامج +بالبرامية +بالبربرية +بالبرد +بالبرلمان +بالبرنامج +بالبروبليس +بالبروز +بالبريد +بالبريق +بالبساتين +بالبساطة +بالبسملة +بالبشر +بالبشرة +بالبضائع +بالبطن +بالبطولات +بالبطولة +بالبعد +بالبعض +بالبعيد +بالبقاء +بالبكاء +بالبكتيريا +بالبلاد +بالبلد +بالبلدان +بالبلدة +بالبناء +بالبنان +بالبندقية +بالبنزين +بالبنك +بالبنية +بالبنيوية +بالبهجة +بالبهلوان +بالبهلول +بالبوابات +بالبواخر +بالبوح +بالبولب +بالبيئة +بالبيانات +بالبيانو +بالبيت +بالبيرق +بالبيزنطيين +بالبيع +بالبيوض +بالتأريخ +بالتأقلم +بالتأكد +بالتأكيد +بالتأمل +بالتأنث +بالتئام +بالتاريخ +بالتالى +بالتالي +بالتبشير +بالتبعية +بالتبني +بالتتابع +بالتثقيف +بالتجاهل +بالتجديد +بالتجربة +بالتجريب +بالتجريد +بالتجعّدات +بالتجمد +بالتجمع +بالتجوال +بالتجول +بالتحاب +بالتحدث +بالتحديد +بالتحديق +بالتحذير +بالتحرك +بالتحف +بالتحقق +بالتحقيق +بالتحكم +بالتحلل +بالتحليل +بالتحول +بالتحولات +بالتحية +بالتخثر +بالتخطيط +بالتخلص +بالتخلف +بالتخلي +بالتدريب +بالتدريج +بالتدريس +بالتدرّج +بالتدفق +بالتدقيق +بالتدني +بالتدهور +بالتذكّر +بالتراب +بالتراث +بالترام +بالتربة +بالتربية +بالترتيب +بالترجمة +بالترحّم +بالتردد +بالترع +بالترفيه +بالترقّي +بالتركية +بالتركيز +بالتزام +بالتزامات +بالتزاماتها +بالتزلج +بالتزويق +بالتسامح +بالتسامي +بالتساوي +بالتسجيل +بالتسرُّب +بالتسلق +بالتسمم +بالتسوق +بالتشاؤم +بالتشجيع +بالتشخيص +بالتشريع +بالتشريعات +بالتشفي +بالتشويه +بالتصحيح +بالتصفيق +بالتصميم +بالتصوير +بالتصوّف +بالتضخم +بالتطبيق +بالتطلع +بالتطهير +بالتطور +بالتطوير +بالتظاهر +بالتعاون +بالتعب +بالتعبير +بالتعجيل +بالتعددية +بالتعديل +بالتعذيب +بالتعرض +بالتعرف +بالتعصب +بالتعليم +بالتعليمات +بالتعميم +بالتعويض +بالتفاؤل +بالتفاصيل +بالتفاعل +بالتفوق +بالتقانيات +بالتقدم +بالتقدير +بالتقرب +بالتقسيط +بالتقصير +بالتقنيات +بالتقنية +بالتقوى +بالتكثف +بالتكذيب +بالتكنولوجيا +بالتكوينات +بالتلاشي +بالتلاقي +بالتلحين +بالتلوُّث +بالتليفزيون +بالتماثل +بالتمارين +بالتماس +بالتمام +بالتمثيل +بالتمدد +بالتمرد +بالتمردات +بالتمسك +بالتمويل +بالتنازل +بالتناقص +بالتناقضات +بالتنبيه +بالتنسيق +بالتنصت +بالتنصّر +بالتنظير +بالتنقيب +بالتنكس +بالتنمية +بالتنوع +بالتنوير +بالتهاب +بالتهابات +بالتهجير +بالتهديد +بالتهرب +بالتوابيت +بالتوازي +بالتواصل +بالتواضع +بالتواطؤ +بالتوافد +بالتوالد +بالتوتر +بالتوجه +بالتوجيه +بالتوحيد +بالتورط +بالتوقيع +بالتي +بالتيبس +بالثانوية +بالثاني +بالثدييات +بالثروات +بالثروة +بالثقافات +بالثقافة +بالثقافي +بالثقب +بالثقة +بالثقوب +بالثلوج +بالثمن +بالثواني +بالجائزة +بالجاذبية +بالجاروف +بالجامع +بالجامعات +بالجامعة +بالجان +بالجانب +بالجبال +بالجثة +بالجحر +بالجحود +بالجد +بالجدار +بالجديد +بالجذور +بالجرأة +بالجراح +بالجراحة +بالجرح +بالجروح +بالجريدة +بالجزء +بالجزئيات +بالجزائر +بالجزر +بالجزع +بالجزيرة +بالجسم +بالجلد +بالجلدرات +بالجلوس +بالجمال +بالجمرة +بالجمع +بالجمعيات +بالجمعية +بالجملة +بالجمهرة +بالجمهور +بالجمود +بالجميع +بالجنة +بالجنس +بالجنوب +بالجنود +بالجنون +بالجنين +بالجهات +بالجهاد +بالجهاز +بالجهامة +بالجهد +بالجهل +بالجهود +بالجوائز +بالجوانب +بالجودة +بالجوز +بالجوع +بالجولات +بالجوهر +بالجيزة +بالجيش +بالجينات +بالحاجة +بالحادثة +بالحاضر +بالحافلة +بالحال +بالحالة +بالحامض +بالحب +بالحبال +بالحبة +بالحبل +بالحبوب +بالحتم +بالحج +بالحجاب +بالحجاز +بالحجة +بالحجر +بالحجز +بالحجم +بالحد +بالحدود +بالحديث +بالحديد +بالحديقة +بالحذاء +بالحرائر +بالحرارة +بالحراسة +بالحرب +بالحرباء +بالحرج +بالحرص +بالحرف +بالحرفية +بالحركات +بالحركة +بالحروب +بالحروف +بالحرية +بالحزام +بالحزب +بالحس +بالحسابات +بالحشرات +بالحشف +بالحصان +بالحصباء +بالحصول +بالحضارات +بالحضارة +بالحضور +بالحفر +بالحفظ +بالحفل +بالحق +بالحقائق +بالحقوق +بالحقيقة +بالحكم +بالحكمة +بالحل +بالحلق +بالحلي +بالحليب +بالحماسة +بالحماقات +بالحمامات +بالحمامتين +بالحماية +بالحملة +بالحمى +بالحمّى +بالحناء +بالحنق +بالحنين +بالحوسبة +بالحول +بالحياة +بالحيرة +بالحيف +بالحيوان +بالحيوانات +بالحيوية +بالخارج +بالخالدية +بالخبر +بالخبراء +بالخبرة +بالخجل +بالخدر +بالخدمات +بالخرسانة +بالخرقة +بالخرنفش +بالخروج +بالخريج +بالخسائر +بالخشب +بالخصوبة +بالخصوصية +بالخضار +بالخضراوات +بالخضروات +بالخضيري +بالخط +بالخطأ +بالخطة +بالخطر +بالخطط +بالخطوط +بالخفاش +بالخفق +بالخلايا +بالخلق +بالخلود +بالخليج +بالخمر +بالخنجر +بالخواء +بالخوف +بالخيار +بالخيال +بالخيامية +بالخير +بالخيش +بالخيط +بالخيمة +بالخيوط +بالخيول +بالخَـلَف +بالدائري +بالداخل +بالدار +بالدخان +بالدخول +بالدراسات +بالدراسة +بالدرجات +بالدرجة +بالدرس +بالدروع +بالدستور +بالدعاء +بالدعوة +بالدفء +بالدفع +بالدقيق +بالدقيقة +بالدك +بالدكتور +بالدكتورة +بالدلتا +بالدليل +بالدم +بالدماء +بالدمام +بالدموع +بالدناءة +بالدنيا +بالدهشة +بالدوافع +بالدوحة +بالدورقبل +بالدورين +بالدوس +بالدول +بالدولار +بالدولة +بالدونية +بالديانة +بالدير +بالديمقراطية +بالديموتيقية +بالدين +بالديني +بالديون +بالدّعاء +بالذات +بالذرة +بالذكر +بالذكرى +بالذكري +بالذكريات +بالذل +بالذنب +بالذهب +بالذين +بالرأس +بالرأي +بالرؤية +بالرئة +بالرئتين +بالرئيس +بالراحة +بالراحل +بالرافدين +بالرباط +بالربح +بالربع +بالربو +بالرتق +بالرجال +بالرجل +بالرجوع +بالرحلة +بالرحيل +بالرخام +بالرد +بالرذاذ +بالرسائل +بالرسالات +بالرسالة +بالرسل +بالرسو +بالرسوم +بالرصاص +بالرضا +بالرعاية +بالرعب +بالرفاق +بالرفض +بالرقابة +بالرقبة +بالرقة +بالرقص +بالرقم +بالركاكة +بالركعة +بالركون +بالرمال +بالرمز +بالرمل +بالرمو +بالرهبة +بالروابط +بالروافد +بالرواية +بالروح +بالروزنامة +بالروسية +بالروماتيزم +بالرياح +بالريادة +بالرياض +بالريح +بالريشة +بالرُها +بالزاد +بالزاهيات +بالزجاج +بالزراعة +بالزرنيخ +بالزعيم +بالزكاة +بالزمالك +بالزمن +بالزهو +بالزهور +بالزواج +بالزوار +بالزوجين +بالزورق +بالزيارات +بالزيارة +بالزيت +بالسؤال +بالسائحين +بالساحة +بالسادس +بالساعات +بالساعة +بالسالمية +بالسالين +بالسب +بالسبق +بالسجاد +بالسجن +بالسحر +بالسخاء +بالسخرية +بالسذاجة +بالسردين +بالسرطا +بالسرطان +بالسرطانات +بالسرعة +بالسرقة +بالسروج +بالسريع +بالسعادة +بالسعال +بالسعفة +بالسعودية +بالسفارة +بالسفر +بالسفن +بالسكان +بالسكتة +بالسكر +بالسكن +بالسل +بالسلاح +بالسلالات +بالسلة +بالسلطات +بالسلطان +بالسلطة +بالسلم +بالسلوقي +بالسلوكيات +بالسلوم +بالسماح +بالسمك +بالسموم +بالسن +بالسنة +بالسنين +بالسهر +بالسهلة +بالسهولة +بالسوء +بالسواد +بالسودانيين +بالسوس +بالسوط +بالسوق +بالسويس +بالسويك +بالسياحة +بالسياحـة +بالسيارات +بالسيارة +بالسياسة +بالسيرة +بالسيطرة +بالسينما +بالسيوف +بالسيّاب +بالشأن +بالشؤون +بالشاب +بالشاحنات +بالشاطئ +بالشاعرية +بالشاليهات +بالشام +بالشاهد +بالشباب +بالشباك +بالشبكة +بالشبكية +بالشبه +بالشبهة +بالشخصيات +بالشخصية +بالشخير +بالشراء +بالشرائح +بالشرائط +بالشراسة +بالشرح +بالشرف +بالشرق +بالشرقية +بالشركة +بالشروط +بالشظف +بالشعاب +بالشعارات +بالشعب +بالشعر +بالشعراء +بالشعوب +بالشعور +بالشـــراء +بالشفاء +بالشفافية +بالشك +بالشكر +بالشكل +بالشلل +بالشمال +بالشمس +بالشمع +بالشهادات +بالشهادتين +بالشهرة +بالشهيد +بالشواطئ +بالشواهد +بالشوكولاتة +بالشيء +بالشيح +بالشيخ +بالشيخوخة +بالشيطان +بالشيكولاته +بالصابون +بالصانع +بالصبر +بالصحافة +بالصحة +بالصحراء +بالصحف +بالصحيفة +بالصداقة +بالصدام +بالصدر +بالصدف +بالصدفة +بالصدق +بالصراخ +بالصراع +بالصراعات +بالصرع +بالصرف +بالصعود +بالصفاء +بالصلاة +بالصلاحية +بالصلب +بالصلح +بالصلصال +بالصلوات +بالصمت +بالصور +بالصورة +بالصوفي +بالصياح +بالصيدلة +بالصين +بالصّابون +بالضآلة +بالضابط +بالضاحية +بالضبابية +بالضبط +بالضجر +بالضحك +بالضرب +بالضرورة +بالضروري +بالضعفاء +بالضفة +بالضمادات +بالضمان +بالضمير +بالضوء +بالضوابط +بالضياع +بالضيق +بالطائر +بالطائرات +بالطائرة +بالطائف +بالطابع +بالطابق +بالطابوق +بالطالبان +بالطب +بالطبع +بالطبقة +بالطبيب +بالطبيعة +بالطرح +بالطرد +بالطرق +بالطريق +بالطريقة +بالطعام +بالطفلين +بالطفيل +بالطقس +بالطلاب +بالطلب +بالطمأنينة +بالطموح +بالطهارة +بالطو +بالطول +بالطيب +بالطير +بالطيران +بالطين +بالطيور +بالظاهر +بالظاهرة +بالظفر +بالظلام +بالظلم +بالظهران +بالظهور +بالظواهر +بالعائل +بالعائلة +بالعات +بالعاج +بالعادات +بالعار +بالعاصمة +بالعاطفة +بالعالم +بالعالمية +بالعالمين +بالعام +بالعامية +بالعباءة +بالعبادات +بالعباسية +بالعبرية +بالعبقري +بالعبقرية +بالعبودية +بالعبيد +بالعثور +بالعجائز +بالعجب +بالعجز +بالعجمي +بالعدالة +بالعداوة +بالعدل +بالعدو +بالعديد +بالعذوبة +بالعراق +بالعراك +بالعرب +بالعربة +بالعربي +بالعربية +بالعرض +بالعرق +بالعروبة +بالعسل +بالعش +بالعشاء +بالعشرات +بالعصر +بالعصي +بالعصيدة +بالعض +بالعضوية +بالعطاءات +بالعطب +بالعطل +بالعظمة +بالعفو +بالعقاب +بالعقاد +بالعقارب +بالعقاقير +بالعقبات +بالعقديات +بالعقل +بالعقلانية +بالعقلية +بالعقول +بالعقيدة +بالعكس +بالعلاج +بالعلاقات +بالعلامة +بالعلم +بالعلماء +بالعلوم +بالعم +بالعمالة +بالعمر +بالعمق +بالعمل +بالعملاء +بالعملة +بالعمى +بالعناية +بالعنصر +بالعنف +بالعنق +بالعهد +بالعواطف +بالعوالق +بالعوامل +بالعودة +بالعياط +بالعيش +بالعين +بالعيوب +بالعيون +بالـذات +بالفأس +بالفئات +بالفائدة +بالفاتح +بالفاعلين +بالفتح +بالفترة +بالفتق +بالفتيات +بالفحص +بالفحم +بالفحوص +بالفخر +بالفخروالاعتزاز +بالفرادة +بالفرار +بالفراز +بالفراش +بالفرح +بالفرد +بالفرز +بالفرص +بالفرق +بالفرقة +بالفرنج +بالفرنسية +بالفروسية +بالفريسة +بالفسطاط +بالفسلفة +بالفسيفساء +بالفشل +بالفضة +بالفضل +بالفضول +بالفضيحة +بالفطرة +بالفعاليات +بالفعل +بالفقهي +بالفكاهة +بالفكر +بالفكرة +بالفلزَّات +بالفلسفة +بالفلوس +بالفليبين +بالفم +بالفن +بالفنادق +بالفنان +بالفنانين +بالفندق +بالفواخير +بالفوسفور +بالفول +بالفيتامين +بالفيروس +بالفيروسات +بالفيلاريا +بالفيلم +بالقات +بالقادم +بالقار +بالقارة +بالقاع +بالقانون +بالقاهرة +بالقبائل +بالقبة +بالقبض +بالقبلات +بالقبول +بالقتال +بالقتل +بالقداسة +بالقدر +بالقدرة +بالقدس +بالقديس +بالقديم +بالقرآن +بالقراءة +بالقراد +بالقرارات +بالقرب +بالقرحة +بالقرد +بالقرن +بالقرنة +بالقرنية +بالقرود +بالقروض +بالقرية +بالقسوة +بالقصر +بالقصص +بالقصف +بالقصيدة +بالقصيرة +بالقضاء +بالقضايا +بالقضية +بالقطار +بالقطاع +بالقطع +بالقطن +بالقلعة +بالقلق +بالقلم +بالقلي +بالقليل +بالقليلة +بالقماش +بالقمح +بالقنابل +بالقنص +بالقهر +بالقهقهة +بالقهوة +بالقواعد +بالقوانين +بالقوة +بالقول +بالقومي +بالقومية +بالقوى +بالقيادة +بالقياس +بالقيام +بالقيلة +بالقيم +بالقيمة +بالك +بالكآبة +بالكائنات +بالكاتب +بالكاد +بالكارثة +بالكاريبي +بالكامل +بالكاميرا +بالكبار +بالكباري +بالكبت +بالكبريت +بالكبيسة +بالكتاب +بالكتابة +بالكتابِ +بالكتب +بالكثير +بالكثيرين +بالكحول +بالكذب +بالكرباج +بالكرة +بالكرخ +بالكرم +بالكرنك +بالكروان +بالكسل +بالكشف +بالكعبة +بالكفاءة +بالكلام +بالكلس +بالكلمات +بالكلمة +بالكليات +بالكلية +بالكمبيوتر +بالكمة +بالكمون +بالكمين +بالكهرباء +بالكورتيزون +بالكورنيش +بالكوفة +بالكوليج +بالكوليرا +بالكون +بالكويت +بالكي +بالكيان +بالكيس +بالكيسي +بالكيفية +بالكيماويات +باللآلئ +باللائمة +باللاحقين +باللافتات +باللامباشر +باللباس +باللجنة +باللجوء +باللحظة +باللعب +باللفظ +باللفق +باللقاء +بالله +باللهجة +باللهفة +باللوفر +باللون +بالليدي +بالليزر +بالليل +بالليمون +بالمأساة +بالمؤلفين +بالمؤن +بالمئات +بالماء +بالمائة +بالمادة +بالمارة +بالمارينز +بالماضي +بالماكياج +بالماكينة +بالماورد +بالمباني +بالمبنى +بالمبيدات +بالمبيضّ +بالمتابعات +بالمتاح +بالمتحف +بالمتربصّين +بالمتعة +بالمتلازمة +بالمتنزَّه +بالمثقف +بالمثل +بالمثول +بالمثير +بالمجاملة +بالمجان +بالمجتمع +بالمجلة +بالمجلس +بالمجمع +بالمجموعات +بالمجين +بالمحاصيل +بالمحاضرات +بالمحافظة +بالمحاليل +بالمحاماة +بالمحبة +بالمحبطات +بالمحتاج +بالمحرمات +بالمحصلة +بالمحصول +بالمحطات +بالمحلات +بالمحميات +بالمحمية +بالمحيط +بالمخابر +بالمخاطر +بالمختبر +بالمخترع +بالمختصر +بالمخرج +بالمخطوطات +بالمخيلة +بالمدارس +بالمدافع +بالمدرسة +بالمدن +بالمديح +بالمدينة +بالمذاهب +بالمرآة +بالمرأة +بالمراحل +بالمرارة +بالمرافق +بالمراكب +بالمراكز +بالمرة +بالمرتبة +بالمرج +بالمرجعيات +بالمرح +بالمرحلة +بالمرسم +بالمرصاد +بالمرصد +بالمرض +بالمرضى +بالمركب +بالمركز +بالمرمر +بالمرور +بالمرونة +بالمري +بالمزيد +بالمسألة +بالمسؤولية +بالمسئولية +بالمسائل +بالمساج +بالمساجد +بالمساحات +بالمساحة +بالمسارح +بالمسافة +بالمساهمة +بالمساواة +بالمستثمر +بالمستحيل +بالمستر +بالمستقبل +بالمستقبليات +بالمستندات +بالمستنقعات +بالمستودع +بالمستوطنات +بالمستوى +بالمسجد +بالمسح +بالمسرات +بالمسرح +بالمسز +بالمسطرة +بالمسعكر +بالمسكنات +بالمسكّنات +بالمسلم +بالمسمى +بالمسيحية +بالمشاركة +بالمشاريع +بالمشاعر +بالمشاكل +بالمشاهد +بالمشرط +بالمشرق +بالمشروعات +بالمشفى +بالمشكلة +بالمشهد +بالمشي +بالمصاب +بالمصاعب +بالمصالح +بالمصالحة +بالمصانع +بالمصاهرة +بالمصحف +بالمصدر +بالمصطلحات +بالمصعد +بالمصير +بالمضادات +بالمطابقة +بالمطار +بالمطبوعات +بالمطر +بالمطرب +بالمطلق +بالمطلوب +بالمظاهر +بالمظلات +بالمظلة +بالمعادل +بالمعادي +بالمعارك +بالمعاني +بالمعاول +بالمعتدين +بالمعتقدات +بالمعدة +بالمعدل +بالمعدَّلات +بالمعرض +بالمعرفة +بالمعركة +بالمعروف +بالمعلم +بالمعلمين +بالمعلومات +بالمعنى +بالمعهد +بالمفاجآت +بالمفاداة +بالمفارقات +بالمفارقة +بالمفتاح +بالمفردة +بالمفرق +بالمفرّق +بالمفهوم +بالمقابل +بالمقابلة +بالمقارنة +بالمقاعد +بالمقالة +بالمقام +بالمقامات +بالمقاييس +بالمقدار +بالمقدمة +بالمقرنصات +بالمقص +بالمقطم +بالمقيمين +بالمكاتب +بالمكان +بالمكانة +بالمكملات +بالملابس +بالملاحة +بالملاحظة +بالملاحف +بالملاريا +بالملايين +بالملح +بالملعب +بالملك +بالملل +بالملوثات +بالملوخية +بالممارسة +بالممرات +بالممرضة +بالمملكة +بالمناخ +بالمنازل +بالمناسبات +بالمناسبة +بالمناسك +بالمناطق +بالمناظر +بالمنتجات +بالمنتوج +بالمنجزات +بالمنجنيق +بالمنسوخ +بالمنشآت +بالمنشار +بالمنطق +بالمنطقة +بالمنظار +بالمنظمات +بالمنظمة +بالمنهج +بالمهاجرين +بالمهارات +بالمهرج +بالمهرجانات +بالمهرطق +بالمهرطقين +بالمهمة +بالمهن +بالمواد +بالموارد +بالمواسم +بالمواصفات +بالمواصلات +بالمواضيع +بالمواطنة +بالموافقة +بالمواقع +بالمواهب +بالمواويل +بالموت +بالموجود +بالمودودي +بالموروث +بالموز +بالموسيقى +بالموسيقيين +بالموضوع +بالموضوعية +بالموعد +بالموقع +بالمومياوات +بالمياه +بالمِصَرْ +بالنا +بالناحية +بالنادر +بالنادي +بالنار +بالناس +بالنتائج +بالنتيجة +بالنث +بالنثر +بالنجاح +بالنجوم +بالنحت +بالنحل +بالنخيل +بالندم +بالندى +بالنرويج +بالنزاعات +بالنزول +بالنسبة +بالنسبية +بالنسخ +بالنسيان +بالنشارة +بالنشاط +بالنشر +بالنشوة +بالنص +بالنصائح +بالنصح +بالنصر +بالنصف +بالنصوص +بالنظام +بالنظر +بالنظرة +بالنظرية +بالنعناع +بالنعومة +بالنفائس +بالنفاذ +بالنفس +بالنفط +بالنفع +بالنفي +بالنقد +بالنقص +بالنقض +بالنقل +بالنقود +بالنقوش +بالنمطيّة +بالنمو +بالنموذج +بالنموذجين +بالنهار +بالنهب +بالنهر +بالنهضة +بالنواة +بالنوافير +بالنوتة +بالنيابة +بالنيل +بالنّظافة +بالنَّفيس +باله +بالها +بالهبوب +بالهجرات +بالهجرة +بالهداية +بالهدم +بالهدوء +بالهدى +بالهراوات +بالهرطقة +بالهرم +بالهطول +بالهلال +بالهلب +بالهلع +بالهم +بالهموم +بالهناء +بالهناءة +بالهند +بالهندسة +بالهواء +بالهوة +بالهولندية +بالهوية +بالهيئة +بالهيدروجين +بالهيكل +بالهيمنة +بالهِرَم +بالواجبات +بالواقع +بالواقفين +بالوجد +بالوجه +بالوجود +بالوحدات +بالوحدة +بالوحي +بالوخز +بالود +بالوداعة +بالوراثة +بالورد +بالورع +بالورق +بالورم +بالوزارة +بالوزن +بالوس +بالوسائل +بالوسط +بالوصــــال +بالوصف +بالوصول +بالوطن +بالوطنين +بالوظائف +بالوظيفة +بالوعر +بالوعى +بالوعيد +بالوفود +بالوفيات +بالوقاية +بالوقت +بالوقود +بالوقوف +بالوكالة +بالولادة +بالولايات +بالوليد +بالونات +بالوهج +بالوهن +بالي +باليأس +باليابان +بالية +باليتة +باليته +باليخت +باليد +باليدين +باليسيرة +باليقين +باليمامة +باليمن +بالينو +باليه +باليهود +باليوم +باليون +بامبو +بامتداد +بامتدادات +بامتصاص +بامتعاض +بامتلاك +بامتياز +بامتيازات +بامرأة +بامشي +بامكانية +باموات +بان +باناسونيك +باناهي +بانتباه +بانتحال +بانتخاب +بانتشار +بانتشال +بانتصار +بانتظار +بانتظارنا +بانتظاره +بانتظارهم +بانتظاري +بانتظام +بانتعاشة +بانتفاء +بانتقام +بانتماء +بانتمائه +بانتهاء +بانحطاط +بانحناء +بانحناءاته +بانحناءة +بانخراطه +بانخراطي +بانخفاض +باندفاع +باندفاعة +باندماجها +بانزعاج +بانسجام +بانسداد +بانسياب +بانشاء +بانصرافه +بانصياعها +بانضمامها +بانطباع +بانطباعات +بانطلاق +بانفجار +بانفسهم +بانفعال +بانفعالات +بانقباض +بانقراض +بانقشاع +بانكماش +بانكماشها +بانكوك +بانهيار +بانيان +بانيبال +باهت +باهتا +باهتاً +باهتة +باهتمام +باهتمامات +باهتين +باهر +باهراً +باهرة +باهظ +باهظا +باهظاً +باهظة +باهي +باور +باورز +باورو +باولا +باولنج +باولو +باولين +باى +باي +باية +بايتان +بباب +بباريس +بباعة +بباكستان +ببال +بباله +ببالها +ببالي +ببانكوك +ببتيد +ببث +ببحار +ببحبوحة +ببحة +ببحث +ببحثكم +ببحر +ببحوث +ببخار +ببدء +ببداياته +ببدلة +ببذل +ببراءة +ببراءته +ببراءتهم +ببراءتهما +ببرائته +ببراعة +ببراعته +ببرامج +ببرامجها +ببرانس +ببرجيه +ببرد +ببردى +ببرقية +ببرمنجهام +ببرنامج +ببرنامجه +ببروتين +ببرود +ببرودة +ببرودواي +ببروز +ببريطانيا +ببريقها +ببساطة +ببساطته +ببسالة +ببشاشة +ببشر +ببشرة +ببشريتنا +ببصره +ببصرها +ببصيرة +ببصيرته +ببضع +ببطء +ببطاريات +ببطاقات +ببطن +ببطولة +ببطولته +ببطولتها +ببطون +ببعض +ببعضها +ببعضهما +ببعوضة +ببعيد +ببقاء +ببكاء +ببلاد +ببلازموديوم +ببلاش +ببلد +ببلدة +ببلدتها +ببلدية +ببللا +ببلنسيه +ببليوجرافي +ببناء +ببناءه +ببنادقهم +ببنت +ببندقية +ببنك +ببنود +ببنية +ببنيته +ببهاء +ببهجة +ببوابة +ببوبال +ببور +ببولندا +ببومباي +ببيئات +ببيئة +ببيئته +ببيان +ببيانه +ببيت +ببيروت +ببيروقراطية +ببيشة +ببيع +بتأ +بتأبين +بتأثر +بتأثير +بتأثيراتها +بتأجير +بتأجيل +بتأسيس +بتأشيرات +بتأصيل +بتأليف +بتأمل +بتأمين +بتأن +بتأويل +بتأييد +بتابوت +بتاتا +بتاتاً +بتاج +بتاجر +بتاخذ +بتاريخ +بتاريخنا +بتاريخه +بتبئير +بتبادل +بتبخيرها +بتبديد +بتبعاتها +بتبني +بتتبع +بتتويج +بتتويجه +بتتي +بتثاقل +بتثلث +بتجارب +بتجاوز +بتجبيرها +بتجديد +بتجربة +بتجربتي +بتجرده +بتجريب +بتجريم +بتجسيد +بتجلياتها +بتجمعات +بتجميعها +بتجنب +بتجويف +بتحالفها +بتحاليل +بتحد +بتحديات +بتحديث +بتحديد +بتحرير +بتحريرها +بتحريض +بتحريك +بتحريم +بتحسين +بتحصين +بتحضير +بتحفيظ +بتحقيق +بتحقيقها +بتحليل +بتحليلاته +بتحليلها +بتحميل +بتحمّل +بتحنية +بتحول +بتحوير +بتحويل +بتحية +بتحيزاتها +بتخدير +بتخرجي +بتخريج +بتخريشها +بتخزين +بتخصيب +بتخصيص +بتخطي +بتخطيط +بتخفيف +بتخليق +بتخليني +بتخيل +بتداخلاته +بتداعاياتها +بتدريب +بتدريس +بتدريسها +بتدعيمها +بتدلي +بتدمير +بتدويرها +بتدوين +بتذكيره +بتر +بترا +بتراب +بترابط +بتراث +بتراثنا +بتراثه +بتراثها +بتراكيز +بتربية +بتربيته +بترت +بترتيب +بترتيبات +بترتيبها +بترجمة +بترجمتها +بترجيع +بترحاب +بترخيص +بتردد +بترديد +بترسانتها +بترشيح +بترشيحه +بترفيع +بترقب +بترك +بتركك +بتركها +بتركيا +بتركيب +بتركيبها +بتركيزات +بترميم +بترول +بترولي +بترولية +بترويضها +بتري +بتزايد +بتزويد +بتزويدي +بتزويق +بتزيين +بتزيينها +بتسبورج +بتسجيل +بتسخيرها +بتسخين +بتسديد +بتسديدها +بتسعة +بتسلم +بتسليح +بتسليم +بتسليمه +بتسهيل +بتسويق +بتسيير +بتشتتنا +بتشجيع +بتشجيعي +بتشذيب +بتشريح +بتشريعات +بتشكيل +بتشنج +بتشويه +بتشويهه +بتشىيد +بتشييدها +بتصادمات +بتصحيح +بتصدير +بتصرف +بتصفية +بتصفيتها +بتصفيق +بتصميم +بتصميمه +بتصنيع +بتصنيف +بتصوير +بتصويرها +بتضافر +بتطبيق +بتطبيقات +بتطـوير +بتطليق +بتطور +بتطورات +بتطوير +بتطويره +بتطويرها +بتطويع +بتعاقب +بتعالي +بتعاليم +بتعامل +بتعاون +بتعب +بتعبئة +بتعبير +بتعدد +بتعدديتها +بتعديل +بتعريبه +بتعريض +بتعريف +بتعريفي +بتعقد +بتعقيب +بتعلم +بتعلمها +بتعليق +بتعليم +بتعليمهم +بتعميم +بتعيين +بتعيينه +بتفاصيل +بتفاصيلها +بتفاهم +بتفجير +بتفرد +بتفردها +بتفريخ +بتفريعاتها +بتفشي +بتفصيلاتها +بتفضيل +بتفوق +بتفوقه +بتفوّقها +بتقارب +بتقارير +بتقاليد +بتقاليده +بتقانيات +بتقبيلها +بتقتير +بتقدم +بتقدمه +بتقدير +بتقديرات +بتقديم +بتقديمها +بتقلبات +بتقليد +بتقليص +بتقنيات +بتقوية +بتقويتها +بتقويم +بتقوّض +بتقيؤ +بتكاتف +بتكاملها +بتكزز +بتكلفة +بتكليف +بتكون +بتكوين +بتكوينها +بتلات +بتلاطم +بتلال +بتلاميذ +بتلاوة +بتلبية +بتلخيصه +بتلر +بتلعثم +بتلعثمات +بتلقائية +بتلقي +بتلقيح +بتلك +بتلوث +بتلويحات +بتم +بتماثيل +بتمام +بتمثيل +بتمدد +بتمديد +بتمريرها +بتمرّدهم +بتمكن +بتمكنه +بتموجات +بتمويل +بتمويلها +بتمييز +بتناقض +بتناقضاتها +بتناول +بتنبيه +بتنسيب +بتنشيطهم +بتنظيم +بتنفع +بتنفيذ +بتنفيذها +بتنمية +بتنوع +بتنوعها +بتنوير +بتهدئة +بتهذيب +بتهريب +بتهريبها +بتهم +بتهمة +بتهمتي +بتوابع +بتواجده +بتواريخ +بتوازن +بتوازنه +بتوازنها +بتواصل +بتواضع +بتوافق +بتوافه +بتوجس +بتوجهاته +بتوجيه +بتوجيهات +بتوجيهه +بتوخي +بتوديع +بتوربينات +بتوزع +بتوزيع +بتوزيعها +بتوسعة +بتوسيع +بتوصية +بتوصيل +بتوصيلها +بتوضيح +بتوضيحه +بتوظيفها +بتوعك +بتوفير +بتوقيت +بتوقيع +بتولي +بتوليفة +بتونس +بتياراته +بتّه +بتُّ +بث +بثبات +بثتها +بثرائه +بثرثرته +بثروة +بثروتها +بثعابين +بثقافات +بثقب +بثقة +بثقته +بثقل +بثقله +بثلاث +بثلاثة +بثلثي +بثمانمائة +بثمرات +بثمن +بثمنه +بثمنها +بثها +بثوبه +بثوبها +بثور +بثورة +بثورتي +بثياب +بثّ +بجائزة +بجائزتنا +بجائزتها +بجامع +بجامعة +بجانب +بجانبنا +بجانبه +بجانبها +بجانبهم +بجانبي +بجاهليّه +بجبال +بجبروت +بجبل +بجثته +بجحافل +بجد +بجدار +بجدارة +بجدة +بجدران +بجدرانه +بجدي +بجدية +بجديد +بجديّة +بجدّ +بجذب +بجذورك +بجذوره +بجذورها +بجذوري +بجرأة +بجرأته +بجرحى +بجرد +بجرسه +بجرعات +بجريد +بجريدة +بجريرة +بجريرته +بجريمة +بجزء +بجزأيها +بجزئيته +بجزيئات +بجزية +بجزيرة +بجسد +بجسده +بجسدها +بجسدي +بجســمك +بجسم +بجسمه +بجسمها +بجع +بجعل +بجفافها +بجلاء +بجلابيبهم +بجلال +بجلالة +بجلطة +بجماعة +بجمال +بجمالها +بجمالية +بجماهيرية +بجمجمته +بجمرات +بجمع +بجمعها +بجمعية +بجمل +بجملة +بجميع +بجميل +بجميلهم +بجناحها +بجناحيه +بجناحيها +بجنازة +بجنازته +بجنان +بجند +بجندي +بجنس +بجنوب +بجنوده +بجنوز +بجنون +بجني +بجنيف +بجهاز +بجهد +بجهده +بجهود +بجهودها +بجو +بجوائز +بجواب +بجوار +بجواره +بجوارهم +بجواز +بجوازها +بجوازي +بجوامع +بجوانب +بجودته +بجوربيه +بجولات +بجولة +بجولتنا +بجوهانسبيرج +بجوهر +بجوهرية +بجينات +بحائط +بحاثة +بحاجة +بحادث +بحادثة +بحادثٍ +بحار +بحارا +بحاراً +بحارة +بحارته +بحاسباتهم +بحال +بحالات +بحالة +بحالته +بحب +بحبالها +بحبه +بحبها +بحبيبته +بحبّ +بحة +بحت +بحتا +بحتاً +بحتة +بحتمية +بحث +بحثا +بحثان +بحثاً +بحثت +بحثنا +بحثه +بحثها +بحثوا +بحثي +بحثية +بحثين +بحثًا +بحجارة +بحجة +بحجر +بحجم +بحجمه +بحجمها +بحد +بحدة +بحدتها +بحدسه +بحدوث +بحدود +بحديث +بحديثنا +بحديثه +بحديثها +بحديثهم +بحديقة +بحذافيره +بحذاقه +بحذر +بحذف +بحذفها +بحذق +بحر +بحرا +بحرارة +بحرارةٍ +بحرارته +بحرارتها +بحراسة +بحران +بحراً +بحرص +بحرف +بحرفهم +بحرفية +بحرق +بحرقة +بحركات +بحركاتها +بحركاتهـا +بحركاتهما +بحركة +بحركته +بحرمان +بحرها +بحري +بحرية +بحريتها +بحريتين +بحرين +بحريين +بحزام +بحزب +بحزم +بحس +بحساب +بحساسية +بحساسيتها +بحسب +بحسبان +بحسبه +بحسرة +بحسم +بحسن +بحسنها +بحسه +بحصان +بحصة +بحصر +بحصص +بحصير +بحضارات +بحضارة +بحضارتهم +بحضور +بحظر +بحـالات +بحـب +بحـوالى +بحـيث +بحفاظه +بحفاوة +بحفر +بحفريات +بحفظ +بحفل +بحفنة +بحق +بحقبة +بحقل +بحقن +بحقه +بحقهم +بحقوق +بحقوقها +بحقوقهم +بحقوقهن +بحقولها +بحقيبة +بحقيقة +بحقيقتها +بحكاياته +بحكاية +بحكم +بحكماء +بحكمة +بحل +بحلاقة +بحلب +بحلة +بحلته +بحلف +بحلقة +بحلم +بحلمة +بحلمها +بحلمٍ +بحلول +بحلوها +بحماس +بحماسة +بحمام +بحماية +بحمد +بحمرة +بحمص +بحمل +بحملات +بحملة +بحملته +بحمله +بحملها +بحمولاتها +بحمى +بحميمية +بحنان +بحنجرتي +بحواجز +بحوادث +بحواديت +بحواسنا +بحوالي +بحوث +بحوثهم +بحوثي +بحوزة +بحوزتها +بحوزتهما +بحوزتي +بحوض +بحياء +بحياة +بحياتك +بحياته +بحياتها +بحياتهم +بحياتي +بحياد +بحيادها +بحيازته +بحيث +بحيرات +بحيرة +بحيرتا +بحيرتي +بحيوية +بحيويتها +بحّ +بحّاراً +بحّارة +بخار +بخارجها +بخاصة +بخاطرها +بخاله +بخبث +بخبر +بخبرات +بخبراتها +بخبراتهم +بخبزه +بخت +بختم +بخجل +بخدمات +بخدماته +بخدماتهم +بخدمة +بخراطيش +بخرافات +بخرق +بخروج +بخروجك +بخريطة +بخزانة +بخسارته +بخسةَ +بخصائص +بخصائصها +بخصاله +بخصم +بخصوبة +بخصوص +بخصوصية +بخصوصيتها +بخضرتها +بخط +بخطاب +بخطابها +بخطة +بخطر +بخطط +بخطه +بخطوات +بخطواته +بخطوة +بخطوتها +بخطورة +بخطوط +بخطى +بخفة +بخفر +بخفض +بخفية +بخلاء +بخلاف +بخلافة +بخلافته +بخلايا +بخلخلة +بخلدها +بخلط +بخلع +بخلعها +بخلق +بخلو +بخلوها +بخلية +بخليط +بخمارها +بخمسة +بخمسمائة +بخمسين +بخواطرنا +بخوف +بخوفي +بخيالي +بخيبات +بخيت +بخير +بخيراتها +بخيره +بخيرها +بخيلا +بخيمة +بخيوط +بد +بدء +بدءا +بدءاً +بدءوا +بدءًا +بدأ +بدأب +بدأت +بدأتها +بدأتُ +بدأن +بدأنا +بدأه +بدأها +بدأوا +بدئ +بدا +بداء +بدائرتهم +بدائل +بدائياً +بدائية +بدائيتها +بدائيين +بداخل +بداخله +بداخلها +بداخلهم +بداخلي +بدار +بدارا +بداره +بداعي +بدافع +بدانة +بداهة +بدايات +بداياته +بداياتها +بداياتهم +بداياتي +بداية +بدايةً +بدايته +بدايتها +بدايتي +بداً +بدبلوم +بدبوس +بدت +بدخول +بدخولنا +بدخولها +بدد +بدر +بدراسات +بدراسة +بدراسته +بدراستها +بدران +بدرت +بدرجات +بدرجة +بدرس +بدرع +بدرها +بدروبهم +بدروس +بدري +بدعائه +بدعم +بدعمها +بدعوة +بدعوتنا +بدعوته +بدعوتها +بدعوتي +بدعوى +بدفء +بدفئها +بدفتين +بدفع +بدفن +بدفنه +بدقات +بدقة +بدقيقة +بدقّة +بدل +بدلا +بدلات +بدلالات +بدلاً +بدلة +بدلت +بدلتا +بدلته +بدلكها +بدلوه +بدلوها +بدليل +بدم +بدمائه +بدمشق +بدمعي +بدن +بدنه +بدني +بدنياً +بدنية +بدهان +بدهشة +بدهشه +بدهلي +بدهم +بدهيا +بدواء +بدواءين +بدوائر +بدوافع +بدور +بدورانه +بدورنا +بدوره +بدورها +بدورهم +بدورهن +بدوري +بدول +بدولة +بدولتين +بدون +بدونها +بدوي +بدوية +بدويًّا +بديار +بديع +بديعة +بديكور +بديل +بديلا +بديلاً +بديلة +بديلتين +بديمومة +بدينا +بدينار +بدينه +بدينها +بدينهم +بدينين +بديهة +بديهي +بديهية +بديوان +بديوانه +بدّ +بدّاً +بدّدها +بدًّا +بذاءته +بذات +بذاته +بذاتها +بذاتهم +بذار +بذارها +بذاك +بذاكرته +بذخا +بذراعه +بذرة +بذرَّات +بذكاء +بذكائك +بذكائه +بذكائها +بذكر +بذكره +بذكرها +بذكرى +بذكريات +بذكور +بذل +بذلت +بذلتم +بذلتَه +بذلتُه +بذلك +بذله +بذلها +بذلوا +بذلّ +بذهبية +بذهني +بذهنية +بذهول +بذور +بذورها +بذورٍ +بذوق +بذوي +بذيله +بر +برءوسنا +برأس +برأسمال +برأسه +برأسي +برأوكسيد +برأي +برأيك +برأيكم +برأينا +برأيي +برؤى +برؤية +برؤيته +برؤيتهم +برئاسة +برئيس +برئيسة +براء +براءات +براءة +براءت +براءته +براءتها +براءتهم +برائحة +برابطة +براتس +براثن +براثنه +براجماتية +براحة +براحته +برادار +برادبري +برادفورد +براذرز +براري +براز +برازه +برازيليا +براسي +براعة +براعته +براعتها +براعم +براعمها +براقة +برامج +برامجه +برامجها +براهي +براهين +براون +برايتنباك +برايتون +برايد +برايل +براييبا +براً +بربادوس +بربارا +بربارة +برباط +بربح +بربحه +بربروس +بربروسا +بربروسّا +بربري +بربرية +بربط +بربطها +بربع +بربه +برتراند +برتقال +برتقالها +برتقالي +برتقالية +برته +برتولت +برج +برجا +برجال +برجالها +برجام +برجاً +برجل +برجليها +برجه +برجي +برجين +برحلات +برحلاته +برحلة +برحلتنا +برحلته +برحمته +برحيل +برحيله +برخت +برد +بردا +برداً +بردي +برديات +بردية +برذاذ +برذرز +برر +بررة +برز +برزت +برزوا +برس +برسائل +برسالة +برسالته +برسالتها +برسالتهم +برستد +برسم +برسول +برسوم +برسومات +برش +برشاد +برشاقة +برشة +برشلونة +برصاصات +برصد +برطوبة +برع +برعاية +برعايته +برعب +برعم +برعما +برف +برفاهية +برفض +برفضها +برفع +برفعه +برفق +برفوف +برفيع +برفيقات +برق +برقبة +برقة +برقصه +برقعة +برقوق +برك +بركابه +بركات +بركان +بركانا +بركاني +بركب +بركة +بركوب +برلك +برلمان +برلماني +برلمانيا +برلين +برم +برمائية +برمال +برمته +برمتها +برمجة +برمنجهام +برمود +برمي +برميل +برميمه +برميها +برمّته +برمّتها +برن +برنارد +برناردشو +برناسيّ +برناسيّا +برنامج +برنامجا +برنامجاً +برنامجكم +برنامجنا +برنامجه +برنامجها +برنامجي +برنامجيها +برنامجًا +برنزي +برنزية +برنسه +برني +برنيق +برنيكي +برهافة +برهان +برهبة +برهة +بروائح +بروايته +بروبيلين +بروتمان +بروتون +بروتونا +بروتونات +بروتيز +بروتين +بروتينات +بروتيناً +بروج +بروح +بروحك +بروحه +بروحي +برودة +برودته +برودواي +بروز +بروزاك +بروسبيرو +بروسن +بروسيا +بروشورات +بروعة +بروق +بروكس +بروكسل +بروكسيل +برومود +برونسيك +برويز +بري +بريء +بريئا +بريئة +بريا +بريادار +برياض +برية +بريتانيا +بريتشارد +بريتوريا +بريتون +بريخان +بريد +بريدج +بريستول +بريسلي +بريشته +بريشه +بريشها +بريطاني +بريطانيا +بريطانية +بريطانيتين +بريطانيون +بريفير +بريق +بريقه +بريقها +بريل +بريلي +بريليوم +بريماما +بريمر +بريندل +برينستون +بريّة +بريّتين +برُعب +برّاق +برّحها +برَّد +برِّية +بزات +بزاد +بزاوية +بزبائنه +بزته +بزجاج +بزجاجات +بزحف +بزخارف +بزخرفة +بزخرفتها +بزخرفها +بزراعة +بزراعته +بزرع +بزرقة +بزرقته +بزرقتها +بزعامة +بزعم +بزعمه +بزعنفة +بزكاته +بزكام +بزمام +بزماننا +بزمكان +بزمن +بزميلي +بزهرة +بزهرتها +بزواج +بزوار +بزوال +بزوجة +بزوجته +بزوجي +بزيادة +بزيادته +بزيارات +بزيارة +بزيارته +بزيت +بزيتون +بزيه +بزيها +بزيهم +بزيورخ +بزيوريخ +بزّهم +بس +بسؤال +بسؤالها +بسؤالهم +بسابق +بساتين +بساحة +بساحل +بسارس +بسارية +بساط +بساطة +بساطته +بساطتها +بساعات +بساعة +بسام +بسبابته +بسبابتِهِ +بسبب +بسببك +بسببه +بسببها +بسببهم +بسبره +بسبع +بسبعة +بسبيلنا +بست +بستائر +بستان +بستانا +بستاني +بستة +بستر +بستين +بسجن +بسحب +بسحر +بسحرها +بسخرية +بسخط +بسد +بسداده +بسذاجته +بسر +بسردها +بسرطان +بسرطانات +بسرعات +بسرعة +بسرعتها +بسرقة +بسرها +بسرور +بسري +بسرية +بسرٍّ +بسط +بسطالي +بسطة +بسطها +بسطوا +بسعادة +بسعال +بسعة +بسعر +بسعرها +بسفارتنا +بسفرتَيْن +بسفري +بسفينة +بسقف +بسقوط +بسكانها +بسكر +بسلاح +بسلاسة +بسلام +بسلامة +بسلحفاة +بسلسلة +بسلطة +بسلك +بسلوك +بسلوكه +بسم +بسمائها +بسمات +بسماتنا +بسماحته +بسمة +بسمةٌ +بسمتها +بسمنود +بسمو +بسن +بسنة +بسند +بسنن +بسنوات +بسنين +بسهولة +بسوء +بسوائل +بسواه +بسوداوية +بسوط +بسوطه +بسوق +بسونيتات +بسويسرا +بسيادته +بسيارات +بسيارة +بسيارته +بسيارتي +بسياسة +بسياق +بسياقات +بسيجارة +بسيد +بسيدة +بسيدنا +بسير +بسيرورة +بسيط +بسيطا +بسيطاً +بسيطة +بسيطرة +بسيفه +بسيقانه +بسيل +بسيناريوهاتها +بسيون +بسّام +بشأن +بشأنه +بشأنها +بشأني +بشؤون +بشئون +بشابة +بشاحنة +بشار +بشارب +بشارة +بشارع +بشاش +بشاطئ +بشاعة +بشباب +بشباك +بشبكات +بشبكة +بشبه +بشتى +بشجاعة +بشجاعتهم +بشحن +بشحومها +بشخص +بشخصياتها +بشخصياتهم +بشخصية +بشخصيته +بشخصيتي +بشخير +بشخيره +بشدة +بشذا +بشذى +بشر +بشراء +بشرائط +بشرائه +بشرارتها +بشراسة +بشراهة +بشرايين +بشراً +بشرب +بشرة +بشرته +بشرتهم +بشرتي +بشرح +بشرط +بشرف +بشرق +بشرقها +بشركات +بشركة +بشركتنا +بشرها +بشروحاته +بشروط +بشرى +بشري +بشرياً +بشرية +بشطريها +بشظف +بشع +بشعابها +بشعار +بشعاع +بشعبنا +بشعبية +بشعة +بشعر +بشعري +بشعريتها +بشعور +بشفافية +بشق +بشقاء +بشقيقاتها +بشقيقه +بشقيه +بشقيها +بشكل +بشكله +بشكلها +بشكوى +بشكّه +بشلالات +بشمال +بشموخ +بشن +بشهادات +بشهادة +بشهادتي +بشهر +بشهرة +بشهرته +بشهرين +بشهقة +بشهوانية +بشهور +بشهية +بشوارع +بشواطئنا +بشواطئه +بشواطئها +بشوالٍ +بشوق +بشوكة +بشى +بشيء +بشيءٍ +بشيئين +بشيت +بشيخ +بشيخه +بشيخي +بشير +بشيوع +بصاحبها +بصادراتنا +بصاروخ +بصالته +بصبر +بصبره +بصبرها +بصحبة +بصحبته +بصحبتهم +بصحة +بصحتهم +بصحرائها +بصحفها +بصخب +بصخور +بصداع +بصداقة +بصدد +بصدده +بصددها +بصدري +بصدق +بصدقها +بصدور +بصديق +بصديقه +بصديقي +بصراحة +بصرخات +بصرخة +بصرف +بصرك +بصره +بصرها +بصرهم +بصري +بصرية +بصريح +بصعوبات +بصعوبة +بصعيد +بصــــفة +بصـورة +بصفاء +بصفات +بصفة +بصفتكم +بصفته +بصفتي +بصفر +بصفوفها +بصفّ +بصقته +بصقلية +بصل +بصلابة +بصلة +بصلةٍ +بصلواته +بصمات +بصماتها +بصمة +بصمت +بصمتي +بصمود +بصناعة +بصنع +بصنعاء +بصنعه +بصنعِ +بصنفيها +بصنوف +بصوت +بصوته +بصور +بصورة +بصورتها +بصورتيه +بصورهم +بصوفيّه +بصيانة +بصيد +بصيده +بصير +بصيراً +بصيرة +بصيرتنا +بصيرته +بصيرتهم +بصيص +بصيصا +بضآلة +بضائع +بضائعنا +بضائعه +بضائعهم +بضائقة +بضاعة +بضاعته +بضاعتهم +بضاعتي +بضجر +بضحاياها +بضحكة +بضرائب +بضربة +بضروب +بضرورة +بضع +بضعة +بضعف +بضفاف +بضمان +بضمير +بضوء +بضواحي +بضياء +بضياعه +بضيق +بضيقهما +بط +بطء +بطئا +بطائرات +بطائرة +بطائلٍ +بطابع +بطابعين +بطاريات +بطارية +بطاطسهم +بطاقات +بطاقاته +بطاقاتها +بطاقة +بطاقتك +بطاقته +بطالة +بطبائعهم +بطباشير +بطباعة +بطبع +بطبعات +بطبعة +بطبعه +بطبعها +بطبعهم +بطبعي +بطبقة +بطبيعة +بطبيعته +بطبيعتها +بطرابلس +بطراز +بطرح +بطرد +بطرده +بطرس +بطرسبرج +بطرسبورج +بطرف +بطرفتين +بطرق +بطريرك +بطريق +بطريقا +بطريقة +بطريقته +بطريقتهم +بطريقتي +بطريقتين +بطش +بطشها +بطعم +بطعمه +بطفلة +بطفلهم +بطل +بطلا +بطلاء +بطلاب +بطلاقة +بطلان +بطلاً +بطلب +بطلبات +بطلة +بطلتها +بطلق +بطله +بطلها +بطلي +بطليموس +بطمأنينة +بطموح +بطن +بطنا +بطنه +بطنها +بطني +بطنِ +بطه +بطوطة +بطوكيو +بطول +بطولات +بطولة +بطولتها +بطوله +بطولها +بطون +بطونها +بطونهم +بطيء +بطيئا +بطيئاً +بطيئة +بطيخ +بطينية +بطيور +بظاهرة +بظرفه +بظروفه +بظلاله +بظلالها +بظلام +بظلمهم +بظمئها +بظهر +بظهره +بظهور +بظهورها +بظواهر +بعائلة +بعادات +بعاداتنا +بعالم +بعالمنا +بعالمهم +بعام +بعامة +بعامل +بعامين +بعباءات +بعباءتها +بعبارة +بعبث +بعبد +بعبدا +بعبدالحليم +بعتاب +بعث +بعثات +بعثة +بعثت +بعثته +بعثراتي +بعثها +بعجالة +بعد +بعدئذ +بعدا +بعداها +بعداً +بعدة +بعدت +بعدد +بعددها +بعدك +بعدم +بعدما +بعدمها +بعده +بعدها +بعدهم +بعدهما +بعدوى +بعدي +بعدية +بعدين +بعدًا +بعدٍ +بعدُ +بعذاباته +بعرائضهم +بعراك +بعربية +بعرض +بعرق +بعرقك +بعروبيته +بعروض +بعريه +بعز +بعزف +بعزفه +بعزم +بعزمه +بعزيمة +بعزّ +بعسل +بعشب +بعشر +بعشرات +بعشرة +بعشرين +بعشق +بعصا +بعصارة +بعصبية +بعصبيته +بعصر +بعصير +بعصيهم +بعض +بعضا +بعضاً +بعضكم +بعضلة +بعضنا +بعضه +بعضها +بعضهم +بعضهما +بعضهن +بعضي +بعضًا +بعضِ +بعضِها +بعطائه +بعطر +بعطسة +بعطف +بعطلتهم +بعظام +بعظيم +بعـض +بعـــض +بعــــض +بعقائد +بعقاقير +بعقد +بعقل +بعقلانية +بعقلي +بعقلية +بعقوبات +بعقول +بعكس +بعل +بعلاج +بعلاقة +بعلامات +بعلامة +بعلبك +بعلبكي +بعلم +بعلماء +بعلمائنا +بعلمائه +بعلمه +بعلوم +بعلومها +بعلوية +بعمائرها +بعمان +بعمر +بعمره +بعمق +بعمل +بعملائه +بعملك +بعملنا +بعمله +بعملها +بعملهم +بعملي +بعمليات +بعملية +بعمليتها +بعمود +بعموميتها +بعناد +بعناصر +بعناصرها +بعناية +بعنصر +بعنف +بعنفه +بعنقه +بعنوان +بعهد +بعهدهم +بعوارض +بعواقبه +بعوامل +بعودة +بعودته +بعوده +بعوضة +بعون +بعيب +بعيد +بعيدا +بعيداً +بعيدة +بعيدتين +بعيدين +بعيدًا +بعيرا +بعيرك +بعيره +بعيري +بعين +بعينه +بعينها +بعيني +بعينين +بعينيه +بعينيها +بعيون +بعيونه +بعيونها +بعيوني +بـ +بـرصاصة +بـما +بـماء +بـمـطاردة +بفؤاد +بفئات +بفائدة +بفائدتها +بفارق +بفاعلية +بفتاة +بفتة +بفتح +بفترة +بفحص +بفخر +بفداحة +بفراء +بفرادته +بفراستكم +بفرح +بفرحة +بفرسان +بفرسه +بفرص +بفرط +بفرق +بفرنسا +بفريدريك +بفريضة +بفريق +بفسائل +بفستانها +بفشل +بفصاحة +بفصاحته +بفصاحتها +بفصل +بفصول +بفض +بفضاء +بفضائل +بفضل +بفضله +بفضلها +بفضلهم +بفطور +بفعالية +بفعاليته +بفعل +بفعله +بفقد +بفقدان +بفقر +بفك +بفكر +بفكرة +بفكرك +بفكره +بفكرهم +بفلان +بفلتر +بفلسطين +بفلوريدا +بفم +بفمه +بفن +بفناء +بفنانين +بفنجا +بفنجان +بفندق +بفهم +بفهمه +بفوائد +بفوزحزب +بفوزه +بفوزها +بفوكوه +بفول +بفيتامين +بفيروس +بفيلدونج +بقاء +بقاءه +بقاءهم +بقائمة +بقائه +بقائها +بقائهم +بقائي +بقاتل +بقاتلته +بقادرين +بقارّة +بقاطرة +بقاع +بقاعدة +بقافلة +بقافية +بقال +بقالب +بقالة +بقامته +بقانون +بقايا +بقبة +بقبر +بقبره +بقبضة +بقبضتيها +بقبلاته +بقبلة +بقبول +بقتل +بقتله +بقداس +بقدر +بقدرات +بقدراته +بقدراتها +بقدراتهم +بقدرة +بقدرته +بقدرتها +بقدسية +بقدمه +بقدميه +بقدميها +بقدوم +بقدونس +بقذفها +بقراءة +بقراءته +بقراءتها +بقراب +بقرار +بقراري +بقرب +بقربه +بقربها +بقربي +بقرشين +بقرض +بقرن +بقرون +بقرية +بقريتنا +بقرّاء +بقزامتي +بقسط +بقسم +بقسوة +بقسيمة +بقشرة +بقشيش +بقصائد +بقصته +بقصد +بقصر +بقصص +بقصصه +بقصيدة +بقصيدته +بقصيرة +بقضاء +بقضايا +بقضيب +بقضية +بقضيته +بقطار +بقطاع +بقطرياني +بقطع +بقطعة +بقع +بقعة +بقعته +بقعٌ +بقــــضايا +بقفزاته +بقفزة +بقلادة +بقلب +بقلبها +بقلبي +بقلة +بقلعة +بقلق +بقلم +بقلمه +بقلمها +بقلمي +بقلوبهم +بقليل +بقماش +بقمر +بقنا +بقنابل +بقناع +بقناعة +بقنـاطره +بقنفذ +بقهر +بقوا +بقوات +بقواعد +بقوالب +بقوانين +بقوة +بقوتك +بقوته +بقوتها +بقوش +بقول +بقولته +بقولنا +بقوله +بقولها +بقولهم +بقومه +بقوه +بقى +بقي +بقيء +بقيادة +بقيادته +بقياس +بقيام +بقية +بقيت +بقيتها +بقيتِ +بقيد +بقيصري +بقيق +بقيم +بقيمة +بقيود +بك +بكاء +بكاؤها +بكائن +بكائه +بكاتب +بكادر +بكارة +بكاف +بكافة +بكالوريا +بكالوريوس +بكاليفورنيا +بكامل +بكامله +بكاملها +بكبار +بكبر +بكبرياء +بكة +بكت +بكتائب +بكتاب +بكتابات +بكتاباته +بكتابة +بكتابته +بكتابتها +بكتابي +بكتب +بكتفه +بكتل +بكتلة +بكتلها +بكتيريا +بكتيرية +بكثافة +بكثرة +بكثير +بكحّة +بكر +بكرا +بكراتشى +بكراتشي +بكراسي +بكرامة +بكرامته +بكرامتي +بكرة +بكرةً +بكساوي +بكسر +بكسل +بكسوتها +بكسور +بكشف +بكشفك +بكشفه +بكف +بكفاءة +بكفالة +بكفها +بكل +بكلام +بكلامه +بكلتا +بكلفة +بكلمات +بكلماته +بكلمة +بكلمتين +بكلية +بكليته +بكليهما +بكم +بكميات +بكمية +بكمّ +بكناياتها +بكندا +بكنز +بكنوز +بكوبا +بكورونافيرس +بكوري +بكون +بكونك +بكونه +بكونها +بكوني +بكى +بكيت +بكيفية +بكيماويات +بكين +بكَمّ +بكِ +بل +بلا +بلاء +بلاؤه +بلاتيني +بلاد +بلادا +بلادة +بلادك +بلادنا +بلاده +بلادها +بلادهم +بلادي +بلازا +بلازموديوم +بلاس +بلاستيك +بلاستيكية +بلاش +بلاشك +بلاط +بلاطة +بلاطكم +بلاطه +بلال +بلامبالاة +بلانك +بلانينج +بلاهة +بلاير +بلايموث +بلايين +بلباقة +بلبلة +بلبنان +بلة +بلتفتون +بلجام +بلجيكا +بلحاف +بلحظات +بلحظة +بلحيتهِ +بلد +بلدا +بلدان +بلدانا +بلداننا +بلدانه +بلدانها +بلدانهم +بلداً +بلدة +بلدته +بلدتهم +بلدكم +بلدنا +بلده +بلدها +بلدهم +بلدوين +بلدي +بلديات +بلدية +بلدًا +بلدٍ +بلذة +بلس +بلسان +بلسانه +بلسانها +بلساني +بلسع +بلصق +بلطجي +بلطف +بلع +بلعبة +بلعبهم +بلعت +بلعنة +بلعوم +بلفافة +بلفت +بلفظتين +بلفها +بلفور +بلقاء +بلقائه +بلقب +بلقزيز +بلقمان +بلقيس +بلكونة +بللت +بلمسة +بلندن +بلهبها +بلهجة +بلهفة +بلو +بلوتارك +بلوحة +بلور +بلورة +بلورت +بلوشستان +بلوكان +بلومسبري +بلومندو +بلون +بلونه +بلونها +بلوني +بلونين +بلونيه +بلى +بليبيا +بليخ +بليد +بلير +بليس +بلينوس +بليون +بليونان +بليوني +بليونين +بلِبان +بلّة +بلْ +بم +بمآذنه +بمأساتنا +بمؤسسة +بمؤهلات +بمئات +بما +بماء +بمائة +بمائتي +بمائها +بمادة +بماذا +بماردين +بماضي +بماهية +بمبادئ +بمبادئه +بمبادراتها +بمبادرة +بمبادرته +بمباركة +بمبانيها +بمبدئه +بمبشر +بمبعد +بمبنى +بمبيد +بمتابعة +بمتاجر +بمتحف +بمتصل +بمتطلبات +بمتعة +بمتلازمة +بمثابة +بمثل +بمثله +بمثلها +بمثلهم +بمثيلاتها +بمجال +بمجالات +بمجالس +بمجاله +بمجامع +بمجتمع +بمجتمعات +بمجتمعاته +بمجتمعه +بمجدافين +بمجرد +بمجس +بمجسات +بمجلة +بمجلس +بمجملها +بمجموع +بمجموعات +بمجموعة +بمجموعها +بمحاذاة +بمحاربة +بمحاصيل +بمحاضرة +بمحاضرته +بمحافظة +بمحاكمة +بمحاولات +بمحاولاتي +بمحاولة +بمحبة +بمحبي +بمحبّيه +بمحتويات +بمحتوياته +بمحتوياتها +بمحدداتها +بمحصول +بمحض +بمحطات +بمحطة +بمحفظة +بمحلول +بمحمد +بمحمود +بمحنة +بمحو +بمخاطبة +بمخاطر +بمخالبه +بمختبر +بمختبرات +بمختلف +بمخرجين +بمخزون +بمخزونه +بمخلفات +بمخلوق +بمخلوقات +بمخلوقه +بمد +بمداد +بمدخلات +بمدر +بمدرسة +بمدرسته +بمدريد +بمدى +بمدي +بمدينة +بمدينتكم +بمدينتهم +بمدّها +بمذبحة +بمذهبه +بمرآة +بمراجعة +بمراجعتها +بمراحل +بمراحله +بمرارة +بمراسم +بمرافقة +بمرافقه +بمراقبة +بمراكز +بمربعات +بمرتب +بمرتبة +بمرتين +بمرجعه +بمرح +بمرحلة +بمرشح +بمرصد +بمرض +بمرضى +بمركز +بمرور +بمرونة +بمروياته +بمروية +بمريض +بمزاج +بمزاجية +بمزاولة +بمزايا +بمزاياه +بمزج +بمزيد +بمسألة +بمسؤوليته +بمسؤوليتهم +بمسئوليات +بمسئولية +بمسائل +بمسابقة +بمساحة +بمساحته +بمساحـة +بمسار +بمسارها +بمساعدات +بمساعدة +بمساعدتهم +بمساعدتي +بمسافة +بمساكن +بمساكنهم +بمساندة +بمستبق +بمستجدات +بمستقبل +بمستقبلهم +بمستلزماتها +بمستودع +بمستوطنات +بمستوى +بمستوي +بمستويات +بمسجد +بمسجل +بمسرح +بمسز +بمسقط +بمسلمة +بمسلمي +بمسندين +بمسيحيتهم +بمسيرة +بمسيرتهم +بمشاركة +بمشاريع +بمشاريعه +بمشاعر +بمشاعري +بمشاكل +بمشاكلك +بمشاهدات +بمشاهداتي +بمشاهدة +بمشروع +بمشقة +بمشكلة +بمشهد +بمشيئة +بمصاحبتها +بمصادر +بمصادرة +بمصادرتها +بمصادره +بمصالح +بمصدر +بمصدرها +بمصدريتها +بمصر +بمصطلح +بمضاربها +بمضاعفات +بمضمون +بمضي +بمطابع +بمطار +بمطاعم +بمطالب +بمطالعة +بمطربة +بمطرها +بمطهّر +بمظانه +بمظاهر +بمظاهرة +بمظهر +بمظهره +بمعادلة +بمعارض +بمعارضة +بمعارضها +بمعارضيه +بمعاشهم +بمعالجة +بمعالجتها +بمعامل +بمعاملتهم +بمعاونتنا +بمعايير +بمعبد +بمعدل +بمعدلات +بمعدن +بمعدَّلات +بمعدَّلاتٍ +بمعرض +بمعرضين +بمعرفة +بمعرفته +بمعزل +بمعطفه +بمعطيات +بمعظم +بمعـــناه +بمعلمة +بمعلومات +بمعماريته +بمعمل +بمعمودية +بمعناه +بمعناها +بمعنى +بمعني +بمعهد +بمعيار +بمعية +بمعيته +بمفاجأة +بمفاصلي +بمفاهيم +بمفتاح +بمفتاحه +بمفردات +بمفرده +بمفردها +بمفردهما +بمفهوم +بمفهومها +بمقابر +بمقاديرها +بمقاصدها +بمقاطعة +بمقالاته +بمقاومة +بمقايضة +بمقاييس +بمقبرة +بمقتضاه +بمقتضاها +بمقتضى +بمقتضي +بمقتضيات +بمقدار +بمقداره +بمقدرة +بمقدرته +بمقدساتها +بمقدم +بمقدمة +بمقدمته +بمقدور +بمقدورنا +بمقدوره +بمقدورهم +بمقر +بمقره +بمقصورة +بمقود +بمقولة +بمقومات +بمقياس +بمقياسه +بمكاتب +بمكاتبها +بمكافأة +بمكافأتها +بمكافحة +بمكان +بمكانة +بمكانتها +بمكاني +بمكبر +بمكة +بمكتبة +بمكتبه +بمكر +بمكن +بمكونات +بملء +بملابس +بملابسم +بملابسه +بملابسهم +بملابسهن +بملاحظاته +بملاحظة +بملاحقة +بملاعق +بملامسة +بملايين +بملايينه +بملايينها +بملحوظة +بملك +بملكية +بملل +بمليار +بمليارات +بمليم +بمليون +بمليوني +بمليونين +بممارسة +بممانعة +بممانعتها +بممر +بممرات +بمن +بمنأى +بمناجم +بمنازلها +بمناسبة +بمناطق +بمناظرها +بمنافسة +بمناقشة +بمناهج +بمناهجها +بمنتجات +بمنتجاتها +بمنتهى +بمنجزات +بمنح +بمنحة +بمنحه +بمنحها +بمنحوتتين +بمنخري +بمندوبين +بمنديل +بمنزل +بمنزلة +بمنزله +بمنشفة +بمنصب +بمنطق +بمنطقة +بمنطقية +بمنظار +بمنظماتها +بمنظمة +بمنظومة +بمنع +بمنعطف +بمنفذين +بمنفعة +بمنقاش +بمنهجه +بمنهجية +بمهاجمة +بمهاراتهم +بمهارة +بمهامها +بمهامهم +بمهرجان +بمهمة +بمهنة +بمهنية +بمواجهة +بمواد +بموارد +بموازاة +بمواصفات +بمواصلة +بمواطنيه +بموافقة +بمواقع +بمواقعها +بمواقيت +بمواكبة +بموت +بموته +بموجب +بموجبه +بموجبها +بموجة +بمودة +بموديلين +بموروث +بموسكو +بموسم +بموسيقاه +بموسيقاها +بموسيقى +بموضوع +بموعد +بموعود +بموقع +بموقعه +بموقعها +بموقفه +بموقفها +بمولد +بموهبتهم +بموهبتي +بمي +بمياه +بمياهه +بميدان +بميزانين +بميزة +بميسوري +بميكرفون +بميلاد +بن +بنا +بناء +بناءه +بناءً +بناؤه +بنائه +بنائها +بنائي +بناة +بنات +بناتها +بناتي +بنادق +بنار +بناطحات +بناظرها +بنافورته +بناقة +بناقدين +بنامٍ +بناه +بناها +بنايات +بناياتها +بناياتهم +بناية +بنبأ +بنباتات +بنبالهم +بنبرتي +بنبع +بنت +بنتا +بنتائج +بنتاج +بنتها +بنتيجة +بنتيوم +بنثاره +بنثر +بنجاب +بنجاح +بنجاحي +بنجاسة +بنجلاديش +بنحاس +بنحت +بنحو +بنخيلها +بند +بنداء +بندر +بندشوار +بندقية +بندورة +بندولاً +بنزاهة +بنزاهته +بنزع +بنزول +بنزيف +بنزين +بنسب +بنسبة +بنسبه +بنسخ +بنسخة +بنسل +بنسلفانيا +بنسيج +بنسيلفانيا +بنشأة +بنشاط +بنشاطات +بنشاطه +بنشر +بنشرها +بنشوة +بنصف +بنصها +بنصوص +بنصيب +بنصيحة +بنصيحته +بنضج +بنطالا +بنظارتيه +بنظافة +بنظافتها +بنظام +بنظامها +بنظر +بنظرات +بنظراته +بنظراتها +بنظرة +بنظرته +بنظري +بنظرية +بنظير +بنظيراتها +بنعم +بنعمة +بنعومة +بنفايات +بنفخ +بنفس +بنفسجية +بنفسك +بنفسه +بنفسها +بنفسي +بنفوذ +بنفي +بنفيه +بنفيها +بنقائصنا +بنقاط +بنقد +بنقش +بنقص +بنقصها +بنقطة +بنقل +بنقلة +بنقله +بنقلها +بنقوش +بنقوشها +بنك +بنكتة +بنمط +بنمطه +بنموذج +بنهايات +بنهاية +بنهايته +بنهب +بنهج +بنهضة +بنهم +بنو +بنوا +بنوادر +بنوازع +بنوب +بنوبة +بنوتة +بنود +بنودها +بنور +بنورماندي +بنورها +بنوري +بنوس +بنوع +بنوعه +بنوعية +بنوعيه +بنوك +بنى +بني +بنيات +بنيامين +بنيان +بنيانا +بنيانها +بنية +بنيت +بنيتنا +بنيتها +بنين +بنينا +بنيناه +بنيناها +بنيه +بنيها +بنيوي +بنيوية +بنيويورك +بنيويًا +بنيّ +بنَفَس +بنّاءة +به +بهؤلاء +بها +بهاء +بهاءه +بهاءها +بهاءً +بهائم +بهاجس +بهادور +بهالات +بهامشية +بهبيت +بهت +بهجة +بهجت +بهجرة +بهجرهم +بهجمات +بهجماتها +بهدف +بهدم +بهدنة +بهدوء +بهدوئه +بهذا +بهذه +بهذين +بهر +بهراواتهم +بهرتني +بهرتها +بهرني +بهزات +بهزة +بهزّها +بهستريا +بهستيريا +بهستيرية +بهـدوء +بهلع +بهلوانية +بهم +بهما +بهمان +بهمة +بهن +بهندسة +بهو +بهواجس +بهوس +بهول +بهولندا +بهونج +بهويتها +بهويتهم +بهيئة +بهيا +بهية +بهيكله +بهيمنة +بهيمي +بو +بوأها +بوابات +بواباتها +بوابة +بوابتين +بوابل +بواجب +بواجبات +بواجباته +بواجباتها +بواجباتي +بواجهة +بواحد +بواحدة +بواخر +بوادر +بواسطة +بواسطته +بواسطتها +بواشنطن +بواعث +بواقع +بواقعه +بواقعها +بواقعية +بواكيره +بواكيري +بوالب +بوالدي +بوالص +بوان +بوبال +بوتائر +بوتره +بوتس +بوتسوانا +بوتقة +بوتو +بوتيل +بوجدانه +بوجع +بوجه +بوجهات +بوجهة +بوجهه +بوجهها +بوجهي +بوجود +بوجودنا +بوجوده +بوجودها +بوجودهم +بوجودي +بوجوم +بوجوه +بوحدانية +بوحدة +بوحي +بوخالد +بوخز +بوخضير +بودلير +بودي +بوذية +بور +بورا +بورتوريكو +بورتوفينو +بورخارت +بورخس +بورد +بوردها +بورع +بورقة +بورقيبة +بوركهاردت +بورم +بورما +بورندي +بورنو +بوريقات +بوريما +بوزاة +بوزار +بوزارة +بوزاني +بوزن +بوزنه +بوزنها +بوزير +بوسائل +بوسائلنا +بوسائله +بوساطة +بوسط +بوسطن +بوسع +بوسعك +بوسعكم +بوسعه +بوسعهم +بوسعي +بوش +بوشاحها +بوشر +بوصات +بوصة +بوصتين +بوصف +بوصفه +بوصفها +بوصفي +بوصلة +بوصول +بوضع +بوضعية +بوضوح +بوطأة +بوطبنية +بوطنه +بوطنهم +بوطنيته +بوظائف +بوظائفها +بوظته +بوظهير +بوظيفة +بوعده +بوعدها +بوعودها +بوعي +بوعيه +بوعيها +بوف +بوفاة +بوفانيل +بوفرة +بوفورات +بوفون +بوفيدون +بوفيه +بوق +بوقت +بوقته +بوقف +بوقفات +بوقفة +بوقود +بوك +بوكر +بوكس +بوكلاء +بوكيمون +بول +بولاياتها +بولاية +بولب +بولدر +بولدن +بولدين +بولس +بولص +بولع +بولندا +بوله +بولونيا +بولي +بوليب +بوليبات +بوليتان +بوليتزر +بوليسية +بوليمة +بومباي +بون +بونابرت +بونتاجروسا +بوند +بونيتي +بوهمند +بوهيمي +بوهيمياً +بوهين +بوية +بويضات +بويك +بويليك +بوينت +بوينتا +بوينج +بويون +بى +بي +بيئات +بيئاته +بيئاتهم +بيئة +بيئتنا +بيئته +بيئتها +بيئتهم +بيئي +بيئيا +بيئياً +بيئية +بياء +بياترس +بياتريس +بياراتها +بيارق +بياض +بياضا +بياضاً +بياضه +بياضها +بياضهما +بيان +بيانا +بيانات +بياناته +بياناتها +بياناتهم +بياناتي +بياناً +بيانه +بيانها +بيانو +بيانًا +بيبرس +بيبلوس +بيبيس +بيت +بيتا +بيتان +بيتاهيدروكس +بيتاً +بيتحكم +بيتر +بيتروكوس +بيتروناس +بيتزاهت +بيتس +بيتك +بيتمان +بيتنا +بيته +بيتها +بيتهم +بيتهما +بيتي +بيتُ +بيثرو +بيجن +بيجوم +بيجين +بيد +بيدك +بيده +بيدها +بيدو +بيدي +بيدين +بيديه +بيديها +بير +بيران +بيرة +بيرتون +بيرج +بيرجر +بيرد +بيردي +بيرس +بيرم +بيرنارد +بيرو +بيروت +بيروتية +بيروكسيد +بيروكسيداز +بيرونيك +بيروي +بيري +بيريز +بيريس +بيريفوتشيك +بيزنس +بيزنطة +بيزنطي +بيزنطية +بيسا +بيسان +بيسر +بيسي +بيش +بيشاور +بيض +بيضا +بيضاء +بيضة +بيضها +بيضوي +بيطرانية +بيطرية +بيع +بيعت +بيعه +بيعها +بيعي +بيقين +بيك +بيكار +بيكاسو +بيكسل +بيكو +بيكون +بيكويث +بيل +بيلا +بيلاثكيت +بيلار +بيلامين +بيلوبس +بيلوز +بيمبي +بيمينه +بين +بينابيعه +بينات +بيناته +بينازير +بينالي +بينة +بينت +بينتويش +بينجمية +بيندرانوال +بينك +بينكم +بينما +بينمالايزال +بيننا +بينه +بينها +بينهم +بينهما +بينهن +بينوا +بيني +بينياً +بينية +بينَّا +بيهار +بيوبيلها +بيوت +بيوتا +بيوتات +بيوتاً +بيوتنا +بيوتها +بيوتهم +بيوتهن +بيوتي +بيوتيرات +بيوتيك +بيور +بيوسف +بيوسيا +بيوضها +بيولوجي +بيولوجيا +بيولوجية +بيوم +بيومين +بيونس +بيير +بيّنت +بًا +بَدَّلُوا +بَرَكة +بَعْضٍ +بَعْضُكُم +بَعْضُهُمْ +بُح +بُد +بُدًّا +بُذلت +بُضع +بُعد +بُعيد +بُعْد +بُني +بُنيت +بِالْمَعْرُوفِ +بِهِ +ة +ت +تآكل +تآلف +تآليف +تآمرية +تأبط +تأبه +تأبى +تأبي +تأبيد +تأبين +تأبينه +تأت +تأتى +تأتي +تأتيكم +تأتينا +تأتيه +تأثر +تأثرا +تأثراً +تأثرت +تأثره +تأثرها +تأثرهما +تأثروا +تأثيث +تأثير +تأثيرا +تأثيرات +تأثيراتها +تأثيراً +تأثيره +تأثيرها +تأثيريا +تأثيرية +تأثيرًا +تأثيرٌ +تأثّرت +تأثّري +تأثُّر +تأثُّراً +تأجير +تأجيل +تأخذ +تأخذك +تأخذني +تأخذه +تأخر +تأخرت +تأخرتم +تأخره +تأخير +تأخّر +تأدبت +تأديبه +تأدية +تأديتها +تأذي +تأرجح +تأرجحا +تأرجحات +تأرجحت +تأريخ +تأريخي +تأريخية +تأسس +تأسست +تأسستا +تأسوا +تأسيس +تأسيسا +تأسيسه +تأسيسها +تأسيسيًا +تأشيرات +تأشيرة +تأصلت +تأصيل +تأصيلاً +تأطير +تأقلم +تأكد +تأكدت +تأكل +تأكلها +تأكلهُ +تأكيد +تأكيدا +تأكيداً +تأكيدنا +تأكيـــد +تألف +تألق +تألقا +تألقت +تألقه +تألقًا +تألم +تألمت +تأليف +تأليفه +تأليفها +تأليفي +تألّف +تأمل +تأملات +تأملاته +تأملها +تأملهم +تأملوا +تأملي +تأملية +تأمليًّا +تأميم +تأمين +تأمينها +تأمّلها +تأنيب +تأنيبه +تأنيبي +تأنيث +تأهب +تأهل +تأهيل +تأهيلاً +تأوي +تأويل +تأويلات +تأييد +تأييدًا +تأّمل +تؤاخدنا +تؤاخذنا +تؤازره +تؤتي +تؤثر +تؤجل +تؤخذ +تؤخر +تؤدى +تؤدي +تؤذي +تؤذين +تؤرق +تؤرقه +تؤرقهم +تؤسس +تؤكد +تؤكده +تؤكـــد +تؤلف +تؤلمانني +تؤمن +تؤمنها +تؤهب +تؤهله +تؤهلهم +تؤويهم +تؤيد +تؤيدهم +تئن +تاء +تائه +تائهون +تاب +تابات +تابع +تابعا +تابعاً +تابعة +تابعت +تابعنا +تابعه +تابعوا +تابعين +تابعَ +تابلوهات +تابوا +تابوت +تابوتا +تابوتها +تابوتي +تاتشر +تاثيراته +تاثيراً +تاج +تاجر +تاجرا +تاجراً +تاجري +تاجوراء +تاخذ +تاخير +تاديوز +تارة +تارك +تاركا +تاركاً +تاركة +تاركين +تاركًا +تاريخ +تاريخا +تاريخاً +تاريخنا +تاريخه +تاريخها +تاريخهم +تاريخي +تاريخيا +تاريخياً +تاريخية +تاريخيته +تاريخين +تاريخيًا +تافه +تافهة +تاكسي +تاكيلا +تالفة +تالله +تاليان +تالياً +تالياًلتوجيه +تالية +تاليًا +تام +تاما +تامارا +تاماً +تامة +تامّاً +تانجه +تاه +تاون +تايبجي +تايبيه +تايلر +تايلند +تايلور +تايم +تايمز +تايوان +تب +تبا +تباب +تبادرها +تبادل +تبادلت +تبادلنا +تبادلينا +تبادلِ +تبارحه +تبارز +تبارك +تبارى +تباري +تباشير +تباطأت +تباطأتْ +تباطؤ +تباع +تباعا +تباعاً +تباعد +تبال +تباهي +تباين +تبايناً +تباينت +تبتدع +تبتسم +تبتسي +تبتعد +تبتلع +تبتلعها +تبث +تبثه +تبثها +تبح +تبحث +تبحثا +تبحثون +تبحثين +تبحر +تبحلق +تبخر +تبخرها +تبد +تبدأ +تبدت +تبدد +تبددت +تبدع +تبدل +تبدلات +تبدلت +تبدو +تبدي +تبديد +تبديل +تبديله +تبديها +تبدّت +تبدّل +تبدَّى +تبدُّل +تبذل +تبذلها +تبذير +تبرئة +تبرحني +تبرحه +تبرد +تبرر +تبرز +تبرزها +تبرع +تبرعات +تبرعتا +تبرق +تبرقان +تبريد +تبرير +تبريرها +تبرّم +تبزّ +تبسيط +تبشر +تبصر +تبصران +تبطئ +تبطن +تبع +تبعا +تبعات +تبعاته +تبعاتها +تبعاً +تبعته +تبعتها +تبعث +تبعثر +تبعثرت +تبعثها +تبعد +تبعه +تبعها +تبعية +تبعيتها +تبعًا +تبـني +تبق +تبقت +تبقوا +تبقى +تبقي +تبقيه +تبقّى +تبكي +تبلر +تبلل +تبللت +تبللني +تبلور +تبلورت +تبليط +تبنت +تبنته +تبنتها +تبنى +تبني +تبنيتها +تبنيه +تبنيها +تبنّى +تبهرني +تبهره +تبوء +تبوأت +تبوح +تبوك +تبويبها +تبي +تبياناً +تبيت +تبيح +تبيد +تبيع +تبيعه +تبيعها +تبين +تبينت +تبينوا +تبيّن +تبيِّن +تبِع +تبّاً +تبًّا +تت +تتآكل +تتآمر +تتأثر +تتأثَّر +تتأجج +تتأرجح +تتأكد +تتألف +تتألق +تتألم +تتأمل +تتأمَّل +تتابع +تتابعت +تتاح +تتالى +تتبادل +تتبارز +تتبارى +تتباعد +تتباهى +تتباهي +تتباين +تتبختر +تتبخر +تتبدد +تتبدل +تتبدى +تتبدّى +تتبع +تتبعت +تتبعثر +تتبعه +تتبعها +تتبعهم +تتبق +تتبلور +تتبناه +تتبناهما +تتبنى +تتبني +تتبنَّى +تتبوأ +تتبين +تتجاذب +تتجافى +تتجاهل +تتجاهلني +تتجاهلها +تتجاوب +تتجاور +تتجاوز +تتجاوزونها +تتجدد +تتجرع +تتجسد +تتجسس +تتجسّم +تتجلى +تتجلّى +تتجمع +تتجنب +تتجه +تتجول +تتح +تتحايل +تتحد +تتحداني +تتحدث +تتحدثان +تتحدثين +تتحدد +تتحرر +تتحرك +تتحركان +تتحرّك +تتحسس +تتحسسان +تتحسسها +تتحسن +تتحسّر +تتحسّس +تتحسَّس +تتحصّل +تتحطم +تتحفظ +تتحقق +تتحكم +تتحلل +تتحلى +تتحلَّى +تتحمس +تتحمل +تتحملها +تتحمّل +تتحول +تتحوّل +تتحوَّل +تتحين +تتخاصم +تتخاطفها +تتخبط +تتخبطان +تتخبّط +تتخذ +تتخذه +تتخذها +تتخرجوا +تتخصص +تتخضب +تتخطى +تتخفى +تتخلص +تتخلع +تتخلف +تتخلق +تتخلل +تتخللها +تتخلى +تتخلَّصي +تتخيل +تتخيله +تتداخل +تتدافع +تتدخل +تتدفق +تتدلى +تتدنى +تتذكر +تتذكرني +تتذكره +تتذكرون +تتر +تتراءى +تتراجع +تترادف +تتراص +تترافق +تتراكض +تتراكم +تتراوح +تتربع +تترتب +تترجم +تترجمه +تترجمون +تترجّانا +تتردد +تترددان +تترسب +تترصد +تترصدني +تترقب +تترك +تتركز +تتركني +تتركه +تتركها +تتركون +تتركي +تتركّز +تتزايد +تتزحزح +تتزوج +تتزوجني +تتزين +تتساءل +تتسابق +تتساحب +تتسارع +تتساقط +تتساوى +تتسبب +تتستروا +تتسخ +تتسخن +تتسرب +تتسرعي +تتسرّب +تتسع +تتسق +تتسلل +تتسلم +تتسم +تتسيّج +تتسَّبب +تتشابك +تتشابه +تتشارك +تتشبث +تتشظى +تتشقق +تتشكل +تتشكّل +تتصادم +تتصارع +تتصاعد +تتصالب +تتصالح +تتصحَّر +تتصدر +تتصدى +تتصدين +تتصدّرها +تتصرف +تتصف +تتصل +تتصوّره +تتضاءل +تتضاعف +تتضافر +تتضح +تتضخم +تتضرر +تتضمن +تتضمنه +تتضمّن +تتضمَّن +تتطابق +تتطاول +تتطاير +تتطلب +تتطلبه +تتطلبها +تتطلع +تتطلعان +تتطلعون +تتطهر +تتطور +تتطورالأعراض +تتظاهر +تتعابث +تتعارض +تتعاطف +تتعاظم +تتعالى +تتعامل +تتعاملين +تتعايش +تتعب +تتعبني +تتعثر +تتعجب +تتعداها +تتعدد +تتعدى +تتعدَّ +تتعرض +تتعرف +تتعرَّف +تتعسر +تتعشق +تتعطر +تتعفن +تتعقد +تتعكر +تتعلق +تتعلم +تتعمد +تتعملق +تتعنى +تتعهد +تتفاخر +تتفاداه +تتفاعل +تتفاقم +تتفاوت +تتفتت +تتفتح +تتفتق +تتفتّح +تتفحصان +تتفرج +تتفرع +تتفضلون +تتفق +تتقاتل +تتقارب +تتقاسم +تتقاسمه +تتقاطع +تتقافز +تتقبل +تتقبلها +تتقدم +تتقصى +تتقصّد +تتقلص +تتقمص +تتقمّص +تتقن +تتقيد +تتكاتف +تتكاثر +تتكاثف +تتكالب +تتكامل +تتكبد +تتكبدها +تتكتّل +تتكثف +تتكدس +تتكرر +تتكفل +تتكلم +تتكلمون +تتكهن +تتكون +تتكيس +تتكيف +تتلاءم +تتلاحق +تتلاشى +تتلاشي +تتلاطم +تتلاقى +تتلخص +تتلف +تتلفها +تتلقاها +تتلقفك +تتلقى +تتلقي +تتلمذ +تتلمذت +تتلمس +تتلمسها +تتلمَّس +تتلى +تتلْمُذي +تتم +تتماثل +تتماسك +تتماشى +تتماهى +تتمايز +تتمايل +تتمتع +تتمثل +تتمحور +تتمخض +تتمدد +تتمركز +تتمزق +تتمسك +تتمشى +تتمكن +تتملص +تتملكه +تتملَّص +تتممه +تتمناها +تتمنى +تتمنّى +تتمهل +تتميز +تتمّ +تتناءى +تتناثر +تتناجى +تتناحر +تتنازل +تتنازلين +تتناسب +تتناقص +تتناقض +تتنامى +تتنامي +تتناهى +تتناول +تتنبأ +تتنزه +تتنصت +تتنكر +تتنوع +تتهادى +تتهاوى +تتهدل +تتهدَّد +تتهرب +تتهربي +تتهكم +تتهمه +تتهمون +تتهيأ +تتهيّأ +تتواءم +تتواجد +تتوارث +تتوارى +تتوازن +تتواصل +تتوافر +تتوالد +تتوالى +تتوانى +تتوتر +تتوج +تتوجب +تتوجه +تتوحد +تتوخى +تتورم +تتوزع +تتوسط +تتوسطها +تتوسع +تتوضع +تتوفر +تتوق +تتوقع +تتوقف +تتولد +تتولى +تتولي +تتوهج +تتوهّج +تتويجاً +تتيح +تتيحه +تتيحها +تتّحسّن +تثار +تثاقف +تثاقل +تثاقلاً +تثاقلية +تثب +تثبت +تثبتين +تثبط +تثبيت +تثبيتا +تثبيته +تثبيط +تثرى +تثري +تثقب +تثقبه +تثقف +تثقل +تثقي +تثقيبه +تثقيف +تثقيفي +تثمر +تثمره +تثني +تثور +تثير +تثيره +تثيرها +تثيرهم +تجاذب +تجاذبوني +تجار +تجاراً +تجارب +تجاربنا +تجاربه +تجاربها +تجاربى +تجاربي +تجارة +تجارةٌ +تجارته +تجارتها +تجاره +تجارى +تجاري +تجارياً +تجارية +تجاعيد +تجالسه +تجانس +تجانسه +تجاه +تجاهك +تجاهل +تجاهلاً +تجاهلت +تجاهلنا +تجاهله +تجاهلها +تجاهلوا +تجاهلوه +تجاهنا +تجاهه +تجاهها +تجاوب +تجاوباً +تجاور +تجاورت +تجاوز +تجاوزا +تجاوزات +تجاوزت +تجاوزتها +تجاوزني +تجاوزه +تجاوزها +تجاوزوا +تجاوزوها +تجاويفه +تجب +تجبر +تجبهه +تجتاح +تجتاز +تجتذب +تجتمع +تجتمعان +تجد +تجددت +تجددها +تجدر +تجدك +تجدني +تجده +تجدها +تجدهم +تجدوا +تجدي +تجديد +تجديدي +تجديديا +تجديدية +تجذب +تجذبه +تجذر +تجر +تجرأ +تجرأت +تجرؤ +تجرب +تجربة +تجربةً +تجربتنا +تجربته +تجربتها +تجربتهم +تجربتي +تجرثم +تجرش +تجرفه +تجرها +تجرى +تجري +تجريب +تجريبها +تجريبي +تجريبياً +تجريبية +تجريبيّ +تجريح +تجريد +تجريده +تجريدي +تجريدية +تجريها +تجرّب +تجزئة +تجزع +تجسد +تجسدت +تجسر +تجسس +تجسسية +تجسسًا +تجسيد +تجسيدا +تجسيداً +تجسيدها +تجسيدًا +تجسيم +تجسّد +تجسّده +تجسّدها +تجسّسي +تجشأ +تجشمت +تجعل +تجعلك +تجعلنا +تجعلني +تجعله +تجعلها +تجعلهم +تجـريبية +تجف +تجفل +تجفيف +تجفيفه +تجفيفها +تجفّف +تجفُّ +تجل +تجلب +تجلبه +تجلبها +تجلت +تجلس +تجلسان +تجلى +تجلي +تجليات +تجلياته +تجلياتها +تجليد +تجليّات +تجليّاته +تجلّت +تجلَّت +تجمع +تجمعات +تجمعاته +تجمعاتها +تجمعت +تجمعنا +تجمعني +تجمعها +تجمعهم +تجمعوا +تجميد +تجميع +تجميعا +تجميل +تجميلي +تجميليا +تجميلية +تجمّع +تجمّعات +تجمّعنا +تجمّعوا +تجمَّع +تجنب +تجنبا +تجنباً +تجنبت +تجنبك +تجنبها +تجنبهم +تجنى +تجني +تجنيد +تجنّبا +تجنّبنا +تجهر +تجهز +تجهل +تجهلها +تجهيز +تجهيزات +تجهيزاته +تجهيزاتهما +تجهيزه +تجهيزها +تجهّم +تجوالنا +تجواله +تجوالي +تجوب +تجوبان +تجوز +تجوس +تجول +تجولت +تجولنا +تجويد +تجويدي +تجويف +تجوّلت +تجيء +تجيب +تجيد +تجيده +تجيدها +تجيزه +تجّار +تجّمعات +تحابي +تحات +تحادث +تحاذر +تحارب +تحاشي +تحاشيه +تحاصر +تحافظ +تحاكم +تحاكى +تحاكي +تحالف +تحالفاتها +تحالفاً +تحامل +تحاملت +تحاور +تحاورت +تحاورها +تحاول +تحايل +تحب +تحبب +تحبطه +تحبه +تحبها +تحبو +تحبّذ +تحبّه +تحت +تحتاج +تحتاجه +تحتاجها +تحتاجين +تحتال +تحتج +تحترف +تحترق +تحترم +تحترمه +تحتشد +تحتضن +تحتضنني +تحتضنه +تحتضنها +تحتضنهم +تحتفظ +تحتقر +تحتل +تحتلّ +تحتمس +تحتمل +تحتملهم +تحتمها +تحتمي +تحتنا +تحته +تحتها +تحتهم +تحتهما +تحتوى +تحتوي +تحتويه +تحتويها +تحتي +تحتية +تحتَ +تحث +تحثنا +تحجب +تحجز +تحجل +تحجيم +تحجيمها +تحد +تحداهم +تحدث +تحدثت +تحدثتم +تحدثنا +تحدثني +تحدثه +تحدثها +تحدثوا +تحدثونا +تحدد +تحددت +تحدده +تحددها +تحدر +تحدق +تحدقان +تحدو +تحدونا +تحدوه +تحدى +تحدي +تحديا +تحديات +تحدياً +تحديت +تحديث +تحديثات +تحديثي +تحديد +تحديدا +تحديداً +تحديده +تحديدها +تحديدي +تحديقهما +تحديًا +تحدٍ +تحدّث +تحدّثت +تحدّثنا +تحدّق +تحدّياً +تحدٍّ +تحدَّث +تحذر +تحذرني +تحذو +تحذير +تحذيرا +تحذيرات +تحذيراتنا +تحذيره +تحذّر +تحرجا +تحرر +تحررت +تحررني +تحررها +تحررهما +تحررية +تحرس +تحرسنا +تحرص +تحرق +تحرقه +تحرك +تحركاتها +تحركاتهم +تحركت +تحركنا +تحرم +تحري +تحرير +تحريرة +تحريرصحيفة +تحريره +تحريرها +تحريرية +تحريض +تحريضات +تحريضاً +تحريضهم +تحريفه +تحريك +تحريم +تحريمات +تحريماً +تحرّراً +تحرّرت +تحرّك +تحرّكت +تحرّكه +تحرَّكت +تحزن +تحزني +تحس +تحسب +تحسبا +تحسباً +تحسبهم +تحسس +تحسسي +تحسسية +تحسن +تحسنا +تحسون +تحسين +تحسينه +تحسينها +تحسينيًا +تحسَّست +تحسُّباً +تحشر +تحشرين +تحصد +تحصل +تحصلون +تحصلَ +تحصى +تحصيل +تحصيلهم +تحصيلي +تحصينات +تحصيناته +تحصينها +تحصّن +تحض +تحضر +تحضير +تحضيرها +تحط +تحطان +تحطم +تحطمت +تحطمها +تحطيم +تحطيمه +تحطيمي +تحطّم +تحظ +تحظر +تحظى +تحظي +تحـتاج +تحـتل +تحـتوى +تحـظي +تحـفيز +تحـقق +تحـقيق +تحـقيقاً +تحف +تحفة +تحفر +تحفرها +تحفز +تحفزنا +تحفظ +تحفظاً +تحفظه +تحفظها +تحفل +تحفهم +تحفيز +تحفيزاً +تحفيظ +تحفّ +تحفّظت +تحقق +تحققت +تحققه +تحققها +تحقن +تحقيق +تحقيقا +تحقيقات +تحقيقاً +تحقيقه +تحقيقها +تحقيقي +تحقيقًا +تحقّق +تحقّقها +تحكم +تحكمه +تحكمها +تحكموا +تحكي +تحكيم +تحل +تحلــل +تحلق +تحلقوا +تحلل +تحللت +تحلله +تحلم +تحلى +تحلية +تحليق +تحليل +تحليلاتهم +تحليلاً +تحليلنا +تحليله +تحليلها +تحليلي +تحليلية +تحلّق +تحلَّم +تحمد +تحمر +تحمسوا +تحمل +تحملا +تحملت +تحملنا +تحمله +تحملها +تحملهم +تحملهما +تحمى +تحمي +تحميل +تحميها +تحمّل +تحمّلت +تحمّلها +تحمُّل +تحن +تحنية +تحور +تحول +تحولا +تحولات +تحولاتها +تحولاً +تحولت +تحولها +تحولهم +تحولوا +تحوي +تحويد +تحوير +تحويل +تحويله +تحويلها +تحويه +تحويها +تحوّل +تحوّلت +تحوّلنا +تحوّله +تحوّلي +تحوُّل +تحيا +تحياه +تحياها +تحية +تحيتها +تحيد +تحيروا +تحيز +تحيزها +تحيط +تحيطها +تحيق +تحيك +تحيلها +تحين +تحييد +تخاذل +تخاصم +تخاطب +تخاف +تخافي +تخالطه +تخالف +تخبئ +تخبر +تخبرنا +تخبرني +تخبره +تخبريني +تخبطها +تخبو +تختار +تختاره +تختال +تختبئ +تختبر +تختتم +تخترق +تخترقها +تختزل +تختزلهما +تختزن +تختزنها +تختص +تختصر +تختفي +تختل +تختلج +تختلس +تختلط +تختلف +تختلقها +تختم +تختنق +تخثر +تخثره +تخجلين +تخدش +تخدم +تخدمها +تخذل +تخذله +تخرب +تخرج +تخرجت +تخرجتُ +تخرجك +تخرجكم +تخرجه +تخرجهم +تخرجوا +تخرجي +تخرجين +تخريب +تخريبها +تخريبي +تخريج +تخريجه +تخريش +تخرّجت +تخزن +تخزه +تخزين +تخزينها +تخسر +تخشى +تخشي +تخص +تخصص +تخصصات +تخصصاتهم +تخصصاً +تخصصت +تخصصه +تخصصها +تخصصي +تخصصية +تخصها +تخصهم +تخصيب +تخصيص +تخصيصاً +تخصيصه +تخصيصها +تخصّه +تخضبن +تخضر +تخضع +تخط +تخطأ +تخطئ +تخطئها +تخطاني +تخطب +تخطت +تخطر +تخطط +تخططون +تخطف +تخطو +تخطى +تخطي +تخطيط +تخطيطا +تخطيطاً +تخطيطي +تخطّيها +تخف +تخفت +تخفض +تخفف +تخففا +تخففها +تخفى +تخفي +تخفيض +تخفيضات +تخفيف +تخفيفا +تخفيه +تخفّ +تخل +تخلب +تخلخل +تخلص +تخلصت +تخلصه +تخلط +تخلف +تخلفت +تخلفنا +تخلفهم +تخلفوا +تخلق +تخلل +تخلله +تخلو +تخلى +تخلي +تخليا +تخليد +تخليدا +تخليداً +تخليص +تخليصه +تخليق +تخليقه +تخلينا +تخليه +تخلّ +تخلّت +تخلّص +تخلّع +تخلّف +تخلّفتُ +تخلَّص +تخلِّصنا +تخلِّصني +تخمد +تخمين +تخنق +تخني +تخوض +تخوضه +تخوضها +تخوف +تخوفات +تخوفهم +تخوفي +تخول +تخوله +تخوم +تخومها +تخون +تخونني +تخونها +تخيب +تخيفه +تخيل +تخيلاتنا +تخيلت +تخيلته +تخيلها +تخيلي +تخيلّتُ +تدابير +تداخل +تداخلت +تداخلها +تدار +تدارسها +تدارك +تداريه +تداعى +تداعي +تداعيات +تداعياته +تدافع +تدافعناه +تداول +تداولاً +تداولها +تداولوا +تدب +تدبر +تدبرنا +تدبير +تدبيرها +تدبّرها +تدجيل +تدجين +تدجينها +تدخل +تدخلت +تدخله +تدخلها +تدخين +تدخّل +تدخّلاً +تدر +تدرب +تدربي +تدرج +تدرجت +تدرس +تدرسنا +تدرك +تدركه +تدره +تدري +تدريب +تدريبا +تدريبات +تدريباً +تدريبه +تدريبها +تدريبهم +تدريبي +تدريبية +تدريبًا +تدريجي +تدريجيا +تدريجياً +تدريجيًا +تدريجيًّا +تدريس +تدريسا +تدريساً +تدريسه +تدريسها +تدريسهم +تدرّجت +تدرّس +تدش +تدشين +تدشينها +تدع +تدعم +تدعمها +تدعه +تدعها +تدعو +تدعونا +تدعوني +تدعى +تدعي +تدعيم +تدعيمه +تدعيمها +تدفئ +تدفع +تدفعني +تدفعه +تدفعها +تدفعهم +تدفق +تدفقات +تدفقاً +تدفقت +تدفقها +تدفن +تدفنها +تدق +تدقق +تدقيق +تدقيقها +تدكُّ +تدل +تدلت +تدله +تدلها +تدليك +تدليه +تدلُّه +تدم +تدمر +تدمرت +تدمرها +تدمير +تدميرية +تدمّر +تدن +تدنو +تدني +تدهش +تدهشنا +تدهور +تدهوراً +تدهورت +تدهورها +تدهورًا +تدور +تدوران +تدورُ +تدوس +تدوم +تدوير +تدويره +تدويرها +تدوين +تدوّي +تدير +تديره +تديرها +تدين +تدينجتون +تديّناً +تدّعين +تذاب +تذاع +تذاكر +تذاكرهم +تذبذب +تذرف +تذكاراً +تذكارى +تذكاري +تذكارية +تذكر +تذكرة +تذكرت +تذكرتني +تذكرته +تذكرنا +تذكرني +تذكره +تذكرها +تذكري +تذكرين +تذكيرهم +تذكّر +تذكّرها +تذكَّر +تذلل +تذللك +تذليل +تذمر +تذنبوا +تذهب +تذهبي +تذهبين +تذوب +تذوق +تذوقه +تذيبه +تذيعهما +تر +ترأس +ترأست +ترأستها +ترأسه +ترأسهم +تراءى +تراب +ترابه +ترابها +ترابي +ترابية +تراتبية +تراتيله +تراث +تراثاً +تراثنا +تراثه +تراثها +تراثهم +تراثي +تراثيا +تراثياً +تراثية +تراثيين +تراثيًّا +تراجان +تراجع +تراجعاً +تراجعت +تراجعه +تراجعوا +تراجم +تراجمه +تراجيديا +تراحم +تراحمي +تراخيص +ترادفها +تراصت +تراعي +ترافق +ترافقت +ترافقتُ +ترافقنا +ترافقني +ترافيل +تراق +تراقب +تراقبان +تراقبه +تراكض +تراكضت +تراكم +تراكما +تراكمت +تراكمه +تراكمها +تراكمية +تراكميٌّ +تراكي +تراكيب +تراكيبها +ترام +ترانزستورات +تراني +تراه +تراها +تراهم +تراوحت +تراود +تربة +تربت +تربتها +تربح +تربص +تربط +تربطاننا +تربطك +تربطنا +تربطه +تربطها +تربطهم +تربنة +تربوية +تربويًا +تربى +تربي +تربية +تربيةِ +تربيت +تربيته +تربيتها +تربيتي +تربيتُ +تربّى +ترتاح +ترتاحون +ترتاد +ترتب +ترتبت +ترتبط +ترتبك +ترتج +ترتجف +ترتجفان +ترتد +ترتدي +ترتديه +ترتسم +ترتضي +ترتطم +ترتعد +ترتعش +ترتفع +ترتقي +ترتكب +ترتكز +ترتكن +ترتوي +ترتيب +ترتيبه +ترتيبها +ترتّب +ترثي +ترجع +ترجم +ترجمات +ترجمان +ترجمة +ترجمت +ترجمتم +ترجمته +ترجمتها +ترجمتهما +ترجمتي +ترجمه +ترجمها +ترجموا +ترجو +ترجيح +ترحال +ترحالي +ترحب +ترحل +ترحلين +ترحم +ترحمه +ترحيب +ترحيبا +ترحيباً +ترحيبي +ترحيبياً +ترحيبية +ترحيل +ترحيله +ترحيلها +ترخيص +ترخيصا +ترد +تردد +ترددا +ترددات +تردداتها +ترددت +ترددنا +تردده +ترددهم +تردف +تردمها +تردي +ترديد +ترديدها +تردّ +تردّد +تردّيه +ترزح +ترسانة +ترسب +ترسخ +ترسخت +ترسل +ترسلها +ترسم +ترسمت +ترسمن +ترسمه +ترسمها +ترسمي +ترسي +ترسيخ +ترسَّخت +ترسُّب +ترش +ترشح +ترشيح +ترشيحها +ترشيد +ترصد +ترصدان +ترصده +ترصدها +ترض +ترضى +ترضي +ترطب +ترطيب +ترعاها +ترعة +ترعرع +ترعرعت +ترعى +ترعينه +ترف +ترفاً +ترفة +ترفدها +ترفرف +ترفض +ترفضني +ترفع +ترفعه +ترفل +ترفيه +ترفيهى +ترفيهياً +ترفيهية +ترفًا +ترفّع +ترفّعت +ترقب +ترقبت +ترقبه +ترقبوا +ترقد +ترقص +ترقق +ترقى +ترقية +ترقيته +ترقّّصه +ترك +تركاه +تركب +تركت +تركتك +تركتني +تركته +تركتها +تركتهما +تركتُ +تركز +تركض +تركن +تركنا +تركناه +تركني +تركه +تركها +تركهما +تركوا +تركوه +تركوها +تركى +تركي +تركيا +تركيب +تركيبات +تركيباته +تركيباتها +تركيبة +تركيبتها +تركيبه +تركيبها +تركيبي +تركيبية +تركية +تركيز +تركيزا +تركيزات +تركيزاً +تركيزه +تركيزي +ترمز +ترمش +ترمي +ترميم +ترميمات +ترميمه +ترميمها +ترميمي +ترنح +ترنو +ترهل +تروج +ترودجيل +ترودوس +تروضه +تروق +ترون +تروى +تروي +ترويجها +ترويجية +ترويس +ترويها +ترى +تري +ترياق +تريبيون +تريد +تريدالإنتحار +تريدنا +تريدني +تريده +تريدها +تريدون +تريدين +تريزي +تريسامينا +تريليون +تريليونات +ترين +تريننا +تريني +تريها +تزاحم +تزاد +تزال +تزامن +تزامنت +تزاوج +تزايد +تزايداً +تزايدت +تزايدهن +تزجيتها +تزحزح +تزحف +تزخر +تزد +تزداد +تزدادين +تزدان +تزدحم +تزدرد +تزدهر +تزدهي +تزرع +تزعج +تزعجني +تزعجه +تزعجهم +تزعزع +تزعم +تزكمها +تزل +تزلج +تزلزل +تزمّتنا +تزنر +تزهر +تزهو +تزوج +تزوجت +تزوجتكِ +تزوجن +تزوجنا +تزوجها +تزود +تزودنا +تزور +تزول +تزويجه +تزويد +تزويدها +تزويدهم +تزويدي +تزوّد +تزوّدنا +تزيح +تزيد +تزيف +تزين +تزينها +تزييف +تزيين +تزيّنه +تسأل +تسألني +تسأله +تسألها +تساءل +تساءلت +تساءلوا +تساؤل +تساؤلا +تساؤلات +تساؤلاتها +تسابق +تسابقت +تسابقني +تسابقها +تسارع +تساعد +تساعدنا +تساعدني +تساعده +تساعدها +تساعدهم +تساعدوا +تساعديني +تسافر +تسافران +تساقط +تساقطت +تسامح +تسامحا +تسامي +تساندها +تساهم +تساوه +تساوى +تساوي +تساير +تسبب +تسببا +تسببت +تسببتوا +تسببه +تسببها +تسبح +تسبق +تسبقها +تسبه +تسبوا +تسبّبت +تسبِّب +تستأثر +تستأذن +تستأهل +تستأهلها +تستبطن +تستبعد +تستبيح +تستتب +تستتبع +تستثمر +تستثن +تستثنى +تستثيرها +تستجب +تستجد +تستجدي +تستجدّ +تستجمع +تستجيب +تستجير +تستحق +تستحقان +تستحقه +تستحقها +تستحكم +تستحوذ +تستحي +تستحيل +تستخدم +تستخدمه +تستخدمها +تستخدمون +تستخدمينها +تستدرك +تستدعي +تستدعيه +تستدير +تستذكر +تستر +تسترجع +تستردفَهُ +تسترها +تستريح +تستسلم +تستشعر +تستصرخ +تستضيف +تستضيفها +تستضيفهم +تستطع +تستطيب +تستطيع +تستطيعان +تستطيعون +تستطيعي +تستطيعين +تستطيل +تستعجل +تستعد +تستعدان +تستعدي +تستعرض +تستعرضه +تستعصي +تستعمل +تستعمله +تستعيد +تستعيده +تستعير +تستعين +تستفحل +تستفسر +تستفيد +تستقبل +تستقبلنا +تستقبله +تستقر +تستقطب +تستقل +تستقيل +تستقيم +تستكشف +تستكمل +تستكين +تستلزم +تستلقي +تستمتع +تستمد +تستمر +تستمرئ +تستمع +تستمعوا +تستنتج +تستند +تستنشق +تستهدف +تستهدفونه +تستهلك +تستهلكه +تستهن +تستهوي +تستهوينا +تستهويني +تستهويه +تستهويها +تستوجب +تستوحى +تستورد +تستورده +تستوطن +تستوعب +تستوعبني +تستوف +تستوقفك +تستوقفها +تستولون +تستولي +تستيقظ +تسجل +تسجلها +تسجيل +تسجيلات +تسجيلاتنا +تسجيله +تسجيلها +تسجيليا +تسجيلية +تسحب +تسحبها +تسحر +تسخر +تسخير +تسخين +تسخينها +تسد +تسديد +تسر +تسرب +تسربات +تسرباً +تسربت +تسربها +تسرح +تسرحي +تسرع +تسرق +تسري +تسريحة +تسريحه +تسريع +تسرّب +تسرّبات +تسرّبت +تسرَّب +تسطع +تسع +تسعة +تسعمائة +تسعني +تسعون +تسعى +تسعين +تسعينيات +تسـاعدني +تسقط +تسكب +تسكعية +تسكن +تسكنني +تسكنه +تسكنها +تسكين +تسلح +تسلحوا +تسلخات +تسلسلها +تسلط +تسلق +تسلك +تسلكها +تسلل +تسللت +تسلم +تسلمت +تسلمته +تسلمنا +تسلمني +تسلية +تسليت +تسليح +تسليحه +تسليحها +تسليط +تسليطها +تسليم +تسليمه +تسليمها +تسلّط +تسلّم +تسمح +تسمحان +تسمحي +تسمحين +تسمرت +تسمع +تسمعها +تسمعوا +تسمك +تسمم +تسمى +تسمية +تسميته +تسميتها +تسميح +تسميد +تسميعه +تسميم +تسمينها +تسميه +تسميها +تسمّم +تسمّى +تسمّيه +تسنده +تسنم +تسنى +تسهر +تسهرون +تسهل +تسهم +تسهيل +تسهيلا +تسهيلات +تسهيلاته +تسهيلاً +تسو +تسود +تسودان +تسوق +تسول +تسولف +تسونامي +تسوية +تسويد +تسويق +تسويقنا +تسويقها +تسويقي +تسويقية +تسي +تسيء +تسيد +تسير +تسيطر +تسيل +تسيىء +تسيير +تسييس +تسيّر +تشأ +تشاء +تشاءمت +تشابك +تشابكت +تشابه +تشابها +تشابهًا +تشاد +تشارتر +تشارف +تشارك +تشاركا +تشاركنا +تشاركه +تشاركها +تشاركيني +تشارلز +تشارلس +تشارلي +تشاكر +تشامب +تشاندرا +تشاهد +تشاهده +تشاهدوه +تشايلد +تشبثي +تشبع +تشبعوا +تشبه +تشبهان +تشبهني +تشبهه +تشبهها +تشبيهها +تشتت +تشتد +تشترط +تشترك +تشتري +تشتعل +تشتم +تشتمل +تشتملان +تشتهر +تشتهي +تشتيت +تشتيتها +تشجع +تشجعت +تشجعنا +تشجعه +تشجيع +تشجيعاً +تشجيعهما +تشجيعية +تشجيعًا +تشجّع +تشجِّع +تشخص +تشخيص +تشخيصات +تشخيصه +تشخيصية +تشد +تشدد +تشدني +تشده +تشدها +تشدهم +تشديد +تشدّ +تشذ +تشذي +تشذيب +تشذيبها +تشرب +تشرح +تشرد +تشردَ +تشرشل +تشرف +تشرنوبيل +تشريد +تشريع +تشريعات +تشريعاته +تشريعًا +تشريف +تشرين +تشرّد +تشع +تشعبا +تشعباً +تشعبت +تشعر +تشعره +تشفر +تشفع +تشفى +تشفي +تشق +تشقق +تشققت +تشقى +تشقّ +تشك +تشكل +تشكلت +تشكو +تشكيك +تشكيل +تشكيلات +تشكيلاً +تشكيلة +تشكيله +تشكيلها +تشكيلي +تشكيلياً +تشكيلية +تشكيليون +تشكيليين +تشكّل +تشكّلت +تشل +تشم +تشمل +تشمله +تشميع +تشمين +تشمُّ +تشن +تشنج +تشنجات +تشنها +تشهد +تشهدان +تشهده +تشهدها +تشهر +تشوب +تشوبها +تشوبي +تشوشا +تشوفه +تشوه +تشوها +تشوهات +تشوهت +تشويش +تشويق +تشويه +تشويهه +تشوّه +تشوّهات +تشىيد +تشي +تشيخ +تشيد +تشير +تشيرنوبل +تشيرنوشيفسكي +تشيع +تشيعها +تشيكوف +تشيكيا +تشيلي +تشين +تشيو +تشييد +تشييع +تصاب +تصاحب +تصاحبه +تصاحبها +تصادر +تصادف +تصادفت +تصادفنا +تصادفه +تصادم +تصادمات +تصارح +تصارع +تصارعا +تصاريح +تصاعد +تصاعدت +تصاعدي +تصالح +تصالحنا +تصب +تصبح +تصبحون +تصبحي +تصبها +تصح +تصحب +تصحبه +تصحيح +تصحيحها +تصحُ +تصحّر +تصحَّرت +تصخب +تصدأ +تصدت +تصدح +تصدحُ +تصدر +تصدران +تصدرت +تصدرته +تصدره +تصدرها +تصدعات +تصدق +تصدقوني +تصدم +تصدوا +تصدى +تصدير +تصديرها +تصديرية +تصديق +تصدّر +تصدّق +تصدّقهم +تصر +تصرخ +تصرف +تصرفات +تصرفاتنا +تصرفاته +تصرفاً +تصرفهم +تصريح +تصريحا +تصريحات +تصريحاً +تصريحه +تصريف +تصريفه +تصرّ +تصرّفاتها +تصطاده +تصطادها +تصطدم +تصطرع +تصطف +تصطفون +تصعب +تصعد +تصعدان +تصعقهم +تصعيد +تصف +تصفح +تصفحنا +تصفق +تصفه +تصفون +تصفي +تصفيات +تصفية +تصقل +تصل +تصلان +تصلب +تصلح +تصلنا +تصله +تصلي +تصليح +تصمت +تصمد +تصميم +تصميمه +تصميمها +تصميمي +تصميمين +تصميمًا +تصنع +تصنعه +تصنعها +تصنعي +تصنف +تصنيع +تصنيعا +تصنيعه +تصنيعها +تصنيعي +تصنيعية +تصنيف +تصنيفا +تصنيفات +تصنيفها +تصنيفهم +تصنّفين +تصور +تصورا +تصورات +تصوراتنا +تصوراته +تصوراً +تصورته +تصورنا +تصوره +تصورهم +تصوروا +تصوري +تصورًا +تصوفهم +تصوفية +تصوير +تصويرنا +تصويره +تصويرها +تصويري +تصويرية +تصوّر +تصوّرت +تصوّرنا +تصوّره +تصوّروا +تصوَّرته +تصيب +تصيبه +تصيبها +تصيبهم +تصيح +تصير +تصيرين +تصيّد +تضاء +تضاءلت +تضاؤل +تضاجع +تضاربت +تضاربوا +تضاريس +تضاريسه +تضاعف +تضاعفت +تضاف +تضافر +تضافرت +تضامن +تضامنا +تضامنه +تضامنًا +تضاهى +تضاهي +تضاهيها +تضايق +تضايقت +تضبط +تضبطها +تضجر +تضحك +تضحكوا +تضحكين +تضحي +تضحيات +تضحية +تضخم +تضخمت +تضخمها +تضخّم +تضخّه +تضر +تضرب +تضررًا +تضرع +تضره +تضرها +تضرّرت +تضطر +تضطرم +تضطلع +تضع +تضعضعه +تضعنا +تضعه +تضعها +تضعوا +تضفي +تضليل +تضم +تضمن +تضمنا +تضمنت +تضمنتها +تضمنتهم +تضمنه +تضمنها +تضمه +تضمها +تضمهم +تضميد +تضمين +تضميني +تضوى +تضيء +تضيئها +تضيع +تضيف +تضيق +تضيقها +تضييق +تضييقا +تضُّمنا +تطأ +تطابق +تطابقاً +تطارد +تطاردهم +تطاق +تطال +تطالب +تطالع +تطالعنا +تطالهم +تطاول +تطايرت +تطايره +تطبع +تطبعها +تطبق +تطبقها +تطبيع +تطبيق +تطبيقا +تطبيقات +تطبيقاته +تطبيقاتها +تطبيقه +تطبيقها +تطبيقي +تطبيقية +تطرأ +تطرب +تطرح +تطرحه +تطرحها +تطرز +تطرف +تطرق +تطرقوا +تطريبية +تطريز +تطعمه +تطعمها +تطعيم +تطعيمها +تطفئوه +تطفو +تطل +تطلب +تطلبين +تطلع +تطلعات +تطلعاتكم +تطلعاته +تطلعت +تطلعوا +تطلق +تطلقه +تطلقها +تطلّ +تطلّبت +تطلّون +تطمئن +تطمح +تطمسه +تطن +تطهرت +تطهير +تطور +تطورا +تطورات +تطوراً +تطورت +تطوره +تطورها +تطورية +تطورًا +تطوعي +تطوعًا +تطوف +تطوفان +تطوقها +تطول +تطوله +تطوى +تطوىر +تطوي +تطوير +تطويرا +تطويراً +تطويرها +تطويرى +تطويرية +تطويع +تطويعه +تطوّر +تطوّرالحمّى +تطوّرت +تطوّقها +تطير +تطيران +تطيش +تطيق +تطيقه +تطيقها +تطيل +تظاهر +تظاهروا +تظل +تظللهم +تظليل +تظلّها +تظن +تظنني +تظنين +تظنِّين +تظهر +تظهران +تعابير +تعابيره +تعاتبني +تعاجله +تعاد +تعادل +تعادلها +تعارض +تعارضا +تعارضاتها +تعارضت +تعارضنها +تعارف +تعاريف +تعاسة +تعاسيف +تعاطاه +تعاطف +تعاطفاً +تعاطفها +تعاطي +تعاظم +تعاظماً +تعاف +تعافه +تعاقب +تعاقبت +تعاقبني +تعاقد +تعاقدات +تعاقدي +تعاقدية +تعال +تعالا +تعالت +تعالج +تعالوا +تعالى +تعالي +تعاليم +تعاليمه +تعالَيْ +تعامل +تعاملاتها +تعاملت +تعاملنا +تعاملني +تعامله +تعاملها +تعاملي +تعاندها +تعاني +تعانين +تعانيه +تعانيها +تعاود +تعاوده +تعاون +تعاونوا +تعاونيات +تعاونية +تعايش +تعب +تعبأ +تعبئة +تعبئته +تعبئتها +تعبئين +تعبا +تعبان +تعبت +تعبتا +تعبد +تعبر +تعبق +تعبك +تعبكَ +تعبنا +تعبي +تعبير +تعبيرا +تعبيرات +تعبيراتها +تعبيراً +تعبيره +تعبيريا +تعبيرية +تعبّر +تعتبر +تعتبران +تعتبره +تعتبرها +تعتبرونها +تعتبرين +تعتبريني +تعتدي +تعترض +تعترف +تعتري +تعتريهم +تعتز +تعتزم +تعتزّ +تعتقد +تعتقدون +تعتقدين +تعتلي +تعتليه +تعتمد +تعتمده +تعتملان +تعتنق +تعتني +تعثر +تعثّر +تعج +تعجب +تعجبت +تعجبنا +تعجبه +تعجز +تعجن +تعجيزية +تعجّ +تعد +تعداد +تعداده +تعدادها +تعدادهم +تعدت +تعدتهما +تعدد +تعددت +تعددها +تعددية +تعدكم +تعدل +تعدها +تعدو +تعدى +تعدي +تعديد +تعديل +تعديلات +تعديله +تعديلها +تعديني +تعدّ +تعدّت +تعدّدها +تعدّك +تعذبوا +تعذر +تعذرني +تعذيب +تعذيبهم +تعر +تعرب +تعرج +تعرض +تعرضا +تعرضاً +تعرضت +تعرضنا +تعرضه +تعرضها +تعرضهم +تعرضوا +تعرف +تعرفت +تعرفنا +تعرفني +تعرفه +تعرفها +تعرفهم +تعرفون +تعرفين +تعرفينها +تعرقل +تعريب +تعرية +تعريتها +تعريض +تعريضها +تعريف +تعريفا +تعريفات +تعريفاته +تعريفاً +تعريفنا +تعريفه +تعريفها +تعريفهن +تعريفياً +تعريفية +تعرّض +تعرّضاً +تعرّضت +تعرّضه +تعرّف +تعرَّضت +تعرَّف +تعرِّض +تعرِّف +تعزز +تعززت +تعزف +تعزله +تعزية +تعزير +تعزيز +تعزيزا +تعزيزاً +تعسر +تعسروا +تعسفي +تعش +تعشش +تعشعش +تعشق +تعشيق +تعصب +تعصبه +تعصبي +تعصر +تعصف +تعصّب +تعضد +تعط +تعطش +تعطشهم +تعطل +تعطلت +تعطه +تعطوننا +تعطى +تعطي +تعطيك +تعطيل +تعطيني +تعطيه +تعطيها +تعطّش +تعظم +تعظيم +تعــطيك +تعفر +تعفن +تعقب +تعقبه +تعقبها +تعقد +تعقدت +تعقده +تعقدها +تعقل +تعقيب +تعقيباً +تعقيد +تعقيدا +تعقيدات +تعقيداً +تعقيده +تعقيدًا +تعقّب +تعكس +تعكسان +تعكسه +تعكسها +تعكسين +تعكف +تعلب +تعلق +تعلقاً +تعلقت +تعلقه +تعلقها +تعلقونها +تعلقي +تعلل +تعلم +تعلماً +تعلمت +تعلمتموه +تعلمته +تعلمتها +تعلمتُ +تعلمنا +تعلمناه +تعلمه +تعلمها +تعلموا +تعلمون +تعلمين +تعلمينه +تعلن +تعلو +تعلوها +تعلي +تعليب +تعليبها +تعليق +تعليقات +تعليقاته +تعليقاتها +تعليقك +تعليقه +تعليقها +تعليم +تعليما +تعليمات +تعليماتها +تعليماً +تعليمنا +تعليمه +تعليمها +تعليمهم +تعليمهن +تعليمي +تعليميا +تعليمياً +تعليمية +تعليميتها +تعليمًا +تعلّق +تعلّمت +تعلّمنا +تعلّمه +تعلّمي +تعم +تعمد +تعمدت +تعمر +تعمق +تعمقاً +تعمقت +تعمل +تعملان +تعملق +تعمها +تعميد +تعميده +تعمير +تعميق +تعميم +تعمّقت +تعمُّ +تعن +تعنت +تعنى +تعني +تعنين +تعنيه +تعنِّف +تعهد +تعهدات +تعهدت +تعهدته +تعهدكم +تعهّدت +تعهّدني +تعود +تعودان +تعودت +تعودنا +تعودوا +تعودين +تعوزنا +تعوق +تعوقني +تعوقه +تعول +تعوم +تعويد +تعويذة +تعويض +تعويضات +تعويضاً +تعويضها +تعويضيا +تعويضية +تعويم +تعوّذ +تعوَّدته +تعي +تعيد +تعيدك +تعيدنا +تعيش +تعيشه +تعيشها +تعيشون +تعيشي +تعيشين +تعيق +تعين +تعينت +تعيننا +تعينني +تعينه +تعيين +تعيينك +تعيينه +تعييني +تعُرِّضُوا +تعّلمناه +تـــلوث +تــقــول +تــكون +تـقـانـة +تـم +تف +تفئيرت +تفاءلت +تفاؤل +تفاجأ +تفاح +تفاحتين +تفاخر +تفادي +تفاديا +تفارق +تفارقان +تفارقني +تفارقه +تفاسير +تفاسيرهم +تفاصيل +تفاصيله +تفاصيلها +تفاعل +تفاعلات +تفاعلاتها +تفاعلاً +تفاعله +تفاعلها +تفاعلهم +تفاقم +تفاقمت +تفاقمها +تفانت +تفاهم +تفاوت +تفاوتاً +تفاوتت +تفاوض +تفتت +تفتتح +تفتح +تفتحت +تفتحتا +تفتحه +تفتر +تفترش +تفترض +تفترّ +تفتش +تفتعل +تفتقد +تفتقده +تفتقر +تفتك +تفتنها +تفتيت +تفتيش +تفتيشية +تفتُرْ +تفجر +تفجرت +تفجير +تفجيرها +تفجّر +تفحص +تفحصت +تفخر +تفخيم +تفرح +تفرحوا +تفرد +تفرده +تفرز +تفرزها +تفرش +تفرض +تفرضه +تفرضها +تفرعات +تفرق +تفرقة +تفرقت +تفريط +تفريطها +تفريق +تفرّده +تفرّقت +تفرُّدها +تفسخ +تفسد +تفسر +تفسرون +تفسرين +تفسير +تفسيرا +تفسيرات +تفسيراتهم +تفسيراً +تفسيره +تفسيرها +تفسّر +تفشت +تفشل +تفصح +تفصل +تفصيل +تفصيلا +تفصيلات +تفصيلاً +تفصيلها +تفصيلي +تفصيليا +تفصيلية +تفض +تفضح +تفضحنا +تفضحها +تفضل +تفضلت +تفضلتم +تفضلها +تفضي +تفضيل +تفضيلها +تفعل +تفعلا +تفعله +تفعلوا +تفعلي +تفعيل +تفقد +تفقده +تفقدها +تفقس +تفكر +تفكرين +تفكير +تفكيرا +تفكيرك +تفكيره +تفكيرهم +تفكيري +تفكيك +تفكيكه +تفكّر +تفلت +تفلتها +تفلح +تفنى +تفنيدا +تفنيده +تفنيدها +تفهم +تفهمت +تفهمه +تفهمها +تفهموني +تفهيم +تفهّم +تفهّمت +تفوت +تفوتك +تفوتها +تفوح +تفوق +تفوقا +تفوقاً +تفوقه +تفوقهم +تفوقًا +تفوهت +تفويض +تفي +تفيد +تفيدنا +تفيده +تفيض +تقابل +تقابلنا +تقابله +تقابلها +تقادم +تقاذفوا +تقارب +تقاربات +تقارن +تقارنون +تقارير +تقاريره +تقاس +تقاسمتها +تقاسمنا +تقاسمه +تقاضى +تقاضيه +تقاطع +تقاطعات +تقاطعه +تقاطعها +تقاطعوني +تقاعد +تقاعدت +تقاعده +تقاعدها +تقاعدهم +تقال +تقاليد +تقاليدها +تقالّوا +تقام +تقانة +تقانيات +تقاوم +تقاومنا +تقاومه +تقبض +تقبع +تقبل +تقبلتهم +تقبله +تقبلها +تقبيل +تقبّل +تقتحم +تقتحمه +تقترب +تقترح +تقترن +تقتسره +تقتسم +تقتصر +تقتضى +تقتضي +تقتل +تقتلع +تقتله +تقتلهم +تقتلين +تقتلينهم +تقتنه +تقتير +تقدح +تقدر +تقدرون +تقدس +تقدم +تقدما +تقدماً +تقدمت +تقدمتا +تقدمنا +تقدمه +تقدمها +تقدموا +تقدمون +تقدمي +تقدمية +تقدمًا +تقدير +تقديرا +تقديرات +تقديراتهم +تقديراً +تقديركم +تقديره +تقديرها +تقديري +تقديرية +تقديرًا +تقديس +تقديم +تقديماً +تقديمه +تقديمها +تقديمهما +تقدّر +تقدّرين +تقدّم +تقدّماً +تقدّمه +تقدّمياً +تقدَّم +تقدُّم +تقدِّم +تقذف +تقذفه +تقذفها +تقر +تقرأ +تقرأون +تقرؤه +تقرئيها +تقرب +تقربني +تقربوا +تقرحات +تقرر +تقرع +تقرون +تقريب +تقريبا +تقريباً +تقريبهما +تقريبية +تقريبًا +تقرير +تقريرا +تقريراً +تقريره +تقريرها +تقريرهم +تقريعها +تقرِّب +تقزز +تقسم +تقسو +تقسيم +تقسيما +تقسيمات +تقسيمها +تقشر +تقشرت +تقشير +تقصد +تقصدين +تقصر +تقصف +تقصي +تقصير +تقصّى +تقض +تقضم +تقضى +تقضي +تقطر +تقطع +تقطفون +تقطن +تقطيع +تقطّع +تقطِّرُ +تقع +تقعان +تقـانة +تقف +تقفز +تقل +تقلان +تقلب +تقلبات +تقلباته +تقلباتها +تقلبتها +تقلبني +تقلد +تقلدت +تقلدنا +تقلدها +تقلدوا +تقلص +تقلصت +تقلع +تقلق +تقلل +تقله +تقليد +تقليدا +تقليده +تقليدها +تقليدهم +تقليدى +تقليدي +تقليديا +تقليدياً +تقليدية +تقليص +تقليل +تقلّب +تقلّص +تقم +تقمير +تقميش +تقنع +تقنعنا +تقنعيه +تقنــــيات +تقنىين +تقني +تقنيا +تقنيات +تقنياتها +تقنية +تقنيتها +تقنين +تقنيًا +تقهر +تقهقر +تقواها +تقود +تقودنا +تقوده +تقودها +تقوست +تقول +تقوله +تقولون +تقولي +تقولين +تقوم +تقومون +تقوى +تقوية +تقويتها +تقويض +تقويم +تقويمك +تقويمها +تقويمية +تقىيم +تقىيمكم +تقي +تقيأ +تقيؤ +تقياً +تقية +تقيح +تقيداً +تقيده +تقيدي +تقيس +تقيم +تقيما +تقيمه +تقيمها +تقيموا +تقيمين +تقييد +تقييده +تقييم +تقييمه +تقييمي +تقييمية +تقييهم +تك +تكاتف +تكاثر +تكاثرها +تكاد +تكادان +تكاسلا +تكافأون +تكافؤ +تكافح +تكافلي +تكالبت +تكالبوا +تكاليف +تكاليفها +تكامل +تكاملا +تكبح +تكبدهم +تكبدوا +تكبر +تكبران +تكبره +تكبل +تكبلني +تكبير +تكبيره +تكتب +تكتبته +تكتبه +تكتبها +تكتبين +تكتبينه +تكترث +تكتسب +تكتسبها +تكتسح +تكتشف +تكتشفون +تكتظ +تكتف +تكتفي +تكتل +تكتلات +تكتمل +تكتنفه +تكتيكية +تكثر +تكثيف +تكثيفا +تكد +تكذب +تكذبها +تكر +تكرار +تكرارالتجربة +تكراراً +تكرارها +تكرر +تكررت +تكرس +تكرم +تكره +تكرهوا +تكرير +تكريس +تكريسا +تكريساً +تكريم +تكريمها +تكريمي +تكساس +تكسب +تكسبه +تكسبها +تكسر +تكسرت +تكسرها +تكسو +تكسوها +تكسية +تكسير +تكشف +تكشفت +تكشفه +تكشيرة +تكف +تكفل +تكفهر +تكفون +تكفي +تكفينا +تكفيني +تكفِ +تكفّ +تكل +تكلف +تكلفة +تكلفته +تكلفتها +تكلفتي +تكلل +تكللت +تكلم +تكلموا +تكليف +تكمل +تكملة +تكمن +تكن +تكنولوجي +تكنولوجيا +تكنولوجية +تكنولوجيتنا +تكنولوجيز +تكهف +تكون +تكونا +تكونت +تكونتا +تكونها +تكونوا +تكوني +تكوين +تكوينات +تكويناً +تكوينه +تكوينها +تكوينهما +تكويني +تكوّن +تكوّنت +تكىيف +تكيف +تكييف +تل +تلا +تلاءمت +تلائم +تلاحظ +تلاحظه +تلاحظون +تلاحق +تلاحقت +تلاحقني +تلاحقه +تلاحقها +تلاحم +تلاحمه +تلازم +تلازمت +تلاشت +تلاشى +تلاشي +تلاصق +تلاطم +تلاعب +تلاعبها +تلافي +تلافيف +تلاقح +تلاقي +تلال +تلامذة +تلامذته +تلامس +تلامسان +تلاميذ +تلاميذه +تلاميذها +تلاميذهم +تلاميذي +تلاه +تلاها +تلاوة +تلاوين +تلبث +تلبد +تلبري +تلبس +تلبسه +تلبى +تلبي +تلبية +تلبيتها +تلة +تلت +تلتئم +تلتحق +تلتزم +تلتصق +تلتف +تلتفت +تلتقط +تلتقطه +تلتقطها +تلتقطي +تلتقي +تلتقيان +تلتمع +تلته +تلتها +تلتهب +تلتهم +تلتهمها +تلجأ +تلجأون +تلح +تلحظ +تلحظها +تلحق +تلحقنا +تلحن +تلحين +تلحينه +تلحّ +تلخص +تلخصت +تلخيص +تلخيصا +تلخيصها +تلد +تلدها +تلذ +تلزم +تلطف +تلطيف +تلعب +تلعبان +تلعبه +تلعثمت +تلعن +تلف +تلفازي +تلفت +تلفتت +تلفتوا +تلفزيون +تلفزيونا +تلفزيونات +تلفزيونياً +تلفزيونية +تلفلف +تلفها +تلفونيا +تلفُّ +تلق +تلقاء +تلقائي +تلقائيا +تلقائياً +تلقائية +تلقائيين +تلقائيًا +تلقاه +تلقاها +تلقت +تلقح +تلقفته +تلقفه +تلقفها +تلقوا +تلقى +تلقي +تلقيت +تلقيته +تلقيتها +تلقيح +تلقين +تلقينا +تلقيناه +تلقيه +تلقيها +تلقَّى +تلك +تلكم +تلم +تلمح +تلمحني +تلمحه +تلمذته +تلمس +تلمسه +تلمسيها +تلمع +تلمعان +تلمني +تلمه +تلميذ +تلميذا +تلميذاً +تلميذة +تلميذك +تلميذه +تلمَّست +تلن +تلهب +تلهبه +تلهو +تلهي +تلو +تلوث +تلوثا +تلوح +تلوذ +تلومونني +تلون +تلونت +تلونها +تلونين +تلويث +تلويح +تلوين +تلوينا +تلوّث +تليف +تليفزيون +تليفزيوني +تليفزيونية +تليفونا +تليفونية +تليق +تليميريز +تلين +تليها +تليين +تم +تماثل +تماثلا +تماثلها +تماثيل +تمادي +تمارس +تمارسه +تمارسها +تمارين +تمازج +تماس +تماسك +تماسكا +تماسكاً +تماسكت +تماسكنا +تماسكها +تماسّ +تمام +تماما +تماماً +تمامه +تمامًا +تمانع +تمايز +تمايزات +تمبوكتو +تمت +تمتات +تمتاز +تمتد +تمتدح +تمتزج +تمتص +تمتصه +تمتصّ +تمتطيها +تمتع +تمتعت +تمتـص +تمتلئ +تمتلك +تمتلكه +تمتم +تمتمة +تمتهن +تمتينا +تمتّ +تمثال +تمثالا +تمثالاً +تمثاله +تمثل +تمثلت +تمثلن +تمثله +تمثلها +تمثيل +تمثيلا +تمثيله +تمثيلياته +تمثيلية +تمثّل +تمثّلت +تمجيد +تمحل +تمحو +تمحورت +تمحى +تمحيص +تمخر +تمخض +تمخضت +تمد +تمدح +تمدد +تمدني +تمديد +تمدّنا +تمر +تمراً +تمرد +تمردت +تمردها +تمرر +تمررها +تمركزت +تمركزوا +تمركشت +تمرّ +تمرُّ +تمزج +تمزق +تمزقها +تمس +تمسح +تمسحت +تمسك +تمسكا +تمسكه +تمسكها +تمشط +تمشون +تمشي +تمشياً +تمصير +تمض +تمضي +تمضية +تمضِ +تمطر +تمطركثيرا +تمعن +تمكن +تمكنا +تمكنت +تمكننا +تمكنه +تمكنها +تمكنهم +تمكنوا +تمكين +تمكينها +تمكّن +تمكّنه +تملأ +تملأه +تملؤها +تملك +تملكتني +تملكني +تملكه +تملكها +تملكون +تمليكه +تمليه +تمليها +تملّ +تملّك +تمم +تمناها +تمنت +تمنح +تمنحك +تمنحنا +تمنحني +تمنحه +تمنحها +تمنع +تمنعن +تمنعنا +تمنعه +تمنعها +تمنوه +تمنياته +تمنيت +تمنيته +تمنيتُ +تمنيني +تمهد +تمهلنا +تمهيد +تمهيدا +تمهيداً +تمهيدية +تمهيدًا +تموت +تموتوا +تموج +تموجات +تمور +تموز +تمول +تموله +تمويل +تمويلاً +تمويلها +تمويلي +تمويليا +تموين +تمويناً +تموينية +تمويه +تموّل +تميز +تميزا +تميزت +تميزه +تميزها +تميزهن +تميزًا +تميط +تميل +تميم +تميمة +تمييز +تمييزاً +تمييزها +تمييزًا +تميّز +تميّزبين +تميّزت +تميّزنا +تميّزه +تميِّز +تمُتُّ +تمُدُّ +تمّ +تمّام +تمّت +تمّيزت +تمَّ +تمَّحي +تنأى +تنابذنا +تناثر +تناثرت +تناجي +تناحر +تنادت +تنادى +تنادي +تناديك +تناديه +تناذر +تنازع +تنازل +تنازلات +تنازلت +تنازلها +تناسب +تناسباً +تناسبت +تناسبني +تناسق +تناسقه +تناسل +تناسلي +تناسلية +تناسي +تناسيتُ +تناسيه +تناضل +تناظرا +تنافر +تنافس +تنافسى +تنافسية +تناقش +تناقشوا +تناقص +تناقصت +تناقض +تناقضا +تناقضات +تناقضاً +تناقضه +تناقل +تناقلته +تناقلتها +تناقلها +تنال +تناله +تنام +تنامت +تنامى +تنامي +تناهت +تناهض +تناهي +تناول +تناولت +تناولته +تناولتها +تناوله +تناولها +تناولهم +تناولهما +تناولوا +تناولوه +تناولوها +تنبأ +تنبؤات +تنبئ +تنبئك +تنبت +تنبثق +تنبح +تنبذ +تنبس +تنبض +تنبع +تنبعث +تنبه +تنبهت +تنبهر +تنبهوا +تنبيه +تنبيهها +تنبّأتُ +تنتاب +تنتابه +تنتبه +تنتثر +تنتج +تنتجه +تنتجها +تنتزع +تنتسب +تنتشر +تنتشل +تنتصب +تنتطح +تنتظر +تنتظرك +تنتظرنا +تنتظرني +تنتظره +تنتظرها +تنتظري +تنتظم +تنتفي +تنتقد +تنتقل +تنتقم +تنتكس +تنتمى +تنتمي +تنته +تنتهجها +تنتهك +تنتهى +تنتهي +تنثال +تنثر +تنثني +تنجانيقا +تنجب +تنجح +تنجرف +تنجز +تنجزه +تنجلي +تنجم +تنجو +تنجي +تنحاز +تنحجب +تنحدر +تنحرف +تنحسر +تنحصر +تنحل +تنحني +تنحى +تنحية +تنحيف +تنخرط +تنخرف +تنخفض +تنخلع +تند +تندب +تندبه +تندثر +تندد +تندرج +تندفع +تندقم +تندلع +تندمج +تندمل +تندهش +تنديدها +تنذر +تنزانيا +تنزح +تنزع +تنزعان +تنزل +تنزيله +تنزّل +تنس +تنساب +تنسب +تنسج +تنسحب +تنسخ +تنسدل +تنسلخ +تنسها +تنسوا +تنسى +تنسيق +تنسيقها +تنسين +تنسَ +تنشأ +تنشئ +تنشئة +تنشئتها +تنشب +تنشدها +تنشر +تنشره +تنشرها +تنشط +تنشع +تنشق +تنشيط +تنشيطه +تنشيطها +تنص +تنصب +تنصت +تنصتون +تنصرف +تنصهر +تنصيرية +تنضج +تنضح +تنضم +تنضير +تنط +تنطبق +تنطفئ +تنطق +تنطقان +تنطلق +تنطوي +تنظر +تنظران +تنظرني +تنظرون +تنظري +تنظرين +تنظم +تنظمها +تنظير +تنظيراتهم +تنظيراً +تنظيف +تنظيفها +تنظيم +تنظيمات +تنظيماتها +تنظيماً +تنظيمه +تنظيمها +تنظيميا +تنعدم +تنعطف +تنعكس +تنعم +تنعيه +تنـهدم +تنفتح +تنفجر +تنفد +تنفذ +تنفرجان +تنفرد +تنفس +تنفسي +تنفسية +تنفصل +تنفصم +تنفض +تنفضه +تنفع +تنفـيذها +تنفق +تنفلت +تنفلق +تنفي +تنفيذ +تنفيذاً +تنفيذه +تنفيذها +تنفيذهها +تنفيذية +تنفيذيين +تنقب +تنقدهم +تنقر +تنقرض +تنقسم +تنقص +تنقصنا +تنقصه +تنقصها +تنقصي +تنقض +تنقطع +تنقل +تنقلات +تنقلاتنا +تنقلاتي +تنقلب +تنقلت +تنقلك +تنقلنا +تنقله +تنقلها +تنقلهم +تنقيب +تنقية +تنكتب +تنكر +تنكرهم +تنكروا +تنكس +تنكسية +تنكشف +تنكص +تنكمش +تنل +تنلها +تنم +تنمو +تنموي +تنموية +تنمي +تنمية +تنميته +تنميتها +تنميط +تنميق +تنه +تنهار +تنهال +تنهد +تنهدت +تنهش +تنهشه +تنهض +تنهل +تنهمر +تنهمران +تنهه +تنهي +تنور +تنورة +تنورتان +تنورته +تنوس +تنوع +تنوعاً +تنوعت +تنوعه +تنوعًا +تنوي +تنوير +تنويع +تنويعات +تنويم +تنوّع +تنوّعا +تنوّعاً +تنوّعت +تنير +تنّور +تنُّوب +ته +تها +تهاتفنا +تهاجرالاناث +تهاجم +تهاجمنا +تهاجمه +تهاجمها +تهافت +تهافتت +تهامة +تهاوت +تهاويل +تهب +تهبط +تهبّ +تهتز +تهتف +تهتم +تهتموا +تهتمين +تهجم +تهجير +تهجيرك +تهدأ +تهدئة +تهدد +تهددهم +تهدر +تهدرها +تهدف +تهدم +تهدمت +تهدمه +تهدهد +تهديد +تهديدا +تهديدات +تهديداً +تهديدًا +تهديها +تهذي +تهذيب +تهذيباً +تهذّب +تهرب +تهرع +تهريب +تهريباً +تهريبها +تهز +تهزج +تهزمها +تهزه +تهزهما +تهزي +تهزّ +تهطل +تهفو +تهفوا +تهكما +تهل +تهلك +تهلكها +تهم +تهمة +تهمتنا +تهمد +تهمس +تهمل +تهملين +تهمنا +تهمني +تهمه +تهمها +تهميش +تهمينا +تهمّ +تهمُّما +تهن +تهنئة +تهوري +تهوى +تهوي +تهوية +تهويد +تهويمات +تهيء +تهيأ +تهيأت +تهيئ +تهيئة +تهيئته +تهيج +تهيجاً +تهيل +تهيمن +تهيّبت +توأم +توائم +توابعه +توابل +توابيت +تواتر +تواتره +تواترها +تواجد +تواجدت +تواجده +تواجدهم +تواجه +تواجهك +تواجهنا +تواجهني +تواجهه +تواجهها +تواجههم +توادهم +توارث +توارثته +توارى +تواريخ +توازن +توازنات +توازنه +توازنها +توازني +توازي +تواصل +تواصله +تواضع +تواضعاً +تواضعت +تواطؤ +توافد +توافدت +توافر +توافرت +توافرها +توافق +توافقه +توافقها +توافقين +توافقينني +توافه +تواقات +تواقاً +تواكب +تواكل +توالت +توالد +توالده +توالوا +توالى +توالي +تواً +توب +توبته +توبفر +توت +توتر +توتراً +توتّرا +توثقت +توثيق +توج +توجب +توجت +توجتها +توجد +توجده +توجس +توجساتنا +توجست +توجه +توجها +توجهات +توجهاتها +توجهاتي +توجهت +توجهنا +توجهه +توجهها +توجههم +توجهي +توجهًا +توجهّ +توجو +توجيه +توجيها +توجيهات +توجيهاتكم +توجيهاً +توجيهه +توجيهها +توجّه +توجَّه +توجُّه +توجِّه +توحدت +توحش +توحي +توحيد +توحيده +توحّدت +توخته +توخي +تود +تودد +تودي +تورا +توراتية +تورتة +تورد +تورط +تورق +توركانا +تورم +تورنتو +تورنر +توريد +توريطه +توريقا +تورينجينسيس +تورّث +توزر +توزع +توزعت +توزعتها +توزيع +توزيعا +توزيعه +توزيعها +توزيعًا +توسد +توسط +توسع +توسعاً +توسعة +توسعت +توسعي +توسعية +توسكاي +توسل +توسلت +توسوس +توسيع +توسيعها +توش +توشك +توشيبا +توصف +توصل +توصلت +توصلتم +توصلتُ +توصلنا +توصله +توصلوا +توصى +توصيات +توصياتهم +توصية +توصيف +توصيفات +توصيفها +توصيل +توصيلات +توصّل +توصَّل +توضح +توضحه +توضع +توضعه +توضيح +توضيحاتنا +توطنوا +توطيد +توطين +توظيف +توظيفها +توعد +توعدون +توعك +توعية +توفاه +توفاهما +توفر +توفرت +توفره +توفرها +توفى +توفي +توفيت +توفير +توفيركل +توفيرها +توفيق +توفيقيّ +توفّر +توفَّرت +توفُّر +توفِّر +توقا +توقظ +توقظنا +توقظي +توقع +توقعات +توقعاتنا +توقعاته +توقعاه +توقعنا +توقعه +توقف +توقفت +توقفتْ +توقفنا +توقفها +توقفوا +توقفي +توقه +توقيت +توقيتها +توقيع +توقيعاتهم +توقيعي +توقًا +توكأت +توكللي +توكيد +تولاها +تولت +تولد +تولده +تولستوي +تولوز +تولول +تولى +تولي +توليا +توليت +توليد +توليدو +توليفاً +توليفة +توليه +توليها +تولّت +تولّد +تولِّد +توم +تومئ +توماس +توماهوك +تومرت +تونا +تونس +تونسية +تونكا +توني +توهب +توهج +توهم +توهما +توهماتسو +توهنه +توي +توينبي +تويني +توّاقاً +توّجت +تي +تيأس +تيأسي +تيار +تيارا +تيارات +تياراتها +تياراً +تياره +تيارها +تيارين +تيارًا +تيتانيك +تيتم +تيتو +تيجا +تيجان +تيراثوبياس +تيران +تيراي +تيرثينايل +تيرجي +تيرنر +تيزيني +تيسر +تيسروا +تيسليت +تيسير +تيسّر +تيفر +تيفولي +تيقنتُ +تيقوما +تيلر +تيم +تيمة +تيممت +تيمنا +تيمناً +تيمنًا +تيمور +تيمية +تين +تيه +تيّار +تَبْدِيلاً +تَجْرِي +تَحْتِهَا +تَذْرَعان +تَستقبل +تَصِحّوا +تَعُد +تَـجُـدْ +تَنسَ +تُبارى +تُبنى +تُتداول +تُتيح +تُتَطور +تُتْبَع +تُثرثر +تُجابه +تُجرَى +تُجرّؤكَ +تُجمع +تُجهض +تُجيد +تُجِبْ +تُجْرَى +تُحدقُ +تُحسب +تُحفر +تُحَلّ +تُخبئها +تُخصّص +تُدرّس +تُدعى +تُذكر +تُذلل +تُذْهَب +تُرافق +تُرجم +تُرجى +تُرفع +تُركب +تُرى +تُريني +تُريه +تُرَ +تُرَد +تُرَى +تُزال +تُزرع +تُزِالَ +تُستخدم +تُستعمل +تُستقبل +تُستهلك +تُستَخدَم +تُسقط +تُسمى +تُسمّي +تُسمِّي +تُسهم +تُسيِّر +تُسْتَخْدَم +تُسْتَمَرّ +تُشاهد +تُشدُّ +تُصب +تُصبَّ +تُصوِّر +تُصيخ +تُصَبُّ +تُضحك +تُضرب +تُطرح +تُطرد +تُطفأ +تُطلقه +تُظهر +تُعبر +تُعتَبَر +تُعد +تُعدُّ +تُعرف +تُعرَف +تُعرّف +تُعزَى +تُعقد +تُعلّمنا +تُعيد +تُعَد +تُعَدُّ +تُفرحها +تُفرز +تُفسِد +تُفقد +تُقابَل +تُقاس +تُقال +تُقام +تُقبل +تُقدح +تُقرأ +تُقرّ +تُقسر +تُقلق +تُقَيَّم +تُكتب +تُكتشف +تُلتقط +تُمارس +تُمثّل +تُملى +تُملي +تُمنَح +تُمنّي +تُميّز +تُميِّز +تُمْحى +تُنتج +تُنسج +تُنسى +تُنشد +تُنشر +تُنكر +تُنَظَّف +تُنَفَّذ +تُهان +تُهيأ +تُوج +تُوصي +تُوَقَّف +تُوِّج +تّصلّب +تّنفّس +تّنفّسية +ث +ثأر +ثأرا +ثأرت +ثائر +ثائرة +ثابت +ثابتا +ثابتاً +ثابتة +ثابتًا +ثابرت +ثابروا +ثاتشر +ثار +ثارت +ثاقب +ثاقبة +ثالث +ثالثا +ثالثاً +ثالثة +ثالثي +ثالثًا +ثالوث +ثالوثاً +ثامن +ثان +ثانوي +ثانوية +ثانى +ثاني +ثانيا +ثانياً +ثانية +ثانيه +ثانيهما +ثانيًا +ثانٍ +ثاوية +ثبات +ثباته +ثباتها +ثبت +ثبتا +ثبتت +ثبتناه +ثبته +ثبوت +ثبّتت +ثخذ +ثديي +ثراء +ثرائه +ثراه +ثراهما +ثرثارة +ثرثرة +ثرثرتكِ +ثروات +ثروة +ثروته +ثروتي +ثرى +ثري +ثريا +ثريات +ثرياً +ثرية +ثعالب +ثعبان +ثعلب +ثقاب +ثقافات +ثقافة +ثقافتك +ثقافتنا +ثقافته +ثقافتها +ثقافتهم +ثقافتهما +ثقافتي +ثقافتين +ثقافي +ثقافيا +ثقافياً +ثقافية +ثقب +ثقباً +ثقباًً +ثقبها +ثقبين +ثقة +ثقتك +ثقتكم +ثقته +ثقتهم +ثقل +ثقلا +ثقلها +ثقوب +ثقوبا +ثقوبها +ثقيف +ثقيل +ثقيلا +ثقيلاً +ثقيلة +ثك +ثكلت +ثكلى +ثلاث +ثلاثا +ثلاثاً +ثلاثة +ثلاثتنا +ثلاثمائة +ثلاثون +ثلاثى +ثلاثي +ثلاثيا +ثلاثية +ثلاثيته +ثلاثين +ثلاجة +ثلث +ثلثا +ثلثي +ثلج +ثلجية +ثلوج +ثم +ثمار +ثماره +ثمارها +ثمان +ثمانمائة +ثمانى +ثماني +ثمانية +ثمانين +ثمة +ثمر +ثمرات +ثمراً +ثمرة +ثمرها +ثمل +ثمن +ثمنا +ثمناً +ثمنه +ثمنها +ثمين +ثمينة +ثمّ +ثمّة +ثناء +ثناؤك +ثنائي +ثنائيا +ثنائيات +ثنائية +ثناه +ثنايا +ثنتين +ثنيات +ثو +ثواب +ثوابت +ثوابتُها +ثوان +ثواني +ثوب +ثوبه +ثوبها +ثوبًا +ثور +ثورات +ثوراته +ثوراتهم +ثوران +ثوراً +ثورة +ثورته +ثورتين +ثورن +ثوريا +ثوم +ثياب +ثيابها +ثيابهم +ثير +ثيرمى +ثيسبيدس +ثيودو +ثيودور +ثَم +ثَمَّ +ثَوَابًا +ج +جأش +جأشي +جئت +جئتك +جئتم +جئتنا +جئتُ +جئنا +جئناها +جا +جاء +جاءت +جاءتك +جاءتني +جاءته +جاءك +جاءنا +جاءني +جاءه +جاءها +جاءوا +جاؤوا +جائر +جائرة +جائزا +جائزة +جائزته +جائزتها +جائزتي +جائعاً +جائعة +جائعين +جائعًا +جاب +جابر +جابرييل +جابهنا +جابوها +جات +جاتا +جاثمة +جاد +جادا +جادافبوت +جاداً +جادة +جادت +جادل +جادون +جادين +جاذبي +جاذبية +جاذبيته +جاذبيتها +جار +جاراً +جارة +جارت +جارتنا +جارتها +جارتهم +جارثيا +جارجي +جارحا +جارحة +جاردنز +جارف +جارفة +جارفين +جارك +جارلاند +جارمكو +جاره +جارودي +جارون +جارى +جاري +جارية +جاريةً +جاريتها +جاز +جازالتعبير +جازما +جازييف +جاسم +جاسنر +جاسوس +جاسوسا +جاع +جاعلا +جاعلة +جاف +جافا +جافة +جاك +جاكادى +جاكادي +جاكسون +جاكوبسون +جال +جالس +جالسا +جالسان +جالساً +جالسة +جالسته +جالسير +جالسين +جالسًا +جالليكاس +جالون +جالونات +جاليات +جاليليو +جالينوس +جام +جاما +جامايكا +جامبو +جامبيا +جامحة +جامدة +جامع +جامعا +جامعات +جامعاتنا +جامعاتها +جامعة +جامعتنا +جامعته +جامعتي +جامعه +جامعي +جامعيا +جامعياً +جامعية +جامعيًّا +جان +جانب +جانبا +جانباً +جانبنا +جانبه +جانبها +جانبهم +جانبى +جانبي +جانبيا +جانبية +جانبيتان +جانبيه +جانبيها +جانبًا +جانبٍ +جانسين +جاني +جانيرو +جانٍ +جاها +جاهد +جاهدا +جاهداً +جاهدة +جاهدت +جاهدين +جاهدًا +جاهز +جاهزا +جاهزاً +جاهزة +جاهزين +جاهزًا +جاهلية +جاهين +جاوبتهم +جاورته +جاورها +جاوز +جاوزت +جب +جبار +جبارة +جباع +جبال +جبالها +جبان +جبانا +جبانة +جبر +جبرا +جبرائيل +جبران +جبره +جبريل +جبرين +جبسية +جبل +جبلاً +جبلة +جبلي +جبليا +جبلية +جبن +جبناء +جبني +جبنيت +جبهات +جبهة +جبهتي +جبهتين +جبور +جبيك +جبيل +جبين +جبينك +جبينه +جبينها +جبينهم +جبّارة +جثة +جثته +جثث +جثثا +جثم +جثمان +جثمانه +جثّته +جحا +جحر +جحره +جحرها +جحود +جحور +جحورها +جحيم +جد +جدا +جدار +جدارا +جدارة +جدارته +جدارتها +جدارتهم +جداري +جدارية +جدارًا +جدال +جدالا +جدالاً +جداول +جداً +جداًً +جدة +جدتك +جدته +جدتي +جدد +جددا +جدران +جدرانه +جدرانها +جدرانَها +جدعان +جدف +جدكم +جدل +جدلا +جدلاً +جدلية +جده +جدها +جدو +جدواها +جدول +جدولنا +جدوى +جدوي +جدي +جدياً +جدية +جديد +جديدا +جديداً +جديدة +جديدةً +جديده +جديدين +جديدًا +جدير +جديرا +جديرة +جديرتان +جديرٌ +جديّة +جدًا +جدّ +جدّاه +جدّاَ +جدًّا +جذاب +جذابا +جذاباً +جذابة +جذب +جذباً +جذبت +جذبتني +جذبته +جذبه +جذبوي +جذر +جذره +جذرها +جذرى +جذري +جذريا +جذرياً +جذرية +جذع +جذعها +جذعية +جذلاناً +جذوة +جذوته +جذوتها +جذور +جذورنا +جذوره +جذورها +جذورهم +جذوع +جذي +جذّاب +جر +جرأة +جرا +جراء +جرائد +جرائم +جرابات +جرابي +جراثيم +جراح +جراحا +جراحات +جراحاتنا +جراحة +جراحته +جراحه +جراحي +جراحيا +جراحية +جراحًا +جرار +جرارات +جرارة +جرافة +جرافيك +جرام +جراما +جرامات +جراماً +جرامًا +جرانت +جراند +جرانيت +جرايد +جربت +جرت +جرثوم +جرثومة +جرثومي +جرثومية +جرجا +جرح +جرحا +جرحاً +جرحت +جرحك +جرحًا +جرد +جرداء +جرس +جرسا +جرش +جرعات +جرعاتها +جرعة +جرعته +جرف +جرفت +جرفتهما +جرهارلم +جرهم +جروا +جروح +جروحاً +جروسمان +جرى +جري +جريء +جريئا +جريئة +جريا +جريان +جريبن +جريتا +جريجوري +جريجوريو +جريح +جريحا +جريد +جريدة +جريدتا +جريدته +جريدتي +جرير +جريمة +جرين +جرينبيس +جرينتش +جرينلاند +جريًا +جرّ +جرّب +جرّت +جرّتين +جرّنا +جرّي +جرَّاء +جرِّ +جزء +جزءا +جزءان +جزءاً +جزءً +جزءًا +جزءٌ +جزآن +جزأين +جزئه +جزئها +جزئي +جزئيا +جزئيات +جزئياً +جزئية +جزاء +جزاءات +جزائري +جزائرية +جزار +جزافاً +جزافًا +جزاك +جزر +جزع +جزعتُ +جزيء +جزيئات +جزيئاً +جزيئي +جزيرة +جزيرتهم +جزيل +جس +جسارته +جسام +جساماً +جسامته +جسد +جسدا +جسداً +جسدت +جسدنا +جسده +جسدها +جسدهم +جسدي +جسديا +جسدينا +جسديًا +جسر +جسرا +جسراً +جسره +جسرين +جســـــمنا +جسم +جسمالمريض +جسمانياً +جسماً +جسمك +جسمنا +جسمه +جسمها +جسمي +جسمية +جسور +جسوره +جسيمة +جسّار +جسّدها +جشع +جعبر +جعفر +جعفرباناهي +جعل +جعلا +جعلت +جعلتنا +جعلتني +جعلته +جعلتها +جعلنا +جعلني +جعله +جعلها +جعلهم +جعلوا +جعلوه +جعلي +جعودة +جعيط +جـ +جـديد +جــــريدة +جــمال +جف +جفاء +جفاف +جفافا +جفان +جفت +جفل +جفن +جفنيها +جفول +جفّ +جفّت +جفّف +جل +جلاء +جلابية +جلاد +جلادستون +جلاديس +جلاديه +جلاس +جلاسر +جلال +جلالة +جلالتكم +جلالته +جلاله +جلايكول +جلب +جلباب +جلبة +جلبرت +جلبنا +جلبه +جلبهم +جلبوا +جلبي +جلت +جلجامش +جلد +جلدته +جلدرات +جلدك +جلده +جلدها +جلدي +جلدية +جلس +جلسا +جلساءه +جلسائه +جلسات +جلسة +جلست +جلستنا +جلسته +جلسنا +جلسوا +جلسَ +جلطات +جلطة +جللا +جلمودُ +جله +جلها +جلوبال +جلوبيفارم +جلودنا +جلودهم +جلوسنا +جلوسه +جلون +جلي +جليا +جليانة +جلية +جليد +جليدة +جليدى +جليدية +جليسة +جليسه +جليل +جليلا +جليلة +جليًّا +جليَّا +جلّ +جماجم +جماح +جماحه +جمادى +جمادي +جماع +جماعات +جماعة +جماعتنا +جماعته +جماعي +جماعيا +جماعية +جماعيًا +جمال +جمالا +جمالاً +جماله +جمالها +جمالي +جماليات +جمالية +جماهير +جماهيره +جماهيري +جماهيريا +جماهيرياً +جماهيرية +جماً +جمة +جمجته +جمجمة +جمجمته +جمحمته +جمر +جمرات +جمع +جمعا +جمعاء +جمعة +جمعت +جمعتنا +جمعتني +جمعته +جمعتها +جمعتهم +جمعتهما +جمعني +جمعه +جمعها +جمعهما +جمعوا +جمعيات +جمعية +جمعيتنا +جمعيته +جمعيتي +جمل +جملا +جملاً +جملة +جملته +جملتها +جملتهم +جملتين +جمهرة +جمهور +جمهورا +جمهوراً +جمهورك +جمهوره +جمهورها +جمهوري +جمهوريات +جمهورية +جمود +جموع +جميع +جميعا +جميعات +جميعاً +جميعنا +جميعها +جميعهم +جميعهن +جميعًا +جميل +جميلا +جميلان +جميلاً +جميلة +جميلتي +جن +جنائز +جنائية +جنات +جناتا +جناح +جناحاً +جناحـاً +جناحي +جناحين +جناحيه +جناحيَّ +جنازة +جنازتكم +جنازته +جنازتها +جناية +جناً +جنب +جنبا +جنبات +جنباته +جنباتها +جنباً +جنبه +جنبيات +جنة +جنته +جنتها +جنح +جنحوا +جند +جندت +جندي +جنديا +جندية +جنرال +جنرالات +جنرالاتنا +جنس +جنسك +جنسه +جنسهم +جنسيا +جنسيات +جنسياً +جنسية +جنسيته +جنسيًّا +جنكيز +جنوب +جنوبا +جنوباً +جنوبه +جنوبها +جنوبهم +جنوبي +جنوبية +جنوبًا +جنوة +جنوح +جنود +جنودهم +جنون +جنونا +جنونه +جنونها +جنونية +جنوه +جنى +جني +جنيف +جنين +جنيناً +جنيه +جنيها +جنيهات +جنيهاً +جنيّا +جنّب +جنّة +جها +جهات +جهاتك +جهاته +جهاتها +جهاد +جهاداً +جهادك +جهادها +جهادية +جهادًا +جهاراً +جهاز +جهازا +جهازك +جهازهم +جهازي +جهازًا +جهاني +جهة +جهته +جهتها +جهد +جهداً +جهدت +جهدنا +جهده +جهدها +جهدهم +جهدي +جهراً +جهرًا +جهز +جهل +جهلاً +جهلة +جهلك +جهلنا +جهلها +جهلهم +جهنم +جهنمي +جهنمية +جهود +جهودا +جهوداً +جهودكم +جهوده +جهودها +جهودهم +جهودي +جهودًا +جهودٌ +جهيد +جهيزة +جهيزته +جهينة +جهّزتما +جو +جوا +جوائز +جوائزها +جواب +جوابا +جواباً +جوابه +جوابها +جوابهم +جوابي +جوابًا +جواتيمالا +جواد +جواده +جوار +جوارحنا +جوارحي +جواره +جوارها +جوارهم +جوارهما +جواريرِ +جواز +جوازات +جوازه +جواسيس +جوالاً +جوامع +جوامعها +جوانا +جوانب +جوانبه +جوانبها +جوانتانامو +جوانتاناميرا +جوانجدونج +جوانحها +جواهر +جواً +جوبه +جوبهت +جوبهوا +جوته +جوخ +جودة +جودته +جودتها +جودل +جوده +جودو +جودوي +جودي +جوذا +جور +جورانتي +جورباتشوف +جورج +جورجي +جورجيا +جورجيو +جوردن +جورديمر +جورنال +جورنيجرات +جورينتي +جوريون +جوز +جوزف +جوزيف +جوستنياوس +جوسلين +جوع +جوعا +جوعاً +جوعى +جوعي +جوف +جوفاء +جوفه +جوفي +جوفية +جول +جولات +جولاتنا +جولة +جولتنا +جولته +جولد +جوليس +جومث +جون +جوناثان +جونس +جونسون +جوني +جونية +جونيه +جوها +جوهانسبرج +جوهر +جوهرا +جوهرانية +جوهرانيّ +جوهرة +جوهرها +جوهري +جوهريا +جوهرياً +جوهرية +جوهريين +جوي +جويا +جوياً +جوية +جوٍ +جوّ +جوّاب +جوّاً +جى +جي +جيئة +جيادهم +جياش +جياشة +جياع +جيب +جيبك +جيبه +جيبهم +جيبي +جيت +جيتار +جيتني +جيخون +جيد +جيدا +جيداً +جيداَ +جيدة +جيدين +جيدًا +جير +جيرار +جيراروي +جيراس +جيرالد +جيرالدي +جيران +جيراننا +جيربا +جيروم +جيري +جيش +جيشا +جيشاً +جيشه +جيشها +جيشهم +جيشي +جيـت +جيفارا +جيفري +جيفيك +جيكور +جيل +جيلا +جيلادا +جيلاً +جيلنا +جيله +جيلهما +جيلو +جيلي +جيلين +جيلٍ +جيم +جيماك +جيمس +جيمي +جين +جينات +جيناتنا +جيناتها +جينة +جيني +جينية +جينيسليه +جينًا +جيهان +جيوب +جيوبه +جيوبهم +جيوبي +جيورجيو +جيوردانو +جيوزب +جيوسبي +جيوسيبي +جيوش +جيوشا +جيوشاً +جيوشنا +جيوفاني +جيولوجيا +جيولوجية +جيولوجيين +جيّد +جيّداً +جيّدًا +جَثَت +جَدَّاتهم +جَنَّاتٍ +جَهِد +جُبل +جُبِلْن +جُرِّد +جُفاءً +جُمعت +جُندت +جِده +جّل +ح +حائر +حائرا +حائراً +حائرة +حائرون +حائرًا +حائزة +حائط +حائطية +حائكة +حائلا +حائلاً +حابس +حابو +حاتم +حاج +حاجات +حاجاته +حاجاتها +حاجاتي +حاجاً +حاجبه +حاجبيه +حاجة +حاجةً +حاجةٍ +حاجتنا +حاجته +حاجتها +حاجتهم +حاجتي +حاجز +حاجزا +حاجزاً +حاجزًا +حاجياته +حاجياتي +حاجيًا +حاد +حادا +حاداً +حادة +حادت +حادث +حادثا +حادثات +حادثة +حاده +حادّة +حاذقا +حاذقة +حار +حارا +حارات +حاراً +حاربته +حاربوا +حارة +حارته +حارس +حارسا +حارق +حارقة +حارين +حارّة +حاز +حازت +حازتها +حازم +حازما +حازمة +حاسباً +حاسبة +حاسبك +حاسة +حاسم +حاسما +حاسماً +حاسمة +حاشية +حاشيته +حاصد +حاصر +حاصرات +حاصرتني +حاصرته +حاصل +حاصلاً +حاصلين +حاضر +حاضرا +حاضراً +حاضرة +حاضرت +حاضرنا +حاضرها +حاضرهم +حاضري +حاضرًا +حاضنات +حاضنة +حاف +حافة +حافز +حافزاً +حافظ +حافظت +حافظوا +حافظًا +حافل +حافلا +حافلات +حافلاً +حافلة +حافلته +حافلتها +حافيا +حافياً +حافية +حاق +حاقدة +حاقن +حاكاه +حاكم +حاكما +حاكمها +حال +حالا +حالات +حالاته +حالاتها +حالاتهم +حالاتي +حالاً +حالة +حالةً +حالت +حالتنا +حالته +حالتها +حالتهم +حالتي +حالتين +حالفاه +حالفنا +حالك +حالكة +حالم +حالما +حالمة +حالنا +حاله +حالها +حالهم +حالي +حاليا +حالياً +حالية +حالين +حاليًا +حاليًّا +حام +حامد +حامض +حامضي +حامل +حاملا +حاملاً +حاملة +حامله +حاملها +حاملي +حاملين +حامليه +حامي +حامية +حاميتين +حامينا +حاميه +حان +حانات +حانت +حانقا +حانوتي +حانون +حانية +حاوره +حاوطوه +حاول +حاولت +حاولته +حاولنا +حاولوا +حاولي +حاوي +حاوية +حاييم +حب +حبا +حبائل +حبات +حباته +حباتها +حبال +حبالا +حباه +حباها +حباً +حببت +حبة +حبث +حبر +حبراً +حبس +حبسا +حبست +حبسه +حبسها +حبك +حبل +حبلاً +حبله +حبلى +حبلية +حبلٍ +حبن +حبنا +حبه +حبها +حبهما +حبوب +حبوبا +حبوباتي +حبي +حبيب +حبيبات +حبيبتي +حبيبه +حبيبي +حبيبين +حبيس +حبيسة +حبّ +حبّاته +حبّاً +حبّه +حبّهم +حتب +حتخبي +حتفه +حتفهم +حتفهما +حتما +حتماً +حتمت +حتميا +حتمياً +حتمية +حتمًا +حتى +حتي +حتّى +حث +حثت +حثيثة +حثًا +حج +حجاب +حجابها +حجاج +حجار +حجارة +حجازي +حجب +حجباً +حجبتها +حجة +حجته +حجج +حججه +حجر +حجرا +حجرات +حجراتنا +حجراته +حجرة +حجرته +حجرتي +حجره +حجرها +حجري +حجريات +حجرية +حجريًّا +حجرًا +حجز +حجزت +حجزنا +حجم +حجما +حجماً +حجمك +حجمه +حجمها +حجمي +حجمِها +حجوا +حجوزات +حجوزاتهم +حجَّت +حد +حدا +حدائق +حدائقها +حداثات +حداثة +حداثتنا +حداثته +حداثي +حداثياً +حداثية +حداد +حداً +حدب +حدة +حدتث +حدتها +حدث +حدثا +حدثاً +حدثت +حدثتنا +حدثتني +حدثته +حدثتهما +حدثنا +حدثني +حدثيني +حدج +حدجه +حدد +حددت +حددته +حددها +حددوا +حددوها +حدس +حدقة +حدقوا +حده +حدوة +حدوث +حدوثه +حدوثها +حدود +حدودا +حدوداً +حدودنا +حدوده +حدودها +حدودهم +حدودهما +حدي +حديث +حديثا +حديثاً +حديثاُ +حديثة +حديثكِ +حديثنا +حديثه +حديثها +حديثي +حديثًا +حديد +حديده +حديدو +حديدي +حديدية +حديقة +حديقته +حديقتي +حديقتين +حدين +حدًا +حدٍ +حدّ +حدّا +حدّاً +حدّة +حدّتها +حدّثتنا +حدّثنا +حدّقت +حدّقتُ +حدّها +حدّي +حدًّا +حدَّ +حدَّق +حدَّقوا +حذاء +حذاءك +حذاءه +حذاؤك +حذائه +حذائها +حذائي +حذار +حذر +حذرا +حذراُ +حذرة +حذرت +حذرنا +حذره +حذروا +حذرين +حذف +حذفناه +حذو +حذوه +حذّرتني +حر +حرا +حراء +حرائق +حرارة +حرارته +حرارتها +حرارية +حراس +حراستها +حراك +حرام +حران +حراً +حرب +حربا +حرباء +حرباً +حربة +حربكم +حربنا +حربه +حربها +حربهم +حربي +حربية +حربًا +حرة +حرج +حرجا +حرجاً +حرجة +حرجٌ +حردًا +حرر +حررتني +حررته +حررها +حرزيم +حرس +حرسه +حرسها +حرص +حرصا +حرصاً +حرصت +حرصنا +حرصه +حرصها +حرصهم +حرصوا +حرصي +حرضت +حرضتنا +حرضنا +حرف +حرفا +حرفاً +حرفة +حرفي +حرفيا +حرفياً +حرفية +حرفين +حرفيين +حرفًا +حرق +حرقة +حرقه +حرقها +حرك +حركات +حركاتنا +حركاته +حركة +حركت +حركته +حركتها +حركتهم +حركتي +حركية +حرم +حرمات +حرمان +حرمانها +حرماني +حرمة +حرمت +حرمته +حرمتها +حرمني +حرمه +حرمها +حرمهم +حرموا +حروب +حروبا +حروف +حروفا +حروفه +حروفها +حروق +حرياته +حرية +حريتنا +حريته +حريتها +حريتهم +حريتهن +حريتي +حريري +حريص +حريصا +حريصاً +حريصة +حريصين +حريصًا +حريق +حريمة +حريّتها +حرًا +حرّ +حرّاسه +حرّان +حرّة +حرّكت +حرّيته +حرَّانِ +حرَّكته +حزام +حزب +حزبا +حزبان +حزباً +حزبها +حزبي +حزبية +حزبيًا +حزتُ +حزم +حزمة +حزمت +حزن +حزنا +حزناً +حزنت +حزنه +حزنهم +حزنًا +حزوزا +حزيران +حزين +حزينا +حزيناً +حزينة +حزينون +حزّ +حس +حسا +حساء +حساب +حسابات +حساباتنا +حساباته +حساباتها +حساباً +حسابته +حسابك +حسابه +حسابها +حسابي +حسابية +حساس +حساسة +حساسية +حساسيته +حساسيتها +حسان +حساً +حسب +حسبانه +حسبت +حسبك +حسبما +حسد +حسداً +حسدت +حسر +حسرة +حسم +حسما +حسمت +حسن +حسنا +حسناء +حسناً +حسنة +حسنت +حسنتين +حسنى +حسني +حسنين +حسنًا +حسه +حسية +حسين +حسّاسة +حسّية +حسِّية +حسْبُك +حشائش +حشد +حشدا +حشداً +حشدت +حشدهم +حشرا +حشرات +حشرة +حشرت +حشرجة +حشرية +حشمة +حشي +حشيشة +حصائره +حصاة +حصاد +حصاداً +حصادنا +حصادها +حصار +حصاره +حصارها +حصارهم +حصان +حصانا +حصانة +حصانته +حصانه +حصة +حصته +حصتهم +حصد +حصر +حصرا +حصراً +حصره +حصرها +حصرية +حصص +حصل +حصلت +حصلنا +حصلوا +حصن +حصناً +حصول +حصوله +حصولها +حصولهم +حصولي +حصون +حصونه +حصونهم +حصيات +حصيرة +حصيلة +حصيلتي +حصينا +حصينة +حصّته +حصّتها +حصّل +حضارات +حضاراتها +حضاراتهم +حضارة +حضارةً +حضارتنا +حضارته +حضارتها +حضارتهم +حضارتين +حضارى +حضاري +حضاريا +حضارياً +حضارية +حضاريتين +حضاريين +حضاريًّا +حضانة +حضر +حضرات +حضرة +حضرت +حضرته +حضرنا +حضره +حضرها +حضروا +حضريوما +حضن +حضناً +حضنت +حضور +حضورا +حضوراً +حضورنا +حضوره +حضورها +حضورهم +حضوري +حضّرت +حط +حطام +حطان +حطة +حطت +حطم +حطمته +حطمها +حطه +حطي +حطين +حطينا +حطّين +حطَّمت +حظ +حظا +حظائر +حظاً +حظر +حظه +حظهم +حظهما +حظوته +حظي +حظيت +حظيرة +حظّه +حـاج +حـاجاتهم +حـاجة +حـافزاً +حـالة +حـالياً +حـتي +حـجارة +حـجب +حـجم +حـدود +حـديثة +حـديقة +حـدٍ +حـرص +حـركة +حـسين +حـصر +حـصيلة +حـفر +حـفرة +حـفل +حـقق +حـققت +حـملات +حـمله +حـوالى +حـول +حـيث +حف +حفائر +حفازة +حفاظاً +حفاظًا +حفاوة +حفر +حفرات +حفرة +حفرت +حفرتها +حفرها +حفريات +حفرياته +حفرية +حفز +حفزاً +حفزت +حفظ +حفظت +حفظتها +حفظنا +حفظناها +حفظه +حفظها +حفظًا +حفل +حفلا +حفلات +حفلاته +حفلاتها +حفلاً +حفلة +حفلت +حفنة +حفني +حفياً +حفيداه +حفيدته +حفيده +حفيظة +حفيف +حفّارٌ +حفّت +حق +حقا +حقائب +حقائبنا +حقائبه +حقائبهم +حقائق +حقانى +حقانية +حقاً +حقب +حقبة +حقبتي +حقد +حقدا +حقده +حقفة +حقق +حققت +حققته +حققتها +حققنا +حققناه +حققه +حققها +حققوه +حقك +حقل +حقلاً +حقن +حقنا +حقنات +حقناً +حقنها +حقه +حقها +حقهم +حقوق +حقوقا +حقوقاً +حقوقك +حقوقكم +حقوقه +حقوقها +حقوقهم +حقوقهن +حقوقي +حقوقيًا +حقوقًا +حقول +حقولهم +حقي +حقيبة +حقيبته +حقيبتها +حقيبتي +حقير +حقيراً +حقيرة +حقيق +حقيقة +حقيقتنا +حقيقته +حقيقتها +حقيقي +حقيقيا +حقيقيان +حقيقياً +حقيقية +حقيقيون +حقيقيين +حقيقيًا +حقًا +حقّ +حقّاً +حقّة +حقّقه +حقّها +حقّهم +حقًّا +حقٌّ +حقَّاً +حك +حكام +حكامهم +حكايا +حكايات +حكاياته +حكاياتهم +حكاية +حكايتها +حكة +حكت +حكر +حكرا +حكم +حكما +حكماء +حكمة +حكمت +حكمتم +حكمته +حكمدار +حكمنا +حكمه +حكمها +حكمهم +حكموا +حكواتي +حكومات +حكوماته +حكوماتها +حكوماتهم +حكومة +حكومته +حكومتهم +حكومي +حكومية +حكوميين +حكوميًا +حكى +حكيم +حكيما +حكيمة +حكّمها +حل +حلا +حلاق +حلاقة +حلال +حلاوة +حلايب +حلاً +حلاّق +حلب +حلبة +حلبي +حلة +حلت +حلزون +حلف +حلفا +حلقات +حلقاته +حلقاتها +حلقة +حلقتان +حلقه +حلقها +حلقي +حلقية +حلقَ +حلكة +حللته +حلم +حلما +حلماً +حلمت +حلمتُ +حلمنا +حلمه +حلمها +حلمي +حلمية +حلميش +حلمًا +حلنا +حلها +حلو +حلوان +حلوة +حلول +حلولا +حلولاً +حلوى +حلي +حليب +حليبها +حليفا +حليفاً +حليفهم +حلين +حلّ +حلّت +حلّها +حلٌّ +حلَّت +حلَّها +حلُّ +حمأة +حماة +حماةٌ +حماد +حمار +حمارة +حماره +حماس +حماسا +حماسة +حماستهم +حماستي +حماسه +حماسها +حماسي +حماسًا +حماقة +حماكم +حمام +حماما +حمامات +حمامة +حمامتين +حمامى +حمانا +حماها +حماية +حمايته +حمايتها +حمايتهم +حمة +حمد +حمدا +حمدان +حمدت +حمده +حمدي +حمراء +حمرة +حمزة +حمص +حمصي +حمض +حمضه +حمضية +حمقاء +حمل +حملات +حملاتهم +حملاه +حملة +حملت +حملتا +حملتك +حملتنا +حملته +حملتها +حملتهم +حمله +حملها +حملوا +حملي +حمن +حمود +حمولة +حمويه +حمى +حمية +حميت +حميته +حميد +حميدة +حميم +حميما +حميماً +حميمة +حميمية +حميمين +حمَلة +حمّاس +حمّالاً +حمّام +حمّامها +حمّى +حمَّال +حنا +حنان +حناناً +حنانك +حنانه +حنانها +حنانيا +حناياها +حنبل +حنة +حنجرة +حنجرتي +حنضل +حنظلة +حنفية +حنفيو +حنق +حنقا +حنكة +حنونًا +حنيش +حنيفة +حنين +حنيناً +حنينه +حنينها +حوائج +حوائجا +حوائجهم +حوائط +حوائطه +حواجز +حوادث +حوادثها +حوار +حوارا +حوارات +حواراته +حواراتها +حواراً +حواره +حوارهما +حواري +حواريا +حوارية +حواريون +حواس +حواسي +حواشي +حواشيها +حواضر +حواف +حوافز +حوافه +حوافها +حوال +حوالات +حوالى +حوالي +حوالينا +حواه +حوتاً +حوته +حور +حوران +حورية +حوريتك +حوزة +حوش +حوض +حوضاً +حوضه +حوقل +حول +حولا +حولت +حولتنا +حولك +حولنا +حوله +حولها +حولهم +حولهما +حولوا +حولي +حوليات +حولية +حومة +حوّلاها +حوّلت +حوّلوا +حي +حيا +حياء +حياة +حياتك +حياتكم +حياتنا +حياته +حياتها +حياتهم +حياتهن +حياتي +حياتياً +حياتية +حياتين +حيادي +حيادية +حيارى +حيازة +حيازتي +حياضه +حياك +حياكة +حيال +حياله +حيالها +حيان +حياً +حية +حيث +حيثما +حيثيات +حيثياتها +حيثُ +حيدة +حيدر +حيرة +حيرته +حيرتي +حيز +حيزا +حيزاً +حيزها +حيض +حيل +حيلة +حين +حينئذ +حينا +حيناً +حينذاك +حينما +حينه +حينها +حينًا +حيوات +حيوان +حيوانا +حيوانات +حيواناتها +حيواناتهم +حيواناً +حيوانية +حيوانيًّا +حيوي +حيويا +حيوية +حيويته +حيويتها +حيويين +حييتُ +حيّ +حيّاه +حيّاً +حيّزا +حيّنا +حيّوا +حيٍّ +حيَّر +حيَّرت +حيِّزٍ +حَبِيب +حَجب +حَدَثٌ +حَسُن +حَسُنت +حَظٍّ +حَكِيمٌ +حَمَلنا +حَمَلَها +حُبَيْب +حُبَّه +حُزْنان +حُسن +حُسْنُ +حُشر +حُشرت +حُفظت +حُكمه +حُمص +حِبّ +حِيلة +حّدق +خ +خا +خائب +خائبا +خائبين +خائف +خائفا +خائفاً +خائفة +خائفون +خائفًا +خائن +خائنا +خائنات +خاب +خابيتا +خاتشا +خاتشادوريان +خاتم +خاتما +خاتمة +خادعة +خادم +خادما +خادمات +خادماً +خادمة +خادمًا +خارج +خارجا +خارجاً +خارجة +خارجه +خارجها +خارجي +خارجيا +خارجياً +خارجية +خارجين +خارجًا +خارطة +خارقاً +خارقة +خازنها +خاسرة +خاشع +خاشعين +خاص +خاصا +خاصان +خاصاً +خاصة +خاصةً +خاصرة +خاصمني +خاصيات +خاصية +خاصًا +خاصّة +خاصًّا +خاض +خاضت +خاضتها +خاضعان +خاضعاً +خاضعة +خاضها +خاضوا +خاطئ +خاطئاً +خاطئة +خاطب +خاطبت +خاطبتنا +خاطبه +خاطبوا +خاطر +خاطرنا +خاطره +خاطرها +خاطروا +خاطري +خاطفها +خاف +خافت +خافتاً +خافتة +خافض +خافضين +خافه +خافوا +خافوه +خافيا +خاكية +خال +خالة +خالت +خالتها +خالتي +خالد +خالدا +خالداً +خالدة +خالص +خالصا +خالصة +خالصين +خالطت +خالطه +خالف +خالفت +خالفه +خالقا +خالقاً +خالقه +خالقهم +خالك +خاله +خالها +خالي +خاليا +خالياً +خالية +خاليةٌ +خالٍ +خام +خامات +خامة +خامداً +خامرتها +خامس +خامسا +خامساً +خاملا +خاملةً +خان +خانة +خانتني +خانته +خانتها +خانق +خانقاً +خانقة +خانقه +خانني +خانوف +خاوية +خاويًا +خايف +خبأه +خبا +خباز +خبايا +خبث +خبثًا +خبر +خبرا +خبراء +خبرائه +خبرائهم +خبرات +خبراته +خبراتهم +خبراتي +خبراً +خبرة +خبرت +خبرتنا +خبرته +خبرتها +خبرتي +خبز +خبزك +خبي +خبيئة +خبيث +خبيثا +خبيثة +خبير +خبيرا +خبيراً +خبيرة +خبيرًا +ختام +ختاما +ختك +ختم +ختمتها +ختمناه +ختمه +ختمها +خجل +خجلا +خجلاً +خجلة +خجلها +خجلي +خجول +خجولاً +خجولة +خد +خداع +خداعا +خداعنا +خداعها +خداعي +خداعية +خدر +خدره +خدرها +خدش +خدعة +خدعنا +خدعه +خدعهم +خدم +خدمات +خدماته +خدماتها +خدماتي +خدمة +خدمت +خدمتك +خدمته +خدمتهم +خدمه +خدمى +خدمي +خدمية +خده +خدها +خدوجة +خدي +خديجة +خديها +خذ +خذت +خرائب +خرائط +خراب +خرابا +خرابنا +خرابها +خراج +خراساني +خرافات +خرافة +خرافيا +خرافية +خربة +خربشات +خرج +خرجت +خرجتُ +خرجنا +خرجوا +خرجيتي +خرزة +خرساباد +خرطوشة +خرف +خرفها +خرق +خروج +خروجا +خروجاً +خروجك +خروجه +خروجها +خروجهم +خروجي +خروجًا +خروف +خريبكة +خريبيش +خريج +خريجاً +خريجو +خريجى +خريجي +خريجينا +خريجيه +خريجيها +خريطة +خريف +خزائن +خزافي +خزان +خزانات +خزانة +خزانته +خزع +خزف +خزفية +خسائر +خسائره +خسارة +خسارتهم +خساو +خساً +خسر +خسرت +خسرته +خسرنا +خسرناه +خسره +خسرو +خسيس +خشب +خشبة +خشبته +خشبي +خشبيا +خشبية +خشبيّ +خشبيّة +خشخاش +خشخشة +خشخشت +خشلاستيك +خشنة +خشونة +خشي +خشية +خشيت +خشيتهم +خص +خصائص +خصائصه +خصائصها +خصاصة +خصال +خصالا +خصب +خصبا +خصبها +خصته +خصراً +خصره +خصرها +خصص +خصصت +خصصه +خصلة +خصلةً +خصم +خصوبة +خصوص +خصوصا +خصوصاً +خصوصي +خصوصيات +خصوصياته +خصوصياتها +خصوصية +خصوصيتنا +خصوصيته +خصوصيتها +خصوصًا +خصوم +خصومات +خصومة +خصومه +خصومها +خصيب +خصية +خصيصا +خصيصاً +خصيصًا +خضاب +خضار +خضت +خضرا +خضراء +خضراوان +خضرة +خضع +خضعت +خضعوا +خضم +خضمّ +خضوع +خضوعها +خضير +خط +خطأ +خطأه +خطأها +خطأين +خطأً +خطئه +خطئي +خطا +خطاب +خطابا +خطابات +خطاباتنا +خطاباته +خطاباتهم +خطابنا +خطابه +خطاط +خطانا +خطاه +خطاها +خطاي +خطايا +خطاً +خطب +خطبا +خطباء +خطباءـ +خطباؤه +خطبة +خطبته +خطبه +خطة +خطت +خطته +خطتهم +خطتي +خطر +خطرا +خطراً +خطرة +خطرت +خطرجديداً +خطرن +خطره +خطرها +خطرًا +خطط +خططاً +خططك +خططنا +خططها +خططهم +خططًا +خطـر +خطف +خطفت +خطها +خطوات +خطواتك +خطواتكم +خطواتنا +خطواته +خطواتها +خطواتي +خطواتُه +خطوة +خطوتها +خطوتين +خطورة +خطورته +خطورتها +خطوط +خطوطا +خطوطاً +خطوطه +خطوطها +خطى +خطي +خطيئة +خطيب +خطيبا +خطير +خطيرا +خطيراً +خطيرة +خطيرًا +خطين +خف +خفاءٍ +خفاجي +خفة +خفت +خفتت +خفتُ +خفض +خفف +خفق +خفقت +خفوت +خفي +خفيا +خفية +خفير +خفيرا +خفيض +خفيف +خفيفاً +خفيفة +خفيًا +خفّف +خفَّت +خلا +خلاء +خلابة +خلات +خلاص +خلاصا +خلاصة +خلاف +خلافا +خلافات +خلافاتنا +خلافاته +خلافاً +خلافة +خلافه +خلافها +خلافهم +خلافًا +خلاق +خلاقا +خلاقة +خلال +خلاله +خلالها +خلالهم +خلالهما +خلايا +خلايانا +خلاياهم +خلت +خلجان +خلخلة +خلد +خلدت +خلده +خلدها +خلدون +خلسة +خلصت +خلصوا +خلصونا +خلط +خلطة +خلطها +خلع +خلعا +خلعة +خلف +خلفاء +خلفاؤه +خلفان +خلفة +خلفته +خلفتها +خلفك +خلفنا +خلفه +خلفها +خلفهم +خلفوا +خلفي +خلفيات +خلفية +خلفيتي +خلق +خلقا +خلقاً +خلقت +خلقتها +خلقك +خلقناكم +خلقني +خلقه +خلقها +خلقهم +خلقي +خلقية +خلقًا +خلك +خلل +خللا +خللاً +خلني +خلو +خلواته +خلوة +خلوتنا +خلود +خلوي +خلوية +خلي +خلية +خليته +خليتها +خليتيني +خليج +خليجي +خليجيا +خليجية +خليط +خليطا +خليطاً +خليفة +خليفته +خليق +خليقة +خليل +خليلات +خليلاته +خلّدها +خلّف +خلّفنا +خلُّوا +خمارات +خمارهن +خمارويه +خماسي +خمس +خمسة +خمســـة +خمسمائة +خمسها +خمسون +خمسية +خمسين +خمسينيات +خمسًا +خمسٌ +خمنت +خمور +خمولاً +خمير +خميرة +خميس +خمّن +خنادقها +خنجر +خندق +خندقا +خندقاً +خنزير +خنزيري +خنق +خنقا +خنوع +خواتم +خواتمه +خوادم +خوارق +خواص +خواصه +خواصها +خواطر +خوان +خوذا +خوذات +خوري +خورية +خوسيه +خوض +خوف +خوفا +خوفاً +خوفه +خوفها +خوفهما +خوفي +خوفًا +خولة +خولوا +خونة +خيار +خيارا +خيارات +خياراته +خياراً +خيارنا +خيارين +خياشيمها +خياط +خيال +خيالات +خيالنا +خياله +خيالها +خيالهم +خيالي +خيالية +خيام +خيامه +خيامهم +خيامية +خيانة +خيانته +خيبات +خيبة +خيبت +خيبر +خير +خيرا +خيرات +خيراته +خيراً +خيرة +خيرهما +خيريا +خيرية +خيريتين +خيرًا +خيزراناتهم +خيزرانة +خيزرانته +خيط +خيطاً +خيفة +خيل +خيلاء +خيم +خيمة +خيمت +خيمته +خيوط +خيوطها +خيوطٍ +خيولهم +خيّبت +خيّل +خيّم +خيِّر +خيِّل +خَبِر +خَرَّجَت +خَصِيصة +خَلَقْنَاكُم +خَيْرٌ +خُفِّض +خُلق +خُلِقت +خُلِقَ +خُلّدت +خُلِّفوا +خُمس +خُيّر +خُيّل +د +دءوب +دأب +دأبت +دأبه +دأبوا +دأبي +داء +داءً +دائبون +دائرا +دائراً +دائرة +دائرته +دائرتها +دائري +دائرية +دائم +دائما +دائماً +دائمة +دائمين +دائمًا +دابة +دابر +دابره +دابروسكا +داتاكرايم +داخت +داخـل +داخل +داخلا +داخلاً +داخلة +داخلك +داخله +داخلها +داخلهم +داخلي +داخليا +داخلياً +داخلية +داخليًا +دار +دارا +دارالمأمون +داراً +دارة +دارت +دارتنا +دارته +دارج +دارس +دارسي +دارسيها +دارك +دارنا +داره +دارها +دارهم +دارون +دارويش +داروين +داري +داريا +دارين +داريو +داس +داسه +داسوا +داعب +داعبها +داعماً +داعمة +داعمي +داعي +داعيا +داعيات +داعياً +داعية +داعيكم +داعيًا +داعٍ +دافئ +دافئا +دافئة +دافع +دافعا +دافعاً +دافعة +دافعت +دافعه +دافعها +دافعهم +دافعوا +دافعي +دافقاً +دافنشي +دافيد +داكن +داكنا +داكنة +دال +دالة +دالية +دام +داما +دامت +دامس +داميان +دامية +دان +دانت +دانتي +دانلوس +داني +دانيال +داهم +داهمت +داهمتني +داهمنا +داهمه +داهمها +داود +داومت +داون +داوود +داى +داي +دايان +دايجنيوس +دايفيد +دايك +دايملر +دب +دباباته +دباباتها +دبابيس +دبالية +دباً +دبت +دبجها +دبدوب +دبلوم +دبلوماسيون +دبلوماسيين +دبلوماسيينا +دبلومه +دبلومًا +دبليو +دبى +دبي +دبيب +دبّين +دبٍّ +دة +دترويت +دجاج +دجلة +دجون +دحضا +دحضت +دحضها +دخان +دخانياً +دخل +دخلا +دخلاء +دخلاً +دخلت +دخلتني +دخلتها +دخلن +دخلنا +دخلناه +دخله +دخلها +دخلهم +دخلوا +دخلوها +دخن +دخول +دخولك +دخولنا +دخوله +دخولها +دخولهم +دخولهن +دخولي +دخيل +دخيلة +درء +دراجات +دراجاتهم +دراجة +دراجتك +دراجته +دراسات +دراساتنا +دراساته +دراساتها +دراساتهم +دراساتي +دراسة +دراستك +دراستكم +دراستنا +دراسته +دراستها +دراستهم +دراستي +دراسي +دراسيا +دراسية +دراما +دراماتيكي +دراماتيكية +درامي +دراميا +درامية +دراهم +دراية +درب +دربا +دربتني +دربي +درة +درج +درجات +درجاتك +درجاته +درجاتها +درجاتهم +درجاً +درجة +درجت +درجته +درجتي +درجتين +درجنا +درجهم +درجي +دردشة +درز +درزن +درس +درسا +درساً +درست +درستها +درستُ +درسناها +درسه +درسها +درسهم +درسوا +درسوه +درسًا +درع +درعمي +درعمية +درقاتها +درقة +درك +درنة +درهام +درهم +دروب +دروبا +دروس +دروسا +دروسه +دروسها +دروسهم +دروسي +دروسًا +دروع +درويش +دري +دريد +درّاجة +درّس +درّست +درَّس +درَّست +درُّك +دزيرة +دس +دسائس +دساماته +دستور +دستوري +دستورية +دسست +دسمة +دسوقي +دسوه +دش +دشتاً +دشنت +دع +دعا +دعاء +دعائم +دعائي +دعائية +دعاة +دعارة +دعان +دعانا +دعاني +دعاه +دعاها +دعاهم +دعاوى +دعاية +دعبل +دعت +دعته +دعك +دعم +دعماً +دعمت +دعمه +دعمها +دعمًا +دعنا +دعني +دعوا +دعوات +دعواي +دعوة +دعوةً +دعوت +دعوتك +دعوته +دعوتها +دعوتهم +دعوتهما +دعوتهن +دعوتي +دعونا +دعوى +دعويا +دعوية +دعى +دعي +دعيت +دعيج +دعينا +دعيني +دعيه +دفء +دفات +دفاتر +دفاتره +دفاع +دفاعات +دفاعاتها +دفاعاً +دفاعه +دفاعها +دفاعي +دفاعية +دفاعًا +دفة +دفتر +دفتراً +دفتري +دفع +دفعا +دفعاه +دفعاً +دفعة +دفعت +دفعتنا +دفعتني +دفعته +دفعتها +دفعك +دفعنا +دفعني +دفعه +دفعها +دفعهم +دفق +دفن +دفنت +دفنها +دفوف +دفيئة +دق +دقائق +دقائقنا +دقائقه +دقائقها +دقات +دقة +دقت +دقتها +دققت +دققنا +دقلة +دقيق +دقيقا +دقيقاً +دقيقة +دقيقتان +دقيقًا +دك +دكا +دكان +دكانه +دكتاتور +دكتاتورنا +دكتاتوريات +دكتاتورية +دكتور +دكتوراة +دكتوراه +دكَّاً +دل +دلائل +دلافيدا +دلالات +دلالاتها +دلالة +دلالته +دلالتها +دلت +دلتا +دلفت +دلفنا +دلفي +دلكاسال +دلنا +دلني +دلهي +دلوها +دليل +دليلا +دليلاً +دليلك +دليلنا +دليله +دليلي +دلّ +دلّت +دم +دماء +دماؤه +دمائها +دمار +دمامل +دمت +دمتم +دمث +دمج +دمجها +دمجهما +دمر +دمرت +دمرتنا +دمشق +دمشقي +دمشقية +دمع +دمعة +دمعتان +دمعته +دمعتي +دمك +دمل +دمنا +دمنهور +دمه +دمها +دمهم +دمور +دموع +دموعا +دموعك +دموعه +دموعها +دموعهما +دموعي +دموي +دمويا +دموية +دمى +دمي +دمياط +دميان +دمية +دميرة +دنا +دنانير +دندرة +دندشي +دندني +دنس +دنفر +دنقل +دنكسن +دنوا +دنوت +دنيا +دنيانا +دنياه +دنياهما +دنياي +دنيس +دنيور +دنيوي +دنيوية +ده +دها +دهاء +دهاك +دهان +دهراً +دهسها +دهش +دهشاً +دهشة +دهشته +دهشتها +دهشتهم +دهشتي +دهشًا +دهلي +دهليز +دهمتها +دهن +دهوراً +دهوك +دهون +دو +دواء +دواءين +دوائر +دوائرنا +دوائرها +دوائي +دوائياً +دوائية +دواب +دوابهم +دواخل +دواخلها +دوار +دوارات +دوارًا +دواسة +دواستي +دواعي +دوافع +دوافعه +دوافعها +دواليك +دوام +دوامات +دوامة +دوامه +دوامها +دواوين +دواوينها +دواويني +دوبلكس +دوبيتران +دوتش +دوجلاس +دوخنا +دودة +دودو +دودي +دور +دورا +دورات +دوراتها +دوران +دورانها +دوراً +دورة +دورةً +دورتها +دورتين +دوركاس +دورنا +دوره +دورها +دورهم +دوروثيا +دوري +دوريات +دورياتهم +دوريان +دورية +دورين +دورًا +دورٍ +دوز +دوزا +دوفان +دوق +دول +دولا +دولاب +دولاباً +دولار +دولارا +دولارات +دولاراً +دولارين +دولارًا +دولاكروا +دولاً +دولة +دولتنا +دولتهم +دولتي +دولتين +دولفين +دولفينا +دولنا +دولها +دولهم +دولي +دوليا +دوليان +دولياً +دولية +دوليون +دوليين +دوليًّا +دوم +دوما +دوماً +دومو +دومون +دومينيك +دومًا +دون +دونانا +دونكن +دونكيشوتية +دونم +دونما +دونمات +دونماً +دوننا +دونه +دونها +دوني +دونية +دوهني +دوى +دوي +دويا +دوّامة +دوّت +دوّنها +دوّى +دى +دي +دياب +ديار +دياركم +ديارنا +ديارها +ديارهم +ديافينيج +ديان +ديب +ديباجة +ديبانكار +ديبوفوار +دية +ديترويت +ديتريش +ديدان +دير +ديركله +ديزاين +ديزل +ديزنى +ديزني +ديس +ديساي +ديسك +ديسمبر +ديسيبل +ديفيد +ديفيز +ديك +ديكا +ديكتاتورا +ديكتاتوريات +ديكستر +ديكور +ديل +ديلا +ديلاتشيلا +ديلاكروا +ديلمون +ديلويت +ديليب +ديمتريو +ديمقراطي +ديمقراطيا +ديمقراطياً +ديمقراطية +ديمقريطس +ديملر +ديموقراطية +ديمومة +دين +دينا +دينار +دينارا +دينارين +دينارًا +دينامي +ديناميا +ديناميات +دينامية +ديناميت +ديناميتها +ديناميكية +ديناً +دينك +ديننا +دينه +دينها +دينهام +دينهم +ديني +دينية +دينيًّا +دينًا +دينٌ +ديهم +ديوان +ديواناً +ديوانك +ديوانه +ديوانها +ديواني +ديوانًا +ديوبند +ديوبندورف +ديوتى +ديودوروس +ديور +ديوك +ديون +ديونز +ديونها +دييجو +دَرَجَاتٍ +دَرَوْهُ +دَعَتَها +دُبَيْب +دُخانا +دُرِسَتْ +دُعيَ +دُفن +دُوز +دُونَ +دُويْن +دِيَارِهِمْ +ذ +ذئاب +ذئب +ذا +ذائدا +ذائع +ذابت +ذابلة +ذات +ذاتـية +ذاتنا +ذاته +ذاتها +ذاتهم +ذاتي +ذاتيا +ذاتياً +ذاتية +ذاتين +ذاتيًا +ذاع +ذاعت +ذاق +ذاك +ذاكرا +ذاكراتي +ذاكراً +ذاكرة +ذاكرةً +ذاكرتك +ذاكرتنا +ذاكرته +ذاكرتها +ذاكرتهم +ذاكرتي +ذاكرنا +ذاكري +ذاكرًا +ذان +ذاهبا +ذاهبة +ذاهبون +ذاهل +ذاهلا +ذبابة +ذبالتها +ذبح +ذبذبة +ذبلت +ذخائر +ذخرها +ذخيرة +ذر +ذرات +ذراته +ذراع +ذراعا +ذراعاً +ذراعه +ذراعي +ذراعين +ذراعيه +ذراعيها +ذرة +ذرةْ +ذرعاً +ذرف +ذروة +ذروته +ذروتها +ذرى +ذري +ذرية +ذريتك +ذريته +ذريعا +ذرّة +ذعراً +ذعروا +ذقنه +ذقنَه +ذقنَهُ +ذكاء +ذكاءه +ذكائه +ذكر +ذكراه +ذكراها +ذكراهم +ذكراً +ذكرت +ذكرتم +ذكرتنا +ذكرته +ذكرتها +ذكرتهم +ذكرنا +ذكرناه +ذكرناها +ذكرني +ذكره +ذكرها +ذكرهم +ذكروا +ذكرى +ذكريات +ذكرياته +ذكرياتي +ذكور +ذكوري +ذكورية +ذكوريّ +ذكي +ذكيا +ذكية +ذل +ذلك +ذلكم +ذلكَ +ذللك +ذله +ذليل +ذمة +ذنب +ذنباً +ذنبه +ذنبها +ذنوبه +ذهابا +ذهاباً +ذهابنا +ذهابها +ذهابهم +ذهابهن +ذهابي +ذهانية +ذهب +ذهبا +ذهباً +ذهبت +ذهبنا +ذهبوا +ذهبى +ذهبي +ذهبيات +ذهبية +ذهبيتان +ذهل +ذهلت +ذهن +ذهنك +ذهنه +ذهنها +ذهنهم +ذهني +ذهنيا +ذهنياً +ذهنية +ذهول +ذو +ذوات +ذواتنا +ذواتهم +ذواقًا +ذواكر +ذوبان +ذوق +ذوقك +ذوو +ذوى +ذوي +ذويه +ذويها +ذويهم +ذويهما +ذى +ذي +ذيل +ذيلا +ذيله +ذيلها +ذيوع +ذَكَرٍ +ذَلِكَ +ذُخْر +ذُكر +ذُو +ر +رءوس +رءوسنا +رءوسهم +رءوسهن +رآنا +رآني +رآه +رآها +رآهم +رآهن +رأت +رأتني +رأته +رأس +رأسا +رأساً +رأسك +رأسمال +رأسماله +رأسمالي +رأسمالياً +رأسه +رأسها +رأسهم +رأسي +رأسيا +رأسَهُ +رأوا +رأوه +رأوْه +رأى +رأي +رأيا +رأياً +رأيت +رأيتك +رأيتم +رأيتموها +رأيتني +رأيته +رأيتها +رأيك +رأيكم +رأيكِ +رأينا +رأيناه +رأيناها +رأيه +رأيها +رأيهم +رأيي +رأيين +رأيًا +رأيٌ +رؤاه +رؤساء +رؤساءه +رؤسائه +رؤوس +رؤوسنا +رؤوسها +رؤوسهم +رؤوف +رؤى +رؤيا +رؤية +رؤيتنا +رؤيته +رؤيتها +رؤيتهم +رؤيتي +رئات +رئاسة +رئاسته +رئاستها +رئاسي +رئاسيا +رئاسية +رئة +رئتاي +رئته +رئتيه +رئتيها +رئتيّ +رئويّ +رئيس +رئيسا +رئيسان +رئيساً +رئيسة +رئيسه +رئيسها +رئيسى +رئيسي +رئيسيا +رئيسيان +رئيسياً +رئيسية +رئيسيتين +رئيسيين +رئيسيّ +رئيسيًّا +رئيسًا +را +راءول +رائجة +رائحا +رائحة +رائحته +رائحتي +رائد +رائدا +رائدان +رائداً +رائدة +رائدًا +رائع +رائعا +رائعاً +رائعة +رائعته +رائعتها +رابضا +رابضة +رابط +رابطا +رابطة +رابطت +رابع +رابعا +رابعاً +رابعة +رابينوفيتش +راتب +راتباً +راتبه +راتبي +راتشيل +راتينستير +راجع +راجعاً +راجعت +راجعتني +راجعته +راجعنا +راجعني +راجية +راجيف +راح +راحة +راحةً +راحت +راحته +راحتهم +راحه +راحوا +راحيل +رادع +رادعاً +رادعة +رادو +راديسون +راديكالية +راديو +راس +راسب +راسة +راسخ +راسخة +راسخةٌ +راسك +راسم +راسماً +راسه +راسية +راسين +راشد +راشيل +راض +راضة +راضون +راضى +راضي +راضيا +راضية +راضين +راضيًا +راضٍ +راعى +راعي +راعيا +راعية +راعٍ +رافد +رافدا +رافداً +رافضا +رافضة +رافضًا +رافع +رافعات +رافعة +رافعي +رافعًا +رافق +رافقت +رافقتنا +رافقتني +رافقته +رافقنا +رافقه +رافقها +رافين +راق +راقات +راقبت +راقبه +راقت +راقدة +راقص +راقصا +راقصة +راقصي +راقني +راقي +راقية +راكاح +راكب +راكباً +راكبي +راكبًا +راكدا +راكضا +راكضة +راكضًا +رالف +رام +راماي +رامبو +رامز +رامي +ران +راهب +راهبات +راهن +راو +راوالبندي +راود +راودتني +راودني +راوند +راوية +راي +رايات +راية +رايةُ +رايت +رايته +رايتهما +رايحين +رايس +راينا +رايني +رايي +رب +ربات +رباح +رباط +رباطة +رباعي +رباعيات +رباعية +رباني +ربانية +ربة +ربت +ربتت +ربحية +ربط +ربطا +ربطة +ربطت +ربطتهم +ربطه +ربطها +ربطوا +ربع +ربعا +ربعه +ربك +ربكة +ربكم +ربما +ربنا +ربه +ربو +ربوة +ربوع +ربوعها +ربوية +ربي +ربيبتها +ربيع +ربيعا +ربيعاً +ربيعة +ربيعها +ربيعي +ربيعًا +ربّت +ربّما +ربّها +ربّى +ربًّا +ربَّة +ربَّك +رت +رتب +رتبة +رتبها +رتبوا +رتقها +رتلاً +رتوش +رتيبة +رتّب +رثة +رثًّا +رج +رجاء +رجاءً +رجائي +رجات +رجال +رجالا +رجالات +رجالاته +رجالاً +رجاله +رجالها +رجب +رجت +رجح +رجحان +رجحت +رجس +رجساً +رجع +رجعة +رجعت +رجعوا +رجعي +رجعياً +رجفان +رجفة +رجل +رجلا +رجلان +رجلاً +رجلك +رجله +رجلها +رجلي +رجلين +رجليه +رجلٍ +رجوع +رجوعا +رجوعه +رجوك +رجولة +رجولتي +رحاب +رحابة +رحابتها +رحابه +رحابها +رحالة +رحالنا +رحالها +رحاها +رحب +رحبا +رحباني +رحبة +رحبت +رحبوا +رحت +رحـلات +رحـلاتها +رحـمه +رحل +رحلات +رحلاته +رحلاتها +رحلاتهم +رحلاتي +رحلة +رحلت +رحلتك +رحلتنا +رحلته +رحلتها +رحلتهم +رحلتي +رحلتين +رحلنا +رحلوا +رحم +رحمة +رحمته +رحمه +رحمها +رحمهم +رحمون +رحمين +رحومًا +رحية +رحيق +رحيل +رحيله +رحيلها +رحيلهم +رحيلي +رحيم +رحيماً +رحيمة +رحّالة +رخاء +رخامي +رخص +رخصا +رخصة +رخواً +رخوة +رخويات +رخيص +رخيصا +رخيصة +رد +ردا +رداء +رداءة +رداً +ردة +ردت +ردح +ردحا +ردد +رددت +ردده +رددها +ردع +ردعاً +ردعه +ردم +ردمها +ردني +رده +ردها +ردهاتها +ردهم +ردود +ردوده +ردي +رديء +ردية +ردًًا +ردّ +ردّت +ردّد +ردّك +ردّه +ردّها +ردًّا +ردَّ +ردُّ +رذاذ +رذاذات +رذيلة +رزانة +رزحت +رزق +رزقا +رزقت +رزقكم +رزقنا +رزقه +رزقهم +رزقي +رزم +رزمة +رزين +رس +رسا +رسائل +رسائلنا +رسائله +رسائلها +رسائلهم +رسائلي +رسالة +رسالتك +رسالتنا +رسالته +رسالتها +رسالتهم +رسالتي +رسالتين +رسام +رساما +رساماً +رسبت +رسل +رسم +رسما +رسمت +رسمته +رسمتها +رسمتُ +رسمه +رسمها +رسموا +رسمي +رسميا +رسمياً +رسمية +رسميًا +رسه +رسوبي +رسوبية +رسول +رسولا +رسوله +رسوم +رسوما +رسومات +رسوماته +رسوماتها +رسوماتهم +رسوماتي +رسوماً +رسومها +رسّخت +رسّخها +رش +رشاد +رشاقة +رشح +رشحات +رشحت +رشحته +رشحني +رشد +رشدي +رشرشات +رششت +رشف +رشفة +رشفته +رشفوا +رشه +رشوان +رشيد +رشيق +رشيقة +رشّه +رصاص +رصاصا +رصاصات +رصاصاً +رصاصة +رصانة +رصانةً +رصد +رصدت +رصدنا +رصده +رصدها +رصف +رصيد +رصيدا +رصيداً +رصيدك +رصيدنا +رصيده +رصيدي +رصيف +رصين +رض +رضا +رضاء +رضاك +رضاه +رضخت +رضوان +رضوخ +رضوض +رضوى +رضوي +رضى +رضي +رضية +رضيع +رضيعها +رضيعًا +رضينا +رطب +رطبا +رطبة +رطبها +رطبًا +رطل +رطلاً +رطوبة +رع +رعاة +رعاف +رعاني +رعاها +رعاياه +رعاياها +رعاياهم +رعاية +رعايته +رعايتهم +رعب +رعبا +رعبهم +رعبٌّ +رعتها +رعد +رعشة +رعنان +رعونة +رعيته +رعيتها +رعيتهِ +رعيل +رعيلاً +رفات +رفادات +رفاعة +رفاق +رفاقاً +رفاقه +رفاقي +رفاه +رفاهة +رفاهية +رفجان +رفح +رفد +رفدها +رفض +رفضت +رفضه +رفضها +رفضهم +رفضوه +رفع +رفعة +رفعت +رفعتها +رفعتْ +رفعنا +رفعناه +رفعه +رفعها +رفق +رفقة +رفقها +رفوف +رفيع +رفيعا +رفيعاً +رفيعة +رفيعًا +رفيف +رفيق +رفيقاتها +رفيقة +رفيقتها +رفيقك +رفيقنا +رفيقه +رفيقيه +رفْض +رقائق +رقابة +رقابهم +رقابي +رقابية +رقاقة +رقاقته +رقباء +رقبة +رقبته +رقبتي +رقة +رقتك +رقدته +رقر +رقش +رقص +رقصات +رقصة +رقصنا +رقع +رقعة +رقم +رقما +رقماً +رقمه +رقمية +رقيب +رقيبه +رقيق +رقيقا +رقيقاً +رقيقة +رقّموها +ركائز +ركاب +ركابه +ركابها +ركارت +ركام +ركب +ركبة +ركبت +ركبتني +ركبتيه +ركبوا +ركبي +ركته +ركز +ركزا +ركزت +ركزوا +ركض +ركضت +ركضٍ +ركع +ركعا +ركعة +ركعتين +ركلها +ركن +ركنا +ركنان +ركناً +ركنتُها +ركنين +ركنًا +ركوب +ركود +ركوداً +ركون +ركيزة +ركيزتان +ركيزتين +ركّز +ركّزت +رماد +رماده +رمادهم +رمادية +رماك +رمال +رماه +رماها +رمته +رمحها +رمز +رمزا +رمزاً +رمزت +رمزي +رمزيا +رمزية +رمسيس +رمشة +رمضان +رمضاني +رمق +رمقنا +رمقه +رمل +رملي +رملية +رمم +رموز +رموزها +رمى +رمي +رمية +رميـ +رن +رنبديل +رنة +رنين +رنينه +ره +رهائن +رهان +رهبان +رهبة +رهص +رهصت +رهن +رهنا +رهيب +رهين +روائح +روائع +روائي +روائياً +روائية +روابط +رواتب +رواتبهم +رواج +رواجا +رواجاً +رواجها +رواجًا +رواد +روادا +رواداً +رواده +روادها +رواسب +روافد +رواق +روالبندي +روان +رواندا +رواه +روايات +رواياتك +رواياته +رواياتهم +رواياتي +رواية +روايتان +روايتك +روايته +روايتها +روايتي +روب +روباكن +روبرت +روبرتس +روبرتية +روبرستون +روبي +روبية +روبيرون +روتردام +روتردمام +روتنبرج +روتين +روتينية +روجت +روجر +روح +روحا +روحاني +روحانية +روحاً +روحنا +روحه +روحها +روحي +روحية +روحيهما +روحًا +رودس +روز +روزفلت +روزماري +روزنامة +روس +روسا +روسو +روسي +روسيا +روسية +روسيين +روش +روشتات +روضة +روضتان +روع +روعة +روعت +روعه +روعى +روعي +روعيت +روفائيل +رول +رولاند +رولانديس +روما +رومان +رومانتيكي +رومانسي +رومانوس +روماني +رومنطيقياً +رومنطيقية +رومي +روميانتسيف +روميل +رونالد +رونالدو +رونقا +رونقاً +رونقًا +روى +روي +رويا +رويال +روية +رويت +رويج +رويدا +رويداً +روّاد +روّادها +روّجت +روَّاد +ري +رياء +رياح +رياحين +ريادة +رياض +رياضة +رياضي +رياضيا +رياضيات +رياضية +ريال +ريالاً +ريان +رياناً +ريب +ريبانكس +ريبة +ريبموند +ريبورتاجات +ريبَ +ريتشارد +ريتشاردز +ريتشمان +ريثما +ريجان +ريح +ريحان +ريحانا +ريختر +ريد +ريزا +ريزنس +ريش +ريشة +ريشتك +ريشته +ريشه +ريشها +ريع +ريعان +ريعه +ريعها +ريعي +ريف +ريفل +ريفولي +ريفي +ريفية +ريفيرا +ريقا +ريقه +ريقها +ريكيافيك +ريلاكس +ريلكه +ريمارك +ريمان +ريمر +ريمو +ريمون +ريموند +رينارد +رينو +رينيه +ريو +ريّ +ريّها +رَبَّة +رَبَّتك +رَبُّهُمْ +رَجعَة +رَجْعَة +رَويَّها +رُجار +رُحل +رُزقت +رُشحت +رُصدت +رُفض +رُفعت +رُفِعَتْ +رِجل +رِجَالٌ +رّئويّ +رَّبِّ +ز +زئبقي +زئير +زائد +زائدا +زائداً +زائدة +زائدتيه +زائر +زائرا +زائراً +زائرة +زائره +زائريه +زائريهم +زائرًا +زائف +زائفة +زائل +زائلا +زائلة +زات +زاحفة +زاحفين +زاحمتهم +زاخر +زاخرا +زاخرة +زاد +زادا +زاداً +زادت +زادته +زاده +زادًا +زار +زارا +زارت +زارتنا +زارتني +زارحي +زارع +زارنا +زاره +زارها +زاروا +زاروب +زازا +زاعماً +زاعمين +زاكسن +زال +زالت +زالوا +زامبيا +زامة +زامل +زاهد +زاهدا +زاهر +زاهن +زاهي +زاهية +زاوية +زاويته +زاويتي +زايد +زايلر +زبائن +زبائنه +زبدة +زبدها +زبيب +زبيبة +زبيد +زبيدة +زج +زجاج +زجاجات +زجاجاتهم +زجاجة +زجاجته +زجاجه +زجاجها +زجاجي +زجاجية +زجت +زجر +زجراً +زحام +زحاماً +زحف +زحفت +زحل +زحمة +زخارف +زخارفه +زخرف +زخرفة +زخرفها +زخرفيان +زخرفية +زخريّا +زخم +زخماً +زخمة +زد +زر +زراعات +زراعاتهم +زراعة +زراعتها +زراعي +زراعية +زراعيين +زراعيًّا +زرافات +زرت +زرته +زرتها +زرد +زرزور +زرع +زرعناها +زرعه +زرعها +زرق +زرقاء +زرقة +زرناه +زرناها +زرنيخ +زري +زرياب +زريق +زعامة +زعق +زعقت +زعلت +زعلي +زعم +زعماء +زعمائه +زعمهم +زعموا +زعنفته +زعيم +زعيما +زعيمها +زعيمهم +زفاف +زفافها +زفافهما +زفر +زفراتي +زفس +زفيرا +زقاق +زقر +زقزقاتها +زقزقة +زقطان +زقورات +زكاة +زكاته +زكام +زكامن +زكري +زكريا +زكور +زكي +زكية +زلة +زلت +زلته +زلزال +زلزالا +زلزالاً +زلزلة +زلل +زلنا +زليتن +زليخة +زمام +زمان +زماننا +زمانه +زمانها +زماني +زمانية +زمبرك +زمرة +زمرتها +زمزم +زمكان +زمكاني +زملاء +زملاؤكم +زملاؤه +زملاؤهم +زملائنا +زملائه +زملائها +زملائهم +زملائي +زمن +زمنا +زمناً +زمننا +زمنه +زمنها +زمنى +زمني +زمنياً +زمنية +زمنين +زمنٍ +زمهرير +زمية +زميل +زميلا +زميلاً +زميلة +زميلتها +زميلتي +زميلنا +زميله +زميلها +زميلي +زناد +زنجبار +زنجي +زنجية +زنزانة +زنكي +زنوج +زهاء +زهدا +زهر +زهران +زهرة +زهرتها +زهرتين +زهور +زهورا +زهيد +زهيدة +زواج +زواجك +زواجنا +زواجه +زواجها +زواجي +زوار +زوارنا +زواره +زواريبه +زوال +زوالها +زوايا +زواياه +زوبعة +زوج +زوجا +زوجات +زوجاتهم +زوجاً +زوجة +زوجته +زوجتي +زوجك +زوجه +زوجها +زوجي +زود +زودت +زوربا +زوركين +زوروا +زوريخ +زوزانثللي +زوزو +زوزي +زويد +زويل +زويلة +زوّدوا +زي +زيا +زياد +زيادات +زيادة +زيادته +زيارات +زياراتنا +زياراته +زياراتها +زياراتي +زيارة +زيارتك +زيارتنا +زيارته +زيارتها +زيارتهم +زيارتهما +زيارتى +زيارتي +زيت +زيتون +زيتية +زيجات +زيجازجروفيتش +زيد +زيدان +زيدت +زيرمات +زيف +زيفاً +زيفه +زين +زينب +زينة +زينت +زينته +زينتها +زينوا +زيهم +زيورخ +زيوريخ +زيوس +زيي +زيّه +زَبَد +زُجّ +زِدْنِي +س +سآتيك +سآخذ +سأبحث +سأبدأ +سأبعث +سأبيع +سأتأقلم +سأتجاوز +سأترك +سأتركك +سأتزوج +سأجد +سأجعل +سأجعله +سأجلب +سأجيب +سأحاول +سأحدث +سأحدثكم +سأحدثكِ +سأحضر +سأحطمك +سأحلم +سأحمل +سأحييها +سأخبر +سأخبرك +سأخفي +سأدخل +سأدق +سأذهب +سأذوق +سأرتدي +سأرتكب +سأرسم +سأروي +سأزعل +سأسأل +سأسبح +سأستمتع +سأستمر +سأسمح +سأسير +سأشتري +سأشرب +سأصادف +سأصبح +سأصعد +سأصل +سأصنع +سأضطر +سأطلب +سأطيق +سأظل +سأعتذر +سأعترف +سأعرف +سأعود +سأفجع +سأفعل +سأفقد +سأقتل +سأقف +سأقلعها +سأقول +سأقوله +سأقولها +سأقوم +سأكسر +سأكمل +سأكون +سأل +سألت +سألتقطها +سألتني +سألته +سألتها +سألك +سألنا +سألناه +سألناها +سألني +سأله +سألها +سألوا +سألوه +سأنام +سأنتظر +سأنتقم +سأنسل +سأنشره +سأهديها +سأوقظك +سؤال +سؤالا +سؤالان +سؤالاً +سؤالك +سؤاله +سؤالها +سؤالي +سؤالين +سئل +سئلت +سئمتُ +ساءت +ساءك +سائح +سائحا +سائحاً +سائحـين +سائحون +سائد +سائدا +سائدان +سائداً +سائدة +سائدًا +سائر +سائرا +سائرًا +سائق +سائقي +سائل +سائلا +سائلاً +سائلة +سائلةً +سائله +سابحا +سابحة +سابق +سابقا +سابقاً +سابقة +سابقتها +سابقين +سابقيه +سابقًا +سابك +سابلين +ساتيس +ساجان +ساجداً +ساجدين +ساجدًا +ساح +ساحات +ساحاته +ساحاتها +ساحة +ساحر +ساحرا +ساحرة +ساحـل +ساحقة +ساحل +ساحلاً +ساحلية +ساخرا +ساخرة +ساخن +ساخنا +ساخناً +ساخنة +ساد +سادة +سادت +سادتي +سادسة +ساذجاً +ساذجة +سار +سارا +سارة +سارت +سارتر +سارتون +سارجنت +سارز +سارس +سارع +سارعت +سارعن +سارعوا +ساروجا +ساروجة +ساروفين +سارياً +سارية +ساس +ساستمر +ساسكاتشوان +ساسون +ساطع +ساعات +ساعة +ساعتان +ساعتنا +ساعته +ساعتها +ساعتين +ساعد +ساعدت +ساعدتنا +ساعدتني +ساعدتها +ساعدنا +ساعدني +ساعده +ساعدونا +ساعدوهم +ساعدي +ساعديني +ساعديه +ساعلقه +ساعي +ساعيا +ساعية +ساعين +سافر +سافرا +سافرات +سافرة +سافرت +سافروا +سافو +ساق +ساقا +ساقاي +ساقبل +ساقط +ساقطاً +ساقطة +ساقه +ساقها +ساقية +ساقيها +ساكس +ساكن +ساكنا +ساكناً +ساكنة +ساكنيه +ساكنيها +سال +سالت +سالس +سالف +سالكاً +سالكين +سالم +سالما +سالماً +سالمون +سالمين +سام +سامة +سامحنى +سامحني +سامر +سامسونج +سامقة +سامى +سامي +سامية +سامٍ +سامّة +سان +سانت +سانتو +سانتياجو +سانتينيكيتان +سانجر +سانحة +ساندتها +ساندرا +ساندى +سانريكو +سانكيتي +ساهرا +ساهرات +ساهم +ساهما +ساهمت +ساهموا +ساونا +سايكس +ساينس +سبأ +سبا +سبائك +سبابته +سبابتُه +سبابَتَهُ +سبات +سباته +سباتها +سباحة +سباحته +سباع +سباعية +سباق +سباقا +سباقات +سباقان +سباقه +سبب +سببا +سبباً +سببت +سببته +سببه +سببها +سببًا +سبتمبر +سبحا +سبحان +سبحانك +سبحانه +سبخة +سبر +سبراطة +سبراي +سبراً +سبع +سبعة +سبعمائة +سبعون +سبعين +سبعينات +سبعيناته +سبعينيات +سبق +سبقا +سبقانا +سبقاً +سبقت +سبقتنا +سبقته +سبقتهم +سبقنا +سبقني +سبقه +سبقها +سبقهم +سبقوا +سبقونا +سبقوني +سبقوه +سبقوها +سبكه +سبل +سبوحة +سبور +سبيس +سبيعي +سبيكة +سبيل +سبيلا +سبيلاً +سبيلك +سبيله +سبيلها +سبيلهم +سبيلٍ +سبيننوزا +سبّاقا +سبّب +ست +ستأخذها +ستأكل +ستؤخذ +ستؤدي +ستائر +ستار +ستارا +ستارة +ستاروود +ستازي +ستافروس +ستافسكي +ستالين +ستان +ستاندرد +ستانفورد +ستانلي +ستايرين +ستبحث +ستبدأ +ستبقى +ستبقي +ستبين +ستة +ستتاح +ستتجاوز +ستتدفق +ستتدهور +ستتزايد +ستتفاوت +ستتقن +ستتلاشي +ستتلقاني +ستتم +ستتمكن +ستتناولين +ستتيح +ستجد +ستجذب +ستجري +ستجعل +ستجلس +ستجيب +ستحافظ +ستحسن +ستحصل +ستحقق +ستحل +ستحلق +ستحلل +ستحمل +ستحملنا +ستحملون +ستخبره +ستختفي +ستخضع +ستدرس +ستدعو +ستذهب +ستر +سترابون +ستراسبورج +ستراني +ستراوسكي +سترة +سترت +سترتاح +سترتفع +سترته +سترجع +ستردد +سترسم +سترلينج +سترمي +سترها +سترونج +سترى +ستريت +ستريه +ستزال +ستزول +ستساعد +ستسافر +ستساهم +ستسببون +ستستثمر +ستستخدم +ستستطيعين +ستستقل +ستسفر +ستسقط +ستسمح +ستسهم +ستسوق +ستسير +ستشاهدين +ستشعر +ستشق +ستشكل +ستشهد +ستصبح +ستصبحين +ستصدرها +ستصرخ +ستصنع +ستضاف +ستضطرني +ستطبق +ستطردين +ستظل +ستظهر +ستعترف +ستعرض +ستعرف +ستعطينا +ستعمل +ستعني +ستعود +ستعيش +ستفتح +ستفرض +ستفعل +ستفهم +ستقاوم +ستقبض +ستقدمها +ستقرؤه +ستقرب +ستقسّم +ستقل +ستقول +ستقولينه +ستقوم +ستكبرين +ستكتئب +ستكتفي +ستكثر +ستكنسون +ستكون +ستكونين +ستلحق +ستلد +ستمائة +ستمثل +ستمر +ستمسح +ستمنح +ستنتهي +ستنجلي +ستنجم +ستندلر +ستنطلق +ستنظمها +ستنفجر +ستنفذ +ستنهار +ستهدأ +ستواجه +ستواجهه +ستواجهها +ستوب +ستور +ستوضع +ستوفر +ستوكل +ستوكهولم +ستون +ستي +ستيرن +ستيف +ستيفانو +ستيفانيل +ستيفن +ستيفنز +ستيفين +ستيكسرود +ستيكل +ستيلار +ستين +ستينيات +ستيوارت +سجادات +سجادة +سجالاً +سجل +سجلات +سجلاته +سجلاً +سجلت +سجلته +سجلتها +سجله +سجلها +سجلوا +سجن +سجنا +سجناء +سجنت +سجنه +سجون +سجى +سجيتها +سجين +سجينا +سجينة +سجّلت +سحائية +سحاب +سحاباً +سحابة +سحاحير +سحال +سحايا +سحب +سحبت +سحبتْ +سحبها +سحبوا +سحر +سحرا +سحراً +سحرته +سحرني +سحره +سحرها +سحرهما +سحري +سحريا +سحرياً +سحرية +سحق +سحقته +سحقها +سحم +سحنة +سحيق +سحيقة +سخاء +سخاروف +سخافاته +سخرت +سخرية +سخطه +سخطها +سخف +سخمت +سخونة +سخونته +سخونتها +سخياً +سخية +سخيفة +سخيّا +سخيَّةً +سخّر +سد +سدادة +سداسي +سدة +سددت +سدها +سدوله +سدى +سدّ +سدّا +سدّهما +سذاجة +سذاجتي +سر +سرا +سراء +سراب +سرابا +سراج +سراح +سراحه +سراحي +سرادق +سرادقات +سراديب +سراعًا +سرايا +سراية +سراييفو +سراً +سرب +سرت +سرج +سرجة +سرجون +سرح +سرحت +سرحد +سرد +سردابٌ +سردابٍ +سرديّة +سرطان +سرطانات +سرطاناً +سرعان +سرعة +سرعته +سرعتها +سرعـة +سرق +سرقات +سرقة +سرقت +سرقتها +سرقـوا +سرقها +سرقوا +سرمد +سرمدية +سرها +سروالاً +سروة +سرور +سروراً +سروره +سرى +سري +سريا +سريان +سريانها +سرية +سرير +سريره +سريرها +سريري +سريرية +سريريه +سريع +سريعا +سريعاً +سريعة +سريعه +سريعًا +سرًا +سرّ +سرّاً +سرّني +سرّها +سرّية +سرًّا +سرٌّ +سرُّ +سطح +سطحه +سطحها +سطحي +سطحيا +سطحية +سطر +سطرا +سطس +سطع +سطعت +سطــح +سطل +سطو +سطوة +سطوتها +سطوح +سطور +سطوره +سطوع +سطوعاً +سع +سعاد +سعادة +سعادته +سعادتها +سعادتهما +سعادتي +سعار +سعال +سعة +سعت +سعتهما +سعد +سعداء +سعدة +سعدت +سعدي +سعدياً +سعر +سعرات +سعره +سعرها +سعرية +سعرًا +سعف +سعفات +سعفص +سعود +سعودة +سعودى +سعودي +سعودياً +سعودية +سعوديون +سعوديين +سعوديًا +سعى +سعي +سعيا +سعياً +سعيت +سعيد +سعيدا +سعيداً +سعيدة +سعيدًا +سعيرها +سعينا +سعيه +سعيها +سعيًا +سـلك +سفاجا +سفاحون +سفارتسشيلد +سفارتها +سفاري +سفالبارد +سفح +سفحك +سفحه +سفر +سفرا +سفراء +سفرات +سفراته +سفراتي +سفرة +سفرك +سفرنامة +سفرنامته +سفره +سفرهم +سفري +سفرياتهم +سفلة +سفلي +سفلية +سفن +سفنها +سفنهم +سفوبودا +سفوح +سفوحه +سفور +سفورزا +سفيان +سفير +سفيرا +سفيراً +سفيرًا +سفينة +سفيه +سقارة +سقاريا +سقاية +سقت +سقراط +سقراطيس +سقط +سقطات +سقطاتها +سقطة +سقطت +سقطوا +سقف +سقفه +سقفها +سقفية +سقفًا +سقمت +سقناه +سقوط +سقوطاً +سقوطه +سكاف +سكاكيني +سكالا +سكان +سكانه +سكانها +سكانية +سكاى +سكب +سكبت +سكة +سكت +سكتت +سكتوا +سكر +سكران +سكرة +سكرتير +سكرتيراً +سكرتيرة +سكريات +سكريبس +سكسي +سكن +سكنا +سكنت +سكنتُ +سكندري +سكنه +سكنها +سكنهم +سكنوه +سكني +سكنيا +سكنية +سكوا +سكوب +سكوت +سكوتر +سكون +سكين +سكينة +سكّان +سكّير +سل +سلاح +سلاحا +سلاحاً +سلاحها +سلاحي +سلاسة +سلاسل +سلاطين +سلاطينهم +سلالا +سلالات +سلالاته +سلالاتهم +سلالة +سلالتها +سلالم +سلاله +سلام +سلاما +سلاماً +سلامة +سلامته +سلامتها +سلامه +سلامي +سلاميّات +سلاّه +سلب +سلبا +سلباً +سلبه +سلبها +سلبي +سلبيا +سلبيات +سلبياتها +سلبياً +سلبية +سلبيين +سلبيًّا +سلة +سلخ +سلخات +سلسالها +سلسة +سلسلة +سلسلتين +سلطات +سلطان +سلطانه +سلطانها +سلطانهم +سلطانيّة +سلطة +سلطت +سلطتنا +سلطته +سلطتها +سلطتهم +سلطنة +سلطنياد +سلع +سلعا +سلعة +سلعتان +سلعتين +سلعيا +سلف +سلفادور +سلفاً +سلفه +سلفياً +سلفية +سلفًا +سلك +سلكه +سلكها +سلم +سلمان +سلماً +سلمتُ +سلمك +سلمنا +سلمى +سلمي +سلمية +سلوان +سلوفانيا +سلوفينيا +سلوقي +سلوك +سلوكاً +سلوكه +سلوكها +سلوكهم +سلوكي +سلوكيا +سلوكيات +سلوكياتنا +سلوكياتهم +سلوكية +سلوى +سليط +سليفرمان +سليل +سليلة +سليلوا +سليم +سليما +سليمان +سليماً +سليمة +سليمتان +سليمين +سلّ +سلّم +سم +سماء +سمات +سماته +سماتها +سماحة +سماحته +سماد +سمارة +سمارت +سماسرة +سماع +سماعا +سماعات +سماعة +سماعنا +سماعيا +سماعياً +سماكة +سماكته +سمان +سماه +سماها +سماوات +سماوي +سماويا +سماوية +سمبل +سمة +سمت +سمته +سمتُهُ +سمح +سمحا +سمحت +سمحوا +سمر +سمراء +سمرة +سمرقند +سمريا +سمسم +سمع +سمعا +سمعان +سمعة +سمعت +سمعته +سمعتها +سمعتُ +سمعتِ +سمعنا +سمعه +سمعها +سمعوا +سمعون +سمعوه +سمعي +سمعية +سمق +سمك +سمكة +سمكه +سمكها +سمن +سمنة +سمنت +سمو +سموالأمير +سموج +سموكم +سموم +سموه +سموها +سمى +سمي +سميت +سميته +سميتهم +سميث +سميدلي +سمير +سميرة +سميرنوف +سميساط +سميع +سميك +سميكة +سمين +سميناً +سمينًا +سميه +سميّة +سمّاه +سمّته +سمّيت +سمّيته +سمًّيا +سمَّاها +سمِّيت +سن +سنا +سنابك +سنارة +سنان +سناً +سنبدأ +سنبقى +سنة +سنتات +سنتان +سنتجاوزها +سنتحدث +سنتر +سنتراجع +سنتعامل +سنتعاون +سنتعرض +سنتناول +سنتناوله +سنتها +سنتهم +سنتي +سنتيمتر +سنتيمترا +سنتيمترات +سنتيمتراً +سنتيمترًا +سنتين +سنثبت +سنج +سنجاي +سنجد +سنجنيها +سنحاول +سنحت +سنحتفل +سنحدد +سنخرج +سند +سندا +سندتني +سندرجها +سندرلاند +سندك +سنديس +سنذهب +سنرسل +سنرى +سنستمتع +سنستوطن +سنسهر +سنصل +سنضع +سنظهر +سنعرض +سنعلمه +سنعود +سنقدم +سنقضي +سنقوم +سنقيم +سنكتفي +سنكون +سنلاحظ +سنمار +سنن +سننتقل +سننقله +سنه +سنوات +سنواتك +سنواته +سنواتي +سنوضحه +سنوك +سنولي +سنونا +سنونو +سنوي +سنويا +سنوياً +سنوية +سنويًا +سنويًّا +سني +سنية +سنيك +سنين +سنًا +سنّ +سنّة +سنَّة +سه +سهر +سهرات +سهرة +سهرنا +سهل +سهلا +سهلاً +سهلة +سهلت +سهم +سهوا +سهول +سهولة +سهير +سهيل +سهّلت +سهَّل +سوء +سوءا +سوءاً +سوءًا +سوا +سواء +سواءً +سوائل +سوابق +سوات +سواتر +سواح +سواحل +سواحلنا +سواد +سوادا +سوادها +سوارا +سواراً +سوانا +سواه +سواها +سواهم +سواهما +سواي +سوبر +سوبرماركت +سوثبي +سوداء +سوداني +سودنة +سور +سورات +سوراً +سورة +سوره +سورها +سوري +سوريا +سوريالياً +سوريالية +سورية +سوريو +سوريون +سوزان +سوزوكي +سوسة +سوسن +سوسو +سوسيكس +سوسيولوجيا +سوسيولوجية +سوطت +سوف +سوفت +سوفييتية +سوق +سوقا +سوقان +سوقاً +سوقرن +سوقها +سوقية +سوكر +سولاريوم +سولاي +سولت +سوما +سومر +سومري +سوميخ +سوناتات +سونجهاي +سوندرز +سوندريجر +سونى +سوني +سوى +سوي +سويا +سوياً +سوية +سويتوا +سويدا +سويدي +سويدية +سويديًا +سويس +سويسرا +سويسري +سويسرياً +سويسرية +سويعات +سويف +سوينا +سوينكا +سويّ +سويّا +سوّى +سى +سي +سيء +سيأتون +سيأتى +سيأتي +سيأخذ +سيأخذنا +سيأكلك +سيؤازره +سيؤثر +سيؤخرني +سيؤدون +سيؤدى +سيؤدي +سيئ +سيئا +سيئاته +سيئة +سيئي +سياتل +سياجا +سياجات +سياجاً +سياح +سياحاً +سياحة +سياحتنا +سياحـة +سياحـى +سياحـية +سياحى +سياحي +سياحيا +سياحياً +سياحية +سياحيين +سيادة +سيار +سيارات +سياراتهم +سياراتهن +سيارة +سيارتك +سيارتنا +سيارته +سيارتها +سيارتي +سيارتين +سياسات +سياساته +سياساتها +سياسة +سياسته +سياسوية +سياسي +سياسيا +سياسياً +سياسية +سياسيين +سياسييه +سياسيًا +سياسيًّا +سياط +سياق +سياقه +سياقها +سياقيا +سياقين +سيالة +سيام +سيان +سياولين +سيبتعد +سيبتلعني +سيبحث +سيبحثه +سيبدأ +سيبقون +سيبقى +سيبكيه +سيتار +سيتارو +سيتبعها +سيتبين +سيتجدد +سيتجول +سيتحقق +سيتخطى +سيتركونه +سيتزامن +سيتسببان +سيتعامل +سيتعجَّب +سيتعين +سيتفاجئ +سيتفق +سيتكفل +سيتلقى +سيتم +سيتمثل +سيتمكن +سيتمكنون +سيتهمه +سيتوقف +سيتي +سيثير +سيجار +سيجارا +سيجارته +سيجارها +سيجد +سيجري +سيجزل +سيجعلنا +سيحاربون +سيحافظ +سيحتاج +سيحتد +سيحجب +سيحدث +سيحدد +سيحصل +سيحقق +سيحكم +سيحل +سيحمل +سيحمله +سيحول +سيحيق +سيحين +سيختلف +سيخرج +سيخصص +سيد +سيدات +سيداتي +سيدافع +سيداً +سيدة +سيدتنا +سيدخل +سيدفع +سيدنا +سيدني +سيدها +سيدي +سيذاكر +سيذكر +سيذهب +سير +سيرا +سيراس +سيراسيتاس +سيراك +سيراكوز +سيراكوزه +سيراليون +سيرة +سيرتك +سيرته +سيرتها +سيرتي +سيرج +سيرفر +سيرفن +سيرفين +سيركز +سيرنا +سيره +سيرها +سيرهم +سيري +سيريز +سيريلانكا +سيرين +سيزان +سيزداد +سيزنز +سيزور +سيزول +سيزيد +سيزيوم +سيساعدك +سيسافر +سيساهم +سيستخدم +سيستطيع +سيستفيد +سيستقبلها +سيستقر +سيستمتعون +سيستمز +سيسجلها +سيسعى +سيسقط +سيسلي +سيسمى +سيسهم +سيسي +سيشاركون +سيشتري +سيشده +سيشرع +سيشهد +سيصاب +سيصبح +سيصف +سيصفعني +سيصل +سيصلك +سيصنعها +سيضاف +سيضبطها +سيضربوننا +سيضطرني +سيضطلع +سيضع +سيضعها +سيضمها +سيطالب +سيطر +سيطربكم +سيطرة +سيطرت +سيطرتها +سيطرتهم +سيطرح +سيطرق +سيطلب +سيطول +سيظل +سيظهر +سيعاد +سيعاقب +سيعتاد +سيعتبرون +سيعزز +سيعطيه +سيعقد +سيعمل +سيعمم +سيعني +سيعود +سيعودان +سيعيد +سيعيش +سيعيشون +سيعيق +سيف +سيفاجأ +سيفرح +سيفرض +سيفشل +سيفقد +سيفه +سيفهمه +سيفين +سيقاطع +سيقام +سيقان +سيقانه +سيقانهم +سيقتحم +سيقتطع +سيقرره +سيقرعون +سيقع +سيقهر +سيقودنا +سيقول +سيقوم +سيكتبه +سيكتم +سيكستوس +سيكلف +سيكلفنا +سيكو +سيكون +سيكونان +سيكونون +سيكوني +سيل +سيلا +سيلازمنا +سيلان +سيلانيز +سيلاً +سيلبير +سيلتقي +سيلزبوري +سيلزم +سيلفر +سيلفريدج +سيلقاه +سيلوستازول +سيليت +سيليو +سيما +سيمثلان +سيمر +سيمفوني +سيمفونيا +سيمفونيان +سيمفونية +سيمفونيته +سيمكن +سيمكنان +سيمكننا +سيملانسكي +سيملك +سيمنحنا +سيموت +سيمون +سين +سينا +سيناء +سيناريو +سيناريوهات +سيناسبيسموس +سيناقشونها +سينالهم +سينامات +سينتج +سينتقل +سينتهج +سينتهي +سينج +سينجارن +سينزعج +سينعكس +سينقصان +سينقطع +سينما +سينمائي +سينمائيا +سينمائية +سينمات +سينماتك +سينماتين +سينهض +سينو +سينوباه +سينورهابديتيتس +سينيك +سيهبط +سيواجه +سيواجهان +سيواجهون +سيوافق +سيور +سيوس +سيوضع +سيوف +سيوفر +سيولة +سييء +سيّدي +سيّما +سيِّئانُ +سيِّئة +سَبِيلِي +سَفَري +سَيَرْحَمُهُمُ +سَيِّئَاتِهِمْ +سُئل +سُجن +سُجِّلت +سُخرت +سُخط +سُدسُ +سُرق +سُقنا +سُقناه +سُلب +سُلّم +سُموا +سُميت +سُميّة +سُميّت +سُمِّي +سُنة +سُنن +سِيَراً +سِيْوَة +سَّرين +ش +شآخرتها +شأن +شأنا +شأناً +شأنه +شأنها +شأنهم +شأني +شأنَ +شؤم +شؤون +شئ +شئت +شئتم +شئنا +شئون +شئونه +شئونها +شا +شاء +شاءوا +شائع +شائعا +شائعات +شائعاً +شائعة +شائقة +شاب +شابا +شاباً +شابة +شابرا +شابلن +شابه +شابها +شابهه +شابهها +شابين +شابّة +شابًّا +شابٌّ +شاتوبريان +شاتيلا +شاحب +شاحبات +شاحباً +شاحبة +شاحنات +شاحنة +شاحنًا +شاخص +شاخصة +شادي +شادية +شاربان +شارحا +شارحًا +شارد +شاردا +شاردة +شارع +شارعا +شارعان +شارعه +شارك +شاركت +شاركته +شاركتهم +شاركنا +شاركني +شاركها +شاركو +شاركوا +شارل +شارلمان +شارلي +شارون +شاستري +شاسعة +شاشات +شاشة +شاطئ +شاطئاً +شاطئه +شاطئها +شاع +شاعت +شاعر +شاعرا +شاعرات +شاعران +شاعراً +شاعرة +شاعرنا +شاعرهم +شاعري +شاعرية +شاعرين +شاف +شافية +شافيًا +شاق +شاقا +شاقة +شاقني +شاكر +شاكرين +شاكل +شاكي +شاكياً +شال +شالسبب +شاله +شاليهات +شامبليون +شامخاً +شامخة +شامخًا +شامل +شاملا +شاملاً +شاملة +شامي +شامية +شانيدار +شاه +شاهد +شاهدا +شاهداً +شاهدة +شاهدت +شاهدتموه +شاهدتها +شاهدنا +شاهدناه +شاهدوا +شاهدًا +شاهدٍ +شاهق +شاهقة +شاهين +شاور +شاوول +شاى +شاي +شايرز +شايف +شايلد +شاينا +شب +شباب +شبابا +شباباً +شبابك +شبابنا +شبابه +شبابها +شبابي +شبابيا +شبابية +شبابيك +شباز +شباط +شباك +شباكا +شباكه +شبان +شببت +شبت +شبح +شبحاً +شبر +شبراً +شبرة +شبعا +شبعان +شبعاً +شبكات +شبكة +شبكيات +شبكياتها +شبكياتهم +شبكية +شبكيته +شبلاج +شبه +شبهة +شبهت +شبهه +شبوح +شبيب +شبيبة +شبيجل +شبيجيل +شبيه +شبيهاً +شبيهة +شبيهًا +شبّاكه +شتاء +شتائمه +شتات +شتارك +شتالو +شتبون +شتبي +شتقول +شتلات +شتلة +شتم +شتمك +شتوية +شتى +شتيرن +شتّى +شجار +شجاع +شجاعا +شجاعة +شجاعتي +شجاعي +شجر +شجرات +شجرة +شجرته +شجع +شجعان +شجعت +شجعتني +شجعته +شجعنا +شجعني +شجعوا +شجون +شجياً +شجية +شجيرات +شجيرة +شجّع +شجَّعه +شح +شحا +شحات +شحاتة +شحاذ +شحت +شحتة +شحدتك +شحذ +شحم +شحمي +شحمية +شحن +شحنات +شحناتها +شحنة +شحنها +شحوم +شحيحة +شحّ +شخب +شخبرة +شخص +شخصا +شخصاً +شخصه +شخصها +شخصي +شخصيا +شخصيات +شخصياته +شخصياتهم +شخصياتي +شخصياً +شخصية +شخصيتك +شخصيتنا +شخصيته +شخصيتها +شخصيتهم +شخصيتي +شخصيتين +شخصين +شخصيًا +شخصيًّا +شخصًا +شخطت +شخوص +شخيرهم +شخّصت +شد +شدا +شدات +شداد +شدة +شدتني +شدته +شدتها +شدد +شدقية +شدني +شده +شديد +شديدا +شديداً +شديدة +شديدي +شديدًا +شدّني +شدّولي +شذاها +شذرات +شر +شرا +شراء +شراءه +شراءها +شراؤها +شرائح +شرائط +شرائه +شرائها +شرائية +شراباً +شرار +شرارات +شرارة +شراسة +شراستهم +شراشف +شراع +شراعية +شراك +شراكة +شراها +شراهتها +شرايك +شرايين +شرايينها +شراً +شرب +شربت +شرجي +شرح +شرحاً +شرحت +شرحته +شرحنا +شرحه +شرحها +شرخا +شرخاً +شرخت +شرد +شردهم +شرذمة +شرس +شرسة +شرسق +شرط +شرطا +شرطاً +شرطة +شرطى +شرطي +شرطيا +شرطيان +شرطيين +شرع +شرعت +شرعتم +شرعها +شرعي +شرعيا +شرعية +شرعيته +شرعيتها +شرعيًا +شرعيًّا +شرعًا +شرف +شرفا +شرفاء +شرفات +شرفة +شرفت +شرفها +شرفية +شرق +شرقا +شرقاً +شرقه +شرقها +شرقي +شرقيا +شرقية +شرقيون +شرقًا +شرك +شركا +شركاء +شركائها +شركائهم +شركات +شركاته +شركاتها +شركاتهم +شركة +شركةً +شركتنا +شركته +شرلوك +شرم +شرنقتها +شرها +شروخا +شرور +شروره +شروط +شروطاً +شروطه +شروطها +شروطًا +شروق +شروقها +شروى +شريان +شريبة +شريحة +شرير +شريرة +شريط +شريطا +شريطان +شريطاً +شريطة +شريطه +شريطًا +شريطٌ +شريعة +شريف +شريفاً +شريفة +شريك +شريكا +شريكاً +شريكة +شريكنا +شريكين +شرِّ +شزر +شزرا +شسويتوا +شصار +شط +شطآن +شطح +شطر +شطري +شطط +شطين +شظايا +شظف +شظية +شعائرها +شعاب +شعابا +شعابنا +شعابه +شعار +شعارا +شعارات +شعاراتها +شعاراً +شعاره +شعارها +شعارهم +شعارًا +شعاع +شعاعها +شعاعية +شعب +شعبا +شعبان +شعباً +شعبة +شعبتين +شعبك +شعبنا +شعبه +شعبها +شعبهم +شعبي +شعبيا +شعبياً +شعبية +شعبيتها +شعبينا +شعبيًّا +شعبًا +شعث +شعر +شعرا +شعراء +شعرائنا +شعرائها +شعرات +شعراوي +شعراً +شعرة +شعرت +شعرك +شعرنا +شعره +شعرها +شعرهم +شعروا +شعري +شعريا +شعرياً +شعرية +شعريًا +شعريّ +شعشع +شعشعت +شعلة +شعواء +شعوب +شعوبا +شعوبنا +شعوبه +شعوبها +شعوبهم +شعوبية +شعور +شعورا +شعوراً +شعورك +شعورنا +شعوره +شعورهم +شعورهن +شعوري +شعورية +شعورًا +شعيرات +شعيراتها +شعيرتين +شـهر +شـوقى +شف +شفاء +شفاءً +شفائه +شفائها +شفائي +شفاعة +شفافا +شفافة +شفافية +شفاه +شفاهة +شفاهي +شفايزر +شفة +شفت +شفتاكْ +شفتاه +شفتاها +شفته +شفتيه +شفتيها +شفتيهِ +شفرة +شفش +شفط +شفطها +شفعت +شفقة +شفقتي +شفيت +شفيق +شفَقا +شق +شقا +شقاء +شقائق +شقال +شقة +شقت +شقتك +شقته +شقتي +شقراء +شقرة +شقق +شققت +شققني +شقها +شقهم +شقوق +شقيق +شقيقات +شقيقاتها +شقيقة +شقيقته +شقيقتي +شقيقتيها +شقيقه +شقيقي +شقيقَه +شقيقَهُ +شقيقِه +شقين +شقّت +شقّها +شك +شكا +شكاكة +شكاوى +شكاوي +شكت +شكتها +شكر +شكرا +شكراً +شكرت +شكره +شكري +شكسبير +شكسبيرية +شكل +شكلا +شكلاً +شكلت +شكلتا +شكلتها +شكله +شكلها +شكلي +شكلية +شكلين +شكلِها +شكواه +شكواي +شكوت +شكور +شكوك +شكوكو +شكوى +شكيب +شكيت +شكّل +شكّلت +شكَّ +شل +شلاج +شلة +شلل +شللي +شلوف +شلون +شمائله +شمائلها +شمال +شمالا +شمالاً +شماله +شمالها +شمالي +شمالية +شمر +شمرا +شمروا +شمس +شمسا +شمسه +شمسها +شمسي +شمسية +شمسيته +شمسيتين +شمع +شمعة +شمعون +شمل +شملت +شملني +شملها +شموخا +شموخك +شمولاً +شموليا +شمولية +شمية +شميدت +شميما +شمّاء +شناق +شنايدر +شنتها +شندي +شنقول +شنو +شنوا +شنيعة +شنّ +شهاب +شهادات +شهاداتهم +شهادة +شهادتها +شهادتهم +شهادتين +شهادتَيْ +شهامتي +شهد +شهداء +شهداءها +شهدت +شهدته +شهدتها +شهدنا +شهدناه +شهده +شهدها +شهر +شهرا +شهران +شهراً +شهرة +شهرته +شهرتها +شهرزاد +شهري +شهريا +شهريار +شهرياً +شهرية +شهرين +شهريًا +شهرًا +شهــرة +شهقات +شهقة +شهماً +شهمًا +شهمٍ +شهوانية +شهوة +شهوته +شهوتهم +شهود +شهور +شهورا +شهوراً +شهية +شهيته +شهيتي +شهيد +شهيدًا +شهير +شهيرا +شهيراً +شهيرة +شو +شواء +شوائب +شوائبها +شواذ +شواذا +شوارع +شوارعنا +شوارعها +شوارعِ +شواطئ +شواطئنا +شواطئه +شواطئها +شواطئهم +شوال +شوالٍ +شواهد +شوبان +شوتاواي +شوتايم +شورك +شوسكا +شوشة +شوشـــة +شوط +شوطاً +شوطًا +شوف +شوفو +شوق +شوقا +شوقي +شوكة +شوكتهم +شوكولاتة +شوكيات +شوكية +شولتز +شونتو +شوهت +شوهد +شوي +شويك +شويه +شي +شيء +شيءٍ +شيءَ +شيئ +شيئا +شيئان +شيئاً +شيئين +شيئًا +شياطين +شيب +شيبارد +شيبة +شيبس +شيبوب +شيت +شيجانوفا +شيخ +شيخا +شيخك +شيخنا +شيخه +شيخوخة +شيخوخته +شيخون +شيخي +شيخين +شيد +شيدت +شيده +شيدها +شيراتون +شيراز +شيرشوف +شيرين +شيش +شيطان +شيطانيا +شيطانية +شيعت +شيفرة +شيفرته +شيق +شيقاً +شيقة +شيك +شيكا +شيكات +شيكل +شيكلا +شيكلاً +شيكولاتة +شيلي +شيماس +شيمل +شيمه +شين +شينج +شيني +شينيانج +شيوخ +شيوخاً +شيوخه +شيوع +شيوعا +شيوعاً +شيوعي +شيوعًا +شيّدته +شيّدتها +شيّعهم +شَعرها +شَعْر +شُرح +شُرع +شُعُوبًا +شُنق +شُهر +شُيِّدت +ص +صائب +صائبا +صائبة +صائد +صائم +صابورات +صاح +صاحب +صاحبة +صاحبت +صاحبته +صاحبتها +صاحبك +صاحبنا +صاحبه +صاحبها +صاحبوا +صاحبوني +صاحبي +صاحبيها +صاحت +صاحـب +صاحوا +صاخب +صاخبة +صادح +صادر +صادرا +صادرات +صادراتها +صادرة +صادرت +صادف +صادفتنا +صادفتني +صادفنا +صادفه +صادق +صادقا +صادقاً +صادقة +صادقوا +صادم +صادمة +صار +صارت +صارتا +صارجدامي +صارحيني +صارخ +صارخا +صارخة +صارخًا +صارم +صارمة +صاروا +صاروخ +صاروخي +صاعد +صاعدا +صاعداً +صاعدة +صاعقة +صاف +صافحته +صافحنا +صافياً +صافية +صافِقاً +صال +صالات +صالة +صالح +صالحا +صالحاً +صالحة +صالحنا +صالحًا +صالون +صالونات +صالوناً +صامت +صامتا +صامتاً +صامتة +صامتين +صامدا +صامدة +صامويل +صاند +صانع +صانعة +صانعه +صانعو +صانعي +صانعيها +صب +صباح +صباحا +صباحاته +صباحاً +صباحـاً +صباحه +صباحها +صباحهم +صباحية +صباحًا +صبان +صباه +صباها +صباي +صبايا +صببت +صبح +صبحي +صبر +صبره +صبرى +صبري +صبرَهُ +صبها +صبوحاً +صبوراً +صبي +صبيا +صبيان +صبياً +صبية +صبيحة +صبيًّا +صبّ +صبّتها +صبّوا +صة +صج +صح +صحائف +صحائفهم +صحار +صحارى +صحاري +صحافتهم +صحافيا +صحافيون +صحافيين +صحبة +صحبت +صحبته +صحبتهم +صحبتي +صحبني +صحة +صحت +صحته +صحتها +صحتهم +صحتي +صحح +صحراء +صحراوات +صحراوي +صحراوية +صحف +صحفنا +صحفى +صحفي +صحفيا +صحفيان +صحفياً +صحفية +صحفيون +صحفًا +صحن +صحوات +صحوة +صحوتها +صحونا +صحي +صحيا +صحياً +صحية +صحيح +صحيحا +صحيحاً +صحيحة +صحيحه +صحيفة +صحيفته +صحّ +صحّة +صخب +صخبها +صخر +صخرة +صخرته +صخرية +صخور +صد +صدأ +صدئ +صدار +صدارة +صداع +صداقاتها +صداقة +صداقته +صدام +صدامه +صدامياً +صداها +صدد +صددت +صدر +صدرت +صدرك +صدرنا +صدره +صدرها +صدري +صدرية +صدع +صدف +صدفة +صدق +صدقاً +صدقة +صدقت +صدقته +صدقني +صدقه +صدقها +صدقي +صدقيتها +صدم +صدمة +صدمته +صدور +صدوره +صدورها +صدورهم +صدى +صدىء +صديدية +صديق +صديقا +صديقات +صديقاتها +صديقاً +صديقة +صديقته +صديقتي +صديقك +صديقنا +صديقه +صديقهم +صديقهما +صديقي +صديقين +صدّر +صدّقوني +صر +صراحة +صراحتي +صراخ +صراخه +صراع +صراعا +صراعات +صراعاتهم +صراعاً +صراعهم +صراعهما +صراعي +صراف +صرامته +صرة +صرةُ +صرت +صرتُ +صرح +صرحاً +صرحت +صرحوا +صرخ +صرخة +صرخت +صرختي +صرختُ +صرعات +صرعة +صرعتها +صرف +صرفة +صرفته +صرنا +صروح +صروحاً +صروف +صريح +صريحاً +صريحة +صرير +صريع +صريعاً +صريعة +صرّة +صرّح +صرَّح +صطار +صعب +صعبا +صعباً +صعبة +صعد +صعدا +صعدت +صعدنا +صعصعة +صعلوك +صعوبات +صعوبة +صعوبتها +صعوبتين +صعود +صعودا +صعوداً +صعودنا +صعوده +صعيد +صعيده +صعيدها +صعيدي +صف +صفاء +صفائح +صفات +صفاته +صفاتها +صفاتٍ +صفار +صفارات +صفاقة +صفان +صفة +صفته +صفتها +صفحات +صفحاته +صفحاتها +صفحة +صفحتها +صفحتين +صفحتِهِ +صفر +صفرا +صفراء +صفرة +صفعة +صفق +صفقات +صفقة +صفه +صفو +صفوان +صفوة +صفوت +صفوف +صفوفه +صفوفها +صفوفهم +صفي +صفية +صفيح +صفيحات +صفير +صفيرها +صفًا +صفّ +صفّا +صفّر +صفّق +صفَّقت +صقر +صقع +صقل +صقلية +صقيلاً +صك +صكّ +صلابة +صلابته +صلاة +صلات +صلاته +صلاتهم +صلاح +صلاحها +صلاحيات +صلاحياتها +صلاحية +صلاحيته +صلاحيتها +صلب +صلبة +صلبه +صلة +صلته +صلتها +صلتهم +صلتي +صلح +صلحاً +صلحها +صلواته +صلواتهم +صلى +صليب +صليبا +صليبنا +صليبه +صليبي +صليبية +صلّ +صلّت +صم +صماء +صمام +صماماً +صمت +صمتت +صمتتا +صمتنا +صمته +صمتهما +صمتي +صمتٌ +صمتٍ +صمد +صمدت +صمدوا +صمم +صممت +صممنا +صممناه +صممه +صممها +صموئيل +صموت +صموتا +صمود +صميم +صميمة +صميمي +صمّ +صمّاء +صن +صنابير +صناديق +صناع +صناعات +صناعاتها +صناعاً +صناعة +صناعته +صناعتها +صناعىين +صناعي +صناعيا +صناعياً +صناعية +صنبور +صندالاً +صندوق +صندوقا +صندوقاً +صندوقها +صنع +صنعاء +صنعاني +صنعانية +صنعة +صنعت +صنعته +صنعنا +صنعه +صنعها +صنعوا +صنعية +صنف +صنفت +صنفها +صنم +صنوان +صنوبر +صنوبرة +صنوف +صنيع +صنيعهم +صنّاع +صنّاعه +صنّف +صنّفها +صهر +صهره +صهريج +صهريجا +صهريجه +صهوات +صهيون +صهيوني +صهيونيا +صهيونية +صواب +صوابه +صواريخ +صوامع +صوب +صوبها +صوبي +صوت +صوتا +صوتت +صوته +صوتها +صوتهم +صوتهما +صوتهن +صوتي +صوتية +صوتًا +صوتٌ +صور +صورا +صوراً +صورة +صورت +صورتك +صورتنا +صورته +صورتها +صورتهم +صورتي +صورتين +صورتيه +صورك +صوره +صورها +صوري +صوريا +صورية +صورًا +صوفاً +صوفي +صوفيا +صوفية +صومعة +صومعته +صون +صونها +صوّب +صوّر +صوّرت +صوّره +صوّروا +صياح +صياحه +صياد +صيادا +صيام +صيامه +صيانة +صيت +صيته +صيتها +صيحات +صيحاته +صيحاتٍ +صيحة +صيحته +صيد +صيدا +صيدح +صيدلانيا +صيدلى +صيدليات +صيدلية +صيده +صيدها +صيدون +صيف +صيفاً +صيفها +صيفىين +صيفي +صيفية +صيني +صينية +صيوان +صَبَرُوا +صَدَقُوا +صَعَّد +صَنيعة +صَنيعةَ +صُعق +صُنعت +صُنفت +صِلاته +ض +ضآلته +ضآلتها +ضئيل +ضئيلا +ضئيلاً +ضئيلة +ضائعة +ضائقة +ضائقته +ضابط +ضابطا +ضابطات +ضابطها +ضابطًا +ضاجعت +ضاحك +ضاحكا +ضاحكة +ضاحكين +ضاحية +ضاحيتا +ضار +ضاربا +ضاربة +ضاربي +ضاربين +ضارة +ضارعين +ضاريا +ضارية +ضاع +ضاعت +ضاعف +ضاق +ضاقت +ضاقوا +ضالة +ضالتها +ضامرة +ضامن +ضباب +ضبابية +ضباط +ضباع +ضبط +ضبطت +ضبطه +ضبطها +ضبعا +ضج +ضجة +ضجت +ضجره +ضجيج +ضجيجا +ضجيجه +ضجّت +ضجَّت +ضحايا +ضحاياه +ضحاياها +ضحك +ضحكاتهم +ضحكة +ضحكت +ضحكتهم +ضحكه +ضحكوا +ضحكي +ضحلة +ضحى +ضحية +ضحيته +ضحيتها +ضخ +ضخامة +ضخم +ضخما +ضخماً +ضخمة +ضخمًا +ضخّ +ضد +ضدالقوات +ضدان +ضدك +ضدنا +ضده +ضدها +ضدهم +ضدي +ضدّ +ضراء +ضرائب +ضراعة +ضرب +ضربا +ضربات +ضرباً +ضربة +ضربت +ضربته +ضربه +ضربها +ضربوها +ضرر +ضررها +ضرس +ضرع +ضره +ضرورات +ضرورة +ضرورتها +ضروري +ضروريا +ضروريات +ضرورياً +ضرورية +ضروريًا +ضروريًّا +ضريبة +ضريح +ضع +ضعف +ضعفا +ضعفاء +ضعفاً +ضعفت +ضعفك +ضعفنا +ضعفه +ضعفي +ضعوا +ضعيف +ضعيفا +ضعيفة +ضعيفًا +ضفاف +ضفافه +ضفة +ضفته +ضفتي +ضفتين +ضفتيه +ضفدعة +ضفيرة +ضفيرتي +ضل +ضلال +ضلعي +ضلفة +ضلفتيه +ضللنا +ضلوا +ضلوع +ضلوعه +ضم +ضمآن +ضماد +ضمامة +ضمان +ضمانات +ضماناً +ضمت +ضمته +ضمتها +ضممت +ضممته +ضممنا +ضمن +ضمناً +ضمنته +ضمنه +ضمنها +ضمنوا +ضمنيا +ضمنيّا +ضمنًا +ضمها +ضمور +ضموراً +ضمير +ضميري +ضمّنه +ضننت +ضنين +ضوء +ضوءالقمر +ضوؤها +ضوئها +ضوئي +ضوئيا +ضوئية +ضوابط +ضوابطه +ضواحي +ضواحيها +ضياء +ضياع +ضياعها +ضيافة +ضير +ضيعت +ضيعتها +ضيعناه +ضيعها +ضيف +ضيفا +ضيفة +ضيق +ضيقا +ضيقة +ضيقت +ضيقه +ضيقٌ +ضيوف +ضيوفك +ضيوفه +ضيّق +ضَمَّها +ضُبط +ضُربت +ضُعَيّف +ضِعفاً +ضّيق +ط +طأطأ +طائر +طائرا +طائرات +طائراتها +طائراً +طائرة +طائرته +طائشة +طائعين +طائفة +طائفتان +طائفته +طائفتها +طائفتي +طائفي +طائلة +طاب +طابع +طابعا +طابعات +طابعة +طابعه +طابعها +طابعًا +طابق +طابقاً +طابقين +طابقًا +طابور +طاحونة +طاحونتين +طار +طارئ +طارئا +طارئاً +طارئة +طارئين +طارت +طاردا +طاردنا +طاردني +طارق +طازجة +طاسة +طاستك +طاش +طاشت +طاعة +طاعناً +طاعنة +طاعون +طاف +طافت +طافش +طافوا +طافيا +طافية +طاقات +طاقاته +طاقاتها +طاقة +طاقته +طاقتها +طاقتهم +طاقم +طاقي +طاقية +طاقيًا +طال +طالب +طالبا +طالبات +طالباتها +طالبان +طالباً +طالبة +طالبت +طالبتين +طالبنا +طالبوا +طالبين +طالبيه +طالبًا +طالت +طالع +طالعتنا +طالعته +طالعي +طالما +طالها +طامي +طانيوس +طاهر +طاهراً +طاولات +طاولة +طاولته +طاولتها +طاولتهم +طب +طبائعهم +طباع +طباعة +طبانه +طبخ +طبخهم +طبرق +طبريا +طبرية +طبع +طبعا +طبعات +طبعاً +طبعة +طبعت +طبعته +طبعتها +طبعه +طبعها +طبعهم +طبعي +طبعًا +طبـعه +طبق +طبقا +طبقات +طبقاته +طبقاً +طبقة +طبقت +طبقتها +طبقي +طبقًا +طبلية +طبول +طبوله +طبي +طبيا +طبياً +طبيب +طبيبا +طبيبان +طبيباً +طبيبة +طبيبه +طبيبهم +طبيبًا +طبية +طبيعة +طبيعتنا +طبيعته +طبيعتها +طبيعتي +طبيعي +طبيعيا +طبيعياً +طبيعية +طبيعيين +طبيعيًّا +طبّقت +طبّيًّا +طحلب +طحين +طرأ +طرأت +طرائف +طرائفها +طرائق +طرابلس +طرابلسى +طراز +طرازاتها +طرازه +طرافة +طربوش +طرت +طرح +طرحت +طرحته +طرحه +طرحها +طرحًا +طرد +طردته +طردها +طردهم +طردوا +طردية +طرطور +طرف +طرفا +طرفان +طرفاها +طرفة +طرفه +طرفها +طرفهم +طرفي +طرفًا +طرق +طرقا +طرقات +طرقاً +طرقة +طرقت +طرقتين +طرقها +طرقهم +طرقهن +طرقي +طرقًا +طرنا +طروادة +طروحاته +طري +طريا +طرياً +طرية +طريف +طريفا +طريفة +طريق +طريقا +طريقان +طريقاً +طريقة +طريقتنا +طريقته +طريقتها +طريقتي +طريقتين +طريقك +طريقنا +طريقه +طريقها +طريقهم +طريقهما +طريقي +طريقين +طريقًا +طرَحها +طرّاحة +طرّاحته +طزاجة +طزاجتها +طشقند +طعام +طعاما +طعاماً +طعامكم +طعامنا +طعامه +طعامها +طعامهم +طعامي +طعامًا +طعم +طعما +طعماً +طعمه +طعمها +طعن +طعوم +طـرحت +طفا +طفايات +طفت +طفح +طفرات +طفرة +طفرت +طفل +طفلا +طفلاً +طفلة +طفلته +طفلتها +طفلتين +طفلها +طفلين +طفنا +طفولة +طفولتك +طفولته +طفولتها +طفولتهم +طفولتي +طفولي +طفولياً +طفولية +طفيفا +طفيفة +طفيل +طفيليات +طق +طقاطقة +طقت +طقسا +طقساً +طقسها +طقم +طقوس +طقوسه +طلاءات +طلاءاته +طلائع +طلائعهم +طلائها +طلاب +طلابا +طلابنا +طلابه +طلابها +طلابهم +طلابي +طلابية +طلابًا +طلاس +طلاسم +طلاسمها +طلاق +طلال +طلاوتهما +طلب +طلبا +طلبات +طلباته +طلباً +طلبة +طلبت +طلبته +طلبتها +طلبتُ +طلبنا +طلبه +طلبها +طلبي +طلبًا +طلت +طلخا +طلع +طلعت +طلعنا +طلعوا +طلقات +طلقة +طلمبات +طلميثة +طلوع +طلي +طليعة +طليعتها +طليعتهم +طليعية +طليق +طليقاً +طليقة +طمأنينتك +طماطم +طمحوا +طمس +طمع +طموح +طموحا +طموحات +طموحاتك +طموحاتكم +طموحاته +طموحاتي +طموحة +طموحـات +طموحي +طن +طنافس +طناً +طنجة +طه +طهاة +طهران +طهنا +طهيت +طهيه +طهّرا +طوائف +طوابق +طوابير +طواحين +طوارئ +طواعية +طوافات +طوال +طواه +طواها +طواهم +طوب +طوباس +طوخ +طور +طورت +طورتها +طورد +طوره +طوروا +طوعاً +طوعيا +طوعًا +طوفان +طوفت +طوق +طوقان +طوقتني +طوكيو +طول +طولا +طولانيتان +طولاً +طوله +طولها +طولياً +طولية +طومان +طومانباي +طوى +طويت +طويل +طويلا +طويلاً +طويلاًً +طويلب +طويلة +طويلتان +طويلين +طويناها +طوّرت +طوَّر +طوَّع +طي +طيء +طياته +طياتها +طيار +طياراً +طيارون +طيب +طيبا +طيباً +طيبة +طيبون +طيبين +طير +طيرا +طيران +طيرانه +طيرانها +طيش +طيطوس +طيعة +طيـلة +طيف +طيفاً +طيفه +طيلة +طينته +طينية +طيور +طيوراً +طيوره +طيورها +طيّ +طيّاتها +طيَّب +طيَّرت +طُرح +طُرحت +طُردوا +طُرق +طُرّة +طُفيل +طُلب +ظ +ظالم +ظالما +ظالمة +ظالمنا +ظانا +ظاهر +ظاهرة +ظاهرتان +ظاهرتها +ظاهرها +ظاهريا +ظاهرياً +ظاهريًا +ظبي +ظبياً +ظرف +ظرفه +ظروف +ظروفا +ظروفاً +ظروفه +ظروفهم +ظروفي +ظل +ظلا +ظلال +ظلالا +ظلاله +ظلام +ظلاما +ظلت +ظلتا +ظللنا +ظلم +ظلما +ظلمائه +ظلماً +ظلمة +ظلمنا +ظله +ظلها +ظلوا +ظلي +ظلّ +ظلّت +ظلّها +ظلٌّ +ظلَّ +ظلَّت +ظمأ +ظمأه +ظن +ظنت +ظنته +ظنك +ظننا +ظننت +ظننتك +ظنه +ظنها +ظنهم +ظنوا +ظني +ظنًا +ظهر +ظهرا +ظهراني +ظهرانينا +ظهراً +ظهرت +ظهرك +ظهرنا +ظهره +ظهرها +ظهروا +ظهري +ظهرية +ظهرًا +ظهور +ظهوراً +ظهوره +ظهورها +ظهورهم +ظهورهِ +ظهيرة +ظواهر +ظواهره +ظواهرها +ع +عا +عائد +عائدا +عائدات +عائداتها +عائداً +عائدة +عائده +عائدين +عائدًا +عائذ +عائش +عائشا +عائشة +عائق +عائقا +عائقاً +عائلات +عائلاتهم +عائلة +عائلته +عائلتها +عائلتي +عائله +عائلي +عائلية +عائلين +عاب +عابئ +عابئة +عابئين +عابثة +عابد +عابدون +عابدًا +عابر +عابرا +عابرة +عابرون +عابري +عابرين +عابرًا +عابرِ +عابساً +عابسة +عابق +عابىء +عات +عاتب +عاتبه +عاتق +عاتقه +عاتقها +عاث +عاثت +عاجز +عاجزا +عاجزاً +عاجزة +عاجزون +عاجزين +عاجل +عاجلا +عاجلاً +عاجلة +عاجلها +عاجي +عاد +عادا +عادات +عاداتنا +عاداته +عاداتها +عادة +عادةً +عادت +عادتك +عادته +عادتها +عادتي +عادل +عادلا +عادلة +عادوا +عادى +عادي +عاديا +عاديات +عادياً +عادية +عاديون +عاديًّا +عارض +عارضاً +عارضت +عارضًا +عارف +عارفًا +عارمة +عاري +عاريا +عاريات +عارياً +عارية +عازف +عازفا +عازفون +عازفي +عازفًا +عازل +عازلة +عازم +عاش +عاشت +عاشته +عاشتها +عاشرة +عاشق +عاشقا +عاشقة +عاشه +عاشها +عاشوا +عاشور +عاشوها +عاص +عاصرة +عاصروا +عاصف +عاصفا +عاصفة +عاصمة +عاصمته +عاصمتها +عاصي +عاطرة +عاطف +عاطفة +عاطفي +عاطفية +عاطل +عاطلون +عافاككم +عافاه +عافية +عافيته +عافيتها +عاقبة +عاقبته +عاقدة +عاقدًا +عاقلة +عاكساً +عاكسة +عاكف +عاكفة +عال +عالة +عالتمام +عالج +عالجت +عالجها +عالجهم +عالقة +عالقةً +عالم +عالما +عالمال +عالمان +عالماً +عالمة +عالمنا +عالمه +عالمها +عالمهم +عالمي +عالميا +عالمياً +عالمية +عالميةً +عالمين +عالميون +عالميين +عالميًا +عالميًّا +عالميْن +عالمًا +عالمٍ +عالي +عاليا +عالياً +عالية +عاليتين +عاليًا +عالٍ +عالَمان +عالِم +عالِمي +عام +عاما +عامان +عاماً +عامة +عامةً +عامداً +عامدة +عامدين +عامر +عامراً +عامرة +عامـًا +عامل +عاملا +عاملان +عاملاً +عاملة +عاملتني +عاملته +عامله +عاملوا +عاملي +عامليا +عاملين +عامه +عامها +عامى +عامي +عامية +عاميتها +عامين +عامًا +عامّ +عاناه +عاناها +عانت +عانته +عاندته +عانقني +عانوا +عانى +عانيت +عاهة +عاهدت +عاهدوا +عاود +عاودت +عاودني +عاودوا +عايدوه +عايش +عايشت +عايض +عاين +عاينت +عب +عبء +عبأ +عبئا +عبئاً +عباءة +عباءته +عباءتها +عباب +عباد +عبادة +عباده +عبادي +عبارات +عباراته +عبارة +عبارتان +عبارته +عباس +عباسيا +عبث +عبثا +عبثاً +عبثت +عبثي +عبثية +عبثًا +عبد +عبدالجبار +عبدالحفيظ +عبدالحق +عبدالحكيم +عبدالحليم +عبدالحميد +عبدالر +عبدالرؤوف +عبدالرازق +عبدالرحمن +عبدالرزاق +عبدالرسول +عبدالرشيد +عبدالسلام +عبدالصبور +عبدالصمد +عبدالعزيز +عبدالفتاح +عبدالقادر +عبدالقدوس +عبدالكريم +عبداللطيف +عبدالله +عبدالمحسن +عبدالمطلب +عبدالملك +عبدالمنعم +عبدالناصر +عبدالنبي +عبدالهادي +عبدالوهاب +عبداً +عبدتُك +عبده +عبدهما +عبدو +عبدَ +عبر +عبرات +عبرت +عبره +عبرها +عبرهما +عبروا +عبس +عبـر +عبـرها +عبق +عبقا +عبقر +عبقري +عبقريات +عبقرياته +عبقرية +عبقريته +عبقريتها +عبلة +عبوات +عبواتها +عبود +عبودية +عبوديته +عبور +عبورها +عبورهم +عبيد +عبيدا +عبيداً +عبَّه +عبّر +عبّرت +عبّرتُ +عبَّ +عتاب +عتبات +عتبة +عتبته +عتمة +عتمه +عته +عتيق +عتيقا +عتيلة +عثة +عثر +عثرة +عثرت +عثرنا +عثروا +عثمان +عثمانية +عج +عجائبها +عجاف +عجافٍ +عجب +عجبا +عجبت +عجبهم +عجبًا +عجبَ +عجز +عجزت +عجزنا +عجزه +عجزها +عجزهم +عجزًا +عجفاء +عجل +عجلا +عجلات +عجلاتها +عجلة +عجلت +عجمان +عجوز +عجوزا +عجيب +عجيباً +عجيبة +عجينة +عجيني +عجّل +عجَّلت +عد +عدا +عداء +عدائي +عدائيا +عدائية +عداد +عدادات +عدالة +عداه +عداها +عداهما +عداوات +عداوتهم +عدة +عدت +عدتنا +عدته +عدتَ +عدد +عددا +عددالطيور +عددان +عدداً +عدداَ +عددت +عدده +عددها +عددهم +عددهن +عددًا +عدسات +عدسته +عدل +عدلت +عدم +عدمها +عدن +عدنا +عدنان +عده +عدها +عدو +عدوا +عدوان +عدوانه +عدوانها +عدواها +عدوتك +عدوك +عدوهم +عدوى +عدوي +عدوّ +عدوّاً +عدوّهم +عدي +عديد +عديدات +عديدة +عديدون +عديدين +عديم +عديمة +عدّة +عدّه +عدَّ +عدَّة +عذاب +عذابات +عذاباتك +عذاباتنا +عذاراهن +عذارى +عذب +عذبة +عذبهم +عذبي +عذبيني +عذر +عذرا +عذراء +عذري +عذوبة +عذوق +عذَّبها +عراء +عرائس +عرائض +عراب +عرابها +عرابي +عراجين +عراجينها +عراق +عراقة +عراقتها +عراقي +عراقيا +عراقية +عراقيي +عراقيين +عراقيًا +عراوٍ +عرايا +عرب +عربا +عربات +عرباته +عرباتهم +عرباً +عربة +عربهم +عربي +عربيا +عربيات +عربيان +عربياً +عربية +عربيتين +عربيًا +عربيّ +عرس +عرسا +عرسان +عرش +عرشه +عرشها +عرض +عرضا +عرضاً +عرضة +عرضت +عرضتا +عرضتها +عرضحالجيا +عرضناها +عرضه +عرضها +عرضهم +عرضوا +عرضي +عرضية +عرضين +عرضيّة +عرضًا +عرف +عرفات +عرفاً +عرفة +عرفت +عرفتم +عرفتني +عرفته +عرفتها +عرفتهم +عرفتيه +عرفتُ +عرفنا +عرفناه +عرفناها +عرفه +عرفها +عرفوا +عرفوه +عرفوها +عرق +عرقل +عرقلة +عرقه +عرقهم +عرقي +عرقية +عروا +عروبة +عروبته +عروبيي +عروة +عروس +عروسك +عروسه +عروسي +عروسين +عروض +عروضاً +عروضه +عروضها +عروضيا +عروقنا +عروقها +عرى +عريض +عريضان +عريضاً +عريضة +عريق +عريقة +عريه +عرّافي +عرّضه +عرّف +عز +عزاء +عزاؤه +عزائي +عزام +عزة +عزت +عزتهم +عزرا +عزز +عززت +عزف +عزفا +عزفه +عزفها +عزل +عزلة +عزلته +عزلتي +عزلها +عزم +عزماً +عزمت +عزمه +عزمهم +عزمي +عزو +عزوت +عزوته +عزوف +عزوفا +عزيز +عزيزاً +عزيزة +عزيزتي +عزيزى +عزيزي +عزيمة +عزيمته +عزّ +عزّت +عزَّ +عساليج +عسانا +عساني +عسر +عسرة +عسروا +عسكرت +عسكري +عسكريا +عسكرياً +عسكرية +عسكريتين +عسل +عسلا +عسلاً +عسله +عسلية +عسول +عسى +عسير +عسيرا +عسيرة +عش +عشاء +عشاءه +عشارا +عشاق +عشاقها +عشان +عشب +عشبة +عشبي +عشبية +عشت +عشتار +عشتروت +عشتها +عشر +عشرات +عشراتها +عشراوي +عشراً +عشربن +عشرة +عشرتي +عشرون +عشري +عشرين +عشريني +عشرينيات +عشرِ +عشق +عشقا +عشقت +عشقنا +عشقه +عشقي +عشن +عشنا +عشه +عشهما +عشوائي +عشي +عشية +عشيرة +عشيرته +عشيقة +عشيقته +عشّاقنا +عصا +عصائر +عصابات +عصابة +عصابية +عصاة +عصاته +عصاراته +عصارة +عصافير +عصام +عصامي +عصاه +عصاها +عصب +عصبة +عصبي +عصبياً +عصبية +عصر +عصرا +عصراً +عصرنا +عصره +عصرها +عصرهن +عصري +عصرية +عصرًا +عصف +عصفت +عصفور +عصفوران +عصفورة +عصفورين +عصمة +عصمت +عصور +عصوره +عصورها +عصورهم +عصي +عصيان +عصيانه +عصياً +عصية +عصير +عصيين +عصيّات +عصيًّا +عضال +عضلات +عضلاته +عضلاتها +عضلة +عضلي +عضلية +عضو +عضوا +عضوات +عضواً +عضوة +عضوي +عضويا +عضوية +عضويته +عضويتها +عضوًا +عضيمة +عطا +عطاء +عطاءات +عطاءاته +عطاءه +عطاؤه +عطائنا +عطائها +عطائي +عطار +عطارد +عطاس +عطاياهم +عطر +عطرا +عطرك +عطره +عطرها +عطري +عطس +عطش +عطشاً +عطشى +عطشي +عطف +عطفا +عطفاً +عطفهم +عطل +عطلات +عطلة +عطلت +عطلته +عطلهم +عطوان +عطور +عطوف +عطوفًا +عطية +عطيرات +عطيل +عظاءة +عظام +عظامه +عظامي +عظم +عظماء +عظمة +عظمته +عظمتها +عظمك +عظمنا +عظمى +عظمي +عظميا +عظيم +عظيما +عظيماً +عظيمة +عظيمًا +عظيمٍ +عظُم +عظُمت +عـام +عــنها +عـلي +عـند +عفا +عفان +عفريتًا +عفلق +عفنا +عفو +عفوا +عفوي +عفوياً +عفوية +عفويتها +عفويتهم +عفويّ +عفية +عفيف +عفّان +عقائد +عقائده +عقائدها +عقائدي +عقائديان +عقائدياً +عقائدية +عقاب +عقابا +عقاباً +عقابيله +عقار +عقارا +عقاراً +عقارب +عقاري +عقارياً +عقارية +عقارًا +عقاقير +عقاقيرها +عقب +عقبات +عقبان +عقباننا +عقباه +عقباها +عقبة +عقبهما +عقد +عقدة +عقدت +عقدته +عقدتها +عقده +عقدها +عقدوا +عقدوه +عقدي +عقدياً +عقدية +عقدين +عقدًا +عقر +عقران +عقرب +عقربا +عقــل +عقل +عقلا +عقلانية +عقلة +عقله +عقلها +عقلهم +عقلي +عقليا +عقلية +عقليته +عقليًا +عقليّة +عقوبات +عقوباته +عقوبة +عقوبته +عقود +عقودا +عقودها +عقول +عقولكم +عقولنا +عقوله +عقولها +عقولهم +عقيدات +عقيدة +عقيدتها +عقيدتهم +عقيل +عقيمات +عكا +عكازتين +عكاشة +عكاظ +عكاوية +عكر +عكرا +عكرمة +عكس +عكسه +عكسياً +عكسية +عكف +عكفت +عكَس +عكّازَ +عل +علا +علاء +علائق +علائم +علاتها +علاج +علاجا +علاجات +علاجاً +علاجه +علاجها +علاجهم +علاجيا +علاجية +علاجًا +علاقات +علاقاته +علاقاتها +علاقاتهم +علاقاتهما +علاقاتي +علاقة +علاقتنا +علاقته +علاقتها +علاقتهم +علاقتهما +علاقتي +علام +علامات +علاماته +علامة +علامتين +علان +علانية +علاها +علاوة +علب +علبة +علبتك +علبته +علبتين +علشان +علـــق +علـى +علق +علقت +علقني +علك +علل +عللت +عللها +عللهم +علم +علما +علماء +علماؤنا +علماؤه +علمائنا +علمائه +علمائها +علمائهم +علمان +علماني +علمانية +علمانيتهم +علمانيي +علماً +علمت +علمتنا +علمتني +علمك +علمكم +علمنا +علمني +علمه +علمها +علمهم +علموا +علموني +علموها +علمي +علميا +علمياً +علمية +علمين +علميًا +علميًّا +علمًا +علمْتُ +علنا +علني +علنيا +عله +علها +علو +علوا +علوة +علوم +علومه +علومها +علومي +علومًا +علوي +علويا +علوية +علوٍ +على +علىعشائي +علي +عليا +علياء +عليائها +علية +عليج +عليـها +عليك +عليكم +عليكما +عليلاً +عليم +علينا +عليه +عليها +عليهم +عليهما +عليهن +عليَ +عليّ +عليّا +عليّاستمر +عليًّا +عليٌّ +عليَّ +علٍ +علّتك +علّق +علّقت +علّك +علّم +علّمتني +علّمك +علّمه +علّمها +علّموا +علّني +علّها +علَّق +عم +عما +عماد +عمادات +عمادة +عمار +عماراتها +عمارة +عمارته +عمارتها +عمارتهم +عمال +عمالة +عمالقة +عمامة +عمامته +عمان +عمانوئيل +عماني +عمة +عمتكم +عمتنا +عمته +عمتي +عمد +عمدا +عمدة +عمدت +عمدوا +عمر +عمران +عمرانها +عمرانية +عمراً +عمرة +عمرت +عمرسنة +عمرك +عمرنا +عمرناها +عمره +عمرها +عمرهم +عمرو +عمري +عمرية +عمريتين +عمق +عمقا +عمقاً +عمقه +عمقها +عمك +عمل +عملا +عملاء +عملائه +عملائها +عملات +عملاتها +عملاق +عملاقا +عملاقة +عملاقًا +عملان +عملاً +عملة +عملت +عملتم +عملته +عملك +عملكم +عملن +عملنا +عمله +عملها +عملهم +عملوا +عملي +عمليا +عمليات +عملياته +عملياتها +عملياتهم +عملياتيا +عملياً +عملية +عمليتها +عمليتي +عمليتين +عملين +عمليّات +عمن +عمه +عمود +عموداً +عمودي +عمودية +عمورية +عمولة +عموم +عموما +عموماً +عمومة +عمومتها +عمومي +عمي +عمياء +عميات +عميد +عميدا +عميداً +عميدًا +عميق +عميقا +عميقاً +عميقة +عميقًا +عميل +عمّ +عمّآ +عمّا +عمّال +عمّان +عمّت +عمّك +عمّي +عمَّا +عن +عنا +عناء +عنات +عناد +عناصر +عناصرا +عناصره +عناق +عناقاً +عناقها +عنان +عناني +عناهم +عناوين +عناوينها +عناية +عنايته +عنب +عنترة +عنخ +عند +عندئذ +عندا +عندالسعال +عندك +عندكم +عندكِ +عندليب +عندما +عندنا +عنده +عندها +عندهم +عندهن +عندي +عنزان +عنصر +عنصرا +عنصران +عنصراً +عنصري +عنصرية +عنصرين +عنــدما +عنف +عنفا +عنفها +عنق +عنقه +عنقها +عنقود +عنقي +عنك +عنكما +عنكِ +عنه +عنها +عنهم +عنهما +عنوان +عنوانا +عنوانان +عنواناً +عنوانه +عنوانها +عنوانهما +عنوة +عنونة +عنونت +عني +عنيت +عنيد +عنيدا +عنيداً +عنيدة +عنيف +عنيفا +عنيفاً +عنيفة +عنيناه +عنّا +عهد +عهدئذ +عهداً +عهدة +عهدتك +عهدذاك +عهدك +عهده +عهدها +عهدهم +عهدهِ +عهدي +عهود +عهودها +عوائد +عوائدها +عوائق +عوائل +عواد +عوادم +عوارض +عوارها +عواصف +عواصم +عواقبه +عوالم +عوالمها +عواماته +عوامل +عود +عودا +عوداً +عودة +عودتك +عودتنا +عودته +عودتها +عودتهم +عودتي +عودهم +عودي +عورات +عورة +عوز +عوض +عوضا +عوضاً +عوضًا +عوف +عوقبت +عول +عولج +عولجت +عولجوا +عولمة +عولمته +عولمتها +عوملوا +عون +عونك +عونًا +عونٍ +عويس +عويص +عويضة +عويل +عوّد +عوّض +عوَّض +عى +عياد +عيادات +عيادة +عيادته +عيار +عيارات +عياره +عياض +عياضاً +عيال +عيالها +عيان +عياناها +عيب +عيبا +عيبان +عيباً +عيد +عيدان +عيداً +عيسان +عيسى +عيش +عيشة +عيشهم +عيشي +عيل +عين +عينا +عينات +عيناك +عينان +عيناه +عيناها +عيناي +عينة +عينت +عينه +عينها +عينوا +عينوه +عيني +عينية +عينيك +عينين +عينيه +عينيها +عينيّ +عيوب +عيوبا +عيوبه +عيوبها +عيون +عيونج +عيونكم +عيوننا +عيونه +عيونها +عيونهم +عيونهما +عيونهن +عيوني +عيّن +عيّنة +عيّنوه +عيِّناته +عَامِلٍ +عَاهَدُوا +عَزِيزٌ +عَظِيمٍ +عَكْسَ +عَلَماً +عَلَيْهِ +عَمَلَ +عَنون +عَنِ +عَنْهُمْ +عَهِد +عَيْن +عُتّق +عُثر +عُدّ +عُذرة +عُرض +عُرضت +عُرف +عُرفت +عُرْس +عُرْساً +عُشْر +عُقدة +عُلم +عُمان +عُمد +عُمِّر +عُني +عُوِّضتُ +عُين +عُيِّن +عِرضها +عِزُّ +عِقدٍ +عِلْمًا +عِندَ +عِنْدَهُ +عِنْدِ +ـ +ـت +ــ +ـــ +ــفنــ +ـك +ف +فآرنست +فآمل +فأبادر +فأبت +فأبدأ +فأبدت +فأبدعوا +فأبدى +فأبرأتهم +فأبعد +فأبقاها +فأبواب +فأبوه +فأبى +فأتاح +فأتت +فأتحرّر +فأتسلل +فأتقنت +فأتوني +فأتى +فأثار +فأثمرت +فأثملهم +فأجاب +فأجابني +فأجابه +فأجابها +فأجازه +فأجبت +فأجد +فأجرى +فأجريت +فأجمعوا +فأجهزة +فأجيب +فأحاطته +فأحببت +فأحبّه +فأحدث +فأحدهما +فأحزان +فأحس +فأحسسنا +فأحسها +فأحضر +فأحضرت +فأحيي +فأخبر +فأخبرته +فأخبريني +فأخذ +فأخذت +فأخذته +فأخذنا +فأخرج +فأخرجوا +فأخطأ +فأخطر +فأخطُّ +فأداة +فأدبه +فأدخل +فأدخلته +فأدرك +فأدركت +فأدركته +فأدركوا +فأدى +فأذعن +فأذكر +فأذهب +فأر +فأراد +فأرادت +فأراني +فأراود +فأرتجع +فأرتعش +فأردد +فأرزق +فأرسل +فأرسلت +فأرسله +فأرسلوا +فأرفعه +فأس +فأساءت +فأسبابها +فأسجله +فأسد +فأسرع +فأسس +فأسعى +فأسقط +فأسقطته +فأسهب +فأسًا +فأشار +فأشاع +فأشرت +فأشعر +فأشهد +فأصاب +فأصابتها +فأصبح +فأصبحت +فأصبحوا +فأصدر +فأصدرت +فأصمت +فأضاء +فأضجر +فأضعف +فأطراف +فأطفأ +فأطلب +فأظهر +فأظهروا +فأعاد +فأعانته +فأعتقد +فأعجب +فأعجبه +فأعجبوا +فأعرض +فأعطاه +فأعطاها +فأعطاهم +فأعطت +فأعطيتها +فأعلن +فأعلنوا +فأعلنوك +فأعماله +فأعمق +فأعملت +فأعود +فأفاد +فأفادنى +فأفدح +فأفرج +فأفضل +فأقام +فأقاموا +فأقبل +فأقرؤه +فأقسمت +فأقصى +فأقـــلبها +فأقفل +فأقل +فأقمت +فأقنع +فأقول +فأقوى +فأكثر +فأكد +فأكمل +فأل +فألقت +فألقى +فألقي +فأما +فأمثلة +فأمر +فأمره +فأمريكا +فأمسكها +فأمضيت +فأن +فأنا +فأنام +فأنت +فأنتج +فأنتم +فأنجزه +فأنزل +فأنسى +فأنشأ +فأنشأت +فأنشأوا +فأنكر +فأنه +فأهاب +فأهداه +فأهلكهم +فأهم +فأهملوها +فأود +فأوضح +فأوفد +فأوفدت +فأوقف +فأوقفها +فأولا +فأومن +فأي +فأيقن +فأيقَظت +فأين +فأيهما +فأيٌ +فأَمّا +فأُجيبه +فأُنشئت +فؤاد +فؤادك +فؤاده +فؤادها +فإدارته +فإذا +فإذن +فإسرائيل +فإلى +فإما +فإن +فإنقاذ +فإنك +فإنكم +فإنما +فإننا +فإنني +فإنه +فإنها +فإنهم +فإنهما +فإني +فإنّ +فإنَّك +فئات +فئاتها +فئة +فائدة +فائدتها +فائض +فائق +فائقات +فائقة +فابتسمت +فابتعد +فابتعدت +فابن +فابنا +فابنته +فات +فاتتني +فاتجه +فاتجهت +فاتح +فاتحا +فاتحة +فاتحـة +فاتحين +فاتحًا +فاتخذ +فاتخذوها +فاتر +فاترينات +فاترينة +فاتسعت +فاتسلاف +فاتصل +فاتصلت +فاتفق +فاتفقت +فاتك +فاتكم +فاتنات +فاتنة +فاتنته +فاتني +فاته +فاتورة +فاجأ +فاجأت +فاجأته +فاجأتها +فاجأني +فاجأهم +فاجتاحها +فاجتازت +فاجتمع +فاجع +فاجنر +فاجيه +فاحتال +فاحتجزتها +فاحتدم +فاحترمته +فاحتمل +فاحسن +فاحصة +فاحصه +فاحم +فاحمد +فاختار +فاختارت +فاخترت +فاخترعوا +فاختطفه +فاختلطت +فاختياره +فاختير +فاخر +فاخراً +فاخرة +فاخوري +فادح +فادحة +فادع +فادفع +فادية +فاذا +فارا +فارتجف +فارتفاع +فارتفعت +فارتكبت +فارتمى +فارتوى +فارس +فارسا +فارسي +فارسيما +فارسين +فارق +فارقة +فارقتها +فارنوش +فارهة +فارو +فاروق +فاز +فازت +فازداد +فازدادت +فاس +فاسأل +فاستأجروا +فاستحال +فاستدار +فاستدعوه +فاستشاط +فاستصدرت +فاستطاع +فاستعاد +فاستعماله +فاستعن +فاستعنت +فاستقال +فاستقامت +فاستقبله +فاستناده +فاستنكر +فاستهدف +فاستوت +فاستوعبها +فاستيقظت +فاسد +فاسدا +فاسداً +فاسدة +فاسمح +فاسمع +فاسمه +فاسو +فاسيل +فاشترى +فاشتهر +فاشل +فاشلا +فاشلة +فاصطدم +فاصل +فاصلا +فاصلاً +فاصلة +فاصلٌ +فاض +فاضح +فاضحاً +فاضحة +فاضطر +فاضطررت +فاضطروا +فاضل +فاضلة +فاضي +فاطمة +فاطمية +فاعتبرت +فاعتذرت +فاعترضوها +فاعتقل +فاعتمد +فاعرف +فاعل +فاعلا +فاعلاً +فاعلة +فاعلون +فاعلي +فاعلية +فاعليتها +فاعلين +فافخر +فاق +فاقت +فاقتحم +فاقترب +فاقتربت +فاقترح +فاقترحت +فاقتنعوا +فاقد +فاقدو +فاقدًا +فاقرؤها +فاقمت +فاقها +فاقهم +فاقوس +فاكتسب +فاكتشف +فاكتفوا +فاكتفي +فاكتفيت +فاكساً +فالآيات +فالأب +فالأحفورة +فالأختام +فالأخذ +فالأدب +فالأدباء +فالأرض +فالأرقام +فالأزرق +فالأسباب +فالأسرة +فالأسلوب +فالأسوار +فالأشقياء +فالأشهرُ +فالأصلح +فالأطفال +فالأعمدة +فالأفضل +فالأفكار +فالأقرب +فالأقصى +فالأقطاب +فالأكواخ +فالأم +فالأمر +فالأمل +فالأمن +فالأموال +فالأنثى +فالأنساق +فالأولى +فالأيام +فالإبداعات +فالإرث +فالإسراف +فالإسلام +فالإشارات +فالإصبع +فالإمكانات +فالإنترنت +فالإنسان +فالإيمان +فالابتسامة +فالاثنان +فالاحتجاز +فالاختلاج +فالارقام +فالاستثمار +فالاستقرار +فالاستقلال +فالاعتدال +فالاعتراف +فالاقتصادات +فالانتفاضة +فالاندفاعة +فالبابون +فالباحث +فالباكستانيون +فالبامبو +فالبحر +فالبدلات +فالبديل +فالبربر +فالبشر +فالبعد +فالبعض +فالبعوض +فالبلاستيك +فالبنود +فالبيت +فالتأنيب +فالتجربة +فالتحدي +فالتحديث +فالتحق +فالتحقت +فالتر +فالتراب +فالترانزستورات +فالتركيب +فالتسامح +فالتطور +فالتعرض +فالتعريف +فالتعليم +فالتفت +فالتقارب +فالتقارير +فالتقفه +فالتقليد +فالتلوث +فالتماثل +فالتمثيل +فالتمر +فالتنفس +فالتوقيت +فالتيوفيللين +فالثابت +فالثعالب +فالثور +فالثورة +فالجائزة +فالجاحظ +فالجزر +فالجماعة +فالجمال +فالجميع +فالجهود +فالجيل +فالح +فالحب +فالحجاب +فالحد +فالحديث +فالحرب +فالحركة +فالحروب +فالحسن +فالحشيش +فالحصان +فالحضارة +فالحقيقة +فالحكمة +فالحياة +فالحيتان +فالخارج +فالخبراء +فالخلفيات +فالخيال +فالخيوط +فالداعية +فالدراسة +فالدكتور +فالدكتورة +فالدموع +فالدميةُ +فالدواء +فالدودة +فالدول +فالديانة +فالديس +فالدين +فالذاكرة +فالذهب +فالذي +فالذين +فالرؤيا +فالرؤية +فالراعي +فالراوي +فالرب +فالرباط +فالرجال +فالرجل +فالرجولة +فالرسم +فالرطوبة +فالرقائق +فالرقابة +فالرمز +فالريع +فالزمكان +فالزوار +فالزوجة +فالس +فالسؤال +فالسبب +فالسعادةُ +فالسفر +فالسكوت +فالسوق +فالسياسة +فالسيبارام +فالسيجار +فالشأن +فالشاعر +فالشبكية +فالشجرة +فالشخص +فالشخصيات +فالشعور +فالشمس +فالشوارع +فالشيفرة +فالشيّاب +فالصبر +فالصحراء +فالصقر +فالصورة +فالصين +فالضحك +فالضرر +فالضفة +فالضيوف +فالطاقات +فالطبقات +فالطبقة +فالطبيعة +فالطرفان +فالطريف +فالطفل +فالظروف +فالعالم +فالعبادات +فالعبرة +فالعديد +فالعراق +فالعرب +فالعربي +فالعروبة +فالعسل +فالعقاد +فالعقارب +فالعقبان +فالعقل +فالعقلية +فالعلاقة +فالعلم +فالعلماء +فالعلوم +فالعمل +فالعملية +فالعوامل +فالفائدة +فالفارق +فالفتاة +فالفساد +فالفصل +فالفضل +فالفن +فالفنان +فالفيل +فالفيلم +فالق +فالقات +فالقارب +فالقبيلة +فالقدس +فالقرآن +فالقراءة +فالقرار +فالقرية +فالقصة +فالقصيدة +فالقضية +فالقطعة +فالقلق +فالقنفذ +فالقوانين +فالقول +فالكائنات +فالكاتب +فالكبيسي +فالكتاب +فالكثرة +فالكثير +فالكثيرون +فالكفاح +فالكلام +فالكلب +فالكلمات +فالكلمة +فالكمبيوتر +فالكميات +فالكمية +فاللائكية +فاللجنين +فاللمسات +فاللهجة +فاللوب +فالليلة +فالمؤرخون +فالماء +فالمباشر +فالمتعب +فالمتهم +فالمجتمع +فالمحاولات +فالمخاطرة +فالمدة +فالمدرات +فالمدن +فالمدينة +فالمرأة +فالمرايا +فالمربع +فالمرشحون +فالمسئول +فالمساحة +فالمساهمات +فالمستعمرة +فالمسرح +فالمسرحية +فالمسروقات +فالمسلمات +فالمسلمون +فالمشكلة +فالمصاب +فالمضاربات +فالمطعم +فالمعادلات +فالمعترف +فالمعتمر +فالمعدة +فالمعروف +فالمقارنة +فالمقدرة +فالمقدمات +فالمقطعان +فالمقياس +فالمكان +فالمكسيك +فالمكونات +فالملابس +فالملاحظ +فالمليونير +فالممثل +فالمنطقة +فالمهم +فالموت +فالموجود +فالموسم +فالموقف +فالمياه +فالناس +فالنبتة +فالنجاح +فالنحل +فالنخلة +فالنسيا +فالنشاط +فالنضال +فالنظام +فالنقب +فالنموذج +فالنهضة +فالنيل +فالهرمون +فالهند +فالهواء +فالهوية +فالواقع +فالوالد +فالوجهان +فالوجود +فالوزن +فالوسط +فالوطن +فالوعي +فالولادات +فالولايات +فامتد +فاميلي +فان +فانبرى +فانبهر +فانتابهم +فانتحل +فانتحيا +فانتخب +فانتشر +فانتشرت +فانتصار +فانتظري +فانتفض +فانتقل +فانتقلت +فانتهى +فانخرطا +فانخفضت +فاندثرت +فاندفع +فانسيدار +فانشدك +فانشرح +فانشطرت +فانصرف +فانضم +فانطلقت +فانظر +فانعطف +فانعقدت +فانفجر +فانفجروا +فانهزم +فاهتدوا +فاهتدى +فاهتم +فاوتد +فاونسا +فايدة +فايز +فايزة +فايزر +فب +فبإمكانك +فبئر +فباعتبار +فباقي +فبالأمس +فبالإضافة +فبالإيمان +فبالصدق +فبالطبع +فبالعلم +فبالقبلة +فبالقروض +فبالنسبة +فبانتْ +فبدأ +فبدأت +فبدأنا +فبدأوا +فبدا +فبدت +فبدرجات +فبدل +فبدلا +فبراير +فبرزت +فبسببها +فبسط +فبعد +فبعدد +فبعدما +فبعدها +فبعض +فبعضها +فبعضهم +فبعضهن +فبقدر +فبقيت +فبكى +فبم +فبمقدار +فبنوا +فبها +فبيعت +فبين +فبينما +فتأتي +فتأثر +فتأكدت +فتأمل +فتأمَّلي +فتؤثر +فتئ +فتئت +فتابع +فتابعت +فتابعنا +فتاة +فتات +فتاتان +فتاتي +فتاح +فتاحة +فتارة +فتاك +فتاكا +فتاوى +فتبحث +فتبحر +فتبددت +فتبدو +فتبقى +فتبقيه +فتتجمع +فتتجه +فتتحرر +فتتحسن +فتتحمل +فتتحول +فتتخذه +فتتخطاه +فتتخطَّي +فتتداخل +فتتدهور +فتتذكر +فتتراجع +فتتراكب +فتتردى +فتترك +فتتسبب +فتتضاعف +فتتعاظم +فتتعاقب +فتتعدد +فتتعرف +فتتعلم +فتتفاقم +فتتكاثر +فتتكفّلان +فتتلاشى +فتتلاعب +فتتلخص +فتتمايل +فتتمدد +فتتميز +فتثبت +فتثبّت +فتثقل +فتجاوزت +فتجد +فتجدها +فتجرعت +فتجري +فتجعل +فتجف +فتجنب +فتجيب +فتجيبني +فتح +فتحا +فتحات +فتحبطنا +فتحة +فتحت +فتحتهما +فتحجب +فتحدث +فتحدد +فتحركت +فتحرم +فتحسنت +فتحصل +فتحفز +فتحقق +فتحلم +فتحمله +فتحنا +فتحها +فتحهم +فتحولت +فتحولوا +فتحي +فتحيا +فتحية +فتخبرنا +فتخرج +فتخصصت +فتخطئه +فتخفي +فتخمد +فتدرك +فتدفق +فتدفَّقت +فتدكها +فتدمع +فتدهورت +فتدير +فتذكر +فترات +فتراته +فتراه +فتراهم +فتربَّى +فترة +فترتب +فترتيب +فترتين +فترجع +فترجم +فترجما +فترجمت +فترجمته +فترد +فتردد +فترفع +فترفق +فترك +فتركت +فتركها +فتركوها +فتروي +فترى +فتزداد +فتسارع +فتستجيب +فتستقبلنا +فتستوعب +فتسرَّب +فتسعِّر +فتسلب +فتسلمتها +فتسمع +فتسمية +فتشاهد +فتشاورنا +فتشبه +فتشت +فتشتري +فتشحذ +فتشربها +فتشرع +فتشعر +فتشمل +فتشوا +فتشير +فتصادمت +فتصبح +فتصدره +فتصدّر +فتصعد +فتصل +فتصنف +فتصيبها +فتصير +فتضربه +فتضطرب +فتضعفهم +فتضعه +فتضيع +فتطأك +فتطبيق +فتطلب +فتظل +فتظهر +فتعاظم +فتعاقدت +فتعالوا +فتعتعوا +فتعرض +فتعرضت +فتعرف +فتعرفه +فتعرية +فتعطبه +فتعطي +فتعظيم +فتعكس +فتعلقت +فتعلم +فتعلمت +فتعلموا +فتعمق +فتعني +فتعود +فتعيش +فتفتَّق +فتفجّرت +فتفر +فتفرض +فتفرقنا +فتفسح +فتفككت +فتفوقوا +فتق +فتقاطرت +فتقاليد +فتقام +فتقدم +فتقرر +فتقف +فتقفز +فتقول +فتقوم +فتكا +فتكاثرت +فتكثر +فتكمل +فتكون +فتكونت +فتكوّن +فتلاحقها +فتلاشت +فتلتفت +فتلتهب +فتلطَّخت +فتلعب +فتلعثم +فتلقى +فتلك +فتم +فتمت +فتمجد +فتمحو +فتمد +فتمدنا +فتمرره +فتمضي +فتمطر +فتمكن +فتمكنت +فتملأ +فتمنح +فتمنع +فتمنيت +فتموت +فتميزوا +فتن +فتناقصت +فتنبت +فتنة +فتنتابه +فتنتابها +فتنتج +فتنتظر +فتنتها +فتنتهي +فتنحدر +فتنخفض +فتنظر +فتنفست +فتنقل +فتنمو +فتنوع +فتهافتت +فتهشمت +فتهمه +فتوجد +فتوجس +فتوجه +فتوجهت +فتوصلت +فتوفر +فتوفير +فتوقف +فتوقفنا +فتولدت +فتولى +فتولي +فتوى +فتى +فتيات +فتياتنا +فتياراته +فتَدفّعا +فتُظلمها +فثار +فثالات +فثلثه +فثمة +فثورة +فج +فجأة +فجأةً +فجئت +فجاء +فجاءت +فجائي +فجائية +فجاوبها +فجدوا +فجدي +فجدُّهُ +فجذبته +فجر +فجرا +فجراً +فجرت +فجرحه +فجرفتها +فجرها +فجري +فجزأته +فجعل +فجعلت +فجل +فجلبت +فجلست +فجلسنا +فجمعت +فجمّدتها +فجنوب +فجوات +فجوة +فجوسلين +فجيعة +فجيعتها +فحازت +فحالما +فحاول +فحاولت +فحتمية +فحتى +فحجبها +فحداني +فحدث +فحدثته +فحدثنا +فحدجتُ +فحدّث +فحدِّث +فحرم +فحرمان +فحزنت +فحسب +فحسين +فحص +فحصت +فحصتهم +فحصل +فحصلت +فحصه +فحصهم +فحصول +فحط +فحطمناه +فحفظ +فحفظت +فحقوق +فحقوقي +فحل +فحمدت +فحملت +فحملن +فحمي +فحوادث +فحوالي +فحوت +فحوص +فحوصات +فحوكم +فحول +فحين +فحينئذ +فحينما +فحييني +فخ +فخائر +فخاب +فخاخ +فخار +فخاريات +فخاطب +فخاف +فخامة +فخانهما +فخبر +فخذ +فخر +فخرا +فخراً +فخرج +فخرجتُ +فخري +فخرية +فخصصت +فخصصوا +فخططت +فخطفت +فخلاصة +فخلال +فخلايا +فخلع +فخلعه +فخلو +فخم +فخماً +فخمة +فخور +فخورا +فخورة +فخيم +فداء +فدائماً +فداناً +فدبروا +فدحنا +فدخل +فدخلتها +فدخلنا +فدخلوا +فدرس +فدع +فدعا +فدعانا +فدعت +فدعنا +فدعوا +فدعوته +فدفعت +فدفعه +فدقت +فدمر +فدمروا +فدنوتُ +فدور +فدوى +فذاع +فذاك +فذاكرته +فذبحه +فذة +فذكاء +فذكر +فذكرت +فذلك +فذلكة +فذهب +فذهبت +فذو +فرآه +فرأت +فرأته +فرأتها +فرأس +فرأوا +فرأى +فرأيت +فرائس +فرائسه +فرائصه +فرائه +فراج +فراحت +فرادة +فرادته +فراراً +فراز +فراس +فراسة +فراسر +فراش +فراشات +فراشة +فراشك +فراشه +فراشها +فراعنة +فراعها +فرافق +فراق +فراقا +فرانز +فرانس +فرانسوا +فرانسيز +فرانسيسكو +فرانك +فرانكشتاين +فرانكفورت +فربما +فرت +فرتر +فرج +فرجة +فرجته +فرجعت +فرجوية +فرجينيا +فرح +فرحا +فرحات +فرحان +فرحانة +فرحاً +فرحبت +فرحة +فرحت +فرحته +فرحتي +فرحلت +فرحم +فرحه +فرحها +فرحون +فرحي +فرحين +فرحًا +فرد +فرداً +فردت +فردتني +فردتي +فردريش +فردريك +فردوس +فردوسا +فردوسه +فردي +فرديا +فردية +فرديناند +فرديًا +فرديّ +فرديًّا +فردًا +فرسان +فرسانها +فرساي +فرسم +فرش +فرشاتي +فرص +فرصا +فرصاً +فرصة +فرصةً +فرصتهم +فرصتي +فرض +فرضا +فرضت +فرضتها +فرضه +فرضها +فرضوا +فرضوي +فرضي +فرضية +فرضًا +فرط +فرع +فرعا +فرعان +فرعاً +فرعون +فرعونية +فرعية +فرفض +فرفضا +فرفضتها +فرفع +فرفعوه +فرق +فرقا +فرقائق +فرقاً +فرقة +فرقته +فرقتها +فرقه +فرقها +فركبوه +فركت +فركضوا +فرم +فرمال +فرملة +فرمه +فرن +فرنجي +فرنجية +فرنسا +فرنسوا +فرنسي +فرنسيات +فرنسية +فرنسيون +فرنك +فرنكاً +فرهود +فروجهن +فروجيه +فروخ +فروض +فروع +فروعا +فروعًا +فروق +فروقا +فروقاً +فروقًا +فرومانتان +فرومنتان +فرويد +فروين +فري +فريحة +فريد +فريدا +فريداً +فريدة +فريدةً +فريدريك +فريدريكو +فريديريك +فرير +فريسة +فريسته +فريضة +فريق +فريقا +فريقه +فريقين +فرِد +فرّت +فرّق +فرّكت +فزاحمها +فزادت +فزادهم +فزار +فزارها +فزان +فزت +فزجاجة +فزرت +فزع +فزعا +فزعاً +فزعت +فزعزع +فزعين +فزفرت +فزوجه +فزيادة +فسأحتاج +فسأرسل +فسأروى +فسأقيم +فسأل +فسألت +فسألته +فسألتها +فسألناه +فسأله +فسؤال +فساحة +فساد +فسادا +فساداً +فسادوا +فسار +فسارعوا +فساعدت +فسافر +فسافرت +فساهم +فسبقنا +فستان +فستاني +فستجد +فسحب +فسحة +فسحتها +فسحقته +فسدت +فسر +فسرت +فسرعة +فسرنا +فسروا +فسطاط +فسطاطك +فسطاطه +فسعى +فسقط +فسقطت +فسكان +فسكت +فسكن +فسلام +فسماء +فسمح +فسمحت +فسمع +فسمعنا +فسمى +فسنختفي +فسنسعى +فسنظل +فسنكون +فسهول +فسوء +فسوف +فسيارات +فسيجد +فسيح +فسيحة +فسيكون +فسيمنعه +فسيولوجية +فسّاطم +فشاهد +فشبر +فشجعان +فشجعه +فشجعوا +فشدا +فشدّ +فشرح +فشركات +فشعرت +فشعره +فشقوا +فشكا +فشكلها +فشكلوا +فشل +فشلا +فشلاً +فشلت +فشلنا +فشله +فشلها +فشلوا +فشمروا +فشمل +فشهد +فشهدت +فشهدنا +فشواذ +فشوارعها +فشيئا +فشيئاً +فشيئًا +فشيدت +فص +فصائل +فصائلها +فصاح +فصار +فصارت +فصانعو +فصبها +فصح +فصحتها +فصحيح +فصدرت +فصدقناكِ +فصرت +فصرخ +فصفعني +فصل +فصلا +فصلاً +فصلت +فصلك +فصلن +فصلناها +فصله +فصلهم +فصلهما +فصلي +فصلية +فصلين +فصنع +فصوت +فصوص +فصول +فصولا +فصولاً +فصوله +فصولها +فصيح +فصيحا +فصيص +فصيل +فصيلة +فض +فضاء +فضاءنا +فضاءها +فضاءً +فضائح +فضائل +فضائلها +فضائه +فضائي +فضائيا +فضائياً +فضائية +فضاعت +فضاقت +فضة +فضح +فضحته +فضحك +فضحكنا +فضحكوا +فضحّوا +فضخوا +فضرب +فضربوا +فضعف +فضفاضا +فضفاضة +فضل +فضلا +فضلاء +فضلاتها +فضلال +فضلان +فضلاً +فضلت +فضلك +فضلكم +فضله +فضلها +فضلوا +فضم +فضول +فضية +فضيحة +فضيلة +فضّل +فضَّة +فطار +فطر +فطرأت +فطرتي +فطرح +فطرد +فطرق +فطري +فطريا +فطريات +فطرية +فطريًّا +فطلب +فطلبت +فطمأن +فطمأنه +فطنا +فطوبى +فطوري +فطين +فظا +فظاعة +فظة +فظلت +فظللت +فظن +فظهر +فظهرت +فظيع +فظيعة +فعائشة +فعاد +فعادة +فعادت +فعاقبهُ +فعال +فعالا +فعالة +فعالم +فعاليات +فعالياته +فعالياتها +فعالية +فعاليته +فعاليتها +فعبر +فعثر +فعدد +فعددهم +فعديد +فعرضت +فعرفت +فعزمت +فعسى +فعشت +فعشقت +فعصر +فعقد +فعقلها +فعقيدتها +فعكفوا +فعل +فعلا +فعلاً +فعلة +فعلت +فعلته +فعلتها +فعلتُ +فعلقت +فعلقته +فعلماء +فعلمت +فعلنا +فعله +فعلها +فعلوا +فعلى +فعلي +فعليا +فعلياً +فعلية +فعليك +فعلينا +فعليه +فعليها +فعليهم +فعليًا +فعلّم +فعمان +فعمد +فعمدت +فعمل +فعملت +فعملية +فعن +فعند +فعندما +فعهد +فعوض +فعوضا +فعّالاً +فعّالة +فعَّال +فـ +فـرص +فـــاروق +فــلا +فـها +فـول +فـي +ففازت +ففتح +ففتحت +ففجّر +ففرحت +ففرض +ففريق +ففزع +ففصل +ففضل +ففعل +ففقدان +ففكرة +ففلسفة +ففوجئ +ففوجئت +ففى +ففي +ففيلم +ففيه +ففيها +ففيهما +فقادني +فقارية +فقاطعه +فقاعات +فقال +فقالا +فقالت +فقالوا +فقام +فقامت +فقاموا +فقبره +فقبل +فقبلتها +فقبله +فقتل +فقتلت +فقد +فقدا +فقدان +فقدانه +فقدانها +فقدت +فقدته +فقدتُ +فقدم +فقدمت +فقدمني +فقدنا +فقده +فقدها +فقدوا +فقديما +فقدَ +فقر +فقرأ +فقرأت +فقرا +فقراء +فقراءة +فقرائه +فقرائهم +فقرات +فقراً +فقرة +فقرتين +فقرر +فقررا +فقررت +فقرروا +فقرها +فقري +فقرًا +فقرَّ +فقص +فقصر +فقضى +فقضيت +فقط +فقطاري +فقطب +فقطع +فقطعت +فقفز +فقل +فقلة +فقلت +فقلتها +فقلتُ +فقلما +فقمات +فقمة +فقمت +فقه +فقها +فقهاء +فقهياً +فقهية +فقوى +فقير +فقيرا +فقيراً +فقيرة +فقيرًا +فقيل +فقيه +فقيها +فقيِّده +فقَدَ +فك +فكأنك +فكأنما +فكأنها +فكاد +فكان +فكانت +فكانوا +فكاهات +فكتاب +فكتب +فكتبا +فكتبت +فكتبوا +فكتور +فكثرة +فكثيرا +فكثيراً +فكثيرة +فكر +فكرا +فكراً +فكرة +فكرت +فكرتان +فكرته +فكرتها +فكرتي +فكررت +فكرـ +فكرك +فكرمه +فكرنا +فكره +فكروا +فكرى +فكري +فكريا +فكرياً +فكرية +فكريين +فكريّة +فكشفت +فكل +فكلاهما +فكلما +فكلمة +فكلها +فكلي +فكم +فكما +فكنا +فكنت +فكهة +فكوا +فكون +فكوني +فكوّن +فكوّنت +فكيف +فكيفما +فكيك +فكّ +فكّر +فكَّر +فكَّرت +فل +فلأتوقف +فلأجل +فلإدراك +فلا +فلابد +فلابدّ +فلاتزال +فلاح +فلاحظ +فلاحظت +فلاحين +فلادلفيا +فلاديمير +فلار +فلاسفة +فلان +فلايجدون +فلاّح +فلبى +فلتة +فلتت +فلتسجيل +فلتكن +فلتكونوا +فلتمييز +فلتنته +فلجأ +فلحقه +فلحّن +فلدى +فلدي +فلدينا +فلديه +فلربما +فلربّما +فلس +فلساً +فلست +فلسطين +فلسطيني +فلسطينيا +فلسطينية +فلسطينيو +فلسطينيي +فلسطينيين +فلسفة +فلسفته +فلسفي +فلسفية +فلسفيًّا +فلسوف +فلطالما +فلعل +فلعلها +فلعلي +فلـقد +فلفت +فلفظت +فلفل +فلفلة +فلقد +فلقيهما +فلك +فلكل +فلكلوري +فلكلورية +فلكم +فلكها +فلكي +فلكية +فلل +فللعراق +فللمثقفين +فلله +فلليابسة +فلم +فلما +فلماذا +فلمبان +فلمح +فلمحاولة +فلمست +فلمَ +فلن +فلنا +فلنتأمل +فلنترك +فلنحيينه +فلندز +فلنسافر +فلنفعل +فلنقل +فله +فلها +فلو +فلوات +فلواتي +فلوبير +فلوحات +فلوحة +فلورايدا +فلورنسا +فلوروميبندازول +فلوريان +فلوريدا +فلوسه +فلولا +فلون +فلويد +فلي +فليأكل +فليبصق +فليبيا +فليتفضل +فليتنا +فليحمد +فليس +فليسامح +فليست +فليستجيبوا +فليستعذ +فليصل +فليعد +فليفل +فليقم +فلِم +فم +فما +فماتت +فماذا +فمال +فمباشر +فمتوسط +فمثل +فمثلا +فمثلاً +فمجافون +فمحمد +فمزج +فمسألة +فمسحوق +فمصادرها +فمصدر +فمضى +فمضينا +فمع +فمعظم +فمعنى +فمفاصل +فمفهوم +فمقابلة +فمقارنةً +فمك +فمكث +فمكنني +فملأ +فملاذهم +فملوكها +فمما +فمن +فمناظرها +فمنحه +فمنحها +فمنذ +فمنطقة +فمنظمة +فمنعني +فمنه +فمنها +فمنهم +فمه +فمها +فمهجتي +فمهما +فمهنة +فموضوع +فموية +فمي +فن +فنأخذ +فنا +فناء +فنادت +فنادق +فنادقها +فنادى +فنار +فناسج +فناشدته +فنال +فنان +فنانا +فناناً +فنانة +فنانو +فنانون +فنانوها +فناني +فنانين +فنانيه +فنبتت +فنتائجها +فنتزاحم +فنتفق +فنتمنى +فنتناول +فنتيجة +فنجان +فنجانا +فنجانه +فنجح +فنجحت +فنجد +فنحن +فندرت +فندق +فندقاً +فندقه +فندقي +فندقية +فنراه +فنزح +فنزعنا +فنسبة +فنسبية +فنسجوا +فنسخ +فنسميها +فنشأ +فنشأت +فنشر +فنصب +فنصحوه +فنصل +فنضب +فنظر +فنظرإليه +فنظرت +فنعود +فنعْم +فنقبل +فنقل +فنقول +فنكرر +فنكون +فنلقي +فنلندا +فنما +فنمت +فنموت +فنه +فنها +فنهضنـا +فنهم +فنوبات +فنون +فنوننا +فنونها +فنى +فني +فنيا +فنياً +فنية +فنيين +فنيًا +فنَّدت +فه +فهؤلاء +فها +فهاجم +فهارس +فهارسك +فهالني +فهاهو +فهاهي +فهب +فهبط +فهبّ +فهد +فهذا +فهذه +فهر +فهراً +فهرب +فهربت +فهرتزل +فهرس +فهرسا +فهرسته +فهرسوا +فهرسًا +فهرع +فهزت +فهضم +فهطلت +فهكذا +فهل +فهلا +فهلوية +فهم +فهما +فهماً +فهمت +فهمتها +فهمك +فهمنا +فهمه +فهمها +فهمي +فهمًا +فهن +فهنا +فهناك +فهنيئاً +فهو +فهوفمان +فهى +فهي +فهيا +فو +فوائد +فوائده +فوائض +فوات +فواجع +فواجه +فواحة +فواخير +فواز +فواعل +فوافق +فوافقت +فوافقها +فوافقهم +فواقع +فوالله +فوج +فوجئ +فوجئا +فوجئت +فوجئنا +فوجئوا +فوجا +فوجد +فوجدت +فوجدته +فوجدتها +فوجدتُ +فوجدنا +فوجدناه +فوجده +فوجدها +فوجدوا +فوجدوه +فوجدوها +فوجنا +فودع +فودعت +فور +فورا +فوراً +فوربان +فوربز +فورة +فورت +فورد +فورم +فوره +فوري +فوريا +فورية +فورًا +فوز +فوزك +فوزه +فوزي +فوزية +فوسائل +فوسفات +فوسفورية +فوسيفير +فوشان +فوضاه +فوضع +فوضعنا +فوضعوا +فوضوي +فوضى +فوعدته +فوعدني +فوفاة +فوفر +فوفّرت +فوق +فوقته +فوقعت +فوقف +فوقفوا +فوقه +فوقها +فوقي +فوقَّعت +فوكو +فوكوه +فوكوياما +فول +فولاذ +فولاذي +فولبي +فولتير +فولع +فولكر +فولكلوريا +فولكلورية +فوهات +فويرزا +فويل +فوينيكس +فوّتت +فوّهة +فوَّهاته +فى +في +فيأتنس +فيأتي +فيأخذ +فيؤدي +فيا +فياض +فيبتسم +فيبتلعوها +فيبتهج +فيبحث +فيبدأ +فيبدو +فيبدي +فيبروفيبر +فيبقى +فيبكي +فيبيعونه +فيت +فيتأهب +فيتالي +فيتامين +فيتامينات +فيتاميناتكم +فيتبعه +فيتحرر +فيتحرش +فيتحرك +فيتحقق +فيتخذها +فيتراكم +فيترجم +فيترك +فيتز +فيتساءلون +فيتساقط +فيتسرب +فيتسرع +فيتشيعون +فيتعامل +فيتعذّر +فيتعلق +فيتعلم +فيتعلموا +فيتم +فيتمثل +فيتمخض +فيتمكن +فيتنام +فيتناول +فيتو +فيتوالد +فيتوقع +فيتوقف +فيتولى +فيثير +فيجب +فيجد +فيجدوا +فيجرى +فيجفل +فيجلس +فيجيب +فيحافظ +فيحاول +فيحاولون +فيحب +فيحبس +فيحتاج +فيحترم +فيحتفل +فيحدث +فيحدثنا +فيحرم +فيحصل +فيحفرون +فيحفظها +فيحكي +فيحول +فيحييها +فيختفي +فيخرج +فيخصص +فيخضع +فيخطئه +فيخطر +فيخفف +فيدخل +فيدر +فيدركرز +فيدعو +فيدفع +فيدل +فيدمر +فيدور +فيدوسييف +فيديو +فيذكر +فيذكرنا +فيرا +فيرارا +فيراه +فيراها +فيربانكس +فيرتج +فيرتجف +فيرجع +فيرجين +فيردد +فيردم +فيردونها +فيرز +فيرسم +فيرفض +فيرقي +فيركز +فيركور +فيرمون +فيرموناتها +فيرن +فيرنيه +فيروح +فيروز +فيروس +فيروسا +فيروسات +فيروسي +فيروسية +فيروفياس +فيرون +فيروي +فيرى +فيزا +فيزحف +فيزداد +فيزياء +فيزيائيا +فيزيائيًا +فيزيد +فيزيقية +فيزيولوجي +فيزيولوجية +فيستبد +فيستجيب +فيستخدم +فيستدير +فيستسلمون +فيستكين +فيستلزم +فيستمر +فيستوطن +فيسد +فيسرد +فيسرع +فيسعى +فيسقط +فيسقيني +فيسكنون +فيسهل +فيش +فيشترى +فيشد +فيشرحه +فيشعر +فيشكو +فيشوهه +فيشير +فيصبح +فيصحبني +فيصدق +فيصفها +فيصل +فيصلي +فيصوره +فيصيبه +فيصير +فيض +فيضان +فيضانه +فيضحي +فيضطر +فيضطرب +فيضع +فيضل +فيضيع +فيضيف +فيطالب +فيطرح +فيطرحه +فيطمئن +فيظلوا +فيعالج +فيعبر +فيعتلي +فيعتمد +فيعجز +فيعرج +فيعرضهن +فيعرفون +فيعزز +فيعفى +فيعلق +فيعلم +فيعمل +فيعود +فيعودون +فيعيد +فيعيشون +فيفاجأوا +فيفاكس +فيفر +فيفشل +فيفضل +فيفعل +فيفقد +فيفهمه +فيفيان +فيفيض +فيقبض +فيقبل +فيقترح +فيقدم +فيقدمون +فيقرؤون +فيقصم +فيقع +فيقف +فيقلل +فيقمعونه +فيقول +فيقوم +فيقيم +فيك +فيكاد +فيكتب +فيكتسب +فيكتسح +فيكتفي +فيكتور +فيكتوريا +فيكسره +فيكمن +فيكون +فيكونت +فيكوّن +فيكي +فيكيدون +فيكِ +فيل +فيلا +فيلبسونها +فيلبيرت +فيلة +فيلتقي +فيلتهم +فيلد +فيلدونج +فيلسوف +فيلسوفا +فيلسوفاً +فيلسوفهم +فيلفت +فيلق +فيلقى +فيلقي +فيلكا +فيلم +فيلما +فيلماً +فيلمه +فيلمها +فيلمي +فيلمًا +فيلوث +فيلونج +فيليب +فيليه +فيم +فيما +فيماتصل +فيمان +فيمتد +فيمتزج +فيمتص +فيمتليء +فيمضي +فيمكثُ +فيمكن +فيمكننا +فيملأن +فيملؤها +فيمن +فيمنع +فيموت +فيموتون +فيميزها +فينا +فينادي +فينايل +فينتابهم +فينتج +فينتشر +فينتظر +فينتقل +فينخفض +فيندفع +فينزل +فينساقون +فينسيا +فينشط +فينطلق +فينطوي +فينعكس +فينقسم +فينوس +فيني +فينيسيا +فينيقيا +فينيقية +فيه +فيها +فيهاجمها +فيهبّ +فيهرب +فيهـــا +فيهلك +فيهلكها +فيهم +فيهما +فيورد +فيوسف +فيونتس +فيّ +فَاسْتَجَابَ +فَالَّذِينَ +فَتَخْطَفُه +فَتِيَّةً +فَصَلتْ +فَقَبِلته +فَقْد +فَكّرَ +فَمِنْهُم +فَهْم +فَيَذّهَبُ +فُرض +فُسحٌ +فُصل +فُصلتْ +فُطر +فُطرت +فُهمت +فِي +ق +قائد +قائدا +قائدات +قائدة +قائدها +قائدًا +قائظة +قائل +قائلا +قائلاً +قائلة +قائلها +قائم +قائما +قائماً +قائمة +قائمًا +قابضة +قابضين +قابع +قابعا +قابعة +قابل +قابلا +قابلاً +قابلة +قابلت +قابلتان +قابلتنا +قابلته +قابلتها +قابلناهم +قابله +قابلها +قابلهم +قابلية +قابليتها +قابوس +قابيل +قات +قاتل +قاتلا +قاتلة +قاتلوا +قاتم +قاتما +قاتمة +قاحل +قاحلة +قاد +قادة +قادت +قادتني +قادته +قادتها +قادحة +قادر +قادرا +قادران +قادراً +قادرة +قادرون +قادرين +قادرًا +قادم +قادما +قادماً +قادمة +قادمون +قادمين +قادنا +قادني +قاده +قادها +قار +قارئ +قارئا +قارئاً +قارئة +قارئنا +قارئه +قارئها +قارئي +قارات +قارب +قاربت +قاربها +قاربوا +قاربًا +قارة +قارته +قارتهم +قارتين +قارس +قارساً +قارعا +قارعةِ +قارن +قارنا +قارنت +قاري +قاريء +قازان +قاس +قاسم +قاسماً +قاسى +قاسيا +قاسياً +قاسية +قاسيون +قاصاً +قاصدا +قاصدة +قاصدين +قاصدًا +قاصر +قاصرا +قاصرات +قاصراً +قاصرة +قاضي +قاضيا +قاضيات +قاضياً +قاضية +قاضيًا +قاطبة +قاطع +قاطعا +قاطعات +قاطعة +قاطعت +قاطعتها +قاطعه +قاطني +قاطنيه +قاطنيها +قاع +قاعات +قاعاته +قاعة +قاعتها +قاعدا +قاعدة +قاعه +قاعها +قافكو +قافلة +قافلتي +قال +قالا +قالب +قالت +قالته +قالتها +قاله +قالها +قالوا +قالوها +قام +قاما +قامة +قامت +قامتها +قامتي +قاموا +قاموس +قاموسها +قاموسي +قاموسًا +قانون +قانونا +قانوناً +قانونى +قانوني +قانونيا +قانونية +قانونيًا +قانية +قاهر +قاهرة +قاوم +قاوما +قاومت +قاومه +قايتباي +قباء +قبائل +قبائلها +قباب +قبالة +قبالتنا +قبالته +قباني +قبباً +قبة +قبحا +قبر +قبراً +قبرص +قبره +قبسًا +قبض +قبضا +قبضة +قبضت +قبضته +قبضتها +قبضوا +قبعة +قبقاب +قبل +قبلا +قبلات +قبلاته +قبلاً +قبلة +قبلت +قبلته +قبلكم +قبلني +قبله +قبلها +قبلهم +قبلهما +قبلي +قبلية +قبلُ +قبواً +قبور +قبول +قبولا +قبولاً +قبوله +قبولها +قبولهم +قبيحاً +قبيحة +قبيس +قبيل +قبيلة +قبيلتك +قبيلته +قبيلتها +قبيلتي +قبيلتين +قبّاني +قبّلت +قبّلته +قتادة +قتال +قتالا +قتامتها +قتل +قتلا +قتلانا +قتلاه +قتلت +قتلته +قتلتْه +قتلنا +قتله +قتلهم +قتيبة +قتيبية +قتيلا +قح +قحط +قد +قداسة +قدامى +قدر +قدرا +قدرات +قدراتك +قدراتنا +قدراته +قدراتها +قدراتهم +قدراتهما +قدراتي +قدراه +قدراً +قدرة +قدرت +قدرتكم +قدرتنا +قدرته +قدرتها +قدرتهم +قدرنا +قدره +قدرها +قدرهم +قدرون +قدري +قدريا +قدريًا +قدرًا +قدس +قدسية +قدسيته +قدم +قدما +قدماء +قدماك +قدمان +قدماني +قدماه +قدماها +قدماي +قدماً +قدمت +قدمتم +قدمته +قدمتها +قدمنا +قدمه +قدمها +قدموا +قدموس +قدمي +قدميك +قدمين +قدميه +قدميها +قدميّ +قدمٌ +قدوة +قدور +قدورة +قدوم +قدوماً +قدومه +قدومها +قدومهم +قدير +قديسة +قديش +قديم +قديما +قديماً +قديمة +قديمه +قديمها +قديمًا +قدّر +قدّرت +قدّم +قدّمت +قدّمتها +قدّمناه +قدّمها +قدّيساً +قدَّم +قدَّمها +قذرة +قذف +قذفت +قذفتنا +قذفتهما +قذفها +قذفوا +قرآن +قرآنا +قرآني +قرآنية +قرأ +قرأت +قرأتم +قرأته +قرأتها +قرأتُ +قرأنا +قرأناها +قرأه +قرأها +قرأوا +قرا +قراء +قراءات +قراءاته +قراءاتهم +قراءاتي +قراءة +قراءةالعالم +قراءةٍ +قراءتك +قراءته +قراءتها +قراءتي +قرائن +قرائه +قرائها +قرابة +قرابين +قرابيني +قرار +قرارا +قرارات +قراراته +قراراتهم +قراراً +قرارة +قرارته +قرارك +قراره +قرارها +قراري +قرارًا +قراصنة +قراض +قراميدان +قران +قرانات +قرانه +قرانهما +قراني +قراهم +قرب +قربانا +قرباً +قربة +قربت +قربته +قربه +قربها +قرة +قرحات +قرد +قردا +قردوح +قرر +قررا +قررت +قررتها +قررها +قرروا +قرش +قرشا +قرشت +قرشًا +قرص +قرصان +قرصي +قرض +قرضت +قرطاج +قرطاس +قرطبة +قرع +قرعة +قرعته +قرن +قرنا +قرناً +قرنق +قرنه +قرني +قرنية +قرنين +قرنيين +قرنًا +قره +قرود +قروش +قروض +قروضاً +قرون +قرونا +قرونه +قروياً +قروية +قرى +قريات +قريب +قريبا +قريبات +قريبان +قريباً +قريبة +قريبته +قريبي +قريبًا +قرية +قريتنا +قريته +قريتها +قريتي +قريحة +قريش +قريع +قرين +قرينه +قرّاء +قرّائه +قرّر +قرَّر +قزح +قزحية +قزق +قزم +قزمه +قسائم +قساوة +قساوسة +قست +قسر +قسرا +قسط +قسطا +قسطنطين +قسم +قسما +قسمان +قسماً +قسمناه +قسمها +قسموا +قسموها +قسمين +قسمًا +قسوة +قسوتها +قسيس +قسيسا +قسيمة +قش +قشتالة +قشر +قشرة +قشرتها +قشريات +قشعريرة +قشور +قشورها +قشيبة +قص +قصائد +قصائدنا +قصائده +قصائدهِ +قصائدي +قصارى +قصاقيص +قصب +قصبة +قصة +قصتان +قصته +قصتها +قصتهم +قصتين +قصد +قصدت +قصدته +قصدتُ +قصدناه +قصدوا +قصدير +قصديريا +قصر +قصرا +قصرت +قصرنا +قصره +قصرها +قصرهما +قصروا +قصص +قصصا +قصصاً +قصصه +قصصها +قصصي +قصصياً +قصصية +قصصًا +قصعة +قصف +قصفها +قصمت +قصور +قصورا +قصوراً +قصورهم +قصوى +قصي +قصياً +قصيدة +قصيدته +قصيدتهم +قصيدتي +قصيده +قصير +قصيرا +قصيرة +قصيّة +قصّة +قض +قضاء +قضاؤه +قضائه +قضائها +قضائي +قضائية +قضاه +قضاها +قضاهما +قضايا +قضايانا +قضاياهم +قضبان +قضت +قضم +قضوا +قضى +قضيب +قضية +قضيت +قضيتك +قضيتنا +قضيته +قضيتها +قضيتين +قضينا +قضيناها +قضيّة +قط +قطار +قطارات +قطاران +قطاع +قطاعا +قطاعات +قطاعاتها +قطاعها +قطاعي +قطاف +قطب +قطبان +قطبي +قطبية +قطة +قطر +قطرات +قطران +قطرة +قطرتين +قطره +قطرها +قطط +قططها +قطع +قطعا +قطعان +قطعانا +قطعاً +قطعة +قطعةً +قطعت +قطعتان +قطعتها +قطعتين +قطعنا +قطعه +قطعها +قطعوها +قطعياً +قطعية +قطف +قطفا +قطفتها +قطفه +قطنا +قطنوا +قطني +قطه +قطوف +قطيع +قطيعا +قطيعاً +قطيعة +قطيعها +قطَّعوا +قعر +قعقعة +قـول +قف +قفاها +قفر +قفز +قفزات +قفزاته +قفزة +قفزت +قفص +قل +قلائل +قلادات +قلادة +قلاع +قلاقل +قلب +قلبا +قلباَ +قلبت +قلبك +قلبكم +قلبنا +قلبه +قلبها +قلبي +قلبية +قلة +قلت +قلتم +قلته +قلتها +قلتَ +قلتُ +قلتِ +قلدت +قلده +قلدوا +قلص +قلصت +قلع +قلعة +قلعتا +قلعتان +قلعها +قلق +قلقا +قلقاً +قلقة +قلقت +قلقه +قلقها +قلقون +قلقي +قلقين +قلقًا +قلل +قللت +قلم +قلما +قلماً +قلمه +قلمها +قلمي +قلنا +قلوب +قلوبكم +قلوبنا +قلوبها +قلوبهم +قليل +قليلا +قليلاً +قليلة +قليلي +قلّ +قلّة +قلّما +قلَّ +قم +قماش +قماشة +قماشيا +قمامة +قمة +قمت +قمتم +قمته +قمتها +قمتى +قمتين +قمتُ +قمح +قمر +قمرا +قمراً +قمرية +قمرين +قمصان +قمع +قمعين +قمل +قمم +قممها +قمنا +قمو +قميرى +قميص +قميصا +قميصه +قميصها +قمّة +قمَّة +قنابل +قناة +قناته +قناتها +قناديل +قناصو +قناطير +قناطيراً +قناع +قناعا +قناعات +قناعاته +قناعاتهم +قناعاً +قناعة +قناعتي +قناعي +قناعًا +قنافذ +قنبلة +قنبلتان +قنبلته +قندهار +قنديل +قنزعتان +قنصلي +قنصليات +قنصوة +قنطارا +قنطرة +قنعت +قنفذا +قنوات +قنواتها +قنينة +قنينته +قنينتهم +قهر +قهرت +قهقهاته +قهقهوا +قهوة +قوائم +قوائمه +قوات +قوارب +قوارض +قوارير +قواسم +قواصفها +قواطع +قواعد +قوافل +قوافلها +قوافلهم +قوافيها +قواقع +قوالب +قوام +قواما +قوامته +قوامه +قوامها +قوامي +قواميس +قوانين +قوانينها +قواه +قواها +قوبل +قوبلت +قوة +قوتان +قوتك +قوتكم +قوتنا +قوته +قوتها +قوتي +قورن +قورنت +قوروش +قوس +قوسي +قوسين +قوطان +قوقعة +قوقعتها +قول +قولاً +قولبة +قولة +قولك +قوله +قولهم +قولوا +قولي +قوليها +قوم +قومه +قومها +قوموا +قومي +قوميا +قومياً +قومية +قوميتين +قومٌ +قومِهِ +قونيا +قوى +قوي +قويا +قوياً +قوية +قويةً +قويتين +قويم +قويًا +قويّ +قويّة +قويًّا +قوّة +قي +قيء +قيادات +قياداته +قيادة +قيادته +قيادتها +قيادتي +قيادية +قياس +قياسا +قياسات +قياساتها +قياساً +قياسه +قياسها +قياسي +قياسياً +قياسية +قياصرة +قيام +قياماً +قيامك +قيامه +قيامها +قيامهم +قيامهن +قيثارة +قيثاري +قيحية +قيد +قيدناه +قيدني +قيده +قيدها +قير +قيس +قيسارية +قيست +قيصر +قيصري +قيضها +قيظ +قيعان +قيل +قيلة +قيلنش +قيم +قيما +قيمة +قيمتك +قيمته +قيمتها +قيمتهما +قيمتي +قيمنا +قيمه +قيمهم +قيمية +قيود +قيوداً +قيوده +قيودها +قيوم +قيّمة +قَدَرًا +قَدَرْنا +قَضَى +قَلَبة +قَلْت +قُبلها +قُبِلوا +قُتل +قُدر +قُدِّرت +قُرنوا +قُصد +قُلْ +قُيِّض +قِبل +قِبَل +ك +كآباء +كآبة +كآبته +كآلاف +كأحد +كأحدهم +كأحطاب +كأداء +كأداة +كأدبه +كأديب +كأراض +كأس +كأساس +كأساً +كأسباب +كأستاذ +كأستاذة +كأسرة +كأسنان +كأسين +كأشرطة +كأشكال +كأشهر +كأعضاء +كأفراد +كأفضل +كأكل +كأم +كأمانة +كأمة +كأمثلة +كأمل +كأن +كأنثى +كأنسي +كأنف +كأنك +كأنما +كأننا +كأنني +كأنه +كأنها +كأنهم +كأنهما +كأني +كأهل +كأوزة +كأول +كأولويات +كأي +كأيام +كأينشتاين +كؤوس +كإجراء +كإسفنجة +كإطار +كإقامة +كإمام +كإنسان +كإنسانة +كإنقاص +كإيجار +كئوسهم +كئيب +كئيبا +كئيبة +كا +كائد +كائن +كائنا +كائنات +كائناً +كائنه +كائنين +كابتن +كابريرا +كابل +كابوس +كابوسا +كابوساً +كابول +كابيتان +كابيه +كات +كاتب +كاتبا +كاتبات +كاتبان +كاتباً +كاتبة +كاتبنا +كاتبه +كاتبها +كاتبوها +كاتدرائية +كاترين +كاتسورة +كاتكوف +كاتو +كاثوليكي +كاثوليكية +كاحتمال +كاحتياطي +كاحل +كاد +كادت +كادوا +كاديلاك +كاذب +كاذبا +كاذبات +كاذبة +كاراتشي +كاراتيه +كارامازوف +كارتر +كارثة +كارثية +كارثيًا +كاردوسو +كاردينالي +كارسة +كارستان +كارسن +كارفاليو +كارل +كارلا +كارلسروه +كارلهاينز +كارلوس +كارليل +كارم +كارنافون +كارها +كارهي +كاروتين +كارولاينا +كارولو +كارولينا +كارولينسكا +كاريزما +كاريكاتورية +كاريكاتير +كاريكاتيريا +كارين +كارينا +كازا +كازابلانكا +كازاكوف +كازاماذا +كازانـتزاكس +كازينو +كاسبر +كاستثمار +كاستجابة +كاستخدامها +كاسترو +كاسح +كاسر +كاسف +كاسكاد +كاسكل +كاسيات +كاسيت +كاشفة +كاشفًا +كاظم +كاف +كافأت +كافأته +كافافي +كافة +كافر +كافنديش +كافور +كافي +كافيا +كافياً +كافية +كافٍ +كاقتصادنا +كالآتي +كالآلية +كالأراضي +كالأرض +كالأسرة +كالأطفال +كالأعوام +كالأفعى +كالأمد +كالأوردو +كالإبل +كالاتحاد +كالاجتماع +كالاستشارة +كالاشتراكية +كالاضطهاد +كالانتماء +كالبارود +كالبترول +كالبر +كالبرامج +كالبربر +كالبرعمة +كالبطن +كالبنك +كالبنيان +كالبياتي +كالبيوت +كالتالي +كالتبشير +كالتخطيط +كالتدريبات +كالتعاون +كالتقدم +كالتكنولوجيا +كالتلوث +كالتمثال +كالتهاب +كالتي +كالتيوبا +كالثلج +كالجبل +كالجثث +كالجراحة +كالجرح +كالجمر +كالجنس +كالجواهر +كالح +كالحة +كالحديد +كالحرية +كالحضارة +كالحليب +كالحمامة +كالحيوانات +كالخروج +كالخس +كالخوف +كالخيامية +كالدار +كالدم +كالدورة +كالدولار +كالذكاء +كالذهب +كالذي +كالرؤى +كالرئيس +كالراهب +كالرجل +كالرشوة +كالرياض +كالرياضيات +كالريح +كالزبرجد +كالزرافة +كالزمن +كالزهري +كالساقية +كالسامر +كالسحر +كالسرطان +كالسلسلة +كالسماء +كالسهم +كالسوائل +كالسيارة +كالسيل +كالسيمفونية +كالسيوم +كالشجرة +كالشعر +كالشمس +كالشيخ +كالصيد +كالضخامة +كالطائفية +كالطب +كالطرق +كالطلاق +كالعادة +كالعاشق +كالعرب +كالعرقسوس +كالعسكري +كالعصفور +كالعطارة +كالعقلانية +كالعنصرية +كالعود +كالعيس +كالعِلم +كالفارسية +كالفتح +كالفرنسية +كالفلسفة +كالفن +كالفنادق +كالقادرية +كالقباب +كالقص +كالقناع +كالقنبلة +كالكتاب +كالكلابِ +كالكمبيوتر +كالكوتا +كاللذة +كالماء +كالمارد +كالمتاحف +كالمجنونة +كالمختبر +كالمختبرات +كالمدارس +كالمدرسة +كالمدفع +كالمدنية +كالمرايا +كالمرقوم +كالمستجير +كالمسجد +كالمشي +كالمصابين +كالمطارق +كالمعتاد +كالمعلبات +كالمعلمة +كالمقصات +كالملح +كالملفات +كالمنومة +كالمواطنة +كالموت +كالميثانول +كالميراث +كالنار +كالنازية +كالنباتات +كالنبع +كالنحاس +كالنخلة +كالند +كالنشر +كالنظر +كالنفط +كالنكتة +كالهضاب +كالوجودية +كالوحش +كالوديان +كالوري +كالولايات +كالي +كاليفورنيا +كاليكولو +كاليوم +كامب +كامبردج +كامتداد +كامرأة +كامل +كاملا +كاملاً +كاملة +كاملةً +كاملتين +كاملين +كامن +كامنا +كامناً +كامنة +كامنًا +كامو +كاميرا +كاميراتهم +كاميرته +كاميليا +كان +كانا +كانت +كانتا +كانتفاخ +كانتون +كانجارو +كانخفاض +كاندي +كانسلاخ +كانط +كانوا +كانون +كانْ +كاهل +كاهلها +كاهن +كاهوتا +كاونتر +كب +كبار +كبارا +كباراً +كباريس +كباريه +كباقي +كبت +كبح +كبحث +كبحّار +كبد +كبدت +كبدها +كبدي +كبديل +كبر +كبراهن +كبراهنّ +كبرت +كبرتم +كبرتُ +كبروا +كبرى +كبريات +كبرياتها +كبريانو +كبريتات +كبساط +كبسه +كبسول +كبسولات +كبش +كبشر +كبطانة +كبطل +كبطن +كبعض +كبــــيرة +كبقية +كبل +كبلينج +كبناء +كبنت +كبني +كبنية +كبوتنا +كبوتها +كبير +كبيرا +كبيران +كبيراً +كبيرة +كبيرةً +كبيرتين +كبيرهم +كبيرين +كبيرًا +كبيرِ +كتائب +كتاب +كتابا +كتابات +كتاباتك +كتاباته +كتاباتهم +كتاباتي +كتابان +كتاباً +كتابة +كتابتنا +كتابته +كتابتها +كتابتي +كتابك +كتابنا +كتابه +كتابها +كتابهما +كتابي +كتابية +كتابين +كتابيه +كتابًا +كتابٌ +كتاريخ +كتاكسيات +كتايب +كتب +كتبا +كتباً +كتبة +كتبت +كتبته +كتبتها +كتبتيها +كتبتُ +كتبتُه +كتبدار +كتبـــــه +كتبنا +كتبناها +كتبنها +كتبه +كتبها +كتبهم +كتبوا +كتبي +كتبًا +كتبْتُ +كتجار +كتجربة +كتحت +كتحفة +كتخفيف +كتعبير +كتــــابة +كتف +كتفك +كتفه +كتفها +كتفي +كتفيك +كتفيه +كتفيها +كتقديم +كتل +كتلة +كتلته +كتلتها +كتلتين +كتلك +كتلميذ +كتلوين +كتم +كتمارين +كتهمة +كتيب +كتيبات +كتيبة +كتيبًا +كتّاب +كتّاباً +كثافة +كثاني +كثب +كثبان +كثر +كثرة +كثرت +كثرته +كثرتها +كثف +كثفت +كثورته +كثير +كثيرا +كثيرات +كثيراً +كثيرة +كثيرون +كثيري +كثيرين +كثيرًا +كثيرٍ +كثيف +كثيفا +كثيفة +كثُرت +كجامعة +كجبال +كجذع +كجرح +كجرعات +كجزء +كجلد +كجلمود +كجم +كجندي +كجنس +كجيمس +كحاج +كحافز +كحال +كحالة +كحبات +كحتمية +كحجر +كحد +كحدّ +كحراس +كحرف +كحركة +كحظه +كحفيف +كحقن +كحل +كحلاً +كحلقة +كحليا +كحمض +كحمّال +كحولية +كحياته +كخامات +كخبرة +كخبير +كخزينة +كخسارة +كخط +كخطأ +كخطوة +كخطوط +كخلية +كخليفة +كخياط +كخيول +كدت +كدتُ +كدح +كدراسات +كدسة +كدقات +كدليل +كدموع +كدمية +كدولة +كدي +كدين +كديوان +كدّ +كدّويّ +كذا +كذب +كذبة +كذبوا +كذلك +كر +كرأس +كرئيس +كرائد +كرابط +كرات +كراتشكوفسكي +كراتشي +كراج +كراسات +كراسي +كراعية +كراقص +كرام +كراماته +كرامة +كرامةً +كرامته +كرامتهم +كراهية +كراوز +كراوٍ +كرايزلر +كرايسلر +كربته +كربكسيفان +كربلاء +كربوجا +كربون +كربونات +كربونية +كرة +كرتك +كرتنا +كرتون +كرتونا +كرج +كرجال +كرجالات +كرحالة +كرد +كردي +كردّة +كرر +كررت +كرز +كرس +كرست +كرسوم +كرسي +كرسيا +كرسيه +كرش +كرضوي +كركام +كركوتلي +كركوك +كرم +كرما +كرماء +كرمة +كرمت +كرمز +كرمنا +كرمها +كرموز +كرمى +كرمٌ +كره +كرهت +كرهتموهن +كرهته +كرهتُ +كرهًا +كرهٌ +كروائية +كروان +كرواية +كروحه +كروز +كروس +كروش +كرومر +كروموزوماتها +كروموسومات +كروية +كريات +كريت +كريستوس +كريستوف +كريستوفر +كريستي +كريستيان +كريستياني +كريستين +كريستينسين +كريسماس +كريكت +كريم +كريما +كريمان +كريماً +كريمة +كريمته +كريمي +كريمًا +كرين +كريهة +كريوبلان +كرّت +كرّسه +كرَّةً +كزميل +كزوجتي +كزيادة +كزينة +كسائه +كسابقتها +كسابقه +كساحات +كساد +كساه +كساوي +كسبب +كسبت +كسبرالي +كسبره +كسبه +كسر +كسراب +كسرعة +كسره +كسروا +كسروه +كسفراء +كسل +كسلا +كسلي +كسمكة +كسنابل +كسوات +كسوة +كسور +كسوف +كسوق +كسويسرا +كسياسة +كشأن +كشاب +كشارع +كشارون +كشاعر +كشاعرة +كشجرة +كشخص +كشخصية +كشر +كشرط +كشركات +كشركة +كشروحات +كشريط +كشعار +كشعب +كشف +كشفا +كشفت +كشفنا +كشفه +كشفية +كشفًا +كشموخ +كشمير +كشهرة +كشوف +كشوفات +كشوفه +كصبر +كصحفي +كصدى +كصفحة +كصلة +كصناعة +كصوت +كصورة +كضابط +كضرورة +كضيف +كطائر +كطارد +كطالب +كطرف +كطريقة +كطعام +كطفلة +كطيّار +كظاهرة +كظلك +كظله +كعادة +كعادته +كعادتها +كعالم +كعامل +كعب +كعرب +كعضو +كعقار +كعكة +كعلاج +كعلامة +كعلم +كعملات +كعملة +كعنوان +كعهدها +كعيكاتي +كـ +كـوانج +كف +كفء +كفؤا +كفئاً +كفاء +كفاءات +كفاءاتها +كفاءة +كفاءته +كفاءتها +كفاءتهم +كفاءتي +كفاتورة +كفاح +كفاحه +كفاحها +كفاحي +كفارة +كفارس +كفاك +كفالات +كفاه +كفاوين +كفايات +كفاية +كفة +كفت +كفته +كفتوح +كفتي +كفحول +كفر +كفرا +كفرنسا +كفريق +كفرًا +كفك +كفكرة +كفكف +كفل +كفلج +كفنان +كفه +كفى +كفي +كفيف +كفيفا +كفيل +كفيلان +كفيلاً +كفيلة +كفين +كفّة +كفّت +كفَّة +كفِّ +كقارب +كقاصّة +كقاعة +كقاعدة +كقرية +كقسم +كقصبة +كقصة +كقضاة +كقطرة +كقطع +كقطيع +كقلائد +كقوة +كقيمة +ككائن +ككاتب +ككاتبة +ككتّاب +ككل +ككلاب +ككلية +ككوادر +ككوبيين +ككومبارس +كل +كلا +كلاب +كلاباً +كلابريا +كلارا +كلارك +كلارينز +كلاسيك +كلاسيكي +كلاسيكية +كلاسيكيّ +كلام +كلاما +كلاماً +كلامك +كلامنا +كلامه +كلامها +كلامهم +كلامي +كلامية +كلاميديا +كلانا +كلانجا +كلاهما +كلاوس +كلاي +كلاين +كلاً +كلاًّ +كلب +كلبه +كلبها +كلبي +كلتا +كلتاهما +كلتيهما +كلثوم +كلرز +كلش +كلعبة +كلف +كلفة +كلفت +كلفتك +كلفته +كلفتها +كلفك +كلفني +كلفه +كلكامش +كلكم +كلل +كللت +كلما +كلمات +كلماتك +كلماته +كلماتها +كلماتهما +كلماتي +كلمة +كلمةً +كلمةٍ +كلمتا +كلمتان +كلمته +كلمتها +كلمتي +كلمتين +كلمن +كلنا +كله +كلها +كلهم +كلهن +كلوب +كلود +كلوديا +كلور +كلورادو +كلورايد +كلوفر +كليا +كليات +كلياً +كليب +كلية +كليةً +كليته +كلير +كليرز +كليفلاند +كليفورد +كليلة +كلينتون +كليهما +كليو +كليوباترا +كلٌ +كلٍ +كلَها +كلّ +كلٌّ +كلَّ +كلِّ +كلِّيَّةً +كم +كمؤرخ +كمؤسسات +كمؤسسة +كمؤشر +كمؤشرات +كمؤلف +كمئات +كما +كماأن +كمادات +كمادة +كمال +كمامته +كمان +كمبردج +كمبوديا +كمبيد +كمبيدات +كمبيوتر +كمبيوتل +كمتجه +كمتحدث +كمترجم +كمتطلب +كمثال +كمثل +كمجتمع +كمجرد +كمحاربين +كمحددات +كمحرر +كمحمد +كمختلف +كمخرج +كمخرجة +كمدرس +كمدن +كمدير +كمدينة +كمذيب +كمراكز +كمرايا +كمرشد +كمرض +كمرضى +كمركز +كمزار +كمزولة +كمساعد +كمسافر +كمسبب +كمستحضر +كمستحضرات +كمستشار +كمستعربين +كمستقبلات +كمستهلكين +كمسلم +كمسلمين +كمشاهد +كمشرف +كمشروب +كمشكلة +كمصادر +كمصدات +كمصدر +كمصر +كمصور +كمطرب +كمظهر +كمعاملة +كمعدل +كمعدن +كمعظم +كمفتاح +كمفكر +كمقدم +كمقصد +كمل +كملف +كملوحة +كممثل +كمملكة +كممول +كمن +كمناضل +كمنبه +كمنتج +كمنجة +كمنشد +كمنطق +كمنطقة +كمنفذ +كمنهج +كمهتمين +كمهد +كمهر +كمهندس +كمهندسة +كمواد +كمواطنين +كمواقف +كموج +كمورد +كموسوعة +كموضة +كموطن +كمون +كميات +كمياته +كمياتها +كمياه +كمية +كميت +كميته +كمين +كمينا +كمّ +كمّاً +كمّيّة +كمًّا +كمُّ +كن +كنا +كنائس +كناري +كناشنا +كناقد +كنانات +كنانة +كناني +كنانيا +كناية +كنبات +كنت +كنتاكى +كنتاكي +كنتم +كنتها +كنتيجة +كنتُ +كنتُه +كنتِ +كنج +كنجة +كنجز +كندا +كندي +كندية +كنز +كنزا +كنزاً +كنزهة +كنزو +كنسبة +كنشرة +كنصب +كنظام +كنعان +كنـته +كنف +كنفه +كنفها +كنقيق +كنمط +كنموذج +كنهر +كنهه +كنهها +كنواة +كنوز +كنوزنا +كنوزها +كنوزًا +كنوع +كنية +كنيدي +كنيس +كنيسة +كنيسته +كنّ +كنّا +كهؤلاء +كهدف +كهدية +كهذا +كهذه +كهرباء +كهربائي +كهربائياً +كهربائية +كهربائيًا +كهربية +كهروكيميائيًا +كهف +كهفا +كهفي +كهلة +كهواة +كهواية +كهوف +كهولته +كهولندا +كهونيم +كو +كوابيس +كوابينا +كوات +كواحات +كواحد +كواحدة +كوادر +كوادره +كوارتيت +كوارث +كواكب +كوالالمبور +كوالدك +كوالده +كوامن +كوانج +كوب +كوبا +كوباكابانا +كوبر +كوبري +كوبي +كوة +كوتد +كوتسيا +كوجه +كوجهة +كوحدة +كوخ +كودا +كوده +كورت +كورتيزونية +كورليس +كورنيش +كورنيل +كورونا +كوري +كوريا +كوريتاسكوت +كورينايكا +كوريني +كوزارات +كوزارة +كوزموبوليتان +كوزموبوليتانية +كوزير +كوست +كوستاريكا +كوسوفا +كوسيط +كوسيلة +كوشما +كوفئ +كوفاري +كوفمان +كوفي +كوفية +كوفير +كوفيّ +كوفيّته +كوقود +كوكا +كوكب +كوكبة +كوكبنا +كوكس +كوكيلة +كول +كولدج +كولمبس +كولمبوس +كولورادو +كولومبس +كولومبو +كولومبوس +كولومبيا +كوليربا +كوليردج +كوم +كوما +كومبانترين +كومبيفير +كومبيوترية +كومة +كومدكس +كومنتري +كوميدي +كوميديا +كون +كونابل +كوناً +كونت +كونتنو +كونج +كونديرا +كونراد +كونستانت +كونسورتيوم +كونسولو +كونسيرج +كونشوار +كونفشيوس +كونك +كونكايت +كونكتسف +كونكتكت +كونكورد +كونلز +كوننا +كونه +كونها +كونهم +كوني +كونيا +كونيان +كونية +كونيكتيكت +كوهبي +كوهن +كويتا +كويتي +كوين +كوينزلاند +كوّن +كى +كي +كياروستامي +كياس +كياستك +كيان +كيانات +كيانه +كيانها +كياني +كيب +كيد +كير +كيربرشويك +كيرستين +كيركجارد +كيرلا +كيز +كيس +كيسا +كيسادا +كيساً +كيسها +كيسيّ +كيف +كيفما +كيفي +كيفية +كيكرز +كيلاني +كيلبورن +كيلة +كيلو +كيلوجرام +كيلوجراما +كيلوجرامين +كيلومتر +كيلومترا +كيلومترات +كيلومتراً +كيلومترين +كيلومترًا +كيما +كيماوي +كيماويات +كيماوية +كيموسكوب +كيمياء +كيميائي +كيميائيا +كيميائياً +كيميائية +كين +كينج +كيندي +كينك +كينون +كينونة +كينيا +كينيه +كيوتو +كيَّفه +كَبُرَ +كُتب +كُتبت +كُتُب +كُتِبَ +كُتّاب +كُثر +كُسيت +كُفِّي +كُلى +كُلّفتْ +كُلِّف +ل +لآثار +لآخر +لآداب +لآدابها +لآدم +لآفات +لآفاقها +لآل +لآلئ +لآلات +لآلاف +لآلة +لآماد +لآمال +لآيات +لأ +لأؤدي +لأؤكد +لأب +لأبحاث +لأبحث +لأبدأ +لأبدلوا +لأبرر +لأبرز +لأبسط +لأبعاد +لأبقراط +لأبناء +لأبنائنا +لأبنائه +لأبنائها +لأبنائهم +لأبنائهما +لأبنك +لأبوظبي +لأبويه +لأبي +لأبيض +لأبيه +لأتابع +لأتباعه +لأتبين +لأتساءل +لأتعلم +لأتممها +لأتوقع +لأتولى +لأثمرت +لأثير +لأجبت +لأجبتك +لأجد +لأجدادهم +لأجدّ +لأجزاء +لأجل +لأجلبهم +لأجله +لأجمع +لأجنده +لأجهزة +لأحجية +لأحد +لأحدث +لأحدها +لأحدهم +لأحضره +لأحكام +لأحلام +لأحلى +لأحمد +لأحمل +لأحوال +لأخبار +لأخذ +لأخرجها +لأخره +لأخرى +لأخطار +لأخلاق +لأخي +لأداء +لأدب +لأدباء +لأدبك +لأدبه +لأدرس +لأدركت +لأدركنا +لأدفع +لأدنى +لأدوية +لأدويتها +لأدي +لأذاكر +لأذكر +لأذواق +لأذواقهم +لأذوق +لأذية +لأرأس +لأراضي +لأراقب +لأربط +لأربع +لأربعة +لأرسطو +لأرسطوفان +لأرسم +لأرقام +لأرى +لأريك +لأريكم +لأزحنا +لأزدجر +لأزمات +لأزمة +لأزمته +لأسئلة +لأسابيع +لأساتذة +لأسال +لأساليب +لأساهم +لأسباب +لأسبوعين +لأستاذه +لأستاذها +لأستاذي +لأستاذية +لأستجلي +لأستعين +لأستكشافها +لأسر +لأسرة +لأسرته +لأسرتها +لأسس +لأسعار +لأسعاره +لأسفل +لأسلافه +لأسلوب +لأسماء +لأسواق +لأسيوط +لأشبع +لأشتري +لأشجار +لأشخاص +لأشرت +لأشرطة +لأشعار +لأشعة +لأشقائنا +لأشكال +لأشهر +لأصالة +لأصبحت +لأصحاب +لأصحابها +لأصوات +لأصور +لأصول +لأطر +لأطفال +لأطفالنا +لأطفالها +لأطفالهم +لأطفالي +لأطهرها +لأطول +لأعالي +لأعبر +لأعتبر +لأعداد +لأعراض +لأعضاء +لأعظم +لأعلام +لأعلى +لأعماق +لأعمال +لأعمالنا +لأعماله +لأعمالها +لأعمدة +لأعوانه +لأعود +لأعين +لأفتش +لأفراد +لأفراده +لأفرشنّ +لأفضل +لأفكاره +لأفكارها +لأفكارهم +لأفكر +لأفلام +لأفيد +لأقارب +لأقاربه +لأقانيم +لأقسام +لأقسى +لأقصاب +لأقل +لأقوال +لأقوالها +لأقول +لأقوم +لأقيم +لأكاديمية +لأكبر +لأكتب +لأكثر +لأكداس +لأكلهم +لأكمل +لأكون +لألاءة +لألبوماتي +لألتقاط +لألتهم +لألعاب +لألعب +لألف +لألفاظه +لألفريد +لألقاء +لألقي +لألمانيا +لألوان +لألوانها +لأم +لأمارس +لأمة +لأمتنا +لأمته +لأمثالنا +لأمثالها +لأمد +لأمر +لأمراض +لأمريكا +لأمسيات +لأمك +لأمل +لأملاح +لأمم +لأمن +لأمنياتنا +لأمنية +لأمه +لأمها +لأمهات +لأمواج +لأمي +لأمير +لأمين +لأن +لأناس +لأنثى +لأندريه +لأندية +لأنسى +لأنشطة +لأنطاكية +لأنطون +لأنظر +لأنظمة +لأنعمه +لأنفسنا +لأنفسهم +لأنفي +لأنقذنا +لأنقل +لأنك +لأنكم +لأننا +لأنني +لأنه +لأنها +لأنهم +لأنهما +لأنهن +لأنواع +لأني +لأنّا +لأنّاس +لأنّه +لأنّها +لأهالى +لأهالي +لأهداف +لأهرب +لأهل +لأهله +لأهم +لأهمية +لأهميته +لأهميتهما +لأواصل +لأوافق +لأوانه +لأوبيك +لأوجست +لأورام +لأوربا +لأوركسترا +لأوزانهم +لأوسكار +لأوضاع +لأوطانها +لأوقات +لأوكرانيا +لأول +لأولئك +لأولاد +لأولاده +لأولادي +لأوّل +لأى +لأي +لأيام +لأية +لأيتام +لأيد +لأيديولوجيا +لأيسلندا +لأيّ +لأُكَفِّرَنَّ +لإبداع +لإبداعه +لإبراز +لإبراهيم +لإبعاد +لإبقاء +لإتمام +لإتمامها +لإثبات +لإجباره +لإجراء +لإجماع +لإحداث +لإحدى +لإحراجه +لإحراز +لإحساس +لإحصاءات +لإحياء +لإخضاعنا +لإخفاء +لإخفائها +لإخفاقي +لإخوانه +لإدارة +لإدارتي +لإدخال +لإدراك +لإدوارد +لإذاعة +لإرجاع +لإرساء +لإرسال +لإرسالها +لإرشاد +لإرهاب +لإرواء +لإروائه +لإزالة +لإسبانيا +لإستصطدار +لإستضافة +لإستعدادا +لإسرائيل +لإسعادي +لإسكات +لإسلامه +لإسهاماته +لإسهامه +لإشارات +لإشارة +لإشاعة +لإشباع +لإشراف +لإشكالياتها +لإشكالية +لإصابات +لإصدار +لإصدارها +لإصلاح +لإضاءة +لإضفاء +لإطالة +لإطعام +لإطلاع +لإطلاق +لإعادة +لإعادتنا +لإعاقة +لإعالة +لإعالته +لإعانة +لإعداد +لإعطاء +لإعلامها +لإعلان +لإفراز +لإفريقيا +لإفساد +لإفهامهم +لإقامة +لإقامته +لإقامتها +لإقحام +لإقصاء +لإقليم +لإقناع +لإقناعه +لإقناعهم +لإكساب +لإكسابها +لإكمال +لإلقاء +لإمارة +لإمداد +لإمكان +لإمكانات +لإمكانيات +لإنتاج +لإنجاز +لإنجازات +لإنجازها +لإنسان +لإنشاء +لإنشائه +لإنعاش +لإنفاق +لإنقاذ +لإنقاذها +لإنقاص +لإنهاء +لإنهائها +لإنهاض +لإهداء +لإيجاد +لإيجاده +لإيجار +لإيذاء +لإيران +لإيصال +لإيقاظ +لإيقاع +لإيقاف +لإيلاج +لإيهام +لئلا +لئن +لا +لاأتصور +لاأجد +لاأحد +لاأدري +لاأريد +لاأزال +لاأميزه +لاأهتم +لاإرادي +لاإراديا +لاإقليدية +لائحة +لائذاً +لائق +لائكيا +لائكية +لائم +لاارادي +لاب +لابأس +لابتعاث +لابتكار +لابتلاع +لابد +لابدأ +لابدّ +لابقاء +لابن +لابنته +لابنتها +لابنتي +لابنه +لابورد +لابيزينجا +لابيه +لاتأتي +لاتأخذ +لاتؤدي +لاتباع +لاتباعه +لاتبعنا +لاتتجاوز +لاتتحقق +لاتتحمل +لاتتعرض +لاتجد +لاتحاد +لاتحبل +لاتحتاج +لاتحركها +لاتخاذ +لاتخرج +لاتخشى +لاتخفى +لاتخلو +لاتدركها +لاتدل +لاتذيب +لاتربطهم +لاتريب +لاتريد +لاتزال +لاتزيد +لاتساع +لاتشبع +لاتشبه +لاتصل +لاتصهل +لاتعبير +لاتعرف +لاتعمم +لاتعيش +لاتفرح +لاتفيها +لاتقاء +لاتقال +لاتقبل +لاتكتب +لاتكفي +لاتكون +لاتمسوه +لاتنسى +لاتنير +لاتهام +لاتوفرها +لاتيس +لاتيني +لاتينية +لاثبات +لاجئ +لاجئا +لاجئة +لاجتياح +لاجل +لاجنسيًّا +لاحت +لاحتراف +لاحتضان +لاحتفالات +لاحتفالاتها +لاحتلال +لاحتمال +لاحتواء +لاحتوائه +لاحتياجات +لاحتياجاته +لاحتياجاتهم +لاحتياجها +لاحضار +لاحظ +لاحظت +لاحظته +لاحظنا +لاحظه +لاحق +لاحقا +لاحقاً +لاحقة +لاحقتها +لاحقه +لاحقًا +لاحول +لاختبار +لاختبارات +لاختباره +لاختراع +لاختراعه +لاختراق +لاختصار +لاختصاصها +لاختفاء +لاختفائه +لاختلاجات +لاختلاف +لاختلافات +لاختلافه +لاختيار +لاختيارك +لاختيارنا +لاداعي +لادن +لاذت +لاذع +لاذعا +لاذعة +لارتباط +لارتباطه +لارتخاء +لارتفاع +لارسون +لاري +لاريب +لاريدو +لازال +لازالت +لازدهار +لازلت +لازلتُ +لازلتِ +لازلنا +لازم +لازما +لازمة +لازمك +لازمني +لازمه +لازمها +لازورد +لاس +لاسال +لاسانزا +لاسبيل +لاستئصال +لاستثمار +لاستثماراتها +لاستجلاء +لاستخدام +لاستخدامه +لاستخدامها +لاستخدمت +لاستخراج +لاستخلاص +لاستدراك +لاستراتيجيات +لاسترجاع +لاسترجاعها +لاسترداده +لاستشارتها +لاستشراف +لاستضافة +لاستطاعت +لاستطعنا +لاستطلاع +لاستعادة +لاستعجال +لاستعدادي +لاستعراض +لاستعمار +لاستعمال +لاستعمالاتنا +لاستعمالها +لاستفتاء +لاستقبال +لاستقباله +لاستقدام +لاستقراره +لاستقصاء +لاستقطاب +لاستكشاف +لاستكمال +لاستلام +لاستمرار +لاستمرارية +لاستنساخ +لاستهلاك +لاستيراد +لاستيطان +لاستيعاب +لاستيعابها +لاسم +لاسمه +لاسمها +لاسنت +لاسيما +لاسينزا +لاشأن +لاشعورية +لاشك +لاشيء +لاصدقائه +لاصطياد +لاصقة +لاضطرابات +لاضطهاد +لاعادة +لاعب +لاعبو +لاعتبارات +لاعتقادنا +لاعتقادهم +لاعتقادي +لاعتقال +لاعتقد +لاعلاقة +لاعلم +لافاندوم +لافت +لافتا +لافتات +لافتة +لافتراس +لافوازييه +لافونتي +لافيران +لاقامة +لاقة +لاقت +لاقتحام +لاقتصار +لاقتضاء +لاقتفاء +لاقتلاعه +لاقتناص +لاقدر +لاقى +لاقيت +لاقيتها +لاقيمة +لاكتساب +لاكتشاف +لاكتشفت +لاكتظاظ +لاكوست +لال +لالتحاق +لالتحاقه +لالتقاء +لالتقاط +لالتهاب +لامباريا +لامبالاته +لامبرك +لامة +لامتحان +لامتحاناتها +لامتداد +لامتصاص +لامتلاك +لامتناهية +لامتيازاتها +لامتيازاتهم +لامجال +لامدادك +لامدارس +لامرأة +لامرتين +لامس +لامست +لامسته +لامعاً +لامعة +لاميناريا +لان +لانبعاث +لانتدابه +لانتزاع +لانتشار +لانتشال +لانتصور +لانتقال +لانتقاله +لانتهاك +لانتهت +لانج +لانجيري +لانحراف +لانحيازي +لانخرج +لانخفاض +لاند +لاندماج +لانريد +لانزال +لانست +لانستطيع +لانسيت +لانصراف +لانصرافي +لانطلاق +لانعقاده +لانعلم +لانفتاح +لانفجار +لانفعالاته +لانقاذ +لانقاص +لانقضاض +لانقطاع +لانكستر +لانني +لانها +لانهاية +لانهيار +لاهاي +لاهبا +لاهتزاز +لاهتم +لاهث +لاهثا +لاهثة +لاهثًا +لاهور +لاهية +لاهين +لاوست +لاي +لايبقى +لايتضمن +لايتم +لايتيح +لايثير +لايجب +لايجد +لايحتاج +لايحترمون +لايحدث +لايحصل +لايحصلون +لايخشون +لايخفى +لايدركون +لايدن +لايذكرهم +لايراه +لايرتاب +لايزال +لايزالون +لايزيد +لايسألون +لايستطيع +لايستهدف +لايسمح +لايشبه +لايشك +لايشهد +لايصل +لايطمع +لايعاد +لايعتمد +لايعد +لايعني +لايفصل +لايقدر +لايقرأنا +لايكتب +لايكتبون +لايكون +لايمكن +لايمكنهن +لايملكون +لايمنح +لاين +لاينفصل +لايني +لايهتمون +لايوجد +لاَ +لب +لبؤة +لبائع +لباب +لباحث +لباحثين +لباس +لباسه +لباسهن +لباقي +لباكستان +لبالي +لباني +لبترته +لبتهوفن +لبث +لبثت +لبحث +لبحر +لبحوث +لبحيرة +لبدء +لبداية +لبدة +لبدن +لبذور +لبرامج +لبرامز +لبرك +لبرمجيات +لبرنامج +لبريطانيا +لبس +لبسته +لبسك +لبسه +لبشرته +لبضائعها +لبضع +لبطاقات +لبطاقة +لبطل +لبعثة +لبعدي +لبعض +لبعضها +لبعضهم +لبعضهما +لبق +لبقة +لبقي +لبقية +لبكتريا +لبلادنا +لبلاده +لبلادهم +لبلاشير +لبلد +لبلدان +لبلدانهم +لبلدة +لبلدنا +لبلده +لبلدوين +لبلدية +لبلورة +لبنا +لبناء +لبنات +لبنان +لبناني +لبنانية +لبنود +لبني +لبنياً +لبنيكم +لبواكير +لبوس +لبولب +لبوني +لبي +لبيان +لبيانات +لبيب +لبيتك +لبيتنا +لبيته +لبيرم +لبيروت +لبيضها +لبيع +لبيعها +لبيك +لبيوت +لبَلْورة +لبّ +لبّوا +لبّيت +لة +لتأثير +لتأثيرها +لتأخذ +لتأخذي +لتأخير +لتأدية +لتأذيه +لتأسيس +لتأكل +لتأكيد +لتأليف +لتأمين +لتأهيل +لتأهيلهم +لتأييد +لتؤدي +لتؤطر +لتؤكد +لتاجر +لتاريخ +لتاريخهم +لتاريخي +لتبادلنا +لتبتلعها +لتبدأ +لتبدلت +لتبدو +لتبديله +لتبرئته +لتبرز +لتبرير +لتبصيرهم +لتبعد +لتبقى +لتبلور +لتبني +لتتجمع +لتتجنب +لتتحقق +لتتحول +لتتخصص +لتتخلق +لتتر +لتترك +لتتساقط +لتتساوى +لتتسرَّب +لتتسلم +لتتصفح +لتتعرف +لتتفادى +لتتقارب +لتتقيح +لتتكامل +لتتكثف +لتتكشف +لتتكون +لتتكيّف +لتتلاءم +لتتلاقى +لتتم +لتتمكن +لتتناسب +لتتوافر +لتتوافق +لتتوقف +لتتولى +لتثبت +لتثبيت +لتثقيفه +لتثور +لتجارب +لتجاوز +لتجاوزها +لتجتاح +لتجتازي +لتجتمع +لتجد +لتجديد +لتجربة +لتجربته +لتجربتي +لتجري +لتجسيد +لتجفف +لتجفيف +لتجلب +لتجلية +لتجمع +لتجميع +لتجميل +لتجنب +لتجنبها +لتجنيب +لتحاصر +لتحافظ +لتحاكي +لتحتفظ +لتحتل +لتحدث +لتحديات +لتحديث +لتحديد +لتحرق +لتحري +لتحرير +لتحسين +لتحصل +لتحصيل +لتحضر +لتحضيرهم +لتحطيم +لتحظى +لتحـفيز +لتحـقيق +لتحـويل +لتحقق +لتحقيق +لتحقيقات +لتحقيقه +لتحقيقها +لتحل +لتحليقه +لتحليل +لتحمل +لتحمله +لتحمي +لتحميله +لتحول +لتحوير +لتحويل +لتحويله +لتحويلها +لتحيط +لتحيّة +لتختلط +لتخدم +لتخرج +لتخريج +لتخزين +لتخسيس +لتخصص +لتخصيص +لتخطيط +لتخفف +لتخفيض +لتخفيف +لتخلص +لتخلق +لتخليد +لتخليص +لتخليق +لتدابير +لتدارس +لتدارك +لتداعب +لتداعيات +لتداعياته +لتداول +لتدخل +لتدخلي +لتدرج +لتدريب +لتدريس +لتدعو +لتدعيم +لتدفع +لتدلل +لتدليل +لتدني +لتدهور +لتذكرني +لتذكير +لتذوقها +لتذويب +لتر +لترا +لتراب +لترات +لتراث +لتراثنا +لتراثهم +لتراخيص +لتراعي +لتراقبه +لتراكم +لتراني +لتراً +لتربية +لتربيته +لتربيتي +لترتبط +لترتيب +لترتيبه +لترجمة +لترجيح +لترحمنا +لترسم +لترسمي +لترسيخ +لترسيخها +لترشيد +لترصد +لترضع +لترطيب +لترفع +لترفعها +لترقق +لترقية +لتركيا +لتركيزات +لترميم +لترهل +لتروج +لترويج +لترويجه +لترى +لتري +لتريحهم +لتريها +لتزاحم +لتزايد +لتزود +لتزول +لتزويد +لتزويدهم +لتزوير +لتزيينها +لتسأل +لتساعد +لتساعدني +لتساقط +لتسامح +لتسبح +لتستثمر +لتسترجع +لتستضيف +لتستطيع +لتستعملها +لتستعيد +لتستعيض +لتستقر +لتستكشف +لتستمر +لتستوعب +لتسجل +لتسجيل +لتسجيلهم +لتسحتك +لتسديد +لتسع +لتسعة +لتسقط +لتسكب +لتسكبه +لتسكنوا +لتسلط +لتسلمها +لتسلية +لتسليط +لتسليم +لتسهم +لتسهيل +لتسوية +لتسويق +لتسىير +لتسيل +لتسيير +لتشابه +لتشتري +لتشخيص +لتشريدهم +لتشعر +لتشعله +لتشكك +لتشكل +لتشكيل +لتشكّل +لتشمل +لتشن +لتشويه +لتشيد +لتصبح +لتصحيح +لتصدر +لتصدَّر +لتصطاد +لتصعد +لتصل +لتصميم +لتصنع +لتصنيع +لتصنيف +لتصهر +لتصور +لتصورهم +لتصوير +لتصويرها +لتصويري +لتصير +لتضع +لتضعضعت +لتضليل +لتضم +لتضمن +لتضمها +لتضيع +لتضييع +لتطبيع +لتطبيق +لتطرد +لتطرية +لتطعيم +لتطل +لتطليق +لتطور +لتطوى +لتطوير +لتطويرها +لتطويع +لتعارفوا +لتعاليم +لتعاملات +لتعبر +لتعبّر +لتعد +لتعداد +لتعدد +لتعددية +لتعديل +لتعرض +لتعرية +لتعريف +لتعريفهم +لتعزز +لتعزية +لتعزيز +لتعطل +لتعطي +لتعطيل +لتعظيم +لتعقيم +لتعكس +لتعلق +لتعلم +لتعلمه +لتعلن +لتعليقه +لتعليم +لتعليمات +لتعمل +لتعمية +لتعميمها +لتعود +لتعويض +لتعيد +لتعيدني +لتعيش +لتعينها +لتعيّن +لتفادي +لتفاصيل +لتفاقمت +لتفاهة +لتفتيش +لتفجّر +لتفريخ +لتفرُّدٍ +لتفسح +لتفسير +لتفصيل +لتفض +لتفعيل +لتفقد +لتفكر +لتفكيك +لتفهم +لتفوق +لتقارب +لتقارير +لتقاطيع +لتقانيات +لتقاوم +لتقبض +لتقبل +لتقترب +لتقدم +لتقدمه +لتقدير +لتقديم +لتقدّم +لتقرر +لتقريب +لتقريبها +لتقرير +لتقص +لتقصر +لتقصّي +لتقف +لتقل +لتقليص +لتقليل +لتقنيات +لتقودني +لتقول +لتقوم +لتقوية +لتقويم +لتقويمه +لتقويمها +لتقىيم +لتقي +لتقيم +لتقييم +لتكاثر +لتكاد +لتكاليف +لتكامل +لتكتب +لتكتمل +لتكثيف +لتكرارها +لتكرس +لتكريس +لتكريم +لتكريمهم +لتكسر +لتكلفة +لتكليف +لتكن +لتكون +لتكوين +لتكوّن +لتلائم +لتلاحقك +لتلاحقني +لتلامذته +لتلاميذه +لتلاوة +لتلبى +لتلبية +لتلبيتها +لتلتصق +لتلحق +لتلحقهم +لتلعب +لتلفزيون +لتلقى +لتلقي +لتلقيني +لتلك +لتلمحها +لتلمس +لتلميذ +لتلميذه +لتلوُّث +لتماس +لتمتعهم +لتمزق +لتمشية +لتمضي +لتمضية +لتمكين +لتملأ +لتملك +لتمنعهم +لتمنّ +لتمهد +لتمويل +لتناسب +لتنافس +لتنالي +لتنام +لتناول +لتناوله +لتنبيه +لتنتج +لتنتحر +لتنتشر +لتنتقل +لتنتقي +لتنتهي +لتنداح +لتندلع +لتنذرها +لتنزعه +لتنزوي +لتنسحق +لتنسيق +لتنشئة +لتنشر +لتنشط +لتنشيط +لتنصت +لتنطلق +لتنظر +لتنظم +لتنظيف +لتنظيم +لتنظيمها +لتنفقه +لتنفي +لتنفيذ +لتنفيذه +لتنفيذها +لتنقص +لتنقل +لتنقية +لتنكأه +لتنمي +لتنمية +لتنميتها +لتنهي +لتنوع +لتنير +لتهاجم +لتهدمه +لتهديدات +لتهديها +لتهريب +لتهنئني +لتهوية +لتهيئة +لتواجه +لتوازن +لتواصل +لتواضعهم +لتوافد +لتوافر +لتوالد +لتوجه +لتوجهات +لتوجيه +لتوجيهات +لتوجّه +لتوزيع +لتوزيعها +لتوسطها +لتوسيع +لتوصلك +لتوصلها +لتوطيد +لتوطين +لتوظيف +لتوعية +لتوفر +لتوفرها +لتوفير +لتوقف +لتوقيع +لتولستوي +لتولي +لتوليد +لتوه +لتوها +لتوهم +لتوّه +لتيار +لتيارات +لتيّار +لتُطوى +لتُفسح +لتُقطف +لثانويات +لثاني +لثروة +لثقافات +لثقافة +لثقافتنا +لثقته +لثلاث +لثلاثة +لثمان +لثماني +لثمانية +لثماً +لثنايا +لثوان +لثوران +لثورة +لجأ +لجأت +لجأتُ +لجأنا +لجاء +لجائزة +لجارثيا +لجاره +لجالينوس +لجام +لجامعة +لجان +لجبر +لجبران +لجبل +لجبهة +لجداتنا +لجدار +لجدته +لجدران +لجدل +لجدوى +لجدي +لجذب +لجذورها +لجرائم +لجراثيم +لجراح +لجراحها +لجرعات +لجريدة +لجريدته +لجرينلاند +لجزء +لجزارها +لجزيرة +لجسارة +لجسدها +لجسم +لجعل +لجعلنا +لجعله +لجلاء +لجلال +لجلالة +لجلوس +لجليده +لجم +لجماجم +لجمال +لجماليات +لجمالية +لجماهير +لجمع +لجمعية +لجملة +لجمهوري +لجمهورية +لجموع +لجميع +لجميل +لجنة +لجنته +لجنتهم +لجنسية +لجنينها +لجنيّ +لجهات +لجهاز +لجهة +لجهده +لجهود +لجهوده +لجهودها +لجوء +لجوءها +لجوئي +لجوائز +لجواد +لجوانب +لجوته +لجودة +لجول +لجولة +لجيش +لجيل +لحاجات +لحاجة +لحاجته +لحاخامات +لحاخامي +لحادثة +لحاشية +لحافي +لحاقي +لحال +لحالات +لحالة +لحالته +لحالتها +لحالتهم +لحام +لحاملي +لحامية +لحبها +لحبوب +لحج +لحجاج +لحجب +لحجز +لحجم +لحد +لحدائق +لحدوث +لحدوثها +لحدود +لحديث +لحديثه +لحديد +لحديقة +لحذاء +لحرارة +لحراسة +لحرس +لحرصها +لحرف +لحرق +لحركة +لحركتها +لحروب +لحروفه +لحرية +لحريق +لحزب +لحزن +لحس +لحساب +لحسابات +لحسابها +لحسن +لحسنات +لحسه +لحصان +لحصر +لحصلنا +لحصن +لحصول +لحضارة +لحضارتنا +لحضراتكم +لحضور +لحضوره +لحضورها +لحظات +لحظاتها +لحظاتي +لحظة +لحظت +لحظته +لحظتها +لحظتي +لحظر +لحظيرة +لحـفظ +لحـوالى +لحفر +لحفظ +لحفظة +لحفيدته +لحق +لحقبة +لحقت +لحقل +لحقن +لحقه +لحقوق +لحقوقنا +لحقوقه +لحقوقها +لحقول +لحقيقة +لحكايات +لحكم +لحكمة +لحكمهم +لحكومة +لحكومته +لحل +لحلف +لحلقة +لحلم +لحلمي +لحلول +لحم +لحماره +لحماس +لحماسة +لحمامات +لحماية +لحمايته +لحمايتها +لحمة +لحمل +لحملة +لحمله +لحمه +لحمها +لحمي +لحن +لحنا +لحناً +لحنت +لحنجرة +لحنجرتي +لحنه +لحنها +لحني +لحنيه +لحنًا +لحوادث +لحوار +لحوالي +لحوحًا +لحوليات +لحوم +لحي +لحياة +لحياتنا +لحياته +لحياتها +لحياتهم +لحية +لحيته +لحيلها +لحيمة +لحين +لحيوات +لحيوان +لحيوانات +لحّن +لخابيط +لخاتم +لخاصة +لخالق +لخاله +لخبراء +لخبير +لخجل +لخداع +لخدعة +لخدمات +لخدمة +لخدمته +لخدمتهم +لخروج +لخزائن +لخصت +لخصوصية +لخصومات +لخضته +لخطاب +لخطبتها +لخطبتي +لخطة +لخطر +لخطط +لخططنا +لخطواتنا +لخطوة +لخطوته +لخطورة +لخطورتها +لخطّاء +لخفت +لخفض +لخلاص +لخلافته +لخلافتها +لخلق +لخلو +لخلية +لخليفة +لخليفته +لخمس +لخمسة +لخمسين +لخوض +لخوفه +لخيالي +لخير +لد +لدأبها +لداء +لدائرة +لدائن +لدائني +لدار +لداروين +لدانة +لدبلوم +لدخان +لدخول +لدرء +لدراسات +لدراساتي +لدراسة +لدراسته +لدراستها +لدرجات +لدرجة +لدرجتي +لدرفلة +لدروس +لدس +لدعم +لدعمها +لدعوة +لدعوته +لدعوتها +لدفتر +لدفع +لدفعه +لدقائق +لدقة +لدماء +لدن +لدنة +لدنيا +لدهم +لدواء +لدواعي +لدواوين +لدود +لدودا +لدودة +لدور +لدورة +لدورتين +لدوره +لدورهم +لدورياتِ +لدول +لدولة +لدولتهم +لدى +لدي +لديدان +لديك +لديكم +لدين +لدينا +لدينها +لديه +لديها +لديهم +لديهما +لديهن +لديوان +لديّ +لذ +لذا +لذات +لذاته +لذاتها +لذاك +لذاكرتها +لذة +لذتها +لذعاته +لذكائه +لذكر +لذكراه +لذكرت +لذكرها +لذكرى +لذلك +لذهن +لذواتهم +لذوق +لذوقهم +لذوي +لذيذ +لذيذا +لذّ +لذّته +لرأس +لرأي +لرأيت +لرؤاهم +لرؤية +لرؤيتك +لرؤيته +لرؤيتها +لرؤيتهم +لرئاسة +لرئيس +لرئيسه +لرابطة +لراحة +لراكب +لرامز +لراويته +لرباعيات +لربة +لربط +لربما +لرجال +لرجالات +لرجل +لرجلٍ +لرحالة +لرحلات +لرحلاتهم +لرحلة +لرحيق +لرخص +لرد +لرداءة +لردح +لردم +لرسالة +لرسام +لرسومك +لرش +لرصد +لرصدها +لرضا +لرضح +لرعاية +لرعايتها +لرعيته +لرفضه +لرفع +لرقابة +لركاب +لركابها +لرمضان +لرموز +لرمي +لرميته +لرواد +لرواده +لرواية +لروتردام +لروجر +لروح +لروحها +لروحي +لروسيا +لرياضة +لزائره +لزاما +لزبائنها +لزبد +لزبيدة +لزج +لزجاً +لزجة +لزحف +لزراعة +لزرع +لزرعها +لزعم +لزعيم +لزكريا +لزم +لزما +لزمام +لزملائي +لزمه +لزميل +لزميلهم +لزميلي +لزنكي +لزواجه +لزواجى +لزوار +لزوارها +لزوجة +لزوجته +لزوجتي +لزوجها +لزوجي +لزوم +لزيادة +لزيارة +لزيارتك +لزيارته +لزيارتها +لزيارتي +لسؤال +لسؤالك +لسؤاله +لسؤالهم +لسؤالهِ +لسائح +لسائر +لسارس +لساعات +لساعة +لساكنه +لسان +لسانا +لساننا +لسانه +لسانها +لساني +لسانيات +لسانية +لسبات +لسبب +لسببين +لسبع +لسبعة +لسبعين +لست +لستة +لستُ +لستِ +لسجناء +لسحب +لسحرا +لسخرية +لسخطه +لسد +لسدس +لسرطان +لسرطانات +لسرعة +لسرقة +لسطوع +لسعادة +لسعة +لسعته +لسعها +لسعود +لسعي +لسفر +لسفرتنا +لسفن +لسفينة +لسقراط +لسقطت +لسقوط +لسكان +لسكانه +لسكانها +لسكين +لسلاسة +لسلسلة +لسلطات +لسلطة +لسلوك +لسلوكات +لسلوكه +لسلوكيات +لسليم +لسليمان +لسماع +لسمعة +لسمكة +لسمناها +لسموكم +لسنا +لسنة +لسنةٍ +لسنتين +لسنوات +لسوء +لسواحل +لسواه +لسور +لسورتي +لسوريا +لسورية +لسوف +لسوق +لسويسرا +لسويعات +لسياحة +لسيارات +لسيارة +لسيارتي +لسياسات +لسياسة +لسيد +لسيدات +لسيدة +لسير +لسيرة +لسيرين +لسيطرة +لسيطرتهم +لسيل +لسينما +لشؤون +لشؤونها +لشئون +لشارع +لشاطئ +لشاعر +لشاكر +لشباب +لشبكة +لشبهة +لشبونة +لشتى +لشتّى +لشجرة +لشجونه +لشحناتهم +لشخص +لشخصيات +لشخصية +لشخصيته +لشخصين +لشدة +لشراء +لشرح +لشرحها +لشرق +لشركات +لشركة +لشرم +لشروط +لشريط +لشريك +لشعائر +لشعبه +لشعر +لشعراء +لشعوب +لشعوره +لشعوري +لشفاء +لشق +لشقيقتيه +لشقيقه +لشكل +لشم +لشن +لشهادة +لشهر +لشهرته +لشهيته +لشوارع +لشوقي +لشيء +لشيخنا +لشيخه +لشيراتون +لشيرين +لشيطان +لشيوخ +لشيوخه +لشَرْعنة +لص +لصاحب +لصاحبتها +لصاحبه +لصاحبها +لصالح +لصالحنا +لصالحه +لصالحهم +لصان +لصبي +لصحة +لصحراء +لصحيفة +لصداق +لصدق +لصدمات +لصديقه +لصديقي +لصراحته +لصراعات +لصراف +لصرخة +لصرخته +لصرفه +لصعود +لصفاته +لصفحة +لصفوف +لصفية +لصق +لصقات +لصقها +لصلاة +لصلاح +لصناع +لصناعات +لصناعة +لصندوق +لصنع +لصنعاء +لصهره +لصهيل +لصوامع +لصور +لصورة +لصوص +لصون +لصيانة +لصيت +لصيحة +لصيد +لصيف +لصيقة +لصيقًا +لضاع +لضبط +لضبع +لضحايا +لضحكات +لضخ +لضخامة +لضخامته +لضرب +لضرورات +لضرورة +لضعف +لضعفنا +لضعفه +لضفدعة +لضلالي +لضمان +لضيف +لضيوف +لضيوفه +لضيوفها +لطائر +لطائرات +لطائراتها +لطائرة +لطائفة +لطارق +لطاقات +لطاقاتنا +لطاقة +لطالباتي +لطالبي +لطالما +لطباعة +لطباعته +لطبع +لطبعها +لطبقة +لطبيب +لطبيعة +لطرابلس +لطرح +لطرد +لطردنا +لطرده +لطريقها +لطـوانا +لطف +لطفل +لطفلين +لطفولته +لطفي +لطفًا +لطلاب +لطلابنا +لطلابه +لطلابها +لطلب +لطلبات +لطلباته +لطلبة +لطلبه +لطلبي +لطمس +لطموح +لطموحه +لطه +لطوكيو +لطول +لطيف +لطيفاً +لطيفة +لظاهرة +لظاهرتي +لظروف +لظلم +لظهور +لظهوره +لعائلات +لعائلة +لعائلتنا +لعائلته +لعاب +لعاد +لعادات +لعادة +لعادل +لعازف +لعاصفة +لعالم +لعالمنا +لعام +لعامة +لعامل +لعامين +لعب +لعبادة +لعبارات +لعبة +لعبت +لعبته +لعبتها +لعبتهم +لعبتين +لعبد +لعبدالحليم +لعبدالرحمن +لعبدالكريم +لعبدالناصر +لعبده +لعبقرية +لعبه +لعبور +لعجز +لعجمي +لعدة +لعدد +لعدستي +لعدم +لعده +لعربي +لعرس +لعرسان +لعرشه +لعرض +لعرضها +لعرق +لعروس +لعزف +لعزم +لعشاق +لعشتروت +لعشر +لعشرات +لعشرة +لعشرين +لعصبة +لعصر +لعصره +لعصور +لعصيت +لعضلة +لعضوية +لعطاءات +لعطل +لعطلات +لعقار +لعقد +لعقدة +لعقدين +لعقيدتها +لعل +لعلاج +لعلاجات +لعلاجه +لعلاجها +لعلاقة +لعلاقته +لعلامة +لعلبة +لعلك +لعلم +لعلماء +لعلمك +لعلمنة +لعلمه +لعلنا +لعله +لعلها +لعلهم +لعلوم +لعلي +لعلّني +لعلّي +لعمار +لعمانوئيل +لعمر +لعمري +لعمق +لعمل +لعملاء +لعملائنا +لعملائها +لعملة +لعمله +لعملهم +لعمليات +لعملية +لعميدة +لعنات +لعناد +لعناصر +لعنة +لعنترة +لعنصر +لعهود +لعوادي +لعوالم +لعوامل +لعودة +لعودتهما +لعودتي +لعولمة +لعيادة +لعين +لعينيه +لعيون +لـ +لـباب +لـتطور +لـما +لـها +لـهذه +لف +لفأر +لفئات +لفائدة +لفارسها +لفاعليتها +لفافة +لفايزة +لفة +لفت +لفتة +لفتح +لفتحها +لفترات +لفترة +لفتق +لفتنا +لفتهم +لفحتها +لفحواها +لفخامة +لفخامته +لفرادتها +لفرد +لفرديناند +لفرص +لفرض +لفرط +لفرقة +لفرنسا +لفروع +لفرومنتان +لفريق +لفشل +لفصول +لفضح +لفضل +لفضلها +لفظ +لفظة +لفظت +لفظتان +لفظها +لفظي +لفظية +لفظًا +لفعاليات +لفعل +لفعلة +لفعلها +لفقدانه +لفقدانهم +لفقدهن +لفقراء +لفقهها +لفك +لفكر +لفكرة +لفكرنا +لفكره +لفككتُ +لفلاح +لفلسطين +لفلسفاتهم +لفلفة +لفلّك +لفن +لفنان +لفنانة +لفناني +لفنانين +لفندق +لفنه +لفنون +لفهم +لفهمه +لفهمها +لفوهة +لفيلة +لفيلدونج +لفيلم +لفيلمه +لفّا +لفّها +لقاء +لقاءات +لقاءاتنا +لقاءاته +لقاءاتي +لقاءه +لقاءها +لقاءً +لقاؤنا +لقائدهم +لقائمة +لقائنا +لقائه +لقائها +لقائهما +لقائي +لقات +لقاتلونا +لقاح +لقادة +لقادمين +لقارئ +لقارئه +لقاع +لقامت +لقب +لقبائل +لقباً +لقبر +لقبه +لقبور +لقبول +لقبوله +لقتال +لقتل +لقتله +لقتلها +لقتلهم +لقحت +لقد +لقدم +لقدمها +لقدوم +لقراءة +لقراءتها +لقرائنا +لقراراتها +لقراصنة +لقربه +لقربها +لقرحات +لقرص +لقرع +لقرناء +لقرون +لقرّائي +لقزم +لقسم +لقصة +لقصد +لقصر +لقصرها +لقصص +لقصف +لقصيدة +لقضاء +لقضايا +لقضاياهم +لقضــــية +لقضية +لقضيتك +لقطاء +لقطات +لقطاع +لقطب +لقطة +لقطع +لقلة +لقلت +لقلعة +لقلقي +لقلل +لقلمي +لقلوب +لقلوبهم +لقماش +لقمة +لقمري +لقن +لقناع +لقناعات +لقنني +لقنه +لقوا +لقواعد +لقوانين +لقوانينها +لقوة +لقول +لقوم +لقومه +لقوى +لقي +لقيا +لقيادة +لقياس +لقياسها +لقيام +لقيامه +لقيت +لقيتك +لقيته +لقيتها +لقيطا +لقيعان +لقيم +لقيماً +لقيمة +لقيه +لك +لكأنه +لكائن +لكائنات +لكابوس +لكابوسه +لكاتب +لكارثة +لكارلاباور +لكافة +لكان +لكانت +لكانط +لكبار +لكبر +لكبيرة +لكتاب +لكتابات +لكتاباته +لكتابة +لكتابتها +لكتابه +لكتب +لكتبه +لكتيب +لكتّاب +لكثر +لكثرة +لكثرتهم +لكثير +لكرامتهم +لكرة +لكررت +لكرستوفر +لكرمه +لكريستوفر +لكسب +لكسر +لكشف +لكشفه +لكـم +لكفيلة +لكل +لكلا +لكلام +لكلامها +لكلامٍ +لكلمة +لكلية +لكلِّ +لكم +لكمال +لكميات +لكن +لكنة +لكنت +لكنك +لكنكِ +لكننا +لكنني +لكنه +لكنها +لكنهم +لكنهما +لكنهّ +لكني +لكنيسة +لكنّ +لكنَّ +لكوادر +لكوارث +لكوبا +لكوكب +لكولمبس +لكون +لكونستانتا +لكونك +لكونه +لكونها +لكونهم +لكوني +لكي +لكيفية +لكيلا +لكِ +للآبار +للآتي +للآثار +للآخر +للآخرين +للآداب +للآراء +للآفات +للآلاف +للآلية +للآن +للآيات +للأب +للأبحاث +للأبد +للأبرياء +للأبناء +للأبواب +للأجسام +للأجفان +للأجهزة +للأجيال +للأحاديث +للأحافير +للأحداث +للأحفاد +للأحفورة +للأحكام +للأحلام +للأخ +للأخرى +للأخطاء +للأخطار +للأخلاف +للأخلاق +للأخير +للأدب +للأدباء +للأدنى +للأدوات +للأدوية +للأديب +للأذهان +للأذى +للأراضي +للأرانب +للأربعين +للأرشيف +للأرصاد +للأرض +للأرضيات +للأرق +للأرقام +للأرنب +للأرواح +للأرياف +للأزهر +للأسئلة +للأساتذة +للأساليب +للأسباب +للأسبوع +للأستاذ +للأسر +للأسرة +للأسطح +للأسعار +للأسف +للأسفار +للأسفل +للأسلوب +للأسماك +للأسمدة +للأسنان +للأسواق +للأسى +للأشجار +للأشخاص +للأشعة +للأشنانداني +للأشياء +للأصل +للأصوات +للأصول +للأضرحة +للأطباء +للأطفال +للأعداد +للأعرابي +للأعشاب +للأعصاب +للأعضاء +للأعلى +للأعمال +للأعمش +للأعين +للأفراد +للأفكار +للأفلام +للأفيال +للأقلام +للأقليات +للأقمشة +للأقوال +للأكاديمية +للأكراد +للأكسجين +للأكل +للألباني +للألعاب +للألف +للألم +للألواح +للأم +للأماكن +للأمام +للأمان +للأمانة +للأمة +للأمتعة +للأمراء +للأمراض +للأمريكيين +للأمطار +للأمل +للأمم +للأمن +للأمهات +للأمواج +للأموال +للأمور +للأمومة +للأمير +للأميركان +للأناشيد +للأنام +للأنبياء +للأندية +للأنسجة +للأنسنة +للأنشطة +للأنظمة +للأنفلونزا +للأنماط +للأنواع +للأهالي +للأهل +للأهمية +للأورام +للأوزان +للأوضاع +للأوقات +للأوقاف +للأول +للأولمباد +للأولى +للأيتام +للأيديولوجيا +للأيديولوجية +للإبحار +للإبداع +للإبداعات +للإبداعية +للإبقاء +للإبهار +للإجابة +للإجازة +للإجراءات +للإجهاض +للإحاطة +للإحتفال +للإحتقان +للإحساس +للإحصائيات +للإختلاطات +للإخوان +للإخوة +للإدارات +للإدخار +للإدريسي +للإدمان +للإذاعة +للإرشاد +للإرهاب +للإرهاق +للإزدحام +للإزعاج +للإسبان +للإستثمارات +للإستخدام +للإستزادة +للإستشفاء +للإسكان +للإسلام +للإسلاميين +للإسهاب +للإسهام +للإشارة +للإشعاع +للإصابة +للإصرار +للإصلاح +للإطلال +للإعاقة +للإعجاب +للإعدام +للإعفاء +للإعلام +للإعلاميين +للإعلان +للإفتاء +للإقامة +للإقراض +للإمارة +للإمام +للإمبراطورية +للإمتصاص +للإمساك +للإمكانات +للإناث +للإنتاج +للإنتان +للإنترنت +للإنجازات +للإنجيل +للإنذار +للإنسان +للإنسانية +للإنشاد +للإنفاق +للإنفجار +للإهمال +للإيجار +للإيدز +للإيقاع +للإيمان +للائتلاف +للابتعاد +للابقاء +للاتجار +للاتجاه +للاتجاهات +للاتحاد +للاتصال +للاتهام +للاثنين +للاجئين +للاجتراءات +للاجترار +للاجتياح +للاحتجاج +للاحتفاء +للاحتفاظ +للاحتفالات +للاحتقان +للاحتكاك +للاحتلال +للاحتمالات +للاحتياج +للاحتياجات +للاحـتفال +للاختبارات +للاختراق +للاختفاء +للاختلاج +للاختلاجات +للاختلاف +للاختمار +للاختيار +للاخر +للادخار +للارتباط +للارتزاق +للارتفاع +للارتقاء +للارتماء +للارتياب +للاستثمار +للاستثمارات +للاستجابة +للاستحمام +للاستحواذ +للاستخدام +للاستدفاء +للاستدلال +للاستراحة +للاسترزاق +للاستزادة +للاستسلام +للاستشارات +للاستشفاء +للاستصلاح +للاستعراب +للاستعراض +للاستعلامات +للاستعمار +للاستعمال +للاستفادة +للاستفسار +للاستقامة +للاستقرار +للاستلقاء +للاستماع +للاستمتاع +للاستمرار +للاستنباط +للاستهلاك +للاستيعاب +للاستيلاء +للاسم +للاشتراك +للاشنانداني +للاصابة +للاصفرار +للاطلاع +للاعتبار +للاعتبارات +للاعتداء +للاعتراف +للاعتقاد +للاعتقال +للاعتماد +للافتراس +للاقتراب +للاقتراح +للاقتصاد +للاقتلاع +للاكتئاب +للاكتتاب +للاكتفاء +للالتباس +للالتحاق +للالتفاف +للالتقاء +للالتهاب +للالتهابات +للامتداد +للامتصاص +للانبعاث +للانتساب +للانتشار +للانتظام +للانتقاد +للانتقاص +للانتقال +للانتقام +للانثى +للانحدار +للانخراط +للانخفاض +للاندلاع +للاندماج +للانزلاق +للانزواء +للانضمام +للانطلاق +للانفاق +للانفتاح +للانفجار +للانفجارات +للانفراد +للانفعالات +للانقراض +للانقسام +للانقضاض +للانقلابات +للاهتمام +للاوضاع +للبائع +للبابا +للبابوية +للباحث +للباحثين +للباس +للباصات +للباعة +للباكستان +للبامبو +للباندا +للباي +للببليوثيرابيا +للبتر +للبتراء +للبتروكيماويات +للبترول +للبحث +للبحر +للبحوث +للبخار +للبدائل +للبدو +للبرازيل +للبرامج +للبرجوازية +للبرميل +للبرنامج +للبرهان +للبروتين +للبروتينات +للبروفيسور +للبريد +للبس +للبسطاء +للبشر +للبشرة +للبشرية +للبطالة +للبطل +للبطولة +للبعثات +للبعثة +للبعض +للبعوض +للبعوضة +للبقا +للبقاء +للبقالة +للبقر +للبكتريا +للبلاد +للبلاذري +للبلازموديوم +للبلاستيك +للبلد +للبلدة +للبلدية +للبلعوم +للبناء +للبنائين +للبنات +للبنان +للبنايات +للبناية +للبنت +للبنك +للبنوك +للبني +للبنيان +للبنية +للبنين +للبوالب +للبول +للبيئة +للبيان +للبيانات +للبيانو +للبيت +للبيض +للبيع +للبيوت +للتأثير +للتأسيس +للتأكد +للتأمين +للتأهب +للتأويل +للتاريخ +للتبادل +للتباهي +للتبصر +للتثبيت +للتثقيف +للتجار +للتجارب +للتجارة +للتجاعيد +للتجدد +للتجديد +للتجربة +للتجسس +للتجعد +للتجوال +للتحالف +للتحامل +للتحايل +للتحديات +للتحديث +للتحذير +للتحرج +للتحرر +للتحري +للتحرير +للتحسس +للتحصيل +للتحقق +للتحقيق +للتحكم +للتحلل +للتحول +للتخريب +للتخزين +للتخصص +للتخصيص +للتخطيط +للتخفيف +للتخفّي +للتخلص +للتخلف +للتخمر +للتدخين +للتدرب +للتدريب +للتدريس +للتراث +للتراكتورات +للترانزستورات +للتربة +للتربية +للترجمان +للترجمة +للترخيص +للترفيه +للترقي +للتركات +للتركيز +للترميم +للترويج +للترويح +للتزلج +للتساؤل +للتساؤلات +للتسامح +للتستر +للتسجيلات +للتسلسل +للتسلية +للتسليع +للتسلّح +للتسوق +للتسوية +للتسويق +للتشاؤم +للتشبث +للتشخيص +للتشريع +للتشريعات +للتشكل +للتشمس +للتشنج +للتشوهات +للتصدى +للتصدير +للتصديق +للتصرف +للتصفية +للتصميم +للتصنيف +للتصور +للتصورات +للتصوير +للتضامن +للتضحية +للتضييق +للتطبيع +للتطبيق +للتطرف +للتطور +للتطورات +للتطوير +للتعاقد +للتعامل +للتعاون +للتعب +للتعبئة +للتعبير +للتعجيل +للتعداد +للتعدد +للتعديل +للتعدين +للتعذيب +للتعرض +للتعرف +للتعريف +للتعرّف +للتعصب +للتعلم +للتعليم +للتعويذة +للتعويض +للتفاعل +للتفاني +للتفاوض +للتفتيش +للتفسخ +للتفكير +للتفوق +للتقارب +للتقارير +للتقاعد +للتقاليد +للتقدم +للتقريب +للتقرير +للتقليل +للتقنيات +للتقنية +للتقوقع +للتقويم +للتقيد +للتكاثر +للتكامل +للتكرار +للتكنولوجيا +للتكوينات +للتكيف +للتكيّف +للتلاعب +للتلاميذ +للتلفزة +للتلفزيون +للتلوث +للتماثيل +للتماهي +للتمتع +للتمثيل +للتمرين +للتمزق +للتمسك +للتمكن +للتمويل +للتمييز +للتناقص +للتنبؤ +للتنبيه +للتنبُّؤ +للتندر +للتنس +للتنسيق +للتنصت +للتنصير +للتنضير +للتنظيم +للتنفس +للتنفيذ +للتنقل +للتنقيب +للتنمية +للتنوع +للتنوير +للتهنئة +للتو +للتواصل +للتوتر +للتوثيق +للتوجه +للتوجهات +للتوحيد +للتوراة +للتوسعات +للتوظف +للتوظيف +للتوعية +للتوفيق +للتوقف +للتي +للتّعرّف +للتّوقّف +للثاني +للثراء +للثروة +للثعلب +للثقافة +للثقب +للثقة +للثواب +للثوار +للثورة +للجائزة +للجاحظ +للجاذبية +للجاليات +للجالية +للجامع +للجامعات +للجامعة +للجانها +للجبهة +للجبيل +للجحيم +للجدال +للجدل +للجدلية +للجدية +للجذب +للجذر +للجذور +للجراثيم +للجراح +للجراحة +للجراحين +للجرح +للجريدة +للجزء +للجزأين +للجزيرة +للجسد +للجسم +للجسيمات +للجفاف +للجفن +للجلد +للجلوس +للجماعة +للجمال +للجماهير +للجمع +للجمعيات +للجمعية +للجمل +للجمهور +للجمهورية +للجميع +للجنة +للجنس +للجهات +للجهاد +للجهاز +للجهة +للجهل +للجهود +للجوائز +للجوانب +للجولف +للجيران +للجيش +للجيل +للجين +للجينوم +للجيوب +للجيولوجيا +للحئول +للحائط +للحاجب +للحاجة +للحاضر +للحاق +للحاكم +للحالات +للحالة +للحب +للحبل +للحبوب +للحث +للحج +للحجاب +للحجاج +للحجز +للحجم +للحجيج +للحد +للحدائق +للحداثة +للحديث +للحديد +للحديقة +للحرارة +للحراس +للحرب +للحرث +للحرف +للحركة +للحرم +للحروب +للحروف +للحريات +للحرية +للحزب +للحزبيين +للحزن +للحساسية +للحسن +للحشرات +للحشف +للحشيش +للحصاد +للحصان +للحصر +للحصول +للحضارة +للحظاتنا +للحظة +للحـد +للحـوافز +للحفاظ +للحق +للحقد +للحقل +للحقن +للحقيقة +للحقّ +للحكايات +للحكاية +للحكم +للحكماء +للحكومة +للحل +للحلف +للحلم +للحلول +للحلوى +للحم +للحمار +للحمام +للحماية +للحمل +للحملة +للحوادث +للحوار +للحواريين +للحواس +للحول +للحياة +للحيتان +للحيف +للحيلولة +للحيوان +للحيوانات +للخارج +للخالق +للخدمات +للخدمة +للخروج +للخريج +للخريجين +للخصخصة +للخضوع +للخط +للخطة +للخطر +للخطوبة +للخطوط +للخلاص +للخلاف +للخلافة +للخلايا +للخلف +للخلل +للخلية +للخليج +للخليفة +للخمود +للخناجر +للخواص +للخوف +للخيال +للخيالات +للخيامية +للخيبة +للخير +للخيل +للخيمي +للخيوط +للخيول +للدائن +للداخل +للداخلين +للدار +للدارس +للدارسين +للداعيات +للداعية +للدبابات +للدببة +للدبلوم +للدخان +للدخل +للدخول +للدراسات +للدراسة +للدراما +للدرجة +للدرس +للدعاية +للدعم +للدعوة +للدفاع +للدكان +للدكتور +للدكتوراه +للدكتورة +للدلالة +للدم +للدماء +للدمار +للدموع +للدميري +للدنيا +للدهشة +للدهون +للدواء +للدواب +للدوخة +للدودة +للدور +للدورة +للدول +للدولة +للديار +للديانات +للديك +للديمقراطية +للدين +للذئاب +للذات +للذاتي +للذاكرة +للذبح +للذرة +للذكر +للذكور +للذهاب +للذهب +للذهنية +للذوبان +للذود +للذين +للرأس +للرأسمالية +للرأي +للرأيين +للرؤساء +للرؤية +للرئتين +للرئيس +للرابطة +للراحة +للراحل +للراديو +للرازي +للراعي +للراكب +للراهبات +للرب +للربط +للربو +للرجال +للرجل +للرجلين +للرحلات +للرحلة +للرحيق +للرحيل +للرد +للرداءة +للرذيلة +للرسائل +للرسالة +للرسم +للرصاص +للرصاصة +للرصد +للرض +للرضا +للرضيع +للرعاية +للرفاهية +للرقابة +للرقة +للرقص +للرقصات +للركاب +للرواد +للرواية +للروح +للروسية +للرومانسية +للري +للرياح +للريادة +للرياضة +للرياضيات +للريب +للريبرتوار +للريح +للرُها +للزائر +للزائرين +للزبيدي +للزحف +للزرابي +للزراعة +للزرزور +للزعم +للزعنفة +للزعيم +للزفاف +للزكاة +للزمان +للزمكان +للزمن +للزنك +للزنوج +للزهرة +للزواج +للزوار +للزوال +للزورق +للزي +للزيارة +للزينة +للسؤال +للسائح +للسائحـين +للسائحين +للسائد +للسائل +للسابع +للساحة +للسادات +للسادة +للساسة +للساعات +للساعة +للسباحة +للسباق +للسبعينيات +للسجل +للسجن +للسجناء +للسجين +للسحور +للسخرية +للسرادق +للسرطان +للسطح +للسعادة +للسعة +للسعوديين +للسفارات +للسفر +للسفن +للسفير +للسكارى +للسكان +للسكة +للسكر +للسكن +للسلاجقة +للسلام +للسلطات +للسلطة +للسلطنة +للسلع +للسلف +للسلوك +للسلوكيات +للسماء +للسماح +للسمنة +للسموم +للسنة +للسنوات +للسهرة +للسود +للسودان +للسور +للسوفيات +للسوق +للسويد +للسياح +للسياحة +للسياحـة +للسيارات +للسيارة +للسياسات +للسياسة +للسيجار +للسيد +للسيدات +للسيدة +للسير +للسيرة +للسيطرة +للسيناريو +للسينما +للسينوباه +للسّنة +للسَّارين +للشؤون +للشئون +للشاب +للشارع +للشاطئ +للشاعر +للشاعرة +للشاي +للشباب +للشبكية +للشبهة +للشتاء +للشجرة +للشحن +للشحنات +للشخص +للشخصيات +للشخصية +للشدة +للشراء +للشرائح +للشراع +للشرب +للشرح +للشرطة +للشرطي +للشرعية +للشرفة +للشرق +للشركات +للشركة +للشروط +للشعاب +للشعارات +للشعب +للشعر +للشعراء +للشعوب +للشعوذة +للشعير +للشفاء +للشفقة +للشقاء +للشقق +للشك +للشكل +للشكلانية +للشمال +للشمس +للشهادة +للشهرة +للشهوة +للشواذ +للشواطئ +للشورى +للشوكولاتة +للشيخ +للشيخوخة +للشيرازيين +للشيوخ +للشيوعية +للصائمين +للصبي +للصبيان +للصحارى +للصحافة +للصحافيين +للصحة +للصحراء +للصحف +للصحفين +للصحيفة +للصداع +للصداقة +للصدر +للصراع +للصراعات +للصرف +للصعلوك +للصعود +للصعيد +للصف +للصفة +للصفدي +للصفوف +للصقور +للصلاة +للصلب +للصمت +للصناعات +للصناعة +للصهاينة +للصهيونية +للصواريخ +للصور +للصورة +للصوص +للصيادلة +للصيد +للصين +للصيوان +للضباب +للضباط +للضجيج +للضرب +للضرورة +للضفة +للضوء +للضوابط +للضياع +للضيافة +للضيف +للضيوف +للطائرات +للطائفين +للطابع +للطابق +للطاقة +للطالب +للطالبات +للطاهر +للطباعة +للطبري +للطبع +للطبعة +للطبقات +للطبيب +للطحالب +للطرب +للطرح +للطرف +للطرق +للطريق +للطريقة +للطعام +للطفرات +للطفرة +للطفل +للطفيل +للطلاءات +للطلاب +للطلب +للطلبة +للطناحي +للطوائف +للطوارئ +للطواف +للطول +للطيب +للطير +للطيران +للطيور +للطّالب +للظاهرة +للظروف +للظلام +للظهر +للظهور +للعائل +للعائلات +للعائلة +للعادة +للعار +للعاصمة +للعالم +للعالمية +للعالمين +للعام +للعامة +للعامل +للعاملين +للعب +للعبادة +للعبقري +للعبقريات +للعبقرية +للعبور +للعثمانيين +للعثور +للعجب +للعجز +للعدالة +للعدد +للعدسة +للعدل +للعدو +للعدوى +للعديد +للعذاب +للعراء +للعراق +للعراقي +للعرب +للعرج +للعرض +للعروبة +للعروض +للعزاء +للعزف +للعسل +للعش +للعشاء +للعشاق +للعشرين +للعصر +للعضو +للعضوية +للعطاء +للعطور +للعفش +للعقائد +للعقاب +للعقار +للعقارات +للعقارب +للعقل +للعلاج +للعلاقات +للعلاقة +للعلم +للعلماء +للعلوم +للعمادة +للعمارة +للعمالة +للعماني +للعمرة +للعمل +للعملاء +للعملات +للعملاق +للعملة +للعمى +للعميد +للعناكب +للعناية +للعنصر +للعنف +للعهد +للعواصف +للعواطف +للعوام +للعود +للعودة +للعولمة +للعيان +للعيش +للعين +للعينين +للعيون +للـ +للفئات +للفئة +للفتاة +للفتح +للفترة +للفتوى +للفتيات +للفحم +للفحوصات +للفرار +للفرجة +للفرح +للفرد +للفرص +للفرق +للفرقة +للفرنج +للفرنجة +للفروسية +للفروق +للفريق +للفساد +للفسطاط +للفصل +للفضاء +للفضائيات +للفضلات +للفطرة +للفعل +للفقراء +للفقمة +للفقهاء +للفكر +للفكرة +للفلاسفة +للفلسطينيين +للفلسفة +للفلكلور +للفليبين +للفن +للفنادق +للفنان +للفنانة +للفنانين +للفندق +للفنون +للفهم +للفوائد +للفوز +للفياجرا +للفيتامين +للفيتلمينات +للفيروس +للفيروسات +للفيزياء +للفيضانات +للفيلا +للفيلاريا +للفيلم +للقاء +للقاءات +للقائنا +للقاح +للقادرين +للقادم +للقادمين +للقارئ +للقارات +للقاري +للقاصدين +للقانون +للقاهرة +للقبائل +للقبض +للقبلات +للقبلية +للقبول +للقبيلة +للقتل +للقدر +للقدرة +للقدس +للقدم +للقدمين +للقرآن +للقراء +للقراءة +للقرار +للقراصنة +للقرب +للقربات +للقرحات +للقرحة +للقرد +للقرض +للقرم +للقرن +للقرى +للقرية +للقرّاء +للقسم +للقصبات +للقصة +للقصص +للقصور +للقصيدة +للقضاء +للقضبان +للقطاع +للقطاعات +للقطب +للقطرات +للقطن +للقطيعة +للقـا +للقلب +للقلق +للقلوب +للقماش +للقمح +للقنوات +للقوات +للقوانين +للقوة +للقول +للقوى +للقوي +للقيادة +للقياس +للقيام +للقيم +للكائن +للكائنات +للكاتب +للكاتبة +للكاثوليكية +للكارثة +للكارديوليبين +للكاريكاتير +للكاميرا +للكبار +للكبريت +للكتاب +للكتابة +للكتب +للكتل +للكتّاب +للكثير +للكثيرين +للكحلاوي +للكراهية +للكسر +للكشف +للكل +للكلام +للكلب +للكلس +للكلمات +للكلمة +للكلية +للكم +للكمبيوتر +للكميت +للكنائس +للكنيسة +للكهرباء +للكوارث +للكورنيش +للكوكائين +للكون +للكونجرس +للكويت +للكيان +للكيانات +للكيفية +للكيماويات +للكيمياء +للكينونة +للمأزق +للمؤتمر +للمؤتمرات +للمؤذن +للمؤسسات +للمؤسسة +للمؤلف +للمؤمن +للمؤمنين +للماء +للماجستير +للمادة +للمارة +للماضي +للمبادرة +للمبتدئين +للمبدع +للمبدعين +للمبرد +للمبررات +للمبرّد +للمبشر +للمبنى +للمبيد +للمبيدات +للمبيعات +للمتأمل +للمتابع +للمتابعة +للمتاجرة +للمتحف +للمتر +للمترجمين +للمتزوجين +للمتعة +للمتهم +للمتوفى +للمثقفين +للمجاهدين +للمجتمع +للمجتمعات +للمجرات +للمجرى +للمجعراتي +للمجلة +للمجلدات +للمجلس +للمجمع +للمجموعات +للمجموعة +للمحار +للمحاسبات +للمحاصيل +للمحاضر +للمحافظة +للمحاكم +للمحاكمة +للمحاماة +للمحبين +للمحتاجين +للمحلات +للمحيط +للمحيطين +للمخ +للمخاطية +للمختصين +للمخدرات +للمخرج +للمخزن +للمخصِّبات +للمخطوطات +للمخيلة +للمدارس +للمدة +للمدرسة +للمدرسين +للمدن +للمدنية +للمديرة +للمديرين +للمدينة +للمرء +للمرأة +للمراجعة +للمراحل +للمراقبة +للمراكب +للمراكز +للمربي +للمرة +للمرجانيات +للمرحلة +للمرحلتين +للمرحوم +للمرسم +للمرصد +للمرض +للمرضى +للمركب +للمركز +للمريض +للمزادات +للمزارعين +للمزايا +للمزيد +للمسألة +للمسئولين +للمساءلة +للمساجد +للمساحات +للمساحة +للمسارح +للمساعدات +للمساعدة +للمسافر +للمسافرين +للمساهمة +للمستثمر +للمستثمرين +للمستشرقة +للمستشفى +للمستعمر +للمستقبل +للمستهلكين +للمستوى +للمستويات +للمسجد +للمسدس +للمسرح +للمسكنات +للمسلسل +للمسلم +للمسلمات +للمسلمين +للمسمين +للمسنين +للمسيح +للمسيحية +للمشاة +للمشاركة +للمشاركين +للمشاريع +للمشاعر +للمشاكل +للمشاهد +للمشاهدين +للمشتركين +للمشروع +للمشروعات +للمشفقات +للمشكلة +للمشهد +للمشي +للمصابين +للمصادر +للمصارعين +للمصارف +للمصريات +للمصريين +للمصطلح +للمصعب +للمصلحة +للمصلين +للمصنع +للمضادات +للمضي +للمضيفات +للمطار +للمطارحات +للمطاردة +للمطالبة +للمطر +للمطرب +للمطربين +للمظاهر +للمظلوم +للمعادلات +للمعادن +للمعارضة +للمعارف +للمعاش +للمعاق +للمعاقين +للمعالجات +للمعالجة +للمعالم +للمعاملة +للمعاناة +للمعاهد +للمعاىير +للمعايير +للمعبد +للمعتزلة +للمعتصم +للمعتقدات +للمعتمرين +للمعدات +للمعدة +للمعدلات +للمعدَّل +للمعرض +للمعرفة +للمعركة +للمعري +للمعلم +للمعلمات +للمعلمة +للمعلمين +للمعلومات +للمعنى +للمعهد +للمعوّقات +للمعيدين +للمعيشة +للمفاهيم +للمفتاح +للمفترى +للمفتش +للمفردات +للمفكر +للمفهوم +للمقارنة +للمقاطعة +للمقامات +للمقاومة +للمقاييس +للمقبرة +للمقدسات +للمقعد +للمكاتب +للمكان +للمكانة +للمكاوي +للمكتب +للمكتبات +للمكتبة +للمكفوفين +للملابس +للملاحة +للملاريا +للملايين +للملتزمات +للملحمة +للملحن +للملك +للملوك +للمليارات +للممارسات +للممارسة +للممثل +للممر +للمملكة +للمناخ +للمنازل +للمناسبات +للمناسبة +للمناسك +للمناطق +للمناعة +للمنافذ +للمنافسة +للمناقشة +للمناهج +للمناورة +للمنتجات +للمنتجع +للمنتخبات +للمنتسبين +للمنزل +للمنشآت +للمنشأة +للمنطق +للمنطقة +للمنظرين +للمنفلوطي +للمنكوبين +للمنهج +للمهاجرين +للمهاري +للمهرجان +للمهمة +للمهند +للمواجهة +للمواد +للموارد +للمواصفات +للمواضعات +للمواطن +للمواطنين +للموافقة +للمواقع +للمواقف +للموانئ +للمواهب +للموت +للموج +للمودة +للمودودي +للموروث +للموسم +للموسوعة +للموسيقار +للموسيقى +للموسيقيين +للموصل +للموضوع +للموظف +للموظفين +للموقف +للموهبة +للموهوبين +للمياه +للميثاق +للميلاد +للنائم +للنادرة +للنادل +للنار +للناس +للناشئة +للنافورة +للناقد +للناقل +للناقلة +للنامي +للنبات +للنباتات +للنبي +للنتائج +للنتاج +للنثر +للنجاة +للنجاح +للنجم +للنجوم +للنجومية +للنحاس +للنحت +للنحر +للنحل +للنخب +للنخبة +للنرجسية +للنزاع +للنزاعات +للنزلاء +للنزوع +للنزيل +للنساء +للنسخ +للنسور +للنسيان +للنشء +للنشاط +للنشالين +للنشر +للنص +للنصر +للنصرانية +للنصوص +للنطاسي +للنطاق +للنظائر +للنظارات +للنظام +للنظر +للنظرة +للنظرية +للنظم +للنفاذ +للنفس +للنفوذ +للنقاد +للنقاش +للنقد +للنقص +للنقل +للنقود +للنكتة +للنمساوي +للنمط +للنمل +للنمو +للنهاية +للنهب +للنهر +للنهضة +للنهوض +للنوارس +للنوايا +للنوبات +للنور +للنوعين +للنوم +للنوى +للنيران +للنيل +للنَّدى +لله +للهاثهم +للهبوط +للهجات +للهجرات +للهجران +للهجرة +للهجمة +للهجوم +للهجين +للهدف +للهدوء +للهراوي +للهرم +للهروي +للهشيم +للهكتار +للهلاك +للهند +للهندسة +للهنود +للهواء +للهواية +للهوية +للهيئة +للهياج +للهيب +للهيدروجين +للهيمنة +للواحات +للواقدي +للواقع +للواقعة +للواقعية +للوالدين +للوتدة +للوثنية +للوجه +للوجهات +للوجود +للوجودية +للوحاتها +للوحة +للوحدات +للود +للوراثة +للورد +للوزارة +للوزمة +للوزير +للوسط +للوسن +للوصول +للوصوليين +للوضع +للوضوء +للوطن +للوظائف +للوعظ +للوفاء +للوفاة +للوفد +للوفود +للوفيات +للوقاية +للوقت +للوقف +للوقود +للوقوف +للولايات +للولاية +للون +للوهلة +للويس +لليابان +لليابس +لليافعين +لليبيا +لليرموك +لليسار +لليل +لليلة +لليلى +للينابيع +لليهود +لليوم +لليونسكو +لليونيسكو +للُعب +لم +لمأكل +لمؤتمر +لمؤسس +لمؤسسات +لمؤسسة +لمؤلفات +لمؤلفه +لمؤلفين +لمؤيد +لمئات +لما +لماء +لمادة +لماذا +لمارتن +لمارتي +لماري +لمالكي +لماما +لمانحين +لمبادئ +لمباشرة +لمبدأ +لمبررات +لمبعوث +لمبيد +لمبيدات +لمتابعة +لمتحف +لمتخذي +لمتطلبات +لمتعة +لمتعتها +لمتعددي +لمثقف +لمثل +لمجابهة +لمجاراة +لمجال +لمجتمعات +لمجتمعاتها +لمجتمعنا +لمجتمعها +لمجد +لمجرد +لمجلة +لمجلد +لمجلس +لمجمعات +لمجمل +لمجموعات +لمجموعة +لمجموعتك +لمجموعتي +لمجهوداته +لمجيد +لمح +لمحات +لمحادثتها +لمحاربة +لمحاصرة +لمحاصيل +لمحاضرات +لمحاضرة +لمحافظة +لمحاكم +لمحاكمة +لمحاولات +لمحاولة +لمحاولته +لمحب +لمحبي +لمحة +لمحت +لمحتها +لمحتويات +لمحتوياته +لمحدث +لمحدّدات +لمحصولي +لمحطات +لمحطته +لمحل +لمحلات +لمحلول +لمحمد +لمحمود +لمحنة +لمحو +لمخ +لمخاطر +لمخالفة +لمختبر +لمخترع +لمختلف +لمخصصات +لمخطوطات +لمخلوق +لمخيلتهم +لمد +لمداخلة +لمدافع +لمدة +لمدد +لمدرسة +لمدن +لمدى +لمدي +لمدينة +لمدينته +لمدّة +لمرأى +لمرات +لمراجعة +لمراحل +لمرارة +لمراسم +لمراعاة +لمرافق +لمراقبة +لمراكز +لمراوح +لمرة +لمرتادى +لمرتع +لمرحلة +لمرحلتين +لمرشحي +لمرض +لمرضه +لمرضهم +لمرضى +لمرفق +لمركب +لمركز +لمريض +لمريم +لمزارع +لمزاولة +لمزيد +لمس +لمسألة +لمسؤلين +لمسئولين +لمسائل +لمسائلَ +لمسات +لمساحات +لمساحيق +لمسار +لمساعدة +لمساعدتك +لمساعدتنا +لمساعدتها +لمساعدتهم +لمسافات +لمسافة +لمسافري +لمسالك +لمساندة +لمساندتها +لمساهماته +لمسايرة +لمسة +لمست +لمستخدميها +لمستفتٍ +لمستقبله +لمستكشف +لمستلزمات +لمسته +لمستودع +لمستوى +لمستويات +لمسح +لمسخ +لمسرح +لمسرحياتي +لمسرحية +لمسلم +لمسلمي +لمسه +لمسها +لمسيرة +لمسيرته +لمشاركة +لمشاركتنا +لمشاركتهم +لمشاريع +لمشاعر +لمشاعري +لمشاكل +لمشاكله +لمشاهد +لمشاهدة +لمشاهدتها +لمشاوي +لمشتركات +لمشروع +لمشروعات +لمشروعه +لمشروعها +لمشروعي +لمشكلة +لمشهد +لمشيئة +لمشيئتها +لمصادر +لمصادرة +لمصالح +لمصانع +لمصداقية +لمصر +لمصطفى +لمصطلح +لمصلحة +لمصلحتهم +لمصير +لمضمونه +لمضيق +لمطابقتها +لمطاحن +لمطالب +لمطالعة +لمطران +لمطربة +لمطربين +لمطوري +لمظاهر +لمع +لمعادلات +لمعادلة +لمعارفنا +لمعارك +لمعاصرين +لمعالجات +لمعالجة +لمعالم +لمعاناته +لمعانه +لمعاني +لمعاهدة +لمعاونة +لمعاوية +لمعاىير +لمعاينة +لمعايير +لمعت +لمعتنقي +لمعدل +لمعدن +لمعرض +لمعرفة +لمعرفتهم +لمعركة +لمعصيتهم +لمعضلات +لمعضلة +لمعظم +لمعلمي +لمعلوف +لمعنوياتهم +لمعنى +لمعهد +لمعيار +لمــتابعة +لمفاهيم +لمفاوضة +لمفردات +لمفكر +لمفكرين +لمفكريها +لمفهوم +لمقابلة +لمقار +لمقارنة +لمقاعد +لمقالة +لمقامه +لمقاومة +لمقاومته +لمقاييس +لمقبض +لمقتضى +لمقدرة +لمقر +لمقولة +لمقومات +لمقوماتها +لمكافحة +لمكافحتها +لمكامن +لمكان +لمكانة +لمكانته +لمكتب +لمكتبة +لمكتبه +لمكفوفي +لملء +لملابسات +لملاحقة +لملازمته +لملاقاة +لملامح +لملامحها +لملايين +لملتقي +لملعب +لملك +لملكة +لملمة +لملمت +لملمتها +لملوك +لملوّثات +لممارسات +لممارسة +لممارستها +لممارسى +لممارسي +لممتلكاتها +لمملكة +لمن +لمنابع +لمناجاة +لمناخ +لمنازل +لمناسبة +لمناشدتها +لمناطق +لمناظر +لمنافستها +لمناقشة +لمناهج +لمنتجات +لمنتجاتها +لمنتجي +لمنح +لمنحنى +لمنزل +لمنزله +لمنزلي +لمنصور +لمنطقة +لمنطقته +لمنظر +لمنظمة +لمنظومة +لمنظّف +لمنع +لمنعهم +لمنفعة +لمنهج +لمنهجي +لمهاجمة +لمهرجان +لمهمة +لمهمته +لمهنتك +لمهنتي +لمهندسي +لمواجهة +لمواجهته +لمواد +لموارد +لموارده +لمواسم +لمواصلة +لمواطنهم +لمواطنى +لمواطني +لمواطنيه +لمواقف +لمواكبة +لموت +لموجات +لموجوعي +لمورسكيين +لموسكو +لموسم +لموسيقى +لموضوع +لموضوعات +لموطئ +لموطن +لموظف +لموقف +لمياه +لميتة +لميزان +لميزانية +لميكروب +لميل +لمَ +لمّا +لمْ +لن +لنأخذ +لنأكل +لنؤكد +لنؤكّد +لنا +لناأنا +لنابعد +لنادل +لنادي +لناس +لناقة +لنبات +لنباتات +لنبتعد +لنبث +لنبحث +لنبدأ +لنبذ +لنبرة +لنبرهن +لنبوءة +لنتأمل +لنتأمّل +لنتائج +لنتابع +لنتبادل +لنتركها +لنتعرف +لنتن +لنتوقف +لنتيجة +لنجاح +لنجد +لنجدة +لنجله +لنجم +لنجيب +لنحسبه +لنحصل +لنحو +لنخبة +لنختبئ +لنختتم +لنداء +لنداءات +لندائي +لندخل +لندع +لندن +لندني +لندنية +لنذهب +لنراقب +لنرد +لنرى +لنزلاء +لنزلائه +لنزورها +لنزول +لنزولك +لنزولها +لنزيح +لنساء +لنسبة +لنستدلّ +لنستريح +لنستطيع +لنستمد +لنسهر +لنشأة +لنشاط +لنشاطه +لنشاهد +لنشر +لنشرتنا +لنشرها +لنشكل +لنص +لنصارى +لنصح +لنصرتها +لنصف +لنصل +لنصوص +لنضال +لنضحي +لنضع +لنضفي +لنضوجهم +لنطقنا +لنطل +لنظارات +لنظافة +لنظام +لنظامنا +لنظامي +لنظر +لنظرائهم +لنظرة +لنظريات +لنظرية +لنظم +لنعد +لنعرف +لنعطي +لنعود +لنعيش +لنفحات +لنفرش +لنفس +لنفسك +لنفسه +لنفسها +لنفسي +لنفسية +لنفهم +لنفوس +لنفي +لنقابة +لنقاش +لنقاط +لنقترب +لنقد +لنقدم +لنقص +لنقل +لنقلته +لنقول +لنكمل +لنكملْ +لنلتقط +لنلتقى +لنلتقي +لنلمح +لنمارس +لنمو +لنموذج +لنموه +لنموهم +لنناقش +لننام +لننتبه +لننتظر +لننتقل +لننطلق +لنهاية +لنهايتها +لنهج +لنهجها +لنهر +لنهري +لنهضة +لنواة +لنوازع +لنواصل +لنواياهم +لنوبات +لنوبل +لنودعها +لنوع +لنوعية +لنوم +لنومٍ +لنيران +لنيكولن +لنيل +لنَمْذَجة +لنُصْحها +له +لهؤلاء +لها +لهاتين +لهافانا +لهالة +لهاييتي +لهب +لهبوط +لهث +لهجات +لهجة +لهجته +لهجتهم +لهجتي +لهجمات +لهجوم +لهجَتْ +لهدأة +لهدر +لهدفين +لهدم +لهدمها +لهذا +لهذه +لهذين +لهزات +لهزيمة +لهفة +لهفتها +لهم +لهما +لهن +لهندسة +لهو +لهواء +لهواة +لهولندا +لهوليدي +لهوية +لهى +لهيئات +لهيئة +لهيب +لهيبتها +لهيكل +لهيمنة +لهيمنتها +لو +لواء +لوائح +لوائها +لواثقون +لواجهات +لواحد +لوادي +لوازم +لوازمهم +لواعج +لواقع +لوالد +لوالدتي +لوالدك +لوالده +لوالدها +لوالدى +لوالديك +لوالديه +لوباتشفسكي +لوبلان +لوبلولى +لوبين +لوت +لوتاه +لوتيليري +لوثائق +لوثر +لوثه +لوثها +لوجد +لوجدت +لوجدنا +لوجدناها +لوجه +لوجهات +لوجهة +لوجهي +لوجود +لوجودنا +لوجوده +لوجودها +لوجودهم +لوجودي +لوجوه +لوح +لوحا +لوحات +لوحاته +لوحاتهم +لوحاتي +لوحة +لوحته +لوحتي +لوحتين +لوحدة +لوحده +لوحدها +لوحدهم +لوحش +لوحظ +لوحظت +لودرميلك +لودفيج +لودفيكو +لورا +لورد +لوركا +لورنس +لوره +لورين +لوزات +لوزارة +لوزراء +لوزن +لوزير +لوس +لوسائل +لوسيون +لوسيونات +لوشة +لوصف +لوصول +لوصوله +لوصولي +لوضع +لوضعها +لوضعيات +لوضعيتها +لوطننا +لوطنها +لوظيفة +لوعة +لوفد +لوفرة +لوفود +لوفيلان +لوفين +لوقا +لوقائع +لوقت +لوقف +لوقود +لوقوع +لوكاش +لوكالات +لوكالة +لوكتبنا +لوكلاء +لوكيد +لولا +لولائي +لولاه +لولاية +لولبي +لولوج +لوليفه +لوليمة +لوليو +لوم +لوموند +لوميير +لون +لونان +لوناً +لونجة +لونجمان +لونه +لونها +لوني +لونية +لونين +لونًا +لونِها +لويد +لويز +لويزة +لويس +لويسفيل +لويلسون +لويندوز +لى +لي +ليأتي +ليأخذ +ليأكل +ليأكلوا +ليأمرهم +ليؤدي +ليؤدينها +ليؤسس +ليؤكد +ليؤهلنا +لياقة +ليال +ليالي +ليالينا +لياليّ +ليامن +ليباد +ليباعوا +ليبحث +ليبدأ +ليبدو +ليبرالى +ليبرالي +ليبرالية +ليبرتي +ليبرز +ليبرمان +ليبقى +ليبكوا +ليبمان +ليبنوا +ليبور +ليبي +ليبيا +ليبيات +ليبية +ليبيدات +ليبيعوها +لية +ليت +ليتأكد +ليتاح +ليتامى +ليتبناه +ليتبين +ليتجاوز +ليتحدث +ليتحلى +ليتحمل +ليتحملوا +ليتخذوهما +ليتخلص +ليتر +ليترجمها +ليترسب +ليتركوا +ليتزوج +ليتسع +ليتسنى +ليتطلّب +ليتعدى +ليتعرف +ليتعلم +ليتعلمن +ليتعلموا +ليتفادى +ليتقدم +ليتقوا +ليتك +ليتكدسوا +ليتل +ليتلاءم +ليتلقاه +ليتلو +ليتم +ليتماشى +ليتمتع +ليتمكن +ليتناولوا +ليتني +ليته +ليتها +ليتهم +ليتوانيا +ليتوبوا +ليتوحش +ليتولى +ليتَكِ +ليثبت +ليثجاو +ليجتمعوا +ليجد +ليجدوا +ليجدوه +ليجس +ليجسد +ليجعل +ليجعله +ليجعلوا +ليجعلوهم +ليجعلَ +ليجلسها +ليجمعوا +ليجهزوا +ليجيب +ليحارب +ليحافظ +ليحب +ليحتطب +ليحتفظ +ليحتوي +ليحثني +ليحدد +ليحزن +ليحصل +ليحضره +ليحضرها +ليحطم +ليحظى +ليحفظها +ليحقق +ليحك +ليحكم +ليحل +ليحمل +ليحول +ليحيل +ليحيى +ليخبره +ليخبرهم +ليختاروا +ليختفي +ليختلط +ليخرج +ليخرجها +ليخطر +ليخفي +ليخلطا +ليخلّصه +ليدخل +ليدرس +ليدرك +ليدعوهم +ليدفئ +ليدفعوا +ليدفن +ليدفنوه +ليدن +ليدون +ليدي +ليديا +ليدير +ليديره +ليذاكر +ليذبح +ليذكر +ليرأس +ليرة +ليرتاح +ليرد +ليرسلوا +ليرسم +ليرسمني +ليرصد +ليرقع +ليرقي +ليرمي +ليرميه +ليرهب +ليروا +ليروجها +ليروي +ليرى +ليرينيوس +ليريهم +ليزا +ليزجي +ليزداد +ليزدادَ +ليزر +ليزري +ليزرية +ليزور +ليزيح +ليزيدها +ليس +ليسأله +ليسألوا +ليسا +ليساعد +ليساعده +ليسافر +ليسانس +ليسبح +ليست +ليستا +ليستجم +ليستجيب +ليستحم +ليستر +ليستريح +ليستسلموا +ليستطيع +ليستعر +ليستعرض +ليستعيرها +ليستقر +ليستقروا +ليستقي +ليستكشف +ليستكمل +ليستمتعوا +ليستمد +ليستمر +ليستنزفها +ليستوطنوا +ليستولي +ليسجل +ليسد +ليسرد +ليسرق +ليســــت +ليسهل +ليسوا +ليش +ليشاركوننا +ليشاهدوا +ليشبعوا +ليشتري +ليشرب +ليشعر +ليشفع +ليشق +ليشقوا +ليشكل +ليشكلا +ليشمل +ليشهدوا +ليشير +ليشْحن +ليصبح +ليصطحب +ليصعد +ليصل +ليصلوا +ليصنع +ليصير +ليضخّم +ليضرب +ليضع +ليضعه +ليضعها +ليضعوا +ليضعوها +ليضفي +ليضيف +ليضيق +ليطالع +ليطبق +ليطفو +ليطل +ليطلق +ليطلقوا +ليطهر +ليطيح +ليطيل +ليظل +ليظهر +ليظهره +ليعاد +ليعالج +ليعالجوه +ليعاود +ليعبدون +ليعبر +ليعتمد +ليعتمدوا +ليعجب +ليعدل +ليعرض +ليعرف +ليعرفن +ليعرفنا +ليعطينا +ليعقبه +ليعلق +ليعلم +ليعلموا +ليعلن +ليعلنا +ليعمل +ليعملا +ليعملوا +ليعود +ليعيد +ليعيش +ليعيشوا +ليعينك +ليفاجأ +ليفارق +ليفتح +ليفر +ليفربول +ليفرض +ليفروا +ليفزعه +ليفنى +ليفهم +ليفي +ليقابلوا +ليقاوم +ليقبض +ليقبل +ليقبلها +ليقتبسوا +ليقترب +ليقتفي +ليقتل +ليقتله +ليقتلوا +ليقدم +ليقدموا +ليقرءوا +ليقضي +ليقطع +ليقف +ليقم +ليقمع +ليقول +ليقولوا +ليقوم +ليقوموا +ليقيم +ليكتب +ليكتسح +ليكتشف +ليكتشفها +ليكتشفوا +ليكسبها +ليكمل +ليكن +ليكون +ليكونوا +ليل +ليلا +ليلاً +ليلة +ليلةٍ +ليلتان +ليلتحق +ليلتقط +ليلتقطوا +ليلته +ليلتهمه +ليلتي +ليلتين +ليلحقوا +ليلد +ليلعبا +ليلفنا +ليلقوا +ليلقى +ليلقي +ليله +ليلى +ليلي +ليلياً +ليلية +ليما +ليمارس +ليمان +ليمثل +ليمفوما +ليملأوها +ليمنحنا +ليمنع +ليمنعوك +ليموزين +ليمون +ليميز +لين +لينا +ليناس +لينال +لينام +لينتج +لينتزعوا +لينتظروا +لينتظم +لينتهي +لينجز +ليندي +لينذر +لينزل +لينسي +لينشئوا +لينضما +لينظر +لينظم +لينظموا +لينعم +لينفق +لينقذ +لينقضُ +لينقل +لينكولن +لينمو +لينياس +لينير +لينين +ليه +ليها +ليهاجر +ليهدم +ليو +ليواجه +ليواجهن +ليواسي +ليواصل +ليوجهوا +ليودعني +ليوسف +ليوصله +ليوضع +ليوفر +ليوفقا +ليوقف +ليوم +ليون +ليونارد +ليوناردو +ليونور +ليونيد +ليوهم +ليُحكم +ليُصدَّر +ليّ +ليّن +ليَّ +لَمْ +لَهُمْ +لُعب +لُمَعٌ +لِتَعَارَفُوا +لِما +لِمَن +م +مآثر +مآثرنا +مآذنها +مآرب +مآس +مآسي +مآكل +مأثرة +مأثور +مأثورًا +مأخذه +مأخذي +مأخوذا +مأخوذاً +مأخوذة +مأخوذين +مأدبة +مأرب +مأزق +مأزقا +مأزقاً +مأزقه +مأساة +مأساته +مأساوي +مأساويا +مأساوية +مأساويًا +مأسدة +مأسورة +مأكولات +مأكولاتنا +مأكولاً +مألوف +مألوفا +مألوفة +مأمن +مأمورية +مأمون +مأمونة +مأمونية +مأوى +مؤاتية +مؤامرة +مؤامرتهم +مؤتلف +مؤتمر +مؤتمرا +مؤتمرات +مؤتمراته +مؤتمراً +مؤتمرًا +مؤتمن +مؤثر +مؤثرا +مؤثرات +مؤثراتهم +مؤثراً +مؤثرة +مؤثرين +مؤثّرة +مؤثِّراً +مؤخرا +مؤخراتهم +مؤخراً +مؤخرة +مؤخرًا +مؤد +مؤداها +مؤدبة +مؤديا +مؤدية +مؤدّاها +مؤذيا +مؤذياً +مؤذية +مؤرخ +مؤرخا +مؤرخهم +مؤرخو +مؤرخي +مؤسس +مؤسسا +مؤسسات +مؤسساتنا +مؤسساً +مؤسسة +مؤسسته +مؤسستها +مؤسستين +مؤسسها +مؤسسوها +مؤسسي +مؤسسية +مؤسسيه +مؤسسيها +مؤسسًا +مؤشر +مؤشرا +مؤشرات +مؤشراتهما +مؤشراً +مؤشرٌ +مؤشِّراً +مؤصّلاً +مؤطرا +مؤقت +مؤقتا +مؤقتاً +مؤقتة +مؤقَّت +مؤكد +مؤكدا +مؤكدة +مؤكدين +مؤكدًا +مؤكسج +مؤكسدة +مؤكّدة +مؤلف +مؤلفا +مؤلفات +مؤلفاتنا +مؤلفاته +مؤلفاتهم +مؤلفاتي +مؤلفاً +مؤلفة +مؤلفتين +مؤلفه +مؤلفها +مؤلفون +مؤلفوها +مؤلفين +مؤلفيه +مؤلفًا +مؤلم +مؤلما +مؤلماً +مؤلمة +مؤمن +مؤمناً +مؤمنة +مؤهبة +مؤهل +مؤهلا +مؤهلات +مؤهلاته +مؤهلاتها +مؤهلاً +مؤهلة +مؤهلتان +مؤهلين +مؤهّل +مؤيد +مؤيدا +مؤيدوها +مئات +مئة +مئتى +مئذنة +مئزره +مئونة +مئوية +مئويّ +ما +ماء +ماءها +ماءً +ماأزال +ماأطلقت +ماؤه +ماإذا +مائة +مائتا +مائتى +مائتي +مائتين +مائدة +مائل +مائلة +مائها +مائى +مائي +مائياً +مائية +ماالتوصيات +ماالذي +مابقيت +مابين +مات +ماتا +ماتت +ماتر +ماترهورن +ماتلبث +ماتو +ماتوا +ماتيس +ماثل +ماثلا +ماثلاً +ماثلة +ماجاس +ماجد +ماجدة +ماجستير +مادام +مادامت +ماداموا +مادة +مادته +مادتي +مادح +مادمت +مادمنا +مادون +مادي +ماديا +مادياً +مادية +ماديًا +ماذا +مار +ماراثون +مارايني +مارةً +مارتن +مارتي +مارجالا +مارجرجس +مارجريت +مارد +مارس +مارست +مارسته +مارستُها +مارسوا +مارسيل +مارك +ماركة +ماركت +ماركتها +ماركس +ماركسياً +ماركسية +ماركو +ماركوس +ماركيز +مارلين +مارون +ماري +ماريا +ماريانو +ماريلا +ماريلاند +مارين +مارينا +ماريو +ماريي +مازال +مازالت +مازالتا +مازالوا +مازلت +مازلنا +مازن +ماساتشوستس +ماساشوسيتس +ماسانشوستش +ماسة +ماستركارد +ماسح +ماسحًا +ماسك +ماسكين +ماسويه +ماسيبو +ماسيموديوتي +ماسّة +ماشاء +ماشيا +ماشياً +ماص +ماصدرت +ماض +ماضون +ماضي +ماضية +ماضينا +ماضيه +ماضيها +ماضيهم +ماضيين +ماضٍ +ماطبق +ماعت +ماعدا +ماعداه +ماعداهم +ماعرف +ماعز +ماعوز +ماعية +مافيها +ماقبل +ماقراءات +ماقلت +ماقلته +ماك +ماكبث +ماكجل +ماكدونالدز +ماكرة +ماكسون +ماكسويل +ماكفرلن +ماكفيه +ماكو +ماكول +ماكينات +ماكينة +مال +مالا +مالاما +مالاً +مالبث +مالت +مالتوس +مالحا +مالحاً +مالحة +مالطا +مالطية +مالقا +مالك +مالكة +مالكم +مالكها +مالكولم +مالكوم +مالكون +مالكي +مالم +مالنا +ماله +مالها +مالي +مالية +ماليزي +ماليزيا +ماليكون +ماليًا +ماليًّا +ماما +مامدى +ماملا +مانجو +مانحاً +مانديل +مانديلا +مانشتات +مانشر +مانشستر +مانع +مانعة +مانعين +مانلي +مانهايم +مانويل +ماني +مانيتوبا +مانيللا +ماهان +ماهذا +ماهر +ماهرا +ماهرة +ماهم +ماهو +ماهي +ماهية +ماهيته +ماهيدول +ماي +ماياكوفسكي +مايتردد +مايثار +مايجب +مايجرى +مايحدث +ماير +مايرز +مايزال +مايزرسكويب +مايزيد +مايسمى +مايشاهد +مايشبه +مايشي +مايصادف +مايعحبه +مايقال +مايقدمه +مايقرب +مايكروباص +مايكروسوفت +مايكفل +مايكل +مايكوبلاسما +مايلي +مايمكن +ماينمي +مايو +مايوصي +مب +مباحا +مباحث +مباحثات +مبادئ +مبادئه +مبادئها +مبادرات +مبادرة +مباراة +مبارزات +مبارك +مباركا +مباركة +مباركته +مباريات +مباشر +مباشرا +مباشراً +مباشرة +مباشرةً +مباشرًا +مبالية +مبان +مبانى +مباني +مبانيها +مباهج +مبتدأ +مبتدئ +مبتدئا +مبتدئاً +مبتدئة +مبتذلة +مبتسم +مبتسما +مبتسماً +مبتعدا +مبتعدة +مبتكر +مبتكرة +مبتكرًا +مبتلى +مبتهجا +مبتهجاً +مبتهجًا +مبتور +مبتورة +مبثوثة +مبجل +مبحث +مبحثها +مبحلقا +مبحوحا +مبخرة +مبدأ +مبدؤها +مبدئه +مبدئياً +مبدئية +مبدع +مبدعا +مبدعاً +مبدعة +مبدعها +مبدعون +مبدعين +مبدعينا +مبدلا +مبرحة +مبرد +مبرر +مبررا +مبررات +مبررة +مبررها +مبرمج +مبرمجا +مبسط +مبسطة +مبسّطة +مبشر +مبشرا +مبشراً +مبشرة +مبطنة +مبطونة +مبعث +مبعثرة +مبعثه +مبعدا +مبعدة +مبعوث +مبعوثة +مبعوثًا +مبقية +مبكر +مبكرا +مبكراً +مبكرة +مبكرًا +مبكّر +مبكّراً +مبللا +مبللة +مبنى +مبني +مبنيا +مبنياً +مبنية +مبنيً +مبهرة +مبهم +مبهمة +مبهمًا +مبهوتاً +مبهورا +مبهوراً +مبهورين +مبيد +مبيدات +مبيعا +مبيعات +مبيعاتها +مبيناً +مت +متآكل +متأبطا +متأتٍ +متأثر +متأثرا +متأثراً +متأثرة +متأثرون +متأخر +متأخرا +متأخرة +متأخرين +متأخرًا +متأسيًا +متأففًا +متأكد +متأكدا +متأكدة +متأكدون +متأكدين +متألق +متألقا +متألقة +متأملا +متأملاً +متأملة +متأنيا +متأنية +متأهبا +متابع +متابعة +متابعتك +متابعته +متابعتها +متابعتي +متابعيه +متاجر +متاح +متاحا +متاحاً +متاحة +متاحف +متاريس +متاع +متاعا +متاعب +متاعبه +متاعبها +متاعه +متانة +متاهات +متاهة +متاهته +متاهْ +متبادل +متبادلة +متباطئاً +متباعدة +متباعدتين +متباين +متبايناً +متباينة +متباينو +متبتلة +متبرمة +متبع +متبعة +متبعين +متبلات +متبلور +متبلّدة +متبنية +متتابعة +متتاليات +متتالية +متتاليتين +متتبعا +متثاقلة +متجانس +متجانسة +متجاوبة +متجاورة +متجاوزا +متجاوزاً +متجاوزة +متجدد +متجددا +متجددة +متجدّدة +متجر +متجردة +متجردًا +متجره +متجمعاً +متجه +متجها +متجهة +متجهم +متجهون +متجهين +متجهًا +متجولا +متحاشياً +متحجبات +متحجبتين +متحجر +متحدة +متحدث +متحدثاً +متحدثة +متحديا +متحدين +متحديه +متحرج +متحرر +متحررة +متحررين +متحرك +متحركاً +متحركة +متحركين +متحرّك +متحسسين +متحصنة +متحضر +متحضرون +متحـيز +متحف +متحفاً +متحفكم +متحفية +متحفّز +متحلقات +متحمسة +متحولة +متحوِّلاً +متحيز +متخذا +متخذين +متخشبة +متخصص +متخصصا +متخصصاً +متخصصة +متخصصتين +متخصصين +متخصصًا +متخطياً +متخفيا +متخفية +متخلف +متخلفاً +متخلفة +متخلفين +متخلّفاً +متخلّفة +متخلّفين +متخيلا +متداخلا +متداخلان +متداخلة +متداعية +متداولة +متدحرجا +متدربا +متدرجاً +متدفقة +متدن +متدني +متدنية +متدينا +متدينة +متدينون +متدينًا +متذرعة +متذكرا +متذمراً +متر +مترا +مترابطة +مترات +مترادفان +مترادفتين +مترادفين +متراصة +مترافقا +مترافقاً +مترافقة +متراكبة +متراكمة +مترامية +متران +متراً +متربة +متربصون +متربعين +مترتبة +مترجم +مترجما +مترجماً +مترجمة +مترجمه +مترجمو +مترجمي +مترجمين +مترجميها +متردد +مترددا +مترددة +مترددين +متردم +مترسبة +مترصّد +مترع +مترفة +مترق +مترقبة +مترقرق +متركّزاً +مترملة +مترهلا +متروكة +متري +متريس +مترين +مترًا +متزاحمات +متزامنا +متزامناً +متزايد +متزايداً +متزايدة +متزمتة +متزن +متزنة +متزوج +متزوجات +متزوجة +متزوجون +متساءلا +متسائلا +متسائلاً +متسائلة +متسابقا +متسارع +متسارعة +متساهلة +متساو +متساوون +متساويات +متساوية +متساوين +متسببتين +متسخة +متسربلون +متسع +متسعة +متسقا +متسقة +متسلقاً +متسلل +متسممة +متسمّراً +متسوق +متسولة +متسّع +متشائم +متشائماً +متشائمة +متشابكةَ +متشابكي +متشابه +متشابهات +متشابهة +متشابهةٍ +متشبعًا +متشدد +متشربا +متشربات +متشعب +متشوق +متصادمة +متصارعة +متصاعدا +متصل +متصلة +متصوراً +متصوفة +متضاربة +متضامنة +متضامنين +متضايق +متضايقا +متضخم +متضرر +متضرع +متضمّنًا +متطابقة +متطايرة +متطرفة +متطرفي +متطرفين +متطرّفة +متطفل +متطلبات +متطلباتها +متطلباتهم +متطلعاً +متطلعة +متطور +متطورة +متطوعان +متطوعون +متطوّر +متطوّرة +متظاهر +متع +متعادل +متعادلان +متعادلتان +متعاديتين +متعارضان +متعارضين +متعارف +متعاطفون +متعاطي +متعاقبة +متعاكسان +متعاكسة +متعاكستان +متعال +متعاملاً +متعانقًا +متعاونون +متعاونين +متعايشة +متعب +متعبا +متعبة +متعبين +متعة +متعته +متعثرة +متعجبا +متعجبون +متعجرفة +متعجلة +متعجِّلة +متعدد +متعددا +متعددة +متعددو +متعرج +متعرجة +متعسفة +متعصّبة +متعطرون +متعطش +متعطشة +متعطشين +متعطلين +متعلق +متعلقا +متعلقاً +متعلقة +متعلقًا +متعلم +متعلمة +متعمدا +متعمداً +متعمدة +متعمدين +متعمّدا +متعمّدين +متعنت +متعهد +متعوداً +متفائل +متفائلا +متفاعلا +متفاعلة +متفاوت +متفاوتاً +متفاوتة +متفتحة +متفجرا +متفرج +متفرفة +متفرقا +متفرقة +متفرقين +متفرّدة +متفرّقة +متفق +متفقا +متفقة +متفوق +متفوقة +متفوِّقة +متقابلتان +متقاربان +متقاربة +متقاطعة +متقاطعةً +متقاعد +متقد +متقدا +متقدة +متقدم +متقدما +متقدماً +متقدمة +متقدّمة +متقززا +متقشّفة +متقطع +متقطعة +متقطعًا +متقعرة +متقلّب +متقن +متقنة +متقوص +متكئا +متكئة +متكاتفة +متكاسلة +متكافئة +متكامل +متكاملا +متكاملان +متكاملاً +متكاملة +متكاملين +متكرر +متكرراً +متكررة +متكلم +متكلما +متكوما +متلألئاً +متلألئة +متلاحق +متلاحقة +متلازمات +متلازمان +متلازمة +متلازمين +متلازمًا +متلاصقة +متلاطم +متلامحة +متلبدة +متلبس +متلبسا +متلبساً +متلبسة +متلبّسة +متلذذا +متلصص +متلعثما +متلفّعة +متلقيا +متلهف +متلهفاً +متماثلا +متماثلة +متماهيا +متماوجة +متمتعين +متمثل +متمثلا +متمثلاً +متمثلة +متمثّلاً +متمحوراً +متمدد +متمدن +متمرد +متمردا +متمردة +متمرس +متمسكا +متمسكاً +متمسكة +متمكنا +متململا +متملّك +متممان +متمنيا +متمنين +متميز +متميزا +متميزاً +متميزة +متميزًا +متميّز +متميّزة +متن +متناثراً +متناثرة +متناسبا +متناسبة +متناسقة +متناسيا +متناسين +متناظر +متنافران +متنافرة +متناقصة +متناقضات +متناقضة +متنام +متنامية +متناه +متناهية +متناول +متناولهم +متنبها +متنبّهاً +متنزه +متنزها +متنصتاعلى +متنصرا +متنصرة +متنفسا +متنفساً +متنقلا +متنقلاً +متنكرا +متنها +متنهدا +متنورة +متنوع +متنوعا +متنوعة +متنوعون +متنوِّعة +متهالكة +متهجداً +متهدج +متهدلة +متهكما +متهكمة +متهم +متهما +متهمة +متهيجاً +متهّماً +متوائم +متواتر +متواترة +متوارث +متوارثة +متواز +متوازن +متوازناً +متوازنة +متوازية +متوازيين +متواصل +متواصلا +متواصلاً +متواصلة +متواضع +متواضعا +متواضعاً +متواضعة +متواضعًا +متوافر +متوافرا +متوافرة +متوافقا +متوافقاً +متوافقة +متوافقةً +متواليات +متوالية +متوترا +متوترة +متوثبة +متوجا +متوجة +متوجةً +متوجسا +متوجع +متوجها +متوجَّسًا +متوجَّهًا +متوحدة +متوحشة +متوحلون +متوذما +متوذمة +متورط +متورطاً +متورطتين +متوسط +متوسطة +متوسطي +متوسطية +متوضع +متوعدا +متوفر +متوفرة +متوقدتان +متوقع +متوقعا +متوقعاً +متوقعة +متوقفة +متولي +متون +متوهج +متوهماً +متى +متي +متيقظ +متيقنا +متيقنة +متيم +متيمنا +متين +متينا +متينة +متيّم +متّسعة +متّصل +متَّزن +متُّ +مثا +مثابة +مثار +مثاراً +مثال +مثالا +مثالاً +مثاله +مثالي +مثاليا +مثاليات +مثالية +مثانة +مثبت +مثبتا +مثبتة +مثبطات +مثبطاً +مثبطة +مثرثرات +مثريًا +مثقف +مثقفات +مثقفة +مثقفي +مثقفين +مثقلات +مثقلاً +مثقلة +مثل +مثلا +مثلاً +مثلت +مثلث +مثلثة +مثلجة +مثلك +مثلكم +مثلكِ +مثلما +مثلنا +مثله +مثلها +مثلهم +مثلهن +مثلوا +مثلومة +مثلي +مثلُ +مثمر +مثمراً +مثمرة +مثمّن +مثنويته +مثنى +مثواه +مثوى +مثير +مثيرا +مثيرات +مثيراً +مثيرة +مثيرًا +مثيل +مثيلا +مثيلاتها +مثيلاً +مثيلتها +مثيله +مثَل +مثّل +مثّلت +مثَّل +مثَّلت +مج +مجار +مجاراة +مجازا +مجازر +مجازي +مجازيا +مجازياً +مجازية +مجازين +مجاعة +مجال +مجالا +مجالات +مجالاتها +مجالاتهما +مجالاً +مجالس +مجالسة +مجالسه +مجالسهم +مجالنا +مجاله +مجالها +مجالي +مجامع +مجاملاً +مجاملة +مجاملته +مجاميع +مجانا +مجاناً +مجاني +مجانيا +مجانياً +مجانية +مجاهد +مجاهدا +مجاورة +مجايليه +مجبرة +مجبرون +مجبرين +مجبورا +مجبوراً +مجبولاً +مجبولون +مجتاحة +مجترحا +مجتماعاتهم +مجتمع +مجتمعا +مجتمعات +مجتمعاتنا +مجتمعاتها +مجتمعاتهم +مجتمعاً +مجتمعة +مجتمعنا +مجتمعه +مجتمعها +مجتمعهم +مجتمعية +مجتمعين +مجتمعيًّا +مجتهدًا +مجثمه +مجج +مجحف +مجد +مجدب +مجدد +مجددا +مجدداً +مجددة +مجددي +مجدنا +مجده +مجدها +مجدو +مجدولة +مجدي +مجدية +مجدّدة +مجرات +مجراه +مجرب +مجرة +مجرتنا +مجرد +مجردة +مجردين +مجرم +مجرمين +مجروحين +مجرى +مجريات +مجرّد +مجرَّما +مجزأ +مجزرة +مجزياً +مجزية +مجزّأ +مجزَّأ +مجسات +مجسمات +مجسمة +مجسّاتها +مجسّداً +مجفف +مجلات +مجلة +مجلتا +مجلتنا +مجلته +مجلتي +مجلتين +مجلد +مجلدا +مجلدات +مجلداته +مجلدان +مجلده +مجلدين +مجلدٍ +مجلس +مجلسان +مجلساً +مجلسه +مجلسها +مجلياً +مجلّة +مجلّتها +مجمع +مجمعات +مجمعاتها +مجمعاً +مجمعة +مجمعها +مجمل +مجملة +مجملها +مجموع +مجموعات +مجموعاته +مجموعاتهم +مجموعاتي +مجموعة +مجموعتك +مجموعتكم +مجموعته +مجموعتها +مجموعتي +مجموعتين +مجموعه +مجموعها +مجموعهما +مجمّداً +مجمَّداً +مجنزرة +مجنون +مجنونة +مجني +مجهداً +مجهدة +مجهري +مجهرية +مجهزا +مجهزة +مجهود +مجهودات +مجهوداً +مجهول +مجهولا +مجهولاً +مجهولة +مجهوله +مجهولون +مجوهرات +مجوهراتها +مجوَّفة +مجيء +مجيئك +مجيئه +مجيئهم +مجيئي +مجيب +مجيباً +مجيد +مجيدا +مجيداً +مجيدي +مجيلس +مجّاناً +مح +محابر +محاذرا +محاذية +محاذير +محاذيًا +محارب +محاربا +محارباً +محاربة +محاربته +محاسب +محاسن +محاسنه +محاسنها +محاصر +محاصرا +محاصرة +محاصرًا +محاصيل +محاصيلنا +محاصيلهم +محاضر +محاضرا +محاضرات +محاضراته +محاضراً +محاضرة +محاضرته +محاضرتي +محاضرتين +محاضرًا +محاط +محاطا +محاطاً +محاطة +محافظ +محافظات +محافظاً +محافظة +محافظته +محافظتها +محافظًا +محافل +محاكاة +محاكم +محاكمة +محاكمته +محاكمتهم +محال +محالة +محاليل +محاميا +محامياً +محاه +محاور +محاورة +محاوره +محاولا +محاولات +محاولاتنا +محاولاته +محاولاتها +محاولاتهم +محاولاً +محاولة +محاولته +محاولتهم +محاولين +محايدا +محايداً +محايدة +محايدين +محب +محبا +محباً +محبب +محببة +محبة +محبت +محبتي +محبذ +محبطا +محبو +محبوبة +محبوسا +محبوسة +محبي +محبًا +محبّة +محبّةً +محبًّا +محت +محتاج +محتاجا +محتاجاً +محتاجين +محتار +محتاراً +محتال +محتجا +محتجباً +محتجة +محتدم +محتدمة +محترف +محترفا +محترفون +محترفين +محترم +محترما +محترمة +محتشد +محتشمة +محتفظا +محتفظاً +محتفظة +محتقرتان +محتلا +محتلة +محتلين +محتمل +محتملا +محتملة +محتواها +محتومة +محتوى +محتويات +محتوياتها +محجا +محجر +محجريهما +محجوب +محجوبة +محجوزة +محد +محدبة +محدث +محدثا +محدثاً +محدثة +محدثتي +محدثنا +محدثه +محدثي +محدد +محددا +محددات +محدداً +محددة +محددون +محدود +محدودا +محدوداً +محدودبة +محدودة +محدودي +محدودية +محدّثي +محدّد +محدّداً +محذرا +محذراً +محذِّرة +محراب +محرجاً +محرر +محررا +محررات +محرراً +محررة +محرز +محرضا +محرضة +محرفة +محرقة +محرك +محركات +محركاتها +محركاً +محركة +محركين +محرم +محرمة +محروثة +محروقة +محروم +محروما +محروماً +محرومين +محرّضة +محرّك +محرّكات +محرّكة +محرّكها +محزن +محزنا +محسسة +محسن +محسوب +محسوباً +محسوبة +محسود +محسوس +محسوسا +محسوسة +محسّنة +محصلة +محصلي +محصنة +محصور +محصورا +محصوراً +محصورة +محصول +محصولاً +محصولها +محصولي +محصّلة +محصّن +محض +محضراً +محضره +محضن +محط +محطات +محطاتنا +محطاً +محطة +محطتان +محطتنا +محطته +محطتي +محظور +محظورا +محظورات +محظورة +محظوظاً +محظوظة +محـافظة +محـترفى +محـطة +محـققة +محـل +محـلياً +محفزا +محفزة +محفل +محفور +محفورة +محفوظ +محفوظة +محفوفًا +محقة +محقق +محققا +محققاً +محققة +محققي +محقن +محقين +محك +محكم +محكما +محكمة +محكوما +محكومة +محكومون +محل +محلا +محلات +محلاً +محلة +محلقا +محلقاً +محلقة +محلل +محللا +محللاً +محللون +محله +محلها +محلول +محلي +محليا +محلياً +محلية +محليين +محليًا +محليًّا +محلّ +محلّف +محلّق +محلَّ +محمد +محمدأبو +محمدا +محمدجمال +محمدراسم +محمدصادق +محمل +محملا +محملاً +محملة +محملقة +محمود +محمودة +محمول +محمولة +محموم +محموما +محمومة +محمي +محميات +محمية +محمّلاً +محمّلة +محنة +محنته +محنتي +محنطاً +محو +محوا +محواً +محور +محورا +محوري +محورية +محوه +محوها +محوَّرَة +محير +محيرة +محيط +محيطا +محيطاً +محيطنا +محيطه +محيطها +محيلين +محيي +محييا +محيّر +مخ +مخادع +مخارج +مخارجها +مخازن +مخاض +مخاط +مخاطبا +مخاطباً +مخاطبة +مخاطبتهم +مخاطر +مخاطرة +مخاطره +مخاطرها +مخاطية +مخافة +مخالب +مخالبه +مخالبها +مخالطة +مخالف +مخالفا +مخالفة +مخاوف +مخاوفك +مخاوفه +مخاوفهم +مخاوفي +مخبأ +مخبأة +مخبئها +مخبئهما +مخبره +مخبريا +مخبرية +مختار +مختارا +مختارات +مختاراً +مختارة +مختال +مختبئة +مختبر +مختبرا +مختبرات +مختبراً +مختبره +مختبَرَية +مختتم +مخترع +مخترقا +مخترقة +مخترقي +مخترقين +مختصا +مختصة +مختصر +مختصرا +مختصرة +مختصون +مختصين +مختصًا +مختف +مختفية +مختلط +مختلطة +مختلف +مختلفا +مختلفان +مختلفاً +مختلفة +مختلفتين +مختلفون +مختلفين +مختلفًا +مختلقا +مختومة +مخجلة +مخدر +مخدرا +مخدرات +مخدرة +مخدوما +مخرب +مخرج +مخرجا +مخرجات +مخرجاً +مخرجة +مخرجًا +مخرز +مخرشة +مخروطي +مخروطيا +مخروطية +مخزن +مخزوم +مخزون +مخزونات +مخزونه +مخزونها +مخزوني +مخزي +مخصبة +مخصص +مخصصة +مخصصتين +مخصِّباتٍ +مخضرة +مخطئا +مخطئاً +مخطئة +مخطط +مخططات +مخططة +مخطوط +مخطوطا +مخطوطات +مخطوطاته +مخطوطاتها +مخطوطة +مخطوطتي +مخطوطي +مخطّط +مخفض +مخفضة +مخفف +مخففة +مخفًّفًا +مخفَّفًا +مخلب +مخلة +مخلص +مخلصا +مخلصة +مخلصنا +مخلصون +مخلفا +مخلفات +مخلفاتها +مخلوق +مخلوقات +مخلوقاته +مخلوقاً +مخلوقة +مخلوقته +مخلوقين +مخلَّفات +مخمشات +مخملباف +مخموج +مخموجات +مخموس +مخولين +مخيف +مخيفاً +مخيفة +مخيفًا +مخيلة +مخيلتك +مخيلتنا +مخيلتها +مخيلتي +مخيم +مخيمات +مخيماً +مخيَّلتهم +مد +مدائن +مدائنهم +مداح +مداخل +مداخلا +مداخلات +مداخلة +مداخله +مداخلها +مداخن +مداخيل +مداد +مداده +مدار +مداراة +مدارات +مدارالعام +مدارج +مدارس +مدارسنا +مدارسه +مدارسها +مدارسهم +مدارك +مداري +مداعبا +مداعباتي +مداعبة +مدافع +مدافعا +مدافعاً +مدافعة +مدافعه +مدافعًا +مدافن +مدام +مدان +مدانا +مدانين +مداه +مداها +مداهماته +مداواة +مداواتها +مداوٍ +مدببة +مدبرا +مدبرة +مدبلجا +مدبّرة +مدة +مدت +مدته +مدتها +مدجنين +مدجّنين +مدح +مدحه +مدحوا +مدحورة +مدخر +مدخراته +مدخل +مدخلا +مدخلاً +مدخلنا +مدخله +مدخنا +مدخنين +مدد +مددت +مدر +مدراء +مدرب +مدربه +مدربين +مدرج +مدرجات +مدرس +مدرسا +مدرساً +مدرسة +مدرسةً +مدرسته +مدرستها +مدرستي +مدرستين +مدرسوها +مدرسي +مدرسيا +مدرسياً +مدرسية +مدرسين +مدرسيها +مدرسيّ +مدرسًا +مدركا +مدركة +مدركين +مدروس +مدروسا +مدروساً +مدروسة +مدريد +مدرّج +مدرّساً +مدشنا +مدعاة +مدعم +مدعمة +مدعو +مدعواً +مدعوماً +مدعومة +مدعوين +مدفأة +مدفعا +مدفنه +مدفوعا +مدفوعة +مدفونة +مدقع +مدقعًا +مدقِّقاً +مدكور +مدلول +مدلولات +مدلولاته +مدمج +مدمجة +مدمر +مدمرة +مدمس +مدمني +مدموجة +مدمّراً +مدمّرة +مدن +مدناً +مدننا +مدنه +مدنها +مدني +مدنية +مدنيًّا +مدها +مدهش +مدهشا +مدهشة +مدور +مدورة +مدونات +مدويا +مدوّر +مدى +مدي +مديح +مديد +مديدة +مدير +مديرا +مديراً +مديرة +مديره +مديرو +مديرون +مديري +مديرية +مديع +مدين +مدينا +مدينة +مدينتان +مدينتك +مدينتكم +مدينتكن +مدينتنا +مدينته +مدينتهم +مدينتى +مدينتي +مدينتين +مدينـة +مدّ +مدّة +مدّت +مدَّت +مذ +مذاب +مذابح +مذاق +مذاهب +مذاهبهم +مذبحة +مذركير +مذعنة +مذعورات +مذعورة +مذعورًا +مذكرات +مذكراته +مذكراتها +مذكراتي +مذكرة +مذكور +مذلة +مذنب +مذهب +مذهبا +مذهبة +مذهبه +مذهبي +مذهبية +مذهبين +مذهل +مذهلا +مذهلاً +مذهلة +مذهولا +مذهولة +مذهّبة +مذيع +مذيعا +مذيعاً +مذيعة +مر +مرآباً +مرآة +مرآتك +مرأى +مرئي +مرئياتكم +مرئية +مرابحة +مرابط +مرابعاً +مرابي +مرات +مراتب +مراتعه +مراجع +مراجعة +مراجعتها +مراجعه +مراجعي +مراحل +مراحله +مراحلها +مراحيض +مراد +مرادفا +مرادفاتها +مرادفة +مرارا +مراراً +مرارة +مرارته +مرارًا +مراسل +مراسلا +مراسلات +مراسلة +مراسلها +مراسم +مراسيل +مراسيم +مراصد +مراع +مراعاة +مراعاتها +مراعاتهم +مراعيا +مراعيه +مراعيها +مرافئ +مرافئها +مرافئهم +مرافعاتهم +مرافق +مرافقا +مرافقة +مرافقتها +مرافقتي +مرافقنا +مرافقي +مرافقينا +مراقب +مراقبة +مراقص +مراكز +مراكش +مراكمتها +مراهقاً +مراهقة +مراهقتي +مراهقين +مراهم +مراوح +مرايا +مرايانا +مربحة +مربط +مربع +مربعا +مربعات +مربعاً +مربعة +مربعين +مربعًا +مربوط +مربوطاً +مربوع +مربى +مربي +مربية +مربّي +مربَّع +مرة +مرةً +مرت +مرتاح +مرتاحة +مرتاحين +مرتادى +مرتادي +مرتان +مرتب +مرتبا +مرتبة +مرتبط +مرتبطا +مرتبطان +مرتبطاً +مرتبطة +مرتبطًا +مرتبكا +مرتبكاً +مرتبكة +مرتبنا +مرتبي +مرتجفا +مرتد +مرتدين +مرتديه +مرتدًّا +مرتزق +مرتزقة +مرتشو +مرتع +مرتعا +مرتعاً +مرتعش +مرتعشة +مرتعشين +مرتفع +مرتفعات +مرتفعة +مرتكبي +مرتكبيه +مرتكزات +مرتكزاً +مرتكزة +مرتل +مرتهنة +مرتين +مرتّب +مرثية +مرج +مرجاني +مرجانية +مرجع +مرجعا +مرجعاً +مرجعنا +مرجعه +مرجعها +مرجعياته +مرجعية +مرجعيته +مرجليوث +مرجو +مرجواً +مرح +مرحا +مرحاض +مرحاضاً +مرحب +مرحبا +مرحبة +مرحة +مرحلة +مرحلةً +مرحلته +مرحلتها +مرحلتين +مرحليا +مرحى +مرحّبا +مرخصة +مردان +مردخاي +مرددا +مرددة +مرده +مردود +مردودان +مردوداً +مردوده +مردودها +مرذولون +مررت +مررنا +مرزا +مرزوق +مرساة +مرساته +مرسلة +مرسم +مرسما +مرسمك +مرسمه +مرسمي +مرسوم +مرسوما +مرسى +مرسي +مرسين +مرشح +مرشحا +مرشحاً +مرشحة +مرشد +مرصد +مرصعا +مرصعة +مرض +مرضا +مرضات +مرضانا +مرضاه +مرضاً +مرضت +مرضك +مرضه +مرضى +مرضي +مرضياً +مرضية +مرضٌ +مرطبة +مرعاه +مرعب +مرعبا +مرعباً +مرعبة +مرعى +مرعيّة +مرفأ +مرفق +مرفقا +مرفقة +مرفقه +مرفقًا +مرفوض +مرفوضة +مرفوع +مرفوعة +مرقة +مرقدها +مرقص +مرقعة +مركب +مركبا +مركبات +مركبة +مركبنا +مركز +مركزا +مركزاً +مركزبحث +مركزة +مركزنا +مركزه +مركزها +مركزي +مركزيا +مركزية +مركزين +مركزًا +مركونة +مركّب +مركّبات +مركّبنا +مركّزاً +مركَّبات +مرموز +مرموق +مرموقا +مرموقاً +مرموقة +مرموقون +مرموقين +مرميا +مرنة +مرنقة +مره +مرهف +مرهفة +مرهفين +مرهقاَ +مرهقة +مرهونة +مروا +مروان +مروة +مروجاً +مروحة +مروحيات +مروحية +مرور +مرورا +مروراً +مروره +مروري +مرورًا +مروض +مروضا +مروع +مرونة +مروية +مرويته +مروّة +مريانا +مريبة +مريح +مريحا +مريحان +مريحة +مريدين +مريديه +مريدًا +مريرا +مريرة +مريض +مريضا +مريضة +مريضه +مريضها +مريضين +مريم +مرين +مرّ +مرّاً +مرّة +مرّت +مرٍّ +مرَّ +مرَّة +مرَّةً +مزاج +مزاجك +مزاجه +مزاجي +مزاحمة +مزاحمتها +مزاد +مزادات +مزار +مزارا +مزاراً +مزارع +مزارعة +مزارعها +مزارعين +مزاعمه +مزالق +مزامير +مزاولة +مزايا +مزاياها +مزاياهن +مزايدات +مزج +مزجا +مزجت +مزجه +مزجهم +مزدانة +مزدحم +مزدحماً +مزدحمة +مزدهر +مزدهرة +مزدهرًا +مزدوج +مزدوجاً +مزدوجة +مزر +مزرعة +مزرعته +مزروعاتنا +مزروعة +مزريا +مزعجا +مزعجة +مزعجًا +مزقت +مزقتا +مزقها +مزلجتين +مزماره +مزمن +مزمنة +مزمومة +مزهر +مزهوا +مزود +مزودة +مزوّد +مزوّري +مزية +مزيج +مزيجا +مزيجاً +مزيد +مزيدا +مزيداً +مزيف +مزيفا +مزيفة +مزين +مزينة +مزيّفة +مزيّنة +مزّاحا +مزّقت +مزَّقت +مس +مسألة +مسؤلوا +مسؤول +مسؤولا +مسؤولة +مسؤولو +مسؤولون +مسؤولى +مسؤولي +مسؤوليات +مسؤولياتها +مسؤولية +مسؤوليتنا +مسؤولين +مسئول +مسئولا +مسئولاً +مسئولة +مسئولو +مسئولون +مسئولى +مسئولي +مسئوليات +مسئولياته +مسئولياتها +مسئولياتهم +مسئولية +مسئوليته +مسئوليتها +مسئوليتهما +مسئولين +مسئوليها +مسا +مساء +مساءلة +مساءً +مسائل +مسائلة +مسابح +مسابقات +مسابقاتها +مسابقة +مسابقتها +مساج +مساجد +مساجدهم +مساحات +مساحاتها +مساحة +مساحته +مساحتها +مساحـتها +مسار +مسارا +مسارات +مسارب +مسارح +مسارك +مساره +مسارها +مسارهم +مساس +مساعد +مساعدا +مساعدات +مساعداً +مساعدة +مساعدتك +مساعدته +مساعديه +مساعدًا +مساعي +مساعيه +مساعيها +مسافات +مسافة +مسافته +مسافر +مسافرا +مسافراً +مسافرين +مساكن +مساكنهم +مسالك +مسالم +مسالمًا +مسامرات +مسامراتنا +مسامعنا +مسامعه +مسامعهم +مسامي +مسامير +مساند +مساندة +مساندته +مساهمات +مساهمان +مساهمة +مساهمتنا +مساهمتها +مساهمـة +مساهمين +مساهميها +مساوئه +مساوئها +مساواة +مساواتها +مساوية +مسبار +مسبارًا +مسبب +مسببات +مسبباته +مسببة +مسبح +مسبحة +مسبق +مسبقا +مسبقاً +مسبقة +مسبقًا +مسبوق +مسبوقا +مسبوقة +مستأجر +مستباحة +مستجدات +مستجيبا +مستحب +مستحدث +مستحضراً +مستحق +مستحقاته +مستحقاتهم +مستحقيها +مستحيل +مستحيلاً +مستحيلة +مستخدم +مستخدما +مستخدماً +مستخدمة +مستخدمو +مستخدمي +مستخدمين +مستخلص +مستخلصة +مستخلفًا +مستدرجا +مستدركا +مستديرة +مستذكرا +مستر +مسترخيا +مسترسلاً +مسترشدين +مستريحة +مستسلما +مستسلمة +مستسلمين +مستشار +مستشارا +مستشاراً +مستشارة +مستشاري +مستشارية +مستشاريه +مستشارًا +مستشرق +مستشرقة +مستشفى +مستشفي +مستشفيات +مستصعبات +مستصعباً +مستصعبة +مستطردا +مستطلعا +مستطلعة +مستطيل +مستطيلة +مستعار +مستعد +مستعدا +مستعداً +مستعدة +مستعدون +مستعدين +مستعرب +مستعرباً +مستعربينا +مستعرضا +مستعرضين +مستعصية +مستعظماً +مستعمر +مستعمرات +مستعمراتها +مستعمرة +مستعمرو +مستعمري +مستعمرينا +مستعملة +مستعيداً +مستعينا +مستعيناً +مستعينين +مستفادة +مستفهمة +مستفيدا +مستفيدة +مستفيدين +مستفيضة +مستقاة +مستقبل +مستقبلا +مستقبلات +مستقبلاً +مستقبلة +مستقبلنا +مستقبله +مستقبلهم +مستقبلى +مستقبلي +مستقبلياً +مستقبلية +مستقبليهم +مستقر +مستقرة +مستقرها +مستقرّة +مستقرَّاً +مستقل +مستقلا +مستقلاً +مستقلة +مستقلتان +مستقلتين +مستقيم +مستقيما +مستقيماً +مستقيمة +مستقيمي +مستكشفاً +مستلبون +مستلزمات +مستلزماتها +مستلق +مستلقيا +مستلقٍ +مستلهماً +مستلهمة +مستلّة +مستمتعا +مستمد +مستمدة +مستمر +مستمرا +مستمراً +مستمرة +مستمرين +مستمرّة +مستمسكا +مستمع +مستمعا +مستمعاً +مستمعين +مستند +مستندا +مستندة +مستنسخ +مستنقع +مستنقعات +مستنير +مستهدف +مستهدفا +مستهدفاً +مستهدفة +مستهل +مستهلكة +مستهلكون +مستهلكي +مستهلكين +مستهلكيه +مستو +مستوا +مستواك +مستواها +مستوحاة +مستوحدين +مستودع +مستودعات +مستودعاً +مستور +مستورد +مستوردة +مستوطن +مستوطنة +مستوطنون +مستوفزا +مستوفى +مستوى +مستوي +مستويات +مستوياته +مستوياتها +مستوياتهن +مستوية +مستيقظ +مسجد +مسجدا +مسجداً +مسجده +مسجدي +مسجدًا +مسجل +مسجلا +مسجلاً +مسجلة +مسجلون +مسجلين +مسجور +مسجونين +مسجى +مسجّى +مسح +مسحا +مسحة +مسحت +مسحتنا +مسحها +مسحورة +مسحوق +مسحى +مسحَ +مسخ +مسخاً +مسخناً +مسخها +مسخّرا +مسدس +مسدود +مسراي +مسرج +مسرح +مسرحا +مسرحاً +مسرحنا +مسرحه +مسرحي +مسرحيا +مسرحيات +مسرحياته +مسرحياتي +مسرحياً +مسرحية +مسرحيتك +مسرحيته +مسرحيتي +مسرحيين +مسرحًا +مسرطن +مسرطنة +مسرطِنة +مسرعا +مسرعاً +مسرعة +مسرورة +مسروق +مسروقات +مسروقة +مسز +مسطح +مسطحا +مسطحات +مسطحها +مسطرة +مسطوح +مسعاه +مسعود +مسعورا +مسعورة +مسقط +مسقوف +مسقوفة +مسك +مسكر +مسكن +مسكناً +مسكنه +مسكني +مسكوبا +مسكون +مسكونا +مسكوناً +مسكونة +مسكين +مسكينة +مسلاتة +مسلة +مسلح +مسلحة +مسلحين +مسلسل +مسلسلات +مسلك +مسلم +مسلما +مسلماً +مسلمة +مسلمتين +مسلمهم +مسلمو +مسلمون +مسلمى +مسلمي +مسلمين +مسلميْن +مسلمًا +مسلوب +مسلوخ +مسلية +مسماة +مسمعه +مسمعي +مسموح +مسموحاً +مسموع +مسموعة +مسموعي +مسمى +مسمي +مسمياته +مسمّياته +مسن +مسنة +مسنودة +مسنّ +مسها +مسهبة +مسهما +مسوح +مسوحات +مسوخ +مسودات +مسورة +مسوَّدةُ +مسيح +مسيحي +مسيحيا +مسيحية +مسيرة +مسيرتا +مسيرته +مسيرتها +مسيرتي +مسيره +مسيطر +مسيطرا +مسيطرة +مسيَّجة +مش +مشئوم +مشا +مشابه +مشابهة +مشابهًا +مشاة +مشاجرة +مشادة +مشاربهم +مشارف +مشارك +مشاركا +مشاركات +مشاركاته +مشاركاتها +مشاركاً +مشاركة +مشاركته +مشاركتها +مشاركتهم +مشاركتي +مشاركين +مشاري +مشاريع +مشاريعه +مشاريعها +مشاريعي +مشاط +مشاعا +مشاعر +مشاعرنا +مشاعره +مشاعرهم +مشاعرى +مشاعري +مشاعًا +مشافهة +مشافي +مشاق +مشاكساته +مشاكل +مشاكلنا +مشاكله +مشاكلهم +مشاكلهن +مشاكلي +مشاهد +مشاهدات +مشاهداته +مشاهداتي +مشاهدة +مشاهدته +مشاهدتها +مشاهدتهم +مشاهدتي +مشاهده +مشاهدها +مشاهدو +مشاهدي +مشاهدين +مشاهديه +مشاهير +مشاوير +مشايخ +مشبعة +مشبعه +مشبوه +مشبوهة +مشت +مشتراة +مشترك +مشتركا +مشتركاً +مشتركة +مشترواتهم +مشتريات +مشترياتها +مشترياتهم +مشترياتهما +مشتعلاً +مشتعلة +مشتق +مشتقات +مشتقاته +مشتقة +مشتقةٌ +مشتلا +مشتهاة +مشتى +مشتّت +مشجر +مشجرات +مشجع +مشجعة +مشجعين +مشجّرات +مشحوناً +مشحونة +مشد +مشددا +مشددة +مشدودا +مشدوداً +مشدودة +مشدوها +مشرئبة +مشربة +مشربيات +مشرط +مشرع +مشرعة +مشرف +مشرفاً +مشرفة +مشرق +مشرقا +مشرقاً +مشرقة +مشرقية +مشركاً +مشروب +مشروباً +مشروح +مشروحة +مشروط +مشروطة +مشروع +مشروعا +مشروعات +مشروعاته +مشروعاتها +مشروعاتي +مشروعاً +مشروعة +مشروعنا +مشروعه +مشروعها +مشروعهم +مشروعي +مشروعية +مشروعيتها +مشروعًا +مشرّفة +مشط +مشع +مشعة +مشعل +مشعّ +مشـتاق +مشفقة +مشفى +مشقة +مشقةً +مشككا +مشكلات +مشكلاتنا +مشكلاته +مشكلاتهم +مشكلاً +مشكلة +مشكلتان +مشكلتك +مشكلتنا +مشكلته +مشكلتها +مشكور +مشكورا +مشكوراً +مشكورة +مشكوك +مشكيني +مشلولا +مشمس +مشمولة +مشهد +مشهدا +مشهدية +مشهود +مشهودا +مشهودة +مشهور +مشهورا +مشهورة +مشهورًا +مشوار +مشوارك +مشوارنا +مشواره +مشورة +مشوه +مشوهة +مشوية +مشوّه +مشوّهة +مشى +مشياً +مشيته +مشيتها +مشيرا +مشيراً +مشيرة +مشينا +مشيّأة +مشيّدة +مص +مصائب +مصائبنا +مصائد +مصائر +مصائرهم +مصاب +مصابا +مصابات +مصاباً +مصابة +مصابتين +مصابها +مصابون +مصابيح +مصابين +مصابًا +مصاحب +مصاحبا +مصاحبة +مصادر +مصادرة +مصادره +مصادرها +مصادفة +مصادمات +مصارعة +مصارعين +مصارف +مصاريعها +مصاريف +مصاطب +مصاعد +مصاف +مصافِ +مصالح +مصالحة +مصالحنا +مصالحها +مصالحهم +مصانع +مصانعها +مصايد +مصايف +مصب +مصبات +مصباح +مصباحا +مصبه +مصبًا +مصبّ +مصبّها +مصححا +مصححًا +مصحف +مصحفا +مصحفك +مصحفه +مصحفًا +مصحوب +مصحوباً +مصحوبة +مصحوبٌ +مصدات +مصداق +مصداقية +مصداقيتها +مصدر +مصدرا +مصدران +مصدراً +مصدره +مصدرها +مصدرى +مصدرية +مصدرين +مصدرًا +مصدق +مصدقة +مصر +مصرا +مصراته +مصراعيه +مصراعيها +مصرع +مصرف +مصرفي +مصروف +مصروفات +مصروفاتها +مصروفك +مصروفه +مصروفهم +مصروفي +مصري +مصريا +مصرية +مصريون +مصريين +مصريّة +مصطبة +مصطدمة +مصطفى +مصطفي +مصطلح +مصطلحات +مصطلحاتها +مصطلحين +مصطنعاً +مصعد +مصفاة +مصفد +مصفرًا +مصفف +مصفقة +مصفوع +مصفوفات +مصل +مصلاه +مصلحة +مصلحتك +مصلحتنا +مصلحته +مصلحتها +مصلحتهم +مصلحية +مصلحين +مصلى +مصلي +مصلّح +مصمت +مصمد +مصمم +مصمما +مصممة +مصممه +مصممو +مصممين +مصمّد +مصنع +مصنعا +مصنعاً +مصنعة +مصنعها +مصنعي +مصنعيها +مصنف +مصنفات +مصنفه +مصنفي +مصنوع +مصنوعا +مصنوعة +مصهورا +مصور +مصورا +مصوراً +مصورة +مصوره +مصورين +مصوَّبًا +مصيب +مصيبة +مصيدة +مصير +مصيرا +مصيراً +مصيرنا +مصيره +مصيرها +مصيرية +مضاءة +مضاءه +مضائق +مضاجع +مضاد +مضادا +مضادات +مضادة +مضادين +مضارباً +مضاربة +مضاعة +مضاعفا +مضاعفات +مضاعفاته +مضاعفاتها +مضاعفاً +مضاعفة +مضافا +مضافة +مضامير +مضامين +مضامينها +مضايقات +مضايقة +مضبوطة +مضت +مضجعا +مضجعه +مضحك +مضحكة +مضخات +مضخة +مضر +مضرة +مضرجاً +مضروبة +مضرّاً +مضض +مضطجع +مضطر +مضطراً +مضطربة +مضطرة +مضطرين +مضطهد +مضــــيئة +مضللاً +مضمار +مضمون +مضموناً +مضمونة +مضمونه +مضمونها +مضن +مضنية +مضنٍ +مضوا +مضى +مضي +مضيء +مضيئا +مضيئة +مضياف +مضيافة +مضيت +مضيفا +مضيفنا +مضيفيه +مضيق +مضينا +مطابخ +مطابخنا +مطابع +مطابقا +مطابقة +مطاحن +مطار +مطارات +مطاراتها +مطاراً +مطارد +مطاردة +مطاردته +مطاردولي +مطاردين +مطارديه +مطاردًا +مطارق +مطارها +مطاطية +مطاع +مطاعم +مطالب +مطالبا +مطالبة +مطالبتهم +مطالبهم +مطالبون +مطالبين +مطالعة +مطالعةِ +مطامح +مطامحك +مطامحهم +مطامع +مطامعهم +مطاوع +مطبخ +مطبعة +مطبعية +مطبق +مطبقا +مطبقاً +مطبوع +مطبوعا +مطبوعة +مطحنة +مطحونة +مطر +مطران +مطرانا +مطرب +مطربات +مطربة +مطربنا +مطربي +مطرح +مطرحو +مطرد +مطرداً +مطردة +مطرز +مطرزة +مطرقة +مطروحا +مطروحاً +مطروحة +مطروقة +مطرية +مطعم +مطعماً +مطعمنا +مطفأة +مطلب +مطلبا +مطلبنا +مطلبه +مطلبهم +مطلع +مطلعا +مطلعه +مطلعها +مطلق +مطلقا +مطلقات +مطلقاً +مطلقة +مطلقته +مطلقًا +مطلك +مطلوب +مطلوبا +مطلوباً +مطلوبة +مطلي +مطمئن +مطمئنا +مطمئناً +مطمئنة +مطمئنين +مطمئنًا +مطمع +مطموسة +مطواعتين +مطورة +مطوري +مطول +مطولا +مطولة +مطوّلا +مطوّلاً +مطية +مطير +مطيرة +مطّرداً +مطّردة +مظاريف +مظالمنا +مظانها +مظاهر +مظاهرات +مظاهرة +مظاهره +مظاهرها +مظفرة +مظلة +مظلته +مظللة +مظلمة +مظلومة +مظهر +مظهرا +مظهراً +مظهره +مظهرها +مع +معا +معابد +معابدهم +معابر +معاداة +معادل +معادلا +معادلات +معادلاتهم +معادلة +معادلتي +معادلها +معادن +معادها +معادية +معادٍ +معارض +معارضا +معارضة +معارضته +معارضتهم +معارضه +معارضها +معارضوه +معارضي +معارضيه +معارضيها +معارف +معارفه +معارفها +معارك +معاركنا +معاريف +معاشها +معاصر +معاصرا +معاصراً +معاصرة +معاصريك +معاصريه +معاصرًا +معاطف +معافى +معاقل +معاك +معاكس +معاكساً +معاكسة +معالجات +معالجاته +معالجة +معالجته +معالجتها +معالجتهم +معالم +معالمنا +معالمه +معالمها +معالي +معامل +معاملات +معاملاتهم +معاملة +معاملتك +معاملتها +معاملها +معان +معانا +معاناة +معاناته +معاناتهن +معاناتي +معاند +معانقاً +معانقًا +معاني +معانيه +معانيها +معاه +معاهد +معاهدة +معاهم +معاودة +معاودتها +معاونته +معاوية +معايشة +معاينة +معايير +معاييرنا +معاييرها +معاً +معبد +معبداً +معبر +معبراً +معبراَ +معبرة +معبور +معبّأة +معبّر +معتادا +معتاداً +معتادة +معتادون +معتادًا +معتاشا +معتبرا +معتبرة +معتبرين +معتبرًا +معتدا +معتدل +معتدلة +معتذراً +معترضة +معترف +معترفا +معترفاً +معترفًا +معترك +معتز +معتزة +معتصم +معتصماً +معتفس +معتق +معتقد +معتقدات +معتقداتنا +معتقداتهم +معتقداً +معتقلات +معتقلاته +معتم +معتمة +معتمدا +معتمداً +معتمدة +معتمدين +معتمدًا +معتمر +معتنى +معجب +معجبا +معجباً +معجبون +معجزة +معجزته +معجل +معجم +معجمي +معجون +معجونة +معد +معدات +معدة +معدتك +معدل +معدلات +معدلاتها +معدلة +معدن +معدني +معدنية +معدودا +معدودات +معدودة +معدومة +معدي +معدية +معدّ +معدّل +معدّلات +معدّلة +معدَّلة +معذبا +معذبة +معذرة +معذّب +معراجا +معربا +معرشة +معرض +معرضا +معرضاً +معرضه +معرضون +معرضي +معرضين +معرضًا +معرفاً +معرفة +معرفتنا +معرفته +معرفتهم +معرفتي +معرفي +معرفيا +معرفياً +معرفية +معركة +معركته +معركتها +معركتهم +معروض +معروضة +معروف +معروفا +معروفاً +معروفة +معروفي +معروفين +معروفًا +معروق +معرّض +معرّضاً +معرّضة +معرّضون +معز +معزوفة +معزوفته +معزولا +معزولاً +معزولة +معزولين +معسكر +معسكرات +معسكراتهم +معسكرين +معشبة +معشر +معشوقته +معصرة +معصوبة +معصوماً +معصية +معصيته +معصيتهم +معضلة +معط +معطاء +معطاة +معطلاً +معطلة +معطوب +معطى +معطيات +معطياته +معطياتها +معطيً +معظم +معظمنا +معظمه +معظمها +معظمهم +معظمُ +معـاني +معقد +معقدة +معقدون +معقـول +معقلا +معقلين +معقودة +معقودٍ +معقول +معقولا +معقولاً +معقولة +معقوليتها +معقّدة +معك +معكسراتهم +معكم +معكوسة +معكِ +معلبا +معلبات +معلبة +معلق +معلقات +معلقاً +معلقة +معلقًا +معللا +معللين +معلم +معلما +معلماً +معلمة +معلمهم +معلموكم +معلمي +معلمين +معلميه +معلمًا +معلن +معلنا +معلنة +معلوف +معلوفية +معلوم +معلومات +معلوماتنا +معلوماته +معلوماتها +معلوماتهم +معلوماتي +معلوماتية +معلومة +معلّقا +معلّقاً +معلّمه +معمار +معمارها +معماري +معمارية +معمر +معمعة +معمقة +معمل +معملاً +معمله +معممة +معمّقة +معن +معنا +معناه +معناها +معندة +معنويا +معنوياتهم +معنوياً +معنوية +معنى +معني +معنيا +معنياً +معنية +معنيّة +معه +معها +معهد +معهدا +معهداً +معهدًا +معهم +معهما +معوقا +معوقات +معوقين +معولا +معونات +معونة +معونته +معي +معيار +معيارا +معيباً +معيد +معيداً +معيدًا +معيش +معيشة +معيشته +معيشتها +معيشتهم +معيشية +معيق +معين +معينا +معيناً +معينة +معينه +معينها +معينًا +معيّن +معيّنا +معيّنة +معًا +مـدفوعاً +مـدير +مـــــاذا +مـــنذ +مـن +مفاتنها +مفاتيح +مفاتيحه +مفاتيحها +مفاجآت +مفاجأة +مفاجئ +مفاجئا +مفاجئاً +مفاجئة +مفاجىء +مفاخر +مفاده +مفادها +مفارق +مفارقات +مفارقة +مفارقتها +مفاسد +مفاصل +مفاصله +مفاعل +مفاعلات +مفاهيم +مفاهيمنا +مفاهيمية +مفاوضات +مفتاح +مفتاحاً +مفتاحها +مفتاحي +مفتتح +مفتخراً +مفترضاً +مفترضة +مفترق +مفتش +مفتشي +مفتشيها +مفتعلا +مفتعلة +مفتقد +مفتوح +مفتوحا +مفتوحاً +مفتوحة +مفتوحتين +مفتوحًا +مفتونا +مفتونون +مفتي +مفتيا +مفجعا +مفخرة +مفدى +مفر +مفردات +مفرداته +مفرداتها +مفردة +مفرزات +مفرزة +مفرط +مفرطة +مفرقها +مفروش +مفروشة +مفروضة +مفرّ +مفزعا +مفزعاً +مفزعة +مفزوعا +مفزوعاً +مفسحة +مفسد +مفسدا +مفسدون +مفسر +مفصل +مفصلا +مفصلاً +مفصلة +مفصولا +مفصّل +مفضضة +مفضلاً +مفضلة +مفضلين +مفعم +مفعمة +مفعول +مفعولا +مفعولاً +مفعوله +مفعولها +مفقود +مفقودا +مفقوداً +مفقودة +مفكر +مفكرا +مفكراً +مفكرة +مفكرتي +مفكرو +مفكرون +مفكري +مفكرين +مفكريه +مفندا +مفهرسة +مفهوم +مفهومة +مفهومنا +مفهومه +مفهومها +مفهومهما +مفهومي +مفهومين +مفهومًا +مفوض +مفوضاً +مفوضة +مفوضية +مفوه +مفوهًا +مفيد +مفيدا +مفيداً +مفيدة +مفيدًا +مقابر +مقابرهم +مقابض +مقابل +مقابلات +مقابلة +مقابلته +مقابله +مقابلها +مقاتلات +مقاتلاً +مقاتلين +مقادير +مقار +مقارب +مقاربا +مقاربات +مقارباته +مقاربة +مقاربته +مقاربتها +مقارنة +مقارنةً +مقارنته +مقارنتها +مقارها +مقاريبه +مقاسمة +مقاصة +مقاصد +مقاصده +مقاضاة +مقاطع +مقاطعا +مقاطعات +مقاطعة +مقاطعتي +مقاطعها +مقاعد +مقاعدنا +مقاعده +مقاعدها +مقاعدهم +مقال +مقالا +مقالات +مقالاتكم +مقالاته +مقالاتي +مقالاً +مقالب +مقالبه +مقالبي +مقالة +مقالته +مقالنا +مقاليد +مقام +مقاما +مقامات +مقاماتها +مقامة +مقامه +مقامي +مقاه +مقاهي +مقاهيها +مقاولات +مقاولاً +مقاولي +مقاوماً +مقاومة +مقاومته +مقاومتها +مقايضة +مقايضته +مقاييس +مقاييسه +مقبر +مقبرة +مقبرته +مقبرتي +مقبل +مقبلة +مقبلون +مقبلين +مقبول +مقبولا +مقبولاً +مقبولة +مقتبس +مقتبل +مقتحم +مقتدر +مقتربا +مقترحات +مقترنا +مقترنًا +مقتصر +مقتصرا +مقتضباً +مقتضبة +مقتضى +مقتضيات +مقتطعة +مقتطفات +مقتل +مقتلعا +مقتنع +مقتنعا +مقتنيات +مقتنياته +مقتنياتها +مقتولين +مقدار +مقداراً +مقداره +مقدارها +مقدارهم +مقدر +مقدرة +مقدرتك +مقدرتهم +مقدرتي +مقدس +مقدسا +مقدسات +مقدساته +مقدساً +مقدسة +مقدسي +مقدسيون +مقدسيين +مقدم +مقدما +مقدمات +مقدمة +مقدمته +مقدمتها +مقدمتهم +مقدور +مقدونيا +مقديسي +مقدّرا +مقدّمة +مقدَّم +مقر +مقرأة +مقرا +مقراً +مقربة +مقررا +مقررات +مقررًا +مقرفصا +مقره +مقرها +مقروء +مقروءة +مقرونة +مقرًا +مقسم +مقسمة +مقسوما +مقشرة +مقشوراً +مقص +مقصاً +مقصدا +مقصده +مقصر +مقصرون +مقصود +مقصودا +مقصوداً +مقصور +مقصورا +مقصوراً +مقصورة +مقصورتها +مقصّر +مقضيا +مقطع +مقطعا +مقطعاً +مقطعين +مقطورٌ +مقطوع +مقطوعات +مقعد +مقعدا +مقعداً +مقعدة +مقعده +مقعدها +مقعدي +مقعدية +مقفلة +مقلة +مقلدا +مقلداً +مقلدة +مقلعا +مقلقة +مقلما +مقلوب +مقلوبة +مقلّدا +مقنع +مقنعا +مقنعاً +مقنعة +مقنن +مقننة +مقنَّنة +مقهورا +مقهى +مقود +مقوسة +مقولات +مقولة +مقولته +مقومات +مقوماتنا +مقوماتها +مقوي +مقويات +مقوّسا +مقوّمات +مقوِّمات +مقياس +مقياسا +مقياساً +مقياسها +مقياسًا +مقيتا +مقيد +مقيدة +مقيل +مقيم +مقيما +مقيماً +مقيمة +مقيمي +مقيمين +مقيمًا +مقيّداً +مكائده +مكائن +مكابح +مكابدات +مكاتب +مكاتبها +مكاتبهم +مكاسب +مكاسبها +مكافآت +مكافأة +مكافأته +مكافأتها +مكافئ +مكافئة +مكافحات +مكافحة +مكافحته +مكان +مكانا +مكاناً +مكانة +مكانته +مكانتها +مكانتهم +مكانك +مكانه +مكانها +مكانهم +مكاني +مكانًا +مكانَهُ +مكاوي +مكبا +مكبرات +مكبوتا +مكبوتة +مكبّلين +مكبَّلة +مكة +مكتئب +مكتئباً +مكتب +مكتبا +مكتبات +مكتباتنا +مكتبان +مكتباً +مكتبة +مكتبةِ +مكتبته +مكتبتها +مكتبتي +مكتبه +مكتبها +مكتبي +مكتبية +مكترث +مكترثين +مكتشف +مكتشفات +مكتشفه +مكتشفو +مكتظا +مكتظة +مكتـبي +مكتـظ +مكتفية +مكتفين +مكتمل +مكتملة +مكتنزة +مكتوب +مكتوبا +مكتوبة +مكتوفة +مكتوفي +مكتوفين +مكتوم +مكتومة +مكث +مكثت +مكثف +مكثفة +مكثنا +مكدسة +مكدّسة +مكرر +مكررا +مكرراً +مكررة +مكرم +مكرهاً +مكرهة +مكروه +مكروهة +مكروية +مكرّس +مكس +مكسب +مكسبا +مكسرة +مكسوة +مكسورة +مكشوف +مكشوفة +مكشوفون +مكعب +مكعبات +مكفهراً +مكلف +مكلفا +مكلفة +مكللا +مكللة +مكلَّفاً +مكملا +مكملاتها +مكملاً +مكملة +مكملتين +مكمن +مكمنه +مكمنها +مكن +مكنت +مكنتنا +مكنته +مكنه +مكنها +مكنهم +مكنونات +مكنوناتها +مكنيل +مكنّه +مكوثه +مكون +مكونا +مكونات +مكوناته +مكوناتها +مكوناً +مكونة +مكوّن +مكوّنات +مكوّناتها +مكوّنة +مكوّنًا +مكي +مكياج +مكيبي +مكيف +مكيفات +مكيفة +مكيفين +مكين +مكّن +مكّنتها +مل +ملء +ملأ +ملأت +ملأته +ملأوا +ملأى +ملؤه +ملؤها +ملئ +ملئت +ملا +ملاءتها +ملاءمة +ملائكيتنا +ملائم +ملائما +ملائماً +ملائمة +ملابس +ملابساتها +ملابسك +ملابسه +ملابسها +ملابسهم +ملابسي +ملاجئها +ملاح +ملاحاً +ملاحظات +ملاحظاتنا +ملاحظاته +ملاحظاتهم +ملاحظة +ملاحظته +ملاحظتها +ملاحظون +ملاحقة +ملاحقته +ملاحم +ملاحي +ملاحية +ملاذاً +ملاذكرد +ملاذها +ملاذي +ملازم +ملازما +ملازماً +ملازمة +ملازمتي +ملازمًا +ملاسنات +ملاطفا +ملاعب +ملاعبه +ملاك +ملاكا +ملاكمة +ملاكمين +ملامح +ملامحه +ملامحها +ملامحهن +ملامحي +ملامسة +ملان +ملاه +ملاهي +ملاوي +ملاىين +ملايين +ملبس +ملبسة +ملبين +ملة +ملت +ملتحقة +ملتحمة +ملتحمين +ملتزم +ملتزمون +ملتزمًا +ملتصقا +ملتصقاً +ملتصقة +ملتصقين +ملتفت +ملتفتٍ +ملتقى +ملتقي +ملتهباً +ملتوية +ملثمة +ملجأ +ملح +ملحة +ملحـة +ملحق +ملحقاً +ملحقة +ملحمة +ملحمته +ملحمية +ملحن +ملحني +ملحوظ +ملحوظا +ملحوظاً +ملحوظة +ملحوظًا +ملحي +ملحَّة +ملخص +ملخصاً +ملخصها +ملذات +ملرد +ملزم +ملزما +ملزماً +ملزمون +ملساء +ملصق +ملصقاً +ملصقة +ملعب +ملعبا +ملعبي +ملعقة +ملعلعين +ملف +ملفا +ملفات +ملفاتها +ملفق +ملفقة +ملفوفة +ملفًا +ملقاة +ملقة +ملقناً +ملك +ملكا +ملكات +ملكاً +ملكة +ملكه +ملكها +ملكهم +ملكوت +ملكوته +ملكي +ملكية +ملكيته +ملكيين +ملكًا +ملل +مللت +مللنا +ملله +ملليجرام +ملليمترين +ملم +ملماتها +ملماً +ملمس +ملمساً +ملمسه +ملموس +ملموسا +ملموساً +ملموسة +ملمًّا +ملهاة +ملهمة +ملوثات +ملوثة +ملوحا +ملوحة +ملوحته +ملوك +ملوكهم +ملون +ملونا +ملونة +ملويّة +ملوّثاً +ملوّثة +ملوّنة +ملوِّث +ملوِّثات +مليء +مليئا +مليئاً +مليئة +مليئتين +مليا +مليار +مليارا +مليارات +ملياراً +ملياري +ملياً +مليح +مليكي +مليمترات +مليمتراً +مليمترًا +مليون +مليونا +مليونان +مليوناً +مليونى +مليوني +مليونين +مليّاً +مليِّن +مم +مما +مماتها +مماثل +مماثلا +مماثلاً +مماثلة +ممارسا +ممارسات +ممارساته +ممارسة +ممارستنا +ممارسته +ممارسي +ممارسين +ممارسيه +ممازحا +ممالك +ممتاز +ممتازاً +ممتازة +ممتازًا +ممتد +ممتداً +ممتدة +ممتطيا +ممتع +ممتعا +ممتعة +ممتلئ +ممتلئة +ممتلكات +ممتلكاتك +ممتلكاته +ممتلكاتها +ممثل +ممثلا +ممثلاً +ممثلة +ممثلو +ممثلون +ممثلى +ممثلي +ممثلين +ممثليه +ممثليهم +ممدد +ممدوح +ممدودة +ممر +ممرات +ممرض +ممرضات +ممرٌّ +ممرَّات +ممزقة +ممزقًا +ممزوج +ممزوجا +ممزوجاً +ممزوجة +ممسكا +ممسكة +ممسكًا +ممسوخ +ممسوس +ممسوسة +ممشوق +ممضة +ممطرة +ممفيس +ممكن +ممكنا +ممكنات +ممكناً +ممكنة +ممكنًا +مملاً +مملة +مملكة +مملكته +مملكتي +مملوء +مملوءا +مملوءة +مملوكة +مملَّحة +ممن +ممنهج +ممنوع +ممنوعا +ممنوعة +ممنيا +ممهد +ممهدا +ممهدة +ممهورة +ممهّداتها +مميتا +مميز +مميزا +مميزات +مميزاتها +مميزاً +مميزة +مميزًا +مميّز +مميِّزة +ممّن +من +منأى +منا +منابت +منابتها +منابر +منابرنا +منابع +منابعه +مناجاة +مناجاتها +مناجم +مناجمه +مناجمها +مناجيا +مناحل +مناحلهم +مناحم +مناحي +مناحيم +مناحٍ +مناخ +مناخا +مناخه +مناخها +مناخية +مناداته +مناداتي +منادمة +منادي +مناديا +مناديل +منارات +منارته +منازع +منازعات +منازل +منازلنا +منازله +منازلهم +منازلهن +مناسب +مناسبا +مناسبات +مناسباً +مناسبة +مناسبةعلى +مناسبتان +مناسبتين +مناسة +مناسك +مناسكها +مناشدة +مناص +مناصب +مناصبها +مناصرة +مناصروه +مناصفة +مناضل +مناضلا +مناطق +مناطقه +مناطقها +مناطقهم +مناظر +مناظرات +مناظرة +مناعات +مناعة +مناعته +مناعي +منافذ +منافذها +منافس +منافسا +منافساً +منافسة +منافسته +منافستها +منافسه +منافسيها +منافع +منافعه +منافعها +منافعهم +منافـذ +منافق +منافية +مناقب +مناقش +مناقشا +مناقشات +مناقشاً +مناقشة +مناقشته +مناقشتها +مناقصة +مناقضة +مناقير +منال +منامه +منامها +منامي +منان +مناهج +مناهجه +مناهجها +مناهجهم +مناهض +مناهضا +مناهضة +مناهل +مناهم +مناوئ +مناورات +مناورة +مناولة +مناولته +مناولتي +منبتّ +منبثق +منبر +منبرًا +منبسطة +منبع +منبعا +منبعاً +منبعه +منبعها +منبهة +منبهين +منتبجة +منتبها +منتبهين +منتج +منتجا +منتجات +منتجاتها +منتجاتهم +منتجاً +منتجة +منتجع +منتجعات +منتجعنا +منتجعين +منتجي +منتجيْن +منتحل +منتخب +منتخبات +منتخبة +منتدى +منتزع +منتزعا +منتزعاً +منتزه +منتزهات +منتسبا +منتسبة +منتسبين +منتشرة +منتشرون +منتشياً +منتصب +منتصبتين +منتصرة +منتصف +منتصفه +منتظر +منتظرا +منتظرة +منتظرين +منتظم +منتظمة +منتظمين +منتعشاً +منتقاة +منتمية +منتمين +منتهاه +منتهاها +منتهى +منتوجات +منجة +منجزات +منجزاته +منجزاً +منجم +منجمية +منجية +منح +منحة +منحت +منحتني +منحته +منحتها +منحدر +منحدرا +منحدرات +منحرفًا +منحك +منحنا +منحنتني +منحنى +منحني +منحنيا +منحنيات +منحنية +منحه +منحها +منحهم +منحوتاتهم +منحوتة +منحولة +منحى +منحي +منخرطًا +منخفض +منخفضاً +منخفضة +مندسا +مندفعاً +مندمجا +مندمجاً +مندمجة +مندهشا +مندهشاً +مندوب +مندوبا +مندوباً +مندوبًا +مندور +مندوس +منديلاً +منذ +منذئذ +منذر +منذرا +منذعام +منذورة +منزل +منزلا +منزلاً +منزلة +منزلتها +منزلك +منزلكم +منزلنا +منزله +منزلها +منزلهم +منزلي +منزلية +منزلين +منزليّ +منزه +منزوية +منساقا +منساقاً +منسجمًا +منسق +منسوب +منسوبا +منسوبي +منسوبيها +منسي +منسيا +منسية +منشآت +منشأ +منشأة +منشؤه +منشئها +منشئي +منشدين +منشطة +منشودة +منشور +منشورات +منشوراته +منشوراتها +منشورة +منشّطة +منصب +منصبا +منصباً +منصبه +منصبّاً +منصة +منصتا +منصر +منصرفا +منصف +منصفا +منصوبة +منصور +منصّات +منضبطة +منضبطًا +منضدة +منطق +منطقاً +منطقة +منطقةٍ +منطقتنا +منطقته +منطقتها +منطقتي +منطقه +منطقهم +منطقي +منطقيا +منطقياً +منطقية +منطقيته +منطلق +منطلقا +منطلقات +منطلقاته +منطلقاً +منطلقة +منطلقي +منطلقين +منطلقًا +منطوق +منظار +منظر +منظراً +منظرو +منظف +منظفا +منظم +منظما +منظمات +منظماً +منظمة +منظمتي +منظمي +منظمًا +منظور +منظورا +منظوره +منظورها +منظومات +منظومة +منظومية +منظّم +منع +منعاً +منعت +منعتنا +منعدم +منعدمة +منعزل +منعزلة +منعشة +منعطف +منعطفة +منعقدان +منعكسا +منعه +منعها +منعهم +منعوا +منـ +منفاه +منفاي +منفتح +منفتحات +منفتحاً +منفتحة +منفذ +منفذاً +منفذًا +منفرد +منفردا +منفرداً +منفردة +منفردين +منفصل +منفصلا +منفصلان +منفصلاً +منفصلة +منفصلين +منفصم +منفصمة +منفعة +منفعته +منفعتها +منفعية +منفوشين +منفى +منفي +منفياً +منفية +منفيين +منفّر +منقاداً +منقار +منقارا +منقباد +منقبة +منقحة +منقذ +منقسمة +منقضّة +منقطع +منقطعي +منقع +منقلبا +منقوش +منقوشة +منقوصاً +منقوصًا +منقوعًا +منقولات +منقولاته +منك +منكسراً +منكفئا +منكم +منكما +منكمشا +منكن +منكوبون +منكِ +منه +منها +منهج +منهجا +منهجه +منهجي +منهجية +منهجيته +منهك +منهكة +منهم +منهما +منهمكة +منهمكين +منهن +منهنَّ +منهيا +منهية +منو +منواله +منوط +منوطًا +منوعاً +منوعة +منى +مني +منيا +منير +منيرة +منيعا +منيعة +منيعًا +منيني +منّ +منّا +منّة +منَّا +مهاجر +مهاجرا +مهاجرة +مهاجرين +مهاجرًا +مهاجما +مهاجمة +مهاجمته +مهادنا +مهادنة +مهارات +مهاراته +مهارة +مهارته +مهارتها +مهاريهم +مهازل +مهام +مهامه +مهامهم +مهامي +مهاوي +مهب +مهتز +مهتم +مهتما +مهتماً +مهتمة +مهجنة +مهجور +مهجورة +مهجّنة +مهد +مهدئ +مهدئاً +مهدئة +مهداة +مهدت +مهدد +مهددا +مهدداً +مهددة +مهددًا +مهده +مهدها +مهدوا +مهدودًا +مهدي +مهدّدون +مهدَّاة +مهدِّداً +مهذارا +مهذب +مهذبة +مهرب +مهربة +مهربو +مهرة +مهرج +مهرجان +مهرجانات +مهرجاناً +مهرجانها +مهرجوي +مهرجين +مهرطقا +مهرطقون +مهرطقين +مهرولا +مهري +مهرّبة +مهشم +مهشمة +مهل +مهلا +مهلته +مهم +مهما +مهمات +مهماته +مهماتها +مهمان +مهماً +مهمة +مهمتان +مهمتنا +مهمته +مهمتها +مهمتهم +مهمتي +مهمتين +مهمشة +مهمـا +مهمل +مهملاً +مهملة +مهموم +مهموما +مهموماً +مهمين +مهمًا +مهمّشة +مهمًّا +مهن +مهنة +مهنتان +مهنتنا +مهنته +مهنتهم +مهنتي +مهندس +مهندسا +مهندسة +مهندسي +مهندسين +مهندسيين +مهندسًا +مهندسَيْن +مهنها +مهني +مهنياً +مهنية +مهنيًا +مهنيًّا +مهيء +مهيأ +مهيئ +مهيئون +مهيب +مهيبة +مهيج +مهيمنا +مهيمنة +مهين +مهينا +مهّد +مو +موئل +موئله +موئلها +مواء +مواءمة +مواؤها +موائد +موائدنا +موائدهم +موائله +موائلها +موات +مواتية +مواثيق +مواجع +مواجها +مواجهات +مواجهة +مواجهته +مواجهتها +مواجهين +مواد +موادا +مواداً +مواده +موادَّ +مواربة +موارد +مواردنا +موارده +مواردها +مواردهم +مواز +موازاة +موازن +موازنات +موازنة +موازنتها +موازياً +موازية +موازين +موازيًا +مواسم +مواسمها +مواسير +مواصفات +مواصلا +مواصلات +مواصلة +مواضع +مواضيع +مواضيعها +مواطن +مواطنا +مواطناً +مواطنة +مواطنــينا +مواطنه +مواطنها +مواطنهم +مواطنو +مواطنون +مواطنونا +مواطنوها +مواطنى +مواطني +مواطنين +مواطنيه +مواطنيهم +مواعيد +مواعيده +مواعيدها +موافق +موافقا +موافقات +موافقة +موافقته +مواقع +مواقعه +مواقعها +مواقعهم +مواقف +مواقفك +مواقفه +مواقفهم +مواقيتها +مواكب +مواكبة +موال +موالاة +موالد +مواليا +موالياً +مواليد +موانئ +موانع +مواني +مواهب +مواهبهم +موبوءة +موبيل +موت +موتاهم +موتاً +موتشي +موته +موتهم +موتي +موتيه +موثقا +موثقة +موثوق +موجات +موجة +موجتها +موجتين +موجز +موجزا +موجع +موجعاً +موجعة +موجه +موجها +موجهاً +موجهة +موجود +موجودا +موجودات +موجوداً +موجودة +موجودتين +موجودون +موجودين +موجودًا +موجّه +موجّها +موجّهة +موجَّه +موجَّهة +موح +موحا +موحد +موحدا +موحداً +موحدة +موحش +موحّدة +موحّدين +مود +موداعي +مودة +مودع +مودود +موديل +موديلات +موديلها +مور +مورثات +مورثة +مورثتين +مورثياً +مورجان +مورد +موردا +مورداً +موردًا +مورس +مورست +مورقة +مورلي +مورهاوس +مورو +موروا +موروث +موروثة +موروثنا +موريا +موريس +موريسكي +موز +موزارت +موزة +موزع +موزعا +موزعة +موزعين +موزمبيق +موزّعة +موزَّعةً +موستراس +موسر +موسع +موسعا +موسعات +موسعة +موسكو +موسم +موسماً +موسمه +موسمها +موسمياً +موسوعات +موسوعة +موسوعته +موسوعتين +موسوعية +موسى +موسيقار +موسيقارا +موسيقانا +موسيقاه +موسيقى +موسيقي +موسيقيا +موسيقياً +موسيقية +موسيقيين +موسيقيًّا +موسّع +موسّعة +موسَّعة +موشكين +موشوم +موشى +موشي +موشيه +موصل +موصلي +موصولة +موصومين +موضة +موضحا +موضحاً +موضحة +موضحًا +موضع +موضعه +موضعها +موضعي +موضعيا +موضعية +موضوع +موضوعا +موضوعات +موضوعاتها +موضوعان +موضوعاً +موضوعة +موضوعنا +موضوعه +موضوعها +موضوعي +موضوعيا +موضوعياً +موضوعية +موضوعين +موطئ +موطئا +موطن +موطناً +موطنه +موطنها +موطنهم +موظف +موظفا +موظفاً +موظفة +موظفون +موظفي +موظفية +موظفين +موظفيها +موظفيهم +موعد +موعدا +موعدنا +موعده +موعدها +موعوده +موفد +موفدا +موفدين +موفقاً +موفقة +موفور +موفي +موقد +موقع +موقعا +موقعاً +موقعنا +موقعه +موقعها +موقعهم +موقعي +موقف +موقفا +موقفاً +موقفك +موقفنا +موقفه +موقفها +موقفي +موقفينا +موقوفاً +موكب +موكل +موكلة +موكلين +مول +مولاكِ +مولانا +مولاي +مولت +مولد +مولداً +مولدة +مولده +مولدهم +مولدي +مولع +مولعا +مولعين +مولود +مولودا +مولوي +مولِّدةً +مومباي +مومبين +مومياء +مومياوات +مومياواتهم +مومياوين +مون +موناليزا +مونان +مونبولي +مونت +مونتاج +مونتانا +مونتجمري +مونتريال +مونتفرات +مونتي +موندوس +مونرو +مونسانتو +مونسـانتو +مونو +مونولوجاً +موهبة +موهبته +موهوب +موهوباً +موهوبين +مويتشي +موّل +مي +ميا +ميادين +ميالا +ميامي +ميانمار +مياه +مياها +مياهه +مياهها +ميبندازول +ميت +ميتا +ميتان +ميتاً +ميتة +ميتران +ميترلنك +ميتسوبيشي +ميتشجان +ميتشل +ميتشيل +ميثاق +ميثانول +ميثوكسي +ميجاوات +ميخائيل +ميخائيلوف +ميد +ميدالية +ميداليتان +ميدان +ميدانا +ميدانه +ميدانها +ميدانى +ميداني +ميدانيا +ميدانية +ميدانًا +ميدنيكوف +ميدو +مير +ميراث +ميراثاً +ميراثه +ميرامار +ميران +ميردال +ميرزا +ميرسك +ميرك +ميرل +ميري +ميريت +ميريديان +ميز +ميزا +ميزات +ميزاته +ميزاتها +ميزان +ميزانيات +ميزانياتهم +ميزانية +ميزانيته +ميزانيتها +ميزانيتي +ميزة +ميزةً +ميزت +ميزته +ميزوا +ميساء +ميسرة +ميسم +ميسورا +ميسورة +ميسوري +ميسيسيبي +ميسّر +ميسّراً +ميسّرة +ميشال +ميشان +ميشليه +ميشيل +ميعاده +ميفلوكين +ميكال +ميكانيكا +ميكانيكي +ميكانيكياً +ميكانيكية +ميكرو +ميكروب +ميكروبات +ميكروجراما +ميكروجرامات +ميكروسكوبي +ميكروسكوبية +ميكروفون +ميكروفيلم +ميكرومتراً +ميكروميتر +ميكروناً +ميكلسون +ميكنة +ميكيل +ميل +ميلا +ميلاد +ميلادك +ميلاده +ميلادي +ميلادية +ميلان +ميلانو +ميلاً +ميللر +ميلودي +ميلي +ميليشيات +مينا +ميناء +ميناءين +مينائها +مينة +ميندو +مينه +مينوس +مينيسوتا +ميول +ميوله +ميولهم +ميولى +ميونيخ +ميّالة +ميّزت +ميّزه +مَا +مَحكًّا +مَدَّت +مَريتش +مَن +مَنٍّ +مَنْ +مُبرّرة +مُتأمِّلاً +مُجرَّد +مُخلَّط +مُخيفة +مُدرّساً +مُدهِش +مُرة +مُرضية +مُزْن +مُستحَقٌ +مُستمرة +مُشاحّة +مُصاب +مُصرًّا +مُعوِّقًا +مُلقى +مُنتج +مُنتجا +مُنح +مُنحت +مُنحتها +مُنحها +مُهاب +مُوثّق +مُيز +مِقْعَدَة +مِن +مِنكُمْ +مِنَ +مَّا +مَّن +مِّن +مِّنْكُم +ن +نأتي +نأخذ +نأخذكما +نأخذه +نأكل +نأكله +نألو +نأمل +نؤثر +نؤجل +نؤدي +نؤكد +نؤمل +نؤمن +ناءٍ +نائب +نائبا +نائباً +نائبة +نائم +نائماً +نائمة +نائمين +نائية +ناب +نابذات +نابض +نابع +نابعا +نابعة +نابلس +نابليون +نابولي +ناتئ +ناتئة +ناتج +ناتجا +ناتجة +ناتجتان +ناتجًا +ناثال +ناثر +ناجح +ناجحا +ناجحاً +ناجحة +ناجحون +ناجحين +ناجع +ناجعة +ناجم +ناجما +ناجمة +ناجي +ناجين +ناحوم +ناحية +ناحيته +ناحيتها +ناحيتي +ناخب +ناخت +ناد +نادت +نادته +نادر +نادرا +نادراً +نادرة +نادرتين +نادرين +نادرًا +نادم +نادمات +نادماً +نادوا +نادى +نادي +ناديا +نادياً +نادية +ناديته +نادين +ناديناك +نار +نارا +ناراً +ناره +نارها +نارية +نارين +ناريّ +نازعة +نازك +نازل +نازلا +نازلة +ناس +ناسا +ناسج +ناسخًا +ناسه +ناسي +ناسياً +ناشجاً +ناشد +ناشدت +ناشدته +ناشر +ناشرة +ناشري +ناشز +ناشطة +ناشطون +ناشطي +ناصح +ناصحاً +ناصر +ناصع +ناصعات +ناصعة +ناصـــيــف +ناصف +ناصية +ناصيتك +ناصيف +ناضجة +ناضران +ناضل +ناضلت +ناطحات +ناطق +ناطقاً +ناطقة +ناظري +ناظريها +ناظريّا +ناظم +ناظمها +ناعسة +ناعم +ناعما +ناعماً +ناعمة +نافارو +نافت +نافخي +نافذ +نافذة +نافذةالقطار +نافذةٍ +نافذته +نافذتي +نافس +نافستك +نافستها +نافضا +نافضات +نافع +نافعا +نافعاً +نافعة +نافلة +نافورة +نافيا +نافية +ناقة +ناقته +ناقد +ناقدا +ناقداً +ناقدة +ناقدها +ناقش +ناقشت +ناقشتموه +ناقشه +ناقص +ناقصا +ناقصة +ناقصًا +ناقض +ناقل +ناقلاً +ناقلة +ناقما +ناقمة +ناقوس +نال +نالت +نالتهم +ناله +نالها +نام +ناما +نامة +نامت +نامي +ناميبيا +نامية +ناهضة +ناهيت +ناهيك +ناووس +ناي +نايتس +نايجل +ناين +نايه +نب +نبأ +نبات +نباتات +نباتي +نباتيا +نباتياً +نباتية +نباح +نبارح +نبتة +نبتت +نبتعد +نبحث +نبحثه +نبخل +نبدأ +نبذ +نبذة +نبذل +نبذهم +نبرأها +نبراسكا +نبرة +نبرته +نبض +نبضا +نبضات +نبضاتها +نبضة +نبع +نبعا +نبعة +نبعها +نبقى +نبقي +نبل +نبلا +نبلاء +نبني +نبنيها +نبوءات +نبوءة +نبوخذ +نبوخذنصر +نبي +نبياً +نبيل +نبيلة +نبيه +نبيهور +نبّهه +نبْشا +نت +نتأثر +نتأكد +نتأمل +نتأمله +نتأهب +نتائج +نتائجه +نتائجها +نتائجهم +نتابع +نتابعها +نتاج +نتاجه +نتاجها +نتاجهن +نتاجي +نتاجٌ +نتالي +نتبادل +نتبرع +نتبوؤها +نتبين +نتتبع +نتج +نتجاهل +نتجت +نتجمع +نتجنب +نتجول +نتحدث +نتحدّث +نتحرر +نتحرك +نتحسّر +نتحمل +نتحملها +نتحوّل +نتخذ +نتخرج +نتخطاه +نتخطاها +نتخلى +نتخوف +نتخيل +نتداول +نتذكر +نترجم +نترك +نتركها +نتساءل +نتسامح +نتشابه +نتصرف +نتطرق +نتطلع +نتظارنا +نتظاهر +نتعامل +نتعاون +نتعجب +نتعرض +نتعرف +نتعرّض +نتعلم +نتعمد +نتعمق +نتعود +نتعوَّد +نتف +نتفرّس +نتفق +نتقبل +نتقدم +نتقن +نتكلم +نتلافى +نتلقى +نتلمس +نتمكن +نتملك +نتمنى +نتمي +نتميز +نتنازل +نتناول +نتناوله +نتنبأ +نتنة +نتنزّه +نتنصل +نتنفس +نتنه +نتهاون +نتهم +نتوء +نتواصل +نتوجه +نتوخاه +نتوسل +نتوقع +نتوقعها +نتوقف +نتوهّم +نتيجة +نتيجةً +نتيجته +نتيجتها +نتيحها +نتيقن +نثبت +نثر +نثرا +نثراء +نثراً +نثق +نثقبها +نثيث +نج +نجا +نجاة +نجاتي +نجاح +نجاحا +نجاحات +نجاحاته +نجاحاً +نجاحه +نجاحها +نجاحي +نجاحًا +نجادل +نجارا +نجاراً +نجارين +نجاسة +نجاشي +نجاه +نجاهد +نجبه +نجت +نجح +نجحت +نجحنا +نجحوا +نجد +نجدت +نجدتك +نجدد +نجده +نجدها +نجدهم +نجران +نجرب +نجره +نجرو +نجزم +نجعل +نجعله +نجـاحـها +نجلب +نجلس +نجله +نجليه +نجم +نجما +نجماً +نجمة +نجمت +نجمع +نجمعها +نجمل +نجمه +نجمها +نجمهم +نجمي +نجمًا +نجنى +نجهز +نجهلها +نجوب +نجوس +نجوع +نجوم +نجوما +نجومه +نجومها +نجومية +نجيب +نجيباً +نجيبة +نجيم +نح +نحاتا +نحار +نحارب +نحاسية +نحافتها +نحافظ +نحاكي +نحالو +نحاور +نحاول +نحب +نحبذ +نحبه +نحبهم +نحت +نحتاج +نحتاجه +نحترم +نحتضن +نحتفظ +نحتفل +نحتفي +نحتنا +نحته +نحدثه +نحدد +نحذر +نحذف +نحر +نحرر +نحرص +نحرمهم +نحس +نحسد +نحصدها +نحصر +نحصل +نحضر +نحضره +نحط +نحظى +نحـتاجه +نحـو +نحف +نحفظ +نحقق +نحل +نحلة +نحلم +نحمل +نحمله +نحملها +نحمي +نحن +نحو +نحواً +نحوت +نحوك +نحونا +نحوه +نحوها +نحوهم +نحوي +نحوٍ +نحى +نحيا +نحيطه +نحيف +نحيفين +نحيل +نحيلاً +نحيلة +نحينا +نحييكم +نحّى +نحّيتك +نخاف +نخال +نخامية +نخب +نخبئ +نخبا +نخبة +نخبتنا +نخبر +نخبوي +نختار +نختبئ +نخترع +نختزنه +نختصرها +نختصها +نختفي +نختلف +نختم +نخر +نخرج +نخشى +نخطط +نخفيها +نخل +نخلة +نخلته +نخلط +نخور +نخوض +نخيل +نخيلها +ندا +نداء +نداءات +نداءه +ندائه +ندافع +نداً +ندب +ندبات +ندبة +ندبت +ندخل +ندر +ندرة +ندرت +ندرج +ندرس +ندرك +ندركها +ندري +ندع +ندعم +ندعمهم +ندعو +ندعوك +ندعوه +ندعي +ندفعها +ندقق +ندلل +ندم +ندموا +ندوات +ندواته +ندوة +ندوته +ندور +ندوس +ندى +نديم +نديما +ندين +ندّت +ندّدنا +ندٌّ +نذالته +نذر +نذراً +نذرت +نذريـّها +نذكر +نذكرك +نذهب +نذير +نذيرا +نر +نراقب +نراك +نراه +نراها +نراهم +نربط +نربّي +نرتاح +نرتجف +نرتشف +نرتكبه +نرجح +نرجع +نرجو +نرجوك +نرجّح +نرحل +نرد +نردّ +نرسخ +نرسل +نرسلها +نرسم +نرشّها +نرصد +نرضى +نرفال +نرفض +نركز +نرمي +نرميها +نره +نرى +نري +نريد +نريده +نريدها +نزار +نزاع +نزاعاً +نزال +نزاهتها +نزح +نزحت +نزحف +نزرع +نزع +نزعات +نزعاتنا +نزعة +نزعتي +نزعج +نزعها +نزف +نزقة +نزقه +نزل +نزلات +نزلت +نزلوا +نزهة +نزوة +نزوح +نزودهم +نزورها +نزوع +نزول +نزولنا +نزوله +نزوى +نزوّد +نزيف +نزيل +نزيلا +نزيلة +نزيهًا +نزّل +نس +نسأل +نسأله +نسألها +نساء +نساؤه +نسائنا +نسائها +نسائهم +نسائياً +نسائية +نسابا +نساخها +نسارع +نساعدكم +نسافر +نساندك +نساهم +نساير +نسب +نسبا +نسباً +نسبة +نسبت +نسبته +نسبتها +نسبتهم +نسبر +نسبق +نسبه +نسبها +نسبهم +نسبى +نسبي +نسبيا +نسبياً +نسبية +نسبيًا +نسبًا +نستأجر +نستأنس +نستبعد +نستبق +نستثمر +نستحثها +نستحسن +نستحوذ +نستخدم +نستخدمها +نستخلص +نستدرك +نستدله +نستذكر +نستسلم +نستشهد +نستطع +نستطلع +نستطيع +نستعد +نستعرض +نستعمله +نستعيد +نستعيض +نستعين +نستفيد +نستقبل +نستقدم +نستقطب +نستكتب +نستلهم +نستلهمه +نستمتع +نستمدها +نستمر +نستمع +نستنتج +نستهدف +نستهم +نستي +نسج +نسجت +نسجتا +نسجل +نسجها +نسحقهم +نسخ +نسخة +نسخت +نسخته +نسختها +نسخها +نسدل +نسرا +نسراً +نسرق +نسع +نسعى +نسعي +نسق +نسقت +نسك +نسكن +نسل +نسلط +نسمات +نسمة +نسمح +نسمع +نسمعه +نسمي +نسميه +نسميها +نسمّيه +نسهر +نسوة +نسور +نسوه +نسوياً +نسوية +نسى +نسي +نسيء +نسيا +نسيان +نسياناً +نسيانه +نسيانها +نسياني +نسيبة +نسيبًا +نسيت +نسيتني +نسيتها +نسيتُ +نسيج +نسيجا +نسيجه +نسيجها +نسير +نسينا +نسيه +نسيها +نشأ +نشأة +نشأت +نشأته +نشأتها +نشأتهم +نشأتي +نشأنا +نشاء +نشارك +نشاط +نشاطا +نشاطات +نشاطاتك +نشاطاته +نشاطاتها +نشاطاتهم +نشاطاتي +نشاطاً +نشاطه +نشاطها +نشاطهم +نشاهد +نشاهده +نشاهدها +نشب +نشبت +نشبر +نشبع +نشبه +نشبّهه +نشبّهها +نشتري +نشتهر +نشجع +نشحذ +نشحن +نشر +نشراته +نشرة +نشرت +نشرتنا +نشرته +نشرتها +نشرحها +نشره +نشرها +نشط +نشطاء +نشطاً +نشطة +نشطت +نشعر +نشك +نشكو +نشهد +نشهدها +نشوء +نشوة +نشيج +نشيد +نشيده +نشير +نشيطا +نشيطان +نشيطاً +نشيطة +نشيطي +نشَّطت +نص +نصا +نصائح +نصائحي +نصائحَ +نصادر +نصادف +نصادفه +نصار +نصارع +نصارى +نصاعة +نصاً +نصب +نصبت +نصبح +نصبه +نصحته +نصحني +نصحه +نصحو +نصحوه +نصدر +نصدرها +نصدق +نصر +نصرا +نصرالله +نصراني +نصرانية +نصرة +نصرته +نصرخ +نصرهم +نصري +نصطدم +نصعد +نصف +نصفه +نصفها +نصفهم +نصفي +نصفُ +نصل +نصلب +نصلح +نصلي +نصنا +نصنع +نصه +نصها +نصور +نصوص +نصوصا +نصوصهنّ +نصوصي +نصوّر +نصوُّح +نصي +نصيب +نصيباً +نصيبك +نصيبه +نصيبها +نصيبهم +نصيبي +نصيحة +نصيحتك +نصير +نصيره +نصًا +نصّ +نصّا +نصّاً +نصّت +نصّك +نصّه +نصٍّ +نضارات +نضارة +نضال +نضالنا +نضاله +نضالها +نضاليا +نضالية +نضبت +نضج +نضجاً +نضجه +نضجها +نضجًا +نضحكها +نضرب +نضطر +نضع +نضعه +نضمن +نضوب +نضوبة +نضوج +نضيع +نضيعَ +نضيف +نضّر +نط +نطؤها +نطاق +نطاقاً +نطاقها +نطالب +نطرحه +نطق +نطقا +نطقالراء +نطقت +نطقها +نطلب +نطلق +نطمح +نطهر +نطور +نطيح +نطيع +نظائر +نظائرها +نظائرهم +نظارات +نظاراتهم +نظارة +نظارت +نظارته +نظارتها +نظافة +نظام +نظاما +نظاماً +نظامنا +نظامه +نظامها +نظامهم +نظامية +نظاميين +نظامًا +نظر +نظرا +نظرائها +نظرائهم +نظرات +نظراته +نظراتها +نظراتهم +نظراتهما +نظراتي +نظراتِهِ +نظراً +نظرة +نظرةً +نظرت +نظرتنا +نظرته +نظرتهم +نظرتي +نظرتين +نظركم +نظرنا +نظره +نظرهم +نظروا +نظري +نظريا +نظريات +نظرياته +نظرياتها +نظرياتهم +نظرياً +نظرية +نظريته +نظريًا +نظريًّا +نظرًا +نظـري +نظفت +نظل +نظلمه +نظم +نظمت +نظمته +نظمتها +نظمه +نظمها +نظن +نظهر +نظير +نظيرا +نظيراتها +نظيرة +نظيرتها +نظيره +نظيرية +نظيريه +نظيف +نظيفا +نظيفاً +نظيفة +نظَّمه +نعاس +نعال +نعالاً +نعالج +نعالجها +نعاني +نعانيه +نعبر +نعت +نعتبر +نعتبره +نعترف +نعتز +نعتقد +نعتمد +نعته +نعتها +نعثر +نعد +نعده +نعرض +نعرضها +نعرف +نعرفة +نعرفه +نعرفها +نعرفهم +نعرِّفهم +نعش +نعشق +نعصر +نعط +نعطي +نعطيه +نعكس +نعكف +نعلق +نعلم +نعلمه +نعلمهم +نعلن +نعلنها +نعلِّق +نعم +نعمان +نعمة +نعمت +نعمتُ +نعمل +نعنى +نعني +نعنيه +نعود +نعومة +نعومي +نعى +نعي +نعيد +نعيش +نعيشه +نعيشها +نعيم +نعيمة +نعيمي +نـبـض +نـظمت +نـظيفة +نفاثة +نفاد +نفاذاً +نفاذة +نفاضل +نفايات +نفاياتهم +نفت +نفتتحه +نفتح +نفتحها +نفتخر +نفترض +نفتقد +نفتقده +نفتقدها +نفتقدْ +نفتقر +نفحات +نفحة +نفخ +نفخر +نفد +نفدت +نفذ +نفذت +نفذه +نفذها +نفر +نفرح +نفرد +نفرش +نفرض +نفرٌ +نفرّق +نفس +نفسانية +نفساً +نفسح +نفسـي +نفسك +نفسكِ +نفسه +نفسها +نفسهم +نفسى +نفسي +نفسيا +نفسياً +نفسية +نفسيته +نفسينا +نفسيّا +نفسًا +نفسِ +نفصلها +نفصلهم +نفصّل +نفض +نفضت +نفضل +نفط +نفطن +نفع +نفعا +نفعل +نفعلها +نفعه +نفعية +نفق +نفقات +نفقة +نفقتك +نفقته +نفقتها +نفكر +نفكّر +نفمبر +نفنّد +نفهم +نفهمه +نفهمهم +نفوذ +نفوذه +نفوذها +نفوذهم +نفور +نفوراً +نفوس +نفوسنا +نفوسهم +نفوق +نفى +نفي +نفيس +نفيسة +نفيه +نفّاذ +نفّذوا +نقاء +نقابة +نقابل +نقابله +نقابي +نقابية +نقاد +نقاده +نقار +نقارن +نقاش +نقاشا +نقاشات +نقاط +نقالة +نقبل +نقبله +نقتاتُ +نقتحمها +نقترب +نقترح +نقتل +نقد +نقدا +نقدته +نقدر +نقدم +نقدمه +نقدمها +نقده +نقدي +نقديا +نقدياً +نقدية +نقدًا +نقدّر +نقدّم +نقر +نقرأ +نقرأه +نقرؤه +نقرات +نقراته +نقرة +نقرر +نقش +نقشت +نقص +نقصا +نقصان +نقصاً +نقصت +نقصد +نقصده +نقصي +نقضي +نقطة +نقطتين +نقطع +نقطن +نقطها +نقـــاش +نقف +نقل +نقلا +نقلات +نقلاً +نقلة +نقلت +نقلته +نقلتها +نقلده +نقلنا +نقله +نقلها +نقلهم +نقلوا +نقلي +نقلّب +نقم +نقمة +نقنع +نقود +نقودا +نقوداً +نقودك +نقوده +نقودهم +نقودي +نقوش +نقوشا +نقوشها +نقول +نقولا +نقوله +نقولها +نقوم +نقوّم +نقي +نقيا +نقيبًا +نقية +نقير +نقيس +نقيض +نقيضا +نقيم +نقّاد +نقّاده +نقّاش +نقّب +نكاد +نكبات +نكباته +نكبة +نكبّل +نكتب +نكتبه +نكتة +نكتشف +نكتفي +نكران +نكرمهم +نكس +نكسة +نكسها +نكشف +نكفكف +نكلا +نكلف +نكمل +نكن +نكهة +نكهته +نكون +نكوِّن +نلاحظ +نلاحظه +نلاحظها +نلبس +نلت +نلتحق +نلتزم +نلتف +نلتقي +نلجأ +نلحظ +نلحظه +نلحظها +نلحق +نلزم +نلعب +نلق +نلقى +نلقي +نللينو +نلمح +نلمس +نلمسه +نلمسها +نلوب +نما +نماؤها +نمائية +نماذج +نماذجها +نمارس +نمارسها +نمت +نمتلك +نمثل +نمر +نمرا +نمزج +نمساوية +نمسح +نمشي +نمضي +نمط +نمطا +نمطاً +نمطك +نمطها +نمطية +نمطًا +نمل +نملأ +نملك +نمله +نمنع +نمو +نموا +نمواً +نموت +نموذج +نموذجا +نموذجاً +نموذجي +نموذجياً +نموذجية +نموذجين +نموذجيّ +نموذجًا +نمور +نموه +نموها +نموهم +نموي +نموًا +نمير +نميراً +نميري +نميرية +نميز +نميل +ننار +نناقش +نناقشه +ننام +ننتبه +ننتج +ننتظر +ننتظرها +ننتقل +ننتمي +ننتهي +ننجح +ننجز +ننجزه +نندد +ننزل +ننسى +ننشئ +ننشده +ننشدها +ننشر +ننشرها +ننصح +ننطلق +ننظر +ننظم +ننعطف +ننفذ +ننفض +ننفضُ +ننفق +ننفقه +ننقل +ننقلها +ننكر +ننمي +ننه +ننهل +ننهي +ننوي +نه +نها +نهائي +نهائيا +نهائيات +نهائياً +نهائية +نهائيًّا +نهاجم +نهاد +نهار +نهارا +نهارات +نهاراً +نهاره +نهارها +نهاري +نهارية +نهاك +نهاه +نهاهم +نهايات +نهاية +نهايته +نهايتها +نهب +نهبت +نهبوا +نهبوه +نهتم +نهج +نهجا +نهجاً +نهجه +نهجها +نهجي +نهجًا +نهد +نهدف +نهر +نهرا +نهراً +نهرب +نهرو +نهري +نهرًا +نهرٌ +نهز +نهشا +نهض +نهضات +نهضة +نهضت +نهضتها +نهضتهم +نهضتُ +نهضنا +نهضوا +نهضوي +نهل +نهلا +نهلة +نهم +نهمل +نهمي +نهوض +نهوند +نهى +نهيأ +نهير +نوئيل +نواب +نواة +نواةً +نواته +نواتها +نواجه +نواجهه +نواجهها +نواح +نواحي +نوادر +نوادى +نوادي +نوارس +نواز +نواس +نواصل +نوافذ +نوافذها +نوافذهم +نوافي +نوافير +نواقيس +نوال +نواويس +نواياها +نواياهم +نواياي +نوب +نوبات +نوبة +نوبل +نوتردام +نوتنجهام +نوتيّ +نوجب +نوجد +نوجه +نوح +نود +نودع +نور +نورا +نوراً +نورتون +نورث +نورثها +نورد +نورس +نورسا +نورسك +نورك +نورمان +نورهان +نوروز +نوروود +نوري +نوزت +نوزع +نوشيره +نوصيكم +نوضح +نوع +نوعا +نوعان +نوعاً +نوعه +نوعها +نوعي +نوعية +نوعين +نوعًا +نوفارتس +نوفارتيس +نوفاليس +نوفجورد +نوفر +نوفرها +نوفق +نوفمبر +نوفورتوني +نوفيكوف +نوق +نوقشت +نوقف +نول +نولي +نوم +نوماً +نومه +نومها +نومهم +نومي +نون +نونايل +نووي +نوويا +نووياً +نووية +نوويد +نوويّ +نويمان +نوّهت +ني +نيابة +نياراجي +نياركوس +نياط +نيام +نياماً +نيبال +نيبهور +نية +نيت +نيتشر +نيته +نيتي +نيجاتيف +نيجيريا +نيدر +نير +نيران +نيرانا +نيرن +نيروبي +نيرودا +نيسا +نيسان +نيستوكا +نيسلون +نيشان +نيشن +نيفاً +نيقولاس +نيقولاى +نيقية +نيقيه +نيك +نيكست +نيكسون +نيكل +نيكوس +نيكوليتا +نيل +نيلسون +نيله +نيلها +نيلوس +نيلي +نيمم +نينوى +نيو +نيوتروناً +نيوتن +نيوجيرسى +نيودلهى +نيودلهي +نيوز +نيوزيلندا +نيومكسيكو +نيومي +نيويورك +نيويوركية +نيّفت +نيِّر +نَأْي +نَحْبَهُ +نَص +نَفَحـتنا +نُبتلع +نُبرر +نُبهر +نُبْحر +نُتخم +نُدخل +نُدرةً +نُزُلها +نُسهم +نُسَخ +نُشرت +نُظمت +نُعجَب +نُفق +نُقذف +نُقشت +نُقلت +نُلْق +نُمعن +نُواحه +نِمنَا +نّقص +ه +هؤلاء +ها +هاأنا +هاأنت +هاأنذا +هائجاً +هائجًا +هائل +هائلا +هائلاً +هائلة +هائمة +هابطاً +هابطة +هابطًا +هابل +هات +هاتان +هاتفه +هاتفيا +هاتفية +هاتفيين +هاته +هاتوا +هاتي +هاتيراسّ +هاتيك +هاتين +هاج +هاجر +هاجرت +هاجروا +هاجس +هاجساً +هاجسه +هاجسي +هاجعة +هاجم +هاجمة +هاجمت +هاجمته +هاجموا +هاجموني +هاجموه +هاجو +هاد +هادئ +هادئا +هادئاً +هادئة +هادئين +هادرة +هادفاً +هاديء +هاذي +هار +هاربا +هارباً +هاربرز +هارستنج +هارعا +هارفارد +هارفرد +هارلان +هارلم +هارمر +هارموني +هارود +هارون +هاريس +هاريسون +هاس +هاسكل +هاشم +هاف +هافانا +هافل +هاكرز +هالات +هالة +هالفلوس +هالك +هالكة +هالو +هالوديول +هالوفانترين +هاليفاكس +هالييتاس +هام +هاما +هامات +هاماً +هامبولدت +هامبون +هامة +هامدة +هامر +هامرسميث +هامس +هامسا +هامساً +هامستيد +هامسًا +هامش +هامشاً +هامشياً +هامشية +هامشيين +هامّاً +هامّة +هان +هانئ +هانز +هانم +هانوي +هاني +هاهم +هاهما +هاهو +هاهي +هاواى +هاواي +هاورد +هاوس +هاوسي +هاويا +هايتي +هايد +هايدرو +هاير +هايكو +هاييتي +هب +هباء +هبات +هبة +هبت +هبط +هبطت +هبطوا +هبوا +هبوب +هبوط +هبوطا +هبوطاً +هبوطهم +هبّ +هبّات +هبّة +هبّت +هتافاتهم +هتف +هتفنا +هتلر +هجاه +هجاها +هجر +هجرات +هجرة +هجرته +هجرتها +هجرتهم +هجرتي +هجرها +هجروها +هجرية +هجم +هجمات +هجماته +هجمة +هجمت +هجمنا +هجوم +هجوما +هجوماً +هجومه +هجين +هدأ +هدأة +هدأت +هدأتهم +هدا +هدارة +هدامة +هداهم +هدايا +هداياه +هداية +هدتني +هدد +هددت +هددوه +هدر +هدراً +هدرها +هدسون +هدف +هدفا +هدفاً +هدفتُ +هدفنا +هدفه +هدفها +هدفهم +هدفى +هدفًا +هدم +هدمت +هدمه +هدمها +هدموا +هدنة +هده +هدهدنا +هدوء +هدوءاً +هدوئه +هدومي +هدى +هدي +هدية +هديتي +هدير +هديراً +هديه +هدّأته +هدّاما +هدّد +هدَّها +هذ +هذا +هذان +هذاوخاصة +هذة +هذه +هذي +هذيا +هذيانه +هذين +هراء +هرب +هربا +هرباً +هرباًمن +هربت +هربرت +هربنا +هربه +هرتزل +هرج +هرجة +هرطقات +هرطقية +هرع +هرعت +هرعنا +هرفيه +هرقل +هرلر +هرم +هرمز +هرمون +هرمونية +هروب +هروبه +هروخيه +هرون +هريرة +هز +هزاز +هزة +هزت +هززت +هزلية +هزمت +هزنا +هزني +هزيع +هزيلاً +هزيمة +هزيمته +هزيمتها +هزّ +هزّت +هزَّت +هس +هستيري +هستيريا +هسيسهم +هش +هشا +هشاشة +هشام +هشّ +هشّة +هشَّة +هضابه +هضبة +هضم +هضمت +هضمها +هطل +هطلت +هطول +هعير +هـ +هـذا +هـــو +هفن +هفوت +هكتار +هكتارات +هكذا +هكسلي +هكـذا +هل +هلا +هلاك +هلاكا +هلال +هلام +هلامهم +هلاميات +هلامية +هلاّ +هلع +هلعا +هلعاً +هلعًا +هليوبوليس +هم +هما +همام +هماً +همة +همته +همتها +همجيتهم +همدت +همزات +همزة +همس +همسا +همسات +همساً +همسة +همست +همشه +هملت +همم +هممت +هممكم +همنجواي +همه +همها +همهمات +همهمت +هموم +همومها +همومي +همي +همّ +همّا +همّة +همّه +همّي +همَّ +همَّة +همِّش +هن +هنأت +هنا +هناك +هنالك +هنتر +هنتسمان +هنتنجتون +هندامها +هندسة +هندسى +هندسي +هندسياً +هندسية +هندي +هندية +هنري +هني +هنيئة +هنيه +هنيهة +هنَّ +هه +ههنا +هو +هواء +هواءها +هوائية +هواة +هواتف +هواجس +هواجسه +هوادة +هواليبيك +هواه +هوايات +هواية +هوايته +هوايتهم +هوايتي +هوباحث +هوة +هوت +هوتميل +هوتيل +هوجم +هوجو +هورموناتها +هورن +هوز +هوس +هوسا +هوسي +هوف +هوفمان +هوكست +هوكنج +هول +هولاند +هولاً +هولت +هولدن +هولمز +هولندا +هولنداي +هولندي +هولندية +هولوواي +هوليدى +هوليدي +هوليوود +هولِ +هومايون +هومستوباريوس +هومير +هوميروس +هون +هونج +هوندو +هونها +هونيكمان +هوى +هويات +هوياتهم +هوية +هويتنا +هويته +هويتها +هويتهم +هويتي +هوّة +هوّز +هى +هي +هيأت +هيئ +هيئات +هيئاتهن +هيئة +هيئته +هيئتها +هيا +هياج +هياكل +هياكلها +هيبة +هيبتها +هيبرا +هيبون +هيجو +هيدرو +هيدروجين +هيدروجينية +هيدروكسيد +هيدلبرج +هيدلي +هيرا +هيربرت +هيرتزل +هيرفي +هيرودوت +هيرودوتس +هيرودوس +هيروشيما +هيس +هيكل +هيكلا +هيكلاً +هيكلة +هيكله +هيكلهم +هيكلياتها +هيكلية +هيلانة +هيلبيك +هيلتون +هيلجا +هيلموت +هيمن +هيمنة +هين +هيناً +هيني +هيهات +هيو +هيوارد +هيوز +هيوستن +هيولية +هيومان +هيومايون +هيّأني +هيَّأها +هَاجَرُوا +هَرَم +هَزُلت +هَلْ +هُزُعا +هِرَم +و +وآ +وآباء +وآثار +وآثاره +وآثارها +وآثام +وآثر +وآثرنا +وآخذ +وآخر +وآخرة +وآخرتها +وآخرها +وآخرون +وآخرى +وآخرين +وآداب +وآدابا +وآدابه +وآدابها +وآدم +وآراء +وآراءه +وآراؤه +وآرائه +وآرائهم +وآسيا +وآسيوية +وآشور +وآفاق +وآكل +وآل +وآلا +وآلات +وآلاف +وآلام +وآلياتها +وآمال +وآمالهم +وآمل +وآمن +وآمنة +وآن +وآهٍ +وآياته +وآية +وأ +وأؤدي +وأؤكد +وأئمة +وأئمته +وأب +وأباطيل +وأباكم +وأبانت +وأبتعد +وأبحاث +وأبحاثه +وأبحاثهم +وأبخرة +وأبدأ +وأبدا +وأبداننا +وأبداً +وأبدت +وأبدع +وأبدعوا +وأبدوا +وأبدى +وأبدي +وأبدية +وأبراج +وأبرز +وأبرزته +وأبرق +وأبصارنا +وأبصر +وأبعاد +وأبعادها +وأبعد +وأبقت +وأبقراط +وأبقى +وأبقيت +وأبكاهم +وأبلوا +وأبناء +وأبنائه +وأبنائها +وأبنائهم +وأبنائهما +وأبنائي +وأبنية +وأبها +وأبهاء +وأبهة +وأبو +وأبوابها +وأبوه +وأبوهم +وأبي +وأبيض +وأبيه +وأبيها +وأبّهة +وأتأكد +وأتأمل +وأتأملها +وأتابع +وأتابعها +وأتابكتهم +وأتاح +وأتاحت +وأتباعه +وأتباعها +وأتبع +وأتبعتهم +وأتبعها +وأتحدث +وأتحرّر +وأتحسس +وأتخيل +وأتذكر +وأتذوقه +وأترأس +وأتراحها +وأتراحهم +وأتراكا +وأتربة +وأترجاه +وأترك +وأتركها +وأتساءل +وأتصور +وأتعامل +وأتعاون +وأتعجب +وأتعرف +وأتفحص +وأتقدم +وأتقن +وأتقنها +وأتلو +وأتم +وأتمشى +وأتمنى +وأتمّ +وأتوقع +وأتى +وأتيح +وأتيحت +وأثاث +وأثاثها +وأثار +وأثارت +وأثاناسيوس +وأثبت +وأثبتت +وأثبتوا +وأثخنوها +وأثر +وأثره +وأثرها +وأثقل +وأثمان +وأثمر +وأثمرت +وأثناء +وأثناءها +وأثنى +وأثوابهن +وأثّر +وأجاب +وأجاثا +وأجاد +وأجادت +وأجبت +وأجبرتهم +وأجتهد +وأجد +وأجدادنا +وأجدادهم +وأجدد +وأجدر +وأجدكِ +وأجدني +وأجدّ +وأجروا +وأجرى +وأجريت +وأجز +وأجزاء +وأجزائه +وأجزل +وأجزلَ +وأجسادنا +وأجسادهم +وأجسام +وأجعل +وأجلس +وأجمل +وأجمله +وأجملها +وأجنابها +وأجنبية +وأجنحة +وأجهزة +وأجهزتها +وأجهزتهم +وأجواء +وأجود +وأجيب +وأجّجنا +وأحادي +وأحادية +وأحاديث +وأحاديثنا +وأحاسيسها +وأحاط +وأحاطا +وأحاطت +وأحالها +وأحاورهم +وأحاول +وأحب +وأحبابي +وأحببت +وأحببتها +وأحببتُ +وأحبه +وأحبها +وأحجامه +وأحجمت +وأحد +وأحداث +وأحداثها +وأحدث +وأحدثكم +وأحدثوا +وأحدقت +وأحدهما +وأحذية +وأحراشها +وأحرق +وأحزاب +وأحزمة +وأحس +وأحسب +وأحسبني +وأحسبه +وأحست +وأحسست +وأحسن +وأحسه +وأحصر +وأحضر +وأحطم +وأحطمها +وأحـد +وأحفادنا +وأحفاده +وأحفادهم +وأحفظ +وأحقهم +وأحكام +وأحكامها +وأحلام +وأحلامنا +وأحلامه +وأحلامهم +وأحلامي +وأحلم +وأحلى +وأحمد +وأحمل +وأحميها +وأحمّل +وأحنى +وأحواضاً +وأحوال +وأحوالهم +وأحوز +وأحيا +وأحياء +وأحيانا +وأحياناً +وأحيانًا +وأحيت +وأخاف +وأخال +وأخالنا +وأخاً +وأخبار +وأخبرتني +وأخبرنا +وأخبرني +وأختار +وأختام +وأختاً +وأخترق +وأختزنها +وأخته +وأخذ +وأخذا +وأخذت +وأخذتني +وأخذته +وأخذنا +وأخذوا +وأخذوها +وأخذوهم +وأخرج +وأخرجت +وأخرجه +وأخرجها +وأخرى +وأخشاها +وأخصبوا +وأخطأت +وأخطائهم +وأخطائي +وأخطاره +وأخطارها +وأخطر +وأخـــلاقه +وأخفاها +وأخفضت +وأخفق +وأخفقت +وأخفى +وأخلاقيات +وأخلاقياتهم +وأخلاقية +وأخلاقيًّا +وأخلعه +وأخواتها +وأخواتي +وأخوة +وأخوته +وأخوتي +وأخوض +وأخوف +وأخوه +وأخوَّته +وأخي +وأخيرا +وأخيراً +وأخيرًا +وأخيه +وأد +وأداء +وأدائه +وأدائهم +وأداة +وأداتها +وأدار +وأدب +وأدباء +وأدباً +وأدبر +وأدبه +وأدبها +وأدبية +وأدبًا +وأدت +وأدخل +وأدخلت +وأدخلته +وأدخلتها +وأدخله +وأدخنة +وأدرت +وأدرك +وأدركت +وأدركه +وأدع +وأدعو +وأدعية +وأدفع +وأدفعها +وأدق +وأدلها +وأدندن +وأدها +وأدوات +وأدواتها +وأدوار +وأدوية +وأدوّن +وأدى +وأديانهم +وأديب +وأديبا +وأديبات +وأديباً +وأديبها +وأدّت +وأذاع +وأذاكر +وأذكار +وأذكر +وأذكى +وأذهب +وأذى +وأراد +وأرادت +وأراده +وأراضي +وأراضٍ +وأراني +وأراه +وأربابه +وأربع +وأربعة +وأربعمائة +وأربعون +وأربعين +وأرتاح +وأرتال +وأرتنا +وأرجع +وأرجعوها +وأرجلهم +وأرجو +وأرحل +وأردت +وأردف +وأردية +وأرسطو +وأرسل +وأرسلت +وأرسله +وأرسم +وأرض +وأرضاً +وأرضه +وأرضية +وأرعد +وأرفعهم +وأرفف +وأرفق +وأرقام +وأرقب +وأرقص +وأرقى +وأركض +وأرمي +وأرميه +وأرميها +وأرهقته +وأرهقه +وأرواح +وأرواحنا +وأرواحهم +وأروح +وأروع +وأروقة +وأروِ +وأرى +وأريج +وأريحية +وأريد +وأزاح +وأزالت +وأزداد +وأزرع +وأزعم +وأزقتها +وأزمات +وأزهاره +وأزياء +وأزيح +وأزيلت +وأزِن +وأسأل +وأسألهما +وأسئلة +وأسئلته +وأسئلتها +وأساءت +وأساتذة +وأساس +وأساسيا +وأساسية +وأساطير +وأساطيرها +وأساعدها +وأسافر +وأساليب +وأساليبه +وأسامة +وأساور +وأسباب +وأسبابها +وأسبانيا +وأسبر +وأسبوع +وأستاذ +وأستاذاً +وأستباحها +وأستبعد +وأستخدم +وأستخدمه +وأستذكر +وأستراليا +وأسترجع +وأستريح +وأستطيع +وأستعدوا +وأستمتع +وأستمع +وأستيقظت +وأسر +وأسرار +وأسرتاهما +وأسرته +وأسرع +وأسرعت +وأسرعها +وأسرفت +وأسره +وأسرى +وأسس +وأسست +وأسسه +وأسسوا +وأسطورة +وأسطول +وأسعار +وأسعارها +وأسفار +وأسفاراً +وأسفاري +وأسفر +وأسفرت +وأسفهم +وأسقط +وأسقطت +وأسقف +وأسقفها +وأسقيه +وأسكته +وأسكنت +وأسكنه +وأسلحة +وأسلحتها +وأسلم +وأسلمنا +وأسلوب +وأسلوبه +وأسلوبي +وأسماء +وأسمار +وأسماكاً +وأسماها +وأسمع +وأسنانه +وأسندت +وأسهل +وأسهم +وأسهمت +وأسواق +وأسواقها +وأسود +وأسوشيتدبرس +وأسوي +وأسيراً +وأسيوط +وأشاد +وأشار +وأشارت +وأشاعوا +وأشاهد +وأشجار +وأشخاص +وأشد +وأشده +وأشدها +وأشرأب +وأشرس +وأشرطة +وأشرف +وأشرى +وأشعار +وأشعارا +وأشعاره +وأشعر +وأشعل +وأشعلوا +وأشفق +وأشقّ +وأشكال +وأشكاله +وأشكالها +وأشكالي +وأشنق +وأشهد +وأشهر +وأشهرها +وأشهرهم +وأشواقها +وأشياء +وأشير +وأصاب +وأصابت +وأصابعنا +وأصالة +وأصبح +وأصبحت +وأصبحتم +وأصبحتُ +وأصبحوا +وأصح +وأصحاب +وأصحابه +وأصحابها +وأصخنا +وأصدر +وأصدرت +وأصدرته +وأصدرتها +وأصدره +وأصدرها +وأصدق +وأصدقاء +وأصدقاءنا +وأصدقاؤه +وأصدقائه +وأصدقائي +وأصدقكم +وأصر +وأصرخ +وأصروا +وأصعب +وأصف +وأصفها +وأصل +وأصلب +وأصلحها +وأصمت +وأصناف +وأصوات +وأصول +وأصولا +وأصوله +وأصولها +وأصولهم +وأصيب +وأصيبت +وأصيل +وأصيلة +وأضاف +وأضافت +وأضحك +وأضخم +وأضر +وأضراب +وأضرار +وأضراره +وأضرّ +وأضعف +وأضعفها +وأضف +وأضفت +وأضلوا +وأضواء +وأضوائها +وأضيف +وأضيفت +وأطال +وأطباء +وأطر +وأطراف +وأطرحها +وأطرق +وأطروحاته +وأطفال +وأطفاله +وأطفالها +وأطفالهم +وأطفالي +وأطل +وأطلال +وأطلت +وأطلعه +وأطلق +وأطلقا +وأطلقت +وأطلقتها +وأطلقوا +وأطوارها +وأطول +وأظل +وأظن +وأظنني +وأظنهما +وأظهر +وأظهرت +وأظهري +وأعاد +وأعادت +وأعادني +وأعادوهم +وأعاق +وأعالي +وأعباءه +وأعباؤه +وأعبائه +وأعتبر +وأعتبره +وأعترف +وأعتز +وأعتقد +وأعثر +وأعجب +وأعجبت +وأعد +وأعداء +وأعدائه +وأعدائهم +وأعداد +وأعدد +وأعددت +وأعدك +وأعدها +وأعراسها +وأعرب +وأعرف +وأعرِضُ +وأعزف +وأعسال +وأعشابه +وأعضاء +وأعطانا +وأعطاه +وأعطت +وأعطته +وأعطتها +وأعطى +وأعطي +وأعطيتها +وأعظم +وأعقب +وأعقد +وأعلامه +وأعلامهم +وأعلاها +وأعلن +وأعلنت +وأعلنتها +وأعلنوا +وأعلى +وأعمار +وأعمال +وأعماله +وأعمالهم +وأعمامي +وأعمدة +وأعمق +وأعمل +وأعني +وأعوانه +وأعود +وأعوم +وأعياد +وأعيادهم +وأعياه +وأعيته +وأعيتهم +وأعيد +وأعيدت +وأعيش +وأفاد +وأفادت +وأفارقة +وأفاضل +وأفاقون +وأفانين +وأفتى +وأفخر +وأفراحهم +وأفراخها +وأفراد +وأفرادالمجتمع +وأفرادها +وأفراس +وأفرج +وأفرجت +وأفرزت +وأفرشها +وأفريقيا +وأفزعت +وأفسحت +وأفضل +وأفضلها +وأفضِّل +وأفطر +وأفعالها +وأفعل +وأفق +وأفكار +وأفكاراً +وأفكاره +وأفكارهم +وأفكاري +وأفكر +وأفلاطون +وأفلام +وأفلاما +وأفنيون +وأفواه +وأقارب +وأقام +وأقامت +وأقاموا +وأقبل +وأقبلت +وأقبلهم +وأقبية +وأقدس +وأقدم +وأقدمت +وأقذف +وأقر +وأقرأ +وأقرؤها +وأقراص +وأقرانه +وأقرب +وأقربها +وأقربهم +وأقرت +وأقرهم +وأقساها +وأقصد +وأقطار +وأقطارنا +وأقف +وأقفل +وأقل +وأقلام +وأقلامه +وأقلها +وأقلية +وأقمشة +وأقمنا +وأقنان +وأقنع +وأقنعته +وأقواسـه +وأقوال +وأقواله +وأقوالهم +وأقول +وأقوم +وأقوى +وأقيم +وأكاد +وأكاديميات +وأكبادنا +وأكبادهم +وأكبر +وأكبرها +وأكتب +وأكتفي +وأكثر +وأكثرمن +وأكثرها +وأكثرهم +وأكثرهن +وأكد +وأكدت +وأكدوا +وأكرر +وأكرم +وأكره +وأكسبتكم +وأكسبه +وأكسجين +وأكسفورد +وأكشف +وأكل +وأكلا +وأكلمه +وأكمل +وأكملت +وأكواخ +وأكوام +وأكون +وأكياس +وأكيدة +وألا +وألاعيب +وألاعيبهم +وألبرت +وألبسته +وألبسه +وألبومي +وألج +وألحان +وألحت +وألزم +وألسنة +وألعاب +وألعابا +وألف +وألفاظ +وألفريد +وألقا +وألقاكما +وألقت +وألقها +وألقوه +وألقى +وألقي +وألقيت +وألقيتها +وألقيها +وألم +وألمانيا +وألمهم +وألمّ +وألهمها +وألوان +وألوانه +وألوانها +وألواني +وألون +وألونهما +وأليماً +وألّف +وأم +وأما +وأماكن +وأمام +وأمامكم +وأمامنا +وأمامها +وأمامهم +وأمان +وأماناً +وأمانة +وأمانتها +وأمانيهم +وأمتعته +وأمتعنا +وأمتك +وأمثال +وأمثاله +وأمثالها +وأمثالهما +وأمثلة +وأمر +وأمراض +وأمراضها +وأمره +وأمرهم +وأمريكا +وأمريكية +وأمريكيين +وأمسح +وأمسك +وأمشي +وأمضى +وأمضيت +وأمضيتُ +وأمضينا +وأمعنت +وأمعنوا +وأمكث +وأمكن +وأمكنك +وأمكنهم +وأمل +وأملاً +وأمله +وأملي +وأمليت +وأمنا +وأمنه +وأمنهم +وأمنياً +وأمنية +وأمنيتي +وأمه +وأمها +وأمهات +وأمهاتهم +وأمهم +وأمواجه +وأموالاً +وأموالها +وأمي +وأمية +وأمير +وأميرة +وأميل +وأمين +وأمينا +وأن +وأنا +وأناة +وأناس +وأناسه +وأناشيده +وأناعلى +وأناقة +وأناهيد +وأنت +وأنتج +وأنتجت +وأنتجوا +وأنتصر +وأنتظر +وأنتم +وأنتما +وأنتهي +وأنتِ +وأنثى +وأنجب +وأنجز +وأنجعها +وأنحاء +وأندريه +وأندية +وأنذر +وأنزلت +وأنزله +وأنساق +وأنسته +وأنشأ +وأنشأت +وأنشأوا +وأنشئت +وأنشد +وأنشر +وأنشطة +وأنشطتها +وأنصار +وأنصارهم +وأنصاف +وأنضر +وأنطاكية +وأنطون +وأنظر +وأنظمة +وأنظمتها +وأنف +وأنفسهم +وأنفض +وأنفع +وأنفه +وأنقاهم +وأنقل +وأنك +وأنكرت +وأنم +وأنماط +وأنماطها +وأننا +وأنني +وأنه +وأنها +وأنهض +وأنهم +وأنهما +وأنهوا +وأنهى +وأنواع +وأنواعاً +وأنواعه +وأنواعها +وأنور +وأنى +وأني +وأنياب +وأنياباً +وأنيابها +وأنّى +وأنَّ +وأهالي +وأهداف +وأهدافنا +وأهدافه +وأهدافها +وأهدافهم +وأهداها +وأهديها +وأهرع +وأهفو +وأهل +وأهلك +وأهله +وأهلها +وأهلية +وأهم +وأهمله +وأهمها +وأهمية +وأهميته +وأهميتها +وأهوائه +وأوائل +وأواخر +وأواصر +وأوافيه +وأوان +وأوباش +وأوتي +وأوجاعه +وأوجاعها +وأوجزهم +وأوجه +وأوجين +وأودعت +وأودعهم +وأودعوه +وأوراق +وأوراقي +وأوربا +وأوربي +وأورث +وأورجواي +وأورد +وأوروبا +وأوروبية +وأوسع +وأوسمة +وأوشك +وأوصلها +وأوصى +وأوضاع +وأوضح +وأوضحت +وأوضحهم +وأوعز +وأوعزت +وأوفدت +وأوقعوا +وأوقف +وأوقفه +وأوقفوا +وأوكلت +وأول +وأولئك +وأولاده +وأولادها +وأولاها +وأولاهم +وأولبرايت +وأوله +وأولها +وأولهم +وأولوياتها +وأولى +وأولياء +وأوليائه +وأوهاما +وأوهامي +وأي +وأيا +وأيام +وأيامنا +وأيامهم +وأياً +وأية +وأيد +وأيدت +وأيديهم +وأيديولوجيا +وأيديولوجيات +وأيرلندا +وأيسر +وأيضا +وأيضاً +وأيضًا +وأيمن +وأين +وأينما +وأيها +وأيهما +وأيّ +وأيّا +وأيّدني +وأَمَّا +وأُدخلت +وأُشْرِبتها +وأُطلِقَ +وأُعدَّ +وأُعطي +وأُقفل +وأُلبِست +وأُلحقت +وإباضية +وإبان +وإبحار +وإبداع +وإبداعات +وإبداعاً +وإبداعنا +وإبداعه +وإبداعية +وإبراز +وإبراهيم +وإبطالها +وإبعاد +وإبقاء +وإبقاءها +وإبهاراً +وإتاحة +وإتقان +وإتقانهم +وإتلافه +وإتمام +وإثابة +وإثارة +وإثبات +وإثباتها +وإثر +وإثراء +وإثرائها +وإثنية +وإثيوبيا +وإجاص +وإجراء +وإجراءات +وإجرائنا +وإجمالاً +وإجمالي +وإحاطاته +وإحباط +وإحداث +وإحداثها +وإحدى +وإحساس +وإحساسه +وإحساسي +وإحسان +وإحلال +وإحياء +وإحيائه +وإخاء +وإخبارها +وإخراج +وإخراجه +وإخراجها +وإخراجهم +وإخراجي +وإخفاء +وإخفاق +وإخفاقه +وإخلاص +وإخلاصها +وإخوانك +وإخواننا +وإخوانه +وإخوته +وإخوتي +وإدارات +وإداراتها +وإدارة +وإدارت +وإدارته +وإدارتها +وإداري +وإداريين +وإدخال +وإدراج +وإدراك +وإدراكهم +وإدراكي +وإدماج +وإدمان +وإدوار +وإذ +وإذا +وإذن +وإرادته +وإراقة +وإرثها +وإرساء +وإرسال +وإرسالي +وإرشاد +وإرشادات +وإرهاق +وإريتريا +وإزاء +وإزاحة +وإزالة +وإزمان +وإزهاق +وإسبانيا +وإسرائيل +وإسرائيلية +وإسقاط +وإسقاطاتها +وإسلام +وإسلامي +وإسلامية +وإسلاميّه +وإسلاميًّا +وإسماعيل +وإسهامها +وإشارات +وإشاعاتهم +وإشاعة +وإشراق +وإشراقا +وإصابة +وإصدار +وإصدارها +وإصلاح +وإصلاحها +وإصلاحيات +وإضاءة +وإضافاته +وإضافة +وإضافية +وإضراراً +وإضرارها +وإضفاء +وإطارات +وإطعام +وإطلاع +وإطلاعه +وإطلاعهم +وإطلاق +وإطلاقه +وإطلاقها +وإطلالة +وإظهار +وإظهارها +وإعادة +وإعاشة +وإعاقة +وإعاقته +وإعانة +وإعجاب +وإعجابه +وإعجابي +وإعداد +وإعداده +وإعدادها +وإعزاز +وإعطاء +وإعطاؤها +وإعفاء +وإعفاؤهم +وإعلاء +وإعلامية +وإعلاميين +وإعلان +وإعلانات +وإعلانية +وإفرازات +وإفريقيا +وإفريقية +وإفساح +وإفساد +وإفطار +وإقامة +وإقامته +وإقبال +وإقبالاً +وإقرار +وإقصاءه +وإقفال +وإقليم +وإقليمياً +وإقليمية +وإقناع +وإقناعك +وإقناعه +وإكثار +وإكساب +وإكسابهن +وإكسل +وإكمال +وإلا +وإلاّ +وإلاَّ +وإلباس +وإلحاحه +وإلحاق +وإلحاقاً +وإلحاقهن +وإلزام +وإلصاق +وإلقاء +وإلكترونية +وإلهام +وإلهي +وإلهية +وإلى +وإلي +وإليك +وإليكم +وإليه +وإليها +وإم +وإما +وإماء +وإماراتها +وإمام +وإمامها +وإمبراطوره +وإمدادها +وإمدادهم +وإمكان +وإمكانات +وإمكاناتك +وإمكاناته +وإمكاناتها +وإمكانيات +وإمكانياتها +وإمكانية +وإملاءات +وإملاءٍ +وإميل +وإن +وإناث +وإنارتها +وإنت +وإنتاج +وإنتاجا +وإنتاجه +وإنتاجي +وإنتاجياتها +وإنتاجية +وإنتو +وإنجاب +وإنجاز +وإنجازات +وإنجازاته +وإنجازاتها +وإنجلترا +وإندونيسيا +وإنزيمات +وإنساناً +وإنسانياً +وإنسانية +وإنسانيته +وإنسانيتها +وإنشاء +وإنشائية +وإنشادًا +وإنصافا +وإنطاق +وإنعاش +وإنعاشي +وإنـما +وإنفاق +وإنقاذ +وإنما +وإننا +وإنني +وإنه +وإنها +وإنهائها +وإني +وإنْ +وإهانة +وإهمال +وإهمالنا +وإيابا +وإياباً +وإياكم +وإياه +وإياهم +وإيجابا +وإيجابي +وإيجابية +وإيجاد +وإيداعه +وإيذاء +وإيراداتها +وإيران +وإيزابيلا +وإيضاحه +وإيطاليا +وإيطالية +وإيطاليين +وإيقاعات +وإيقاعاتها +وإيقاعه +وإيقاعية +وإيقاف +وإيلامه +وإيمان +وإيماناً +وإيمانه +وإيميل +وإيواء +وإيوان +وا +واءمة +واب +وابتدأ +وابتسامة +وابتسامتكِ +وابتسامته +وابتسم +وابتسمت +وابتعاث +وابتعادها +وابتعادهم +وابتعث +وابتعد +وابتكار +وابتكاراتها +وابتكاراً +وابتكر +وابتكرت +وابتلاء +وابتلاع +وابتلاعها +وابحثي +وابعاد +وابل +وابن +وابنة +وابنتها +وابنه +وابنها +وابني +وات +واتباع +واتباعه +واتبعته +واتت +واتجاه +واتجاهات +واتجاهاته +واتجاهاتهم +واتجاهه +واتجه +واتجهنا +واتحاد +واتخاذ +واتخاذها +واتخذ +واتخذوا +واتزانها +واتساع +واتساعاً +واتساعها +واتساقاً +واتساقًا +واتسعت +واتصاف +واتصال +واتصل +واتصلت +واتضح +واتفاقيات +واتفاقية +واتفق +واتفقنا +واتقانها +واتقوا +واتمايلي +واتهام +واتهم +واتهمنى +واتهمه +واتهمهما +واتهموه +واتهموها +واتِّخاذه +واثاره +واثبتت +واثق +واثقاً +واثقة +واثقون +واثقين +واثناء +واثنان +واثنتين +واجب +واجبات +واجباته +واجباتها +واجباتي +واجبكم +واجبه +واجبي +واجتاحت +واجتاز +واجتذبت +واجترار +واجتم +واجتماعي +واجتماعيا +واجتماعياً +واجتماعية +واجتماعيون +واجتماعيًا +واجتمع +واجتناب +واجتهاد +واجتهاداته +واجتياحهم +واجداً +واجعلنا +واجعله +واجمون +واجنر +واجه +واجهات +واجهاتها +واجهة +واجهت +واجهته +واجهتها +واجهوا +واحات +واحاتنا +واحة +واحت +واحتاج +واحتجان +واحتجزته +واحتداد +واحترار +واحترام +واحتراماً +واحترامه +واحترامها +واحترامي +واحترامًا +واحترفت +واحتضنتها +واحتفال +واحتفالية +واحتفظت +واحتفل +واحتفى +واحتكار +واحتلالنا +واحتلت +واحتمال +واحتمالات +واحتمالاته +واحته +واحتوائها +واحتوى +واحتياج +واحتياجات +واحتياجاته +واحتُفظ +واحد +واحدا +واحداً +واحداَ +واحدة +واحده +واحدًا +واحدٍ +واحساس +واحصلوا +واحـة +واحـد +واحـداً +واحـدة +واحيائه +واختار +واختارت +واختارته +واختارني +واختاره +واختارها +واختاروا +واختبآ +واختتم +واختتمت +واختتمها +واختراعاته +واختراعه +واخترت +واخترنا +واختزال +واختزنها +واختصارها +واختطت +واختفاء +واختفائها +واختفى +واختلاط +واختلاف +واختلافات +واختلافنا +واختلط +واختلف +واختنقت +واختيار +واختياره +واختير +واختيرت +واخرج +واخضاع +واخفاقات +واد +وادحضي +وادخار +وادع +وادعة +وادعت +وادى +وادي +واديها +واديهم +وادّخار +وادٍّ +واذا +واذكر +وار +وارتأت +وارتباط +وارتباطا +وارتباطه +وارتباطها +وارتباك +وارتباكي +وارتبط +وارتبطت +وارتجاف +وارتجفت +وارتجي +وارتح +وارتحاله +وارتخاء +وارتداء +وارتدادات +وارتدت +وارتدوا +وارتسمتْ +وارتعدت +وارتفاع +وارتفاعا +وارتفاعه +وارتفاعها +وارتفع +وارتفعت +وارتقاء +وارتقت +وارتكبت +وارتوائها +وارتياح +وارتياده +وارد +واردا +وارداتها +واردة +وارسم +وارسو +وارض +وارفة +وارقدت +وارنر +وازداد +وازدادت +وازدانت +وازدحامها +وازدراء +وازدهاراً +وازدهر +وازدهرت +وازدياد +واسأل +واسإله +واست +واستأذن +واستأذنت +واستأنسوا +واستئصال +واستباحة +واستبدال +واستبداله +واستبدالها +واستبدّ +واستبطان +واستتبع +واستثمارها +واستثمرته +واستثني +واستجابة +واستجابت +واستجابتهم +واستجار +واستجداء +واستجلاء +واستجمعت +واستجوبتهم +واستحسانها +واستحسانًا +واستحقت +واستحللتم +واستخدام +واستخدامه +واستخدامها +واستخدم +واستخدمت +واستخدموه +واستخراج +واستخراجها +واستخفى +واستخلاص +واستخلصوا +واستدار +واستدارت +واستدرجوه +واستدعاء +واستدعى +واستراتيجية +واسترداد +واسترعت +واستزادة +واستشاط +واستشرائه +واستشرافا +واستشهد +واستصلاح +واستضافته +واستضعفوه +واستطاع +واستطاعت +واستطاعوا +واستطعت +واستطعنا +واستطلاع +واستطيع +واستعاد +واستعادة +واستعادتها +واستعان +واستعد +واستعداد +واستعدادات +واستعدادنا +واستعداده +واستعدادها +واستعدادهم +واستعدادي +واستعدت +واستعدته +واستعرتها +واستعرض +واستعمال +واستعماله +واستعمالها +واستعملوه +واستعينوا +واستفتاء +واستفحال +واستفدت +واستقام +واستقامة +واستقبال +واستقبالهم +واستقبل +واستقبلنا +واستقدم +واستقر +واستقرار +واستقرارها +واستقرت +واستقصاء +واستقطاب +واستقطب +واستقل +واستقلال +واستقلالها +واستقلالية +واستكانة +واستكمال +واستكمالاً +واستكمل +واستكملوا +واستلاب +واستلقيت +واستلهامهما +واستمالت +واستمتعتم +واستمدت +واستمر +واستمرار +واستمراره +واستمرارها +واستمرت +واستمرفي +واستمرّوا +واستمسكت +واستمطروا +واستمع +واستمعت +واستمعنا +واستناداً +واستناده +واستنادًا +واستنارة +واستنتاج +واستنتاجاته +واستنتج +واستنتجوا +واستنزفت +واستنساخ +واستنشق +واستنفار +واستنفدت +واستنكاراً +واستنكر +واستهتار +واستهجان +واستهدافاته +واستهلاك +واستهلاكها +واستهلاكية +واستهلالاً +واستهنت +واستهوتهم +واستوحي +واستوديوهات +واستوطن +واستوطنوا +واستوعب +واستوعبت +واستوعبتها +واستولت +واستولوا +واستولى +واستيراد +واستيعاب +واستيعابه +واستيقظ +واستيقظت +واستيلاء +واستيلائه +واستُبدلت +واسط +واسطبلات +واسطة +واسع +واسعا +واسعاً +واسعة +واسعي +واسعًا +واسكتشات +واسكتلندا +واسكندر +واسم +واسماه +واسماً +واسمه +واسمها +واسيتات +واسيدا +واشتد +واشتداد +واشتدت +واشتراطات +واشتراكيته +واشترط +واشترطت +واشترك +واشتروا +واشترى +واشتريت +واشتعلت +واشتمل +واشتهر +واشتهرت +واشتُهر +واشحذوا +واشنطن +واصبح +واصبحوا +واصطحب +واصطحبني +واصطحبونا +واصعد +واصف +واصفا +واصفاً +واصل +واصلا +واصلة +واصلت +واصلتا +واصلوا +واضح +واضحا +واضحاً +واضحة +واضحةً +واضحـة +واضحين +واضحًا +واضرب +واضطر +واضطراب +واضطرابات +واضطراري +واضطرام +واضطرت +واضطررت +واضع +واضعاً +واضعو +واضعي +واضعين +واضعيها +واضعًا +واط +واطلاعاتهم +واطلاعه +واطلب +واطلع +واطلعت +واطلعوا +واطمأنت +واطمئنان +واع +واعتبار +واعتبارات +واعتبر +واعتبرت +واعتبرته +واعتبرتها +واعتبروا +واعتبروها +واعتداد +واعتداده +واعتدال +واعتدوا +واعتذر +واعترافا +واعترته +واعترف +واعترفت +واعترفوا +واعتزاز +واعتصموا +واعتقادهم +واعتقال +واعتقالات +واعتقالها +واعتقد +واعتقدت +واعتقل +واعتقلوه +واعتكافها +واعتماد +واعتمدت +واعتنق +واعد +واعدا +واعدة +واعذريني +واعظا +واعلم +واعيا +واعية +واعٍ +واف +وافتتاحه +وافتتح +وافتتحت +وافتتحه +وافتخر +وافتراءات +وافترشا +وافترض +وافترقا +وافتقاد +وافتقد +وافتقده +وافته +وافدة +وافدون +وافر +وافرا +وافرة +وافق +وافقت +وافية +وافٍ +واقتحام +واقتحمته +واقتدار +واقتراح +واقتران +واقترب +واقتربت +واقتربنا +واقتربَ +واقترح +واقترحت +واقتصاداً +واقتصادى +واقتصادي +واقتصاديا +واقتصاديات +واقتصادياتها +واقتصادياً +واقتصادية +واقتصاديًا +واقتصرت +واقتلاع +واقتنع +واقتنعت +واقتنوا +واقرأ +واقع +واقعا +واقعاً +واقعة +واقعةً +واقعنا +واقعها +واقعي +واقعيا +واقعياً +واقعية +واقعًا +واقفا +واقفاً +واقفة +واقفين +واقفٌ +واقي +واقيًا +واقٍ +واكب +واكبت +واكتئاب +واكتساب +واكتسابهم +واكتسب +واكتسبت +واكتشاف +واكتشافاتها +واكتشافي +واكتشف +واكتشفت +واكتشفوا +واكتفت +واكتفى +واكتفيت +واكتمل +واكتملت +واكد +وال +والآباء +والآبار +والآثار +والآجر +والآخر +والآخرة +والآخرون +والآداب +والآراء +والآراميون +والآزوت +والآسيويين +والآشوري +والآشوريين +والآفات +والآلات +والآليات +والآلية +والآمال +والآن +والآنية +والآيات +والآيس +والأب +والأباطيل +والأبحاث +والأبخرة +والأبراج +والأبطال +والأبعاد +والأبعد +والأبقار +والأبناء +والأبنية +والأبهاء +والأبواب +والأبيض +والأتراك +والأثاث +والأثر +والأثري +والأثرياء +والأثرية +والأجانب +والأجبان +والأجداد +والأجدى +والأجزاء +والأجسام +والأجمل +والأجناس +والأجنبي +والأجنبية +والأجنة +والأجنحة +والأجنحـة +والأجهزة +والأجواء +والأجوبة +والأحاديث +والأحاسيس +والأحافير +والأحجار +والأحجام +والأحد +والأحداث +والأحذية +والأحزاب +والأحزان +والأحصنة +والأحفاد +والأحكام +والأحلام +والأحوال +والأحياء +والأخ +والأخت +والأختام +والأخذ +والأخرى +والأخشاب +والأخضر +والأخطاء +والأخلاق +والأخلاقي +والأخلاقية +والأخوة +والأخوّة +والأخير +والأخيرة +والأخيرةُ +والأخيرَ +والأداء +والأدب +والأدباء +والأدبي +والأدبيات +والأدبية +والأدعية +والأدق +والأدوات +والأدوار +والأدوية +والأديان +والأديب +والأديرة +والأذرة +والأذكار +والأذن +والأذواق +والأراجوز +والأراضي +والأرامل +والأرباح +والأربعين +والأربعينيات +والأرجل +والأرجنتين +والأرحام +والأردن +والأردنيين +والأرض +والأرنب +والأرياف +والأزرار +والأزرق +والأزقة +والأزليج +والأزمات +والأزمان +والأزمنة +والأزياء +والأسئلة +والأسابيع +والأسابيعُ +والأساتذة +والأساسي +والأساسية +والأساطير +والأساطيل +والأساقفة +والأساليب +والأسباب +والأسبانية +والأستاذ +والأستاذة +والأسخف +والأسد +والأسرار +والأسرة +والأسرية +والأسطورة +والأسطوري +والأسطورية +والأسطول +والأسعار +والأسقف +والأسلاك +والأسلحة +والأسلوب +والأسماء +والأسماع +والأسماك +والأسمدة +والأسمر +والأسمنت +والأسنان +والأسوأ +والأسوار +والأسواق +والأسود +والأسّ +والأشبه +والأشجار +والأشخاص +والأشرار +والأشرطة +والأشعار +والأشعة +والأشكال +والأشهر +والأشواق +والأشياء +والأصابع +والأصالة +والأصداء +والأصداف +والأصدقاء +والأصعب +والأصفر +والأصوات +والأضرحة +والأطباء +والأطباق +والأطر +والأطروحات +والأطعمة +والأطفال +والأطلال +والأطماع +والأظافر +والأعاصير +والأعجب +والأعداء +والأعراس +والأعراض +والأعراف +والأعراق +والأعصاب +والأعضاء +والأعلام +والأعلى +والأعم +والأعمال +والأعمام +والأعوام +والأعياد +والأعيان +والأفئدة +والأفارقة +والأفراح +والأفراد +والأفران +والأفريقي +والأفعال +والأفق +والأفقية +والأفكار +والأفلام +والأفوات +والأقارب +والأقاليم +والأقباط +والأقبية +والأقداح +والأقدار +والأقدام +والأقراص +والأقراط +والأقسى +والأقصر +والأقصى +والأقطار +والأقل +والأقلام +والأقمار +والأقمشة +والأقوات +والأقواس +والأقوال +والأقوياء +والأكاديمي +والأكاديميات +والأكاديمية +والأكاديميين +والأكثر +والأكزيما +والأكسجين +والأكل +والأكلات +والأكواع +والألبان +والألباني +والألحان +والألعاب +والألف +والألفبائية +والألفة +والألم +والألمان +والألماني +والألمانية +والألوان +والألومنيوم +والأمازون +والأماسي +والأماكن +والأمان +والأمانة +والأمة +والأمتعة +والأمثال +والأمثلة +والأمر +والأمراء +والأمراض +والأمران +والأمريكى +والأمريكي +والأمريكية +والأمريكيين +والأمسيات +والأمطار +والأمكنة +والأمل +والأملاح +والأمم +والأممية +والأمن +والأمني +والأمنية +والأمهات +والأموات +والأمواج +والأموال +والأمور +والأمي +والأمير +والأميركية +والأمين +والأمينية +والأناجيل +والأناقة +والأناهيد +والأنبوبة +والأنثروبولوجيا +والأنثى +والأندلس +والأندلسي +والأندية +والأنسجة +والأنسنة +والأنشطة +والأنصار +والأنظمة +والأنف +والأنفاس +والأنفاق +والأنفس +والأنفليد +والأنهار +والأنوار +والأنواع +والأنوثة +والأنين +والأهالي +والأهرامات +والأهل +والأهلي +والأهلية +والأهم +والأهمية +والأواني +والأوبئة +والأوبريتات +والأوحال +والأوحد +والأودية +والأوراد +والأوراق +والأوربي +والأوربية +والأوربيون +والأوربيين +والأورج +والأوردية +والأوروبية +والأوز +والأوساخ +والأوسط +والأوضاع +والأوكسجين +والأول +والأولاد +والأولوية +والأولياء +والأوهام +والأيام +والأيديولوجي +والأيديولوجيا +والأيديولوجيات +والأيديولوجية +والإبداع +والإبداعية +والإبرة +والإبعاد +والإبل +والإتاوات +والإتجار +والإتصالات +والإتقان +والإتيان +والإثارة +والإثنية +والإجابة +والإجازات +والإجراءات +والإجهاد +والإجهاض +والإحباط +والإحساس +والإحسان +والإحصاءات +والإحصائيات +والإخاء +والإخراج +والإخلاص +والإخوان +والإدارات +والإدارة +والإداري +والإداريات +والإدارية +والإداريين +والإدراك +والإذاعات +والإذاعي +والإذاعية +والإرادة +والإرشاد +والإرشادات +والإرشادية +والإرهاب +والإرهابيين +والإرهاق +والإزدهار +والإسبان +والإسبانية +والإستراتيجيات +والإستقرار +والإستين +والإسرائيلية +والإسرائيليين +والإسطبل +والإسفراييني +والإسكان +والإسكندرية +والإسكواش +والإسلام +والإسلامي +والإسلامية +والإسلاميون +والإسلاميين +والإسهاب +والإسهال +والإسهام +والإسهامات +والإشادة +والإشارة +والإشاعات +والإشراف +والإشعاع +والإشكاليات +والإشهار +والإصابات +والإصحاح +والإصرار +والإصراروالمثابرة +والإصلاح +والإصلاحية +والإضافة +والإضافية +والإضرار +والإطلاع +والإعادة +والإعاشة +والإعاشية +والإعانات +والإعانة +والإعجاب +والإعدادية +والإعدام +والإعصار +والإعلام +والإعلامي +والإعلاميات +والإعلامية +والإعلاميين +والإعلان +والإعلانات +والإعمار +والإفتاء +والإفريقية +والإفساح +والإقامة +والإقبال +والإقتصادية +والإقدام +والإقصاء +والإقطاع +والإقليمية +والإقواء +والإكثار +والإلكترونيات +والإلهام +والإلهية +والإمارات +والإمبراطور +والإمبراطورية +والإمبريالية +والإمعان +والإمكانات +والإمكانيات +والإناث +والإناسة +والإنتاج +والإنتاجي +والإنتاجية +والإنترنت +والإنجاب +والإنجاز +والإنجازات +والإنجليزية +والإنجيل +والإندونيسية +والإنزيمات +والإنس +والإنسان +والإنساني +والإنسانيات +والإنسانية +والإنشائية +والإنشاد +والإنصاف +والإنضاج +والإنفاق +والإنماء +والإياب +والإيثار +والإيدز +والإيراني +والإيطالية +والإيفادات +والإيقاع +والإيقاعات +والإيلام +والإيمان +والا +والابتسامات +والابتعاد +والابتكار +والابتكارات +والابتهاج +والابتهالات +والابن +والابنة +والاتجار +والاتجاه +والاتجاهات +والاتحاد +والاتحادات +والاتساع +والاتصال +والاتصالات +والاتصالية +والاتفاق +والاتفاقيا +والاتفاقيات +والاتهام +والاتهامات +والاتهامـات +والاثنية +والاجتماع +والاجتماعي +والاجتماعيات +والاجتماعية +والاجتهاد +والاجتهادات +والاجتهادي +والاجراء +والاحاديث +والاحتجاج +والاحترافية +والاحترام +والاحتفاء +والاحتفاظ +والاحتفالات +والاحتقار +والاحتكاكات +والاحتكام +والاحتلال +والاحتماء +والاحتمال +والاحتمالات +والاحتياج +والاحتياجات +والاختبارات +والاختراعات +والاختزالية +والاختصار +والاختفاء +والاختلاط +والاختلاف +والاختلالات +والاختيار +والاختيارات +والادعاء +والارتباط +والارتباك +والارتشاف +والارتفاع +والارتقاء +والازدراء +والازدهار +والاستئثار +والاستباحة +والاستثمار +والاستثمارى +والاستثمارية +والاستثناء +والاستجابة +والاستجمام +والاستخدام +والاستخدامات +والاستخفاف +والاستدلالات +والاستراتيجية +والاسترخاء +والاستسلام +والاستشراق +والاستشعار +والاستشفاء +والاستطلاع +والاستعاضة +والاستعانة +والاستعداد +والاستعراب +والاستعلامات +والاستعمار +والاستعماري +والاستعمارية +والاستفادة +والاستفسارات +والاستقالات +والاستقامة +والاستقدام +والاستقرار +والاستقصاء +والاستقلال +والاستقلالية +والاستكشاف +والاستكشافات +والاستكشافي +والاستمتاع +والاستمرار +والاستمرارية +والاستهتار +والاستهداء +والاستهلاك +والاستيعاب +والاستيلاء +والاسكندرية +والاسم +والاشاعات +والاشتراكية +والاشتهاء +والاشمئزاز +والاضحكاك +والاضطرابات +والاضطراري +والاضطهاد +والاطفال +والاطلاع +والاطمئنان +والاعتبار +والاعتداء +والاعتذار +والاعتراف +والاعترافات +والاعتصام +والاعتقاد +والاعتقال +والاعتماد +والاعدادي +والافتتان +والافتراق +والافتعال +والافتقار +والاقتحامات +والاقتصاد +والاقتصادي +والاقتصادية +والاقتصاديين +والاكتئاب +والاكتشاف +والاكتشافات +والاكتفاء +والالتزام +والالتزامات +والالتقاء +والامتحانات +والامتنان +والانبعاث +والانتحار +والانتساب +والانتشار +والانتصار +والانتظار +والانتقال +والانتقام +والانتماء +والانجراف +والانجليزية +والانحدار +والانحراف +والانحلال +والانحناءات +والانحياز +والانخفاض +والاندثار +والاندفاع +والاندماج +والانسجام +والانسحاب +والانسلاخ +والانسيابية +والانشطار +والانصراف +والانضباط +والانطباعات +والانطلاق +والانطواء +والانعزال +والانفاق +والانفتاح +والانفجار +والانفراد +والانفصال +والانفضاض +والانفعال +والانقراض +والانقسامات +والانقياد +والانكسار +والانكفاء +والانهيار +والاهتمام +والاهتمامات +والاهم +والبؤس +والبائعين +والباب +والبابلي +والباحة +والباحث +والباحثون +والباحثين +والبارود +والباستيليا +والباسل +والباطنة +والباعة +والباقون +والباقي +والباكستاني +والباكستانية +والباكستانيين +والباكية +والباليه +والبامبو +والبتر +والبتروكيماويات +والبحاثة +والبحار +والبحتري +والبحث +والبحر +والبحرى +والبحرية +والبحرين +والبحريني +والبحوث +والبحيرات +والبخور +والبدء +والبداية +والبدلة +والبدنية +والبديل +والبذل +والبر +والبرازيل +والبراعم +والبراق +والبرامج +والبرانس +والبراني +والبراهين +والبربري +والبربرية +والبرتقال +والبرتقالي +والبرج +والبرد +والبرديات +والبرك +والبركة +والبرلمان +والبرنامج +والبرنوس +والبرهان +والبرهنة +والبروتين +والبروتينات +والبروز +والبروستاتا +والبروفيسور +والبرية +والبريثرويدات +والبريد +والبريطاني +والبريطانية +والبس +والبساتين +والبساطة +والبسطاء +والبسيط +والبشر +والبشير +والبصر +والبصرة +والبصري +والبصرية +والبصيرة +والبضائع +والبطاطا +والبطاطس +والبطاقة +والبطالة +والبطانة +والبطيخ +والبعثات +والبعد +والبعض +والبعيد +والبعيدة +والبق +والبقاء +والبقايا +والبقطرياني +والبقع +والبقعة +والبقلاوة +والبكتيريا +والبكم +والبلابل +والبلاد +والبلاستك +والبلاستيك +والبلاستيكية +والبلاهة +والبلايا +والبلد +والبلدان +والبلدة +والبلعوم +والبلورات +والبلورية +والبلوز +والبلياردو +والبن +والبناء +والبنائين +والبنات +والبنطال +والبنك +والبنوك +والبنى +والبني +والبنية +والبهائم +والبهارات +والبهجة +والبهلوان +والبهي +والبواخر +والبوسنة +والبوصلة +والبوفيهات +والبولوفوني +والبوليس +والبوليمرات +والبوم +والبويضات +والبيئات +والبيئة +والبيئي +والبيئية +والبيارق +والبيان +والبيانات +والبيانو +والبيت +والبيداءُ +والبيرة +والبيروني +والبيزنطيين +والبيض +والبيضاء +والبيع +والبيعية +والبيمارستانات +والبيوت +والبيولوجيا +والبيولوجية +والبيّاتي +والبِلَى +والت +والتآخي +والتآليف +والتأثر +والتأثير +والتأثيرات +والتأخر +والتأدب +والتأريخ +والتأسيس +والتأقلم +والتأكد +والتأكيد +والتأليف +والتأمل +والتأمين +والتأييد +والتائبين +والتابو +والتاريخ +والتاريخي +والتاريخية +والتبادل +والتباكي +والتباين +والتبدلات +والتبدّل +والتبرم +والتبريكات +والتبشير +والتبصر +والتبعية +والتبـصر +والتبيين +والتتري +والتثاقف +والتثقيف +والتثقيفي +والتجأ +والتجاذب +والتجار +والتجارب +والتجارة +والتجارى +والتجارية +والتجاريين +والتجاهل +والتجاوز +والتجدد +والتجديد +والتجديدات +والتجدّد +والتجذر +والتجربة +والتجرد +والتجريب +والتجريبية +والتجريد +والتجسس +والتجلد +والتجمعات +والتجميل +والتجهم +والتجهيز +والتجهيزات +والتجهيل +والتجوال +والتجويد +والتجويع +والتحادث +والتحالف +والتحامل +والتحاور +والتحايل +والتحدث +والتحدي +والتحديات +والتحديث +والتحرر +والتحرك +والتحركات +والتحرير +والتحريف +والتحريفات +والتحريم +والتحسس +والتحصيل +والتحصينات +والتحضر +والتحف +والتحفظي +والتحق +والتحقت +والتحقوا +والتحقيق +والتحقيقات +والتحكم +والتحليل +والتحليلات +والتحمل +والتحول +والتحولات +والتحوّلات +والتحيز +والتحّور +والتخريب +والتخريشية +والتخزين +والتخصص +والتخصصات +والتخطيط +والتخفي +والتخلص +والتخلف +والتخلي +والتخوف +والتداعيات +والتدبر +والتدبير +والتدخل +والتدخين +والتدريب +والتدريس +والتدقيق +والتدمير +والتدني +والتدوين +والتدين +والتذكير +والتر +والترابط +والتراتبية +والتراث +والتراجع +والتراجم +والتراحم +والتربة +والتربوي +والتربوية +والتربية +والترتيب +والترتيبات +والترجمة +والترحال +والترخيص +والتردد +والترع +والترف +والترفية +والترفيه +والترفيهية +والترقب +والترقي +والترقيع +والترقيم +والتركة +والتركمان +والتركي +والتركيبات +والتركيبة +والتركيز +والترميم +والترهيب +والترويج +والترويجية +والترويح +والتزاما +والتزامي +والتزكية +والتزلج +والتزم +والتزمت +والتزمني +والتزوير +والتزويق +والتزييف +والتزيين +والتسامح +والتستر +والتسجيل +والتسديد +والتسعينيات +والتسلح +والتسلط +والتسلية +والتسمُّم +والتسهيلات +والتسوق +والتسويق +والتسويقية +والتسيّب +والتشاؤم +والتشابك +والتشاور +والتشجيع +والتشخيصات +والتشرد +والتشريح +والتشريعات +والتشريعي +والتشظّي +والتشكك +والتشكيل +والتشهير +والتشويق +والتشويه +والتشيك +والتشييء +والتشييد +والتصاريح +والتصاعد +والتصاميم +والتصحيح +والتصدق +والتصدير +والتصقت +والتصلب +والتصميم +والتصميمات +والتصنيع +والتصورات +والتصوف +والتصوير +والتصوّرات +والتضافر +والتضامن +والتضحية +والتضخيم +والتضرع +والتضرعات +والتضلع +والتطابقِ +والتطبيق +والتطبيقات +والتطبيقية +والتطرف +والتطفل +والتطلع +والتطهير +والتطور +والتطورات +والتطوير +والتعارف +والتعالي +والتعاليم +والتعامل +والتعاون +والتعاويذ +والتعب +والتعبئة +والتعبير +والتعبيرات +والتعثر +والتعجب +والتعجيل +والتعددية +والتعديل +والتعذيب +والتعرف +والتعرية +والتعريف +والتعرّف +والتعرُّض +والتعصب +والتعطيل +والتعظيم +والتعــــاطف +والتعقيد +والتعقيدات +والتعلق +والتعلم +والتعلمية +والتعليق +والتعليم +والتعليمات +والتعليمية +والتعمق +والتعويل +والتعيين +والتفاؤل +والتفاتة +والتفاصيل +والتفاعل +والتفاف +والتفاكر +والتفاني +والتفاهم +والتفاوض +والتفت +والتفتت +والتفتح +والتفتنا +والتفتّح +والتفجير +والتفرد +والتفرقة +والتفريع +والتفريعات +والتفسير +والتفكك +والتفكير +والتفكيكية +والتفنن +والتفوق +والتفويض +والتفّ +والتقارب +والتقارير +والتقاليد +والتقانيات +والتقد +والتقدم +والتقدير +والتقديم +والتقريب +والتقسيم +والتقشير +والتقط +والتقطت +والتقعيد +والتقلب +والتقليد +والتقليدية +والتقني +والتقنيات +والتقنية +والتقنيين +والتقوقع +والتقوى +والتقويم +والتقى +والتقينا +والتقييم +والتكاثر +والتكافؤ +والتكامل +والتكايا +والتكبر +والتكبير +والتكبيرات +والتكتلات +والتكريم +والتكليف +والتكنولوجي +والتكنولوجيا +والتكنولوجيات +والتكنولوجية +والتكوين +والتلاحم +والتلاقح +والتلاقي +والتلال +والتلحين +والتلفزة +والتلفزيون +والتلفزيونية +والتلفون +والتلقائية +والتلمذة +والتلوث +والتلوين +والتليد +والتليفزيون +والتماثيل +والتمازج +والتماسيح +والتمتع +والتمثل +والتمثيل +والتمثيليات +والتمثيلية +والتمحيص +والتمر +والتمرد +والتمرس +والتمزقات +والتمسك +والتمهيد +والتمور +والتمويل +والتمويلية +والتموين +والتميز +والتمييز +والتميّز +والتناسلية +والتنافس +والتناقضات +والتنانير +والتنباك +والتنبيه +والتندر +والتنديد +والتنزه +والتنسيق +والتنظير +والتنظيرية +والتنظيم +والتنظيمات +والتنفس +والتنفيذيين +والتنقل +والتنقيب +والتنكيل +والتنموية +والتنمية +والتنوع +والتنوير +والتنوين +والتنويه +والتنوّع +والتهاب +والتهابات +والتهجد +والتهجمات +والتهدئة +والتهديد +والتهريب +والتهميش +والتهوين +والتوابل +والتواريخ +والتوازن +والتواصل +والتواضع +والتوافق +والتوالد +والتوبة +والتوتر +والتوترات +والتوثيق +والتوجس +والتوجه +والتوجهات +والتوجيه +والتوجيهية +والتوجّه +والتوحد +والتوحيد +والتوحيدي +والتوراة +والتوزيع +والتوسع +والتوسعات +والتوسل +والتوصيات +والتوصيلات +والتوصيلية +والتوظيف +والتوعية +والتوفيق +والتوقف +والتى +والتي +والتيار +والتيارات +والتيقظ +والتين +والثأر +والثائر +والثابت +والثالث +والثالثة +والثامن +والثانوي +والثانوية +والثاني +والثانية +والثانيةُ +والثبات +والثبور +والثدييات +والثروات +والثروة +والثعابين +والثعلب +والثقافات +والثقافة +والثقافي +والثقافية +والثقب +والثقة +والثقـافة +والثلاثة +والثلاثون +والثلاثين +والثلاثينيات +والثلج +والثلوج +والثمار +والثمانينيات +والثمرات +والثمينة +والثناء +والثنائي +والثنيات +والثوابت +والثوار +والثور +والثورات +والثورة +والثورية +والثياب +والثيران +والجاحظ +والجاذبية +والجاروف +والجاسوسية +والجامع +والجامعات +والجامعة +والجامعي +والجامعية +والجاه +والجاهلون +والجبال +والجبر +والجبرية +والجبل +والجبلية +والجدال +والجدة +والجدد +والجدران +والجدل +والجدلية +والجدي +والجديد +والجديدة +والجدير +والجديّة +والجذب +والجذل +والجذور +والجرأة +والجرائم +والجراحة +والجراحية +والجرجاوي +والجرح +والجرذان +والجرس +والجريء +والجريح +والجريدة +والجريمة +والجزء +والجزأين +والجزائر +والجزائريان +والجزائرية +والجزار +والجزر +والجزع +والجزيرة +والجسد +والجسدي +والجسدية +والجسم +والجشتية +والجشع +والجعلان +والجفاف +والجلالي +والجلد +والجلسات +والجلود +والجلوس +والجليد +والجليل +والجليلة +والجمادات +والجمارك +والجماعات +والجماعة +والجماعية +والجمال +والجمالية +والجمع +والجمعة +والجمعيات +والجمعية +والجملة +والجمنازيوم +والجمهور +والجمهوري +والجمهوريات +والجمود +والجميع +والجميل +والجميلات +والجميلة +والجنابي +والجندب +والجنس +والجنوب +والجنوبية +والجنود +والجنون +والجنيه +والجهات +والجهاد +والجهاز +والجهد +والجهل +والجهود +والجهوية +والجو +والجوائز +والجوارح +والجواسيس +والجوامع +والجوانب +والجواهري +والجود +والجودة +والجور +والجوع +والجوف +والجولان +والجولوفي +والجوهر +والجوية +والجياد +والجير +والجيش +والجينات +والجينز +والجينية +والجيوب +والجيولوجيا +والجيولوجيين +والحادي +والحارات +والحارس +والحاسبات +والحاسم +والحاسوب +والحاضر +والحاضنَ +والحافز +والحافل +والحافلات +والحاكي +والحال +والحالات +والحالة +والحاملة +والحب +والحبر +والحبوب +والحبور +والحبيب +والحج +والحجاب +والحجارة +والحجاز +والحجب +والحجة +والحجج +والحجر +والحجز +والحجلة +والحجم +والحد +والحدائق +والحداثة +والحدادين +والحدس +والحدود +والحديث +والحديثة +والحديد +والحديدية +والحديقة +والحذر +والحر +والحرائر +والحراب +والحرارة +والحراسة +والحراك +والحرام +والحرب +والحربي +والحربين +والحرص +والحرف +والحرفة +والحرفي +والحرفية +والحرفيين +والحركات +والحركة +والحرمان +والحروب +والحروف +والحروفية +والحروق +والحريات +والحرية +والحرير +والحرّ +والحزب +والحزبان +والحزبيين +والحزن +والحس +والحساب +والحساسية +والحسد +والحسرة +والحسك +والحسن +والحسي +والحسية +والحشائش +والحشرات +والحشرية +والحصاد +والحصار +والحصان +والحصبة +والحصر +والحصول +والحصون +والحض +والحضارات +والحضارة +والحضاري +والحضارية +والحضر +والحط +والحظ +والحـد +والحـدائق +والحـضارة +والحـضارية +والحفاظ +والحفاوة +والحفر +والحفلات +والحفيدتين +والحق +والحقائب +والحقائق +والحقب +والحقوق +والحقوقية +والحقوقيين +والحقول +والحقيبة +والحقيقة +والحقيقيين +والحكاك +والحكام +والحكايات +والحكة +والحكم +والحكماء +والحكمة +والحكومات +والحكومة +والحكومي +والحل +والحلاجين +والحلان +والحلم +والحلول +والحلوى +والحلي +والحليب +والحمار +والحماس +والحماسة +والحمام +والحمامات +والحمامى +والحماية +والحمد +والحمدلله +والحمراء +والحمقاء +والحمل +والحملات +والحمى +والحمية +والحمير +والحمّاد +والحنان +والحنجرة +والحنين +والحواجز +والحوادث +والحوار +والحواريون +والحواريين +والحواس +والحولي +والحوليات +والحويصلات +والحي +والحياء +والحياة +والحية +والحيرة +والحيطة +والحين +والحيوان +والحيوانات +والحيوانى +والحيواني +والحيوانية +والحيوية +والخ +والخائن +والخاتم +والخاتونية +والخارج +والخارجى +والخارجي +والخارجية +والخاص +والخاصة +والخاكي +والخالية +والخامات +والخامس +والخامسة +والخباز +والخبر +والخبراء +والخبرات +والخبرة +والخبز +والختامية +والختمية +والخدمات +والخدماتية +والخدمة +والخدمية +والخديعة +والخديوي +والخراب +والخراجات +والخرافات +والخردوات +والخرسانة +والخرطوم +والخرم +والخروج +والخريجين +والخريف +والخزانات +والخزف +والخزّافين +والخسائر +والخسارة +والخشب +والخصائص +والخصب +والخصوصية +والخصية +والخضار +والخضر +والخضراوات +والخضرة +والخضروات +والخط +والخطاب +والخطابات +والخطاطين +والخطب +والخطباء +والخطر +والخطرة +والخطط +والخطوات +والخطوط +والخطيبة +والخطير +والخفة +والخفيفة +والخفيّ +والخلاب +والخلاص +والخلاصة +والخلافة +والخلايا +والخلجات +والخلط +والخلفاء +والخلفية +والخلق +والخلقية +والخلود +والخليج +والخليجي +والخليجية +والخليجيين +والخليط +والخليفة +والخمائر +والخمس +والخمسون +والخمسين +والخمسينيات +والخنادق +والخوارزمي +والخوارق +والخورنقات +والخوف +والخيار +والخيارات +والخياط +والخياطة +والخياطين +والخيال +والخيالات +والخيانة +والخير +والخيرة +والخيش +والخيل +والخيوط +والد +والدائم +والداخل +والداخلي +والداخلية +والدار +والدارسون +والدارسين +والداعية +والداعين +والدافئة +والدافعية +والداه +والداها +والداي +والدبابات +والدبلوماسي +والدبلوماسية +والدبلوماسيون +والدة +والدته +والدتها +والدتي +والدجاجة +والدجاني +والدخان +والدخل +والدخلاء +والدخول +والدراسات +والدراسة +والدراما +والدراهم +والدراية +والدرج +والدرس +والدروع +والدساكر +والدستورية +والدسمة +والدشت +والدعاء +والدعاة +والدعايات +والدعاية +والدعم +والدعوات +والدعوة +والدفاع +والدفتردار +والدفع +والدفعات +والدفوف +والدفيئة +والدقائق +والدقة +والدقيق +والدقيقة +والدك +والدكتاتورية +والدكتور +والدكتورة +والدكم +والدلافين +والدلال +والدلنج +والدليل +والدم +والدماء +والدمار +والدمام +والدمج +والدمع +والدموع +والدمى +والدنمارك +والدنيا +والدنيوي +والدنيوية +والده +والدها +والدهشة +والدهم +والدهما +والدهون +والدو +والدواء +والدوائر +والدواجن +والدوار +والدوافع +والدودة +والدور +والدوريات +والدوشات +والدول +والدولة +والدولى +والدولي +والدولية +والدومينيك +والدونية +والدوهم +والدى +والدي +والديار +والديانة +والديباج +والديدان +والديك +والديكور +والديمقراطي +والديمقراطية +والديمومة +والدين +والديناميت +والديناميكا +والديناميكية +والديني +والدينية +والديه +والديها +والديهم +والديون +والديّ +والدُه +والدُّرّة +والذئاب +والذات +والذاتية +والذاكرة +والذبابة +والذرائع +والذرة +والذكاء +والذكر +والذكرى +والذكريات +والذل +والذنوب +والذهاب +والذهب +والذهنية +والذهول +والذوبان +والذوق +والذى +والذي +والذين +والرأسمالية +والرأفة +والرأي +والرؤساء +والرؤى +والرؤي +والرؤيا +والرؤية +والرئاسة +والرئاسية +والرئة +والرئيس +والرابع +والراحة +والرازي +والراست +والراعي +والرافضة +والراكب +والراهن +والرب +والربابة +والرباط +والربع +والربلة +والربو +والربيع +والرتوش +والرتيبة +والرجاء +والرجال +والرجل +والرجوع +والرجولة +والرحالة +والرحلات +والرحمة +والرحيق +والرحيل +والرحّالة +والرخامة +والرد +والردة +والردف +والردود +والرذائل +والرزق +والرزين +والرسائل +والرسالة +والرسالي +والرسام +والرسامين +والرسم +والرسمي +والرسمية +والرسوم +والرسومات +والرشاش +والرشاشات +والرشاقة +والرصاص +والرصانة +والرصد +والرصيد +والرصين +والرضا +والرضَّع +والرطوبة +والرعاية +والرعد +والرعي +والرفائين +والرفاهية +والرفد +والرفض +والرفق +والرقابة +والرقص +والرقي +والرقيق +والركع +والركن +والركود +والرمال +والرمان +والرمزية +والرمل +والرموز +والرموش +والرنجة +والرهبة +والروابط +والروابي +والرواج +والروايات +والرواية +والروايتان +والروح +والروحانية +والروحانيين +والروحي +والروحية +والروس +والروسي +والروسية +والروعة +والرومان +والرومانسكية +والرومانسية +والروماني +والرومانية +والرومانيين +والرومنطيقية +والرونق +والروية +والري +والرياح +والرياض +والرياضات +والرياضة +والرياضيات +والرياضية +والريبة +والريح +والريحـــان +والريشة +والريف +والرُها +والرّبح +والرَّضاع +والز +والزائر +والزائرين +والزبد +والزبيب +والزجاج +والزجر +والزحام +والزخارف +والزخرفة +والزراعة +والزراعي +والزراعية +والزرزور +والزرع +والزرنيخ +والزعفران +والزعماء +والزعيم +والزفاف +والزفير +والزقازيق +والزكاة +والزمان +والزماني +والزمانية +والزمرد +والزمن +والزميل +والزنك +والزهاد +والزهد +والزهو +والزهور +والزوابع +والزواج +والزوار +والزوايا +والزوجات +والزوجة +والزوّار +والزي +والزيات +والزيادة +والزيارات +والزيارة +والزيت +والزيتون +والزيتوني +والزير +والزيف +والزين +والزينة +والزيوت +والس +والسؤال +والسائح +والسائحين +والسابع +والسابقين +والساحات +والساحة +والساحرات +والساخرة +والساخنة +والسادس +والساسة +والساعة +والسالمون +والسالمية +والسامي +والسامية +والسب +والسباب +والسبب +والسببية +والسبت +والسبعين +والسبعينيات +والسبق +والسبل +والسبوع +والسبيل +والستين +والستينيات +والسجاد +والسجن +والسحاق +والسحب +والسحر +والسحرة +والسحوبات +والسدسية +والسدود +والسرطان +والسرعة +والسرقة +والسريالي +والسرياني +والسريانية +والسعادة +والسعال +والسعر +والسعودة +والسعودي +والسعودية +والسعي +والسعيد +والســـــنة +والسفر +والسفراء +والسفن +والسفير +والسقف +والسقم +والسقوط +والسكان +والسكانية +والسكتة +والسكر +والسكري +والسكريات +والسكك +والسكن +والسكون +والسكير +والسكين +والسكينة +والسل +والسلاح +والسلاحف +والسلام +والسلامة +والسلبيات +والسلبية +والسلطات +والسلطان +والسلطة +والسلع +والسلم +والسلوان +والسلوك +والسلوكيات +والسلوكية +والسليم +والسليمة +والسماء +والسمات +والسماح +والسماد +والسمان +والسماوات +والسمر +والسمعيات +والسمك +والسمكة +والسمن +والسميط +والسنة +والسند +والسندباد +والسنن +والسنهوري +والسنوات +والسنون +والسنين +والسنّة +والسهر +والسهرات +والسهروردية +والسواتر +والسواح +والسواحل +والسواقي +والسود +والسودان +والسورية +والسوريين +والسوفت +والسوق +والسونا +والسويد +والسيئ +والسيئات +والسياب +والسياح +والسياحة +والسياحـة +والسياحـية +والسياحي +والسياحية +والسيارات +والسيارة +والسياسات +والسياسة +والسياسي +والسياسية +والسياسيون +والسياسيين +والسيخ +والسيد +والسيدة +والسير +والسيرة +والسيطرة +والسيكولوجية +والسيلولوز +والسينما +والسينمائية +والسينمائيين +والسيول +والسيولة +والسيّاح +والسُل +والسَّمْت +والشؤون +والشئون +والشائع +والشاب +والشابات +والشاذ +والشارع +والشاطئ +والشاعر +والشاعرة +والشاعرية +والشاليهات +والشام +والشامخ +والشامل +والشاميات +والشانزيليزيه +والشاهد +والشاي +والشباب +والشباكية +والشبكات +والشبكة +والشبكية +والشتاء +والشتائم +والشتلات +والشتم +والشجاعة +والشجر +والشجرة +والشجيرات +والشحاحير +والشحـن +والشحن +والشحنات +والشخص +والشخصيات +والشخصية +والشخير +والشدو +والشديدة +والشر +والشراء +والشرائح +والشراب +والشراشف +والشراع +والشرايين +والشرب +والشرح +والشرطة +والشرع +والشرفاء +والشرق +والشرقية +والشركات +والشركة +والشروط +والشريعة +والشريف +والشطحات +والشطرنج +والشظايا +والشعائر +والشعاب +والشعارات +والشعب +والشعبي +والشعبية +والشعر +والشعراء +والشعري +والشعرية +والشعوب +والشعور +والشعير +والشفا +والشفاء +والشفط +والشقاء +والشقق +والشك +والشكر +والشكل +والشكلُ +والشكوى +والشلال +والشمس +والشمع +والشمندر +والشمول +والشنطة +والشهادات +والشهادة +والشهد +والشهرة +والشهرستاني +والشهيد +والشوارع +والشواطئ +والشورى +والشوفانية +والشوكولا +والشوكولاتة +والشيء +والشيخ +والشيخوخة +والشيشان +والشيعة +والشيعيون +والشيوعية +والشَّرف +والصابون +والصادقة +والصالة +والصالونات +والصانع +والصبا +والصبايا +والصبر +والصبي +والصحافة +والصحبة +والصحة +والصحراء +والصحـية +والصحف +والصحفي +والصحفية +والصحفيين +والصحو +والصحون +والصحي +والصحية +والصحيح +والصخرة +والصخور +والصداع +والصداقة +والصدامات +والصدفية +والصدق +والصدقات +والصدور +والصديق +والصديقين +والصراخ +والصراصير +والصراط +والصراع +والصراعات +والصرخات +والصرف +والصعاب +والصعوبات +والصعود +والصفاء +والصفات +والصفحات +والصفراء +والصفية +والصفيح +والصقليين +والصقيع +والصلاة +والصلب +والصلبة +والصلة +والصلدة +والصلصال +والصلوات +والصليب +والصمت +والصناع +والصناعات +والصناعة +والصناعي +والصناعية +والصنايعية +والصندوق +والصهيونية +والصواب +والصواريخ +والصوت +والصوتيات +والصوتية +والصور +والصورة +والصوفي +والصوفية +والصومال +والصون +والصويحبات +والصيانة +والصيد +والصيدلاني +والصيدلة +والصيدليات +والصيدلية +والصيف +والصين +والصيني +والصينية +والصَّابرة +والضائعين +والضاربون +والضباط +والضجر +والضجيج +والضحايا +والضحك +والضحكات +والضحى +والضراء +والضرب +والضرر +والضرورة +والضرورية +والضريبة +والضعفاء +والضفة +والضلال +والضلالات +والضلع +والضمة +والضوء +والضوابط +والضوضاء +والضيافة +والضيف +والضيوف +والطائرات +والطائف +والطائفي +والطائفية +والطاعة +والطاعون +والطاقات +والطاقة +والطاقية +والطالب +والطالبات +والطامح +والطب +والطباع +والطباعة +والطباق +والطبقات +والطبقة +والطبقي +والطبيب +والطبيبات +والطبية +والطبيعة +والطبيعي +والطبيعيات +والطبيعية +والطحالب +والطحين +والطرائف +والطرب +والطرق +والطرقات +والطروحات +والطريف +والطريق +والطريقة +والطعام +والطعين +والطفح +والطفل +والطفولة +والطفولية +والطفيليات +والطفيليين +والطقس +والطقوس +والطلاء +والطلاب +والطلابي +والطلب +والطلبة +والطمأنينة +والطماطم +والطموح +والطموحات +والطهر +والطوائف +والطوب +والطوسي +والطوفان +والطويل +والطويلة +والطيب +والطيبة +والطير +والطيران +والطيور +والظالمة +والظاهر +والظاهرة +والظباء +والظروف +والظفر +والظلام +والظلاميين +والظلم +والظلمة +والظهران +والظواهر +والعائد +والعائلات +والعائلة +والعابرة +والعابرون +والعابرين +والعاج +والعاجزون +والعاجلة +والعادات +والعارفين +والعاشر +والعاشق +والعاصفة +والعاصمة +والعاطفة +والعاطفي +والعاكفين +والعالم +والعالمي +والعالمية +والعالي +والعام +والعامة +والعامل +والعاملون +والعاملين +والعباد +والعبارات +والعبارة +والعبث +والعبد +والعبدلي +والعبقرية +والعبوات +والعبيد +والعتابة +والعتيق +والعجز +والعجزة +والعجلات +والعجم +والعجمي +والعجيب +والعداء +والعدالة +والعداوة +والعدسات +والعدل +والعدم +والعدوان +والعدوى +والعديد +والعذاب +والعراق +والعراقة +والعراقُ +والعراوي +والعرب +والعربى +والعربي +والعربية +والعرجي +والعرس +والعرض +والعرفان +والعرق +والعرقية +والعروبة +والعروض +والعريف +والعريق +والعزاء +والعزف +والعزلة +والعسكر +والعسكري +والعسكرية +والعسل +والعسيرين +والعشاء +والعشب +والعشرون +والعشرين +والعصابة +والعصاة +والعصافير +والعصب +والعصبية +والعصر +والعصي +والعصيان +والعضلات +والعضو +والعطاء +والعطس +والعطش +والعطلات +والعظام +والعظم +والعظماء +والعظمة +والعظيمات +والعفاريت +والعفش +والعقائد +والعقاب +والعقاد +والعقارب +والعقاقير +والعقب +والعقبات +والعقبة +والعقديات +والعقل +والعقلانية +والعقلية +والعقوبات +والعقود +والعقول +والعقيق +والعكس +والعلا +والعلائق +والعلاج +والعلاجات +والعلاجية +والعلاقات +والعلاقة +والعلامات +والعلة +والعلم +والعلماء +والعلمانية +والعلمانيون +والعلمانيين +والعلمي +والعلمية +والعلن +والعلو +والعلوم +والعليا +والعمارات +والعمارة +والعمال +والعمالة +والعمامة +والعمران +والعمرانية +والعمرة +والعمرية +والعمق +والعمل +والعملاء +والعملات +والعملاق +والعملان +والعملي +والعمليات +والعملية +والعمود +والعميقة +والعناد +والعناصر +والعناكب +والعناوين +والعناية +والعنب +والعنصر +والعنصرية +والعنف +والعنق +والعنوان +والعنود +والعنيف +والعنيفة +والعهدة +والعواصف +والعوامل +والعودة +والعوز +والعولمة +والعويد +والعويل +والعيادة +والعياذ +والعيب +والعيدين +والعيزرية +والعيساوية +والعيش +والعين +والعيوب +والعيون +والعِبَر +والعِدّة +والعِوز +والـجَلَد +والـــهواء +والـمتجمِّلة +والـهَنَاء +والفئران +والفائدة +والفائزون +والفاتحون +والفاتحين +والفارابي +والفارس +والفارسي +والفارسية +والفارق +والفاروق +والفاطمي +والفاطميون +والفاعل +والفاعلة +والفاقة +والفاكس +والفاكهة +والفانوس +والفتاوى +والفترة +والفتيات +والفتيان +والفحص +والفحـص +والفحم +والفحوصات +والفخار +والفخامة +والفخرانية +والفداء +والفرات +والفراشات +والفراشي +والفرجة +والفرح +والفرد +والفردي +والفردية +والفرس +والفرشات +والفرص +والفرصة +والفرع +والفرعوني +والفرعيين +والفرق +والفرنج +والفرنسية +والفرنسيون +والفرنك +والفروسية +والفروع +والفريدة +والفرّ +والفزع +والفساتين +والفساد +والفسحة +والفسيفساء +والفسيولوجيا +والفسيولوجية +والفشل +والفصل +والفضاء +والفضائل +والفضائيات +والفضائية +والفضة +والفضل +والفضول +والفضوليون +والفطريات +والفطور +والفظاظة +والفعال +والفعاليات +والفعل +والفــل +والفقر +والفقراء +والفقه +والفقهي +والفقهيّ +والفقير +والفقيرة +والفقيه +والفكر +والفكرة +والفكري +والفكرية +والفلاح +والفلاسفة +والفلبين +والفلترة +والفلسطيني +والفلسطينية +والفلسطينيين +والفلسفات +والفلسفة +والفلسفي +والفلسفية +والفلفل +والفلك +والفلكية +والفلل +والفلوت +والفم +والفن +والفنادق +والفنان +والفنانات +والفنانة +والفنانون +والفنانين +والفنجان +والفندق +والفندقة +والفندقي +والفندقية +والفنون +والفني +والفنية +والفنيون +والفنيين +والفهم +والفواصل +والفواكه +والفوز +والفوسفات +والفوسفاتية +والفوسفورية +والفوضى +والفولجا +والفولكلورية +والفيتوري +والفيروسات +والفيزياء +والفيزيولوجية +والفيضان +والفيضانات +والفيـتامينات +والفيلة +والفيلسوف +والفينيقية +والقائم +والقائمين +والقابليات +والقادة +والقادرين +والقادم +والقاديانيين +والقارئ +والقارة +والقاص +والقاضي +والقاعات +والقاعدة +والقافية +والقانون +والقانوني +والقانونية +والقانونيين +والقاهرة +والقبائل +والقباطي +والقبعات +والقبلات +والقبلة +والقبوات +والقبول +والقتل +والقتلة +والقحط +والقدر +والقدرات +والقدرة +والقدس +والقدم +والقدمين +والقدوة +والقديس +والقديم +والقرآن +والقراء +والقراءات +والقراءة +والقرابين +والقرارات +والقراقوز +والقرد +والقردة +والقرص +والقرصنة +والقرضاوي +والقرم +والقرميد +والقرن +والقرود +والقروض +والقرون +والقرى +والقري +والقريبة +والقسم +والقشرة +والقشريات +والقص +والقصائد +والقصاصين +والقصبات +والقصة +والقصد +والقصدير +والقصص +والقصصي +والقصور +والقصيدة +والقصير +والقصيرة +والقضاء +والقضاة +والقضايا +والقضية +والقط +والقطاع +والقطاعات +والقطرية +والقطط +والقطن +والقفل +والقلائد +والقلاع +والقلاقل +والقلب +والقلق +والقلم +والقلنسوة +والقلوب +والقليل +والقماش +والقمر +والقمع +والقمم +والقنابل +والقناة +والقناصل +والقناعة +والقنبلة +والقنص +والقنفذ +والقنوات +والقهر +والقوات +والقوارب +والقوارير +والقواعد +والقوانين +والقوة +والقورمة +والقوصي +والقوقاز +والقول +والقومي +والقوميات +والقومية +والقوميين +والقوي +والقيادة +والقيادي +والقياس +والقياسات +والقيام +والقيقب +والقيم +والقيمة +والقيود +والقُطُر +والقِيَم +والكآبة +والكائنات +والكاتب +والكاتبات +والكاثارية +والكادميوم +والكارثة +والكارهان +والكاريبي +والكاشف +والكاكاو +والكالسيوم +والكانولا +والكاونترباص +والكبار +والكباري +والكبت +والكبدة +والكبرى +والكبس +والكبير +والكبيرة +والكتاب +والكتابات +والكتابة +والكتان +والكتب +والكتلة +والكتّاب +والكثافة +والكثير +والكثيرون +والكحول +والكذب +والكرامات +والكرامة +والكراهية +والكردى +والكرم +والكرملين +والكره +والكروم +والكريم +والكريمات +والكساء +والكسرة +والكسل +والكشف +والكشوف +والكعك +والكف +والكفاءات +والكفاح +والكفاية +والكل +والكلاب +والكلام +والكلب +والكلف +والكلمات +والكلمة +والكلى +والكليات +والكلية +والكم +والكمال +والكمان +والكمبيوتر +والكميات +والكميت +والكنائس +والكنافة +والكندية +والكنز +والكنسي +والكنوز +والكنيسة +والكهرباء +والكهربائيات +والكهربائية +والكوائين +والكوابيس +والكوات +والكوادر +والكوارث +والكوارك +والكوبرا +والكورية +والكوفة +والكوكب +والكولا +والكوميديا +والكوميدية +والكون +والكويت +والكويتية +والكي +والكيان +والكيف +والكيفية +والكيماويات +والكيماوية +والكيمياء +والكُتاب +واللائحة +واللاتين +واللاتينية +واللاجئين +واللاذقية +واللازمة +واللافت +واللامبالاة +واللبرالية +واللبن +واللبنانية +واللتين +واللجان +واللجنة +واللجنين +واللجوء +واللحظات +واللحظة +واللحم +واللحن +واللحوم +واللد +واللذان +واللذين +واللصوص +واللطف +واللعب +واللعنات +واللفظ +واللقاء +واللقاءات +واللقى +واللمز +والله +واللهاث +واللوائح +واللوحات +واللوز +واللوعة +واللون +واللونُ +واللي +واللياقة +والليالي +والليبرالية +والليث +والليطاني +والليل +والليلُ +والليمون +والليمونين +واللّه +والمأثورات +والمأساة +والمأكل +والمأكولات +والمألوف +والمأمن +والمأمول +والمأوى +والمؤامرات +والمؤتمر +والمؤتمرات +والمؤثر +والمؤثرات +والمؤثرة +والمؤدية +والمؤرخ +والمؤرخون +والمؤرخين +والمؤسسات +والمؤسساتي +والمؤسساتية +والمؤسسة +والمؤسسي +والمؤسف +والمؤشرات +والمؤلف +والمؤلفات +والمؤلم +والمؤمن +والمئات +والماء +والماجد +والمادي +والمادية +والمارة +والمارك +والماركسي +والماركسية +والمازني +والماشية +والماضي +والماعز +والمال +والمالي +والمالية +والماليزية +والمبادئ +والمبادرات +والمبادرة +والمباشرة +والمباني +والمبتكرة +والمبدئية +والمبدع +والمبدعين +والمبذر +والمبرمجين +والمبضع +والمبيت +والمبيدات +والمبيعات +والمبيعة +والمتأخرة +والمتأهب +والمتابع +والمتابعين +والمتاجر +والمتاحف +والمتاعب +والمتانة +والمتباعد +والمتباينة +والمتبتل +والمتبوعة +والمتتاليات +والمتتبع +والمتجانسة +والمتجددة +والمتجذّرة +والمتحامقين +والمتحجرة +والمتحضرة +والمتحف +والمتخصصة +والمتخيل +والمتداولة +والمتدرجة +والمتذوق +والمترجم +والمترجمة +والمتزن +والمتزنة +والمتسائلين +والمتسلطين +والمتسوقون +والمتسوقين +والمتسولين +والمتشابكة +والمتشعبة +والمتصلة +والمتصنعة +والمتصهين +والمتصوفة +والمتضررين +والمتطلبات +والمتطلعة +والمتطورة +والمتعالية +والمتعة +والمتعددة +والمتعلق +والمتعلقة +والمتعمقة +والمتفرج +والمتفوقين +والمتقاطعة +والمتقاعدين +والمتكامل +والمتكاملة +والمتلاحقة +والمتلقي +والمتلقّين +والمتمثلة +والمتمردون +والمتمركز +والمتميزة +والمتميزين +والمتناقضة +والمتنبي +والمتنزهات +والمتنقلين +والمتنورة +والمتنوعة +والمتوارث +والمتواصل +والمتواضعة +والمتوحشة +والمتوسط +والمتوسطة +والمتوسِّطة +والمتوقع +والمتوقعين +والمثابرة +والمثاعيب +والمثال +والمثالية +والمثقف +والمثقفين +والمثقّف +والمثل +والمثلث +والمثمرة +والمثير +والمجادلة +والمجاري +والمجازر +والمجاعات +والمجال +والمجالات +والمجالس +والمجتمع +والمجتمعات +والمجد +والمجدية +والمجر +والمجسمات +والمجلات +والمجلة +والمجلجل +والمجلدات +والمجلس +والمجمدة +والمجمع +والمجموعات +والمجموعة +والمجمّدة +والمجهر +والمجهول +والمجون +والمجوهرات +والمحاباة +والمحادثة +والمحارب +والمحاسبة +والمحاضرات +والمحاط +والمحافظات +والمحافظة +والمحافل +والمحاكاة +والمحاكمة +والمحامين +والمحبين +والمحتاج +والمحتاجين +والمحتالين +والمحترفون +والمحتل +والمحتوى +والمحددة +والمحدود +والمحدّثين +والمحسنين +والمحطات +والمحفزات +والمحفورة +والمحك +والمحلات +والمحلية +والمحمل +والمحيط +والمحيطات +والمخ +والمخاطية +والمخاطَب +والمخالف +والمخاوف +والمخبرين +والمخبولين +والمختبرات +والمخترع +والمخترعات +والمختصة +والمختصين +والمخدرات +والمخربة +والمخرج +والمخرشات +والمخزومي +والمخصِّبات +والمخطط +والمخطوط +والمخطوطات +والمخطوطة +والمخلفات +والمخلوط +والمخلوقات +والمخيلة +والمخيمات +والمخيّلة +والمد +والمدائح +والمداخل +والمداخلات +والمداد +والمدار +والمدارس +والمدافعة +والمدافعين +والمدافن +والمداولات +والمدجج +والمدخنين +والمدربة +والمدرس +والمدرسات +والمدرسة +والمدرسين +والمدعمة +والمدفعية +والمدن +والمدنيات +والمدنية +والمدهش +والمدير +والمدينة +والمدّ +والمذابح +والمذاقات +والمذاهب +والمذلة +والمذهبية +والمذهل +والمذيع +والمرء +والمرآة +والمرأة +والمرئيات +والمرئية +والمرابع +والمراثي +والمراجع +والمراجعات +والمراجعة +والمراحـل +والمراحل +والمرافئ +والمرافق +والمراقبة +والمراكز +والمراهق +والمربعات +والمربى +والمربيات +والمربين +والمرة +والمرتبطة +والمرتزقين +والمرتفعات +والمرج +والمرجان +والمرجرين +والمرجوة +والمرح +والمرحلة +والمرحوم +والمرخيات +والمرسومة +والمرض +والمرضى +والمرعب +والمرقمة +والمركز +والمركوب +والمرهقة +والمرور +والمرونة +والمرويات +والمريرة +والمريض +والمزاج +والمزارات +والمزارع +والمزايا +والمزمنات +والمزهر +والمزيد +والمسؤول +والمسؤولية +والمسئوليات +والمسئولية +والمسئولين +والمساء +والمسائل +والمسابح +والمسابقات +والمساجد +والمساحات +والمساحة +والمساس +والمساطر +والمساعدات +والمساعدة +والمسافة +والمسافرين +والمساكن +والمساكين +والمسالم +والمسامرات +والمسامرة +والمساندة +والمساهمة +والمساواة +والمستأجر +والمستثمر +والمستثمرين +والمستجدات +والمستجدّات +والمستحدثات +والمستحدثة +والمستشار +والمستشارين +والمستشرق +والمستشرقين +والمستشفيات +والمستصعبات +والمستضعفين +والمستطيل +والمستعملة +والمستقبل +والمستقبلية +والمستقر +والمستقلة +والمستكشفون +والمستكشفين +والمستلزمات +والمستمر +والمستمرة +والمستمع +والمستندات +والمستندة +والمستنسخات +والمستنقعات +والمستهلكين +والمستورد +والمستوردات +والمستوصفات +والمستوطنات +والمستوطنين +والمستوى +والمستوي +والمستويات +والمسجد +والمسجلين +والمسح +والمسرح +والمسرحي +والمسرحيات +والمسرحية +والمسعودي +والمسقط +والمسقوف +والمسكرات +والمسكن +والمسكنة +والمسلسلات +والمسلمون +والمسلمين +والمسموع +والمسموعة +والمسوق +والمسيحي +والمسيحية +والمسيحيون +والمسيرات +والمسيسيبي +والمشاركات +والمشاركة +والمشاركين +والمشاريع +والمشاعر +والمشاعل +والمشاكل +والمشاهد +والمشاهدات +والمشايخ +والمشترك +والمشترين +والمشتقات +والمشتي +والمشرب +والمشربيات +والمشرعين +والمشرفين +والمشرفَ +والمشروبات +والمشروعات +والمشعوذين +والمشقة +والمشكلة +والمشهد +والمشورة +والمشيمية +والمصاب +والمصابيح +والمصابين +والمصاحف +والمصادر +والمصادرات +والمصادقة +والمصارحة +والمصارف +والمصالح +والمصانع +والمصايف +والمصب +والمصحوبة +والمصدر +والمصدرة +والمصدّرة +والمصرارة +والمصروفات +والمصري +والمصريون +والمصريين +والمصطلحات +والمصلحة +والمصنفات +والمصنفين +والمصنوعات +والمصور +والمصورين +والمضايقات +والمضحية +والمضطرب +والمضمون +والمضي +والمطابقة +والمطار +والمطارات +والمطاردات +والمطاط +والمطاعم +والمطافئ +والمطالبة +والمطبات +والمطبخ +والمطر +والمطرب +والمطربات +والمطربين +والمطرد +والمطرزين +والمطرِّز +والمطعم +والمطلبية +والمطلوب +والمطهية +والمطول +والمظاهر +والمظهر +والمعابد +والمعادن +والمعارض +والمعارضة +والمعارف +والمعارك +والمعاصر +والمعاصرة +والمعاصم +والمعاصي +والمعاقين +والمعالجة +والمعالم +والمعامل +والمعاناة +والمعاني +والمعاهد +والمعاونة +والمعايشة +والمعايير +والمعبر +والمعبرة +والمعتدلين +والمعتقدات +والمعتقل +والمعتقلات +والمعتمد +والمعتمرين +والمعدات +والمعدنية +والمعذبين +والمعراج +والمعرض +والمعرضة +والمعرفة +والمعرفي +والمعرفية +والمعروف +والمعروفة +والمعري +والمعطيات +والمعقدة +والمعقول +والمعلقات +والمعلمات +والمعلمة +والمعلنة +والمعلومات +والمعماري +والمعمّرة +والمعنوي +والمعنويات +والمعنوية +والمعنى +والمعهد +والمعوزين +والمعوقات +والمعيشة +والمعيشية +والمفاتحة +والمفاتشة +والمفاجأة +والمفارش +والمفارقة +والمفاهيم +والمفاوض +والمفاوضات +والمفتش +والمفتوح +والمفردات +والمفروض +والمفضلة +والمفكر +والمفكرون +والمفكرين +والمفلطحة +والمفوضية +والمفيد +والمفيدة +والمقاتلين +والمقادير +والمقاربة +والمقارن +والمقاعد +والمقال +والمقالات +والمقامرين +والمقاهي +والمقاولات +والمقاولون +والمقاومة +والمقاييس +والمقتدر +والمقتنيات +والمقدامة +والمقدرة +والمقرنصات +والمقريزي +والمقصود +والمقنعة +والمقولات +والمقومات +والمقيم +والمقيمة +والمقيمين +والمكابدات +والمكابدة +والمكاتب +والمكاشفات +والمكافآت +والمكافأة +والمكالمات +والمكان +والمكانية +والمكتبات +والمكتبة +والمكتبية +والمكتسبات +والمكتوبة +والمكسب +والمكسيك +والمكلاّ +والمكلفة +والمكملة +والمكوس +والمكونات +والمكونة +والمكوّنة +والمكيفة +والملائمة +والملابس +والملابسات +والملاح +والملاحدة +والملاحظ +والملاحظة +والملاحقات +والملاحم +والملاحين +والملاريا +والملاك +والملاهي +والملبس +والملتقيات +والملح +والملحوظ +والملخص +والملذات +والملصقات +والملف +والملفوف +والملقب +والملك +والملكات +والملكة +والملل +والملمس +والملهي +والملوِّثات +والملّحنَيْن +والممارسات +والممارسة +والمماليك +والممتعة +والممتلئ +والممتلكات +والممثل +والممثلون +والممثلين +والممرات +والممكن +والمملكة +والمملوء +والمملوكي +والمملوكية +والممولين +والمميزة +والمميَّزة +والمناجم +والمناخ +والمنارة +والمنازل +والمناسب +والمناسبات +والمناسل +والمناشدات +والمناشف +والمناصب +والمناضل +والمناطق +والمناظر +والمناظرات +والمنافسة +والمنافي +والمناقب +والمناقشة +والمناهج +والمناوئين +والمناورة +والمنبر +والمنتج +والمنتجات +والمنتجعات +والمنتجين +والمنتزهات +والمنتظر +والمنتفعون +والمنتمين +والمنجمية +والمنح +والمنحدرات +والمنحدرين +والمنحنيات +والمنحوتات +والمنحى +والمنخفضة +والمندهشة +والمنزل +والمنزلية +والمنزه +والمنسوجات +والمنسي +والمنشآت +والمنشر +والمنصوب +والمنصورة +والمنطق +والمنطقة +والمنظر +والمنظم +والمنظمات +والمنظمة +والمنظور +والمنظوم +والمنظومة +والمنفلوطي +والمنفى +والمنقولة +والمنقّر +والمنكر +والمنكرات +والمنكرة +والمنكوبين +والمنمنمات +والمنهج +والمنهجية +والمهاجر +والمهاجرون +والمهاجرين +والمهارات +والمهارة +والمهاري +والمهام +والمهتمين +والمهجرية +والمهدئة +والمهدي +والمهذبة +والمهرجان +والمهرجانات +والمهري +والمهرّجين +والمهم +والمهمة +والمهمشين +والمهندس +والمهندسات +والمهندسة +والمهندسين +والمهني +والمهنية +والمهنيون +والموئل +والمواثيق +والمواد +والموارد +والمواساة +والمواسم +والمواصفات +والمواصلات +والمواطنون +والمواطنين +والمواظبة +والمواعظ +والمواعيد +والموافقات +والموافقة +والمواقع +والمواقف +والموالد +والموانئ +والمواني +والمواهب +والمواويل +والموت +والموتى +والموج +والموجز +والموجهة +والموجودة +والموجي +والموحد +والمودة +والموروث +والموروثة +والموريتاني +والموز +والموزعة +والموسم +والموسوعات +والموسوعة +والموسيقا +والموسيقار +والموسيقى +والموسيقية +والموسيقيّ +والموشحات +والموصل +والموصولة +والموصى +والموضوع +والموضوعي +والموضوعية +والموظفون +والموظفين +والموقف +والمولد +والمولعين +والمونتاج +والموهوب +والموهوبين +والموهومين +والميادين +والمياه +والميتان +والميثانول +والميداليات +والميدالية +والميديا +والميزانيات +والميكانيكا +والميكروب +والميكروبات +والميل +والمينا +والميوعة +والمُخلَّط +والناب +والنابلم +والناتجة +والناجم +والناجمة +والنادر +والنادى +والنادي +والنار +والنارية +والناس +والناصرة +والناصري +والنافذة +والناقة +والناقد +والناميات +والنامية +والناي +والنايلون +والنبأ +والنبابيت +والنبات +والنباتات +والنباتية +والنبيلة +والنتائج +والنتيجة +والنثري +والنثرية +والنجابة +والنجاح +والنجاحات +والنجارة +والنجارين +والنجف +والنجمة +والنجوم +والنحاس +والنحت +والنحر +والنحل +والنحو +والنحور +والنخبة +والنخيل +والنداءات +والندوات +والندى +والنرجسية +والنرويج +والنزاعات +والنزعة +والنزف +والنزهة +والنزوع +والنساء +والنساءُ +والنسائي +والنسب +والنسبة +والنسبية +والنسج +والنسر +والنسوية +والنسيج +والنشء +والنشأة +والنشاط +والنشاطات +والنشر +والنشوء +والنص +والنصف +والنصيحة +والنضال +والنظائر +والنظارتان +والنظافة +والنظام +والنظر +والنظرات +والنظريات +والنظم +والنظيفة +والنعاج +والنعمة +والنعيم +والنفاق +والنفايات +والنفس +والنفسي +والنفسية +والنفط +والنفطية +والنفع +والنفقات +والنفوذ +والنفور +والنفي +والنفْس +والنقاب +والنقابات +والنقاد +والنقب +والنقد +والنقدي +والنقدية +والنقشة +والنقطة +والنقل +والنقود +والنقوش +والنقي +والنكد +والنكوص +والنماء +والنماذج +والنمارق +والنمر +والنمسا +والنمو +والنموذج +والنموّ +والنميمة +والنهار +والنهايات +والنهب +والنهر +والنهضات +والنهضة +والنهوض +والنهي +والنوادر +والنوادي +والنوافذ +والنوافل +والنوبة +والنور +والنوع +والنوم +والنووية +والنياشين +والنياق +والنيتروجين +والنيترونية +والنيجر +والنيشانات +والنيكل +والنيكوتين +والنيل +والنيِّر +والنَّاهية +والهاتف +والهادفة +والهامة +والهبل +والهبوط +والهجر +والهجرة +والهجن +والهدايا +والهدف +والهدوء +والهراوات +والهرب +والهرسك +والهرطقات +والهرمونات +والهروب +والهزارات +والهزال +والهزام +والهزيمة +والهضاب +والهفوف +والهلال +والهلع +والهمجية +والهمز +والهموم +والهمّ +والهند +والهندسة +والهندسية +والهندي +والهندية +والهنود +والهواء +والهواة +والهواجس +والهوايات +والهودج +والهورمونات +والهوس +والهولنديين +والهوية +والهوّة +والهيئات +والهيئة +والهيدروجين +والهيكلية +والهيمنة +والواجب +والواجبات +والواحات +والواحة +والوارد +والواسع +والواعدة +والوافد +والوافدين +والواقع +والواقعة +والواقعي +والواقعية +والواقي +والوالدان +والوالدين +والواو +والوتر +والوجاهة +والوجبات +والوجداني +والوجدانية +والوجع +والوجنتين +والوجه +والوجودي +والوجوه +والوحدات +والوحدة +والوحشي +والوحشية +والوحل +والوحيد +والوحيدة +والوديان +والوديع +والورد +والوردي +والورش +والورع +والورق +والورقة +والورود +والورّاقين +والوزارات +والوزارة +والوزراء +والوزنُ +والوسائل +والوساوس +والوسط +والوسطي +والوسطية +والوسيلة +والوصايا +والوصايات +والوصل +والوصول +والوضع +والوضعية +والوضوح +والوطن +والوطنى +والوطنية +والوظائف +والوظيفي +والوظيفية +والوعاظ +والوعظ +والوعود +والوعي +والوفاء +والوفد +والوفرة +والوفود +والوقائع +والوقار +والوقاية +والوقت +والوقف +والوقود +والوقوع +والوقوف +والوكالات +والوكالة +والولاة +والولادة +والولايات +والولد +والولوج +والولي +والومضات +والوهن +والويل +والى +والي +واليأس +والياء +واليائس +واليابان +والياباني +واليابانية +واليابس +والياس +والياسمين +واليانصيب +والياً +واليباس +واليدوية +واليرموك +واليسار +واليفاع +واليفاعة +واليكانت +واليمامة +واليمن +والين +واليهود +واليهودية +واليورانيوم +واليوم +واليونان +واليونانية +واليونانيين +واليونسيف +واليونيسيف +وام +وامتاز +وامتثل +وامتحان +وامتحت +وامتد +وامتدادا +وامتدادات +وامتداداً +وامتدادها +وامتدت +وامتزاج +وامتزج +وامتلأ +وامتلأت +وامتلكت +وامتناناً +وامتنع +وامتهن +وامرأة +وان +وانبثق +وانبرى +وانتابه +وانتبه +وانتخب +وانتركونتيننتال +وانتزاع +وانتسابي +وانتسبتُ +وانتشار +وانتشارها +وانتشارهم +وانتشارهن +وانتشر +وانتشرت +وانتصار +وانتظار +وانتظاره +وانتظرت +وانتظروا +وانتظمت +وانتظمتُ +وانتعاش +وانتفاء +وانتفاضة +وانتفض +وانتفضت +وانتقاء +وانتقادها +وانتقال +وانتقالها +وانتقام +وانتقل +وانتقلت +وانتماءاتها +وانتماءه +وانتمائي +وانتهاء +وانتهاءً +وانتهاك +وانتهاكها +وانتهت +وانتهى +وانتهيت +وانتي +وانتُخب +وانثقابات +وانجذاب +وانجلت +وانجلترا +وانجليزية +وانحدرت +وانحراف +وانحسار +وانحناء +وانحنى +وانحيازك +وانخراطه +وانخرطت +وانخرطوا +وانخفاض +وانخفض +وانخفضت +واندثار +واندس +واندفاع +واندفاعه +واندفع +واندفعنا +واندهاشه +واندهاشي +وانزواء +وانسابت +وانسحبنا +وانسراح +وانسل +وانشراح +وانشقاق +وانصراف +وانصرف +وانصرفت +وانضباط +وانضم +وانضممن +وانطفأت +وانطلاقاً +وانطلاقي +وانطلق +وانطلقت +وانطوائه +وانظر +وانظري +وانعدام +وانعدامها +وانعصاراتنا +وانعطفت +وانعقاد +وانعقدت +وانعكاسات +وانعكاساتها +وانعكس +وانعكست +وانفتاحه +وانفتحت +وانفجارات +وانفجر +وانفصال +وانفصام +وانفعالات +وانفعالاته +وانفعاله +وانفعالية +وانفلت +وانقرضت +وانقسمت +وانقضت +وانقضى +وانقطاع +وانقطع +وانقطعت +وانقلابا +وانقلابات +وانقلب +وانقلبت +وانكسار +وانكساراتها +وانكوي +وانما +وانمائية +وانه +وانها +وانهارت +وانهالت +وانهماكهم +وانهمرت +وانهمكت +وانهيار +وانهيارحكومة +وانيط +واهبك +واهتز +واهتزاز +واهتم +واهتمام +واهتماماته +واهتمامه +واهتمامهم +واهتمت +واهتموا +واهن +واهنة +واهية +واهٍ +واية +وايت +وايتمن +وايتمور +وايزمن +وايسلندا +وايقاع +وايلامها +وايلد +وبأجزاء +وبأساليب +وبأسطح +وبأسعار +وبأسلوب +وبأسماء +وبأصوات +وبأعلى +وبأقدام +وبأمتهم +وبأمل +وبأن +وبأنسنتها +وبأنكم +وبأنه +وبأنها +وبأهميته +وبأية +وبإدراك +وبإرادته +وبإشراف +وبإصدار +وبإصداره +وبإضافة +وبإضـافة +وبإلهام +وبإمكان +وبإمكانية +وبإنشاء +وبئر +وبئس +وباء +وبائع +وبائعات +وبائيا +وبائية +وباب +وبابل +وبابلو +وبات +وباتت +وباتجاه +وباتوا +وباجر +وباحته +وباحث +وباحثون +وباحثين +وباختصار +وبادرت +وباردة +وبارز +وبارفيز +وباركنسون +وباركني +وباريس +وباستثناء +وباستخدام +وباستسلام +وباستطاعتي +وباستمرار +وباستور +وباسط +وباسم +وباسيل +وباشر +وباشرت +وباطن +وباع +وباعتبار +وباعتدال +وبافتتاح +وباقى +وباقي +وباكرا +وباكراً +وباكستان +وباكو +وبالأحضان +وبالأخص +وبالأصداف +وبالإضافة +وبالإنجازات +وبالازدراء +وبالانتقال +وبالاً +وبالبساطة +وبالبشر +وبالتأكيد +وبالتالى +وبالتالي +وبالتحاق +وبالتحديد +وبالتحكم +وبالتدريج +وبالتعاون +وبالتعليم +وبالتقسيط +وبالتنبؤات +وبالتواتر +وبالتوجهات +وبالحجاب +وبالحرس +وبالحلم +وبالحياة +وبالدرجة +وبالدولار +وبالذات +وبالرمو +وبالروايات +وبالزراعة +وبالسجن +وبالسعر +وبالسلطة +وبالسياق +وبالشعاب +وبالشعر +وبالصعود +وبالصلاة +وبالطبع +وبالظل +وبالعار +وبالعامية +وبالعبقرية +وبالعراقيل +وبالعسل +وبالعقل +وبالعكس +وبالعلم +وبالعودة +وبالفرسان +وبالفعل +وبالفن +وبالقدر +وبالقدرة +وبالقرب +وبالقلم +وبالكاد +وبالمثل +وبالمخطوطات +وبالمدير +وبالمرور +وبالمستقبل +وبالمعدل +وبالمعنى +وبالمفاوضات +وبالمفردات +وبالمقابل +وبالمكاسب +وبالملابس +وبالمناسبة +وبالمنتجع +وبالمنطقة +وبالميناء +وبالنتيجة +وبالنسبة +وبالنظر +وبالوسائل +وباليه +وباليونانية +وبانا +وباهت +وباهتة +وباور +وباورو +وببدء +وببروز +وببساطة +وببسـاطة +وببصيرة +وببطء +وببعض +وبت +وبتحديد +وبتحمل +وبتخطيطها +وبتر +وبترابط +وبتراكم +وبتركيبته +وبترها +وبتعديل +وبتفسير +وبتقديم +وبتقريبها +وبتكلفة +وبتلك +وبتناسق +وبتواضع +وبتواضعه +وبتوثيق +وبث +وبثروة +وبثقة +وبجانب +وبجرعات +وبجسد +وبجمال +وبجهد +وبجوار +وبحاجة +وبحار +وبحاراً +وبحت +وبحث +وبحثه +وبحثوا +وبحثي +وبحداثة +وبحديثها +وبحرارة +وبحركة +وبحرمانهما +وبحسب +وبحضارتها +وبحضور +وبحق +وبحقه +وبحكم +وبحلول +وبحمايتها +وبحوث +وبحوثا +وبحوثي +وبحيث +وبحيرة +وبحيرتها +وبخارى +وبخاصة +وبخبراتهم +وبخروج +وبخصوصية +وبخطه +وبخه +وبخور +وبخوف +وبدء +وبدءا +وبدءوا +وبدأ +وبدأت +وبدأنا +وبدأوا +وبدا +وبدائع +وبداهة +وبدايات +وبداياتها +وبداية +وبدايتك +وبدت +وبدخوله +وبدراسة +وبدرجات +وبدعمها +وبدعوة +وبدلا +وبدلاً +وبدليل +وبدنك +وبدهي +وبدهيات +وبدوره +وبدون +وبدوي +وبديع +وبديعها +وبديهي +وبذا +وبذرة +وبذكرى +وبذل +وبذلت +وبذلك +وبذور +وبذورها +وبر +وبرأي +وبرا +وبراءات +وبراءة +وبراءته +وبراريها +وبراعة +وبرامج +وبرامجه +وبراهينه +وبرايتن +وبرج +وبرزت +وبرسالته +وبرعاية +وبرعايته +وبرفقته +وبرفقتهم +وبركاته +وبركة +وبرلمانية +وبرمَ +وبرنارد +وبرناردشو +وبرناسيّة +وبرنامج +وبرنس +وبرهان +وبرهانا +وبروائع +وبروتينات +وبرودة +وبروز +وبروس +وبروكسل +وبريستول +وبريطانيا +وبريطانية +وبريقه +وبريقها +وبزوال +وبزيادة +وبس +وبساتينها +وبساطة +وبساطتها +وبسبب +وبسخاء +وبسرعة +وبسطاء +وبسطال +وبسطوع +وبسعر +وبسقف +وبسهولة +وبسيطة +وبشبكة +وبشخصية +وبشرا +وبشرني +وبشكل +وبشكلها +وبصاق +وبصحبته +وبصحة +وبصدد +وبصراحة +وبصرخة +وبصرف +وبصرنا +وبصره +وبصريا +وبصرية +وبصريح +وبصفة +وبصوت +وبصورة +وبضرورة +وبضوئها +وبطء +وبطاقات +وبطاقة +وبطباعتهم +وبطبيعة +وبطبيعته +وبطريقة +وبطل +وبطلا +وبطن +وبطولاتها +وبطولاتهم +وبطولة +وبطون +وبعاطفة +وبعبارة +وبعث +وبعثة +وبعثرة +وبعثرت +وبعد +وبعدئذ +وبعدا +وبعداً +وبعدد +وبعدما +وبعده +وبعدها +وبعدين +وبعض +وبعضنا +وبعضها +وبعضهم +وبعضهن +وبعطاء +وبعظمة +وبعلب +وبعلبك +وبعناية +وبعيد +وبعيدا +وبعيدان +وبعيداً +وبعيدة +وبعيدًا +وبفائدتها +وبفارق +وبفضل +وبفضله +وبفنها +وبقاع +وبقالب +وبقايا +وبقدر +وبقدراتي +وبقدرته +وبقرب +وبقسوة +وبقصيدة +وبقطع +وبقلب +وبقلة +وبقوة +وبقومه +وبقى +وبقي +وبقيادة +وبقياس +وبقية +وبقيت +وبقيتْ +وبقيع +وبقينا +وبقيّة +وبكت +وبكتيريا +وبكثير +وبكر +وبكفاءة +وبكل +وبكلابهم +وبكلمات +وبكوا +وبكونهم +وبكيت +وبل +وبلا +وبلابل +وبلاد +وبلاده +وبلت +وبلجيكا +وبلح +وبلحة +وبلحظة +وبلحن +وبلدان +وبلدانهم +وبلدة +وبلذة +وبلزاك +وبلهجة +وبلورة +وبلوشستان +وبلون +وبليني +وبما +وبماليتها +وبمتعة +وبمجتمعاتنا +وبمجتمعاته +وبمجرد +وبمختلف +وبمرور +وبمساحة +وبمساعدة +وبمسرح +وبمصاحبة +وبمعنى +وبمعونة +وبمعيته +وبمعيتها +وبمفاهيم +وبمفعول +وبمقارنة +وبمقاعد +وبمقالات +وبمقدار +وبمناسبة +وبمهارة +وبموجب +وبموضوعية +وبناء +وبناءها +وبناءً +وبناءّ +وبناؤه +وبناؤهم +وبنائها +وبنات +وبناته +وبناتها +وبناتهم +وبناتي +وبنادقهم +وبنبرة +وبنت +وبنتا +وبنتك +وبنجر +وبنجلاديش +وبنسبة +وبنصر +وبنظرات +وبنظيرتها +وبنفس +وبنفسه +وبنك +وبنما +وبنهاية +وبنوك +وبنوه +وبنى +وبني +وبنية +وبنيت +وبنيتها +وبنَفَس +وبه +وبها +وبهاء +وبهاؤه +وبهاما +وبهتت +وبهجةً +وبهجت +وبهجوم +وبهذا +وبهذه +وبهرني +وبهما +وبهوس +وبوابة +وبواسطة +وبواعثها +وبوجود +وبودي +وبور +وبورتوريكو +وبوركينا +وبوساطة +وبوسطن +وبوسعي +وبوصلته +وبوضوح +وبوعي +وبوقا +وبوقت +وبول +وبولونيا +وبوهمند +وبوهيميّ +وبي +وبيئاته +وبيئة +وبيئته +وبيئية +وبيات +وبياطرة +وبيان +وبيانات +وبياواي +وبيت +وبيتر +وبيده +وبيدها +وبيروت +وبيزنطة +وبيسان +وبيض +وبيضاء +وبيع +وبيعها +وبيليز +وبين +وبينت +وبينجامين +وبينما +وبينه +وبينها +وبينهم +وبينهما +وبينهن +وبيوت +وبيوتها +وبيّن +وبَلْوره +وتآكل +وتأبى +وتأبي +وتأتأة +وتأتى +وتأتي +وتأثر +وتأثراتها +وتأثرت +وتأثره +وتأثير +وتأثيرا +وتأثيراته +وتأثيره +وتأثيرهما +وتأثيرًا +وتأجج +وتأجير +وتأخذ +وتأخر +وتأخير +وتأخيراً +وتأريخه +وتأسست +وتأسيس +وتأسيساً +وتأشيرة +وتأصيل +وتأكد +وتأكدت +وتأكدتْ +وتأكل +وتأكيد +وتأكيداً +وتألقت +وتألقه +وتأليف +وتأمر +وتأمل +وتأملا +وتأملات +وتأملاتي +وتأميم +وتأمين +وتأمينا +وتأنقه +وتأنيب +وتأهبا +وتأهيل +وتأهيله +وتأهيلي +وتأويلات +وتأويلاتها +وتأييدها +وتؤثر +وتؤدى +وتؤدي +وتؤكد +وتؤلمني +وتؤمن +وتؤيد +وتابع +وتابعا +وتابعت +وتابعه +وتاجر +وتارة +وتاريخ +وتاريخاً +وتاريخه +وتاريخها +وتاريخهم +وتاريخيا +وتاريخية +وتاريخيتها +وتالله +وتالياً +وتاليتها +وتاه +وتايبيه +وتايلاند +وتايوان +وتبادل +وتبادلات +وتبادلنا +وتبادلهم +وتبادلوا +وتباع +وتباعدا +وتباين +وتباينا +وتباينت +وتبتذل +وتبتسم +وتبتعد +وتبتكر +وتبث +وتبجيل +وتبجّح +وتبدأ +وتبدد +وتبدلاتها +وتبدو +وتبرئة +وتبرر +وتبرز +وتبرع +وتبريرية +وتبريز +وتبعاً +وتبعت +وتبعثرت +وتبعد +وتبعيته +وتبعيتهم +وتبعًا +وتبقى +وتبقي +وتبكي +وتبلع +وتبليس +وتبنت +وتبني +وتبنيت +وتبنيه +وتبنّي +وتبوك +وتبويبها +وتبي +وتبيع +وتبين +وتبيّنت +وتتأكَّد +وتتألف +وتتأمل +وتتأهب +وتتابع +وتتابعت +وتتباين +وتتبدل +وتتبدى +وتتبع +وتتبلور +وتتبنى +وتتثبت +وتتجاوز +وتتجدد +وتتجشأ +وتتجمع +وتتجه +وتتحدث +وتتحرك +وتتحسس +وتتحقق +وتتحكَّم +وتتحلل +وتتحمل +وتتحول +وتتحوّل +وتتخذ +وتتخصص +وتتداخل +وتتداعى +وتتدافع +وتتدنى +وتتراءى +وتتراوح +وتتربص +وتترجم +وتترقبان +وتترك +وتتركني +وتتركّز +وتتزايد +وتتزواج +وتتساءل +وتتساقط +وتتساوى +وتتسبب +وتتسترون +وتتسلل +وتتسلى +وتتسم +وتتشابه +وتتشبث +وتتشعب +وتتشوش +وتتصاعد +وتتصدر +وتتصرف +وتتصف +وتتصل +وتتضافر +وتتضح +وتتضخم +وتتضمن +وتتطلب +وتتطلع +وتتطهر +وتتطور +وتتعاظم +وتتعالى +وتتعاون +وتتعايش +وتتعدد +وتتعر +وتتعرض +وتتعلق +وتتعمدين +وتتفاقم +وتتفاوت +وتتفهم +وتتفوق +وتتفوّق +وتتقاطع +وتتقلب +وتتقلد +وتتقيأ +وتتكرر +وتتكلم +وتتكون +وتتلخص +وتتلف +وتتلقى +وتتلمذ +وتتلمذوا +وتتم +وتتماشى +وتتمتع +وتتمثل +وتتمدد +وتتمسح +وتتميز +وتتناثر +وتتنامى +وتتناول +وتتنفس +وتتنوع +وتتهدج +وتتهشم +وتتواصل +وتتوافد +وتتوالى +وتتوزع +وتتوسط +وتتوفر +وتتوقع +وتتوقف +وتتولى +وتتويج +وتتيح +وتثبيت +وتثبيتها +وتثقيفها +وتثني +وتثير +وتجاذبا +وتجار +وتجارب +وتجاربه +وتجاربها +وتجاربي +وتجارة +وتجارتهم +وتجارياً +وتجارية +وتجاه +وتجاوب +وتجاوبا +وتجاور +وتجاوز +وتجاوزت +وتجاوزه +وتجاوزًا +وتجبر +وتجد +وتجددها +وتجدر +وتجدون +وتجديد +وتجديده +وتجذب +وتجربة +وتجربته +وتجربتها +وتجرداً +وتجردك +وتجرى +وتجري +وتجريباً +وتجريحا +وتجريف +وتجرُّدٍ +وتجسد +وتجسدت +وتجسيدي +وتجشُّؤ +وتجعل +وتجعلني +وتجعله +وتجعلها +وتجف +وتجفيف +وتجلت +وتجلى +وتجليات +وتجلياته +وتجلّياتها +وتجمع +وتجمعات +وتجمعاً +وتجميع +وتجميلي +وتجنب +وتجنبا +وتجند +وتجهيزات +وتجهيزه +وتجهيزها +وتجولت +وتجويد +وتجويده +وتجيبنا +وتجّار +وتحاصره +وتحاصرهم +وتحافظ +وتحاكي +وتحاول +وتحايل +وتحب +وتحبه +وتحت +وتحتاج +وتحترمها +وتحتضن +وتحتفظ +وتحتل +وتحتمل +وتحتمي +وتحتنا +وتحته +وتحتها +وتحتوي +وتحث +وتحجر +وتحدث +وتحدثت +وتحدثتم +وتحدثنا +وتحدي +وتحديا +وتحديات +وتحديث +وتحديثها +وتحديد +وتحديدا +وتحديداً +وتحديده +وتحديه +وتحذيرات +وتحذيرهن +وتحررها +وتحرص +وتحرضهم +وتحرق +وتحرير +وتحريرها +وتحريك +وتحريم +وتحزن +وتحس +وتحسب +وتحسبين +وتحسر +وتحسن +وتحسين +وتحسينها +وتحصد +وتحصل +وتحصيل +وتحصينها +وتحصّنت +وتحضير +وتحطم +وتحطمت +وتحطيم +وتحظى +وتحـديد +وتحـليل +وتحفز +وتحفيز +وتحفيظ +وتحفيظه +وتحقق +وتحققت +وتحققه +وتحقيق +وتحقيقات +وتحقيقاتنا +وتحقيقاً +وتحقيقها +وتحكم +وتحكمت +وتحكمه +وتحكي +وتحكيان +وتحكّم +وتحل +وتحلب +وتحلل +وتحلله +وتحلم +وتحليل +وتحليلاتها +وتحليلاتهم +وتحليله +وتحليلها +وتحمر +وتحمل +وتحملون +وتحمي +وتحول +وتحولات +وتحولت +وتحولها +وتحولوا +وتحوي +وتحويل +وتحويله +وتحويلها +وتحويلهم +وتحويلهما +وتحوّل +وتحوّلات +وتحوّلاته +وتحوّله +وتحياها +وتحيط +وتحين +وتخاذل +وتخالف +وتخبرنا +وتخبّط +وتختار +وتخترق +وتختزنه +وتختفي +وتختلف +وتخدم +وتخرب +وتخرج +وتخرجت +وتخزين +وتخزينه +وتخزينها +وتخسر +وتخشاها +وتخشى +وتخصيص +وتخصَّص +وتخضع +وتخطاه +وتخطر +وتخطط +وتخطى +وتخطيطات +وتخطيطه +وتخفض +وتخفف +وتخفيض +وتخفيف +وتخلخل +وتخلف +وتخلو +وتخلي +وتخليدها +وتخليص +وتخليصها +وتخليقها +وتخليها +وتخلّفها +وتخمّر +وتخوُّفاً +وتخيل +وتخيلاته +وتخيلته +وتخييل +وتداخل +وتداخلت +وتداخلها +وتدار +وتداعبني +وتداعيات +وتدافع +وتدب +وتدبر +وتدبّ +وتدبّر +وتدجينه +وتدجينها +وتدخل +وتدخلت +وتدخين +وتدرج +وتدرجها +وتدرس +وتدرك +وتدريب +وتدريبا +وتدريبها +وتدريس +وتدريسه +وتدريسهم +وتدرّس +وتدشين +وتدعم +وتدعمها +وتدعو +وتدعونا +وتدعوني +وتدعى +وتدعي +وتدفع +وتدفق +وتدفّقت +وتدق +وتدل +وتدليكه +وتدمج +وتدمجها +وتدمرها +وتدمع +وتدمير +وتدني +وتدهشك +وتدهور +وتدور +وتدوم +وتدير +وتديرها +وتدين +وتدّعي +وتذكر +وتذكرت +وتذكرنا +وتذكرني +وتذكري +وتذليل +وتذهب +وتذوقه +وتذويب +وتذويقه +وتر +وترأس +وترأست +وترابطها +وتراث +وتراثنا +وتراثه +وتراثها +وتراثهم +وتراثية +وتراجع +وتراجعا +وتراجم +وتراحمهم +وتراقب +وتراكم +وتران +وتراه +وتربة +وتربص +وتربطهم +وتربع +وتربوي +وتربوية +وتربويين +وتربى +وتربي +وتربية +وتربيته +وتربيهم +وترة +وترتاد +وترتبط +وترتجي +وترتد +وترتدي +وترتفع +وترتقب +وترتيب +وترثي +وترجع +وترجم +وترجمت +وترجمته +وترجمها +وترجو +وترحالنا +وترحل +وترحماً +وترحيب +وترد +وتردت +وتردد +وترديده +وترسبت +وترسبه +وترسخ +وترسل +وترسيب +وترسيخ +وترشح +وترشيد +وترصد +وترصعها +وترضى +وترضي +وترطيب +وترعانا +وترعاه +وترعرع +وترعرعت +وترعى +وترفض +وترفع +وترفعه +وترفيعا +وترفيه +وترفيهية +وترقبت +وترك +وتركب +وتركت +وتركته +وتركتهما +وتركز +وتركزت +وتركنا +وتركه +وتركها +وتركهم +وتركوا +وتركوني +وتركوهم +وتركيا +وتركيب +وتركيزها +وترمي +وترميم +وترميمها +وترنحت +وترهبنوا +وترهل +وتروح +وتروعت +وتروى +وترى +وتريد +وترينداد +وترينيداد +وتزاحم +وتزامن +وتزاوج +وتزايد +وتزايدت +وتزحف +وتزداد +وتزدهر +وتزرع +وتزكي +وتزلج +وتزن +وتزوج +وتزويج +وتزويده +وتزويدها +وتزويدهم +وتزوير +وتزوّده +وتزيد +وتزيل +وتزين +وتزييفها +وتزيين +وتسألها +وتساءل +وتساءلت +وتساؤلات +وتسائلها +وتسارعت +وتساعد +وتساهم +وتسبب +وتسبيحهم +وتسبِّب +وتستأثر +وتستثنى +وتستجدّ +وتستجلي +وتستجيب +وتستخدم +وتستخدمها +وتستدرج +وتستذكر +وتسترق +وتستريح +وتستشرف +وتستشهد +وتستطيع +وتستعد +وتستعذب +وتستعرض +وتستعمل +وتستعيد +وتستفحل +وتستفزه +وتستقدم +وتستقر +وتستكين +وتستمر +وتستنزف +وتستهدف +وتستهلك +وتستهلكه +وتستوحي +وتستوعب +وتستوعبه +وتستوفي +وتسجيل +وتسحبها +وتسخير +وتسخيرها +وتسد +وتسرب +وتسرق +وتسري +وتسع +وتسعد +وتسعمية +وتسعى +وتسعي +وتسقط +وتسكبه +وتسلب +وتسلط +وتسللت +وتسللها +وتسللوا +وتسليت +وتسليم +وتسليمًا +وتسمح +وتسمع +وتسمى +وتسهب +وتسهم +وتسهيل +وتسودّ +وتسويد +وتسويق +وتسويقية +وتسير +وتسيطر +وتسيير +وتشاء +وتشابكت +وتشارك +وتشايكوفسكي +وتشبيهاتك +وتشبُّع +وتشتمل +وتشتهر +وتشتهي +وتشجع +وتشجيع +وتشحن +وتشخيص +وتشدك +وتشرب +وتشردت +وتشرده +وتشردوا +وتشرع +وتشريد +وتشريع +وتشريف +وتشرّد +وتشرّده +وتشع +وتشعباتها +وتشعر +وتشعرك +وتشفّ +وتشققها +وتشقى +وتشكل +وتشكلاته +وتشكلت +وتشكيل +وتشكيلاته +وتشكّلاته +وتشمل +وتشنج +وتشهد +وتشويه +وتشويهها +وتشوّهات +وتشيد +وتشير +وتصادر +وتصادف +وتصانيف +وتصايحهم +وتصبح +وتصحبها +وتصحيح +وتصحيحه +وتصدت +وتصدر +وتصدير +وتصدّرها +وتصرفات +وتصريحات +وتصرّف +وتصطحبه +وتصطدم +وتصعد +وتصف +وتصفية +وتصفيته +وتصل +وتصلب +وتصلح +وتصميم +وتصنع +وتصنيع +وتصنيف +وتصنيفها +وتصنيفهم +وتصنُّع +وتصور +وتصورات +وتصوراتهم +وتصوم +وتصون +وتصويب +وتصويته +وتصوير +وتصويره +وتصويرها +وتصيب +وتصير +وتصيره +وتضاء +وتضاءل +وتضاريس +وتضاعف +وتضاعفت +وتضاف +وتضافر +وتضامن +وتضحك +وتضحياته +وتضخمت +وتضرعت +وتضطلع +وتضع +وتضعفها +وتضعه +وتضليل +وتضم +وتضمن +وتضميد +وتضمينها +وتضيء +وتضيف +وتطارده +وتطال +وتطالب +وتطالع +وتطبع +وتطبعها +وتطبق +وتطبيق +وتطبيقا +وتطبيقات +وتطبيقاته +وتطبيقاتها +وتطبيقية +وتطرب +وتطرح +وتطرحها +وتطرز +وتطرق +وتطرّق +وتطل +وتطلب +وتطلبني +وتطلع +وتطلعات +وتطلعاته +وتطلعاتهم +وتطلعه +وتطلق +وتطلّ +وتطلّع +وتطمع +وتطهير +وتطور +وتطورا +وتطورات +وتطوراً +وتطورت +وتطوره +وتطورها +وتطوع +وتطوعهم +وتطول +وتطوير +وتطويره +وتطويرها +وتطويعها +وتطوّرات +وتطوّراته +وتطوّره +وتطوَّرت +وتطوُّره +وتطيح +وتطير +وتطييب +وتظافر +وتظاهرات +وتظل +وتظلل +وتظليل +وتظلّ +وتظنين +وتظنينه +وتظهر +وتعابيره +وتعارضها +وتعارفنا +وتعاضد +وتعاطف +وتعاطي +وتعاظمت +وتعاقب +وتعال +وتعالى +وتعاليمه +وتعاليمهم +وتعامل +وتعاملا +وتعاملت +وتعاملنا +وتعامله +وتعاملهم +وتعاملوا +وتعانقها +وتعاني +وتعاون +وتعاونه +وتعايشت +وتعب +وتعبئتها +وتعبر +وتعبرني +وتعبوا +وتعبير +وتعبيرا +وتعبيرات +وتعبيره +وتعتبر +وتعتبرها +وتعترف +وتعتقد +وتعتمد +وتعتنقه +وتعثر +وتعجب +وتعجز +وتعد +وتعداد +وتعدد +وتعددت +وتعديل +وتعديلاته +وتعذر +وتعرض +وتعرضه +وتعرضها +وتعرضهم +وتعرضوا +وتعرف +وتعرفت +وتعريته +وتعريف +وتعريفات +وتعريفية +وتعزز +وتعزيز +وتعزيزها +وتعشق +وتعشقها +وتعصف +وتعطي +وتعطيل +وتعطيلها +وتعطينا +وتعطّرت +وتعظم +وتعقب +وتعقد +وتعقدت +وتعقّدت +وتعكس +وتعكف +وتعلق +وتعلقت +وتعلقنا +وتعلقي +وتعلم +وتعلمت +وتعلمن +وتعلمنا +وتعلموا +وتعلو +وتعلي +وتعليب +وتعليق +وتعليقًا +وتعليم +وتعليمهم +وتعلّقت +وتعمر +وتعمل +وتعمير +وتعميق +وتعميقها +وتعميم +وتعمّق +وتعنى +وتعني +وتعهداتهم +وتعود +وتعودنا +وتعول +وتعويض +وتعي +وتعيث +وتعيد +وتعيش +وتعيشه +وتعين +وتعيين +وتعيينهم +وتفاؤلها +وتفادي +وتفادياً +وتفاسير +وتفاصيل +وتفاعل +وتفاعلاً +وتفاقم +وتفاقمت +وتفاهة +وتفاهم +وتفاوتت +وتفتتح +وتفتح +وتفترض +وتفتك +وتفتيح +وتفتيق +وتفجر +وتفجير +وتفحصي +وتفرجت +وتفرح +وتفرخ +وتفرز +وتفرش +وتفرض +وتفرعاتها +وتفرعت +وتفرقة +وتفسير +وتفسيرها +وتفسيرًا +وتفشت +وتفشي +وتفصيلا +وتفصيلاته +وتفصيليًا +وتفضح +وتفضل +وتفضي +وتفعل +وتفعيل +وتفقده +وتفكر +وتفكير +وتفكيره +وتفكيرها +وتفكيرهم +وتفكيري +وتفكيك +وتفلح +وتفهم +وتفهمهم +وتفوق +وتفوقت +وتفوقه +وتفوّقها +وتفيد +وتفيدنا +وتقابل +وتقاتل +وتقادم +وتقارب +وتقاس +وتقاطيعي +وتقاعسهم +وتقاليد +وتقاليدنا +وتقاليده +وتقاليدها +وتقاليدهم +وتقبل +وتقبله +وتقبلها +وتقبيلاً +وتقبّله +وتقترب +وتقتصر +وتقتل +وتقدر +وتقدم +وتقدمت +وتقدمه +وتقدمها +وتقدير +وتقديره +وتقديري +وتقديرًا +وتقديس +وتقديم +وتقديمه +وتقديمها +وتقدَّم +وتقرأه +وتقرح +وتقرفصت +وتقريب +وتقريبا +وتقرير +وتقسيم +وتقسيماتهم +وتقسيمه +وتقشعر +وتقصه +وتقطر +وتقطعت +وتقع +وتقف +وتقل +وتقلبات +وتقلباته +وتقلبت +وتقلص +وتقلصت +وتقلل +وتقليص +وتقليل +وتقليم +وتقلّب +وتقلَّصت +وتقنيات +وتقنياته +وتقنياتها +وتقنية +وتقهقرها +وتقواه +وتقوقع +وتقول +وتقولين +وتقوم +وتقوها +وتقوى +وتقوية +وتقويته +وتقويتها +وتقويم +وتقىيم +وتقىيمها +وتقيؤهم +وتقية +وتقيد +وتقيم +وتقيه +وتقييم +وتكاتفنا +وتكاثرت +وتكاد +وتكافؤ +وتكافح +وتكاليف +وتكاليفها +وتكامل +وتكاملاً +وتكاملها +وتكايا +وتكبر +وتكتبين +وتكتمل +وتكتنزان +وتكثر +وتكثيف +وتكثيفها +وتكر +وتكرار +وتكرارا +وتكراراً +وتكرر +وتكررت +وتكرس +وتكرسها +وتكرير +وتكريسها +وتكريمها +وتكسبني +وتكسر +وتكسوها +وتكشف +وتكفينه +وتكفيه +وتكلفة +وتكلمن +وتكليف +وتكليفهم +وتكمل +وتكمن +وتكنولوجيا +وتكهن +وتكون +وتكوين +وتكوينه +وتكويني +وتلا +وتلاعب +وتلاعبوا +وتلافي +وتلافيف +وتلال +وتلامذته +وتلامذتهما +وتلاميذ +وتلاميذه +وتلاه +وتلاوات +وتلاوة +وتلاوتها +وتلبس +وتلبى +وتلبي +وتلبية +وتلتصق +وتلتقطها +وتلته +وتلتهم +وتلج +وتلح +وتلحين +وتلد +وتلزمك +وتلصق +وتلعب +وتلعبه +وتلعنه +وتلفت +وتلقائياً +وتلقائية +وتلقى +وتلقي +وتلقينهم +وتلقيها +وتلقّفها +وتلك +وتلمح +وتلمسها +وتلميذة +وتلوثها +وتلوح +وتلونها +وتلوينه +وتليفزيون +وتم +وتماثيل +وتماثيلها +وتمارس +وتمارين +وتماسكها +وتماما +وتماهى +وتمت +وتمتاز +وتمتد +وتمتص +وتمتعهم +وتمتلكه +وتمتين +وتمتّعت +وتمثل +وتمثلت +وتمثله +وتمثلها +وتمثيل +وتمثيلها +وتمثيلي +وتمثيلية +وتمثّلته +وتمجيد +وتمد +وتمددت +وتمديد +وتمر +وتمرة +وتمرح +وتمرست +وتمرين +وتمرّده +وتمزج +وتمزجها +وتمزيق +وتمس +وتمسكه +وتمشياً +وتمشيه +وتمضى +وتمعني +وتمكن +وتمكنا +وتمكنت +وتمكننا +وتمكنوا +وتمكين +وتمكينه +وتمكينهم +وتملأ +وتملك +وتمنح +وتمنحنا +وتمنحه +وتمنع +وتمنعني +وتمنعه +وتمنعها +وتمنى +وتمني +وتمنيت +وتمهيد +وتموت +وتموجات +وتمول +وتموله +وتمويل +وتمويهاته +وتميز +وتميزاً +وتميزت +وتميزه +وتميط +وتميل +وتميّزها +وتمّ +وتمَّ +وتناثرت +وتنادي +وتناديني +وتناسب +وتناسق +وتناسلاتها +وتنافسه +وتنافسهم +وتناقشنا +وتناقل +وتناقلته +وتناقلتها +وتناقلها +وتنال +وتنام +وتنامى +وتنامي +وتناول +وتناولت +وتناوله +وتنبع +وتنبيه +وتنتج +وتنتجها +وتنتزع +وتنتشر +وتنتظر +وتنتقل +وتنتقي +وتنتكس +وتنتهي +وتنجح +وتنحدر +وتنحـدر +وتنحي +وتنحّت +وتنخفض +وتندر +وتندرج +وتنزل +وتنسب +وتنسبه +وتنسجم +وتنسحب +وتنسلخ +وتنسم +وتنسى +وتنسيق +وتنسيقها +وتنسيقًا +وتنشأ +وتنشب +وتنشر +وتنشيط +وتنصب +وتنصرف +وتنصهر +وتنطبع +وتنطق +وتنطلق +وتنظر +وتنظفها +وتنظم +وتنظمها +وتنظيرا +وتنظيم +وتنظيماته +وتنفتح +وتنفجر +وتنفذ +وتنفذين +وتنفض +وتنفيذ +وتنفيذاً +وتنفيذها +وتنفّس +وتنقسم +وتنقص +وتنقصنا +وتنقل +وتنقيب +وتنقية +وتنمتيها +وتنمو +وتنمي +وتنمية +وتنميته +وتنميتها +وتنهب +وتنورات +وتنوع +وتنوعت +وتنوعها +وتنويع +وتنويعاتها +وتنوّعها +وتنوُّعاً +وتنوُّعه +وتهاجر +وتهافته +وتهامة +وتهانيهم +وتهتم +وتهجير +وتهدد +وتهدف +وتهديدات +وتهدّم +وتهذيب +وتهذّب +وتهرب +وتهرول +وتهريب +وتهريبها +وتهشيم +وتهضمها +وتهليلهم +وتهميش +وتهميشاً +وتهون +وتهويدها +وتهيأت +وتهيئة +وتهيئنا +وتهيب +وتوابع +وتوابل +وتواجده +وتواجه +وتواجهك +وتوارت +وتوارد +وتواريخ +وتوازنه +وتوازنها +وتوازنهم +وتواصلت +وتواصلها +وتواضع +وتواطأت +وتوافد +وتوافق +وتوالت +وتوالد +وتوالى +وتوالي +وتوبة +وتوتر +وتوثقت +وتوثيق +وتوثيقها +وتوجت +وتوجد +وتوجس +وتوجه +وتوجهاتها +وتوجهاتهم +وتوجهت +وتوجهه +وتوجهها +وتوجيه +وتوجيهات +وتوجيهاتها +وتوجيهاتهم +وتوجيههم +وتوحـيد +وتوحي +وتوحيد +وتوخّي +وتوديعه +وتورق +وتوزان +وتوزر +وتوزع +وتوزعه +وتوزيع +وتوزيعاتها +وتوزيعه +وتوزيعها +وتوسع +وتوسعاً +وتوسعته +وتوسل +وتوسيع +وتوسيعا +وتوسيعها +وتوصل +وتوصلت +وتوصلوا +وتوصيات +وتوصيلها +وتوضح +وتوضع +وتوضيب +وتوضيح +وتوضيحهما +وتوطدت +وتوطيد +وتوطين +وتوظيف +وتوظيفها +وتوعيتهم +وتوفر +وتوفير +وتوفيرها +وتوفيق +وتوفّز +وتوقع +وتوقعات +وتوقف +وتوقفوا +وتوقيته +وتولت +وتولد +وتولى +وتولي +وتوليد +وتوليف +وتونس +وتيار +وتيارات +وتيرامايتيكا +وتيرة +وتيسير +وتيقننا +وتين +وتَشكله +وتُبرز +وتُحمدون +وتُختصُّ +وتُعد +وتُعرف +وتُعْرض +وتُميِّز +وتُوّجت +وث +وثائق +وثائقي +وثائقياً +وثائقية +وثابة +وثار +وثاقبة +وثالث +وثالثة +وثالثها +وثانوي +وثاني +وثانيا +وثانياً +وثانية +وثانيها +وثانيهما +وثانيًا +وثبات +وثبة +وثبت +وثبتت +وثبوا +وثراء +وثرائه +وثرثرنا +وثروته +وثروتها +وثعبان +وثق +وثقافات +وثقافاتها +وثقافاتهم +وثقافة +وثقافتنا +وثقافته +وثقافتها +وثقافتي +وثقافي +وثقافيا +وثقافياً +وثقافية +وثقافيًا +وثقة +وثقل +وثقله +وثقوا +وثقى +وثلاث +وثلاثا +وثلاثة +وثلاثمئة +وثلاثمائة +وثلاثون +وثلاثين +وثلثه +وثلوج +وثمار +وثمانمائة +وثماني +وثمانية +وثمانين +وثمة +وثواره +وثوب +وثوبها +وثورة +وثورو +وثياب +وثيابها +وثيرة +وثيق +وثيقاً +وثيقة +وثيقًا +وجئت +وجاء +وجاءت +وجاءني +وجاءوا +وجائزة +وجائع +وجاحتنا +وجاد +وجادت +وجادوا +وجاذبية +وجاذبيتها +وجار +وجارت +وجازان +وجاست +وجاف +وجافة +وجاق +وجاكوزي +وجالسه +وجامايكا +وجامعات +وجامعة +وجامعتي +وجان +وجانب +وجاهزون +وجاوة +وجب +وجبات +وجباته +وجباتهم +وجبال +وجباله +وجبالها +وجبة +وجبران +وجبرت +وجبل +وجبنا +وجبهات +وجد +وجدا +وجدار +وجداره +وجدال +وجدان +وجدانا +وجدانه +وجداني +وجدانية +وجدة +وجدت +وجدتك +وجدتني +وجدته +وجدتها +وجدتهما +وجدتي +وجدتُ +وجدتُني +وجدد +وجدران +وجدل +وجدلوها +وجدنا +وجدناه +وجدناها +وجده +وجدها +وجدوا +وجدول +وجدوه +وجدوها +وجدي +وجدير +وجدّة +وجذب +وجذرية +وجذوره +وجذورها +وجذوري +وجرأة +وجرأته +وجراحيا +وجربة +وجرت +وجرح +وجرحت +وجرده +وجرفتنا +وجروح +وجرى +وجري +وجريئة +وجريجي +وجريمة +وجرّ +وجزء +وجزءاً +وجزاك +وجزر +وجزيرة +وجزّار +وجسارة +وجسد +وجسده +وجسدها +وجسدياً +وجسمه +وجسمي +وجسنا +وجشع +وجع +وجعل +وجعلت +وجعلته +وجعلك +وجعلناكم +وجعلني +وجعله +وجعلها +وجعلهم +وجعلوا +وجـرت +وجفاف +وجفت +وجفّ +وجل +وجلال +وجلالها +وجلب +وجلبة +وجلبوا +وجلد +وجلس +وجلسائه +وجلسة +وجلست +وجلنا +وجلهم +وجلي +وجليسات +وجليل +وجليّا +وجلَّ +وجماجم +وجماعات +وجماعة +وجماعية +وجمال +وجمالاً +وجماله +وجمالها +وجمالهم +وجماليا +وجماليّاتها +وجماهيريتها +وجمع +وجمعت +وجمعتني +وجمعيات +وجمعية +وجمل +وجمنازيوم +وجمهورية +وجمود +وجموع +وجميع +وجميعها +وجميل +وجميلا +وجميلة +وجمّد +وجمّل +وجناحاً +وجنبه +وجنة +وجنتها +وجندية +وجنرالاتهم +وجنس +وجنوب +وجنوباً +وجنوبه +وجنوبها +وجنوبًا +وجنوده +وجنودها +وجنى +وجني +وجنيف +وجنين +وجه +وجها +وجهات +وجهاد +وجهاده +وجهادها +وجهاز +وجهان +وجهاً +وجهة +وجهت +وجهته +وجهتها +وجهتهم +وجهدي +وجهرا +وجهك +وجهل +وجهه +وجهها +وجههِ +وجهود +وجهوده +وجهي +وجهية +وجهين +وجهينا +وجهيها +وجهَهُ +وجهِ +وجو +وجوائز +وجوابي +وجواتيمالا +وجوارح +وجوارحه +وجواريها +وجواز +وجواسيس +وجوامع +وجوانحه +وجوب +وجوتيريزناصيرا +وجوجان +وجود +وجودالوب +وجوداً +وجودة +وجودك +وجودنا +وجوده +وجودها +وجودهم +وجودي +وجودية +وجوديّ +وجوديًّا +وجورج +وجوزف +وجوسلين +وجوعى +وجولة +وجولييت +وجوم +وجومه +وجوه +وجوهراً +وجوهرية +وجوهنا +وجوهها +وجوههم +وجوههن +وجويدي +وجوِّ +وجيانا +وجيدة +وجيرانه +وجيرانها +وجيراني +وجيروم +وجيزة +وجيشه +وجيعتة +وجيل +وجيمس +وجيه +وجيوبه +وجيوشا +وجيولوجي +وجُعلت +وجّه +وجَّه +وحائط +وحائل +وحاجاته +وحاجاتهم +وحاجبان +وحاجة +وحاجتها +وحادة +وحادثة +وحاده +وحاراتها +وحارب +وحاربا +وحاربوه +وحارة +وحارته +وحارس +وحاز +وحاسبات +وحاسما +وحاشيته +وحاصر +وحاصرها +وحاضر +وحاضرة +وحاضرت +وحاضرنا +وحاضره +وحافزاً +وحافظ +وحافظت +وحاكم +وحاكمها +وحال +وحالات +وحالاتي +وحالة +وحالما +وحالي +وحاليا +وحالياً +وحاليين +وحامد +وحاملين +وحان +وحانة +وحاول +وحاولت +وحاولتا +وحاولوا +وحاوي +وحاويات +وحاوياتها +وحب +وحبب +وحببته +وحبه +وحبوب +وحبيبات +وحبيبته +وحبيبتي +وحبيبي +وحبيبًا +وحبيسة +وحبّ +وحتماً +وحتى +وحتي +وحثالة +وحثت +وحثّه +وحج +وحجاب +وحجاج +وحجارة +وحجازي +وحجب +وحجته +وحجز +وحجم +وحجوزات +وحجية +وحجَبَها +وحدائق +وحدات +وحداتها +وحداتٍ +وحداثة +وحداثتنا +وحداثتها +وحداثيا +وحدادي +وحدانية +وحدة +وحدةٌ +وحدته +وحدتها +وحدث +وحدثا +وحدثت +وحدثتنا +وحدثتني +وحدثته +وحدثنا +وحدد +وحددت +وحددوا +وحدق +وحدقت +وحدك +وحدنا +وحده +وحدها +وحدهم +وحدوث +وحدود +وحدويا +وحدي +وحديث +وحديثا +وحديثاً +وحديثه +وحديثها +وحديثًا +وحديقة +وحدّة +وحدّقت +وحذر +وحذرت +وحذفوها +وحذق +وحرارة +وحرارتها +وحراستها +وحران +وحرب +وحرة +وحرر +وحرسه +وحرص +وحرصا +وحرصاً +وحرصه +وحرصهم +وحرف +وحرفة +وحرفًا +وحرق +وحرقة +وحرقت +وحرقها +وحرك +وحركات +وحركاتها +وحركة +وحركتنا +وحركته +وحرمان +وحرمانه +وحرمانهم +وحرمة +وحرمتهم +وحروب +وحروبه +وحروبها +وحروف +وحروفها +وحروفًا +وحرية +وحريته +وحريتها +وحريصة +وحريٌّ +وحرّاس +وحرّان +وحزب +وحزمة +وحزن +وحزنت +وحزيناً +وحساء +وحساب +وحسابات +وحساباته +وحساسية +وحساسيتها +وحسب +وحسبان +وحسبك +وحسبنا +وحسبوها +وحسبي +وحسدت +وحسرته +وحسن +وحسياً +وحسين +وحش +وحشائش +وحشاشة +وحشاً +وحشة +وحشدًا +وحشره +وحشي +وحشيا +وحشية +وحشًا +وحصار +وحصان +وحصر +وحصل +وحصلت +وحصلوا +وحصول +وحصوله +وحصون +وحصَّل +وحض +وحضارات +وحضارة +وحضارتنا +وحضارته +وحضارتها +وحضارتهم +وحضارتي +وحضاري +وحضاريا +وحضارياً +وحضارية +وحضر +وحضرت +وحضره +وحضرها +وحضها +وحضور +وحضوره +وحضورها +وحضورهم +وحضوري +وحطم +وحطموا +وحطين +وحظ +وحظر +وحظه +وحـتي +وحـدة +وحـسب +وحف +وحفائر +وحفاوته +وحفر +وحفز +وحفزهم +وحفظ +وحفظاً +وحفظت +وحفظه +وحفظها +وحفل +وحفلات +وحفيد +وحفيدة +وحفيدته +وحفيف +وحق +وحقائب +وحقائق +وحقق +وحققت +وحققوا +وحقل +وحقله +وحقها +وحقوق +وحقوقه +وحقوقها +وحقولها +وحقيقة +وحقيقته +وحقيقتها +وحقيقيا +وحكاوي +وحكايا +وحكايات +وحكاية +وحكم +وحكما +وحكمت +وحكمته +وحكمهم +وحكموا +وحكومات +وحكومة +وحكومته +وحكى +وحكيم +وحل +وحلب +وحلبتها +وحلت +وحلفاءها +وحلفاؤها +وحلفائها +وحلقات +وحلقة +وحلقي +وحلوان +وحلواه +وحلوها +وحلويات +وحلى +وحليب +وحلَّقت +وحماة +وحماره +وحماسا +وحماسة +وحماقة +وحمامات +وحماه +وحماية +وحمايته +وحمايتها +وحمايتهم +وحمد +وحمراء +وحمص +وحمض +وحمقى +وحمل +وحملات +وحملاتهم +وحملاني +وحملة +وحملت +وحملته +وحملتها +وحمله +وحملها +وحملوا +وحملوه +وحموها +وحمي +وحميمية +وحميميتها +وحمّالة +وحمّى +وحنا +وحنان +وحنانا +وحناناً +وحنتوب +وحنين +وحواء +وحواجز +وحوادث +وحوار +وحواراتي +وحواريوه +وحواش +وحواف +وحوالى +وحوانيت +وحوران +وحورية +وحوش +وحول +وحولت +وحولتها +وحولهم +وحولوا +وحوَّلت +وحى +وحي +وحياء +وحياة +وحياته +وحياتها +وحياتهم +وحياتهما +وحياتي +وحياتيا +وحيانا +وحياً +وحية +وحيث +وحيثما +وحيد +وحيدا +وحيدات +وحيداً +وحيدة +وحيدر +وحيدها +وحيدين +وحيدًا +وحيل +وحين +وحينئذ +وحينذاك +وحينما +وحينها +وحيوانات +وحيواناتهم +وحيوانية +وحيوي +وحيوية +وحيويته +وحيّرني +وحُب +وحُبَيّب +وحُسْن +وخائف +وخائفا +وخارج +وخارجا +وخارجاً +وخارجه +وخارجها +وخارجي +وخارجياً +وخارجية +وخارطة +وخاص +وخاصة +وخاصتهم +وخاصية +وخاضوا +وخاطب +وخالد +وخالطه +وخالف +وخالية +وخاليًا +وخامات +وخاماته +وخامة +وخامس +وخامسها +وخان +وخانته +وخبر +وخبراء +وخبرات +وخبراتها +وخبراتهم +وخبرة +وخبرته +وخبرتهم +وخبرونا +وخبروها +وخبيثة +وختم +وختمت +وختمها +وخجلت +وخدم +وخدمات +وخدماتها +وخدمة +وخدمته +وخدمية +وخذ +وخذهم +وخر +وخرائط +وخراب +وخرافات +وخرج +وخرجت +وخرجنا +وخرماً +وخروج +وخروجاً +وخروجًا +وخروف +وخريجيه +وخريجيها +وخريطة +وخرّب +وخز +وخزانة +وخزينة +وخسارتنا +وخشب +وخشبة +وخشوع +وخشونة +وخشية +وخص +وخصائص +وخصائصه +وخصائصها +وخصبة +وخصص +وخصصت +وخصما +وخصوصا +وخصوصاً +وخصوصياتهم +وخصوصية +وخصوصيته +وخصوصيتها +وخصوصيتهم +وخصوصًا +وخصومات +وخصومه +وخصّت +وخضت +وخضع +وخضعت +وخط +وخطب +وخطر +وخطراً +وخطرة +وخطرت +وخطط +وخططت +وخططه +وخططها +وخطف +وخطفت +وخطوبه +وخطورة +وخطورته +وخطوط +وخطوطها +وخطى +وخطير +وخطيرة +وخفة +وخفت +وخفض +وخفضت +وخفقان +وخفي +وخلات +وخلاخيل +وخلاصات +وخلاصة +وخلافاتها +وخلافه +وخلال +وخلالا +وخلايا +وخلص +وخلعة +وخلف +وخلفت +وخلفنا +وخلفيات +وخلفية +وخلفيته +وخلق +وخلني +وخلوات +وخلود +وخلوده +وخلوه +وخليته +وخليج +وخليفة +وخليق +وخليل +وخلّفوا +وخمس +وخمسا +وخمسة +وخمسمائة +وخمسون +وخمسين +وخمّرته +وخنت +وخواب +وخواص +وخواطر +وخوان +وخور +وخوسيه +وخوف +وخوفا +وخوفاً +وخوفًا +وخيار +وخياطي +وخيال +وخيام +وخيبة +وخيبتي +وخير +وخيرات +وخيره +وخيرها +وخيط +وخيطا +وخيمة +وخيول +ود +ودأب +ودأبت +ودائما +ودائماً +ودائمًا +ودابوه +وداخل +وداخله +وداخلها +وداخلية +ودار +ودارت +وداع +وداعا +وداعة +وداعه +وداعيا +ودافئا +ودالي +وداوادة +ودايفيد +ودب +ودبلوم +ودبلوماسيون +ودبي +ودبّجت +ودجاج +ودجلة +ودحضه +ودخان +ودخل +ودخلا +ودخلت +ودخلنا +ودخلوا +ودخول +ودخوله +ودخولها +ودخيلة +وددت +ودراسات +ودراساته +ودراسة +ودراستها +ودراية +ودرايـة +ودربت +ودرة +ودرجات +ودرجة +ودرجتُ +ودرجه +ودرس +ودرساً +ودرست +ودرسه +ودرسوا +ودرنيد +ودروس +ودروع +ودريّة +ودرًس +ودرّبت +ودرّس +ودسوقي +ودع +ودعا +ودعاء +ودعائهم +ودعاة +ودعارة +ودعاه +ودعاوى +ودعت +ودعته +ودعم +ودعمه +ودعنا +ودعها +ودعوا +ودعوة +ودعوته +ودعونا +ودعوناه +ودعوني +ودعوه +ودعيت +ودفء +ودفئها +ودفاتر +ودفاعًا +ودفتر +ودفع +ودفعة +ودفعت +ودفعته +ودفعتها +ودفعنا +ودفعني +ودفعه +ودفعها +ودفعهم +ودفقة +ودفنت +ودقائقه +ودقة +ودقيق +ودقيقًا +ودقّة +ودكا +ودكان +ودكتاتورية +ودكتوراة +ودكتوراه +ودل +ودلالاته +ودلالة +ودلهي +ودليل +ودلّ +ودماء +ودمائنا +ودماثة +ودماثته +ودمار +ودمجها +ودمشق +ودمعة +ودمنة +ودموع +ودمى +ودنو +ودنيا +ودنياهم +ودنيوية +ودهاءً +ودهاليز +ودهشة +ودهشتي +ودهماء +ودوائر +ودواخلهم +ودوار +ودواعيها +ودوافع +ودوافعه +ودواوين +ودودًا +ودور +ودورات +ودورة +ودورك +ودوره +ودورها +ودوري +ودوزنة +ودول +ودولة +ودوله +ودولياً +ودولية +ودون +ودونما +ودوّنوها +ودوَّى +ودي +وديان +وديانات +وديانتهم +ودير +وديع +وديعة +وديكارت +وديكور +وديملر +ودين +ودينا +وديناً +وديني +ودينية +ودينيًّا +وديودورس +ودُرَّة +ودُعي +ودُعيتُ +ودّ +ودّع +ودّها +ودّهم +ودَّعت +وذئب +وذات +وذاته +وذاتهم +وذاع +وذاعت +وذاك +وذاكرات +وذاكرته +وذاكرتي +وذبابة +وذبح +وذبحوهم +وذبذبات +وذبول +وذراعيها +وذروة +وذرّ +وذقنه +وذكاءهم +وذكر +وذكرت +وذكرتها +وذكره +وذكرهم +وذكروا +وذكرى +وذكريات +وذكي +وذلة +وذلك +وذهابا +وذهاباً +وذهابه +وذهب +وذهبا +وذهبت +وذهبوا +وذهل +وذهنا +وذهنياً +وذهنية +وذو +وذوبان +وذوبانها +وذوق +وذوقه +وذوي +وذويكم +وذوينا +وذويه +وذويهم +وذي +وذيلها +ورءوس +ورءوسهم +ورآها +ورأت +ورأته +ورأس +ورأسه +ورأوا +ورأوه +ورأى +ورأي +ورأيت +ورأينا +ورأيها +ورأيي +ورؤساء +ورؤى +ورؤي +ورؤيا +ورؤية +ورؤيته +ورؤيتها +ورئاسة +ورئاستها +ورئيس +ورئيساً +ورئيسة +ورئيسه +ورئيسًا +وراء +وراءنا +وراءه +وراءها +وراءهم +وراءهما +وراءي +ورائحة +ورائد +ورائدا +ورائداً +ورائعة +ورائك +ورائه +ورائها +ورائي +ورابطة +ورابطته +ورابع +ورابعة +ورابعها +وراثة +وراثي +وراثيا +وراثياً +وراثية +وراثيٌّ +وراجت +وراجيف +وراح +وراحة +وراحت +وراسب +وراسل +وراعه +ورافداً +ورافض +ورافقوني +وراق +وراقب +وراقصون +وراكب +ورام +ورب +ورباب +ورباط +ورباطة +ورباعا +وربت +وربط +وربطها +وربطهم +وربطوا +وربع +وربما +وربنا +وربه +وربيع +وربيعاً +وربيعة +وربيكا +ورث +ورثائه +ورثاه +ورثت +ورثته +ورثنا +ورثها +ورثوها +ورجاؤهم +ورجائهم +ورجاحة +ورجال +ورجالا +ورجالاً +ورجاله +ورجالها +ورجاه +ورجتني +ورجع +ورجعت +ورجعوا +ورجل +ورجلاها +ورجليه +ورحابة +ورحب +ورحت +ورحـلات +ورحلات +ورحلاته +ورحلة +ورحلت +ورحلته +ورحلوا +ورحم +ورحمة +ورحمتهم +ورحمك +ورخاء +ورخاءها +ورخص +ورخيصة +ورد +وردا +ورداً +وردة +وردت +وردد +ورددت +وردزورث +وردع +وردن +وردي +وردية +وردّا +وردّه +وردّي +ورزازات +ورزقت +ورسائل +ورسالته +ورسالتها +ورسام +ورساماً +ورسب +ورسله +ورسم +ورسمت +ورسمنا +ورسمها +ورسموا +ورسواً +ورسوله +ورسوم +ورش +ورشا +ورشاقته +ورشاوى +ورشة +ورشح +ورشحت +ورشفة +ورشيد +ورشَّاش +ورصاصة +ورصد +ورصها +ورصيده +ورصيفاتها +ورضاً +ورضوي +ورضيت +ورضيعها +ورطبة +ورطة +ورطوبة +ورطوبته +ورع +ورعاية +ورعايته +ورعايتها +ورعايتهم +ورعاً +ورعبي +ورعدة +ورعونته +ورفاق +ورفاهية +ورفت +ورفض +ورفضت +ورفضها +ورفضوا +ورفضي +ورفع +ورفعا +ورفعة +ورفعت +ورفعتها +ورفعه +ورفعها +ورفق +ورفقاء +ورفقائه +ورفيف +ورفيق +ورفيقة +ورفيقي +ورق +ورقابتها +ورقاً +ورقة +ورقتان +ورقتك +ورقته +ورقتها +ورقتي +ورقص +ورقم +ورقما +ورقمها +ورقمي +ورقي +ورقيت +ورقيقًا +ورقيه +ورقيهم +ورقّم +ورك +وركام +وركب +وركز +وركضت +وركضنا +وركضي +وركوب +وركود +ورليانز +ورماد +ورمالها +ورمبيك +ورمته +ورمتهما +ورمز +ورمزا +ورمزي +ورمضاء +ورمضان +ورمقتهم +ورموز +ورموزها +ورمى +ورمية +ورهافتها +ورهيبا +وروائح +وروائحه +وروائية +ورواة +ورواد +وروادا +وروادع +ورواده +وروادها +ورواسب +وروافد +وروافده +ورواها +وروايات +ورواياتي +ورواية +وروايته +وروج +وروجر +وروح +وروحانية +وروحه +وروحها +وروحي +وروحية +ورود +وروسيا +وروضة +وروعة +وروعتها +وروعي +وروما +وروماني +ورومانية +وروميو +ورونقا +ورونقه +ورونقها +وروى +ورويت +وريادتها +ورياض +ورياضة +وريث +وريثاً +وريدية +وريزا +وريفل +وريقات +وريقة +وريم +وريموند +ورُزق +ورُزِقَ +وزائريه +وزائريها +وزاد +وزادت +وزادها +وزار +وزارات +وزارة +وزارته +وزارتهم +وزارتي +وزارع +وزاره +وزاروب +وزالت +وزامل +وزاول +وزبيدة +وزج +وزجاجات +وزجاجته +وزجرته +وزجره +وزجّ +وزحزحة +وزحمة +وزخارف +وزخارفه +وزخرفة +وزخم +وزخمها +وزراء +وزرائه +وزراعتها +وزراعياً +وزراعيين +وزرزي +وزرع +وزرعت +وزرعنا +وزرقاء +وزرقة +وزركشته +وزرنا +وزع +وزعت +وزعم +وزعماء +وزعمائه +وزعمائها +وزعيق +وزعيمه +وزقاق +وزكاة +وزكريا +وزكى +وزكي +وزكّاني +وزلفى +وزليطن +وزمرها +وزملاؤه +وزملائه +وزملائي +وزمن +وزمنيًا +وزميلاه +وزميلتي +وزميلي +وزن +وزناً +وزنه +وزنها +وزنوجا +وزني +وزنِها +وزهادة +وزهد +وزهرة +وزهيد +وزهير +وزهّده +وزواجها +وزوار +وزوارقها +وزواره +وزوالها +وزوايا +وزوجاته +وزوجة +وزوجته +وزوجه +وزوجها +وزوجي +وزودت +وزوّدت +وزوّر +وزيادة +وزيارة +وزير +وزيرا +وزيراً +وزيرة +وزيرستان +وزيره +وزيرًا +وزيرَه +وزيفا +وزيمان +وزيمبابوي +وزين +وزينها +وزينوا +وزيني +وزّعت +وسأبدأ +وسأبقى +وسأتفهم +وسأحاول +وسأخبرك +وسأختم +وسأخص +وسأذكر +وسأذهب +وسأراقب +وسأريك +وسأستمتع +وسأعطي +وسأعلمك +وسأعود +وسأل +وسألت +وسألته +وسألتهم +وسألنا +وسأله +وسألها +وسأمضي +وسأنشره +وسأُنصت +وسؤال +وسؤاله +وسائح +وسائد +وسائر +وسائط +وسائق +وسائقها +وسائل +وسائلنا +وسابقتها +وسابقه +وسابك +وساحات +وساحرة +وساحل +وساخرة +وساد +وسادة +وسادته +وسادتي +وسار +وسارا +وسارت +وسارس +وسارع +وساطة +وساطته +وساعات +وساعة +وساعتها +وساعد +وساعدت +وساعدني +وساعده +وساعدها +وسافر +وسافرت +وساقه +وساكنتُ +وساكنوها +وساكني +وسال +وسالماً +وسام +وساما +وسامرّاء +وسامسونج +وساموا +وسامي +وسان +وسانتا +وسانتاماريا +وساندت +وسانده +وساهم +وساهمت +وساهموا +وساوره +وسبب +وسببها +وسببًا +وسبع +وسبعا +وسبعة +وسبعين +وسبك +وسبل +وسبيلا +وست +وستأتي +وستؤتي +وستبدأ +وستبقى +وستة +وستتضمن +وستتم +وستتوقف +وستدفع +وسترابو +وسترى +وستسمح +وستصفى +وستضم +وستطلق +وستظل +وستعاني +وستعكف +وستعيش +وستفرض +وستقام +وستقدم +وستقول +وستقوم +وستكون +وستمائة +وستمتدُ +وستمنح +وستنجهاوس +وستون +وستين +وستينيات +وسجادها +وسجداً +وسجل +وسجلت +وسجلنا +وسجلناها +وسجن +وسجني +وسجون +وسجونها +وسجيتها +وسحب +وسحبناه +وسحبها +وسحر +وسحره +وسحق +وسحنتي +وسخانات +وسخة +وسخر +وسخرها +وسخريته +وسخونة +وسخّر +وسد +وسداد +وسدنة +وسر +وسراج +وسرادق +وسرادقات +وسرح +وسرطان +وسرطانات +وسرعان +وسرعة +وسرقا +وسرقاتهم +وسرقة +وسرقت +وسروج +وسريان +وسريع +وسط +وسطا +وسطح +وسطحا +وسطحه +وسطه +وسطها +وسطوعها +وسطي +وسطيا +وسع +وسعاد +وسعادة +وسعادةً +وسعادتهم +وسعة +وسعت +وسعتها +وسعد +وسعدت +وسعدنا +وسعدي +وسعر +وسعف +وسعها +وسعهم +وسعهما +وسعى +وسعي +وسعيا +وسعيد +وسعيدة +وسعينا +وسعيه +وسعيها +وسعيهم +وسعيهما +وسـكون +وسـلِّمت +وسفارات +وسفاري +وسفر +وسفرا +وسفراء +وسفره +وسفير +وسفيره +وسقط +وسقطت +وسقف +وسقفها +وسقوط +وسقى +وسكاكين +وسكان +وسكانها +وسكب +وسكر +وسكريات +وسكنت +وسكنتها +وسكنها +وسكون +وسكينة +وسلاحهم +وسلاحي +وسلاسة +وسلاسل +وسلالات +وسلام +وسلاماً +وسلامة +وسلاّلة +وسلب +وسلبياته +وسلبية +وسلس +وسلسلة +وسلسلتا +وسلط +وسلطات +وسلطة +وسلطتها +وسلعة +وسلف +وسلفن +وسلم +وسلمان +وسلمه +وسلمى +وسلوكا +وسلوكك +وسلوكها +وسلوكهم +وسلوكيات +وسلوكياتهم +وسلوكية +وسلوى +وسليط +وسليما +وسليمان +وسليماً +وسليمي +وسلّمني +وسلِّم +وسماء +وسمات +وسماته +وسماتها +وسماحة +وسماد +وسماعه +وسماكة +وسماه +وسماها +وسمة +وسمت +وسمح +وسمرقند +وسمع +وسمعت +وسمعته +وسمعوا +وسمكة +وسمكها +وسممت +وسمي +وسمية +وسميت +وسميته +وسنة +وسنتريس +وسنتناول +وسنتين +وسنجار +وسنجد +وسنجعل +وسنحاول +وسنحظى +وسنركز +وسنعرض +وسنفتح +وسنكون +وسنوات +وسنين +وسهل +وسهلا +وسهلوا +وسهول +وسهولة +وسهومه +وسوء +وسواء +وسوابق +وسواتر +وسواحل +وسوار +وسواكن +وسواه +وسواها +وسواهم +وسواهما +وسواهن +وسواي +وسودنة +وسوريا +وسورية +وسورينام +وسوزان +وسوطه +وسوف +وسوق +وسوى +وسويسرا +وسيأتي +وسياحة +وسياحية +وسيادة +وسيادتها +وسيارات +وسياراتنا +وسياراتهم +وسيارة +وسياسات +وسياسة +وسياسته +وسياسي +وسياسيا +وسياسياً +وسياسية +وسياسيًّا +وسياط +وسياقها +وسيبقى +وسيتادل +وسيتبع +وسيتطلب +وسيتعرض +وسيتم +وسيتواجد +وسيجتمع +وسيجما +وسيحافظ +وسيحقق +وسيحوت +وسيد +وسيدته +وسيدي +وسيرة +وسيرتفع +وسيركع +وسيستفيد +وسيسحقوننا +وسيسهم +وسيشعر +وسيشكل +وسيصدح +وسيضيف +وسيط +وسيطا +وسيطر +وسيطرة +وسيطرت +وسيطروا +وسيظل +وسيعاد +وسيعرف +وسيعود +وسيق +وسيقانها +وسيقدم +وسيكتشف +وسيكولوجية +وسيكون +وسيلان +وسيلة +وسيلته +وسيلتهم +وسيلتي +وسيلعب +وسيله +وسيم +وسيماً +وسيمون +وسينا +وسيناريو +وسينتج +وسينمائية +وسيور +وسيول +وسيُقدّر +وسُجلت +وسُجن +وسُرقت +وسُكنى +وسّع +وشأنك +وشأننا +وشأنه +وشؤون +وشؤونها +وشئ +وشئت +وشئون +وشاء +وشائج +وشاب +وشاح +وشاخ +وشاخصة +وشاربي +وشارح +وشارحا +وشارع +وشارك +وشاركت +وشاركتهما +وشاركها +وشاشات +وشاشتي +وشاطئ +وشاطئا +وشاطئها +وشاع +وشاعت +وشاعر +وشاعرا +وشاعرية +وشاقة +وشاكر +وشامبليون +وشاملا +وشاهد +وشاهدا +وشاهدته +وشاهدنا +وشاهدها +وشاي +وشايات +وشباب +وشبابنا +وشبابها +وشبابي +وشبان +وشباناً +وشبك +وشبكات +وشبكة +وشبه +وشتائم +وشتاتنا +وشتبي +وشتلات +وشجاعة +وشجاعته +وشجاعتها +وشجر +وشجع +وشجعني +وشجعه +وشجيرات +وشحات +وشحذ +وشخصه +وشخصيات +وشخصياته +وشخصية +وشخصيتي +وشخوص +وشد +وشدة +وشدت +وشديد +وشديدة +وشدَّ +وشذاك +وشذوذ +وشراء +وشرائح +وشرائحها +وشرائحهم +وشرائط +وشراب +وشراع +وشراهة +وشرب +وشربا +وشربهم +وشرح +وشرحه +وشرط +وشرعا +وشرعت +وشرعته +وشرعنا +وشرعية +وشرف +وشرفا +وشرفة +وشرفه +وشرفها +وشرق +وشرقاً +وشرقها +وشرقي +وشرقية +وشركاء +وشركات +وشركاتها +وشركاه +وشركة +وشرم +وشره +وشرها +وشروح +وشروحاتها +وشروحها +وشروطها +وشريان +وشريحة +وشرير +وشريط +وشريعة +وشرّها +وشطحات +وشطّوا +وشظايا +وشعائر +وشعار +وشعاراتية +وشعارنا +وشعاع +وشعب +وشعبان +وشعبه +وشعبي +وشعبية +وشعر +وشعراء +وشعرت +وشعرنا +وشعره +وشعرها +وشعرهم +وشعروا +وشعري +وشعوبها +وشعور +وشعورها +وشفافية +وشفافيته +وشفاهنا +وشفتاه +وشفتيه +وشفتيها +وشفراتها +وشفروليت +وشفقته +وشفي +وشفيت +وشفيق +وشفّافاً +وشفّها +وشق +وشقته +وشقيقاه +وشقيقتها +وشقيقها +وشقيقي +وشك +وشكرا +وشكراً +وشكرت +وشكرته +وشكل +وشكلا +وشكلت +وشكله +وشكلها +وشكه +وشكواه +وشكوكو +وشكّك +وشلاتين +وشلبي +وشلٌ +وشمال +وشمالاً +وشماله +وشماً +وشمعة +وشمل +وشملت +وشممنا +وشمول +وشنقه +وشنّوا +وشهاب +وشهادات +وشهادة +وشهد +وشهدت +وشهرة +وشهرته +وشهور +وشهيد +وشهيدها +وشوارب +وشوارع +وشوارعها +وشواطئ +وشوال +وشواهد +وشوق +وشوقي +وشوكها +وشوهها +وشى +وشيء +وشيئا +وشيئاً +وشيجة +وشيخ +وشيراتون +وشيع +وشيعية +وشيكا +وشيوخ +وشيّدوا +وشَبَّت +وشُتِّت +وصابون +وصاح +وصاحب +وصاحباه +وصاحبنا +وصاحبيه +وصاحت +وصادرت +وصادف +وصادقة +وصادقت +وصادقين +وصار +وصارت +وصارحيني +وصاروا +وصافحه +وصافياً +وصالة +وصالحة +وصالون +وصامتة +وصايا +وصاية +وصايتها +وصايتهم +وصب +وصبا +وصباح +وصباه +وصباي +وصبر +وصبرنا +وصبره +وصبري +وصحار +وصحارى +وصحاريها +وصحافياً +وصحبته +وصحة +وصحراء +وصحـاريها +وصحفي +وصحفيا +وصحوات +وصحوه +وصحية +وصحيح +وصحيفة +وصخرة +وصداقة +وصدام +وصدح +وصددته +وصدر +وصدرت +وصدره +وصدرَتْ +وصدق +وصدقت +وصدقوني +وصدقي +وصدى +وصديقه +وصديقي +وصراحة +وصراعات +وصراعاتنا +وصراعاته +وصراعاتها +وصراعاتهم +وصراعهما +وصرت +وصرتما +وصرح +وصرخ +وصرخة +وصرخت +وصرخوا +وصرف +وصرفها +وصرنا +وصعب +وصعباً +وصعد +وصعوبة +وصعود +وصف +وصفا +وصفاقس +وصفاً +وصفة +وصفت +وصفتنني +وصفته +وصفتها +وصفحاته +وصفحة +وصفعه +وصفقاتها +وصفه +وصفها +وصفهم +وصفوة +وصفوه +وصفية +وصفيح +وصفًا +وصفٌ +وصقلها +وصك +وصل +وصلا +وصلابة +وصلات +وصلاح +وصلاحها +وصلالة +وصلب +وصلة +وصلت +وصلتك +وصلتنا +وصلتني +وصلته +وصلتها +وصلحه +وصلن +وصلنا +وصله +وصلها +وصلوا +وصلواتهم +وصلوها +وصلى +وصلي +وصمت +وصمتت +وصمد +وصممت +وصناديق +وصناعة +وصناعتها +وصناعي +وصناعية +وصندوق +وصنع +وصنعت +وصنعوا +وصنف +وصنيع +وصنّف +وصهرها +وصوب +وصوت +وصوته +وصوتها +وصوتي +وصور +وصورة +وصورت +وصوره +وصورها +وصورًا +وصول +وصولا +وصولاً +وصولنا +وصوله +وصولها +وصولهم +وصولي +وصوم +وصون +وصوناً +وصونها +وصياح +وصياحه +وصيام +وصيانة +وصيانته +وصيانتها +وصية +وصيته +وصيد +وصيدا +وصيدليات +وصيفا +وصيفتي +وصينية +وصُوّر +وضابط +وضاح +وضارة +وضاع +وضاعة +وضاعت +وضاعف +وضاقت +وضباب +وضباط +وضبط +وضبطه +وضجر +وضجيج +وضجيجا +وضجيجها +وضحاها +وضحايا +وضحك +وضحكات +وضحكاتهم +وضحى +وضحيته +وضحيتها +وضخ +وضخامة +وضخها +وضد +وضرب +وضربات +وضربه +وضربها +وضرع +وضرورة +وضروري +وضرورية +وضروريًّا +وضع +وضعا +وضعاً +وضعة +وضعت +وضعتني +وضعته +وضعتها +وضعف +وضعفت +وضعنا +وضعناها +وضعني +وضعه +وضعها +وضعهما +وضعوا +وضعوه +وضعي +وضعية +وضعيفة +وضم +وضمان +وضمت +وضمن +وضمنتها +وضمني +وضمها +وضمّوه +وضوء +وضوابط +وضواحيها +وضوح +وضوحا +وضوحاً +وضوحها +وضوحًا +وضياء +وضياع +وضياعنا +وضيع +وضيق +وضيوفه +وضيوفها +وضّحته +وضّحناه +وطءِ +وطأة +وطأت +وطئت +وطائفة +وطائفية +وطاب +وطابعه +وطابور +وطاجكستان +وطار +وطارئة +وطارت +وطازج +وطاقاته +وطاقاتها +وطاقة +وطالب +وطالباته +وطالبة +وطالبت +وطالبوا +وطالت +وطالعتني +وطالما +وطاهراً +وطاولات +وطاووس +وطب +وطبائعها +وطباع +وطبت +وطبعت +وطبعته +وطبعها +وطبعهما +وطبق +وطبقا +وطبقات +وطبقاً +وطبقة +وطبقت +وطبقنا +وطبقناها +وطبيب +وطبيعة +وطبيعتها +وطبيعي +وطبيعية +وطبَّق +وطحن +وطرأت +وطرائق +وطرائقه +وطرابلس +وطرافتهم +وطرت +وطرح +وطرحت +وطرحـها +وطرحها +وطرد +وطردوا +وطرفاية +وطرق +وطرقها +وطرميسين +وطروحات +وطروحك +وطريق +وطريقة +وطريقته +وطريقتهم +وطرْق +وطشقند +وطعام +وطعامها +وطعم +وطعمه +وطعمها +وطفلة +وطفيليات +وطقطقات +وطقوس +وطلائه +وطلاب +وطلابه +وطلابها +وطلب +وطلباتهم +وطلبت +وطلبنا +وطلبوا +وطلخا +وطلع +وطليت +وطليطلة +وطمأنني +وطمأنينة +وطمح +وطمس +وطمست +وطموحاته +وطموحاتهم +وطموحة +وطموحي +وطن +وطنا +وطناً +وطنطا +وطنك +وطنكم +وطننا +وطنه +وطنها +وطنهم +وطنى +وطني +وطنية +وطنٍ +وطه +وطهران +وطوائف +وطوال +وطوب +وطوبة +وطور +وطورها +وطوكيو +وطول +وطوله +وطويت +وطويلة +وطوّعت +وطيارات +وطيب +وطيبة +وطيد +وطيدة +وطيف +وطيلة +وطيوب +وطيور +وطيوراً +وطِيب +وظائف +وظائفهم +وظائفي +وظروف +وظروفه +وظل +وظلا +وظلال +وظلالها +وظلام +وظلت +وظللت +وظلم +وظلما +وظلمه +وظن +وظنت +وظننت +وظنوا +وظهر +وظهراً +وظهرت +وظهرها +وظهري +وظهور +وظواهرها +وظيفة +وظيفته +وظيفتها +وظيفتهم +وظيفي +وظيفياً +وظيفية +وظَّف +وعاء +وعائلاتهم +وعائلة +وعائلته +وعائلتي +وعابثا +وعابرة +وعاد +وعادات +وعاداتنا +وعاداته +وعاداتها +وعادة +وعادت +وعادل +وعادوا +وعارضا +وعارفي +وعازف +وعاش +وعاشت +وعاشقات +وعاشوا +وعاصرته +وعاطفية +وعافية +وعالج +وعالم +وعالمنا +وعالمه +وعالمها +وعالمياً +وعالمية +وعالميته +وعالمين +وعالية +وعام +وعامل +وعاملا +وعامًا +وعانق +وعانى +وعاينت +وعبء +وعبادة +وعباده +وعبارات +وعباراته +وعبارة +وعباس +وعباسيين +وعباسيّه +وعبثا +وعبثاً +وعبثاِ +وعبثت +وعبد +وعبدالباري +وعبدالجبار +وعبدالحليم +وعبدالحميد +وعبدالخالق +وعبدالرحمن +وعبدالرشيد +وعبدالعزيز +وعبدالعظيم +وعبدالقادر +وعبدالكريم +وعبدالله +وعبدالوهاب +وعبر +وعبرت +وعبقريته +وعبوات +وعبود +وعبّأ +وعبّد +وعبّرت +وعت +وعثر +وعثمان +وعثمانيين +وعجائب +وعجز +وعجزها +وعجم +وعجمهم +وعجيب +وعد +وعدا +وعداً +وعدة +وعدت +وعدتُ +وعدد +وعددها +وعددهم +وعدساني +وعدل +وعدله +وعدم +وعدمه +وعدن +وعدنا +وعدنان +وعدني +وعده +وعدها +وعدو +وعدوا +وعدوانية +وعدوٍ +وعديدة +وعديمة +وعدينا +وعدَّل +وعدُّوا +وعذاب +وعذاباته +وعذاباتهم +وعذابه +وعذابهم +وعذوبته +وعراقة +وعراك +وعرايا +وعرب +وعربدة +وعربي +وعربية +وعربيته +وعربيًّا +وعرة +وعرس +وعرش +وعرض +وعرضت +وعرضتها +وعرضه +وعرضها +وعرضهما +وعرضوها +وعرضًا +وعرف +وعرفات +وعرفانيّ +وعرفت +وعرفتهم +وعرفنا +وعرفني +وعرفه +وعرفها +وعرفوا +وعرق +وعرقلت +وعرقه +وعروبة +وعروبته +وعروبتي +وعروض +وعروضا +وعريق +وعرّجت +وعزت +وعزف +وعزلته +وعزلها +وعزم +وعزمت +وعزمه +وعزيز +وعزيمة +وعسل +وعسى +وعشاء +وعشاق +وعشتروت +وعشر +وعشرة +وعشرون +وعشرين +وعششت +وعشق +وعشقته +وعشقها +وعشياً +وعشيقها +وعصابته +وعصافير +وعصراً +وعصري +وعصرية +وعصمة +وعصوره +وعصير +وعضو +وعضوا +وعضوية +وعضويتها +وعضوًا +وعطاء +وعطاءاته +وعطار +وعطالة +وعطرها +وعطلة +وعطلوا +وعطّلوا +وعظام +وعظمة +وعظمك +وعظه +وعظيم +وعفا +وعفاف +وعفوي +وعفيف +وعقاب +وعقارات +وعقاقير +وعقب +وعقبات +وعقد +وعقدت +وعقل +وعقلا +وعقلاني +وعقلي +وعقلية +وعقليّ +وعقود +وعقول +وعقولنا +وعقيدة +وعقيدته +وعقيدتهم +وعقيل +وعكا +وعكاشة +وعكة +وعكس +وعكف +وعلا +وعلائقه +وعلاج +وعلاقات +وعلاقاتهما +وعلاقة +وعلاقته +وعلاقتها +وعلاقتهما +وعلال +وعلامات +وعلامة +وعلامتيه +وعلاوة +وعلب +وعلت +وعلته +وعلق +وعلقت +وعلقتها +وعلقتهما +وعللت +وعلم +وعلما +وعلماء +وعلمائنا +وعلمانيين +وعلماً +وعلمت +وعلمني +وعلمه +وعلمها +وعلمي +وعلميا +وعلمية +وعلميًا +وعلو +وعلوم +وعلوماً +وعلومه +وعلى +وعلي +وعليك +وعلينا +وعليه +وعليها +وعليهما +وعليّ +وعلّقه +وعلّم +وعما +وعمادة +وعمال +وعمد +وعمدة +وعمدت +وعمر +وعمرانية +وعمرة +وعمره +وعمرها +وعمري +وعمق +وعمقاً +وعمقه +وعمقها +وعمل +وعملائه +وعملائها +وعملت +وعملهم +وعملوا +وعملي +وعمليا +وعمليات +وعملية +وعموديته +وعموم +وعموماً +وعمي +وعميدة +وعميق +وعميقا +وعميقة +وعمّا +وعمّر +وعمَّت +وعن +وعناء +وعناصر +وعناصري +وعناية +وعند +وعندئذ +وعندما +وعندنا +وعندها +وعندهم +وعندي +وعنفا +وعنفوانهم +وعنهم +وعنوان +وعنوانه +وعنوانها +وعهدنا +وعوائدهم +وعوارض +وعواقبه +وعوالم +وعوامل +وعود +وعودا +وعودة +وعودته +وعودتهم +وعودتي +وعورة +وعورته +وعولمته +وعومل +وعويل +وعى +وعي +وعيا +وعياً +وعيت +وعيد +وعيدان +وعيشه +وعين +وعينا +وعيناك +وعيناه +وعينت +وعينه +وعينوا +وعينين +وعينيه +وعيه +وعيها +وعيهم +وعيون +وعيوننا +وعيونها +وعيونهم +وعيي +وعيًا +وعَبْر +وعُتق +وعُرضت +وعُرْسه +وعُهد +وعُيِّن +وف +وفؤاد +وفئة +وفاء +وفائدة +وفائق +وفائها +وفاة +وفاتته +وفاتـــه +وفاته +وفاتها +وفاتورة +وفاجأ +وفادتنا +وفادته +وفار +وفارس +وفارسية +وفارق +وفاروق +وفاز +وفازت +وفاطمة +وفاطميين +وفاعل +وفاعلة +وفاعلية +وفاعليتها +وفاق +وفاقت +وفاقدا +وفاقي +وفاليري +وفان +وفايز +وفايزة +وفتاة +وفتالات +وفتح +وفتحة +وفتحت +وفتحها +وفتحوا +وفتحي +وفتر +وفتشوا +وفتوحاتهم +وفتى +وفتيات +وفجأة +وفجره +وفجور +وفحص +وفحواها +وفخركم +وفخري +وفد +وفداحة +وفداً +وفدها +وفدوا +وفدوى +وفديا +وفدية +وفدًا +وفر +وفرائسها +وفرار +وفراشة +وفراملها +وفرانكفورت +وفراً +وفرة +وفرت +وفرته +وفرتها +وفرحة +وفرد +وفردها +وفردية +وفرز +وفرسا +وفرسان +وفرسانه +وفرساي +وفرسه +وفرش +وفرشاة +وفرشاتي +وفرشه +وفرص +وفرض +وفرضت +وفرضه +وفرضها +وفرضهم +وفرط +وفرع +وفرق +وفرقة +وفرنسا +وفرنسي +وفرنسية +وفرنسيس +وفرنيسيا +وفروا +وفروعها +وفريد +وفريدة +وفريق +وفريقه +وفرَّقني +وفساد +وفسفوري +وفسيولوجيًا +وفشل +وفشلت +وفصاحته +وفصلها +وفصيل +وفضاء +وفضاءات +وفضح +وفضل +وفضلا +وفضلات +وفضلاً +وفضلت +وفضله +وفضولي +وفضيلة +وفطائر +وفطريات +وفطنوا +وفعالة +وفعاليات +وفعالياته +وفعالية +وفعاليته +وفعل +وفعلا +وفعلاً +وفعلها +وفعّال +وفق +وفقا +وفقاً +وفقد +وفقدان +وفقدانه +وفقدها +وفقدوا +وفقط +وفقكم +وفقه +وفقهاء +وفقيراً +وفقًا +وفك +وفكتور +وفكر +وفكرة +وفكرت +وفكرته +وفكره +وفكري +وفكريا +وفكرية +وفكرًا +وفكّر +وفلاح +وفلاحها +وفلاسفة +وفلاسفتهم +وفلاش +وفلان +وفلج +وفلذة +وفلسطين +وفلسطينية +وفلسطينيون +وفلسفة +وفلسفته +وفلسفي +وفلسفية +وفلكلور +وفلكي +وفلل +وفلوس +وفمه +وفن +وفناء +وفنادق +وفنادقها +وفنان +وفنانا +وفنانون +وفناني +وفنانين +وفنانًا +وفناً +وفند +وفندق +وفندقها +وفندقية +وفنزويلا +وفنلندا +وفنون +وفنونه +وفنونها +وفني +وفنيا +وفنياً +وفنية +وفنيتها +وفهرس +وفهم +وفهمه +وفهمها +وفوائده +وفوائدها +وفوار +وفواكه +وفواكهها +وفوجئ +وفوجئت +وفود +وفودًا +وفور +وفورا +وفورسيزنز +وفورية +وفوزي +وفوض +وفوق +وفوقنا +وفى +وفي +وفيا +وفيات +وفية +وفيت +وفيتنام +وفير +وفيرا +وفيرة +وفيروز +وفيروسات +وفيرًا +وفيزا +وفيزياء +وفيزيائية +وفيزيقية +وفيض +وفيعام +وفيق +وفيلسوف +وفيلسوفا +وفيلمون +وفيما +وفينثنثو +وفينوس +وفينيقية +وفيه +وفيها +وفيهم +وفيًا +وفَتَنَنِي +وفَقْد +وفَلاحها +وفُتح +وفُتحت +وفُتنت +وفُقد +وفَّر +وفَّقه +وق +وقأقأ +وقائد +وقائع +وقائعها +وقائم +وقائمة +وقائي +وقائيا +وقائية +وقابل +وقابلة +وقابلتهم +وقابليته +وقابليتها +وقاتم +وقاد +وقادة +وقادت +وقادرا +وقادراً +وقاذورات +وقار +وقارئا +وقارنت +وقارنها +وقاسيا +وقاص +وقاصدي +وقاضي +وقاطن +وقاطنيه +وقاع +وقاعات +وقاعة +وقافلة +وقال +وقالا +وقالت +وقالوا +وقام +وقامت +وقامته +وقاموا +وقانوني +وقانونيا +وقانونية +وقاوم +وقاومت +وقاية +وقبائل +وقباب +وقبابه +وقبة +وقبته +وقبرص +وقبضاتها +وقبع +وقبل +وقبلت +وقبلتهما +وقبله +وقبلها +وقبلهما +وقبلوني +وقبول +وقبولا +وقبولاً +وقبيل +وقبيلته +وقت +وقتئذ +وقتا +وقتاً +وقتذاك +وقتك +وقتل +وقتلاهم +وقتلهم +وقتلوه +وقتما +وقتنا +وقته +وقتها +وقتهم +وقتي +وقتية +وقتٍ +وقتَ +وقد +وقداسة +وقدر +وقدرات +وقدراته +وقدراتها +وقدراتهم +وقدرة +وقدرةً +وقدرت +وقدرته +وقدرتها +وقدرتهم +وقدره +وقدروا +وقدري +وقدسته +وقدسية +وقدم +وقدمت +وقدمناها +وقدمني +وقدمها +وقدموا +وقدمي +وقدوة +وقدوم +وقديمة +وقذائف +وقذف +وقذفت +وقرآني +وقرأ +وقرأت +وقرأته +وقرأتها +وقرأه +وقراءاته +وقراءة +وقراءه +وقراؤنا +وقراراتي +وقراه +وقربتها +وقرر +وقررت +وقرروا +وقرصة +وقرطاج +وقرى +وقريب +وقريبا +وقريبة +وقرية +وقرّر +وقرَّبت +وقزح +وقس +وقسا +وقساوسة +وقسط +وقسم +وقسما +وقسماتها +وقسماتي +وقسمت +وقسوة +وقسوته +وقسَّموا +وقشتالة +وقشف +وقص +وقصائد +وقصة +وقصد +وقصدوا +وقصر +وقصرها +وقصص +وقصصاً +وقصصًا +وقصور +وقصيدة +وقصيدتي +وقصيرة +وقصّ +وقصّرت +وقضاء +وقضايا +وقضاياها +وقضاياهم +وقضبان +وقضمنا +وقضوا +وقضى +وقضية +وقضيت +وقطار +وقطاع +وقطة +وقطر +وقطرها +وقطع +وقطعة +وقطعنا +وقع +وقعا +وقعة +وقعت +وقعنا +وقعها +وقعوا +وقـال +وقف +وقفا +وقفات +وقفاً +وقفة +وقفت +وقفته +وقفتي +وقفر +وقفز +وقفزاته +وقفزت +وقفشات +وقفصة +وقفنا +وقفوا +وقفية +وقل +وقلادة +وقلاعه +وقلب +وقلبا +وقلبها +وقلبي +وقلة +وقلت +وقلعة +وقلق +وقلقة +وقلقه +وقلقي +وقلل +وقللت +وقللوا +وقلم +وقلما +وقلماً +وقلمه +وقلنا +وقليت +وقليل +وقليلا +وقليلات +وقليلاً +وقليلة +وقلّد +وقمت +وقممه +وقمنا +وقناديل +وقناطر +وقناع +وقناعة +وقنافذ +وقنصلياتها +وقنوات +وقنيدس +وقهر +وقهرها +وقهقهاتهم +وقوات +وقواعد +وقواعده +وقوافل +وقوامه +وقوانين +وقوبلت +وقوة +وقوته +وقوتها +وقود +وقودا +وقوداً +وقودها +وقودية +وقودًا +وقورنت +وقوع +وقوعه +وقوعها +وقوف +وقوفه +وقوفها +وقوفهم +وقوله +وقومي +وقوى +وقوية +وقوّ +وقى +وقيادات +وقيادة +وقيادتها +وقياس +وقياساً +وقيام +وقيسارية +وقيض +وقيل +وقيم +وقيمة +وقيمته +وقيمتها +وقيمه +وقيمها +وقيمياً +وقُبر +وقُبَلُنا +وقُتل +وقُدمت +وكأس +وكأن +وكأنك +وكأنما +وكأننا +وكأنني +وكأنه +وكأنها +وكأنهم +وكأنهما +وكأني +وكإجراء +وكإنسان +وكائناته +وكابد +وكاتب +وكاتم +وكاد +وكادت +وكارليل +وكاسات +وكاسيو +وكافتيرات +وكافتيريا +وكافور +وكالات +وكالاتها +وكالة +وكالتين +وكالحارات +وكالطائر +وكالعادة +وكامل +وكان +وكانا +وكانت +وكانوا +وكبار +وكبح +وكبر +وكبرت +وكبرياء +وكبـرت +وكبير +وكبيرة +وكتاب +وكتاباته +وكتابة +وكتابتها +وكتابك +وكتابنا +وكتابه +وكتب +وكتبت +وكتبتهما +وكتبه +وكتبوا +وكتبًا +وكتجسيد +وكتفه +وكتفيها +وكتيب +وكتّاب +وكثافتها +وكثر +وكثرة +وكثرت +وكثير +وكثيرا +وكثيرات +وكثيراً +وكثيفاً +وكحلٌ +وكد +وكدنا +وكذا +وكذلك +وكراتشي +وكراستنا +وكراسي +وكراهيتهم +وكراون +وكربر +وكربلائيات +وكربوهيدرات +وكرة +وكررت +وكرست +وكرمه +وكروب +وكروكيات +وكروم +وكريم +وكرّست +وكرّمته +وكزبرة +وكزته +وكسا +وكسب +وكسر +وكسرت +وكسروا +وكسل +وكسوة +وكشاهد +وكشف +وكشفت +وكشمير +وكعادتها +وكعب +وكعبة +وكف +وكفاءات +وكفاءة +وكفاءته +وكفاحه +وكفالة +وكفى +وكفّنهم +وكل +وكلا +وكلاء +وكلاب +وكلام +وكلاهما +وكلف +وكلفت +وكلفهم +وكلكم +وكلما +وكلماته +وكلماتها +وكلمة +وكلنا +وكله +وكلها +وكلود +وكلوريد +وكلي +وكليا +وكليات +وكليب +وكلية +وكلَّفه +وكلَّمتُه +وكلُّه +وكم +وكما +وكمامات +وكمبردج +وكمبوديا +وكمبيدات +وكمثال +وكمسلم +وكمسلمة +وكمن +وكمية +وكن +وكنا +وكنائس +وكنانة +وكنت +وكنتيجة +وكنتُ +وكندا +وكنديات +وكنز +وكنوز +وكنوع +وكنيسة +وكهفه +وكهلاً +وكوابيسها +وكوارث +وكواليسها +وكوبا +وكوبونات +وكوجهة +وكورال +وكوراليس +وكورنيي +وكوريا +وكوستاريكا +وكوسوفا +وكوسوفو +وكوش +وكولورادو +وكولومبيا +وكوم +وكوموا +وكون +وكونداكوف +وكونه +وكونها +وكونوا +وكوّن +وكوّنا +وكوّنوا +وكي +وكيانه +وكيانها +وكيانهم +وكياني +وكيرمان +وكيف +وكيفية +وكيفيّات +وكيل +وكيلا +وكيلاً +وكيله +وكيلها +وكيماوي +وكيماويات +وكيماوية +وكيمياء +وكينونتها +وكينويل +وكينيا +وكَرَجَتْ +وكُتب +وكُتّابه +وكُرم +ول +ولآلئ +ولأجل +ولأجيال +ولأخي +ولأرى +ولأسباب +ولأسفاره +ولأشح +ولأشعة +ولأمد +ولأن +ولأنني +ولأنه +ولأنها +ولأنهم +ولأني +ولأوركسترا +ولأول +ولأولئك +ولأي +ولإدراك +ولإذكاء +ولإعالة +ولإعداد +ولإقبال +ولإقناع +ولئن +ولا +ولاء +ولاأخفيكم +ولاأزال +ولائحة +ولابد +ولابمنع +ولاتزال +ولاتعرف +ولاتفصلني +ولاتقتربوا +ولاتقتصر +ولاتقول +ولاتلبث +ولاتنداح +ولاجئيها +ولاحتمالات +ولاحظ +ولاحظت +ولاحقا +ولاحقتها +ولاد +ولادات +ولادة +ولادته +ولادتها +ولادتهم +ولادتي +ولادي +ولازالت +ولازم +ولاس +ولاسيما +ولاسيَّما +ولاشك +ولاعب +ولاعبي +ولاعصرية +ولافتات +ولاقت +ولاقطة +ولاقى +ولانتهاكات +ولانلبث +ولاننسى +ولاهي +ولاوس +ولايات +ولاية +ولايتسكر +ولايتي +ولايحافظون +ولايحسون +ولايزال +ولايستأذنونهم +ولايسمح +ولايقوم +ولايلبث +ولاينتهى +ولاينجدني +ولاينشر +ولاينفى +ولباس +ولبت +ولبست +ولبسته +ولبنان +ولبى +ولبيان +ولبيت +ولبّوا +ولتأكيد +ولتؤجج +ولتؤدوا +ولتاريخها +ولتجسيد +ولتحفيز +ولتحقيق +ولتدمير +ولتربت +ولترجمة +ولتسائل +ولتستريحوا +ولتسليط +ولتشجيع +ولتشويهها +ولتصطدم +ولتعرف +ولتعريف +ولتعزيز +ولتعلن +ولتقول +ولتكن +ولتكنْ +ولتكون +ولتكوينه +ولتلبية +ولتنفيذ +ولتنقية +ولتوفير +ولتوقع +ولثقافتها +ولجأت +ولجان +ولجانه +ولجانها +ولجت +ولجمله +ولجميع +ولجنة +ولجوءاً +ولجوئها +ولحاء +ولحاجتي +ولحال +ولحاهم +ولحركة +ولحسن +ولحظات +ولحظة +ولحق +ولحقني +ولحكومه +ولحم +ولحماية +ولحمه +ولحن +ولحنت +ولحوالي +ولحوم +ولحية +ولحيته +ولخص +ولد +ولدا +ولدافعي +ولدان +ولداً +ولدت +ولدتني +ولدته +ولدتها +ولدراسة +ولدعاوى +ولده +ولدها +ولدوا +ولدى +ولدي +ولديك +ولدينا +ولديه +ولديها +ولديهم +ولديّ +ولذا +ولذة +ولذةً +ولذته +ولذلك +ولذوقه +ولربط +ولرحلة +ولزم +ولزمت +ولزملائي +ولزوجة +ولزوجته +ولسان +ولسانه +ولسانيات +ولست +ولستُ +ولسرطانات +ولسعته +ولسعهم +ولسماع +ولسنا +ولسنوات +ولسوء +ولسوف +ولشد +ولشعب +ولشفتي +ولشيخك +ولصالح +ولصحفية +ولصدور +ولصون +ولضخ +ولضمان +ولطائف +ولطالما +ولطف +ولطيف +ولطيفة +ولع +ولعائلتها +ولعاب +ولعاً +ولعب +ولعبا +ولعبارته +ولعبة +ولعبدالجبار +ولعت +ولعدة +ولعدد +ولعدم +ولعل +ولعلك +ولعلكم +ولعلنا +ولعله +ولعلها +ولعلهم +ولعلي +ولعلّ +ولعلّني +ولعلّي +ولعلَّ +ولعه +ولعي +ولـما +ولفتت +ولفتح +ولفترات +ولفترة +ولفريق +ولفنه +ولقاء +ولقاءات +ولقاءاته +ولقاؤه +ولقاحاً +ولقب +ولقد +ولقدرتها +ولقل +ولقلدت +ولقي +ولقيتني +ولقّب +ولك +ولكاتب +ولكثير +ولكسب +ولكل +ولكلِّ +ولكم +ولكن +ولكنك +ولكننا +ولكنني +ولكنه +ولكنها +ولكنهم +ولكنهما +ولكنى +ولكني +ولكنّ +ولكنَّ +ولكوننا +ولكي +ولكيلا +وللآخرين +وللأسف +وللأسماء +وللأسواق +وللأطفال +وللأفراخ +وللإسلام +وللإعلام +وللبحر +وللبحوث +وللتأكد +وللتاريخ +وللتبادل +وللتجميل +وللتخفيف +وللتدليل +وللتساؤل +وللتعارف +وللتوجهات +وللثقافة +وللحال +وللحصول +وللحظة +وللحقيقة +وللحيرة +وللخارج +وللدهشة +وللدول +وللذهب +وللرأي +وللرجال +وللردّ +وللرواسب +وللرواية +وللزمن +وللزوار +وللسكون +وللسهر +وللشعب +وللشوارع +وللشيخ +وللضيوف +وللطبيعة +وللطلاب +وللعادات +وللعالم +وللعرب +وللعمل +وللفقراء +وللقانون +وللقطان +وللكلام +وللكلمات +وللمحافظة +وللمخطوطات +وللمدارس +وللمدينة +وللمرء +وللمراقبين +وللمرة +وللمرطبات +وللمزيد +وللمسلمين +وللمناداة +وللمواطن +وللمولوية +وللناقد +وللنحر +وللنحل +وللنشر +ولله +وللولايات +ولليمين +وللُبِّها +ولم +ولما +ولماذا +ولمبات +ولمجرد +ولمحته +ولمدة +ولمزيد +ولمس +ولمساعدة +ولمسافة +ولمسايرة +ولمست +ولمستها +ولمسنا +ولمصانع +ولمصلحة +ولمظاهر +ولمع +ولمعانيه +ولمعرفة +ولمعرفتها +ولمن +ولمنهجها +ولمواجهة +ولمواكبة +ولموضوع +ولمَّا +ولن +ولنأخذ +ولنا +ولنبدأ +ولنبل +ولنتأمل +ولنتائجها +ولنتذكر +ولنتركه +ولنتعرف +ولنجزينهم +ولندرك +ولندع +ولندن +ولنستمع +ولنعرف +ولنعطي +ولنقل +ولننتقل +ولننظر +وله +ولها +ولهديه +ولهذا +ولهذه +ولهذين +ولهم +ولهيبها +ولو +ولوائح +ولواها +ولوج +ولوجهم +ولوح +ولوحات +ولوحاتي +ولودفيح +ولوذعيته +ولوركا +ولوزة +ولوس +ولوعة +ولوقا +ولولا +ولوم +ولون +ولويزه +ولويس +ولوّن +ولى +ولي +وليؤكد +وليؤمنوا +وليال +وليالي +ولياليه +وليالٍ +وليام +وليامز +وليبرمان +وليبعث +وليبيا +وليت +وليتذكر +وليتعوذ +وليتفقد +وليتفل +وليتمان +وليتني +وليته +وليتهم +وليحدث +وليد +وليدة +وليده +وليدي +وليس +وليساعد +وليست +وليستا +وليستعذ +وليسوا +وليصلح +وليضيف +وليفين +وليكتب +وليكن +وليكون +وليل +وليلاً +وليلة +وليلى +وليم +وليمة +ولين +وليننجراد +وليوصلن +ولييها +وليّناً +ولُقّب +ولِي +ولّد +وم +ومأثورها +ومأجوج +ومأساوي +ومألوف +ومأمون +ومأمونة +ومؤازة +ومؤازرة +ومؤتمر +ومؤتمرات +ومؤتمراته +ومؤتمراتهم +ومؤثر +ومؤثرا +ومؤثرات +ومؤثراً +ومؤثرة +ومؤديا +ومؤذية +ومؤرخاً +ومؤرخي +ومؤرخيه +ومؤسس +ومؤسسات +ومؤسساته +ومؤسساتها +ومؤسسة +ومؤسسها +ومؤسسوه +ومؤسسيا +ومؤشر +ومؤلف +ومؤلفات +ومؤلفاتهم +ومؤلفاً +ومؤلم +ومؤلمة +ومؤملة +ومؤمنا +ومؤهلون +ومؤيد +ومؤيديه +ومئات +ومئذنة +وما +وماء +وماأزال +ومائة +ومائتا +ومائتى +ومائتي +ومائدة +ومات +وماج +وماجستير +وماجهل +ومادام +ومادامت +ومادة +ومادون +وماذا +ومارتن +ومارس +ومارست +وماركات +ومارنيون +ومازال +ومازالت +ومازلت +ومازلتم +ومازلنا +وماستركارد +وماضيها +وماضيهم +ومافيهما +وماكسيمو +ومالك +ومالم +ومالي +ومالية +وماليزيا +ومانتيكية +وماهو +وماهية +ومبادئ +ومبادئها +ومبادرة +ومبادلاتها +ومباركة +ومباركتهم +ومباشر +ومباشراً +ومباشرة +ومبانيها +ومبتكرة +ومبتهجاً +ومبحوحة +ومبدئية +ومبدعا +ومبدعه +ومبسطة +ومبشرين +ومبعث +ومبناها +ومبيدات +ومتأثرا +ومتأنّ +ومتابعا +ومتابعة +ومتابعته +ومتابعتها +ومتاحف +ومتاعبه +ومتاعبهم +ومتاعه +ومتباعدة +ومتباينة +ومتجدد +ومتجددة +ومتجددًا +ومتحدثا +ومتحدثاً +ومتحدثة +ومتحضر +ومتحف +ومتخاصمة +ومتخصصة +ومتخصصوه +ومتخلفة +ومتخمة +ومتداولة +ومتراكمة +ومترجما +ومترجمة +ومتره +ومتزايد +ومتسخا +ومتسقاً +ومتشحة +ومتشعبة +ومتصاعداً +ومتصل +ومتصلبة +ومتطلبات +ومتطلباتها +ومتطورا +ومتعاطفة +ومتعة +ومتعددة +ومتعرجة +ومتعصّبة +ومتعلم +ومتقنة +ومتكامل +ومتكرر +ومتلازمة +ومتمايزة +ومتمرد +ومتمردة +ومتمرسا +ومتميز +ومتميزة +ومتنقلا +ومتنوع +ومتنوعاً +ومتنوعة +ومتهالكة +ومتواصل +ومتواصلة +ومتوافر +ومتوجها +ومتوسط +ومتولدة +ومتى +ومتينا +ومثابرته +ومثبطات +ومثقف +ومثقفا +ومثقفة +ومثقفون +ومثقفينا +ومثل +ومثلت +ومثلما +ومثله +ومثلها +ومثيل +ومثّلا +ومجابهاتها +ومجاريه +ومجازر +ومجال +ومجالات +ومجالاته +ومجالاً +ومجالس +ومجانية +ومجاهدة +ومجتمع +ومجتمعا +ومجتمعاتهم +ومجتمعه +ومجتمعي +ومجدد +ومجدي +ومجدياً +ومجرى +ومجزرة +ومجلات +ومجلاتنا +ومجلاتها +ومجلاتهم +ومجلة +ومجلس +ومجلسها +ومجموعات +ومجموعة +ومجهدة +ومجهز +ومجهول +ومجيء +ومحادثات +ومحاربة +ومحاسبة +ومحاسن +ومحاضر +ومحاضراتكم +ومحاضراته +ومحاضراتها +ومحاضراتي +ومحاطة +ومحاكاة +ومحاكم +ومحاكمة +ومحاكمتهم +ومحال +ومحاليقه +ومحامي +ومحاورا +ومحاوراته +ومحاولات +ومحاولاته +ومحاولاتي +ومحاولة +ومحاولتهم +ومحب +ومحبة +ومحبي +ومحبيه +ومحبّوه +ومحترفاً +ومحتفظة +ومحتويات +ومحتوياته +ومحتوياتها +ومحجة +ومحدث +ومحدداتها +ومحددة +ومحدق +ومحدود +ومحدودة +ومحسوس +ومحطات +ومحطة +ومحطومي +ومحـتوياتها +ومحفظي +ومحفل +ومحقق +ومحققًا +ومحلات +ومحليًّا +ومحمد +ومحمود +ومحو +ومحيط +ومحيطات +ومحيي +ومخارج +ومخازن +ومخاض +ومخاطبة +ومخاطر +ومخالفتها +ومخاوف +ومخاوفهم +ومخاوفي +ومخبره +ومختار +ومختبرات +ومخترعًا +ومختصر +ومختطف +ومختلسة +ومختلف +ومختلفة +ومخربا +ومخرج +ومخرجين +ومخصبات +ومخصصة +ومخططات +ومخططاتها +ومخطوطات +ومخلفات +ومخلوق +ومخمس +ومخيلة +ومخيمات +ومد +ومدائن +ومداخل +ومداخله +ومداد +ومدارس +ومدافعا +ومدافعة +ومدافن +ومداهمته +ومدببة +ومدة +ومدت +ومدته +ومدتها +ومدح +ومدحوه +ومدراء +ومدربة +ومدرجات +ومدرساً +ومدرسة +ومدرستي +ومدرسين +ومدرسيهم +ومدرّساً +ومدعومًا +ومدققي +ومدن +ومدنهم +ومدهشة +ومدون +ومدى +ومدير +ومديراً +ومديرها +ومدينة +ومدَّ +ومذاقه +ومذكرات +ومذنب +ومذهبه +ومذهبية +ومر +ومرآة +ومرأى +ومرئية +ومرابض +ومرات +ومراجع +ومراجعات +ومراجعة +ومراجعهم +ومراحل +ومراد +ومراسم +ومراعاة +ومراعي +ومرافق +ومرافقها +ومرافقيه +ومراقب +ومراقبة +ومراقبتها +ومراقبيه +ومراكب +ومراكز +ومراكش +ومرام +ومراهقتي +ومراوح +ومراوحتها +ومربعة +ومربيّاً +ومرة +ومرت +ومرتاديه +ومرتبطة +ومرتع +ومرج +ومرجعاً +ومرجعيات +ومرجعية +ومرح +ومرحا +ومرد +ومردوده +ومرزا +ومرسم +ومرسمه +ومرسى +ومرسيليا +ومرشحة +ومرصد +ومرصعة +ومرض +ومرضه +ومرضى +ومرعبا +ومرفق +ومركب +ومركبات +ومركباته +ومركبة +ومركز +ومركزها +ومركزًا +ومرها +ومروءته +ومروجها +ومروجي +ومرور +ومرورا +ومروراً +ومرورنا +ومرونة +ومريدي +ومريديه +ومرير +ومرّ +ومرّت +ومرّر +ومرّها +ومزاراً +ومزارع +ومزايا +ومزاياه +ومزدحمة +ومزقتْها +ومزماره +ومزوراً +ومزيد +ومزيداً +ومزيدة +ومزيفا +ومسألة +ومسؤولة +ومسؤولية +ومسؤوليتها +ومسئولة +ومسئولي +ومسئولية +ومسئولين +ومساء +ومساءلة +ومساؤهم +ومسائها +ومسابقات +ومسابك +ومساجات +ومساجد +ومساجلاته +ومساحات +ومساحة +ومسار +ومسارها +ومسارًا +ومساعداً +ومساعدة +ومساعده +ومساعيه +ومسالمًا +ومسامراته +ومسامع +ومساندة +ومساهماته +ومساهمة +ومساهمته +ومساواتهم +ومسببات +ومسببة +ومسبحه +ومسبقة +ومسبِّباتها +ومستثمرين +ومستحضرات +ومستديما +ومستشار +ومستشاراً +ومستشاره +ومستشارًا +ومستشارَه +ومستشرف +ومستشفى +ومستشفيات +ومستفيدا +ومستقبل +ومستقبلاً +ومستقبله +ومستقبلهم +ومستقيمة +ومستلزمات +ومستمر +ومستمرة +ومستهل +ومستهلكة +ومستواه +ومستودعات +ومستوردة +ومستوصفا +ومستوى +ومستوي +ومستويات +ومستوياته +ومستوياتهم +ومسجد +ومسجلة +ومسحها +ومسرح +ومسرحيات +ومسرحية +ومسعود +ومسقط +ومسقوفة +ومسلسلات +ومسلطًا +ومسلم +ومسلماته +ومسلمة +ومسلمون +ومسمع +ومسموعة +ومسمّيات +ومسهمة +ومسيئاً +ومسيحية +ومسيحيهم +ومسيرته +ومسيرتي +ومسيّراً +ومشابهاتها +ومشاركة +ومشاركتها +ومشاريع +ومشاطرتي +ومشاعر +ومشاعره +ومشاعرها +ومشاعل +ومشافهته +ومشاكل +ومشاكلها +ومشاهداته +ومشاهدته +ومشاهير +ومشايخها +ومشتركة +ومشتقات +ومشتقاته +ومشجع +ومشجعا +ومشدود +ومشرئبة +ومشرب +ومشردي +ومشرف +ومشروبات +ومشروحة +ومشروع +ومشروعات +ومشروعاتها +ومشعل +ومشعلاً +ومشفقا +ومشقة +ومشكلات +ومشكلة +ومشكلتي +ومشهد +ومشوراته +ومشى +ومصابيح +ومصادر +ومصادرة +ومصادرتها +ومصادره +ومصادقة +ومصارف +ومصاريف +ومصالح +ومصالحه +ومصالحها +ومصايفها +ومصبّ +ومصداقا +ومصداقية +ومصدر +ومصدرة +ومصدرهما +ومصر +ومصروفي +ومصطفى +ومصطفي +ومصطلح +ومصطلحات +ومصفى +ومصمما +ومصنعًا +ومصنوعاته +ومصنوعاتها +ومصوراتها +ومصوع +ومصير +ومصيرية +ومضاءلة +ومضامينها +ومضت +ومضخات +ومضللة +ومضمون +ومضمونا +ومضموناً +ومضمونه +ومضنية +ومضوا +ومضى +ومضيت +ومضيفا +ومطابقة +ومطابقته +ومطاحن +ومطار +ومطارات +ومطارحة +ومطاعم +ومطالبة +ومطالبه +ومطالبها +ومطالعة +ومطبخه +ومطبوعات +ومطران +ومطربين +ومطعمة +ومطعونين +ومطلع +ومطلوب +ومطيع +ومطيعة +ومظاهر +ومظاهرات +ومظاهره +ومظاهرها +ومظلمة +ومظهرا +ومع +ومعاجم +ومعارض +ومعارضتها +ومعارضتهم +ومعارف +ومعارفهم +ومعارك +ومعاركه +ومعاصر +ومعاصريه +ومعاقبة +ومعاقبتهم +ومعالجات +ومعالجة +ومعالجته +ومعالم +ومعالمه +ومعالمها +ومعامل +ومعاناة +ومعاند +ومعانيه +ومعانٍ +ومعاهد +ومعاوية +ومعايشتهم +ومعايير +ومعبد +ومعبّرة +ومعتدل +ومعتقداته +ومعتقداتها +ومعتقل +ومعتمدة +ومعتمر +ومعدات +ومعداته +ومعدل +ومعدلات +ومعدنه +ومعدين +ومعذرة +ومعرض +ومعرضي +ومعرفة +ومعرفته +ومعرفتهم +ومعرفتي +ومعرفي +ومعروف +ومعروفاً +ومعروفة +ومعزولة +ومعسكر +ومعسكراتهم +ومعضلة +ومعطيات +ومعظم +ومعظمه +ومعظمها +ومعظمهم +ومعقد +ومعقدة +ومعكم +ومعلف +ومعلقا +ومعلما +ومعلمه +ومعلميه +ومعلنة +ومعلوم +ومعلومات +ومعلوماتها +ومعمار +ومعمول +ومعن +ومعنا +ومعناه +ومعناها +ومعنوي +ومعنويا +ومعنى +ومعنيون +ومعنيين +ومعه +ومعها +ومعهد +ومعهم +ومعوقات +ومعي +ومعيشتهم +ومفاجآت +ومفاجئ +ومفاد +ومفاده +ومفارقاتها +ومفارقة +ومفاهيم +ومفتاح +ومفتش +ومفتونا +ومفرداتها +ومفرزاتها +ومفروض +ومفروكة +ومفكر +ومفكرا +ومفكرته +ومفكرون +ومفكروه +ومفكرين +ومفكريهم +ومفكّر +ومفكّرا +ومفكّريهم +ومفهوم +ومفهومات +ومفهومه +ومفيد +ومفيداً +ومقابل +ومقابلة +ومقاتلة +ومقارنا +ومقارنة +ومقارنته +ومقاصدها +ومقاصدهم +ومقاطعة +ومقاعد +ومقالات +ومقالاتنا +ومقالاته +ومقالبه +ومقالنا +ومقاليد +ومقام +ومقامات +ومقاماته +ومقاماً +ومقامها +ومقاهي +ومقاهيها +ومقاول +ومقاومة +ومقاومته +ومقبرتي +ومقبول +ومقتضب +ومقتفيه +ومقتن +ومقتي +ومقدار +ومقدرا +ومقدرتها +ومقدرتهم +ومقدساته +ومقدمه +ومقر +ومقراً +ومقره +ومقرها +ومقننًا +ومقهى +ومقوله +ومقومات +ومقوّماتنا +ومقياسها +ومكابح +ومكابرتك +ومكاتب +ومكاتبها +ومكاسبهم +ومكافئات +ومكافحة +ومكان +ومكانة +ومكانةالمركز +ومكانته +ومكانتها +ومكانه +ومكاني +ومكانًا +ومكة +ومكتب +ومكتبات +ومكتبة +ومكتبته +ومكتبتها +ومكتبتي +ومكتبي +ومكتبيا +ومكتبًا +ومكتسبات +ومكتوب +ومكتوبه +ومكث +ومكثفة +ومكر +ومكسبا +ومكشوف +ومكناس +ومكنه +ومكونات +ومكوناته +ومكوناتها +ومكّنتها +وملء +وملأتها +وملأوا +وملاءمته +وملائكته +وملائمة +وملابس +وملابسه +وملابسها +وملابسي +وملاحظات +وملاحظة +وملاحقات +وملاحمه +وملاذا +وملازمته +وملامح +وملامحها +وملاهي +وملاهيها +وملاوي +وملايين +وملبس +وملبسة +وملتاعا +وملتبس +وملتقط +وملتقى +وملح +وملحقاته +وملحقاتها +وملحمة +وملخص +وملخصا +وملعباً +وملعمي +وملفات +وملكا +وملكة +وملما +وملموسان +وملموسة +وملونين +وملوِّثة +ومليئا +ومليئة +ومما +وممارسات +وممارساته +وممارساتها +وممارسة +وممارستها +وممالك +وممتعا +وممتعاً +وممتلئًا +وممثل +وممثلو +وممثلى +وممثلي +وممثلين +وممرات +ومملة +وممن +وممنوع +ومميزات +وممّا +ومن +ومناجم +ومناحي +ومناخية +ومنارة +ومناسبات +ومناسبة +ومناصري +ومناضلا +ومناطق +ومناطقها +ومناظر +ومناظرتها +ومنافسة +ومنافع +ومناقشات +ومناقشاته +ومناقشة +ومناقشتها +ومناهج +ومناهجه +ومناهجها +ومناهضة +ومناهضته +ومنبثقة +ومنتج +ومنتجات +ومنتجاته +ومنتجاتها +ومنتجع +ومنتجعات +ومنتجعاً +ومنتديات +ومنتشية +ومنتقاة +ومنتهى +ومنتوجاتها +ومنجزاتنا +ومنجزاته +ومنجزاتها +ومنح +ومنحت +ومنحته +ومنحنى +ومنحنيات +ومنحه +ومنحوتات +ومنخفضاته +ومندوب +ومندوبو +ومنذ +ومنذئذ +ومنزلته +ومنشئك +ومنصات +ومنصور +ومنطق +ومنطقة +ومنطقته +ومنطلقات +ومنطلقاتها +ومنطوق +ومنظم +ومنظمات +ومنظماته +ومنظمة +ومنظمى +ومنظور +ومنظومة +ومنظّرة +ومنظّم +ومنع +ومنعت +ومنعتني +ومنعطفات +ومنعوا +ومنعوه +ومنفذ +ومنفعلا +ومنفى +ومنقبتها +ومنقذنا +ومنك +ومنكمشا +ومنمنمات +ومنمنماتها +ومنه +ومنها +ومنهج +ومنهجهم +ومنهجي +ومنهجية +ومنهم +ومنهما +ومني +ومنير +ومنيرة +ومهاجرة +ومهاجريه +ومهاد +ومهارات +ومهارة +ومهارته +ومهتما +ومهتمون +ومهدئ +ومهدم +ومهدي +ومهرجان +ومهرجانات +ومهم +ومهما +ومهمات +ومهمان +ومهمة +ومهمته +ومهملات +ومهن +ومهندسا +ومهوى +ومهيبا +ومهيَّأة +ومهّدت +ومهّدوا +وموائد +ومواجهتهم +ومواد +ومواده +وموارد +ومواساة +ومواصفات +ومواصلة +ومواطنون +ومواعظ +ومواعظه +ومواقف +ومواقفه +ومواكبة +ومواكبتي +ومواهب +ومواهبها +وموته +وموثوقين +وموجة +وموجه +وموجود +وموجودًا +وموحدة +وموحية +ومودة +وموردا +وموريس +وموزونة +وموسرون +وموسكوفية +وموسم +وموسوعية +وموسى +وموسيقار +وموسيقى +وموصلا +وموصول +وموضع +وموضوعاتها +وموضوعاً +وموطن +وموطنه +وموظف +وموظفي +وموفنبيك +وموقع +وموقعه +وموقعها +وموقف +وموقفاً +وموقفه +ومول +ومولد +ومونولوجات +وموهبة +وموهبتها +وموهبتي +وموهوبا +وموّلته +ومي +وميادين +وميادينها +ومياه +ومياها +ومياهه +ومية +وميتا +وميخائيل +وميداليات +وميدان +وميدانية +وميزان +وميسر +وميسرة +وميسورو +وميض +وميعاد +وميكروبات +وميل +وميليسا +ومَن +ومَنْ +ومُسلَّمة +ومُسمعا +ومُضعِفًا +ومُنجّم +ونأمل +ونأياً +ونؤسس +ونائب +ونائيا +ونابلس +وناجحًا +وناجي +ونادر +ونادراً +ونادى +ونادي +ونادية +ونار +وناسيتوس +وناشد +وناشرا +وناضلت +وناظرها +وناقد +وناقدا +وناقدة +وناقش +وناقشتها +وناقشها +ونال +ونالت +ونام +وناميبيا +وناولني +ونايس +ونباتات +ونباتها +ونبال +ونبتـــرد +ونبدأ +ونبذل +ونبض +ونبقى +ونبهتني +ونبيل +ونبيلة +ونبيّه +ونتائج +ونتائجها +ونتاج +ونتاجها +ونتبنى +ونتج +ونتجاوزه +ونتحايل +ونتحدث +ونتحسس +ونتراشف +ونترجمها +ونترك +ونتطلع +ونتعفن +ونتفا +ونتفق +ونتماثل +ونتمناه +ونتوقع +ونتوقف +ونتيجة +ونثر +ونجاة +ونجاح +ونجاحاً +ونجاه +ونجح +ونجحت +ونجحنا +ونجحوا +ونجد +ونجده +ونجدها +ونجران +ونجعل +ونجلس +ونجم +ونجمين +ونجهل +ونجور +ونجيب +ونحاور +ونحاول +ونحت +ونحلم +ونحمد +ونحن +ونحو +ونحوها +ونحيفا +ونخرجه +ونخلص +وندر +وندرة +وندرت +وندرمير +وندعم +وندفن +وندوات +وندواته +وندى +ونذكر +ونذهب +ونرجسه +ونرجو +ونرفع +ونركب +ونرميه +ونرى +ونري +ونزاهته +ونزاهتها +ونزع +ونزعة +ونزف +ونزل +ونزهو +ونزوةُ +ونزوع +ونسألها +ونساء +ونساءً +ونسائية +ونسب +ونسبا +ونسبة +ونسبه +ونستأني +ونستحدث +ونستطيع +ونستعرض +ونستعمله +ونستـــظلّ +ونستلهم +ونستمع +ونستنكر +ونستون +ونسج +ونسجوا +ونسخ +ونسخة +ونسخها +ونسعى +ونسمع +ونسمعها +ونسميها +ونسوا +ونسى +ونسيان +ونسيب +ونسيت +ونسيج +ونسيمها +ونسينا +ونشأ +ونشأة +ونشأةِ +ونشأت +ونشأته +ونشأتها +ونشأتُ +ونشاط +ونشاطات +ونشاطاته +ونشاطنا +ونشاطه +ونشاطها +ونشاهد +ونشاهدها +ونشبت +ونشدد +ونشر +ونشرا +ونشرات +ونشرت +ونشرته +ونشرتهما +ونشره +ونشرها +ونشعر +ونشوء +ونشيده +ونشير +ونشيطا +ونص +ونصائح +ونصائحها +ونصبه +ونصحتني +ونصحه +ونصدقها +ونصدّر +ونصر +ونصف +ونصفها +ونصفٌ +ونصوص +ونصوصنا +ونصيب +ونصيبي +ونصيبين +ونصيحتي +ونضالات +ونضالاً +ونضاله +ونضالها +ونضالية +ونضجت +ونضحت +ونضحي +ونضع +ونضيع +ونطالب +ونطمئن +ونظافة +ونظافتها +ونظام +ونظاما +ونظامها +ونظر +ونظرا +ونظرات +ونظراتها +ونظراً +ونظرة +ونظرت +ونظرته +ونظرتها +ونظروا +ونظري +ونظريات +ونظرية +ونظريته +ونظرًا +ونظل +ونظم +ونظمت +ونظمته +ونظيرتها +ونظيفة +ونظّم +ونظّمت +ونعالجه +ونعتقد +ونعتمد +ونعتنق +ونعرف +ونعلم +ونعم +ونعمت +ونعمته +ونعني +ونعيش +ونعيمة +ونفاذ +ونفترق +ونفتقد +ونفخت +ونفذت +ونفس +ونفسي +ونفسياً +ونفعه +ونفق +ونفكر +ونفوذ +ونفور +ونفى +ونفيه +ونقائصه +ونقاد +ونقاده +ونقاش +ونقاشا +ونقاشاتهم +ونقاط +ونقترب +ونقد +ونقدا +ونقدم +ونقدية +ونقرأه +ونقرأها +ونقش +ونقشوا +ونقص +ونقصان +ونقضي +ونقطة +ونقطتها +ونقل +ونقلت +ونقله +ونقلها +ونقلهم +ونقلوا +ونقوداً +ونقوشاتها +ونقول +ونقوم +ونقيضه +ونقيضها +ونكبة +ونكتشف +ونكتفي +ونكشف +ونكهتها +ونكون +ونلاحظ +ونلحظ +ونما +ونماءها +ونمائهم +ونماذج +ونمت +ونمحوه +ونمر +ونمط +ونملأ +ونمو +ونمواً +ونموت +ونموذج +ونموها +ونموهم +ونموّه +ونموّهم +ونمير +ونناقش +وننام +وننتظر +وننزل +وننصح +وننظمها +وننفق +ونهاد +ونهارا +ونهاره +ونهاية +ونهايتها +ونهب +ونهبت +ونهر +ونهرب +ونهض +ونهضة +ونهضت +ونهضويّه +ونهلت +ونهلنا +ونواب +ونواجه +ونوادر +ونوادره +ونوازع +ونوال +ونواياه +ونوبل +ونور +ونورا +ونورد +ونورسك +ونوضح +ونوع +ونوعا +ونوعاً +ونوعية +ونيابة +ونياراجي +ونيرودا +ونيف +ونيكاراجوا +ونينا +ونيوترونات +ونيوجيرسى +ونيوكاليدونيا +ونيويورك +ونُبْل +ونُحرم +ونُشِرَت +ونُقلت +ونُننزل +وهأنا +وهؤلاء +وها +وهاتان +وهاجة +وهاجر +وهاجم +وهادئة +وهادفة +وهافانا +وهامته +وهامشية +وهانحن +وهاهم +وهاهو +وهاهوالقطار +وهاهي +وهاواي +وهايتي +وهبت +وهبتنا +وهبتني +وهبك +وهبكم +وهبني +وهبه +وهبوط +وهبوطا +وهبي +وهبّت +وهتف +وهجا +وهجاً +وهجر +وهجرة +وهجرته +وهجه +وهجها +وهجوم +وهدأت +وهداياه +وهدد +وهدف +وهدفاً +وهدم +وهدمه +وهدوء +وهدوءها +وهدى +وهدّأ +وهدَّد +وهذا +وهذبت +وهذه +وهران +وهرب +وهربنا +وهرعت +وهرعنا +وهز +وهزات +وهزام +وهزة +وهزله +وهزم +وهزه +وهشمت +وهضم +وهضمته +وهضمها +وهكذا +وهل +وهلاك +وهلال +وهلة +وهلعي +وهم +وهما +وهماً +وهمة +وهمس +وهمهن +وهموم +وهمومك +وهمومه +وهمومي +وهمية +وهمًا +وهمّه +وهمّي +وهمَّة +وهن +وهنا +وهناك +وهنالك +وهندسة +وهندوراس +وهندية +وهنية +وهو +وهواء +وهواتف +وهواجسه +وهوامش +وهواياته +وهوراس +وهوكثيرا +وهولندا +وهوليان +وهوليدى +وهوما +وهونج +وهوندوراس +وهوى +وهوية +وهويت +وهويتها +وهويّتها +وهى +وهي +وهيأ +وهيأت +وهيئات +وهيئة +وهيئتهم +وهيب +وهيج +وهيكل +وهيكلة +وهيكله +وهيلتون +وهيمنة +وهيمنت +وهيو +وواجب +وواجباته +وواجباتها +وواجبه +وواجه +وواجهات +وواجهت +وواحد +ووادي +ووادٍ +وواسعاً +وواشنطن +وواصل +وواضح +ووافق +وواقع +وواقعنا +وواقعه +وواقعية +وواكبه +ووالد +ووالدته +ووالدتي +ووالدك +ووالده +ووالدها +ووالدي +ووتان +ووثقوا +ووجبات +ووجبة +ووجد +ووجدان +ووجدانه +ووجداني +ووجدت +ووجدتني +ووجدته +ووجدتُ +ووجدنا +ووجده +ووجدوا +ووجدوه +ووجع +ووجنتيها +ووجه +ووجهة +ووجهت +ووجهك +ووجهه +ووجهها +ووجهي +ووجود +ووجوده +ووجوهها +ووجوههم +ووجيه +ووحدات +ووحدانا +ووحدة +ووحدتها +ووحشة +ووحيد +ووحيدة +ووحَّدت +ووخزات +ووداد +وودت +وودز +وودي +ووديانه +ووراءها +وورث +وورد +ووردة +ووردت +وورش +وورلد +وورنر +ووريثة +ووزارة +ووزراء +ووزعت +ووزعوا +ووزنه +ووزير +ووسائط +ووسائل +ووسائلها +ووساطات +ووسام +ووسط +ووسع +ووسمه +ووسمها +ووسيلة +ووصائية +ووصاية +ووصف +ووصفات +ووصفه +ووصل +ووصلت +ووصلتني +ووصلته +ووصلوا +ووصولاً +ووضح +ووضع +ووضعاها +ووضعت +ووضعتها +ووضعناه +ووضعه +ووضعها +ووضعهم +ووضعوا +ووضعوه +ووضعيته +ووضعيتها +ووضوح +ووضوحها +ووطئت +ووطنك +ووطنه +ووطنها +ووطنيته +ووظائف +ووظائفه +ووظائفها +ووظيفة +ووظيفته +ووعد +ووعدت +ووعدته +ووعدتهم +ووعدني +ووعدوا +ووعي +ووعيك +ووعيها +ووفاء +ووفائه +ووفاة +ووفاته +ووفت +ووفدوا +ووفرت +ووفرتها +ووفرنا +ووفق +ووفقا +ووفقاً +ووفقًا +ووفود +ووقائعها +ووقاحة +ووقت +ووقته +ووقع +ووقعا +ووقعت +ووقعها +ووقف +ووقفت +ووقفتم +ووقفوا +ووقوفه +ووقوفي +ووكالات +ووكالاتها +ووكالة +ووكر +وول +وولتر +وولدا +وولداه +وولدت +وولده +وولدي +وولراف +وولع +وولعت +وولف +وولونج +ووليد +ووهبني +ووهبوا +ووهج +ووهم +ووي +وويل +وويندوز +ووُفر +ووِرْد +ويأبى +ويأتون +ويأتى +ويأتي +ويأخذ +ويأخذون +ويأسفون +ويأسه +ويأكل +ويأمل +ويؤثر +ويؤخذ +ويؤخر +ويؤدى +ويؤدي +ويؤرقها +ويؤكد +ويؤكدها +ويؤلف +ويؤمن +ويؤول +ويؤيد +ويؤيده +ويا +وياسين +ويافا +ويافعاً +وياكم +وياله +وياليتها +ويامن +وياي +ويبتسم +ويبتعد +ويبث +ويبحث +ويبدأ +ويبدؤهم +ويبدع +ويبدو +ويبدي +ويبذل +ويبرز +ويبرّر +ويبشر +ويبشرنا +ويبصرني +ويبعث +ويبعد +ويبقى +ويبقي +ويبقيني +ويبكون +ويبكي +ويبنوا +ويبنون +ويبني +ويبهر +ويبهرك +ويبيعونه +ويبيعونها +ويبين +وية +ويتأخر +ويتألف +ويتأمل +ويتابع +ويتابعون +ويتاح +ويتامى +ويتبادر +ويتبادل +ويتبادلون +ويتباعد +ويتبع +ويتبينوا +ويتجاوز +ويتجدد +ويتجلى +ويتجمعون +ويتجه +ويتحاشى +ويتحتم +ويتحدث +ويتحدثون +ويتحدد +ويتحرر +ويتحرك +ويتحزم +ويتحسن +ويتحطم +ويتحقق +ويتحكم +ويتحللون +ويتحلين +ويتحمس +ويتحمل +ويتحوطون +ويتحول +ويتحولون +ويتخذ +ويتخطى +ويتخلص +ويتخلف +ويتداخل +ويتدرب +ويتدرج +ويتذكر +ويتذوق +ويترأس +ويتراءى +ويتراكم +ويتراوح +ويترجمها +ويتردد +ويترسب +ويترك +ويتركز +ويتركه +ويتركها +ويتركوا +ويتركون +ويتزاحمون +ويتزوجون +ويتساءل +ويتسارع +ويتسامرون +ويتسحب +ويتسرب +ويتسطح +ويتسع +ويتسلط +ويتسم +ويتشرّب +ويتصرفون +ويتصرّفون +ويتصف +ويتصل +ويتصور +ويتضاحكون +ويتضاعف +ويتضح +ويتضمن +ويتطاير +ويتطلب +ويتطلع +ويتطور +ويتعاطف +ويتعالى +ويتعامل +ويتعانقان +ويتعانقُ +ويتعاون +ويتعايش +ويتعبون +ويتعبّدون +ويتعدى +ويتعرض +ويتعزز +ويتعففن +ويتعلق +ويتعلم +ويتعلمون +ويتفاعل +ويتفاوت +ويتفحص +ويتفق +ويتفقون +ويتقابل +ويتقاضى +ويتقاطع +ويتقافزون +ويتقدم +ويتقرب +ويتقل +ويتقن +ويتكدس +ويتكفل +ويتكفلون +ويتكون +ويتكوّن +ويتلخص +ويتلذذ +ويتلف +ويتلقى +ويتم +ويتماسك +ويتمان +ويتماوت +ويتمتع +ويتمثل +ويتمدد +ويتمركز +ويتمنى +ويتميز +ويتميَّز +ويتناسلون +ويتناسى +ويتناقشون +ويتناول +ويتنبى +ويتنفس +ويتنفسونه +ويتنقل +ويتنقلون +ويتنوع +ويتوارى +ويتوافر +ويتوجه +ويتوسط +ويتوضأ +ويتوفرحالياً +ويتوقع +ويتوقف +ويتوقفوا +ويتولى +ويتولَّد +ويتيح +ويثبّت +ويجالند +ويجانب +ويجاهدان +ويجب +ويجتمع +ويجتهدون +ويجد +ويجدر +ويجدون +ويجدونه +ويجذبه +ويجر +ويجرجر +ويجرون +ويجرى +ويجري +ويجسد +ويجسمون +ويجعل +ويجعلن +ويجعلنا +ويجعلني +ويجعله +ويجعلها +ويجعلهم +ويجعلونها +ويجعلوها +ويجف +ويجلب +ويجلجل +ويجلس +ويجلسها +ويجلسون +ويجمع +ويجمّله +ويجنح +ويجهر +ويجود +ويجيد +ويحادثونني +ويحاذر +ويحاسبون +ويحاصر +ويحاضر +ويحاكموهم +ويحاوره +ويحاول +ويحاولون +ويحب +ويحبذها +ويحبه +ويحبها +ويحبون +ويحتاج +ويحتار +ويحتذين +ويحترم +ويحتسين +ويحتفظ +ويحتفل +ويحتكمون +ويحتل +ويحتوى +ويحتوي +ويحدث +ويحدثنا +ويحدثونك +ويحدد +ويحددون +ويحدّق +ويحرص +ويحرقون +ويحرك +ويحركُ +ويحرم +ويحرمها +ويحرمون +ويحرّك +ويحس +ويحسن +ويحصدون +ويحصر +ويحصل +ويحصلوا +ويحصلون +ويحصي +ويحضر +ويحضرني +ويحضن +ويحضونهم +ويحطم +ويحطيهم +ويحظر +ويحظى +ويحفز +ويحفظ +ويحفظون +ويحق +ويحقق +ويحك +ويحكمها +ويحكي +ويحل +ويحلق +ويحلل +ويحللها +ويحلم +ويحمل +ويحملان +ويحملن +ويحملها +ويحملون +ويحملوه +ويحمي +ويحميه +ويحول +ويحوله +ويحولها +ويحولونها +ويحوم +ويحيا +ويحيط +ويحين +ويحيى +ويحيي +ويحييهم +ويخادعها +ويخاطبوا +ويخالجها +ويخالف +ويخبر +ويخبره +ويخبرهم +ويختار +ويختتم +ويختزن +ويختزنه +ويختفي +ويختلط +ويختلف +ويختلق +ويختم +ويخدم +ويخرج +ويخرجون +ويخرجُ +ويخزن +ويخسر +ويخشى +ويخص +ويخصص +ويخطئ +ويخطب +ويخطط +ويخفض +ويخفضونها +ويخفف +ويخفي +ويخلص +ويخلف +ويخلق +ويخنقه +ويخوفونك +ويدا +ويداعبها +ويداوون +ويدخل +ويدخلوا +ويدخنون +ويدربني +ويدرس +ويدرسه +ويدرسون +ويدرك +ويدركون +ويدس +ويدعم +ويدعو +ويدعوا +ويدعون +ويدعوه +ويدعى +ويدعين +ويدفع +ويدفنون +ويدل +ويدلف +ويدمر +ويدمرون +ويدها +ويدهس +ويدهش +ويدور +ويدورون +ويدوسون +ويدون +ويدوّن +ويدي +ويدير +ويديه +ويذكر +ويذله +ويذلّل +ويذهب +ويذهبان +ويذهبن +ويذهبون +ويذوب +ويذيلها +وير +ويرأس +ويراجعها +ويراد +ويراعي +ويرافقها +ويراه +ويراها +ويراهم +ويربح +ويربط +ويربكه +ويربي +ويرتبط +ويرتبونها +ويرتدون +ويرتدي +ويرتضيه +ويرتع +ويرتعون +ويرتفع +ويرتقي +ويرث +ويرجح +ويرجع +ويرجعه +ويرجو +ويرحل +ويرد +ويردد +ويرددان +ويردّد +ويرسلها +ويرسم +ويرسمن +ويرسّب +ويرش +ويرشحها +ويرشدهُ +ويرشف +ويرشو +ويرصد +ويرضع +ويرعاه +ويرعاها +ويرعينها +ويرفض +ويرفضها +ويرفع +ويرفعون +ويرفعونها +ويرقات +ويركب +ويركبون +ويركز +ويركل +ويرمز +ويرمقني +ويرمون +ويرمي +ويروج +ويروح +ويرون +ويروى +ويروي +ويرى +ويري +ويريد +ويريدها +ويريدون +ويزحف +ويزداد +ويزرع +ويزعم +ويزعمون +ويزكيهم +ويزن +ويزهدوا +ويزور +ويزول +ويزيد +ويزيدان +ويزيده +ويزيدها +ويزيدهم +ويزيدون +ويسأل +ويسألا +ويسألني +ويسألها +ويسألهم +ويسألون +ويسارا +ويساريين +ويساعد +ويساعدني +ويساعده +ويساعدها +ويساق +ويساهم +ويساوي +ويسبب +ويست +ويستبدل +ويستبدّ +ويستبعد +ويستبيح +ويستبيحون +ويستجيب +ويستجيش +ويستحق +ويستخدم +ويستخدمه +ويستخدمها +ويستدعي +ويستذكر +ويسترجع +ويستشهدون +ويستضيف +ويستضيفان +ويستطرد +ويستطيع +ويستظل +ويستعمل +ويستعيد +ويستفز +ويستفيد +ويستقبل +ويستقبلها +ويستقبلوا +ويستقطب +ويستقى +ويستل +ويستلزم +ويستلقي +ويستمتع +ويستمتعون +ويستمد +ويستمر +ويستمعون +ويستمنستر +ويستند +ويستنكر +ويستهلكون +ويستوجب +ويستوحي +ويستوعب +ويستوعبها +ويستوقفني +ويستيقظ +ويستيقظون +ويسجل +ويسحبنها +ويسخر +ويسد +ويسدد +ويسدل +ويسر +ويسرة +ويسرت +ويسرح +ويسرق +ويسروا +ويسري +ويسطون +ويسعدني +ويسعون +ويسعى +ويسعي +ويسقط +ويسكب +ويسكنسن +ويسكونسن +ويسلبها +ويسلكن +ويسلمون +ويسمح +ويسمع +ويسمعون +ويسمونه +ويسمى +ويسمي +ويسميه +ويسميها +ويسهل +ويسهم +ويسود +ويسوقون +ويسيء +ويسيّروا +ويشار +ويشارك +ويشاركه +ويشاهد +ويشاهدها +ويشترط +ويشترك +ويشتروا +ويشتمل +ويشتمنها +ويشجع +ويشجعهم +ويشربون +ويشرح +ويشرحون +ويشرف +ويشعر +ويشعرون +ويشكر +ويشكل +ويشكله +ويشكلون +ويشكو +ويشمل +ويشن +ويشهد +ويشهداهم +ويشوه +ويشوّه +ويشوِّه +ويشيد +ويشير +ويشيرون +ويشيع +ويصاب +ويصادق +ويصافح +ويصبح +ويصبحون +ويصحبه +ويصدح +ويصدر +ويصدمون +ويصر +ويصرخ +ويصطففن +ويصعب +ويصف +ويصفق +ويصفها +ويصفون +ويصقلها +ويصل +ويصلح +ويصلني +ويصلى +ويصلي +ويصنع +ويصنعون +ويصوره +ويصوم +ويصيب +ويصيبها +ويصيخ +ويصير +ويضاعف +ويضايق +ويضبطه +ويضحك +ويضر +ويضرب +ويضطر +ويضطرب +ويضطرون +ويضطلع +ويضع +ويضعها +ويضعونها +ويضم +ويضمرون +ويضمن +ويضيء +ويضيف +ويطارده +ويطالب +ويطالبن +ويطالبنا +ويطالبون +ويطبع +ويطبعه +ويطبعون +ويطبقون +ويطرب +ويطربوا +ويطرح +ويطرحها +ويطرحون +ويطرد +ويطعمون +ويطعمونه +ويطعّم +ويطل +ويطلب +ويطلبون +ويطلق +ويطمئنهم +ويطهو +ويطور +ويطوف +ويطوّروا +ويطوّق +ويطيب +ويطير +ويطيل +ويطّرد +ويظل +ويظهر +ويعاد +ويعاني +ويعاودون +ويعاونهم +ويعبثون +ويعبر +ويعتادها +ويعتبر +ويعتبرون +ويعتدى +ويعتدي +ويعترف +ويعتزم +ويعتقد +ويعتقدون +ويعتقل +ويعتم +ويعتمد +ويعتمدون +ويعتني +ويعجب +ويعجبني +ويعجز +ويعد +ويعدد +ويعدو +ويعدون +ويعدّونهم +ويعذبني +ويعرجون +ويعرض +ويعرف +ويعرفن +ويعرفون +ويعرفَ +ويعرّضه +ويعزز +ويعزله +ويعزلها +ويعزو +ويعزى +ويعشق +ويعطـونك +ويعطل +ويعطونه +ويعطى +ويعطي +ويعطيه +ويعقب +ويعقبها +ويعكف +ويعلق +ويعلم +ويعلو +ويعلِّق +ويعمل +ويعملون +ويعنى +ويعني +ويعنيان +ويعود +ويعودوا +ويعيد +ويعيدوا +ويعيدون +ويعيش +ويعيشون +ويعينه +ويعينها +ويفاجأ +ويفاضل +ويفتتحه +ويفتتني +ويفتح +ويفتقدك +ويفجر +ويفحص +ويفر +ويفرج +ويفرح +ويفرد +ويفرض +ويفرضه +ويفرضون +ويفزعون +ويفسر +ويفشيه +ويفصلها +ويفضح +ويفضل +ويفضلون +ويفعل +ويفقد +ويفقدهم +ويفقهن +ويفكر +ويفلحان +ويفلحون +ويفهم +ويفهمها +ويفور +ويفيد +ويفيدون +ويقابل +ويقارب +ويقارن +ويقاس +ويقال +ويقام +ويقاوم +ويقبل +ويقبلها +ويقبلون +ويقتبس +ويقتتل +ويقتتلون +ويقترب +ويقترح +ويقترن +ويقتصر +ويقتضي +ويقتل +ويقتله +ويقدر +ويقدرون +ويقدم +ويقدمه +ويقدمون +ويقدنها +ويقدّر +ويقذفونه +ويقرأ +ويقرأه +ويقرأها +ويقرب +ويقرر +ويقرع +ويقرن +ويقرِّب +ويقسم +ويقسو +ويقصد +ويقصر +ويقضون +ويقضي +ويقضيها +ويقطعون +ويقطنها +ويقع +ويقف +ويقفز +ويقفون +ويقل +ويقلص +ويقلل +ويقلن +ويقلّدها +ويقود +ويقوده +ويقودهم +ويقودون +ويقول +ويقوله +ويقولون +ويقوم +ويقومون +ويقوى +ويقوّموا +ويقيد +ويقيم +ويقيه +ويك +ويكاد +ويكبد +ويكبر +ويكتب +ويكتبون +ويكتسب +ويكتشفوا +ويكتشفونه +ويكتفي +ويكتم +ويكثر +ويكذبون +ويكرر +ويكسر +ويكشف +ويكشفون +ويكفي +ويكفينا +ويكلم +ويكمل +ويكون +ويكوّن +ويلات +ويلاحظ +ويلاحظه +ويلاحقهم +ويلامس +ويلبسه +ويلبي +ويلتف +ويلتقطان +ويلتقي +ويلتمس +ويلتمسوا +ويلجأ +ويلجأوا +ويلحق +ويلخص +ويلخصان +ويلخصها +ويلز +ويلسون +ويلصق +ويلطخ +ويلعب +ويلعبان +ويلعبون +ويلف +ويلفت +ويلفظها +ويلقن +ويلقوا +ويلقون +ويلقونه +ويلقى +ويلقي +ويلكي +ويلموا +ويلنيس +ويلهب +ويلهلم +ويلهو +ويلهون +ويلوح +ويلومها +ويلون +ويلونها +ويلويها +ويلي +ويليام +ويليامز +ويليم +ويليه +ويمارس +ويمارسون +ويمازح +ويمبلدون +ويمتاز +ويمتد +ويمتصونها +ويمتلئ +ويمتلك +ويمثل +ويمثلها +ويمثلهما +ويمجد +ويمد +ويمر +ويمرّ +ويمسح +ويمسكون +ويمضي +ويمطرنا +ويمعن +ويمكن +ويمكنك +ويمكننا +ويمكنه +ويمكنها +ويمكّن +ويملأ +ويملك +ويملكهما +ويملكون +ويمنح +ويمنحه +ويمنحهم +ويمنع +ويمنعه +ويموت +ويموتون +ويميقه +ويميل +وين +ويناجيه +وينادون +ويناضل +وينال +وينبذ +وينبذها +وينبذهم +وينبع +وينبوع +وينتج +وينتحر +وينتخب +وينتربورن +وينتشر +وينتظر +وينتظروا +وينتظرون +وينتعل +وينتقد +وينتقل +وينتقم +وينتمون +وينتهك +وينتهى +وينتهي +وينجح +وينحت +وينحني +وينحون +ويندر +ويندفع +ويندمج +ويندوز +وينر +وينزل +وينساك +وينساها +وينسب +وينسبون +وينسحب +وينسلون +وينسلّ +وينسون +وينشئ +وينشد +وينشر +وينصتون +وينصح +وينضم +وينطلق +وينطوي +وينظر +وينظرون +وينظم +وينظمها +وينعكس +وينعم +وينعون +وينفتح +وينفخ +وينفي +وينقدون +وينقسم +وينقص +وينقطعون +وينقل +وينمو +وينمون +وينمي +وينهق +وينهيها +وينوي +ويه +ويهبط +ويهتضم +ويهتف +ويهتم +ويهتموا +ويهدف +ويهدفون +ويهرب +ويهرع +ويهز +ويهزلون +ويهلكها +ويهم +ويهمل +ويهملون +ويهمنا +ويهمهم +ويهمّنا +ويهندسها +ويهودية +ويواجه +ويواجهان +ويواجهنا +ويواجهون +ويوازن +ويواصل +ويوافق +ويوجد +ويوجه +ويوجهني +ويوجهها +ويوجهون +ويوحي +ويودعنا +ويورانيوم +ويورثه +ويورجنسن +ويورد +ويوسع +ويوسف +ويوسيفوس +ويوصف +ويوصلها +ويوصي +ويوصيهم +ويوضح +ويوضع +ويوفر +ويوقدونه +ويوقع +ويوم +ويومها +ويوّجه +ويَحُول +ويُترجم +ويُحكم +ويُخشى +ويُخضعها +ويُدخل +ويُذكر +ويُردُّ +ويُشترى +ويُشْرِف +ويُعرف +ويُعطى +ويُفقد +ويُلصِق +ويُمنح +ويُنسى +ويُهرِّبون +وَأُخْرِجُوا +وَأُنثَى +وَأُوذُوا +وَاللهُ +وَالَّذِينَ +وَالْمُؤْمِنَاتُ +وَالْمُؤْمِنُونَ +وَبَرة +وَجَعَلْنَاكُمْ +وَرَسُولَهُ +وَقَاتَلُوا +وَقَبَائِلَ +وَقُتِلُوا +وَقُل +وَلأُدْخِلَنَّهُمْ +وَلَج +وَلِبَاسُ +وَلِعَ +وَمَا +وَمِق +وَمِنْهُم +وَيَنْهَوْنَ +وَيُؤْتُونَ +وَيُطِيعُونَ +وَيُقِيمُونَ +وُجد +وُجدت +وُزع +وُضع +وُضعت +وُفِّق +وُلد +وُلدت +وُلدتُ +وُلدوا +وُلدِن +وُلِد +وِجاقُ +ى +ي +يأبه +يأبها +يأبى +يأت +يأتها +يأتوا +يأتون +يأتى +يأتي +يأتيك +يأتينا +يأتيني +يأتيه +يأتيها +يأجوج +يأخذ +يأخذك +يأخذن +يأخذني +يأخذه +يأخذها +يأخذهما +يأخذوا +يأخذون +يأخذونني +يأخذوني +يأسر +يأسه +يأكل +يأكلني +يأكله +يأكلها +يأكلوا +يأكلون +يأمر +يأمرني +يأمرونهم +يأمل +يأملون +يأنس +يأنف +يأوي +يأويهم +يؤبه +يؤتمن +يؤتمنَ +يؤتي +يؤتيه +يؤثر +يؤثران +يؤثرون +يؤثِّر +يؤجر +يؤجل +يؤخذ +يؤخر +يؤد +يؤدون +يؤدونها +يؤدى +يؤدي +يؤديان +يؤديه +يؤديها +يؤذن +يؤذونها +يؤذي +يؤرخ +يؤسس +يؤسسوا +يؤسف +يؤصل +يؤصّل +يؤكد +يؤكده +يؤكل +يؤلف +يؤلم +يؤلمك +يؤم +يؤمل +يؤمن +يؤمنان +يؤمنوا +يؤمنون +يؤمه +يؤمها +يؤمّن +يؤهب +يؤهل +يؤهلها +يؤهلون +يؤول +يؤيدني +يئس +يا +ياأبي +يائسا +يائسة +يابا +ياباني +يابانياً +يابانية +يابانيون +يابس +يابسة +يابسًا +يابن +يابني +يابوك +ياترى +ياته +ياجو +ياحون +ياروشاليمي +يارون +ياسر +ياسمين +ياسنت +ياسيدي +ياسين +يافا +يافعا +يافعاً +يافعة +يافعًا +يافوية +ياقة +ياقوت +ياكرام +يال +يالجين +يالطا +ياللأسف +يالله +ياله +ياما +يامن +يان +يانا +يانوس +ياه +ياوا +يباب +يبادر +يبادروا +يبادرون +يبادلني +يبارى +يباسهم +يباشروا +يباع +يباعد +يباعون +يبال +يبالي +يباهيني +يبة +يبتئس +يبتدئ +يبتدع +يبتدعه +يبتسم +يبتسمان +يبتعد +يبتعدوا +يبتكره +يبتلعني +يبتلعه +يبتلعها +يبتلعوني +يبتني +يبتهل +يبث +يبثها +يبحث +يبحثوا +يبحثون +يبحلق +يبخعها +يبد +يبدأ +يبدأوا +يبدأون +يبدؤون +يبدد +يبددون +يبدع +يبدل +يبدو +يبدوا +يبدوان +يبدوكما +يبدون +يبدى +يبدي +يبديه +يبذل +يبذله +يبذلها +يبذلون +يبر +يبرئ +يبرحه +يبرحها +يبرد +يبرر +يبرره +يبررها +يبرز +يبرزه +يبرق +يبرو +يبس +يبسط +يبشر +يبشران +يبشرون +يبصرني +يبصروا +يبصق +يبصقها +يبضن +يبطؤ +يبطل +يبطن +يبطنها +يبطّن +يبعث +يبعثها +يبعد +يبعدهما +يبعدون +يبق +يبقى +يبقي +يبقينا +يبقيه +يبقيهم +يبكون +يبكي +يبلل +يبللها +يبنوا +يبنون +يبنونها +يبنى +يبني +يبنيها +يبه +يبهت +يبهج +يبهرك +يبهرهم +يبوح +يبوس +يبيح +يبيع +يبيعني +يبيعه +يبيعون +يبين +ية +يتآخى +يتآلف +يتأبط +يتأبّطُ +يتأتى +يتأتي +يتأثر +يتأجل +يتأخر +يتأخرون +يتأرجح +يتأسس +يتأقلم +يتأكد +يتألف +يتألم +يتأمل +يتأمله +يتأملها +يتأملهم +يتأنى +يتأهب +يتئدْ +يتابع +يتابعني +يتابعها +يتابعون +يتاجر +يتاجرون +يتاح +يتامى +يتبادر +يتبادل +يتبادلان +يتبادلون +يتبارز +يتبارى +يتباهون +يتباهى +يتبحرون +يتبخر +يتبدل +يتبدى +يتبدّل +يتبع +يتبعان +يتبعنني +يتبعه +يتبعها +يتبعهم +يتبعوا +يتبعوك +يتبعونني +يتبعونها +يتبقى +يتبل +يتبلور +يتبناه +يتبناها +يتبنون +يتبنى +يتبني +يتبين +يتبينه +يتبيّن +يتتبع +يتتلمذون +يتثاءب +يتجادلون +يتجاهل +يتجاوب +يتجاور +يتجاوز +يتجاوزه +يتجاوزها +يتجاوزون +يتجدد +يتجذّر +يتجرأ +يتجرّد +يتجزأ +يتجسد +يتجشّموا +يتجعد +يتجلى +يتجلّى +يتجمد +يتجمع +يتجمل +يتجمّع +يتجنب +يتجنبن +يتجنّبوا +يتجه +يتجهون +يتجول +يتحادثان +يتحاشون +يتحاشى +يتحاور +يتحتّم +يتحدث +يتحدثان +يتحدثوا +يتحدثون +يتحدد +يتحدر +يتحدن +يتحدون +يتحدى +يتحدّثوا +يتحدّر +يتحرج +يتحرر +يتحرقون +يتحرك +يتحركان +يتحركن +يتحركون +يتحرى +يتحرّكان +يتحرّكون +يتحسر +يتحسس +يتحسسه +يتحسن +يتحصنان +يتحطم +يتحفظ +يتحقق +يتحكم +يتحلل +يتحلى +يتحمل +يتحمله +يتحملها +يتحملوا +يتحملونها +يتحمّس +يتحمَّل +يتحول +يتحولن +يتحولون +يتحوّل +يتحَدَّد +يتخاصم +يتخبطون +يتخذ +يتخذه +يتخذوا +يتخرج +يتخرجوا +يتخصص +يتخصصوا +يتخطون +يتخطى +يتخل +يتخلص +يتخلف +يتخلل +يتخللها +يتخللهما +يتخلى +يتخلّف +يتخلَّ +يتخلَّلها +يتخوفون +يتخوَّف +يتخير +يتخيل +يتداخل +يتدارك +يتداعى +يتدافعون +يتداوله +يتداولونها +يتدبر +يتدخل +يتدخلا +يتدرج +يتدفق +يتدفقون +يتدنى +يتذكر +يتذكره +يتذكرها +يتذكرهم +يتذمر +يترأس +يترأسه +يترأسها +يتراءى +يتراجع +يتراخى +يترافق +يترافقان +يتراقصون +يتراكم +يتراكمون +يتراوح +يتربص +يتربع +يتربّع +يترتب +يترجم +يترجمه +يترجمون +يتردد +يترددون +يترسب +يترفّعوا +يترك +يتركان +يتركز +يتركك +يتركني +يتركه +يتركها +يتركوا +يتركون +يتركونها +يتركوها +يترنح +يتزاحمون +يتزامن +يتزاوج +يتزايد +يتزايدون +يتزعزع +يتزعزعا +يتزعم +يتزعمها +يتزوج +يتزوجك +يتزوجها +يتزود +يتزودون +يتساءل +يتسارع +يتساقط +يتساقطون +يتساوى +يتسبب +يتسبّب +يتستر +يتسحاق +يتسرب +يتسربون +يتسرع +يتسرّب +يتسرَّب +يتسع +يتسعون +يتسقط +يتسكر +يتسكع +يتسلل +يتسلم +يتسم +يتسن +يتسنى +يتسنّى +يتشابه +يتشارك +يتشاور +يتشاوران +يتشبث +يتشبه +يتشخّص +يتشدد +يتشدقون +يتشرب +يتشرف +يتشكل +يتشكّل +يتشممن +يتصارع +يتصاعد +يتصبب +يتصدر +يتصدعا +يتصدى +يتصرف +يتصرفون +يتصرّفون +يتصف +يتصفح +يتصفون +يتصل +يتصلون +يتصنع +يتصور +يتصوره +يتصورون +يتضاءل +يتضاعف +يتضاعفت +يتضايقون +يتضجر +يتضح +يتضخم +يتضرع +يتضمن +يتضمنه +يتضمنها +يتضمّن +يتضمَّن +يتطابق +يتطابقان +يتطاير +يتطب +يتطرق +يتطلب +يتطلبه +يتطلع +يتطلعن +يتطلعون +يتطلّب +يتطلّعُ +يتطلَّع +يتطلَّعون +يتطور +يتطورضيق +يتطوروا +يتطورون +يتطوّع +يتظاهر +يتعارض +يتعارف +يتعاطاه +يتعاطفوا +يتعاطفون +يتعاطون +يتعاطى +يتعاطين +يتعاظم +يتعاقد +يتعامل +يتعاملون +يتعاون +يتعاونا +يتعاونوا +يتعايش +يتعب +يتعبون +يتعتعوا +يتعثر +يتعجب +يتعداه +يتعداها +يتعداهم +يتعدد +يتعدى +يتعدّى +يتعدَّى +يتعذب +يتعذر +يتعرض +يتعرضن +يتعرضوا +يتعرضون +يتعرف +يتعرفن +يتعرفوا +يتعرّضون +يتعرّفون +يتعرَّض +يتعفن +يتعلق +يتعلقون +يتعلم +يتعلمه +يتعلمها +يتعلموا +يتعلمون +يتعلمونه +يتعلّق +يتعلّم +يتعلّمها +يتعلَّمْنَ +يتعمدون +يتعمق +يتعمّد +يتعود +يتعوذ +يتعين +يتفاجأ +يتفادى +يتفاعل +يتفاعلا +يتفاعلوا +يتفاقم +يتفاوت +يتفتت +يتفتق +يتفجر +يتفحصها +يتفحم +يتفرع +يتفرقون +يتفرّع +يتفصد +يتفضل +يتفق +يتفقد +يتفقهن +يتفقون +يتفكرون +يتفكه +يتفنن +يتفهم +يتفهمها +يتفوقون +يتفوهُ +يتفيئون +يتقاتلون +يتقارب +يتقاسم +يتقاضاه +يتقاضون +يتقاضى +يتقاطع +يتقاعد +يتقبل +يتقبلها +يتقدم +يتقدمنا +يتقدمه +يتقدمها +يتقدمهم +يتقدمون +يتقدّم +يتقصون +يتقلب +يتقلص +يتقن +يتقنها +يتقنون +يتقوقع +يتقيأ +يتقيد +يتقين +يتكئ +يتكاتفن +يتكاثر +يتكتم +يتكدر +يتكدّسون +يتكرر +يتكسّر +يتكشف +يتكفن +يتكلم +يتكلمان +يتكلمها +يتكون +يتكونان +يتلألأ +يتلاءم +يتلاشى +يتلاعب +يتلبث +يتلخص +يتلذذ +يتلصصون +يتلفت +يتلقاها +يتلقون +يتلقى +يتلقيان +يتلمس +يتلمّسون +يتلو +يتلونون +يتلوه +يتلوّن +يتم +يتمادون +يتمادى +يتماشى +يتمالك +يتماوج +يتمتع +يتمتعن +يتمتعون +يتمتم +يتمثل +يتمثلها +يتمثلون +يتمحور +يتمخض +يتمدد +يتمرأى +يتمزق +يتمسك +يتمكن +يتمكنوا +يتمكنون +يتمكّن +يتملق +يتملكني +يتملّكه +يتملَّى +يتمم +يتمناه +يتمنون +يتمنى +يتمنّى +يتموج +يتميز +يتميزان +يتميزون +يتميّز +يتمّ +يتناثر +يتناجيان +يتنازعني +يتنازل +يتنازلون +يتناساها +يتناسب +يتنافس +يتنافسون +يتنافى +يتناقشون +يتناقض +يتناقل +يتناقله +يتناقلها +يتنامى +يتناهى +يتناوب +يتناول +يتناولن +يتناوله +يتناولها +يتناولهما +يتناولون +يتناولونه +يتنبه +يتنبهون +يتنبَّأ +يتنزل +يتنزه +يتنصل +يتنفذ +يتنفس +يتنفسه +يتنفسها +يتنفسون +يتنقل +يتنقلون +يتنكر +يتنهد +يتهادى +يتهامسون +يتهاوى +يتهدد +يتهددها +يتهددهم +يتهم +يتهمنا +يتهمهم +يتهيأ +يتواءم +يتوارثها +يتوارى +يتواصل +يتواطأ +يتوافد +يتوافدون +يتوافر +يتوافق +يتوالد +يتوالى +يتوانيا +يتوثب +يتوج +يتوجب +يتوجه +يتوجهوا +يتوجهون +يتوجّب +يتوجَّه +يتوحد +يتوخاها +يتوخون +يتوخى +يتوخي +يتوذم +يتورط +يتوزع +يتوسد +يتوسدن +يتوسط +يتوسع +يتوسل +يتوسلن +يتوسلني +يتوسلها +يتوسلون +يتوصل +يتوصلوا +يتوضأون +يتوضّع +يتوفر +يتوقع +يتوقعا +يتوقعها +يتوقعوا +يتوقعون +يتوقف +يتوقفن +يتوقفوا +يتوكأ +يتولاه +يتولد +يتولى +يتولي +يتوّهمون +يتيبس +يتيح +يتيحه +يتيحها +يتيسر +يتيقن +يتيم +يتيما +يتيمة +يتيمًا +يتّبعوا +يتَّهمه +يثار +يثبت +يثبته +يثبتها +يثبتوا +يثبّتون +يثبِّط +يثر +يثق +يثقف +يثقلها +يثلب +يثني +يثور +يثير +يثيرها +يثيرون +يثْنها +يجادل +يجارى +يجامل +يجانبها +يجاهد +يجاور +يجاورونها +يجاوز +يجب +يجبر +يجبرون +يجبها +يجبُ +يجبّ +يجتاح +يجتاحنا +يجتاحني +يجتاحه +يجتاحهم +يجتاحون +يجتاز +يجتث +يجتذب +يجتذبها +يجتمع +يجتمعان +يجتمعون +يجثو +يجد +يجدا +يجداه +يجدد +يجددان +يجدر +يجدلها +يجدني +يجده +يجدها +يجدهم +يجدوا +يجدون +يجدونه +يجدونها +يجدوها +يجدي +يجدّ +يجدُّ +يجذب +يجذبني +يجر +يجرؤ +يجرب +يجربوا +يجرع +يجرفه +يجرفها +يجرنا +يجرون +يجرونها +يجرى +يجري +يجريان +يجريها +يجرِ +يجرّ +يجرّه +يجزع +يجزم +يجزي +يجسد +يجسده +يجسّد +يجعل +يجعلك +يجعلنا +يجعلني +يجعله +يجعلها +يجعلهم +يجعلونها +يجعلُ +يجف +يجفل +يجلب +يجلبها +يجلبونها +يجلد +يجلس +يجلسون +يجمع +يجمعنا +يجمعه +يجمعها +يجمعهم +يجمعون +يجمّلها +يجن +يجنب +يجنح +يجنون +يجني +يجنّدونهم +يجهد +يجهش +يجهضه +يجهل +يجهلن +يجهله +يجهلون +يجوب +يجوبون +يجوز +يجول +يجيء +يجيئ +يجيئون +يجيئونه +يجيب +يجيبان +يجيبك +يجيد +يجيدها +يجيدوا +يجيدون +يجيدُ +يجيش +يجيى +يجِيْبَنّه +يحابي +يحاذي +يحارب +يحاسبه +يحاسبها +يحاصرها +يحاصرونه +يحاضر +يحاط +يحافظ +يحافظوا +يحافظون +يحاكي +يحال +يحالفهم +يحاور +يحاوره +يحاورها +يحاول +يحاولان +يحاولوا +يحاولون +يحب +يحبحب +يحبذ +يحبذها +يحبس +يحبسوا +يحبط +يحبل +يحبني +يحبه +يحبها +يحبو +يحبون +يحبونه +يحبّها +يحتا +يحتاج +يحتاجانه +يحتاجها +يحتاجون +يحتاجونه +يحتار +يحتاروا +يحتارون +يحتاطوا +يحتدم +يحتذى +يحتذي +يحترف +يحترق +يحترقون +يحترم +يحترمون +يحتسون +يحتشد +يحتضن +يحتضنه +يحتضنها +يحتفظ +يحتفظوا +يحتفظون +يحتفل +يحتفلون +يحتقرهم +يحتكر +يحتكرون +يحتل +يحتلان +يحتلها +يحتم +يحتمل +يحتمي +يحتميان +يحتوى +يحتوي +يحتويان +يحتويه +يحتويها +يحتِّم +يحث +يحثه +يحثها +يحثون +يحثّ +يحج +يحجب +يحجز +يحجزون +يحجل +يحجم +يحجمون +يحجوا +يحجون +يحد +يحدث +يحدثك +يحدثنا +يحدثني +يحدثه +يحدثها +يحدثوا +يحدثون +يحدثونك +يحدد +يحددك +يحدده +يحددها +يحددون +يحدق +يحدها +يحدُث +يحدّ +يحدّث +يحدّثني +يحدّد +يحدّق +يحذر +يحذرني +يحذرونني +يحذف +يحذوا +يحذّر +يحرث +يحرثه +يحرز +يحرزه +يحرزون +يحرسون +يحرص +يحرصان +يحرصن +يحرصون +يحرض +يحرضها +يحرق +يحرك +يحركا +يحركه +يحركها +يحركُ +يحرم +يحرمهم +يحرّض +يحرّك +يحرّكه +يحزن +يحزنني +يحزّ +يحس +يحسبوا +يحسبون +يحسد +يحسدنا +يحسده +يحسدهم +يحسدون +يحسكم +يحسم +يحسن +يحسنون +يحسوا +يحسّنه +يحسّها +يحشد +يحصد +يحصدها +يحصرون +يحصل +يحصلوا +يحصلون +يحصى +يحضر +يحضرن +يحضرني +يحضره +يحضرها +يحضروا +يحضرون +يحضن +يحضّرون +يحط +يحطم +يحظ +يحظر +يحظون +يحظى +يحظيان +يحـتوى +يحـــددهما +يحـقق +يحفر +يحفرون +يحفز +يحفظ +يحفظك +يحفظن +يحفظها +يحفظون +يحفل +يحفِّز +يحق +يحقق +يحققا +يحققه +يحققها +يحققوا +يحققون +يحكم +يحكمه +يحكمها +يحكمهم +يحكمون +يحكه +يحكى +يحكي +يحكُّ +يحل +يحلق +يحلقان +يحلقَ +يحلل +يحلم +يحلمُ +يحلو +يحلُم +يحلّ +يحلّق +يحم +يحمر +يحمل +يحملان +يحملق +يحملن +يحملني +يحمله +يحملها +يحملهم +يحملهما +يحملون +يحملونه +يحملونها +يحملوني +يحمها +يحمي +يحمينا +يحميه +يحميها +يحمّل +يحن +يحني +يحورها +يحوزها +يحوطه +يحول +يحولك +يحولنا +يحولها +يحولوا +يحومان +يحوى +يحوي +يحويه +يحوّل +يحوّلها +يحيا +يحياه +يحيد +يحير +يحيرك +يحيرني +يحيط +يحيطنا +يحيطني +يحيطها +يحيطون +يحيق +يحيل +يحين +يحيه +يحيون +يحيونها +يحيى +يحيي +يحييها +يخاتل +يخاطب +يخاطبني +يخاطبه +يخاطبهم +يخاطبون +يخاطر +يخاف +يخافون +يخال +يخالط +يخالف +يخالفها +يخامرني +يخب +يخبئ +يخبر +يخبرنا +يخبره +يخبرها +يخبرونه +يخبو +يخت +يختار +يختارك +يختارها +يختاروا +يختارون +يختارونه +يختارونها +يختال +يختبئ +يختبر +يختتم +يخترع +يخترق +يخترقه +يخترقون +يختزل +يختزله +يختص +يختصر +يختطف +يختف +يختفي +يختل +يختلج +يختلس +يختلسون +يختلط +يختلف +يختلفان +يختلفون +يختلق +يختلي +يختليان +يختم +يختنق +يخته +يخجل +يخجلني +يخدرهم +يخدع +يخدم +يخذل +يخر +يخرب +يخرج +يخرجه +يخرجوا +يخرجون +يخرس +يخرف +يخرقه +يخرَّ +يخزن +يخزنان +يخسر +يخسره +يخسرونها +يخشاه +يخشاها +يخشاهم +يخشـى +يخشون +يخشى +يخص +يخصص +يخصني +يخصّ +يخصُّ +يخضع +يخضعا +يخضعون +يخط +يخطئ +يخطئون +يخطب +يخطبون +يخطر +يخطط +يخططون +يخطف +يخطه +يخطو +يخـلو +يخف +يخفت +يخفض +يخفضا +يخفضان +يخفف +يخففون +يخفق +يخفوا +يخفى +يخفي +يخفيه +يخفيها +يخل +يخلب +يخلد +يخلدون +يخلص +يخلصنا +يخلصها +يخلط +يخلطون +يخلع +يخلعني +يخلف +يخلفه +يخلق +يخلو +يخلوا +يخلّص +يخنق +يخنقني +يخوص +يخوض +يخوضه +يخوضها +يخيب +يخيفني +يخيفها +يخيل +يخيم +يخيّروه +يخيّل +يد +يدأب +يدا +يداخلها +يدار +يداعب +يداعبها +يدافع +يدافعوا +يدافعون +يدانيه +يداه +يداها +يداهمهم +يداوي +يداي +يداً +يدب +يدة +يدحض +يدخل +يدخله +يدخلها +يدخلوا +يدخلون +يدخن +يدخنون +يدر +يدرأ +يدرب +يدربن +يدربني +يدرج +يدرس +يدرسن +يدرسني +يدرسها +يدرسوا +يدرسون +يدرسوه +يدرك +يدركوا +يدركون +يدرون +يدري +يدرّس +يدرِّس +يدس +يدسون +يدسونه +يدش +يدشنها +يدع +يدعم +يدعمه +يدعني +يدعو +يدعوك +يدعون +يدعونا +يدعوني +يدعوه +يدعوهم +يدعى +يدعي +يدعيها +يدفع +يدفعا +يدفعكِ +يدفعنا +يدفعني +يدفعه +يدفعها +يدفعهم +يدفعون +يدفعوننا +يدفن +يدفنون +يدق +يدقق +يدك +يدل +يدلف +يدلك +يدلل +يدلها +يدلي +يدلّ +يدمر +يدمرونها +يدمي +يده +يدها +يدهشك +يدهشنا +يدهشني +يدهشه +يدهم +يدور +يدورون +يدوس +يدوسها +يدوم +يدوي +يدويا +يدوياً +يدوية +يدى +يدي +يدير +يديره +يديرها +يديرون +يديعوت +يديك +يدين +يدينون +يديه +يديها +يديّ +يدٌ +يدّعون +يدّعي +يدَّخره +يدَّخرون +يذاع +يذاكر +يذبح +يذبل +يذرع +يذرعه +يذق +يذكر +يذكرك +يذكرنا +يذكرني +يذكره +يذكرها +يذكرهم +يذكرون +يذكّرها +يذنبون +يذهب +يذهبوا +يذهبون +يذوب +يذودون +يذوق +يذيبون +ير +يرأس +يرأسني +يرأسها +يراجع +يراجعون +يراد +يراسل +يراسلها +يراعي +يرافق +يرافقنا +يرافقني +يرافقه +يرافقها +يراقب +يراقبان +يراقبهم +يراقبهما +يراك +يرام +يرانا +يراني +يراه +يراها +يراهم +يراهما +يراهن +يراود +يراودَ +يربض +يربط +يربطانهما +يربطني +يربطه +يربطها +يربطهم +يربطون +يربك +يربو +يربي +يرتاح +يرتاد +يرتاده +يرتادها +يرتادون +يرتب +يرتبط +يرتبون +يرتج +يرتجف +يرتجفان +يرتحل +يرتد +يرتدع +يرتدون +يرتدونه +يرتدى +يرتدي +يرتدين +يرتديه +يرتديها +يرتسم +يرتشف +يرتشفون +يرتضي +يرتضيه +يرتع +يرتعد +يرتعدْ +يرتعش +يرتفع +يرتق +يرتكبها +يرتكبون +يرتكز +يرتل +يرتلان +يرتوي +يرث +يرثى +يرج +يرجح +يرجع +يرجف +يرجمهم +يرجو +يرجونه +يرجوه +يرحب +يرحل +يرحلون +يرحم +يرحمنا +يرحمه +يرد +يردد +يرددها +يرددون +يردعها +يردعهم +يردن +يردها +يردوا +يردون +يردّدها +يردّني +يرزحون +يرزق +يرسخ +يرسل +يرسلاني +يرسلك +يرسله +يرسلها +يرسلوا +يرسلون +يرسلونه +يرسم +يرسمها +يرسو +يرش +يرشح +يرشحها +يرشحوني +يرشدني +يرشده +يرشدهم +يرشدون +يرصد +يرصدها +يرصع +يرض +يرضعن +يرضون +يرضى +يرضي +يرضيني +يرضيه +يرع +يرعاني +يرعى +يرفده +يرفرف +يرفض +يرفضن +يرفضه +يرفضها +يرفضون +يرفع +يرفعه +يرفعها +يرفعهم +يرفعوا +يرفعون +يرفعوهم +يرفل +يرفلن +يرق +يرقات +يرقبك +يرقبونه +يرقد +يرقص +يرقى +يركب +يركبني +يركبها +يركبون +يركبونه +يركز +يركزون +يركض +يركّز +يرم +يرمز +يرمزان +يرمي +يرميه +يرميها +يرنّ +يره +يرها +يرهب +يرهقني +يرو +يروج +يروحون +يروضني +يروضه +يروعني +يروق +يروقها +يرون +يرونني +يرونه +يرونها +يروه +يروها +يروونها +يروي +يرويني +يرويه +يرويها +يروّج +يروِّضونه +يرى +يري +يريد +يريدك +يريدني +يريده +يريدها +يريدون +يريدونه +يزاد +يزال +يزالون +يزبد +يزبك +يزجرها +يزحف +يزحفان +يزحمهم +يزخر +يزد +يزداد +يزدادون +يزدحم +يزده +يزدها +يزدهر +يزرع +يزرعه +يزرعون +يزرعونها +يزرها +يزعج +يزعجني +يزعجها +يزعق +يزعل +يزعم +يزعمه +يزعمون +يزقزق +يزقن +يزل +يزلزل +يزمجر +يزن +يزنر +يزها +يزوجها +يزود +يزور +يزورنا +يزورني +يزوره +يزورهما +يزورون +يزول +يزوّد +يزيح +يزيحه +يزيد +يزيدني +يزيدها +يزيدون +يزيل +يزين +يزينه +يزينوا +يزيّن +يس +يسأل +يسألنا +يسأله +يسألها +يسألهما +يسألون +يسألونني +يسألونها +يساء +يسائل +يسار +يسارا +يساراً +يسارع +يساره +يساري +يساريا +يسارياً +يساريًا +يساعد +يساعدك +يساعدني +يساعده +يساعدها +يساعدهم +يساعدون +يسافر +يسافرون +يساق +يسامر +يساندها +يساهم +يساوى +يساوي +يساير +يسبب +يسببه +يسببها +يسببوا +يسبح +يسبحون +يسبق +يسبقني +يسبقها +يسبقهما +يسبّ +يستأثر +يستأجر +يستأجرن +يستأسرون +يستأصلون +يستأنس +يستأهل +يستبدل +يستبشر +يستبطن +يستبعد +يستبعدوا +يستتب +يستتبع +يستثمر +يستثن +يستثني +يستجب +يستجد +يستجمع +يستجوبه +يستجيب +يستحب +يستحبه +يستحث +يستحدث +يستحضر +يستحق +يستحقه +يستحقها +يستحم +يستحوذ +يستحيل +يستخد +يستخدم +يستخدمان +يستخدمن +يستخدمنها +يستخدمه +يستخدمها +يستخدموا +يستخدمون +يستخدمونه +يستخدمونها +يستخرج +يستخلص +يستدرجها +يستدرك +يستدعي +يستدل +يستدير +يستذكر +يستذكرون +يستر +يسترجع +يسترد +يستردفها +يستردّ +يستردُّ +يسترسل +يسترضون +يسترضي +يسترها +يستريثوك +يستريح +يستريحوا +يستريحون +يستزلم +يستزيدونني +يستسلم +يستسلمون +يستسهل +يستشعر +يستشعرون +يستشفها +يستشهد +يستشير +يستشيروا +يستصرخ +يستصرخكم +يستطرد +يستطع +يستطعن +يستطلع +يستطيع +يستطيعه +يستطيعوا +يستطيعون +يستطيعُ +يستظل +يستعجل +يستعد +يستعدون +يستعرض +يستعرضها +يستعطف +يستعطون +يستعمل +يستعملها +يستعملون +يستعملونه +يستعيد +يستعير +يستعيرون +يستعين +يستفاد +يستفد +يستفز +يستفزني +يستفزها +يستفسر +يستفيد +يستفيدون +يستقبل +يستقبلنا +يستقبلني +يستقبله +يستقبلها +يستقبلهم +يستقبلون +يستقر +يستقصي +يستقطب +يستقطع +يستقل +يستقلّ +يستكتبه +يستكثر +يستكره +يستكمل +يستكملها +يستكملون +يستلب +يستلزم +يستلقي +يستمتع +يستمتعان +يستمتعون +يستمد +يستمدّ +يستمر +يستمطرها +يستمع +يستمهلني +يستنبط +يستنتج +يستنجد +يستنجدني +يستند +يستنسخ +يستنشق +يستنشقهم +يستنصرهم +يستنطق +يستنفر +يستنيرون +يستهان +يستهدف +يستهل +يستهلك +يستهلكه +يستهلكون +يستهله +يستهوي +يستهويكم +يستهويني +يستوجب +يستورده +يستوطن +يستوطنه +يستوطنوا +يستوعب +يستوعبوا +يستوقف +يستوقفك +يستوقفه +يستولون +يستولي +يستيقظ +يستيقظا +يستيقظوا +يستيقظون +يسجل +يسجلا +يسجن +يسحب +يسخر +يسخرون +يسخن +يسخنون +يسدد +يسدل +يسدى +يسدّ +يسر +يسرا +يسرد +يسرع +يسرق +يسرقنا +يسرقها +يسرقون +يسرنى +يسروا +يسري +يسرُّ +يسطر +يسع +يسعد +يسعدني +يسعف +يسعفه +يسعك +يسعنا +يسعني +يسعها +يسعون +يسعى +يسفر +يسقط +يسقطون +يسقي +يسقيها +يسكب +يسكت +يسكر +يسكن +يسكنني +يسكنه +يسكنها +يسكنوا +يسكنون +يسكنونه +يسلبها +يسلقني +يسلكون +يسلم +يسلمك +يسلمني +يسلمه +يسلمها +يسمح +يسمحوا +يسمحون +يسمع +يسمعان +يسمعك +يسمعني +يسمعه +يسمعون +يسمعونك +يسمعونها +يسمو +يسمون +يسمونه +يسمونها +يسمى +يسمي +يسميه +يسميها +يسمّون +يسمّونني +يسمّى +يسمّيه +يسمَّى +يسند +يسهب +يسهر +يسهرون +يسهل +يسهم +يسهمون +يسهّل +يسوء +يسود +يسودها +يسوع +يسوق +يسوقون +يسومني +يسيء +يسيئون +يسيج +يسير +يسيراً +يسيرة +يسيرون +يسيطر +يسيل +يسيىء +يسيّر +يسّر +يشأ +يشاء +يشاؤها +يشابه +يشار +يشارك +يشاركان +يشاركن +يشاركنا +يشاركني +يشاركه +يشاركها +يشاركهم +يشاركهما +يشاركون +يشاركونهم +يشاركوني +يشاع +يشاهد +يشاهدن +يشاهده +يشاهدها +يشاهدون +يشاهدوه +يشب +يشبع +يشبه +يشبهان +يشبهني +يشبهه +يشتبك +يشتد +يشترط +يشترك +يشتركا +يشتركان +يشتركون +يشترون +يشتري +يشترين +يشتريها +يشتعل +يشتكي +يشتكين +يشتم +يشتمل +يشتملان +يشتهر +يشتهي +يشجع +يشجعه +يشجعوا +يشجعوه +يشحذ +يشخب +يشخر +يشخص +يشخّصوا +يشد +يشدد +يشدني +يشدونْ +يشدّك +يشدّني +يشر +يشرب +يشربها +يشربون +يشرح +يشرحه +يشرخ +يشرد +يشرع +يشرف +يشرفون +يشرق +يشرك +يشع +يشعر +يشعرا +يشعرك +يشعرنا +يشعرها +يشعروا +يشعرون +يشعلها +يشفه +يشفى +يشفي +يشفيه +يشق +يشك +يشكره +يشكل +يشكلان +يشكلها +يشكلون +يشكو +يشكون +يشكّل +يشكّلون +يشكَّل +يشكِّل +يشم +يشمر +يشمل +يشمله +يشملها +يشمها +يشنها +يشنّون +يشه +يشهد +يشهدان +يشهده +يشهدها +يشوبه +يشوبها +يشوفه +يشوه +يشوهها +يشوهون +يشي +يشيد +يشيدون +يشير +يشيران +يشيروا +يشيش +يشيع +يشيعون +يشينه +يشيّء +يصاب +يصابوا +يصابون +يصاحب +يصاحبني +يصاحبه +يصادر +يصادف +يصادفها +يصار +يصارع +يصارعان +يصافحه +يصب +يصبح +يصبحوا +يصبحون +يصبر +يصبرون +يصبّ +يصح +يصحبنا +يصحبننا +يصحبه +يصحو +يصدأ +يصدح +يصدر +يصدرها +يصدق +يصدقها +يصدقون +يصدم +يصده +يصدّق +يصدّقها +يصر +يصرحون +يصرخ +يصرخن +يصرخون +يصررن +يصرف +يصرفنا +يصرفه +يصرّ +يصرّفه +يصرّون +يصطاد +يصطادني +يصطادها +يصطحب +يصطحبنا +يصطحبون +يصطدم +يصطف +يصطفون +يصعب +يصعد +يصعدها +يصعدون +يصعق +يصعّد +يصف +يصفر +يصفعني +يصفق +يصفقون +يصفه +يصفها +يصفهن +يصفون +يصفونه +يصك +يصل +يصلا +يصلح +يصلنا +يصله +يصلها +يصلوا +يصلون +يصلي +يصمت +يصمد +يصمم +يصنع +يصنعها +يصنعون +يصنف +يصنفها +يصور +يصورك +يصوره +يصورها +يصوّره +يصيب +يصيبه +يصيبها +يصيبهم +يصيبوها +يصيح +يصيحون +يصيخ +يصير +يصيروا +يضاء +يضاد +يضارعها +يضاف +يضاهى +يضاهي +يضاهيها +يضايق +يضايقك +يضايقني +يضايقهم +يضبط +يضبطها +يضجر +يضح +يضحك +يضحكوا +يضحكون +يضحى +يضحي +يضر +يضرب +يضربني +يضربه +يضربها +يضربوا +يضربون +يضره +يضروك +يضرّ +يضطر +يضطرب +يضطلع +يضع +يضعف +يضعن +يضعه +يضعها +يضعهما +يضعون +يضفي +يضلل +يضللنّ +يضم +يضمان +يضمر +يضمن +يضمنها +يضمها +يضمهم +يضن +يضنّ +يضيء +يضيئون +يضيرنا +يضيع +يضيعه +يضيعوا +يضيف +يضيفه +يضيفون +يضيق +يضيقون +يطابق +يطارد +يطارده +يطاردها +يطاردون +يطاردونه +يطاردونها +يطاق +يطال +يطالب +يطالبني +يطالبه +يطالبها +يطالبهم +يطالبهما +يطالبون +يطالبونني +يطالع +يطالعون +يطاوعه +يطاوله +يطبخون +يطبع +يطبعها +يطبعون +يطبق +يطبّقه +يطرأ +يطرب +يطربنا +يطرح +يطرحا +يطرحه +يطرحون +يطرز +يطرق +يطرّد +يطعم +يطعمهم +يطفأ +يطفئها +يطفح +يطفو +يطفيها +يطل +يطلان +يطلب +يطلبه +يطلبها +يطلبوا +يطلبون +يطلبونها +يطلع +يطلعنا +يطلعني +يطلعونه +يطلق +يطلقن +يطلقه +يطلقها +يطلقون +يطلون +يطمئن +يطمح +يطمحون +يطمس +يطمع +يطهره +يطهم +يطوح +يطور +يطوروا +يطوعن +يطوف +يطوفوا +يطوق +يطول +يطوّر +يطوّرون +يطير +يطيق +يظـهر +يظفر +يظل +يظلم +يظلوا +يظلون +يظلّ +يظن +يظنه +يظنهم +يظنون +يظنّن +يظهر +يظهران +يظهرن +يظهرها +يظهروا +يظهرون +يظهرَ +يعاجله +يعاجلها +يعاد +يعادل +يعادله +يعادلها +يعارض +يعارضونه +يعاشر +يعاقب +يعاقبهم +يعالج +يعالجه +يعالجها +يعامل +يعامله +يعاملهم +يعاملوننا +يعاملونه +يعامَل +يعانون +يعانونه +يعانى +يعاني +يعانيه +يعانيها +يعاود +يعاونها +يعبأ +يعبئهم +يعبث +يعبدها +يعبر +يعبق +يعبّر +يعبّرون +يعتاد +يعتادوا +يعتبر +يعتبران +يعتبره +يعتبرها +يعتبرهم +يعتبرون +يعتد +يعتدل +يعتدي +يعتذر +يعترض +يعترضه +يعترضهم +يعترف +يعترفون +يعتريها +يعتز +يعتزلها +يعتزم +يعتزمه +يعتزون +يعتقد +يعتقدون +يعتقل +يعتكف +يعتلي +يعتليه +يعتم +يعتمد +يعتمدان +يعتمدن +يعتمدون +يعتمرون +يعتنون +يعتني +يعتنين +يعتورها +يعثر +يعثروا +يعج +يعجب +يعجبك +يعجبني +يعجبه +يعجبون +يعجز +يعجزون +يعجل +يعجن +يعجّ +يعد +يعدان +يعدد +يعدل +يعدلها +يعدم +يعدنا +يعدها +يعدو +يعدون +يعدونهم +يعدّ +يعدَّ +يعدُّ +يعدُّون +يعذب +يعر +يعرب +يعرج +يعرض +يعرضان +يعرضه +يعرضها +يعرضهم +يعرضهما +يعرضون +يعرف +يعرفكم +يعرفنا +يعرفنها +يعرفني +يعرفه +يعرفها +يعرفهم +يعرفوا +يعرفون +يعرفونني +يعرفونه +يعرفونها +يعرقل +يعرّض +يعرّف +يعزز +يعزف +يعزفه +يعزفها +يعزفون +يعزل +يعزّز +يعزّزون +يعزّيني +يعش +يعشق +يعشقها +يعشقون +يعشن +يعشى +يعصف +يعصمهم +يعض +يعضد +يعط +يعطل +يعطه +يعطهم +يعطون +يعطونه +يعطوه +يعطى +يعطي +يعطيك +يعطين +يعطينا +يعطيني +يعطيه +يعطيها +يعطّلني +يعفو +يعفى +يعفي +يعفيهم +يعقب +يعقبه +يعقد +يعقل +يعقوب +يعكر +يعكس +يعكسه +يعكف +يعكفان +يعكفون +يعلق +يعلم +يعلمان +يعلمن +يعلمني +يعلمه +يعلمها +يعلمهم +يعلمون +يعلن +يعلنها +يعلو +يعلوه +يعلوها +يعلي +يعلّق +يعم +يعمد +يعمق +يعمل +يعملا +يعملان +يعملوا +يعملون +يعمون +يعمي +يعن +يعند +يعنون +يعنى +يعني +يعنيان +يعنيك +يعنيكم +يعنينا +يعنيني +يعنيه +يعنيهم +يعهد +يعوا +يعود +يعودا +يعودوا +يعودون +يعوزها +يعوض +يعوق +يعول +يعولهم +يعوم +يعوّل +يعوِّض +يعوِّل +يعي +يعيبها +يعيث +يعيثون +يعيد +يعيدنا +يعيدني +يعيدها +يعيدوا +يعيدون +يعيدوها +يعيرها +يعيش +يعيشان +يعيشه +يعيشها +يعيشوا +يعيشون +يعيـــش +يعيق +يعيقه +يعين +يعينه +يعينها +يعينهم +يعينهما +يعّرف +يعْتَقَد +يـحقّق +يــعرف +يـــكون +يــكاد +يفاجأ +يفاجئ +يفاجئنا +يفاجئه +يفاخر +يفارقنا +يفارقني +يفارقه +يفاعتي +يفتؤ +يفتتح +يفتح +يفتحه +يفتحون +يفتحونها +يفتخر +يفترس +يفترض +يفترقان +يفتش +يفتشوا +يفتقد +يفتقدون +يفتقدونه +يفتقر +يفتقرون +يفتك +يفجر +يفحص +يفحصها +يفخر +يفد +يفدون +يفر +يفرج +يفرح +يفرحه +يفرد +يفرز +يفرزه +يفرض +يفرضه +يفرضون +يفرط +يفرق +يفرقها +يفرّج +يفرّط +يفرّق +يفز +يفسح +يفسد +يفسدان +يفسدون +يفسدونه +يفسر +يفسره +يفسّر +يفشل +يفشيها +يفصح +يفصل +يفصلنا +يفصلهما +يفصلوا +يفصلون +يفضح +يفضل +يفضلها +يفضلون +يفضي +يفضّلون +يفضِّل +يفطر +يفعل +يفعلان +يفعلن +يفعله +يفعلها +يفعلوا +يفعلون +يفقد +يفقدك +يفقدنا +يفقدني +يفقده +يفقدها +يفقدوا +يفقدون +يفقدُ +يفقس +يفقهوا +يفك +يفكر +يفكروا +يفكرون +يفلت +يفلح +يفلحوا +يفلحون +يفنى +يفنّد +يفهم +يفهمنا +يفهمني +يفهمه +يفهمها +يفهموا +يفهموننا +يفهمونها +يفوت +يفوتك +يفوتنا +يفوته +يفوز +يفوق +يفوقها +يفون +يفي +يفيد +يفيدها +يفيدوا +يفيض +يفيها +يق +يقأقئ +يقابل +يقابلني +يقابله +يقابلها +يقابلهم +يقاتل +يقارب +يقاربونه +يقارن +يقاس +يقاسمه +يقاسين +يقال +يقام +يقاوم +يقاومه +يقبض +يقبع +يقبل +يقبلان +يقبلها +يقبلوا +يقبلون +يقتبس +يقتحم +يقتدي +يقترب +يقتربان +يقتربون +يقترح +يقترحها +يقترحون +يقترن +يقتسم +يقتسموا +يقتسمون +يقتصر +يقتضي +يقتطع +يقتطعون +يقتفي +يقتل +يقتلع +يقتلعهم +يقتلك +يقتلني +يقتلها +يقتلهم +يقتلوا +يقتلون +يقتلونني +يقتنصون +يقتنع +يقتنعوا +يقدح +يقدر +يقدره +يقدرها +يقدروا +يقدرونها +يقدس +يقدم +يقدمن +يقدمه +يقدمها +يقدموا +يقدمون +يقدّر +يقدّم +يقدّمها +يقذف +يقر +يقرءون +يقرأ +يقرأه +يقرأها +يقرأوا +يقرأون +يقرؤه +يقرؤها +يقرئك +يقرب +يقرر +يقرع +يقرعه +يقرعون +يقرقر +يقره +يقرَّ +يقسم +يقسو +يقص +يقصد +يقصده +يقصدها +يقصدون +يقصدونه +يقصدونها +يقصر +يقصره +يقصها +يقض +يقضمها +يقضون +يقضونها +يقضى +يقضي +يقضيانها +يقضيه +يقضيها +يقضيهما +يقضٌون +يقضِ +يقطع +يقطعه +يقطعها +يقطعون +يقطف +يقطن +يقطنه +يقطنها +يقطنونه +يقطينات +يقطينة +يقظ +يقظا +يقظة +يقظته +يقظتها +يقع +يقعان +يقعده +يقعدها +يقعوا +يقعي +يقف +يقفز +يقفزن +يقفلها +يقفوا +يقفون +يقفَ +يققاً +يقل +يقلب +يقلبها +يقلد +يقلدهما +يقلدونها +يقلع +يقلعوا +يقلق +يقلقني +يقلقه +يقلل +يقله +يقلّل +يقلُّ +يقم +يقمن +يقنع +يقنعون +يقنّن +يقهر +يقهرن +يقهقه +يقود +يقودنا +يقوده +يقودها +يقودوا +يقودون +يقول +يقوله +يقولوا +يقولون +يقولونه +يقولي +يقوم +يقوما +يقوموا +يقومون +يقوى +يقوي +يقوّ +يقي +يقيس +يقيسها +يقيسون +يقيم +يقيمها +يقيموا +يقيمون +يقين +يقينا +يقيناً +يقيني +يقينًا +يقيهم +يقيّض +يقيّمون +يكابد +يكابده +يكابدون +يكاد +يكادون +يكافأ +يكافح +يكافحون +يكافيء +يكبت +يكبدها +يكبر +يكبران +يكبرن +يكبره +يكبرهم +يكبرون +يكبرونني +يكبّل +يكتئب +يكتب +يكتبا +يكتبه +يكتبها +يكتبوا +يكتبون +يكتبونها +يكترث +يكترثن +يكتسب +يكتسبها +يكتسبوا +يكتسبون +يكتشف +يكتشفها +يكتشفوا +يكتشفُ +يكتظ +يكتف +يكتفوا +يكتفون +يكتفي +يكتفِ +يكتم +يكتمل +يكتنفه +يكثر +يكثرن +يكثرون +يكثفون +يكد +يكدح +يكذب +يكذبون +يكرر +يكرسون +يكرم +يكره +يكرهني +يكرهه +يكرّر +يكرّس +يكس +يكسب +يكسبنا +يكسبه +يكسح +يكسر +يكسرها +يكسرون +يكسو +يكسوه +يكشف +يكشفن +يكف +يكفل +يكفه +يكفون +يكفي +يكفيك +يكفينا +يكفيه +يكفيها +يكفيهم +يكفيهن +يكفّ +يكلف +يكلفه +يكلفهم +يكلم +يكلمنا +يكلمني +يكلّف +يكمل +يكملها +يكمن +يكن +يكنز +يكنها +يكون +يكونا +يكونان +يكونها +يكونوا +يكونون +يكوّر +يكوّن +يكوّنها +يكوِّن +يكيد +يكيف +يكُف +يلائم +يلائمك +يلائمه +يلاحظ +يلاحظه +يلاحظها +يلاحظون +يلاحق +يلاحقني +يلاحقه +يلاحقها +يلازم +يلاطفونه +يلاعب +يلاقي +يلاقيه +يلامس +يلبث +يلبثان +يلبثوا +يلبس +يلبسن +يلبسها +يلبسوا +يلبسون +يلبي +يلبيه +يلبّوها +يلبِّ +يلتحق +يلتحقوا +يلتحقون +يلتزم +يلتزموا +يلتصق +يلتفت +يلتقط +يلتقون +يلتقي +يلتقيا +يلتقيان +يلتقيه +يلتمس +يلتهب +يلتهم +يلتهمون +يلتهون +يلجأ +يلجأون +يلجؤون +يلجئه +يلح +يلحظ +يلحظن +يلحظه +يلحظها +يلحظوا +يلحق +يلحقه +يلحقها +يلحون +يلخص +يلخصها +يلد +يلذع +يلزم +يلزمك +يلزمني +يلزمه +يلزمها +يلزمهم +يلسع +يلسعَكَ +يلصق +يلصقُ +يلطخ +يلطم +يلعب +يلعبان +يلعبه +يلعبون +يلعنونك +يلف +يلفت +يلفتني +يلفتوا +يلفظها +يلفك +يلفه +يلفها +يلفهم +يلفون +يلق +يلقاه +يلقاها +يلقب +يلقبون +يلقمه +يلقنها +يلقنهم +يلقوا +يلقون +يلقونه +يلقى +يلقي +يلقيها +يلماز +يلمح +يلمحه +يلمس +يلمسوها +يلمع +يلمعوا +يلملم +يلهب +يلهث +يلهثون +يلهج +يلهم +يلهون +يلهُو +يلوث +يلوثوا +يلوح +يلوذون +يلومه +يلومونني +يلونها +يلوي +يلوّنونها +يلى +يلي +يليق +يلين +يليه +يليها +يم +يما +يماثل +يماثلها +يمارس +يمارسا +يمارسان +يمارسه +يمارسها +يمارسوا +يمارسون +يمارَس +يمارَسان +يمازحني +يمام +يمامات +يمامة +يمانع +يماني +يمانية +يمايز +يمة +يمت +يمتاز +يمتحن +يمتد +يمتدح +يمتدحها +يمتدّ +يمتزج +يمتص +يمتلئ +يمتلك +يمتلكه +يمتلكها +يمتلكهما +يمتلكوا +يمتلكون +يمتلكونه +يمتلكونها +يمتن +يمتنعون +يمتّ +يمثل +يمثلان +يمثله +يمثلون +يمثّل +يمثّله +يمثِّل +يمخر +يمخروا +يمد +يمدح +يمدون +يمدّ +يمر +يمرر +يمرض +يمرضون +يمرنَّ +يمرون +يمرّ +يمزج +يمزق +يمس +يمسح +يمسرح +يمسسها +يمسك +يمسكن +يمسكوا +يمسكون +يمسه +يمسهم +يمسهما +يمسّ +يمسّها +يمش +يمشي +يمشيش +يمشين +يمض +يمضي +يمضيان +يمضين +يمعن +يمك +يمكث +يمكثون +يمكن +يمكنك +يمكننا +يمكنني +يمكنه +يمكنها +يمكنهم +يمكنّا +يمكِّن +يمل +يملأ +يملأون +يملؤها +يملؤوا +يملك +يملكه +يملكها +يملكوا +يملكون +يملكونها +يملي +يمليه +يملُّ +يمن +يمنة +يمنح +يمنحان +يمنحك +يمنحنا +يمنحني +يمنحه +يمنحها +يمنحونه +يمنع +يمنعنا +يمنعني +يمنعه +يمنعها +يمنعهم +يمنون +يمني +يمه +يمهله +يموت +يموتون +يموج +يمولون +يميت +يميز +يميزه +يميزها +يميزوا +يميزون +يميل +يميلون +يمين +يمينا +يميناً +يمينه +يميني +يمينية +يميّز +يميّزهم +يمُتّ +يمّمنا +يمَّمْتَ +ين +ينابيع +ينابيعها +يناجي +ينادونني +ينادونه +ينادي +يناديه +يناديها +يناسب +يناسبني +يناسبه +يناسبهم +يناشد +يناصر +يناضل +يناطح +يناظر +يناظرها +ينافس +ينافسه +ينافسها +ينافسون +يناقش +يناقشه +يناقشها +يناقشونهم +يناقض +ينال +يناله +ينالها +ينالهم +ينالوا +ينام +ينامون +يناهز +يناوش +يناير +ينبئ +ينبت +ينبثق +ينبذ +ينبذه +ينبري +ينبس +ينبش +ينبض +ينبع +ينبعث +ينبني +ينبه +ينبهني +ينبوع +ينبي +ينتابني +ينتابها +ينتبه +ينتج +ينتجان +ينتجه +ينتجها +ينتجوا +ينتحب +ينتخب +ينتزع +ينتسب +ينتسبون +ينتشر +ينتشله +ينتصب +ينتصر +ينتظر +ينتظران +ينتظرنا +ينتظرني +ينتظره +ينتظرها +ينتظرهم +ينتظرون +ينتظرونه +ينتعل +ينتعله +ينتفض +ينتفع +ينتقص +ينتقل +ينتقلا +ينتقلوا +ينتقلون +ينتقي +ينتمون +ينتمى +ينتمي +ينتميان +ينتمين +ينته +ينتهج +ينتهك +ينتهى +ينتهي +ينثر +ينثره +ينثني +ينج +ينجاب +ينجب +ينجبن +ينجح +ينجحا +ينجحوا +ينجحون +ينجذب +ينجر +ينجرف +ينجز +ينجزها +ينجم +ينجو +ينجوا +ينحازون +ينحت +ينحشر +ينحصر +ينحن +ينحني +ينحو +ينخر +ينخرط +ينخرطوا +ينخفض +ينخلع +يندب +يندر +يندرج +يندس +يندفع +يندفعن +يندفعوا +يندم +يندمج +يندمجا +يندمجوا +يندمل +ينذر +ينذرني +ينزح +ينزع +ينزعج +ينزعها +ينزف +ينزل +ينزلق +ينزلها +ينس +ينساب +ينساه +ينساها +ينسب +ينسبها +ينسبون +ينسج +ينسجم +ينسجها +ينسحب +ينسخ +ينسدل +ينسف +ينسق +ينسكب +ينسل +ينسلخ +ينسهم +ينسون +ينسى +ينسينا +ينسيني +ينشأ +ينشأوا +ينشأُ +ينشئ +ينشئونها +ينشد +ينشدها +ينشدون +ينشدونه +ينشر +ينشرا +ينشط +ينشطون +ينشق +ينشَب +ينشِّط +ينص +ينصب +ينصبون +ينصبونها +ينصبّ +ينصت +ينصح +ينصحون +ينصحونهم +ينصرف +ينصرفوا +ينصرم +ينصهرون +ينضب +ينضج +ينضم +ينضموا +ينضمون +ينضمّ +ينضوي +ينطبق +ينطفئ +ينطق +ينطقه +ينطقها +ينطلق +ينطلقان +ينطوي +ينظر +ينظرن +ينظروا +ينظرون +ينظفها +ينظم +ينظمه +ينظمها +ينظمونه +ينظّم +ينظِّم +ينعت +ينعته +ينعتونه +ينعدم +ينعشه +ينعطف +ينعقد +ينعكس +ينعم +ينعموا +ينعمون +ينعون +ينعي +ينـسى +ينفتح +ينفثون +ينفجر +ينفد +ينفذ +ينفذها +ينفذوا +ينفذون +ينفر +ينفرد +ينفصل +ينفصلان +ينفض +ينفضون +ينفع +ينفعل +ينفعني +ينفعوك +ينفق +ينفقه +ينفقونه +ينفك +ينفي +ينفيه +ينقبض +ينقدها +ينقذ +ينقذنا +ينقذه +ينقر +ينقران +ينقرض +ينقسم +ينقسمون +ينقشع +ينقص +ينقصنا +ينقصها +ينقض +ينقضي +ينقضّ +ينقضّوا +ينقطع +ينقل +ينقلب +ينقلنا +ينقلني +ينقله +ينقلها +ينقلوا +ينقلون +ينكر +ينكرون +ينكس +ينكسر +ينكمش +ينل +ينم +ينمو +ينهار +ينهال +ينهبه +ينهبون +ينهره +ينهش +ينهض +ينهضوا +ينهل +ينهمر +ينهمك +ينهوا +ينهون +ينهى +ينهي +ينوء +ينوب +ينورفولك +ينومان +ينوي +ينير +ينيرها +ينْتَشَرَ +يها +يهاب +يهاجر +يهاجم +يهاجمني +يهاجمه +يهان +يهب +يهبط +يهبطون +يهبنا +يهتد +يهتز +يهتزّ +يهتم +يهتمون +يهجروا +يهجم +يهدآ +يهدأ +يهدئ +يهداك +يهدد +يهددها +يهددون +يهدر +يهدف +يهدفون +يهدم +يهدمها +يهدى +يهديانها +يهديه +يهذر +يهذي +يهرب +يهرع +يهرول +يهز +يهزلون +يهزه +يهزون +يهضم +يهطل +يهفو +يهم +يهمس +يهمش +يهمل +يهمنا +يهمني +يهمه +يهمها +يهمهم +يهمّ +يهن +يهود +يهودي +يهودية +يهون +يهوى +يهيئ +يهيمن +يواجه +يواجهنا +يواجهه +يواجهها +يواجهوا +يواجهون +يواجهونه +يواجهوها +يوازى +يوازي +يوازيها +يواسيني +يواصل +يواظب +يوافق +يوافقه +يوافقوا +يوافقون +يوافيخهم +يواقيم +يواكب +يوبخها +يوتو +يوثق +يوجب +يوجبها +يوجد +يوجه +يوجهها +يوجههُ +يوجوسلافيا +يوجين +يوجّه +يوحدها +يوحدون +يوحنا +يوحي +يود +يودع +يودعني +يودعه +يودعهم +يودعوا +يودون +يورانيوم +يورثها +يورج +يورجنسن +يورد +يوردان +يورك +يورو +يوروبيان +يوزع +يوزعها +يوزعونها +يوسبريدس +يوســــف +يوسف +يوسيبوس +يوشتشنكو +يوشك +يوصد +يوصف +يوصل +يوصلنا +يوصلني +يوصلون +يوصي +يوصيهم +يوضح +يوضحوا +يوضع +يوظف +يوفر +يوفرها +يوفرون +يوفرونها +يوفقنا +يوفقني +يوقظ +يوقع +يوقعها +يوقعهم +يوقف +يوقّع +يوكوهاما +يوكوهاها +يولد +يولدون +يولع +يولم +يولي +يوليبيوس +يولية +يوليه +يوليهما +يوليو +يوليوس +يولّد +يولّدها +يوم +يومئ +يومئذ +يوما +يومان +يوماً +يومذاك +يومض +يومك +يومنا +يومه +يومها +يومي +يوميا +يوميات +يومياتها +يومياتهم +يومياً +يومية +يومين +يوميًّا +يومًا +يومٍ +يونان +يونانيا +يونانية +يونانيًا +يونايتد +يونج +يونس +يوننيو +يونية +يونينيرفيس +يونيو +يوهب +يوهم +يويو +ييئس +ييت +ييل +يَأْمُرُونَ +يَا +يَثْبُت +يَخْفَى +يَرْفَعِ +يَسْتَوِي +يَشَاء +يَعُد +يَعْلَمُونَ +يَفرك +يَفضل +يَفُزْ +يَنتَظِرُ +يَنْبَنِ +يَنْفَعُ +يُؤخِّر +يُؤسس +يُبرّر +يُبسا +يُبقي +يُبكَى +يُبلعا +يُبنى +يُبهر +يُبهرهن +يُتاح +يُترك +يُتَخَلَّص +يُحب +يُحتفظ +يُحتمل +يُحدد +يُحدِث +يُحدّد +يُحذَف +يُحس +يُحسن +يُحكى +يُحيّن +يُختتم +يُخشى +يُدخل +يُدخلوا +يُدركنا +يُدس +يُدعى +يُدفن +يُدل +يُدْخَل +يُدْفَع +يُذكر +يُذهل +يُراد +يُرجع +يُرجعون +يُرسل +يُرضع +يُرضيه +يُروى +يُرى +يُزرع +يُزمع +يُساء +يُستبعد +يُستخدم +يُستشف +يُستشفّ +يُستعمل +يُستهلك +يُسعدك +يُسعف +يُسقط +يُسمح +يُسمع +يُسمن +يُسمى +يُسهم +يُسَبَّب +يُسْمَح +يُشاع +يُشتبه +يُشعرهن +يُشعرُكَ +يُشكِّل +يُشيعه +يُشْبهني +يُشْرَكَ +يُصاب +يُصدر +يُصَدُّ +يُطبع +يُطرح +يُطل +يُطلب +يُطلق +يُطمر +يُطيق +يُظن +يُع +يُعتبر +يُعتد +يُعتدي +يُعتقد +يُعتَقد +يُعد +يُعدّ +يُعدُّ +يُعذب +يُعرض +يُعرف +يُعرفها +يُعرِّض +يُعزى +يُعطى +يُعقد +يُعقل +يُعنَ +يُعَبِّد +يُعَد +يُعَدّ +يُعَيَّن +يُعِد +يُعْمَل +يُعْنى +يُفتح +يُفترض +يُفرض +يُفرّط +يُفسح +يُفسَّر +يُفضي +يُفهم +يُقال +يُقبلن +يُقدَّرون +يُقهر +يُقْدَع +يُكافَأ +يُكتب +يُكتشف +يُكرهها +يُكسب +يُكسَب +يُكشف +يُكْتب +يُلَقَّاهَا +يُمايز +يُمكن +يُمكنك +يُمل +يُمنع +يُمنى +يُمنّي +يُنادى +يُنتجه +يُنزِل +يُنسب +يُنسى +يُنفق +يُنقل +يُنهك +يُنْكَر +يُهان +يُولَد diff --git a/test/resources/complexscripts/arab/ttx/arab-001.ttx b/test/resources/complexscripts/arab/ttx/arab-001.ttx new file mode 100644 index 000000000..d43eb9e5f --- /dev/null +++ b/test/resources/complexscripts/arab/ttx/arab-001.ttx @@ -0,0 +1 @@ + diff --git a/test/resources/complexscripts/arab/ttx/arab-002.ttx b/test/resources/complexscripts/arab/ttx/arab-002.ttx new file mode 100644 index 000000000..7a0c0c2a5 --- /dev/null +++ b/test/resources/complexscripts/arab/ttx/arab-002.ttx @@ -0,0 +1 @@ + diff --git a/test/resources/complexscripts/arab/ttx/arab-003.ttx b/test/resources/complexscripts/arab/ttx/arab-003.ttx new file mode 100644 index 000000000..57ba7da35 --- /dev/null +++ b/test/resources/complexscripts/arab/ttx/arab-003.ttx @@ -0,0 +1 @@ + diff --git a/test/resources/complexscripts/arab/ttx/arab-004.ttx b/test/resources/complexscripts/arab/ttx/arab-004.ttx new file mode 100644 index 000000000..cf3ae37a6 --- /dev/null +++ b/test/resources/complexscripts/arab/ttx/arab-004.ttx @@ -0,0 +1 @@ + -- cgit v1.2.3 From eff48e4a891b2c8159ac81d13cae4e65e444cce2 Mon Sep 17 00:00:00 2001 From: Glenn Adams Date: Fri, 2 Mar 2012 22:19:46 +0000 Subject: enable UnusedImports rule; fix violations git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@1296496 13f79535-47bb-0310-9956-ffa450edef68 --- checkstyle-5.5.xml | 2 +- .../java/org/apache/fop/complexscripts/bidi/GenerateBidiClass.java | 1 - src/java/org/apache/fop/afp/AFPGraphics2D.java | 1 - src/java/org/apache/fop/afp/modca/AbstractAFPObject.java | 1 - src/java/org/apache/fop/afp/modca/ImageObject.java | 1 - src/java/org/apache/fop/afp/modca/PresentationTextData.java | 1 - src/java/org/apache/fop/afp/ptoca/PtocaProducer.java | 2 -- src/java/org/apache/fop/afp/util/DefaultFOPResourceAccessor.java | 2 -- src/java/org/apache/fop/apps/FOUserAgent.java | 1 - src/java/org/apache/fop/area/AreaTreeObject.java | 1 - src/java/org/apache/fop/area/MainReference.java | 1 - src/java/org/apache/fop/area/inline/FilledArea.java | 2 -- src/java/org/apache/fop/complexscripts/bidi/InlineRun.java | 2 -- src/java/org/apache/fop/complexscripts/fonts/GlyphClassTable.java | 1 - .../org/apache/fop/complexscripts/fonts/GlyphDefinitionTable.java | 4 ---- .../apache/fop/complexscripts/fonts/GlyphPositioningSubtable.java | 2 -- .../org/apache/fop/complexscripts/fonts/GlyphSubstitutionTable.java | 2 -- src/java/org/apache/fop/complexscripts/fonts/GlyphTable.java | 1 - .../fop/complexscripts/scripts/DevanagariScriptProcessor.java | 1 - .../apache/fop/complexscripts/scripts/GujaratiScriptProcessor.java | 1 - .../apache/fop/complexscripts/scripts/GurmukhiScriptProcessor.java | 1 - src/java/org/apache/fop/complexscripts/util/GlyphSequence.java | 2 -- src/java/org/apache/fop/fo/FOTreeBuilder.java | 1 - src/java/org/apache/fop/fo/flow/BidiOverride.java | 6 ------ src/java/org/apache/fop/fo/flow/InlineContainer.java | 1 - src/java/org/apache/fop/fo/pagination/RegionBody.java | 1 - src/java/org/apache/fop/fonts/FontReader.java | 1 - src/java/org/apache/fop/fonts/apps/TTFReader.java | 1 - src/java/org/apache/fop/fonts/truetype/TTFSubSetFile.java | 1 - .../org/apache/fop/layoutmgr/BalancingColumnBreakingAlgorithm.java | 1 - src/java/org/apache/fop/layoutmgr/BreakElement.java | 2 -- src/java/org/apache/fop/layoutmgr/KnuthPenalty.java | 2 -- src/java/org/apache/fop/layoutmgr/PageBreakingAlgorithm.java | 1 - .../layoutmgr/inline/AbstractPageNumberCitationLayoutManager.java | 2 -- .../org/apache/fop/layoutmgr/list/ListItemContentLayoutManager.java | 1 - src/java/org/apache/fop/layoutmgr/table/RowPainter.java | 1 - src/java/org/apache/fop/pdf/PDFColor.java | 1 - src/java/org/apache/fop/pdf/PDFStructElem.java | 1 - src/java/org/apache/fop/render/AbstractRenderer.java | 1 - src/java/org/apache/fop/render/ImageHandler.java | 1 - src/java/org/apache/fop/render/afp/AFPDocumentHandler.java | 1 - .../org/apache/fop/render/afp/extensions/AFPIncludeFormMap.java | 2 -- .../apache/fop/render/afp/extensions/AFPIncludeFormMapElement.java | 1 - src/java/org/apache/fop/render/afp/extensions/AFPPageOverlay.java | 2 -- .../org/apache/fop/render/bitmap/AbstractBitmapDocumentHandler.java | 1 - .../org/apache/fop/render/bitmap/BitmapRendererConfigurator.java | 1 - src/java/org/apache/fop/render/bitmap/PNGDocumentHandler.java | 1 - src/java/org/apache/fop/render/bitmap/TIFFDocumentHandler.java | 1 - .../apache/fop/render/intermediate/AbstractIFDocumentHandler.java | 3 --- src/java/org/apache/fop/render/intermediate/IFRenderer.java | 1 - src/java/org/apache/fop/render/intermediate/IFUtil.java | 1 - src/java/org/apache/fop/render/java2d/Base14FontCollection.java | 2 -- src/java/org/apache/fop/render/java2d/CustomFontMetricsMapper.java | 1 - src/java/org/apache/fop/render/java2d/InstalledFontCollection.java | 1 - src/java/org/apache/fop/render/java2d/Java2DPainter.java | 1 - src/java/org/apache/fop/render/java2d/Java2DUtil.java | 2 -- src/java/org/apache/fop/render/java2d/SystemFontMetricsMapper.java | 1 - src/java/org/apache/fop/render/pcl/PCLDocumentHandler.java | 1 - src/java/org/apache/fop/render/pcl/PCLPainter.java | 1 - src/java/org/apache/fop/render/pcl/PCLRendererConfigurator.java | 1 - src/java/org/apache/fop/render/ps/PSDocumentHandler.java | 1 - src/java/org/apache/fop/svg/PDFAElementBridge.java | 1 - src/java/org/apache/fop/traits/MinOptMax.java | 3 --- src/java/org/apache/fop/traits/TraitEnum.java | 2 -- src/java/org/apache/fop/util/ColorExt.java | 2 -- src/sandbox/org/apache/fop/render/svg/SVGDocumentHandler.java | 1 - src/sandbox/org/apache/fop/render/svg/SVGPrintDocumentHandler.java | 1 - 67 files changed, 1 insertion(+), 95 deletions(-) (limited to 'src/java/org/apache/fop/render/bitmap') diff --git a/checkstyle-5.5.xml b/checkstyle-5.5.xml index 0e361ba8b..fd934eff3 100644 --- a/checkstyle-5.5.xml +++ b/checkstyle-5.5.xml @@ -242,7 +242,7 @@ - + diff --git a/src/codegen/unicode/java/org/apache/fop/complexscripts/bidi/GenerateBidiClass.java b/src/codegen/unicode/java/org/apache/fop/complexscripts/bidi/GenerateBidiClass.java index 6b1222011..c38b39c68 100644 --- a/src/codegen/unicode/java/org/apache/fop/complexscripts/bidi/GenerateBidiClass.java +++ b/src/codegen/unicode/java/org/apache/fop/complexscripts/bidi/GenerateBidiClass.java @@ -20,7 +20,6 @@ package org.apache.fop.complexscripts.bidi; import java.io.BufferedReader; -import java.io.FileReader; import java.io.FileWriter; import java.io.InputStreamReader; import java.io.PrintWriter; diff --git a/src/java/org/apache/fop/afp/AFPGraphics2D.java b/src/java/org/apache/fop/afp/AFPGraphics2D.java index d0f1b41b0..41be79160 100644 --- a/src/java/org/apache/fop/afp/AFPGraphics2D.java +++ b/src/java/org/apache/fop/afp/AFPGraphics2D.java @@ -26,7 +26,6 @@ import java.awt.Dimension; import java.awt.Font; import java.awt.FontMetrics; import java.awt.Graphics; -import java.awt.Graphics2D; import java.awt.GraphicsConfiguration; import java.awt.Image; import java.awt.Paint; diff --git a/src/java/org/apache/fop/afp/modca/AbstractAFPObject.java b/src/java/org/apache/fop/afp/modca/AbstractAFPObject.java index 1dd14b124..2c612092e 100644 --- a/src/java/org/apache/fop/afp/modca/AbstractAFPObject.java +++ b/src/java/org/apache/fop/afp/modca/AbstractAFPObject.java @@ -20,7 +20,6 @@ package org.apache.fop.afp.modca; import java.io.IOException; -import java.io.InputStream; import java.io.OutputStream; import java.util.Collection; import java.util.Iterator; diff --git a/src/java/org/apache/fop/afp/modca/ImageObject.java b/src/java/org/apache/fop/afp/modca/ImageObject.java index 2f075ce33..c6cfa3808 100644 --- a/src/java/org/apache/fop/afp/modca/ImageObject.java +++ b/src/java/org/apache/fop/afp/modca/ImageObject.java @@ -29,7 +29,6 @@ import org.apache.xmlgraphics.util.MimeConstants; import org.apache.fop.afp.AFPDataObjectInfo; import org.apache.fop.afp.AFPImageObjectInfo; import org.apache.fop.afp.Factory; -import org.apache.fop.afp.ioca.IDEStructureParameter; import org.apache.fop.afp.ioca.ImageSegment; /** diff --git a/src/java/org/apache/fop/afp/modca/PresentationTextData.java b/src/java/org/apache/fop/afp/modca/PresentationTextData.java index 2b56caf1a..9b1c2eeda 100644 --- a/src/java/org/apache/fop/afp/modca/PresentationTextData.java +++ b/src/java/org/apache/fop/afp/modca/PresentationTextData.java @@ -24,7 +24,6 @@ import java.io.OutputStream; import org.apache.commons.io.output.ByteArrayOutputStream; -import org.apache.fop.afp.ptoca.PtocaBuilder; import org.apache.fop.afp.ptoca.PtocaConstants; import org.apache.fop.afp.util.BinaryUtils; diff --git a/src/java/org/apache/fop/afp/ptoca/PtocaProducer.java b/src/java/org/apache/fop/afp/ptoca/PtocaProducer.java index 504c49658..9b6d97dec 100644 --- a/src/java/org/apache/fop/afp/ptoca/PtocaProducer.java +++ b/src/java/org/apache/fop/afp/ptoca/PtocaProducer.java @@ -21,8 +21,6 @@ package org.apache.fop.afp.ptoca; import java.io.IOException; -import org.apache.fop.afp.modca.PresentationTextObject; - /** * Producer interface that is passed to a {@link PresentationTextObject} to produce PTOCA control * sequences using a {@link PtocaBuilder}. diff --git a/src/java/org/apache/fop/afp/util/DefaultFOPResourceAccessor.java b/src/java/org/apache/fop/afp/util/DefaultFOPResourceAccessor.java index 053db01af..f379546e2 100644 --- a/src/java/org/apache/fop/afp/util/DefaultFOPResourceAccessor.java +++ b/src/java/org/apache/fop/afp/util/DefaultFOPResourceAccessor.java @@ -31,8 +31,6 @@ import javax.xml.transform.stream.StreamSource; import org.apache.commons.io.IOUtils; import org.apache.fop.apps.FOUserAgent; -import org.apache.fop.apps.FopFactory; -import org.apache.fop.fonts.FontManager; /** * Default implementation of the {@link ResourceAccessor} interface for use inside FOP. diff --git a/src/java/org/apache/fop/apps/FOUserAgent.java b/src/java/org/apache/fop/apps/FOUserAgent.java index c13a624cf..665c1abf8 100644 --- a/src/java/org/apache/fop/apps/FOUserAgent.java +++ b/src/java/org/apache/fop/apps/FOUserAgent.java @@ -48,7 +48,6 @@ import org.apache.fop.events.EventListener; import org.apache.fop.events.FOPEventListenerProxy; import org.apache.fop.events.LoggingEventListener; import org.apache.fop.fo.FOEventHandler; -import org.apache.fop.fonts.FontManager; import org.apache.fop.render.Renderer; import org.apache.fop.render.RendererFactory; import org.apache.fop.render.XMLHandlerRegistry; diff --git a/src/java/org/apache/fop/area/AreaTreeObject.java b/src/java/org/apache/fop/area/AreaTreeObject.java index dbbfc5744..ebd88b887 100644 --- a/src/java/org/apache/fop/area/AreaTreeObject.java +++ b/src/java/org/apache/fop/area/AreaTreeObject.java @@ -20,7 +20,6 @@ package org.apache.fop.area; import java.util.Collections; -import java.util.Iterator; import java.util.List; import java.util.Map; diff --git a/src/java/org/apache/fop/area/MainReference.java b/src/java/org/apache/fop/area/MainReference.java index 44f4cc8c8..154e9523c 100644 --- a/src/java/org/apache/fop/area/MainReference.java +++ b/src/java/org/apache/fop/area/MainReference.java @@ -22,7 +22,6 @@ package org.apache.fop.area; import org.apache.fop.traits.WritingModeTraitsGetter; import java.util.ArrayList; -import java.util.Iterator; import java.util.List; /** diff --git a/src/java/org/apache/fop/area/inline/FilledArea.java b/src/java/org/apache/fop/area/inline/FilledArea.java index dfb3af58b..786b0265d 100644 --- a/src/java/org/apache/fop/area/inline/FilledArea.java +++ b/src/java/org/apache/fop/area/inline/FilledArea.java @@ -20,9 +20,7 @@ package org.apache.fop.area.inline; import java.util.ArrayList; -import java.util.Iterator; import java.util.List; -import java.util.ListIterator; /** * Filled area. diff --git a/src/java/org/apache/fop/complexscripts/bidi/InlineRun.java b/src/java/org/apache/fop/complexscripts/bidi/InlineRun.java index 6ea62494a..7897770f8 100644 --- a/src/java/org/apache/fop/complexscripts/bidi/InlineRun.java +++ b/src/java/org/apache/fop/complexscripts/bidi/InlineRun.java @@ -31,10 +31,8 @@ import org.apache.fop.area.inline.InlineViewport; import org.apache.fop.area.inline.Leader; import org.apache.fop.area.inline.Space; import org.apache.fop.area.inline.SpaceArea; -import org.apache.fop.area.inline.TextArea; import org.apache.fop.area.inline.UnresolvedPageNumber; import org.apache.fop.area.inline.WordArea; -import org.apache.fop.traits.Direction; import org.apache.fop.util.CharUtilities; // CSOFF: EmptyForIteratorPadCheck diff --git a/src/java/org/apache/fop/complexscripts/fonts/GlyphClassTable.java b/src/java/org/apache/fop/complexscripts/fonts/GlyphClassTable.java index 60ba6f864..02498af25 100644 --- a/src/java/org/apache/fop/complexscripts/fonts/GlyphClassTable.java +++ b/src/java/org/apache/fop/complexscripts/fonts/GlyphClassTable.java @@ -19,7 +19,6 @@ package org.apache.fop.complexscripts.fonts; -import java.util.Arrays; import java.util.List; import java.util.Iterator; diff --git a/src/java/org/apache/fop/complexscripts/fonts/GlyphDefinitionTable.java b/src/java/org/apache/fop/complexscripts/fonts/GlyphDefinitionTable.java index d5cd04615..62a502eb0 100644 --- a/src/java/org/apache/fop/complexscripts/fonts/GlyphDefinitionTable.java +++ b/src/java/org/apache/fop/complexscripts/fonts/GlyphDefinitionTable.java @@ -19,13 +19,9 @@ package org.apache.fop.complexscripts.fonts; -import java.nio.CharBuffer; - -import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; -import java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/src/java/org/apache/fop/complexscripts/fonts/GlyphPositioningSubtable.java b/src/java/org/apache/fop/complexscripts/fonts/GlyphPositioningSubtable.java index 4325a3547..cb87faff4 100644 --- a/src/java/org/apache/fop/complexscripts/fonts/GlyphPositioningSubtable.java +++ b/src/java/org/apache/fop/complexscripts/fonts/GlyphPositioningSubtable.java @@ -19,8 +19,6 @@ package org.apache.fop.complexscripts.fonts; -import java.util.List; - import org.apache.fop.complexscripts.util.GlyphSequence; import org.apache.fop.complexscripts.util.ScriptContextTester; diff --git a/src/java/org/apache/fop/complexscripts/fonts/GlyphSubstitutionTable.java b/src/java/org/apache/fop/complexscripts/fonts/GlyphSubstitutionTable.java index b6db2fb47..e17c8012c 100644 --- a/src/java/org/apache/fop/complexscripts/fonts/GlyphSubstitutionTable.java +++ b/src/java/org/apache/fop/complexscripts/fonts/GlyphSubstitutionTable.java @@ -19,8 +19,6 @@ package org.apache.fop.complexscripts.fonts; -import java.nio.CharBuffer; - import java.util.ArrayList; import java.util.Iterator; import java.util.List; diff --git a/src/java/org/apache/fop/complexscripts/fonts/GlyphTable.java b/src/java/org/apache/fop/complexscripts/fonts/GlyphTable.java index 427973359..1667e26f1 100644 --- a/src/java/org/apache/fop/complexscripts/fonts/GlyphTable.java +++ b/src/java/org/apache/fop/complexscripts/fonts/GlyphTable.java @@ -21,7 +21,6 @@ package org.apache.fop.complexscripts.fonts; import java.util.Arrays; import java.util.ArrayList; -import java.util.Collection; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.LinkedList; diff --git a/src/java/org/apache/fop/complexscripts/scripts/DevanagariScriptProcessor.java b/src/java/org/apache/fop/complexscripts/scripts/DevanagariScriptProcessor.java index 58bfae734..624c5b153 100644 --- a/src/java/org/apache/fop/complexscripts/scripts/DevanagariScriptProcessor.java +++ b/src/java/org/apache/fop/complexscripts/scripts/DevanagariScriptProcessor.java @@ -23,7 +23,6 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.fop.complexscripts.util.GlyphSequence; -import org.apache.fop.complexscripts.util.ScriptContextTester; // CSOFF: AvoidNestedBlocksCheck // CSOFF: NoWhitespaceAfterCheck diff --git a/src/java/org/apache/fop/complexscripts/scripts/GujaratiScriptProcessor.java b/src/java/org/apache/fop/complexscripts/scripts/GujaratiScriptProcessor.java index 7d1af5366..fd68d4b7c 100644 --- a/src/java/org/apache/fop/complexscripts/scripts/GujaratiScriptProcessor.java +++ b/src/java/org/apache/fop/complexscripts/scripts/GujaratiScriptProcessor.java @@ -23,7 +23,6 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.fop.complexscripts.util.GlyphSequence; -import org.apache.fop.complexscripts.util.ScriptContextTester; // CSOFF: AvoidNestedBlocksCheck // CSOFF: NoWhitespaceAfterCheck diff --git a/src/java/org/apache/fop/complexscripts/scripts/GurmukhiScriptProcessor.java b/src/java/org/apache/fop/complexscripts/scripts/GurmukhiScriptProcessor.java index f5be626a0..efe8791b9 100644 --- a/src/java/org/apache/fop/complexscripts/scripts/GurmukhiScriptProcessor.java +++ b/src/java/org/apache/fop/complexscripts/scripts/GurmukhiScriptProcessor.java @@ -24,7 +24,6 @@ import org.apache.commons.logging.LogFactory; import org.apache.fop.complexscripts.fonts.GlyphDefinitionTable; import org.apache.fop.complexscripts.util.GlyphSequence; -import org.apache.fop.complexscripts.util.ScriptContextTester; // CSOFF: AvoidNestedBlocksCheck // CSOFF: NoWhitespaceAfterCheck diff --git a/src/java/org/apache/fop/complexscripts/util/GlyphSequence.java b/src/java/org/apache/fop/complexscripts/util/GlyphSequence.java index e4316d596..47b158491 100644 --- a/src/java/org/apache/fop/complexscripts/util/GlyphSequence.java +++ b/src/java/org/apache/fop/complexscripts/util/GlyphSequence.java @@ -26,8 +26,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import org.apache.fop.util.CharUtilities; - // CSOFF: InnerAssignmentCheck // CSOFF: LineLengthCheck // CSOFF: WhitespaceAfterCheck diff --git a/src/java/org/apache/fop/fo/FOTreeBuilder.java b/src/java/org/apache/fop/fo/FOTreeBuilder.java index 938efb8f9..e312a8038 100644 --- a/src/java/org/apache/fop/fo/FOTreeBuilder.java +++ b/src/java/org/apache/fop/fo/FOTreeBuilder.java @@ -37,7 +37,6 @@ import org.apache.fop.accessibility.fo.FO2StructureTreeConverter; import org.apache.fop.apps.FOPException; import org.apache.fop.apps.FOUserAgent; import org.apache.fop.apps.FormattingResults; -import org.apache.fop.area.AreaTreeHandler; import org.apache.fop.fo.ElementMapping.Maker; import org.apache.fop.fo.extensions.ExtensionElementMapping; import org.apache.fop.fo.pagination.Root; diff --git a/src/java/org/apache/fop/fo/flow/BidiOverride.java b/src/java/org/apache/fop/fo/flow/BidiOverride.java index d38df90c7..0c14688b7 100644 --- a/src/java/org/apache/fop/fo/flow/BidiOverride.java +++ b/src/java/org/apache/fop/fo/flow/BidiOverride.java @@ -22,18 +22,12 @@ package org.apache.fop.fo.flow; import java.util.Iterator; import java.util.Stack; -import org.xml.sax.Locator; - import org.apache.fop.apps.FOPException; import org.apache.fop.complexscripts.bidi.DelimitedTextRange; -import org.apache.fop.datatypes.Length; import org.apache.fop.fo.Constants; import org.apache.fop.fo.FONode; -import org.apache.fop.fo.FObjMixed; import org.apache.fop.fo.PropertyList; -import org.apache.fop.fo.ValidationException; import org.apache.fop.fo.properties.Property; -import org.apache.fop.fo.properties.SpaceProperty; import org.apache.fop.util.CharUtilities; /** diff --git a/src/java/org/apache/fop/fo/flow/InlineContainer.java b/src/java/org/apache/fop/fo/flow/InlineContainer.java index a52801c3f..b79d66bb0 100644 --- a/src/java/org/apache/fop/fo/flow/InlineContainer.java +++ b/src/java/org/apache/fop/fo/flow/InlineContainer.java @@ -36,7 +36,6 @@ import org.apache.fop.fo.properties.SpaceProperty; import org.apache.fop.traits.Direction; import org.apache.fop.traits.WritingMode; import org.apache.fop.traits.WritingModeTraits; -import org.apache.fop.traits.WritingModeTraitsGetter; /** * Class modelling the
    diff --git a/src/java/org/apache/fop/fo/pagination/RegionBody.java b/src/java/org/apache/fop/fo/pagination/RegionBody.java index 9eb38c260..1fa260ff5 100644 --- a/src/java/org/apache/fop/fo/pagination/RegionBody.java +++ b/src/java/org/apache/fop/fo/pagination/RegionBody.java @@ -32,7 +32,6 @@ import org.apache.fop.fo.Constants; import org.apache.fop.fo.FONode; import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.properties.CommonMarginBlock; -import org.apache.fop.traits.WritingMode; /** * Class modelling the diff --git a/src/java/org/apache/fop/fonts/FontReader.java b/src/java/org/apache/fop/fonts/FontReader.java index 0f0348fc1..9d75ad74f 100644 --- a/src/java/org/apache/fop/fonts/FontReader.java +++ b/src/java/org/apache/fop/fonts/FontReader.java @@ -34,7 +34,6 @@ import org.xml.sax.Attributes; import org.xml.sax.InputSource; import org.xml.sax.Locator; import org.xml.sax.SAXException; -import org.xml.sax.SAXParseException; import org.xml.sax.XMLReader; import org.xml.sax.helpers.DefaultHandler; diff --git a/src/java/org/apache/fop/fonts/apps/TTFReader.java b/src/java/org/apache/fop/fonts/apps/TTFReader.java index 9a12e888c..7159a60b7 100644 --- a/src/java/org/apache/fop/fonts/apps/TTFReader.java +++ b/src/java/org/apache/fop/fonts/apps/TTFReader.java @@ -21,7 +21,6 @@ package org.apache.fop.fonts.apps; import java.io.IOException; import java.util.Iterator; -import java.util.List; import java.util.Map; import java.util.Set; diff --git a/src/java/org/apache/fop/fonts/truetype/TTFSubSetFile.java b/src/java/org/apache/fop/fonts/truetype/TTFSubSetFile.java index e081734be..d400c0bfd 100644 --- a/src/java/org/apache/fop/fonts/truetype/TTFSubSetFile.java +++ b/src/java/org/apache/fop/fonts/truetype/TTFSubSetFile.java @@ -22,7 +22,6 @@ package org.apache.fop.fonts.truetype; import java.io.IOException; import java.util.Iterator; import java.util.Map; -import java.util.Set; /** diff --git a/src/java/org/apache/fop/layoutmgr/BalancingColumnBreakingAlgorithm.java b/src/java/org/apache/fop/layoutmgr/BalancingColumnBreakingAlgorithm.java index 0eae6fa9c..2bcdb6127 100644 --- a/src/java/org/apache/fop/layoutmgr/BalancingColumnBreakingAlgorithm.java +++ b/src/java/org/apache/fop/layoutmgr/BalancingColumnBreakingAlgorithm.java @@ -22,7 +22,6 @@ package org.apache.fop.layoutmgr; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.apache.fop.fo.Constants; import org.apache.fop.traits.MinOptMax; /** diff --git a/src/java/org/apache/fop/layoutmgr/BreakElement.java b/src/java/org/apache/fop/layoutmgr/BreakElement.java index 7208a585f..1c89c2009 100644 --- a/src/java/org/apache/fop/layoutmgr/BreakElement.java +++ b/src/java/org/apache/fop/layoutmgr/BreakElement.java @@ -21,8 +21,6 @@ package org.apache.fop.layoutmgr; import java.util.List; -import org.apache.fop.fo.Constants; - /** * This class represents an unresolved break possibility. */ diff --git a/src/java/org/apache/fop/layoutmgr/KnuthPenalty.java b/src/java/org/apache/fop/layoutmgr/KnuthPenalty.java index 22a74485e..2d4e1f2be 100644 --- a/src/java/org/apache/fop/layoutmgr/KnuthPenalty.java +++ b/src/java/org/apache/fop/layoutmgr/KnuthPenalty.java @@ -19,8 +19,6 @@ package org.apache.fop.layoutmgr; -import org.apache.fop.fo.Constants; - /** * An instance of this class represents information about a feasible * breaking point; it does not represent any piece of content. diff --git a/src/java/org/apache/fop/layoutmgr/PageBreakingAlgorithm.java b/src/java/org/apache/fop/layoutmgr/PageBreakingAlgorithm.java index 4b6638300..3d45812d8 100644 --- a/src/java/org/apache/fop/layoutmgr/PageBreakingAlgorithm.java +++ b/src/java/org/apache/fop/layoutmgr/PageBreakingAlgorithm.java @@ -20,7 +20,6 @@ package org.apache.fop.layoutmgr; import java.util.ArrayList; -import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.ListIterator; diff --git a/src/java/org/apache/fop/layoutmgr/inline/AbstractPageNumberCitationLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/AbstractPageNumberCitationLayoutManager.java index aba137115..b9110de9e 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/AbstractPageNumberCitationLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/AbstractPageNumberCitationLayoutManager.java @@ -19,12 +19,10 @@ package org.apache.fop.layoutmgr.inline; -import org.apache.fop.area.PageViewport; import org.apache.fop.area.Resolvable; import org.apache.fop.area.Trait; import org.apache.fop.area.inline.InlineArea; import org.apache.fop.area.inline.TextArea; -import org.apache.fop.area.inline.UnresolvedPageNumber; import org.apache.fop.fo.flow.AbstractPageNumberCitation; import org.apache.fop.fonts.Font; import org.apache.fop.fonts.FontInfo; diff --git a/src/java/org/apache/fop/layoutmgr/list/ListItemContentLayoutManager.java b/src/java/org/apache/fop/layoutmgr/list/ListItemContentLayoutManager.java index 72e4e227a..291def4c3 100644 --- a/src/java/org/apache/fop/layoutmgr/list/ListItemContentLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/list/ListItemContentLayoutManager.java @@ -20,7 +20,6 @@ package org.apache.fop.layoutmgr.list; import java.util.LinkedList; -import java.util.List; import org.apache.fop.area.Area; import org.apache.fop.area.Block; diff --git a/src/java/org/apache/fop/layoutmgr/table/RowPainter.java b/src/java/org/apache/fop/layoutmgr/table/RowPainter.java index b3cb06582..f6c831b3f 100644 --- a/src/java/org/apache/fop/layoutmgr/table/RowPainter.java +++ b/src/java/org/apache/fop/layoutmgr/table/RowPainter.java @@ -46,7 +46,6 @@ import org.apache.fop.layoutmgr.KnuthPossPosIter; import org.apache.fop.layoutmgr.LayoutContext; import org.apache.fop.layoutmgr.SpaceResolver; import org.apache.fop.layoutmgr.TraitSetter; -import org.apache.fop.traits.BorderProps; class RowPainter { private static Log log = LogFactory.getLog(RowPainter.class); diff --git a/src/java/org/apache/fop/pdf/PDFColor.java b/src/java/org/apache/fop/pdf/PDFColor.java index 781012cfa..8eea7e390 100644 --- a/src/java/org/apache/fop/pdf/PDFColor.java +++ b/src/java/org/apache/fop/pdf/PDFColor.java @@ -19,7 +19,6 @@ package org.apache.fop.pdf; -import java.awt.Color; import java.awt.color.ColorSpace; import java.util.ArrayList; import java.util.List; diff --git a/src/java/org/apache/fop/pdf/PDFStructElem.java b/src/java/org/apache/fop/pdf/PDFStructElem.java index 160d55384..e35a860d9 100644 --- a/src/java/org/apache/fop/pdf/PDFStructElem.java +++ b/src/java/org/apache/fop/pdf/PDFStructElem.java @@ -21,7 +21,6 @@ package org.apache.fop.pdf; import java.io.IOException; import java.io.OutputStream; -import java.io.Writer; import java.util.ArrayList; import java.util.List; import java.util.Locale; diff --git a/src/java/org/apache/fop/render/AbstractRenderer.java b/src/java/org/apache/fop/render/AbstractRenderer.java index 639f8590b..a2d74bd8d 100644 --- a/src/java/org/apache/fop/render/AbstractRenderer.java +++ b/src/java/org/apache/fop/render/AbstractRenderer.java @@ -25,7 +25,6 @@ import java.awt.geom.AffineTransform; import java.awt.geom.Rectangle2D; import java.io.IOException; import java.io.OutputStream; -import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.Set; diff --git a/src/java/org/apache/fop/render/ImageHandler.java b/src/java/org/apache/fop/render/ImageHandler.java index 0078e37bd..fe6952de1 100644 --- a/src/java/org/apache/fop/render/ImageHandler.java +++ b/src/java/org/apache/fop/render/ImageHandler.java @@ -23,7 +23,6 @@ import java.awt.Rectangle; import java.io.IOException; import org.apache.xmlgraphics.image.loader.Image; -import org.apache.xmlgraphics.image.loader.impl.ImageXMLDOM; /** * This interface is a service provider interface for image handlers. diff --git a/src/java/org/apache/fop/render/afp/AFPDocumentHandler.java b/src/java/org/apache/fop/render/afp/AFPDocumentHandler.java index 29f689555..cddcc7b84 100644 --- a/src/java/org/apache/fop/render/afp/AFPDocumentHandler.java +++ b/src/java/org/apache/fop/render/afp/AFPDocumentHandler.java @@ -53,7 +53,6 @@ import org.apache.fop.render.afp.extensions.AFPPageSegmentElement; import org.apache.fop.render.afp.extensions.AFPPageSetup; import org.apache.fop.render.afp.extensions.ExtensionPlacement; import org.apache.fop.render.intermediate.AbstractBinaryWritingIFDocumentHandler; -import org.apache.fop.render.intermediate.IFDocumentHandler; import org.apache.fop.render.intermediate.IFDocumentHandlerConfigurator; import org.apache.fop.render.intermediate.IFException; import org.apache.fop.render.intermediate.IFPainter; diff --git a/src/java/org/apache/fop/render/afp/extensions/AFPIncludeFormMap.java b/src/java/org/apache/fop/render/afp/extensions/AFPIncludeFormMap.java index 06c7cbc9d..842456f69 100644 --- a/src/java/org/apache/fop/render/afp/extensions/AFPIncludeFormMap.java +++ b/src/java/org/apache/fop/render/afp/extensions/AFPIncludeFormMap.java @@ -25,8 +25,6 @@ import org.xml.sax.ContentHandler; import org.xml.sax.SAXException; import org.xml.sax.helpers.AttributesImpl; -import org.apache.fop.fo.extensions.ExtensionAttachment; - /** * This extension allows to include an AFP form map resource. It is implemented as an extension * attachment ({@link ExtensionAttachment}). diff --git a/src/java/org/apache/fop/render/afp/extensions/AFPIncludeFormMapElement.java b/src/java/org/apache/fop/render/afp/extensions/AFPIncludeFormMapElement.java index 719d8c765..37f818f64 100644 --- a/src/java/org/apache/fop/render/afp/extensions/AFPIncludeFormMapElement.java +++ b/src/java/org/apache/fop/render/afp/extensions/AFPIncludeFormMapElement.java @@ -30,7 +30,6 @@ import org.apache.fop.fo.Constants; import org.apache.fop.fo.FONode; import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.extensions.ExtensionAttachment; -import org.apache.fop.fo.extensions.ExtensionObj; /** * This class extends the {@link ExtensionObj} class. It represents the "include-form-map" diff --git a/src/java/org/apache/fop/render/afp/extensions/AFPPageOverlay.java b/src/java/org/apache/fop/render/afp/extensions/AFPPageOverlay.java index a82fe3457..0900d40b4 100644 --- a/src/java/org/apache/fop/render/afp/extensions/AFPPageOverlay.java +++ b/src/java/org/apache/fop/render/afp/extensions/AFPPageOverlay.java @@ -23,8 +23,6 @@ import org.xml.sax.ContentHandler; import org.xml.sax.SAXException; import org.xml.sax.helpers.AttributesImpl; -import org.apache.fop.fo.extensions.ExtensionAttachment; - /** * This extension allows to include an AFP Page Overlay resource. It is implemented as an extension * attachment ({@link ExtensionAttachment}). diff --git a/src/java/org/apache/fop/render/bitmap/AbstractBitmapDocumentHandler.java b/src/java/org/apache/fop/render/bitmap/AbstractBitmapDocumentHandler.java index 0577a737a..c98c05a8e 100644 --- a/src/java/org/apache/fop/render/bitmap/AbstractBitmapDocumentHandler.java +++ b/src/java/org/apache/fop/render/bitmap/AbstractBitmapDocumentHandler.java @@ -40,7 +40,6 @@ import org.apache.fop.apps.FopFactoryConfigurator; import org.apache.fop.fonts.FontInfo; import org.apache.fop.render.intermediate.AbstractBinaryWritingIFDocumentHandler; import org.apache.fop.render.intermediate.IFContext; -import org.apache.fop.render.intermediate.IFDocumentHandler; import org.apache.fop.render.intermediate.IFDocumentHandlerConfigurator; import org.apache.fop.render.intermediate.IFException; import org.apache.fop.render.intermediate.IFPainter; diff --git a/src/java/org/apache/fop/render/bitmap/BitmapRendererConfigurator.java b/src/java/org/apache/fop/render/bitmap/BitmapRendererConfigurator.java index 296d4628a..2ca0a172b 100644 --- a/src/java/org/apache/fop/render/bitmap/BitmapRendererConfigurator.java +++ b/src/java/org/apache/fop/render/bitmap/BitmapRendererConfigurator.java @@ -19,7 +19,6 @@ package org.apache.fop.render.bitmap; -import java.awt.Graphics2D; import java.awt.image.BufferedImage; import java.util.List; diff --git a/src/java/org/apache/fop/render/bitmap/PNGDocumentHandler.java b/src/java/org/apache/fop/render/bitmap/PNGDocumentHandler.java index 77a024436..05c44a1a6 100644 --- a/src/java/org/apache/fop/render/bitmap/PNGDocumentHandler.java +++ b/src/java/org/apache/fop/render/bitmap/PNGDocumentHandler.java @@ -20,7 +20,6 @@ package org.apache.fop.render.bitmap; import org.apache.fop.apps.MimeConstants; -import org.apache.fop.render.intermediate.IFDocumentHandler; import org.apache.fop.render.intermediate.IFDocumentHandlerConfigurator; /** diff --git a/src/java/org/apache/fop/render/bitmap/TIFFDocumentHandler.java b/src/java/org/apache/fop/render/bitmap/TIFFDocumentHandler.java index a212d0e9e..4b7fa3c2d 100644 --- a/src/java/org/apache/fop/render/bitmap/TIFFDocumentHandler.java +++ b/src/java/org/apache/fop/render/bitmap/TIFFDocumentHandler.java @@ -20,7 +20,6 @@ package org.apache.fop.render.bitmap; import org.apache.fop.apps.MimeConstants; -import org.apache.fop.render.intermediate.IFDocumentHandler; import org.apache.fop.render.intermediate.IFDocumentHandlerConfigurator; /** diff --git a/src/java/org/apache/fop/render/intermediate/AbstractIFDocumentHandler.java b/src/java/org/apache/fop/render/intermediate/AbstractIFDocumentHandler.java index ad4e6ad0e..2b90e4a7b 100644 --- a/src/java/org/apache/fop/render/intermediate/AbstractIFDocumentHandler.java +++ b/src/java/org/apache/fop/render/intermediate/AbstractIFDocumentHandler.java @@ -21,9 +21,6 @@ package org.apache.fop.render.intermediate; import java.util.Locale; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - import org.apache.fop.accessibility.DummyStructureTreeEventHandler; import org.apache.fop.accessibility.StructureTreeEventHandler; import org.apache.fop.apps.FOUserAgent; diff --git a/src/java/org/apache/fop/render/intermediate/IFRenderer.java b/src/java/org/apache/fop/render/intermediate/IFRenderer.java index 64633bfab..5940fb661 100644 --- a/src/java/org/apache/fop/render/intermediate/IFRenderer.java +++ b/src/java/org/apache/fop/render/intermediate/IFRenderer.java @@ -61,7 +61,6 @@ import org.apache.fop.area.BlockViewport; import org.apache.fop.area.BookmarkData; import org.apache.fop.area.CTM; import org.apache.fop.area.DestinationData; -import org.apache.fop.area.LineArea; import org.apache.fop.area.OffDocumentExtensionAttachment; import org.apache.fop.area.OffDocumentItem; import org.apache.fop.area.PageSequence; diff --git a/src/java/org/apache/fop/render/intermediate/IFUtil.java b/src/java/org/apache/fop/render/intermediate/IFUtil.java index fa1e87780..a384461ac 100644 --- a/src/java/org/apache/fop/render/intermediate/IFUtil.java +++ b/src/java/org/apache/fop/render/intermediate/IFUtil.java @@ -23,7 +23,6 @@ import java.awt.Rectangle; import java.awt.geom.AffineTransform; import org.apache.fop.apps.FOPException; -import org.apache.fop.apps.FopFactory; import org.apache.fop.fonts.FontInfo; import org.apache.fop.util.DecimalFormatCache; diff --git a/src/java/org/apache/fop/render/java2d/Base14FontCollection.java b/src/java/org/apache/fop/render/java2d/Base14FontCollection.java index 578745281..b9b6d12e6 100644 --- a/src/java/org/apache/fop/render/java2d/Base14FontCollection.java +++ b/src/java/org/apache/fop/render/java2d/Base14FontCollection.java @@ -19,8 +19,6 @@ package org.apache.fop.render.java2d; -import java.awt.Graphics2D; - import org.apache.fop.fonts.Font; import org.apache.fop.fonts.FontCollection; import org.apache.fop.fonts.FontInfo; diff --git a/src/java/org/apache/fop/render/java2d/CustomFontMetricsMapper.java b/src/java/org/apache/fop/render/java2d/CustomFontMetricsMapper.java index 6540d6e37..5d964cbbf 100644 --- a/src/java/org/apache/fop/render/java2d/CustomFontMetricsMapper.java +++ b/src/java/org/apache/fop/render/java2d/CustomFontMetricsMapper.java @@ -30,7 +30,6 @@ import javax.xml.transform.Source; import javax.xml.transform.stream.StreamSource; import org.apache.fop.fonts.CustomFont; -import org.apache.fop.fonts.FontMetrics; import org.apache.fop.fonts.FontType; import org.apache.fop.fonts.LazyFont; import org.apache.fop.fonts.Typeface; diff --git a/src/java/org/apache/fop/render/java2d/InstalledFontCollection.java b/src/java/org/apache/fop/render/java2d/InstalledFontCollection.java index f41dd4d92..65e82f7b3 100644 --- a/src/java/org/apache/fop/render/java2d/InstalledFontCollection.java +++ b/src/java/org/apache/fop/render/java2d/InstalledFontCollection.java @@ -19,7 +19,6 @@ package org.apache.fop.render.java2d; -import java.awt.Graphics2D; import java.awt.GraphicsEnvironment; import java.util.Set; diff --git a/src/java/org/apache/fop/render/java2d/Java2DPainter.java b/src/java/org/apache/fop/render/java2d/Java2DPainter.java index c7fa1adc5..dd830a15b 100644 --- a/src/java/org/apache/fop/render/java2d/Java2DPainter.java +++ b/src/java/org/apache/fop/render/java2d/Java2DPainter.java @@ -40,7 +40,6 @@ import org.apache.fop.render.RenderingContext; import org.apache.fop.render.intermediate.AbstractIFPainter; import org.apache.fop.render.intermediate.IFContext; import org.apache.fop.render.intermediate.IFException; -import org.apache.fop.render.intermediate.IFPainter; import org.apache.fop.render.intermediate.IFState; import org.apache.fop.render.intermediate.IFUtil; import org.apache.fop.traits.BorderProps; diff --git a/src/java/org/apache/fop/render/java2d/Java2DUtil.java b/src/java/org/apache/fop/render/java2d/Java2DUtil.java index 961d64ad2..924460bd8 100644 --- a/src/java/org/apache/fop/render/java2d/Java2DUtil.java +++ b/src/java/org/apache/fop/render/java2d/Java2DUtil.java @@ -19,8 +19,6 @@ package org.apache.fop.render.java2d; -import java.awt.Graphics2D; - import org.apache.fop.apps.FOUserAgent; import org.apache.fop.fonts.FontCollection; import org.apache.fop.fonts.FontEventAdapter; diff --git a/src/java/org/apache/fop/render/java2d/SystemFontMetricsMapper.java b/src/java/org/apache/fop/render/java2d/SystemFontMetricsMapper.java index fac436909..06c975b86 100644 --- a/src/java/org/apache/fop/render/java2d/SystemFontMetricsMapper.java +++ b/src/java/org/apache/fop/render/java2d/SystemFontMetricsMapper.java @@ -20,7 +20,6 @@ package org.apache.fop.render.java2d; // Java -import java.awt.Graphics2D; import java.util.Map; import java.util.Set; diff --git a/src/java/org/apache/fop/render/pcl/PCLDocumentHandler.java b/src/java/org/apache/fop/render/pcl/PCLDocumentHandler.java index 5af0fd179..52e522c7a 100644 --- a/src/java/org/apache/fop/render/pcl/PCLDocumentHandler.java +++ b/src/java/org/apache/fop/render/pcl/PCLDocumentHandler.java @@ -37,7 +37,6 @@ import org.apache.fop.apps.MimeConstants; import org.apache.fop.fonts.FontInfo; import org.apache.fop.render.intermediate.AbstractBinaryWritingIFDocumentHandler; import org.apache.fop.render.intermediate.IFContext; -import org.apache.fop.render.intermediate.IFDocumentHandler; import org.apache.fop.render.intermediate.IFDocumentHandlerConfigurator; import org.apache.fop.render.intermediate.IFException; import org.apache.fop.render.intermediate.IFPainter; diff --git a/src/java/org/apache/fop/render/pcl/PCLPainter.java b/src/java/org/apache/fop/render/pcl/PCLPainter.java index 53e3d77da..9fc575456 100644 --- a/src/java/org/apache/fop/render/pcl/PCLPainter.java +++ b/src/java/org/apache/fop/render/pcl/PCLPainter.java @@ -49,7 +49,6 @@ import org.apache.fop.render.RenderingContext; import org.apache.fop.render.intermediate.AbstractIFPainter; import org.apache.fop.render.intermediate.IFContext; import org.apache.fop.render.intermediate.IFException; -import org.apache.fop.render.intermediate.IFPainter; import org.apache.fop.render.intermediate.IFState; import org.apache.fop.render.intermediate.IFUtil; import org.apache.fop.render.java2d.FontMetricsMapper; diff --git a/src/java/org/apache/fop/render/pcl/PCLRendererConfigurator.java b/src/java/org/apache/fop/render/pcl/PCLRendererConfigurator.java index 84608b685..bc4cdc567 100644 --- a/src/java/org/apache/fop/render/pcl/PCLRendererConfigurator.java +++ b/src/java/org/apache/fop/render/pcl/PCLRendererConfigurator.java @@ -19,7 +19,6 @@ package org.apache.fop.render.pcl; -import java.awt.Graphics2D; import java.util.List; import org.apache.avalon.framework.configuration.Configuration; diff --git a/src/java/org/apache/fop/render/ps/PSDocumentHandler.java b/src/java/org/apache/fop/render/ps/PSDocumentHandler.java index d55e0724b..490e42b2d 100644 --- a/src/java/org/apache/fop/render/ps/PSDocumentHandler.java +++ b/src/java/org/apache/fop/render/ps/PSDocumentHandler.java @@ -52,7 +52,6 @@ import org.apache.xmlgraphics.ps.dsc.events.DSCCommentHiResBoundingBox; import org.apache.fop.apps.MimeConstants; import org.apache.fop.render.intermediate.AbstractBinaryWritingIFDocumentHandler; import org.apache.fop.render.intermediate.IFContext; -import org.apache.fop.render.intermediate.IFDocumentHandler; import org.apache.fop.render.intermediate.IFDocumentHandlerConfigurator; import org.apache.fop.render.intermediate.IFException; import org.apache.fop.render.intermediate.IFPainter; diff --git a/src/java/org/apache/fop/svg/PDFAElementBridge.java b/src/java/org/apache/fop/svg/PDFAElementBridge.java index c68578d63..eed567447 100644 --- a/src/java/org/apache/fop/svg/PDFAElementBridge.java +++ b/src/java/org/apache/fop/svg/PDFAElementBridge.java @@ -26,7 +26,6 @@ import org.w3c.dom.svg.SVGAElement; import org.apache.batik.bridge.AbstractGraphicsNodeBridge; import org.apache.batik.bridge.BridgeContext; -import org.apache.batik.gvt.CompositeGraphicsNode; import org.apache.batik.gvt.GraphicsNode; /** diff --git a/src/java/org/apache/fop/traits/MinOptMax.java b/src/java/org/apache/fop/traits/MinOptMax.java index 45b55695f..022f3c214 100644 --- a/src/java/org/apache/fop/traits/MinOptMax.java +++ b/src/java/org/apache/fop/traits/MinOptMax.java @@ -21,9 +21,6 @@ package org.apache.fop.traits; import java.io.Serializable; -import org.apache.fop.fo.properties.LengthRangeProperty; -import org.apache.fop.fo.properties.SpaceProperty; - /** * This class holds the resolved (as mpoints) form of a {@link LengthRangeProperty LengthRange} or * {@link SpaceProperty Space} type property value. diff --git a/src/java/org/apache/fop/traits/TraitEnum.java b/src/java/org/apache/fop/traits/TraitEnum.java index c473228cb..18fdffaab 100644 --- a/src/java/org/apache/fop/traits/TraitEnum.java +++ b/src/java/org/apache/fop/traits/TraitEnum.java @@ -21,8 +21,6 @@ package org.apache.fop.traits; import java.io.Serializable; -import org.apache.fop.fo.Constants; - /** Base class for enumeration classes representing traits. */ public abstract class TraitEnum implements Serializable { diff --git a/src/java/org/apache/fop/util/ColorExt.java b/src/java/org/apache/fop/util/ColorExt.java index bd4aee340..d0ac6767c 100644 --- a/src/java/org/apache/fop/util/ColorExt.java +++ b/src/java/org/apache/fop/util/ColorExt.java @@ -23,8 +23,6 @@ import java.awt.Color; import java.awt.color.ColorSpace; import java.util.Arrays; -import org.apache.xmlgraphics.java2d.color.ColorWithAlternatives; - /** * Color helper class. *

    diff --git a/src/sandbox/org/apache/fop/render/svg/SVGDocumentHandler.java b/src/sandbox/org/apache/fop/render/svg/SVGDocumentHandler.java index 6c775f177..ef0d9f301 100644 --- a/src/sandbox/org/apache/fop/render/svg/SVGDocumentHandler.java +++ b/src/sandbox/org/apache/fop/render/svg/SVGDocumentHandler.java @@ -48,7 +48,6 @@ import org.apache.commons.io.IOUtils; import org.apache.fop.render.bitmap.BitmapRendererEventProducer; import org.apache.fop.render.bitmap.MultiFileRenderingUtil; import org.apache.fop.render.intermediate.DelegatingFragmentContentHandler; -import org.apache.fop.render.intermediate.IFDocumentHandler; import org.apache.fop.render.intermediate.IFException; import org.apache.fop.render.intermediate.IFPainter; import org.apache.fop.util.GenerationHelperContentHandler; diff --git a/src/sandbox/org/apache/fop/render/svg/SVGPrintDocumentHandler.java b/src/sandbox/org/apache/fop/render/svg/SVGPrintDocumentHandler.java index e5832eba1..10be9588e 100644 --- a/src/sandbox/org/apache/fop/render/svg/SVGPrintDocumentHandler.java +++ b/src/sandbox/org/apache/fop/render/svg/SVGPrintDocumentHandler.java @@ -27,7 +27,6 @@ import org.xml.sax.SAXException; import org.xml.sax.helpers.AttributesImpl; import org.apache.fop.render.intermediate.IFConstants; -import org.apache.fop.render.intermediate.IFDocumentHandler; import org.apache.fop.render.intermediate.IFException; import org.apache.fop.render.intermediate.IFPainter; import org.apache.fop.util.XMLUtil; -- cgit v1.2.3 From e7181a7fdfa0336e688d8ed9e27f0304c741d7d2 Mon Sep 17 00:00:00 2001 From: Glenn Adams Date: Mon, 4 Jun 2012 05:42:06 +0000 Subject: Eliminate javadocs warnings. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@1345838 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/afp/AFPGraphics2D.java | 4 +- src/java/org/apache/fop/afp/modca/ImageObject.java | 6 ++- .../apache/fop/afp/modca/PresentationTextData.java | 2 +- .../fop/afp/util/DefaultFOPResourceAccessor.java | 3 +- src/java/org/apache/fop/apps/FOUserAgent.java | 5 +- .../fonts/GlyphPositioningTable.java | 2 +- .../scripts/IndicScriptProcessor.java | 2 +- src/java/org/apache/fop/fo/FOEventHandler.java | 14 +++-- .../BalancingColumnBreakingAlgorithm.java | 16 +++--- .../org/apache/fop/layoutmgr/BreakElement.java | 34 ++++++++---- .../org/apache/fop/layoutmgr/KnuthPenalty.java | 7 ++- src/java/org/apache/fop/pdf/PDFColor.java | 2 +- src/java/org/apache/fop/pdf/PDFEmbeddedFile.java | 5 +- src/java/org/apache/fop/pdf/PDFObject.java | 6 --- src/java/org/apache/fop/render/ImageHandler.java | 3 +- .../apache/fop/render/afp/AFPDocumentHandler.java | 3 +- .../render/afp/extensions/AFPIncludeFormMap.java | 2 +- .../afp/extensions/AFPIncludeFormMapElement.java | 4 +- .../fop/render/afp/extensions/AFPPageOverlay.java | 2 +- .../bitmap/AbstractBitmapDocumentHandler.java | 3 +- .../fop/render/bitmap/PNGDocumentHandler.java | 3 +- .../fop/render/bitmap/TIFFDocumentHandler.java | 3 +- .../apache/fop/render/intermediate/IFContext.java | 4 +- .../org/apache/fop/render/intermediate/IFUtil.java | 8 +-- .../fop/render/java2d/CustomFontMetricsMapper.java | 2 +- .../apache/fop/render/java2d/Java2DPainter.java | 3 +- .../apache/fop/render/pcl/PCLDocumentHandler.java | 3 +- src/java/org/apache/fop/render/pcl/PCLPainter.java | 3 +- .../apache/fop/render/ps/NativeTextHandler.java | 6 --- .../apache/fop/render/ps/PSDocumentHandler.java | 3 +- src/java/org/apache/fop/svg/PDFAElementBridge.java | 2 +- src/java/org/apache/fop/traits/MinOptMax.java | 5 +- src/java/org/apache/fop/traits/TraitEnum.java | 4 +- src/java/org/apache/fop/util/ColorExt.java | 2 +- .../org/apache/fop/render/mif/MIFHandler.java | 60 ++++++++++++++-------- .../apache/fop/render/svg/SVGDocumentHandler.java | 3 +- .../fop/render/svg/SVGPrintDocumentHandler.java | 3 +- status.xml | 3 ++ 38 files changed, 149 insertions(+), 96 deletions(-) (limited to 'src/java/org/apache/fop/render/bitmap') diff --git a/src/java/org/apache/fop/afp/AFPGraphics2D.java b/src/java/org/apache/fop/afp/AFPGraphics2D.java index e9a269ac4..7172b0ee3 100644 --- a/src/java/org/apache/fop/afp/AFPGraphics2D.java +++ b/src/java/org/apache/fop/afp/AFPGraphics2D.java @@ -67,7 +67,7 @@ import org.apache.fop.svg.NativeImageHandler; /** * This is a concrete implementation of {@link AbstractGraphics2D} (and - * therefore of {@link Graphics2D}) which is able to generate GOCA byte + * therefore of {@link java.awt.Graphics2D}) which is able to generate GOCA byte * codes. * * @see org.apache.xmlgraphics.java2d.AbstractGraphics2D @@ -165,7 +165,7 @@ public class AFPGraphics2D extends AbstractGraphics2D implements NativeImageHand } /** - * Returns the AFP resource manager associated with this {@link Graphics2D} instance. + * Returns the AFP resource manager associated with this {@link java.awt.Graphics2D} instance. * @return the resource manager */ public AFPResourceManager getResourceManager() { diff --git a/src/java/org/apache/fop/afp/modca/ImageObject.java b/src/java/org/apache/fop/afp/modca/ImageObject.java index adb56e626..e42639248 100644 --- a/src/java/org/apache/fop/afp/modca/ImageObject.java +++ b/src/java/org/apache/fop/afp/modca/ImageObject.java @@ -119,7 +119,8 @@ public class ImageObject extends AbstractDataObject { * Sets the image IDE color model. * * @param colorModel the IDE color model. - * @deprecated Use {@link IDEStructureParameter#setColorModel(byte)} instead. + * @deprecated Use {@link org.apache.fop.afp.ioca.IDEStructureParameter#setColorModel(byte)} + * instead. */ public void setIDEColorModel(byte colorModel) { getImageSegment().setIDEColorModel(colorModel); @@ -128,7 +129,8 @@ public class ImageObject extends AbstractDataObject { /** * Set either additive or subtractive mode (used for ASFLAG). * @param subtractive true for subtractive mode, false for additive mode - * @deprecated Use {@link IDEStructureParameter#setSubtractive(boolean)} instead. + * @deprecated Use {@link org.apache.fop.afp.ioca.IDEStructureParameter#setSubtractive(boolean)} + * instead. */ public void setSubtractive(boolean subtractive) { getImageSegment().setSubtractive(subtractive); diff --git a/src/java/org/apache/fop/afp/modca/PresentationTextData.java b/src/java/org/apache/fop/afp/modca/PresentationTextData.java index b68131413..c0934b1e5 100644 --- a/src/java/org/apache/fop/afp/modca/PresentationTextData.java +++ b/src/java/org/apache/fop/afp/modca/PresentationTextData.java @@ -46,7 +46,7 @@ import org.apache.fop.afp.util.BinaryUtils; * which signal an alternate mode of processing for the content of the current * Presentation Text data. *

    - * The content for this object can be created using {@link PtocaBuilder}. + * The content for this object can be created using {@link org.apache.fop.afp.ptoca.PtocaBuilder}. */ public class PresentationTextData extends AbstractAFPObject implements PtocaConstants { diff --git a/src/java/org/apache/fop/afp/util/DefaultFOPResourceAccessor.java b/src/java/org/apache/fop/afp/util/DefaultFOPResourceAccessor.java index f379546e2..2872976b6 100644 --- a/src/java/org/apache/fop/afp/util/DefaultFOPResourceAccessor.java +++ b/src/java/org/apache/fop/afp/util/DefaultFOPResourceAccessor.java @@ -44,7 +44,8 @@ public class DefaultFOPResourceAccessor extends SimpleResourceAccessor { * Constructor for resource to be accessed via the {@link FOUserAgent}. This contructor * can take two base URIs: the category base URI is the one to use when differentiating between * normal resources (ex. images) and font resources. So, if fonts need to be accessed, you can - * set the {@link FontManager}'s base URI instead of the one on the {@link FopFactory}. + * set the {@link org.apache.fop.fonts.FontManager}'s base URI instead of the one on the + * {@link org.apache.fop.apps.FopFactory}. * @param userAgent the FO user agent * @param categoryBaseURI the category base URI (may be null) * @param baseURI the custom base URI to resolve relative URIs against (may be null) diff --git a/src/java/org/apache/fop/apps/FOUserAgent.java b/src/java/org/apache/fop/apps/FOUserAgent.java index 665c1abf8..035b6f1a1 100644 --- a/src/java/org/apache/fop/apps/FOUserAgent.java +++ b/src/java/org/apache/fop/apps/FOUserAgent.java @@ -355,7 +355,7 @@ public class FOUserAgent { /** * Sets font base URL. * @param fontBaseUrl font base URL - * @deprecated Use {@link FontManager#setFontBaseURL(String)} instead. + * @deprecated Use {@link org.apache.fop.fonts.FontManager#setFontBaseURL(String)} instead. */ public void setFontBaseURL(String fontBaseUrl) { try { @@ -500,7 +500,8 @@ public class FOUserAgent { /** * Returns the font base URL. * @return the font base URL - * @deprecated Use {@link FontManager#getFontBaseURL()} instead. This method is not used by FOP. + * @deprecated Use {@link org.apache.fop.fonts.FontManager#getFontBaseURL()} instead. + * This method is not used by FOP. */ public String getFontBaseURL() { String fontBase = getFactory().getFontManager().getFontBaseURL(); diff --git a/src/java/org/apache/fop/complexscripts/fonts/GlyphPositioningTable.java b/src/java/org/apache/fop/complexscripts/fonts/GlyphPositioningTable.java index 3b7c14b0e..6db6be726 100644 --- a/src/java/org/apache/fop/complexscripts/fonts/GlyphPositioningTable.java +++ b/src/java/org/apache/fop/complexscripts/fonts/GlyphPositioningTable.java @@ -1783,9 +1783,9 @@ public class GlyphPositioningTable extends GlyphTable { * Find device adjustment. * @param fontSize the font size to search for * @return an adjustment if font size matches an entry - * @asf.todo at present, assumes that 1 device unit equals one point */ public int findAdjustment ( int fontSize ) { + // [TODO] at present, assumes that 1 device unit equals one point int fs = fontSize / 1000; if ( fs < startSize ) { return 0; diff --git a/src/java/org/apache/fop/complexscripts/scripts/IndicScriptProcessor.java b/src/java/org/apache/fop/complexscripts/scripts/IndicScriptProcessor.java index ce4585828..26249bc22 100644 --- a/src/java/org/apache/fop/complexscripts/scripts/IndicScriptProcessor.java +++ b/src/java/org/apache/fop/complexscripts/scripts/IndicScriptProcessor.java @@ -360,7 +360,7 @@ public class IndicScriptProcessor extends DefaultScriptProcessor { } /** Abstract syllabizer. */ - protected abstract static class Syllabizer { + protected abstract static class Syllabizer implements Comparable { private String script; private String language; Syllabizer ( String script, String language ) { diff --git a/src/java/org/apache/fop/fo/FOEventHandler.java b/src/java/org/apache/fop/fo/FOEventHandler.java index 743708b72..11b6d4a2f 100644 --- a/src/java/org/apache/fop/fo/FOEventHandler.java +++ b/src/java/org/apache/fop/fo/FOEventHandler.java @@ -123,11 +123,17 @@ public abstract class FOEventHandler { public void endDocument() throws SAXException { } - /** {@inheritDoc} */ + /** + * Called upon start of root element. + * @param root element + */ public void startRoot(Root root) { } - /** {@inheritDoc} */ + /** + * Called upon end of root element. + * @param root element + */ public void endRoot(Root root) { } @@ -413,9 +419,9 @@ public abstract class FOEventHandler { /** * Process end of a Static. - * @param statisContent StaticContent that is ending + * @param staticContent StaticContent that is ending */ - public void endStatic(StaticContent statisContent) { + public void endStatic(StaticContent staticContent) { } diff --git a/src/java/org/apache/fop/layoutmgr/BalancingColumnBreakingAlgorithm.java b/src/java/org/apache/fop/layoutmgr/BalancingColumnBreakingAlgorithm.java index 2bcdb6127..03c159843 100644 --- a/src/java/org/apache/fop/layoutmgr/BalancingColumnBreakingAlgorithm.java +++ b/src/java/org/apache/fop/layoutmgr/BalancingColumnBreakingAlgorithm.java @@ -41,12 +41,16 @@ public class BalancingColumnBreakingAlgorithm extends PageBreakingAlgorithm { * @param topLevelLM the top level layout manager * @param pageProvider the page provider * @param layoutListener the layout listener - * @param alignment alignment of the paragraph/page. One of {@link Constants#EN_START}, - * {@link Constants#EN_JUSTIFY}, {@link Constants#EN_CENTER}, - * {@link Constants#EN_END}. - * For pages, {@link Constants#EN_BEFORE} and {@link Constants#EN_AFTER} - * are mapped to the corresponding inline properties, - * {@link Constants#EN_START} and {@link Constants#EN_END}. + * @param alignment alignment of the paragraph/page. One of + * {@link org.apache.fop.fo.Constants#EN_START}, + * {@link org.apache.fop.fo.Constants#EN_JUSTIFY}, + * {@link org.apache.fop.fo.Constants#EN_CENTER}, + * {@link org.apache.fop.fo.Constants#EN_END}. + * For pages, {@link org.apache.fop.fo.Constants#EN_BEFORE} and + * {@link org.apache.fop.fo.Constants#EN_AFTER} + * are mapped to the corresponding inline properties, + * {@link org.apache.fop.fo.Constants#EN_START} and + * {@link org.apache.fop.fo.Constants#EN_END}. * @param alignmentLast alignment of the paragraph's last line * @param footnoteSeparatorLength length of footnote separator * @param partOverflowRecovery {@code true} if too long elements should be moved to diff --git a/src/java/org/apache/fop/layoutmgr/BreakElement.java b/src/java/org/apache/fop/layoutmgr/BreakElement.java index 1c89c2009..77e7f140b 100644 --- a/src/java/org/apache/fop/layoutmgr/BreakElement.java +++ b/src/java/org/apache/fop/layoutmgr/BreakElement.java @@ -46,8 +46,11 @@ public class BreakElement extends UnresolvedListElement { * Create a new BreakElement for the given {@code position}, {@code penaltyValue} * and {@code breakClass}. (Used principally to generate break-possibilities in * ranges of content that must be kept together within the context corresponding - * to the {@code breakClass}; expected to be one of {@link Constants#EN_AUTO}, - * {@link Constants#EN_LINE}, {@link Constants#EN_COLUMN} or {@link Constants#EN_PAGE}) + * to the {@code breakClass}; expected to be one of + * {@link org.apache.fop.fo.Constants#EN_AUTO}, + * {@link org.apache.fop.fo.Constants#EN_LINE}, + * {@link org.apache.fop.fo.Constants#EN_COLUMN} or + * {@link org.apache.fop.fo.Constants#EN_PAGE}) * @param position the corresponding {@link Position} * @param penaltyValue the penalty value * @param breakClass the break class @@ -64,9 +67,12 @@ public class BreakElement extends UnresolvedListElement { * @param position the Position instance needed by the addAreas stage of the LMs. * @param penaltyWidth the penalty width * @param penaltyValue the penalty value for the penalty element to be constructed - * @param breakClass the break class of this penalty (one of {@link Constants#EN_AUTO}, - * {@link Constants#EN_COLUMN}, {@link Constants#EN_PAGE}, - * {@link Constants#EN_EVEN_PAGE}, {@link Constants#EN_ODD_PAGE}) + * @param breakClass the break class of this penalty (one of + * {@link org.apache.fop.fo.Constants#EN_AUTO}, + * {@link org.apache.fop.fo.Constants#EN_COLUMN}, + * {@link org.apache.fop.fo.Constants#EN_PAGE}, + * {@link org.apache.fop.fo.Constants#EN_EVEN_PAGE}, + * {@link org.apache.fop.fo.Constants#EN_ODD_PAGE}) * @param context the layout context which contains the pending conditional elements */ public BreakElement(Position position, int penaltyWidth, int penaltyValue, @@ -120,9 +126,12 @@ public class BreakElement extends UnresolvedListElement { /** * Returns the break class of this penalty. * - * @return one of {@link Constants#EN_AUTO}, {@link Constants#EN_COLUMN}, - * {@link Constants#EN_PAGE}, {@link Constants#EN_EVEN_PAGE}, - * {@link Constants#EN_ODD_PAGE} + * @return one of + * {@link org.apache.fop.fo.Constants#EN_AUTO}, + * {@link org.apache.fop.fo.Constants#EN_COLUMN}, + * {@link org.apache.fop.fo.Constants#EN_PAGE}, + * {@link org.apache.fop.fo.Constants#EN_EVEN_PAGE}, + * {@link org.apache.fop.fo.Constants#EN_ODD_PAGE}. */ public int getBreakClass() { return breakClass; @@ -131,9 +140,12 @@ public class BreakElement extends UnresolvedListElement { /** * Sets the break class. * - * @param breakClass one of {@link Constants#EN_AUTO}, {@link Constants#EN_COLUMN}, - * {@link Constants#EN_PAGE}, {@link Constants#EN_EVEN_PAGE}, - * {@link Constants#EN_ODD_PAGE} + * @param breakClass one of + * {@link org.apache.fop.fo.Constants#EN_AUTO}, + * {@link org.apache.fop.fo.Constants#EN_COLUMN}, + * {@link org.apache.fop.fo.Constants#EN_PAGE}, + * {@link org.apache.fop.fo.Constants#EN_EVEN_PAGE}, + * {@link org.apache.fop.fo.Constants#EN_ODD_PAGE}. */ public void setBreakClass(int breakClass) { this.breakClass = breakClass; diff --git a/src/java/org/apache/fop/layoutmgr/KnuthPenalty.java b/src/java/org/apache/fop/layoutmgr/KnuthPenalty.java index 2d4e1f2be..220f9c35d 100644 --- a/src/java/org/apache/fop/layoutmgr/KnuthPenalty.java +++ b/src/java/org/apache/fop/layoutmgr/KnuthPenalty.java @@ -72,8 +72,11 @@ public class KnuthPenalty extends KnuthElement { * @param penalty the penalty value of this penalty * @param penaltyFlagged is this penalty flagged? * @param breakClass the break class of this penalty (one of - * {@link Constants#EN_AUTO}, {@link Constants#EN_COLUMN}, {@link Constants#EN_PAGE}, - * {@link Constants#EN_EVEN_PAGE}, {@link Constants#EN_ODD_PAGE}) + * {@link org.apache.fop.fo.Constants#EN_AUTO}, + * {@link org.apache.fop.fo.Constants#EN_COLUMN}, + * {@link org.apache.fop.fo.Constants#EN_PAGE}, + * {@link org.apache.fop.fo.Constants#EN_EVEN_PAGE}, + * {@link org.apache.fop.fo.Constants#EN_ODD_PAGE}). * @param pos the Position stored in this penalty * @param isAuxiliary is this penalty auxiliary? */ diff --git a/src/java/org/apache/fop/pdf/PDFColor.java b/src/java/org/apache/fop/pdf/PDFColor.java index 8eea7e390..1fb544368 100644 --- a/src/java/org/apache/fop/pdf/PDFColor.java +++ b/src/java/org/apache/fop/pdf/PDFColor.java @@ -30,7 +30,7 @@ import org.apache.xmlgraphics.java2d.color.DeviceCMYKColorSpace; * image. And in this context, only RGB and Gray values are used. *

    * Use of this class is discouraged. {@link PDFColorHandler} is now used for in-content color - * selection. For masked bitmaps, it may be wiser to switch to {@link Color} in the long run. + * selection. For masked bitmaps, it may be wiser to switch to {@link java.awt.Color} in the long run. */ public class PDFColor extends PDFPathPaint { // could be 3.0 as well. diff --git a/src/java/org/apache/fop/pdf/PDFEmbeddedFile.java b/src/java/org/apache/fop/pdf/PDFEmbeddedFile.java index dc0681405..ae6893944 100644 --- a/src/java/org/apache/fop/pdf/PDFEmbeddedFile.java +++ b/src/java/org/apache/fop/pdf/PDFEmbeddedFile.java @@ -38,7 +38,10 @@ public class PDFEmbeddedFile extends PDFStream { put("Params", params); } - /** {@inheritDoc} */ + /** + * Determine if should encode on the fly. + * @return true if should encode on the fly + */ protected boolean isEncodingOnTheFly() { //Acrobat doesn't like an indirect /Length object in this case, //but only when the embedded file is a PDF file. diff --git a/src/java/org/apache/fop/pdf/PDFObject.java b/src/java/org/apache/fop/pdf/PDFObject.java index 1b9c4eea7..e0f950154 100644 --- a/src/java/org/apache/fop/pdf/PDFObject.java +++ b/src/java/org/apache/fop/pdf/PDFObject.java @@ -22,7 +22,6 @@ package org.apache.fop.pdf; // Java import java.io.IOException; import java.io.OutputStream; -import java.io.Writer; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -210,11 +209,6 @@ public abstract class PDFObject implements PDFWritable { return pdf.length; } - /** {@inheritDoc} */ - public void outputInline(OutputStream out, Writer writer) throws IOException { - throw new UnsupportedOperationException("Don't use anymore: " + getClass().getName()); - } - /** {@inheritDoc} */ public void outputInline(OutputStream out, StringBuilder textBuffer) throws IOException { if (hasObjectNumber()) { diff --git a/src/java/org/apache/fop/render/ImageHandler.java b/src/java/org/apache/fop/render/ImageHandler.java index fe6952de1..190d7c5d6 100644 --- a/src/java/org/apache/fop/render/ImageHandler.java +++ b/src/java/org/apache/fop/render/ImageHandler.java @@ -33,7 +33,8 @@ public interface ImageHandler extends ImageHandlerBase { * Indicates whether the image handler is compatible with the indicated target represented * by the rendering context object and with the image to be processed. The image is also * passed as a parameter because a handler might not support every subtype of image that is - * presented. For example: in the case of {@link ImageXMLDOM}, the image might carry an SVG + * presented. For example: in the case of + * {@link org.apache.xmlgraphics.image.loader.impl.ImageXMLDOM}, the image might carry an SVG * or some other XML format. One handler might only handle SVG but no other XML format. * @param targetContext the target rendering context * @param image the image to be processed (or null if only to check based on the rendering diff --git a/src/java/org/apache/fop/render/afp/AFPDocumentHandler.java b/src/java/org/apache/fop/render/afp/AFPDocumentHandler.java index 7823a2ce6..2ae95dd4c 100644 --- a/src/java/org/apache/fop/render/afp/AFPDocumentHandler.java +++ b/src/java/org/apache/fop/render/afp/AFPDocumentHandler.java @@ -58,7 +58,8 @@ import org.apache.fop.render.intermediate.IFException; import org.apache.fop.render.intermediate.IFPainter; /** - * {@link IFDocumentHandler} implementation that produces AFP (MO:DCA). + * {@link org.apache.fop.render.intermediate.IFDocumentHandler} implementation that + * produces AFP (MO:DCA). */ public class AFPDocumentHandler extends AbstractBinaryWritingIFDocumentHandler implements AFPCustomizable { diff --git a/src/java/org/apache/fop/render/afp/extensions/AFPIncludeFormMap.java b/src/java/org/apache/fop/render/afp/extensions/AFPIncludeFormMap.java index 842456f69..824ecbabb 100644 --- a/src/java/org/apache/fop/render/afp/extensions/AFPIncludeFormMap.java +++ b/src/java/org/apache/fop/render/afp/extensions/AFPIncludeFormMap.java @@ -27,7 +27,7 @@ import org.xml.sax.helpers.AttributesImpl; /** * This extension allows to include an AFP form map resource. It is implemented as an extension - * attachment ({@link ExtensionAttachment}). + * attachment ({@link org.apache.fop.fo.extensions.ExtensionAttachment}). */ public class AFPIncludeFormMap extends AFPExtensionAttachment { diff --git a/src/java/org/apache/fop/render/afp/extensions/AFPIncludeFormMapElement.java b/src/java/org/apache/fop/render/afp/extensions/AFPIncludeFormMapElement.java index 37f818f64..c5079b2bd 100644 --- a/src/java/org/apache/fop/render/afp/extensions/AFPIncludeFormMapElement.java +++ b/src/java/org/apache/fop/render/afp/extensions/AFPIncludeFormMapElement.java @@ -32,8 +32,8 @@ import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.extensions.ExtensionAttachment; /** - * This class extends the {@link ExtensionObj} class. It represents the "include-form-map" - * extension in the FO tree. + * This class extends the {@link org.apache.fop.fo.extensions.ExtensionObj} class. + * It represents the "include-form-map" extension in the FO tree. */ public class AFPIncludeFormMapElement extends AbstractAFPExtensionObject { diff --git a/src/java/org/apache/fop/render/afp/extensions/AFPPageOverlay.java b/src/java/org/apache/fop/render/afp/extensions/AFPPageOverlay.java index 0900d40b4..1e6aee7d5 100644 --- a/src/java/org/apache/fop/render/afp/extensions/AFPPageOverlay.java +++ b/src/java/org/apache/fop/render/afp/extensions/AFPPageOverlay.java @@ -25,7 +25,7 @@ import org.xml.sax.helpers.AttributesImpl; /** * This extension allows to include an AFP Page Overlay resource. It is implemented as an extension - * attachment ({@link ExtensionAttachment}). + * attachment ({@link org.apache.fop.fo.extensions.ExtensionAttachment}). */ public class AFPPageOverlay extends AFPExtensionAttachment { diff --git a/src/java/org/apache/fop/render/bitmap/AbstractBitmapDocumentHandler.java b/src/java/org/apache/fop/render/bitmap/AbstractBitmapDocumentHandler.java index c98c05a8e..0c6ebde56 100644 --- a/src/java/org/apache/fop/render/bitmap/AbstractBitmapDocumentHandler.java +++ b/src/java/org/apache/fop/render/bitmap/AbstractBitmapDocumentHandler.java @@ -47,7 +47,8 @@ import org.apache.fop.render.java2d.Java2DPainter; import org.apache.fop.render.java2d.Java2DUtil; /** - * Abstract {@link IFDocumentHandler} implementation for producing bitmap images. + * Abstract {@link org.apache.fop.render.intermediate.IFDocumentHandler} implementation + * for producing bitmap images. */ public abstract class AbstractBitmapDocumentHandler extends AbstractBinaryWritingIFDocumentHandler { diff --git a/src/java/org/apache/fop/render/bitmap/PNGDocumentHandler.java b/src/java/org/apache/fop/render/bitmap/PNGDocumentHandler.java index 05c44a1a6..ed92b852f 100644 --- a/src/java/org/apache/fop/render/bitmap/PNGDocumentHandler.java +++ b/src/java/org/apache/fop/render/bitmap/PNGDocumentHandler.java @@ -23,7 +23,8 @@ import org.apache.fop.apps.MimeConstants; import org.apache.fop.render.intermediate.IFDocumentHandlerConfigurator; /** - * {@link IFDocumentHandler} implementation that produces PNG files. + * {@link org.apache.fop.render.intermediate.IFDocumentHandler} implementation + * that produces PNG files. */ public class PNGDocumentHandler extends AbstractBitmapDocumentHandler { diff --git a/src/java/org/apache/fop/render/bitmap/TIFFDocumentHandler.java b/src/java/org/apache/fop/render/bitmap/TIFFDocumentHandler.java index 4b7fa3c2d..1c9a39bbe 100644 --- a/src/java/org/apache/fop/render/bitmap/TIFFDocumentHandler.java +++ b/src/java/org/apache/fop/render/bitmap/TIFFDocumentHandler.java @@ -23,7 +23,8 @@ import org.apache.fop.apps.MimeConstants; import org.apache.fop.render.intermediate.IFDocumentHandlerConfigurator; /** - * {@link IFDocumentHandler} implementation that produces TIFF files. + * {@link org.apache.fop.render.intermediate.IFDocumentHandler} implementation + * that produces TIFF files. */ public class TIFFDocumentHandler extends AbstractBitmapDocumentHandler { diff --git a/src/java/org/apache/fop/render/intermediate/IFContext.java b/src/java/org/apache/fop/render/intermediate/IFContext.java index c59a02ba8..681b996e4 100644 --- a/src/java/org/apache/fop/render/intermediate/IFContext.java +++ b/src/java/org/apache/fop/render/intermediate/IFContext.java @@ -145,7 +145,7 @@ public class IFContext { /** * Resets the current structure tree element. - * @see #setStructureTreeElement(String) + * @see #setStructureTreeElement(StructureTreeElement) */ public void resetStructureTreeElement() { setStructureTreeElement(null); @@ -154,7 +154,7 @@ public class IFContext { /** * Returns the current structure tree element. * @return the structure tree element (or null if no element is active) - * @see #setStructureTreeElement(String) + * @see #setStructureTreeElement(StructureTreeElement) */ public StructureTreeElement getStructureTreeElement() { return this.structureTreeElement; diff --git a/src/java/org/apache/fop/render/intermediate/IFUtil.java b/src/java/org/apache/fop/render/intermediate/IFUtil.java index e8651a3df..c4f681936 100644 --- a/src/java/org/apache/fop/render/intermediate/IFUtil.java +++ b/src/java/org/apache/fop/render/intermediate/IFUtil.java @@ -147,8 +147,8 @@ public final class IFUtil { /** * Sets up the fonts on a document handler. If the document handler provides a configurator - * object the configuration from the {@link FopFactory} will be used. Otherwise, - * a default font configuration will be set up. + * object the configuration from the {@link org.apache.fop.apps.FopFactory} will be used. + * Otherwise, a default font configuration will be set up. * @param documentHandler the document handler * @param fontInfo the font info object (may be null) * @throws FOPException if an error occurs while setting up the fonts @@ -175,8 +175,8 @@ public final class IFUtil { /** * Sets up the fonts on a document handler. If the document handler provides a configurator - * object the configuration from the {@link FopFactory} will be used. Otherwise, - * a default font configuration will be set up. + * object the configuration from the {@link org.apache.fop.apps.FopFactory} will be used. + * Otherwise, a default font configuration will be set up. * @param documentHandler the document handler * @throws FOPException if an error occurs while setting up the fonts */ diff --git a/src/java/org/apache/fop/render/java2d/CustomFontMetricsMapper.java b/src/java/org/apache/fop/render/java2d/CustomFontMetricsMapper.java index 5d964cbbf..36df00f20 100644 --- a/src/java/org/apache/fop/render/java2d/CustomFontMetricsMapper.java +++ b/src/java/org/apache/fop/render/java2d/CustomFontMetricsMapper.java @@ -36,7 +36,7 @@ import org.apache.fop.fonts.Typeface; /** * FontMetricsMapper that delegates most methods to an underlying - * {@link FontMetrics} instance. This class was designed to allow + * {@link org.apache.fop.fonts.FontMetrics} instance. This class was designed to allow * the underlying {@link Font} to be loaded from a * user-configured file not registered in the current graphics environment. */ diff --git a/src/java/org/apache/fop/render/java2d/Java2DPainter.java b/src/java/org/apache/fop/render/java2d/Java2DPainter.java index dd830a15b..575242d38 100644 --- a/src/java/org/apache/fop/render/java2d/Java2DPainter.java +++ b/src/java/org/apache/fop/render/java2d/Java2DPainter.java @@ -47,7 +47,8 @@ import org.apache.fop.traits.RuleStyle; import org.apache.fop.util.CharUtilities; /** - * {@link IFPainter} implementation that paints on a Graphics2D instance. + * {@link org.apache.fop.render.intermediate.IFPainter} implementation + * that paints on a Graphics2D instance. */ public class Java2DPainter extends AbstractIFPainter { diff --git a/src/java/org/apache/fop/render/pcl/PCLDocumentHandler.java b/src/java/org/apache/fop/render/pcl/PCLDocumentHandler.java index 52e522c7a..332b4a77d 100644 --- a/src/java/org/apache/fop/render/pcl/PCLDocumentHandler.java +++ b/src/java/org/apache/fop/render/pcl/PCLDocumentHandler.java @@ -45,7 +45,8 @@ import org.apache.fop.render.java2d.Java2DUtil; import org.apache.fop.render.pcl.extensions.PCLElementMapping; /** - * {@link IFDocumentHandler} implementation that produces PCL 5. + * {@link org.apache.fop.render.intermediate.IFDocumentHandler} implementation + * that produces PCL 5. */ public class PCLDocumentHandler extends AbstractBinaryWritingIFDocumentHandler implements PCLConstants { diff --git a/src/java/org/apache/fop/render/pcl/PCLPainter.java b/src/java/org/apache/fop/render/pcl/PCLPainter.java index 9fc575456..0d630826c 100644 --- a/src/java/org/apache/fop/render/pcl/PCLPainter.java +++ b/src/java/org/apache/fop/render/pcl/PCLPainter.java @@ -58,7 +58,8 @@ import org.apache.fop.traits.RuleStyle; import org.apache.fop.util.CharUtilities; /** - * {@link IFPainter} implementation that produces PCL 5. + * {@link org.apache.fop.render.intermediate.IFPainter} implementation + * that produces PCL 5. */ public class PCLPainter extends AbstractIFPainter implements PCLConstants { diff --git a/src/java/org/apache/fop/render/ps/NativeTextHandler.java b/src/java/org/apache/fop/render/ps/NativeTextHandler.java index 33adcb8d7..e8f123dc5 100644 --- a/src/java/org/apache/fop/render/ps/NativeTextHandler.java +++ b/src/java/org/apache/fop/render/ps/NativeTextHandler.java @@ -100,12 +100,6 @@ public class NativeTextHandler implements PSTextHandler { //nop } - /** {@inheritDoc} */ - public void drawString(String text, float x, float y) throws IOException { - // TODO Remove me after removing the deprecated method in TextHandler. - throw new UnsupportedOperationException("Deprecated method!"); - } - /** * Draw a string to the PostScript document. The text is painted using * text operations. diff --git a/src/java/org/apache/fop/render/ps/PSDocumentHandler.java b/src/java/org/apache/fop/render/ps/PSDocumentHandler.java index 95647d820..dc785ea18 100644 --- a/src/java/org/apache/fop/render/ps/PSDocumentHandler.java +++ b/src/java/org/apache/fop/render/ps/PSDocumentHandler.java @@ -63,7 +63,8 @@ import org.apache.fop.render.ps.extensions.PSSetPageDevice; import org.apache.fop.render.ps.extensions.PSSetupCode; /** - * {@link IFDocumentHandler} implementation that produces PostScript. + * {@link org.apache.fop.render.intermediate.IFDocumentHandler} implementation + * that produces PostScript. */ public class PSDocumentHandler extends AbstractBinaryWritingIFDocumentHandler { diff --git a/src/java/org/apache/fop/svg/PDFAElementBridge.java b/src/java/org/apache/fop/svg/PDFAElementBridge.java index cd70bed34..c2a481af9 100644 --- a/src/java/org/apache/fop/svg/PDFAElementBridge.java +++ b/src/java/org/apache/fop/svg/PDFAElementBridge.java @@ -64,7 +64,7 @@ public class PDFAElementBridge extends AbstractGraphicsNodeBridge { } /** - * Creates a {@link CompositeGraphicsNode}. + * Creates a {@link org.apache.batik.gvt.CompositeGraphicsNode}. * @return a new PDFANode */ protected GraphicsNode instantiateGraphicsNode() { diff --git a/src/java/org/apache/fop/traits/MinOptMax.java b/src/java/org/apache/fop/traits/MinOptMax.java index 022f3c214..84fb0156a 100644 --- a/src/java/org/apache/fop/traits/MinOptMax.java +++ b/src/java/org/apache/fop/traits/MinOptMax.java @@ -22,8 +22,9 @@ package org.apache.fop.traits; import java.io.Serializable; /** - * This class holds the resolved (as mpoints) form of a {@link LengthRangeProperty LengthRange} or - * {@link SpaceProperty Space} type property value. + * This class holds the resolved (as mpoints) form of a + * {@link org.apache.fop.fo.properties.LengthRangeProperty} or + * {@link org.apache.fop.fo.properties.SpaceProperty} type property value. *

    * Instances of this class are immutable. All arithmetic methods like {@link #plus(MinOptMax) plus}, * {@link #minus(MinOptMax) minus} or {@link #mult(int) mult} return a different instance. So it is diff --git a/src/java/org/apache/fop/traits/TraitEnum.java b/src/java/org/apache/fop/traits/TraitEnum.java index 18fdffaab..0d664a6df 100644 --- a/src/java/org/apache/fop/traits/TraitEnum.java +++ b/src/java/org/apache/fop/traits/TraitEnum.java @@ -30,7 +30,7 @@ public abstract class TraitEnum implements Serializable { /** * Constructor to add a new named item. * @param name Name of the item. - * @param enumValue the {@link Constants}.EN_* value + * @param enumValue the {@link org.apache.fop.fo.Constants}.EN_* value */ protected TraitEnum(String name, int enumValue) { this.name = name; @@ -46,7 +46,7 @@ public abstract class TraitEnum implements Serializable { } /** - * Returns the enumeration value (one of {@link Constants}.EN_*). + * Returns the enumeration value (one of {@link org.apache.fop.fo.Constants}.EN_*). * @return the enumeration value */ public int getEnumValue() { diff --git a/src/java/org/apache/fop/util/ColorExt.java b/src/java/org/apache/fop/util/ColorExt.java index d0ac6767c..f92e7c2a6 100644 --- a/src/java/org/apache/fop/util/ColorExt.java +++ b/src/java/org/apache/fop/util/ColorExt.java @@ -28,7 +28,7 @@ import java.util.Arrays; *

    * This class extends java.awt.Color class keeping track of the original color * property values specified by the fo user in a rgb-icc call. - * @deprecated Replaced by {@link ColorWithAlternatives} + * @deprecated Replaced by {@link org.apache.xmlgraphics.java2d.color.ColorWithAlternatives} */ @Deprecated public final class ColorExt extends Color { diff --git a/src/sandbox/org/apache/fop/render/mif/MIFHandler.java b/src/sandbox/org/apache/fop/render/mif/MIFHandler.java index cfc86edc7..5ef4c0940 100644 --- a/src/sandbox/org/apache/fop/render/mif/MIFHandler.java +++ b/src/sandbox/org/apache/fop/render/mif/MIFHandler.java @@ -29,8 +29,10 @@ import org.apache.commons.logging.LogFactory; import org.apache.fop.apps.FOUserAgent; import org.apache.fop.fo.FOEventHandler; +import org.apache.fop.fo.FOText; import org.apache.fop.fo.flow.BasicLink; import org.apache.fop.fo.flow.Block; +import org.apache.fop.fo.flow.Character; import org.apache.fop.fo.flow.ExternalGraphic; import org.apache.fop.fo.flow.Footnote; import org.apache.fop.fo.flow.FootnoteBody; @@ -39,6 +41,8 @@ import org.apache.fop.fo.flow.InstreamForeignObject; import org.apache.fop.fo.flow.Leader; import org.apache.fop.fo.flow.ListBlock; import org.apache.fop.fo.flow.ListItem; +import org.apache.fop.fo.flow.ListItemBody; +import org.apache.fop.fo.flow.ListItemLabel; import org.apache.fop.fo.flow.PageNumber; import org.apache.fop.fo.flow.table.Table; import org.apache.fop.fo.flow.table.TableBody; @@ -51,6 +55,7 @@ import org.apache.fop.fo.pagination.Flow; import org.apache.fop.fo.pagination.PageSequence; import org.apache.fop.fo.pagination.PageSequenceMaster; import org.apache.fop.fo.pagination.SimplePageMaster; +import org.apache.fop.fo.pagination.StaticContent; import org.apache.fop.fonts.FontSetup; import org.apache.fop.render.DefaultFontResolver; @@ -267,27 +272,27 @@ public class MIFHandler extends FOEventHandler { } /** {@inheritDoc} */ - public void startListLabel() { + public void startListLabel(ListItemLabel listItemLabel) { } /** {@inheritDoc} */ - public void endListLabel() { + public void endListLabel(ListItemLabel listItemLabel) { } /** {@inheritDoc} */ - public void startListBody() { + public void startListBody(ListItemBody listItemBody) { } /** {@inheritDoc} */ - public void endListBody() { + public void endListBody(ListItemBody listItemBody) { } /** {@inheritDoc} */ - public void startStatic() { + public void startStatic(StaticContent staticContent) { } /** {@inheritDoc} */ - public void endStatic() { + public void endStatic(StaticContent staticContent) { } /** {@inheritDoc} */ @@ -303,7 +308,7 @@ public class MIFHandler extends FOEventHandler { } /** {@inheritDoc} */ - public void endLink() { + public void endLink(BasicLink basicLink) { } /** {@inheritDoc} */ @@ -315,7 +320,11 @@ public class MIFHandler extends FOEventHandler { } /** {@inheritDoc} */ - public void foreignObject(InstreamForeignObject ifo) { + public void startInstreamForeignObject(InstreamForeignObject ifo) { + } + + /** {@inheritDoc} */ + public void endInstreamForeignObject(InstreamForeignObject ifo) { } /** {@inheritDoc} */ @@ -335,19 +344,37 @@ public class MIFHandler extends FOEventHandler { } /** {@inheritDoc} */ - public void leader(Leader l) { + public void startLeader(Leader l) { + } + + /** {@inheritDoc} */ + public void endLeader(Leader l) { + } + + public void character(Character c) { + appendCharacters ( new String ( new char[] {c.getCharacter()} ) ); + } + + /** {@inheritDoc} */ + public void characters(FOText foText) { + appendCharacters ( foText.getCharSequence().toString() ); + } + + /** {@inheritDoc} */ + public void startPageNumber(PageNumber pagenum) { } /** {@inheritDoc} */ - public void characters(char[] data, int start, int length) { + public void endPageNumber(PageNumber pagenum) { + } + + private void appendCharacters ( String str ) { if (para != null) { - String str = new String(data, start, length); str = str.trim(); // break into nice length chunks if (str.length() == 0) { return; } - MIFElement line = new MIFElement("ParaLine"); MIFElement prop = new MIFElement("TextRectID"); prop.setValue("2"); @@ -355,17 +382,8 @@ public class MIFHandler extends FOEventHandler { prop = new MIFElement("String"); prop.setValue("\"" + str + "\""); line.addElement(prop); - para.addElement(line); } } - - /** {@inheritDoc} */ - public void startPageNumber(PageNumber pagenum) { - } - - /** {@inheritDoc} */ - public void endPageNumber(PageNumber pagenum) { - } } diff --git a/src/sandbox/org/apache/fop/render/svg/SVGDocumentHandler.java b/src/sandbox/org/apache/fop/render/svg/SVGDocumentHandler.java index ef0d9f301..6fd4d3618 100644 --- a/src/sandbox/org/apache/fop/render/svg/SVGDocumentHandler.java +++ b/src/sandbox/org/apache/fop/render/svg/SVGDocumentHandler.java @@ -54,7 +54,8 @@ import org.apache.fop.util.GenerationHelperContentHandler; import org.apache.fop.util.XMLUtil; /** - * {@link IFDocumentHandler} implementation that writes SVG 1.1. + * {@link org.apache.fop.render.intermediate.IFDocumentHandler} implementation + * that writes SVG 1.1. */ public class SVGDocumentHandler extends AbstractSVGDocumentHandler { diff --git a/src/sandbox/org/apache/fop/render/svg/SVGPrintDocumentHandler.java b/src/sandbox/org/apache/fop/render/svg/SVGPrintDocumentHandler.java index 10be9588e..8ec374731 100644 --- a/src/sandbox/org/apache/fop/render/svg/SVGPrintDocumentHandler.java +++ b/src/sandbox/org/apache/fop/render/svg/SVGPrintDocumentHandler.java @@ -32,7 +32,8 @@ import org.apache.fop.render.intermediate.IFPainter; import org.apache.fop.util.XMLUtil; /** - * {@link IFDocumentHandler} implementation that writes SVG Print. + * {@link org.apache.fop.render.intermediate.IFDocumentHandler} implementation + * that writes SVG Print. */ public class SVGPrintDocumentHandler extends AbstractSVGDocumentHandler { diff --git a/status.xml b/status.xml index d6a04cd29..c632d3305 100644 --- a/status.xml +++ b/status.xml @@ -63,6 +63,9 @@ documents. Example: the fix of marks layering will be such a case when it's done. --> + + Eliminate javadocs warnings. + Update xmlgraphics common jar to reflect recent fixes in XGC. -- cgit v1.2.3