Exemplo n.º 1
0
        private void SetCodePageAndFont(SCFL sfcl)
        {
            curCodePage    = string.Empty;
            curFontCharSet = string.Empty;

            MCF1 map1 = aeContainer.GetStructure <MCF1>();

            // MCF2 is not supported yet...
            if (map1 != null)
            {
                // Get mapping info with the ID specified in the SCFL field
                MCF1.MCF1Data mcfData = map1.MappedData.FirstOrDefault(m => m.ID == sfcl.FontId);

                if (mcfData != null)
                {
                    // If it already has a code page/font character set specified, use that.
                    if (!string.IsNullOrWhiteSpace(mcfData.CodePageName) && !string.IsNullOrWhiteSpace(mcfData.FontCharacterSetName))
                    {
                        curCodePage    = mcfData.CodePageName;
                        curFontCharSet = mcfData.FontCharacterSetName;
                    }
                    else
                    {
                        // Otherwise, we need to load it from the coded font resource
                        Resource codedFont = afpFile.Resources.OfTypeAndName(Resource.eResourceType.CodedFont, mcfData.CodedFontName);

                        if (codedFont.IsLoaded)
                        {
                            CFI cfi = codedFont.Fields.OfType <CFI>().FirstOrDefault();
                            if (cfi != null && cfi.FontInfoList.Any())
                            {
                                curCodePage    = cfi.FontInfoList[0].CodePageName;
                                curFontCharSet = cfi.FontInfoList[0].FontCharacterSetName;
                            }
                        }
                    }
                }
            }

            if (!string.IsNullOrWhiteSpace(curFontCharSet))
            {
                curFontCharSetResource = afpFile.Resources.OfTypeAndName(Resource.eResourceType.FontCharacterSet, curFontCharSet);
            }
        }
Exemplo n.º 2
0
        private void RefreshGraphicCharactersCache()
        {
            // Do nothing if the images are already cached
            if (fontCaches.Any())
            {
                return;
            }

            curCodePage    = "";
            curFontCharSet = "";

            // On every page, store a unique list of every used code point, as well as associated font information
            foreach (Container pc in pageContainers)
            {
                foreach (PTX ptx in pc.GetStructures <PTX>())
                {
                    foreach (PTXControlSequence cs in ptx.ControlSequences)
                    {
                        // Store active code page and coded font
                        if (cs.GetType() == typeof(SCFL))
                        {
                            // Lookup info from MCF1 data on this page
                            MCF1.MCF1Data mcfData = pc.GetStructure <MCF1>()?.MappedData.First(m => m.ID == ((SCFL)cs).FontId);

                            // If we have a coded font, we need to load that resource. Otherwise, get the values from here
                            if (mcfData != null)
                            {
                                Resource codedFontResource = afpFile.Resources.OfTypeAndName(Resource.eResourceType.CodedFont, mcfData.CodedFontName);
                                CFI      resourceCFI       = codedFontResource != null && codedFontResource.IsLoaded ? codedFontResource.Fields.OfType <CFI>().FirstOrDefault() : null;

                                if (resourceCFI != null && resourceCFI.FontInfoList.Any())
                                {
                                    // Get the code page and font char set from the resource
                                    curCodePage    = resourceCFI.FontInfoList[0].CodePageName;
                                    curFontCharSet = resourceCFI.FontInfoList[0].FontCharacterSetName;
                                }
                                else
                                {
                                    // Store mcf's code page and font char set specifiers
                                    curCodePage    = mcfData.CodePageName;
                                    curFontCharSet = mcfData.FontCharacterSetName;
                                }
                            }
                        }
                        else if (cs.GetType() == typeof(TRN))
                        {
                            foreach (byte b in cs.Data)
                            {
                                // Add a new font cache item if this exact combo (byte/code page/char set) does not yet exist
                                if (!fontCaches.Any(f => f.CodePoint == b && f.CodePage == curCodePage && f.FontCharSet == curFontCharSet))
                                {
                                    fontCaches.Add(new FontCache(b, curCodePage, curFontCharSet));
                                }
                            }
                        }
                    }
                }
            }

            // For each byte/code point/font, generate a bitmap by looking up its resource
            curCodePage    = "";
            curFontCharSet = "";
            Dictionary <byte, string> cpMappings = CodePages.C1252;
            Resource  fontResource = null;
            Container foc          = null;
            float     emInchSize   = 0;
            byte      vsc          = 0;

            foreach (FontCache fc in fontCaches.OrderBy(f => f.CodePage).ThenBy(f => f.FontCharSet))
            {
                // Generate new code page mappings if needed
                if (fc.CodePage != curCodePage)
                {
                    cpMappings = new Dictionary <byte, string>();

                    // If the code page is a resource, generate from scratch
                    Resource cp = afpFile.Resources.OfTypeAndName(Resource.eResourceType.CodePage, fc.CodePage);
                    if (cp != null && cp.IsLoaded)
                    {
                        foreach (CPI.Info info in cp.Fields.OfType <CPI>().First().CPIInfos)
                        {
                            cpMappings.Add(info.CodePoints[0], info.GID);
                        }

                        // Is variable space char if the byte equals the one specified by the code page descriptor
                        vsc = cp.Fields.OfType <CPC>().First().VariableSpaceCharacter;
                    }
                    // Else, get by looking up last 4 page digits
                    else
                    {
                        // Get probably name of static field in Code Pages lookups
                        string sectionedCodePage = string.Empty;
                        if (fc.CodePage.Length >= 4)
                        {
                            sectionedCodePage = $"C{fc.CodePage.Substring(fc.CodePage.Length - 4)}";
                        }

                        // Find the matching lookup method in our code page helper class
                        FieldInfo field = typeof(CodePages).GetField(sectionedCodePage);
                        if (field != null)
                        {
                            cpMappings = (Dictionary <byte, string>)field.GetValue(null);
                        }

                        // Is variable space character if the byte GID equals SP010000
                        vsc = cpMappings.First(c => c.Value == "SP010000").Key;
                    }

                    curCodePage = fc.CodePage;
                }

                // Lookup new font character set if needed
                if (fc.FontCharSet != curFontCharSet)
                {
                    fontResource   = afpFile.Resources.OfTypeAndName(Resource.eResourceType.FontCharacterSet, fc.FontCharSet);
                    curFontCharSet = fc.FontCharSet;
                    foc            = fontResource.Fields[0].LowestLevelContainer;
                    emInchSize     = foc.GetStructure <FND>().EmInches;
                }

                // Generate a bitmap for this code point by looking up the raster pattern of the FCS by current code page
                string gid = cpMappings.ContainsKey(fc.CodePoint) ? cpMappings[fc.CodePoint] : string.Empty;
                if (!string.IsNullOrEmpty(gid) && fontResource != null && fontResource.IsLoaded && afpFile.ParsedFontPatterns.ContainsKey(foc))
                {
                    // Get raster pattern info of GID
                    KeyValuePair <FNI.Info, bool[, ]> pattern = afpFile.ParsedFontPatterns[foc].FirstOrDefault(p => p.Key.GCGID == gid);

                    // Build bitmap
                    if (pattern.Key != null)
                    {
                        // Set font and variable space info here
                        fc.FontInfo            = pattern.Key;
                        fc.IsVariableSpaceChar = fc.CodePoint == vsc;
                        fc.EmInchSize          = emInchSize;

                        Bitmap bmp = new Bitmap(pattern.Value.GetUpperBound(0) + 1, pattern.Value.GetUpperBound(1) + 1);
                        for (int y = 0; y < bmp.Height; y++)
                        {
                            for (int x = 0; x < bmp.Width; x++)
                            {
                                if (pattern.Value[x, y])
                                {
                                    bmp.SetPixel(x, y, Color.Black); // Set to black - we remap colors later
                                }
                            }
                        }
                        // Since we know how many inches 1 em is, we can determine inch width and height of each character
                        float heightInches = emInchSize * ((pattern.Key.AscenderHeight + pattern.Key.DescenderDepth) / 1000f);
                        float dpi          = (float)Math.Round(bmp.Height / heightInches);
                        bmp.SetResolution(dpi, dpi);

                        // Assign to font cache
                        fc.Pattern = bmp;
                    }
                }
            }
        }