From 55fbf510250ace0c4891060934da0c6bc61beb96 Mon Sep 17 00:00:00 2001 From: Vincent Hennebert Date: Thu, 25 Nov 2010 21:04:09 +0000 Subject: Another go at removing all trailing whitespace git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@1039179 13f79535-47bb-0310-9956-ffa450edef68 --- src/sandbox/org/apache/fop/render/mif/RefElement.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/sandbox/org/apache/fop/render/mif') diff --git a/src/sandbox/org/apache/fop/render/mif/RefElement.java b/src/sandbox/org/apache/fop/render/mif/RefElement.java index b23dffa2b..0849f4f69 100644 --- a/src/sandbox/org/apache/fop/render/mif/RefElement.java +++ b/src/sandbox/org/apache/fop/render/mif/RefElement.java @@ -38,7 +38,7 @@ public class RefElement extends MIFElement { super(name); } - /** + /** * @param key a key * @return an mif element */ -- 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/sandbox/org/apache/fop/render/mif') 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 2ed4c2e0346fe366c48ab12acc987f30c956a784 Mon Sep 17 00:00:00 2001 From: Glenn Adams Date: Sat, 3 Mar 2012 00:18:45 +0000 Subject: enable ImportOrder rule; fix violations git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@1296526 13f79535-47bb-0310-9956-ffa450edef68 --- checkstyle-5.5.xml | 4 +--- src/java/org/apache/fop/afp/fonts/CharacterSet.java | 1 + .../org/apache/fop/afp/modca/AbstractPageObject.java | 2 +- src/java/org/apache/fop/afp/ptoca/PtocaBuilder.java | 4 +++- .../org/apache/fop/afp/svg/AFPTextElementBridge.java | 1 + src/java/org/apache/fop/afp/util/DTDEntityResolver.java | 3 ++- src/java/org/apache/fop/area/Area.java | 1 + src/java/org/apache/fop/area/CTM.java | 2 +- src/java/org/apache/fop/area/LineArea.java | 2 +- src/java/org/apache/fop/area/LinkResolver.java | 3 +-- src/java/org/apache/fop/area/MainReference.java | 4 ++-- src/java/org/apache/fop/area/Page.java | 4 ++-- src/java/org/apache/fop/area/PageViewport.java | 6 +++--- src/java/org/apache/fop/area/RegionViewport.java | 4 ++-- src/java/org/apache/fop/area/Trait.java | 2 +- src/java/org/apache/fop/area/inline/Container.java | 6 +++--- src/java/org/apache/fop/area/inline/ForeignObject.java | 4 ++-- src/java/org/apache/fop/area/inline/InlineParent.java | 2 +- .../org/apache/fop/complexscripts/bidi/TextInterval.java | 2 +- .../apache/fop/complexscripts/fonts/GlyphClassTable.java | 2 +- .../fop/complexscripts/fonts/GlyphCoverageTable.java | 2 +- .../fop/complexscripts/fonts/GlyphMappingTable.java | 2 +- .../fop/complexscripts/fonts/GlyphPositioningTable.java | 2 +- .../fop/complexscripts/fonts/GlyphProcessingState.java | 2 +- .../org/apache/fop/complexscripts/fonts/GlyphTable.java | 2 +- .../org/apache/fop/complexscripts/util/CharScript.java | 2 +- src/java/org/apache/fop/datatypes/LengthBase.java | 1 + src/java/org/apache/fop/fo/ValidationException.java | 3 ++- src/java/org/apache/fop/fo/XMLObj.java | 3 +-- src/java/org/apache/fop/fo/XMLWhiteSpaceHandler.java | 1 + .../org/apache/fop/fo/expr/FromTableColumnFunction.java | 3 ++- src/java/org/apache/fop/fo/expr/Function.java | 2 +- src/java/org/apache/fop/fo/expr/LabelEndFunction.java | 2 +- src/java/org/apache/fop/fo/expr/NumericProperty.java | 2 +- src/java/org/apache/fop/fo/expr/RGBColorFunction.java | 2 +- .../org/apache/fop/fo/expr/RelativeNumericProperty.java | 2 +- src/java/org/apache/fop/fo/extensions/ExtensionObj.java | 6 +++--- .../fo/extensions/svg/BatikExtensionElementMapping.java | 5 ++++- .../apache/fop/fo/extensions/svg/SVGElementMapping.java | 13 ++++++++----- .../fop/fo/extensions/xmp/AbstractMetadataElement.java | 3 ++- .../org/apache/fop/fo/extensions/xmp/RDFElement.java | 3 ++- .../apache/fop/fo/extensions/xmp/RDFElementMapping.java | 7 ++++--- .../fop/fo/extensions/xmp/XMPContentHandlerFactory.java | 8 +++++--- .../apache/fop/fo/extensions/xmp/XMPElementMapping.java | 7 ++++--- .../org/apache/fop/fo/extensions/xmp/XMPMetaElement.java | 3 ++- .../org/apache/fop/fo/extensions/xmp/XMPMetadata.java | 8 +++++--- src/java/org/apache/fop/fo/flow/BlockContainer.java | 3 ++- src/java/org/apache/fop/fo/flow/RetrieveMarker.java | 5 +++-- src/java/org/apache/fop/fo/flow/RetrieveTableMarker.java | 7 ++++--- src/java/org/apache/fop/fo/flow/table/TableBody.java | 2 +- src/java/org/apache/fop/fo/pagination/ColorProfile.java | 4 ++-- .../apache/fop/fo/pagination/PageSequenceWrapper.java | 2 +- src/java/org/apache/fop/fo/pagination/RegionAfter.java | 6 ++---- src/java/org/apache/fop/fo/pagination/RegionBefore.java | 4 +--- src/java/org/apache/fop/fo/pagination/RegionEnd.java | 6 ++---- src/java/org/apache/fop/fo/pagination/RegionStart.java | 6 ++---- .../apache/fop/fo/properties/CommonTextDecoration.java | 4 ++-- src/java/org/apache/fop/fo/properties/PercentLength.java | 2 +- src/java/org/apache/fop/fo/properties/Property.java | 2 +- src/java/org/apache/fop/fo/properties/PropertyCache.java | 4 ++-- src/java/org/apache/fop/fo/properties/URIProperty.java | 6 +++--- .../org/apache/fop/fonts/FontManagerConfigurator.java | 1 + src/java/org/apache/fop/fonts/LazyFont.java | 4 ++-- src/java/org/apache/fop/fonts/Typeface.java | 1 + .../org/apache/fop/fonts/apps/AbstractFontReader.java | 1 + src/java/org/apache/fop/fonts/apps/TTFReader.java | 10 ++++++---- .../org/apache/fop/fonts/autodetect/FontInfoFinder.java | 1 + .../org/apache/fop/fonts/substitute/FontQualifier.java | 1 + .../apache/fop/fonts/substitute/FontSubstitutions.java | 1 + .../fonts/substitute/FontSubstitutionsConfigurator.java | 1 + src/java/org/apache/fop/fonts/truetype/TTFFile.java | 1 + .../org/apache/fop/fonts/truetype/TTFFontLoader.java | 4 +++- src/java/org/apache/fop/fonts/type1/PFBData.java | 2 +- src/java/org/apache/fop/fonts/type1/PFBParser.java | 5 ++--- src/java/org/apache/fop/fonts/type1/PFMInputStream.java | 2 +- src/java/org/apache/fop/hyphenation/Hyphenator.java | 3 ++- src/java/org/apache/fop/hyphenation/PatternParser.java | 16 +++++++--------- src/java/org/apache/fop/hyphenation/TernaryTree.java | 2 +- .../fop/image/loader/batik/ImageConverterSVG2G2D.java | 5 +++-- .../fop/image/loader/batik/ImageConverterWMF2G2D.java | 5 +++-- .../org/apache/fop/image/loader/batik/PreloaderSVG.java | 5 +++-- .../org/apache/fop/image/loader/batik/PreloaderWMF.java | 5 +++-- .../org/apache/fop/layoutmgr/AbstractLayoutManager.java | 3 ++- src/java/org/apache/fop/layoutmgr/KnuthSequence.java | 4 ++-- src/java/org/apache/fop/layoutmgr/LayoutException.java | 2 +- .../org/apache/fop/layoutmgr/LayoutManagerMaker.java | 5 +++-- src/java/org/apache/fop/layoutmgr/SpaceSpecifier.java | 3 ++- .../fop/layoutmgr/UnresolvedListElementWithLength.java | 1 + .../fop/layoutmgr/inline/FootnoteLayoutManager.java | 1 + .../fop/layoutmgr/inline/LeafNodeLayoutManager.java | 3 ++- .../apache/fop/layoutmgr/inline/TextLayoutManager.java | 2 +- .../fop/layoutmgr/inline/WrapperLayoutManager.java | 2 +- .../fop/layoutmgr/list/ListItemContentLayoutManager.java | 2 +- .../fop/layoutmgr/table/RowGroupLayoutManager.java | 1 + src/java/org/apache/fop/pdf/ASCII85Filter.java | 2 +- src/java/org/apache/fop/pdf/ASCIIHexFilter.java | 2 +- src/java/org/apache/fop/pdf/InMemoryStreamCache.java | 2 +- src/java/org/apache/fop/pdf/PDFCharProcs.java | 2 +- src/java/org/apache/fop/pdf/PDFFilter.java | 2 +- src/java/org/apache/fop/pdf/PDFGState.java | 2 +- src/java/org/apache/fop/pdf/PDFInfo.java | 2 +- src/java/org/apache/fop/pdf/PDFPages.java | 3 +-- src/java/org/apache/fop/pdf/PDFPattern.java | 5 ++--- src/java/org/apache/fop/pdf/PDFResources.java | 1 + src/java/org/apache/fop/pdf/StreamCache.java | 2 +- src/java/org/apache/fop/pdf/TempFileStreamCache.java | 6 ++---- src/java/org/apache/fop/render/AbstractConfigurator.java | 2 ++ .../org/apache/fop/render/XMLHandlerConfigurator.java | 2 ++ .../org/apache/fop/render/afp/AFPGraphics2DAdapter.java | 3 ++- src/java/org/apache/fop/render/afp/AFPInfo.java | 1 + src/java/org/apache/fop/render/afp/AFPPainter.java | 8 +++++--- .../org/apache/fop/render/afp/AFPRendererImageInfo.java | 3 ++- .../afp/extensions/AFPExtensionHandlerFactory.java | 3 ++- .../fop/render/afp/extensions/AFPPageOverlayElement.java | 7 ++++--- src/java/org/apache/fop/render/awt/viewer/Command.java | 4 ++-- .../org/apache/fop/render/awt/viewer/GoToPageDialog.java | 5 ++--- .../apache/fop/render/awt/viewer/ImageProxyPanel.java | 1 + .../fop/render/awt/viewer/PreviewDialogAboutBox.java | 8 +++----- .../org/apache/fop/render/awt/viewer/Translator.java | 3 +-- .../org/apache/fop/render/intermediate/IFRenderer.java | 3 ++- .../fop/render/java2d/InstalledFontCollection.java | 1 + .../fop/render/java2d/Java2DRendererConfigurator.java | 1 + .../org/apache/fop/render/java2d/Java2DSVGHandler.java | 5 +++-- .../org/apache/fop/render/pdf/PDFImageHandlerSVG.java | 5 +++-- src/java/org/apache/fop/render/ps/FontResourceCache.java | 3 ++- src/java/org/apache/fop/render/ps/PSFontUtils.java | 12 +++++++----- .../org/apache/fop/render/ps/PSGraphics2DAdapter.java | 2 +- .../apache/fop/render/ps/PSImageHandlerGraphics2D.java | 3 ++- src/java/org/apache/fop/render/ps/PSSVGHandler.java | 1 + .../render/ps/extensions/AbstractPSExtensionObject.java | 6 +++--- .../render/ps/extensions/PSExtensionElementMapping.java | 2 +- .../render/ps/extensions/PSExtensionHandlerFactory.java | 3 ++- src/java/org/apache/fop/render/rtf/FOPRtfAttributes.java | 1 + src/java/org/apache/fop/render/rtf/FoUnitsConverter.java | 3 ++- .../apache/fop/render/rtf/TableAttributesConverter.java | 2 +- .../apache/fop/render/rtf/rtflib/rtfdoc/RtfAfter.java | 2 +- .../fop/render/rtf/rtflib/rtfdoc/RtfAfterBeforeBase.java | 2 +- .../apache/fop/render/rtf/rtflib/rtfdoc/RtfBefore.java | 2 +- .../apache/fop/render/rtf/rtflib/rtfdoc/RtfBookmark.java | 2 +- .../rtf/rtflib/rtfdoc/RtfBookmarkContainerImpl.java | 2 +- .../fop/render/rtf/rtflib/rtfdoc/RtfColorTable.java | 4 ++-- .../fop/render/rtf/rtflib/rtfdoc/RtfContainer.java | 5 +++-- .../fop/render/rtf/rtflib/rtfdoc/RtfDocumentArea.java | 2 +- .../apache/fop/render/rtf/rtflib/rtfdoc/RtfElement.java | 3 +-- .../fop/render/rtf/rtflib/rtfdoc/RtfExtraRowSet.java | 8 ++++---- .../org/apache/fop/render/rtf/rtflib/rtfdoc/RtfFile.java | 7 ++++--- .../fop/render/rtf/rtflib/rtfdoc/RtfFontTable.java | 2 +- .../apache/fop/render/rtf/rtflib/rtfdoc/RtfFootnote.java | 3 +-- .../apache/fop/render/rtf/rtflib/rtfdoc/RtfHeader.java | 7 +++---- .../fop/render/rtf/rtflib/rtfdoc/RtfHyperLink.java | 2 +- .../apache/fop/render/rtf/rtflib/rtfdoc/RtfJforCmd.java | 2 +- .../fop/render/rtf/rtflib/rtfdoc/RtfLineBreak.java | 2 +- .../apache/fop/render/rtf/rtflib/rtfdoc/RtfListItem.java | 2 +- .../fop/render/rtf/rtflib/rtfdoc/RtfListTable.java | 7 +++---- .../org/apache/fop/render/rtf/rtflib/rtfdoc/RtfNull.java | 2 +- .../apache/fop/render/rtf/rtflib/rtfdoc/RtfPageArea.java | 2 +- .../fop/render/rtf/rtflib/rtfdoc/RtfPageBreak.java | 2 +- .../fop/render/rtf/rtflib/rtfdoc/RtfPageNumber.java | 2 +- .../fop/render/rtf/rtflib/rtfdoc/RtfParagraph.java | 2 +- .../rtf/rtflib/rtfdoc/RtfParagraphKeepTogether.java | 2 +- .../apache/fop/render/rtf/rtflib/rtfdoc/RtfSection.java | 2 +- .../fop/render/rtf/rtflib/rtfdoc/RtfStringConverter.java | 4 ++-- .../fop/render/rtf/rtflib/rtfdoc/RtfStyleSheetTable.java | 4 ++-- .../apache/fop/render/rtf/rtflib/tools/TableContext.java | 3 ++- .../apache/fop/render/txt/TXTRendererConfigurator.java | 1 + src/java/org/apache/fop/render/xml/XMLXMLHandler.java | 6 +++--- src/java/org/apache/fop/servlet/FopPrintServlet.java | 4 ++-- src/java/org/apache/fop/svg/ACIUtils.java | 9 +++++---- src/java/org/apache/fop/svg/AbstractFOPTextPainter.java | 5 +++-- src/java/org/apache/fop/svg/AbstractFOPTranscoder.java | 6 ++++-- src/java/org/apache/fop/svg/NativeTextPainter.java | 5 +++-- .../apache/fop/svg/PDFBatikFlowTextElementBridge.java | 1 + src/java/org/apache/fop/svg/PDFFlowExtTextPainter.java | 1 + src/java/org/apache/fop/svg/PDFFlowTextPainter.java | 1 + src/java/org/apache/fop/svg/PDFGraphicsDevice.java | 4 ++-- .../org/apache/fop/svg/PDFSVGFlowRootElementBridge.java | 1 + src/java/org/apache/fop/svg/PDFTranscoder.java | 1 + src/java/org/apache/fop/tools/TestConverter.java | 11 ++++++----- src/java/org/apache/fop/tools/anttasks/FileCompare.java | 8 ++++---- src/java/org/apache/fop/tools/anttasks/RunTest.java | 11 ++++------- src/java/org/apache/fop/util/ColorSpaceCache.java | 2 +- src/java/org/apache/fop/util/LogUtil.java | 1 + src/sandbox/org/apache/fop/render/mif/MIFHandler.java | 5 +++-- src/sandbox/org/apache/fop/render/svg/SVGRenderer.java | 7 ++++--- src/sandbox/org/apache/fop/render/svg/SVGSVGHandler.java | 14 ++++++++------ 185 files changed, 360 insertions(+), 292 deletions(-) (limited to 'src/sandbox/org/apache/fop/render/mif') diff --git a/checkstyle-5.5.xml b/checkstyle-5.5.xml index fd934eff3..a3acdb549 100644 --- a/checkstyle-5.5.xml +++ b/checkstyle-5.5.xml @@ -121,13 +121,11 @@ - diff --git a/src/java/org/apache/fop/afp/fonts/CharacterSet.java b/src/java/org/apache/fop/afp/fonts/CharacterSet.java index 738028fdf..341abde0b 100644 --- a/src/java/org/apache/fop/afp/fonts/CharacterSet.java +++ b/src/java/org/apache/fop/afp/fonts/CharacterSet.java @@ -26,6 +26,7 @@ import java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + import org.apache.fop.afp.AFPConstants; import org.apache.fop.afp.AFPEventProducer; import org.apache.fop.afp.fonts.CharactersetEncoder.EncodedChars; diff --git a/src/java/org/apache/fop/afp/modca/AbstractPageObject.java b/src/java/org/apache/fop/afp/modca/AbstractPageObject.java index 99afd322a..e8b8bc1df 100644 --- a/src/java/org/apache/fop/afp/modca/AbstractPageObject.java +++ b/src/java/org/apache/fop/afp/modca/AbstractPageObject.java @@ -27,8 +27,8 @@ import java.util.List; import org.apache.fop.afp.AFPLineDataInfo; import org.apache.fop.afp.Completable; import org.apache.fop.afp.Factory; -import org.apache.fop.afp.ptoca.PtocaProducer; import org.apache.fop.afp.fonts.AFPFont; +import org.apache.fop.afp.ptoca.PtocaProducer; /** * Pages contain the data objects that comprise a presentation document. Each diff --git a/src/java/org/apache/fop/afp/ptoca/PtocaBuilder.java b/src/java/org/apache/fop/afp/ptoca/PtocaBuilder.java index 059753338..1ea63c7f9 100644 --- a/src/java/org/apache/fop/afp/ptoca/PtocaBuilder.java +++ b/src/java/org/apache/fop/afp/ptoca/PtocaBuilder.java @@ -25,11 +25,13 @@ import java.io.IOException; import java.io.OutputStream; import org.apache.commons.io.output.ByteArrayOutputStream; -import org.apache.fop.afp.fonts.CharactersetEncoder.EncodedChars; + import org.apache.xmlgraphics.java2d.color.CIELabColorSpace; import org.apache.xmlgraphics.java2d.color.ColorUtil; import org.apache.xmlgraphics.java2d.color.ColorWithAlternatives; +import org.apache.fop.afp.fonts.CharactersetEncoder.EncodedChars; + /** * Generator class for PTOCA data structures. */ diff --git a/src/java/org/apache/fop/afp/svg/AFPTextElementBridge.java b/src/java/org/apache/fop/afp/svg/AFPTextElementBridge.java index 31aa3fe60..85bb78593 100644 --- a/src/java/org/apache/fop/afp/svg/AFPTextElementBridge.java +++ b/src/java/org/apache/fop/afp/svg/AFPTextElementBridge.java @@ -20,6 +20,7 @@ package org.apache.fop.afp.svg; import org.apache.batik.gvt.TextPainter; + import org.apache.fop.svg.AbstractFOPTextElementBridge; /** diff --git a/src/java/org/apache/fop/afp/util/DTDEntityResolver.java b/src/java/org/apache/fop/afp/util/DTDEntityResolver.java index b4eb7fc23..7ba061993 100644 --- a/src/java/org/apache/fop/afp/util/DTDEntityResolver.java +++ b/src/java/org/apache/fop/afp/util/DTDEntityResolver.java @@ -22,10 +22,11 @@ package org.apache.fop.afp.util; import java.io.IOException; import java.net.URL; -import org.apache.fop.afp.fonts.FontRuntimeException; import org.xml.sax.EntityResolver; import org.xml.sax.InputSource; +import org.apache.fop.afp.fonts.FontRuntimeException; + /** * An entity resolver for both DOM and SAX models of the SAX document. *

    diff --git a/src/java/org/apache/fop/area/Area.java b/src/java/org/apache/fop/area/Area.java index 435876d65..bdd886e2c 100644 --- a/src/java/org/apache/fop/area/Area.java +++ b/src/java/org/apache/fop/area/Area.java @@ -24,6 +24,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; diff --git a/src/java/org/apache/fop/area/CTM.java b/src/java/org/apache/fop/area/CTM.java index 4b6adb9dc..3979bce56 100644 --- a/src/java/org/apache/fop/area/CTM.java +++ b/src/java/org/apache/fop/area/CTM.java @@ -29,8 +29,8 @@ 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; +import static org.apache.fop.fo.Constants.EN_TB_RL; /** * Describe a PDF or PostScript style coordinate transformation matrix (CTM). diff --git a/src/java/org/apache/fop/area/LineArea.java b/src/java/org/apache/fop/area/LineArea.java index 1d3262487..ac5322f96 100644 --- a/src/java/org/apache/fop/area/LineArea.java +++ b/src/java/org/apache/fop/area/LineArea.java @@ -26,10 +26,10 @@ import java.util.List; import org.apache.fop.area.inline.InlineArea; -import static org.apache.fop.fo.Constants.EN_START; import static org.apache.fop.fo.Constants.EN_CENTER; import static org.apache.fop.fo.Constants.EN_END; import static org.apache.fop.fo.Constants.EN_JUSTIFY; +import static org.apache.fop.fo.Constants.EN_START; /** * The line area. diff --git a/src/java/org/apache/fop/area/LinkResolver.java b/src/java/org/apache/fop/area/LinkResolver.java index b458a1baf..1c711a18e 100644 --- a/src/java/org/apache/fop/area/LinkResolver.java +++ b/src/java/org/apache/fop/area/LinkResolver.java @@ -19,10 +19,9 @@ package org.apache.fop.area; -// Java +import java.io.Serializable; import java.util.ArrayList; import java.util.List; -import java.io.Serializable; /** * Link resolving for resolving internal links. diff --git a/src/java/org/apache/fop/area/MainReference.java b/src/java/org/apache/fop/area/MainReference.java index 154e9523c..13c92df9c 100644 --- a/src/java/org/apache/fop/area/MainReference.java +++ b/src/java/org/apache/fop/area/MainReference.java @@ -19,11 +19,11 @@ package org.apache.fop.area; -import org.apache.fop.traits.WritingModeTraitsGetter; - import java.util.ArrayList; import java.util.List; +import org.apache.fop.traits.WritingModeTraitsGetter; + /** * The main-reference-area generated by an fo:region-body * This object holds one or more span-reference-areas (block-areas diff --git a/src/java/org/apache/fop/area/Page.java b/src/java/org/apache/fop/area/Page.java index 3a08809dc..9bf670a0e 100644 --- a/src/java/org/apache/fop/area/Page.java +++ b/src/java/org/apache/fop/area/Page.java @@ -35,13 +35,13 @@ 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.EN_ERROR_IF_OVERFLOW; +import static org.apache.fop.fo.Constants.EN_HIDDEN; import static org.apache.fop.fo.Constants.FO_REGION_AFTER; import static org.apache.fop.fo.Constants.FO_REGION_BEFORE; import static org.apache.fop.fo.Constants.FO_REGION_BODY; import static org.apache.fop.fo.Constants.FO_REGION_END; import static org.apache.fop.fo.Constants.FO_REGION_START; -import static org.apache.fop.fo.Constants.EN_ERROR_IF_OVERFLOW; -import static org.apache.fop.fo.Constants.EN_HIDDEN; /** * The page. diff --git a/src/java/org/apache/fop/area/PageViewport.java b/src/java/org/apache/fop/area/PageViewport.java index f335fa128..9ec46a53d 100644 --- a/src/java/org/apache/fop/area/PageViewport.java +++ b/src/java/org/apache/fop/area/PageViewport.java @@ -36,11 +36,11 @@ 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; import static org.apache.fop.fo.Constants.EN_FIC; -import static org.apache.fop.fo.Constants.EN_LSWP; +import static org.apache.fop.fo.Constants.EN_FSWP; import static org.apache.fop.fo.Constants.EN_LEWP; +import static org.apache.fop.fo.Constants.EN_LSWP; +import static org.apache.fop.fo.Constants.FO_REGION_BODY; /** * Page viewport that specifies the viewport area and holds the page contents. diff --git a/src/java/org/apache/fop/area/RegionViewport.java b/src/java/org/apache/fop/area/RegionViewport.java index 0104b53ad..7eeadbffd 100644 --- a/src/java/org/apache/fop/area/RegionViewport.java +++ b/src/java/org/apache/fop/area/RegionViewport.java @@ -19,13 +19,13 @@ package org.apache.fop.area; -import org.apache.fop.traits.WritingModeTraitsGetter; - import java.awt.Rectangle; import java.awt.geom.Rectangle2D; import java.io.IOException; import java.util.HashMap; +import org.apache.fop.traits.WritingModeTraitsGetter; + /** * Region Viewport area. * This object represents the region-viewport-area. It has a diff --git a/src/java/org/apache/fop/area/Trait.java b/src/java/org/apache/fop/area/Trait.java index 9942a1370..65320fd48 100644 --- a/src/java/org/apache/fop/area/Trait.java +++ b/src/java/org/apache/fop/area/Trait.java @@ -30,10 +30,10 @@ 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_NOREPEAT; import static org.apache.fop.fo.Constants.EN_REPEAT; import static org.apache.fop.fo.Constants.EN_REPEATX; import static org.apache.fop.fo.Constants.EN_REPEATY; -import static org.apache.fop.fo.Constants.EN_NOREPEAT; // properties should be serialized by the holder /** diff --git a/src/java/org/apache/fop/area/inline/Container.java b/src/java/org/apache/fop/area/inline/Container.java index 9267b92d0..bc2acaa28 100644 --- a/src/java/org/apache/fop/area/inline/Container.java +++ b/src/java/org/apache/fop/area/inline/Container.java @@ -19,12 +19,12 @@ package org.apache.fop.area.inline; +import java.util.ArrayList; +import java.util.List; + import org.apache.fop.area.Area; import org.apache.fop.area.Block; -import java.util.List; -import java.util.ArrayList; - /** * Container area for inline container. * This area should be placed in a viewport as a result of the diff --git a/src/java/org/apache/fop/area/inline/ForeignObject.java b/src/java/org/apache/fop/area/inline/ForeignObject.java index 3c36b3195..cc0e0b0ad 100644 --- a/src/java/org/apache/fop/area/inline/ForeignObject.java +++ b/src/java/org/apache/fop/area/inline/ForeignObject.java @@ -19,10 +19,10 @@ package org.apache.fop.area.inline; -import org.apache.fop.area.Area; - import org.w3c.dom.Document; +import org.apache.fop.area.Area; + // cacheable object /** * Foreign object inline area. diff --git a/src/java/org/apache/fop/area/inline/InlineParent.java b/src/java/org/apache/fop/area/inline/InlineParent.java index 0e1f32dff..405d71a50 100644 --- a/src/java/org/apache/fop/area/inline/InlineParent.java +++ b/src/java/org/apache/fop/area/inline/InlineParent.java @@ -19,8 +19,8 @@ package org.apache.fop.area.inline; -import java.util.List; import java.util.Iterator; +import java.util.List; import org.apache.fop.area.Area; diff --git a/src/java/org/apache/fop/complexscripts/bidi/TextInterval.java b/src/java/org/apache/fop/complexscripts/bidi/TextInterval.java index 7d4ab105b..8249c4628 100644 --- a/src/java/org/apache/fop/complexscripts/bidi/TextInterval.java +++ b/src/java/org/apache/fop/complexscripts/bidi/TextInterval.java @@ -21,8 +21,8 @@ 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.AbstractPageNumberCitation; import org.apache.fop.fo.flow.BidiOverride; import org.apache.fop.fo.flow.Character; import org.apache.fop.fo.flow.Leader; diff --git a/src/java/org/apache/fop/complexscripts/fonts/GlyphClassTable.java b/src/java/org/apache/fop/complexscripts/fonts/GlyphClassTable.java index 02498af25..71aa206ba 100644 --- a/src/java/org/apache/fop/complexscripts/fonts/GlyphClassTable.java +++ b/src/java/org/apache/fop/complexscripts/fonts/GlyphClassTable.java @@ -19,8 +19,8 @@ package org.apache.fop.complexscripts.fonts; -import java.util.List; import java.util.Iterator; +import java.util.List; // CSOFF: LineLengthCheck // CSOFF: NoWhitespaceAfterCheck diff --git a/src/java/org/apache/fop/complexscripts/fonts/GlyphCoverageTable.java b/src/java/org/apache/fop/complexscripts/fonts/GlyphCoverageTable.java index dea92d8c1..f0e7e50da 100644 --- a/src/java/org/apache/fop/complexscripts/fonts/GlyphCoverageTable.java +++ b/src/java/org/apache/fop/complexscripts/fonts/GlyphCoverageTable.java @@ -20,8 +20,8 @@ package org.apache.fop.complexscripts.fonts; import java.util.Arrays; -import java.util.List; import java.util.Iterator; +import java.util.List; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/src/java/org/apache/fop/complexscripts/fonts/GlyphMappingTable.java b/src/java/org/apache/fop/complexscripts/fonts/GlyphMappingTable.java index e7d67ce6a..6c4b0bf37 100644 --- a/src/java/org/apache/fop/complexscripts/fonts/GlyphMappingTable.java +++ b/src/java/org/apache/fop/complexscripts/fonts/GlyphMappingTable.java @@ -20,8 +20,8 @@ package org.apache.fop.complexscripts.fonts; import java.util.Arrays; -import java.util.List; import java.util.Iterator; +import java.util.List; // CSOFF: NoWhitespaceAfterCheck // CSOFF: InnerAssignmentCheck diff --git a/src/java/org/apache/fop/complexscripts/fonts/GlyphPositioningTable.java b/src/java/org/apache/fop/complexscripts/fonts/GlyphPositioningTable.java index 01f78d2f2..07a0077bf 100644 --- a/src/java/org/apache/fop/complexscripts/fonts/GlyphPositioningTable.java +++ b/src/java/org/apache/fop/complexscripts/fonts/GlyphPositioningTable.java @@ -19,8 +19,8 @@ package org.apache.fop.complexscripts.fonts; -import java.util.Arrays; import java.util.ArrayList; +import java.util.Arrays; import java.util.Iterator; import java.util.List; import java.util.Map; diff --git a/src/java/org/apache/fop/complexscripts/fonts/GlyphProcessingState.java b/src/java/org/apache/fop/complexscripts/fonts/GlyphProcessingState.java index 4b04b1ca9..b40708e11 100644 --- a/src/java/org/apache/fop/complexscripts/fonts/GlyphProcessingState.java +++ b/src/java/org/apache/fop/complexscripts/fonts/GlyphProcessingState.java @@ -23,8 +23,8 @@ 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.GlyphSequence; import org.apache.fop.complexscripts.util.GlyphTester; import org.apache.fop.complexscripts.util.ScriptContextTester; diff --git a/src/java/org/apache/fop/complexscripts/fonts/GlyphTable.java b/src/java/org/apache/fop/complexscripts/fonts/GlyphTable.java index 1667e26f1..f95ee8778 100644 --- a/src/java/org/apache/fop/complexscripts/fonts/GlyphTable.java +++ b/src/java/org/apache/fop/complexscripts/fonts/GlyphTable.java @@ -19,8 +19,8 @@ package org.apache.fop.complexscripts.fonts; -import java.util.Arrays; import java.util.ArrayList; +import java.util.Arrays; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.LinkedList; diff --git a/src/java/org/apache/fop/complexscripts/util/CharScript.java b/src/java/org/apache/fop/complexscripts/util/CharScript.java index 06bc02a4f..c0a2f8ee4 100644 --- a/src/java/org/apache/fop/complexscripts/util/CharScript.java +++ b/src/java/org/apache/fop/complexscripts/util/CharScript.java @@ -20,9 +20,9 @@ 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.Iterator; import java.util.Map; import java.util.Set; diff --git a/src/java/org/apache/fop/datatypes/LengthBase.java b/src/java/org/apache/fop/datatypes/LengthBase.java index 00eaee8c8..b7e51e191 100644 --- a/src/java/org/apache/fop/datatypes/LengthBase.java +++ b/src/java/org/apache/fop/datatypes/LengthBase.java @@ -21,6 +21,7 @@ package org.apache.fop.datatypes; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + import org.apache.fop.fo.Constants; import org.apache.fop.fo.FObj; import org.apache.fop.fo.PropertyList; diff --git a/src/java/org/apache/fop/fo/ValidationException.java b/src/java/org/apache/fop/fo/ValidationException.java index 2285fbd19..745732863 100644 --- a/src/java/org/apache/fop/fo/ValidationException.java +++ b/src/java/org/apache/fop/fo/ValidationException.java @@ -19,9 +19,10 @@ package org.apache.fop.fo; -import org.apache.fop.apps.FOPException; import org.xml.sax.Locator; +import org.apache.fop.apps.FOPException; + /** * Exception thrown during FO tree validation. */ diff --git a/src/java/org/apache/fop/fo/XMLObj.java b/src/java/org/apache/fop/fo/XMLObj.java index a73eda2e9..5f20fa159 100644 --- a/src/java/org/apache/fop/fo/XMLObj.java +++ b/src/java/org/apache/fop/fo/XMLObj.java @@ -19,7 +19,6 @@ package org.apache.fop.fo; -// Java import java.awt.geom.Point2D; import java.util.HashMap; @@ -33,8 +32,8 @@ import org.xml.sax.Locator; import org.apache.fop.apps.FOPException; import org.apache.fop.datatypes.Length; -import org.apache.fop.util.XMLConstants; import org.apache.fop.util.ContentHandlerFactory.ObjectBuiltListener; +import org.apache.fop.util.XMLConstants; /** * Abstract class modelling generic, non-XSL-FO XML objects. Such objects are diff --git a/src/java/org/apache/fop/fo/XMLWhiteSpaceHandler.java b/src/java/org/apache/fop/fo/XMLWhiteSpaceHandler.java index 51e84551c..bc406cfcd 100644 --- a/src/java/org/apache/fop/fo/XMLWhiteSpaceHandler.java +++ b/src/java/org/apache/fop/fo/XMLWhiteSpaceHandler.java @@ -21,6 +21,7 @@ package org.apache.fop.fo; import java.util.List; import java.util.Stack; + import org.apache.fop.fo.flow.Block; import org.apache.fop.util.CharUtilities; diff --git a/src/java/org/apache/fop/fo/expr/FromTableColumnFunction.java b/src/java/org/apache/fop/fo/expr/FromTableColumnFunction.java index df84939f1..627459cf1 100644 --- a/src/java/org/apache/fop/fo/expr/FromTableColumnFunction.java +++ b/src/java/org/apache/fop/fo/expr/FromTableColumnFunction.java @@ -20,9 +20,10 @@ package org.apache.fop.fo.expr; import java.util.List; + import org.apache.fop.fo.Constants; -import org.apache.fop.fo.FObj; import org.apache.fop.fo.FOPropertyMapping; +import org.apache.fop.fo.FObj; import org.apache.fop.fo.flow.table.ColumnNumberManager; import org.apache.fop.fo.flow.table.Table; import org.apache.fop.fo.flow.table.TableCell; diff --git a/src/java/org/apache/fop/fo/expr/Function.java b/src/java/org/apache/fop/fo/expr/Function.java index 78e40fad2..82ec1b7fd 100644 --- a/src/java/org/apache/fop/fo/expr/Function.java +++ b/src/java/org/apache/fop/fo/expr/Function.java @@ -19,8 +19,8 @@ package org.apache.fop.fo.expr; -import org.apache.fop.fo.properties.Property; import org.apache.fop.datatypes.PercentBase; +import org.apache.fop.fo.properties.Property; /** * Interface for managing XSL-FO Functions diff --git a/src/java/org/apache/fop/fo/expr/LabelEndFunction.java b/src/java/org/apache/fop/fo/expr/LabelEndFunction.java index 65be6cf9f..5deb3ae30 100644 --- a/src/java/org/apache/fop/fo/expr/LabelEndFunction.java +++ b/src/java/org/apache/fop/fo/expr/LabelEndFunction.java @@ -19,9 +19,9 @@ package org.apache.fop.fo.expr; -import org.apache.fop.datatypes.Numeric; import org.apache.fop.datatypes.Length; import org.apache.fop.datatypes.LengthBase; +import org.apache.fop.datatypes.Numeric; import org.apache.fop.fo.Constants; import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.flow.ListItem; diff --git a/src/java/org/apache/fop/fo/expr/NumericProperty.java b/src/java/org/apache/fop/fo/expr/NumericProperty.java index f80e1f5a5..81e4220ae 100644 --- a/src/java/org/apache/fop/fo/expr/NumericProperty.java +++ b/src/java/org/apache/fop/fo/expr/NumericProperty.java @@ -23,8 +23,8 @@ import java.awt.Color; import org.apache.fop.apps.FOUserAgent; import org.apache.fop.datatypes.Length; -import org.apache.fop.datatypes.PercentBaseContext; import org.apache.fop.datatypes.Numeric; +import org.apache.fop.datatypes.PercentBaseContext; import org.apache.fop.fo.properties.FixedLength; import org.apache.fop.fo.properties.Property; diff --git a/src/java/org/apache/fop/fo/expr/RGBColorFunction.java b/src/java/org/apache/fop/fo/expr/RGBColorFunction.java index 1c7a91503..868b9a8bf 100644 --- a/src/java/org/apache/fop/fo/expr/RGBColorFunction.java +++ b/src/java/org/apache/fop/fo/expr/RGBColorFunction.java @@ -19,8 +19,8 @@ package org.apache.fop.fo.expr; -import org.apache.fop.datatypes.PercentBaseContext; import org.apache.fop.datatypes.PercentBase; +import org.apache.fop.datatypes.PercentBaseContext; import org.apache.fop.fo.properties.ColorProperty; import org.apache.fop.fo.properties.Property; diff --git a/src/java/org/apache/fop/fo/expr/RelativeNumericProperty.java b/src/java/org/apache/fop/fo/expr/RelativeNumericProperty.java index 10fde01b6..a869b75c8 100644 --- a/src/java/org/apache/fop/fo/expr/RelativeNumericProperty.java +++ b/src/java/org/apache/fop/fo/expr/RelativeNumericProperty.java @@ -20,8 +20,8 @@ package org.apache.fop.fo.expr; import org.apache.fop.datatypes.Length; -import org.apache.fop.datatypes.PercentBaseContext; import org.apache.fop.datatypes.Numeric; +import org.apache.fop.datatypes.PercentBaseContext; import org.apache.fop.fo.properties.Property; import org.apache.fop.fo.properties.TableColLength; diff --git a/src/java/org/apache/fop/fo/extensions/ExtensionObj.java b/src/java/org/apache/fop/fo/extensions/ExtensionObj.java index 4329f1a7e..c35dcfc73 100644 --- a/src/java/org/apache/fop/fo/extensions/ExtensionObj.java +++ b/src/java/org/apache/fop/fo/extensions/ExtensionObj.java @@ -19,14 +19,14 @@ package org.apache.fop.fo.extensions; +import org.xml.sax.Attributes; +import org.xml.sax.Locator; + import org.apache.fop.apps.FOPException; import org.apache.fop.fo.FOEventHandler; import org.apache.fop.fo.FONode; import org.apache.fop.fo.FObj; import org.apache.fop.fo.PropertyList; -import org.xml.sax.Attributes; -import org.xml.sax.Locator; - /** * Base class for pdf bookmark extension objects. diff --git a/src/java/org/apache/fop/fo/extensions/svg/BatikExtensionElementMapping.java b/src/java/org/apache/fop/fo/extensions/svg/BatikExtensionElementMapping.java index 6103345cf..7f8da1063 100644 --- a/src/java/org/apache/fop/fo/extensions/svg/BatikExtensionElementMapping.java +++ b/src/java/org/apache/fop/fo/extensions/svg/BatikExtensionElementMapping.java @@ -20,12 +20,15 @@ package org.apache.fop.fo.extensions.svg; import java.util.HashMap; + import javax.xml.parsers.SAXParserFactory; +import org.w3c.dom.DOMImplementation; + import org.apache.batik.util.XMLResourceDescriptor; + import org.apache.fop.fo.ElementMapping; import org.apache.fop.fo.FONode; -import org.w3c.dom.DOMImplementation; /** * This Element Mapping is for Batik SVG Extension elements diff --git a/src/java/org/apache/fop/fo/extensions/svg/SVGElementMapping.java b/src/java/org/apache/fop/fo/extensions/svg/SVGElementMapping.java index 7120dbb59..0e46076cd 100644 --- a/src/java/org/apache/fop/fo/extensions/svg/SVGElementMapping.java +++ b/src/java/org/apache/fop/fo/extensions/svg/SVGElementMapping.java @@ -20,16 +20,19 @@ package org.apache.fop.fo.extensions.svg; import java.util.HashMap; + import javax.xml.parsers.SAXParserFactory; -import org.apache.fop.fo.FONode; -import org.apache.fop.fo.ElementMapping; +import org.w3c.dom.DOMImplementation; -import org.apache.batik.util.XMLResourceDescriptor; -import org.apache.batik.dom.svg.SVGDOMImplementation; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.w3c.dom.DOMImplementation; + +import org.apache.batik.dom.svg.SVGDOMImplementation; +import org.apache.batik.util.XMLResourceDescriptor; + +import org.apache.fop.fo.ElementMapping; +import org.apache.fop.fo.FONode; /** * Setup the SVG element mapping. diff --git a/src/java/org/apache/fop/fo/extensions/xmp/AbstractMetadataElement.java b/src/java/org/apache/fop/fo/extensions/xmp/AbstractMetadataElement.java index f4b770bbe..8004be01b 100644 --- a/src/java/org/apache/fop/fo/extensions/xmp/AbstractMetadataElement.java +++ b/src/java/org/apache/fop/fo/extensions/xmp/AbstractMetadataElement.java @@ -19,12 +19,13 @@ package org.apache.fop.fo.extensions.xmp; +import org.apache.xmlgraphics.xmp.Metadata; + import org.apache.fop.fo.FONode; import org.apache.fop.fo.FObj; import org.apache.fop.fo.extensions.ExtensionAttachment; import org.apache.fop.util.ContentHandlerFactory; import org.apache.fop.util.ContentHandlerFactory.ObjectBuiltListener; -import org.apache.xmlgraphics.xmp.Metadata; /** * Abstract base class for the XMP and RDF root nodes. diff --git a/src/java/org/apache/fop/fo/extensions/xmp/RDFElement.java b/src/java/org/apache/fop/fo/extensions/xmp/RDFElement.java index cf1c40c4a..094e1ab5c 100644 --- a/src/java/org/apache/fop/fo/extensions/xmp/RDFElement.java +++ b/src/java/org/apache/fop/fo/extensions/xmp/RDFElement.java @@ -19,9 +19,10 @@ package org.apache.fop.fo.extensions.xmp; -import org.apache.fop.fo.FONode; import org.apache.xmlgraphics.xmp.XMPConstants; +import org.apache.fop.fo.FONode; + /** * Represents the top-level "RDF" element used by XMP metadata. */ diff --git a/src/java/org/apache/fop/fo/extensions/xmp/RDFElementMapping.java b/src/java/org/apache/fop/fo/extensions/xmp/RDFElementMapping.java index a6befd710..027a35a32 100644 --- a/src/java/org/apache/fop/fo/extensions/xmp/RDFElementMapping.java +++ b/src/java/org/apache/fop/fo/extensions/xmp/RDFElementMapping.java @@ -21,11 +21,12 @@ package org.apache.fop.fo.extensions.xmp; import java.util.HashMap; -import org.apache.fop.fo.FONode; -import org.apache.fop.fo.ElementMapping; +import org.w3c.dom.DOMImplementation; + import org.apache.xmlgraphics.xmp.XMPConstants; -import org.w3c.dom.DOMImplementation; +import org.apache.fop.fo.ElementMapping; +import org.apache.fop.fo.FONode; /** * Setup the element mapping for XMP metadata. diff --git a/src/java/org/apache/fop/fo/extensions/xmp/XMPContentHandlerFactory.java b/src/java/org/apache/fop/fo/extensions/xmp/XMPContentHandlerFactory.java index 02a74b86d..fd64f1a98 100644 --- a/src/java/org/apache/fop/fo/extensions/xmp/XMPContentHandlerFactory.java +++ b/src/java/org/apache/fop/fo/extensions/xmp/XMPContentHandlerFactory.java @@ -19,12 +19,14 @@ package org.apache.fop.fo.extensions.xmp; -import org.apache.fop.util.ContentHandlerFactory; -import org.apache.xmlgraphics.xmp.XMPConstants; -import org.apache.xmlgraphics.xmp.XMPHandler; import org.xml.sax.ContentHandler; import org.xml.sax.SAXException; +import org.apache.xmlgraphics.xmp.XMPConstants; +import org.apache.xmlgraphics.xmp.XMPHandler; + +import org.apache.fop.util.ContentHandlerFactory; + /** * ContentHandlerFactory for the XMP root element. */ diff --git a/src/java/org/apache/fop/fo/extensions/xmp/XMPElementMapping.java b/src/java/org/apache/fop/fo/extensions/xmp/XMPElementMapping.java index d934dc2b1..bdcadc780 100644 --- a/src/java/org/apache/fop/fo/extensions/xmp/XMPElementMapping.java +++ b/src/java/org/apache/fop/fo/extensions/xmp/XMPElementMapping.java @@ -21,11 +21,12 @@ package org.apache.fop.fo.extensions.xmp; import java.util.HashMap; -import org.apache.fop.fo.FONode; -import org.apache.fop.fo.ElementMapping; +import org.w3c.dom.DOMImplementation; + import org.apache.xmlgraphics.xmp.XMPConstants; -import org.w3c.dom.DOMImplementation; +import org.apache.fop.fo.ElementMapping; +import org.apache.fop.fo.FONode; /** * Setup the element mapping for XMP metadata. diff --git a/src/java/org/apache/fop/fo/extensions/xmp/XMPMetaElement.java b/src/java/org/apache/fop/fo/extensions/xmp/XMPMetaElement.java index f99ccd2aa..f61c59d64 100644 --- a/src/java/org/apache/fop/fo/extensions/xmp/XMPMetaElement.java +++ b/src/java/org/apache/fop/fo/extensions/xmp/XMPMetaElement.java @@ -19,9 +19,10 @@ package org.apache.fop.fo.extensions.xmp; -import org.apache.fop.fo.FONode; import org.apache.xmlgraphics.xmp.XMPConstants; +import org.apache.fop.fo.FONode; + /** * Represents the top-level "xmpmeta" element used by XMP metadata. */ diff --git a/src/java/org/apache/fop/fo/extensions/xmp/XMPMetadata.java b/src/java/org/apache/fop/fo/extensions/xmp/XMPMetadata.java index 6dcc31385..af8231448 100644 --- a/src/java/org/apache/fop/fo/extensions/xmp/XMPMetadata.java +++ b/src/java/org/apache/fop/fo/extensions/xmp/XMPMetadata.java @@ -21,12 +21,14 @@ package org.apache.fop.fo.extensions.xmp; import java.io.Serializable; -import org.apache.fop.fo.extensions.ExtensionAttachment; +import org.xml.sax.ContentHandler; +import org.xml.sax.SAXException; + import org.apache.xmlgraphics.util.XMLizable; import org.apache.xmlgraphics.xmp.Metadata; import org.apache.xmlgraphics.xmp.XMPConstants; -import org.xml.sax.ContentHandler; -import org.xml.sax.SAXException; + +import org.apache.fop.fo.extensions.ExtensionAttachment; /** * This is the pass-through value object for the XMP metadata extension. diff --git a/src/java/org/apache/fop/fo/flow/BlockContainer.java b/src/java/org/apache/fop/fo/flow/BlockContainer.java index 1dc43fd36..cdeb99081 100644 --- a/src/java/org/apache/fop/fo/flow/BlockContainer.java +++ b/src/java/org/apache/fop/fo/flow/BlockContainer.java @@ -19,6 +19,8 @@ package org.apache.fop.fo.flow; +import org.xml.sax.Locator; + import org.apache.fop.apps.FOPException; import org.apache.fop.datatypes.Numeric; import org.apache.fop.fo.FONode; @@ -35,7 +37,6 @@ 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 diff --git a/src/java/org/apache/fop/fo/flow/RetrieveMarker.java b/src/java/org/apache/fop/fo/flow/RetrieveMarker.java index 0d0331359..6e1cb0a6e 100644 --- a/src/java/org/apache/fop/fo/flow/RetrieveMarker.java +++ b/src/java/org/apache/fop/fo/flow/RetrieveMarker.java @@ -19,11 +19,12 @@ package org.apache.fop.fo.flow; +import org.xml.sax.Attributes; +import org.xml.sax.Locator; + import org.apache.fop.apps.FOPException; import org.apache.fop.fo.FONode; import org.apache.fop.fo.PropertyList; -import org.xml.sax.Locator; -import org.xml.sax.Attributes; /** * Class modelling the diff --git a/src/java/org/apache/fop/fo/flow/RetrieveTableMarker.java b/src/java/org/apache/fop/fo/flow/RetrieveTableMarker.java index 3fe977b21..3090cb702 100644 --- a/src/java/org/apache/fop/fo/flow/RetrieveTableMarker.java +++ b/src/java/org/apache/fop/fo/flow/RetrieveTableMarker.java @@ -19,11 +19,12 @@ package org.apache.fop.fo.flow; +import org.xml.sax.Attributes; +import org.xml.sax.Locator; + +import org.apache.fop.apps.FOPException; import org.apache.fop.fo.FONode; import org.apache.fop.fo.PropertyList; -import org.apache.fop.apps.FOPException; -import org.xml.sax.Locator; -import org.xml.sax.Attributes; /** * Class modelling the diff --git a/src/java/org/apache/fop/fo/flow/table/TableBody.java b/src/java/org/apache/fop/fo/flow/table/TableBody.java index 0b42fd837..d69081e48 100644 --- a/src/java/org/apache/fop/fo/flow/table/TableBody.java +++ b/src/java/org/apache/fop/fo/flow/table/TableBody.java @@ -19,8 +19,8 @@ package org.apache.fop.fo.flow.table; -import org.apache.fop.fo.FONode; import org.apache.fop.apps.FOPException; +import org.apache.fop.fo.FONode; /** * Class modelling the diff --git a/src/java/org/apache/fop/fo/pagination/ColorProfile.java b/src/java/org/apache/fop/fo/pagination/ColorProfile.java index 7fac8655e..e1ca99ff9 100644 --- a/src/java/org/apache/fop/fo/pagination/ColorProfile.java +++ b/src/java/org/apache/fop/fo/pagination/ColorProfile.java @@ -19,14 +19,14 @@ package org.apache.fop.fo.pagination; +import org.xml.sax.Locator; + import org.apache.fop.apps.FOPException; import org.apache.fop.fo.FONode; import org.apache.fop.fo.FObj; import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.ValidationException; -import org.xml.sax.Locator; - /** * Class modelling the * fo:color-profile object. diff --git a/src/java/org/apache/fop/fo/pagination/PageSequenceWrapper.java b/src/java/org/apache/fop/fo/pagination/PageSequenceWrapper.java index 247384770..f3f362b10 100644 --- a/src/java/org/apache/fop/fo/pagination/PageSequenceWrapper.java +++ b/src/java/org/apache/fop/fo/pagination/PageSequenceWrapper.java @@ -22,8 +22,8 @@ package org.apache.fop.fo.pagination; import org.xml.sax.Locator; import org.apache.fop.apps.FOPException; -import org.apache.fop.fo.FObj; import org.apache.fop.fo.FONode; +import org.apache.fop.fo.FObj; import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.ValidationException; diff --git a/src/java/org/apache/fop/fo/pagination/RegionAfter.java b/src/java/org/apache/fop/fo/pagination/RegionAfter.java index da7ef812a..9c4e2fd3a 100644 --- a/src/java/org/apache/fop/fo/pagination/RegionAfter.java +++ b/src/java/org/apache/fop/fo/pagination/RegionAfter.java @@ -19,15 +19,13 @@ package org.apache.fop.fo.pagination; -// Java 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; import org.apache.fop.datatypes.PercentBaseContext; +import org.apache.fop.fo.Constants; +import org.apache.fop.fo.FONode; /** * Class modelling the diff --git a/src/java/org/apache/fop/fo/pagination/RegionBefore.java b/src/java/org/apache/fop/fo/pagination/RegionBefore.java index 7d285f3d7..eddd290a9 100644 --- a/src/java/org/apache/fop/fo/pagination/RegionBefore.java +++ b/src/java/org/apache/fop/fo/pagination/RegionBefore.java @@ -19,14 +19,12 @@ package org.apache.fop.fo.pagination; -// Java 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; +import org.apache.fop.fo.Constants; import org.apache.fop.fo.FONode; /** diff --git a/src/java/org/apache/fop/fo/pagination/RegionEnd.java b/src/java/org/apache/fop/fo/pagination/RegionEnd.java index a0daf1776..535524c37 100644 --- a/src/java/org/apache/fop/fo/pagination/RegionEnd.java +++ b/src/java/org/apache/fop/fo/pagination/RegionEnd.java @@ -19,15 +19,13 @@ package org.apache.fop.fo.pagination; -// Java 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; import org.apache.fop.datatypes.PercentBaseContext; +import org.apache.fop.fo.Constants; +import org.apache.fop.fo.FONode; /** * Class modelling the diff --git a/src/java/org/apache/fop/fo/pagination/RegionStart.java b/src/java/org/apache/fop/fo/pagination/RegionStart.java index afb9ff1a7..3371a934e 100644 --- a/src/java/org/apache/fop/fo/pagination/RegionStart.java +++ b/src/java/org/apache/fop/fo/pagination/RegionStart.java @@ -19,15 +19,13 @@ package org.apache.fop.fo.pagination; -// Java 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; import org.apache.fop.datatypes.PercentBaseContext; +import org.apache.fop.fo.Constants; +import org.apache.fop.fo.FONode; /** * Class modelling the diff --git a/src/java/org/apache/fop/fo/properties/CommonTextDecoration.java b/src/java/org/apache/fop/fo/properties/CommonTextDecoration.java index f7c11578d..8ef62ced0 100644 --- a/src/java/org/apache/fop/fo/properties/CommonTextDecoration.java +++ b/src/java/org/apache/fop/fo/properties/CommonTextDecoration.java @@ -19,11 +19,11 @@ package org.apache.fop.fo.properties; +import java.awt.Color; + import java.util.Iterator; import java.util.List; -import java.awt.Color; - import org.apache.fop.apps.FOUserAgent; import org.apache.fop.fo.Constants; import org.apache.fop.fo.PropertyList; diff --git a/src/java/org/apache/fop/fo/properties/PercentLength.java b/src/java/org/apache/fop/fo/properties/PercentLength.java index 66f1f175c..4e83fb919 100644 --- a/src/java/org/apache/fop/fo/properties/PercentLength.java +++ b/src/java/org/apache/fop/fo/properties/PercentLength.java @@ -19,8 +19,8 @@ package org.apache.fop.fo.properties; -import org.apache.fop.datatypes.PercentBaseContext; import org.apache.fop.datatypes.PercentBase; +import org.apache.fop.datatypes.PercentBaseContext; import org.apache.fop.fo.expr.PropertyException; /** diff --git a/src/java/org/apache/fop/fo/properties/Property.java b/src/java/org/apache/fop/fo/properties/Property.java index a04f96a3c..e5ee87bd6 100644 --- a/src/java/org/apache/fop/fo/properties/Property.java +++ b/src/java/org/apache/fop/fo/properties/Property.java @@ -19,8 +19,8 @@ package org.apache.fop.fo.properties; -import java.util.List; import java.awt.Color; +import java.util.List; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/src/java/org/apache/fop/fo/properties/PropertyCache.java b/src/java/org/apache/fop/fo/properties/PropertyCache.java index 8bd1d847f..cb11cf6fa 100644 --- a/src/java/org/apache/fop/fo/properties/PropertyCache.java +++ b/src/java/org/apache/fop/fo/properties/PropertyCache.java @@ -19,11 +19,11 @@ package org.apache.fop.fo.properties; -import org.apache.fop.fo.flow.Marker; - import java.lang.ref.ReferenceQueue; import java.lang.ref.WeakReference; +import org.apache.fop.fo.flow.Marker; + /** * Dedicated cache, meant for storing canonical instances * of property-related classes. diff --git a/src/java/org/apache/fop/fo/properties/URIProperty.java b/src/java/org/apache/fop/fo/properties/URIProperty.java index 6465fafdb..60c3a2067 100644 --- a/src/java/org/apache/fop/fo/properties/URIProperty.java +++ b/src/java/org/apache/fop/fo/properties/URIProperty.java @@ -19,14 +19,14 @@ package org.apache.fop.fo.properties; +import java.net.URI; +import java.net.URISyntaxException; + import org.apache.fop.datatypes.URISpecification; import org.apache.fop.fo.FObj; import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.expr.PropertyException; -import java.net.URI; -import java.net.URISyntaxException; - import static org.apache.fop.fo.Constants.PR_X_XML_BASE; /** diff --git a/src/java/org/apache/fop/fonts/FontManagerConfigurator.java b/src/java/org/apache/fop/fonts/FontManagerConfigurator.java index 40e163d42..1a900fe2f 100644 --- a/src/java/org/apache/fop/fonts/FontManagerConfigurator.java +++ b/src/java/org/apache/fop/fonts/FontManagerConfigurator.java @@ -29,6 +29,7 @@ import org.apache.avalon.framework.configuration.Configuration; import org.apache.avalon.framework.configuration.ConfigurationException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + import org.apache.fop.apps.FOPException; import org.apache.fop.fonts.substitute.FontSubstitutions; import org.apache.fop.fonts.substitute.FontSubstitutionsConfigurator; diff --git a/src/java/org/apache/fop/fonts/LazyFont.java b/src/java/org/apache/fop/fonts/LazyFont.java index dfd2367b2..7474c17f1 100644 --- a/src/java/org/apache/fop/fonts/LazyFont.java +++ b/src/java/org/apache/fop/fonts/LazyFont.java @@ -27,6 +27,8 @@ import java.util.Set; import javax.xml.transform.Source; import javax.xml.transform.stream.StreamSource; +import org.xml.sax.InputSource; + import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -35,8 +37,6 @@ 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. */ diff --git a/src/java/org/apache/fop/fonts/Typeface.java b/src/java/org/apache/fop/fonts/Typeface.java index e933781cd..0e3844077 100644 --- a/src/java/org/apache/fop/fonts/Typeface.java +++ b/src/java/org/apache/fop/fonts/Typeface.java @@ -24,6 +24,7 @@ import java.util.Set; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + import org.apache.xmlgraphics.fonts.Glyphs; /** diff --git a/src/java/org/apache/fop/fonts/apps/AbstractFontReader.java b/src/java/org/apache/fop/fonts/apps/AbstractFontReader.java index 89c7890af..39f7e14a4 100644 --- a/src/java/org/apache/fop/fonts/apps/AbstractFontReader.java +++ b/src/java/org/apache/fop/fonts/apps/AbstractFontReader.java @@ -31,6 +31,7 @@ import javax.xml.transform.TransformerFactory; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + import org.apache.fop.util.CommandLineLogger; /** diff --git a/src/java/org/apache/fop/fonts/apps/TTFReader.java b/src/java/org/apache/fop/fonts/apps/TTFReader.java index 7159a60b7..6acb490c2 100644 --- a/src/java/org/apache/fop/fonts/apps/TTFReader.java +++ b/src/java/org/apache/fop/fonts/apps/TTFReader.java @@ -26,17 +26,19 @@ import java.util.Set; import javax.xml.parsers.DocumentBuilderFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.xml.sax.Attributes; +import org.xml.sax.SAXException; + import org.apache.commons.logging.LogFactory; + import org.apache.fop.Version; import org.apache.fop.fonts.FontUtil; import org.apache.fop.fonts.truetype.FontFileReader; import org.apache.fop.fonts.truetype.TTFCmapEntry; import org.apache.fop.fonts.truetype.TTFFile; import org.apache.fop.util.CommandLineLogger; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.xml.sax.Attributes; -import org.xml.sax.SAXException; // CSOFF: InnerAssignmentCheck // CSOFF: LineLengthCheck diff --git a/src/java/org/apache/fop/fonts/autodetect/FontInfoFinder.java b/src/java/org/apache/fop/fonts/autodetect/FontInfoFinder.java index bf6f493cf..bd0a33cb1 100644 --- a/src/java/org/apache/fop/fonts/autodetect/FontInfoFinder.java +++ b/src/java/org/apache/fop/fonts/autodetect/FontInfoFinder.java @@ -29,6 +29,7 @@ import java.util.regex.Pattern; import org.apache.commons.io.IOUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + import org.apache.fop.fonts.CustomFont; import org.apache.fop.fonts.EmbedFontInfo; import org.apache.fop.fonts.EncodingMode; diff --git a/src/java/org/apache/fop/fonts/substitute/FontQualifier.java b/src/java/org/apache/fop/fonts/substitute/FontQualifier.java index 3419ab2c7..c1b6a93cd 100644 --- a/src/java/org/apache/fop/fonts/substitute/FontQualifier.java +++ b/src/java/org/apache/fop/fonts/substitute/FontQualifier.java @@ -26,6 +26,7 @@ import java.util.Set; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + import org.apache.fop.fonts.Font; import org.apache.fop.fonts.FontInfo; import org.apache.fop.fonts.FontTriplet; diff --git a/src/java/org/apache/fop/fonts/substitute/FontSubstitutions.java b/src/java/org/apache/fop/fonts/substitute/FontSubstitutions.java index e018bb2c2..e96459577 100644 --- a/src/java/org/apache/fop/fonts/substitute/FontSubstitutions.java +++ b/src/java/org/apache/fop/fonts/substitute/FontSubstitutions.java @@ -24,6 +24,7 @@ import java.util.List; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + import org.apache.fop.fonts.FontInfo; import org.apache.fop.fonts.FontTriplet; diff --git a/src/java/org/apache/fop/fonts/substitute/FontSubstitutionsConfigurator.java b/src/java/org/apache/fop/fonts/substitute/FontSubstitutionsConfigurator.java index 0c6c0db0e..75e6497ee 100644 --- a/src/java/org/apache/fop/fonts/substitute/FontSubstitutionsConfigurator.java +++ b/src/java/org/apache/fop/fonts/substitute/FontSubstitutionsConfigurator.java @@ -20,6 +20,7 @@ package org.apache.fop.fonts.substitute; import org.apache.avalon.framework.configuration.Configuration; + import org.apache.fop.apps.FOPException; /** diff --git a/src/java/org/apache/fop/fonts/truetype/TTFFile.java b/src/java/org/apache/fop/fonts/truetype/TTFFile.java index 33d608540..bcbd73a6f 100644 --- a/src/java/org/apache/fop/fonts/truetype/TTFFile.java +++ b/src/java/org/apache/fop/fonts/truetype/TTFFile.java @@ -28,6 +28,7 @@ import java.util.Set; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + import org.apache.xmlgraphics.fonts.Glyphs; import org.apache.fop.complexscripts.fonts.AdvancedTypographicTableFormatException; diff --git a/src/java/org/apache/fop/fonts/truetype/TTFFontLoader.java b/src/java/org/apache/fop/fonts/truetype/TTFFontLoader.java index 54324be52..c03f0fb6a 100644 --- a/src/java/org/apache/fop/fonts/truetype/TTFFontLoader.java +++ b/src/java/org/apache/fop/fonts/truetype/TTFFontLoader.java @@ -27,6 +27,9 @@ import java.util.Map; import java.util.Set; import org.apache.commons.io.IOUtils; + +import org.apache.xmlgraphics.fonts.Glyphs; + import org.apache.fop.fonts.BFEntry; import org.apache.fop.fonts.CIDFontType; import org.apache.fop.fonts.EncodingMode; @@ -36,7 +39,6 @@ import org.apache.fop.fonts.FontType; import org.apache.fop.fonts.MultiByteFont; import org.apache.fop.fonts.NamedCharacter; import org.apache.fop.fonts.SingleByteFont; -import org.apache.xmlgraphics.fonts.Glyphs; /** * Loads a TrueType font into memory directly from the original font file. diff --git a/src/java/org/apache/fop/fonts/type1/PFBData.java b/src/java/org/apache/fop/fonts/type1/PFBData.java index 157dc8066..abccfbb8d 100644 --- a/src/java/org/apache/fop/fonts/type1/PFBData.java +++ b/src/java/org/apache/fop/fonts/type1/PFBData.java @@ -19,8 +19,8 @@ package org.apache.fop.fonts.type1; -import java.io.OutputStream; import java.io.IOException; +import java.io.OutputStream; /** * Class that represents the contents of a PFB file. diff --git a/src/java/org/apache/fop/fonts/type1/PFBParser.java b/src/java/org/apache/fop/fonts/type1/PFBParser.java index 8cb90b146..f6dfe53ef 100644 --- a/src/java/org/apache/fop/fonts/type1/PFBParser.java +++ b/src/java/org/apache/fop/fonts/type1/PFBParser.java @@ -19,12 +19,11 @@ package org.apache.fop.fonts.type1; +import java.io.BufferedInputStream; +import java.io.DataInputStream; import java.io.IOException; import java.io.InputStream; -import java.io.DataInputStream; -import java.io.BufferedInputStream; -//Commons import org.apache.commons.io.IOUtils; /** diff --git a/src/java/org/apache/fop/fonts/type1/PFMInputStream.java b/src/java/org/apache/fop/fonts/type1/PFMInputStream.java index f563059c3..e8f0cb705 100644 --- a/src/java/org/apache/fop/fonts/type1/PFMInputStream.java +++ b/src/java/org/apache/fop/fonts/type1/PFMInputStream.java @@ -19,10 +19,10 @@ package org.apache.fop.fonts.type1; +import java.io.DataInputStream; import java.io.EOFException; import java.io.IOException; import java.io.InputStream; -import java.io.DataInputStream; import java.io.InputStreamReader; /** diff --git a/src/java/org/apache/fop/hyphenation/Hyphenator.java b/src/java/org/apache/fop/hyphenation/Hyphenator.java index 455520b09..ba52e2baf 100644 --- a/src/java/org/apache/fop/hyphenation/Hyphenator.java +++ b/src/java/org/apache/fop/hyphenation/Hyphenator.java @@ -29,10 +29,11 @@ import java.util.Map; import javax.xml.transform.Source; import javax.xml.transform.stream.StreamSource; +import org.xml.sax.InputSource; + import org.apache.commons.io.IOUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.xml.sax.InputSource; /** * This class is the main entry point to the hyphenation package. diff --git a/src/java/org/apache/fop/hyphenation/PatternParser.java b/src/java/org/apache/fop/hyphenation/PatternParser.java index 404f10c7f..c08d84660 100644 --- a/src/java/org/apache/fop/hyphenation/PatternParser.java +++ b/src/java/org/apache/fop/hyphenation/PatternParser.java @@ -19,15 +19,6 @@ package org.apache.fop.hyphenation; -// SAX -import org.xml.sax.XMLReader; -import org.xml.sax.InputSource; -import org.xml.sax.SAXException; -import org.xml.sax.SAXParseException; -import org.xml.sax.helpers.DefaultHandler; -import org.xml.sax.Attributes; - -// Java import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; @@ -39,6 +30,13 @@ import java.util.ArrayList; import javax.xml.parsers.SAXParserFactory; +import org.xml.sax.Attributes; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.SAXParseException; +import org.xml.sax.XMLReader; +import org.xml.sax.helpers.DefaultHandler; + /** * A SAX document handler to read and parse hyphenation patterns * from a XML file. diff --git a/src/java/org/apache/fop/hyphenation/TernaryTree.java b/src/java/org/apache/fop/hyphenation/TernaryTree.java index 2734c0385..918a747fa 100644 --- a/src/java/org/apache/fop/hyphenation/TernaryTree.java +++ b/src/java/org/apache/fop/hyphenation/TernaryTree.java @@ -19,9 +19,9 @@ package org.apache.fop.hyphenation; +import java.io.Serializable; import java.util.Enumeration; import java.util.Stack; -import java.io.Serializable; /** *

    Ternary Search Tree.

    diff --git a/src/java/org/apache/fop/image/loader/batik/ImageConverterSVG2G2D.java b/src/java/org/apache/fop/image/loader/batik/ImageConverterSVG2G2D.java index 0b7989fb2..79592efd1 100644 --- a/src/java/org/apache/fop/image/loader/batik/ImageConverterSVG2G2D.java +++ b/src/java/org/apache/fop/image/loader/batik/ImageConverterSVG2G2D.java @@ -25,13 +25,14 @@ import java.util.Map; import org.w3c.dom.Document; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + import org.apache.batik.bridge.BridgeContext; import org.apache.batik.bridge.GVTBuilder; import org.apache.batik.bridge.UserAgent; import org.apache.batik.dom.svg.SVGDOMImplementation; import org.apache.batik.gvt.GraphicsNode; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; import org.apache.xmlgraphics.image.GraphicsConstants; import org.apache.xmlgraphics.image.loader.Image; diff --git a/src/java/org/apache/fop/image/loader/batik/ImageConverterWMF2G2D.java b/src/java/org/apache/fop/image/loader/batik/ImageConverterWMF2G2D.java index 7bc8c2050..6d84a03d3 100644 --- a/src/java/org/apache/fop/image/loader/batik/ImageConverterWMF2G2D.java +++ b/src/java/org/apache/fop/image/loader/batik/ImageConverterWMF2G2D.java @@ -24,11 +24,12 @@ import java.awt.Graphics2D; import java.awt.geom.Rectangle2D; import java.util.Map; -import org.apache.batik.transcoder.wmf.tosvg.WMFPainter; -import org.apache.batik.transcoder.wmf.tosvg.WMFRecordStore; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.apache.batik.transcoder.wmf.tosvg.WMFPainter; +import org.apache.batik.transcoder.wmf.tosvg.WMFRecordStore; + import org.apache.xmlgraphics.image.loader.Image; import org.apache.xmlgraphics.image.loader.ImageFlavor; import org.apache.xmlgraphics.image.loader.impl.AbstractImageConverter; diff --git a/src/java/org/apache/fop/image/loader/batik/PreloaderSVG.java b/src/java/org/apache/fop/image/loader/batik/PreloaderSVG.java index c675e3cfc..022ff462f 100644 --- a/src/java/org/apache/fop/image/loader/batik/PreloaderSVG.java +++ b/src/java/org/apache/fop/image/loader/batik/PreloaderSVG.java @@ -30,13 +30,14 @@ import javax.xml.transform.dom.DOMSource; import org.w3c.dom.Element; import org.w3c.dom.svg.SVGDocument; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + import org.apache.batik.bridge.BridgeContext; import org.apache.batik.bridge.UnitProcessor; import org.apache.batik.bridge.UserAgent; import org.apache.batik.dom.svg.SAXSVGDocumentFactory; import org.apache.batik.dom.svg.SVGOMDocument; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; import org.apache.xmlgraphics.image.loader.ImageContext; import org.apache.xmlgraphics.image.loader.ImageInfo; diff --git a/src/java/org/apache/fop/image/loader/batik/PreloaderWMF.java b/src/java/org/apache/fop/image/loader/batik/PreloaderWMF.java index 8bda04903..3bef0f41d 100644 --- a/src/java/org/apache/fop/image/loader/batik/PreloaderWMF.java +++ b/src/java/org/apache/fop/image/loader/batik/PreloaderWMF.java @@ -25,13 +25,14 @@ import java.io.InputStream; import javax.xml.transform.Source; -import org.apache.batik.transcoder.wmf.WMFConstants; -import org.apache.batik.transcoder.wmf.tosvg.WMFRecordStore; import org.apache.commons.io.EndianUtils; import org.apache.commons.io.IOUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.apache.batik.transcoder.wmf.WMFConstants; +import org.apache.batik.transcoder.wmf.tosvg.WMFRecordStore; + import org.apache.xmlgraphics.image.loader.ImageContext; import org.apache.xmlgraphics.image.loader.ImageInfo; import org.apache.xmlgraphics.image.loader.ImageSize; diff --git a/src/java/org/apache/fop/layoutmgr/AbstractLayoutManager.java b/src/java/org/apache/fop/layoutmgr/AbstractLayoutManager.java index dd9c34149..05f3b1eff 100644 --- a/src/java/org/apache/fop/layoutmgr/AbstractLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/AbstractLayoutManager.java @@ -27,6 +27,8 @@ import java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.apache.xmlgraphics.util.QName; + import org.apache.fop.area.Area; import org.apache.fop.area.AreaTreeObject; import org.apache.fop.area.PageViewport; @@ -35,7 +37,6 @@ import org.apache.fop.fo.FONode; import org.apache.fop.fo.FObj; import org.apache.fop.fo.flow.Marker; import org.apache.fop.fo.flow.RetrieveMarker; -import org.apache.xmlgraphics.util.QName; /** * The base class for most LayoutManagers. diff --git a/src/java/org/apache/fop/layoutmgr/KnuthSequence.java b/src/java/org/apache/fop/layoutmgr/KnuthSequence.java index 1a9bb6534..d568da45e 100644 --- a/src/java/org/apache/fop/layoutmgr/KnuthSequence.java +++ b/src/java/org/apache/fop/layoutmgr/KnuthSequence.java @@ -19,12 +19,12 @@ package org.apache.fop.layoutmgr; -import org.apache.fop.util.ListUtil; - import java.util.ArrayList; import java.util.List; import java.util.ListIterator; +import org.apache.fop.util.ListUtil; + /** * Represents a list of {@link KnuthElement Knuth elements}. */ diff --git a/src/java/org/apache/fop/layoutmgr/LayoutException.java b/src/java/org/apache/fop/layoutmgr/LayoutException.java index f22d34bd8..0fa96e03f 100644 --- a/src/java/org/apache/fop/layoutmgr/LayoutException.java +++ b/src/java/org/apache/fop/layoutmgr/LayoutException.java @@ -22,8 +22,8 @@ package org.apache.fop.layoutmgr; import java.util.Locale; import org.apache.fop.events.Event; -import org.apache.fop.events.EventFormatter; import org.apache.fop.events.EventExceptionManager.ExceptionFactory; +import org.apache.fop.events.EventFormatter; /** * Exception thrown by FOP if an unrecoverable layout error occurs. An example: An area overflows diff --git a/src/java/org/apache/fop/layoutmgr/LayoutManagerMaker.java b/src/java/org/apache/fop/layoutmgr/LayoutManagerMaker.java index e9e3fb6a7..789d66eb2 100644 --- a/src/java/org/apache/fop/layoutmgr/LayoutManagerMaker.java +++ b/src/java/org/apache/fop/layoutmgr/LayoutManagerMaker.java @@ -20,6 +20,9 @@ package org.apache.fop.layoutmgr; import java.util.List; + +import org.apache.fop.area.AreaTreeHandler; +import org.apache.fop.area.Block; import org.apache.fop.fo.FONode; import org.apache.fop.fo.extensions.ExternalDocument; import org.apache.fop.fo.pagination.Flow; @@ -28,8 +31,6 @@ 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.ContentLayoutManager; -import org.apache.fop.area.AreaTreeHandler; -import org.apache.fop.area.Block; /** * The interface for all LayoutManager makers diff --git a/src/java/org/apache/fop/layoutmgr/SpaceSpecifier.java b/src/java/org/apache/fop/layoutmgr/SpaceSpecifier.java index 83a67b101..394477658 100644 --- a/src/java/org/apache/fop/layoutmgr/SpaceSpecifier.java +++ b/src/java/org/apache/fop/layoutmgr/SpaceSpecifier.java @@ -19,10 +19,11 @@ package org.apache.fop.layoutmgr; -import org.apache.fop.traits.SpaceVal; import java.util.ArrayList; import java.util.List; + import org.apache.fop.traits.MinOptMax; +import org.apache.fop.traits.SpaceVal; /** * Accumulate a sequence of space-specifiers (XSL space type) on diff --git a/src/java/org/apache/fop/layoutmgr/UnresolvedListElementWithLength.java b/src/java/org/apache/fop/layoutmgr/UnresolvedListElementWithLength.java index 0667b9355..ef4a366eb 100644 --- a/src/java/org/apache/fop/layoutmgr/UnresolvedListElementWithLength.java +++ b/src/java/org/apache/fop/layoutmgr/UnresolvedListElementWithLength.java @@ -21,6 +21,7 @@ package org.apache.fop.layoutmgr; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + import org.apache.fop.traits.MinOptMax; /** diff --git a/src/java/org/apache/fop/layoutmgr/inline/FootnoteLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/FootnoteLayoutManager.java index d5d62dd4b..68a240ff1 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/FootnoteLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/FootnoteLayoutManager.java @@ -25,6 +25,7 @@ import java.util.ListIterator; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + import org.apache.fop.fo.flow.Footnote; import org.apache.fop.layoutmgr.FootnoteBodyLayoutManager; import org.apache.fop.layoutmgr.InlineKnuthSequence; diff --git a/src/java/org/apache/fop/layoutmgr/inline/LeafNodeLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/LeafNodeLayoutManager.java index c7205905b..203c7a7fc 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/LeafNodeLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/LeafNodeLayoutManager.java @@ -19,12 +19,13 @@ package org.apache.fop.layoutmgr.inline; +import java.util.Collections; import java.util.LinkedList; import java.util.List; -import java.util.Collections; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + import org.apache.fop.area.Area; import org.apache.fop.area.inline.InlineArea; import org.apache.fop.fo.FObj; diff --git a/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java index 4010777ad..0ec6de43b 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java @@ -19,8 +19,8 @@ package org.apache.fop.layoutmgr.inline; -import java.util.Arrays; import java.util.ArrayList; +import java.util.Arrays; import java.util.LinkedList; import java.util.List; import java.util.ListIterator; diff --git a/src/java/org/apache/fop/layoutmgr/inline/WrapperLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/WrapperLayoutManager.java index 4b93bcdac..ca5179399 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/WrapperLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/WrapperLayoutManager.java @@ -19,8 +19,8 @@ package org.apache.fop.layoutmgr.inline; -import org.apache.fop.area.inline.InlineArea; import org.apache.fop.area.Block; +import org.apache.fop.area.inline.InlineArea; import org.apache.fop.fo.flow.Wrapper; import org.apache.fop.layoutmgr.BlockLayoutManager; import org.apache.fop.layoutmgr.BlockStackingLayoutManager; diff --git a/src/java/org/apache/fop/layoutmgr/list/ListItemContentLayoutManager.java b/src/java/org/apache/fop/layoutmgr/list/ListItemContentLayoutManager.java index 291def4c3..a84069082 100644 --- a/src/java/org/apache/fop/layoutmgr/list/ListItemContentLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/list/ListItemContentLayoutManager.java @@ -34,8 +34,8 @@ import org.apache.fop.layoutmgr.LayoutManager; import org.apache.fop.layoutmgr.NonLeafPosition; import org.apache.fop.layoutmgr.Position; import org.apache.fop.layoutmgr.PositionIterator; -import org.apache.fop.layoutmgr.TraitSetter; import org.apache.fop.layoutmgr.SpaceResolver.SpaceHandlingBreakPosition; +import org.apache.fop.layoutmgr.TraitSetter; /** * LayoutManager for a list-item-label or list-item-body FO. diff --git a/src/java/org/apache/fop/layoutmgr/table/RowGroupLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/RowGroupLayoutManager.java index 7c11db17d..f41f77ea4 100644 --- a/src/java/org/apache/fop/layoutmgr/table/RowGroupLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/RowGroupLayoutManager.java @@ -25,6 +25,7 @@ import java.util.List; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + import org.apache.fop.fo.Constants; import org.apache.fop.fo.flow.table.EffRow; import org.apache.fop.fo.flow.table.GridUnit; diff --git a/src/java/org/apache/fop/pdf/ASCII85Filter.java b/src/java/org/apache/fop/pdf/ASCII85Filter.java index df82c5179..7a86f57ee 100644 --- a/src/java/org/apache/fop/pdf/ASCII85Filter.java +++ b/src/java/org/apache/fop/pdf/ASCII85Filter.java @@ -19,8 +19,8 @@ package org.apache.fop.pdf; -import java.io.OutputStream; import java.io.IOException; +import java.io.OutputStream; import org.apache.xmlgraphics.util.io.ASCII85OutputStream; diff --git a/src/java/org/apache/fop/pdf/ASCIIHexFilter.java b/src/java/org/apache/fop/pdf/ASCIIHexFilter.java index 01dc75190..3456cf1ae 100644 --- a/src/java/org/apache/fop/pdf/ASCIIHexFilter.java +++ b/src/java/org/apache/fop/pdf/ASCIIHexFilter.java @@ -19,8 +19,8 @@ package org.apache.fop.pdf; -import java.io.OutputStream; import java.io.IOException; +import java.io.OutputStream; import org.apache.xmlgraphics.util.io.ASCIIHexOutputStream; diff --git a/src/java/org/apache/fop/pdf/InMemoryStreamCache.java b/src/java/org/apache/fop/pdf/InMemoryStreamCache.java index 7e9a78aa4..85d265e7f 100644 --- a/src/java/org/apache/fop/pdf/InMemoryStreamCache.java +++ b/src/java/org/apache/fop/pdf/InMemoryStreamCache.java @@ -20,8 +20,8 @@ package org.apache.fop.pdf; import java.io.ByteArrayOutputStream; -import java.io.OutputStream; import java.io.IOException; +import java.io.OutputStream; /** * StreamCache implementation that uses temporary files rather than heap. diff --git a/src/java/org/apache/fop/pdf/PDFCharProcs.java b/src/java/org/apache/fop/pdf/PDFCharProcs.java index 73fe19a5e..6a423e038 100644 --- a/src/java/org/apache/fop/pdf/PDFCharProcs.java +++ b/src/java/org/apache/fop/pdf/PDFCharProcs.java @@ -19,8 +19,8 @@ package org.apache.fop.pdf; -import java.util.Map; import java.util.HashMap; +import java.util.Map; /** * class representing a /CharProcs dictionary for Type3 fonts. diff --git a/src/java/org/apache/fop/pdf/PDFFilter.java b/src/java/org/apache/fop/pdf/PDFFilter.java index c257f0da0..191e9bc66 100644 --- a/src/java/org/apache/fop/pdf/PDFFilter.java +++ b/src/java/org/apache/fop/pdf/PDFFilter.java @@ -19,8 +19,8 @@ package org.apache.fop.pdf; -import java.io.OutputStream; import java.io.IOException; +import java.io.OutputStream; /** * PDF Filter class. diff --git a/src/java/org/apache/fop/pdf/PDFGState.java b/src/java/org/apache/fop/pdf/PDFGState.java index 4b997a145..fe57e39c2 100644 --- a/src/java/org/apache/fop/pdf/PDFGState.java +++ b/src/java/org/apache/fop/pdf/PDFGState.java @@ -19,8 +19,8 @@ package org.apache.fop.pdf; -import java.util.Map; import java.util.Iterator; +import java.util.Map; /** * Class representing a /ExtGState object. diff --git a/src/java/org/apache/fop/pdf/PDFInfo.java b/src/java/org/apache/fop/pdf/PDFInfo.java index 14937bfd7..dabd88685 100644 --- a/src/java/org/apache/fop/pdf/PDFInfo.java +++ b/src/java/org/apache/fop/pdf/PDFInfo.java @@ -19,9 +19,9 @@ package org.apache.fop.pdf; -import java.util.Date; import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.util.Date; /** * class representing an /Info object diff --git a/src/java/org/apache/fop/pdf/PDFPages.java b/src/java/org/apache/fop/pdf/PDFPages.java index bef4bdbc4..1f09fbca6 100644 --- a/src/java/org/apache/fop/pdf/PDFPages.java +++ b/src/java/org/apache/fop/pdf/PDFPages.java @@ -19,9 +19,8 @@ package org.apache.fop.pdf; -// Java -import java.util.List; import java.util.ArrayList; +import java.util.List; /** * class representing a /Pages object. diff --git a/src/java/org/apache/fop/pdf/PDFPattern.java b/src/java/org/apache/fop/pdf/PDFPattern.java index 74f56377e..378b1cf8b 100644 --- a/src/java/org/apache/fop/pdf/PDFPattern.java +++ b/src/java/org/apache/fop/pdf/PDFPattern.java @@ -19,10 +19,9 @@ package org.apache.fop.pdf; -// Java -import java.util.List; -import java.io.OutputStream; import java.io.IOException; +import java.io.OutputStream; +import java.util.List; /** * class representing a PDF Function. diff --git a/src/java/org/apache/fop/pdf/PDFResources.java b/src/java/org/apache/fop/pdf/PDFResources.java index 317f703e1..70f9af504 100644 --- a/src/java/org/apache/fop/pdf/PDFResources.java +++ b/src/java/org/apache/fop/pdf/PDFResources.java @@ -28,6 +28,7 @@ import java.util.Map; import java.util.Set; import org.apache.xmlgraphics.java2d.color.profile.ColorProfileUtil; + import org.apache.fop.fonts.FontDescriptor; import org.apache.fop.fonts.FontInfo; import org.apache.fop.fonts.Typeface; diff --git a/src/java/org/apache/fop/pdf/StreamCache.java b/src/java/org/apache/fop/pdf/StreamCache.java index 95d21ab80..6fa687f23 100644 --- a/src/java/org/apache/fop/pdf/StreamCache.java +++ b/src/java/org/apache/fop/pdf/StreamCache.java @@ -19,8 +19,8 @@ package org.apache.fop.pdf; -import java.io.OutputStream; import java.io.IOException; +import java.io.OutputStream; /** * Interface used to store the bytes for a PDFStream. It's actually a generic diff --git a/src/java/org/apache/fop/pdf/TempFileStreamCache.java b/src/java/org/apache/fop/pdf/TempFileStreamCache.java index 9920a334d..18a7a8b29 100644 --- a/src/java/org/apache/fop/pdf/TempFileStreamCache.java +++ b/src/java/org/apache/fop/pdf/TempFileStreamCache.java @@ -19,13 +19,11 @@ package org.apache.fop.pdf; -// Java +import java.io.File; +import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.io.IOException; -import java.io.File; -//Commons import org.apache.commons.io.IOUtils; /** diff --git a/src/java/org/apache/fop/render/AbstractConfigurator.java b/src/java/org/apache/fop/render/AbstractConfigurator.java index 4adc1451e..c3c6733b0 100644 --- a/src/java/org/apache/fop/render/AbstractConfigurator.java +++ b/src/java/org/apache/fop/render/AbstractConfigurator.java @@ -21,8 +21,10 @@ package org.apache.fop.render; import org.apache.avalon.framework.configuration.Configuration; import org.apache.avalon.framework.configuration.ConfigurationException; + import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + import org.apache.fop.apps.FOUserAgent; /** diff --git a/src/java/org/apache/fop/render/XMLHandlerConfigurator.java b/src/java/org/apache/fop/render/XMLHandlerConfigurator.java index b93d4003a..604fdb672 100644 --- a/src/java/org/apache/fop/render/XMLHandlerConfigurator.java +++ b/src/java/org/apache/fop/render/XMLHandlerConfigurator.java @@ -21,8 +21,10 @@ package org.apache.fop.render; import org.apache.avalon.framework.configuration.Configuration; import org.apache.avalon.framework.configuration.ConfigurationException; + import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + import org.apache.fop.apps.FOPException; import org.apache.fop.apps.FOUserAgent; diff --git a/src/java/org/apache/fop/render/afp/AFPGraphics2DAdapter.java b/src/java/org/apache/fop/render/afp/AFPGraphics2DAdapter.java index becafda23..88734dfb8 100644 --- a/src/java/org/apache/fop/render/afp/AFPGraphics2DAdapter.java +++ b/src/java/org/apache/fop/render/afp/AFPGraphics2DAdapter.java @@ -25,6 +25,8 @@ import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; import java.io.IOException; +import org.apache.xmlgraphics.java2d.Graphics2DImagePainter; + import org.apache.fop.afp.AFPGraphics2D; import org.apache.fop.afp.AFPGraphicsObjectInfo; import org.apache.fop.afp.AFPPaintingState; @@ -32,7 +34,6 @@ import org.apache.fop.afp.AFPResourceManager; import org.apache.fop.render.AbstractGraphics2DAdapter; import org.apache.fop.render.RendererContext; import org.apache.fop.render.RendererContext.RendererContextWrapper; -import org.apache.xmlgraphics.java2d.Graphics2DImagePainter; /** * Graphics2DAdapter implementation for AFP. diff --git a/src/java/org/apache/fop/render/afp/AFPInfo.java b/src/java/org/apache/fop/render/afp/AFPInfo.java index 53a1aa046..db00d8ee4 100644 --- a/src/java/org/apache/fop/render/afp/AFPInfo.java +++ b/src/java/org/apache/fop/render/afp/AFPInfo.java @@ -20,6 +20,7 @@ package org.apache.fop.render.afp; import org.apache.avalon.framework.configuration.Configuration; + import org.apache.fop.afp.AFPGraphics2D; import org.apache.fop.afp.AFPPaintingState; import org.apache.fop.afp.AFPResourceInfo; diff --git a/src/java/org/apache/fop/render/afp/AFPPainter.java b/src/java/org/apache/fop/render/afp/AFPPainter.java index 30e4e7693..8b2f31555 100644 --- a/src/java/org/apache/fop/render/afp/AFPPainter.java +++ b/src/java/org/apache/fop/render/afp/AFPPainter.java @@ -30,6 +30,11 @@ import java.net.URI; import java.net.URISyntaxException; import java.util.Map; +import org.w3c.dom.Document; + +import org.apache.xmlgraphics.image.loader.ImageProcessingHints; +import org.apache.xmlgraphics.image.loader.ImageSessionContext; + import org.apache.fop.afp.AFPBorderPainter; import org.apache.fop.afp.AFPPaintingState; import org.apache.fop.afp.AFPUnitConverter; @@ -61,9 +66,6 @@ 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; -import org.apache.xmlgraphics.image.loader.ImageProcessingHints; -import org.apache.xmlgraphics.image.loader.ImageSessionContext; -import org.w3c.dom.Document; /** * IFPainter implementation that produces AFP (MO:DCA). diff --git a/src/java/org/apache/fop/render/afp/AFPRendererImageInfo.java b/src/java/org/apache/fop/render/afp/AFPRendererImageInfo.java index 2687d9071..c11c89217 100644 --- a/src/java/org/apache/fop/render/afp/AFPRendererImageInfo.java +++ b/src/java/org/apache/fop/render/afp/AFPRendererImageInfo.java @@ -23,10 +23,11 @@ import java.awt.Point; import java.awt.geom.Rectangle2D; import java.util.Map; -import org.apache.fop.render.RendererContext; import org.apache.xmlgraphics.image.loader.Image; import org.apache.xmlgraphics.image.loader.ImageInfo; +import org.apache.fop.render.RendererContext; + /** * The AFP image information */ diff --git a/src/java/org/apache/fop/render/afp/extensions/AFPExtensionHandlerFactory.java b/src/java/org/apache/fop/render/afp/extensions/AFPExtensionHandlerFactory.java index e987866df..cc12ed9f4 100644 --- a/src/java/org/apache/fop/render/afp/extensions/AFPExtensionHandlerFactory.java +++ b/src/java/org/apache/fop/render/afp/extensions/AFPExtensionHandlerFactory.java @@ -19,9 +19,10 @@ package org.apache.fop.render.afp.extensions; -import org.apache.fop.util.ContentHandlerFactory; import org.xml.sax.ContentHandler; +import org.apache.fop.util.ContentHandlerFactory; + /** * Factory for the ContentHandler that handles serialized AFPPageSetup instances. */ diff --git a/src/java/org/apache/fop/render/afp/extensions/AFPPageOverlayElement.java b/src/java/org/apache/fop/render/afp/extensions/AFPPageOverlayElement.java index 7d2f2f7d3..0b9645236 100644 --- a/src/java/org/apache/fop/render/afp/extensions/AFPPageOverlayElement.java +++ b/src/java/org/apache/fop/render/afp/extensions/AFPPageOverlayElement.java @@ -22,14 +22,15 @@ package org.apache.fop.render.afp.extensions; import org.xml.sax.Attributes; import org.xml.sax.Locator; +import org.apache.xmlgraphics.util.UnitConv; + +import org.apache.fop.afp.AFPPaintingState; +import org.apache.fop.afp.AFPUnitConverter; import org.apache.fop.apps.FOPException; 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.afp.AFPPaintingState; -import org.apache.fop.afp.AFPUnitConverter; -import org.apache.xmlgraphics.util.UnitConv; /** * This class extends the org.apache.fop.render.afp.extensions.AbstractAFPExtensionObject class. diff --git a/src/java/org/apache/fop/render/awt/viewer/Command.java b/src/java/org/apache/fop/render/awt/viewer/Command.java index ef6559a11..f989eaf33 100644 --- a/src/java/org/apache/fop/render/awt/viewer/Command.java +++ b/src/java/org/apache/fop/render/awt/viewer/Command.java @@ -19,11 +19,11 @@ package org.apache.fop.render.awt.viewer; -//Java import java.awt.event.ActionEvent; +import java.net.URL; + import javax.swing.AbstractAction; import javax.swing.ImageIcon; -import java.net.URL; /** * This class represents UI-commands, which can be used as menu or toolbar diff --git a/src/java/org/apache/fop/render/awt/viewer/GoToPageDialog.java b/src/java/org/apache/fop/render/awt/viewer/GoToPageDialog.java index 0ff71be67..599a7d788 100644 --- a/src/java/org/apache/fop/render/awt/viewer/GoToPageDialog.java +++ b/src/java/org/apache/fop/render/awt/viewer/GoToPageDialog.java @@ -24,6 +24,8 @@ import java.awt.Frame; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; import javax.swing.JButton; import javax.swing.JDialog; @@ -31,9 +33,6 @@ import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JTextField; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; - /** * Go to Page Dialog. * Originally contributed by: diff --git a/src/java/org/apache/fop/render/awt/viewer/ImageProxyPanel.java b/src/java/org/apache/fop/render/awt/viewer/ImageProxyPanel.java index 9b3cac0a0..d0d35e84b 100644 --- a/src/java/org/apache/fop/render/awt/viewer/ImageProxyPanel.java +++ b/src/java/org/apache/fop/render/awt/viewer/ImageProxyPanel.java @@ -25,6 +25,7 @@ import java.awt.Insets; import java.awt.image.BufferedImage; import java.lang.ref.Reference; import java.lang.ref.SoftReference; + import javax.swing.JPanel; import org.apache.fop.apps.FOPException; diff --git a/src/java/org/apache/fop/render/awt/viewer/PreviewDialogAboutBox.java b/src/java/org/apache/fop/render/awt/viewer/PreviewDialogAboutBox.java index b76675179..53cd585c9 100644 --- a/src/java/org/apache/fop/render/awt/viewer/PreviewDialogAboutBox.java +++ b/src/java/org/apache/fop/render/awt/viewer/PreviewDialogAboutBox.java @@ -19,24 +19,22 @@ package org.apache.fop.render.awt.viewer; -//Java import java.awt.AWTEvent; import java.awt.BorderLayout; import java.awt.Dialog; import java.awt.FlowLayout; import java.awt.Frame; import java.awt.GridLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.WindowEvent; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.border.EmptyBorder; -import java.awt.event.ActionListener; -import java.awt.event.WindowEvent; -import java.awt.event.ActionEvent; -//FOP import org.apache.fop.Version; /** diff --git a/src/java/org/apache/fop/render/awt/viewer/Translator.java b/src/java/org/apache/fop/render/awt/viewer/Translator.java index df07a987f..538c2cd59 100644 --- a/src/java/org/apache/fop/render/awt/viewer/Translator.java +++ b/src/java/org/apache/fop/render/awt/viewer/Translator.java @@ -19,9 +19,8 @@ package org.apache.fop.render.awt.viewer; -//Java -import java.util.ResourceBundle; import java.util.Locale; +import java.util.ResourceBundle; /** * AWT Viewer's localization class, backed up by java.util.ResourceBundle. diff --git a/src/java/org/apache/fop/render/intermediate/IFRenderer.java b/src/java/org/apache/fop/render/intermediate/IFRenderer.java index 5940fb661..ba308eadb 100644 --- a/src/java/org/apache/fop/render/intermediate/IFRenderer.java +++ b/src/java/org/apache/fop/render/intermediate/IFRenderer.java @@ -39,10 +39,11 @@ import javax.xml.transform.stream.StreamResult; import org.w3c.dom.Document; import org.xml.sax.SAXException; -import org.apache.batik.parser.AWTTransformProducer; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.apache.batik.parser.AWTTransformProducer; + import org.apache.xmlgraphics.xmp.Metadata; import org.apache.xmlgraphics.xmp.schemas.DublinCoreAdapter; import org.apache.xmlgraphics.xmp.schemas.DublinCoreSchema; diff --git a/src/java/org/apache/fop/render/java2d/InstalledFontCollection.java b/src/java/org/apache/fop/render/java2d/InstalledFontCollection.java index 65e82f7b3..afb22a883 100644 --- a/src/java/org/apache/fop/render/java2d/InstalledFontCollection.java +++ b/src/java/org/apache/fop/render/java2d/InstalledFontCollection.java @@ -24,6 +24,7 @@ import java.util.Set; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + 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/Java2DRendererConfigurator.java b/src/java/org/apache/fop/render/java2d/Java2DRendererConfigurator.java index 0709d4ea9..a12cb3898 100644 --- a/src/java/org/apache/fop/render/java2d/Java2DRendererConfigurator.java +++ b/src/java/org/apache/fop/render/java2d/Java2DRendererConfigurator.java @@ -20,6 +20,7 @@ package org.apache.fop.render.java2d; import org.apache.avalon.framework.configuration.Configuration; + import org.apache.fop.apps.FOPException; import org.apache.fop.apps.FOUserAgent; import org.apache.fop.render.PrintRendererConfigurator; diff --git a/src/java/org/apache/fop/render/java2d/Java2DSVGHandler.java b/src/java/org/apache/fop/render/java2d/Java2DSVGHandler.java index 4c20a8959..9227e678a 100644 --- a/src/java/org/apache/fop/render/java2d/Java2DSVGHandler.java +++ b/src/java/org/apache/fop/render/java2d/Java2DSVGHandler.java @@ -25,11 +25,12 @@ import java.util.Map; import org.w3c.dom.Document; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + import org.apache.batik.bridge.BridgeContext; import org.apache.batik.bridge.GVTBuilder; import org.apache.batik.gvt.GraphicsNode; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; import org.apache.fop.image.loader.batik.BatikUtil; import org.apache.fop.render.AbstractGenericSVGHandler; diff --git a/src/java/org/apache/fop/render/pdf/PDFImageHandlerSVG.java b/src/java/org/apache/fop/render/pdf/PDFImageHandlerSVG.java index b5b13e935..bc3b66ece 100644 --- a/src/java/org/apache/fop/render/pdf/PDFImageHandlerSVG.java +++ b/src/java/org/apache/fop/render/pdf/PDFImageHandlerSVG.java @@ -26,13 +26,14 @@ import java.io.IOException; import org.w3c.dom.Document; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + import org.apache.batik.bridge.BridgeContext; import org.apache.batik.bridge.GVTBuilder; import org.apache.batik.dom.svg.SVGDOMImplementation; import org.apache.batik.gvt.GraphicsNode; import org.apache.batik.util.SVGConstants; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; import org.apache.xmlgraphics.image.loader.Image; import org.apache.xmlgraphics.image.loader.ImageFlavor; diff --git a/src/java/org/apache/fop/render/ps/FontResourceCache.java b/src/java/org/apache/fop/render/ps/FontResourceCache.java index 086117536..9d4090eed 100644 --- a/src/java/org/apache/fop/render/ps/FontResourceCache.java +++ b/src/java/org/apache/fop/render/ps/FontResourceCache.java @@ -21,10 +21,11 @@ package org.apache.fop.render.ps; import java.util.Map; +import org.apache.xmlgraphics.ps.PSResource; + import org.apache.fop.fonts.FontInfo; import org.apache.fop.fonts.LazyFont; import org.apache.fop.fonts.Typeface; -import org.apache.xmlgraphics.ps.PSResource; /** * A cache for font resource objects. diff --git a/src/java/org/apache/fop/render/ps/PSFontUtils.java b/src/java/org/apache/fop/render/ps/PSFontUtils.java index b8d1b63e8..5e95b5ded 100644 --- a/src/java/org/apache/fop/render/ps/PSFontUtils.java +++ b/src/java/org/apache/fop/render/ps/PSFontUtils.java @@ -30,6 +30,13 @@ import javax.xml.transform.stream.StreamSource; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + +import org.apache.xmlgraphics.fonts.Glyphs; +import org.apache.xmlgraphics.ps.DSCConstants; +import org.apache.xmlgraphics.ps.PSGenerator; +import org.apache.xmlgraphics.ps.PSResource; +import org.apache.xmlgraphics.ps.dsc.ResourceTracker; + import org.apache.fop.fonts.Base14Font; import org.apache.fop.fonts.CustomFont; import org.apache.fop.fonts.Font; @@ -39,11 +46,6 @@ import org.apache.fop.fonts.LazyFont; import org.apache.fop.fonts.SingleByteEncoding; import org.apache.fop.fonts.SingleByteFont; import org.apache.fop.fonts.Typeface; -import org.apache.xmlgraphics.fonts.Glyphs; -import org.apache.xmlgraphics.ps.DSCConstants; -import org.apache.xmlgraphics.ps.PSGenerator; -import org.apache.xmlgraphics.ps.PSResource; -import org.apache.xmlgraphics.ps.dsc.ResourceTracker; /** * Utility code for font handling in PostScript. diff --git a/src/java/org/apache/fop/render/ps/PSGraphics2DAdapter.java b/src/java/org/apache/fop/render/ps/PSGraphics2DAdapter.java index e13591ae3..d55e0960a 100644 --- a/src/java/org/apache/fop/render/ps/PSGraphics2DAdapter.java +++ b/src/java/org/apache/fop/render/ps/PSGraphics2DAdapter.java @@ -34,8 +34,8 @@ import org.apache.fop.pdf.PDFFactory; import org.apache.fop.render.AbstractGraphics2DAdapter; import org.apache.fop.render.ImageHandlerUtil; import org.apache.fop.render.RendererContext; -import org.apache.fop.render.RendererContextConstants; import org.apache.fop.render.RendererContext.RendererContextWrapper; +import org.apache.fop.render.RendererContextConstants; /** * Graphics2DAdapter implementation for PostScript. diff --git a/src/java/org/apache/fop/render/ps/PSImageHandlerGraphics2D.java b/src/java/org/apache/fop/render/ps/PSImageHandlerGraphics2D.java index 9bbd3e62b..3293840e5 100644 --- a/src/java/org/apache/fop/render/ps/PSImageHandlerGraphics2D.java +++ b/src/java/org/apache/fop/render/ps/PSImageHandlerGraphics2D.java @@ -26,7 +26,6 @@ import java.awt.geom.Dimension2D; import java.awt.geom.Rectangle2D; import java.io.IOException; -import org.apache.fop.render.RenderingContext; import org.apache.xmlgraphics.image.loader.Image; import org.apache.xmlgraphics.image.loader.ImageFlavor; import org.apache.xmlgraphics.image.loader.ImageInfo; @@ -37,6 +36,8 @@ import org.apache.xmlgraphics.ps.FormGenerator; import org.apache.xmlgraphics.ps.PSGenerator; import org.apache.xmlgraphics.ps.PSProcSets; +import org.apache.fop.render.RenderingContext; + /** * Image handler implementation which handles vector graphics (Java2D) for PostScript output. */ diff --git a/src/java/org/apache/fop/render/ps/PSSVGHandler.java b/src/java/org/apache/fop/render/ps/PSSVGHandler.java index 14e2beddd..c52f45332 100644 --- a/src/java/org/apache/fop/render/ps/PSSVGHandler.java +++ b/src/java/org/apache/fop/render/ps/PSSVGHandler.java @@ -27,6 +27,7 @@ import java.util.Map; import org.w3c.dom.Document; import org.apache.avalon.framework.configuration.Configuration; + import org.apache.batik.bridge.BridgeContext; import org.apache.batik.bridge.GVTBuilder; import org.apache.batik.gvt.GraphicsNode; diff --git a/src/java/org/apache/fop/render/ps/extensions/AbstractPSExtensionObject.java b/src/java/org/apache/fop/render/ps/extensions/AbstractPSExtensionObject.java index d5aea37df..d097e7b5e 100644 --- a/src/java/org/apache/fop/render/ps/extensions/AbstractPSExtensionObject.java +++ b/src/java/org/apache/fop/render/ps/extensions/AbstractPSExtensionObject.java @@ -19,14 +19,14 @@ package org.apache.fop.render.ps.extensions; -// FOP +import org.xml.sax.Attributes; +import org.xml.sax.Locator; + import org.apache.fop.apps.FOPException; import org.apache.fop.fo.FONode; import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.ValidationException; import org.apache.fop.fo.extensions.ExtensionAttachment; -import org.xml.sax.Attributes; -import org.xml.sax.Locator; /** * Base class for the PostScript-specific extension elements. diff --git a/src/java/org/apache/fop/render/ps/extensions/PSExtensionElementMapping.java b/src/java/org/apache/fop/render/ps/extensions/PSExtensionElementMapping.java index 54806d047..00d0594f2 100644 --- a/src/java/org/apache/fop/render/ps/extensions/PSExtensionElementMapping.java +++ b/src/java/org/apache/fop/render/ps/extensions/PSExtensionElementMapping.java @@ -19,8 +19,8 @@ package org.apache.fop.render.ps.extensions; -import org.apache.fop.fo.FONode; import org.apache.fop.fo.ElementMapping; +import org.apache.fop.fo.FONode; /** * This class provides the element mapping for the PostScript-specific extensions. diff --git a/src/java/org/apache/fop/render/ps/extensions/PSExtensionHandlerFactory.java b/src/java/org/apache/fop/render/ps/extensions/PSExtensionHandlerFactory.java index d94e236f7..736246dfb 100644 --- a/src/java/org/apache/fop/render/ps/extensions/PSExtensionHandlerFactory.java +++ b/src/java/org/apache/fop/render/ps/extensions/PSExtensionHandlerFactory.java @@ -19,9 +19,10 @@ package org.apache.fop.render.ps.extensions; -import org.apache.fop.util.ContentHandlerFactory; import org.xml.sax.ContentHandler; +import org.apache.fop.util.ContentHandlerFactory; + /** * Factory for the ContentHandler that handles serialized PSSetupCode instances. */ diff --git a/src/java/org/apache/fop/render/rtf/FOPRtfAttributes.java b/src/java/org/apache/fop/render/rtf/FOPRtfAttributes.java index 5cc752d30..3ffed6ba0 100644 --- a/src/java/org/apache/fop/render/rtf/FOPRtfAttributes.java +++ b/src/java/org/apache/fop/render/rtf/FOPRtfAttributes.java @@ -20,6 +20,7 @@ package org.apache.fop.render.rtf; import java.awt.Color; + import org.apache.fop.datatypes.Length; import org.apache.fop.render.DummyPercentBaseContext; import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfAttributes; diff --git a/src/java/org/apache/fop/render/rtf/FoUnitsConverter.java b/src/java/org/apache/fop/render/rtf/FoUnitsConverter.java index 8540fcde3..647b3f53b 100644 --- a/src/java/org/apache/fop/render/rtf/FoUnitsConverter.java +++ b/src/java/org/apache/fop/render/rtf/FoUnitsConverter.java @@ -22,9 +22,10 @@ package org.apache.fop.render.rtf; import java.util.HashMap; import java.util.Map; +import org.apache.xmlgraphics.util.UnitConv; + import org.apache.fop.apps.FOPException; import org.apache.fop.fo.properties.FixedLength; -import org.apache.xmlgraphics.util.UnitConv; /** Converts XSL-FO units to RTF units diff --git a/src/java/org/apache/fop/render/rtf/TableAttributesConverter.java b/src/java/org/apache/fop/render/rtf/TableAttributesConverter.java index 2944b230a..a9be38d16 100644 --- a/src/java/org/apache/fop/render/rtf/TableAttributesConverter.java +++ b/src/java/org/apache/fop/render/rtf/TableAttributesConverter.java @@ -24,9 +24,9 @@ import java.awt.Color; import org.apache.fop.apps.FOPException; import org.apache.fop.fo.Constants; import org.apache.fop.fo.flow.table.Table; -import org.apache.fop.fo.flow.table.TablePart; import org.apache.fop.fo.flow.table.TableCell; import org.apache.fop.fo.flow.table.TableHeader; +import org.apache.fop.fo.flow.table.TablePart; import org.apache.fop.fo.flow.table.TableRow; import org.apache.fop.fo.properties.CommonBorderPaddingBackground; import org.apache.fop.render.rtf.rtflib.rtfdoc.ITableAttributes; diff --git a/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfAfter.java b/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfAfter.java index 078439306..f081bd2ee 100644 --- a/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfAfter.java +++ b/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfAfter.java @@ -26,8 +26,8 @@ package org.apache.fop.render.rtf.rtflib.rtfdoc; * the FOP project. */ -import java.io.Writer; import java.io.IOException; +import java.io.Writer; /** RtfContainer that encloses footers */ public class RtfAfter extends RtfAfterBeforeBase { diff --git a/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfAfterBeforeBase.java b/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfAfterBeforeBase.java index 5fbde8d3e..6038ebfdd 100644 --- a/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfAfterBeforeBase.java +++ b/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfAfterBeforeBase.java @@ -26,8 +26,8 @@ package org.apache.fop.render.rtf.rtflib.rtfdoc; * the FOP project. */ -import java.io.Writer; import java.io.IOException; +import java.io.Writer; /** Common code for RtfAfter and RtfBefore * @author Andreas Lambert diff --git a/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfBefore.java b/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfBefore.java index 0828be238..415b70b7d 100644 --- a/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfBefore.java +++ b/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfBefore.java @@ -26,8 +26,8 @@ package org.apache.fop.render.rtf.rtflib.rtfdoc; * the FOP project. */ -import java.io.Writer; import java.io.IOException; +import java.io.Writer; /** The opposite of RtfAfter */ public class RtfBefore extends RtfAfterBeforeBase { diff --git a/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfBookmark.java b/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfBookmark.java index 7da14061e..714026848 100644 --- a/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfBookmark.java +++ b/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfBookmark.java @@ -26,8 +26,8 @@ package org.apache.fop.render.rtf.rtflib.rtfdoc; * the FOP project. */ -import java.io.Writer; import java.io.IOException; +import java.io.Writer; /** * RTF Bookmark. diff --git a/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfBookmarkContainerImpl.java b/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfBookmarkContainerImpl.java index 3eee4cd71..b8bcc5614 100644 --- a/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfBookmarkContainerImpl.java +++ b/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfBookmarkContainerImpl.java @@ -26,8 +26,8 @@ package org.apache.fop.render.rtf.rtflib.rtfdoc; * the FOP project. */ -import java.io.Writer; import java.io.IOException; +import java.io.Writer; /** * RTF Bookmark container implementation. diff --git a/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfColorTable.java b/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfColorTable.java index 8df7bd7b2..118c810e0 100644 --- a/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfColorTable.java +++ b/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfColorTable.java @@ -26,9 +26,9 @@ package org.apache.fop.render.rtf.rtflib.rtfdoc; * the FOP project. */ -import java.util.Vector; -import java.util.Hashtable; import java.io.IOException; +import java.util.Hashtable; +import java.util.Vector; /** * Singelton of the RTF color table. diff --git a/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfContainer.java b/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfContainer.java index 5a6b1d6ed..b138f722b 100644 --- a/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfContainer.java +++ b/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfContainer.java @@ -26,11 +26,12 @@ package org.apache.fop.render.rtf.rtflib.rtfdoc; * the FOP project. */ +import java.io.IOException; import java.io.Writer; +import java.util.Iterator; import java.util.LinkedList; import java.util.List; -import java.util.Iterator; -import java.io.IOException; + import org.apache.fop.render.rtf.rtflib.exceptions.RtfStructureException; /** An RtfElement that can contain other elements. diff --git a/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfDocumentArea.java b/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfDocumentArea.java index 6204e2ac2..c94f24554 100644 --- a/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfDocumentArea.java +++ b/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfDocumentArea.java @@ -26,8 +26,8 @@ package org.apache.fop.render.rtf.rtflib.rtfdoc; * the FOP project. */ -import java.io.Writer; import java.io.IOException; +import java.io.Writer; /** The RTF document area, container for RtfSection objects. * @author Bertrand Delacretaz bdelacretaz@codeconsult.ch diff --git a/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfElement.java b/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfElement.java index 3f1e2f7e1..424fd22b1 100644 --- a/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfElement.java +++ b/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfElement.java @@ -26,10 +26,9 @@ package org.apache.fop.render.rtf.rtflib.rtfdoc; * the FOP project. */ -import java.io.Writer; import java.io.IOException; +import java.io.Writer; import java.util.Iterator; -//import org.apache.fop.render.rtf.rtflib.jfor.main.JForVersionInfo; /** Base class for all elements of an RTF file. * @author Bertrand Delacretaz bdelacretaz@codeconsult.ch diff --git a/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfExtraRowSet.java b/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfExtraRowSet.java index c08008fee..42888ee59 100644 --- a/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfExtraRowSet.java +++ b/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfExtraRowSet.java @@ -26,12 +26,12 @@ package org.apache.fop.render.rtf.rtflib.rtfdoc; * the FOP project. */ -import java.io.Writer; import java.io.IOException; -import java.util.List; -import java.util.LinkedList; -import java.util.Iterator; +import java.io.Writer; import java.util.Collections; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; /** diff --git a/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfFile.java b/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfFile.java index 9376f5564..de29afd2a 100644 --- a/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfFile.java +++ b/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfFile.java @@ -26,12 +26,13 @@ package org.apache.fop.render.rtf.rtflib.rtfdoc; * the FOP project. */ -import org.apache.fop.render.rtf.rtflib.exceptions.RtfStructureException; -import java.io.Writer; -import java.io.IOException; import java.io.BufferedWriter; import java.io.FileWriter; +import java.io.IOException; import java.io.OutputStreamWriter; +import java.io.Writer; + +import org.apache.fop.render.rtf.rtflib.exceptions.RtfStructureException; /** * Models the top-level structure of an RTF file. diff --git a/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfFontTable.java b/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfFontTable.java index c64f27377..236919c96 100644 --- a/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfFontTable.java +++ b/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfFontTable.java @@ -26,8 +26,8 @@ package org.apache.fop.render.rtf.rtflib.rtfdoc; * the FOP project. */ -import java.io.Writer; import java.io.IOException; +import java.io.Writer; /** RTF font table * @author Bertrand Delacretaz bdelacretaz@codeconsult.ch diff --git a/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfFootnote.java b/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfFootnote.java index d7ab4c716..394d12680 100644 --- a/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfFootnote.java +++ b/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfFootnote.java @@ -19,9 +19,8 @@ package org.apache.fop.render.rtf.rtflib.rtfdoc; -//Java -import java.io.Writer; import java.io.IOException; +import java.io.Writer; /** Model of an RTF footnote * @author Peter Herweg, pherweg@web.de diff --git a/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfHeader.java b/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfHeader.java index 2554cad38..b093eab49 100644 --- a/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfHeader.java +++ b/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfHeader.java @@ -26,12 +26,11 @@ package org.apache.fop.render.rtf.rtflib.rtfdoc; * the FOP project. */ -import java.util.Map; +import java.io.IOException; +import java.io.Writer; import java.util.HashMap; import java.util.Iterator; -import java.io.Writer; -import java.io.IOException; -//import org.apache.fop.render.rtf.rtflib.jfor.main.JForVersionInfo; +import java.util.Map; /** RTF file header, contains style, font and other document-level information. * @author Bertrand Delacretaz bdelacretaz@codeconsult.ch diff --git a/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfHyperLink.java b/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfHyperLink.java index a021948ab..6e0028b55 100644 --- a/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfHyperLink.java +++ b/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfHyperLink.java @@ -26,8 +26,8 @@ package org.apache.fop.render.rtf.rtflib.rtfdoc; * the FOP project. */ -import java.io.Writer; import java.io.IOException; +import java.io.Writer; /** * Creates an hyperlink. diff --git a/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfJforCmd.java b/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfJforCmd.java index b9e53d42f..c52ccb959 100644 --- a/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfJforCmd.java +++ b/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfJforCmd.java @@ -26,9 +26,9 @@ package org.apache.fop.render.rtf.rtflib.rtfdoc; * the FOP project. */ +import java.io.IOException; import java.io.Writer; import java.util.Iterator; -import java.io.IOException; /** * Process "jfor-cmd" diff --git a/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfLineBreak.java b/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfLineBreak.java index 4073302ce..2b1db99ce 100644 --- a/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfLineBreak.java +++ b/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfLineBreak.java @@ -26,8 +26,8 @@ package org.apache.fop.render.rtf.rtflib.rtfdoc; * the FOP project. */ -import java.io.Writer; import java.io.IOException; +import java.io.Writer; /** "Model" of an RTF line break * @author Bertrand Delacretaz bdelacretaz@codeconsult.ch diff --git a/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfListItem.java b/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfListItem.java index 53af6940f..13628a49d 100644 --- a/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfListItem.java +++ b/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfListItem.java @@ -26,8 +26,8 @@ package org.apache.fop.render.rtf.rtflib.rtfdoc; * the FOP project. */ -import java.io.Writer; import java.io.IOException; +import java.io.Writer; /** Model of an RTF list item, which can contain RTF paragraphs * @author Bertrand Delacretaz bdelacretaz@codeconsult.ch diff --git a/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfListTable.java b/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfListTable.java index aeb9618f4..7bdda21a0 100644 --- a/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfListTable.java +++ b/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfListTable.java @@ -26,11 +26,10 @@ package org.apache.fop.render.rtf.rtflib.rtfdoc; * the FOP project. */ -import java.util.LinkedList; -import java.util.Iterator; -import java.io.Writer; import java.io.IOException; -//import org.apache.fop.render.rtf.rtflib.jfor.main.JForVersionInfo; +import java.io.Writer; +import java.util.Iterator; +import java.util.LinkedList; /** * RtfListTable: used to make the list table in the header section of the RtfFile. diff --git a/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfNull.java b/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfNull.java index 4e6e08291..bd44ae2ba 100644 --- a/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfNull.java +++ b/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfNull.java @@ -26,8 +26,8 @@ package org.apache.fop.render.rtf.rtflib.rtfdoc; * the FOP project. */ -import java.io.Writer; import java.io.IOException; +import java.io.Writer; /** * @author Christopher Scott, scottc@westinghouse.com diff --git a/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfPageArea.java b/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfPageArea.java index 851dc6c87..0696a70c0 100644 --- a/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfPageArea.java +++ b/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfPageArea.java @@ -26,8 +26,8 @@ package org.apache.fop.render.rtf.rtflib.rtfdoc; * the FOP project. */ -import java.io.Writer; import java.io.IOException; +import java.io.Writer; /** * @author Christopher Scott, scottc@westinghouse.com diff --git a/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfPageBreak.java b/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfPageBreak.java index b570842c2..b386c7c0f 100644 --- a/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfPageBreak.java +++ b/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfPageBreak.java @@ -26,8 +26,8 @@ package org.apache.fop.render.rtf.rtflib.rtfdoc; * the FOP project. */ -import java.io.Writer; import java.io.IOException; +import java.io.Writer; /** "Model" of an RTF page break * @author Bertrand Delacretaz bdelacretaz@codeconsult.ch diff --git a/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfPageNumber.java b/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfPageNumber.java index 235b3f8e1..ad2984b9b 100644 --- a/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfPageNumber.java +++ b/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfPageNumber.java @@ -26,8 +26,8 @@ package org.apache.fop.render.rtf.rtflib.rtfdoc; * the FOP project. */ -import java.io.Writer; import java.io.IOException; +import java.io.Writer; /** * @author Christopher Scott, scottc@westinghouse.com diff --git a/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfParagraph.java b/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfParagraph.java index ffc37a667..a4ad8e8f4 100644 --- a/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfParagraph.java +++ b/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfParagraph.java @@ -26,8 +26,8 @@ package org.apache.fop.render.rtf.rtflib.rtfdoc; * the FOP project. */ -import java.io.Writer; import java.io.IOException; +import java.io.Writer; import java.util.List; /** Model of an RTF paragraph, which can contain RTF text elements. diff --git a/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfParagraphKeepTogether.java b/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfParagraphKeepTogether.java index e27ab6460..d682626ec 100644 --- a/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfParagraphKeepTogether.java +++ b/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfParagraphKeepTogether.java @@ -26,8 +26,8 @@ package org.apache.fop.render.rtf.rtflib.rtfdoc; * the FOP project. */ -import java.io.Writer; import java.io.IOException; +import java.io.Writer; /** * Models the keep together attributes of paragraphs diff --git a/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfSection.java b/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfSection.java index 4b7f8f677..88ab8ec2d 100644 --- a/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfSection.java +++ b/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfSection.java @@ -26,8 +26,8 @@ package org.apache.fop.render.rtf.rtflib.rtfdoc; * the FOP project. */ -import java.io.Writer; import java.io.IOException; +import java.io.Writer; /** Models a section in an RTF document * @author Bertrand Delacretaz bdelacretaz@codeconsult.ch diff --git a/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfStringConverter.java b/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfStringConverter.java index 9afe35b29..d7774f2ed 100644 --- a/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfStringConverter.java +++ b/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfStringConverter.java @@ -26,10 +26,10 @@ package org.apache.fop.render.rtf.rtflib.rtfdoc; * the FOP project. */ -import java.util.Map; -import java.util.HashMap; import java.io.IOException; import java.io.Writer; +import java.util.HashMap; +import java.util.Map; /** Converts java Strings according to RTF conventions * @author Bertrand Delacretaz bdelacretaz@codeconsult.ch diff --git a/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfStyleSheetTable.java b/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfStyleSheetTable.java index 30dee96d7..678508607 100644 --- a/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfStyleSheetTable.java +++ b/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfStyleSheetTable.java @@ -26,10 +26,10 @@ package org.apache.fop.render.rtf.rtflib.rtfdoc; * the FOP project. */ -import java.util.Vector; -import java.util.Hashtable; import java.io.IOException; +import java.util.Hashtable; import java.util.Iterator; +import java.util.Vector; /** * Singelton of the RTF style sheet table. diff --git a/src/java/org/apache/fop/render/rtf/rtflib/tools/TableContext.java b/src/java/org/apache/fop/render/rtf/rtflib/tools/TableContext.java index 96d65ad12..3cdd454f5 100644 --- a/src/java/org/apache/fop/render/rtf/rtflib/tools/TableContext.java +++ b/src/java/org/apache/fop/render/rtf/rtflib/tools/TableContext.java @@ -21,8 +21,9 @@ package org.apache.fop.render.rtf.rtflib.tools; import java.util.List; -import org.apache.commons.logging.impl.SimpleLog; import org.apache.commons.logging.Log; +import org.apache.commons.logging.impl.SimpleLog; + import org.apache.fop.render.rtf.rtflib.rtfdoc.ITableColumnsInfo; import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfAttributes; diff --git a/src/java/org/apache/fop/render/txt/TXTRendererConfigurator.java b/src/java/org/apache/fop/render/txt/TXTRendererConfigurator.java index f2c47735f..59c3bf5e6 100644 --- a/src/java/org/apache/fop/render/txt/TXTRendererConfigurator.java +++ b/src/java/org/apache/fop/render/txt/TXTRendererConfigurator.java @@ -20,6 +20,7 @@ package org.apache.fop.render.txt; import org.apache.avalon.framework.configuration.Configuration; + import org.apache.fop.apps.FOPException; import org.apache.fop.apps.FOUserAgent; import org.apache.fop.render.PrintRendererConfigurator; diff --git a/src/java/org/apache/fop/render/xml/XMLXMLHandler.java b/src/java/org/apache/fop/render/xml/XMLXMLHandler.java index d1cf1cf9a..65a3aa026 100644 --- a/src/java/org/apache/fop/render/xml/XMLXMLHandler.java +++ b/src/java/org/apache/fop/render/xml/XMLXMLHandler.java @@ -19,13 +19,13 @@ package org.apache.fop.render.xml; +import org.xml.sax.ContentHandler; + import org.apache.fop.render.Renderer; -import org.apache.fop.render.XMLHandler; import org.apache.fop.render.RendererContext; +import org.apache.fop.render.XMLHandler; import org.apache.fop.util.DOM2SAX; -import org.xml.sax.ContentHandler; - /** * XML handler for the XML renderer. */ diff --git a/src/java/org/apache/fop/servlet/FopPrintServlet.java b/src/java/org/apache/fop/servlet/FopPrintServlet.java index 5c243ecae..3972b6fec 100644 --- a/src/java/org/apache/fop/servlet/FopPrintServlet.java +++ b/src/java/org/apache/fop/servlet/FopPrintServlet.java @@ -24,10 +24,10 @@ import java.io.PrintWriter; import javax.servlet.http.HttpServletResponse; -import javax.xml.transform.Transformer; -import javax.xml.transform.TransformerException; import javax.xml.transform.Result; import javax.xml.transform.Source; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerException; import javax.xml.transform.sax.SAXResult; import org.apache.fop.apps.FOPException; diff --git a/src/java/org/apache/fop/svg/ACIUtils.java b/src/java/org/apache/fop/svg/ACIUtils.java index 91361432a..64552b303 100644 --- a/src/java/org/apache/fop/svg/ACIUtils.java +++ b/src/java/org/apache/fop/svg/ACIUtils.java @@ -21,19 +21,20 @@ package org.apache.fop.svg; import java.awt.font.TextAttribute; import java.text.AttributedCharacterIterator; -import java.text.CharacterIterator; import java.text.AttributedCharacterIterator.Attribute; +import java.text.CharacterIterator; import java.util.List; import java.util.Map; -import java.util.Set; import java.util.Map.Entry; +import java.util.Set; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.apache.batik.bridge.SVGFontFamily; import org.apache.batik.gvt.font.GVTFont; import org.apache.batik.gvt.font.GVTFontFamily; import org.apache.batik.gvt.text.GVTAttributedCharacterIterator; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; import org.apache.fop.fonts.Font; import org.apache.fop.fonts.FontInfo; diff --git a/src/java/org/apache/fop/svg/AbstractFOPTextPainter.java b/src/java/org/apache/fop/svg/AbstractFOPTextPainter.java index 77179b381..49f5a1b75 100644 --- a/src/java/org/apache/fop/svg/AbstractFOPTextPainter.java +++ b/src/java/org/apache/fop/svg/AbstractFOPTextPainter.java @@ -33,6 +33,9 @@ import java.text.CharacterIterator; import java.util.Iterator; import java.util.List; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + import org.apache.batik.dom.svg.SVGOMTextElement; import org.apache.batik.gvt.TextNode; import org.apache.batik.gvt.TextPainter; @@ -40,8 +43,6 @@ import org.apache.batik.gvt.renderer.StrokingTextPainter; import org.apache.batik.gvt.text.GVTAttributedCharacterIterator; import org.apache.batik.gvt.text.Mark; import org.apache.batik.gvt.text.TextPaintInfo; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; import org.apache.fop.afp.AFPGraphics2D; import org.apache.fop.fonts.Font; diff --git a/src/java/org/apache/fop/svg/AbstractFOPTranscoder.java b/src/java/org/apache/fop/svg/AbstractFOPTranscoder.java index c079a80e3..e04bf0d35 100644 --- a/src/java/org/apache/fop/svg/AbstractFOPTranscoder.java +++ b/src/java/org/apache/fop/svg/AbstractFOPTranscoder.java @@ -32,6 +32,10 @@ import org.apache.avalon.framework.configuration.Configurable; import org.apache.avalon.framework.configuration.Configuration; import org.apache.avalon.framework.configuration.ConfigurationException; import org.apache.avalon.framework.configuration.DefaultConfiguration; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.impl.SimpleLog; + import org.apache.batik.bridge.UserAgent; import org.apache.batik.dom.svg.SVGDOMImplementation; import org.apache.batik.dom.util.DocumentFactory; @@ -44,8 +48,6 @@ import org.apache.batik.transcoder.keys.BooleanKey; import org.apache.batik.transcoder.keys.FloatKey; import org.apache.batik.util.ParsedURL; import org.apache.batik.util.SVGConstants; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.impl.SimpleLog; import org.apache.xmlgraphics.image.GraphicsConstants; import org.apache.xmlgraphics.image.loader.ImageContext; diff --git a/src/java/org/apache/fop/svg/NativeTextPainter.java b/src/java/org/apache/fop/svg/NativeTextPainter.java index b641337de..4513e0101 100644 --- a/src/java/org/apache/fop/svg/NativeTextPainter.java +++ b/src/java/org/apache/fop/svg/NativeTextPainter.java @@ -24,11 +24,12 @@ import java.io.IOException; import java.text.AttributedCharacterIterator; import java.util.List; -import org.apache.batik.gvt.renderer.StrokingTextPainter; -import org.apache.batik.gvt.text.TextSpanLayout; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.apache.batik.gvt.renderer.StrokingTextPainter; +import org.apache.batik.gvt.text.TextSpanLayout; + import org.apache.fop.fonts.Font; import org.apache.fop.fonts.FontInfo; import org.apache.fop.util.CharUtilities; diff --git a/src/java/org/apache/fop/svg/PDFBatikFlowTextElementBridge.java b/src/java/org/apache/fop/svg/PDFBatikFlowTextElementBridge.java index d167f5de4..90dd9f304 100644 --- a/src/java/org/apache/fop/svg/PDFBatikFlowTextElementBridge.java +++ b/src/java/org/apache/fop/svg/PDFBatikFlowTextElementBridge.java @@ -23,6 +23,7 @@ import org.apache.batik.extension.svg.BatikFlowTextElementBridge; import org.apache.batik.gvt.GraphicsNode; import org.apache.batik.gvt.TextNode; import org.apache.batik.gvt.TextPainter; + import org.apache.fop.fonts.FontInfo; /** diff --git a/src/java/org/apache/fop/svg/PDFFlowExtTextPainter.java b/src/java/org/apache/fop/svg/PDFFlowExtTextPainter.java index 1c85a2899..0f11e99bf 100644 --- a/src/java/org/apache/fop/svg/PDFFlowExtTextPainter.java +++ b/src/java/org/apache/fop/svg/PDFFlowExtTextPainter.java @@ -24,6 +24,7 @@ import java.util.List; import org.apache.batik.extension.svg.FlowExtTextPainter; import org.apache.batik.gvt.TextNode; + import org.apache.fop.fonts.FontInfo; /** diff --git a/src/java/org/apache/fop/svg/PDFFlowTextPainter.java b/src/java/org/apache/fop/svg/PDFFlowTextPainter.java index 5b307ce83..7b07ec297 100644 --- a/src/java/org/apache/fop/svg/PDFFlowTextPainter.java +++ b/src/java/org/apache/fop/svg/PDFFlowTextPainter.java @@ -24,6 +24,7 @@ import java.util.List; import org.apache.batik.gvt.TextNode; import org.apache.batik.gvt.flow.FlowTextPainter; + import org.apache.fop.fonts.FontInfo; /** diff --git a/src/java/org/apache/fop/svg/PDFGraphicsDevice.java b/src/java/org/apache/fop/svg/PDFGraphicsDevice.java index 538dd16c2..43658fd6d 100644 --- a/src/java/org/apache/fop/svg/PDFGraphicsDevice.java +++ b/src/java/org/apache/fop/svg/PDFGraphicsDevice.java @@ -19,9 +19,9 @@ package org.apache.fop.svg; -import java.awt.GraphicsDevice; -import java.awt.GraphicsConfiguration; import java.awt.GraphicsConfigTemplate; +import java.awt.GraphicsConfiguration; +import java.awt.GraphicsDevice; /** * This implements the GraphicsDevice interface as appropriate for diff --git a/src/java/org/apache/fop/svg/PDFSVGFlowRootElementBridge.java b/src/java/org/apache/fop/svg/PDFSVGFlowRootElementBridge.java index d313e6cc4..7d2b947e7 100644 --- a/src/java/org/apache/fop/svg/PDFSVGFlowRootElementBridge.java +++ b/src/java/org/apache/fop/svg/PDFSVGFlowRootElementBridge.java @@ -23,6 +23,7 @@ import org.apache.batik.bridge.svg12.SVGFlowRootElementBridge; import org.apache.batik.gvt.GraphicsNode; import org.apache.batik.gvt.TextNode; import org.apache.batik.gvt.TextPainter; + import org.apache.fop.fonts.FontInfo; /** diff --git a/src/java/org/apache/fop/svg/PDFTranscoder.java b/src/java/org/apache/fop/svg/PDFTranscoder.java index 8cf396ae5..04b1b5497 100644 --- a/src/java/org/apache/fop/svg/PDFTranscoder.java +++ b/src/java/org/apache/fop/svg/PDFTranscoder.java @@ -28,6 +28,7 @@ import org.w3c.dom.Document; import org.w3c.dom.svg.SVGLength; import org.apache.avalon.framework.configuration.Configuration; + import org.apache.batik.bridge.BridgeContext; import org.apache.batik.bridge.UnitProcessor; import org.apache.batik.bridge.UserAgent; diff --git a/src/java/org/apache/fop/tools/TestConverter.java b/src/java/org/apache/fop/tools/TestConverter.java index 0c6e09bd0..f453fecdf 100644 --- a/src/java/org/apache/fop/tools/TestConverter.java +++ b/src/java/org/apache/fop/tools/TestConverter.java @@ -26,17 +26,18 @@ import java.util.Map; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; -import org.apache.fop.apps.FopFactory; -import org.apache.fop.apps.FOUserAgent; -import org.apache.fop.apps.MimeConstants; -import org.apache.fop.cli.InputHandler; -import org.apache.fop.tools.anttasks.FileCompare; import org.w3c.dom.Document; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.apache.commons.logging.impl.SimpleLog; +import org.apache.fop.apps.FOUserAgent; +import org.apache.fop.apps.FopFactory; +import org.apache.fop.apps.MimeConstants; +import org.apache.fop.cli.InputHandler; +import org.apache.fop.tools.anttasks.FileCompare; + /** * TestConverter is used to process a set of tests specified in * a testsuite. diff --git a/src/java/org/apache/fop/tools/anttasks/FileCompare.java b/src/java/org/apache/fop/tools/anttasks/FileCompare.java index a50f9801e..462049907 100644 --- a/src/java/org/apache/fop/tools/anttasks/FileCompare.java +++ b/src/java/org/apache/fop/tools/anttasks/FileCompare.java @@ -19,16 +19,16 @@ package org.apache.fop.tools.anttasks; -import java.util.Date; -import java.util.List; -import java.util.StringTokenizer; import java.io.BufferedInputStream; import java.io.File; import java.io.IOException; import java.io.PrintWriter; +import java.text.DateFormat; +import java.util.Date; +import java.util.List; +import java.util.StringTokenizer; import org.apache.tools.ant.BuildException; -import java.text.DateFormat; /** * This class is an extension of Ant, a script utility from diff --git a/src/java/org/apache/fop/tools/anttasks/RunTest.java b/src/java/org/apache/fop/tools/anttasks/RunTest.java index 1e1a959ed..6a959d758 100644 --- a/src/java/org/apache/fop/tools/anttasks/RunTest.java +++ b/src/java/org/apache/fop/tools/anttasks/RunTest.java @@ -19,21 +19,18 @@ package org.apache.fop.tools.anttasks; -// Ant -import org.apache.tools.ant.BuildException; -import org.apache.tools.ant.Task; - -// Java import java.io.File; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; -import java.net.URLClassLoader; -import java.net.URL; import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; import java.util.ArrayList; import java.util.Iterator; import java.util.Map; +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Task; /** * Testing ant task. diff --git a/src/java/org/apache/fop/util/ColorSpaceCache.java b/src/java/org/apache/fop/util/ColorSpaceCache.java index 63db937a0..246477f6b 100644 --- a/src/java/org/apache/fop/util/ColorSpaceCache.java +++ b/src/java/org/apache/fop/util/ColorSpaceCache.java @@ -30,10 +30,10 @@ import javax.xml.transform.stream.StreamSource; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.apache.xmlgraphics.java2d.color.profile.ColorProfileUtil; import org.apache.xmlgraphics.java2d.color.ICCColorSpaceWithIntent; import org.apache.xmlgraphics.java2d.color.RenderingIntent; +import org.apache.xmlgraphics.java2d.color.profile.ColorProfileUtil; /** * Map with cached ICC based ColorSpace objects. diff --git a/src/java/org/apache/fop/util/LogUtil.java b/src/java/org/apache/fop/util/LogUtil.java index 664667a76..acecca2ee 100644 --- a/src/java/org/apache/fop/util/LogUtil.java +++ b/src/java/org/apache/fop/util/LogUtil.java @@ -20,6 +20,7 @@ package org.apache.fop.util; import org.apache.commons.logging.Log; + import org.apache.fop.apps.FOPException; /** diff --git a/src/sandbox/org/apache/fop/render/mif/MIFHandler.java b/src/sandbox/org/apache/fop/render/mif/MIFHandler.java index 34eb7dc8d..cfc86edc7 100644 --- a/src/sandbox/org/apache/fop/render/mif/MIFHandler.java +++ b/src/sandbox/org/apache/fop/render/mif/MIFHandler.java @@ -19,12 +19,14 @@ package org.apache.fop.render.mif; -// Java import java.io.IOException; import java.io.OutputStream; +import org.xml.sax.SAXException; + import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + import org.apache.fop.apps.FOUserAgent; import org.apache.fop.fo.FOEventHandler; import org.apache.fop.fo.flow.BasicLink; @@ -51,7 +53,6 @@ import org.apache.fop.fo.pagination.PageSequenceMaster; import org.apache.fop.fo.pagination.SimplePageMaster; import org.apache.fop.fonts.FontSetup; import org.apache.fop.render.DefaultFontResolver; -import org.xml.sax.SAXException; // TODO: do we really want every method throwing a SAXException diff --git a/src/sandbox/org/apache/fop/render/svg/SVGRenderer.java b/src/sandbox/org/apache/fop/render/svg/SVGRenderer.java index 0e575c736..9cbc1662d 100644 --- a/src/sandbox/org/apache/fop/render/svg/SVGRenderer.java +++ b/src/sandbox/org/apache/fop/render/svg/SVGRenderer.java @@ -29,13 +29,14 @@ 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.batik.dom.GenericDOMImplementation; +import org.apache.batik.svggen.SVGGeneratorContext; +import org.apache.batik.svggen.SVGGraphics2D; + import org.apache.fop.apps.FOUserAgent; import org.apache.fop.apps.MimeConstants; import org.apache.fop.area.PageViewport; diff --git a/src/sandbox/org/apache/fop/render/svg/SVGSVGHandler.java b/src/sandbox/org/apache/fop/render/svg/SVGSVGHandler.java index c46c35b99..57079bf03 100644 --- a/src/sandbox/org/apache/fop/render/svg/SVGSVGHandler.java +++ b/src/sandbox/org/apache/fop/render/svg/SVGSVGHandler.java @@ -19,12 +19,6 @@ package org.apache.fop.render.svg; -import org.apache.batik.dom.svg.SVGDOMImplementation; -import org.apache.batik.dom.util.DOMUtilities; -import org.apache.batik.dom.util.XMLSupport; -import org.apache.fop.render.Renderer; -import org.apache.fop.render.RendererContext; -import org.apache.fop.render.XMLHandler; import org.w3c.dom.DOMImplementation; import org.w3c.dom.Element; import org.w3c.dom.Node; @@ -32,6 +26,14 @@ import org.w3c.dom.svg.SVGDocument; import org.w3c.dom.svg.SVGElement; import org.w3c.dom.svg.SVGSVGElement; +import org.apache.batik.dom.svg.SVGDOMImplementation; +import org.apache.batik.dom.util.DOMUtilities; +import org.apache.batik.dom.util.XMLSupport; + +import org.apache.fop.render.Renderer; +import org.apache.fop.render.RendererContext; +import org.apache.fop.render.XMLHandler; + /** The svg:svg element handler. */ public class SVGSVGHandler implements XMLHandler, SVGRendererContextConstants { -- 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/sandbox/org/apache/fop/render/mif') 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