Exemplo n.º 1
0
        internal static OpenTypeLayoutResult SubstituteGlyphs(
            IOpenTypeFont           Font,           // In: Font access interface
            OpenTypeLayoutWorkspace workspace,      // In: Workspace for layout engine
            uint                    ScriptTag,      // In: Script tag 
            uint                    LangSysTag,     // In: LangSys tag
            Feature[]               FeatureSet,     // In: List of features to apply 
            int                     featureCount,   // In: Actual number of features in FeatureSet 
            int                     featureSetOffset,
            int                     CharCount,      // In: Characters count (i.e. Charmap.Length); 
            UshortList              Charmap,        // In/out: Char to glyph mapping
            GlyphInfoList           Glyphs          // In/out: List of GlyphInfo structs
            )
        { 
            try
            { 
                FontTable GsubTable = Font.GetFontTable(OpenTypeTags.GSUB); 
                if (!GsubTable.IsPresent) {return OpenTypeLayoutResult.ScriptNotFound;}
 
                GSUBHeader GsubHeader = new GSUBHeader(0);
                ScriptList ScriptList = GsubHeader.GetScriptList(GsubTable);

                ScriptTable Script    = ScriptList.FindScript(GsubTable,ScriptTag); 
                if (Script.IsNull) {return OpenTypeLayoutResult.ScriptNotFound;}
 
                LangSysTable LangSys = Script.FindLangSys(GsubTable,LangSysTag); 
                if (LangSys.IsNull) {return OpenTypeLayoutResult.LangSysNotFound;}
 
                FeatureList FeatureList = GsubHeader.GetFeatureList(GsubTable);
                LookupList LookupList = GsubHeader.GetLookupList(GsubTable);

                LayoutEngine.ApplyFeatures( 
                    Font,
                    workspace, 
                    OpenTypeTags.GSUB, 
                    GsubTable,
                    new LayoutMetrics(), //it is not needed for substitution 
                    LangSys,
                    FeatureList,
                    LookupList,
                    FeatureSet, 
                    featureCount,
                    featureSetOffset, 
                    CharCount, 
                    Charmap,
                    Glyphs, 
                    null,
                    null
                );
            } 
            catch (FileFormatException)
            { 
                return OpenTypeLayoutResult.BadFontTable; 
            }
 
            return OpenTypeLayoutResult.Success;
        }
Exemplo n.º 2
0
        internal static void GetComplexLanguageList(
                                                OpenTypeTags            tableTag,
                                                FontTable               table,
                                                uint[]                  featureTagsList,
                                                uint[]                  glyphBits,
                                                ushort                  minGlyphId,
                                                ushort                  maxGlyphId,
                                                out WritingSystem[]     complexLanguages,
                                                out int                 complexLanguageCount
                                             )
        {
            ScriptList  scriptList  = new ScriptList(0);
            FeatureList featureList = new FeatureList(0);
            LookupList  lookupList  = new LookupList(0);

            Debug.Assert(tableTag == OpenTypeTags.GSUB || tableTag == OpenTypeTags.GPOS);

            switch (tableTag)
            {
                case OpenTypeTags.GSUB:
                    GSUBHeader gsubHeader = new GSUBHeader(0);
                    scriptList  = gsubHeader.GetScriptList(table);
                    featureList = gsubHeader.GetFeatureList(table);
                    lookupList  = gsubHeader.GetLookupList(table);
                    break;

                case OpenTypeTags.GPOS:
                    GPOSHeader gposHeader = new GPOSHeader(0);
                    scriptList  = gposHeader.GetScriptList(table);
                    featureList = gposHeader.GetFeatureList(table);
                    lookupList  = gposHeader.GetLookupList(table);
                    break;
            }

            int scriptCount  = scriptList.GetScriptCount(table);
            int featureCount = featureList.FeatureCount(table);
            int lookupCount  = lookupList.LookupCount(table);

            // We will mark lookups that should be tested.
            // At the end, we will have only complex ones marked
            uint[] lookupBits = new uint[(lookupCount+31)>>5];

            for(int i = 0; i < (lookupCount+31)>>5; i++)
            {
                lookupBits[i] = 0;
            }

            // Iterate through list of featuers in the table
            for(ushort featureIndex = 0; featureIndex < featureCount; featureIndex++)
            {
                uint featureTag = (uint)featureList.FeatureTag(table, featureIndex);
                bool tagFound   = false;

                //Search for tag in the list of features in question
                for(int j = 0; j < featureTagsList.Length; j++)
                {
                    if (featureTagsList[j] == featureTag)
                    {
                        tagFound = true;
                        break;
                    }
                }

                if (tagFound)
                {
                    // We should mark all lookup mapped to this feature
                    FeatureTable featureTable = featureList.FeatureTable(table, featureIndex);
                    ushort featureLookupCount = featureTable.LookupCount(table);

                    for(ushort j = 0; j < featureLookupCount; j++)
                    {
                        ushort lookupIndex = featureTable.LookupIndex(table, j);
                        
                        if (lookupIndex >= lookupCount)
                        {
                            //This should be invalid font. Lookup associated with the feature is not in lookup array.
                            throw new FileFormatException();
                        }

                        lookupBits[lookupIndex>>5] |= (uint)(1 << (lookupIndex%32));
                    }
                }
            }

            //
            //




            //Now test all marked lookups
            for(ushort lookupIndex = 0; lookupIndex < lookupCount; lookupIndex++)
            {
                if ((lookupBits[lookupIndex>>5] & (1 << (lookupIndex%32))) == 0)
                {
                    continue;
                }

                LookupTable lookup = lookupList.Lookup(table,lookupIndex);

                ushort lookupType    = lookup.LookupType();
                ushort subtableCount = lookup.SubTableCount();

                bool lookupIsCovered = false;

                ushort originalLookupType = lookupType; // We need it to recover,
                                                        // if extension lookup updated lookupFormat
                for(ushort subtableIndex = 0;
                    !lookupIsCovered && subtableIndex < subtableCount;
                    subtableIndex++)
                {
                    lookupType = originalLookupType;
                    int subtableOffset = lookup.SubtableOffset(table, subtableIndex);

                    switch (tableTag)
                    {
                        case OpenTypeTags.GSUB:
                        {
                            if (lookupType == 7)
                            {
                                ExtensionLookupTable extension =
                                        new ExtensionLookupTable(subtableOffset);

                                lookupType = extension.LookupType(table);
                                subtableOffset = extension.LookupSubtableOffset(table);
                            }

                            switch (lookupType)
                            {
                                case 1: //SingleSubst
                                    SingleSubstitutionSubtable singleSub =
                                        new SingleSubstitutionSubtable(subtableOffset);
                                    lookupIsCovered = singleSub.IsLookupCovered(table,glyphBits,minGlyphId,maxGlyphId);
                                    break;

                                case 2: //MultipleSubst
                                    MultipleSubstitutionSubtable multipleSub =
                                        new MultipleSubstitutionSubtable(subtableOffset);
                                    lookupIsCovered = multipleSub.IsLookupCovered(table,glyphBits,minGlyphId,maxGlyphId);
                                    break;

                                case 3: //AlternateSubst
                                    AlternateSubstitutionSubtable alternateSub =
                                        new AlternateSubstitutionSubtable(subtableOffset);
                                    lookupIsCovered = alternateSub.IsLookupCovered(table,glyphBits,minGlyphId,maxGlyphId);
                                    break;

                                case 4: //Ligature subst
                                    LigatureSubstitutionSubtable ligaSub =
                                        new LigatureSubstitutionSubtable(subtableOffset);
                                    lookupIsCovered = ligaSub.IsLookupCovered(table,glyphBits,minGlyphId,maxGlyphId);
                                    break;

                                case 5: //ContextualSubst
                                    ContextSubtable contextSub =
                                        new ContextSubtable(subtableOffset);
                                    lookupIsCovered = contextSub.IsLookupCovered(table,glyphBits,minGlyphId,maxGlyphId);
                                    break;

                                case 6: //ChainingSubst
                                    ChainingSubtable chainingSub =
                                                        new ChainingSubtable(subtableOffset);
                                    lookupIsCovered = chainingSub.IsLookupCovered(table,glyphBits,minGlyphId,maxGlyphId);
                                    break;

                                case 7: //Extension lookup
                                    Debug.Assert(false,"Ext.Lookup processed earlier!");
                                    break;

                                case 8: //ReverseCahiningSubst
                                    ReverseChainingSubtable reverseChainingSub =
                                        new ReverseChainingSubtable(subtableOffset);
                                    lookupIsCovered = reverseChainingSub.IsLookupCovered(table,glyphBits,minGlyphId,maxGlyphId);
                                    break;

                                default:
                                    // Unknown format
                                    lookupIsCovered = true;
                                    break;
                            }

                            break;
                        }

                        case OpenTypeTags.GPOS:
                        {
                            if (lookupType == 9)
                            {
                                ExtensionLookupTable extension =
                                        new ExtensionLookupTable(subtableOffset);

                                lookupType = extension.LookupType(table);
                                subtableOffset = extension.LookupSubtableOffset(table);

                            }

                            switch (lookupType)
                            {
                                case 1: //SinglePos
                                    SinglePositioningSubtable singlePos =
                                        new SinglePositioningSubtable(subtableOffset);
                                    lookupIsCovered = singlePos.IsLookupCovered(table,glyphBits,minGlyphId,maxGlyphId);
                                    break;

                                case 2: //PairPos
                                    PairPositioningSubtable pairPos =
                                        new PairPositioningSubtable(subtableOffset);
                                    lookupIsCovered = pairPos.IsLookupCovered(table,glyphBits,minGlyphId,maxGlyphId);
                                    break;

                                case 3: // CursivePos
                                    // Under construction
                                    CursivePositioningSubtable cursivePositioningSubtable =
                                        new CursivePositioningSubtable(subtableOffset);

                                    lookupIsCovered = cursivePositioningSubtable.IsLookupCovered(table,glyphBits,minGlyphId,maxGlyphId);

                                    break;

                                case 4: //MarkToBasePos
                                    MarkToBasePositioningSubtable markToBasePos =
                                        new MarkToBasePositioningSubtable(subtableOffset);
                                    lookupIsCovered = markToBasePos.IsLookupCovered(table,glyphBits,minGlyphId,maxGlyphId);
                                    break;


                                case 5: //MarkToLigaturePos
                                    // Under construction
                                    MarkToLigaturePositioningSubtable markToLigaPos =
                                       new MarkToLigaturePositioningSubtable(subtableOffset);
                                    lookupIsCovered = markToLigaPos.IsLookupCovered(table,glyphBits,minGlyphId,maxGlyphId);
                                    break;

                                case 6: //MarkToMarkPos
                                    MarkToMarkPositioningSubtable markToMarkPos =
                                        new MarkToMarkPositioningSubtable(subtableOffset);
                                    lookupIsCovered = markToMarkPos.IsLookupCovered(table,glyphBits,minGlyphId,maxGlyphId);
                                    break;

                                case 7: // Contextual
                                    ContextSubtable contextSub =
                                        new ContextSubtable(subtableOffset);
                                    lookupIsCovered = contextSub.IsLookupCovered(table,glyphBits,minGlyphId,maxGlyphId);
                                    break;

                                case 8: // Chaining
                                    ChainingSubtable chainingSub =
                                        new ChainingSubtable(subtableOffset);
                                    lookupIsCovered = chainingSub.IsLookupCovered(table,glyphBits,minGlyphId,maxGlyphId);
                                    break;

                                case 9: //Extension lookup
                                    Debug.Assert(false,"Ext.Lookup processed earlier!");
                                    break;

                                default:
                                    // Unknown format
                                    lookupIsCovered = true;
                                    break;
                            }

                            break;
                        }

                        default:
                            Debug.Assert(false,"Unknown OpenType layout table!");
                            break;
                    }
                }

                if (!lookupIsCovered)
                {
                    // Clean the flag
                    lookupBits[lookupIndex>>5] &= ~(uint)(1 << (lookupIndex%32));
                }
            }


            // Check if we have any lookup left
            bool complexLookupFound = false;

            for(int i = 0; i < (lookupCount+31)>>5; i++)
            {
                if (lookupBits[i] != 0)
                {
                    complexLookupFound = true;
                    break;
                }
            }

            if (!complexLookupFound)
            {
                // There are no complex lookups
                complexLanguages = null;
                complexLanguageCount = 0;
                return;
            }

            // Now go through all langauages and fill the list
            complexLanguages = new WritingSystem[10];
            complexLanguageCount = 0;

            for(ushort scriptIndex = 0; scriptIndex < scriptCount; scriptIndex++)
            {
                ScriptTable  scriptTable = scriptList.GetScriptTable(table, scriptIndex);
                uint scriptTag = scriptList.GetScriptTag(table, scriptIndex);

                ushort langSysCount = scriptTable.GetLangSysCount(table);

                if (scriptTable.IsDefaultLangSysExists(table))
                {
                    AppendLangSys(scriptTag, (uint)OpenTypeTags.dflt,
                                  scriptTable.GetDefaultLangSysTable(table),
                                  featureList,
                                  table,
                                  featureTagsList,
                                  lookupBits,
                                  ref complexLanguages,
                                  ref complexLanguageCount
                                 );
                }

                for(ushort langSysIndex = 0; langSysIndex < langSysCount; langSysIndex++)
                {
                    uint langSysTag = scriptTable.GetLangSysTag(table, langSysIndex);

                    AppendLangSys(scriptTag, langSysTag,
                                  scriptTable.GetLangSysTable(table, langSysIndex),
                                  featureList,
                                  table,
                                  featureTagsList,
                                  lookupBits,
                                  ref complexLanguages,
                                  ref complexLanguageCount
                                 );
                }
            }
        }
Exemplo n.º 3
0
        internal static TagInfoFlags FindLangSys(
            IOpenTypeFont       Font, 
            uint                ScriptTag,
            uint                LangSysTag
            )
        { 
            TagInfoFlags flags = TagInfoFlags.None;
 
            try 
            {
                FontTable gsubTable = Font.GetFontTable(OpenTypeTags.GSUB); 
                if (gsubTable.IsPresent)
                {
                    GSUBHeader gsubHeader = new GSUBHeader(0);
                    ScriptTable gsubScript = gsubHeader.GetScriptList(gsubTable).FindScript(gsubTable,ScriptTag); 
                    if (!gsubScript.IsNull && !gsubScript.FindLangSys(gsubTable,LangSysTag).IsNull)
                    { 
                        flags |= TagInfoFlags.Substitution; 
                    }
                } 
            }
            catch (FileFormatException)
            {
                return TagInfoFlags.None; 
            }
 
            try 
            {
                FontTable gposTable = Font.GetFontTable(OpenTypeTags.GPOS); 
                if (gposTable.IsPresent)
                {
                    GPOSHeader gposHeader = new GPOSHeader(0);
                    ScriptTable gposScript = gposHeader.GetScriptList(gposTable).FindScript(gposTable,ScriptTag); 
                    if (!gposScript.IsNull && !gposScript.FindLangSys(gposTable,LangSysTag).IsNull)
                    { 
                        flags |= TagInfoFlags.Positioning; 
                    }
                } 
            }
            catch (FileFormatException)
            {
                return TagInfoFlags.None; 
            }
 
            return flags; 
        }