Пример #1
0
        public bool IsLookupCovered(
            FontTable table,
            uint[] glyphBits,
            ushort minGlyphId,
            ushort maxGlyphId)
        {
            if (!Coverage(table).IsAnyGlyphCovered(table,
                                                   glyphBits,
                                                   minGlyphId,
                                                   maxGlyphId
                                                   )
                )
            {
                return(false);
            }

            ushort ligatureSetCount = LigatureSetCount(table);

            for (ushort setIndex = 0; setIndex < ligatureSetCount; setIndex++)
            {
                LigatureSetTable ligatureSet = LigatureSet(table, setIndex);
                ushort           ligaCount   = ligatureSet.LigatureCount(table);

                for (ushort liga = 0; liga < ligaCount; liga++)
                {
                    LigatureTable ligature  = ligatureSet.Ligature(table, liga);
                    ushort        compCount = ligature.ComponentCount(table);

                    bool ligatureIsComplex = true;

                    for (ushort compIndex = 1; compIndex < compCount; compIndex++)
                    {
                        ushort glyphId = ligature.Component(table, compIndex);

                        if (glyphId > maxGlyphId ||
                            glyphId < minGlyphId ||
                            (glyphBits[glyphId >> 5] & (1 << (glyphId % 32))) == 0
                            )
                        {
                            ligatureIsComplex = false;
                            break;
                        }
                    }

                    if (ligatureIsComplex)
                    {
                        return(true);
                    }
                }
            }

            return(false);
        }
Пример #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
            )
        {
            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);
        }