Exemple #1
0
        public unsafe bool Apply(
            IOpenTypeFont   Font,
            FontTable       Table,
            int             CharCount,
            UshortList      Charmap,        // Character to glyph map
            GlyphInfoList   GlyphInfo,      // List of GlyphInfo
            ushort          LookupFlags,    // Lookup flags for glyph lookups
            int             FirstGlyph,     // where to apply it
            int             AfterLastGlyph, // how long is a context we can use
            out int         NextGlyph       // Next glyph to process
            )
         {
            NextGlyph = FirstGlyph + 1; // in case we don't match
            
            if (Format(Table) != 1) return false; //unknown format
            
            int oldGlyphCount=GlyphInfo.Length;
            
            ushort glyphId = GlyphInfo.Glyphs[FirstGlyph];
            int coverageIndex = Coverage(Table).GetGlyphIndex(Table,glyphId);
            if (coverageIndex==-1) return false;
            
            MultipleSubstitutionSequenceTable sequence = Sequence(Table,coverageIndex);

            ushort sequenceLength = sequence.GlyphCount(Table);
            int lengthDelta = sequenceLength - 1;
            
            if (sequenceLength==0)
            {
                // This is illegal, because mapping will be broken -
                // corresponding char will be lost. Just leave it as it is.
                // (char will be attached to the following glyph).
                GlyphInfo.Remove(FirstGlyph,1);
            }
            else
            {
                ushort firstChar = GlyphInfo.FirstChars[FirstGlyph];
                ushort ligatureCount = GlyphInfo.LigatureCounts[FirstGlyph];

                if (lengthDelta > 0)
                {
                    GlyphInfo.Insert(FirstGlyph,lengthDelta);
                }
                
                //put glyphs in place
                for(ushort gl=0; gl<sequenceLength; gl++)
                {
                    GlyphInfo.Glyphs[FirstGlyph + gl] = sequence.Glyph(Table,gl);
                    GlyphInfo.GlyphFlags[FirstGlyph + gl] =
                                (ushort)(GlyphFlags.Unresolved | GlyphFlags.Substituted);
                    GlyphInfo.FirstChars[FirstGlyph + gl] = firstChar;
                    GlyphInfo.LigatureCounts[FirstGlyph + gl] = ligatureCount;
                }
            }
            
            //Fix char mapping - very simple for now. 
            // Works only for arabic base+mark -> base and marks decomposition
            //
            for(int ch=0;ch<CharCount;ch++)
            {
                if (Charmap[ch]>FirstGlyph) Charmap[ch] = (ushort)(Charmap[ch]+lengthDelta);
            }
            
            NextGlyph = FirstGlyph + lengthDelta + 1;
            
            return true;
         }
Exemple #2
0
        public unsafe bool Apply(
            IOpenTypeFont Font,
            FontTable Table,
            int CharCount,
            UshortList Charmap,             // Character to glyph map
            GlyphInfoList GlyphInfo,        // List of GlyphInfo
            ushort LookupFlags,             // Lookup flags for glyph lookups
            int FirstGlyph,                 // where to apply it
            int AfterLastGlyph,             // how long is a context we can use
            out int NextGlyph               // Next glyph to process
            )
        {
            NextGlyph = FirstGlyph + 1; // in case we don't match

            if (Format(Table) != 1)
            {
                return(false);                    //unknown format
            }
            int oldGlyphCount = GlyphInfo.Length;

            ushort glyphId       = GlyphInfo.Glyphs[FirstGlyph];
            int    coverageIndex = Coverage(Table).GetGlyphIndex(Table, glyphId);

            if (coverageIndex == -1)
            {
                return(false);
            }

            MultipleSubstitutionSequenceTable sequence = Sequence(Table, coverageIndex);

            ushort sequenceLength = sequence.GlyphCount(Table);
            int    lengthDelta    = sequenceLength - 1;

            if (sequenceLength == 0)
            {
                // This is illegal, because mapping will be broken -
                // corresponding char will be lost. Just leave it as it is.
                // (char will be attached to the following glyph).
                GlyphInfo.Remove(FirstGlyph, 1);
            }
            else
            {
                ushort firstChar     = GlyphInfo.FirstChars[FirstGlyph];
                ushort ligatureCount = GlyphInfo.LigatureCounts[FirstGlyph];

                if (lengthDelta > 0)
                {
                    GlyphInfo.Insert(FirstGlyph, lengthDelta);
                }

                //put glyphs in place
                for (ushort gl = 0; gl < sequenceLength; gl++)
                {
                    GlyphInfo.Glyphs[FirstGlyph + gl]     = sequence.Glyph(Table, gl);
                    GlyphInfo.GlyphFlags[FirstGlyph + gl] =
                        (ushort)(GlyphFlags.Unresolved | GlyphFlags.Substituted);
                    GlyphInfo.FirstChars[FirstGlyph + gl]     = firstChar;
                    GlyphInfo.LigatureCounts[FirstGlyph + gl] = ligatureCount;
                }
            }

            // Fix char mapping - very simple for now.
            // Works only for arabic base+mark -> base and marks decomposition
            // Needs work for full mapping
            for (int ch = 0; ch < CharCount; ch++)
            {
                if (Charmap[ch] > FirstGlyph)
                {
                    Charmap[ch] = (ushort)(Charmap[ch] + lengthDelta);
                }
            }

            NextGlyph = FirstGlyph + lengthDelta + 1;

            return(true);
        }
Exemple #3
0
        public unsafe bool Apply(
                            IOpenTypeFont   Font,
                            FontTable       Table,
                            int             CharCount,
                            UshortList      Charmap,        // Character to glyph map
                            GlyphInfoList   GlyphInfo,      // List of GlyphInfo
                            ushort          LookupFlags,    // Lookup flags for glyph lookups
                            int             FirstGlyph,     // where to apply it
                            int             AfterLastGlyph, // how long is a context we can use
                            out int         NextGlyph       // Next glyph to process
                          )
        {
            Invariant.Assert(FirstGlyph>=0);
            Invariant.Assert(AfterLastGlyph<=GlyphInfo.Length);

            NextGlyph = FirstGlyph + 1; //In case we don't match;
            
            if (Format(Table) != 1) return false; // Unknown format
                
            int glyphCount=GlyphInfo.Length;
            ushort glyphId = GlyphInfo.Glyphs[FirstGlyph];
            int CoverageIndex = Coverage(Table).GetGlyphIndex(Table,glyphId);
            if (CoverageIndex==-1) return false;

            int curGlyph;
            ushort ligatureGlyph=0;
            bool match = false;
            ushort compCount=0;

            LigatureSetTable ligatureSet = LigatureSet(Table,(ushort)CoverageIndex);
            ushort ligaCount = ligatureSet.LigatureCount(Table);
            for(ushort liga=0; liga<ligaCount; liga++)
            {
                LigatureTable ligature = ligatureSet.Ligature(Table,liga);
                compCount = ligature.ComponentCount(Table);
                if (compCount == 0)
                {
                    throw new FileFormatException();
                }
                
                curGlyph=FirstGlyph;
                ushort comp=1;
                for(comp=1;comp<compCount;comp++)
                {
                    curGlyph = LayoutEngine.GetNextGlyphInLookup(Font,GlyphInfo,curGlyph+1,LookupFlags,LayoutEngine.LookForward);
                    if (curGlyph>=AfterLastGlyph) break;
                    
                    if (GlyphInfo.Glyphs[curGlyph]!=ligature.Component(Table,comp)) break;
                }
                
                if (comp==compCount) //liga matched
                {
                    match=true;
                    ligatureGlyph = ligature.LigatureGlyph(Table);
                    break; //Liga found
                }
            }
            //If no ligature found, match will remain false after last iteration
            
            if (match) 
            {
                //Fix character and glyph Mapping
            
                //PERF: localize ligature character range
                    
                //Calculate Ligature CharCount
                int totalLigaCharCount=0;
                int firstLigaChar=int.MaxValue;
                curGlyph=FirstGlyph;
                for(ushort comp=0;comp<compCount;comp++)
                {
                    Invariant.Assert(curGlyph<AfterLastGlyph);
                    
                    int curFirstChar = GlyphInfo.FirstChars[curGlyph];
                    int curLigaCount = GlyphInfo.LigatureCounts[curGlyph];
                    
                    totalLigaCharCount += curLigaCount;
                    if (curFirstChar<firstLigaChar) firstLigaChar=curFirstChar;
                    
                    curGlyph = LayoutEngine.GetNextGlyphInLookup(Font,GlyphInfo,curGlyph+1,LookupFlags,LayoutEngine.LookForward);
                }
                    
                curGlyph=FirstGlyph;
                int prevGlyph=FirstGlyph;
                ushort shift=0;
                for(ushort comp=1;comp<=compCount;comp++)
                {
                    prevGlyph=curGlyph;
                    
                    if (comp<compCount)
                    {
                        curGlyph = LayoutEngine.
                                        GetNextGlyphInLookup(Font,GlyphInfo,
                                                             curGlyph+1,
                                                             LookupFlags,
                                                             LayoutEngine.LookForward);
                    }
                    else curGlyph = GlyphInfo.Length; // to the end from last component
                    
                    // Set charmap for ligature component
                    for(int curChar=0; curChar<CharCount; curChar++)
                    {
                        if (Charmap[curChar]==prevGlyph)
                        {
                            Charmap[curChar] = (ushort)FirstGlyph;
                        }
                    }

                    //Shift glyphInfo
                    if (shift>0)
                    {
                        for(int glyph=prevGlyph+1; glyph<curGlyph; glyph++)
                        {
                            GlyphInfo.Glyphs[glyph-shift]         = GlyphInfo.Glyphs[glyph];
                            GlyphInfo.GlyphFlags[glyph-shift]     = GlyphInfo.GlyphFlags[glyph];
                            GlyphInfo.FirstChars[glyph-shift]     = GlyphInfo.FirstChars[glyph];
                            GlyphInfo.LigatureCounts[glyph-shift] = GlyphInfo.LigatureCounts[glyph];
                        }
                    
                        if (curGlyph-prevGlyph>1) //do fixing only if have glyphs in between
                        {
                            for(int curChar=0; curChar<CharCount; curChar++)
                            {
                                ushort curCharmap = Charmap[curChar];
                                if (curCharmap>prevGlyph && curCharmap<curGlyph)
                                {
                                    Charmap[curChar] -= shift;
                                }
                            }
                        }
                    }
                                        
                    ++shift;
                }
                
                //Place new glyph into position of first ligature glyph
                GlyphInfo.Glyphs[FirstGlyph]         = ligatureGlyph;
                GlyphInfo.GlyphFlags[FirstGlyph]     = (ushort)(GlyphFlags.Unresolved | GlyphFlags.Substituted);
                GlyphInfo.FirstChars[FirstGlyph]     = (ushort)firstLigaChar;
                GlyphInfo.LigatureCounts[FirstGlyph] = (ushort)totalLigaCharCount;
                
                //remove empty space
                if (compCount > 1)
                {
                    GlyphInfo.Remove(GlyphInfo.Length-compCount+1,compCount-1);
                }
                
                NextGlyph=prevGlyph-(compCount-1)+1;
            }
            
            return match;
        }
Exemple #4
0
        public unsafe bool Apply(
            IOpenTypeFont Font,
            FontTable Table,
            int CharCount,
            UshortList Charmap,                             // Character to glyph map
            GlyphInfoList GlyphInfo,                        // List of GlyphInfo
            ushort LookupFlags,                             // Lookup flags for glyph lookups
            int FirstGlyph,                                 // where to apply it
            int AfterLastGlyph,                             // how long is a context we can use
            out int NextGlyph                               // Next glyph to process
            )
        {
            Invariant.Assert(FirstGlyph >= 0);
            Invariant.Assert(AfterLastGlyph <= GlyphInfo.Length);

            NextGlyph = FirstGlyph + 1; //In case we don't match;

            if (Format(Table) != 1)
            {
                return(false);                    // Unknown format
            }
            int    glyphCount    = GlyphInfo.Length;
            ushort glyphId       = GlyphInfo.Glyphs[FirstGlyph];
            int    CoverageIndex = Coverage(Table).GetGlyphIndex(Table, glyphId);

            if (CoverageIndex == -1)
            {
                return(false);
            }

            int    curGlyph;
            ushort ligatureGlyph = 0;
            bool   match         = false;
            ushort compCount     = 0;

            LigatureSetTable ligatureSet = LigatureSet(Table, (ushort)CoverageIndex);
            ushort           ligaCount   = ligatureSet.LigatureCount(Table);

            for (ushort liga = 0; liga < ligaCount; liga++)
            {
                LigatureTable ligature = ligatureSet.Ligature(Table, liga);
                compCount = ligature.ComponentCount(Table);
                if (compCount == 0)
                {
                    throw new FileFormatException();
                }

                curGlyph = FirstGlyph;
                ushort comp = 1;
                for (comp = 1; comp < compCount; comp++)
                {
                    curGlyph = LayoutEngine.GetNextGlyphInLookup(Font, GlyphInfo, curGlyph + 1, LookupFlags, LayoutEngine.LookForward);
                    if (curGlyph >= AfterLastGlyph)
                    {
                        break;
                    }

                    if (GlyphInfo.Glyphs[curGlyph] != ligature.Component(Table, comp))
                    {
                        break;
                    }
                }

                if (comp == compCount) //liga matched
                {
                    match         = true;
                    ligatureGlyph = ligature.LigatureGlyph(Table);
                    break; //Liga found
                }
            }
            //If no ligature found, match will remain false after last iteration

            if (match)
            {
                //Fix character and glyph Mapping

                //PERF: localize ligature character range

                //Calculate Ligature CharCount
                int totalLigaCharCount = 0;
                int firstLigaChar      = int.MaxValue;
                curGlyph = FirstGlyph;
                for (ushort comp = 0; comp < compCount; comp++)
                {
                    Invariant.Assert(curGlyph < AfterLastGlyph);

                    int curFirstChar = GlyphInfo.FirstChars[curGlyph];
                    int curLigaCount = GlyphInfo.LigatureCounts[curGlyph];

                    totalLigaCharCount += curLigaCount;
                    if (curFirstChar < firstLigaChar)
                    {
                        firstLigaChar = curFirstChar;
                    }

                    curGlyph = LayoutEngine.GetNextGlyphInLookup(Font, GlyphInfo, curGlyph + 1, LookupFlags, LayoutEngine.LookForward);
                }

                curGlyph = FirstGlyph;
                int    prevGlyph = FirstGlyph;
                ushort shift     = 0;
                for (ushort comp = 1; comp <= compCount; comp++)
                {
                    prevGlyph = curGlyph;

                    if (comp < compCount)
                    {
                        curGlyph = LayoutEngine.
                                   GetNextGlyphInLookup(Font, GlyphInfo,
                                                        curGlyph + 1,
                                                        LookupFlags,
                                                        LayoutEngine.LookForward);
                    }
                    else
                    {
                        curGlyph = GlyphInfo.Length;  // to the end from last component
                    }
                    // Set charmap for ligature component
                    for (int curChar = 0; curChar < CharCount; curChar++)
                    {
                        if (Charmap[curChar] == prevGlyph)
                        {
                            Charmap[curChar] = (ushort)FirstGlyph;
                        }
                    }

                    //Shift glyphInfo
                    if (shift > 0)
                    {
                        for (int glyph = prevGlyph + 1; glyph < curGlyph; glyph++)
                        {
                            GlyphInfo.Glyphs[glyph - shift]         = GlyphInfo.Glyphs[glyph];
                            GlyphInfo.GlyphFlags[glyph - shift]     = GlyphInfo.GlyphFlags[glyph];
                            GlyphInfo.FirstChars[glyph - shift]     = GlyphInfo.FirstChars[glyph];
                            GlyphInfo.LigatureCounts[glyph - shift] = GlyphInfo.LigatureCounts[glyph];
                        }

                        if (curGlyph - prevGlyph > 1) //do fixing only if have glyphs in between
                        {
                            for (int curChar = 0; curChar < CharCount; curChar++)
                            {
                                ushort curCharmap = Charmap[curChar];
                                if (curCharmap > prevGlyph && curCharmap < curGlyph)
                                {
                                    Charmap[curChar] -= shift;
                                }
                            }
                        }
                    }

                    ++shift;
                }

                //Place new glyph into position of first ligature glyph
                GlyphInfo.Glyphs[FirstGlyph]         = ligatureGlyph;
                GlyphInfo.GlyphFlags[FirstGlyph]     = (ushort)(GlyphFlags.Unresolved | GlyphFlags.Substituted);
                GlyphInfo.FirstChars[FirstGlyph]     = (ushort)firstLigaChar;
                GlyphInfo.LigatureCounts[FirstGlyph] = (ushort)totalLigaCharCount;

                //remove empty space
                if (compCount > 1)
                {
                    GlyphInfo.Remove(GlyphInfo.Length - compCount + 1, compCount - 1);
                }

                NextGlyph = prevGlyph - (compCount - 1) + 1;
            }

            return(match);
        }