public override void ParseData() { // Get all groups int curIndx = 0; List <Info> allInfo = new List <Info>(); while (curIndx < Data.Length) { CommonMappings.eRotations rot = (CommonMappings.eRotations)Data[curIndx + 3]; short maxBaseOSet = GetNumericValueFromData <short>(curIndx + 4, 2); ushort maxCharInc = GetNumericValueFromData <ushort>(curIndx + 6, 2); ushort spaceCharInc = GetNumericValueFromData <ushort>(curIndx + 8, 2); ushort maxBaseExt = GetNumericValueFromData <ushort>(curIndx + 10, 2); Info.eControlFlags cFlags = (Info.eControlFlags)Data[curIndx + 12]; ushort emSpaceInc = GetNumericValueFromData <ushort>(curIndx + 14, 2); ushort figSpaceInc = GetNumericValueFromData <ushort>(curIndx + 18, 2); ushort nomCharInc = GetNumericValueFromData <ushort>(curIndx + 20, 2); ushort defaultBaseInc = GetNumericValueFromData <ushort>(curIndx + 22, 2); short minASpace = GetNumericValueFromData <short>(curIndx + 24, 2); allInfo.Add(new Info(rot, maxBaseOSet, maxCharInc, spaceCharInc, maxBaseExt, cFlags, emSpaceInc, figSpaceInc, nomCharInc, defaultBaseInc, minASpace)); curIndx += RepeatingGroupLength; } _FNOInfo = allInfo; }
public STO(CommonMappings.eRotations iOrient, CommonMappings.eRotations bOrient, bool hasPrefix, bool isChained) : base(Lookups.PTXControlSequenceID <STO>(isChained), hasPrefix, null) { Data = new byte[4]; // The enum values need to be multiplied by 2 to reflect the actual degree values IDegrees = (ushort)((ushort)iOrient * 2); BDegrees = (ushort)((ushort)bOrient * 2); }
/// <summary> /// Adds a string to the a location on a page, using a specific encoding. /// </summary> /// <param name="pageContainer"></param> The container of the page which will contain the specified text /// <param name="fontCharacterSet"></param> The name of the Font Character Set resource file. Will create a new MCF record if needed. /// <param name="inline"></param> The inline (relative horizontal) position offset of the text /// <param name="baseline"></param> The baseline (relative vertical) position offset of the text /// <param name="text"></param> The string to encode /// <param name="encoding"></param> The type of encoding to map characters to. Must correspond to code page mapping parameter. /// <param name="interCharSpacing"></param> If specified, overrides the default intercharacter spacing of 0 /// <param name="codePage"></param> The code page to use when decoding bytes to LIDs /// <param name="inlineRotation"></param> The inline (relative horizontal) direction of the text. Must be parallel to baseline rotation. /// <param name="baselineRotation"></param> The baseline (relative vertical) direction of the text. Must be parallel to inline rotation. public void AddText(Container pageContainer, string fontCharacterSet, short inline, short baseline, string text, Encoding encoding, short interCharSpacing = 0, string codePage = "T1DM1252", CommonMappings.eRotations inlineRotation = CommonMappings.eRotations.Zero, CommonMappings.eRotations baselineRotation = CommonMappings.eRotations.Ninety) { // Make sure the inline/baseline rotations are parallel bool inlineIsHorizontal = inlineRotation == CommonMappings.eRotations.Zero || inlineRotation == CommonMappings.eRotations.OneEighty; bool baselineIsHorizontal = baselineRotation == CommonMappings.eRotations.Zero || baselineRotation == CommonMappings.eRotations.OneEighty; if (inlineIsHorizontal == baselineIsHorizontal) { throw new Exception("Error: Inline and baseline rotations must be parallel to each other."); } // Find the MCF-1 field on this page MCF1 mcf = pageContainer.GetStructure <MCF1>(); IReadOnlyList <MCF1.MCF1Data> mcfData = mcf?.MappedData; if (mcfData == null) { throw new Exception("Error: MCF-1 field could not be found in the specified page."); } // If the specified font character set does not exist, create it byte fontId = mcfData.FirstOrDefault(m => m.FontCharacterSetName == fontCharacterSet)?.ID ?? mcf.AddFontDefinition(string.Empty, codePage, fontCharacterSet); // Add several sequences to the list based on passed parameters List <PTXControlSequence> newSequences = new List <PTXControlSequence>(); newSequences.Add(new SCFL(fontId, true, true)); newSequences.Add(new AMI(inline, false, true)); newSequences.Add(new AMB(baseline, false, true)); newSequences.Add(new STO(inlineRotation, baselineRotation, false, true)); if (interCharSpacing != 0) { newSequences.Add(new SIA(interCharSpacing, false, true)); } newSequences.Add(new TRN(encoding.GetBytes(text), false, false)); // Create a new BPT/PTX/EPT at the end of this page int indexToInsert = 0; for (int i = 0; i < Fields.Count; i++) { if (Fields[i] == pageContainer.Structures.Last()) { indexToInsert = i; break; } } AddFields(new List <StructuredField>() { new BPT(), new PTX(newSequences), new EPT() }, indexToInsert); }
public Info(CommonMappings.eRotations rot, short maxBaseOSet, ushort maxCharInc, ushort spaceCharInc, ushort maxBaseExt, eControlFlags cFlags, ushort emSpaceInc, ushort figSpaceInc, ushort nomCharInc, ushort defaultBaseInc, short minASpace) { Rotation = rot; MaxBaselineOffset = maxBaseOSet; MaxCharIncrement = maxCharInc; SpaceCharIncrement = spaceCharInc; MaxBaselineExtent = maxBaseExt; ControlFlags = cFlags; EmSpaceIncrement = emSpaceInc; FigureSpaceIncrement = figSpaceInc; NominalCharIncrement = nomCharInc; DefaultBaselineIncrement = defaultBaseInc; MinASpace = minASpace; }
private void SaveBitmapsAsFont() { // Open each bitmap, and convert pure black pixels to an array of bools List <CharInfo> charInfos = new List <CharInfo>(); foreach (FileInfo f in new DirectoryInfo(Path.Combine(Environment.CurrentDirectory, "..\\..\\..\\Sample Files\\Barcode Chars")).GetFiles()) { Bitmap png = new Bitmap(f.FullName); char thisChar = f.Name == "Asterisk.png" ? '*' : f.Name[0]; bool[,] boolVals = new bool[png.Width + 1, png.Height]; for (int y = 0; y < png.Height; y++) { for (int x = 0; x < png.Width; x++) { boolVals[x + 1, y] = png.GetPixel(x, y).GetBrightness() < 0.5; } } charInfos.Add(new CharInfo(thisChar, boolVals)); } // Create an AFP font file (BFN, FND, FNC, FNM, FNO, FNP, FNIs, FNGs, EFN) using bool arrays as FNGs BFN newBFN = new BFN("BARCOD39"); FND newFND = new FND("Code 39 Barcode", 172); ushort maxBitsWideIdx = (ushort)(charInfos.Max(c => c.BitWidth) - 1); ushort maxBitsTallIdx = (ushort)(charInfos.Max(c => c.BitHeight) - 1); int totalRasterBytes = charInfos.Sum(c => c.RoundedBitWidth * c.BitHeight); FNC newFNC = new FNC(maxBitsWideIdx, maxBitsTallIdx, totalRasterBytes); uint curFNMIndex = 0; List <FNM.PatternData> fnmPatData = new List <FNM.PatternData>(); foreach (CharInfo c in charInfos) { fnmPatData.Add(new FNM.PatternData((ushort)(c.BitWidth - 1), (ushort)(c.BitHeight - 1), curFNMIndex)); curFNMIndex += (uint)((c.RoundedBitWidth * c.BitHeight) / 8); } FNM newFNM = new FNM(fnmPatData); List <FNO.Info> fnoInfos = new List <FNO.Info>(); ushort maxCharInc = charInfos.Max(c => c.CharIncrement); for (int i = 0; i < 4; i++) { Type eType = typeof(CommonMappings.eRotations); CommonMappings.eRotations curRot = (CommonMappings.eRotations)Enum.Parse(eType, Enum.GetNames(eType)[i]); ushort curBaseline = (i == 0 || i == 2) ? (ushort)1000 : maxCharInc; ushort curCharInc = (i == 0 || i == 2) ? maxCharInc : (ushort)1000; FNO.Info.eControlFlags flags = i == 0 ? 0 : i == 1 ? FNO.Info.eControlFlags.FNI1 : i == 2 ? FNO.Info.eControlFlags.FNI2 : FNO.Info.eControlFlags.FNI3; fnoInfos.Add(new FNO.Info(curRot, (short)curBaseline, curCharInc, 0, curBaseline, flags, 1000, curCharInc, curCharInc, curBaseline, 0)); } FNO newFNO = new FNO(fnoInfos); List <FNP.Info> fnpInfos = new List <FNP.Info>(); for (int i = 0; i < 4; i++) { short curAsc = (short)((i == 0 || i == 2) ? maxCharInc : 1000); fnpInfos.Add(new FNP.Info(1000, 1000, curAsc, 0, 1000, 100)); } FNP newFNP = new FNP(fnpInfos); List <FNI> newFNIs = new List <FNI>(); for (int i = 0; i < 4; i++) { ushort fnmIndex = 0; List <FNI.Info> fniInfos = new List <FNI.Info>(); foreach (CharInfo c in charInfos) { string gid = CodePages.C1140[Converters.EBCDIC.GetBytes(new[] { c.Character })[0]]; ushort curCharInc = (ushort)((i == 0 || i == 2) ? c.CharIncrement : 1000); short curAscHeight = (short)((i == 0 || i == 2) ? 1000 : c.CharIncrement); fniInfos.Add(new FNI.Info(gid, c.CharIncrement, curAscHeight, 0, fnmIndex++, 0, curCharInc, 0, curAscHeight)); } newFNIs.Add(new FNI(fniInfos)); } List <byte> fngBytes = new List <byte>(); foreach (CharInfo c in charInfos) { for (int y = 0; y < c.BitHeight; y++) { for (int x = 0; x < c.BitWidth; x += 8) { int[] curByte = new int[1]; List <bool> bitRow = new List <bool>(); for (int i = 0; i < 8; i++) { if (c.RawBits.GetUpperBound(0) >= x + i) { bitRow.Add(c.RawBits[x + i, y]); } else { bitRow.Add(false); } } if (BitConverter.IsLittleEndian) { bitRow.Reverse(); } new BitArray(bitRow.ToArray()).CopyTo(curByte, 0); fngBytes.Add((byte)curByte[0]); } } } FNG newFNG = new FNG(fngBytes.ToArray()); EFN newEFN = new EFN(newBFN.ObjectName); string path = Path.Combine(Environment.CurrentDirectory, "..\\..\\..\\Sample Files\\FONTS\\FONTTEST"); List <StructuredField> fields = new List <StructuredField>() { newBFN, newFND, newFNC, newFNM, newFNO, newFNP }; fields.AddRange(newFNIs); fields.AddRange(new StructuredField[] { newFNG, newEFN }); List <byte> encoded = new List <byte>(); foreach (StructuredField field in fields) { encoded.Add(0x5A); encoded.AddRange(field.Introducer); encoded.AddRange(field.Data); } File.WriteAllBytes(path, encoded.ToArray()); }